@vltpkg/cli-sdk 1.0.0-rc.9 → 1.0.2
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.d.ts +23 -0
- package/dist/commands/access.js +251 -0
- package/dist/{esm/commands → commands}/bugs.d.ts +0 -1
- package/dist/{esm/commands → commands}/bugs.js +0 -1
- package/dist/{esm/commands → commands}/build.d.ts +1 -1
- package/dist/{esm/commands → commands}/build.js +1 -1
- package/dist/{esm/commands → commands}/cache.d.ts +1 -1
- package/dist/{esm/commands → commands}/cache.js +1 -1
- package/dist/{esm/commands → commands}/ci.d.ts +1 -1
- package/dist/{esm/commands → commands}/ci.js +12 -3
- package/dist/{esm/commands → commands}/config.d.ts +0 -1
- package/dist/{esm/commands → commands}/config.js +6 -1
- package/dist/commands/create.d.ts +9 -0
- package/dist/commands/create.js +103 -0
- package/dist/commands/deprecate.d.ts +14 -0
- package/dist/commands/deprecate.js +142 -0
- package/dist/commands/dist-tag.d.ts +22 -0
- package/dist/commands/dist-tag.js +179 -0
- package/dist/{esm/commands → commands}/docs.d.ts +0 -1
- package/dist/{esm/commands → commands}/docs.js +0 -1
- package/dist/{esm/commands → commands}/exec-cache.d.ts +1 -1
- package/dist/{esm/commands → commands}/exec-cache.js +1 -1
- package/dist/{esm/commands/run-exec.d.ts → commands/exec-local.d.ts} +0 -1
- package/dist/{esm/commands → commands}/exec-local.js +23 -1
- package/dist/{esm/commands → commands}/exec.d.ts +1 -1
- package/dist/{esm/commands → commands}/exec.js +85 -10
- package/dist/{esm/commands → commands}/help.d.ts +0 -1
- package/dist/{esm/commands → commands}/help.js +5 -1
- package/dist/{esm/commands → commands}/init.d.ts +0 -1
- package/dist/{esm/commands → commands}/init.js +31 -10
- package/dist/{esm/commands → commands}/install/reporter.d.ts +0 -1
- package/dist/{esm/commands → commands}/install/reporter.js +0 -1
- package/dist/{esm/commands → commands}/install.d.ts +22 -3
- package/dist/commands/install.js +152 -0
- package/dist/{esm/commands → commands}/list.d.ts +5 -2
- package/dist/{esm/commands → commands}/list.js +9 -10
- package/dist/{esm/commands → commands}/login.d.ts +0 -1
- package/dist/commands/login.js +35 -0
- package/dist/{esm/commands → commands}/logout.d.ts +1 -1
- package/dist/commands/logout.js +27 -0
- package/dist/{esm/commands → commands}/pack.d.ts +1 -1
- package/dist/{esm/commands → commands}/pack.js +91 -32
- package/dist/commands/ping.d.ts +18 -0
- package/dist/commands/ping.js +117 -0
- package/dist/{esm/commands → commands}/pkg.d.ts +0 -1
- package/dist/{esm/commands → commands}/pkg.js +27 -1
- package/dist/commands/profile.d.ts +14 -0
- package/dist/commands/profile.js +106 -0
- package/dist/{esm/commands → commands}/publish.d.ts +2 -2
- package/dist/{esm/commands → commands}/publish.js +70 -16
- package/dist/{esm/commands → commands}/query.d.ts +5 -2
- package/dist/{esm/commands → commands}/query.js +54 -11
- package/dist/commands/registry.d.ts +26 -0
- package/dist/commands/registry.js +99 -0
- package/dist/commands/repo.d.ts +17 -0
- package/dist/commands/repo.js +157 -0
- package/dist/{esm/commands/exec-local.d.ts → commands/run-exec.d.ts} +1 -1
- package/dist/commands/run-exec.js +41 -0
- package/dist/{esm/commands → commands}/run.d.ts +0 -1
- package/dist/{esm/commands → commands}/run.js +27 -1
- package/dist/commands/setup.d.ts +25 -0
- package/dist/commands/setup.js +155 -0
- package/dist/commands/token.d.ts +32 -0
- package/dist/commands/token.js +193 -0
- package/dist/{esm/commands → commands}/uninstall.d.ts +1 -1
- package/dist/{esm/commands → commands}/uninstall.js +15 -1
- package/dist/commands/unpublish.d.ts +16 -0
- package/dist/commands/unpublish.js +203 -0
- package/dist/{esm/commands → commands}/update.d.ts +1 -1
- package/dist/{esm/commands → commands}/update.js +7 -1
- package/dist/{esm/commands → commands}/version.d.ts +0 -1
- package/dist/{esm/commands → commands}/version.js +27 -1
- package/dist/commands/view.d.ts +23 -0
- package/dist/commands/view.js +335 -0
- package/dist/{esm/commands → commands}/whoami.d.ts +1 -1
- package/dist/commands/whoami.js +33 -0
- package/dist/{esm/config → config}/definition.d.ts +72 -19
- package/dist/{esm/config → config}/definition.js +157 -50
- package/dist/{esm/config → config}/index.d.ts +0 -1
- package/dist/{esm/config → config}/index.js +43 -2
- package/dist/{esm/config → config}/merge.d.ts +0 -1
- package/dist/{esm/config → config}/merge.js +0 -1
- package/dist/{esm/config → config}/usage.d.ts +0 -1
- package/dist/{esm/config → config}/usage.js +0 -1
- package/dist/{esm/custom-help.d.ts → custom-help.d.ts} +0 -1
- package/dist/{esm/custom-help.js → custom-help.js} +95 -120
- package/dist/{esm/exec-command.d.ts → exec-command.d.ts} +0 -1
- package/dist/{esm/exec-command.js → exec-command.js} +14 -8
- package/dist/{esm/index.d.ts → index.d.ts} +0 -1
- package/dist/{esm/index.js → index.js} +5 -2
- package/dist/{esm/load-command.d.ts → load-command.d.ts} +6 -1
- package/dist/{esm/load-command.js → load-command.js} +0 -1
- package/dist/mermaid-image-view.d.ts +18 -0
- package/dist/mermaid-image-view.js +36 -0
- package/dist/{esm/output.d.ts → output.d.ts} +2 -2
- package/dist/{esm/output.js → output.js} +70 -3
- package/dist/{esm/pack-tarball.d.ts → pack-tarball.d.ts} +15 -1
- package/dist/{esm/pack-tarball.js → pack-tarball.js} +133 -91
- package/dist/{esm/parse-add-remove-args.d.ts → parse-add-remove-args.d.ts} +0 -1
- package/dist/{esm/parse-add-remove-args.js → parse-add-remove-args.js} +65 -12
- package/dist/{esm/print-err.d.ts → print-err.d.ts} +0 -1
- package/dist/{esm/print-err.js → print-err.js} +28 -4
- package/dist/query-diff-files.d.ts +17 -0
- package/dist/query-diff-files.js +63 -0
- package/dist/{esm/query-host-contexts.d.ts → query-host-contexts.d.ts} +0 -1
- package/dist/{esm/query-host-contexts.js → query-host-contexts.js} +8 -7
- package/dist/{esm/read-password.d.ts → read-password.d.ts} +0 -1
- package/dist/{esm/read-password.js → read-password.js} +0 -1
- package/dist/read-project-folders.d.ts +17 -0
- package/dist/read-project-folders.js +100 -0
- package/dist/registry-error-message.d.ts +2 -0
- package/dist/registry-error-message.js +29 -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/require-registry.d.ts +48 -0
- package/dist/require-registry.js +122 -0
- package/dist/select-registry.d.ts +23 -0
- package/dist/select-registry.js +40 -0
- package/dist/telemetry.d.ts +58 -0
- package/dist/telemetry.js +170 -0
- package/dist/verbose-log.d.ts +31 -0
- package/dist/verbose-log.js +62 -0
- package/dist/{esm/view.d.ts → view.d.ts} +0 -1
- package/dist/{esm/view.js → view.js} +1 -2
- package/package.json +75 -82
- package/dist/esm/commands/bugs.d.ts.map +0 -1
- package/dist/esm/commands/bugs.js.map +0 -1
- package/dist/esm/commands/build.d.ts.map +0 -1
- package/dist/esm/commands/build.js.map +0 -1
- package/dist/esm/commands/cache.d.ts.map +0 -1
- package/dist/esm/commands/cache.js.map +0 -1
- package/dist/esm/commands/ci.d.ts.map +0 -1
- package/dist/esm/commands/ci.js.map +0 -1
- package/dist/esm/commands/config.d.ts.map +0 -1
- package/dist/esm/commands/config.js.map +0 -1
- package/dist/esm/commands/docs.d.ts.map +0 -1
- package/dist/esm/commands/docs.js.map +0 -1
- package/dist/esm/commands/exec-cache.d.ts.map +0 -1
- package/dist/esm/commands/exec-cache.js.map +0 -1
- package/dist/esm/commands/exec-local.d.ts.map +0 -1
- package/dist/esm/commands/exec-local.js.map +0 -1
- package/dist/esm/commands/exec.d.ts.map +0 -1
- package/dist/esm/commands/exec.js.map +0 -1
- package/dist/esm/commands/help.d.ts.map +0 -1
- package/dist/esm/commands/help.js.map +0 -1
- package/dist/esm/commands/init.d.ts.map +0 -1
- package/dist/esm/commands/init.js.map +0 -1
- package/dist/esm/commands/install/reporter.d.ts.map +0 -1
- package/dist/esm/commands/install/reporter.js.map +0 -1
- package/dist/esm/commands/install.d.ts.map +0 -1
- package/dist/esm/commands/install.js +0 -46
- package/dist/esm/commands/install.js.map +0 -1
- package/dist/esm/commands/list.d.ts.map +0 -1
- package/dist/esm/commands/list.js.map +0 -1
- package/dist/esm/commands/login.d.ts.map +0 -1
- package/dist/esm/commands/login.js +0 -13
- package/dist/esm/commands/login.js.map +0 -1
- package/dist/esm/commands/logout.d.ts.map +0 -1
- package/dist/esm/commands/logout.js +0 -13
- package/dist/esm/commands/logout.js.map +0 -1
- package/dist/esm/commands/pack.d.ts.map +0 -1
- package/dist/esm/commands/pack.js.map +0 -1
- package/dist/esm/commands/pkg.d.ts.map +0 -1
- package/dist/esm/commands/pkg.js.map +0 -1
- package/dist/esm/commands/publish.d.ts.map +0 -1
- package/dist/esm/commands/publish.js.map +0 -1
- package/dist/esm/commands/query.d.ts.map +0 -1
- package/dist/esm/commands/query.js.map +0 -1
- package/dist/esm/commands/run-exec.d.ts.map +0 -1
- package/dist/esm/commands/run-exec.js +0 -14
- package/dist/esm/commands/run-exec.js.map +0 -1
- package/dist/esm/commands/run.d.ts.map +0 -1
- package/dist/esm/commands/run.js.map +0 -1
- package/dist/esm/commands/serve.d.ts +0 -14
- package/dist/esm/commands/serve.d.ts.map +0 -1
- package/dist/esm/commands/serve.js +0 -103
- package/dist/esm/commands/serve.js.map +0 -1
- package/dist/esm/commands/token.d.ts +0 -4
- package/dist/esm/commands/token.d.ts.map +0 -1
- package/dist/esm/commands/token.js +0 -30
- package/dist/esm/commands/token.js.map +0 -1
- package/dist/esm/commands/uninstall.d.ts.map +0 -1
- package/dist/esm/commands/uninstall.js.map +0 -1
- package/dist/esm/commands/update.d.ts.map +0 -1
- package/dist/esm/commands/update.js.map +0 -1
- package/dist/esm/commands/version.d.ts.map +0 -1
- package/dist/esm/commands/version.js.map +0 -1
- package/dist/esm/commands/whoami.d.ts.map +0 -1
- package/dist/esm/commands/whoami.js +0 -19
- package/dist/esm/commands/whoami.js.map +0 -1
- package/dist/esm/config/definition.d.ts.map +0 -1
- package/dist/esm/config/definition.js.map +0 -1
- package/dist/esm/config/index.d.ts.map +0 -1
- package/dist/esm/config/index.js.map +0 -1
- package/dist/esm/config/merge.d.ts.map +0 -1
- package/dist/esm/config/merge.js.map +0 -1
- package/dist/esm/config/usage.d.ts.map +0 -1
- package/dist/esm/config/usage.js.map +0 -1
- package/dist/esm/custom-help.d.ts.map +0 -1
- package/dist/esm/custom-help.js.map +0 -1
- package/dist/esm/exec-command.d.ts.map +0 -1
- package/dist/esm/exec-command.js.map +0 -1
- package/dist/esm/index.d.ts.map +0 -1
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/load-command.d.ts.map +0 -1
- package/dist/esm/load-command.js.map +0 -1
- package/dist/esm/output.d.ts.map +0 -1
- package/dist/esm/output.js.map +0 -1
- package/dist/esm/pack-tarball.d.ts.map +0 -1
- package/dist/esm/pack-tarball.js.map +0 -1
- package/dist/esm/package.json +0 -3
- package/dist/esm/parse-add-remove-args.d.ts.map +0 -1
- package/dist/esm/parse-add-remove-args.js.map +0 -1
- package/dist/esm/print-err.d.ts.map +0 -1
- package/dist/esm/print-err.js.map +0 -1
- package/dist/esm/query-host-contexts.d.ts.map +0 -1
- package/dist/esm/query-host-contexts.js.map +0 -1
- package/dist/esm/read-password.d.ts.map +0 -1
- package/dist/esm/read-password.js.map +0 -1
- package/dist/esm/start-gui.d.ts +0 -10
- package/dist/esm/start-gui.d.ts.map +0 -1
- package/dist/esm/start-gui.js +0 -60
- package/dist/esm/start-gui.js.map +0 -1
- package/dist/esm/view.d.ts.map +0 -1
- package/dist/esm/view.js.map +0 -1
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { availableParallelism, homedir } from 'node:os';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
|
+
import { callLimit } from 'promise-call-limit';
|
|
4
|
+
const limit = Math.max(availableParallelism() - 1, 1) * 8;
|
|
5
|
+
let home;
|
|
6
|
+
try {
|
|
7
|
+
home = homedir();
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
home = dirname(process.cwd());
|
|
11
|
+
}
|
|
12
|
+
const ignoredHomedirFolderNames = [
|
|
13
|
+
'downloads',
|
|
14
|
+
'movies',
|
|
15
|
+
'music',
|
|
16
|
+
'pictures',
|
|
17
|
+
'private',
|
|
18
|
+
'library',
|
|
19
|
+
'dropbox',
|
|
20
|
+
].concat(process.platform === 'darwin' ?
|
|
21
|
+
[
|
|
22
|
+
'public',
|
|
23
|
+
'private',
|
|
24
|
+
'applications',
|
|
25
|
+
'applications (parallels)',
|
|
26
|
+
'sites',
|
|
27
|
+
'sync',
|
|
28
|
+
]
|
|
29
|
+
: process.platform === 'win32' ?
|
|
30
|
+
[
|
|
31
|
+
'appdata',
|
|
32
|
+
'application data',
|
|
33
|
+
'favorites',
|
|
34
|
+
'links',
|
|
35
|
+
'videos',
|
|
36
|
+
'contacts',
|
|
37
|
+
'searches',
|
|
38
|
+
]
|
|
39
|
+
: ['videos', 'public']);
|
|
40
|
+
/**
|
|
41
|
+
* Retrieves folders from a given directory, if that directory is
|
|
42
|
+
* recognized to be the current cli project root folder then we
|
|
43
|
+
* proceed to read its siblings.
|
|
44
|
+
*
|
|
45
|
+
* Traverses nested directory recursively until project folders can
|
|
46
|
+
* be find, always stopping at the first level where a package.json
|
|
47
|
+
* is present.
|
|
48
|
+
*/
|
|
49
|
+
export const readProjectFolders = async ({ path = home, scurry, userDefinedProjectPaths, }, maxDepth = 7) => {
|
|
50
|
+
const result = [];
|
|
51
|
+
const homeEntry = scurry.cwd.resolve(home);
|
|
52
|
+
const paths = userDefinedProjectPaths.length ? userDefinedProjectPaths : [path];
|
|
53
|
+
const step = (entry, depth) => async () => {
|
|
54
|
+
try {
|
|
55
|
+
for (const child of await entry.readdir()) {
|
|
56
|
+
if (await collectResult(child, result, scurry, entry === homeEntry, depth, maxDepth)) {
|
|
57
|
+
traverse.push(step(child, depth + 1));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/* c8 ignore next 4 */
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// Ignore directories that can't be read.
|
|
64
|
+
// This commonly happens in restricted environments.
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
let traverse = (await Promise.all(paths.map(path => scurry.lstat(path))))
|
|
68
|
+
.filter(p => !!p)
|
|
69
|
+
.map(p => step(p, 0));
|
|
70
|
+
// have to do it in phases this way because pushing into the queue
|
|
71
|
+
// during the promise-call-limit confuses its tracking.
|
|
72
|
+
let t;
|
|
73
|
+
do {
|
|
74
|
+
t = traverse;
|
|
75
|
+
traverse = [];
|
|
76
|
+
await callLimit(t, { limit });
|
|
77
|
+
} while (traverse.length);
|
|
78
|
+
return result;
|
|
79
|
+
};
|
|
80
|
+
const collectResult = async (entry, result, scurry, fromHome, depth, maxDepth) => {
|
|
81
|
+
if (!entry.isDirectory() ||
|
|
82
|
+
entry.isSymbolicLink() ||
|
|
83
|
+
entry.name === 'node_modules' ||
|
|
84
|
+
(fromHome &&
|
|
85
|
+
ignoredHomedirFolderNames.includes(entry.name.toLowerCase())) ||
|
|
86
|
+
entry.name.startsWith('.') ||
|
|
87
|
+
depth > maxDepth) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
const resolved = entry.fullpath();
|
|
91
|
+
const statPackageJson = await scurry
|
|
92
|
+
.lstat(`${resolved}/package.json`)
|
|
93
|
+
.catch(() => { });
|
|
94
|
+
const hasValidPackageJson = statPackageJson &&
|
|
95
|
+
statPackageJson.isFile() &&
|
|
96
|
+
!statPackageJson.isSymbolicLink();
|
|
97
|
+
if (hasValidPackageJson)
|
|
98
|
+
result.push(entry);
|
|
99
|
+
return !hasValidPackageJson;
|
|
100
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { STATUS_CODES } from 'node:http';
|
|
2
|
+
export const registryErrorMessage = (response) => {
|
|
3
|
+
const statusMessage = STATUS_CODES[response.statusCode];
|
|
4
|
+
const status = `${response.statusCode}${statusMessage ? ` ${statusMessage}` : ''}`;
|
|
5
|
+
let text;
|
|
6
|
+
try {
|
|
7
|
+
text = response.text().trim();
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return status;
|
|
11
|
+
}
|
|
12
|
+
if (!text)
|
|
13
|
+
return status;
|
|
14
|
+
let detail = text;
|
|
15
|
+
try {
|
|
16
|
+
const body = JSON.parse(text);
|
|
17
|
+
if (body &&
|
|
18
|
+
typeof body === 'object' &&
|
|
19
|
+
'error' in body &&
|
|
20
|
+
typeof body.error === 'string' &&
|
|
21
|
+
body.error) {
|
|
22
|
+
detail = body.error;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
// A non-JSON response body is itself the most useful error detail.
|
|
27
|
+
}
|
|
28
|
+
return `${status} — ${detail}`;
|
|
29
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const reloadConfig = async (folder) => {
|
|
2
|
+
try {
|
|
3
|
+
const { unload } = (await import('@vltpkg/vlt-json'));
|
|
4
|
+
unload('user');
|
|
5
|
+
unload('project');
|
|
6
|
+
/* c8 ignore next */
|
|
7
|
+
}
|
|
8
|
+
catch { }
|
|
9
|
+
const { Config } = await import("./config/index.js");
|
|
10
|
+
return Config.load(folder, process.argv, true);
|
|
11
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type OutputFormat = 'svg' | 'png';
|
|
2
|
+
/**
|
|
3
|
+
* Renders mermaid diagram text to an SVG string using
|
|
4
|
+
* the `beautiful-mermaid` library. No external process
|
|
5
|
+
* is spawned — everything runs in-process.
|
|
6
|
+
* @returns {string} The SVG markup as a string.
|
|
7
|
+
*/
|
|
8
|
+
export declare const renderMermaidSvg: (mermaidText: string) => string;
|
|
9
|
+
/**
|
|
10
|
+
* Renders mermaid diagram text to an SVG file.
|
|
11
|
+
* Uses `beautiful-mermaid` in-process, then writes
|
|
12
|
+
* the result to a temp directory.
|
|
13
|
+
* @returns {Promise<string>} The file path of the generated SVG.
|
|
14
|
+
*/
|
|
15
|
+
export declare const renderMermaidToFile: (mermaidText: string) => Promise<string>;
|
|
16
|
+
/**
|
|
17
|
+
* Renders mermaid diagram text to a PNG file.
|
|
18
|
+
* Uses `beautiful-mermaid` for SVG, then `@resvg/resvg-wasm`
|
|
19
|
+
* to convert SVG to PNG. Writes to a temp directory.
|
|
20
|
+
* @returns {Promise<string>} The file path of the generated PNG.
|
|
21
|
+
*/
|
|
22
|
+
export declare const renderMermaidToPng: (mermaidText: string) => Promise<string>;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { writeFile, mkdtemp } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { error } from '@vltpkg/error-cause';
|
|
5
|
+
import { renderMermaidSVG } from 'beautiful-mermaid';
|
|
6
|
+
/**
|
|
7
|
+
* Replace `#64;` with `@` for display rendering.
|
|
8
|
+
* Mermaid text uses `#64;` to avoid issues with `@` in
|
|
9
|
+
* GitHub/markdown parsers, but SVG/PNG should show `@`.
|
|
10
|
+
*/
|
|
11
|
+
const decodeForDisplay = (mermaidText) => mermaidText.replace(/#64;/g, '@');
|
|
12
|
+
/**
|
|
13
|
+
* Renders mermaid diagram text to an SVG string using
|
|
14
|
+
* the `beautiful-mermaid` library. No external process
|
|
15
|
+
* is spawned — everything runs in-process.
|
|
16
|
+
* @returns {string} The SVG markup as a string.
|
|
17
|
+
*/
|
|
18
|
+
export const renderMermaidSvg = (mermaidText) => {
|
|
19
|
+
try {
|
|
20
|
+
return renderMermaidSVG(decodeForDisplay(mermaidText), {
|
|
21
|
+
bg: '#FFFFFF',
|
|
22
|
+
fg: '#27272A',
|
|
23
|
+
padding: 40,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
catch (cause) {
|
|
27
|
+
throw error('Error rendering SVG', { cause });
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Renders mermaid diagram text to an SVG file.
|
|
32
|
+
* Uses `beautiful-mermaid` in-process, then writes
|
|
33
|
+
* the result to a temp directory.
|
|
34
|
+
* @returns {Promise<string>} The file path of the generated SVG.
|
|
35
|
+
*/
|
|
36
|
+
export const renderMermaidToFile = async (mermaidText) => {
|
|
37
|
+
const svg = renderMermaidSvg(mermaidText);
|
|
38
|
+
const dir = await mkdtemp(join(tmpdir(), 'vlt-mermaid-'));
|
|
39
|
+
const outputFile = join(dir, 'graph.svg');
|
|
40
|
+
await writeFile(outputFile, svg);
|
|
41
|
+
return outputFile;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Renders mermaid diagram text to a PNG file.
|
|
45
|
+
* Uses `beautiful-mermaid` for SVG, then `@resvg/resvg-wasm`
|
|
46
|
+
* to convert SVG to PNG. Writes to a temp directory.
|
|
47
|
+
* @returns {Promise<string>} The file path of the generated PNG.
|
|
48
|
+
*/
|
|
49
|
+
export const renderMermaidToPng = async (mermaidText) => {
|
|
50
|
+
const svg = renderMermaidSvg(mermaidText);
|
|
51
|
+
const { Resvg, initWasm } = await import('@resvg/resvg-wasm');
|
|
52
|
+
const { readFile: rf } = await import('node:fs/promises');
|
|
53
|
+
const { createRequire: cr } = await import('node:module');
|
|
54
|
+
const wasmPath = cr(import.meta.url).resolve('@resvg/resvg-wasm/index_bg.wasm');
|
|
55
|
+
try {
|
|
56
|
+
await initWasm(await rf(wasmPath));
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// WASM may already be initialized — ignore
|
|
60
|
+
}
|
|
61
|
+
const resvg = new Resvg(svg);
|
|
62
|
+
const pngData = resvg.render();
|
|
63
|
+
const pngBuffer = pngData.asPng();
|
|
64
|
+
const dir = await mkdtemp(join(tmpdir(), 'vlt-mermaid-'));
|
|
65
|
+
const outputFile = join(dir, 'graph.png');
|
|
66
|
+
await writeFile(outputFile, pngBuffer);
|
|
67
|
+
return outputFile;
|
|
68
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { RegistryCandidate } from './select-registry.ts';
|
|
2
|
+
import type { LoadedConfig } from './config/index.ts';
|
|
3
|
+
/**
|
|
4
|
+
* There is no default registry. This is the single message used
|
|
5
|
+
* everywhere a registry is required but missing.
|
|
6
|
+
*/
|
|
7
|
+
export declare const missingRegistryError: () => Error;
|
|
8
|
+
/**
|
|
9
|
+
* Multiple registries are configured and none was selected. Used in
|
|
10
|
+
* non-interactive contexts where we cannot prompt and there is no
|
|
11
|
+
* `default-registry-alias` to fall back to.
|
|
12
|
+
*/
|
|
13
|
+
export declare const ambiguousRegistryError: (candidates: RegistryCandidate[]) => Error;
|
|
14
|
+
/**
|
|
15
|
+
* Resolve a named registry alias to its URL, throwing an `ECONFIG`
|
|
16
|
+
* error (listing the known aliases) when the alias is not configured.
|
|
17
|
+
*/
|
|
18
|
+
export declare const resolveRegistryAlias: (conf: LoadedConfig, alias: string) => string;
|
|
19
|
+
/**
|
|
20
|
+
* Whether the current config provides a registry a `needsRegistry`
|
|
21
|
+
* command could act against without prompting for setup. True when an
|
|
22
|
+
* explicit `--registry` URL is set or the user has configured at least
|
|
23
|
+
* one non-default registry alias. Kept consistent with
|
|
24
|
+
* {@link resolveRegistry} so the pre-command gate never rejects a config
|
|
25
|
+
* the resolver would otherwise accept or prompt for.
|
|
26
|
+
*/
|
|
27
|
+
export declare const hasConfiguredRegistry: (conf: LoadedConfig) => boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Synchronous, non-interactive registry resolution used by
|
|
30
|
+
* programmatic callers. Precedence: explicit alias > `--registry`
|
|
31
|
+
* scalar > single configured alias > `default-registry-alias`. Throws
|
|
32
|
+
* when nothing is configured or the choice is ambiguous.
|
|
33
|
+
*/
|
|
34
|
+
export declare const requireRegistry: (conf: LoadedConfig, alias?: string) => string;
|
|
35
|
+
/**
|
|
36
|
+
* Resolve the registry a command should act against.
|
|
37
|
+
*
|
|
38
|
+
* Precedence: explicit `alias` (from `vlt registry <alias> <cmd>`) >
|
|
39
|
+
* `--registry` URL scalar > the single configured alias. When multiple
|
|
40
|
+
* aliases are configured and none was chosen, prompt interactively on a
|
|
41
|
+
* TTY, otherwise fall back to `default-registry-alias`, else error.
|
|
42
|
+
*/
|
|
43
|
+
export declare const resolveRegistry: (conf: LoadedConfig, { alias, interactive, input, output, }?: {
|
|
44
|
+
alias?: string;
|
|
45
|
+
interactive?: boolean;
|
|
46
|
+
input?: NodeJS.ReadableStream;
|
|
47
|
+
output?: NodeJS.WritableStream;
|
|
48
|
+
}) => Promise<string>;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { error } from '@vltpkg/error-cause';
|
|
2
|
+
import { defaultRegistries } from '@vltpkg/spec';
|
|
3
|
+
import { selectRegistry } from "./select-registry.js";
|
|
4
|
+
/**
|
|
5
|
+
* There is no default registry. This is the single message used
|
|
6
|
+
* everywhere a registry is required but missing.
|
|
7
|
+
*/
|
|
8
|
+
export const missingRegistryError = () => error([
|
|
9
|
+
'Missing registry configuration.',
|
|
10
|
+
'',
|
|
11
|
+
'vlt has no default registry. Run `vlt setup` to get configured.',
|
|
12
|
+
'',
|
|
13
|
+
'See https://docs.vlt.sh/cli for other ways to set a registry.',
|
|
14
|
+
].join('\n'), { code: 'ECONFIG' });
|
|
15
|
+
/**
|
|
16
|
+
* Multiple registries are configured and none was selected. Used in
|
|
17
|
+
* non-interactive contexts where we cannot prompt and there is no
|
|
18
|
+
* `default-registry-alias` to fall back to.
|
|
19
|
+
*/
|
|
20
|
+
export const ambiguousRegistryError = (candidates) => error([
|
|
21
|
+
'Multiple registries are configured; specify which one to use.',
|
|
22
|
+
'',
|
|
23
|
+
'Run `vlt registry <alias> <command>` with one of:',
|
|
24
|
+
...candidates.map(c => ` ${c.alias} -> ${c.url}`),
|
|
25
|
+
].join('\n'), {
|
|
26
|
+
code: 'ECONFIG',
|
|
27
|
+
validOptions: candidates.map(c => c.alias),
|
|
28
|
+
});
|
|
29
|
+
/**
|
|
30
|
+
* Resolve a named registry alias to its URL, throwing an `ECONFIG`
|
|
31
|
+
* error (listing the known aliases) when the alias is not configured.
|
|
32
|
+
*/
|
|
33
|
+
export const resolveRegistryAlias = (conf, alias) => {
|
|
34
|
+
const url = conf.options.registries[alias];
|
|
35
|
+
if (!url) {
|
|
36
|
+
throw error(`Unknown registry alias: ${alias}`, {
|
|
37
|
+
code: 'ECONFIG',
|
|
38
|
+
found: alias,
|
|
39
|
+
validOptions: Object.keys(conf.options.registries),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return url;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* The registries the user has actually configured, when no explicit
|
|
46
|
+
* `--registry` URL is set. Order follows the `registries` config (which
|
|
47
|
+
* preserves insertion order).
|
|
48
|
+
*
|
|
49
|
+
* Built-in defaults (eg `gh`) are excluded so they don't implicitly
|
|
50
|
+
* satisfy "a registry is configured" for account/auth commands. A
|
|
51
|
+
* built-in alias the user has overridden to a different URL counts as
|
|
52
|
+
* configured. Built-in aliases can still be targeted explicitly via
|
|
53
|
+
* `vlt registry <alias> <cmd>` (which resolves through
|
|
54
|
+
* {@link resolveRegistryAlias}).
|
|
55
|
+
*/
|
|
56
|
+
const gatherCandidates = (conf) => {
|
|
57
|
+
const builtins = defaultRegistries;
|
|
58
|
+
return Object.entries(conf.options.registries)
|
|
59
|
+
.filter(([alias, url]) => builtins[alias] !== url)
|
|
60
|
+
.map(([alias, url]) => ({ alias, url }));
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Whether the current config provides a registry a `needsRegistry`
|
|
64
|
+
* command could act against without prompting for setup. True when an
|
|
65
|
+
* explicit `--registry` URL is set or the user has configured at least
|
|
66
|
+
* one non-default registry alias. Kept consistent with
|
|
67
|
+
* {@link resolveRegistry} so the pre-command gate never rejects a config
|
|
68
|
+
* the resolver would otherwise accept or prompt for.
|
|
69
|
+
*/
|
|
70
|
+
export const hasConfiguredRegistry = (conf) => !!conf.options.registry || gatherCandidates(conf).length > 0;
|
|
71
|
+
/**
|
|
72
|
+
* Synchronous, non-interactive registry resolution used by
|
|
73
|
+
* programmatic callers. Precedence: explicit alias > `--registry`
|
|
74
|
+
* scalar > single configured alias > `default-registry-alias`. Throws
|
|
75
|
+
* when nothing is configured or the choice is ambiguous.
|
|
76
|
+
*/
|
|
77
|
+
export const requireRegistry = (conf, alias) => {
|
|
78
|
+
if (alias !== undefined)
|
|
79
|
+
return resolveRegistryAlias(conf, alias);
|
|
80
|
+
const { registry } = conf.options;
|
|
81
|
+
if (registry)
|
|
82
|
+
return registry;
|
|
83
|
+
const candidates = gatherCandidates(conf);
|
|
84
|
+
const [first, second] = candidates;
|
|
85
|
+
if (!first)
|
|
86
|
+
throw missingRegistryError();
|
|
87
|
+
if (!second)
|
|
88
|
+
return first.url;
|
|
89
|
+
const defaultUrl = conf.options.registries[conf.options['default-registry-alias']];
|
|
90
|
+
if (defaultUrl)
|
|
91
|
+
return defaultUrl;
|
|
92
|
+
throw ambiguousRegistryError(candidates);
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Resolve the registry a command should act against.
|
|
96
|
+
*
|
|
97
|
+
* Precedence: explicit `alias` (from `vlt registry <alias> <cmd>`) >
|
|
98
|
+
* `--registry` URL scalar > the single configured alias. When multiple
|
|
99
|
+
* aliases are configured and none was chosen, prompt interactively on a
|
|
100
|
+
* TTY, otherwise fall back to `default-registry-alias`, else error.
|
|
101
|
+
*/
|
|
102
|
+
export const resolveRegistry = async (conf, { alias, interactive = process.stdin.isTTY, input, output, } = {}) => {
|
|
103
|
+
if (alias !== undefined)
|
|
104
|
+
return resolveRegistryAlias(conf, alias);
|
|
105
|
+
const { registry } = conf.options;
|
|
106
|
+
if (registry)
|
|
107
|
+
return registry;
|
|
108
|
+
const candidates = gatherCandidates(conf);
|
|
109
|
+
const [first, second] = candidates;
|
|
110
|
+
if (!first)
|
|
111
|
+
throw missingRegistryError();
|
|
112
|
+
if (!second)
|
|
113
|
+
return first.url;
|
|
114
|
+
const defaultAlias = conf.options['default-registry-alias'];
|
|
115
|
+
if (interactive) {
|
|
116
|
+
return selectRegistry(candidates, { defaultAlias, input, output });
|
|
117
|
+
}
|
|
118
|
+
const defaultUrl = conf.options.registries[defaultAlias];
|
|
119
|
+
if (defaultUrl)
|
|
120
|
+
return defaultUrl;
|
|
121
|
+
throw ambiguousRegistryError(candidates);
|
|
122
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** A configured registry the user can act against. */
|
|
2
|
+
export type RegistryCandidate = {
|
|
3
|
+
/** the configured alias name (a key in `registries`) */
|
|
4
|
+
alias: string;
|
|
5
|
+
/** the resolved registry URL */
|
|
6
|
+
url: string;
|
|
7
|
+
};
|
|
8
|
+
export type SelectStreams = {
|
|
9
|
+
input: NodeJS.ReadableStream;
|
|
10
|
+
output: NodeJS.WritableStream;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Interactively prompt the user to choose one of the configured
|
|
14
|
+
* registries. `defaultAlias` (when present in `candidates`) is
|
|
15
|
+
* pre-selected so pressing enter accepts it.
|
|
16
|
+
*
|
|
17
|
+
* Streams are injectable so tests can drive the prompt deterministically.
|
|
18
|
+
*/
|
|
19
|
+
export declare const selectRegistry: (candidates: RegistryCandidate[], { defaultAlias, input, output, }?: {
|
|
20
|
+
defaultAlias?: string;
|
|
21
|
+
input?: NodeJS.ReadableStream;
|
|
22
|
+
output?: NodeJS.WritableStream;
|
|
23
|
+
}) => Promise<string>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { error } from '@vltpkg/error-cause';
|
|
2
|
+
import { createInterface } from 'node:readline/promises';
|
|
3
|
+
/**
|
|
4
|
+
* Interactively prompt the user to choose one of the configured
|
|
5
|
+
* registries. `defaultAlias` (when present in `candidates`) is
|
|
6
|
+
* pre-selected so pressing enter accepts it.
|
|
7
|
+
*
|
|
8
|
+
* Streams are injectable so tests can drive the prompt deterministically.
|
|
9
|
+
*/
|
|
10
|
+
export const selectRegistry = async (candidates, { defaultAlias, input = process.stdin, output = process.stdout, } = {}) => {
|
|
11
|
+
const defaultIndex = Math.max(candidates.findIndex(c => c.alias === defaultAlias), 0);
|
|
12
|
+
const fallback = candidates[defaultIndex] ?? candidates[0];
|
|
13
|
+
if (!fallback) {
|
|
14
|
+
throw error('No registries to select from', { code: 'ECONFIG' });
|
|
15
|
+
}
|
|
16
|
+
const rl = createInterface({ input, output });
|
|
17
|
+
try {
|
|
18
|
+
output.write('Multiple registries are configured. Select one:\n');
|
|
19
|
+
for (const [i, c] of candidates.entries()) {
|
|
20
|
+
const marker = i === defaultIndex ? ' (default)' : '';
|
|
21
|
+
output.write(` ${i + 1}) ${c.alias} -> ${c.url}${marker}\n`);
|
|
22
|
+
}
|
|
23
|
+
const answer = (await rl.question(`Registry [${defaultIndex + 1}]: `)).trim();
|
|
24
|
+
if (!answer)
|
|
25
|
+
return fallback.url;
|
|
26
|
+
const choice = Number(answer);
|
|
27
|
+
const picked = candidates[choice - 1];
|
|
28
|
+
if (!Number.isInteger(choice) || !picked) {
|
|
29
|
+
throw error('Invalid registry selection', {
|
|
30
|
+
found: answer,
|
|
31
|
+
validOptions: candidates.map((_, i) => String(i + 1)),
|
|
32
|
+
code: 'EUSAGE',
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return picked.url;
|
|
36
|
+
}
|
|
37
|
+
finally {
|
|
38
|
+
rl.close();
|
|
39
|
+
}
|
|
40
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anonymized telemetry for the vlt CLI.
|
|
3
|
+
*
|
|
4
|
+
* - Sends anonymous, non-PII events to PostHog.
|
|
5
|
+
* - Generates a random UUID on first run, stored in XDG data dir.
|
|
6
|
+
* - Respects opt-out via `DO_NOT_TRACK=1`, `VLT_TELEMETRY=0`,
|
|
7
|
+
* or the `--telemetry=false` config flag.
|
|
8
|
+
* - Flush is awaited with a timeout cap so it never blocks CLI exit for long.
|
|
9
|
+
* - Fails silently on any network or runtime error.
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Check whether telemetry is disabled via environment variables.
|
|
14
|
+
*
|
|
15
|
+
* - `DO_NOT_TRACK=1` — https://consoledonottrack.com/
|
|
16
|
+
* - `VLT_TELEMETRY=0`
|
|
17
|
+
*/
|
|
18
|
+
export declare const isOptedOut: () => boolean;
|
|
19
|
+
export interface CommandEvent {
|
|
20
|
+
command: string;
|
|
21
|
+
duration_ms: number;
|
|
22
|
+
success: boolean;
|
|
23
|
+
node_version: string;
|
|
24
|
+
vlt_version: string;
|
|
25
|
+
os: string;
|
|
26
|
+
arch: string;
|
|
27
|
+
ci: boolean;
|
|
28
|
+
}
|
|
29
|
+
export interface InstallEvent {
|
|
30
|
+
dependency_count: number;
|
|
31
|
+
duration_ms: number;
|
|
32
|
+
}
|
|
33
|
+
export interface ErrorEvent {
|
|
34
|
+
command: string;
|
|
35
|
+
error_code?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Capture a `cli_command` event.
|
|
39
|
+
*/
|
|
40
|
+
export declare const trackCommand: (ev: CommandEvent, telemetryFlag?: boolean) => void;
|
|
41
|
+
/**
|
|
42
|
+
* Capture a `cli_install` event.
|
|
43
|
+
*/
|
|
44
|
+
export declare const trackInstall: (ev: InstallEvent, telemetryFlag?: boolean) => void;
|
|
45
|
+
/**
|
|
46
|
+
* Capture a `cli_error` event.
|
|
47
|
+
*/
|
|
48
|
+
export declare const trackError: (ev: ErrorEvent, telemetryFlag?: boolean) => void;
|
|
49
|
+
/**
|
|
50
|
+
* Flush pending events. Returns a promise that resolves once flushing
|
|
51
|
+
* completes **or** when `SHUTDOWN_TIMEOUT_MS` elapses — whichever
|
|
52
|
+
* comes first. Never rejects.
|
|
53
|
+
*
|
|
54
|
+
* The safety-net timer is unreffed so it cannot keep the process alive
|
|
55
|
+
* on its own — if the caller does not `await` this, Node will still
|
|
56
|
+
* exit promptly once all other handles are drained.
|
|
57
|
+
*/
|
|
58
|
+
export declare const flush: () => Promise<void>;
|