@vltpkg/cli-sdk 1.4.0 → 1.5.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 +7 -1
- package/dist/commands/build.js +19 -9
- package/dist/commands/ci.d.ts +1 -1
- package/dist/commands/ci.js +10 -2
- package/dist/commands/init.js +4 -3
- package/dist/commands/install/reporter.js +46 -0
- package/dist/commands/install.d.ts +29 -1
- package/dist/commands/install.js +29 -1
- package/dist/commands/list.js +3 -1
- package/dist/commands/publish.d.ts +0 -1
- package/dist/commands/publish.js +27 -16
- package/dist/commands/query.js +3 -1
- package/dist/commands/skills.d.ts +56 -0
- package/dist/commands/skills.js +268 -0
- package/dist/commands/uninstall.d.ts +5 -1
- package/dist/commands/uninstall.js +4 -2
- package/dist/commands/unpublish.d.ts +0 -1
- package/dist/commands/unpublish.js +17 -4
- package/dist/commands/update.d.ts +12 -0
- package/dist/commands/update.js +18 -1
- package/dist/config/definition.d.ts +20 -0
- package/dist/config/definition.js +49 -1
- package/dist/custom-help.js +4 -0
- package/dist/index.js +7 -1
- 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/print-err.js +4 -1
- package/dist/publish-config.d.ts +9 -0
- package/dist/publish-config.js +8 -0
- package/dist/skills-prompt.d.ts +28 -0
- package/dist/skills-prompt.js +78 -0
- package/package.json +28 -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
|
@@ -3,6 +3,13 @@ import type { CommandFn, CommandUsage } from '../index.ts';
|
|
|
3
3
|
export declare const views: {
|
|
4
4
|
readonly human: (result: BuildResult) => string;
|
|
5
5
|
readonly json: (result: BuildResult) => {
|
|
6
|
+
message: string;
|
|
7
|
+
skipped?: {
|
|
8
|
+
id: import("@vltpkg/dep-id").DepID;
|
|
9
|
+
name: string;
|
|
10
|
+
version: string | undefined;
|
|
11
|
+
}[] | undefined;
|
|
12
|
+
skippedReason?: "timeout" | "unscanned" | undefined;
|
|
6
13
|
success: {
|
|
7
14
|
id: import("@vltpkg/dep-id").DepID;
|
|
8
15
|
name: string;
|
|
@@ -13,7 +20,6 @@ export declare const views: {
|
|
|
13
20
|
name: string;
|
|
14
21
|
version: string | undefined;
|
|
15
22
|
}[];
|
|
16
|
-
message: string;
|
|
17
23
|
};
|
|
18
24
|
};
|
|
19
25
|
export declare const needsRegistry = true;
|
package/dist/commands/build.js
CHANGED
|
@@ -2,39 +2,49 @@ import { build } from '@vltpkg/graph';
|
|
|
2
2
|
import { error } from '@vltpkg/error-cause';
|
|
3
3
|
import { commandUsage } from "../config/usage.js";
|
|
4
4
|
import { isErrorWithCause } from '@vltpkg/types';
|
|
5
|
+
const skippedMessage = (count, reason) => `${count} package${count === 1 ? '' : 's'} not built, ${reason === 'unscanned' ?
|
|
6
|
+
'Socket has not scanned them yet'
|
|
7
|
+
: 'security data timed out'}. Run "vlt build" again later.`;
|
|
5
8
|
export const views = {
|
|
6
9
|
human: (result) => {
|
|
7
10
|
const successCount = result.success.length;
|
|
8
11
|
const failureCount = result.failure.length;
|
|
12
|
+
const skippedCount = result.skipped?.length ?? 0;
|
|
9
13
|
const messages = [];
|
|
10
14
|
if (successCount > 0) {
|
|
11
15
|
messages.push(`🔨 Built ${successCount} package${successCount === 1 ? '' : 's'} successfully.`);
|
|
12
16
|
}
|
|
13
|
-
else {
|
|
17
|
+
else if (!skippedCount) {
|
|
14
18
|
messages.push('📦 All packages are already built.');
|
|
15
19
|
}
|
|
16
20
|
if (failureCount > 0) {
|
|
17
21
|
messages.push(`🔎 ${failureCount} optional package${ /* c8 ignore next */failureCount === 1 ? '' : 's'} failed to build.`);
|
|
18
22
|
}
|
|
23
|
+
if (skippedCount > 0) {
|
|
24
|
+
messages.push(`⏳ ${skippedMessage(skippedCount, result.skippedReason)}`);
|
|
25
|
+
}
|
|
19
26
|
return messages.join('\n');
|
|
20
27
|
},
|
|
21
28
|
json: (result) => {
|
|
22
|
-
const
|
|
29
|
+
const toJSON = (node) => ({
|
|
23
30
|
id: node.id,
|
|
24
31
|
name: node.name,
|
|
25
32
|
version: node.version,
|
|
26
|
-
})
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
version: node.version,
|
|
31
|
-
}));
|
|
33
|
+
});
|
|
34
|
+
const successList = result.success.map(toJSON);
|
|
35
|
+
const failureList = result.failure.map(toJSON);
|
|
36
|
+
const skippedList = result.skipped?.map(toJSON) ?? [];
|
|
32
37
|
return {
|
|
33
38
|
success: successList,
|
|
34
39
|
failure: failureList,
|
|
40
|
+
...(skippedList.length ?
|
|
41
|
+
{ skipped: skippedList, skippedReason: result.skippedReason }
|
|
42
|
+
: {}),
|
|
35
43
|
message: successList.length > 0 ?
|
|
36
44
|
`Built ${successList.length} package${successList.length === 1 ? '' : 's'}.`
|
|
37
|
-
:
|
|
45
|
+
: skippedList.length ?
|
|
46
|
+
skippedMessage(skippedList.length, result.skippedReason)
|
|
47
|
+
: 'No packages needed building.',
|
|
38
48
|
};
|
|
39
49
|
},
|
|
40
50
|
};
|
package/dist/commands/ci.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
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;
|
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
|
};
|
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
|
|
@@ -5,6 +5,7 @@ import { createElement as $, Fragment, useEffect, useState, } from 'react';
|
|
|
5
5
|
import { ViewClass } from "../../view.js";
|
|
6
6
|
import { asError } from '@vltpkg/types';
|
|
7
7
|
import { persistedEntries } from "../../persist-spec-config.js";
|
|
8
|
+
import { keptLine, savedLine, unmatchedLines, unscannedLines, } from "../../allow-skills.js";
|
|
8
9
|
const labels = {
|
|
9
10
|
build: 'resolving dependencies',
|
|
10
11
|
actual: '',
|
|
@@ -75,6 +76,17 @@ const App = ({ trailer }) => {
|
|
|
75
76
|
export class InstallReporter extends ViewClass {
|
|
76
77
|
#instance = null;
|
|
77
78
|
start() {
|
|
79
|
+
// Ink measures the terminal on every render, and when stdout has no
|
|
80
|
+
// width (a pipe, a CI log) it does so by spawning `tput cols` and
|
|
81
|
+
// `tput lines`: thousands of processes over one install. Give a
|
|
82
|
+
// non-TTY stdout the width Ink would fall back to anyway, so the
|
|
83
|
+
// output is the same and nothing is spawned.
|
|
84
|
+
if (!process.stdout.isTTY) {
|
|
85
|
+
// only a sane COLUMNS counts; -1 or Infinity would be truthy
|
|
86
|
+
const cols = Number(process.env.COLUMNS);
|
|
87
|
+
process.stdout.columns ||=
|
|
88
|
+
Number.isInteger(cols) && cols > 0 ? cols : 80;
|
|
89
|
+
}
|
|
78
90
|
this.#instance = render($(App));
|
|
79
91
|
}
|
|
80
92
|
async done(_result, { time }) {
|
|
@@ -87,12 +99,46 @@ export class InstallReporter extends ViewClass {
|
|
|
87
99
|
out +=
|
|
88
100
|
'🔨 Run `vlt build` to run all required scripts to build installed packages.\n';
|
|
89
101
|
}
|
|
102
|
+
const { linked = [], removed = [], conflicts = [], skipped = [], gitignore = [], unmatched = [], } = _result.skills ?? {};
|
|
103
|
+
const s = (n) => (n === 1 ? '' : 's');
|
|
104
|
+
const skills = [];
|
|
105
|
+
if (linked.length) {
|
|
106
|
+
// one per skill, linked in any number of dirs
|
|
107
|
+
const n = new Set(linked.map(r => `${r.id}\0${r.skill}`)).size;
|
|
108
|
+
const dirs = [...new Set(linked.map(r => r.dir))].join(', ');
|
|
109
|
+
skills.push(`🔗 Linked ${n} agent skill${s(n)} into ${dirs}`);
|
|
110
|
+
}
|
|
111
|
+
if (removed.length) {
|
|
112
|
+
skills.push(`🧹 Removed ${removed.length} stale skill link${s(removed.length)}: ${removed.join(', ')}`);
|
|
113
|
+
}
|
|
114
|
+
if (conflicts.length) {
|
|
115
|
+
skills.push(`⚠️ ${conflicts.length} skill link${s(conflicts.length)} skipped, path in use or taken by another package: ${conflicts.join(', ')}`);
|
|
116
|
+
}
|
|
117
|
+
skills.push(...unmatchedLines(unmatched));
|
|
118
|
+
if (skipped.length) {
|
|
119
|
+
skills.push(`⚠️ Skipped ${skipped.join(', ')}`);
|
|
120
|
+
}
|
|
121
|
+
if (gitignore.length) {
|
|
122
|
+
skills.push(`⚠️ Could not update ${gitignore.join(', ')}`);
|
|
123
|
+
}
|
|
124
|
+
skills.push(...unscannedLines(_result.skills ?? {}));
|
|
125
|
+
if (skills.length)
|
|
126
|
+
out += `\n${skills.join('\n')}\n`;
|
|
90
127
|
const saved = _result.persistedConfig;
|
|
91
128
|
if (saved) {
|
|
92
129
|
for (const e of persistedEntries(saved.values)) {
|
|
93
130
|
out += `\nSaved ${e} to ${saved.which} vlt.json`;
|
|
94
131
|
}
|
|
95
132
|
}
|
|
133
|
+
const migrated = _result.migratedWorkspaces;
|
|
134
|
+
if (migrated) {
|
|
135
|
+
out += `\nSaved workspaces from ${migrated.source} to vlt.json`;
|
|
136
|
+
}
|
|
137
|
+
const a = _result.allowSkills;
|
|
138
|
+
if (a?.stored)
|
|
139
|
+
out += `\n${keptLine(a.stored)}`;
|
|
140
|
+
else if (a)
|
|
141
|
+
out += `\n${savedLine(a.query, 'project')}`;
|
|
96
142
|
this.#instance?.rerender($(App, { trailer: out }));
|
|
97
143
|
return undefined;
|
|
98
144
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import type { AllowSkillsSave } from '../allow-skills.ts';
|
|
2
|
+
import type { MigratedWorkspaces } from '../migrate-workspaces.ts';
|
|
1
3
|
import type { SpecConfigPersistPlan } from '../persist-spec-config.ts';
|
|
2
4
|
import type { DepID } from '@vltpkg/dep-id';
|
|
3
|
-
import type { Diff, Graph } from '@vltpkg/graph';
|
|
5
|
+
import type { Diff, Graph, LinkSkillsResult } from '@vltpkg/graph';
|
|
4
6
|
import type { CommandFn, CommandUsage } from '../index.ts';
|
|
5
7
|
/**
|
|
6
8
|
* The resulting object of an install operation. To be used by the view impl.
|
|
@@ -22,12 +24,38 @@ export type InstallResult = {
|
|
|
22
24
|
* Spec config from the cli / env that was saved to a config file.
|
|
23
25
|
*/
|
|
24
26
|
persistedConfig?: SpecConfigPersistPlan;
|
|
27
|
+
/**
|
|
28
|
+
* Workspaces saved to vlt.json from package.json or pnpm-workspace.yaml.
|
|
29
|
+
*/
|
|
30
|
+
migratedWorkspaces?: MigratedWorkspaces;
|
|
31
|
+
/**
|
|
32
|
+
* Agent skill links added or removed.
|
|
33
|
+
*/
|
|
34
|
+
skills?: LinkSkillsResult;
|
|
35
|
+
/**
|
|
36
|
+
* `--allow-skills` saved to vlt.json, or kept because another query
|
|
37
|
+
* is stored.
|
|
38
|
+
*/
|
|
39
|
+
allowSkills?: AllowSkillsSave;
|
|
25
40
|
};
|
|
26
41
|
export declare const needsRegistry = true;
|
|
27
42
|
export declare const needsNpmRegistry = true;
|
|
28
43
|
export declare const usage: CommandUsage;
|
|
29
44
|
export declare const views: {
|
|
30
45
|
readonly json: (i: InstallResult) => {
|
|
46
|
+
allowSkills?: AllowSkillsSave | undefined;
|
|
47
|
+
skills?: {
|
|
48
|
+
unscanned?: string[];
|
|
49
|
+
unscannedReason?: "timeout" | "unscanned";
|
|
50
|
+
removed: string[];
|
|
51
|
+
conflicts: string[];
|
|
52
|
+
dirs: string[];
|
|
53
|
+
skipped?: string[];
|
|
54
|
+
gitignore?: string[];
|
|
55
|
+
unmatched?: import("@vltpkg/graph").UnmatchedPattern[];
|
|
56
|
+
linked: string[];
|
|
57
|
+
} | undefined;
|
|
58
|
+
migratedWorkspaces?: MigratedWorkspaces | undefined;
|
|
31
59
|
persistedConfig?: SpecConfigPersistPlan | undefined;
|
|
32
60
|
buildQueue?: DepID[] | undefined;
|
|
33
61
|
message?: string | undefined;
|
package/dist/commands/install.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { commandUsage } from "../config/usage.js";
|
|
2
2
|
import { install } from '@vltpkg/graph';
|
|
3
|
+
import { saveAllowSkills } from "../allow-skills.js";
|
|
3
4
|
import { parseAddArgs } from "../parse-add-remove-args.js";
|
|
4
5
|
import { planSpecConfigPersist } from "../persist-spec-config.js";
|
|
5
6
|
import { asUnknownSpecPrefix } from "../require-registry.js";
|
|
6
7
|
import { addTypesDeps } from "../save-types.js";
|
|
8
|
+
import { migrateWorkspaces } from "../migrate-workspaces.js";
|
|
7
9
|
import { trackInstall } from "../telemetry.js";
|
|
8
10
|
import { lazyView } from "../view.js";
|
|
9
11
|
export const needsRegistry = true;
|
|
@@ -39,6 +41,9 @@ export const usage = () => commandUsage({
|
|
|
39
41
|
'save-config': {
|
|
40
42
|
description: 'Save registry and git host options given on the command line or via env (e.g. `--registries name=url`) to the project vlt.json, or the user vlt.json with --config=user.',
|
|
41
43
|
},
|
|
44
|
+
'no-migrate-workspaces': {
|
|
45
|
+
description: "Don't save workspaces read from package.json or pnpm-workspace.yaml to vlt.json.",
|
|
46
|
+
},
|
|
42
47
|
workspace: {
|
|
43
48
|
value: '<path|glob>',
|
|
44
49
|
description: 'Limit installation targets to matching workspaces.',
|
|
@@ -60,8 +65,17 @@ export const usage = () => commandUsage({
|
|
|
60
65
|
value: '<query>',
|
|
61
66
|
description: 'Filter which packages are allowed to run lifecycle scripts using DSS query syntax.',
|
|
62
67
|
},
|
|
68
|
+
'allow-skills': {
|
|
69
|
+
value: '<query>',
|
|
70
|
+
description: "Link agent skills of packages matching this DSS query into the project's agent skill dirs. Saved to vlt.json.",
|
|
71
|
+
},
|
|
63
72
|
},
|
|
64
73
|
});
|
|
74
|
+
// link mounts; `unchanged` left out
|
|
75
|
+
const skillsJson = ({ linked, unchanged: _, ...rest }) => ({
|
|
76
|
+
linked: linked.map(s => s.mount),
|
|
77
|
+
...rest,
|
|
78
|
+
});
|
|
65
79
|
export const views = {
|
|
66
80
|
json: i => {
|
|
67
81
|
const added = i.diff?.nodes.add ?? new Set();
|
|
@@ -123,6 +137,11 @@ export const views = {
|
|
|
123
137
|
...(i.persistedConfig ?
|
|
124
138
|
{ persistedConfig: i.persistedConfig }
|
|
125
139
|
: null),
|
|
140
|
+
...(i.migratedWorkspaces ?
|
|
141
|
+
{ migratedWorkspaces: i.migratedWorkspaces }
|
|
142
|
+
: null),
|
|
143
|
+
...(i.skills ? { skills: skillsJson(i.skills) } : null),
|
|
144
|
+
...(i.allowSkills ? { allowSkills: i.allowSkills } : null),
|
|
126
145
|
};
|
|
127
146
|
},
|
|
128
147
|
human: lazyView(async () => (await import('./install/reporter.ts')).InstallReporter),
|
|
@@ -146,20 +165,26 @@ export const command = async (conf) => {
|
|
|
146
165
|
String(conf.get('allow-scripts'))
|
|
147
166
|
: ':not(*)';
|
|
148
167
|
/* c8 ignore stop */
|
|
168
|
+
const allowSkills = conf.get('allow-skills');
|
|
149
169
|
const installStart = Date.now();
|
|
150
|
-
const { buildQueue, graph, diff } = await install({
|
|
170
|
+
const { buildQueue, graph, diff, skills } = await install({
|
|
151
171
|
...conf.options,
|
|
152
172
|
frozenLockfile,
|
|
153
173
|
expectLockfile,
|
|
154
174
|
allowScripts,
|
|
175
|
+
allowSkills,
|
|
176
|
+
skillsDirs: conf.get('skills-dir'),
|
|
155
177
|
lockfileOnly,
|
|
156
178
|
saveExact,
|
|
157
179
|
savePrefix,
|
|
158
180
|
}, add).catch((er) => {
|
|
159
181
|
throw asUnknownSpecPrefix(er);
|
|
160
182
|
});
|
|
183
|
+
const migrated = frozenLockfile || expectLockfile ? undefined : (migrateWorkspaces(conf));
|
|
161
184
|
if (persist)
|
|
162
185
|
await conf.addConfigToFile(persist.which, persist.values);
|
|
186
|
+
// nothing linked on --lockfile-only
|
|
187
|
+
const allowSkillsSave = lockfileOnly ? undefined : await saveAllowSkills(conf);
|
|
163
188
|
/* c8 ignore next 9 - telemetry is best-effort */
|
|
164
189
|
try {
|
|
165
190
|
trackInstall({
|
|
@@ -173,5 +198,8 @@ export const command = async (conf) => {
|
|
|
173
198
|
graph,
|
|
174
199
|
diff,
|
|
175
200
|
...(persist ? { persistedConfig: persist } : null),
|
|
201
|
+
...(migrated ? { migratedWorkspaces: migrated } : null),
|
|
202
|
+
...(skills ? { skills } : null),
|
|
203
|
+
...(allowSkillsSave ? { allowSkills: allowSkillsSave } : null),
|
|
176
204
|
};
|
|
177
205
|
};
|
package/dist/commands/list.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { actual, asNode, humanReadableOutput, jsonOutput, mermaidOutput, GraphModifier, } from '@vltpkg/graph';
|
|
1
|
+
import { actual, asNode, hasSkills, humanReadableOutput, jsonOutput, mermaidOutput, GraphModifier, } from '@vltpkg/graph';
|
|
2
2
|
import { Query } from '@vltpkg/query';
|
|
3
3
|
import { SecurityArchive } from '@vltpkg/security-archive';
|
|
4
4
|
import { error } from '@vltpkg/error-cause';
|
|
@@ -138,6 +138,7 @@ export const command = async (conf) => {
|
|
|
138
138
|
securityArchive,
|
|
139
139
|
hostContexts,
|
|
140
140
|
getAuthHeader,
|
|
141
|
+
hasSkills,
|
|
141
142
|
});
|
|
142
143
|
const { nodes: resultNodes } = await scopeQuery.search(scopeQueryString, {
|
|
143
144
|
signal: new AbortController().signal,
|
|
@@ -190,6 +191,7 @@ export const command = async (conf) => {
|
|
|
190
191
|
securityArchive,
|
|
191
192
|
hostContexts,
|
|
192
193
|
getAuthHeader,
|
|
194
|
+
hasSkills,
|
|
193
195
|
});
|
|
194
196
|
const query = queryString ||
|
|
195
197
|
/* c8 ignore next */
|
package/dist/commands/publish.js
CHANGED
|
@@ -14,14 +14,17 @@ import { sortScopeLocations } from "../sort-scope-locations.js";
|
|
|
14
14
|
import { minimatch } from 'minimatch';
|
|
15
15
|
import { resolveRegistry } from "../require-registry.js";
|
|
16
16
|
import { stderr } from "../output.js";
|
|
17
|
-
|
|
17
|
+
import { getPublishConfig } from "../publish-config.js";
|
|
18
18
|
export const usage = () => commandUsage({
|
|
19
19
|
command: 'publish',
|
|
20
20
|
usage: '',
|
|
21
21
|
description: `Create a tarball from a package and publish it to the configured registry.
|
|
22
22
|
|
|
23
23
|
This command will pack the package in the current directory or specified folder,
|
|
24
|
-
and then upload it to the configured registry
|
|
24
|
+
and then upload it to the configured registry.
|
|
25
|
+
|
|
26
|
+
The registry is the package's \`publishConfig.registry\` if set (no other
|
|
27
|
+
registry config needed), else \`--registry\`, else a configured alias.`,
|
|
25
28
|
options: {
|
|
26
29
|
tag: {
|
|
27
30
|
description: 'Publish the package with the given tag',
|
|
@@ -143,22 +146,34 @@ export const command = async (conf) => {
|
|
|
143
146
|
single = options.packageJson.find(process.cwd()) ?? projectRoot;
|
|
144
147
|
}
|
|
145
148
|
if (single) {
|
|
146
|
-
|
|
149
|
+
const [target] = await resolveTargets([single], conf);
|
|
150
|
+
assert(target);
|
|
151
|
+
return commandSingle(target, conf);
|
|
147
152
|
}
|
|
148
153
|
assert(locations.length > 0, error('No workspaces or query results found'));
|
|
149
154
|
const results = [];
|
|
150
|
-
for (const
|
|
151
|
-
results.push(await commandSingle(
|
|
155
|
+
for (const target of await resolveTargets(locations, conf)) {
|
|
156
|
+
results.push(await commandSingle(target, conf));
|
|
152
157
|
}
|
|
153
158
|
return results;
|
|
154
159
|
};
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
+
/**
|
|
161
|
+
* Registry of every target, before anything runs or publishes.
|
|
162
|
+
* The configured one is only resolved (or prompted for) once.
|
|
163
|
+
*/
|
|
164
|
+
const resolveTargets = async (locations, conf) => {
|
|
165
|
+
let fallback;
|
|
166
|
+
const targets = [];
|
|
167
|
+
for (const location of locations) {
|
|
168
|
+
const manifestPath = conf.options.packageJson.find(location);
|
|
169
|
+
assert(manifestPath, 'No package.json found');
|
|
170
|
+
const manifestDir = dirname(manifestPath);
|
|
171
|
+
const manifest = conf.options.packageJson.read(manifestDir);
|
|
172
|
+
const registry = getPublishConfig(manifest)?.registry ??
|
|
173
|
+
(await (fallback ??= resolveRegistry(conf)));
|
|
174
|
+
targets.push({ manifestDir, registry });
|
|
160
175
|
}
|
|
161
|
-
return
|
|
176
|
+
return targets;
|
|
162
177
|
};
|
|
163
178
|
/** Of several readmes at the package root, npm prefers the markdown one. */
|
|
164
179
|
const README_MARKDOWN_EXTENSION = /\.(?:md|markdown|mdown|mdwn|mkd|mkdn)$/i;
|
|
@@ -182,17 +197,13 @@ const readPublishReadme = (packDir, files) => {
|
|
|
182
197
|
readmeFilename,
|
|
183
198
|
};
|
|
184
199
|
};
|
|
185
|
-
const commandSingle = async (
|
|
186
|
-
const manifestPath = conf.options.packageJson.find(location);
|
|
187
|
-
assert(manifestPath, 'No package.json found');
|
|
188
|
-
const manifestDir = dirname(manifestPath);
|
|
200
|
+
const commandSingle = async ({ manifestDir, registry }, conf) => {
|
|
189
201
|
const manifest = conf.options.packageJson.read(manifestDir);
|
|
190
202
|
assert(!manifest.private, error('Package has been marked as private'));
|
|
191
203
|
const { 'dry-run': dry = false, otp } = conf.options;
|
|
192
204
|
const publishConfig = getPublishConfig(manifest);
|
|
193
205
|
const tag = publishConfig?.tag ?? conf.options.tag;
|
|
194
206
|
const access = publishConfig?.access ?? conf.options.access;
|
|
195
|
-
const registry = publishConfig?.registry ?? (await resolveRegistry(conf));
|
|
196
207
|
const registryUrl = new URL(registryBase(registry));
|
|
197
208
|
const runOptions = {
|
|
198
209
|
cwd: manifestDir,
|
package/dist/commands/query.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { actual, asNode, humanReadableOutput, jsonOutput, mermaidOutput, GraphModifier, } from '@vltpkg/graph';
|
|
1
|
+
import { actual, asNode, hasSkills, humanReadableOutput, jsonOutput, mermaidOutput, GraphModifier, } from '@vltpkg/graph';
|
|
2
2
|
import { Query } from '@vltpkg/query';
|
|
3
3
|
import { stdout } from "../output.js";
|
|
4
4
|
import { error } from '@vltpkg/error-cause';
|
|
@@ -166,6 +166,7 @@ export const command = async (conf) => {
|
|
|
166
166
|
hostContexts,
|
|
167
167
|
diffFiles,
|
|
168
168
|
getAuthHeader,
|
|
169
|
+
hasSkills,
|
|
169
170
|
});
|
|
170
171
|
const { nodes: resultNodes } = await scopeQuery.search(scopeQueryString, {
|
|
171
172
|
signal: new AbortController().signal,
|
|
@@ -231,6 +232,7 @@ export const command = async (conf) => {
|
|
|
231
232
|
hostContexts,
|
|
232
233
|
diffFiles,
|
|
233
234
|
getAuthHeader,
|
|
235
|
+
hasSkills,
|
|
234
236
|
});
|
|
235
237
|
const query = queryString ||
|
|
236
238
|
(graph ? defaultProjectQueryString : defaultLocalScopeQueryString);
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { DepID } from '@vltpkg/dep-id';
|
|
2
|
+
import type { LinkSkillsResult, ListSkillsResult, UnscannedSkills } from '@vltpkg/graph';
|
|
3
|
+
import type { WhichConfig } from '@vltpkg/vlt-json';
|
|
4
|
+
import type { CommandFn, CommandUsage } from '../index.ts';
|
|
5
|
+
import type { ViewOptions } from '../view.ts';
|
|
6
|
+
export type SkillsResult = ({
|
|
7
|
+
action: 'list';
|
|
8
|
+
} & ListSkillsResult) | ({
|
|
9
|
+
action: 'link';
|
|
10
|
+
/** the `allow-skills` applied */
|
|
11
|
+
query: string;
|
|
12
|
+
/** the config file it was saved to, if changed */
|
|
13
|
+
saved?: WhichConfig;
|
|
14
|
+
} & LinkSkillsResult) | {
|
|
15
|
+
action: 'unchanged';
|
|
16
|
+
};
|
|
17
|
+
export declare const needsRegistry = true;
|
|
18
|
+
export declare const usage: CommandUsage;
|
|
19
|
+
export declare const views: {
|
|
20
|
+
readonly human: (r: SkillsResult, o?: ViewOptions) => string;
|
|
21
|
+
readonly json: (r: SkillsResult) => ({
|
|
22
|
+
action: "link";
|
|
23
|
+
/** the `allow-skills` applied */
|
|
24
|
+
query: string;
|
|
25
|
+
/** the config file it was saved to, if changed */
|
|
26
|
+
saved?: WhichConfig;
|
|
27
|
+
} & UnscannedSkills & {
|
|
28
|
+
linked: import("@vltpkg/graph").SkillRow[];
|
|
29
|
+
unchanged: import("@vltpkg/graph").SkillRow[];
|
|
30
|
+
removed: string[];
|
|
31
|
+
conflicts: string[];
|
|
32
|
+
dirs: string[];
|
|
33
|
+
skipped?: string[];
|
|
34
|
+
gitignore?: string[];
|
|
35
|
+
unmatched?: import("@vltpkg/graph").UnmatchedPattern[];
|
|
36
|
+
}) | {
|
|
37
|
+
action: "unchanged";
|
|
38
|
+
} | {
|
|
39
|
+
skills: {
|
|
40
|
+
frontmatterName?: string;
|
|
41
|
+
path: string;
|
|
42
|
+
linked: string[];
|
|
43
|
+
name: string;
|
|
44
|
+
description: string | undefined;
|
|
45
|
+
'dependency-name': string;
|
|
46
|
+
'package-id': DepID;
|
|
47
|
+
}[];
|
|
48
|
+
action: "list";
|
|
49
|
+
unscanned?: string[];
|
|
50
|
+
unscannedReason?: "timeout" | "unscanned";
|
|
51
|
+
dirs: string[];
|
|
52
|
+
skipped?: string[];
|
|
53
|
+
};
|
|
54
|
+
readonly mermaid: (r: SkillsResult) => string;
|
|
55
|
+
};
|
|
56
|
+
export declare const command: CommandFn<SkillsResult>;
|