@sap-ux/adp-tooling 1.0.16 → 1.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,25 @@
1
- import path, { dirname } from 'node:path';
2
- import { fileURLToPath } from 'node:url';
1
+ import path from 'node:path';
3
2
  import { existsSync, readFileSync, readdirSync } from 'node:fs';
4
- const __dirname = dirname(fileURLToPath(import.meta.url));
5
3
  import { DirName, getWebappPath } from '@sap-ux/project-access';
4
+ import { getTemplatePath } from '../templates.js';
6
5
  import { FlexLayer, TemplateFileName, ChangeTypeMap } from '../types.js';
7
6
  import { renderFile } from 'ejs';
8
7
  import { replaceTextsWithI18nBindings, writeKeyUserTranslations } from '../writer/i18n/key-user-translations.js';
8
+ /**
9
+ * Returns the change file extension matching the change's `fileType` (e.g. `.ctrl_variant`,
10
+ * `.annotation_change`, `.change`). Falls back to `.change` when `fileType` is missing or
11
+ * empty so malformed or legacy payloads do not produce extension-less files.
12
+ *
13
+ * The UI5 Flex frontend routes change files by their suffix; the suffix must match the
14
+ * embedded `fileType`, otherwise non-`change` types (e.g. `ctrl_variant`, `annotation_change`)
15
+ * are misclassified at runtime.
16
+ *
17
+ * @param fileType - The change's `fileType` value, if present.
18
+ * @returns The file extension, including the leading dot.
19
+ */
20
+ function getChangeFileExtension(fileType) {
21
+ return fileType ? `.${fileType}` : '.change';
22
+ }
9
23
  /**
10
24
  * Writes annotation changes to the specified project path using the provided `mem-fs-editor` instance.
11
25
  *
@@ -23,14 +37,14 @@ export async function writeAnnotationChange(projectPath, timestamp, annotation,
23
37
  const changesFolderPath = path.join(webappPath, DirName.Changes);
24
38
  const annotationsFolderPath = path.join(changesFolderPath, DirName.Annotations);
25
39
  if (change) {
26
- const changeFileName = `${change.fileName}.change`;
40
+ const changeFileName = `${change.fileName}${getChangeFileExtension(change.fileType)}`;
27
41
  const changeFilePath = path.join(changesFolderPath, changeFileName);
28
42
  writeChangeToFile(changeFilePath, change, fs);
29
43
  }
30
44
  if (!annotation.filePath) {
31
45
  const annotationsTemplate = templatesPath
32
46
  ? path.join(templatesPath, 'changes', TemplateFileName.Annotation)
33
- : path.join(__dirname, '..', '..', 'templates', 'changes', TemplateFileName.Annotation);
47
+ : getTemplatePath(`changes/${TemplateFileName.Annotation}`);
34
48
  const { namespaces, serviceUrl } = annotation;
35
49
  const schemaNamespace = `local_${timestamp}`;
36
50
  renderFile(annotationsTemplate, { namespaces, path: serviceUrl, schemaNamespace }, {}, (err, str) => {
@@ -125,7 +139,7 @@ export async function writeChangeToFolder(projectPath, change, fs, dir = '') {
125
139
  if (dir) {
126
140
  targetFolderPath = path.join(targetFolderPath, dir);
127
141
  }
128
- const fileName = `${change.fileName}.change`;
142
+ const fileName = `${change.fileName}${getChangeFileExtension(change.fileType)}`;
129
143
  const filePath = path.join(targetFolderPath, fileName);
130
144
  writeChangeToFile(filePath, change, fs);
131
145
  }
@@ -1,14 +1,12 @@
1
1
  import * as fs from 'node:fs';
2
2
  import axios from 'axios';
3
3
  import * as path from 'node:path';
4
- import { fileURLToPath } from 'node:url';
5
4
  import { Cli } from '@sap/cf-tools';
6
- import { dirname } from 'node:path';
7
- const __dirname = dirname(fileURLToPath(import.meta.url));
8
5
  import { isAppStudio } from '@sap-ux/btp-utils';
9
6
  import { t } from '../../i18n.js';
10
7
  import { getProjectNameForXsSecurity } from '../project/index.js';
11
8
  import { createServiceKey, getServiceKeys, requestCfApi } from './cli.js';
9
+ import { getTemplatePath } from '../../templates.js';
12
10
  const PARAM_MAP = new Map([
13
11
  ['spaceGuids', 'space_guids'],
14
12
  ['planNames', 'service_plan_names'],
@@ -179,7 +177,7 @@ export async function createServiceInstance(plan, serviceInstanceName, serviceNa
179
177
  if (xsSecurityProjectName) {
180
178
  let xsSecurity = null;
181
179
  try {
182
- const baseTmplPath = path.join(__dirname, '../../../templates');
180
+ const baseTmplPath = getTemplatePath();
183
181
  const templatePath = templatePathOverwrite ?? baseTmplPath;
184
182
  const filePath = path.resolve(templatePath, 'cf/xs-security.json');
185
183
  const xsContent = fs.readFileSync(filePath, 'utf-8');
@@ -1,9 +1,8 @@
1
1
  import { ChangeType, TemplateFileName } from '../types.js';
2
- import { basename, dirname, join } from 'node:path';
3
- import { fileURLToPath } from 'node:url';
2
+ import { basename, join } from 'node:path';
4
3
  import { render } from 'ejs';
5
4
  import { randomBytes } from 'node:crypto';
6
- const __dirname = dirname(fileURLToPath(import.meta.url));
5
+ import { getTemplatePath } from '../templates.js';
7
6
  import { ManifestService } from '../base/abap/manifest-service.js';
8
7
  import { getVariant, isTypescriptSupported } from '../base/helper.js';
9
8
  import { getAnnotationNamespaces } from '@sap-ux/odata-service-writer';
@@ -221,7 +220,7 @@ export function addXmlFragment(basePath, change, fs, logger, additionalChangeInf
221
220
  const templateConfig = fragmentTemplateDefinitions[additionalChangeInfo?.templateName ?? ''];
222
221
  try {
223
222
  if (templateConfig) {
224
- const fragmentTemplatePath = join(__dirname, '../../templates/rta', templateConfig.path);
223
+ const fragmentTemplatePath = getTemplatePath(`rta/${templateConfig.path}`);
225
224
  const text = fs.read(fragmentTemplatePath);
226
225
  const changeTemplate = {
227
226
  ...templateConfig.getData(change),
@@ -235,7 +234,7 @@ export function addXmlFragment(basePath, change, fs, logger, additionalChangeInf
235
234
  else {
236
235
  // use default fragment template
237
236
  const templateName = 'fragment.xml'; /* TemplateFileName.Fragment */
