@vltpkg/cli-sdk 1.4.0 → 1.6.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/allow-skills.d.ts +36 -0
- package/dist/allow-skills.js +49 -0
- package/dist/commands/build.d.ts +15 -4
- package/dist/commands/build.js +50 -12
- package/dist/commands/ci.d.ts +2 -2
- package/dist/commands/ci.js +10 -2
- package/dist/commands/create.d.ts +2 -1
- package/dist/commands/create.js +2 -3
- package/dist/commands/exec.d.ts +2 -1
- package/dist/commands/exec.js +2 -3
- package/dist/commands/init.js +4 -3
- package/dist/commands/install/reporter.d.ts +1 -1
- package/dist/commands/install/reporter.js +91 -5
- package/dist/commands/install.d.ts +50 -4
- package/dist/commands/install.js +107 -25
- package/dist/commands/list.js +8 -2
- package/dist/commands/publish.d.ts +0 -1
- package/dist/commands/publish.js +27 -16
- package/dist/commands/query.js +8 -2
- package/dist/commands/setup.d.ts +28 -2
- package/dist/commands/setup.js +185 -3
- package/dist/commands/skills.d.ts +56 -0
- package/dist/commands/skills.js +267 -0
- package/dist/commands/token.js +1 -1
- package/dist/commands/uninstall.d.ts +15 -4
- package/dist/commands/uninstall.js +32 -4
- package/dist/commands/unpublish.d.ts +0 -1
- package/dist/commands/unpublish.js +17 -4
- package/dist/commands/update.d.ts +13 -1
- package/dist/commands/update.js +18 -1
- package/dist/config/definition.d.ts +52 -0
- package/dist/config/definition.js +109 -1
- package/dist/config/index.d.ts +26 -3
- package/dist/config/index.js +149 -7
- package/dist/custom-help.js +4 -0
- package/dist/global-bin-dir.d.ts +37 -0
- package/dist/global-bin-dir.js +138 -0
- package/dist/global-project.d.ts +18 -0
- package/dist/global-project.js +67 -0
- package/dist/global-state.d.ts +24 -0
- package/dist/global-state.js +94 -0
- package/dist/global.d.ts +78 -0
- package/dist/global.js +409 -0
- package/dist/index.js +14 -3
- package/dist/install-receipt.d.ts +40 -0
- package/dist/install-receipt.js +69 -0
- package/dist/load-command.d.ts +2 -0
- package/dist/migrate-workspaces.d.ts +16 -0
- package/dist/migrate-workspaces.js +44 -0
- package/dist/output.js +13 -0
- package/dist/parse-add-remove-args.js +2 -14
- package/dist/print-err.js +4 -1
- package/dist/publish-config.d.ts +9 -0
- package/dist/publish-config.js +8 -0
- package/dist/query-auth.d.ts +3 -2
- package/dist/query-auth.js +6 -4
- package/dist/reload-config.js +2 -1
- package/dist/require-registry.d.ts +7 -0
- package/dist/require-registry.js +13 -1
- package/dist/self-update.d.ts +74 -0
- package/dist/self-update.js +401 -0
- package/dist/shell-setup/env.d.ts +9 -0
- package/dist/shell-setup/env.js +25 -0
- package/dist/shell-setup/index.d.ts +69 -0
- package/dist/shell-setup/index.js +213 -0
- package/dist/shell-setup/posix.d.ts +36 -0
- package/dist/shell-setup/posix.js +158 -0
- package/dist/shell-setup/windows.d.ts +39 -0
- package/dist/shell-setup/windows.js +151 -0
- package/dist/shell.d.ts +18 -0
- package/dist/shell.js +110 -0
- package/dist/skills-prompt.d.ts +28 -0
- package/dist/skills-prompt.js +78 -0
- package/package.json +30 -28
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { UnmatchedPattern, UnscannedSkills } from '@vltpkg/graph';
|
|
2
|
+
import type { WhichConfig } from '@vltpkg/vlt-json';
|
|
3
|
+
import type { LoadedConfig } from './config/index.ts';
|
|
4
|
+
/** An `allow-skills` query stored in a config file. */
|
|
5
|
+
export type StoredAllowSkills = {
|
|
6
|
+
query: string;
|
|
7
|
+
which: WhichConfig;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Outcome of saving `--allow-skills` after install/update. `stored`
|
|
11
|
+
* set: another query is stored and was kept.
|
|
12
|
+
*/
|
|
13
|
+
export type AllowSkillsSave = {
|
|
14
|
+
query: string;
|
|
15
|
+
stored?: StoredAllowSkills;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* The top-level `allow-skills` of the project vlt.json, else the user
|
|
19
|
+
* one. A project `null` or `''` drops the user's.
|
|
20
|
+
*/
|
|
21
|
+
export declare const storedAllowSkills: (conf: Pick<LoadedConfig, "layers">) => StoredAllowSkills | undefined;
|
|
22
|
+
/** The file's name in messages. */
|
|
23
|
+
export declare const configLabel: (which: WhichConfig) => string;
|
|
24
|
+
/**
|
|
25
|
+
* After a successful install/update: save an explicit `--allow-skills`
|
|
26
|
+
* to the project vlt.json, unless another query is stored.
|
|
27
|
+
*/
|
|
28
|
+
export declare const saveAllowSkills: (conf: LoadedConfig) => Promise<AllowSkillsSave | undefined>;
|
|
29
|
+
/** Warnings for `:skill()` patterns that matched nothing. */
|
|
30
|
+
export declare const unmatchedLines: (unmatched?: UnmatchedPattern[]) => string[];
|
|
31
|
+
/** Skills left out: their packages have no security data. */
|
|
32
|
+
export declare const unscannedLines: ({ unscanned, unscannedReason, }: UnscannedSkills) => string[];
|
|
33
|
+
/** `allow-skills` saved to a config file. */
|
|
34
|
+
export declare const savedLine: (query: string, which: WhichConfig) => string;
|
|
35
|
+
/** `--allow-skills` not saved: another query is stored. */
|
|
36
|
+
export declare const keptLine: (s: StoredAllowSkills) => string;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The top-level `allow-skills` of the project vlt.json, else the user
|
|
3
|
+
* one. A project `null` or `''` drops the user's.
|
|
4
|
+
*/
|
|
5
|
+
export const storedAllowSkills = (conf) => {
|
|
6
|
+
const { project, user } = conf.layers;
|
|
7
|
+
const p = project?.['allow-skills'];
|
|
8
|
+
if (p)
|
|
9
|
+
return { query: p, which: 'project' };
|
|
10
|
+
if (project && 'allow-skills' in project)
|
|
11
|
+
return undefined;
|
|
12
|
+
const u = user?.['allow-skills'];
|
|
13
|
+
return u ? { query: u, which: 'user' } : undefined;
|
|
14
|
+
};
|
|
15
|
+
/** The file's name in messages. */
|
|
16
|
+
export const configLabel = (which) => which === 'user' ? 'user vlt.json' : 'vlt.json';
|
|
17
|
+
/**
|
|
18
|
+
* After a successful install/update: save an explicit `--allow-skills`
|
|
19
|
+
* to the project vlt.json, unless another query is stored.
|
|
20
|
+
*/
|
|
21
|
+
export const saveAllowSkills = async (conf) => {
|
|
22
|
+
const query = conf.explicit['allow-skills'];
|
|
23
|
+
if (!query || query === ':not(*)')
|
|
24
|
+
return undefined;
|
|
25
|
+
const stored = storedAllowSkills(conf);
|
|
26
|
+
if (stored?.query === query)
|
|
27
|
+
return undefined;
|
|
28
|
+
if (stored)
|
|
29
|
+
return { query, stored };
|
|
30
|
+
await conf.addConfigToFile('project', { 'allow-skills': query });
|
|
31
|
+
return { query };
|
|
32
|
+
};
|
|
33
|
+
/** Warnings for `:skill()` patterns that matched nothing. */
|
|
34
|
+
export const unmatchedLines = (unmatched = []) => unmatched.map(({ pattern, skills }) => `⚠️ No skill matches "${pattern}"; ${!skills ? 'no installed package matches its selector'
|
|
35
|
+
: skills.length ?
|
|
36
|
+
`the selected packages ship: ${skills.join(', ')}`
|
|
37
|
+
: 'the selected packages ship no skills'}`);
|
|
38
|
+
/** Skills left out: their packages have no security data. */
|
|
39
|
+
export const unscannedLines = ({ unscanned = [], unscannedReason, }) => unscanned.length ?
|
|
40
|
+
[
|
|
41
|
+
`⏳ ${unscanned.length} skill${unscanned.length === 1 ? '' : 's'} left out, ${unscannedReason === 'timeout' ?
|
|
42
|
+
'security data timed out'
|
|
43
|
+
: 'Socket has not scanned their packages yet'}: ${unscanned.join(', ')}. Try again later.`,
|
|
44
|
+
]
|
|
45
|
+
: [];
|
|
46
|
+
/** `allow-skills` saved to a config file. */
|
|
47
|
+
export const savedLine = (query, which) => `Saved allow-skills="${query}" to ${configLabel(which)}`;
|
|
48
|
+
/** `--allow-skills` not saved: another query is stored. */
|
|
49
|
+
export const keptLine = (s) => `allow-skills is already set (${configLabel(s.which)}): "${s.query}"; not replaced. Run vlt skills link to change it, or edit ${configLabel(s.which)}`;
|
package/dist/commands/build.d.ts
CHANGED
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
import type { BuildResult } from '@vltpkg/graph';
|
|
2
|
+
import type { GlobalBins } from '../global.ts';
|
|
2
3
|
import type { CommandFn, CommandUsage } from '../index.ts';
|
|
4
|
+
export type BuildCommandResult = BuildResult & {
|
|
5
|
+
global?: GlobalBins;
|
|
6
|
+
};
|
|
3
7
|
export declare const views: {
|
|
4
|
-
readonly human: (result:
|
|
5
|
-
readonly json: (result:
|
|
8
|
+
readonly human: (result: BuildCommandResult) => string;
|
|
9
|
+
readonly json: (result: BuildCommandResult) => {
|
|
10
|
+
global?: GlobalBins | undefined;
|
|
11
|
+
message: string;
|
|
12
|
+
skipped?: {
|
|
13
|
+
id: import("@vltpkg/dep-id").DepID;
|
|
14
|
+
name: string;
|
|
15
|
+
version: string | undefined;
|
|
16
|
+
}[] | undefined;
|
|
17
|
+
skippedReason?: "timeout" | "unscanned" | undefined;
|
|
6
18
|
success: {
|
|
7
19
|
id: import("@vltpkg/dep-id").DepID;
|
|
8
20
|
name: string;
|
|
@@ -13,7 +25,6 @@ export declare const views: {
|
|
|
13
25
|
name: string;
|
|
14
26
|
version: string | undefined;
|
|
15
27
|
}[];
|
|
16
|
-
message: string;
|
|
17
28
|
};
|
|
18
29
|
};
|
|
19
30
|
export declare const needsRegistry = true;
|
|
@@ -22,4 +33,4 @@ export declare const usage: CommandUsage;
|
|
|
22
33
|
* Build command implementation. Runs any required "postinstall"
|
|
23
34
|
* lifecycle scripts and binary linking.
|
|
24
35
|
*/
|
|
25
|
-
export declare const command: CommandFn<
|
|
36
|
+
export declare const command: CommandFn<BuildCommandResult>;
|
package/dist/commands/build.js
CHANGED
|
@@ -1,40 +1,55 @@
|
|
|
1
|
-
import { build } from '@vltpkg/graph';
|
|
1
|
+
import { actual, build } from '@vltpkg/graph';
|
|
2
2
|
import { error } from '@vltpkg/error-cause';
|
|
3
3
|
import { commandUsage } from "../config/usage.js";
|
|
4
|
+
import { globalBinsLines, linkGlobalBins } from "../global.js";
|
|
5
|
+
import { resolveGlobalBinDir } from "../global-bin-dir.js";
|
|
4
6
|
import { isErrorWithCause } from '@vltpkg/types';
|
|
7
|
+
const skippedMessage = (count, reason) => `${count} package${count === 1 ? '' : 's'} not built, ${reason === 'unscanned' ?
|
|
8
|
+
'Socket has not scanned them yet'
|
|
9
|
+
: 'security data timed out'}. Run "vlt build" again later.`;
|
|
5
10
|
export const views = {
|
|
6
11
|
human: (result) => {
|
|
7
12
|
const successCount = result.success.length;
|
|
8
13
|
const failureCount = result.failure.length;
|
|
14
|
+
const skippedCount = result.skipped?.length ?? 0;
|
|
9
15
|
const messages = [];
|
|
10
16
|
if (successCount > 0) {
|
|
11
17
|
messages.push(`🔨 Built ${successCount} package${successCount === 1 ? '' : 's'} successfully.`);
|
|
12
18
|
}
|
|
13
|
-
else {
|
|
19
|
+
else if (!skippedCount) {
|
|
14
20
|
messages.push('📦 All packages are already built.');
|
|
15
21
|
}
|
|
16
22
|
if (failureCount > 0) {
|
|
17
23
|
messages.push(`🔎 ${failureCount} optional package${ /* c8 ignore next */failureCount === 1 ? '' : 's'} failed to build.`);
|
|
18
24
|
}
|
|
25
|
+
if (skippedCount > 0) {
|
|
26
|
+
messages.push(`⏳ ${skippedMessage(skippedCount, result.skippedReason)}`);
|
|
27
|
+
}
|
|
28
|
+
if (result.global)
|
|
29
|
+
messages.push(...globalBinsLines(result.global));
|
|
19
30
|
return messages.join('\n');
|
|
20
31
|
},
|
|
21
32
|
json: (result) => {
|
|
22
|
-
const
|
|
23
|
-
id: node.id,
|
|
24
|
-
name: node.name,
|
|
25
|
-
version: node.version,
|
|
26
|
-
}));
|
|
27
|
-
const failureList = result.failure.map(node => ({
|
|
33
|
+
const toJSON = (node) => ({
|
|
28
34
|
id: node.id,
|
|
29
35
|
name: node.name,
|
|
30
36
|
version: node.version,
|
|
31
|
-
})
|
|
37
|
+
});
|
|
38
|
+
const successList = result.success.map(toJSON);
|
|
39
|
+
const failureList = result.failure.map(toJSON);
|
|
40
|
+
const skippedList = result.skipped?.map(toJSON) ?? [];
|
|
32
41
|
return {
|
|
33
42
|
success: successList,
|
|
34
43
|
failure: failureList,
|
|
44
|
+
...(skippedList.length ?
|
|
45
|
+
{ skipped: skippedList, skippedReason: result.skippedReason }
|
|
46
|
+
: {}),
|
|
35
47
|
message: successList.length > 0 ?
|
|
36
48
|
`Built ${successList.length} package${successList.length === 1 ? '' : 's'}.`
|
|
37
|
-
:
|
|
49
|
+
: skippedList.length ?
|
|
50
|
+
skippedMessage(skippedList.length, result.skippedReason)
|
|
51
|
+
: 'No packages needed building.',
|
|
52
|
+
...(result.global ? { global: result.global } : null),
|
|
38
53
|
};
|
|
39
54
|
},
|
|
40
55
|
};
|
|
@@ -58,6 +73,9 @@ export const usage = () => commandUsage({
|
|
|
58
73
|
value: '<query>',
|
|
59
74
|
description: 'Query selector to filter packages using DSS syntax.',
|
|
60
75
|
},
|
|
76
|
+
global: {
|
|
77
|
+
description: 'Build packages installed in the global project.',
|
|
78
|
+
},
|
|
61
79
|
},
|
|
62
80
|
});
|
|
63
81
|
const isGraphRunError = (error) => typeof error === 'object' &&
|
|
@@ -71,6 +89,8 @@ const isGraphRunError = (error) => typeof error === 'object' &&
|
|
|
71
89
|
*/
|
|
72
90
|
export const command = async (conf) => {
|
|
73
91
|
const { options, projectRoot } = conf;
|
|
92
|
+
const binDir = conf.globalRoot ? await resolveGlobalBinDir(conf) : undefined;
|
|
93
|
+
let result;
|
|
74
94
|
try {
|
|
75
95
|
// Get target from option or first positional, default to all scripts
|
|
76
96
|
const targetOption = conf.get('target');
|
|
@@ -79,7 +99,7 @@ export const command = async (conf) => {
|
|
|
79
99
|
targetPositional ||
|
|
80
100
|
':scripts:not(:built):not(:malware)';
|
|
81
101
|
// Run the build process using the graph build function
|
|
82
|
-
|
|
102
|
+
result = await build({
|
|
83
103
|
...options,
|
|
84
104
|
projectRoot,
|
|
85
105
|
packageJson: options.packageJson,
|
|
@@ -87,7 +107,6 @@ export const command = async (conf) => {
|
|
|
87
107
|
scurry: options.scurry,
|
|
88
108
|
target,
|
|
89
109
|
});
|
|
90
|
-
return result;
|
|
91
110
|
}
|
|
92
111
|
catch (cause) {
|
|
93
112
|
const graphRunError = isErrorWithCause(cause) && isGraphRunError(cause.cause) ?
|
|
@@ -99,4 +118,23 @@ export const command = async (conf) => {
|
|
|
99
118
|
}
|
|
100
119
|
throw error('Build failed', { cause });
|
|
101
120
|
}
|
|
121
|
+
if (!binDir)
|
|
122
|
+
return result;
|
|
123
|
+
// relink global bins, targets may be new
|
|
124
|
+
const graph = actual.load({
|
|
125
|
+
...options,
|
|
126
|
+
projectRoot,
|
|
127
|
+
mainManifest: options.packageJson.read(projectRoot),
|
|
128
|
+
monorepo: options.monorepo,
|
|
129
|
+
scurry: options.scurry,
|
|
130
|
+
loadManifests: true,
|
|
131
|
+
});
|
|
132
|
+
const global = await linkGlobalBins(graph, {
|
|
133
|
+
projectRoot,
|
|
134
|
+
scurry: options.scurry,
|
|
135
|
+
force: options.force,
|
|
136
|
+
binDir,
|
|
137
|
+
fallback: () => resolveGlobalBinDir(conf, { selfUnwritable: true }),
|
|
138
|
+
});
|
|
139
|
+
return { ...result, global };
|
|
102
140
|
};
|
package/dist/commands/ci.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { CommandFn, CommandUsage } from '../index.ts';
|
|
2
2
|
import type { InstallResult } from './install.ts';
|
|
3
|
-
export type CIResult = Pick<InstallResult, 'buildQueue' | 'graph'>;
|
|
3
|
+
export type CIResult = Pick<InstallResult, 'buildQueue' | 'graph' | 'skills'>;
|
|
4
4
|
export declare const needsRegistry = true;
|
|
5
5
|
export declare const needsNpmRegistry = true;
|
|
6
6
|
export declare const usage: CommandUsage;
|
|
7
7
|
export declare const views: {
|
|
8
8
|
readonly json: (i: CIResult) => import("@vltpkg/graph").LockfileData;
|
|
9
|
-
readonly human: import("../view.ts").LazyView<InstallResult
|
|
9
|
+
readonly human: import("../view.ts").LazyView<Partial<InstallResult>>;
|
|
10
10
|
};
|
|
11
11
|
export declare const command: CommandFn<CIResult>;
|
package/dist/commands/ci.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { install } from '@vltpkg/graph';
|
|
2
2
|
import { commandUsage } from "../config/usage.js";
|
|
3
|
+
import { warnIgnoredWorkspaces } from "../migrate-workspaces.js";
|
|
3
4
|
import { lazyView } from "../view.js";
|
|
4
5
|
export const needsRegistry = true;
|
|
5
6
|
export const needsNpmRegistry = true;
|
|
@@ -22,6 +23,10 @@ export const usage = () => commandUsage({
|
|
|
22
23
|
value: '<query>',
|
|
23
24
|
description: 'Filter which packages are allowed to run lifecycle scripts using DSS query syntax.',
|
|
24
25
|
},
|
|
26
|
+
'allow-skills': {
|
|
27
|
+
value: '<query>',
|
|
28
|
+
description: "Link agent skills of packages matching this DSS query into the project's agent skill dirs.",
|
|
29
|
+
},
|
|
25
30
|
'lockfile-only': {
|
|
26
31
|
description: 'Only update lockfile and package.json files; skip node_modules operations.',
|
|
27
32
|
},
|
|
@@ -32,15 +37,18 @@ export const views = {
|
|
|
32
37
|
human: lazyView(async () => (await import('./install/reporter.ts')).InstallReporter),
|
|
33
38
|
};
|
|
34
39
|
export const command = async (conf) => {
|
|
40
|
+
warnIgnoredWorkspaces(conf);
|
|
35
41
|
const ciOptions = {
|
|
36
42
|
...conf.options,
|
|
37
43
|
// same default as install: no scripts
|
|
38
44
|
allowScripts: conf.get('allow-scripts') ?? ':not(*)',
|
|
45
|
+
allowSkills: conf.get('allow-skills'),
|
|
46
|
+
skillsDirs: conf.get('skills-dir'),
|
|
39
47
|
expectLockfile: true,
|
|
40
48
|
frozenLockfile: true,
|
|
41
49
|
cleanInstall: true,
|
|
42
50
|
lockfileOnly: conf.options['lockfile-only'],
|
|
43
51
|
};
|
|
44
|
-
const { buildQueue, graph } = await install(ciOptions);
|
|
45
|
-
return { buildQueue, graph };
|
|
52
|
+
const { buildQueue, graph, skills } = await install(ciOptions);
|
|
53
|
+
return { buildQueue, graph, ...(skills ? { skills } : null) };
|
|
46
54
|
};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { PromptFn } from '@vltpkg/vlx';
|
|
2
2
|
import type { ExecResult } from '../exec-command.ts';
|
|
3
3
|
import type { CommandFn, CommandUsage } from '../index.ts';
|
|
4
|
+
import { prettyPath } from '../shell.ts';
|
|
4
5
|
export { views } from '../exec-command.ts';
|
|
5
6
|
export declare const needsRegistry = true;
|
|
6
7
|
export declare const usage: CommandUsage;
|
|
7
|
-
export
|
|
8
|
+
export { prettyPath };
|
|
8
9
|
export declare const promptFn: PromptFn;
|
|
9
10
|
export declare const command: CommandFn<ExecResult>;
|
package/dist/commands/create.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { exec, execFG } from '@vltpkg/run';
|
|
2
2
|
import * as vlx from '@vltpkg/vlx';
|
|
3
|
-
import { homedir } from 'node:os';
|
|
4
3
|
import { createInterface } from 'node:readline/promises';
|
|
5
4
|
import { commandUsage } from "../config/usage.js";
|
|
6
5
|
import { ExecCommand } from "../exec-command.js";
|
|
7
6
|
import { styleTextStdout } from "../output.js";
|
|
7
|
+
import { prettyPath } from "../shell.js";
|
|
8
8
|
export { views } from "../exec-command.js";
|
|
9
9
|
export const needsRegistry = true;
|
|
10
10
|
export const usage = () => commandUsage({
|
|
@@ -47,8 +47,7 @@ export const usage = () => commandUsage({
|
|
|
47
47
|
},
|
|
48
48
|
},
|
|
49
49
|
});
|
|
50
|
-
|
|
51
|
-
export const prettyPath = (path) => path.startsWith(HOME) ? `~${path.substring(HOME.length)}` : path;
|
|
50
|
+
export { prettyPath };
|
|
52
51
|
export const promptFn = async (pkgSpec, path, resolution) => {
|
|
53
52
|
const response = await createInterface(process.stdin, process.stdout).question(`About to install: ${styleTextStdout(['bgWhiteBright', 'black', 'bold'], String(pkgSpec))}
|
|
54
53
|
from: ${styleTextStdout(['bgWhiteBright', 'black', 'bold'], resolution)}
|
package/dist/commands/exec.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { PromptFn } from '@vltpkg/vlx';
|
|
2
2
|
import type { ExecResult } from '../exec-command.ts';
|
|
3
3
|
import type { CommandFn, CommandUsage } from '../index.ts';
|
|
4
|
+
import { prettyPath } from '../shell.ts';
|
|
4
5
|
export { views } from '../exec-command.ts';
|
|
5
6
|
export declare const needsRegistry = true;
|
|
6
7
|
export declare const needsNpmRegistry = true;
|
|
7
8
|
export declare const usage: CommandUsage;
|
|
8
|
-
export
|
|
9
|
+
export { prettyPath };
|
|
9
10
|
export declare const promptFn: PromptFn;
|
|
10
11
|
export declare const command: CommandFn<ExecResult>;
|
package/dist/commands/exec.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { exec, execFG } from '@vltpkg/run';
|
|
2
2
|
import * as vlx from '@vltpkg/vlx';
|
|
3
|
-
import { homedir } from 'node:os';
|
|
4
3
|
import { env, platform } from 'node:process';
|
|
5
4
|
import { createInterface } from 'node:readline/promises';
|
|
6
5
|
import { commandUsage } from "../config/usage.js";
|
|
7
6
|
import { ExecCommand } from "../exec-command.js";
|
|
8
7
|
import { styleTextStdout } from "../output.js";
|
|
8
|
+
import { prettyPath } from "../shell.js";
|
|
9
9
|
export { views } from "../exec-command.js";
|
|
10
10
|
export const needsRegistry = true;
|
|
11
11
|
export const needsNpmRegistry = true;
|
|
@@ -113,8 +113,7 @@ export const usage = () => commandUsage({
|
|
|
113
113
|
},
|
|
114
114
|
},
|
|
115
115
|
});
|
|
116
|
-
|
|
117
|
-
export const prettyPath = (path) => path.startsWith(HOME) ? `~${path.substring(HOME.length)}` : path;
|
|
116
|
+
export { prettyPath };
|
|
118
117
|
export const promptFn = async (pkgSpec, path, resolution) => {
|
|
119
118
|
const response = await createInterface(process.stdin, process.stdout).question(`About to install: ${styleTextStdout(['bgWhiteBright', 'black', 'bold'], String(pkgSpec))}
|
|
120
119
|
from: ${styleTextStdout(['bgWhiteBright', 'black', 'bold'], resolution)}
|
package/dist/commands/init.js
CHANGED
|
@@ -4,7 +4,7 @@ import { minimatch } from 'minimatch';
|
|
|
4
4
|
import { init } from '@vltpkg/init';
|
|
5
5
|
import { install } from '@vltpkg/graph';
|
|
6
6
|
import { load, save } from '@vltpkg/vlt-json';
|
|
7
|
-
import { assertWSConfig, resolveWSConfig, splitNegatedPatterns, } from '@vltpkg/workspaces';
|
|
7
|
+
import { assertWSConfig, migratableWSConfig, resolveWSConfig, splitNegatedPatterns, } from '@vltpkg/workspaces';
|
|
8
8
|
import { commandUsage } from "../config/usage.js";
|
|
9
9
|
export const usage = () => commandUsage({
|
|
10
10
|
command: 'init',
|
|
@@ -57,14 +57,15 @@ export const command = async (conf) => {
|
|
|
57
57
|
if (conf.values.workspace?.length) {
|
|
58
58
|
// the *effective* config, which may come from the root package.json
|
|
59
59
|
// rather than vlt.json
|
|
60
|
-
const
|
|
60
|
+
const resolved = resolveWSConfig(conf.options.projectRoot, conf.options.packageJson);
|
|
61
|
+
const parsedWSConfig = resolved.config;
|
|
61
62
|
// what gets written back to vlt.json. The raw vlt.json value is
|
|
62
63
|
// reused as-is so its existing shape is preserved. When the
|
|
63
64
|
// definitions live in package.json or pnpm-workspace.yaml instead,
|
|
64
65
|
// seed vlt.json with them first -- otherwise adding a `workspaces`
|
|
65
66
|
// field here would shadow every workspace already declared there.
|
|
66
67
|
const workspacesConfig = load('workspaces', assertWSConfig) ??
|
|
67
|
-
(
|
|
68
|
+
migratableWSConfig(resolved);
|
|
68
69
|
const results = [];
|
|
69
70
|
const addToConfig = [];
|
|
70
71
|
// create a new package.json file for every workspace
|
|
@@ -3,7 +3,7 @@ import type { InstallResult } from '../install.ts';
|
|
|
3
3
|
export declare class InstallReporter extends ViewClass {
|
|
4
4
|
#private;
|
|
5
5
|
start(): void;
|
|
6
|
-
done(_result: InstallResult
|
|
6
|
+
done(_result: Partial<InstallResult>, { time }: {
|
|
7
7
|
time: number;
|
|
8
8
|
}): Promise<undefined>;
|
|
9
9
|
error(err: unknown): void;
|
|
@@ -4,7 +4,11 @@ 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 { isSelfUpdateArgs, selfUpdateLines, } from "../../self-update.js";
|
|
7
8
|
import { persistedEntries } from "../../persist-spec-config.js";
|
|
9
|
+
import { keptLine, savedLine, unmatchedLines, unscannedLines, } from "../../allow-skills.js";
|
|
10
|
+
import { globalBinsLines } from "../../global.js";
|
|
11
|
+
import { offerPathSetup } from "../../shell-setup/index.js";
|
|
8
12
|
const labels = {
|
|
9
13
|
build: 'resolving dependencies',
|
|
10
14
|
actual: '',
|
|
@@ -74,26 +78,108 @@ const App = ({ trailer }) => {
|
|
|
74
78
|
};
|
|
75
79
|
export class InstallReporter extends ViewClass {
|
|
76
80
|
#instance = null;
|
|
81
|
+
#plain = false;
|
|
77
82
|
start() {
|
|
83
|
+
// Ink measures the terminal on every render, and when stdout has no
|
|
84
|
+
// width (a pipe, a CI log) it does so by spawning `tput cols` and
|
|
85
|
+
// `tput lines`: thousands of processes over one install. Give a
|
|
86
|
+
// non-TTY stdout the width Ink would fall back to anyway, so the
|
|
87
|
+
// output is the same and nothing is spawned.
|
|
88
|
+
if (!process.stdout.isTTY) {
|
|
89
|
+
// only a sane COLUMNS counts; -1 or Infinity would be truthy
|
|
90
|
+
const cols = Number(process.env.COLUMNS);
|
|
91
|
+
process.stdout.columns ||=
|
|
92
|
+
Number.isInteger(cols) && cols > 0 ? cols : 80;
|
|
93
|
+
}
|
|
94
|
+
// npm may write to the terminal: no live view
|
|
95
|
+
if (isSelfUpdateArgs(this.config)) {
|
|
96
|
+
this.#plain = true;
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
78
99
|
this.#instance = render($(App));
|
|
79
100
|
}
|
|
80
101
|
async done(_result, { time }) {
|
|
81
|
-
|
|
102
|
+
const { self } = _result;
|
|
103
|
+
let out = self && !_result.graph ? '' : `Done in ${time}ms`;
|
|
82
104
|
// prints a very complete message explaining users the next steps
|
|
83
105
|
// in case there are packages to be built
|
|
106
|
+
const g = _result.global ? ' -g' : '';
|
|
84
107
|
if (_result.buildQueue?.length) {
|
|
85
108
|
out += `\n\n📦 ${_result.buildQueue.length} packages have install scripts defined & were not fully built\n`;
|
|
86
|
-
out +=
|
|
87
|
-
out +=
|
|
88
|
-
|
|
109
|
+
out += `🔎 Run \`vlt query${g} :scripts\` to list them\n`;
|
|
110
|
+
out += `🔨 Run \`vlt build${g}\` to run all required scripts to build installed packages.\n`;
|
|
111
|
+
}
|
|
112
|
+
if (self) {
|
|
113
|
+
for (const l of selfUpdateLines(self))
|
|
114
|
+
out += out ? `\n${l}` : l;
|
|
115
|
+
}
|
|
116
|
+
if (_result.global) {
|
|
117
|
+
// the self-update line says why
|
|
118
|
+
const bins = self?.status === 'updated' && self.case === 'bootstrap' ?
|
|
119
|
+
{ ..._result.global, notWritable: undefined }
|
|
120
|
+
: _result.global;
|
|
121
|
+
for (const l of globalBinsLines(bins))
|
|
122
|
+
out += `\n${l}`;
|
|
123
|
+
}
|
|
124
|
+
const { linked = [], removed = [], conflicts = [], skipped = [], gitignore = [], unmatched = [], } = _result.skills ?? {};
|
|
125
|
+
const s = (n) => (n === 1 ? '' : 's');
|
|
126
|
+
const skills = [];
|
|
127
|
+
if (linked.length) {
|
|
128
|
+
// one per skill, linked in any number of dirs
|
|
129
|
+
const n = new Set(linked.map(r => `${r.id}\0${r.skill}`)).size;
|
|
130
|
+
const dirs = [...new Set(linked.map(r => r.dir))].join(', ');
|
|
131
|
+
skills.push(`🔗 Linked ${n} agent skill${s(n)} into ${dirs}`);
|
|
132
|
+
}
|
|
133
|
+
if (removed.length) {
|
|
134
|
+
skills.push(`🧹 Removed ${removed.length} stale skill link${s(removed.length)}: ${removed.join(', ')}`);
|
|
89
135
|
}
|
|
136
|
+
if (conflicts.length) {
|
|
137
|
+
skills.push(`⚠️ ${conflicts.length} skill link${s(conflicts.length)} skipped, path in use or taken by another package: ${conflicts.join(', ')}`);
|
|
138
|
+
}
|
|
139
|
+
skills.push(...unmatchedLines(unmatched));
|
|
140
|
+
if (skipped.length) {
|
|
141
|
+
skills.push(`⚠️ Skipped ${skipped.join(', ')}`);
|
|
142
|
+
}
|
|
143
|
+
if (gitignore.length) {
|
|
144
|
+
skills.push(`⚠️ Could not update ${gitignore.join(', ')}`);
|
|
145
|
+
}
|
|
146
|
+
skills.push(...unscannedLines(_result.skills ?? {}));
|
|
147
|
+
if (skills.length)
|
|
148
|
+
out += `\n${skills.join('\n')}\n`;
|
|
90
149
|
const saved = _result.persistedConfig;
|
|
91
150
|
if (saved) {
|
|
92
151
|
for (const e of persistedEntries(saved.values)) {
|
|
93
152
|
out += `\nSaved ${e} to ${saved.which} vlt.json`;
|
|
94
153
|
}
|
|
95
154
|
}
|
|
96
|
-
|
|
155
|
+
const migrated = _result.migratedWorkspaces;
|
|
156
|
+
if (migrated) {
|
|
157
|
+
out += `\nSaved workspaces from ${migrated.source} to vlt.json`;
|
|
158
|
+
}
|
|
159
|
+
const a = _result.allowSkills;
|
|
160
|
+
if (a?.stored)
|
|
161
|
+
out += `\n${keptLine(a.stored)}`;
|
|
162
|
+
else if (a)
|
|
163
|
+
out += `\n${savedLine(a.query, 'project')}`;
|
|
164
|
+
// failed: npm already said why
|
|
165
|
+
if (!out)
|
|
166
|
+
return undefined;
|
|
167
|
+
if (this.#plain)
|
|
168
|
+
this.#instance = render($(Text, null, out));
|
|
169
|
+
else
|
|
170
|
+
this.#instance?.rerender($(App, { trailer: out }));
|
|
171
|
+
if (_result.global) {
|
|
172
|
+
await offerPathSetup(_result.global, {
|
|
173
|
+
globalDir: this.config.projectRoot,
|
|
174
|
+
yes: !!this.config.get('yes'),
|
|
175
|
+
noModifyPath: !!this.config.get('no-modify-path'),
|
|
176
|
+
// ink owns the terminal until unmounted
|
|
177
|
+
beforeOutput: () => {
|
|
178
|
+
this.#instance?.unmount();
|
|
179
|
+
this.#instance = null;
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
}
|
|
97
183
|
return undefined;
|
|
98
184
|
}
|
|
99
185
|
error(err) {
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import type { AllowSkillsSave } from '../allow-skills.ts';
|
|
2
|
+
import type { GlobalBins } from '../global.ts';
|
|
3
|
+
import type { SelfUpdate } from '../self-update.ts';
|
|
4
|
+
import type { MigratedWorkspaces } from '../migrate-workspaces.ts';
|
|
1
5
|
import type { SpecConfigPersistPlan } from '../persist-spec-config.ts';
|
|
2
6
|
import type { DepID } from '@vltpkg/dep-id';
|
|
3
|
-
import type { Diff, Graph } from '@vltpkg/graph';
|
|
7
|
+
import type { Diff, Graph, LinkSkillsResult } from '@vltpkg/graph';
|
|
4
8
|
import type { CommandFn, CommandUsage } from '../index.ts';
|
|
5
9
|
/**
|
|
6
10
|
* The resulting object of an install operation. To be used by the view impl.
|
|
@@ -22,12 +26,54 @@ export type InstallResult = {
|
|
|
22
26
|
* Spec config from the cli / env that was saved to a config file.
|
|
23
27
|
*/
|
|
24
28
|
persistedConfig?: SpecConfigPersistPlan;
|
|
29
|
+
/**
|
|
30
|
+
* Workspaces saved to vlt.json from package.json or pnpm-workspace.yaml.
|
|
31
|
+
*/
|
|
32
|
+
migratedWorkspaces?: MigratedWorkspaces;
|
|
33
|
+
/**
|
|
34
|
+
* Agent skill links added or removed.
|
|
35
|
+
*/
|
|
36
|
+
skills?: LinkSkillsResult;
|
|
37
|
+
/**
|
|
38
|
+
* `--allow-skills` saved to vlt.json, or kept because another query
|
|
39
|
+
* is stored.
|
|
40
|
+
*/
|
|
41
|
+
allowSkills?: AllowSkillsSave;
|
|
42
|
+
/**
|
|
43
|
+
* Bins linked by a `--global` install.
|
|
44
|
+
*/
|
|
45
|
+
global?: GlobalBins;
|
|
46
|
+
/**
|
|
47
|
+
* `vlt install -g vlt`
|
|
48
|
+
*/
|
|
49
|
+
self?: SelfUpdate;
|
|
50
|
+
};
|
|
51
|
+
/** self-update handed off or nothing to do */
|
|
52
|
+
export type InstallCommandResult = InstallResult | {
|
|
53
|
+
self: SelfUpdate;
|
|
25
54
|
};
|
|
26
55
|
export declare const needsRegistry = true;
|
|
27
56
|
export declare const needsNpmRegistry = true;
|
|
28
57
|
export declare const usage: CommandUsage;
|
|
29
58
|
export declare const views: {
|
|
30
|
-
readonly json: (i:
|
|
59
|
+
readonly json: (i: InstallCommandResult) => {
|
|
60
|
+
self: SelfUpdate;
|
|
61
|
+
} | {
|
|
62
|
+
self?: SelfUpdate | undefined;
|
|
63
|
+
global?: GlobalBins | undefined;
|
|
64
|
+
allowSkills?: AllowSkillsSave | undefined;
|
|
65
|
+
skills?: {
|
|
66
|
+
unscanned?: string[];
|
|
67
|
+
unscannedReason?: "timeout" | "unscanned";
|
|
68
|
+
removed: string[];
|
|
69
|
+
conflicts: string[];
|
|
70
|
+
dirs: string[];
|
|
71
|
+
skipped?: string[];
|
|
72
|
+
gitignore?: string[];
|
|
73
|
+
unmatched?: import("@vltpkg/graph").UnmatchedPattern[];
|
|
74
|
+
linked: string[];
|
|
75
|
+
} | undefined;
|
|
76
|
+
migratedWorkspaces?: MigratedWorkspaces | undefined;
|
|
31
77
|
persistedConfig?: SpecConfigPersistPlan | undefined;
|
|
32
78
|
buildQueue?: DepID[] | undefined;
|
|
33
79
|
message?: string | undefined;
|
|
@@ -48,6 +94,6 @@ export declare const views: {
|
|
|
48
94
|
}[];
|
|
49
95
|
removed: number;
|
|
50
96
|
};
|
|
51
|
-
readonly human: import("../view.ts").LazyView<InstallResult
|
|
97
|
+
readonly human: import("../view.ts").LazyView<Partial<InstallResult>>;
|
|
52
98
|
};
|
|
53
|
-
export declare const command: CommandFn<
|
|
99
|
+
export declare const command: CommandFn<InstallCommandResult>;
|