prodex 1.4.11 → 2.0.1
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 +240 -234
- package/bin/prodex.js +0 -0
- package/dist/app/execute-run.d.ts +2 -0
- package/dist/app/execute-run.js +74 -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 +28 -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 +101 -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 +62 -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
|
@@ -5,120 +5,89 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.resolvePhpImports = resolvePhpImports;
|
|
7
7
|
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
8
9
|
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const
|
|
10
|
+
const cache_keys_1 = require("../../cache/cache-keys");
|
|
11
|
+
const cache_manager_1 = require("../../cache/cache-manager");
|
|
12
|
+
const logger_1 = require("../../diagnostics/logger");
|
|
13
|
+
const path_2 = require("../../filesystem/path");
|
|
14
|
+
const read_file_1 = require("../../filesystem/read-file");
|
|
15
|
+
const resolver_result_1 = require("../resolver-result");
|
|
10
16
|
const bindings_1 = require("./bindings");
|
|
17
|
+
const extract_imports_1 = require("./extract-imports");
|
|
11
18
|
const psr4_1 = require("./psr4");
|
|
12
|
-
|
|
13
|
-
const shared_1 = require("../../shared");
|
|
14
|
-
const store_1 = require("../../store");
|
|
15
|
-
const constants_1 = require("../../constants");
|
|
16
|
-
const cache_1 = require("../../core/managers/cache");
|
|
17
|
-
const collections_1 = require("../../shared/collections");
|
|
18
|
-
const promises_1 = __importDefault(require("fs/promises")); // (add near the top if not present)
|
|
19
|
-
/**
|
|
20
|
-
* Typed PHP resolver (aligned with JS resolver signature).
|
|
21
|
-
* - Uses global config via getConfig()
|
|
22
|
-
* - Returns ResolverResult (files + stats)
|
|
23
|
-
* - Depth/visited guarded recursion
|
|
24
|
-
*/
|
|
25
|
-
async function resolvePhpImports({ filePath, visited = new Set(), depth = 0, maxDepth, ctx }) {
|
|
26
|
-
const { root: ROOT, resolve: { exclude: excludePatterns = [], depth: defaultDepth = 10 }, } = (0, store_1.getConfig)();
|
|
27
|
-
const limitDepth = maxDepth ?? defaultDepth;
|
|
28
|
-
if (depth >= limitDepth)
|
|
29
|
-
return (0, collections_1.emptyResult)(visited);
|
|
30
|
-
if (visited.has(filePath))
|
|
31
|
-
return (0, collections_1.emptyResult)(visited);
|
|
32
|
-
visited.add(filePath);
|
|
33
|
-
// Fast existence / read
|
|
19
|
+
async function resolvePhpImports({ cfg, filePath, ctx }) {
|
|
34
20
|
if (!fs_1.default.existsSync(filePath))
|
|
35
|
-
return (0,
|
|
36
|
-
const code = (0,
|
|
21
|
+
return (0, resolver_result_1.emptyResolverResult)();
|
|
22
|
+
const code = (0, read_file_1.readFileSafe)(filePath);
|
|
37
23
|
if (!code)
|
|
38
|
-
return (0,
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const stats = (0, shared_1.newStats)();
|
|
48
|
-
const filesOut = [];
|
|
49
|
-
for (const imp0 of imports) {
|
|
50
|
-
let imp = imp0;
|
|
51
|
-
if (!imp || typeof imp !== "string")
|
|
52
|
-
continue;
|
|
53
|
-
// Fully-qualified check
|
|
54
|
-
const isFullyQualified = imp.includes("\\") || imp.startsWith("\\");
|
|
55
|
-
if (!isFullyQualified && currentNamespace) {
|
|
56
|
-
imp = `${currentNamespace}\\${imp}`;
|
|
57
|
-
}
|
|
58
|
-
// Respect Laravel container bindings (Interface → Implementation)
|
|
59
|
-
if (phpCtx.bindings[imp]) {
|
|
60
|
-
// logger.debug("[php-resolver] binding:", imp, "→", _2j(phpCtx.bindings[imp]));
|
|
61
|
-
imp = phpCtx.bindings[imp];
|
|
62
|
-
}
|
|
63
|
-
// Only resolve PSR-4 mapped namespaces
|
|
64
|
-
if (!startsWithAnyNamespace(imp, phpCtx.nsKeys))
|
|
24
|
+
return (0, resolver_result_1.emptyResolverResult)();
|
|
25
|
+
const currentNamespace = getCurrentNamespace(code);
|
|
26
|
+
const phpCtx = buildPhpCtx(cfg.root, ctx);
|
|
27
|
+
const imports = (0, extract_imports_1.expandGroupedUses)((0, extract_imports_1.extractPhpImports)(code));
|
|
28
|
+
const stats = (0, resolver_result_1.newResolverStats)();
|
|
29
|
+
const files = [];
|
|
30
|
+
for (const importName of imports) {
|
|
31
|
+
const resolvedImport = resolveNamespaceImport(importName, currentNamespace, phpCtx);
|
|
32
|
+
if (!resolvedImport)
|
|
65
33
|
continue;
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
// Exclusion check after final resolution
|
|
69
|
-
if ((0, shared_1.isExcluded)(resolvedPath, excludePatterns, ROOT))
|
|
70
|
-
continue;
|
|
71
|
-
stats.expected.add(imp);
|
|
34
|
+
const resolvedPath = await tryResolvePhpFile(resolvedImport, filePath, phpCtx.psr4);
|
|
35
|
+
stats.expected.add(resolvedImport);
|
|
72
36
|
if (!resolvedPath)
|
|
73
37
|
continue;
|
|
74
|
-
stats.resolved.add(
|
|
75
|
-
|
|
76
|
-
// Recurse
|
|
77
|
-
const sub = await resolvePhpImports({
|
|
78
|
-
filePath: resolvedPath,
|
|
79
|
-
visited,
|
|
80
|
-
depth: depth + 1,
|
|
81
|
-
maxDepth: limitDepth,
|
|
82
|
-
ctx: phpCtx,
|
|
83
|
-
});
|
|
84
|
-
filesOut.push(...sub.files);
|
|
85
|
-
(0, shared_1.mergeStats)(stats, sub.stats);
|
|
38
|
+
stats.resolved.add(resolvedImport);
|
|
39
|
+
files.push(resolvedPath);
|
|
86
40
|
}
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
logger_1.logger.debug(`🪶 [php-resolver] ${path_1.default.basename(filePath)} → expected: ${stats.expected.size}, resolved: ${stats.resolved.size}`);
|
|
41
|
+
const unresolved = (0, resolver_result_1.resolverSetDiff)(stats.expected, stats.resolved);
|
|
42
|
+
logger_1.logger.debug(`[php-resolver] ${path_1.default.basename(filePath)} -> expected: ${stats.expected.size}, resolved: ${stats.resolved.size}`);
|
|
90
43
|
if (unresolved.size)
|
|
91
44
|
logger_1.logger.debug("[php-resolver] unresolved:", [...unresolved]);
|
|
92
|
-
return { files:
|
|
45
|
+
return { files: (0, resolver_result_1.uniqueResolvedFiles)(files), stats };
|
|
46
|
+
}
|
|
47
|
+
function getCurrentNamespace(code) {
|
|
48
|
+
const nsMatch = code.match(/\bnamespace\s+([^;]+);/);
|
|
49
|
+
return nsMatch ? nsMatch[1].trim() : null;
|
|
50
|
+
}
|
|
51
|
+
function resolveNamespaceImport(importName, currentNamespace, ctx) {
|
|
52
|
+
if (!importName || typeof importName !== "string")
|
|
53
|
+
return null;
|
|
54
|
+
let resolved = importName;
|
|
55
|
+
const isFullyQualified = resolved.includes("\\") || resolved.startsWith("\\");
|
|
56
|
+
if (!isFullyQualified && currentNamespace)
|
|
57
|
+
resolved = `${currentNamespace}\\${resolved}`;
|
|
58
|
+
if (ctx.bindings[resolved])
|
|
59
|
+
resolved = ctx.bindings[resolved];
|
|
60
|
+
return startsWithAnyNamespace(resolved, ctx.nsKeys) ? resolved : null;
|
|
93
61
|
}
|
|
94
62
|
async function tryResolvePhpFile(imp, fromFile, psr4) {
|
|
95
63
|
const key = `php:${imp}:${fromFile}`;
|
|
96
|
-
const cached =
|
|
64
|
+
const cached = cache_manager_1.CacheManager.get(cache_keys_1.CACHE_KEYS.PHP_FILECACHE, key);
|
|
97
65
|
if (cached !== undefined)
|
|
98
66
|
return cached;
|
|
99
|
-
const nsKey = Object.keys(psr4).find((
|
|
67
|
+
const nsKey = Object.keys(psr4).find((candidate) => imp.startsWith(candidate));
|
|
100
68
|
if (!nsKey) {
|
|
101
|
-
|
|
69
|
+
cache_manager_1.CacheManager.set(cache_keys_1.CACHE_KEYS.PHP_FILECACHE, key, null);
|
|
102
70
|
return null;
|
|
103
71
|
}
|
|
104
|
-
const
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
72
|
+
const relativeImport = (0, path_2.normalizePath)(imp.replace(nsKey, ""));
|
|
73
|
+
const candidates = [
|
|
74
|
+
path_1.default.join(psr4[nsKey], relativeImport),
|
|
75
|
+
path_1.default.join(psr4[nsKey], relativeImport + ".php"),
|
|
76
|
+
path_1.default.join(psr4[nsKey], relativeImport, "index.php"),
|
|
77
|
+
];
|
|
78
|
+
const results = await Promise.allSettled(candidates.map(async (candidate) => {
|
|
108
79
|
try {
|
|
109
|
-
const
|
|
110
|
-
return
|
|
80
|
+
const stats = await promises_1.default.stat(candidate);
|
|
81
|
+
return stats.isFile() ? path_1.default.resolve(candidate) : null;
|
|
111
82
|
}
|
|
112
83
|
catch {
|
|
113
84
|
return null;
|
|
114
85
|
}
|
|
115
86
|
}));
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
cache_1.CacheManager.set(constants_1.CACHE_KEYS.PHP_FILECACHE, key, resolved);
|
|
87
|
+
const resolved = results.find(isFulfilledPath)?.value ?? null;
|
|
88
|
+
cache_manager_1.CacheManager.set(cache_keys_1.CACHE_KEYS.PHP_FILECACHE, key, resolved);
|
|
119
89
|
return resolved;
|
|
120
90
|
}
|
|
121
|
-
/** Ensure we have a PHP resolver context for the current root */
|
|
122
91
|
function buildPhpCtx(root, prev) {
|
|
123
92
|
if (prev?.kind === "php")
|
|
124
93
|
return prev;
|
|
@@ -127,10 +96,12 @@ function buildPhpCtx(root, prev) {
|
|
|
127
96
|
const bindings = (0, bindings_1.loadLaravelBindings)(root);
|
|
128
97
|
return { kind: "php", psr4, nsKeys, bindings };
|
|
129
98
|
}
|
|
130
|
-
/** Namespace prefix check */
|
|
131
99
|
function startsWithAnyNamespace(imp, nsKeys) {
|
|
132
|
-
for (const
|
|
133
|
-
if (imp.startsWith(
|
|
100
|
+
for (const nsKey of nsKeys)
|
|
101
|
+
if (imp.startsWith(nsKey))
|
|
134
102
|
return true;
|
|
135
103
|
return false;
|
|
136
104
|
}
|
|
105
|
+
function isFulfilledPath(result) {
|
|
106
|
+
return result.status === "fulfilled" && !!result.value;
|
|
107
|
+
}
|
|
@@ -6,19 +6,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.resolvePsr4 = resolvePsr4;
|
|
7
7
|
const fs_1 = __importDefault(require("fs"));
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const
|
|
10
|
-
const cache_keys_1 = require("../../
|
|
9
|
+
const cache_manager_1 = require("../../cache/cache-manager");
|
|
10
|
+
const cache_keys_1 = require("../../cache/cache-keys");
|
|
11
11
|
/**
|
|
12
|
-
* Builds a PSR-4 namespace
|
|
12
|
+
* Builds a PSR-4 namespace to directory map from composer.json.
|
|
13
13
|
* Returns absolute paths in the map values.
|
|
14
14
|
*/
|
|
15
15
|
function resolvePsr4(root) {
|
|
16
|
-
const cached =
|
|
16
|
+
const cached = cache_manager_1.CacheManager.get(cache_keys_1.CACHE_KEYS.PHP_PSR4, root);
|
|
17
17
|
if (cached)
|
|
18
18
|
return cached;
|
|
19
19
|
const composer = path_1.default.join(root, "composer.json");
|
|
20
20
|
if (!fs_1.default.existsSync(composer)) {
|
|
21
|
-
|
|
21
|
+
cache_manager_1.CacheManager.set(cache_keys_1.CACHE_KEYS.PHP_PSR4, root, {});
|
|
22
22
|
return {};
|
|
23
23
|
}
|
|
24
24
|
try {
|
|
@@ -29,11 +29,11 @@ function resolvePsr4(root) {
|
|
|
29
29
|
const cleanNs = ns.replace(/\\+$/, "");
|
|
30
30
|
map[cleanNs] = path_1.default.resolve(root, src[ns]);
|
|
31
31
|
}
|
|
32
|
-
|
|
32
|
+
cache_manager_1.CacheManager.set(cache_keys_1.CACHE_KEYS.PHP_PSR4, root, map);
|
|
33
33
|
return map;
|
|
34
34
|
}
|
|
35
35
|
catch {
|
|
36
|
-
|
|
36
|
+
cache_manager_1.CacheManager.set(cache_keys_1.CACHE_KEYS.PHP_PSR4, root, {});
|
|
37
37
|
return {};
|
|
38
38
|
}
|
|
39
39
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DTS_EXT = exports.REAL_EXTS = exports.BASE_EXTS = exports.CODE_EXTS = void 0;
|
|
4
|
+
exports.CODE_EXTS = [".js", ".mjs", ".ts", ".tsx", ".d.ts", ".php"];
|
|
5
|
+
exports.BASE_EXTS = [".ts", ".tsx", ".js", ".jsx", ".mjs"];
|
|
6
|
+
exports.REAL_EXTS = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".d.ts", ".json"]);
|
|
7
|
+
exports.DTS_EXT = ".d.ts";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ResolverResult } from "../types";
|
|
2
|
+
export declare function newResolverStats(): ResolverResult["stats"];
|
|
3
|
+
export declare function emptyResolverResult(): ResolverResult;
|
|
4
|
+
export declare function resolverSetDiff<A>(left: Set<A>, right: Set<A>): Set<A>;
|
|
5
|
+
export declare function uniqueResolvedFiles(files: string[]): string[];
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.newResolverStats = newResolverStats;
|
|
4
|
+
exports.emptyResolverResult = emptyResolverResult;
|
|
5
|
+
exports.resolverSetDiff = resolverSetDiff;
|
|
6
|
+
exports.uniqueResolvedFiles = uniqueResolvedFiles;
|
|
7
|
+
function newResolverStats() {
|
|
8
|
+
return { expected: new Set(), resolved: new Set() };
|
|
9
|
+
}
|
|
10
|
+
function emptyResolverResult() {
|
|
11
|
+
return { files: [], stats: newResolverStats() };
|
|
12
|
+
}
|
|
13
|
+
function resolverSetDiff(left, right) {
|
|
14
|
+
return new Set([...left].filter((item) => !right.has(item)));
|
|
15
|
+
}
|
|
16
|
+
function uniqueResolvedFiles(files) {
|
|
17
|
+
return [...new Set(files)];
|
|
18
|
+
}
|
|
@@ -4,10 +4,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.isExcluded = isExcluded;
|
|
7
|
-
// File: src/shared/patterns.ts
|
|
8
7
|
const micromatch_1 = __importDefault(require("micromatch"));
|
|
9
8
|
const path_1 = __importDefault(require("path"));
|
|
10
|
-
const
|
|
9
|
+
const read_file_1 = require("../filesystem/read-file");
|
|
10
|
+
const path_2 = require("../filesystem/path");
|
|
11
11
|
/**
|
|
12
12
|
* Centralized exclusion logic.
|
|
13
13
|
* Accepts namespaces, absolute paths, or relative paths
|
|
@@ -18,10 +18,10 @@ function isExcluded(p, patterns = [], root = process.cwd()) {
|
|
|
18
18
|
return false;
|
|
19
19
|
if (!p)
|
|
20
20
|
return false;
|
|
21
|
-
let norm =
|
|
21
|
+
let norm = (0, path_2.normalizePath)(p);
|
|
22
22
|
if (!path_1.default.isAbsolute(norm) && /^[A-Z]/.test(norm))
|
|
23
23
|
return false;
|
|
24
24
|
if (path_1.default.isAbsolute(norm))
|
|
25
|
-
norm = (0,
|
|
25
|
+
norm = (0, path_2.normalizePath)((0, read_file_1.rel)(norm, root));
|
|
26
26
|
return micromatch_1.default.isMatch(norm, patterns);
|
|
27
27
|
}
|
|
@@ -0,0 +1,63 @@
|
|
|
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
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const logger_1 = require("../diagnostics/logger");
|
|
9
|
+
const exclude_1 = require("./exclude");
|
|
10
|
+
const trace_stats_1 = require("./trace-stats");
|
|
11
|
+
const resolver_registry_1 = require("./resolver-registry");
|
|
12
|
+
async function followChain(entryFiles, cfg) {
|
|
13
|
+
const limit = cfg.resolve.maxFiles;
|
|
14
|
+
const resolverDepth = cfg.resolve.maxDepth;
|
|
15
|
+
logger_1.logger.debug("Following dependency chain...");
|
|
16
|
+
const visited = new Set();
|
|
17
|
+
const all = [];
|
|
18
|
+
const stats = (0, trace_stats_1.newStats)();
|
|
19
|
+
for (const file of entryFiles) {
|
|
20
|
+
await visitFile(file, 0);
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
files: (0, trace_stats_1.unique)(all),
|
|
24
|
+
stats,
|
|
25
|
+
};
|
|
26
|
+
async function visitFile(file, depth) {
|
|
27
|
+
if (visited.has(file))
|
|
28
|
+
return;
|
|
29
|
+
visited.add(file);
|
|
30
|
+
all.push(file);
|
|
31
|
+
if (limit && all.length >= limit) {
|
|
32
|
+
logger_1.logger.warn("File limit reached:", limit);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (depth >= resolverDepth)
|
|
36
|
+
return;
|
|
37
|
+
const ext = path_1.default.extname(file);
|
|
38
|
+
if (!(0, resolver_registry_1.hasResolver)(ext))
|
|
39
|
+
return;
|
|
40
|
+
const resolver = (0, resolver_registry_1.getResolver)(ext);
|
|
41
|
+
if (!resolver)
|
|
42
|
+
return;
|
|
43
|
+
const params = { cfg, filePath: file };
|
|
44
|
+
let result = null;
|
|
45
|
+
try {
|
|
46
|
+
result = await resolver(params);
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
logger_1.logger.warn(`Resolver failed for ${file}:`, err.message || err);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (!result)
|
|
53
|
+
return;
|
|
54
|
+
(0, trace_stats_1.mergeStats)(stats, result.stats);
|
|
55
|
+
for (const resolvedFile of result.files) {
|
|
56
|
+
if ((0, exclude_1.isExcluded)(resolvedFile, cfg.exclude, cfg.root))
|
|
57
|
+
continue;
|
|
58
|
+
if (limit && all.length >= limit)
|
|
59
|
+
return;
|
|
60
|
+
await visitFile(resolvedFile, depth + 1);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
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.applyIncludes = applyIncludes;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const glob_scan_1 = require("../filesystem/glob-scan");
|
|
10
|
+
const path_2 = require("../filesystem/path");
|
|
11
|
+
const trace_stats_1 = require("./trace-stats");
|
|
12
|
+
async function applyIncludes(cfg, files) {
|
|
13
|
+
const { include, root } = cfg;
|
|
14
|
+
const absoluteFiles = [];
|
|
15
|
+
const patterns = [];
|
|
16
|
+
for (const raw of include) {
|
|
17
|
+
const candidate = String(raw ?? "").trim();
|
|
18
|
+
if (!candidate)
|
|
19
|
+
continue;
|
|
20
|
+
const normalized = (0, path_2.normalizePath)(candidate);
|
|
21
|
+
if (path_1.default.isAbsolute(normalized)) {
|
|
22
|
+
try {
|
|
23
|
+
if (fs_1.default.statSync(normalized).isFile()) {
|
|
24
|
+
absoluteFiles.push(path_1.default.resolve(normalized));
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
// Treat unreadable absolute paths as glob patterns so include handling stays consistent.
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
patterns.push(normalized);
|
|
33
|
+
}
|
|
34
|
+
const scan = await (0, glob_scan_1.globScan)(patterns, { cwd: root });
|
|
35
|
+
return (0, trace_stats_1.unique)([...files, ...absoluteFiles, ...scan.files]);
|
|
36
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ResolverParams, ResolverResult } from "../types";
|
|
2
|
+
type Resolver = (params: ResolverParams) => Promise<ResolverResult>;
|
|
3
|
+
export declare function hasResolver(extension: string): boolean;
|
|
4
|
+
export declare function getResolver(extension: string): Resolver | undefined;
|
|
5
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.hasResolver = hasResolver;
|
|
4
|
+
exports.getResolver = getResolver;
|
|
5
|
+
const resolver_constants_1 = require("../resolvers/resolver-constants");
|
|
6
|
+
const js_resolver_1 = require("../resolvers/js/js-resolver");
|
|
7
|
+
const php_resolver_1 = require("../resolvers/php/php-resolver");
|
|
8
|
+
const RESOLVERS = {
|
|
9
|
+
".php": php_resolver_1.resolvePhpImports,
|
|
10
|
+
".ts": js_resolver_1.resolveJsImports,
|
|
11
|
+
".tsx": js_resolver_1.resolveJsImports,
|
|
12
|
+
".d.ts": js_resolver_1.resolveJsImports,
|
|
13
|
+
".js": js_resolver_1.resolveJsImports,
|
|
14
|
+
};
|
|
15
|
+
function hasResolver(extension) {
|
|
16
|
+
return resolver_constants_1.CODE_EXTS.includes(extension) && !!RESOLVERS[extension];
|
|
17
|
+
}
|
|
18
|
+
function getResolver(extension) {
|
|
19
|
+
return RESOLVERS[extension];
|
|
20
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runTrace = runTrace;
|
|
4
|
+
const follow_chain_1 = require("./follow-chain");
|
|
5
|
+
const include_files_1 = require("./include-files");
|
|
6
|
+
const naming_1 = require("../output/naming");
|
|
7
|
+
const produce_output_1 = require("../output/produce-output");
|
|
8
|
+
async function runTrace({ cfg, opts }) {
|
|
9
|
+
const entries = opts.entries ?? [];
|
|
10
|
+
const result = entries.length ? await (0, follow_chain_1.followChain)(entries, cfg) : undefined;
|
|
11
|
+
const files = await (0, include_files_1.applyIncludes)(cfg, result?.files ?? []);
|
|
12
|
+
if (!files.length) {
|
|
13
|
+
return { entries, files: [], stats: result?.stats };
|
|
14
|
+
}
|
|
15
|
+
const outputPath = await (0, produce_output_1.produceOutput)({
|
|
16
|
+
name: opts.outputName ?? (0, naming_1.smartNaming)(entries),
|
|
17
|
+
files,
|
|
18
|
+
cfg,
|
|
19
|
+
});
|
|
20
|
+
return { outputPath, entries, files, stats: result?.stats };
|
|
21
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.newStats = newStats;
|
|
4
|
+
exports.mergeStats = mergeStats;
|
|
5
|
+
exports.unique = unique;
|
|
6
|
+
function newStats() {
|
|
7
|
+
return { expected: new Set(), resolved: new Set() };
|
|
8
|
+
}
|
|
9
|
+
function mergeStats(target, src) {
|
|
10
|
+
src.expected.forEach((item) => target.expected.add(item));
|
|
11
|
+
src.resolved.forEach((item) => target.resolved.add(item));
|
|
12
|
+
return target;
|
|
13
|
+
}
|
|
14
|
+
function unique(arr) {
|
|
15
|
+
return [...new Set(arr)];
|
|
16
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { MigrationCommandResult } from "../config/migration";
|
|
2
|
+
import type { ProdexFlags } from "./cli.types";
|
|
3
|
+
import type { ProdexConfig } from "./config.types";
|
|
4
|
+
import type { ChainResult } from "./tracing.types";
|
|
5
|
+
export type CliCommand = {
|
|
6
|
+
kind: "run";
|
|
7
|
+
rootArg?: string;
|
|
8
|
+
flags: Partial<ProdexFlags>;
|
|
9
|
+
} | {
|
|
10
|
+
kind: "init";
|
|
11
|
+
rootArg?: string;
|
|
12
|
+
force?: boolean;
|
|
13
|
+
} | {
|
|
14
|
+
kind: "profiles";
|
|
15
|
+
rootArg?: string;
|
|
16
|
+
} | {
|
|
17
|
+
kind: "migrate";
|
|
18
|
+
rootArg?: string;
|
|
19
|
+
write?: boolean;
|
|
20
|
+
check?: boolean;
|
|
21
|
+
} | {
|
|
22
|
+
kind: "help";
|
|
23
|
+
topic?: string;
|
|
24
|
+
} | {
|
|
25
|
+
kind: "version";
|
|
26
|
+
};
|
|
27
|
+
export interface CliParseResult {
|
|
28
|
+
command?: CliCommand;
|
|
29
|
+
warnings: string[];
|
|
30
|
+
errors: string[];
|
|
31
|
+
}
|
|
32
|
+
export interface RunPlan {
|
|
33
|
+
root: string;
|
|
34
|
+
config: ProdexConfig;
|
|
35
|
+
flags: Partial<ProdexFlags>;
|
|
36
|
+
outputName?: string;
|
|
37
|
+
profile?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface RunResult {
|
|
40
|
+
ok: boolean;
|
|
41
|
+
root: string;
|
|
42
|
+
mode: "trace" | "include-only" | "mixed";
|
|
43
|
+
outputPath?: string;
|
|
44
|
+
outputName?: string;
|
|
45
|
+
entries: string[];
|
|
46
|
+
includes: string[];
|
|
47
|
+
files: string[];
|
|
48
|
+
stats?: ChainResult["stats"];
|
|
49
|
+
warnings: string[];
|
|
50
|
+
errors: string[];
|
|
51
|
+
profile?: string;
|
|
52
|
+
}
|
|
53
|
+
export interface CommandResult {
|
|
54
|
+
ok: boolean;
|
|
55
|
+
exitCode: number;
|
|
56
|
+
message?: string;
|
|
57
|
+
profiles?: string[];
|
|
58
|
+
migration?: MigrationCommandResult;
|
|
59
|
+
warnings: string[];
|
|
60
|
+
errors: string[];
|
|
61
|
+
runs: RunResult[];
|
|
62
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface ProdexFlags {
|
|
2
|
+
/** Entry globs or file paths. Repeatable and comma-aware. */
|
|
3
|
+
entry?: string[];
|
|
4
|
+
/** Extra files or globs appended without dependency resolution. */
|
|
5
|
+
include?: string[];
|
|
6
|
+
/** Files or globs to skip during traversal. */
|
|
7
|
+
exclude?: string[];
|
|
8
|
+
/** Output format override. */
|
|
9
|
+
format?: "md" | "txt";
|
|
10
|
+
/** Output basename override for this run. */
|
|
11
|
+
name?: string | null;
|
|
12
|
+
/** Maximum dependency traversal depth. */
|
|
13
|
+
maxDepth?: number | null;
|
|
14
|
+
/** Maximum number of files to trace. */
|
|
15
|
+
maxFiles?: number | null;
|
|
16
|
+
/** Enable debug logs. */
|
|
17
|
+
debug?: boolean;
|
|
18
|
+
/** Named profiles to run, in user-provided order. */
|
|
19
|
+
profiles?: string[];
|
|
20
|
+
/** Run all configured profiles. */
|
|
21
|
+
allProfiles?: boolean;
|
|
22
|
+
}
|
package/dist/types/cli.types.js
CHANGED
|
@@ -1,12 +1,2 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* CLI flag schema for Prodex.
|
|
4
|
-
* Mirrors the current CLI synopsis:
|
|
5
|
-
*
|
|
6
|
-
* prodex [entries...] [-tcdv]
|
|
7
|
-
* [--txt] [--ci] [--debug] [--verbose]
|
|
8
|
-
* [--name=<string>|-n=<string>]
|
|
9
|
-
* [--limit=<int>|-l=<int>]
|
|
10
|
-
* [--inc=<globs>] [--exc=<globs>]
|
|
11
|
-
*/
|
|
12
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export interface ProdexConfig extends ProdexBase {
|
|
2
|
+
root: string;
|
|
3
|
+
name?: string;
|
|
4
|
+
}
|
|
5
|
+
export type ProdexConfigFile = DeepPartial<ProdexBase> & {
|
|
6
|
+
$schema: string;
|
|
7
|
+
version: number;
|
|
8
|
+
};
|
|
9
|
+
export type DeepPartial<T> = {
|
|
10
|
+
[K in keyof T]?: T[K] extends Array<infer Item> ? Item[] : T[K] extends object ? DeepPartial<T[K]> : T[K];
|
|
11
|
+
};
|
|
12
|
+
export type ProdexProfile = {
|
|
13
|
+
name?: string;
|
|
14
|
+
entry?: string[];
|
|
15
|
+
include?: string[];
|
|
16
|
+
exclude?: string[];
|
|
17
|
+
};
|
|
18
|
+
interface ProdexBase {
|
|
19
|
+
output: {
|
|
20
|
+
dir: string;
|
|
21
|
+
versioned: boolean;
|
|
22
|
+
format: "md" | "txt";
|
|
23
|
+
};
|
|
24
|
+
entry: string[];
|
|
25
|
+
include: string[];
|
|
26
|
+
exclude: string[];
|
|
27
|
+
resolve: {
|
|
28
|
+
aliases: Record<string, string>;
|
|
29
|
+
maxDepth: number;
|
|
30
|
+
maxFiles: number;
|
|
31
|
+
};
|
|
32
|
+
profiles: Record<string, ProdexProfile>;
|
|
33
|
+
}
|
|
34
|
+
export {};
|