@vltpkg/cli-sdk 1.0.9 → 1.1.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/dist/commands/access.js +40 -4
- package/dist/commands/cache.js +7 -2
- package/dist/commands/deprecate.js +9 -9
- package/dist/commands/dist-tag.js +15 -19
- package/dist/commands/install/reporter.js +7 -0
- package/dist/commands/install.d.ts +6 -0
- package/dist/commands/install.js +20 -2
- package/dist/commands/list.js +25 -13
- package/dist/commands/profile.js +19 -1
- package/dist/commands/publish.js +27 -19
- package/dist/commands/query.js +20 -7
- package/dist/commands/setup.js +1 -2
- package/dist/commands/token.js +3 -1
- package/dist/commands/unpublish.js +35 -30
- package/dist/commands/update.d.ts +1 -0
- package/dist/commands/update.js +18 -1
- package/dist/commands/version.js +19 -9
- package/dist/commands/whoami.js +20 -2
- package/dist/config/definition.d.ts +16 -0
- package/dist/config/definition.js +39 -0
- package/dist/config/index.d.ts +14 -0
- package/dist/config/index.js +110 -5
- package/dist/is-vlt-installed.d.ts +18 -0
- package/dist/is-vlt-installed.js +46 -0
- package/dist/parse-add-remove-args.js +14 -1
- package/dist/persist-spec-config.d.ts +27 -0
- package/dist/persist-spec-config.js +212 -0
- package/dist/print-err.js +35 -1
- package/dist/query-host-contexts.js +2 -6
- package/dist/require-registry.d.ts +12 -0
- package/dist/require-registry.js +29 -0
- package/package.json +25 -25
- package/dist/registry-error-message.d.ts +0 -2
- package/dist/registry-error-message.js +0 -29
package/dist/commands/access.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { error } from '@vltpkg/error-cause';
|
|
2
|
-
import { RegistryClient } from '@vltpkg/registry-client';
|
|
2
|
+
import { RegistryClient, assertOk } from '@vltpkg/registry-client';
|
|
3
3
|
import { commandUsage } from "../config/usage.js";
|
|
4
4
|
import { resolveRegistry } from "../require-registry.js";
|
|
5
5
|
export const needsRegistry = true;
|
|
@@ -89,6 +89,14 @@ export const command = async (conf) => {
|
|
|
89
89
|
const encodePkgName = (name) => name.startsWith('@') ?
|
|
90
90
|
`@${encodeURIComponent(name.slice(1))}`
|
|
91
91
|
: encodeURIComponent(name);
|
|
92
|
+
// 401/403/404 from the access endpoints all mean something the user can
|
|
93
|
+
// act on, so each gets a concrete next step rather than a bare status.
|
|
94
|
+
const accessAdvice = (what) => (statusCode) => statusCode === 401 ? 'Run `vlt login` and try again.'
|
|
95
|
+
: statusCode === 403 ?
|
|
96
|
+
`This account cannot ${what}. Run \`vlt whoami\` to see who you are logged in as.`
|
|
97
|
+
: statusCode === 404 ?
|
|
98
|
+
'Not found. Check the name, and that this account has access to it.'
|
|
99
|
+
: undefined;
|
|
92
100
|
const listPackages = async (conf, args) => {
|
|
93
101
|
const [keyword, entity] = args;
|
|
94
102
|
if (keyword !== 'packages') {
|
|
@@ -103,6 +111,11 @@ const listPackages = async (conf, args) => {
|
|
|
103
111
|
const scope = entity ?? getDefaultScope(conf);
|
|
104
112
|
const url = new URL(`-/org/${encodeURIComponent(scope)}/package`, registryUrl);
|
|
105
113
|
const response = await rc.request(url, { useCache: false });
|
|
114
|
+
assertOk(response, {
|
|
115
|
+
message: 'Failed to list packages',
|
|
116
|
+
url,
|
|
117
|
+
advice: accessAdvice('list packages for this scope'),
|
|
118
|
+
});
|
|
106
119
|
const data = response.json();
|
|
107
120
|
return { packages: data };
|
|
108
121
|
};
|
|
@@ -123,6 +136,11 @@ const getStatus = async (conf, args) => {
|
|
|
123
136
|
const registryUrl = new URL(await resolveRegistry(conf));
|
|
124
137
|
const url = new URL(`-/package/${encodePkgName(pkg)}/access`, registryUrl);
|
|
125
138
|
const response = await rc.request(url, { useCache: false });
|
|
139
|
+
assertOk(response, {
|
|
140
|
+
message: 'Failed to get package access status',
|
|
141
|
+
url,
|
|
142
|
+
advice: accessAdvice('read access for this package'),
|
|
143
|
+
});
|
|
126
144
|
const data = response.json();
|
|
127
145
|
return { package: pkg, access: data.access };
|
|
128
146
|
};
|
|
@@ -148,13 +166,19 @@ const setStatus = async (conf, args) => {
|
|
|
148
166
|
const rc = new RegistryClient(conf.options);
|
|
149
167
|
const registryUrl = new URL(await resolveRegistry(conf));
|
|
150
168
|
const url = new URL(`-/package/${encodePkgName(pkg)}/access`, registryUrl);
|
|
151
|
-
await rc.request(url, {
|
|
169
|
+
const response = await rc.request(url, {
|
|
152
170
|
method: 'PUT',
|
|
153
171
|
headers: { 'content-type': 'application/json' },
|
|
154
172
|
body: JSON.stringify({ access: accessLevel }),
|
|
155
173
|
otp: conf.options.otp,
|
|
156
174
|
useCache: false,
|
|
157
175
|
});
|
|
176
|
+
assertOk(response, {
|
|
177
|
+
message: 'Failed to set package access status',
|
|
178
|
+
url,
|
|
179
|
+
method: 'PUT',
|
|
180
|
+
advice: accessAdvice('change access for this package'),
|
|
181
|
+
});
|
|
158
182
|
return { package: pkg, access: accessLevel };
|
|
159
183
|
};
|
|
160
184
|
const grant = async (conf, args) => {
|
|
@@ -184,7 +208,7 @@ const grant = async (conf, args) => {
|
|
|
184
208
|
const rc = new RegistryClient(conf.options);
|
|
185
209
|
const registryUrl = new URL(await resolveRegistry(conf));
|
|
186
210
|
const url = new URL(`-/team/${encodeURIComponent(scope)}/${encodeURIComponent(team)}/package`, registryUrl);
|
|
187
|
-
await rc.request(url, {
|
|
211
|
+
const response = await rc.request(url, {
|
|
188
212
|
method: 'PUT',
|
|
189
213
|
headers: { 'content-type': 'application/json' },
|
|
190
214
|
body: JSON.stringify({
|
|
@@ -194,6 +218,12 @@ const grant = async (conf, args) => {
|
|
|
194
218
|
otp: conf.options.otp,
|
|
195
219
|
useCache: false,
|
|
196
220
|
});
|
|
221
|
+
assertOk(response, {
|
|
222
|
+
message: 'Failed to grant team access',
|
|
223
|
+
url,
|
|
224
|
+
method: 'PUT',
|
|
225
|
+
advice: accessAdvice('grant access for this team'),
|
|
226
|
+
});
|
|
197
227
|
return {
|
|
198
228
|
granted: {
|
|
199
229
|
team: `${scope}:${team}`,
|
|
@@ -221,13 +251,19 @@ const revoke = async (conf, args) => {
|
|
|
221
251
|
const rc = new RegistryClient(conf.options);
|
|
222
252
|
const registryUrl = new URL(await resolveRegistry(conf));
|
|
223
253
|
const url = new URL(`-/team/${encodeURIComponent(scope)}/${encodeURIComponent(team)}/package`, registryUrl);
|
|
224
|
-
await rc.request(url, {
|
|
254
|
+
const response = await rc.request(url, {
|
|
225
255
|
method: 'DELETE',
|
|
226
256
|
headers: { 'content-type': 'application/json' },
|
|
227
257
|
body: JSON.stringify({ package: pkgName }),
|
|
228
258
|
otp: conf.options.otp,
|
|
229
259
|
useCache: false,
|
|
230
260
|
});
|
|
261
|
+
assertOk(response, {
|
|
262
|
+
message: 'Failed to revoke team access',
|
|
263
|
+
url,
|
|
264
|
+
method: 'DELETE',
|
|
265
|
+
advice: accessAdvice('revoke access for this team'),
|
|
266
|
+
});
|
|
231
267
|
return {
|
|
232
268
|
revoked: {
|
|
233
269
|
team: `${scope}:${team}`,
|
package/dist/commands/cache.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { error } from '@vltpkg/error-cause';
|
|
2
|
-
import { CacheEntry } from '@vltpkg/registry-client';
|
|
2
|
+
import { CacheEntry, assertOk } from '@vltpkg/registry-client';
|
|
3
3
|
import { Spec } from '@vltpkg/spec';
|
|
4
4
|
import { mkdir, rm } from 'node:fs/promises';
|
|
5
5
|
import prettyBytes from 'pretty-bytes';
|
|
@@ -243,12 +243,17 @@ const add = async (conf, specs, view) => {
|
|
|
243
243
|
})
|
|
244
244
|
.then(async (r) => {
|
|
245
245
|
const { resolved, integrity } = r;
|
|
246
|
-
await (await packageInfo.getRegistryClient()).request(resolved, {
|
|
246
|
+
const response = await (await packageInfo.getRegistryClient()).request(resolved, {
|
|
247
247
|
...conf.options,
|
|
248
248
|
integrity,
|
|
249
249
|
staleWhileRevalidate: false,
|
|
250
250
|
query: undefined,
|
|
251
251
|
});
|
|
252
|
+
// otherwise a 404 tarball still prints '+ <spec>'
|
|
253
|
+
assertOk(response, {
|
|
254
|
+
message: `Failed to cache ${spec}`,
|
|
255
|
+
url: resolved,
|
|
256
|
+
});
|
|
252
257
|
view?.stdout('+', spec, r.resolved);
|
|
253
258
|
});
|
|
254
259
|
promises.push(p);
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { error } from '@vltpkg/error-cause';
|
|
2
2
|
import { PackageInfoClient } from '@vltpkg/package-info';
|
|
3
|
-
import { RegistryClient } from '@vltpkg/registry-client';
|
|
3
|
+
import { RegistryClient, assertOk, requestError, } from '@vltpkg/registry-client';
|
|
4
4
|
import { Spec } from '@vltpkg/spec';
|
|
5
5
|
import { satisfies } from '@vltpkg/semver';
|
|
6
|
-
import { asError } from '@vltpkg/types';
|
|
7
6
|
import { commandUsage } from "../config/usage.js";
|
|
8
7
|
import { resolveRegistry } from "../require-registry.js";
|
|
9
8
|
export const needsRegistry = true;
|
|
@@ -123,16 +122,17 @@ export const command = async (conf) => {
|
|
|
123
122
|
});
|
|
124
123
|
}
|
|
125
124
|
catch (err) {
|
|
126
|
-
throw
|
|
127
|
-
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
if (response.statusCode < 200 || response.statusCode >= 300) {
|
|
131
|
-
throw error('failed to update deprecation status', {
|
|
125
|
+
throw requestError(err, {
|
|
126
|
+
message: 'failed to update deprecation status',
|
|
132
127
|
url: packageUrl,
|
|
133
|
-
|
|
128
|
+
method: 'PUT',
|
|
134
129
|
});
|
|
135
130
|
}
|
|
131
|
+
assertOk(response, {
|
|
132
|
+
message: 'failed to update deprecation status',
|
|
133
|
+
url: packageUrl,
|
|
134
|
+
method: 'PUT',
|
|
135
|
+
});
|
|
136
136
|
return {
|
|
137
137
|
name,
|
|
138
138
|
version: versionRange || '*',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { error } from '@vltpkg/error-cause';
|
|
2
|
-
import { RegistryClient } from '@vltpkg/registry-client';
|
|
2
|
+
import { RegistryClient, assertOk } from '@vltpkg/registry-client';
|
|
3
3
|
import { Spec } from '@vltpkg/spec';
|
|
4
4
|
import { commandUsage } from "../config/usage.js";
|
|
5
5
|
import { resolveRegistry } from "../require-registry.js";
|
|
@@ -121,12 +121,11 @@ export const command = async (conf) => {
|
|
|
121
121
|
body: JSON.stringify(version),
|
|
122
122
|
useCache: false,
|
|
123
123
|
});
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
124
|
+
assertOk(response, {
|
|
125
|
+
message: 'Failed to add dist-tag',
|
|
126
|
+
url,
|
|
127
|
+
method: 'PUT',
|
|
128
|
+
});
|
|
130
129
|
return { id: name, tag, version };
|
|
131
130
|
}
|
|
132
131
|
case 'rm':
|
|
@@ -144,12 +143,11 @@ export const command = async (conf) => {
|
|
|
144
143
|
method: 'DELETE',
|
|
145
144
|
useCache: false,
|
|
146
145
|
});
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
}
|
|
146
|
+
assertOk(response, {
|
|
147
|
+
message: 'Failed to remove dist-tag',
|
|
148
|
+
url,
|
|
149
|
+
method: 'DELETE',
|
|
150
|
+
});
|
|
153
151
|
return { id: name, tag };
|
|
154
152
|
}
|
|
155
153
|
case 'ls':
|
|
@@ -159,12 +157,10 @@ export const command = async (conf) => {
|
|
|
159
157
|
const response = await rc.request(url, {
|
|
160
158
|
useCache: false,
|
|
161
159
|
});
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
});
|
|
167
|
-
}
|
|
160
|
+
assertOk(response, {
|
|
161
|
+
message: 'Failed to list dist-tags',
|
|
162
|
+
url,
|
|
163
|
+
});
|
|
168
164
|
const tags = response.json();
|
|
169
165
|
return { id: name, tags };
|
|
170
166
|
}
|
|
@@ -4,6 +4,7 @@ import Spinner from 'ink-spinner';
|
|
|
4
4
|
import { createElement as $, Fragment, useEffect, useState, } from 'react';
|
|
5
5
|
import { ViewClass } from "../../view.js";
|
|
6
6
|
import { asError } from '@vltpkg/types';
|
|
7
|
+
import { persistedEntries } from "../../persist-spec-config.js";
|
|
7
8
|
const labels = {
|
|
8
9
|
build: 'resolving dependencies',
|
|
9
10
|
actual: '',
|
|
@@ -84,6 +85,12 @@ export class InstallReporter extends ViewClass {
|
|
|
84
85
|
out +=
|
|
85
86
|
'🔨 Run `vlt build` to run all required scripts to build installed packages.\n';
|
|
86
87
|
}
|
|
88
|
+
const saved = _result.persistedConfig;
|
|
89
|
+
if (saved) {
|
|
90
|
+
for (const e of persistedEntries(saved.values)) {
|
|
91
|
+
out += `\nSaved ${e} to ${saved.which} vlt.json`;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
87
94
|
this.#instance?.rerender($(App, { trailer: out }));
|
|
88
95
|
return undefined;
|
|
89
96
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SpecConfigPersistPlan } from '../persist-spec-config.ts';
|
|
1
2
|
import type { DepID } from '@vltpkg/dep-id';
|
|
2
3
|
import type { Diff, Graph } from '@vltpkg/graph';
|
|
3
4
|
import type { CommandFn, CommandUsage } from '../index.ts';
|
|
@@ -17,12 +18,17 @@ export type InstallResult = {
|
|
|
17
18
|
* The diff between the actual and ideal graphs, if available.
|
|
18
19
|
*/
|
|
19
20
|
diff?: Diff;
|
|
21
|
+
/**
|
|
22
|
+
* Spec config from the cli / env that was saved to a config file.
|
|
23
|
+
*/
|
|
24
|
+
persistedConfig?: SpecConfigPersistPlan;
|
|
20
25
|
};
|
|
21
26
|
export declare const needsRegistry = true;
|
|
22
27
|
export declare const needsNpmRegistry = true;
|
|
23
28
|
export declare const usage: CommandUsage;
|
|
24
29
|
export declare const views: {
|
|
25
30
|
readonly json: (i: InstallResult) => {
|
|
31
|
+
persistedConfig?: SpecConfigPersistPlan | undefined;
|
|
26
32
|
buildQueue?: DepID[] | undefined;
|
|
27
33
|
message?: string | undefined;
|
|
28
34
|
add: {
|
package/dist/commands/install.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { commandUsage } from "../config/usage.js";
|
|
2
2
|
import { install } from '@vltpkg/graph';
|
|
3
3
|
import { parseAddArgs } from "../parse-add-remove-args.js";
|
|
4
|
+
import { planSpecConfigPersist } from "../persist-spec-config.js";
|
|
5
|
+
import { asUnknownSpecPrefix } from "../require-registry.js";
|
|
4
6
|
import { trackInstall } from "../telemetry.js";
|
|
5
7
|
import { lazyView } from "../view.js";
|
|
6
8
|
export const needsRegistry = true;
|
|
@@ -30,6 +32,9 @@ export const usage = () => commandUsage({
|
|
|
30
32
|
'save-prod': {
|
|
31
33
|
description: 'Save installed packages to package.json as dependencies.',
|
|
32
34
|
},
|
|
35
|
+
'save-config': {
|
|
36
|
+
description: 'Save registry and git host options given on the command line or via env (e.g. `--registries name=url`) to the project vlt.json, or the user vlt.json with --config=user.',
|
|
37
|
+
},
|
|
33
38
|
workspace: {
|
|
34
39
|
value: '<path|glob>',
|
|
35
40
|
description: 'Limit installation targets to matching workspaces.',
|
|
@@ -111,6 +116,9 @@ export const views = {
|
|
|
111
116
|
message: `${i.buildQueue.length} packages that will need to be built, run "vlt build" to complete the install.`,
|
|
112
117
|
}
|
|
113
118
|
: null),
|
|
119
|
+
...(i.persistedConfig ?
|
|
120
|
+
{ persistedConfig: i.persistedConfig }
|
|
121
|
+
: null),
|
|
114
122
|
};
|
|
115
123
|
},
|
|
116
124
|
human: lazyView(async () => (await import('./install/reporter.ts')).InstallReporter),
|
|
@@ -121,6 +129,7 @@ export const command = async (conf) => {
|
|
|
121
129
|
const monorepo = conf.options.monorepo;
|
|
122
130
|
const scurry = conf.options.scurry;
|
|
123
131
|
const { add } = parseAddArgs(conf, scurry, monorepo);
|
|
132
|
+
const persist = planSpecConfigPersist(conf);
|
|
124
133
|
const frozenLockfile = conf.options['frozen-lockfile'];
|
|
125
134
|
const expectLockfile = conf.options['expect-lockfile'];
|
|
126
135
|
const lockfileOnly = conf.options['lockfile-only'];
|
|
@@ -140,7 +149,11 @@ export const command = async (conf) => {
|
|
|
140
149
|
lockfileOnly,
|
|
141
150
|
saveExact,
|
|
142
151
|
savePrefix,
|
|
143
|
-
}, add)
|
|
152
|
+
}, add).catch((er) => {
|
|
153
|
+
throw asUnknownSpecPrefix(er);
|
|
154
|
+
});
|
|
155
|
+
if (persist)
|
|
156
|
+
await conf.addConfigToFile(persist.which, persist.values);
|
|
144
157
|
/* c8 ignore next 9 - telemetry is best-effort */
|
|
145
158
|
try {
|
|
146
159
|
trackInstall({
|
|
@@ -149,5 +162,10 @@ export const command = async (conf) => {
|
|
|
149
162
|
}, conf.values.telemetry);
|
|
150
163
|
}
|
|
151
164
|
catch { }
|
|
152
|
-
return {
|
|
165
|
+
return {
|
|
166
|
+
buildQueue,
|
|
167
|
+
graph,
|
|
168
|
+
diff,
|
|
169
|
+
...(persist ? { persistedConfig: persist } : null),
|
|
170
|
+
};
|
|
153
171
|
};
|
package/dist/commands/list.js
CHANGED
|
@@ -5,6 +5,7 @@ import { error } from '@vltpkg/error-cause';
|
|
|
5
5
|
import { commandUsage } from "../config/usage.js";
|
|
6
6
|
import { createHostContextsMap } from "../query-host-contexts.js";
|
|
7
7
|
import { createGetAuthHeader } from "../query-auth.js";
|
|
8
|
+
import { assertVltInstalled } from "../is-vlt-installed.js";
|
|
8
9
|
import { MermaidImageView } from "../mermaid-image-view.js";
|
|
9
10
|
export const needsRegistry = true;
|
|
10
11
|
export const usage = () => commandUsage({
|
|
@@ -25,6 +26,11 @@ export const usage = () => commandUsage({
|
|
|
25
26
|
filter what dependencies to include in the output. Using both options
|
|
26
27
|
allows you to render subgraphs of the dependency graph.
|
|
27
28
|
|
|
29
|
+
The listed graph is the one built by \`vlt install\`. In a project
|
|
30
|
+
installed by another client there is no such graph and the command
|
|
31
|
+
errors instead of reporting every dependency as missing. Queries
|
|
32
|
+
using \`:host()\` load their graph from elsewhere and are exempt.
|
|
33
|
+
|
|
28
34
|
Defaults to listing direct dependencies of a project and any configured
|
|
29
35
|
workspace.`,
|
|
30
36
|
examples: {
|
|
@@ -73,19 +79,6 @@ export const command = async (conf) => {
|
|
|
73
79
|
const mainManifest = conf.options.packageJson.maybeRead(conf.options.projectRoot);
|
|
74
80
|
let graph;
|
|
75
81
|
let securityArchive;
|
|
76
|
-
// optionally load the cwd graph if we found a package.json file
|
|
77
|
-
if (mainManifest) {
|
|
78
|
-
graph = actual.load({
|
|
79
|
-
...conf.options,
|
|
80
|
-
mainManifest,
|
|
81
|
-
modifiers,
|
|
82
|
-
monorepo,
|
|
83
|
-
loadManifests: true,
|
|
84
|
-
});
|
|
85
|
-
securityArchive = await SecurityArchive.start({
|
|
86
|
-
nodes: [...graph.nodes.values()],
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
82
|
// Validate positional arguments - only allow package names, not direct queries
|
|
90
83
|
for (const arg of conf.positionals) {
|
|
91
84
|
if (!/^[@\w-]/.test(arg)) {
|
|
@@ -103,6 +96,25 @@ export const command = async (conf) => {
|
|
|
103
96
|
const scopeQueryString = conf.get('scope');
|
|
104
97
|
const queryString = targetQueryString || positionalQueryString;
|
|
105
98
|
const projectQueryString = ':workspace, :project > *';
|
|
99
|
+
// `:host()` swaps the graph for one loaded from somewhere else, so
|
|
100
|
+
// those queries do not need this project to be installed.
|
|
101
|
+
const usesHostContext = [queryString, scopeQueryString].some(q => q?.includes(':host('));
|
|
102
|
+
// optionally load the cwd graph if we found a package.json file
|
|
103
|
+
if (mainManifest) {
|
|
104
|
+
if (!usesHostContext) {
|
|
105
|
+
assertVltInstalled(conf.options.projectRoot, 'ls');
|
|
106
|
+
}
|
|
107
|
+
graph = actual.load({
|
|
108
|
+
...conf.options,
|
|
109
|
+
mainManifest,
|
|
110
|
+
modifiers,
|
|
111
|
+
monorepo,
|
|
112
|
+
loadManifests: true,
|
|
113
|
+
});
|
|
114
|
+
securityArchive = await SecurityArchive.start({
|
|
115
|
+
nodes: [...graph.nodes.values()],
|
|
116
|
+
});
|
|
117
|
+
}
|
|
106
118
|
const selectImporters = [];
|
|
107
119
|
const hostContexts = await createHostContextsMap(conf);
|
|
108
120
|
const getAuthHeader = createGetAuthHeader(conf);
|
package/dist/commands/profile.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { error } from '@vltpkg/error-cause';
|
|
2
|
-
import { RegistryClient } from '@vltpkg/registry-client';
|
|
2
|
+
import { RegistryClient, assertOk } from '@vltpkg/registry-client';
|
|
3
3
|
import { commandUsage } from "../config/usage.js";
|
|
4
4
|
import { resolveRegistry } from "../require-registry.js";
|
|
5
5
|
export const needsRegistry = true;
|
|
@@ -69,6 +69,16 @@ const getProfile = async (conf, args) => {
|
|
|
69
69
|
const registryUrl = new URL(await resolveRegistry(conf));
|
|
70
70
|
const url = new URL('-/npm/v1/user', registryUrl);
|
|
71
71
|
const response = await rc.request(url, { useCache: false });
|
|
72
|
+
// before json(): otherwise an error body makes the 'Property not
|
|
73
|
+
// found in profile' check below blame the user's argument for what is
|
|
74
|
+
// really an auth failure.
|
|
75
|
+
assertOk(response, {
|
|
76
|
+
message: 'Failed to fetch profile',
|
|
77
|
+
url,
|
|
78
|
+
advice: statusCode => statusCode === 401 || statusCode === 403 ?
|
|
79
|
+
`Not logged in to ${registryUrl.origin}. Run \`vlt login\` and try again.`
|
|
80
|
+
: undefined,
|
|
81
|
+
});
|
|
72
82
|
const data = response.json();
|
|
73
83
|
const [property] = args;
|
|
74
84
|
if (property) {
|
|
@@ -101,6 +111,14 @@ const setProfile = async (conf, args) => {
|
|
|
101
111
|
otp: conf.options.otp,
|
|
102
112
|
useCache: false,
|
|
103
113
|
});
|
|
114
|
+
assertOk(response, {
|
|
115
|
+
message: 'Failed to update profile',
|
|
116
|
+
url,
|
|
117
|
+
method: 'POST',
|
|
118
|
+
advice: statusCode => statusCode === 401 || statusCode === 403 ?
|
|
119
|
+
`Not logged in to ${registryUrl.origin}. Run \`vlt login\` and try again.`
|
|
120
|
+
: undefined,
|
|
121
|
+
});
|
|
104
122
|
const data = response.json();
|
|
105
123
|
return { property, value: data[property] };
|
|
106
124
|
};
|
package/dist/commands/publish.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { error } from '@vltpkg/error-cause';
|
|
2
|
-
import { RegistryClient, oidc, registryBase, } from '@vltpkg/registry-client';
|
|
2
|
+
import { RegistryClient, assertOk, oidc, registryBase, requestError, } from '@vltpkg/registry-client';
|
|
3
3
|
import { run } from '@vltpkg/run';
|
|
4
4
|
import { commandUsage } from "../config/usage.js";
|
|
5
5
|
import { packTarball } from "../pack-tarball.js";
|
|
6
6
|
import assert from 'node:assert';
|
|
7
|
-
import { asError } from '@vltpkg/types';
|
|
8
7
|
import { dirname, resolve } from 'node:path';
|
|
9
8
|
import prettyBytes from 'pretty-bytes';
|
|
10
9
|
import { actual } from '@vltpkg/graph';
|
|
@@ -12,7 +11,6 @@ import { Query } from '@vltpkg/query';
|
|
|
12
11
|
import { createHostContextsMap } from "../query-host-contexts.js";
|
|
13
12
|
import { minimatch } from 'minimatch';
|
|
14
13
|
import { resolveRegistry } from "../require-registry.js";
|
|
15
|
-
import { registryErrorMessage } from "../registry-error-message.js";
|
|
16
14
|
import { stderr } from "../output.js";
|
|
17
15
|
export const needsRegistry = true;
|
|
18
16
|
export const usage = () => commandUsage({
|
|
@@ -246,6 +244,17 @@ const commandSingle = async (location, conf) => {
|
|
|
246
244
|
});
|
|
247
245
|
const publishUrl = new URL(name.startsWith('@') ? name.replace('/', '%2F') : name, registryUrl);
|
|
248
246
|
if (!dry) {
|
|
247
|
+
// the same guidance whether the registry refused the request or the
|
|
248
|
+
// client threw before a response came back (an expired token, say)
|
|
249
|
+
const publishAdvice = (statusCode) => statusCode === 409 ?
|
|
250
|
+
`${name}@${version} already exists in the registry. Bump the version and try again.`
|
|
251
|
+
: statusCode === 404 ?
|
|
252
|
+
"Make sure you're logged in and have access to publish the package."
|
|
253
|
+
: statusCode === 401 ?
|
|
254
|
+
`Not logged in to ${registryUrl.origin}. Run \`vlt login\` and try again.`
|
|
255
|
+
: statusCode === 403 ?
|
|
256
|
+
`${name} cannot be published by this account. Run \`vlt whoami\` to see who you are logged in as, and \`vlt login\` to switch accounts. A name already taken by someone else cannot be reused.`
|
|
257
|
+
: undefined;
|
|
249
258
|
let response;
|
|
250
259
|
try {
|
|
251
260
|
response = await rc.request(publishUrl, {
|
|
@@ -261,27 +270,26 @@ const commandSingle = async (location, conf) => {
|
|
|
261
270
|
});
|
|
262
271
|
}
|
|
263
272
|
catch (err) {
|
|
264
|
-
throw
|
|
265
|
-
|
|
273
|
+
throw requestError(err, {
|
|
274
|
+
message: 'Failed to publish package',
|
|
275
|
+
url: publishUrl,
|
|
276
|
+
method: 'PUT',
|
|
277
|
+
advice: publishAdvice,
|
|
266
278
|
});
|
|
267
279
|
}
|
|
268
280
|
// Any 2xx response is a successful publish. The npm registry may
|
|
269
281
|
// respond with a 202 Accepted when processing is deferred (e.g. for
|
|
270
282
|
// publish-time malware scanning).
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
url: publishUrl,
|
|
282
|
-
response,
|
|
283
|
-
});
|
|
284
|
-
}
|
|
283
|
+
//
|
|
284
|
+
// assertOk tells a rejected credential (ENEEDAUTH) apart from a
|
|
285
|
+
// registry that is simply broken (EREQUEST): the former is the
|
|
286
|
+
// user's to fix, not a bug to report.
|
|
287
|
+
assertOk(response, {
|
|
288
|
+
message: 'Failed to publish package',
|
|
289
|
+
url: publishUrl,
|
|
290
|
+
method: 'PUT',
|
|
291
|
+
advice: publishAdvice,
|
|
292
|
+
});
|
|
285
293
|
// On deferred publishes the registry explains the delay in an
|
|
286
294
|
// npm-notice header, e.g. "Your package is being processed and may
|
|
287
295
|
// take a few minutes to become available."
|
package/dist/commands/query.js
CHANGED
|
@@ -7,6 +7,7 @@ import { SecurityArchive } from '@vltpkg/security-archive';
|
|
|
7
7
|
import { commandUsage } from "../config/usage.js";
|
|
8
8
|
import { createHostContextsMap } from "../query-host-contexts.js";
|
|
9
9
|
import { createGetAuthHeader } from "../query-auth.js";
|
|
10
|
+
import { assertVltInstalled } from "../is-vlt-installed.js";
|
|
10
11
|
import { MermaidImageView } from "../mermaid-image-view.js";
|
|
11
12
|
export const needsRegistry = true;
|
|
12
13
|
export const usage = () => commandUsage({
|
|
@@ -30,6 +31,11 @@ export const usage = () => commandUsage({
|
|
|
30
31
|
dependencies to include in the output. Using both options allows you to
|
|
31
32
|
render subgraphs of the dependency graph.
|
|
32
33
|
|
|
34
|
+
The queried graph is the one built by \`vlt install\`. In a project
|
|
35
|
+
installed by another client there is no such graph and the command
|
|
36
|
+
errors instead of reporting every dependency as missing. Queries
|
|
37
|
+
using \`:host()\` load their graph from elsewhere and are exempt.
|
|
38
|
+
|
|
33
39
|
Defaults to listing all dependencies of the project root and workspaces.`,
|
|
34
40
|
examples: {
|
|
35
41
|
[`'#foo'`]: {
|
|
@@ -109,8 +115,22 @@ export const command = async (conf) => {
|
|
|
109
115
|
const mainManifest = conf.options.packageJson.maybeRead(conf.options.projectRoot);
|
|
110
116
|
let graph;
|
|
111
117
|
let securityArchive;
|
|
118
|
+
// retrieve default values and set up host contexts
|
|
119
|
+
const defaultProjectQueryString = '*';
|
|
120
|
+
const defaultLocalScopeQueryString = ':host(local) *';
|
|
121
|
+
const positionalQueryString = conf.positionals[0];
|
|
122
|
+
const targetQueryString = conf.get('target');
|
|
123
|
+
const scopeQueryString = conf.get('scope');
|
|
124
|
+
// --target takes precedence over the positional query
|
|
125
|
+
const queryString = targetQueryString || positionalQueryString;
|
|
126
|
+
// `:host()` swaps the graph for one loaded from somewhere else, so
|
|
127
|
+
// those queries do not need this project to be installed.
|
|
128
|
+
const usesHostContext = [queryString, scopeQueryString].some(q => q?.includes(':host('));
|
|
112
129
|
// optionally load the cwd graph if we found a package.json file
|
|
113
130
|
if (mainManifest) {
|
|
131
|
+
if (!usesHostContext) {
|
|
132
|
+
assertVltInstalled(conf.options.projectRoot, 'query');
|
|
133
|
+
}
|
|
114
134
|
graph = actual.load({
|
|
115
135
|
...conf.options,
|
|
116
136
|
mainManifest,
|
|
@@ -122,13 +142,6 @@ export const command = async (conf) => {
|
|
|
122
142
|
nodes: [...graph.nodes.values()],
|
|
123
143
|
});
|
|
124
144
|
}
|
|
125
|
-
// retrieve default values and set up host contexts
|
|
126
|
-
const defaultProjectQueryString = '*';
|
|
127
|
-
const defaultLocalScopeQueryString = ':host(local) *';
|
|
128
|
-
const positionalQueryString = conf.positionals[0];
|
|
129
|
-
const targetQueryString = conf.get('target');
|
|
130
|
-
const scopeQueryString = conf.get('scope');
|
|
131
|
-
const queryString = targetQueryString || positionalQueryString;
|
|
132
145
|
const hostContexts = await createHostContextsMap(conf);
|
|
133
146
|
const diffFiles = createDiffFilesProvider(conf.options.projectRoot);
|
|
134
147
|
const getAuthHeader = createGetAuthHeader(conf);
|
package/dist/commands/setup.js
CHANGED
|
@@ -6,6 +6,7 @@ import { createInterface } from 'node:readline/promises';
|
|
|
6
6
|
import { configWriteTarget } from "../config/index.js";
|
|
7
7
|
import { registrySelectionFields } from "../config/merge-layers.js";
|
|
8
8
|
import { commandUsage } from "../config/usage.js";
|
|
9
|
+
import { normalizeRegistryURL } from "../require-registry.js";
|
|
9
10
|
import { stdout } from "../output.js";
|
|
10
11
|
/** Where users sign up for / log into a vlt.io account. */
|
|
11
12
|
export const VLT_SIGNUP_URL = 'https://www.vlt.io';
|
|
@@ -36,8 +37,6 @@ const accountAuthError = (account, er) => (isErrorWithCause(er) &&
|
|
|
36
37
|
`organization at ${VLT_SIGNUP_URL}, then run \`vlt setup\` again.`,
|
|
37
38
|
].join('\n'), { code: 'ECONFIG', cause: er })
|
|
38
39
|
: asError(er);
|
|
39
|
-
/** Ensure a registry URL ends with a single trailing slash. */
|
|
40
|
-
const normalizeRegistryURL = (url) => url.endsWith('/') ? url : `${url}/`;
|
|
41
40
|
export const views = {
|
|
42
41
|
human: (result) => {
|
|
43
42
|
const lines = [
|
package/dist/commands/token.js
CHANGED
|
@@ -77,7 +77,9 @@ const formatRegistryTokens = (r) => {
|
|
|
77
77
|
lines.push(' (skipped remote query — no auth token)');
|
|
78
78
|
}
|
|
79
79
|
else if (r.error) {
|
|
80
|
-
|
|
80
|
+
// messages now carry advice on a second line; keep it indented
|
|
81
|
+
// under the registry heading rather than dedented to column 0.
|
|
82
|
+
lines.push(` error: ${r.error.replaceAll('\n', '\n ')}`);
|
|
81
83
|
}
|
|
82
84
|
else if (r.tokens.length === 0) {
|
|
83
85
|
lines.push(' (no remote tokens found)');
|