Skip to content

Commit f586d8c

Browse files
committed
[FEATURE][PoC] Add UI5 Workspace support
Implementing UI5/cli#157
1 parent 198aa78 commit f586d8c

File tree

2 files changed

+115
-1
lines changed

2 files changed

+115
-1
lines changed

lib/graph/Workspace.js

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import fs from "graceful-fs";
2+
import path from "node:path";
3+
import {promisify} from "node:util";
4+
import logger from "@ui5/logger";
5+
6+
const readFile = promisify(fs.readFile);
7+
const log = logger.getLogger("graph:Workspace");
8+
9+
/**
10+
* Workspace representation
11+
*
12+
* @public
13+
* @class
14+
* @alias @ui5/project/graph/Workspace
15+
*/
16+
class Workspace {
17+
/**
18+
* @param {object} options
19+
* @param {object} options.cwd
20+
* @param {object} options.workspaceConfiguration Workspace configuration
21+
* @param {string} options.workspaceConfiguration.specVersion
22+
* @param {object} options.workspaceConfiguration.metadata
23+
* @param {object} options.workspaceConfiguration.dependencyManagement
24+
*/
25+
constructor({cwd, workspaceConfiguration}) {
26+
const {specVersion, metadata, dependencyManagement} = workspaceConfiguration;
27+
if (!cwd || !specVersion || !metadata?.name) {
28+
throw new Error("[Workspace] One or more mandatory parameters not provided");
29+
}
30+
31+
this._name = metadata.name;
32+
this._cwd = cwd;
33+
this._dependencyManagement = dependencyManagement;
34+
}
35+
36+
async getNode(id) {
37+
const nodes = await this._resolveDependencyResolutionPaths();
38+
return nodes[id];
39+
}
40+
41+
_getResolvedNodes() {
42+
if (this._pResolvedNodes) {
43+
return this._pResolvedNodes;
44+
}
45+
46+
return this._pResolvedNodes = this._resolveNodes();
47+
}
48+
async _resolveNodes() {
49+
if (!this._dependencyManagement?.resolutions?.length) {
50+
return [];
51+
}
52+
53+
const resolvedNodes = await Promise.all(this._dependencyManagement.resolutions.map(async (resolutionConfig) => {
54+
if (!resolutionConfig.path) {
55+
throw new Error(
56+
`Missing property 'path' in dependency resolution configuration of workspace ${this._name}`);
57+
}
58+
const nodes = await this._getNodesFromPath(resolutionConfig.path);
59+
60+
if (!Array.isArray(nodes) && resolutionConfig.configuration) {
61+
nodes.configuration = resolutionConfig.configuration;
62+
}
63+
return nodes;
64+
}));
65+
66+
// Flatten array since workspaces might have lead to nested arrays
67+
return Array.prototype.concat.apply([], resolvedNodes);
68+
}
69+
70+
async _getNodesFromPath(cwd, relPath, resolveWorkspace = true) {
71+
const nodePath = path.join(this._cwd, relPath);
72+
const pkg = await this._readPackageJson(nodePath);
73+
if (pkg.workspaces?.length) {
74+
if (!resolveWorkspace) {
75+
log.info(`Ignoring nested package workspace of module ${pkg.name} at ${nodePath}`);
76+
return [];
77+
}
78+
return Promise.all(pkg.workspaces.map(async (workspacePath) => {
79+
const nodes = this._getNodesFromPath(nodePath, workspacePath, false);
80+
if (nodes.lengh > 1) {
81+
throw new Error(
82+
`Package workspace of module ${pkg.name} at ${nodePath} ` +
83+
`unexpectedly resolved to multiple modules`);
84+
}
85+
return nodes[0];
86+
}));
87+
} else {
88+
return this._getNodeFromPackage(pkg, nodePath);
89+
}
90+
}
91+
92+
_getNodeFromPackage(pkg, path) {
93+
return {
94+
id: pkg.name,
95+
version: pkg.version,
96+
path: path
97+
};
98+
}
99+
100+
/**
101+
* Reads the package.json file and returns its content
102+
*
103+
* @private
104+
* @param {string} modulePath Path to the module containing the package.json
105+
* @returns {object} Package json content
106+
*/
107+
async _readPackageJson(modulePath) {
108+
const content = await readFile(path.join(modulePath, "package.json"), "utf8");
109+
return JSON.parse(content);
110+
}
111+
}
112+
113+
export default Workspace;

lib/graph/projectGraphBuilder.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,10 @@ function validateNode(node) {
9595
* @function default
9696
* @static
9797
* @param {@ui5/project/graph/ProjectGraphBuilder~NodeProvider} nodeProvider
98+
* @param {@ui5/project/graph/Workspace} workspace
9899
* @returns {@ui5/project/graph/ProjectGraph} A new project graph instance
99100
*/
100-
async function projectGraphBuilder(nodeProvider) {
101+
async function projectGraphBuilder(nodeProvider, workspace) {
101102
const shimCollection = new ShimCollection();
102103
const moduleCollection = {};
103104

0 commit comments

Comments
 (0)