eminiar 0.5.1 → 0.6.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/.claude-plugin/plugin.json +1 -1
- package/README.md +2 -2
- package/dist/cli.js +1355 -206
- package/dist/hook.js +23 -6
- package/dist/server.js +1415 -266
- package/dist/ui/app.global.js +30 -30
- package/eminiar.config.schema.json +4 -2
- package/package.json +2 -1
- package/vendor/grammars/php.wasm +0 -0
package/dist/server.js
CHANGED
|
@@ -2266,8 +2266,8 @@ var require_resolve = __commonJS({
|
|
|
2266
2266
|
}
|
|
2267
2267
|
return count;
|
|
2268
2268
|
}
|
|
2269
|
-
function getFullPath(resolver, id = "",
|
|
2270
|
-
if (
|
|
2269
|
+
function getFullPath(resolver, id = "", normalize7) {
|
|
2270
|
+
if (normalize7 !== false)
|
|
2271
2271
|
id = normalizeId(id);
|
|
2272
2272
|
const p = resolver.parse(id);
|
|
2273
2273
|
return _getFullPath(resolver, p);
|
|
@@ -3019,7 +3019,7 @@ var require_compile = __commonJS({
|
|
|
3019
3019
|
const schOrFunc = root.refs[ref];
|
|
3020
3020
|
if (schOrFunc)
|
|
3021
3021
|
return schOrFunc;
|
|
3022
|
-
let _sch =
|
|
3022
|
+
let _sch = resolve8.call(this, root, ref);
|
|
3023
3023
|
if (_sch === void 0) {
|
|
3024
3024
|
const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
|
|
3025
3025
|
const { schemaId } = this.opts;
|
|
@@ -3046,7 +3046,7 @@ var require_compile = __commonJS({
|
|
|
3046
3046
|
function sameSchemaEnv(s1, s2) {
|
|
3047
3047
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
3048
3048
|
}
|
|
3049
|
-
function
|
|
3049
|
+
function resolve8(root, ref) {
|
|
3050
3050
|
let sch;
|
|
3051
3051
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
3052
3052
|
ref = sch;
|
|
@@ -3869,7 +3869,7 @@ var require_fast_uri = __commonJS({
|
|
|
3869
3869
|
}
|
|
3870
3870
|
return decodedScheme;
|
|
3871
3871
|
}
|
|
3872
|
-
function
|
|
3872
|
+
function normalize7(uri, options) {
|
|
3873
3873
|
if (typeof uri === "string") {
|
|
3874
3874
|
uri = /** @type {T} */
|
|
3875
3875
|
normalizeString(uri, options);
|
|
@@ -3879,7 +3879,7 @@ var require_fast_uri = __commonJS({
|
|
|
3879
3879
|
}
|
|
3880
3880
|
return uri;
|
|
3881
3881
|
}
|
|
3882
|
-
function
|
|
3882
|
+
function resolve8(baseURI, relativeURI, options) {
|
|
3883
3883
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3884
3884
|
const {
|
|
3885
3885
|
parsed: baseParsed,
|
|
@@ -3912,49 +3912,49 @@ var require_fast_uri = __commonJS({
|
|
|
3912
3912
|
schemelessOptions.skipEscape = true;
|
|
3913
3913
|
return serialize(resolved, schemelessOptions);
|
|
3914
3914
|
}
|
|
3915
|
-
function resolveComponent(base,
|
|
3915
|
+
function resolveComponent(base, relative9, options, skipNormalization) {
|
|
3916
3916
|
const target = {};
|
|
3917
3917
|
if (!skipNormalization) {
|
|
3918
3918
|
base = parse3(serialize(base, options), options);
|
|
3919
|
-
|
|
3919
|
+
relative9 = parse3(serialize(relative9, options), options);
|
|
3920
3920
|
}
|
|
3921
3921
|
options = options || {};
|
|
3922
|
-
if (!options.tolerant &&
|
|
3923
|
-
target.scheme =
|
|
3924
|
-
target.userinfo =
|
|
3925
|
-
target.host =
|
|
3926
|
-
target.port =
|
|
3927
|
-
target.path = removeDotSegments(
|
|
3928
|
-
target.query =
|
|
3922
|
+
if (!options.tolerant && relative9.scheme) {
|
|
3923
|
+
target.scheme = relative9.scheme;
|
|
3924
|
+
target.userinfo = relative9.userinfo;
|
|
3925
|
+
target.host = relative9.host;
|
|
3926
|
+
target.port = relative9.port;
|
|
3927
|
+
target.path = removeDotSegments(relative9.path || "");
|
|
3928
|
+
target.query = relative9.query;
|
|
3929
3929
|
} else {
|
|
3930
|
-
if (
|
|
3931
|
-
target.userinfo =
|
|
3932
|
-
target.host =
|
|
3933
|
-
target.port =
|
|
3934
|
-
target.path = removeDotSegments(
|
|
3935
|
-
target.query =
|
|
3930
|
+
if (relative9.userinfo !== void 0 || relative9.host !== void 0 || relative9.port !== void 0) {
|
|
3931
|
+
target.userinfo = relative9.userinfo;
|
|
3932
|
+
target.host = relative9.host;
|
|
3933
|
+
target.port = relative9.port;
|
|
3934
|
+
target.path = removeDotSegments(relative9.path || "");
|
|
3935
|
+
target.query = relative9.query;
|
|
3936
3936
|
} else {
|
|
3937
|
-
if (!
|
|
3937
|
+
if (!relative9.path) {
|
|
3938
3938
|
target.path = base.path;
|
|
3939
|
-
if (
|
|
3940
|
-
target.query =
|
|
3939
|
+
if (relative9.query !== void 0) {
|
|
3940
|
+
target.query = relative9.query;
|
|
3941
3941
|
} else {
|
|
3942
3942
|
target.query = base.query;
|
|
3943
3943
|
}
|
|
3944
3944
|
} else {
|
|
3945
|
-
if (
|
|
3946
|
-
target.path = removeDotSegments(
|
|
3945
|
+
if (relative9.path[0] === "/") {
|
|
3946
|
+
target.path = removeDotSegments(relative9.path);
|
|
3947
3947
|
} else {
|
|
3948
3948
|
if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
|
|
3949
|
-
target.path = "/" +
|
|
3949
|
+
target.path = "/" + relative9.path;
|
|
3950
3950
|
} else if (!base.path) {
|
|
3951
|
-
target.path =
|
|
3951
|
+
target.path = relative9.path;
|
|
3952
3952
|
} else {
|
|
3953
|
-
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) +
|
|
3953
|
+
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative9.path;
|
|
3954
3954
|
}
|
|
3955
3955
|
target.path = removeDotSegments(target.path);
|
|
3956
3956
|
}
|
|
3957
|
-
target.query =
|
|
3957
|
+
target.query = relative9.query;
|
|
3958
3958
|
}
|
|
3959
3959
|
target.userinfo = base.userinfo;
|
|
3960
3960
|
target.host = base.host;
|
|
@@ -3962,7 +3962,7 @@ var require_fast_uri = __commonJS({
|
|
|
3962
3962
|
}
|
|
3963
3963
|
target.scheme = base.scheme;
|
|
3964
3964
|
}
|
|
3965
|
-
target.fragment =
|
|
3965
|
+
target.fragment = relative9.fragment;
|
|
3966
3966
|
return target;
|
|
3967
3967
|
}
|
|
3968
3968
|
function equal(uriA, uriB, options) {
|
|
@@ -4247,8 +4247,8 @@ var require_fast_uri = __commonJS({
|
|
|
4247
4247
|
}
|
|
4248
4248
|
var fastUri = {
|
|
4249
4249
|
SCHEMES,
|
|
4250
|
-
normalize:
|
|
4251
|
-
resolve:
|
|
4250
|
+
normalize: normalize7,
|
|
4251
|
+
resolve: resolve8,
|
|
4252
4252
|
resolveComponent,
|
|
4253
4253
|
equal,
|
|
4254
4254
|
serialize,
|
|
@@ -10972,15 +10972,15 @@ var require_pattern2 = __commonJS({
|
|
|
10972
10972
|
exports.removeDuplicateSlashes = removeDuplicateSlashes;
|
|
10973
10973
|
function partitionAbsoluteAndRelative(patterns) {
|
|
10974
10974
|
const absolute = [];
|
|
10975
|
-
const
|
|
10975
|
+
const relative9 = [];
|
|
10976
10976
|
for (const pattern2 of patterns) {
|
|
10977
10977
|
if (isAbsolute2(pattern2)) {
|
|
10978
10978
|
absolute.push(pattern2);
|
|
10979
10979
|
} else {
|
|
10980
|
-
|
|
10980
|
+
relative9.push(pattern2);
|
|
10981
10981
|
}
|
|
10982
10982
|
}
|
|
10983
|
-
return [absolute,
|
|
10983
|
+
return [absolute, relative9];
|
|
10984
10984
|
}
|
|
10985
10985
|
exports.partitionAbsoluteAndRelative = partitionAbsoluteAndRelative;
|
|
10986
10986
|
function isAbsolute2(pattern2) {
|
|
@@ -11411,11 +11411,11 @@ var require_out = __commonJS({
|
|
|
11411
11411
|
async.read(path3, getSettings(optionsOrSettingsOrCallback), callback);
|
|
11412
11412
|
}
|
|
11413
11413
|
exports.stat = stat;
|
|
11414
|
-
function
|
|
11414
|
+
function statSync10(path3, optionsOrSettings) {
|
|
11415
11415
|
const settings = getSettings(optionsOrSettings);
|
|
11416
11416
|
return sync.read(path3, settings);
|
|
11417
11417
|
}
|
|
11418
|
-
exports.statSync =
|
|
11418
|
+
exports.statSync = statSync10;
|
|
11419
11419
|
function getSettings(settingsOrOptions = {}) {
|
|
11420
11420
|
if (settingsOrOptions instanceof settings_1.default) {
|
|
11421
11421
|
return settingsOrOptions;
|
|
@@ -12096,41 +12096,41 @@ var require_queue = __commonJS({
|
|
|
12096
12096
|
queue.drained = drained;
|
|
12097
12097
|
return queue;
|
|
12098
12098
|
function push(value) {
|
|
12099
|
-
var p = new Promise(function(
|
|
12099
|
+
var p = new Promise(function(resolve8, reject) {
|
|
12100
12100
|
pushCb(value, function(err, result) {
|
|
12101
12101
|
if (err) {
|
|
12102
12102
|
reject(err);
|
|
12103
12103
|
return;
|
|
12104
12104
|
}
|
|
12105
|
-
|
|
12105
|
+
resolve8(result);
|
|
12106
12106
|
});
|
|
12107
12107
|
});
|
|
12108
12108
|
p.catch(noop);
|
|
12109
12109
|
return p;
|
|
12110
12110
|
}
|
|
12111
12111
|
function unshift(value) {
|
|
12112
|
-
var p = new Promise(function(
|
|
12112
|
+
var p = new Promise(function(resolve8, reject) {
|
|
12113
12113
|
unshiftCb(value, function(err, result) {
|
|
12114
12114
|
if (err) {
|
|
12115
12115
|
reject(err);
|
|
12116
12116
|
return;
|
|
12117
12117
|
}
|
|
12118
|
-
|
|
12118
|
+
resolve8(result);
|
|
12119
12119
|
});
|
|
12120
12120
|
});
|
|
12121
12121
|
p.catch(noop);
|
|
12122
12122
|
return p;
|
|
12123
12123
|
}
|
|
12124
12124
|
function drained() {
|
|
12125
|
-
var p = new Promise(function(
|
|
12125
|
+
var p = new Promise(function(resolve8) {
|
|
12126
12126
|
process.nextTick(function() {
|
|
12127
12127
|
if (queue.idle()) {
|
|
12128
|
-
|
|
12128
|
+
resolve8();
|
|
12129
12129
|
} else {
|
|
12130
12130
|
var previousDrain = queue.drain;
|
|
12131
12131
|
queue.drain = function() {
|
|
12132
12132
|
if (typeof previousDrain === "function") previousDrain();
|
|
12133
|
-
|
|
12133
|
+
resolve8();
|
|
12134
12134
|
queue.drain = previousDrain;
|
|
12135
12135
|
};
|
|
12136
12136
|
}
|
|
@@ -12627,9 +12627,9 @@ var require_stream3 = __commonJS({
|
|
|
12627
12627
|
});
|
|
12628
12628
|
}
|
|
12629
12629
|
_getStat(filepath) {
|
|
12630
|
-
return new Promise((
|
|
12630
|
+
return new Promise((resolve8, reject) => {
|
|
12631
12631
|
this._stat(filepath, this._fsStatSettings, (error62, stats) => {
|
|
12632
|
-
return error62 === null ?
|
|
12632
|
+
return error62 === null ? resolve8(stats) : reject(error62);
|
|
12633
12633
|
});
|
|
12634
12634
|
});
|
|
12635
12635
|
}
|
|
@@ -12654,10 +12654,10 @@ var require_async5 = __commonJS({
|
|
|
12654
12654
|
this._readerStream = new stream_1.default(this._settings);
|
|
12655
12655
|
}
|
|
12656
12656
|
dynamic(root, options) {
|
|
12657
|
-
return new Promise((
|
|
12657
|
+
return new Promise((resolve8, reject) => {
|
|
12658
12658
|
this._walkAsync(root, options, (error62, entries) => {
|
|
12659
12659
|
if (error62 === null) {
|
|
12660
|
-
|
|
12660
|
+
resolve8(entries);
|
|
12661
12661
|
} else {
|
|
12662
12662
|
reject(error62);
|
|
12663
12663
|
}
|
|
@@ -12667,10 +12667,10 @@ var require_async5 = __commonJS({
|
|
|
12667
12667
|
async static(patterns, options) {
|
|
12668
12668
|
const entries = [];
|
|
12669
12669
|
const stream = this._readerStream.static(patterns, options);
|
|
12670
|
-
return new Promise((
|
|
12670
|
+
return new Promise((resolve8, reject) => {
|
|
12671
12671
|
stream.once("error", reject);
|
|
12672
12672
|
stream.on("data", (entry) => entries.push(entry));
|
|
12673
|
-
stream.once("end", () =>
|
|
12673
|
+
stream.once("end", () => resolve8(entries));
|
|
12674
12674
|
});
|
|
12675
12675
|
}
|
|
12676
12676
|
};
|
|
@@ -13845,6 +13845,40 @@ function parseRestShorthand(rest, actionName) {
|
|
|
13845
13845
|
}
|
|
13846
13846
|
return [{ method: "ALL", path: joinRoutePath(rest) }];
|
|
13847
13847
|
}
|
|
13848
|
+
function phpRoutePath(...parts) {
|
|
13849
|
+
return normalizeRoutePath(
|
|
13850
|
+
joinRoutePath(...parts).replace(/\{(\w+)\s*:[^{}]*(?:\{[^{}]*\}[^{}]*)*\}/g, "{$1}").replace(/\{(\w+)<[^>]*>[^}]*\}/g, "{$1}")
|
|
13851
|
+
);
|
|
13852
|
+
}
|
|
13853
|
+
function resourceParam(segment) {
|
|
13854
|
+
return segment.replace(/-/g, "_").replace(/ies$/, "y").replace(/(s|x|z|ch|sh)es$/, "$1").replace(/([^s])s$/, "$1");
|
|
13855
|
+
}
|
|
13856
|
+
function laravelResource(name, api = false, only, except) {
|
|
13857
|
+
const segs = name.split(".").filter(Boolean);
|
|
13858
|
+
const last = segs.pop();
|
|
13859
|
+
if (!last) return [];
|
|
13860
|
+
const base = joinRoutePath(...segs.map((s) => `${s}/:${resourceParam(s)}`), last);
|
|
13861
|
+
const param = `:${resourceParam(last)}`;
|
|
13862
|
+
return RESOURCE_ACTIONS.filter(
|
|
13863
|
+
([, , action]) => !(api && (action === "create" || action === "edit")) && (!only || only.includes(action)) && !except?.includes(action)
|
|
13864
|
+
).map(([method, suffix, action]) => ({
|
|
13865
|
+
method,
|
|
13866
|
+
path: `${base === "/" ? "" : base}${suffix.replace("{p}", param)}` || "/",
|
|
13867
|
+
action
|
|
13868
|
+
}));
|
|
13869
|
+
}
|
|
13870
|
+
function parseRouteAnnotations(doc) {
|
|
13871
|
+
const out = [];
|
|
13872
|
+
for (const m of doc.matchAll(/@Route\(([^)]*)\)/g)) {
|
|
13873
|
+
const body = m[1] ?? "";
|
|
13874
|
+
const path3 = /^\s*"([^"]*)"/.exec(body)?.[1] ?? /\bpath\s*=\s*"([^"]*)"/.exec(body)?.[1];
|
|
13875
|
+
if (path3 === void 0) continue;
|
|
13876
|
+
const list2 = /\bmethods\s*=\s*(\{[^}]*\}|"[^"]*")/.exec(body)?.[1] ?? "";
|
|
13877
|
+
const methods = [...list2.matchAll(/"([^"]+)"/g)].map((x) => httpMethod(x[1])).filter((x) => !!x);
|
|
13878
|
+
for (const method of methods.length ? methods : ["ALL"]) out.push({ method, path: path3 });
|
|
13879
|
+
}
|
|
13880
|
+
return out;
|
|
13881
|
+
}
|
|
13848
13882
|
function frameworkOf(importedPackages) {
|
|
13849
13883
|
for (const p of importedPackages) {
|
|
13850
13884
|
const f = FRAMEWORK_PKGS[p];
|
|
@@ -13889,7 +13923,7 @@ function fileRoutes(rel, exportedNames, defaultExport) {
|
|
|
13889
13923
|
}
|
|
13890
13924
|
return out;
|
|
13891
13925
|
}
|
|
13892
|
-
var ROUTE_METHODS, JS_METHOD_ALIASES, REST_ALIASES, FRAMEWORK_PKGS, routeId, NEXT_APP_ROUTE, NEXT_PAGES_API, HTTP_EXPORTS;
|
|
13926
|
+
var ROUTE_METHODS, JS_METHOD_ALIASES, REST_ALIASES, RESOURCE_ACTIONS, FRAMEWORK_PKGS, routeId, NEXT_APP_ROUTE, NEXT_PAGES_API, HTTP_EXPORTS;
|
|
13893
13927
|
var init_routes = __esm({
|
|
13894
13928
|
"src/graph/routes.ts"() {
|
|
13895
13929
|
"use strict";
|
|
@@ -13913,6 +13947,16 @@ var init_routes = __esm({
|
|
|
13913
13947
|
["PATCH", "/:id", "patch"],
|
|
13914
13948
|
["DELETE", "/:id", "remove"]
|
|
13915
13949
|
];
|
|
13950
|
+
RESOURCE_ACTIONS = [
|
|
13951
|
+
["GET", "", "index"],
|
|
13952
|
+
["GET", "/create", "create"],
|
|
13953
|
+
["POST", "", "store"],
|
|
13954
|
+
["GET", "/{p}", "show"],
|
|
13955
|
+
["GET", "/{p}/edit", "edit"],
|
|
13956
|
+
["PUT", "/{p}", "update"],
|
|
13957
|
+
["PATCH", "/{p}", "update"],
|
|
13958
|
+
["DELETE", "/{p}", "destroy"]
|
|
13959
|
+
];
|
|
13916
13960
|
FRAMEWORK_PKGS = {
|
|
13917
13961
|
express: "express",
|
|
13918
13962
|
fastify: "fastify",
|
|
@@ -13943,7 +13987,18 @@ var init_routes = __esm({
|
|
|
13943
13987
|
"github.com/labstack/echo": "echo",
|
|
13944
13988
|
"github.com/gorilla/mux": "gorilla",
|
|
13945
13989
|
"github.com/gofiber/fiber": "fiber",
|
|
13946
|
-
"github.com/julienschmidt/httprouter": "httprouter"
|
|
13990
|
+
"github.com/julienschmidt/httprouter": "httprouter",
|
|
13991
|
+
// PHP (top-level namespace of a `use` the project cannot resolve)
|
|
13992
|
+
Illuminate: "laravel",
|
|
13993
|
+
Symfony: "symfony",
|
|
13994
|
+
Slim: "slim",
|
|
13995
|
+
CodeIgniter: "codeigniter",
|
|
13996
|
+
// PHP (composer.json `require`, when no `use` in the file names the framework)
|
|
13997
|
+
"laravel/lumen-framework": "lumen",
|
|
13998
|
+
"laravel/framework": "laravel",
|
|
13999
|
+
"symfony/framework-bundle": "symfony",
|
|
14000
|
+
"slim/slim": "slim",
|
|
14001
|
+
"codeigniter4/framework": "codeigniter"
|
|
13947
14002
|
};
|
|
13948
14003
|
routeId = (method, path3) => `route:${method} ${path3}`;
|
|
13949
14004
|
NEXT_APP_ROUTE = /(?:^|\/)app\/(.*?)(?:\/)?route\.(?:ts|tsx|js|jsx|mjs)$/;
|
|
@@ -13999,6 +14054,8 @@ function grammarFor(path3) {
|
|
|
13999
14054
|
return "python";
|
|
14000
14055
|
case ".go":
|
|
14001
14056
|
return "go";
|
|
14057
|
+
case ".php":
|
|
14058
|
+
return "php";
|
|
14002
14059
|
default:
|
|
14003
14060
|
return void 0;
|
|
14004
14061
|
}
|
|
@@ -14503,28 +14560,1095 @@ var init_go = __esm({
|
|
|
14503
14560
|
}
|
|
14504
14561
|
});
|
|
14505
14562
|
|
|
14506
|
-
// src/graph/languages/
|
|
14507
|
-
import {
|
|
14563
|
+
// src/graph/languages/php.ts
|
|
14564
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync4, statSync } from "fs";
|
|
14508
14565
|
import { dirname as dirname4, join as join7, normalize as normalize2, relative as relative2, resolve as resolve3 } from "path";
|
|
14566
|
+
function readComposer(dir) {
|
|
14567
|
+
const file3 = join7(dir, "composer.json");
|
|
14568
|
+
if (!isFile(file3)) return null;
|
|
14569
|
+
try {
|
|
14570
|
+
const json2 = JSON.parse(readFileSync4(file3, "utf8"));
|
|
14571
|
+
const info = { dir, psr4: [], psr0: [], classmap: [], files: [], require: [] };
|
|
14572
|
+
for (const key of ["autoload", "autoload-dev"]) {
|
|
14573
|
+
const section = json2[key];
|
|
14574
|
+
for (const [prefix, dirs] of Object.entries(section?.["psr-4"] ?? {})) {
|
|
14575
|
+
info.psr4.push({
|
|
14576
|
+
prefix: prefix && !prefix.endsWith("\\") ? `${prefix}\\` : prefix,
|
|
14577
|
+
dirs: asList(dirs)
|
|
14578
|
+
});
|
|
14579
|
+
}
|
|
14580
|
+
for (const [prefix, dirs] of Object.entries(section?.["psr-0"] ?? {}))
|
|
14581
|
+
info.psr0.push({ prefix, dirs: asList(dirs) });
|
|
14582
|
+
info.classmap.push(...section?.classmap ?? []);
|
|
14583
|
+
info.files.push(...section?.files ?? []);
|
|
14584
|
+
}
|
|
14585
|
+
info.require = Object.keys(json2.require ?? {});
|
|
14586
|
+
info.psr4.sort((a, b) => b.prefix.length - a.prefix.length);
|
|
14587
|
+
info.psr0.sort((a, b) => b.prefix.length - a.prefix.length);
|
|
14588
|
+
const empty2 = !info.psr4.length && !info.psr0.length && !info.classmap.length && !info.files.length && !info.require.length;
|
|
14589
|
+
return empty2 ? null : info;
|
|
14590
|
+
} catch {
|
|
14591
|
+
return null;
|
|
14592
|
+
}
|
|
14593
|
+
}
|
|
14594
|
+
function composerAutoload(root, fromAbs) {
|
|
14595
|
+
let dir = dirname4(fromAbs);
|
|
14596
|
+
while (dir.startsWith(root)) {
|
|
14597
|
+
let hit = composerCache.get(dir);
|
|
14598
|
+
if (hit === void 0) {
|
|
14599
|
+
hit = readComposer(dir);
|
|
14600
|
+
composerCache.set(dir, hit);
|
|
14601
|
+
}
|
|
14602
|
+
if (hit) return hit;
|
|
14603
|
+
if (dir === root) break;
|
|
14604
|
+
dir = dirname4(dir);
|
|
14605
|
+
}
|
|
14606
|
+
return void 0;
|
|
14607
|
+
}
|
|
14608
|
+
function phpFilesUnder(abs, budget) {
|
|
14609
|
+
if (isFile(abs)) return abs.endsWith(".php") ? [abs] : [];
|
|
14610
|
+
let entries;
|
|
14611
|
+
try {
|
|
14612
|
+
entries = readdirSync2(abs, { recursive: true, encoding: "utf8" });
|
|
14613
|
+
} catch {
|
|
14614
|
+
return [];
|
|
14615
|
+
}
|
|
14616
|
+
const out = [];
|
|
14617
|
+
for (const e of entries) {
|
|
14618
|
+
if (budget.left <= 0) break;
|
|
14619
|
+
if (!e.endsWith(".php") || e.split(/[\\/]/).includes("vendor")) continue;
|
|
14620
|
+
out.push(join7(abs, e));
|
|
14621
|
+
budget.left--;
|
|
14622
|
+
}
|
|
14623
|
+
return out;
|
|
14624
|
+
}
|
|
14625
|
+
function classmapClasses(root, auto) {
|
|
14626
|
+
if (auto.classes) return auto.classes;
|
|
14627
|
+
const classes = /* @__PURE__ */ new Map();
|
|
14628
|
+
const budget = { left: CLASSMAP_MAX_FILES };
|
|
14629
|
+
for (const entry of auto.classmap) {
|
|
14630
|
+
for (const f of phpFilesUnder(join7(auto.dir, entry), budget)) {
|
|
14631
|
+
if (relative2(root, f).startsWith("..")) continue;
|
|
14632
|
+
let code;
|
|
14633
|
+
try {
|
|
14634
|
+
code = readFileSync4(f, "utf8");
|
|
14635
|
+
} catch {
|
|
14636
|
+
continue;
|
|
14637
|
+
}
|
|
14638
|
+
const ns = /^\s*namespace\s+([\w\\]+)\s*[;{]/m.exec(code)?.[1];
|
|
14639
|
+
for (const m of code.matchAll(
|
|
14640
|
+
/^\s*(?:(?:abstract|final|readonly)\s+)*(?:class|interface|trait|enum)\s+(\w+)/gm
|
|
14641
|
+
)) {
|
|
14642
|
+
const fq = ns ? `${ns}\\${m[1]}` : m[1];
|
|
14643
|
+
if (!classes.has(fq)) classes.set(fq, toRel(root, f));
|
|
14644
|
+
}
|
|
14645
|
+
}
|
|
14646
|
+
}
|
|
14647
|
+
auto.classes = classes;
|
|
14648
|
+
return classes;
|
|
14649
|
+
}
|
|
14650
|
+
function autoloadedFunctions(root, auto) {
|
|
14651
|
+
if (auto.functions) return auto.functions;
|
|
14652
|
+
const functions = /* @__PURE__ */ new Map();
|
|
14653
|
+
for (const entry of auto.files) {
|
|
14654
|
+
const f = join7(auto.dir, entry);
|
|
14655
|
+
if (!isFile(f) || relative2(root, f).startsWith("..")) continue;
|
|
14656
|
+
let code;
|
|
14657
|
+
try {
|
|
14658
|
+
code = readFileSync4(f, "utf8");
|
|
14659
|
+
} catch {
|
|
14660
|
+
continue;
|
|
14661
|
+
}
|
|
14662
|
+
if (/^\s*namespace\s+[\w\\]+\s*[;{]/m.test(code)) continue;
|
|
14663
|
+
for (const m of code.matchAll(/^\s*function\s+&?\s*(\w+)\s*\(/gm))
|
|
14664
|
+
if (!functions.has(m[1])) functions.set(m[1], toRel(root, f));
|
|
14665
|
+
}
|
|
14666
|
+
auto.functions = functions;
|
|
14667
|
+
return functions;
|
|
14668
|
+
}
|
|
14669
|
+
function resolvePhpClass(root, fromRel, fqcn) {
|
|
14670
|
+
const name = fqcn.replace(/^\\+/, "");
|
|
14671
|
+
if (!name) return void 0;
|
|
14672
|
+
const candidates2 = [];
|
|
14673
|
+
const auto = composerAutoload(root, resolve3(root, fromRel));
|
|
14674
|
+
if (auto?.psr4.length || auto?.psr0.length) {
|
|
14675
|
+
for (const { prefix, dirs } of auto.psr4) {
|
|
14676
|
+
if (!name.startsWith(prefix)) continue;
|
|
14677
|
+
const rest = name.slice(prefix.length).split("\\");
|
|
14678
|
+
for (const d of dirs) candidates2.push(join7(auto.dir, d, ...rest));
|
|
14679
|
+
}
|
|
14680
|
+
for (const { prefix, dirs } of auto.psr0) {
|
|
14681
|
+
if (!name.startsWith(prefix)) continue;
|
|
14682
|
+
const cut = name.lastIndexOf("\\");
|
|
14683
|
+
const ns = cut === -1 ? [] : name.slice(0, cut).split("\\");
|
|
14684
|
+
const cls = name.slice(cut + 1).split("_");
|
|
14685
|
+
for (const d of dirs) candidates2.push(join7(auto.dir, d, ...ns, ...cls));
|
|
14686
|
+
}
|
|
14687
|
+
} else {
|
|
14688
|
+
const parts = name.split("\\");
|
|
14689
|
+
candidates2.push(resolve3(root, ...parts), resolve3(root, "src", ...parts));
|
|
14690
|
+
}
|
|
14691
|
+
for (const c of candidates2) {
|
|
14692
|
+
const f = `${c}.php`;
|
|
14693
|
+
if (isFile(f) && !relative2(root, f).startsWith("..")) return toRel(root, f);
|
|
14694
|
+
}
|
|
14695
|
+
return auto?.classmap.length ? classmapClasses(root, auto).get(name) : void 0;
|
|
14696
|
+
}
|
|
14697
|
+
function phpString(n) {
|
|
14698
|
+
if (!n || n.type !== "string" && n.type !== "encapsed_string") return void 0;
|
|
14699
|
+
if (n.namedChildren.some((c) => c && c.type !== "string_content" && c.type !== "escape_sequence"))
|
|
14700
|
+
return void 0;
|
|
14701
|
+
return literalText(n)?.replace(/\\(\\|')/g, "$1");
|
|
14702
|
+
}
|
|
14703
|
+
function argsOf(call) {
|
|
14704
|
+
const list2 = call.childForFieldName("arguments") ?? call.childForFieldName("parameters");
|
|
14705
|
+
return (list2?.namedChildren ?? []).filter((a) => a?.type === "argument").map((a) => a.namedChildren[a.namedChildren.length - 1]).filter((a) => !!a);
|
|
14706
|
+
}
|
|
14707
|
+
function positionalArgs(call) {
|
|
14708
|
+
const list2 = call.childForFieldName("arguments") ?? call.childForFieldName("parameters");
|
|
14709
|
+
return (list2?.namedChildren ?? []).filter((a) => a?.type === "argument" && !a.childForFieldName("name")).map((a) => a.namedChildren[0]).filter((a) => !!a);
|
|
14710
|
+
}
|
|
14711
|
+
function namedArg(call, name) {
|
|
14712
|
+
const list2 = call.childForFieldName("arguments") ?? call.childForFieldName("parameters");
|
|
14713
|
+
for (const a of list2?.namedChildren ?? []) {
|
|
14714
|
+
if (a?.type === "argument" && a.childForFieldName("name")?.text === name)
|
|
14715
|
+
return a.namedChildren[a.namedChildren.length - 1] ?? void 0;
|
|
14716
|
+
}
|
|
14717
|
+
return void 0;
|
|
14718
|
+
}
|
|
14719
|
+
function stringsOf(n) {
|
|
14720
|
+
if (!n) return [];
|
|
14721
|
+
if (n.type !== "array_creation_expression") {
|
|
14722
|
+
const s = phpString(n);
|
|
14723
|
+
return s === void 0 ? [] : [s];
|
|
14724
|
+
}
|
|
14725
|
+
return n.namedChildren.flatMap((el) => {
|
|
14726
|
+
const s = el?.namedChildren.length === 1 ? phpString(el.namedChildren[0]) : void 0;
|
|
14727
|
+
return s === void 0 ? [] : [s];
|
|
14728
|
+
});
|
|
14729
|
+
}
|
|
14730
|
+
function arrayElements(arr2) {
|
|
14731
|
+
const out = [];
|
|
14732
|
+
for (const el of arr2.namedChildren) {
|
|
14733
|
+
if (el?.type !== "array_element_initializer") continue;
|
|
14734
|
+
const kids = el.namedChildren.filter((c) => !!c);
|
|
14735
|
+
if (kids.length === 1) out.push({ value: kids[0] });
|
|
14736
|
+
else if (kids.length === 2) out.push({ key: phpString(kids[0]), value: kids[1] });
|
|
14737
|
+
}
|
|
14738
|
+
return out;
|
|
14739
|
+
}
|
|
14740
|
+
function handlerShaped(a) {
|
|
14741
|
+
if (!a) return false;
|
|
14742
|
+
switch (a.type) {
|
|
14743
|
+
case "anonymous_function":
|
|
14744
|
+
case "arrow_function":
|
|
14745
|
+
case "class_constant_access_expression":
|
|
14746
|
+
return true;
|
|
14747
|
+
case "string":
|
|
14748
|
+
case "encapsed_string":
|
|
14749
|
+
return CONTROLLER_STRING.test(phpString(a) ?? "");
|
|
14750
|
+
case "array_creation_expression":
|
|
14751
|
+
return arrayElements(a).some((e) => e.key ? e.key === "uses" : handlerShaped(e.value));
|
|
14752
|
+
default:
|
|
14753
|
+
return false;
|
|
14754
|
+
}
|
|
14755
|
+
}
|
|
14756
|
+
async function parsePhp(root, rel, code) {
|
|
14757
|
+
const p = await getParser("php");
|
|
14758
|
+
const tree = p.parse(code);
|
|
14759
|
+
if (!tree) return { nodes: [], edges: [], exports: [] };
|
|
14760
|
+
const fid = fileId(rel);
|
|
14761
|
+
const fileNode = {
|
|
14762
|
+
id: fid,
|
|
14763
|
+
kind: "file",
|
|
14764
|
+
name: rel,
|
|
14765
|
+
path: rel,
|
|
14766
|
+
source: "tree-sitter"
|
|
14767
|
+
};
|
|
14768
|
+
const nodes = [fileNode];
|
|
14769
|
+
const edges = [];
|
|
14770
|
+
const exportsList = [];
|
|
14771
|
+
const scope = /* @__PURE__ */ new Map();
|
|
14772
|
+
let classUses = /* @__PURE__ */ new Map();
|
|
14773
|
+
const usesByBlock = /* @__PURE__ */ new Map();
|
|
14774
|
+
const declared = /* @__PURE__ */ new Set();
|
|
14775
|
+
const localSyms = /* @__PURE__ */ new Map();
|
|
14776
|
+
const varTypes = /* @__PURE__ */ new Map();
|
|
14777
|
+
const propTypes = /* @__PURE__ */ new Map();
|
|
14778
|
+
const parents = /* @__PURE__ */ new Map();
|
|
14779
|
+
const imports = /* @__PURE__ */ new Map();
|
|
14780
|
+
const resolvedClasses = /* @__PURE__ */ new Map();
|
|
14781
|
+
const importedPkgs = /* @__PURE__ */ new Set();
|
|
14782
|
+
const refs = new RefCollector();
|
|
14783
|
+
let complexity = 0;
|
|
14784
|
+
let namespace = "";
|
|
14785
|
+
const namespaces = [];
|
|
14786
|
+
const pushEdge = (e) => edges.push({ confidence: 1, weight: 1, ...e });
|
|
14787
|
+
const auto = composerAutoload(root, resolve3(root, rel));
|
|
14788
|
+
const stmts = [];
|
|
14789
|
+
let block = 0;
|
|
14790
|
+
for (const stmt of tree.rootNode.namedChildren) {
|
|
14791
|
+
if (!stmt) continue;
|
|
14792
|
+
if (stmt.type === "namespace_definition") {
|
|
14793
|
+
block++;
|
|
14794
|
+
namespace = stmt.childForFieldName("name")?.text ?? "";
|
|
14795
|
+
if (namespace) addNamespace(stmt, namespace);
|
|
14796
|
+
for (const s of stmt.childForFieldName("body")?.namedChildren ?? [])
|
|
14797
|
+
if (s) stmts.push([s, namespace, block]);
|
|
14798
|
+
} else stmts.push([stmt, namespace, block]);
|
|
14799
|
+
}
|
|
14800
|
+
const enter = (ns, b) => {
|
|
14801
|
+
namespace = ns;
|
|
14802
|
+
let uses = usesByBlock.get(b);
|
|
14803
|
+
if (!uses) {
|
|
14804
|
+
uses = /* @__PURE__ */ new Map();
|
|
14805
|
+
usesByBlock.set(b, uses);
|
|
14806
|
+
}
|
|
14807
|
+
classUses = uses;
|
|
14808
|
+
};
|
|
14809
|
+
for (const [stmt] of stmts) {
|
|
14810
|
+
const name = CLASS_KINDS[stmt.type] ? stmt.childForFieldName("name")?.text : void 0;
|
|
14811
|
+
if (name) declared.add(name);
|
|
14812
|
+
}
|
|
14813
|
+
for (const [stmt, ns, b] of stmts) {
|
|
14814
|
+
enter(ns, b);
|
|
14815
|
+
if (stmt.type === "namespace_use_declaration") handleUse(stmt);
|
|
14816
|
+
}
|
|
14817
|
+
for (const [stmt, ns, b] of stmts) {
|
|
14818
|
+
enter(ns, b);
|
|
14819
|
+
if (stmt.type !== "namespace_use_declaration") collectDecls(stmt);
|
|
14820
|
+
}
|
|
14821
|
+
for (const [stmt, ns, b] of stmts) {
|
|
14822
|
+
enter(ns, b);
|
|
14823
|
+
if (stmt.type !== "namespace_use_declaration") walkRefs(stmt);
|
|
14824
|
+
}
|
|
14825
|
+
handleIncludes(tree.rootNode);
|
|
14826
|
+
edges.push(...imports.values());
|
|
14827
|
+
edges.push(...refs.edges());
|
|
14828
|
+
const errors = tree.rootNode.hasError ? tree.rootNode.descendantsOfType("ERROR").length : 0;
|
|
14829
|
+
fileNode.meta = {
|
|
14830
|
+
loc: tree.rootNode.endPosition.row + 1,
|
|
14831
|
+
complexity,
|
|
14832
|
+
...namespaces.length ? { php_namespace: namespaces[0] } : {},
|
|
14833
|
+
...errors ? { parse_errors: errors } : {}
|
|
14834
|
+
};
|
|
14835
|
+
return { nodes, edges, exports: exportsList, errors };
|
|
14836
|
+
function addNamespace(n, name) {
|
|
14837
|
+
if (namespaces.includes(name)) return;
|
|
14838
|
+
namespaces.push(name);
|
|
14839
|
+
const id = symId(rel, name);
|
|
14840
|
+
nodes.push({
|
|
14841
|
+
id,
|
|
14842
|
+
kind: "namespace",
|
|
14843
|
+
name,
|
|
14844
|
+
path: rel,
|
|
14845
|
+
startLine: n.startPosition.row + 1,
|
|
14846
|
+
endLine: n.endPosition.row + 1,
|
|
14847
|
+
source: "tree-sitter"
|
|
14848
|
+
});
|
|
14849
|
+
pushEdge({ src: fid, dst: id, kind: "defines", source: "tree-sitter" });
|
|
14850
|
+
}
|
|
14851
|
+
function addImport(dst, name, spec, line, conf) {
|
|
14852
|
+
const cur = imports.get(dst);
|
|
14853
|
+
if (cur?.meta) {
|
|
14854
|
+
const names = cur.meta.names;
|
|
14855
|
+
if (!names.includes(name)) names.push(name);
|
|
14856
|
+
return;
|
|
14857
|
+
}
|
|
14858
|
+
imports.set(dst, {
|
|
14859
|
+
src: fid,
|
|
14860
|
+
dst,
|
|
14861
|
+
kind: "imports",
|
|
14862
|
+
source: "tree-sitter",
|
|
14863
|
+
confidence: conf,
|
|
14864
|
+
weight: 1,
|
|
14865
|
+
meta: { names: [name], spec, line }
|
|
14866
|
+
});
|
|
14867
|
+
}
|
|
14868
|
+
function handleUse(decl) {
|
|
14869
|
+
const group = decl.childForFieldName("body");
|
|
14870
|
+
const prefix = group ? decl.namedChildren.find((c) => c?.type === "namespace_name")?.text : void 0;
|
|
14871
|
+
const declKind = decl.children.find((c) => c?.type === "function" || c?.type === "const")?.type;
|
|
14872
|
+
for (const c of (group ?? decl).namedChildren) {
|
|
14873
|
+
if (c?.type !== "namespace_use_clause") continue;
|
|
14874
|
+
const alias = c.childForFieldName("alias");
|
|
14875
|
+
const target = c.namedChildren.find(
|
|
14876
|
+
(x) => x && x.id !== alias?.id && (x.type === "qualified_name" || x.type === "name")
|
|
14877
|
+
);
|
|
14878
|
+
if (!target) continue;
|
|
14879
|
+
const fqn = (prefix ? `${prefix}\\${target.text}` : target.text).replace(/^\\+/, "");
|
|
14880
|
+
const local = alias?.text ?? lastSegment(fqn);
|
|
14881
|
+
const kind = c.children.find((x) => x?.type === "function" || x?.type === "const")?.type ?? declKind;
|
|
14882
|
+
const line = c.startPosition.row + 1;
|
|
14883
|
+
const label = alias ? `${fqn} as ${alias.text}` : fqn;
|
|
14884
|
+
const file3 = kind ? void 0 : classFile(fqn);
|
|
14885
|
+
if (file3) {
|
|
14886
|
+
if (file3 !== rel) addImport(fileId(file3), label, fqn, line, 0.95);
|
|
14887
|
+
} else {
|
|
14888
|
+
const top = fqn.split("\\")[0];
|
|
14889
|
+
importedPkgs.add(top);
|
|
14890
|
+
if (!imports.has(pkgId(top)))
|
|
14891
|
+
nodes.push({ id: pkgId(top), kind: "package", name: top, source: "tree-sitter" });
|
|
14892
|
+
addImport(pkgId(top), label, fqn, line, 1);
|
|
14893
|
+
}
|
|
14894
|
+
if (kind) scope.set(local, { id: pkgId(fqn.split("\\")[0]), confidence: 0.6 });
|
|
14895
|
+
else classUses.set(local, fqn);
|
|
14896
|
+
}
|
|
14897
|
+
}
|
|
14898
|
+
function handleIncludes(rootNode) {
|
|
14899
|
+
const here = dirname4(resolve3(root, rel));
|
|
14900
|
+
for (const inc of rootNode.descendantsOfType([
|
|
14901
|
+
"require_expression",
|
|
14902
|
+
"require_once_expression",
|
|
14903
|
+
"include_expression",
|
|
14904
|
+
"include_once_expression"
|
|
14905
|
+
])) {
|
|
14906
|
+
const arg = inc.namedChildren[0];
|
|
14907
|
+
if (!arg) continue;
|
|
14908
|
+
const candidates2 = [];
|
|
14909
|
+
const plain = phpString(arg);
|
|
14910
|
+
if (plain !== void 0) candidates2.push(resolve3(here, plain), resolve3(root, plain));
|
|
14911
|
+
else if (arg.type === "binary_expression") {
|
|
14912
|
+
const left = arg.childForFieldName("left")?.text.replace(/\s+/g, "") ?? "";
|
|
14913
|
+
const right = phpString(arg.childForFieldName("right"));
|
|
14914
|
+
const up = /^dirname\(__(?:DIR|FILE)__(?:,(\d+))?\)$/.exec(left);
|
|
14915
|
+
let base;
|
|
14916
|
+
if (left === "__DIR__" || left === "dirname(__FILE__)") base = here;
|
|
14917
|
+
else if (up) {
|
|
14918
|
+
base = here;
|
|
14919
|
+
for (let i = left.includes("__FILE__") ? 1 : 0; i < Number(up[1] ?? 1); i++)
|
|
14920
|
+
base = dirname4(base);
|
|
14921
|
+
}
|
|
14922
|
+
if (base && right !== void 0) candidates2.push(join7(base, right));
|
|
14923
|
+
}
|
|
14924
|
+
const hit = candidates2.find((c) => isFile(c) && !relative2(root, c).startsWith(".."));
|
|
14925
|
+
if (!hit) continue;
|
|
14926
|
+
const file3 = toRel(root, hit);
|
|
14927
|
+
if (file3 !== rel) addImport(fileId(file3), "*", arg.text, inc.startPosition.row + 1, 0.9);
|
|
14928
|
+
}
|
|
14929
|
+
}
|
|
14930
|
+
function classFile(fqcn) {
|
|
14931
|
+
let hit = resolvedClasses.get(fqcn);
|
|
14932
|
+
if (hit === void 0) {
|
|
14933
|
+
hit = resolvePhpClass(root, rel, fqcn) ?? null;
|
|
14934
|
+
resolvedClasses.set(fqcn, hit);
|
|
14935
|
+
}
|
|
14936
|
+
return hit ?? void 0;
|
|
14937
|
+
}
|
|
14938
|
+
function fqcnOf(name) {
|
|
14939
|
+
if (name.startsWith("\\")) return name.slice(1);
|
|
14940
|
+
const [head, ...rest] = name.split("\\");
|
|
14941
|
+
const used = classUses.get(head);
|
|
14942
|
+
if (used) return [used, ...rest].join("\\");
|
|
14943
|
+
return namespace ? `${namespace}\\${name}` : name;
|
|
14944
|
+
}
|
|
14945
|
+
function classRef(name) {
|
|
14946
|
+
if (!name || RELATIVE.has(name.toLowerCase())) return void 0;
|
|
14947
|
+
if (!name.includes("\\") && !classUses.has(name) && declared.has(name))
|
|
14948
|
+
return { id: symId(rel, name), confidence: 0.9 };
|
|
14949
|
+
const fqcn = fqcnOf(name);
|
|
14950
|
+
const file3 = classFile(fqcn);
|
|
14951
|
+
if (file3) return { id: symId(file3, lastSegment(fqcn)), confidence: file3 === rel ? 0.9 : 0.85 };
|
|
14952
|
+
const used = classUses.get(name.replace(/^\\/, "").split("\\")[0]);
|
|
14953
|
+
if (used && !name.startsWith("\\")) return { id: pkgId(used.split("\\")[0]), confidence: 0.6 };
|
|
14954
|
+
return void 0;
|
|
14955
|
+
}
|
|
14956
|
+
function typeRef(n) {
|
|
14957
|
+
if (!n) return void 0;
|
|
14958
|
+
const named = n.type === "named_type" ? n : n.descendantsOfType("named_type")[0];
|
|
14959
|
+
const t = named ? classRef(named.text) : void 0;
|
|
14960
|
+
return t?.id.startsWith("sym:") ? t.id : void 0;
|
|
14961
|
+
}
|
|
14962
|
+
function collectDecls(n) {
|
|
14963
|
+
if (CLASS_KINDS[n.type]) {
|
|
14964
|
+
collectClass(n);
|
|
14965
|
+
return;
|
|
14966
|
+
}
|
|
14967
|
+
switch (n.type) {
|
|
14968
|
+
case "function_definition": {
|
|
14969
|
+
const name = n.childForFieldName("name")?.text;
|
|
14970
|
+
if (name) addFunction(name, n);
|
|
14971
|
+
return;
|
|
14972
|
+
}
|
|
14973
|
+
case "if_statement": {
|
|
14974
|
+
for (const f of n.descendantsOfType("function_definition")) {
|
|
14975
|
+
const name = f.childForFieldName("name")?.text;
|
|
14976
|
+
if (name && !insideDecl(f, n)) addFunction(name, f);
|
|
14977
|
+
}
|
|
14978
|
+
return;
|
|
14979
|
+
}
|
|
14980
|
+
case "const_declaration": {
|
|
14981
|
+
for (const el of n.namedChildren) {
|
|
14982
|
+
const name = el?.type === "const_element" ? el.namedChildren[0]?.text : void 0;
|
|
14983
|
+
if (name) addSym(name, "variable", el, true);
|
|
14984
|
+
}
|
|
14985
|
+
return;
|
|
14986
|
+
}
|
|
14987
|
+
case "expression_statement": {
|
|
14988
|
+
const call = n.namedChildren[0];
|
|
14989
|
+
if (call?.type !== "function_call_expression") return;
|
|
14990
|
+
if (call.childForFieldName("function")?.text !== "define") return;
|
|
14991
|
+
const name = phpString(argsOf(call)[0]);
|
|
14992
|
+
if (name && /^\w+$/.test(name)) addSym(name, "variable", call, true);
|
|
14993
|
+
return;
|
|
14994
|
+
}
|
|
14995
|
+
default:
|
|
14996
|
+
return;
|
|
14997
|
+
}
|
|
14998
|
+
}
|
|
14999
|
+
function insideDecl(n, top) {
|
|
15000
|
+
for (let cur = n.parent; cur && cur.id !== top.id; cur = cur.parent) {
|
|
15001
|
+
if (cur.type === "function_definition" || cur.type === "method_declaration") return true;
|
|
15002
|
+
if (CLASS_KINDS[cur.type]) return true;
|
|
15003
|
+
}
|
|
15004
|
+
return false;
|
|
15005
|
+
}
|
|
15006
|
+
function addFunction(name, n) {
|
|
15007
|
+
addSym(name, "function", n, true);
|
|
15008
|
+
scope.set(name, { id: symId(rel, name), confidence: 0.9 });
|
|
15009
|
+
}
|
|
15010
|
+
function collectClass(n) {
|
|
15011
|
+
const name = n.childForFieldName("name")?.text;
|
|
15012
|
+
const kind = CLASS_KINDS[n.type];
|
|
15013
|
+
if (!name || !kind) return;
|
|
15014
|
+
addSym(name, kind, n, true);
|
|
15015
|
+
const self = symId(rel, name);
|
|
15016
|
+
for (const h of n.namedChildren) {
|
|
15017
|
+
if (h?.type !== "base_clause" && h?.type !== "class_interface_clause") continue;
|
|
15018
|
+
for (const b of h.namedChildren) {
|
|
15019
|
+
if (b?.type !== "name" && b?.type !== "qualified_name") continue;
|
|
15020
|
+
const target = heritage(self, b.text, h.type === "base_clause" ? "extends" : "implements");
|
|
15021
|
+
if (target && h.type === "base_clause" && kind === "class") parents.set(name, target);
|
|
15022
|
+
}
|
|
15023
|
+
}
|
|
15024
|
+
const body = n.childForFieldName("body");
|
|
15025
|
+
for (const m of body?.namedChildren ?? []) {
|
|
15026
|
+
if (!m) continue;
|
|
15027
|
+
switch (m.type) {
|
|
15028
|
+
case "method_declaration": {
|
|
15029
|
+
const mname = m.childForFieldName("name")?.text;
|
|
15030
|
+
if (!mname) break;
|
|
15031
|
+
addSym(`${name}.${mname}`, "method", m, isPublic(m));
|
|
15032
|
+
const params = m.childForFieldName("parameters")?.namedChildren ?? [];
|
|
15033
|
+
for (const prm of params) {
|
|
15034
|
+
if (prm?.type !== "property_promotion_parameter") continue;
|
|
15035
|
+
const pname = prm.childForFieldName("name")?.text.replace(/^\$/, "");
|
|
15036
|
+
if (!pname) continue;
|
|
15037
|
+
addSym(`${name}.${pname}`, "field", prm, isPublic(prm));
|
|
15038
|
+
const t = typeRef(prm.childForFieldName("type"));
|
|
15039
|
+
if (t) propTypes.set(`${name}.${pname}`, t);
|
|
15040
|
+
}
|
|
15041
|
+
break;
|
|
15042
|
+
}
|
|
15043
|
+
case "property_declaration": {
|
|
15044
|
+
const t = typeRef(m.childForFieldName("type"));
|
|
15045
|
+
for (const el of m.namedChildren) {
|
|
15046
|
+
if (el?.type !== "property_element") continue;
|
|
15047
|
+
const pname = el.childForFieldName("name")?.text.replace(/^\$/, "");
|
|
15048
|
+
if (!pname) continue;
|
|
15049
|
+
addSym(`${name}.${pname}`, "field", el, isPublic(m));
|
|
15050
|
+
if (t) propTypes.set(`${name}.${pname}`, t);
|
|
15051
|
+
}
|
|
15052
|
+
break;
|
|
15053
|
+
}
|
|
15054
|
+
case "const_declaration": {
|
|
15055
|
+
for (const el of m.namedChildren) {
|
|
15056
|
+
const cname = el?.type === "const_element" ? el.namedChildren[0]?.text : void 0;
|
|
15057
|
+
if (cname) addSym(`${name}.${cname}`, "field", el, isPublic(m));
|
|
15058
|
+
}
|
|
15059
|
+
break;
|
|
15060
|
+
}
|
|
15061
|
+
case "enum_case": {
|
|
15062
|
+
const cname = m.childForFieldName("name")?.text;
|
|
15063
|
+
if (cname) addSym(`${name}.${cname}`, "field", m, true);
|
|
15064
|
+
break;
|
|
15065
|
+
}
|
|
15066
|
+
case "use_declaration": {
|
|
15067
|
+
for (const t of m.namedChildren) {
|
|
15068
|
+
if (t?.type === "name" || t?.type === "qualified_name")
|
|
15069
|
+
heritage(self, t.text, "extends", { trait: true });
|
|
15070
|
+
}
|
|
15071
|
+
break;
|
|
15072
|
+
}
|
|
15073
|
+
default:
|
|
15074
|
+
break;
|
|
15075
|
+
}
|
|
15076
|
+
}
|
|
15077
|
+
attributeRoutes(n, name);
|
|
15078
|
+
}
|
|
15079
|
+
function heritage(src, name, kind, meta4) {
|
|
15080
|
+
const ref = classRef(name) ?? (name.startsWith("\\") && !name.slice(1).includes("\\") ? void 0 : { id: symId(rel, lastSegment(name)), confidence: 0.5 });
|
|
15081
|
+
if (!ref) return void 0;
|
|
15082
|
+
pushEdge({
|
|
15083
|
+
src,
|
|
15084
|
+
dst: ref.id,
|
|
15085
|
+
kind,
|
|
15086
|
+
source: "tree-sitter",
|
|
15087
|
+
confidence: ref.confidence,
|
|
15088
|
+
...meta4 ? { meta: meta4 } : {}
|
|
15089
|
+
});
|
|
15090
|
+
return ref.id.startsWith("sym:") ? ref.id : void 0;
|
|
15091
|
+
}
|
|
15092
|
+
function addSym(qualified, kind, n, exported) {
|
|
15093
|
+
const id = symId(rel, qualified);
|
|
15094
|
+
const c = kind === "function" || kind === "method" ? complexityOf(n, BRANCHES2, BOOL_OPS2) : 0;
|
|
15095
|
+
complexity += c;
|
|
15096
|
+
nodes.push({
|
|
15097
|
+
id,
|
|
15098
|
+
kind,
|
|
15099
|
+
name: qualified,
|
|
15100
|
+
path: rel,
|
|
15101
|
+
startLine: n.startPosition.row + 1,
|
|
15102
|
+
endLine: n.endPosition.row + 1,
|
|
15103
|
+
source: "tree-sitter",
|
|
15104
|
+
meta: {
|
|
15105
|
+
...exported ? { exported: true } : {},
|
|
15106
|
+
loc: n.endPosition.row - n.startPosition.row + 1,
|
|
15107
|
+
...c ? { complexity: c } : {}
|
|
15108
|
+
}
|
|
15109
|
+
});
|
|
15110
|
+
pushEdge({ src: fid, dst: id, kind: "defines", source: "tree-sitter" });
|
|
15111
|
+
if (exported) {
|
|
15112
|
+
exportsList.push(qualified);
|
|
15113
|
+
pushEdge({ src: fid, dst: id, kind: "exports", source: "tree-sitter" });
|
|
15114
|
+
}
|
|
15115
|
+
localSyms.set(qualified, id);
|
|
15116
|
+
}
|
|
15117
|
+
function enclosing(n) {
|
|
15118
|
+
let cur = n.parent;
|
|
15119
|
+
while (cur) {
|
|
15120
|
+
if (cur.type === "method_declaration") {
|
|
15121
|
+
const name = cur.childForFieldName("name")?.text;
|
|
15122
|
+
const owner = cur.parent?.parent?.childForFieldName("name")?.text;
|
|
15123
|
+
const q = owner && name ? `${owner}.${name}` : void 0;
|
|
15124
|
+
if (q && localSyms.has(q)) return q;
|
|
15125
|
+
}
|
|
15126
|
+
if (cur.type === "function_definition") {
|
|
15127
|
+
const name = cur.childForFieldName("name")?.text;
|
|
15128
|
+
if (name && localSyms.has(name)) return name;
|
|
15129
|
+
}
|
|
15130
|
+
cur = cur.parent;
|
|
15131
|
+
}
|
|
15132
|
+
return void 0;
|
|
15133
|
+
}
|
|
15134
|
+
function objectType2(obj, caller) {
|
|
15135
|
+
const cls = classOf(caller);
|
|
15136
|
+
if (obj.type === "variable_name") {
|
|
15137
|
+
if (obj.text === "$this") return cls ? { id: symId(rel, cls), confidence: 0.9 } : void 0;
|
|
15138
|
+
const t = varTypes.get(`${caller ?? ""}\0${obj.text}`);
|
|
15139
|
+
return t ? { id: t, confidence: 0.8 } : void 0;
|
|
15140
|
+
}
|
|
15141
|
+
if (obj.type === "member_access_expression" || obj.type === "nullsafe_member_access_expression") {
|
|
15142
|
+
const inner = obj.childForFieldName("object");
|
|
15143
|
+
const prop = obj.childForFieldName("name")?.text;
|
|
15144
|
+
if (inner?.text !== "$this" || !cls || !prop) return void 0;
|
|
15145
|
+
const t = propTypes.get(`${cls}.${prop}`);
|
|
15146
|
+
return t ? { id: t, confidence: 0.8 } : void 0;
|
|
15147
|
+
}
|
|
15148
|
+
return void 0;
|
|
15149
|
+
}
|
|
15150
|
+
function scopeType(s, caller) {
|
|
15151
|
+
const cls = classOf(caller);
|
|
15152
|
+
if (s.type === "relative_scope" || RELATIVE.has(s.text.toLowerCase())) {
|
|
15153
|
+
const word = s.text.toLowerCase();
|
|
15154
|
+
if (!cls) return void 0;
|
|
15155
|
+
if (word === "parent") {
|
|
15156
|
+
const p2 = parents.get(cls);
|
|
15157
|
+
return p2 ? { id: p2, confidence: 0.8 } : void 0;
|
|
15158
|
+
}
|
|
15159
|
+
return { id: symId(rel, cls), confidence: 0.9 };
|
|
15160
|
+
}
|
|
15161
|
+
if (s.type === "name" || s.type === "qualified_name") return classRef(s.text);
|
|
15162
|
+
return void 0;
|
|
15163
|
+
}
|
|
15164
|
+
function callTarget(call, caller) {
|
|
15165
|
+
switch (call.type) {
|
|
15166
|
+
case "function_call_expression": {
|
|
15167
|
+
const fn = call.childForFieldName("function");
|
|
15168
|
+
if (fn?.type !== "name") return void 0;
|
|
15169
|
+
const local = scope.get(fn.text);
|
|
15170
|
+
if (local || !auto?.files.length) return local;
|
|
15171
|
+
const file3 = autoloadedFunctions(root, auto).get(fn.text);
|
|
15172
|
+
return file3 && file3 !== rel ? { id: symId(file3, fn.text), confidence: 0.8 } : void 0;
|
|
15173
|
+
}
|
|
15174
|
+
case "member_call_expression":
|
|
15175
|
+
case "nullsafe_member_call_expression": {
|
|
15176
|
+
const obj = call.childForFieldName("object");
|
|
15177
|
+
const m = call.childForFieldName("name");
|
|
15178
|
+
if (!obj || m?.type !== "name") return void 0;
|
|
15179
|
+
const t = objectType2(obj, caller);
|
|
15180
|
+
return t ? { id: `${t.id}.${m.text}`, confidence: t.confidence } : void 0;
|
|
15181
|
+
}
|
|
15182
|
+
case "scoped_call_expression": {
|
|
15183
|
+
const s = call.childForFieldName("scope");
|
|
15184
|
+
const m = call.childForFieldName("name");
|
|
15185
|
+
if (!s || m?.type !== "name") return void 0;
|
|
15186
|
+
const t = scopeType(s, caller);
|
|
15187
|
+
if (t?.id.startsWith("pkg:")) return t;
|
|
15188
|
+
return t ? { id: `${t.id}.${m.text}`, confidence: t.confidence } : void 0;
|
|
15189
|
+
}
|
|
15190
|
+
case "object_creation_expression": {
|
|
15191
|
+
const cls = call.namedChildren.find(
|
|
15192
|
+
(c) => c?.type === "name" || c?.type === "qualified_name"
|
|
15193
|
+
);
|
|
15194
|
+
return cls ? classRef(cls.text) : void 0;
|
|
15195
|
+
}
|
|
15196
|
+
default:
|
|
15197
|
+
return void 0;
|
|
15198
|
+
}
|
|
15199
|
+
}
|
|
15200
|
+
function noteVarTypes(n) {
|
|
15201
|
+
for (const prm of n.descendantsOfType("simple_parameter")) {
|
|
15202
|
+
const t = typeRef(prm.childForFieldName("type"));
|
|
15203
|
+
const v = prm.childForFieldName("name")?.text;
|
|
15204
|
+
if (t && v) varTypes.set(`${enclosing(prm) ?? ""}\0${v}`, t);
|
|
15205
|
+
}
|
|
15206
|
+
for (const a of n.descendantsOfType("assignment_expression")) {
|
|
15207
|
+
const left = a.childForFieldName("left");
|
|
15208
|
+
const right = a.childForFieldName("right");
|
|
15209
|
+
if (left?.type !== "variable_name" || right?.type !== "object_creation_expression") continue;
|
|
15210
|
+
const cls = right.namedChildren.find(
|
|
15211
|
+
(c) => c?.type === "name" || c?.type === "qualified_name"
|
|
15212
|
+
);
|
|
15213
|
+
const t = cls ? classRef(cls.text) : void 0;
|
|
15214
|
+
if (t?.id.startsWith("sym:")) varTypes.set(`${enclosing(a) ?? ""}\0${left.text}`, t.id);
|
|
15215
|
+
}
|
|
15216
|
+
}
|
|
15217
|
+
function addRoute(method, path3, framework, line, handlers, confidence, extra = {}) {
|
|
15218
|
+
const id = routeId(method, path3);
|
|
15219
|
+
if (!nodes.some((n) => n.id === id)) {
|
|
15220
|
+
nodes.push({
|
|
15221
|
+
id,
|
|
15222
|
+
kind: "route",
|
|
15223
|
+
name: `${method} ${path3}`,
|
|
15224
|
+
path: rel,
|
|
15225
|
+
startLine: line,
|
|
15226
|
+
endLine: line,
|
|
15227
|
+
source: "tree-sitter",
|
|
15228
|
+
meta: { method, route: path3, framework, ...extra }
|
|
15229
|
+
});
|
|
15230
|
+
pushEdge({ src: fid, dst: id, kind: "defines", source: "tree-sitter" });
|
|
15231
|
+
}
|
|
15232
|
+
for (const h of handlers)
|
|
15233
|
+
pushEdge({ src: h, dst: id, kind: "handles", source: "tree-sitter", confidence });
|
|
15234
|
+
}
|
|
15235
|
+
function controllerRef(name, literal2 = false) {
|
|
15236
|
+
if (!literal2) {
|
|
15237
|
+
const direct = classRef(name);
|
|
15238
|
+
if (direct?.id.startsWith("sym:")) return direct;
|
|
15239
|
+
}
|
|
15240
|
+
const fq = name.replace(/^\\+/, "");
|
|
15241
|
+
const candidates2 = CONTROLLER_NAMESPACES.map((ns) => `${ns}\\${fq}`);
|
|
15242
|
+
if (literal2) candidates2.push(fq);
|
|
15243
|
+
for (const c of candidates2) {
|
|
15244
|
+
const file3 = classFile(c);
|
|
15245
|
+
if (file3) return { id: symId(file3, lastSegment(fq)), confidence: 0.85 };
|
|
15246
|
+
}
|
|
15247
|
+
return void 0;
|
|
15248
|
+
}
|
|
15249
|
+
function classConstant(n) {
|
|
15250
|
+
if (n.type !== "class_constant_access_expression") return void 0;
|
|
15251
|
+
const [cls, member] = n.namedChildren;
|
|
15252
|
+
if (!cls || member?.text !== "class") return void 0;
|
|
15253
|
+
const t = controllerRef(cls.text);
|
|
15254
|
+
return t?.id.startsWith("sym:") ? t : void 0;
|
|
15255
|
+
}
|
|
15256
|
+
function handlersOf(arg, caller, controller) {
|
|
15257
|
+
const handlers = [];
|
|
15258
|
+
let confidence = 0.9;
|
|
15259
|
+
const self = caller ? symId(rel, caller) : fid;
|
|
15260
|
+
const visit2 = (a) => {
|
|
15261
|
+
if (!a) return;
|
|
15262
|
+
if (a.type === "anonymous_function" || a.type === "arrow_function") {
|
|
15263
|
+
handlers.push(self);
|
|
15264
|
+
confidence = Math.min(confidence, 0.7);
|
|
15265
|
+
} else if (a.type === "class_constant_access_expression") {
|
|
15266
|
+
const t = classConstant(a);
|
|
15267
|
+
if (t) handlers.push(t.id);
|
|
15268
|
+
} else if (a.type === "string" || a.type === "encapsed_string") {
|
|
15269
|
+
const s = phpString(a) ?? "";
|
|
15270
|
+
const m = CONTROLLER_STRING.exec(s);
|
|
15271
|
+
const t = m ? controllerRef(m[1], true) : void 0;
|
|
15272
|
+
if (t && m) handlers.push(`${t.id}.${m[2]}`);
|
|
15273
|
+
else if (controller && /^\w+$/.test(s)) handlers.push(`${controller.id}.${s}`);
|
|
15274
|
+
} else if (a.type === "array_creation_expression") {
|
|
15275
|
+
const els = arrayElements(a);
|
|
15276
|
+
const [first, second] = els;
|
|
15277
|
+
const method = second && !second.key ? phpString(second.value) : void 0;
|
|
15278
|
+
const cls = first && !first.key ? classConstant(first.value) : void 0;
|
|
15279
|
+
if (els.length === 2 && cls && method) handlers.push(`${cls.id}.${method}`);
|
|
15280
|
+
else for (const el of els) if (!el.key || el.key === "uses") visit2(el.value);
|
|
15281
|
+
}
|
|
15282
|
+
};
|
|
15283
|
+
visit2(arg);
|
|
15284
|
+
if (!handlers.length) {
|
|
15285
|
+
handlers.push(self);
|
|
15286
|
+
confidence = 0.5;
|
|
15287
|
+
}
|
|
15288
|
+
return { handlers: [...new Set(handlers)], confidence };
|
|
15289
|
+
}
|
|
15290
|
+
function groupContext(n) {
|
|
15291
|
+
const prefixes = [];
|
|
15292
|
+
let controller;
|
|
15293
|
+
for (let cur = n.parent; cur; cur = cur.parent) {
|
|
15294
|
+
if (cur.type !== "anonymous_function" && cur.type !== "arrow_function") continue;
|
|
15295
|
+
const call = cur.parent?.type === "argument" ? cur.parent.parent?.parent : void 0;
|
|
15296
|
+
if (!call || !isCall(call) || call.childForFieldName("name")?.text !== "group") continue;
|
|
15297
|
+
const own2 = [];
|
|
15298
|
+
const first = argsOf(call)[0];
|
|
15299
|
+
const direct = first && first.id !== cur.id ? phpString(first) : void 0;
|
|
15300
|
+
if (direct !== void 0) own2.push(direct);
|
|
15301
|
+
else if (first?.type === "array_creation_expression") {
|
|
15302
|
+
const prefix = arrayElements(first).find((e) => e.key === "prefix");
|
|
15303
|
+
const s = prefix ? phpString(prefix.value) : void 0;
|
|
15304
|
+
if (s !== void 0) own2.push(s);
|
|
15305
|
+
}
|
|
15306
|
+
for (let link = call.childForFieldName("object"); link && isCall(link); ) {
|
|
15307
|
+
const name = link.childForFieldName("name")?.text;
|
|
15308
|
+
const a0 = argsOf(link)[0];
|
|
15309
|
+
if (name === "prefix") {
|
|
15310
|
+
const s = phpString(a0);
|
|
15311
|
+
if (s !== void 0) own2.unshift(s);
|
|
15312
|
+
} else if (name === "controller" && a0 && !controller) {
|
|
15313
|
+
const s = phpString(a0);
|
|
15314
|
+
controller = classConstant(a0) ?? (s ? controllerRef(s, true) : void 0);
|
|
15315
|
+
}
|
|
15316
|
+
link = link.childForFieldName("object");
|
|
15317
|
+
}
|
|
15318
|
+
prefixes.unshift(...own2);
|
|
15319
|
+
}
|
|
15320
|
+
return { prefixes, controller };
|
|
15321
|
+
}
|
|
15322
|
+
function laravelBase() {
|
|
15323
|
+
return /(^|\/)routes\/api\.php$/.test(rel) ? "/api" : void 0;
|
|
15324
|
+
}
|
|
15325
|
+
function routeFromCall(call, caller) {
|
|
15326
|
+
let facade = false;
|
|
15327
|
+
const chained = [];
|
|
15328
|
+
for (let link = call; link && isCall(link); ) {
|
|
15329
|
+
if (link.type === "scoped_call_expression") {
|
|
15330
|
+
facade = lastSegment(link.childForFieldName("scope")?.text ?? "") === "Route";
|
|
15331
|
+
break;
|
|
15332
|
+
}
|
|
15333
|
+
link = link.childForFieldName("object");
|
|
15334
|
+
if (link && isCall(link) && link.childForFieldName("name")?.text === "prefix") {
|
|
15335
|
+
const s = phpString(argsOf(link)[0]);
|
|
15336
|
+
if (s !== void 0) chained.unshift(s);
|
|
15337
|
+
}
|
|
15338
|
+
}
|
|
15339
|
+
const obj = call.type === "member_call_expression" ? call.childForFieldName("object") : null;
|
|
15340
|
+
const member = !facade && obj?.type === "variable_name" && obj.text !== "$this";
|
|
15341
|
+
if (!facade && !member) return;
|
|
15342
|
+
const verb = call.childForFieldName("name")?.text ?? "";
|
|
15343
|
+
const lower = verb.toLowerCase();
|
|
15344
|
+
const args = argsOf(call);
|
|
15345
|
+
if (facade && (verb === "resource" || verb === "apiResource")) {
|
|
15346
|
+
const name = phpString(args[0]);
|
|
15347
|
+
if (name) resourceRoutes(call, verb === "apiResource", name, args, caller, chained);
|
|
15348
|
+
return;
|
|
15349
|
+
}
|
|
15350
|
+
if (facade && (verb === "resources" || verb === "apiResources")) {
|
|
15351
|
+
if (args[0]?.type !== "array_creation_expression") return;
|
|
15352
|
+
for (const el of arrayElements(args[0])) {
|
|
15353
|
+
if (el.key)
|
|
15354
|
+
resourceRoutes(
|
|
15355
|
+
call,
|
|
15356
|
+
verb === "apiResources",
|
|
15357
|
+
el.key,
|
|
15358
|
+
[void 0, el.value, args[1]],
|
|
15359
|
+
caller,
|
|
15360
|
+
chained
|
|
15361
|
+
);
|
|
15362
|
+
}
|
|
15363
|
+
return;
|
|
15364
|
+
}
|
|
15365
|
+
let methods;
|
|
15366
|
+
let rest;
|
|
15367
|
+
if (facade && lower === "view") {
|
|
15368
|
+
methods = ["GET"];
|
|
15369
|
+
rest = args.slice(0, 1);
|
|
15370
|
+
} else if (facade && (lower === "redirect" || lower === "permanentredirect")) {
|
|
15371
|
+
methods = ["ALL"];
|
|
15372
|
+
rest = args.slice(0, 1);
|
|
15373
|
+
} else if (lower === "match" || lower === "map") {
|
|
15374
|
+
methods = stringsOf(args[0]).map((m) => httpMethod(m)).filter((m) => !!m);
|
|
15375
|
+
rest = args.slice(1);
|
|
15376
|
+
} else if (lower === "any") {
|
|
15377
|
+
methods = ["ALL"];
|
|
15378
|
+
rest = args;
|
|
15379
|
+
} else if (ROUTE_METHODS.has(lower) && lower !== "all") {
|
|
15380
|
+
methods = [lower.toUpperCase()];
|
|
15381
|
+
rest = args;
|
|
15382
|
+
} else return;
|
|
15383
|
+
const raw = phpString(rest[0]);
|
|
15384
|
+
if (raw === void 0 || !methods.length) return;
|
|
15385
|
+
if (member && (!handlerShaped(rest[1]) || !raw.startsWith("/") && !ROUTER_VARS.has(obj.text)))
|
|
15386
|
+
return;
|
|
15387
|
+
const ctx = groupContext(call);
|
|
15388
|
+
const { handlers, confidence } = handlersOf(rest[1], caller, ctx.controller);
|
|
15389
|
+
const path3 = phpRoutePath(facade ? laravelBase() : void 0, ...ctx.prefixes, ...chained, raw);
|
|
15390
|
+
const framework = facade ? "laravel" : frameworkOf(importedPkgs) ?? frameworkOf(auto?.require ?? []) ?? "http";
|
|
15391
|
+
for (const m of methods)
|
|
15392
|
+
addRoute(m, path3, framework, call.startPosition.row + 1, handlers, confidence);
|
|
15393
|
+
}
|
|
15394
|
+
function resourceRoutes(call, api, name, args, caller, chained) {
|
|
15395
|
+
let only;
|
|
15396
|
+
let except;
|
|
15397
|
+
if (args[2]?.type === "array_creation_expression") {
|
|
15398
|
+
for (const opt of arrayElements(args[2])) {
|
|
15399
|
+
if (opt.key === "only") only = stringsOf(opt.value);
|
|
15400
|
+
if (opt.key === "except") except = stringsOf(opt.value);
|
|
15401
|
+
}
|
|
15402
|
+
}
|
|
15403
|
+
for (let cur = call; cur.parent?.type === "member_call_expression"; cur = cur.parent) {
|
|
15404
|
+
if (cur.parent.childForFieldName("object")?.id !== cur.id) break;
|
|
15405
|
+
const m = cur.parent.childForFieldName("name")?.text;
|
|
15406
|
+
if (m === "only") only = stringsOf(argsOf(cur.parent)[0]);
|
|
15407
|
+
if (m === "except") except = stringsOf(argsOf(cur.parent)[0]);
|
|
15408
|
+
}
|
|
15409
|
+
const ctx = groupContext(call);
|
|
15410
|
+
const literal2 = phpString(args[1]);
|
|
15411
|
+
const cls = args[1] ? classConstant(args[1]) ?? (literal2 ? controllerRef(literal2, true) : void 0) : void 0;
|
|
15412
|
+
const self = caller ? symId(rel, caller) : fid;
|
|
15413
|
+
for (const spec of laravelResource(name, api, only, except)) {
|
|
15414
|
+
addRoute(
|
|
15415
|
+
spec.method,
|
|
15416
|
+
phpRoutePath(laravelBase(), ...ctx.prefixes, ...chained, spec.path),
|
|
15417
|
+
"laravel",
|
|
15418
|
+
call.startPosition.row + 1,
|
|
15419
|
+
[cls ? `${cls.id}.${spec.action}` : self],
|
|
15420
|
+
cls ? 0.9 : 0.5
|
|
15421
|
+
);
|
|
15422
|
+
}
|
|
15423
|
+
}
|
|
15424
|
+
function attributesOf(n) {
|
|
15425
|
+
return (n.childForFieldName("attributes")?.descendantsOfType("attribute") ?? []).map(
|
|
15426
|
+
(attr) => ({ attr, fq: fqcnOf(attr.namedChildren[0]?.text ?? "") })
|
|
15427
|
+
);
|
|
15428
|
+
}
|
|
15429
|
+
function routeSpecs(n) {
|
|
15430
|
+
const out = [];
|
|
15431
|
+
for (const { attr, fq } of attributesOf(n)) {
|
|
15432
|
+
const short = lastSegment(fq);
|
|
15433
|
+
if (fq.startsWith(SPATIE_ATTRIBUTES)) {
|
|
15434
|
+
const verb = short === "Any" ? "ALL" : httpMethod(short);
|
|
15435
|
+
const pos = positionalArgs(attr);
|
|
15436
|
+
const methods2 = short === "Route" ? stringsOf(namedArg(attr, "method") ?? pos.shift()).map((m) => httpMethod(m)).filter((m) => !!m) : verb ? [verb] : [];
|
|
15437
|
+
const path4 = phpString(namedArg(attr, "uri") ?? pos[0]);
|
|
15438
|
+
if (path4 === void 0) continue;
|
|
15439
|
+
for (const method of methods2) out.push({ method, path: path4, spatie: true });
|
|
15440
|
+
continue;
|
|
15441
|
+
}
|
|
15442
|
+
if (short !== "Route") continue;
|
|
15443
|
+
const path3 = phpString(namedArg(attr, "path")) ?? phpString(positionalArgs(attr)[0]);
|
|
15444
|
+
if (path3 === void 0) continue;
|
|
15445
|
+
const methods = stringsOf(namedArg(attr, "methods")).map((m) => httpMethod(m)).filter((m) => !!m);
|
|
15446
|
+
for (const method of methods.length ? methods : ["ALL"]) out.push({ method, path: path3 });
|
|
15447
|
+
}
|
|
15448
|
+
const doc = n.previousNamedSibling;
|
|
15449
|
+
if (doc?.type === "comment" && doc.text.includes("@Route"))
|
|
15450
|
+
out.push(...parseRouteAnnotations(doc.text));
|
|
15451
|
+
return out;
|
|
15452
|
+
}
|
|
15453
|
+
function attributeRoutes(cls, className) {
|
|
15454
|
+
const classSpecs = routeSpecs(cls);
|
|
15455
|
+
let prefix = classSpecs[0]?.path;
|
|
15456
|
+
const framework = frameworkOf(importedPkgs) ?? "symfony";
|
|
15457
|
+
const line = cls.startPosition.row + 1;
|
|
15458
|
+
for (const { attr, fq } of attributesOf(cls)) {
|
|
15459
|
+
if (!fq.startsWith(SPATIE_ATTRIBUTES)) continue;
|
|
15460
|
+
const short = lastSegment(fq);
|
|
15461
|
+
const pos = positionalArgs(attr);
|
|
15462
|
+
if (short === "Prefix") prefix = phpString(namedArg(attr, "prefix") ?? pos[0]) ?? prefix;
|
|
15463
|
+
if (short !== "Resource") continue;
|
|
15464
|
+
const name = phpString(namedArg(attr, "resource") ?? pos[0]);
|
|
15465
|
+
if (!name) continue;
|
|
15466
|
+
const api = (namedArg(attr, "apiResource") ?? pos[1])?.text === "true";
|
|
15467
|
+
const only = namedArg(attr, "only");
|
|
15468
|
+
const except = namedArg(attr, "except");
|
|
15469
|
+
for (const spec of laravelResource(
|
|
15470
|
+
name,
|
|
15471
|
+
api,
|
|
15472
|
+
only ? stringsOf(only) : void 0,
|
|
15473
|
+
except ? stringsOf(except) : void 0
|
|
15474
|
+
))
|
|
15475
|
+
addRoute(
|
|
15476
|
+
spec.method,
|
|
15477
|
+
phpRoutePath(prefix, spec.path),
|
|
15478
|
+
"laravel",
|
|
15479
|
+
line,
|
|
15480
|
+
[symId(rel, `${className}.${spec.action}`)],
|
|
15481
|
+
0.95
|
|
15482
|
+
);
|
|
15483
|
+
}
|
|
15484
|
+
for (const m of cls.childForFieldName("body")?.namedChildren ?? []) {
|
|
15485
|
+
if (m?.type !== "method_declaration") continue;
|
|
15486
|
+
const mname = m.childForFieldName("name")?.text;
|
|
15487
|
+
if (!mname) continue;
|
|
15488
|
+
const specs = routeSpecs(m);
|
|
15489
|
+
if (!specs.length && mname === "__invoke" && classSpecs.length) {
|
|
15490
|
+
for (const s of classSpecs)
|
|
15491
|
+
addRoute(
|
|
15492
|
+
s.method,
|
|
15493
|
+
phpRoutePath(s.path),
|
|
15494
|
+
framework,
|
|
15495
|
+
line,
|
|
15496
|
+
[symId(rel, `${className}.${mname}`)],
|
|
15497
|
+
0.95
|
|
15498
|
+
);
|
|
15499
|
+
continue;
|
|
15500
|
+
}
|
|
15501
|
+
for (const s of specs) {
|
|
15502
|
+
addRoute(
|
|
15503
|
+
s.method,
|
|
15504
|
+
phpRoutePath(prefix, s.path),
|
|
15505
|
+
s.spatie ? "laravel" : framework,
|
|
15506
|
+
m.startPosition.row + 1,
|
|
15507
|
+
[symId(rel, `${className}.${mname}`)],
|
|
15508
|
+
0.95
|
|
15509
|
+
);
|
|
15510
|
+
}
|
|
15511
|
+
}
|
|
15512
|
+
}
|
|
15513
|
+
function walkRefs(n) {
|
|
15514
|
+
noteVarTypes(n);
|
|
15515
|
+
for (const call of n.descendantsOfType(CALLS)) {
|
|
15516
|
+
const caller = enclosing(call);
|
|
15517
|
+
routeFromCall(call, caller);
|
|
15518
|
+
const target = callTarget(call, caller);
|
|
15519
|
+
if (!target) continue;
|
|
15520
|
+
refs.push(
|
|
15521
|
+
caller ? symId(rel, caller) : fid,
|
|
15522
|
+
target.id,
|
|
15523
|
+
"calls",
|
|
15524
|
+
target.confidence,
|
|
15525
|
+
call.startPosition.row + 1
|
|
15526
|
+
);
|
|
15527
|
+
}
|
|
15528
|
+
const named = [];
|
|
15529
|
+
for (const t of n.descendantsOfType("named_type")) named.push(t);
|
|
15530
|
+
for (const a of n.descendantsOfType([
|
|
15531
|
+
"class_constant_access_expression",
|
|
15532
|
+
"scoped_property_access_expression"
|
|
15533
|
+
])) {
|
|
15534
|
+
const s = a.namedChildren[0];
|
|
15535
|
+
if (s && (s.type === "name" || s.type === "qualified_name")) named.push(s);
|
|
15536
|
+
}
|
|
15537
|
+
for (const b of n.descendantsOfType("binary_expression")) {
|
|
15538
|
+
const right = b.childForFieldName("right");
|
|
15539
|
+
if (b.childForFieldName("operator")?.type === "instanceof" && right) named.push(right);
|
|
15540
|
+
}
|
|
15541
|
+
for (const t of named) {
|
|
15542
|
+
const target = classRef(t.text);
|
|
15543
|
+
if (!target) continue;
|
|
15544
|
+
const caller = enclosing(t);
|
|
15545
|
+
refs.push(
|
|
15546
|
+
caller ? symId(rel, caller) : fid,
|
|
15547
|
+
target.id,
|
|
15548
|
+
"references",
|
|
15549
|
+
target.confidence * 0.9,
|
|
15550
|
+
t.startPosition.row + 1
|
|
15551
|
+
);
|
|
15552
|
+
}
|
|
15553
|
+
for (const me of n.descendantsOfType([
|
|
15554
|
+
"member_access_expression",
|
|
15555
|
+
"nullsafe_member_access_expression"
|
|
15556
|
+
])) {
|
|
15557
|
+
if (me.childForFieldName("object")?.text !== "$this") continue;
|
|
15558
|
+
const caller = enclosing(me);
|
|
15559
|
+
const cls = classOf(caller);
|
|
15560
|
+
const prop = me.childForFieldName("name")?.text;
|
|
15561
|
+
if (!cls || !prop || !localSyms.has(`${cls}.${prop}`)) continue;
|
|
15562
|
+
refs.push(
|
|
15563
|
+
symId(rel, caller),
|
|
15564
|
+
symId(rel, `${cls}.${prop}`),
|
|
15565
|
+
"references",
|
|
15566
|
+
0.81,
|
|
15567
|
+
me.startPosition.row + 1
|
|
15568
|
+
);
|
|
15569
|
+
}
|
|
15570
|
+
}
|
|
15571
|
+
}
|
|
15572
|
+
var BRANCHES2, BOOL_OPS2, CALLS, CLASS_KINDS, RELATIVE, ROUTER_VARS, CONTROLLER_NAMESPACES, SPATIE_ATTRIBUTES, isFile, toRel, CLASSMAP_MAX_FILES, composerCache, asList, CONTROLLER_STRING, isPublic, classOf, lastSegment, isCall;
|
|
15573
|
+
var init_php = __esm({
|
|
15574
|
+
"src/graph/languages/php.ts"() {
|
|
15575
|
+
"use strict";
|
|
15576
|
+
init_esm_shims();
|
|
15577
|
+
init_ids();
|
|
15578
|
+
init_routes();
|
|
15579
|
+
init_parser();
|
|
15580
|
+
BRANCHES2 = [
|
|
15581
|
+
"if_statement",
|
|
15582
|
+
"else_if_clause",
|
|
15583
|
+
"for_statement",
|
|
15584
|
+
"foreach_statement",
|
|
15585
|
+
"while_statement",
|
|
15586
|
+
"do_statement",
|
|
15587
|
+
"case_statement",
|
|
15588
|
+
"catch_clause",
|
|
15589
|
+
"conditional_expression",
|
|
15590
|
+
"match_conditional_expression",
|
|
15591
|
+
"binary_expression"
|
|
15592
|
+
];
|
|
15593
|
+
BOOL_OPS2 = /* @__PURE__ */ new Set(["&&", "||", "and", "or", "??"]);
|
|
15594
|
+
CALLS = [
|
|
15595
|
+
"function_call_expression",
|
|
15596
|
+
"member_call_expression",
|
|
15597
|
+
"nullsafe_member_call_expression",
|
|
15598
|
+
"scoped_call_expression",
|
|
15599
|
+
"object_creation_expression"
|
|
15600
|
+
];
|
|
15601
|
+
CLASS_KINDS = {
|
|
15602
|
+
class_declaration: "class",
|
|
15603
|
+
interface_declaration: "interface",
|
|
15604
|
+
trait_declaration: "trait",
|
|
15605
|
+
enum_declaration: "enum"
|
|
15606
|
+
};
|
|
15607
|
+
RELATIVE = /* @__PURE__ */ new Set(["self", "static", "parent"]);
|
|
15608
|
+
ROUTER_VARS = /* @__PURE__ */ new Set(["$app", "$router", "$routes", "$route", "$group", "$r"]);
|
|
15609
|
+
CONTROLLER_NAMESPACES = ["App\\Http\\Controllers", "App\\Controllers"];
|
|
15610
|
+
SPATIE_ATTRIBUTES = "Spatie\\RouteAttributes\\Attributes\\";
|
|
15611
|
+
isFile = (p) => {
|
|
15612
|
+
try {
|
|
15613
|
+
return statSync(p).isFile();
|
|
15614
|
+
} catch {
|
|
15615
|
+
return false;
|
|
15616
|
+
}
|
|
15617
|
+
};
|
|
15618
|
+
toRel = (root, abs) => normalize2(relative2(root, abs)).split("\\").join("/");
|
|
15619
|
+
CLASSMAP_MAX_FILES = 5e3;
|
|
15620
|
+
composerCache = /* @__PURE__ */ new Map();
|
|
15621
|
+
asList = (v) => Array.isArray(v) ? v : [v];
|
|
15622
|
+
CONTROLLER_STRING = /^\\?([\w\\]+?)(?:@|::?)(\w+)$/;
|
|
15623
|
+
isPublic = (m) => !m.namedChildren.some((c) => c?.type === "visibility_modifier" && c.text !== "public");
|
|
15624
|
+
classOf = (caller) => caller?.includes(".") ? caller.split(".")[0] : void 0;
|
|
15625
|
+
lastSegment = (name) => name.split("\\").pop() ?? name;
|
|
15626
|
+
isCall = (n) => n.type === "member_call_expression" || n.type === "scoped_call_expression";
|
|
15627
|
+
}
|
|
15628
|
+
});
|
|
15629
|
+
|
|
15630
|
+
// src/graph/languages/python.ts
|
|
15631
|
+
import { existsSync as existsSync5, statSync as statSync2 } from "fs";
|
|
15632
|
+
import { dirname as dirname5, join as join8, normalize as normalize3, relative as relative3, resolve as resolve4 } from "path";
|
|
14509
15633
|
function resolvePython(root, fromRel, module, level) {
|
|
14510
15634
|
const parts = module ? module.split(".") : [];
|
|
14511
15635
|
const candidates2 = [];
|
|
14512
15636
|
if (level > 0) {
|
|
14513
|
-
let base =
|
|
14514
|
-
for (let i = 1; i < level; i++) base =
|
|
14515
|
-
candidates2.push(
|
|
15637
|
+
let base = dirname5(resolve4(root, fromRel));
|
|
15638
|
+
for (let i = 1; i < level; i++) base = dirname5(base);
|
|
15639
|
+
candidates2.push(join8(base, ...parts));
|
|
14516
15640
|
} else {
|
|
14517
|
-
candidates2.push(
|
|
14518
|
-
let dir =
|
|
15641
|
+
candidates2.push(resolve4(root, ...parts), resolve4(root, "src", ...parts));
|
|
15642
|
+
let dir = dirname5(resolve4(root, fromRel));
|
|
14519
15643
|
while (dir.startsWith(root) && dir !== root) {
|
|
14520
|
-
candidates2.push(
|
|
14521
|
-
dir =
|
|
15644
|
+
candidates2.push(join8(dir, ...parts));
|
|
15645
|
+
dir = dirname5(dir);
|
|
14522
15646
|
}
|
|
14523
15647
|
}
|
|
14524
15648
|
for (const c of candidates2) {
|
|
14525
|
-
for (const f of [`${c}.py`,
|
|
14526
|
-
if (
|
|
14527
|
-
return
|
|
15649
|
+
for (const f of [`${c}.py`, join8(c, "__init__.py"), `${c}.pyi`]) {
|
|
15650
|
+
if (isFile2(f) && !relative3(root, f).startsWith(".."))
|
|
15651
|
+
return normalize3(relative3(root, f)).split("\\").join("/");
|
|
14528
15652
|
}
|
|
14529
15653
|
}
|
|
14530
15654
|
return void 0;
|
|
@@ -14561,7 +15685,7 @@ async function parsePython(root, rel, code) {
|
|
|
14561
15685
|
walkRefs(stmt);
|
|
14562
15686
|
}
|
|
14563
15687
|
edges.push(...refs.edges());
|
|
14564
|
-
if (!existsSync5(
|
|
15688
|
+
if (!existsSync5(join8(root, rel))) {
|
|
14565
15689
|
}
|
|
14566
15690
|
const errors = tree.rootNode.hasError ? tree.rootNode.descendantsOfType("ERROR").length : 0;
|
|
14567
15691
|
fileNode.meta = {
|
|
@@ -14714,7 +15838,7 @@ async function parsePython(root, rel, code) {
|
|
|
14714
15838
|
}
|
|
14715
15839
|
function addSym(qualified, kind, n, exported) {
|
|
14716
15840
|
const id = symId(rel, qualified);
|
|
14717
|
-
const c = kind === "function" || kind === "method" ? complexityOf(n,
|
|
15841
|
+
const c = kind === "function" || kind === "method" ? complexityOf(n, BRANCHES3, BOOL_OPS3) : 0;
|
|
14718
15842
|
complexity += c;
|
|
14719
15843
|
nodes.push({
|
|
14720
15844
|
id,
|
|
@@ -14857,7 +15981,7 @@ async function parsePython(root, rel, code) {
|
|
|
14857
15981
|
}
|
|
14858
15982
|
}
|
|
14859
15983
|
}
|
|
14860
|
-
var
|
|
15984
|
+
var BRANCHES3, BOOL_OPS3, isFile2, topModule, REF_SKIP_PARENT;
|
|
14861
15985
|
var init_python = __esm({
|
|
14862
15986
|
"src/graph/languages/python.ts"() {
|
|
14863
15987
|
"use strict";
|
|
@@ -14865,7 +15989,7 @@ var init_python = __esm({
|
|
|
14865
15989
|
init_ids();
|
|
14866
15990
|
init_routes();
|
|
14867
15991
|
init_parser();
|
|
14868
|
-
|
|
15992
|
+
BRANCHES3 = [
|
|
14869
15993
|
"if_statement",
|
|
14870
15994
|
"elif_clause",
|
|
14871
15995
|
"for_statement",
|
|
@@ -14876,10 +16000,10 @@ var init_python = __esm({
|
|
|
14876
16000
|
"case_clause",
|
|
14877
16001
|
"for_in_clause"
|
|
14878
16002
|
];
|
|
14879
|
-
|
|
14880
|
-
|
|
16003
|
+
BOOL_OPS3 = /* @__PURE__ */ new Set(["and", "or"]);
|
|
16004
|
+
isFile2 = (p) => {
|
|
14881
16005
|
try {
|
|
14882
|
-
return
|
|
16006
|
+
return statSync2(p).isFile();
|
|
14883
16007
|
} catch {
|
|
14884
16008
|
return false;
|
|
14885
16009
|
}
|
|
@@ -14908,21 +16032,21 @@ var init_python = __esm({
|
|
|
14908
16032
|
});
|
|
14909
16033
|
|
|
14910
16034
|
// src/graph/resolve.ts
|
|
14911
|
-
import { existsSync as existsSync6, readdirSync as
|
|
14912
|
-
import { dirname as
|
|
16035
|
+
import { existsSync as existsSync6, readdirSync as readdirSync3, readFileSync as readFileSync5, statSync as statSync3 } from "fs";
|
|
16036
|
+
import { dirname as dirname6, join as join9, normalize as normalize4, relative as relative4, resolve as resolve5 } from "path";
|
|
14913
16037
|
function loadTsPaths(root) {
|
|
14914
16038
|
const hit = tsPathsCache.get(root);
|
|
14915
16039
|
if (hit !== void 0) return hit;
|
|
14916
16040
|
let out = null;
|
|
14917
16041
|
try {
|
|
14918
|
-
const file3 =
|
|
16042
|
+
const file3 = join9(root, "tsconfig.json");
|
|
14919
16043
|
if (existsSync6(file3)) {
|
|
14920
|
-
const raw =
|
|
16044
|
+
const raw = readFileSync5(file3, "utf8").replace(/\/\*[\s\S]*?\*\//g, "").replace(/^\s*\/\/.*$/gm, "").replace(/,(\s*[}\]])/g, "$1");
|
|
14921
16045
|
const cfg = JSON.parse(raw);
|
|
14922
16046
|
const co = cfg.compilerOptions ?? {};
|
|
14923
16047
|
if (co.paths) {
|
|
14924
16048
|
out = {
|
|
14925
|
-
baseUrl:
|
|
16049
|
+
baseUrl: resolve5(root, co.baseUrl ?? "."),
|
|
14926
16050
|
paths: Object.entries(co.paths).map(([k, v]) => {
|
|
14927
16051
|
const star = k.indexOf("*");
|
|
14928
16052
|
return star === -1 ? { prefix: k, suffix: "\0", targets: v } : { prefix: k.slice(0, star), suffix: k.slice(star + 1), targets: v };
|
|
@@ -14939,7 +16063,7 @@ function loadTsPaths(root) {
|
|
|
14939
16063
|
function probe(abs) {
|
|
14940
16064
|
const tryFile = (p) => {
|
|
14941
16065
|
try {
|
|
14942
|
-
return
|
|
16066
|
+
return statSync3(p).isFile() ? p : void 0;
|
|
14943
16067
|
} catch {
|
|
14944
16068
|
return void 0;
|
|
14945
16069
|
}
|
|
@@ -14955,16 +16079,16 @@ function probe(abs) {
|
|
|
14955
16079
|
if (tryFile(abs + ext)) return abs + ext;
|
|
14956
16080
|
}
|
|
14957
16081
|
for (const ext of EXTS) {
|
|
14958
|
-
const idx =
|
|
16082
|
+
const idx = join9(abs, `index${ext}`);
|
|
14959
16083
|
if (tryFile(idx)) return idx;
|
|
14960
16084
|
}
|
|
14961
16085
|
return void 0;
|
|
14962
16086
|
}
|
|
14963
16087
|
function readPackageJson(dir) {
|
|
14964
16088
|
try {
|
|
14965
|
-
const file3 =
|
|
16089
|
+
const file3 = join9(dir, "package.json");
|
|
14966
16090
|
if (!existsSync6(file3)) return void 0;
|
|
14967
|
-
return JSON.parse(
|
|
16091
|
+
return JSON.parse(readFileSync5(file3, "utf8"));
|
|
14968
16092
|
} catch {
|
|
14969
16093
|
return void 0;
|
|
14970
16094
|
}
|
|
@@ -14980,9 +16104,9 @@ function loadWorkspaces(root) {
|
|
|
14980
16104
|
if (Array.isArray(ws)) globs.push(...ws);
|
|
14981
16105
|
else if (ws?.packages) globs.push(...ws.packages);
|
|
14982
16106
|
try {
|
|
14983
|
-
const yaml =
|
|
16107
|
+
const yaml = join9(root, "pnpm-workspace.yaml");
|
|
14984
16108
|
if (existsSync6(yaml)) {
|
|
14985
|
-
for (const m of
|
|
16109
|
+
for (const m of readFileSync5(yaml, "utf8").matchAll(/^\s*-\s*['"]?([^'"\n#]+?)['"]?\s*$/gm))
|
|
14986
16110
|
globs.push(m[1].trim());
|
|
14987
16111
|
}
|
|
14988
16112
|
} catch {
|
|
@@ -14991,12 +16115,12 @@ function loadWorkspaces(root) {
|
|
|
14991
16115
|
if (g.startsWith("!")) continue;
|
|
14992
16116
|
const star = g.indexOf("*");
|
|
14993
16117
|
const dirs = [];
|
|
14994
|
-
if (star === -1) dirs.push(
|
|
16118
|
+
if (star === -1) dirs.push(resolve5(root, g));
|
|
14995
16119
|
else {
|
|
14996
|
-
const base =
|
|
16120
|
+
const base = resolve5(root, g.slice(0, star));
|
|
14997
16121
|
try {
|
|
14998
|
-
for (const d of
|
|
14999
|
-
if (d.isDirectory()) dirs.push(
|
|
16122
|
+
for (const d of readdirSync3(base, { withFileTypes: true })) {
|
|
16123
|
+
if (d.isDirectory()) dirs.push(join9(base, d.name));
|
|
15000
16124
|
}
|
|
15001
16125
|
} catch {
|
|
15002
16126
|
}
|
|
@@ -15050,16 +16174,16 @@ function resolvePackageEntry(dir, sub) {
|
|
|
15050
16174
|
} else candidates2.push(sub, `src/${sub}`, `lib/${sub}`);
|
|
15051
16175
|
for (const c of candidates2) {
|
|
15052
16176
|
if (c.includes("*")) continue;
|
|
15053
|
-
const hit = probe(
|
|
16177
|
+
const hit = probe(resolve5(dir, c));
|
|
15054
16178
|
if (hit) return hit;
|
|
15055
16179
|
}
|
|
15056
16180
|
return void 0;
|
|
15057
16181
|
}
|
|
15058
16182
|
function resolveImport(root, fromRel, spec) {
|
|
15059
16183
|
if (spec.startsWith(".") || spec.startsWith("/")) {
|
|
15060
|
-
const abs = spec.startsWith("/") ? spec :
|
|
16184
|
+
const abs = spec.startsWith("/") ? spec : resolve5(root, dirname6(fromRel), spec);
|
|
15061
16185
|
const hit = probe(abs);
|
|
15062
|
-
return hit ?
|
|
16186
|
+
return hit ? normalize4(relative4(root, hit)) : void 0;
|
|
15063
16187
|
}
|
|
15064
16188
|
const tp = loadTsPaths(root);
|
|
15065
16189
|
if (tp) {
|
|
@@ -15068,8 +16192,8 @@ function resolveImport(root, fromRel, spec) {
|
|
|
15068
16192
|
if (exact ? spec === p.prefix : spec.startsWith(p.prefix) && spec.endsWith(p.suffix)) {
|
|
15069
16193
|
const star = exact ? "" : spec.slice(p.prefix.length, spec.length - p.suffix.length);
|
|
15070
16194
|
for (const t of p.targets) {
|
|
15071
|
-
const hit = probe(
|
|
15072
|
-
if (hit) return
|
|
16195
|
+
const hit = probe(resolve5(tp.baseUrl, t.replace("*", star)));
|
|
16196
|
+
if (hit) return normalize4(relative4(root, hit));
|
|
15073
16197
|
}
|
|
15074
16198
|
}
|
|
15075
16199
|
}
|
|
@@ -15078,7 +16202,7 @@ function resolveImport(root, fromRel, spec) {
|
|
|
15078
16202
|
const dir = loadWorkspaces(root).get(name);
|
|
15079
16203
|
if (dir) {
|
|
15080
16204
|
const hit = resolvePackageEntry(dir, spec.slice(name.length + 1));
|
|
15081
|
-
if (hit && !
|
|
16205
|
+
if (hit && !relative4(root, hit).startsWith("..")) return normalize4(relative4(root, hit));
|
|
15082
16206
|
}
|
|
15083
16207
|
return void 0;
|
|
15084
16208
|
}
|
|
@@ -15142,6 +16266,7 @@ async function parseFile(root, rel, code) {
|
|
|
15142
16266
|
if (!grammar) return { nodes: [], edges: [], exports: [] };
|
|
15143
16267
|
if (grammar === "python") return parsePython(root, rel, code);
|
|
15144
16268
|
if (grammar === "go") return parseGo(root, rel, code);
|
|
16269
|
+
if (grammar === "php") return parsePhp(root, rel, code);
|
|
15145
16270
|
const p = await getParser(grammar);
|
|
15146
16271
|
const tree = p.parse(code);
|
|
15147
16272
|
if (!tree) return { nodes: [], edges: [], exports: [] };
|
|
@@ -15734,6 +16859,7 @@ var init_treesitter = __esm({
|
|
|
15734
16859
|
init_ids();
|
|
15735
16860
|
init_go();
|
|
15736
16861
|
init_parser();
|
|
16862
|
+
init_php();
|
|
15737
16863
|
init_python();
|
|
15738
16864
|
init_resolve();
|
|
15739
16865
|
init_routes();
|
|
@@ -15822,8 +16948,8 @@ __export(indexer_exports, {
|
|
|
15822
16948
|
indexContent: () => indexContent,
|
|
15823
16949
|
indexPath: () => indexPath
|
|
15824
16950
|
});
|
|
15825
|
-
import { readFileSync as
|
|
15826
|
-
import { relative as
|
|
16951
|
+
import { readFileSync as readFileSync6, statSync as statSync4 } from "fs";
|
|
16952
|
+
import { relative as relative5, resolve as resolve6 } from "path";
|
|
15827
16953
|
function indexContent(db, input2) {
|
|
15828
16954
|
const kind = input2.kind ?? (input2.contentType === "code" ? "code" : input2.contentType === "json" ? "json" : void 0);
|
|
15829
16955
|
const { chunks, kind: k } = input2.chunks ? { chunks: finalize2(input2.chunks, input2.contentType ?? "code"), kind: kind ?? "code" } : chunk(input2.content, input2.title, kind, input2.uri);
|
|
@@ -15856,9 +16982,9 @@ function indexContent(db, input2) {
|
|
|
15856
16982
|
return { documentId: id, created, chunks: chunks.length, chars: input2.content.length, kind: k };
|
|
15857
16983
|
}
|
|
15858
16984
|
function indexPath(db, root, target, opts = {}) {
|
|
15859
|
-
const abs =
|
|
16985
|
+
const abs = resolve6(root, target);
|
|
15860
16986
|
const summary = { files: 0, indexed: 0, unchanged: 0, skipped: [], chunks: 0 };
|
|
15861
|
-
const st =
|
|
16987
|
+
const st = statSync4(abs);
|
|
15862
16988
|
const files = st.isDirectory() ? import_fast_glob.default.sync(opts.globs ?? ["**/*.md"], {
|
|
15863
16989
|
cwd: abs,
|
|
15864
16990
|
absolute: true,
|
|
@@ -15869,14 +16995,14 @@ function indexPath(db, root, target, opts = {}) {
|
|
|
15869
16995
|
}) : [abs];
|
|
15870
16996
|
for (const file3 of files) {
|
|
15871
16997
|
summary.files++;
|
|
15872
|
-
const rel =
|
|
16998
|
+
const rel = relative5(root, file3) || file3;
|
|
15873
16999
|
try {
|
|
15874
|
-
const size =
|
|
17000
|
+
const size = statSync4(file3).size;
|
|
15875
17001
|
if (size > MAX_FILE_BYTES) {
|
|
15876
17002
|
summary.skipped.push({ path: rel, reason: `too large (${size} bytes)` });
|
|
15877
17003
|
continue;
|
|
15878
17004
|
}
|
|
15879
|
-
const content =
|
|
17005
|
+
const content = readFileSync6(file3, "utf8");
|
|
15880
17006
|
if (content.includes("\0")) {
|
|
15881
17007
|
summary.skipped.push({ path: rel, reason: "binary" });
|
|
15882
17008
|
continue;
|
|
@@ -16094,6 +17220,11 @@ function inherited(db, classId, member, depth) {
|
|
|
16094
17220
|
}
|
|
16095
17221
|
return void 0;
|
|
16096
17222
|
}
|
|
17223
|
+
function ownerAncestor(db, path3, name) {
|
|
17224
|
+
const dot = name.indexOf(".");
|
|
17225
|
+
const owner = symId(path3, name.slice(0, dot));
|
|
17226
|
+
return db.graphGetNode(owner) ? inherited(db, owner, name.slice(dot + 1), 0) : void 0;
|
|
17227
|
+
}
|
|
16097
17228
|
function defaultExportOf(db, path3) {
|
|
16098
17229
|
const f = db.graphGetNode(fileId(path3));
|
|
16099
17230
|
if (!f?.meta) return void 0;
|
|
@@ -16142,6 +17273,10 @@ function linkGraph(db) {
|
|
|
16142
17273
|
direct = true;
|
|
16143
17274
|
} else target = goSibling(db, path3, head);
|
|
16144
17275
|
}
|
|
17276
|
+
if (!target && name.includes(".")) {
|
|
17277
|
+
target = ownerAncestor(db, path3, name);
|
|
17278
|
+
direct = true;
|
|
17279
|
+
}
|
|
16145
17280
|
if (target && name.includes(".") && !direct) {
|
|
16146
17281
|
const rest2 = name.slice(name.indexOf(".") + 1);
|
|
16147
17282
|
const member = `${target}.${rest2}`;
|
|
@@ -16180,7 +17315,7 @@ function linkGraph(db) {
|
|
|
16180
17315
|
const name = meta4.unresolved;
|
|
16181
17316
|
if (!name) continue;
|
|
16182
17317
|
const id = symId(e.dst.slice(5), name);
|
|
16183
|
-
const target = db.graphGetNode(id) ? id : viaReexports(db, e.dst.slice(5), name.split(".")[0], 0, /* @__PURE__ */ new Set());
|
|
17318
|
+
const target = db.graphGetNode(id) ? id : viaReexports(db, e.dst.slice(5), name.split(".")[0], 0, /* @__PURE__ */ new Set()) ?? (name.includes(".") ? ownerAncestor(db, e.dst.slice(5), name) : void 0);
|
|
16184
17319
|
if (!target || target === e.src) continue;
|
|
16185
17320
|
const { unresolved: _u, ...rest } = meta4;
|
|
16186
17321
|
replace(db, e, {
|
|
@@ -16503,6 +17638,7 @@ var init_metrics = __esm({
|
|
|
16503
17638
|
"class",
|
|
16504
17639
|
"method",
|
|
16505
17640
|
"interface",
|
|
17641
|
+
"trait",
|
|
16506
17642
|
"type",
|
|
16507
17643
|
"enum",
|
|
16508
17644
|
"field",
|
|
@@ -16532,8 +17668,8 @@ __export(reindex_exports, {
|
|
|
16532
17668
|
reindexCode: () => reindexCode,
|
|
16533
17669
|
reindexGitSignals: () => reindexGitSignals
|
|
16534
17670
|
});
|
|
16535
|
-
import { readFileSync as
|
|
16536
|
-
import { join as
|
|
17671
|
+
import { readFileSync as readFileSync7, statSync as statSync5 } from "fs";
|
|
17672
|
+
import { join as join10 } from "path";
|
|
16537
17673
|
function listCodeFiles(ctx) {
|
|
16538
17674
|
return import_fast_glob2.default.sync(ctx.config.graph.include, {
|
|
16539
17675
|
cwd: ctx.root,
|
|
@@ -16544,8 +17680,8 @@ function listCodeFiles(ctx) {
|
|
|
16544
17680
|
});
|
|
16545
17681
|
}
|
|
16546
17682
|
async function indexOne(ctx, db, rel, force) {
|
|
16547
|
-
const abs =
|
|
16548
|
-
const st =
|
|
17683
|
+
const abs = join10(ctx.root, rel);
|
|
17684
|
+
const st = statSync5(abs);
|
|
16549
17685
|
const backend = getCodeBackend(ctx);
|
|
16550
17686
|
const language = backend.languageOf(rel) ?? null;
|
|
16551
17687
|
if (st.size > MAX_CODE_BYTES) {
|
|
@@ -16564,7 +17700,7 @@ async function indexOne(ctx, db, rel, force) {
|
|
|
16564
17700
|
}
|
|
16565
17701
|
return "skipped";
|
|
16566
17702
|
}
|
|
16567
|
-
const code =
|
|
17703
|
+
const code = readFileSync7(abs, "utf8");
|
|
16568
17704
|
const hash2 = hashText(code);
|
|
16569
17705
|
const prev = db.fileIndexGet(rel);
|
|
16570
17706
|
if (!force && prev?.hash === hash2 && prev.status !== "skipped") return "unchanged";
|
|
@@ -16645,7 +17781,7 @@ async function reindexCode(ctx, db, opts = {}) {
|
|
|
16645
17781
|
summary.unsupported++;
|
|
16646
17782
|
if (db.fileIndexGet(rel)?.status === "unsupported") continue;
|
|
16647
17783
|
try {
|
|
16648
|
-
const st =
|
|
17784
|
+
const st = statSync5(join10(ctx.root, rel));
|
|
16649
17785
|
db.fileIndexSet({
|
|
16650
17786
|
path: rel,
|
|
16651
17787
|
hash: "",
|
|
@@ -16661,7 +17797,7 @@ async function reindexCode(ctx, db, opts = {}) {
|
|
|
16661
17797
|
}
|
|
16662
17798
|
for (const rel of targets) {
|
|
16663
17799
|
try {
|
|
16664
|
-
if (!statSafe(
|
|
17800
|
+
if (!statSafe(join10(ctx.root, rel))) {
|
|
16665
17801
|
if (db.fileIndexGet(rel)) {
|
|
16666
17802
|
removeOne(db, rel);
|
|
16667
17803
|
summary.removed++;
|
|
@@ -16673,7 +17809,7 @@ async function reindexCode(ctx, db, opts = {}) {
|
|
|
16673
17809
|
const error62 = err.message;
|
|
16674
17810
|
summary.errors.push({ path: rel, error: error62 });
|
|
16675
17811
|
try {
|
|
16676
|
-
const st =
|
|
17812
|
+
const st = statSync5(join10(ctx.root, rel));
|
|
16677
17813
|
db.fileIndexSet({
|
|
16678
17814
|
path: rel,
|
|
16679
17815
|
hash: "",
|
|
@@ -16736,7 +17872,7 @@ async function reindexCode(ctx, db, opts = {}) {
|
|
|
16736
17872
|
}
|
|
16737
17873
|
function statSafe(p) {
|
|
16738
17874
|
try {
|
|
16739
|
-
return
|
|
17875
|
+
return statSync5(p).isFile();
|
|
16740
17876
|
} catch {
|
|
16741
17877
|
return false;
|
|
16742
17878
|
}
|
|
@@ -16776,10 +17912,10 @@ function indexFreshness(ctx, db) {
|
|
|
16776
17912
|
const dirty = [];
|
|
16777
17913
|
for (const r of rows.slice(0, 400)) {
|
|
16778
17914
|
try {
|
|
16779
|
-
const abs =
|
|
16780
|
-
const st =
|
|
17915
|
+
const abs = join10(ctx.root, r.path);
|
|
17916
|
+
const st = statSync5(abs);
|
|
16781
17917
|
if (r.mtime !== null && Math.abs(st.mtimeMs - r.mtime) < 1 && st.size === r.size) continue;
|
|
16782
|
-
if (hashText(
|
|
17918
|
+
if (hashText(readFileSync7(abs, "utf8")) !== r.hash) dirty.push(r.path);
|
|
16783
17919
|
} catch {
|
|
16784
17920
|
dirty.push(r.path);
|
|
16785
17921
|
}
|
|
@@ -16899,13 +18035,13 @@ __export(store_exports, {
|
|
|
16899
18035
|
import {
|
|
16900
18036
|
existsSync as existsSync8,
|
|
16901
18037
|
mkdirSync as mkdirSync3,
|
|
16902
|
-
readFileSync as
|
|
18038
|
+
readFileSync as readFileSync8,
|
|
16903
18039
|
renameSync,
|
|
16904
|
-
statSync as
|
|
18040
|
+
statSync as statSync6,
|
|
16905
18041
|
unlinkSync,
|
|
16906
18042
|
writeFileSync as writeFileSync2
|
|
16907
18043
|
} from "fs";
|
|
16908
|
-
import { dirname as
|
|
18044
|
+
import { dirname as dirname7, join as join12, relative as relative6, sep } from "path";
|
|
16909
18045
|
function isStatus(s) {
|
|
16910
18046
|
return typeof s === "string" && MEMORY_STATUSES.includes(s);
|
|
16911
18047
|
}
|
|
@@ -16919,16 +18055,16 @@ function memoriesRel(ctx) {
|
|
|
16919
18055
|
return ctx.config.memories.dir.replace(/^\.\//, "").replace(/\/+$/, "");
|
|
16920
18056
|
}
|
|
16921
18057
|
function memoriesDir(ctx) {
|
|
16922
|
-
return
|
|
18058
|
+
return join12(ctx.root, memoriesRel(ctx));
|
|
16923
18059
|
}
|
|
16924
18060
|
function relOf(ctx, name) {
|
|
16925
18061
|
return `${memoriesRel(ctx)}/${name}.md`;
|
|
16926
18062
|
}
|
|
16927
18063
|
function absOf(ctx, name) {
|
|
16928
|
-
return
|
|
18064
|
+
return join12(ctx.root, relOf(ctx, name));
|
|
16929
18065
|
}
|
|
16930
18066
|
function nameOfFile(ctx, abs) {
|
|
16931
|
-
const rel =
|
|
18067
|
+
const rel = relative6(memoriesDir(ctx), abs).split(sep).join("/");
|
|
16932
18068
|
if (!rel.endsWith(".md")) return void 0;
|
|
16933
18069
|
const name = rel.slice(0, -3);
|
|
16934
18070
|
return isValidName(name) ? name : void 0;
|
|
@@ -16967,7 +18103,7 @@ function normalizeRelated(ids) {
|
|
|
16967
18103
|
}
|
|
16968
18104
|
function writeMemoryFile(ctx, name, meta4, body) {
|
|
16969
18105
|
const abs = absOf(ctx, name);
|
|
16970
|
-
mkdirSync3(
|
|
18106
|
+
mkdirSync3(dirname7(abs), { recursive: true });
|
|
16971
18107
|
writeFileSync2(abs, serializeMemoryFile(meta4, `
|
|
16972
18108
|
${body.trim()}
|
|
16973
18109
|
`));
|
|
@@ -17012,12 +18148,12 @@ function syncFile(ctx, db, name, opts = {}) {
|
|
|
17012
18148
|
const abs = absOf(ctx, name);
|
|
17013
18149
|
const rel = relOf(ctx, name);
|
|
17014
18150
|
if (!existsSync8(abs)) return void 0;
|
|
17015
|
-
let st =
|
|
18151
|
+
let st = statSync6(abs);
|
|
17016
18152
|
const row = db.memoryGetByName(name);
|
|
17017
18153
|
const mtime = Math.floor(st.mtimeMs);
|
|
17018
18154
|
if (!opts.force && row && row.file_mtime === mtime && row.file_size === st.size)
|
|
17019
18155
|
return { changed: false, row };
|
|
17020
|
-
let text2 =
|
|
18156
|
+
let text2 = readFileSync8(abs, "utf8");
|
|
17021
18157
|
let hash2 = hashText(text2);
|
|
17022
18158
|
if (!opts.force && row && row.file_hash === hash2) {
|
|
17023
18159
|
db.memoryUpsertByName({
|
|
@@ -17056,7 +18192,7 @@ function syncFile(ctx, db, name, opts = {}) {
|
|
|
17056
18192
|
${parsed.body.replace(/^\s*\n/, "")}`
|
|
17057
18193
|
);
|
|
17058
18194
|
writeFileSync2(abs, text2);
|
|
17059
|
-
st =
|
|
18195
|
+
st = statSync6(abs);
|
|
17060
18196
|
hash2 = hashText(text2);
|
|
17061
18197
|
}
|
|
17062
18198
|
const body = parsed.body.trim();
|
|
@@ -17094,7 +18230,7 @@ tags: ${tags.join(", ")}` : ""}`,
|
|
|
17094
18230
|
function setMeta(ctx, db, name, patch) {
|
|
17095
18231
|
const abs = absOf(ctx, name);
|
|
17096
18232
|
if (!existsSync8(abs)) return false;
|
|
17097
|
-
const parsed = parseMemoryFile(
|
|
18233
|
+
const parsed = parseMemoryFile(readFileSync8(abs, "utf8"));
|
|
17098
18234
|
const meta4 = { ...parsed.meta };
|
|
17099
18235
|
for (const [k, v] of Object.entries(patch)) {
|
|
17100
18236
|
if (v === void 0) delete meta4[k];
|
|
@@ -17143,7 +18279,7 @@ function reconcile(ctx, db) {
|
|
|
17143
18279
|
for (const f of files) {
|
|
17144
18280
|
const name = nameOfFile(ctx, f);
|
|
17145
18281
|
if (!name) {
|
|
17146
|
-
out.skipped.push(
|
|
18282
|
+
out.skipped.push(relative6(ctx.root, f));
|
|
17147
18283
|
continue;
|
|
17148
18284
|
}
|
|
17149
18285
|
seen.add(name);
|
|
@@ -17175,7 +18311,7 @@ function write(ctx, db, input2) {
|
|
|
17175
18311
|
let extra = {};
|
|
17176
18312
|
if (exists) {
|
|
17177
18313
|
try {
|
|
17178
|
-
extra = parseMemoryFile(
|
|
18314
|
+
extra = parseMemoryFile(readFileSync8(abs, "utf8")).meta;
|
|
17179
18315
|
} catch {
|
|
17180
18316
|
}
|
|
17181
18317
|
}
|
|
@@ -17202,7 +18338,7 @@ function write(ctx, db, input2) {
|
|
|
17202
18338
|
function read(ctx, db, name) {
|
|
17203
18339
|
const synced = syncFile(ctx, db, name);
|
|
17204
18340
|
if (!synced) return void 0;
|
|
17205
|
-
const parsed = parseMemoryFile(
|
|
18341
|
+
const parsed = parseMemoryFile(readFileSync8(absOf(ctx, name), "utf8"));
|
|
17206
18342
|
return {
|
|
17207
18343
|
name,
|
|
17208
18344
|
kind: synced.row.kind,
|
|
@@ -17229,7 +18365,7 @@ function edit(ctx, db, name, opts) {
|
|
|
17229
18365
|
const abs = absOf(ctx, name);
|
|
17230
18366
|
if (!existsSync8(abs)) throw new Error(`memory "${name}" does not exist`);
|
|
17231
18367
|
syncFile(ctx, db, name);
|
|
17232
|
-
const parsed = parseMemoryFile(
|
|
18368
|
+
const parsed = parseMemoryFile(readFileSync8(abs, "utf8"));
|
|
17233
18369
|
const re = new RegExp(opts.regex ? opts.find : escapeRe(opts.find), "g");
|
|
17234
18370
|
const count = (parsed.body.match(re) ?? []).length;
|
|
17235
18371
|
if (!count) return 0;
|
|
@@ -17247,9 +18383,9 @@ function rename(ctx, db, from, to) {
|
|
|
17247
18383
|
const absTo = absOf(ctx, to);
|
|
17248
18384
|
if (!existsSync8(absFrom)) throw new Error(`memory "${from}" does not exist`);
|
|
17249
18385
|
if (existsSync8(absTo) || db.memoryGetByName(to)) throw new Error(`memory "${to}" already exists`);
|
|
17250
|
-
mkdirSync3(
|
|
18386
|
+
mkdirSync3(dirname7(absTo), { recursive: true });
|
|
17251
18387
|
renameSync(absFrom, absTo);
|
|
17252
|
-
const parsed = parseMemoryFile(
|
|
18388
|
+
const parsed = parseMemoryFile(readFileSync8(absTo, "utf8"));
|
|
17253
18389
|
writeFileSync2(
|
|
17254
18390
|
absTo,
|
|
17255
18391
|
serializeMemoryFile(
|
|
@@ -17265,7 +18401,7 @@ function rename(ctx, db, from, to) {
|
|
|
17265
18401
|
if (!row.name || row.name === to) continue;
|
|
17266
18402
|
const abs = absOf(ctx, row.name);
|
|
17267
18403
|
if (!existsSync8(abs)) continue;
|
|
17268
|
-
const text2 =
|
|
18404
|
+
const text2 = readFileSync8(abs, "utf8");
|
|
17269
18405
|
if (!ref.test(text2)) continue;
|
|
17270
18406
|
ref.lastIndex = 0;
|
|
17271
18407
|
writeFileSync2(abs, text2.replace(ref, `mem:${to}`));
|
|
@@ -17284,11 +18420,11 @@ function remove(ctx, db, name) {
|
|
|
17284
18420
|
function gitignoreHint(ctx) {
|
|
17285
18421
|
if (hinted.has(ctx.root)) return void 0;
|
|
17286
18422
|
hinted.add(ctx.root);
|
|
17287
|
-
const file3 =
|
|
18423
|
+
const file3 = join12(ctx.root, ".gitignore");
|
|
17288
18424
|
if (!existsSync8(file3)) return void 0;
|
|
17289
18425
|
const dir = memoriesRel(ctx);
|
|
17290
18426
|
const top = dir.split("/")[0];
|
|
17291
|
-
const ignored =
|
|
18427
|
+
const ignored = readFileSync8(file3, "utf8").split(/\r?\n/).map((l) => l.trim().replace(/^\//, "").replace(/\/$/, "")).some((l) => l === top || l === dir || l === `${top}/**` || l === `${dir}/**`);
|
|
17292
18428
|
return ignored ? `note: .gitignore ignores ${dir}, so memories stay local to this machine (remove that line to share them with the team)` : void 0;
|
|
17293
18429
|
}
|
|
17294
18430
|
var import_fast_glob3, MEMORY_KINDS, SEGMENT, NAME_RE, hinted;
|
|
@@ -17815,14 +18951,14 @@ function buildHistory(ctx, db, opts = {}) {
|
|
|
17815
18951
|
};
|
|
17816
18952
|
});
|
|
17817
18953
|
const bySha = new Map(commits.map((c) => [c.sha, c]));
|
|
17818
|
-
const
|
|
18954
|
+
const resolve8 = (prefix) => {
|
|
17819
18955
|
if (bySha.has(prefix)) return bySha.get(prefix);
|
|
17820
18956
|
for (const c of commits) if (c.sha.startsWith(prefix)) return c;
|
|
17821
18957
|
return void 0;
|
|
17822
18958
|
};
|
|
17823
18959
|
for (const c of commits) {
|
|
17824
18960
|
if (c.kind !== "revert" || !c.revertOf) continue;
|
|
17825
|
-
const target =
|
|
18961
|
+
const target = resolve8(c.revertOf);
|
|
17826
18962
|
if (target) {
|
|
17827
18963
|
target.revertedBy = c.sha;
|
|
17828
18964
|
c.origins.push(target.sha);
|
|
@@ -27085,7 +28221,7 @@ var recursive = /* @__PURE__ */ new WeakMap();
|
|
|
27085
28221
|
var NONE = 0;
|
|
27086
28222
|
var ASSUMED = 1;
|
|
27087
28223
|
var PROVEN = 2;
|
|
27088
|
-
function isRecursive(inst, stack,
|
|
28224
|
+
function isRecursive(inst, stack, resolve8) {
|
|
27089
28225
|
const cached5 = recursive.get(inst);
|
|
27090
28226
|
if (cached5 !== void 0)
|
|
27091
28227
|
return cached5 ? PROVEN : NONE;
|
|
@@ -27095,7 +28231,7 @@ function isRecursive(inst, stack, resolve7) {
|
|
|
27095
28231
|
let result = NONE;
|
|
27096
28232
|
const check3 = (child) => {
|
|
27097
28233
|
if (result !== PROVEN && child?._zod) {
|
|
27098
|
-
const answer = isRecursive(child, stack,
|
|
28234
|
+
const answer = isRecursive(child, stack, resolve8);
|
|
27099
28235
|
if (answer > result)
|
|
27100
28236
|
result = answer;
|
|
27101
28237
|
}
|
|
@@ -27106,7 +28242,7 @@ function isRecursive(inst, stack, resolve7) {
|
|
|
27106
28242
|
const desc = Object.getOwnPropertyDescriptor(sh, key);
|
|
27107
28243
|
if (spread && !desc.enumerable)
|
|
27108
28244
|
continue;
|
|
27109
|
-
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack,
|
|
28245
|
+
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve8) : NONE;
|
|
27110
28246
|
if (child > answer)
|
|
27111
28247
|
answer = child;
|
|
27112
28248
|
}
|
|
@@ -27170,7 +28306,7 @@ function isRecursive(inst, stack, resolve7) {
|
|
|
27170
28306
|
break;
|
|
27171
28307
|
// `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
|
|
27172
28308
|
case "lazy": {
|
|
27173
|
-
const inner = def._cachedInner ?? (
|
|
28309
|
+
const inner = def._cachedInner ?? (resolve8 ? inst._zod.innerType : void 0);
|
|
27174
28310
|
merge2(inner ? isRecursive(inner, stack, false) : ASSUMED);
|
|
27175
28311
|
break;
|
|
27176
28312
|
}
|
|
@@ -45763,7 +46899,7 @@ var Protocol = class {
|
|
|
45763
46899
|
return;
|
|
45764
46900
|
}
|
|
45765
46901
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
45766
|
-
await new Promise((
|
|
46902
|
+
await new Promise((resolve8) => setTimeout(resolve8, pollInterval));
|
|
45767
46903
|
options?.signal?.throwIfAborted();
|
|
45768
46904
|
}
|
|
45769
46905
|
} catch (error62) {
|
|
@@ -45780,7 +46916,7 @@ var Protocol = class {
|
|
|
45780
46916
|
*/
|
|
45781
46917
|
request(request, resultSchema, options) {
|
|
45782
46918
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
45783
|
-
return new Promise((
|
|
46919
|
+
return new Promise((resolve8, reject) => {
|
|
45784
46920
|
const earlyReject = (error62) => {
|
|
45785
46921
|
reject(error62);
|
|
45786
46922
|
};
|
|
@@ -45858,7 +46994,7 @@ var Protocol = class {
|
|
|
45858
46994
|
if (!parseResult.success) {
|
|
45859
46995
|
reject(parseResult.error);
|
|
45860
46996
|
} else {
|
|
45861
|
-
|
|
46997
|
+
resolve8(parseResult.data);
|
|
45862
46998
|
}
|
|
45863
46999
|
} catch (error62) {
|
|
45864
47000
|
reject(error62);
|
|
@@ -46120,12 +47256,12 @@ var Protocol = class {
|
|
|
46120
47256
|
}
|
|
46121
47257
|
} catch {
|
|
46122
47258
|
}
|
|
46123
|
-
return new Promise((
|
|
47259
|
+
return new Promise((resolve8, reject) => {
|
|
46124
47260
|
if (signal.aborted) {
|
|
46125
47261
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
46126
47262
|
return;
|
|
46127
47263
|
}
|
|
46128
|
-
const timeoutId = setTimeout(
|
|
47264
|
+
const timeoutId = setTimeout(resolve8, interval);
|
|
46129
47265
|
signal.addEventListener("abort", () => {
|
|
46130
47266
|
clearTimeout(timeoutId);
|
|
46131
47267
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -47268,7 +48404,7 @@ var McpServer = class {
|
|
|
47268
48404
|
let task = createTaskResult.task;
|
|
47269
48405
|
const pollInterval = task.pollInterval ?? 5e3;
|
|
47270
48406
|
while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
|
|
47271
|
-
await new Promise((
|
|
48407
|
+
await new Promise((resolve8) => setTimeout(resolve8, pollInterval));
|
|
47272
48408
|
const updatedTask = await extra.taskStore.getTask(taskId);
|
|
47273
48409
|
if (!updatedTask) {
|
|
47274
48410
|
throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
|
|
@@ -47934,12 +49070,12 @@ var StdioServerTransport = class {
|
|
|
47934
49070
|
this.onclose?.();
|
|
47935
49071
|
}
|
|
47936
49072
|
send(message) {
|
|
47937
|
-
return new Promise((
|
|
49073
|
+
return new Promise((resolve8) => {
|
|
47938
49074
|
const json2 = serializeMessage(message);
|
|
47939
49075
|
if (this._stdout.write(json2)) {
|
|
47940
|
-
|
|
49076
|
+
resolve8();
|
|
47941
49077
|
} else {
|
|
47942
|
-
this._stdout.once("drain",
|
|
49078
|
+
this._stdout.once("drain", resolve8);
|
|
47943
49079
|
}
|
|
47944
49080
|
});
|
|
47945
49081
|
}
|
|
@@ -47988,7 +49124,8 @@ var ConfigSchema = external_exports.object({
|
|
|
47988
49124
|
"**/*.mjs",
|
|
47989
49125
|
"**/*.cjs",
|
|
47990
49126
|
"**/*.py",
|
|
47991
|
-
"**/*.go"
|
|
49127
|
+
"**/*.go",
|
|
49128
|
+
"**/*.php"
|
|
47992
49129
|
]),
|
|
47993
49130
|
exclude: external_exports.array(external_exports.string()).default([
|
|
47994
49131
|
"**/node_modules/**",
|
|
@@ -48002,7 +49139,8 @@ var ConfigSchema = external_exports.object({
|
|
|
48002
49139
|
"**/__pycache__/**",
|
|
48003
49140
|
"**/site-packages/**",
|
|
48004
49141
|
"**/vendor/**",
|
|
48005
|
-
"**/*.min.js"
|
|
49142
|
+
"**/*.min.js",
|
|
49143
|
+
"**/*.blade.php"
|
|
48006
49144
|
])
|
|
48007
49145
|
}).prefault({}),
|
|
48008
49146
|
git: external_exports.object({
|
|
@@ -48200,15 +49338,15 @@ init_reindex();
|
|
|
48200
49338
|
// src/session/server-alive.ts
|
|
48201
49339
|
init_esm_shims();
|
|
48202
49340
|
init_paths();
|
|
48203
|
-
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync as
|
|
48204
|
-
import { join as
|
|
49341
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readdirSync as readdirSync4, rmSync, writeFileSync } from "fs";
|
|
49342
|
+
import { join as join11 } from "path";
|
|
48205
49343
|
function markersDir(ctx) {
|
|
48206
|
-
return
|
|
49344
|
+
return join11(projectDir(ctx.id), "servers");
|
|
48207
49345
|
}
|
|
48208
49346
|
function markServerAlive(ctx, pid = process.pid) {
|
|
48209
49347
|
const dir = markersDir(ctx);
|
|
48210
49348
|
mkdirSync2(dir, { recursive: true });
|
|
48211
|
-
const file3 =
|
|
49349
|
+
const file3 = join11(dir, String(pid));
|
|
48212
49350
|
writeFileSync(file3, (/* @__PURE__ */ new Date()).toISOString());
|
|
48213
49351
|
return () => {
|
|
48214
49352
|
try {
|
|
@@ -48229,11 +49367,11 @@ function liveServers(ctx) {
|
|
|
48229
49367
|
const dir = markersDir(ctx);
|
|
48230
49368
|
if (!existsSync7(dir)) return [];
|
|
48231
49369
|
const live = [];
|
|
48232
|
-
for (const name of
|
|
49370
|
+
for (const name of readdirSync4(dir)) {
|
|
48233
49371
|
const pid = Number(name);
|
|
48234
49372
|
if (!Number.isInteger(pid) || pid <= 0) continue;
|
|
48235
49373
|
if (processAlive(pid)) live.push(pid);
|
|
48236
|
-
else rmSync(
|
|
49374
|
+
else rmSync(join11(dir, name), { force: true });
|
|
48237
49375
|
}
|
|
48238
49376
|
return live;
|
|
48239
49377
|
}
|
|
@@ -49237,12 +50375,18 @@ var SqliteAdapter = class _SqliteAdapter {
|
|
|
49237
50375
|
const ids = this.db.prepare("SELECT id FROM graph_nodes WHERE source = ? AND path = ?").all(source, path3).map((r) => r.id);
|
|
49238
50376
|
const fileId2 = `file:${path3}`;
|
|
49239
50377
|
const all = ids.includes(fileId2) ? ids : [...ids, fileId2];
|
|
50378
|
+
this.db.prepare(
|
|
50379
|
+
"DELETE FROM graph_edges WHERE source = ? AND kind = 'handles' AND dst IN (SELECT id FROM graph_nodes WHERE source = ? AND path = ? AND kind = 'route')"
|
|
50380
|
+
).run(source, source, path3);
|
|
50381
|
+
const foreignRoute = "AND NOT (kind = 'handles' AND dst IN (SELECT id FROM graph_nodes WHERE kind = 'route' AND path IS NOT ?))";
|
|
49240
50382
|
for (let i = 0; i < all.length; i += 400) {
|
|
49241
50383
|
const slice = all.slice(i, i + 400);
|
|
49242
50384
|
const ph = slice.map(() => "?").join(",");
|
|
49243
|
-
this.db.prepare(`DELETE FROM graph_edges WHERE source = ? AND src IN (${ph})`).run(source, ...slice);
|
|
50385
|
+
this.db.prepare(`DELETE FROM graph_edges WHERE source = ? AND src IN (${ph}) ${foreignRoute}`).run(source, ...slice, path3);
|
|
49244
50386
|
}
|
|
49245
|
-
this.db.prepare(
|
|
50387
|
+
this.db.prepare(
|
|
50388
|
+
`DELETE FROM graph_edges WHERE source = ? AND src LIKE ? ESCAPE '\\' ${foreignRoute}`
|
|
50389
|
+
).run(source, `sym:${path3.replace(/[%_\\]/g, "\\$&")}#%`, path3);
|
|
49246
50390
|
if (opts.keepFile) {
|
|
49247
50391
|
this.db.prepare("DELETE FROM graph_nodes WHERE source = ? AND path = ? AND kind != 'file'").run(source, path3);
|
|
49248
50392
|
} else {
|
|
@@ -49589,8 +50733,8 @@ init_esm_shims();
|
|
|
49589
50733
|
init_esm_shims();
|
|
49590
50734
|
init_store();
|
|
49591
50735
|
init_metrics();
|
|
49592
|
-
import { existsSync as existsSync9, readFileSync as
|
|
49593
|
-
import { join as
|
|
50736
|
+
import { existsSync as existsSync9, readFileSync as readFileSync9 } from "fs";
|
|
50737
|
+
import { join as join13 } from "path";
|
|
49594
50738
|
|
|
49595
50739
|
// src/graph/query.ts
|
|
49596
50740
|
init_esm_shims();
|
|
@@ -50009,8 +51153,8 @@ var ASPECTS = [
|
|
|
50009
51153
|
];
|
|
50010
51154
|
function pkgJson(root) {
|
|
50011
51155
|
try {
|
|
50012
|
-
const f =
|
|
50013
|
-
return existsSync9(f) ? JSON.parse(
|
|
51156
|
+
const f = join13(root, "package.json");
|
|
51157
|
+
return existsSync9(f) ? JSON.parse(readFileSync9(f, "utf8")) : {};
|
|
50014
51158
|
} catch {
|
|
50015
51159
|
return {};
|
|
50016
51160
|
}
|
|
@@ -50188,10 +51332,10 @@ init_esm_shims();
|
|
|
50188
51332
|
// src/session/current.ts
|
|
50189
51333
|
init_esm_shims();
|
|
50190
51334
|
init_paths();
|
|
50191
|
-
import { readFileSync as
|
|
50192
|
-
import { join as
|
|
51335
|
+
import { readFileSync as readFileSync10, statSync as statSync7, writeFileSync as writeFileSync3 } from "fs";
|
|
51336
|
+
import { join as join14 } from "path";
|
|
50193
51337
|
function file2(ctx) {
|
|
50194
|
-
return
|
|
51338
|
+
return join14(projectDir(ctx.id), "current-session");
|
|
50195
51339
|
}
|
|
50196
51340
|
var cached3;
|
|
50197
51341
|
function getCurrentSession(ctx) {
|
|
@@ -50199,12 +51343,12 @@ function getCurrentSession(ctx) {
|
|
|
50199
51343
|
const f = file2(ctx);
|
|
50200
51344
|
let mtimeMs;
|
|
50201
51345
|
try {
|
|
50202
|
-
mtimeMs =
|
|
51346
|
+
mtimeMs = statSync7(f).mtimeMs;
|
|
50203
51347
|
} catch {
|
|
50204
51348
|
return "unknown";
|
|
50205
51349
|
}
|
|
50206
51350
|
if (cached3 && cached3.file === f && cached3.mtimeMs === mtimeMs) return cached3.id;
|
|
50207
|
-
const id =
|
|
51351
|
+
const id = readFileSync10(f, "utf8").trim() || "unknown";
|
|
50208
51352
|
cached3 = { file: f, mtimeMs, id };
|
|
50209
51353
|
return id;
|
|
50210
51354
|
}
|
|
@@ -50417,7 +51561,7 @@ var NodeFilterSchema = external_exports.object({
|
|
|
50417
51561
|
});
|
|
50418
51562
|
var emGraphQuery = defineTool({
|
|
50419
51563
|
name: "em_graph_query",
|
|
50420
|
-
description: 'Look up nodes in the project knowledge graph (files, functions, classes, routes, packages, people, concepts, memories) by name/path, run a preset (hotspots, coupled, orphans, dead_code, routes, cycles, clusters, stats), or run a structured pattern: start at nodes matching `from`, walk `edge.kinds` in `edge.direction` for `edge.depth` hops, keep what matches `to` \u2014 e.g. {from:{kind:"route"}, edge:{kinds:["handles"], direction:"in"}} lists every route handler, {from:{name:"^parseFile$"}, edge:{kinds:["calls"], direction:"in", depth:2}} its callers two levels up. Built from tree-sitter (TS/JS, Python, Go), git history, memories and em_graph_add.',
|
|
51564
|
+
description: 'Look up nodes in the project knowledge graph (files, functions, classes, routes, packages, people, concepts, memories) by name/path, run a preset (hotspots, coupled, orphans, dead_code, routes, cycles, clusters, stats), or run a structured pattern: start at nodes matching `from`, walk `edge.kinds` in `edge.direction` for `edge.depth` hops, keep what matches `to` \u2014 e.g. {from:{kind:"route"}, edge:{kinds:["handles"], direction:"in"}} lists every route handler, {from:{name:"^parseFile$"}, edge:{kinds:["calls"], direction:"in", depth:2}} its callers two levels up. Built from tree-sitter (TS/JS, Python, Go, PHP), git history, memories and em_graph_add.',
|
|
50421
51565
|
schema: {
|
|
50422
51566
|
query: external_exports.string().optional().describe("Substring of a name, path or id"),
|
|
50423
51567
|
kind: external_exports.string().optional().describe(
|
|
@@ -50778,13 +51922,13 @@ init_esm_shims();
|
|
|
50778
51922
|
// src/sandbox/execute.ts
|
|
50779
51923
|
init_esm_shims();
|
|
50780
51924
|
import { unlinkSync as unlinkSync2 } from "fs";
|
|
50781
|
-
import { join as
|
|
51925
|
+
import { join as join17 } from "path";
|
|
50782
51926
|
|
|
50783
51927
|
// src/permissions/settings.ts
|
|
50784
51928
|
init_esm_shims();
|
|
50785
|
-
import { existsSync as existsSync10, readFileSync as
|
|
51929
|
+
import { existsSync as existsSync10, readFileSync as readFileSync11, statSync as statSync8 } from "fs";
|
|
50786
51930
|
import { homedir as homedir2 } from "os";
|
|
50787
|
-
import { join as
|
|
51931
|
+
import { join as join15 } from "path";
|
|
50788
51932
|
|
|
50789
51933
|
// src/permissions/rules.ts
|
|
50790
51934
|
init_esm_shims();
|
|
@@ -50911,7 +52055,7 @@ function splitCommand(line) {
|
|
|
50911
52055
|
i++;
|
|
50912
52056
|
}
|
|
50913
52057
|
flush();
|
|
50914
|
-
return segments.map(
|
|
52058
|
+
return segments.map(normalize5).filter(Boolean);
|
|
50915
52059
|
}
|
|
50916
52060
|
function matchParen(s, open3) {
|
|
50917
52061
|
let d = 0;
|
|
@@ -50924,7 +52068,7 @@ function matchParen(s, open3) {
|
|
|
50924
52068
|
}
|
|
50925
52069
|
return s.length;
|
|
50926
52070
|
}
|
|
50927
|
-
function
|
|
52071
|
+
function normalize5(seg) {
|
|
50928
52072
|
let s = seg.trim();
|
|
50929
52073
|
for (; ; ) {
|
|
50930
52074
|
const before = s;
|
|
@@ -50940,7 +52084,7 @@ function normalize4(seg) {
|
|
|
50940
52084
|
function readRules(file3) {
|
|
50941
52085
|
if (!existsSync10(file3)) return {};
|
|
50942
52086
|
try {
|
|
50943
|
-
const s = JSON.parse(
|
|
52087
|
+
const s = JSON.parse(readFileSync11(file3, "utf8"));
|
|
50944
52088
|
return s.permissions ?? {};
|
|
50945
52089
|
} catch {
|
|
50946
52090
|
return {};
|
|
@@ -50948,7 +52092,7 @@ function readRules(file3) {
|
|
|
50948
52092
|
}
|
|
50949
52093
|
function stamp(file3) {
|
|
50950
52094
|
try {
|
|
50951
|
-
return
|
|
52095
|
+
return statSync8(file3).mtimeMs;
|
|
50952
52096
|
} catch {
|
|
50953
52097
|
return -1;
|
|
50954
52098
|
}
|
|
@@ -50956,9 +52100,9 @@ function stamp(file3) {
|
|
|
50956
52100
|
var cache2 = /* @__PURE__ */ new Map();
|
|
50957
52101
|
function loadPermissionRules(root, extraDeny = []) {
|
|
50958
52102
|
const files = [
|
|
50959
|
-
|
|
50960
|
-
|
|
50961
|
-
|
|
52103
|
+
join15(homedir2(), ".claude", "settings.json"),
|
|
52104
|
+
join15(root, ".claude", "settings.json"),
|
|
52105
|
+
join15(root, ".claude", "settings.local.json")
|
|
50962
52106
|
];
|
|
50963
52107
|
const key = `${root}\0${extraDeny.join("\0")}`;
|
|
50964
52108
|
const stamps = files.map(stamp);
|
|
@@ -51068,12 +52212,12 @@ init_esm_shims();
|
|
|
51068
52212
|
init_paths();
|
|
51069
52213
|
import { accessSync, constants, existsSync as existsSync11, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
51070
52214
|
import { createRequire } from "module";
|
|
51071
|
-
import { delimiter, join as
|
|
52215
|
+
import { delimiter, join as join16 } from "path";
|
|
51072
52216
|
var require2 = createRequire(import.meta.url);
|
|
51073
52217
|
function findOnPath(bin) {
|
|
51074
52218
|
for (const dir of (process.env.PATH ?? "").split(delimiter)) {
|
|
51075
52219
|
if (!dir) continue;
|
|
51076
|
-
const p =
|
|
52220
|
+
const p = join16(dir, bin);
|
|
51077
52221
|
try {
|
|
51078
52222
|
accessSync(p, constants.X_OK);
|
|
51079
52223
|
return p;
|
|
@@ -51208,7 +52352,7 @@ function writeScratch(code, ext) {
|
|
|
51208
52352
|
mkdirSync4(dir, { recursive: true });
|
|
51209
52353
|
scratchDir = dir;
|
|
51210
52354
|
}
|
|
51211
|
-
const file3 =
|
|
52355
|
+
const file3 = join16(dir, `em-${Date.now()}-${Math.random().toString(36).slice(2, 8)}${ext}`);
|
|
51212
52356
|
try {
|
|
51213
52357
|
writeFileSync4(file3, code, { mode: 384 });
|
|
51214
52358
|
} catch (err) {
|
|
@@ -51224,7 +52368,7 @@ init_esm_shims();
|
|
|
51224
52368
|
import { spawn } from "child_process";
|
|
51225
52369
|
function runProcess(argv, opts) {
|
|
51226
52370
|
const started = Date.now();
|
|
51227
|
-
return new Promise((
|
|
52371
|
+
return new Promise((resolve8) => {
|
|
51228
52372
|
const [cmd, ...args] = argv;
|
|
51229
52373
|
const child = spawn(cmd, args, {
|
|
51230
52374
|
cwd: opts.cwd,
|
|
@@ -51267,7 +52411,7 @@ function runProcess(argv, opts) {
|
|
|
51267
52411
|
if (done) return;
|
|
51268
52412
|
done = true;
|
|
51269
52413
|
clearTimeout(timer);
|
|
51270
|
-
|
|
52414
|
+
resolve8({
|
|
51271
52415
|
stdout: Buffer.concat(out).toString("utf8"),
|
|
51272
52416
|
stderr: errTail,
|
|
51273
52417
|
exitCode,
|
|
@@ -51310,7 +52454,7 @@ async function execute(ctx, input2) {
|
|
|
51310
52454
|
const file3 = writeScratch(input2.code, lang.ext);
|
|
51311
52455
|
const env = buildEnv(ctx.config.sandbox.envAllow, {
|
|
51312
52456
|
EMINIAR_PROJECT_ROOT: ctx.root,
|
|
51313
|
-
NODE_PATH: [
|
|
52457
|
+
NODE_PATH: [join17(ctx.root, "node_modules"), process.env.NODE_PATH].filter(Boolean).join(":"),
|
|
51314
52458
|
...input2.env
|
|
51315
52459
|
});
|
|
51316
52460
|
try {
|
|
@@ -52882,13 +54026,13 @@ function catalogForProvider(provider, catalog = CATALOG) {
|
|
|
52882
54026
|
// src/docs/discover.ts
|
|
52883
54027
|
init_esm_shims();
|
|
52884
54028
|
var import_fast_glob4 = __toESM(require_out4(), 1);
|
|
52885
|
-
import { existsSync as existsSync13, readFileSync as
|
|
52886
|
-
import { basename, join as
|
|
54029
|
+
import { existsSync as existsSync13, readFileSync as readFileSync13, statSync as statSync9 } from "fs";
|
|
54030
|
+
import { basename, join as join19, relative as relative7 } from "path";
|
|
52887
54031
|
|
|
52888
54032
|
// src/docs/manifest.ts
|
|
52889
54033
|
init_esm_shims();
|
|
52890
|
-
import { existsSync as existsSync12, mkdirSync as mkdirSync5, readFileSync as
|
|
52891
|
-
import { dirname as
|
|
54034
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync5, readFileSync as readFileSync12, writeFileSync as writeFileSync5 } from "fs";
|
|
54035
|
+
import { dirname as dirname8, join as join18 } from "path";
|
|
52892
54036
|
var DOCS_PREFIX = "docs:";
|
|
52893
54037
|
var NAME_RE2 = /^[a-z0-9][a-z0-9._-]{0,63}$/;
|
|
52894
54038
|
function docsTag(name) {
|
|
@@ -52902,7 +54046,7 @@ function slugify3(input2) {
|
|
|
52902
54046
|
return (s || "source").slice(0, 64);
|
|
52903
54047
|
}
|
|
52904
54048
|
function manifestPathAt(root, rel = ".eminiar/docs.json") {
|
|
52905
|
-
return
|
|
54049
|
+
return join18(root, rel);
|
|
52906
54050
|
}
|
|
52907
54051
|
function manifestPath(ctx) {
|
|
52908
54052
|
return manifestPathAt(ctx.root, ctx.config.docs.manifest);
|
|
@@ -52910,7 +54054,7 @@ function manifestPath(ctx) {
|
|
|
52910
54054
|
function empty() {
|
|
52911
54055
|
return { version: 1, sources: [] };
|
|
52912
54056
|
}
|
|
52913
|
-
function
|
|
54057
|
+
function normalize6(raw) {
|
|
52914
54058
|
if (!raw || typeof raw !== "object") return empty();
|
|
52915
54059
|
const sources = Array.isArray(raw.sources) ? raw.sources : [];
|
|
52916
54060
|
const out = [];
|
|
@@ -52932,7 +54076,7 @@ function normalize5(raw) {
|
|
|
52932
54076
|
function readManifestAt(file3) {
|
|
52933
54077
|
if (!existsSync12(file3)) return empty();
|
|
52934
54078
|
try {
|
|
52935
|
-
return
|
|
54079
|
+
return normalize6(JSON.parse(readFileSync12(file3, "utf8")));
|
|
52936
54080
|
} catch {
|
|
52937
54081
|
return empty();
|
|
52938
54082
|
}
|
|
@@ -52942,7 +54086,7 @@ function readManifest(ctx) {
|
|
|
52942
54086
|
}
|
|
52943
54087
|
function writeManifest(ctx, m) {
|
|
52944
54088
|
const file3 = manifestPath(ctx);
|
|
52945
|
-
mkdirSync5(
|
|
54089
|
+
mkdirSync5(dirname8(file3), { recursive: true });
|
|
52946
54090
|
const sorted = {
|
|
52947
54091
|
version: 1,
|
|
52948
54092
|
sources: [...m.sources].sort((a, b) => a.name.localeCompare(b.name))
|
|
@@ -53193,7 +54337,7 @@ var GENERIC_ENV = /* @__PURE__ */ new Set([
|
|
|
53193
54337
|
var SKIP_EXT = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".gif", ".svg", ".pdf", ".zip", ".ico"]);
|
|
53194
54338
|
function readText(file3) {
|
|
53195
54339
|
try {
|
|
53196
|
-
return
|
|
54340
|
+
return readFileSync13(file3, "utf8");
|
|
53197
54341
|
} catch {
|
|
53198
54342
|
return void 0;
|
|
53199
54343
|
}
|
|
@@ -53211,7 +54355,7 @@ function sizeOf(files) {
|
|
|
53211
54355
|
let n = 0;
|
|
53212
54356
|
for (const f of files) {
|
|
53213
54357
|
try {
|
|
53214
|
-
n +=
|
|
54358
|
+
n += statSync9(f).size;
|
|
53215
54359
|
} catch {
|
|
53216
54360
|
}
|
|
53217
54361
|
}
|
|
@@ -53219,7 +54363,7 @@ function sizeOf(files) {
|
|
|
53219
54363
|
}
|
|
53220
54364
|
var VISIBLE_DOT_DIRS = /* @__PURE__ */ new Set([".github", ".claude", ".cursor", ".gitlab", ".circleci"]);
|
|
53221
54365
|
function hiddenPath(cwd, file3) {
|
|
53222
|
-
const parts =
|
|
54366
|
+
const parts = relative7(cwd, file3).split("/");
|
|
53223
54367
|
return parts.slice(0, -1).some((p, i) => {
|
|
53224
54368
|
if (!p.startsWith(".")) return false;
|
|
53225
54369
|
if (p === ".claude") return !["agents", "skills", "commands"].includes(parts[i + 1] ?? "");
|
|
@@ -53248,8 +54392,8 @@ function findProjects(root, opts) {
|
|
|
53248
54392
|
const found = /* @__PURE__ */ new Set();
|
|
53249
54393
|
for (const m of markers) {
|
|
53250
54394
|
for (const f of glob(root, [`*/${m}`, `*/*/${m}`], 3)) {
|
|
53251
|
-
const dir =
|
|
53252
|
-
const rel =
|
|
54395
|
+
const dir = join19(f, "..");
|
|
54396
|
+
const rel = relative7(root, dir);
|
|
53253
54397
|
if (!rel || rel.split("/").some((p) => p.startsWith(".") || p === "node_modules")) continue;
|
|
53254
54398
|
found.add(dir);
|
|
53255
54399
|
}
|
|
@@ -53257,7 +54401,7 @@ function findProjects(root, opts) {
|
|
|
53257
54401
|
const max = opts.maxProjects ?? 40;
|
|
53258
54402
|
const seenNames = /* @__PURE__ */ new Set();
|
|
53259
54403
|
const nameOf = (dir) => {
|
|
53260
|
-
const pkg = readJson2(
|
|
54404
|
+
const pkg = readJson2(join19(dir, "package.json"));
|
|
53261
54405
|
return typeof pkg?.name === "string" ? pkg.name : void 0;
|
|
53262
54406
|
};
|
|
53263
54407
|
const rootName = nameOf(root);
|
|
@@ -53275,7 +54419,7 @@ function findProjects(root, opts) {
|
|
|
53275
54419
|
return out;
|
|
53276
54420
|
}
|
|
53277
54421
|
function npmSignals(dir, includeDev, project) {
|
|
53278
|
-
const pkg = readJson2(
|
|
54422
|
+
const pkg = readJson2(join19(dir, "package.json"));
|
|
53279
54423
|
if (!pkg) return [];
|
|
53280
54424
|
const sections = ["dependencies", ...includeDev ? ["devDependencies"] : []];
|
|
53281
54425
|
const out = [];
|
|
@@ -53292,13 +54436,13 @@ function npmSignals(dir, includeDev, project) {
|
|
|
53292
54436
|
}
|
|
53293
54437
|
function pythonSignals(dir, project) {
|
|
53294
54438
|
const out = [];
|
|
53295
|
-
const py = readText(
|
|
54439
|
+
const py = readText(join19(dir, "pyproject.toml"));
|
|
53296
54440
|
if (py) {
|
|
53297
54441
|
const block = /dependencies\s*=\s*\[([\s\S]*?)\]/.exec(py)?.[1] ?? "";
|
|
53298
54442
|
for (const m of block.matchAll(/["']([A-Za-z0-9_.-]+)/g))
|
|
53299
54443
|
out.push({ kind: "pypi", key: m[1].toLowerCase(), project });
|
|
53300
54444
|
}
|
|
53301
|
-
const req = readText(
|
|
54445
|
+
const req = readText(join19(dir, "requirements.txt"));
|
|
53302
54446
|
if (req) {
|
|
53303
54447
|
for (const line of req.split("\n")) {
|
|
53304
54448
|
const name = /^\s*([A-Za-z0-9_.-]+)/.exec(line)?.[1];
|
|
@@ -53309,7 +54453,7 @@ function pythonSignals(dir, project) {
|
|
|
53309
54453
|
return out;
|
|
53310
54454
|
}
|
|
53311
54455
|
function goSignals(dir, project) {
|
|
53312
|
-
const mod = readText(
|
|
54456
|
+
const mod = readText(join19(dir, "go.mod"));
|
|
53313
54457
|
if (!mod) return [];
|
|
53314
54458
|
const out = [];
|
|
53315
54459
|
const block = /require\s*\(([\s\S]*?)\)/g;
|
|
@@ -53494,62 +54638,67 @@ var DOC_HOST_RE = /^(docs?|developer|developers|devdocs|apidocs|api-docs|help|su
|
|
|
53494
54638
|
var DOC_HOST_SUFFIX = /\.(readthedocs\.io|gitbook\.io|github\.io|gitlab\.io|netlify\.app|vercel\.app|mintlify\.app|readme\.io|redoc\.ly|stoplight\.io)$/i;
|
|
53495
54639
|
var DOC_PATH_RE = /^\/(docs?|documentation|developers?|guides?|learn|reference|manual|wiki|help|en|latest|stable|v\d+(\.\d+)*\/docs)(\/|$)/i;
|
|
53496
54640
|
var COMMENT_RE = /^\s*(\/\/|#|\*|\/\*|<!--|--|;|'''|""")/;
|
|
54641
|
+
var PLACEHOLDER_RE = /\bplaceholder\b/i;
|
|
54642
|
+
var REFERENCE_TABLE_HOSTS = 15;
|
|
53497
54643
|
function isDocLink(host, path3) {
|
|
53498
54644
|
return DOC_HOST_RE.test(host) || DOC_HOST_SUFFIX.test(host) || DOC_PATH_RE.test(path3) && !API_HOST_RE.test(host);
|
|
53499
54645
|
}
|
|
53500
54646
|
function apiSignals(dir, project) {
|
|
53501
54647
|
const hits = /* @__PURE__ */ new Map();
|
|
53502
54648
|
const docLinks = /* @__PURE__ */ new Map();
|
|
53503
|
-
const files = glob(dir, CODE_GLOBS, 8).filter((f) => !/\.min\.(js|mjs|cjs)$/.test(f)).filter((f) => !TEST_PATH_RE.test(
|
|
54649
|
+
const files = glob(dir, CODE_GLOBS, 8).filter((f) => !/\.min\.(js|mjs|cjs)$/.test(f)).filter((f) => !TEST_PATH_RE.test(relative7(dir, f))).slice(0, 4e3);
|
|
53504
54650
|
for (const file3 of files) {
|
|
53505
54651
|
let size = 0;
|
|
53506
54652
|
try {
|
|
53507
|
-
size =
|
|
54653
|
+
size = statSync9(file3).size;
|
|
53508
54654
|
} catch {
|
|
53509
54655
|
continue;
|
|
53510
54656
|
}
|
|
53511
54657
|
if (size > 400 * 1024) continue;
|
|
53512
54658
|
const text2 = readText(file3);
|
|
53513
54659
|
if (!text2 || text2.includes("\0")) continue;
|
|
53514
|
-
const rel =
|
|
54660
|
+
const rel = relative7(dir, file3).split("\\").join("/");
|
|
53515
54661
|
const isEnv = basename(file3).startsWith(".env");
|
|
53516
54662
|
const lines = text2.split("\n");
|
|
54663
|
+
const found = [];
|
|
53517
54664
|
for (let i = 0; i < lines.length; i++) {
|
|
53518
54665
|
const line = lines[i];
|
|
53519
|
-
if (!line.includes("http")) continue;
|
|
53520
|
-
const comment = COMMENT_RE.test(line);
|
|
54666
|
+
if (!line.includes("http") || PLACEHOLDER_RE.test(line)) continue;
|
|
53521
54667
|
for (const m of line.matchAll(URL_RE)) {
|
|
53522
54668
|
const host = m[1].toLowerCase();
|
|
53523
|
-
|
|
53524
|
-
|
|
53525
|
-
|
|
53526
|
-
|
|
53527
|
-
|
|
53528
|
-
|
|
53529
|
-
|
|
53530
|
-
|
|
53531
|
-
|
|
53532
|
-
|
|
53533
|
-
|
|
53534
|
-
|
|
53535
|
-
|
|
53536
|
-
|
|
53537
|
-
|
|
53538
|
-
|
|
53539
|
-
|
|
53540
|
-
|
|
53541
|
-
|
|
53542
|
-
|
|
53543
|
-
|
|
53544
|
-
|
|
53545
|
-
|
|
53546
|
-
|
|
53547
|
-
|
|
53548
|
-
|
|
53549
|
-
|
|
53550
|
-
|
|
53551
|
-
|
|
54669
|
+
if (isApiHostCandidate(host)) found.push({ host, path: m[2] ?? "/", line, i });
|
|
54670
|
+
}
|
|
54671
|
+
}
|
|
54672
|
+
if (new Set(found.map((f) => f.host)).size >= REFERENCE_TABLE_HOSTS) continue;
|
|
54673
|
+
for (const { host, path: path3, line, i } of found) {
|
|
54674
|
+
const comment = COMMENT_RE.test(line);
|
|
54675
|
+
const spec = SPEC_URL_RE.test(path3);
|
|
54676
|
+
if (!spec && isDocLink(host, path3)) {
|
|
54677
|
+
if (comment && !isEnv) continue;
|
|
54678
|
+
const link = docLinks.get(host) ?? { host, urls: [], samples: [], project };
|
|
54679
|
+
const full = `https://${host}${path3.replace(/[#?].*$/, "")}`;
|
|
54680
|
+
if (!link.urls.includes(full) && link.urls.length < 3) link.urls.push(full);
|
|
54681
|
+
if (link.samples.length < 3) link.samples.push(`${rel}:${i + 1}`);
|
|
54682
|
+
docLinks.set(host, link);
|
|
54683
|
+
continue;
|
|
54684
|
+
}
|
|
54685
|
+
const callLike = !comment && (spec || isEnv || CALL_RE.test(line) || API_PATH_RE.test(path3) || API_HOST_RE.test(host));
|
|
54686
|
+
const cur = hits.get(host) ?? {
|
|
54687
|
+
host,
|
|
54688
|
+
calls: 0,
|
|
54689
|
+
mentions: 0,
|
|
54690
|
+
samples: [],
|
|
54691
|
+
specUrls: [],
|
|
54692
|
+
project
|
|
54693
|
+
};
|
|
54694
|
+
if (callLike) cur.calls++;
|
|
54695
|
+
else cur.mentions++;
|
|
54696
|
+
if (callLike && cur.samples.length < 3) cur.samples.push(`${rel}:${i + 1}`);
|
|
54697
|
+
if (spec) {
|
|
54698
|
+
const full = `https://${host}${path3}`;
|
|
54699
|
+
if (!cur.specUrls.includes(full) && cur.specUrls.length < 4) cur.specUrls.push(full);
|
|
53552
54700
|
}
|
|
54701
|
+
hits.set(host, cur);
|
|
53553
54702
|
}
|
|
53554
54703
|
}
|
|
53555
54704
|
return { hits, docLinks };
|
|
@@ -53598,7 +54747,7 @@ function fileSignals(dir, project) {
|
|
|
53598
54747
|
function localCandidates(root, dir, project, isRegistered) {
|
|
53599
54748
|
const out = [];
|
|
53600
54749
|
const prefix = project ? `${slugify3(basename(dir))}-` : "";
|
|
53601
|
-
const rel = (abs) =>
|
|
54750
|
+
const rel = (abs) => relative7(root, abs).split("\\").join("/");
|
|
53602
54751
|
const push = (c) => {
|
|
53603
54752
|
if (!c.files) return;
|
|
53604
54753
|
out.push({ ...c, project, registered: isRegistered(c) });
|
|
@@ -53628,7 +54777,7 @@ function localCandidates(root, dir, project, isRegistered) {
|
|
|
53628
54777
|
why: "project readme and top-level guides"
|
|
53629
54778
|
});
|
|
53630
54779
|
for (const d of ["docs", "doc", "documentation"]) {
|
|
53631
|
-
const abs =
|
|
54780
|
+
const abs = join19(dir, d);
|
|
53632
54781
|
if (!existsSync13(abs)) continue;
|
|
53633
54782
|
const files = glob(abs, ["**/*.md", "**/*.mdx", "**/*.rst", "**/*.txt"]).filter(
|
|
53634
54783
|
(f) => !SKIP_EXT.has(f.slice(f.lastIndexOf(".")))
|
|
@@ -53652,7 +54801,7 @@ function localCandidates(root, dir, project, isRegistered) {
|
|
|
53652
54801
|
"docs/decisions",
|
|
53653
54802
|
"decisions"
|
|
53654
54803
|
]) {
|
|
53655
|
-
const abs =
|
|
54804
|
+
const abs = join19(dir, d);
|
|
53656
54805
|
if (!existsSync13(abs)) continue;
|
|
53657
54806
|
if (out.some((c) => c.path && rel(abs).startsWith(`${c.path}/`))) break;
|
|
53658
54807
|
const files = glob(abs, ["**/*.md"]);
|
|
@@ -53712,7 +54861,7 @@ function localCandidates(root, dir, project, isRegistered) {
|
|
|
53712
54861
|
push({
|
|
53713
54862
|
name: `${prefix}api-specs`,
|
|
53714
54863
|
path: rel(dir) || ".",
|
|
53715
|
-
glob: api.map((f) =>
|
|
54864
|
+
glob: api.map((f) => relative7(dir, f).split("\\").join("/")),
|
|
53716
54865
|
files: api.length,
|
|
53717
54866
|
bytes: sizeOf(api),
|
|
53718
54867
|
why: "OpenAPI / Postman / GraphQL / protobuf specs"
|
|
@@ -53786,7 +54935,7 @@ function discoverDocs(ctx, opts = {}) {
|
|
|
53786
54935
|
const apiHits = /* @__PURE__ */ new Map();
|
|
53787
54936
|
const docLinks = /* @__PURE__ */ new Map();
|
|
53788
54937
|
for (const dir of projects) {
|
|
53789
|
-
const project = dir === root ? "" :
|
|
54938
|
+
const project = dir === root ? "" : relative7(root, dir).split("\\").join("/");
|
|
53790
54939
|
const own2 = dir === root && projects.length > 1 ? void 0 : dir;
|
|
53791
54940
|
local.push(...localCandidates(root, dir, project, isRegistered));
|
|
53792
54941
|
signals.push(...npmSignals(dir, includeDev, project));
|
|
@@ -53796,7 +54945,7 @@ function discoverDocs(ctx, opts = {}) {
|
|
|
53796
54945
|
signals.push(...fileSignals(dir, project));
|
|
53797
54946
|
const api = apiSignals(own2 ?? dir, project);
|
|
53798
54947
|
const inSubproject = (samples) => own2 === void 0 && projects.some(
|
|
53799
|
-
(p) => p !== root && samples.some((s) => s.startsWith(`${
|
|
54948
|
+
(p) => p !== root && samples.some((s) => s.startsWith(`${relative7(root, p)}/`))
|
|
53800
54949
|
);
|
|
53801
54950
|
for (const hit of api.hits.values()) {
|
|
53802
54951
|
if (inSubproject(hit.samples)) continue;
|
|
@@ -53986,7 +55135,7 @@ function discoverDocs(ctx, opts = {}) {
|
|
|
53986
55135
|
);
|
|
53987
55136
|
return {
|
|
53988
55137
|
root,
|
|
53989
|
-
projects: projects.map((p) => p === root ? "." :
|
|
55138
|
+
projects: projects.map((p) => p === root ? "." : relative7(root, p)),
|
|
53990
55139
|
local,
|
|
53991
55140
|
providers
|
|
53992
55141
|
};
|
|
@@ -55525,9 +56674,9 @@ init_esm_shims();
|
|
|
55525
56674
|
init_esm_shims();
|
|
55526
56675
|
init_paths();
|
|
55527
56676
|
init_version();
|
|
55528
|
-
import { accessSync as accessSync2, constants as constants2, existsSync as existsSync14, readFileSync as
|
|
56677
|
+
import { accessSync as accessSync2, constants as constants2, existsSync as existsSync14, readFileSync as readFileSync14 } from "fs";
|
|
55529
56678
|
import { createRequire as createRequire3 } from "module";
|
|
55530
|
-
import { join as
|
|
56679
|
+
import { join as join20 } from "path";
|
|
55531
56680
|
var require4 = createRequire3(import.meta.url);
|
|
55532
56681
|
function check2(name, fn) {
|
|
55533
56682
|
try {
|
|
@@ -55557,7 +56706,7 @@ function runDoctor() {
|
|
|
55557
56706
|
checks.push(
|
|
55558
56707
|
check2("node-path pin", () => {
|
|
55559
56708
|
if (!existsSync14(p.nodePathFile)) return "not pinned (run `eminiar install`); using PATH node";
|
|
55560
|
-
const pinned =
|
|
56709
|
+
const pinned = readFileSync14(p.nodePathFile, "utf8").trim();
|
|
55561
56710
|
accessSync2(pinned, constants2.X_OK);
|
|
55562
56711
|
return pinned;
|
|
55563
56712
|
})
|
|
@@ -55566,8 +56715,8 @@ function runDoctor() {
|
|
|
55566
56715
|
check2("root-path pin", () => {
|
|
55567
56716
|
if (!existsSync14(p.rootPathFile))
|
|
55568
56717
|
return "not pinned (run `eminiar install`); the bin/ shims run only from a directory that has node_modules";
|
|
55569
|
-
const root =
|
|
55570
|
-
if (!existsSync14(
|
|
56718
|
+
const root = readFileSync14(p.rootPathFile, "utf8").trim();
|
|
56719
|
+
if (!existsSync14(join20(root, "dist", "server.js")))
|
|
55571
56720
|
throw new Error(`${root} has no dist/server.js (run \`eminiar install\`)`);
|
|
55572
56721
|
return root;
|
|
55573
56722
|
})
|
|
@@ -55626,8 +56775,8 @@ init_queue();
|
|
|
55626
56775
|
|
|
55627
56776
|
// src/hooks/coexist.ts
|
|
55628
56777
|
init_esm_shims();
|
|
55629
|
-
import { readFileSync as
|
|
55630
|
-
import { join as
|
|
56778
|
+
import { readFileSync as readFileSync16 } from "fs";
|
|
56779
|
+
import { join as join22 } from "path";
|
|
55631
56780
|
|
|
55632
56781
|
// src/install/claude-config.ts
|
|
55633
56782
|
init_esm_shims();
|
|
@@ -55636,24 +56785,24 @@ import {
|
|
|
55636
56785
|
copyFileSync,
|
|
55637
56786
|
existsSync as existsSync15,
|
|
55638
56787
|
mkdirSync as mkdirSync6,
|
|
55639
|
-
readdirSync as
|
|
55640
|
-
readFileSync as
|
|
56788
|
+
readdirSync as readdirSync5,
|
|
56789
|
+
readFileSync as readFileSync15,
|
|
55641
56790
|
writeFileSync as writeFileSync6
|
|
55642
56791
|
} from "fs";
|
|
55643
56792
|
import { homedir as homedir3 } from "os";
|
|
55644
|
-
import { dirname as
|
|
55645
|
-
var claudeDir = () => process.env.CLAUDE_CONFIG_DIR ||
|
|
55646
|
-
var pluginsDir = () =>
|
|
56793
|
+
import { dirname as dirname9, join as join21 } from "path";
|
|
56794
|
+
var claudeDir = () => process.env.CLAUDE_CONFIG_DIR || join21(homedir3(), ".claude");
|
|
56795
|
+
var pluginsDir = () => join21(claudeDir(), "plugins");
|
|
55647
56796
|
function readJson3(file3) {
|
|
55648
56797
|
if (!existsSync15(file3)) return {};
|
|
55649
56798
|
try {
|
|
55650
|
-
return JSON.parse(
|
|
56799
|
+
return JSON.parse(readFileSync15(file3, "utf8"));
|
|
55651
56800
|
} catch (err) {
|
|
55652
56801
|
throw new Error(`${file3} is not valid JSON: ${err.message}`);
|
|
55653
56802
|
}
|
|
55654
56803
|
}
|
|
55655
56804
|
var PLUGIN_SERVER_ID = "plugin:eminiar:eminiar";
|
|
55656
|
-
var mcpNeedsAuthPath = () =>
|
|
56805
|
+
var mcpNeedsAuthPath = () => join21(claudeDir(), "mcp-needs-auth-cache.json");
|
|
55657
56806
|
function needsAuthEntry(id = PLUGIN_SERVER_ID) {
|
|
55658
56807
|
try {
|
|
55659
56808
|
const entry = readJson3(mcpNeedsAuthPath())[id];
|
|
@@ -55668,7 +56817,7 @@ var cached4;
|
|
|
55668
56817
|
function contextModeInstalled() {
|
|
55669
56818
|
if (cached4 !== void 0) return cached4;
|
|
55670
56819
|
try {
|
|
55671
|
-
const reg = JSON.parse(
|
|
56820
|
+
const reg = JSON.parse(readFileSync16(join22(pluginsDir(), "installed_plugins.json"), "utf8"));
|
|
55672
56821
|
cached4 = Object.keys(reg.plugins ?? {}).some((id) => id.startsWith("context-mode@"));
|
|
55673
56822
|
} catch {
|
|
55674
56823
|
cached4 = false;
|
|
@@ -55788,16 +56937,16 @@ init_esm_shims();
|
|
|
55788
56937
|
// src/sandbox/file.ts
|
|
55789
56938
|
init_esm_shims();
|
|
55790
56939
|
import { realpathSync as realpathSync2 } from "fs";
|
|
55791
|
-
import { isAbsolute, relative as
|
|
56940
|
+
import { isAbsolute, relative as relative8, resolve as resolve7 } from "path";
|
|
55792
56941
|
function confinePath(root, target, rules) {
|
|
55793
|
-
const abs =
|
|
56942
|
+
const abs = resolve7(root, target);
|
|
55794
56943
|
let real;
|
|
55795
56944
|
try {
|
|
55796
56945
|
real = realpathSync2(abs);
|
|
55797
56946
|
} catch {
|
|
55798
56947
|
throw new Error(`file not found: ${target}`);
|
|
55799
56948
|
}
|
|
55800
|
-
const rel =
|
|
56949
|
+
const rel = relative8(root, real);
|
|
55801
56950
|
const inside = rel !== "" && !rel.startsWith("..") && !isAbsolute(rel);
|
|
55802
56951
|
if (inside) return real;
|
|
55803
56952
|
if (rules.allow.some((r) => matchRead(r, real))) return real;
|
|
@@ -56154,8 +57303,8 @@ init_esm_shims();
|
|
|
56154
57303
|
|
|
56155
57304
|
// src/code/symbols.ts
|
|
56156
57305
|
init_esm_shims();
|
|
56157
|
-
import { existsSync as existsSync16, readFileSync as
|
|
56158
|
-
import { join as
|
|
57306
|
+
import { existsSync as existsSync16, readFileSync as readFileSync17 } from "fs";
|
|
57307
|
+
import { join as join23 } from "path";
|
|
56159
57308
|
|
|
56160
57309
|
// src/code/namepath.ts
|
|
56161
57310
|
init_esm_shims();
|
|
@@ -56224,10 +57373,10 @@ function children(db, parent, depth = 1) {
|
|
|
56224
57373
|
}
|
|
56225
57374
|
function symbolBody(db, root, n) {
|
|
56226
57375
|
if (!n.path || !n.start_line || !n.end_line) return void 0;
|
|
56227
|
-
const abs =
|
|
57376
|
+
const abs = join23(root, n.path);
|
|
56228
57377
|
if (existsSync16(abs)) {
|
|
56229
57378
|
try {
|
|
56230
|
-
return
|
|
57379
|
+
return readFileSync17(abs, "utf8").split("\n").slice(n.start_line - 1, n.end_line).join("\n");
|
|
56231
57380
|
} catch {
|
|
56232
57381
|
}
|
|
56233
57382
|
}
|
|
@@ -57253,7 +58402,7 @@ function referrerLabel(db, id, nodes) {
|
|
|
57253
58402
|
}
|
|
57254
58403
|
var emSymbols = defineTool({
|
|
57255
58404
|
name: "em_symbols",
|
|
57256
|
-
description: "Symbol-level code navigation on the tree-sitter graph (TS/JS, Python, Go): overview lists every symbol in a file with kinds and line ranges; find matches a name path (`method`, `Class/method`, `Class.method`, `/Class/method` for whole-name, `src/x.ts#Class.method`), optionally with the body; references lists what calls, references, extends or implements a symbol, grouped by the referencing symbol. Compact output; prefer this over reading whole files.",
|
|
58405
|
+
description: "Symbol-level code navigation on the tree-sitter graph (TS/JS, Python, Go, PHP): overview lists every symbol in a file with kinds and line ranges; find matches a name path (`method`, `Class/method`, `Class.method`, `/Class/method` for whole-name, `src/x.ts#Class.method`), optionally with the body; references lists what calls, references, extends or implements a symbol, grouped by the referencing symbol. Compact output; prefer this over reading whole files.",
|
|
57257
58406
|
schema: {
|
|
57258
58407
|
mode: external_exports.enum(["overview", "find", "references"]).optional().describe("default find"),
|
|
57259
58408
|
file: external_exports.string().optional().describe("overview: the file; find/references: restrict to (or referrers in) this path"),
|