release-it 19.0.0-next.4 → 19.0.0-next.5
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/bin/release-it.js +0 -5
- package/lib/config.js +113 -103
- package/lib/index.js +2 -10
- package/lib/plugin/git/Git.js +2 -2
- package/lib/plugin/github/GitHub.js +2 -2
- package/lib/plugin/gitlab/GitLab.js +2 -2
- package/lib/shell.js +6 -6
- package/package.json +6 -7
- package/test/args.js +3 -3
- package/test/config.js +146 -71
- package/test/git.init.js +30 -30
- package/test/git.js +26 -26
- package/test/github.js +21 -21
- package/test/gitlab.js +27 -27
- package/test/npm.js +31 -31
- package/test/prompt.js +6 -5
- package/test/shell.js +5 -5
- package/test/spinner.js +8 -5
- package/test/stub/config/remote/.release-it.json +5 -0
- package/test/stub/config/remote/sub/.release-it.json +5 -0
- package/test/tasks.interactive.js +20 -13
- package/test/tasks.js +1 -1
- package/test/util/fetch.js +32 -0
- package/test/util/helpers.js +13 -8
- package/test/util/index.js +2 -1
- package/test/version.js +42 -42
package/bin/release-it.js
CHANGED
|
@@ -1,15 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import updater from 'update-notifier';
|
|
4
3
|
import release from '../lib/cli.js';
|
|
5
|
-
import { readJSON } from '../lib/util.js';
|
|
6
4
|
import { parseCliArguments } from '../lib/args.js';
|
|
7
5
|
|
|
8
|
-
const pkg = readJSON(new URL('../package.json', import.meta.url));
|
|
9
|
-
|
|
10
6
|
const options = parseCliArguments([].slice.call(process.argv, 2));
|
|
11
7
|
|
|
12
|
-
updater({ pkg: pkg }).notify();
|
|
13
8
|
release(options).then(
|
|
14
9
|
() => process.exit(0),
|
|
15
10
|
({ code }) => process.exit(Number.isInteger(code) ? code : 1)
|
package/lib/config.js
CHANGED
|
@@ -1,121 +1,31 @@
|
|
|
1
1
|
import util from 'node:util';
|
|
2
|
-
import
|
|
3
|
-
import parseToml from '@iarna/toml/parse-string.js';
|
|
2
|
+
import assert from 'node:assert';
|
|
4
3
|
import { isCI } from 'ci-info';
|
|
5
4
|
import defaultsDeep from '@nodeutils/defaults-deep';
|
|
6
5
|
import { isObjectStrict } from '@phun-ky/typeof';
|
|
7
6
|
import merge from 'lodash.merge';
|
|
8
7
|
import get from 'lodash.get';
|
|
9
|
-
import {
|
|
8
|
+
import { loadConfig as loadC12 } from 'c12';
|
|
9
|
+
import { getSystemInfo, readJSON } from './util.js';
|
|
10
10
|
|
|
11
11
|
const debug = util.debug('release-it:config');
|
|
12
12
|
const defaultConfig = readJSON(new URL('../config/release-it.json', import.meta.url));
|
|
13
13
|
|
|
14
|
-
const searchPlaces = [
|
|
15
|
-
'package.json',
|
|
16
|
-
'.release-it.json',
|
|
17
|
-
'.release-it.js',
|
|
18
|
-
'.release-it.ts',
|
|
19
|
-
'.release-it.cjs',
|
|
20
|
-
'.release-it.yaml',
|
|
21
|
-
'.release-it.yml',
|
|
22
|
-
'.release-it.toml'
|
|
23
|
-
];
|
|
24
|
-
|
|
25
|
-
const loaders = {
|
|
26
|
-
'.toml': (_, content) => parseToml(content)
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const getLocalConfig = ({ file, dir = process.cwd() }) => {
|
|
30
|
-
let localConfig = {};
|
|
31
|
-
if (file === false) return localConfig;
|
|
32
|
-
const explorer = cosmiconfigSync('release-it', {
|
|
33
|
-
searchPlaces,
|
|
34
|
-
loaders
|
|
35
|
-
});
|
|
36
|
-
const result = file ? explorer.load(file) : explorer.search(dir);
|
|
37
|
-
if (result && typeof result.config === 'string') {
|
|
38
|
-
throw new Error(`Invalid configuration file at ${result.filepath}`);
|
|
39
|
-
}
|
|
40
|
-
debug({ cosmiconfig: result });
|
|
41
|
-
return result && isObjectStrict(result.config) ? result.config : localConfig;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
const fetchConfigurationFromGitHub = async configuration => {
|
|
45
|
-
const docs = 'https://github.com/release-it/release-it/blob/main/docs/configuration.md';
|
|
46
|
-
|
|
47
|
-
const regex = /^github:([^/]+)\/([^#:]+)(?::([^#]+))?(?:#(.+))?$/;
|
|
48
|
-
const match = configuration.match(regex);
|
|
49
|
-
|
|
50
|
-
if (!match) {
|
|
51
|
-
throw e(`Invalid Extended Configuration from GitHub: ${configuration}`, docs);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const [, owner, repo, file = '.release-it.json', tag] = match;
|
|
55
|
-
const ref = tag ? `refs/tags/${tag}` : 'HEAD';
|
|
56
|
-
const url = new URL(`https://raw.githubusercontent.com/${owner}/${repo}/${ref}/${file}`);
|
|
57
|
-
|
|
58
|
-
const response = await fetch(url);
|
|
59
|
-
|
|
60
|
-
if (!response.ok) {
|
|
61
|
-
throw e(`Failed to fetch ${url}: ${response.statusText}`, docs);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return response.json();
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
const getRemoteConfiguration = async configuration => {
|
|
68
|
-
return fetchConfigurationFromGitHub(configuration);
|
|
69
|
-
};
|
|
70
|
-
|
|
71
14
|
class Config {
|
|
72
15
|
constructor(config = {}) {
|
|
73
16
|
this.constructorConfig = config;
|
|
74
|
-
this.localConfig = getLocalConfig({ file: config.config, dir: config.configDir });
|
|
75
|
-
this.options = this.mergeOptions();
|
|
76
|
-
this.options = this.expandPreReleaseShorthand(this.options);
|
|
77
17
|
this.contextOptions = {};
|
|
78
18
|
debug({ system: getSystemInfo() });
|
|
79
|
-
debug(this.options);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
expandPreReleaseShorthand(options) {
|
|
83
|
-
const { increment, preRelease, preReleaseId, snapshot, preReleaseBase } = options;
|
|
84
|
-
const isPreRelease = Boolean(preRelease) || Boolean(snapshot);
|
|
85
|
-
const inc = snapshot ? 'prerelease' : increment;
|
|
86
|
-
const preId = typeof preRelease === 'string' ? preRelease : typeof snapshot === 'string' ? snapshot : preReleaseId;
|
|
87
|
-
options.version = {
|
|
88
|
-
increment: inc,
|
|
89
|
-
isPreRelease,
|
|
90
|
-
preReleaseId: preId,
|
|
91
|
-
preReleaseBase
|
|
92
|
-
};
|
|
93
|
-
if (typeof snapshot === 'string' && options.git) {
|
|
94
|
-
// Pre set and hard code some options
|
|
95
|
-
options.git.tagMatch = `0.0.0-${snapshot}.[0-9]*`;
|
|
96
|
-
options.git.getLatestTagFromAllRefs = true;
|
|
97
|
-
options.git.requireBranch = '!main';
|
|
98
|
-
options.git.requireUpstream = false;
|
|
99
|
-
options.npm.ignoreVersion = true;
|
|
100
|
-
}
|
|
101
|
-
return options;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
mergeOptions() {
|
|
105
|
-
return defaultsDeep(
|
|
106
|
-
{},
|
|
107
|
-
this.constructorConfig,
|
|
108
|
-
{
|
|
109
|
-
ci: isCI
|
|
110
|
-
},
|
|
111
|
-
this.localConfig,
|
|
112
|
-
this.defaultConfig
|
|
113
|
-
);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
mergeRemoteOptions(remoteConfiguration) {
|
|
117
|
-
return merge({}, this.options, remoteConfiguration);
|
|
118
19
|
}
|
|
20
|
+
|
|
21
|
+
async init() {
|
|
22
|
+
await loadOptions(this.constructorConfig).then(({ options, localConfig }) => {
|
|
23
|
+
this._options = options;
|
|
24
|
+
this._localConfig = localConfig;
|
|
25
|
+
debug(this._options);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
119
29
|
getContext(path) {
|
|
120
30
|
const context = merge({}, this.options, this.contextOptions);
|
|
121
31
|
return path ? get(context, path) : context;
|
|
@@ -169,8 +79,108 @@ class Config {
|
|
|
169
79
|
get isChangelog() {
|
|
170
80
|
return Boolean(this.options['changelog']);
|
|
171
81
|
}
|
|
82
|
+
|
|
83
|
+
get options() {
|
|
84
|
+
assert(this._options, `The "options" not resolve yet`);
|
|
85
|
+
return this._options;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
get localConfig() {
|
|
89
|
+
assert(this._localConfig, `The "localConfig" not resolve yet`);
|
|
90
|
+
return this._localConfig;
|
|
91
|
+
}
|
|
172
92
|
}
|
|
173
93
|
|
|
174
|
-
|
|
94
|
+
async function loadOptions(constructorConfig) {
|
|
95
|
+
const localConfig = await loadLocalConfig(constructorConfig);
|
|
96
|
+
const merged = defaultsDeep(
|
|
97
|
+
{},
|
|
98
|
+
constructorConfig,
|
|
99
|
+
{
|
|
100
|
+
ci: isCI
|
|
101
|
+
},
|
|
102
|
+
localConfig,
|
|
103
|
+
defaultConfig
|
|
104
|
+
);
|
|
105
|
+
const expanded = expandPreReleaseShorthand(merged);
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
options: expanded,
|
|
109
|
+
localConfig
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function expandPreReleaseShorthand(options) {
|
|
114
|
+
const { increment, preRelease, preReleaseId, snapshot, preReleaseBase } = options;
|
|
115
|
+
const isPreRelease = Boolean(preRelease) || Boolean(snapshot);
|
|
116
|
+
const inc = snapshot ? 'prerelease' : increment;
|
|
117
|
+
const preId = typeof preRelease === 'string' ? preRelease : typeof snapshot === 'string' ? snapshot : preReleaseId;
|
|
118
|
+
options.version = {
|
|
119
|
+
increment: inc,
|
|
120
|
+
isPreRelease,
|
|
121
|
+
preReleaseId: preId,
|
|
122
|
+
preReleaseBase
|
|
123
|
+
};
|
|
124
|
+
if (typeof snapshot === 'string' && options.git) {
|
|
125
|
+
// Pre set and hard code some options
|
|
126
|
+
options.git.tagMatch = `0.0.0-${snapshot}.[0-9]*`;
|
|
127
|
+
options.git.getLatestTagFromAllRefs = true;
|
|
128
|
+
options.git.requireBranch = '!main';
|
|
129
|
+
options.git.requireUpstream = false;
|
|
130
|
+
options.npm.ignoreVersion = true;
|
|
131
|
+
}
|
|
132
|
+
return options;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async function loadLocalConfig(constructorConfig) {
|
|
136
|
+
const file = resolveFile();
|
|
137
|
+
const dir = resolveDir();
|
|
138
|
+
const extend = resolveExtend();
|
|
139
|
+
const defaultConfig = resolveDefaultConfig();
|
|
140
|
+
|
|
141
|
+
if (file === false) return {};
|
|
142
|
+
|
|
143
|
+
const resolvedConfig = await loadC12({
|
|
144
|
+
name: 'release-it',
|
|
145
|
+
configFile: file,
|
|
146
|
+
packageJson: true,
|
|
147
|
+
rcFile: false,
|
|
148
|
+
envName: false,
|
|
149
|
+
cwd: dir,
|
|
150
|
+
extend,
|
|
151
|
+
defaultConfig
|
|
152
|
+
}).catch(() => {
|
|
153
|
+
throw new Error(`Invalid configuration file at ${file}`);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
if (Object.keys(resolvedConfig.config).length === 0) {
|
|
157
|
+
throw new Error(`no such file ${resolvedConfig.configFile}`);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
debug('Loaded local config', resolvedConfig.config);
|
|
161
|
+
return isObjectStrict(resolvedConfig.config) ? resolvedConfig.config : {};
|
|
162
|
+
|
|
163
|
+
function resolveFile() {
|
|
164
|
+
if (constructorConfig.config === false) return false;
|
|
165
|
+
|
|
166
|
+
if (constructorConfig.config === true) return '.release-it';
|
|
167
|
+
|
|
168
|
+
return constructorConfig.config ?? '.release-it';
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function resolveDir() {
|
|
172
|
+
return constructorConfig.configDir ?? process.cwd();
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function resolveExtend() {
|
|
176
|
+
return constructorConfig.extends === false ? false : undefined;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function resolveDefaultConfig() {
|
|
180
|
+
return {
|
|
181
|
+
extends: constructorConfig.extends === false ? undefined : constructorConfig.extends
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
}
|
|
175
185
|
|
|
176
186
|
export default Config;
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getPlugins } from './plugin/factory.js';
|
|
2
2
|
import Logger from './log.js';
|
|
3
|
-
import Config
|
|
3
|
+
import Config from './config.js';
|
|
4
4
|
import Shell from './shell.js';
|
|
5
5
|
import Prompt from './prompt.js';
|
|
6
6
|
import Spinner from './spinner.js';
|
|
@@ -12,15 +12,7 @@ const runTasks = async (opts, di) => {
|
|
|
12
12
|
try {
|
|
13
13
|
Object.assign(container, di);
|
|
14
14
|
container.config = container.config || new Config(opts);
|
|
15
|
-
|
|
16
|
-
if (typeof container.config.options?.extends === 'string') {
|
|
17
|
-
/**
|
|
18
|
-
* If the configuration has an 'extends' property, fetch the remote configuration
|
|
19
|
-
* and merge it into the local configuration options.
|
|
20
|
-
*/
|
|
21
|
-
const remoteConfiguration = await getRemoteConfiguration(container.config.options.extends);
|
|
22
|
-
container.config.options = container.config.mergeRemoteOptions(remoteConfiguration);
|
|
23
|
-
}
|
|
15
|
+
await container.config.init();
|
|
24
16
|
|
|
25
17
|
const { config } = container;
|
|
26
18
|
const { isCI, isVerbose, verbosityLevel, isDryRun, isChangelog, isReleaseVersion } = config;
|
package/lib/plugin/git/Git.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EOL } from 'node:os';
|
|
2
|
-
import {
|
|
2
|
+
import { x } from 'tinyexec';
|
|
3
3
|
import matcher from 'wildcard-match';
|
|
4
4
|
import { format, e, fixArgs, once, castArray } from '../../util.js';
|
|
5
5
|
import GitBase from '../GitBase.js';
|
|
@@ -12,7 +12,7 @@ const options = { write: false };
|
|
|
12
12
|
const docs = 'https://git.io/release-it-git';
|
|
13
13
|
|
|
14
14
|
const isGitRepo = () =>
|
|
15
|
-
|
|
15
|
+
x('git', ['rev-parse', '--git-dir'], { throwOnError: true }).then(
|
|
16
16
|
() => true,
|
|
17
17
|
() => false
|
|
18
18
|
);
|
|
@@ -2,7 +2,7 @@ import { createReadStream, statSync } from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import open from 'open';
|
|
4
4
|
import { Octokit } from '@octokit/rest';
|
|
5
|
-
import {
|
|
5
|
+
import { glob } from 'tinyglobby';
|
|
6
6
|
import mime from 'mime-types';
|
|
7
7
|
import retry from 'async-retry';
|
|
8
8
|
import newGithubReleaseUrl from 'new-github-release-url';
|
|
@@ -336,7 +336,7 @@ class GitHub extends Release {
|
|
|
336
336
|
return true;
|
|
337
337
|
}
|
|
338
338
|
|
|
339
|
-
return
|
|
339
|
+
return glob(patterns).then(files => {
|
|
340
340
|
if (!files.length) {
|
|
341
341
|
this.log.warn(`octokit repos.uploadReleaseAssets: did not find "${assets}" relative to ${process.cwd()}`);
|
|
342
342
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import fs from 'node:fs'; // import fs here so it can be stubbed in tests
|
|
3
3
|
import { readFile } from 'node:fs/promises';
|
|
4
|
-
import {
|
|
4
|
+
import { glob } from 'tinyglobby';
|
|
5
5
|
import { Agent } from 'undici';
|
|
6
6
|
import Release from '../GitRelease.js';
|
|
7
7
|
import { format, e, castArray } from '../../util.js';
|
|
@@ -323,7 +323,7 @@ class GitLab extends Release {
|
|
|
323
323
|
return noop;
|
|
324
324
|
}
|
|
325
325
|
|
|
326
|
-
return
|
|
326
|
+
return glob(patterns).then(files => {
|
|
327
327
|
if (!files.length) {
|
|
328
328
|
this.log.warn(`gitlab releases#uploadAssets: could not find "${assets}" relative to ${process.cwd()}`);
|
|
329
329
|
}
|
package/lib/shell.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import util from 'node:util';
|
|
2
2
|
import childProcess from 'node:child_process';
|
|
3
|
-
import {
|
|
3
|
+
import { x } from 'tinyexec';
|
|
4
4
|
import { format } from './util.js';
|
|
5
5
|
|
|
6
6
|
const debug = util.debug('release-it:shell');
|
|
@@ -72,17 +72,17 @@ class Shell {
|
|
|
72
72
|
const [program, ...programArgs] = command;
|
|
73
73
|
|
|
74
74
|
try {
|
|
75
|
-
const { stdout: out, stderr } = await
|
|
75
|
+
const { stdout: out, stderr } = await x(program, programArgs, { throwOnError: true });
|
|
76
76
|
const stdout = out === '""' ? '' : out;
|
|
77
77
|
this.log.verbose(stdout, { isExternal });
|
|
78
78
|
debug({ command, options, stdout, stderr });
|
|
79
|
-
return Promise.resolve(stdout || stderr);
|
|
79
|
+
return Promise.resolve((stdout || stderr).trim());
|
|
80
80
|
} catch (err) {
|
|
81
|
-
if (err.stdout) {
|
|
82
|
-
this.log.log(`\n${err.stdout}`);
|
|
81
|
+
if (err.output.stdout) {
|
|
82
|
+
this.log.log(`\n${err.output.stdout}`);
|
|
83
83
|
}
|
|
84
84
|
debug(err);
|
|
85
|
-
return Promise.reject(new Error(err.stderr || err.message));
|
|
85
|
+
return Promise.reject(new Error(err.output.stderr || err.output.stdout || err.message));
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "release-it",
|
|
3
|
-
"version": "19.0.0-next.
|
|
3
|
+
"version": "19.0.0-next.5",
|
|
4
4
|
"description": "Generic CLI tool to automate versioning and package publishing-related tasks.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"build",
|
|
@@ -78,17 +78,14 @@
|
|
|
78
78
|
},
|
|
79
79
|
"license": "MIT",
|
|
80
80
|
"dependencies": {
|
|
81
|
-
"@iarna/toml": "2.2.5",
|
|
82
81
|
"@nodeutils/defaults-deep": "1.1.0",
|
|
83
82
|
"@octokit/rest": "21.1.1",
|
|
84
83
|
"@phun-ky/typeof": "1.2.4",
|
|
85
84
|
"async-retry": "1.3.3",
|
|
85
|
+
"c12": "2.0.4",
|
|
86
86
|
"ci-info": "^4.2.0",
|
|
87
|
-
"cosmiconfig": "9.0.0",
|
|
88
87
|
"eta": "3.5.0",
|
|
89
|
-
"execa": "9.5.2",
|
|
90
88
|
"git-url-parse": "16.0.1",
|
|
91
|
-
"globby": "14.1.0",
|
|
92
89
|
"inquirer": "12.5.2",
|
|
93
90
|
"issue-parser": "7.0.1",
|
|
94
91
|
"lodash.get": "4.4.2",
|
|
@@ -100,8 +97,9 @@
|
|
|
100
97
|
"os-name": "6.0.0",
|
|
101
98
|
"proxy-agent": "6.5.0",
|
|
102
99
|
"semver": "7.7.1",
|
|
100
|
+
"tinyexec": "1.0.1",
|
|
101
|
+
"tinyglobby": "0.2.12",
|
|
103
102
|
"undici": "6.21.2",
|
|
104
|
-
"update-notifier": "7.3.1",
|
|
105
103
|
"url-join": "5.0.0",
|
|
106
104
|
"wildcard-match": "5.1.4",
|
|
107
105
|
"yargs-parser": "21.1.1"
|
|
@@ -117,11 +115,12 @@
|
|
|
117
115
|
"globals": "16.0.0",
|
|
118
116
|
"installed-check": "9.3.0",
|
|
119
117
|
"knip": "5.48.0",
|
|
120
|
-
"mentoss": "0.9.
|
|
118
|
+
"mentoss": "0.9.2",
|
|
121
119
|
"mock-stdio": "1.0.3",
|
|
122
120
|
"prettier": "3.5.3",
|
|
123
121
|
"remark-cli": "12.0.1",
|
|
124
122
|
"remark-preset-webpro": "1.1.1",
|
|
123
|
+
"tar": "6.2.1",
|
|
125
124
|
"typescript": "5.8.3"
|
|
126
125
|
},
|
|
127
126
|
"overrides": {
|
package/test/args.js
CHANGED
|
@@ -2,7 +2,7 @@ import test from 'node:test';
|
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
3
|
import { parseCliArguments } from '../lib/args.js';
|
|
4
4
|
|
|
5
|
-
test(
|
|
5
|
+
test('should parse boolean arguments', () => {
|
|
6
6
|
const args = [
|
|
7
7
|
'--dry-run=false',
|
|
8
8
|
'--ci',
|
|
@@ -11,8 +11,8 @@ test("should parse boolean arguments", () => {
|
|
|
11
11
|
'--git.addUntrackedFiles=true',
|
|
12
12
|
'--git.commit=false',
|
|
13
13
|
'--no-git.tag',
|
|
14
|
-
'--git.commitMessage=test'
|
|
15
|
-
]
|
|
14
|
+
'--git.commitMessage=test'
|
|
15
|
+
];
|
|
16
16
|
|
|
17
17
|
const result = parseCliArguments(args);
|
|
18
18
|
|