diff --git a/lib/cli/base.js b/lib/cli/base.js index 83f0f991..733e6a0a 100644 --- a/lib/cli/base.js +++ b/lib/cli/base.js @@ -52,7 +52,7 @@ export default function(cli) { "config", "dependency-definition", "workspace-config", "workspace", "log-level", // tree.js, build.js & serve.js - "framework-version", + "framework-version", "cache-mode", // build.js "dest", diff --git a/lib/cli/commands/build.js b/lib/cli/commands/build.js index abf619c8..6fe1a6a4 100644 --- a/lib/cli/commands/build.js +++ b/lib/cli/commands/build.js @@ -101,6 +101,15 @@ build.builder = function(cli) { describe: "Overrides the framework version defined by the project", type: "string" }) + .option("cache-mode", { + describe: + "Cache mode to use when consuming SNAPSHOT versions of a framework: 'Default', 'Force', or 'Off'. " + + "The 'Default' behavior is to invalidate the cache after 9 hours. 'Force' uses the cache only and " + + "does not create any requests. 'Off' invalidates any existing cache and updates from the repository", + type: "string", + default: "Default", + choices: ["Default", "Force", "Off"] + }) .option("experimental-css-variables", { describe: "Generate CSS variables (css-variables.css, css-variables.source.less)" + @@ -129,12 +138,14 @@ async function handleBuild(argv) { graph = await graphFromStaticFile({ filePath: argv.dependencyDefinition, rootConfigPath: argv.config, - versionOverride: argv.frameworkVersion + versionOverride: argv.frameworkVersion, + cacheMode: argv.cacheMode, }); } else { graph = await graphFromPackageDependencies({ rootConfigPath: argv.config, versionOverride: argv.frameworkVersion, + cacheMode: argv.cacheMode, workspaceConfigPath: argv.workspaceConfig, workspaceName: argv.workspace === false ? null : argv.workspace, }); diff --git a/lib/cli/commands/serve.js b/lib/cli/commands/serve.js index 93f8d6b9..c9a82028 100644 --- a/lib/cli/commands/serve.js +++ b/lib/cli/commands/serve.js @@ -65,11 +65,20 @@ serve.builder = function(cli) { describe: "Overrides the framework version defined by the project", type: "string" }) + .option("cache-mode", { + describe: + "Cache mode to use when consuming SNAPSHOT versions of a framework: 'Default', 'Force', or 'Off'. " + + "The 'Default' behavior is to invalidate the cache after 9 hours. 'Force' uses the cache only and " + + "does not create any requests. 'Off' invalidates any existing cache and updates from the repository", + type: "string", + default: "Default", + choices: ["Default", "Force", "Off"] + }) .example("ui5 serve", "Start a web server for the current project") .example("ui5 serve --h2", "Enable the HTTP/2 protocol for the web server (requires SSL certificate)") .example("ui5 serve --config /path/to/ui5.yaml", "Use the project configuration from a custom path") - .example("ui5 serve --translator static:/path/to/projectDependencies.yaml", - "Use a \"static\" translator with translator parameters.") + .example("ui5 serve --dependency-definition /path/to/projectDependencies.yaml", + "Use a static dependency definition file") .example("ui5 serve --port 1337 --open tests/QUnit.html", "Listen to port 1337 and launch default browser with http://localhost:1337/test/QUnit.html"); }; @@ -83,12 +92,14 @@ serve.handler = async function(argv) { if (argv.dependencyDefinition) { graph = await graphFromStaticFile({ filePath: argv.dependencyDefinition, - versionOverride: argv.frameworkVersion + versionOverride: argv.frameworkVersion, + cacheMode: argv.cacheMode, }); } else { graph = await graphFromPackageDependencies({ rootConfigPath: argv.config, versionOverride: argv.frameworkVersion, + cacheMode: argv.cacheMode, workspaceConfigPath: argv.workspaceConfig, workspaceName: argv.workspace === false ? null : argv.workspace, }); diff --git a/lib/cli/commands/tree.js b/lib/cli/commands/tree.js index 1079731e..519f3bba 100644 --- a/lib/cli/commands/tree.js +++ b/lib/cli/commands/tree.js @@ -16,6 +16,15 @@ tree.builder = function(cli) { describe: "Overrides the framework version defined by the project", type: "string" + }) + .option("cache-mode", { + describe: + "Cache mode to use when consuming SNAPSHOT versions of a framework: 'Default', 'Force', or 'Off'. " + + "The 'Default' behavior is to invalidate the cache after 9 hours. 'Force' uses the cache only and " + + "does not create any requests. 'Off' invalidates any existing cache and updates from the repository", + type: "string", + default: "Default", + choices: ["Default", "Force", "Off"] }); }; @@ -30,12 +39,14 @@ tree.handler = async function(argv) { if (argv.dependencyDefinition) { graph = await graphFromStaticFile({ filePath: argv.dependencyDefinition, - versionOverride: argv.frameworkVersion + versionOverride: argv.frameworkVersion, + cacheMode: argv.cacheMode, }); } else { graph = await graphFromPackageDependencies({ rootConfigPath: argv.config, versionOverride: argv.frameworkVersion, + cacheMode: argv.cacheMode, workspaceConfigPath: argv.workspaceConfig, workspaceName: argv.workspace === false ? null : argv.workspace, }); diff --git a/test/lib/cli/commands/build.js b/test/lib/cli/commands/build.js index 4b672c92..3e0e0ca3 100644 --- a/test/lib/cli/commands/build.js +++ b/test/lib/cli/commands/build.js @@ -23,6 +23,8 @@ function getDefaultArgv() { "cleanDest": false, "experimental-css-variables": false, "experimentalCssVariables": false, + "cache-mode": "Default", + "cacheMode": "Default", "$0": "ui5" }; } @@ -127,6 +129,26 @@ test.serial("ui5 build --framework-version", async (t) => { versionOverride: "1.99.0", workspaceConfigPath: undefined, workspaceName: undefined, + cacheMode: "Default", + }, "generateProjectGraph.graphFromPackageDependencies got called with expected arguments" + ); +}); + +test.serial("ui5 build --cache-mode", async (t) => { + const {build, argv, graphFromPackageDependenciesStub} = t.context; + + argv.cacheMode = "Off"; + + await build.handler(argv); + + t.deepEqual( + graphFromPackageDependenciesStub.getCall(0).args[0], + { + rootConfigPath: undefined, + versionOverride: undefined, + workspaceConfigPath: undefined, + workspaceName: undefined, + cacheMode: "Off", }, "generateProjectGraph.graphFromPackageDependencies got called with expected arguments" ); }); @@ -145,6 +167,7 @@ test.serial("ui5 build --config", async (t) => { versionOverride: undefined, workspaceConfigPath: undefined, workspaceName: undefined, + cacheMode: "Default", }, "generateProjectGraph.graphFromPackageDependencies got called with expected arguments" ); }); @@ -163,6 +186,7 @@ test.serial("ui5 build --workspace", async (t) => { versionOverride: undefined, workspaceConfigPath: undefined, workspaceName: "dolphin", + cacheMode: "Default", }, "generateProjectGraph.graphFromPackageDependencies got called with expected arguments" ); }); @@ -181,6 +205,7 @@ test.serial("ui5 build --no-workspace", async (t) => { versionOverride: undefined, workspaceConfigPath: undefined, workspaceName: null, + cacheMode: "Default", }, "generateProjectGraph.graphFromPackageDependencies got called with expected arguments" ); }); @@ -200,6 +225,7 @@ test.serial("ui5 build --workspace-config", async (t) => { versionOverride: undefined, workspaceConfigPath: fakePath, workspaceName: undefined, + cacheMode: "Default", }, "generateProjectGraph.graphFromPackageDependencies got called with expected arguments" ); }); @@ -217,6 +243,7 @@ test.serial("ui5 build --dependency-definition", async (t) => { filePath: "dependencies.yaml", rootConfigPath: undefined, versionOverride: undefined, + cacheMode: "Default", }, "generateProjectGraph.graphFromStaticFile got called with expected arguments" ); }); @@ -235,6 +262,7 @@ test.serial("ui5 build --dependency-definition --config", async (t) => { filePath: "dependencies.yaml", rootConfigPath: "ui5-test.yaml", versionOverride: undefined, + cacheMode: "Default", }, "generateProjectGraph.graphFromStaticFile got called with expected arguments" ); }); @@ -254,6 +282,7 @@ test.serial("ui5 build --dependency-definition --config --framework-version", as filePath: "dependencies.yaml", rootConfigPath: "ui5-test.yaml", versionOverride: "1.99.0", + cacheMode: "Default", }, "generateProjectGraph.graphFromStaticFile got called with expected arguments" ); }); diff --git a/test/lib/cli/commands/serve.js b/test/lib/cli/commands/serve.js index 2767209a..4b0fc883 100644 --- a/test/lib/cli/commands/serve.js +++ b/test/lib/cli/commands/serve.js @@ -24,6 +24,8 @@ function getDefaultArgv() { "sapCspPolicies": false, "serve-csp-reports": false, "serveCspReports": false, + "cache-mode": "Default", + "cacheMode": "Default", "$0": "ui5" }; } @@ -87,6 +89,7 @@ test.serial("ui5 serve: default", async (t) => { t.deepEqual(graph.graphFromPackageDependencies.getCall(0).args, [{ rootConfigPath: undefined, versionOverride: undefined, workspaceConfigPath: undefined, workspaceName: undefined, + cacheMode: "Default", }]); t.is(t.context.consoleOutput, `Server started @@ -132,6 +135,7 @@ test.serial("ui5 serve --h2", async (t) => { t.deepEqual(graph.graphFromPackageDependencies.getCall(0).args, [{ rootConfigPath: undefined, versionOverride: undefined, workspaceConfigPath: undefined, workspaceName: undefined, + cacheMode: "Default", }]); t.is(t.context.consoleOutput, `Server started @@ -173,6 +177,7 @@ test.serial("ui5 serve --accept-remote-connections", async (t) => { t.deepEqual(graph.graphFromPackageDependencies.getCall(0).args, [{ rootConfigPath: undefined, versionOverride: undefined, workspaceConfigPath: undefined, workspaceName: undefined, + cacheMode: "Default", }]); t.is(t.context.consoleOutput, ` @@ -216,6 +221,7 @@ test.serial("ui5 serve --open", async (t) => { t.deepEqual(graph.graphFromPackageDependencies.getCall(0).args, [{ rootConfigPath: undefined, versionOverride: undefined, workspaceConfigPath: undefined, workspaceName: undefined, + cacheMode: "Default", }]); t.is(t.context.consoleOutput, `Server started @@ -256,6 +262,7 @@ test.serial("ui5 serve --open (opens default url)", async (t) => { t.deepEqual(graph.graphFromPackageDependencies.getCall(0).args, [{ rootConfigPath: undefined, versionOverride: undefined, workspaceConfigPath: undefined, workspaceName: undefined, + cacheMode: "Default", }]); t.is(t.context.consoleOutput, `Server started @@ -297,6 +304,7 @@ test.serial("ui5 serve --config", async (t) => { t.deepEqual(graph.graphFromPackageDependencies.getCall(0).args, [{ rootConfigPath: fakePath, versionOverride: undefined, workspaceConfigPath: undefined, workspaceName: undefined, + cacheMode: "Default", }]); t.is(t.context.consoleOutput, `Server started @@ -332,6 +340,7 @@ test.serial("ui5 serve --dependency-definition", async (t) => { t.is(graph.graphFromStaticFile.callCount, 1); t.deepEqual(graph.graphFromStaticFile.getCall(0).args, [{ filePath: fakePath, versionOverride: undefined, + cacheMode: "Default", }]); t.is(t.context.consoleOutput, `Server started @@ -367,6 +376,43 @@ test.serial("ui5 serve --framework-version", async (t) => { t.deepEqual(graph.graphFromPackageDependencies.getCall(0).args, [{ rootConfigPath: undefined, versionOverride: "1.234.5", workspaceConfigPath: undefined, workspaceName: undefined, + cacheMode: "Default", + }]); + + t.is(t.context.consoleOutput, `Server started +URL: http://localhost:8080 +`); + + t.is(server.serve.callCount, 1); + t.deepEqual(server.serve.getCall(0).args, [ + fakeGraph, + { + acceptRemoteConnections: false, + cert: undefined, + changePortIfInUse: true, + h2: false, + key: undefined, + port: 8080, + sendSAPTargetCSP: false, + serveCSPReports: false, + simpleIndex: false, + } + ]); +}); + +test.serial("ui5 serve --cache-mode", async (t) => { + const {argv, serve, graph, server, fakeGraph} = t.context; + + argv.cacheMode = "Force"; + + await serve.handler(argv); + + t.is(graph.graphFromStaticFile.callCount, 0); + t.is(graph.graphFromPackageDependencies.callCount, 1); + t.deepEqual(graph.graphFromPackageDependencies.getCall(0).args, [{ + rootConfigPath: undefined, versionOverride: undefined, + workspaceConfigPath: undefined, workspaceName: undefined, + cacheMode: "Force", }]); t.is(t.context.consoleOutput, `Server started @@ -402,6 +448,7 @@ test.serial("ui5 serve --workspace", async (t) => { t.deepEqual(graph.graphFromPackageDependencies.getCall(0).args, [{ rootConfigPath: undefined, versionOverride: undefined, workspaceConfigPath: undefined, workspaceName: "dolphin", + cacheMode: "Default", }]); t.is(t.context.consoleOutput, `Server started @@ -437,6 +484,7 @@ test.serial("ui5 serve --no-workspace", async (t) => { t.deepEqual(graph.graphFromPackageDependencies.getCall(0).args, [{ rootConfigPath: undefined, versionOverride: undefined, workspaceConfigPath: undefined, workspaceName: null, + cacheMode: "Default", }]); t.is(t.context.consoleOutput, `Server started @@ -473,6 +521,7 @@ test.serial("ui5 serve --workspace-config", async (t) => { t.deepEqual(graph.graphFromPackageDependencies.getCall(0).args, [{ rootConfigPath: undefined, versionOverride: undefined, workspaceConfigPath: fakePath, workspaceName: undefined, + cacheMode: "Default", }]); t.is(t.context.consoleOutput, `Server started @@ -508,6 +557,7 @@ test.serial("ui5 serve --sap-csp-policies", async (t) => { t.deepEqual(graph.graphFromPackageDependencies.getCall(0).args, [{ rootConfigPath: undefined, versionOverride: undefined, workspaceConfigPath: undefined, workspaceName: undefined, + cacheMode: "Default", }]); t.is(t.context.consoleOutput, `Server started @@ -543,6 +593,7 @@ test.serial("ui5 serve --serve-csp-reports", async (t) => { t.deepEqual(graph.graphFromPackageDependencies.getCall(0).args, [{ rootConfigPath: undefined, versionOverride: undefined, workspaceConfigPath: undefined, workspaceName: undefined, + cacheMode: "Default", }]); t.is(t.context.consoleOutput, `Server started @@ -578,6 +629,7 @@ test.serial("ui5 serve --simple-index", async (t) => { t.deepEqual(graph.graphFromPackageDependencies.getCall(0).args, [{ rootConfigPath: undefined, versionOverride: undefined, workspaceConfigPath: undefined, workspaceName: undefined, + cacheMode: "Default", }]); t.is(t.context.consoleOutput, `Server started @@ -620,6 +672,7 @@ test.serial("ui5 serve with ui5.yaml port setting", async (t) => { t.deepEqual(graph.graphFromPackageDependencies.getCall(0).args, [{ rootConfigPath: undefined, versionOverride: undefined, workspaceConfigPath: undefined, workspaceName: undefined, + cacheMode: "Default", }]); t.is(t.context.consoleOutput, `Server started @@ -669,6 +722,7 @@ test.serial("ui5 serve --h2 with ui5.yaml port setting", async (t) => { t.deepEqual(graph.graphFromPackageDependencies.getCall(0).args, [{ rootConfigPath: undefined, versionOverride: undefined, workspaceConfigPath: undefined, workspaceName: undefined, + cacheMode: "Default", }]); t.is(t.context.consoleOutput, `Server started @@ -725,6 +779,7 @@ test.serial("ui5 serve --h2 with ui5.yaml port setting and port CLI argument", a t.deepEqual(graph.graphFromPackageDependencies.getCall(0).args, [{ rootConfigPath: undefined, versionOverride: undefined, workspaceConfigPath: undefined, workspaceName: undefined, + cacheMode: "Default", }]); t.is(t.context.consoleOutput, `Server started diff --git a/test/lib/cli/commands/tree.js b/test/lib/cli/commands/tree.js index b5c25272..873506ac 100644 --- a/test/lib/cli/commands/tree.js +++ b/test/lib/cli/commands/tree.js @@ -13,6 +13,8 @@ function getDefaultArgv() { "logLevel": "info", "perf": false, "silent": false, + "cache-mode": "Default", + "cacheMode": "Default", "$0": "ui5" }; } @@ -71,6 +73,7 @@ test.serial("ui5 tree (Without dependencies)", async (t) => { t.deepEqual(graph.graphFromPackageDependencies.getCall(0).args, [{ rootConfigPath: undefined, versionOverride: undefined, workspaceConfigPath: undefined, workspaceName: undefined, + cacheMode: "Default", }]); t.is(t.context.consoleOutput, @@ -136,6 +139,7 @@ test.serial("ui5 tree", async (t) => { t.deepEqual(graph.graphFromPackageDependencies.getCall(0).args, [{ rootConfigPath: undefined, versionOverride: undefined, workspaceConfigPath: undefined, workspaceName: undefined, + cacheMode: "Default", }]); t.is(t.context.consoleOutput, @@ -200,6 +204,7 @@ test.serial("ui5 tree (With extensions)", async (t) => { t.deepEqual(graph.graphFromPackageDependencies.getCall(0).args, [{ rootConfigPath: undefined, versionOverride: undefined, workspaceConfigPath: undefined, workspaceName: undefined, + cacheMode: "Default", }]); t.is(t.context.consoleOutput, @@ -244,6 +249,7 @@ test.serial("ui5 tree --perf", async (t) => { t.deepEqual(graph.graphFromPackageDependencies.getCall(0).args, [{ rootConfigPath: undefined, versionOverride: undefined, workspaceConfigPath: undefined, workspaceName: undefined, + cacheMode: "Default", }]); t.is(t.context.consoleOutput, @@ -283,6 +289,45 @@ test.serial("ui5 tree --framework-version", async (t) => { t.deepEqual(graph.graphFromPackageDependencies.getCall(0).args, [{ rootConfigPath: undefined, versionOverride: "1.234.5", workspaceConfigPath: undefined, workspaceName: undefined, + cacheMode: "Default", + }]); + + t.is(t.context.consoleOutput, + `${chalk.bold.underline("Dependencies (1):")} +╰─ ${chalk.bold("project1")} ${chalk.inverse("test/project1")} ${chalk.dim("(1.0.0, application) ")}\ +${chalk.dim.italic("/home/project1")} + +${chalk.bold.underline("Extensions (0):")} +${chalk.italic("None")} +`); +}); + +test.serial("ui5 tree --cache-mode", async (t) => { + const {argv, tree, traverseBreadthFirst, graph} = t.context; + + argv.cacheMode = "Force"; + + traverseBreadthFirst.callsFake(async (fn) => { + await fn({ + project: { + getName: sinon.stub().returns("project1"), + getNamespace: sinon.stub().returns("test/project1"), + getVersion: sinon.stub().returns("1.0.0"), + getType: sinon.stub().returns("application"), + getRootPath: sinon.stub().returns("/home/project1") + }, + dependencies: [] + }); + }); + + await tree.handler(argv); + + t.is(graph.graphFromStaticFile.callCount, 0); + t.is(graph.graphFromPackageDependencies.callCount, 1); + t.deepEqual(graph.graphFromPackageDependencies.getCall(0).args, [{ + rootConfigPath: undefined, versionOverride: undefined, + workspaceConfigPath: undefined, workspaceName: undefined, + cacheMode: "Force", }]); t.is(t.context.consoleOutput, @@ -321,6 +366,7 @@ test.serial("ui5 tree --config", async (t) => { t.deepEqual(graph.graphFromPackageDependencies.getCall(0).args, [{ rootConfigPath: fakePath, versionOverride: undefined, workspaceConfigPath: undefined, workspaceName: undefined, + cacheMode: "Default", }]); t.is(t.context.consoleOutput, @@ -358,6 +404,7 @@ test.serial("ui5 tree --workspace", async (t) => { t.deepEqual(graph.graphFromPackageDependencies.getCall(0).args, [{ rootConfigPath: undefined, versionOverride: undefined, workspaceConfigPath: undefined, workspaceName: "dolphin", + cacheMode: "Default", }]); t.is(t.context.consoleOutput, @@ -395,6 +442,7 @@ test.serial("ui5 tree --no-workspace", async (t) => { t.deepEqual(graph.graphFromPackageDependencies.getCall(0).args, [{ rootConfigPath: undefined, versionOverride: undefined, workspaceConfigPath: undefined, workspaceName: null, + cacheMode: "Default", }]); t.is(t.context.consoleOutput, @@ -433,6 +481,7 @@ test.serial("ui5 tree --workspace-config", async (t) => { t.deepEqual(graph.graphFromPackageDependencies.getCall(0).args, [{ rootConfigPath: undefined, versionOverride: undefined, workspaceConfigPath: fakePath, workspaceName: undefined, + cacheMode: "Default", }]); t.is(t.context.consoleOutput, @@ -468,9 +517,9 @@ test.serial("ui5 tree --dependency-definition", async (t) => { t.is(graph.graphFromPackageDependencies.callCount, 0); t.is(graph.graphFromStaticFile.callCount, 1); - t.deepEqual(graph.graphFromStaticFile.getCall(0).args, [ - {filePath: fakePath, versionOverride: undefined} - ]); + t.deepEqual(graph.graphFromStaticFile.getCall(0).args, [{ + filePath: fakePath, versionOverride: undefined, cacheMode: "Default" + }]); t.is(t.context.consoleOutput, `${chalk.bold.underline("Dependencies (1):")}