Skip to content

Commit

Permalink
[FIX] ui5Framework: Prevent install of libraries within workspace
Browse files Browse the repository at this point in the history
  • Loading branch information
matz3 committed Mar 10, 2023
1 parent 9b414a7 commit 2e5306d
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 4 deletions.
67 changes: 64 additions & 3 deletions lib/graph/helpers/ui5Framework.js
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,57 @@ const utils = {
);
}
},
/**
* This logic needs to stay in sync with the @sapui5/distribution-metadata package
*
* @param project
*/
async getFrameworkLibraryDependencies(project) {
let dependencies = [];
let optionalDependencies = [];

if (project.__id.startsWith("@sapui5/")) {
project.getFrameworkDependencies().forEach((dependency) => {
if (dependency.optional) {
// Add optional dependency to optionalDependencies
optionalDependencies.push(dependency.name);
} else if (!dependency.development) {
// Add non-development dependency to dependencies
dependencies.push(dependency.name);
}
});
} else if (project.__id.startsWith("@openui5/")) {
const packageResource = await project.getRootReader().byPath("/package.json");
const packageInfo = JSON.parse(await packageResource.getString());

dependencies = Object.keys(
packageInfo.dependencies || {}
).map(($) => $.replace("@openui5/", "")); // @sapui5 dependencies must not be defined in package.json
optionalDependencies = Object.keys(
packageInfo.devDependencies || {}
).map(($) => $.replace("@openui5/", "")); // @sapui5 dependencies must not be defined in package.json
}

return {dependencies, optionalDependencies};
},

async getWorkspaceFrameworkLibraryMetadata({workspace, projectGraph}) {
const libraryMetadata = Object.create(null);
const {projectNameMap} = await workspace._getResolvedModules(); // TODO: private API usage
for (const ui5Module of projectNameMap.values()) {
const {project} = await ui5Module.getSpecifications();
if (project.isFrameworkProject?.() && !projectGraph.getProject(project.getName())) {
const metadata = libraryMetadata[project.getName()] = Object.create(null);
metadata.id = project.__id;
metadata.path = project.getRootPath();
metadata.version = project.getVersion();
const {dependencies, optionalDependencies} = await utils.getFrameworkLibraryDependencies(project);
metadata.dependencies = dependencies;
metadata.optionalDependencies = optionalDependencies;
}
}
return libraryMetadata;
},
ProjectProcessor
};

Expand All @@ -232,6 +283,7 @@ export default {
* Promise resolving with the given graph instance to allow method chaining
*/
enrichProjectGraph: async function(projectGraph, options = {}) {
const {workspace} = options;
const rootProject = projectGraph.getRoot();
const frameworkName = rootProject.getFrameworkName();
const frameworkVersion = rootProject.getFrameworkVersion();
Expand All @@ -242,6 +294,8 @@ export default {
let version = options.versionOverride || frameworkVersion;

if (rootProject.isFrameworkProject() && !version) {
// TODO: Also take workspace into account

// If the root project is a framework project and no framework version is defined,
// all framework dependencies must already be part of the graph
rootProject.getFrameworkDependencies().forEach((dep) => {
Expand Down Expand Up @@ -298,14 +352,21 @@ export default {

log.info(`Using ${frameworkName} version: ${version}`);

const resolver = new Resolver({cwd: rootProject.getRootPath(), version});
const resolver = new Resolver({cwd: rootProject.getRootPath(), version, workspace});

let startTime;
if (log.isLevelEnabled("verbose")) {
startTime = process.hrtime();
}

const {libraryMetadata} = await resolver.install(referencedLibraries);
let workspaceFrameworkLibraryMetadata;
if (workspace) {
workspaceFrameworkLibraryMetadata = await utils.getWorkspaceFrameworkLibraryMetadata({
workspace, projectGraph
});
}

const {libraryMetadata} = await resolver.install(referencedLibraries, workspaceFrameworkLibraryMetadata);

if (log.isLevelEnabled("verbose")) {
const timeDiff = process.hrtime(startTime);
Expand All @@ -322,7 +383,7 @@ export default {
const projectProcessor = new utils.ProjectProcessor({
libraryMetadata,
graph: frameworkGraph,
workspace: options.workspace
workspace
});

await Promise.all(referencedLibraries.map(async (libName) => {
Expand Down
6 changes: 5 additions & 1 deletion lib/ui5Framework/AbstractResolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,15 @@ class AbstractResolver {
*
* @public
* @param {string[]} libraryNames List of library names to be installed
* @param {object} [initialLibraryMetadata] Initial libraryMetadata object to be used
* @returns {@ui5/project/ui5Framework/AbstractResolver~ResolverInstallResult}
* Resolves with an object containing the <code>libraryMetadata</code>
*/
async install(libraryNames) {
async install(libraryNames, initialLibraryMetadata) {
const libraryMetadata = Object.create(null);
if (initialLibraryMetadata) {
Object.assign(libraryMetadata, initialLibraryMetadata);
}
const errors = [];

await this._processLibraries(libraryNames, libraryMetadata, errors);
Expand Down

0 comments on commit 2e5306d

Please sign in to comment.