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
|
@@ -13,8 +13,8 @@ function reportCommandResult(result) {
|
|
|
13
13
|
console.error(`Error: ${error}`);
|
|
14
14
|
if (result.message)
|
|
15
15
|
console.log(result.message);
|
|
16
|
-
if (result.
|
|
17
|
-
|
|
16
|
+
if (result.scopes)
|
|
17
|
+
reportScopes(result.scopes);
|
|
18
18
|
if (result.migration)
|
|
19
19
|
reportMigration(result.migration);
|
|
20
20
|
reportRuns(result.runs);
|
|
@@ -22,25 +22,37 @@ function reportCommandResult(result) {
|
|
|
22
22
|
function reportRuns(runs) {
|
|
23
23
|
for (const run of runs) {
|
|
24
24
|
reportRunWarningsAndErrors(run);
|
|
25
|
+
if (run.plannedCommands && run.plannedCommands.length > 0) {
|
|
26
|
+
console.log(`[dry-run] Planned command attachments to run in sequence:`);
|
|
27
|
+
for (const cmd of run.plannedCommands) {
|
|
28
|
+
console.log(` - ${cmd}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
25
31
|
}
|
|
26
|
-
const
|
|
27
|
-
if (!
|
|
32
|
+
const reportableRuns = runs.filter((run) => run.ok || run.outputPath);
|
|
33
|
+
if (!reportableRuns.length)
|
|
28
34
|
return;
|
|
29
|
-
const rows =
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
+
const rows = reportableRuns.map((run) => {
|
|
36
|
+
const sizeMb = run.outputSizeBytes !== undefined ? (run.outputSizeBytes / (1024 * 1024)).toFixed(2) : "0.00";
|
|
37
|
+
return {
|
|
38
|
+
icon: run.ok ? "✓" : "✗",
|
|
39
|
+
label: formatRunLabel(run),
|
|
40
|
+
mode: run.mode,
|
|
41
|
+
files: `${run.files.length} files`,
|
|
42
|
+
size: `${sizeMb} MB`,
|
|
43
|
+
output: run.outputPath ? formatPath(run.outputPath, run.root) : "dry-run",
|
|
44
|
+
};
|
|
45
|
+
});
|
|
35
46
|
const labelWidth = maxWidth(rows.map((row) => row.label));
|
|
36
47
|
const modeWidth = maxWidth(rows.map((row) => row.mode));
|
|
37
48
|
const filesWidth = maxWidth(rows.map((row) => row.files));
|
|
49
|
+
const sizeWidth = maxWidth(rows.map((row) => row.size));
|
|
38
50
|
for (const row of rows) {
|
|
39
|
-
console.log(
|
|
51
|
+
console.log(`${row.icon} ${row.label.padEnd(labelWidth)} ${row.mode.padEnd(modeWidth)} ${row.files.padStart(filesWidth)} ${row.size.padStart(sizeWidth)} ${row.output}`);
|
|
40
52
|
}
|
|
41
53
|
}
|
|
42
54
|
function reportRunWarningsAndErrors(run) {
|
|
43
|
-
const label = run.
|
|
55
|
+
const label = run.scopeKey ? ` [${run.scopeKey}]` : "";
|
|
44
56
|
for (const warning of run.warnings)
|
|
45
57
|
console.warn(`Warning${label}: ${warning}`);
|
|
46
58
|
for (const error of run.errors)
|
|
@@ -50,16 +62,16 @@ function reportMigration(migration) {
|
|
|
50
62
|
if (migration.errors.length)
|
|
51
63
|
return;
|
|
52
64
|
if (!migration.needed) {
|
|
53
|
-
console.log("prodex.json is already using config version
|
|
65
|
+
console.log("prodex.json is already using config version 5.");
|
|
54
66
|
return;
|
|
55
67
|
}
|
|
56
68
|
if (migration.written) {
|
|
57
69
|
console.log(`Backed up prodex.json to ${formatPath(migration.backupPath, path_1.default.dirname(migration.path))}`);
|
|
58
|
-
console.log("Migrated prodex.json to version
|
|
70
|
+
console.log("Migrated prodex.json to version 5.");
|
|
59
71
|
return;
|
|
60
72
|
}
|
|
61
73
|
const from = migration.fromVersion ?? "legacy";
|
|
62
|
-
console.log(`prodex.json can be migrated from version ${from} to version
|
|
74
|
+
console.log(`prodex.json can be migrated from version ${from} to version 5.`);
|
|
63
75
|
if (migration.changes.length) {
|
|
64
76
|
console.log("");
|
|
65
77
|
console.log("Changes:");
|
|
@@ -69,20 +81,20 @@ function reportMigration(migration) {
|
|
|
69
81
|
console.log("");
|
|
70
82
|
console.log("Run `prodex migrate --write` to update prodex.json.");
|
|
71
83
|
}
|
|
72
|
-
function
|
|
73
|
-
if (!
|
|
74
|
-
console.log("No
|
|
84
|
+
function reportScopes(scopes) {
|
|
85
|
+
if (!scopes.length) {
|
|
86
|
+
console.log("No scopes configured.");
|
|
75
87
|
return;
|
|
76
88
|
}
|
|
77
|
-
console.log("Available
|
|
78
|
-
for (const
|
|
79
|
-
console.log(` ${
|
|
89
|
+
console.log("Available scopes:");
|
|
90
|
+
for (const scope of scopes)
|
|
91
|
+
console.log(` ${scope}`);
|
|
80
92
|
}
|
|
81
93
|
function formatRunLabel(run) {
|
|
82
|
-
if (run.profile)
|
|
83
|
-
return run.profile;
|
|
84
94
|
if (run.outputName)
|
|
85
95
|
return run.outputName;
|
|
96
|
+
if (run.scopeKey)
|
|
97
|
+
return run.scopeKey;
|
|
86
98
|
if (!run.outputPath)
|
|
87
99
|
return "run";
|
|
88
100
|
const ext = path_1.default.extname(run.outputPath);
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { ProdexFlags, RunResult } from "../types";
|
|
2
|
-
export interface
|
|
2
|
+
export interface GitCommandResult {
|
|
3
3
|
runs: RunResult[];
|
|
4
4
|
warnings: string[];
|
|
5
5
|
errors: string[];
|
|
6
6
|
}
|
|
7
|
-
export declare function
|
|
7
|
+
export declare function gitCommand(params: {
|
|
8
8
|
rootArg?: string;
|
|
9
9
|
flags?: Partial<ProdexFlags>;
|
|
10
10
|
cwd?: string;
|
|
11
|
-
}): Promise<
|
|
11
|
+
}): Promise<GitCommandResult>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.gitCommand = gitCommand;
|
|
4
|
+
const shared_runner_1 = require("./shared-runner");
|
|
5
|
+
async function gitCommand(params) {
|
|
6
|
+
return (0, shared_runner_1.executeCommandWithPlanner)("git", params);
|
|
7
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ProdexFlags, RunResult } from "../types";
|
|
2
|
+
export interface GrepCommandResult {
|
|
3
|
+
runs: RunResult[];
|
|
4
|
+
warnings: string[];
|
|
5
|
+
errors: string[];
|
|
6
|
+
}
|
|
7
|
+
export declare function grepCommand(params: {
|
|
8
|
+
rootArg?: string;
|
|
9
|
+
flags?: Partial<ProdexFlags>;
|
|
10
|
+
cwd?: string;
|
|
11
|
+
}): Promise<GrepCommandResult>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.grepCommand = grepCommand;
|
|
4
|
+
const shared_runner_1 = require("./shared-runner");
|
|
5
|
+
async function grepCommand(params) {
|
|
6
|
+
return (0, shared_runner_1.executeCommandWithPlanner)("grep", params);
|
|
7
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ProdexFlags, RunResult } from "../types";
|
|
2
|
+
export interface PackCommandResult {
|
|
3
|
+
runs: RunResult[];
|
|
4
|
+
warnings: string[];
|
|
5
|
+
errors: string[];
|
|
6
|
+
}
|
|
7
|
+
export declare function packCommand(params: {
|
|
8
|
+
rootArg?: string;
|
|
9
|
+
flags?: Partial<ProdexFlags>;
|
|
10
|
+
cwd?: string;
|
|
11
|
+
}): Promise<PackCommandResult>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.packCommand = packCommand;
|
|
4
|
+
const shared_runner_1 = require("./shared-runner");
|
|
5
|
+
async function packCommand(params) {
|
|
6
|
+
return (0, shared_runner_1.executeCommandWithPlanner)("pack", params);
|
|
7
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ProdexFlags, RunResult } from "../types";
|
|
2
|
+
export interface ScopeCommandResult {
|
|
3
|
+
runs: RunResult[];
|
|
4
|
+
warnings: string[];
|
|
5
|
+
errors: string[];
|
|
6
|
+
scopes?: string[];
|
|
7
|
+
}
|
|
8
|
+
export declare function scopeCommand(params: {
|
|
9
|
+
rootArg?: string;
|
|
10
|
+
flags?: Partial<ProdexFlags>;
|
|
11
|
+
cwd?: string;
|
|
12
|
+
}): Promise<ScopeCommandResult>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.scopeCommand = scopeCommand;
|
|
4
|
+
const shared_runner_1 = require("./shared-runner");
|
|
5
|
+
async function scopeCommand(params) {
|
|
6
|
+
return (0, shared_runner_1.executeCommandWithPlanner)("scope", params);
|
|
7
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ProdexFlags, RunResult } from "../types";
|
|
2
|
+
export interface PlannerCommandResult {
|
|
3
|
+
runs: RunResult[];
|
|
4
|
+
warnings: string[];
|
|
5
|
+
errors: string[];
|
|
6
|
+
scopes?: string[];
|
|
7
|
+
}
|
|
8
|
+
export declare function executeCommandWithPlanner(kind: "pack" | "trace" | "scope" | "git" | "grep", params: {
|
|
9
|
+
rootArg?: string;
|
|
10
|
+
flags?: Partial<ProdexFlags>;
|
|
11
|
+
cwd?: string;
|
|
12
|
+
}): Promise<PlannerCommandResult>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.executeCommandWithPlanner = executeCommandWithPlanner;
|
|
4
|
+
const project_context_1 = require("../app/project-context");
|
|
5
|
+
const planner_1 = require("../app/planner");
|
|
6
|
+
const execute_run_1 = require("../app/execute-run");
|
|
7
|
+
async function executeCommandWithPlanner(kind, params) {
|
|
8
|
+
const project = (0, project_context_1.loadProjectContext)(params.rootArg, params.cwd);
|
|
9
|
+
const warnings = [...project.warnings];
|
|
10
|
+
const errors = [...project.errors];
|
|
11
|
+
if (errors.length)
|
|
12
|
+
return { runs: [], warnings, errors };
|
|
13
|
+
const planned = (0, planner_1.createExecutionPlans)({
|
|
14
|
+
intent: { kind, rootArg: params.rootArg, flags: params.flags ?? {} },
|
|
15
|
+
userConfig: project.config,
|
|
16
|
+
root: project.root,
|
|
17
|
+
});
|
|
18
|
+
warnings.push(...planned.warnings);
|
|
19
|
+
errors.push(...planned.errors);
|
|
20
|
+
if (errors.length)
|
|
21
|
+
return { runs: [], warnings, errors };
|
|
22
|
+
if (planned.listScopes) {
|
|
23
|
+
return { runs: [], warnings, errors, scopes: planned.listScopes };
|
|
24
|
+
}
|
|
25
|
+
const runs = [];
|
|
26
|
+
for (const plan of planned.plans) {
|
|
27
|
+
runs.push(await (0, execute_run_1.executeRun)(plan));
|
|
28
|
+
}
|
|
29
|
+
return { runs, warnings, errors };
|
|
30
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ProdexFlags, RunResult } from "../types";
|
|
2
|
+
export interface TraceCommandResult {
|
|
3
|
+
runs: RunResult[];
|
|
4
|
+
warnings: string[];
|
|
5
|
+
errors: string[];
|
|
6
|
+
}
|
|
7
|
+
export declare function traceCommand(params: {
|
|
8
|
+
rootArg?: string;
|
|
9
|
+
flags?: Partial<ProdexFlags>;
|
|
10
|
+
cwd?: string;
|
|
11
|
+
}): Promise<TraceCommandResult>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.traceCommand = traceCommand;
|
|
4
|
+
const shared_runner_1 = require("./shared-runner");
|
|
5
|
+
async function traceCommand(params) {
|
|
6
|
+
return (0, shared_runner_1.executeCommandWithPlanner)("trace", params);
|
|
7
|
+
}
|
|
@@ -2,22 +2,18 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DEFAULT_PRODEX_CONFIG = void 0;
|
|
4
4
|
exports.DEFAULT_PRODEX_CONFIG = {
|
|
5
|
-
version:
|
|
5
|
+
version: 5,
|
|
6
6
|
$schema: "https://raw.githubusercontent.com/emxhive/prodex/main/schema/prodex.schema.json",
|
|
7
7
|
output: {
|
|
8
8
|
dir: "prodex",
|
|
9
9
|
versioned: true,
|
|
10
10
|
format: "md",
|
|
11
11
|
},
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
resolve: {
|
|
16
|
-
aliases: {
|
|
17
|
-
"@": "resources/js",
|
|
18
|
-
},
|
|
19
|
-
maxDepth: 10,
|
|
20
|
-
maxFiles: 200,
|
|
12
|
+
exclude: ["node_modules/**", "vendor/**", "dist/**"],
|
|
13
|
+
aliases: {
|
|
14
|
+
"@": "resources/js",
|
|
21
15
|
},
|
|
22
|
-
|
|
16
|
+
depth: 2,
|
|
17
|
+
maxFiles: 200,
|
|
18
|
+
scopes: {},
|
|
23
19
|
};
|
package/dist/config/load.d.ts
CHANGED
package/dist/config/load.js
CHANGED
|
@@ -3,19 +3,277 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.validateConfig = validateConfig;
|
|
6
7
|
exports.loadConfig = loadConfig;
|
|
7
8
|
const fs_1 = __importDefault(require("fs"));
|
|
8
9
|
const path_1 = __importDefault(require("path"));
|
|
9
10
|
const default_config_1 = require("./default-config");
|
|
10
11
|
const migration_1 = require("./migration");
|
|
11
12
|
const json_1 = require("./json");
|
|
13
|
+
function cloneDefaultConfig() {
|
|
14
|
+
return JSON.parse(JSON.stringify(default_config_1.DEFAULT_PRODEX_CONFIG));
|
|
15
|
+
}
|
|
16
|
+
function validateConfig(config) {
|
|
17
|
+
const errors = [];
|
|
18
|
+
if (!config || typeof config !== "object") {
|
|
19
|
+
errors.push("Configuration must be a JSON object.");
|
|
20
|
+
return errors;
|
|
21
|
+
}
|
|
22
|
+
if (config.version === undefined) {
|
|
23
|
+
errors.push("Config 'version' is required.");
|
|
24
|
+
}
|
|
25
|
+
else if (config.version !== 5) {
|
|
26
|
+
errors.push("Config 'version' must equal 5.");
|
|
27
|
+
}
|
|
28
|
+
if (config.output !== undefined) {
|
|
29
|
+
if (typeof config.output !== "object" || config.output === null || Array.isArray(config.output)) {
|
|
30
|
+
errors.push("Config 'output' must be an object.");
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
const allowedOutputKeys = new Set(["dir", "versioned", "format"]);
|
|
34
|
+
for (const key of Object.keys(config.output)) {
|
|
35
|
+
if (!allowedOutputKeys.has(key)) {
|
|
36
|
+
errors.push(`Config 'output' contains unknown key '${key}'.`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (config.output.dir !== undefined && typeof config.output.dir !== "string") {
|
|
40
|
+
errors.push("Config 'output.dir' must be a string.");
|
|
41
|
+
}
|
|
42
|
+
if (config.output.versioned !== undefined && typeof config.output.versioned !== "boolean") {
|
|
43
|
+
errors.push("Config 'output.versioned' must be a boolean.");
|
|
44
|
+
}
|
|
45
|
+
if (config.output.format !== undefined && config.output.format !== "md" && config.output.format !== "txt") {
|
|
46
|
+
errors.push("Config 'output.format' must be either 'md' or 'txt'.");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (config.exclude !== undefined) {
|
|
51
|
+
if (!Array.isArray(config.exclude)) {
|
|
52
|
+
errors.push("Config 'exclude' must be an array.");
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
for (let i = 0; i < config.exclude.length; i++) {
|
|
56
|
+
if (typeof config.exclude[i] !== "string") {
|
|
57
|
+
errors.push(`Config 'exclude[${i}]' must be a string.`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (config.aliases !== undefined) {
|
|
63
|
+
if (typeof config.aliases !== "object" || config.aliases === null || Array.isArray(config.aliases)) {
|
|
64
|
+
errors.push("Config 'aliases' must be an object.");
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
for (const [key, val] of Object.entries(config.aliases)) {
|
|
68
|
+
if (typeof val !== "string") {
|
|
69
|
+
errors.push(`Config 'aliases.${key}' must be a string.`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (config.depth !== undefined) {
|
|
75
|
+
if (typeof config.depth !== "number" || !Number.isInteger(config.depth) || config.depth < 0) {
|
|
76
|
+
errors.push("Config --depth must be an integer greater than or equal to 0.");
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (config.maxFiles !== undefined) {
|
|
80
|
+
if (typeof config.maxFiles !== "number" || !Number.isInteger(config.maxFiles) || config.maxFiles <= 0) {
|
|
81
|
+
errors.push("Config --max-files must be an integer greater than 0.");
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (config.scopes !== undefined) {
|
|
85
|
+
if (typeof config.scopes !== "object" || config.scopes === null || Array.isArray(config.scopes)) {
|
|
86
|
+
errors.push("Config 'scopes' must be an object.");
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
for (const [scopeKey, scopeVal] of Object.entries(config.scopes)) {
|
|
90
|
+
const scope = scopeVal;
|
|
91
|
+
if (typeof scope !== "object" || scope === null || Array.isArray(scope)) {
|
|
92
|
+
errors.push(`Config 'scopes.${scopeKey}' must be an object.`);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
const allowedScopeKeys = new Set(["name", "entry", "include", "exclude", "grep"]);
|
|
96
|
+
for (const key of Object.keys(scope)) {
|
|
97
|
+
if (!allowedScopeKeys.has(key)) {
|
|
98
|
+
errors.push(`Config 'scopes.${scopeKey}' contains unknown key '${key}'.`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (scope.name !== undefined && typeof scope.name !== "string") {
|
|
102
|
+
errors.push(`Config 'scopes.${scopeKey}.name' must be a string.`);
|
|
103
|
+
}
|
|
104
|
+
if (scope.entry !== undefined) {
|
|
105
|
+
if (!Array.isArray(scope.entry)) {
|
|
106
|
+
errors.push(`Config 'scopes.${scopeKey}.entry' must be an array.`);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
for (let i = 0; i < scope.entry.length; i++) {
|
|
110
|
+
if (typeof scope.entry[i] !== "string") {
|
|
111
|
+
errors.push(`Config 'scopes.${scopeKey}.entry[${i}]' must be a string.`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (scope.include !== undefined) {
|
|
117
|
+
if (!Array.isArray(scope.include)) {
|
|
118
|
+
errors.push(`Config 'scopes.${scopeKey}.include' must be an array.`);
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
for (let i = 0; i < scope.include.length; i++) {
|
|
122
|
+
if (typeof scope.include[i] !== "string") {
|
|
123
|
+
errors.push(`Config 'scopes.${scopeKey}.include[${i}]' must be a string.`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (scope.exclude !== undefined) {
|
|
129
|
+
if (!Array.isArray(scope.exclude)) {
|
|
130
|
+
errors.push(`Config 'scopes.${scopeKey}.exclude' must be an array.`);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
for (let i = 0; i < scope.exclude.length; i++) {
|
|
134
|
+
if (typeof scope.exclude[i] !== "string") {
|
|
135
|
+
errors.push(`Config 'scopes.${scopeKey}.exclude[${i}]' must be a string.`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (scope.grep !== undefined) {
|
|
141
|
+
if (typeof scope.grep !== "object" || scope.grep === null || Array.isArray(scope.grep)) {
|
|
142
|
+
errors.push(`Config 'scopes.${scopeKey}.grep' must be an object.`);
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
const allowedGrepKeys = new Set(["query", "any", "all", "regex", "not", "within", "skip"]);
|
|
146
|
+
for (const key of Object.keys(scope.grep)) {
|
|
147
|
+
if (!allowedGrepKeys.has(key)) {
|
|
148
|
+
errors.push(`Config 'scopes.${scopeKey}.grep' contains unknown key '${key}'.`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (scope.entry !== undefined) {
|
|
152
|
+
errors.push(`Scope "${scopeKey}" cannot define both "entry" and "grep".`);
|
|
153
|
+
}
|
|
154
|
+
const searchModes = ["query", "any", "all", "regex"];
|
|
155
|
+
const definedModes = searchModes.filter(m => scope.grep[m] !== undefined);
|
|
156
|
+
if (definedModes.length !== 1) {
|
|
157
|
+
errors.push(`Scope "${scopeKey}" grep config must define exactly one of "query", "any", "all", or "regex".`);
|
|
158
|
+
}
|
|
159
|
+
if (scope.grep.query !== undefined) {
|
|
160
|
+
if (typeof scope.grep.query !== "string") {
|
|
161
|
+
errors.push(`Config 'scopes.${scopeKey}.grep.query' must be a string.`);
|
|
162
|
+
}
|
|
163
|
+
else if (!scope.grep.query.trim()) {
|
|
164
|
+
errors.push(`Config 'scopes.${scopeKey}.grep.query' cannot be blank.`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (scope.grep.regex !== undefined) {
|
|
168
|
+
if (typeof scope.grep.regex !== "string") {
|
|
169
|
+
errors.push(`Config 'scopes.${scopeKey}.grep.regex' must be a string.`);
|
|
170
|
+
}
|
|
171
|
+
else if (!scope.grep.regex.trim()) {
|
|
172
|
+
errors.push(`Config 'scopes.${scopeKey}.grep.regex' cannot be blank.`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (scope.grep.any !== undefined) {
|
|
176
|
+
if (!Array.isArray(scope.grep.any)) {
|
|
177
|
+
errors.push(`Config 'scopes.${scopeKey}.grep.any' must be an array.`);
|
|
178
|
+
}
|
|
179
|
+
else if (scope.grep.any.length === 0) {
|
|
180
|
+
errors.push(`Config 'scopes.${scopeKey}.grep.any' must contain at least one item.`);
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
for (let i = 0; i < scope.grep.any.length; i++) {
|
|
184
|
+
if (typeof scope.grep.any[i] !== "string") {
|
|
185
|
+
errors.push(`Config 'scopes.${scopeKey}.grep.any[${i}]' must be a string.`);
|
|
186
|
+
}
|
|
187
|
+
else if (!scope.grep.any[i].trim()) {
|
|
188
|
+
errors.push(`Config 'scopes.${scopeKey}.grep.any[${i}]' cannot be blank.`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (scope.grep.all !== undefined) {
|
|
194
|
+
if (!Array.isArray(scope.grep.all)) {
|
|
195
|
+
errors.push(`Config 'scopes.${scopeKey}.grep.all' must be an array.`);
|
|
196
|
+
}
|
|
197
|
+
else if (scope.grep.all.length === 0) {
|
|
198
|
+
errors.push(`Config 'scopes.${scopeKey}.grep.all' must contain at least one item.`);
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
for (let i = 0; i < scope.grep.all.length; i++) {
|
|
202
|
+
if (typeof scope.grep.all[i] !== "string") {
|
|
203
|
+
errors.push(`Config 'scopes.${scopeKey}.grep.all[${i}]' must be a string.`);
|
|
204
|
+
}
|
|
205
|
+
else if (!scope.grep.all[i].trim()) {
|
|
206
|
+
errors.push(`Config 'scopes.${scopeKey}.grep.all[${i}]' cannot be blank.`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
if (scope.grep.not !== undefined) {
|
|
212
|
+
if (!Array.isArray(scope.grep.not)) {
|
|
213
|
+
errors.push(`Config 'scopes.${scopeKey}.grep.not' must be an array.`);
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
for (let i = 0; i < scope.grep.not.length; i++) {
|
|
217
|
+
if (typeof scope.grep.not[i] !== "string") {
|
|
218
|
+
errors.push(`Config 'scopes.${scopeKey}.grep.not[${i}]' must be a string.`);
|
|
219
|
+
}
|
|
220
|
+
else if (!scope.grep.not[i].trim()) {
|
|
221
|
+
errors.push(`Config 'scopes.${scopeKey}.grep.not[${i}]' cannot be blank.`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (scope.grep.within !== undefined) {
|
|
227
|
+
if (!Array.isArray(scope.grep.within)) {
|
|
228
|
+
errors.push(`Config 'scopes.${scopeKey}.grep.within' must be an array.`);
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
for (let i = 0; i < scope.grep.within.length; i++) {
|
|
232
|
+
if (typeof scope.grep.within[i] !== "string") {
|
|
233
|
+
errors.push(`Config 'scopes.${scopeKey}.grep.within[${i}]' must be a string.`);
|
|
234
|
+
}
|
|
235
|
+
else if (!scope.grep.within[i].trim()) {
|
|
236
|
+
errors.push(`Config 'scopes.${scopeKey}.grep.within[${i}]' cannot be blank.`);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
if (scope.grep.skip !== undefined) {
|
|
242
|
+
if (!Array.isArray(scope.grep.skip)) {
|
|
243
|
+
errors.push(`Config 'scopes.${scopeKey}.grep.skip' must be an array.`);
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
for (let i = 0; i < scope.grep.skip.length; i++) {
|
|
247
|
+
if (typeof scope.grep.skip[i] !== "string") {
|
|
248
|
+
errors.push(`Config 'scopes.${scopeKey}.grep.skip[${i}]' must be a string.`);
|
|
249
|
+
}
|
|
250
|
+
else if (!scope.grep.skip[i].trim()) {
|
|
251
|
+
errors.push(`Config 'scopes.${scopeKey}.grep.skip[${i}]' cannot be blank.`);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
const allowedRootKeys = new Set(["$schema", "version", "output", "exclude", "aliases", "depth", "maxFiles", "scopes"]);
|
|
263
|
+
for (const key of Object.keys(config)) {
|
|
264
|
+
if (!allowedRootKeys.has(key)) {
|
|
265
|
+
errors.push(`Config contains unknown root key '${key}'.`);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return errors;
|
|
269
|
+
}
|
|
12
270
|
function loadConfig(root) {
|
|
13
271
|
const configPath = path_1.default.join(root, "prodex.json");
|
|
14
272
|
const warnings = [];
|
|
15
273
|
const errors = [];
|
|
16
274
|
if (!fs_1.default.existsSync(configPath)) {
|
|
17
275
|
return {
|
|
18
|
-
config:
|
|
276
|
+
config: cloneDefaultConfig(),
|
|
19
277
|
path: configPath,
|
|
20
278
|
warnings,
|
|
21
279
|
errors,
|
|
@@ -24,11 +282,18 @@ function loadConfig(root) {
|
|
|
24
282
|
}
|
|
25
283
|
try {
|
|
26
284
|
const parsed = (0, json_1.parseJsonFile)(fs_1.default.readFileSync(configPath, "utf8"));
|
|
27
|
-
if ((0, migration_1.
|
|
285
|
+
if ((0, migration_1.isFutureConfig)(parsed)) {
|
|
286
|
+
errors.push(`prodex.json uses future config version ${parsed.version}, but this Prodex version only supports up to config version ${migration_1.REQUIRED_CONFIG_VERSION}.`);
|
|
287
|
+
}
|
|
288
|
+
else if ((0, migration_1.requiresConfigMigration)(parsed)) {
|
|
28
289
|
errors.push((0, migration_1.isOutdatedConfig)(parsed) ? (0, migration_1.configVersionError)(parsed.version) : (0, migration_1.legacyConfigShapeError)());
|
|
29
290
|
}
|
|
291
|
+
else {
|
|
292
|
+
const validationErrors = validateConfig(parsed);
|
|
293
|
+
errors.push(...validationErrors);
|
|
294
|
+
}
|
|
30
295
|
return {
|
|
31
|
-
config: parsed,
|
|
296
|
+
config: errors.length > 0 ? cloneDefaultConfig() : parsed,
|
|
32
297
|
path: configPath,
|
|
33
298
|
warnings,
|
|
34
299
|
errors,
|
|
@@ -38,7 +303,7 @@ function loadConfig(root) {
|
|
|
38
303
|
catch (err) {
|
|
39
304
|
errors.push(`Invalid prodex.json: ${err?.message || err}`);
|
|
40
305
|
return {
|
|
41
|
-
config:
|
|
306
|
+
config: cloneDefaultConfig(),
|
|
42
307
|
path: configPath,
|
|
43
308
|
warnings,
|
|
44
309
|
errors,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export declare const REQUIRED_CONFIG_VERSION =
|
|
1
|
+
export declare const REQUIRED_CONFIG_VERSION = 5;
|
|
2
2
|
export declare function isOutdatedConfig(config: any): boolean;
|
|
3
|
+
export declare function isFutureConfig(config: any): boolean;
|
|
3
4
|
export declare function requiresConfigMigration(config: any): boolean;
|
|
4
5
|
export declare function looksLikeLegacyConfig(config: any): boolean;
|
|
@@ -2,17 +2,25 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.REQUIRED_CONFIG_VERSION = void 0;
|
|
4
4
|
exports.isOutdatedConfig = isOutdatedConfig;
|
|
5
|
+
exports.isFutureConfig = isFutureConfig;
|
|
5
6
|
exports.requiresConfigMigration = requiresConfigMigration;
|
|
6
7
|
exports.looksLikeLegacyConfig = looksLikeLegacyConfig;
|
|
7
|
-
exports.REQUIRED_CONFIG_VERSION =
|
|
8
|
+
exports.REQUIRED_CONFIG_VERSION = 5;
|
|
8
9
|
function isOutdatedConfig(config) {
|
|
9
10
|
return typeof config?.version === "number" && config.version < exports.REQUIRED_CONFIG_VERSION;
|
|
10
11
|
}
|
|
12
|
+
function isFutureConfig(config) {
|
|
13
|
+
return typeof config?.version === "number" && config.version > exports.REQUIRED_CONFIG_VERSION;
|
|
14
|
+
}
|
|
11
15
|
function requiresConfigMigration(config) {
|
|
12
16
|
return isOutdatedConfig(config) || looksLikeLegacyConfig(config);
|
|
13
17
|
}
|
|
14
18
|
function looksLikeLegacyConfig(config) {
|
|
15
|
-
return !!(config?.
|
|
19
|
+
return !!(config?.profiles ||
|
|
20
|
+
config?.resolve ||
|
|
21
|
+
config?.shortcuts ||
|
|
22
|
+
config?.entry !== undefined ||
|
|
23
|
+
config?.include !== undefined ||
|
|
16
24
|
config?.entry?.files ||
|
|
17
25
|
config?.resolve?.include ||
|
|
18
26
|
config?.resolve?.exclude ||
|