@vltpkg/cli-sdk 1.0.0-rc.3 → 1.0.0-rc.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/access.d.ts +22 -0
- package/dist/commands/access.js +246 -0
- package/dist/commands/bugs.d.ts +17 -0
- package/dist/commands/bugs.js +163 -0
- package/dist/{esm/commands → commands}/build.d.ts +0 -1
- package/dist/{esm/commands → commands}/build.js +0 -1
- package/dist/{esm/commands → commands}/cache.d.ts +0 -1
- package/dist/{esm/commands → commands}/cache.js +0 -1
- package/dist/{esm/commands → commands}/ci.d.ts +0 -1
- package/dist/{esm/commands → commands}/ci.js +11 -3
- package/dist/{esm/commands → commands}/config.d.ts +0 -1
- package/dist/{esm/commands → commands}/config.js +6 -1
- package/dist/commands/create.d.ts +8 -0
- package/dist/commands/create.js +102 -0
- package/dist/commands/deprecate.d.ts +13 -0
- package/dist/commands/deprecate.js +139 -0
- package/dist/commands/dist-tag.d.ts +21 -0
- package/dist/commands/dist-tag.js +177 -0
- package/dist/{esm/commands → commands}/docs.d.ts +0 -1
- package/dist/{esm/commands → commands}/docs.js +2 -3
- package/dist/{esm/commands → commands}/exec-cache.d.ts +0 -1
- package/dist/{esm/commands → commands}/exec-cache.js +0 -1
- package/dist/{esm/commands → commands}/exec-local.d.ts +0 -1
- package/dist/{esm/commands → commands}/exec-local.js +23 -1
- package/dist/{esm/commands → commands}/exec.d.ts +0 -1
- package/dist/{esm/commands → commands}/exec.js +84 -10
- package/dist/{esm/commands → commands}/help.d.ts +0 -1
- package/dist/{esm/commands → commands}/help.js +5 -1
- package/dist/{esm/commands → commands}/init.d.ts +0 -1
- package/dist/{esm/commands → commands}/init.js +31 -10
- package/dist/{esm/commands → commands}/install/reporter.d.ts +0 -1
- package/dist/{esm/commands → commands}/install/reporter.js +0 -1
- package/dist/{esm/commands → commands}/install.d.ts +21 -3
- package/dist/commands/install.js +140 -0
- package/dist/{esm/commands → commands}/list.d.ts +4 -2
- package/dist/{esm/commands → commands}/list.js +8 -10
- package/dist/{esm/commands → commands}/login.d.ts +0 -1
- package/dist/{esm/commands → commands}/login.js +10 -1
- package/dist/{esm/commands/token.d.ts → commands/logout.d.ts} +0 -1
- package/dist/{esm/commands → commands}/logout.js +10 -1
- package/dist/{esm/commands → commands}/pack.d.ts +0 -1
- package/dist/{esm/commands → commands}/pack.js +90 -32
- package/dist/commands/ping.d.ts +17 -0
- package/dist/commands/ping.js +114 -0
- package/dist/{esm/commands → commands}/pkg.d.ts +0 -1
- package/dist/{esm/commands → commands}/pkg.js +27 -1
- package/dist/commands/profile.d.ts +13 -0
- package/dist/commands/profile.js +104 -0
- package/dist/{esm/commands → commands}/publish.d.ts +1 -2
- package/dist/{esm/commands → commands}/publish.js +63 -12
- package/dist/{esm/commands → commands}/query.d.ts +4 -2
- package/dist/{esm/commands → commands}/query.js +12 -10
- package/dist/commands/repo.d.ts +17 -0
- package/dist/commands/repo.js +157 -0
- package/dist/{esm/commands → commands}/run-exec.d.ts +0 -1
- package/dist/commands/run-exec.js +40 -0
- package/dist/{esm/commands → commands}/run.d.ts +0 -1
- package/dist/{esm/commands → commands}/run.js +27 -1
- package/dist/commands/token.d.ts +31 -0
- package/dist/commands/token.js +186 -0
- package/dist/{esm/commands → commands}/uninstall.d.ts +0 -1
- package/dist/{esm/commands → commands}/uninstall.js +16 -3
- package/dist/commands/unpublish.d.ts +15 -0
- package/dist/commands/unpublish.js +200 -0
- package/dist/{esm/commands → commands}/update.d.ts +0 -1
- package/dist/{esm/commands → commands}/update.js +6 -1
- package/dist/{esm/commands → commands}/version.d.ts +0 -1
- package/dist/{esm/commands → commands}/version.js +27 -1
- package/dist/commands/view.d.ts +22 -0
- package/dist/commands/view.js +334 -0
- package/dist/{esm/commands → commands}/whoami.d.ts +0 -1
- package/dist/{esm/commands → commands}/whoami.js +10 -1
- package/dist/{esm/config → config}/definition.d.ts +39 -19
- package/dist/{esm/config → config}/definition.js +74 -39
- package/dist/{esm/config → config}/index.d.ts +0 -1
- package/dist/{esm/config → config}/index.js +37 -2
- package/dist/{esm/config → config}/merge.d.ts +0 -1
- package/dist/{esm/config → config}/merge.js +0 -1
- package/dist/{esm/config → config}/usage.d.ts +0 -1
- package/dist/{esm/config → config}/usage.js +0 -1
- package/dist/{esm/custom-help.d.ts → custom-help.d.ts} +0 -1
- package/dist/{esm/custom-help.js → custom-help.js} +35 -9
- package/dist/{esm/exec-command.d.ts → exec-command.d.ts} +0 -1
- package/dist/{esm/exec-command.js → exec-command.js} +14 -8
- package/dist/{esm/index.d.ts → index.d.ts} +0 -1
- package/dist/{esm/index.js → index.js} +1 -2
- package/dist/{esm/load-command.d.ts → load-command.d.ts} +0 -1
- package/dist/{esm/load-command.js → load-command.js} +0 -1
- package/dist/mermaid-image-view.d.ts +18 -0
- package/dist/mermaid-image-view.js +36 -0
- package/dist/{esm/output.d.ts → output.d.ts} +2 -2
- package/dist/{esm/output.js → output.js} +55 -2
- package/dist/{esm/pack-tarball.d.ts → pack-tarball.d.ts} +15 -1
- package/dist/{esm/pack-tarball.js → pack-tarball.js} +133 -91
- package/dist/{esm/parse-add-remove-args.d.ts → parse-add-remove-args.d.ts} +9 -3
- package/dist/{esm/parse-add-remove-args.js → parse-add-remove-args.js} +43 -11
- package/dist/{esm/print-err.d.ts → print-err.d.ts} +0 -1
- package/dist/{esm/print-err.js → print-err.js} +18 -3
- package/dist/query-diff-files.d.ts +17 -0
- package/dist/query-diff-files.js +63 -0
- package/dist/{esm/query-host-contexts.d.ts → query-host-contexts.d.ts} +0 -1
- package/dist/{esm/query-host-contexts.js → query-host-contexts.js} +8 -7
- package/dist/{esm/read-password.d.ts → read-password.d.ts} +0 -1
- package/dist/{esm/read-password.js → read-password.js} +0 -1
- package/dist/read-project-folders.d.ts +17 -0
- package/dist/read-project-folders.js +100 -0
- package/dist/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/telemetry.d.ts +58 -0
- package/dist/telemetry.js +170 -0
- package/dist/{esm/view.d.ts → view.d.ts} +0 -1
- package/dist/{esm/view.js → view.js} +1 -2
- package/package.json +69 -83
- package/dist/esm/commands/build.d.ts.map +0 -1
- package/dist/esm/commands/build.js.map +0 -1
- package/dist/esm/commands/cache.d.ts.map +0 -1
- package/dist/esm/commands/cache.js.map +0 -1
- package/dist/esm/commands/ci.d.ts.map +0 -1
- package/dist/esm/commands/ci.js.map +0 -1
- package/dist/esm/commands/config.d.ts.map +0 -1
- package/dist/esm/commands/config.js.map +0 -1
- package/dist/esm/commands/docs.d.ts.map +0 -1
- package/dist/esm/commands/docs.js.map +0 -1
- package/dist/esm/commands/exec-cache.d.ts.map +0 -1
- package/dist/esm/commands/exec-cache.js.map +0 -1
- package/dist/esm/commands/exec-local.d.ts.map +0 -1
- package/dist/esm/commands/exec-local.js.map +0 -1
- package/dist/esm/commands/exec.d.ts.map +0 -1
- package/dist/esm/commands/exec.js.map +0 -1
- package/dist/esm/commands/help.d.ts.map +0 -1
- package/dist/esm/commands/help.js.map +0 -1
- package/dist/esm/commands/init.d.ts.map +0 -1
- package/dist/esm/commands/init.js.map +0 -1
- package/dist/esm/commands/install/reporter.d.ts.map +0 -1
- package/dist/esm/commands/install/reporter.js.map +0 -1
- package/dist/esm/commands/install.d.ts.map +0 -1
- package/dist/esm/commands/install.js +0 -45
- package/dist/esm/commands/install.js.map +0 -1
- package/dist/esm/commands/list.d.ts.map +0 -1
- package/dist/esm/commands/list.js.map +0 -1
- package/dist/esm/commands/login.d.ts.map +0 -1
- package/dist/esm/commands/login.js.map +0 -1
- package/dist/esm/commands/logout.d.ts +0 -4
- package/dist/esm/commands/logout.d.ts.map +0 -1
- package/dist/esm/commands/logout.js.map +0 -1
- package/dist/esm/commands/pack.d.ts.map +0 -1
- package/dist/esm/commands/pack.js.map +0 -1
- package/dist/esm/commands/pkg.d.ts.map +0 -1
- package/dist/esm/commands/pkg.js.map +0 -1
- package/dist/esm/commands/publish.d.ts.map +0 -1
- package/dist/esm/commands/publish.js.map +0 -1
- package/dist/esm/commands/query.d.ts.map +0 -1
- package/dist/esm/commands/query.js.map +0 -1
- package/dist/esm/commands/run-exec.d.ts.map +0 -1
- package/dist/esm/commands/run-exec.js +0 -14
- package/dist/esm/commands/run-exec.js.map +0 -1
- package/dist/esm/commands/run.d.ts.map +0 -1
- package/dist/esm/commands/run.js.map +0 -1
- package/dist/esm/commands/serve.d.ts +0 -14
- package/dist/esm/commands/serve.d.ts.map +0 -1
- package/dist/esm/commands/serve.js +0 -103
- package/dist/esm/commands/serve.js.map +0 -1
- package/dist/esm/commands/token.d.ts.map +0 -1
- package/dist/esm/commands/token.js +0 -30
- package/dist/esm/commands/token.js.map +0 -1
- package/dist/esm/commands/uninstall.d.ts.map +0 -1
- package/dist/esm/commands/uninstall.js.map +0 -1
- package/dist/esm/commands/update.d.ts.map +0 -1
- package/dist/esm/commands/update.js.map +0 -1
- package/dist/esm/commands/version.d.ts.map +0 -1
- package/dist/esm/commands/version.js.map +0 -1
- package/dist/esm/commands/whoami.d.ts.map +0 -1
- package/dist/esm/commands/whoami.js.map +0 -1
- package/dist/esm/config/definition.d.ts.map +0 -1
- package/dist/esm/config/definition.js.map +0 -1
- package/dist/esm/config/index.d.ts.map +0 -1
- package/dist/esm/config/index.js.map +0 -1
- package/dist/esm/config/merge.d.ts.map +0 -1
- package/dist/esm/config/merge.js.map +0 -1
- package/dist/esm/config/usage.d.ts.map +0 -1
- package/dist/esm/config/usage.js.map +0 -1
- package/dist/esm/custom-help.d.ts.map +0 -1
- package/dist/esm/custom-help.js.map +0 -1
- package/dist/esm/exec-command.d.ts.map +0 -1
- package/dist/esm/exec-command.js.map +0 -1
- package/dist/esm/index.d.ts.map +0 -1
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/load-command.d.ts.map +0 -1
- package/dist/esm/load-command.js.map +0 -1
- package/dist/esm/output.d.ts.map +0 -1
- package/dist/esm/output.js.map +0 -1
- package/dist/esm/pack-tarball.d.ts.map +0 -1
- package/dist/esm/pack-tarball.js.map +0 -1
- package/dist/esm/package.json +0 -3
- package/dist/esm/parse-add-remove-args.d.ts.map +0 -1
- package/dist/esm/parse-add-remove-args.js.map +0 -1
- package/dist/esm/print-err.d.ts.map +0 -1
- package/dist/esm/print-err.js.map +0 -1
- package/dist/esm/query-host-contexts.d.ts.map +0 -1
- package/dist/esm/query-host-contexts.js.map +0 -1
- package/dist/esm/read-password.d.ts.map +0 -1
- package/dist/esm/read-password.js.map +0 -1
- package/dist/esm/start-gui.d.ts +0 -10
- package/dist/esm/start-gui.d.ts.map +0 -1
- package/dist/esm/start-gui.js +0 -60
- package/dist/esm/start-gui.js.map +0 -1
- package/dist/esm/view.d.ts.map +0 -1
- package/dist/esm/view.js.map +0 -1
|
@@ -4,6 +4,16 @@ import { defaultView } from "./config/definition.js";
|
|
|
4
4
|
import { printErr, formatOptions } from "./print-err.js";
|
|
5
5
|
import { isViewClass } from "./view.js";
|
|
6
6
|
import { generateDefaultHelp, generateFullHelp, } from "./custom-help.js";
|
|
7
|
+
import { flush as flushTelemetry, trackCommand, trackError, } from "./telemetry.js";
|
|
8
|
+
/* c8 ignore start - CI env detection is a best-effort heuristic */
|
|
9
|
+
const isCI = () => !!(process.env.CI ||
|
|
10
|
+
process.env.GITHUB_ACTIONS ||
|
|
11
|
+
process.env.GITLAB_CI ||
|
|
12
|
+
process.env.CIRCLECI ||
|
|
13
|
+
process.env.JENKINS_URL ||
|
|
14
|
+
process.env.BUILDKITE ||
|
|
15
|
+
process.env.TRAVIS);
|
|
16
|
+
/* c8 ignore stop */
|
|
7
17
|
const supportsColor = (stream) => {
|
|
8
18
|
const res = createSupportsColor(stream, { sniffFlags: false });
|
|
9
19
|
if (res === false)
|
|
@@ -77,7 +87,9 @@ const startView = (conf, opts, views, { start } = { start: Date.now() }) => {
|
|
|
77
87
|
* the user-requested view, or the default if the user requested a view
|
|
78
88
|
* that is not defined for this command.
|
|
79
89
|
*/
|
|
80
|
-
export const outputCommand = async (cliCommand, conf, { start } = {
|
|
90
|
+
export const outputCommand = async (cliCommand, conf, { start, vltVersion } = {
|
|
91
|
+
start: Date.now(),
|
|
92
|
+
}) => {
|
|
81
93
|
const { usage, views, command } = cliCommand;
|
|
82
94
|
const stdoutColor = conf.values.color ?? supportsColor(process.stdout);
|
|
83
95
|
const stderrColor = conf.values.color ?? supportsColor(process.stderr);
|
|
@@ -102,8 +114,21 @@ export const outputCommand = async (cliCommand, conf, { start } = { start: Date.
|
|
|
102
114
|
const { onDone, onError } = startView(conf,
|
|
103
115
|
// assume views will always output to stdout so use color support from there
|
|
104
116
|
{ colors: stdoutColor }, views, { start });
|
|
117
|
+
const telemetryEnabled = conf.values.telemetry;
|
|
118
|
+
const commandName = conf.command;
|
|
105
119
|
try {
|
|
106
120
|
const output = await onDone(await command(conf));
|
|
121
|
+
const duration_ms = Date.now() - start;
|
|
122
|
+
trackCommand({
|
|
123
|
+
command: commandName,
|
|
124
|
+
duration_ms,
|
|
125
|
+
success: true,
|
|
126
|
+
node_version: process.version,
|
|
127
|
+
vlt_version: vltVersion ?? 'unknown',
|
|
128
|
+
os: process.platform,
|
|
129
|
+
arch: process.arch,
|
|
130
|
+
ci: isCI(),
|
|
131
|
+
}, telemetryEnabled);
|
|
107
132
|
if (output !== undefined && conf.values.view !== 'silent') {
|
|
108
133
|
stdout(conf.values.view === 'json' ?
|
|
109
134
|
JSON.stringify(output, null, 2)
|
|
@@ -112,10 +137,39 @@ export const outputCommand = async (cliCommand, conf, { start } = { start: Date.
|
|
|
112
137
|
colors: stdoutColor,
|
|
113
138
|
}, output));
|
|
114
139
|
}
|
|
140
|
+
// Await the flush so pending telemetry events are sent before
|
|
141
|
+
// the process exits. The flush has a built-in timeout cap
|
|
142
|
+
// (SHUTDOWN_TIMEOUT_MS) so it will never block for long, and the
|
|
143
|
+
// timer is unreffed so even if this is not awaited the process
|
|
144
|
+
// can still exit promptly.
|
|
145
|
+
await flushTelemetry();
|
|
115
146
|
}
|
|
116
147
|
catch (err) {
|
|
117
148
|
onError?.(err);
|
|
118
149
|
process.exitCode ||= 1;
|
|
150
|
+
const duration_ms = Date.now() - start;
|
|
151
|
+
trackCommand({
|
|
152
|
+
command: commandName,
|
|
153
|
+
duration_ms,
|
|
154
|
+
success: false,
|
|
155
|
+
node_version: process.version,
|
|
156
|
+
vlt_version: vltVersion ?? 'unknown',
|
|
157
|
+
os: process.platform,
|
|
158
|
+
arch: process.arch,
|
|
159
|
+
ci: isCI(),
|
|
160
|
+
}, telemetryEnabled);
|
|
161
|
+
const errorCode = (err instanceof Error &&
|
|
162
|
+
err.cause &&
|
|
163
|
+
typeof err.cause === 'object' &&
|
|
164
|
+
'code' in err.cause &&
|
|
165
|
+
typeof err.cause.code === 'string') ?
|
|
166
|
+
err.cause.code
|
|
167
|
+
: undefined;
|
|
168
|
+
trackError({
|
|
169
|
+
command: commandName,
|
|
170
|
+
error_code: errorCode,
|
|
171
|
+
}, telemetryEnabled);
|
|
172
|
+
await flushTelemetry();
|
|
119
173
|
printErr(err, usage, stderr, {
|
|
120
174
|
...formatOptions,
|
|
121
175
|
colors: stderrColor,
|
|
@@ -123,4 +177,3 @@ export const outputCommand = async (cliCommand, conf, { start } = { start: Date.
|
|
|
123
177
|
process.exit(process.exitCode);
|
|
124
178
|
}
|
|
125
179
|
};
|
|
126
|
-
//# sourceMappingURL=output.js.map
|
|
@@ -10,7 +10,22 @@ export type PackTarballResult = {
|
|
|
10
10
|
files: string[];
|
|
11
11
|
integrity?: string;
|
|
12
12
|
shasum?: string;
|
|
13
|
+
/** The manifest used for packing (may differ from input when publishConfig.directory is set). */
|
|
14
|
+
resolvedManifest: NormalizedManifest;
|
|
13
15
|
};
|
|
16
|
+
/**
|
|
17
|
+
* Build the tar filter function for packing.
|
|
18
|
+
*
|
|
19
|
+
* Follows npm's precedence rules:
|
|
20
|
+
* 1. `files` field in package.json → allowlist (ignore files are not read)
|
|
21
|
+
* 2. `.npmignore` → denylist (`.gitignore` is NOT read)
|
|
22
|
+
* 3. `.gitignore` → fallback denylist when no `.npmignore` exists
|
|
23
|
+
*
|
|
24
|
+
* Regardless of mode, always-excluded files (lockfiles, .git, node_modules,
|
|
25
|
+
* .npmrc, vlt.json, etc.) are excluded and always-included files (package.json,
|
|
26
|
+
* README, LICENSE, etc.) are included.
|
|
27
|
+
*/
|
|
28
|
+
export declare const buildPackFilter: (manifest: NormalizedManifest, packDir: string) => ((path: string) => boolean);
|
|
14
29
|
/**
|
|
15
30
|
* Create a tarball from a package directory
|
|
16
31
|
* @param {NormalizedManifest} manifest - The manifest of the package to pack
|
|
@@ -19,4 +34,3 @@ export type PackTarballResult = {
|
|
|
19
34
|
* @returns {Promise<PackTarballResult>} The manifest, filename, and tarball data (unless dry run)
|
|
20
35
|
*/
|
|
21
36
|
export declare const packTarball: (manifest: NormalizedManifest, dir: string, config: LoadedConfig) => Promise<PackTarballResult>;
|
|
22
|
-
//# sourceMappingURL=pack-tarball.d.ts.map
|
|
@@ -3,10 +3,11 @@ import { minimatch } from 'minimatch';
|
|
|
3
3
|
import { error } from '@vltpkg/error-cause';
|
|
4
4
|
import * as ssri from 'ssri';
|
|
5
5
|
import assert from 'node:assert';
|
|
6
|
-
import { existsSync, statSync } from 'node:fs';
|
|
6
|
+
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
7
7
|
import { Spec } from '@vltpkg/spec';
|
|
8
8
|
import { join } from 'node:path';
|
|
9
9
|
import { parse, stringify } from 'polite-json';
|
|
10
|
+
import ignore from 'ignore';
|
|
10
11
|
/**
|
|
11
12
|
* Replace workspace: and catalog: specs with actual versions
|
|
12
13
|
* @param {NormalizedManifest} manifest_ - The manifest to process
|
|
@@ -82,6 +83,121 @@ const replaceWorkspaceAndCatalogSpecs = (manifest_, config) => {
|
|
|
82
83
|
}
|
|
83
84
|
return manifest;
|
|
84
85
|
};
|
|
86
|
+
const alwaysExcludePatterns = [
|
|
87
|
+
/^\.?\/?\.git(\/|$)/,
|
|
88
|
+
/^\.?\/?node_modules(\/|$)/,
|
|
89
|
+
/^\.?\/?\.nyc_output(\/|$)/,
|
|
90
|
+
/^\.?\/?coverage(\/|$)/,
|
|
91
|
+
/^\.?\/?\.vscode(\/|$)/,
|
|
92
|
+
/^\.?\/?\.idea(\/|$)/,
|
|
93
|
+
/^\.?\/?\.DS_Store$/,
|
|
94
|
+
/^\.?\/?\.npmrc$/,
|
|
95
|
+
/^\.?\/?\.gitignore$/,
|
|
96
|
+
/^\.?\/?\.npmignore$/,
|
|
97
|
+
/^\.?\/?\.editorconfig$/,
|
|
98
|
+
/^\.?\/?package-lock\.json$/,
|
|
99
|
+
/^\.?\/?yarn\.lock$/,
|
|
100
|
+
/^\.?\/?pnpm-lock\.yaml$/,
|
|
101
|
+
/^\.?\/?bun\.lockb$/,
|
|
102
|
+
/^\.?\/?bun\.lock$/,
|
|
103
|
+
/^\.?\/?vlt-lock\.json$/,
|
|
104
|
+
/^\.?\/?vlt\.json$/,
|
|
105
|
+
/~$/,
|
|
106
|
+
/\.swp$/,
|
|
107
|
+
/\.tgz$/,
|
|
108
|
+
];
|
|
109
|
+
const alwaysIncludePatterns = [
|
|
110
|
+
/^README(\..*)?$/i,
|
|
111
|
+
/^CHANGELOG(\..*)?$/i,
|
|
112
|
+
/^HISTORY(\..*)?$/i,
|
|
113
|
+
/^LICENSE(\..*)?$/i,
|
|
114
|
+
/^LICENCE(\..*)?$/i,
|
|
115
|
+
];
|
|
116
|
+
/**
|
|
117
|
+
* Read an ignore file (.npmignore or .gitignore) and return its contents,
|
|
118
|
+
* or undefined if the file does not exist.
|
|
119
|
+
*/
|
|
120
|
+
const readIgnoreFile = (dir, name) => {
|
|
121
|
+
const filePath = join(dir, name);
|
|
122
|
+
if (!existsSync(filePath))
|
|
123
|
+
return undefined;
|
|
124
|
+
return readFileSync(filePath, 'utf8');
|
|
125
|
+
};
|
|
126
|
+
/**
|
|
127
|
+
* Build the tar filter function for packing.
|
|
128
|
+
*
|
|
129
|
+
* Follows npm's precedence rules:
|
|
130
|
+
* 1. `files` field in package.json → allowlist (ignore files are not read)
|
|
131
|
+
* 2. `.npmignore` → denylist (`.gitignore` is NOT read)
|
|
132
|
+
* 3. `.gitignore` → fallback denylist when no `.npmignore` exists
|
|
133
|
+
*
|
|
134
|
+
* Regardless of mode, always-excluded files (lockfiles, .git, node_modules,
|
|
135
|
+
* .npmrc, vlt.json, etc.) are excluded and always-included files (package.json,
|
|
136
|
+
* README, LICENSE, etc.) are included.
|
|
137
|
+
*/
|
|
138
|
+
export const buildPackFilter = (manifest, packDir) => {
|
|
139
|
+
const manifestWithFiles = manifest;
|
|
140
|
+
const hasFilesField = Array.isArray(manifestWithFiles.files) &&
|
|
141
|
+
manifestWithFiles.files.length > 0;
|
|
142
|
+
const hasEmptyFilesField = Array.isArray(manifestWithFiles.files) &&
|
|
143
|
+
manifestWithFiles.files.length === 0;
|
|
144
|
+
// Build ignore matcher from .npmignore or .gitignore (only when no files field)
|
|
145
|
+
let ig;
|
|
146
|
+
if (!hasFilesField && !hasEmptyFilesField) {
|
|
147
|
+
const npmignoreContent = readIgnoreFile(packDir, '.npmignore');
|
|
148
|
+
if (npmignoreContent !== undefined) {
|
|
149
|
+
ig = ignore().add(npmignoreContent);
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
const gitignoreContent = readIgnoreFile(packDir, '.gitignore');
|
|
153
|
+
if (gitignoreContent !== undefined) {
|
|
154
|
+
ig = ignore().add(gitignoreContent);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return (path) => {
|
|
159
|
+
const normalizedPath = path.replace(/^\.\//, '');
|
|
160
|
+
if (path === '.' || normalizedPath === '') {
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
if (alwaysExcludePatterns.some(pattern => pattern.test(normalizedPath))) {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
if (alwaysIncludePatterns.some(pattern => pattern.test(normalizedPath))) {
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
if (normalizedPath === 'package.json') {
|
|
170
|
+
return true;
|
|
171
|
+
}
|
|
172
|
+
// files field: allowlist mode
|
|
173
|
+
if (hasEmptyFilesField) {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
if (hasFilesField && manifestWithFiles.files) {
|
|
177
|
+
return manifestWithFiles.files.some((pattern) => {
|
|
178
|
+
if (pattern.endsWith('/')) {
|
|
179
|
+
const dirName = pattern.slice(0, -1);
|
|
180
|
+
const globPattern = pattern.replace(/\/$/, '/**');
|
|
181
|
+
const matchesDir = normalizedPath === dirName;
|
|
182
|
+
const matchesContents = minimatch(normalizedPath, globPattern, { dot: true });
|
|
183
|
+
return matchesDir || matchesContents;
|
|
184
|
+
}
|
|
185
|
+
const directMatch = minimatch(normalizedPath, pattern, {
|
|
186
|
+
dot: true,
|
|
187
|
+
});
|
|
188
|
+
const isParentDir = pattern.includes('/') &&
|
|
189
|
+
pattern.startsWith(normalizedPath + '/');
|
|
190
|
+
const isChildOfPattern = minimatch(normalizedPath, pattern + '/**', { dot: true });
|
|
191
|
+
return directMatch || isParentDir || isChildOfPattern;
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
// Ignore-file mode: apply .npmignore or .gitignore deny patterns
|
|
195
|
+
if (ig?.ignores(normalizedPath)) {
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
return true;
|
|
199
|
+
};
|
|
200
|
+
};
|
|
85
201
|
/**
|
|
86
202
|
* Create a tarball from a package directory
|
|
87
203
|
* @param {NormalizedManifest} manifest - The manifest of the package to pack
|
|
@@ -91,21 +207,25 @@ const replaceWorkspaceAndCatalogSpecs = (manifest_, config) => {
|
|
|
91
207
|
*/
|
|
92
208
|
export const packTarball = async (manifest, dir, config) => {
|
|
93
209
|
let packDir = dir;
|
|
94
|
-
// Check if publishDirectory is configured
|
|
95
|
-
const
|
|
210
|
+
// Check if publishDirectory is configured via CLI flag or package.json publishConfig.directory
|
|
211
|
+
const cliPublishDir = config.get('publish-directory');
|
|
212
|
+
const manifestPublishDir = manifest.publishConfig?.directory;
|
|
213
|
+
const publishDirectory = cliPublishDir ?? manifestPublishDir;
|
|
96
214
|
if (publishDirectory) {
|
|
215
|
+
// CLI flag paths are used as-is; publishConfig.directory is relative to the package dir
|
|
216
|
+
const resolvedPublishDir = cliPublishDir ? publishDirectory : join(dir, publishDirectory);
|
|
97
217
|
// Validate that the publish directory exists and is a directory
|
|
98
|
-
assert(existsSync(
|
|
99
|
-
found:
|
|
218
|
+
assert(existsSync(resolvedPublishDir), error(`Publish directory does not exist: ${resolvedPublishDir}`, {
|
|
219
|
+
found: resolvedPublishDir,
|
|
100
220
|
}));
|
|
101
|
-
assert(statSync(
|
|
102
|
-
found:
|
|
221
|
+
assert(statSync(resolvedPublishDir).isDirectory(), error(`Publish directory is not a directory: ${resolvedPublishDir}`, {
|
|
222
|
+
found: resolvedPublishDir,
|
|
103
223
|
wanted: 'directory',
|
|
104
224
|
}));
|
|
105
|
-
if (existsSync(join(
|
|
106
|
-
manifest = config.options.packageJson.read(
|
|
225
|
+
if (existsSync(join(resolvedPublishDir, 'package.json'))) {
|
|
226
|
+
manifest = config.options.packageJson.read(resolvedPublishDir);
|
|
107
227
|
}
|
|
108
|
-
packDir =
|
|
228
|
+
packDir = resolvedPublishDir;
|
|
109
229
|
}
|
|
110
230
|
assert(manifest.name && manifest.version, error('Package must have a name and version'));
|
|
111
231
|
const processedManifest = replaceWorkspaceAndCatalogSpecs(manifest, config);
|
|
@@ -113,91 +233,13 @@ export const packTarball = async (manifest, dir, config) => {
|
|
|
113
233
|
const tarballName = `${manifest.name}-${manifest.version}.tgz`;
|
|
114
234
|
try {
|
|
115
235
|
config.options.packageJson.write(packDir, processedManifest);
|
|
236
|
+
const packFilter = buildPackFilter(manifest, packDir);
|
|
116
237
|
const tarballData = await tarCreate({
|
|
117
238
|
cwd: packDir,
|
|
118
239
|
gzip: true,
|
|
119
240
|
portable: true,
|
|
120
241
|
prefix: 'package/',
|
|
121
|
-
filter:
|
|
122
|
-
// Normalize path - remove leading './'
|
|
123
|
-
const normalizedPath = path.replace(/^\.\//, '');
|
|
124
|
-
// Always include root directory
|
|
125
|
-
if (path === '.' || normalizedPath === '') {
|
|
126
|
-
return true;
|
|
127
|
-
}
|
|
128
|
-
// Always exclude certain files/directories
|
|
129
|
-
const alwaysExcludePatterns = [
|
|
130
|
-
/^\.?\/?\.git(\/|$)/,
|
|
131
|
-
/^\.?\/?node_modules(\/|$)/,
|
|
132
|
-
/^\.?\/?\.nyc_output(\/|$)/,
|
|
133
|
-
/^\.?\/?coverage(\/|$)/,
|
|
134
|
-
/^\.?\/?\.DS_Store$/,
|
|
135
|
-
/^\.?\/?\.npmrc$/,
|
|
136
|
-
/^\.?\/?package-lock\.json$/,
|
|
137
|
-
/^\.?\/?yarn\.lock$/,
|
|
138
|
-
/^\.?\/?pnpm-lock\.yaml$/,
|
|
139
|
-
/^\.?\/?bun\.lockb$/,
|
|
140
|
-
/^\.?\/?bun\.lock$/,
|
|
141
|
-
/^\.?\/?vlt-lock\.json$/,
|
|
142
|
-
/~$/,
|
|
143
|
-
/\.swp$/,
|
|
144
|
-
];
|
|
145
|
-
if (alwaysExcludePatterns.some(pattern => pattern.test(normalizedPath))) {
|
|
146
|
-
return false;
|
|
147
|
-
}
|
|
148
|
-
// Always include certain files
|
|
149
|
-
const alwaysIncludePatterns = [
|
|
150
|
-
/^README(\..*)?$/i,
|
|
151
|
-
/^CHANGELOG(\..*)?$/i,
|
|
152
|
-
/^HISTORY(\..*)?$/i,
|
|
153
|
-
/^LICENSE(\..*)?$/i,
|
|
154
|
-
/^LICENCE(\..*)?$/i,
|
|
155
|
-
];
|
|
156
|
-
if (alwaysIncludePatterns.some(pattern => pattern.test(normalizedPath))) {
|
|
157
|
-
return true;
|
|
158
|
-
}
|
|
159
|
-
// Always include package.json
|
|
160
|
-
if (normalizedPath === 'package.json') {
|
|
161
|
-
return true;
|
|
162
|
-
}
|
|
163
|
-
// If files field is specified in package.json, use it for inclusion
|
|
164
|
-
const manifestWithFiles = manifest;
|
|
165
|
-
if (manifestWithFiles.files &&
|
|
166
|
-
Array.isArray(manifestWithFiles.files)) {
|
|
167
|
-
// Empty files array means exclude everything except always-included files
|
|
168
|
-
if (manifestWithFiles.files.length === 0) {
|
|
169
|
-
return false;
|
|
170
|
-
}
|
|
171
|
-
return manifestWithFiles.files.some((pattern) => {
|
|
172
|
-
if (pattern.endsWith('/')) {
|
|
173
|
-
const dirName = pattern.slice(0, -1);
|
|
174
|
-
const globPattern = pattern.replace(/\/$/, '/**');
|
|
175
|
-
const matchesDir = normalizedPath === dirName;
|
|
176
|
-
const matchesContents = minimatch(normalizedPath, globPattern, {
|
|
177
|
-
dot: true,
|
|
178
|
-
});
|
|
179
|
-
return matchesDir || matchesContents;
|
|
180
|
-
}
|
|
181
|
-
// File pattern: check direct match and if this path is a directory that could contain the pattern
|
|
182
|
-
const directMatch = minimatch(normalizedPath, pattern, {
|
|
183
|
-
dot: true,
|
|
184
|
-
});
|
|
185
|
-
// Check if this path is a directory that could contain the pattern
|
|
186
|
-
const isParentDir = pattern.includes('/') &&
|
|
187
|
-
pattern.startsWith(normalizedPath + '/');
|
|
188
|
-
return directMatch || isParentDir;
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
// Default behavior when no files field - exclude common development files
|
|
192
|
-
const defaultExcludePatterns = [
|
|
193
|
-
/^\.?\/?\.vscode(\/|$)/,
|
|
194
|
-
/^\.?\/?\.idea(\/|$)/,
|
|
195
|
-
/^\.?\/?\.gitignore$/,
|
|
196
|
-
/^\.?\/?\.npmignore$/,
|
|
197
|
-
/^\.?\/?\.editorconfig$/,
|
|
198
|
-
];
|
|
199
|
-
return !defaultExcludePatterns.some(pattern => pattern.test(normalizedPath));
|
|
200
|
-
},
|
|
242
|
+
filter: packFilter,
|
|
201
243
|
}, ['.']).concat();
|
|
202
244
|
let unpackedSize = 0;
|
|
203
245
|
const files = [];
|
|
@@ -239,6 +281,7 @@ export const packTarball = async (manifest, dir, config) => {
|
|
|
239
281
|
files,
|
|
240
282
|
integrity,
|
|
241
283
|
shasum,
|
|
284
|
+
resolvedManifest: processedManifest,
|
|
242
285
|
};
|
|
243
286
|
}
|
|
244
287
|
finally {
|
|
@@ -246,4 +289,3 @@ export const packTarball = async (manifest, dir, config) => {
|
|
|
246
289
|
config.options.packageJson.write(packDir, manifest);
|
|
247
290
|
}
|
|
248
291
|
};
|
|
249
|
-
//# sourceMappingURL=pack-tarball.js.map
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { PathScurry } from 'path-scurry';
|
|
1
2
|
import type { AddImportersDependenciesMap, RemoveImportersDependenciesMap } from '@vltpkg/graph';
|
|
2
3
|
import type { Monorepo } from '@vltpkg/workspaces';
|
|
3
4
|
import type { LoadedConfig } from './config/index.ts';
|
|
@@ -17,6 +18,11 @@ export type WorkspaceTypes = {
|
|
|
17
18
|
workspace?: string[];
|
|
18
19
|
'workspace-group'?: string[];
|
|
19
20
|
};
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Parses the positional arguments into {@link AddImportersDependenciesMap}.
|
|
23
|
+
*/
|
|
24
|
+
export declare const parseAddArgs: (config: LoadedConfig, scurry: PathScurry, monorepo?: Monorepo) => ParsedAddArgs;
|
|
25
|
+
/**
|
|
26
|
+
* Parses the positional arguments into {@link RemoveImportersDependenciesMap}.
|
|
27
|
+
*/
|
|
28
|
+
export declare const parseRemoveArgs: (config: LoadedConfig, scurry: PathScurry, monorepo?: Monorepo) => ParsedRemoveArgs;
|
|
@@ -1,12 +1,27 @@
|
|
|
1
|
-
import { joinDepIDTuple } from '@vltpkg/dep-id';
|
|
2
1
|
import { asDependency } from '@vltpkg/graph';
|
|
2
|
+
import { joinDepIDTuple } from '@vltpkg/dep-id';
|
|
3
3
|
import { Spec } from '@vltpkg/spec';
|
|
4
4
|
const rootDepID = joinDepIDTuple(['file', '.']);
|
|
5
|
+
/**
|
|
6
|
+
* Compute a DepID for the current working directory relative to the project
|
|
7
|
+
* root. Returns the root DepID if cwd is the project root, otherwise returns
|
|
8
|
+
* the computed DepID.
|
|
9
|
+
*/
|
|
10
|
+
const getCwdDepID = (scurry) => {
|
|
11
|
+
const cwd = process.cwd();
|
|
12
|
+
const relPath = scurry.relativePosix(cwd);
|
|
13
|
+
// If cwd is the project root or outside it, return root DepID
|
|
14
|
+
if (!relPath || relPath.startsWith('..')) {
|
|
15
|
+
return rootDepID;
|
|
16
|
+
}
|
|
17
|
+
// Return a DepID for the nested folder (posix-style path)
|
|
18
|
+
return joinDepIDTuple(['file', relPath.split('\\').join('/')]);
|
|
19
|
+
};
|
|
5
20
|
/**
|
|
6
21
|
* Get the list of importers that are currently selected
|
|
7
22
|
* in {@link WorkspaceTypes}.
|
|
8
23
|
*/
|
|
9
|
-
const
|
|
24
|
+
const getWorkspaceImporters = (opts, monorepo) => {
|
|
10
25
|
const res = new Set();
|
|
11
26
|
// collects DepID references to any selected workspace
|
|
12
27
|
if (monorepo) {
|
|
@@ -14,10 +29,6 @@ const getImporters = (opts, monorepo) => {
|
|
|
14
29
|
res.add(ws.id);
|
|
15
30
|
}
|
|
16
31
|
}
|
|
17
|
-
// if no references were found, default behavior is to point to project root
|
|
18
|
-
if (!res.size) {
|
|
19
|
-
res.add(rootDepID);
|
|
20
|
-
}
|
|
21
32
|
return res;
|
|
22
33
|
};
|
|
23
34
|
const getType = (opts) => opts['save-prod'] ? 'prod'
|
|
@@ -34,38 +45,59 @@ class AddImportersDependenciesMapImpl extends Map {
|
|
|
34
45
|
class RemoveImportersDependenciesMapImpl extends Map {
|
|
35
46
|
modifiedDependencies = false;
|
|
36
47
|
}
|
|
37
|
-
|
|
48
|
+
/**
|
|
49
|
+
* Parses the positional arguments into {@link AddImportersDependenciesMap}.
|
|
50
|
+
*/
|
|
51
|
+
export const parseAddArgs = (config, scurry, monorepo) => {
|
|
38
52
|
const add = new AddImportersDependenciesMapImpl();
|
|
39
53
|
const items = config.positionals;
|
|
40
54
|
const type = getType(config.values);
|
|
41
|
-
const importers =
|
|
55
|
+
const importers = getWorkspaceImporters(config.values, monorepo);
|
|
42
56
|
const newDependencies = new Map();
|
|
43
57
|
const specOptions = config.options;
|
|
44
58
|
// nameless spec definitions will need to use their full
|
|
45
59
|
// stringified spec result instead of their name in order
|
|
46
60
|
// to have an unique key name in the resulting Map
|
|
47
61
|
const getName = (s) => s.name === '(unknown)' ? s.spec : s.name;
|
|
62
|
+
// parses each positional argument into a Spec and
|
|
63
|
+
// adds it to the new dependencies Map
|
|
48
64
|
for (const item of items) {
|
|
49
65
|
const spec = Spec.parseArgs(item, specOptions);
|
|
50
66
|
newDependencies.set(getName(spec), asDependency({ spec, type }));
|
|
51
67
|
add.modifiedDependencies = true;
|
|
52
68
|
}
|
|
69
|
+
// assigns the new dependencies to each selected workspace importer
|
|
53
70
|
for (const importer of importers) {
|
|
54
71
|
add.set(importer, newDependencies);
|
|
55
72
|
}
|
|
73
|
+
// if no workspaces were selected, default to the cwd importer which
|
|
74
|
+
// can be either the root or a nested folder in case the user is installing
|
|
75
|
+
// from a subfolder that is also a file: type dependency
|
|
76
|
+
if (!importers.size) {
|
|
77
|
+
const cwdDepID = getCwdDepID(scurry);
|
|
78
|
+
add.set(cwdDepID, newDependencies);
|
|
79
|
+
}
|
|
56
80
|
return {
|
|
57
81
|
add,
|
|
58
82
|
};
|
|
59
83
|
};
|
|
60
|
-
|
|
84
|
+
/**
|
|
85
|
+
* Parses the positional arguments into {@link RemoveImportersDependenciesMap}.
|
|
86
|
+
*/
|
|
87
|
+
export const parseRemoveArgs = (config, scurry, monorepo) => {
|
|
61
88
|
const remove = new RemoveImportersDependenciesMapImpl();
|
|
62
|
-
const importers =
|
|
89
|
+
const importers = getWorkspaceImporters(config.values, monorepo);
|
|
63
90
|
for (const importer of importers) {
|
|
64
91
|
remove.set(importer, new Set(config.positionals));
|
|
65
92
|
remove.modifiedDependencies = true;
|
|
66
93
|
}
|
|
94
|
+
// if no workspaces were selected, default to the cwd importer
|
|
95
|
+
if (!importers.size) {
|
|
96
|
+
const cwdDepID = getCwdDepID(scurry);
|
|
97
|
+
remove.set(cwdDepID, new Set(config.positionals));
|
|
98
|
+
remove.modifiedDependencies = true;
|
|
99
|
+
}
|
|
67
100
|
return {
|
|
68
101
|
remove,
|
|
69
102
|
};
|
|
70
103
|
};
|
|
71
|
-
//# sourceMappingURL=parse-add-remove-args.js.map
|
|
@@ -11,4 +11,3 @@ export type ErrorFormatOptions = InspectOptions & {
|
|
|
11
11
|
export type Formatter = (arg: unknown, options?: ErrorFormatOptions) => string;
|
|
12
12
|
export declare const indent: (lines: string, num?: number) => string;
|
|
13
13
|
export declare const printErr: (e: unknown, usage: CommandUsage, stderr: (...a: string[]) => void, baseOpts?: ErrorFormatOptions) => void;
|
|
14
|
-
//# sourceMappingURL=print-err.d.ts.map
|
|
@@ -2,8 +2,8 @@ import { splitDepID } from '@vltpkg/dep-id';
|
|
|
2
2
|
import { parseError } from '@vltpkg/output/error';
|
|
3
3
|
import { isErrorWithCause, isObject } from '@vltpkg/types';
|
|
4
4
|
import { XDG } from '@vltpkg/xdg';
|
|
5
|
-
import { isGraphRunError } from 'graph-run';
|
|
6
|
-
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
5
|
+
import { isGraphRunError } from '@vltpkg/graph-run';
|
|
6
|
+
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
7
7
|
import { join } from 'node:path';
|
|
8
8
|
import { formatWithOptions } from 'node:util';
|
|
9
9
|
export const formatOptions = {
|
|
@@ -33,6 +33,14 @@ const writeErrorLog = (e, format) => {
|
|
|
33
33
|
return null;
|
|
34
34
|
}
|
|
35
35
|
};
|
|
36
|
+
const readErrorLog = (file) => {
|
|
37
|
+
try {
|
|
38
|
+
return readFileSync(file, 'utf8');
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
36
44
|
export const printErr = (e, usage, stderr, baseOpts) => {
|
|
37
45
|
const format = (arg, opts) => {
|
|
38
46
|
const { maxLines = 200, ...rest } = {
|
|
@@ -62,6 +70,14 @@ export const printErr = (e, usage, stderr, baseOpts) => {
|
|
|
62
70
|
if (fileWritten) {
|
|
63
71
|
stderr('');
|
|
64
72
|
stderr(`Full details written to: ${fileWritten}`);
|
|
73
|
+
if (process.env.CI) {
|
|
74
|
+
const fullErrorLog = readErrorLog(fileWritten);
|
|
75
|
+
if (fullErrorLog) {
|
|
76
|
+
stderr('');
|
|
77
|
+
stderr('Full details:');
|
|
78
|
+
stderr(fullErrorLog);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
65
81
|
}
|
|
66
82
|
if (!knownError || knownError.bug) {
|
|
67
83
|
stderr('');
|
|
@@ -175,4 +191,3 @@ const printCode = (err, usage, stderr, format) => {
|
|
|
175
191
|
}
|
|
176
192
|
}
|
|
177
193
|
};
|
|
178
|
-
//# sourceMappingURL=print-err.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { DiffFilesProvider } from '@vltpkg/query';
|
|
2
|
+
/**
|
|
3
|
+
* Validates that a commitish string is safe to use
|
|
4
|
+
* in a git command.
|
|
5
|
+
*/
|
|
6
|
+
export declare const validateCommitish: (commitish: string) => string;
|
|
7
|
+
/**
|
|
8
|
+
* Creates a {@link DiffFilesProvider} that uses
|
|
9
|
+
* `git diff --name-only` to determine changed files.
|
|
10
|
+
* @param {string} projectRoot - The absolute path to the
|
|
11
|
+
* project root directory where git commands will be
|
|
12
|
+
* executed.
|
|
13
|
+
* @returns {DiffFilesProvider} A function that takes a
|
|
14
|
+
* commitish and returns a Set of changed file paths
|
|
15
|
+
* relative to the project root.
|
|
16
|
+
*/
|
|
17
|
+
export declare const createDiffFilesProvider: (projectRoot: string) => DiffFilesProvider;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
import { error } from '@vltpkg/error-cause';
|
|
3
|
+
/**
|
|
4
|
+
* Pattern to validate commitish arguments.
|
|
5
|
+
* Allows branch names, tags, SHAs, HEAD~N, HEAD^N, etc.
|
|
6
|
+
* Rejects shell metacharacters to prevent command injection.
|
|
7
|
+
*/
|
|
8
|
+
const VALID_COMMITISH = /^[a-zA-Z0-9_./@^~:#{}-]+$/;
|
|
9
|
+
/**
|
|
10
|
+
* Validates that a commitish string is safe to use
|
|
11
|
+
* in a git command.
|
|
12
|
+
*/
|
|
13
|
+
export const validateCommitish = (commitish) => {
|
|
14
|
+
if (!commitish) {
|
|
15
|
+
throw error('Missing commitish argument for :diff() selector');
|
|
16
|
+
}
|
|
17
|
+
if (!VALID_COMMITISH.test(commitish)) {
|
|
18
|
+
throw error('Invalid commitish argument for :diff() selector', {
|
|
19
|
+
found: commitish,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
return commitish;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Creates a {@link DiffFilesProvider} that uses
|
|
26
|
+
* `git diff --name-only` to determine changed files.
|
|
27
|
+
* @param {string} projectRoot - The absolute path to the
|
|
28
|
+
* project root directory where git commands will be
|
|
29
|
+
* executed.
|
|
30
|
+
* @returns {DiffFilesProvider} A function that takes a
|
|
31
|
+
* commitish and returns a Set of changed file paths
|
|
32
|
+
* relative to the project root.
|
|
33
|
+
*/
|
|
34
|
+
export const createDiffFilesProvider = (projectRoot) => {
|
|
35
|
+
// Cache results per commitish to avoid repeated git calls
|
|
36
|
+
const cache = new Map();
|
|
37
|
+
return (commitish) => {
|
|
38
|
+
const cached = cache.get(commitish);
|
|
39
|
+
if (cached)
|
|
40
|
+
return cached;
|
|
41
|
+
const safeCommitish = validateCommitish(commitish);
|
|
42
|
+
try {
|
|
43
|
+
const stdout = execSync(`git diff --name-only ${safeCommitish}`, {
|
|
44
|
+
cwd: projectRoot,
|
|
45
|
+
encoding: 'utf8',
|
|
46
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
47
|
+
timeout: 30_000,
|
|
48
|
+
});
|
|
49
|
+
const files = new Set();
|
|
50
|
+
for (const line of stdout.split('\n')) {
|
|
51
|
+
const trimmed = line.trim();
|
|
52
|
+
if (trimmed) {
|
|
53
|
+
files.add(trimmed);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
cache.set(commitish, files);
|
|
57
|
+
return files;
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
throw error(`Failed to run git diff for commitish: ${safeCommitish}`, { cause: err });
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
};
|
|
@@ -13,4 +13,3 @@ export type HostContextsMapResult = {
|
|
|
13
13
|
* pseudo selector to dynamically load graphs from different sources.
|
|
14
14
|
*/
|
|
15
15
|
export declare const createHostContextsMap: (conf: LoadedConfig) => Promise<Map<string, () => Promise<HostContextsMapResult>>>;
|
|
16
|
-
//# sourceMappingURL=query-host-contexts.d.ts.map
|