prisma-generator-express 1.53.0 → 1.55.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 (35) hide show
  1. package/README.md +123 -12
  2. package/dist/constants.d.ts +1 -0
  3. package/dist/generators/generateOperationCore.d.ts +2 -0
  4. package/dist/generators/generateOperationCore.js +30 -3
  5. package/dist/generators/generateOperationCore.js.map +1 -1
  6. package/dist/generators/generateRouter.d.ts +3 -1
  7. package/dist/generators/generateRouter.js +6 -4
  8. package/dist/generators/generateRouter.js.map +1 -1
  9. package/dist/generators/generateRouterFastify.d.ts +3 -1
  10. package/dist/generators/generateRouterFastify.js +6 -4
  11. package/dist/generators/generateRouterFastify.js.map +1 -1
  12. package/dist/generators/generateRouterHono.d.ts +3 -1
  13. package/dist/generators/generateRouterHono.js +6 -3
  14. package/dist/generators/generateRouterHono.js.map +1 -1
  15. package/dist/generators/generateUnifiedScalarUI.d.ts +2 -1
  16. package/dist/generators/generateUnifiedScalarUI.js +13 -10
  17. package/dist/generators/generateUnifiedScalarUI.js.map +1 -1
  18. package/dist/index.js +23 -3
  19. package/dist/index.js.map +1 -1
  20. package/package.json +1 -1
  21. package/src/constants.ts +3 -1
  22. package/src/copy/autoIncludeRuntime.ts +52 -24
  23. package/src/copy/buildModelOpenApi.ts +144 -23
  24. package/src/copy/docsRenderer.ts +121 -95
  25. package/src/copy/operationRuntime.ts +9 -0
  26. package/src/copy/routeConfig.express.ts +2 -0
  27. package/src/copy/routeConfig.fastify.ts +2 -0
  28. package/src/copy/routeConfig.hono.ts +2 -0
  29. package/src/copy/routeConfig.ts +2 -0
  30. package/src/generators/generateOperationCore.ts +43 -3
  31. package/src/generators/generateRouter.ts +8 -3
  32. package/src/generators/generateRouterFastify.ts +8 -3
  33. package/src/generators/generateRouterHono.ts +8 -2
  34. package/src/generators/generateUnifiedScalarUI.ts +15 -11
  35. package/src/index.ts +27 -7
@@ -2,17 +2,20 @@ import { DMMF } from '@prisma/generator-helper'
2
2
  import { generateRouteConfigType } from './generateRouteConfigType'
3
3
  import { ImportStyle } from '../utils/resolveImportStyle'
4
4
  import { importExt } from '../utils/importExt'
5
+ import { WriteStrategy } from '../constants'
5
6
 
6
7
  export function generateHonoRouterFunction({
7
8
  model,
8
9
  enums,
9
10
  guardShapesImport,
10
11
  importStyle,
12
+ writeStrategy,
11
13
  }: {
12
14
  model: DMMF.Model
13
15
  enums: DMMF.DatamodelEnum[]
14
16
  guardShapesImport: string | null
15
17
  importStyle: ImportStyle
18
+ writeStrategy: WriteStrategy
16
19
  }): string {
17
20
  const ext = importExt(importStyle)
18
21
  const modelName = model.name
@@ -73,6 +76,7 @@ import type {
73
76
  HonoEnvBase,
74
77
  HonoInternalVariables,
75
78
  GeneratedHonoEnv,
79
+ WriteStrategy,
76
80
  } from '../routeConfig.target${ext}'
77
81
  import { parseQueryParams } from '../parseQueryParams${ext}'
78
82
  import { sanitizeKeys, normalizePrefix, getEnv } from '../misc${ext}'
@@ -82,6 +86,8 @@ import { mapError, transformResult, type OperationContext } from '../operationRu
82
86
  ${generateRouteConfigType(modelName, 'HonoHookHandler', guardShapesImport, importStyle, 'hono')}
83
87
  const _env = getEnv()
84
88
 
89
+ const WRITE_STRATEGY: WriteStrategy = '${writeStrategy}'
90
+
85
91
  const MODEL_FIELDS = ${JSON.stringify(fieldsMeta, null, 2)} as const
86
92
 
87
93
  const MODEL_ENUMS = ${JSON.stringify(enumsMeta, null, 2)} as const
@@ -224,7 +230,7 @@ export function ${routerFunctionName}<TCtx = unknown, TPrisma = any, TEnv extend
224
230
  MODEL_FIELDS as unknown as Parameters<typeof buildModelOpenApi>[1],
225
231
  MODEL_ENUMS as unknown as Parameters<typeof buildModelOpenApi>[2],
226
232
  config as RouteConfig,
227
- { format: 'json' },
233
+ { format: 'json', writeStrategy: WRITE_STRATEGY },
228
234
  )
