prodex 2.0.0 → 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.
Files changed (119) hide show
  1. package/README.md +369 -146
  2. package/dist/app/dependency-source-provider.d.ts +2 -0
  3. package/dist/app/dependency-source-provider.js +66 -0
  4. package/dist/app/entry-resolver.d.ts +7 -0
  5. package/dist/app/entry-resolver.js +26 -0
  6. package/dist/app/execute-run.d.ts +2 -2
  7. package/dist/app/execute-run.js +138 -36
  8. package/dist/app/git-source-provider.d.ts +4 -0
  9. package/dist/app/git-source-provider.js +551 -0
  10. package/dist/app/grep-source-provider.d.ts +2 -0
  11. package/dist/app/grep-source-provider.js +226 -0
  12. package/dist/app/planner.d.ts +12 -0
  13. package/dist/app/planner.js +106 -0
  14. package/dist/app/planners/attachment-options.d.ts +2 -0
  15. package/dist/app/planners/attachment-options.js +39 -0
  16. package/dist/app/planners/git-plan.d.ts +13 -0
  17. package/dist/app/planners/git-plan.js +141 -0
  18. package/dist/app/planners/grep-plan.d.ts +13 -0
  19. package/dist/app/planners/grep-plan.js +115 -0
  20. package/dist/app/planners/list-utils.d.ts +1 -0
  21. package/dist/app/planners/list-utils.js +6 -0
  22. package/dist/app/planners/pack-plan.d.ts +13 -0
  23. package/dist/app/planners/pack-plan.js +65 -0
  24. package/dist/app/planners/scope-plan.d.ts +17 -0
  25. package/dist/app/planners/scope-plan.js +143 -0
  26. package/dist/app/planners/trace-plan.d.ts +13 -0
  27. package/dist/app/planners/trace-plan.js +77 -0
  28. package/dist/app/source-collector.d.ts +5 -0
  29. package/dist/app/source-collector.js +33 -0
  30. package/dist/app/target-resolver.d.ts +7 -0
  31. package/dist/app/target-resolver.js +110 -0
  32. package/dist/cli/cli-input.js +70 -19
  33. package/dist/cli/flag-specs.d.ts +7 -3
  34. package/dist/cli/flag-specs.js +58 -7
  35. package/dist/cli/help-specs.d.ts +205 -0
  36. package/dist/cli/help-specs.js +136 -0
  37. package/dist/cli/help.js +107 -28
  38. package/dist/cli/report-command.js +59 -26
  39. package/dist/commands/{run-command.d.ts → git-command.d.ts} +3 -3
  40. package/dist/commands/git-command.js +7 -0
  41. package/dist/commands/grep-command.d.ts +11 -0
  42. package/dist/commands/grep-command.js +7 -0
  43. package/dist/commands/pack-command.d.ts +11 -0
  44. package/dist/commands/pack-command.js +7 -0
  45. package/dist/commands/scope-command.d.ts +12 -0
  46. package/dist/commands/scope-command.js +7 -0
  47. package/dist/commands/shared-runner.d.ts +12 -0
  48. package/dist/commands/shared-runner.js +30 -0
  49. package/dist/commands/trace-command.d.ts +11 -0
  50. package/dist/commands/trace-command.js +7 -0
  51. package/dist/config/default-config.js +7 -11
  52. package/dist/config/load.d.ts +1 -0
  53. package/dist/config/load.js +269 -4
  54. package/dist/config/migration/detect.d.ts +2 -1
  55. package/dist/config/migration/detect.js +10 -2
  56. package/dist/config/migration/messages.js +12 -11
  57. package/dist/config/migration/transform.js +77 -32
  58. package/dist/filesystem/binary.d.ts +2 -0
  59. package/dist/filesystem/binary.js +30 -0
  60. package/dist/filesystem/entry-discovery.d.ts +14 -0
  61. package/dist/filesystem/entry-discovery.js +78 -0
  62. package/dist/filesystem/file-set.d.ts +7 -0
  63. package/dist/filesystem/file-set.js +57 -0
  64. package/dist/filesystem/glob-scan.d.ts +6 -2
  65. package/dist/filesystem/glob-scan.js +12 -7
  66. package/dist/filesystem/path-patterns.d.ts +20 -0
  67. package/dist/filesystem/path-patterns.js +70 -0
  68. package/dist/index.js +51 -29
  69. package/dist/output/markdown-sections.d.ts +5 -0
  70. package/dist/output/markdown-sections.js +103 -0
  71. package/dist/output/markdown-toc.d.ts +31 -0
  72. package/dist/output/markdown-toc.js +287 -0
  73. package/dist/output/markdown.d.ts +5 -8
  74. package/dist/output/markdown.js +80 -127
  75. package/dist/output/produce-output.d.ts +4 -1
  76. package/dist/output/produce-output.js +6 -7
  77. package/dist/output/render-helpers.d.ts +4 -0
  78. package/dist/output/render-helpers.js +14 -0
  79. package/dist/output/text.d.ts +2 -2
  80. package/dist/output/text.js +47 -8
  81. package/dist/resolvers/js/resolve-alias.js +10 -41
  82. package/dist/resolvers/php/bindings.js +6 -6
  83. package/dist/resolvers/php/extract-imports.d.ts +19 -7
  84. package/dist/resolvers/php/extract-imports.js +146 -26
  85. package/dist/resolvers/php/php-resolver.js +55 -24
  86. package/dist/resolvers/php/psr4.d.ts +1 -1
  87. package/dist/resolvers/php/psr4.js +7 -1
  88. package/dist/runtime/shell-command-runner.d.ts +5 -0
  89. package/dist/runtime/shell-command-runner.js +118 -0
  90. package/dist/tracing/collect-trace.d.ts +10 -0
  91. package/dist/tracing/collect-trace.js +23 -0
  92. package/dist/tracing/exclude.d.ts +0 -5
  93. package/dist/tracing/exclude.js +16 -12
  94. package/dist/tracing/follow-chain.js +2 -2
  95. package/dist/types/app.types.d.ts +38 -8
  96. package/dist/types/artifact.types.d.ts +50 -0
  97. package/dist/types/artifact.types.js +2 -0
  98. package/dist/types/cli.types.d.ts +52 -4
  99. package/dist/types/config.types.d.ts +37 -20
  100. package/dist/types/index.d.ts +2 -0
  101. package/dist/types/index.js +2 -0
  102. package/dist/types/output.types.d.ts +12 -3
  103. package/dist/types/planner.types.d.ts +76 -0
  104. package/dist/types/planner.types.js +2 -0
  105. package/dist/types/resolver.types.d.ts +1 -1
  106. package/dist/types/tracing.types.d.ts +0 -11
  107. package/package.json +2 -2
  108. package/schema/prodex.schema.json +59 -41
  109. package/dist/app/run-plans.d.ts +0 -11
  110. package/dist/app/run-plans.js +0 -61
  111. package/dist/commands/profiles-command.d.ts +0 -6
  112. package/dist/commands/profiles-command.js +0 -16
  113. package/dist/commands/run-command.js +0 -17
  114. package/dist/config/build-config.d.ts +0 -13
  115. package/dist/config/build-config.js +0 -127
  116. package/dist/tracing/include-files.d.ts +0 -2
  117. package/dist/tracing/include-files.js +0 -36
  118. package/dist/tracing/trace-run.d.ts +0 -2
  119. package/dist/tracing/trace-run.js +0 -21
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.collectDependencySources = collectDependencySources;
4
+ const entry_resolver_1 = require("./entry-resolver");
5
+ const target_resolver_1 = require("./target-resolver");
6
+ const collect_trace_1 = require("../tracing/collect-trace");
7
+ async function collectDependencySources(plan) {
8
+ const warnings = [];
9
+ const errors = [];
10
+ const resolveResult = plan.command === "trace"
11
+ ? await (0, target_resolver_1.resolveTargets)(plan)
12
+ : await (0, entry_resolver_1.resolveEntries)(plan);
13
+ warnings.push(...resolveResult.warnings);
14
+ errors.push(...resolveResult.errors);
15
+ const entries = resolveResult.entries;
16
+ const includes = plan.include ?? [];
17
+ const mode = getRunMode(entries.length, includes.length);
18
+ if (errors.length) {
19
+ return { files: [], entries, includes, mode, warnings, errors };
20
+ }
21
+ if (!entries.length && !includes.length) {
22
+ return {
23
+ files: [],
24
+ entries,
25
+ includes,
26
+ mode,
27
+ warnings,
28
+ errors: ["No entry files found and no include patterns were configured."],
29
+ };
30
+ }
31
+ const traceResult = await (0, collect_trace_1.collectTraceSources)({
32
+ cfg: {
33
+ root: plan.root,
34
+ name: plan.outputName,
35
+ entry: plan.entry,
36
+ include: plan.include,
37
+ exclude: plan.exclude,
38
+ aliases: plan.aliases,
39
+ depth: plan.depth,
40
+ maxFiles: plan.maxFiles,
41
+ output: plan.output,
42
+ scopes: {},
43
+ dryRun: plan.dryRun,
44
+ },
45
+ opts: {
46
+ entries,
47
+ outputName: plan.outputName,
48
+ },
49
+ });
50
+ return {
51
+ files: traceResult.files,
52
+ entries,
53
+ includes,
54
+ mode,
55
+ stats: traceResult.stats,
56
+ warnings,
57
+ errors,
58
+ };
59
+ }
60
+ function getRunMode(entryCount, includePatternCount) {
61
+ if (entryCount && includePatternCount)
62
+ return "mixed";
63
+ if (entryCount)
64
+ return "trace";
65
+ return "include-only";
66
+ }
@@ -0,0 +1,7 @@
1
+ import type { ExecutionPlan } from "../types";
2
+ export interface EntryResolutionResult {
3
+ entries: string[];
4
+ warnings: string[];
5
+ errors: string[];
6
+ }
7
+ export declare function resolveEntries(plan: ExecutionPlan): Promise<EntryResolutionResult>;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveEntries = resolveEntries;
4
+ const exclude_1 = require("../tracing/exclude");
5
+ const entry_discovery_1 = require("../filesystem/entry-discovery");
6
+ async function resolveEntries(plan) {
7
+ const resolved = [];
8
+ const errors = [];
9
+ const warnings = [];
10
+ const root = plan.root;
11
+ const excludes = plan.exclude;
12
+ for (const entryPattern of plan.entry) {
13
+ const step1Matches = await (0, entry_discovery_1.scanGlob)([entryPattern], root);
14
+ const step1NonExcluded = step1Matches.filter((file) => !(0, exclude_1.isExcluded)(file, excludes, root));
15
+ if (step1NonExcluded.length > 0) {
16
+ resolved.push(...step1NonExcluded);
17
+ continue;
18
+ }
19
+ errors.push(`Entry "${entryPattern}" did not match any files.`);
20
+ }
21
+ return {
22
+ entries: [...new Set(resolved)],
23
+ errors,
24
+ warnings,
25
+ };
26
+ }
@@ -1,2 +1,2 @@
1
- import type { RunPlan, RunResult } from "../types";
2
- export declare function executeRun(plan: RunPlan): Promise<RunResult>;
1
+ import type { ExecutionPlan, RunResult } from "../types";
2
+ export declare function executeRun(plan: ExecutionPlan): Promise<RunResult>;
@@ -1,19 +1,38 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.executeRun = executeRun;
7
+ const fs_1 = __importDefault(require("fs"));
4
8
  const cache_manager_1 = require("../cache/cache-manager");
