diff --git a/lib/Specification.js b/lib/Specification.js index 4dd3820f6..fc4ffe90e 100644 --- a/lib/Specification.js +++ b/lib/Specification.js @@ -6,28 +6,17 @@ * @param {object} parameters.configuration Configuration object to use */ module.exports = { - // async create(specParams) { - // if (!specParams.configuration) { - // throw new Error(`Unable to create Specification: No configuration provided`); - // } - // switch (specParams.configuration.kind) { - // case "project": - // return Project.create(specParams); - // case "extension": - // return Extension.create(specParams); - // default: - // throw new Error( - // `Encountered unexpected specification configuration of kind ${specParams.configuration.kind} ` + - // `Supported kinds are 'project' and 'extension'`); - // } - // } - async create(params) { - if (!["project", "extension"].includes(params.configuration.kind)) { - throw new Error(`Unable to create Specification instance: Unknown kind '${params.configuration.kind}'`); + if (!params.configuration) { + throw new Error( + `Unable to create Specification instance: Missing configuration parameter`); + } + const {kind, type} = params.configuration; + if (!["project", "extension"].includes(kind)) { + throw new Error(`Unable to create Specification instance: Unknown kind '${kind}'`); } - switch (params.configuration.type) { + switch (type) { case "application": { return createAndInitializeSpec("Application", params); } @@ -51,7 +40,7 @@ module.exports = { } default: throw new Error( - `Unable to create Specification instance: Unknown specification type '${params.configuration.type}'`); + `Unable to create Specification instance: Unknown specification type '${type}'`); } } }; diff --git a/lib/graph/Module.js b/lib/graph/Module.js index e70adafa5..d48845b89 100644 --- a/lib/graph/Module.js +++ b/lib/graph/Module.js @@ -61,9 +61,9 @@ class Module { if (shimCollection) { // Retrieve and clone shims in constructor // Shims added to the collection at a later point in time should not be applied in this module - const shims = shimCollection.getConfigurationShims(this.getId()); + const shims = shimCollection.getProjectConfigurationShims(this.getId()); if (shims && shims.length) { - this._configShims = clone(shims); + this._projectConfigShims = clone(shims); } } } @@ -91,8 +91,6 @@ class Module { async _getSpecifications() { const configs = await this._getConfigurations(); - // let project; - // const extensions = []; const specs = await Promise.all(configs.map(async (configuration) => { const spec = await Specification.create({ id: this.getId(), @@ -103,36 +101,6 @@ class Module { log.verbose(`Module ${this.getId()} contains ${spec.getKind()} ${spec.getName()}`); return spec; - - // switch (configuration.kind) { - // case "project": - // if (project) { - // throw new Error( - // `Invalid configuration for module ${this.getId()}: Per module there ` + - // `must be no more than one configuration of kind 'project'`); - // } - // log.verbose(`Module ${this.getId()} contains project ${configuration.getName()}`); - // project = await Project.create({ - // id: this.getId(), - // version: this.getVersion(), - // modulePath: this.getPath(), - // configuration - // }); - // break; - // case "extension": - // log.verbose(`Module ${this.getId()} contains extension ${configuration.getName()}`); - // extensions.push(new Extension({ - // id: this.getId(), - // version: this.getVersion(), - // modulePath: this.getPath(), - // configuration - // })); - // break; - // default: - // throw new Error( - // `Encountered unexpected specification configuration of kind ${configuration.kind} ` + - // `Supported kinds are 'project' and 'extension'`); - // } })); const projects = specs.filter((spec) => { @@ -172,29 +140,28 @@ class Module { return configurations || []; } - async _createConfigurationObject(config) { + async _normalizeAndApplyShims(config) { this._normalizeConfig(config); - if (config.kind === "project") { - this._applyShims(config); + + if (config.kind !== "project") { + this._applyProjectShims(config); } - // await this._validateConfig(config); return config; } async _createConfigurationFromShim() { - const config = this._applyShims(); + const config = this._applyProjectShims(); if (config) { this._normalizeConfig(config); - // await this._validateConfig(config); return config; } } - _applyShims(config = {}) { - if (!this._configShims) { + _applyProjectShims(config = {}) { + if (!this._projectConfigShims) { return; } - this._configShims.forEach(({name, shim}) => { + this._projectConfigShims.forEach(({name, shim}) => { log.verbose(`Applying project shim ${name} for module ${this.getId()}...`); Object.assign(config, shim); }); @@ -205,7 +172,7 @@ class Module { if (this._suppliedConfigs.length) { log.verbose(`Configuration for module ${this.getId()} has been supplied directly`); return await Promise.all(this._suppliedConfigs.map(async (config) => { - return this._createConfigurationObject(config); + return this._normalizeAndApplyShims(config); })); } } @@ -228,44 +195,8 @@ class Module { return []; } - // for (let i = configs.length - 1; i >= 0; i--) { - // this._normalizeConfig(configs[i]); - // } - - // const projectConfigs = configs.filter((config) => { - // return config.kind === "project"; - // }); - - // const extensionConfigs = configs.filter((config) => { - // return config.kind === "extension"; - // }); - - // // While a project can contain multiple configurations, - // // from a dependency tree perspective it is always a single project - // // This means it can represent one "project", plus multiple extensions or - // // one extension, plus multiple extensions - - // if (projectConfigs.length > 1) { - // throw new Error( - // `Found ${projectConfigs.length} configurations of kind 'project' for ` + - // `project ${this.getId()}. There is only one project per configuration allowed.`); - // } else if (projectConfigs.length === 0 && extensionConfigs.length === 0) { - // throw new Error( - // `Found ${configs.length} configurations for ` + - // `project ${this.getId()}. However, none of them are of kind 'project' or 'extension'.`); - // } - - // const configurations = []; - // if (projectConfigs.length) { - // configurations.push(await this._createConfigurationObject(projectConfigs[0])); - // } - - // await Promise.all(extensionConfigs.map(async (config) => { - // configurations.push(await this._createConfigurationObject(config)); - // })); - return await Promise.all(configs.map((config) => { - return this._createConfigurationObject(config); + return this._normalizeAndApplyShims(config); })); } @@ -361,34 +292,6 @@ class Module { return config; } - // async _validateConfig(config) { - // const moduleId = this.getId(); - // if (!moduleId.startsWith("@openui5/") && !moduleId.startsWith("@sapui5/")) { - // if (config.specVersion === "0.1" || config.specVersion === "1.0" || - // config.specVersion === "1.1") { - // throw new Error( - // `Unsupported specification version ${config.specVersion} defined in module ` + - // `${this.getId()}. The new Module API can only be used with specification versions >= 2.0. ` + - // `For details see https://sap.github.io/ui5-tooling/pages/Configuration/#specification-versions`); - // } - // if (config.specVersion !== "2.0" && - // config.specVersion !== "2.1" && config.specVersion !== "2.2" && - // config.specVersion !== "2.3") { - // throw new Error( - // `Unsupported specification version ${config.specVersion} defined in module ` + - // `${this.getId()}. Your UI5 CLI installation might be outdated. ` + - // `For details see https://sap.github.io/ui5-tooling/pages/Configuration/#specification-versions`); - // } - // } - - // await validate({ - // config, - // project: { - // id: moduleId - // } - // }); - // } - _isConfigValid(project) { if (!project.type) { if (project._isRoot) { diff --git a/lib/graph/ShimCollection.js b/lib/graph/ShimCollection.js index 5fb0e87f0..63ec2ca4b 100644 --- a/lib/graph/ShimCollection.js +++ b/lib/graph/ShimCollection.js @@ -14,19 +14,19 @@ function addToMap(name, fromMap, toMap) { class ShimCollection { constructor() { - this._configShims = {}; + this._projectConfigShims = {}; this._dependencyShims = {}; this._collectionShims = {}; } - addShim(shimExtension) { + addProjectShim(shimExtension) { const name = shimExtension.getName(); log.verbose(`Adding new shim ${name}...`); // TODO: Move this into a dedicated ShimConfiguration class? const config = shimExtension.getConfigurationObject(); const {configurations, dependencies, collections} = config.shims; if (configurations) { - addToMap(name, configurations, this._configShims); + addToMap(name, configurations, this._projectConfigShims); } if (dependencies) { addToMap(name, dependencies, this._dependencyShims); @@ -36,8 +36,8 @@ class ShimCollection { } } - getConfigurationShims(moduleId) { - return this._configShims[moduleId]; + getProjectConfigurationShims(moduleId) { + return this._projectConfigShims[moduleId]; } getAllDependencyShims() { diff --git a/lib/graph/projectGraphBuilder.js b/lib/graph/projectGraphBuilder.js index 0495b546b..0826cccca 100644 --- a/lib/graph/projectGraphBuilder.js +++ b/lib/graph/projectGraphBuilder.js @@ -9,7 +9,7 @@ function _handleExtensions(graph, shimCollection, extensions) { const type = extension.getType(); switch (type) { case "project-shim": - shimCollection.addShim(extension); + shimCollection.addProjectShim(extension); break; case "task": case "server-middleware": diff --git a/lib/specifications/configurations/AbstractConfiguration.js b/lib/specifications/configurations/AbstractConfiguration.js deleted file mode 100644 index c1f197d2a..000000000 --- a/lib/specifications/configurations/AbstractConfiguration.js +++ /dev/null @@ -1,38 +0,0 @@ -/* -* Private configuration class for use in specifications -*/ - -class AbstractConfiguration { - /** - * @param {object} parameters - * @param {object} parameters.specification Specification instance - * @param {object} parameters.configObject Configuration object - */ - constructor({configObject, specification}) { - this._config = configObject; - this._specification = specification; - } - - async init() { - /* to be implemented by subclasses where needed*/ - return this; - } - - getName() { - return this._config.metadata.name; - } - - getKind() { - return this._config.kind; - } - - getType() { - return this._config.type; - } - - getObject() { - return this._config; - } -} - -module.exports = AbstractConfiguration; diff --git a/lib/specifications/configurations/Application.js b/lib/specifications/configurations/Application.js deleted file mode 100644 index 1f2b14c21..000000000 --- a/lib/specifications/configurations/Application.js +++ /dev/null @@ -1,13 +0,0 @@ -const AbstractConfiguration = require("./AbstractConfiguration"); - -/* -* Private configuration class for use in Module and specifications -*/ - -class Application extends AbstractConfiguration { - async init() { - - } -} - -module.exports = Application; diff --git a/lib/specifications/types/Application.js b/lib/specifications/types/Application.js index f65adb455..d218ca57e 100644 --- a/lib/specifications/types/Application.js +++ b/lib/specifications/types/Application.js @@ -45,7 +45,7 @@ class Application extends Project { getBuildtimeReader() { return resourceFactory.createReader({ fsBasePath: path.join(this.getPath(), this._webappPath), - virBasePath: "/resources" + this.getNamespace(), + virBasePath: `/resources/${this.getNamespace()}/`, name: `Source reader for ${this.getType()} ${this.getKind()} ${this.getName()}` }); } diff --git a/test/lib/specifications/Project.js b/test/lib/specifications/Project.js index 0f5ef5765..4eee1d6fa 100644 --- a/test/lib/specifications/Project.js +++ b/test/lib/specifications/Project.js @@ -1,40 +1,34 @@ const test = require("ava"); const path = require("path"); -const Project = require("../../../lib/specifications/Project"); -const Configuration = require("../../../lib/specifications/Configuration"); +const Specification = require("../../../lib/Specification"); const applicationAPath = path.join(__dirname, "..", "..", "fixtures", "application.a"); - -test.beforeEach(async (t) => { - t.context.basicConfiguration = new Configuration({ +const basicProjectInput = { + id: "application.a.id", + version: "1.0.0", + modulePath: applicationAPath, + configuration: { specVersion: "2.3", kind: "project", type: "application", metadata: {name: "application.a"} - }); - - t.context.basicProjectInput = { - id: "application.a.id", - version: "1.0.0", - modulePath: applicationAPath, - configuration: t.context.basicConfiguration - }; -}); + } +}; test("Instantiate a basic project", async (t) => { - const project = new Project(t.context.basicProjectInput); + const project = await Specification.create(basicProjectInput); t.is(project.getName(), "application.a", "Returned correct name"); t.is(project.getVersion(), "1.0.0", "Returned correct version"); t.is(project.getPath(), applicationAPath, "Returned correct project path"); }); -test("_getConfiguration", async (t) => { - const project = new Project(t.context.basicProjectInput); - t.is(await project._getConfiguration(), t.context.basicConfiguration, "Returned correct configuration instance"); +test("Configurations", async (t) => { + const project = await Specification.create(basicProjectInput); + t.is(project.getKind(), "project", "Returned correct kind configuration"); }); test("Access project root resources via reader", async (t) => { - const project = new Project(t.context.basicProjectInput); + const project = await Specification.create(basicProjectInput); const rootReader = await project.getRootReader(); const packageJsonResource = await rootReader.byPath("/package.json"); t.is(packageJsonResource.getPath(), "/package.json", "Successfully retrieved root resource");