@contractspec/lib.source-extractors 0.2.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/README.md +86 -0
- package/dist/_virtual/rolldown_runtime.js +18 -0
- package/dist/codegen/index.d.ts +12 -0
- package/dist/codegen/index.d.ts.map +1 -0
- package/dist/codegen/index.js +17 -0
- package/dist/codegen/index.js.map +1 -0
- package/dist/codegen/operation-gen.d.ts +16 -0
- package/dist/codegen/operation-gen.d.ts.map +1 -0
- package/dist/codegen/operation-gen.js +91 -0
- package/dist/codegen/operation-gen.js.map +1 -0
- package/dist/codegen/registry-gen.d.ts +11 -0
- package/dist/codegen/registry-gen.d.ts.map +1 -0
- package/dist/codegen/registry-gen.js +47 -0
- package/dist/codegen/registry-gen.js.map +1 -0
- package/dist/codegen/schema-gen.d.ts +16 -0
- package/dist/codegen/schema-gen.d.ts.map +1 -0
- package/dist/codegen/schema-gen.js +93 -0
- package/dist/codegen/schema-gen.js.map +1 -0
- package/dist/codegen/types.d.ts +48 -0
- package/dist/codegen/types.d.ts.map +1 -0
- package/dist/detect.d.ts +47 -0
- package/dist/detect.d.ts.map +1 -0
- package/dist/detect.js +177 -0
- package/dist/detect.js.map +1 -0
- package/dist/extract.d.ts +24 -0
- package/dist/extract.d.ts.map +1 -0
- package/dist/extract.js +125 -0
- package/dist/extract.js.map +1 -0
- package/dist/extractors/base.d.ts +90 -0
- package/dist/extractors/base.d.ts.map +1 -0
- package/dist/extractors/base.js +152 -0
- package/dist/extractors/base.js.map +1 -0
- package/dist/extractors/elysia/extractor.d.ts +15 -0
- package/dist/extractors/elysia/extractor.d.ts.map +1 -0
- package/dist/extractors/elysia/extractor.js +58 -0
- package/dist/extractors/elysia/extractor.js.map +1 -0
- package/dist/extractors/express/extractor.d.ts +15 -0
- package/dist/extractors/express/extractor.d.ts.map +1 -0
- package/dist/extractors/express/extractor.js +61 -0
- package/dist/extractors/express/extractor.js.map +1 -0
- package/dist/extractors/fastify/extractor.d.ts +15 -0
- package/dist/extractors/fastify/extractor.d.ts.map +1 -0
- package/dist/extractors/fastify/extractor.js +61 -0
- package/dist/extractors/fastify/extractor.js.map +1 -0
- package/dist/extractors/hono/extractor.d.ts +15 -0
- package/dist/extractors/hono/extractor.d.ts.map +1 -0
- package/dist/extractors/hono/extractor.js +57 -0
- package/dist/extractors/hono/extractor.js.map +1 -0
- package/dist/extractors/index.d.ts +21 -0
- package/dist/extractors/index.d.ts.map +1 -0
- package/dist/extractors/index.js +42 -0
- package/dist/extractors/index.js.map +1 -0
- package/dist/extractors/nestjs/extractor.d.ts +29 -0
- package/dist/extractors/nestjs/extractor.d.ts.map +1 -0
- package/dist/extractors/nestjs/extractor.js +118 -0
- package/dist/extractors/nestjs/extractor.js.map +1 -0
- package/dist/extractors/next-api/extractor.d.ts +16 -0
- package/dist/extractors/next-api/extractor.d.ts.map +1 -0
- package/dist/extractors/next-api/extractor.js +80 -0
- package/dist/extractors/next-api/extractor.js.map +1 -0
- package/dist/extractors/trpc/extractor.d.ts +15 -0
- package/dist/extractors/trpc/extractor.d.ts.map +1 -0
- package/dist/extractors/trpc/extractor.js +71 -0
- package/dist/extractors/trpc/extractor.js.map +1 -0
- package/dist/extractors/zod/extractor.d.ts +16 -0
- package/dist/extractors/zod/extractor.d.ts.map +1 -0
- package/dist/extractors/zod/extractor.js +69 -0
- package/dist/extractors/zod/extractor.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +7 -0
- package/dist/registry.d.ts +85 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +87 -0
- package/dist/registry.js.map +1 -0
- package/dist/types.d.ts +272 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +0 -0
- package/package.json +71 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { BaseExtractor } from "../base.js";
|
|
2
|
+
|
|
3
|
+
//#region src/extractors/elysia/extractor.ts
|
|
4
|
+
/**
|
|
5
|
+
* Elysia extractor.
|
|
6
|
+
*
|
|
7
|
+
* Extracts contract candidates from Elysia applications by parsing:
|
|
8
|
+
* - app.get(), app.post(), etc. route handlers
|
|
9
|
+
* - t.* schema definitions
|
|
10
|
+
*/
|
|
11
|
+
const PATTERNS = {
|
|
12
|
+
route: /\.(get|post|put|patch|delete)\s*\(\s*['"`]([^'"`]+)['"`]/gi,
|
|
13
|
+
tSchema: /body:\s*t\.\w+/g
|
|
14
|
+
};
|
|
15
|
+
var ElysiaExtractor = class extends BaseExtractor {
|
|
16
|
+
id = "elysia";
|
|
17
|
+
name = "Elysia Extractor";
|
|
18
|
+
frameworks = ["elysia"];
|
|
19
|
+
priority = 15;
|
|
20
|
+
async doExtract(ctx) {
|
|
21
|
+
const { project, options, fs } = ctx;
|
|
22
|
+
const pattern = options.scope?.length ? options.scope.map((s) => `${s}/**/*.ts`).join(",") : "**/*.ts";
|
|
23
|
+
const files = await fs.glob(pattern, { cwd: project.rootPath });
|
|
24
|
+
ctx.ir.stats.filesScanned = files.length;
|
|
25
|
+
for (const file of files) {
|
|
26
|
+
if (file.includes("node_modules") || file.includes(".test.")) continue;
|
|
27
|
+
const fullPath = `${project.rootPath}/${file}`;
|
|
28
|
+
const content = await fs.readFile(fullPath);
|
|
29
|
+
if (!content.includes("elysia")) continue;
|
|
30
|
+
await this.extractRoutes(ctx, file, content);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async extractRoutes(ctx, file, content) {
|
|
34
|
+
const matches = [...content.matchAll(PATTERNS.route)];
|
|
35
|
+
for (const match of matches) {
|
|
36
|
+
const method = match[1]?.toUpperCase() ?? "GET";
|
|
37
|
+
const path = match[2] ?? "/";
|
|
38
|
+
const index = match.index ?? 0;
|
|
39
|
+
const lineNumber = content.slice(0, index).split("\n").length;
|
|
40
|
+
const afterMatch = content.slice(index, index + 500);
|
|
41
|
+
const hasTSchema = PATTERNS.tSchema.test(afterMatch);
|
|
42
|
+
const endpoint = {
|
|
43
|
+
id: this.generateEndpointId(method, path),
|
|
44
|
+
method,
|
|
45
|
+
path,
|
|
46
|
+
kind: this.methodToOpKind(method),
|
|
47
|
+
handlerName: "handler",
|
|
48
|
+
source: this.createLocation(file, lineNumber, lineNumber + 5),
|
|
49
|
+
confidence: this.createConfidence(hasTSchema ? "high" : "medium", hasTSchema ? "explicit-schema" : "decorator-hints")
|
|
50
|
+
};
|
|
51
|
+
this.addEndpoint(ctx, endpoint);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
//#endregion
|
|
57
|
+
export { ElysiaExtractor };
|
|
58
|
+
//# sourceMappingURL=extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractor.js","names":[],"sources":["../../../src/extractors/elysia/extractor.ts"],"sourcesContent":["/**\n * Elysia extractor.\n *\n * Extracts contract candidates from Elysia applications by parsing:\n * - app.get(), app.post(), etc. route handlers\n * - t.* schema definitions\n */\n\nimport { BaseExtractor, type ExtractionContext } from '../base';\nimport type { EndpointCandidate, HttpMethod } from '../../types';\n\nconst PATTERNS = {\n route: /\\.(get|post|put|patch|delete)\\s*\\(\\s*['\"`]([^'\"`]+)['\"`]/gi,\n tSchema: /body:\\s*t\\.\\w+/g,\n};\n\nexport class ElysiaExtractor extends BaseExtractor {\n id = 'elysia';\n name = 'Elysia Extractor';\n frameworks = ['elysia'];\n priority = 15;\n\n protected async doExtract(ctx: ExtractionContext): Promise<void> {\n const { project, options, fs } = ctx;\n\n const pattern = options.scope?.length\n ? options.scope.map((s) => `${s}/**/*.ts`).join(',')\n : '**/*.ts';\n\n const files = await fs.glob(pattern, { cwd: project.rootPath });\n ctx.ir.stats.filesScanned = files.length;\n\n for (const file of files) {\n if (file.includes('node_modules') || file.includes('.test.')) continue;\n\n const fullPath = `${project.rootPath}/${file}`;\n const content = await fs.readFile(fullPath);\n\n if (!content.includes('elysia')) continue;\n\n await this.extractRoutes(ctx, file, content);\n }\n }\n\n private async extractRoutes(\n ctx: ExtractionContext,\n file: string,\n content: string\n ): Promise<void> {\n const matches = [...content.matchAll(PATTERNS.route)];\n\n for (const match of matches) {\n const method = (match[1]?.toUpperCase() ?? 'GET') as HttpMethod;\n const path = match[2] ?? '/';\n const index = match.index ?? 0;\n const lineNumber = content.slice(0, index).split('\\n').length;\n\n const afterMatch = content.slice(index, index + 500);\n const hasTSchema = PATTERNS.tSchema.test(afterMatch);\n\n const endpoint: EndpointCandidate = {\n id: this.generateEndpointId(method, path),\n method,\n path,\n kind: this.methodToOpKind(method),\n handlerName: 'handler',\n source: this.createLocation(file, lineNumber, lineNumber + 5),\n confidence: this.createConfidence(\n hasTSchema ? 'high' : 'medium',\n hasTSchema ? 'explicit-schema' : 'decorator-hints'\n ),\n };\n\n this.addEndpoint(ctx, endpoint);\n }\n }\n}\n"],"mappings":";;;;;;;;;;AAWA,MAAM,WAAW;CACf,OAAO;CACP,SAAS;CACV;AAED,IAAa,kBAAb,cAAqC,cAAc;CACjD,KAAK;CACL,OAAO;CACP,aAAa,CAAC,SAAS;CACvB,WAAW;CAEX,MAAgB,UAAU,KAAuC;EAC/D,MAAM,EAAE,SAAS,SAAS,OAAO;EAEjC,MAAM,UAAU,QAAQ,OAAO,SAC3B,QAAQ,MAAM,KAAK,MAAM,GAAG,EAAE,UAAU,CAAC,KAAK,IAAI,GAClD;EAEJ,MAAM,QAAQ,MAAM,GAAG,KAAK,SAAS,EAAE,KAAK,QAAQ,UAAU,CAAC;AAC/D,MAAI,GAAG,MAAM,eAAe,MAAM;AAElC,OAAK,MAAM,QAAQ,OAAO;AACxB,OAAI,KAAK,SAAS,eAAe,IAAI,KAAK,SAAS,SAAS,CAAE;GAE9D,MAAM,WAAW,GAAG,QAAQ,SAAS,GAAG;GACxC,MAAM,UAAU,MAAM,GAAG,SAAS,SAAS;AAE3C,OAAI,CAAC,QAAQ,SAAS,SAAS,CAAE;AAEjC,SAAM,KAAK,cAAc,KAAK,MAAM,QAAQ;;;CAIhD,MAAc,cACZ,KACA,MACA,SACe;EACf,MAAM,UAAU,CAAC,GAAG,QAAQ,SAAS,SAAS,MAAM,CAAC;AAErD,OAAK,MAAM,SAAS,SAAS;GAC3B,MAAM,SAAU,MAAM,IAAI,aAAa,IAAI;GAC3C,MAAM,OAAO,MAAM,MAAM;GACzB,MAAM,QAAQ,MAAM,SAAS;GAC7B,MAAM,aAAa,QAAQ,MAAM,GAAG,MAAM,CAAC,MAAM,KAAK,CAAC;GAEvD,MAAM,aAAa,QAAQ,MAAM,OAAO,QAAQ,IAAI;GACpD,MAAM,aAAa,SAAS,QAAQ,KAAK,WAAW;GAEpD,MAAM,WAA8B;IAClC,IAAI,KAAK,mBAAmB,QAAQ,KAAK;IACzC;IACA;IACA,MAAM,KAAK,eAAe,OAAO;IACjC,aAAa;IACb,QAAQ,KAAK,eAAe,MAAM,YAAY,aAAa,EAAE;IAC7D,YAAY,KAAK,iBACf,aAAa,SAAS,UACtB,aAAa,oBAAoB,kBAClC;IACF;AAED,QAAK,YAAY,KAAK,SAAS"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BaseExtractor, ExtractionContext } from "../base.js";
|
|
2
|
+
|
|
3
|
+
//#region src/extractors/express/extractor.d.ts
|
|
4
|
+
|
|
5
|
+
declare class ExpressExtractor extends BaseExtractor {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
frameworks: string[];
|
|
9
|
+
priority: number;
|
|
10
|
+
protected doExtract(ctx: ExtractionContext): Promise<void>;
|
|
11
|
+
private extractRoutes;
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { ExpressExtractor };
|
|
15
|
+
//# sourceMappingURL=extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractor.d.ts","names":[],"sources":["../../../src/extractors/express/extractor.ts"],"sourcesContent":[],"mappings":";;;;cAmBa,gBAAA,SAAyB,aAAA;;;;;2BAML,oBAAoB"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { BaseExtractor } from "../base.js";
|
|
2
|
+
|
|
3
|
+
//#region src/extractors/express/extractor.ts
|
|
4
|
+
/**
|
|
5
|
+
* Express extractor.
|
|
6
|
+
*
|
|
7
|
+
* Extracts contract candidates from Express applications by parsing:
|
|
8
|
+
* - app.get(), app.post(), etc. route handlers
|
|
9
|
+
* - Router instances
|
|
10
|
+
* - Zod validation middleware
|
|
11
|
+
*/
|
|
12
|
+
const PATTERNS = {
|
|
13
|
+
route: /(?:app|router)\.(get|post|put|patch|delete|head|options)\s*\(\s*['"`]([^'"`]+)['"`]/gi,
|
|
14
|
+
routerUse: /(?:app|router)\.use\s*\(\s*['"`]([^'"`]+)['"`]/gi,
|
|
15
|
+
zodValidate: /validate\s*\(\s*(\w+)\s*\)/g
|
|
16
|
+
};
|
|
17
|
+
var ExpressExtractor = class extends BaseExtractor {
|
|
18
|
+
id = "express";
|
|
19
|
+
name = "Express Extractor";
|
|
20
|
+
frameworks = ["express"];
|
|
21
|
+
priority = 15;
|
|
22
|
+
async doExtract(ctx) {
|
|
23
|
+
const { project, options, fs } = ctx;
|
|
24
|
+
const pattern = options.scope?.length ? options.scope.map((s) => `${s}/**/*.ts`).join(",") : "**/*.ts";
|
|
25
|
+
const files = await fs.glob(pattern, { cwd: project.rootPath });
|
|
26
|
+
ctx.ir.stats.filesScanned = files.length;
|
|
27
|
+
for (const file of files) {
|
|
28
|
+
if (file.includes("node_modules") || file.includes(".test.")) continue;
|
|
29
|
+
const fullPath = `${project.rootPath}/${file}`;
|
|
30
|
+
const content = await fs.readFile(fullPath);
|
|
31
|
+
await this.extractRoutes(ctx, file, content);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async extractRoutes(ctx, file, content) {
|
|
35
|
+
const matches = [...content.matchAll(PATTERNS.route)];
|
|
36
|
+
for (const match of matches) {
|
|
37
|
+
const method = match[1]?.toUpperCase() ?? "GET";
|
|
38
|
+
const path = match[2] ?? "/";
|
|
39
|
+
const index = match.index ?? 0;
|
|
40
|
+
const lineNumber = content.slice(0, index).split("\n").length;
|
|
41
|
+
const afterMatch = content.slice(index, index + 500);
|
|
42
|
+
const handlerMatch = afterMatch.match(/(?:async\s+)?(?:function\s+)?(\w+)|,\s*(\w+)\s*\)/);
|
|
43
|
+
const handlerName = handlerMatch?.[1] ?? handlerMatch?.[2] ?? "handler";
|
|
44
|
+
const hasZodValidation = PATTERNS.zodValidate.test(afterMatch);
|
|
45
|
+
const endpoint = {
|
|
46
|
+
id: this.generateEndpointId(method, path, handlerName),
|
|
47
|
+
method,
|
|
48
|
+
path,
|
|
49
|
+
kind: this.methodToOpKind(method),
|
|
50
|
+
handlerName,
|
|
51
|
+
source: this.createLocation(file, lineNumber, lineNumber + 5),
|
|
52
|
+
confidence: this.createConfidence(hasZodValidation ? "high" : "medium", hasZodValidation ? "explicit-schema" : "decorator-hints")
|
|
53
|
+
};
|
|
54
|
+
this.addEndpoint(ctx, endpoint);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
//#endregion
|
|
60
|
+
export { ExpressExtractor };
|
|
61
|
+
//# sourceMappingURL=extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractor.js","names":[],"sources":["../../../src/extractors/express/extractor.ts"],"sourcesContent":["/**\n * Express extractor.\n *\n * Extracts contract candidates from Express applications by parsing:\n * - app.get(), app.post(), etc. route handlers\n * - Router instances\n * - Zod validation middleware\n */\n\nimport { BaseExtractor, type ExtractionContext } from '../base';\nimport type { EndpointCandidate, HttpMethod } from '../../types';\n\nconst PATTERNS = {\n route:\n /(?:app|router)\\.(get|post|put|patch|delete|head|options)\\s*\\(\\s*['\"`]([^'\"`]+)['\"`]/gi,\n routerUse: /(?:app|router)\\.use\\s*\\(\\s*['\"`]([^'\"`]+)['\"`]/gi,\n zodValidate: /validate\\s*\\(\\s*(\\w+)\\s*\\)/g,\n};\n\nexport class ExpressExtractor extends BaseExtractor {\n id = 'express';\n name = 'Express Extractor';\n frameworks = ['express'];\n priority = 15;\n\n protected async doExtract(ctx: ExtractionContext): Promise<void> {\n const { project, options, fs } = ctx;\n\n const pattern = options.scope?.length\n ? options.scope.map((s) => `${s}/**/*.ts`).join(',')\n : '**/*.ts';\n\n const files = await fs.glob(pattern, { cwd: project.rootPath });\n ctx.ir.stats.filesScanned = files.length;\n\n for (const file of files) {\n if (file.includes('node_modules') || file.includes('.test.')) continue;\n\n const fullPath = `${project.rootPath}/${file}`;\n const content = await fs.readFile(fullPath);\n\n await this.extractRoutes(ctx, file, content);\n }\n }\n\n private async extractRoutes(\n ctx: ExtractionContext,\n file: string,\n content: string\n ): Promise<void> {\n const matches = [...content.matchAll(PATTERNS.route)];\n\n for (const match of matches) {\n const method = (match[1]?.toUpperCase() ?? 'GET') as HttpMethod;\n const path = match[2] ?? '/';\n const index = match.index ?? 0;\n const lineNumber = content.slice(0, index).split('\\n').length;\n\n const afterMatch = content.slice(index, index + 500);\n const handlerMatch = afterMatch.match(\n /(?:async\\s+)?(?:function\\s+)?(\\w+)|,\\s*(\\w+)\\s*\\)/\n );\n const handlerName = handlerMatch?.[1] ?? handlerMatch?.[2] ?? 'handler';\n\n const hasZodValidation = PATTERNS.zodValidate.test(afterMatch);\n\n const endpoint: EndpointCandidate = {\n id: this.generateEndpointId(method, path, handlerName),\n method,\n path,\n kind: this.methodToOpKind(method),\n handlerName,\n source: this.createLocation(file, lineNumber, lineNumber + 5),\n confidence: this.createConfidence(\n hasZodValidation ? 'high' : 'medium',\n hasZodValidation ? 'explicit-schema' : 'decorator-hints'\n ),\n };\n\n this.addEndpoint(ctx, endpoint);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;AAYA,MAAM,WAAW;CACf,OACE;CACF,WAAW;CACX,aAAa;CACd;AAED,IAAa,mBAAb,cAAsC,cAAc;CAClD,KAAK;CACL,OAAO;CACP,aAAa,CAAC,UAAU;CACxB,WAAW;CAEX,MAAgB,UAAU,KAAuC;EAC/D,MAAM,EAAE,SAAS,SAAS,OAAO;EAEjC,MAAM,UAAU,QAAQ,OAAO,SAC3B,QAAQ,MAAM,KAAK,MAAM,GAAG,EAAE,UAAU,CAAC,KAAK,IAAI,GAClD;EAEJ,MAAM,QAAQ,MAAM,GAAG,KAAK,SAAS,EAAE,KAAK,QAAQ,UAAU,CAAC;AAC/D,MAAI,GAAG,MAAM,eAAe,MAAM;AAElC,OAAK,MAAM,QAAQ,OAAO;AACxB,OAAI,KAAK,SAAS,eAAe,IAAI,KAAK,SAAS,SAAS,CAAE;GAE9D,MAAM,WAAW,GAAG,QAAQ,SAAS,GAAG;GACxC,MAAM,UAAU,MAAM,GAAG,SAAS,SAAS;AAE3C,SAAM,KAAK,cAAc,KAAK,MAAM,QAAQ;;;CAIhD,MAAc,cACZ,KACA,MACA,SACe;EACf,MAAM,UAAU,CAAC,GAAG,QAAQ,SAAS,SAAS,MAAM,CAAC;AAErD,OAAK,MAAM,SAAS,SAAS;GAC3B,MAAM,SAAU,MAAM,IAAI,aAAa,IAAI;GAC3C,MAAM,OAAO,MAAM,MAAM;GACzB,MAAM,QAAQ,MAAM,SAAS;GAC7B,MAAM,aAAa,QAAQ,MAAM,GAAG,MAAM,CAAC,MAAM,KAAK,CAAC;GAEvD,MAAM,aAAa,QAAQ,MAAM,OAAO,QAAQ,IAAI;GACpD,MAAM,eAAe,WAAW,MAC9B,oDACD;GACD,MAAM,cAAc,eAAe,MAAM,eAAe,MAAM;GAE9D,MAAM,mBAAmB,SAAS,YAAY,KAAK,WAAW;GAE9D,MAAM,WAA8B;IAClC,IAAI,KAAK,mBAAmB,QAAQ,MAAM,YAAY;IACtD;IACA;IACA,MAAM,KAAK,eAAe,OAAO;IACjC;IACA,QAAQ,KAAK,eAAe,MAAM,YAAY,aAAa,EAAE;IAC7D,YAAY,KAAK,iBACf,mBAAmB,SAAS,UAC5B,mBAAmB,oBAAoB,kBACxC;IACF;AAED,QAAK,YAAY,KAAK,SAAS"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BaseExtractor, ExtractionContext } from "../base.js";
|
|
2
|
+
|
|
3
|
+
//#region src/extractors/fastify/extractor.d.ts
|
|
4
|
+
|
|
5
|
+
declare class FastifyExtractor extends BaseExtractor {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
frameworks: string[];
|
|
9
|
+
priority: number;
|
|
10
|
+
protected doExtract(ctx: ExtractionContext): Promise<void>;
|
|
11
|
+
private extractRoutes;
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { FastifyExtractor };
|
|
15
|
+
//# sourceMappingURL=extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractor.d.ts","names":[],"sources":["../../../src/extractors/fastify/extractor.ts"],"sourcesContent":[],"mappings":";;;;cAoBa,gBAAA,SAAyB,aAAA;;;;;2BAML,oBAAoB"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { BaseExtractor } from "../base.js";
|
|
2
|
+
|
|
3
|
+
//#region src/extractors/fastify/extractor.ts
|
|
4
|
+
/**
|
|
5
|
+
* Fastify extractor.
|
|
6
|
+
*
|
|
7
|
+
* Extracts contract candidates from Fastify applications by parsing:
|
|
8
|
+
* - fastify.get(), fastify.post(), etc. route handlers
|
|
9
|
+
* - JSON Schema definitions
|
|
10
|
+
* - Route options with schema
|
|
11
|
+
*/
|
|
12
|
+
const PATTERNS = {
|
|
13
|
+
route: /(?:fastify|app|server)\.(get|post|put|patch|delete|head|options)\s*\(\s*['"`]([^'"`]+)['"`]/gi,
|
|
14
|
+
schemaOption: /schema\s*:\s*\{/g,
|
|
15
|
+
bodySchema: /body\s*:\s*(\w+)/g,
|
|
16
|
+
responseSchema: /response\s*:\s*\{/g
|
|
17
|
+
};
|
|
18
|
+
var FastifyExtractor = class extends BaseExtractor {
|
|
19
|
+
id = "fastify";
|
|
20
|
+
name = "Fastify Extractor";
|
|
21
|
+
frameworks = ["fastify"];
|
|
22
|
+
priority = 15;
|
|
23
|
+
async doExtract(ctx) {
|
|
24
|
+
const { project, options, fs } = ctx;
|
|
25
|
+
const pattern = options.scope?.length ? options.scope.map((s) => `${s}/**/*.ts`).join(",") : "**/*.ts";
|
|
26
|
+
const files = await fs.glob(pattern, { cwd: project.rootPath });
|
|
27
|
+
ctx.ir.stats.filesScanned = files.length;
|
|
28
|
+
for (const file of files) {
|
|
29
|
+
if (file.includes("node_modules") || file.includes(".test.")) continue;
|
|
30
|
+
const fullPath = `${project.rootPath}/${file}`;
|
|
31
|
+
const content = await fs.readFile(fullPath);
|
|
32
|
+
await this.extractRoutes(ctx, file, content);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async extractRoutes(ctx, file, content) {
|
|
36
|
+
const matches = [...content.matchAll(PATTERNS.route)];
|
|
37
|
+
for (const match of matches) {
|
|
38
|
+
const method = match[1]?.toUpperCase() ?? "GET";
|
|
39
|
+
const path = match[2] ?? "/";
|
|
40
|
+
const index = match.index ?? 0;
|
|
41
|
+
const lineNumber = content.slice(0, index).split("\n").length;
|
|
42
|
+
const afterMatch = content.slice(index, index + 1e3);
|
|
43
|
+
const hasSchema = PATTERNS.schemaOption.test(afterMatch);
|
|
44
|
+
const endpoint = {
|
|
45
|
+
id: this.generateEndpointId(method, path),
|
|
46
|
+
method,
|
|
47
|
+
path,
|
|
48
|
+
kind: this.methodToOpKind(method),
|
|
49
|
+
handlerName: "handler",
|
|
50
|
+
source: this.createLocation(file, lineNumber, lineNumber + 10),
|
|
51
|
+
confidence: this.createConfidence(hasSchema ? "high" : "medium", hasSchema ? "explicit-schema" : "decorator-hints"),
|
|
52
|
+
frameworkMeta: { hasSchema }
|
|
53
|
+
};
|
|
54
|
+
this.addEndpoint(ctx, endpoint);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
//#endregion
|
|
60
|
+
export { FastifyExtractor };
|
|
61
|
+
//# sourceMappingURL=extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractor.js","names":[],"sources":["../../../src/extractors/fastify/extractor.ts"],"sourcesContent":["/**\n * Fastify extractor.\n *\n * Extracts contract candidates from Fastify applications by parsing:\n * - fastify.get(), fastify.post(), etc. route handlers\n * - JSON Schema definitions\n * - Route options with schema\n */\n\nimport { BaseExtractor, type ExtractionContext } from '../base';\nimport type { EndpointCandidate, HttpMethod } from '../../types';\n\nconst PATTERNS = {\n route:\n /(?:fastify|app|server)\\.(get|post|put|patch|delete|head|options)\\s*\\(\\s*['\"`]([^'\"`]+)['\"`]/gi,\n schemaOption: /schema\\s*:\\s*\\{/g,\n bodySchema: /body\\s*:\\s*(\\w+)/g,\n responseSchema: /response\\s*:\\s*\\{/g,\n};\n\nexport class FastifyExtractor extends BaseExtractor {\n id = 'fastify';\n name = 'Fastify Extractor';\n frameworks = ['fastify'];\n priority = 15;\n\n protected async doExtract(ctx: ExtractionContext): Promise<void> {\n const { project, options, fs } = ctx;\n\n const pattern = options.scope?.length\n ? options.scope.map((s) => `${s}/**/*.ts`).join(',')\n : '**/*.ts';\n\n const files = await fs.glob(pattern, { cwd: project.rootPath });\n ctx.ir.stats.filesScanned = files.length;\n\n for (const file of files) {\n if (file.includes('node_modules') || file.includes('.test.')) continue;\n\n const fullPath = `${project.rootPath}/${file}`;\n const content = await fs.readFile(fullPath);\n\n await this.extractRoutes(ctx, file, content);\n }\n }\n\n private async extractRoutes(\n ctx: ExtractionContext,\n file: string,\n content: string\n ): Promise<void> {\n const matches = [...content.matchAll(PATTERNS.route)];\n\n for (const match of matches) {\n const method = (match[1]?.toUpperCase() ?? 'GET') as HttpMethod;\n const path = match[2] ?? '/';\n const index = match.index ?? 0;\n const lineNumber = content.slice(0, index).split('\\n').length;\n\n const afterMatch = content.slice(index, index + 1000);\n const hasSchema = PATTERNS.schemaOption.test(afterMatch);\n\n const endpoint: EndpointCandidate = {\n id: this.generateEndpointId(method, path),\n method,\n path,\n kind: this.methodToOpKind(method),\n handlerName: 'handler',\n source: this.createLocation(file, lineNumber, lineNumber + 10),\n confidence: this.createConfidence(\n hasSchema ? 'high' : 'medium',\n hasSchema ? 'explicit-schema' : 'decorator-hints'\n ),\n frameworkMeta: { hasSchema },\n };\n\n this.addEndpoint(ctx, endpoint);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;AAYA,MAAM,WAAW;CACf,OACE;CACF,cAAc;CACd,YAAY;CACZ,gBAAgB;CACjB;AAED,IAAa,mBAAb,cAAsC,cAAc;CAClD,KAAK;CACL,OAAO;CACP,aAAa,CAAC,UAAU;CACxB,WAAW;CAEX,MAAgB,UAAU,KAAuC;EAC/D,MAAM,EAAE,SAAS,SAAS,OAAO;EAEjC,MAAM,UAAU,QAAQ,OAAO,SAC3B,QAAQ,MAAM,KAAK,MAAM,GAAG,EAAE,UAAU,CAAC,KAAK,IAAI,GAClD;EAEJ,MAAM,QAAQ,MAAM,GAAG,KAAK,SAAS,EAAE,KAAK,QAAQ,UAAU,CAAC;AAC/D,MAAI,GAAG,MAAM,eAAe,MAAM;AAElC,OAAK,MAAM,QAAQ,OAAO;AACxB,OAAI,KAAK,SAAS,eAAe,IAAI,KAAK,SAAS,SAAS,CAAE;GAE9D,MAAM,WAAW,GAAG,QAAQ,SAAS,GAAG;GACxC,MAAM,UAAU,MAAM,GAAG,SAAS,SAAS;AAE3C,SAAM,KAAK,cAAc,KAAK,MAAM,QAAQ;;;CAIhD,MAAc,cACZ,KACA,MACA,SACe;EACf,MAAM,UAAU,CAAC,GAAG,QAAQ,SAAS,SAAS,MAAM,CAAC;AAErD,OAAK,MAAM,SAAS,SAAS;GAC3B,MAAM,SAAU,MAAM,IAAI,aAAa,IAAI;GAC3C,MAAM,OAAO,MAAM,MAAM;GACzB,MAAM,QAAQ,MAAM,SAAS;GAC7B,MAAM,aAAa,QAAQ,MAAM,GAAG,MAAM,CAAC,MAAM,KAAK,CAAC;GAEvD,MAAM,aAAa,QAAQ,MAAM,OAAO,QAAQ,IAAK;GACrD,MAAM,YAAY,SAAS,aAAa,KAAK,WAAW;GAExD,MAAM,WAA8B;IAClC,IAAI,KAAK,mBAAmB,QAAQ,KAAK;IACzC;IACA;IACA,MAAM,KAAK,eAAe,OAAO;IACjC,aAAa;IACb,QAAQ,KAAK,eAAe,MAAM,YAAY,aAAa,GAAG;IAC9D,YAAY,KAAK,iBACf,YAAY,SAAS,UACrB,YAAY,oBAAoB,kBACjC;IACD,eAAe,EAAE,WAAW;IAC7B;AAED,QAAK,YAAY,KAAK,SAAS"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BaseExtractor, ExtractionContext } from "../base.js";
|
|
2
|
+
|
|
3
|
+
//#region src/extractors/hono/extractor.d.ts
|
|
4
|
+
|
|
5
|
+
declare class HonoExtractor extends BaseExtractor {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
frameworks: string[];
|
|
9
|
+
priority: number;
|
|
10
|
+
protected doExtract(ctx: ExtractionContext): Promise<void>;
|
|
11
|
+
private extractRoutes;
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { HonoExtractor };
|
|
15
|
+
//# sourceMappingURL=extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractor.d.ts","names":[],"sources":["../../../src/extractors/hono/extractor.ts"],"sourcesContent":[],"mappings":";;;;cAiBa,aAAA,SAAsB,aAAA;;;;;2BAMF,oBAAoB"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { BaseExtractor } from "../base.js";
|
|
2
|
+
|
|
3
|
+
//#region src/extractors/hono/extractor.ts
|
|
4
|
+
/**
|
|
5
|
+
* Hono extractor.
|
|
6
|
+
*
|
|
7
|
+
* Extracts contract candidates from Hono applications by parsing:
|
|
8
|
+
* - app.get(), app.post(), etc. route handlers
|
|
9
|
+
* - Zod validator middleware
|
|
10
|
+
*/
|
|
11
|
+
const PATTERNS = {
|
|
12
|
+
route: /(?:app|hono)\.(get|post|put|patch|delete|all)\s*\(\s*['"`]([^'"`]+)['"`]/gi,
|
|
13
|
+
zodValidator: /zValidator\s*\(\s*['"`](\w+)['"`]\s*,\s*(\w+)/g
|
|
14
|
+
};
|
|
15
|
+
var HonoExtractor = class extends BaseExtractor {
|
|
16
|
+
id = "hono";
|
|
17
|
+
name = "Hono Extractor";
|
|
18
|
+
frameworks = ["hono"];
|
|
19
|
+
priority = 15;
|
|
20
|
+
async doExtract(ctx) {
|
|
21
|
+
const { project, options, fs } = ctx;
|
|
22
|
+
const pattern = options.scope?.length ? options.scope.map((s) => `${s}/**/*.ts`).join(",") : "**/*.ts";
|
|
23
|
+
const files = await fs.glob(pattern, { cwd: project.rootPath });
|
|
24
|
+
ctx.ir.stats.filesScanned = files.length;
|
|
25
|
+
for (const file of files) {
|
|
26
|
+
if (file.includes("node_modules") || file.includes(".test.")) continue;
|
|
27
|
+
const fullPath = `${project.rootPath}/${file}`;
|
|
28
|
+
const content = await fs.readFile(fullPath);
|
|
29
|
+
await this.extractRoutes(ctx, file, content);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async extractRoutes(ctx, file, content) {
|
|
33
|
+
const matches = [...content.matchAll(PATTERNS.route)];
|
|
34
|
+
for (const match of matches) {
|
|
35
|
+
const method = match[1]?.toUpperCase() ?? "GET";
|
|
36
|
+
const path = match[2] ?? "/";
|
|
37
|
+
const index = match.index ?? 0;
|
|
38
|
+
const lineNumber = content.slice(0, index).split("\n").length;
|
|
39
|
+
const afterMatch = content.slice(index, index + 500);
|
|
40
|
+
const hasZodValidator = PATTERNS.zodValidator.test(afterMatch);
|
|
41
|
+
const endpoint = {
|
|
42
|
+
id: this.generateEndpointId(method, path),
|
|
43
|
+
method,
|
|
44
|
+
path,
|
|
45
|
+
kind: this.methodToOpKind(method),
|
|
46
|
+
handlerName: "handler",
|
|
47
|
+
source: this.createLocation(file, lineNumber, lineNumber + 5),
|
|
48
|
+
confidence: this.createConfidence(hasZodValidator ? "high" : "medium", hasZodValidator ? "explicit-schema" : "decorator-hints")
|
|
49
|
+
};
|
|
50
|
+
this.addEndpoint(ctx, endpoint);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
//#endregion
|
|
56
|
+
export { HonoExtractor };
|
|
57
|
+
//# sourceMappingURL=extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractor.js","names":[],"sources":["../../../src/extractors/hono/extractor.ts"],"sourcesContent":["/**\n * Hono extractor.\n *\n * Extracts contract candidates from Hono applications by parsing:\n * - app.get(), app.post(), etc. route handlers\n * - Zod validator middleware\n */\n\nimport { BaseExtractor, type ExtractionContext } from '../base';\nimport type { EndpointCandidate, HttpMethod } from '../../types';\n\nconst PATTERNS = {\n route:\n /(?:app|hono)\\.(get|post|put|patch|delete|all)\\s*\\(\\s*['\"`]([^'\"`]+)['\"`]/gi,\n zodValidator: /zValidator\\s*\\(\\s*['\"`](\\w+)['\"`]\\s*,\\s*(\\w+)/g,\n};\n\nexport class HonoExtractor extends BaseExtractor {\n id = 'hono';\n name = 'Hono Extractor';\n frameworks = ['hono'];\n priority = 15;\n\n protected async doExtract(ctx: ExtractionContext): Promise<void> {\n const { project, options, fs } = ctx;\n\n const pattern = options.scope?.length\n ? options.scope.map((s) => `${s}/**/*.ts`).join(',')\n : '**/*.ts';\n\n const files = await fs.glob(pattern, { cwd: project.rootPath });\n ctx.ir.stats.filesScanned = files.length;\n\n for (const file of files) {\n if (file.includes('node_modules') || file.includes('.test.')) continue;\n\n const fullPath = `${project.rootPath}/${file}`;\n const content = await fs.readFile(fullPath);\n\n await this.extractRoutes(ctx, file, content);\n }\n }\n\n private async extractRoutes(\n ctx: ExtractionContext,\n file: string,\n content: string\n ): Promise<void> {\n const matches = [...content.matchAll(PATTERNS.route)];\n\n for (const match of matches) {\n const method = (match[1]?.toUpperCase() ?? 'GET') as HttpMethod;\n const path = match[2] ?? '/';\n const index = match.index ?? 0;\n const lineNumber = content.slice(0, index).split('\\n').length;\n\n const afterMatch = content.slice(index, index + 500);\n const hasZodValidator = PATTERNS.zodValidator.test(afterMatch);\n\n const endpoint: EndpointCandidate = {\n id: this.generateEndpointId(method, path),\n method,\n path,\n kind: this.methodToOpKind(method),\n handlerName: 'handler',\n source: this.createLocation(file, lineNumber, lineNumber + 5),\n confidence: this.createConfidence(\n hasZodValidator ? 'high' : 'medium',\n hasZodValidator ? 'explicit-schema' : 'decorator-hints'\n ),\n };\n\n this.addEndpoint(ctx, endpoint);\n }\n }\n}\n"],"mappings":";;;;;;;;;;AAWA,MAAM,WAAW;CACf,OACE;CACF,cAAc;CACf;AAED,IAAa,gBAAb,cAAmC,cAAc;CAC/C,KAAK;CACL,OAAO;CACP,aAAa,CAAC,OAAO;CACrB,WAAW;CAEX,MAAgB,UAAU,KAAuC;EAC/D,MAAM,EAAE,SAAS,SAAS,OAAO;EAEjC,MAAM,UAAU,QAAQ,OAAO,SAC3B,QAAQ,MAAM,KAAK,MAAM,GAAG,EAAE,UAAU,CAAC,KAAK,IAAI,GAClD;EAEJ,MAAM,QAAQ,MAAM,GAAG,KAAK,SAAS,EAAE,KAAK,QAAQ,UAAU,CAAC;AAC/D,MAAI,GAAG,MAAM,eAAe,MAAM;AAElC,OAAK,MAAM,QAAQ,OAAO;AACxB,OAAI,KAAK,SAAS,eAAe,IAAI,KAAK,SAAS,SAAS,CAAE;GAE9D,MAAM,WAAW,GAAG,QAAQ,SAAS,GAAG;GACxC,MAAM,UAAU,MAAM,GAAG,SAAS,SAAS;AAE3C,SAAM,KAAK,cAAc,KAAK,MAAM,QAAQ;;;CAIhD,MAAc,cACZ,KACA,MACA,SACe;EACf,MAAM,UAAU,CAAC,GAAG,QAAQ,SAAS,SAAS,MAAM,CAAC;AAErD,OAAK,MAAM,SAAS,SAAS;GAC3B,MAAM,SAAU,MAAM,IAAI,aAAa,IAAI;GAC3C,MAAM,OAAO,MAAM,MAAM;GACzB,MAAM,QAAQ,MAAM,SAAS;GAC7B,MAAM,aAAa,QAAQ,MAAM,GAAG,MAAM,CAAC,MAAM,KAAK,CAAC;GAEvD,MAAM,aAAa,QAAQ,MAAM,OAAO,QAAQ,IAAI;GACpD,MAAM,kBAAkB,SAAS,aAAa,KAAK,WAAW;GAE9D,MAAM,WAA8B;IAClC,IAAI,KAAK,mBAAmB,QAAQ,KAAK;IACzC;IACA;IACA,MAAM,KAAK,eAAe,OAAO;IACjC,aAAa;IACb,QAAQ,KAAK,eAAe,MAAM,YAAY,aAAa,EAAE;IAC7D,YAAY,KAAK,iBACf,kBAAkB,SAAS,UAC3B,kBAAkB,oBAAoB,kBACvC;IACF;AAED,QAAK,YAAY,KAAK,SAAS"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { BaseExtractor, ExtractionContext, ExtractorFsAdapter } from "./base.js";
|
|
2
|
+
import { NestJsExtractor } from "./nestjs/extractor.js";
|
|
3
|
+
import { ExpressExtractor } from "./express/extractor.js";
|
|
4
|
+
import { FastifyExtractor } from "./fastify/extractor.js";
|
|
5
|
+
import { HonoExtractor } from "./hono/extractor.js";
|
|
6
|
+
import { ElysiaExtractor } from "./elysia/extractor.js";
|
|
7
|
+
import { TrpcExtractor } from "./trpc/extractor.js";
|
|
8
|
+
import { NextApiExtractor } from "./next-api/extractor.js";
|
|
9
|
+
import { ZodSchemaExtractor } from "./zod/extractor.js";
|
|
10
|
+
|
|
11
|
+
//#region src/extractors/index.d.ts
|
|
12
|
+
declare namespace index_d_exports {
|
|
13
|
+
export { BaseExtractor, ElysiaExtractor, ExpressExtractor, ExtractionContext, ExtractorFsAdapter, FastifyExtractor, HonoExtractor, NestJsExtractor, NextApiExtractor, TrpcExtractor, ZodSchemaExtractor, registerAllExtractors };
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Register all built-in extractors with the global registry.
|
|
17
|
+
*/
|
|
18
|
+
declare function registerAllExtractors(): void;
|
|
19
|
+
//#endregion
|
|
20
|
+
export { BaseExtractor, ElysiaExtractor, ExpressExtractor, type ExtractionContext, type ExtractorFsAdapter, FastifyExtractor, HonoExtractor, NestJsExtractor, NextApiExtractor, TrpcExtractor, ZodSchemaExtractor, index_d_exports, registerAllExtractors };
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/extractors/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;;iBAoCgB,qBAAA,CAAA"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { __exportAll } from "../_virtual/rolldown_runtime.js";
|
|
2
|
+
import { extractorRegistry } from "../registry.js";
|
|
3
|
+
import { BaseExtractor } from "./base.js";
|
|
4
|
+
import { NestJsExtractor } from "./nestjs/extractor.js";
|
|
5
|
+
import { ExpressExtractor } from "./express/extractor.js";
|
|
6
|
+
import { FastifyExtractor } from "./fastify/extractor.js";
|
|
7
|
+
import { HonoExtractor } from "./hono/extractor.js";
|
|
8
|
+
import { ElysiaExtractor } from "./elysia/extractor.js";
|
|
9
|
+
import { TrpcExtractor } from "./trpc/extractor.js";
|
|
10
|
+
import { NextApiExtractor } from "./next-api/extractor.js";
|
|
11
|
+
import { ZodSchemaExtractor } from "./zod/extractor.js";
|
|
12
|
+
|
|
13
|
+
//#region src/extractors/index.ts
|
|
14
|
+
var extractors_exports = /* @__PURE__ */ __exportAll({
|
|
15
|
+
BaseExtractor: () => BaseExtractor,
|
|
16
|
+
ElysiaExtractor: () => ElysiaExtractor,
|
|
17
|
+
ExpressExtractor: () => ExpressExtractor,
|
|
18
|
+
FastifyExtractor: () => FastifyExtractor,
|
|
19
|
+
HonoExtractor: () => HonoExtractor,
|
|
20
|
+
NestJsExtractor: () => NestJsExtractor,
|
|
21
|
+
NextApiExtractor: () => NextApiExtractor,
|
|
22
|
+
TrpcExtractor: () => TrpcExtractor,
|
|
23
|
+
ZodSchemaExtractor: () => ZodSchemaExtractor,
|
|
24
|
+
registerAllExtractors: () => registerAllExtractors
|
|
25
|
+
});
|
|
26
|
+
/**
|
|
27
|
+
* Register all built-in extractors with the global registry.
|
|
28
|
+
*/
|
|
29
|
+
function registerAllExtractors() {
|
|
30
|
+
extractorRegistry.register(new NestJsExtractor());
|
|
31
|
+
extractorRegistry.register(new ExpressExtractor());
|
|
32
|
+
extractorRegistry.register(new FastifyExtractor());
|
|
33
|
+
extractorRegistry.register(new HonoExtractor());
|
|
34
|
+
extractorRegistry.register(new ElysiaExtractor());
|
|
35
|
+
extractorRegistry.register(new TrpcExtractor());
|
|
36
|
+
extractorRegistry.register(new NextApiExtractor());
|
|
37
|
+
extractorRegistry.register(new ZodSchemaExtractor());
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
//#endregion
|
|
41
|
+
export { BaseExtractor, ElysiaExtractor, ExpressExtractor, FastifyExtractor, HonoExtractor, NestJsExtractor, NextApiExtractor, TrpcExtractor, ZodSchemaExtractor, extractors_exports, registerAllExtractors };
|
|
42
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/extractors/index.ts"],"sourcesContent":["/**\n * Source extractors module.\n *\n * Exports all available framework extractors.\n */\n\n// Base extractor class\nexport { BaseExtractor } from './base';\nexport type { ExtractorFsAdapter, ExtractionContext } from './base';\n\n// Framework-specific extractors\nexport { NestJsExtractor } from './nestjs/extractor';\nexport { ExpressExtractor } from './express/extractor';\nexport { FastifyExtractor } from './fastify/extractor';\nexport { HonoExtractor } from './hono/extractor';\nexport { ElysiaExtractor } from './elysia/extractor';\nexport { TrpcExtractor } from './trpc/extractor';\nexport { NextApiExtractor } from './next-api/extractor';\n\n// Schema extractors\nexport { ZodSchemaExtractor } from './zod/extractor';\n\n// Registration helper\nimport { extractorRegistry } from '../registry';\nimport { NestJsExtractor } from './nestjs/extractor';\nimport { ExpressExtractor } from './express/extractor';\nimport { FastifyExtractor } from './fastify/extractor';\nimport { HonoExtractor } from './hono/extractor';\nimport { ElysiaExtractor } from './elysia/extractor';\nimport { TrpcExtractor } from './trpc/extractor';\nimport { NextApiExtractor } from './next-api/extractor';\nimport { ZodSchemaExtractor } from './zod/extractor';\n\n/**\n * Register all built-in extractors with the global registry.\n */\nexport function registerAllExtractors(): void {\n extractorRegistry.register(new NestJsExtractor());\n extractorRegistry.register(new ExpressExtractor());\n extractorRegistry.register(new FastifyExtractor());\n extractorRegistry.register(new HonoExtractor());\n extractorRegistry.register(new ElysiaExtractor());\n extractorRegistry.register(new TrpcExtractor());\n extractorRegistry.register(new NextApiExtractor());\n extractorRegistry.register(new ZodSchemaExtractor());\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,SAAgB,wBAA8B;AAC5C,mBAAkB,SAAS,IAAI,iBAAiB,CAAC;AACjD,mBAAkB,SAAS,IAAI,kBAAkB,CAAC;AAClD,mBAAkB,SAAS,IAAI,kBAAkB,CAAC;AAClD,mBAAkB,SAAS,IAAI,eAAe,CAAC;AAC/C,mBAAkB,SAAS,IAAI,iBAAiB,CAAC;AACjD,mBAAkB,SAAS,IAAI,eAAe,CAAC;AAC/C,mBAAkB,SAAS,IAAI,kBAAkB,CAAC;AAClD,mBAAkB,SAAS,IAAI,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { BaseExtractor, ExtractionContext } from "../base.js";
|
|
2
|
+
|
|
3
|
+
//#region src/extractors/nestjs/extractor.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* NestJS framework extractor.
|
|
7
|
+
*/
|
|
8
|
+
declare class NestJsExtractor extends BaseExtractor {
|
|
9
|
+
id: string;
|
|
10
|
+
name: string;
|
|
11
|
+
frameworks: string[];
|
|
12
|
+
priority: number;
|
|
13
|
+
protected doExtract(ctx: ExtractionContext): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Extract controllers and their routes from a file.
|
|
16
|
+
*/
|
|
17
|
+
private extractControllers;
|
|
18
|
+
/**
|
|
19
|
+
* Extract DTO classes from a file.
|
|
20
|
+
*/
|
|
21
|
+
private extractDtos;
|
|
22
|
+
/**
|
|
23
|
+
* Normalize a path (remove double slashes, ensure leading slash).
|
|
24
|
+
*/
|
|
25
|
+
private normalizePath;
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
export { NestJsExtractor };
|
|
29
|
+
//# sourceMappingURL=extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractor.d.ts","names":[],"sources":["../../../src/extractors/nestjs/extractor.ts"],"sourcesContent":[],"mappings":";;;;;;;cAmCa,eAAA,SAAwB,aAAA;;;;;2BAMJ,oBAAoB"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { BaseExtractor } from "../base.js";
|
|
2
|
+
|
|
3
|
+
//#region src/extractors/nestjs/extractor.ts
|
|
4
|
+
/**
|
|
5
|
+
* NestJS extractor.
|
|
6
|
+
*
|
|
7
|
+
* Extracts contract candidates from NestJS applications by parsing:
|
|
8
|
+
* - @Controller() decorated classes
|
|
9
|
+
* - @Get(), @Post(), etc. decorated methods
|
|
10
|
+
* - Class-validator DTOs
|
|
11
|
+
* - HttpException patterns
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Regex patterns for NestJS detection and extraction.
|
|
15
|
+
*/
|
|
16
|
+
const PATTERNS = {
|
|
17
|
+
controller: /@Controller\s*\(\s*['"`]([^'"`]*)['"`]\s*\)/g,
|
|
18
|
+
route: /@(Get|Post|Put|Patch|Delete|Head|Options)\s*\(\s*(?:['"`]([^'"`]*)['"`])?\s*\)/g,
|
|
19
|
+
body: /@Body\s*\(\s*\)/g,
|
|
20
|
+
param: /@Param\s*\(\s*(?:['"`]([^'"`]*)['"`])?\s*\)/g,
|
|
21
|
+
query: /@Query\s*\(\s*(?:['"`]([^'"`]*)['"`])?\s*\)/g,
|
|
22
|
+
dto: /class\s+(\w+(?:Dto|DTO|Request|Response|Input|Output))\s*\{/g,
|
|
23
|
+
classValidator: /@(IsString|IsNumber|IsBoolean|IsArray|IsOptional|IsNotEmpty|Min|Max|Length|Matches)/g
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* NestJS framework extractor.
|
|
27
|
+
*/
|
|
28
|
+
var NestJsExtractor = class extends BaseExtractor {
|
|
29
|
+
id = "nestjs";
|
|
30
|
+
name = "NestJS Extractor";
|
|
31
|
+
frameworks = ["nestjs"];
|
|
32
|
+
priority = 20;
|
|
33
|
+
async doExtract(ctx) {
|
|
34
|
+
const { project, options, fs } = ctx;
|
|
35
|
+
const pattern = options.scope?.length ? options.scope.map((s) => `${s}/**/*.ts`).join(",") : "**/*.ts";
|
|
36
|
+
const files = await fs.glob(pattern, { cwd: project.rootPath });
|
|
37
|
+
ctx.ir.stats.filesScanned = files.length;
|
|
38
|
+
for (const file of files) {
|
|
39
|
+
if (file.includes("node_modules") || file.includes(".spec.") || file.includes(".test.")) continue;
|
|
40
|
+
const fullPath = `${project.rootPath}/${file}`;
|
|
41
|
+
const content = await fs.readFile(fullPath);
|
|
42
|
+
await this.extractControllers(ctx, file, content);
|
|
43
|
+
await this.extractDtos(ctx, file, content);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Extract controllers and their routes from a file.
|
|
48
|
+
*/
|
|
49
|
+
async extractControllers(ctx, file, content) {
|
|
50
|
+
const controllerMatches = [...content.matchAll(PATTERNS.controller)];
|
|
51
|
+
for (const controllerMatch of controllerMatches) {
|
|
52
|
+
const basePath = controllerMatch[1] || "";
|
|
53
|
+
const controllerIndex = controllerMatch.index ?? 0;
|
|
54
|
+
const controllerName = content.slice(controllerIndex).match(/class\s+(\w+)/)?.[1] ?? "UnknownController";
|
|
55
|
+
const nextController = content.indexOf("@Controller", controllerIndex + 1);
|
|
56
|
+
const controllerBlock = nextController > 0 ? content.slice(controllerIndex, nextController) : content.slice(controllerIndex);
|
|
57
|
+
const routeMatches = [...controllerBlock.matchAll(PATTERNS.route)];
|
|
58
|
+
for (const routeMatch of routeMatches) {
|
|
59
|
+
const method = routeMatch[1]?.toUpperCase();
|
|
60
|
+
const routePath = routeMatch[2] || "";
|
|
61
|
+
const fullPath = this.normalizePath(`/${basePath}/${routePath}`);
|
|
62
|
+
const afterRoute = controllerBlock.slice(routeMatch.index ?? 0);
|
|
63
|
+
const handlerName = afterRoute.match(/(?:async\s+)?(\w+)\s*\([^)]*\)\s*(?::\s*\w+(?:<[^>]+>)?)?\s*\{/)?.[1] ?? "unknownHandler";
|
|
64
|
+
const absoluteIndex = controllerIndex + (routeMatch.index ?? 0);
|
|
65
|
+
const lineNumber = content.slice(0, absoluteIndex).split("\n").length;
|
|
66
|
+
const hasBody = PATTERNS.body.test(afterRoute.slice(0, 200));
|
|
67
|
+
const hasParams = PATTERNS.param.test(afterRoute.slice(0, 200));
|
|
68
|
+
const hasQuery = PATTERNS.query.test(afterRoute.slice(0, 200));
|
|
69
|
+
const endpoint = {
|
|
70
|
+
id: this.generateEndpointId(method, fullPath, handlerName),
|
|
71
|
+
method,
|
|
72
|
+
path: fullPath,
|
|
73
|
+
kind: this.methodToOpKind(method),
|
|
74
|
+
handlerName,
|
|
75
|
+
controllerName,
|
|
76
|
+
source: this.createLocation(file, lineNumber, lineNumber + 10),
|
|
77
|
+
confidence: this.createConfidence("medium", "decorator-hints"),
|
|
78
|
+
frameworkMeta: {
|
|
79
|
+
hasBody,
|
|
80
|
+
hasParams,
|
|
81
|
+
hasQuery
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
this.addEndpoint(ctx, endpoint);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Extract DTO classes from a file.
|
|
90
|
+
*/
|
|
91
|
+
async extractDtos(ctx, file, content) {
|
|
92
|
+
const dtoMatches = [...content.matchAll(PATTERNS.dto)];
|
|
93
|
+
for (const match of dtoMatches) {
|
|
94
|
+
const name = match[1] ?? "UnknownDto";
|
|
95
|
+
const index = match.index ?? 0;
|
|
96
|
+
const lineNumber = content.slice(0, index).split("\n").length;
|
|
97
|
+
const hasClassValidator = content.includes("class-validator") || content.includes("@IsString") || content.includes("@IsNumber");
|
|
98
|
+
const schema = {
|
|
99
|
+
id: this.generateSchemaId(name, file),
|
|
100
|
+
name,
|
|
101
|
+
schemaType: hasClassValidator ? "class-validator" : "typescript",
|
|
102
|
+
source: this.createLocation(file, lineNumber, lineNumber + 20),
|
|
103
|
+
confidence: this.createConfidence(hasClassValidator ? "high" : "medium", hasClassValidator ? "explicit-schema" : "inferred-types")
|
|
104
|
+
};
|
|
105
|
+
this.addSchema(ctx, schema);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Normalize a path (remove double slashes, ensure leading slash).
|
|
110
|
+
*/
|
|
111
|
+
normalizePath(path) {
|
|
112
|
+
return "/" + path.replace(/\/+/g, "/").replace(/^\/+|\/+$/g, "");
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
//#endregion
|
|
117
|
+
export { NestJsExtractor };
|
|
118
|
+
//# sourceMappingURL=extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractor.js","names":[],"sources":["../../../src/extractors/nestjs/extractor.ts"],"sourcesContent":["/**\n * NestJS extractor.\n *\n * Extracts contract candidates from NestJS applications by parsing:\n * - @Controller() decorated classes\n * - @Get(), @Post(), etc. decorated methods\n * - Class-validator DTOs\n * - HttpException patterns\n */\n\nimport { BaseExtractor, type ExtractionContext } from '../base';\nimport type {\n EndpointCandidate,\n HttpMethod,\n SchemaCandidate,\n} from '../../types';\n\n/**\n * Regex patterns for NestJS detection and extraction.\n */\nconst PATTERNS = {\n controller: /@Controller\\s*\\(\\s*['\"`]([^'\"`]*)['\"`]\\s*\\)/g,\n route:\n /@(Get|Post|Put|Patch|Delete|Head|Options)\\s*\\(\\s*(?:['\"`]([^'\"`]*)['\"`])?\\s*\\)/g,\n body: /@Body\\s*\\(\\s*\\)/g,\n param: /@Param\\s*\\(\\s*(?:['\"`]([^'\"`]*)['\"`])?\\s*\\)/g,\n query: /@Query\\s*\\(\\s*(?:['\"`]([^'\"`]*)['\"`])?\\s*\\)/g,\n dto: /class\\s+(\\w+(?:Dto|DTO|Request|Response|Input|Output))\\s*\\{/g,\n classValidator:\n /@(IsString|IsNumber|IsBoolean|IsArray|IsOptional|IsNotEmpty|Min|Max|Length|Matches)/g,\n};\n\n/**\n * NestJS framework extractor.\n */\nexport class NestJsExtractor extends BaseExtractor {\n id = 'nestjs';\n name = 'NestJS Extractor';\n frameworks = ['nestjs'];\n priority = 20; // Higher priority for NestJS-specific detection\n\n protected async doExtract(ctx: ExtractionContext): Promise<void> {\n const { project, options, fs } = ctx;\n\n // Find TypeScript files\n const pattern = options.scope?.length\n ? options.scope.map((s) => `${s}/**/*.ts`).join(',')\n : '**/*.ts';\n\n const files = await fs.glob(pattern, { cwd: project.rootPath });\n ctx.ir.stats.filesScanned = files.length;\n\n for (const file of files) {\n // Skip test files and node_modules\n if (\n file.includes('node_modules') ||\n file.includes('.spec.') ||\n file.includes('.test.')\n ) {\n continue;\n }\n\n const fullPath = `${project.rootPath}/${file}`;\n const content = await fs.readFile(fullPath);\n\n // Extract controllers and routes\n await this.extractControllers(ctx, file, content);\n\n // Extract DTOs\n await this.extractDtos(ctx, file, content);\n }\n }\n\n /**\n * Extract controllers and their routes from a file.\n */\n private async extractControllers(\n ctx: ExtractionContext,\n file: string,\n content: string\n ): Promise<void> {\n // Find controllers\n const controllerMatches = [...content.matchAll(PATTERNS.controller)];\n\n for (const controllerMatch of controllerMatches) {\n const basePath = controllerMatch[1] || '';\n const controllerIndex = controllerMatch.index ?? 0;\n\n // Find the class name after the decorator\n const afterDecorator = content.slice(controllerIndex);\n const classMatch = afterDecorator.match(/class\\s+(\\w+)/);\n const controllerName = classMatch?.[1] ?? 'UnknownController';\n\n // Find route decorators in this controller\n // We need to find routes between this controller and the next one (or end of file)\n const nextController = content.indexOf(\n '@Controller',\n controllerIndex + 1\n );\n const controllerBlock =\n nextController > 0\n ? content.slice(controllerIndex, nextController)\n : content.slice(controllerIndex);\n\n const routeMatches = [...controllerBlock.matchAll(PATTERNS.route)];\n\n for (const routeMatch of routeMatches) {\n const method = routeMatch[1]?.toUpperCase() as HttpMethod;\n const routePath = routeMatch[2] || '';\n const fullPath = this.normalizePath(`/${basePath}/${routePath}`);\n\n // Find the method name after the route decorator\n const afterRoute = controllerBlock.slice(routeMatch.index ?? 0);\n const methodMatch = afterRoute.match(\n /(?:async\\s+)?(\\w+)\\s*\\([^)]*\\)\\s*(?::\\s*\\w+(?:<[^>]+>)?)?\\s*\\{/\n );\n const handlerName = methodMatch?.[1] ?? 'unknownHandler';\n\n // Calculate line numbers\n const absoluteIndex = controllerIndex + (routeMatch.index ?? 0);\n const lineNumber = content.slice(0, absoluteIndex).split('\\n').length;\n\n // Check for body, params, query decorators\n const hasBody = PATTERNS.body.test(afterRoute.slice(0, 200));\n const hasParams = PATTERNS.param.test(afterRoute.slice(0, 200));\n const hasQuery = PATTERNS.query.test(afterRoute.slice(0, 200));\n\n const endpoint: EndpointCandidate = {\n id: this.generateEndpointId(method, fullPath, handlerName),\n method,\n path: fullPath,\n kind: this.methodToOpKind(method),\n handlerName,\n controllerName,\n source: this.createLocation(file, lineNumber, lineNumber + 10),\n confidence: this.createConfidence('medium', 'decorator-hints'),\n frameworkMeta: {\n hasBody,\n hasParams,\n hasQuery,\n },\n };\n\n this.addEndpoint(ctx, endpoint);\n }\n }\n }\n\n /**\n * Extract DTO classes from a file.\n */\n private async extractDtos(\n ctx: ExtractionContext,\n file: string,\n content: string\n ): Promise<void> {\n const dtoMatches = [...content.matchAll(PATTERNS.dto)];\n\n for (const match of dtoMatches) {\n const name = match[1] ?? 'UnknownDto';\n const index = match.index ?? 0;\n const lineNumber = content.slice(0, index).split('\\n').length;\n\n // Check if it uses class-validator (check for import statement)\n const hasClassValidator =\n content.includes('class-validator') ||\n content.includes('@IsString') ||\n content.includes('@IsNumber');\n\n const schema: SchemaCandidate = {\n id: this.generateSchemaId(name, file),\n name,\n schemaType: hasClassValidator ? 'class-validator' : 'typescript',\n source: this.createLocation(file, lineNumber, lineNumber + 20),\n confidence: this.createConfidence(\n hasClassValidator ? 'high' : 'medium',\n hasClassValidator ? 'explicit-schema' : 'inferred-types'\n ),\n };\n\n this.addSchema(ctx, schema);\n }\n }\n\n /**\n * Normalize a path (remove double slashes, ensure leading slash).\n */\n private normalizePath(path: string): string {\n return '/' + path.replace(/\\/+/g, '/').replace(/^\\/+|\\/+$/g, '');\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { BaseExtractor, ExtractionContext } from "../base.js";
|
|
2
|
+
|
|
3
|
+
//#region src/extractors/next-api/extractor.d.ts
|
|
4
|
+
|
|
5
|
+
declare class NextApiExtractor extends BaseExtractor {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
frameworks: string[];
|
|
9
|
+
priority: number;
|
|
10
|
+
protected doExtract(ctx: ExtractionContext): Promise<void>;
|
|
11
|
+
private extractAppRoutes;
|
|
12
|
+
private extractPagesRoutes;
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { NextApiExtractor };
|
|
16
|
+
//# sourceMappingURL=extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractor.d.ts","names":[],"sources":["../../../src/extractors/next-api/extractor.ts"],"sourcesContent":[],"mappings":";;;;cAkBa,gBAAA,SAAyB,aAAA;;;;;2BAML,oBAAoB"}
|