@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/cli.cjs
CHANGED
|
@@ -5363,6 +5363,7 @@ init_cjs_shims();
|
|
|
5363
5363
|
var import_node_path23 = __toESM(require("path"), 1);
|
|
5364
5364
|
var import_tree_sitter2 = __toESM(require("tree-sitter"), 1);
|
|
5365
5365
|
var import_tree_sitter_javascript2 = __toESM(require("tree-sitter-javascript"), 1);
|
|
5366
|
+
var import_tree_sitter_python2 = __toESM(require("tree-sitter-python"), 1);
|
|
5366
5367
|
var import_types11 = require("@neat.is/types");
|
|
5367
5368
|
var PARSE_CHUNK2 = 16384;
|
|
5368
5369
|
function parseSource2(parser, source) {
|
|
@@ -5375,6 +5376,11 @@ function makeJsParser2() {
|
|
|
5375
5376
|
p.setLanguage(import_tree_sitter_javascript2.default);
|
|
5376
5377
|
return p;
|
|
5377
5378
|
}
|
|
5379
|
+
function makePyParser2() {
|
|
5380
|
+
const p = new import_tree_sitter2.default();
|
|
5381
|
+
p.setLanguage(import_tree_sitter_python2.default);
|
|
5382
|
+
return p;
|
|
5383
|
+
}
|
|
5378
5384
|
var ROUTER_METHODS = /* @__PURE__ */ new Set([
|
|
5379
5385
|
"get",
|
|
5380
5386
|
"post",
|
|
@@ -5387,6 +5393,7 @@ var ROUTER_METHODS = /* @__PURE__ */ new Set([
|
|
|
5387
5393
|
]);
|
|
5388
5394
|
var NEXT_APP_METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
|
|
5389
5395
|
var JS_ROUTE_EXTENSIONS = /* @__PURE__ */ new Set([".js", ".jsx", ".mjs", ".cjs", ".ts", ".tsx"]);
|
|
5396
|
+
var FASTAPI_METHODS = /* @__PURE__ */ new Set(["get", "post", "put", "patch", "delete", "options", "head", "trace"]);
|
|
5390
5397
|
function canonicalizeTemplate(raw) {
|
|
5391
5398
|
let p = raw.split("?")[0].split("#")[0];
|
|
5392
5399
|
if (!p.startsWith("/")) p = "/" + p;
|
|
@@ -5614,8 +5621,102 @@ function nextRoutesFromFile(source, relFile, parser) {
|
|
|
5614
5621
|
}
|
|
5615
5622
|
return [];
|
|
5616
5623
|
}
|
|
5624
|
+
function pyStaticStringText(node) {
|
|
5625
|
+
if (node.type !== "string") return null;
|
|
5626
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
5627
|
+
const child = node.namedChild(i);
|
|
5628
|
+
if (child?.type === "interpolation") return null;
|
|
5629
|
+
if (child?.type === "string_content") return child.text;
|
|
5630
|
+
}
|
|
5631
|
+
return "";
|
|
5632
|
+
}
|
|
5633
|
+
function keywordArrayStrings(argsNode, key) {
|
|
5634
|
+
for (let i = 0; i < argsNode.namedChildCount; i++) {
|
|
5635
|
+
const arg = argsNode.namedChild(i);
|
|
5636
|
+
if (arg?.type !== "keyword_argument") continue;
|
|
5637
|
+
if (arg.childForFieldName("name")?.text !== key) continue;
|
|
5638
|
+
const val = arg.childForFieldName("value");
|
|
5639
|
+
if (!val || val.type !== "list") return [];
|
|
5640
|
+
const out = [];
|
|
5641
|
+
for (let j = 0; j < val.namedChildCount; j++) {
|
|
5642
|
+
const el = val.namedChild(j);
|
|
5643
|
+
if (el?.type === "string") {
|
|
5644
|
+
const s = pyStaticStringText(el);
|
|
5645
|
+
if (s) out.push(s);
|
|
5646
|
+
}
|
|
5647
|
+
}
|
|
5648
|
+
return out;
|
|
5649
|
+
}
|
|
5650
|
+
return [];
|
|
5651
|
+
}
|
|
5652
|
+
function collectApiRouterPrefixes(root) {
|
|
5653
|
+
const prefixes = /* @__PURE__ */ new Map();
|
|
5654
|
+
walk(root, (node) => {
|
|
5655
|
+
if (node.type !== "assignment") return;
|
|
5656
|
+
const right = node.childForFieldName("right");
|
|
5657
|
+
if (!right || right.type !== "call") return;
|
|
5658
|
+
const fn = right.childForFieldName("function");
|
|
5659
|
+
if (!fn) return;
|
|
5660
|
+
const ctor = fn.type === "attribute" ? fn.childForFieldName("attribute")?.text : fn.text;
|
|
5661
|
+
if (ctor !== "APIRouter") return;
|
|
5662
|
+
const left = node.childForFieldName("left");
|
|
5663
|
+
if (!left || left.type !== "identifier") return;
|
|
5664
|
+
const args = right.childForFieldName("arguments");
|
|
5665
|
+
if (!args) return;
|
|
5666
|
+
for (let i = 0; i < args.namedChildCount; i++) {
|
|
5667
|
+
const arg = args.namedChild(i);
|
|
5668
|
+
if (arg?.type !== "keyword_argument") continue;
|
|
5669
|
+
if (arg.childForFieldName("name")?.text !== "prefix") continue;
|
|
5670
|
+
const val = arg.childForFieldName("value");
|
|
5671
|
+
const p = val ? pyStaticStringText(val) : null;
|
|
5672
|
+
if (p !== null) prefixes.set(left.text, p);
|
|
5673
|
+
}
|
|
5674
|
+
});
|
|
5675
|
+
return prefixes;
|
|
5676
|
+
}
|
|
5677
|
+
function fastapiRoutesFromSource(source, parser) {
|
|
5678
|
+
const tree = parseSource2(parser, source);
|
|
5679
|
+
const prefixes = collectApiRouterPrefixes(tree.rootNode);
|
|
5680
|
+
const out = [];
|
|
5681
|
+
walk(tree.rootNode, (node) => {
|
|
5682
|
+
if (node.type !== "decorator") return;
|
|
5683
|
+
const call = node.namedChild(0);
|
|
5684
|
+
if (!call || call.type !== "call") return;
|
|
5685
|
+
const fn = call.childForFieldName("function");
|
|
5686
|
+
if (!fn || fn.type !== "attribute") return;
|
|
5687
|
+
const method = fn.childForFieldName("attribute")?.text?.toLowerCase();
|
|
5688
|
+
if (!method) return;
|
|
5689
|
+
const isVerb = FASTAPI_METHODS.has(method);
|
|
5690
|
+
if (!isVerb && method !== "api_route") return;
|
|
5691
|
+
const args = call.childForFieldName("arguments");
|
|
5692
|
+
const first = args?.namedChild(0);
|
|
5693
|
+
if (!first || first.type !== "string") return;
|
|
5694
|
+
const rawPath = pyStaticStringText(first);
|
|
5695
|
+
if (rawPath === null || !rawPath.startsWith("/")) return;
|
|
5696
|
+
const obj = fn.childForFieldName("object")?.text;
|
|
5697
|
+
const prefix = obj ? prefixes.get(obj) ?? "" : "";
|
|
5698
|
+
const pathTemplate = canonicalizeTemplate(prefix + rawPath);
|
|
5699
|
+
const line = node.startPosition.row + 1;
|
|
5700
|
+
if (isVerb) {
|
|
5701
|
+
out.push({ method: method.toUpperCase(), pathTemplate, line, framework: "fastapi" });
|
|
5702
|
+
return;
|
|
5703
|
+
}
|
|
5704
|
+
const methods = keywordArrayStrings(args, "methods");
|
|
5705
|
+
const list = methods.length > 0 ? methods : ["ALL"];
|
|
5706
|
+
for (const m of list) {
|
|
5707
|
+
out.push({
|
|
5708
|
+
method: m === "ALL" ? "ALL" : m.toUpperCase(),
|
|
5709
|
+
pathTemplate,
|
|
5710
|
+
line,
|
|
5711
|
+
framework: "fastapi"
|
|
5712
|
+
});
|
|
5713
|
+
}
|
|
5714
|
+
});
|
|
5715
|
+
return out;
|
|
5716
|
+
}
|
|
5617
5717
|
async function addRoutes(graph, services) {
|
|
5618
5718
|
const jsParser = makeJsParser2();
|
|
5719
|
+
const pyParser = makePyParser2();
|
|
5619
5720
|
let nodesAdded = 0;
|
|
5620
5721
|
let edgesAdded = 0;
|
|
5621
5722
|
for (const service of services) {
|
|
@@ -5627,15 +5728,20 @@ async function addRoutes(graph, services) {
|
|
|
5627
5728
|
const hasFastify = deps["fastify"] !== void 0;
|
|
5628
5729
|
const hasHono = deps["hono"] !== void 0;
|
|
5629
5730
|
const hasNext = deps["next"] !== void 0;
|
|
5630
|
-
|
|
5731
|
+
const hasFastapi = deps["fastapi"] !== void 0;
|
|
5732
|
+
if (!hasExpress && !hasFastify && !hasHono && !hasNext && !hasFastapi) continue;
|
|
5631
5733
|
const files = await loadSourceFiles(service.dir);
|
|
5632
5734
|
for (const file of files) {
|
|
5633
5735
|
if (isTestPath(file.path)) continue;
|
|
5634
|
-
|
|
5736
|
+
const ext = import_node_path23.default.extname(file.path);
|
|
5737
|
+
const isPy = ext === ".py";
|
|
5738
|
+
if (!JS_ROUTE_EXTENSIONS.has(ext) && !isPy) continue;
|
|
5635
5739
|
const relFile = toPosix2(import_node_path23.default.relative(service.dir, file.path));
|
|
5636
5740
|
let routes;
|
|
5637
5741
|
try {
|
|
5638
|
-
if (
|
|
5742
|
+
if (isPy) {
|
|
5743
|
+
routes = hasFastapi ? fastapiRoutesFromSource(file.content, pyParser) : [];
|
|
5744
|
+
} else if (hasNext && (isNextAppRouteFile(relFile) || isNextPagesApiFile(relFile))) {
|
|
5639
5745
|
routes = nextRoutesFromFile(file.content, relFile, jsParser);
|
|
5640
5746
|
} else if (hasExpress || hasFastify || hasHono) {
|
|
5641
5747
|
routes = serverRoutesFromSource(file.content, jsParser, hasExpress, hasFastify, hasHono);
|
|
@@ -5819,7 +5925,7 @@ init_cjs_shims();
|
|
|
5819
5925
|
var import_node_path25 = __toESM(require("path"), 1);
|
|
5820
5926
|
var import_tree_sitter3 = __toESM(require("tree-sitter"), 1);
|
|
5821
5927
|
var import_tree_sitter_javascript3 = __toESM(require("tree-sitter-javascript"), 1);
|
|
5822
|
-
var
|
|
5928
|
+
var import_tree_sitter_python3 = __toESM(require("tree-sitter-python"), 1);
|
|
5823
5929
|
var import_types13 = require("@neat.is/types");
|
|
5824
5930
|
var STRING_LITERAL_NODE_TYPES = /* @__PURE__ */ new Set(["string_fragment", "string_content"]);
|
|
5825
5931
|
var JSX_EXTERNAL_LINK_TAGS = /* @__PURE__ */ new Set(["a", "Link", "NavLink", "ExternalLink", "Anchor"]);
|
|
@@ -5874,14 +5980,14 @@ function makeJsParser3() {
|
|
|
5874
5980
|
p.setLanguage(import_tree_sitter_javascript3.default);
|
|
5875
5981
|
return p;
|
|
5876
5982
|
}
|
|
5877
|
-
function
|
|
5983
|
+
function makePyParser3() {
|
|
5878
5984
|
const p = new import_tree_sitter3.default();
|
|
5879
|
-
p.setLanguage(
|
|
5985
|
+
p.setLanguage(import_tree_sitter_python3.default);
|
|
5880
5986
|
return p;
|
|
5881
5987
|
}
|
|
5882
5988
|
async function addHttpCallEdges(graph, services) {
|
|
5883
5989
|
const jsParser = makeJsParser3();
|
|
5884
|
-
const pyParser =
|
|
5990
|
+
const pyParser = makePyParser3();
|
|
5885
5991
|
const { knownHosts, hostToNodeId } = buildServiceHostIndex(services);
|
|
5886
5992
|
let nodesAdded = 0;
|
|
5887
5993
|
let edgesAdded = 0;
|