229
235
  const openApiYamlSpec = openApiDisabled
230
236
  ? null
@@ -233,7 +239,7 @@ export function ${routerFunctionName}<TCtx = unknown, TPrisma = any, TEnv extend
233
239
  MODEL_FIELDS as unknown as Parameters<typeof buildModelOpenApi>[1],
234
240
  MODEL_ENUMS as unknown as Parameters<typeof buildModelOpenApi>[2],
235
241
  config as RouteConfig,
236
- { format: 'yaml' },
242
+ { format: 'yaml', writeStrategy: WRITE_STRATEGY },
237
243
  )
238
244
 
239
245
  if (isQueryBuilderEnabled(config as RouteConfig)) {
@@ -1,5 +1,5 @@
1
1
  import { DMMF } from '@prisma/generator-helper'
2
- import { Target } from '../constants'
2
+ import { Target, WriteStrategy } from '../constants'
3
3
  import { ImportStyle } from '../utils/resolveImportStyle'
4
4
  import { importExt } from '../utils/importExt'
5
5
 
@@ -51,7 +51,7 @@ function generateExpressDocsExport(modelName: string): string {
51
51
  MODEL_FIELDS as unknown as Parameters<typeof buildModelOpenApi>[1],
52
52
  MODEL_ENUMS as unknown as Parameters<typeof buildModelOpenApi>[2],
53
53
  config,
54
- { format: 'yaml' }
54
+ { format: 'yaml', writeStrategy: WRITE_STRATEGY }
55
55
  )
56
56
  return res.type('application/yaml').send(yaml as string)
57
57
  }
@@ -61,7 +61,7 @@ function generateExpressDocsExport(modelName: string): string {
61
61
  MODEL_FIELDS as unknown as Parameters<typeof buildModelOpenApi>[1],
62
62
  MODEL_ENUMS as unknown as Parameters<typeof buildModelOpenApi>[2],
63
63
  config,
64
- { format: 'json' }
64
+ { format: 'json', writeStrategy: WRITE_STRATEGY }
65
65
  )
66
66
 
67
67
  if (ui === 'json') return res.json(spec)
@@ -72,7 +72,7 @@ function generateExpressDocsExport(modelName: string): string {
72
72
  return res.type('html').send(renderScalar('${modelName}', spec, pageTitle, config.scalarCdnUrl))
73
73
  }
74
74
 
75
- const html = renderDocs('${modelName}', config, MODEL_CONTEXT)
75
+ const html = renderDocs('${modelName}', config, MODEL_CONTEXT, WRITE_STRATEGY)
76
76
  return res.type('html').send(html)
77
77
  }
78
78
  }`
@@ -102,7 +102,7 @@ function generateFastifyDocsExport(modelName: string): string {
102
102
  MODEL_FIELDS as unknown as Parameters<typeof buildModelOpenApi>[1],
103
103
  MODEL_ENUMS as unknown as Parameters<typeof buildModelOpenApi>[2],
104
104
  config,
105
- { format: 'yaml' }
105
+ { format: 'yaml', writeStrategy: WRITE_STRATEGY }
106
106
  )
107
107
  reply.type('application/yaml').send(yaml as string); return
108
108
  }
@@ -112,7 +112,7 @@ function generateFastifyDocsExport(modelName: string): string {
112
112
  MODEL_FIELDS as unknown as Parameters<typeof buildModelOpenApi>[1],
113
113
  MODEL_ENUMS as unknown as Parameters<typeof buildModelOpenApi>[2],
114
114
  config,
115
- { format: 'json' }
115
+ { format: 'json', writeStrategy: WRITE_STRATEGY }
116
116
  )
117
117
 
118
118
  if (ui === 'json') { reply.send(spec); return }
@@ -123,7 +123,7 @@ function generateFastifyDocsExport(modelName: string): string {
123
123
  reply.type('text/html').send(renderScalar('${modelName}', spec, pageTitle, config.scalarCdnUrl)); return
124
124
  }
125
125
 
126
- const html = renderDocs('${modelName}', config, MODEL_CONTEXT)
126
+ const html = renderDocs('${modelName}', config, MODEL_CONTEXT, WRITE_STRATEGY)
127
127
  reply.type('text/html').send(html)
128
128
  }
129
129
  }`