238
- const fragmentTemplatePath = join(__dirname, '../../templates/rta', templateName);
237
+ const fragmentTemplatePath = getTemplatePath(`rta/${templateName}`);
239
238
  const text = fs.read(fragmentTemplatePath);
240
239
  const template = render(text, {
241
240
  viewName: additionalChangeInfo?.viewName,
@@ -265,7 +264,7 @@ export async function addControllerExtension(rootPath, basePath, change, fs, log
265
264
  const fileName = basename(codeRef, '.js');
266
265
  const fullName = `${fileName}.${isTsSupported ? 'ts' : 'js'}`;
267
266
  const tmplFileName = isTsSupported ? TemplateFileName.TSController : TemplateFileName.Controller;
268
- const tmplPath = join(__dirname, '../../templates/rta', tmplFileName);
267
+ const tmplPath = getTemplatePath(`rta/${tmplFileName}`);
269
268
  try {
270
269
  const text = fs.read(tmplPath);
271
270
  const id = (await getVariant(rootPath))?.id;
@@ -1,9 +1,8 @@
1
- import { dirname, join } from 'node:path';
2
- import { fileURLToPath } from 'node:url';
1
+ import { join } from 'node:path';
3
2
  import { getFragmentPathFromTemplate } from './utils.js';
4
3
  import { randomBytes } from 'node:crypto';
5
4
  import { render } from 'ejs';
6
- const __dirname = dirname(fileURLToPath(import.meta.url));
5
+ import { getTemplatePath } from '../templates.js';
7
6
  export const customFragmentConfig = {
8
7
  path: 'v4/custom-section.xml',
9
8
  getData: () => {
@@ -81,7 +80,7 @@ export function addCustomFragment(basePath, change, fs, logger) {
81
80
  }
82
81
  const fragmentPath = `${path}.fragment.xml`;
83
82
  const fullPath = join(basePath, fragmentPath);
84
- const fragmentTemplatePath = join(__dirname, '../../templates/rta', config.path);
83
+ const fragmentTemplatePath = getTemplatePath(`rta/${config.path}`);
85
84
  const text = fs.read(fragmentTemplatePath);
86
85
  // Safe: Template files are from our own codebase (templates/rta/), config.path is from getConfig()
87
86
  // which only returns predefined paths (customFragmentConfig or customColumnFragmentConfig).
@@ -1,16 +1,14 @@
1
1
  import * as fs from 'node:fs';
2
2
  import * as os from 'node:os';
3
3
  import * as path from 'node:path';
4
- import { fileURLToPath } from 'node:url';
5
4
  import { renderFile } from 'ejs';
6
- import { dirname } from 'node:path';
7
- const __dirname = dirname(fileURLToPath(import.meta.url));
8
5
  import sanitize from 'sanitize-filename';
9
6
  import { isAppStudio } from '@sap-ux/btp-utils';
10
7
  import { TemplateFileName, HttpStatusCodes } from '../types.js';
11
8
  import { DirName } from '@sap-ux/project-access';
12
9
  import { ManifestService } from '../base/abap/manifest-service.js';
13
10
  import { getVariant, isTypescriptSupported } from '../base/helper.js';
11
+ import { getTemplatePath } from '../templates.js';
14
12
  /**
15
13
  * @description Handles API Routes
16
14
  */
@@ -337,7 +335,7 @@ async function generateControllerFile(rootPath, filePath, name) {
337
335
  const id = (await getVariant(rootPath))?.id;
338
336
  const isTsSupported = isTypescriptSupported(rootPath);
339
337
  const tmplFileName = isTsSupported ? TemplateFileName.TSController : TemplateFileName.Controller;
340
- const tmplPath = path.join(__dirname, '../../templates/rta', tmplFileName);
338
+ const tmplPath = getTemplatePath(`rta/${tmplFileName}`);
341
339
  const extensionPath = `${id}.${name}`;
342
340
  const templateData = isTsSupported ? { name, ns: id } : { extensionPath };
343
341
  renderFile(tmplPath, templateData, {}, (err, str) => {
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Locates template files relative to the dist folder.
3
+ * This helps to locate templates when this module is bundled and the dir structure is flattened, maintaining the relative paths.
4
+ *
5
+ * @param relativeTemplatePath - optional, the path of the required template relative to the ./templates folder. If not specified the root templates folder is returned.
6
+ * @returns the path of the template specified or templates root folder
7
+ */
8
+ export declare function getTemplatePath(relativeTemplatePath?: string): string;
9
+ //# sourceMappingURL=templates.d.ts.map
@@ -0,0 +1,14 @@
1
+ import { dirname, join } from 'node:path';
2
+ import { fileURLToPath } from 'node:url';
3
+ const __dirname = dirname(fileURLToPath(import.meta.url));
4
+ /**
5
+ * Locates template files relative to the dist folder.
6
+ * This helps to locate templates when this module is bundled and the dir structure is flattened, maintaining the relative paths.
7
+ *
8
+ * @param relativeTemplatePath - optional, the path of the required template relative to the ./templates folder. If not specified the root templates folder is returned.
9
+ * @returns the path of the template specified or templates root folder
10
+ */
11
+ export function getTemplatePath(relativeTemplatePath = '') {
12
+ return join(__dirname, '../templates', relativeTemplatePath);
13
+ }
14
+ //# sourceMappingURL=templates.js.map
@@ -1,5 +1,4 @@
1
- import { dirname, join } from 'node:path';
2
- import { fileURLToPath } from 'node:url';
1
+ import { join } from 'node:path';
3
2
  import { create as createStorage } from 'mem-fs';
4
3
  import { create } from 'mem-fs-editor';
5
4
  import { getManifestContent } from './manifest/index.js';
@@ -8,8 +7,7 @@ import { writeTemplateToFolder, writeUI5Yaml, writeUI5DeployYaml } from './proje
8
7
  import { FlexLayer } from '../types.js';
9
8
  import { getApplicationType } from '../source/index.js';
10
9
  import { writeKeyUserChanges } from '../base/change-utils.js';
11
- const __dirname = dirname(fileURLToPath(import.meta.url));
12
- const baseTmplPath = join(__dirname, '../../templates');
10
+ import { getTemplatePath } from '../templates.js';
13
11
  /**
14
12
  * Set default values for optional properties.
15
13
  *
@@ -50,7 +48,7 @@ export async function generate(basePath, config, fs) {
50
48
  fs = create(createStorage());
51
49
  }
52
50
  const fullConfig = setDefaults(config);
53
- const templatePath = config.options?.templatePathOverwrite ?? baseTmplPath;
51
+ const templatePath = config.options?.templatePathOverwrite ?? getTemplatePath();
54
52
  writeI18nModels(basePath, fullConfig.app.i18nModels, fs);
55
53
  writeTemplateToFolder(templatePath, join(basePath), fullConfig, fs);
56
54
  await writeUI5DeployYaml(basePath, fullConfig, fs);
@@ -71,7 +69,7 @@ export async function migrate(basePath, config, fs) {
71
69
  fs = create(createStorage());
72
70
  }
73
71
  const fullConfig = setDefaults(config);
74
- const tmplPath = join(baseTmplPath, 'project');
72
+ const tmplPath = join(getTemplatePath(), 'project');
75
73
  // Copy the specified files to target project
76
74
  fs.copyTpl(join(tmplPath, '**/ui5.yaml'), join(basePath), fullConfig, undefined, {
77
75
  globOptions: { dot: true }
@@ -1,7 +1,6 @@
1
- import { dirname, join } from 'node:path';
2
- import { fileURLToPath } from 'node:url';
1
+ import { join } from 'node:path';
3
2
  import { readFileSync } from 'node:fs';
4
- const __dirname = dirname(fileURLToPath(import.meta.url));
3
+ import { getTemplatePath } from '../templates.js';
5
4
  import { enhanceUI5DeployYaml, enhanceUI5Yaml, hasDeployConfig, enhanceUI5YamlWithCustomConfig, enhanceUI5YamlWithCustomTask, enhanceUI5YamlWithTranspileMiddleware, enhanceUI5YamlWithCfCustomTask, enhanceUI5YamlWithFioriToolsMiddleware } from './options.js';
6
5
  import { UI5Config, UI5_DEFAULT, getEsmTypesVersion, getTypesPackage, getTypesVersion } from '@sap-ux/ui5-config';
7
6
  /**
@@ -15,7 +14,7 @@ export function getPackageJSONInfo() {
15
14
  version: 'NO_VERSION_FOUND'
16
15
  };
17
16
  try {
18
- return JSON.parse(readFileSync(join(__dirname, '../../package.json'), 'utf-8'));
17
+ return JSON.parse(readFileSync(join(getTemplatePath(), '../package.json'), 'utf-8'));
19
18
  }
20
19
  catch (e) {
21
20
  return defaultPackage;
@@ -189,8 +188,7 @@ export async function writeUI5DeployYaml(projectPath, data, fs) {
189
188
  * @param {Editor} fs - The memfs editor instance.
190
189
  */
191
190
  export async function writeCfTemplates(basePath, variant, config, fs) {
192
- const baseTmplPath = join(__dirname, '../../templates');
193
- const templatePath = config.options?.templatePathOverwrite ?? baseTmplPath;
191
+ const templatePath = config.options?.templatePathOverwrite ?? getTemplatePath();
194
192
  const { app, project, options } = config;
195
193
  fs.copyTpl(join(templatePath, 'project/webapp/manifest.appdescr_variant'), join(project.folder, 'webapp', 'manifest.appdescr_variant'), { app: variant });
196
194
  fs.copyTpl(join(templatePath, 'cf/package.json'), join(project.folder, 'package.json'), {
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "bugs": {
11
11
  "url": "https://github.com/SAP/open-ux-tools/issues?q=is%3Aopen+is%3Aissue+label%3Abug+label%3Aadp-tooling"
12
12
  },
13
- "version": "1.0.16",
13
+ "version": "1.0.17",
14
14
  "license": "Apache-2.0",
15
15
  "author": "@SAP/ux-tools-team",
16
16
  "main": "dist/index.js",
@@ -40,10 +40,10 @@
40
40
  "@sap-ux/axios-extension": "2.0.3",
41
41
  "@sap-ux/btp-utils": "2.0.2",
42
42
  "@sap-ux/i18n": "1.0.1",
43
- "@sap-ux/inquirer-common": "1.0.11",
43
+ "@sap-ux/inquirer-common": "1.0.12",
44
44
  "@sap-ux/logger": "1.0.1",
45
45
  "@sap-ux/nodejs-utils": "1.0.3",
46
- "@sap-ux/odata-service-writer": "1.0.6",
46
+ "@sap-ux/odata-service-writer": "1.0.7",
47
47
  "@sap-ux/project-access": "2.1.2",
48
48
  "@sap-ux/project-input-validator": "1.0.6",
49
49
  "@sap-ux/store": "2.0.1",