@sap-ux/adp-tooling 0.18.93 → 0.18.95

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,8 +1,7 @@
1
1
  import type { ToolsLogger } from '@sap-ux/logger';
2
2
  import type { Manifest, ManifestNamespace } from '@sap-ux/project-access';
3
3
  import { type AbapServiceProvider } from '@sap-ux/axios-extension';
4
- import type { DescriptorVariant } from '../../types';
5
- export type DataSources = Record<string, ManifestNamespace.DataSource>;
4
+ import type { DescriptorVariant, IManifestService, DataSources } from '../../types';
6
5
  /**
7
6
  * Retrieves the inbound navigation configurations from the project's manifest.
8
7
  *
@@ -23,7 +22,7 @@ export declare function getRegistrationIdFromManifest(manifest: Manifest): strin
23
22
  * It provides methods to fetch the manifest, data sources and metadata of a data source.
24
23
  *
25
24
  */
26
- export declare class ManifestService {
25
+ export declare class ManifestService implements IManifestService {
27
26
  private readonly provider;
28
27
  private readonly logger;
29
28
  private manifest;
@@ -105,7 +105,7 @@ function getAppParamsFromUI5Yaml(projectPath) {
105
105
  const appConfiguration = parsedYaml?.builder?.customTasks?.[0]?.configuration;
106
106
  const appParams = {
107
107
  appHostId: appConfiguration?.appHostId || '',
108
- appName: appConfiguration?.appVersion || '',
108
+ appName: appConfiguration?.appName || '',
109
109
  appVersion: appConfiguration?.appVersion || '',
110
110
  spaceGuid: appConfiguration?.space || ''
111
111
  };
@@ -1,3 +1,4 @@
1
1
  export * from './api';
2
2
  export * from './cli';
3
+ export * from './manifest';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -16,4 +16,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./api"), exports);
18
18
  __exportStar(require("./cli"), exports);
19
+ __exportStar(require("./manifest"), exports);
19
20
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,52 @@
1
+ import type { ToolsLogger } from '@sap-ux/logger';
2
+ import type { Manifest } from '@sap-ux/project-access';
3
+ import type { IManifestService, DataSources } from '../../types';
4
+ /**
5
+ * Service class for handling operations related to the manifest of a CF-deployed UI5 application.
6
+ * Extends the ABAP {@link ManifestService} API, but retrieves the manifest from the local
7
+ * build output (`dist/`)
8
+ *
9
+ * The build is triggered automatically during initialization so that the `dist/` folder
10
+ * contains the latest merged manifest before it is read.
11
+ */
12
+ export declare class ManifestServiceCF implements IManifestService {
13
+ private readonly logger;
14
+ private manifest;
15
+ /**
16
+ * Private constructor to initialize the ManifestServiceCF.
17
+ *
18
+ * @param logger - The logger instance.
19
+ */
20
+ private constructor();
21
+ /**
22
+ * Creates an instance of the ManifestServiceCF by building the project and
23
+ * reading the manifest from the `dist/` folder.
24
+ *
25
+ * @param projectPath - The path to the adaptation project.
26
+ * @param logger - The logger instance.
27
+ * @returns A promise that resolves to an instance of ManifestServiceCF.
28
+ */
29
+ static init(projectPath: string, logger: ToolsLogger): Promise<ManifestServiceCF>;
30
+ /**
31
+ * Returns the manifest read from the build output during initialization.
32
+ *
33
+ * @returns The current manifest.
34
+ */
35
+ getManifest(): Manifest;
36
+ /**
37
+ * Returns the data sources from the manifest.
38
+ *
39
+ * @returns The data sources from the manifest.
40
+ * @throws Error if no data sources are found in the manifest.
41
+ */
42
+ getManifestDataSources(): DataSources;
43
+ /**
44
+ * Metadata fetching is not supported for CF projects because there is no ABAP service provider
45
+ * to proxy the OData metadata request. Consumers should handle this gracefully.
46
+ *
47
+ * @param _dataSourceId - The ID of the data source (unused).
48
+ * @throws Error indicating metadata fetching is not supported for CF projects.
49
+ */
50
+ getDataSourceMetadata(_dataSourceId: string): Promise<string>;
51
+ }
52
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ManifestServiceCF = void 0;
4
+ const node_fs_1 = require("node:fs");
5
+ const node_path_1 = require("node:path");
6
+ const project_builder_1 = require("../../base/project-builder");
7
+ const i18n_1 = require("../../i18n");
8
+ /** Default build output folder used by CF ADP projects. */
9
+ const CF_BUILD_PATH = 'dist';
10
+ /**
11
+ * Service class for handling operations related to the manifest of a CF-deployed UI5 application.
12
+ * Extends the ABAP {@link ManifestService} API, but retrieves the manifest from the local
13
+ * build output (`dist/`)
14
+ *
15
+ * The build is triggered automatically during initialization so that the `dist/` folder
16
+ * contains the latest merged manifest before it is read.
17
+ */
18
+ class ManifestServiceCF {
19
+ logger;
20
+ manifest;
21
+ /**
22
+ * Private constructor to initialize the ManifestServiceCF.
23
+ *
24
+ * @param logger - The logger instance.
25
+ */
26
+ constructor(logger) {
27
+ this.logger = logger;
28
+ }
29
+ /**
30
+ * Creates an instance of the ManifestServiceCF by building the project and
31
+ * reading the manifest from the `dist/` folder.
32
+ *
33
+ * @param projectPath - The path to the adaptation project.
34
+ * @param logger - The logger instance.
35
+ * @returns A promise that resolves to an instance of ManifestServiceCF.
36
+ */
37
+ static async init(projectPath, logger) {
38
+ const service = new ManifestServiceCF(logger);
39
+ logger.debug('Triggering project build to generate dist folder');
40
+ await (0, project_builder_1.runBuild)(projectPath, { ADP_BUILDER_MODE: 'preview' });
41
+ const manifestPath = (0, node_path_1.join)(projectPath, CF_BUILD_PATH, 'manifest.json');
42
+ logger.debug(`Reading manifest from '${manifestPath}'`);
43
+ const manifestContent = (0, node_fs_1.readFileSync)(manifestPath, 'utf-8');
44
+ service.manifest = JSON.parse(manifestContent);
45
+ logger.debug('Manifest successfully read from dist folder');
46
+ return service;
47
+ }
48
+ /**
49
+ * Returns the manifest read from the build output during initialization.
50
+ *
51
+ * @returns The current manifest.
52
+ */
53
+ getManifest() {
54
+ return this.manifest;
55
+ }
56
+ /**
57
+ * Returns the data sources from the manifest.
58
+ *
59
+ * @returns The data sources from the manifest.
60
+ * @throws Error if no data sources are found in the manifest.
61
+ */
62
+ getManifestDataSources() {
63
+ const dataSources = this.manifest['sap.app'].dataSources;
64
+ if (!dataSources) {
65
+ throw new Error('No data sources found in the manifest');
66
+ }
67
+ this.logger.debug(`Found ${Object.keys(dataSources).length} data source(s) in manifest`);
68
+ return dataSources;
69
+ }
70
+ /**
71
+ * Metadata fetching is not supported for CF projects because there is no ABAP service provider
72
+ * to proxy the OData metadata request. Consumers should handle this gracefully.
73
+ *
74
+ * @param _dataSourceId - The ID of the data source (unused).
75
+ * @throws Error indicating metadata fetching is not supported for CF projects.
76
+ */
77
+ async getDataSourceMetadata(_dataSourceId) {
78
+ const message = (0, i18n_1.t)('error.metadataFetchingNotSupportedForCF');
79
+ this.logger.warn(message);
80
+ throw new Error(message);
81
+ }
82
+ }
83
+ exports.ManifestServiceCF = ManifestServiceCF;
84
+ //# sourceMappingURL=manifest.js.map
@@ -13,7 +13,9 @@ export declare const enum ApiRoutes {
13
13
  FRAGMENT = "/adp/api/fragment",
14
14
  CONTROLLER = "/adp/api/controller",
15
15
  CODE_EXT = "/adp/api/code_ext",
16
- ANNOTATION = "/adp/api/annotation"
16
+ ANNOTATION = "/adp/api/annotation",
17
+ OVP_DATA_SOURCES = "/adp/api/ovp/datasources",
18
+ OVP_METAMODEL = "/adp/api/ovp/metamodel"
17
19
  }
18
20
  /**
19
21
  * Instance of an adaptation project handling requests and data transformation.
@@ -35,6 +37,10 @@ export declare class AdpPreview {
35
37
  * Routes handler class to handle API requests
36
38
  */
37
39
  private routesHandler;
40
+ /**
41
+ * Routes handler for OVP bridge functions
42
+ */
43
+ private ovpRoutesHandler;
38
44
  private lrep;
39
45
  private descriptorVariantId;
40
46
  private projectTypeValue?;
@@ -7,6 +7,7 @@ exports.AdpPreview = void 0;
7
7
  const adm_zip_1 = __importDefault(require("adm-zip"));
8
8
  const system_access_1 = require("@sap-ux/system-access");
9
9
  const routes_handler_1 = __importDefault(require("./routes-handler"));
10
+ const ovp_routes_handler_1 = __importDefault(require("./ovp-routes-handler"));
10
11
  const change_handler_1 = require("./change-handler");
11
12
  const descriptor_change_handler_1 = require("./descriptor-change-handler");
12
13
  const helper_1 = require("../base/helper");
@@ -31,6 +32,10 @@ class AdpPreview {
31
32
  * Routes handler class to handle API requests
32
33
  */
33
34
  routesHandler;
35
+ /**
36
+ * Routes handler for OVP bridge functions
37
+ */
38
+ ovpRoutesHandler;
34
39
  lrep;
35
40
  descriptorVariantId;
36
41
  projectTypeValue;
@@ -102,6 +107,7 @@ class AdpPreview {
102
107
  this.descriptorVariantId = descriptorVariant.id;
103
108
  this.provider = await (0, system_access_1.createAbapServiceProvider)(this.config.target, { ignoreCertErrors: this.config.ignoreCertErrors }, true, this.logger);
104
109
  this.routesHandler = new routes_handler_1.default(this.project, this.util, this.provider, this.logger);
110
+ this.ovpRoutesHandler = new ovp_routes_handler_1.default(this.provider, this.logger);
105
111
  this.lrep = this.provider.getLayeredRepository();
106
112
  // fetch a merged descriptor from the backend
107
113
  await this.lrep.getCsrfToken();
@@ -205,6 +211,10 @@ class AdpPreview {
205
211
  router.post("/adp/api/controller" /* ApiRoutes.CONTROLLER */, this.routesHandler.handleWriteControllerExt);
206
212
  router.get("/adp/api/code_ext" /* ApiRoutes.CODE_EXT */, this.routesHandler.handleGetControllerExtensionData);
207
213
  router.get("/adp/api/annotation" /* ApiRoutes.ANNOTATION */, this.routesHandler.handleGetAllAnnotationFilesMappedByDataSource);
214
+ if (this.ovpRoutesHandler) {
215
+ router.get("/adp/api/ovp/datasources" /* ApiRoutes.OVP_DATA_SOURCES */, this.ovpRoutesHandler.handleGetDataSources);
216
+ router.post("/adp/api/ovp/metamodel" /* ApiRoutes.OVP_METAMODEL */, this.ovpRoutesHandler.handleGetMetaModel);
217
+ }
208
218
  }
209
219
  /**
210
220
  * Handles different types of change requests to project files.
@@ -0,0 +1,38 @@
1
+ import type { ToolsLogger } from '@sap-ux/logger';
2
+ import type { NextFunction, Request, Response } from 'express';
3
+ import type { AbapServiceProvider } from '@sap-ux/axios-extension';
4
+ /**
5
+ * Server-side handler for OVP bridge function API routes.
6
+ * Provides data source catalog and service metadata endpoints
7
+ * consumed by the client-side OVP bridge functions.
8
+ */
9
+ export default class OvpRoutesHandler {
10
+ private readonly provider;
11
+ private readonly logger;
12
+ /**
13
+ * Creates an instance of OvpRoutesHandler.
14
+ *
15
+ * @param provider AbapServiceProvider instance for backend communication
16
+ * @param logger Logger instance
17
+ */
18
+ constructor(provider: AbapServiceProvider, logger: ToolsLogger);
19
+ /**
20
+ * Handler for fetching available OData V2 services from the catalog.
21
+ *
22
+ * @param _req Request
23
+ * @param res Response
24
+ * @param next Next function
25
+ */
26
+ handleGetDataSources: (_req: Request, res: Response, next: NextFunction) => Promise<void>;
27
+ /**
28
+ * Handler for fetching service info and annotation URLs for a selected data source.
29
+ * Returns the service URL and annotation details so the client can create
30
+ * a real UI5 ODataModel with annotations merged for full metamodel support.
31
+ *
32
+ * @param req Request containing dataSource in body
33
+ * @param res Response
34
+ * @param next Next function
35
+ */
36
+ handleGetMetaModel: (req: Request, res: Response, next: NextFunction) => Promise<void>;
37
+ }
38
+ //# sourceMappingURL=ovp-routes-handler.d.ts.map
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const axios_extension_1 = require("@sap-ux/axios-extension");
4
+ /**
5
+ * Converts an absolute URL to a relative path.
6
+ * Annotation URIs from the catalog service are absolute (e.g. https://host/sap/opu/...).
7
+ * The client needs relative paths so requests go through the backend proxy.
8
+ *
9
+ * @param uri Absolute or relative URI
10
+ * @returns Relative path
11
+ */
12
+ function toRelativePath(uri) {
13
+ try {
14
+ return new URL(uri).pathname;
15
+ }
16
+ catch {
17
+ return uri;
18
+ }
19
+ }
20
+ /**
21
+ * Server-side handler for OVP bridge function API routes.
22
+ * Provides data source catalog and service metadata endpoints
23
+ * consumed by the client-side OVP bridge functions.
24
+ */
25
+ class OvpRoutesHandler {
26
+ provider;
27
+ logger;
28
+ /**
29
+ * Creates an instance of OvpRoutesHandler.
30
+ *
31
+ * @param provider AbapServiceProvider instance for backend communication
32
+ * @param logger Logger instance
33
+ */
34
+ constructor(provider, logger) {
35
+ this.provider = provider;
36
+ this.logger = logger;
37
+ }
38
+ /**
39
+ * Handler for fetching available OData V2 services from the catalog.
40
+ *
41
+ * @param _req Request
42
+ * @param res Response
43
+ * @param next Next function
44
+ */
45
+ handleGetDataSources = async (_req, res, next) => {
46
+ try {
47
+ const catalogService = this.provider.catalog(axios_extension_1.ODataVersion.v2);
48
+ const response = await catalogService.get('/ServiceCollection', {
49
+ params: { $format: 'json' }
50
+ });
51
+ const services = response.odata();
52
+ res.status(200 /* HttpStatusCodes.OK */).json({ results: services });
53
+ this.logger.debug(`OVP: Fetched ${services.length} data sources from catalog`);
54
+ }
55
+ catch (e) {
56
+ this.logger.error(`OVP: Failed to fetch data sources: ${e.message}`);
57
+ res.status(500 /* HttpStatusCodes.INTERNAL_SERVER_ERROR */).json({
58
+ message: `Failed to fetch data sources: ${e.message}`
59
+ });
60
+ next(e);
61
+ }
62
+ };
63
+ /**
64
+ * Handler for fetching service info and annotation URLs for a selected data source.
65
+ * Returns the service URL and annotation details so the client can create
66
+ * a real UI5 ODataModel with annotations merged for full metamodel support.
67
+ *
68
+ * @param req Request containing dataSource in body
69
+ * @param res Response
70
+ * @param next Next function
71
+ */
72
+ handleGetMetaModel = async (req, res, next) => {
73
+ try {
74
+ const { dataSource } = req.body;
75
+ this.logger.debug(`OVP: getMetaModel called for service ${dataSource?.Title ?? 'unknown'}`);
76
+ if (!dataSource?.Title) {
77
+ res.status(400 /* HttpStatusCodes.BAD_REQUEST */).json({ message: 'dataSource with Title is required' });
78
+ return;
79
+ }
80
+ const catalogService = this.provider.catalog(axios_extension_1.ODataVersion.v2);
81
+ const filterOptions = dataSource.ID ? { id: dataSource.ID } : { title: dataSource.Title };
82
+ const annotations = await catalogService.getAnnotations(filterOptions);
83
+ if (annotations.length === 0) {
84
+ res.status(200 /* HttpStatusCodes.OK */).json(null);
85
+ this.logger.debug(`OVP: No annotations found for service ${dataSource.Title}`);
86
+ return;
87
+ }
88
+ const serviceURI = `/sap/opu/odata/sap/${dataSource.Title}`;
89
+ res.status(200 /* HttpStatusCodes.OK */).json({
90
+ serviceUrl: `${serviceURI}/`,
91
+ annotations: annotations.map((a) => ({
92
+ TechnicalName: a.TechnicalName,
93
+ Uri: toRelativePath(a.Uri)
94
+ })),
95
+ modelInformation: {
96
+ serviceURI,
97
+ serviceAnnotation: annotations[0].TechnicalName,
98
+ serviceAnnotationURI: toRelativePath(annotations[0].Uri)
99
+ }
100
+ });
101
+ this.logger.debug(`OVP: Fetched service info for ${dataSource.Title} with ${annotations.length} annotations`);
102
+ }
103
+ catch (e) {
104
+ this.logger.error(`OVP: Failed to fetch metamodel: ${e.message}`);
105
+ res.status(500 /* HttpStatusCodes.INTERNAL_SERVER_ERROR */).json({
106
+ message: `Failed to fetch metamodel: ${e.message}`
107
+ });
108
+ next(e);
109
+ }
110
+ };
111
+ }
112
+ exports.default = OvpRoutesHandler;
113
+ //# sourceMappingURL=ovp-routes-handler.js.map
@@ -111,7 +111,8 @@
111
111
  "xsAppJsonNotFound": "The xs-app.json file was not found in any of the expected locations: {{paths}}",
112
112
  "noServiceInstanceNameFound": "No serviceInstanceName found in the app-variant-bundler-build configuration",
113
113
  "noServiceKeysFoundForInstance": "No service keys found for service instance: {{serviceInstanceName}}",
114
- "couldNotFetchServiceKeys": "Could not fetch the service keys: {{error}}"
114
+ "couldNotFetchServiceKeys": "Cannot fetch the service keys. Error: {{error}}",
115
+ "metadataFetchingNotSupportedForCF": "Metadata fetching is not supported for Cloud Foundry projects."
115
116
  },
116
117
  "choices": {
117
118
  "true": "true",
package/dist/types.d.ts CHANGED
@@ -7,6 +7,32 @@ import type { Destination } from '@sap-ux/btp-utils';
7
7
  import type { YUIQuestion } from '@sap-ux/inquirer-common';
8
8
  import type AdmZip from 'adm-zip';
9
9
  import type { SupportedProject } from './source';
10
+ export type DataSources = Record<string, ManifestNamespace.DataSource>;
11
+ /**
12
+ * Common interface for manifest services (ABAP and CF).
13
+ * Consumers should program against this interface to support both environments.
14
+ */
15
+ export interface IManifestService {
16
+ /**
17
+ * Returns the manifest.
18
+ *
19
+ * @returns The manifest.
20
+ */
21
+ getManifest(): Manifest;
22
+ /**
23
+ * Returns the data sources from the manifest.
24
+ *
25
+ * @returns The data sources from the manifest.
26
+ */
27
+ getManifestDataSources(): DataSources;
28
+ /**
29
+ * Returns the metadata of a data source.
30
+ *
31
+ * @param dataSourceId - The ID of the data source.
32
+ * @returns A promise that resolves to the metadata of the data source.
33
+ */
34
+ getDataSourceMetadata(dataSourceId: string): Promise<string>;
35
+ }
10
36
  export interface DescriptorVariant {
11
37
  layer: UI5FlexLayer;
12
38
  reference: string;
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "bugs": {
10
10
  "url": "https://github.com/SAP/open-ux-tools/issues?q=is%3Aopen+is%3Aissue+label%3Abug+label%3Aadp-tooling"
11
11
  },
12
- "version": "0.18.93",
12
+ "version": "0.18.95",
13
13
  "license": "Apache-2.0",
14
14
  "author": "@SAP/ux-tools-team",
15
15
  "main": "dist/index.js",