vitek-plugin 0.2.0-beta → 0.2.2-beta
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 +1 -1
- package/dist/adapters/dispatch/http-webhook.d.ts +10 -0
- package/dist/adapters/dispatch/http-webhook.d.ts.map +1 -0
- package/dist/adapters/dispatch/http-webhook.js +38 -0
- package/dist/adapters/node/console-structured-request-logger.d.ts +6 -0
- package/dist/adapters/node/console-structured-request-logger.d.ts.map +1 -0
- package/dist/adapters/node/console-structured-request-logger.js +31 -0
- package/dist/build/build-api-bundle.d.ts.map +1 -1
- package/dist/build/build-api-bundle.js +11 -0
- package/dist/build/build-sockets-bundle.d.ts.map +1 -1
- package/dist/build/build-sockets-bundle.js +11 -0
- package/dist/cli/contract.d.ts +11 -0
- package/dist/cli/contract.d.ts.map +1 -0
- package/dist/cli/contract.js +143 -0
- package/dist/cli/doctor.d.ts +2 -0
- package/dist/cli/doctor.d.ts.map +1 -0
- package/dist/cli/doctor.js +70 -0
- package/dist/cli/generate.d.ts +2 -0
- package/dist/cli/generate.d.ts.map +1 -0
- package/dist/cli/generate.js +56 -0
- package/dist/cli/mcp-docs.d.ts +2 -0
- package/dist/cli/mcp-docs.d.ts.map +1 -0
- package/dist/cli/mcp-docs.js +4 -0
- package/dist/cli/mcp-project-write-tools.d.ts +4 -0
- package/dist/cli/mcp-project-write-tools.d.ts.map +1 -0
- package/dist/cli/mcp-project-write-tools.js +64 -0
- package/dist/cli/schedule.d.ts +2 -0
- package/dist/cli/schedule.d.ts.map +1 -0
- package/dist/cli/schedule.js +66 -0
- package/dist/core/contract/compare-asyncapi.d.ts +3 -0
- package/dist/core/contract/compare-asyncapi.d.ts.map +1 -0
- package/dist/core/contract/compare-asyncapi.js +45 -0
- package/dist/core/contract/compare-openapi.d.ts +3 -0
- package/dist/core/contract/compare-openapi.d.ts.map +1 -0
- package/dist/core/contract/compare-openapi.js +116 -0
- package/dist/core/contract/http-methods.d.ts +2 -0
- package/dist/core/contract/http-methods.d.ts.map +1 -0
- package/dist/core/contract/http-methods.js +2 -0
- package/dist/core/contract/index.d.ts +9 -0
- package/dist/core/contract/index.d.ts.map +1 -0
- package/dist/core/contract/index.js +7 -0
- package/dist/core/contract/project-specs.d.ts +12 -0
- package/dist/core/contract/project-specs.d.ts.map +1 -0
- package/dist/core/contract/project-specs.js +27 -0
- package/dist/core/contract/sort-json.d.ts +2 -0
- package/dist/core/contract/sort-json.d.ts.map +1 -0
- package/dist/core/contract/sort-json.js +14 -0
- package/dist/core/contract/types.d.ts +7 -0
- package/dist/core/contract/types.d.ts.map +1 -0
- package/dist/core/contract/types.js +1 -0
- package/dist/core/dispatch/dispatchers.d.ts +4 -0
- package/dist/core/dispatch/dispatchers.d.ts.map +1 -0
- package/dist/core/dispatch/dispatchers.js +16 -0
- package/dist/core/dispatch/emit-safe.d.ts +3 -0
- package/dist/core/dispatch/emit-safe.d.ts.map +1 -0
- package/dist/core/dispatch/emit-safe.js +10 -0
- package/dist/core/dispatch/index.d.ts +4 -0
- package/dist/core/dispatch/index.d.ts.map +1 -0
- package/dist/core/dispatch/index.js +2 -0
- package/dist/core/dispatch/types.d.ts +22 -0
- package/dist/core/dispatch/types.d.ts.map +1 -0
- package/dist/core/dispatch/types.js +1 -0
- package/dist/core/doctor/index.d.ts +3 -0
- package/dist/core/doctor/index.d.ts.map +1 -0
- package/dist/core/doctor/index.js +1 -0
- package/dist/core/doctor/report.d.ts +4 -0
- package/dist/core/doctor/report.d.ts.map +1 -0
- package/dist/core/doctor/report.js +166 -0
- package/dist/core/doctor/scan.d.ts +3 -0
- package/dist/core/doctor/scan.d.ts.map +1 -0
- package/dist/core/doctor/scan.js +23 -0
- package/dist/core/doctor/types.d.ts +12 -0
- package/dist/core/doctor/types.d.ts.map +1 -0
- package/dist/core/doctor/types.js +1 -0
- package/dist/core/events/event-bus.d.ts +8 -0
- package/dist/core/events/event-bus.d.ts.map +1 -0
- package/dist/core/events/event-bus.js +26 -0
- package/dist/core/events/index.d.ts +3 -0
- package/dist/core/events/index.d.ts.map +1 -0
- package/dist/core/events/index.js +1 -0
- package/dist/core/generators/adapters/drizzle.d.ts +3 -0
- package/dist/core/generators/adapters/drizzle.d.ts.map +1 -0
- package/dist/core/generators/adapters/drizzle.js +26 -0
- package/dist/core/generators/adapters/prisma.d.ts +3 -0
- package/dist/core/generators/adapters/prisma.d.ts.map +1 -0
- package/dist/core/generators/adapters/prisma.js +136 -0
- package/dist/core/generators/adapters/sql.d.ts +3 -0
- package/dist/core/generators/adapters/sql.d.ts.map +1 -0
- package/dist/core/generators/adapters/sql.js +26 -0
- package/dist/core/generators/generate-crud.d.ts +8 -0
- package/dist/core/generators/generate-crud.d.ts.map +1 -0
- package/dist/core/generators/generate-crud.js +17 -0
- package/dist/core/generators/index.d.ts +3 -0
- package/dist/core/generators/index.d.ts.map +1 -0
- package/dist/core/generators/index.js +1 -0
- package/dist/core/generators/types.d.ts +16 -0
- package/dist/core/generators/types.d.ts.map +1 -0
- package/dist/core/generators/types.js +1 -0
- package/dist/core/generators/utils.d.ts +3 -0
- package/dist/core/generators/utils.d.ts.map +1 -0
- package/dist/core/generators/utils.js +10 -0
- package/dist/core/observability/with-span.d.ts +5 -0
- package/dist/core/observability/with-span.d.ts.map +1 -0
- package/dist/core/observability/with-span.js +7 -0
- package/dist/core/scheduler/define-schedule.d.ts +3 -0
- package/dist/core/scheduler/define-schedule.d.ts.map +1 -0
- package/dist/core/scheduler/define-schedule.js +3 -0
- package/dist/core/scheduler/in-memory-lock.d.ts +6 -0
- package/dist/core/scheduler/in-memory-lock.d.ts.map +1 -0
- package/dist/core/scheduler/in-memory-lock.js +12 -0
- package/dist/core/scheduler/index.d.ts +5 -0
- package/dist/core/scheduler/index.d.ts.map +1 -0
- package/dist/core/scheduler/index.js +3 -0
- package/dist/core/scheduler/runner.d.ts +6 -0
- package/dist/core/scheduler/runner.d.ts.map +1 -0
- package/dist/core/scheduler/runner.js +37 -0
- package/dist/core/scheduler/types.d.ts +21 -0
- package/dist/core/scheduler/types.d.ts.map +1 -0
- package/dist/core/scheduler/types.js +1 -0
- package/dist/core/server/request-log-meta.d.ts +5 -0
- package/dist/core/server/request-log-meta.d.ts.map +1 -0
- package/dist/core/server/request-log-meta.js +1 -0
- package/dist/mcp/write/apply-guard.d.ts +7 -0
- package/dist/mcp/write/apply-guard.d.ts.map +1 -0
- package/dist/mcp/write/apply-guard.js +22 -0
- package/dist/mcp/write/openapi-jsdoc.d.ts +2 -0
- package/dist/mcp/write/openapi-jsdoc.d.ts.map +1 -0
- package/dist/mcp/write/openapi-jsdoc.js +15 -0
- package/dist/mcp/write/project-write-handlers.d.ts +46 -0
- package/dist/mcp/write/project-write-handlers.d.ts.map +1 -0
- package/dist/mcp/write/project-write-handlers.js +304 -0
- package/dist/mcp/write/risks.d.ts +3 -0
- package/dist/mcp/write/risks.d.ts.map +1 -0
- package/dist/mcp/write/risks.js +20 -0
- package/dist/mcp/write/route-snippet.d.ts +5 -0
- package/dist/mcp/write/route-snippet.d.ts.map +1 -0
- package/dist/mcp/write/route-snippet.js +46 -0
- package/dist/mcp/write/safe-path.d.ts +3 -0
- package/dist/mcp/write/safe-path.d.ts.map +1 -0
- package/dist/mcp/write/safe-path.js +16 -0
- package/dist/mcp/write/test-file-content.d.ts +8 -0
- package/dist/mcp/write/test-file-content.d.ts.map +1 -0
- package/dist/mcp/write/test-file-content.js +31 -0
- package/dist/mcp/write/unified-diff.d.ts +2 -0
- package/dist/mcp/write/unified-diff.d.ts.map +1 -0
- package/dist/mcp/write/unified-diff.js +19 -0
- package/dist/mcp/write/validation-scaffold.d.ts +2 -0
- package/dist/mcp/write/validation-scaffold.d.ts.map +1 -0
- package/dist/mcp/write/validation-scaffold.js +31 -0
- package/dist/mcp-docs-server/resources/configuration.d.ts +3 -0
- package/dist/mcp-docs-server/resources/configuration.d.ts.map +1 -0
- package/dist/mcp-docs-server/resources/configuration.js +25 -0
- package/dist/mcp-docs-server/resources/context.d.ts +3 -0
- package/dist/mcp-docs-server/resources/context.d.ts.map +1 -0
- package/dist/mcp-docs-server/resources/context.js +34 -0
- package/dist/mcp-docs-server/resources/errors.d.ts +3 -0
- package/dist/mcp-docs-server/resources/errors.d.ts.map +1 -0
- package/dist/mcp-docs-server/resources/errors.js +27 -0
- package/dist/mcp-docs-server/resources/introspection.d.ts +3 -0
- package/dist/mcp-docs-server/resources/introspection.d.ts.map +1 -0
- package/dist/mcp-docs-server/resources/introspection.js +24 -0
- package/dist/mcp-docs-server/resources/middlewares.d.ts +3 -0
- package/dist/mcp-docs-server/resources/middlewares.d.ts.map +1 -0
- package/dist/mcp-docs-server/resources/middlewares.js +36 -0
- package/dist/mcp-docs-server/resources/plugin-api.d.ts +3 -0
- package/dist/mcp-docs-server/resources/plugin-api.d.ts.map +1 -0
- package/dist/mcp-docs-server/resources/plugin-api.js +32 -0
- package/dist/mcp-docs-server/resources/response.d.ts +3 -0
- package/dist/mcp-docs-server/resources/response.d.ts.map +1 -0
- package/dist/mcp-docs-server/resources/response.js +39 -0
- package/dist/mcp-docs-server/resources/routing.d.ts +3 -0
- package/dist/mcp-docs-server/resources/routing.d.ts.map +1 -0
- package/dist/mcp-docs-server/resources/routing.js +47 -0
- package/dist/mcp-docs-server/resources/validation.d.ts +3 -0
- package/dist/mcp-docs-server/resources/validation.d.ts.map +1 -0
- package/dist/mcp-docs-server/resources/validation.js +37 -0
- package/dist/mcp-docs-server/resources/websockets.d.ts +3 -0
- package/dist/mcp-docs-server/resources/websockets.d.ts.map +1 -0
- package/dist/mcp-docs-server/resources/websockets.js +42 -0
- package/dist/mcp-docs-server/start-mcp-docs-server.d.ts +2 -0
- package/dist/mcp-docs-server/start-mcp-docs-server.d.ts.map +1 -0
- package/dist/mcp-docs-server/start-mcp-docs-server.js +171 -0
- package/dist/mcp-docs-server/tools/create-middleware.d.ts +5 -0
- package/dist/mcp-docs-server/tools/create-middleware.d.ts.map +1 -0
- package/dist/mcp-docs-server/tools/create-middleware.js +29 -0
- package/dist/mcp-docs-server/tools/create-route.d.ts +5 -0
- package/dist/mcp-docs-server/tools/create-route.d.ts.map +1 -0
- package/dist/mcp-docs-server/tools/create-route.js +44 -0
- package/dist/mcp-docs-server/tools/create-socket.d.ts +5 -0
- package/dist/mcp-docs-server/tools/create-socket.d.ts.map +1 -0
- package/dist/mcp-docs-server/tools/create-socket.js +39 -0
- package/dist/mcp-docs-server/tools/suggest-vite-config.d.ts +11 -0
- package/dist/mcp-docs-server/tools/suggest-vite-config.d.ts.map +1 -0
- package/dist/mcp-docs-server/tools/suggest-vite-config.js +30 -0
- package/dist/mcp-docs-server/tools/validate-convention.d.ts +21 -0
- package/dist/mcp-docs-server/tools/validate-convention.d.ts.map +1 -0
- package/dist/mcp-docs-server/tools/validate-convention.js +48 -0
- package/dist/platform/config.d.ts +30 -0
- package/dist/platform/config.d.ts.map +1 -0
- package/dist/platform/config.js +85 -0
- package/dist/platform/correlation.d.ts +5 -0
- package/dist/platform/correlation.d.ts.map +1 -0
- package/dist/platform/correlation.js +19 -0
- package/dist/platform/index.d.ts +5 -0
- package/dist/platform/index.d.ts.map +1 -0
- package/dist/platform/index.js +3 -0
- package/dist/platform/redaction.d.ts +6 -0
- package/dist/platform/redaction.d.ts.map +1 -0
- package/dist/platform/redaction.js +40 -0
- package/dist/plugin/mode.d.ts +5 -0
- package/dist/plugin/mode.d.ts.map +1 -0
- package/dist/plugin/mode.js +7 -0
- package/dist/plugin/vitek-resolve.d.ts.map +1 -1
- package/dist/plugin/vitek-resolve.js +4 -3
- package/dist/plugin/vitek-transform.d.ts +1 -1
- package/dist/plugin/vitek-transform.d.ts.map +1 -1
- package/dist/plugin/vitek-transform.js +30 -5
- package/dist/public/dispatch.d.ts +3 -0
- package/dist/public/dispatch.d.ts.map +1 -0
- package/dist/public/dispatch.js +1 -0
- package/dist/public/doctor.d.ts +3 -0
- package/dist/public/doctor.d.ts.map +1 -0
- package/dist/public/doctor.js +1 -0
- package/dist/public/errors.d.ts +2 -0
- package/dist/public/errors.d.ts.map +1 -0
- package/dist/public/errors.js +1 -0
- package/dist/public/events.d.ts +3 -0
- package/dist/public/events.d.ts.map +1 -0
- package/dist/public/events.js +1 -0
- package/dist/public/generators.d.ts +3 -0
- package/dist/public/generators.d.ts.map +1 -0
- package/dist/public/generators.js +1 -0
- package/dist/public/introspection.d.ts +3 -0
- package/dist/public/introspection.d.ts.map +1 -0
- package/dist/public/introspection.js +1 -0
- package/dist/public/observability.d.ts +3 -0
- package/dist/public/observability.d.ts.map +1 -0
- package/dist/public/observability.js +1 -0
- package/dist/public/platform.d.ts +3 -0
- package/dist/public/platform.d.ts.map +1 -0
- package/dist/public/platform.js +1 -0
- package/dist/public/plugin.d.ts +3 -0
- package/dist/public/plugin.d.ts.map +1 -0
- package/dist/public/plugin.js +1 -0
- package/dist/public/response.d.ts +2 -0
- package/dist/public/response.d.ts.map +1 -0
- package/dist/public/response.js +1 -0
- package/dist/public/scheduler.d.ts +3 -0
- package/dist/public/scheduler.d.ts.map +1 -0
- package/dist/public/scheduler.js +1 -0
- package/dist/public/testing.d.ts +3 -0
- package/dist/public/testing.d.ts.map +1 -0
- package/dist/public/testing.js +1 -0
- package/dist/public/validation.d.ts +3 -0
- package/dist/public/validation.d.ts.map +1 -0
- package/dist/public/validation.js +1 -0
- package/dist/shared/mode.d.ts +5 -0
- package/dist/shared/mode.d.ts.map +1 -0
- package/dist/shared/mode.js +7 -0
- package/dist/testing/testing.d.ts +15 -0
- package/dist/testing/testing.d.ts.map +1 -0
- package/dist/testing/testing.js +51 -0
- package/package.json +23 -21
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
**File-based HTTP API generation for Vite**
|
|
7
7
|
|
|
8
|
-
[](https://github.com/martinsbicudo/vitek-plugin)
|
|
9
9
|
[](LICENSE)
|
|
10
10
|
[](https://vitejs.dev/)
|
|
11
11
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { IssueDispatcher, IssueEvent } from '../../core/dispatch/types.js';
|
|
2
|
+
export interface HttpWebhookIssueDispatcherOptions {
|
|
3
|
+
url: string;
|
|
4
|
+
headers?: Record<string, string>;
|
|
5
|
+
retries?: number;
|
|
6
|
+
backoffMs?: number;
|
|
7
|
+
onDeadLetter?: (event: IssueEvent, error: Error) => void;
|
|
8
|
+
}
|
|
9
|
+
export declare function createHttpWebhookIssueDispatcher(options: HttpWebhookIssueDispatcherOptions): IssueDispatcher;
|
|
10
|
+
//# sourceMappingURL=http-webhook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-webhook.d.ts","sourceRoot":"","sources":["../../../src/adapters/dispatch/http-webhook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAEhF,MAAM,WAAW,iCAAiC;IAChD,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAC1D;AAMD,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,iCAAiC,GACzC,eAAe,CAkCjB"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
function sleep(ms) {
|
|
2
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3
|
+
}
|
|
4
|
+
export function createHttpWebhookIssueDispatcher(options) {
|
|
5
|
+
const retries = options.retries ?? 2;
|
|
6
|
+
const backoffMs = options.backoffMs ?? 150;
|
|
7
|
+
return {
|
|
8
|
+
async dispatch(event) {
|
|
9
|
+
let lastError = null;
|
|
10
|
+
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
11
|
+
try {
|
|
12
|
+
const res = await fetch(options.url, {
|
|
13
|
+
method: 'POST',
|
|
14
|
+
headers: {
|
|
15
|
+
'Content-Type': 'application/json',
|
|
16
|
+
...(options.headers ?? {}),
|
|
17
|
+
},
|
|
18
|
+
body: JSON.stringify(event),
|
|
19
|
+
});
|
|
20
|
+
if (res.ok) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
throw new Error(`Dispatch webhook failed with status ${res.status}`);
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
lastError = err instanceof Error ? err : new Error(String(err));
|
|
27
|
+
if (attempt < retries) {
|
|
28
|
+
await sleep(backoffMs * Math.pow(2, attempt));
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const finalError = lastError ?? new Error('Dispatch webhook failed');
|
|
34
|
+
options.onDeadLetter?.(event, finalError);
|
|
35
|
+
throw finalError;
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { RequestLogMeta } from '../../core/server/request-log-meta.js';
|
|
2
|
+
export declare function createConsoleStructuredRequestLogger(): {
|
|
3
|
+
requestStart(method: string, path: string, meta?: RequestLogMeta): void;
|
|
4
|
+
request(method: string, path: string, statusCode: number, duration?: number, meta?: RequestLogMeta): void;
|
|
5
|
+
};
|
|
6
|
+
//# sourceMappingURL=console-structured-request-logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console-structured-request-logger.d.ts","sourceRoot":"","sources":["../../../src/adapters/node/console-structured-request-logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAY5E,wBAAgB,oCAAoC,IAAI;IACtD,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IACxE,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;CAC3G,CAuBA"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
function emit(record) {
|
|
2
|
+
console.log(JSON.stringify({
|
|
3
|
+
ts: new Date().toISOString(),
|
|
4
|
+
component: 'vitek',
|
|
5
|
+
...record,
|
|
6
|
+
}));
|
|
7
|
+
}
|
|
8
|
+
export function createConsoleStructuredRequestLogger() {
|
|
9
|
+
return {
|
|
10
|
+
requestStart(method, path, meta) {
|
|
11
|
+
emit({
|
|
12
|
+
event: 'http.request.start',
|
|
13
|
+
method,
|
|
14
|
+
path,
|
|
15
|
+
...(meta?.requestId != null ? { requestId: meta.requestId } : {}),
|
|
16
|
+
...(meta?.route != null ? { route: meta.route } : {}),
|
|
17
|
+
});
|
|
18
|
+
},
|
|
19
|
+
request(method, path, statusCode, duration, meta) {
|
|
20
|
+
emit({
|
|
21
|
+
event: 'http.request.complete',
|
|
22
|
+
method,
|
|
23
|
+
path,
|
|
24
|
+
status: statusCode,
|
|
25
|
+
...(duration !== undefined ? { durationMs: duration } : {}),
|
|
26
|
+
...(meta?.requestId != null ? { requestId: meta.requestId } : {}),
|
|
27
|
+
...(meta?.route != null ? { route: meta.route } : {}),
|
|
28
|
+
});
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-api-bundle.d.ts","sourceRoot":"","sources":["../../src/build/build-api-bundle.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"build-api-bundle.d.ts","sourceRoot":"","sources":["../../src/build/build-api-bundle.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAcH,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAuFD;;;GAGG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAoD3F;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C"}
|
|
@@ -7,6 +7,8 @@ import * as fs from 'fs';
|
|
|
7
7
|
import { scanApiDirectory } from '../core/file-system/scan-api-dir.js';
|
|
8
8
|
import { patternToRegex } from '../core/normalize/normalize-path.js';
|
|
9
9
|
const VITEK_API_BUNDLE_FILENAME = 'vitek-api.mjs';
|
|
10
|
+
const ESM_REQUIRE_SHIM = 'import { createRequire as __createRequire } from "node:module";\n' +
|
|
11
|
+
'const require = __createRequire(import.meta.url);\n';
|
|
10
12
|
/**
|
|
11
13
|
* Generates the virtual entry file content that imports all route handlers and middlewares
|
|
12
14
|
* and exports { routes, middlewares } in the shape expected by createRequestHandler
|
|
@@ -76,6 +78,14 @@ function createAliasPlugin(root, alias) {
|
|
|
76
78
|
},
|
|
77
79
|
};
|
|
78
80
|
}
|
|
81
|
+
function ensureEsmRequireShim(outFile) {
|
|
82
|
+
if (!fs.existsSync(outFile))
|
|
83
|
+
return;
|
|
84
|
+
const content = fs.readFileSync(outFile, 'utf-8');
|
|
85
|
+
if (content.includes('__createRequire(import.meta.url)'))
|
|
86
|
+
return;
|
|
87
|
+
fs.writeFileSync(outFile, `${ESM_REQUIRE_SHIM}${content}`, 'utf-8');
|
|
88
|
+
}
|
|
79
89
|
/**
|
|
80
90
|
* Builds the API bundle and writes it to outDir/vitek-api.mjs
|
|
81
91
|
* Returns the path to the written file, or null if skipped (no apiDir, no routes, or error)
|
|
@@ -113,6 +123,7 @@ export async function buildApiBundle(options) {
|
|
|
113
123
|
minify: true,
|
|
114
124
|
plugins,
|
|
115
125
|
});
|
|
126
|
+
ensureEsmRequireShim(outFile);
|
|
116
127
|
return outFile;
|
|
117
128
|
}
|
|
118
129
|
finally {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-sockets-bundle.d.ts","sourceRoot":"","sources":["../../src/build/build-sockets-bundle.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"build-sockets-bundle.d.ts","sourceRoot":"","sources":["../../src/build/build-sockets-bundle.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAaH,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAqCD;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAqDxB;AAED,wBAAgB,wBAAwB,IAAI,MAAM,CAEjD"}
|
|
@@ -7,6 +7,8 @@ import * as fs from 'fs';
|
|
|
7
7
|
import { scanApiDirectory } from '../core/file-system/scan-api-dir.js';
|
|
8
8
|
import { patternToRegex } from '../core/normalize/normalize-path.js';
|
|
9
9
|
import { VITEK_SOCKETS_BUNDLE_FILENAME } from '../shared/constants.js';
|
|
10
|
+
const ESM_REQUIRE_SHIM = 'import { createRequire as __createRequire } from "node:module";\n' +
|
|
11
|
+
'const require = __createRequire(import.meta.url);\n';
|
|
10
12
|
/**
|
|
11
13
|
* Generates the entry file content that imports all socket handlers
|
|
12
14
|
* and exports { sockets } in the shape expected by createSocketHandler
|
|
@@ -31,6 +33,14 @@ function generateSocketsEntryContent(sockets, entryDir) {
|
|
|
31
33
|
lines.push('export { sockets };');
|
|
32
34
|
return lines.join('\n');
|
|
33
35
|
}
|
|
36
|
+
function ensureEsmRequireShim(outFile) {
|
|
37
|
+
if (!fs.existsSync(outFile))
|
|
38
|
+
return;
|
|
39
|
+
const content = fs.readFileSync(outFile, 'utf-8');
|
|
40
|
+
if (content.includes('__createRequire(import.meta.url)'))
|
|
41
|
+
return;
|
|
42
|
+
fs.writeFileSync(outFile, `${ESM_REQUIRE_SHIM}${content}`, 'utf-8');
|
|
43
|
+
}
|
|
34
44
|
/**
|
|
35
45
|
* Builds the sockets bundle and writes it to outDir/vitek-sockets.mjs
|
|
36
46
|
* Returns the path to the written file, or null if skipped (no sockets or error)
|
|
@@ -65,6 +75,7 @@ export async function buildSocketsBundle(options) {
|
|
|
65
75
|
outfile: outFile,
|
|
66
76
|
external: ['vitek-plugin'],
|
|
67
77
|
});
|
|
78
|
+
ensureEsmRequireShim(outFile);
|
|
68
79
|
return outFile;
|
|
69
80
|
}
|
|
70
81
|
finally {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface ContractCliOptions {
|
|
2
|
+
root: string;
|
|
3
|
+
apiDir: string;
|
|
4
|
+
apiBasePath: string;
|
|
5
|
+
socketBasePath: string;
|
|
6
|
+
failOn: 'error' | 'warning';
|
|
7
|
+
}
|
|
8
|
+
export declare function runContractSnapshot(argv: string[]): Promise<void>;
|
|
9
|
+
export declare function runContractCheck(argv: string[]): Promise<void>;
|
|
10
|
+
export declare function runContract(subCmd: string | undefined, argv: string[]): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../src/cli/contract.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC;CAC7B;AAyCD,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBvE;AAUD,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAmDpE;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAY3F"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { loadMcpConfig } from './mcp-project-config.js';
|
|
4
|
+
import { ASYNCAPI_SNAPSHOT_FILE, CONTRACT_DIR, OPENAPI_SNAPSHOT_FILE, compareAsyncApiSpecs, compareOpenApiSpecs, loadProjectContractSpecs, } from '../core/contract/index.js';
|
|
5
|
+
function parseContractArgs(argv) {
|
|
6
|
+
const out = {};
|
|
7
|
+
for (let i = 0; i < argv.length; i++) {
|
|
8
|
+
const arg = argv[i];
|
|
9
|
+
if (arg.startsWith('--root='))
|
|
10
|
+
out.root = arg.slice(7);
|
|
11
|
+
else if (arg === '--root' && argv[i + 1])
|
|
12
|
+
out.root = argv[++i];
|
|
13
|
+
else if (arg.startsWith('--api-dir='))
|
|
14
|
+
out.apiDir = arg.slice(10);
|
|
15
|
+
else if (arg === '--api-dir' && argv[i + 1])
|
|
16
|
+
out.apiDir = argv[++i];
|
|
17
|
+
else if (arg.startsWith('--fail-on=')) {
|
|
18
|
+
const v = arg.slice(10);
|
|
19
|
+
if (v === 'error' || v === 'warning')
|
|
20
|
+
out.failOn = v;
|
|
21
|
+
}
|
|
22
|
+
else if (arg === '--fail-on' && argv[i + 1]) {
|
|
23
|
+
const v = argv[++i];
|
|
24
|
+
if (v === 'error' || v === 'warning')
|
|
25
|
+
out.failOn = v;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
30
|
+
function resolveOptions(root, overrides) {
|
|
31
|
+
const mcp = loadMcpConfig(root);
|
|
32
|
+
return {
|
|
33
|
+
root,
|
|
34
|
+
apiDir: overrides.apiDir ?? mcp.apiDir,
|
|
35
|
+
apiBasePath: mcp.apiBasePath,
|
|
36
|
+
socketBasePath: mcp.socketBasePath,
|
|
37
|
+
failOn: overrides.failOn ?? 'error',
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function contractPaths(root) {
|
|
41
|
+
const dir = path.join(root, CONTRACT_DIR);
|
|
42
|
+
return {
|
|
43
|
+
dir,
|
|
44
|
+
openApi: path.join(dir, OPENAPI_SNAPSHOT_FILE),
|
|
45
|
+
asyncApi: path.join(dir, ASYNCAPI_SNAPSHOT_FILE),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export async function runContractSnapshot(argv) {
|
|
49
|
+
const parsed = parseContractArgs(argv);
|
|
50
|
+
const root = path.resolve(parsed.root ?? process.cwd());
|
|
51
|
+
const opts = resolveOptions(root, parsed);
|
|
52
|
+
const specs = loadProjectContractSpecs({
|
|
53
|
+
root: opts.root,
|
|
54
|
+
apiDir: opts.apiDir,
|
|
55
|
+
apiBasePath: opts.apiBasePath,
|
|
56
|
+
socketBasePath: opts.socketBasePath,
|
|
57
|
+
});
|
|
58
|
+
const { dir, openApi: openApiPath, asyncApi: asyncApiPath } = contractPaths(opts.root);
|
|
59
|
+
if (!fs.existsSync(dir)) {
|
|
60
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
61
|
+
}
|
|
62
|
+
fs.writeFileSync(openApiPath, JSON.stringify(specs.openApi, null, 2), 'utf-8');
|
|
63
|
+
console.log(`[vitek] Contract snapshot written: ${path.relative(opts.root, openApiPath)}`);
|
|
64
|
+
if (specs.asyncApi != null) {
|
|
65
|
+
fs.writeFileSync(asyncApiPath, JSON.stringify(specs.asyncApi, null, 2), 'utf-8');
|
|
66
|
+
console.log(`[vitek] AsyncAPI snapshot written: ${path.relative(opts.root, asyncApiPath)}`);
|
|
67
|
+
}
|
|
68
|
+
else if (fs.existsSync(asyncApiPath)) {
|
|
69
|
+
fs.unlinkSync(asyncApiPath);
|
|
70
|
+
console.log(`[vitek] Removed AsyncAPI snapshot (no socket routes).`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function formatIssues(issues) {
|
|
74
|
+
if (issues.length === 0) {
|
|
75
|
+
return 'No drift detected.';
|
|
76
|
+
}
|
|
77
|
+
const lines = ['Contract Drift Report', ...issues.map((i) => `- ${i.severity.toUpperCase()}: ${i.message}`)];
|
|
78
|
+
return lines.join('\n');
|
|
79
|
+
}
|
|
80
|
+
export async function runContractCheck(argv) {
|
|
81
|
+
const parsed = parseContractArgs(argv);
|
|
82
|
+
const root = path.resolve(parsed.root ?? process.cwd());
|
|
83
|
+
const opts = resolveOptions(root, parsed);
|
|
84
|
+
const { openApi: openApiPath, asyncApi: asyncApiPath } = contractPaths(opts.root);
|
|
85
|
+
if (!fs.existsSync(openApiPath)) {
|
|
86
|
+
console.error(`[vitek] OpenAPI snapshot not found. Run: vitek contract snapshot`);
|
|
87
|
+
process.exit(2);
|
|
88
|
+
}
|
|
89
|
+
const baselineOpen = JSON.parse(fs.readFileSync(openApiPath, 'utf-8'));
|
|
90
|
+
const specs = loadProjectContractSpecs({
|
|
91
|
+
root: opts.root,
|
|
92
|
+
apiDir: opts.apiDir,
|
|
93
|
+
apiBasePath: opts.apiBasePath,
|
|
94
|
+
socketBasePath: opts.socketBasePath,
|
|
95
|
+
});
|
|
96
|
+
let issues = compareOpenApiSpecs(baselineOpen, specs.openApi);
|
|
97
|
+
if (fs.existsSync(asyncApiPath)) {
|
|
98
|
+
const baselineAsync = JSON.parse(fs.readFileSync(asyncApiPath, 'utf-8'));
|
|
99
|
+
if (specs.asyncApi != null) {
|
|
100
|
+
issues = issues.concat(compareAsyncApiSpecs(baselineAsync, specs.asyncApi));
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
issues = issues.concat([
|
|
104
|
+
{
|
|
105
|
+
severity: 'error',
|
|
106
|
+
code: 'asyncapi_baseline_orphan',
|
|
107
|
+
message: 'Baseline includes AsyncAPI but project has no socket routes.',
|
|
108
|
+
},
|
|
109
|
+
]);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else if (specs.asyncApi != null) {
|
|
113
|
+
issues = issues.concat([
|
|
114
|
+
{
|
|
115
|
+
severity: 'warning',
|
|
116
|
+
code: 'asyncapi_baseline_missing',
|
|
117
|
+
message: 'Project has socket routes but no AsyncAPI snapshot. Run: vitek contract snapshot',
|
|
118
|
+
},
|
|
119
|
+
]);
|
|
120
|
+
}
|
|
121
|
+
console.log(formatIssues(issues));
|
|
122
|
+
const errors = issues.filter((i) => i.severity === 'error').length;
|
|
123
|
+
const warnings = issues.filter((i) => i.severity === 'warning').length;
|
|
124
|
+
if (opts.failOn === 'warning' && (errors > 0 || warnings > 0)) {
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
if (opts.failOn === 'error' && errors > 0) {
|
|
128
|
+
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
export async function runContract(subCmd, argv) {
|
|
132
|
+
if (subCmd === 'snapshot') {
|
|
133
|
+
await runContractSnapshot(argv);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (subCmd === 'check') {
|
|
137
|
+
await runContractCheck(argv);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
console.error('Usage: vitek contract snapshot [--root=DIR] [--api-dir=PATH]');
|
|
141
|
+
console.error(' vitek contract check [--root=DIR] [--api-dir=PATH] [--fail-on=error|warning]');
|
|
142
|
+
process.exit(1);
|
|
143
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"AA6CA,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAiC7D"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { buildDoctorReport } from '../core/doctor/index.js';
|
|
4
|
+
import { loadPlatformConfig } from '../platform/config.js';
|
|
5
|
+
import { redactObject } from '../platform/redaction.js';
|
|
6
|
+
function parseArgs(argv) {
|
|
7
|
+
let root = process.cwd();
|
|
8
|
+
let json = false;
|
|
9
|
+
let aiAnalyze = false;
|
|
10
|
+
for (let i = 0; i < argv.length; i++) {
|
|
11
|
+
const arg = argv[i];
|
|
12
|
+
if (arg.startsWith('--root='))
|
|
13
|
+
root = path.resolve(arg.slice(7));
|
|
14
|
+
else if (arg === '--root' && argv[i + 1])
|
|
15
|
+
root = path.resolve(argv[++i]);
|
|
16
|
+
else if (arg === '--json')
|
|
17
|
+
json = true;
|
|
18
|
+
else if (arg === '--ai-analyze')
|
|
19
|
+
aiAnalyze = true;
|
|
20
|
+
}
|
|
21
|
+
return { root, json, aiAnalyze };
|
|
22
|
+
}
|
|
23
|
+
function printText(report) {
|
|
24
|
+
console.log(`Vitek Doctor Score: ${report.score}/100`);
|
|
25
|
+
for (const d of report.dimensions) {
|
|
26
|
+
console.log(`- ${d.name}: ${d.score}/${d.max}`);
|
|
27
|
+
}
|
|
28
|
+
if (report.topActions.length > 0) {
|
|
29
|
+
console.log('Top actions:');
|
|
30
|
+
report.topActions.forEach((a, idx) => console.log(`${idx + 1}) ${a}`));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function writeLocalAiInput(root, payload) {
|
|
34
|
+
const outDir = path.join(root, '.vitek', 'doctor');
|
|
35
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
36
|
+
const outPath = path.join(outDir, 'ai-input.redacted.json');
|
|
37
|
+
fs.writeFileSync(outPath, JSON.stringify(payload, null, 2), 'utf-8');
|
|
38
|
+
return outPath;
|
|
39
|
+
}
|
|
40
|
+
export async function runDoctor(argv) {
|
|
41
|
+
const args = parseArgs(argv);
|
|
42
|
+
const config = loadPlatformConfig(args.root);
|
|
43
|
+
const report = buildDoctorReport(args.root, config);
|
|
44
|
+
if (args.json) {
|
|
45
|
+
console.log(JSON.stringify(report, null, 2));
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
printText(report);
|
|
49
|
+
}
|
|
50
|
+
if (args.aiAnalyze) {
|
|
51
|
+
if (!config.ai.enabled || config.ai.mode === 'off') {
|
|
52
|
+
console.log('[vitek] AI analyze skipped: ai.enabled=false or ai.mode=off');
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const redacted = redactObject({
|
|
56
|
+
project: path.basename(args.root),
|
|
57
|
+
score: report.score,
|
|
58
|
+
dimensions: report.dimensions,
|
|
59
|
+
topActions: report.topActions,
|
|
60
|
+
}, config.ai.redaction);
|
|
61
|
+
if (config.ai.mode === 'local-only') {
|
|
62
|
+
const outPath = writeLocalAiInput(args.root, redacted);
|
|
63
|
+
console.log(`[vitek] AI local-only payload written: ${outPath}`);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (config.ai.mode === 'remote-redacted') {
|
|
67
|
+
console.log('[vitek] AI remote-redacted mode is enabled. Network transport is not configured in this baseline.');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/cli/generate.ts"],"names":[],"mappings":"AAgCA,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuB3F"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { generateCrudFiles } from '../core/generators/index.js';
|
|
4
|
+
function parseCrudArgs(argv) {
|
|
5
|
+
const model = argv[0];
|
|
6
|
+
if (!model) {
|
|
7
|
+
throw new Error('Model is required. Usage: vitek generate crud <Model> --adapter prisma --out src/api/<model>');
|
|
8
|
+
}
|
|
9
|
+
let adapter = 'prisma';
|
|
10
|
+
let outDir = `src/api/${model.toLowerCase()}s`;
|
|
11
|
+
let root = process.cwd();
|
|
12
|
+
for (let i = 1; i < argv.length; i++) {
|
|
13
|
+
const arg = argv[i];
|
|
14
|
+
if (arg.startsWith('--adapter='))
|
|
15
|
+
adapter = arg.slice(10);
|
|
16
|
+
else if (arg === '--adapter' && argv[i + 1])
|
|
17
|
+
adapter = argv[++i];
|
|
18
|
+
else if (arg.startsWith('--out='))
|
|
19
|
+
outDir = arg.slice(6);
|
|
20
|
+
else if (arg === '--out' && argv[i + 1])
|
|
21
|
+
outDir = argv[++i];
|
|
22
|
+
else if (arg.startsWith('--root='))
|
|
23
|
+
root = path.resolve(arg.slice(7));
|
|
24
|
+
else if (arg === '--root' && argv[i + 1])
|
|
25
|
+
root = path.resolve(argv[++i]);
|
|
26
|
+
}
|
|
27
|
+
if (!['prisma', 'drizzle', 'sql'].includes(adapter)) {
|
|
28
|
+
throw new Error(`Unsupported adapter: ${adapter}. Use prisma, drizzle, or sql.`);
|
|
29
|
+
}
|
|
30
|
+
return { model, adapter, outDir, root };
|
|
31
|
+
}
|
|
32
|
+
export async function runGenerate(subCmd, argv) {
|
|
33
|
+
if (subCmd !== 'crud') {
|
|
34
|
+
console.error('Usage: vitek generate crud <Model> --adapter prisma|drizzle|sql --out src/api/<name>');
|
|
35
|
+
process.exit(1);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const opts = parseCrudArgs(argv);
|
|
40
|
+
const files = generateCrudFiles(opts);
|
|
41
|
+
for (const file of files) {
|
|
42
|
+
const abs = path.resolve(opts.root, file.path);
|
|
43
|
+
fs.mkdirSync(path.dirname(abs), { recursive: true });
|
|
44
|
+
fs.writeFileSync(abs, file.content, 'utf-8');
|
|
45
|
+
}
|
|
46
|
+
console.log(`[vitek] Generated ${files.length} file(s) for model ${opts.model} using ${opts.adapter}`);
|
|
47
|
+
for (const file of files) {
|
|
48
|
+
console.log(`- ${file.path}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
53
|
+
console.error(`[vitek] ${message}`);
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-docs.d.ts","sourceRoot":"","sources":["../../src/cli/mcp-docs.ts"],"names":[],"mappings":"AAEA,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAEhD"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { VitekMcpConfig } from './mcp-project-config.js';
|
|
3
|
+
export declare function registerMcpWriteTools(server: McpServer, root: string, config: VitekMcpConfig): void;
|
|
4
|
+
//# sourceMappingURL=mcp-project-write-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-project-write-tools.d.ts","sourceRoot":"","sources":["../../src/cli/mcp-project-write-tools.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAiB9D,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAqFnG"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { handleVitekOpenapiSync, handleVitekRouteCreate, handleVitekRouteUpdate, handleVitekTestGenerate, handleVitekValidationSuggest, } from '../mcp/write/project-write-handlers.js';
|
|
3
|
+
function respond(r) {
|
|
4
|
+
return {
|
|
5
|
+
content: [{ type: 'text', text: JSON.stringify(r, null, 2) }],
|
|
6
|
+
isError: !r.ok,
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
export function registerMcpWriteTools(server, root, config) {
|
|
10
|
+
const ctx = {
|
|
11
|
+
root,
|
|
12
|
+
apiDir: config.apiDir,
|
|
13
|
+
apiBasePath: config.apiBasePath,
|
|
14
|
+
baseUrl: config.baseUrl,
|
|
15
|
+
};
|
|
16
|
+
server.registerTool('vitek_route_create', {
|
|
17
|
+
title: 'Create Vitek route (write-safe)',
|
|
18
|
+
description: 'Dry-run by default: returns unified diff and risk hints. Writes only with apply:true, dryRun:false, and vitek.platform.json features.mcpWriteTools:true.',
|
|
19
|
+
inputSchema: {
|
|
20
|
+
routePath: z.string().describe('Logical path, e.g. health or users/[id] or users/:id'),
|
|
21
|
+
method: z.enum(['get', 'post', 'put', 'patch', 'delete', 'head', 'options']),
|
|
22
|
+
extension: z.enum(['ts', 'js']).optional().default('ts'),
|
|
23
|
+
dryRun: z.boolean().optional().default(true),
|
|
24
|
+
apply: z.boolean().optional().default(false),
|
|
25
|
+
},
|
|
26
|
+
}, async (input) => respond(handleVitekRouteCreate(ctx, input)));
|
|
27
|
+
server.registerTool('vitek_route_update', {
|
|
28
|
+
title: 'Replace Vitek route file (write-safe)',
|
|
29
|
+
description: 'Overwrites an existing route file. Dry-run by default; same apply rules as vitek_route_create.',
|
|
30
|
+
inputSchema: {
|
|
31
|
+
filePath: z.string().describe('Path relative to project root, e.g. src/api/health.get.ts'),
|
|
32
|
+
content: z.string().describe('Full new file content'),
|
|
33
|
+
dryRun: z.boolean().optional().default(true),
|
|
34
|
+
apply: z.boolean().optional().default(false),
|
|
35
|
+
},
|
|
36
|
+
}, async (input) => respond(handleVitekRouteUpdate(ctx, input)));
|
|
37
|
+
server.registerTool('vitek_validation_suggest', {
|
|
38
|
+
title: 'Suggest validateBody scaffold (write-safe)',
|
|
39
|
+
description: 'Proposes import + validateBody(context.body, {}). Dry-run by default; same apply rules.',
|
|
40
|
+
inputSchema: {
|
|
41
|
+
filePath: z.string().describe('Route file path relative to project root'),
|
|
42
|
+
dryRun: z.boolean().optional().default(true),
|
|
43
|
+
apply: z.boolean().optional().default(false),
|
|
44
|
+
},
|
|
45
|
+
}, async (input) => respond(handleVitekValidationSuggest(ctx, input)));
|
|
46
|
+
server.registerTool('vitek_test_generate', {
|
|
47
|
+
title: 'Generate Vitest fetch test for route (write-safe)',
|
|
48
|
+
description: 'Creates colocated *.test.ts next to the route. Dry-run by default; same apply rules.',
|
|
49
|
+
inputSchema: {
|
|
50
|
+
routeFilePath: z.string().describe('Route file path relative to project root'),
|
|
51
|
+
dryRun: z.boolean().optional().default(true),
|
|
52
|
+
apply: z.boolean().optional().default(false),
|
|
53
|
+
},
|
|
54
|
+
}, async (input) => respond(handleVitekTestGenerate(ctx, input)));
|
|
55
|
+
server.registerTool('vitek_openapi_sync', {
|
|
56
|
+
title: 'Sync JSDoc @summary for OpenAPI (write-safe)',
|
|
57
|
+
description: 'Sets @summary from manifest (METHOD pattern). Dry-run by default; same apply rules.',
|
|
58
|
+
inputSchema: {
|
|
59
|
+
filePath: z.string().describe('Route file path relative to project root'),
|
|
60
|
+
dryRun: z.boolean().optional().default(true),
|
|
61
|
+
apply: z.boolean().optional().default(false),
|
|
62
|
+
},
|
|
63
|
+
}, async (input) => respond(handleVitekOpenapiSync(ctx, input)));
|
|
64
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule.d.ts","sourceRoot":"","sources":["../../src/cli/schedule.ts"],"names":[],"mappings":"AAgCA,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAmC3F"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { pathToFileURL } from 'url';
|
|
4
|
+
import { runScheduleOnce } from '../core/scheduler/index.js';
|
|
5
|
+
function parseArgs(argv) {
|
|
6
|
+
let root = process.cwd();
|
|
7
|
+
let file = 'vitek.schedule.mjs';
|
|
8
|
+
let json = false;
|
|
9
|
+
for (let i = 0; i < argv.length; i++) {
|
|
10
|
+
const arg = argv[i];
|
|
11
|
+
if (arg.startsWith('--root='))
|
|
12
|
+
root = path.resolve(arg.slice(7));
|
|
13
|
+
else if (arg === '--root' && argv[i + 1])
|
|
14
|
+
root = path.resolve(argv[++i]);
|
|
15
|
+
else if (arg.startsWith('--file='))
|
|
16
|
+
file = arg.slice(7);
|
|
17
|
+
else if (arg === '--file' && argv[i + 1])
|
|
18
|
+
file = argv[++i];
|
|
19
|
+
else if (arg === '--json')
|
|
20
|
+
json = true;
|
|
21
|
+
}
|
|
22
|
+
return { root, file, json };
|
|
23
|
+
}
|
|
24
|
+
function extractDefinition(mod) {
|
|
25
|
+
const candidate = (mod.default ?? mod.schedule);
|
|
26
|
+
if (!candidate || !Array.isArray(candidate.tasks))
|
|
27
|
+
return null;
|
|
28
|
+
return candidate;
|
|
29
|
+
}
|
|
30
|
+
export async function runSchedule(subCmd, argv) {
|
|
31
|
+
if (subCmd !== 'run') {
|
|
32
|
+
console.error('Usage: vitek schedule run [--root=DIR] [--file=vitek.schedule.mjs] [--json]');
|
|
33
|
+
process.exit(1);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const opts = parseArgs(argv);
|
|
37
|
+
const filePath = path.isAbsolute(opts.file) ? opts.file : path.join(opts.root, opts.file);
|
|
38
|
+
if (!fs.existsSync(filePath)) {
|
|
39
|
+
console.error(`[vitek] Schedule file not found: ${filePath}`);
|
|
40
|
+
process.exit(2);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const mod = (await import(pathToFileURL(filePath).href));
|
|
44
|
+
const definition = extractDefinition(mod);
|
|
45
|
+
if (!definition) {
|
|
46
|
+
console.error('[vitek] Invalid schedule file. Export default defineSchedule({ tasks: [...] })');
|
|
47
|
+
process.exit(1);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const result = await runScheduleOnce(definition);
|
|
51
|
+
if (opts.json) {
|
|
52
|
+
console.log(JSON.stringify(result, null, 2));
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
console.log('Vitek Schedule Run');
|
|
56
|
+
for (const task of result.tasks) {
|
|
57
|
+
const status = task.ok ? 'OK' : 'ERROR';
|
|
58
|
+
const error = task.error ? ` - ${task.error}` : '';
|
|
59
|
+
console.log(`- ${status}: ${task.name} (${task.cron})${error}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (result.tasks.some((t) => !t.ok)) {
|
|
63
|
+
process.exit(1);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
}
|