prisma-generator-express 1.66.0 → 1.68.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.
Files changed (130) hide show
  1. package/README.md +188 -3432
  2. package/dist/client/encodeQueryParams.js +3 -1
  3. package/dist/client/encodeQueryParams.js.map +1 -1
  4. package/dist/copy/misc.d.ts +1 -0
  5. package/dist/copy/misc.js +14 -0
  6. package/dist/copy/misc.js.map +1 -1
  7. package/dist/copy/operationDefinitions.d.ts +4 -1
  8. package/dist/copy/operationDefinitions.js +133 -9
  9. package/dist/copy/operationDefinitions.js.map +1 -1
  10. package/dist/generators/generateFastifyHandler.d.ts +2 -2
  11. package/dist/generators/generateFastifyHandler.js +68 -12
  12. package/dist/generators/generateFastifyHandler.js.map +1 -1
  13. package/dist/generators/generateHonoHandler.d.ts +2 -2
  14. package/dist/generators/generateHonoHandler.js +53 -6
  15. package/dist/generators/generateHonoHandler.js.map +1 -1
  16. package/dist/generators/generateHonoOpenApi.d.ts +13 -0
  17. package/dist/generators/generateHonoOpenApi.js +70 -0
  18. package/dist/generators/generateHonoOpenApi.js.map +1 -0
  19. package/dist/generators/generateImportPrismaStatement.d.ts +1 -0
  20. package/dist/generators/generateImportPrismaStatement.js +6 -0
  21. package/dist/generators/generateImportPrismaStatement.js.map +1 -1
  22. package/dist/generators/generateMcpApp.d.ts +10 -0
  23. package/dist/generators/generateMcpApp.js +113 -0
  24. package/dist/generators/generateMcpApp.js.map +1 -0
  25. package/dist/generators/generateModelMcp.d.ts +9 -0
  26. package/dist/generators/generateModelMcp.js +145 -0
  27. package/dist/generators/generateModelMcp.js.map +1 -0
  28. package/dist/generators/generateModelMetadata.js +29 -15
  29. package/dist/generators/generateModelMetadata.js.map +1 -1
  30. package/dist/generators/generateOperationCore.d.ts +3 -3
  31. package/dist/generators/generateOperationCore.js +51 -16
  32. package/dist/generators/generateOperationCore.js.map +1 -1
  33. package/dist/generators/generateRelationMeta.js +2 -2
  34. package/dist/generators/generateRelationMeta.js.map +1 -1
  35. package/dist/generators/generateRouteConfigType.d.ts +2 -2
  36. package/dist/generators/generateRouteConfigType.js +29 -11
  37. package/dist/generators/generateRouteConfigType.js.map +1 -1
  38. package/dist/generators/generateRouter.d.ts +7 -4
  39. package/dist/generators/generateRouter.js +164 -65
  40. package/dist/generators/generateRouter.js.map +1 -1
  41. package/dist/generators/generateRouterFastify.d.ts +7 -4
  42. package/dist/generators/generateRouterFastify.js +106 -86
  43. package/dist/generators/generateRouterFastify.js.map +1 -1
  44. package/dist/generators/generateRouterHono.d.ts +7 -4
  45. package/dist/generators/generateRouterHono.js +59 -414
  46. package/dist/generators/generateRouterHono.js.map +1 -1
  47. package/dist/generators/generateRouterPartsHono.d.ts +14 -0
  48. package/dist/generators/generateRouterPartsHono.js +180 -0
  49. package/dist/generators/generateRouterPartsHono.js.map +1 -0
  50. package/dist/generators/generateUnifiedDocs.d.ts +1 -1
  51. package/dist/generators/generateUnifiedDocs.js +15 -8
  52. package/dist/generators/generateUnifiedDocs.js.map +1 -1
  53. package/dist/generators/generateUnifiedHandler.d.ts +2 -2
  54. package/dist/generators/generateUnifiedHandler.js +42 -18
  55. package/dist/generators/generateUnifiedHandler.js.map +1 -1
  56. package/dist/guardOptions.js +12 -7
  57. package/dist/guardOptions.js.map +1 -1
  58. package/dist/index.d.ts +3 -1
  59. package/dist/index.js +123 -4
  60. package/dist/index.js.map +1 -1
  61. package/dist/utils/copyFiles.d.ts +1 -1
  62. package/dist/utils/copyFiles.js +42 -7
  63. package/dist/utils/copyFiles.js.map +1 -1
  64. package/dist/utils/importExt.d.ts +1 -1
  65. package/dist/utils/mcpGate.d.ts +10 -0
  66. package/dist/utils/mcpGate.js +118 -0
  67. package/dist/utils/mcpGate.js.map +1 -0
  68. package/dist/utils/pathCasing.d.ts +4 -0
  69. package/dist/utils/pathCasing.js +40 -0
  70. package/dist/utils/pathCasing.js.map +1 -0
  71. package/dist/utils/resolveImportStyle.js +13 -5
  72. package/dist/utils/resolveImportStyle.js.map +1 -1
  73. package/dist/utils/writeFileSafely.js +6 -0
  74. package/dist/utils/writeFileSafely.js.map +1 -1
  75. package/package.json +22 -5
  76. package/src/bin.ts +1 -1
  77. package/src/client/encodeQueryParams.ts +39 -35
  78. package/src/constants.ts +1 -1
  79. package/src/copy/autoIncludePlanner.ts +93 -27
  80. package/src/copy/autoIncludePlannerGuarded.ts +171 -48
  81. package/src/copy/autoIncludeRuntimeGuarded.ts +25 -7
  82. package/src/copy/buildModelOpenApi.ts +229 -176
  83. package/src/copy/concurrency.ts +10 -8
  84. package/src/copy/docsRenderer.ts +14 -15
  85. package/src/copy/errorMapper.ts +68 -19
  86. package/src/copy/guardHelpers.ts +30 -9
  87. package/src/copy/materializedCount.ts +17 -5
  88. package/src/copy/mcpRuntime.ts +1017 -0
  89. package/src/copy/misc.ts +88 -68
  90. package/src/copy/ndjson.ts +72 -0
  91. package/src/copy/operationDefinitions.ts +177 -25
  92. package/src/copy/operationPipeline.ts +267 -0
  93. package/src/copy/operationRuntime.ts +124 -26
  94. package/src/copy/operationSchemas.ts +2773 -0
  95. package/src/copy/pagination.ts +35 -13
  96. package/src/copy/parseQueryParams.ts +47 -48
  97. package/src/copy/projectionDefaults.ts +6 -4
  98. package/src/copy/routeConfig.express.ts +16 -4
  99. package/src/copy/routeConfig.fastify.ts +16 -2
  100. package/src/copy/routeConfig.hono.ts +46 -14
  101. package/src/copy/routeConfig.ts +175 -40
  102. package/src/copy/routerParts.ts +524 -0
  103. package/src/copy/scalarTypes.ts +7 -2
  104. package/src/copy/sse.ts +72 -19
  105. package/src/generators/generateFastifyHandler.ts +77 -20
  106. package/src/generators/generateHonoHandler.ts +62 -14
  107. package/src/generators/generateHonoOpenApi.ts +93 -0
  108. package/src/generators/generateImportPrismaStatement.ts +93 -81
  109. package/src/generators/generateMcpApp.ts +133 -0
  110. package/src/generators/generateModelMcp.ts +208 -0
  111. package/src/generators/generateModelMetadata.ts +40 -22
  112. package/src/generators/generateOperationCore.ts +81 -33
  113. package/src/generators/generateRelationMeta.ts +23 -11
  114. package/src/generators/generateRouteConfigType.ts +39 -13
  115. package/src/generators/generateRouter.ts +171 -68
  116. package/src/generators/generateRouterFastify.ts +117 -89
  117. package/src/generators/generateRouterHono.ts +84 -464
  118. package/src/generators/generateRouterPartsHono.ts +220 -0
  119. package/src/generators/generateUnifiedDocs.ts +29 -8
  120. package/src/generators/generateUnifiedHandler.ts +47 -24
  121. package/src/generators/generateUnifiedScalarUI.ts +1 -1
  122. package/src/guardOptions.ts +105 -92
  123. package/src/index.ts +161 -6
  124. package/src/utils/copyFiles.ts +235 -168
  125. package/src/utils/importExt.ts +2 -2
  126. package/src/utils/mcpGate.ts +157 -0
  127. package/src/utils/pathCasing.ts +42 -0
  128. package/src/utils/resolveImportStyle.ts +37 -15
  129. package/src/utils/strings.ts +2 -2
  130. package/src/utils/writeFileSafely.ts +12 -2
