@sap-ux/project-access 1.4.0 → 1.5.0

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,5 +1,8 @@
1
1
  export declare const FileName: {
2
+ readonly AdaptationConfig: "config.json";
3
+ readonly ExtConfigJson: ".extconfig.json";
2
4
  readonly Manifest: "manifest.json";
5
+ readonly ManifestAppDescrVar: "manifest.appdescr_variant";
3
6
  readonly Package: "package.json";
4
7
  readonly Tsconfig: "tsconfig.json";
5
8
  readonly Ui5Yaml: "ui5.yaml";
package/dist/constants.js CHANGED
@@ -2,7 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FileName = void 0;
4
4
  exports.FileName = {
5
+ AdaptationConfig: 'config.json',
6
+ ExtConfigJson: '.extconfig.json',
5
7
  Manifest: 'manifest.json',
8
+ ManifestAppDescrVar: 'manifest.appdescr_variant',
6
9
  Package: 'package.json',
7
10
  Tsconfig: 'tsconfig.json',
8
11
  Ui5Yaml: 'ui5.yaml',
@@ -1,4 +1,22 @@
1
1
  import type { Editor } from 'mem-fs-editor';
2
+ /**
3
+ * Find function to search for files by names or file extensions.
4
+ *
5
+ * @param options - find options
6
+ * @param [options.fileNames] - optional array of file names to search for
7
+ * @param [options.extensionNames] - optional array of file extensions to search for
8
+ * @param options.root - folder to start recursive search
9
+ * @param [options.excludeFolders] - optional array of folder names to exclude
10
+ * @param [options.memFs] - optional memfs editor instance
11
+ * @returns - array of paths that contain the file
12
+ */
13
+ export declare function findBy(options: {
14
+ fileNames?: string[];
15
+ extensionNames?: string[];
16
+ root: string;
17
+ excludeFolders?: string[];
18
+ memFs?: Editor;
19
+ }): Promise<string[]>;
2
20
  /**
3
21
  * Search for 'filename' starting from 'root'. Returns array of paths that contain the file.
4
22
  *
@@ -12,7 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.findFileUp = exports.findFilesByExtension = exports.findFiles = void 0;
15
+ exports.findFileUp = exports.findFilesByExtension = exports.findFiles = exports.findBy = void 0;
16
16
  const path_1 = require("path");
17
17
  const findit2_1 = __importDefault(require("findit2"));
18
18
  const file_access_1 = require("./file-access");
@@ -20,15 +20,15 @@ const file_access_1 = require("./file-access");
20
20
  * Get deleted and modified files from mem-fs editor filtered by query and 'by' (name|extension).
21
21
  *
22
22
  * @param changes - memfs editor changes, usually retrieved by fs.dump()
23
- * @param query - search string, file name or file extension
24
- * @param by - search by file 'name' or file 'extension'
23
+ * @param fileNames - array of file names to search for
24
+ * @param extensionNames - array of extensions names to search for
25
25
  * @returns - array of deleted and modified files filtered by query
26
26
  */
27
- function getMemFsChanges(changes, query, by) {
27
+ function getMemFsChanges(changes, fileNames, extensionNames) {
28
28
  const deleted = [];
29
29
  const modified = [];
30
- const getFilePartToCompare = by === 'extension' ? path_1.extname : path_1.basename;
31
- for (const file of Object.keys(changes).filter((f) => getFilePartToCompare(f) === query)) {
30
+ const filteredChanges = Object.keys(changes).filter((f) => fileNames.includes((0, path_1.basename)(f)) || extensionNames.includes((0, path_1.extname)(f)));
31
+ for (const file of filteredChanges) {
32
32
  if (changes[file].state === 'deleted') {
33
33
  deleted.push((0, path_1.join)(file));
34
34
  }
@@ -39,42 +39,41 @@ function getMemFsChanges(changes, query, by) {
39
39
  return { deleted, modified };
40
40
  }
41
41
  /**
42
- * Find function to search for files.
42
+ * Find function to search for files by names or file extensions.
43
43
  *
44
44
  * @param options - find options
45
- * @param options.query - search string
46
- * @param options.by - search by file 'name' or file 'extension'
45
+ * @param [options.fileNames] - optional array of file names to search for
46
+ * @param [options.extensionNames] - optional array of file extensions to search for
47
47
  * @param options.root - folder to start recursive search
48
- * @param options.excludeFolders - folder names to exclude
48
+ * @param [options.excludeFolders] - optional array of folder names to exclude
49
49
  * @param [options.memFs] - optional memfs editor instance
50
- * @returns - array of paths that contain the file if searched for name; array of full file paths in case of search by extension
50
+ * @returns - array of paths that contain the file
51
51
  */
52
52
  function findBy(options) {
53
- const getFilePartToCompare = options.by === 'extension' ? path_1.extname : path_1.basename;
54
53
  return new Promise((resolve, reject) => {
55
54
  const results = [];
55
+ const fileNames = Array.isArray(options.fileNames) ? options.fileNames : [];
56
+ const extensionNames = Array.isArray(options.extensionNames) ? options.extensionNames : [];
57
+ const excludeFolders = Array.isArray(options.excludeFolders) ? options.excludeFolders : [];
56
58
  const finder = (0, findit2_1.default)(options.root);
57
59
  finder.on('directory', (dir, _stat, stop) => {
58
60
  const base = (0, path_1.basename)(dir);
59
- if (options.excludeFolders.includes(base)) {
61
+ if (excludeFolders.includes(base)) {
60
62
  stop();
61
63
  }
62
64
  });
63
65
  finder.on('file', (file) => {
64
- if (getFilePartToCompare(file) === options.query) {
66
+ if (extensionNames.includes((0, path_1.extname)(file)) || fileNames.includes((0, path_1.basename)(file))) {
65
67
  results.push(file);
66
68
  }
67
69
  });
68
70
  finder.on('end', () => {
69
71
  let searchResult = results;
70
72
  if (options.memFs) {
71
- const { modified, deleted } = getMemFsChanges(options.memFs.dump(''), options.query, options.by);
73
+ const { modified, deleted } = getMemFsChanges(options.memFs.dump(''), fileNames, extensionNames);
72
74
  const merged = Array.from(new Set([...results, ...modified]));
73
75
  searchResult = merged.filter((f) => !deleted.includes(f));
74
76
  }
75
- if (options.by === 'name') {
76
- searchResult = searchResult.map((f) => (0, path_1.dirname)(f));
77
- }
78
77
  resolve(searchResult);
79
78
  });
80
79
  finder.on('error', (error) => {
@@ -82,6 +81,7 @@ function findBy(options) {
82
81
  });
83
82
  });
84
83
  }
84
+ exports.findBy = findBy;
85
85
  /**
86
86
  * Search for 'filename' starting from 'root'. Returns array of paths that contain the file.
87
87
  *
@@ -92,7 +92,10 @@ function findBy(options) {
92
92
  * @returns - array of paths that contain the filename
93
93
  */
94
94
  function findFiles(filename, root, excludeFolders, memFs) {
95
- return findBy({ query: filename, by: 'name', root, excludeFolders, memFs });
95
+ return __awaiter(this, void 0, void 0, function* () {
96
+ const results = yield findBy({ fileNames: [filename], root, excludeFolders, memFs });
97
+ return results.map((f) => (0, path_1.dirname)(f));
98
+ });
96
99
  }
97
100
  exports.findFiles = findFiles;
98
101
  /**
@@ -105,7 +108,7 @@ exports.findFiles = findFiles;
105
108
  * @returns - array of file paths that have the extension
106
109
  */
107
110
  function findFilesByExtension(extension, root, excludeFolders, memFs) {
108
- return findBy({ query: extension, by: 'extension', root, excludeFolders, memFs });
111
+ return findBy({ extensionNames: [extension], root, excludeFolders, memFs });
109
112
  }
110
113
  exports.findFilesByExtension = findFilesByExtension;
111
114
  /**
@@ -1,3 +1,3 @@
1
1
  export { fileExists, readFile, readJSON } from './file-access';
2
- export { findFiles, findFilesByExtension, findFileUp } from './file-search';
2
+ export { findBy, findFiles, findFilesByExtension, findFileUp } from './file-search';
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1,11 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.findFileUp = exports.findFilesByExtension = exports.findFiles = exports.readJSON = exports.readFile = exports.fileExists = void 0;
3
+ exports.findFileUp = exports.findFilesByExtension = exports.findFiles = exports.findBy = exports.readJSON = exports.readFile = exports.fileExists = void 0;
4
4
  var file_access_1 = require("./file-access");
5
5
  Object.defineProperty(exports, "fileExists", { enumerable: true, get: function () { return file_access_1.fileExists; } });
6
6
  Object.defineProperty(exports, "readFile", { enumerable: true, get: function () { return file_access_1.readFile; } });
7
7
  Object.defineProperty(exports, "readJSON", { enumerable: true, get: function () { return file_access_1.readJSON; } });
8
8
  var file_search_1 = require("./file-search");
9
+ Object.defineProperty(exports, "findBy", { enumerable: true, get: function () { return file_search_1.findBy; } });
9
10
  Object.defineProperty(exports, "findFiles", { enumerable: true, get: function () { return file_search_1.findFiles; } });
10
11
  Object.defineProperty(exports, "findFilesByExtension", { enumerable: true, get: function () { return file_search_1.findFilesByExtension; } });
11
12
  Object.defineProperty(exports, "findFileUp", { enumerable: true, get: function () { return file_search_1.findFileUp; } });
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { FileName } from './constants';
2
- export { findAllApps, findProjectRoot, getAppRootFromWebappPath, getAppProgrammingLanguage, getCapEnvironment, getCapModelAndServices, getCapProjectType, getWebappPath, isCapJavaProject, isCapNodeJsProject, loadModuleFromProject, readUi5Yaml } from './project';
2
+ export { findAllApps, findFioriArtifacts, findProjectRoot, getAppRootFromWebappPath, getAppProgrammingLanguage, getCapEnvironment, getCapModelAndServices, getCapProjectType, getWebappPath, isCapJavaProject, isCapNodeJsProject, loadModuleFromProject, readUi5Yaml } from './project';
3
3
  export * from './types';
4
4
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -14,11 +14,12 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.readUi5Yaml = exports.loadModuleFromProject = exports.isCapNodeJsProject = exports.isCapJavaProject = exports.getWebappPath = exports.getCapProjectType = exports.getCapModelAndServices = exports.getCapEnvironment = exports.getAppProgrammingLanguage = exports.getAppRootFromWebappPath = exports.findProjectRoot = exports.findAllApps = exports.FileName = void 0;
17
+ exports.readUi5Yaml = exports.loadModuleFromProject = exports.isCapNodeJsProject = exports.isCapJavaProject = exports.getWebappPath = exports.getCapProjectType = exports.getCapModelAndServices = exports.getCapEnvironment = exports.getAppProgrammingLanguage = exports.getAppRootFromWebappPath = exports.findProjectRoot = exports.findFioriArtifacts = exports.findAllApps = exports.FileName = void 0;
18
18
  var constants_1 = require("./constants");
19
19
  Object.defineProperty(exports, "FileName", { enumerable: true, get: function () { return constants_1.FileName; } });
20
20
  var project_1 = require("./project");
21
21
  Object.defineProperty(exports, "findAllApps", { enumerable: true, get: function () { return project_1.findAllApps; } });
22
+ Object.defineProperty(exports, "findFioriArtifacts", { enumerable: true, get: function () { return project_1.findFioriArtifacts; } });
22
23
  Object.defineProperty(exports, "findProjectRoot", { enumerable: true, get: function () { return project_1.findProjectRoot; } });
23
24
  Object.defineProperty(exports, "getAppRootFromWebappPath", { enumerable: true, get: function () { return project_1.getAppRootFromWebappPath; } });
24
25
  Object.defineProperty(exports, "getAppProgrammingLanguage", { enumerable: true, get: function () { return project_1.getAppProgrammingLanguage; } });
@@ -1,6 +1,6 @@
1
1
  export { getCapModelAndServices, getCapProjectType, isCapJavaProject, isCapNodeJsProject, getCapEnvironment } from './cap';
2
2
  export { getAppProgrammingLanguage } from './info';
3
3
  export { loadModuleFromProject } from './module-loader';
4
- export { findAllApps, findProjectRoot, getAppRootFromWebappPath } from './search';
4
+ export { findAllApps, findFioriArtifacts, findProjectRoot, getAppRootFromWebappPath } from './search';
5
5
  export { getWebappPath, readUi5Yaml } from './ui5-config';
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.readUi5Yaml = exports.getWebappPath = exports.getAppRootFromWebappPath = exports.findProjectRoot = exports.findAllApps = exports.loadModuleFromProject = exports.getAppProgrammingLanguage = exports.getCapEnvironment = exports.isCapNodeJsProject = exports.isCapJavaProject = exports.getCapProjectType = exports.getCapModelAndServices = void 0;
3
+ exports.readUi5Yaml = exports.getWebappPath = exports.getAppRootFromWebappPath = exports.findProjectRoot = exports.findFioriArtifacts = exports.findAllApps = exports.loadModuleFromProject = exports.getAppProgrammingLanguage = exports.getCapEnvironment = exports.isCapNodeJsProject = exports.isCapJavaProject = exports.getCapProjectType = exports.getCapModelAndServices = void 0;
4
4
  var cap_1 = require("./cap");
5
5
  Object.defineProperty(exports, "getCapModelAndServices", { enumerable: true, get: function () { return cap_1.getCapModelAndServices; } });
6
6
  Object.defineProperty(exports, "getCapProjectType", { enumerable: true, get: function () { return cap_1.getCapProjectType; } });
@@ -13,6 +13,7 @@ var module_loader_1 = require("./module-loader");
13
13
  Object.defineProperty(exports, "loadModuleFromProject", { enumerable: true, get: function () { return module_loader_1.loadModuleFromProject; } });
14
14
  var search_1 = require("./search");
15
15
  Object.defineProperty(exports, "findAllApps", { enumerable: true, get: function () { return search_1.findAllApps; } });
16
+ Object.defineProperty(exports, "findFioriArtifacts", { enumerable: true, get: function () { return search_1.findFioriArtifacts; } });
16
17
  Object.defineProperty(exports, "findProjectRoot", { enumerable: true, get: function () { return search_1.findProjectRoot; } });
17
18
  Object.defineProperty(exports, "getAppRootFromWebappPath", { enumerable: true, get: function () { return search_1.getAppRootFromWebappPath; } });
18
19
  var ui5_config_1 = require("./ui5-config");
@@ -1,4 +1,4 @@
1
- import type { AllAppResults, WorkspaceFolder } from '../types';
1
+ import type { AllAppResults, FioriArtifactTypes, FoundFioriArtifacts, WorkspaceFolder } from '../types';
2
2
  /**
3
3
  * Find root folder of the project containing the given file.
4
4
  *
@@ -16,9 +16,23 @@ export declare function findProjectRoot(path: string, sapuxRequired?: boolean, s
16
16
  export declare function getAppRootFromWebappPath(webappPath: string): Promise<string | null>;
17
17
  /**
18
18
  * Find all app that are supported by Fiori tools for a given list of roots (workspace folders).
19
+ * This is a convenient function to retrieve all apps. Same result can be achieved with call
20
+ * findFioriArtifacts({ wsFolders, artifacts: ['applications'] }); from same module.
19
21
  *
20
22
  * @param wsFolders - list of roots, either as vscode WorkspaceFolder[] or array of paths
21
23
  * @returns - results as path to apps plus files already parsed, e.g. manifest.json
22
24
  */
23
25
  export declare function findAllApps(wsFolders: WorkspaceFolder[] | string[] | undefined): Promise<AllAppResults[]>;
26
+ /**
27
+ * Find all requested Fiori artifacts like apps, adaptations, extensions, that are supported by Fiori tools, for a given list of roots (workspace folders).
28
+ *
29
+ * @param options - find options
30
+ * @param options.wsFolders - list of roots, either as vscode WorkspaceFolder[] or array of paths
31
+ * @param options.artifacts - list of artifacts to search for: 'application', 'adaptation', 'extension' see FioriArtifactTypes
32
+ * @returns - data structure containing the search results, for app e.g. as path to app plus files already parsed, e.g. manifest.json
33
+ */
34
+ export declare function findFioriArtifacts(options: {
35
+ wsFolders?: WorkspaceFolder[] | string[];
36
+ artifacts: FioriArtifactTypes[];
37
+ }): Promise<FoundFioriArtifacts>;
24
38
  //# sourceMappingURL=search.d.ts.map
@@ -9,13 +9,29 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.findAllApps = exports.getAppRootFromWebappPath = exports.findProjectRoot = void 0;
12
+ exports.findFioriArtifacts = exports.findAllApps = exports.getAppRootFromWebappPath = exports.findProjectRoot = void 0;
13
13
  const path_1 = require("path");
14
14
  const constants_1 = require("../constants");
15
15
  const file_1 = require("../file");
16
16
  const dependencies_1 = require("./dependencies");
17
17
  const cap_1 = require("./cap");
18
18
  const ui5_config_1 = require("./ui5-config");
19
+ /**
20
+ * Map artifact to file that is specific to the artifact type. Some artifacts can
21
+ * be identified by the same file, like app and library have file 'manifest.json'.
22
+ * Further filtering for specific artifact types happens in the filter{Artifact}
23
+ * functions.
24
+ */
25
+ const filterFileMap = {
26
+ applications: constants_1.FileName.Manifest,
27
+ adaptations: constants_1.FileName.ManifestAppDescrVar,
28
+ extensions: constants_1.FileName.ExtConfigJson,
29
+ libraries: constants_1.FileName.Manifest
30
+ };
31
+ /**
32
+ * Default folders to exclude from search.
33
+ */
34
+ const excludeFolders = ['.git', 'node_modules', 'dist'];
19
35
  /**
20
36
  * WorkspaceFolder type guard.
21
37
  *
@@ -26,39 +42,26 @@ function isWorkspaceFolder(value) {
26
42
  return value && value.length > 0 && value[0].uri !== undefined;
27
43
  }
28
44
  /**
29
- * Search all manifest.json files in given workspaces. This is used as starting point to find all tools
30
- * supported apps.
45
+ * Convert workspace root folders to root paths.
31
46
  *
32
- * @param wsFolders - workspace folders
33
- * @returns - array of path to manifest.json files
47
+ * @param wsFolders - list of roots, either as vscode WorkspaceFolder[] or array of paths
48
+ * @returns - root paths
34
49
  */
35
- function findAllManifest(wsFolders) {
36
- return __awaiter(this, void 0, void 0, function* () {
37
- // extract root path if provided as VSCode folder
38
- let wsRoots;
39
- if (wsFolders && isWorkspaceFolder(wsFolders)) {
40
- wsRoots = [];
41
- wsFolders
42
- .filter((each) => each.uri.scheme === 'file')
43
- .forEach((folder) => {
44
- wsRoots.push(folder.uri.fsPath);
45
- });
46
- }
47
- else {
48
- wsRoots = wsFolders || [];
49
- }
50
- // find all manifest files
51
- const manifests = [];
52
- for (const root of wsRoots) {
53
- try {
54
- manifests.push(...(yield (0, file_1.findFiles)(constants_1.FileName.Manifest, root, ['.git', 'node_modules', 'dist'])));
55
- }
56
- catch (_a) {
57
- // ignore exceptions during find
58
- }
59
- }
60
- return manifests;
61
- });
50
+ function wsFoldersToRootPaths(wsFolders) {
51
+ // extract root path if provided as VSCode folder
52
+ let wsRoots;
53
+ if (wsFolders && isWorkspaceFolder(wsFolders)) {
54
+ wsRoots = [];
55
+ wsFolders
56
+ .filter((each) => each.uri.scheme === 'file')
57
+ .forEach((folder) => {
58
+ wsRoots.push(folder.uri.fsPath);
59
+ });
60
+ }
61
+ else {
62
+ wsRoots = wsFolders || [];
63
+ }
64
+ return wsRoots;
62
65
  }
63
66
  /**
64
67
  * Find root folder of the project containing the given file.
@@ -211,32 +214,197 @@ function findRootsForPath(path) {
211
214
  }
212
215
  /**
213
216
  * Find all app that are supported by Fiori tools for a given list of roots (workspace folders).
217
+ * This is a convenient function to retrieve all apps. Same result can be achieved with call
218
+ * findFioriArtifacts({ wsFolders, artifacts: ['applications'] }); from same module.
214
219
  *
215
220
  * @param wsFolders - list of roots, either as vscode WorkspaceFolder[] or array of paths
216
221
  * @returns - results as path to apps plus files already parsed, e.g. manifest.json
217
222
  */
218
223
  function findAllApps(wsFolders) {
224
+ var _a;
225
+ return __awaiter(this, void 0, void 0, function* () {
226
+ const findResults = yield findFioriArtifacts({ wsFolders, artifacts: ['applications'] });
227
+ return (_a = findResults.applications) !== null && _a !== void 0 ? _a : [];
228
+ });
229
+ }
230
+ exports.findAllApps = findAllApps;
231
+ /**
232
+ * Filter Fiori apps from a list of files.
233
+ *
234
+ * @param pathMap - map of files. Key is the path, on first read parsed content will be set as value to prevent multiple reads of a file.
235
+ * @returns - results as path to apps plus files already parsed, e.g. manifest.json
236
+ */
237
+ function filterApplications(pathMap) {
238
+ var _a;
219
239
  return __awaiter(this, void 0, void 0, function* () {
220
240
  const result = [];
221
- const manifestPaths = yield findAllManifest(wsFolders);
241
+ const manifestPaths = Object.keys(pathMap).filter((path) => (0, path_1.basename)(path) === constants_1.FileName.Manifest);
222
242
  for (const manifestPath of manifestPaths) {
223
243
  try {
224
244
  // All UI5 apps have at least sap.app: { id: <ID>, type: "application" } in manifest.json
225
- const manifest = yield (0, file_1.readJSON)((0, path_1.join)(manifestPath, constants_1.FileName.Manifest));
245
+ (_a = pathMap[manifestPath]) !== null && _a !== void 0 ? _a : (pathMap[manifestPath] = yield (0, file_1.readJSON)(manifestPath));
246
+ const manifest = pathMap[manifestPath];
226
247
  if (!manifest['sap.app'] || !manifest['sap.app'].id || manifest['sap.app'].type !== 'application') {
227
248
  continue;
228
249
  }
229
250
  const roots = yield findRootsForPath(manifestPath);
230
- if (roots) {
251
+ if (roots && !(yield (0, file_1.fileExists)((0, path_1.join)(roots.appRoot, '.adp', constants_1.FileName.AdaptationConfig)))) {
231
252
  result.push({ appRoot: roots.appRoot, projectRoot: roots.projectRoot, manifest, manifestPath });
232
253
  }
233
254
  }
234
- catch (_a) {
255
+ catch (_b) {
235
256
  // ignore exceptions for invalid manifests
236
257
  }
237
258
  }
238
259
  return result;
239
260
  });
240
261
  }
241
- exports.findAllApps = findAllApps;
262
+ /**
263
+ * Filter adaptation projects from a list of files.
264
+ *
265
+ * @param pathMap - map of files. Key is the path, on first read parsed content will be set as value to prevent multiple reads of a file.
266
+ * @returns - results as array of found adaptation projects.
267
+ */
268
+ function filterAdaptations(pathMap) {
269
+ return __awaiter(this, void 0, void 0, function* () {
270
+ const results = [];
271
+ const manifestAppDescrVars = Object.keys(pathMap).filter((path) => path.endsWith(constants_1.FileName.ManifestAppDescrVar));
272
+ for (const manifestAppDescrVar of manifestAppDescrVars) {
273
+ const adpPath = yield (0, file_1.findFileUp)('.adp', (0, path_1.dirname)(manifestAppDescrVar));
274
+ if (adpPath && (yield (0, file_1.fileExists)((0, path_1.join)(adpPath, constants_1.FileName.AdaptationConfig)))) {
275
+ results.push({ appRoot: (0, path_1.dirname)(adpPath) });
276
+ }
277
+ }
278
+ return results;
279
+ });
280
+ }
281
+ /**
282
+ * Filter extensions projects from a list of files.
283
+ *
284
+ * @param pathMap - map of files. Key is the path, on first read parsed content will be set as value to prevent multiple reads of a file.
285
+ * @returns - results as array of found extension projects.
286
+ */
287
+ function filterExtensions(pathMap) {
288
+ var _a;
289
+ return __awaiter(this, void 0, void 0, function* () {
290
+ const results = [];
291
+ const extensionConfigs = Object.keys(pathMap).filter((path) => (0, path_1.basename)(path) === constants_1.FileName.ExtConfigJson);
292
+ for (const extensionConfig of extensionConfigs) {
293
+ try {
294
+ let manifest = null;
295
+ let manifestPath = Object.keys(pathMap).find((path) => path.startsWith((0, path_1.dirname)(extensionConfig) + path_1.sep) && (0, path_1.basename)(path) === constants_1.FileName.Manifest);
296
+ if (manifestPath) {
297
+ (_a = pathMap[manifestPath]) !== null && _a !== void 0 ? _a : (pathMap[manifestPath] = yield (0, file_1.readJSON)(manifestPath));
298
+ manifest = pathMap[manifestPath];
299
+ }
300
+ else {
301
+ const manifests = yield (0, file_1.findBy)({
302
+ fileNames: [constants_1.FileName.Manifest],
303
+ root: (0, path_1.dirname)(extensionConfig),
304
+ excludeFolders
305
+ });
306
+ if (manifests.length === 1) {
307
+ [manifestPath] = manifests;
308
+ manifest = yield (0, file_1.readJSON)(manifestPath);
309
+ }
310
+ }
311
+ if (manifestPath && manifest) {
312
+ results.push({ appRoot: (0, path_1.dirname)(extensionConfig), manifest, manifestPath });
313
+ }
314
+ }
315
+ catch (_b) {
316
+ // ignore exceptions for invalid manifests
317
+ }
318
+ }
319
+ return results;
320
+ });
321
+ }
322
+ /**
323
+ * Filter extensions projects from a list of files.
324
+ *
325
+ * @param pathMap - path to files
326
+ * @returns - results as array of found library projects.
327
+ */
328
+ function filterLibraries(pathMap) {
329
+ var _a;
330
+ return __awaiter(this, void 0, void 0, function* () {
331
+ const results = [];
332
+ const manifestPaths = Object.keys(pathMap).filter((path) => (0, path_1.basename)(path) === constants_1.FileName.Manifest);
333
+ for (const manifestPath of manifestPaths) {
334
+ try {
335
+ (_a = pathMap[manifestPath]) !== null && _a !== void 0 ? _a : (pathMap[manifestPath] = yield (0, file_1.readJSON)(manifestPath));
336
+ const manifest = pathMap[manifestPath];
337
+ if (manifest['sap.app'] && manifest['sap.app'].type === 'library') {
338
+ const packageJsonPath = yield (0, file_1.findFileUp)(constants_1.FileName.Package, (0, path_1.dirname)(manifestPath));
339
+ const projectRoot = packageJsonPath ? (0, path_1.dirname)(packageJsonPath) : null;
340
+ if (projectRoot && (yield (0, file_1.fileExists)((0, path_1.join)(projectRoot, constants_1.FileName.Ui5Yaml)))) {
341
+ results.push({ projectRoot, manifestPath, manifest });
342
+ }
343
+ }
344
+ }
345
+ catch (_b) {
346
+ // ignore exceptions for invalid manifests
347
+ }
348
+ }
349
+ return results;
350
+ });
351
+ }
352
+ /**
353
+ * Get the files to search for according to requested artifact type.
354
+ *
355
+ * @param artifacts - requests artifacts like apps, adaptations, extensions
356
+ * @returns - array of filenames to search for
357
+ */
358
+ function getFilterFileNames(artifacts) {
359
+ const uniqueFilterFiles = new Set();
360
+ for (const artifact of artifacts) {
361
+ if (filterFileMap[artifact]) {
362
+ uniqueFilterFiles.add(filterFileMap[artifact]);
363
+ }
364
+ }
365
+ return Array.from(uniqueFilterFiles);
366
+ }
367
+ /**
368
+ * Find all requested Fiori artifacts like apps, adaptations, extensions, that are supported by Fiori tools, for a given list of roots (workspace folders).
369
+ *
370
+ * @param options - find options
371
+ * @param options.wsFolders - list of roots, either as vscode WorkspaceFolder[] or array of paths
372
+ * @param options.artifacts - list of artifacts to search for: 'application', 'adaptation', 'extension' see FioriArtifactTypes
373
+ * @returns - data structure containing the search results, for app e.g. as path to app plus files already parsed, e.g. manifest.json
374
+ */
375
+ function findFioriArtifacts(options) {
376
+ return __awaiter(this, void 0, void 0, function* () {
377
+ const results = {};
378
+ const fileNames = getFilterFileNames(options.artifacts);
379
+ const wsRoots = wsFoldersToRootPaths(options.wsFolders);
380
+ const pathMap = {};
381
+ for (const root of wsRoots) {
382
+ try {
383
+ const foundFiles = yield (0, file_1.findBy)({
384
+ fileNames,
385
+ root,
386
+ excludeFolders
387
+ });
388
+ foundFiles.forEach((path) => (pathMap[path] = null));
389
+ }
390
+ catch (_a) {
391
+ // ignore exceptions during find
392
+ }
393
+ }
394
+ if (options.artifacts.includes('applications')) {
395
+ results.applications = yield filterApplications(pathMap);
396
+ }
397
+ if (options.artifacts.includes('adaptations')) {
398
+ results.adaptations = yield filterAdaptations(pathMap);
399
+ }
400
+ if (options.artifacts.includes('extensions')) {
401
+ results.extensions = yield filterExtensions(pathMap);
402
+ }
403
+ if (options.artifacts.includes('libraries')) {
404
+ results.libraries = yield filterLibraries(pathMap);
405
+ }
406
+ return results;
407
+ });
408
+ }
409
+ exports.findFioriArtifacts = findFioriArtifacts;
242
410
  //# sourceMappingURL=search.js.map
@@ -1,8 +1,82 @@
1
1
  import type { Manifest } from '../webapp';
2
+ export type FioriArtifactTypes = 'applications' | 'adaptations' | 'extensions' | 'libraries';
3
+ /**
4
+ * Search result when searching for apps. It is valid for all types of
5
+ * Fiori apps, like Fiori elements, UI5 freestyle, apps that are part
6
+ * of CAP projects.
7
+ */
2
8
  export interface AllAppResults {
9
+ /**
10
+ * Application root is where package.json and ui5.yaml resides.
11
+ */
3
12
  appRoot: string;
13
+ /**
14
+ * Project root is different from appRoot for CAP applications only,
15
+ * where the project root is the root of the CAP project. For all
16
+ * other applications it is the same as appRoot.
17
+ */
4
18
  projectRoot: string;
19
+ /**
20
+ * Path to the manifest.json, by default the webapp path but can be
21
+ * configured in ui5.yaml
22
+ */
5
23
  manifestPath: string;
24
+ /**
25
+ * Parsed content of the manifest.json to avoid multiple reads when working with
26
+ * the search results.
27
+ */
6
28
  manifest: Manifest;
7
29
  }
30
+ /**
31
+ * Search result when searching for adaptation projects.
32
+ */
33
+ export interface AdaptationResults {
34
+ /**
35
+ * Root of the adapted application where package.json and ui5.yaml resides.
36
+ */
37
+ appRoot: string;
38
+ }
39
+ /**
40
+ * Search result when searching for extension projects.
41
+ */
42
+ export interface ExtensionResults {
43
+ /**
44
+ * Root of the extended application where package.json and ui5.yaml resides.
45
+ */
46
+ appRoot: string;
47
+ /**
48
+ * Path to the manifest.json, by default the webapp path but can be
49
+ * configured in ui5.yaml
50
+ */
51
+ manifestPath: string;
52
+ /**
53
+ * Parsed content of the manifest.json to avoid multiple reads when working with
54
+ * the search results.
55
+ */
56
+ manifest: Manifest;
57
+ }
58
+ /**
59
+ * Search result when searching for libraries.
60
+ */
61
+ export interface LibraryResults {
62
+ /**
63
+ * Root of the library project, where package.json and ui5.yaml resides.
64
+ */
65
+ projectRoot: string;
66
+ /**
67
+ * Path to the manifest.json of the library.
68
+ */
69
+ manifestPath: string;
70
+ /**
71
+ * Parsed content of the manifest.json to avoid multiple reads when working with
72
+ * the search results.
73
+ */
74
+ manifest: Manifest;
75
+ }
76
+ export interface FoundFioriArtifacts {
77
+ applications?: AllAppResults[];
78
+ adaptations?: AdaptationResults[];
79
+ extensions?: ExtensionResults[];
80
+ libraries?: LibraryResults[];
81
+ }
8
82
  //# sourceMappingURL=index.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sap-ux/project-access",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "Library to access SAP Fiori tools projects",
5
5
  "repository": {
6
6
  "type": "git",