@@ -152,7 +152,7 @@ function generateHonoDocsExport(modelName: string): string {
152
152
  MODEL_FIELDS as unknown as Parameters<typeof buildModelOpenApi>[1],
153
153
  MODEL_ENUMS as unknown as Parameters<typeof buildModelOpenApi>[2],
154
154
  config,
155
- { format: 'yaml' }
155
+ { format: 'yaml', writeStrategy: WRITE_STRATEGY }
156
156
  ) as string
157
157
  return c.body(yaml, 200, { 'Content-Type': 'application/yaml' })
158
158
  }
@@ -162,7 +162,7 @@ function generateHonoDocsExport(modelName: string): string {
162
162
  MODEL_FIELDS as unknown as Parameters<typeof buildModelOpenApi>[1],
163
163
  MODEL_ENUMS as unknown as Parameters<typeof buildModelOpenApi>[2],
164
164
  config,
165
- { format: 'json' }
165
+ { format: 'json', writeStrategy: WRITE_STRATEGY }
166
166
  )
167
167
 
168
168
  if (ui === 'json') return c.json(spec as Record<string, unknown>)
@@ -173,7 +173,7 @@ function generateHonoDocsExport(modelName: string): string {
173
173
  return c.html(renderScalar('${modelName}', spec, pageTitle, config.scalarCdnUrl))
174
174
  }
175
175
 
176
- const html = renderDocs('${modelName}', config, MODEL_CONTEXT)
176
+ const html = renderDocs('${modelName}', config, MODEL_CONTEXT, WRITE_STRATEGY)
177
177
  return c.html(html)
178
178
  }
179
179
  }`
@@ -184,8 +184,9 @@ export function generateScalarUIHandler(options: {
184
184
  enums: DMMF.DatamodelEnum[]
185
185
  target?: Target
186
186
  importStyle: ImportStyle
187
+ writeStrategy: WriteStrategy
187
188
  }): string {
188
- const { model, enums } = options
189
+ const { model, enums, writeStrategy } = options
189
190
  const target = options.target || 'express'
190
191
  const ext = importExt(options.importStyle)
191
192
  const modelName = model.name
@@ -260,6 +261,7 @@ export function generateScalarUIHandler(options: {
260
261
 
261
262
  return `${frameworkImport}
262
263
  import { buildModelOpenApi } from '../buildModelOpenApi${ext}'
