@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,15 @@
|
|
|
1
|
+
import { SecurityArchive } from '@vltpkg/security-archive';
|
|
2
|
+
import type { EdgeLike, NodeLike } from '@vltpkg/types';
|
|
3
|
+
import type { LoadedConfig } from './config/index.ts';
|
|
4
|
+
export type HostContextsMapResult = {
|
|
5
|
+
initialEdges: EdgeLike[];
|
|
6
|
+
initialNodes: NodeLike[];
|
|
7
|
+
edges: EdgeLike[];
|
|
8
|
+
nodes: NodeLike[];
|
|
9
|
+
securityArchive: SecurityArchive;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Creates a Map of host context functions that can be used by the :host
|
|
13
|
+
* pseudo selector to dynamically load graphs from different sources.
|
|
14
|
+
*/
|
|
15
|
+
export declare const createHostContextsMap: (conf: LoadedConfig) => Promise<Map<string, () => Promise<HostContextsMapResult>>>;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { homedir } from 'node:os';
|
|
2
|
+
import { parse, posix } from 'node:path';
|
|
3
|
+
import { readProjectFolders } from "./read-project-folders.js";
|
|
4
|
+
import { reloadConfig } from "./reload-config.js";
|
|
5
|
+
import { actual, createVirtualRoot } from '@vltpkg/graph';
|
|
6
|
+
import { SecurityArchive } from '@vltpkg/security-archive';
|
|
7
|
+
import { error } from '@vltpkg/error-cause';
|
|
8
|
+
// In restricted environments (like locked-down Codespaces),
|
|
9
|
+
// homedir() might fail. Fall back to parent directory.
|
|
10
|
+
let foundHome;
|
|
11
|
+
try {
|
|
12
|
+
foundHome = posix.format(parse(homedir()));
|
|
13
|
+
/* c8 ignore next 3 */
|
|
14
|
+
}
|
|
15
|
+
catch { }
|
|
16
|
+
const home = foundHome ?? posix.dirname(posix.format(parse(process.cwd())));
|
|
17
|
+
const isVltInstalled = (folder) => !!folder.resolve('node_modules/.vlt').lstatSync()?.isDirectory() ||
|
|
18
|
+
!!folder
|
|
19
|
+
.resolve('node_modules/.vlt-lock.json')
|
|
20
|
+
.lstatSync()
|
|
21
|
+
?.isFile();
|
|
22
|
+
/**
|
|
23
|
+
* Generates possible project keys for a given folder.
|
|
24
|
+
*/
|
|
25
|
+
const getPossibleProjectKeys = (folder, scurry) => {
|
|
26
|
+
const relativePath = posix.relative(scurry.cwd.fullpathPosix(), folder.fullpathPosix());
|
|
27
|
+
const absolutePath = folder.fullpathPosix();
|
|
28
|
+
const homeRelativePath = posix.relative(scurry.resolvePosix(home), folder.fullpathPosix());
|
|
29
|
+
const dotRelativeKey = relativePath === '' ? 'file:.' : `file:./${relativePath}`;
|
|
30
|
+
const relativeKey = `file:${relativePath}`;
|
|
31
|
+
const absoluteKey = `file:${absolutePath}`;
|
|
32
|
+
const homeRelativeKey = `file:~/${homeRelativePath}`;
|
|
33
|
+
const keys = [
|
|
34
|
+
relativeKey,
|
|
35
|
+
dotRelativeKey,
|
|
36
|
+
absoluteKey,
|
|
37
|
+
homeRelativeKey,
|
|
38
|
+
`${relativeKey}/`,
|
|
39
|
+
`${dotRelativeKey}/`,
|
|
40
|
+
`${absoluteKey}/`,
|
|
41
|
+
`${homeRelativeKey}/`,
|
|
42
|
+
];
|
|
43
|
+
return new Set(keys);
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Creates a Map of host context functions that can be used by the :host
|
|
47
|
+
* pseudo selector to dynamically load graphs from different sources.
|
|
48
|
+
*/
|
|
49
|
+
export const createHostContextsMap = async (conf) => {
|
|
50
|
+
const hostContexts = new Map();
|
|
51
|
+
// Read all project folders from the configured paths
|
|
52
|
+
const { scurry } = conf.options;
|
|
53
|
+
const projectFolders = await readProjectFolders({
|
|
54
|
+
scurry,
|
|
55
|
+
userDefinedProjectPaths: conf.options['dashboard-root'] ?? [],
|
|
56
|
+
});
|
|
57
|
+
for (const folder of projectFolders) {
|
|
58
|
+
const retrieveProjectGraph = async () => {
|
|
59
|
+
const initialEdges = [];
|
|
60
|
+
const initialNodes = [];
|
|
61
|
+
const config = await reloadConfig(folder.fullpath());
|
|
62
|
+
// load each individual graph
|
|
63
|
+
const graph = actual.load({
|
|
64
|
+
...config.options,
|
|
65
|
+
projectRoot: folder.fullpath(),
|
|
66
|
+
skipLoadingNodesOnModifiersChange: false,
|
|
67
|
+
});
|
|
68
|
+
initialEdges.push(...graph.edges);
|
|
69
|
+
initialNodes.push(...graph.nodes.values());
|
|
70
|
+
// Initialize security archive with all loaded nodes
|
|
71
|
+
const securityArchive = await SecurityArchive.start({
|
|
72
|
+
nodes: initialNodes,
|
|
73
|
+
});
|
|
74
|
+
return {
|
|
75
|
+
initialEdges,
|
|
76
|
+
initialNodes,
|
|
77
|
+
edges: [],
|
|
78
|
+
nodes: [graph.mainImporter],
|
|
79
|
+
securityArchive,
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
// add multiple keys for each project folder
|
|
83
|
+
for (const path of getPossibleProjectKeys(folder, scurry)) {
|
|
84
|
+
if (!hostContexts.has(path)) {
|
|
85
|
+
hostContexts.set(path, retrieveProjectGraph);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Define local context - loads graphs from all projects in user's project paths
|
|
90
|
+
hostContexts.set('local', async () => {
|
|
91
|
+
// Load graphs from each project folder
|
|
92
|
+
const initialEdges = [];
|
|
93
|
+
const initialNodes = [];
|
|
94
|
+
const mainImporters = [];
|
|
95
|
+
for (const folder of projectFolders) {
|
|
96
|
+
try {
|
|
97
|
+
const config = await reloadConfig(folder.fullpath());
|
|
98
|
+
// only include projects that are vlt-installed
|
|
99
|
+
if (!isVltInstalled(folder)) {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
// load each individual graph
|
|
103
|
+
const graph = actual.load({
|
|
104
|
+
...config.options,
|
|
105
|
+
projectRoot: folder.fullpath(),
|
|
106
|
+
skipLoadingNodesOnModifiersChange: false,
|
|
107
|
+
});
|
|
108
|
+
initialEdges.push(...graph.edges);
|
|
109
|
+
initialNodes.push(...graph.nodes.values());
|
|
110
|
+
mainImporters.push(graph.mainImporter);
|
|
111
|
+
}
|
|
112
|
+
catch (_error) {
|
|
113
|
+
// Skip projects that fail to load
|
|
114
|
+
// This might happen for projects without proper package.json
|
|
115
|
+
// or other loading issues
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// Initialize security archive with all loaded nodes
|
|
120
|
+
const securityArchive = await SecurityArchive.start({
|
|
121
|
+
nodes: initialNodes,
|
|
122
|
+
});
|
|
123
|
+
const virtualRoot = createVirtualRoot('local', conf.options, mainImporters);
|
|
124
|
+
if (!virtualRoot) {
|
|
125
|
+
throw error('Failed to create virtual root for local context');
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
initialEdges,
|
|
129
|
+
initialNodes,
|
|
130
|
+
edges: [],
|
|
131
|
+
nodes: [virtualRoot],
|
|
132
|
+
securityArchive,
|
|
133
|
+
};
|
|
134
|
+
});
|
|
135
|
+
return hostContexts;
|
|
136
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { error } from '@vltpkg/error-cause';
|
|
2
|
+
export const readPassword = async (prompt, { stdin, stdout } = process) => {
|
|
3
|
+
let input = '';
|
|
4
|
+
stdout.write(prompt);
|
|
5
|
+
stdin.setRawMode(true);
|
|
6
|
+
await new Promise((res, rej) => {
|
|
7
|
+
stdin.on('data', (c) => {
|
|
8
|
+
// backspace
|
|
9
|
+
if (c.length === 1 && c[0] === 0x7f) {
|
|
10
|
+
input = input.substring(0, input.length - 1);
|
|
11
|
+
stdout.write('\x1b[1D \x1b[1D');
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
input += String(c);
|
|
15
|
+
if (/\r|\n|\x04|\x03/.test(input)) {
|
|
16
|
+
input = input.replace(/(\r|\n|\x04|\x03)/g, '');
|
|
17
|
+
stdin.setRawMode(false);
|
|
18
|
+
stdin.pause();
|
|
19
|
+
// x03 === ^C
|
|
20
|
+
if (c[c.length - 1] === 3) {
|
|
21
|
+
rej(error('canceled', { signal: 'SIGINT' }));
|
|
22
|
+
}
|
|
23
|
+
else
|
|
24
|
+
res();
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
stdout.write('*'.repeat(c.length));
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
return input;
|
|
32
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { PathBase, PathScurry } from 'path-scurry';
|
|
2
|
+
type ProjectFolderOptions = {
|
|
3
|
+
path?: string;
|
|
4
|
+
scurry: PathScurry;
|
|
5
|
+
userDefinedProjectPaths: string[];
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Retrieves folders from a given directory, if that directory is
|
|
9
|
+
* recognized to be the current cli project root folder then we
|
|
10
|
+
* proceed to read its siblings.
|
|
11
|
+
*
|
|
12
|
+
* Traverses nested directory recursively until project folders can
|
|
13
|
+
* be find, always stopping at the first level where a package.json
|
|
14
|
+
* is present.
|
|
15
|
+
*/
|
|
16
|
+
export declare const readProjectFolders: ({ path, scurry, userDefinedProjectPaths, }: ProjectFolderOptions, maxDepth?: number) => Promise<PathBase[]>;
|
|
17
|
+
export {};
|
|
@@ -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,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
|
+
};
|
package/dist/view.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { LoadedConfig } from './config/index.ts';
|
|
2
|
+
export type ViewOptions = {
|
|
3
|
+
colors?: boolean;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* The base class for all View classes
|
|
7
|
+
*
|
|
8
|
+
* Do not override the constructor, just provide start/done/error methods.
|
|
9
|
+
*
|
|
10
|
+
* These classes should be used as one or more of the exported views for
|
|
11
|
+
* commands that need to know when the processing starts, handle errors in
|
|
12
|
+
* various ways, etc. Fancy stuff.
|
|
13
|
+
*
|
|
14
|
+
* For simple use cases, usually better to create a {@link ViewFn} instead.
|
|
15
|
+
*/
|
|
16
|
+
export declare class ViewClass<T = unknown> {
|
|
17
|
+
options: ViewOptions;
|
|
18
|
+
config: LoadedConfig;
|
|
19
|
+
constructor(options: ViewOptions, config: LoadedConfig);
|
|
20
|
+
start(): void;
|
|
21
|
+
done(_result: T, _opts: {
|
|
22
|
+
time: number;
|
|
23
|
+
}): Promise<unknown>;
|
|
24
|
+
error(_err: unknown): void;
|
|
25
|
+
}
|
|
26
|
+
export type ViewFn<T = unknown> = (result: T, options: ViewOptions, conf: LoadedConfig) => unknown;
|
|
27
|
+
export type View<T = unknown> = ViewFn<T> | typeof ViewClass<T>;
|
|
28
|
+
export declare const isViewClass: <T = unknown>(view: View<T>) => view is typeof ViewClass<T>;
|
|
29
|
+
export type Views<T = unknown> = View<T> | Record<string, View<T>>;
|
package/dist/view.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The base class for all View classes
|
|
3
|
+
*
|
|
4
|
+
* Do not override the constructor, just provide start/done/error methods.
|
|
5
|
+
*
|
|
6
|
+
* These classes should be used as one or more of the exported views for
|
|
7
|
+
* commands that need to know when the processing starts, handle errors in
|
|
8
|
+
* various ways, etc. Fancy stuff.
|
|
9
|
+
*
|
|
10
|
+
* For simple use cases, usually better to create a {@link ViewFn} instead.
|
|
11
|
+
*/
|
|
12
|
+
export class ViewClass {
|
|
13
|
+
options;
|
|
14
|
+
config;
|
|
15
|
+
constructor(options, config) {
|
|
16
|
+
this.options = options;
|
|
17
|
+
this.config = config;
|
|
18
|
+
}
|
|
19
|
+
// TODO: maybe have start() return a flag to say "i got this, do not
|
|
20
|
+
// run the command", for example to just open a web browser
|
|
21
|
+
// to the page relevant to a given thing, rather than computing it twice
|
|
22
|
+
start() { }
|
|
23
|
+
async done(_result, _opts) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
error(_err) { }
|
|
27
|
+
}
|
|
28
|
+
export const isViewClass = (view) => typeof view === 'function' &&
|
|
29
|
+
'prototype' in view &&
|
|
30
|
+
view.prototype instanceof ViewClass;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vltpkg/cli-sdk",
|
|
3
3
|
"description": "The source for the vlt CLI",
|
|
4
|
-
"version": "1.0.0-rc.
|
|
4
|
+
"version": "1.0.0-rc.24",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/vltpkg/vltpkg.git",
|
|
@@ -13,30 +13,30 @@
|
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"@resvg/resvg-wasm": "^2.6.2",
|
|
16
|
-
"@vltpkg/config": "1.0.0-rc.
|
|
17
|
-
"@vltpkg/dep-id": "1.0.0-rc.
|
|
18
|
-
"@vltpkg/dot-prop": "1.0.0-rc.
|
|
19
|
-
"@vltpkg/error-cause": "1.0.0-rc.
|
|
20
|
-
"@vltpkg/git": "1.0.0-rc.
|
|
21
|
-
"@vltpkg/graph": "1.0.0-rc.
|
|
22
|
-
"@vltpkg/graph-run": "1.0.0-rc.
|
|
23
|
-
"@vltpkg/init": "1.0.0-rc.
|
|
24
|
-
"@vltpkg/output": "1.0.0-rc.
|
|
25
|
-
"@vltpkg/package-info": "1.0.0-rc.
|
|
26
|
-
"@vltpkg/package-json": "1.0.0-rc.
|
|
27
|
-
"@vltpkg/promise-spawn": "1.0.0-rc.
|
|
28
|
-
"@vltpkg/query": "1.0.0-rc.
|
|
29
|
-
"@vltpkg/registry-client": "1.0.0-rc.
|
|
30
|
-
"@vltpkg/rollback-remove": "1.0.0-rc.
|
|
31
|
-
"@vltpkg/run": "1.0.0-rc.
|
|
32
|
-
"@vltpkg/security-archive": "1.0.0-rc.
|
|
33
|
-
"@vltpkg/spec": "1.0.0-rc.
|
|
34
|
-
"@vltpkg/types": "1.0.0-rc.
|
|
35
|
-
"@vltpkg/url-open": "1.0.0-rc.
|
|
36
|
-
"@vltpkg/vlt-json": "1.0.0-rc.
|
|
37
|
-
"@vltpkg/vlx": "1.0.0-rc.
|
|
38
|
-
"@vltpkg/workspaces": "1.0.0-rc.
|
|
39
|
-
"@vltpkg/xdg": "1.0.0-rc.
|
|
16
|
+
"@vltpkg/config": "1.0.0-rc.24",
|
|
17
|
+
"@vltpkg/dep-id": "1.0.0-rc.24",
|
|
18
|
+
"@vltpkg/dot-prop": "1.0.0-rc.24",
|
|
19
|
+
"@vltpkg/error-cause": "1.0.0-rc.24",
|
|
20
|
+
"@vltpkg/git": "1.0.0-rc.24",
|
|
21
|
+
"@vltpkg/graph": "1.0.0-rc.24",
|
|
22
|
+
"@vltpkg/graph-run": "1.0.0-rc.24",
|
|
23
|
+
"@vltpkg/init": "1.0.0-rc.24",
|
|
24
|
+
"@vltpkg/output": "1.0.0-rc.24",
|
|
25
|
+
"@vltpkg/package-info": "1.0.0-rc.24",
|
|
26
|
+
"@vltpkg/package-json": "1.0.0-rc.24",
|
|
27
|
+
"@vltpkg/promise-spawn": "1.0.0-rc.24",
|
|
28
|
+
"@vltpkg/query": "1.0.0-rc.24",
|
|
29
|
+
"@vltpkg/registry-client": "1.0.0-rc.24",
|
|
30
|
+
"@vltpkg/rollback-remove": "1.0.0-rc.24",
|
|
31
|
+
"@vltpkg/run": "1.0.0-rc.24",
|
|
32
|
+
"@vltpkg/security-archive": "1.0.0-rc.24",
|
|
33
|
+
"@vltpkg/spec": "1.0.0-rc.24",
|
|
34
|
+
"@vltpkg/types": "1.0.0-rc.24",
|
|
35
|
+
"@vltpkg/url-open": "1.0.0-rc.24",
|
|
36
|
+
"@vltpkg/vlt-json": "1.0.0-rc.24",
|
|
37
|
+
"@vltpkg/vlx": "1.0.0-rc.24",
|
|
38
|
+
"@vltpkg/workspaces": "1.0.0-rc.24",
|
|
39
|
+
"@vltpkg/xdg": "1.0.0-rc.24",
|
|
40
40
|
"ansi-to-pre": "^1.0.6",
|
|
41
41
|
"beautiful-mermaid": "^1.1.3",
|
|
42
42
|
"chalk": "^5.6.2",
|
|
@@ -87,28 +87,28 @@
|
|
|
87
87
|
"extends": "../../tap-config.yaml"
|
|
88
88
|
},
|
|
89
89
|
"prettier": "../../.prettierrc.js",
|
|
90
|
-
"module": "./
|
|
90
|
+
"module": "./dist/index.js",
|
|
91
91
|
"type": "module",
|
|
92
92
|
"exports": {
|
|
93
93
|
"./package.json": "./package.json",
|
|
94
94
|
".": {
|
|
95
95
|
"import": {
|
|
96
|
-
"default": "./
|
|
96
|
+
"default": "./dist/index.js"
|
|
97
97
|
}
|
|
98
98
|
},
|
|
99
99
|
"./config": {
|
|
100
100
|
"import": {
|
|
101
|
-
"default": "./
|
|
101
|
+
"default": "./dist/config/index.js"
|
|
102
102
|
}
|
|
103
103
|
},
|
|
104
104
|
"./definition": {
|
|
105
105
|
"import": {
|
|
106
|
-
"default": "./
|
|
106
|
+
"default": "./dist/config/definition.js"
|
|
107
107
|
}
|
|
108
108
|
},
|
|
109
109
|
"./view": {
|
|
110
110
|
"import": {
|
|
111
|
-
"default": "./
|
|
111
|
+
"default": "./dist/view.js"
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
},
|