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.
Files changed (263) hide show
  1. package/README.md +1 -1
  2. package/dist/adapters/dispatch/http-webhook.d.ts +10 -0
  3. package/dist/adapters/dispatch/http-webhook.d.ts.map +1 -0
  4. package/dist/adapters/dispatch/http-webhook.js +38 -0
  5. package/dist/adapters/node/console-structured-request-logger.d.ts +6 -0
  6. package/dist/adapters/node/console-structured-request-logger.d.ts.map +1 -0
  7. package/dist/adapters/node/console-structured-request-logger.js +31 -0
  8. package/dist/build/build-api-bundle.d.ts.map +1 -1
  9. package/dist/build/build-api-bundle.js +11 -0
  10. package/dist/build/build-sockets-bundle.d.ts.map +1 -1
  11. package/dist/build/build-sockets-bundle.js +11 -0
  12. package/dist/cli/contract.d.ts +11 -0
  13. package/dist/cli/contract.d.ts.map +1 -0
  14. package/dist/cli/contract.js +143 -0
  15. package/dist/cli/doctor.d.ts +2 -0
  16. package/dist/cli/doctor.d.ts.map +1 -0
  17. package/dist/cli/doctor.js +70 -0
  18. package/dist/cli/generate.d.ts +2 -0
  19. package/dist/cli/generate.d.ts.map +1 -0
  20. package/dist/cli/generate.js +56 -0
  21. package/dist/cli/mcp-docs.d.ts +2 -0
  22. package/dist/cli/mcp-docs.d.ts.map +1 -0
  23. package/dist/cli/mcp-docs.js +4 -0
  24. package/dist/cli/mcp-project-write-tools.d.ts +4 -0
  25. package/dist/cli/mcp-project-write-tools.d.ts.map +1 -0
  26. package/dist/cli/mcp-project-write-tools.js +64 -0
  27. package/dist/cli/schedule.d.ts +2 -0
  28. package/dist/cli/schedule.d.ts.map +1 -0
  29. package/dist/cli/schedule.js +66 -0
  30. package/dist/core/contract/compare-asyncapi.d.ts +3 -0
  31. package/dist/core/contract/compare-asyncapi.d.ts.map +1 -0
  32. package/dist/core/contract/compare-asyncapi.js +45 -0
  33. package/dist/core/contract/compare-openapi.d.ts +3 -0
  34. package/dist/core/contract/compare-openapi.d.ts.map +1 -0
  35. package/dist/core/contract/compare-openapi.js +116 -0
  36. package/dist/core/contract/http-methods.d.ts +2 -0
  37. package/dist/core/contract/http-methods.d.ts.map +1 -0
  38. package/dist/core/contract/http-methods.js +2 -0
  39. package/dist/core/contract/index.d.ts +9 -0
  40. package/dist/core/contract/index.d.ts.map +1 -0
  41. package/dist/core/contract/index.js +7 -0
  42. package/dist/core/contract/project-specs.d.ts +12 -0
  43. package/dist/core/contract/project-specs.d.ts.map +1 -0
  44. package/dist/core/contract/project-specs.js +27 -0
  45. package/dist/core/contract/sort-json.d.ts +2 -0
  46. package/dist/core/contract/sort-json.d.ts.map +1 -0
  47. package/dist/core/contract/sort-json.js +14 -0
  48. package/dist/core/contract/types.d.ts +7 -0
  49. package/dist/core/contract/types.d.ts.map +1 -0
  50. package/dist/core/contract/types.js +1 -0
  51. package/dist/core/dispatch/dispatchers.d.ts +4 -0
  52. package/dist/core/dispatch/dispatchers.d.ts.map +1 -0
  53. package/dist/core/dispatch/dispatchers.js +16 -0
  54. package/dist/core/dispatch/emit-safe.d.ts +3 -0
  55. package/dist/core/dispatch/emit-safe.d.ts.map +1 -0
  56. package/dist/core/dispatch/emit-safe.js +10 -0
  57. package/dist/core/dispatch/index.d.ts +4 -0
  58. package/dist/core/dispatch/index.d.ts.map +1 -0
  59. package/dist/core/dispatch/index.js +2 -0
  60. package/dist/core/dispatch/types.d.ts +22 -0
  61. package/dist/core/dispatch/types.d.ts.map +1 -0
  62. package/dist/core/dispatch/types.js +1 -0
  63. package/dist/core/doctor/index.d.ts +3 -0
  64. package/dist/core/doctor/index.d.ts.map +1 -0
  65. package/dist/core/doctor/index.js +1 -0
  66. package/dist/core/doctor/report.d.ts +4 -0
  67. package/dist/core/doctor/report.d.ts.map +1 -0
  68. package/dist/core/doctor/report.js +166 -0
  69. package/dist/core/doctor/scan.d.ts +3 -0
  70. package/dist/core/doctor/scan.d.ts.map +1 -0
  71. package/dist/core/doctor/scan.js +23 -0
  72. package/dist/core/doctor/types.d.ts +12 -0
  73. package/dist/core/doctor/types.d.ts.map +1 -0
  74. package/dist/core/doctor/types.js +1 -0
  75. package/dist/core/events/event-bus.d.ts +8 -0
  76. package/dist/core/events/event-bus.d.ts.map +1 -0
  77. package/dist/core/events/event-bus.js +26 -0
  78. package/dist/core/events/index.d.ts +3 -0
  79. package/dist/core/events/index.d.ts.map +1 -0
  80. package/dist/core/events/index.js +1 -0
  81. package/dist/core/generators/adapters/drizzle.d.ts +3 -0
  82. package/dist/core/generators/adapters/drizzle.d.ts.map +1 -0
  83. package/dist/core/generators/adapters/drizzle.js +26 -0
  84. package/dist/core/generators/adapters/prisma.d.ts +3 -0
  85. package/dist/core/generators/adapters/prisma.d.ts.map +1 -0
  86. package/dist/core/generators/adapters/prisma.js +136 -0
  87. package/dist/core/generators/adapters/sql.d.ts +3 -0
  88. package/dist/core/generators/adapters/sql.d.ts.map +1 -0
  89. package/dist/core/generators/adapters/sql.js +26 -0
  90. package/dist/core/generators/generate-crud.d.ts +8 -0
  91. package/dist/core/generators/generate-crud.d.ts.map +1 -0
  92. package/dist/core/generators/generate-crud.js +17 -0
  93. package/dist/core/generators/index.d.ts +3 -0
  94. package/dist/core/generators/index.d.ts.map +1 -0
  95. package/dist/core/generators/index.js +1 -0
  96. package/dist/core/generators/types.d.ts +16 -0
  97. package/dist/core/generators/types.d.ts.map +1 -0
  98. package/dist/core/generators/types.js +1 -0
  99. package/dist/core/generators/utils.d.ts +3 -0
  100. package/dist/core/generators/utils.d.ts.map +1 -0
  101. package/dist/core/generators/utils.js +10 -0
  102. package/dist/core/observability/with-span.d.ts +5 -0
  103. package/dist/core/observability/with-span.d.ts.map +1 -0
  104. package/dist/core/observability/with-span.js +7 -0
  105. package/dist/core/scheduler/define-schedule.d.ts +3 -0
  106. package/dist/core/scheduler/define-schedule.d.ts.map +1 -0
  107. package/dist/core/scheduler/define-schedule.js +3 -0
  108. package/dist/core/scheduler/in-memory-lock.d.ts +6 -0
  109. package/dist/core/scheduler/in-memory-lock.d.ts.map +1 -0
  110. package/dist/core/scheduler/in-memory-lock.js +12 -0
  111. package/dist/core/scheduler/index.d.ts +5 -0
  112. package/dist/core/scheduler/index.d.ts.map +1 -0
  113. package/dist/core/scheduler/index.js +3 -0
  114. package/dist/core/scheduler/runner.d.ts +6 -0
  115. package/dist/core/scheduler/runner.d.ts.map +1 -0
  116. package/dist/core/scheduler/runner.js +37 -0
  117. package/dist/core/scheduler/types.d.ts +21 -0
  118. package/dist/core/scheduler/types.d.ts.map +1 -0
  119. package/dist/core/scheduler/types.js +1 -0
  120. package/dist/core/server/request-log-meta.d.ts +5 -0
  121. package/dist/core/server/request-log-meta.d.ts.map +1 -0
  122. package/dist/core/server/request-log-meta.js +1 -0
  123. package/dist/mcp/write/apply-guard.d.ts +7 -0
  124. package/dist/mcp/write/apply-guard.d.ts.map +1 -0
  125. package/dist/mcp/write/apply-guard.js +22 -0
  126. package/dist/mcp/write/openapi-jsdoc.d.ts +2 -0
  127. package/dist/mcp/write/openapi-jsdoc.d.ts.map +1 -0
  128. package/dist/mcp/write/openapi-jsdoc.js +15 -0
  129. package/dist/mcp/write/project-write-handlers.d.ts +46 -0
  130. package/dist/mcp/write/project-write-handlers.d.ts.map +1 -0
  131. package/dist/mcp/write/project-write-handlers.js +304 -0
  132. package/dist/mcp/write/risks.d.ts +3 -0
  133. package/dist/mcp/write/risks.d.ts.map +1 -0
  134. package/dist/mcp/write/risks.js +20 -0
  135. package/dist/mcp/write/route-snippet.d.ts +5 -0
  136. package/dist/mcp/write/route-snippet.d.ts.map +1 -0
  137. package/dist/mcp/write/route-snippet.js +46 -0
  138. package/dist/mcp/write/safe-path.d.ts +3 -0
  139. package/dist/mcp/write/safe-path.d.ts.map +1 -0
  140. package/dist/mcp/write/safe-path.js +16 -0
  141. package/dist/mcp/write/test-file-content.d.ts +8 -0
  142. package/dist/mcp/write/test-file-content.d.ts.map +1 -0
  143. package/dist/mcp/write/test-file-content.js +31 -0
  144. package/dist/mcp/write/unified-diff.d.ts +2 -0
  145. package/dist/mcp/write/unified-diff.d.ts.map +1 -0
  146. package/dist/mcp/write/unified-diff.js +19 -0
  147. package/dist/mcp/write/validation-scaffold.d.ts +2 -0
  148. package/dist/mcp/write/validation-scaffold.d.ts.map +1 -0
  149. package/dist/mcp/write/validation-scaffold.js +31 -0
  150. package/dist/mcp-docs-server/resources/configuration.d.ts +3 -0
  151. package/dist/mcp-docs-server/resources/configuration.d.ts.map +1 -0
  152. package/dist/mcp-docs-server/resources/configuration.js +25 -0
  153. package/dist/mcp-docs-server/resources/context.d.ts +3 -0
  154. package/dist/mcp-docs-server/resources/context.d.ts.map +1 -0
  155. package/dist/mcp-docs-server/resources/context.js +34 -0
  156. package/dist/mcp-docs-server/resources/errors.d.ts +3 -0
  157. package/dist/mcp-docs-server/resources/errors.d.ts.map +1 -0
  158. package/dist/mcp-docs-server/resources/errors.js +27 -0
  159. package/dist/mcp-docs-server/resources/introspection.d.ts +3 -0
  160. package/dist/mcp-docs-server/resources/introspection.d.ts.map +1 -0
  161. package/dist/mcp-docs-server/resources/introspection.js +24 -0
  162. package/dist/mcp-docs-server/resources/middlewares.d.ts +3 -0
  163. package/dist/mcp-docs-server/resources/middlewares.d.ts.map +1 -0
  164. package/dist/mcp-docs-server/resources/middlewares.js +36 -0
  165. package/dist/mcp-docs-server/resources/plugin-api.d.ts +3 -0
  166. package/dist/mcp-docs-server/resources/plugin-api.d.ts.map +1 -0
  167. package/dist/mcp-docs-server/resources/plugin-api.js +32 -0
  168. package/dist/mcp-docs-server/resources/response.d.ts +3 -0
  169. package/dist/mcp-docs-server/resources/response.d.ts.map +1 -0
  170. package/dist/mcp-docs-server/resources/response.js +39 -0
  171. package/dist/mcp-docs-server/resources/routing.d.ts +3 -0
  172. package/dist/mcp-docs-server/resources/routing.d.ts.map +1 -0
  173. package/dist/mcp-docs-server/resources/routing.js +47 -0
  174. package/dist/mcp-docs-server/resources/validation.d.ts +3 -0
  175. package/dist/mcp-docs-server/resources/validation.d.ts.map +1 -0
  176. package/dist/mcp-docs-server/resources/validation.js +37 -0
  177. package/dist/mcp-docs-server/resources/websockets.d.ts +3 -0
  178. package/dist/mcp-docs-server/resources/websockets.d.ts.map +1 -0
  179. package/dist/mcp-docs-server/resources/websockets.js +42 -0
  180. package/dist/mcp-docs-server/start-mcp-docs-server.d.ts +2 -0
  181. package/dist/mcp-docs-server/start-mcp-docs-server.d.ts.map +1 -0
  182. package/dist/mcp-docs-server/start-mcp-docs-server.js +171 -0
  183. package/dist/mcp-docs-server/tools/create-middleware.d.ts +5 -0
  184. package/dist/mcp-docs-server/tools/create-middleware.d.ts.map +1 -0
  185. package/dist/mcp-docs-server/tools/create-middleware.js +29 -0
  186. package/dist/mcp-docs-server/tools/create-route.d.ts +5 -0
  187. package/dist/mcp-docs-server/tools/create-route.d.ts.map +1 -0
  188. package/dist/mcp-docs-server/tools/create-route.js +44 -0
  189. package/dist/mcp-docs-server/tools/create-socket.d.ts +5 -0
  190. package/dist/mcp-docs-server/tools/create-socket.d.ts.map +1 -0
  191. package/dist/mcp-docs-server/tools/create-socket.js +39 -0
  192. package/dist/mcp-docs-server/tools/suggest-vite-config.d.ts +11 -0
  193. package/dist/mcp-docs-server/tools/suggest-vite-config.d.ts.map +1 -0
  194. package/dist/mcp-docs-server/tools/suggest-vite-config.js +30 -0
  195. package/dist/mcp-docs-server/tools/validate-convention.d.ts +21 -0
  196. package/dist/mcp-docs-server/tools/validate-convention.d.ts.map +1 -0
  197. package/dist/mcp-docs-server/tools/validate-convention.js +48 -0
  198. package/dist/platform/config.d.ts +30 -0
  199. package/dist/platform/config.d.ts.map +1 -0
  200. package/dist/platform/config.js +85 -0
  201. package/dist/platform/correlation.d.ts +5 -0
  202. package/dist/platform/correlation.d.ts.map +1 -0
  203. package/dist/platform/correlation.js +19 -0
  204. package/dist/platform/index.d.ts +5 -0
  205. package/dist/platform/index.d.ts.map +1 -0
  206. package/dist/platform/index.js +3 -0
  207. package/dist/platform/redaction.d.ts +6 -0
  208. package/dist/platform/redaction.d.ts.map +1 -0
  209. package/dist/platform/redaction.js +40 -0
  210. package/dist/plugin/mode.d.ts +5 -0
  211. package/dist/plugin/mode.d.ts.map +1 -0
  212. package/dist/plugin/mode.js +7 -0
  213. package/dist/plugin/vitek-resolve.d.ts.map +1 -1
  214. package/dist/plugin/vitek-resolve.js +4 -3
  215. package/dist/plugin/vitek-transform.d.ts +1 -1
  216. package/dist/plugin/vitek-transform.d.ts.map +1 -1
  217. package/dist/plugin/vitek-transform.js +30 -5
  218. package/dist/public/dispatch.d.ts +3 -0
  219. package/dist/public/dispatch.d.ts.map +1 -0
  220. package/dist/public/dispatch.js +1 -0
  221. package/dist/public/doctor.d.ts +3 -0
  222. package/dist/public/doctor.d.ts.map +1 -0
  223. package/dist/public/doctor.js +1 -0
  224. package/dist/public/errors.d.ts +2 -0
  225. package/dist/public/errors.d.ts.map +1 -0
  226. package/dist/public/errors.js +1 -0
  227. package/dist/public/events.d.ts +3 -0
  228. package/dist/public/events.d.ts.map +1 -0
  229. package/dist/public/events.js +1 -0
  230. package/dist/public/generators.d.ts +3 -0
  231. package/dist/public/generators.d.ts.map +1 -0
  232. package/dist/public/generators.js +1 -0
  233. package/dist/public/introspection.d.ts +3 -0
  234. package/dist/public/introspection.d.ts.map +1 -0
  235. package/dist/public/introspection.js +1 -0
  236. package/dist/public/observability.d.ts +3 -0
  237. package/dist/public/observability.d.ts.map +1 -0
  238. package/dist/public/observability.js +1 -0
  239. package/dist/public/platform.d.ts +3 -0
  240. package/dist/public/platform.d.ts.map +1 -0
  241. package/dist/public/platform.js +1 -0
  242. package/dist/public/plugin.d.ts +3 -0
  243. package/dist/public/plugin.d.ts.map +1 -0
  244. package/dist/public/plugin.js +1 -0
  245. package/dist/public/response.d.ts +2 -0
  246. package/dist/public/response.d.ts.map +1 -0
  247. package/dist/public/response.js +1 -0
  248. package/dist/public/scheduler.d.ts +3 -0
  249. package/dist/public/scheduler.d.ts.map +1 -0
  250. package/dist/public/scheduler.js +1 -0
  251. package/dist/public/testing.d.ts +3 -0
  252. package/dist/public/testing.d.ts.map +1 -0
  253. package/dist/public/testing.js +1 -0
  254. package/dist/public/validation.d.ts +3 -0
  255. package/dist/public/validation.d.ts.map +1 -0
  256. package/dist/public/validation.js +1 -0
  257. package/dist/shared/mode.d.ts +5 -0
  258. package/dist/shared/mode.d.ts.map +1 -0
  259. package/dist/shared/mode.js +7 -0
  260. package/dist/testing/testing.d.ts +15 -0
  261. package/dist/testing/testing.d.ts.map +1 -0
  262. package/dist/testing/testing.js +51 -0
  263. package/package.json +23 -21
