Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an option to open source FE writer generate to enable writing annotations. #2849

Open
wants to merge 46 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
b9dfe11
add enable npm workspaces to appOptions
kjose90 Jan 16, 2025
3dd9c4c
removing unecessary console logs
kjose90 Jan 16, 2025
d246d0e
removing debugger
kjose90 Jan 16, 2025
560cb17
Merge branch 'main' into moveCapUpdates
kjose90 Jan 16, 2025
3f89f43
lint issues
kjose90 Jan 16, 2025
d763ff1
Linting auto fix commit
github-actions[bot] Jan 16, 2025
901a6e5
unit tests
kjose90 Jan 17, 2025
82bd7e2
Merge branch 'moveCapUpdates' of https://github.com/SAP/open-ux-tools…
kjose90 Jan 17, 2025
3d88289
Linting auto fix commit
github-actions[bot] Jan 17, 2025
a120f48
Merge branch 'main' into moveCapUpdates
kjose90 Jan 17, 2025
87020f2
remove unused reference to package type
kjose90 Jan 17, 2025
811810b
sonar qube fix
kjose90 Jan 17, 2025
dea250e
add documentation to enable npm workspaces type
kjose90 Jan 22, 2025
cee24bb
add enableNPMWorkspaces doc to f-f-w
kjose90 Jan 22, 2025
b2fed1e
add comment
kjose90 Jan 22, 2025
e1851b8
Move and types from to
kjose90 Jan 22, 2025
9a5d436
remve old changeset
kjose90 Jan 22, 2025
20a39b7
merge main and fix conflicts
kjose90 Jan 22, 2025
3490ac7
Linting auto fix commit
github-actions[bot] Jan 22, 2025
da1f726
Merge branch 'main' into updateCapService
kjose90 Jan 22, 2025
ca59e47
enable npm workspace comment
kjose90 Jan 22, 2025
b01a596
js doc fix
kjose90 Jan 23, 2025
e4546f7
Merge branch 'updateCapService' of https://github.com/SAP/open-ux-too…
kjose90 Jan 23, 2025
110da8c
Linting auto fix commit
github-actions[bot] Jan 23, 2025
1bb7159
js doc fix
kjose90 Jan 23, 2025
b01bef7
js doc fix
kjose90 Jan 23, 2025
200aed4
Linting auto fix commit
github-actions[bot] Jan 23, 2025
4596f1f
Merge branch 'main' into updateCapService
kjose90 Jan 23, 2025
b33329b
Merge branch 'main' into updateCapService
kjose90 Jan 28, 2025
6e359be
remove enable npm workspace options from ff and fe appOptions
kjose90 Jan 28, 2025
8328245
resolve merge conflict
kjose90 Jan 28, 2025
ffcfe4e
move annotation writing logic to generate function of FE
kjose90 Jan 28, 2025
ce2e16a
move annotations generation to writers
kjose90 Jan 29, 2025
f059df7
fix merge conflicts
kjose90 Jan 29, 2025
bfc3c55
add annotations logic to FE generate and tests
kjose90 Jan 30, 2025
7263e0a
Merge branch 'main' into moveWriteAnnotationsLogic
kjose90 Jan 30, 2025
3d058c9
add changeset
kjose90 Jan 30, 2025
288b612
delete old changeset
kjose90 Jan 30, 2025
e1709f3
add js docs
kjose90 Jan 30, 2025
e1563f5
sonar issues fix
kjose90 Jan 30, 2025
2e249a1
improise annotation wirting logic
kjose90 Jan 31, 2025
137d521
Merge branch 'main' into moveWriteAnnotationsLogic
kjose90 Jan 31, 2025
7dc70dc
add logger to f-e-w
kjose90 Jan 31, 2025
2bfb2c8
fix test for write annotations
kjose90 Jan 31, 2025
de66d3c
sonar issues
kjose90 Jan 31, 2025
c3e53c6
move writeAnnotations and improvise
kjose90 Jan 31, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/sweet-games-raise.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sap-ux/fiori-elements-writer': minor
---

Add an option to open source FE writer to enable writing annotations.
2 changes: 2 additions & 0 deletions packages/fiori-elements-writer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
"@sap-ux/ui5-test-writer": "workspace:*",
"@sap-ux/fiori-generator-shared": "workspace:*",
"@sap-ux/cap-config-writer": "workspace:*",
"@sap-ux/annotation-generator": "workspace:*",
"@sap-ux/logger": "workspace:*",
"ejs": "3.1.10",
"i18next": "20.6.1",
"lodash": "4.17.21",
Expand Down
20 changes: 14 additions & 6 deletions packages/fiori-elements-writer/src/data/templateAttributes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ type TemplateAttributes = {
minimumUi5Version: {
[V in OdataVersion]?: string; // Minimum UI5 Versions required for the specific OdataVersion
};
// Function to determine if annotations can be generated for the specific template type
supportsAnnotations: (odataServiceVersion?: OdataVersion) => boolean;
};
};

