prodex 1.4.10 → 2.0.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/LICENSE +20 -20
- package/README.md +238 -234
- package/bin/prodex.js +0 -0
- package/dist/app/execute-run.d.ts +2 -0
- package/dist/app/execute-run.js +73 -0
- package/dist/app/project-context.d.ts +12 -0
- package/dist/app/project-context.js +48 -0
- package/dist/app/run-plans.d.ts +11 -0
- package/dist/app/run-plans.js +61 -0
- package/dist/cache/cache-keys.d.ts +9 -0
- package/dist/cache/cache-manager.d.ts +9 -0
- package/dist/{core/managers/cache.js → cache/cache-manager.js} +5 -18
- package/dist/cli/cli-input.d.ts +2 -0
- package/dist/cli/cli-input.js +138 -124
- package/dist/cli/flag-specs.d.ts +12 -0
- package/dist/cli/flag-specs.js +27 -0
- package/dist/cli/help.d.ts +2 -0
- package/dist/cli/help.js +83 -0
- package/dist/cli/report-command.d.ts +2 -0
- package/dist/cli/report-command.js +80 -0
- package/dist/cli/reporter.d.ts +2 -0
- package/dist/cli/reporter.js +8 -0
- package/dist/commands/init-command.d.ts +1 -0
- package/dist/commands/init-command.js +9 -0
- package/dist/commands/migrate-command.d.ts +7 -0
- package/dist/commands/migrate-command.js +76 -0
- package/dist/commands/profiles-command.d.ts +6 -0
- package/dist/commands/profiles-command.js +16 -0
- package/dist/commands/run-command.d.ts +11 -0
- package/dist/commands/run-command.js +17 -0
- package/dist/config/build-config.d.ts +13 -0
- package/dist/config/build-config.js +127 -0
- package/dist/config/create-default-config.d.ts +9 -0
- package/dist/config/create-default-config.js +25 -0
- package/dist/config/default-config.d.ts +2 -0
- package/dist/config/default-config.js +23 -0
- package/dist/config/json.d.ts +2 -0
- package/dist/config/json.js +10 -0
- package/dist/config/load.d.ts +9 -0
- package/dist/config/load.js +48 -0
- package/dist/config/migration/detect.d.ts +4 -0
- package/dist/config/migration/detect.js +22 -0
- package/dist/config/migration/index.d.ts +4 -0
- package/dist/{shared → config/migration}/index.js +4 -3
- package/dist/config/migration/messages.d.ts +2 -0
- package/dist/config/migration/messages.js +35 -0
- package/dist/config/migration/transform.d.ts +2 -0
- package/dist/config/migration/transform.js +80 -0
- package/dist/config/migration/types.d.ts +16 -0
- package/dist/config/string-list.d.ts +2 -0
- package/dist/config/string-list.js +17 -0
- package/dist/diagnostics/logger.d.ts +3 -0
- package/dist/diagnostics/logger.js +33 -0
- package/dist/filesystem/glob-scan.d.ts +4 -0
- package/dist/filesystem/glob-scan.js +26 -0
- package/dist/filesystem/inspect.d.ts +1 -0
- package/dist/filesystem/inspect.js +15 -0
- package/dist/filesystem/path.d.ts +2 -0
- package/dist/filesystem/path.js +11 -0
- package/dist/filesystem/read-file.d.ts +8 -0
- package/dist/{shared/io.js → filesystem/read-file.js} +0 -25
- package/dist/filesystem/stat-cache.d.ts +1 -0
- package/dist/filesystem/stat-cache.js +22 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +76 -83
- package/dist/output/markdown.d.ts +12 -0
- package/dist/output/markdown.js +150 -0
- package/dist/output/naming.d.ts +2 -0
- package/dist/output/naming.js +30 -0
- package/dist/output/produce-output.d.ts +2 -0
- package/dist/output/produce-output.js +35 -0
- package/dist/output/render-constants.d.ts +21 -0
- package/dist/{constants → output}/render-constants.js +2 -1
- package/dist/output/text.d.ts +2 -0
- package/dist/output/text.js +14 -0
- package/dist/resolvers/js/extract-imports.d.ts +1 -0
- package/dist/resolvers/js/js-resolver.d.ts +2 -0
- package/dist/resolvers/js/js-resolver.js +45 -89
- package/dist/resolvers/js/resolve-alias.d.ts +2 -0
- package/dist/resolvers/js/resolve-alias.js +12 -20
- package/dist/resolvers/php/bindings.d.ts +8 -0
- package/dist/resolvers/php/bindings.js +8 -9
- package/dist/resolvers/php/extract-imports.d.ts +13 -0
- package/dist/resolvers/php/extract-imports.js +1 -1
- package/dist/resolvers/php/php-resolver.d.ts +2 -0
- package/dist/resolvers/php/php-resolver.js +61 -90
- package/dist/resolvers/php/psr4.d.ts +5 -0
- package/dist/resolvers/php/psr4.js +7 -7
- package/dist/resolvers/resolver-constants.d.ts +4 -0
- package/dist/resolvers/resolver-constants.js +7 -0
- package/dist/resolvers/resolver-result.d.ts +5 -0
- package/dist/resolvers/resolver-result.js +18 -0
- package/dist/tracing/exclude.d.ts +6 -0
- package/dist/{shared/patterns.js → tracing/exclude.js} +4 -4
- package/dist/tracing/follow-chain.d.ts +5 -0
- package/dist/tracing/follow-chain.js +63 -0
- package/dist/tracing/include-files.d.ts +2 -0
- package/dist/tracing/include-files.js +36 -0
- package/dist/tracing/resolver-registry.d.ts +5 -0
- package/dist/tracing/resolver-registry.js +20 -0
- package/dist/tracing/trace-run.d.ts +2 -0
- package/dist/tracing/trace-run.js +21 -0
- package/dist/tracing/trace-stats.d.ts +4 -0
- package/dist/tracing/trace-stats.js +16 -0
- package/dist/types/app.types.d.ts +61 -0
- package/dist/types/app.types.js +2 -0
- package/dist/types/cli.types.d.ts +22 -0
- package/dist/types/cli.types.js +0 -10
- package/dist/types/config.types.d.ts +34 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.js +3 -1
- package/dist/types/output.types.d.ts +6 -0
- package/dist/types/output.types.js +2 -0
- package/dist/types/resolver.types.d.ts +23 -0
- package/dist/types/tracing.types.d.ts +23 -0
- package/dist/types/tracing.types.js +2 -0
- package/dist/types/utils.types.d.ts +10 -0
- package/package.json +35 -12
- package/schema/prodex.schema.json +122 -0
- package/dist/cli/init.js +0 -21
- package/dist/cli/picker.js +0 -83
- package/dist/cli/summary.js +0 -32
- package/dist/constants/config.js +0 -27
- package/dist/constants/default-config.js +0 -43
- package/dist/constants/flags.js +0 -79
- package/dist/constants/index.js +0 -20
- package/dist/core/combine.js +0 -56
- package/dist/core/dependency.js +0 -98
- package/dist/core/helpers.js +0 -85
- package/dist/core/managers/config.js +0 -140
- package/dist/core/output.js +0 -49
- package/dist/core/renderers.js +0 -210
- package/dist/debug.js +0 -15
- package/dist/lib/logger.js +0 -42
- package/dist/lib/polyfills.js +0 -17
- package/dist/lib/prompt.js +0 -34
- package/dist/lib/questions.js +0 -28
- package/dist/lib/utils.js +0 -46
- package/dist/shared/collections.js +0 -33
- package/dist/store.js +0 -15
- /package/dist/{constants → cache}/cache-keys.js +0 -0
- /package/dist/{types/core.types.js → config/migration/types.js} +0 -0
package/dist/core/dependency.js
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
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.followChain = followChain;
|
|
7
|
-
exports.applyIncludes = applyIncludes;
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const config_1 = require("../constants/config");
|
|
10
|
-
const helpers_1 = require("./helpers");
|
|
11
|
-
const logger_1 = require("../lib/logger");
|
|
12
|
-
const collections_1 = require("../shared/collections");
|
|
13
|
-
const fs_1 = __importDefault(require("fs"));
|
|
14
|
-
/**
|
|
15
|
-
* 🧩 followChain()
|
|
16
|
-
* Traverses all dependencies starting from the given entry files.
|
|
17
|
-
* Uses language-specific resolvers (JS / PHP) under the hood.
|
|
18
|
-
*/
|
|
19
|
-
async function followChain(entryFiles, cfg) {
|
|
20
|
-
const limit = cfg.resolve.limit;
|
|
21
|
-
const resolverDepth = cfg.resolve.depth;
|
|
22
|
-
logger_1.logger.debug("🧩 Following dependency chain...");
|
|
23
|
-
const visited = new Set();
|
|
24
|
-
const all = [];
|
|
25
|
-
const expected = new Set();
|
|
26
|
-
const resolved = new Set();
|
|
27
|
-
for (const f of entryFiles) {
|
|
28
|
-
if (visited.has(f))
|
|
29
|
-
continue;
|
|
30
|
-
all.push(f);
|
|
31
|
-
const ext = path_1.default.extname(f);
|
|
32
|
-
if (!config_1.CODE_EXTS.includes(ext))
|
|
33
|
-
continue;
|
|
34
|
-
const resolver = config_1.RESOLVERS[ext];
|
|
35
|
-
if (!resolver)
|
|
36
|
-
continue;
|
|
37
|
-
const params = {
|
|
38
|
-
filePath: f,
|
|
39
|
-
visited,
|
|
40
|
-
depth: 0,
|
|
41
|
-
maxDepth: resolverDepth,
|
|
42
|
-
};
|
|
43
|
-
let result = null;
|
|
44
|
-
try {
|
|
45
|
-
result = await resolver(params);
|
|
46
|
-
}
|
|
47
|
-
catch (err) {
|
|
48
|
-
logger_1.logger.warn(`⚠️ Resolver failed for ${f}:`, err.message || err);
|
|
49
|
-
continue;
|
|
50
|
-
}
|
|
51
|
-
if (!result)
|
|
52
|
-
continue;
|
|
53
|
-
const { files, stats } = result;
|
|
54
|
-
all.push(...files);
|
|
55
|
-
stats.expected.forEach((x) => expected.add(x));
|
|
56
|
-
stats.resolved.forEach((x) => resolved.add(x));
|
|
57
|
-
if (limit && all.length >= limit) {
|
|
58
|
-
logger_1.logger.warn("⚠️ Limit reached:", limit);
|
|
59
|
-
break;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
return {
|
|
63
|
-
files: (0, collections_1.unique)(all),
|
|
64
|
-
stats: { expected, resolved },
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* 🧩 applyIncludes()
|
|
69
|
-
* Scans and appends additional files defined in config.resolve.include.
|
|
70
|
-
*/
|
|
71
|
-
// src/core/dependency.ts
|
|
72
|
-
// (existing imports stay)
|
|
73
|
-
async function applyIncludes(cfg, files) {
|
|
74
|
-
const { resolve, root } = cfg;
|
|
75
|
-
const absFiles = [];
|
|
76
|
-
const patterns = [];
|
|
77
|
-
for (const raw of resolve.include) {
|
|
78
|
-
const p = String(raw ?? "").trim();
|
|
79
|
-
if (!p)
|
|
80
|
-
continue;
|
|
81
|
-
const norm = p.norm(); // uses your polyfill (slashes -> "/")
|
|
82
|
-
// absolute *file* paths bypass globScan (and its ignores)
|
|
83
|
-
if (path_1.default.isAbsolute(norm)) {
|
|
84
|
-
try {
|
|
85
|
-
if (fs_1.default.statSync(norm).isFile()) {
|
|
86
|
-
absFiles.push(path_1.default.resolve(norm));
|
|
87
|
-
continue;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
catch {
|
|
91
|
-
// doesn't exist / can't stat → treat as pattern
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
patterns.push(norm);
|
|
95
|
-
}
|
|
96
|
-
const scan = await (0, helpers_1.globScan)(patterns, { cwd: root });
|
|
97
|
-
return (0, collections_1.unique)([...files, ...absFiles, ...scan.files]);
|
|
98
|
-
}
|
package/dist/core/helpers.js
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
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.walk = walk;
|
|
7
|
-
exports.orderByPriority = orderByPriority;
|
|
8
|
-
exports.smartNaming = smartNaming;
|
|
9
|
-
exports.globScan = globScan;
|
|
10
|
-
const fs_1 = __importDefault(require("fs"));
|
|
11
|
-
const micromatch_1 = __importDefault(require("micromatch"));
|
|
12
|
-
const shared_1 = require("../shared");
|
|
13
|
-
const path_1 = __importDefault(require("path"));
|
|
14
|
-
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
15
|
-
const constants_1 = require("../constants");
|
|
16
|
-
const logger_1 = require("../lib/logger");
|
|
17
|
-
/**
|
|
18
|
-
* Recursive walker that respects glob exclude.
|
|
19
|
-
* Returns all files under the given directory tree.
|
|
20
|
-
*/
|
|
21
|
-
function* walk(dir, cfg, depth = 0) {
|
|
22
|
-
const { root, entry: { ui: { scanDepth }, }, resolve: { exclude }, } = cfg;
|
|
23
|
-
if (depth > scanDepth)
|
|
24
|
-
return;
|
|
25
|
-
const entries = fs_1.default.readdirSync(dir, { withFileTypes: true });
|
|
26
|
-
for (const e of entries) {
|
|
27
|
-
const full = path_1.default.join(dir, e.name);
|
|
28
|
-
if (e.isDirectory()) {
|
|
29
|
-
// Skip excluded directories entirely
|
|
30
|
-
const relPath = (0, shared_1.rel)(full, root);
|
|
31
|
-
if ((0, shared_1.isExcluded)(relPath, exclude))
|
|
32
|
-
continue;
|
|
33
|
-
yield* walk(full, cfg, depth + 1);
|
|
34
|
-
continue;
|
|
35
|
-
}
|
|
36
|
-
if (e.isFile()) {
|
|
37
|
-
const relPath = (0, shared_1.rel)(full, root);
|
|
38
|
-
if ((0, shared_1.isExcluded)(relPath, exclude))
|
|
39
|
-
continue;
|
|
40
|
-
yield full;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
function orderByPriority(files, priorityList = []) {
|
|
45
|
-
if (!priorityList.length)
|
|
46
|
-
return files;
|
|
47
|
-
const prioritized = [];
|
|
48
|
-
const normal = [];
|
|
49
|
-
for (const f of files) {
|
|
50
|
-
const normalized = f.norm().toLowerCase();
|
|
51
|
-
if (priorityList.some((p) => micromatch_1.default.isMatch(normalized, p.toLowerCase())))
|
|
52
|
-
prioritized.push(f);
|
|
53
|
-
else
|
|
54
|
-
normal.push(f);
|
|
55
|
-
}
|
|
56
|
-
return (0, shared_1.unique)([...prioritized, ...normal]);
|
|
57
|
-
}
|
|
58
|
-
function smartNaming(entries) {
|
|
59
|
-
const names = (0, shared_1.unique)(entries.map((f) => path_1.default.basename(f, path_1.default.extname(f))));
|
|
60
|
-
if (names.length === 1)
|
|
61
|
-
return names[0];
|
|
62
|
-
if (names.length === 2)
|
|
63
|
-
return `${names[0]}-${names[1]}`;
|
|
64
|
-
if (names.length > 2)
|
|
65
|
-
return `${names[0]}-and-${names.length - 1}more`;
|
|
66
|
-
return "prodex";
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Safe micromatch.scan wrapper (compatible with micromatch v4 & v5)
|
|
70
|
-
*/
|
|
71
|
-
async function globScan(patterns, opts) {
|
|
72
|
-
const { absolute = true, cwd = process.cwd() } = opts;
|
|
73
|
-
if (!patterns?.length)
|
|
74
|
-
return { files: [] };
|
|
75
|
-
const files = (await (0, fast_glob_1.default)(patterns, {
|
|
76
|
-
cwd,
|
|
77
|
-
extglob: true,
|
|
78
|
-
dot: true,
|
|
79
|
-
onlyFiles: true,
|
|
80
|
-
ignore: constants_1.GLOBAL_IGNORE,
|
|
81
|
-
absolute,
|
|
82
|
-
})).map((f) => path_1.default.resolve(f));
|
|
83
|
-
logger_1.logger.debug("globScan →", _2j(files));
|
|
84
|
-
return { files };
|
|
85
|
-
}
|
|
@@ -1,140 +0,0 @@
|
|
|
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.ConfigManager = void 0;
|
|
7
|
-
const fs_1 = __importDefault(require("fs"));
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const constants_1 = require("../../constants");
|
|
10
|
-
const utils_1 = require("../../lib/utils");
|
|
11
|
-
const flags_1 = require("../../constants/flags");
|
|
12
|
-
const store_1 = require("../../store");
|
|
13
|
-
/**
|
|
14
|
-
* 🧩 ConfigManager
|
|
15
|
-
* Unified loader, merger, and flag applier.
|
|
16
|
-
*/
|
|
17
|
-
class ConfigManager {
|
|
18
|
-
static rawFile = null;
|
|
19
|
-
static load(cwd = process.cwd()) {
|
|
20
|
-
const file = path_1.default.join(cwd, "prodex.json");
|
|
21
|
-
if (!fs_1.default.existsSync(file))
|
|
22
|
-
return constants_1.DEFAULT_PRODEX_CONFIG;
|
|
23
|
-
try {
|
|
24
|
-
const parsed = JSON.parse(fs_1.default.readFileSync(file, "utf8"));
|
|
25
|
-
this.rawFile = parsed; // <-- SAVE RAW COPY
|
|
26
|
-
return parsed;
|
|
27
|
-
}
|
|
28
|
-
catch {
|
|
29
|
-
console.warn("⚠️ Invalid prodex.json — using defaults.");
|
|
30
|
-
return constants_1.DEFAULT_PRODEX_CONFIG;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
static merge(user, flags, cwd = process.cwd()) {
|
|
34
|
-
const merged = {
|
|
35
|
-
// ...rest,
|
|
36
|
-
...user,
|
|
37
|
-
output: { ...constants_1.DEFAULT_PRODEX_CONFIG.output, ...user.output },
|
|
38
|
-
entry: {
|
|
39
|
-
...constants_1.DEFAULT_PRODEX_CONFIG.entry,
|
|
40
|
-
...user.entry,
|
|
41
|
-
ui: { ...constants_1.DEFAULT_PRODEX_CONFIG.entry.ui, ...user.entry?.ui },
|
|
42
|
-
},
|
|
43
|
-
resolve: { ...constants_1.DEFAULT_PRODEX_CONFIG.resolve, ...user.resolve },
|
|
44
|
-
root: cwd,
|
|
45
|
-
name: flags?.name ?? null,
|
|
46
|
-
};
|
|
47
|
-
this.applyFlags(merged, flags);
|
|
48
|
-
return this.normalize(merged);
|
|
49
|
-
}
|
|
50
|
-
static applyFlags(cfg, flags) {
|
|
51
|
-
if (!flags)
|
|
52
|
-
return cfg;
|
|
53
|
-
for (const [key, val] of Object.entries(flags)) {
|
|
54
|
-
if (val === undefined)
|
|
55
|
-
continue;
|
|
56
|
-
const def = flags_1.FLAG_MAP[key];
|
|
57
|
-
if (def?.apply)
|
|
58
|
-
def.apply(cfg, val);
|
|
59
|
-
}
|
|
60
|
-
const hasFiles = Array.isArray(flags.files) ? flags.files.length > 0 : !!flags.files;
|
|
61
|
-
const hasInclude = Array.isArray(flags.include) ? flags.include.length > 0 : !!flags.include;
|
|
62
|
-
if (hasInclude && !hasFiles)
|
|
63
|
-
cfg.entry.files = [];
|
|
64
|
-
if (hasFiles && !hasInclude)
|
|
65
|
-
cfg.resolve.include = [];
|
|
66
|
-
if (flags.shortcut && cfg.shortcuts && cfg.shortcuts[flags.shortcut])
|
|
67
|
-
return this.applyShortcuts(cfg, flags);
|
|
68
|
-
return cfg;
|
|
69
|
-
}
|
|
70
|
-
static applyShortcuts(cfg, flags) {
|
|
71
|
-
const shortcut = cfg.shortcuts?.[flags.shortcut];
|
|
72
|
-
if (!shortcut)
|
|
73
|
-
return cfg;
|
|
74
|
-
const mergeOrReplace = (key, target) => {
|
|
75
|
-
const flagValues = (flags[key] || []);
|
|
76
|
-
const hasFlags = !(0, utils_1.ArrisEmpty)(flagValues);
|
|
77
|
-
let values = shortcut[key];
|
|
78
|
-
if (!values && !hasFlags) {
|
|
79
|
-
target[key] = [];
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
if (!values)
|
|
83
|
-
values = [];
|
|
84
|
-
target[key] = hasFlags ? [...flagValues, ...values] : values;
|
|
85
|
-
};
|
|
86
|
-
// include / exclude live in cfg.resolve
|
|
87
|
-
mergeOrReplace("include", cfg.resolve);
|
|
88
|
-
mergeOrReplace("exclude", cfg.resolve);
|
|
89
|
-
// files live in cfg.entry
|
|
90
|
-
mergeOrReplace("files", cfg.entry);
|
|
91
|
-
// name override
|
|
92
|
-
if (shortcut.prefix)
|
|
93
|
-
cfg.name = shortcut.prefix;
|
|
94
|
-
return cfg;
|
|
95
|
-
}
|
|
96
|
-
static normalize(cfg) {
|
|
97
|
-
cfg.entry.files = (0, utils_1.normalizePatterns)(cfg.entry.files);
|
|
98
|
-
//TODO: Is there a need?
|
|
99
|
-
// cfg.resolve.include = normalizePatterns(cfg.resolve.include);
|
|
100
|
-
// cfg.resolve.exclude = normalizePatterns(cfg.resolve.exclude);
|
|
101
|
-
return cfg;
|
|
102
|
-
}
|
|
103
|
-
static persist(partial) {
|
|
104
|
-
const cfg = (0, store_1.getConfig)();
|
|
105
|
-
const dest = path_1.default.join(cfg.root, "prodex.json");
|
|
106
|
-
// Start from the raw config, never the merged runtime version
|
|
107
|
-
const base = ConfigManager.rawFile
|
|
108
|
-
? JSON.parse(JSON.stringify(ConfigManager.rawFile)) // deep clone to avoid mutation
|
|
109
|
-
: {};
|
|
110
|
-
// Apply only the partial updates (aliases, etc.)
|
|
111
|
-
const patched = deepMerge(base, partial);
|
|
112
|
-
try {
|
|
113
|
-
fs_1.default.writeFileSync(dest, (0, utils_1.toJson)(patched) + "\n", "utf8");
|
|
114
|
-
}
|
|
115
|
-
catch (err) {
|
|
116
|
-
console.warn("⚠️ Failed to persist config:", err?.message || err);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
exports.ConfigManager = ConfigManager;
|
|
121
|
-
function deepMerge(base, patch) {
|
|
122
|
-
if (!patch)
|
|
123
|
-
return base;
|
|
124
|
-
const out = Array.isArray(base) ? [...base] : { ...base };
|
|
125
|
-
for (const [k, v] of Object.entries(patch)) {
|
|
126
|
-
if (v === undefined)
|
|
127
|
-
continue;
|
|
128
|
-
const bv = base[k];
|
|
129
|
-
if (Array.isArray(v))
|
|
130
|
-
out[k] = [...v]; // overwrite arrays
|
|
131
|
-
else if (isPlainObject(v) && isPlainObject(bv))
|
|
132
|
-
out[k] = deepMerge(bv, v);
|
|
133
|
-
else
|
|
134
|
-
out[k] = v;
|
|
135
|
-
}
|
|
136
|
-
return out;
|
|
137
|
-
}
|
|
138
|
-
function isPlainObject(x) {
|
|
139
|
-
return x && typeof x === "object" && !Array.isArray(x);
|
|
140
|
-
}
|
package/dist/core/output.js
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
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.produceOutput = produceOutput;
|
|
7
|
-
const fs_1 = __importDefault(require("fs"));
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const prompt_1 = require("../lib/prompt");
|
|
10
|
-
const renderers_1 = require("./renderers");
|
|
11
|
-
const logger_1 = require("../lib/logger");
|
|
12
|
-
const utils_1 = require("../lib/utils");
|
|
13
|
-
const questions_1 = require("../lib/questions");
|
|
14
|
-
const constants_1 = require("../constants");
|
|
15
|
-
/**
|
|
16
|
-
* 🧩 produceOutput()
|
|
17
|
-
* Handles rendering and writing of the final trace file.
|
|
18
|
-
* Receives resolved files and configuration from combine.ts.
|
|
19
|
-
*/
|
|
20
|
-
async function produceOutput({ name, files, cfg, showUi }) {
|
|
21
|
-
const { output: { format, versioned, dir }, } = cfg;
|
|
22
|
-
// 1️⃣ Determine base filename
|
|
23
|
-
let outputBase = name;
|
|
24
|
-
if (showUi) {
|
|
25
|
-
const result = await (0, prompt_1.prompt)(questions_1.OUTPUT_NAME_QUESTION);
|
|
26
|
-
if (result?.outputBase)
|
|
27
|
-
outputBase = result.outputBase;
|
|
28
|
-
}
|
|
29
|
-
// 2️⃣ Prefix timestamp if versioned
|
|
30
|
-
outputBase = `${outputBase}-${constants_1.SUFFIX}`;
|
|
31
|
-
if (versioned)
|
|
32
|
-
outputBase = `${outputBase}_${(0, utils_1.shortTimestamp)()}`;
|
|
33
|
-
// 3️⃣ Ensure output directory
|
|
34
|
-
try {
|
|
35
|
-
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
36
|
-
}
|
|
37
|
-
catch {
|
|
38
|
-
logger_1.logger.warn("Could not create dir directory:", dir);
|
|
39
|
-
}
|
|
40
|
-
// 4️⃣ Prepare and write content
|
|
41
|
-
const outputPath = path_1.default.join(dir, `${outputBase}.${format}`);
|
|
42
|
-
const sorted = [...files].sort((a, b) => a.localeCompare(b));
|
|
43
|
-
//[tocMd(sorted), ...sorted.map((f, i) => renderMd(f, i)), MD_FOOTER].join("\n")
|
|
44
|
-
const content = format === "txt"
|
|
45
|
-
? [(0, renderers_1.tocTxt)(sorted), ...sorted.map(renderers_1.renderTxt)].join("")
|
|
46
|
-
: (0, renderers_1.renderTraceMd)(sorted).content;
|
|
47
|
-
fs_1.default.writeFileSync(outputPath, content, "utf8");
|
|
48
|
-
return outputPath;
|
|
49
|
-
}
|
package/dist/core/renderers.js
DELETED
|
@@ -1,210 +0,0 @@
|
|
|
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.renderTraceMd = renderTraceMd;
|
|
7
|
-
exports.tocMd = tocMd;
|
|
8
|
-
exports.renderMd = renderMd;
|
|
9
|
-
exports.tocTxt = tocTxt;
|
|
10
|
-
exports.renderTxt = renderTxt;
|
|
11
|
-
const path_1 = __importDefault(require("path"));
|
|
12
|
-
const shared_1 = require("../shared");
|
|
13
|
-
const constants_1 = require("../constants");
|
|
14
|
-
/**
|
|
15
|
-
* renderTraceMd()
|
|
16
|
-
* Builds the full Markdown document AND computes:
|
|
17
|
-
* - listing start/end lines
|
|
18
|
-
* - each file section start/end lines (in the final output)
|
|
19
|
-
*/
|
|
20
|
-
// src/core/renderers.ts
|
|
21
|
-
function renderTraceMd(files) {
|
|
22
|
-
const count = files.length;
|
|
23
|
-
// Render sections at once (content of each file)
|
|
24
|
-
const sections = files.map((f, i) => renderMd(f, i));
|
|
25
|
-
// 1) Build a FIRST PASS doc with placeholder TOC (no line ranges)
|
|
26
|
-
const pass1Toc = buildToc({
|
|
27
|
-
files,
|
|
28
|
-
count,
|
|
29
|
-
listingStart: 0,
|
|
30
|
-
listingEnd: 0,
|
|
31
|
-
trace: null,
|
|
32
|
-
withRanges: false,
|
|
33
|
-
});
|
|
34
|
-
const pass1Content = [pass1Toc, ...sections, constants_1.MD_FOOTER].join("\n");
|
|
35
|
-
// 2) Analyze the FINAL STRING (pass 1) to get real line indexes
|
|
36
|
-
const pass1Analysis = analyzeTrace(pass1Content, count);
|
|
37
|
-
// 3) Build pass 2 TOC including listing range + per-file ranges
|
|
38
|
-
const pass2Toc = buildToc({
|
|
39
|
-
files,
|
|
40
|
-
count,
|
|
41
|
-
listingStart: pass1Analysis.listingStart,
|
|
42
|
-
listingEnd: pass1Analysis.listingEnd,
|
|
43
|
-
trace: pass1Analysis.trace,
|
|
44
|
-
withRanges: true,
|
|
45
|
-
});
|
|
46
|
-
const pass2Content = [pass2Toc, ...sections, constants_1.MD_FOOTER].join("\n");
|
|
47
|
-
// 4) Re-analyze pass 2 content (should be identical; extra safety)
|
|
48
|
-
const pass2Analysis = analyzeTrace(pass2Content, count);
|
|
49
|
-
// If anything drifted (it really shouldn’t), trust pass 2’s analysis.
|
|
50
|
-
// Rebuilding again would still not change line counts, so this is stable.
|
|
51
|
-
return {
|
|
52
|
-
content: pass2Content,
|
|
53
|
-
trace: pass2Analysis.trace,
|
|
54
|
-
listingStart: pass2Analysis.listingStart,
|
|
55
|
-
listingEnd: pass2Analysis.listingEnd,
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
const rangeText = (start, end) => ` L${start}-L${end}`;
|
|
59
|
-
function buildToc(opts) {
|
|
60
|
-
const { files, count, listingStart, listingEnd, trace, withRanges } = opts;
|
|
61
|
-
const indexRange = withRanges && listingStart && listingEnd
|
|
62
|
-
? `L${listingStart}-L${listingEnd}`
|
|
63
|
-
: constants_1.INDEX_RANGE_PLACEHOLDER;
|
|
64
|
-
const tocHead = [
|
|
65
|
-
constants_1.MD_HEADER,
|
|
66
|
-
constants_1.LLM_NOTE,
|
|
67
|
-
"",
|
|
68
|
-
"# Index",
|
|
69
|
-
`<!-- PRODEX_INDEX_RANGE: ${indexRange} -->`,
|
|
70
|
-
`<!-- PRODEX_FILE_COUNT: ${count} -->`,
|
|
71
|
-
"<!-- PRODEX_INDEX_LIST_START -->",
|
|
72
|
-
];
|
|
73
|
-
const items = files.map((f, i) => {
|
|
74
|
-
const rp = (0, shared_1.rel)(f);
|
|
75
|
-
if (!withRanges || !trace)
|
|
76
|
-
return `- [${rp}](#${i + 1})`;
|
|
77
|
-
const t = trace[i];
|
|
78
|
-
return `- [${rp}](#${i + 1}) ${rangeText(t.startLine, t.endLine)}`;
|
|
79
|
-
});
|
|
80
|
-
const tocTail = ["<!-- PRODEX_INDEX_LIST_END -->", "", "---"];
|
|
81
|
-
return [...tocHead, ...items, ...tocTail].join("\n");
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Analyze the already-generated Markdown to compute:
|
|
85
|
-
* - listing start/end lines
|
|
86
|
-
* - each section start/end line (per file index)
|
|
87
|
-
*
|
|
88
|
-
* All line numbers are 1-based.
|
|
89
|
-
*/
|
|
90
|
-
function analyzeTrace(content, count) {
|
|
91
|
-
const lines = content.split("\n");
|
|
92
|
-
// --- Listing range ---
|
|
93
|
-
const startMarkerIdx = lines.findIndex((l) => l.trim() === "<!-- PRODEX_INDEX_LIST_START -->");
|
|
94
|
-
const endMarkerIdx = lines.findIndex((l) => l.trim() === "<!-- PRODEX_INDEX_LIST_END -->");
|
|
95
|
-
let listingStart = 0;
|
|
96
|
-
let listingEnd = 0;
|
|
97
|
-
if (startMarkerIdx >= 0 && endMarkerIdx > startMarkerIdx) {
|
|
98
|
-
const itemIdxs = [];
|
|
99
|
-
for (let i = startMarkerIdx + 1; i < endMarkerIdx; i++) {
|
|
100
|
-
if (lines[i].trim().startsWith("- "))
|
|
101
|
-
itemIdxs.push(i);
|
|
102
|
-
}
|
|
103
|
-
if (itemIdxs.length) {
|
|
104
|
-
listingStart = itemIdxs[0] + 1; // 1-based
|
|
105
|
-
// count is zero during the first (placeholder) pass; cap to the requested count when provided, otherwise use the discovered items
|
|
106
|
-
const cappedCount = count > 0 ? Math.min(itemIdxs.length, count) : itemIdxs.length;
|
|
107
|
-
const lastItemIdx = itemIdxs[cappedCount - 1];
|
|
108
|
-
listingEnd = lastItemIdx + 1;
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
listingStart = startMarkerIdx + 2; // move past the marker line (0-based) and convert to 1-based line numbers
|
|
112
|
-
listingEnd = listingStart;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
// --- Footer start (exclude footer from last file range) ---
|
|
116
|
-
let footerMarkerIdx = lines.findIndex((l) => l.includes("<!-- PRODEx v"));
|
|
117
|
-
if (footerMarkerIdx < 0)
|
|
118
|
-
footerMarkerIdx = lines.findIndex((l) => l.includes("*Generated with [Prodex]"));
|
|
119
|
-
let footerStartIdx = footerMarkerIdx >= 0 ? footerMarkerIdx : lines.length; // 0-based
|
|
120
|
-
if (footerStartIdx > 0 && lines[footerStartIdx - 1].trim() === "---")
|
|
121
|
-
footerStartIdx = footerStartIdx - 1;
|
|
122
|
-
// --- Section markers: find "#### N" lines ---
|
|
123
|
-
const markerLineIdxByN = new Map();
|
|
124
|
-
for (let i = 0; i < lines.length; i++) {
|
|
125
|
-
const m = lines[i].trim().match(/^####\s+(\d+)\s*$/);
|
|
126
|
-
if (!m)
|
|
127
|
-
continue;
|
|
128
|
-
const n = Number(m[1]);
|
|
129
|
-
if (!Number.isFinite(n))
|
|
130
|
-
continue;
|
|
131
|
-
if (n < 1 || n > count)
|
|
132
|
-
continue;
|
|
133
|
-
if (!markerLineIdxByN.has(n))
|
|
134
|
-
markerLineIdxByN.set(n, i);
|
|
135
|
-
}
|
|
136
|
-
// Compute each section's start idx (prefer the preceding "---" line if present)
|
|
137
|
-
const startIdxs = [];
|
|
138
|
-
for (let n = 1; n <= count; n++) {
|
|
139
|
-
const markerIdx = markerLineIdxByN.get(n);
|
|
140
|
-
if (markerIdx == null) {
|
|
141
|
-
// Fallback: if marker missing, make it non-crashy.
|
|
142
|
-
// Put start at footerStart (it'll produce tiny/empty ranges rather than exploding).
|
|
143
|
-
startIdxs.push(footerStartIdx);
|
|
144
|
-
continue;
|
|
145
|
-
}
|
|
146
|
-
const maybeStart = markerIdx > 0 && lines[markerIdx - 1].trim() === "---" ? markerIdx - 1 : markerIdx;
|
|
147
|
-
startIdxs.push(maybeStart);
|
|
148
|
-
}
|
|
149
|
-
// Compute end idx using next section start, or footer start
|
|
150
|
-
const trace = [];
|
|
151
|
-
for (let i = 0; i < count; i++) {
|
|
152
|
-
const startIdx = startIdxs[i];
|
|
153
|
-
const nextStartIdx = i < count - 1 ? startIdxs[i + 1] : footerStartIdx;
|
|
154
|
-
const endIdx = Math.max(startIdx, nextStartIdx - 1);
|
|
155
|
-
trace.push({
|
|
156
|
-
file: "", // filled by caller if needed; TOC uses rel(files[i]) anyway
|
|
157
|
-
anchor: i + 1,
|
|
158
|
-
startLine: startIdx + 1,
|
|
159
|
-
endLine: endIdx + 1,
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
return { listingStart, listingEnd, trace };
|
|
163
|
-
}
|
|
164
|
-
/**
|
|
165
|
-
* Existing functions kept as-is.
|
|
166
|
-
* (renderMd is used by renderTraceMd above)
|
|
167
|
-
*/
|
|
168
|
-
function tocMd(files) {
|
|
169
|
-
const count = files.length;
|
|
170
|
-
const items = files.map((f, i) => `- [${(0, shared_1.rel)(f)}](#${i + 1})`);
|
|
171
|
-
return [
|
|
172
|
-
constants_1.MD_HEADER,
|
|
173
|
-
constants_1.LLM_NOTE,
|
|
174
|
-
"",
|
|
175
|
-
"# Index",
|
|
176
|
-
`<!-- PRODEX_INDEX_RANGE: ${constants_1.INDEX_RANGE_PLACEHOLDER} -->`,
|
|
177
|
-
`<!-- PRODEX_FILE_COUNT: ${count} -->`,
|
|
178
|
-
"<!-- PRODEX_INDEX_LIST_START -->",
|
|
179
|
-
...items,
|
|
180
|
-
"<!-- PRODEX_INDEX_LIST_END -->",
|
|
181
|
-
"",
|
|
182
|
-
"---",
|
|
183
|
-
].join("\n");
|
|
184
|
-
}
|
|
185
|
-
function renderMd(p, i) {
|
|
186
|
-
const rp = (0, shared_1.rel)(p);
|
|
187
|
-
const ext = path_1.default.extname(p).toLowerCase();
|
|
188
|
-
const lang = constants_1.LANG_MAP[ext] || "txt";
|
|
189
|
-
const code = (0, shared_1.readFileSafe)(p).trimEnd();
|
|
190
|
-
return [
|
|
191
|
-
`---\n#### ${i + 1}`,
|
|
192
|
-
"\n",
|
|
193
|
-
"` File: " + rp + "` [↑ Back to top](#index)",
|
|
194
|
-
"",
|
|
195
|
-
"```" + lang,
|
|
196
|
-
code,
|
|
197
|
-
"```",
|
|
198
|
-
"",
|
|
199
|
-
].join("\n");
|
|
200
|
-
}
|
|
201
|
-
// TXT versions unchanged
|
|
202
|
-
function tocTxt(files) {
|
|
203
|
-
const sorted = [...files].sort((a, b) => a.localeCompare(b));
|
|
204
|
-
return ["##==== Combined Scope ====", ...sorted.map((f) => "## - " + (0, shared_1.rel)(f))].join("\n") + "\n\n";
|
|
205
|
-
}
|
|
206
|
-
function renderTxt(p) {
|
|
207
|
-
const relPath = (0, shared_1.rel)(p);
|
|
208
|
-
const code = (0, shared_1.readFileSafe)(p);
|
|
209
|
-
return ["##==== path: " + relPath + " ====", "##region " + relPath, code, "##endregion", ""].join("\n");
|
|
210
|
-
}
|
package/dist/debug.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
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
|
-
const index_1 = __importDefault(require("./index"));
|
|
7
|
-
require("source-map-support/register");
|
|
8
|
-
(async () => {
|
|
9
|
-
const mockArgs = ["node", "prodex", "-i", "src/**", "-d"];
|
|
10
|
-
process.argv = mockArgs;
|
|
11
|
-
//"-f", "**/(dashboard|accounts).tsx",
|
|
12
|
-
console.log("🧩 Debug runner starting...");
|
|
13
|
-
await (0, index_1.default)();
|
|
14
|
-
console.log("🧩 Debug runner done.");
|
|
15
|
-
})();
|
package/dist/lib/logger.js
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.logger = void 0;
|
|
4
|
-
const store_1 = require("../store");
|
|
5
|
-
let FLAGS = null;
|
|
6
|
-
let DEBUG = false;
|
|
7
|
-
let SILENT = false;
|
|
8
|
-
function ensureFlags() {
|
|
9
|
-
if (FLAGS)
|
|
10
|
-
return;
|
|
11
|
-
FLAGS = (0, store_1.getFlags)() || {};
|
|
12
|
-
DEBUG = !!FLAGS.debug;
|
|
13
|
-
SILENT = !!FLAGS.silent;
|
|
14
|
-
}
|
|
15
|
-
exports.logger = {
|
|
16
|
-
debug: (...a) => {
|
|
17
|
-
ensureFlags();
|
|
18
|
-
if (DEBUG && !SILENT)
|
|
19
|
-
console.log("\n🪶 [debug]", ...a);
|
|
20
|
-
},
|
|
21
|
-
info: (...a) => {
|
|
22
|
-
ensureFlags();
|
|
23
|
-
if (!SILENT)
|
|
24
|
-
console.log("\n📌 [info]", ...a);
|
|
25
|
-
},
|
|
26
|
-
warn: (...a) => {
|
|
27
|
-
ensureFlags();
|
|
28
|
-
if (!SILENT)
|
|
29
|
-
console.warn("\n⚠️ [warn]", ...a);
|
|
30
|
-
},
|
|
31
|
-
error: (...a) => {
|
|
32
|
-
ensureFlags();
|
|
33
|
-
if (!SILENT)
|
|
34
|
-
console.error("\n💥 [error]", ...a);
|
|
35
|
-
},
|
|
36
|
-
log: (...a) => {
|
|
37
|
-
ensureFlags();
|
|
38
|
-
if (!SILENT)
|
|
39
|
-
console.log("\n", ...a);
|
|
40
|
-
},
|
|
41
|
-
clear: () => console.clear(),
|
|
42
|
-
};
|
package/dist/lib/polyfills.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
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
|
-
const util_1 = __importDefault(require("util"));
|
|
7
|
-
if (!String.prototype.norm) {
|
|
8
|
-
String.prototype.norm = function () {
|
|
9
|
-
return this.replace(/\\/g, "/");
|
|
10
|
-
};
|
|
11
|
-
}
|
|
12
|
-
if (!String.prototype.clean) {
|
|
13
|
-
String.prototype.clean = function () {
|
|
14
|
-
return this.replace(/[<>:\"/\\|?*]+/g, "_");
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
globalThis._2j = (obj) => util_1.default.inspect(obj, { colors: true, depth: null, breakLength: 150, compact: 3 });
|