From 642d507b36f771ad10dcd76ba11b8c8965941db5 Mon Sep 17 00:00:00 2001 From: Nicolas Lunet Date: Tue, 28 Jan 2025 15:48:29 +0100 Subject: [PATCH 01/17] fix: make sure the canvas dependency is not required (#2838) * fix: ensure that by default we won't require people to have the canvas dependency When allowCSS is set to false, we need to ensure that no additional package is required. * chore: changeset * chore: sonar --- .changeset/good-knives-visit.md | 5 +++ packages/jest-environment-ui5/README.md | 21 ++++++++++ packages/jest-environment-ui5/src/index.js | 6 +++ .../test/unit/index.test.js | 39 +++++++++++++++++++ 4 files changed, 71 insertions(+) create mode 100644 .changeset/good-knives-visit.md diff --git a/.changeset/good-knives-visit.md b/.changeset/good-knives-visit.md new file mode 100644 index 0000000000..1ed329a6c2 --- /dev/null +++ b/.changeset/good-knives-visit.md @@ -0,0 +1,5 @@ +--- +'@sap-ux/jest-environment-ui5': patch +--- + +Fix the canvas dependency issue diff --git a/packages/jest-environment-ui5/README.md b/packages/jest-environment-ui5/README.md index 1fbc1d45eb..5e25f10be3 100644 --- a/packages/jest-environment-ui5/README.md +++ b/packages/jest-environment-ui5/README.md @@ -59,6 +59,27 @@ framework: - name: sap.m ``` +### Options + +You can define with the following options in the `jest.config.js` file: + +##### Enable css support + +By default the css is not supported and are not loaded when you run the test through jest. +In some case, it might make sense to have css enabled. To enable it, you need to add the following configuration in jest.config.js +If you enable CSS, you will need to pull the `canvas` package as a dependency. +```javascript +module.exports = { + // use custom test environment + testEnvironment: "@sap-ux/jest-environment-ui5", + + testEnvironmentOptions: { + allowCSS: true + } +}; +``` + + ## Enable reporting ```json "devDependencies": { diff --git a/packages/jest-environment-ui5/src/index.js b/packages/jest-environment-ui5/src/index.js index 3cf4509eaa..be1235a54c 100644 --- a/packages/jest-environment-ui5/src/index.js +++ b/packages/jest-environment-ui5/src/index.js @@ -52,6 +52,12 @@ class UI5DOMEnvironment extends JSDOMEnvironment { context.testPath = this.testPath; global.window = context; global.Object = context.Object; + if (!this.allowCSS) { + global.CanvasRenderingContext2D = function () {}; + context.HTMLCanvasElement.prototype.getContext = () => {}; + window.CanvasRenderingContext2D = function () {}; + } + window.NewObject = Object; [ 'sap', diff --git a/packages/jest-environment-ui5/test/unit/index.test.js b/packages/jest-environment-ui5/test/unit/index.test.js index a091063345..0eb8cbe0af 100644 --- a/packages/jest-environment-ui5/test/unit/index.test.js +++ b/packages/jest-environment-ui5/test/unit/index.test.js @@ -1,4 +1,5 @@ const jestCLI = require('jest'); +const UI5DOMEnvironment = require('../../src'); describe('Custom environment', () => { it('Can be created', async () => { let failed = false; @@ -11,4 +12,42 @@ describe('Custom environment', () => { // This is done centrally in the CustomEnvironment constructor but we need to call it here for the test purpose }, 60000); + + it('should not mock the canvas runtime if allowCSS is true', async () => { + global.requireFn = require; + global.CanvasRenderingContext2D = undefined; + const domStuff = new UI5DOMEnvironment( + { globalConfig: {}, projectConfig: { setupFiles: [], testEnvironmentOptions: { allowCSS: true } } }, + { console: console, testPath: '' } + ); + try { + await domStuff.setup(); + } catch (e) { + console.error(e); + } + expect(global.CanvasRenderingContext2D).toBeUndefined(); + }); + + it('should mock the canvas runtime if allowCSS is false', async () => { + global.requireFn = require; + global.CanvasRenderingContext2D = undefined; + const domStuff = new UI5DOMEnvironment( + { globalConfig: {}, projectConfig: { setupFiles: [], testEnvironmentOptions: {} } }, + { console: console, testPath: '' } + ); + try { + await domStuff.setup(); + } catch (e) { + console.error(e); + } + + expect(global.CanvasRenderingContext2D).toBeDefined(); + let hasError = false; + try { + global.CanvasRenderingContext2D(); + } catch (e) { + hasError = e !== undefined; + } + expect(hasError).toBe(false); + }); }); From 8d067cab7b26a929112e8f42b5967694b11dac79 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 28 Jan 2025 15:13:21 +0000 Subject: [PATCH 02/17] chore: apply latest changesets --- .changeset/good-knives-visit.md | 5 ----- packages/jest-environment-ui5/CHANGELOG.md | 6 ++++++ packages/jest-environment-ui5/package.json | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) delete mode 100644 .changeset/good-knives-visit.md diff --git a/.changeset/good-knives-visit.md b/.changeset/good-knives-visit.md deleted file mode 100644 index 1ed329a6c2..0000000000 --- a/.changeset/good-knives-visit.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@sap-ux/jest-environment-ui5': patch ---- - -Fix the canvas dependency issue diff --git a/packages/jest-environment-ui5/CHANGELOG.md b/packages/jest-environment-ui5/CHANGELOG.md index 70e730e862..8ff8be92ce 100644 --- a/packages/jest-environment-ui5/CHANGELOG.md +++ b/packages/jest-environment-ui5/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## 5.3.7 + +### Patch Changes + +- 642d507: Fix the canvas dependency issue + ## 5.3.6 ### Patch Changes diff --git a/packages/jest-environment-ui5/package.json b/packages/jest-environment-ui5/package.json index 57b1fc2085..065c20cd5d 100644 --- a/packages/jest-environment-ui5/package.json +++ b/packages/jest-environment-ui5/package.json @@ -1,6 +1,6 @@ { "name": "@sap-ux/jest-environment-ui5", - "version": "5.3.6", + "version": "5.3.7", "description": "Jest matchers for files and folders", "repository": { "type": "git", From d6b744070a057b49319f2cbf9caf77c506f13a7e Mon Sep 17 00:00:00 2001 From: kitzkan Date: Tue, 28 Jan 2025 15:36:40 +0000 Subject: [PATCH 03/17] Move cap updates to generate functions of FE/FF (#2810) * add enable npm workspaces to appOptions * removing unecessary console logs * removing debugger * lint issues * Linting auto fix commit * unit tests * Linting auto fix commit * remove unused reference to package type * sonar qube fix * add documentation to enable npm workspaces type * add enableNPMWorkspaces doc to f-f-w * add comment * Move and types from to * remve old changeset * Linting auto fix commit * enable npm workspace comment * js doc fix * Linting auto fix commit * js doc fix * Linting auto fix commit * remove enable npm workspace options from ff and fe appOptions --------- Co-authored-by: github-actions[bot] Co-authored-by: Austin Devine --- .changeset/friendly-toes-beg.md | 8 ++ packages/cap-config-writer/package.json | 1 - .../cap-config-writer/src/cap-config/types.ts | 36 +++++- .../cap-config-writer/src/cap-writer/utils.ts | 2 +- packages/cap-config-writer/src/index.ts | 1 + .../test/unit/cap-writer/package-json.test.ts | 2 +- packages/cap-config-writer/tsconfig.json | 3 - packages/fiori-elements-writer/package.json | 1 + packages/fiori-elements-writer/src/index.ts | 16 +++ packages/fiori-elements-writer/src/types.ts | 5 +- .../fiori-elements-writer/test/lrop.test.ts | 94 +++++++++++++++ packages/fiori-elements-writer/tsconfig.json | 3 + packages/fiori-freestyle-writer/package.json | 1 + packages/fiori-freestyle-writer/src/index.ts | 22 ++++ packages/fiori-freestyle-writer/src/types.ts | 5 +- .../fiori-freestyle-writer/test/basic.test.ts | 113 ++++++++++++++++++ packages/fiori-freestyle-writer/tsconfig.json | 3 + packages/odata-service-inquirer/package.json | 1 + packages/odata-service-inquirer/src/index.ts | 9 +- .../datasources/cap-project/cap-helpers.ts | 3 +- .../prompts/datasources/cap-project/types.ts | 3 +- packages/odata-service-inquirer/src/types.ts | 36 +----- .../prompts/cap-project/questions.test.ts | 2 +- packages/odata-service-inquirer/tsconfig.json | 3 + pnpm-lock.yaml | 12 +- 25 files changed, 330 insertions(+), 55 deletions(-) create mode 100644 .changeset/friendly-toes-beg.md diff --git a/.changeset/friendly-toes-beg.md b/.changeset/friendly-toes-beg.md new file mode 100644 index 0000000000..a61628109b --- /dev/null +++ b/.changeset/friendly-toes-beg.md @@ -0,0 +1,8 @@ +--- +'@sap-ux/odata-service-inquirer': major +'@sap-ux/cap-config-writer': minor +'@sap-ux/fiori-freestyle-writer': patch +'@sap-ux/fiori-elements-writer': patch +--- + +Move `CapService` and `CapRuntime` types from `@sap-ux/odata-service-inquirer` to `@sap-ux/cap-config-writer` for better relevance; add CAP updates to generate functions of Fiori Elements and Freestyle writers diff --git a/packages/cap-config-writer/package.json b/packages/cap-config-writer/package.json index a7fddc7d26..fb4749f3fd 100644 --- a/packages/cap-config-writer/package.json +++ b/packages/cap-config-writer/package.json @@ -39,7 +39,6 @@ "xml-js": "1.6.11" }, "devDependencies": { - "@sap-ux/odata-service-inquirer": "workspace:*", "@types/mem-fs": "1.1.2", "@types/mem-fs-editor": "7.0.1", "@types/semver": "7.5.2" diff --git a/packages/cap-config-writer/src/cap-config/types.ts b/packages/cap-config-writer/src/cap-config/types.ts index db7c29e2e3..ce86eb5b23 100644 --- a/packages/cap-config-writer/src/cap-config/types.ts +++ b/packages/cap-config-writer/src/cap-config/types.ts @@ -1,4 +1,4 @@ -import type { CapService } from '@sap-ux/odata-service-inquirer'; +import type { CdsVersionInfo } from '@sap-ux/project-access'; export type CdsUi5PluginInfo = { /** @@ -19,6 +19,40 @@ export type CdsUi5PluginInfo = { hasCdsUi5Plugin: boolean; }; +export type CapRuntime = 'Node.js' | 'Java'; + +export interface CapService { + /** + * The path to the CAP project. + */ + projectPath: string; + /** + * The CDS info for the Cds instance that was used to compile the project when determining the service. + */ + cdsVersionInfo?: CdsVersionInfo; + /** + * The name of the CAP service as identified by the cds model. + */ + serviceName: string; + /** + * The URL path to the service, as specfied in the manifest.json of generated apps + * This is also provided as `OdataServicePromptAnswers` property `servicePath` + */ + urlPath?: string; + /** + * The relative path (from the `projectPath`) to the service cds file. + */ + serviceCdsPath?: string; + /** + * The runtime of the Cds instance that was used to compile the project when determining the service. + */ + capType?: CapRuntime; + /** + * The relative path (from the `projectPath`) to the app folder + */ + appPath?: string; +} + export interface CapServiceCdsInfo extends CapService { cdsUi5PluginInfo: CdsUi5PluginInfo; } diff --git a/packages/cap-config-writer/src/cap-writer/utils.ts b/packages/cap-config-writer/src/cap-writer/utils.ts index d7f3acf599..7257b68f5e 100644 --- a/packages/cap-config-writer/src/cap-writer/utils.ts +++ b/packages/cap-config-writer/src/cap-writer/utils.ts @@ -1,5 +1,5 @@ import { t } from '../i18n'; -import type { CapRuntime } from '@sap-ux/odata-service-inquirer'; +import type { CapRuntime } from '../cap-config/types'; /** * Returns the url to the specified cap app as served by `cds serve` or `cds watch`. diff --git a/packages/cap-config-writer/src/index.ts b/packages/cap-config-writer/src/index.ts index faa4d06859..f75d9e2948 100644 --- a/packages/cap-config-writer/src/index.ts +++ b/packages/cap-config-writer/src/index.ts @@ -1,3 +1,4 @@ export { checkCdsUi5PluginEnabled, enableCdsUi5Plugin, satisfiesMinCdsVersion } from './cap-config'; +export type { CapService, CapRuntime } from './cap-config/types'; export type { CdsUi5PluginInfo, CapServiceCdsInfo, CapProjectSettings } from './cap-config/types'; export * from './cap-writer'; diff --git a/packages/cap-config-writer/test/unit/cap-writer/package-json.test.ts b/packages/cap-config-writer/test/unit/cap-writer/package-json.test.ts index 53f1bde428..4eb70c8af4 100644 --- a/packages/cap-config-writer/test/unit/cap-writer/package-json.test.ts +++ b/packages/cap-config-writer/test/unit/cap-writer/package-json.test.ts @@ -1,4 +1,4 @@ -import type { CapRuntime } from '@sap-ux/odata-service-inquirer'; +import type { CapRuntime } from '../../../src/cap-config/types'; import { satisfiesMinCdsVersion } from '../../../src/cap-config/package-json'; import memFs from 'mem-fs'; import { ToolsLogger } from '@sap-ux/logger'; diff --git a/packages/cap-config-writer/tsconfig.json b/packages/cap-config-writer/tsconfig.json index efd6d4f244..d3bb5ee88e 100644 --- a/packages/cap-config-writer/tsconfig.json +++ b/packages/cap-config-writer/tsconfig.json @@ -16,9 +16,6 @@ { "path": "../logger" }, - { - "path": "../odata-service-inquirer" - }, { "path": "../project-access" }, diff --git a/packages/fiori-elements-writer/package.json b/packages/fiori-elements-writer/package.json index 8de03c5817..b0c381b37a 100644 --- a/packages/fiori-elements-writer/package.json +++ b/packages/fiori-elements-writer/package.json @@ -37,6 +37,7 @@ "@sap-ux/ui5-config": "workspace:*", "@sap-ux/ui5-test-writer": "workspace:*", "@sap-ux/fiori-generator-shared": "workspace:*", + "@sap-ux/cap-config-writer": "workspace:*", "ejs": "3.1.10", "i18next": "20.6.1", "lodash": "4.17.21", diff --git a/packages/fiori-elements-writer/src/index.ts b/packages/fiori-elements-writer/src/index.ts index cd6347d474..dbfffa7542 100644 --- a/packages/fiori-elements-writer/src/index.ts +++ b/packages/fiori-elements-writer/src/index.ts @@ -21,6 +21,7 @@ import semVer from 'semver'; 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'; export const V2_FE_TYPES_AVAILABLE = '1.108.0'; /** @@ -206,6 +207,21 @@ async function generate(basePath: string, data: FioriElementsApp extends Ui5App { template: Template; - service: Omit; // Model name will use defaults + service: Omit & { + capService?: CapServiceCdsInfo; + }; app: FioriApp; appOptions: Partial & { /** diff --git a/packages/fiori-elements-writer/test/lrop.test.ts b/packages/fiori-elements-writer/test/lrop.test.ts index 54d6d1babd..70d3432ae4 100644 --- a/packages/fiori-elements-writer/test/lrop.test.ts +++ b/packages/fiori-elements-writer/test/lrop.test.ts @@ -2,6 +2,7 @@ import type { FioriElementsApp, LROPSettings } from '../src'; import { generate, TableType, TemplateType } from '../src'; import { join } from 'path'; import { removeSync } from 'fs-extra'; +import { OdataVersion } from '@sap-ux/odata-service-writer'; import { testOutputDir, debug, @@ -17,6 +18,9 @@ import { } from './common'; import { ServiceType } from '@sap-ux/odata-service-writer'; import { type OdataService } from '@sap-ux/odata-service-writer'; +import { applyCAPUpdates, type CapServiceCdsInfo } from '@sap-ux/cap-config-writer'; +import { create as createStorage } from 'mem-fs'; +import { create } from 'mem-fs-editor'; const TEST_NAME = 'lropTemplates'; if (debug?.enabled) { @@ -32,6 +36,11 @@ jest.mock('read-pkg-up', () => ({ }) })); +jest.mock('@sap-ux/cap-config-writer', () => ({ + ...jest.requireActual('@sap-ux/cap-config-writer'), + applyCAPUpdates: jest.fn() +})); + describe(`Fiori Elements template: ${TEST_NAME}`, () => { const curTestOutPath = join(testOutputDir, TEST_NAME); @@ -424,4 +433,89 @@ describe(`Fiori Elements template: ${TEST_NAME}`, () => { const packageJson = fs.readJSON(packageJsonPath); expect((packageJson as any)?.sapuxLayer).toBe('CUSTOMER_BASE'); }); + + describe('CAP updates', () => { + const capProjectSettings = { + appRoot: curTestOutPath, + packageName: 'felrop1', + appId: 'felrop1', + sapux: true, + enableTypescript: undefined + }; + + const getFioriElementsApp = (capService?: CapServiceCdsInfo) => { + return { + ...Object.assign(feBaseConfig('felrop1'), { + template: { + type: TemplateType.ListReportObjectPage, + settings: v4TemplateSettings + } + }), + service: { + version: OdataVersion.v4, + capService + }, + package: { + ...feBaseConfig('felrop1').package, + sapuxLayer: 'CUSTOMER_BASE' + } + } as FioriElementsApp; + }; + + afterEach(() => { + jest.clearAllMocks(); + jest.resetAllMocks(); + }); + + test('should perform CAP updates when CAP service is available and cds ui5 plugin is enabled', async () => { + const capService: CapServiceCdsInfo = { + cdsUi5PluginInfo: { + isCdsUi5PluginEnabled: true, + hasMinCdsVersion: true, + isWorkspaceEnabled: true, + hasCdsUi5Plugin: true + }, + projectPath: 'test/path', + serviceName: 'test-service', + capType: 'Node.js' + }; + const fs = create(createStorage()); + + const fioriElementsApp = getFioriElementsApp(capService); + await generate(curTestOutPath, fioriElementsApp, fs); + expect(applyCAPUpdates).toBeCalledTimes(1); + + expect(applyCAPUpdates).toBeCalledWith(fs, capService, { + ...capProjectSettings, + enableNPMWorkspaces: true, + enableCdsUi5Plugin: true + }); + }); + + test('should perform CAP updates when CAP service is available and cds ui5 plugin is disabled', async () => { + const fs = create(createStorage()); + const capServiceWithoutCdsUi5PluginInfo = { + projectPath: 'test/path', + serviceName: 'test-service', + capType: 'Node.js' + }; + const fioriElementsApp = getFioriElementsApp(capServiceWithoutCdsUi5PluginInfo as CapServiceCdsInfo); + await generate(curTestOutPath, fioriElementsApp, fs); + + expect(applyCAPUpdates).toBeCalledTimes(1); + expect(applyCAPUpdates).toBeCalledWith(fs, capServiceWithoutCdsUi5PluginInfo, { + ...capProjectSettings, + enableNPMWorkspaces: false, + enableCdsUi5Plugin: false + }); + }); + + test('should not perform CAP updates, when no cap service provided', async () => { + const fs = create(createStorage()); + + const fioriElementsApp = getFioriElementsApp(); + await generate(curTestOutPath, fioriElementsApp, fs); + expect(applyCAPUpdates).toBeCalledTimes(0); + }); + }); }); diff --git a/packages/fiori-elements-writer/tsconfig.json b/packages/fiori-elements-writer/tsconfig.json index 506c72a722..15f16839f5 100644 --- a/packages/fiori-elements-writer/tsconfig.json +++ b/packages/fiori-elements-writer/tsconfig.json @@ -10,6 +10,9 @@ "outDir": "dist" }, "references": [ + { + "path": "../cap-config-writer" + }, { "path": "../eslint-plugin-fiori-tools" }, diff --git a/packages/fiori-freestyle-writer/package.json b/packages/fiori-freestyle-writer/package.json index 529ccb8476..8c1527fb54 100644 --- a/packages/fiori-freestyle-writer/package.json +++ b/packages/fiori-freestyle-writer/package.json @@ -36,6 +36,7 @@ "@sap-ux/ui5-application-writer": "workspace:*", "@sap-ux/ui5-config": "workspace:*", "@sap-ux/fiori-generator-shared": "workspace:*", + "@sap-ux/cap-config-writer": "workspace:*", "ejs": "3.1.10", "i18next": "20.6.1", "lodash": "4.17.21", diff --git a/packages/fiori-freestyle-writer/src/index.ts b/packages/fiori-freestyle-writer/src/index.ts index 4f6c851df4..b87c27c0d4 100644 --- a/packages/fiori-freestyle-writer/src/index.ts +++ b/packages/fiori-freestyle-writer/src/index.ts @@ -12,6 +12,7 @@ import { UI5Config } from '@sap-ux/ui5-config'; import { initI18n } from './i18n'; import { getBootstrapResourceUrls, getPackageScripts } from '@sap-ux/fiori-generator-shared'; import { getTemplateVersionPath, processDestinationPath } from './utils'; +import { applyCAPUpdates, type CapProjectSettings } from '@sap-ux/cap-config-writer'; /** * Generate a UI5 application based on the specified Fiori Freestyle floorplan template. @@ -166,6 +167,27 @@ async function generate(basePath: string, data: FreestyleApp, fs?: Editor) fs.write(ui5LocalConfigPath, ui5LocalConfig.toString()); } + if (ffApp.service?.capService) { + const hasCdsUi5PluginInfo = !!ffApp.service.capService.cdsUi5PluginInfo; + const settings: CapProjectSettings = { + appRoot: basePath, + packageName: ffApp.package.name ?? '', + appId: ffApp.app.id, + sapux: ffApp.appOptions?.sapux, + enableTypescript: ffApp.appOptions?.typescript, + // Enable CDS UI5 plugin and NPM workspaces if the CDS UI5 plugin info is present + enableCdsUi5Plugin: hasCdsUi5PluginInfo, + enableNPMWorkspaces: hasCdsUi5PluginInfo + }; + // Enable CDS UI5 plugin and NPM workspaces if the CDS UI5 plugin info is present + if (ffApp.service?.capService.cdsUi5PluginInfo) { + settings.enableCdsUi5Plugin = true; + settings.enableNPMWorkspaces = true; + } + // apply cap updates when service is cap + await applyCAPUpdates(fs, ffApp.service.capService, settings); + } + return fs; } diff --git a/packages/fiori-freestyle-writer/src/types.ts b/packages/fiori-freestyle-writer/src/types.ts index a1b80d8f49..df20c999ed 100644 --- a/packages/fiori-freestyle-writer/src/types.ts +++ b/packages/fiori-freestyle-writer/src/types.ts @@ -1,5 +1,6 @@ import type { Ui5App, App } from '@sap-ux/ui5-application-writer'; import type { OdataService } from '@sap-ux/odata-service-writer'; +import type { CapServiceCdsInfo } from '@sap-ux/cap-config-writer'; export const TemplateType = { Basic: 'basic', @@ -38,7 +39,9 @@ export interface FioriApp extends App { } export interface FreestyleApp extends Ui5App { template: Template; - service?: OdataService; + service?: OdataService & { + capService?: CapServiceCdsInfo; + }; app: FioriApp; } diff --git a/packages/fiori-freestyle-writer/test/basic.test.ts b/packages/fiori-freestyle-writer/test/basic.test.ts index 4f6f63e7a5..85997ae496 100644 --- a/packages/fiori-freestyle-writer/test/basic.test.ts +++ b/packages/fiori-freestyle-writer/test/basic.test.ts @@ -6,6 +6,10 @@ import { testOutputDir, debug, updatePackageJSONDependencyToUseLocalPath } from import { OdataVersion, ServiceType } from '@sap-ux/odata-service-writer'; import type { BasicAppSettings } from '../src/types'; import { projectChecks } from './common'; +import { applyCAPUpdates, type CapServiceCdsInfo } from '@sap-ux/cap-config-writer'; +import { create as createStorage } from 'mem-fs'; +import { create, type Editor } from 'mem-fs-editor'; +import { types } from 'util'; const TEST_NAME = 'basicTemplate'; jest.setTimeout(240000); // Needed when debug.enabled @@ -19,6 +23,11 @@ jest.mock('read-pkg-up', () => ({ }) })); +jest.mock('@sap-ux/cap-config-writer', () => ({ + ...jest.requireActual('@sap-ux/cap-config-writer'), + applyCAPUpdates: jest.fn() +})); + describe(`Fiori freestyle template: ${TEST_NAME}`, () => { const curTestOutPath = join(testOutputDir, TEST_NAME); @@ -364,4 +373,108 @@ describe(`Fiori freestyle template: ${TEST_NAME}`, () => { ).toBeTruthy(); }); }); + + describe('CAP updates', () => { + const capService: CapServiceCdsInfo = { + cdsUi5PluginInfo: { + isCdsUi5PluginEnabled: true, + hasMinCdsVersion: true, + isWorkspaceEnabled: true, + hasCdsUi5Plugin: true + }, + projectPath: 'test/path', + serviceName: 'test-service', + capType: 'Node.js' + }; + + const getFreestyleApp = (options: { typescript: boolean; sapux: boolean; capService?: CapServiceCdsInfo }) => { + const { typescript, sapux, capService } = options; + return { + app: { + id: 'ff-basic-id' + }, + template: { + type: TemplateType.Basic, + settings: {} + }, + service: { + version: OdataVersion.v4, + capService + }, + package: { + name: 'ff-basic-id' + }, + appOptions: { + sapux, + typescript + } + } as FreestyleApp; + }; + + const capProjectSettings = { + appRoot: curTestOutPath, + packageName: 'ff-basic-id', + appId: 'ff-basic-id', + sapux: true, + enableTypescript: false + }; + + afterEach(() => { + jest.clearAllMocks(); + jest.resetAllMocks(); + }); + + test('should perform CAP updates when CAP service is available and cds ui5 plugin is enabled', async () => { + const fs = create(createStorage()); + + const freestyleApp: FreestyleApp = getFreestyleApp({ + sapux: false, + typescript: false, + capService + }); + await generate(curTestOutPath, freestyleApp, fs); + expect(applyCAPUpdates).toBeCalledTimes(1); + expect(applyCAPUpdates).toBeCalledWith(fs, capService, { + ...capProjectSettings, + enableNPMWorkspaces: true, + enableCdsUi5Plugin: true, + sapux: false + }); + }); + + test('should perform CAP updates when CAP service is available, and cds ui5 plugin is disabled', async () => { + const fs = create(createStorage()); + + const capServiceWithoutCdsUi5PluginInfo = { + projectPath: 'test/path', + serviceName: 'test-service', + capType: 'Node.js' + }; + + const freestyleApp: FreestyleApp = getFreestyleApp({ + sapux: false, + typescript: false, + capService: capServiceWithoutCdsUi5PluginInfo as CapServiceCdsInfo + }); + await generate(curTestOutPath, freestyleApp, fs); + + expect(applyCAPUpdates).toBeCalledTimes(1); + expect(applyCAPUpdates).toBeCalledWith(fs, capServiceWithoutCdsUi5PluginInfo, { + ...capProjectSettings, + sapux: false, + enableNPMWorkspaces: false, + enableCdsUi5Plugin: false + }); + }); + + test('should not perform CAP updates, when no cap service provided', async () => { + const fs = create(createStorage()); + const freestyleApp: FreestyleApp = getFreestyleApp({ + sapux: false, + typescript: false + }); + await generate(curTestOutPath, freestyleApp, fs); + expect(applyCAPUpdates).toBeCalledTimes(0); + }); + }); }); diff --git a/packages/fiori-freestyle-writer/tsconfig.json b/packages/fiori-freestyle-writer/tsconfig.json index 46147e7903..a4a412cba2 100644 --- a/packages/fiori-freestyle-writer/tsconfig.json +++ b/packages/fiori-freestyle-writer/tsconfig.json @@ -10,6 +10,9 @@ "outDir": "dist" }, "references": [ + { + "path": "../cap-config-writer" + }, { "path": "../eslint-plugin-fiori-tools" }, diff --git a/packages/odata-service-inquirer/package.json b/packages/odata-service-inquirer/package.json index 410491ed91..fa2f9857db 100644 --- a/packages/odata-service-inquirer/package.json +++ b/packages/odata-service-inquirer/package.json @@ -56,6 +56,7 @@ "@sap-ux/fiori-freestyle-writer": "workspace:*", "@sap-ux/feature-toggle": "workspace:*", "@sap-ux/odata-service-writer": "workspace:*", + "@sap-ux/cap-config-writer": "workspace:*", "@sap-ux/vocabularies-types": "0.13.0", "@sap-devx/yeoman-ui-types": "1.14.4", "@types/inquirer-autocomplete-prompt": "2.0.1", diff --git a/packages/odata-service-inquirer/src/index.ts b/packages/odata-service-inquirer/src/index.ts index 18868707c0..13e63da550 100644 --- a/packages/odata-service-inquirer/src/index.ts +++ b/packages/odata-service-inquirer/src/index.ts @@ -22,17 +22,16 @@ import type { TemplateType } from '@sap-ux/fiori-elements-writer'; import { getEntitySelectionQuestions } from './prompts/edmx/questions'; import LoggerHelper from './prompts/logger-helper'; import { - type CapRuntime, - type CapService, + DatasourceType, + promptNames, type OdataServiceAnswers, type OdataServicePromptOptions, type OdataServiceQuestion, type SapSystemType, type EntityPromptOptions, - DatasourceType, - EntityRelatedAnswers, - promptNames + EntityRelatedAnswers } from './types'; +import type { CapService, CapRuntime } from '@sap-ux/cap-config-writer'; import { getPromptHostEnvironment, PromptState } from './utils'; /** diff --git a/packages/odata-service-inquirer/src/prompts/datasources/cap-project/cap-helpers.ts b/packages/odata-service-inquirer/src/prompts/datasources/cap-project/cap-helpers.ts index 07a22d8782..7051868f54 100644 --- a/packages/odata-service-inquirer/src/prompts/datasources/cap-project/cap-helpers.ts +++ b/packages/odata-service-inquirer/src/prompts/datasources/cap-project/cap-helpers.ts @@ -8,7 +8,8 @@ import { } from '@sap-ux/project-access'; import { basename, isAbsolute, relative } from 'path'; import { t } from '../../../i18n'; -import type { CapService, CapServiceChoice } from '../../../types'; +import type { CapServiceChoice } from '../../../types'; +import type { CapService } from '@sap-ux/cap-config-writer'; import LoggerHelper from '../../logger-helper'; import { errorHandler } from '../../prompt-helpers'; import type { CapProjectChoice, CapProjectPaths, CapProjectRootPath } from './types'; diff --git a/packages/odata-service-inquirer/src/prompts/datasources/cap-project/types.ts b/packages/odata-service-inquirer/src/prompts/datasources/cap-project/types.ts index 75927004c4..ded50386ae 100644 --- a/packages/odata-service-inquirer/src/prompts/datasources/cap-project/types.ts +++ b/packages/odata-service-inquirer/src/prompts/datasources/cap-project/types.ts @@ -1,5 +1,6 @@ import type { CapCustomPaths } from '@sap-ux/project-access'; -import type { CapService, CapServiceChoice, promptNames } from '../../../types'; +import type { CapServiceChoice, promptNames } from '../../../types'; +import type { CapService } from '@sap-ux/cap-config-writer'; import type { ListChoiceOptions } from 'inquirer'; /** diff --git a/packages/odata-service-inquirer/src/types.ts b/packages/odata-service-inquirer/src/types.ts index 9ec8fda8c3..6b7f38514d 100644 --- a/packages/odata-service-inquirer/src/types.ts +++ b/packages/odata-service-inquirer/src/types.ts @@ -2,9 +2,9 @@ import type { Annotations, ServiceProvider } from '@sap-ux/axios-extension'; import type { Destination } from '@sap-ux/btp-utils'; import type { CommonPromptOptions, YUIQuestion } from '@sap-ux/inquirer-common'; import type { OdataVersion } from '@sap-ux/odata-service-writer'; -import type { CdsVersionInfo } from '@sap-ux/project-access'; import type { BackendSystem } from '@sap-ux/store'; import type { ListChoiceOptions } from 'inquirer'; +import type { CapService } from '@sap-ux/cap-config-writer'; import type { EntityAnswer, NavigationEntityAnswer } from './prompts/edmx/entity-helper'; import type { TableSelectionMode, TableType } from '@sap-ux/fiori-elements-writer'; @@ -202,40 +202,6 @@ export type EntityRelatedAnswers = EntitySelectionAnswers & AnnotationGenerationAnswers & AlpTableConfigAnswers; -export type CapRuntime = 'Node.js' | 'Java'; - -export interface CapService { - /** - * The path to the CAP project. - */ - projectPath: string; - /** - * The CDS info for the Cds instance that was used to compile the project when determining the service. - */ - cdsVersionInfo?: CdsVersionInfo; - /** - * The name of the CAP service as identified by the cds model. - */ - serviceName: string; - /** - * The URL path to the service, as specfied in the manifest.json of generated apps - * This is also provided as `OdataServicePromptAnswers` property `servicePath` - */ - urlPath?: string; - /** - * The relative path (from the `projectPath`) to the service cds file. - */ - serviceCdsPath?: string; - /** - * The runtime of the Cds instance that was used to compile the project when determining the service. - */ - capType?: CapRuntime; - /** - * The relative path (from the `projectPath`) to the app folder - */ - appPath?: string; -} - export interface CapServiceChoice extends ListChoiceOptions { value: CapService; } diff --git a/packages/odata-service-inquirer/test/unit/prompts/cap-project/questions.test.ts b/packages/odata-service-inquirer/test/unit/prompts/cap-project/questions.test.ts index d7d06f1b18..d02002052d 100644 --- a/packages/odata-service-inquirer/test/unit/prompts/cap-project/questions.test.ts +++ b/packages/odata-service-inquirer/test/unit/prompts/cap-project/questions.test.ts @@ -1,7 +1,7 @@ import type { ListQuestion } from 'inquirer'; import { initI18nOdataServiceInquirer, t } from '../../../../src/i18n'; import { getLocalCapProjectPrompts } from '../../../../src/prompts/datasources/cap-project/questions'; -import type { CapService } from '../../../../src/types'; +import type { CapService } from '@sap-ux/cap-config-writer'; import { promptNames, type CapServiceChoice } from '../../../../src/types'; import { type CapProjectChoice, capInternalPromptNames } from '../../../../src/prompts/datasources/cap-project/types'; import { PromptState, getPromptHostEnvironment } from '../../../../src/utils'; diff --git a/packages/odata-service-inquirer/tsconfig.json b/packages/odata-service-inquirer/tsconfig.json index 212b115663..c4c92aa807 100644 --- a/packages/odata-service-inquirer/tsconfig.json +++ b/packages/odata-service-inquirer/tsconfig.json @@ -15,6 +15,9 @@ { "path": "../btp-utils" }, + { + "path": "../cap-config-writer" + }, { "path": "../feature-toggle" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b0aef78e65..7678e728b0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -859,9 +859,6 @@ importers: specifier: 1.6.11 version: 1.6.11 devDependencies: - '@sap-ux/odata-service-inquirer': - specifier: workspace:* - version: link:../odata-service-inquirer '@types/mem-fs': specifier: 1.1.2 version: 1.1.2 @@ -1713,6 +1710,9 @@ importers: packages/fiori-elements-writer: dependencies: + '@sap-ux/cap-config-writer': + specifier: workspace:* + version: link:../cap-config-writer '@sap-ux/fe-fpm-writer': specifier: workspace:* version: link:../fe-fpm-writer @@ -1780,6 +1780,9 @@ importers: packages/fiori-freestyle-writer: dependencies: + '@sap-ux/cap-config-writer': + specifier: workspace:* + version: link:../cap-config-writer '@sap-ux/fiori-generator-shared': specifier: workspace:* version: link:../fiori-generator-shared @@ -2446,6 +2449,9 @@ importers: '@sap-devx/yeoman-ui-types': specifier: 1.14.4 version: 1.14.4 + '@sap-ux/cap-config-writer': + specifier: workspace:* + version: link:../cap-config-writer '@sap-ux/feature-toggle': specifier: workspace:* version: link:../feature-toggle From bcdd0700269fd5700200a221cef23c433e4846c2 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 28 Jan 2025 15:58:27 +0000 Subject: [PATCH 04/17] chore: apply latest changesets --- .changeset/friendly-toes-beg.md | 8 -------- examples/simple-generator/CHANGELOG.md | 8 ++++++++ examples/simple-generator/package.json | 2 +- packages/cap-config-writer/CHANGELOG.md | 6 ++++++ packages/cap-config-writer/package.json | 2 +- packages/create/CHANGELOG.md | 7 +++++++ packages/create/package.json | 2 +- packages/fiori-elements-writer/CHANGELOG.md | 8 ++++++++ packages/fiori-elements-writer/package.json | 2 +- packages/fiori-freestyle-writer/CHANGELOG.md | 8 ++++++++ packages/fiori-freestyle-writer/package.json | 2 +- packages/odata-service-inquirer/CHANGELOG.md | 6 ++++++ packages/odata-service-inquirer/package.json | 2 +- 13 files changed, 49 insertions(+), 14 deletions(-) delete mode 100644 .changeset/friendly-toes-beg.md diff --git a/.changeset/friendly-toes-beg.md b/.changeset/friendly-toes-beg.md deleted file mode 100644 index a61628109b..0000000000 --- a/.changeset/friendly-toes-beg.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@sap-ux/odata-service-inquirer': major -'@sap-ux/cap-config-writer': minor -'@sap-ux/fiori-freestyle-writer': patch -'@sap-ux/fiori-elements-writer': patch ---- - -Move `CapService` and `CapRuntime` types from `@sap-ux/odata-service-inquirer` to `@sap-ux/cap-config-writer` for better relevance; add CAP updates to generate functions of Fiori Elements and Freestyle writers diff --git a/examples/simple-generator/CHANGELOG.md b/examples/simple-generator/CHANGELOG.md index 6d41e55701..5d1de5a1d9 100644 --- a/examples/simple-generator/CHANGELOG.md +++ b/examples/simple-generator/CHANGELOG.md @@ -1,5 +1,13 @@ # @sap-ux/generator-simple-fe +## 1.0.114 + +### Patch Changes + +- Updated dependencies [d6b7440] + - @sap-ux/fiori-freestyle-writer@2.0.3 + - @sap-ux/fiori-elements-writer@2.0.4 + ## 1.0.113 ### Patch Changes diff --git a/examples/simple-generator/package.json b/examples/simple-generator/package.json index e92c8645fc..5a9833c84a 100644 --- a/examples/simple-generator/package.json +++ b/examples/simple-generator/package.json @@ -1,6 +1,6 @@ { "name": "@sap-ux/generator-simple-fe", - "version": "1.0.113", + "version": "1.0.114", "description": "Simple example of a yeoman generator for Fiori elements.", "license": "Apache-2.0", "private": true, diff --git a/packages/cap-config-writer/CHANGELOG.md b/packages/cap-config-writer/CHANGELOG.md index e11aa274e0..41ef410006 100644 --- a/packages/cap-config-writer/CHANGELOG.md +++ b/packages/cap-config-writer/CHANGELOG.md @@ -1,5 +1,11 @@ # @sap-ux/cap-config-writer +## 0.9.0 + +### Minor Changes + +- d6b7440: Move `CapService` and `CapRuntime` types from `@sap-ux/odata-service-inquirer` to `@sap-ux/cap-config-writer` for better relevance; add CAP updates to generate functions of Fiori Elements and Freestyle writers + ## 0.8.4 ### Patch Changes diff --git a/packages/cap-config-writer/package.json b/packages/cap-config-writer/package.json index fb4749f3fd..86f022e1c5 100644 --- a/packages/cap-config-writer/package.json +++ b/packages/cap-config-writer/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/cap-config-writer", "description": "Add or update configuration for SAP CAP projects", - "version": "0.8.4", + "version": "0.9.0", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/create/CHANGELOG.md b/packages/create/CHANGELOG.md index 6156ca9dc6..4b19b68cd0 100644 --- a/packages/create/CHANGELOG.md +++ b/packages/create/CHANGELOG.md @@ -1,5 +1,12 @@ # @sap-ux/create +## 0.11.46 + +### Patch Changes + +- Updated dependencies [d6b7440] + - @sap-ux/cap-config-writer@0.9.0 + ## 0.11.45 ### Patch Changes diff --git a/packages/create/package.json b/packages/create/package.json index 2a4a5bed16..5365433bc4 100644 --- a/packages/create/package.json +++ b/packages/create/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/create", "description": "SAP Fiori tools module to add or remove features", - "version": "0.11.45", + "version": "0.11.46", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/fiori-elements-writer/CHANGELOG.md b/packages/fiori-elements-writer/CHANGELOG.md index b349f7f66f..927f16d9fd 100644 --- a/packages/fiori-elements-writer/CHANGELOG.md +++ b/packages/fiori-elements-writer/CHANGELOG.md @@ -1,5 +1,13 @@ # @sap-ux/fiori-elements-writer +## 2.0.4 + +### Patch Changes + +- d6b7440: Move `CapService` and `CapRuntime` types from `@sap-ux/odata-service-inquirer` to `@sap-ux/cap-config-writer` for better relevance; add CAP updates to generate functions of Fiori Elements and Freestyle writers +- Updated dependencies [d6b7440] + - @sap-ux/cap-config-writer@0.9.0 + ## 2.0.3 ### Patch Changes diff --git a/packages/fiori-elements-writer/package.json b/packages/fiori-elements-writer/package.json index b0c381b37a..cca52536eb 100644 --- a/packages/fiori-elements-writer/package.json +++ b/packages/fiori-elements-writer/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/fiori-elements-writer", "description": "SAP Fiori elements application writer", - "version": "2.0.3", + "version": "2.0.4", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/fiori-freestyle-writer/CHANGELOG.md b/packages/fiori-freestyle-writer/CHANGELOG.md index 0c1498da37..fefced29d8 100644 --- a/packages/fiori-freestyle-writer/CHANGELOG.md +++ b/packages/fiori-freestyle-writer/CHANGELOG.md @@ -1,5 +1,13 @@ # @sap-ux/fiori-freestyle-writer +## 2.0.3 + +### Patch Changes + +- d6b7440: Move `CapService` and `CapRuntime` types from `@sap-ux/odata-service-inquirer` to `@sap-ux/cap-config-writer` for better relevance; add CAP updates to generate functions of Fiori Elements and Freestyle writers +- Updated dependencies [d6b7440] + - @sap-ux/cap-config-writer@0.9.0 + ## 2.0.2 ### Patch Changes diff --git a/packages/fiori-freestyle-writer/package.json b/packages/fiori-freestyle-writer/package.json index 8c1527fb54..38f83ad5e6 100644 --- a/packages/fiori-freestyle-writer/package.json +++ b/packages/fiori-freestyle-writer/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/fiori-freestyle-writer", "description": "SAP Fiori freestyle application writer", - "version": "2.0.2", + "version": "2.0.3", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/odata-service-inquirer/CHANGELOG.md b/packages/odata-service-inquirer/CHANGELOG.md index 339a0b5ee0..2d4c54fb34 100644 --- a/packages/odata-service-inquirer/CHANGELOG.md +++ b/packages/odata-service-inquirer/CHANGELOG.md @@ -1,5 +1,11 @@ # @sap-ux/odata-service-inquirer +## 2.0.0 + +### Major Changes + +- d6b7440: Move `CapService` and `CapRuntime` types from `@sap-ux/odata-service-inquirer` to `@sap-ux/cap-config-writer` for better relevance; add CAP updates to generate functions of Fiori Elements and Freestyle writers + ## 1.3.0 ### Minor Changes diff --git a/packages/odata-service-inquirer/package.json b/packages/odata-service-inquirer/package.json index fa2f9857db..cd4b6cad47 100644 --- a/packages/odata-service-inquirer/package.json +++ b/packages/odata-service-inquirer/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/odata-service-inquirer", "description": "Prompts module that can prompt users for inputs required for odata service writing", - "version": "1.3.0", + "version": "2.0.0", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", From 9910e7fe8a6a59fe204d1b1bc45766698fc01e08 Mon Sep 17 00:00:00 2001 From: broksy <122096996+broksy@users.noreply.github.com> Date: Tue, 28 Jan 2025 19:19:18 +0200 Subject: [PATCH 05/17] fix: Setting default name for the service model (#2794) * fix: setting default name for the service model * feat: changeset * fix: condition for default model * test: enahnce data --- .changeset/dirty-wasps-relax.md | 5 ++++ .../odata-service-writer/src/data/defaults.ts | 3 ++- .../test/unit/index.test.ts | 23 +++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 .changeset/dirty-wasps-relax.md diff --git a/.changeset/dirty-wasps-relax.md b/.changeset/dirty-wasps-relax.md new file mode 100644 index 0000000000..39ba78a4b0 --- /dev/null +++ b/.changeset/dirty-wasps-relax.md @@ -0,0 +1,5 @@ +--- +'@sap-ux/odata-service-writer': patch +--- + +Improved set function for the default service model. diff --git a/packages/odata-service-writer/src/data/defaults.ts b/packages/odata-service-writer/src/data/defaults.ts index 548c9fdd58..612958bef2 100644 --- a/packages/odata-service-writer/src/data/defaults.ts +++ b/packages/odata-service-writer/src/data/defaults.ts @@ -61,7 +61,8 @@ async function setDefaultServiceModel(basePath: string, service: OdataService, f const servicesModels = Object.values(models).filter((model) => model.dataSource); service.model = servicesModels.length === 0 || - servicesModels.find((serviceModel) => serviceModel.dataSource === 'mainService') // model for mainService is "" + (servicesModels.find((serviceModel) => serviceModel.dataSource === DEFAULT_DATASOURCE_NAME) && + service.name === DEFAULT_DATASOURCE_NAME) // model for mainService is "" ? '' : service.model ?? service.name; } diff --git a/packages/odata-service-writer/test/unit/index.test.ts b/packages/odata-service-writer/test/unit/index.test.ts index 3ed8e0546b..68a5679ce4 100644 --- a/packages/odata-service-writer/test/unit/index.test.ts +++ b/packages/odata-service-writer/test/unit/index.test.ts @@ -483,6 +483,29 @@ describe('generate', () => { "version": "2", } `); + + // mainService model already exists + fs.writeJSON(join('webapp', 'manifest.json'), { + 'sap.app': { dataSources: { mainService: { type: 'OData' } } }, + 'sap.ui5': { models: { '': { dataSource: 'mainService' } } } + }); + // model called differentService is being added, 'differentService' should be used for model + configCopy = cloneDeep(Object.assign({}, config, { name: 'differentService' })); + await enhanceData('', configCopy, fs); + expect(configCopy).toMatchInlineSnapshot(` + Object { + "model": "differentService", + "name": "differentService", + "path": "/V2/Northwind/Northwind.svc/", + "previewSettings": Object { + "path": "/V2", + "url": "https://services.odata.org", + }, + "type": "edmx", + "url": "https://services.odata.org", + "version": "2", + } + `); }); }); }); From 882eeebebdbd536ff8f327a23544d45c3562b0c8 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 28 Jan 2025 17:41:21 +0000 Subject: [PATCH 06/17] chore: apply latest changesets --- .changeset/dirty-wasps-relax.md | 5 ----- examples/simple-generator/CHANGELOG.md | 7 +++++++ examples/simple-generator/package.json | 2 +- packages/adp-tooling/CHANGELOG.md | 7 +++++++ packages/adp-tooling/package.json | 2 +- packages/create/CHANGELOG.md | 11 +++++++++++ packages/create/package.json | 2 +- packages/fiori-elements-writer/CHANGELOG.md | 7 +++++++ packages/fiori-elements-writer/package.json | 2 +- packages/fiori-freestyle-writer/CHANGELOG.md | 7 +++++++ packages/fiori-freestyle-writer/package.json | 2 +- packages/flp-config-inquirer/CHANGELOG.md | 6 ++++++ packages/flp-config-inquirer/package.json | 2 +- packages/flp-config-sub-generator/CHANGELOG.md | 7 +++++++ packages/flp-config-sub-generator/package.json | 2 +- packages/odata-service-writer/CHANGELOG.md | 6 ++++++ packages/odata-service-writer/package.json | 2 +- packages/preview-middleware/CHANGELOG.md | 6 ++++++ packages/preview-middleware/package.json | 2 +- 19 files changed, 73 insertions(+), 14 deletions(-) delete mode 100644 .changeset/dirty-wasps-relax.md diff --git a/.changeset/dirty-wasps-relax.md b/.changeset/dirty-wasps-relax.md deleted file mode 100644 index 39ba78a4b0..0000000000 --- a/.changeset/dirty-wasps-relax.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@sap-ux/odata-service-writer': patch ---- - -Improved set function for the default service model. diff --git a/examples/simple-generator/CHANGELOG.md b/examples/simple-generator/CHANGELOG.md index 5d1de5a1d9..b4c90ec4bb 100644 --- a/examples/simple-generator/CHANGELOG.md +++ b/examples/simple-generator/CHANGELOG.md @@ -1,5 +1,12 @@ # @sap-ux/generator-simple-fe +## 1.0.115 + +### Patch Changes + +- @sap-ux/fiori-elements-writer@2.0.5 +- @sap-ux/fiori-freestyle-writer@2.0.4 + ## 1.0.114 ### Patch Changes diff --git a/examples/simple-generator/package.json b/examples/simple-generator/package.json index 5a9833c84a..104ed18d1d 100644 --- a/examples/simple-generator/package.json +++ b/examples/simple-generator/package.json @@ -1,6 +1,6 @@ { "name": "@sap-ux/generator-simple-fe", - "version": "1.0.114", + "version": "1.0.115", "description": "Simple example of a yeoman generator for Fiori elements.", "license": "Apache-2.0", "private": true, diff --git a/packages/adp-tooling/CHANGELOG.md b/packages/adp-tooling/CHANGELOG.md index 312d7c6205..646b097767 100644 --- a/packages/adp-tooling/CHANGELOG.md +++ b/packages/adp-tooling/CHANGELOG.md @@ -1,5 +1,12 @@ # @sap-ux/adp-tooling +## 0.12.116 + +### Patch Changes + +- Updated dependencies [9910e7f] + - @sap-ux/odata-service-writer@0.25.5 + ## 0.12.115 ### Patch Changes diff --git a/packages/adp-tooling/package.json b/packages/adp-tooling/package.json index fc01c44706..8c9e0b3656 100644 --- a/packages/adp-tooling/package.json +++ b/packages/adp-tooling/package.json @@ -9,7 +9,7 @@ "bugs": { "url": "https://github.com/SAP/open-ux-tools/issues?q=is%3Aopen+is%3Aissue+label%3Abug+label%3Aadp-tooling" }, - "version": "0.12.115", + "version": "0.12.116", "license": "Apache-2.0", "author": "@SAP/ux-tools-team", "main": "dist/index.js", diff --git a/packages/create/CHANGELOG.md b/packages/create/CHANGELOG.md index 4b19b68cd0..60f6ea0fe5 100644 --- a/packages/create/CHANGELOG.md +++ b/packages/create/CHANGELOG.md @@ -1,5 +1,16 @@ # @sap-ux/create +## 0.11.47 + +### Patch Changes + +- Updated dependencies [9910e7f] + - @sap-ux/odata-service-writer@0.25.5 + - @sap-ux/adp-tooling@0.12.116 + - @sap-ux/flp-config-inquirer@0.2.22 + - @sap-ux/preview-middleware@0.17.4 + - @sap-ux/app-config-writer@0.5.19 + ## 0.11.46 ### Patch Changes diff --git a/packages/create/package.json b/packages/create/package.json index 5365433bc4..444374cf27 100644 --- a/packages/create/package.json +++ b/packages/create/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/create", "description": "SAP Fiori tools module to add or remove features", - "version": "0.11.46", + "version": "0.11.47", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/fiori-elements-writer/CHANGELOG.md b/packages/fiori-elements-writer/CHANGELOG.md index 927f16d9fd..bb105bffbb 100644 --- a/packages/fiori-elements-writer/CHANGELOG.md +++ b/packages/fiori-elements-writer/CHANGELOG.md @@ -1,5 +1,12 @@ # @sap-ux/fiori-elements-writer +## 2.0.5 + +### Patch Changes + +- Updated dependencies [9910e7f] + - @sap-ux/odata-service-writer@0.25.5 + ## 2.0.4 ### Patch Changes diff --git a/packages/fiori-elements-writer/package.json b/packages/fiori-elements-writer/package.json index cca52536eb..45968d7fb9 100644 --- a/packages/fiori-elements-writer/package.json +++ b/packages/fiori-elements-writer/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/fiori-elements-writer", "description": "SAP Fiori elements application writer", - "version": "2.0.4", + "version": "2.0.5", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/fiori-freestyle-writer/CHANGELOG.md b/packages/fiori-freestyle-writer/CHANGELOG.md index fefced29d8..38b00abd5b 100644 --- a/packages/fiori-freestyle-writer/CHANGELOG.md +++ b/packages/fiori-freestyle-writer/CHANGELOG.md @@ -1,5 +1,12 @@ # @sap-ux/fiori-freestyle-writer +## 2.0.4 + +### Patch Changes + +- Updated dependencies [9910e7f] + - @sap-ux/odata-service-writer@0.25.5 + ## 2.0.3 ### Patch Changes diff --git a/packages/fiori-freestyle-writer/package.json b/packages/fiori-freestyle-writer/package.json index 38f83ad5e6..3b18bc26a0 100644 --- a/packages/fiori-freestyle-writer/package.json +++ b/packages/fiori-freestyle-writer/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/fiori-freestyle-writer", "description": "SAP Fiori freestyle application writer", - "version": "2.0.3", + "version": "2.0.4", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/flp-config-inquirer/CHANGELOG.md b/packages/flp-config-inquirer/CHANGELOG.md index a84b14d021..d2d535bc92 100644 --- a/packages/flp-config-inquirer/CHANGELOG.md +++ b/packages/flp-config-inquirer/CHANGELOG.md @@ -1,5 +1,11 @@ # @sap-ux/flp-config-inquirer +## 0.2.22 + +### Patch Changes + +- @sap-ux/adp-tooling@0.12.116 + ## 0.2.21 ### Patch Changes diff --git a/packages/flp-config-inquirer/package.json b/packages/flp-config-inquirer/package.json index e27bc4f32e..4a3a74b072 100644 --- a/packages/flp-config-inquirer/package.json +++ b/packages/flp-config-inquirer/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/flp-config-inquirer", "description": "Prompts module that can prompt users for inputs required for FLP configuration", - "version": "0.2.21", + "version": "0.2.22", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/flp-config-sub-generator/CHANGELOG.md b/packages/flp-config-sub-generator/CHANGELOG.md index 64543b9f0f..b1c6dd6f4b 100644 --- a/packages/flp-config-sub-generator/CHANGELOG.md +++ b/packages/flp-config-sub-generator/CHANGELOG.md @@ -1,5 +1,12 @@ # @sap-ux/flp-config-sub-generator +## 0.0.23 + +### Patch Changes + +- @sap-ux/flp-config-inquirer@0.2.22 +- @sap-ux/app-config-writer@0.5.19 + ## 0.0.22 ### Patch Changes diff --git a/packages/flp-config-sub-generator/package.json b/packages/flp-config-sub-generator/package.json index f21dd6323b..4f3c48600a 100644 --- a/packages/flp-config-sub-generator/package.json +++ b/packages/flp-config-sub-generator/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/flp-config-sub-generator", "description": "Generator for creating Fiori Launcpad configuration", - "version": "0.0.22", + "version": "0.0.23", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/odata-service-writer/CHANGELOG.md b/packages/odata-service-writer/CHANGELOG.md index 5b4ad55557..a55f4a6fbe 100644 --- a/packages/odata-service-writer/CHANGELOG.md +++ b/packages/odata-service-writer/CHANGELOG.md @@ -1,5 +1,11 @@ # @sap-ux/odata-service-writer +## 0.25.5 + +### Patch Changes + +- 9910e7f: Improved set function for the default service model. + ## 0.25.4 ### Patch Changes diff --git a/packages/odata-service-writer/package.json b/packages/odata-service-writer/package.json index 96cc1004c1..3f617664be 100644 --- a/packages/odata-service-writer/package.json +++ b/packages/odata-service-writer/package.json @@ -9,7 +9,7 @@ "bugs": { "url": "https://github.com/SAP/open-ux-tools/issues?q=is%3Aopen+is%3Aissue+label%3Abug+label%3Aodata-service-writer" }, - "version": "0.25.4", + "version": "0.25.5", "license": "Apache-2.0", "main": "dist/index.js", "scripts": { diff --git a/packages/preview-middleware/CHANGELOG.md b/packages/preview-middleware/CHANGELOG.md index b362fd5d97..4c1b353d00 100644 --- a/packages/preview-middleware/CHANGELOG.md +++ b/packages/preview-middleware/CHANGELOG.md @@ -1,5 +1,11 @@ # @sap-ux/preview-middleware +## 0.17.4 + +### Patch Changes + +- @sap-ux/adp-tooling@0.12.116 + ## 0.17.3 ### Patch Changes diff --git a/packages/preview-middleware/package.json b/packages/preview-middleware/package.json index 20582cf548..d40ce37ba9 100644 --- a/packages/preview-middleware/package.json +++ b/packages/preview-middleware/package.json @@ -9,7 +9,7 @@ "bugs": { "url": "https://github.com/SAP/open-ux-tools/issues?q=is%3Aopen+is%3Aissue+label%3Abug+label%3Apreview-middleware" }, - "version": "0.17.3", + "version": "0.17.4", "license": "Apache-2.0", "author": "@SAP/ux-tools-team", "main": "dist/index.js", From 3ff99e258693e81a2d18c237feec7e2fb406a620 Mon Sep 17 00:00:00 2001 From: J Long Date: Wed, 29 Jan 2025 12:06:06 +0000 Subject: [PATCH 07/17] 2821/add generate cap mta (#2822) * fix(cf-deploy-config-writer): expose a new method called generateCAPConfig to expose CAP mta generation flow * fix(cf-deploy-config-writer): add more tests * fix(cf-deploy-config-writer): add changeset * fix(cf-deploy-config-writer): fix lint * fix(cf-deploy-config-writer): fix lint * fix(cf-deploy-config-writer): add more tests --------- Co-authored-by: IainSAP <46536134+IainSAP@users.noreply.github.com> --- .changeset/soft-carrots-brush.md | 5 + packages/cf-deploy-config-writer/README.md | 73 +- .../src/cf-writer/app-config.ts | 129 ++-- .../src/cf-writer/base-config.ts | 148 +--- .../src/cf-writer/cap-config.ts | 52 ++ .../src/cf-writer/index.ts | 1 + .../cf-deploy-config-writer/src/constants.ts | 5 + .../src/mta-config/index.ts | 92 ++- .../src/mta-config/mta.ts | 156 ++-- .../cf-deploy-config-writer.i18n.json | 32 +- .../src/types/index.ts | 1 + packages/cf-deploy-config-writer/src/utils.ts | 120 ++- .../test/sample/capcds/.gitignore | 34 + .../test/sample/capcds/package.json | 29 + .../test/sample/capcds/xs-security.json | 6 + .../test/sample/standalone/.gitignore | 10 + .../test/sample/standalone/mta.yaml | 60 ++ .../test/sample/standalone/package.json | 15 + .../sample/standalone/router/package.json | 18 + .../test/sample/standalone/router/xs-app.json | 17 + .../test/sample/standalone/xs-security.json | 7 + .../test/sample/standalonewithapp/.gitignore | 10 + .../test/sample/standalonewithapp/mta.yaml | 60 ++ .../standalonewithapp/myapp/package.json | 28 + .../sample/standalonewithapp/myapp/ui5.yaml | 28 + .../myapp/webapp/manifest.json | 97 +++ .../sample/standalonewithapp/package.json | 15 + .../standalonewithapp/router/package.json | 18 + .../standalonewithapp/router/xs-app.json | 17 + .../sample/standalonewithapp/xs-security.json | 7 + .../unit/__snapshots__/index-app.test.ts.snap | 701 ++++++++++++------ .../unit/__snapshots__/index-cap.test.ts.snap | 306 ++++++++ .../test/unit/cap.test.ts | 4 +- .../unit/fixtures/mta-types/cdsmta/mta.yaml | 101 +++ .../test/unit/index-app.test.ts | 65 +- .../test/unit/index-cap.test.ts | 136 ++++ 36 files changed, 2053 insertions(+), 550 deletions(-) create mode 100644 .changeset/soft-carrots-brush.md create mode 100644 packages/cf-deploy-config-writer/src/cf-writer/cap-config.ts create mode 100644 packages/cf-deploy-config-writer/test/sample/capcds/.gitignore create mode 100644 packages/cf-deploy-config-writer/test/sample/capcds/package.json create mode 100644 packages/cf-deploy-config-writer/test/sample/capcds/xs-security.json create mode 100644 packages/cf-deploy-config-writer/test/sample/standalone/.gitignore create mode 100644 packages/cf-deploy-config-writer/test/sample/standalone/mta.yaml create mode 100644 packages/cf-deploy-config-writer/test/sample/standalone/package.json create mode 100644 packages/cf-deploy-config-writer/test/sample/standalone/router/package.json create mode 100644 packages/cf-deploy-config-writer/test/sample/standalone/router/xs-app.json create mode 100644 packages/cf-deploy-config-writer/test/sample/standalone/xs-security.json create mode 100644 packages/cf-deploy-config-writer/test/sample/standalonewithapp/.gitignore create mode 100644 packages/cf-deploy-config-writer/test/sample/standalonewithapp/mta.yaml create mode 100644 packages/cf-deploy-config-writer/test/sample/standalonewithapp/myapp/package.json create mode 100644 packages/cf-deploy-config-writer/test/sample/standalonewithapp/myapp/ui5.yaml create mode 100644 packages/cf-deploy-config-writer/test/sample/standalonewithapp/myapp/webapp/manifest.json create mode 100644 packages/cf-deploy-config-writer/test/sample/standalonewithapp/package.json create mode 100644 packages/cf-deploy-config-writer/test/sample/standalonewithapp/router/package.json create mode 100644 packages/cf-deploy-config-writer/test/sample/standalonewithapp/router/xs-app.json create mode 100644 packages/cf-deploy-config-writer/test/sample/standalonewithapp/xs-security.json create mode 100644 packages/cf-deploy-config-writer/test/unit/__snapshots__/index-cap.test.ts.snap create mode 100644 packages/cf-deploy-config-writer/test/unit/fixtures/mta-types/cdsmta/mta.yaml create mode 100644 packages/cf-deploy-config-writer/test/unit/index-cap.test.ts diff --git a/.changeset/soft-carrots-brush.md b/.changeset/soft-carrots-brush.md new file mode 100644 index 0000000000..79207e43e8 --- /dev/null +++ b/.changeset/soft-carrots-brush.md @@ -0,0 +1,5 @@ +--- +'@sap-ux/cf-deploy-config-writer': minor +--- + +append new logic to create CAP mta diff --git a/packages/cf-deploy-config-writer/README.md b/packages/cf-deploy-config-writer/README.md index fd087ae72e..351f9f1785 100644 --- a/packages/cf-deploy-config-writer/README.md +++ b/packages/cf-deploy-config-writer/README.md @@ -16,8 +16,13 @@ Yarn Pnpm `pnpm add @sap-ux/cf-deploy-config-writer` -## Usage -Calling the `MtaConfig` library to add different types of modules, for example HTML5 resources, routing module and mta extension configurations to an existing MTA configuration file. Dependent on the [MTA Tool](https://www.npmjs.com/package/mta) for exploring and validating the changes being made. +## Example: Reading and writing MTA Configurations +Generate an `MtaConfig` instance to read an `mta.yaml` configuration to allow you append different resources and modules. For example HTML5 resources, routing modules or append mta extension configurations. + +Dependent on the [MTA Tool](https://www.npmjs.com/package/mta) being installed globally on your dev space. +- For VSCode, run the command `npm i -g mta` +- For Business Application Studio, the binary is already installed + ```Typescript import { MtaConfig } from '@sap-ux/cf-deploy-config-writer'; // Create a new instance of MtaConfig @@ -38,17 +43,41 @@ await mtaConfig.addMtaExtensionConfig('mynewdestination', 'https://my-service-ur await mtaConfig.save(); ``` +## Example: Appending a Managed Approuter Configuration to an SAP Fiori UI5 Application + Calling the `generateAppConfig` function to append Cloud Foundry configuration to a HTML5 application, assumes `manifest.json` and `ui5.yaml` configurations are present otherwise the process will exit with an error; ```Typescript import { generateAppConfig, DefaultMTADestination } from '@sap-ux/cf-deploy-config-writer' import { join } from 'path'; const exampleWriter = async () => { - const appPath = join(__dirname, 'testapp'); + const ui5AppPath = join(__dirname, 'testapp'); // Option 1. Append managed approuter configuration, toggle `addManagedAppRouter` to false to ommit the managed approuter configuration being appended to the mta.yaml - const fs = await generateAppConfig({appPath, addManagedAppRouter: true, destinationName: 'SAPBTPDestination'}); + const fs = await generateAppConfig({appPath: ui5AppPath, addManagedAppRouter: true, destinationName: 'SAPBTPDestination'}); + return new Promise((resolve) => { + fs.commit(resolve); // When using with Yeoman it handle the fs commit. + }); +} +// Calling the function +await exampleWriter(); +``` + +## Example: Generate or Append a `Managed` Approuter Configuration to a SAP Fiori UI5 Application + +Calling the `generateAppConfig` function to append Cloud Foundry configuration to a HTML5 application; +- Assumes `manifest.json` and `ui5.yaml` configurations are present in the target folder +- Supports `CAP` projects where an existing `mta.yaml` is already present and you are adding a SAP Fiori UI5 app to it + +```Typescript +import { generateAppConfig, DefaultMTADestination } from '@sap-ux/cf-deploy-config-writer' +import { join } from 'path'; + +const exampleWriter = async () => { + const ui5AppPath = join(__dirname, 'testapp'); + // Option 1. Append managed approuter configuration, toggle `addManagedAppRouter` to false to ommit the managed approuter configuration being appended to the mta.yaml + const fs = await generateAppConfig({appPath: ui5AppPath, addManagedAppRouter: true, destinationName: 'SAPBTPDestination'}); // Option 2. For CAP flows, set the destination to DefaultMTADestination to create a destination instance between the HTML5 app and CAP Project - const fs = await generateAppConfig({appPath, addManagedAppRouter: true, destinationName: DefaultMTADestination}); + const fs = await generateAppConfig({appPath: ui5AppPath, addManagedAppRouter: true, destinationName: DefaultMTADestination}); return new Promise((resolve) => { fs.commit(resolve); // When using with Yeoman it handle the fs commit. }); @@ -57,15 +86,43 @@ const exampleWriter = async () => { await exampleWriter(); ``` +## Example: Generate a Base `Managed` | `Standalone` Approuter Configuration + Calling the `generateBaseConfig` function to generate a `new` Cloud Foundry configuration, supporting `managed` | `standalone` configurations; +- Creates a new `mta.yaml` into the specified `mtaPath`, it will fail if an existing `mta.yaml` is found +- Optional parameters include adding a `connectivity` service if the SAP BTP destination is using an `OnPremise` configuration +- New configuration will include a destination instance to expose a `UI5` endpoint, consumed by SAP Fiori applications when deployed to Cloud Foundry ```Typescript import { generateBaseConfig, RouterModuleType } from '@sap-ux/cf-deploy-config-writer' import { join } from 'path'; const exampleWriter = async () => { - const mtaPath = join(__dirname, 'testapp'); + const mtaPath = join(__dirname, 'testproject'); + // If your SAPUI5 application will be consuming an SAB BTP OnPremise destination, Connectivity serivce is required; Refer to https://discovery-center.cloud.sap/serviceCatalog/connectivity-service?region=all + const addConnectivityService = true; // Generate a managed approuter configuration, toggle the routerType to RouterModuleType.Standard for a standalone configuration - const fs = await generateBaseConfig({ mtaId: 'myapp', routerType: RouterModuleType.Managed, mtaPath }); + const fs = await generateBaseConfig({ mtaId: 'mymtaproject', routerType: RouterModuleType.Managed, mtaPath, addConnectivityService }); + return new Promise((resolve) => { + fs.commit(resolve); // When using with Yeoman it handle the fs commit. + }); +} +// Calling the function +await exampleWriter(); +``` + +## Example: Generate a CAP `Managed` | `Standalone` Approuter Configuration +Calling the `generateCAPConfig` function to generate a `new` Cloud Foundry configuration, supporting `managed` | `standalone` configurations; +- Generate a CAP `mta.yaml` with `destination`, `HTML5-Repo` and `XSUAA` services added by default +- New configuration will include destination instances to expose `UI5` and `CAP` endpoints, consumed by SAP Fiori applications when deployed to Cloud Foundry + +```Typescript +import { generateCAPConfig, RouterModuleType } from '@sap-ux/cf-deploy-config-writer' +import { join } from 'path'; + +const exampleWriter = async () => { + const mtaPath = join(__dirname, 'testcapproject'); + // Generate a managed approuter configuration, toggle the routerType to RouterModuleType.Standard or RouterModuleType.Managed + const fs = await generateCAPConfig({ mtaId: 'mymtaproject', routerType: RouterModuleType.Managed, mtaPath }); return new Promise((resolve) => { fs.commit(resolve); // When using with Yeoman it handle the fs commit. }); @@ -81,4 +138,6 @@ SAP Deployment Cloud Foundry MTA Multi-Target Application +CAP +CDS diff --git a/packages/cf-deploy-config-writer/src/cf-writer/app-config.ts b/packages/cf-deploy-config-writer/src/cf-writer/app-config.ts index 9e7a3f872d..9340ce05a8 100644 --- a/packages/cf-deploy-config-writer/src/cf-writer/app-config.ts +++ b/packages/cf-deploy-config-writer/src/cf-writer/app-config.ts @@ -1,8 +1,6 @@ import { dirname, join, relative } from 'path'; -import { spawnSync } from 'child_process'; import { create as createStorage } from 'mem-fs'; import { create, type Editor } from 'mem-fs-editor'; -import { sync } from 'hasbin'; import { type FioriToolsProxyConfig, type UI5Config, UI5Config as UI5ConfigInstance } from '@sap-ux/ui5-config'; import { addPackageDevDependency, @@ -16,16 +14,11 @@ import { import { Authentication } from '@sap-ux/btp-utils'; import { appDeployMTAScript, - CDSAddMtaParams, - CDSBinNotFound, - CDSExecutable, DefaultMTADestination, EmptyDestination, MbtPackage, MbtPackageVersion, - MTABinNotFound, MTABuildScript, - MTAExecutable, MTAFileExtension, ResourceMTADestination, Rimraf, @@ -33,14 +26,12 @@ import { rootDeployMTAScript, UI5DeployBuildScript, undeployMTAScript, - XSAppFile, - XSSecurityFile + WelcomeFile, + XSAppFile } from '../constants'; import { addCommonPackageDependencies, - addGitIgnore, - addRootPackage, - addXSSecurityConfig, + generateSupportingConfig, getDestinationProperties, getTemplatePath, readManifest, @@ -48,7 +39,10 @@ import { } from '../utils'; import { addMtaDeployParameters, + createCAPMTA, createMTA, + doesCDSBinaryExist, + doesMTABinaryExist, getMtaConfig, getMtaId, type MtaConfig, @@ -57,7 +51,7 @@ import { import LoggerHelper from '../logger-helper'; import { t } from '../i18n'; import { type Logger } from '@sap-ux/logger'; -import { ApiHubType, type CFAppConfig, type CFConfig, type MTABaseConfig } from '../types'; +import { type XSAppDocument, ApiHubType, type CFAppConfig, type CFConfig, type MTABaseConfig } from '../types'; /** * Add a managed approuter configuration to an existing HTML5 application. @@ -74,22 +68,11 @@ export async function generateAppConfig(cfAppConfig: CFAppConfig, fs?: Editor, l if (logger) { LoggerHelper.logger = logger; } - validateMtaConfig(); + doesMTABinaryExist(); await generateDeployConfig(cfAppConfig, fs); return fs; } -/** - * Validate the conditions to allow deployment configuration to be added. - * - */ -function validateMtaConfig(): void { - // CF writer is dependent on the mta-lib library, which in turn relies on the mta executable being installed and available in the path - if (!sync(MTAExecutable)) { - throw new Error(MTABinNotFound); - } -} - /** * Returns the updated configuration for the given HTML5 app, after reading all the required files. * @@ -105,6 +88,11 @@ async function getUpdatedConfig(cfAppConfig: CFAppConfig, fs: Editor): Promise { - const cfConfig = await getUpdatedConfig(cfAppConfig, fs); - // Generate MTA Config, LCAP will generate the mta.yaml on the fly so we dont care about it! - if (!cfConfig.lcapMode) { - createMTAConfig(cfConfig); - await generateSupportingConfig(cfConfig, fs); - await updateMtaConfig(cfConfig); + const config = await getUpdatedConfig(cfAppConfig, fs); + + LoggerHelper?.logger?.debug(`Generate app configuration using: \n ${JSON.stringify(config)}`); + + // Generate MTA Config, LCAP will generate the mta.yaml on the fly so we don't care about it! + if (!config.lcapMode) { + generateMTAFile(config); + await generateSupportingConfig(config, fs); + await updateMtaConfig(config, fs); } // Generate HTML5 config - await appendCloudFoundryConfigurations(cfConfig, fs); - await updateManifest(cfConfig, fs); - await updateHTML5AppPackage(cfConfig, fs); - await updateRootPackage(cfConfig, fs); + await appendCloudFoundryConfigurations(config, fs); + await updateManifest(config, fs); + await updateHTML5AppPackage(config, fs); + await updateRootPackage(config, fs); } /** @@ -251,15 +238,10 @@ async function generateDeployConfig(cfAppConfig: CFAppConfig, fs: Editor): Promi * * @param cfConfig writer configuration */ -function createMTAConfig(cfConfig: CFConfig): void { +export function generateMTAFile(cfConfig: CFConfig): void { if (!cfConfig.mtaId) { if (cfConfig.isCap) { - const result = spawnSync(CDSExecutable, CDSAddMtaParams, { - cwd: cfConfig.rootPath - }); - if (result.error) { - throw new Error(CDSBinNotFound); - } + createCAPMTA(cfConfig.rootPath); } else { createMTA({ mtaId: cfConfig.appId, mtaPath: cfConfig.mtaPath ?? cfConfig.rootPath } as MTABaseConfig); } @@ -268,34 +250,13 @@ function createMTAConfig(cfConfig: CFConfig): void { } } -/** - * Generate CF specific configurations to support deployment and undeployment. - * - * @param config writer configuration - * @param fs reference to a mem-fs editor - */ -async function generateSupportingConfig(config: CFConfig, fs: Editor): Promise { - const mtaId: string | undefined = config.mtaId ?? (await getMtaId(config.rootPath)); - // Add specific MTA ID configurations - const mtaConfig = { mtaId: mtaId ?? config.appId, mtaPath: config.rootPath } as MTABaseConfig; - if (mtaId && !fs.exists(join(config.rootPath, 'package.json'))) { - addRootPackage(mtaConfig, fs); - } - if (config.addManagedAppRouter && !fs.exists(join(config.rootPath, XSSecurityFile))) { - addXSSecurityConfig(mtaConfig, fs); - } - // Be a good developer and add a .gitignore if missing from the existing project root - if (!fs.exists(join(config.rootPath, '.gitignore'))) { - addGitIgnore(config.rootPath, fs); - } -} - /** * Updates the MTA configuration file. * * @param cfConfig writer configuration + * @param fs reference to a mem-fs editor */ -async function updateMtaConfig(cfConfig: CFConfig): Promise { +async function updateMtaConfig(cfConfig: CFConfig, fs: Editor): Promise { const mtaInstance = await getMtaConfig(cfConfig.rootPath); if (mtaInstance) { await mtaInstance.addRoutingModules({ isManagedApp: cfConfig.addManagedAppRouter }); @@ -315,11 +276,37 @@ async function updateMtaConfig(cfConfig: CFConfig): Promise { cfConfig.destinationAuthentication = Authentication.NO_AUTHENTICATION; } } + cleanupStandaloneRoutes(cfConfig, mtaInstance, fs); await saveMta(cfConfig, mtaInstance); cfConfig.cloudServiceName = mtaInstance.cloudServiceName; } } +/** + * + * @param root0 + * @param root0.rootPath + * @param root0.appId + * @param mtaInstance + * @param fs + */ +function cleanupStandaloneRoutes({ rootPath, appId }: CFConfig, mtaInstance: MtaConfig, fs: Editor): void { + // Cleanup standalone xs-app.json to reflect new application + const appRouterPath = mtaInstance.standaloneRouterPath; + if (appRouterPath) { + try { + const xsAppPath = join(appRouterPath, XSAppFile); + const appRouterXsAppObj = fs.readJSON(join(rootPath, xsAppPath)) as unknown as XSAppDocument; + if ((appRouterXsAppObj && !appRouterXsAppObj?.[WelcomeFile]) || appRouterXsAppObj?.[WelcomeFile] === '/') { + appRouterXsAppObj[WelcomeFile] = `/${appId}`; + fs.writeJSON(join(rootPath, xsAppPath), appRouterXsAppObj); + } + } catch (error) { + LoggerHelper.logger?.error(t('error.cannotUpdateRouterXSApp', { error })); + } + } +} + /** * Apply changes to mta.yaml. * @@ -420,7 +407,7 @@ async function updateHTML5AppPackage(cfConfig: CFConfig, fs: Editor): Promise { - const packageExists = fs.exists(join(cfConfig.rootPath, 'package.json')); + const packageExists = fs.exists(join(cfConfig.rootPath, FileName.Package)); // Append mta scripts only if mta.yaml is at a different level to the HTML5 app if (cfConfig.isMtaRoot && packageExists) { await addPackageDevDependency(cfConfig.rootPath, Rimraf, RimrafVersion, fs); diff --git a/packages/cf-deploy-config-writer/src/cf-writer/base-config.ts b/packages/cf-deploy-config-writer/src/cf-writer/base-config.ts index b69ae55e74..3145d718c3 100644 --- a/packages/cf-deploy-config-writer/src/cf-writer/base-config.ts +++ b/packages/cf-deploy-config-writer/src/cf-writer/base-config.ts @@ -1,22 +1,12 @@ -import { join } from 'path'; import { create as createStorage } from 'mem-fs'; import { create, type Editor } from 'mem-fs-editor'; -import { sync } from 'hasbin'; -import { apiGetInstanceCredentials } from '@sap/cf-tools'; -import { MTAExecutable, MTABinNotFound, RouterModule, XSAppFile } from '../constants'; -import { - getTemplatePath, - toMtaModuleName, - validateVersion, - addGitIgnore, - addRootPackage, - addXSSecurityConfig -} from '../utils'; +import { addSupportingConfig, addRoutingConfig } from '../utils'; import LoggerHelper from '../logger-helper'; -import { t } from '../i18n'; -import { MtaConfig, createMTA, addMtaDeployParameters } from '../mta-config'; +import { createMTA, validateMtaConfig } from '../mta-config'; import { type Logger } from '@sap-ux/logger'; -import { type CFBaseConfig, RouterModuleType, type MTABaseConfig } from '../types'; +import { type CFBaseConfig, type MTABaseConfig } from '../types'; +import { join } from 'path'; +import { t } from '../i18n'; /** * Add a standalone | managed approuter to an empty target folder. @@ -33,132 +23,14 @@ export async function generateBaseConfig(config: CFBaseConfig, fs?: Editor, logg if (logger) { LoggerHelper.logger = logger; } - - logger?.debug(`Generate configuration using: \n ${JSON.stringify(config)}`); - - validateMtaConfig(config, fs); - updateBaseConfig(config); + logger?.debug(`Generate base configuration using: \n ${JSON.stringify(config)}`); + validateMtaConfig(config); + if (fs.exists(join(config.mtaPath, config.mtaId))) { + throw new Error(t('error.mtaFolderAlreadyExists')); + } createMTA(config as MTABaseConfig); await addRoutingConfig(config, fs); addSupportingConfig(config, fs); LoggerHelper.logger?.debug(`CF Config ${JSON.stringify(config, null, 2)}`); return fs; } - -/** - * Add standalone or managed approuter to the target folder. - * - * @param config writer configuration - * @param fs reference to a mem-fs editor - */ -async function addRoutingConfig(config: CFBaseConfig, fs: Editor): Promise { - const mtaConfigInstance = await MtaConfig.newInstance(config.mtaPath); - if (config.routerType === RouterModuleType.Standard) { - await addStandaloneRouter(config, mtaConfigInstance, fs); - } else { - await mtaConfigInstance.addRoutingModules({ isManagedApp: true, addMissingModules: false }); - } - await addMtaDeployParameters(mtaConfigInstance); - await mtaConfigInstance.save(); -} - -/** - * Update the writer configuration with defaults. - * - * @param config writer configuration - */ -function updateBaseConfig(config: CFBaseConfig): void { - config.mtaPath = config.mtaPath.replace(/\/$/, ''); - config.addConnectivityService ||= false; - config.mtaId = toMtaModuleName(config.mtaId); -} - -/** - * Add standalone approuter to the target folder. - * - * @param cfConfig writer configuration - * @param mtaInstance MTA configuration instance - * @param fs reference to a mem-fs editor - */ -async function addStandaloneRouter(cfConfig: CFBaseConfig, mtaInstance: MtaConfig, fs: Editor): Promise { - await mtaInstance.addStandaloneRouter(true); - if (cfConfig.addConnectivityService) { - await mtaInstance.addConnectivityResource(); - } - const { abapServiceName, abapService } = cfConfig.abapServiceProvider ?? {}; - if (abapServiceName && abapService) { - await mtaInstance.addAbapService(abapServiceName, abapService); - } - - fs.copyTpl(getTemplatePath(`router/package.json`), join(cfConfig.mtaPath, `${RouterModule}/package.json`)); - - if (abapServiceName) { - let serviceKey; - try { - const instanceCredentials = await apiGetInstanceCredentials(abapServiceName); - serviceKey = instanceCredentials?.credentials; - } catch { - LoggerHelper.logger?.error(t('error.serviceKeyFailed')); - } - const endpoints = serviceKey?.endpoints ? Object.keys(serviceKey.endpoints) : ['']; - const service = serviceKey ? serviceKey['sap.cloud.service'] : ''; - fs.copyTpl( - getTemplatePath('router/xs-app-abapservice.json'), - join(cfConfig.mtaPath, `${RouterModule}/${XSAppFile}`), - { servicekeyService: service, servicekeyEndpoint: endpoints[0] } - ); - } else { - fs.copyTpl( - getTemplatePath('router/xs-app-server.json'), - join(cfConfig.mtaPath, `${RouterModule}/${XSAppFile}`) - ); - } -} - -/** - * Add supporting configuration to the target folder. - * - * @param config writer configuration - * @param fs reference to a mem-fs editor - */ -function addSupportingConfig(config: CFBaseConfig, fs: Editor): void { - addRootPackage(config, fs); - addGitIgnore(config.mtaPath, fs); - addXSSecurityConfig(config, fs); -} - -/** - * Validate the writer configuration to ensure all required parameters are present. - * - * @param config writer configuration - * @param fs reference to a mem-fs editor - */ -function validateMtaConfig(config: CFBaseConfig, fs: Editor): void { - // We use mta-lib, which in turn relies on the mta executable being installed and available in the path - if (!sync(MTAExecutable)) { - throw new Error(MTABinNotFound); - } - - if (!config.routerType || !config.mtaId || !config.mtaPath) { - throw new Error(t('error.missingMtaParameters')); - } - if (config.mtaId.length > 128 || !/^[a-zA-Z_]/.test(config.mtaId)) { - throw new Error(t('error.invalidMtaId')); - } - if (!/^[\w\-.]*$/.test(config.mtaId)) { - throw new Error(t('error.invalidMtaIdWithChars')); - } - - validateVersion(config.mtaVersion); - - if ( - config.abapServiceProvider && - (!config.abapServiceProvider.abapService || !config.abapServiceProvider.abapServiceName) - ) { - throw new Error(t('error.missingABAPServiceBindingDetails')); - } - - if (fs.exists(join(config.mtaPath, config.mtaId))) { - throw new Error(t('error.mtaAlreadyExists')); - } -} diff --git a/packages/cf-deploy-config-writer/src/cf-writer/cap-config.ts b/packages/cf-deploy-config-writer/src/cf-writer/cap-config.ts new file mode 100644 index 0000000000..0a5b5abe1b --- /dev/null +++ b/packages/cf-deploy-config-writer/src/cf-writer/cap-config.ts @@ -0,0 +1,52 @@ +import { create as createStorage } from 'mem-fs'; +import { create, type Editor } from 'mem-fs-editor'; +import { addSupportingConfig, addRoutingConfig } from '../utils'; +import { createCAPMTA, validateMtaConfig, isMTAFound } from '../mta-config'; +import LoggerHelper from '../logger-helper'; +import type { Logger } from '@sap-ux/logger'; +import type { CAPConfig, CFBaseConfig } from '../types'; +import { CDSDestinationService, CDSHTML5RepoService, CDSXSUAAService } from '../constants'; +import { t } from '../i18n'; +import { getCapProjectType } from '@sap-ux/project-access'; + +/** + * Add a standalone | managed approuter to a CAP project. + * + * @param config writer configuration + * @param fs an optional reference to a mem-fs editor + * @param logger optional logger instance + * @returns file system reference + */ +export async function generateCAPConfig(config: CAPConfig, fs?: Editor, logger?: Logger): Promise { + if (!fs) { + fs = create(createStorage()); + } + if (logger) { + LoggerHelper.logger = logger; + } + logger?.debug(`Generate CAP configuration using: \n ${JSON.stringify(config)}`); + await validateConfig(config); + const cdsOptionalParams: string[] = [CDSXSUAAService, CDSDestinationService, CDSHTML5RepoService]; + createCAPMTA(config.mtaPath, cdsOptionalParams); + await addRoutingConfig(config, fs); + addSupportingConfig(config, fs); + LoggerHelper.logger?.debug(`CF CAP Config ${JSON.stringify(config, null, 2)}`); + return fs; +} + +/** + * Ensure the configuration is valid, target folder exists and is a CAP Node.js app and mta.yaml does not already exist. + * + * @param config writer configuration + */ +async function validateConfig(config: CAPConfig): Promise { + validateMtaConfig(config as CFBaseConfig); + // Check if the target directory contains a CAP Node.js project or exists! + if ((await getCapProjectType(config.mtaPath)) !== 'CAPNodejs') { + throw new Error(t('error.doesNotContainACapApp')); + } + // Check if the target directory contains an existing mta.yaml + if (isMTAFound(config.mtaPath)) { + throw new Error(t('error.mtaAlreadyExists')); + } +} diff --git a/packages/cf-deploy-config-writer/src/cf-writer/index.ts b/packages/cf-deploy-config-writer/src/cf-writer/index.ts index 82ffb7df67..bb7188ba21 100644 --- a/packages/cf-deploy-config-writer/src/cf-writer/index.ts +++ b/packages/cf-deploy-config-writer/src/cf-writer/index.ts @@ -1,2 +1,3 @@ export { generateAppConfig } from './app-config'; export { generateBaseConfig } from './base-config'; +export { generateCAPConfig } from './cap-config'; diff --git a/packages/cf-deploy-config-writer/src/constants.ts b/packages/cf-deploy-config-writer/src/constants.ts index fdbc26b412..a5fb565b93 100644 --- a/packages/cf-deploy-config-writer/src/constants.ts +++ b/packages/cf-deploy-config-writer/src/constants.ts @@ -9,6 +9,7 @@ export const MTABuildParams = 'build-parameters'; export const MTAFileExtension = 'mta-ext.mtaext'; export const DefaultServiceURL = '${default-url}'; export const ManagedXSUAA = 'managed:xsuaa'; +export const HTML5RepoHost = 'html5-apps-repo:app-host'; export const SRV_API = 'srv-api'; export const DefaultMTADestination = 'fiori-default-srv-api'; export const EmptyDestination = 'NONE'; @@ -36,6 +37,10 @@ export const UI5TaskZipperPackageVersion = '^3.1.3'; export const UI5Package = '@ui5/cli'; export const UI5PackageVersion = '^3.9.2'; export const CDSAddMtaParams = ['add', 'mta']; +export const CDSXSUAAService = 'xsuaa'; +export const CDSHTML5RepoService = 'html5-repo'; +export const CDSConnectivityService = 'connectivity'; +export const CDSDestinationService = 'destination'; export const MTAAPIDestination = { Name: ResourceMTADestination, Type: 'HTTP', diff --git a/packages/cf-deploy-config-writer/src/mta-config/index.ts b/packages/cf-deploy-config-writer/src/mta-config/index.ts index 03fd46f1d5..49c380da75 100644 --- a/packages/cf-deploy-config-writer/src/mta-config/index.ts +++ b/packages/cf-deploy-config-writer/src/mta-config/index.ts @@ -2,11 +2,25 @@ import { readFileSync, writeFileSync } from 'fs'; import { join } from 'path'; import { render } from 'ejs'; import { MtaConfig } from './mta'; -import { getTemplatePath } from '../utils'; -import { MTAYamlFile, MTAVersion, MTADescription, deployMode, enableParallelDeployments } from '../constants'; +import { getTemplatePath, setMtaDefaults, validateVersion } from '../utils'; +import { + MTAYamlFile, + MTAVersion, + MTADescription, + deployMode, + enableParallelDeployments, + CDSAddMtaParams, + CDSBinNotFound, + CDSExecutable, + MTABinNotFound, + MTAExecutable +} from '../constants'; import type { mta } from '@sap/mta-lib'; -import type { MTABaseConfig } from '../types'; +import { type MTABaseConfig, type CFBaseConfig } from '../types'; import LoggerHelper from '../logger-helper'; +import { sync } from 'hasbin'; +import { spawnSync } from 'child_process'; +import { t } from '../i18n'; /** * Get the MTA ID, read from the root path specified. @@ -93,4 +107,76 @@ export async function addMtaDeployParameters(mtaInstance: MtaConfig): Promise 128 || !/^[a-zA-Z_]/.test(config.mtaId)) { + throw new Error(t('error.invalidMtaId')); + } + if (!/^[\w\-.]*$/.test(config.mtaId)) { + throw new Error(t('error.invalidMtaIdWithChars')); + } + + validateVersion(config.mtaVersion); + + if ( + config.abapServiceProvider && + (!config.abapServiceProvider.abapService || !config.abapServiceProvider.abapServiceName) + ) { + throw new Error(t('error.missingABAPServiceBindingDetails')); + } + + setMtaDefaults(config); +} + export * from './mta'; diff --git a/packages/cf-deploy-config-writer/src/mta-config/mta.ts b/packages/cf-deploy-config-writer/src/mta-config/mta.ts index 8f32388d31..763c8309c4 100644 --- a/packages/cf-deploy-config-writer/src/mta-config/mta.ts +++ b/packages/cf-deploy-config-writer/src/mta-config/mta.ts @@ -23,7 +23,8 @@ import { MTAAPIDestination, UI5StandaloneModuleDestination, ServiceAPIRequires, - HTMLAppBuildParams + HTMLAppBuildParams, + HTML5RepoHost } from '../constants'; import { t } from '../i18n'; import type { Logger } from '@sap-ux/logger'; @@ -115,7 +116,7 @@ export class MtaConfig { if (resource.parameters?.service === 'html5-apps-repo') { this.resources.set( resource.parameters['service-plan'] === 'app-host' - ? 'html5-apps-repo:app-host' + ? HTML5RepoHost : 'html5-apps-repo:app-runtime', resource ); @@ -139,7 +140,7 @@ export class MtaConfig { this.apps.set(module.name, module); } else if (this.targetExists(module.requires ?? [], 'destination')) { this.modules.set('com.sap.application.content:destination', module); - } else if (this.targetExists(module.requires ?? [], 'html5-apps-repo:app-host')) { + } else if (this.targetExists(module.requires ?? [], HTML5RepoHost)) { this.modules.set('com.sap.application.content:resource', module); } else { this.modules.set(module.type as ModuleType, module); // i.e. 'approuter.nodejs' @@ -150,11 +151,11 @@ export class MtaConfig { } private async addAppContent(): Promise { - if (!this.resources.has('html5-apps-repo:app-host')) { + if (!this.resources.has(HTML5RepoHost)) { await this.addHtml5Host(); } // Setup the basic module template, artifacts will be added in another step - const appHostName = this.resources.get('html5-apps-repo:app-host')?.name; + const appHostName = this.resources.get(HTML5RepoHost)?.name; if (appHostName) { const deployer: mta.Module = { name: `${this.prefix.slice(0, 100)}-app-content`, @@ -205,6 +206,24 @@ export class MtaConfig { this.dirty = true; } + /** + * + * @param serviceName + * @param resourceName + */ + private async updateServiceName(serviceName: string, resourceName: string): Promise { + const resource = this.resources.get(resourceName); + if (resource && !resource.parameters?.['service-name']) { + resource.parameters = { + ...(resource.parameters ?? {}), + 'service-name': `${this.prefix.slice(0, 100)}-${serviceName}-service` + }; + await this.mta.updateResource(resource); + this.resources.set(resourceName, resource); + this.dirty = true; + } + } + private async addHtml5Host(): Promise { const html5host = `${this.prefix.slice(0, 100)}-repo-host`; // Need to cater for -key being added too! const resource: mta.Resource = { @@ -217,7 +236,7 @@ export class MtaConfig { } }; await this.mta.addResource(resource); - this.resources.set('html5-apps-repo:app-host', resource); + this.resources.set(HTML5RepoHost, resource); this.dirty = true; } @@ -525,7 +544,7 @@ export class MtaConfig { isManagedApp?: boolean; addMissingModules?: boolean; } = {}): Promise { - if (isManagedApp && !this.modules.has('com.sap.application.content:destination')) { + if (isManagedApp) { await this.addManagedAppRouter(); } @@ -822,72 +841,79 @@ export class MtaConfig { if (!this.resources.has(ManagedXSUAA)) { await this.addManagedUaa(); } - if (!this.resources.has('html5-apps-repo:app-host')) { + if (!this.resources.has(HTML5RepoHost)) { await this.addHtml5Host(); } - const destinationName = this.resources.get('destination')?.name; - const appHostName = this.resources.get('html5-apps-repo:app-host')?.name; - const appHostServiceName = this.resources.get('html5-apps-repo:app-host')?.parameters?.['service-name']; - const managedXSUAAName = this.resources.get(ManagedXSUAA)?.name; - const managedXSUAAServiceName = this.resources.get(ManagedXSUAA)?.parameters?.['service-name']; - if (destinationName && appHostName && managedXSUAAName && managedXSUAAServiceName) { - const router: mta.Module = { - name: `${this.prefix.slice(0, 100)}-destination-content`, - type: 'com.sap.application.content', - requires: [ - { - name: destinationName, - parameters: { - 'content-target': true - } - }, - { - name: appHostName, - parameters: { - 'service-key': { - name: `${appHostName}-key` + // Assume these need to be updated for safety! + await this.updateServiceName('html5', HTML5RepoHost); + await this.updateServiceName('xsuaa', ManagedXSUAA); + + // We only want to append a new one, if missing from the existing mta config + if (!this.modules.has('com.sap.application.content:destination')) { + const destinationName = this.resources.get('destination')?.name; + const appHostName = this.resources.get(HTML5RepoHost)?.name; + const appHostServiceName = this.resources.get(HTML5RepoHost)?.parameters?.['service-name']; + const managedXSUAAName = this.resources.get(ManagedXSUAA)?.name; + const managedXSUAAServiceName = this.resources.get(ManagedXSUAA)?.parameters?.['service-name']; + if (destinationName && appHostName && managedXSUAAName && managedXSUAAServiceName) { + const router: mta.Module = { + name: `${this.prefix.slice(0, 100)}-destination-content`, + type: 'com.sap.application.content', + requires: [ + { + name: destinationName, + parameters: { + 'content-target': true } - } - }, - { - name: managedXSUAAName, - parameters: { - 'service-key': { - name: `${managedXSUAAName}-key` + }, + { + name: appHostName, + parameters: { + 'service-key': { + name: `${appHostName}-key` + } } - } - } - ], - parameters: { - content: { - instance: { - destinations: [ - { - Name: `${this.prefix.slice(0, 100)}_html_repo_host`, - ServiceInstanceName: appHostServiceName, - ServiceKeyName: `${appHostName}-key`, - 'sap.cloud.service': `${this.prefix.slice(0, 100)}` - }, - { - Authentication: 'OAuth2UserTokenExchange', - Name: `${this.prefix.slice(0, 100)}_uaa`, - ServiceInstanceName: managedXSUAAServiceName, - ServiceKeyName: `${managedXSUAAName}-key`, - 'sap.cloud.service': `${this.prefix.slice(0, 100)}` + }, + { + name: managedXSUAAName, + parameters: { + 'service-key': { + name: `${managedXSUAAName}-key` } - ], - 'existing_destinations_policy': 'update' + } } + ], + parameters: { + content: { + instance: { + destinations: [ + { + Name: `${this.prefix.slice(0, 100)}_html_repo_host`, + ServiceInstanceName: appHostServiceName, + ServiceKeyName: `${appHostName}-key`, + 'sap.cloud.service': `${this.prefix.slice(0, 100)}` + }, + { + Authentication: 'OAuth2UserTokenExchange', + Name: `${this.prefix.slice(0, 100)}_uaa`, + ServiceInstanceName: managedXSUAAServiceName, + ServiceKeyName: `${managedXSUAAName}-key`, + 'sap.cloud.service': `${this.prefix.slice(0, 100)}` + } + ], + 'existing_destinations_policy': 'update' + } + } + }, + 'build-parameters': { + 'no-source': true } - }, - 'build-parameters': { - 'no-source': true - } - }; - await this.mta.addModule(router); - this.modules.set('com.sap.application.content:destination', router); - this.dirty = true; + }; + await this.mta.addModule(router); + this.modules.set('com.sap.application.content:destination', router); + this.dirty = true; + } } } diff --git a/packages/cf-deploy-config-writer/src/translations/cf-deploy-config-writer.i18n.json b/packages/cf-deploy-config-writer/src/translations/cf-deploy-config-writer.i18n.json index c086be3905..ae2d32e90f 100644 --- a/packages/cf-deploy-config-writer/src/translations/cf-deploy-config-writer.i18n.json +++ b/packages/cf-deploy-config-writer/src/translations/cf-deploy-config-writer.i18n.json @@ -5,21 +5,25 @@ "ui5YamlDoesNotExist": "File ui5.yaml does not exist in the project" }, "error": { - "unableToLoadMTA": "Unable to load mta.yaml configuration", - "updatingMTAExtensionFailed": "Unable to add mta extension configuration to file: {{mtaExtFilePath}}", - "cannotFindBinary": "Cannot find the \"{{bin}}\" executable. Please add it to the path or use \"npm i -g {{pkg}}\" to install it.", - "mtaExtensionFailed": "Unable to create or update the mta extension file for Api Hub Enterprise destination configuration: {{error}}", - "serviceKeyFailed": "Failed to fetch service key", - "missingMtaParameters": "Missing required parameters, MTA path, MTA ID or router type is missing", - "invalidMtaIdWithChars": "The MTA ID can only contain letters, numbers, dashes, periods, underscores", - "invalidMtaId": "The MTA ID must start with a letter or underscore and be less than 128 characters long", - "missingABAPServiceBindingDetails": "Missing ABAP service details for direct service binding", - "mtaAlreadyExists": "A folder with same name already exists in the target directory" + "unableToLoadMTA": "Unable to load mta.yaml configuration.", + "updatingMTAExtensionFailed": "Unable to add mta extension configuration to file: {{mtaExtFilePath}}.", + "cannotFindBinary": "Cannot find the \"{{bin}}\" executable. Please add it to the path or use \"npm i -g {{- pkg}}\" to install it.", + "mtaExtensionFailed": "Unable to create or update the mta extension file for Api Hub Enterprise destination configuration: {{error}}.", + "serviceKeyFailed": "Failed to fetch service key.", + "missingMtaParameters": "Missing required parameters, MTA path, MTA ID or router type is missing.", + "invalidMtaIdWithChars": "The MTA ID can only contain letters, numbers, dashes, periods, underscores.", + "invalidMtaId": "The MTA ID must start with a letter or underscore and be less than 128 characters long.", + "missingABAPServiceBindingDetails": "Missing ABAP service details for direct service binding.", + "mtaFolderAlreadyExists": "A folder with same name already exists in the target directory.", + "mtaAlreadyExists": "An mta.yaml already exists in the target directory.", + "cannotUpdateRouterXSApp": "Unable to update router xs-app.json welcome location.", + "targetFolderDoesNotExist": "Target folder does not exist, {{targetFolder}}.", + "doesNotContainACapApp": "Target folder does not contain a Node.js CAP project." }, "info":{ - "existingMTAExtensionNotFound": "Cannot find a valid existing mta extension file, a new one will be created", - "existingDestinationNotFound": "A destination service resource cannot be found in the mta.yaml. An mta extension destination instance cannot be added", - "mtaExtensionCreated": "Created file: {{mtaExtFile}} to extend mta module {{appMtaId}} with destination configuration", - "mtaExtensionUpdated": "Updated file: {{mtaExtFile}} with module destination configuration" + "existingMTAExtensionNotFound": "Cannot find a valid existing mta extension file, a new one will be created.", + "existingDestinationNotFound": "A destination service resource cannot be found in the mta.yaml. An mta extension destination instance cannot be added.", + "mtaExtensionCreated": "Created file: {{mtaExtFile}} to extend mta module {{appMtaId}} with destination configuration.", + "mtaExtensionUpdated": "Updated file: {{mtaExtFile}} with module destination configuration." } } diff --git a/packages/cf-deploy-config-writer/src/types/index.ts b/packages/cf-deploy-config-writer/src/types/index.ts index 55a887a26e..0392348f02 100644 --- a/packages/cf-deploy-config-writer/src/types/index.ts +++ b/packages/cf-deploy-config-writer/src/types/index.ts @@ -67,6 +67,7 @@ export interface CFConfig extends CFAppConfig, CFBaseConfig { firstServicePathSegment?: string; isMtaRoot?: boolean; } +export interface CAPConfig extends Omit {} export const enum ApiHubType { apiHub = 'API_HUB', apiHubEnterprise = 'API_HUB_ENTERPRISE' diff --git a/packages/cf-deploy-config-writer/src/utils.ts b/packages/cf-deploy-config-writer/src/utils.ts index 9290dc4ac2..afa670dc52 100644 --- a/packages/cf-deploy-config-writer/src/utils.ts +++ b/packages/cf-deploy-config-writer/src/utils.ts @@ -7,7 +7,7 @@ import { type Authentication, type Destinations } from '@sap-ux/btp-utils'; -import { addPackageDevDependency, type Manifest } from '@sap-ux/project-access'; +import { addPackageDevDependency, FileName, type Manifest } from '@sap-ux/project-access'; import { MTAVersion, UI5BuilderWebIdePackage, @@ -16,10 +16,16 @@ import { UI5PackageVersion, UI5TaskZipperPackage, UI5TaskZipperPackageVersion, - XSSecurityFile + XSSecurityFile, + RouterModule, + XSAppFile } from './constants'; import type { Editor } from 'mem-fs-editor'; -import type { MTABaseConfig } from './types'; +import { type MTABaseConfig, type CFConfig, type CFBaseConfig, RouterModuleType } from './types'; +import { getMtaId, MtaConfig, addMtaDeployParameters } from './mta-config'; +import { apiGetInstanceCredentials } from '@sap/cf-tools'; +import LoggerHelper from './logger-helper'; +import { t } from './i18n'; let cachedDestinationsList: Destinations = {}; @@ -41,7 +47,7 @@ export async function readManifest(manifestPath: string, fs: Editor): Promise { + const mtaId: string = config.mtaId ?? (await getMtaId(config.rootPath)); + // Add specific MTA ID configurations + const mtaConfig = { mtaId, mtaPath: config.rootPath } as MTABaseConfig; + if (mtaId && !fs.exists(join(config.rootPath, 'package.json'))) { + addRootPackage(mtaConfig, fs); + } + if (config.addManagedAppRouter && !fs.exists(join(config.rootPath, XSSecurityFile))) { + addXSSecurityConfig(mtaConfig, fs); + } + // Be a good developer and add a .gitignore if missing from the existing project root + if (!fs.exists(join(config.rootPath, '.gitignore'))) { + addGitIgnore(config.rootPath, fs); + } +} + +/** + * Add supporting configuration to the target folder. + * + * @param config writer configuration + * @param fs reference to a mem-fs editor + */ +export function addSupportingConfig(config: MTABaseConfig, fs: Editor): void { + addRootPackage(config, fs); + addGitIgnore(config.mtaPath, fs); + addXSSecurityConfig(config, fs); +} + +/** + * Add standalone approuter to the target folder. + * + * @param cfConfig writer configuration + * @param mtaInstance MTA configuration instance + * @param fs reference to a mem-fs editor + */ +async function addStandaloneRouter(cfConfig: CFBaseConfig, mtaInstance: MtaConfig, fs: Editor): Promise { + await mtaInstance.addStandaloneRouter(true); + if (cfConfig.addConnectivityService) { + await mtaInstance.addConnectivityResource(); + } + const { abapServiceName, abapService } = cfConfig.abapServiceProvider ?? {}; + if (abapServiceName && abapService) { + await mtaInstance.addAbapService(abapServiceName, abapService); + } + + fs.copyTpl(getTemplatePath(`router/package.json`), join(cfConfig.mtaPath, `${RouterModule}/${FileName.Package}`)); + + if (abapServiceName) { + let serviceKey; + try { + const instanceCredentials = await apiGetInstanceCredentials(abapServiceName); + serviceKey = instanceCredentials?.credentials; + } catch { + LoggerHelper.logger?.error(t('error.serviceKeyFailed')); + } + const endpoints = serviceKey?.endpoints ? Object.keys(serviceKey.endpoints) : ['']; + const service = serviceKey ? serviceKey['sap.cloud.service'] : ''; + fs.copyTpl( + getTemplatePath('router/xs-app-abapservice.json'), + join(cfConfig.mtaPath, `${RouterModule}/${XSAppFile}`), + { servicekeyService: service, servicekeyEndpoint: endpoints[0] } + ); + } else { + fs.copyTpl( + getTemplatePath('router/xs-app-server.json'), + join(cfConfig.mtaPath, `${RouterModule}/${XSAppFile}`) + ); + } +} + +/** + * Add standalone or managed approuter to the target folder. + * + * @param config writer configuration + * @param fs reference to a mem-fs editor + */ +export async function addRoutingConfig(config: CFBaseConfig, fs: Editor): Promise { + const mtaConfigInstance = await MtaConfig.newInstance(config.mtaPath); + if (config.routerType === RouterModuleType.Standard) { + await addStandaloneRouter(config, mtaConfigInstance, fs); + } else { + await mtaConfigInstance.addRoutingModules({ isManagedApp: true, addMissingModules: false }); + } + await addMtaDeployParameters(mtaConfigInstance); + await mtaConfigInstance.save(); +} + +/** + * Update the writer configuration with defaults. + * + * @param config writer configuration + */ +export function setMtaDefaults(config: CFBaseConfig): void { + config.mtaPath = config.mtaPath.replace(/\/$/, ''); + config.addConnectivityService ||= false; + config.mtaId = toMtaModuleName(config.mtaId); +} diff --git a/packages/cf-deploy-config-writer/test/sample/capcds/.gitignore b/packages/cf-deploy-config-writer/test/sample/capcds/.gitignore new file mode 100644 index 0000000000..1f6d632351 --- /dev/null +++ b/packages/cf-deploy-config-writer/test/sample/capcds/.gitignore @@ -0,0 +1,34 @@ +# CAP captestproject +_out +*.db +*.sqlite +connection.properties +default-*.json +.cdsrc-private.json +gen/ +node_modules/ +target/ + +# Web IDE, App Studio +.che/ +.gen/ + +# MTA +*_mta_build_tmp +*.mtar +mta_archives/ + +# Other +.DS_Store +*.orig +*.log + +*.iml +*.flattened-pom.xml + +# IDEs +# .vscode +# .idea + +# @cap-js/cds-typer +@cds-models diff --git a/packages/cf-deploy-config-writer/test/sample/capcds/package.json b/packages/cf-deploy-config-writer/test/sample/capcds/package.json new file mode 100644 index 0000000000..bcdb9ea088 --- /dev/null +++ b/packages/cf-deploy-config-writer/test/sample/capcds/package.json @@ -0,0 +1,29 @@ +{ + "name": "captestproject", + "version": "1.0.0", + "description": "A simple CAP project.", + "repository": "", + "license": "UNLICENSED", + "private": true, + "dependencies": { + "@sap/cds": "^8", + "express": "^4", + "@sap/xssec": "^4" + }, + "devDependencies": { + "@cap-js/cds-types": "^0.8.0", + "@cap-js/sqlite": "^1", + "@sap/cds-dk": "^8" + }, + "scripts": { + "start": "cds-serve" + }, + "cds": { + "requires": { + "auth": "xsuaa", + "connectivity": true, + "destinations": true, + "html5-repo": true + } + } +} diff --git a/packages/cf-deploy-config-writer/test/sample/capcds/xs-security.json b/packages/cf-deploy-config-writer/test/sample/capcds/xs-security.json new file mode 100644 index 0000000000..e1d3992300 --- /dev/null +++ b/packages/cf-deploy-config-writer/test/sample/capcds/xs-security.json @@ -0,0 +1,6 @@ +{ + "scopes": [], + "attributes": [], + "role-templates": [], + "authorities-inheritance": false +} diff --git a/packages/cf-deploy-config-writer/test/sample/standalone/.gitignore b/packages/cf-deploy-config-writer/test/sample/standalone/.gitignore new file mode 100644 index 0000000000..647906e4ca --- /dev/null +++ b/packages/cf-deploy-config-writer/test/sample/standalone/.gitignore @@ -0,0 +1,10 @@ +node_modules/ +dist/ +.scp/ +.env +Makefile*.mta +mta_archives +mta-* +resources +archive.zip +.*_mta_build_tmp \ No newline at end of file diff --git a/packages/cf-deploy-config-writer/test/sample/standalone/mta.yaml b/packages/cf-deploy-config-writer/test/sample/standalone/mta.yaml new file mode 100644 index 0000000000..c993a68f40 --- /dev/null +++ b/packages/cf-deploy-config-writer/test/sample/standalone/mta.yaml @@ -0,0 +1,60 @@ +_schema-version: "3.2" +ID: standalone +version: 0.0.1 +modules: +- name: standalone-router + type: approuter.nodejs + path: router + requires: + - name: standalone-html5-repo-runtime + - name: standalone-uaa + - name: standalone-destination-service + group: destinations + properties: + forwardAuthToken: false + name: ui5 + url: https://ui5.sap.com + - name: standalone-connectivity + parameters: + disk-quota: 256M + memory: 256M +resources: +- name: standalone-uaa + type: org.cloudfoundry.managed-service + parameters: + config: + tenant-mode: dedicated + xsappname: standalone-${space-guid} + service: xsuaa + service-plan: application +- name: standalone-html5-repo-runtime + type: org.cloudfoundry.managed-service + parameters: + service: html5-apps-repo + service-plan: app-runtime +- name: standalone-destination-service + type: org.cloudfoundry.managed-service + parameters: + config: + HTML5Runtime_enabled: false + init_data: + instance: + destinations: + - Authentication: NoAuthentication + Name: ui5 + ProxyType: Internet + Type: HTTP + URL: https://ui5.sap.com + existing_destinations_policy: update + version: 1.0.0 + service: destination + service-name: standalone-destination-service + service-plan: lite +- name: standalone-connectivity + type: org.cloudfoundry.managed-service + parameters: + service: connectivity + service-plan: lite +parameters: + deploy_mode: html5-repo + enable-parallel-deployments: true diff --git a/packages/cf-deploy-config-writer/test/sample/standalone/package.json b/packages/cf-deploy-config-writer/test/sample/standalone/package.json new file mode 100644 index 0000000000..c459a59e41 --- /dev/null +++ b/packages/cf-deploy-config-writer/test/sample/standalone/package.json @@ -0,0 +1,15 @@ +{ + "name": "mta-project", + "version": "0.0.1", + "description": "Build and deployment scripts", + "scripts": { + "clean": "rimraf resources mta_archives mta-op*", + "build": "rimraf resources mta_archives && mbt build --mtar archive", + "deploy": "cf deploy mta_archives/archive.mtar --retries 1", + "undeploy": "cf undeploy standalone --delete-services --delete-service-keys --delete-service-brokers" + }, + "devDependencies": { + "mbt": "^1.2.29", + "rimraf": "^5.0.5" + } +} diff --git a/packages/cf-deploy-config-writer/test/sample/standalone/router/package.json b/packages/cf-deploy-config-writer/test/sample/standalone/router/package.json new file mode 100644 index 0000000000..50f3e8353a --- /dev/null +++ b/packages/cf-deploy-config-writer/test/sample/standalone/router/package.json @@ -0,0 +1,18 @@ +{ + "name": "app-router", + "private": true, + "description": "App router", + "engines": { + "node": ">= 16.0.0" + }, + "scripts": { + "start": "node node_modules/@sap/approuter/approuter.js", + "start-local": "node node_modules/@sap/html5-repo-mock/index.js" + }, + "dependencies": { + "@sap/approuter": "^14" + }, + "devDependencies": { + "@sap/html5-repo-mock": "^2.1.0" + } +} diff --git a/packages/cf-deploy-config-writer/test/sample/standalone/router/xs-app.json b/packages/cf-deploy-config-writer/test/sample/standalone/router/xs-app.json new file mode 100644 index 0000000000..4c7a8957dc --- /dev/null +++ b/packages/cf-deploy-config-writer/test/sample/standalone/router/xs-app.json @@ -0,0 +1,17 @@ +{ + "authenticationMethod": "route", + "routes": [ + { + "source": "^(?:/app|/app/.*)?/resources/(.*)$", + "target": "/resources/$1", + "authenticationType": "none", + "destination": "ui5" + }, + { + "source": "^(?:/app|/app/.*)?/test-resources/(.*)$", + "target": "/test-resources/$1", + "authenticationType": "none", + "destination": "ui5" + } + ] +} diff --git a/packages/cf-deploy-config-writer/test/sample/standalone/xs-security.json b/packages/cf-deploy-config-writer/test/sample/standalone/xs-security.json new file mode 100644 index 0000000000..c31481ff7b --- /dev/null +++ b/packages/cf-deploy-config-writer/test/sample/standalone/xs-security.json @@ -0,0 +1,7 @@ +{ + "xsappname": "standalone", + "tenant-mode": "dedicated", + "description": "Security profile of called application", + "scopes": [], + "role-templates": [] +} diff --git a/packages/cf-deploy-config-writer/test/sample/standalonewithapp/.gitignore b/packages/cf-deploy-config-writer/test/sample/standalonewithapp/.gitignore new file mode 100644 index 0000000000..647906e4ca --- /dev/null +++ b/packages/cf-deploy-config-writer/test/sample/standalonewithapp/.gitignore @@ -0,0 +1,10 @@ +node_modules/ +dist/ +.scp/ +.env +Makefile*.mta +mta_archives +mta-* +resources +archive.zip +.*_mta_build_tmp \ No newline at end of file diff --git a/packages/cf-deploy-config-writer/test/sample/standalonewithapp/mta.yaml b/packages/cf-deploy-config-writer/test/sample/standalonewithapp/mta.yaml new file mode 100644 index 0000000000..c993a68f40 --- /dev/null +++ b/packages/cf-deploy-config-writer/test/sample/standalonewithapp/mta.yaml @@ -0,0 +1,60 @@ +_schema-version: "3.2" +ID: standalone +version: 0.0.1 +modules: +- name: standalone-router + type: approuter.nodejs + path: router + requires: + - name: standalone-html5-repo-runtime + - name: standalone-uaa + - name: standalone-destination-service + group: destinations + properties: + forwardAuthToken: false + name: ui5 + url: https://ui5.sap.com + - name: standalone-connectivity + parameters: + disk-quota: 256M + memory: 256M +resources: +- name: standalone-uaa + type: org.cloudfoundry.managed-service + parameters: + config: + tenant-mode: dedicated + xsappname: standalone-${space-guid} + service: xsuaa + service-plan: application +- name: standalone-html5-repo-runtime + type: org.cloudfoundry.managed-service + parameters: + service: html5-apps-repo + service-plan: app-runtime +- name: standalone-destination-service + type: org.cloudfoundry.managed-service + parameters: + config: + HTML5Runtime_enabled: false + init_data: + instance: + destinations: + - Authentication: NoAuthentication + Name: ui5 + ProxyType: Internet + Type: HTTP + URL: https://ui5.sap.com + existing_destinations_policy: update + version: 1.0.0 + service: destination + service-name: standalone-destination-service + service-plan: lite +- name: standalone-connectivity + type: org.cloudfoundry.managed-service + parameters: + service: connectivity + service-plan: lite +parameters: + deploy_mode: html5-repo + enable-parallel-deployments: true diff --git a/packages/cf-deploy-config-writer/test/sample/standalonewithapp/myapp/package.json b/packages/cf-deploy-config-writer/test/sample/standalonewithapp/myapp/package.json new file mode 100644 index 0000000000..0a21b9650f --- /dev/null +++ b/packages/cf-deploy-config-writer/test/sample/standalonewithapp/myapp/package.json @@ -0,0 +1,28 @@ +{ + "name": "myapp", + "version": "0.0.1", + "description": "An SAP Fiori application.", + "keywords": [ + "ui5", + "openui5", + "sapui5" + ], + "main": "webapp/index.html", + "dependencies": {}, + "devDependencies": { + "@ui5/cli": "^3.0.0", + "@sap/ux-ui5-tooling": "1" + }, + "scripts": { + "start": "fiori run --open \"test/flpSandbox.html?sap-ui-xx-viewCache=false#project8-display\"", + "start-local": "fiori run --config ./ui5-local.yaml --open \"test/flpSandbox.html?sap-ui-xx-viewCache=false#project8-display\"", + "build": "ui5 build --config=ui5.yaml --clean-dest --dest dist", + "deploy": "fiori verify", + "deploy-config": "fiori add deploy-config", + "start-noflp": "fiori run --open \"index.html?sap-ui-xx-viewCache=false\"", + "start-variants-management": "fiori run --open \"preview.html?sap-ui-xx-viewCache=false&fiori-tools-rta-mode=true&sap-ui-rta-skip-flex-validation=true#preview-app\"", + "unit-tests": "fiori run --open 'test/unit/unitTests.qunit.html'", + "int-tests": "fiori run --open 'test/integration/opaTests.qunit.html'" + }, + "sapuxLayer": "VENDOR" +} diff --git a/packages/cf-deploy-config-writer/test/sample/standalonewithapp/myapp/ui5.yaml b/packages/cf-deploy-config-writer/test/sample/standalonewithapp/myapp/ui5.yaml new file mode 100644 index 0000000000..199b61ba08 --- /dev/null +++ b/packages/cf-deploy-config-writer/test/sample/standalonewithapp/myapp/ui5.yaml @@ -0,0 +1,28 @@ +# yaml-language-server: $schema=https://sap.github.io/ui5-tooling/schema/ui5.yaml.json + +specVersion: "3.1" +metadata: + name: myapp +type: application +server: + customMiddleware: + - name: fiori-tools-proxy + afterMiddleware: compression + configuration: + ignoreCertError: false # If set to true, certificate errors will be ignored. E.g. self-signed certificates will be accepted + ui5: + path: + - /resources + - /test-resources + url: https://ui5.sap.com + - name: fiori-tools-appreload + afterMiddleware: compression + configuration: + port: 35729 + path: webapp + delay: 300 + - name: fiori-tools-preview + afterMiddleware: fiori-tools-appreload + configuration: + component: myapp + ui5Theme: sap_horizon diff --git a/packages/cf-deploy-config-writer/test/sample/standalonewithapp/myapp/webapp/manifest.json b/packages/cf-deploy-config-writer/test/sample/standalonewithapp/myapp/webapp/manifest.json new file mode 100644 index 0000000000..ad87bc26a5 --- /dev/null +++ b/packages/cf-deploy-config-writer/test/sample/standalonewithapp/myapp/webapp/manifest.json @@ -0,0 +1,97 @@ +{ + "_version": "1.65.0", + "sap.app": { + "id": "myapp", + "type": "application", + "i18n": "i18n/i18n.properties", + "applicationVersion": { + "version": "0.0.1" + }, + "title": "{{appTitle}}", + "description": "{{appDescription}}", + "resources": "resources.json", + "sourceTemplate": { + "id": "@sap/generator-fiori:basic", + "version": "1.16.3-pre-20250120124504-86cdda28f.0", + "toolsId": "0d780c67-3898-4e0f-aab3-44c95943a533" + } + }, + "sap.ui": { + "technology": "UI5", + "icons": { + "icon": "", + "favIcon": "", + "phone": "", + "phone@2": "", + "tablet": "", + "tablet@2": "" + }, + "deviceTypes": { + "desktop": true, + "tablet": true, + "phone": true + } + }, + "sap.ui5": { + "flexEnabled": true, + "dependencies": { + "minUI5Version": "1.132.0", + "libs": { + "sap.m": {}, + "sap.ui.core": {} + } + }, + "contentDensities": { + "compact": true, + "cozy": true + }, + "models": { + "i18n": { + "type": "sap.ui.model.resource.ResourceModel", + "settings": { + "bundleName": "myapp.i18n.i18n" + } + } + }, + "resources": { + "css": [ + { + "uri": "css/style.css" + } + ] + }, + "routing": { + "config": { + "routerClass": "sap.m.routing.Router", + "controlAggregation": "pages", + "controlId": "app", + "transition": "slide", + "type": "View", + "viewType": "XML", + "path": "myapp.view", + "async": true, + "viewPath": "myapp.view" + }, + "routes": [ + { + "name": "RouteView1", + "pattern": ":?query:", + "target": [ + "TargetView1" + ] + } + ], + "targets": { + "TargetView1": { + "id": "View1", + "name": "View1" + } + } + }, + "rootView": { + "viewName": "myapp.view.App", + "type": "XML", + "id": "App" + } + } +} \ No newline at end of file diff --git a/packages/cf-deploy-config-writer/test/sample/standalonewithapp/package.json b/packages/cf-deploy-config-writer/test/sample/standalonewithapp/package.json new file mode 100644 index 0000000000..c459a59e41 --- /dev/null +++ b/packages/cf-deploy-config-writer/test/sample/standalonewithapp/package.json @@ -0,0 +1,15 @@ +{ + "name": "mta-project", + "version": "0.0.1", + "description": "Build and deployment scripts", + "scripts": { + "clean": "rimraf resources mta_archives mta-op*", + "build": "rimraf resources mta_archives && mbt build --mtar archive", + "deploy": "cf deploy mta_archives/archive.mtar --retries 1", + "undeploy": "cf undeploy standalone --delete-services --delete-service-keys --delete-service-brokers" + }, + "devDependencies": { + "mbt": "^1.2.29", + "rimraf": "^5.0.5" + } +} diff --git a/packages/cf-deploy-config-writer/test/sample/standalonewithapp/router/package.json b/packages/cf-deploy-config-writer/test/sample/standalonewithapp/router/package.json new file mode 100644 index 0000000000..50f3e8353a --- /dev/null +++ b/packages/cf-deploy-config-writer/test/sample/standalonewithapp/router/package.json @@ -0,0 +1,18 @@ +{ + "name": "app-router", + "private": true, + "description": "App router", + "engines": { + "node": ">= 16.0.0" + }, + "scripts": { + "start": "node node_modules/@sap/approuter/approuter.js", + "start-local": "node node_modules/@sap/html5-repo-mock/index.js" + }, + "dependencies": { + "@sap/approuter": "^14" + }, + "devDependencies": { + "@sap/html5-repo-mock": "^2.1.0" + } +} diff --git a/packages/cf-deploy-config-writer/test/sample/standalonewithapp/router/xs-app.json b/packages/cf-deploy-config-writer/test/sample/standalonewithapp/router/xs-app.json new file mode 100644 index 0000000000..4c7a8957dc --- /dev/null +++ b/packages/cf-deploy-config-writer/test/sample/standalonewithapp/router/xs-app.json @@ -0,0 +1,17 @@ +{ + "authenticationMethod": "route", + "routes": [ + { + "source": "^(?:/app|/app/.*)?/resources/(.*)$", + "target": "/resources/$1", + "authenticationType": "none", + "destination": "ui5" + }, + { + "source": "^(?:/app|/app/.*)?/test-resources/(.*)$", + "target": "/test-resources/$1", + "authenticationType": "none", + "destination": "ui5" + } + ] +} diff --git a/packages/cf-deploy-config-writer/test/sample/standalonewithapp/xs-security.json b/packages/cf-deploy-config-writer/test/sample/standalonewithapp/xs-security.json new file mode 100644 index 0000000000..c31481ff7b --- /dev/null +++ b/packages/cf-deploy-config-writer/test/sample/standalonewithapp/xs-security.json @@ -0,0 +1,7 @@ +{ + "xsappname": "standalone", + "tenant-mode": "dedicated", + "description": "Security profile of called application", + "scopes": [], + "role-templates": [] +} diff --git a/packages/cf-deploy-config-writer/test/unit/__snapshots__/index-app.test.ts.snap b/packages/cf-deploy-config-writer/test/unit/__snapshots__/index-app.test.ts.snap index 4168a0abdb..f10b2938a7 100644 --- a/packages/cf-deploy-config-writer/test/unit/__snapshots__/index-app.test.ts.snap +++ b/packages/cf-deploy-config-writer/test/unit/__snapshots__/index-app.test.ts.snap @@ -248,100 +248,100 @@ builder: `; exports[`CF Writer App Generate deployment configs - HTML5 App and destination read from ui5.yaml 2`] = ` -"_schema-version: \\"3.2\\" +"_schema-version: '3.2' ID: basicapp description: Generated by Fiori Tools version: 0.0.1 +parameters: + enable-parallel-deployments: true + deploy_mode: html5-repo modules: -- name: basicapp-destination-content - type: com.sap.application.content - requires: - - name: basicapp-destination-service + - name: basicapp-destination-content + type: com.sap.application.content + requires: + - name: basicapp-destination-service + parameters: + content-target: true + - name: basicapp-repo-host + parameters: + service-key: + name: basicapp-repo-host-key + - name: basicapp-uaa + parameters: + service-key: + name: basicapp-uaa-key parameters: - content-target: true - - name: basicapp-repo-host + content: + instance: + destinations: + - Name: basicapp_html_repo_host + ServiceInstanceName: basicapp-html5-service + ServiceKeyName: basicapp-repo-host-key + sap.cloud.service: basicapp + - Authentication: OAuth2UserTokenExchange + Name: basicapp_uaa + ServiceInstanceName: basicapp-xsuaa-service + ServiceKeyName: basicapp-uaa-key + sap.cloud.service: basicapp + existing_destinations_policy: update + build-parameters: + no-source: true + - name: basicapp-app-content + type: com.sap.application.content + path: . + requires: + - name: basicapp-repo-host + parameters: + content-target: true + build-parameters: + build-result: resources + requires: + - name: basicapp + artifacts: + - basicapp.zip + target-path: resources/ + - name: basicapp + type: html5 + path: . + build-parameters: + builder: custom + build-result: dist + commands: + - npm install + - 'npm run build:cf' + supported-platforms: [] +resources: + - name: basicapp-destination-service + type: org.cloudfoundry.managed-service parameters: - service-key: - name: basicapp-repo-host-key + service: destination + service-name: basicapp-destination-service + service-plan: lite + config: + HTML5Runtime_enabled: true + version: 1.0.0 + init_data: + instance: + existing_destinations_policy: update + destinations: + - Name: ui5 + Type: HTTP + URL: 'https://ui5.sap.com' + ProxyType: Internet + Authentication: NoAuthentication - name: basicapp-uaa + type: org.cloudfoundry.managed-service parameters: - service-key: - name: basicapp-uaa-key - parameters: - content: - instance: - destinations: - - Name: basicapp_html_repo_host - ServiceInstanceName: basicapp-html5-service - ServiceKeyName: basicapp-repo-host-key - sap.cloud.service: basicapp - - Authentication: OAuth2UserTokenExchange - Name: basicapp_uaa - ServiceInstanceName: basicapp-xsuaa-service - ServiceKeyName: basicapp-uaa-key - sap.cloud.service: basicapp - existing_destinations_policy: update - build-parameters: - no-source: true -- name: basicapp-app-content - type: com.sap.application.content - path: . - requires: + path: ./xs-security.json + service: xsuaa + service-name: basicapp-xsuaa-service + service-plan: application - name: basicapp-repo-host + type: org.cloudfoundry.managed-service parameters: - content-target: true - build-parameters: - build-result: resources - requires: - - artifacts: - - basicapp.zip - name: basicapp - target-path: resources/ -- name: basicapp - type: html5 - path: . - build-parameters: - build-result: dist - builder: custom - commands: - - npm install - - npm run build:cf - supported-platforms: [] -resources: -- name: basicapp-destination-service - type: org.cloudfoundry.managed-service - parameters: - config: - HTML5Runtime_enabled: true - init_data: - instance: - destinations: - - Authentication: NoAuthentication - Name: ui5 - ProxyType: Internet - Type: HTTP - URL: https://ui5.sap.com - existing_destinations_policy: update - version: 1.0.0 - service: destination - service-name: basicapp-destination-service - service-plan: lite -- name: basicapp-uaa - type: org.cloudfoundry.managed-service - parameters: - path: ./xs-security.json - service: xsuaa - service-name: basicapp-xsuaa-service - service-plan: application -- name: basicapp-repo-host - type: org.cloudfoundry.managed-service - parameters: - service: html5-apps-repo - service-name: basicapp-html5-service - service-plan: app-host -parameters: - deploy_mode: html5-repo - enable-parallel-deployments: true + service-name: basicapp-html5-service + service-plan: app-host + service: html5-apps-repo " `; @@ -645,97 +645,97 @@ builder: `; exports[`CF Writer App Generate deployment configs - HTML5 App with managed approuter attached to a multi target application 2`] = ` -"_schema-version: \\"3.1\\" +"_schema-version: '3.1' ID: multiproject description: Fiori elements app version: 0.0.1 modules: -- name: multiproject-destination-content - type: com.sap.application.content - requires: - - name: multiproject-destination-service + - name: multiproject-destination-content + type: com.sap.application.content + requires: + - name: multiproject-destination-service + parameters: + content-target: true + - name: multiproject-repo-host + parameters: + service-key: + name: multiproject-repo-host-key + - name: multiproject-uaa + parameters: + service-key: + name: multiproject-uaa-key parameters: - content-target: true - - name: multiproject-repo-host + content: + instance: + destinations: + - Name: multiproject_html_repo_host + ServiceInstanceName: multiproject-html5-service + ServiceKeyName: multiproject-repo-host-key + sap.cloud.service: multiproject + - Authentication: OAuth2UserTokenExchange + Name: multiproject_uaa + ServiceInstanceName: multiproject-xsuaa-service + ServiceKeyName: multiproject-uaa-key + sap.cloud.service: multiproject + existing_destinations_policy: update + build-parameters: + no-source: true + - name: multiproject-app-content + type: com.sap.application.content + path: . + requires: + - name: multiproject-repo-host + parameters: + content-target: true + build-parameters: + build-result: resources + requires: + - name: comfioritoolslrop + artifacts: + - comfioritoolslrop.zip + target-path: resources/ + - name: comfioritoolslrop + type: html5 + path: . + build-parameters: + builder: custom + build-result: dist + commands: + - npm install + - 'npm run build:cf' + supported-platforms: [] +resources: + - name: multiproject-destination-service + type: org.cloudfoundry.managed-service parameters: - service-key: - name: multiproject-repo-host-key + service: destination + service-name: multiproject-destination-service + service-plan: lite + config: + HTML5Runtime_enabled: true + version: 1.0.0 + init_data: + instance: + existing_destinations_policy: update + destinations: + - Name: ui5 + Type: HTTP + URL: 'https://ui5.sap.com' + ProxyType: Internet + Authentication: NoAuthentication - name: multiproject-uaa + type: org.cloudfoundry.managed-service parameters: - service-key: - name: multiproject-uaa-key - parameters: - content: - instance: - destinations: - - Name: multiproject_html_repo_host - ServiceInstanceName: multiproject-html5-service - ServiceKeyName: multiproject-repo-host-key - sap.cloud.service: multiproject - - Authentication: OAuth2UserTokenExchange - Name: multiproject_uaa - ServiceInstanceName: multiproject-xsuaa-service - ServiceKeyName: multiproject-uaa-key - sap.cloud.service: multiproject - existing_destinations_policy: update - build-parameters: - no-source: true -- name: multiproject-app-content - type: com.sap.application.content - path: . - requires: + path: ./xs-security.json + service: xsuaa + service-name: multiproject-xsuaa-service + service-plan: application - name: multiproject-repo-host + type: org.cloudfoundry.managed-service parameters: - content-target: true - build-parameters: - build-result: resources - requires: - - artifacts: - - comfioritoolslrop.zip - name: comfioritoolslrop - target-path: resources/ -- name: comfioritoolslrop - type: html5 - path: . - build-parameters: - build-result: dist - builder: custom - commands: - - npm install - - npm run build:cf - supported-platforms: [] -resources: -- name: multiproject-destination-service - type: org.cloudfoundry.managed-service - parameters: - config: - HTML5Runtime_enabled: true - init_data: - instance: - destinations: - - Authentication: NoAuthentication - Name: ui5 - ProxyType: Internet - Type: HTTP - URL: https://ui5.sap.com - existing_destinations_policy: update - version: 1.0.0 - service: destination - service-name: multiproject-destination-service - service-plan: lite -- name: multiproject-uaa - type: org.cloudfoundry.managed-service - parameters: - path: ./xs-security.json - service: xsuaa - service-name: multiproject-xsuaa-service - service-plan: application -- name: multiproject-repo-host - type: org.cloudfoundry.managed-service - parameters: - service: html5-apps-repo - service-name: multiproject-html5-service - service-plan: app-host + service-name: multiproject-html5-service + service-plan: app-host + service: html5-apps-repo parameters: deploy_mode: html5-repo enable-parallel-deployments: true @@ -1042,99 +1042,312 @@ builder: `; exports[`CF Writer App Generate deployment configs - HTML5 App with managed approuter attached with no destination available 2`] = ` -"_schema-version: \\"3.2\\" +"_schema-version: '3.2' ID: comfioritoolslrop description: Generated by Fiori Tools version: 0.0.1 +parameters: + enable-parallel-deployments: true + deploy_mode: html5-repo modules: -- name: comfioritoolslrop-destination-content - type: com.sap.application.content - requires: - - name: comfioritoolslrop-destination-service + - name: comfioritoolslrop-destination-content + type: com.sap.application.content + requires: + - name: comfioritoolslrop-destination-service + parameters: + content-target: true + - name: comfioritoolslrop-repo-host + parameters: + service-key: + name: comfioritoolslrop-repo-host-key + - name: comfioritoolslrop-uaa + parameters: + service-key: + name: comfioritoolslrop-uaa-key parameters: - content-target: true - - name: comfioritoolslrop-repo-host + content: + instance: + destinations: + - Name: comfioritoolslrop_html_repo_host + ServiceInstanceName: comfioritoolslrop-html5-service + ServiceKeyName: comfioritoolslrop-repo-host-key + sap.cloud.service: comfioritoolslrop + - Authentication: OAuth2UserTokenExchange + Name: comfioritoolslrop_uaa + ServiceInstanceName: comfioritoolslrop-xsuaa-service + ServiceKeyName: comfioritoolslrop-uaa-key + sap.cloud.service: comfioritoolslrop + existing_destinations_policy: update + build-parameters: + no-source: true + - name: comfioritoolslrop-app-content + type: com.sap.application.content + path: . + requires: + - name: comfioritoolslrop-repo-host + parameters: + content-target: true + build-parameters: + build-result: resources + requires: + - name: comfioritoolslrop + artifacts: + - comfioritoolslrop.zip + target-path: resources/ + - name: comfioritoolslrop + type: html5 + path: . + build-parameters: + builder: custom + build-result: dist + commands: + - npm install + - 'npm run build:cf' + supported-platforms: [] +resources: + - name: comfioritoolslrop-destination-service + type: org.cloudfoundry.managed-service parameters: - service-key: - name: comfioritoolslrop-repo-host-key + service: destination + service-name: comfioritoolslrop-destination-service + service-plan: lite + config: + HTML5Runtime_enabled: true + version: 1.0.0 + init_data: + instance: + existing_destinations_policy: update + destinations: + - Name: ui5 + Type: HTTP + URL: 'https://ui5.sap.com' + ProxyType: Internet + Authentication: NoAuthentication - name: comfioritoolslrop-uaa + type: org.cloudfoundry.managed-service parameters: - service-key: - name: comfioritoolslrop-uaa-key - parameters: - content: - instance: - destinations: - - Name: comfioritoolslrop_html_repo_host - ServiceInstanceName: comfioritoolslrop-html5-service - ServiceKeyName: comfioritoolslrop-repo-host-key - sap.cloud.service: comfioritoolslrop - - Authentication: OAuth2UserTokenExchange - Name: comfioritoolslrop_uaa - ServiceInstanceName: comfioritoolslrop-xsuaa-service - ServiceKeyName: comfioritoolslrop-uaa-key - sap.cloud.service: comfioritoolslrop - existing_destinations_policy: update - build-parameters: - no-source: true -- name: comfioritoolslrop-app-content - type: com.sap.application.content - path: . - requires: + path: ./xs-security.json + service: xsuaa + service-name: comfioritoolslrop-xsuaa-service + service-plan: application - name: comfioritoolslrop-repo-host + type: org.cloudfoundry.managed-service parameters: - content-target: true - build-parameters: - build-result: resources + service-name: comfioritoolslrop-html5-service + service-plan: app-host + service: html5-apps-repo +" +`; + +exports[`CF Writer App Generate deployment configs - generateSupportingConfig read mtaId read from file 1`] = ` +"{ + \\"name\\": \\"mta-project\\", + \\"version\\": \\"0.0.1\\", + \\"description\\": \\"Build and deployment scripts\\", + \\"scripts\\": { + \\"clean\\": \\"rimraf resources mta_archives mta-op*\\", + \\"build\\": \\"rimraf resources mta_archives && mbt build --mtar archive\\", + \\"deploy\\": \\"cf deploy mta_archives/archive.mtar --retries 1\\", + \\"undeploy\\": \\"cf undeploy captestproject --delete-services --delete-service-keys --delete-service-brokers\\" + }, + \\"devDependencies\\": { + \\"mbt\\": \\"^1.2.29\\", + \\"rimraf\\": \\"^5.0.5\\" + } +} +" +`; + +exports[`CF Writer App Generate deployment configs - generateSupportingConfig read mtaId read from file 2`] = ` +"node_modules/ +dist/ +.scp/ +.env +Makefile*.mta +mta_archives +mta-* +resources +archive.zip +.*_mta_build_tmp" +`; + +exports[`CF Writer App Generate deployment configs - generateSupportingConfig read mtaId read from file 3`] = ` +"{ + \\"xsappname\\": \\"captestproject\\", + \\"tenant-mode\\": \\"dedicated\\", + \\"description\\": \\"Security profile of called application\\", + \\"scopes\\": [], + \\"role-templates\\": [] +} +" +`; + +exports[`CF Writer App Generate deployment configs - generateSupportingConfig with mtaId passed in 1`] = ` +"{ + \\"name\\": \\"mta-project\\", + \\"version\\": \\"0.0.1\\", + \\"description\\": \\"Build and deployment scripts\\", + \\"scripts\\": { + \\"clean\\": \\"rimraf resources mta_archives mta-op*\\", + \\"build\\": \\"rimraf resources mta_archives && mbt build --mtar archive\\", + \\"deploy\\": \\"cf deploy mta_archives/archive.mtar --retries 1\\", + \\"undeploy\\": \\"cf undeploy testMtaId --delete-services --delete-service-keys --delete-service-brokers\\" + }, + \\"devDependencies\\": { + \\"mbt\\": \\"^1.2.29\\", + \\"rimraf\\": \\"^5.0.5\\" + } +} +" +`; + +exports[`CF Writer App Generate deployment configs - generateSupportingConfig with mtaId passed in 2`] = ` +"node_modules/ +dist/ +.scp/ +.env +Makefile*.mta +mta_archives +mta-* +resources +archive.zip +.*_mta_build_tmp" +`; + +exports[`CF Writer App Generate deployment configs - standalone approuter cleanup 1`] = ` +"_schema-version: '3.2' +ID: standalone +version: 0.0.1 +modules: + - name: standalone-router + type: approuter.nodejs + path: router + requires: + - name: standalone-html5-repo-runtime + - name: standalone-uaa + - name: standalone-destination-service + group: destinations + properties: + forwardAuthToken: false + name: ui5 + url: 'https://ui5.sap.com' + - name: standalone-connectivity + parameters: + disk-quota: 256M + memory: 256M + - name: standalone-app-content + type: com.sap.application.content + path: . requires: - - artifacts: - - comfioritoolslrop.zip - name: comfioritoolslrop - target-path: resources/ -- name: comfioritoolslrop - type: html5 - path: . - build-parameters: - build-result: dist - builder: custom - commands: - - npm install - - npm run build:cf - supported-platforms: [] + - name: standalone-repo-host + parameters: + content-target: true + build-parameters: + build-result: resources + requires: + - name: myapp + artifacts: + - myapp.zip + target-path: resources/ + - name: myapp + type: html5 + path: myapp + build-parameters: + builder: custom + build-result: dist + commands: + - npm install + - 'npm run build:cf' + supported-platforms: [] resources: -- name: comfioritoolslrop-destination-service - type: org.cloudfoundry.managed-service - parameters: - config: - HTML5Runtime_enabled: true - init_data: - instance: - destinations: - - Authentication: NoAuthentication - Name: ui5 - ProxyType: Internet - Type: HTTP - URL: https://ui5.sap.com - existing_destinations_policy: update - version: 1.0.0 - service: destination - service-name: comfioritoolslrop-destination-service - service-plan: lite -- name: comfioritoolslrop-uaa - type: org.cloudfoundry.managed-service - parameters: - path: ./xs-security.json - service: xsuaa - service-name: comfioritoolslrop-xsuaa-service - service-plan: application -- name: comfioritoolslrop-repo-host - type: org.cloudfoundry.managed-service - parameters: - service: html5-apps-repo - service-name: comfioritoolslrop-html5-service - service-plan: app-host + - name: standalone-uaa + type: org.cloudfoundry.managed-service + parameters: + config: + tenant-mode: dedicated + xsappname: 'standalone-\${space-guid}' + service: xsuaa + service-plan: application + - name: standalone-html5-repo-runtime + type: org.cloudfoundry.managed-service + parameters: + service: html5-apps-repo + service-plan: app-runtime + - name: standalone-destination-service + type: org.cloudfoundry.managed-service + parameters: + config: + HTML5Runtime_enabled: false + init_data: + instance: + destinations: + - Authentication: NoAuthentication + Name: ui5 + ProxyType: Internet + Type: HTTP + URL: 'https://ui5.sap.com' + existing_destinations_policy: update + version: 1.0.0 + service: destination + service-name: standalone-destination-service + service-plan: lite + - name: standalone-connectivity + type: org.cloudfoundry.managed-service + parameters: + service: connectivity + service-plan: lite + - name: standalone-repo-host + type: org.cloudfoundry.managed-service + parameters: + service-name: standalone-html5-service + service-plan: app-host + service: html5-apps-repo parameters: deploy_mode: html5-repo enable-parallel-deployments: true " `; + +exports[`CF Writer App Generate deployment configs - standalone approuter cleanup 2`] = ` +"{ + \\"name\\": \\"app-router\\", + \\"private\\": true, + \\"description\\": \\"App router\\", + \\"engines\\": { + \\"node\\": \\">= 16.0.0\\" + }, + \\"scripts\\": { + \\"start\\": \\"node node_modules/@sap/approuter/approuter.js\\", + \\"start-local\\": \\"node node_modules/@sap/html5-repo-mock/index.js\\" + }, + \\"dependencies\\": { + \\"@sap/approuter\\": \\"^14\\" + }, + \\"devDependencies\\": { + \\"@sap/html5-repo-mock\\": \\"^2.1.0\\" + } +} +" +`; + +exports[`CF Writer App Generate deployment configs - standalone approuter cleanup 3`] = ` +"{ + \\"authenticationMethod\\": \\"route\\", + \\"routes\\": [ + { + \\"source\\": \\"^(?:/app|/app/.*)?/resources/(.*)$\\", + \\"target\\": \\"/resources/$1\\", + \\"authenticationType\\": \\"none\\", + \\"destination\\": \\"ui5\\" + }, + { + \\"source\\": \\"^(?:/app|/app/.*)?/test-resources/(.*)$\\", + \\"target\\": \\"/test-resources/$1\\", + \\"authenticationType\\": \\"none\\", + \\"destination\\": \\"ui5\\" + } + ], + \\"welcomeFile\\": \\"/myapp\\" +} +" +`; diff --git a/packages/cf-deploy-config-writer/test/unit/__snapshots__/index-cap.test.ts.snap b/packages/cf-deploy-config-writer/test/unit/__snapshots__/index-cap.test.ts.snap new file mode 100644 index 0000000000..6c0a24ddfb --- /dev/null +++ b/packages/cf-deploy-config-writer/test/unit/__snapshots__/index-cap.test.ts.snap @@ -0,0 +1,306 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`CF Writer CAP Validate generation of CAP mta configurations managed 1`] = ` +"_schema-version: 3.3.0 +ID: captestproject +version: 1.0.0 +description: A simple CAP project. +parameters: + enable-parallel-deployments: true + deploy_mode: html5-repo +build-parameters: + before-all: + - builder: custom + commands: + - npm ci + - npx cds build --production +modules: + - name: captestproject-srv + type: nodejs + path: gen/srv + parameters: + buildpack: nodejs_buildpack + readiness-health-check-type: http + readiness-health-check-http-endpoint: /health + build-parameters: + builder: npm + provides: + - name: srv-api + properties: + srv-url: '\${default-url}' + requires: + - name: captestproject-db + - name: captestproject-auth + - name: captestproject-connectivity + - name: captestproject-destination + - name: captestproject-db-deployer + type: hdb + path: gen/db + parameters: + buildpack: nodejs_buildpack + requires: + - name: captestproject-db + - name: captestproject-app-deployer + type: com.sap.application.content + path: gen + requires: + - name: captestproject-html5-repo-host + parameters: + content-target: true + build-parameters: + build-result: app/ + requires: null + - name: captestproject-destination-content + type: com.sap.application.content + requires: + - name: captestproject-destination + parameters: + content-target: true + - name: captestproject-html5-repo-host + parameters: + service-key: + name: captestproject-html5-repo-host-key + - name: captestproject-auth + parameters: + service-key: + name: captestproject-auth-key + parameters: + content: + instance: + destinations: + - Name: captestproject_html_repo_host + ServiceInstanceName: captestproject-html5-service + ServiceKeyName: captestproject-html5-repo-host-key + sap.cloud.service: captestproject + - Authentication: OAuth2UserTokenExchange + Name: captestproject_uaa + ServiceInstanceName: captestproject-xsuaa-service + ServiceKeyName: captestproject-auth-key + sap.cloud.service: captestproject + existing_destinations_policy: update + build-parameters: + no-source: true +resources: + - name: captestproject-db + type: com.sap.xs.hdi-container + parameters: + service: hana + service-plan: hdi-shared + - name: captestproject-auth + type: org.cloudfoundry.managed-service + parameters: + service: xsuaa + service-plan: application + path: ./xs-security.json + config: + xsappname: 'captestproject-\${org}-\${space}' + tenant-mode: dedicated + service-name: captestproject-xsuaa-service + - name: captestproject-connectivity + type: org.cloudfoundry.managed-service + parameters: + service: connectivity + service-plan: lite + - name: captestproject-destination + type: org.cloudfoundry.managed-service + parameters: + service: destination + service-plan: lite + config: + HTML5Runtime_enabled: true + init_data: + instance: + existing_destinations_policy: update + destinations: + - Name: captestproject-srv-api + URL: '~{srv-api/srv-url}' + Authentication: NoAuthentication + Type: HTTP + ProxyType: Internet + HTML5.ForwardAuthToken: true + HTML5.DynamicDestination: true + - Name: ui5 + URL: 'https://ui5.sap.com' + Authentication: NoAuthentication + Type: HTTP + ProxyType: Internet + - name: captestproject-html5-repo-host + type: org.cloudfoundry.managed-service + parameters: + service: html5-apps-repo + service-plan: app-host + service-name: captestproject-html5-service +" +`; + +exports[`CF Writer CAP Validate generation of CAP mta configurations standard 1`] = ` +"_schema-version: 3.3.0 +ID: captestproject +version: 1.0.0 +description: A simple CAP project. +parameters: + enable-parallel-deployments: true + deploy_mode: html5-repo +build-parameters: + before-all: + - builder: custom + commands: + - npm ci + - npx cds build --production +modules: + - name: captestproject-srv + type: nodejs + path: gen/srv + parameters: + buildpack: nodejs_buildpack + readiness-health-check-type: http + readiness-health-check-http-endpoint: /health + build-parameters: + builder: npm + provides: + - name: srv-api + properties: + srv-url: '\${default-url}' + requires: + - name: captestproject-db + - name: captestproject-auth + - name: captestproject-connectivity + - name: captestproject-destination + - name: captestproject-db-deployer + type: hdb + path: gen/db + parameters: + buildpack: nodejs_buildpack + requires: + - name: captestproject-db + - name: captestproject-app-deployer + type: com.sap.application.content + path: gen + requires: + - name: captestproject-html5-repo-host + parameters: + content-target: true + build-parameters: + build-result: app/ + requires: null + - name: captestproject-router + type: approuter.nodejs + path: router + parameters: + disk-quota: 256M + memory: 256M + requires: + - name: captestproject-html5-repo-runtime + - name: captestproject-uaa + - name: captestproject-destination + group: destinations + properties: + name: ui5 + url: 'https://ui5.sap.com' + forwardAuthToken: false +resources: + - name: captestproject-db + type: com.sap.xs.hdi-container + parameters: + service: hana + service-plan: hdi-shared + - name: captestproject-auth + type: org.cloudfoundry.managed-service + parameters: + service: xsuaa + service-plan: application + path: ./xs-security.json + config: + xsappname: 'captestproject-\${org}-\${space}' + tenant-mode: dedicated + - name: captestproject-connectivity + type: org.cloudfoundry.managed-service + parameters: + service: connectivity + service-plan: lite + - name: captestproject-destination + type: org.cloudfoundry.managed-service + parameters: + service: destination + service-plan: lite + config: + HTML5Runtime_enabled: true + init_data: + instance: + existing_destinations_policy: update + destinations: + - Name: captestproject-srv-api + URL: '~{srv-api/srv-url}' + Authentication: NoAuthentication + Type: HTTP + ProxyType: Internet + HTML5.ForwardAuthToken: true + HTML5.DynamicDestination: true + - Name: ui5 + URL: 'https://ui5.sap.com' + Authentication: NoAuthentication + Type: HTTP + ProxyType: Internet + - name: captestproject-html5-repo-host + type: org.cloudfoundry.managed-service + parameters: + service: html5-apps-repo + service-plan: app-host + - name: captestproject-uaa + type: org.cloudfoundry.managed-service + parameters: + service-plan: application + service: xsuaa + config: + xsappname: 'captestproject-\${space-guid}' + tenant-mode: dedicated + - name: captestproject-html5-repo-runtime + type: org.cloudfoundry.managed-service + parameters: + service-plan: app-runtime + service: html5-apps-repo +" +`; + +exports[`CF Writer CAP Validate generation of CAP mta configurations standard 2`] = ` +"{ + \\"name\\": \\"app-router\\", + \\"private\\": true, + \\"description\\": \\"App router\\", + \\"engines\\": { + \\"node\\": \\">= 16.0.0\\" + }, + \\"scripts\\": { + \\"start\\": \\"node node_modules/@sap/approuter/approuter.js\\", + \\"start-local\\": \\"node node_modules/@sap/html5-repo-mock/index.js\\" + }, + \\"dependencies\\": { + \\"@sap/approuter\\": \\"^14\\" + }, + \\"devDependencies\\": { + \\"@sap/html5-repo-mock\\": \\"^2.1.0\\" + } +} +" +`; + +exports[`CF Writer CAP Validate generation of CAP mta configurations standard 3`] = ` +"{ + \\"authenticationMethod\\": \\"route\\", + \\"routes\\": [ + { + \\"source\\": \\"^(?:/app|/app/.*)?/resources/(.*)$\\", + \\"target\\": \\"/resources/$1\\", + \\"authenticationType\\": \\"none\\", + \\"destination\\": \\"ui5\\" + }, + { + \\"source\\": \\"^(?:/app|/app/.*)?/test-resources/(.*)$\\", + \\"target\\": \\"/test-resources/$1\\", + \\"authenticationType\\": \\"none\\", + \\"destination\\": \\"ui5\\" + } + ] +} +" +`; diff --git a/packages/cf-deploy-config-writer/test/unit/cap.test.ts b/packages/cf-deploy-config-writer/test/unit/cap.test.ts index 14612f7b3c..38548fe23a 100644 --- a/packages/cf-deploy-config-writer/test/unit/cap.test.ts +++ b/packages/cf-deploy-config-writer/test/unit/cap.test.ts @@ -86,7 +86,7 @@ describe('CF Writer', () => { await expect(generateAppConfig({ appPath: capPath }, unitTestFs)).rejects.toThrowError(MTABinNotFound); }); - test('Validate dependency on CDS', async () => { + test('Validate error is thrown if cds fails', async () => { spawnMock = jest.spyOn(childProcess, 'spawnSync').mockImplementation(() => ({ error: 1 } as any)); const capPath = join(outputDir, 'capcds'); fsExtra.mkdirSync(outputDir, { recursive: true }); @@ -101,7 +101,7 @@ describe('CF Writer', () => { }, unitTestFs ) - ).rejects.toThrowError(CDSBinNotFound); + ).rejects.toThrowError(/Something went wrong creating mta.yaml!/); expect(spawnMock).not.toHaveBeenCalledWith(''); }); }); diff --git a/packages/cf-deploy-config-writer/test/unit/fixtures/mta-types/cdsmta/mta.yaml b/packages/cf-deploy-config-writer/test/unit/fixtures/mta-types/cdsmta/mta.yaml new file mode 100644 index 0000000000..6baa5d05c8 --- /dev/null +++ b/packages/cf-deploy-config-writer/test/unit/fixtures/mta-types/cdsmta/mta.yaml @@ -0,0 +1,101 @@ +_schema-version: 3.3.0 +ID: captestproject +version: 1.0.0 +description: "A simple CAP project." +parameters: + enable-parallel-deployments: true + deploy_mode: html5-repo +build-parameters: + before-all: + - builder: custom + commands: + - npm ci + - npx cds build --production +modules: + - name: captestproject-srv + type: nodejs + path: gen/srv + parameters: + buildpack: nodejs_buildpack + readiness-health-check-type: http + readiness-health-check-http-endpoint: /health + build-parameters: + builder: npm + provides: + - name: srv-api # required by consumers of CAP services (e.g. approuter) + properties: + srv-url: ${default-url} + requires: + - name: captestproject-db + - name: captestproject-auth + - name: captestproject-connectivity + - name: captestproject-destination + + - name: captestproject-db-deployer + type: hdb + path: gen/db + parameters: + buildpack: nodejs_buildpack + requires: + - name: captestproject-db + + - name: captestproject-app-deployer + type: com.sap.application.content + path: gen + requires: + - name: captestproject-html5-repo-host + parameters: + content-target: true + build-parameters: + build-result: app/ + requires: + + +resources: + - name: captestproject-db + type: com.sap.xs.hdi-container + parameters: + service: hana + service-plan: hdi-shared + - name: captestproject-auth + type: org.cloudfoundry.managed-service + parameters: + service: xsuaa + service-plan: application + path: ./xs-security.json + config: + xsappname: captestproject-${org}-${space} + tenant-mode: dedicated + - name: captestproject-connectivity + type: org.cloudfoundry.managed-service + parameters: + service: connectivity + service-plan: lite + - name: captestproject-destination + type: org.cloudfoundry.managed-service + parameters: + service: destination + service-plan: lite + config: + HTML5Runtime_enabled: true + init_data: + instance: + existing_destinations_policy: update + destinations: + - Name: captestproject-srv-api + URL: ~{srv-api/srv-url} + Authentication: NoAuthentication + Type: HTTP + ProxyType: Internet + HTML5.ForwardAuthToken: true + HTML5.DynamicDestination: true + - Name: ui5 + URL: https://ui5.sap.com + Authentication: NoAuthentication + Type: HTTP + ProxyType: Internet + - name: captestproject-html5-repo-host + type: org.cloudfoundry.managed-service + parameters: + service: html5-apps-repo + service-plan: app-host diff --git a/packages/cf-deploy-config-writer/test/unit/index-app.test.ts b/packages/cf-deploy-config-writer/test/unit/index-app.test.ts index a8447c8282..51bf1aba0b 100644 --- a/packages/cf-deploy-config-writer/test/unit/index-app.test.ts +++ b/packages/cf-deploy-config-writer/test/unit/index-app.test.ts @@ -3,7 +3,11 @@ import fsExtra from 'fs-extra'; import hasbin from 'hasbin'; import { NullTransport, ToolsLogger } from '@sap-ux/logger'; import * as btp from '@sap-ux/btp-utils'; -import { generateAppConfig } from '../../src'; +import { generateAppConfig, DefaultMTADestination } from '../../src'; +import { generateSupportingConfig } from '../../src/utils'; +import type { CFConfig } from '../../src/types'; +import { create } from 'mem-fs-editor'; +import { create as createStorage } from 'mem-fs'; jest.mock('@sap-ux/btp-utils', () => ({ ...jest.requireActual('@sap-ux/btp-utils'), @@ -16,6 +20,13 @@ jest.mock('hasbin', () => ({ sync: jest.fn() })); +jest.mock('@sap/mta-lib', () => { + return { + // eslint-disable-next-line @typescript-eslint/no-var-requires + Mta: require('./mockMta').MockMta + }; +}); + let hasSyncMock: jest.SpyInstance; let isAppStudioMock: jest.SpyInstance; let listDestinationsMock: jest.SpyInstance; @@ -64,6 +75,10 @@ describe('CF Writer App', () => { jest.resetAllMocks(); }); + test('Generate deployment configs - DefaultMTADestination', async () => { + expect(DefaultMTADestination).toEqual('fiori-default-srv-api'); + }); + test('Generate deployment configs - HTML5 App and destination read from ui5.yaml', async () => { isAppStudioMock.mockResolvedValue(true); listDestinationsMock.mockResolvedValue(destinationsMock); @@ -113,4 +128,52 @@ describe('CF Writer App', () => { const appPath = join(outputDir, appName); await expect(generateAppConfig({ appPath }, undefined, logger)).rejects.toThrowError(); }); + + test('Generate deployment configs - should fail if no HTML5 app found', async () => { + const appName = 'standalone'; + const appPath = join(outputDir, appName); + fsExtra.mkdirSync(outputDir, { recursive: true }); + fsExtra.mkdirSync(appPath); + fsExtra.copySync(join(__dirname, `../sample/standalone`), appPath); + await expect(generateAppConfig({ appPath, addManagedAppRouter: false })).rejects.toThrowError( + /No SAP Fiori UI5 application found./ + ); + }); + + test('Generate deployment configs - standalone approuter cleanup', async () => { + const rootPath = join(outputDir, 'standalonewithapp'); + const appPath = join(rootPath, 'myapp'); + fsExtra.mkdirSync(outputDir, { recursive: true }); + fsExtra.mkdirSync(rootPath); + fsExtra.copySync(join(__dirname, `../sample/standalonewithapp`), rootPath); + const localFs = await generateAppConfig({ appPath, addManagedAppRouter: false }); + expect(localFs.read(join(rootPath, 'mta.yaml'))).toMatchSnapshot(); + expect(localFs.read(join(rootPath, 'router', 'package.json'))).toMatchSnapshot(); + expect(localFs.read(join(rootPath, 'router', 'xs-app.json'))).toMatchSnapshot(); + }); + + test('Generate deployment configs - generateSupportingConfig with mtaId passed in', async () => { + const fs = create(createStorage()); + const appPath = join(outputDir, 'supportingconfig'); + fsExtra.mkdirSync(outputDir, { recursive: true }); + fsExtra.mkdirSync(appPath); + await generateSupportingConfig({ appPath, mtaId: 'testMtaId', rootPath: appPath } as unknown as CFConfig, fs); + expect(fs.read(join(appPath, 'package.json'))).toMatchSnapshot(); + expect(fs.read(join(appPath, '.gitignore'))).toMatchSnapshot(); + }); + + test('Generate deployment configs - generateSupportingConfig read mtaId read from file', async () => { + const fs = create(createStorage()); + const appPath = join(outputDir, 'supportingconfigreadmta'); + fsExtra.mkdirSync(outputDir, { recursive: true }); + fsExtra.mkdirSync(appPath); + fsExtra.copySync(join(__dirname, 'fixtures/mta-types/cdsmta'), appPath); + await generateSupportingConfig( + { appPath, rootPath: appPath, addManagedAppRouter: true } as unknown as CFConfig, + fs + ); + expect(fs.read(join(appPath, 'package.json'))).toMatchSnapshot(); + expect(fs.read(join(appPath, '.gitignore'))).toMatchSnapshot(); + expect(fs.read(join(appPath, 'xs-security.json'))).toMatchSnapshot(); + }); }); diff --git a/packages/cf-deploy-config-writer/test/unit/index-cap.test.ts b/packages/cf-deploy-config-writer/test/unit/index-cap.test.ts new file mode 100644 index 0000000000..2b558724bb --- /dev/null +++ b/packages/cf-deploy-config-writer/test/unit/index-cap.test.ts @@ -0,0 +1,136 @@ +import { join } from 'path'; +import fsExtra from 'fs-extra'; +import hasbin from 'hasbin'; +import { NullTransport, ToolsLogger } from '@sap-ux/logger'; +import { generateCAPConfig, RouterModuleType } from '../../src'; +import * as childProcess from 'child_process'; +import * as projectAccess from '@sap-ux/project-access'; +import fs from 'fs'; + +jest.mock('child_process'); +jest.mock('hasbin', () => ({ + ...(jest.requireActual('hasbin') as {}), + sync: jest.fn() +})); + +let hasSyncMock: jest.SpyInstance; +let spawnMock: jest.SpyInstance; +const originalPlatform = process.platform; + +jest.mock('child_process'); + +jest.mock('@sap/mta-lib', () => { + return { + // eslint-disable-next-line @typescript-eslint/no-var-requires + Mta: require('./mockMta').MockMta + }; +}); + +describe('CF Writer CAP', () => { + jest.setTimeout(10000); + const logger = new ToolsLogger({ + transports: [new NullTransport()] + }); + const outputDir = join(__dirname, '../test-output', 'capcds'); + + beforeEach(() => { + jest.resetAllMocks(); + jest.restoreAllMocks(); + hasSyncMock = jest.spyOn(hasbin, 'sync').mockImplementation(() => true); + }); + + beforeAll(() => { + fsExtra.removeSync(outputDir); + jest.clearAllMocks(); + jest.spyOn(hasbin, 'sync').mockReturnValue(true); + jest.mock('hasbin', () => { + return { + ...(jest.requireActual('hasbin') as {}), + sync: hasSyncMock + }; + }); + Object.defineProperty(process, 'platform', { value: 'win32' }); + }); + + afterAll(() => { + jest.resetAllMocks(); + Object.defineProperty(process, 'platform', { + value: originalPlatform + }); + }); + + it.each([[RouterModuleType.Managed], [RouterModuleType.Standard]])( + 'Validate generation of CAP mta configurations %s', + async (routerType: RouterModuleType) => { + const mtaId = 'captestproject'; + const mtaPath = join(outputDir, routerType, mtaId); + fsExtra.mkdirSync(mtaPath, { recursive: true }); + fsExtra.copySync(join(__dirname, `../sample/capcds`), mtaPath); + const getCapProjectTypeMock = jest.spyOn(projectAccess, 'getCapProjectType').mockResolvedValue('CAPNodejs'); + // For testing purposes, an existing mta.yaml is copied to reflect the spawn command; + // `cds add mta xsuaa connectivity destination html5-repo` + spawnMock = jest.spyOn(childProcess, 'spawnSync').mockImplementation(() => { + fsExtra.copySync(join(__dirname, `fixtures/mta-types/cdsmta`), mtaPath); + return { status: 0 } as any; + }); + const localFs = await generateCAPConfig( + { + mtaPath, + mtaId, + routerType + }, + undefined, + logger + ); + expect(localFs.read(join(mtaPath, 'mta.yaml'))).toMatchSnapshot(); + expect(getCapProjectTypeMock).toHaveBeenCalled(); + expect(spawnMock.mock.calls).toHaveLength(2); + expect(spawnMock).toHaveBeenCalledWith( + 'cds', + ['add', 'mta', 'xsuaa', 'destination', 'html5-repo'], + expect.objectContaining({ cwd: expect.stringContaining(mtaId) }) + ); + expect(spawnMock.mock.calls[1][0]).toStrictEqual('npm.cmd'); // Just always test for windows! + expect(spawnMock.mock.calls[1][1]).toStrictEqual(['install', '--ignore-engines']); + if (RouterModuleType.Standard === routerType) { + expect(localFs.read(join(mtaPath, `router`, 'package.json'))).toMatchSnapshot(); + expect(localFs.read(join(mtaPath, `router`, 'xs-app.json'))).toMatchSnapshot(); + } + } + ); + + test('Validate CAP project type is correct when creating mta.yaml', async () => { + const mtaId = 'captestproject'; + const mtaPath = join(outputDir, mtaId); + jest.spyOn(projectAccess, 'getCapProjectType').mockResolvedValue('CAPJava'); + await expect( + generateCAPConfig( + { + mtaPath, + mtaId, + routerType: RouterModuleType.Managed + }, + undefined, + logger + ) + ).rejects.toThrowError(/Target folder does not contain a Node.js CAP project./); + }); + + test('Validate CAP type if target contains mta.yaml', async () => { + const mtaId = 'captestproject'; + const mtaPath = join(outputDir, mtaId); + jest.spyOn(projectAccess, 'getCapProjectType').mockResolvedValue('CAPNodejs'); + jest.spyOn(fs, 'existsSync').mockReturnValue(true); + await expect( + generateCAPConfig( + { + mtaPath, + mtaId, + routerType: RouterModuleType.Managed + }, + undefined, + logger + ) + ).rejects.toThrowError(/An mta.yaml already exists in the target directory./); + }); +}); From ac5c2ed486896ebc2674e6267b015585f91829d8 Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 29 Jan 2025 12:28:18 +0000 Subject: [PATCH 08/17] chore: apply latest changesets --- .changeset/soft-carrots-brush.md | 5 ----- packages/cf-deploy-config-sub-generator/CHANGELOG.md | 7 +++++++ packages/cf-deploy-config-sub-generator/package.json | 2 +- packages/cf-deploy-config-writer/CHANGELOG.md | 6 ++++++ packages/cf-deploy-config-writer/package.json | 2 +- 5 files changed, 15 insertions(+), 7 deletions(-) delete mode 100644 .changeset/soft-carrots-brush.md diff --git a/.changeset/soft-carrots-brush.md b/.changeset/soft-carrots-brush.md deleted file mode 100644 index 79207e43e8..0000000000 --- a/.changeset/soft-carrots-brush.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@sap-ux/cf-deploy-config-writer': minor ---- - -append new logic to create CAP mta diff --git a/packages/cf-deploy-config-sub-generator/CHANGELOG.md b/packages/cf-deploy-config-sub-generator/CHANGELOG.md index e2430ce4de..70bd9201ee 100644 --- a/packages/cf-deploy-config-sub-generator/CHANGELOG.md +++ b/packages/cf-deploy-config-sub-generator/CHANGELOG.md @@ -1,5 +1,12 @@ # @sap-ux/cf-deploy-config-sub-generator +## 0.0.5 + +### Patch Changes + +- Updated dependencies [3ff99e2] + - @sap-ux/cf-deploy-config-writer@0.1.0 + ## 0.0.4 ### Patch Changes diff --git a/packages/cf-deploy-config-sub-generator/package.json b/packages/cf-deploy-config-sub-generator/package.json index 54fd4916c8..2a8bba96f4 100644 --- a/packages/cf-deploy-config-sub-generator/package.json +++ b/packages/cf-deploy-config-sub-generator/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/cf-deploy-config-sub-generator", "description": "Generators for configuring Cloud Foundry deployment configuration", - "version": "0.0.4", + "version": "0.0.5", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/cf-deploy-config-writer/CHANGELOG.md b/packages/cf-deploy-config-writer/CHANGELOG.md index 9c1a5428d3..24e84c4201 100644 --- a/packages/cf-deploy-config-writer/CHANGELOG.md +++ b/packages/cf-deploy-config-writer/CHANGELOG.md @@ -1,5 +1,11 @@ # @sap-ux/cf-deploy-config-inquirer +## 0.1.0 + +### Minor Changes + +- 3ff99e2: append new logic to create CAP mta + ## 0.0.19 ### Patch Changes diff --git a/packages/cf-deploy-config-writer/package.json b/packages/cf-deploy-config-writer/package.json index 8163d69fca..d2811512d3 100644 --- a/packages/cf-deploy-config-writer/package.json +++ b/packages/cf-deploy-config-writer/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/cf-deploy-config-writer", "description": "Add or amend Cloud Foundry and ABAP deployment configuration for SAP projects", - "version": "0.0.19", + "version": "0.1.0", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", From df2d965e5b1f4b67d075f2156817ff7b83d88c7f Mon Sep 17 00:00:00 2001 From: J Long Date: Wed, 29 Jan 2025 13:09:33 +0000 Subject: [PATCH 09/17] 2702/expose new btp destination creation (#2799) * fix(axios-ext): expose new create BTP destination function * fix(btp-utils): add unit tests * fix(btp-utils): merge with master yarn lock * fix(btp-utils): add changeset * fix(btp-utils): cleanup * fix(btp-utils): address sonar issues * fix(btp-utils): return oauth destination * fix(btp-utils): change to minor version bump * fix(btp-utils): updates to reflect changes to bas-sdk * fix(btp-utils: consume bas-sdk to generate and create new oauth2 destination * fix(btp-utils): fix linting * fix(btp-utils): update tests based on changed in bas-sdk * fix(btp-utils): bump to latest version * fix(btp-utils): return BTP destination, update tests and docs * fix(btp-utils): cleanup text --------- Co-authored-by: IainSAP <46536134+IainSAP@users.noreply.github.com> Co-authored-by: Austin Devine --- .changeset/thirty-trains-beam.md | 5 + packages/btp-utils/package.json | 3 +- packages/btp-utils/src/app-studio.ts | 167 +++++++++++++++++- packages/btp-utils/src/destination.ts | 41 +++++ packages/btp-utils/test/app-studio.test.ts | 142 ++++++++++++++- .../test/mockResponses/destinations.json | 11 ++ pnpm-lock.yaml | 34 ++++ 7 files changed, 394 insertions(+), 9 deletions(-) create mode 100644 .changeset/thirty-trains-beam.md diff --git a/.changeset/thirty-trains-beam.md b/.changeset/thirty-trains-beam.md new file mode 100644 index 0000000000..cbeed81869 --- /dev/null +++ b/.changeset/thirty-trains-beam.md @@ -0,0 +1,5 @@ +--- +'@sap-ux/btp-utils': minor +--- + +new functionality to generate OAuth2TokenExchange BTP destination using cf-tools diff --git a/packages/btp-utils/package.json b/packages/btp-utils/package.json index 39158094eb..dec2f4e725 100644 --- a/packages/btp-utils/package.json +++ b/packages/btp-utils/package.json @@ -27,7 +27,8 @@ }, "dependencies": { "@sap/cf-tools": "3.2.2", - "axios": "1.7.4" + "axios": "1.7.4", + "@sap/bas-sdk": "3.11.2" }, "devDependencies": { "nock": "13.4.0", diff --git a/packages/btp-utils/src/app-studio.ts b/packages/btp-utils/src/app-studio.ts index a717c37503..8291692958 100644 --- a/packages/btp-utils/src/app-studio.ts +++ b/packages/btp-utils/src/app-studio.ts @@ -1,8 +1,30 @@ import axios from 'axios'; -import { cfGetInstanceKeyParameters } from '@sap/cf-tools'; +import { + apiCreateServiceInstance, + apiGetInstanceCredentials, + apiGetServicesInstancesFilteredByType, + cfGetInstanceKeyParameters, + cfGetTarget +} from '@sap/cf-tools'; import type { Logger } from '@sap-ux/logger'; import { ENV } from './app-studio.env'; -import { isS4HC, type Destination, type ListDestinationOpts } from './destination'; +import { + Authentication, + type Destination, + isS4HC, + type ListDestinationOpts, + type CloudFoundryServiceInfo, + OAuthUrlType, + DestinationProxyType, + DestinationType +} from './destination'; +import type { ServiceInfo } from './service-info'; +import { destinations as destinationAPI } from '@sap/bas-sdk'; + +/** + * ABAP Cloud destination instance name. + */ +const DESTINATION_INSTANCE_NAME: string = 'abap-cloud-destination-instance'; /** * HTTP header that is to be used for encoded credentials when communicating with a destination service instance. @@ -10,7 +32,7 @@ import { isS4HC, type Destination, type ListDestinationOpts } from './destinatio export const BAS_DEST_INSTANCE_CRED_HEADER = 'bas-destination-instance-cred'; /** - * Check if this is exectued in SAP Business Application Studio. + * Check if this is executed in SAP Business Application Studio. * * @returns true if yes */ @@ -81,7 +103,7 @@ export type Destinations = { [name: string]: Destination }; * Helper function to strip `-api` from the host name. * * @param host - - * @returns + * @returns an updated string value, with `-api` removed */ function stripS4HCApiHost(host: string): string { const [first, ...rest] = host.split('.'); @@ -127,3 +149,140 @@ export async function exposePort(port: number, logger?: Logger): Promise return ''; } } + +/** + * Transform a destination object into a TokenExchangeDestination destination, appended with UAA properties. + * + * @param destination destination info + * @param credentials object representing the Client ID and Client Secret and token endpoint + * @returns Populated OAuth destination + */ +function transformToBASSDKDestination( + destination: Destination, + credentials: ServiceInfo['uaa'] +): destinationAPI.DestinationInfo { + const BASProperties = { + usage: 'odata_abap,dev_abap,abap_cloud', + html5DynamicDestination: 'true', + html5Timeout: '60000' + } as destinationAPI.BASProperties; + + const oauth2UserTokenExchange: destinationAPI.OAuth2UserTokenExchange = { + clientId: credentials.clientid, + clientSecret: credentials.clientsecret, + tokenServiceURL: new URL('/oauth/token', credentials.url).toString(), + tokenServiceURLType: OAuthUrlType.DEDICATED + }; + + return { + name: destination.Name, + description: destination.Description, + url: new URL(credentials.url), + type: DestinationType.HTTP, + proxyType: DestinationProxyType.INTERNET, + basProperties: BASProperties, + credentials: { + authentication: Authentication.OAUTH2_USER_TOKEN_EXCHANGE as destinationAPI.AuthenticationType, + oauth2UserTokenExchange + } + } as destinationAPI.DestinationInfo; +} + +/** + * Generate a destination name representing the CF target the user is logged into i.e. abap-cloud-mydestination-myorg-mydevspace. + * + * @param name destination name + * @returns formatted destination name using target space and target organisation + */ +export async function generateABAPCloudDestinationName(name: string): Promise { + const target = await cfGetTarget(true); + if (!target.space) { + throw new Error(`No Dev Space has been created for the subaccount.`); + } + const formattedInstanceName = `${name}-${target.org}-${target.space}`.replace(/\W/gi, '-').toLowerCase(); + return `abap-cloud-${formattedInstanceName}`.substring(0, 199); +} + +/** + * Generate a new object representing an OAuth2 token exchange BTP destination. + * + * @param destination destination info + * @param serviceInstanceName name of the service instance, for example, the ABAP Environment service name which is linked to the service technical name i.e. abap-canary + * @param logger Logger + * @returns Preconfigured OAuth destination + */ +async function generateOAuth2UserTokenExchangeDestination( + destination: Destination, + serviceInstanceName: string, + logger?: Logger +): Promise { + if (!serviceInstanceName) { + throw new Error(`No service instance name defined.`); + } + + const destinationName: string = await generateABAPCloudDestinationName(destination.Name); + const instances: CloudFoundryServiceInfo[] = await apiGetServicesInstancesFilteredByType(['destination']); + const destinationInstance = instances.find( + (instance: CloudFoundryServiceInfo) => instance.label === DESTINATION_INSTANCE_NAME + ); + + if (!destinationInstance) { + // Create a new abap-cloud destination instance on the target CF subaccount + await apiCreateServiceInstance('destination', 'lite', DESTINATION_INSTANCE_NAME, null); + logger?.info(`New ABAP destination instance ${DESTINATION_INSTANCE_NAME} created.`); + } + + const instanceDetails = await apiGetInstanceCredentials(serviceInstanceName); + if (!instanceDetails?.credentials) { + throw new Error(`Could not retrieve SAP BTP credentials for ${serviceInstanceName}.`); + } + return transformToBASSDKDestination( + { + ...destination, + Description: `Destination generated by App Studio for '${destination.Name}', Do not remove.`, + Name: destinationName + }, + instanceDetails.credentials as ServiceInfo['uaa'] + ); +} + +/** + * Create a new SAP BTP subaccount destination of type 'OAuth2UserTokenExchange' using cf-tools to populate the UAA properties. + * If the destination already exists, only new or missing properties will be appended, existing fields are not updated with newer values. + * For example: If an existing SAP BTP destination already contains `WebIDEEnabled` and the value is set as `false`, the value will remain `false` even after the update. + * + * Exceptions: an exception will be thrown if the user is not logged into Cloud Foundry, ensure you are logged `cf login -a https://my-test-env.hana.ondemand.com -o staging -s qa` + * + * @param destination destination info + * @param serviceInstanceName name of the service instance, for example, the ABAP Environment service name reflecting name of the service created using a supported service technical name i.e. abap | abap-canary + * @param logger Logger + * @returns the newly generated SAP BTP destination + */ +export async function createOAuth2UserTokenExchangeDest( + destination: Destination, + serviceInstanceName: string, + logger?: Logger +): Promise { + if (!isAppStudio()) { + throw new Error(`Creating a SAP BTP destinations is only supported on SAP Business Application Studio.`); + } + try { + const basSDKDestination: destinationAPI.DestinationInfo = await generateOAuth2UserTokenExchangeDestination( + destination, + serviceInstanceName, + logger + ); + // Destination is created on SAP BTP but nothing is returned to validate this! + await destinationAPI.createDestination(basSDKDestination); + logger?.debug(`SAP BTP destination ${JSON.stringify(basSDKDestination, null, 2)} created.`); + // Return updated destination from SAP BTP + const destinations = await listDestinations(); + const newDestination = destinations?.[basSDKDestination.name]; + if (!newDestination) { + throw new Error('Destination not found on SAP BTP.'); + } + return newDestination; + } catch (error) { + throw new Error(`An error occurred while generating destination ${destination.Name}: ${error}`); + } +} diff --git a/packages/btp-utils/src/destination.ts b/packages/btp-utils/src/destination.ts index c3d9ff0591..9110c588cb 100644 --- a/packages/btp-utils/src/destination.ts +++ b/packages/btp-utils/src/destination.ts @@ -1,3 +1,21 @@ +/** + * Support different Token Service URL Types + */ +export enum DestinationType { + HTTP = 'HTTP', + LDAP = 'LDAP', + MAIL = 'MAIL', + RFC = 'RFC' +} + +/** + * Support different Token Service URL Types + */ +export enum OAuthUrlType { + DEDICATED = 'Dedicated', + COMMON = 'Common' +} + /** * Support destination authentication types */ @@ -76,6 +94,7 @@ export interface Destination extends Partial { Authentication: string; ProxyType: string; Description: string; + /** * N.B. Not the host but the full destination URL property! */ @@ -286,3 +305,25 @@ export const AbapEnvType = { } as const; export type AbapEnvType = (typeof AbapEnvType)[keyof typeof AbapEnvType]; + +/** + * OAuth destination properties. + */ +export interface OAuth2Destination extends Omit, Partial { + URL: string; // Required for creation flow + clientSecret: string; + clientId: string; + tokenServiceURL: string; + tokenServiceURLType?: 'Dedicated'; // Optional for OAuth2Password destinations +} + +export interface CloudFoundryServiceInfo { + label: string; + serviceName: string; + guid?: string; + tags?: string[]; + alwaysShow?: boolean; + plan_guid?: string; + plan?: string; + credentials?: any; +} diff --git a/packages/btp-utils/test/app-studio.test.ts b/packages/btp-utils/test/app-studio.test.ts index 12c9569fae..d10689ca6e 100644 --- a/packages/btp-utils/test/app-studio.test.ts +++ b/packages/btp-utils/test/app-studio.test.ts @@ -1,6 +1,6 @@ import nock from 'nock'; import { join } from 'path'; -import type { Destination } from '../src'; +import { Destination } from '../src'; import { getAppStudioProxyURL, getAppStudioBaseURL, @@ -8,10 +8,13 @@ import { getDestinationUrlForAppStudio, listDestinations, getCredentialsForDestinationService, - exposePort + exposePort, + createOAuth2UserTokenExchangeDest } from '../src'; import { ENV } from '../src/app-studio.env'; import destinationList from './mockResponses/destinations.json'; +import { type ServiceInstanceInfo } from '@sap/cf-tools'; +import { ToolsLogger } from '@sap-ux/logger'; const destinations: { [key: string]: Destination } = {}; destinationList.forEach((dest) => { @@ -23,6 +26,18 @@ const mockInstanceSettings = { clientsecret: 'CLIENT_SECRET' }; +let cfDiscoveredAbapEnvsMock: ServiceInstanceInfo[] = [ + { label: 'system1', serviceName: 'service1' }, + { label: 'system2', serviceName: 'service2' } +]; +let uaaCredentialsMock = { + credentials: { + clientid: 'CLIENT_ID/WITH/STH/TO/ENCODE', + clientsecret: 'CLIENT_SECRET', + url: 'http://my-server' + } +}; +let cfTargetMock = { org: 'testOrg', space: 'testSpace' }; jest.mock('@sap/cf-tools', () => { const original = jest.requireActual('@sap/cf-tools'); return { @@ -39,7 +54,11 @@ jest.mock('@sap/cf-tools', () => { ? { credentials: { uaa: mockInstanceSettings } } : { credentials: mockInstanceSettings }; } - }) + }), + cfGetTarget: jest.fn(() => Promise.resolve(cfTargetMock)), + apiGetServicesInstancesFilteredByType: jest.fn().mockImplementation(() => cfDiscoveredAbapEnvsMock), + apiCreateServiceInstance: jest.fn().mockImplementation(() => {}), + apiGetInstanceCredentials: jest.fn(() => Promise.resolve(uaaCredentialsMock)) }; }); @@ -55,7 +74,7 @@ describe('App Studio', () => { expect(isAppStudio()).toBeFalsy(); }); - it('returns true when env variable is ""', () => { + it('returns true when env variable is ', () => { process.env[ENV.H2O_URL] = ''; expect(isAppStudio()).toBeFalsy(); }); @@ -189,4 +208,119 @@ describe('App Studio', () => { expect(url).toStrictEqual(''); }); }); + + describe('createOAuth2UserTokenExchangeDest', () => { + let envH20Settings: string | undefined; + let envWSBaseURLSettings: string | undefined; + const logger = new ToolsLogger(); + const infoMock = (logger.info = jest.fn()); + const debugMock = (logger.debug = jest.fn()); + + const serviceInstanceName = 'abap-test'; + const server = 'https://destinations.example'; + // Some settings are toggled or incorrect, to ensure the correct params are posted to BTP + const destination: Destination = { + Name: 'my-abap-env', + Type: 'MAIL', + ProxyType: 'Internet', + Authentication: 'NoAuthentication', + WebIDEEnabled: 'false', + Description: 'This should be removed during the regeneration of the BTP destination', + 'HTML5.DynamicDestination': 'false', + Host: 'https://658bd07a-eda6-40bc-b17a-b9a8b79b646b.abap.canaryaws.hanavlab.ondemand.com/' + }; + + beforeAll(() => { + nock(server).get('/reload').reply(200).persist(); + envH20Settings = process.env[ENV.H2O_URL]; + envWSBaseURLSettings = process.env['WS_BASE_URL']; + process.env[ENV.H2O_URL] = server; + process.env[ENV.PROXY_URL] = server; + }); + + afterAll(() => { + process.env[ENV.H2O_URL] = envH20Settings; + process.env['WS_BASE_URL'] = envWSBaseURLSettings; + jest.resetAllMocks(); + }); + + test('creation is only supported on BAS', async () => { + delete process.env[ENV.H2O_URL]; + await expect(createOAuth2UserTokenExchangeDest(destination, serviceInstanceName)).rejects.toThrow( + /SAP Business Application Studio/ + ); + }); + + test('generate new OAuth2UserTokenExchange SAP BTP destination', async () => { + process.env[ENV.H2O_URL] = server; + process.env['WS_BASE_URL'] = server; // Required for bas-sdk to ensure isAppStudio is true + const result = ` + Object { + "Authentication": "OAuth2UserTokenExchange", + "Description": "Destination generated by App Studio for 'my-abap-env', Do not remove.", + "HTML5.DynamicDestination": "true", + "HTML5.Timeout": "60000", + "Name": "abap-cloud-my-abap-env-testorg-testspace", + "ProxyType": "Internet", + "Type": "HTTP", + "URL": "http://my-server/", + "WebIDEEnabled": "true", + "WebIDEUsage": "odata_abap,dev_abap,abap_cloud", + "clientId": "CLIENT_ID/WITH/STH/TO/ENCODE", + "clientSecret": "CLIENT_SECRET", + "tokenServiceURL": "http://my-server/oauth/token", + "tokenServiceURLType": "Dedicated", + } + `; + let bodyParam; + nock(server) + .post('/api/createDestination', (body) => { + bodyParam = body; + return true; + }) + .reply(200); + nock(server) + .get('/api/listDestinations') + .replyWithFile(200, join(__dirname, 'mockResponses/destinations.json')); + await expect( + createOAuth2UserTokenExchangeDest(destination, serviceInstanceName, logger) + ).resolves.toMatchObject(destinations['abap-cloud-my-abap-env-testorg-testspace']); + expect(bodyParam).toMatchInlineSnapshot(result); + expect(infoMock).toBeCalledTimes(1); + expect(debugMock).toBeCalledTimes(1); + }); + + test('throw exception if no destination found in SAP BTP', async () => { + process.env[ENV.H2O_URL] = server; + process.env['WS_BASE_URL'] = server; + nock(server).post('/api/createDestination').reply(200); + nock(server).get('/api/listDestinations').reply(200); + await expect(createOAuth2UserTokenExchangeDest(destination, serviceInstanceName)).rejects.toThrow( + /Destination not found on SAP BTP./ + ); + }); + + test('throw exception if no service instance name provided', async () => { + process.env[ENV.H2O_URL] = server; + await expect(createOAuth2UserTokenExchangeDest(destination, '')).rejects.toThrow( + /No service instance name defined./ + ); + }); + + test('throw exception if no UAA credentials found', async () => { + process.env[ENV.H2O_URL] = server; + uaaCredentialsMock = {} as any; + await expect(createOAuth2UserTokenExchangeDest(destination, serviceInstanceName)).rejects.toThrow( + /Could not retrieve SAP BTP credentials./ + ); + }); + + test('throw exception if no dev space is created for the respective subaccount', async () => { + process.env[ENV.H2O_URL] = server; + cfTargetMock = {} as any; + await expect(createOAuth2UserTokenExchangeDest(destination, serviceInstanceName)).rejects.toThrow( + /No Dev Space has been created for the subaccount./ + ); + }); + }); }); diff --git a/packages/btp-utils/test/mockResponses/destinations.json b/packages/btp-utils/test/mockResponses/destinations.json index 78a61c56d9..cc7b449e4b 100644 --- a/packages/btp-utils/test/mockResponses/destinations.json +++ b/packages/btp-utils/test/mockResponses/destinations.json @@ -70,5 +70,16 @@ "HTML5.DynamicDestination": "true", "audience": "https://s4hc-example.sap.example", "authnContextClassRef": "urn:oasis:names:tc:SAML:2.0:ac:classes:PreviousSession" + }, + { + "Name": "abap-cloud-my-abap-env-testorg-testspace", + "Type": "HTTP", + "Authentication": "SAMLAssertion", + "ProxyType": "Internet", + "Description": "Destination generated by App Studio for 'my-abap-env', Do not remove.", + "WebIDEEnabled": "true", + "WebIDEUsage": "odata_abap,dev_abap,abap_cloud", + "Host": "http://my-server/", + "HTML5.DynamicDestination": "true" } ] diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7678e728b0..4f00d8d451 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -815,6 +815,9 @@ importers: packages/btp-utils: dependencies: + '@sap/bas-sdk': + specifier: 3.11.2 + version: 3.11.2 '@sap/cf-tools': specifier: 3.2.2 version: 3.2.2 @@ -8285,6 +8288,22 @@ packages: resolution: {integrity: sha512-srR9ffXpgvVxsrD/3ZvX6PnxXyY6yeth6LuKfCDgcyDoPeRj1jQknpgVF+k9hHDv7LkGkDiHYvjWY+JP8OlDLw==} engines: {node: '>=18.x'} + /@sap/bas-sdk@3.11.2: + resolution: {integrity: sha512-UU7tZNiWg2yvSdS2lqYq8o22GyzFKkqpJnWv1ihGMrfgp7riaZVfSKpO1+VZvmyJl7qbTRP0oyg5DKAoWVyAEw==} + dependencies: + axios: 1.7.9 + cross-spawn: 7.0.5 + fs-extra: 11.1.1 + jwt-decode: 4.0.0 + lodash: 4.17.21 + url-join: 4.0.1 + ws: 8.17.1 + transitivePeerDependencies: + - bufferutil + - debug + - utf-8-validate + dev: false + /@sap/bas-sdk@3.8.9: resolution: {integrity: sha512-ycYttnSTlEPjDrb0svSv0jBgqEvoekD4bNB4IxuKCu5OKk5FycwsOTgufU8CXYf1ag23wTlurN+N7c4Po6PcJQ==} dependencies: @@ -11067,6 +11086,16 @@ packages: transitivePeerDependencies: - debug + /axios@1.7.9: + resolution: {integrity: sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==} + dependencies: + follow-redirects: 1.15.6 + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + dev: false + /b4a@1.6.6: resolution: {integrity: sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==} @@ -16790,6 +16819,11 @@ packages: resolution: {integrity: sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==} dev: true + /jwt-decode@4.0.0: + resolution: {integrity: sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==} + engines: {node: '>=18'} + dev: false + /keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} dependencies: From 5efd9d21deee27779847c7da1a77f9187b650f3b Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 29 Jan 2025 13:31:31 +0000 Subject: [PATCH 10/17] chore: apply latest changesets --- .changeset/thirty-trains-beam.md | 5 ----- examples/odata-cli/CHANGELOG.md | 8 ++++++++ examples/odata-cli/package.json | 2 +- examples/simple-generator/CHANGELOG.md | 11 +++++++++++ examples/simple-generator/package.json | 2 +- packages/abap-deploy-config-inquirer/CHANGELOG.md | 11 +++++++++++ packages/abap-deploy-config-inquirer/package.json | 2 +- .../abap-deploy-config-sub-generator/CHANGELOG.md | 12 ++++++++++++ .../abap-deploy-config-sub-generator/package.json | 2 +- packages/abap-deploy-config-writer/CHANGELOG.md | 6 ++++++ packages/abap-deploy-config-writer/package.json | 2 +- packages/adp-tooling/CHANGELOG.md | 10 ++++++++++ packages/adp-tooling/package.json | 2 +- packages/app-config-writer/CHANGELOG.md | 8 ++++++++ packages/app-config-writer/package.json | 2 +- packages/axios-extension/CHANGELOG.md | 7 +++++++ packages/axios-extension/package.json | 2 +- packages/backend-proxy-middleware/CHANGELOG.md | 8 ++++++++ packages/backend-proxy-middleware/package.json | 2 +- packages/btp-utils/CHANGELOG.md | 6 ++++++ packages/btp-utils/package.json | 2 +- packages/cap-config-writer/CHANGELOG.md | 6 ++++++ packages/cap-config-writer/package.json | 2 +- packages/cf-deploy-config-inquirer/CHANGELOG.md | 8 ++++++++ packages/cf-deploy-config-inquirer/package.json | 2 +- .../cf-deploy-config-sub-generator/CHANGELOG.md | 9 +++++++++ .../cf-deploy-config-sub-generator/package.json | 2 +- packages/cf-deploy-config-writer/CHANGELOG.md | 7 +++++++ packages/cf-deploy-config-writer/package.json | 2 +- packages/create/CHANGELOG.md | 13 +++++++++++++ packages/create/package.json | 2 +- .../deploy-config-generator-shared/CHANGELOG.md | 7 +++++++ .../deploy-config-generator-shared/package.json | 2 +- packages/deploy-tooling/CHANGELOG.md | 9 +++++++++ packages/deploy-tooling/package.json | 2 +- packages/environment-check/CHANGELOG.md | 8 ++++++++ packages/environment-check/package.json | 2 +- packages/fiori-elements-writer/CHANGELOG.md | 7 +++++++ packages/fiori-elements-writer/package.json | 2 +- packages/fiori-freestyle-writer/CHANGELOG.md | 7 +++++++ packages/fiori-freestyle-writer/package.json | 2 +- packages/fiori-generator-shared/CHANGELOG.md | 8 ++++++++ packages/fiori-generator-shared/package.json | 2 +- packages/flp-config-inquirer/CHANGELOG.md | 10 ++++++++++ packages/flp-config-inquirer/package.json | 2 +- packages/flp-config-sub-generator/CHANGELOG.md | 10 ++++++++++ packages/flp-config-sub-generator/package.json | 2 +- packages/inquirer-common/CHANGELOG.md | 9 +++++++++ packages/inquirer-common/package.json | 2 +- packages/nodejs-utils/CHANGELOG.md | 7 +++++++ packages/nodejs-utils/package.json | 2 +- packages/odata-service-inquirer/CHANGELOG.md | 11 +++++++++++ packages/odata-service-inquirer/package.json | 2 +- packages/preview-middleware/CHANGELOG.md | 8 ++++++++ packages/preview-middleware/package.json | 2 +- packages/reload-middleware/CHANGELOG.md | 7 +++++++ packages/reload-middleware/package.json | 2 +- packages/system-access/CHANGELOG.md | 8 ++++++++ packages/system-access/package.json | 2 +- packages/telemetry/CHANGELOG.md | 7 +++++++ packages/telemetry/package.json | 2 +- packages/ui5-application-inquirer/CHANGELOG.md | 6 ++++++ packages/ui5-application-inquirer/package.json | 2 +- packages/ui5-library-inquirer/CHANGELOG.md | 6 ++++++ packages/ui5-library-inquirer/package.json | 2 +- .../ui5-library-reference-inquirer/CHANGELOG.md | 6 ++++++ .../ui5-library-reference-inquirer/package.json | 2 +- .../CHANGELOG.md | 8 ++++++++ .../package.json | 2 +- packages/ui5-library-sub-generator/CHANGELOG.md | 8 ++++++++ packages/ui5-library-sub-generator/package.json | 2 +- 71 files changed, 322 insertions(+), 40 deletions(-) delete mode 100644 .changeset/thirty-trains-beam.md diff --git a/.changeset/thirty-trains-beam.md b/.changeset/thirty-trains-beam.md deleted file mode 100644 index cbeed81869..0000000000 --- a/.changeset/thirty-trains-beam.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@sap-ux/btp-utils': minor ---- - -new functionality to generate OAuth2TokenExchange BTP destination using cf-tools diff --git a/examples/odata-cli/CHANGELOG.md b/examples/odata-cli/CHANGELOG.md index a5503cab62..3b1f9dc50c 100644 --- a/examples/odata-cli/CHANGELOG.md +++ b/examples/odata-cli/CHANGELOG.md @@ -1,5 +1,13 @@ # @sap-ux/odata-cli +## 0.16.3 + +### Patch Changes + +- Updated dependencies [df2d965] + - @sap-ux/btp-utils@0.18.0 + - @sap-ux/axios-extension@1.18.3 + ## 0.16.2 ### Patch Changes diff --git a/examples/odata-cli/package.json b/examples/odata-cli/package.json index 28a85934db..f599bbd19a 100644 --- a/examples/odata-cli/package.json +++ b/examples/odata-cli/package.json @@ -1,6 +1,6 @@ { "name": "@sap-ux/odata-cli", - "version": "0.16.2", + "version": "0.16.3", "description": "Simple example CLI uing the @sap-ux/axios-extension module to fetch metadata and annotations from an SAP system.", "license": "Apache-2.0", "private": true, diff --git a/examples/simple-generator/CHANGELOG.md b/examples/simple-generator/CHANGELOG.md index b4c90ec4bb..d54e27a719 100644 --- a/examples/simple-generator/CHANGELOG.md +++ b/examples/simple-generator/CHANGELOG.md @@ -1,5 +1,16 @@ # @sap-ux/generator-simple-fe +## 1.0.116 + +### Patch Changes + +- Updated dependencies [df2d965] + - @sap-ux/btp-utils@0.18.0 + - @sap-ux/axios-extension@1.18.3 + - @sap-ux/system-access@0.5.28 + - @sap-ux/fiori-elements-writer@2.0.6 + - @sap-ux/fiori-freestyle-writer@2.0.5 + ## 1.0.115 ### Patch Changes diff --git a/examples/simple-generator/package.json b/examples/simple-generator/package.json index 104ed18d1d..0c25499631 100644 --- a/examples/simple-generator/package.json +++ b/examples/simple-generator/package.json @@ -1,6 +1,6 @@ { "name": "@sap-ux/generator-simple-fe", - "version": "1.0.115", + "version": "1.0.116", "description": "Simple example of a yeoman generator for Fiori elements.", "license": "Apache-2.0", "private": true, diff --git a/packages/abap-deploy-config-inquirer/CHANGELOG.md b/packages/abap-deploy-config-inquirer/CHANGELOG.md index 75a5d96ab7..9e3a581692 100644 --- a/packages/abap-deploy-config-inquirer/CHANGELOG.md +++ b/packages/abap-deploy-config-inquirer/CHANGELOG.md @@ -1,5 +1,16 @@ # @sap-ux/abap-deploy-config-inquirer +## 1.2.5 + +### Patch Changes + +- Updated dependencies [df2d965] + - @sap-ux/btp-utils@0.18.0 + - @sap-ux/axios-extension@1.18.3 + - @sap-ux/fiori-generator-shared@0.7.22 + - @sap-ux/inquirer-common@0.6.8 + - @sap-ux/system-access@0.5.28 + ## 1.2.4 ### Patch Changes diff --git a/packages/abap-deploy-config-inquirer/package.json b/packages/abap-deploy-config-inquirer/package.json index 75510ea44d..11703a5d95 100644 --- a/packages/abap-deploy-config-inquirer/package.json +++ b/packages/abap-deploy-config-inquirer/package.json @@ -6,7 +6,7 @@ "url": "https://github.com/SAP/open-ux-tools.git", "directory": "packages/abap-deploy-config-inquirer" }, - "version": "1.2.4", + "version": "1.2.5", "license": "Apache-2.0", "main": "dist/index.js", "scripts": { diff --git a/packages/abap-deploy-config-sub-generator/CHANGELOG.md b/packages/abap-deploy-config-sub-generator/CHANGELOG.md index 73782dc35f..3ba0807bb7 100644 --- a/packages/abap-deploy-config-sub-generator/CHANGELOG.md +++ b/packages/abap-deploy-config-sub-generator/CHANGELOG.md @@ -1,5 +1,17 @@ # @sap-ux/abap-deploy-config-sub-generator +## 0.0.22 + +### Patch Changes + +- Updated dependencies [df2d965] + - @sap-ux/btp-utils@0.18.0 + - @sap-ux/abap-deploy-config-inquirer@1.2.5 + - @sap-ux/deploy-config-generator-shared@0.0.14 + - @sap-ux/fiori-generator-shared@0.7.22 + - @sap-ux/telemetry@0.5.54 + - @sap-ux/abap-deploy-config-writer@0.0.80 + ## 0.0.21 ### Patch Changes diff --git a/packages/abap-deploy-config-sub-generator/package.json b/packages/abap-deploy-config-sub-generator/package.json index 67a3f332e5..75c3e905f3 100644 --- a/packages/abap-deploy-config-sub-generator/package.json +++ b/packages/abap-deploy-config-sub-generator/package.json @@ -6,7 +6,7 @@ "url": "https://github.com/SAP/open-ux-tools.git", "directory": "packages/abap-deploy-config-sub-generator" }, - "version": "0.0.21", + "version": "0.0.22", "license": "Apache-2.0", "main": "generators/app/index.js", "scripts": { diff --git a/packages/abap-deploy-config-writer/CHANGELOG.md b/packages/abap-deploy-config-writer/CHANGELOG.md index c5f8d8d154..7f108bc3d9 100644 --- a/packages/abap-deploy-config-writer/CHANGELOG.md +++ b/packages/abap-deploy-config-writer/CHANGELOG.md @@ -1,5 +1,11 @@ # @sap-ux/abap-deploy-config-writer +## 0.0.80 + +### Patch Changes + +- @sap-ux/system-access@0.5.28 + ## 0.0.79 ### Patch Changes diff --git a/packages/abap-deploy-config-writer/package.json b/packages/abap-deploy-config-writer/package.json index e2dfdfd2d2..ce4ebdb0fa 100644 --- a/packages/abap-deploy-config-writer/package.json +++ b/packages/abap-deploy-config-writer/package.json @@ -6,7 +6,7 @@ "url": "https://github.com/SAP/open-ux-tools.git", "directory": "packages/abap-deploy-config-writer" }, - "version": "0.0.79", + "version": "0.0.80", "license": "Apache-2.0", "main": "dist/index.js", "scripts": { diff --git a/packages/adp-tooling/CHANGELOG.md b/packages/adp-tooling/CHANGELOG.md index 646b097767..de83919fe1 100644 --- a/packages/adp-tooling/CHANGELOG.md +++ b/packages/adp-tooling/CHANGELOG.md @@ -1,5 +1,15 @@ # @sap-ux/adp-tooling +## 0.12.117 + +### Patch Changes + +- Updated dependencies [df2d965] + - @sap-ux/btp-utils@0.18.0 + - @sap-ux/axios-extension@1.18.3 + - @sap-ux/inquirer-common@0.6.8 + - @sap-ux/system-access@0.5.28 + ## 0.12.116 ### Patch Changes diff --git a/packages/adp-tooling/package.json b/packages/adp-tooling/package.json index 8c9e0b3656..7eadb6878c 100644 --- a/packages/adp-tooling/package.json +++ b/packages/adp-tooling/package.json @@ -9,7 +9,7 @@ "bugs": { "url": "https://github.com/SAP/open-ux-tools/issues?q=is%3Aopen+is%3Aissue+label%3Abug+label%3Aadp-tooling" }, - "version": "0.12.116", + "version": "0.12.117", "license": "Apache-2.0", "author": "@SAP/ux-tools-team", "main": "dist/index.js", diff --git a/packages/app-config-writer/CHANGELOG.md b/packages/app-config-writer/CHANGELOG.md index 1cb42d9c33..55b8aed018 100644 --- a/packages/app-config-writer/CHANGELOG.md +++ b/packages/app-config-writer/CHANGELOG.md @@ -1,5 +1,13 @@ # @sap-ux/app-config-writer +## 0.5.20 + +### Patch Changes + +- Updated dependencies [df2d965] + - @sap-ux/btp-utils@0.18.0 + - @sap-ux/axios-extension@1.18.3 + ## 0.5.19 ### Patch Changes diff --git a/packages/app-config-writer/package.json b/packages/app-config-writer/package.json index e44a32a00c..ff2b1cbf01 100644 --- a/packages/app-config-writer/package.json +++ b/packages/app-config-writer/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/app-config-writer", "description": "Add or update configuration for SAP Fiori tools application", - "version": "0.5.19", + "version": "0.5.20", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/axios-extension/CHANGELOG.md b/packages/axios-extension/CHANGELOG.md index 635c6c5810..1e8a3dffa9 100644 --- a/packages/axios-extension/CHANGELOG.md +++ b/packages/axios-extension/CHANGELOG.md @@ -1,5 +1,12 @@ # @sap-ux/axios-extension +## 1.18.3 + +### Patch Changes + +- Updated dependencies [df2d965] + - @sap-ux/btp-utils@0.18.0 + ## 1.18.2 ### Patch Changes diff --git a/packages/axios-extension/package.json b/packages/axios-extension/package.json index 2c1296dae5..4dcd3ae277 100644 --- a/packages/axios-extension/package.json +++ b/packages/axios-extension/package.json @@ -1,6 +1,6 @@ { "name": "@sap-ux/axios-extension", - "version": "1.18.2", + "version": "1.18.3", "description": "Extension of the Axios module adding convenience methods to interact with SAP systems especially with OData services.", "repository": { "type": "git", diff --git a/packages/backend-proxy-middleware/CHANGELOG.md b/packages/backend-proxy-middleware/CHANGELOG.md index 3cb5c2a1e1..8267197106 100644 --- a/packages/backend-proxy-middleware/CHANGELOG.md +++ b/packages/backend-proxy-middleware/CHANGELOG.md @@ -1,5 +1,13 @@ # @sap-ux/backend-proxy-middleware +## 0.8.31 + +### Patch Changes + +- Updated dependencies [df2d965] + - @sap-ux/btp-utils@0.18.0 + - @sap-ux/axios-extension@1.18.3 + ## 0.8.30 ### Patch Changes diff --git a/packages/backend-proxy-middleware/package.json b/packages/backend-proxy-middleware/package.json index 4e4e2766e4..2a4339cdbd 100644 --- a/packages/backend-proxy-middleware/package.json +++ b/packages/backend-proxy-middleware/package.json @@ -9,7 +9,7 @@ "bugs": { "url": "https://github.com/SAP/open-ux-tools/issues?q=is%3Aopen+is%3Aissue+label%3Abug+label%3Abackend-proxy-middleware" }, - "version": "0.8.30", + "version": "0.8.31", "license": "Apache-2.0", "author": "@SAP/ux-tools-team", "main": "dist/index.js", diff --git a/packages/btp-utils/CHANGELOG.md b/packages/btp-utils/CHANGELOG.md index 9337827dfa..7587b9f701 100644 --- a/packages/btp-utils/CHANGELOG.md +++ b/packages/btp-utils/CHANGELOG.md @@ -1,5 +1,11 @@ # @sap-ux/btp-utils +## 0.18.0 + +### Minor Changes + +- df2d965: new functionality to generate OAuth2TokenExchange BTP destination using cf-tools + ## 0.17.2 ### Patch Changes diff --git a/packages/btp-utils/package.json b/packages/btp-utils/package.json index dec2f4e725..f10172474c 100644 --- a/packages/btp-utils/package.json +++ b/packages/btp-utils/package.json @@ -1,6 +1,6 @@ { "name": "@sap-ux/btp-utils", - "version": "0.17.2", + "version": "0.18.0", "description": "Library to simplify working with SAP BTP specific features especially in SAP Business Application", "repository": { "type": "git", diff --git a/packages/cap-config-writer/CHANGELOG.md b/packages/cap-config-writer/CHANGELOG.md index 41ef410006..ecf4f19bec 100644 --- a/packages/cap-config-writer/CHANGELOG.md +++ b/packages/cap-config-writer/CHANGELOG.md @@ -1,5 +1,11 @@ # @sap-ux/cap-config-writer +## 0.9.1 + +### Patch Changes + +- @sap-ux/fiori-generator-shared@0.7.22 + ## 0.9.0 ### Minor Changes diff --git a/packages/cap-config-writer/package.json b/packages/cap-config-writer/package.json index 86f022e1c5..d4bd57c564 100644 --- a/packages/cap-config-writer/package.json +++ b/packages/cap-config-writer/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/cap-config-writer", "description": "Add or update configuration for SAP CAP projects", - "version": "0.9.0", + "version": "0.9.1", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/cf-deploy-config-inquirer/CHANGELOG.md b/packages/cf-deploy-config-inquirer/CHANGELOG.md index f9c3eeb2e9..81eebf885c 100644 --- a/packages/cf-deploy-config-inquirer/CHANGELOG.md +++ b/packages/cf-deploy-config-inquirer/CHANGELOG.md @@ -1,5 +1,13 @@ # @sap-ux/cf-deploy-config-inquirer +## 0.1.22 + +### Patch Changes + +- Updated dependencies [df2d965] + - @sap-ux/btp-utils@0.18.0 + - @sap-ux/inquirer-common@0.6.8 + ## 0.1.21 ### Patch Changes diff --git a/packages/cf-deploy-config-inquirer/package.json b/packages/cf-deploy-config-inquirer/package.json index 4dfd4277dd..49aa4b1e81 100644 --- a/packages/cf-deploy-config-inquirer/package.json +++ b/packages/cf-deploy-config-inquirer/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/cf-deploy-config-inquirer", "description": "Prompts module that can provide prompts for cf deployment config writer", - "version": "0.1.21", + "version": "0.1.22", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/cf-deploy-config-sub-generator/CHANGELOG.md b/packages/cf-deploy-config-sub-generator/CHANGELOG.md index 70bd9201ee..df62d694de 100644 --- a/packages/cf-deploy-config-sub-generator/CHANGELOG.md +++ b/packages/cf-deploy-config-sub-generator/CHANGELOG.md @@ -1,5 +1,14 @@ # @sap-ux/cf-deploy-config-sub-generator +## 0.0.6 + +### Patch Changes + +- @sap-ux/cf-deploy-config-inquirer@0.1.22 +- @sap-ux/cf-deploy-config-writer@0.1.1 +- @sap-ux/deploy-config-generator-shared@0.0.14 +- @sap-ux/inquirer-common@0.6.8 + ## 0.0.5 ### Patch Changes diff --git a/packages/cf-deploy-config-sub-generator/package.json b/packages/cf-deploy-config-sub-generator/package.json index 2a8bba96f4..4ee545bd84 100644 --- a/packages/cf-deploy-config-sub-generator/package.json +++ b/packages/cf-deploy-config-sub-generator/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/cf-deploy-config-sub-generator", "description": "Generators for configuring Cloud Foundry deployment configuration", - "version": "0.0.5", + "version": "0.0.6", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/cf-deploy-config-writer/CHANGELOG.md b/packages/cf-deploy-config-writer/CHANGELOG.md index 24e84c4201..2a98dac746 100644 --- a/packages/cf-deploy-config-writer/CHANGELOG.md +++ b/packages/cf-deploy-config-writer/CHANGELOG.md @@ -1,5 +1,12 @@ # @sap-ux/cf-deploy-config-inquirer +## 0.1.1 + +### Patch Changes + +- Updated dependencies [df2d965] + - @sap-ux/btp-utils@0.18.0 + ## 0.1.0 ### Minor Changes diff --git a/packages/cf-deploy-config-writer/package.json b/packages/cf-deploy-config-writer/package.json index d2811512d3..519df6ded5 100644 --- a/packages/cf-deploy-config-writer/package.json +++ b/packages/cf-deploy-config-writer/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/cf-deploy-config-writer", "description": "Add or amend Cloud Foundry and ABAP deployment configuration for SAP projects", - "version": "0.1.0", + "version": "0.1.1", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/create/CHANGELOG.md b/packages/create/CHANGELOG.md index 60f6ea0fe5..2a1c51b557 100644 --- a/packages/create/CHANGELOG.md +++ b/packages/create/CHANGELOG.md @@ -1,5 +1,18 @@ # @sap-ux/create +## 0.11.48 + +### Patch Changes + +- @sap-ux/abap-deploy-config-inquirer@1.2.5 +- @sap-ux/adp-tooling@0.12.117 +- @sap-ux/app-config-writer@0.5.20 +- @sap-ux/flp-config-inquirer@0.2.23 +- @sap-ux/preview-middleware@0.17.5 +- @sap-ux/system-access@0.5.28 +- @sap-ux/cap-config-writer@0.9.1 +- @sap-ux/abap-deploy-config-writer@0.0.80 + ## 0.11.47 ### Patch Changes diff --git a/packages/create/package.json b/packages/create/package.json index 444374cf27..49c576b4cc 100644 --- a/packages/create/package.json +++ b/packages/create/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/create", "description": "SAP Fiori tools module to add or remove features", - "version": "0.11.47", + "version": "0.11.48", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/deploy-config-generator-shared/CHANGELOG.md b/packages/deploy-config-generator-shared/CHANGELOG.md index 371d8ff6fb..8ed395ff6d 100644 --- a/packages/deploy-config-generator-shared/CHANGELOG.md +++ b/packages/deploy-config-generator-shared/CHANGELOG.md @@ -1,5 +1,12 @@ # @sap-ux/deploy-config-generator-shared +## 0.0.14 + +### Patch Changes + +- @sap-ux/fiori-generator-shared@0.7.22 +- @sap-ux/nodejs-utils@0.1.5 + ## 0.0.13 ### Patch Changes diff --git a/packages/deploy-config-generator-shared/package.json b/packages/deploy-config-generator-shared/package.json index 49c19bd723..e4f72ee78e 100644 --- a/packages/deploy-config-generator-shared/package.json +++ b/packages/deploy-config-generator-shared/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/deploy-config-generator-shared", "description": "Commonly used shared functionality and types to support the deploy config generator.", - "version": "0.0.13", + "version": "0.0.14", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/deploy-tooling/CHANGELOG.md b/packages/deploy-tooling/CHANGELOG.md index ca0104e9bf..54b7d44f77 100644 --- a/packages/deploy-tooling/CHANGELOG.md +++ b/packages/deploy-tooling/CHANGELOG.md @@ -1,5 +1,14 @@ # @sap-ux/deploy-tooling +## 0.15.40 + +### Patch Changes + +- Updated dependencies [df2d965] + - @sap-ux/btp-utils@0.18.0 + - @sap-ux/axios-extension@1.18.3 + - @sap-ux/system-access@0.5.28 + ## 0.15.39 ### Patch Changes diff --git a/packages/deploy-tooling/package.json b/packages/deploy-tooling/package.json index 90e2f0af18..c44c6603b9 100644 --- a/packages/deploy-tooling/package.json +++ b/packages/deploy-tooling/package.json @@ -9,7 +9,7 @@ "bugs": { "url": "https://github.com/SAP/open-ux-tools/issues?q=is%3Aopen+is%3Aissue+label%3Abug+label%3Adeploy-tooling" }, - "version": "0.15.39", + "version": "0.15.40", "license": "Apache-2.0", "author": "@SAP/ux-tools-team", "main": "dist/index.js", diff --git a/packages/environment-check/CHANGELOG.md b/packages/environment-check/CHANGELOG.md index e3f9eadfbc..d3c0617841 100644 --- a/packages/environment-check/CHANGELOG.md +++ b/packages/environment-check/CHANGELOG.md @@ -1,5 +1,13 @@ # @sap-ux/environment-check +## 0.17.72 + +### Patch Changes + +- Updated dependencies [df2d965] + - @sap-ux/btp-utils@0.18.0 + - @sap-ux/axios-extension@1.18.3 + ## 0.17.71 ### Patch Changes diff --git a/packages/environment-check/package.json b/packages/environment-check/package.json index eb522572f8..f85b3d8a2f 100644 --- a/packages/environment-check/package.json +++ b/packages/environment-check/package.json @@ -1,6 +1,6 @@ { "name": "@sap-ux/environment-check", - "version": "0.17.71", + "version": "0.17.72", "description": "SAP Fiori environment check", "license": "Apache-2.0", "bin": { diff --git a/packages/fiori-elements-writer/CHANGELOG.md b/packages/fiori-elements-writer/CHANGELOG.md index bb105bffbb..d848475595 100644 --- a/packages/fiori-elements-writer/CHANGELOG.md +++ b/packages/fiori-elements-writer/CHANGELOG.md @@ -1,5 +1,12 @@ # @sap-ux/fiori-elements-writer +## 2.0.6 + +### Patch Changes + +- @sap-ux/fiori-generator-shared@0.7.22 +- @sap-ux/cap-config-writer@0.9.1 + ## 2.0.5 ### Patch Changes diff --git a/packages/fiori-elements-writer/package.json b/packages/fiori-elements-writer/package.json index 45968d7fb9..e261d3a4d1 100644 --- a/packages/fiori-elements-writer/package.json +++ b/packages/fiori-elements-writer/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/fiori-elements-writer", "description": "SAP Fiori elements application writer", - "version": "2.0.5", + "version": "2.0.6", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/fiori-freestyle-writer/CHANGELOG.md b/packages/fiori-freestyle-writer/CHANGELOG.md index 38b00abd5b..9e2a4f25b4 100644 --- a/packages/fiori-freestyle-writer/CHANGELOG.md +++ b/packages/fiori-freestyle-writer/CHANGELOG.md @@ -1,5 +1,12 @@ # @sap-ux/fiori-freestyle-writer +## 2.0.5 + +### Patch Changes + +- @sap-ux/fiori-generator-shared@0.7.22 +- @sap-ux/cap-config-writer@0.9.1 + ## 2.0.4 ### Patch Changes diff --git a/packages/fiori-freestyle-writer/package.json b/packages/fiori-freestyle-writer/package.json index 3b18bc26a0..ac15f9f33f 100644 --- a/packages/fiori-freestyle-writer/package.json +++ b/packages/fiori-freestyle-writer/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/fiori-freestyle-writer", "description": "SAP Fiori freestyle application writer", - "version": "2.0.4", + "version": "2.0.5", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/fiori-generator-shared/CHANGELOG.md b/packages/fiori-generator-shared/CHANGELOG.md index fad108865c..3451d65fbc 100644 --- a/packages/fiori-generator-shared/CHANGELOG.md +++ b/packages/fiori-generator-shared/CHANGELOG.md @@ -1,5 +1,13 @@ # @sap-ux/fiori-generator-shared +## 0.7.22 + +### Patch Changes + +- Updated dependencies [df2d965] + - @sap-ux/btp-utils@0.18.0 + - @sap-ux/telemetry@0.5.54 + ## 0.7.21 ### Patch Changes diff --git a/packages/fiori-generator-shared/package.json b/packages/fiori-generator-shared/package.json index 6e46af28d1..d86ef8dca0 100644 --- a/packages/fiori-generator-shared/package.json +++ b/packages/fiori-generator-shared/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/fiori-generator-shared", "description": "Commonly used shared functionality and types to support the fiori generator.", - "version": "0.7.21", + "version": "0.7.22", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/flp-config-inquirer/CHANGELOG.md b/packages/flp-config-inquirer/CHANGELOG.md index d2d535bc92..02dea1ed22 100644 --- a/packages/flp-config-inquirer/CHANGELOG.md +++ b/packages/flp-config-inquirer/CHANGELOG.md @@ -1,5 +1,15 @@ # @sap-ux/flp-config-inquirer +## 0.2.23 + +### Patch Changes + +- Updated dependencies [df2d965] + - @sap-ux/btp-utils@0.18.0 + - @sap-ux/adp-tooling@0.12.117 + - @sap-ux/fiori-generator-shared@0.7.22 + - @sap-ux/inquirer-common@0.6.8 + ## 0.2.22 ### Patch Changes diff --git a/packages/flp-config-inquirer/package.json b/packages/flp-config-inquirer/package.json index 4a3a74b072..13e45c3c56 100644 --- a/packages/flp-config-inquirer/package.json +++ b/packages/flp-config-inquirer/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/flp-config-inquirer", "description": "Prompts module that can prompt users for inputs required for FLP configuration", - "version": "0.2.22", + "version": "0.2.23", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/flp-config-sub-generator/CHANGELOG.md b/packages/flp-config-sub-generator/CHANGELOG.md index b1c6dd6f4b..9f9dbb7efa 100644 --- a/packages/flp-config-sub-generator/CHANGELOG.md +++ b/packages/flp-config-sub-generator/CHANGELOG.md @@ -1,5 +1,15 @@ # @sap-ux/flp-config-sub-generator +## 0.0.24 + +### Patch Changes + +- @sap-ux/app-config-writer@0.5.20 +- @sap-ux/deploy-config-generator-shared@0.0.14 +- @sap-ux/fiori-generator-shared@0.7.22 +- @sap-ux/flp-config-inquirer@0.2.23 +- @sap-ux/inquirer-common@0.6.8 + ## 0.0.23 ### Patch Changes diff --git a/packages/flp-config-sub-generator/package.json b/packages/flp-config-sub-generator/package.json index 4f3c48600a..23fa5cc405 100644 --- a/packages/flp-config-sub-generator/package.json +++ b/packages/flp-config-sub-generator/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/flp-config-sub-generator", "description": "Generator for creating Fiori Launcpad configuration", - "version": "0.0.23", + "version": "0.0.24", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/inquirer-common/CHANGELOG.md b/packages/inquirer-common/CHANGELOG.md index 3efc29bb8b..dec4927317 100644 --- a/packages/inquirer-common/CHANGELOG.md +++ b/packages/inquirer-common/CHANGELOG.md @@ -1,5 +1,14 @@ # @sap-ux/inquirer-common +## 0.6.8 + +### Patch Changes + +- Updated dependencies [df2d965] + - @sap-ux/btp-utils@0.18.0 + - @sap-ux/fiori-generator-shared@0.7.22 + - @sap-ux/telemetry@0.5.54 + ## 0.6.7 ### Patch Changes diff --git a/packages/inquirer-common/package.json b/packages/inquirer-common/package.json index b7b67e69e8..c91a80d960 100644 --- a/packages/inquirer-common/package.json +++ b/packages/inquirer-common/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/inquirer-common", "description": "Commonly used shared functionality and types to support inquirer modules.", - "version": "0.6.7", + "version": "0.6.8", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/nodejs-utils/CHANGELOG.md b/packages/nodejs-utils/CHANGELOG.md index f84ac7a8d6..804682e820 100644 --- a/packages/nodejs-utils/CHANGELOG.md +++ b/packages/nodejs-utils/CHANGELOG.md @@ -1,5 +1,12 @@ # @sap-ux/nodejs-utils +## 0.1.5 + +### Patch Changes + +- Updated dependencies [df2d965] + - @sap-ux/btp-utils@0.18.0 + ## 0.1.4 ### Patch Changes diff --git a/packages/nodejs-utils/package.json b/packages/nodejs-utils/package.json index 48e3315120..0ee27835b1 100644 --- a/packages/nodejs-utils/package.json +++ b/packages/nodejs-utils/package.json @@ -1,6 +1,6 @@ { "name": "@sap-ux/nodejs-utils", - "version": "0.1.4", + "version": "0.1.5", "description": "Nodejs utility wrappers", "repository": { "type": "git", diff --git a/packages/odata-service-inquirer/CHANGELOG.md b/packages/odata-service-inquirer/CHANGELOG.md index 2d4c54fb34..bdd879f965 100644 --- a/packages/odata-service-inquirer/CHANGELOG.md +++ b/packages/odata-service-inquirer/CHANGELOG.md @@ -1,5 +1,16 @@ # @sap-ux/odata-service-inquirer +## 2.0.1 + +### Patch Changes + +- Updated dependencies [df2d965] + - @sap-ux/btp-utils@0.18.0 + - @sap-ux/axios-extension@1.18.3 + - @sap-ux/fiori-generator-shared@0.7.22 + - @sap-ux/inquirer-common@0.6.8 + - @sap-ux/telemetry@0.5.54 + ## 2.0.0 ### Major Changes diff --git a/packages/odata-service-inquirer/package.json b/packages/odata-service-inquirer/package.json index cd4b6cad47..0c8724674f 100644 --- a/packages/odata-service-inquirer/package.json +++ b/packages/odata-service-inquirer/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/odata-service-inquirer", "description": "Prompts module that can prompt users for inputs required for odata service writing", - "version": "2.0.0", + "version": "2.0.1", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/preview-middleware/CHANGELOG.md b/packages/preview-middleware/CHANGELOG.md index 4c1b353d00..474097e8bc 100644 --- a/packages/preview-middleware/CHANGELOG.md +++ b/packages/preview-middleware/CHANGELOG.md @@ -1,5 +1,13 @@ # @sap-ux/preview-middleware +## 0.17.5 + +### Patch Changes + +- Updated dependencies [df2d965] + - @sap-ux/btp-utils@0.18.0 + - @sap-ux/adp-tooling@0.12.117 + ## 0.17.4 ### Patch Changes diff --git a/packages/preview-middleware/package.json b/packages/preview-middleware/package.json index d40ce37ba9..2e5dcc3986 100644 --- a/packages/preview-middleware/package.json +++ b/packages/preview-middleware/package.json @@ -9,7 +9,7 @@ "bugs": { "url": "https://github.com/SAP/open-ux-tools/issues?q=is%3Aopen+is%3Aissue+label%3Abug+label%3Apreview-middleware" }, - "version": "0.17.4", + "version": "0.17.5", "license": "Apache-2.0", "author": "@SAP/ux-tools-team", "main": "dist/index.js", diff --git a/packages/reload-middleware/CHANGELOG.md b/packages/reload-middleware/CHANGELOG.md index b15de9dd91..1ea98df3c5 100644 --- a/packages/reload-middleware/CHANGELOG.md +++ b/packages/reload-middleware/CHANGELOG.md @@ -1,5 +1,12 @@ # @sap-ux/reload-middleware +## 0.2.14 + +### Patch Changes + +- Updated dependencies [df2d965] + - @sap-ux/btp-utils@0.18.0 + ## 0.2.13 ### Patch Changes diff --git a/packages/reload-middleware/package.json b/packages/reload-middleware/package.json index a13d3802d5..6b1b021915 100644 --- a/packages/reload-middleware/package.json +++ b/packages/reload-middleware/package.json @@ -9,7 +9,7 @@ "bugs": { "url": "https://github.com/SAP/open-ux-tools/issues?q=is%3Aopen+is%3Aissue+label%3Abug+label%3Areload-middleware" }, - "version": "0.2.13", + "version": "0.2.14", "author": "@SAP/ux-tools-team", "license": "Apache-2.0", "main": "dist/index.js", diff --git a/packages/system-access/CHANGELOG.md b/packages/system-access/CHANGELOG.md index eff7ba40e3..6fb1245c17 100644 --- a/packages/system-access/CHANGELOG.md +++ b/packages/system-access/CHANGELOG.md @@ -1,5 +1,13 @@ # @sap-ux/system-access +## 0.5.28 + +### Patch Changes + +- Updated dependencies [df2d965] + - @sap-ux/btp-utils@0.18.0 + - @sap-ux/axios-extension@1.18.3 + ## 0.5.27 ### Patch Changes diff --git a/packages/system-access/package.json b/packages/system-access/package.json index b68cf0bfd2..5d7fbf2edf 100644 --- a/packages/system-access/package.json +++ b/packages/system-access/package.json @@ -9,7 +9,7 @@ "bugs": { "url": "https://github.com/SAP/open-ux-tools/issues?q=is%3Aopen+is%3Aissue+label%3Abug+label%3Asystem-access" }, - "version": "0.5.27", + "version": "0.5.28", "license": "Apache-2.0", "author": "@SAP/ux-tools-team", "main": "dist/index.js", diff --git a/packages/telemetry/CHANGELOG.md b/packages/telemetry/CHANGELOG.md index 6e01388ec3..e2ffca7678 100644 --- a/packages/telemetry/CHANGELOG.md +++ b/packages/telemetry/CHANGELOG.md @@ -1,5 +1,12 @@ # @sap-ux/telemetry +## 0.5.54 + +### Patch Changes + +- Updated dependencies [df2d965] + - @sap-ux/btp-utils@0.18.0 + ## 0.5.53 ### Patch Changes diff --git a/packages/telemetry/package.json b/packages/telemetry/package.json index 96c4507e88..2977d052a7 100644 --- a/packages/telemetry/package.json +++ b/packages/telemetry/package.json @@ -1,6 +1,6 @@ { "name": "@sap-ux/telemetry", - "version": "0.5.53", + "version": "0.5.54", "description": "Library for sending usage telemetry data", "repository": { "type": "git", diff --git a/packages/ui5-application-inquirer/CHANGELOG.md b/packages/ui5-application-inquirer/CHANGELOG.md index d99280bcbb..9492175772 100644 --- a/packages/ui5-application-inquirer/CHANGELOG.md +++ b/packages/ui5-application-inquirer/CHANGELOG.md @@ -1,5 +1,11 @@ # @sap-ux/ui5-application-inquirer +## 0.9.8 + +### Patch Changes + +- @sap-ux/inquirer-common@0.6.8 + ## 0.9.7 ### Patch Changes diff --git a/packages/ui5-application-inquirer/package.json b/packages/ui5-application-inquirer/package.json index 46d97459f4..7d19c16e2b 100644 --- a/packages/ui5-application-inquirer/package.json +++ b/packages/ui5-application-inquirer/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/ui5-application-inquirer", "description": "Prompts module that can prompt users for inputs required for UI5 application writing", - "version": "0.9.7", + "version": "0.9.8", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/ui5-library-inquirer/CHANGELOG.md b/packages/ui5-library-inquirer/CHANGELOG.md index 9088c05b0f..62bf3b690d 100644 --- a/packages/ui5-library-inquirer/CHANGELOG.md +++ b/packages/ui5-library-inquirer/CHANGELOG.md @@ -1,5 +1,11 @@ # @sap-ux/ui5-library-inquirer +## 0.3.37 + +### Patch Changes + +- @sap-ux/inquirer-common@0.6.8 + ## 0.3.36 ### Patch Changes diff --git a/packages/ui5-library-inquirer/package.json b/packages/ui5-library-inquirer/package.json index cd90321762..dbad0d09fe 100644 --- a/packages/ui5-library-inquirer/package.json +++ b/packages/ui5-library-inquirer/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/ui5-library-inquirer", "description": "Prompts module that can provide prompts for UI5 library writer", - "version": "0.3.36", + "version": "0.3.37", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/ui5-library-reference-inquirer/CHANGELOG.md b/packages/ui5-library-reference-inquirer/CHANGELOG.md index 39e9759816..acea1a4c16 100644 --- a/packages/ui5-library-reference-inquirer/CHANGELOG.md +++ b/packages/ui5-library-reference-inquirer/CHANGELOG.md @@ -1,5 +1,11 @@ # @sap-ux/ui5-library-reference-inquirer +## 0.3.69 + +### Patch Changes + +- @sap-ux/inquirer-common@0.6.8 + ## 0.3.68 ### Patch Changes diff --git a/packages/ui5-library-reference-inquirer/package.json b/packages/ui5-library-reference-inquirer/package.json index 59fa428254..5cf1ea9354 100644 --- a/packages/ui5-library-reference-inquirer/package.json +++ b/packages/ui5-library-reference-inquirer/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/ui5-library-reference-inquirer", "description": "Prompts module that can provide prompts for UI5 library writer", - "version": "0.3.68", + "version": "0.3.69", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/ui5-library-reference-sub-generator/CHANGELOG.md b/packages/ui5-library-reference-sub-generator/CHANGELOG.md index 048c937526..31a2160c39 100644 --- a/packages/ui5-library-reference-sub-generator/CHANGELOG.md +++ b/packages/ui5-library-reference-sub-generator/CHANGELOG.md @@ -1,5 +1,13 @@ # @sap-ux/ui5-library-reference-sub-generator +## 0.0.29 + +### Patch Changes + +- @sap-ux/fiori-generator-shared@0.7.22 +- @sap-ux/telemetry@0.5.54 +- @sap-ux/ui5-library-reference-inquirer@0.3.69 + ## 0.0.28 ### Patch Changes diff --git a/packages/ui5-library-reference-sub-generator/package.json b/packages/ui5-library-reference-sub-generator/package.json index f7ee0a8306..03ef51df13 100644 --- a/packages/ui5-library-reference-sub-generator/package.json +++ b/packages/ui5-library-reference-sub-generator/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/ui5-library-reference-sub-generator", "description": "Generator for adding reference libraries to a project", - "version": "0.0.28", + "version": "0.0.29", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/ui5-library-sub-generator/CHANGELOG.md b/packages/ui5-library-sub-generator/CHANGELOG.md index 8c8541dd53..84a5275a4b 100644 --- a/packages/ui5-library-sub-generator/CHANGELOG.md +++ b/packages/ui5-library-sub-generator/CHANGELOG.md @@ -1,5 +1,13 @@ # @sap-ux/ui5-library-sub-generator +## 0.0.51 + +### Patch Changes + +- @sap-ux/fiori-generator-shared@0.7.22 +- @sap-ux/nodejs-utils@0.1.5 +- @sap-ux/ui5-library-inquirer@0.3.37 + ## 0.0.50 ### Patch Changes diff --git a/packages/ui5-library-sub-generator/package.json b/packages/ui5-library-sub-generator/package.json index 5e31f19cfc..d1ec438264 100644 --- a/packages/ui5-library-sub-generator/package.json +++ b/packages/ui5-library-sub-generator/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/ui5-library-sub-generator", "description": "Generator for creating UI5 libraries", - "version": "0.0.50", + "version": "0.0.51", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", From 1f98f073727dbe19feb644f8ebb6340780b6ae7b Mon Sep 17 00:00:00 2001 From: GDamyanov Date: Wed, 29 Jan 2025 16:01:24 +0200 Subject: [PATCH 11/17] feat: Add stable Ids in AddFragment and ControllerExtension forms (#2816) * feat: add stable ids * refactor: format xml * chore: add changeset * chore: format file --- .changeset/rude-dragons-speak.md | 6 +++++ .../src/adp/ui/AddFragment.fragment.xml | 25 ++++++++++++++----- .../adp/ui/ControllerExtension.fragment.xml | 1 + 3 files changed, 26 insertions(+), 6 deletions(-) create mode 100644 .changeset/rude-dragons-speak.md diff --git a/.changeset/rude-dragons-speak.md b/.changeset/rude-dragons-speak.md new file mode 100644 index 0000000000..c26c9d9058 --- /dev/null +++ b/.changeset/rude-dragons-speak.md @@ -0,0 +1,6 @@ +--- +'@sap-ux-private/preview-middleware-client': patch +'@sap-ux/preview-middleware': patch +--- + +Add stable ids in AddFragment and ControllerExtension forms diff --git a/packages/preview-middleware-client/src/adp/ui/AddFragment.fragment.xml b/packages/preview-middleware-client/src/adp/ui/AddFragment.fragment.xml index 2c8f137b54..868acae326 100644 --- a/packages/preview-middleware-client/src/adp/ui/AddFragment.fragment.xml +++ b/packages/preview-middleware-client/src/adp/ui/AddFragment.fragment.xml @@ -1,9 +1,11 @@