Expand All @@ -148,39 +150,45 @@ export const TemplateTypeAttributes: TemplateAttributes = {
minimumUi5Version: {
[OdataVersion.v2]: minSupportedUI5Version,
[OdataVersion.v4]: '1.99.0'
}
},
supportsAnnotations: (odataServiceVersion?: OdataVersion) => odataServiceVersion === OdataVersion.v4 && true
},
[TemplateType.ListReportObjectPage]: {
supportedODataVersions: [OdataVersion.v2, OdataVersion.v4],
minimumUi5Version: {
[OdataVersion.v2]: minSupportedUI5Version,
[OdataVersion.v4]: '1.84.0'
}
},
supportsAnnotations: (odataServiceVersion?: OdataVersion) => odataServiceVersion === OdataVersion.v4 && true
},
[TemplateType.AnalyticalListPage]: {
supportedODataVersions: [OdataVersion.v2, OdataVersion.v4],
minimumUi5Version: {
[OdataVersion.v2]: minSupportedUI5Version,
[OdataVersion.v4]: '1.90.0'
}
},
supportsAnnotations: () => false
},
[TemplateType.OverviewPage]: {
supportedODataVersions: [OdataVersion.v2, OdataVersion.v4],
minimumUi5Version: {
[OdataVersion.v2]: minSupportedUI5Version,
[OdataVersion.v4]: '1.96.8'
}
},
supportsAnnotations: () => false
},
[TemplateType.FormEntryObjectPage]: {
supportedODataVersions: [OdataVersion.v4],
minimumUi5Version: {
[OdataVersion.v4]: '1.90.0'
}
},
supportsAnnotations: () => true
},
[TemplateType.FlexibleProgrammingModel]: {
supportedODataVersions: [OdataVersion.v4],
minimumUi5Version: {
[OdataVersion.v4]: '1.94.0'
}
},
supportsAnnotations: () => false
}
};
12 changes: 11 additions & 1 deletion packages/fiori-elements-writer/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import { initI18n } from './i18n';
import { getBootstrapResourceUrls, getPackageScripts } from '@sap-ux/fiori-generator-shared';
import { generateFpmConfig } from './fpmConfig';
import { applyCAPUpdates, type CapProjectSettings } from '@sap-ux/cap-config-writer';
import type { Logger } from '@sap-ux/logger';
import { writeAnnotations } from './writeAnnotations';

