prodex 1.3.0 → 1.4.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/README.md +234 -234
- package/dist/cli/cli-input.js +20 -26
- package/dist/cli/init.js +4 -5
- package/dist/cli/picker.js +8 -7
- package/dist/cli/summary.js +15 -9
- package/dist/constants/cache-keys.js +11 -0
- package/dist/constants/config.js +6 -5
- package/dist/constants/flags.js +73 -0
- package/dist/constants/index.js +20 -0
- package/dist/constants/render-constants.js +0 -4
- package/dist/core/combine.js +31 -13
- package/dist/core/dependency.js +39 -19
- package/dist/core/helpers.js +42 -38
- package/dist/core/managers/cache.js +53 -0
- package/dist/core/managers/config.js +103 -0
- package/dist/core/renderers.js +9 -8
- package/dist/debug.js +13 -0
- package/dist/index.js +42 -13
- package/dist/lib/logger.js +37 -9
- package/dist/lib/polyfills.js +0 -10
- package/dist/lib/utils.js +0 -13
- package/dist/{core/parsers → resolvers/js}/extract-imports.js +1 -7
- package/dist/resolvers/js/js-resolver.js +92 -116
- package/dist/resolvers/js/resolve-alias.js +57 -0
- package/dist/resolvers/php/bindings.js +20 -9
- package/dist/resolvers/php/extract-imports.js +49 -0
- package/dist/resolvers/php/php-resolver.js +98 -59
- package/dist/resolvers/php/psr4.js +18 -5
- package/dist/shared/collections.js +33 -0
- package/dist/shared/index.js +19 -0
- package/dist/shared/io.js +51 -0
- package/dist/shared/patterns.js +29 -0
- package/dist/store.js +15 -0
- package/package.json +5 -4
- package/dist/cli/flags.js +0 -42
- package/dist/constants/config-loader.js +0 -95
- package/dist/core/file-utils.js +0 -41
- package/dist/resolvers/js/alias-loader.js +0 -52
- package/dist/resolvers/php/patterns.js +0 -17
- package/dist/resolvers/shared/excludes.js +0 -11
- package/dist/resolvers/shared/file-cache.js +0 -29
- package/dist/resolvers/shared/stats.js +0 -17
package/dist/debug.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
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
|
+
(async () => {
|
|
8
|
+
const mockArgs = ["node", "prodex", "C:\\Users\\USER\\Herd\\fireshot", "-f", "**/(dashboard|accounts).tsx", "-cd"];
|
|
9
|
+
process.argv = mockArgs;
|
|
10
|
+
console.log("🧩 Debug runner starting...");
|
|
11
|
+
await (0, index_1.default)();
|
|
12
|
+
console.log("🧩 Debug runner done.");
|
|
13
|
+
})();
|
package/dist/index.js
CHANGED
|
@@ -1,26 +1,55 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
36
|
exports.default = startProdex;
|
|
4
|
-
const combine_1 = require("./core/combine");
|
|
5
37
|
const init_1 = require("./cli/init");
|
|
6
38
|
const cli_input_1 = require("./cli/cli-input");
|
|
7
|
-
const
|
|
8
|
-
require("./
|
|
9
|
-
const
|
|
10
|
-
async function startProdex() {
|
|
11
|
-
|
|
12
|
-
// Handle init mode
|
|
13
|
-
if (args.includes("init")) {
|
|
39
|
+
const config_1 = require("./core/managers/config");
|
|
40
|
+
const store_1 = require("./store");
|
|
41
|
+
const combine_1 = require("./core/combine");
|
|
42
|
+
async function startProdex(args = process.argv) {
|
|
43
|
+
if (args.includes("init"))
|
|
14
44
|
return (0, init_1.initProdex)();
|
|
15
|
-
}
|
|
16
|
-
// Parse CLI input
|
|
17
45
|
const { root, flags } = (0, cli_input_1.parseCliInput)(args);
|
|
18
|
-
|
|
19
|
-
const config =
|
|
20
|
-
(0,
|
|
46
|
+
const userConfig = config_1.ConfigManager.load(root);
|
|
47
|
+
const config = config_1.ConfigManager.merge(userConfig, flags, root);
|
|
48
|
+
(0, store_1.setGlobals)(config, flags);
|
|
21
49
|
const opts = {
|
|
22
50
|
showUi: !flags.ci && !flags?.files?.length && !config?.entry?.ui?.enablePicker,
|
|
23
51
|
cliName: config.name,
|
|
24
52
|
};
|
|
53
|
+
await Promise.resolve().then(() => __importStar(require("./lib/polyfills")));
|
|
25
54
|
await (0, combine_1.runCombine)({ cfg: config, opts });
|
|
26
55
|
}
|
package/dist/lib/logger.js
CHANGED
|
@@ -1,14 +1,42 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.logger = void 0;
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
+
}
|
|
8
15
|
exports.logger = {
|
|
9
|
-
debug: (...
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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(),
|
|
14
42
|
};
|
package/dist/lib/polyfills.js
CHANGED
|
@@ -15,13 +15,3 @@ if (!String.prototype.clean) {
|
|
|
15
15
|
};
|
|
16
16
|
}
|
|
17
17
|
globalThis._2j = (obj) => util_1.default.inspect(obj, { colors: true, depth: null, breakLength: 150, compact: 3 });
|
|
18
|
-
globalThis._bpt = function (param) {
|
|
19
|
-
if (process.env.PRODEX_DEBUG !== "1")
|
|
20
|
-
return;
|
|
21
|
-
console.log("⭕ BREAKPOINT");
|
|
22
|
-
if (typeof param === "function")
|
|
23
|
-
param();
|
|
24
|
-
else
|
|
25
|
-
console.log(_2j(param));
|
|
26
|
-
process.exit(1);
|
|
27
|
-
};
|
package/dist/lib/utils.js
CHANGED
|
@@ -1,21 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// @ts-nocheck
|
|
3
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.unique = unique;
|
|
5
|
-
exports.setDiff = setDiff;
|
|
6
|
-
exports.toArray = toArray;
|
|
7
3
|
exports.shortTimestamp = shortTimestamp;
|
|
8
4
|
exports.normalizePatterns = normalizePatterns;
|
|
9
5
|
const config_1 = require("../constants/config");
|
|
10
|
-
function unique(arr) {
|
|
11
|
-
return [...new Set(arr)];
|
|
12
|
-
}
|
|
13
|
-
function setDiff(A, B) {
|
|
14
|
-
return new Set([...A].filter((x) => !B.has(x)));
|
|
15
|
-
}
|
|
16
|
-
function toArray(v) {
|
|
17
|
-
return Array.isArray(v) ? v : [v];
|
|
18
|
-
}
|
|
19
6
|
/** Compact YYMMDD-HHmm timestamp for versioned filenames. */
|
|
20
7
|
function shortTimestamp() {
|
|
21
8
|
const d = new Date();
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// @ts-nocheck
|
|
3
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
4
|
};
|
|
@@ -35,12 +34,7 @@ async function extractImports(filePath, code) {
|
|
|
35
34
|
}
|
|
36
35
|
}
|
|
37
36
|
function fallbackRegex(code) {
|
|
38
|
-
const patterns = [
|
|
39
|
-
/import\s+[^'"]*['"]([^'"]+)['"]/g,
|
|
40
|
-
/import\(\s*['"]([^'"]+)['"]\s*\)/g,
|
|
41
|
-
/require\(\s*['"]([^'"]+)['"]\s*\)/g,
|
|
42
|
-
/export\s+\*\s+from\s+['"]([^'"]+)['"]/g,
|
|
43
|
-
];
|
|
37
|
+
const patterns = [/import\s+[^'"]*['"]([^'"]+)['"]/g, /import\(\s*['"]([^'"]+)['"]\s*\)/g, /require\(\s*['"]([^'"]+)['"]\s*\)/g, /export\s+\*\s+from\s+['"]([^'"]+)['"]/g];
|
|
44
38
|
const matches = new Set();
|
|
45
39
|
for (const r of patterns) {
|
|
46
40
|
let m;
|
|
@@ -1,153 +1,129 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// @ts-nocheck
|
|
3
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
4
|
};
|
|
6
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
6
|
exports.resolveJsImports = resolveJsImports;
|
|
8
|
-
const promises_1 = __importDefault(require("fs/promises"));
|
|
9
7
|
const path_1 = __importDefault(require("path"));
|
|
10
|
-
const
|
|
11
|
-
const extract_imports_1 = require("../../core/parsers/extract-imports");
|
|
12
|
-
const alias_loader_1 = require("./alias-loader");
|
|
8
|
+
const extract_imports_1 = require("./extract-imports");
|
|
13
9
|
const config_1 = require("../../constants/config");
|
|
14
|
-
const
|
|
10
|
+
const collections_1 = require("../../shared/collections");
|
|
15
11
|
const logger_1 = require("../../lib/logger");
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
|
|
12
|
+
const store_1 = require("../../store");
|
|
13
|
+
const resolve_alias_1 = require("./resolve-alias"); // alias: config + cache + fast-glob
|
|
14
|
+
const cache_1 = require("../../core/managers/cache");
|
|
15
|
+
const cache_keys_1 = require("../../constants/cache-keys");
|
|
16
|
+
const shared_1 = require("../../shared");
|
|
17
|
+
const shared_2 = require("../../shared");
|
|
18
|
+
const { JS_STATS, JS_IMPORTS } = cache_keys_1.CACHE_KEYS;
|
|
19
|
+
async function resolveJsImports({ filePath, visited = new Set(), depth = 0, maxDepth }) {
|
|
20
|
+
const limitDepth = maxDepth;
|
|
21
|
+
if (depth >= limitDepth)
|
|
22
|
+
return (0, collections_1.emptyResult)(visited);
|
|
26
23
|
if (visited.has(filePath))
|
|
27
|
-
return
|
|
24
|
+
return (0, collections_1.emptyResult)(visited);
|
|
28
25
|
visited.add(filePath);
|
|
26
|
+
const { root: ROOT, resolve: { exclude: excludePatterns }, } = (0, store_1.getConfig)();
|
|
29
27
|
const ext = path_1.default.extname(filePath).toLowerCase();
|
|
30
28
|
const isDts = ext === config_1.DTS_EXT;
|
|
31
29
|
if (!config_1.BASE_EXTS.includes(ext) && !isDts)
|
|
32
|
-
return
|
|
33
|
-
let code;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
ctx.aliases = { ...(0, alias_loader_1.loadProjectAliases)(ROOT), ...(resolveCfg.aliases || {}) };
|
|
42
|
-
}
|
|
43
|
-
const aliases = ctx.aliases;
|
|
44
|
-
const matches = await getImportsCached(filePath, code);
|
|
45
|
-
if (!matches.size)
|
|
46
|
-
return empty(visited);
|
|
47
|
-
const filesOut = [];
|
|
30
|
+
return (0, collections_1.emptyResult)(visited);
|
|
31
|
+
let code = (0, shared_1.readFileSafe)(filePath);
|
|
32
|
+
if (!code)
|
|
33
|
+
return (0, collections_1.emptyResult)(visited);
|
|
34
|
+
// Extract imports ---------------------------------------
|
|
35
|
+
const imports = await getImportsCached(filePath, code);
|
|
36
|
+
if (!imports.size)
|
|
37
|
+
return (0, collections_1.emptyResult)(visited);
|
|
38
|
+
// Trackers ----------------------------------------------
|
|
48
39
|
const expected = new Set();
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
40
|
+
const resolved = new Set();
|
|
41
|
+
const files = [];
|
|
42
|
+
// Main resolution loop ----------------------------------
|
|
43
|
+
for (const imp of imports) {
|
|
44
|
+
// skip bare packages (react, lodash, etc.)
|
|
45
|
+
if (!imp.startsWith(".") && !imp.startsWith("/") && !imp.startsWith("@"))
|
|
53
46
|
continue;
|
|
54
|
-
|
|
55
|
-
// Apply single exclude matcher to the RAW specifier
|
|
56
|
-
if (isExcluded(imp))
|
|
47
|
+
if ((0, shared_1.isExcluded)(imp, excludePatterns))
|
|
57
48
|
continue;
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
49
|
+
let base = null;
|
|
50
|
+
if (imp.startsWith(".")) {
|
|
51
|
+
// relative → like original resolver
|
|
52
|
+
base = path_1.default.resolve(path_1.default.dirname(filePath), imp);
|
|
53
|
+
}
|
|
54
|
+
else if (imp.startsWith("/")) {
|
|
55
|
+
// absolute path import → like original resolver
|
|
56
|
+
base = path_1.default.resolve(imp);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
// alias (@...) → unified resolver (config + cache + glob)
|
|
60
|
+
base = await (0, resolve_alias_1.resolveAliasPath)(imp, ROOT, (0, store_1.getConfig)());
|
|
61
|
+
}
|
|
62
|
+
if (!base)
|
|
62
63
|
continue;
|
|
63
|
-
const
|
|
64
|
+
const absBase = path_1.default.resolve(base);
|
|
65
|
+
expected.add(absBase);
|
|
66
|
+
const resolvedPath = await tryResolveImport(absBase);
|
|
64
67
|
if (!resolvedPath)
|
|
65
68
|
continue;
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
//
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
for (const
|
|
77
|
-
expected.add(
|
|
69
|
+
resolved.add(absBase);
|
|
70
|
+
files.push(resolvedPath);
|
|
71
|
+
// Recursive traversal
|
|
72
|
+
const sub = await resolveJsImports({
|
|
73
|
+
filePath: resolvedPath,
|
|
74
|
+
visited,
|
|
75
|
+
depth: depth + 1,
|
|
76
|
+
maxDepth: limitDepth,
|
|
77
|
+
});
|
|
78
|
+
files.push(...sub.files);
|
|
79
|
+
for (const e of sub.stats.expected)
|
|
80
|
+
expected.add(e);
|
|
78
81
|
for (const r of sub.stats.resolved)
|
|
79
|
-
|
|
82
|
+
resolved.add(r);
|
|
80
83
|
}
|
|
81
|
-
const uniqueFiles =
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
logger_1.logger.debug([...diff], "🔴THE diff");
|
|
88
|
-
return { files: uniqueFiles, visited, stats: { expected, resolved: resolvedSet } };
|
|
89
|
-
}
|
|
90
|
-
// ---------- helpers ----------
|
|
91
|
-
function startsWithAnyAlias(imp, aliases) {
|
|
92
|
-
return Object.keys(aliases).some((a) => imp === a || imp.startsWith(a + "/"));
|
|
84
|
+
const uniqueFiles = (0, collections_1.unique)(files);
|
|
85
|
+
const diff = (0, shared_2.setDiff)(expected, resolved);
|
|
86
|
+
logger_1.logger.debug(`🪶 [js-resolver] ${filePath} → expected: ${expected.size}, resolved: ${resolved.size}`);
|
|
87
|
+
if (diff.size)
|
|
88
|
+
logger_1.logger.debug([...diff], "🔴 THE diff");
|
|
89
|
+
return { files: uniqueFiles, visited, stats: { expected, resolved } };
|
|
93
90
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
.sort((a, b) => b.length - a.length)[0];
|
|
99
|
-
if (!key)
|
|
100
|
-
return null;
|
|
101
|
-
const relPart = specifier.slice(key.length).replace(/^\/+/, "");
|
|
102
|
-
return path_1.default.resolve(aliases[key], relPart);
|
|
103
|
-
}
|
|
104
|
-
if (specifier.startsWith(".")) {
|
|
105
|
-
return path_1.default.resolve(path_1.default.dirname(fromFile), specifier);
|
|
106
|
-
}
|
|
107
|
-
if (specifier.startsWith("/")) {
|
|
108
|
-
return path_1.default.resolve(specifier);
|
|
109
|
-
}
|
|
110
|
-
return null;
|
|
111
|
-
}
|
|
112
|
-
async function tryResolveImport(basePath, ROOT) {
|
|
91
|
+
// ---------------------------------------------------------
|
|
92
|
+
// tryResolveImport (pure)
|
|
93
|
+
// ---------------------------------------------------------
|
|
94
|
+
async function tryResolveImport(basePath) {
|
|
113
95
|
const candidates = [];
|
|
114
|
-
|
|
96
|
+
const ext = path_1.default.extname(basePath).toLowerCase();
|
|
97
|
+
if (ext && config_1.REAL_EXTS.has(ext)) {
|
|
115
98
|
candidates.push(basePath);
|
|
116
99
|
}
|
|
117
100
|
else {
|
|
118
|
-
for (const
|
|
119
|
-
candidates.push(basePath +
|
|
120
|
-
candidates.push(path_1.default.join(basePath, "index" +
|
|
101
|
+
for (const e of [...config_1.BASE_EXTS, config_1.DTS_EXT]) {
|
|
102
|
+
candidates.push(basePath + e);
|
|
103
|
+
candidates.push(path_1.default.join(basePath, "index" + e));
|
|
121
104
|
}
|
|
122
105
|
}
|
|
123
|
-
|
|
106
|
+
// Run all stat checks in parallel
|
|
107
|
+
const results = await Promise.allSettled(candidates.map(async (c) => {
|
|
124
108
|
const abs = path_1.default.resolve(c);
|
|
125
|
-
const st = await
|
|
126
|
-
|
|
127
|
-
|
|
109
|
+
const st = await (0, shared_1.safeStatCached)(JS_STATS, abs);
|
|
110
|
+
return st && st.isFile() ? abs : null;
|
|
111
|
+
}));
|
|
112
|
+
// Find the first fulfilled non-null result
|
|
113
|
+
for (const r of results) {
|
|
114
|
+
if (r.status === "fulfilled" && r.value)
|
|
115
|
+
return r.value;
|
|
128
116
|
}
|
|
129
117
|
return null;
|
|
130
118
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
try {
|
|
135
|
-
const st = await promises_1.default.stat(p);
|
|
136
|
-
STAT_CACHE.set(p, st);
|
|
137
|
-
return st;
|
|
138
|
-
}
|
|
139
|
-
catch {
|
|
140
|
-
STAT_CACHE.set(p, null);
|
|
141
|
-
return null;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
119
|
+
// ---------------------------------------------------------
|
|
120
|
+
// Cached stat + import scanners
|
|
121
|
+
// ---------------------------------------------------------
|
|
144
122
|
async function getImportsCached(filePath, code) {
|
|
145
|
-
|
|
146
|
-
|
|
123
|
+
const cached = cache_1.CacheManager.get(JS_IMPORTS, filePath);
|
|
124
|
+
if (cached)
|
|
125
|
+
return cached;
|
|
147
126
|
const set = await (0, extract_imports_1.extractImports)(filePath, code);
|
|
148
|
-
|
|
127
|
+
cache_1.CacheManager.set(JS_IMPORTS, filePath, set);
|
|
149
128
|
return set;
|
|
150
129
|
}
|
|
151
|
-
function empty(visited) {
|
|
152
|
-
return { files: [], visited, stats: { expected: new Set(), resolved: new Set() } };
|
|
153
|
-
}
|
|
@@ -0,0 +1,57 @@
|
|
|
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.resolveAliasPath = resolveAliasPath;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const cache_1 = require("../../core/managers/cache");
|
|
9
|
+
const constants_1 = require("../../constants");
|
|
10
|
+
const helpers_1 = require("../../core/helpers");
|
|
11
|
+
/**
|
|
12
|
+
* 🧩 resolveAliasPath()
|
|
13
|
+
* Unifies alias lookup across config, cache, and fallback discovery.
|
|
14
|
+
*
|
|
15
|
+
* - Checks cfg.resolve.aliases first.
|
|
16
|
+
* - Then cached aliases (from Cache Manager).
|
|
17
|
+
* - If still unresolved, runs Fast-Glob to discover and cache new alias root.
|
|
18
|
+
*/
|
|
19
|
+
async function resolveAliasPath(specifier, root, cfg) {
|
|
20
|
+
if (!specifier.includes("/"))
|
|
21
|
+
return null;
|
|
22
|
+
const [aliasName, ...rest] = specifier.split("/");
|
|
23
|
+
const remainder = rest.join("/");
|
|
24
|
+
const knownAliases = cfg.resolve.aliases || {};
|
|
25
|
+
const aliasKey = aliasName.startsWith("@") ? aliasName : `@${aliasName}`;
|
|
26
|
+
// 1️⃣ Check config-defined aliases
|
|
27
|
+
if (knownAliases[aliasKey]) {
|
|
28
|
+
const relPart = remainder.replace(/^\/+/, "");
|
|
29
|
+
return path_1.default.resolve(root, knownAliases[aliasKey], relPart);
|
|
30
|
+
}
|
|
31
|
+
// 2️⃣ Check cached aliases
|
|
32
|
+
const cached = cache_1.CacheManager.get(constants_1.CACHE_KEYS.ALIASES, aliasKey);
|
|
33
|
+
if (cached) {
|
|
34
|
+
const relPart = remainder.replace(/^\/+/, "");
|
|
35
|
+
return path_1.default.resolve(root, cached, relPart);
|
|
36
|
+
}
|
|
37
|
+
// 3️⃣ Fallback discovery with Fast-Glob
|
|
38
|
+
const stripped = remainder; // remove prefix before first '/'
|
|
39
|
+
const hasExt = /\.[a-z0-9]+$/i.test(stripped);
|
|
40
|
+
const patterns = hasExt ? [`**/${stripped}`] : [`**/${stripped}.*`, `**/${stripped}/index.*`];
|
|
41
|
+
const { files: matches } = await (0, helpers_1.globScan)(patterns, { cwd: root });
|
|
42
|
+
if (matches.length === 1) {
|
|
43
|
+
return resolveMatches(matches, remainder, aliasKey);
|
|
44
|
+
}
|
|
45
|
+
//There are multiple matches, Assuming they match the target approximate folder.
|
|
46
|
+
if (matches.length > 1) {
|
|
47
|
+
const resolvedMatch = resolveMatches(matches, remainder, aliasKey);
|
|
48
|
+
return resolvedMatch.replace(/\.[^/.]+$/, "");
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
function resolveMatches(matches, remainder, aliasKey) {
|
|
53
|
+
const foundFile = matches[0];
|
|
54
|
+
const aliasRoot = foundFile.split(remainder)[0].replace(/\\/g, "/");
|
|
55
|
+
cache_1.CacheManager.set(constants_1.CACHE_KEYS.ALIASES, aliasKey, aliasRoot);
|
|
56
|
+
return foundFile;
|
|
57
|
+
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// @ts-nocheck
|
|
3
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
4
|
};
|
|
@@ -7,18 +6,29 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
7
6
|
exports.loadLaravelBindings = loadLaravelBindings;
|
|
8
7
|
const fs_1 = __importDefault(require("fs"));
|
|
9
8
|
const path_1 = __importDefault(require("path"));
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
const cache_1 = require("../../core/managers/cache");
|
|
10
|
+
const cache_keys_1 = require("../../constants/cache-keys");
|
|
11
|
+
/**
|
|
12
|
+
* Scans app/Providers/*.php for `$this->app->bind()` / `singleton()` calls
|
|
13
|
+
* and returns a map of Interface::class → Implementation::class (FQCN strings).
|
|
14
|
+
*/
|
|
15
|
+
function loadLaravelBindings(root) {
|
|
16
|
+
const cached = cache_1.CacheManager.get(cache_keys_1.CACHE_KEYS.PHP_BINDINGS, root);
|
|
17
|
+
if (cached)
|
|
18
|
+
return cached;
|
|
19
|
+
const providersDir = path_1.default.join(root, "app", "Providers");
|
|
13
20
|
const bindings = {};
|
|
14
|
-
if (!fs_1.default.existsSync(providersDir))
|
|
21
|
+
if (!fs_1.default.existsSync(providersDir)) {
|
|
22
|
+
cache_1.CacheManager.set(cache_keys_1.CACHE_KEYS.PHP_BINDINGS, root, bindings);
|
|
15
23
|
return bindings;
|
|
24
|
+
}
|
|
16
25
|
const files = fs_1.default
|
|
17
26
|
.readdirSync(providersDir)
|
|
18
|
-
.filter(f => f.endsWith(".php"))
|
|
19
|
-
.map(f => path_1.default.join(providersDir, f));
|
|
20
|
-
//
|
|
21
|
-
|
|
27
|
+
.filter((f) => f.endsWith(".php"))
|
|
28
|
+
.map((f) => path_1.default.join(providersDir, f));
|
|
29
|
+
// $this->app->bind(Interface::class, Implementation::class)
|
|
30
|
+
// $this->app->singleton(Interface::class, Implementation::class)
|
|
31
|
+
const re = /\$this->app->(?:bind|singleton)\s*\(\s*([A-Za-z0-9_:\\\\]+)::class\s*,\s*([A-Za-z0-9_:\\\\]+)::class/g;
|
|
22
32
|
for (const file of files) {
|
|
23
33
|
const code = fs_1.default.readFileSync(file, "utf8");
|
|
24
34
|
let m;
|
|
@@ -28,5 +38,6 @@ function loadLaravelBindings() {
|
|
|
28
38
|
bindings[iface] = impl;
|
|
29
39
|
}
|
|
30
40
|
}
|
|
41
|
+
cache_1.CacheManager.set(cache_keys_1.CACHE_KEYS.PHP_BINDINGS, root, bindings);
|
|
31
42
|
return bindings;
|
|
32
43
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractPhpImports = extractPhpImports;
|
|
4
|
+
exports.expandGroupedUses = expandGroupedUses;
|
|
5
|
+
/**
|
|
6
|
+
* Extracts import-like references from PHP code.
|
|
7
|
+
* Supports:
|
|
8
|
+
* - require/include/require_once/include_once
|
|
9
|
+
* - use statements (including grouped imports like `use App\Models\{User, Team};`)
|
|
10
|
+
*/
|
|
11
|
+
function extractPhpImports(code) {
|
|
12
|
+
const out = new Set();
|
|
13
|
+
const patterns = [
|
|
14
|
+
/\b(?:require|include|require_once|include_once)\s*\(?['"]([^'"]+)['"]\)?/g,
|
|
15
|
+
/\buse\s+([A-Z][\w\\]+(?:\s*{[^}]+})?)/g,
|
|
16
|
+
];
|
|
17
|
+
for (const r of patterns) {
|
|
18
|
+
let m;
|
|
19
|
+
while ((m = r.exec(code))) {
|
|
20
|
+
const val = m[1];
|
|
21
|
+
if (val)
|
|
22
|
+
out.add(val);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return out;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Expands grouped `use` imports into individual fully qualified names.
|
|
29
|
+
* Example:
|
|
30
|
+
* "App\\Models\\{User, Team}" → ["App\\Models\\User", "App\\Models\\Team"]
|
|
31
|
+
*/
|
|
32
|
+
function expandGroupedUses(raw) {
|
|
33
|
+
const out = new Set();
|
|
34
|
+
for (const imp of raw) {
|
|
35
|
+
const g = imp.match(/^(.+?)\s*{([^}]+)}/);
|
|
36
|
+
if (g) {
|
|
37
|
+
const base = g[1].trim().replace(/\\+$/, "");
|
|
38
|
+
g[2]
|
|
39
|
+
.split(",")
|
|
40
|
+
.map((x) => x.trim())
|
|
41
|
+
.filter(Boolean)
|
|
42
|
+
.forEach((p) => out.add(`${base}\\${p}`));
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
out.add(imp.trim());
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
}
|