5
- const glob_scan_1 = require("../filesystem/glob-scan");
6
- const trace_run_1 = require("../tracing/trace-run");
7
9
  const logger_1 = require("../diagnostics/logger");
10
+ const naming_1 = require("../output/naming");
11
+ const shell_command_runner_1 = require("../runtime/shell-command-runner");
12
+ const produce_output_1 = require("../output/produce-output");
13
+ const source_collector_1 = require("./source-collector");
14
+ const package_json_1 = __importDefault(require("../../package.json"));
15
+ function hasMeaningfulSectionContent(section) {
16
+ const content = section.content.trim();
17
+ if (!content)
18
+ return false;
19
+ const normalized = content.toLowerCase();
20
+ return ![
21
+ "(none)",
22
+ "(no changes)",
23
+ "(no cached diff stat)",
24
+ ].includes(normalized);
25
+ }
8
26
  async function executeRun(plan) {
9
27
  cache_manager_1.CacheManager.clear();
10
- (0, logger_1.setLoggerOptions)(plan.flags);
28
+ (0, logger_1.setLoggerOptions)(plan);
11
29
  const warnings = [];
12
30
  const errors = [];
13
- const entries = await resolveHeadlessEntries(plan);
14
- const includes = plan.config.include ?? [];
15
- const mode = getRunMode(entries.length, includes.length);
16
- if (!entries.length && !includes.length) {
31
+ const collectResult = await (0, source_collector_1.collectSources)(plan);
32
+ warnings.push(...collectResult.warnings);
33
+ errors.push(...collectResult.errors);
34
+ const { entries, includes, mode } = collectResult;
35
+ if (errors.length) {
17
36
  return {
18
37
  ok: false,
19
38
  root: plan.root,
@@ -22,52 +41,135 @@ async function executeRun(plan) {
22
41
  includes,
23
42
  files: [],
24
43
  warnings,
25
- errors: ["No entry files found and no include patterns were configured."],
26
- profile: plan.profile,
44
+ errors,
45
+ scopeKey: plan.scopeKey,
27
46
  };
28
47
  }
29
- const result = await (0, trace_run_1.runTrace)({
30
- cfg: plan.config,
31
- opts: {
32
- entries,
33
- outputName: plan.outputName,
34
- },
35
- });
36
- if (!result.outputPath) {
48
+ const rawSections = collectResult.sections ?? [];
49
+ const filteredSections = rawSections.filter(hasMeaningfulSectionContent);
50
+ const hasContent = collectResult.files.length > 0 || filteredSections.length > 0;
51
+ if (!hasContent) {
37
52
  return {
38
53
  ok: false,
39
54
  root: plan.root,
40
55
  mode,
41
56
  entries,
42
57
  includes,
43
- files: result.files,
44
- stats: result.stats,
58
+ files: [],
59
+ stats: collectResult.stats,
45
60
  warnings,
46
- errors: ["No files matched the selected entries or include patterns."],
47
- profile: plan.profile,
61
+ errors: ["No files or metadata sections matched the selected options."],
62
+ scopeKey: plan.scopeKey,
48
63
  };
49
64
  }
65
+ const resolvedOutputName = plan.outputName?.trim() ||
66
+ (plan.command === "trace"
67
+ ? (0, naming_1.smartNaming)(entries)
68
+ : plan.command === "scope"
69
+ ? plan.scopeKey
70
+ : "pack-combined");
71
+ if (plan.dryRun) {
72
+ return {
73
+ ok: true,
74
+ root: plan.root,
75
+ mode,
76
+ outputName: resolvedOutputName,
77
+ entries,
78
+ includes,
79
+ files: collectResult.files,
80
+ stats: collectResult.stats,
81
+ warnings,
82
+ errors,
83
+ scopeKey: plan.scopeKey,
84
+ plannedCommands: plan.attachmentOptions?.commands ?? [],
85
+ };
86
+ }
87
+ // 1. Snapshot resolved files
88
+ const filesSnapshots = [];
89
+ const snapshotsMap = new Map();
90
+ if (collectResult.snapshots) {
91
+ for (const snap of collectResult.snapshots) {
92
+ snapshotsMap.set(snap.path, snap);
93
+ }
94
+ }
95
+ for (const file of collectResult.files) {
96
+ const cachedSnap = snapshotsMap.get(file);
97
+ if (cachedSnap) {
98
+ filesSnapshots.push(cachedSnap);
99
+ }
100
+ else {
101
+ try {
102
+ const content = fs_1.default.readFileSync(file, "utf8");
103
+ filesSnapshots.push({ path: file, content });
104
+ }
105
+ catch (err) {
106
+ filesSnapshots.push({ path: file, content: "", readError: err.message || String(err) });
107
+ }
108
+ }
109
+ }
110
+ // 2. Spawn attached commands sequentially
111
+ const commandOutputs = [];
112
+ if (plan.attachmentOptions && plan.attachmentOptions.commands.length > 0) {
113
+ for (const command of plan.attachmentOptions.commands) {
114
+ const cmdRes = await (0, shell_command_runner_1.executeAttachedCommand)(command, plan.root, plan.attachmentOptions.timeoutSeconds);
115
+ commandOutputs.push(cmdRes);
116
+ if (cmdRes.status !== "success") {
117
+ const errorMsg = `Attached command "${command}" failed with status: ${cmdRes.status}`;
118
+ if (plan.attachmentOptions.failOnError) {
119
+ errors.push(errorMsg);
120
+ }
121
+ else {
122
+ warnings.push(errorMsg);
123
+ }
124
+ }
125
+ }
126
+ }
127
+ // 3. Construct payload and write output
128
+ const payload = {
129
+ root: plan.root,
130
+ sections: filteredSections,
131
+ files: filesSnapshots,
132
+ commandOutputs,
133
+ metadata: {
134
+ version: package_json_1.default.version,
135
+ timestamp: new Date().toISOString(),
136
+ commandKind: plan.command,
137
+ mode,
138
+ outputName: resolvedOutputName,
139
+ entries,
140
+ includes,
141
+ scopeKey: plan.scopeKey,
142
+ targets: plan.target,
143
+ depth: plan.depth,
144
+ },
145
+ };
146
+ let produceResult;
147
+ try {
148
+ produceResult = await (0, produce_output_1.produceOutput)({
149
+ name: resolvedOutputName,
150
+ payload,
151
+ format: plan.output.format,
152
+ dir: plan.output.dir,
153
+ versioned: plan.output.versioned,
154
+ });
155
+ }
156
+ catch (err) {
157
+ errors.push(`Failed to generate output file: ${err.message || String(err)}`);
158
+ }
159
+ const ok = errors.length === 0 && produceResult !== undefined;
50
160
  return {
51
- ok: true,
161
+ ok,
52
162
  root: plan.root,
53
163
  mode,
54
- outputPath: result.outputPath,
164
+ outputPath: produceResult?.outputPath,
165
+ outputSizeBytes: produceResult?.outputSizeBytes,
166
+ outputName: resolvedOutputName,
55
167
  entries,
56
168
  includes,
57
- files: result.files,
58
- stats: result.stats,
169
+ files: collectResult.files,
170
+ stats: collectResult.stats,
59
171
  warnings,
60
172
  errors,
61
- profile: plan.profile,
173
+ scopeKey: plan.scopeKey,
62
174
  };
63
175
  }
64
- async function resolveHeadlessEntries(plan) {
65
- return (await (0, glob_scan_1.globScan)(plan.config.entry, { cwd: plan.root })).files;
66
- }
67
- function getRunMode(entryCount, includePatternCount) {
68
- if (entryCount && includePatternCount)
69
- return "mixed";
70
- if (entryCount)
71
- return "trace";
72
- return "include-only";
73
- }
@@ -0,0 +1,4 @@
1
+ import type { ExecutionPlan, SourceCollectionResult } from "../types";
2
+ export declare function runGit(args: string[], cwd: string, warnings: string[], errors: string[], maxBuffer?: number): string;
3
+ export declare function runGitBuffer(args: string[], cwd: string, warnings: string[], errors: string[], maxBuffer?: number): Buffer | null;
4
+ export declare function collectGitSources(plan: ExecutionPlan): Promise<SourceCollectionResult>;