package/src/index.ts CHANGED
@@ -15,7 +15,11 @@ export {
15
15
  HARDENED_GUARD_PROFILE,
16
16
  resolveGuardPolicy,
17
17
  } from './guardOptions'
18
- export type { GuardPolicy, GuardOptionMetadata, GuardResolutionOrder } from './guardOptions'
18
+ export type {
19
+ GuardPolicy,
20
+ GuardOptionMetadata,
21
+ GuardResolutionOrder,
22
+ } from './guardOptions'
19
23
 
20
24
  import {
21
25
  generatorHandler,
@@ -29,6 +33,10 @@ import { generateHonoHandler } from './generators/generateHonoHandler'
29
33
  import { generateRouterFunction } from './generators/generateRouter'
30
34
  import { generateFastifyRouterFunction } from './generators/generateRouterFastify'
31
35
  import { generateHonoRouterFunction } from './generators/generateRouterHono'
36
+ import { generateHonoRouterParts } from './generators/generateRouterPartsHono'
37
+ import { generateHonoOpenApiRoutes } from './generators/generateHonoOpenApi'
38
+ import { generateModelMcp } from './generators/generateModelMcp'
39
+ import { generateMcpApp, generateMcpMount } from './generators/generateMcpApp'
32
40
  import { generateScalarUIHandler } from './generators/generateUnifiedScalarUI'
33
41
  import { generateUnifiedDocs } from './generators/generateUnifiedDocs'
34
42
  import { generateQueryBuilderHelper } from './generators/generateQueryBuilderHelper'
@@ -40,11 +48,17 @@ import {
40
48
  import { generateModelMetadata } from './generators/generateModelMetadata'
41
49
  import {
42
50
  getRelativeClientPath,
51
+ getRelativeClientTypeImport,
43
52
  getGuardShapesImport,
44
53
  } from './generators/generateImportPrismaStatement'
45
54
  import { writeFileSafely } from './utils/writeFileSafely'
55
+ import {
56
+ assertMcpGuardCompatibility,
57
+ assertMcpGuardVersion,
58
+ } from './utils/mcpGate'
46
59
  import { copyFiles } from './utils/copyFiles'
47
60
  import { resolveImportStyle, ImportStyle } from './utils/resolveImportStyle'
61
+ import { parsePathCase, modelPathSegment, PathCase } from './utils/pathCasing'
48
62
  import {
49
63
  GENERATOR_NAME,
50
64
  Target,
@@ -99,6 +113,32 @@ function getFindManyPaginatedMode(
99
113
  )
100
114
  }
101
115
 
116
+ function getPathCase(options: GeneratorOptions): PathCase {
117
+ return parsePathCase(
118
+ (options.generator.config as Record<string, unknown>).pathCase,
119
+ )
120
+ }
121
+
122
+ function getMcp(options: GeneratorOptions): boolean {
123
+ const raw = (options.generator.config as Record<string, unknown>).mcp
124
+ if (raw === undefined || raw === null) return false
125
+ if (typeof raw === 'boolean') return raw
126
+ if (typeof raw === 'string') {
127
+ const lower = raw.trim().toLowerCase()
128
+ if (lower === 'true' || lower === '1' || lower === 'yes') return true
129
+ if (
130
+ lower === 'false' ||
131
+ lower === '0' ||
132
+ lower === 'no' ||
133
+ raw.trim() === ''
134
+ )
135
+ return false
136
+ }
137
+ throw new Error(
138
+ 'Invalid mcp option "' + String(raw) + '". Expected true or false.',
139
+ )
140
+ }
141
+
102
142
  function getDropGuard(options: GeneratorOptions): boolean {
103
143
  const raw = (options.generator.config as Record<string, unknown>).dropGuard
104
144
  if (raw === undefined || raw === null) return false
@@ -109,7 +149,8 @@ function getDropGuard(options: GeneratorOptions): boolean {
109
149
  const s = raw.trim()
110
150
  const lower = s.toLowerCase()
111
151
  if (lower === 'true' || lower === '1' || lower === 'yes') return true
112
- if (lower === 'false' || lower === '0' || lower === 'no' || s === '') return false
152
+ if (lower === 'false' || lower === '0' || lower === 'no' || s === '')
153
+ return false
113
154
  const envVal = process.env[s]
114
155
  if (envVal === undefined) return false
115
156
  const el = envVal.trim().toLowerCase()
@@ -136,10 +177,25 @@ generatorHandler({
136
177
  },
137
178
 
138
179
  async onGenerate(options: GeneratorOptions) {
180
+ await runGenerate(options)
181
+ },
182
+ })
183
+
184
+ /**
185
+ * The full generation path, exported so tests exercise what `prisma generate`
186
+ * runs — including the mcp/dropGuard gate — instead of re-implementing pieces.
187
+ */
188
+ export async function runGenerate(options: GeneratorOptions): Promise<void> {
189
+ {
139
190
  const target = getTarget(options)
140
191
  const writeStrategy = getWriteStrategy(options)
141
192
  const findManyPaginatedMode = getFindManyPaginatedMode(options)
142
193
  const dropGuard = getDropGuard(options)
194
+ const mcp = getMcp(options)
195
+ const pathCase = getPathCase(options)
196
+
197
+ assertMcpGuardCompatibility(mcp, dropGuard)
198
+ assertMcpGuardVersion(mcp, options.schemaPath)
143
199
 
144
200
  const manifestDefaultAbs = path.resolve(
145
201
  __dirname,
@@ -160,11 +216,13 @@ generatorHandler({
160
216
  const importStyle = resolveImportStyle(options)
161
217
 
162
218
  console.log(`\n═══ Prisma Generator (${target.toUpperCase()}) ═══`)
219
+ if (mcp) console.log(` MCP: enabled (reads + opt-in writes)`)
163
220
  console.log(` Target: ${target}`)
164
221
  console.log(` Output: ${options.generator.output?.value}`)
165
222
  console.log(` Import style: ${importStyle}`)
166
223
  console.log(` Write strategy: ${writeStrategy}`)
167
224
  console.log(` findManyPaginated mode: ${findManyPaginatedMode}`)
225
+ console.log(` Path case: ${pathCase}`)
168
226
 
169
227
  if (dropGuard) {
170
228
  console.log('')
@@ -178,9 +236,10 @@ generatorHandler({
178
236
  validateClientGeneratorPresent(options)
179
237
  }
180
238
 
181
- await copyFiles(options, target, importStyle)
239
+ await copyFiles(options, target, importStyle, mcp)
182
240
 
183
241
  const modelNames: string[] = []
242
+ let guardArtifactsSeen = false
184
243
  const generateHandler: (opts: {
185
244
  model: DMMF.Model
186
245
  importStyle: ImportStyle
@@ -201,6 +260,7 @@ generatorHandler({
201
260
  modelNames.push(model.name)
202
261
 
203
262
  const guardShapesImport = getGuardShapesImport(options, model.name)
263
+ if (guardShapesImport) guardArtifactsSeen = true
204
264
 
205
265
  await writeFileSafely({
206
266
  content: generateModelMetadata({
@@ -238,28 +298,34 @@ generatorHandler({
238
298
  model: model as DMMF.Model,
239
299
  enums: options.dmmf.datamodel.enums as DMMF.DatamodelEnum[],
240
300
  guardShapesImport,
301
+ clientImport: getRelativeClientTypeImport(options, model.name),
241
302
  importStyle,
242
303
  writeStrategy,
243
304
  findManyPaginatedMode,
244
305
  dropGuard,
306
+ pathCase,
245
307
  })
246
308
  : target === 'hono'
247
309
  ? generateHonoRouterFunction({
248
310
  model: model as DMMF.Model,
249
311
  enums: options.dmmf.datamodel.enums as DMMF.DatamodelEnum[],
250
312
  guardShapesImport,
313
+ clientImport: getRelativeClientTypeImport(options, model.name),
251
314
  importStyle,
252
315
  writeStrategy,
253
316
  dropGuard,
317
+ pathCase,
254
318
  })
255
319
  : generateRouterFunction({
256
320
  model: model as DMMF.Model,
257
321
  enums: options.dmmf.datamodel.enums as DMMF.DatamodelEnum[],
258
322
  guardShapesImport,
323
+ clientImport: getRelativeClientTypeImport(options, model.name),
259
324
  importStyle,
260
325
  writeStrategy,
261
326
  findManyPaginatedMode,
262
327
  dropGuard,
328
+ pathCase,
263
329
  })
264
330
 
265
331
  await writeFileSafely({
@@ -269,6 +335,38 @@ generatorHandler({
269
335
  operation: 'Router',
270
336
  })
271
337
 
338
+ if (target === 'hono') {
339
+ await writeFileSafely({
340
+ content: generateHonoRouterParts({
341
+ model: model as DMMF.Model,
342
+ enums: options.dmmf.datamodel.enums as DMMF.DatamodelEnum[],
343
+ guardShapesImport,
344
+ clientImport: getRelativeClientTypeImport(options, model.name),
345
+ importStyle,
346
+ writeStrategy,
347
+ dropGuard,
348
+ pathCase,
349
+ }),
350
+ options,
351
+ model: model as DMMF.Model,
352
+ operation: 'RouterParts',
353
+ })
354
+ await writeFileSafely({
355
+ content: generateHonoOpenApiRoutes({
356
+ model: model as DMMF.Model,
357
+ enums: options.dmmf.datamodel.enums as DMMF.DatamodelEnum[],
358
+ guardShapesImport,
359
+ clientImport: getRelativeClientTypeImport(options, model.name),
360
+ importStyle,
361
+ writeStrategy,
362
+ pathCase,
363
+ }),
364
+ options,
365
+ model: model as DMMF.Model,
366
+ operation: 'OpenApiRoutes',
367
+ })
368
+ }
369
+
272
370
  await writeFileSafely({
273
371
  content: generateScalarUIHandler({
274
372
  model: model as DMMF.Model,
@@ -304,8 +402,38 @@ generatorHandler({
304
402
  })
305
403
  }
306
404
 
405
+ if (mcp) {
406
+ // after the loop: each tool factory narrows schemas with THIS model's
407
+ // metadata plus the metadata of every model it relates to
408
+ for (const model of allModels) {
409
+ if (!modelNames.includes(model.name)) continue
410
+ await writeFileSafely({
411
+ content: generateModelMcp({
412
+ model,
413
+ allModels: allModels.filter((m) =>
414
+ modelNames.includes(m.name),
415
+ ) as DMMF.Model[],
416
+ importStyle,
417
+ writeStrategy,
418
+ }),
419
+ options,
420
+ model: model as DMMF.Model,
421
+ operation: 'Mcp',
422
+ })
423
+ }
424
+ }
425
+
426
+ const pathSegments = Object.fromEntries(
427
+ modelNames.map((n) => [n, modelPathSegment(n, pathCase)]),
428
+ )
429
+
307
430
  await writeFileSafely({
308
- content: generateUnifiedDocs(modelNames, target, importStyle),
431
+ content: generateUnifiedDocs(
432
+ modelNames,
433
+ pathSegments,
434
+ target,
435
+ importStyle,
436
+ ),
309
437
  options,
310
438
  operation: 'combinedDocs',
311
439
  })
@@ -316,8 +444,35 @@ generatorHandler({
316
444
  operation: 'queryBuilder',
317
445
  })
318
446
 
447
+ if (mcp) {
448
+ await writeFileSafely({
449
+ content: generateMcpApp({
450
+ serverName: 'prisma-api',
451
+ serverVersion: require('../package.json').version,
452
+ importStyle,
453
+ }),
454
+ options,
455
+ operation: 'mcpApp',
456
+ })
457
+ await writeFileSafely({
458
+ content: generateMcpMount({ target, importStyle }),
459
+ options,
460
+ operation: 'mcpMount',
461
+ })
462
+ }
463
+
464
+ if (modelNames.length > 0 && !guardArtifactsSeen) {
465
+ console.log('')
466
+ console.log(
467
+ ' Note: prisma-guard not detected. Generated routes call Prisma directly',
468
+ )
469
+ console.log(
470
+ ' unless your route configs define guard shapes or variants.',
471
+ )
472
+ }
473
+
319
474
  console.log('\n═══ Generation Complete ═══')
320
475
  console.log(`✓ ${modelNames.length} models (${target})`)
321
476
  console.log('')
322
- },
323
- })
477
+ }
478
+ }