@neat.is/core 0.6.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-5PVQJLPR.js → chunk-3YUNROLT.js} +2 -2
- package/dist/{chunk-CS4GHQO3.js → chunk-7C6ZULNU.js} +114 -8
- package/dist/chunk-7C6ZULNU.js.map +1 -0
- package/dist/cli.cjs +113 -7
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +2 -2
- package/dist/index.cjs +113 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/neatd.cjs +113 -7
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +2 -2
- package/dist/server.cjs +113 -7
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-CS4GHQO3.js.map +0 -1
- /package/dist/{chunk-5PVQJLPR.js.map → chunk-3YUNROLT.js.map} +0 -0
package/dist/neatd.js
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
import {
|
|
3
3
|
reconcileDaemonRecordSync,
|
|
4
4
|
startDaemon
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-3YUNROLT.js";
|
|
6
6
|
import {
|
|
7
7
|
listProjects,
|
|
8
8
|
registryPath
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-7C6ZULNU.js";
|
|
10
10
|
import {
|
|
11
11
|
BindAuthorityError,
|
|
12
12
|
__require
|
package/dist/server.cjs
CHANGED
|
@@ -5863,6 +5863,7 @@ init_cjs_shims();
|
|
|
5863
5863
|
var import_node_path24 = __toESM(require("path"), 1);
|
|
5864
5864
|
var import_tree_sitter2 = __toESM(require("tree-sitter"), 1);
|
|
5865
5865
|
var import_tree_sitter_javascript2 = __toESM(require("tree-sitter-javascript"), 1);
|
|
5866
|
+
var import_tree_sitter_python2 = __toESM(require("tree-sitter-python"), 1);
|
|
5866
5867
|
var import_types12 = require("@neat.is/types");
|
|
5867
5868
|
var PARSE_CHUNK2 = 16384;
|
|
5868
5869
|
function parseSource2(parser, source) {
|
|
@@ -5875,6 +5876,11 @@ function makeJsParser2() {
|
|
|
5875
5876
|
p.setLanguage(import_tree_sitter_javascript2.default);
|
|
5876
5877
|
return p;
|
|
5877
5878
|
}
|
|
5879
|
+
function makePyParser2() {
|
|
5880
|
+
const p = new import_tree_sitter2.default();
|
|
5881
|
+
p.setLanguage(import_tree_sitter_python2.default);
|
|
5882
|
+
return p;
|
|
5883
|
+
}
|
|
5878
5884
|
var ROUTER_METHODS = /* @__PURE__ */ new Set([
|
|
5879
5885
|
"get",
|
|
5880
5886
|
"post",
|
|
@@ -5887,6 +5893,7 @@ var ROUTER_METHODS = /* @__PURE__ */ new Set([
|
|
|
5887
5893
|
]);
|
|
5888
5894
|
var NEXT_APP_METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
|
|
5889
5895
|
var JS_ROUTE_EXTENSIONS = /* @__PURE__ */ new Set([".js", ".jsx", ".mjs", ".cjs", ".ts", ".tsx"]);
|
|
5896
|
+
var FASTAPI_METHODS = /* @__PURE__ */ new Set(["get", "post", "put", "patch", "delete", "options", "head", "trace"]);
|
|
5890
5897
|
function canonicalizeTemplate(raw) {
|
|
5891
5898
|
let p = raw.split("?")[0].split("#")[0];
|
|
5892
5899
|
if (!p.startsWith("/")) p = "/" + p;
|
|
@@ -6114,8 +6121,102 @@ function nextRoutesFromFile(source, relFile, parser) {
|
|
|
6114
6121
|
}
|
|
6115
6122
|
return [];
|
|
6116
6123
|
}
|
|
6124
|
+
function pyStaticStringText(node) {
|
|
6125
|
+
if (node.type !== "string") return null;
|
|
6126
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
6127
|
+
const child = node.namedChild(i);
|
|
6128
|
+
if (child?.type === "interpolation") return null;
|
|
6129
|
+
if (child?.type === "string_content") return child.text;
|
|
6130
|
+
}
|
|
6131
|
+
return "";
|
|
6132
|
+
}
|
|
6133
|
+
function keywordArrayStrings(argsNode, key) {
|
|
6134
|
+
for (let i = 0; i < argsNode.namedChildCount; i++) {
|
|
6135
|
+
const arg = argsNode.namedChild(i);
|
|
6136
|
+
if (arg?.type !== "keyword_argument") continue;
|
|
6137
|
+
if (arg.childForFieldName("name")?.text !== key) continue;
|
|
6138
|
+
const val = arg.childForFieldName("value");
|
|
6139
|
+
if (!val || val.type !== "list") return [];
|
|
6140
|
+
const out = [];
|
|
6141
|
+
for (let j = 0; j < val.namedChildCount; j++) {
|
|
6142
|
+
const el = val.namedChild(j);
|
|
6143
|
+
if (el?.type === "string") {
|
|
6144
|
+
const s = pyStaticStringText(el);
|
|
6145
|
+
if (s) out.push(s);
|
|
6146
|
+
}
|
|
6147
|
+
}
|
|
6148
|
+
return out;
|
|
6149
|
+
}
|
|
6150
|
+
return [];
|
|
6151
|
+
}
|
|
6152
|
+
function collectApiRouterPrefixes(root) {
|
|
6153
|
+
const prefixes = /* @__PURE__ */ new Map();
|
|
6154
|
+
walk(root, (node) => {
|
|
6155
|
+
if (node.type !== "assignment") return;
|
|
6156
|
+
const right = node.childForFieldName("right");
|
|
6157
|
+
if (!right || right.type !== "call") return;
|
|
6158
|
+
const fn = right.childForFieldName("function");
|
|
6159
|
+
if (!fn) return;
|
|
6160
|
+
const ctor = fn.type === "attribute" ? fn.childForFieldName("attribute")?.text : fn.text;
|
|
6161
|
+
if (ctor !== "APIRouter") return;
|
|
6162
|
+
const left = node.childForFieldName("left");
|
|
6163
|
+
if (!left || left.type !== "identifier") return;
|
|
6164
|
+
const args = right.childForFieldName("arguments");
|
|
6165
|
+
if (!args) return;
|
|
6166
|
+
for (let i = 0; i < args.namedChildCount; i++) {
|
|
6167
|
+
const arg = args.namedChild(i);
|
|
6168
|
+
if (arg?.type !== "keyword_argument") continue;
|
|
6169
|
+
if (arg.childForFieldName("name")?.text !== "prefix") continue;
|
|
6170
|
+
const val = arg.childForFieldName("value");
|
|
6171
|
+
const p = val ? pyStaticStringText(val) : null;
|
|
6172
|
+
if (p !== null) prefixes.set(left.text, p);
|
|
6173
|
+
}
|
|
6174
|
+
});
|
|
6175
|
+
return prefixes;
|
|
6176
|
+
}
|
|
6177
|
+
function fastapiRoutesFromSource(source, parser) {
|
|
6178
|
+
const tree = parseSource2(parser, source);
|
|
6179
|
+
const prefixes = collectApiRouterPrefixes(tree.rootNode);
|
|
6180
|
+
const out = [];
|
|
6181
|
+
walk(tree.rootNode, (node) => {
|
|
6182
|
+
if (node.type !== "decorator") return;
|
|
6183
|
+
const call = node.namedChild(0);
|
|
6184
|
+
if (!call || call.type !== "call") return;
|
|
6185
|
+
const fn = call.childForFieldName("function");
|
|
6186
|
+
if (!fn || fn.type !== "attribute") return;
|
|
6187
|
+
const method = fn.childForFieldName("attribute")?.text?.toLowerCase();
|
|
6188
|
+
if (!method) return;
|
|
6189
|
+
const isVerb = FASTAPI_METHODS.has(method);
|
|
6190
|
+
if (!isVerb && method !== "api_route") return;
|
|
6191
|
+
const args = call.childForFieldName("arguments");
|
|
6192
|
+
const first = args?.namedChild(0);
|
|
6193
|
+
if (!first || first.type !== "string") return;
|
|
6194
|
+
const rawPath = pyStaticStringText(first);
|
|
6195
|
+
if (rawPath === null || !rawPath.startsWith("/")) return;
|
|
6196
|
+
const obj = fn.childForFieldName("object")?.text;
|
|
6197
|
+
const prefix = obj ? prefixes.get(obj) ?? "" : "";
|
|
6198
|
+
const pathTemplate = canonicalizeTemplate(prefix + rawPath);
|
|
6199
|
+
const line = node.startPosition.row + 1;
|
|
6200
|
+
if (isVerb) {
|
|
6201
|
+
out.push({ method: method.toUpperCase(), pathTemplate, line, framework: "fastapi" });
|
|
6202
|
+
return;
|
|
6203
|
+
}
|
|
6204
|
+
const methods = keywordArrayStrings(args, "methods");
|
|
6205
|
+
const list = methods.length > 0 ? methods : ["ALL"];
|
|
6206
|
+
for (const m of list) {
|
|
6207
|
+
out.push({
|
|
6208
|
+
method: m === "ALL" ? "ALL" : m.toUpperCase(),
|
|
6209
|
+
pathTemplate,
|
|
6210
|
+
line,
|
|
6211
|
+
framework: "fastapi"
|
|
6212
|
+
});
|
|
6213
|
+
}
|
|
6214
|
+
});
|
|
6215
|
+
return out;
|
|
6216
|
+
}
|
|
6117
6217
|
async function addRoutes(graph, services) {
|
|
6118
6218
|
const jsParser = makeJsParser2();
|
|
6219
|
+
const pyParser = makePyParser2();
|
|
6119
6220
|
let nodesAdded = 0;
|
|
6120
6221
|
let edgesAdded = 0;
|
|
6121
6222
|
for (const service of services) {
|
|
@@ -6127,15 +6228,20 @@ async function addRoutes(graph, services) {
|
|
|
6127
6228
|
const hasFastify = deps["fastify"] !== void 0;
|
|
6128
6229
|
const hasHono = deps["hono"] !== void 0;
|
|
6129
6230
|
const hasNext = deps["next"] !== void 0;
|
|
6130
|
-
|
|
6231
|
+
const hasFastapi = deps["fastapi"] !== void 0;
|
|
6232
|
+
if (!hasExpress && !hasFastify && !hasHono && !hasNext && !hasFastapi) continue;
|
|
6131
6233
|
const files = await loadSourceFiles(service.dir);
|
|
6132
6234
|
for (const file of files) {
|
|
6133
6235
|
if (isTestPath(file.path)) continue;
|
|
6134
|
-
|
|
6236
|
+
const ext = import_node_path24.default.extname(file.path);
|
|
6237
|
+
const isPy = ext === ".py";
|
|
6238
|
+
if (!JS_ROUTE_EXTENSIONS.has(ext) && !isPy) continue;
|
|
6135
6239
|
const relFile = toPosix2(import_node_path24.default.relative(service.dir, file.path));
|
|
6136
6240
|
let routes;
|
|
6137
6241
|
try {
|
|
6138
|
-
if (
|
|
6242
|
+
if (isPy) {
|
|
6243
|
+
routes = hasFastapi ? fastapiRoutesFromSource(file.content, pyParser) : [];
|
|
6244
|
+
} else if (hasNext && (isNextAppRouteFile(relFile) || isNextPagesApiFile(relFile))) {
|
|
6139
6245
|
routes = nextRoutesFromFile(file.content, relFile, jsParser);
|
|
6140
6246
|
} else if (hasExpress || hasFastify || hasHono) {
|
|
6141
6247
|
routes = serverRoutesFromSource(file.content, jsParser, hasExpress, hasFastify, hasHono);
|
|
@@ -6319,7 +6425,7 @@ init_cjs_shims();
|
|
|
6319
6425
|
var import_node_path26 = __toESM(require("path"), 1);
|
|
6320
6426
|
var import_tree_sitter3 = __toESM(require("tree-sitter"), 1);
|
|
6321
6427
|
var import_tree_sitter_javascript3 = __toESM(require("tree-sitter-javascript"), 1);
|
|
6322
|
-
var
|
|
6428
|
+
var import_tree_sitter_python3 = __toESM(require("tree-sitter-python"), 1);
|
|
6323
6429
|
var import_types14 = require("@neat.is/types");
|
|
6324
6430
|
var STRING_LITERAL_NODE_TYPES = /* @__PURE__ */ new Set(["string_fragment", "string_content"]);
|
|
6325
6431
|
var JSX_EXTERNAL_LINK_TAGS = /* @__PURE__ */ new Set(["a", "Link", "NavLink", "ExternalLink", "Anchor"]);
|
|
@@ -6374,14 +6480,14 @@ function makeJsParser3() {
|
|
|
6374
6480
|
p.setLanguage(import_tree_sitter_javascript3.default);
|
|
6375
6481
|
return p;
|
|
6376
6482
|
}
|
|
6377
|
-
function
|
|
6483
|
+
function makePyParser3() {
|
|
6378
6484
|
const p = new import_tree_sitter3.default();
|
|
6379
|
-
p.setLanguage(
|
|
6485
|
+
p.setLanguage(import_tree_sitter_python3.default);
|
|
6380
6486
|
return p;
|
|
6381
6487
|
}
|
|
6382
6488
|
async function addHttpCallEdges(graph, services) {
|
|
6383
6489
|
const jsParser = makeJsParser3();
|
|
6384
|
-
const pyParser =
|
|
6490
|
+
const pyParser = makePyParser3();
|
|
6385
6491
|
const { knownHosts, hostToNodeId } = buildServiceHostIndex(services);
|
|
6386
6492
|
let nodesAdded = 0;
|
|
6387
6493
|
let edgesAdded = 0;
|