prodex 2.0.1 → 2.1.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/README.md +367 -146
- package/dist/app/dependency-source-provider.d.ts +2 -0
- package/dist/app/dependency-source-provider.js +66 -0
- package/dist/app/entry-resolver.d.ts +7 -0
- package/dist/app/entry-resolver.js +26 -0
- package/dist/app/execute-run.d.ts +2 -2
- package/dist/app/execute-run.js +138 -37
- package/dist/app/git-source-provider.d.ts +4 -0
- package/dist/app/git-source-provider.js +551 -0
- package/dist/app/grep-source-provider.d.ts +2 -0
- package/dist/app/grep-source-provider.js +226 -0
- package/dist/app/planner.d.ts +12 -0
- package/dist/app/planner.js +106 -0
- package/dist/app/planners/attachment-options.d.ts +2 -0
- package/dist/app/planners/attachment-options.js +39 -0
- package/dist/app/planners/git-plan.d.ts +13 -0
- package/dist/app/planners/git-plan.js +141 -0
- package/dist/app/planners/grep-plan.d.ts +13 -0
- package/dist/app/planners/grep-plan.js +115 -0
- package/dist/app/planners/list-utils.d.ts +1 -0
- package/dist/app/planners/list-utils.js +6 -0
- package/dist/app/planners/pack-plan.d.ts +13 -0
- package/dist/app/planners/pack-plan.js +65 -0
- package/dist/app/planners/scope-plan.d.ts +17 -0
- package/dist/app/planners/scope-plan.js +143 -0
- package/dist/app/planners/trace-plan.d.ts +13 -0
- package/dist/app/planners/trace-plan.js +77 -0
- package/dist/app/source-collector.d.ts +5 -0
- package/dist/app/source-collector.js +33 -0
- package/dist/app/target-resolver.d.ts +7 -0
- package/dist/app/target-resolver.js +110 -0
- package/dist/cli/cli-input.js +70 -19
- package/dist/cli/flag-specs.d.ts +7 -3
- package/dist/cli/flag-specs.js +58 -8
- package/dist/cli/help-specs.d.ts +205 -0
- package/dist/cli/help-specs.js +136 -0
- package/dist/cli/help.js +107 -28
- package/dist/cli/report-command.js +35 -23
- package/dist/commands/{run-command.d.ts → git-command.d.ts} +3 -3
- package/dist/commands/git-command.js +7 -0
- package/dist/commands/grep-command.d.ts +11 -0
- package/dist/commands/grep-command.js +7 -0
- package/dist/commands/pack-command.d.ts +11 -0
- package/dist/commands/pack-command.js +7 -0
- package/dist/commands/scope-command.d.ts +12 -0
- package/dist/commands/scope-command.js +7 -0
- package/dist/commands/shared-runner.d.ts +12 -0
- package/dist/commands/shared-runner.js +30 -0
- package/dist/commands/trace-command.d.ts +11 -0
- package/dist/commands/trace-command.js +7 -0
- package/dist/config/default-config.js +7 -11
- package/dist/config/load.d.ts +1 -0
- package/dist/config/load.js +269 -4
- package/dist/config/migration/detect.d.ts +2 -1
- package/dist/config/migration/detect.js +10 -2
- package/dist/config/migration/messages.js +12 -11
- package/dist/config/migration/transform.js +77 -32
- package/dist/filesystem/binary.d.ts +2 -0
- package/dist/filesystem/binary.js +30 -0
- package/dist/filesystem/entry-discovery.d.ts +14 -0
- package/dist/filesystem/entry-discovery.js +78 -0
- package/dist/filesystem/file-set.d.ts +7 -0
- package/dist/filesystem/file-set.js +57 -0
- package/dist/filesystem/glob-scan.d.ts +6 -2
- package/dist/filesystem/glob-scan.js +12 -7
- package/dist/filesystem/path-patterns.d.ts +20 -0
- package/dist/filesystem/path-patterns.js +70 -0
- package/dist/index.js +51 -29
- package/dist/output/markdown-sections.d.ts +5 -0
- package/dist/output/markdown-sections.js +103 -0
- package/dist/output/markdown-toc.d.ts +31 -0
- package/dist/output/markdown-toc.js +287 -0
- package/dist/output/markdown.d.ts +5 -8
- package/dist/output/markdown.js +80 -127
- package/dist/output/produce-output.d.ts +4 -1
- package/dist/output/produce-output.js +6 -7
- package/dist/output/render-helpers.d.ts +4 -0
- package/dist/output/render-helpers.js +14 -0
- package/dist/output/text.d.ts +2 -2
- package/dist/output/text.js +47 -8
- package/dist/resolvers/js/resolve-alias.js +10 -41
- package/dist/resolvers/php/bindings.js +6 -6
- package/dist/resolvers/php/extract-imports.d.ts +19 -7
- package/dist/resolvers/php/extract-imports.js +146 -26
- package/dist/resolvers/php/php-resolver.js +55 -24
- package/dist/resolvers/php/psr4.d.ts +1 -1
- package/dist/resolvers/php/psr4.js +7 -1
- package/dist/runtime/shell-command-runner.d.ts +5 -0
- package/dist/runtime/shell-command-runner.js +118 -0
- package/dist/tracing/collect-trace.d.ts +10 -0
- package/dist/tracing/collect-trace.js +23 -0
- package/dist/tracing/exclude.d.ts +0 -5
- package/dist/tracing/exclude.js +16 -12
- package/dist/tracing/follow-chain.js +2 -2
- package/dist/types/app.types.d.ts +37 -8
- package/dist/types/artifact.types.d.ts +50 -0
- package/dist/types/artifact.types.js +2 -0
- package/dist/types/cli.types.d.ts +52 -4
- package/dist/types/config.types.d.ts +37 -20
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +2 -0
- package/dist/types/output.types.d.ts +12 -3
- package/dist/types/planner.types.d.ts +76 -0
- package/dist/types/planner.types.js +2 -0
- package/dist/types/resolver.types.d.ts +1 -1
- package/dist/types/tracing.types.d.ts +0 -11
- package/package.json +2 -2
- package/schema/prodex.schema.json +59 -41
- package/dist/app/run-plans.d.ts +0 -11
- package/dist/app/run-plans.js +0 -61
- package/dist/commands/profiles-command.d.ts +0 -6
- package/dist/commands/profiles-command.js +0 -16
- package/dist/commands/run-command.js +0 -17
- package/dist/config/build-config.d.ts +0 -13
- package/dist/config/build-config.js +0 -127
- package/dist/tracing/include-files.d.ts +0 -2
- package/dist/tracing/include-files.js +0 -36
- package/dist/tracing/trace-run.d.ts +0 -2
- package/dist/tracing/trace-run.js +0 -21
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ExecutionPlan, CommandIntent, ProdexConfigFile, CommandAttachmentOptions } from "../../types";
|
|
2
|
+
export declare function buildPackPlan(params: {
|
|
3
|
+
intent: CommandIntent;
|
|
4
|
+
userConfig: ProdexConfigFile;
|
|
5
|
+
root: string;
|
|
6
|
+
aliases: Record<string, string>;
|
|
7
|
+
depth: number;
|
|
8
|
+
maxFiles: number;
|
|
9
|
+
defaultOutput: ExecutionPlan["output"];
|
|
10
|
+
attachmentOptions: CommandAttachmentOptions | undefined;
|
|
11
|
+
warnings: string[];
|
|
12
|
+
errors: string[];
|
|
13
|
+
}): ExecutionPlan[];
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildPackPlan = buildPackPlan;
|
|
4
|
+
const path_patterns_1 = require("../../filesystem/path-patterns");
|
|
5
|
+
const list_utils_1 = require("./list-utils");
|
|
6
|
+
function buildPackPlan(params) {
|
|
7
|
+
const { intent, userConfig, root, aliases, depth, maxFiles, defaultOutput, attachmentOptions, warnings, errors } = params;
|
|
8
|
+
const flags = intent.flags ?? {};
|
|
9
|
+
// Validation
|
|
10
|
+
if (flags.key !== undefined || flags.all !== undefined || flags.list !== undefined) {
|
|
11
|
+
errors.push('Command "pack" does not accept "--key", "--all", or "--list".');
|
|
12
|
+
return [];
|
|
13
|
+
}
|
|
14
|
+
const hasCliEntry = flags.entry && flags.entry.length > 0;
|
|
15
|
+
const hasCliInclude = flags.include && flags.include.length > 0;
|
|
16
|
+
const hasCliScope = flags.scope && flags.scope.length > 0;
|
|
17
|
+
if (!hasCliEntry && !hasCliInclude && !hasCliScope) {
|
|
18
|
+
errors.push('Command "pack" requires at least one source: --entry, --include, or --scope.');
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
const rootExclude = userConfig.exclude ?? [];
|
|
22
|
+
const scopeEntries = [];
|
|
23
|
+
const scopeIncludes = [];
|
|
24
|
+
const scopeExcludes = [];
|
|
25
|
+
if (flags.scope && flags.scope.length > 0) {
|
|
26
|
+
for (const scopeKey of flags.scope) {
|
|
27
|
+
const scope = userConfig.scopes?.[scopeKey];
|
|
28
|
+
if (!scope) {
|
|
29
|
+
errors.push(`Unknown scope "${scopeKey}".`);
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
if (scope.entry)
|
|
33
|
+
scopeEntries.push(...scope.entry);
|
|
34
|
+
if (scope.include)
|
|
35
|
+
scopeIncludes.push(...scope.include);
|
|
36
|
+
if (scope.exclude)
|
|
37
|
+
scopeExcludes.push(...scope.exclude);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const mergedEntry = [...scopeEntries, ...(flags.entry ?? [])].map((item) => (0, path_patterns_1.normalizePathOrGlob)(item, root, { role: "entry" }));
|
|
41
|
+
const mergedInclude = [...scopeIncludes, ...(flags.include ?? [])].map((item) => (0, path_patterns_1.normalizePathOrGlob)(item, root, { role: "include" }));
|
|
42
|
+
const mergedExclude = [...rootExclude, ...scopeExcludes, ...(flags.exclude ?? [])].map((item) => (0, path_patterns_1.normalizePathOrGlob)(item, root, { role: "exclude" }));
|
|
43
|
+
if (errors.length) {
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
const plan = {
|
|
47
|
+
root,
|
|
48
|
+
command: "pack",
|
|
49
|
+
outputName: flags.name ?? "pack-combined",
|
|
50
|
+
entry: (0, list_utils_1.uniqueTrimmed)(mergedEntry),
|
|
51
|
+
include: (0, list_utils_1.uniqueTrimmed)(mergedInclude),
|
|
52
|
+
exclude: (0, list_utils_1.uniqueTrimmed)(mergedExclude),
|
|
53
|
+
depth: flags.depth ?? depth,
|
|
54
|
+
maxFiles: flags.maxFiles ?? maxFiles,
|
|
55
|
+
aliases,
|
|
56
|
+
output: {
|
|
57
|
+
dir: defaultOutput.dir,
|
|
58
|
+
versioned: defaultOutput.versioned,
|
|
59
|
+
format: flags.format ?? defaultOutput.format,
|
|
60
|
+
},
|
|
61
|
+
dryRun: !!flags.dryRun,
|
|
62
|
+
attachmentOptions,
|
|
63
|
+
};
|
|
64
|
+
return [plan];
|
|
65
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ExecutionPlan, CommandIntent, ProdexConfigFile, CommandAttachmentOptions } from "../../types";
|
|
2
|
+
export interface ScopePlanResult {
|
|
3
|
+
plans: ExecutionPlan[];
|
|
4
|
+
listScopes?: string[];
|
|
5
|
+
}
|
|
6
|
+
export declare function buildScopePlan(params: {
|
|
7
|
+
intent: CommandIntent;
|
|
8
|
+
userConfig: ProdexConfigFile;
|
|
9
|
+
root: string;
|
|
10
|
+
aliases: Record<string, string>;
|
|
11
|
+
depth: number;
|
|
12
|
+
maxFiles: number;
|
|
13
|
+
defaultOutput: ExecutionPlan["output"];
|
|
14
|
+
attachmentOptions: CommandAttachmentOptions | undefined;
|
|
15
|
+
warnings: string[];
|
|
16
|
+
errors: string[];
|
|
17
|
+
}): ScopePlanResult;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildScopePlan = buildScopePlan;
|
|
4
|
+
const path_patterns_1 = require("../../filesystem/path-patterns");
|
|
5
|
+
const list_utils_1 = require("./list-utils");
|
|
6
|
+
function buildScopePlan(params) {
|
|
7
|
+
const { intent, userConfig, root, aliases, depth, maxFiles, defaultOutput, attachmentOptions, warnings, errors } = params;
|
|
8
|
+
const flags = intent.flags ?? {};
|
|
9
|
+
// Validation
|
|
10
|
+
if (flags.entry !== undefined ||
|
|
11
|
+
flags.include !== undefined ||
|
|
12
|
+
flags.scope !== undefined ||
|
|
13
|
+
flags.name !== undefined ||
|
|
14
|
+
flags.depth !== undefined ||
|
|
15
|
+
flags.maxFiles !== undefined) {
|
|
16
|
+
errors.push('Command "scope" does not accept "--entry", "--include", "--scope", "--name", "--depth", or "--max-files".');
|
|
17
|
+
return { plans: [] };
|
|
18
|
+
}
|
|
19
|
+
const hasKey = flags.key && flags.key.length > 0;
|
|
20
|
+
const hasAll = !!flags.all;
|
|
21
|
+
const hasList = !!flags.list;
|
|
22
|
+
if (!hasKey && !hasAll && !hasList) {
|
|
23
|
+
errors.push('Command "scope" requires specifying "-k/--key", "--all", or "--list".');
|
|
24
|
+
return { plans: [] };
|
|
25
|
+
}
|
|
26
|
+
let selectedModesCount = 0;
|
|
27
|
+
if (hasKey)
|
|
28
|
+
selectedModesCount++;
|
|
29
|
+
if (hasAll)
|
|
30
|
+
selectedModesCount++;
|
|
31
|
+
if (hasList)
|
|
32
|
+
selectedModesCount++;
|
|
33
|
+
if (selectedModesCount > 1) {
|
|
34
|
+
errors.push('Command "scope" options "--key", "--all", and "--list" are mutually exclusive.');
|
|
35
|
+
return { plans: [] };
|
|
36
|
+
}
|
|
37
|
+
const availableScopes = Object.keys(userConfig.scopes ?? {}).sort();
|
|
38
|
+
if (hasList) {
|
|
39
|
+
if ((flags.cmd && flags.cmd.length > 0) || flags.cmdTimeout !== undefined || flags.failOnCmdError !== undefined) {
|
|
40
|
+
errors.push('Option "--list" cannot be used with command attachment options.');
|
|
41
|
+
return { plans: [] };
|
|
42
|
+
}
|
|
43
|
+
return { plans: [], listScopes: availableScopes };
|
|
44
|
+
}
|
|
45
|
+
if (errors.length) {
|
|
46
|
+
return { plans: [] };
|
|
47
|
+
}
|
|
48
|
+
let targetKeys = [];
|
|
49
|
+
if (hasAll) {
|
|
50
|
+
targetKeys = availableScopes;
|
|
51
|
+
if (!targetKeys.length) {
|
|
52
|
+
errors.push("No scopes are defined in prodex.json.");
|
|
53
|
+
return { plans: [] };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
else if (flags.key) {
|
|
57
|
+
for (const key of flags.key) {
|
|
58
|
+
if (!userConfig.scopes?.[key]) {
|
|
59
|
+
errors.push(`Unknown scope "${key}".`);
|
|
60
|
+
return { plans: [] };
|
|
61
|
+
}
|
|
62
|
+
targetKeys.push(key);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const plans = [];
|
|
66
|
+
for (const key of targetKeys) {
|
|
67
|
+
const scope = userConfig.scopes[key];
|
|
68
|
+
const scopeIncludes = (scope.include ?? []).map((item) => (0, path_patterns_1.normalizePathOrGlob)(item, root, { role: "include" }));
|
|
69
|
+
const scopeExcludes = [...(userConfig.exclude ?? []), ...(scope.exclude ?? []), ...(flags.exclude ?? [])].map((item) => (0, path_patterns_1.normalizePathOrGlob)(item, root, { role: "exclude" }));
|
|
70
|
+
if (scope.grep) {
|
|
71
|
+
let grepMode = "query";
|
|
72
|
+
let grepTerms = [];
|
|
73
|
+
if (scope.grep.query !== undefined) {
|
|
74
|
+
grepMode = "query";
|
|
75
|
+
grepTerms = [scope.grep.query];
|
|
76
|
+
}
|
|
77
|
+
else if (scope.grep.any !== undefined) {
|
|
78
|
+
grepMode = "any";
|
|
79
|
+
grepTerms = scope.grep.any;
|
|
80
|
+
}
|
|
81
|
+
else if (scope.grep.all !== undefined) {
|
|
82
|
+
grepMode = "all";
|
|
83
|
+
grepTerms = scope.grep.all;
|
|
84
|
+
}
|
|
85
|
+
else if (scope.grep.regex !== undefined) {
|
|
86
|
+
grepMode = "regex";
|
|
87
|
+
grepTerms = [scope.grep.regex];
|
|
88
|
+
}
|
|
89
|
+
const negativeTerms = scope.grep.not ?? [];
|
|
90
|
+
const mergedWithin = (scope.grep.within ?? []).map((item) => (0, path_patterns_1.normalizePathOrGlob)(item, root, { role: "within" }));
|
|
91
|
+
const mergedSkip = (scope.grep.skip ?? []).map((item) => (0, path_patterns_1.normalizePathOrGlob)(item, root, { role: "skip" }));
|
|
92
|
+
plans.push({
|
|
93
|
+
root,
|
|
94
|
+
command: "scope",
|
|
95
|
+
outputName: scope.name ?? key,
|
|
96
|
+
entry: [],
|
|
97
|
+
include: scopeIncludes,
|
|
98
|
+
exclude: (0, list_utils_1.uniqueTrimmed)(scopeExcludes),
|
|
99
|
+
depth,
|
|
100
|
+
maxFiles,
|
|
101
|
+
aliases,
|
|
102
|
+
output: {
|
|
103
|
+
dir: defaultOutput.dir,
|
|
104
|
+
versioned: defaultOutput.versioned,
|
|
105
|
+
format: flags.format ?? defaultOutput.format,
|
|
106
|
+
},
|
|
107
|
+
dryRun: !!flags.dryRun,
|
|
108
|
+
scopeKey: key,
|
|
109
|
+
attachmentOptions,
|
|
110
|
+
grepOptions: {
|
|
111
|
+
mode: grepMode,
|
|
112
|
+
terms: grepTerms,
|
|
113
|
+
negativeTerms: (0, list_utils_1.uniqueTrimmed)(negativeTerms),
|
|
114
|
+
within: (0, list_utils_1.uniqueTrimmed)(mergedWithin),
|
|
115
|
+
skip: (0, list_utils_1.uniqueTrimmed)(mergedSkip),
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
const scopeEntries = (scope.entry ?? []).map((item) => (0, path_patterns_1.normalizePathOrGlob)(item, root, { role: "entry" }));
|
|
121
|
+
plans.push({
|
|
122
|
+
root,
|
|
123
|
+
command: "scope",
|
|
124
|
+
outputName: scope.name ?? key,
|
|
125
|
+
entry: scopeEntries,
|
|
126
|
+
include: scopeIncludes,
|
|
127
|
+
exclude: (0, list_utils_1.uniqueTrimmed)(scopeExcludes),
|
|
128
|
+
depth,
|
|
129
|
+
maxFiles,
|
|
130
|
+
aliases,
|
|
131
|
+
output: {
|
|
132
|
+
dir: defaultOutput.dir,
|
|
133
|
+
versioned: defaultOutput.versioned,
|
|
134
|
+
format: flags.format ?? defaultOutput.format,
|
|
135
|
+
},
|
|
136
|
+
dryRun: !!flags.dryRun,
|
|
137
|
+
scopeKey: key,
|
|
138
|
+
attachmentOptions,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return { plans };
|
|
143
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ExecutionPlan, CommandIntent, ProdexConfigFile, CommandAttachmentOptions } from "../../types";
|
|
2
|
+
export declare function buildTracePlan(params: {
|
|
3
|
+
intent: CommandIntent;
|
|
4
|
+
userConfig: ProdexConfigFile;
|
|
5
|
+
root: string;
|
|
6
|
+
aliases: Record<string, string>;
|
|
7
|
+
depth: number;
|
|
8
|
+
maxFiles: number;
|
|
9
|
+
defaultOutput: ExecutionPlan["output"];
|
|
10
|
+
attachmentOptions: CommandAttachmentOptions | undefined;
|
|
11
|
+
warnings: string[];
|
|
12
|
+
errors: string[];
|
|
13
|
+
}): ExecutionPlan[];
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildTracePlan = buildTracePlan;
|
|
4
|
+
const default_config_1 = require("../../config/default-config");
|
|
5
|
+
const path_patterns_1 = require("../../filesystem/path-patterns");
|
|
6
|
+
const list_utils_1 = require("./list-utils");
|
|
7
|
+
function buildTracePlan(params) {
|
|
8
|
+
const { intent, userConfig, root, aliases, depth, maxFiles, defaultOutput, attachmentOptions, warnings, errors } = params;
|
|
9
|
+
const flags = intent.flags ?? {};
|
|
10
|
+
// Validation
|
|
11
|
+
if (flags.entry && flags.entry.length > 0) {
|
|
12
|
+
errors.push("`prodex trace --entry` has been removed.\n" +
|
|
13
|
+
"Use `prodex trace --target <target> --depth <number>` to trace from a semantic target.\n" +
|
|
14
|
+
"Use `prodex pack --entry <path-or-glob>` to collect files directly.");
|
|
15
|
+
}
|
|
16
|
+
if (flags.scope !== undefined) {
|
|
17
|
+
errors.push('Command "trace" does not accept "--scope" (or "-s").');
|
|
18
|
+
}
|
|
19
|
+
if (flags.key !== undefined || flags.all !== undefined || flags.list !== undefined) {
|
|
20
|
+
errors.push('Command "trace" does not accept "--key", "--all", or "--list".');
|
|
21
|
+
}
|
|
22
|
+
let finalDepth = depth;
|
|
23
|
+
const configDepth = userConfig.depth !== undefined && userConfig.depth !== null ? userConfig.depth : default_config_1.DEFAULT_PRODEX_CONFIG.depth;
|
|
24
|
+
const hasTarget = flags.target && flags.target.length > 0;
|
|
25
|
+
if (!hasTarget) {
|
|
26
|
+
if (!flags.entry || flags.entry.length === 0) {
|
|
27
|
+
errors.push('Command "trace" requires --target.');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
// Validate configured default depth
|
|
32
|
+
const configDepthVal = Number(configDepth);
|
|
33
|
+
if (!Number.isInteger(configDepthVal) || configDepthVal < 0) {
|
|
34
|
+
errors.push('--depth must be an integer greater than or equal to 0.');
|
|
35
|
+
}
|
|
36
|
+
if (flags.depth !== undefined && flags.depth !== null) {
|
|
37
|
+
const depthVal = Number(flags.depth);
|
|
38
|
+
if (!Number.isInteger(depthVal) || depthVal < 0) {
|
|
39
|
+
errors.push('--depth must be an integer greater than or equal to 0.');
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
finalDepth = depthVal;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
if (Number.isInteger(configDepthVal) && configDepthVal >= 0) {
|
|
47
|
+
finalDepth = configDepthVal;
|
|
48
|
+
warnings.push(`No --depth provided. Using configured default depth: ${finalDepth}.\n` +
|
|
49
|
+
`Override with --depth <number> or -d <number>.`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (errors.length)
|
|
54
|
+
return [];
|
|
55
|
+
const mergedExclude = [...(userConfig.exclude ?? []), ...(flags.exclude ?? [])].map((item) => (0, path_patterns_1.normalizePathOrGlob)(item, root, { role: "exclude" }));
|
|
56
|
+
const finalInclude = (flags.include ?? []).map((item) => (0, path_patterns_1.normalizePathOrGlob)(item, root, { role: "include" }));
|
|
57
|
+
const plan = {
|
|
58
|
+
root,
|
|
59
|
+
command: "trace",
|
|
60
|
+
outputName: flags.name,
|
|
61
|
+
entry: [],
|
|
62
|
+
target: (0, list_utils_1.uniqueTrimmed)(flags.target ?? []),
|
|
63
|
+
include: (0, list_utils_1.uniqueTrimmed)(finalInclude),
|
|
64
|
+
exclude: (0, list_utils_1.uniqueTrimmed)(mergedExclude),
|
|
65
|
+
depth: finalDepth,
|
|
66
|
+
maxFiles: flags.maxFiles ?? maxFiles,
|
|
67
|
+
aliases,
|
|
68
|
+
output: {
|
|
69
|
+
dir: defaultOutput.dir,
|
|
70
|
+
versioned: defaultOutput.versioned,
|
|
71
|
+
format: flags.format ?? defaultOutput.format,
|
|
72
|
+
},
|
|
73
|
+
dryRun: !!flags.dryRun,
|
|
74
|
+
attachmentOptions,
|
|
75
|
+
};
|
|
76
|
+
return [plan];
|
|
77
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.collectSources = collectSources;
|
|
4
|
+
const dependency_source_provider_1 = require("./dependency-source-provider");
|
|
5
|
+
const git_source_provider_1 = require("./git-source-provider");
|
|
6
|
+
const grep_source_provider_1 = require("./grep-source-provider");
|
|
7
|
+
async function collectSources(plan) {
|
|
8
|
+
switch (plan.command) {
|
|
9
|
+
case "pack":
|
|
10
|
+
case "trace":
|
|
11
|
+
return (0, dependency_source_provider_1.collectDependencySources)(plan);
|
|
12
|
+
case "scope":
|
|
13
|
+
if (plan.grepOptions !== undefined) {
|
|
14
|
+
return (0, grep_source_provider_1.collectGrepSources)(plan);
|
|
15
|
+
}
|
|
16
|
+
return (0, dependency_source_provider_1.collectDependencySources)(plan);
|
|
17
|
+
case "git":
|
|
18
|
+
return (0, git_source_provider_1.collectGitSources)(plan);
|
|
19
|
+
case "grep":
|
|
20
|
+
return (0, grep_source_provider_1.collectGrepSources)(plan);
|
|
21
|
+
default: {
|
|
22
|
+
const exhaustiveCheck = plan.command;
|
|
23
|
+
return {
|
|
24
|
+
files: [],
|
|
25
|
+
entries: [],
|
|
26
|
+
includes: [],
|
|
27
|
+
mode: "include-only",
|
|
28
|
+
warnings: [],
|
|
29
|
+
errors: [`Unsupported command kind for source collection: ${exhaustiveCheck}`],
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.resolveTargets = resolveTargets;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const exclude_1 = require("../tracing/exclude");
|
|
10
|
+
const entry_discovery_1 = require("../filesystem/entry-discovery");
|
|
11
|
+
const path_patterns_1 = require("../filesystem/path-patterns");
|
|
12
|
+
// runBareNameDiscovery consolidated into discoverBareName from entry-discovery
|
|
13
|
+
function formatAmbiguousTargetError(target, candidates, root) {
|
|
14
|
+
const formattedMatches = candidates
|
|
15
|
+
.map((c) => `- ${path_1.default.relative(root, c).replaceAll("\\", "/")}`)
|
|
16
|
+
.join("\n");
|
|
17
|
+
const exampleCandidate = candidates[1] || candidates[0];
|
|
18
|
+
const relativeCandidate = path_1.default.relative(root, exampleCandidate).replaceAll("\\", "/");
|
|
19
|
+
const ext = path_1.default.extname(relativeCandidate);
|
|
20
|
+
const suggestion = ext ? relativeCandidate.slice(0, -ext.length) : relativeCandidate;
|
|
21
|
+
const targetStem = path_1.default.basename(target, path_1.default.extname(target));
|
|
22
|
+
const uniqueExts = [...new Set(candidates.map((c) => path_1.default.extname(c).toLowerCase()))];
|
|
23
|
+
const extensionsDiffer = uniqueExts.length > 1;
|
|
24
|
+
const packExtension = extensionsDiffer ? ".*" : (uniqueExts[0] || ".ts");
|
|
25
|
+
return `Ambiguous target "${target}". Matches:\n` +
|
|
26
|
+
`${formattedMatches}\n\n` +
|
|
27
|
+
`Use a more specific target, such as:\n` +
|
|
28
|
+
` prodex trace --target ${suggestion} --depth 2\n\n` +
|
|
29
|
+
`If you intended to collect all matching files directly, use a glob with pack:\n` +
|
|
30
|
+
` prodex pack --entry "src/**/${targetStem}${packExtension}"`;
|
|
31
|
+
}
|
|
32
|
+
async function resolveTargets(plan) {
|
|
33
|
+
const resolved = [];
|
|
34
|
+
const errors = [];
|
|
35
|
+
const warnings = [];
|
|
36
|
+
const root = plan.root;
|
|
37
|
+
const excludes = plan.exclude;
|
|
38
|
+
const targets = plan.target ?? [];
|
|
39
|
+
for (const target of targets) {
|
|
40
|
+
if ((0, path_patterns_1.isGlobPattern)(target)) {
|
|
41
|
+
errors.push(`Command "trace" does not accept glob targets.\n` +
|
|
42
|
+
`Use \`prodex pack --entry <glob>\` to collect files directly.`);
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
// 1. Exact path match
|
|
46
|
+
const absPath = path_1.default.resolve(root, target);
|
|
47
|
+
let isFile = false;
|
|
48
|
+
try {
|
|
49
|
+
isFile = fs_1.default.statSync(absPath).isFile();
|
|
50
|
+
}
|
|
51
|
+
catch { }
|
|
52
|
+
if (isFile) {
|
|
53
|
+
if (!(0, exclude_1.isExcluded)(absPath, excludes, root)) {
|
|
54
|
+
resolved.push(absPath);
|
|
55
|
+
}
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
// 2. Extensionless path expansion
|
|
59
|
+
const hasExt = path_1.default.extname(target) !== "";
|
|
60
|
+
if (!hasExt) {
|
|
61
|
+
const step2Matches = (0, entry_discovery_1.expandPathLike)(target, root);
|
|
62
|
+
const step2NonExcluded = step2Matches.filter((file) => !(0, exclude_1.isExcluded)(file, excludes, root));
|
|
63
|
+
if (step2NonExcluded.length > 0) {
|
|
64
|
+
if (step2NonExcluded.length === 1) {
|
|
65
|
+
resolved.push(step2NonExcluded[0]);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
errors.push(formatAmbiguousTargetError(target, step2NonExcluded, root));
|
|
69
|
+
}
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// 3. Bare-name discovery
|
|
74
|
+
const isPathLike = target.includes("/") || target.includes("\\");
|
|
75
|
+
if (!isPathLike) {
|
|
76
|
+
const step3Matches = await (0, entry_discovery_1.discoverBareName)(target, root, true);
|
|
77
|
+
const step3NonExcluded = step3Matches.filter((file) => !(0, exclude_1.isExcluded)(file, excludes, root));
|
|
78
|
+
if (step3NonExcluded.length > 0) {
|
|
79
|
+
if (step3NonExcluded.length === 1) {
|
|
80
|
+
resolved.push(step3NonExcluded[0]);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
errors.push(formatAmbiguousTargetError(target, step3NonExcluded, root));
|
|
84
|
+
}
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// 4. Case-insensitive bare-name discovery
|
|
89
|
+
if (!isPathLike) {
|
|
90
|
+
const step4Matches = await (0, entry_discovery_1.discoverBareName)(target, root, false);
|
|
91
|
+
const step4NonExcluded = step4Matches.filter((file) => !(0, exclude_1.isExcluded)(file, excludes, root));
|
|
92
|
+
if (step4NonExcluded.length > 0) {
|
|
93
|
+
if (step4NonExcluded.length === 1) {
|
|
94
|
+
resolved.push(step4NonExcluded[0]);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
errors.push(formatAmbiguousTargetError(target, step4NonExcluded, root));
|
|
98
|
+
}
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// Fail clearly if no matches found
|
|
103
|
+
errors.push(`Target "${target}" did not match any files.`);
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
entries: [...new Set(resolved)],
|
|
107
|
+
errors,
|
|
108
|
+
warnings,
|
|
109
|
+
};
|
|
110
|
+
}
|
package/dist/cli/cli-input.js
CHANGED
|
@@ -9,7 +9,7 @@ function parseCliInput(argv = process.argv) {
|
|
|
9
9
|
const errors = [];
|
|
10
10
|
const flags = {};
|
|
11
11
|
if (!tokens.length) {
|
|
12
|
-
errors.push("Missing command. Use `prodex
|
|
12
|
+
errors.push("Missing command. Use `prodex pack`, `prodex trace`, `prodex scope`, `prodex grep`, `prodex git`, or `prodex migrate`.");
|
|
13
13
|
return { warnings, errors };
|
|
14
14
|
}
|
|
15
15
|
if (tokens.includes("--version") || tokens.includes("-v")) {
|
|
@@ -20,21 +20,25 @@ function parseCliInput(argv = process.argv) {
|
|
|
20
20
|
}
|
|
21
21
|
const commandName = tokens[0];
|
|
22
22
|
if (!isCommand(commandName)) {
|
|
23
|
-
errors.push(`Unknown command "${commandName}". Use
|
|
23
|
+
errors.push(`Unknown command "${commandName}". Use pack, trace, scope, grep, git, or migrate.`);
|
|
24
24
|
return { warnings, errors };
|
|
25
25
|
}
|
|
26
|
+
const isGrep = commandName === "grep";
|
|
27
|
+
const flagsByLong = isGrep ? flag_specs_1.GREP_FLAGS_BY_LONG : flag_specs_1.FLAGS_BY_LONG;
|
|
28
|
+
const flagsByShort = isGrep ? flag_specs_1.GREP_FLAGS_BY_SHORT : flag_specs_1.FLAGS_BY_SHORT;
|
|
29
|
+
const flagAliases = isGrep ? flag_specs_1.GREP_FLAG_ALIASES : flag_specs_1.FLAG_ALIASES;
|
|
26
30
|
let rootArg;
|
|
27
31
|
for (let i = 1; i < tokens.length; i++) {
|
|
28
32
|
const token = tokens[i];
|
|
29
33
|
if (!token)
|
|
30
34
|
continue;
|
|
31
35
|
if (token.startsWith("--")) {
|
|
32
|
-
const consumed = readLongFlag(tokens, i, flags, errors);
|
|
36
|
+
const consumed = readLongFlag(tokens, i, flags, errors, flagAliases, flagsByLong);
|
|
33
37
|
i += consumed;
|
|
34
38
|
continue;
|
|
35
39
|
}
|
|
36
40
|
if (token.startsWith("-") && token !== "-") {
|
|
37
|
-
const consumed = readShortFlag(tokens, i, flags, errors);
|
|
41
|
+
const consumed = readShortFlag(tokens, i, flags, errors, flagsByShort);
|
|
38
42
|
i += consumed;
|
|
39
43
|
continue;
|
|
40
44
|
}
|
|
@@ -46,14 +50,57 @@ function parseCliInput(argv = process.argv) {
|
|
|
46
50
|
}
|
|
47
51
|
if (flags.help)
|
|
48
52
|
return { command: { kind: "help", topic: commandName }, warnings, errors };
|
|
49
|
-
|
|
53
|
+
const validationErrors = validateCliInput(commandName, flags);
|
|
54
|
+
errors.push(...validationErrors);
|
|
55
|
+
if (errors.length) {
|
|
56
|
+
return { warnings, errors };
|
|
57
|
+
}
|
|
58
|
+
if (commandName === "init") {
|
|
50
59
|
return { command: { kind: "init", rootArg }, warnings, errors };
|
|
51
|
-
|
|
52
|
-
return { command: { kind: "profiles", rootArg }, warnings, errors };
|
|
60
|
+
}
|
|
53
61
|
if (commandName === "migrate") {
|
|
54
62
|
return { command: { kind: "migrate", rootArg, write: !!flags.write, check: !!flags.check }, warnings, errors };
|
|
55
63
|
}
|
|
56
|
-
|
|
64
|
+
if (commandName === "pack") {
|
|
65
|
+
return { command: { kind: "pack", rootArg, flags }, warnings, errors };
|
|
66
|
+
}
|
|
67
|
+
if (commandName === "trace") {
|
|
68
|
+
return { command: { kind: "trace", rootArg, flags }, warnings, errors };
|
|
69
|
+
}
|
|
70
|
+
if (commandName === "scope") {
|
|
71
|
+
return { command: { kind: "scope", rootArg, flags }, warnings, errors };
|
|
72
|
+
}
|
|
73
|
+
if (commandName === "git") {
|
|
74
|
+
return { command: { kind: "git", rootArg, flags }, warnings, errors };
|
|
75
|
+
}
|
|
76
|
+
if (commandName === "grep") {
|
|
77
|
+
return { command: { kind: "grep", rootArg, flags }, warnings, errors };
|
|
78
|
+
}
|
|
79
|
+
return { warnings, errors };
|
|
80
|
+
}
|
|
81
|
+
function validateCliInput(commandName, flags) {
|
|
82
|
+
const errors = [];
|
|
83
|
+
if (commandName === "run") {
|
|
84
|
+
errors.push("`prodex run` has been replaced.\nUse `prodex pack`, `prodex trace`, or `prodex scope`.");
|
|
85
|
+
}
|
|
86
|
+
if (commandName === "profiles") {
|
|
87
|
+
errors.push("`prodex profiles` has been replaced.\nUse `prodex scope --list`.");
|
|
88
|
+
}
|
|
89
|
+
if (flags.profile !== undefined) {
|
|
90
|
+
errors.push("`--profile` has been replaced.\nUse `prodex pack --scope <key>` to merge scopes into one pack, or `prodex scope -k <key>` to run configured scopes separately.");
|
|
91
|
+
}
|
|
92
|
+
if (flags.allProfiles !== undefined) {
|
|
93
|
+
errors.push("`--all-profiles` has been replaced.\nUse `--all` with `prodex scope`.");
|
|
94
|
+
}
|
|
95
|
+
if (flags.maxDepth !== undefined) {
|
|
96
|
+
errors.push("`--max-depth` has been replaced.\nUse `--depth`.");
|
|
97
|
+
}
|
|
98
|
+
if (commandName === "init" || commandName === "migrate") {
|
|
99
|
+
if (flags.cmd !== undefined || flags.cmdTimeout !== undefined || flags.failOnCmdError !== undefined) {
|
|
100
|
+
errors.push(`Command "${commandName}" does not accept command attachment options.`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return errors;
|
|
57
104
|
}
|
|
58
105
|
function stripExecutable(argv) {
|
|
59
106
|
const [first, second, ...rest] = argv;
|
|
@@ -73,14 +120,14 @@ function basename(value) {
|
|
|
73
120
|
function isCommand(token) {
|
|
74
121
|
return flag_specs_1.COMMANDS.includes(token);
|
|
75
122
|
}
|
|
76
|
-
function readLongFlag(tokens, index, flags, errors) {
|
|
123
|
+
function readLongFlag(tokens, index, flags, errors, flagAliases, flagsByLong) {
|
|
77
124
|
const token = tokens[index];
|
|
78
125
|
const raw = token.slice(2);
|
|
79
126
|
const equalsAt = raw.indexOf("=");
|
|
80
127
|
const rawName = equalsAt === -1 ? raw : raw.slice(0, equalsAt);
|
|
81
|
-
const name =
|
|
128
|
+
const name = flagAliases[rawName] ?? rawName;
|
|
82
129
|
const inlineValue = equalsAt === -1 ? undefined : raw.slice(equalsAt + 1);
|
|
83
|
-
const spec =
|
|
130
|
+
const spec = flagsByLong.get(name);
|
|
84
131
|
if (!spec) {
|
|
85
132
|
errors.push(`Unknown flag "--${rawName}".`);
|
|
86
133
|
return 0;
|
|
@@ -90,19 +137,19 @@ function readLongFlag(tokens, index, flags, errors) {
|
|
|
90
137
|
return 0;
|
|
91
138
|
}
|
|
92
139
|
const value = inlineValue ?? tokens[index + 1];
|
|
93
|
-
if (value === undefined || value.startsWith("-")) {
|
|
140
|
+
if (value === undefined || (value.startsWith("-") && !/^-?\d+(\.\d+)?$/.test(value))) {
|
|
94
141
|
errors.push(`Flag "--${rawName}" expects a value.`);
|
|
95
142
|
return 0;
|
|
96
143
|
}
|
|
97
144
|
assignFlag(flags, spec, value, errors);
|
|
98
145
|
return inlineValue === undefined ? 1 : 0;
|
|
99
146
|
}
|
|
100
|
-
function readShortFlag(tokens, index, flags, errors) {
|
|
147
|
+
function readShortFlag(tokens, index, flags, errors, flagsByShort) {
|
|
101
148
|
const token = tokens[index];
|
|
102
149
|
const cluster = token.slice(1);
|
|
103
150
|
if (cluster.length > 1) {
|
|
104
151
|
for (const ch of cluster) {
|
|
105
|
-
const spec =
|
|
152
|
+
const spec = flagsByShort.get(ch);
|
|
106
153
|
if (!spec) {
|
|
107
154
|
errors.push(`Unknown flag "-${ch}".`);
|
|
108
155
|
continue;
|
|
@@ -115,7 +162,7 @@ function readShortFlag(tokens, index, flags, errors) {
|
|
|
115
162
|
}
|
|
116
163
|
return 0;
|
|
117
164
|
}
|
|
118
|
-
const spec =
|
|
165
|
+
const spec = flagsByShort.get(cluster);
|
|
119
166
|
if (!spec) {
|
|
120
167
|
errors.push(`Unknown flag "-${cluster}".`);
|
|
121
168
|
return 0;
|
|
@@ -125,7 +172,7 @@ function readShortFlag(tokens, index, flags, errors) {
|
|
|
125
172
|
return 0;
|
|
126
173
|
}
|
|
127
174
|
const value = tokens[index + 1];
|
|
128
|
-
if (value === undefined || value.startsWith("-")) {
|
|
175
|
+
if (value === undefined || (value.startsWith("-") && !/^-?\d+(\.\d+)?$/.test(value))) {
|
|
129
176
|
errors.push(`Flag "-${cluster}" expects a value.`);
|
|
130
177
|
return 0;
|
|
131
178
|
}
|
|
@@ -143,9 +190,13 @@ function assignFlag(flags, spec, value, errors) {
|
|
|
143
190
|
}
|
|
144
191
|
if (spec.type === "list") {
|
|
145
192
|
const values = (0, string_list_1.splitStringList)(value);
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
193
|
+
const current = (flags[spec.long] ?? []);
|
|
194
|
+
flags[spec.long] = [...current, ...values];
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
if (spec.type === "raw-list") {
|
|
198
|
+
const current = (flags[spec.long] ?? []);
|
|
199
|
+
flags[spec.long] = [...current, value];
|
|
149
200
|
return;
|
|
150
201
|
}
|
|
151
202
|
if (spec.long === "format" && !["md", "txt"].includes(value)) {
|