264
+ import type { WriteStrategy } from '../routeConfig${ext}'
263
265
  import {
264
266
  renderDocs,
265
267
  renderScalar,
@@ -273,6 +275,8 @@ import {
273
275
  type DocsModelContext,
274
276
  } from '../docsRenderer${ext}'
275
277
 
278
+ const WRITE_STRATEGY: WriteStrategy = '${writeStrategy}'
279
+
276
280
  export const MODEL_FIELDS: FieldMeta[] = ${JSON.stringify(fieldsMeta, null, 2)}
277
281
 
278
282
  export const MODEL_ENUMS: EnumMeta[] = ${JSON.stringify(enumsMeta, null, 2)}
package/src/index.ts CHANGED
@@ -25,7 +25,7 @@ import {
25
25
  import { writeFileSafely } from './utils/writeFileSafely'
26
26
  import { copyFiles } from './utils/copyFiles'
27
27
  import { resolveImportStyle, ImportStyle } from './utils/resolveImportStyle'
28
- import { GENERATOR_NAME, Target } from './constants'
28
+ import { GENERATOR_NAME, Target, WriteStrategy } from './constants'
29
29
 
30
30
  const GENERATOR_OFF_RE = /\bgenerator off\b/
31
31
 
@@ -34,8 +34,25 @@ function getTarget(options: GeneratorOptions): Target {
34
34
  (options.generator.config as Record<string, unknown>).target ?? 'express',
35
35
  ).toLowerCase()
36
36
  if (raw === 'express' || raw === 'fastify' || raw === 'hono') return raw
37
+ throw new Error(`Invalid target "${raw}". Expected "express", "fastify", or "hono".`)
38
+ }
39
+
40
+ function getWriteStrategy(options: GeneratorOptions): WriteStrategy {
41
+ const raw = String(
42
+ (options.generator.config as Record<string, unknown>).writeStrategy ?? 'regular',
43
+ )
44
+ const lower = raw.toLowerCase()
45
+ if (lower === 'regular') return 'regular'
46
+ if (lower === 'throwonnonreturning') return 'throwOnNonReturning'
47
+ if (lower === 'throwonregular') {
48
+ console.warn(
49
+ '[prisma-generator-express] writeStrategy="throwOnRegular" is deprecated. Use "throwOnNonReturning" instead.',
50
+ )
51
+ return 'throwOnNonReturning'
52
+ }
53
+ if (lower === 'forcereturn') return 'forceReturn'
37
54
  throw new Error(
38
- `Invalid target "${raw}". Expected "express", "fastify", or "hono".`,
55
+ `Invalid writeStrategy "${raw}". Expected "regular", "throwOnNonReturning", or "forceReturn".`,
39
56
  )
40
57
  }
41
58
 
@@ -54,6 +71,7 @@ generatorHandler({
54
71
 
55
72
  async onGenerate(options: GeneratorOptions) {
56
73
  const target = getTarget(options)
74
+ const writeStrategy = getWriteStrategy(options)
57
75
  const hasExplicitOutput =
58
76
  !!options.generator.output?.fromEnvVar ||
59
77
  (options.generator.config as Record<string, unknown>).output !== undefined
@@ -70,6 +88,7 @@ generatorHandler({
70
88
  console.log(` Target: ${target}`)
71
89
  console.log(` Output: ${options.generator.output?.value}`)
72
90
  console.log(` Import style: ${importStyle}`)
91
+ console.log(` Write strategy: ${writeStrategy}`)
73
92
 
74
93
  if (options.dmmf.datamodel.models.length > 0) {
75
94
  validateClientGeneratorPresent(options)
@@ -91,10 +110,7 @@ generatorHandler({
91
110
  const allModels = options.dmmf.datamodel.models as DMMF.Model[]
92
111
 
93
112
  for (const model of options.dmmf.datamodel.models) {
94
- if (
95
- model.documentation &&
96
- GENERATOR_OFF_RE.test(model.documentation)
97
- ) {
113
+ if (model.documentation && GENERATOR_OFF_RE.test(model.documentation)) {
98
114
  console.log(` Skipping: ${model.name} (generator off)`)
99
115
  continue
100
116
  }
@@ -103,7 +119,7 @@ generatorHandler({
103
119
  const guardShapesImport = getGuardShapesImport(options, model.name)
104
120
 
105
121
  await writeFileSafely({
106
- content: generateModelCore({ model: model as DMMF.Model, importStyle }),
122
+ content: generateModelCore({ model: model as DMMF.Model, importStyle, writeStrategy }),
107
123
  options,
108
124
  model: model as DMMF.Model,
109
125
  operation: 'Core',
@@ -123,6 +139,7 @@ generatorHandler({
123
139
  enums: options.dmmf.datamodel.enums as DMMF.DatamodelEnum[],
124
140
  guardShapesImport,
125
141
  importStyle,
142
+ writeStrategy,
126
143
  })
127
144
  : target === 'hono'
128
145
  ? generateHonoRouterFunction({
@@ -130,12 +147,14 @@ generatorHandler({
130
147
  enums: options.dmmf.datamodel.enums as DMMF.DatamodelEnum[],
131
148
  guardShapesImport,
132
149
  importStyle,
150
+ writeStrategy,
133
151
  })
134
152
  : generateRouterFunction({
135
153
  model: model as DMMF.Model,
136
154
  enums: options.dmmf.datamodel.enums as DMMF.DatamodelEnum[],
137
155
  guardShapesImport,
138
156
  importStyle,
157
+ writeStrategy,
139
158
  })
140
159
 
141
160
  await writeFileSafely({
@@ -151,6 +170,7 @@ generatorHandler({
151
170
  enums: options.dmmf.datamodel.enums as DMMF.DatamodelEnum[],
152
171
  target,
153
172
  importStyle,
173
+ writeStrategy,
154
174
  }),
155
175
  options,
156
176
  model: model as DMMF.Model,