@ui5/cli 3.0.0-rc.4 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/cli/base.js CHANGED
@@ -1,10 +1,12 @@
1
1
  import chalk from "chalk";
2
2
  import {isLogLevelEnabled} from "@ui5/logger";
3
+ import ConsoleWriter from "@ui5/logger/writers/Console";
3
4
 
4
5
  export default function(cli) {
5
6
  cli.usage("Usage: ui5 <command> [options]")
6
7
  .demandCommand(1, "Command required! Please have a look at the help documentation above.")
7
8
  .option("config", {
9
+ alias: "c",
8
10
  describe: "Path to project configuration file in YAML format",
9
11
  type: "string"
10
12
  })
@@ -13,31 +15,80 @@ export default function(cli) {
13
15
  "This option will disable resolution of node package dependencies.",
14
16
  type: "string"
15
17
  })
16
- .option("verbose", {
17
- describe: "Enable verbose logging.",
18
- type: "boolean"
18
+ .option("workspace-config", {
19
+ describe: "Path to workspace configuration file in YAML format",
20
+ type: "string"
21
+ })
22
+ .option("workspace", {
23
+ alias: "w",
24
+ describe: "Name of the workspace configuration to use",
25
+ default: "default",
26
+ type: "string"
19
27
  })
20
28
  .option("loglevel", {
21
29
  alias: "log-level",
22
- describe: "Set the logging level (error|warn|info|verbose|silly).",
30
+ describe: "Set the logging level (silent|error|warn|info|perf|verbose|silly).",
23
31
  default: "info",
24
- type: "string"
32
+ type: "string",
33
+ choices: ["silent", "error", "warn", "info", "perf", "verbose", "silly"]
34
+ })
35
+ .option("verbose", {
36
+ describe: "Enable verbose logging.",
37
+ default: false,
38
+ type: "boolean"
39
+ })
40
+ .option("perf", {
41
+ describe: "Enable performance measurements and related logging.",
42
+ default: false,
43
+ type: "boolean"
25
44
  })
26
- .option("x-perf", {
27
- describe: "Outputs performance measurements",
45
+ .option("silent", {
46
+ describe: "Disable all log output.",
28
47
  default: false,
29
48
  type: "boolean"
30
49
  })
50
+ .coerce([
51
+ // base.js
52
+ "config", "dependency-definition", "workspace-config", "workspace", "log-level",
53
+
54
+ // tree.js, build.js & serve.js
55
+ "framework-version",
56
+
57
+ // build.js
58
+ "dest",
59
+
60
+ // serve.js
61
+ "open", "port", "key", "cert",
62
+ ], (arg) => {
63
+ // If an option is specified multiple times, yargs creates an array for all the values,
64
+ // independently of whether the option is of type "array" or "string".
65
+ // This is unexpected for options listed above, which should all only have only one definitive value.
66
+ // The yargs behavior could be disabled by using the parserConfiguration "duplicate-arguments-array": true
67
+ // However, yargs would then cease to create arrays for those options where we *do* expect the
68
+ // automatic creation of arrays in case the option is specified multiple times. Like "--include-task".
69
+ // Also see https://github.com/yargs/yargs/issues/1318
70
+ // Note: This is not necessary for options of type "boolean"
71
+ if (Array.isArray(arg)) {
72
+ // If the option is specified multiple times, use the value of the last option
73
+ return arg[arg.length - 1];
74
+ }
75
+ return arg;
76
+ })
31
77
  .showHelpOnFail(true)
32
78
  .strict(true)
33
79
  .alias("help", "h")
34
80
  .alias("version", "v")
35
- .example("ui5 <command> --translator static:/path/to/projectDependencies.yaml",
36
- "Execute command using a \"static\" translator with translator parameters")
81
+ .example("ui5 <command> --dependency-definition /path/to/projectDependencies.yaml",
82
+ "Execute command using a static dependency tree instead of resolving node package dependencies")
37
83
  .example("ui5 <command> --config /path/to/ui5.yaml",
38
84
  "Execute command using a project configuration from custom path")
85
+ .example("ui5 <command> --workspace dolphin",
86
+ "Execute command using the 'dolphin' workspace of a ui5-workspace.yaml")
87
+ .example("ui5 <command> --log-level silly",
88
+ "Execute command with the maximum log output")
39
89
  .fail(function(msg, err, yargs) {
40
90
  if (err) {
91
+ ConsoleWriter.stop();
41
92
  // Exception
42
93
  if (isLogLevelEnabled("error")) {
43
94
  console.log("");
@@ -36,33 +36,39 @@ build.builder = function(cli) {
36
36
  describe: "A list of dependencies to be included in the build result. You can use the asterisk '*' as" +
37
37
  " an alias for including all dependencies in the build result. The listed dependencies cannot be" +
38
38
  " overruled by dependencies defined in 'exclude-dependency'.",
39
- type: "array"
39
+ type: "string",
40
+ array: true
40
41
  })
41
42
  .option("include-dependency-regexp", {
42
43
  describe: "A list of regular expressions defining dependencies to be included in the build result." +
43
44
  " This list is prioritized like 'include-dependency'.",
44
- type: "array"
45
+ type: "string",
46
+ array: true
45
47
  })
46
48
  .option("include-dependency-tree", {
47
49
  describe: "A list of dependencies to be included in the build result. Transitive dependencies are" +
48
50
  " implicitly included and do not need to be part of this list. These dependencies overrule" +
49
51
  " the selection of 'exclude-dependency-tree' but can be overruled by 'exclude-dependency'.",
50
- type: "array"
52
+ type: "string",
53
+ array: true
51
54
  })
52
55
  .option("exclude-dependency", {
53
56
  describe: "A list of dependencies to be excluded from the build result. The listed dependencies can" +
54
57
  " be overruled by dependencies defined in 'include-dependency'.",
55
- type: "array"
58
+ type: "string",
59
+ array: true
56
60
  })
57
61
  .option("exclude-dependency-regexp", {
58
62
  describe: "A list of regular expressions defining dependencies to be excluded from the build result." +
59
63
  " This list is prioritized like 'exclude-dependency'.",
60
- type: "array"
64
+ type: "string",
65
+ array: true
61
66
  })
62
67
  .option("exclude-dependency-tree", {
63
68
  describe: "A list of dependencies to be excluded from the build result. Transitive dependencies are" +
64
69
  " implicitly included and do not need to be part of this list.",
65
- type: "array"
70
+ type: "string",
71
+ array: true
66
72
  })
67
73
  .option("dest", {
68
74
  describe: "Path of build destination",
@@ -83,11 +89,13 @@ build.builder = function(cli) {
83
89
  .option("include-task", {
84
90
  describe: "A list of tasks to be added to the default execution set. " +
85
91
  "This option takes precedence over any excludes.",
86
- type: "array"
92
+ type: "string",
93
+ array: true
87
94
  })
88
95
  .option("exclude-task", {
89
96
  describe: "A list of tasks to be excluded from the default task execution set",
90
- type: "array"
97
+ type: "string",
98
+ array: true
91
99
  })
92
100
  .option("framework-version", {
93
101
  describe: "Overrides the framework version defined by the project",
@@ -126,7 +134,9 @@ async function handleBuild(argv) {
126
134
  } else {
127
135
  graph = await graphFromPackageDependencies({
128
136
  rootConfigPath: argv.config,
129
- versionOverride: argv.frameworkVersion
137
+ versionOverride: argv.frameworkVersion,
138
+ workspaceConfigPath: argv.workspaceConfig,
139
+ workspaceName: argv.workspace === false ? null : argv.workspace,
130
140
  });
131
141
  }
132
142
  const buildSettings = graph.getRoot().getBuilderSettings() || {};
@@ -88,7 +88,9 @@ serve.handler = async function(argv) {
88
88
  } else {
89
89
  graph = await graphFromPackageDependencies({
90
90
  rootConfigPath: argv.config,
91
- versionOverride: argv.frameworkVersion
91
+ versionOverride: argv.frameworkVersion,
92
+ workspaceConfigPath: argv.workspaceConfig,
93
+ workspaceName: argv.workspace === false ? null : argv.workspace,
92
94
  });
93
95
  }
94
96
 
@@ -22,7 +22,7 @@ tree.builder = function(cli) {
22
22
  tree.handler = async function(argv) {
23
23
  let startTime;
24
24
  let elapsedTime;
25
- if (argv.xPerf) {
25
+ if (argv.perf) {
26
26
  startTime = process.hrtime();
27
27
  }
28
28
  const {graphFromStaticFile, graphFromPackageDependencies} = await import("@ui5/project/graph");
@@ -35,11 +35,13 @@ tree.handler = async function(argv) {
35
35
  } else {
36
36
  graph = await graphFromPackageDependencies({
37
37
  rootConfigPath: argv.config,
38
- versionOverride: argv.frameworkVersion
38
+ versionOverride: argv.frameworkVersion,
39
+ workspaceConfigPath: argv.workspaceConfig,
40
+ workspaceName: argv.workspace === false ? null : argv.workspace,
39
41
  });
40
42
  }
41
43
 
42
- if (argv.xPerf) {
44
+ if (argv.perf) {
43
45
  elapsedTime = await getElapsedTime(startTime);
44
46
  }
45
47
 
@@ -55,9 +57,9 @@ tree.handler = async function(argv) {
55
57
  const connectorString = lastChild ? "╰─" : "├─";
56
58
  console.log(
57
59
  `${baseString}${connectorString} ${chalk.bold(project.getName())} ` +
58
- `${project.getNamespace ? chalk.inverse(project.getNamespace()) + " " : ""}` +
60
+ `${project.getNamespace() ? chalk.inverse(project.getNamespace()) + " " : ""}` +
59
61
  chalk.dim(`(${project.getVersion()}, ${project.getType()}) `) +
60
- chalk.dim.italic(`${project.getPath()}`)
62
+ chalk.dim.italic(`${project.getRootPath()}`)
61
63
  );
62
64
 
63
65
  const lastIdx = dependencies.length - 1;
@@ -88,12 +90,12 @@ tree.handler = async function(argv) {
88
90
  console.log(
89
91
  `${connectorString} ${extensionName} ` +
90
92
  chalk.dim(`(${extension.getVersion()}, ${extension.getType()}) `) +
91
- chalk.dim.italic(`${extension.getPath()}`));
93
+ chalk.dim.italic(`${extension.getRootPath()}`));
92
94
  });
93
95
  } else {
94
96
  console.log(chalk.italic(`None`));
95
97
  }
96
- if (argv.xPerf) {
98
+ if (argv.perf) {
97
99
  console.log("");
98
100
  console.log(chalk.blue(
99
101
  `Dependency graph generation took ${chalk.bold(elapsedTime)}`));
@@ -1,4 +1,4 @@
1
- import {setLogLevel, getLogger} from "@ui5/logger";
1
+ import {setLogLevel, isLogLevelEnabled, getLogger} from "@ui5/logger";
2
2
  import ConsoleWriter from "@ui5/logger/writers/Console";
3
3
  import {getVersion} from "../version.js";
4
4
  /**
@@ -7,13 +7,25 @@ import {getVersion} from "../version.js";
7
7
  * @param {object} argv logger arguments
8
8
  */
9
9
  export async function initLogger(argv) {
10
- ConsoleWriter.init();
11
-
12
- if (argv.loglevel) {
13
- setLogLevel(argv.loglevel);
10
+ if (argv.silent) {
11
+ setLogLevel("silent");
12
+ }
13
+ if (argv.perf) {
14
+ setLogLevel("perf");
14
15
  }
15
16
  if (argv.verbose) {
16
17
  setLogLevel("verbose");
18
+ }
19
+ if (argv.loglevel && argv.loglevel !== "info") {
20
+ // argv.loglevel defaults to "info", which is anyways already the Logger's default
21
+ // Therefore do not explicitly set it again in order to allow overwriting the log level
22
+ // using the UI5_LOG_LVL environment variable
23
+ setLogLevel(argv.loglevel);
24
+ }
25
+
26
+ // Initialize writer
27
+ ConsoleWriter.init();
28
+ if (isLogLevelEnabled("verbose")) {
17
29
  const log = getLogger("cli:middlewares:base");
18
30
  log.verbose(`using @ui5/cli version ${getVersion()}`);
19
31
  log.verbose(`using node version ${process.version}`);
@@ -33,7 +33,7 @@ export default async function({projectGraphOptions, libraries}) {
33
33
  const Resolver = getFrameworkResolver(project.getFrameworkName());
34
34
 
35
35
  const resolver = new Resolver({
36
- cwd: project.getPath(),
36
+ cwd: project.getRootPath(),
37
37
  version: project.getFrameworkVersion()
38
38
  });
39
39
 
@@ -1,7 +1,7 @@
1
1
  import path from "node:path";
2
2
  import {readFile, writeFile} from "node:fs/promises";
3
3
  import {loadAll, dump} from "js-yaml";
4
- import {fromYaml, getPosition, getValue} from "data-with-position";
4
+ import {fromYaml, getPosition, getValue, getKind} from "data-with-position";
5
5
  import {getLogger} from "@ui5/logger";
6
6
 
7
7
  const log = getLogger("cli:framework:updateYaml");
@@ -110,7 +110,23 @@ function getValueFromPath(data, path) {
110
110
  }
111
111
 
112
112
  function getPositionFromPath(positionData, path) {
113
- return getPosition(getValueFromPath(positionData, path));
113
+ const data = getValueFromPath(positionData, path);
114
+ const position = getPosition(data);
115
+ const kind = getKind(data);
116
+ if ((kind === "array" && data.length) || kind === "object") {
117
+ // data-with-position treats arrays and objects different from primitives:
118
+ // The end index of such nodes always reaches up to the beginning of the following node, instead of the end
119
+ // of the contained data.
120
+ // For example, if an array has entries, the end position of the array is *directly* at the beginning of
121
+ // the next node instead of at the end of the last entry.
122
+ // Typically this means one line and multiple columns *after* the array ended.
123
+ // However, if an array has no entries (e.g. "[]"), the end is directly after the end of that data and
124
+ // *not* in the next line (this appears to be an inconsistency).
125
+ // Therefore, in case we encounter an array *with entries*, or an object, we reset the end column to "1"
126
+ // to prevent replacing (i.e. removing) the indentation of the following node.
127
+ position.end.column = 1;
128
+ }
129
+ return position;
114
130
  }
115
131
 
116
132
  function formatValue(value, indent) {
@@ -146,10 +162,10 @@ export default async function({project, configPathOverride, data}) {
146
162
  if (path.isAbsolute(configPathOverride)) {
147
163
  configPath = configPathOverride;
148
164
  } else {
149
- configPath = path.join(project.getPath(), configPathOverride);
165
+ configPath = path.join(project.getRootPath(), configPathOverride);
150
166
  }
151
167
  } else {
152
- configPath = path.join(project.getPath(), "ui5.yaml");
168
+ configPath = path.join(project.getRootPath(), "ui5.yaml");
153
169
  }
154
170
 
155
171
  const configFile = await readFile(configPath, {encoding: "utf8"});
@@ -42,7 +42,7 @@ export default async function({projectGraphOptions, frameworkOptions}) {
42
42
  frameworkName: framework.name,
43
43
  frameworkVersion
44
44
  }, {
45
- cwd: project.getPath()
45
+ cwd: project.getRootPath()
46
46
  });
47
47
  }
48
48