@@ -0,0 +1,304 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { getManifest } from '../../core/introspection/manifest.js';
4
+ import { parseRouteFile } from '../../core/routing/route-parser.js';
5
+ import { resolveApplyMode } from './apply-guard.js';
6
+ import { buildRouteFileContent } from './route-snippet.js';
7
+ import { computeRouteRisks } from './risks.js';
8
+ import { assertUnderApiDir, resolvePathUnderRoot } from './safe-path.js';
9
+ import { unifiedFileDiff } from './unified-diff.js';
10
+ import { applyOpenApiSummaryToFileContent } from './openapi-jsdoc.js';
11
+ import { injectValidationScaffold } from './validation-scaffold.js';
12
+ import { buildRouteTestFileContent } from './test-file-content.js';
13
+ function okResult(partial) {
14
+ return { ok: true, ...partial };
15
+ }
16
+ function errResult(message) {
17
+ return {
18
+ ok: false,
19
+ dryRun: true,
20
+ diff: '',
21
+ risk: [],
22
+ next: '',
23
+ error: message,
24
+ };
25
+ }
26
+ export function handleVitekRouteCreate(ctx, input) {
27
+ const dryRun = input.dryRun !== false;
28
+ const apply = input.apply === true;
29
+ const ext = input.extension ?? 'ts';
30
+ const apiDirAbs = path.resolve(ctx.root, ctx.apiDir);
31
+ let built;
32
+ try {
33
+ built = buildRouteFileContent(input.routePath, input.method, ext);
34
+ }
35
+ catch (e) {
36
+ return errResult(e instanceof Error ? e.message : String(e));
37
+ }
38
+ const rel = path.join(ctx.apiDir, built.relativeFilePath).replace(/\\/g, '/');
39
+ const abs = resolvePathUnderRoot(ctx.root, rel);
40
+ if (!abs || !assertUnderApiDir(ctx.root, ctx.apiDir, abs)) {
41
+ return errResult('Invalid path: must stay under project root and api directory.');
42
+ }
43
+ const manifest = getManifest(ctx.root, ctx.apiDir);
44
+ const parsed = parseRouteFile(abs, apiDirAbs);
45
+ const pattern = parsed?.pattern ?? input.routePath.replace(/\\/g, '/');
46
+ const risk = computeRouteRisks(manifest, pattern, input.method.toLowerCase());
47
+ if (fs.existsSync(abs)) {
48
+ risk.unshift('Target file already exists; write would overwrite.');
49
+ }
50
+ const before = fs.existsSync(abs) ? fs.readFileSync(abs, 'utf-8') : null;
51
+ const diff = unifiedFileDiff(rel, before, built.content);
52
+ const resolution = resolveApplyMode(ctx.root, apply, dryRun);
53
+ if (resolution.rejectReason) {
54
+ return okResult({
55
+ dryRun: true,
56
+ diff,
57
+ risk,
58
+ next: resolution.rejectReason,
59
+ rejectReason: resolution.rejectReason,
60
+ filePath: rel,
61
+ });
62
+ }
63
+ if (!resolution.writeAllowed) {
64
+ return okResult({
65
+ dryRun: true,
66
+ diff,
67
+ risk,
68
+ next: 'Call again with apply: true and dryRun: false to write the file (requires vitek.platform.json mcpWriteTools).',
69
+ filePath: rel,
70
+ });
71
+ }
72
+ fs.mkdirSync(path.dirname(abs), { recursive: true });
73
+ fs.writeFileSync(abs, built.content, 'utf-8');
74
+ return okResult({
75
+ dryRun: false,
76
+ written: true,
77
+ diff,
78
+ risk,
79
+ next: 'File written.',
80
+ filePath: rel,
81
+ });
82
+ }
83
+ export function handleVitekRouteUpdate(ctx, input) {
84
+ const dryRun = input.dryRun !== false;
85
+ const apply = input.apply === true;
86
+ const rel = input.filePath.replace(/\\/g, '/').replace(/^\/+/, '');
87
+ const abs = resolvePathUnderRoot(ctx.root, rel);
88
+ if (!abs || !assertUnderApiDir(ctx.root, ctx.apiDir, abs)) {
89
+ return errResult('Invalid path: must stay under project root and api directory.');
90
+ }
91
+ const before = fs.existsSync(abs) ? fs.readFileSync(abs, 'utf-8') : null;
92
+ if (before === null) {
93
+ return errResult('File does not exist. Use vitek_route_create for new routes.');
94
+ }
95
+ const diff = unifiedFileDiff(rel, before, input.content);
96
+ const risk = ['Overwrites entire file content.'];
97
+ const resolution = resolveApplyMode(ctx.root, apply, dryRun);
98
+ if (resolution.rejectReason) {
99
+ return okResult({
100
+ dryRun: true,
101
+ diff,
102
+ risk,
103
+ next: resolution.rejectReason,
104
+ rejectReason: resolution.rejectReason,
105
+ filePath: rel,
106
+ });
107
+ }
108
+ if (!resolution.writeAllowed) {
109
+ return okResult({
110
+ dryRun: true,
111
+ diff,
112
+ risk,
113
+ next: 'Call again with apply: true and dryRun: false to write.',
114
+ filePath: rel,
115
+ });
116
+ }
117
+ fs.writeFileSync(abs, input.content, 'utf-8');
118
+ return okResult({
119
+ dryRun: false,
120
+ written: true,
121
+ diff,
122
+ risk,
123
+ next: 'File updated.',
124
+ filePath: rel,
125
+ });
126
+ }
127
+ export function handleVitekValidationSuggest(ctx, input) {
128
+ const dryRun = input.dryRun !== false;
129
+ const apply = input.apply === true;
130
+ const rel = input.filePath.replace(/\\/g, '/').replace(/^\/+/, '');
131
+ const abs = resolvePathUnderRoot(ctx.root, rel);
132
+ if (!abs || !assertUnderApiDir(ctx.root, ctx.apiDir, abs)) {
133
+ return errResult('Invalid path: must stay under project root and api directory.');
134
+ }
135
+ if (!fs.existsSync(abs)) {
136
+ return errResult('File not found.');
137
+ }
138
+ const before = fs.readFileSync(abs, 'utf-8');
139
+ if (/validateBody\s*\(/.test(before)) {
140
+ return okResult({
141
+ dryRun: true,
142
+ diff: '',
143
+ risk: [],
144
+ next: 'File already calls validateBody; no change.',
145
+ filePath: rel,
146
+ });
147
+ }
148
+ const after = injectValidationScaffold(before);
149
+ const diff = unifiedFileDiff(rel, before, after);
150
+ const risk = [
151
+ 'Adds validateBody(context.body, {}); replace {} with a real ValidationSchema.',
152
+ 'May not suit GET routes without a body; edit after apply.',
153
+ ];
154
+ const resolution = resolveApplyMode(ctx.root, apply, dryRun);
155
+ if (resolution.rejectReason) {
156
+ return okResult({
157
+ dryRun: true,
158
+ diff,
159
+ risk,
160
+ next: resolution.rejectReason,
161
+ rejectReason: resolution.rejectReason,
162
+ filePath: rel,
163
+ });
164
+ }
165
+ if (!resolution.writeAllowed) {
166
+ return okResult({
167
+ dryRun: true,
168
+ diff,
169
+ risk,
170
+ next: 'Call again with apply: true and dryRun: false to write.',
171
+ filePath: rel,
172
+ });
173
+ }
174
+ fs.writeFileSync(abs, after, 'utf-8');
175
+ return okResult({
176
+ dryRun: false,
177
+ written: true,
178
+ diff,
179
+ risk,
180
+ next: 'Validation scaffold written; tighten schema and remove if not needed.',
181
+ filePath: rel,
182
+ });
183
+ }
184
+ export function handleVitekTestGenerate(ctx, input) {
185
+ const dryRun = input.dryRun !== false;
186
+ const apply = input.apply === true;
187
+ const relRoute = input.routeFilePath.replace(/\\/g, '/').replace(/^\/+/, '');
188
+ const absRoute = resolvePathUnderRoot(ctx.root, relRoute);
189
+ if (!absRoute || !assertUnderApiDir(ctx.root, ctx.apiDir, absRoute)) {
190
+ return errResult('Invalid route file path.');
191
+ }
192
+ if (!fs.existsSync(absRoute)) {
193
+ return errResult('Route file not found.');
194
+ }
195
+ const apiDirAbs = path.resolve(ctx.root, ctx.apiDir);
196
+ const parsed = parseRouteFile(absRoute, apiDirAbs);
197
+ if (!parsed) {
198
+ return errResult('Path is not a Vitek route file.');
199
+ }
200
+ const testRel = relRoute.replace(/\.(ts|js)$/, `.test.ts`);
201
+ const testAbs = resolvePathUnderRoot(ctx.root, testRel);
202
+ if (!testAbs || !assertUnderApiDir(ctx.root, ctx.apiDir, testAbs)) {
203
+ return errResult('Invalid test output path.');
204
+ }
205
+ const content = buildRouteTestFileContent({
206
+ method: parsed.method,
207
+ pattern: parsed.pattern,
208
+ apiBasePath: ctx.apiBasePath,
209
+ baseUrl: ctx.baseUrl,
210
+ });
211
+ const before = fs.existsSync(testAbs) ? fs.readFileSync(testAbs, 'utf-8') : null;
212
+ const diff = unifiedFileDiff(testRel, before, content);
213
+ const risk = ['Ensure dev server is running when executing tests that call fetch.'];
214
+ const resolution = resolveApplyMode(ctx.root, apply, dryRun);
215
+ if (resolution.rejectReason) {
216
+ return okResult({
217
+ dryRun: true,
218
+ diff,
219
+ risk,
220
+ next: resolution.rejectReason,
221
+ rejectReason: resolution.rejectReason,
222
+ filePath: testRel,
223
+ });
224
+ }
225
+ if (!resolution.writeAllowed) {
226
+ return okResult({
227
+ dryRun: true,
228
+ diff,
229
+ risk,
230
+ next: 'Call again with apply: true and dryRun: false to write the test file.',
231
+ filePath: testRel,
232
+ });
233
+ }
234
+ fs.mkdirSync(path.dirname(testAbs), { recursive: true });
235
+ fs.writeFileSync(testAbs, content, 'utf-8');
236
+ return okResult({
237
+ dryRun: false,
238
+ written: true,
239
+ diff,
240
+ risk,
241
+ next: 'Test file written.',
242
+ filePath: testRel,
243
+ });
244
+ }
245
+ export function handleVitekOpenapiSync(ctx, input) {
246
+ const dryRun = input.dryRun !== false;
247
+ const apply = input.apply === true;
248
+ const rel = input.filePath.replace(/\\/g, '/').replace(/^\/+/, '');
249
+ const abs = resolvePathUnderRoot(ctx.root, rel);
250
+ if (!abs || !assertUnderApiDir(ctx.root, ctx.apiDir, abs)) {
251
+ return errResult('Invalid path.');
252
+ }
253
+ if (!fs.existsSync(abs)) {
254
+ return errResult('File not found.');
255
+ }
256
+ const manifest = getManifest(ctx.root, ctx.apiDir);
257
+ const route = manifest.routes.find((r) => r.file === rel || r.file.replace(/\\/g, '/') === rel);
258
+ if (!route) {
259
+ return errResult('No manifest route matches this file; save the route and regenerate manifest if needed.');
260
+ }
261
+ const summary = `${route.method.toUpperCase()} ${route.pattern || '/'}`;
262
+ const before = fs.readFileSync(abs, 'utf-8');
263
+ const after = applyOpenApiSummaryToFileContent(before, summary);
264
+ const diff = unifiedFileDiff(rel, before, after);
265
+ if (diff === '') {
266
+ return okResult({
267
+ dryRun: true,
268
+ diff: '',
269
+ risk: [],
270
+ next: 'JSDoc @summary already matches suggested value.',
271
+ filePath: rel,
272
+ });
273
+ }
274
+ const risk = ['Updates JSDoc only; OpenAPI is regenerated from files on dev/build.'];
275
+ const resolution = resolveApplyMode(ctx.root, apply, dryRun);
276
+ if (resolution.rejectReason) {
277
+ return okResult({
278
+ dryRun: true,
279
+ diff,
280
+ risk,
281
+ next: resolution.rejectReason,
282
+ rejectReason: resolution.rejectReason,
283
+ filePath: rel,
284
+ });
285
+ }
286
+ if (!resolution.writeAllowed) {
287
+ return okResult({
288
+ dryRun: true,
289
+ diff,
290
+ risk,
291
+ next: 'Call again with apply: true and dryRun: false to write.',
292
+ filePath: rel,
293
+ });
294
+ }
295
+ fs.writeFileSync(abs, after, 'utf-8');
296
+ return okResult({
297
+ dryRun: false,
298
+ written: true,
299
+ diff,
300
+ risk,
301
+ next: 'JSDoc @summary updated.',
302
+ filePath: rel,
303
+ });
304
+ }
@@ -0,0 +1,3 @@
1
+ import type { VitekManifest } from '../../core/introspection/manifest.js';
2
+ export declare function computeRouteRisks(manifest: VitekManifest, routePattern: string, method: string): string[];
3
+ //# sourceMappingURL=risks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"risks.d.ts","sourceRoot":"","sources":["../../../src/mcp/write/risks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AAO1E,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAiBzG"}
@@ -0,0 +1,20 @@
1
+ function patternPrefix(pattern) {
2
+ const idx = pattern.indexOf('/');
3
+ return idx === -1 ? pattern : pattern.slice(0, idx);
4
+ }
5
+ export function computeRouteRisks(manifest, routePattern, method) {
6
+ const risks = [];
7
+ const prefix = patternPrefix(routePattern);
8
+ const scoped = manifest.middlewares.filter((m) => m.basePattern !== '' && (routePattern === m.basePattern || routePattern.startsWith(m.basePattern + '/')));
9
+ if (scoped.length === 0 && prefix !== '' && manifest.middlewares.every((m) => m.basePattern === '')) {
10
+ risks.push(`No route-scoped middleware under "${prefix}"; only global middleware applies.`);
11
+ }
12
+ const globalMw = manifest.middlewares.filter((m) => m.basePattern === '').length;
13
+ if (globalMw === 0) {
14
+ risks.push('No global middleware registered.');
15
+ }
16
+ if (method === 'post' || method === 'put' || method === 'patch') {
17
+ risks.push('Validate request body with validateBody / validation rules where appropriate.');
18
+ }
19
+ return risks;
20
+ }
@@ -0,0 +1,5 @@
1
+ export declare function buildRouteFileContent(pathInput: string, method: string, ext: 'ts' | 'js'): {
2
+ relativeFilePath: string;
3
+ content: string;
4
+ };
5
+ //# sourceMappingURL=route-snippet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-snippet.d.ts","sourceRoot":"","sources":["../../../src/mcp/write/route-snippet.ts"],"names":[],"mappings":"AAUA,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,IAAI,GAAG,IAAI,GACf;IAAE,gBAAgB,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAwC/C"}
@@ -0,0 +1,46 @@
1
+ const HTTP_METHODS = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options'];
2
+ function pathToFileSegment(segment) {
3
+ if (/^\[\.\.\.[^\]]+\]$/.test(segment))
4
+ return segment;
5
+ if (/^\[[^\]]+\]$/.test(segment))
6
+ return segment;
7
+ if (segment.startsWith('*'))
8
+ return `[...${segment.slice(1)}]`;
9
+ if (segment.startsWith(':'))
10
+ return `[${segment.slice(1)}]`;
11
+ return segment;
12
+ }
13
+ export function buildRouteFileContent(pathInput, method, ext) {
14
+ const methodLower = method.toLowerCase();
15
+ if (!HTTP_METHODS.includes(methodLower)) {
16
+ throw new Error(`Invalid method: ${method}. Use one of ${HTTP_METHODS.join(', ')}`);
17
+ }
18
+ const normalized = pathInput.replace(/\\/g, '/').replace(/^\/+|\/+$/g, '');
19
+ const segments = normalized ? normalized.split('/').filter(Boolean) : [];
20
+ const fileSegments = segments.map((s) => pathToFileSegment(s));
21
+ const pathPart = fileSegments.length ? fileSegments.join('/') : 'index';
22
+ const fileName = `${pathPart}.${methodLower}.${ext}`;
23
+ const relativeFilePath = fileName.replace(/\/+/g, '/');
24
+ const paramNames = segments
25
+ .filter((s) => s.startsWith(':') ||
26
+ s.startsWith('*') ||
27
+ /^\[\.\.\.[^\]]+\]$/.test(s) ||
28
+ /^\[[^\]]+\]$/.test(s))
29
+ .map((s) => {
30
+ if (s.startsWith('*'))
31
+ return s.slice(1);
32
+ if (s.startsWith(':'))
33
+ return s.slice(1);
34
+ const m = s.match(/^\[\.\.\.?([^\]]+)\]$/);
35
+ return m ? m[1] : s;
36
+ });
37
+ const typeImport = ext === 'ts' ? 'import type { VitekContext } from "vitek-plugin";\n\n' : '';
38
+ const paramsSnippet = paramNames.length > 0
39
+ ? ` const { params } = context;\n return { ${paramNames.map((p) => `${p}: params.${p}`).join(', ')} };`
40
+ : ' return { message: "ok" };';
41
+ const content = typeImport +
42
+ `export default async function handler(context${ext === 'ts' ? ': VitekContext' : ''}) {\n` +
43
+ `${paramsSnippet}\n` +
44
+ `}\n`;
45
+ return { relativeFilePath, content };
46
+ }
@@ -0,0 +1,3 @@
1
+ export declare function resolvePathUnderRoot(root: string, relativePath: string): string | null;
2
+ export declare function assertUnderApiDir(root: string, apiDir: string, absolutePath: string): boolean;
3
+ //# sourceMappingURL=safe-path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safe-path.d.ts","sourceRoot":"","sources":["../../../src/mcp/write/safe-path.ts"],"names":[],"mappings":"AAEA,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAStF;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAI7F"}
@@ -0,0 +1,16 @@
1
+ import * as path from 'path';
2
+ export function resolvePathUnderRoot(root, relativePath) {
3
+ const normalized = relativePath.replace(/\\/g, '/').replace(/^\/+/, '');
4
+ const resolved = path.resolve(root, normalized);
5
+ const rootResolved = path.resolve(root);
6
+ const prefix = rootResolved.endsWith(path.sep) ? rootResolved : rootResolved + path.sep;
7
+ if (resolved !== rootResolved && !resolved.startsWith(prefix)) {
8
+ return null;
9
+ }
10
+ return resolved;
11
+ }
12
+ export function assertUnderApiDir(root, apiDir, absolutePath) {
13
+ const apiRoot = path.resolve(root, apiDir);
14
+ const prefix = apiRoot.endsWith(path.sep) ? apiRoot : apiRoot + path.sep;
15
+ return absolutePath === apiRoot || absolutePath.startsWith(prefix);
16
+ }
@@ -0,0 +1,8 @@
1
+ import type { HttpMethod } from '../../shared/constants.js';
2
+ export declare function buildRouteTestFileContent(opts: {
3
+ method: HttpMethod;
4
+ pattern: string;
5
+ apiBasePath: string;
6
+ baseUrl: string;
7
+ }): string;
8
+ //# sourceMappingURL=test-file-content.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-file-content.d.ts","sourceRoot":"","sources":["../../../src/mcp/write/test-file-content.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAe5D,wBAAgB,yBAAyB,CAAC,IAAI,EAAE;IAC9C,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,MAAM,CAmBT"}
@@ -0,0 +1,31 @@
1
+ function patternToPathSuffix(pattern) {
2
+ if (pattern === '')
3
+ return '';
4
+ return pattern
5
+ .split('/')
6
+ .filter(Boolean)
7
+ .map((seg) => {
8
+ if (seg.startsWith(':'))
9
+ return '1';
10
+ if (seg.startsWith('*'))
11
+ return 'x';
12
+ return seg;
13
+ })
14
+ .join('/');
15
+ }
16
+ export function buildRouteTestFileContent(opts) {
17
+ const suffix = patternToPathSuffix(opts.pattern);
18
+ const pathPart = suffix ? `${suffix}` : '';
19
+ const urlLine = opts.pattern === ''
20
+ ? `const url = \`${opts.baseUrl.replace(/\/$/, '')}${opts.apiBasePath}\`;`
21
+ : `const url = \`${opts.baseUrl.replace(/\/$/, '')}${opts.apiBasePath}/${pathPart}\`;`;
22
+ return (`import { describe, it, expect } from "vitest";\n` +
23
+ `${urlLine}\n\n` +
24
+ `describe("${opts.method.toUpperCase()} ${opts.apiBasePath}/${opts.pattern || '(index)'}", () => {\n` +
25
+ ` it("responds", async () => {\n` +
26
+ ` const res = await fetch(url, { method: "${opts.method.toUpperCase()}" });\n` +
27
+ ` expect(res.status).toBeGreaterThanOrEqual(200);\n` +
28
+ ` expect(res.status).toBeLessThan(600);\n` +
29
+ ` });\n` +
30
+ `});\n`);
31
+ }
@@ -0,0 +1,2 @@
1
+ export declare function unifiedFileDiff(relativePath: string, before: string | null, after: string): string;
2
+ //# sourceMappingURL=unified-diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unified-diff.d.ts","sourceRoot":"","sources":["../../../src/mcp/write/unified-diff.ts"],"names":[],"mappings":"AAAA,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAoBlG"}
@@ -0,0 +1,19 @@
1
+ export function unifiedFileDiff(relativePath, before, after) {
2
+ const a = before ?? '';
3
+ const b = after;
4
+ if (a === b) {
5
+ return '';
6
+ }
7
+ const header = `--- a/${relativePath}\n+++ b/${relativePath}\n`;
8
+ const al = a.split('\n');
9
+ const bl = b.split('\n');
10
+ if (before == null) {
11
+ return header + bl.map((l) => `+${l}`).join('\n') + (bl.length ? '\n' : '');
12
+ }
13
+ return (header +
14
+ `@@ -1,${al.length} +1,${bl.length} @@\n` +
15
+ al.map((l) => `-${l}`).join('\n') +
16
+ '\n' +
17
+ bl.map((l) => `+${l}`).join('\n') +
18
+ '\n');
19
+ }
@@ -0,0 +1,2 @@
1
+ export declare function injectValidationScaffold(content: string): string;
2
+ //# sourceMappingURL=validation-scaffold.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation-scaffold.d.ts","sourceRoot":"","sources":["../../../src/mcp/write/validation-scaffold.ts"],"names":[],"mappings":"AAAA,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CA4BhE"}
@@ -0,0 +1,31 @@
1
+ export function injectValidationScaffold(content) {
2
+ if (/validateBody\s*\(/.test(content)) {
3
+ return content;
4
+ }
5
+ let next = content;
6
+ const importStmt = 'import { validateBody } from "vitek-plugin/validation";\n';
7
+ if (!/from\s+["']vitek-plugin\/validation["']/.test(next)) {
8
+ const lines = next.split('\n');
9
+ let lastImport = -1;
10
+ for (let i = 0; i < lines.length; i++) {
11
+ if (/^\s*import\s/.test(lines[i]))
12
+ lastImport = i;
13
+ }
14
+ if (lastImport >= 0) {
15
+ lines.splice(lastImport + 1, 0, importStmt.trimEnd());
16
+ next = lines.join('\n');
17
+ }
18
+ else {
19
+ next = importStmt + next;
20
+ }
21
+ }
22
+ const asyncFn = /(export default async function handler\([^)]*\)\s*\{)/;
23
+ const syncFn = /(export default function handler\([^)]*\)\s*\{)/;
24
+ if (asyncFn.test(next)) {
25
+ return next.replace(asyncFn, `$1\n validateBody(context.body, {});`);
26
+ }
27
+ if (syncFn.test(next)) {
28
+ return next.replace(syncFn, `$1\n validateBody(context.body, {});`);
29
+ }
30
+ return next;
31
+ }
@@ -0,0 +1,3 @@
1
+ export declare const CONFIGURATION_URI = "vitek://docs/configuration";
2
+ export declare const CONFIGURATION_CONTENT = "# Vitek \u2013 Configuration\n\nPass options to `vitek()` in Vite config.\n\n## Main options\n\n- `apiDir` (default 'src/api') \u2013 directory for route files\n- `srcDir` (default 'src') \u2013 for import rewriting\n- `apiBasePath` (default '/api') \u2013 URL prefix\n- `buildApi` (default true) \u2013 build API bundle for production; false = dev-only\n- `enableValidation` (default false) \u2013 automatic validation\n- `openApi` \u2013 true or object for OpenAPI/AsyncAPI docs\n- `sockets` \u2013 true (default), false, or { path: '/ws' }\n- `logging` \u2013 { level?, enableRequestLogging?, enableRouteLogging? }\n- `onGenerationError` \u2013 callback when type/OpenAPI generation fails\n- `plugins` \u2013 VitekPlugin[]\n- `alias` \u2013 resolve aliases (e.g. { '@lib': 'src/lib' })\n- `cors` \u2013 true or CorsOptions (origin, methods, allowedHeaders)\n- `trustProxy` \u2013 trust X-Forwarded-* (sets context.clientIp)\n- `onError` \u2013 (err, req, res) for non-HttpError\n- `maxBodySize` \u2013 max body bytes (413 when exceeded)\n\nProduction: export `onError`, `maxBodySize`, etc. from `dist/vitek.config.mjs` when using vitek-serve.\n";
3
+ //# sourceMappingURL=configuration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configuration.d.ts","sourceRoot":"","sources":["../../../src/mcp-docs-server/resources/configuration.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,+BAA+B,CAAC;AAE9D,eAAO,MAAM,qBAAqB,goCAuBjC,CAAC"}
@@ -0,0 +1,25 @@
1
+ export const CONFIGURATION_URI = 'vitek://docs/configuration';
2
+ export const CONFIGURATION_CONTENT = `# Vitek – Configuration
3
+
4
+ Pass options to \`vitek()\` in Vite config.
5
+
6
+ ## Main options
7
+
8
+ - \`apiDir\` (default 'src/api') – directory for route files
9
+ - \`srcDir\` (default 'src') – for import rewriting
10
+ - \`apiBasePath\` (default '/api') – URL prefix
11
+ - \`buildApi\` (default true) – build API bundle for production; false = dev-only
12
+ - \`enableValidation\` (default false) – automatic validation
13
+ - \`openApi\` – true or object for OpenAPI/AsyncAPI docs
14
+ - \`sockets\` – true (default), false, or { path: '/ws' }
15
+ - \`logging\` – { level?, enableRequestLogging?, enableRouteLogging? }
16
+ - \`onGenerationError\` – callback when type/OpenAPI generation fails
17
+ - \`plugins\` – VitekPlugin[]
18
+ - \`alias\` – resolve aliases (e.g. { '@lib': 'src/lib' })
19
+ - \`cors\` – true or CorsOptions (origin, methods, allowedHeaders)
20
+ - \`trustProxy\` – trust X-Forwarded-* (sets context.clientIp)
21
+ - \`onError\` – (err, req, res) for non-HttpError
22
+ - \`maxBodySize\` – max body bytes (413 when exceeded)
23
+
24
+ Production: export \`onError\`, \`maxBodySize\`, etc. from \`dist/vitek.config.mjs\` when using vitek-serve.
25
+ `;
@@ -0,0 +1,3 @@
1
+ export declare const CONTEXT_URI = "vitek://docs/context";
2
+ export declare const CONTEXT_CONTENT = "# Vitek \u2013 Context and request\n\n## VitekContext\n\nHandlers receive a `VitekContext` with:\n\n- `url`: full request URL\n- `method`: HTTP method (lowercase)\n- `path`: path relative to API base (e.g. `/users/1`)\n- `query`: parsed query string (`Record<string, string | string[]>`)\n- `params`: route params (e.g. `{ id: \"1\" }` for `/users/[id]`)\n- `headers`: request headers (`Record<string, string>`)\n- `body`: parsed body (when applicable)\n- `clientIp`: client IP (when `trustProxy: true`)\n- `sockets`: `SocketEmitter` for broadcasting to WebSocket clients (when available)\n\n## VitekRequest\n\nMinimal request shape used internally: `url`, `method`, `headers`, `body?`.\n\n## Usage in handlers\n\n```typescript\nimport type { VitekContext } from \"vitek-plugin\";\n\nexport default async function handler(context: VitekContext) {\n const { params, query, body, headers } = context;\n const id = params.id;\n const limit = query.limit ? Number(query.limit) : 10;\n return { id, limit, body };\n}\n```\n";
3
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/mcp-docs-server/resources/context.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,yBAAyB,CAAC;AAElD,eAAO,MAAM,eAAe,mgCAgC3B,CAAC"}
@@ -0,0 +1,34 @@
1
+ export const CONTEXT_URI = 'vitek://docs/context';
2
+ export const CONTEXT_CONTENT = `# Vitek – Context and request
3
+
4
+ ## VitekContext
5
+
6
+ Handlers receive a \`VitekContext\` with:
7
+
8
+ - \`url\`: full request URL
9
+ - \`method\`: HTTP method (lowercase)
10
+ - \`path\`: path relative to API base (e.g. \`/users/1\`)
11
+ - \`query\`: parsed query string (\`Record<string, string | string[]>\`)
12
+ - \`params\`: route params (e.g. \`{ id: "1" }\` for \`/users/[id]\`)
13
+ - \`headers\`: request headers (\`Record<string, string>\`)
14
+ - \`body\`: parsed body (when applicable)
15
+ - \`clientIp\`: client IP (when \`trustProxy: true\`)
16
+ - \`sockets\`: \`SocketEmitter\` for broadcasting to WebSocket clients (when available)
17
+
18
+ ## VitekRequest
19
+
20
+ Minimal request shape used internally: \`url\`, \`method\`, \`headers\`, \`body?\`.
21
+
22
+ ## Usage in handlers
23
+
24
+ \`\`\`typescript
25
+ import type { VitekContext } from "vitek-plugin";
26
+
27
+ export default async function handler(context: VitekContext) {
28
+ const { params, query, body, headers } = context;
29
+ const id = params.id;
30
+ const limit = query.limit ? Number(query.limit) : 10;
31
+ return { id, limit, body };
32
+ }
33
+ \`\`\`
34
+ `;
@@ -0,0 +1,3 @@
1
+ export declare const ERRORS_URI = "vitek://docs/errors";
2
+ export declare const ERRORS_CONTENT = "# Vitek \u2013 Error handling\n\nHTTP error classes map to status codes and JSON error response.\n\n## Error classes (from vitek-plugin)\n\n- BadRequestError \u2192 400\n- UnauthorizedError \u2192 401\n- ForbiddenError \u2192 403\n- NotFoundError \u2192 404\n- ConflictError \u2192 409\n- ValidationError \u2192 422 (supports field errors object: { email: [\"Invalid\"], age: [\"Must be 18+\"] })\n- TooManyRequestsError \u2192 429\n- InternalServerError \u2192 500\n\n```typescript\nimport { NotFoundError, ValidationError } from \"vitek-plugin\";\n\nif (!resource) throw new NotFoundError(\"Resource not found\");\nthrow new ValidationError(\"Invalid\", { email: [\"Invalid format\"] });\n```\n\n## onError (non-HttpError)\n\nFor uncaught exceptions or non-HttpError, set `onError(err, req, res)` in plugin options. Send response and call `res.end()`; otherwise default 500 JSON is sent. In production with vitek-serve, export `onError` from `dist/vitek.config.mjs`.\n";
3
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/mcp-docs-server/resources/errors.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,wBAAwB,CAAC;AAEhD,eAAO,MAAM,cAAc,+8BAyB1B,CAAC"}
@@ -0,0 +1,27 @@
1
+ export const ERRORS_URI = 'vitek://docs/errors';
2
+ export const ERRORS_CONTENT = `# Vitek – Error handling
3
+
4
+ HTTP error classes map to status codes and JSON error response.
5
+
6
+ ## Error classes (from vitek-plugin)
7
+
8
+ - BadRequestError → 400
9
+ - UnauthorizedError → 401
10
+ - ForbiddenError → 403
11
+ - NotFoundError → 404
12
+ - ConflictError → 409
13
+ - ValidationError → 422 (supports field errors object: { email: ["Invalid"], age: ["Must be 18+"] })
14
+ - TooManyRequestsError → 429
15
+ - InternalServerError → 500
16
+
17
+ \`\`\`typescript
18
+ import { NotFoundError, ValidationError } from "vitek-plugin";
19
+
20
+ if (!resource) throw new NotFoundError("Resource not found");
21
+ throw new ValidationError("Invalid", { email: ["Invalid format"] });
22
+ \`\`\`
23
+
24
+ ## onError (non-HttpError)
25
+
26
+ For uncaught exceptions or non-HttpError, set \`onError(err, req, res)\` in plugin options. Send response and call \`res.end()\`; otherwise default 500 JSON is sent. In production with vitek-serve, export \`onError\` from \`dist/vitek.config.mjs\`.
27
+ `;
@@ -0,0 +1,3 @@
1
+ export declare const INTROSPECTION_URI = "vitek://docs/introspection";
2
+ export declare const INTROSPECTION_CONTENT = "# Vitek \u2013 Introspection API\n\nProgrammatic API to inspect routes, middlewares, and sockets. Manifest file generated at build.\n\n## Functions (from vitek-plugin)\n\n- `getManifest(root, apiDir)` \u2013 { routes, middlewares, sockets }\n- `getRoutes(root, apiDir)` \u2013 ParsedRoute[] ({ method, pattern, params, file })\n- `getSockets(root, apiDir)` \u2013 ParsedSocket[] ({ pattern, params, file })\n- `writeManifest(root, apiDir, outDir)` \u2013 writes vitek-manifest.json\n\n## Manifest format (vitek-manifest.json)\n\n```json\n{\n \"routes\": [{ \"method\": \"get\", \"pattern\": \"users/:id\", \"params\": [\"id\"], \"file\": \"src/api/users/[id].get.ts\" }],\n \"middlewares\": [{ \"basePattern\": \"\", \"path\": \"src/api/middleware.ts\" }],\n \"sockets\": [{ \"pattern\": \"chat\", \"params\": [], \"file\": \"src/api/chat.socket.ts\" }]\n}\n```\n\nPaths relative to project root. Use for CLIs, IDEs, CI/CD, or custom docs.\n";
3
+ //# sourceMappingURL=introspection.d.ts.map