From 69c03b87aa42d37650e0d99a016957d6ce7064e4 Mon Sep 17 00:00:00 2001 From: Merlin Beutlberger Date: Fri, 16 Dec 2022 18:06:27 +0100 Subject: [PATCH 01/18] [INTERNAL][POC] Add Configuration.js --- lib/config/Configuration.js | 64 +++++++++++++++++++++++++++++++++++++ package.json | 1 + 2 files changed, 65 insertions(+) create mode 100644 lib/config/Configuration.js diff --git a/lib/config/Configuration.js b/lib/config/Configuration.js new file mode 100644 index 000000000..f6d8495ff --- /dev/null +++ b/lib/config/Configuration.js @@ -0,0 +1,64 @@ +import path from "node:path"; +import os from "node:os"; + +/** + * + * + * @public + * @class + * @alias @ui5/project/config/Configuration + */ +class Configuration { + /** + * @param {object} configuration + * @param {string} [configuration.baseDir="~/.ui5/"] + * @param {string} [configuration.frameworkDir="~/${baseDir}/framework"] + * Directory to store framework artifacts and metadata in. + * @param {string} [configuration.buildCacheDir="~/${baseDir}/build-cache"] + * Directory to store build-cache in. + */ + constructor({baseDir, frameworkDir, buildCacheDir}) { + this._baseDir = baseDir ? path.resolve(baseDir) : path.join(os.homedir(), ".ui5"); + this._frameworkDir = frameworkDir ? path.resolve(frameworkDir) : path.join(this._baseDir, "framework"); + this._buildCacheDir = buildCacheDir ? path.resolve(buildCacheDir) : path.join(this._baseDir, "build-cache"); + } + + getFrameworkDir() { + return this._frameworkDir; + } + + getCacheDir() { + return this._buildCacheDir; + } +} + +export default Configuration; + +/** + * Create Configuration from JSON file + * + * @public + * @static + * @param {string} [filePath="~/.ui5rc"] Path to configuration JSON file + * @returns {@ui5/project/config/Configuration} Configuration instance + */ +export async function fromFile(filePath) { + filePath = filePath || path.join(os.homedir(), ".ui5rc"); + + const {default: fs} = await import("graceful-fs"); + const {promisify} = await import("node:util"); + const readFile = promisify(fs.readFile); + let config; + try { + const fileContent = await readFile(filePath); + config = JSON.parse(fileContent); + } catch (err) { + if (err.code === "ENOENT") { // "File or directory does not exist" + config = {}; + } else { + throw err; + } + } + return new Configuration(config); +} + diff --git a/package.json b/package.json index 9b2a1cb00..a1f0ccdde 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ ], "type": "module", "exports": { + "./config/Configuration": "./lib/config/Configuration.js", "./specifications/Specification": "./lib/specifications/Specification.js", "./specifications/SpecificationVersion": "./lib/specifications/SpecificationVersion.js", "./ui5Framework/Sapui5MavenSnapshotResolver": "./lib/ui5Framework/Sapui5MavenSnapshotResolver.js", From 838b00dd1213f68a7fce3b1f5786001d7fd1a0b9 Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Thu, 2 Mar 2023 11:36:54 +0200 Subject: [PATCH 02/18] Move configuration from https://github.com/SAP/ui5-project/pull/570 --- lib/config/Configuration.js | 290 +++++++++++++++++++++++++++++-- test/lib/config/Configuration.js | 229 ++++++++++++++++++++++++ 2 files changed, 508 insertions(+), 11 deletions(-) create mode 100644 test/lib/config/Configuration.js diff --git a/lib/config/Configuration.js b/lib/config/Configuration.js index f6d8495ff..697b5ba9b 100644 --- a/lib/config/Configuration.js +++ b/lib/config/Configuration.js @@ -1,6 +1,15 @@ import path from "node:path"; import os from "node:os"; +/** + * @public + * @typedef @ui5/project/config/Configuration~cacheMode + * @property {string} "default" Cache everything, invalidate after 9 hours + * @property {string} "off" Do not cache + * @property {string} "force" Use cache only - no requests + * @property {string} "relaxed" Try to refresh, but fallback to cache if refresh fails for up to one week + */ + /** * * @@ -8,27 +17,224 @@ import os from "node:os"; * @class * @alias @ui5/project/config/Configuration */ -class Configuration { +export class Configuration { + #cwd; + #sources; + #version; + #cacheMode; + #ui5HomeDir; + #snapshotEndpointUrl; + #frameworkDir; + #artifactsDir; + #packagesDir; + #metadataDir; + #stagingDir; + #lockDir; + #cacheDir; + /** * @param {object} configuration - * @param {string} [configuration.baseDir="~/.ui5/"] - * @param {string} [configuration.frameworkDir="~/${baseDir}/framework"] + * @param {string} [configuration.cwd="./"] + * @param {string} [configuration.version=""] + * @param {string} [configuration.sources=false] + * @param {string} [configuration.ui5HomeDir="~/.ui5/"] + * @param {string} [configuration.snapshotEndpointUrl=""] + * @param {@ui5/project/config/Configuration~cacheMode} [configuration.cacheMode="default"] + * @param {string} [configuration.frameworkDir="~/${ui5HomeDir}/framework"] * Directory to store framework artifacts and metadata in. - * @param {string} [configuration.buildCacheDir="~/${baseDir}/build-cache"] - * Directory to store build-cache in. + * @param {string} [configuration.cacheDir="~/${ui5HomeDir}/cacache"] + * @param {string} [configuration.artifactsDir="~/${ui5HomeDir}/artifacts"] + * @param {string} [configuration.packagesDir="~/${ui5HomeDir}/packages"] + * @param {string} [configuration.metadataDir="~/${ui5HomeDir}/metadata"] + * @param {string} [configuration.stagingDir="~/${ui5HomeDir}/staging"] + * @param {string} [configuration.lockDir="~/${ui5HomeDir}/locks"] + */ + constructor({ + cwd, + version, + sources, + ui5HomeDir, + snapshotEndpointUrl, + cacheMode = "default", + frameworkDir, + cacheDir, + artifactsDir, + packagesDir, + metadataDir, + stagingDir, + lockDir + }) { + this.#cwd = cwd ? path.resolve(cwd) : process.cwd(); + this.#sources = !!sources; + this.#version = version; + this.#cacheMode = cacheMode; + this.#ui5HomeDir = ui5HomeDir ? path.resolve(ui5HomeDir) : path.join(os.homedir(), ".ui5"); + + this.#snapshotEndpointUrl = process.env.UI5_MAVEN_SNAPSHOT_ENDPOINT || snapshotEndpointUrl; + this.#frameworkDir = frameworkDir ? path.resolve(frameworkDir) : path.join(this.#ui5HomeDir, "framework"); + this.#artifactsDir = artifactsDir ? + path.resolve(artifactsDir) : path.join(this.#frameworkDir, "artifacts"); + this.#packagesDir = packagesDir ? + path.resolve(packagesDir) : path.join(this.#frameworkDir, "packages"); + this.#metadataDir = metadataDir ? + path.resolve(metadataDir) : path.join(this.#frameworkDir, "metadata"); + this.#stagingDir = stagingDir ? path.resolve(stagingDir) : path.join(this.#frameworkDir, "staging"); + this.#lockDir = lockDir ? path.resolve(lockDir) : path.join(this.#frameworkDir, "locks"); + this.#cacheDir = cacheDir ? path.resolve(cacheDir) : path.join(this.#frameworkDir, "cacache"); + } + + /** + * CWD path + * + * @public + * @returns {string} */ - constructor({baseDir, frameworkDir, buildCacheDir}) { - this._baseDir = baseDir ? path.resolve(baseDir) : path.join(os.homedir(), ".ui5"); - this._frameworkDir = frameworkDir ? path.resolve(frameworkDir) : path.join(this._baseDir, "framework"); - this._buildCacheDir = buildCacheDir ? path.resolve(buildCacheDir) : path.join(this._baseDir, "build-cache"); + getCwd() { + return this.#cwd; } + /** + * Prebuild or source files + * + * TODO: Private for now until we decide on how to handle this properly + * + * @private + * @returns {boolean} + */ + getSources() { + return this.#sources; + } + + /** + * UI5 Version + * + * @public + * @returns {string} + */ + getVersion() { + return this.#version; + } + + /** + * Cache mode + * + * @public + * @returns {string} + */ + getCacheMode() { + return this.#cacheMode; + } + + /** + * .ui5 home direcotry + * + * @public + * @returns {string} + */ + getUi5HomeDir() { + return this.#ui5HomeDir; + } + + /** + * SNAPSHOTs URL + * + * @public + * @returns {string} + */ + getSnapshotEndpointUrl() { + return this.#snapshotEndpointUrl; + } + + /** + * Directory to store framework artifacts and metadata in. + * + * @public + * @returns {string} + */ getFrameworkDir() { - return this._frameworkDir; + return this.#frameworkDir; + } + + /** + * Directory to store artifacts in. + * + * @public + * @returns {string} + */ + getArtifactsDir() { + return this.#artifactsDir; + } + + /** + * Directory to packages in + * + * @public + * @returns {string} + */ + getPackagesDir() { + return this.#packagesDir; } + /** + * Directory to store metadata in + * + * @public + * @returns {string} + */ + getMetadataDir() { + return this.#metadataDir; + } + + /** + * Directory to store staging artifacts in + * + * @public + * @returns {string} + */ + getStagingDir() { + return this.#stagingDir; + } + + /** + * Lockfiles directory + * + * @public + * @returns {string} + */ + getLockDir() { + return this.#lockDir; + } + + /** + * Cache directory + * + * @public + * @returns {string} + */ getCacheDir() { - return this._buildCacheDir; + return this.#cacheDir; + } + + /** + * @public + * @returns {object} The configuration in a JSON format + */ + toJSON() { + return { + cwd: this.#cwd, + sources: this.#sources, + version: this.#version, + cacheMode: this.#cacheMode, + ui5HomeDir: this.#ui5HomeDir, + snapshotEndpointUrl: this.#snapshotEndpointUrl, + frameworkDir: this.#frameworkDir, + artifactsDir: this.#artifactsDir, + packagesDir: this.#packagesDir, + metadataDir: this.#metadataDir, + stagingDir: this.#stagingDir, + lockDir: this.#lockDir, + cacheDir: this.#cacheDir, + }; } } @@ -62,3 +268,65 @@ export async function fromFile(filePath) { return new Configuration(config); } +/** + * Save Configuration to a JSON file + * + * @public + * @static + * @param {string} [filePath="~/.ui5rc"] Path to configuration JSON file + * @param {@ui5/project/config/Configuration} config Configuration to save + */ +export async function saveConfig(filePath, config) { + filePath = filePath || path.join(os.homedir(), ".ui5rc"); + + const {default: fs} = await import("graceful-fs"); + const {promisify} = await import("node:util"); + const writeFile = promisify(fs.writeFile); + + return writeFile(filePath, JSON.stringify(config.toJSON())); +} + + +export async function resolveSnapshotEndpointUrl(settingsXML, skipConfirmation) { + let ok = true; + if (!skipConfirmation) { + const {default: yesno} = await import("yesno"); + ok = await yesno({ + question: + "SnapshotURL is missing. " + + "Do you want to try to resolve it from ~/.m2/settings.xml? (yes)", + defaultValue: true, + }); + } + + settingsXML = settingsXML || path.join(os.homedir(), ".m2", "settings.xml"); + const {default: fs} = await import("graceful-fs"); + const {promisify} = await import("node:util"); + const readFile = promisify(fs.readFile); + const xml2js = await import("xml2js"); + const parser = new xml2js.Parser({ + // explicitChildren: true, + preserveChildrenOrder: true, + xmlns: true + }); + let xmlContents; + + try { + const fileContent = await readFile(settingsXML); + xmlContents = await parser.parseStringPromise(fileContent); + } catch (err) { + if (err.code === "ENOENT") { // "File or directory does not exist" + xmlContents = null; + } else { + throw err; + } + } + + if (!ok || !xmlContents) { + throw new Error("SnapshotURL not resolved"); + } + + return xmlContents?.settings?.profiles[0]?.profile + .filter((prof)=> prof.id[0]._ === "snapshot.build")[0] + .pluginRepositories[0].pluginRepository[0].url[0]._; +} diff --git a/test/lib/config/Configuration.js b/test/lib/config/Configuration.js new file mode 100644 index 000000000..421d63da4 --- /dev/null +++ b/test/lib/config/Configuration.js @@ -0,0 +1,229 @@ +import test from "ava"; +import sinonGlobal from "sinon"; +import esmock from "esmock"; + +test.beforeEach(async (t) => { + const sinon = t.context.sinon = sinonGlobal.createSandbox(); + + t.context.homedirStub = sinon.stub().returns("~"); + t.context.promisifyStub = sinon.stub(); + t.context.yesnoStub = sinon.stub(); + t.context.resolveStub = sinon.stub().callsFake((path) => path); + t.context.joinStub = sinon.stub().callsFake((...args) => args.join("/")); + t.context.Configuration = await esmock.p("../../../lib/config/Configuration.js", { + "node:path": { + resolve: t.context.resolveStub, + join: t.context.joinStub + }, + "yesno": t.context.yesnoStub, + "node:util": { + "promisify": t.context.promisifyStub + }, + "node:os": { + "homedir": t.context.homedirStub + } + }); +}); + +test.afterEach.always((t) => { + t.context.sinon.restore(); + esmock.purge(t.context.Configuration); +}); + +test.serial("Build configuration with defaults", (t) => { + const {Configuration} = t.context.Configuration; + + const config = new Configuration({cwd: "/"}); + + t.deepEqual(config.toJSON(), { + artifactsDir: "~/.ui5/framework/artifacts", + cacheDir: "~/.ui5/framework/cacache", + cacheMode: "default", + cwd: "/", + frameworkDir: "~/.ui5/framework", + lockDir: "~/.ui5/framework/locks", + metadataDir: "~/.ui5/framework/metadata", + packagesDir: "~/.ui5/framework/packages", + snapshotEndpointUrl: undefined, + sources: false, + stagingDir: "~/.ui5/framework/staging", + ui5HomeDir: "~/.ui5", + version: undefined, + }); +}); + + +test.serial("Overwrite defaults defaults", (t) => { + const {Configuration} = t.context.Configuration; + + const params = { + artifactsDir: "/custom-location/artifacts", + cacheDir: "/custom-location/cacache", + cacheMode: "force", + cwd: "/", + frameworkDir: "/custom-location/framework", + lockDir: "/custom-location/locks", + metadataDir: "/custom-location/metadata", + packagesDir: "/custom-location/packages", + snapshotEndpointUrl: undefined, + sources: true, + stagingDir: "/custom-location/staging", + ui5HomeDir: "/custom-location", + version: "1.99.0-SNAPSHOT" + }; + + const config = new Configuration(params); + + t.deepEqual(config.toJSON(), params); +}); + +test.serial("Check getters", (t) => { + const {Configuration} = t.context.Configuration; + + const params = { + artifactsDir: "/custom-location/artifacts", + cacheDir: "/custom-location/cacache", + cacheMode: "force", + cwd: "/", + frameworkDir: "/custom-location/framework", + lockDir: "/custom-location/locks", + metadataDir: "/custom-location/metadata", + packagesDir: "/custom-location/packages", + snapshotEndpointUrl: undefined, + sources: true, + stagingDir: "/custom-location/staging", + ui5HomeDir: "/custom-location", + version: "1.99.0-SNAPSHOT" + }; + + const config = new Configuration(params); + + t.is(config.getArtifactsDir(), params.artifactsDir); + t.is(config.getCacheDir(), params.cacheDir); + t.is(config.getCacheMode(), params.cacheMode); + t.is(config.getCwd(), params.cwd); + t.is(config.getFrameworkDir(), params.frameworkDir); + t.is(config.getLockDir(), params.lockDir); + t.is(config.getMetadataDir(), params.metadataDir); + t.is(config.getPackagesDir(), params.packagesDir); + t.is(config.getSnapshotEndpointUrl(), params.snapshotEndpointUrl); + t.is(config.getSources(), params.sources); + t.is(config.getStagingDir(), params.stagingDir); + t.is(config.getUi5HomeDir(), params.ui5HomeDir); + t.is(config.getVersion(), params.version); +}); + + +test.serial("fromFile", async (t) => { + const {fromFile} = t.context.Configuration; + const {promisifyStub, sinon} = t.context; + + const ui5rcContents = { + artifactsDir: "/custom-location/artifacts", + cacheDir: "/custom-location/cacache", + cacheMode: "force", + cwd: "/", + frameworkDir: "/custom-location/framework", + lockDir: "/custom-location/locks", + metadataDir: "/custom-location/metadata", + packagesDir: "/custom-location/packages", + snapshotEndpointUrl: undefined, + sources: true, + stagingDir: "/custom-location/staging", + ui5HomeDir: "/custom-location", + version: "1.99.0-SNAPSHOT", + }; + const responseStub = sinon.stub().resolves(JSON.stringify(ui5rcContents)); + promisifyStub.callsFake(() => responseStub); + + const config = await fromFile("/custom/path/.ui5rc"); + + t.deepEqual(config.toJSON(), ui5rcContents); +}); + +test.serial("fromFile: configuration file not found- fallback to default config", async (t) => { + const {fromFile, Configuration} = t.context.Configuration; + const {promisifyStub, sinon} = t.context; + + const responseStub = sinon.stub().throws({code: "ENOENT"}); + promisifyStub.callsFake(() => responseStub); + + const config = await fromFile("/non-existing/path/.ui5rc"); + + t.is(config instanceof Configuration, true, "Created a default configuration"); + t.is(config.getUi5HomeDir(), "~/.ui5", "Dafault settings"); +}); + +test.serial("fromFile: throws", async (t) => { + const {fromFile} = t.context.Configuration; + const {promisifyStub, sinon} = t.context; + + const responseStub = sinon.stub().throws(new Error("Error")); + promisifyStub.callsFake(() => responseStub); + + await t.throwsAsync(fromFile("/non-existing/path/.ui5rc"), { + message: "Error" + }); +}); + +test.serial("saveConfig", async (t) => { + const {saveConfig, Configuration} = t.context.Configuration; + const {promisifyStub, sinon} = t.context; + + const writeStub = sinon.stub().resolves(); + promisifyStub.callsFake(() => writeStub); + + const config = new Configuration({}); + await saveConfig("/path/to/save/.ui5rc", config); + + t.deepEqual( + writeStub.getCall(0).args, + ["/path/to/save/.ui5rc", JSON.stringify(config.toJSON())], + "Write config to path" + ); +}); + +test.serial("resolveSnapshotEndpointUrl", async (t) => { + const {resolveSnapshotEndpointUrl} = t.context.Configuration; + const {promisifyStub, yesnoStub, sinon} = t.context; + + const readStub = sinon.stub().resolves(` + + + snapshot.build + + + artifactory + /build-snapshots/ + + + + + `); + promisifyStub.callsFake(() => readStub); + yesnoStub.resolves(true); + + const endpoint = await resolveSnapshotEndpointUrl(); + + t.is(endpoint, "/build-snapshots/", "URL Extracted from settings.xml"); +}); + +test.serial("resolveSnapshotEndpointUrl throws", async (t) => { + const {resolveSnapshotEndpointUrl} = t.context.Configuration; + const {promisifyStub, yesnoStub, sinon} = t.context; + + const readStub = sinon.stub() + .onFirstCall().throws({code: "ENOENT"}) + .onSecondCall().throws(new Error("Error")); + promisifyStub.callsFake(() => readStub); + yesnoStub.resolves(true); + + await t.throwsAsync(resolveSnapshotEndpointUrl(), { + message: "SnapshotURL not resolved", + }); + + await t.throwsAsync(resolveSnapshotEndpointUrl(), { + message: "Error", + }); +}); From 0553a0b420b0a33579634bd0a1f0d754b9bb6966 Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Thu, 2 Mar 2023 11:46:46 +0200 Subject: [PATCH 03/18] Improve tests --- test/lib/package-exports.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/lib/package-exports.js b/test/lib/package-exports.js index 9f91f1e10..290c2610d 100644 --- a/test/lib/package-exports.js +++ b/test/lib/package-exports.js @@ -18,6 +18,7 @@ test("check number of exports", (t) => { // Public API contract (exported modules) [ + "config/Configuration", "specifications/Specification", "specifications/SpecificationVersion", "ui5Framework/Openui5Resolver", From 97c6cd3b803a3f444cd835bc1e94ef0eb617fd23 Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Mon, 13 Mar 2023 10:42:20 +0200 Subject: [PATCH 04/18] Cleanup non ambigous diffs with RFC --- lib/config/Configuration.js | 65 +------------------------------- test/lib/config/Configuration.js | 62 ------------------------------ 2 files changed, 1 insertion(+), 126 deletions(-) diff --git a/lib/config/Configuration.js b/lib/config/Configuration.js index 697b5ba9b..0bec9991f 100644 --- a/lib/config/Configuration.js +++ b/lib/config/Configuration.js @@ -70,7 +70,7 @@ export class Configuration { this.#cacheMode = cacheMode; this.#ui5HomeDir = ui5HomeDir ? path.resolve(ui5HomeDir) : path.join(os.homedir(), ".ui5"); - this.#snapshotEndpointUrl = process.env.UI5_MAVEN_SNAPSHOT_ENDPOINT || snapshotEndpointUrl; + this.#snapshotEndpointUrl = snapshotEndpointUrl; this.#frameworkDir = frameworkDir ? path.resolve(frameworkDir) : path.join(this.#ui5HomeDir, "framework"); this.#artifactsDir = artifactsDir ? path.resolve(artifactsDir) : path.join(this.#frameworkDir, "artifacts"); @@ -267,66 +267,3 @@ export async function fromFile(filePath) { } return new Configuration(config); } - -/** - * Save Configuration to a JSON file - * - * @public - * @static - * @param {string} [filePath="~/.ui5rc"] Path to configuration JSON file - * @param {@ui5/project/config/Configuration} config Configuration to save - */ -export async function saveConfig(filePath, config) { - filePath = filePath || path.join(os.homedir(), ".ui5rc"); - - const {default: fs} = await import("graceful-fs"); - const {promisify} = await import("node:util"); - const writeFile = promisify(fs.writeFile); - - return writeFile(filePath, JSON.stringify(config.toJSON())); -} - - -export async function resolveSnapshotEndpointUrl(settingsXML, skipConfirmation) { - let ok = true; - if (!skipConfirmation) { - const {default: yesno} = await import("yesno"); - ok = await yesno({ - question: - "SnapshotURL is missing. " + - "Do you want to try to resolve it from ~/.m2/settings.xml? (yes)", - defaultValue: true, - }); - } - - settingsXML = settingsXML || path.join(os.homedir(), ".m2", "settings.xml"); - const {default: fs} = await import("graceful-fs"); - const {promisify} = await import("node:util"); - const readFile = promisify(fs.readFile); - const xml2js = await import("xml2js"); - const parser = new xml2js.Parser({ - // explicitChildren: true, - preserveChildrenOrder: true, - xmlns: true - }); - let xmlContents; - - try { - const fileContent = await readFile(settingsXML); - xmlContents = await parser.parseStringPromise(fileContent); - } catch (err) { - if (err.code === "ENOENT") { // "File or directory does not exist" - xmlContents = null; - } else { - throw err; - } - } - - if (!ok || !xmlContents) { - throw new Error("SnapshotURL not resolved"); - } - - return xmlContents?.settings?.profiles[0]?.profile - .filter((prof)=> prof.id[0]._ === "snapshot.build")[0] - .pluginRepositories[0].pluginRepository[0].url[0]._; -} diff --git a/test/lib/config/Configuration.js b/test/lib/config/Configuration.js index 421d63da4..d30573d58 100644 --- a/test/lib/config/Configuration.js +++ b/test/lib/config/Configuration.js @@ -165,65 +165,3 @@ test.serial("fromFile: throws", async (t) => { message: "Error" }); }); - -test.serial("saveConfig", async (t) => { - const {saveConfig, Configuration} = t.context.Configuration; - const {promisifyStub, sinon} = t.context; - - const writeStub = sinon.stub().resolves(); - promisifyStub.callsFake(() => writeStub); - - const config = new Configuration({}); - await saveConfig("/path/to/save/.ui5rc", config); - - t.deepEqual( - writeStub.getCall(0).args, - ["/path/to/save/.ui5rc", JSON.stringify(config.toJSON())], - "Write config to path" - ); -}); - -test.serial("resolveSnapshotEndpointUrl", async (t) => { - const {resolveSnapshotEndpointUrl} = t.context.Configuration; - const {promisifyStub, yesnoStub, sinon} = t.context; - - const readStub = sinon.stub().resolves(` - - - snapshot.build - - - artifactory - /build-snapshots/ - - - - - `); - promisifyStub.callsFake(() => readStub); - yesnoStub.resolves(true); - - const endpoint = await resolveSnapshotEndpointUrl(); - - t.is(endpoint, "/build-snapshots/", "URL Extracted from settings.xml"); -}); - -test.serial("resolveSnapshotEndpointUrl throws", async (t) => { - const {resolveSnapshotEndpointUrl} = t.context.Configuration; - const {promisifyStub, yesnoStub, sinon} = t.context; - - const readStub = sinon.stub() - .onFirstCall().throws({code: "ENOENT"}) - .onSecondCall().throws(new Error("Error")); - promisifyStub.callsFake(() => readStub); - yesnoStub.resolves(true); - - await t.throwsAsync(resolveSnapshotEndpointUrl(), { - message: "SnapshotURL not resolved", - }); - - await t.throwsAsync(resolveSnapshotEndpointUrl(), { - message: "Error", - }); -}); From 91fa3e343534134dfb427891e9077ebf0350c25a Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Mon, 13 Mar 2023 11:01:36 +0200 Subject: [PATCH 05/18] Remove yesno --- test/lib/config/Configuration.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/lib/config/Configuration.js b/test/lib/config/Configuration.js index d30573d58..aa6892d56 100644 --- a/test/lib/config/Configuration.js +++ b/test/lib/config/Configuration.js @@ -7,7 +7,6 @@ test.beforeEach(async (t) => { t.context.homedirStub = sinon.stub().returns("~"); t.context.promisifyStub = sinon.stub(); - t.context.yesnoStub = sinon.stub(); t.context.resolveStub = sinon.stub().callsFake((path) => path); t.context.joinStub = sinon.stub().callsFake((...args) => args.join("/")); t.context.Configuration = await esmock.p("../../../lib/config/Configuration.js", { @@ -15,7 +14,6 @@ test.beforeEach(async (t) => { resolve: t.context.resolveStub, join: t.context.joinStub }, - "yesno": t.context.yesnoStub, "node:util": { "promisify": t.context.promisifyStub }, From 92a579b2384682f370c60868c27e232b9a4759dc Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Mon, 13 Mar 2023 13:52:32 +0200 Subject: [PATCH 06/18] Reolve properly the ui5HomeDir --- lib/config/Configuration.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/config/Configuration.js b/lib/config/Configuration.js index 0bec9991f..25ef0df12 100644 --- a/lib/config/Configuration.js +++ b/lib/config/Configuration.js @@ -68,7 +68,11 @@ export class Configuration { this.#sources = !!sources; this.#version = version; this.#cacheMode = cacheMode; - this.#ui5HomeDir = ui5HomeDir ? path.resolve(ui5HomeDir) : path.join(os.homedir(), ".ui5"); + // In some CI environments, the homedir might be set explicitly to a relative + // path (e.g. "./"), but tooling requires an absolute path + this.#ui5HomeDir = path.resolve( + ui5HomeDir || path.join(os.homedir(), ".ui5") + ); this.#snapshotEndpointUrl = snapshotEndpointUrl; this.#frameworkDir = frameworkDir ? path.resolve(frameworkDir) : path.join(this.#ui5HomeDir, "framework"); From fb05fa2090179c2f4b5ea1afc7806cb124dfda76 Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Fri, 31 Mar 2023 11:38:42 +0300 Subject: [PATCH 07/18] Leave just the snapshotUrl setting for now --- lib/config/Configuration.js | 217 ++++--------------------------- test/lib/config/Configuration.js | 89 ++++--------- 2 files changed, 45 insertions(+), 261 deletions(-) diff --git a/lib/config/Configuration.js b/lib/config/Configuration.js index 25ef0df12..15a9e4a5b 100644 --- a/lib/config/Configuration.js +++ b/lib/config/Configuration.js @@ -18,125 +18,14 @@ import os from "node:os"; * @alias @ui5/project/config/Configuration */ export class Configuration { - #cwd; - #sources; - #version; - #cacheMode; - #ui5HomeDir; #snapshotEndpointUrl; - #frameworkDir; - #artifactsDir; - #packagesDir; - #metadataDir; - #stagingDir; - #lockDir; - #cacheDir; /** * @param {object} configuration - * @param {string} [configuration.cwd="./"] - * @param {string} [configuration.version=""] - * @param {string} [configuration.sources=false] - * @param {string} [configuration.ui5HomeDir="~/.ui5/"] * @param {string} [configuration.snapshotEndpointUrl=""] - * @param {@ui5/project/config/Configuration~cacheMode} [configuration.cacheMode="default"] - * @param {string} [configuration.frameworkDir="~/${ui5HomeDir}/framework"] - * Directory to store framework artifacts and metadata in. - * @param {string} [configuration.cacheDir="~/${ui5HomeDir}/cacache"] - * @param {string} [configuration.artifactsDir="~/${ui5HomeDir}/artifacts"] - * @param {string} [configuration.packagesDir="~/${ui5HomeDir}/packages"] - * @param {string} [configuration.metadataDir="~/${ui5HomeDir}/metadata"] - * @param {string} [configuration.stagingDir="~/${ui5HomeDir}/staging"] - * @param {string} [configuration.lockDir="~/${ui5HomeDir}/locks"] */ - constructor({ - cwd, - version, - sources, - ui5HomeDir, - snapshotEndpointUrl, - cacheMode = "default", - frameworkDir, - cacheDir, - artifactsDir, - packagesDir, - metadataDir, - stagingDir, - lockDir - }) { - this.#cwd = cwd ? path.resolve(cwd) : process.cwd(); - this.#sources = !!sources; - this.#version = version; - this.#cacheMode = cacheMode; - // In some CI environments, the homedir might be set explicitly to a relative - // path (e.g. "./"), but tooling requires an absolute path - this.#ui5HomeDir = path.resolve( - ui5HomeDir || path.join(os.homedir(), ".ui5") - ); - + constructor({ snapshotEndpointUrl }) { this.#snapshotEndpointUrl = snapshotEndpointUrl; - this.#frameworkDir = frameworkDir ? path.resolve(frameworkDir) : path.join(this.#ui5HomeDir, "framework"); - this.#artifactsDir = artifactsDir ? - path.resolve(artifactsDir) : path.join(this.#frameworkDir, "artifacts"); - this.#packagesDir = packagesDir ? - path.resolve(packagesDir) : path.join(this.#frameworkDir, "packages"); - this.#metadataDir = metadataDir ? - path.resolve(metadataDir) : path.join(this.#frameworkDir, "metadata"); - this.#stagingDir = stagingDir ? path.resolve(stagingDir) : path.join(this.#frameworkDir, "staging"); - this.#lockDir = lockDir ? path.resolve(lockDir) : path.join(this.#frameworkDir, "locks"); - this.#cacheDir = cacheDir ? path.resolve(cacheDir) : path.join(this.#frameworkDir, "cacache"); - } - - /** - * CWD path - * - * @public - * @returns {string} - */ - getCwd() { - return this.#cwd; - } - - /** - * Prebuild or source files - * - * TODO: Private for now until we decide on how to handle this properly - * - * @private - * @returns {boolean} - */ - getSources() { - return this.#sources; - } - - /** - * UI5 Version - * - * @public - * @returns {string} - */ - getVersion() { - return this.#version; - } - - /** - * Cache mode - * - * @public - * @returns {string} - */ - getCacheMode() { - return this.#cacheMode; - } - - /** - * .ui5 home direcotry - * - * @public - * @returns {string} - */ - getUi5HomeDir() { - return this.#ui5HomeDir; } /** @@ -149,95 +38,13 @@ export class Configuration { return this.#snapshotEndpointUrl; } - /** - * Directory to store framework artifacts and metadata in. - * - * @public - * @returns {string} - */ - getFrameworkDir() { - return this.#frameworkDir; - } - - /** - * Directory to store artifacts in. - * - * @public - * @returns {string} - */ - getArtifactsDir() { - return this.#artifactsDir; - } - - /** - * Directory to packages in - * - * @public - * @returns {string} - */ - getPackagesDir() { - return this.#packagesDir; - } - - /** - * Directory to store metadata in - * - * @public - * @returns {string} - */ - getMetadataDir() { - return this.#metadataDir; - } - - /** - * Directory to store staging artifacts in - * - * @public - * @returns {string} - */ - getStagingDir() { - return this.#stagingDir; - } - - /** - * Lockfiles directory - * - * @public - * @returns {string} - */ - getLockDir() { - return this.#lockDir; - } - - /** - * Cache directory - * - * @public - * @returns {string} - */ - getCacheDir() { - return this.#cacheDir; - } - /** * @public * @returns {object} The configuration in a JSON format */ toJSON() { return { - cwd: this.#cwd, - sources: this.#sources, - version: this.#version, - cacheMode: this.#cacheMode, - ui5HomeDir: this.#ui5HomeDir, snapshotEndpointUrl: this.#snapshotEndpointUrl, - frameworkDir: this.#frameworkDir, - artifactsDir: this.#artifactsDir, - packagesDir: this.#packagesDir, - metadataDir: this.#metadataDir, - stagingDir: this.#stagingDir, - lockDir: this.#lockDir, - cacheDir: this.#cacheDir, }; } } @@ -263,7 +70,8 @@ export async function fromFile(filePath) { const fileContent = await readFile(filePath); config = JSON.parse(fileContent); } catch (err) { - if (err.code === "ENOENT") { // "File or directory does not exist" + if (err.code === "ENOENT") { + // "File or directory does not exist" config = {}; } else { throw err; @@ -271,3 +79,22 @@ export async function fromFile(filePath) { } return new Configuration(config); } + +/** + * Save Configuration to a JSON file + * + * @public + * @static + * @param {string} [filePath="~/.ui5rc"] Path to configuration JSON file + * @param {@ui5/project/config/Configuration} config Configuration to save + * @returns {Promise} + */ +export async function saveConfig(filePath, config) { + filePath = filePath || path.resolve(path.join(os.homedir(), ".ui5rc")); + + const {default: fs} = await import("graceful-fs"); + const {promisify} = await import("node:util"); + const writeFile = promisify(fs.writeFile); + + return writeFile(filePath, JSON.stringify(config.toJSON())); +} diff --git a/test/lib/config/Configuration.js b/test/lib/config/Configuration.js index aa6892d56..c9b3972df 100644 --- a/test/lib/config/Configuration.js +++ b/test/lib/config/Configuration.js @@ -31,22 +31,10 @@ test.afterEach.always((t) => { test.serial("Build configuration with defaults", (t) => { const {Configuration} = t.context.Configuration; - const config = new Configuration({cwd: "/"}); + const config = new Configuration({}); t.deepEqual(config.toJSON(), { - artifactsDir: "~/.ui5/framework/artifacts", - cacheDir: "~/.ui5/framework/cacache", - cacheMode: "default", - cwd: "/", - frameworkDir: "~/.ui5/framework", - lockDir: "~/.ui5/framework/locks", - metadataDir: "~/.ui5/framework/metadata", - packagesDir: "~/.ui5/framework/packages", - snapshotEndpointUrl: undefined, - sources: false, - stagingDir: "~/.ui5/framework/staging", - ui5HomeDir: "~/.ui5", - version: undefined, + snapshotEndpointUrl: undefined }); }); @@ -55,19 +43,7 @@ test.serial("Overwrite defaults defaults", (t) => { const {Configuration} = t.context.Configuration; const params = { - artifactsDir: "/custom-location/artifacts", - cacheDir: "/custom-location/cacache", - cacheMode: "force", - cwd: "/", - frameworkDir: "/custom-location/framework", - lockDir: "/custom-location/locks", - metadataDir: "/custom-location/metadata", - packagesDir: "/custom-location/packages", - snapshotEndpointUrl: undefined, - sources: true, - stagingDir: "/custom-location/staging", - ui5HomeDir: "/custom-location", - version: "1.99.0-SNAPSHOT" + snapshotEndpointUrl: "https://snapshot.url" }; const config = new Configuration(params); @@ -79,36 +55,12 @@ test.serial("Check getters", (t) => { const {Configuration} = t.context.Configuration; const params = { - artifactsDir: "/custom-location/artifacts", - cacheDir: "/custom-location/cacache", - cacheMode: "force", - cwd: "/", - frameworkDir: "/custom-location/framework", - lockDir: "/custom-location/locks", - metadataDir: "/custom-location/metadata", - packagesDir: "/custom-location/packages", - snapshotEndpointUrl: undefined, - sources: true, - stagingDir: "/custom-location/staging", - ui5HomeDir: "/custom-location", - version: "1.99.0-SNAPSHOT" + snapshotEndpointUrl: "https://snapshot.url" }; const config = new Configuration(params); - t.is(config.getArtifactsDir(), params.artifactsDir); - t.is(config.getCacheDir(), params.cacheDir); - t.is(config.getCacheMode(), params.cacheMode); - t.is(config.getCwd(), params.cwd); - t.is(config.getFrameworkDir(), params.frameworkDir); - t.is(config.getLockDir(), params.lockDir); - t.is(config.getMetadataDir(), params.metadataDir); - t.is(config.getPackagesDir(), params.packagesDir); t.is(config.getSnapshotEndpointUrl(), params.snapshotEndpointUrl); - t.is(config.getSources(), params.sources); - t.is(config.getStagingDir(), params.stagingDir); - t.is(config.getUi5HomeDir(), params.ui5HomeDir); - t.is(config.getVersion(), params.version); }); @@ -117,19 +69,7 @@ test.serial("fromFile", async (t) => { const {promisifyStub, sinon} = t.context; const ui5rcContents = { - artifactsDir: "/custom-location/artifacts", - cacheDir: "/custom-location/cacache", - cacheMode: "force", - cwd: "/", - frameworkDir: "/custom-location/framework", - lockDir: "/custom-location/locks", - metadataDir: "/custom-location/metadata", - packagesDir: "/custom-location/packages", - snapshotEndpointUrl: undefined, - sources: true, - stagingDir: "/custom-location/staging", - ui5HomeDir: "/custom-location", - version: "1.99.0-SNAPSHOT", + snapshotEndpointUrl: "https://snapshot.url" }; const responseStub = sinon.stub().resolves(JSON.stringify(ui5rcContents)); promisifyStub.callsFake(() => responseStub); @@ -149,7 +89,7 @@ test.serial("fromFile: configuration file not found- fallback to default config" const config = await fromFile("/non-existing/path/.ui5rc"); t.is(config instanceof Configuration, true, "Created a default configuration"); - t.is(config.getUi5HomeDir(), "~/.ui5", "Dafault settings"); + t.is(config.getSnapshotEndpointUrl(), undefined, "Dafault settings"); }); test.serial("fromFile: throws", async (t) => { @@ -163,3 +103,20 @@ test.serial("fromFile: throws", async (t) => { message: "Error" }); }); + +test.serial("saveConfig", async (t) => { + const {saveConfig, Configuration} = t.context.Configuration; + const {promisifyStub, sinon} = t.context; + + const writeStub = sinon.stub().resolves(); + promisifyStub.callsFake(() => writeStub); + + const config = new Configuration({}); + await saveConfig("/path/to/save/.ui5rc", config); + + t.deepEqual( + writeStub.getCall(0).args, + ["/path/to/save/.ui5rc", JSON.stringify(config.toJSON())], + "Write config to path" + ); +}); From bf0cb5eaa2d4e9cff3a856ca763ca7135974c0c1 Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Fri, 31 Mar 2023 11:41:02 +0300 Subject: [PATCH 08/18] Fix lint issues --- lib/config/Configuration.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/config/Configuration.js b/lib/config/Configuration.js index 15a9e4a5b..02bb19504 100644 --- a/lib/config/Configuration.js +++ b/lib/config/Configuration.js @@ -24,7 +24,7 @@ export class Configuration { * @param {object} configuration * @param {string} [configuration.snapshotEndpointUrl=""] */ - constructor({ snapshotEndpointUrl }) { + constructor({snapshotEndpointUrl}) { this.#snapshotEndpointUrl = snapshotEndpointUrl; } From fb4c8160da878271587f7bd3a3724000c80eca90 Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Fri, 31 Mar 2023 11:42:54 +0300 Subject: [PATCH 09/18] Remove redundant JSDocs --- lib/config/Configuration.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/lib/config/Configuration.js b/lib/config/Configuration.js index 02bb19504..58696b8de 100644 --- a/lib/config/Configuration.js +++ b/lib/config/Configuration.js @@ -1,15 +1,6 @@ import path from "node:path"; import os from "node:os"; -/** - * @public - * @typedef @ui5/project/config/Configuration~cacheMode - * @property {string} "default" Cache everything, invalidate after 9 hours - * @property {string} "off" Do not cache - * @property {string} "force" Use cache only - no requests - * @property {string} "relaxed" Try to refresh, but fallback to cache if refresh fails for up to one week - */ - /** * * From 566efc8a94e033ca730029ca4df2abb13a616b51 Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Fri, 31 Mar 2023 14:31:13 +0300 Subject: [PATCH 10/18] Resolve properly os.homedir() --- lib/config/Configuration.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/config/Configuration.js b/lib/config/Configuration.js index 58696b8de..ee9046c85 100644 --- a/lib/config/Configuration.js +++ b/lib/config/Configuration.js @@ -51,7 +51,7 @@ export default Configuration; * @returns {@ui5/project/config/Configuration} Configuration instance */ export async function fromFile(filePath) { - filePath = filePath || path.join(os.homedir(), ".ui5rc"); + filePath = filePath || path.resolve(path.join(os.homedir(), ".ui5rc")); const {default: fs} = await import("graceful-fs"); const {promisify} = await import("node:util"); From f622df7bc9b73c97edf7a6096fae2ea275667579 Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Mon, 3 Apr 2023 16:54:32 +0300 Subject: [PATCH 11/18] JSDoc updates --- lib/config/Configuration.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/config/Configuration.js b/lib/config/Configuration.js index ee9046c85..b1550c333 100644 --- a/lib/config/Configuration.js +++ b/lib/config/Configuration.js @@ -13,7 +13,7 @@ export class Configuration { /** * @param {object} configuration - * @param {string} [configuration.snapshotEndpointUrl=""] + * @param {string} [configuration.snapshotEndpointUrl] */ constructor({snapshotEndpointUrl}) { this.#snapshotEndpointUrl = snapshotEndpointUrl; @@ -48,7 +48,7 @@ export default Configuration; * @public * @static * @param {string} [filePath="~/.ui5rc"] Path to configuration JSON file - * @returns {@ui5/project/config/Configuration} Configuration instance + * @returns {Promise<@ui5/project/config/Configuration>} Configuration instance */ export async function fromFile(filePath) { filePath = filePath || path.resolve(path.join(os.homedir(), ".ui5rc")); From 4f70bd45ef522de7bfc79d627a7c7c9d35b96ff9 Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Wed, 5 Apr 2023 15:12:05 +0300 Subject: [PATCH 12/18] Update JSDoc --- lib/config/Configuration.js | 96 ++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/lib/config/Configuration.js b/lib/config/Configuration.js index b1550c333..a7c69c7a9 100644 --- a/lib/config/Configuration.js +++ b/lib/config/Configuration.js @@ -2,13 +2,14 @@ import path from "node:path"; import os from "node:os"; /** - * + * Provides basic configuration settings for the resolvers. + * Reads/writes configuration from/to ~/.ui5rc * * @public * @class * @alias @ui5/project/config/Configuration */ -export class Configuration { +export default class Configuration { #snapshotEndpointUrl; /** @@ -20,7 +21,8 @@ export class Configuration { } /** - * SNAPSHOTs URL + * Maven Repository Snapshot URL. + * Used to download artifacts and packages from Maven's build-snapshots URL. * * @public * @returns {string} @@ -38,54 +40,52 @@ export class Configuration { snapshotEndpointUrl: this.#snapshotEndpointUrl, }; } -} - -export default Configuration; - -/** - * Create Configuration from JSON file - * - * @public - * @static - * @param {string} [filePath="~/.ui5rc"] Path to configuration JSON file - * @returns {Promise<@ui5/project/config/Configuration>} Configuration instance - */ -export async function fromFile(filePath) { - filePath = filePath || path.resolve(path.join(os.homedir(), ".ui5rc")); + + /** + * Create Configuration from JSON file + * + * @public + * @static + * @param {string} [filePath="~/.ui5rc"] Path to configuration JSON file + * @returns {Promise<@ui5/project/config/Configuration>} Configuration instance + */ + static async fromFile(filePath) { + filePath = filePath || path.resolve(path.join(os.homedir(), ".ui5rc")); - const {default: fs} = await import("graceful-fs"); - const {promisify} = await import("node:util"); - const readFile = promisify(fs.readFile); - let config; - try { - const fileContent = await readFile(filePath); - config = JSON.parse(fileContent); - } catch (err) { - if (err.code === "ENOENT") { - // "File or directory does not exist" - config = {}; - } else { - throw err; + const {default: fs} = await import("graceful-fs"); + const {promisify} = await import("node:util"); + const readFile = promisify(fs.readFile); + let config; + try { + const fileContent = await readFile(filePath); + config = JSON.parse(fileContent); + } catch (err) { + if (err.code === "ENOENT") { + // "File or directory does not exist" + config = {}; + } else { + throw err; + } } + return new Configuration(config); } - return new Configuration(config); -} - -/** - * Save Configuration to a JSON file - * - * @public - * @static - * @param {string} [filePath="~/.ui5rc"] Path to configuration JSON file - * @param {@ui5/project/config/Configuration} config Configuration to save - * @returns {Promise} - */ -export async function saveConfig(filePath, config) { - filePath = filePath || path.resolve(path.join(os.homedir(), ".ui5rc")); + + /** + * Save Configuration to a JSON file + * + * @public + * @static + * @param {string} [filePath="~/.ui5rc"] Path to configuration JSON file + * @param {@ui5/project/config/Configuration} config Configuration to save + * @returns {Promise} + */ + static async saveConfig(filePath, config) { + filePath = filePath || path.resolve(path.join(os.homedir(), ".ui5rc")); - const {default: fs} = await import("graceful-fs"); - const {promisify} = await import("node:util"); - const writeFile = promisify(fs.writeFile); + const {default: fs} = await import("graceful-fs"); + const {promisify} = await import("node:util"); + const writeFile = promisify(fs.writeFile); - return writeFile(filePath, JSON.stringify(config.toJSON())); + return writeFile(filePath, JSON.stringify(config.toJSON())); + } } From 7f8281c885b52c8141df84438611a0f146e6407e Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Wed, 5 Apr 2023 15:41:06 +0300 Subject: [PATCH 13/18] eslint fix --- lib/config/Configuration.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/config/Configuration.js b/lib/config/Configuration.js index a7c69c7a9..bf58d429d 100644 --- a/lib/config/Configuration.js +++ b/lib/config/Configuration.js @@ -40,7 +40,7 @@ export default class Configuration { snapshotEndpointUrl: this.#snapshotEndpointUrl, }; } - + /** * Create Configuration from JSON file * @@ -69,7 +69,7 @@ export default class Configuration { } return new Configuration(config); } - + /** * Save Configuration to a JSON file * From fefdd65985ee138ef2d71bf7411b59eb6991ab35 Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Wed, 5 Apr 2023 18:52:43 +0300 Subject: [PATCH 14/18] Adjust JSDoc & refactor saveConfig + tests --- lib/config/Configuration.js | 14 ++++++++------ test/lib/config/Configuration.js | 20 ++++++++++---------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/lib/config/Configuration.js b/lib/config/Configuration.js index bf58d429d..40d62e297 100644 --- a/lib/config/Configuration.js +++ b/lib/config/Configuration.js @@ -2,14 +2,14 @@ import path from "node:path"; import os from "node:os"; /** - * Provides basic configuration settings for the resolvers. + * Provides basic configuration settings for @ui5/project/ui5Framework/* resolvers. * Reads/writes configuration from/to ~/.ui5rc * * @public * @class * @alias @ui5/project/config/Configuration */ -export default class Configuration { +class Configuration { #snapshotEndpointUrl; /** @@ -42,7 +42,7 @@ export default class Configuration { } /** - * Create Configuration from JSON file + * Creates Configuration from a JSON file * * @public * @static @@ -71,15 +71,15 @@ export default class Configuration { } /** - * Save Configuration to a JSON file + * Saves Configuration to a JSON file * * @public * @static - * @param {string} [filePath="~/.ui5rc"] Path to configuration JSON file * @param {@ui5/project/config/Configuration} config Configuration to save + * @param {string} [filePath="~/.ui5rc"] Path to configuration JSON file * @returns {Promise} */ - static async saveConfig(filePath, config) { + static async saveConfig(config, filePath) { filePath = filePath || path.resolve(path.join(os.homedir(), ".ui5rc")); const {default: fs} = await import("graceful-fs"); @@ -89,3 +89,5 @@ export default class Configuration { return writeFile(filePath, JSON.stringify(config.toJSON())); } } + +export default Configuration; diff --git a/test/lib/config/Configuration.js b/test/lib/config/Configuration.js index c9b3972df..03ae1ccd0 100644 --- a/test/lib/config/Configuration.js +++ b/test/lib/config/Configuration.js @@ -29,7 +29,7 @@ test.afterEach.always((t) => { }); test.serial("Build configuration with defaults", (t) => { - const {Configuration} = t.context.Configuration; + const {Configuration} = t.context; const config = new Configuration({}); @@ -40,7 +40,7 @@ test.serial("Build configuration with defaults", (t) => { test.serial("Overwrite defaults defaults", (t) => { - const {Configuration} = t.context.Configuration; + const {Configuration} = t.context; const params = { snapshotEndpointUrl: "https://snapshot.url" @@ -52,7 +52,7 @@ test.serial("Overwrite defaults defaults", (t) => { }); test.serial("Check getters", (t) => { - const {Configuration} = t.context.Configuration; + const {Configuration} = t.context; const params = { snapshotEndpointUrl: "https://snapshot.url" @@ -65,7 +65,7 @@ test.serial("Check getters", (t) => { test.serial("fromFile", async (t) => { - const {fromFile} = t.context.Configuration; + const fromFile = t.context.Configuration.fromFile; const {promisifyStub, sinon} = t.context; const ui5rcContents = { @@ -80,8 +80,8 @@ test.serial("fromFile", async (t) => { }); test.serial("fromFile: configuration file not found- fallback to default config", async (t) => { - const {fromFile, Configuration} = t.context.Configuration; - const {promisifyStub, sinon} = t.context; + const {promisifyStub, sinon, Configuration} = t.context; + const fromFile = Configuration.fromFile; const responseStub = sinon.stub().throws({code: "ENOENT"}); promisifyStub.callsFake(() => responseStub); @@ -93,7 +93,7 @@ test.serial("fromFile: configuration file not found- fallback to default config" }); test.serial("fromFile: throws", async (t) => { - const {fromFile} = t.context.Configuration; + const fromFile = t.context.Configuration.fromFile; const {promisifyStub, sinon} = t.context; const responseStub = sinon.stub().throws(new Error("Error")); @@ -105,14 +105,14 @@ test.serial("fromFile: throws", async (t) => { }); test.serial("saveConfig", async (t) => { - const {saveConfig, Configuration} = t.context.Configuration; - const {promisifyStub, sinon} = t.context; + const {promisifyStub, sinon, Configuration} = t.context; + const saveConfig = Configuration.saveConfig; const writeStub = sinon.stub().resolves(); promisifyStub.callsFake(() => writeStub); const config = new Configuration({}); - await saveConfig("/path/to/save/.ui5rc", config); + await saveConfig(config, "/path/to/save/.ui5rc"); t.deepEqual( writeStub.getCall(0).args, From 839c52fb7968c107f3e8816e6e76784b5f20383b Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Wed, 12 Apr 2023 12:20:10 +0300 Subject: [PATCH 15/18] Add snapshotEndpointUrl to test Config --- test/lib/config/Configuration.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/lib/config/Configuration.js b/test/lib/config/Configuration.js index 03ae1ccd0..8d0890c6a 100644 --- a/test/lib/config/Configuration.js +++ b/test/lib/config/Configuration.js @@ -111,7 +111,7 @@ test.serial("saveConfig", async (t) => { const writeStub = sinon.stub().resolves(); promisifyStub.callsFake(() => writeStub); - const config = new Configuration({}); + const config = new Configuration({snapshotEndpointUrl: "https://registry.corp/vendor/build-snapshots/"}); await saveConfig(config, "/path/to/save/.ui5rc"); t.deepEqual( From 47a77c9d6404bd968837a82158dad2a92b55993b Mon Sep 17 00:00:00 2001 From: Merlin Beutlberger Date: Mon, 17 Apr 2023 15:58:34 +0200 Subject: [PATCH 16/18] package-exports: Fix tests that broke by rebase --- test/lib/package-exports.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/lib/package-exports.js b/test/lib/package-exports.js index 290c2610d..c3c7284d6 100644 --- a/test/lib/package-exports.js +++ b/test/lib/package-exports.js @@ -13,7 +13,7 @@ test("export of package.json", (t) => { // Check number of definied exports test("check number of exports", (t) => { const packageJson = require("@ui5/project/package.json"); - t.is(Object.keys(packageJson.exports).length, 11); + t.is(Object.keys(packageJson.exports).length, 12); }); // Public API contract (exported modules) From b0a29e4937ff4afe9515e1da35c86138c8e359b4 Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Tue, 18 Apr 2023 14:59:40 +0300 Subject: [PATCH 17/18] saveConfig -> toFile --- lib/config/Configuration.js | 2 +- test/lib/config/Configuration.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/config/Configuration.js b/lib/config/Configuration.js index 40d62e297..737cc53fe 100644 --- a/lib/config/Configuration.js +++ b/lib/config/Configuration.js @@ -79,7 +79,7 @@ class Configuration { * @param {string} [filePath="~/.ui5rc"] Path to configuration JSON file * @returns {Promise} */ - static async saveConfig(config, filePath) { + static async toFile(config, filePath) { filePath = filePath || path.resolve(path.join(os.homedir(), ".ui5rc")); const {default: fs} = await import("graceful-fs"); diff --git a/test/lib/config/Configuration.js b/test/lib/config/Configuration.js index 8d0890c6a..cc4e333cb 100644 --- a/test/lib/config/Configuration.js +++ b/test/lib/config/Configuration.js @@ -104,15 +104,15 @@ test.serial("fromFile: throws", async (t) => { }); }); -test.serial("saveConfig", async (t) => { +test.serial("toFile", async (t) => { const {promisifyStub, sinon, Configuration} = t.context; - const saveConfig = Configuration.saveConfig; + const toFile = Configuration.toFile; const writeStub = sinon.stub().resolves(); promisifyStub.callsFake(() => writeStub); const config = new Configuration({snapshotEndpointUrl: "https://registry.corp/vendor/build-snapshots/"}); - await saveConfig(config, "/path/to/save/.ui5rc"); + await toFile(config, "/path/to/save/.ui5rc"); t.deepEqual( writeStub.getCall(0).args, From f37a62d8204d17411f7386b286ddec7548f63411 Mon Sep 17 00:00:00 2001 From: Yavor Ivanov Date: Tue, 18 Apr 2023 15:32:34 +0300 Subject: [PATCH 18/18] snapshotEndpointUrl -> mavenSnapshotEndpointUrl --- lib/config/Configuration.js | 14 +++++++------- lib/ui5Framework/Sapui5MavenSnapshotResolver.js | 2 +- lib/ui5Framework/maven/Installer.js | 2 +- test/lib/config/Configuration.js | 14 +++++++------- .../ui5framework/Sapui5MavenSnapshotResolver.js | 2 +- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/lib/config/Configuration.js b/lib/config/Configuration.js index 737cc53fe..622e7c9d7 100644 --- a/lib/config/Configuration.js +++ b/lib/config/Configuration.js @@ -10,14 +10,14 @@ import os from "node:os"; * @alias @ui5/project/config/Configuration */ class Configuration { - #snapshotEndpointUrl; + #mavenSnapshotEndpointUrl; /** * @param {object} configuration - * @param {string} [configuration.snapshotEndpointUrl] + * @param {string} [configuration.mavenSnapshotEndpointUrl] */ - constructor({snapshotEndpointUrl}) { - this.#snapshotEndpointUrl = snapshotEndpointUrl; + constructor({mavenSnapshotEndpointUrl}) { + this.#mavenSnapshotEndpointUrl = mavenSnapshotEndpointUrl; } /** @@ -27,8 +27,8 @@ class Configuration { * @public * @returns {string} */ - getSnapshotEndpointUrl() { - return this.#snapshotEndpointUrl; + getMavenSnapshotEndpointUrl() { + return this.#mavenSnapshotEndpointUrl; } /** @@ -37,7 +37,7 @@ class Configuration { */ toJSON() { return { - snapshotEndpointUrl: this.#snapshotEndpointUrl, + mavenSnapshotEndpointUrl: this.#mavenSnapshotEndpointUrl, }; } diff --git a/lib/ui5Framework/Sapui5MavenSnapshotResolver.js b/lib/ui5Framework/Sapui5MavenSnapshotResolver.js index 0d22e23c4..04dab9137 100644 --- a/lib/ui5Framework/Sapui5MavenSnapshotResolver.js +++ b/lib/ui5Framework/Sapui5MavenSnapshotResolver.js @@ -227,7 +227,7 @@ class Sapui5MavenSnapshotResolver extends AbstractResolver { if (ok) { log.info(`Using Maven snapshot endpoint URL resolved from Maven configuration file: ${url}`); log.info(`Consider persisting this choice by executing the following command: ` + - `ui5 config set snapshotEndpointUrl ${url}`); + `ui5 config set mavenSnapshotEndpointUrl ${url}`); } else { log.verbose(`User rejected usage of the resolved URL`); url = null; diff --git a/lib/ui5Framework/maven/Installer.js b/lib/ui5Framework/maven/Installer.js index 53a0a614b..ff47ba55f 100644 --- a/lib/ui5Framework/maven/Installer.js +++ b/lib/ui5Framework/maven/Installer.js @@ -70,7 +70,7 @@ class Installer extends AbstractInstaller { reject(new Error( `Installer: Missing or empty Maven repository URL for snapshot consumption. ` + `Please configure the correct URL using the following command: ` + - `ui5 config set snapshotEndpointUrl https://registry.corp/vendor/build-snapshots/`)); + `ui5 config set mavenSnapshotEndpointUrl https://registry.corp/vendor/build-snapshots/`)); } resolve(new Registry({endpointUrl: snapshotEndpointUrl})); diff --git a/test/lib/config/Configuration.js b/test/lib/config/Configuration.js index cc4e333cb..d6152220d 100644 --- a/test/lib/config/Configuration.js +++ b/test/lib/config/Configuration.js @@ -34,7 +34,7 @@ test.serial("Build configuration with defaults", (t) => { const config = new Configuration({}); t.deepEqual(config.toJSON(), { - snapshotEndpointUrl: undefined + mavenSnapshotEndpointUrl: undefined }); }); @@ -43,7 +43,7 @@ test.serial("Overwrite defaults defaults", (t) => { const {Configuration} = t.context; const params = { - snapshotEndpointUrl: "https://snapshot.url" + mavenSnapshotEndpointUrl: "https://snapshot.url" }; const config = new Configuration(params); @@ -55,12 +55,12 @@ test.serial("Check getters", (t) => { const {Configuration} = t.context; const params = { - snapshotEndpointUrl: "https://snapshot.url" + mavenSnapshotEndpointUrl: "https://snapshot.url" }; const config = new Configuration(params); - t.is(config.getSnapshotEndpointUrl(), params.snapshotEndpointUrl); + t.is(config.getMavenSnapshotEndpointUrl(), params.mavenSnapshotEndpointUrl); }); @@ -69,7 +69,7 @@ test.serial("fromFile", async (t) => { const {promisifyStub, sinon} = t.context; const ui5rcContents = { - snapshotEndpointUrl: "https://snapshot.url" + mavenSnapshotEndpointUrl: "https://snapshot.url" }; const responseStub = sinon.stub().resolves(JSON.stringify(ui5rcContents)); promisifyStub.callsFake(() => responseStub); @@ -89,7 +89,7 @@ test.serial("fromFile: configuration file not found- fallback to default config" const config = await fromFile("/non-existing/path/.ui5rc"); t.is(config instanceof Configuration, true, "Created a default configuration"); - t.is(config.getSnapshotEndpointUrl(), undefined, "Dafault settings"); + t.is(config.getMavenSnapshotEndpointUrl(), undefined, "Dafault settings"); }); test.serial("fromFile: throws", async (t) => { @@ -111,7 +111,7 @@ test.serial("toFile", async (t) => { const writeStub = sinon.stub().resolves(); promisifyStub.callsFake(() => writeStub); - const config = new Configuration({snapshotEndpointUrl: "https://registry.corp/vendor/build-snapshots/"}); + const config = new Configuration({mavenSnapshotEndpointUrl: "https://registry.corp/vendor/build-snapshots/"}); await toFile(config, "/path/to/save/.ui5rc"); t.deepEqual( diff --git a/test/lib/ui5framework/Sapui5MavenSnapshotResolver.js b/test/lib/ui5framework/Sapui5MavenSnapshotResolver.js index f14890426..ae11523bc 100644 --- a/test/lib/ui5framework/Sapui5MavenSnapshotResolver.js +++ b/test/lib/ui5framework/Sapui5MavenSnapshotResolver.js @@ -282,7 +282,7 @@ test.serial("_resolveSnapshotEndpointUrlFromMaven", async (t) => { "Using Maven snapshot endpoint URL resolved from Maven configuration file: /build-snapshots/"); t.is(loggerInfo.getCall(1).args[0], "Consider persisting this choice by executing the following command: " + - "ui5 config set snapshotEndpointUrl /build-snapshots/"); + "ui5 config set mavenSnapshotEndpointUrl /build-snapshots/"); }); test.serial("_resolveSnapshotEndpointUrlFromMaven fails", async (t) => {