@unbrained/pm-cli 2026.5.24 → 2026.5.28
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/CHANGELOG.md +953 -522
- package/README.md +2 -10
- package/dist/cli/bootstrap-args.d.ts +18 -1
- package/dist/cli/bootstrap-args.js +143 -3
- package/dist/cli/bootstrap-args.js.map +1 -1
- package/dist/cli/commander-usage.js +134 -11
- package/dist/cli/commander-usage.js.map +1 -1
- package/dist/cli/commands/append.js +4 -3
- package/dist/cli/commands/append.js.map +1 -1
- package/dist/cli/commands/claim.js +5 -4
- package/dist/cli/commands/claim.js.map +1 -1
- package/dist/cli/commands/close.d.ts +3 -0
- package/dist/cli/commands/close.js +26 -3
- package/dist/cli/commands/close.js.map +1 -1
- package/dist/cli/commands/completion.d.ts +2 -2
- package/dist/cli/commands/completion.js +109 -56
- package/dist/cli/commands/completion.js.map +1 -1
- package/dist/cli/commands/config.d.ts +1 -1
- package/dist/cli/commands/config.js +82 -4
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/create.js +7 -272
- package/dist/cli/commands/create.js.map +1 -1
- package/dist/cli/commands/delete.js +4 -3
- package/dist/cli/commands/delete.js.map +1 -1
- package/dist/cli/commands/docs.d.ts +1 -12
- package/dist/cli/commands/docs.js +8 -312
- package/dist/cli/commands/docs.js.map +1 -1
- package/dist/cli/commands/extension/bundled-catalog.d.ts +14 -0
- package/dist/cli/commands/extension/bundled-catalog.js +268 -0
- package/dist/cli/commands/extension/bundled-catalog.js.map +1 -0
- package/dist/cli/commands/extension/doctor.d.ts +31 -0
- package/dist/cli/commands/extension/doctor.js +345 -0
- package/dist/cli/commands/extension/doctor.js.map +1 -0
- package/dist/cli/commands/extension/install-sources.d.ts +37 -0
- package/dist/cli/commands/extension/install-sources.js +384 -0
- package/dist/cli/commands/extension/install-sources.js.map +1 -0
- package/dist/cli/commands/extension/managed-state.d.ts +48 -0
- package/dist/cli/commands/extension/managed-state.js +172 -0
- package/dist/cli/commands/extension/managed-state.js.map +1 -0
- package/dist/cli/commands/extension/scaffold.d.ts +14 -0
- package/dist/cli/commands/extension/scaffold.js +202 -0
- package/dist/cli/commands/extension/scaffold.js.map +1 -0
- package/dist/cli/commands/extension/shared.d.ts +14 -0
- package/dist/cli/commands/extension/shared.js +106 -0
- package/dist/cli/commands/extension/shared.js.map +1 -0
- package/dist/cli/commands/extension.d.ts +36 -68
- package/dist/cli/commands/extension.js +143 -1422
- package/dist/cli/commands/extension.js.map +1 -1
- package/dist/cli/commands/files.d.ts +1 -12
- package/dist/cli/commands/files.js +11 -308
- package/dist/cli/commands/files.js.map +1 -1
- package/dist/cli/commands/get.js +4 -3
- package/dist/cli/commands/get.js.map +1 -1
- package/dist/cli/commands/health.js +17 -3
- package/dist/cli/commands/health.js.map +1 -1
- package/dist/cli/commands/history-redact.js +23 -18
- package/dist/cli/commands/history-redact.js.map +1 -1
- package/dist/cli/commands/history-repair.js +24 -18
- package/dist/cli/commands/history-repair.js.map +1 -1
- package/dist/cli/commands/legacy-none-tokens.d.ts +3 -0
- package/dist/cli/commands/legacy-none-tokens.js +39 -0
- package/dist/cli/commands/legacy-none-tokens.js.map +1 -0
- package/dist/cli/commands/linked-artifacts.d.ts +96 -0
- package/dist/cli/commands/linked-artifacts.js +335 -0
- package/dist/cli/commands/linked-artifacts.js.map +1 -0
- package/dist/cli/commands/linked-test-parsers.d.ts +28 -0
- package/dist/cli/commands/linked-test-parsers.js +192 -0
- package/dist/cli/commands/linked-test-parsers.js.map +1 -0
- package/dist/cli/commands/list.js +19 -5
- package/dist/cli/commands/list.js.map +1 -1
- package/dist/cli/commands/normalize.js +4 -3
- package/dist/cli/commands/normalize.js.map +1 -1
- package/dist/cli/commands/plan.d.ts +5 -0
- package/dist/cli/commands/plan.js +56 -8
- package/dist/cli/commands/plan.js.map +1 -1
- package/dist/cli/commands/recurrence-parsers.d.ts +26 -0
- package/dist/cli/commands/recurrence-parsers.js +98 -0
- package/dist/cli/commands/recurrence-parsers.js.map +1 -0
- package/dist/cli/commands/restore.js +19 -8
- package/dist/cli/commands/restore.js.map +1 -1
- package/dist/cli/commands/search.js +5 -8
- package/dist/cli/commands/search.js.map +1 -1
- package/dist/cli/commands/test/linked-command-detection.d.ts +37 -0
- package/dist/cli/commands/test/linked-command-detection.js +200 -0
- package/dist/cli/commands/test/linked-command-detection.js.map +1 -0
- package/dist/cli/commands/test.d.ts +1 -2
- package/dist/cli/commands/test.js +8 -350
- package/dist/cli/commands/test.js.map +1 -1
- package/dist/cli/commands/update-many.js +4 -3
- package/dist/cli/commands/update-many.js.map +1 -1
- package/dist/cli/commands/update.js +83 -356
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/commands/validate.js +32 -12
- package/dist/cli/commands/validate.js.map +1 -1
- package/dist/cli/error-guidance.d.ts +1 -0
- package/dist/cli/error-guidance.js +6 -2
- package/dist/cli/error-guidance.js.map +1 -1
- package/dist/cli/main.d.ts +11 -0
- package/dist/cli/main.js +76 -28
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/register-list-query.d.ts +4 -1
- package/dist/cli/register-list-query.js +242 -203
- package/dist/cli/register-list-query.js.map +1 -1
- package/dist/cli/register-mutation.js +73 -11
- package/dist/cli/register-mutation.js.map +1 -1
- package/dist/cli/register-operations.js +3 -3
- package/dist/cli/register-operations.js.map +1 -1
- package/dist/cli/register-setup.js +12 -7
- package/dist/cli/register-setup.js.map +1 -1
- package/dist/cli/registration-helpers.js +3 -2
- package/dist/cli/registration-helpers.js.map +1 -1
- package/dist/cli.js +4 -3
- package/dist/cli.js.map +1 -1
- package/dist/core/config/positional-value.d.ts +44 -0
- package/dist/core/config/positional-value.js +109 -0
- package/dist/core/config/positional-value.js.map +1 -0
- package/dist/core/extensions/extension-capability-aliases.d.ts +14 -0
- package/dist/core/extensions/extension-capability-aliases.js +159 -0
- package/dist/core/extensions/extension-capability-aliases.js.map +1 -0
- package/dist/core/extensions/extension-hook-runtime.d.ts +13 -0
- package/dist/core/extensions/extension-hook-runtime.js +414 -0
- package/dist/core/extensions/extension-hook-runtime.js.map +1 -0
- package/dist/core/extensions/extension-policy.d.ts +69 -0
- package/dist/core/extensions/extension-policy.js +481 -0
- package/dist/core/extensions/extension-policy.js.map +1 -0
- package/dist/core/extensions/extension-registries.d.ts +8 -0
- package/dist/core/extensions/extension-registries.js +52 -0
- package/dist/core/extensions/extension-registries.js.map +1 -0
- package/dist/core/extensions/extension-runtime-helpers.d.ts +6 -0
- package/dist/core/extensions/extension-runtime-helpers.js +29 -0
- package/dist/core/extensions/extension-runtime-helpers.js.map +1 -0
- package/dist/core/extensions/extension-types.d.ts +13 -39
- package/dist/core/extensions/extension-types.js +34 -2
- package/dist/core/extensions/extension-types.js.map +1 -1
- package/dist/core/extensions/index.d.ts +7 -0
- package/dist/core/extensions/index.js +11 -2
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +4 -22
- package/dist/core/extensions/loader.js +22 -1139
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/history/drift-scan.d.ts +11 -0
- package/dist/core/history/drift-scan.js +114 -32
- package/dist/core/history/drift-scan.js.map +1 -1
- package/dist/core/history/history-rewrite.d.ts +43 -0
- package/dist/core/history/history-rewrite.js +48 -0
- package/dist/core/history/history-rewrite.js.map +1 -0
- package/dist/core/history/history.js +5 -4
- package/dist/core/history/history.js.map +1 -1
- package/dist/core/history/replay.js +4 -3
- package/dist/core/history/replay.js.map +1 -1
- package/dist/core/item/item-record.d.ts +19 -0
- package/dist/core/item/item-record.js +24 -0
- package/dist/core/item/item-record.js.map +1 -0
- package/dist/core/output/mutation-projection.d.ts +31 -0
- package/dist/core/output/mutation-projection.js +103 -0
- package/dist/core/output/mutation-projection.js.map +1 -0
- package/dist/core/output/output.d.ts +2 -0
- package/dist/core/output/output.js +5 -3
- package/dist/core/output/output.js.map +1 -1
- package/dist/core/schema/runtime-schema.js +8 -38
- package/dist/core/schema/runtime-schema.js.map +1 -1
- package/dist/core/search/vector-stores.js +46 -9
- package/dist/core/search/vector-stores.js.map +1 -1
- package/dist/core/sentry/helpers.d.ts +1 -1
- package/dist/core/sentry/helpers.js +20 -3
- package/dist/core/sentry/helpers.js.map +1 -1
- package/dist/core/shared/command-types.d.ts +1 -0
- package/dist/core/shared/command-types.js +2 -2
- package/dist/core/shared/command-types.js.map +1 -1
- package/dist/core/shared/constants.d.ts +10 -1
- package/dist/core/shared/constants.js +56 -58
- package/dist/core/shared/constants.js.map +1 -1
- package/dist/core/shared/levenshtein.js +23 -7
- package/dist/core/shared/levenshtein.js.map +1 -1
- package/dist/core/shared/primitives.d.ts +23 -0
- package/dist/core/shared/primitives.js +39 -2
- package/dist/core/shared/primitives.js.map +1 -1
- package/dist/core/store/front-matter-cache.d.ts +16 -2
- package/dist/core/store/front-matter-cache.js +99 -33
- package/dist/core/store/front-matter-cache.js.map +1 -1
- package/dist/core/store/item-store.js +8 -73
- package/dist/core/store/item-store.js.map +1 -1
- package/dist/mcp/server.js +76 -28
- package/dist/mcp/server.js.map +1 -1
- package/dist/sdk/cli-contracts/enum-contracts.d.ts +20 -0
- package/dist/sdk/cli-contracts/enum-contracts.js +156 -0
- package/dist/sdk/cli-contracts/enum-contracts.js.map +1 -0
- package/dist/sdk/cli-contracts/tool-option-contracts.d.ts +14 -0
- package/dist/sdk/cli-contracts/tool-option-contracts.js +243 -0
- package/dist/sdk/cli-contracts/tool-option-contracts.js.map +1 -0
- package/dist/sdk/cli-contracts/tool-parameter-tables.d.ts +11 -0
- package/dist/sdk/cli-contracts/tool-parameter-tables.js +901 -0
- package/dist/sdk/cli-contracts/tool-parameter-tables.js.map +1 -0
- package/dist/sdk/cli-contracts.d.ts +11 -33
- package/dist/sdk/cli-contracts.js +30 -1356
- package/dist/sdk/cli-contracts.js.map +1 -1
- package/dist/sdk/package-import-adapters.d.ts +74 -0
- package/dist/sdk/package-import-adapters.js +186 -0
- package/dist/sdk/package-import-adapters.js.map +1 -0
- package/dist/sdk/package-runtime-options.d.ts +26 -0
- package/dist/sdk/package-runtime-options.js +71 -0
- package/dist/sdk/package-runtime-options.js.map +1 -0
- package/dist/sdk/runtime.d.ts +2 -0
- package/dist/sdk/runtime.js +4 -2
- package/dist/sdk/runtime.js.map +1 -1
- package/docs/AGENT_GUIDE.md +6 -10
- package/docs/CLAUDE_CODE_PLUGIN.md +5 -28
- package/docs/CODEX_PLUGIN.md +5 -5
- package/docs/COMMANDS.md +19 -3
- package/docs/CONFIGURATION.md +15 -0
- package/docs/EXTENSIONS.md +4 -63
- package/docs/RELEASING.md +4 -4
- package/marketplace.json +7 -3
- package/package.json +9 -6
- package/packages/pm-beads/extensions/beads/index.js +2 -49
- package/packages/pm-beads/extensions/beads/index.ts +2 -54
- package/packages/pm-beads/extensions/beads/runtime-loader.js +86 -0
- package/packages/pm-beads/extensions/beads/runtime-loader.ts +88 -0
- package/packages/pm-beads/extensions/beads/runtime.js +26 -115
- package/packages/pm-beads/extensions/beads/runtime.ts +33 -132
- package/packages/pm-calendar/extensions/calendar/index.js +47 -2
- package/packages/pm-calendar/extensions/calendar/index.ts +52 -2
- package/packages/pm-calendar/extensions/calendar/runtime.js +1 -0
- package/packages/pm-calendar/extensions/calendar/runtime.ts +1 -0
- package/packages/pm-governance-audit/extensions/governance-audit/runtime.js +14 -41
- package/packages/pm-governance-audit/extensions/governance-audit/runtime.ts +25 -41
- package/packages/pm-guide-shell/extensions/guide-shell/runtime.js +10 -50
- package/packages/pm-guide-shell/extensions/guide-shell/runtime.ts +17 -50
- package/packages/pm-linked-test-adapters/extensions/linked-test-adapters/runtime.js +8 -40
- package/packages/pm-linked-test-adapters/extensions/linked-test-adapters/runtime.ts +10 -40
- package/packages/pm-search-advanced/extensions/search-advanced/index.js +1 -1
- package/packages/pm-search-advanced/extensions/search-advanced/runtime.js +4 -37
- package/packages/pm-search-advanced/extensions/search-advanced/runtime.ts +6 -37
- package/packages/pm-todos/extensions/todos/index.js +3 -50
- package/packages/pm-todos/extensions/todos/index.ts +3 -55
- package/packages/pm-todos/extensions/todos/runtime-loader.js +86 -0
- package/packages/pm-todos/extensions/todos/runtime-loader.ts +88 -0
- package/packages/pm-todos/extensions/todos/runtime.js +24 -117
- package/packages/pm-todos/extensions/todos/runtime.ts +32 -129
- package/plugins/pm-claude/README.md +2 -2
- package/plugins/pm-claude/commands/pm-planner.md +1 -15
- package/plugins/pm-claude/scripts/pm-mcp-server.mjs +5 -2
- package/plugins/pm-claude/skills/pm-planner/SKILL.md +3 -21
- package/plugins/pm-codex/scripts/pm-mcp-server.mjs +15 -6
- package/plugins/pm-codex/skills/pm-native/SKILL.md +1 -13
- package/PRD.md +0 -1734
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
// Pure, leaf-level helpers for detecting how linked-test shell commands invoke
|
|
2
|
+
// the pm CLI (directly, via npx/pnpm/npm exec, or a launcher subcommand) and for
|
|
3
|
+
// pulling structured context (subcommand, referenced item ids, runner) out of a
|
|
4
|
+
// normalized command string. Extracted from test.ts to keep that command file
|
|
5
|
+
// under the per-file LOC budget; consumers re-export these from test.ts so no
|
|
6
|
+
// caller outside test.ts changes.
|
|
7
|
+
|
|
8
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="1e2744b0-89b5-5779-ae5b-f905a5780eb3")}catch(e){}}();
|
|
9
|
+
export const PM_GLOBAL_FLAGS_WITH_VALUE = new Set(["--path"]);
|
|
10
|
+
export const NPX_FLAGS_WITH_VALUE = new Set(["-p", "--package", "-c", "--call"]);
|
|
11
|
+
export const PNPM_GLOBAL_FLAGS_WITH_VALUE = new Set([
|
|
12
|
+
"-c",
|
|
13
|
+
"-C",
|
|
14
|
+
"--config",
|
|
15
|
+
"--dir",
|
|
16
|
+
"--filter",
|
|
17
|
+
"--workspace-dir",
|
|
18
|
+
]);
|
|
19
|
+
export const NPM_GLOBAL_FLAGS_WITH_VALUE = new Set(["-C", "--prefix", "--userconfig", "--cache"]);
|
|
20
|
+
export const YARN_GLOBAL_FLAGS_WITH_VALUE = new Set(["--cwd"]);
|
|
21
|
+
export const BUN_GLOBAL_FLAGS_WITH_VALUE = new Set(["--cwd"]);
|
|
22
|
+
export const NPM_EXEC_SUBCOMMANDS = new Set(["exec", "x"]);
|
|
23
|
+
export const SCRIPT_RUN_SUBCOMMANDS = new Set(["run", "run-script"]);
|
|
24
|
+
export const SCRIPT_RUN_FLAGS_WITH_VALUE = new Set(["-C", "--dir", "--cwd", "-w", "--workspace", "--filter"]);
|
|
25
|
+
export function splitNormalizedCommandSegments(normalizedCommand) {
|
|
26
|
+
return normalizedCommand
|
|
27
|
+
.split(/&&|\|\||\||;/)
|
|
28
|
+
.map((segment) => segment.trim())
|
|
29
|
+
.filter((segment) => segment.length > 0);
|
|
30
|
+
}
|
|
31
|
+
export function stripLeadingEnvAssignments(tokens) {
|
|
32
|
+
let start = 0;
|
|
33
|
+
if (tokens[start] === "env") {
|
|
34
|
+
start += 1;
|
|
35
|
+
}
|
|
36
|
+
while (start < tokens.length) {
|
|
37
|
+
const token = tokens[start];
|
|
38
|
+
if (/^(?:[a-z_][a-z0-9_]*|\$env:[a-z_][a-z0-9_]*)=.*/.test(token)) {
|
|
39
|
+
start += 1;
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
return tokens.slice(start);
|
|
45
|
+
}
|
|
46
|
+
export function firstPmSubcommand(args) {
|
|
47
|
+
let index = 0;
|
|
48
|
+
while (index < args.length) {
|
|
49
|
+
const token = args[index];
|
|
50
|
+
if (token === "--") {
|
|
51
|
+
index += 1;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (token.startsWith("-")) {
|
|
55
|
+
if (PM_GLOBAL_FLAGS_WITH_VALUE.has(token)) {
|
|
56
|
+
index += 2;
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
index += 1;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
return token;
|
|
63
|
+
}
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
export function isPmExecutableToken(token) {
|
|
67
|
+
return (token === "pm" ||
|
|
68
|
+
token === "pm.cmd" ||
|
|
69
|
+
token === "pm.exe" ||
|
|
70
|
+
token.endsWith("/pm") ||
|
|
71
|
+
token.endsWith("/pm.cmd") ||
|
|
72
|
+
token.endsWith("/pm.exe"));
|
|
73
|
+
}
|
|
74
|
+
export function normalizePackageSpecifier(token) {
|
|
75
|
+
const trimmed = token.trim();
|
|
76
|
+
if (!trimmed.startsWith("@")) {
|
|
77
|
+
const versionSeparator = trimmed.indexOf("@");
|
|
78
|
+
return versionSeparator === -1 ? trimmed : trimmed.slice(0, versionSeparator);
|
|
79
|
+
}
|
|
80
|
+
const scopeSeparator = trimmed.indexOf("/");
|
|
81
|
+
if (scopeSeparator === -1) {
|
|
82
|
+
return trimmed;
|
|
83
|
+
}
|
|
84
|
+
const versionSeparator = trimmed.indexOf("@", scopeSeparator + 1);
|
|
85
|
+
return versionSeparator === -1 ? trimmed : trimmed.slice(0, versionSeparator);
|
|
86
|
+
}
|
|
87
|
+
export function isPmCliPackageToken(token) {
|
|
88
|
+
const normalizedSpecifier = normalizePackageSpecifier(token);
|
|
89
|
+
return (normalizedSpecifier === "pm-cli" ||
|
|
90
|
+
normalizedSpecifier.endsWith("/pm-cli") ||
|
|
91
|
+
token === "pm-cli" ||
|
|
92
|
+
token.endsWith("/pm-cli"));
|
|
93
|
+
}
|
|
94
|
+
export function isPmCliScriptToken(token) {
|
|
95
|
+
return token === "dist/cli.js" || token === "./dist/cli.js" || token.endsWith("/dist/cli.js");
|
|
96
|
+
}
|
|
97
|
+
export function parseNpxCommand(tokens) {
|
|
98
|
+
let index = 0;
|
|
99
|
+
while (index < tokens.length) {
|
|
100
|
+
const token = tokens[index];
|
|
101
|
+
if (token === "--") {
|
|
102
|
+
index += 1;
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
if (!token.startsWith("-")) {
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
if (token.includes("=")) {
|
|
109
|
+
index += 1;
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
if (NPX_FLAGS_WITH_VALUE.has(token)) {
|
|
113
|
+
index += 2;
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
index += 1;
|
|
117
|
+
}
|
|
118
|
+
const command = tokens[index];
|
|
119
|
+
if (!command) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
command,
|
|
124
|
+
args: tokens.slice(index + 1),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
export function parseLauncherSubcommand(tokens, flagsWithValue) {
|
|
128
|
+
let index = 0;
|
|
129
|
+
while (index < tokens.length) {
|
|
130
|
+
const token = tokens[index];
|
|
131
|
+
if (token === "--") {
|
|
132
|
+
index += 1;
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (token.startsWith("-")) {
|
|
136
|
+
if (token.includes("=")) {
|
|
137
|
+
index += 1;
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
if (flagsWithValue.has(token)) {
|
|
141
|
+
index += 2;
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
index += 1;
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
subcommand: token,
|
|
149
|
+
args: tokens.slice(index + 1),
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
export function parsePnpmDlxCommand(tokens) {
|
|
155
|
+
const parsed = parseLauncherSubcommand(tokens, PNPM_GLOBAL_FLAGS_WITH_VALUE);
|
|
156
|
+
if (parsed?.subcommand !== "dlx") {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
return parseNpxCommand(parsed.args);
|
|
160
|
+
}
|
|
161
|
+
export function parseNpmExecCommand(tokens) {
|
|
162
|
+
const parsed = parseLauncherSubcommand(tokens, NPM_GLOBAL_FLAGS_WITH_VALUE);
|
|
163
|
+
if (!parsed || !NPM_EXEC_SUBCOMMANDS.has(parsed.subcommand)) {
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
return parseNpxCommand(parsed.args);
|
|
167
|
+
}
|
|
168
|
+
export function resolvePmSubcommandContext(args) {
|
|
169
|
+
let index = 0;
|
|
170
|
+
while (index < args.length) {
|
|
171
|
+
const token = args[index];
|
|
172
|
+
if (token === "--") {
|
|
173
|
+
index += 1;
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
if (token.startsWith("-")) {
|
|
177
|
+
if (PM_GLOBAL_FLAGS_WITH_VALUE.has(token)) {
|
|
178
|
+
index += 2;
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
index += 1;
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
subcommand: token,
|
|
186
|
+
remaining: args.slice(index + 1),
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
export function firstPositionalToken(tokens) {
|
|
192
|
+
for (const token of tokens) {
|
|
193
|
+
if (!token.startsWith("-")) {
|
|
194
|
+
return token;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return undefined;
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=linked-command-detection.js.map
|
|
200
|
+
//# debugId=1e2744b0-89b5-5779-ae5b-f905a5780eb3
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linked-command-detection.js","sources":["cli/commands/test/linked-command-detection.ts"],"sourceRoot":"/","sourcesContent":["// Pure, leaf-level helpers for detecting how linked-test shell commands invoke\n// the pm CLI (directly, via npx/pnpm/npm exec, or a launcher subcommand) and for\n// pulling structured context (subcommand, referenced item ids, runner) out of a\n// normalized command string. Extracted from test.ts to keep that command file\n// under the per-file LOC budget; consumers re-export these from test.ts so no\n// caller outside test.ts changes.\n\nexport const PM_GLOBAL_FLAGS_WITH_VALUE = new Set([\"--path\"]);\nexport const NPX_FLAGS_WITH_VALUE = new Set([\"-p\", \"--package\", \"-c\", \"--call\"]);\nexport const PNPM_GLOBAL_FLAGS_WITH_VALUE = new Set([\n \"-c\",\n \"-C\",\n \"--config\",\n \"--dir\",\n \"--filter\",\n \"--workspace-dir\",\n]);\nexport const NPM_GLOBAL_FLAGS_WITH_VALUE = new Set([\"-C\", \"--prefix\", \"--userconfig\", \"--cache\"]);\nexport const YARN_GLOBAL_FLAGS_WITH_VALUE = new Set([\"--cwd\"]);\nexport const BUN_GLOBAL_FLAGS_WITH_VALUE = new Set([\"--cwd\"]);\nexport const NPM_EXEC_SUBCOMMANDS = new Set([\"exec\", \"x\"]);\nexport const SCRIPT_RUN_SUBCOMMANDS = new Set([\"run\", \"run-script\"]);\nexport const SCRIPT_RUN_FLAGS_WITH_VALUE = new Set([\"-C\", \"--dir\", \"--cwd\", \"-w\", \"--workspace\", \"--filter\"]);\n\nexport function splitNormalizedCommandSegments(normalizedCommand: string): string[] {\n return normalizedCommand\n .split(/&&|\\|\\||\\||;/)\n .map((segment) => segment.trim())\n .filter((segment) => segment.length > 0);\n}\n\nexport function stripLeadingEnvAssignments(tokens: string[]): string[] {\n let start = 0;\n if (tokens[start] === \"env\") {\n start += 1;\n }\n while (start < tokens.length) {\n const token = tokens[start];\n if (/^(?:[a-z_][a-z0-9_]*|\\$env:[a-z_][a-z0-9_]*)=.*/.test(token)) {\n start += 1;\n continue;\n }\n break;\n }\n return tokens.slice(start);\n}\n\nexport function firstPmSubcommand(args: string[]): string | undefined {\n let index = 0;\n while (index < args.length) {\n const token = args[index];\n if (token === \"--\") {\n index += 1;\n continue;\n }\n if (token.startsWith(\"-\")) {\n if (PM_GLOBAL_FLAGS_WITH_VALUE.has(token)) {\n index += 2;\n continue;\n }\n index += 1;\n continue;\n }\n return token;\n }\n return undefined;\n}\n\nexport function isPmExecutableToken(token: string): boolean {\n return (\n token === \"pm\" ||\n token === \"pm.cmd\" ||\n token === \"pm.exe\" ||\n token.endsWith(\"/pm\") ||\n token.endsWith(\"/pm.cmd\") ||\n token.endsWith(\"/pm.exe\")\n );\n}\n\nexport function normalizePackageSpecifier(token: string): string {\n const trimmed = token.trim();\n if (!trimmed.startsWith(\"@\")) {\n const versionSeparator = trimmed.indexOf(\"@\");\n return versionSeparator === -1 ? trimmed : trimmed.slice(0, versionSeparator);\n }\n const scopeSeparator = trimmed.indexOf(\"/\");\n if (scopeSeparator === -1) {\n return trimmed;\n }\n const versionSeparator = trimmed.indexOf(\"@\", scopeSeparator + 1);\n return versionSeparator === -1 ? trimmed : trimmed.slice(0, versionSeparator);\n}\n\nexport function isPmCliPackageToken(token: string): boolean {\n const normalizedSpecifier = normalizePackageSpecifier(token);\n return (\n normalizedSpecifier === \"pm-cli\" ||\n normalizedSpecifier.endsWith(\"/pm-cli\") ||\n token === \"pm-cli\" ||\n token.endsWith(\"/pm-cli\")\n );\n}\n\nexport function isPmCliScriptToken(token: string): boolean {\n return token === \"dist/cli.js\" || token === \"./dist/cli.js\" || token.endsWith(\"/dist/cli.js\");\n}\n\nexport function parseNpxCommand(tokens: string[]): { command: string; args: string[] } | null {\n let index = 0;\n while (index < tokens.length) {\n const token = tokens[index];\n if (token === \"--\") {\n index += 1;\n break;\n }\n if (!token.startsWith(\"-\")) {\n break;\n }\n if (token.includes(\"=\")) {\n index += 1;\n continue;\n }\n if (NPX_FLAGS_WITH_VALUE.has(token)) {\n index += 2;\n continue;\n }\n index += 1;\n }\n const command = tokens[index];\n if (!command) {\n return null;\n }\n return {\n command,\n args: tokens.slice(index + 1),\n };\n}\n\nexport function parseLauncherSubcommand(\n tokens: string[],\n flagsWithValue: Set<string>,\n): { subcommand: string; args: string[] } | null {\n let index = 0;\n while (index < tokens.length) {\n const token = tokens[index];\n if (token === \"--\") {\n index += 1;\n continue;\n }\n if (token.startsWith(\"-\")) {\n if (token.includes(\"=\")) {\n index += 1;\n continue;\n }\n if (flagsWithValue.has(token)) {\n index += 2;\n continue;\n }\n index += 1;\n continue;\n }\n return {\n subcommand: token,\n args: tokens.slice(index + 1),\n };\n }\n return null;\n}\n\nexport function parsePnpmDlxCommand(tokens: string[]): { command: string; args: string[] } | null {\n const parsed = parseLauncherSubcommand(tokens, PNPM_GLOBAL_FLAGS_WITH_VALUE);\n if (parsed?.subcommand !== \"dlx\") {\n return null;\n }\n return parseNpxCommand(parsed.args);\n}\n\nexport function parseNpmExecCommand(tokens: string[]): { command: string; args: string[] } | null {\n const parsed = parseLauncherSubcommand(tokens, NPM_GLOBAL_FLAGS_WITH_VALUE);\n if (!parsed || !NPM_EXEC_SUBCOMMANDS.has(parsed.subcommand)) {\n return null;\n }\n return parseNpxCommand(parsed.args);\n}\n\nexport function resolvePmSubcommandContext(args: string[]): { subcommand: string; remaining: string[] } | null {\n let index = 0;\n while (index < args.length) {\n const token = args[index];\n if (token === \"--\") {\n index += 1;\n continue;\n }\n if (token.startsWith(\"-\")) {\n if (PM_GLOBAL_FLAGS_WITH_VALUE.has(token)) {\n index += 2;\n continue;\n }\n index += 1;\n continue;\n }\n return {\n subcommand: token,\n remaining: args.slice(index + 1),\n };\n }\n return null;\n}\n\nexport function firstPositionalToken(tokens: string[]): string | undefined {\n for (const token of tokens) {\n if (!token.startsWith(\"-\")) {\n return token;\n }\n }\n return undefined;\n}\n"],"names":[],"mappings":"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","debugId":"1e2744b0-89b5-5779-ae5b-f905a5780eb3"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { GlobalOptions } from "../../core/shared/command-types.js";
|
|
2
|
+
import { type LinkedTestPmContextMode } from "./linked-test-parsers.js";
|
|
2
3
|
import type { LinkedTest } from "../../types/index.js";
|
|
3
|
-
declare const PM_CONTEXT_MODE_VALUES: readonly ["schema", "tracker", "auto"];
|
|
4
|
-
type LinkedTestPmContextMode = (typeof PM_CONTEXT_MODE_VALUES)[number];
|
|
5
4
|
interface LinkedTestExecutionResult {
|
|
6
5
|
stdout: string;
|
|
7
6
|
stderr: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="f4d1b3b4-fb85-5127-a4b7-7877a66286e8")}catch(e){}}();
|
|
3
3
|
import { spawn } from "node:child_process";
|
|
4
4
|
import { cp, mkdir, mkdtemp, readdir, rm } from "node:fs/promises";
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
@@ -17,14 +17,12 @@ import { readSettings } from "../../core/store/settings.js";
|
|
|
17
17
|
import { appendTrackedTestRunSummary } from "../../core/test/item-test-run-tracking.js";
|
|
18
18
|
import { runInit } from "./init.js";
|
|
19
19
|
import { looksLikeStructuredLinkedTestEntry, normalizeStructuredLinkedTestEntry } from "./linked-test-entry.js";
|
|
20
|
+
import { LINKED_TEST_PM_CONTEXT_MODE_VALUES as PM_CONTEXT_MODE_VALUES, LINKED_TEST_PROTECTED_ENV_KEYS, parseLinkedTestAssertionEqualsMap, parseLinkedTestAssertionGteMap, parseLinkedTestBoolean as parseLinkedTestBooleanValue, parseLinkedTestContextMode as parseLinkedTestContextModeValue, parseLinkedTestEnvClear as parseLinkedTestEnvClearValue, parseLinkedTestEnvSet as parseLinkedTestEnvSetValue, parseLinkedTestMinLines, parseLinkedTestRegexList, parseLinkedTestStringList, } from "./linked-test-parsers.js";
|
|
20
21
|
import { SCOPE_VALUES } from "../../types/index.js";
|
|
21
22
|
const TEST_OUTPUT_MAX_BUFFER_BYTES = 20 * 1024 * 1024;
|
|
22
23
|
const DEFAULT_LINKED_TEST_TIMEOUT_FORCE_KILL_DELAY_MS = 3000;
|
|
23
24
|
const DEFAULT_LINKED_TEST_HEARTBEAT_INTERVAL_MS = 10000;
|
|
24
25
|
const MAX_LINKED_TEST_COMMAND_LABEL_LENGTH = 120;
|
|
25
|
-
const LINKED_TEST_PROTECTED_ENV_KEYS = new Set(["PM_PATH", "PM_GLOBAL_PATH", "FORCE_COLOR"]);
|
|
26
|
-
const LINKED_TEST_ENV_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
27
|
-
const PM_CONTEXT_MODE_VALUES = ["schema", "tracker", "auto"];
|
|
28
26
|
const LINKED_TEST_TRACKER_DIRS_TO_SKIP = new Set(["locks", "extensions", "runtime"]);
|
|
29
27
|
const LINKED_TEST_ITEM_COUNT_DIRS_TO_SKIP = new Set(["history", "index", "search", "extensions", "locks", "runtime"]);
|
|
30
28
|
const LINKED_TEST_INFRA_COLLISION_PATTERNS = [
|
|
@@ -155,165 +153,6 @@ function ensureScope(raw) {
|
|
|
155
153
|
}
|
|
156
154
|
return value;
|
|
157
155
|
}
|
|
158
|
-
function parseLinkedTestBooleanValue(raw, optionName, fieldLabel) {
|
|
159
|
-
if (!raw || raw.trim().length === 0) {
|
|
160
|
-
return undefined;
|
|
161
|
-
}
|
|
162
|
-
const normalized = raw.trim().toLowerCase();
|
|
163
|
-
if (normalized === "true" || normalized === "1" || normalized === "yes") {
|
|
164
|
-
return true;
|
|
165
|
-
}
|
|
166
|
-
if (normalized === "false" || normalized === "0" || normalized === "no") {
|
|
167
|
-
return false;
|
|
168
|
-
}
|
|
169
|
-
throw new PmCliError(`${optionName} ${fieldLabel} must be one of true|false|1|0|yes|no`, EXIT_CODE.USAGE);
|
|
170
|
-
}
|
|
171
|
-
function parseLinkedTestEnvSetValue(raw, optionName) {
|
|
172
|
-
if (!raw || raw.trim().length === 0) {
|
|
173
|
-
return undefined;
|
|
174
|
-
}
|
|
175
|
-
const assignments = raw
|
|
176
|
-
.split(/[;\n]/)
|
|
177
|
-
.map((entry) => entry.trim())
|
|
178
|
-
.filter((entry) => entry.length > 0);
|
|
179
|
-
if (assignments.length === 0) {
|
|
180
|
-
throw new PmCliError(`${optionName} env_set must include at least one KEY=VALUE assignment`, EXIT_CODE.USAGE);
|
|
181
|
-
}
|
|
182
|
-
const envSet = {};
|
|
183
|
-
for (const assignment of assignments) {
|
|
184
|
-
const separatorIndex = assignment.indexOf("=");
|
|
185
|
-
if (separatorIndex <= 0) {
|
|
186
|
-
throw new PmCliError(`${optionName} env_set entries must use KEY=VALUE and be separated by semicolons. Example: env_set=PORT=0;PLAYWRIGHT_BASE_URL=http://127.0.0.1:4173`, EXIT_CODE.USAGE);
|
|
187
|
-
}
|
|
188
|
-
const key = assignment.slice(0, separatorIndex).trim();
|
|
189
|
-
const value = assignment.slice(separatorIndex + 1);
|
|
190
|
-
if (!LINKED_TEST_ENV_NAME_PATTERN.test(key)) {
|
|
191
|
-
throw new PmCliError(`${optionName} env_set key "${key}" is invalid`, EXIT_CODE.USAGE);
|
|
192
|
-
}
|
|
193
|
-
if (LINKED_TEST_PROTECTED_ENV_KEYS.has(key.toUpperCase())) {
|
|
194
|
-
throw new PmCliError(`${optionName} env_set key "${key}" is reserved for sandbox safety`, EXIT_CODE.USAGE);
|
|
195
|
-
}
|
|
196
|
-
envSet[key] = value;
|
|
197
|
-
}
|
|
198
|
-
return Object.keys(envSet).length > 0 ? envSet : undefined;
|
|
199
|
-
}
|
|
200
|
-
function parseLinkedTestEnvClearValue(raw, optionName) {
|
|
201
|
-
if (!raw || raw.trim().length === 0) {
|
|
202
|
-
return undefined;
|
|
203
|
-
}
|
|
204
|
-
const values = [...new Set(raw.split(/[;,\n]/).map((entry) => entry.trim()).filter((entry) => entry.length > 0))];
|
|
205
|
-
if (values.length === 0) {
|
|
206
|
-
throw new PmCliError(`${optionName} env_clear must include at least one environment variable name`, EXIT_CODE.USAGE);
|
|
207
|
-
}
|
|
208
|
-
for (const key of values) {
|
|
209
|
-
if (!LINKED_TEST_ENV_NAME_PATTERN.test(key)) {
|
|
210
|
-
throw new PmCliError(`${optionName} env_clear key "${key}" is invalid`, EXIT_CODE.USAGE);
|
|
211
|
-
}
|
|
212
|
-
if (LINKED_TEST_PROTECTED_ENV_KEYS.has(key.toUpperCase())) {
|
|
213
|
-
throw new PmCliError(`${optionName} env_clear key "${key}" is reserved for sandbox safety`, EXIT_CODE.USAGE);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
return values;
|
|
217
|
-
}
|
|
218
|
-
function parseLinkedTestStringList(raw) {
|
|
219
|
-
if (!raw || raw.trim().length === 0) {
|
|
220
|
-
return undefined;
|
|
221
|
-
}
|
|
222
|
-
const values = [...new Set(raw.split(/[;\n]/).map((entry) => entry.trim()).filter((entry) => entry.length > 0))];
|
|
223
|
-
return values.length > 0 ? values : undefined;
|
|
224
|
-
}
|
|
225
|
-
function parseLinkedTestRegexList(raw, optionName, fieldLabel) {
|
|
226
|
-
const values = parseLinkedTestStringList(raw);
|
|
227
|
-
if (!values || values.length === 0) {
|
|
228
|
-
return undefined;
|
|
229
|
-
}
|
|
230
|
-
for (const pattern of values) {
|
|
231
|
-
try {
|
|
232
|
-
// Validate syntax when linked-test metadata is added.
|
|
233
|
-
new RegExp(pattern, "m");
|
|
234
|
-
}
|
|
235
|
-
catch (error) {
|
|
236
|
-
throw new PmCliError(`${optionName} ${fieldLabel} includes invalid regex "${pattern}": ${error instanceof Error ? error.message : String(error)}`, EXIT_CODE.USAGE);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
return values;
|
|
240
|
-
}
|
|
241
|
-
function parseLinkedTestMinLines(raw, optionName) {
|
|
242
|
-
if (!raw || raw.trim().length === 0) {
|
|
243
|
-
return undefined;
|
|
244
|
-
}
|
|
245
|
-
const parsed = parseOptionalNumber(raw, "assert_stdout_min_lines");
|
|
246
|
-
if (!Number.isInteger(parsed) || parsed < 0) {
|
|
247
|
-
throw new PmCliError(`${optionName} assert_stdout_min_lines must be an integer >= 0`, EXIT_CODE.USAGE);
|
|
248
|
-
}
|
|
249
|
-
return parsed;
|
|
250
|
-
}
|
|
251
|
-
function parseLinkedTestAssertionEqualsMap(raw, optionName) {
|
|
252
|
-
if (!raw || raw.trim().length === 0) {
|
|
253
|
-
return undefined;
|
|
254
|
-
}
|
|
255
|
-
const assignments = raw
|
|
256
|
-
.split(/[;\n]/)
|
|
257
|
-
.map((entry) => entry.trim())
|
|
258
|
-
.filter((entry) => entry.length > 0);
|
|
259
|
-
if (assignments.length === 0) {
|
|
260
|
-
throw new PmCliError(`${optionName} assert_json_field_equals must include at least one path=value assignment`, EXIT_CODE.USAGE);
|
|
261
|
-
}
|
|
262
|
-
const values = {};
|
|
263
|
-
for (const assignment of assignments) {
|
|
264
|
-
const separatorIndex = assignment.indexOf("=");
|
|
265
|
-
if (separatorIndex <= 0) {
|
|
266
|
-
throw new PmCliError(`${optionName} assert_json_field_equals entries must use path=value and be separated by semicolons`, EXIT_CODE.USAGE);
|
|
267
|
-
}
|
|
268
|
-
const key = assignment.slice(0, separatorIndex).trim();
|
|
269
|
-
const value = assignment.slice(separatorIndex + 1).trim();
|
|
270
|
-
if (key.length === 0 || value.length === 0) {
|
|
271
|
-
throw new PmCliError(`${optionName} assert_json_field_equals entries must include non-empty path and value`, EXIT_CODE.USAGE);
|
|
272
|
-
}
|
|
273
|
-
values[key] = value;
|
|
274
|
-
}
|
|
275
|
-
return Object.keys(values).length > 0 ? values : undefined;
|
|
276
|
-
}
|
|
277
|
-
function parseLinkedTestAssertionGteMap(raw, optionName) {
|
|
278
|
-
if (!raw || raw.trim().length === 0) {
|
|
279
|
-
return undefined;
|
|
280
|
-
}
|
|
281
|
-
const assignments = raw
|
|
282
|
-
.split(/[;\n]/)
|
|
283
|
-
.map((entry) => entry.trim())
|
|
284
|
-
.filter((entry) => entry.length > 0);
|
|
285
|
-
if (assignments.length === 0) {
|
|
286
|
-
throw new PmCliError(`${optionName} assert_json_field_gte must include at least one path=value assignment`, EXIT_CODE.USAGE);
|
|
287
|
-
}
|
|
288
|
-
const values = {};
|
|
289
|
-
for (const assignment of assignments) {
|
|
290
|
-
const separatorIndex = assignment.indexOf("=");
|
|
291
|
-
if (separatorIndex <= 0) {
|
|
292
|
-
throw new PmCliError(`${optionName} assert_json_field_gte entries must use path=value and be separated by semicolons`, EXIT_CODE.USAGE);
|
|
293
|
-
}
|
|
294
|
-
const key = assignment.slice(0, separatorIndex).trim();
|
|
295
|
-
const valueRaw = assignment.slice(separatorIndex + 1).trim();
|
|
296
|
-
if (key.length === 0 || valueRaw.length === 0) {
|
|
297
|
-
throw new PmCliError(`${optionName} assert_json_field_gte entries must include non-empty path and value`, EXIT_CODE.USAGE);
|
|
298
|
-
}
|
|
299
|
-
const value = Number.parseFloat(valueRaw);
|
|
300
|
-
if (!Number.isFinite(value)) {
|
|
301
|
-
throw new PmCliError(`${optionName} assert_json_field_gte value for "${key}" must be numeric`, EXIT_CODE.USAGE);
|
|
302
|
-
}
|
|
303
|
-
values[key] = value;
|
|
304
|
-
}
|
|
305
|
-
return Object.keys(values).length > 0 ? values : undefined;
|
|
306
|
-
}
|
|
307
|
-
function parseLinkedTestContextModeValue(raw, optionName) {
|
|
308
|
-
if (!raw || raw.trim().length === 0) {
|
|
309
|
-
return undefined;
|
|
310
|
-
}
|
|
311
|
-
const normalized = raw.trim().toLowerCase();
|
|
312
|
-
if (PM_CONTEXT_MODE_VALUES.includes(normalized)) {
|
|
313
|
-
return normalized;
|
|
314
|
-
}
|
|
315
|
-
throw new PmCliError(`${optionName} pm_context_mode must be one of: ${PM_CONTEXT_MODE_VALUES.join(", ")}`, EXIT_CODE.USAGE);
|
|
316
|
-
}
|
|
317
156
|
function parsePmContextMode(raw) {
|
|
318
157
|
if (!raw) {
|
|
319
158
|
return "schema";
|
|
@@ -391,191 +230,10 @@ function mergeEnvClearDirectives(entries, optionName) {
|
|
|
391
230
|
}
|
|
392
231
|
return [...new Set(values)];
|
|
393
232
|
}
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
"-C",
|
|
399
|
-
"--config",
|
|
400
|
-
"--dir",
|
|
401
|
-
"--filter",
|
|
402
|
-
"--workspace-dir",
|
|
403
|
-
]);
|
|
404
|
-
const NPM_GLOBAL_FLAGS_WITH_VALUE = new Set(["-C", "--prefix", "--userconfig", "--cache"]);
|
|
405
|
-
const YARN_GLOBAL_FLAGS_WITH_VALUE = new Set(["--cwd"]);
|
|
406
|
-
const BUN_GLOBAL_FLAGS_WITH_VALUE = new Set(["--cwd"]);
|
|
407
|
-
const NPM_EXEC_SUBCOMMANDS = new Set(["exec", "x"]);
|
|
408
|
-
const SCRIPT_RUN_SUBCOMMANDS = new Set(["run", "run-script"]);
|
|
409
|
-
const SCRIPT_RUN_FLAGS_WITH_VALUE = new Set(["-C", "--dir", "--cwd", "-w", "--workspace", "--filter"]);
|
|
410
|
-
function splitNormalizedCommandSegments(normalizedCommand) {
|
|
411
|
-
return normalizedCommand
|
|
412
|
-
.split(/&&|\|\||\||;/)
|
|
413
|
-
.map((segment) => segment.trim())
|
|
414
|
-
.filter((segment) => segment.length > 0);
|
|
415
|
-
}
|
|
416
|
-
function stripLeadingEnvAssignments(tokens) {
|
|
417
|
-
let start = 0;
|
|
418
|
-
if (tokens[start] === "env") {
|
|
419
|
-
start += 1;
|
|
420
|
-
}
|
|
421
|
-
while (start < tokens.length) {
|
|
422
|
-
const token = tokens[start];
|
|
423
|
-
if (/^(?:[a-z_][a-z0-9_]*|\$env:[a-z_][a-z0-9_]*)=.*/.test(token)) {
|
|
424
|
-
start += 1;
|
|
425
|
-
continue;
|
|
426
|
-
}
|
|
427
|
-
break;
|
|
428
|
-
}
|
|
429
|
-
return tokens.slice(start);
|
|
430
|
-
}
|
|
431
|
-
function firstPmSubcommand(args) {
|
|
432
|
-
let index = 0;
|
|
433
|
-
while (index < args.length) {
|
|
434
|
-
const token = args[index];
|
|
435
|
-
if (token === "--") {
|
|
436
|
-
index += 1;
|
|
437
|
-
continue;
|
|
438
|
-
}
|
|
439
|
-
if (token.startsWith("-")) {
|
|
440
|
-
if (PM_GLOBAL_FLAGS_WITH_VALUE.has(token)) {
|
|
441
|
-
index += 2;
|
|
442
|
-
continue;
|
|
443
|
-
}
|
|
444
|
-
index += 1;
|
|
445
|
-
continue;
|
|
446
|
-
}
|
|
447
|
-
return token;
|
|
448
|
-
}
|
|
449
|
-
return undefined;
|
|
450
|
-
}
|
|
451
|
-
function isPmExecutableToken(token) {
|
|
452
|
-
return token === "pm" || token.endsWith("/pm") || token.endsWith("/pm.cmd") || token.endsWith("/pm.exe");
|
|
453
|
-
}
|
|
454
|
-
function normalizePackageSpecifier(token) {
|
|
455
|
-
const trimmed = token.trim();
|
|
456
|
-
if (!trimmed.startsWith("@")) {
|
|
457
|
-
const versionSeparator = trimmed.indexOf("@");
|
|
458
|
-
return versionSeparator === -1 ? trimmed : trimmed.slice(0, versionSeparator);
|
|
459
|
-
}
|
|
460
|
-
const scopeSeparator = trimmed.indexOf("/");
|
|
461
|
-
if (scopeSeparator === -1) {
|
|
462
|
-
return trimmed;
|
|
463
|
-
}
|
|
464
|
-
const versionSeparator = trimmed.indexOf("@", scopeSeparator + 1);
|
|
465
|
-
return versionSeparator === -1 ? trimmed : trimmed.slice(0, versionSeparator);
|
|
466
|
-
}
|
|
467
|
-
function isPmCliPackageToken(token) {
|
|
468
|
-
const normalizedSpecifier = normalizePackageSpecifier(token);
|
|
469
|
-
return (normalizedSpecifier === "pm-cli" ||
|
|
470
|
-
normalizedSpecifier.endsWith("/pm-cli") ||
|
|
471
|
-
token === "pm-cli" ||
|
|
472
|
-
token.endsWith("/pm-cli"));
|
|
473
|
-
}
|
|
474
|
-
function isPmCliScriptToken(token) {
|
|
475
|
-
return token === "dist/cli.js" || token === "./dist/cli.js" || token.endsWith("/dist/cli.js");
|
|
476
|
-
}
|
|
477
|
-
function parseNpxCommand(tokens) {
|
|
478
|
-
let index = 0;
|
|
479
|
-
while (index < tokens.length) {
|
|
480
|
-
const token = tokens[index];
|
|
481
|
-
if (token === "--") {
|
|
482
|
-
index += 1;
|
|
483
|
-
break;
|
|
484
|
-
}
|
|
485
|
-
if (!token.startsWith("-")) {
|
|
486
|
-
break;
|
|
487
|
-
}
|
|
488
|
-
if (token.includes("=")) {
|
|
489
|
-
index += 1;
|
|
490
|
-
continue;
|
|
491
|
-
}
|
|
492
|
-
if (NPX_FLAGS_WITH_VALUE.has(token)) {
|
|
493
|
-
index += 2;
|
|
494
|
-
continue;
|
|
495
|
-
}
|
|
496
|
-
index += 1;
|
|
497
|
-
}
|
|
498
|
-
const command = tokens[index];
|
|
499
|
-
if (!command) {
|
|
500
|
-
return null;
|
|
501
|
-
}
|
|
502
|
-
return {
|
|
503
|
-
command,
|
|
504
|
-
args: tokens.slice(index + 1),
|
|
505
|
-
};
|
|
506
|
-
}
|
|
507
|
-
function parseLauncherSubcommand(tokens, flagsWithValue) {
|
|
508
|
-
let index = 0;
|
|
509
|
-
while (index < tokens.length) {
|
|
510
|
-
const token = tokens[index];
|
|
511
|
-
if (token === "--") {
|
|
512
|
-
index += 1;
|
|
513
|
-
continue;
|
|
514
|
-
}
|
|
515
|
-
if (token.startsWith("-")) {
|
|
516
|
-
if (token.includes("=")) {
|
|
517
|
-
index += 1;
|
|
518
|
-
continue;
|
|
519
|
-
}
|
|
520
|
-
if (flagsWithValue.has(token)) {
|
|
521
|
-
index += 2;
|
|
522
|
-
continue;
|
|
523
|
-
}
|
|
524
|
-
index += 1;
|
|
525
|
-
continue;
|
|
526
|
-
}
|
|
527
|
-
return {
|
|
528
|
-
subcommand: token,
|
|
529
|
-
args: tokens.slice(index + 1),
|
|
530
|
-
};
|
|
531
|
-
}
|
|
532
|
-
return null;
|
|
533
|
-
}
|
|
534
|
-
function parsePnpmDlxCommand(tokens) {
|
|
535
|
-
const parsed = parseLauncherSubcommand(tokens, PNPM_GLOBAL_FLAGS_WITH_VALUE);
|
|
536
|
-
if (parsed?.subcommand !== "dlx") {
|
|
537
|
-
return null;
|
|
538
|
-
}
|
|
539
|
-
return parseNpxCommand(parsed.args);
|
|
540
|
-
}
|
|
541
|
-
function parseNpmExecCommand(tokens) {
|
|
542
|
-
const parsed = parseLauncherSubcommand(tokens, NPM_GLOBAL_FLAGS_WITH_VALUE);
|
|
543
|
-
if (!parsed || !NPM_EXEC_SUBCOMMANDS.has(parsed.subcommand)) {
|
|
544
|
-
return null;
|
|
545
|
-
}
|
|
546
|
-
return parseNpxCommand(parsed.args);
|
|
547
|
-
}
|
|
548
|
-
function resolvePmSubcommandContext(args) {
|
|
549
|
-
let index = 0;
|
|
550
|
-
while (index < args.length) {
|
|
551
|
-
const token = args[index];
|
|
552
|
-
if (token === "--") {
|
|
553
|
-
index += 1;
|
|
554
|
-
continue;
|
|
555
|
-
}
|
|
556
|
-
if (token.startsWith("-")) {
|
|
557
|
-
if (PM_GLOBAL_FLAGS_WITH_VALUE.has(token)) {
|
|
558
|
-
index += 2;
|
|
559
|
-
continue;
|
|
560
|
-
}
|
|
561
|
-
index += 1;
|
|
562
|
-
continue;
|
|
563
|
-
}
|
|
564
|
-
return {
|
|
565
|
-
subcommand: token,
|
|
566
|
-
remaining: args.slice(index + 1),
|
|
567
|
-
};
|
|
568
|
-
}
|
|
569
|
-
return null;
|
|
570
|
-
}
|
|
571
|
-
function firstPositionalToken(tokens) {
|
|
572
|
-
for (const token of tokens) {
|
|
573
|
-
if (!token.startsWith("-")) {
|
|
574
|
-
return token;
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
return undefined;
|
|
578
|
-
}
|
|
233
|
+
// Linked-test command detection helpers + constants live in a sibling leaf
|
|
234
|
+
// module to keep this command file under the per-file LOC budget. Re-exported
|
|
235
|
+
// here so no consumer outside this file changes.
|
|
236
|
+
import { BUN_GLOBAL_FLAGS_WITH_VALUE, NPM_GLOBAL_FLAGS_WITH_VALUE, PNPM_GLOBAL_FLAGS_WITH_VALUE, SCRIPT_RUN_FLAGS_WITH_VALUE, SCRIPT_RUN_SUBCOMMANDS, YARN_GLOBAL_FLAGS_WITH_VALUE, firstPmSubcommand, firstPositionalToken, isPmCliPackageToken, isPmCliScriptToken, isPmExecutableToken, parseLauncherSubcommand, parseNpmExecCommand, parseNpxCommand, parsePnpmDlxCommand, resolvePmSubcommandContext, splitNormalizedCommandSegments, stripLeadingEnvAssignments, } from "./test/linked-command-detection.js";
|
|
579
237
|
function looksLikePrefixedItemId(token, idPrefix) {
|
|
580
238
|
const normalizedPrefix = idPrefix.trim().toLowerCase().replace(/-+$/, "");
|
|
581
239
|
if (normalizedPrefix.length === 0) {
|
|
@@ -783,7 +441,7 @@ function assertSandboxSafeTestRunnerCommand(command) {
|
|
|
783
441
|
if (!hasUnsafeDirectRunnerSegment) {
|
|
784
442
|
return;
|
|
785
443
|
}
|
|
786
|
-
throw new PmCliError('Linked test runner commands must be sandbox-safe: use "node scripts/run-tests.mjs <test|coverage>" or
|
|
444
|
+
throw new PmCliError('Linked test runner commands must be sandbox-safe: use "node scripts/run-tests.mjs <test|coverage>" or include PM_PATH=... PM_GLOBAL_PATH=... INLINE in the command string (exporting them in your shell environment is not checked). Example: "PM_PATH=/tmp/pm-x PM_GLOBAL_PATH=/tmp/pm-x-g vitest run".', EXIT_CODE.USAGE);
|
|
787
445
|
}
|
|
788
446
|
function getRuntimeSafetySkipReason(command) {
|
|
789
447
|
if (!invokesRecursiveTestAllCommand(command))
|
|
@@ -1824,4 +1482,4 @@ export async function runTest(id, options, global) {
|
|
|
1824
1482
|
};
|
|
1825
1483
|
}
|
|
1826
1484
|
//# sourceMappingURL=test.js.map
|
|
1827
|
-
//# debugId=
|
|
1485
|
+
//# debugId=f4d1b3b4-fb85-5127-a4b7-7877a66286e8
|