diff --git a/.changeset/popular-students-wonder.md b/.changeset/popular-students-wonder.md new file mode 100644 index 00000000000..ad5ff7d9083 --- /dev/null +++ b/.changeset/popular-students-wonder.md @@ -0,0 +1,5 @@ +--- +'@sap-ux/ui5-library-writer': patch +--- + +add versioning to ui5 lib templates, update deprecated code diff --git a/examples/odata-cli/CHANGELOG.md b/examples/odata-cli/CHANGELOG.md index 16acdc3e308..f2bcfdb001e 100644 --- a/examples/odata-cli/CHANGELOG.md +++ b/examples/odata-cli/CHANGELOG.md @@ -1,5 +1,16 @@ # @sap-ux/odata-cli +## 0.16.0 + +### Minor Changes + +- 2e3c15e: Proper check for cloud ABAP systems + +### Patch Changes + +- Updated dependencies [2e3c15e] + - @sap-ux/axios-extension@1.18.0 + ## 0.15.16 ### Patch Changes diff --git a/examples/odata-cli/package.json b/examples/odata-cli/package.json index ad18dfa3b46..48df85813b9 100644 --- a/examples/odata-cli/package.json +++ b/examples/odata-cli/package.json @@ -1,6 +1,6 @@ { "name": "@sap-ux/odata-cli", - "version": "0.15.16", + "version": "0.16.0", "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/odata-cli/src/activities.ts b/examples/odata-cli/src/activities.ts index 5920a3ec7bd..ee98bbd5d89 100644 --- a/examples/odata-cli/src/activities.ts +++ b/examples/odata-cli/src/activities.ts @@ -200,7 +200,7 @@ export async function testUiServiceGenerator( TEST_TRANSPORT: string; } ): Promise { - const s4Cloud = await provider.isS4Cloud(); + const s4Cloud = await provider.isAbapCloud(); if (!s4Cloud) { logger.warn('Not an S/4 Cloud system. UI service generation might not be supported.'); } diff --git a/examples/simple-generator/CHANGELOG.md b/examples/simple-generator/CHANGELOG.md index 8f7058cf010..f3601bc4407 100644 --- a/examples/simple-generator/CHANGELOG.md +++ b/examples/simple-generator/CHANGELOG.md @@ -1,5 +1,20 @@ # @sap-ux/generator-simple-fe +## 1.0.103 + +### Patch Changes + +- Updated dependencies [2e3c15e] + - @sap-ux/axios-extension@1.18.0 + - @sap-ux/system-access@0.5.25 + +## 1.0.102 + +### Patch Changes + +- @sap-ux/fiori-elements-writer@1.3.42 +- @sap-ux/fiori-freestyle-writer@1.2.38 + ## 1.0.101 ### Patch Changes diff --git a/examples/simple-generator/package.json b/examples/simple-generator/package.json index c833d71b743..5aa51f42b48 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.101", + "version": "1.0.103", "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 9e519dabde2..1201aa873c1 100644 --- a/packages/abap-deploy-config-inquirer/CHANGELOG.md +++ b/packages/abap-deploy-config-inquirer/CHANGELOG.md @@ -1,5 +1,21 @@ # @sap-ux/abap-deploy-config-inquirer +## 1.1.18 + +### Patch Changes + +- Updated dependencies [dac696a] + - @sap-ux/guided-answers-helper@0.2.0 + - @sap-ux/inquirer-common@0.6.2 + +## 1.1.17 + +### Patch Changes + +- Updated dependencies [2e3c15e] + - @sap-ux/axios-extension@1.18.0 + - @sap-ux/system-access@0.5.25 + ## 1.1.16 ### Patch Changes diff --git a/packages/abap-deploy-config-inquirer/package.json b/packages/abap-deploy-config-inquirer/package.json index 4e0ca90b64e..247882e3acd 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.1.16", + "version": "1.1.18", "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 8900bf9a614..3dd02e164ce 100644 --- a/packages/abap-deploy-config-sub-generator/CHANGELOG.md +++ b/packages/abap-deploy-config-sub-generator/CHANGELOG.md @@ -1,5 +1,19 @@ # @sap-ux/abap-deploy-config-sub-generator +## 0.0.10 + +### Patch Changes + +- @sap-ux/abap-deploy-config-inquirer@1.1.18 + +## 0.0.9 + +### Patch Changes + +- @sap-ux/abap-deploy-config-inquirer@1.1.17 +- @sap-ux/deploy-config-generator-shared@0.0.9 +- @sap-ux/abap-deploy-config-writer@0.0.72 + ## 0.0.8 ### Patch Changes diff --git a/packages/abap-deploy-config-sub-generator/package.json b/packages/abap-deploy-config-sub-generator/package.json index eb3feda3ba9..7cb9233bff0 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.8", + "version": "0.0.10", "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 a594beb7428..e8d1491fd44 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.72 + +### Patch Changes + +- @sap-ux/system-access@0.5.25 + ## 0.0.71 ### Patch Changes diff --git a/packages/abap-deploy-config-writer/package.json b/packages/abap-deploy-config-writer/package.json index 8ca56d8f15d..5127f2c537a 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.71", + "version": "0.0.72", "license": "Apache-2.0", "main": "dist/index.js", "scripts": { diff --git a/packages/adp-tooling/CHANGELOG.md b/packages/adp-tooling/CHANGELOG.md index 46f0bfeebf0..5c501b9d157 100644 --- a/packages/adp-tooling/CHANGELOG.md +++ b/packages/adp-tooling/CHANGELOG.md @@ -1,5 +1,20 @@ # @sap-ux/adp-tooling +## 0.12.103 + +### Patch Changes + +- Updated dependencies [dac696a] + - @sap-ux/inquirer-common@0.6.2 + +## 0.12.102 + +### Patch Changes + +- Updated dependencies [2e3c15e] + - @sap-ux/axios-extension@1.18.0 + - @sap-ux/system-access@0.5.25 + ## 0.12.101 ### Patch Changes diff --git a/packages/adp-tooling/package.json b/packages/adp-tooling/package.json index 6cd62546c07..2f01b11e401 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.101", + "version": "0.12.103", "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 0665a80cdb7..f5b7e1f4166 100644 --- a/packages/app-config-writer/CHANGELOG.md +++ b/packages/app-config-writer/CHANGELOG.md @@ -1,5 +1,18 @@ # @sap-ux/app-config-writer +## 0.5.11 + +### Patch Changes + +- Updated dependencies [2e3c15e] + - @sap-ux/axios-extension@1.18.0 + +## 0.5.10 + +### Patch Changes + +- d964a24: feat: add option to convert test runners to preview-config command + ## 0.5.9 ### Patch Changes diff --git a/packages/app-config-writer/package.json b/packages/app-config-writer/package.json index b9c8913673e..cfa22a2cdac 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.9", + "version": "0.5.11", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", @@ -40,7 +40,8 @@ "i18next": "20.6.1", "mem-fs": "2.1.0", "mem-fs-editor": "9.4.0", - "prompts": "2.4.2" + "prompts": "2.4.2", + "semver": "7.6.3" }, "devDependencies": { "@sap-ux/preview-middleware": "workspace:*", @@ -48,6 +49,7 @@ "@types/mem-fs": "1.1.2", "@types/mem-fs-editor": "7.0.1", "@types/prompts": "2.4.4", + "@types/semver": "7.5.8", "axios": "1.7.4", "nock": "13.4.0" }, diff --git a/packages/app-config-writer/src/preview-config/index.ts b/packages/app-config-writer/src/preview-config/index.ts index 540f3439423..f32f2062f14 100644 --- a/packages/app-config-writer/src/preview-config/index.ts +++ b/packages/app-config-writer/src/preview-config/index.ts @@ -1,8 +1,8 @@ import { checkPrerequisites, getExplicitApprovalToAdjustFiles } from './prerequisites'; import { create as createStorage } from 'mem-fs'; import { create, type Editor } from 'mem-fs-editor'; -import { deleteNoLongerUsedFiles, renameDefaultSandboxes } from './preview-files'; -import { updatePreviewMiddlewareConfigs } from './ui5-yaml'; +import { deleteNoLongerUsedFiles, renameDefaultSandboxes, renameDefaultTestFiles } from './preview-files'; +import { updatePreviewMiddlewareConfigs, updateDefaultTestConfig } from './ui5-yaml'; import { updateVariantsCreationScript } from './package-json'; import { type ToolsLogger } from '@sap-ux/logger'; @@ -14,14 +14,19 @@ import { type ToolsLogger } from '@sap-ux/logger'; * Corresponding files which are used for the preview are renamed or deleted. * * @param basePath - base path to be used for the conversion - * @param logger logger to report info to the user - * @param fs - file system reference + * @param options - options for the conversion + * @param options.convertTests - if set to true, then test suite and test runners fill be included in the conversion + * @param options.logger - logger to report info to the user + * @param options.fs - file system reference * @returns file system reference */ -export async function convertToVirtualPreview(basePath: string, logger?: ToolsLogger, fs?: Editor): Promise { - if (!fs) { - fs = create(createStorage()); - } +export async function convertToVirtualPreview( + basePath: string, + options: { convertTests?: boolean; logger?: ToolsLogger; fs?: Editor } +): Promise { + const fs = options.fs ?? create(createStorage()); + const logger = options.logger; + const convertTests = options.convertTests ?? false; if (!(await checkPrerequisites(basePath, fs, logger))) { throw Error('The prerequisites are not met. For more information, see the log messages above.'); @@ -32,8 +37,12 @@ export async function convertToVirtualPreview(basePath: string, logger?: ToolsLo return fs; } - await updatePreviewMiddlewareConfigs(fs, basePath, logger); + await updatePreviewMiddlewareConfigs(fs, basePath, convertTests, logger); await renameDefaultSandboxes(fs, basePath, logger); + if (convertTests) { + await renameDefaultTestFiles(fs, basePath, logger); + await updateDefaultTestConfig(fs, basePath, logger); + } await deleteNoLongerUsedFiles(fs, basePath, logger); await updateVariantsCreationScript(fs, basePath, logger); diff --git a/packages/app-config-writer/src/preview-config/package-json.ts b/packages/app-config-writer/src/preview-config/package-json.ts index fdbb0d4160c..1b01ad5e2d4 100644 --- a/packages/app-config-writer/src/preview-config/package-json.ts +++ b/packages/app-config-writer/src/preview-config/package-json.ts @@ -1,5 +1,5 @@ import { basename, join } from 'path'; -import { extractYamlConfigFileName } from './ui5-yaml'; +import { extractYamlConfigFileName, isTestPath } from './ui5-yaml'; import { generateVariantsConfig } from '../variants-config'; import type { Editor } from 'mem-fs-editor'; import type { ToolsLogger } from '@sap-ux/logger'; @@ -49,8 +49,9 @@ export function extractUrlDetails(script: string): { intent: FlpConfig['intent'] | undefined; } { //extract the URL from the 'open' command of the script - let url = / (?:--open|-o|--o) ([^"]?\S*)/.exec(script)?.[1] ?? undefined; - url = url?.startsWith('"') ? url.slice(1) : url; + let url = / (?:--open|-o|--o) (\S*)/.exec(script)?.[1] ?? undefined; + //delete double or single quotes from the URL + url = url?.replace(/['"]/g, ''); //extract the path from the URL const path = /^[^?#]+\.html/.exec(url ?? '')?.[0] ?? undefined; @@ -83,20 +84,25 @@ export function extractUrlDetails(script: string): { * * @param scriptName - the name of the script from the package.json file * @param script - the content of the script from the package.json file + * @param convertTests - indicator if test suite and test runner should be included in the conversion (default: false) * @returns indicator if the script is valid */ -export function isValidPreviewScript(scriptName: string, script: string | undefined): boolean { +export function isValidPreviewScript( + scriptName: string, + script: string | undefined, + convertTests: boolean = false +): boolean { const isValidScriptName = scriptName != 'start-variants-management' && scriptName != 'start-control-property-editor'; //eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const startsWebServer = !!(script?.includes('ui5 serve') || script?.includes('fiori run')); - const { path } = extractUrlDetails(script ?? ''); - const opensTest = path?.includes('qunit.html'); + const opensTest = isTestPath(path); const opensIndexHtml = path === 'index.html'; - return isValidScriptName && startsWebServer && !opensTest && !opensIndexHtml; + //tests are only relevant if the conversion of test runners is excluded + return isValidScriptName && startsWebServer && !opensIndexHtml && (convertTests ? true : !opensTest); } /** diff --git a/packages/app-config-writer/src/preview-config/prerequisites.ts b/packages/app-config-writer/src/preview-config/prerequisites.ts index 06fa58223ba..88a626c330f 100644 --- a/packages/app-config-writer/src/preview-config/prerequisites.ts +++ b/packages/app-config-writer/src/preview-config/prerequisites.ts @@ -4,6 +4,29 @@ import type { Editor } from 'mem-fs-editor'; import type { Package } from '@sap-ux/project-access'; import type { PromptObject } from 'prompts'; import type { ToolsLogger } from '@sap-ux/logger'; +import { satisfies } from 'semver'; + +/** + * Check if the version of the given package is lower than the minimal version. + * + * @param packageJson - the package.json file content + * @param dependencyName - the name of the (dev)dependency to check + * @param minVersionInfo - the minimal version to check against + * @param mandatory - (default true) if the existence of the dependency is mandatory + * @returns indicator if the version is lower than the minimal version + */ +function isLowerThanMinimalVersion( + packageJson: Package, + dependencyName: string, + minVersionInfo: string, + mandatory: boolean = true +): boolean { + const versionInfo = packageJson?.devDependencies?.[dependencyName] ?? packageJson?.dependencies?.[dependencyName]; + if (!versionInfo) { + return mandatory; + } + return !satisfies(minVersionInfo, versionInfo); +} /** * Check if the prerequisites for the conversion are met. @@ -35,14 +58,20 @@ export async function checkPrerequisites(basePath: string, fs: Editor, logger?: prerequisitesMet = false; } - const ui5CliVersion = packageJson?.devDependencies?.['@ui5/cli'] ?? packageJson?.dependencies?.['@ui5/cli'] ?? '0'; - if (parseInt(ui5CliVersion.split('.')[0], 10) < 3) { + if (isLowerThanMinimalVersion(packageJson, '@ui5/cli', '3.0.0')) { logger?.error( 'UI5 CLI version 3.0.0 or higher is required to convert the preview to virtual files. For more information, see https://sap.github.io/ui5-tooling/v3/updates/migrate-v3.' ); prerequisitesMet = false; } + if (isLowerThanMinimalVersion(packageJson, '@sap/ux-ui5-tooling', '1.15.4', false)) { + logger?.error( + 'UX UI5 Tooling version 1.15.4 or higher is required to convert the preview to virtual files. For more information, see https://www.npmjs.com/package/@sap/ux-ui5-tooling.' + ); + prerequisitesMet = false; + } + const ui5MiddlewareMockserverExists = !!packageJson?.devDependencies?.['@sap-ux/ui5-middleware-fe-mockserver'] || !!packageJson?.dependencies?.['@sap-ux/ui5-middleware-fe-mockserver']; @@ -69,7 +98,7 @@ export async function getExplicitApprovalToAdjustFiles(): Promise { name: 'approval', initial: false, message: - 'The converter will rename the HTML files and delete the JS and TS files used for the existing preview functionality and configure virtual files instead. Do you want to proceed with the conversion?' + 'The converter will rename the HTML files and delete the JS and TS files used for the existing preview functionality and configure virtual endpoints instead. Do you want to proceed with the conversion?' }; return Boolean((await prompt([question])).approval); } diff --git a/packages/app-config-writer/src/preview-config/preview-files.ts b/packages/app-config-writer/src/preview-config/preview-files.ts index add52207075..d82e29d6eb4 100644 --- a/packages/app-config-writer/src/preview-config/preview-files.ts +++ b/packages/app-config-writer/src/preview-config/preview-files.ts @@ -2,12 +2,13 @@ import { basename, join } from 'path'; import { getWebappPath } from '@sap-ux/project-access'; import type { Editor } from 'mem-fs-editor'; import type { ToolsLogger } from '@sap-ux/logger'; +import { TEST_CONFIG_DEFAULTS } from './ui5-yaml'; const renameMessage = (filename: string): string => `Renamed '${filename}' to '${filename.slice( 0, -5 - )}_old.html'. This file is no longer needed for the preview functionality. If you have not modified this file, you can delete it. If you have modified this file, move the modified content to a custom init script for the preview middleware. For more information, see https://www.npmjs.com/package/preview-middleware#migration.`; + )}_old.html'. This file is no longer needed for the preview functionality. If you have not modified this file, you can delete it. If you have modified this file, move the modified content to a custom init script for the preview middleware. For more information, see https://github.com/SAP/open-ux-tools/tree/main/packages/preview-middleware#migration.`; /** * Renames the sandbox file which is used in a given script. @@ -32,7 +33,7 @@ export async function renameSandbox(fs: Editor, path: string, logger?: ToolsLogg ) { logger?.debug(`The file '${basename(path)}', has already been renamed. Skipping renaming.`); } else { - logger?.warn(`The file '${basename(path)}', has not been found. Skipping renaming.`); + logger?.info(`The file '${basename(path)}', has not been found. Skipping renaming.`); } } @@ -53,6 +54,21 @@ export async function renameDefaultSandboxes(fs: Editor, basePath: string, logge } } +/** + * Renames the default test suite and runner files. + * + * The default files are 'testsuite.qunit.html', 'integration/opaTests.qunit.html' and 'unit/unitTests.qunit.html' located under webapp/test. + * + * @param fs - file system reference + * @param basePath - base path to be used for the conversion + * @param logger logger to report info to the user + */ +export async function renameDefaultTestFiles(fs: Editor, basePath: string, logger?: ToolsLogger): Promise { + for (const path of Object.values(TEST_CONFIG_DEFAULTS).map((config) => config.path)) { + await renameSandbox(fs, join(await getWebappPath(basePath), path), logger); + } +} + /** * Deletes the *.js and *.ts files which are no longer used for the virtual preview. * diff --git a/packages/app-config-writer/src/preview-config/ui5-yaml.ts b/packages/app-config-writer/src/preview-config/ui5-yaml.ts index 1fa9593c5c8..9220df78f3a 100644 --- a/packages/app-config-writer/src/preview-config/ui5-yaml.ts +++ b/packages/app-config-writer/src/preview-config/ui5-yaml.ts @@ -10,11 +10,16 @@ import type { FlpConfig, MiddlewareConfig as PreviewConfig, DefaultFlpPath, - DefaultIntent + DefaultIntent, + TestConfigDefaults as PreviewTestConfigDefaults } from '@sap-ux/preview-middleware'; import type { PreviewConfigOptions } from '../types'; import type { ToolsLogger } from '@sap-ux/logger'; +type ArrayElement = ArrayType[number]; + +type PreviewTestConfig = ArrayElement['test']>; + const DEFAULT_FLP_PATH: DefaultFlpPath = '/test/flp.html'; const DEFAULT_INTENT: DefaultIntent = { @@ -22,6 +27,29 @@ const DEFAULT_INTENT: DefaultIntent = { action: 'preview' }; +export const TEST_CONFIG_DEFAULTS: Record>> = { + qunit: { + path: '/test/unitTests.qunit.html', + framework: 'QUnit' + }, + opa5: { + path: '/test/opaTests.qunit.html', + framework: 'OPA5' + }, + testsuite: { + path: '/test/testsuite.qunit.html', + framework: 'Testsuite' + } +} as Omit< + PreviewTestConfigDefaults, + | PreviewTestConfigDefaults['testsuite']['init'] + | PreviewTestConfigDefaults['testsuite']['pattern'] + | PreviewTestConfigDefaults['opa5']['init'] + | PreviewTestConfigDefaults['opa5']['pattern'] + | PreviewTestConfigDefaults['qunit']['init'] + | PreviewTestConfigDefaults['qunit']['pattern'] +>; + /** * Checks if a script can be converted based on the used UI5 yaml configuration file. * @@ -58,41 +86,37 @@ function isUi5YamlToBeConverted( * @param ui5Yaml - the name of the UI5 yaml configuration file * @param scriptName - the name of the script from the package.json file * @param script - the content of the script from the package.json file + * @param convertTests - indicator if test suite and test runner should be included in the conversion * @param logger logger to report info to the user * @returns indicator if the UI5 yaml configuration file has already been converted */ -async function isUi5YamlAlreadyConverted( +async function isUi5YamlFlpPathAlreadyConverted( fs: Editor, basePath: string, ui5Yaml: string, scriptName: string, script: string, + convertTests: boolean, logger?: ToolsLogger ): Promise { - if ( + const yamlConfigAlreadyAdjusted = Object.keys( fs.dump(basePath, (file) => { return file.basename === ui5Yaml && file.state === 'modified'; }) - ).length === 0 - ) { - return false; - } + ).length > 0; const flpPath = ((await getPreviewMiddleware(undefined, basePath, ui5Yaml, fs)) as CustomMiddleware) ?.configuration?.flp?.path; const { path: scriptPath } = extractUrlDetails(script); - if (flpPath != scriptPath) { + if (yamlConfigAlreadyAdjusted && flpPath != scriptPath && (convertTests ? !isTestPath(scriptPath) : true)) { logger?.warn( - `Skipping script'${scriptName}', because another script also refers to UI5 YAML configuration file, '${ui5Yaml}'. Adjust the 'flp.path' property in the UI5 YAML configuration file to the correct endpoint or create a separate UI5 YAML configuration file for script '${scriptName}'. ${ui5Yaml} currently uses ${ + `Skipping script '${scriptName}', because another script also refers to UI5 YAML configuration file, '${ui5Yaml}'. Adjust the 'flp.path' property in the UI5 YAML configuration file to the correct endpoint or create a separate UI5 YAML configuration file for script '${scriptName}'. ${ui5Yaml} currently uses ${ flpPath ?? DEFAULT_FLP_PATH } whereas script '${scriptName}' uses '${scriptPath}'.` ); - } else { - logger?.info( - `Skipping script '${scriptName}', because the UI5 YAML configuration file '${ui5Yaml}' has already been adjusted based on another script.` - ); + return true; } - return true; + return false; } /** @@ -102,14 +126,31 @@ async function isUi5YamlAlreadyConverted( * @param configuration - the preview configuration * @returns indicator if the path is an FLP path */ -function pathIsFlpPath(path: string | undefined, configuration: PreviewConfig): boolean { +function isFlpPath(path: string | undefined, configuration: PreviewConfig): boolean { if (!path) { return false; } - const isNotRtaEditorPath = configuration.rta?.editors?.every((editor) => editor.path !== path) ?? true; - const isNotTestPath = configuration.test?.every((test) => test.path !== path) ?? true; + const isRtaEditorPath = configuration.rta?.editors?.some((editor) => editor.path === path) ?? false; + return !isRtaEditorPath && !isTestPath(path, configuration); +} - return isNotRtaEditorPath && isNotTestPath; +/** + * Check if the path is a test path. + * 1) path matches pattern '**.qunit.html' + * 2) path is being used as test configuration path in yaml configuration. + * + * @param path - the path + * @param configuration - the preview configuration + * @returns indicator if the path is a test path + */ +export function isTestPath(path: string | undefined, configuration?: PreviewConfig): boolean { + if (!path) { + return false; + } + if (path.includes('.qunit.html')) { + return true; + } + return configuration?.test?.some((testConfig) => testConfig.path === path) ?? false; } /** @@ -214,20 +255,26 @@ export function updatePreviewMiddlewareConfig( //copy of configuration to avoid ending up with an empty configuration object in some cases const configuration = { ...newMiddlewareConfig.configuration }; - configuration.flp = configuration.flp ?? {}; let writeConfig = false; - //check path and respect defaults - if (pathIsFlpPath(path, configuration) && !path?.includes(DEFAULT_FLP_PATH)) { - configuration.flp.path = path; - writeConfig = true; - } - //check intent and respect defaults - if (intent && `${intent?.object}-${intent?.action}` !== defaultIntent) { - configuration.flp.intent = { - object: intent.object, - action: intent.action - }; + if (isFlpPath(path, configuration)) { + //adjust path but respect defaults + if (!path?.includes(DEFAULT_FLP_PATH)) { + configuration.flp = configuration.flp ?? {}; + configuration.flp.path = path; + writeConfig = true; + } + //adjust intent but respect defaults + if (intent && `${intent?.object}-${intent?.action}` !== defaultIntent) { + configuration.flp = configuration.flp ?? {}; + configuration.flp.intent = { + object: intent.object, + action: intent.action + }; + writeConfig = true; + } + } else if (isTestPath(path, configuration)) { + configuration.test = updateTestConfig(configuration.test, path); writeConfig = true; } @@ -238,6 +285,97 @@ export function updatePreviewMiddlewareConfig( return newMiddlewareConfig as CustomMiddleware; } +/** + * Update the test configuration. + * + * @param testConfiguration - the test configuration + * @param path - the path + * @returns the updated test configuration + */ +export function updateTestConfig( + testConfiguration: PreviewConfig['test'], + path: string | undefined +): PreviewConfig['test'] { + testConfiguration = testConfiguration ?? []; + + let framework: PreviewTestConfig['framework'] | undefined; + if (path?.includes('testsuite.qunit.html')) { + framework = 'Testsuite'; + } else if (path?.includes('opaTests.qunit.html')) { + framework = 'OPA5'; + } else if (path?.includes('unitTests.qunit.html')) { + framework = 'QUnit'; + } + + if (!framework) { + return testConfiguration; + } + + const defaultPath = TEST_CONFIG_DEFAULTS[framework.toLowerCase()].path; + const testConfig = testConfiguration.find((test) => test.framework === framework); + if (testConfig) { + testConfig.path = path; + if (testConfig.path === defaultPath) { + //sanitize default path + delete testConfig.path; + } + } else if (path?.includes(defaultPath)) { + testConfiguration.push({ framework }); + } else { + testConfiguration.push({ framework, path }); + } + return testConfiguration; +} + +/** + * Updates the default test configurations in the 'ui5.yaml' in case no test config exists in any UI5 configuration file. + * + * @param fs - file system reference + * @param basePath - base path to be used for the conversion + * @param logger logger to report info to the user + */ +export async function updateDefaultTestConfig(fs: Editor, basePath: string, logger?: ToolsLogger): Promise { + const ui5YamlFileNames = await getAllUi5YamlFileNames(basePath, fs); + for (const ui5Yaml of ui5YamlFileNames.filter((ui5Yaml) => ui5Yaml !== FileName.Ui5Yaml)) { + const ui5YamlConfig = await readUi5Yaml(basePath, ui5Yaml, fs); + const previewMiddleware = (await getPreviewMiddleware(ui5YamlConfig)) as CustomMiddleware; + if (previewMiddleware.configuration.test) { + return; + } + } + let ui5YamlConfig: UI5Config; + try { + ui5YamlConfig = await readUi5Yaml(basePath, FileName.Ui5Yaml, fs); + } catch (error) { + logger?.warn( + `The UI5 YAML configuration file 'ui5.yaml', can't be updated to support test frameworks: '${error}'. Please manually add the test configuration to the UI5 YAML configuration file used for testing according to https://github.com/SAP/open-ux-tools/tree/main/packages/preview-middleware#configuration-option-test.` + ); + return; + } + const previewMiddleware = (await getPreviewMiddleware(ui5YamlConfig)) as CustomMiddleware; + + for (const defaultConfig of Object.values(TEST_CONFIG_DEFAULTS)) { + if ( + previewMiddleware.configuration?.test?.some( + (testConfig) => testConfig.framework.toLowerCase() === defaultConfig.framework.toLowerCase() + ) + ) { + //do not touch existing test config + break; + } + previewMiddleware.configuration.test = updateTestConfig( + previewMiddleware.configuration.test, + defaultConfig.path + ); + logger?.info( + `The UI5 YAML configuration file 'ui5.yaml', has been updated to support the test framework '${defaultConfig.framework}'. Please consider transferring the test configuration to the UI5 YAML configuration file used for testing.` + ); + } + ui5YamlConfig.updateCustomMiddleware(previewMiddleware); + const yamlPath = join(basePath, FileName.Ui5Yaml); + fs.write(yamlPath, ui5YamlConfig.toString()); +} + /** * Updates the preview middleware configurations according to the scripts they are being used in package.json. * @@ -247,11 +385,13 @@ export function updatePreviewMiddlewareConfig( * * @param fs - file system reference * @param basePath - base path to be used for the conversion + * @param convertTests - indicator if test suite and test runner should be included in the conversion * @param logger logger to report info to the user */ export async function updatePreviewMiddlewareConfigs( fs: Editor, basePath: string, + convertTests: boolean, logger?: ToolsLogger ): Promise { const ui5YamlFileNames = await getAllUi5YamlFileNames(basePath, fs); @@ -259,7 +399,7 @@ export async function updatePreviewMiddlewareConfigs( const packageJsonPath = join(basePath, 'package.json'); const packageJson = fs.readJSON(packageJsonPath) as Package | undefined; for (const [scriptName, script] of Object.entries(packageJson?.scripts ?? {})) { - if (!script || !isValidPreviewScript(scriptName, script)) { + if (!script || !isValidPreviewScript(scriptName, script, convertTests)) { continue; } @@ -268,7 +408,7 @@ export async function updatePreviewMiddlewareConfigs( if ( !isUi5YamlToBeConverted(ui5Yaml, scriptName, ui5YamlFileNames, logger) || - (await isUi5YamlAlreadyConverted(fs, basePath, ui5Yaml, scriptName, script, logger)) + (await isUi5YamlFlpPathAlreadyConverted(fs, basePath, ui5Yaml, scriptName, script, convertTests, logger)) ) { continue; } diff --git a/packages/app-config-writer/test/fixtures/preview-config/various-configs/ui5-existing-preview-middleware.yaml b/packages/app-config-writer/test/fixtures/preview-config/various-configs/ui5-existing-preview-middleware.yaml index 81dd0eb835f..deef5fe0ade 100644 --- a/packages/app-config-writer/test/fixtures/preview-config/various-configs/ui5-existing-preview-middleware.yaml +++ b/packages/app-config-writer/test/fixtures/preview-config/various-configs/ui5-existing-preview-middleware.yaml @@ -14,9 +14,9 @@ server: action: dance test: - framework: OPA5 - path: /test/integration/opaTests.qunit.html + path: test/integration/opaTests.qunit.html - framework: QUnit - path: /test/unit/unitTests.qunit.html + path: test/unit/unitTests.qunit.html - framework: Testsuite rta: editors: diff --git a/packages/app-config-writer/test/unit/preview-config/__snapshots__/index.test.ts.snap b/packages/app-config-writer/test/unit/preview-config/__snapshots__/index.test.ts.snap new file mode 100644 index 00000000000..61f0143a296 --- /dev/null +++ b/packages/app-config-writer/test/unit/preview-config/__snapshots__/index.test.ts.snap @@ -0,0 +1,47 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`index convertToVirtualPreview convert project to virtual preview (including tests w/o own yaml config) 1`] = ` +"specVersion: '4.0' +metadata: +name: com.sap.cap.fe.ts.sample +server: + customMiddleware: + - name: preview-middleware + afterMiddleware: compression + configuration: + test: + - framework: Testsuite + path: yet/another/path.html + - framework: OPA5 + - framework: QUnit +" +`; + +exports[`index convertToVirtualPreview convert project to virtual preview (including tests with own yaml config) 1`] = ` +" + specVersion: '4.0' + metadata: + name: com.sap.cap.fe.ts.sample + server: + customMiddleware: + - name: preview-middleware + afterMiddleware: compression + " +`; + +exports[`index convertToVirtualPreview convert project to virtual preview (including tests with own yaml config) 2`] = ` +" + specVersion: '4.0' + metadata: + name: com.sap.cap.fe.ts.sample + server: + customMiddleware: + - name: preview-middleware + afterMiddleware: compression + configuration: + test: + - framework: \\"Testsuite\\" + path: \\"yet/another/path.html\\" + - framework: \\"OPA5\\" + " +`; diff --git a/packages/app-config-writer/test/unit/preview-config/__snapshots__/ui5-yaml.test.ts.snap b/packages/app-config-writer/test/unit/preview-config/__snapshots__/ui5-yaml.test.ts.snap index 93109feedee..a1f6835d00f 100644 --- a/packages/app-config-writer/test/unit/preview-config/__snapshots__/ui5-yaml.test.ts.snap +++ b/packages/app-config-writer/test/unit/preview-config/__snapshots__/ui5-yaml.test.ts.snap @@ -39,7 +39,7 @@ server: " `; -exports[`update preview middleware config default ui5.yaml w/o index.html 2`] = `"{\\"scripts\\":{\\"start\\":\\"fiori run --open \\\\\\"test/flpSandbox.html?sap-ui-xx-viewCache=false#v4lropconvert0711-tile\\\\\\"\\",\\"start-index\\":\\"fiori run --open \\\\\\"index.html?sap-ui-xx-viewCache=false#v4lropconvert0711-tile\\\\\\"\\"},\\"devDependencies\\":{\\"@sap/ux-ui5-tooling\\":\\"1.15.4\\"}}"`; +exports[`update preview middleware config default ui5.yaml w/o index.html 2`] = `"{\\"scripts\\":{\\"start\\":\\"fiori run --open \\\\\\"test/flpSandbox.html?sap-ui-xx-viewCache=false#v4lropconvert0711-tile\\\\\\"\\",\\"start-index\\":\\"fiori run --open \\\\\\"index.html?sap-ui-xx-viewCache=false#v4lropconvert0711-tile\\\\\\"\\",\\"start-index2\\":\\"fiori run --open 'index.html?sap-ui-xx-viewCache=false#v4lropconvert0711-tile'\\",\\"start-index3\\":\\"fiori run --open index.html?sap-ui-xx-viewCache=false#v4lropconvert0711-tile\\"},\\"devDependencies\\":{\\"@sap/ux-ui5-tooling\\":\\"1.15.4\\"}}"`; exports[`update preview middleware config deprecated tools preview w/o theme 1`] = ` "specVersion: \\"3.1\\" @@ -82,6 +82,32 @@ server: exports[`update preview middleware config deprecated tools preview with theme 2`] = `"{\\"scripts\\":{\\"ui:mockserver\\":\\"fiori run --open \\\\\\"test/flpSandbox.html?sap-ui-xx-viewCache=false#Chicken-dance\\\\\\" --config ./ui5-deprecated-tools-preview-theme.yaml\\",\\"start-variants-management\\":\\"ui5 serve --o chicken.html\\"},\\"devDependencies\\":{\\"@sap/ux-ui5-tooling\\":\\"1.15.1\\"}}"`; +exports[`update preview middleware config deprecated tools preview with theme and tests 1`] = ` +"specVersion: \\"3.1\\" +metadata: + name: v2lrop0909 +type: application +server: + customMiddleware: + - name: fiori-tools-preview + afterMiddleware: compression + configuration: + flp: + theme: sap_horizon + path: test/flpSandbox.html + intent: + object: Chicken + action: dance + test: + - framework: OPA5 + path: test/integration/opaTests.qunit.html + - framework: QUnit + path: test/unit/unitTests.qunit.html +" +`; + +exports[`update preview middleware config deprecated tools preview with theme and tests 2`] = `"{\\"scripts\\":{\\"ui:mockserver\\":\\"fiori run --open \\\\\\"test/flpSandbox.html?sap-ui-xx-viewCache=false#Chicken-dance\\\\\\" --config ./ui5-deprecated-tools-preview-theme.yaml\\",\\"start-variants-management\\":\\"ui5 serve --o chicken.html\\",\\"ui:opa5\\":\\"fiori run -o test/integration/opaTests.qunit.html?sap-ui-xx-viewCache=false#Chicken-dance --config ./ui5-deprecated-tools-preview-theme.yaml\\",\\"ui:unit\\":\\"fiori run -o test/unit/unitTests.qunit.html?sap-ui-xx-viewCache=false#Chicken-dance --config ./ui5-deprecated-tools-preview-theme.yaml\\"},\\"devDependencies\\":{\\"@sap/ux-ui5-tooling\\":\\"1.15.1\\"}}"`; + exports[`update preview middleware config existing RTA script 1`] = ` "specVersion: \\"3.1\\" metadata: @@ -99,9 +125,9 @@ server: action: dance test: - framework: OPA5 - path: /test/integration/opaTests.qunit.html + path: test/integration/opaTests.qunit.html - framework: QUnit - path: /test/unit/unitTests.qunit.html + path: test/unit/unitTests.qunit.html - framework: Testsuite rta: editors: @@ -128,9 +154,9 @@ server: action: dance test: - framework: OPA5 - path: /test/integration/opaTests.qunit.html + path: test/integration/opaTests.qunit.html - framework: QUnit - path: /test/unit/unitTests.qunit.html + path: test/unit/unitTests.qunit.html - framework: Testsuite rta: editors: @@ -140,6 +166,35 @@ server: exports[`update preview middleware config existing preview middleware 2`] = `"{\\"scripts\\":{\\"ui:mockserver\\":\\"fiori run -o localService/index.html?sap-ui-xx-viewCache=false#Chicken-dance --config ./ui5-existing-preview-middleware.yaml\\",\\"ui:opa5\\":\\"fiori run -o test/integration/opaTests.qunit.html?sap-ui-xx-viewCache=false#Chicken-dance --config ./ui5-existing-preview-middleware.yaml\\",\\"ui:unit\\":\\"fiori run -o test/unit/unitTests.qunit.html?sap-ui-xx-viewCache=false#Chicken-dance --config ./ui5-existing-preview-middleware.yaml\\"},\\"devDependencies\\":{\\"@sap-ux/preview-middleware\\":\\"0.16.102\\"}}"`; +exports[`update preview middleware config existing preview middleware with tests 1`] = ` +"specVersion: \\"3.1\\" +metadata: + name: v2lrop0909 +type: application +server: + customMiddleware: + - name: preview-middleware + afterMiddleware: compression + configuration: + flp: + path: localService/index.html + intent: + object: Chicken + action: dance + test: + - framework: OPA5 + path: test/integration/opaTests.qunit.html + - framework: QUnit + path: test/unit/unitTests.qunit.html + - framework: Testsuite + rta: + editors: + - path: preview.html +" +`; + +exports[`update preview middleware config existing preview middleware with tests 2`] = `"{\\"scripts\\":{\\"ui:mockserver\\":\\"fiori run -o localService/index.html?sap-ui-xx-viewCache=false#Chicken-dance --config ./ui5-existing-preview-middleware.yaml\\",\\"ui:opa5\\":\\"fiori run -o test/integration/opaTests.qunit.html?sap-ui-xx-viewCache=false#Chicken-dance --config ./ui5-existing-preview-middleware.yaml\\",\\"ui:unit\\":\\"fiori run -o test/unit/unitTests.qunit.html?sap-ui-xx-viewCache=false#Chicken-dance --config ./ui5-existing-preview-middleware.yaml\\"},\\"devDependencies\\":{\\"@sap-ux/preview-middleware\\":\\"0.16.102\\"}}"`; + exports[`update preview middleware config existing start-variants-management and start-control-property-editor script 1`] = ` "specVersion: \\"3.1\\" metadata: diff --git a/packages/app-config-writer/test/unit/preview-config/index.test.ts b/packages/app-config-writer/test/unit/preview-config/index.test.ts index 837869d60e4..b52736bf81c 100644 --- a/packages/app-config-writer/test/unit/preview-config/index.test.ts +++ b/packages/app-config-writer/test/unit/preview-config/index.test.ts @@ -1,6 +1,6 @@ import { create as createStorage } from 'mem-fs'; import { create, type Editor } from 'mem-fs-editor'; -import { convertToVirtualPreview } from '../../../src/preview-config'; +import { convertToVirtualPreview } from '../../../src'; import { join } from 'path'; import { ToolsLogger } from '@sap-ux/logger'; import * as packageJson from '../../../src/preview-config/package-json'; @@ -37,7 +37,81 @@ describe('index', () => { test('convert project to virtual preview', async () => { getExplicitApprovalToAdjustFilesSpy.mockResolvedValue(true); - await convertToVirtualPreview(basePath, logger, fs); + await convertToVirtualPreview(basePath, { convertTests: false, logger, fs }); + expect(checkPrerequisitesSpy).toHaveBeenCalled(); + expect(getExplicitApprovalToAdjustFilesSpy).toHaveBeenCalled(); + expect(updatePreviewMiddlewareConfigsSpy).toHaveBeenCalled(); + expect(renameDefaultSandboxesSpy).toHaveBeenCalled(); + expect(deleteNoLongerUsedFilesSpy).toHaveBeenCalled(); + expect(updateVariantsCreationScriptSpy).toHaveBeenCalled(); + }); + + test('convert project to virtual preview (including tests w/o own yaml config)', async () => { + fs.write( + join(basePath, 'ui5.yaml'), + ` + specVersion: '4.0' + metadata: + name: com.sap.cap.fe.ts.sample + server: + customMiddleware: + - name: preview-middleware + afterMiddleware: compression + configuration: + test: + - framework: "Testsuite" + path: "yet/another/path.html" + - framework: "OPA5" + ` + ); + + getExplicitApprovalToAdjustFilesSpy.mockResolvedValue(true); + + await convertToVirtualPreview(basePath, { convertTests: true, logger, fs }); + expect(fs.read(join(basePath, 'ui5.yaml'))).toMatchSnapshot(); + expect(checkPrerequisitesSpy).toHaveBeenCalled(); + expect(getExplicitApprovalToAdjustFilesSpy).toHaveBeenCalled(); + expect(updatePreviewMiddlewareConfigsSpy).toHaveBeenCalled(); + expect(renameDefaultSandboxesSpy).toHaveBeenCalled(); + expect(deleteNoLongerUsedFilesSpy).toHaveBeenCalled(); + expect(updateVariantsCreationScriptSpy).toHaveBeenCalled(); + }); + + test('convert project to virtual preview (including tests with own yaml config)', async () => { + fs.write( + join(basePath, 'ui5.yaml'), + ` + specVersion: '4.0' + metadata: + name: com.sap.cap.fe.ts.sample + server: + customMiddleware: + - name: preview-middleware + afterMiddleware: compression + ` + ); + fs.write( + join(basePath, 'ui5-test.yaml'), + ` + specVersion: '4.0' + metadata: + name: com.sap.cap.fe.ts.sample + server: + customMiddleware: + - name: preview-middleware + afterMiddleware: compression + configuration: + test: + - framework: "Testsuite" + path: "yet/another/path.html" + - framework: "OPA5" + ` + ); + getExplicitApprovalToAdjustFilesSpy.mockResolvedValue(true); + + await convertToVirtualPreview(basePath, { convertTests: true, logger, fs }); + expect(fs.read(join(basePath, 'ui5.yaml'))).toMatchSnapshot(); + expect(fs.read(join(basePath, 'ui5-test.yaml'))).toMatchSnapshot(); expect(checkPrerequisitesSpy).toHaveBeenCalled(); expect(getExplicitApprovalToAdjustFilesSpy).toHaveBeenCalled(); expect(updatePreviewMiddlewareConfigsSpy).toHaveBeenCalled(); @@ -53,9 +127,9 @@ describe('index', () => { JSON.stringify({ devDependencies: { '@ui5/cli': '2.0.0' } }) ); - await expect(convertToVirtualPreview(missingPrerequisitesPath, logger, fs)).rejects.toThrowError( - `The prerequisites are not met. For more information, see the log messages above.` - ); + await expect( + convertToVirtualPreview(missingPrerequisitesPath, { convertTests: false, logger, fs }) + ).rejects.toThrowError(`The prerequisites are not met. For more information, see the log messages above.`); expect(checkPrerequisitesSpy).toHaveBeenCalled(); expect(getExplicitApprovalToAdjustFilesSpy).not.toHaveBeenCalled(); expect(updatePreviewMiddlewareConfigsSpy).not.toHaveBeenCalled(); @@ -67,7 +141,7 @@ describe('index', () => { test('do not convert project to virtual preview - missing approval', async () => { getExplicitApprovalToAdjustFilesSpy.mockResolvedValue(false); - await convertToVirtualPreview(basePath, logger, fs); + await convertToVirtualPreview(basePath, { convertTests: false, logger, fs }); expect(checkPrerequisitesSpy).toHaveBeenCalled(); expect(getExplicitApprovalToAdjustFilesSpy).toHaveBeenCalled(); expect(errorLogMock).toHaveBeenCalledWith( diff --git a/packages/app-config-writer/test/unit/preview-config/prerequisites.test.ts b/packages/app-config-writer/test/unit/preview-config/prerequisites.test.ts index 945cc09be86..e681142dba5 100644 --- a/packages/app-config-writer/test/unit/preview-config/prerequisites.test.ts +++ b/packages/app-config-writer/test/unit/preview-config/prerequisites.test.ts @@ -40,6 +40,39 @@ describe('prerequisites', () => { ); }); + test('check prerequisites with UI5 cli ^3 dependency', async () => { + fs.write( + join(basePath, 'package.json'), + JSON.stringify({ devDependencies: { '@ui5/cli': '^3', 'cds-plugin-ui5': '6.6.6' } }) + ); + + expect(await checkPrerequisites(basePath, fs, logger)).toBeTruthy(); + }); + + test('check prerequisites with UI5 cli ^2 dependency', async () => { + fs.write( + join(basePath, 'package.json'), + JSON.stringify({ devDependencies: { '@ui5/cli': '^2', 'cds-plugin-ui5': '6.6.6' } }) + ); + + expect(await checkPrerequisites(basePath, fs, logger)).toBeFalsy(); + expect(errorLogMock).toHaveBeenCalledWith( + 'UI5 CLI version 3.0.0 or higher is required to convert the preview to virtual files. For more information, see https://sap.github.io/ui5-tooling/v3/updates/migrate-v3.' + ); + }); + + test('check prerequisites with UI5 ux-ui5-tooling 1.15.0 dependency', async () => { + fs.write( + join(basePath, 'package.json'), + JSON.stringify({ devDependencies: { '@sap/ux-ui5-tooling': '1.15.0' } }) + ); + + expect(await checkPrerequisites(basePath, fs, logger)).toBeFalsy(); + expect(errorLogMock).toHaveBeenCalledWith( + 'UX UI5 Tooling version 1.15.4 or higher is required to convert the preview to virtual files. For more information, see https://www.npmjs.com/package/@sap/ux-ui5-tooling.' + ); + }); + test('check prerequisites w/o mockserver dependency', async () => { fs.write(join(basePath, 'package.json'), JSON.stringify({ devDependencies: { '@ui5/cli': '3.0.0' } })); diff --git a/packages/app-config-writer/test/unit/preview-config/preview-files.test.ts b/packages/app-config-writer/test/unit/preview-config/preview-files.test.ts index f8c0f51ba78..53ea7f6b7ec 100644 --- a/packages/app-config-writer/test/unit/preview-config/preview-files.test.ts +++ b/packages/app-config-writer/test/unit/preview-config/preview-files.test.ts @@ -38,10 +38,10 @@ describe('preview-files', () => { '"dummy content flpSandboxMockserver"' ); expect(infoLogMock).toHaveBeenCalledWith( - `Renamed 'flpSandbox.html' to 'flpSandbox_old.html'. This file is no longer needed for the preview functionality. If you have not modified this file, you can delete it. If you have modified this file, move the modified content to a custom init script for the preview middleware. For more information, see https://www.npmjs.com/package/preview-middleware#migration.` + `Renamed 'flpSandbox.html' to 'flpSandbox_old.html'. This file is no longer needed for the preview functionality. If you have not modified this file, you can delete it. If you have modified this file, move the modified content to a custom init script for the preview middleware. For more information, see https://github.com/SAP/open-ux-tools/tree/main/packages/preview-middleware#migration.` ); expect(infoLogMock).toHaveBeenCalledWith( - `Renamed 'flpSandboxMockserver.html' to 'flpSandboxMockserver_old.html'. This file is no longer needed for the preview functionality. If you have not modified this file, you can delete it. If you have modified this file, move the modified content to a custom init script for the preview middleware. For more information, see https://www.npmjs.com/package/preview-middleware#migration.` + `Renamed 'flpSandboxMockserver.html' to 'flpSandboxMockserver_old.html'. This file is no longer needed for the preview functionality. If you have not modified this file, you can delete it. If you have modified this file, move the modified content to a custom init script for the preview middleware. For more information, see https://github.com/SAP/open-ux-tools/tree/main/packages/preview-middleware#migration.` ); }); @@ -75,7 +75,7 @@ describe('preview-files', () => { const path = join(basePath, 'test', 'IdoNotExist.html'); await renameSandbox(fs, path, logger); - expect(warnLogMock).toHaveBeenCalledWith(`The file 'IdoNotExist.html', has not been found. Skipping renaming.`); + expect(infoLogMock).toHaveBeenCalledWith(`The file 'IdoNotExist.html', has not been found. Skipping renaming.`); }); test('skip renaming for files which have already been renamed', async () => { @@ -85,7 +85,7 @@ describe('preview-files', () => { await renameSandbox(fs, path, logger); expect(infoLogMock).toHaveBeenCalledWith( - `Renamed 'ImAlreadyRenamed.html' to 'ImAlreadyRenamed_old.html'. This file is no longer needed for the preview functionality. If you have not modified this file, you can delete it. If you have modified this file, move the modified content to a custom init script for the preview middleware. For more information, see https://www.npmjs.com/package/preview-middleware#migration.` + `Renamed 'ImAlreadyRenamed.html' to 'ImAlreadyRenamed_old.html'. This file is no longer needed for the preview functionality. If you have not modified this file, you can delete it. If you have modified this file, move the modified content to a custom init script for the preview middleware. For more information, see https://github.com/SAP/open-ux-tools/tree/main/packages/preview-middleware#migration.` ); await renameSandbox(fs, path, logger); diff --git a/packages/app-config-writer/test/unit/preview-config/ui5-yaml.test.ts b/packages/app-config-writer/test/unit/preview-config/ui5-yaml.test.ts index 16215fd533f..a3aa211b6b2 100644 --- a/packages/app-config-writer/test/unit/preview-config/ui5-yaml.test.ts +++ b/packages/app-config-writer/test/unit/preview-config/ui5-yaml.test.ts @@ -55,7 +55,7 @@ describe('update preview middleware config', () => { const text = (filename: string) => `The UI5 YAML configuration file '${filename}', is not used in any preview script. Outdated preview middleware will be adjusted, if necessary.`; - await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, logger); + await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, false, logger); expect(fs.read(join(variousConfigsPath, 'package.json'))).toMatchSnapshot(); expect(warnLogMock).toHaveBeenCalledWith(text('ui5-deprecated-tools-preview.yaml')); expect(fs.read(join(variousConfigsPath, 'ui5-deprecated-tools-preview.yaml'))).toMatchSnapshot(); @@ -81,7 +81,7 @@ describe('update preview middleware config', () => { }; fs.write(join(variousConfigsPath, 'package.json'), JSON.stringify(packageJson)); - await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, logger); + await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, false, logger); expect(fs.read(join(variousConfigsPath, 'package.json'))).toMatchSnapshot(); expect(warnLogMock).toHaveBeenCalledWith( `Skipping script 'invalid', which refers to the UI5 YAML configuration file 'ui5-invalid.yaml'. An error occurred when reading 'ui5-invalid.yaml': This file does not comply with the schema.` @@ -101,7 +101,7 @@ describe('update preview middleware config', () => { }; fs.write(join(variousConfigsPath, 'package.json'), JSON.stringify(packageJson)); - await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, logger); + await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, false, logger); expect(fs.read(join(variousConfigsPath, 'package.json'))).toMatchSnapshot(); expect(warnLogMock).toHaveBeenCalledWith( `Skipping script 'not:found', because the UI5 YAML configuration file, 'ui5-unavailable.yaml', could not be found.` @@ -121,11 +121,34 @@ describe('update preview middleware config', () => { }; fs.write(join(variousConfigsPath, 'package.json'), JSON.stringify(packageJson)); - await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, logger); + await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, false, logger); expect(fs.read(join(variousConfigsPath, 'ui5-no-middleware.yaml'))).toMatchSnapshot(); expect(fs.read(join(variousConfigsPath, 'package.json'))).toMatchSnapshot(); }); + test('deprecated tools preview with theme and tests', async () => { + const variousConfigsPath = join(basePath, 'various-configs'); + const packageJson = { + scripts: { + 'ui:mockserver': + 'fiori run --open "test/flpSandbox.html?sap-ui-xx-viewCache=false#Chicken-dance" --config ./ui5-deprecated-tools-preview-theme.yaml', + 'start-variants-management': 'ui5 serve --o chicken.html', + 'ui:opa5': + 'fiori run -o test/integration/opaTests.qunit.html?sap-ui-xx-viewCache=false#Chicken-dance --config ./ui5-deprecated-tools-preview-theme.yaml', + 'ui:unit': + 'fiori run -o test/unit/unitTests.qunit.html?sap-ui-xx-viewCache=false#Chicken-dance --config ./ui5-deprecated-tools-preview-theme.yaml' + }, + 'devDependencies': { + '@sap/ux-ui5-tooling': '1.15.1' + } + }; + fs.write(join(variousConfigsPath, 'package.json'), JSON.stringify(packageJson)); + + await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, true, logger); + expect(fs.read(join(variousConfigsPath, 'ui5-deprecated-tools-preview-theme.yaml'))).toMatchSnapshot(); + expect(fs.read(join(variousConfigsPath, 'package.json'))).toMatchSnapshot(); + }); + test('deprecated tools preview with theme', async () => { const variousConfigsPath = join(basePath, 'various-configs'); const packageJson = { @@ -140,7 +163,7 @@ describe('update preview middleware config', () => { }; fs.write(join(variousConfigsPath, 'package.json'), JSON.stringify(packageJson)); - await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, logger); + await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, false, logger); expect(fs.read(join(variousConfigsPath, 'ui5-deprecated-tools-preview-theme.yaml'))).toMatchSnapshot(); expect(fs.read(join(variousConfigsPath, 'package.json'))).toMatchSnapshot(); }); @@ -159,7 +182,7 @@ describe('update preview middleware config', () => { }; fs.write(join(variousConfigsPath, 'package.json'), JSON.stringify(packageJson)); - await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, logger); + await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, false, logger); expect(fs.read(join(variousConfigsPath, 'ui5-deprecated-tools-preview.yaml'))).toMatchSnapshot(); expect(fs.read(join(variousConfigsPath, 'package.json'))).toMatchSnapshot(); }); @@ -177,11 +200,33 @@ describe('update preview middleware config', () => { }; fs.write(join(variousConfigsPath, 'package.json'), JSON.stringify(packageJson)); - await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, logger); + await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, false, logger); expect(fs.read(join(variousConfigsPath, 'ui5-existing-tools-preview.yaml'))).toMatchSnapshot(); expect(fs.read(join(variousConfigsPath, 'package.json'))).toMatchSnapshot(); }); + test('existing preview middleware with tests', async () => { + const variousConfigsPath = join(basePath, 'various-configs'); + const packageJson = { + scripts: { + 'ui:mockserver': + 'fiori run -o localService/index.html?sap-ui-xx-viewCache=false#Chicken-dance --config ./ui5-existing-preview-middleware.yaml', + 'ui:opa5': + 'fiori run -o test/integration/opaTests.qunit.html?sap-ui-xx-viewCache=false#Chicken-dance --config ./ui5-existing-preview-middleware.yaml', + 'ui:unit': + 'fiori run -o test/unit/unitTests.qunit.html?sap-ui-xx-viewCache=false#Chicken-dance --config ./ui5-existing-preview-middleware.yaml' + }, + 'devDependencies': { + '@sap-ux/preview-middleware': '0.16.102' + } + }; + fs.write(join(variousConfigsPath, 'package.json'), JSON.stringify(packageJson)); + + await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, true, logger); + expect(fs.read(join(variousConfigsPath, 'ui5-existing-preview-middleware.yaml'))).toMatchSnapshot(); + expect(fs.read(join(variousConfigsPath, 'package.json'))).toMatchSnapshot(); + }); + test('existing preview middleware', async () => { const variousConfigsPath = join(basePath, 'various-configs'); const packageJson = { @@ -199,7 +244,7 @@ describe('update preview middleware config', () => { }; fs.write(join(variousConfigsPath, 'package.json'), JSON.stringify(packageJson)); - await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, logger); + await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, false, logger); expect(fs.read(join(variousConfigsPath, 'ui5-existing-preview-middleware.yaml'))).toMatchSnapshot(); expect(fs.read(join(variousConfigsPath, 'package.json'))).toMatchSnapshot(); }); @@ -218,7 +263,7 @@ describe('update preview middleware config', () => { }; fs.write(join(variousConfigsPath, 'package.json'), JSON.stringify(packageJson)); - await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, logger); + await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, false, logger); expect(fs.read(join(variousConfigsPath, 'ui5-existing-preview-middleware.yaml'))).toMatchSnapshot(); expect(fs.read(join(variousConfigsPath, 'package.json'))).toMatchSnapshot(); }); @@ -239,7 +284,7 @@ describe('update preview middleware config', () => { }; fs.write(join(variousConfigsPath, 'package.json'), JSON.stringify(packageJson)); - await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, logger); + await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, false, logger); expect(fs.read(join(variousConfigsPath, 'ui5-deprecated-tools-preview.yaml'))).toMatchSnapshot(); expect(fs.read(join(variousConfigsPath, 'package.json'))).toMatchSnapshot(); }); @@ -258,7 +303,7 @@ describe('update preview middleware config', () => { }; fs.write(join(variousConfigsPath, 'package.json'), JSON.stringify(packageJson)); - await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, logger); + await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, false, logger); expect(fs.read(join(variousConfigsPath, 'ui5-no-middleware.yaml'))).toMatchSnapshot(); expect(fs.read(join(variousConfigsPath, 'package.json'))).toMatchSnapshot(); @@ -269,7 +314,9 @@ describe('update preview middleware config', () => { const packageJson = { scripts: { 'start': 'fiori run --open "test/flpSandbox.html?sap-ui-xx-viewCache=false#v4lropconvert0711-tile"', - 'start-index': 'fiori run --open "index.html?sap-ui-xx-viewCache=false#v4lropconvert0711-tile"' + 'start-index': 'fiori run --open "index.html?sap-ui-xx-viewCache=false#v4lropconvert0711-tile"', + 'start-index2': "fiori run --open 'index.html?sap-ui-xx-viewCache=false#v4lropconvert0711-tile'", + 'start-index3': 'fiori run --open index.html?sap-ui-xx-viewCache=false#v4lropconvert0711-tile' }, 'devDependencies': { '@sap/ux-ui5-tooling': '1.15.4' @@ -277,7 +324,7 @@ describe('update preview middleware config', () => { }; fs.write(join(variousConfigsPath, 'package.json'), JSON.stringify(packageJson)); - await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, logger); + await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, false, logger); expect(fs.read(join(variousConfigsPath, 'ui5.yaml'))).toMatchSnapshot(); expect(fs.read(join(variousConfigsPath, 'package.json'))).toMatchSnapshot(); @@ -297,7 +344,7 @@ describe('update preview middleware config', () => { }; fs.write(join(variousConfigsPath, 'package.json'), JSON.stringify(packageJson)); - await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, logger); + await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, false, logger); expect(warnLogMock).toHaveBeenCalledTimes(5); }); @@ -315,13 +362,13 @@ describe('update preview middleware config', () => { }; fs.write(join(variousConfigsPath, 'package.json'), JSON.stringify(packageJson)); - await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, logger); + await updatePreviewMiddlewareConfigs(fs, variousConfigsPath, false, logger); expect(fs.read(join(variousConfigsPath, 'ui5.yaml'))).toMatchSnapshot(); expect(fs.read(join(variousConfigsPath, 'package.json'))).toMatchSnapshot(); expect(warnLogMock).toHaveBeenCalledWith( - `Skipping script'start2', because another script also refers to UI5 YAML configuration file, 'ui5.yaml'. Adjust the 'flp.path' property in the UI5 YAML configuration file to the correct endpoint or create a separate UI5 YAML configuration file for script 'start2'. ui5.yaml currently uses test/flpSandbox.html whereas script 'start2' uses 'test/flpSandboxMockserver.html'.` + `Skipping script 'start2', because another script also refers to UI5 YAML configuration file, 'ui5.yaml'. Adjust the 'flp.path' property in the UI5 YAML configuration file to the correct endpoint or create a separate UI5 YAML configuration file for script 'start2'. ui5.yaml currently uses test/flpSandbox.html whereas script 'start2' uses 'test/flpSandboxMockserver.html'.` ); }); }); diff --git a/packages/axios-extension/CHANGELOG.md b/packages/axios-extension/CHANGELOG.md index d174b9439c8..7c2e9a4867a 100644 --- a/packages/axios-extension/CHANGELOG.md +++ b/packages/axios-extension/CHANGELOG.md @@ -1,5 +1,11 @@ # @sap-ux/axios-extension +## 1.18.0 + +### Minor Changes + +- 2e3c15e: Proper check for cloud ABAP systems + ## 1.17.8 ### Patch Changes diff --git a/packages/axios-extension/package.json b/packages/axios-extension/package.json index 0498d189f9d..cc94632f94f 100644 --- a/packages/axios-extension/package.json +++ b/packages/axios-extension/package.json @@ -1,6 +1,6 @@ { "name": "@sap-ux/axios-extension", - "version": "1.17.8", + "version": "1.18.0", "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/axios-extension/src/abap/abap-service-provider.ts b/packages/axios-extension/src/abap/abap-service-provider.ts index 644d272987c..f35c3060328 100644 --- a/packages/axios-extension/src/abap/abap-service-provider.ts +++ b/packages/axios-extension/src/abap/abap-service-provider.ts @@ -90,16 +90,11 @@ export class AbapServiceProvider extends ServiceProvider { * * @returns true if it an S/4HANA cloud system */ - public async isS4Cloud(): Promise { + public async isAbapCloud(): Promise { if (this.atoSettings === undefined) { await this.getAtoInfo(); } - return ( - this.atoSettings.tenantType === TenantType.Customer && - this.atoSettings.operationsType === 'C' && - this.atoSettings.developmentPrefix !== '' && - this.atoSettings.developmentPackage !== '' - ); + return this.atoSettings.tenantType === TenantType.Customer && this.atoSettings.operationsType === 'C'; } /** @@ -138,8 +133,8 @@ export class AbapServiceProvider extends ServiceProvider { } else { throw new Error('not implemented yet'); } - Object.defineProperty(service, 'isS4Cloud', { - get: this.isS4Cloud.bind(this) + Object.defineProperty(service, 'isAbapCloud', { + get: this.isAbapCloud.bind(this) }); return service; } diff --git a/packages/axios-extension/test/abap/abap-adt-service.test.ts b/packages/axios-extension/test/abap/abap-adt-service.test.ts index 0684a048f32..f0cc0c9b377 100644 --- a/packages/axios-extension/test/abap/abap-adt-service.test.ts +++ b/packages/axios-extension/test/abap/abap-adt-service.test.ts @@ -412,7 +412,7 @@ describe('Use existing connection session', () => { const provider = createForAbapOnCloud(existingCookieConfigForAbapOnCloudStandalone as any); expect(provider.cookies.toString()).toBe('sap-usercontext=sap-client=100; SAP_SESSIONID_Y05_100=abc'); - expect(await provider.isS4Cloud()).toBe(false); + expect(await provider.isAbapCloud()).toBe(false); expect(attachUaaAuthInterceptorSpy).toBeCalledTimes(0); expect(Uaa.prototype.getAccessToken).toBeCalledTimes(0); expect(Uaa.prototype.getAccessTokenWithClientCredentials).toBeCalledTimes(0); @@ -442,7 +442,7 @@ describe('Use existing connection session', () => { const cloneObj = cloneDeep(configForAbapOnCloud); delete cloneObj.service.uaa.username; const provider = createForAbapOnCloud(cloneObj as any); - expect(await provider.isS4Cloud()).toBe(true); + expect(await provider.isAbapCloud()).toBe(true); expect(await provider.user()).toBe('emailTest'); expect(Uaa.prototype.getAccessToken).toBeCalledTimes(3); expect(Uaa.prototype.getAccessTokenWithClientCredentials).toBeCalledTimes(0); @@ -468,7 +468,7 @@ describe('Use existing connection session', () => { } }; const provider = createForAbapOnCloud(configForAbapOnCloudWithAuthentication as any); - expect(await provider.isS4Cloud()).toBe(false); + expect(await provider.isAbapCloud()).toBe(false); expect(await provider.user()).toBe('email'); expect(Uaa.prototype.getAccessToken).toBeCalledTimes(0); expect(Uaa.prototype.getAccessTokenWithClientCredentials).toBeCalledTimes(2); diff --git a/packages/axios-extension/test/abap/abap-service-provider.test.ts b/packages/axios-extension/test/abap/abap-service-provider.test.ts index 0b5283c805f..d469d06d740 100644 --- a/packages/axios-extension/test/abap/abap-service-provider.test.ts +++ b/packages/axios-extension/test/abap/abap-service-provider.test.ts @@ -95,7 +95,7 @@ describe('AbapServiceProvider', () => { .get(AdtServices.ATO_SETTINGS) .replyWithFile(200, join(__dirname, 'mockResponses/atoSettingsS4C.xml')); const abapSrvProvider = await createForAbap(config); - expect(await abapSrvProvider.isS4Cloud()).toBe(true); + expect(await abapSrvProvider.isAbapCloud()).toBe(true); expect(await abapSrvProvider.getAtoInfo()).toStrictEqual(ato); }); @@ -105,7 +105,7 @@ describe('AbapServiceProvider', () => { .replyWithFile(200, join(__dirname, 'mockResponses/discovery-1.xml')) .get(AdtServices.ATO_SETTINGS) .replyWithFile(200, join(__dirname, 'mockResponses/atoSettingsNotS4C.xml')); - expect(await createForAbap(config).isS4Cloud()).toBe(false); + expect(await createForAbap(config).isAbapCloud()).toBe(false); }); test('No request if known', async () => { @@ -115,8 +115,8 @@ describe('AbapServiceProvider', () => { .replyWithFile(200, join(__dirname, 'mockResponses/discovery-1.xml')) .get(AdtServices.ATO_SETTINGS) .replyWithFile(200, join(__dirname, 'mockResponses/atoSettingsS4C.xml')); - await provider.isS4Cloud(); - expect(await provider.isS4Cloud()).toBe(true); + await provider.isAbapCloud(); + expect(await provider.isAbapCloud()).toBe(true); }); test('Request failed', async () => { @@ -125,7 +125,7 @@ describe('AbapServiceProvider', () => { .replyWithFile(200, join(__dirname, 'mockResponses/discovery-1.xml')) .get(AdtServices.ATO_SETTINGS) .replyWithError('Something went wrong'); - expect(await createForAbap(config).isS4Cloud()).toBe(false); + expect(await createForAbap(config).isAbapCloud()).toBe(false); }); }); diff --git a/packages/backend-proxy-middleware/CHANGELOG.md b/packages/backend-proxy-middleware/CHANGELOG.md index 0224bee6bae..f6fcbcf8d1b 100644 --- a/packages/backend-proxy-middleware/CHANGELOG.md +++ b/packages/backend-proxy-middleware/CHANGELOG.md @@ -1,5 +1,12 @@ # @sap-ux/backend-proxy-middleware +## 0.8.28 + +### Patch Changes + +- Updated dependencies [2e3c15e] + - @sap-ux/axios-extension@1.18.0 + ## 0.8.27 ### Patch Changes diff --git a/packages/backend-proxy-middleware/package.json b/packages/backend-proxy-middleware/package.json index a8ddcc76f91..f8c556ced60 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.27", + "version": "0.8.28", "license": "Apache-2.0", "author": "@SAP/ux-tools-team", "main": "dist/index.js", diff --git a/packages/cf-deploy-config-inquirer/CHANGELOG.md b/packages/cf-deploy-config-inquirer/CHANGELOG.md index da0211ad841..067197264dc 100644 --- a/packages/cf-deploy-config-inquirer/CHANGELOG.md +++ b/packages/cf-deploy-config-inquirer/CHANGELOG.md @@ -1,5 +1,12 @@ # @sap-ux/cf-deploy-config-inquirer +## 0.1.15 + +### Patch Changes + +- Updated dependencies [dac696a] + - @sap-ux/inquirer-common@0.6.2 + ## 0.1.14 ### Patch Changes diff --git a/packages/cf-deploy-config-inquirer/package.json b/packages/cf-deploy-config-inquirer/package.json index 1442a195008..178d0d102b2 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.14", + "version": "0.1.15", "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 79c0a2f1c0c..eb3ed983394 100644 --- a/packages/create/CHANGELOG.md +++ b/packages/create/CHANGELOG.md @@ -1,5 +1,45 @@ # @sap-ux/create +## 0.11.17 + +### Patch Changes + +- @sap-ux/abap-deploy-config-inquirer@1.1.18 +- @sap-ux/adp-tooling@0.12.103 +- @sap-ux/flp-config-inquirer@0.2.8 +- @sap-ux/cap-config-writer@0.7.68 +- @sap-ux/preview-middleware@0.16.160 +- @sap-ux/app-config-writer@0.5.11 + +## 0.11.16 + +### Patch Changes + +- @sap-ux/abap-deploy-config-inquirer@1.1.17 +- @sap-ux/adp-tooling@0.12.102 +- @sap-ux/app-config-writer@0.5.11 +- @sap-ux/preview-middleware@0.16.159 +- @sap-ux/system-access@0.5.25 +- @sap-ux/flp-config-inquirer@0.2.7 +- @sap-ux/cap-config-writer@0.7.68 +- @sap-ux/abap-deploy-config-writer@0.0.72 + +## 0.11.15 + +### Patch Changes + +- Updated dependencies [0f1b457] + - @sap-ux/odata-service-writer@0.25.1 + +## 0.11.14 + +### Patch Changes + +- d964a24: feat: add option to convert test runners to preview-config command +- Updated dependencies [d964a24] + - @sap-ux/app-config-writer@0.5.10 + - @sap-ux/preview-middleware@0.16.158 + ## 0.11.13 ### Patch Changes diff --git a/packages/create/README.md b/packages/create/README.md index 684505e5c1f..f89bce42ac4 100644 --- a/packages/create/README.md +++ b/packages/create/README.md @@ -155,8 +155,9 @@ Executing `sap-ux convert` converts an app to a new feature. ### preview Executing `sap-ux convert preview-config` in the root folder of an app will convert the respective app to the preview with virtual files. It will use the configuration from the scripts in the `package.json` file to adjust the UI5 configuration YAML files accordingly. The obsolete JS and TS sources will be deleted and the HTML files previously used for the preview will be renamed to `*_old.html`. ```sh -sap-ux convert preview [path] +sap-ux convert preview-config [path] ``` +- `-t | --tests` include test suite and test runners in the conversion to virtual files ## sap-ux remove Calling `sap-ux remove` allows removing a feature from a project. diff --git a/packages/create/package.json b/packages/create/package.json index 57361058665..a5acea48b74 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.13", + "version": "0.11.17", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/create/src/cli/convert/preview.ts b/packages/create/src/cli/convert/preview.ts index 2b7e4a354e9..8c3c43c2eea 100644 --- a/packages/create/src/cli/convert/preview.ts +++ b/packages/create/src/cli/convert/preview.ts @@ -10,11 +10,12 @@ export function addConvertPreviewCommand(cmd: Command): void { cmd.command('preview-config [path]') .option('-s, --simulate', 'simulate only do not write or install') .option('-v, --verbose', 'show verbose information') + .option('-t, --tests', 'also convert test suite and test runners') .action(async (path, options) => { if (options.verbose === true || options.simulate) { setLogLevelVerbose(); } - await convertPreview(path, !!options.simulate); + await convertPreview(path, !!options.simulate, !!options.tests); }); } @@ -23,8 +24,9 @@ export function addConvertPreviewCommand(cmd: Command): void { * * @param {string} basePath - The path to the adaptation project. * @param {boolean} simulate - If set to true, then no files will be written to the filesystem. + * @param {boolean} convertTests - If set to true, then test suite and test runners fill be included in the conversion. */ -async function convertPreview(basePath: string, simulate: boolean): Promise { +async function convertPreview(basePath: string, simulate: boolean, convertTests: boolean): Promise { const logger = getLogger(); if (!basePath) { @@ -33,7 +35,7 @@ async function convertPreview(basePath: string, simulate: boolean): Promise logger.info(`The changes for preview conversion have been written.`)); diff --git a/packages/deploy-tooling/CHANGELOG.md b/packages/deploy-tooling/CHANGELOG.md index 65505e8cdf8..9f8b7897b83 100644 --- a/packages/deploy-tooling/CHANGELOG.md +++ b/packages/deploy-tooling/CHANGELOG.md @@ -1,5 +1,13 @@ # @sap-ux/deploy-tooling +## 0.15.36 + +### Patch Changes + +- Updated dependencies [2e3c15e] + - @sap-ux/axios-extension@1.18.0 + - @sap-ux/system-access@0.5.25 + ## 0.15.35 ### Patch Changes diff --git a/packages/deploy-tooling/package.json b/packages/deploy-tooling/package.json index 7b701bf8d25..b84765699af 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.35", + "version": "0.15.36", "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 bd8ec4d04ad..74ca403b992 100644 --- a/packages/environment-check/CHANGELOG.md +++ b/packages/environment-check/CHANGELOG.md @@ -1,5 +1,12 @@ # @sap-ux/environment-check +## 0.17.66 + +### Patch Changes + +- Updated dependencies [2e3c15e] + - @sap-ux/axios-extension@1.18.0 + ## 0.17.65 ### Patch Changes diff --git a/packages/environment-check/package.json b/packages/environment-check/package.json index 0401c2a9141..64d52aa3e71 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.65", + "version": "0.17.66", "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 c104af0322e..92b83455735 100644 --- a/packages/fiori-elements-writer/CHANGELOG.md +++ b/packages/fiori-elements-writer/CHANGELOG.md @@ -1,5 +1,12 @@ # @sap-ux/fiori-elements-writer +## 1.3.42 + +### Patch Changes + +- Updated dependencies [0f1b457] + - @sap-ux/odata-service-writer@0.25.1 + ## 1.3.41 ### Patch Changes diff --git a/packages/fiori-elements-writer/package.json b/packages/fiori-elements-writer/package.json index c554032b153..ee1800cc070 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": "1.3.41", + "version": "1.3.42", "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 a9097261f74..a506bf4f2c4 100644 --- a/packages/fiori-freestyle-writer/CHANGELOG.md +++ b/packages/fiori-freestyle-writer/CHANGELOG.md @@ -1,5 +1,12 @@ # @sap-ux/fiori-freestyle-writer +## 1.2.38 + +### Patch Changes + +- Updated dependencies [0f1b457] + - @sap-ux/odata-service-writer@0.25.1 + ## 1.2.37 ### Patch Changes diff --git a/packages/fiori-freestyle-writer/package.json b/packages/fiori-freestyle-writer/package.json index 04ac71d5e37..51d8b87fa71 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": "1.2.37", + "version": "1.2.38", "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 777e6094a2c..3e1e8ec115e 100644 --- a/packages/flp-config-inquirer/CHANGELOG.md +++ b/packages/flp-config-inquirer/CHANGELOG.md @@ -1,5 +1,19 @@ # @sap-ux/flp-config-inquirer +## 0.2.8 + +### Patch Changes + +- Updated dependencies [dac696a] + - @sap-ux/inquirer-common@0.6.2 + - @sap-ux/adp-tooling@0.12.103 + +## 0.2.7 + +### Patch Changes + +- @sap-ux/adp-tooling@0.12.102 + ## 0.2.6 ### Patch Changes diff --git a/packages/flp-config-inquirer/package.json b/packages/flp-config-inquirer/package.json index ea8f20a6c62..a552c029aa2 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.6", + "version": "0.2.8", "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 63c317c0da3..ed1b69f2db6 100644 --- a/packages/flp-config-sub-generator/CHANGELOG.md +++ b/packages/flp-config-sub-generator/CHANGELOG.md @@ -1,5 +1,29 @@ # @sap-ux/flp-config-sub-generator +## 0.0.4 + +### Patch Changes + +- Updated dependencies [dac696a] + - @sap-ux/inquirer-common@0.6.2 + - @sap-ux/flp-config-inquirer@0.2.8 + - @sap-ux/app-config-writer@0.5.11 + +## 0.0.3 + +### Patch Changes + +- @sap-ux/app-config-writer@0.5.11 +- @sap-ux/deploy-config-generator-shared@0.0.9 +- @sap-ux/flp-config-inquirer@0.2.7 + +## 0.0.2 + +### Patch Changes + +- Updated dependencies [d964a24] + - @sap-ux/app-config-writer@0.5.10 + ## 0.0.1 ### Patch Changes diff --git a/packages/flp-config-sub-generator/package.json b/packages/flp-config-sub-generator/package.json index 8cfea48e203..1dc5a4d4a4e 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.1", + "version": "0.0.4", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/guided-answers-helper/CHANGELOG.md b/packages/guided-answers-helper/CHANGELOG.md index b7868181c94..471698d39cc 100644 --- a/packages/guided-answers-helper/CHANGELOG.md +++ b/packages/guided-answers-helper/CHANGELOG.md @@ -1,5 +1,11 @@ # @sap-ux/guided-answers-helper +## 0.2.0 + +### Minor Changes + +- dac696a: Fix for incorrect error messsages connecting to destinations. Correct incorrect GA node name. + ## 0.1.1 ### Patch Changes diff --git a/packages/guided-answers-helper/package.json b/packages/guided-answers-helper/package.json index e1c6b892469..ebb333c133f 100644 --- a/packages/guided-answers-helper/package.json +++ b/packages/guided-answers-helper/package.json @@ -6,7 +6,7 @@ "url": "https://github.com/SAP/open-ux-tools.git", "directory": "packages/guided-answers-helper" }, - "version": "0.1.1", + "version": "0.2.0", "license": "Apache-2.0", "main": "dist/index.js", "scripts": { diff --git a/packages/guided-answers-helper/src/index.ts b/packages/guided-answers-helper/src/index.ts index 6ff6c92644e..0cf02ba1c72 100644 --- a/packages/guided-answers-helper/src/index.ts +++ b/packages/guided-answers-helper/src/index.ts @@ -23,7 +23,7 @@ export const HELP_NODES = { DESTINATION_UNAVAILABLE: 51208, // Launchpad service is not subscribed to DESTINATION_NOT_FOUND: 51208, // Destination URL is returning an empty response BAD_GATEWAY: 48366, // Bad gateway 502 - DESTINATION_BAD_GATEWAY_503: 52526, // Destination Service Unavailable 503 + DESTINATION_SERVICE_UNAVAILBLE: 52526, // Destination Service Unavailable 503 NO_V4_SERVICES: 57573, // No V4 OData services available NO_ADT_SERVICE_AUTH: 57266, //Users does not have authorizations to use ADT services DESTINATION_CONNECTION_ERRORS: 48366, // Non specific destination connection error help page, currently this is mapped to the same node as BAS_CATALOG_SERVICES_REQUEST_FAILED which will be updated in the future (and the entry here removed) diff --git a/packages/guided-answers-helper/test/unit/index.test.ts b/packages/guided-answers-helper/test/unit/index.test.ts index d1e9ad82fe5..919c6c6c4b6 100644 --- a/packages/guided-answers-helper/test/unit/index.test.ts +++ b/packages/guided-answers-helper/test/unit/index.test.ts @@ -33,10 +33,10 @@ describe('Guided Answers Helper', () => { "BAD_GATEWAY": 48366, "BAS_CATALOG_SERVICES_REQUEST_FAILED": 48366, "CERTIFICATE_ERROR": 53643, - "DESTINATION_BAD_GATEWAY_503": 52526, "DESTINATION_CONNECTION_ERRORS": 48366, "DESTINATION_MISCONFIGURED": 54336, "DESTINATION_NOT_FOUND": 51208, + "DESTINATION_SERVICE_UNAVAILBLE": 52526, "DESTINATION_UNAVAILABLE": 51208, "DEV_PLATFORM": 45996, "FIORI_APP_GENERATOR": 48363, diff --git a/packages/inquirer-common/CHANGELOG.md b/packages/inquirer-common/CHANGELOG.md index 04bd768607f..5ada5fba13b 100644 --- a/packages/inquirer-common/CHANGELOG.md +++ b/packages/inquirer-common/CHANGELOG.md @@ -1,5 +1,13 @@ # @sap-ux/inquirer-common +## 0.6.2 + +### Patch Changes + +- dac696a: Fix for incorrect error messsages connecting to destinations. Correct incorrect GA node name. +- Updated dependencies [dac696a] + - @sap-ux/guided-answers-helper@0.2.0 + ## 0.6.1 ### Patch Changes diff --git a/packages/inquirer-common/package.json b/packages/inquirer-common/package.json index 0d9f6773e24..b4301475e7f 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.1", + "version": "0.6.2", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/inquirer-common/src/error-handler/error-handler.ts b/packages/inquirer-common/src/error-handler/error-handler.ts index 984db57f098..9d03b4e13e9 100644 --- a/packages/inquirer-common/src/error-handler/error-handler.ts +++ b/packages/inquirer-common/src/error-handler/error-handler.ts @@ -51,7 +51,7 @@ export enum ERROR_TYPE { ODATA_URL_NOT_FOUND = 'ODATA_URL_NOT_FOUND', BAD_GATEWAY = 'BAD_GATEWAY', // Can be caused by either local issue or endpoint configuration INTERNAL_SERVER_ERROR = 'INTERNAL_SERVER_ERROR', - DESTINATION_BAD_GATEWAY_503 = 'DESTINATION_BAD_GATEWAY_503', // Caused by endpoint using a firewall or proxy + DESTINATION_SERVICE_UNAVAILABLE = 'DESTINATION_SERVICE_UNAVAILABLE', // Caused by endpoint using a firewall or proxy DESTINATION_UNAVAILABLE = 'DESTINATION_UNAVAILABLE', DESTINATION_NOT_FOUND = 'DESTINATION_NOT_FOUND', DESTINATION_MISCONFIGURED = 'DESTINATION_MISCONFIGURED', @@ -100,7 +100,7 @@ export const ERROR_MAP: Record = { [ERROR_TYPE.ODATA_URL_NOT_FOUND]: [], [ERROR_TYPE.INTERNAL_SERVER_ERROR]: [/500/], [ERROR_TYPE.BAD_GATEWAY]: [/502/], - [ERROR_TYPE.DESTINATION_BAD_GATEWAY_503]: [], + [ERROR_TYPE.DESTINATION_SERVICE_UNAVAILABLE]: [], [ERROR_TYPE.DESTINATION_UNAVAILABLE]: [], [ERROR_TYPE.DESTINATION_NOT_FOUND]: [], [ERROR_TYPE.DESTINATION_MISCONFIGURED]: [], @@ -245,7 +245,7 @@ export class ErrorHandler { }), [ERROR_TYPE.NO_V2_SERVICES]: () => t('errors.noServicesAvailable', { version: '2' }), [ERROR_TYPE.NO_V4_SERVICES]: () => t('errors.noServicesAvailable', { version: '4' }), - [ERROR_TYPE.DESTINATION_BAD_GATEWAY_503]: () => t('errors.destination.unavailable'), + [ERROR_TYPE.DESTINATION_SERVICE_UNAVAILABLE]: () => t('errors.destination.unavailable'), [ERROR_TYPE.REDIRECT]: () => t('errors.redirectError'), [ERROR_TYPE.NO_SUCH_HOST]: () => t('errors.noSuchHostError'), [ERROR_TYPE.NO_ABAP_ENVS]: () => t('errors.abapEnvsUnavailable'), @@ -291,7 +291,7 @@ export class ErrorHandler { [ERROR_TYPE.DESTINATION_UNAVAILABLE]: HELP_NODES.DESTINATION_UNAVAILABLE, [ERROR_TYPE.DESTINATION_NOT_FOUND]: HELP_NODES.DESTINATION_NOT_FOUND, [ERROR_TYPE.BAD_GATEWAY]: HELP_NODES.BAD_GATEWAY, - [ERROR_TYPE.DESTINATION_BAD_GATEWAY_503]: HELP_NODES.DESTINATION_BAD_GATEWAY_503, + [ERROR_TYPE.DESTINATION_SERVICE_UNAVAILABLE]: HELP_NODES.DESTINATION_SERVICE_UNAVAILBLE, [ERROR_TYPE.NO_V4_SERVICES]: HELP_NODES.NO_V4_SERVICES, [ERROR_TYPE.AUTH]: undefined, [ERROR_TYPE.AUTH_TIMEOUT]: undefined, @@ -538,7 +538,7 @@ export class ErrorHandler { this.currentErrorMsg = null; this.currentErrorType = null; } - return errorHelp ?? resolvedErrorMsg; // We mau not have a help link, so return the resolvedend user message + return errorHelp ?? resolvedErrorMsg; // We may not have a help link, so return the resolved end user message } /** * Get a more specific error type for the specified destination. @@ -559,14 +559,14 @@ export class ErrorHandler { destErrorMsg = this.getErrorMsgFromType(destErrorType, 'HTML5.DynamicDestination'); } else if (errorType === ERROR_TYPE.SERVICE_UNAVAILABLE) { if (isOnPremiseDestination(destination)) { - destErrorType = ERROR_TYPE.DESTINATION_BAD_GATEWAY_503; // Remap to specific gateway to allow GA link to be associated + destErrorType = ERROR_TYPE.DESTINATION_SERVICE_UNAVAILABLE; // Remap to specific gateway to allow GA link to be associated } else { destErrorType = ERROR_TYPE.DESTINATION_CONNECTION_ERROR; // General destination connection error, GA link to connection page } } else if (errorType === ERROR_TYPE.NOT_FOUND) { destErrorType = ERROR_TYPE.DESTINATION_NOT_FOUND; + destErrorMsg = this.getErrorMsgFromType(ERROR_TYPE.DESTINATION_NOT_FOUND); } else if (ERROR_TYPE.INTERNAL_SERVER_ERROR === errorType || ERROR_TYPE.SERVER_HTTP_ERROR === errorType) { - // We cannot tell in BAS what this means, so we will just say the connection failed destErrorType = ERROR_TYPE.DESTINATION_CONNECTION_ERROR; } else if (errorType === ERROR_TYPE.AUTH && destination.Authentication !== Authentication.NO_AUTHENTICATION) { // Auth errors for destinations are usually misconfiguration, unless the `Authentication` property is set to `NoAuthentication` diff --git a/packages/inquirer-common/src/translations/inquirer-common.i18n.json b/packages/inquirer-common/src/translations/inquirer-common.i18n.json index 5e075cf8de2..ce66886d130 100644 --- a/packages/inquirer-common/src/translations/inquirer-common.i18n.json +++ b/packages/inquirer-common/src/translations/inquirer-common.i18n.json @@ -8,7 +8,7 @@ "errors": { "destination": { "unavailable": "The selected destination references an instance that is not available. Please check your destination configuration and try again.", - "notFound": "The destination is misconfigured, HTTP Error 404 returned, the requested resource could not be found.", + "notFound": "The destination target URL cannot be found. The request failed with status code 404. Please check the destination target URL connectivity in your BTP cockpit.", "notReachable": "The selected system is not reachable. System name: {{systemName}}, error: {{- error}}", "misconfigured": "The destination is misconfigured. $t(errors.destination.missingPropMsg, {\"destinationProperty\": \"{{destinationProperty}}\" })", "missingPropMsg": "The property: `{{destinationProperty}}` is missing.", diff --git a/packages/inquirer-common/test/unit/error-handler/error-handler.test.ts b/packages/inquirer-common/test/unit/error-handler/error-handler.test.ts index c5e3a924c61..20dbee9862e 100644 --- a/packages/inquirer-common/test/unit/error-handler/error-handler.test.ts +++ b/packages/inquirer-common/test/unit/error-handler/error-handler.test.ts @@ -303,7 +303,7 @@ describe('Test ErrorHandler', () => { expect(ErrorHandler.getErrorMsgFromType(ERROR_TYPE.NO_V4_SERVICES)).toEqual( t('errors.noServicesAvailable', { version: '4' }) ); - expect(ErrorHandler.getErrorMsgFromType(ERROR_TYPE.DESTINATION_BAD_GATEWAY_503)).toEqual( + expect(ErrorHandler.getErrorMsgFromType(ERROR_TYPE.DESTINATION_SERVICE_UNAVAILABLE)).toEqual( t('errors.destination.unavailable') ); expect(ErrorHandler.getErrorMsgFromType(ERROR_TYPE.REDIRECT)).toEqual(t('errors.redirectError')); diff --git a/packages/odata-service-inquirer/CHANGELOG.md b/packages/odata-service-inquirer/CHANGELOG.md index c90a8ce53e4..b35cb35f94d 100644 --- a/packages/odata-service-inquirer/CHANGELOG.md +++ b/packages/odata-service-inquirer/CHANGELOG.md @@ -1,5 +1,20 @@ # @sap-ux/odata-service-inquirer +## 0.8.5 + +### Patch Changes + +- Updated dependencies [dac696a] + - @sap-ux/guided-answers-helper@0.2.0 + - @sap-ux/inquirer-common@0.6.2 + +## 0.8.4 + +### Patch Changes + +- Updated dependencies [2e3c15e] + - @sap-ux/axios-extension@1.18.0 + ## 0.8.3 ### Patch Changes diff --git a/packages/odata-service-inquirer/package.json b/packages/odata-service-inquirer/package.json index 1e3ca4eedcd..f08358b1e07 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": "0.8.3", + "version": "0.8.5", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/odata-service-inquirer/test/unit/prompts/connectionValidator.test.ts b/packages/odata-service-inquirer/test/unit/prompts/connectionValidator.test.ts index 21c9c43e923..1b4c8283ec2 100644 --- a/packages/odata-service-inquirer/test/unit/prompts/connectionValidator.test.ts +++ b/packages/odata-service-inquirer/test/unit/prompts/connectionValidator.test.ts @@ -637,7 +637,8 @@ describe('ConnectionValidator', () => { text: 'Need help with this error?', url: `https://ga.support.sap.com/dtp/viewer/index.html#/tree/${HELP_TREE.FIORI_TOOLS}/actions/${HELP_NODES.DESTINATION_NOT_FOUND}` }, - message: t('errors.urlNotFound') + message: + 'The destination target URL cannot be found. The request failed with status code 404. Please check the destination target URL connectivity in your BTP cockpit.' } }) ); diff --git a/packages/odata-service-writer/CHANGELOG.md b/packages/odata-service-writer/CHANGELOG.md index ce89c9172d0..89ab81dce78 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.1 + +### Patch Changes + +- 0f1b457: Improved update function for manifest by reducing JSON write calls for manifest file. + ## 0.25.0 ### Minor Changes diff --git a/packages/odata-service-writer/package.json b/packages/odata-service-writer/package.json index ea3f4becb58..5c632a9a281 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.0", + "version": "0.25.1", "license": "Apache-2.0", "main": "dist/index.js", "scripts": { diff --git a/packages/odata-service-writer/src/updates.ts b/packages/odata-service-writer/src/updates.ts index 955cc773204..dc8d6144441 100644 --- a/packages/odata-service-writer/src/updates.ts +++ b/packages/odata-service-writer/src/updates.ts @@ -234,8 +234,9 @@ function updateExistingService( * @param {string} webappPath - the webapp path of an existing UI5 application * @param {Manifest} manifest - the manifest.json of the application * @param {Editor} fs - the memfs editor instance + * @returns modified manifest object. */ -async function updateExistingServices(webappPath: string, manifest: Manifest, fs: Editor): Promise { +async function updateExistingServices(webappPath: string, manifest: Manifest, fs: Editor): Promise { const dataSources = manifest?.['sap.app']?.dataSources; for (const dataSourceKey in dataSources) { const dataSource = dataSources[dataSourceKey]; @@ -250,7 +251,7 @@ async function updateExistingServices(webappPath: string, manifest: Manifest, fs } } } - fs.writeJSON(join(webappPath, 'manifest.json'), manifest); + return manifest; } /** @@ -267,15 +268,14 @@ export async function updateManifest(basePath: string, service: OdataService, fs const manifest = fs.readJSON(manifestPath) as unknown as Manifest; const appProp = 'sap.app'; const appid = manifest?.[appProp]?.id; - // Check and update existing services - await updateExistingServices(webappPath, manifest, fs); - const modifiedManifest = fs.readJSON(manifestPath) as unknown as Manifest; // Throw if required property is not found manifest.json if (!appid) { throw new Error( t('error.requiredProjectPropertyNotFound', { property: `'${appProp}'.id`, path: manifestPath }) ); } + // Check and update existing services + const modifiedManifest = await updateExistingServices(webappPath, manifest, fs); // Add or update manifest.json with service enhanceManifest(service, modifiedManifest); fs.writeJSON(manifestPath, modifiedManifest); diff --git a/packages/odata-service-writer/test/test-data/manifest-json/edmx-manifest-older-services.ts b/packages/odata-service-writer/test/test-data/manifest-json/edmx-manifest-older-services.ts new file mode 100644 index 00000000000..371564480ae --- /dev/null +++ b/packages/odata-service-writer/test/test-data/manifest-json/edmx-manifest-older-services.ts @@ -0,0 +1,39 @@ +export const expectedEdmxManifestOlderServices = { + 'sap.app': { + id: 'test.update.manifest', + dataSources: { + mainService: { + type: 'OData', + settings: { + annotations: ['SEPMRA_OVW_ANNO_MDL'] + } + }, + SEPMRA_OVW_ANNO_MDL: { + type: 'ODataAnnotation', + settings: { + localUri: 'localService/mainService/SEPMRA_OVW_ANNO_MDL.xml' + } + }, + aname: { + uri: '/a/path', + type: 'OData', + settings: { + annotations: [], + odataVersion: '2.0' + } + } + } + }, + 'sap.ui5': { + models: { + '': { + dataSource: 'mainService' + }, + amodel: { + dataSource: 'aname', + preload: true, + settings: {} + } + } + } +}; diff --git a/packages/odata-service-writer/test/unit/updates.test.ts b/packages/odata-service-writer/test/unit/updates.test.ts index 6dbe9f7514b..a344d22f891 100644 --- a/packages/odata-service-writer/test/unit/updates.test.ts +++ b/packages/odata-service-writer/test/unit/updates.test.ts @@ -8,6 +8,7 @@ import { OdataVersion, ServiceType } from '../../src'; import { expectedEdmxManifest } from '../test-data/manifest-json/edmx-manifest'; import { expectedEdmxManifestMultipleAnnotations } from '../test-data/manifest-json/edmx-manifest-multiple-annotations'; import { expectedEdmxManifestMultipleServices } from '../test-data/manifest-json/edmx-manifest-multiple-services'; +import { expectedEdmxManifestOlderServices } from '../test-data/manifest-json/edmx-manifest-older-services'; import { expectedCdsManifest } from '../test-data/manifest-json/cap-manifest'; import { expectedEdmxManifestLocalAnnotation } from '../test-data/manifest-json/edmx-manifest-local-annotation'; // single local annotation import { expectedEdmxManifestLocalAnnotations } from '../test-data/manifest-json/edmx-manifest-local-annotations'; // multiple local annotations @@ -305,6 +306,51 @@ describe('updates', () => { expect(manifestJson).toEqual(expectedEdmxManifestMultipleServices); }); + test('Ensure manifest updates are updated as expected as in edmx projects with older services', async () => { + // Test to basically check whether existing service definitions are updated (localUri attribute is modified) + const testManifest = { + 'sap.app': { + id: 'test.update.manifest', + dataSources: { + mainService: { + type: 'OData', + settings: { + annotations: ['SEPMRA_OVW_ANNO_MDL'] + } + }, + SEPMRA_OVW_ANNO_MDL: { + type: 'ODataAnnotation', + settings: { + localUri: 'localService/SEPMRA_OVW_ANNO_MDL.xml' // localUri defined in localService folder - should be updated + } + } + } + }, + 'sap.ui5': { + models: { + '': { + dataSource: 'mainService' + } + } + } + }; + const service: OdataService = { + version: OdataVersion.v2, + client: '123', + model: 'amodel', + name: 'aname', + path: '/a/path', + type: ServiceType.EDMX, + annotations: [] + }; + + fs.writeJSON('./webapp/manifest.json', testManifest); + // Call updateManifest + await updateManifest('./', service, fs); + const manifestJson = fs.readJSON('./webapp/manifest.json'); + expect(manifestJson).toEqual(expectedEdmxManifestOlderServices); + }); + test('Ensure manifest updates are updated as expected as in cds projects', async () => { const testManifest = { 'sap.app': { diff --git a/packages/preview-middleware/CHANGELOG.md b/packages/preview-middleware/CHANGELOG.md index 95f46fee8ac..ea5b5ff4264 100644 --- a/packages/preview-middleware/CHANGELOG.md +++ b/packages/preview-middleware/CHANGELOG.md @@ -1,5 +1,23 @@ # @sap-ux/preview-middleware +## 0.16.160 + +### Patch Changes + +- @sap-ux/adp-tooling@0.12.103 + +## 0.16.159 + +### Patch Changes + +- @sap-ux/adp-tooling@0.12.102 + +## 0.16.158 + +### Patch Changes + +- d964a24: feat: add option to convert test runners to preview-config command + ## 0.16.157 ### Patch Changes diff --git a/packages/preview-middleware/package.json b/packages/preview-middleware/package.json index 74fba977d3a..35c654b7f1a 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.16.157", + "version": "0.16.160", "license": "Apache-2.0", "author": "@SAP/ux-tools-team", "main": "dist/index.js", diff --git a/packages/preview-middleware/src/base/test.ts b/packages/preview-middleware/src/base/test.ts index 830338f6b62..1ec735d1b75 100644 --- a/packages/preview-middleware/src/base/test.ts +++ b/packages/preview-middleware/src/base/test.ts @@ -1,7 +1,7 @@ import type { Resource } from '@ui5/fs'; -import type { InternalTestConfig, TestConfig } from '../types'; +import type { InternalTestConfig, TestConfig, TestConfigDefaults } from '../types'; -const DEFAULTS: Record = { +const DEFAULTS: Record> = { qunit: { path: '/test/unitTests.qunit.html', init: '/test/unitTests.qunit.js', @@ -20,7 +20,7 @@ const DEFAULTS: Record = { pattern: '', framework: 'Testsuite' } -}; +} satisfies TestConfigDefaults; /** * Merge the given test configuration with the default values. diff --git a/packages/preview-middleware/src/index.ts b/packages/preview-middleware/src/index.ts index 563d59ea634..c01737e6f6f 100644 --- a/packages/preview-middleware/src/index.ts +++ b/packages/preview-middleware/src/index.ts @@ -1,3 +1,11 @@ export * from './ui5/middleware'; export { FlpSandbox, initAdp, generatePreviewFiles, getPreviewPaths } from './base'; -export { FlpConfig, RtaConfig, TestConfig, MiddlewareConfig, DefaultFlpPath, DefaultIntent } from './types'; +export { + FlpConfig, + RtaConfig, + TestConfig, + MiddlewareConfig, + DefaultFlpPath, + DefaultIntent, + TestConfigDefaults +} from './types'; diff --git a/packages/preview-middleware/src/types/index.ts b/packages/preview-middleware/src/types/index.ts index 1ba2587e947..7b15c2ad25f 100644 --- a/packages/preview-middleware/src/types/index.ts +++ b/packages/preview-middleware/src/types/index.ts @@ -82,6 +82,27 @@ export interface TestConfig extends Partial { export type InternalTestConfig = TestConfig & OptionalTestConfig; +export type TestConfigDefaults = { + qunit: { + path: '/test/unitTests.qunit.html'; + init: '/test/unitTests.qunit.js'; + pattern: '/test/**/*Test.*'; + framework: 'QUnit'; + }; + opa5: { + path: '/test/opaTests.qunit.html'; + init: '/test/opaTests.qunit.js'; + pattern: '/test/**/*Journey.*'; + framework: 'OPA5'; + }; + testsuite: { + path: '/test/testsuite.qunit.html'; + init: '/test/testsuite.qunit.js'; + pattern: ''; + framework: 'Testsuite'; + }; +}; + /** * Middleware configuration. */ diff --git a/packages/project-integrity/.eslintignore b/packages/project-integrity/.eslintignore new file mode 100644 index 00000000000..93a3fe1f457 --- /dev/null +++ b/packages/project-integrity/.eslintignore @@ -0,0 +1,3 @@ +test/test-output +test/test-input +dist diff --git a/packages/project-integrity/.eslintrc.js b/packages/project-integrity/.eslintrc.js new file mode 100644 index 00000000000..b717f83ae98 --- /dev/null +++ b/packages/project-integrity/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + extends: ['../../.eslintrc'], + parserOptions: { + project: './tsconfig.eslint.json', + tsconfigRootDir: __dirname + } +}; diff --git a/packages/project-integrity/CHANGELOG.md b/packages/project-integrity/CHANGELOG.md new file mode 100644 index 00000000000..e222c9e5e86 --- /dev/null +++ b/packages/project-integrity/CHANGELOG.md @@ -0,0 +1,7 @@ +# @sap-ux/project-integrity + +## 0.0.2 + +### Patch Changes + +- 2bf91ea: New module @sap-ux/project-integrity diff --git a/packages/project-integrity/LICENSE b/packages/project-integrity/LICENSE new file mode 100644 index 00000000000..261eeb9e9f8 --- /dev/null +++ b/packages/project-integrity/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/project-integrity/README.md b/packages/project-integrity/README.md new file mode 100644 index 00000000000..ef5d2d13f83 --- /dev/null +++ b/packages/project-integrity/README.md @@ -0,0 +1,23 @@ +# @sap-ux/project-integrity + +Library that offers functions to detect modifications to a set of files within a project. It also allows to pass addition key -> string values that are stored together with integrity data and can also be checked. +For specific Fiori project, this module contains convenience functions that take care of building up the file and additional string content list, consumer need just to pass a valid Fiori project root. + +## Installation +Npm +`npm install --save @sap-ux/project-integrity` + +Yarn +`yarn add @sap-ux/project-integrity` + +Pnpm +`pnpm add @sap-ux/project-integrity` + +## Usage +See usage in `test/` folder. + +## Keywords +* SAP Fiori tools +* SAP Fiori elements +* SAP Fiori freestyle +* Project integrity \ No newline at end of file diff --git a/packages/project-integrity/jest.config.js b/packages/project-integrity/jest.config.js new file mode 100644 index 00000000000..9e9be597ecb --- /dev/null +++ b/packages/project-integrity/jest.config.js @@ -0,0 +1,2 @@ +const config = require('../../jest.base'); +module.exports = config; diff --git a/packages/project-integrity/package.json b/packages/project-integrity/package.json new file mode 100644 index 00000000000..18aa416230f --- /dev/null +++ b/packages/project-integrity/package.json @@ -0,0 +1,38 @@ +{ + "name": "@sap-ux/project-integrity", + "version": "0.0.2", + "description": "Library to check the integrity of projects", + "repository": { + "type": "git", + "url": "https://github.com/SAP/open-ux-tools.git", + "directory": "packages/project-integrity" + }, + "bugs": { + "url": "https://github.com/SAP/open-ux-tools/issues?q=is%3Aopen+is%3Aissue+label%3Abug+label%3Aproject-integrity" + }, + "license": "Apache-2.0", + "private": false, + "main": "dist/index.js", + "scripts": { + "build": "tsc --build", + "clean": "rimraf --glob dist coverage *.tsbuildinfo", + "format": "prettier --write '**/*.{js,json,ts,yaml,yml}' --ignore-path ../../.prettierignore", + "lint": "eslint . --ext .ts", + "lint:fix": "eslint . --ext .ts --fix", + "test": "jest --ci --forceExit --detectOpenHandles --colors", + "watch": "tsc --watch" + }, + "files": [ + "dist", + "LICENSE", + "!dist/*.map", + "!dist/**/*.map" + ], + "engines": { + "node": ">=18.x" + }, + "dependencies": { + "@sap-ux/project-access": "workspace:*", + "lz-string": "1.5.0" + } +} diff --git a/packages/project-integrity/src/fiori-project/index.ts b/packages/project-integrity/src/fiori-project/index.ts new file mode 100644 index 00000000000..033415ec6ea --- /dev/null +++ b/packages/project-integrity/src/fiori-project/index.ts @@ -0,0 +1,118 @@ +import { existsSync } from 'fs'; +import { join } from 'path'; +import { getCapCustomPaths } from '@sap-ux/project-access'; +import { + checkProjectIntegrity, + disableProjectIntegrity, + enableProjectIntegrity, + initProject, + isProjectIntegrityEnabled, + updateProjectIntegrity +} from '../integrity'; +import type { CheckIntegrityResult, Content } from '../types'; + +export const fioriIntegrityDataPath = join('.fiori-ai/ai-integrity.json'); + +/** + * Get the list of files to protect the integrity of. + * + * @param projectRoot - root folder of the project + * @returns - list of file paths + */ +async function getFileList(projectRoot: string): Promise { + const fileList: string[] = []; + + const schemaCds = join(projectRoot, 'db/schema.cds'); + if (existsSync(schemaCds)) { + fileList.push(schemaCds); + } else { + throw new Error(`File ${schemaCds} does not exist.`); + } + const servicesCds = join(projectRoot, 'srv/service.cds'); + if (existsSync(servicesCds)) { + fileList.push(servicesCds); + } else { + throw new Error(`File ${servicesCds} does not exist.`); + } + + return fileList; +} + +/** + * Returns additional string content, like the CAP environment. + * This content will be stored in the integrity data. + * + * @param projectRoot - root folder of the project + * @returns - additional content to store in the integrity data + */ +async function getAdditionalStringContent(projectRoot: string): Promise { + const capCustomPaths = await getCapCustomPaths(projectRoot); + return { capPaths: JSON.stringify(capCustomPaths) }; +} + +/** + * Initialize a Fiori project for integrity protection. + * + * @param projectRoot - root folder of the project + */ +export async function initFioriProject(projectRoot: string): Promise { + const integrityFilePath = join(projectRoot, fioriIntegrityDataPath); + const fileList = await getFileList(projectRoot); + const additionalStringContent = await getAdditionalStringContent(projectRoot); + await initProject({ integrityFilePath, fileList, additionalStringContent }); +} + +/** + * Check the integrity of a Fiori project. + * + * @param projectRoot - root folder of the project + * @returns - results of the check + */ +export async function checkFioriProjectIntegrity(projectRoot: string): Promise { + const integrityFilePath = join(projectRoot, fioriIntegrityDataPath); + const additionalStringContent = await getAdditionalStringContent(projectRoot); + return checkProjectIntegrity(integrityFilePath, additionalStringContent); +} + +/** + * Updates the integrity data of a Fiori project. + * + * @param projectRoot - root folder of the project + */ +export async function updateFioriProjectIntegrity(projectRoot: string): Promise { + const integrityFilePath = join(projectRoot, fioriIntegrityDataPath); + const additionalStringContent = await getAdditionalStringContent(projectRoot); + await updateProjectIntegrity(integrityFilePath, additionalStringContent); +} + +/** + * Return whether integrity is enabled for a Fiori project. + * + * @param projectRoot - root folder of the project + * @returns true if integrity is enabled, false otherwise + */ +export async function isFioriProjectIntegrityEnabled(projectRoot: string): Promise { + const integrityFilePath = join(projectRoot, fioriIntegrityDataPath); + return isProjectIntegrityEnabled(integrityFilePath); +} + +/** + * Enable integrity protection for a Fiori project. The Fiori project must be initialized first. + * After initialization, Fiori project integrity is enabled by default. + * + * @param projectRoot - root folder of the project + */ +export async function enableFioriProjectIntegrity(projectRoot: string): Promise { + const integrityFilePath = join(projectRoot, fioriIntegrityDataPath); + await enableProjectIntegrity(integrityFilePath); +} + +/** + * Disable integrity protection for a Fiori project. The Fiori project must be initialized first. + * + * @param projectRoot - root folder of the project + */ +export async function disableFioriProjectIntegrity(projectRoot: string): Promise { + const integrityFilePath = join(projectRoot, fioriIntegrityDataPath); + await disableProjectIntegrity(integrityFilePath); +} diff --git a/packages/project-integrity/src/index.ts b/packages/project-integrity/src/index.ts new file mode 100644 index 00000000000..ace2e448b99 --- /dev/null +++ b/packages/project-integrity/src/index.ts @@ -0,0 +1,16 @@ +export { + checkProjectIntegrity, + disableProjectIntegrity, + enableProjectIntegrity, + initProject, + isProjectIntegrityEnabled, + updateProjectIntegrity +} from './integrity'; +export { + checkFioriProjectIntegrity, + disableFioriProjectIntegrity, + enableFioriProjectIntegrity, + initFioriProject, + isFioriProjectIntegrityEnabled, + updateFioriProjectIntegrity +} from './fiori-project'; diff --git a/packages/project-integrity/src/integrity/check.ts b/packages/project-integrity/src/integrity/check.ts new file mode 100644 index 00000000000..86d5ad6e12a --- /dev/null +++ b/packages/project-integrity/src/integrity/check.ts @@ -0,0 +1,99 @@ +import { existsSync } from 'fs'; +import type { CheckIntegrityResult, Content, ContentIntegrity, FileIntegrity, Integrity } from '../types'; +import { getContentIntegrity, getFileIntegrity } from './hash'; + +/** + * Check existing integrity data. + * + * @param integrityData - integrity data + * @param [additionalStringContent] - optional additional new string content + * @returns - results of the check + */ +export async function checkIntegrity( + integrityData: Integrity, + additionalStringContent?: Content +): Promise { + return { + files: await checkFileIntegrity(integrityData.fileIntegrity), + additionalStringContent: checkContentIntegrity(integrityData.contentIntegrity, additionalStringContent) + }; +} + +/** + * Check an array of file hashes against the current state of the files. + * + * @param fileIntegrity - array of file integrity data + * @returns - results of the check + */ +async function checkFileIntegrity(fileIntegrity: FileIntegrity[]): Promise { + const differentFiles: CheckIntegrityResult['files']['differentFiles'] = []; + const equalFiles: string[] = []; + const checkFiles: FileIntegrity[] = []; + + for (const integrity of fileIntegrity) { + if (!existsSync(integrity.filePath)) { + differentFiles.push({ filePath: integrity.filePath, oldContent: integrity.content, newContent: '' }); + } else { + checkFiles.push(integrity); + } + } + const newFileIntegrityArray = await getFileIntegrity(checkFiles.map((fileIntegrity) => fileIntegrity.filePath)); + for (const newFileIntegrity of newFileIntegrityArray) { + const oldFileIntegrity = checkFiles.find((fileHash) => fileHash.filePath === newFileIntegrity.filePath); + if (oldFileIntegrity && oldFileIntegrity.hash === newFileIntegrity.hash) { + equalFiles.push(oldFileIntegrity.filePath); + } else { + differentFiles.push({ + filePath: newFileIntegrity.filePath, + oldContent: oldFileIntegrity?.content, + newContent: newFileIntegrity.content + }); + } + } + return { differentFiles, equalFiles }; +} + +/** + * Check old content integrity against new key->string values. + * + * @param contentIntegrity - existing content integrity from integrity data + * @param additionalStringContent - new additional key->string values + * @returns - result of the check + */ +function checkContentIntegrity( + contentIntegrity: ContentIntegrity[], + additionalStringContent?: Content +): CheckIntegrityResult['additionalStringContent'] { + const oldContentIntegrityArray = structuredClone(contentIntegrity); + const differentContent: CheckIntegrityResult['additionalStringContent']['differentContent'] = []; + const equalContent: string[] = []; + + const newContentIntegrityArray = getContentIntegrity(additionalStringContent); + for (const newContentIntegrity of newContentIntegrityArray) { + const index = oldContentIntegrityArray.findIndex( + (content) => content.contentKey === newContentIntegrity.contentKey + ); + let foundOldContentIntegrity; + if (index > -1) { + foundOldContentIntegrity = oldContentIntegrityArray[index]; + oldContentIntegrityArray.splice(index, 1); + } + if (foundOldContentIntegrity?.hash === newContentIntegrity.hash) { + equalContent.push(newContentIntegrity.contentKey); + } else { + differentContent.push({ + key: newContentIntegrity.contentKey, + newContent: newContentIntegrity.content, + oldContent: foundOldContentIntegrity?.content + }); + } + } + for (const missingContent of oldContentIntegrityArray) { + differentContent.push({ + key: missingContent.contentKey, + newContent: undefined, + oldContent: missingContent.content + }); + } + return { differentContent, equalContent }; +} diff --git a/packages/project-integrity/src/integrity/hash.ts b/packages/project-integrity/src/integrity/hash.ts new file mode 100644 index 00000000000..da2bdf4b866 --- /dev/null +++ b/packages/project-integrity/src/integrity/hash.ts @@ -0,0 +1,59 @@ +import { createReadStream, existsSync } from 'fs'; +import { createHash } from 'crypto'; +import type { Content, ContentIntegrity, FileIntegrity } from '../types'; + +/** + * Create a md5 hash for a given file. + * + * @param filePath - path to file + * @returns - promise that resolves to a FileHash object + */ +async function computeFileIntegrityData(filePath: string): Promise { + return new Promise((resolve, reject) => { + let content = ''; + const hash = createHash('md5'); + const fileStream = createReadStream(filePath); + fileStream.on('data', (chunk: Buffer) => { + content += chunk.toString(); + hash.update(chunk); + }); + fileStream.on('end', () => resolve({ filePath, hash: hash.digest('hex'), content })); + fileStream.on('error', (err) => reject(err)); + }); +} + +/** + * Returns integrity data for a list of given files. + * + * @param files - list of files to + * @returns - promise that resolves to an array of FileHash objects + */ +export async function getFileIntegrity(files: string[]): Promise { + const nonExistingFiles = files.filter((file) => !existsSync(file)); + if (nonExistingFiles.length > 0) { + throw new Error(`The following files do not exist: ${nonExistingFiles.join(', ')}`); + } + const promises = files.map(computeFileIntegrityData); + return await Promise.all(promises); +} + +/** + * Returns content integrity data for a map of key/value (string). + * + * @param additionalStringContent - key value map of additional content to write as integrity data + * @returns - array of + */ +export function getContentIntegrity(additionalStringContent?: Content): ContentIntegrity[] { + const contentIntegrity: ContentIntegrity[] = []; + if (additionalStringContent) { + for (const contentKey in additionalStringContent) { + const content = additionalStringContent[contentKey]; + contentIntegrity.push({ + contentKey, + hash: createHash('md5').update(content).digest('hex'), + content + }); + } + } + return contentIntegrity; +} diff --git a/packages/project-integrity/src/integrity/index.ts b/packages/project-integrity/src/integrity/index.ts new file mode 100644 index 00000000000..79d97c436c9 --- /dev/null +++ b/packages/project-integrity/src/integrity/index.ts @@ -0,0 +1,8 @@ +export { + checkProjectIntegrity, + disableProjectIntegrity, + enableProjectIntegrity, + initProject, + isProjectIntegrityEnabled, + updateProjectIntegrity +} from './project'; diff --git a/packages/project-integrity/src/integrity/persistence.ts b/packages/project-integrity/src/integrity/persistence.ts new file mode 100644 index 00000000000..e41eaf80874 --- /dev/null +++ b/packages/project-integrity/src/integrity/persistence.ts @@ -0,0 +1,80 @@ +import { mkdir, readFile, writeFile } from 'fs/promises'; +import { existsSync } from 'fs'; +import { dirname, join, relative } from 'path'; +import { compressToBase64, decompressFromBase64 } from 'lz-string'; +import type { ContentIntegrity, FileIntegrity, Integrity } from '../types'; + +/** + * Read hashes from a previously stored hash file. + * Throws an error if the file does not exist. + * + * @param integrityFilePath - path to the integrity file + * @returns - integrity data + */ +export async function readIntegrityData(integrityFilePath: string): Promise { + if (!existsSync(integrityFilePath)) { + throw new Error(`Integrity file not found at ${integrityFilePath}`); + } + const content = JSON.parse(await readFile(integrityFilePath, { encoding: 'utf-8' })) as Integrity; + const integrityDir = dirname(integrityFilePath); + for (const fileIntegrity of content.fileIntegrity) { + fileIntegrity.filePath = join(integrityDir, fileIntegrity.filePath); + getifyContent(fileIntegrity); + } + for (const contentIntegrity of content.contentIntegrity) { + getifyContent(contentIntegrity); + } + return content; +} + +/** + * Write file integrity information to file. When storing, use relative paths to the hash file + * so the project as whole can be moved without breaking integrity. + * + * @param integrityFilePath - path to the integrity file + * @param content - content to write to the integrity file + */ +export async function writeIntegrityData(integrityFilePath: string, content: Integrity): Promise { + const integrityDir = dirname(integrityFilePath); + if (!existsSync(integrityDir)) { + await mkdir(integrityDir, { recursive: true }); + } + + for (const fileIntegrity of content.fileIntegrity) { + fileIntegrity.filePath = relative(integrityDir, fileIntegrity.filePath); + if (typeof fileIntegrity.content === 'string') { + fileIntegrity.content = compressToBase64(fileIntegrity.content); + } + } + + for (const contentIntegrity of content.contentIntegrity) { + if (typeof contentIntegrity.content === 'string') { + contentIntegrity.content = compressToBase64(contentIntegrity.content); + } + } + + await writeFile(integrityFilePath, JSON.stringify(content), { encoding: 'utf-8' }); +} + +/** + * Wrap content with getter to decompress on first access. Do nothing if the content does not exist. + * + * @param integrityObject - file or content integrity data with compressed content + */ +function getifyContent(integrityObject: FileIntegrity | ContentIntegrity): void { + if (typeof integrityObject?.content === 'string') { + const compressedContent = integrityObject.content; + let content: string | undefined; + Object.defineProperty(integrityObject, 'content', { + get: () => { + if (!content) { + content = decompressFromBase64(compressedContent); + } + return content; + }, + set: () => { + // Read-only property, ignore content changes + } + }); + } +} diff --git a/packages/project-integrity/src/integrity/project.ts b/packages/project-integrity/src/integrity/project.ts new file mode 100644 index 00000000000..06d16da6f05 --- /dev/null +++ b/packages/project-integrity/src/integrity/project.ts @@ -0,0 +1,133 @@ +import { existsSync } from 'fs'; +import type { CheckIntegrityResult, Content, ProjectSettings } from '../types'; +import { getContentIntegrity, getFileIntegrity } from './hash'; +import { readIntegrityData, writeIntegrityData } from './persistence'; +import { checkIntegrity } from './check'; + +/** + * Function to ensure correct sorting of strings. + * + * @param a - first value to compare + * @param b - second value to compare + * @returns - 1 if a is greater than b, -1 if a is less than b, 0 if a is equal to b + */ +const sortLocal = (a: string, b: string): number => a.localeCompare(b); + +/** + * Initialize a project by creating hashes for all selected files in the project. There is an option to add + * additional key->string content to the integrity data. + * + * @param settings - settings for the project + * @param settings.integrityFilePath - path to file where integrity data will be stored + * @param settings.fileList - list of file paths for files to create integrity data for + * @param [settings.additionalStringContent] - optional key/string map to add to integrity data + */ +export async function initProject(settings: ProjectSettings): Promise { + const enabled = true; + const fileIntegrity = await getFileIntegrity(settings.fileList); + const contentIntegrity = await getContentIntegrity(settings.additionalStringContent); + await writeIntegrityData(settings.integrityFilePath, { enabled, fileIntegrity, contentIntegrity }); +} + +/** + * Check the integrity of a project by comparing the stored integrity data with the current state + * of the files and additional key->string. Throws an error if the project is not initialized, + * which means no integrity data found at 'integrityFilePath'. + * + * @param integrityFilePath - path to file where integrity data is stored + * @param [additionalStringContent] - optional key/string map to add to integrity data + * @returns - results of the check + */ +export async function checkProjectIntegrity( + integrityFilePath: string, + additionalStringContent?: Content +): Promise { + const integrityData = await readIntegrityData(integrityFilePath); + if (!integrityData.enabled) { + throw new Error(`Integrity is disabled for the project with integrity data ${integrityFilePath}`); + } + const checkResult = checkIntegrity(integrityData, additionalStringContent); + return checkResult; +} + +/** + * Updates the integrity data of a project. Throws an error if a file or string content is missing + * or new. + * + * @param integrityFilePath - path to file where integrity data is stored + * @param additionalStringContent - optional key/string map to add to integrity data + */ +export async function updateProjectIntegrity( + integrityFilePath: string, + additionalStringContent?: Content +): Promise { + if (!existsSync(integrityFilePath)) { + throw new Error(`Integrity data not found at ${integrityFilePath}`); + } + const integrityData = await readIntegrityData(integrityFilePath); + if (!integrityData.enabled) { + throw new Error(`Integrity is disabled for the project with integrity data ${integrityFilePath}`); + } + const existingContentKeys = integrityData.contentIntegrity.map((content) => content.contentKey).sort(sortLocal); + const newContentKeys = Object.keys(additionalStringContent ?? {}).sort(sortLocal); + if ( + existingContentKeys.length !== newContentKeys.length || + !existingContentKeys.every((key, index) => key === newContentKeys[index]) + ) { + throw new Error( + `There is a mismatch of additional content keys. +Stored content keys: ${existingContentKeys.join(', ')} +New content keys: ${newContentKeys.join(', ')}` + ); + } + const fileIntegrity = await getFileIntegrity(integrityData.fileIntegrity.map((file) => file.filePath)); + const contentIntegrity = getContentIntegrity(additionalStringContent); + await writeIntegrityData(integrityFilePath, { enabled: integrityData.enabled, fileIntegrity, contentIntegrity }); +} + +/** + * Return whether integrity is enabled for a project. + * + * @param integrityFilePath - path to file where integrity data is stored + * @returns - true if integrity is enabled, false otherwise + */ +export async function isProjectIntegrityEnabled(integrityFilePath: string): Promise { + if (!existsSync(integrityFilePath)) { + throw new Error(`Integrity data not found at ${integrityFilePath}`); + } + const { enabled } = await readIntegrityData(integrityFilePath); + return enabled; +} + +/** + * Enable integrity for a project. The project has to be initialized before enabling integrity. After initialization, + * the project integrity is enabled by default. + * + * @param integrityFilePath - path to file where integrity data is stored + */ +export async function enableProjectIntegrity(integrityFilePath: string): Promise { + if (!existsSync(integrityFilePath)) { + throw new Error(`Integrity data not found at ${integrityFilePath}`); + } + const integrityData = await readIntegrityData(integrityFilePath); + if (!integrityData.enabled) { + integrityData.enabled = true; + await writeIntegrityData(integrityFilePath, integrityData); + } +} + +/** + * Disable integrity for a project. The project has to be initialized before disabling integrity. + * + * @param integrityFilePath - path to file where integrity data is stored + */ +export async function disableProjectIntegrity(integrityFilePath: string): Promise { + if (!existsSync(integrityFilePath)) { + throw new Error(`Integrity data not found at ${integrityFilePath}`); + } + const integrityData = await readIntegrityData(integrityFilePath); + if (integrityData.enabled) { + integrityData.enabled = false; + await writeIntegrityData(integrityFilePath, integrityData); + } +} diff --git a/packages/project-integrity/src/types.ts b/packages/project-integrity/src/types.ts new file mode 100644 index 00000000000..a3d363b8622 --- /dev/null +++ b/packages/project-integrity/src/types.ts @@ -0,0 +1,75 @@ +/** + * Project settings when initializing project integrity. + */ +export interface ProjectSettings { + /** + * Path to the file where integrity data, like hash values, are stored + */ + integrityFilePath: string; + + /** + * List of files to create a hash value for + */ + fileList: string[]; + + /** + * List of content (key->string) to create a hash value for + */ + additionalStringContent?: Content; +} + +/** + * Integrity data for a project, stored as JSON in integrity file. + */ +export interface Integrity { + enabled: boolean; + fileIntegrity: FileIntegrity[]; + contentIntegrity: ContentIntegrity[]; +} + +/** + * Integrity data for a file. + */ +export interface FileIntegrity { + filePath: string; + hash: string; + content?: string; +} + +/** + * Integrity data for a content (key->string). + */ +export interface ContentIntegrity { + contentKey: string; + hash: string; + content?: string; +} + +/** + * Content (key->string) to store in integrity data. + */ +export interface Content { + [contentKey: string]: string; +} + +/** + * Result of a project integrity check. + */ +export interface CheckIntegrityResult { + files: { + differentFiles: { + filePath: string; + oldContent?: string; + newContent?: string; + }[]; + equalFiles: string[]; + }; + additionalStringContent: { + differentContent: { + key: string; + oldContent?: string; + newContent?: string; + }[]; + equalContent: string[]; + }; +} diff --git a/packages/project-integrity/test/test-input/disabled-fiori-project/.fiori-ai/ai-integrity.json b/packages/project-integrity/test/test-input/disabled-fiori-project/.fiori-ai/ai-integrity.json new file mode 100644 index 00000000000..605f0835140 --- /dev/null +++ b/packages/project-integrity/test/test-input/disabled-fiori-project/.fiori-ai/ai-integrity.json @@ -0,0 +1,5 @@ +{ + "enabled": false, + "fileIntegrity": [], + "contentIntegrity": [] +} \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/disabled-project/integrity.json b/packages/project-integrity/test/test-input/disabled-project/integrity.json new file mode 100644 index 00000000000..605f0835140 --- /dev/null +++ b/packages/project-integrity/test/test-input/disabled-project/integrity.json @@ -0,0 +1,5 @@ +{ + "enabled": false, + "fileIntegrity": [], + "contentIntegrity": [] +} \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/enabled-fiori-project/.fiori-ai/ai-integrity.json b/packages/project-integrity/test/test-input/enabled-fiori-project/.fiori-ai/ai-integrity.json new file mode 100644 index 00000000000..426c2386fe9 --- /dev/null +++ b/packages/project-integrity/test/test-input/enabled-fiori-project/.fiori-ai/ai-integrity.json @@ -0,0 +1,5 @@ +{ + "enabled": true, + "fileIntegrity": [], + "contentIntegrity": [] +} \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/enabled-project/integrity.json b/packages/project-integrity/test/test-input/enabled-project/integrity.json new file mode 100644 index 00000000000..426c2386fe9 --- /dev/null +++ b/packages/project-integrity/test/test-input/enabled-project/integrity.json @@ -0,0 +1,5 @@ +{ + "enabled": true, + "fileIntegrity": [], + "contentIntegrity": [] +} \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/invalid-fiori-project-no-schema-cds/srv/service.cds b/packages/project-integrity/test/test-input/invalid-fiori-project-no-schema-cds/srv/service.cds new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/project-integrity/test/test-input/invalid-fiori-project-no-service-cds/db/schema.cds b/packages/project-integrity/test/test-input/invalid-fiori-project-no-service-cds/db/schema.cds new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/project-integrity/test/test-input/invalid-project/bad.xml b/packages/project-integrity/test/test-input/invalid-project/bad.xml new file mode 100644 index 00000000000..68c8465ba7c --- /dev/null +++ b/packages/project-integrity/test/test-input/invalid-project/bad.xml @@ -0,0 +1,3 @@ + + Changed XML + \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/invalid-project/good.txt b/packages/project-integrity/test/test-input/invalid-project/good.txt new file mode 100644 index 00000000000..e3ab9e012e6 --- /dev/null +++ b/packages/project-integrity/test/test-input/invalid-project/good.txt @@ -0,0 +1 @@ +Just a test file. \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/invalid-project/integrity.json b/packages/project-integrity/test/test-input/invalid-project/integrity.json new file mode 100644 index 00000000000..b64f7ac74af --- /dev/null +++ b/packages/project-integrity/test/test-input/invalid-project/integrity.json @@ -0,0 +1,37 @@ +{ + "enabled": true, + "fileIntegrity": [ + { + "filePath": "good.txt", + "hash": "1a8a45c145cca8cb08b03e0eb1f6fcd4", + "content": "FIVwzgLgBAhlEFNJQGYEsA2CB0Q=" + }, + { + "filePath": "bad.xml", + "hash": "1f1cfb2f4e58c4e5c8870252f5d522a6", + "content": "DwDwtgNgfAUABAuwAuBTEyoBVUGdlwAaAsgDJwBmAlhKsAPRoawPjRA=" + }, + { + "filePath": "non-existing.file", + "hash": "0123456789", + "content": "HIewdgBApgHglgZwC5zAcyA=" + } + ], + "contentIntegrity": [ + { + "contentKey": "one", + "hash": "e567579e9506605c8acf5e817d4dc9d8", + "content": "G4QwNgrgpgBA9gOykA==" + }, + { + "contentKey": "two", + "hash": "e4254bf5deaa77586c0012fd21858279", + "content": "G4QwNgrgpgBALgdwPZA=" + }, + { + "contentKey": "three", + "hash": "e883ac885a1b2a06043ba166a5f00c30", + "content": "G4QwNgrgpgBALgCwE5SkA===" + } + ] +} \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/update-project/file-to-update.txt b/packages/project-integrity/test/test-input/update-project/file-to-update.txt new file mode 100644 index 00000000000..47d2739ba2c --- /dev/null +++ b/packages/project-integrity/test/test-input/update-project/file-to-update.txt @@ -0,0 +1 @@ +new content \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/update-project/integrity.json b/packages/project-integrity/test/test-input/update-project/integrity.json new file mode 100644 index 00000000000..60465c3700c --- /dev/null +++ b/packages/project-integrity/test/test-input/update-project/integrity.json @@ -0,0 +1,17 @@ +{ + "enabled": true, + "fileIntegrity": [ + { + "filePath": "file-to-update.txt", + "hash": "96c15c2bb2921193bf290df8cd85e2ba", + "content": "HYUw7gBAxg9sAuIFA===" + } + ], + "contentIntegrity": [ + { + "contentKey": "key", + "hash": "b200a3adbe85fe848b920dc35d5a69b2", + "content": "HYUw7gBAzgLgTgS2AcyA" + } + ] +} \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/.fiori-ai/ai-integrity.json b/packages/project-integrity/test/test-input/valid-fiori-project/.fiori-ai/ai-integrity.json new file mode 100644 index 00000000000..cca7db6757c --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/.fiori-ai/ai-integrity.json @@ -0,0 +1 @@ +{"enabled":true,"fileIntegrity":[{"filePath":"../db/schema.cds","hash":"7c8aeabf4a42453e88d3309692ab45a0","content":"HYQwtgpgzgDiDGEAEAXATiAbhANgWRFAHMJJgUBuAKConIEsUBPJAFQ2xyQG8qkkA1hBYBJACIAuJAFVp46v3T0YAOXAQpAZSXAiACgCsABgCUCpKRg4A9kwgak2tPV2HT5qChAoArlC06+gBM7nyozjDaIGgoYt4OcSgQ5kowAKLAACaJCfHmMM6I0pqSSGIQ8PRgIDjmAEbW1gIuRP5IAIJQUNaV3vTWwKjWSNXALABCjc26UEgDSA1NLVAAdOhYuEgAvEgAJFC4AGbUAL40dCiME1PLPGFCoqWy8mGWNnYOTi1uZmEg9GgcC5oAFnK5jL9+ItpkQclIcuZDkCiAALWLxeF5MIFehFErwipVGopDi4KSdbq9S7zFDDdgbWpUM5AA=="},{"filePath":"../srv/service.cds","hash":"0c598d02c2ca62ced4de09026ca62811","content":"K4Zwlgdg5gBA3jALgJwIYDcCmAbAsqiVKTAW0wkRgF8YAzZAexJgHIA6NgegBMAjTkAGMAFqVRtB3ECwDcAKDkhMydGEGYkaLHgJFS5RAGUV8OTBgABBt1SJx3NLURtyqXtkzczMA2EQBPGAAVLRwYVBAYAAdGACtMQUQwBggYFM0MHHxCYjIKNhDM7HlzXwCYACEGBgBrSChIiOi4hKT09JQi7L085yra+pB5KiA==="}],"contentIntegrity":[{"contentKey":"capPaths","hash":"a6b6345c05e820d69b779cef1587a209","content":"N4IghgDhIFzlB6EAaEATARrdGmoM4BOAbtkcUgL5A==="}]} \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/.fiori-ai/generator-config.json b/packages/project-integrity/test/test-input/valid-fiori-project/.fiori-ai/generator-config.json new file mode 100644 index 00000000000..04732a29f5f --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/.fiori-ai/generator-config.json @@ -0,0 +1,31 @@ +{ + "version": "0.2", + "floorplan": "FE_LROP", + "project": { + "name": "travelmanagement", + "targetFolder": "/Users/d045154/.fioritools/fiori-tools-ai", + "title": "AI generated App travelmanagement", + "description": "AI generated App travelmanagement", + "ui5Version": "", + "localUI5Version": "1.82.2", + "sapux": true + }, + "service": { + "servicePath": "/odata/v4/travel-management-srv/", + "capService": { + "projectPath": "/Users/d045154/.fioritools/fiori-tools-ai", + "serviceName": "travelManagementSrv", + "serviceCdsPath": "srv/service" + } + }, + "entityConfig": { + "mainEntity": { + "entityName": "Travel" + } + }, + "projectType": "LIST_REPORT_OBJECT_PAGE", + "telemetryData": { + "generationSourceName": "AI Headless", + "generationSourceVersion": "1.15.3" + } +} \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/.fiori-ai/log.txt b/packages/project-integrity/test/test-input/valid-fiori-project/.fiori-ai/log.txt new file mode 100644 index 00000000000..47b1caad27b --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/.fiori-ai/log.txt @@ -0,0 +1,553 @@ +2024-10-28T20:25:39.272Z [info] Project generation uses model: "gpt-4o", version: "latest" +2024-10-28T20:25:39.291Z [info] 1/5: Regenerate CAP model via LLM +2024-10-28T20:25:39.292Z [info] Fiori AI Generation Workbench: no 'fioriAiConfig.json' present +2024-10-28T20:25:39.292Z [info] Starting built-in flow "appSkeletonFirstImage" +2024-10-28T20:25:44.811Z [info] +==========LLM call for step "extractImage":========== +The below image is used to describe a Fiori Element application. +Your task is to characterize this image! + + + + +----------Requested Schema:--- +{ + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "user readable name to refer to that image; upperCamelCase, no spaces" + }, + "description": { + "type": "string", + "description": "short description of what is on this image (single sentence)" + }, + "contentKindReason": { + "type": "string", + "description": "provide short reason for the chosen 'contentKind'" + }, + "contentKind": { + "enum": [ + "ListReport", + "ObjectPage", + "DataModel", + "Mixture", + "None" + ], + "description": "image is showing a Fiori ELement List Report page ('ListReport'), Object Page ('ObjectPage'), a data model diagram consisting of entities, their properties and associations ('DataModel'), a 'Mixture' of these or 'None' of these" + }, + "contentSize": { + "enum": [ + "small", + "medium", + "large" + ], + "description": "use 'small' for e.g. icons or company logos, 'medium' for screenshot or diagram with up to twelve labels/captions/texts, 'large' for screenshot or diagram with more than twelve labels/captions/texts" + } + }, + "required": [ + "name", + "description", + "contentKind", + "contentSize" + ], + "additionalProperties": false +} + +----------Response:---------- +{ + "name": "FioriAppManagingTravels", + "description": "A whiteboard diagram describing a Fiori app for managing travels, including entities for Travel and Bookings with their properties and relationships.", + "contentKindReason": "The image shows a data model diagram with entities and their properties and associations.", + "contentKind": "DataModel", + "contentSize": "large" +} +2024-10-28T20:25:47.412Z [info] +==========LLM call for step "extractAppSkeleton":========== +You help the user building a Fiori Elements application described in the user input. + +A Fiori Elements application typically starts with a ListReport page showing the data of the base entity of the application in a table. +Details of a specific table row are shown in the ObjectPage. This first ObjectPage is therefore based on the base entity of the application. +An ObjectPage can contain one or more table sections based on to-many associations of its entity type. +The details of a table section row can be shown in an another ObjectPage based on the associations target entity. + +Your task is to find the entities (with their to-many associations) as well as the ObjectPages (with the to-many associations they use in table sections) described in the user input below. + + + + (DataModel): A whiteboard diagram describing a Fiori app for managing travels, including entities for Travel and Bookings with their properties and relationships. + + + +----------Requested Schema:--- +{ + "type": "object", + "properties": { + "entities": { + "type": "array", + "description": "Define all entities and their to-many associations; entity properties will be determined later", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "UpperCamelCase, no spaces, plural, e.g. 'Orders'" + }, + "label": { + "type": "string", + "description": "max two words, singular" + }, + "associations": { + "type": "array", + "description": "Define to-many associations between entities", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "target": { + "type": "string", + "description": "Points to existing entity, value is entities.name" + } + }, + "required": [ + "name", + "target" + ], + "additionalProperties": false + } + }, + "labelPlural": { + "type": "string" + } + }, + "required": [ + "name", + "label", + "associations", + "labelPlural" + ], + "additionalProperties": false + } + }, + "baseEntity": { + "type": "string", + "description": "base entity of ListReport page (if present) and first ObjectPage" + }, + "noListReportPage": { + "type": "boolean", + "description": "true: no ListReport page will generated, e.g. for applications which start with an (input enabled) Object Page to enter data" + }, + "objectPages": { + "type": "array", + "items": { + "type": "object", + "properties": { + "entityType": { + "type": "string", + "description": "Entity that the ObjectPage is based on, the first ObjectPage is always based on base entity" + }, + "tableSectionsAssociations": { + "type": "array", + "items": { + "type": "string" + }, + "description": "to-many associations of page entity for table sections shown in the ObjectPage" + } + }, + "required": [ + "entityType" + ], + "additionalProperties": false + } + }, + "namespace": { + "type": "string", + "description": "lowerCamelCase, no spaces allowed" + }, + "applicationName": { + "type": "string", + "description": "lowerCamelCase, no spaces allowed" + }, + "userInputKind": { + "enum": [ + "UserInterfaceFirst", + "DataModelFirst" + ], + "description": "use 'UserInterfaceFirst' if User input describes the app based on the user interface, i.e. how List Report and Object Pages should look like; use 'DataModelFirst' if User input describes the app based on its data model, i.e. its entities, their elements and associations" + } + }, + "required": [ + "entities", + "baseEntity", + "objectPages", + "namespace", + "applicationName", + "userInputKind" + ], + "additionalProperties": false +} + +----------Response:---------- +{ + "entities": [ + { + "name": "Travels", + "label": "Travel", + "associations": [ + { + "name": "Bookings", + "target": "Bookings" + } + ], + "labelPlural": "Travels" + }, + { + "name": "Bookings", + "label": "Booking", + "associations": [], + "labelPlural": "Bookings" + } + ], + "baseEntity": "Travels", + "noListReportPage": false, + "objectPages": [ + { + "entityType": "Travels", + "tableSectionsAssociations": [ + "Bookings" + ] + }, + { + "entityType": "Bookings", + "tableSectionsAssociations": [] + } + ], + "namespace": "travelApp", + "applicationName": "manageTravels", + "userInputKind": "DataModelFirst" +} +2024-10-28T20:25:47.413Z [info] Step "switchBasedOnAppSkeleton": case 0 blocked! Evaluation details: + - JSONPath "$.model.applications[0].pages[0]" : [{"type":"ListReport","entityType":"Travels"}] +2024-10-28T20:25:47.414Z [info] Step "switchBasedOnAppSkeleton": case 1 blocked! Evaluation details: + - JSONPath "$.model.applications[0].pages[0].type" : ["ListReport"] +2024-10-28T20:25:47.414Z [info] Step "switchBasedOnAppSkeleton": case 2 blocked! Evaluation details: + - JSONPath "$.userInput.imageCount" : [1] +2024-10-28T20:25:47.414Z [info] Step "switchBasedOnAppSkeleton": case 3 passed! Evaluation details: + - JSONPath "$.userInput.imageCount" : [1] + - JSONPath "$.userInput.lineCount" : [1] +2024-10-28T20:25:47.414Z [info] Step "switchBasedOnSingleImagesKind": case 0 passed! Evaluation details: + - JSONPath "$.imagesArray[0].extractedData.contentKind" : ["DataModel"] +2024-10-28T20:25:47.414Z [info] Step "runDataModelImageOnly": workflow "dataModelImageOnly" started +" +2024-10-28T20:25:55.133Z [info] +==========LLM call for step "extractDataModel":========== +You help the user creating the data model (entities with their associations and elements) from the users input. + +User input is the following image. + + +----------Requested Schema:--- +{ + "type": "object", + "properties": { + "namespace": { + "type": "string", + "description": "lowerCamelCase, no spaces allowed" + }, + "entities": { + "type": "array", + "items": { + "type": "object", + "description": "Mark at max 3 elements as 'essentialElement', the most essential elements. for example elements like: status, priority, state, quantity, daysProcessed.", + "properties": { + "name": { + "type": "string", + "description": "UpperCamelCase, no spaces, plural, e.g. 'Orders'" + }, + "label": { + "type": "string", + "description": "max two words, singular" + }, + "elements": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "camelCase, no spaces" + }, + "type": { + "type": "string", + "description": "Allowed values: String(50), Boolean, Integer, Decimal, Double, Date, Time, DateTime, Timestamp; String length can vary - i.e. String(20)" + }, + "key": { + "type": "boolean", + "description": "max. one optional key, only if this element is a semantic key and can uniquely identify the instance" + }, + "essentialElement": { + "type": "boolean", + "description": "'true' only if element is marked as essential'" + }, + "additionalInfo": { + "type": "string", + "description": "All additional information from user input, e.g. user description, example values; also consider referenced parts in the user input" + } + }, + "required": [ + "name", + "type", + "additionalInfo" + ], + "additionalProperties": false + }, + "description": "At least 5 realistic elements (unless explicitly specified)" + }, + "associations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "target": { + "type": "string", + "description": "Points to existing entity, value is entities.name" + }, + "multiplicity": { + "type": "string", + "enum": [ + "one", + "many" + ] + } + }, + "required": [ + "name", + "target", + "multiplicity" + ], + "additionalProperties": false + }, + "description": "Define all relationships between entities" + }, + "labelPlural": { + "type": "string" + } + }, + "required": [ + "name", + "label", + "elements", + "associations", + "labelPlural" + ], + "additionalProperties": false + } + }, + "baseEntityName": { + "type": "string", + "description": "name of the entity which can be used as base entity of a Giori Elements app - should not be the target of any 1:n association" + }, + "applicationName": { + "type": "string", + "description": "name of the Fiori Elements app that shows data of this data model" + } + }, + "required": [ + "namespace", + "entities", + "baseEntityName", + "applicationName" + ], + "additionalProperties": false +} + +----------Response:---------- +{ + "namespace": "travelManagement", + "entities": [ + { + "name": "Travel", + "label": "Travel", + "elements": [ + { + "name": "tripName", + "type": "String(50)", + "key": false, + "essentialElement": false, + "additionalInfo": "Name of the trip" + }, + { + "name": "employee", + "type": "String(50)", + "key": false, + "essentialElement": false, + "additionalInfo": "Employee associated with the trip" + }, + { + "name": "status", + "type": "String(20)", + "key": false, + "essentialElement": true, + "additionalInfo": "Status of the trip" + }, + { + "name": "tripStartDate", + "type": "Date", + "key": false, + "essentialElement": true, + "additionalInfo": "Start date of the trip" + }, + { + "name": "tripEndDate", + "type": "Date", + "key": false, + "essentialElement": true, + "additionalInfo": "End date of the trip" + }, + { + "name": "priceUSD", + "type": "Decimal", + "key": false, + "essentialElement": false, + "additionalInfo": "Price of the trip in USD" + } + ], + "associations": [ + { + "name": "bookings", + "target": "Bookings", + "multiplicity": "many" + } + ], + "labelPlural": "Travels" + }, + { + "name": "Bookings", + "label": "Booking", + "elements": [ + { + "name": "employee", + "type": "String(50)", + "key": false, + "essentialElement": false, + "additionalInfo": "Employee associated with the booking" + }, + { + "name": "airlines", + "type": "String(50)", + "key": false, + "essentialElement": false, + "additionalInfo": "Airlines for the booking" + }, + { + "name": "bookingDate", + "type": "Date", + "key": false, + "essentialElement": true, + "additionalInfo": "Date of booking" + }, + { + "name": "flightDate", + "type": "Date", + "key": false, + "essentialElement": true, + "additionalInfo": "Date of the flight" + }, + { + "name": "priceUSD", + "type": "Decimal", + "key": false, + "essentialElement": false, + "additionalInfo": "Price of the booking in USD" + } + ], + "associations": [], + "labelPlural": "Bookings" + } + ], + "baseEntityName": "Travel", + "applicationName": "Managing Travels" +} +2024-10-28T20:25:55.136Z [info] 2/5: Build CDS files +2024-10-28T20:25:55.152Z [info] 3/5: Generating mock data +2024-10-28T20:26:04.144Z [info] +==========LLM call for data generation:========== + +For the following list of entities, create data for the empty CSV files. +Entity "Travel" - Properties: + tripName: String(50), Name of the trip + employee: String(50), Employee associated with the trip + status: String(20), Status of the trip + tripStartDate: Date, Start date of the trip + tripEndDate: Date, End date of the trip + priceUSD: Decimal, Price of the trip in USD + +Entity "Bookings" - Properties: + employee: String(50), Employee associated with the booking + airlines: String(50), Airlines for the booking + bookingDate: Date, Date of booking + flightDate: Date, Date of the flight + priceUSD: Decimal, Price of the booking in USD + travel_tripName: String(50), tripName of associated Travel + +Empty CSV files in json format (only generate content for these files!): +{"Travel.csv":"tripName;employee;status;tripStartDate;tripEndDate;priceUSD","Bookings.csv":"employee;airlines;bookingDate;flightDate;priceUSD;travel_tripName"} + +Rules: + - Take over the given header line, do not invent new columns! + - For a given file, add rows, add '\n' characters before each row but don't break the JSON string + - Do not generate rows with same key values, they must be unique! + - Make sure that associations match, i.e. a field containing "Name of the associated Customer" must contain an existing Name of entity Customer + - Always use ";" as a delimiter in CSV files + - The result must be proper JSON format so it can be parsed, don't break JSON strings within, don't add quotes around values. + - Create about 5 rows for the first csv, 7 for the second and so on + - All values must be realistic with meaningful content, e.g. 'Laptop Screen' and not just placeholder values with incremented numbers like 'Product 1', 'Product 2' etc. + +Use format for values: + String(50): string no longer than 50 characters + Date: 2021-06-27 + Decimal(3,2): 1.23 + + +Example output (Do NOT include in output!): +```json +{"Blogs":"blogID;title;description;createdDateTime;views\nBlog1;Tech Blog;A blog about the latest technology trends.;2023-06-27T14:52:23Z;1000\nBlog2;Fashion Blog;Explore the world of fashion and style.;2023-06-27T14:52:23Z;500","Posts":"postID;title;content;publishDate;likes;comments;blogID\n1;The Future of Artificial Intelligence;Artificial intelligence is shaping the future of technology.;2023-06-27;50;10;Blog1 +2;Summer Fashion Trends;Discover the hottest fashion trends for the summer season.;2023-06-27;100;20;Blog2\n3;Must-Have Accessories;10 must-have accessories for the upcoming season;2023-06-27;100;20;Blog2"} +``` +Output ONLY the json contents for the csv files and try to be as accurate as possible. +The generated data should be suitable for the following User Input: + + + +----------Requested Schema:--- +{ + "type": "object", + "properties": { + "Travel.csv": { + "type": "string", + "description": "content for Travel.csv" + }, + "Bookings.csv": { + "type": "string", + "description": "content for Bookings.csv" + } + }, + "required": [ + "Travel.csv", + "Bookings.csv" + ], + "additionalProperties": false +} + +----------Response:---------- +{ + "Travel.csv": "tripName;employee;status;tripStartDate;tripEndDate;priceUSD\nSales Conference;John Doe;Confirmed;2021-07-01;2021-07-05;1500.00\nTech Expo;Jane Smith;Pending;2021-08-15;2021-08-20;2000.00\nMarketing Summit;Alice Johnson;Cancelled;2021-09-10;2021-09-12;800.00\nLeadership Retreat;Bob Brown;Confirmed;2021-10-05;2021-10-10;2500.00\nClient Meeting;Charlie Davis;Completed;2021-11-01;2021-11-03;1200.00", + "Bookings.csv": "employee;airlines;bookingDate;flightDate;priceUSD;travel_tripName\nJohn Doe;Delta Airlines;2021-06-20;2021-07-01;500.00;Sales Conference\nJohn Doe;American Airlines;2021-06-22;2021-07-05;450.00;Sales Conference\nJane Smith;United Airlines;2021-08-01;2021-08-15;600.00;Tech Expo\nAlice Johnson;Southwest Airlines;2021-09-01;2021-09-10;300.00;Marketing Summit\nBob Brown;JetBlue;2021-09-25;2021-10-05;700.00;Leadership Retreat\nCharlie Davis;Alaska Airlines;2021-10-20;2021-11-01;400.00;Client Meeting\nCharlie Davis;Spirit Airlines;2021-10-22;2021-11-03;350.00;Client Meeting" +} +2024-10-28T20:26:04.146Z [info] 4/5: Regenerating application manifest +2024-10-28T20:26:07.223Z [info] 5/5: Copying updated files to CAP project \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/.fiori-ai/model.json b/packages/project-integrity/test/test-input/valid-fiori-project/.fiori-ai/model.json new file mode 100644 index 00000000000..22f9b45e3d3 --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/.fiori-ai/model.json @@ -0,0 +1,179 @@ +{ + "namespace": "travelManagement", + "entities": [ + { + "name": "Travel", + "label": "Travel", + "elements": [ + { + "name": "ID", + "type": "UUID", + "key": true, + "label": "" + }, + { + "name": "tripName", + "type": "String(50)", + "key": false, + "essentialElement": false, + "additionalInfo": "Name of the trip", + "label": "Trip Name" + }, + { + "name": "employee", + "type": "String(50)", + "key": false, + "essentialElement": false, + "additionalInfo": "Employee associated with the trip", + "label": "Employee" + }, + { + "name": "status", + "type": "String(20)", + "key": false, + "essentialElement": true, + "additionalInfo": "Status of the trip", + "label": "Status" + }, + { + "name": "tripStartDate", + "type": "Date", + "key": false, + "essentialElement": true, + "additionalInfo": "Start date of the trip", + "label": "Trip Start Date" + }, + { + "name": "tripEndDate", + "type": "Date", + "key": false, + "essentialElement": true, + "additionalInfo": "End date of the trip", + "label": "Trip End Date" + }, + { + "name": "priceUSD", + "type": "Decimal", + "key": false, + "essentialElement": false, + "additionalInfo": "Price of the trip in USD", + "label": "Price USD" + } + ], + "associations": [ + { + "name": "bookings", + "target": "Bookings", + "multiplicity": "many", + "backAssociation": "travel" + } + ], + "labelPlural": "Travels" + }, + { + "name": "Bookings", + "label": "Booking", + "elements": [ + { + "name": "ID", + "type": "UUID", + "key": true, + "label": "" + }, + { + "name": "employee", + "type": "String(50)", + "key": false, + "essentialElement": false, + "additionalInfo": "Employee associated with the booking", + "label": "Employee" + }, + { + "name": "airlines", + "type": "String(50)", + "key": false, + "essentialElement": false, + "additionalInfo": "Airlines for the booking", + "label": "Airlines" + }, + { + "name": "bookingDate", + "type": "Date", + "key": false, + "essentialElement": true, + "additionalInfo": "Date of booking", + "label": "Booking Date" + }, + { + "name": "flightDate", + "type": "Date", + "key": false, + "essentialElement": true, + "additionalInfo": "Date of the flight", + "label": "Flight Date" + }, + { + "name": "priceUSD", + "type": "Decimal", + "key": false, + "essentialElement": false, + "additionalInfo": "Price of the booking in USD", + "label": "Price USD" + } + ], + "associations": [ + { + "name": "travel", + "target": "Travel", + "multiplicity": "one", + "isComposition": false + } + ], + "labelPlural": "Bookings" + } + ], + "service": { + "name": "travelManagementSrv", + "path": "srv/service.cds" + }, + "applications": [ + { + "name": "TravelManagement", + "pages": [ + { + "type": "ListReport", + "entityType": "Travel", + "listReportContent": { + "loadDataOnAppLaunch": "Enabled", + "filters": [ + "status", + "tripStartDate", + "tripEndDate" + ], + "tables": [] + } + }, + { + "type": "ObjectPage", + "entityType": "Travel", + "objectPageContent": { + "sections": [], + "tabs": [], + "tableSectionAssociations": [ + "bookings" + ] + } + }, + { + "type": "ObjectPage", + "entityType": "Bookings", + "objectPageContent": { + "sections": [], + "tabs": [], + "tableSectionAssociations": [] + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/.fiori-ai/user-input.txt b/packages/project-integrity/test/test-input/valid-fiori-project/.fiori-ai/user-input.txt new file mode 100644 index 00000000000..801992f0c18 --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/.fiori-ai/user-input.txt @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/.fiori-ai/userImage.png b/packages/project-integrity/test/test-input/valid-fiori-project/.fiori-ai/userImage.png new file mode 100644 index 00000000000..362318a3d31 Binary files /dev/null and b/packages/project-integrity/test/test-input/valid-fiori-project/.fiori-ai/userImage.png differ diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/.gitignore b/packages/project-integrity/test/test-input/valid-fiori-project/.gitignore new file mode 100644 index 00000000000..bf21225f8d8 --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/.gitignore @@ -0,0 +1,34 @@ +# CAP fiori-tools-ai +_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/project-integrity/test/test-input/valid-fiori-project/.vscode/extensions.json b/packages/project-integrity/test/test-input/valid-fiori-project/.vscode/extensions.json new file mode 100644 index 00000000000..d558687bc36 --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/.vscode/extensions.json @@ -0,0 +1,18 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. + // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp + + // List of extensions which should be recommended for users of this workspace. + "recommendations": [ + "SAPSE.vscode-cds", + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "mechatroner.rainbow-csv", + "qwtel.sqlite-viewer", + "humao.rest-client" + ], + // List of extensions recommended by VS Code that should not be recommended for users of this workspace. + "unwantedRecommendations": [ + + ] +} diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/.vscode/launch.json b/packages/project-integrity/test/test-input/valid-fiori-project/.vscode/launch.json new file mode 100644 index 00000000000..188a19c4f1d --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/.vscode/launch.json @@ -0,0 +1,20 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "cds serve", + "request": "launch", + "type": "node", + "cwd": "${workspaceFolder}", + "runtimeExecutable": "cds", + "args": [ + "serve", + "--with-mocks", + "--in-memory?" + ], + "skipFiles": [ + "/**" + ] + } + ] +} diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/.vscode/settings.json b/packages/project-integrity/test/test-input/valid-fiori-project/.vscode/settings.json new file mode 100644 index 00000000000..aa9de54c844 --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + // uncomment entries once all libraries have been installed via 'npm install' + "eslint.validate": [ + // "cds", + // "csn", + // "csv", + // "csv (semicolon)", + // "tab", + // "tsv" + ] +} \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/.vscode/tasks.json b/packages/project-integrity/test/test-input/valid-fiori-project/.vscode/tasks.json new file mode 100644 index 00000000000..68697ef7257 --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/.vscode/tasks.json @@ -0,0 +1,25 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "type": "shell", + "label": "cds watch", + "command": "cds", + "args": ["watch"], + "group": { + "kind": "build", + "isDefault": true + }, + "problemMatcher": [] + }, + { + "type": "shell", + "label": "cds serve", + "command": "cds", + "args": ["serve", "--with-mocks", "--in-memory?"], + "problemMatcher": [] + } + ] +} diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/README.md b/packages/project-integrity/test/test-input/valid-fiori-project/README.md new file mode 100644 index 00000000000..dbac29eb159 --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/README.md @@ -0,0 +1,25 @@ +# Getting Started + +Welcome to your new project. + +It contains these folders and files, following our recommended project layout: + +File or Folder | Purpose +---------|---------- +`app/` | content for UI frontends goes here +`db/` | your domain models and data go here +`srv/` | your service models and code go here +`package.json` | project metadata and configuration +`readme.md` | this getting started guide + + +## Next Steps + +- Open a new terminal and run `cds watch` +- (in VS Code simply choose _**Terminal** > Run Task > cds watch_) +- Start adding content, for example, a [db/schema.cds](db/schema.cds). + + +## Learn More + +Learn more at https://cap.cloud.sap/docs/get-started/. diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/app/services.cds b/packages/project-integrity/test/test-input/valid-fiori-project/app/services.cds new file mode 100644 index 00000000000..81b0dc78c14 --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/app/services.cds @@ -0,0 +1,2 @@ + +using from './travelmanagement/annotations'; \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/README.md b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/README.md new file mode 100644 index 00000000000..0b3083b8991 --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/README.md @@ -0,0 +1,35 @@ +## Application Details +| | +| ------------- | +|**Generation Date and Time**
Mon Oct 21 2024 13:50:13 GMT-0700 (Pacific Daylight Time)| +|**App Generator**
@sap/generator-fiori-elements| +|**App Generator Version**
1.15.3-pre-20241016112524-cb4533d78.0| +|**Generation Platform**
CLI| +|**Template Used**
List Report Page V4| +|**Service Type**
Local Cap| +|**Service URL**
http://localhost:4004/odata/v4/travel-management-srv/| +|**Module Name**
travelmanagement| +|**Application Title**
AI generated App travelmanagement| +|**Namespace**
| +|**UI5 Theme**
sap_horizon| +|**UI5 Version**
1.126.0| +|**Enable Code Assist Libraries**
False| +|**Enable TypeScript**
False| +|**Add Eslint configuration**
False| +|**Main Entity**
Travel| + +## travelmanagement + +AI generated App travelmanagement + +### Starting the generated app + +- This app has been generated using the SAP Fiori tools - App Generator, as part of the SAP Fiori tools suite. In order to launch the generated app, simply start your CAP project and navigate to the following location in your browser: + +http://localhost:4004/travelmanagement/webapp/index.html + +#### Pre-requisites: + +1. Active NodeJS LTS (Long Term Support) version and associated supported NPM version. (See https://nodejs.org) + + diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/annotations.cds b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/annotations.cds new file mode 100644 index 00000000000..9482676c469 --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/annotations.cds @@ -0,0 +1,148 @@ +using { travelManagementSrv } from '../../srv/service.cds'; + +annotate travelManagementSrv.Travel with @UI.DataPoint #status: { + Value: status, + Title: 'Status', +}; +annotate travelManagementSrv.Travel with @UI.DataPoint #tripStartDate: { + Value: tripStartDate, + Title: 'Trip Start Date', +}; +annotate travelManagementSrv.Travel with @UI.DataPoint #tripEndDate: { + Value: tripEndDate, + Title: 'Trip End Date', +}; +annotate travelManagementSrv.Travel with @UI.HeaderFacets: [ + { $Type : 'UI.ReferenceFacet', Target : '@UI.DataPoint#status', ID: 'Status' }, + { $Type : 'UI.ReferenceFacet', Target : '@UI.DataPoint#tripStartDate', ID: 'TripStartDate' }, + { $Type : 'UI.ReferenceFacet', Target : '@UI.DataPoint#tripEndDate', ID: 'TripEndDate' } +]; +annotate travelManagementSrv.Travel with @UI.HeaderInfo: { + TypeName: 'Travel', + TypeNamePlural: 'Travels' +}; +annotate travelManagementSrv.Travel with { + tripName @Common.Label: 'Trip Name'; + employee @Common.Label: 'Employee'; + status @Common.Label: 'Status'; + tripStartDate @Common.Label: 'Trip Start Date'; + tripEndDate @Common.Label: 'Trip End Date'; + priceUSD @Common.Label: 'Price USD'; + bookings @Common.Label: 'Bookings' +}; +annotate travelManagementSrv.Travel with @UI.SelectionFields : [ + status, + tripStartDate, + tripEndDate +]; +annotate travelManagementSrv.Travel with @UI.LineItem: [ + { $Type: 'UI.DataField', Value: tripName }, + { $Type: 'UI.DataField', Value: employee }, + { $Type: 'UI.DataField', Value: status }, + { $Type: 'UI.DataField', Value: tripStartDate }, + { $Type: 'UI.DataField', Value: tripEndDate }, + { $Type: 'UI.DataField', Value: priceUSD } +]; +annotate travelManagementSrv.Travel with @UI.FieldGroup #Main: { + $Type: 'UI.FieldGroupType', Data: [ + { $Type: 'UI.DataField', Value: tripName }, + { $Type: 'UI.DataField', Value: employee }, + { $Type: 'UI.DataField', Value: status }, + { $Type: 'UI.DataField', Value: tripStartDate }, + { $Type: 'UI.DataField', Value: tripEndDate }, + { $Type: 'UI.DataField', Value: priceUSD } +]}; +annotate travelManagementSrv.Bookings with @UI.LineItem #Travel_bookings: [ + { $Type: 'UI.DataField', Value: employee }, + { $Type: 'UI.DataField', Value: airlines }, + { $Type: 'UI.DataField', Value: bookingDate }, + { $Type: 'UI.DataField', Value: flightDate }, + { $Type: 'UI.DataField', Value: priceUSD } +]; +annotate travelManagementSrv.Travel with @UI.Facets: [ + { $Type: 'UI.ReferenceFacet', ID: 'Main', Label: 'General Information', Target: '@UI.FieldGroup#Main' }, + { $Type: 'UI.ReferenceFacet', ID: 'bookings', Label: 'Bookings', Target: 'bookings/@UI.LineItem#Travel_bookings' } +]; +annotate travelManagementSrv.Bookings with { + travel @Common.ValueList: { + CollectionPath: 'Travel', + Parameters : [ + { + $Type : 'Common.ValueListParameterInOut', + LocalDataProperty: travel_ID, + ValueListProperty: 'ID' + }, + { + $Type : 'Common.ValueListParameterDisplayOnly', + ValueListProperty: 'tripName' + }, + { + $Type : 'Common.ValueListParameterDisplayOnly', + ValueListProperty: 'employee' + }, + { + $Type : 'Common.ValueListParameterDisplayOnly', + ValueListProperty: 'status' + }, + { + $Type : 'Common.ValueListParameterDisplayOnly', + ValueListProperty: 'tripStartDate' + }, + { + $Type : 'Common.ValueListParameterDisplayOnly', + ValueListProperty: 'tripEndDate' + }, + { + $Type : 'Common.ValueListParameterDisplayOnly', + ValueListProperty: 'priceUSD' + }, + ], + } +}; +annotate travelManagementSrv.Bookings with @UI.DataPoint #bookingDate: { + Value: bookingDate, + Title: 'Booking Date', +}; +annotate travelManagementSrv.Bookings with @UI.DataPoint #flightDate: { + Value: flightDate, + Title: 'Flight Date', +}; +annotate travelManagementSrv.Bookings with @UI.HeaderFacets: [ + { $Type : 'UI.ReferenceFacet', Target : '@UI.DataPoint#bookingDate', ID: 'BookingDate' }, + { $Type : 'UI.ReferenceFacet', Target : '@UI.DataPoint#flightDate', ID: 'FlightDate' } +]; +annotate travelManagementSrv.Bookings with @UI.HeaderInfo: { + TypeName: 'Booking', + TypeNamePlural: 'Bookings' +}; +annotate travelManagementSrv.Bookings with { + employee @Common.Label: 'Employee'; + airlines @Common.Label: 'Airlines'; + bookingDate @Common.Label: 'Booking Date'; + flightDate @Common.Label: 'Flight Date'; + priceUSD @Common.Label: 'Price USD'; + travel @Common.Label: 'Travel' +}; +annotate travelManagementSrv.Bookings with @UI.SelectionFields: [ + travel_ID +]; +annotate travelManagementSrv.Bookings with @UI.LineItem: [ + { $Type: 'UI.DataField', Value: employee }, + { $Type: 'UI.DataField', Value: airlines }, + { $Type: 'UI.DataField', Value: bookingDate }, + { $Type: 'UI.DataField', Value: flightDate }, + { $Type: 'UI.DataField', Value: priceUSD }, + { $Type: 'UI.DataField', Label: 'Travel', Value: travel_ID } +]; +annotate travelManagementSrv.Bookings with @UI.FieldGroup #Main: { + $Type: 'UI.FieldGroupType', Data: [ + { $Type: 'UI.DataField', Value: employee }, + { $Type: 'UI.DataField', Value: airlines }, + { $Type: 'UI.DataField', Value: bookingDate }, + { $Type: 'UI.DataField', Value: flightDate }, + { $Type: 'UI.DataField', Value: priceUSD }, + { $Type: 'UI.DataField', Label: 'Travel', Value: travel_ID } +]}; +annotate travelManagementSrv.Bookings with @UI.Facets: [ + { $Type: 'UI.ReferenceFacet', ID: 'Main', Label: 'General Information', Target: '@UI.FieldGroup#Main' } +]; \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/package.json b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/package.json new file mode 100644 index 00000000000..e0e5a202b34 --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/package.json @@ -0,0 +1,19 @@ +{ + "name": "travelmanagement", + "version": "0.0.1", + "description": "AI generated App travelmanagement", + "keywords": [ + "ui5", + "openui5", + "sapui5" + ], + "main": "webapp/index.html", + "dependencies": {}, + "devDependencies": { + "@ui5/cli": "^3.0.0", + "@sap/ux-ui5-tooling": "1" + }, + "scripts": { + "deploy-config": "npx -p @sap/ux-ui5-tooling fiori add deploy-config cf" + } +} diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/ui5.yaml b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/ui5.yaml new file mode 100644 index 00000000000..c8a0728ea5d --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/ui5.yaml @@ -0,0 +1,23 @@ +# yaml-language-server: $schema=https://sap.github.io/ui5-tooling/schema/ui5.yaml.json + +specVersion: "3.1" +metadata: + name: travelmanagement +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://sapui5.hana.ondemand.com + - name: fiori-tools-appreload + afterMiddleware: compression + configuration: + port: 35729 + path: webapp + delay: 300 diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/Component.js b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/Component.js new file mode 100644 index 00000000000..e4eb4a1b53e --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/Component.js @@ -0,0 +1,12 @@ +sap.ui.define( + ["sap/fe/core/AppComponent"], + function (Component) { + "use strict"; + + return Component.extend("travelmanagement.Component", { + metadata: { + manifest: "json" + } + }); + } +); \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/i18n/i18n.properties b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/i18n/i18n.properties new file mode 100644 index 00000000000..c71fd9b259c --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/i18n/i18n.properties @@ -0,0 +1,9 @@ +# This is the resource bundle for travelmanagement + +#Texts for manifest.json + +#XTIT: Application name +appTitle=AI generated App travelmanagement + +#YDES: Application description +appDescription=AI generated App travelmanagement \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/index.html b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/index.html new file mode 100644 index 00000000000..85f0adb203e --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/index.html @@ -0,0 +1,35 @@ + + + + + + + AI generated App travelmanagement + + + + +
+ + \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/manifest.json b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/manifest.json new file mode 100644 index 00000000000..28d040976b1 --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/manifest.json @@ -0,0 +1,156 @@ +{ + "_version": "1.65.0", + "sap.app": { + "id": "travelmanagement", + "type": "application", + "i18n": "i18n/i18n.properties", + "applicationVersion": { + "version": "0.0.1" + }, + "title": "{{appTitle}}", + "description": "{{appDescription}}", + "resources": "resources.json", + "sourceTemplate": { + "id": "@sap/generator-fiori:lrop", + "version": "1.15.3-pre-20241016112524-cb4533d78.0", + "toolsId": "4d8f2790-c93f-4c0c-9c83-5786770b1d8f" + }, + "dataSources": { + "mainService": { + "uri": "/odata/v4/travel-management-srv/", + "type": "OData", + "settings": { + "annotations": [], + "odataVersion": "4.0" + } + } + } + }, + "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.126.0", + "libs": { + "sap.m": {}, + "sap.ui.core": {}, + "sap.fe.templates": {} + } + }, + "contentDensities": { + "compact": true, + "cozy": true + }, + "models": { + "i18n": { + "type": "sap.ui.model.resource.ResourceModel", + "settings": { + "bundleName": "travelmanagement.i18n.i18n" + } + }, + "": { + "dataSource": "mainService", + "preload": true, + "settings": { + "operationMode": "Server", + "autoExpandSelect": true, + "earlyRequests": true + } + }, + "@i18n": { + "type": "sap.ui.model.resource.ResourceModel", + "uri": "i18n/i18n.properties" + } + }, + "resources": { + "css": [] + }, + "routing": { + "config": {}, + "routes": [ + { + "pattern": ":?query:", + "name": "TravelList", + "target": "TravelList" + }, + { + "pattern": "Travel({key}):?query:", + "name": "TravelObjectPage", + "target": "TravelObjectPage" + }, + { + "pattern": "Travel({key})/bookings({key2}):?query:", + "name": "BookingsObjectPage", + "target": "BookingsObjectPage" + } + ], + "targets": { + "TravelList": { + "type": "Component", + "id": "TravelList", + "name": "sap.fe.templates.ListReport", + "options": { + "settings": { + "contextPath": "/Travel", + "variantManagement": "Page", + "initialLoad": "Enabled", + "navigation": { + "Travel": { + "detail": { + "route": "TravelObjectPage" + } + } + } + } + } + }, + "TravelObjectPage": { + "type": "Component", + "id": "TravelObjectPage", + "name": "sap.fe.templates.ObjectPage", + "options": { + "settings": { + "contextPath": "/Travel", + "navigation": { + "bookings": { + "detail": { + "route": "BookingsObjectPage" + } + } + } + } + } + }, + "BookingsObjectPage": { + "type": "Component", + "id": "BookingsObjectPage", + "name": "sap.fe.templates.ObjectPage", + "options": { + "settings": { + "contextPath": "/Travel/bookings" + } + } + } + } + } + }, + "sap.fiori": { + "registrationIds": [], + "archeType": "transactional" + } +} \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/test/flpSandbox.html b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/test/flpSandbox.html new file mode 100644 index 00000000000..298e0859716 --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/test/flpSandbox.html @@ -0,0 +1,84 @@ + + + + + + + + {{appTitle}} + + + + + + + + + + + + + + + + diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/test/integration/FirstJourney.js b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/test/integration/FirstJourney.js new file mode 100644 index 00000000000..bd9533fd024 --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/test/integration/FirstJourney.js @@ -0,0 +1,38 @@ +sap.ui.define([ + "sap/ui/test/opaQunit" +], function (opaTest) { + "use strict"; + + var Journey = { + run: function() { + QUnit.module("First journey"); + + opaTest("Start application", function (Given, When, Then) { + Given.iStartMyApp(); + + Then.onTheTravelList.iSeeThisPage(); + + }); + + + opaTest("Navigate to ObjectPage", function (Given, When, Then) { + // Note: this test will fail if the ListReport page doesn't show any data + + When.onTheTravelList.onFilterBar().iExecuteSearch(); + + Then.onTheTravelList.onTable().iCheckRows(); + + When.onTheTravelList.onTable().iPressRow(0); + Then.onTheTravelObjectPage.iSeeThisPage(); + + }); + + opaTest("Teardown", function (Given, When, Then) { + // Cleanup + Given.iTearDownMyApp(); + }); + } + } + + return Journey; +}); \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/test/integration/opaTests.qunit.html b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/test/integration/opaTests.qunit.html new file mode 100644 index 00000000000..d032ebe3711 --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/test/integration/opaTests.qunit.html @@ -0,0 +1,30 @@ + + + + Integration tests + + + + + + + + + + + + + +
+
+ + \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/test/integration/opaTests.qunit.js b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/test/integration/opaTests.qunit.js new file mode 100644 index 00000000000..6740434445a --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/test/integration/opaTests.qunit.js @@ -0,0 +1,26 @@ +sap.ui.require( + [ + 'sap/fe/test/JourneyRunner', + 'travelmanagement/test/integration/FirstJourney', + 'travelmanagement/test/integration/pages/TravelList', + 'travelmanagement/test/integration/pages/TravelObjectPage' + ], + function(JourneyRunner, opaJourney, TravelList, TravelObjectPage) { + 'use strict'; + var JourneyRunner = new JourneyRunner({ + // start index.html in web folder + launchUrl: sap.ui.require.toUrl('travelmanagement') + '/index.html' + }); + + + JourneyRunner.run( + { + pages: { + onTheTravelList: TravelList, + onTheTravelObjectPage: TravelObjectPage + } + }, + opaJourney.run + ); + } +); \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/test/integration/pages/TravelList.js b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/test/integration/pages/TravelList.js new file mode 100644 index 00000000000..e3d058424c5 --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/test/integration/pages/TravelList.js @@ -0,0 +1,17 @@ +sap.ui.define(['sap/fe/test/ListReport'], function(ListReport) { + 'use strict'; + + var CustomPageDefinitions = { + actions: {}, + assertions: {} + }; + + return new ListReport( + { + appId: 'travelmanagement', + componentId: 'TravelList', + contextPath: '/Travel' + }, + CustomPageDefinitions + ); +}); \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/test/integration/pages/TravelObjectPage.js b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/test/integration/pages/TravelObjectPage.js new file mode 100644 index 00000000000..cbb69247c14 --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/test/integration/pages/TravelObjectPage.js @@ -0,0 +1,17 @@ +sap.ui.define(['sap/fe/test/ObjectPage'], function(ObjectPage) { + 'use strict'; + + var CustomPageDefinitions = { + actions: {}, + assertions: {} + }; + + return new ObjectPage( + { + appId: 'travelmanagement', + componentId: 'TravelObjectPage', + contextPath: '/Travel' + }, + CustomPageDefinitions + ); +}); \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/test/testsuite.qunit.html b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/test/testsuite.qunit.html new file mode 100644 index 00000000000..1fea4a26d91 --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/test/testsuite.qunit.html @@ -0,0 +1,9 @@ + + + + QUnit test suite + + + + + \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/test/testsuite.qunit.js b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/test/testsuite.qunit.js new file mode 100644 index 00000000000..a37a5c973c3 --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/app/travelmanagement/webapp/test/testsuite.qunit.js @@ -0,0 +1,11 @@ +window.suite = function() { + 'use strict'; + + // eslint-disable-next-line + var oSuite = new parent.jsUnitTestSuite(), + + sContextPath = location.pathname.substring(0, location.pathname.lastIndexOf('/') + 1); + oSuite.addTestPage(sContextPath + 'integration/opaTests.qunit.html'); + + return oSuite; +}; \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/db/schema.cds b/packages/project-integrity/test/test-input/valid-fiori-project/db/schema.cds new file mode 100644 index 00000000000..230b93decf9 --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/db/schema.cds @@ -0,0 +1,22 @@ +namespace travelManagement; + +entity Travel { + key ID: UUID; + tripName: String(50); + employee: String(50); + status: String(20); + tripStartDate: Date; + tripEndDate: Date; + priceUSD: Decimal; + bookings: Association to many Bookings on bookings.travel = $self; +} + +entity Bookings { + key ID: UUID; + employee: String(50); + airlines: String(50); + bookingDate: Date; + flightDate: Date; + priceUSD: Decimal; + travel: Association to Travel; +} diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/eslint.config.mjs b/packages/project-integrity/test/test-input/valid-fiori-project/eslint.config.mjs new file mode 100644 index 00000000000..2fdb4320ca3 --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/eslint.config.mjs @@ -0,0 +1,2 @@ +import cds from '@sap/cds/eslint.config.mjs' +export default [ ...cds.recommended ] diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/package-lock.json b/packages/project-integrity/test/test-input/valid-fiori-project/package-lock.json new file mode 100644 index 00000000000..4709b86393b --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/package-lock.json @@ -0,0 +1,2974 @@ +{ + "name": "fiori-tools-ai", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fiori-tools-ai", + "version": "1.0.0", + "license": "UNLICENSED", + "dependencies": { + "@sap/cds": "^8", + "express": "^4" + }, + "devDependencies": { + "@cap-js/cds-types": "^0.6", + "@cap-js/sqlite": "^1", + "@sap/ux-specification": "UI5-1.126" + } + }, + "node_modules/@babel/runtime": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.7.tgz", + "integrity": "sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@cap-js/cds-types": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@cap-js/cds-types/-/cds-types-0.6.5.tgz", + "integrity": "sha512-lcsc0Bp9aINW2cQIqaadGZ1lSWqCmk9lagoyoHfQimddbSngexevoBm7RDOL9s/L4RMKGO+kBumcPq5sBBU9SA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@types/express": "^4.17.21" + }, + "peerDependencies": { + "@sap/cds": "^8.0.0" + } + }, + "node_modules/@cap-js/db-service": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@cap-js/db-service/-/db-service-1.14.0.tgz", + "integrity": "sha512-2OgzjRhrRhRYmwDLfQubUTszsigSxj/NAIAjUPrWcBMzY56fHTexpnclCr+pr0T07jMajiHfBqkz0YjGwtH1kw==", + "dev": true, + "dependencies": { + "generic-pool": "^3.9.0" + }, + "peerDependencies": { + "@sap/cds": ">=7.9" + } + }, + "node_modules/@cap-js/sqlite": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@cap-js/sqlite/-/sqlite-1.7.4.tgz", + "integrity": "sha512-UGKd4wUwli4ZLdailbtigeNFKQnhwRmA5ei1LmJnX0K61j4tTIAUQG+2AqN73707yOKMhas3B9fdvlSs1Vw67A==", + "dev": true, + "dependencies": { + "@cap-js/db-service": "^1.9.0", + "better-sqlite3": "^11.0.0" + }, + "peerDependencies": { + "@sap/cds": ">=7.6" + } + }, + "node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@dabh/diagnostics": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", + "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", + "dev": true, + "dependencies": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@sap-ux/annotation-converter": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@sap-ux/annotation-converter/-/annotation-converter-0.8.0.tgz", + "integrity": "sha512-LrTDVMRGC2V5xphaB9cDDJMxsK+YBjNbObmQcHJCk6TL2P/trcZzV2UKDsckVv43ZCXjYGK5jkhkbiGgaLbokA==", + "dev": true, + "dependencies": { + "@sap-ux/vocabularies-types": "0.10.0" + } + }, + "node_modules/@sap-ux/annotation-converter/node_modules/@sap-ux/vocabularies-types": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@sap-ux/vocabularies-types/-/vocabularies-types-0.10.0.tgz", + "integrity": "sha512-uTQ2tJJes9qGGAn8e/Npvy0grIul3mAVHzjxsj10U3lF+RZsoFawsdYGxvb6sJYkhY+YEsQzL8GTL6tyYpMv8g==", + "dev": true, + "engines": { + "node": ">=18.0.0 < 19.0.0 || >=20.0.0 < 21.0.0", + "pnpm": ">=8" + } + }, + "node_modules/@sap-ux/cds-annotation-parser": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@sap-ux/cds-annotation-parser/-/cds-annotation-parser-0.2.2.tgz", + "integrity": "sha512-PBMvH8o8Brg/VihhPEsGUu4gac7xi70zvvHJ8xScPU5sLa5B7K0bpnbbStYU4luqqYL4UXJVqJNdWqpTp4li6w==", + "dev": true, + "dependencies": { + "@sap-ux/odata-annotation-core": "0.2.1", + "@sap-ux/odata-entity-model": "0.3.0", + "@sap-ux/odata-vocabularies": "0.4.2", + "@sap-ux/text-document-utils": "0.2.0", + "chevrotain": "7.1.1" + } + }, + "node_modules/@sap-ux/cds-odata-annotation-converter": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@sap-ux/cds-odata-annotation-converter/-/cds-odata-annotation-converter-0.3.6.tgz", + "integrity": "sha512-45QozhF3JJgycpmDdodq8Pil3K1acCzvh03UN9xILEURIjKY8ZA4gGVQPCrUHftXqNSidL0XzBHkQt1epIlrAA==", + "dev": true, + "dependencies": { + "@sap-ux/cds-annotation-parser": "0.2.2", + "@sap-ux/odata-annotation-core": "0.2.1", + "@sap-ux/odata-vocabularies": "0.4.2", + "@sap-ux/text-document-utils": "0.2.0", + "@sap/ux-cds-compiler-facade": "1.15.0", + "i18next": "20.6.1" + } + }, + "node_modules/@sap-ux/cds-odata-annotation-converter/node_modules/i18next": { + "version": "20.6.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-20.6.1.tgz", + "integrity": "sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.12.0" + } + }, + "node_modules/@sap-ux/fe-fpm-writer": { + "version": "0.31.4", + "resolved": "https://registry.npmjs.org/@sap-ux/fe-fpm-writer/-/fe-fpm-writer-0.31.4.tgz", + "integrity": "sha512-qPA5bupuZpK7rK2ZVuQdZQ3Cif49Qfi0e9ksKMuio75M1TBtnlHZyYvdBlNnOG33yAwGT69Ewamg1xf+rZbSVQ==", + "dev": true, + "dependencies": { + "@sap-ux/annotation-converter": "0.8.0", + "@sap-ux/fiori-annotation-api": "0.2.4", + "@sap-ux/project-access": "1.27.4", + "@sap-ux/vocabularies-types": "0.10.0", + "@xmldom/xmldom": "0.8.10", + "ejs": "3.1.10", + "i18next": "21.6.11", + "i18next-fs-backend": "1.1.1", + "mem-fs": "2.1.0", + "mem-fs-editor": "9.4.0", + "semver": "7.5.4", + "xml-formatter": "2.6.1", + "xpath": "0.0.33" + }, + "engines": { + "node": ">=18.x" + } + }, + "node_modules/@sap-ux/fe-fpm-writer/node_modules/@sap-ux/vocabularies-types": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@sap-ux/vocabularies-types/-/vocabularies-types-0.10.0.tgz", + "integrity": "sha512-uTQ2tJJes9qGGAn8e/Npvy0grIul3mAVHzjxsj10U3lF+RZsoFawsdYGxvb6sJYkhY+YEsQzL8GTL6tyYpMv8g==", + "dev": true, + "engines": { + "node": ">=18.0.0 < 19.0.0 || >=20.0.0 < 21.0.0", + "pnpm": ">=8" + } + }, + "node_modules/@sap-ux/fiori-annotation-api": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@sap-ux/fiori-annotation-api/-/fiori-annotation-api-0.2.4.tgz", + "integrity": "sha512-RWo4sJOOWi9rHdyvbD/u5wHRo+7awnKiqJnFQ8ofhgQEvvkhH9bsPE1IxDUY6hHFoB5QTHA0GZyH06wzRDXQ1w==", + "dev": true, + "dependencies": { + "@sap-ux/annotation-converter": "0.8.0", + "@sap-ux/cds-annotation-parser": "0.2.2", + "@sap-ux/cds-odata-annotation-converter": "0.3.6", + "@sap-ux/logger": "0.6.0", + "@sap-ux/odata-annotation-core": "0.2.1", + "@sap-ux/odata-annotation-core-types": "0.4.1", + "@sap-ux/odata-entity-model": "0.3.0", + "@sap-ux/odata-vocabularies": "0.4.2", + "@sap-ux/project-access": "1.27.4", + "@sap-ux/vocabularies-types": "0.10.0", + "@sap-ux/xml-odata-annotation-converter": "0.3.1", + "@sap/ux-cds-compiler-facade": "1.15.0", + "@xml-tools/ast": "5.0.5", + "@xml-tools/parser": "1.0.11", + "mem-fs": "2.1.0", + "mem-fs-editor": "9.4.0", + "vscode-languageserver-textdocument": "1.0.8" + } + }, + "node_modules/@sap-ux/fiori-annotation-api/node_modules/@sap-ux/vocabularies-types": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@sap-ux/vocabularies-types/-/vocabularies-types-0.10.0.tgz", + "integrity": "sha512-uTQ2tJJes9qGGAn8e/Npvy0grIul3mAVHzjxsj10U3lF+RZsoFawsdYGxvb6sJYkhY+YEsQzL8GTL6tyYpMv8g==", + "dev": true, + "engines": { + "node": ">=18.0.0 < 19.0.0 || >=20.0.0 < 21.0.0", + "pnpm": ">=8" + } + }, + "node_modules/@sap-ux/i18n": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@sap-ux/i18n/-/i18n-0.2.0.tgz", + "integrity": "sha512-PVaf1xWsRzvbkjduwI1EPx4df/+bfzwfDsbe/aN3aJpbLV47Cao6X03JM8H12Jg7xT5N11Zn2nYNfSbSGGdsMg==", + "dev": true, + "dependencies": { + "@sap-ux/text-document-utils": "0.2.0", + "jsonc-parser": "3.2.0", + "vscode-languageserver-textdocument": "1.0.7" + }, + "engines": { + "node": ">=18.x" + } + }, + "node_modules/@sap-ux/i18n/node_modules/vscode-languageserver-textdocument": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.7.tgz", + "integrity": "sha512-bFJH7UQxlXT8kKeyiyu41r22jCZXG8kuuVVA33OEJn1diWOZK5n8zBSPZFHVBOu8kXZ6h0LIRhf5UnCo61J4Hg==", + "dev": true + }, + "node_modules/@sap-ux/logger": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@sap-ux/logger/-/logger-0.6.0.tgz", + "integrity": "sha512-/p9Lv3GXdASJbs5CLJy69t2OLRK6VG2zOL/jLRyOPEK1tcZYFF/LerBYDFfFxkvCpHz+cYvUJuhAmxqljLxmJw==", + "dev": true, + "dependencies": { + "chalk": "4.1.2", + "lodash": "4.17.21", + "winston": "3.11.0", + "winston-transport": "4.7.0" + }, + "engines": { + "node": ">=18.x" + } + }, + "node_modules/@sap-ux/odata-annotation-core": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@sap-ux/odata-annotation-core/-/odata-annotation-core-0.2.1.tgz", + "integrity": "sha512-HHue359RcSXfn32S578oPkcuvHMGbU0GekFGV2YWuJ3RANcGeAMqatE9gIHzei7I5mNDTPgeEmYEFFhv4+upSA==", + "dev": true, + "dependencies": { + "@sap-ux/odata-annotation-core-types": "0.4.1", + "@sap-ux/text-document-utils": "0.2.0" + } + }, + "node_modules/@sap-ux/odata-annotation-core-types": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@sap-ux/odata-annotation-core-types/-/odata-annotation-core-types-0.4.1.tgz", + "integrity": "sha512-pWu7h3BgWftFvOkafdYVW/8fUJ7EfBDn4jWZREt1DqGbMjmhNtTlbipQ6krRZZ9gs/Y7DHMrx3lyDfsCZ7WC1Q==", + "dev": true, + "dependencies": { + "@sap-ux/text-document-utils": "0.2.0" + } + }, + "node_modules/@sap-ux/odata-entity-model": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@sap-ux/odata-entity-model/-/odata-entity-model-0.3.0.tgz", + "integrity": "sha512-vWOHb9F6758nV4lIz7dO+p0EeE/lpOM+9g4S7AK383YgRYaAE3kn1Sdh76aF+C7D97E1r2Iia7nobExDbEpYfA==", + "dev": true + }, + "node_modules/@sap-ux/odata-vocabularies": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@sap-ux/odata-vocabularies/-/odata-vocabularies-0.4.2.tgz", + "integrity": "sha512-7u8t9rwuufbBcLVT/tXmNxwN54GkHcuztKbEKUb5dPqBaIqsTb9g7nmHANDVOaqoLjMUk1c8dX7k7U/QE0GlhA==", + "dev": true, + "dependencies": { + "@sap-ux/odata-annotation-core-types": "0.4.1" + } + }, + "node_modules/@sap-ux/project-access": { + "version": "1.27.4", + "resolved": "https://registry.npmjs.org/@sap-ux/project-access/-/project-access-1.27.4.tgz", + "integrity": "sha512-OURZXN3RmeqVmM4+FzR/W1m94wmA9+lT/f0FCtUlISbvbvq7R3JIyFKO1bqL8pj7dZcIIQql0IMW6plyA4y29A==", + "dev": true, + "dependencies": { + "@sap-ux/i18n": "0.2.0", + "@sap-ux/ui5-config": "0.25.0", + "fast-xml-parser": "4.4.1", + "findit2": "2.2.3", + "json-parse-even-better-errors": "3.0.2", + "mem-fs": "2.1.0", + "mem-fs-editor": "9.4.0", + "semver": "7.5.4" + }, + "engines": { + "node": ">=18.x" + } + }, + "node_modules/@sap-ux/text-document-utils": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@sap-ux/text-document-utils/-/text-document-utils-0.2.0.tgz", + "integrity": "sha512-igbsYKY05afkWfehWgapMmCub4L9a8YJxesYcRk00JHffCanfl7N9Pf9xmxflzQUKUKLPkfE/Vjicq1AImOqSg==", + "dev": true, + "dependencies": { + "vscode-languageserver-types": "3.17.2" + }, + "engines": { + "node": ">=18.x" + } + }, + "node_modules/@sap-ux/ui5-config": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@sap-ux/ui5-config/-/ui5-config-0.25.0.tgz", + "integrity": "sha512-Yisd6b6anNvDNqGzYDc6uboFbq8mkq/tmG+GffVqsnuVO1sWttReppJGKsYqozPXM6jYN6ZLMdHyuzN7zdNvUA==", + "dev": true, + "dependencies": { + "@sap-ux/yaml": "0.16.0", + "lodash": "4.17.21", + "semver": "7.5.4" + }, + "engines": { + "node": ">=18.x" + } + }, + "node_modules/@sap-ux/vocabularies-types": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/@sap-ux/vocabularies-types/-/vocabularies-types-0.11.3.tgz", + "integrity": "sha512-bOQz8dk7I/VNtH50hUnfqtiYSMUh/t28nyrMFZcVBbVTwlnxHUTWEUKUGu1Dwllw1yQVHuArCKy+rWhb0v7h6A==", + "dev": true, + "engines": { + "node": ">=18.0.0 < 19.0.0 || >=20.0.0 < 21.0.0", + "pnpm": ">=8" + } + }, + "node_modules/@sap-ux/xml-odata-annotation-converter": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@sap-ux/xml-odata-annotation-converter/-/xml-odata-annotation-converter-0.3.1.tgz", + "integrity": "sha512-qcdJ72RXTkiwV9yP6sOgOiLeoKYY4E1qRhjiG13XeOwg0GOTo5ohUoARqFpENYTE+i52gocVpLNl77Jw011rAA==", + "dev": true, + "dependencies": { + "@sap-ux/odata-annotation-core": "0.2.1" + } + }, + "node_modules/@sap-ux/yaml": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@sap-ux/yaml/-/yaml-0.16.0.tgz", + "integrity": "sha512-jojo+NDZyuguUmTznj+yof2luSRarfqR2x09jRoVhS0CT2oJaAxyd60yXRtuCUFW7FbuEii+jSf+aeBU7QSPVw==", + "dev": true, + "dependencies": { + "lodash": "4.17.21", + "yaml": "2.2.2" + }, + "engines": { + "node": ">=18.x" + } + }, + "node_modules/@sap-ux/yaml/node_modules/yaml": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.2.tgz", + "integrity": "sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@sap/cds": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/@sap/cds/-/cds-8.3.1.tgz", + "integrity": "sha512-v44OYZqeFYrH6ghfO/RqQ7eqgcNYAAQmVVFy9pIbOkxXay0uVDXB1nC3hu6cuqIYvp2PFInL0c3l1e+ycFSkPA==", + "dependencies": { + "@sap/cds-compiler": ">=5.1", + "@sap/cds-fiori": "^1", + "@sap/cds-foss": "^5.0.0" + }, + "bin": { + "cds-deploy": "lib/dbs/cds-deploy.js", + "cds-serve": "bin/serve.js", + "cds-test": "bin/test.js", + "chest": "bin/test.js" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "express": ">=4" + }, + "peerDependenciesMeta": { + "express": { + "optional": true + } + } + }, + "node_modules/@sap/cds-compiler": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/@sap/cds-compiler/-/cds-compiler-5.3.2.tgz", + "integrity": "sha512-aePHQMZHb13+oQuHU+ug5bwxXO11NThBEfUyA3uMGlnjkAxa8pbzuot9pHiiAIMavXLcqTzbCfm/uFGKcfjqBQ==", + "dependencies": { + "antlr4": "4.9.3" + }, + "bin": { + "cdsc": "bin/cdsc.js", + "cdshi": "bin/cdshi.js", + "cdsse": "bin/cdsse.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sap/cds-fiori": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@sap/cds-fiori/-/cds-fiori-1.2.7.tgz", + "integrity": "sha512-F6Uf9wvkv0fXW+Fh7PiV2BbB/k+p1cFJLkQCCKDRJH8HvlxWEcXcn/YIvBrQGuX+GToi125MxB3wd712d8OLTA==", + "peerDependencies": { + "@sap/cds": ">=7.6", + "express": ">=4" + } + }, + "node_modules/@sap/cds-foss": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@sap/cds-foss/-/cds-foss-5.0.1.tgz", + "integrity": "sha512-q6h7LkEx6w9LswCIQzJJ2mnoyeGS8jrmBXN4I4+aECRL60mkLskoqGetot+2tX2xXGxCYJuo5v1dtSafwBqTRQ==", + "dependencies": { + "big.js": "^6.1.1", + "generic-pool": "^3.8.2", + "xmlbuilder": "^15.1.1", + "yaml": "^2.2.2" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@sap/ux-cds-compiler-facade": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@sap/ux-cds-compiler-facade/-/ux-cds-compiler-facade-1.15.0.tgz", + "integrity": "sha512-WeA/wnF0NoHNod6H/Rcpgbh3ue4TVBSAlHQoupWzdu91yl+RZ4rKS4hARaRH+LV7gTXxJ5k6llJ/wyUN7sMDdw==", + "dev": true, + "engines": { + "node": ">=18.16.0" + }, + "peerDependencies": { + "@sap-ux/odata-annotation-core": ">=0.2.1", + "@sap-ux/odata-annotation-core-types": ">=0.4.1", + "@sap-ux/project-access": ">=1.26.6" + } + }, + "node_modules/@sap/ux-specification": { + "version": "1.124.3", + "resolved": "https://registry.npmjs.org/@sap/ux-specification/-/ux-specification-1.124.3.tgz", + "integrity": "sha512-9a0fDI2Qma2hGZn4eTacHWTWILDzBNt0a8hNhT5YMkzFbiSezgSKbd0Sda5JQ2fPKgopTEUbThy8KecUt9VV0g==", + "dev": true, + "dependencies": { + "@sap-ux/fe-fpm-writer": "0.31.4", + "@sap-ux/vocabularies-types": "0.11.3" + }, + "engines": { + "node": ">= 18.0.0 < 19.0.0 || >= 20.0.0 < 21.0.0 || >= 22.0.0", + "yarn": ">=1.22.19 < 2" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", + "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, + "node_modules/@types/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", + "dev": true + }, + "node_modules/@types/node": { + "version": "22.7.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.7.tgz", + "integrity": "sha512-SRxCrrg9CL/y54aiMCG3edPKdprgMVGDXjA3gB8UmmBW5TcXzRUYAh8EWzTnSJFAd1rgImPELza+A3bJ+qxz8Q==", + "dev": true, + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/@types/qs": { + "version": "6.9.16", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.16.tgz", + "integrity": "sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dev": true, + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/triple-beam": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", + "dev": true + }, + "node_modules/@xml-tools/ast": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@xml-tools/ast/-/ast-5.0.5.tgz", + "integrity": "sha512-avvzTOvGplCx9JSKdsTe3vK+ACvsHy2HxVfkcfIqPzu+kF5CT4rw5aUVzs0tJF4cnDyMRVkSyVxR07X0Px8gPA==", + "dev": true, + "dependencies": { + "@xml-tools/common": "^0.1.6", + "@xml-tools/parser": "^1.0.11", + "lodash": "4.17.21" + } + }, + "node_modules/@xml-tools/common": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@xml-tools/common/-/common-0.1.6.tgz", + "integrity": "sha512-7aVZeEYccs1KI/Asd6KKnrB4dTAWXTkjRMjG40ApGEUp5NpfQIvWLEBvMv85Koj2lbSpagcAERwDy9qMsfWGdA==", + "dev": true, + "dependencies": { + "lodash": "4.17.21" + } + }, + "node_modules/@xml-tools/parser": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@xml-tools/parser/-/parser-1.0.11.tgz", + "integrity": "sha512-aKqQ077XnR+oQtHJlrAflaZaL7qZsulWc/i/ZEooar5JiWj1eLt0+Wg28cpa+XLney107wXqneC+oG1IZvxkTA==", + "dev": true, + "dependencies": { + "chevrotain": "7.1.1" + } + }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", + "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/antlr4": { + "version": "4.9.3", + "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.9.3.tgz", + "integrity": "sha512-qNy2odgsa0skmNMCuxzXhM4M8J1YDaPv3TI+vCdnOAanu0N982wBrSqziDKRDctEZLZy9VffqIZXc0UGjjSP/g==", + "engines": { + "node": ">=14" + } + }, + "node_modules/array-differ": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/better-sqlite3": { + "version": "11.4.0", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-11.4.0.tgz", + "integrity": "sha512-B7C9y2aSvtTwDJIz34iUxMjQWmbAYFmpq0Rwf9weYTtx6jUYsUKVt5ePPYlGyLVBoySppPa41PBrzl1ipMhG7A==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "bindings": "^1.5.0", + "prebuild-install": "^7.1.1" + } + }, + "node_modules/big.js": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-6.2.2.tgz", + "integrity": "sha512-y/ie+Faknx7sZA5MfGA2xKlu0GDv8RWrXGsmlteyJQ2lvoKv9GBK/fpRMc2qlSoBAgNxrixICFCBefIq8WCQpQ==", + "engines": { + "node": "*" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/bigjs" + } + }, + "node_modules/binaryextensions": { + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-4.19.0.tgz", + "integrity": "sha512-DRxnVbOi/1OgA5pA9EDiRT8gvVYeqfuN7TmPfLyt6cyho3KbHCi3EtDQf39TTmGDrR5dZ9CspdXhPkL/j/WGbg==", + "dev": true, + "engines": { + "node": ">=0.8" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chevrotain": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-7.1.1.tgz", + "integrity": "sha512-wy3mC1x4ye+O+QkEinVJkPf5u2vsrDIYW9G7ZuwFl6v/Yu0LwUuT2POsb+NUWApebyxfkQq6+yDfRExbnI5rcw==", + "dev": true, + "dependencies": { + "regexp-to-ast": "0.5.0" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha512-KLLTJWrvwIP+OPfMn0x2PheDEP20RPUcGXj/ERegTgdmPEZylALQldygiqrPPu8P45uNuPs7ckmReLY6v/iA5g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha512-au6ydSpg6nsrigcZ4m8Bc9hxjeW+GJ8xh5G3BJCMt4WXe1H10UNaVOamqQTmrx1kjVuxAHIQSNU6hY4Nsn9/ag==", + "dev": true + }, + "node_modules/cloneable-readable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", + "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + } + }, + "node_modules/cloneable-readable/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/cloneable-readable/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/cloneable-readable/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dev": true, + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/color/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/colorspace": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", + "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", + "dev": true, + "dependencies": { + "color": "^3.1.3", + "text-hex": "1.0.x" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", + "dev": true + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/express": { + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.10", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fecha": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", + "dev": true + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/findit2": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/findit2/-/findit2-2.2.3.tgz", + "integrity": "sha512-lg/Moejf4qXovVutL0Lz4IsaPoNYMuxt4PA0nGqFxnJ1CTTGGlEO2wKgoDpwknhvZ8k4Q2F+eesgkLbG2Mxfog==", + "dev": true, + "engines": { + "node": ">=0.8.22" + } + }, + "node_modules/first-chunk-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz", + "integrity": "sha512-X8Z+b/0L4lToKYq+lwnKqi9X/Zek0NibLpsJgVsSxpoYq7JtiCtRb5HqKVEjEw/qAb/4AKKRLOwwKHlWNpm2Eg==", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/first-chunk-stream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/first-chunk-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/first-chunk-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", + "dev": true + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generic-pool": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", + "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "dev": true + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/i18next": { + "version": "21.6.11", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.6.11.tgz", + "integrity": "sha512-tJ2+o0lVO+fhi8bPkCpBAeY1SgkqmQm5NzgPWCQssBrywJw98/o+Kombhty5nxQOpHtvMmsxcOopczUiH6bJxQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "dependencies": { + "@babel/runtime": "^7.12.0" + } + }, + "node_modules/i18next-fs-backend": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/i18next-fs-backend/-/i18next-fs-backend-1.1.1.tgz", + "integrity": "sha512-RFkfy10hNxJqc7MVAp5iAZq0Tum6msBCNebEe3OelOBvrROvzHUPaR8Qe10RQrOGokTm0W4vJGEJzruFkEt+hQ==", + "dev": true + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "dev": true + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", + "dev": true + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/isbinaryfile": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", + "dev": true, + "engines": { + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/jake": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", + "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", + "dev": true, + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", + "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, + "node_modules/kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", + "dev": true + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/logform": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.1.tgz", + "integrity": "sha512-CdaO738xRapbKIMVn2m4F6KTj4j7ooJ8POVnebSgKo3KBz5axNXRAL7ZdRjIV6NOr2Uf4vjtRkxrFETOioCqSA==", + "dev": true, + "dependencies": { + "@colors/colors": "1.6.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/logform/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mem-fs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mem-fs/-/mem-fs-2.1.0.tgz", + "integrity": "sha512-55vFOT4rfJx/9uoWntNrfzEj9209rd26spsSvKsCVBfOPH001YS5IakfElhcyagieC4uL++Ry/XDcwvgxF4/zQ==", + "dev": true, + "dependencies": { + "vinyl": "^2.0.1", + "vinyl-file": "^3.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/mem-fs-editor": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/mem-fs-editor/-/mem-fs-editor-9.4.0.tgz", + "integrity": "sha512-HSSOLSVRrsDdui9I6i96dDtG+oAez/4EB2g4cjSrNhgNQ3M+L57/+22NuPdORSoxvOHjIg/xeOE+C0wwF91D2g==", + "dev": true, + "dependencies": { + "binaryextensions": "^4.16.0", + "commondir": "^1.0.1", + "deep-extend": "^0.6.0", + "ejs": "^3.1.6", + "globby": "^11.0.3", + "isbinaryfile": "^4.0.8", + "minimatch": "^3.0.4", + "multimatch": "^5.0.0", + "normalize-path": "^3.0.0", + "textextensions": "^5.13.0" + }, + "engines": { + "node": ">=12.10.0" + }, + "peerDependencies": { + "mem-fs": "^2.1.0" + }, + "peerDependenciesMeta": { + "mem-fs": { + "optional": true + } + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/multimatch": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz", + "integrity": "sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==", + "dev": true, + "dependencies": { + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", + "dev": true + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-abi": { + "version": "3.71.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.71.0.tgz", + "integrity": "sha512-SZ40vRiy/+wRTf21hxkkEjPJZpARzUMVcJoQse2EF8qkUWbbO2z7vd5oA/H6bVH6SZQ5STGcu0KRDS7biNRfxw==", + "dev": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "dev": true, + "dependencies": { + "fn.name": "1.x.x" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz", + "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==", + "dev": true, + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pump": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true + }, + "node_modules/regexp-to-ast": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz", + "integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==", + "dev": true + }, + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", + "dev": true + }, + "node_modules/replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==", + "dev": true, + "dependencies": { + "is-utf8": "^0.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-bom-buf": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-buf/-/strip-bom-buf-1.0.0.tgz", + "integrity": "sha512-1sUIL1jck0T1mhOLP2c696BIznzT525Lkub+n4jjMHjhjhoAQA6Ye659DxdlZBr0aLDMQoTxKIpnlqxgtwjsuQ==", + "dev": true, + "dependencies": { + "is-utf8": "^0.2.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-bom-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz", + "integrity": "sha512-yH0+mD8oahBZWnY43vxs4pSinn8SMKAdml/EOGBewoe1Y0Eitd0h2Mg3ZRiXruUW6L4P+lvZiEgbh0NgUGia1w==", + "dev": true, + "dependencies": { + "first-chunk-stream": "^2.0.0", + "strip-bom": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "dev": true + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dev": true, + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", + "dev": true + }, + "node_modules/textextensions": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-5.16.0.tgz", + "integrity": "sha512-7D/r3s6uPZyU//MCYrX6I14nzauDwJ5CxazouuRGNuvSCihW87ufN6VLoROLCrHg6FblLuJrT6N2BVaPVzqElw==", + "dev": true, + "engines": { + "node": ">=0.8" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/triple-beam": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", + "dev": true, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vinyl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", + "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", + "dev": true, + "dependencies": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-file": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-3.0.0.tgz", + "integrity": "sha512-BoJDj+ca3D9xOuPEM6RWVtWQtvEPQiQYn82LvdxhLWplfQsBzBqtgK0yhCP0s1BNTi6dH9BO+dzybvyQIacifg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "pify": "^2.3.0", + "strip-bom-buf": "^1.0.0", + "strip-bom-stream": "^2.0.0", + "vinyl": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.8.tgz", + "integrity": "sha512-1bonkGqQs5/fxGT5UchTgjGVnfysL0O8v1AYMBjqTbWQTFn721zaPGDYFkOKtfDgFiSgXM3KwaG3FMGfW4Ed9Q==", + "dev": true + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.2.tgz", + "integrity": "sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA==", + "dev": true + }, + "node_modules/winston": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.11.0.tgz", + "integrity": "sha512-L3yR6/MzZAOl0DsysUXHVjOwv8mKZ71TrA/41EIduGpOOV5LQVodqN+QdQ6BS6PJ/RdIshZhq84P/fStEZkk7g==", + "dev": true, + "dependencies": { + "@colors/colors": "^1.6.0", + "@dabh/diagnostics": "^2.0.2", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.4.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.5.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-transport": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.7.0.tgz", + "integrity": "sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==", + "dev": true, + "dependencies": { + "logform": "^2.3.2", + "readable-stream": "^3.6.0", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/xml-formatter": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/xml-formatter/-/xml-formatter-2.6.1.tgz", + "integrity": "sha512-dOiGwoqm8y22QdTNI7A+N03tyVfBlQ0/oehAzxIZtwnFAHGeSlrfjF73YQvzSsa/Kt6+YZasKsrdu6OIpuBggw==", + "dev": true, + "dependencies": { + "xml-parser-xo": "^3.2.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/xml-parser-xo": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/xml-parser-xo/-/xml-parser-xo-3.2.0.tgz", + "integrity": "sha512-8LRU6cq+d7mVsoDaMhnkkt3CTtAs4153p49fRo+HIB3I1FD1o5CeXRjRH29sQevIfVJIcPjKSsPU/+Ujhq09Rg==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "engines": { + "node": ">=8.0" + } + }, + "node_modules/xpath": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.33.tgz", + "integrity": "sha512-NNXnzrkDrAzalLhIUc01jO2mOzXGXh1JwPgkihcLLzw98c0WgYDmmjSh1Kl3wzaxSVWMuA+fe0WTWOBDWCBmNA==", + "dev": true, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yaml": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + } + } +} diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/package.json b/packages/project-integrity/test/test-input/valid-fiori-project/package.json new file mode 100644 index 00000000000..7ec1674955d --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/package.json @@ -0,0 +1,24 @@ +{ + "name": "fiori-tools-ai", + "version": "1.0.0", + "description": "A simple CAP project.", + "repository": "", + "license": "UNLICENSED", + "private": true, + "dependencies": { + "@sap/cds": "^8", + "express": "^4" + }, + "devDependencies": { + "@cap-js/sqlite": "^1", + "@cap-js/cds-types": "^0.6", + "@sap/ux-specification": "UI5-1.126" + }, + "scripts": { + "start": "cds-serve", + "watch-travelmanagement": "cds watch --open travelmanagement/webapp/index.html?sap-ui-xx-viewCache=false" + }, + "sapux": [ + "app/travelmanagement" + ] +} diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/srv/service.cds b/packages/project-integrity/test/test-input/valid-fiori-project/srv/service.cds new file mode 100644 index 00000000000..fe5789f6c28 --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/srv/service.cds @@ -0,0 +1,7 @@ +using { travelManagement } from '../db/schema.cds'; + +service travelManagementSrv { + @odata.draft.enabled + entity Travel as projection on travelManagement.Travel; + entity Bookings as projection on travelManagement.Bookings; +} \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/test/data/travelManagement-Bookings.csv b/packages/project-integrity/test/test-input/valid-fiori-project/test/data/travelManagement-Bookings.csv new file mode 100644 index 00000000000..3c8ccec3ce9 --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/test/data/travelManagement-Bookings.csv @@ -0,0 +1,8 @@ +ID;employee;airlines;bookingDate;flightDate;priceUSD;travel_ID +3efbe1e6-de90-4ae7-9a94-71c669faeea7;John Doe;Delta Airlines;2021-06-20;2021-07-01;500.00;bda3b521-6a7c-4c6a-b67c-47b6d4333abe +e984fce5-8f2f-4a45-bec7-856391aaf733;John Doe;American Airlines;2021-06-22;2021-07-05;450.00;bda3b521-6a7c-4c6a-b67c-47b6d4333abe +246cdfc3-480f-4a59-948c-67532b3a528d;Jane Smith;United Airlines;2021-08-01;2021-08-15;600.00;48ffb874-9713-4402-a994-8075295d2e6e +a1404f08-5dfb-4f91-bc55-85d27cb9463e;Alice Johnson;Southwest Airlines;2021-09-01;2021-09-10;300.00;95481ec0-8a0b-4ec6-91b0-9fbea59285ab +2fb675de-8cbd-4b39-aa9a-0e66cd9474eb;Bob Brown;JetBlue;2021-09-25;2021-10-05;700.00;eee164c0-ed83-4ec2-8f95-844ab4099fc4 +0f501a38-7484-432d-b7d3-fa5a69a8f813;Charlie Davis;Alaska Airlines;2021-10-20;2021-11-01;400.00;f03c3b75-8592-4f85-a557-28257c4a976d +c9cd31a1-f1fd-42be-97f4-6a8f529a87bf;Charlie Davis;Spirit Airlines;2021-10-22;2021-11-03;350.00;f03c3b75-8592-4f85-a557-28257c4a976d \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/valid-fiori-project/test/data/travelManagement-Travel.csv b/packages/project-integrity/test/test-input/valid-fiori-project/test/data/travelManagement-Travel.csv new file mode 100644 index 00000000000..0e9cae92dda --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-fiori-project/test/data/travelManagement-Travel.csv @@ -0,0 +1,6 @@ +ID;tripName;employee;status;tripStartDate;tripEndDate;priceUSD +bda3b521-6a7c-4c6a-b67c-47b6d4333abe;Sales Conference;John Doe;Confirmed;2021-07-01;2021-07-05;1500.00 +48ffb874-9713-4402-a994-8075295d2e6e;Tech Expo;Jane Smith;Pending;2021-08-15;2021-08-20;2000.00 +95481ec0-8a0b-4ec6-91b0-9fbea59285ab;Marketing Summit;Alice Johnson;Cancelled;2021-09-10;2021-09-12;800.00 +eee164c0-ed83-4ec2-8f95-844ab4099fc4;Leadership Retreat;Bob Brown;Confirmed;2021-10-05;2021-10-10;2500.00 +f03c3b75-8592-4f85-a557-28257c4a976d;Client Meeting;Charlie Davis;Completed;2021-11-01;2021-11-03;1200.00 \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/valid-project/.integrity.json b/packages/project-integrity/test/test-input/valid-project/.integrity.json new file mode 100644 index 00000000000..6e33d04d320 --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-project/.integrity.json @@ -0,0 +1 @@ +{"enabled":true,"fileIntegrity":[{"filePath":"test.txt","hash":"1a8a45c145cca8cb08b03e0eb1f6fcd4","content":"FIVwzgLgBAhlEFNJQGYEsA2CB0Q="}],"contentIntegrity":[{"contentKey":"key1","hash":"9946687e5fa0dab5993ededddb398d2e","content":"G4QwNgrgpgjEA==="},{"contentKey":"key2","hash":"f066ce9385512ee02afc6e14d627e9f2","content":"G4QwNgrgpgTEA==="}]} \ No newline at end of file diff --git a/packages/project-integrity/test/test-input/valid-project/test.txt b/packages/project-integrity/test/test-input/valid-project/test.txt new file mode 100644 index 00000000000..e3ab9e012e6 --- /dev/null +++ b/packages/project-integrity/test/test-input/valid-project/test.txt @@ -0,0 +1 @@ +Just a test file. \ No newline at end of file diff --git a/packages/project-integrity/test/unit/fiori-project/index.test.ts b/packages/project-integrity/test/unit/fiori-project/index.test.ts new file mode 100644 index 00000000000..e93bd0f5703 --- /dev/null +++ b/packages/project-integrity/test/unit/fiori-project/index.test.ts @@ -0,0 +1,123 @@ +import { join } from 'path'; +import { + checkFioriProjectIntegrity, + disableFioriProjectIntegrity, + enableFioriProjectIntegrity, + initFioriProject, + isFioriProjectIntegrityEnabled, + updateFioriProjectIntegrity +} from '../../../src'; +import * as persistence from '../../../src/integrity/persistence'; +import * as updateMock from '../../../src/integrity'; + +describe('Test for initFioriProject()', () => { + test('Init valid Fiori project', async () => { + const projectRoot = join(__dirname, '../../test-input/valid-fiori-project'); + const integrityFilePath = join(projectRoot, '.fiori-ai/ai-integrity.json'); + const targetIntegrityData = await persistence.readIntegrityData(integrityFilePath); + await initFioriProject(projectRoot); + const newIntegrityData = await persistence.readIntegrityData(integrityFilePath); + expect(newIntegrityData).toStrictEqual(targetIntegrityData); + }); + + test('Init invalid Fiori project, no db/schema.cds', async () => { + const projectRoot = join(__dirname, '../../test-input/invalid-fiori-project-no-schema-cds'); + try { + await initFioriProject(projectRoot); + expect(false).toBe('initFioriProject() should have thrown error but did not'); + } catch (error) { + expect(error.message).toContain('schema.cds'); + } + }); + + test('Init valid Fiori project no srv/service.cds', async () => { + const projectRoot = join(__dirname, '../../test-input/invalid-fiori-project-no-service-cds'); + try { + await initFioriProject(projectRoot); + expect(false).toBe('initFioriProject() should have thrown error but did not'); + } catch (error) { + expect(error.message).toContain('service.cds'); + } + }); +}); + +describe('Test for checkFioriProjectIntegrity()', () => { + test('Check valid project', async () => { + const projectRoot = join(__dirname, '../../test-input/valid-fiori-project'); + const results = await checkFioriProjectIntegrity(projectRoot); + expect(results).toStrictEqual({ + 'files': { + 'differentFiles': [], + 'equalFiles': [expect.stringContaining('schema.cds'), expect.stringContaining('service.cds')] + }, + 'additionalStringContent': { 'differentContent': [], 'equalContent': ['capPaths'] } + }); + }); +}); + +describe('Test for updateFioriProjectIntegrity()', () => { + afterEach(() => { + jest.resetAllMocks(); + }); + + test('Update additional string content', async () => { + const mockUpdateFioriProjectIntegrity = jest + .spyOn(updateMock, 'updateProjectIntegrity') + .mockResolvedValueOnce(); + const projectRoot = join(__dirname, '../../test-input/valid-fiori-project'); + await updateFioriProjectIntegrity(projectRoot); + expect(mockUpdateFioriProjectIntegrity).toBeCalledWith(expect.stringContaining('integrity.json'), { + capPaths: '{"app":"app/","db":"db/","srv":"srv/"}' + }); + }); +}); + +describe('Test isFioriProjectIntegrityEnabled()', () => { + test('Check enabled Fiori project', async () => { + const projectRoot = join(__dirname, '../../test-input/enabled-fiori-project'); + const enabled = await isFioriProjectIntegrityEnabled(projectRoot); + expect(enabled).toBe(true); + }); + + test('Check disabled Fiori project', async () => { + const projectRoot = join(__dirname, '../../test-input/disabled-fiori-project'); + const enabled = await isFioriProjectIntegrityEnabled(projectRoot); + expect(enabled).toBe(false); + }); +}); + +describe('Test enableFioriProjectIntegrity()', () => { + afterEach(() => { + jest.resetAllMocks(); + }); + + test('Enable disabled Fiori project', async () => { + const mockWriteIntegrityData = jest.spyOn(persistence, 'writeIntegrityData').mockResolvedValueOnce(); + const projectRoot = join(__dirname, '../../test-input/disabled-fiori-project'); + + await enableFioriProjectIntegrity(projectRoot); + expect(mockWriteIntegrityData).toBeCalledWith(expect.stringContaining('ai-integrity.json'), { + 'enabled': true, + 'fileIntegrity': [], + 'contentIntegrity': [] + }); + }); +}); + +describe('Test disableFioriProjectIntegrity()', () => { + afterEach(() => { + jest.resetAllMocks(); + }); + + test('Disable enabled Fiori project', async () => { + const mockWriteIntegrityData = jest.spyOn(persistence, 'writeIntegrityData').mockResolvedValueOnce(); + const projectRoot = join(__dirname, '../../test-input/enabled-fiori-project'); + + await disableFioriProjectIntegrity(projectRoot); + expect(mockWriteIntegrityData).toBeCalledWith(expect.stringContaining('ai-integrity.json'), { + 'enabled': false, + 'fileIntegrity': [], + 'contentIntegrity': [] + }); + }); +}); diff --git a/packages/project-integrity/test/unit/index.test.ts b/packages/project-integrity/test/unit/index.test.ts new file mode 100644 index 00000000000..2a2f85ff678 --- /dev/null +++ b/packages/project-integrity/test/unit/index.test.ts @@ -0,0 +1,20 @@ +import { + initFioriProject, + initProject, + checkFioriProjectIntegrity, + checkProjectIntegrity, + updateFioriProjectIntegrity, + updateProjectIntegrity +} from '../../src'; + +test('Check public interface for project integrity', () => { + expect(typeof initProject).toBe('function'); + expect(typeof checkProjectIntegrity).toBe('function'); + expect(typeof updateProjectIntegrity).toBe('function'); +}); + +test('Check public interface for Fiori project integrity', () => { + expect(typeof initFioriProject).toBe('function'); + expect(typeof checkFioriProjectIntegrity).toBe('function'); + expect(typeof updateFioriProjectIntegrity).toBe('function'); +}); diff --git a/packages/project-integrity/test/unit/integrity/hash.test.ts b/packages/project-integrity/test/unit/integrity/hash.test.ts new file mode 100644 index 00000000000..81e3abdf62a --- /dev/null +++ b/packages/project-integrity/test/unit/integrity/hash.test.ts @@ -0,0 +1,12 @@ +import { getFileIntegrity } from '../../../src/integrity/hash'; + +test('Test getFileIntegrity()', async () => { + try { + await getFileIntegrity(['non-existing-file', 'other-non-existing-file']); + expect(false).toBe('Call to getFileIntegrity() should have thrown an error, but did not.'); + } catch (error) { + expect(error.message).toBe('The following files do not exist: non-existing-file, other-non-existing-file'); + } +}); + +// Other export of hash.ts are already covered by test in project.test.ts diff --git a/packages/project-integrity/test/unit/integrity/persistence.test.ts b/packages/project-integrity/test/unit/integrity/persistence.test.ts new file mode 100644 index 00000000000..3601a8f1c94 --- /dev/null +++ b/packages/project-integrity/test/unit/integrity/persistence.test.ts @@ -0,0 +1,46 @@ +import { mkdir } from 'fs/promises'; +import { join } from 'path'; +import { readIntegrityData, writeIntegrityData } from '../../../src/integrity/persistence'; +import type { Integrity } from '../../../src/types'; + +jest.mock('fs/promises', () => ({ + ...jest.requireActual('fs/promises'), + mkdir: jest.fn(), + writeFile: jest.fn() +})); + +describe('Test readIntegrityData()', () => { + test('Read integrity data, integrity file does not exist', async () => { + try { + await readIntegrityData('none-existing-file'); + expect(false).toBe('readIntegrityData() should have thrown error but did not.'); + } catch (error) { + expect(error.message).toBe('Integrity file not found at none-existing-file'); + } + }); + + test('Read integrity data, set content should not be possible', async () => { + const integrityFilePath = join(__dirname, '../../test-input/valid-project/.integrity.json'); + const integrityData = await readIntegrityData(integrityFilePath); + expect(integrityData.fileIntegrity[0].content).toBe('Just a test file.'); + integrityData.fileIntegrity[0].content = 'set to readonly property should not do anything'; + expect(integrityData.fileIntegrity[0].content).toBe('Just a test file.'); + }); + + // Other, valid cases, are tested in project.test.ts +}); + +describe('Test writeIntegrityData()', () => { + test('Write integrity data, path to integrity data does not exists', async () => { + const mockedMkdir = mkdir as jest.Mock; + const integrityFilePath = join(__dirname, '../../test-input/new-folder/integrity.json'); + const content: Partial = { + fileIntegrity: [], + contentIntegrity: [] + }; + await writeIntegrityData(integrityFilePath, content as Integrity); + expect(mockedMkdir).toBeCalledWith(expect.stringContaining('new-folder'), { recursive: true }); + }); + + // Other, valid cases, are tested in project.test.ts +}); diff --git a/packages/project-integrity/test/unit/integrity/project.test.ts b/packages/project-integrity/test/unit/integrity/project.test.ts new file mode 100644 index 00000000000..a17566751e5 --- /dev/null +++ b/packages/project-integrity/test/unit/integrity/project.test.ts @@ -0,0 +1,227 @@ +import { join } from 'path'; +import { + checkProjectIntegrity, + disableProjectIntegrity, + enableProjectIntegrity, + initProject, + isProjectIntegrityEnabled, + updateProjectIntegrity +} from '../../../src'; +import * as persistence from '../../../src/integrity/persistence'; + +describe('Test initProject()', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + test('Test initProject() with valid project', async () => { + const integrityFilePath = join(__dirname, '../../test-input/valid-project/.integrity.json'); + const targetIntegrityData = await persistence.readIntegrityData(integrityFilePath); + await initProject({ + integrityFilePath, + fileList: [join(__dirname, '../../test-input/valid-project/test.txt')], + additionalStringContent: { 'key1': 'value1', 'key2': 'value2' } + }); + const newIntegrityData = await persistence.readIntegrityData(integrityFilePath); + expect(newIntegrityData).toStrictEqual(targetIntegrityData); + }); +}); + +describe('Test checkProjectIntegrity()', () => { + test('Valid project, valid additional content', async () => { + const integrityFilePath = join(__dirname, '../../test-input/valid-project/.integrity.json'); + const result = await checkProjectIntegrity(integrityFilePath, { 'key1': 'value1', 'key2': 'value2' }); + expect(result.files.differentFiles.length).toBe(0); + expect(result.files.equalFiles.find((ef) => ef.includes('test.txt'))).toBeDefined(); + expect(result.additionalStringContent.differentContent.length).toBe(0); + expect(result.additionalStringContent.equalContent).toEqual(['key1', 'key2']); + }); + + test('Invalid project', async () => { + const integrityFilePath = join(__dirname, '../../test-input/invalid-project/integrity.json'); + const result = await checkProjectIntegrity(integrityFilePath, { + 'one': 'value one', + 'two': 'not value two', + 'four': 'non existing' + }); + const bad = result.files.differentFiles.find((df) => df.filePath.includes('bad.xml')); + const noneExistingFile = result.files.differentFiles.find((df) => df.filePath.includes('non-existing.file')); + expect(result.files.equalFiles.length).toBe(1); + expect(result.files.equalFiles.find((ef) => ef.includes('good.txt'))).toBeDefined(); + expect(bad?.newContent).toBe('\n Changed XML\n'); + expect(bad?.oldContent).toBe('\n Test XML file\n'); + expect(noneExistingFile?.oldContent).toBe('Non existing'); + expect(result.additionalStringContent.equalContent).toContain('one'); + expect(result.additionalStringContent.differentContent).toStrictEqual([ + { 'key': 'two', 'newContent': 'not value two', 'oldContent': 'value two' }, + { 'key': 'four', 'newContent': 'non existing', 'oldContent': undefined }, + { 'key': 'three', 'newContent': undefined, 'oldContent': 'value three' } + ]); + }); + + test('Disabled project', async () => { + const integrityFilePath = join(__dirname, '../../test-input/disabled-project/integrity.json'); + try { + await checkProjectIntegrity(integrityFilePath); + expect(false).toBe('checkProjectIntegrity() should have thrown error but did not'); + } catch (error) { + expect(error.message).toBe( + `Integrity is disabled for the project with integrity data ${integrityFilePath}` + ); + } + }); +}); + +describe('Test updateProjectIntegrity()', () => { + afterEach(() => { + jest.resetAllMocks(); + }); + + test('Update invalid project', async () => { + const writeSpy = jest.spyOn(persistence, 'writeIntegrityData').mockResolvedValueOnce(); + + const integrityFilePath = join(__dirname, '../../test-input/update-project/integrity.json'); + await updateProjectIntegrity(integrityFilePath, { 'key': 'new string' }); + expect(writeSpy).toBeCalledWith(expect.stringContaining('integrity.json'), { + 'enabled': true, + 'fileIntegrity': [ + { + 'filePath': expect.stringContaining('file-to-update.txt') as string, + 'hash': '96c15c2bb2921193bf290df8cd85e2ba', + 'content': 'new content' + } + ], + 'contentIntegrity': [ + { 'contentKey': 'key', 'hash': 'b200a3adbe85fe848b920dc35d5a69b2', 'content': 'new string' } + ] + }); + }); + + test('Update with non existing additional string content', async () => { + const integrityFilePath = join(__dirname, '../../test-input/valid-project/.integrity.json'); + try { + await updateProjectIntegrity(integrityFilePath, { 'key1': 'value1', 'wrong': 'wrong content' }); + expect(false).toBe('updateProjectIntegrity() should have thrown error but did not'); + } catch (error) { + expect(error.message).toBe( + 'There is a mismatch of additional content keys.\nStored content keys: key1, key2\nNew content keys: key1, wrong' + ); + } + }); + + test('Update with non existing integrity file', async () => { + try { + await updateProjectIntegrity('non-existing'); + expect(false).toBe('updateProjectIntegrity() should have thrown error but did not'); + } catch (error) { + expect(error.message).toBe('Integrity data not found at non-existing'); + } + }); + + test('Update disabled project', async () => { + const integrityFilePath = join(__dirname, '../../test-input/disabled-project/integrity.json'); + try { + await updateProjectIntegrity(integrityFilePath); + expect(false).toBe('updateProjectIntegrity() should have thrown error but did not'); + } catch (error) { + expect(error.message).toBe( + `Integrity is disabled for the project with integrity data ${integrityFilePath}` + ); + } + }); +}); + +describe('Test isProjectIntegrityEnabled()', () => { + afterEach(() => { + jest.resetAllMocks(); + }); + + test('Check enabled project', async () => { + const integrityFilePath = join(__dirname, '../../test-input/enabled-project/integrity.json'); + const enabled = await isProjectIntegrityEnabled(integrityFilePath); + expect(enabled).toBe(true); + }); + + test('Check disabled project', async () => { + const integrityFilePath = join(__dirname, '../../test-input/disabled-project/integrity.json'); + const enabled = await isProjectIntegrityEnabled(integrityFilePath); + expect(enabled).toBe(false); + }); + + test('Check non existing project', async () => { + try { + await isProjectIntegrityEnabled('non-existing'); + expect(false).toBe('isProjectIntegrityEnabled() should have thrown error but did not'); + } catch (error) { + expect(error.message).toBe('Integrity data not found at non-existing'); + } + }); +}); + +describe('Test enableProjectIntegrity()', () => { + afterEach(() => { + jest.resetAllMocks(); + }); + + test('Enable integrity for disabled project', async () => { + const writeSpy = jest.spyOn(persistence, 'writeIntegrityData').mockResolvedValueOnce(); + const integrityFilePath = join(__dirname, '../../test-input/disabled-project/integrity.json'); + await enableProjectIntegrity(integrityFilePath); + expect(writeSpy).toBeCalledWith(expect.stringContaining('integrity.json'), { + 'enabled': true, + 'fileIntegrity': [], + 'contentIntegrity': [] + }); + }); + + test('Enable integrity for enabled project', async () => { + const writeSpy = jest.spyOn(persistence, 'writeIntegrityData').mockResolvedValueOnce(); + const integrityFilePath = join(__dirname, '../../test-input/enabled-project/integrity.json'); + await enableProjectIntegrity(integrityFilePath); + // project already enabled, so writeIntegrityData should not be called + expect(writeSpy).not.toBeCalled(); + }); + + test('Enable integrity for non existing project', async () => { + try { + await enableProjectIntegrity('non-existing'); + expect(false).toBe('enableProjectIntegrity() should have thrown error but did not'); + } catch (error) { + expect(error.message).toBe('Integrity data not found at non-existing'); + } + }); +}); + +describe('Test disableProjectIntegrity()', () => { + afterEach(() => { + jest.resetAllMocks(); + }); + + test('Disable integrity for enabled project', async () => { + const writeSpy = jest.spyOn(persistence, 'writeIntegrityData').mockResolvedValueOnce(); + const integrityFilePath = join(__dirname, '../../test-input/enabled-project/integrity.json'); + await disableProjectIntegrity(integrityFilePath); + expect(writeSpy).toBeCalledWith(expect.stringContaining('integrity.json'), { + 'enabled': false, + 'fileIntegrity': [], + 'contentIntegrity': [] + }); + }); + + test('Disable integrity for disabled project', async () => { + const writeSpy = jest.spyOn(persistence, 'writeIntegrityData').mockResolvedValueOnce(); + const integrityFilePath = join(__dirname, '../../test-input/disabled-project/integrity.json'); + await disableProjectIntegrity(integrityFilePath); + // project already disabled, so writeIntegrityData should not be called + expect(writeSpy).not.toBeCalled(); + }); + + test('Disable integrity for non existing project', async () => { + try { + await disableProjectIntegrity('non-existing'); + expect(false).toBe('disableProjectIntegrity() should have thrown error but did not'); + } catch (error) { + expect(error.message).toBe('Integrity data not found at non-existing'); + } + }); +}); diff --git a/packages/project-integrity/tsconfig.eslint.json b/packages/project-integrity/tsconfig.eslint.json new file mode 100644 index 00000000000..d5f1aa34747 --- /dev/null +++ b/packages/project-integrity/tsconfig.eslint.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "include": ["src", "test", ".eslintrc.js"] +} diff --git a/packages/project-integrity/tsconfig.json b/packages/project-integrity/tsconfig.json new file mode 100644 index 00000000000..f64fd8025e1 --- /dev/null +++ b/packages/project-integrity/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "../../tsconfig.json", + "include": [ + "src" + ], + "compilerOptions": { + "rootDir": "src", + "outDir": "dist" + }, + "references": [ + { + "path": "../project-access" + } + ] +} diff --git a/packages/system-access/CHANGELOG.md b/packages/system-access/CHANGELOG.md index 902aafa73ae..53707e7aedb 100644 --- a/packages/system-access/CHANGELOG.md +++ b/packages/system-access/CHANGELOG.md @@ -1,5 +1,12 @@ # @sap-ux/system-access +## 0.5.25 + +### Patch Changes + +- Updated dependencies [2e3c15e] + - @sap-ux/axios-extension@1.18.0 + ## 0.5.24 ### Patch Changes diff --git a/packages/system-access/package.json b/packages/system-access/package.json index 4c53af6d4d0..ff761e43256 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.24", + "version": "0.5.25", "license": "Apache-2.0", "author": "@SAP/ux-tools-team", "main": "dist/index.js", diff --git a/packages/ui5-application-inquirer/CHANGELOG.md b/packages/ui5-application-inquirer/CHANGELOG.md index 1a33566f1b6..7bd3e5bcbb2 100644 --- a/packages/ui5-application-inquirer/CHANGELOG.md +++ b/packages/ui5-application-inquirer/CHANGELOG.md @@ -1,5 +1,12 @@ # @sap-ux/ui5-application-inquirer +## 0.9.2 + +### Patch Changes + +- Updated dependencies [dac696a] + - @sap-ux/inquirer-common@0.6.2 + ## 0.9.1 ### Patch Changes diff --git a/packages/ui5-application-inquirer/package.json b/packages/ui5-application-inquirer/package.json index 21c53c1812b..d1817acea21 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.1", + "version": "0.9.2", "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 2148c0a737d..7926f827633 100644 --- a/packages/ui5-library-inquirer/CHANGELOG.md +++ b/packages/ui5-library-inquirer/CHANGELOG.md @@ -1,5 +1,12 @@ # @sap-ux/ui5-library-inquirer +## 0.3.31 + +### Patch Changes + +- Updated dependencies [dac696a] + - @sap-ux/inquirer-common@0.6.2 + ## 0.3.30 ### Patch Changes diff --git a/packages/ui5-library-inquirer/package.json b/packages/ui5-library-inquirer/package.json index 0b333bf55ee..bbd9f3beabd 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.30", + "version": "0.3.31", "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 62ccc6182b2..7c5ebcd93e3 100644 --- a/packages/ui5-library-reference-inquirer/CHANGELOG.md +++ b/packages/ui5-library-reference-inquirer/CHANGELOG.md @@ -1,5 +1,12 @@ # @sap-ux/ui5-library-reference-inquirer +## 0.3.63 + +### Patch Changes + +- Updated dependencies [dac696a] + - @sap-ux/inquirer-common@0.6.2 + ## 0.3.62 ### Patch Changes diff --git a/packages/ui5-library-reference-inquirer/package.json b/packages/ui5-library-reference-inquirer/package.json index 29ce81d996b..a2eebf8a2a5 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.62", + "version": "0.3.63", "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 29fb51d6009..4e1ac69f774 100644 --- a/packages/ui5-library-reference-sub-generator/CHANGELOG.md +++ b/packages/ui5-library-reference-sub-generator/CHANGELOG.md @@ -1,5 +1,11 @@ # @sap-ux/ui5-library-reference-sub-generator +## 0.0.23 + +### Patch Changes + +- @sap-ux/ui5-library-reference-inquirer@0.3.63 + ## 0.0.22 ### Patch Changes diff --git a/packages/ui5-library-reference-sub-generator/package.json b/packages/ui5-library-reference-sub-generator/package.json index 26d426c1f3f..3544baaabc3 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.22", + "version": "0.0.23", "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 c972f711783..1b0b9c849c3 100644 --- a/packages/ui5-library-sub-generator/CHANGELOG.md +++ b/packages/ui5-library-sub-generator/CHANGELOG.md @@ -1,5 +1,11 @@ # @sap-ux/ui5-library-sub-generator +## 0.0.42 + +### Patch Changes + +- @sap-ux/ui5-library-inquirer@0.3.31 + ## 0.0.41 ### Patch Changes diff --git a/packages/ui5-library-sub-generator/package.json b/packages/ui5-library-sub-generator/package.json index 13e248b3908..276d43603ed 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.41", + "version": "0.0.42", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/ui5-library-writer/package.json b/packages/ui5-library-writer/package.json index 05266d39768..a6a03b753ca 100644 --- a/packages/ui5-library-writer/package.json +++ b/packages/ui5-library-writer/package.json @@ -36,7 +36,6 @@ }, "dependencies": { "@sap-ux/project-access": "workspace:*", - "@sap-ux/ui5-application-writer": "workspace:*", "@sap-ux/ui5-config": "workspace:*", "ejs": "3.1.10", "i18next": "20.6.1", diff --git a/packages/ui5-library-writer/src/index.ts b/packages/ui5-library-writer/src/index.ts index d833cdaa419..427fd5c247c 100644 --- a/packages/ui5-library-writer/src/index.ts +++ b/packages/ui5-library-writer/src/index.ts @@ -6,6 +6,7 @@ import cloneDeep from 'lodash/cloneDeep'; import type { UI5LibConfig } from './types'; import { enableTypescript } from './options'; import { mergeWithDefaults } from './data'; +import { getTemplateVersionPath } from './utils'; /** * Writes the template to the memfs editor instance. @@ -28,7 +29,9 @@ async function generate(basePath: string, ui5LibConfig: UI5LibConfig, fs?: Edito const tmplPath = join(__dirname, '..', 'templates'); const ignore = [reuseLib.typescript ? '**/*.js' : '**/*.ts']; - fs.copyTpl(join(tmplPath, 'common', '**/*.*'), basePath, libInput, undefined, { + const templateVersionPath = getTemplateVersionPath(reuseLib.frameworkVersion); + + fs.copyTpl(join(tmplPath, 'common', templateVersionPath, '**/*.*'), basePath, libInput, undefined, { globOptions: { dot: true, ignore }, processDestinationPath: (filePath: string) => filePath diff --git a/packages/ui5-library-writer/src/utils.ts b/packages/ui5-library-writer/src/utils.ts new file mode 100644 index 00000000000..1318f867ec2 --- /dev/null +++ b/packages/ui5-library-writer/src/utils.ts @@ -0,0 +1,37 @@ +import { gte } from 'semver'; + +export const ui5LtsVersion_1_71 = '1.71.0'; +export const ui5LtsVersion_1_120 = '1.120.0'; + +/** + * Compares two UI5 versions to determine if the first is greater than or equal to the second. + * + * @param {string} ui5VersionA - The first UI5 version to compare. + * @param {string} ui5VersionB - The second UI5 version to compare. + * @returns {boolean} - True if the first version is greater than or equal to the second, false otherwise. + */ +export function compareUI5VersionGte(ui5VersionA: string, ui5VersionB: string): boolean { + if (ui5VersionA === '') { + // latest version + return true; + } else { + return gte(ui5VersionA, ui5VersionB, { loose: true }); + } +} + +/** + * Gets the template version path based on the UI5 version. + * + * @param version - The framework version. + * @returns {string} - The template version path. + */ +export function getTemplateVersionPath(version: string): string { + let templateVersionPath = ''; + if (compareUI5VersionGte(version, ui5LtsVersion_1_120)) { + templateVersionPath = ui5LtsVersion_1_120; + } else { + templateVersionPath = ui5LtsVersion_1_71; + } + + return templateVersionPath; +} diff --git a/packages/ui5-library-writer/templates/common/gitignore.tmpl b/packages/ui5-library-writer/templates/common/1.120.0/gitignore.tmpl similarity index 100% rename from packages/ui5-library-writer/templates/common/gitignore.tmpl rename to packages/ui5-library-writer/templates/common/1.120.0/gitignore.tmpl diff --git a/packages/ui5-library-writer/templates/common/karma.conf.tmpl b/packages/ui5-library-writer/templates/common/1.120.0/karma.conf.tmpl similarity index 100% rename from packages/ui5-library-writer/templates/common/karma.conf.tmpl rename to packages/ui5-library-writer/templates/common/1.120.0/karma.conf.tmpl diff --git a/packages/ui5-library-writer/templates/common/package.json b/packages/ui5-library-writer/templates/common/1.120.0/package.json similarity index 100% rename from packages/ui5-library-writer/templates/common/package.json rename to packages/ui5-library-writer/templates/common/1.120.0/package.json diff --git a/packages/ui5-library-writer/templates/common/src/baselibrary/.library b/packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/.library similarity index 100% rename from packages/ui5-library-writer/templates/common/src/baselibrary/.library rename to packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/.library diff --git a/packages/ui5-library-writer/templates/common/src/baselibrary/Example.gen.d.ts b/packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/Example.gen.d.ts similarity index 100% rename from packages/ui5-library-writer/templates/common/src/baselibrary/Example.gen.d.ts rename to packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/Example.gen.d.ts diff --git a/packages/ui5-library-writer/templates/common/src/baselibrary/Example.js b/packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/Example.js similarity index 100% rename from packages/ui5-library-writer/templates/common/src/baselibrary/Example.js rename to packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/Example.js diff --git a/packages/ui5-library-writer/templates/common/src/baselibrary/Example.ts b/packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/Example.ts similarity index 100% rename from packages/ui5-library-writer/templates/common/src/baselibrary/Example.ts rename to packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/Example.ts diff --git a/packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/ExampleRenderer.js b/packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/ExampleRenderer.js new file mode 100644 index 00000000000..721405d44db --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/ExampleRenderer.js @@ -0,0 +1,47 @@ +/*! + * ${copyright} + */ + +sap.ui.define([ + "sap/ui/core/Lib", + "./library" +], function (Lib, library) { + "use strict"; + + // refer to library types + var ExampleColor = library.ExampleColor; + + /** + * Example renderer. + * @namespace + */ + var ExampleRenderer = { + apiVersion: 2 // usage of DOM Patcher + }; + + /** + * Renders the HTML for the given control, using the provided + * {@link sap.ui.core.RenderManager}. + * + * @param {sap.ui.core.RenderManager} rm The reference to the sap.ui.core.RenderManager + * @param {sap.ui.core.Control} control The control instance to be rendered + */ + ExampleRenderer.render = function (rm, control) { + + var i18n = Lib.getResourceBundleFor("<%= libraryNamespace %>"); + + rm.openStart("div", control); + if (control.getColor() === ExampleColor.Highlight) { + rm.class("myLibPrefixExampleHighlight"); + } else { + rm.class("myLibPrefixExample"); + } + rm.openEnd( ); + rm.text(i18n.getText("ANY_TEXT") + ": " + control.getText()); + rm.close("div"); + + }; + + return ExampleRenderer; + +}); diff --git a/packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/ExampleRenderer.ts b/packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/ExampleRenderer.ts new file mode 100644 index 00000000000..0261962de58 --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/ExampleRenderer.ts @@ -0,0 +1,41 @@ +/*! + * ${copyright} + */ + +import ResourceBundle from "sap/base/i18n/ResourceBundle"; +import Lib from "sap/ui/core/Lib"; +import RenderManager from "sap/ui/core/RenderManager"; +import Example from "./Example"; +import { ExampleColor } from "./library"; + +/** + * Example renderer. + * @namespace + */ +const ExampleRenderer = { + apiVersion: 2, // usage of DOM Patcher + + /** + * Renders the HTML for the given control, using the provided {@link RenderManager}. + * + * @param {RenderManager} rm The reference to the sap.ui.core.RenderManager + * @param {Example} control The control instance to be rendered + */ + render: function (rm: RenderManager, control: Example) { + + const i18n = Lib.getResourceBundleFor("<%= libraryNamespace %>") as ResourceBundle; + + rm.openStart("div", control); + if (control.getColor() === ExampleColor.Highlight) { + rm.class("myLibPrefixExampleHighlight"); + } else { + rm.class("myLibPrefixExample"); + } + rm.openEnd( ); + rm.text(i18n.getText("ANY_TEXT") + ": " + control.getText()); + rm.close("div"); + } + +}; + +export default ExampleRenderer; \ No newline at end of file diff --git a/packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/library.js b/packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/library.js new file mode 100644 index 00000000000..23120837c0c --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/library.js @@ -0,0 +1,68 @@ +/*! + * ${copyright} + */ + +/** + * Initialization Code and shared classes of library <%= libraryNamespace %>. + */ +sap.ui.define([ + "sap/ui/core/Lib" +], function (Lib) { + "use strict"; + + // delegate further initialization of this library to the Core + // Hint: sap.ui.getCore() must still be used to support preload with sync bootstrap! + Lib.init({ + name: "<%= libraryNamespace %>", + version: "${version}", + dependencies: [ // keep in sync with the ui5.yaml and .library files + "sap.ui.core" + ], + types: [ + "<%= libraryNamespace %>.ExampleColor" + ], + interfaces: [], + controls: [ + "<%= libraryNamespace %>.Example" + ], + elements: [], + noLibraryCSS: false, // if no CSS is provided, you can disable the library.css load here + apiVersion: 2 + }); + + /** + * Some description about <%= libraryName %> + * + * @namespace + * @name <%= libraryNamespace %> + * @author <%= author %> + * @version ${version} + * @public + */ + var thisLib = <%= libraryNamespace %>; + + /** + * Semantic Colors of the <%= libraryNamespace %>.Example. + * + * @enum {string} + * @public + */ + thisLib.ExampleColor = { + + /** + * Default color (brand color) + * @public + */ + Default : "Default", + + /** + * Highlight color + * @public + */ + Highlight : "Highlight" + + }; + + return thisLib; + +}); diff --git a/packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/library.ts b/packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/library.ts new file mode 100644 index 00000000000..bb39a4baaaa --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/library.ts @@ -0,0 +1,58 @@ +/*! + * ${copyright} + */ + +import ObjectPath from "sap/base/util/ObjectPath"; +import Lib from "sap/ui/core/Lib"; + +/** + * Initialization Code and shared classes of library <%= libraryNamespace %>. + */ + +// delegate further initialization of this library to the Core +// Hint: sap.ui.getCore() must still be used here to support preload with sync bootstrap! +Lib.init({ + name: "<%= libraryNamespace %>", + version: "${version}", + dependencies: [ // keep in sync with the ui5.yaml and .library files + "sap.ui.core" + ], + types: [ + "<%= libraryNamespace %>.ExampleColor" + ], + interfaces: [], + controls: [ + "<%= libraryNamespace %>.Example" + ], + elements: [], + noLibraryCSS: false, // if no CSS is provided, you can disable the library.css load here + apiVersion: 2, +}); + +// get the library object from global object space because all enums must be attached to it to be usable as UI5 types +// FIXME: this line is planned to become obsolete and may need to be removed later +const thisLib : {[key: string]: unknown} = ObjectPath.get("<%= libraryNamespace %>") as {[key: string]: unknown}; + +/** + * Semantic Colors of the com.myorg.myUI5Library.Example control. + * + * @enum {string} + * @public + */ +export enum ExampleColor { + + /** + * Default color (brand color) + * @public + */ + Default = "Default", + + /** + * Highlight color + * @public + */ + Highlight = "Highlight" + +} +// FIXME: this line is planned to become obsolete and may need to be removed later +thisLib.ExampleColor = ExampleColor; // add the enum to the library; this is important because UI5 otherwise cannot identify the type and will skip type checking for properties of this type \ No newline at end of file diff --git a/packages/ui5-library-writer/templates/common/src/baselibrary/messagebundle.properties b/packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/messagebundle.properties similarity index 100% rename from packages/ui5-library-writer/templates/common/src/baselibrary/messagebundle.properties rename to packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/messagebundle.properties diff --git a/packages/ui5-library-writer/templates/common/src/baselibrary/themes/base/Example.less b/packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/themes/base/Example.less similarity index 100% rename from packages/ui5-library-writer/templates/common/src/baselibrary/themes/base/Example.less rename to packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/themes/base/Example.less diff --git a/packages/ui5-library-writer/templates/common/src/baselibrary/themes/base/library.source.less b/packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/themes/base/library.source.less similarity index 100% rename from packages/ui5-library-writer/templates/common/src/baselibrary/themes/base/library.source.less rename to packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/themes/base/library.source.less diff --git a/packages/ui5-library-writer/templates/common/src/baselibrary/themes/sap_belize/library.source.less b/packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/themes/sap_belize/library.source.less similarity index 100% rename from packages/ui5-library-writer/templates/common/src/baselibrary/themes/sap_belize/library.source.less rename to packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/themes/sap_belize/library.source.less diff --git a/packages/ui5-library-writer/templates/common/src/baselibrary/themes/sap_belize_hcb/library.source.less b/packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/themes/sap_belize_hcb/library.source.less similarity index 100% rename from packages/ui5-library-writer/templates/common/src/baselibrary/themes/sap_belize_hcb/library.source.less rename to packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/themes/sap_belize_hcb/library.source.less diff --git a/packages/ui5-library-writer/templates/common/src/baselibrary/themes/sap_belize_hcw/library.source.less b/packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/themes/sap_belize_hcw/library.source.less similarity index 100% rename from packages/ui5-library-writer/templates/common/src/baselibrary/themes/sap_belize_hcw/library.source.less rename to packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/themes/sap_belize_hcw/library.source.less diff --git a/packages/ui5-library-writer/templates/common/src/baselibrary/themes/sap_belize_plus/library.source.less b/packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/themes/sap_belize_plus/library.source.less similarity index 100% rename from packages/ui5-library-writer/templates/common/src/baselibrary/themes/sap_belize_plus/library.source.less rename to packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/themes/sap_belize_plus/library.source.less diff --git a/packages/ui5-library-writer/templates/common/src/baselibrary/themes/sap_fiori_3/library.source.less b/packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/themes/sap_fiori_3/library.source.less similarity index 100% rename from packages/ui5-library-writer/templates/common/src/baselibrary/themes/sap_fiori_3/library.source.less rename to packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/themes/sap_fiori_3/library.source.less diff --git a/packages/ui5-library-writer/templates/common/src/baselibrary/themes/sap_fiori_3_dark/library.source.less b/packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/themes/sap_fiori_3_dark/library.source.less similarity index 100% rename from packages/ui5-library-writer/templates/common/src/baselibrary/themes/sap_fiori_3_dark/library.source.less rename to packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/themes/sap_fiori_3_dark/library.source.less diff --git a/packages/ui5-library-writer/templates/common/src/baselibrary/themes/sap_fiori_3_hcb/library.source.less b/packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/themes/sap_fiori_3_hcb/library.source.less similarity index 100% rename from packages/ui5-library-writer/templates/common/src/baselibrary/themes/sap_fiori_3_hcb/library.source.less rename to packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/themes/sap_fiori_3_hcb/library.source.less diff --git a/packages/ui5-library-writer/templates/common/src/baselibrary/themes/sap_fiori_3_hcw/library.source.less b/packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/themes/sap_fiori_3_hcw/library.source.less similarity index 100% rename from packages/ui5-library-writer/templates/common/src/baselibrary/themes/sap_fiori_3_hcw/library.source.less rename to packages/ui5-library-writer/templates/common/1.120.0/src/baselibrary/themes/sap_fiori_3_hcw/library.source.less diff --git a/packages/ui5-library-writer/templates/common/1.120.0/test/baselibrary/Example.html b/packages/ui5-library-writer/templates/common/1.120.0/test/baselibrary/Example.html new file mode 100644 index 00000000000..e2b8e25363b --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.120.0/test/baselibrary/Example.html @@ -0,0 +1,21 @@ + + + + + Test Page for <%= libraryNamespace %>.Example + + + + +

Test Page for <%= libraryNamespace %>.Example

+
+ + diff --git a/packages/ui5-library-writer/templates/common/test/baselibrary/Example.js b/packages/ui5-library-writer/templates/common/1.120.0/test/baselibrary/Example.js similarity index 100% rename from packages/ui5-library-writer/templates/common/test/baselibrary/Example.js rename to packages/ui5-library-writer/templates/common/1.120.0/test/baselibrary/Example.js diff --git a/packages/ui5-library-writer/templates/common/test/baselibrary/Example.ts b/packages/ui5-library-writer/templates/common/1.120.0/test/baselibrary/Example.ts similarity index 100% rename from packages/ui5-library-writer/templates/common/test/baselibrary/Example.ts rename to packages/ui5-library-writer/templates/common/1.120.0/test/baselibrary/Example.ts diff --git a/packages/ui5-library-writer/templates/common/test/baselibrary/qunit/Example.qunit.js b/packages/ui5-library-writer/templates/common/1.120.0/test/baselibrary/qunit/Example.qunit.js similarity index 100% rename from packages/ui5-library-writer/templates/common/test/baselibrary/qunit/Example.qunit.js rename to packages/ui5-library-writer/templates/common/1.120.0/test/baselibrary/qunit/Example.qunit.js diff --git a/packages/ui5-library-writer/templates/common/test/baselibrary/qunit/Example.qunit.ts b/packages/ui5-library-writer/templates/common/1.120.0/test/baselibrary/qunit/Example.qunit.ts similarity index 100% rename from packages/ui5-library-writer/templates/common/test/baselibrary/qunit/Example.qunit.ts rename to packages/ui5-library-writer/templates/common/1.120.0/test/baselibrary/qunit/Example.qunit.ts diff --git a/packages/ui5-library-writer/templates/common/test/baselibrary/qunit/testsuite.qunit.html b/packages/ui5-library-writer/templates/common/1.120.0/test/baselibrary/qunit/testsuite.qunit.html similarity index 100% rename from packages/ui5-library-writer/templates/common/test/baselibrary/qunit/testsuite.qunit.html rename to packages/ui5-library-writer/templates/common/1.120.0/test/baselibrary/qunit/testsuite.qunit.html diff --git a/packages/ui5-library-writer/templates/common/test/baselibrary/qunit/testsuite.qunit.js b/packages/ui5-library-writer/templates/common/1.120.0/test/baselibrary/qunit/testsuite.qunit.js similarity index 100% rename from packages/ui5-library-writer/templates/common/test/baselibrary/qunit/testsuite.qunit.js rename to packages/ui5-library-writer/templates/common/1.120.0/test/baselibrary/qunit/testsuite.qunit.js diff --git a/packages/ui5-library-writer/templates/common/test/baselibrary/qunit/testsuite.qunit.ts b/packages/ui5-library-writer/templates/common/1.120.0/test/baselibrary/qunit/testsuite.qunit.ts similarity index 100% rename from packages/ui5-library-writer/templates/common/test/baselibrary/qunit/testsuite.qunit.ts rename to packages/ui5-library-writer/templates/common/1.120.0/test/baselibrary/qunit/testsuite.qunit.ts diff --git a/packages/ui5-library-writer/templates/common/1.120.0/ui5.yaml b/packages/ui5-library-writer/templates/common/1.120.0/ui5.yaml new file mode 100644 index 00000000000..2622622ec59 --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.120.0/ui5.yaml @@ -0,0 +1,18 @@ +specVersion: '2.2' +metadata: + name: "<%= libraryName %>" +type: library +framework: + name: <%= framework %> + version: <%= frameworkVersion %> + libraries: + - name: sap.ui.core + - name: themelib_sap_fiori_3 +server: + customMiddleware: + - name: fiori-tools-appreload + afterMiddleware: compression + configuration: + path: test + port: 35729 + delay: 300 \ No newline at end of file diff --git a/packages/ui5-library-writer/templates/common/1.71.0/gitignore.tmpl b/packages/ui5-library-writer/templates/common/1.71.0/gitignore.tmpl new file mode 100644 index 00000000000..d0f499126cb --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.71.0/gitignore.tmpl @@ -0,0 +1,9 @@ +node_modules/ +dist/ +.scp/ +Makefile*.mta +mta_archives +mta-* +resources +archive.zip +.*_mta_build_tmp \ No newline at end of file diff --git a/packages/ui5-library-writer/templates/common/1.71.0/karma.conf.tmpl b/packages/ui5-library-writer/templates/common/1.71.0/karma.conf.tmpl new file mode 100644 index 00000000000..11f8dbff81d --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.71.0/karma.conf.tmpl @@ -0,0 +1,7 @@ +// karma-ui5 usage: https://github.com/SAP/karma-ui5 +module.exports = function (config) { + config.set({ + frameworks: ["ui5"], + browsers: ["Chrome"] + }); +}; \ No newline at end of file diff --git a/packages/ui5-library-writer/templates/common/1.71.0/package.json b/packages/ui5-library-writer/templates/common/1.71.0/package.json new file mode 100644 index 00000000000..2db425eed5e --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.71.0/package.json @@ -0,0 +1,18 @@ +{ + "name": "<%= libraryName %>", + "version": "1.0.0", + "devDependencies": { + "@ui5/cli": "^3.9.1", + "karma": "6.3.17", + "karma-chrome-launcher": "^3.1.1", + "karma-cli": "^2.0.0", + "karma-ui5": "^3.0.3", + "@sap/ux-ui5-tooling": "1" + }, + "scripts": { + "build": "ui5 build --clean-dest", + "start": "fiori run --open test-resources/<%= libraryNamespaceURI %>/Example.html", + "testsuite": "fiori run --open test-resources/<%= libraryNamespaceURI %>/qunit/testsuite.qunit.html", + "test": "karma start --browsers=ChromeHeadless --singleRun=true" + } +} diff --git a/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/.library b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/.library new file mode 100644 index 00000000000..8075bd19ea4 --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/.library @@ -0,0 +1,14 @@ + + + <%= libraryNamespace %> + <%= author %> + ${version} + ${copyright} + <%= libraryName %> + Some description about <%= libraryName %> + + + sap.ui.core + + + diff --git a/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/Example.gen.d.ts b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/Example.gen.d.ts new file mode 100644 index 00000000000..05bec07ecea --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/Example.gen.d.ts @@ -0,0 +1,33 @@ +import { ExampleColor } from "./library"; +import Event from "sap/ui/base/Event"; +import { PropertyBindingInfo } from "sap/ui/base/ManagedObject"; +import { $ControlSettings } from "sap/ui/core/Control"; + +declare module "./Example" { + + /** + * Interface defining the settings object used in constructor calls + */ + interface $ExampleSettings extends $ControlSettings { + text?: string | PropertyBindingInfo; + color?: ExampleColor | PropertyBindingInfo | `{${string}}`; + press?: (event: Event) => void; + } + + export default interface Example { + + // property: text + getText(): string; + setText(text: string): this; + + // property: color + getColor(): ExampleColor; + setColor(color: ExampleColor): this; + + // event: press + attachPress(fn: (event: Event) => void, listener?: object): this; + attachPress(data: CustomDataType, fn: (event: Event, data: CustomDataType) => void, listener?: object): this; + detachPress(fn: (event: Event) => void, listener?: object): this; + firePress(parameters?: object): this; + } +} \ No newline at end of file diff --git a/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/Example.js b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/Example.js new file mode 100644 index 00000000000..6c44bb4b8ec --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/Example.js @@ -0,0 +1,68 @@ +/*! + * ${copyright} + */ + +// Provides control <%= libraryNamespace %>.Example. +sap.ui.define([ + "./library", + "sap/ui/core/Control", + "./ExampleRenderer" +], function (library, Control, ExampleRenderer) { + "use strict"; + + // refer to library types + var ExampleColor = library.ExampleColor; + + /** + * Constructor for a new <%= libraryNamespace %>.Example control. + * + * @param {string} [sId] id for the new control, generated automatically if no id is given + * @param {object} [mSettings] initial settings for the new control + * + * @class + * Some class description goes here. + * @extends sap.ui.core.Control + * + * @author <%= author %> + * @version ${version} + * + * @constructor + * @public + * @alias <%= libraryNamespace %>.Example + */ + var Example = Control.extend("<%= libraryNamespace %>.Example", /** @lends <%= libraryNamespace %>.Example.prototype */ { + metadata: { + library: "<%= libraryNamespace %>", + properties: { + /** + * The text to display. + */ + text: { + type: "string", + group: "Data", + defaultValue: null + }, + /** + * The color to use (default to "Default" color). + */ + color: { + type: "<%= libraryNamespace %>.ExampleColor", + group: "Appearance", + defaultValue: ExampleColor.Default + } + }, + events: { + /** + * Event is fired when the user clicks the control. + */ + press: {} + } + }, + renderer: ExampleRenderer, + onclick: function() { + this.firePress(); + } + }); + return Example; + +}); diff --git a/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/Example.ts b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/Example.ts new file mode 100644 index 00000000000..6f019795db0 --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/Example.ts @@ -0,0 +1,65 @@ +/*! + * ${copyright} + */ + +// Provides control <%= libraryNamespace %>.Example. +import Control from "sap/ui/core/Control"; +import ExampleRenderer from "./ExampleRenderer"; +import { ExampleColor } from "./library"; + + + +/** + * Constructor for a new <%= libraryNamespace %>.Example control. + * + * Some class description goes here. + * @extends Control + * + * @author OpenUI5 Team + * @version ${version} + * + * @constructor + * @public + * @name <%= libraryNamespace %>.Example + */ +export default class Example extends Control { + + // The following three lines were generated and should remain as-is to make TypeScript aware of the constructor signatures + constructor(id?: string | $ExampleSettings); + constructor(id?: string, settings?: $ExampleSettings); + constructor(id?: string, settings?: $ExampleSettings) { super(id, settings); } + + static readonly metadata = { + library: "<%= libraryNamespace %>", + properties: { + /** + * The text to display. + */ + text: { + type: "string", + group: "Data", + defaultValue: null + }, + /** + * The color to use (default to "Default" color). + */ + color: { + type: "<%= libraryNamespace %>.ExampleColor", + group: "Appearance", + defaultValue: ExampleColor.Default + } + }, + events: { + /** + * Event is fired when the user clicks the control. + */ + press: {} + } + }; + + static renderer = ExampleRenderer; + + onclick = () => { + this.firePress(); + }; +} \ No newline at end of file diff --git a/packages/ui5-library-writer/templates/common/src/baselibrary/ExampleRenderer.js b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/ExampleRenderer.js similarity index 100% rename from packages/ui5-library-writer/templates/common/src/baselibrary/ExampleRenderer.js rename to packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/ExampleRenderer.js diff --git a/packages/ui5-library-writer/templates/common/src/baselibrary/ExampleRenderer.ts b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/ExampleRenderer.ts similarity index 100% rename from packages/ui5-library-writer/templates/common/src/baselibrary/ExampleRenderer.ts rename to packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/ExampleRenderer.ts diff --git a/packages/ui5-library-writer/templates/common/src/baselibrary/library.js b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/library.js similarity index 100% rename from packages/ui5-library-writer/templates/common/src/baselibrary/library.js rename to packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/library.js diff --git a/packages/ui5-library-writer/templates/common/src/baselibrary/library.ts b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/library.ts similarity index 100% rename from packages/ui5-library-writer/templates/common/src/baselibrary/library.ts rename to packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/library.ts diff --git a/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/messagebundle.properties b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/messagebundle.properties new file mode 100644 index 00000000000..fc0c39f97bb --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/messagebundle.properties @@ -0,0 +1,2 @@ +# Translation file of library <%= libraryNamespace %>. +ANY_TEXT=AnyText diff --git a/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/base/Example.less b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/base/Example.less new file mode 100644 index 00000000000..92e2d5df455 --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/base/Example.less @@ -0,0 +1,19 @@ +/* Theme Parameter Toolbox: https://sdk.openui5.org/test-resources/sap/m/demokit/theming/webapp/index.html */ + +.myLibPrefixExample, +.myLibPrefixExampleHighlight { + color: @sapUiText; + background-color: @sapUiNeutralBG; + border: 1rem solid @sapUiContentForegroundBorderColor; + border-radius: 1rem; + opacity: 0.8; + padding: 2rem; + margin: 2rem 8rem; + text-align: center; + font-size: 2em; + line-height: 3em; +} + +.myLibPrefixExampleHighlight { + background-color: @sapUiSuccessBG; +} diff --git a/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/base/library.source.less b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/base/library.source.less new file mode 100644 index 00000000000..18867023551 --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/base/library.source.less @@ -0,0 +1,4 @@ +@import "/resources/sap/ui/core/themes/base/base.less"; +@import "/resources/sap/ui/core/themes/base/global.less"; + +@import "Example.less"; diff --git a/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/sap_belize/library.source.less b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/sap_belize/library.source.less new file mode 100644 index 00000000000..7b9e8613c46 --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/sap_belize/library.source.less @@ -0,0 +1,3 @@ +@import "../base/library.source.less"; +@import "/resources/sap/ui/core/themes/sap_belize/base.less"; +@import "/resources/sap/ui/core/themes/sap_belize/global.less"; diff --git a/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/sap_belize_hcb/library.source.less b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/sap_belize_hcb/library.source.less new file mode 100644 index 00000000000..9bcf82f9d02 --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/sap_belize_hcb/library.source.less @@ -0,0 +1,3 @@ +@import "../base/library.source.less"; +@import "/resources/sap/ui/core/themes/sap_belize_hcb/base.less"; +@import "/resources/sap/ui/core/themes/sap_belize_hcb/global.less"; diff --git a/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/sap_belize_hcw/library.source.less b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/sap_belize_hcw/library.source.less new file mode 100644 index 00000000000..9c85013ee8d --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/sap_belize_hcw/library.source.less @@ -0,0 +1,3 @@ +@import "../base/library.source.less"; +@import "/resources/sap/ui/core/themes/sap_belize_hcw/base.less"; +@import "/resources/sap/ui/core/themes/sap_belize_hcw/global.less"; diff --git a/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/sap_belize_plus/library.source.less b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/sap_belize_plus/library.source.less new file mode 100644 index 00000000000..8402b96caf6 --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/sap_belize_plus/library.source.less @@ -0,0 +1,3 @@ +@import "../sap_belize/library.source.less"; +@import "/resources/sap/ui/core/themes/sap_belize_plus/base.less"; +@import "/resources/sap/ui/core/themes/sap_belize_plus/global.less"; diff --git a/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/sap_fiori_3/library.source.less b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/sap_fiori_3/library.source.less new file mode 100644 index 00000000000..98a47942165 --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/sap_fiori_3/library.source.less @@ -0,0 +1,3 @@ +@import "../base/library.source.less"; +@import "/resources/sap/ui/core/themes/sap_fiori_3/base.less"; +@import "/resources/sap/ui/core/themes/sap_fiori_3/global.less"; diff --git a/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/sap_fiori_3_dark/library.source.less b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/sap_fiori_3_dark/library.source.less new file mode 100644 index 00000000000..f0b9c891bb9 --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/sap_fiori_3_dark/library.source.less @@ -0,0 +1,3 @@ +@import "../base/library.source.less"; +@import "/resources/sap/ui/core/themes/sap_fiori_3_dark/base.less"; +@import "/resources/sap/ui/core/themes/sap_fiori_3_dark/global.less"; diff --git a/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/sap_fiori_3_hcb/library.source.less b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/sap_fiori_3_hcb/library.source.less new file mode 100644 index 00000000000..9239a9308a1 --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/sap_fiori_3_hcb/library.source.less @@ -0,0 +1,3 @@ +@import "../base/library.source.less"; +@import "/resources/sap/ui/core/themes/sap_fiori_3_hcb/base.less"; +@import "/resources/sap/ui/core/themes/sap_fiori_3_hcb/global.less"; diff --git a/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/sap_fiori_3_hcw/library.source.less b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/sap_fiori_3_hcw/library.source.less new file mode 100644 index 00000000000..721aae859aa --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.71.0/src/baselibrary/themes/sap_fiori_3_hcw/library.source.less @@ -0,0 +1,3 @@ +@import "../base/library.source.less"; +@import "/resources/sap/ui/core/themes/sap_fiori_3_hcw/base.less"; +@import "/resources/sap/ui/core/themes/sap_fiori_3_hcw/global.less"; diff --git a/packages/ui5-library-writer/templates/common/test/baselibrary/Example.html b/packages/ui5-library-writer/templates/common/1.71.0/test/baselibrary/Example.html similarity index 100% rename from packages/ui5-library-writer/templates/common/test/baselibrary/Example.html rename to packages/ui5-library-writer/templates/common/1.71.0/test/baselibrary/Example.html diff --git a/packages/ui5-library-writer/templates/common/1.71.0/test/baselibrary/Example.js b/packages/ui5-library-writer/templates/common/1.71.0/test/baselibrary/Example.js new file mode 100644 index 00000000000..07dab35d240 --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.71.0/test/baselibrary/Example.js @@ -0,0 +1,18 @@ +// eslint-disable-next-line no-undef +sap.ui.define([ + "<%= libraryNamespaceURI %>/library", + "<%= libraryNamespaceURI %>/Example" +], function(library, Example) { + "use strict"; + + // refer to library types + var ExampleColor = library.ExampleColor; + + // create a new instance of the Example control and + // place it into the DOM element with the id "content" + new Example({ + text: "Example", + color: ExampleColor.Highlight + }).placeAt("content"); + +}); diff --git a/packages/ui5-library-writer/templates/common/1.71.0/test/baselibrary/Example.ts b/packages/ui5-library-writer/templates/common/1.71.0/test/baselibrary/Example.ts new file mode 100644 index 00000000000..9eaa0113fc8 --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.71.0/test/baselibrary/Example.ts @@ -0,0 +1,9 @@ +import { ExampleColor } from '<%= libraryNamespaceURI %>/library'; +import Example from '<%= libraryNamespaceURI %>/Example'; + +// Create a new instance of the Example control and +// place it into the DOM element with the id "content" +new Example({ + text: 'Example', + color: ExampleColor.Highlight, +}).placeAt('content'); diff --git a/packages/ui5-library-writer/templates/common/1.71.0/test/baselibrary/qunit/Example.qunit.js b/packages/ui5-library-writer/templates/common/1.71.0/test/baselibrary/qunit/Example.qunit.js new file mode 100644 index 00000000000..5253fd82d35 --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.71.0/test/baselibrary/qunit/Example.qunit.js @@ -0,0 +1,65 @@ +/*global QUnit */ +// eslint-disable-next-line no-undef +sap.ui.define([ + "sap/ui/qunit/QUnitUtils", + "sap/ui/qunit/utils/createAndAppendDiv", + "<%= libraryNamespaceURI %>/library", + "<%= libraryNamespaceURI %>/Example" +], function(qutils, createAndAppendDiv, library, Example) { + "use strict"; + + // refer to library types + var ExampleColor = library.ExampleColor; + + // prepare DOM + createAndAppendDiv("uiArea1"); + + // module for basic checks + QUnit.module("Example Tests"); + + // example sync test + QUnit.test("Sync", function(assert) { + assert.expect(1); + assert.ok(true, "ok"); + }); + + // example async test + QUnit.test("Async", function(assert) { + assert.expect(1); + return new Promise(function(resolve, reject) { + assert.ok(true, "ok"); + resolve(); + }); + }) + + // module for basic checks + QUnit.module("Basic Control Checks"); + + // some basic control checks + QUnit.test("Test get properties", function(assert) { + assert.expect(2); + var oExample = new Example({ + text: "Example" + }); + assert.equal(oExample.getText(), "Example", "Check text equals 'Example'"); + assert.equal(oExample.getColor(), ExampleColor.Default, "Check color equals 'Default'"); + }); + + // some basic eventing check + QUnit.test("Test click event", function(assert) { + assert.expect(1); + var oExample = new Example("example", { + text: "Example", + press: function() { + assert.ok(true, "Event has been fired!") + } + }).placeAt("uiArea1"); + return new Promise(function(resolve, reject) { + setTimeout(function() { + qutils.triggerMouseEvent("example", "click", 1, 1); + resolve(); + }, 100); + }); + }); + +}); diff --git a/packages/ui5-library-writer/templates/common/1.71.0/test/baselibrary/qunit/Example.qunit.ts b/packages/ui5-library-writer/templates/common/1.71.0/test/baselibrary/qunit/Example.qunit.ts new file mode 100644 index 00000000000..9e0f0d3f02f --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.71.0/test/baselibrary/qunit/Example.qunit.ts @@ -0,0 +1,68 @@ +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-nocheck + +/*global QUnit */ +// eslint-disable-next-line no-undef +sap.ui.define([ + "sap/ui/qunit/QUnitUtils", + "sap/ui/qunit/utils/createAndAppendDiv", + "<%= libraryNamespaceURI %>/library", + "<%= libraryNamespaceURI %>/Example" +], function(qutils, createAndAppendDiv, library, Example) { + "use strict"; + + // refer to library types + const ExampleColor = library.ExampleColor; + + // prepare DOM + createAndAppendDiv("uiArea1"); + + // module for basic checks + QUnit.module("Example Tests"); + + // example sync test + QUnit.test("Sync", function(assert) { + assert.expect(1); + assert.ok(true, "ok"); + }); + + // example async test + QUnit.test("Async", function(assert) { + assert.expect(1); + return new Promise(function(resolve, reject) { + assert.ok(true, "ok"); + resolve(); + }); + }) + + // module for basic checks + QUnit.module("Basic Control Checks"); + + // some basic control checks + QUnit.test("Test get properties", function(assert) { + assert.expect(2); + const oExample = new Example({ + text: "Example" + }); + assert.equal(oExample.getText(), "Example", "Check text equals 'Example'"); + assert.equal(oExample.getColor(), ExampleColor.Default, "Check color equals 'Default'"); + }); + + // some basic eventing check + QUnit.test("Test click event", function(assert) { + assert.expect(1); + const oExample = new Example("example", { + text: "Example", + press: function() { + assert.ok(true, "Event has been fired!") + } + }).placeAt("uiArea1"); + return new Promise(function(resolve, reject) { + setTimeout(function() { + qutils.triggerMouseEvent("example", "click", 1, 1); + resolve(); + }, 100); + }); + }); + +}); diff --git a/packages/ui5-library-writer/templates/common/1.71.0/test/baselibrary/qunit/testsuite.qunit.html b/packages/ui5-library-writer/templates/common/1.71.0/test/baselibrary/qunit/testsuite.qunit.html new file mode 100644 index 00000000000..57a2486bd08 --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.71.0/test/baselibrary/qunit/testsuite.qunit.html @@ -0,0 +1,13 @@ + + + + + + + QUnit TestSuite for <%= libraryNamespace %> + + + + + diff --git a/packages/ui5-library-writer/templates/common/1.71.0/test/baselibrary/qunit/testsuite.qunit.js b/packages/ui5-library-writer/templates/common/1.71.0/test/baselibrary/qunit/testsuite.qunit.js new file mode 100644 index 00000000000..4d89d0be582 --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.71.0/test/baselibrary/qunit/testsuite.qunit.js @@ -0,0 +1,35 @@ +// eslint-disable-next-line no-undef +sap.ui.define(function() { + "use strict"; + + return { + name: "QUnit TestSuite for <%= libraryNamespace %>", + defaults: { + bootCore: true, + ui5: { + libs: "sap.ui.core,<%= libraryNamespace %>", + theme: "sap_fiori_3", + noConflict: true, + preload: "auto" + }, + qunit: { + version: 2, + reorder: false + }, + sinon: { + version: 4, + qunitBridge: true, + useFakeTimers: false + }, + module: "./{name}.qunit" + }, + tests: { + // test file for the Example control + Example: { + title: "QUnit Test for Example", + _alternativeTitle: "QUnit tests: <%= libraryNamespace %>.Example" + } + } + }; + +}); diff --git a/packages/ui5-library-writer/templates/common/1.71.0/test/baselibrary/qunit/testsuite.qunit.ts b/packages/ui5-library-writer/templates/common/1.71.0/test/baselibrary/qunit/testsuite.qunit.ts new file mode 100644 index 00000000000..4d89d0be582 --- /dev/null +++ b/packages/ui5-library-writer/templates/common/1.71.0/test/baselibrary/qunit/testsuite.qunit.ts @@ -0,0 +1,35 @@ +// eslint-disable-next-line no-undef +sap.ui.define(function() { + "use strict"; + + return { + name: "QUnit TestSuite for <%= libraryNamespace %>", + defaults: { + bootCore: true, + ui5: { + libs: "sap.ui.core,<%= libraryNamespace %>", + theme: "sap_fiori_3", + noConflict: true, + preload: "auto" + }, + qunit: { + version: 2, + reorder: false + }, + sinon: { + version: 4, + qunitBridge: true, + useFakeTimers: false + }, + module: "./{name}.qunit" + }, + tests: { + // test file for the Example control + Example: { + title: "QUnit Test for Example", + _alternativeTitle: "QUnit tests: <%= libraryNamespace %>.Example" + } + } + }; + +}); diff --git a/packages/ui5-library-writer/templates/common/ui5.yaml b/packages/ui5-library-writer/templates/common/1.71.0/ui5.yaml similarity index 100% rename from packages/ui5-library-writer/templates/common/ui5.yaml rename to packages/ui5-library-writer/templates/common/1.71.0/ui5.yaml diff --git a/packages/ui5-library-writer/test/__snapshots__/index.test.ts.snap b/packages/ui5-library-writer/test/__snapshots__/index.test.ts.snap index 47c96c697fd..3f795fcbb6d 100644 --- a/packages/ui5-library-writer/test/__snapshots__/index.test.ts.snap +++ b/packages/ui5-library-writer/test/__snapshots__/index.test.ts.snap @@ -547,16 +547,1733 @@ server: } `; +exports[`Reuse lib templates Generate files for config: lib-js-1.121.0 1`] = ` +Object { + "com.sap.myui5jslib121/.gitignore": Object { + "contents": "node_modules/ +dist/ +.scp/ +Makefile*.mta +mta_archives +mta-* +resources +archive.zip +.*_mta_build_tmp", + "state": "modified", + }, + "com.sap.myui5jslib121/karma.conf.js": Object { + "contents": "// karma-ui5 usage: https://github.com/SAP/karma-ui5 +module.exports = function (config) { + config.set({ + frameworks: [\\"ui5\\"], + browsers: [\\"Chrome\\"] + }); +};", + "state": "modified", + }, + "com.sap.myui5jslib121/package.json": Object { + "contents": "{ + \\"name\\": \\"myui5jslib121\\", + \\"version\\": \\"1.0.0\\", + \\"devDependencies\\": { + \\"@ui5/cli\\": \\"^3.9.1\\", + \\"karma\\": \\"6.3.17\\", + \\"karma-chrome-launcher\\": \\"^3.1.1\\", + \\"karma-cli\\": \\"^2.0.0\\", + \\"karma-ui5\\": \\"^3.0.3\\", + \\"@sap/ux-ui5-tooling\\": \\"1\\" + }, + \\"scripts\\": { + \\"build\\": \\"ui5 build --clean-dest\\", + \\"start\\": \\"fiori run --open test-resources/com/sap/myui5jslib121/Example.html\\", + \\"testsuite\\": \\"fiori run --open test-resources/com/sap/myui5jslib121/qunit/testsuite.qunit.html\\", + \\"test\\": \\"karma start --browsers=ChromeHeadless --singleRun=true\\" + } +} +", + "state": "modified", + }, + "com.sap.myui5jslib121/src/com/sap/myui5jslib121/.library": Object { + "contents": " + + com.sap.myui5jslib121 + UI5 Lib Author + \${version} + \${copyright} + myui5jslib121 + Some description about myui5jslib121 + + + sap.ui.core + + + +", + "state": "modified", + }, + "com.sap.myui5jslib121/src/com/sap/myui5jslib121/Example.js": Object { + "contents": "/*! + * \${copyright} + */ + +// Provides control com.sap.myui5jslib121.Example. +sap.ui.define([ + \\"./library\\", + \\"sap/ui/core/Control\\", + \\"./ExampleRenderer\\" +], function (library, Control, ExampleRenderer) { + \\"use strict\\"; + + // refer to library types + var ExampleColor = library.ExampleColor; + + /** + * Constructor for a new com.sap.myui5jslib121.Example control. + * + * @param {string} [sId] id for the new control, generated automatically if no id is given + * @param {object} [mSettings] initial settings for the new control + * + * @class + * Some class description goes here. + * @extends sap.ui.core.Control + * + * @author UI5 Lib Author + * @version \${version} + * + * @constructor + * @public + * @alias com.sap.myui5jslib121.Example + */ + var Example = Control.extend(\\"com.sap.myui5jslib121.Example\\", /** @lends com.sap.myui5jslib121.Example.prototype */ { + metadata: { + library: \\"com.sap.myui5jslib121\\", + properties: { + /** + * The text to display. + */ + text: { + type: \\"string\\", + group: \\"Data\\", + defaultValue: null + }, + /** + * The color to use (default to \\"Default\\" color). + */ + color: { + type: \\"com.sap.myui5jslib121.ExampleColor\\", + group: \\"Appearance\\", + defaultValue: ExampleColor.Default + } + }, + events: { + /** + * Event is fired when the user clicks the control. + */ + press: {} + } + }, + renderer: ExampleRenderer, + onclick: function() { + this.firePress(); + } + }); + return Example; + +}); +", + "state": "modified", + }, + "com.sap.myui5jslib121/src/com/sap/myui5jslib121/ExampleRenderer.js": Object { + "contents": "/*! + * \${copyright} + */ + +sap.ui.define([ + \\"sap/ui/core/Lib\\", + \\"./library\\" +], function (Lib, library) { + \\"use strict\\"; + + // refer to library types + var ExampleColor = library.ExampleColor; + + /** + * Example renderer. + * @namespace + */ + var ExampleRenderer = { + apiVersion: 2 // usage of DOM Patcher + }; + + /** + * Renders the HTML for the given control, using the provided + * {@link sap.ui.core.RenderManager}. + * + * @param {sap.ui.core.RenderManager} rm The reference to the sap.ui.core.RenderManager + * @param {sap.ui.core.Control} control The control instance to be rendered + */ + ExampleRenderer.render = function (rm, control) { + + var i18n = Lib.getResourceBundleFor(\\"com.sap.myui5jslib121\\"); + + rm.openStart(\\"div\\", control); + if (control.getColor() === ExampleColor.Highlight) { + rm.class(\\"myLibPrefixExampleHighlight\\"); + } else { + rm.class(\\"myLibPrefixExample\\"); + } + rm.openEnd( ); + rm.text(i18n.getText(\\"ANY_TEXT\\") + \\": \\" + control.getText()); + rm.close(\\"div\\"); + + }; + + return ExampleRenderer; + +}); +", + "state": "modified", + }, + "com.sap.myui5jslib121/src/com/sap/myui5jslib121/library.js": Object { + "contents": "/*! + * \${copyright} + */ + +/** + * Initialization Code and shared classes of library com.sap.myui5jslib121. + */ +sap.ui.define([ + \\"sap/ui/core/Lib\\" +], function (Lib) { + \\"use strict\\"; + + // delegate further initialization of this library to the Core + // Hint: sap.ui.getCore() must still be used to support preload with sync bootstrap! + Lib.init({ + name: \\"com.sap.myui5jslib121\\", + version: \\"\${version}\\", + dependencies: [ // keep in sync with the ui5.yaml and .library files + \\"sap.ui.core\\" + ], + types: [ + \\"com.sap.myui5jslib121.ExampleColor\\" + ], + interfaces: [], + controls: [ + \\"com.sap.myui5jslib121.Example\\" + ], + elements: [], + noLibraryCSS: false, // if no CSS is provided, you can disable the library.css load here + apiVersion: 2 + }); + + /** + * Some description about myui5jslib121 + * + * @namespace + * @name com.sap.myui5jslib121 + * @author UI5 Lib Author + * @version \${version} + * @public + */ + var thisLib = com.sap.myui5jslib121; + + /** + * Semantic Colors of the com.sap.myui5jslib121.Example. + * + * @enum {string} + * @public + */ + thisLib.ExampleColor = { + + /** + * Default color (brand color) + * @public + */ + Default : \\"Default\\", + + /** + * Highlight color + * @public + */ + Highlight : \\"Highlight\\" + + }; + + return thisLib; + +}); +", + "state": "modified", + }, + "com.sap.myui5jslib121/src/com/sap/myui5jslib121/messagebundle.properties": Object { + "contents": "# Translation file of library com.sap.myui5jslib121. +ANY_TEXT=AnyText +", + "state": "modified", + }, + "com.sap.myui5jslib121/src/com/sap/myui5jslib121/themes/base/Example.less": Object { + "contents": "/* Theme Parameter Toolbox: https://sdk.openui5.org/test-resources/sap/m/demokit/theming/webapp/index.html */ + +.myLibPrefixExample, +.myLibPrefixExampleHighlight { + color: @sapUiText; + background-color: @sapUiNeutralBG; + border: 1rem solid @sapUiContentForegroundBorderColor; + border-radius: 1rem; + opacity: 0.8; + padding: 2rem; + margin: 2rem 8rem; + text-align: center; + font-size: 2em; + line-height: 3em; +} + +.myLibPrefixExampleHighlight { + background-color: @sapUiSuccessBG; +} +", + "state": "modified", + }, + "com.sap.myui5jslib121/src/com/sap/myui5jslib121/themes/base/library.source.less": Object { + "contents": "@import \\"/resources/sap/ui/core/themes/base/base.less\\"; +@import \\"/resources/sap/ui/core/themes/base/global.less\\"; + +@import \\"Example.less\\"; +", + "state": "modified", + }, + "com.sap.myui5jslib121/src/com/sap/myui5jslib121/themes/sap_belize/library.source.less": Object { + "contents": "@import \\"../base/library.source.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_belize/base.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_belize/global.less\\"; +", + "state": "modified", + }, + "com.sap.myui5jslib121/src/com/sap/myui5jslib121/themes/sap_belize_hcb/library.source.less": Object { + "contents": "@import \\"../base/library.source.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_belize_hcb/base.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_belize_hcb/global.less\\"; +", + "state": "modified", + }, + "com.sap.myui5jslib121/src/com/sap/myui5jslib121/themes/sap_belize_hcw/library.source.less": Object { + "contents": "@import \\"../base/library.source.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_belize_hcw/base.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_belize_hcw/global.less\\"; +", + "state": "modified", + }, + "com.sap.myui5jslib121/src/com/sap/myui5jslib121/themes/sap_belize_plus/library.source.less": Object { + "contents": "@import \\"../sap_belize/library.source.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_belize_plus/base.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_belize_plus/global.less\\"; +", + "state": "modified", + }, + "com.sap.myui5jslib121/src/com/sap/myui5jslib121/themes/sap_fiori_3/library.source.less": Object { + "contents": "@import \\"../base/library.source.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_fiori_3/base.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_fiori_3/global.less\\"; +", + "state": "modified", + }, + "com.sap.myui5jslib121/src/com/sap/myui5jslib121/themes/sap_fiori_3_dark/library.source.less": Object { + "contents": "@import \\"../base/library.source.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_fiori_3_dark/base.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_fiori_3_dark/global.less\\"; +", + "state": "modified", + }, + "com.sap.myui5jslib121/src/com/sap/myui5jslib121/themes/sap_fiori_3_hcb/library.source.less": Object { + "contents": "@import \\"../base/library.source.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_fiori_3_hcb/base.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_fiori_3_hcb/global.less\\"; +", + "state": "modified", + }, + "com.sap.myui5jslib121/src/com/sap/myui5jslib121/themes/sap_fiori_3_hcw/library.source.less": Object { + "contents": "@import \\"../base/library.source.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_fiori_3_hcw/base.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_fiori_3_hcw/global.less\\"; +", + "state": "modified", + }, + "com.sap.myui5jslib121/test/com/sap/myui5jslib121/Example.html": Object { + "contents": " + + + + Test Page for com.sap.myui5jslib121.Example + + + + +

Test Page for com.sap.myui5jslib121.Example

+
+ + +", + "state": "modified", + }, + "com.sap.myui5jslib121/test/com/sap/myui5jslib121/Example.js": Object { + "contents": "// eslint-disable-next-line no-undef +sap.ui.define([ + \\"com/sap/myui5jslib121/library\\", + \\"com/sap/myui5jslib121/Example\\" +], function(library, Example) { + \\"use strict\\"; + + // refer to library types + var ExampleColor = library.ExampleColor; + + // create a new instance of the Example control and + // place it into the DOM element with the id \\"content\\" + new Example({ + text: \\"Example\\", + color: ExampleColor.Highlight + }).placeAt(\\"content\\"); + +}); +", + "state": "modified", + }, + "com.sap.myui5jslib121/test/com/sap/myui5jslib121/qunit/Example.qunit.js": Object { + "contents": "/*global QUnit */ +// eslint-disable-next-line no-undef +sap.ui.define([ + \\"sap/ui/qunit/QUnitUtils\\", + \\"sap/ui/qunit/utils/createAndAppendDiv\\", + \\"com/sap/myui5jslib121/library\\", + \\"com/sap/myui5jslib121/Example\\" +], function(qutils, createAndAppendDiv, library, Example) { + \\"use strict\\"; + + // refer to library types + var ExampleColor = library.ExampleColor; + + // prepare DOM + createAndAppendDiv(\\"uiArea1\\"); + + // module for basic checks + QUnit.module(\\"Example Tests\\"); + + // example sync test + QUnit.test(\\"Sync\\", function(assert) { + assert.expect(1); + assert.ok(true, \\"ok\\"); + }); + + // example async test + QUnit.test(\\"Async\\", function(assert) { + assert.expect(1); + return new Promise(function(resolve, reject) { + assert.ok(true, \\"ok\\"); + resolve(); + }); + }) + + // module for basic checks + QUnit.module(\\"Basic Control Checks\\"); + + // some basic control checks + QUnit.test(\\"Test get properties\\", function(assert) { + assert.expect(2); + var oExample = new Example({ + text: \\"Example\\" + }); + assert.equal(oExample.getText(), \\"Example\\", \\"Check text equals 'Example'\\"); + assert.equal(oExample.getColor(), ExampleColor.Default, \\"Check color equals 'Default'\\"); + }); + + // some basic eventing check + QUnit.test(\\"Test click event\\", function(assert) { + assert.expect(1); + var oExample = new Example(\\"example\\", { + text: \\"Example\\", + press: function() { + assert.ok(true, \\"Event has been fired!\\") + } + }).placeAt(\\"uiArea1\\"); + return new Promise(function(resolve, reject) { + setTimeout(function() { + qutils.triggerMouseEvent(\\"example\\", \\"click\\", 1, 1); + resolve(); + }, 100); + }); + }); + +}); +", + "state": "modified", + }, + "com.sap.myui5jslib121/test/com/sap/myui5jslib121/qunit/testsuite.qunit.html": Object { + "contents": " + + + + + + QUnit TestSuite for com.sap.myui5jslib121 + + + + + +", + "state": "modified", + }, + "com.sap.myui5jslib121/test/com/sap/myui5jslib121/qunit/testsuite.qunit.js": Object { + "contents": "// eslint-disable-next-line no-undef +sap.ui.define(function() { + \\"use strict\\"; + + return { + name: \\"QUnit TestSuite for com.sap.myui5jslib121\\", + defaults: { + bootCore: true, + ui5: { + libs: \\"sap.ui.core,com.sap.myui5jslib121\\", + theme: \\"sap_fiori_3\\", + noConflict: true, + preload: \\"auto\\" + }, + qunit: { + version: 2, + reorder: false + }, + sinon: { + version: 4, + qunitBridge: true, + useFakeTimers: false + }, + module: \\"./{name}.qunit\\" + }, + tests: { + // test file for the Example control + Example: { + title: \\"QUnit Test for Example\\", + _alternativeTitle: \\"QUnit tests: com.sap.myui5jslib121.Example\\" + } + } + }; + +}); +", + "state": "modified", + }, + "com.sap.myui5jslib121/ui5.yaml": Object { + "contents": "specVersion: '2.2' +metadata: + name: \\"myui5jslib121\\" +type: library +framework: + name: SAPUI5 + version: 1.121.0 + libraries: + - name: sap.ui.core + - name: themelib_sap_fiori_3 +server: + customMiddleware: + - name: fiori-tools-appreload + afterMiddleware: compression + configuration: + path: test + port: 35729 + delay: 300", + "state": "modified", + }, +} +`; + +exports[`Reuse lib templates Generate files for config: lib-js-latest 1`] = ` +Object { + "com.sap.myui5jsliblatest/.gitignore": Object { + "contents": "node_modules/ +dist/ +.scp/ +Makefile*.mta +mta_archives +mta-* +resources +archive.zip +.*_mta_build_tmp", + "state": "modified", + }, + "com.sap.myui5jsliblatest/karma.conf.js": Object { + "contents": "// karma-ui5 usage: https://github.com/SAP/karma-ui5 +module.exports = function (config) { + config.set({ + frameworks: [\\"ui5\\"], + browsers: [\\"Chrome\\"] + }); +};", + "state": "modified", + }, + "com.sap.myui5jsliblatest/package.json": Object { + "contents": "{ + \\"name\\": \\"myui5jsliblatest\\", + \\"version\\": \\"1.0.0\\", + \\"devDependencies\\": { + \\"@ui5/cli\\": \\"^3.9.1\\", + \\"karma\\": \\"6.3.17\\", + \\"karma-chrome-launcher\\": \\"^3.1.1\\", + \\"karma-cli\\": \\"^2.0.0\\", + \\"karma-ui5\\": \\"^3.0.3\\", + \\"@sap/ux-ui5-tooling\\": \\"1\\" + }, + \\"scripts\\": { + \\"build\\": \\"ui5 build --clean-dest\\", + \\"start\\": \\"fiori run --open test-resources/com/sap/myui5jsliblatest/Example.html\\", + \\"testsuite\\": \\"fiori run --open test-resources/com/sap/myui5jsliblatest/qunit/testsuite.qunit.html\\", + \\"test\\": \\"karma start --browsers=ChromeHeadless --singleRun=true\\" + } +} +", + "state": "modified", + }, + "com.sap.myui5jsliblatest/src/com/sap/myui5jsliblatest/.library": Object { + "contents": " + + com.sap.myui5jsliblatest + UI5 Lib Author + \${version} + \${copyright} + myui5jsliblatest + Some description about myui5jsliblatest + + + sap.ui.core + + + +", + "state": "modified", + }, + "com.sap.myui5jsliblatest/src/com/sap/myui5jsliblatest/Example.js": Object { + "contents": "/*! + * \${copyright} + */ + +// Provides control com.sap.myui5jsliblatest.Example. +sap.ui.define([ + \\"./library\\", + \\"sap/ui/core/Control\\", + \\"./ExampleRenderer\\" +], function (library, Control, ExampleRenderer) { + \\"use strict\\"; + + // refer to library types + var ExampleColor = library.ExampleColor; + + /** + * Constructor for a new com.sap.myui5jsliblatest.Example control. + * + * @param {string} [sId] id for the new control, generated automatically if no id is given + * @param {object} [mSettings] initial settings for the new control + * + * @class + * Some class description goes here. + * @extends sap.ui.core.Control + * + * @author UI5 Lib Author + * @version \${version} + * + * @constructor + * @public + * @alias com.sap.myui5jsliblatest.Example + */ + var Example = Control.extend(\\"com.sap.myui5jsliblatest.Example\\", /** @lends com.sap.myui5jsliblatest.Example.prototype */ { + metadata: { + library: \\"com.sap.myui5jsliblatest\\", + properties: { + /** + * The text to display. + */ + text: { + type: \\"string\\", + group: \\"Data\\", + defaultValue: null + }, + /** + * The color to use (default to \\"Default\\" color). + */ + color: { + type: \\"com.sap.myui5jsliblatest.ExampleColor\\", + group: \\"Appearance\\", + defaultValue: ExampleColor.Default + } + }, + events: { + /** + * Event is fired when the user clicks the control. + */ + press: {} + } + }, + renderer: ExampleRenderer, + onclick: function() { + this.firePress(); + } + }); + return Example; + +}); +", + "state": "modified", + }, + "com.sap.myui5jsliblatest/src/com/sap/myui5jsliblatest/ExampleRenderer.js": Object { + "contents": "/*! + * \${copyright} + */ + +sap.ui.define([ + \\"sap/ui/core/Lib\\", + \\"./library\\" +], function (Lib, library) { + \\"use strict\\"; + + // refer to library types + var ExampleColor = library.ExampleColor; + + /** + * Example renderer. + * @namespace + */ + var ExampleRenderer = { + apiVersion: 2 // usage of DOM Patcher + }; + + /** + * Renders the HTML for the given control, using the provided + * {@link sap.ui.core.RenderManager}. + * + * @param {sap.ui.core.RenderManager} rm The reference to the sap.ui.core.RenderManager + * @param {sap.ui.core.Control} control The control instance to be rendered + */ + ExampleRenderer.render = function (rm, control) { + + var i18n = Lib.getResourceBundleFor(\\"com.sap.myui5jsliblatest\\"); + + rm.openStart(\\"div\\", control); + if (control.getColor() === ExampleColor.Highlight) { + rm.class(\\"myLibPrefixExampleHighlight\\"); + } else { + rm.class(\\"myLibPrefixExample\\"); + } + rm.openEnd( ); + rm.text(i18n.getText(\\"ANY_TEXT\\") + \\": \\" + control.getText()); + rm.close(\\"div\\"); + + }; + + return ExampleRenderer; + +}); +", + "state": "modified", + }, + "com.sap.myui5jsliblatest/src/com/sap/myui5jsliblatest/library.js": Object { + "contents": "/*! + * \${copyright} + */ + +/** + * Initialization Code and shared classes of library com.sap.myui5jsliblatest. + */ +sap.ui.define([ + \\"sap/ui/core/Lib\\" +], function (Lib) { + \\"use strict\\"; + + // delegate further initialization of this library to the Core + // Hint: sap.ui.getCore() must still be used to support preload with sync bootstrap! + Lib.init({ + name: \\"com.sap.myui5jsliblatest\\", + version: \\"\${version}\\", + dependencies: [ // keep in sync with the ui5.yaml and .library files + \\"sap.ui.core\\" + ], + types: [ + \\"com.sap.myui5jsliblatest.ExampleColor\\" + ], + interfaces: [], + controls: [ + \\"com.sap.myui5jsliblatest.Example\\" + ], + elements: [], + noLibraryCSS: false, // if no CSS is provided, you can disable the library.css load here + apiVersion: 2 + }); + + /** + * Some description about myui5jsliblatest + * + * @namespace + * @name com.sap.myui5jsliblatest + * @author UI5 Lib Author + * @version \${version} + * @public + */ + var thisLib = com.sap.myui5jsliblatest; + + /** + * Semantic Colors of the com.sap.myui5jsliblatest.Example. + * + * @enum {string} + * @public + */ + thisLib.ExampleColor = { + + /** + * Default color (brand color) + * @public + */ + Default : \\"Default\\", + + /** + * Highlight color + * @public + */ + Highlight : \\"Highlight\\" + + }; + + return thisLib; + +}); +", + "state": "modified", + }, + "com.sap.myui5jsliblatest/src/com/sap/myui5jsliblatest/messagebundle.properties": Object { + "contents": "# Translation file of library com.sap.myui5jsliblatest. +ANY_TEXT=AnyText +", + "state": "modified", + }, + "com.sap.myui5jsliblatest/src/com/sap/myui5jsliblatest/themes/base/Example.less": Object { + "contents": "/* Theme Parameter Toolbox: https://sdk.openui5.org/test-resources/sap/m/demokit/theming/webapp/index.html */ + +.myLibPrefixExample, +.myLibPrefixExampleHighlight { + color: @sapUiText; + background-color: @sapUiNeutralBG; + border: 1rem solid @sapUiContentForegroundBorderColor; + border-radius: 1rem; + opacity: 0.8; + padding: 2rem; + margin: 2rem 8rem; + text-align: center; + font-size: 2em; + line-height: 3em; +} + +.myLibPrefixExampleHighlight { + background-color: @sapUiSuccessBG; +} +", + "state": "modified", + }, + "com.sap.myui5jsliblatest/src/com/sap/myui5jsliblatest/themes/base/library.source.less": Object { + "contents": "@import \\"/resources/sap/ui/core/themes/base/base.less\\"; +@import \\"/resources/sap/ui/core/themes/base/global.less\\"; + +@import \\"Example.less\\"; +", + "state": "modified", + }, + "com.sap.myui5jsliblatest/src/com/sap/myui5jsliblatest/themes/sap_belize/library.source.less": Object { + "contents": "@import \\"../base/library.source.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_belize/base.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_belize/global.less\\"; +", + "state": "modified", + }, + "com.sap.myui5jsliblatest/src/com/sap/myui5jsliblatest/themes/sap_belize_hcb/library.source.less": Object { + "contents": "@import \\"../base/library.source.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_belize_hcb/base.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_belize_hcb/global.less\\"; +", + "state": "modified", + }, + "com.sap.myui5jsliblatest/src/com/sap/myui5jsliblatest/themes/sap_belize_hcw/library.source.less": Object { + "contents": "@import \\"../base/library.source.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_belize_hcw/base.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_belize_hcw/global.less\\"; +", + "state": "modified", + }, + "com.sap.myui5jsliblatest/src/com/sap/myui5jsliblatest/themes/sap_belize_plus/library.source.less": Object { + "contents": "@import \\"../sap_belize/library.source.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_belize_plus/base.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_belize_plus/global.less\\"; +", + "state": "modified", + }, + "com.sap.myui5jsliblatest/src/com/sap/myui5jsliblatest/themes/sap_fiori_3/library.source.less": Object { + "contents": "@import \\"../base/library.source.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_fiori_3/base.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_fiori_3/global.less\\"; +", + "state": "modified", + }, + "com.sap.myui5jsliblatest/src/com/sap/myui5jsliblatest/themes/sap_fiori_3_dark/library.source.less": Object { + "contents": "@import \\"../base/library.source.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_fiori_3_dark/base.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_fiori_3_dark/global.less\\"; +", + "state": "modified", + }, + "com.sap.myui5jsliblatest/src/com/sap/myui5jsliblatest/themes/sap_fiori_3_hcb/library.source.less": Object { + "contents": "@import \\"../base/library.source.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_fiori_3_hcb/base.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_fiori_3_hcb/global.less\\"; +", + "state": "modified", + }, + "com.sap.myui5jsliblatest/src/com/sap/myui5jsliblatest/themes/sap_fiori_3_hcw/library.source.less": Object { + "contents": "@import \\"../base/library.source.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_fiori_3_hcw/base.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_fiori_3_hcw/global.less\\"; +", + "state": "modified", + }, + "com.sap.myui5jsliblatest/test/com/sap/myui5jsliblatest/Example.html": Object { + "contents": " + + + + Test Page for com.sap.myui5jsliblatest.Example + + + + +

Test Page for com.sap.myui5jsliblatest.Example

+
+ + +", + "state": "modified", + }, + "com.sap.myui5jsliblatest/test/com/sap/myui5jsliblatest/Example.js": Object { + "contents": "// eslint-disable-next-line no-undef +sap.ui.define([ + \\"com/sap/myui5jsliblatest/library\\", + \\"com/sap/myui5jsliblatest/Example\\" +], function(library, Example) { + \\"use strict\\"; + + // refer to library types + var ExampleColor = library.ExampleColor; + + // create a new instance of the Example control and + // place it into the DOM element with the id \\"content\\" + new Example({ + text: \\"Example\\", + color: ExampleColor.Highlight + }).placeAt(\\"content\\"); + +}); +", + "state": "modified", + }, + "com.sap.myui5jsliblatest/test/com/sap/myui5jsliblatest/qunit/Example.qunit.js": Object { + "contents": "/*global QUnit */ +// eslint-disable-next-line no-undef +sap.ui.define([ + \\"sap/ui/qunit/QUnitUtils\\", + \\"sap/ui/qunit/utils/createAndAppendDiv\\", + \\"com/sap/myui5jsliblatest/library\\", + \\"com/sap/myui5jsliblatest/Example\\" +], function(qutils, createAndAppendDiv, library, Example) { + \\"use strict\\"; + + // refer to library types + var ExampleColor = library.ExampleColor; + + // prepare DOM + createAndAppendDiv(\\"uiArea1\\"); + + // module for basic checks + QUnit.module(\\"Example Tests\\"); + + // example sync test + QUnit.test(\\"Sync\\", function(assert) { + assert.expect(1); + assert.ok(true, \\"ok\\"); + }); + + // example async test + QUnit.test(\\"Async\\", function(assert) { + assert.expect(1); + return new Promise(function(resolve, reject) { + assert.ok(true, \\"ok\\"); + resolve(); + }); + }) + + // module for basic checks + QUnit.module(\\"Basic Control Checks\\"); + + // some basic control checks + QUnit.test(\\"Test get properties\\", function(assert) { + assert.expect(2); + var oExample = new Example({ + text: \\"Example\\" + }); + assert.equal(oExample.getText(), \\"Example\\", \\"Check text equals 'Example'\\"); + assert.equal(oExample.getColor(), ExampleColor.Default, \\"Check color equals 'Default'\\"); + }); + + // some basic eventing check + QUnit.test(\\"Test click event\\", function(assert) { + assert.expect(1); + var oExample = new Example(\\"example\\", { + text: \\"Example\\", + press: function() { + assert.ok(true, \\"Event has been fired!\\") + } + }).placeAt(\\"uiArea1\\"); + return new Promise(function(resolve, reject) { + setTimeout(function() { + qutils.triggerMouseEvent(\\"example\\", \\"click\\", 1, 1); + resolve(); + }, 100); + }); + }); + +}); +", + "state": "modified", + }, + "com.sap.myui5jsliblatest/test/com/sap/myui5jsliblatest/qunit/testsuite.qunit.html": Object { + "contents": " + + + + + + QUnit TestSuite for com.sap.myui5jsliblatest + + + + + +", + "state": "modified", + }, + "com.sap.myui5jsliblatest/test/com/sap/myui5jsliblatest/qunit/testsuite.qunit.js": Object { + "contents": "// eslint-disable-next-line no-undef +sap.ui.define(function() { + \\"use strict\\"; + + return { + name: \\"QUnit TestSuite for com.sap.myui5jsliblatest\\", + defaults: { + bootCore: true, + ui5: { + libs: \\"sap.ui.core,com.sap.myui5jsliblatest\\", + theme: \\"sap_fiori_3\\", + noConflict: true, + preload: \\"auto\\" + }, + qunit: { + version: 2, + reorder: false + }, + sinon: { + version: 4, + qunitBridge: true, + useFakeTimers: false + }, + module: \\"./{name}.qunit\\" + }, + tests: { + // test file for the Example control + Example: { + title: \\"QUnit Test for Example\\", + _alternativeTitle: \\"QUnit tests: com.sap.myui5jsliblatest.Example\\" + } + } + }; + +}); +", + "state": "modified", + }, + "com.sap.myui5jsliblatest/ui5.yaml": Object { + "contents": "specVersion: '2.2' +metadata: + name: \\"myui5jsliblatest\\" +type: library +framework: + name: SAPUI5 + version: + libraries: + - name: sap.ui.core + - name: themelib_sap_fiori_3 +server: + customMiddleware: + - name: fiori-tools-appreload + afterMiddleware: compression + configuration: + path: test + port: 35729 + delay: 300", + "state": "modified", + }, +} +`; + exports[`Reuse lib templates Generate files for config: lib-t-1.113.0 1`] = ` Object { - "com.sap.myui5tslib113/.eslintrc": Object { + "com.sap.myui5tslib113/.eslintrc": Object { + "contents": "{ + \\"extends\\": \\"plugin:@sap-ux/eslint-plugin-fiori-tools/defaultTS\\", + \\"root\\": true +}", + "state": "modified", + }, + "com.sap.myui5tslib113/.gitignore": Object { + "contents": "node_modules/ +dist/ +.scp/ +Makefile*.mta +mta_archives +mta-* +resources +archive.zip +.*_mta_build_tmp", + "state": "modified", + }, + "com.sap.myui5tslib113/karma.conf.js": Object { + "contents": "// karma-ui5 usage: https://github.com/SAP/karma-ui5 +module.exports = function (config) { + config.set({ + frameworks: [\\"ui5\\"], + browsers: [\\"Chrome\\"] + }); +};", + "state": "modified", + }, + "com.sap.myui5tslib113/package.json": Object { + "contents": "{ + \\"name\\": \\"myui5tslib113\\", + \\"version\\": \\"1.0.0\\", + \\"devDependencies\\": { + \\"@ui5/cli\\": \\"^3.9.1\\", + \\"karma\\": \\"^6.3.17\\", + \\"karma-chrome-launcher\\": \\"^3.1.1\\", + \\"karma-cli\\": \\"^2.0.0\\", + \\"karma-ui5\\": \\"^3.0.3\\", + \\"@sap/ux-ui5-tooling\\": \\"1\\", + \\"@sapui5/types\\": \\"1.113.0\\", + \\"@typescript-eslint/eslint-plugin\\": \\"^7.1.1\\", + \\"@typescript-eslint/parser\\": \\"^7.1.1\\", + \\"@ui5/ts-interface-generator\\": \\"^0.8.1\\", + \\"eslint\\": \\"^8.57.0\\", + \\"npm-run-all\\": \\"^4.1.5\\", + \\"typescript\\": \\"^5.1.6\\", + \\"ui5-tooling-transpile\\": \\"^3.3.7\\", + \\"@sap-ux/eslint-plugin-fiori-tools\\": \\"^0.4.0\\" + }, + \\"scripts\\": { + \\"build\\": \\"run-p -l build-app build-interface\\", + \\"start\\": \\"fiori run --open \\\\\\"test-resources/com/sap/myui5tslib113/Example.html\\\\\\"\\", + \\"testsuite\\": \\"fiori run --open test-resources/com/sap/myui5tslib113/qunit/testsuite.qunit.html\\", + \\"test\\": \\"karma start --browsers=ChromeHeadless --singleRun=true\\", + \\"build-app\\": \\"ui5 build --config=ui5.yaml --clean-dest --dest dist\\", + \\"build-interface\\": \\"npx @ui5/ts-interface-generator\\", + \\"ts-typecheck\\": \\"tsc --noEmit\\", + \\"lint\\": \\"eslint .\\" + } +} +", + "state": "modified", + }, + "com.sap.myui5tslib113/src/com/sap/myui5tslib113/.library": Object { + "contents": " + + com.sap.myui5tslib113 + UX Tools + \${version} + \${copyright} + myui5tslib113 + Some description about myui5tslib113 + + + sap.ui.core + + + +", + "state": "modified", + }, + "com.sap.myui5tslib113/src/com/sap/myui5tslib113/Example.gen.d.ts": Object { + "contents": "import { ExampleColor } from \\"./library\\"; +import Event from \\"sap/ui/base/Event\\"; +import { PropertyBindingInfo } from \\"sap/ui/base/ManagedObject\\"; +import { $ControlSettings } from \\"sap/ui/core/Control\\"; + +declare module \\"./Example\\" { + + /** + * Interface defining the settings object used in constructor calls + */ + interface $ExampleSettings extends $ControlSettings { + text?: string | PropertyBindingInfo; + color?: ExampleColor | PropertyBindingInfo | \`{\${string}}\`; + press?: (event: Event) => void; + } + + export default interface Example { + + // property: text + getText(): string; + setText(text: string): this; + + // property: color + getColor(): ExampleColor; + setColor(color: ExampleColor): this; + + // event: press + attachPress(fn: (event: Event) => void, listener?: object): this; + attachPress(data: CustomDataType, fn: (event: Event, data: CustomDataType) => void, listener?: object): this; + detachPress(fn: (event: Event) => void, listener?: object): this; + firePress(parameters?: object): this; + } +}", + "state": "modified", + }, + "com.sap.myui5tslib113/src/com/sap/myui5tslib113/Example.ts": Object { + "contents": "/*! + * \${copyright} + */ + +// Provides control com.sap.myui5tslib113.Example. +import Control from \\"sap/ui/core/Control\\"; +import ExampleRenderer from \\"./ExampleRenderer\\"; +import { ExampleColor } from \\"./library\\"; + + + +/** + * Constructor for a new com.sap.myui5tslib113.Example control. + * + * Some class description goes here. + * @extends Control + * + * @author OpenUI5 Team + * @version \${version} + * + * @constructor + * @public + * @name com.sap.myui5tslib113.Example + */ +export default class Example extends Control { + + // The following three lines were generated and should remain as-is to make TypeScript aware of the constructor signatures + constructor(id?: string | $ExampleSettings); + constructor(id?: string, settings?: $ExampleSettings); + constructor(id?: string, settings?: $ExampleSettings) { super(id, settings); } + + static readonly metadata = { + library: \\"com.sap.myui5tslib113\\", + properties: { + /** + * The text to display. + */ + text: { + type: \\"string\\", + group: \\"Data\\", + defaultValue: null + }, + /** + * The color to use (default to \\"Default\\" color). + */ + color: { + type: \\"com.sap.myui5tslib113.ExampleColor\\", + group: \\"Appearance\\", + defaultValue: ExampleColor.Default + } + }, + events: { + /** + * Event is fired when the user clicks the control. + */ + press: {} + } + }; + + static renderer = ExampleRenderer; + + onclick = () => { + this.firePress(); + }; +}", + "state": "modified", + }, + "com.sap.myui5tslib113/src/com/sap/myui5tslib113/ExampleRenderer.ts": Object { + "contents": "/*! + * \${copyright} + */ + +import ResourceBundle from \\"sap/base/i18n/ResourceBundle\\"; +import Core from \\"sap/ui/core/Core\\"; +import RenderManager from \\"sap/ui/core/RenderManager\\"; +import Example from \\"./Example\\"; +import { ExampleColor } from \\"./library\\"; + +/** + * Example renderer. + * @namespace + */ +const ExampleRenderer = { + apiVersion: 2, // usage of DOM Patcher + + /** + * Renders the HTML for the given control, using the provided {@link RenderManager}. + * + * @param {RenderManager} rm The reference to the sap.ui.core.RenderManager + * @param {Example} control The control instance to be rendered + */ + render: function (rm: RenderManager, control: Example) { + + const i18n = Core.getLibraryResourceBundle(\\"com.sap.myui5tslib113\\") as ResourceBundle; + + rm.openStart(\\"div\\", control); + if (control.getColor() === ExampleColor.Highlight) { + rm.class(\\"myLibPrefixExampleHighlight\\"); + } else { + rm.class(\\"myLibPrefixExample\\"); + } + rm.openEnd( ); + rm.text(i18n.getText(\\"ANY_TEXT\\") + \\": \\" + control.getText()); + rm.close(\\"div\\"); + } + +}; + +export default ExampleRenderer;", + "state": "modified", + }, + "com.sap.myui5tslib113/src/com/sap/myui5tslib113/library.ts": Object { + "contents": "/*! + * \${copyright} + */ + +import ObjectPath from \\"sap/base/util/ObjectPath\\"; + +/** + * Initialization Code and shared classes of library com.sap.myui5tslib113. + */ + +// delegate further initialization of this library to the Core +// Hint: sap.ui.getCore() must still be used here to support preload with sync bootstrap! +sap.ui.getCore().initLibrary({ + name: \\"com.sap.myui5tslib113\\", + version: \\"\${version}\\", + dependencies: [ // keep in sync with the ui5.yaml and .library files + \\"sap.ui.core\\" + ], + types: [ + \\"com.sap.myui5tslib113.ExampleColor\\" + ], + interfaces: [], + controls: [ + \\"com.sap.myui5tslib113.Example\\" + ], + elements: [], + noLibraryCSS: false // if no CSS is provided, you can disable the library.css load here +}); + +// get the library object from global object space because all enums must be attached to it to be usable as UI5 types +// FIXME: this line is planned to become obsolete and may need to be removed later +const thisLib : {[key: string]: unknown} = ObjectPath.get(\\"com.sap.myui5tslib113\\") as {[key: string]: unknown}; + +/** + * Semantic Colors of the com.myorg.myUI5Library.Example control. + * + * @enum {string} + * @public + */ +export enum ExampleColor { + + /** + * Default color (brand color) + * @public + */ + Default = \\"Default\\", + + /** + * Highlight color + * @public + */ + Highlight = \\"Highlight\\" + +} +// FIXME: this line is planned to become obsolete and may need to be removed later +thisLib.ExampleColor = ExampleColor; // add the enum to the library; this is important because UI5 otherwise cannot identify the type and will skip type checking for properties of this type", + "state": "modified", + }, + "com.sap.myui5tslib113/src/com/sap/myui5tslib113/messagebundle.properties": Object { + "contents": "# Translation file of library com.sap.myui5tslib113. +ANY_TEXT=AnyText +", + "state": "modified", + }, + "com.sap.myui5tslib113/src/com/sap/myui5tslib113/themes/base/Example.less": Object { + "contents": "/* Theme Parameter Toolbox: https://sdk.openui5.org/test-resources/sap/m/demokit/theming/webapp/index.html */ + +.myLibPrefixExample, +.myLibPrefixExampleHighlight { + color: @sapUiText; + background-color: @sapUiNeutralBG; + border: 1rem solid @sapUiContentForegroundBorderColor; + border-radius: 1rem; + opacity: 0.8; + padding: 2rem; + margin: 2rem 8rem; + text-align: center; + font-size: 2em; + line-height: 3em; +} + +.myLibPrefixExampleHighlight { + background-color: @sapUiSuccessBG; +} +", + "state": "modified", + }, + "com.sap.myui5tslib113/src/com/sap/myui5tslib113/themes/base/library.source.less": Object { + "contents": "@import \\"/resources/sap/ui/core/themes/base/base.less\\"; +@import \\"/resources/sap/ui/core/themes/base/global.less\\"; + +@import \\"Example.less\\"; +", + "state": "modified", + }, + "com.sap.myui5tslib113/src/com/sap/myui5tslib113/themes/sap_belize/library.source.less": Object { + "contents": "@import \\"../base/library.source.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_belize/base.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_belize/global.less\\"; +", + "state": "modified", + }, + "com.sap.myui5tslib113/src/com/sap/myui5tslib113/themes/sap_belize_hcb/library.source.less": Object { + "contents": "@import \\"../base/library.source.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_belize_hcb/base.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_belize_hcb/global.less\\"; +", + "state": "modified", + }, + "com.sap.myui5tslib113/src/com/sap/myui5tslib113/themes/sap_belize_hcw/library.source.less": Object { + "contents": "@import \\"../base/library.source.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_belize_hcw/base.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_belize_hcw/global.less\\"; +", + "state": "modified", + }, + "com.sap.myui5tslib113/src/com/sap/myui5tslib113/themes/sap_belize_plus/library.source.less": Object { + "contents": "@import \\"../sap_belize/library.source.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_belize_plus/base.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_belize_plus/global.less\\"; +", + "state": "modified", + }, + "com.sap.myui5tslib113/src/com/sap/myui5tslib113/themes/sap_fiori_3/library.source.less": Object { + "contents": "@import \\"../base/library.source.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_fiori_3/base.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_fiori_3/global.less\\"; +", + "state": "modified", + }, + "com.sap.myui5tslib113/src/com/sap/myui5tslib113/themes/sap_fiori_3_dark/library.source.less": Object { + "contents": "@import \\"../base/library.source.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_fiori_3_dark/base.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_fiori_3_dark/global.less\\"; +", + "state": "modified", + }, + "com.sap.myui5tslib113/src/com/sap/myui5tslib113/themes/sap_fiori_3_hcb/library.source.less": Object { + "contents": "@import \\"../base/library.source.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_fiori_3_hcb/base.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_fiori_3_hcb/global.less\\"; +", + "state": "modified", + }, + "com.sap.myui5tslib113/src/com/sap/myui5tslib113/themes/sap_fiori_3_hcw/library.source.less": Object { + "contents": "@import \\"../base/library.source.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_fiori_3_hcw/base.less\\"; +@import \\"/resources/sap/ui/core/themes/sap_fiori_3_hcw/global.less\\"; +", + "state": "modified", + }, + "com.sap.myui5tslib113/test/com/sap/myui5tslib113/Example.html": Object { + "contents": " + + + + Test Page for com.sap.myui5tslib113.Example + + + + +

Test Page for com.sap.myui5tslib113.Example

+
+ + +", + "state": "modified", + }, + "com.sap.myui5tslib113/test/com/sap/myui5tslib113/Example.ts": Object { + "contents": "import { ExampleColor } from 'com/sap/myui5tslib113/library'; +import Example from 'com/sap/myui5tslib113/Example'; + +// Create a new instance of the Example control and +// place it into the DOM element with the id \\"content\\" +new Example({ + text: 'Example', + color: ExampleColor.Highlight, +}).placeAt('content'); +", + "state": "modified", + }, + "com.sap.myui5tslib113/test/com/sap/myui5tslib113/qunit/Example.qunit.ts": Object { + "contents": "// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-nocheck + +/*global QUnit */ +// eslint-disable-next-line no-undef +sap.ui.define([ + \\"sap/ui/qunit/QUnitUtils\\", + \\"sap/ui/qunit/utils/createAndAppendDiv\\", + \\"com/sap/myui5tslib113/library\\", + \\"com/sap/myui5tslib113/Example\\" +], function(qutils, createAndAppendDiv, library, Example) { + \\"use strict\\"; + + // refer to library types + const ExampleColor = library.ExampleColor; + + // prepare DOM + createAndAppendDiv(\\"uiArea1\\"); + + // module for basic checks + QUnit.module(\\"Example Tests\\"); + + // example sync test + QUnit.test(\\"Sync\\", function(assert) { + assert.expect(1); + assert.ok(true, \\"ok\\"); + }); + + // example async test + QUnit.test(\\"Async\\", function(assert) { + assert.expect(1); + return new Promise(function(resolve, reject) { + assert.ok(true, \\"ok\\"); + resolve(); + }); + }) + + // module for basic checks + QUnit.module(\\"Basic Control Checks\\"); + + // some basic control checks + QUnit.test(\\"Test get properties\\", function(assert) { + assert.expect(2); + const oExample = new Example({ + text: \\"Example\\" + }); + assert.equal(oExample.getText(), \\"Example\\", \\"Check text equals 'Example'\\"); + assert.equal(oExample.getColor(), ExampleColor.Default, \\"Check color equals 'Default'\\"); + }); + + // some basic eventing check + QUnit.test(\\"Test click event\\", function(assert) { + assert.expect(1); + const oExample = new Example(\\"example\\", { + text: \\"Example\\", + press: function() { + assert.ok(true, \\"Event has been fired!\\") + } + }).placeAt(\\"uiArea1\\"); + return new Promise(function(resolve, reject) { + setTimeout(function() { + qutils.triggerMouseEvent(\\"example\\", \\"click\\", 1, 1); + resolve(); + }, 100); + }); + }); + +}); +", + "state": "modified", + }, + "com.sap.myui5tslib113/test/com/sap/myui5tslib113/qunit/testsuite.qunit.html": Object { + "contents": " + + + + + + QUnit TestSuite for com.sap.myui5tslib113 + + + + + +", + "state": "modified", + }, + "com.sap.myui5tslib113/test/com/sap/myui5tslib113/qunit/testsuite.qunit.ts": Object { + "contents": "// eslint-disable-next-line no-undef +sap.ui.define(function() { + \\"use strict\\"; + + return { + name: \\"QUnit TestSuite for com.sap.myui5tslib113\\", + defaults: { + bootCore: true, + ui5: { + libs: \\"sap.ui.core,com.sap.myui5tslib113\\", + theme: \\"sap_fiori_3\\", + noConflict: true, + preload: \\"auto\\" + }, + qunit: { + version: 2, + reorder: false + }, + sinon: { + version: 4, + qunitBridge: true, + useFakeTimers: false + }, + module: \\"./{name}.qunit\\" + }, + tests: { + // test file for the Example control + Example: { + title: \\"QUnit Test for Example\\", + _alternativeTitle: \\"QUnit tests: com.sap.myui5tslib113.Example\\" + } + } + }; + +}); +", + "state": "modified", + }, + "com.sap.myui5tslib113/tsconfig.json": Object { + "contents": "{ + \\"compilerOptions\\": { + \\"target\\": \\"es2022\\", + \\"module\\": \\"es2022\\", + \\"moduleResolution\\": \\"node\\", + \\"skipLibCheck\\": true, + \\"allowJs\\": true, + \\"strict\\": true, + \\"strictPropertyInitialization\\": false, + \\"rootDir\\": \\"./\\", + \\"outDir\\": \\"./dist\\", + \\"baseUrl\\": \\"./\\", + \\"typeRoots\\": [ + \\"./node_modules/@types\\", + \\"./node_modules/@sapui5/types\\" + ], + \\"paths\\": { + \\"com/sap/myui5tslib113/*\\": [ + \\"./src/com/sap/myui5tslib113/*\\" + ] + } + }, + \\"include\\": [ + \\"./src/**/*\\", + \\"./test/**/*\\" + ] +}", + "state": "modified", + }, + "com.sap.myui5tslib113/ui5.yaml": Object { + "contents": "specVersion: '2.2' +metadata: + name: \\"myui5tslib113\\" +type: library +framework: + name: SAPUI5 + version: 1.113.0 + libraries: + - name: sap.ui.core + - name: themelib_sap_belize + - name: themelib_sap_fiori_3 +server: + customMiddleware: + - name: fiori-tools-appreload + afterMiddleware: compression + configuration: + path: src + port: 35729 + delay: 300 + - name: ui5-tooling-transpile-middleware + afterMiddleware: compression + configuration: + debug: true + transformModulesToUI5: + overridesToOverride: true + excludePatterns: + - /Component-preload.js +builder: + customTasks: + - name: ui5-tooling-transpile-task + afterTask: replaceVersion + configuration: + debug: true + transformModulesToUI5: + overridesToOverride: true +", + "state": "modified", + }, +} +`; + +exports[`Reuse lib templates Generate files for config: lib-ts 1`] = ` +Object { + "com.sap.myui5tslib/.eslintrc": Object { "contents": "{ \\"extends\\": \\"plugin:@sap-ux/eslint-plugin-fiori-tools/defaultTS\\", \\"root\\": true }", "state": "modified", }, - "com.sap.myui5tslib113/.gitignore": Object { + "com.sap.myui5tslib/.gitignore": Object { "contents": "node_modules/ dist/ .scp/ @@ -568,7 +2285,7 @@ archive.zip .*_mta_build_tmp", "state": "modified", }, - "com.sap.myui5tslib113/karma.conf.js": Object { + "com.sap.myui5tslib/karma.conf.js": Object { "contents": "// karma-ui5 usage: https://github.com/SAP/karma-ui5 module.exports = function (config) { config.set({ @@ -578,9 +2295,9 @@ module.exports = function (config) { };", "state": "modified", }, - "com.sap.myui5tslib113/package.json": Object { + "com.sap.myui5tslib/package.json": Object { "contents": "{ - \\"name\\": \\"myui5tslib113\\", + \\"name\\": \\"myui5tslib\\", \\"version\\": \\"1.0.0\\", \\"devDependencies\\": { \\"@ui5/cli\\": \\"^3.9.1\\", @@ -589,7 +2306,7 @@ module.exports = function (config) { \\"karma-cli\\": \\"^2.0.0\\", \\"karma-ui5\\": \\"^3.0.3\\", \\"@sap/ux-ui5-tooling\\": \\"1\\", - \\"@sapui5/types\\": \\"1.113.0\\", + \\"@sapui5/ts-types-esm\\": \\"1.102.19\\", \\"@typescript-eslint/eslint-plugin\\": \\"^7.1.1\\", \\"@typescript-eslint/parser\\": \\"^7.1.1\\", \\"@ui5/ts-interface-generator\\": \\"^0.8.1\\", @@ -601,8 +2318,8 @@ module.exports = function (config) { }, \\"scripts\\": { \\"build\\": \\"run-p -l build-app build-interface\\", - \\"start\\": \\"fiori run --open \\\\\\"test-resources/com/sap/myui5tslib113/Example.html\\\\\\"\\", - \\"testsuite\\": \\"fiori run --open test-resources/com/sap/myui5tslib113/qunit/testsuite.qunit.html\\", + \\"start\\": \\"fiori run --open \\\\\\"test-resources/com/sap/myui5tslib/Example.html\\\\\\"\\", + \\"testsuite\\": \\"fiori run --open test-resources/com/sap/myui5tslib/qunit/testsuite.qunit.html\\", \\"test\\": \\"karma start --browsers=ChromeHeadless --singleRun=true\\", \\"build-app\\": \\"ui5 build --config=ui5.yaml --clean-dest --dest dist\\", \\"build-interface\\": \\"npx @ui5/ts-interface-generator\\", @@ -613,15 +2330,15 @@ module.exports = function (config) { ", "state": "modified", }, - "com.sap.myui5tslib113/src/com/sap/myui5tslib113/.library": Object { + "com.sap.myui5tslib/src/com/sap/myui5tslib/.library": Object { "contents": " - com.sap.myui5tslib113 - UX Tools + com.sap.myui5tslib + UI5 Lib Author \${version} \${copyright} - myui5tslib113 - Some description about myui5tslib113 + myui5tslib + Some description about myui5tslib sap.ui.core @@ -631,7 +2348,7 @@ module.exports = function (config) { ", "state": "modified", }, - "com.sap.myui5tslib113/src/com/sap/myui5tslib113/Example.gen.d.ts": Object { + "com.sap.myui5tslib/src/com/sap/myui5tslib/Example.gen.d.ts": Object { "contents": "import { ExampleColor } from \\"./library\\"; import Event from \\"sap/ui/base/Event\\"; import { PropertyBindingInfo } from \\"sap/ui/base/ManagedObject\\"; @@ -667,12 +2384,12 @@ declare module \\"./Example\\" { }", "state": "modified", }, - "com.sap.myui5tslib113/src/com/sap/myui5tslib113/Example.ts": Object { + "com.sap.myui5tslib/src/com/sap/myui5tslib/Example.ts": Object { "contents": "/*! * \${copyright} */ -// Provides control com.sap.myui5tslib113.Example. +// Provides control com.sap.myui5tslib.Example. import Control from \\"sap/ui/core/Control\\"; import ExampleRenderer from \\"./ExampleRenderer\\"; import { ExampleColor } from \\"./library\\"; @@ -680,7 +2397,7 @@ import { ExampleColor } from \\"./library\\"; /** - * Constructor for a new com.sap.myui5tslib113.Example control. + * Constructor for a new com.sap.myui5tslib.Example control. * * Some class description goes here. * @extends Control @@ -690,7 +2407,7 @@ import { ExampleColor } from \\"./library\\"; * * @constructor * @public - * @name com.sap.myui5tslib113.Example + * @name com.sap.myui5tslib.Example */ export default class Example extends Control { @@ -700,7 +2417,7 @@ export default class Example extends Control { constructor(id?: string, settings?: $ExampleSettings) { super(id, settings); } static readonly metadata = { - library: \\"com.sap.myui5tslib113\\", + library: \\"com.sap.myui5tslib\\", properties: { /** * The text to display. @@ -714,7 +2431,7 @@ export default class Example extends Control { * The color to use (default to \\"Default\\" color). */ color: { - type: \\"com.sap.myui5tslib113.ExampleColor\\", + type: \\"com.sap.myui5tslib.ExampleColor\\", group: \\"Appearance\\", defaultValue: ExampleColor.Default } @@ -735,7 +2452,7 @@ export default class Example extends Control { }", "state": "modified", }, - "com.sap.myui5tslib113/src/com/sap/myui5tslib113/ExampleRenderer.ts": Object { + "com.sap.myui5tslib/src/com/sap/myui5tslib/ExampleRenderer.ts": Object { "contents": "/*! * \${copyright} */ @@ -761,7 +2478,7 @@ const ExampleRenderer = { */ render: function (rm: RenderManager, control: Example) { - const i18n = Core.getLibraryResourceBundle(\\"com.sap.myui5tslib113\\") as ResourceBundle; + const i18n = Core.getLibraryResourceBundle(\\"com.sap.myui5tslib\\") as ResourceBundle; rm.openStart(\\"div\\", control); if (control.getColor() === ExampleColor.Highlight) { @@ -779,7 +2496,7 @@ const ExampleRenderer = { export default ExampleRenderer;", "state": "modified", }, - "com.sap.myui5tslib113/src/com/sap/myui5tslib113/library.ts": Object { + "com.sap.myui5tslib/src/com/sap/myui5tslib/library.ts": Object { "contents": "/*! * \${copyright} */ @@ -787,23 +2504,23 @@ export default ExampleRenderer;", import ObjectPath from \\"sap/base/util/ObjectPath\\"; /** - * Initialization Code and shared classes of library com.sap.myui5tslib113. + * Initialization Code and shared classes of library com.sap.myui5tslib. */ // delegate further initialization of this library to the Core // Hint: sap.ui.getCore() must still be used here to support preload with sync bootstrap! sap.ui.getCore().initLibrary({ - name: \\"com.sap.myui5tslib113\\", + name: \\"com.sap.myui5tslib\\", version: \\"\${version}\\", dependencies: [ // keep in sync with the ui5.yaml and .library files \\"sap.ui.core\\" ], types: [ - \\"com.sap.myui5tslib113.ExampleColor\\" + \\"com.sap.myui5tslib.ExampleColor\\" ], interfaces: [], controls: [ - \\"com.sap.myui5tslib113.Example\\" + \\"com.sap.myui5tslib.Example\\" ], elements: [], noLibraryCSS: false // if no CSS is provided, you can disable the library.css load here @@ -811,7 +2528,7 @@ sap.ui.getCore().initLibrary({ // get the library object from global object space because all enums must be attached to it to be usable as UI5 types // FIXME: this line is planned to become obsolete and may need to be removed later -const thisLib : {[key: string]: unknown} = ObjectPath.get(\\"com.sap.myui5tslib113\\") as {[key: string]: unknown}; +const thisLib : {[key: string]: unknown} = ObjectPath.get(\\"com.sap.myui5tslib\\") as {[key: string]: unknown}; /** * Semantic Colors of the com.myorg.myUI5Library.Example control. @@ -838,13 +2555,13 @@ export enum ExampleColor { thisLib.ExampleColor = ExampleColor; // add the enum to the library; this is important because UI5 otherwise cannot identify the type and will skip type checking for properties of this type", "state": "modified", }, - "com.sap.myui5tslib113/src/com/sap/myui5tslib113/messagebundle.properties": Object { - "contents": "# Translation file of library com.sap.myui5tslib113. + "com.sap.myui5tslib/src/com/sap/myui5tslib/messagebundle.properties": Object { + "contents": "# Translation file of library com.sap.myui5tslib. ANY_TEXT=AnyText ", "state": "modified", }, - "com.sap.myui5tslib113/src/com/sap/myui5tslib113/themes/base/Example.less": Object { + "com.sap.myui5tslib/src/com/sap/myui5tslib/themes/base/Example.less": Object { "contents": "/* Theme Parameter Toolbox: https://sdk.openui5.org/test-resources/sap/m/demokit/theming/webapp/index.html */ .myLibPrefixExample, @@ -867,7 +2584,7 @@ ANY_TEXT=AnyText ", "state": "modified", }, - "com.sap.myui5tslib113/src/com/sap/myui5tslib113/themes/base/library.source.less": Object { + "com.sap.myui5tslib/src/com/sap/myui5tslib/themes/base/library.source.less": Object { "contents": "@import \\"/resources/sap/ui/core/themes/base/base.less\\"; @import \\"/resources/sap/ui/core/themes/base/global.less\\"; @@ -875,89 +2592,89 @@ ANY_TEXT=AnyText ", "state": "modified", }, - "com.sap.myui5tslib113/src/com/sap/myui5tslib113/themes/sap_belize/library.source.less": Object { + "com.sap.myui5tslib/src/com/sap/myui5tslib/themes/sap_belize/library.source.less": Object { "contents": "@import \\"../base/library.source.less\\"; @import \\"/resources/sap/ui/core/themes/sap_belize/base.less\\"; @import \\"/resources/sap/ui/core/themes/sap_belize/global.less\\"; ", "state": "modified", }, - "com.sap.myui5tslib113/src/com/sap/myui5tslib113/themes/sap_belize_hcb/library.source.less": Object { + "com.sap.myui5tslib/src/com/sap/myui5tslib/themes/sap_belize_hcb/library.source.less": Object { "contents": "@import \\"../base/library.source.less\\"; @import \\"/resources/sap/ui/core/themes/sap_belize_hcb/base.less\\"; @import \\"/resources/sap/ui/core/themes/sap_belize_hcb/global.less\\"; ", "state": "modified", }, - "com.sap.myui5tslib113/src/com/sap/myui5tslib113/themes/sap_belize_hcw/library.source.less": Object { + "com.sap.myui5tslib/src/com/sap/myui5tslib/themes/sap_belize_hcw/library.source.less": Object { "contents": "@import \\"../base/library.source.less\\"; @import \\"/resources/sap/ui/core/themes/sap_belize_hcw/base.less\\"; @import \\"/resources/sap/ui/core/themes/sap_belize_hcw/global.less\\"; ", "state": "modified", }, - "com.sap.myui5tslib113/src/com/sap/myui5tslib113/themes/sap_belize_plus/library.source.less": Object { + "com.sap.myui5tslib/src/com/sap/myui5tslib/themes/sap_belize_plus/library.source.less": Object { "contents": "@import \\"../sap_belize/library.source.less\\"; @import \\"/resources/sap/ui/core/themes/sap_belize_plus/base.less\\"; @import \\"/resources/sap/ui/core/themes/sap_belize_plus/global.less\\"; ", "state": "modified", }, - "com.sap.myui5tslib113/src/com/sap/myui5tslib113/themes/sap_fiori_3/library.source.less": Object { + "com.sap.myui5tslib/src/com/sap/myui5tslib/themes/sap_fiori_3/library.source.less": Object { "contents": "@import \\"../base/library.source.less\\"; @import \\"/resources/sap/ui/core/themes/sap_fiori_3/base.less\\"; @import \\"/resources/sap/ui/core/themes/sap_fiori_3/global.less\\"; ", "state": "modified", }, - "com.sap.myui5tslib113/src/com/sap/myui5tslib113/themes/sap_fiori_3_dark/library.source.less": Object { + "com.sap.myui5tslib/src/com/sap/myui5tslib/themes/sap_fiori_3_dark/library.source.less": Object { "contents": "@import \\"../base/library.source.less\\"; @import \\"/resources/sap/ui/core/themes/sap_fiori_3_dark/base.less\\"; @import \\"/resources/sap/ui/core/themes/sap_fiori_3_dark/global.less\\"; ", "state": "modified", }, - "com.sap.myui5tslib113/src/com/sap/myui5tslib113/themes/sap_fiori_3_hcb/library.source.less": Object { + "com.sap.myui5tslib/src/com/sap/myui5tslib/themes/sap_fiori_3_hcb/library.source.less": Object { "contents": "@import \\"../base/library.source.less\\"; @import \\"/resources/sap/ui/core/themes/sap_fiori_3_hcb/base.less\\"; @import \\"/resources/sap/ui/core/themes/sap_fiori_3_hcb/global.less\\"; ", "state": "modified", }, - "com.sap.myui5tslib113/src/com/sap/myui5tslib113/themes/sap_fiori_3_hcw/library.source.less": Object { + "com.sap.myui5tslib/src/com/sap/myui5tslib/themes/sap_fiori_3_hcw/library.source.less": Object { "contents": "@import \\"../base/library.source.less\\"; @import \\"/resources/sap/ui/core/themes/sap_fiori_3_hcw/base.less\\"; @import \\"/resources/sap/ui/core/themes/sap_fiori_3_hcw/global.less\\"; ", "state": "modified", }, - "com.sap.myui5tslib113/test/com/sap/myui5tslib113/Example.html": Object { + "com.sap.myui5tslib/test/com/sap/myui5tslib/Example.html": Object { "contents": " - Test Page for com.sap.myui5tslib113.Example + Test Page for com.sap.myui5tslib.Example -

Test Page for com.sap.myui5tslib113.Example

+

Test Page for com.sap.myui5tslib.Example

", "state": "modified", }, - "com.sap.myui5tslib113/test/com/sap/myui5tslib113/Example.ts": Object { - "contents": "import { ExampleColor } from 'com/sap/myui5tslib113/library'; -import Example from 'com/sap/myui5tslib113/Example'; + "com.sap.myui5tslib/test/com/sap/myui5tslib/Example.ts": Object { + "contents": "import { ExampleColor } from 'com/sap/myui5tslib/library'; +import Example from 'com/sap/myui5tslib/Example'; // Create a new instance of the Example control and // place it into the DOM element with the id \\"content\\" @@ -968,7 +2685,7 @@ new Example({ ", "state": "modified", }, - "com.sap.myui5tslib113/test/com/sap/myui5tslib113/qunit/Example.qunit.ts": Object { + "com.sap.myui5tslib/test/com/sap/myui5tslib/qunit/Example.qunit.ts": Object { "contents": "// eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-nocheck @@ -977,8 +2694,8 @@ new Example({ sap.ui.define([ \\"sap/ui/qunit/QUnitUtils\\", \\"sap/ui/qunit/utils/createAndAppendDiv\\", - \\"com/sap/myui5tslib113/library\\", - \\"com/sap/myui5tslib113/Example\\" + \\"com/sap/myui5tslib/library\\", + \\"com/sap/myui5tslib/Example\\" ], function(qutils, createAndAppendDiv, library, Example) { \\"use strict\\"; @@ -1040,16 +2757,16 @@ sap.ui.define([ ", "state": "modified", }, - "com.sap.myui5tslib113/test/com/sap/myui5tslib113/qunit/testsuite.qunit.html": Object { + "com.sap.myui5tslib/test/com/sap/myui5tslib/qunit/testsuite.qunit.html": Object { "contents": " - QUnit TestSuite for com.sap.myui5tslib113 + QUnit TestSuite for com.sap.myui5tslib + data-sap-ui-testsuite=\\"test-resources/com/sap/myui5tslib/qunit/testsuite.qunit\\"> @@ -1057,17 +2774,17 @@ sap.ui.define([ ", "state": "modified", }, - "com.sap.myui5tslib113/test/com/sap/myui5tslib113/qunit/testsuite.qunit.ts": Object { + "com.sap.myui5tslib/test/com/sap/myui5tslib/qunit/testsuite.qunit.ts": Object { "contents": "// eslint-disable-next-line no-undef sap.ui.define(function() { \\"use strict\\"; return { - name: \\"QUnit TestSuite for com.sap.myui5tslib113\\", + name: \\"QUnit TestSuite for com.sap.myui5tslib\\", defaults: { bootCore: true, ui5: { - libs: \\"sap.ui.core,com.sap.myui5tslib113\\", + libs: \\"sap.ui.core,com.sap.myui5tslib\\", theme: \\"sap_fiori_3\\", noConflict: true, preload: \\"auto\\" @@ -1087,7 +2804,7 @@ sap.ui.define(function() { // test file for the Example control Example: { title: \\"QUnit Test for Example\\", - _alternativeTitle: \\"QUnit tests: com.sap.myui5tslib113.Example\\" + _alternativeTitle: \\"QUnit tests: com.sap.myui5tslib.Example\\" } } }; @@ -1096,7 +2813,7 @@ sap.ui.define(function() { ", "state": "modified", }, - "com.sap.myui5tslib113/tsconfig.json": Object { + "com.sap.myui5tslib/tsconfig.json": Object { "contents": "{ \\"compilerOptions\\": { \\"target\\": \\"es2022\\", @@ -1111,11 +2828,11 @@ sap.ui.define(function() { \\"baseUrl\\": \\"./\\", \\"typeRoots\\": [ \\"./node_modules/@types\\", - \\"./node_modules/@sapui5/types\\" + \\"./node_modules/@sapui5/ts-types-esm\\" ], \\"paths\\": { - \\"com/sap/myui5tslib113/*\\": [ - \\"./src/com/sap/myui5tslib113/*\\" + \\"com/sap/myui5tslib/*\\": [ + \\"./src/com/sap/myui5tslib/*\\" ] } }, @@ -1126,14 +2843,14 @@ sap.ui.define(function() { }", "state": "modified", }, - "com.sap.myui5tslib113/ui5.yaml": Object { + "com.sap.myui5tslib/ui5.yaml": Object { "contents": "specVersion: '2.2' metadata: - name: \\"myui5tslib113\\" + name: \\"myui5tslib\\" type: library framework: name: SAPUI5 - version: 1.113.0 + version: 1.102.19 libraries: - name: sap.ui.core - name: themelib_sap_belize @@ -1168,16 +2885,16 @@ builder: } `; -exports[`Reuse lib templates Generate files for config: lib-ts 1`] = ` +exports[`Reuse lib templates Generate files for config: lib-ts-1.121.0 1`] = ` Object { - "com.sap.myui5tslib/.eslintrc": Object { + "com.sap.myui5tslib121/.eslintrc": Object { "contents": "{ \\"extends\\": \\"plugin:@sap-ux/eslint-plugin-fiori-tools/defaultTS\\", \\"root\\": true }", "state": "modified", }, - "com.sap.myui5tslib/.gitignore": Object { + "com.sap.myui5tslib121/.gitignore": Object { "contents": "node_modules/ dist/ .scp/ @@ -1189,7 +2906,7 @@ archive.zip .*_mta_build_tmp", "state": "modified", }, - "com.sap.myui5tslib/karma.conf.js": Object { + "com.sap.myui5tslib121/karma.conf.js": Object { "contents": "// karma-ui5 usage: https://github.com/SAP/karma-ui5 module.exports = function (config) { config.set({ @@ -1199,9 +2916,9 @@ module.exports = function (config) { };", "state": "modified", }, - "com.sap.myui5tslib/package.json": Object { + "com.sap.myui5tslib121/package.json": Object { "contents": "{ - \\"name\\": \\"myui5tslib\\", + \\"name\\": \\"myui5tslib121\\", \\"version\\": \\"1.0.0\\", \\"devDependencies\\": { \\"@ui5/cli\\": \\"^3.9.1\\", @@ -1210,7 +2927,7 @@ module.exports = function (config) { \\"karma-cli\\": \\"^2.0.0\\", \\"karma-ui5\\": \\"^3.0.3\\", \\"@sap/ux-ui5-tooling\\": \\"1\\", - \\"@sapui5/ts-types-esm\\": \\"1.102.19\\", + \\"@sapui5/types\\": \\"1.121.0\\", \\"@typescript-eslint/eslint-plugin\\": \\"^7.1.1\\", \\"@typescript-eslint/parser\\": \\"^7.1.1\\", \\"@ui5/ts-interface-generator\\": \\"^0.8.1\\", @@ -1222,8 +2939,8 @@ module.exports = function (config) { }, \\"scripts\\": { \\"build\\": \\"run-p -l build-app build-interface\\", - \\"start\\": \\"fiori run --open \\\\\\"test-resources/com/sap/myui5tslib/Example.html\\\\\\"\\", - \\"testsuite\\": \\"fiori run --open test-resources/com/sap/myui5tslib/qunit/testsuite.qunit.html\\", + \\"start\\": \\"fiori run --open \\\\\\"test-resources/com/sap/myui5tslib121/Example.html\\\\\\"\\", + \\"testsuite\\": \\"fiori run --open test-resources/com/sap/myui5tslib121/qunit/testsuite.qunit.html\\", \\"test\\": \\"karma start --browsers=ChromeHeadless --singleRun=true\\", \\"build-app\\": \\"ui5 build --config=ui5.yaml --clean-dest --dest dist\\", \\"build-interface\\": \\"npx @ui5/ts-interface-generator\\", @@ -1234,15 +2951,15 @@ module.exports = function (config) { ", "state": "modified", }, - "com.sap.myui5tslib/src/com/sap/myui5tslib/.library": Object { + "com.sap.myui5tslib121/src/com/sap/myui5tslib121/.library": Object { "contents": " - com.sap.myui5tslib + com.sap.myui5tslib121 UI5 Lib Author \${version} \${copyright} - myui5tslib - Some description about myui5tslib + myui5tslib121 + Some description about myui5tslib121 sap.ui.core @@ -1252,7 +2969,7 @@ module.exports = function (config) { ", "state": "modified", }, - "com.sap.myui5tslib/src/com/sap/myui5tslib/Example.gen.d.ts": Object { + "com.sap.myui5tslib121/src/com/sap/myui5tslib121/Example.gen.d.ts": Object { "contents": "import { ExampleColor } from \\"./library\\"; import Event from \\"sap/ui/base/Event\\"; import { PropertyBindingInfo } from \\"sap/ui/base/ManagedObject\\"; @@ -1288,12 +3005,12 @@ declare module \\"./Example\\" { }", "state": "modified", }, - "com.sap.myui5tslib/src/com/sap/myui5tslib/Example.ts": Object { + "com.sap.myui5tslib121/src/com/sap/myui5tslib121/Example.ts": Object { "contents": "/*! * \${copyright} */ -// Provides control com.sap.myui5tslib.Example. +// Provides control com.sap.myui5tslib121.Example. import Control from \\"sap/ui/core/Control\\"; import ExampleRenderer from \\"./ExampleRenderer\\"; import { ExampleColor } from \\"./library\\"; @@ -1301,7 +3018,7 @@ import { ExampleColor } from \\"./library\\"; /** - * Constructor for a new com.sap.myui5tslib.Example control. + * Constructor for a new com.sap.myui5tslib121.Example control. * * Some class description goes here. * @extends Control @@ -1311,7 +3028,7 @@ import { ExampleColor } from \\"./library\\"; * * @constructor * @public - * @name com.sap.myui5tslib.Example + * @name com.sap.myui5tslib121.Example */ export default class Example extends Control { @@ -1321,7 +3038,7 @@ export default class Example extends Control { constructor(id?: string, settings?: $ExampleSettings) { super(id, settings); } static readonly metadata = { - library: \\"com.sap.myui5tslib\\", + library: \\"com.sap.myui5tslib121\\", properties: { /** * The text to display. @@ -1335,7 +3052,7 @@ export default class Example extends Control { * The color to use (default to \\"Default\\" color). */ color: { - type: \\"com.sap.myui5tslib.ExampleColor\\", + type: \\"com.sap.myui5tslib121.ExampleColor\\", group: \\"Appearance\\", defaultValue: ExampleColor.Default } @@ -1356,13 +3073,13 @@ export default class Example extends Control { }", "state": "modified", }, - "com.sap.myui5tslib/src/com/sap/myui5tslib/ExampleRenderer.ts": Object { + "com.sap.myui5tslib121/src/com/sap/myui5tslib121/ExampleRenderer.ts": Object { "contents": "/*! * \${copyright} */ import ResourceBundle from \\"sap/base/i18n/ResourceBundle\\"; -import Core from \\"sap/ui/core/Core\\"; +import Lib from \\"sap/ui/core/Lib\\"; import RenderManager from \\"sap/ui/core/RenderManager\\"; import Example from \\"./Example\\"; import { ExampleColor } from \\"./library\\"; @@ -1382,7 +3099,7 @@ const ExampleRenderer = { */ render: function (rm: RenderManager, control: Example) { - const i18n = Core.getLibraryResourceBundle(\\"com.sap.myui5tslib\\") as ResourceBundle; + const i18n = Lib.getResourceBundleFor(\\"com.sap.myui5tslib121\\") as ResourceBundle; rm.openStart(\\"div\\", control); if (control.getColor() === ExampleColor.Highlight) { @@ -1400,39 +3117,41 @@ const ExampleRenderer = { export default ExampleRenderer;", "state": "modified", }, - "com.sap.myui5tslib/src/com/sap/myui5tslib/library.ts": Object { + "com.sap.myui5tslib121/src/com/sap/myui5tslib121/library.ts": Object { "contents": "/*! * \${copyright} */ import ObjectPath from \\"sap/base/util/ObjectPath\\"; +import Lib from \\"sap/ui/core/Lib\\"; /** - * Initialization Code and shared classes of library com.sap.myui5tslib. + * Initialization Code and shared classes of library com.sap.myui5tslib121. */ // delegate further initialization of this library to the Core // Hint: sap.ui.getCore() must still be used here to support preload with sync bootstrap! -sap.ui.getCore().initLibrary({ - name: \\"com.sap.myui5tslib\\", +Lib.init({ + name: \\"com.sap.myui5tslib121\\", version: \\"\${version}\\", dependencies: [ // keep in sync with the ui5.yaml and .library files \\"sap.ui.core\\" ], types: [ - \\"com.sap.myui5tslib.ExampleColor\\" + \\"com.sap.myui5tslib121.ExampleColor\\" ], interfaces: [], controls: [ - \\"com.sap.myui5tslib.Example\\" + \\"com.sap.myui5tslib121.Example\\" ], elements: [], - noLibraryCSS: false // if no CSS is provided, you can disable the library.css load here + noLibraryCSS: false, // if no CSS is provided, you can disable the library.css load here + apiVersion: 2, }); // get the library object from global object space because all enums must be attached to it to be usable as UI5 types // FIXME: this line is planned to become obsolete and may need to be removed later -const thisLib : {[key: string]: unknown} = ObjectPath.get(\\"com.sap.myui5tslib\\") as {[key: string]: unknown}; +const thisLib : {[key: string]: unknown} = ObjectPath.get(\\"com.sap.myui5tslib121\\") as {[key: string]: unknown}; /** * Semantic Colors of the com.myorg.myUI5Library.Example control. @@ -1459,13 +3178,13 @@ export enum ExampleColor { thisLib.ExampleColor = ExampleColor; // add the enum to the library; this is important because UI5 otherwise cannot identify the type and will skip type checking for properties of this type", "state": "modified", }, - "com.sap.myui5tslib/src/com/sap/myui5tslib/messagebundle.properties": Object { - "contents": "# Translation file of library com.sap.myui5tslib. + "com.sap.myui5tslib121/src/com/sap/myui5tslib121/messagebundle.properties": Object { + "contents": "# Translation file of library com.sap.myui5tslib121. ANY_TEXT=AnyText ", "state": "modified", }, - "com.sap.myui5tslib/src/com/sap/myui5tslib/themes/base/Example.less": Object { + "com.sap.myui5tslib121/src/com/sap/myui5tslib121/themes/base/Example.less": Object { "contents": "/* Theme Parameter Toolbox: https://sdk.openui5.org/test-resources/sap/m/demokit/theming/webapp/index.html */ .myLibPrefixExample, @@ -1488,7 +3207,7 @@ ANY_TEXT=AnyText ", "state": "modified", }, - "com.sap.myui5tslib/src/com/sap/myui5tslib/themes/base/library.source.less": Object { + "com.sap.myui5tslib121/src/com/sap/myui5tslib121/themes/base/library.source.less": Object { "contents": "@import \\"/resources/sap/ui/core/themes/base/base.less\\"; @import \\"/resources/sap/ui/core/themes/base/global.less\\"; @@ -1496,89 +3215,90 @@ ANY_TEXT=AnyText ", "state": "modified", }, - "com.sap.myui5tslib/src/com/sap/myui5tslib/themes/sap_belize/library.source.less": Object { + "com.sap.myui5tslib121/src/com/sap/myui5tslib121/themes/sap_belize/library.source.less": Object { "contents": "@import \\"../base/library.source.less\\"; @import \\"/resources/sap/ui/core/themes/sap_belize/base.less\\"; @import \\"/resources/sap/ui/core/themes/sap_belize/global.less\\"; ", "state": "modified", }, - "com.sap.myui5tslib/src/com/sap/myui5tslib/themes/sap_belize_hcb/library.source.less": Object { + "com.sap.myui5tslib121/src/com/sap/myui5tslib121/themes/sap_belize_hcb/library.source.less": Object { "contents": "@import \\"../base/library.source.less\\"; @import \\"/resources/sap/ui/core/themes/sap_belize_hcb/base.less\\"; @import \\"/resources/sap/ui/core/themes/sap_belize_hcb/global.less\\"; ", "state": "modified", }, - "com.sap.myui5tslib/src/com/sap/myui5tslib/themes/sap_belize_hcw/library.source.less": Object { + "com.sap.myui5tslib121/src/com/sap/myui5tslib121/themes/sap_belize_hcw/library.source.less": Object { "contents": "@import \\"../base/library.source.less\\"; @import \\"/resources/sap/ui/core/themes/sap_belize_hcw/base.less\\"; @import \\"/resources/sap/ui/core/themes/sap_belize_hcw/global.less\\"; ", "state": "modified", }, - "com.sap.myui5tslib/src/com/sap/myui5tslib/themes/sap_belize_plus/library.source.less": Object { + "com.sap.myui5tslib121/src/com/sap/myui5tslib121/themes/sap_belize_plus/library.source.less": Object { "contents": "@import \\"../sap_belize/library.source.less\\"; @import \\"/resources/sap/ui/core/themes/sap_belize_plus/base.less\\"; @import \\"/resources/sap/ui/core/themes/sap_belize_plus/global.less\\"; ", "state": "modified", }, - "com.sap.myui5tslib/src/com/sap/myui5tslib/themes/sap_fiori_3/library.source.less": Object { + "com.sap.myui5tslib121/src/com/sap/myui5tslib121/themes/sap_fiori_3/library.source.less": Object { "contents": "@import \\"../base/library.source.less\\"; @import \\"/resources/sap/ui/core/themes/sap_fiori_3/base.less\\"; @import \\"/resources/sap/ui/core/themes/sap_fiori_3/global.less\\"; ", "state": "modified", }, - "com.sap.myui5tslib/src/com/sap/myui5tslib/themes/sap_fiori_3_dark/library.source.less": Object { + "com.sap.myui5tslib121/src/com/sap/myui5tslib121/themes/sap_fiori_3_dark/library.source.less": Object { "contents": "@import \\"../base/library.source.less\\"; @import \\"/resources/sap/ui/core/themes/sap_fiori_3_dark/base.less\\"; @import \\"/resources/sap/ui/core/themes/sap_fiori_3_dark/global.less\\"; ", "state": "modified", }, - "com.sap.myui5tslib/src/com/sap/myui5tslib/themes/sap_fiori_3_hcb/library.source.less": Object { + "com.sap.myui5tslib121/src/com/sap/myui5tslib121/themes/sap_fiori_3_hcb/library.source.less": Object { "contents": "@import \\"../base/library.source.less\\"; @import \\"/resources/sap/ui/core/themes/sap_fiori_3_hcb/base.less\\"; @import \\"/resources/sap/ui/core/themes/sap_fiori_3_hcb/global.less\\"; ", "state": "modified", }, - "com.sap.myui5tslib/src/com/sap/myui5tslib/themes/sap_fiori_3_hcw/library.source.less": Object { + "com.sap.myui5tslib121/src/com/sap/myui5tslib121/themes/sap_fiori_3_hcw/library.source.less": Object { "contents": "@import \\"../base/library.source.less\\"; @import \\"/resources/sap/ui/core/themes/sap_fiori_3_hcw/base.less\\"; @import \\"/resources/sap/ui/core/themes/sap_fiori_3_hcw/global.less\\"; ", "state": "modified", }, - "com.sap.myui5tslib/test/com/sap/myui5tslib/Example.html": Object { + "com.sap.myui5tslib121/test/com/sap/myui5tslib121/Example.html": Object { "contents": " - Test Page for com.sap.myui5tslib.Example + Test Page for com.sap.myui5tslib121.Example -

Test Page for com.sap.myui5tslib.Example

+

Test Page for com.sap.myui5tslib121.Example

", "state": "modified", }, - "com.sap.myui5tslib/test/com/sap/myui5tslib/Example.ts": Object { - "contents": "import { ExampleColor } from 'com/sap/myui5tslib/library'; -import Example from 'com/sap/myui5tslib/Example'; + "com.sap.myui5tslib121/test/com/sap/myui5tslib121/Example.ts": Object { + "contents": "import { ExampleColor } from 'com/sap/myui5tslib121/library'; +import Example from 'com/sap/myui5tslib121/Example'; // Create a new instance of the Example control and // place it into the DOM element with the id \\"content\\" @@ -1589,7 +3309,7 @@ new Example({ ", "state": "modified", }, - "com.sap.myui5tslib/test/com/sap/myui5tslib/qunit/Example.qunit.ts": Object { + "com.sap.myui5tslib121/test/com/sap/myui5tslib121/qunit/Example.qunit.ts": Object { "contents": "// eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-nocheck @@ -1598,8 +3318,8 @@ new Example({ sap.ui.define([ \\"sap/ui/qunit/QUnitUtils\\", \\"sap/ui/qunit/utils/createAndAppendDiv\\", - \\"com/sap/myui5tslib/library\\", - \\"com/sap/myui5tslib/Example\\" + \\"com/sap/myui5tslib121/library\\", + \\"com/sap/myui5tslib121/Example\\" ], function(qutils, createAndAppendDiv, library, Example) { \\"use strict\\"; @@ -1661,16 +3381,16 @@ sap.ui.define([ ", "state": "modified", }, - "com.sap.myui5tslib/test/com/sap/myui5tslib/qunit/testsuite.qunit.html": Object { + "com.sap.myui5tslib121/test/com/sap/myui5tslib121/qunit/testsuite.qunit.html": Object { "contents": " - QUnit TestSuite for com.sap.myui5tslib + QUnit TestSuite for com.sap.myui5tslib121 + data-sap-ui-testsuite=\\"test-resources/com/sap/myui5tslib121/qunit/testsuite.qunit\\"> @@ -1678,17 +3398,17 @@ sap.ui.define([ ", "state": "modified", }, - "com.sap.myui5tslib/test/com/sap/myui5tslib/qunit/testsuite.qunit.ts": Object { + "com.sap.myui5tslib121/test/com/sap/myui5tslib121/qunit/testsuite.qunit.ts": Object { "contents": "// eslint-disable-next-line no-undef sap.ui.define(function() { \\"use strict\\"; return { - name: \\"QUnit TestSuite for com.sap.myui5tslib\\", + name: \\"QUnit TestSuite for com.sap.myui5tslib121\\", defaults: { bootCore: true, ui5: { - libs: \\"sap.ui.core,com.sap.myui5tslib\\", + libs: \\"sap.ui.core,com.sap.myui5tslib121\\", theme: \\"sap_fiori_3\\", noConflict: true, preload: \\"auto\\" @@ -1708,7 +3428,7 @@ sap.ui.define(function() { // test file for the Example control Example: { title: \\"QUnit Test for Example\\", - _alternativeTitle: \\"QUnit tests: com.sap.myui5tslib.Example\\" + _alternativeTitle: \\"QUnit tests: com.sap.myui5tslib121.Example\\" } } }; @@ -1717,7 +3437,7 @@ sap.ui.define(function() { ", "state": "modified", }, - "com.sap.myui5tslib/tsconfig.json": Object { + "com.sap.myui5tslib121/tsconfig.json": Object { "contents": "{ \\"compilerOptions\\": { \\"target\\": \\"es2022\\", @@ -1732,11 +3452,11 @@ sap.ui.define(function() { \\"baseUrl\\": \\"./\\", \\"typeRoots\\": [ \\"./node_modules/@types\\", - \\"./node_modules/@sapui5/ts-types-esm\\" + \\"./node_modules/@sapui5/types\\" ], \\"paths\\": { - \\"com/sap/myui5tslib/*\\": [ - \\"./src/com/sap/myui5tslib/*\\" + \\"com/sap/myui5tslib121/*\\": [ + \\"./src/com/sap/myui5tslib121/*\\" ] } }, @@ -1747,17 +3467,16 @@ sap.ui.define(function() { }", "state": "modified", }, - "com.sap.myui5tslib/ui5.yaml": Object { + "com.sap.myui5tslib121/ui5.yaml": Object { "contents": "specVersion: '2.2' metadata: - name: \\"myui5tslib\\" + name: \\"myui5tslib121\\" type: library framework: name: SAPUI5 - version: 1.102.19 + version: 1.121.0 libraries: - name: sap.ui.core - - name: themelib_sap_belize - name: themelib_sap_fiori_3 server: customMiddleware: diff --git a/packages/ui5-library-writer/test/common.ts b/packages/ui5-library-writer/test/common.ts index 33b33bc7517..84dfc0e1639 100644 --- a/packages/ui5-library-writer/test/common.ts +++ b/packages/ui5-library-writer/test/common.ts @@ -3,6 +3,7 @@ import { exec as execCP } from 'child_process'; import { promisify } from 'util'; import type { UI5LibConfig } from '../src/types'; import type { Editor } from 'mem-fs-editor'; +import { compareUI5VersionGte, ui5LtsVersion_1_120 } from '../src/utils'; const exec = promisify(execCP); @@ -22,6 +23,7 @@ export function prepareDebug(): { enabled: boolean; debugFull: boolean } { export const projectChecks = async (rootPath: string, config: UI5LibConfig, debugFull = false): Promise => { // Do additional checks on generated projects const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm'; + const npx = process.platform === 'win32' ? 'npx.cmd' : 'npx'; let npmResult; try { if (debugFull) { @@ -42,6 +44,13 @@ export const projectChecks = async (rootPath: string, config: UI5LibConfig, debu npmResult = await exec(`${npm} run lint`, { cwd: rootPath }); console.log('stdout:', npmResult.stdout); console.log('stderr:', npmResult.stderr); + + // UI5 linter for UI5 1.120.0 and above + if (config.frameworkVersion && compareUI5VersionGte(config.frameworkVersion, ui5LtsVersion_1_120)) { + npmResult = await exec(`${npx} --yes @ui5/linter@latest`, { cwd: rootPath }); + console.log('stdout:', npmResult.stdout); + console.log('stderr:', npmResult.stderr); + } } } } catch (error) { diff --git a/packages/ui5-library-writer/test/index.test.ts b/packages/ui5-library-writer/test/index.test.ts index a3e37c55761..6a7249d2b4b 100644 --- a/packages/ui5-library-writer/test/index.test.ts +++ b/packages/ui5-library-writer/test/index.test.ts @@ -22,6 +22,7 @@ describe('Reuse lib templates', () => { typescript: false }; const V1_113_0 = '1.113.0'; + const V1_121_0 = '1.121.0'; const configuration = [ { name: 'lib-js', @@ -44,6 +45,28 @@ describe('Reuse lib templates', () => { frameworkVersion: V1_113_0, author: undefined // to test default is added instead } + }, + { + name: 'lib-js-1.121.0', + config: { ...ui5LibConfig, libraryName: 'myui5jslib121', frameworkVersion: V1_121_0 } + }, + { + name: 'lib-ts-1.121.0', + config: { + ...ui5LibConfig, + libraryName: 'myui5tslib121', + frameworkVersion: V1_121_0, + typescript: true + } + }, + { + name: 'lib-js-latest', + config: { + ...ui5LibConfig, + libraryName: 'myui5jsliblatest', + frameworkVersion: '', + typescript: false + } } ]; @@ -58,7 +81,7 @@ describe('Reuse lib templates', () => { const pkgData = fs.read(join(testOutputDir, projectFolder, 'package.json')); const packageJson = JSON.parse(pkgData); if (config.typescript === true) { - if (config.frameworkVersion === V1_113_0) { + if (config.frameworkVersion === V1_113_0 || config.frameworkVersion === V1_121_0) { expect(packageJson.devDependencies).toHaveProperty('@sapui5/types'); } else { expect(packageJson.devDependencies).toHaveProperty('@sapui5/ts-types-esm'); diff --git a/packages/ui5-library-writer/tsconfig.json b/packages/ui5-library-writer/tsconfig.json index 57ab8d2ff24..fe67e3dbace 100644 --- a/packages/ui5-library-writer/tsconfig.json +++ b/packages/ui5-library-writer/tsconfig.json @@ -16,9 +16,6 @@ { "path": "../project-access" }, - { - "path": "../ui5-application-writer" - }, { "path": "../ui5-config" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d74dd318b40..97b7d491225 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -168,7 +168,7 @@ importers: version: link:../../packages/system-access yeoman-generator: specifier: 5.10.0 - version: 5.10.0(mem-fs@2.1.0)(yeoman-environment@3.19.3) + version: 5.10.0 devDependencies: '@sap-ux/odata-service-writer': specifier: workspace:* @@ -738,6 +738,9 @@ importers: prompts: specifier: 2.4.2 version: 2.4.2 + semver: + specifier: 7.6.3 + version: 7.6.3 devDependencies: '@sap-ux/preview-middleware': specifier: workspace:* @@ -754,6 +757,9 @@ importers: '@types/prompts': specifier: 2.4.4 version: 2.4.4 + '@types/semver': + specifier: 7.5.8 + version: 7.5.8 axios: specifier: 1.7.4 version: 1.7.4 @@ -1400,7 +1406,7 @@ importers: version: 20.6.1 yeoman-generator: specifier: 5.10.0 - version: 5.10.0(mem-fs@2.1.0)(yeoman-environment@3.19.3) + version: 5.10.0 devDependencies: '@sap-ux/axios-extension': specifier: workspace:* @@ -2740,6 +2746,15 @@ importers: specifier: 4.0.2 version: 4.0.2(jest@29.7.0) + packages/project-integrity: + dependencies: + '@sap-ux/project-access': + specifier: workspace:* + version: link:../project-access + lz-string: + specifier: 1.5.0 + version: 1.5.0 + packages/reload-middleware: dependencies: '@sap-ux/btp-utils': @@ -3566,9 +3581,6 @@ importers: '@sap-ux/project-access': specifier: workspace:* version: link:../project-access - '@sap-ux/ui5-application-writer': - specifier: workspace:* - version: link:../ui5-application-writer '@sap-ux/ui5-config': specifier: workspace:* version: link:../ui5-config @@ -6301,7 +6313,7 @@ packages: outdent: 0.5.0 prettier: 2.8.8 resolve-from: 5.0.0 - semver: 7.5.4 + semver: 7.6.3 dev: true /@changesets/assemble-release-plan@6.0.5: @@ -6312,7 +6324,7 @@ packages: '@changesets/should-skip-package': 0.1.1 '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 - semver: 7.5.4 + semver: 7.6.3 dev: true /@changesets/changelog-git@0.2.0: @@ -6350,7 +6362,7 @@ packages: package-manager-detector: 0.2.2 picocolors: 1.1.1 resolve-from: 5.0.0 - semver: 7.5.4 + semver: 7.6.3 spawndamnit: 3.0.1 term-size: 2.2.1 dev: true @@ -6379,7 +6391,7 @@ packages: '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 picocolors: 1.1.1 - semver: 7.5.4 + semver: 7.6.3 dev: true /@changesets/get-release-plan@4.0.5: @@ -7597,7 +7609,7 @@ packages: read-package-json-fast: 2.0.3 readdir-scoped-modules: 1.1.0 rimraf: 3.0.2 - semver: 7.5.4 + semver: 7.6.3 ssri: 8.0.1 treeverse: 1.0.4 walk-up-path: 1.0.0 @@ -7615,7 +7627,7 @@ packages: nopt: 7.2.0 proc-log: 3.0.0 read-package-json-fast: 3.0.2 - semver: 7.5.4 + semver: 7.6.3 walk-up-path: 3.0.1 dev: true @@ -7623,20 +7635,20 @@ packages: resolution: {integrity: sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==} dependencies: '@gar/promisify': 1.1.3 - semver: 7.5.4 + semver: 7.6.3 /@npmcli/fs@2.1.2: resolution: {integrity: sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} dependencies: '@gar/promisify': 1.1.3 - semver: 7.5.4 + semver: 7.6.3 /@npmcli/fs@3.1.0: resolution: {integrity: sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: - semver: 7.5.4 + semver: 7.6.3 /@npmcli/git@2.1.0: resolution: {integrity: sha512-/hBFX/QG1b+N7PZBFs0bi+evgRZcK9nWBxQKZkGoXUT5hJSwl5c4d7y8/hm+NQZRPhQ67RzFaj5UM9YeyKoryw==} @@ -7647,7 +7659,7 @@ packages: npm-pick-manifest: 6.1.1 promise-inflight: 1.0.1 promise-retry: 2.0.1 - semver: 7.5.4 + semver: 7.6.3 which: 2.0.2 transitivePeerDependencies: - bluebird @@ -7662,7 +7674,7 @@ packages: proc-log: 3.0.0 promise-inflight: 1.0.1 promise-retry: 2.0.1 - semver: 7.5.4 + semver: 7.6.3 which: 3.0.1 transitivePeerDependencies: - bluebird @@ -7677,7 +7689,7 @@ packages: proc-log: 3.0.0 promise-inflight: 1.0.1 promise-retry: 2.0.1 - semver: 7.5.4 + semver: 7.6.3 which: 4.0.0 transitivePeerDependencies: - bluebird @@ -7725,7 +7737,7 @@ packages: cacache: 15.3.0 json-parse-even-better-errors: 2.3.1 pacote: 12.0.3 - semver: 7.5.4 + semver: 7.6.3 transitivePeerDependencies: - bluebird - supports-color @@ -8042,7 +8054,7 @@ packages: '@types/shimmer': 1.0.5 import-in-the-middle: 1.4.2 require-in-the-middle: 7.2.0 - semver: 7.5.4 + semver: 7.6.3 shimmer: 1.2.1 transitivePeerDependencies: - supports-color @@ -8451,7 +8463,7 @@ packages: dependencies: '@storybook/core-webpack': 8.4.2(storybook@8.4.2) '@types/node': 22.9.0 - '@types/semver': 7.5.4 + '@types/semver': 7.5.8 browser-assert: 1.2.1 case-sensitive-paths-webpack-plugin: 2.4.0 cjs-module-lexer: 1.3.1 @@ -8463,7 +8475,7 @@ packages: magic-string: 0.30.11 path-browserify: 1.0.1 process: 0.11.10 - semver: 7.5.4 + semver: 7.6.3 storybook: 8.4.2(prettier@2.8.8) style-loader: 3.3.3(webpack@5.96.1) terser-webpack-plugin: 5.3.10(esbuild@0.19.2)(webpack@5.96.1) @@ -8612,14 +8624,14 @@ packages: '@storybook/react': 8.4.2(react-dom@16.14.0)(react@16.14.0)(storybook@8.4.2)(typescript@5.6.2) '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.6.2)(webpack@5.96.1) '@types/node': 22.9.0 - '@types/semver': 7.5.4 + '@types/semver': 7.5.8 find-up: 5.0.0 magic-string: 0.30.11 react: 16.14.0 react-docgen: 7.0.3 react-dom: 16.14.0(react@16.14.0) resolve: 1.22.8 - semver: 7.5.4 + semver: 7.6.3 storybook: 8.4.2(prettier@2.8.8) tsconfig-paths: 4.2.0 typescript: 5.6.2 @@ -9443,6 +9455,10 @@ packages: /@types/semver@7.5.4: resolution: {integrity: sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==} + dev: true + + /@types/semver@7.5.8: + resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} /@types/send@0.17.1: resolution: {integrity: sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==} @@ -9690,7 +9706,7 @@ packages: graphemer: 1.4.0 ignore: 5.2.4 natural-compare: 1.4.0 - semver: 7.5.4 + semver: 7.6.3 ts-api-utils: 1.2.1(typescript@5.6.3) typescript: 5.6.3 transitivePeerDependencies: @@ -9872,7 +9888,7 @@ packages: debug: 4.3.7 globby: 11.1.0 is-glob: 4.0.3 - semver: 7.5.4 + semver: 7.6.3 tsutils: 3.21.0(typescript@5.6.2) typescript: 5.6.2 transitivePeerDependencies: @@ -9893,7 +9909,7 @@ packages: debug: 4.3.7 globby: 11.1.0 is-glob: 4.0.3 - semver: 7.5.4 + semver: 7.6.3 tsutils: 3.21.0(typescript@5.6.3) typescript: 5.6.3 transitivePeerDependencies: @@ -9937,7 +9953,7 @@ packages: globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.3 - semver: 7.5.4 + semver: 7.6.3 ts-api-utils: 1.2.1(typescript@5.6.3) typescript: 5.6.3 transitivePeerDependencies: @@ -9952,13 +9968,13 @@ packages: dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) '@types/json-schema': 7.0.12 - '@types/semver': 7.5.4 + '@types/semver': 7.5.8 '@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/types': 5.62.0 '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.6.2) eslint: 8.57.0 eslint-scope: 5.1.1 - semver: 7.5.4 + semver: 7.6.3 transitivePeerDependencies: - supports-color - typescript @@ -9972,13 +9988,13 @@ packages: dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) '@types/json-schema': 7.0.12 - '@types/semver': 7.5.4 + '@types/semver': 7.5.8 '@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/types': 5.62.0 '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.6.3) eslint: 8.57.0 eslint-scope: 5.1.1 - semver: 7.5.4 + semver: 7.6.3 transitivePeerDependencies: - supports-color - typescript @@ -10008,12 +10024,12 @@ packages: dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) '@types/json-schema': 7.0.12 - '@types/semver': 7.5.4 + '@types/semver': 7.5.8 '@typescript-eslint/scope-manager': 7.2.0 '@typescript-eslint/types': 7.2.0 '@typescript-eslint/typescript-estree': 7.2.0(typescript@5.6.3) eslint: 8.57.0 - semver: 7.5.4 + semver: 7.6.3 transitivePeerDependencies: - supports-color - typescript @@ -10059,7 +10075,7 @@ packages: less-openui5: 0.11.6 pretty-data: 0.40.0 rimraf: 5.0.5 - semver: 7.5.4 + semver: 7.6.3 terser: 5.32.0 workerpool: 6.5.1 xml2js: 0.6.2 @@ -10081,7 +10097,7 @@ packages: js-yaml: 4.1.0 open: 9.1.0 pretty-hrtime: 1.0.3 - semver: 7.5.4 + semver: 7.6.3 update-notifier: 6.0.2 yargs: 17.7.2 transitivePeerDependencies: @@ -10155,7 +10171,7 @@ packages: read-pkg-up: 10.1.0 resolve: 1.22.8 rimraf: 5.0.5 - semver: 7.5.4 + semver: 7.6.3 xml2js: 0.6.2 yesno: 0.4.0 transitivePeerDependencies: @@ -11511,7 +11527,7 @@ packages: /builtins@5.0.1: resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==} dependencies: - semver: 7.5.4 + semver: 7.6.3 /bundle-name@3.0.0: resolution: {integrity: sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==} @@ -12705,7 +12721,7 @@ packages: /diagnostic-channel@1.1.1: resolution: {integrity: sha512-r2HV5qFkUICyoaKlBEpLKHjxMXATUf/l+h8UZPGBHGLy4DDiY2sOLcIctax4eRnTw5wH2jTMExLntGPJ8eOJxw==} dependencies: - semver: 7.5.4 + semver: 7.6.3 dev: false /diff-sequences@29.6.3: @@ -13747,7 +13763,7 @@ packages: eslint: 8.56.0 esquery: 1.6.0 is-builtin-module: 3.2.1 - semver: 7.5.4 + semver: 7.6.3 spdx-expression-parse: 4.0.0 transitivePeerDependencies: - supports-color @@ -14442,7 +14458,7 @@ packages: minimatch: 3.0.5 node-abort-controller: 3.1.1 schema-utils: 3.3.0 - semver: 7.5.4 + semver: 7.6.3 tapable: 2.2.1 typescript: 5.6.2 webpack: 5.96.1(esbuild@0.19.2) @@ -15980,7 +15996,7 @@ packages: '@babel/parser': 7.25.3 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 - semver: 7.5.4 + semver: 7.6.3 transitivePeerDependencies: - supports-color dev: true @@ -16452,7 +16468,7 @@ packages: jest-util: 29.7.0 natural-compare: 1.4.0 pretty-format: 29.7.0 - semver: 7.5.4 + semver: 7.6.3 transitivePeerDependencies: - supports-color dev: true @@ -17038,7 +17054,7 @@ packages: /lz-string@1.5.0: resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} - dev: true + hasBin: true /macos-release@2.5.1: resolution: {integrity: sha512-DXqXhEM7gW59OjZO8NIjBCz9AQ1BEMrfiOAl4AYByHCtVHRF4KoGNO8mqQeM8lRCtQe/UnJ4imO/d2HdkKsd+A==} @@ -17073,7 +17089,7 @@ packages: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} dependencies: - semver: 7.5.4 + semver: 7.6.3 dev: true /make-error@1.3.6: @@ -17691,7 +17707,7 @@ packages: engines: {node: '>=10'} requiresBuild: true dependencies: - semver: 7.5.4 + semver: 7.6.3 dev: true /node-abort-controller@3.1.1: @@ -17721,7 +17737,7 @@ packages: make-fetch-happen: 13.0.0 nopt: 7.2.0 proc-log: 3.0.0 - semver: 7.5.4 + semver: 7.6.3 tar: 6.2.1 which: 4.0.0 transitivePeerDependencies: @@ -17740,7 +17756,7 @@ packages: nopt: 5.0.0 npmlog: 6.0.2 rimraf: 3.0.2 - semver: 7.5.4 + semver: 7.6.3 tar: 6.2.1 which: 2.0.2 transitivePeerDependencies: @@ -17760,7 +17776,7 @@ packages: nopt: 6.0.0 npmlog: 6.0.2 rimraf: 3.0.2 - semver: 7.5.4 + semver: 7.6.3 tar: 6.2.1 which: 2.0.2 transitivePeerDependencies: @@ -17833,7 +17849,7 @@ packages: dependencies: hosted-git-info: 6.1.1 is-core-module: 2.15.0 - semver: 7.5.4 + semver: 7.6.3 validate-npm-package-license: 3.0.4 /normalize-package-data@6.0.0: @@ -17842,7 +17858,7 @@ packages: dependencies: hosted-git-info: 7.0.0 is-core-module: 2.15.0 - semver: 7.5.4 + semver: 7.6.3 validate-npm-package-license: 3.0.4 dev: true @@ -17875,13 +17891,13 @@ packages: resolution: {integrity: sha512-09OmyDkNLYwqKPOnbI8exiOZU2GVVmQp7tgez2BPi5OZC8M82elDAps7sxC4l//uSUtotWqoEIDwjRvWH4qz8w==} engines: {node: '>=10'} dependencies: - semver: 7.5.4 + semver: 7.6.3 /npm-install-checks@6.1.1: resolution: {integrity: sha512-dH3GmQL4vsPtld59cOn8uY0iOqRmqKvV+DLGwNXV/Q7MDgD2QfOADWd/mFXcIE5LVhYYGjA3baz6W9JneqnuCw==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: - semver: 7.5.4 + semver: 7.6.3 /npm-normalize-package-bin@1.0.1: resolution: {integrity: sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==} @@ -17900,7 +17916,7 @@ packages: dependencies: hosted-git-info: 6.1.1 proc-log: 3.0.0 - semver: 7.5.4 + semver: 7.6.3 validate-npm-package-name: 5.0.0 /npm-package-arg@11.0.1: @@ -17909,7 +17925,7 @@ packages: dependencies: hosted-git-info: 7.0.0 proc-log: 3.0.0 - semver: 7.5.4 + semver: 7.6.3 validate-npm-package-name: 5.0.0 dev: true @@ -17918,7 +17934,7 @@ packages: engines: {node: '>=10'} dependencies: hosted-git-info: 4.1.0 - semver: 7.5.4 + semver: 7.6.3 validate-npm-package-name: 3.0.0 /npm-packlist@3.0.0: @@ -17950,7 +17966,7 @@ packages: npm-install-checks: 4.0.0 npm-normalize-package-bin: 1.0.1 npm-package-arg: 8.1.5 - semver: 7.5.4 + semver: 7.6.3 /npm-pick-manifest@8.0.1: resolution: {integrity: sha512-mRtvlBjTsJvfCCdmPtiu2bdlx8d/KXtF7yNXNWe7G0Z36qWA9Ny5zXsI2PfBZEv7SXgoxTmNaTzGSbbzDZChoA==} @@ -17959,7 +17975,7 @@ packages: npm-install-checks: 6.1.1 npm-normalize-package-bin: 3.0.1 npm-package-arg: 10.1.0 - semver: 7.5.4 + semver: 7.6.3 /npm-pick-manifest@9.0.0: resolution: {integrity: sha512-VfvRSs/b6n9ol4Qb+bDwNGUXutpy76x6MARw/XssevE0TnctIKcmklJZM5Z7nqs5z5aW+0S63pgCNbpkUNNXBg==} @@ -17968,7 +17984,7 @@ packages: npm-install-checks: 6.1.1 npm-normalize-package-bin: 3.0.1 npm-package-arg: 11.0.1 - semver: 7.5.4 + semver: 7.6.3 dev: true /npm-registry-fetch@12.0.2: @@ -18138,7 +18154,7 @@ packages: npm-run-path: 4.0.1 open: 8.4.2 ora: 5.3.0 - semver: 7.5.4 + semver: 7.6.3 string-width: 4.2.3 strong-log-transformer: 2.1.0 tar-stream: 2.2.0 @@ -18577,7 +18593,7 @@ packages: got: 12.6.1 registry-auth-token: 5.0.2 registry-url: 6.0.1 - semver: 7.5.4 + semver: 7.6.3 dev: true /package-manager-detector@0.2.2: @@ -20296,7 +20312,7 @@ packages: resolution: {integrity: sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==} engines: {node: '>=12'} dependencies: - semver: 7.5.4 + semver: 7.6.3 dev: true /semver@5.7.2: @@ -20326,7 +20342,6 @@ packages: resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} engines: {node: '>=10'} hasBin: true - dev: true /send@0.19.0: resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} @@ -21065,7 +21080,7 @@ packages: methods: 1.1.2 mime: 2.6.0 qs: 6.11.0 - semver: 7.5.4 + semver: 7.6.3 transitivePeerDependencies: - supports-color dev: true @@ -21406,7 +21421,7 @@ packages: json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 - semver: 7.5.4 + semver: 7.6.3 typescript: 5.6.2 yargs-parser: 21.1.1 dev: true @@ -21441,7 +21456,7 @@ packages: json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 - semver: 7.5.4 + semver: 7.6.3 typescript: 5.6.3 yargs-parser: 21.1.1 dev: true @@ -22040,7 +22055,7 @@ packages: is-yarn-global: 0.4.1 latest-version: 7.0.0 pupa: 3.1.0 - semver: 7.5.4 + semver: 7.6.3 semver-diff: 4.0.0 xdg-basedir: 5.1.0 dev: true @@ -22793,7 +22808,7 @@ packages: preferred-pm: 3.1.4 pretty-bytes: 5.6.0 readable-stream: 4.5.2 - semver: 7.5.4 + semver: 7.6.3 slash: 3.0.0 strip-ansi: 6.0.1 text-table: 0.2.0 @@ -22803,7 +22818,7 @@ packages: - bluebird - supports-color - /yeoman-generator@5.10.0(mem-fs@2.1.0)(yeoman-environment@3.19.3): + /yeoman-generator@5.10.0: resolution: {integrity: sha512-iDUKykV7L4nDNzeYSedRmSeJ5eMYFucnKDi6KN1WNASXErgPepKqsQw55TgXPHnmpcyOh2Dd/LAZkyc+f0qaAw==} engines: {node: '>=12.10.0'} peerDependencies: @@ -22827,6 +22842,37 @@ packages: shelljs: 0.8.5 sort-keys: 4.2.0 text-table: 0.2.0 + transitivePeerDependencies: + - bluebird + - encoding + - mem-fs + - supports-color + dev: false + + /yeoman-generator@5.10.0(mem-fs@2.1.0)(yeoman-environment@3.19.3): + resolution: {integrity: sha512-iDUKykV7L4nDNzeYSedRmSeJ5eMYFucnKDi6KN1WNASXErgPepKqsQw55TgXPHnmpcyOh2Dd/LAZkyc+f0qaAw==} + engines: {node: '>=12.10.0'} + peerDependencies: + yeoman-environment: ^3.2.0 + peerDependenciesMeta: + yeoman-environment: + optional: true + dependencies: + chalk: 4.1.2 + dargs: 7.0.0 + debug: 4.3.7 + execa: 5.1.1 + github-username: 6.0.0 + lodash: 4.17.21 + mem-fs-editor: 9.4.0(mem-fs@2.1.0) + minimist: 1.2.8 + pacote: 15.2.0 + read-pkg-up: 7.0.1 + run-async: 2.4.1 + semver: 7.6.3 + shelljs: 0.8.5 + sort-keys: 4.2.0 + text-table: 0.2.0 yeoman-environment: 3.19.3 transitivePeerDependencies: - bluebird diff --git a/sonar-project.properties b/sonar-project.properties index 90e1c32904d..546c5d689f6 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -80,6 +80,7 @@ sonar.javascript.lcov.reportPaths=packages/abap-deploy-config-inquirer/coverage/ packages/ui5-application-inquirer/coverage/lcov.info, \ packages/inquirer-common/coverage/lcov.info, \ packages/odata-service-inquirer/coverage/lcov.info, \ + packages/project-integrity/coverage/lcov.info, \ packages/jest-environment-ui5/coverage/lcov.info sonar.testExecutionReportPaths=packages/abap-deploy-config-inquirer/coverage/sonar-report.xml, \ packages/abap-deploy-config-sub-generator/coverage/sonar-report.xml, \ @@ -154,5 +155,6 @@ sonar.testExecutionReportPaths=packages/abap-deploy-config-inquirer/coverage/son packages/reload-middleware/coverage/sonar-report.xml, \ packages/ui5-application-inquirer/coverage/sonar-report.xml, \ packages/inquirer-common/coverage/sonar-report.xml, \ + packages/project-integrity/coverage/sonar-report.xml, \ packages/odata-service-inquirer/coverage/sonar-report.xml, \ packages/jest-environment-ui5/coverage/sonar-report.xml diff --git a/tsconfig.json b/tsconfig.json index ef76d2d64ce..897d034719d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -182,6 +182,9 @@ { "path": "packages/project-input-validator" }, + { + "path": "packages/project-integrity" + }, { "path": "packages/reload-middleware" },