@vltpkg/cli-sdk 1.0.0-rc.22 → 1.0.0-rc.24
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/dist/commands/bugs.d.ts +17 -0
- package/dist/commands/bugs.js +163 -0
- package/dist/commands/build.d.ts +24 -0
- package/dist/commands/build.js +101 -0
- package/dist/commands/cache.d.ts +64 -0
- package/dist/commands/cache.js +256 -0
- package/dist/commands/ci.d.ts +10 -0
- package/dist/commands/ci.js +40 -0
- package/dist/commands/config.d.ts +5 -0
- package/dist/commands/config.js +429 -0
- package/dist/commands/create.d.ts +8 -0
- package/dist/commands/create.js +102 -0
- package/dist/commands/docs.d.ts +17 -0
- package/dist/commands/docs.js +153 -0
- package/dist/commands/exec-cache.d.ts +48 -0
- package/dist/commands/exec-cache.js +145 -0
- package/dist/commands/exec-local.d.ts +5 -0
- package/dist/commands/exec-local.js +46 -0
- package/dist/commands/exec.d.ts +8 -0
- package/dist/commands/exec.js +161 -0
- package/dist/commands/help.d.ts +3 -0
- package/dist/commands/help.js +43 -0
- package/dist/commands/init.d.ts +7 -0
- package/dist/commands/init.js +116 -0
- package/dist/commands/install/reporter.d.ts +10 -0
- package/dist/commands/install/reporter.js +93 -0
- package/dist/commands/install.d.ts +27 -0
- package/dist/commands/install.js +80 -0
- package/dist/commands/list.d.ts +17 -0
- package/dist/commands/list.js +197 -0
- package/dist/commands/login.d.ts +3 -0
- package/dist/commands/login.js +22 -0
- package/dist/commands/logout.d.ts +3 -0
- package/dist/commands/logout.js +22 -0
- package/dist/commands/pack.d.ts +31 -0
- package/dist/commands/pack.js +205 -0
- package/dist/commands/ping.d.ts +17 -0
- package/dist/commands/ping.js +114 -0
- package/dist/commands/pkg.d.ts +6 -0
- package/dist/commands/pkg.js +232 -0
- package/dist/commands/publish.d.ts +21 -0
- package/dist/commands/publish.js +282 -0
- package/dist/commands/query.d.ts +18 -0
- package/dist/commands/query.js +216 -0
- package/dist/commands/repo.d.ts +17 -0
- package/dist/commands/repo.js +157 -0
- package/dist/commands/run-exec.d.ts +5 -0
- package/dist/commands/run-exec.js +40 -0
- package/dist/commands/run.d.ts +5 -0
- package/dist/commands/run.js +62 -0
- package/dist/commands/token.d.ts +3 -0
- package/dist/commands/token.js +39 -0
- package/dist/commands/uninstall.d.ts +15 -0
- package/dist/commands/uninstall.js +39 -0
- package/dist/commands/update.d.ts +13 -0
- package/dist/commands/update.js +46 -0
- package/dist/commands/version.d.ts +25 -0
- package/dist/commands/version.js +252 -0
- package/dist/commands/view.d.ts +22 -0
- package/dist/commands/view.js +334 -0
- package/dist/commands/whoami.d.ts +12 -0
- package/dist/commands/whoami.js +28 -0
- package/dist/config/definition.d.ts +407 -0
- package/dist/config/definition.js +684 -0
- package/dist/config/index.d.ts +218 -0
- package/dist/config/index.js +488 -0
- package/dist/config/merge.d.ts +3 -0
- package/dist/config/merge.js +27 -0
- package/dist/config/usage.d.ts +18 -0
- package/dist/config/usage.js +39 -0
- package/dist/custom-help.d.ts +8 -0
- package/dist/custom-help.js +419 -0
- package/dist/exec-command.d.ts +52 -0
- package/dist/exec-command.js +313 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +72 -0
- package/dist/load-command.d.ts +15 -0
- package/dist/load-command.js +20 -0
- package/dist/mermaid-image-view.d.ts +18 -0
- package/dist/mermaid-image-view.js +36 -0
- package/dist/output.d.ts +20 -0
- package/dist/output.js +125 -0
- package/dist/pack-tarball.d.ts +23 -0
- package/dist/pack-tarball.js +256 -0
- package/dist/parse-add-remove-args.d.ts +28 -0
- package/dist/parse-add-remove-args.js +103 -0
- package/dist/print-err.d.ts +13 -0
- package/dist/print-err.js +193 -0
- package/dist/query-diff-files.d.ts +17 -0
- package/dist/query-diff-files.js +63 -0
- package/dist/query-host-contexts.d.ts +15 -0
- package/dist/query-host-contexts.js +136 -0
- package/dist/read-password.d.ts +7 -0
- package/dist/read-password.js +32 -0
- package/dist/read-project-folders.d.ts +17 -0
- package/dist/read-project-folders.js +100 -0
- package/dist/reload-config.d.ts +2 -0
- package/dist/reload-config.js +11 -0
- package/dist/render-mermaid.d.ts +22 -0
- package/dist/render-mermaid.js +68 -0
- package/dist/view.d.ts +29 -0
- package/dist/view.js +30 -0
- package/package.json +30 -30
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { writeFile } from 'node:fs/promises';
|
|
2
|
+
import { dirname, join, relative, resolve } from 'node:path';
|
|
3
|
+
import assert from 'node:assert';
|
|
4
|
+
import { run } from '@vltpkg/run';
|
|
5
|
+
import { commandUsage } from "../config/usage.js";
|
|
6
|
+
import { packTarball } from "../pack-tarball.js";
|
|
7
|
+
import prettyBytes from 'pretty-bytes';
|
|
8
|
+
import { actual } from '@vltpkg/graph';
|
|
9
|
+
import { Query } from '@vltpkg/query';
|
|
10
|
+
import { error } from '@vltpkg/error-cause';
|
|
11
|
+
import { createHostContextsMap } from "../query-host-contexts.js";
|
|
12
|
+
import { minimatch } from 'minimatch';
|
|
13
|
+
export const usage = () => commandUsage({
|
|
14
|
+
command: 'pack',
|
|
15
|
+
usage: '',
|
|
16
|
+
description: `Create a tarball from a package in the current directory or specified folder.
|
|
17
|
+
|
|
18
|
+
The tarball will be saved to the current directory with the name
|
|
19
|
+
<name>-<version>.tgz.`,
|
|
20
|
+
options: {
|
|
21
|
+
'dry-run': {
|
|
22
|
+
description: 'Show what would be packed without creating a tarball',
|
|
23
|
+
},
|
|
24
|
+
scope: {
|
|
25
|
+
value: '<query>',
|
|
26
|
+
description: 'Filter packages to pack using a DSS query selector.',
|
|
27
|
+
},
|
|
28
|
+
workspace: {
|
|
29
|
+
value: '<path|glob>',
|
|
30
|
+
description: 'Limit pack targets to matching workspaces.',
|
|
31
|
+
},
|
|
32
|
+
'workspace-group': {
|
|
33
|
+
value: '<name>',
|
|
34
|
+
description: 'Limit pack targets to workspace groups.',
|
|
35
|
+
},
|
|
36
|
+
recursive: {
|
|
37
|
+
description: 'Pack all workspaces in the monorepo.',
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
export const views = {
|
|
42
|
+
human: results => {
|
|
43
|
+
const item = (r) => {
|
|
44
|
+
const lines = [
|
|
45
|
+
`📦 Package: ${r.id}`,
|
|
46
|
+
`📄 File: ${r.filename}`,
|
|
47
|
+
`📁 ${r.files.length} Files`,
|
|
48
|
+
...r.files.map(f => ` - ${f}`),
|
|
49
|
+
`📊 Package Size: ${prettyBytes(r.size)}`,
|
|
50
|
+
`📂 Unpacked Size: ${prettyBytes(r.unpackedSize)}`,
|
|
51
|
+
];
|
|
52
|
+
if (r.shasum)
|
|
53
|
+
lines.push(`🔒 Shasum: ${r.shasum}`);
|
|
54
|
+
if (r.integrity)
|
|
55
|
+
lines.push(`🔐 Integrity: ${r.integrity}`);
|
|
56
|
+
return lines.join('\n');
|
|
57
|
+
};
|
|
58
|
+
return Array.isArray(results) ?
|
|
59
|
+
results.map(item).join('\n\n')
|
|
60
|
+
: item(results);
|
|
61
|
+
},
|
|
62
|
+
json: r => r,
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Resolve a scope query string to workspace locations using the DSS query system.
|
|
66
|
+
*/
|
|
67
|
+
const scopeLocations = async (queryString, conf) => {
|
|
68
|
+
const { options, projectRoot } = conf;
|
|
69
|
+
const mainManifest = options.packageJson.maybeRead(projectRoot);
|
|
70
|
+
let graph;
|
|
71
|
+
if (mainManifest) {
|
|
72
|
+
graph = actual.load({
|
|
73
|
+
...options,
|
|
74
|
+
mainManifest,
|
|
75
|
+
monorepo: options.monorepo,
|
|
76
|
+
loadManifests: false,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
const hostContexts = await createHostContextsMap(conf);
|
|
80
|
+
const query = new Query({
|
|
81
|
+
/* c8 ignore next */
|
|
82
|
+
nodes: graph ? new Set(graph.nodes.values()) : new Set(),
|
|
83
|
+
edges: graph?.edges ?? new Set(),
|
|
84
|
+
importers: graph?.importers ?? new Set(),
|
|
85
|
+
securityArchive: undefined,
|
|
86
|
+
hostContexts,
|
|
87
|
+
});
|
|
88
|
+
const { nodes } = await query.search(queryString, {
|
|
89
|
+
signal: new AbortController().signal,
|
|
90
|
+
});
|
|
91
|
+
const locations = [];
|
|
92
|
+
for (const node of nodes) {
|
|
93
|
+
const { location } = node.toJSON();
|
|
94
|
+
assert(location, error(`node ${node.id} has no location`, {
|
|
95
|
+
found: node,
|
|
96
|
+
}));
|
|
97
|
+
locations.push(resolve(projectRoot, location));
|
|
98
|
+
}
|
|
99
|
+
return locations;
|
|
100
|
+
};
|
|
101
|
+
export const command = async (conf) => {
|
|
102
|
+
const { options, projectRoot } = conf;
|
|
103
|
+
const queryString = conf.get('scope');
|
|
104
|
+
const paths = conf.get('workspace');
|
|
105
|
+
const groups = conf.get('workspace-group');
|
|
106
|
+
const recursive = conf.get('recursive');
|
|
107
|
+
const locations = [];
|
|
108
|
+
let single = null;
|
|
109
|
+
if (queryString) {
|
|
110
|
+
locations.push(...(await scopeLocations(queryString, conf)));
|
|
111
|
+
}
|
|
112
|
+
else if (paths?.length || groups?.length || recursive) {
|
|
113
|
+
for (const workspace of options.monorepo ?? []) {
|
|
114
|
+
// When specific workspace paths are set (including auto-inferred from cwd),
|
|
115
|
+
// filter to only matching workspaces. Without this, all monorepo workspaces
|
|
116
|
+
// would be operated on even when only one was specified.
|
|
117
|
+
if (paths?.length) {
|
|
118
|
+
const matches = paths.some((p) => workspace.path === p ||
|
|
119
|
+
workspace.name === p ||
|
|
120
|
+
workspace.fullpath === p ||
|
|
121
|
+
resolve(projectRoot, p) === workspace.fullpath ||
|
|
122
|
+
minimatch(workspace.path, p));
|
|
123
|
+
if (!matches)
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
locations.push(workspace.fullpath);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
else if (options.monorepo) {
|
|
130
|
+
const cwd = process.cwd();
|
|
131
|
+
if (cwd === projectRoot) {
|
|
132
|
+
for (const workspace of options.monorepo) {
|
|
133
|
+
locations.push(workspace.fullpath);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
const ws = options.monorepo.get(cwd);
|
|
138
|
+
if (ws) {
|
|
139
|
+
locations.push(ws.fullpath);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
const rel = relative(projectRoot, cwd).replaceAll('\\', '/');
|
|
143
|
+
locations.push(...(await scopeLocations(`:path("${rel}")`, conf)));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
single = options.packageJson.find(process.cwd()) ?? projectRoot;
|
|
149
|
+
}
|
|
150
|
+
if (single) {
|
|
151
|
+
return commandSingle(single, conf);
|
|
152
|
+
}
|
|
153
|
+
assert(locations.length > 0, error('No workspaces or query results found'));
|
|
154
|
+
const results = [];
|
|
155
|
+
for (const location of locations) {
|
|
156
|
+
results.push(await commandSingle(location, conf));
|
|
157
|
+
}
|
|
158
|
+
return results;
|
|
159
|
+
};
|
|
160
|
+
export const commandSingle = async (location, conf) => {
|
|
161
|
+
const manifestPath = conf.options.packageJson.find(location);
|
|
162
|
+
assert(manifestPath, 'No package.json found');
|
|
163
|
+
const manifestDir = dirname(manifestPath);
|
|
164
|
+
const manifest = conf.options.packageJson.read(manifestDir);
|
|
165
|
+
const isDryRun = conf.options['dry-run'];
|
|
166
|
+
const runOptions = {
|
|
167
|
+
cwd: manifestDir,
|
|
168
|
+
projectRoot: conf.projectRoot,
|
|
169
|
+
packageJson: conf.options.packageJson,
|
|
170
|
+
manifest,
|
|
171
|
+
ignoreMissing: true,
|
|
172
|
+
ignorePrePost: true,
|
|
173
|
+
};
|
|
174
|
+
await run({
|
|
175
|
+
...runOptions,
|
|
176
|
+
arg0: 'prepack',
|
|
177
|
+
});
|
|
178
|
+
await run({
|
|
179
|
+
...runOptions,
|
|
180
|
+
arg0: 'prepare',
|
|
181
|
+
});
|
|
182
|
+
// Re-read the manifest after lifecycle scripts, which may have modified package.json.
|
|
183
|
+
const updatedManifest = conf.options.packageJson.read(manifestDir, {
|
|
184
|
+
reload: true,
|
|
185
|
+
});
|
|
186
|
+
const { name, version, filename, tarballData, unpackedSize, files, integrity, shasum, } = await packTarball(updatedManifest, manifestDir, conf);
|
|
187
|
+
if (!isDryRun) {
|
|
188
|
+
await writeFile(join(manifestDir, filename), tarballData);
|
|
189
|
+
}
|
|
190
|
+
await run({
|
|
191
|
+
...runOptions,
|
|
192
|
+
arg0: 'postpack',
|
|
193
|
+
});
|
|
194
|
+
return {
|
|
195
|
+
id: `${name}@${version}`,
|
|
196
|
+
name,
|
|
197
|
+
version,
|
|
198
|
+
filename,
|
|
199
|
+
files,
|
|
200
|
+
size: tarballData.length,
|
|
201
|
+
unpackedSize,
|
|
202
|
+
shasum,
|
|
203
|
+
integrity,
|
|
204
|
+
};
|
|
205
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { CommandFn, CommandUsage } from '../index.ts';
|
|
2
|
+
export declare const usage: CommandUsage;
|
|
3
|
+
type PingResult = {
|
|
4
|
+
registry: string;
|
|
5
|
+
alias?: string;
|
|
6
|
+
status: 'ok' | 'error';
|
|
7
|
+
time: number;
|
|
8
|
+
statusCode?: number;
|
|
9
|
+
error?: string;
|
|
10
|
+
};
|
|
11
|
+
type CommandResult = PingResult | PingResult[];
|
|
12
|
+
export declare const views: {
|
|
13
|
+
readonly human: (r: CommandResult) => string;
|
|
14
|
+
readonly json: (r: CommandResult) => CommandResult;
|
|
15
|
+
};
|
|
16
|
+
export declare const command: CommandFn<CommandResult>;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { RegistryClient } from '@vltpkg/registry-client';
|
|
2
|
+
import { error } from '@vltpkg/error-cause';
|
|
3
|
+
import { commandUsage } from "../config/usage.js";
|
|
4
|
+
export const usage = () => commandUsage({
|
|
5
|
+
command: 'ping',
|
|
6
|
+
usage: ['', '[<registry-alias>]'],
|
|
7
|
+
description: `Ping configured registries to verify connectivity
|
|
8
|
+
and check registry health.
|
|
9
|
+
|
|
10
|
+
By default, pings all configured registries including
|
|
11
|
+
the default registry.
|
|
12
|
+
|
|
13
|
+
If a registry alias is provided, ping only that specific
|
|
14
|
+
registry. Registry aliases are configured via the
|
|
15
|
+
\`registries\` field in vlt.json or with the
|
|
16
|
+
\`--registries\` option.`,
|
|
17
|
+
options: {
|
|
18
|
+
registry: {
|
|
19
|
+
value: '<url>',
|
|
20
|
+
description: 'The default registry URL to ping.',
|
|
21
|
+
},
|
|
22
|
+
registries: {
|
|
23
|
+
value: '<alias=url>',
|
|
24
|
+
description: 'Named registry aliases to ping.',
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
const formatPingResult = (r) => {
|
|
29
|
+
const prefix = r.alias ? `${r.alias} (${r.registry})` : r.registry;
|
|
30
|
+
if (r.status === 'ok') {
|
|
31
|
+
return `Ping successful: ${prefix} (${r.time}ms)`;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
return `Ping failed: ${prefix} - ${r.error}`;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
export const views = {
|
|
38
|
+
human: r => {
|
|
39
|
+
if (Array.isArray(r)) {
|
|
40
|
+
return r.map(formatPingResult).join('\n');
|
|
41
|
+
}
|
|
42
|
+
return formatPingResult(r);
|
|
43
|
+
},
|
|
44
|
+
json: r => r,
|
|
45
|
+
};
|
|
46
|
+
const pingRegistry = async (rc, registry, alias) => {
|
|
47
|
+
const url = new URL('-/ping?write=true', registry);
|
|
48
|
+
const start = Date.now();
|
|
49
|
+
try {
|
|
50
|
+
const response = await rc.request(url, { useCache: false });
|
|
51
|
+
const time = Date.now() - start;
|
|
52
|
+
if (response.statusCode >= 200 && response.statusCode < 300) {
|
|
53
|
+
return {
|
|
54
|
+
registry,
|
|
55
|
+
alias,
|
|
56
|
+
status: 'ok',
|
|
57
|
+
time,
|
|
58
|
+
statusCode: response.statusCode,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
return {
|
|
63
|
+
registry,
|
|
64
|
+
alias,
|
|
65
|
+
status: 'error',
|
|
66
|
+
time,
|
|
67
|
+
statusCode: response.statusCode,
|
|
68
|
+
error: `Registry returned status ${response.statusCode}`,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
const time = Date.now() - start;
|
|
74
|
+
return {
|
|
75
|
+
registry,
|
|
76
|
+
alias,
|
|
77
|
+
status: 'error',
|
|
78
|
+
time,
|
|
79
|
+
error: err instanceof Error ? err.message : String(err),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
export const command = async (conf) => {
|
|
84
|
+
const rc = new RegistryClient(conf.options);
|
|
85
|
+
const registryAlias = conf.positionals[0];
|
|
86
|
+
if (registryAlias) {
|
|
87
|
+
// Ping a specific registry by alias
|
|
88
|
+
const registries = conf.options.registries;
|
|
89
|
+
const registry = registries[registryAlias];
|
|
90
|
+
if (!registry) {
|
|
91
|
+
const availableAliases = Object.keys(registries);
|
|
92
|
+
throw error('Unknown registry alias', {
|
|
93
|
+
found: registryAlias,
|
|
94
|
+
wanted: availableAliases.length > 0 ? availableAliases : undefined,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
return await pingRegistry(rc, registry, registryAlias);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
// Ping all configured registries
|
|
101
|
+
const registries = conf.options.registries;
|
|
102
|
+
const results = [];
|
|
103
|
+
// Always ping the default registry first
|
|
104
|
+
results.push(await pingRegistry(rc, conf.options.registry, 'default'));
|
|
105
|
+
// Then ping all configured registry aliases
|
|
106
|
+
for (const [alias, registry] of Object.entries(registries)) {
|
|
107
|
+
// Skip if it's the same as the default registry
|
|
108
|
+
if (registry !== conf.options.registry) {
|
|
109
|
+
results.push(await pingRegistry(rc, registry, alias));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return results;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CommandFn, CommandUsage } from '../index.ts';
|
|
2
|
+
export declare const views: {
|
|
3
|
+
readonly human: (results: unknown, _: import("../view.ts").ViewOptions, config: import("../config/index.ts").ParsedConfig) => string;
|
|
4
|
+
};
|
|
5
|
+
export declare const usage: CommandUsage;
|
|
6
|
+
export declare const command: CommandFn;
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import * as dotProp from '@vltpkg/dot-prop';
|
|
4
|
+
import { error } from '@vltpkg/error-cause';
|
|
5
|
+
import { init } from '@vltpkg/init';
|
|
6
|
+
import { actual, GraphModifier, VIRTUAL_ROOT_ID } from '@vltpkg/graph';
|
|
7
|
+
import { Query } from '@vltpkg/query';
|
|
8
|
+
import { SecurityArchive } from '@vltpkg/security-archive';
|
|
9
|
+
import { views as initViews } from "./init.js";
|
|
10
|
+
import { commandUsage } from "../config/usage.js";
|
|
11
|
+
import { createHostContextsMap } from "../query-host-contexts.js";
|
|
12
|
+
import { minimatch } from 'minimatch';
|
|
13
|
+
export const views = {
|
|
14
|
+
human: (results, _, config) => {
|
|
15
|
+
// `vlt pkg init` is an alias for `vlt init`
|
|
16
|
+
// use the same output handling
|
|
17
|
+
if (config.positionals[0] === 'init') {
|
|
18
|
+
return initViews.human(results);
|
|
19
|
+
}
|
|
20
|
+
// When `get` is run with a single arg and it returns a string,
|
|
21
|
+
// just print items separated by newlines
|
|
22
|
+
if (Array.isArray(results) && typeof results[0] === 'string') {
|
|
23
|
+
return results.join('\n');
|
|
24
|
+
}
|
|
25
|
+
return JSON.stringify(results, null, 2);
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
export const usage = () => commandUsage({
|
|
29
|
+
command: 'pkg',
|
|
30
|
+
usage: '[<command>] [<args>]',
|
|
31
|
+
description: 'Get or manipulate package.json values',
|
|
32
|
+
subcommands: {
|
|
33
|
+
get: {
|
|
34
|
+
usage: '[<key>]',
|
|
35
|
+
description: 'Get a single value',
|
|
36
|
+
},
|
|
37
|
+
init: {
|
|
38
|
+
usage: '',
|
|
39
|
+
description: 'Initialize a new package.json file in the current directory',
|
|
40
|
+
},
|
|
41
|
+
pick: {
|
|
42
|
+
usage: '[<key> [<key> ...]]',
|
|
43
|
+
description: 'Get multiple values or the entire package',
|
|
44
|
+
},
|
|
45
|
+
set: {
|
|
46
|
+
usage: '<key>=<value> [<key>=<value> ...]',
|
|
47
|
+
description: 'Set one or more key value pairs',
|
|
48
|
+
},
|
|
49
|
+
delete: {
|
|
50
|
+
usage: '<key> [<key> ...]',
|
|
51
|
+
description: 'Delete one or more keys from the package',
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
examples: {
|
|
55
|
+
'set "array[1].key=value"': {
|
|
56
|
+
description: 'Set a value on an object inside an array',
|
|
57
|
+
},
|
|
58
|
+
'set "array[]=value"': {
|
|
59
|
+
description: 'Append a value to an array',
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
options: {
|
|
63
|
+
scope: {
|
|
64
|
+
value: '<query>',
|
|
65
|
+
description: 'Filter package.json targets using a DSS query.',
|
|
66
|
+
},
|
|
67
|
+
workspace: {
|
|
68
|
+
value: '<path|glob>',
|
|
69
|
+
description: 'Limit package.json targets to matching workspaces.',
|
|
70
|
+
},
|
|
71
|
+
'workspace-group': {
|
|
72
|
+
value: '<name>',
|
|
73
|
+
description: 'Limit package.json targets to workspace groups.',
|
|
74
|
+
},
|
|
75
|
+
recursive: {
|
|
76
|
+
description: 'Operate across all workspaces in the current monorepo.',
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
export const command = async (conf) => {
|
|
81
|
+
const [sub, ...args] = conf.positionals;
|
|
82
|
+
if (sub === 'init') {
|
|
83
|
+
return await init({ cwd: process.cwd() });
|
|
84
|
+
}
|
|
85
|
+
assert(sub, error('pkg command requires a subcommand', {
|
|
86
|
+
code: 'EUSAGE',
|
|
87
|
+
validOptions: ['get', 'pick', 'set', 'rm', 'init'],
|
|
88
|
+
}));
|
|
89
|
+
const { options, projectRoot } = conf;
|
|
90
|
+
const queryString = conf.get('scope');
|
|
91
|
+
const paths = conf.get('workspace');
|
|
92
|
+
const groups = conf.get('workspace-group');
|
|
93
|
+
const recursive = conf.get('recursive');
|
|
94
|
+
const locations = [];
|
|
95
|
+
let single = null;
|
|
96
|
+
if (queryString) {
|
|
97
|
+
const modifiers = GraphModifier.maybeLoad(options);
|
|
98
|
+
const mainManifest = options.packageJson.maybeRead(projectRoot);
|
|
99
|
+
let graph;
|
|
100
|
+
let securityArchive;
|
|
101
|
+
if (mainManifest) {
|
|
102
|
+
graph = actual.load({
|
|
103
|
+
...options,
|
|
104
|
+
mainManifest,
|
|
105
|
+
modifiers,
|
|
106
|
+
monorepo: options.monorepo,
|
|
107
|
+
loadManifests: false,
|
|
108
|
+
});
|
|
109
|
+
securityArchive =
|
|
110
|
+
Query.hasSecuritySelectors(queryString) ?
|
|
111
|
+
await SecurityArchive.start({
|
|
112
|
+
nodes: [...graph.nodes.values()],
|
|
113
|
+
})
|
|
114
|
+
: undefined;
|
|
115
|
+
}
|
|
116
|
+
const hostContexts = await createHostContextsMap(conf);
|
|
117
|
+
const edges = graph?.edges ?? new Set();
|
|
118
|
+
const nodes = graph?.nodes ?
|
|
119
|
+
new Set(graph.nodes.values())
|
|
120
|
+
: /* c8 ignore next */ new Set();
|
|
121
|
+
const importers = graph?.importers ?? new Set();
|
|
122
|
+
const query = new Query({
|
|
123
|
+
edges,
|
|
124
|
+
nodes,
|
|
125
|
+
importers,
|
|
126
|
+
securityArchive,
|
|
127
|
+
hostContexts,
|
|
128
|
+
});
|
|
129
|
+
const { nodes: resultNodes } = await query.search(queryString, {
|
|
130
|
+
signal: new AbortController().signal,
|
|
131
|
+
});
|
|
132
|
+
for (const node of resultNodes) {
|
|
133
|
+
const location = node.location;
|
|
134
|
+
assert(location, error(`node ${node.id} has no location`, {
|
|
135
|
+
found: node,
|
|
136
|
+
}));
|
|
137
|
+
if (node.id !== VIRTUAL_ROOT_ID) {
|
|
138
|
+
locations.push(resolve(node.projectRoot, location));
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
else if (paths?.length || groups?.length || recursive) {
|
|
143
|
+
for (const workspace of options.monorepo ?? []) {
|
|
144
|
+
if (paths?.length) {
|
|
145
|
+
const matches = paths.some((p) => workspace.path === p ||
|
|
146
|
+
workspace.name === p ||
|
|
147
|
+
workspace.fullpath === p ||
|
|
148
|
+
resolve(projectRoot, p) === workspace.fullpath ||
|
|
149
|
+
minimatch(workspace.path, p));
|
|
150
|
+
if (!matches)
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
locations.push(workspace.fullpath);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
single = options.packageJson.find(process.cwd()) ?? projectRoot;
|
|
158
|
+
}
|
|
159
|
+
if (single) {
|
|
160
|
+
return commandSingle(single, sub, args, conf);
|
|
161
|
+
}
|
|
162
|
+
assert(locations.length > 0, error('No matching package found using scope', {
|
|
163
|
+
found: queryString || 'workspace selection',
|
|
164
|
+
}));
|
|
165
|
+
const results = [];
|
|
166
|
+
for (const location of locations) {
|
|
167
|
+
results.push(await commandSingle(location, sub, args, conf));
|
|
168
|
+
}
|
|
169
|
+
return results;
|
|
170
|
+
};
|
|
171
|
+
const commandSingle = async (location, sub, args, conf) => {
|
|
172
|
+
const pkg = conf.options.packageJson;
|
|
173
|
+
const manifest = pkg.read(location);
|
|
174
|
+
switch (sub) {
|
|
175
|
+
case 'get':
|
|
176
|
+
return get(manifest, args);
|
|
177
|
+
case 'pick':
|
|
178
|
+
return pick(manifest, args);
|
|
179
|
+
case 'set':
|
|
180
|
+
return set(manifest, location, pkg, args);
|
|
181
|
+
case 'rm':
|
|
182
|
+
case 'remove':
|
|
183
|
+
case 'unset':
|
|
184
|
+
case 'delete':
|
|
185
|
+
return rm(manifest, location, pkg, args);
|
|
186
|
+
default: {
|
|
187
|
+
throw error('Unrecognized pkg command', {
|
|
188
|
+
code: 'EUSAGE',
|
|
189
|
+
found: sub,
|
|
190
|
+
validOptions: ['get', 'set', 'rm'],
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
const get = (manifest, args) => {
|
|
196
|
+
const noArg = () => error('get requires not more than 1 argument. use `pick` to get more than 1.', { code: 'EUSAGE' }, noArg);
|
|
197
|
+
if (args.length === 1) {
|
|
198
|
+
const [key] = args;
|
|
199
|
+
assert(key, noArg());
|
|
200
|
+
return dotProp.get(manifest, key);
|
|
201
|
+
}
|
|
202
|
+
assert(args.length === 0, noArg());
|
|
203
|
+
return pick(manifest, args);
|
|
204
|
+
};
|
|
205
|
+
const pick = (manifest, args) => {
|
|
206
|
+
return args.length ?
|
|
207
|
+
args.reduce((acc, key) => dotProp.set(acc, key, dotProp.get(manifest, key)), {})
|
|
208
|
+
: manifest;
|
|
209
|
+
};
|
|
210
|
+
const set = (manifest, location, pkg, args) => {
|
|
211
|
+
assert(args.length >= 1, error('set requires arguments', { code: 'EUSAGE' }));
|
|
212
|
+
const res = args.reduce((acc, p) => {
|
|
213
|
+
const index = p.indexOf('=');
|
|
214
|
+
assert(index !== -1, error('set arguments must contain `=`', {
|
|
215
|
+
code: 'EUSAGE',
|
|
216
|
+
}));
|
|
217
|
+
return dotProp.set(acc, p.substring(0, index), p.substring(index + 1));
|
|
218
|
+
}, manifest);
|
|
219
|
+
pkg.write(location, res);
|
|
220
|
+
};
|
|
221
|
+
const rm = (manifest, location, pkg, args) => {
|
|
222
|
+
assert(args.length >= 1, error('rm requires arguments', { code: 'EUSAGE' }));
|
|
223
|
+
const res = args.reduce((acc, key) => {
|
|
224
|
+
dotProp.del(acc, key);
|
|
225
|
+
return acc;
|
|
226
|
+
}, manifest);
|
|
227
|
+
pkg.write(location, res);
|
|
228
|
+
return {
|
|
229
|
+
manifest: res,
|
|
230
|
+
location,
|
|
231
|
+
};
|
|
232
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { CommandFn, CommandUsage } from '../index.ts';
|
|
2
|
+
export declare const usage: CommandUsage;
|
|
3
|
+
export type CommandResultSingle = {
|
|
4
|
+
id: string;
|
|
5
|
+
name: string;
|
|
6
|
+
version: string;
|
|
7
|
+
tag: string;
|
|
8
|
+
registry: string;
|
|
9
|
+
shasum?: string;
|
|
10
|
+
integrity?: string;
|
|
11
|
+
size: number;
|
|
12
|
+
access?: string;
|
|
13
|
+
unpackedSize: number;
|
|
14
|
+
files: string[];
|
|
15
|
+
};
|
|
16
|
+
export type CommandResult = CommandResultSingle | CommandResultSingle[];
|
|
17
|
+
export declare const views: {
|
|
18
|
+
readonly human: (results: CommandResult) => string;
|
|
19
|
+
readonly json: (r: CommandResult) => CommandResult;
|
|
20
|
+
};
|
|
21
|
+
export declare const command: CommandFn<CommandResult>;
|