export const V2_FE_TYPES_AVAILABLE = '1.108.0';
/**
Expand Down Expand Up @@ -50,15 +52,22 @@ function getTypeScriptIgnoreGlob<T extends {}>(feApp: FioriElementsApp<T>, coerc
}
return ignore;
}

/**
* Generate a UI5 application based on the specified Fiori Elements floorplan template.
*
* @param basePath - the absolute target path where the application will be generated
* @param data - configuration to generate the Fiori elements application
* @param fs - an optional reference to a mem-fs editor
* @param log - optional logger instance
* @returns Reference to a mem-fs-editor
*/
async function generate<T extends {}>(basePath: string, data: FioriElementsApp<T>, fs?: Editor): Promise<Editor> {
async function generate<T extends {}>(
basePath: string,
data: FioriElementsApp<T>,
fs?: Editor,
log?: Logger
): Promise<Editor> {
// Load i18n translations asynchronously to ensure proper initialization.
// This addresses occasional issues where i18n is not initialized in time, causing tests to fail.
await initI18n();
Expand Down Expand Up @@ -223,6 +232,7 @@ async function generate<T extends {}>(basePath: string, data: FioriElementsApp<T
await applyCAPUpdates(fs, feApp.service.capService, settings);
}

await writeAnnotations(basePath, feApp, fs, log);
return fs;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
"info": {
"mockOnlyWarning": "This application was generated with a local metadata file and does not reference a live server. Please add the required server configuration or start this application with mock data using the target: npm run start-mock"
},
"warn": {
"invalidTypeForAnnotationGeneration": "The provided option addAnnotations is not supported for the specified template '{{ templateType }}' and odata version '{{ odataVersion }}'. Generation will continue but additional annotations will not added."
},
"error": {
"unsupportedOdataVersion": "OData Version of the specified service: {{ serviceVersion }}, is not supported by the template type: {{ templateType }}",
"unsupportedUI5Version": "Specified UI5 property '{{ versionProperty }}': {{ ui5Version }}, is not supported by the template type: {{ templateType }}. Please specify {{minRequiredUI5Version}} or above.",
Expand Down
5 changes: 5 additions & 0 deletions packages/fiori-elements-writer/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@ export interface FioriElementsApp<T> extends Ui5App {
* This will eventually move up to {@link Ui5App.appOptions}
*/
addTests?: boolean;
/**
* If addAnnotations is true, annotations are enabled.
* However, annotations will only be written if the template type is lrop/worklist or formEntryObject; annotation genration is not uspported for other project types.
*/
addAnnotations?: boolean;
};
}

Expand Down
104 changes: 104 additions & 0 deletions packages/fiori-elements-writer/src/writeAnnotations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { sep } from 'path';
import { type CapServiceCdsInfo } from '@sap-ux/cap-config-writer';
import { getCapFolderPathsSync } from '@sap-ux/fiori-generator-shared';
import { TemplateType, type EntityConfig, type FioriElementsApp } from './types';
import {
generateAnnotations,
type AnnotationServiceParameters,
type GenerateAnnotationsOptions
} from '@sap-ux/annotation-generator';
import type { Editor } from 'mem-fs-editor';
import type { OdataVersion } from '@sap-ux/odata-service-writer';
import { TemplateTypeAttributes } from './data/templateAttributes';
import type { Logger } from '@sap-ux/logger';
import { t } from './i18n';

/**
* Generates the annotation file path based on whether the CAP service is available.
*
* @param {string} [appName] - The name of the application.
* @param {CapServiceCdsInfo} [capService] - The CAP service info.
* @returns {string} The annotation file path based on whether the CAP service is available.
*/
function getAnnotationFilePath(appName?: string, capService?: CapServiceCdsInfo): string {
if (capService) {
const appPath = capService.appPath ?? getCapFolderPathsSync(capService.projectPath).app;
return `${appPath}${sep}${appName}${sep}annotations.cds`;
}
return `webapp${sep}annotations${sep}annotation.xml`;
}

/**
* Determines if annotations can be generated for a given template.
*
* @param {OdataVersion} odataServiceVersion - The version of the OData service being used.
* @param {TemplateType} templateType - The type of the template being used by app.
* @param {boolean} [addAnnotations] - An optional flag indicating whether annotations should be enabled.
* @returns {boolean} - Returns `true` if annotations can be generated, otherwise `false`.
*/
export function canGenerateAnnotationsForTemplate(
odataServiceVersion: OdataVersion,
templateType: TemplateType,
addAnnotations: boolean = false
): boolean | undefined {
return addAnnotations && TemplateTypeAttributes[templateType].supportsAnnotations(odataServiceVersion);
}

/**
* Writes annotation files for the given application configuration.
*
* @param basePath - The base directory path of the project.
* @param feApp - to generate the Fiori elements application
* @param fs - The file system editor instance.
* @param log - Logger instance.
*/
export async function writeAnnotations<T extends {}>(
basePath: string,
feApp: FioriElementsApp<T>,
fs: Editor,
log?: Logger
): Promise<void> {
// Check if annotations should be generated
if (
canGenerateAnnotationsForTemplate(feApp.service.version, feApp.template.type, feApp.appOptions?.addAnnotations)
) {
const { settings } = feApp.template;
const { capService } = feApp.service;
const { name: packageName } = feApp.package ?? {};
const entitySetName = (settings as T & { entityConfig?: EntityConfig })?.entityConfig?.mainEntityName ?? '';

const addLineItems =
feApp.template.type === TemplateType.ListReportObjectPage || feApp.template.type === TemplateType.Worklist;

let serviceName = 'mainService';
let projectPath = basePath;

if (capService) {
serviceName = capService.serviceName;
projectPath = capService.projectPath;
}

const options: GenerateAnnotationsOptions = {
entitySetName: entitySetName,
annotationFilePath: getAnnotationFilePath(packageName, capService),
addFacets: true,
addLineItems,
addValueHelps: !!capService
};

const serviceParameters: AnnotationServiceParameters = {
serviceName,
appName: packageName,
project: projectPath
};

await generateAnnotations(fs, serviceParameters, options);
} else {
log?.warn(
t('warn.invalidTypeForAnnotationGeneration', {
templateType: feApp.template.type,
odataVersion: feApp.service.version
})
);
}
}
44 changes: 43 additions & 1 deletion packages/fiori-elements-writer/test/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ import {
type FEOPSettings,
type FioriElementsApp,
type LROPSettings,
type WorklistSettings
type WorklistSettings,
TemplateType
} from '../src/types';
import { promisify } from 'util';
import { exec as execCP } from 'child_process';
const exec = promisify(execCP);
import { ServiceType } from '@sap-ux/odata-service-writer';
import { type CapServiceCdsInfo } from '@sap-ux/cap-config-writer';

export const testOutputDir = join(__dirname, 'test-output');

Expand Down Expand Up @@ -201,3 +203,43 @@ export const projectChecks = async (
expect(error).toBeUndefined();
}
};

export const sampleCapService: CapServiceCdsInfo = {
cdsUi5PluginInfo: {
isCdsUi5PluginEnabled: true,
hasMinCdsVersion: true,
isWorkspaceEnabled: true,
hasCdsUi5Plugin: true
},
projectPath: join('test'),
serviceName: 'mainService',
capType: 'Node.js',
appPath: join('test', 'path')
};

/**
*
* @param name name of the app
* @param templateType template type of the app
* @returns a Fiori Elements App of provided template type
*/
export const applyBaseConfigToFEApp = (name: string, templateType: TemplateType) => {
const addUi5Config = templateType === TemplateType.Worklist;
const appInfo = feBaseConfig(name, !addUi5Config);
return {
...Object.assign(appInfo, {
template: {
type: templateType,
settings: v4TemplateSettings
}
}),
service: {
version: OdataVersion.v4,
capService: sampleCapService
},
package: {
...appInfo.package,
sapuxLayer: 'CUSTOMER_BASE'
}
} as FioriElementsApp<LROPSettings>;
};
63 changes: 62 additions & 1 deletion packages/fiori-elements-writer/test/feop.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,27 @@ import {
v4TemplateSettings,
v4Service,
projectChecks,
updatePackageJSONDependencyToUseLocalPath
updatePackageJSONDependencyToUseLocalPath,
applyBaseConfigToFEApp,
sampleCapService
} from './common';
import type { FEOPSettings } from '../src/types';
import type { CapServiceCdsInfo } from '@sap-ux/cap-config-writer';
import { OdataVersion } from '@sap-ux/odata-service-writer';
import { create as createStorage } from 'mem-fs';
import { create } from 'mem-fs-editor';
import { generateAnnotations } from '@sap-ux/annotation-generator';

const TEST_NAME = 'feopTemplate';
if (debug?.enabled) {
jest.setTimeout(360000);
}

jest.mock('@sap-ux/annotation-generator', () => ({
...jest.requireActual('@sap-ux/annotation-generator'),
generateAnnotations: jest.fn()
}));

describe(`Fiori Elements template: ${TEST_NAME}`, () => {
const curTestOutPath = join(testOutputDir, TEST_NAME);

Expand Down Expand Up @@ -73,3 +85,52 @@ describe(`Fiori Elements template: ${TEST_NAME}`, () => {
});
});
});

describe('Should generate annotations correctly for FEOP projects', () => {
const curTestOutPath = join(testOutputDir, TEST_NAME);
const fs = create(createStorage());

afterEach(() => {
jest.clearAllMocks();
jest.resetAllMocks();
});

test('Should generate annotations for FEOP projects when addAnnotations is enabled, regardless of service availability', async () => {
const fioriElementsApp = {
...applyBaseConfigToFEApp('fefeop1', TemplateType.FormEntryObjectPage),
appOptions: {
addAnnotations: true
}
};
await generate(curTestOutPath, fioriElementsApp, fs);
expect(generateAnnotations).toBeCalledTimes(1);

// ensure addLineItems is false for feop project
expect(generateAnnotations).toBeCalledWith(
fs,
{
serviceName: sampleCapService.serviceName,
appName: fioriElementsApp.package.name,
project: sampleCapService.projectPath
},
{
entitySetName: v4TemplateSettings?.entityConfig?.mainEntityName,
annotationFilePath: join('test', 'path', 'fefeop1', 'annotations.cds'),
addFacets: true,
addLineItems: false,
addValueHelps: true
}
);
});

test('Should generate annotations for FEOP projects when addAnnotations is disabled', async () => {
const fioriElementsApp = {
...applyBaseConfigToFEApp('fefeop1', TemplateType.FormEntryObjectPage),
appOptions: {
addAnnotations: false
}
};
await generate(curTestOutPath, fioriElementsApp, fs);
expect(generateAnnotations).not.toBeCalled();
});
});
Loading
Loading