prisma-generator-express 1.42.0 → 1.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/generators/generateFastifyHandler.d.ts +2 -0
- package/dist/generators/generateFastifyHandler.js +21 -6
- package/dist/generators/generateFastifyHandler.js.map +1 -1
- package/dist/generators/generateHonoHandler.d.ts +2 -0
- package/dist/generators/generateHonoHandler.js +8 -6
- package/dist/generators/generateHonoHandler.js.map +1 -1
- package/dist/generators/generateOperationCore.d.ts +0 -1
- package/dist/generators/generateOperationCore.js +34 -546
- package/dist/generators/generateOperationCore.js.map +1 -1
- package/dist/generators/generateRelationMeta.d.ts +13 -0
- package/dist/generators/generateRelationMeta.js +110 -0
- package/dist/generators/generateRelationMeta.js.map +1 -0
- package/dist/generators/generateRouteConfigType.js +13 -5
- package/dist/generators/generateRouteConfigType.js.map +1 -1
- package/dist/generators/generateRouter.js +83 -19
- package/dist/generators/generateRouter.js.map +1 -1
- package/dist/generators/generateRouterFastify.js +127 -384
- package/dist/generators/generateRouterFastify.js.map +1 -1
- package/dist/generators/generateRouterHono.js +48 -36
- package/dist/generators/generateRouterHono.js.map +1 -1
- package/dist/generators/generateUnifiedHandler.d.ts +2 -0
- package/dist/generators/generateUnifiedHandler.js +28 -10
- package/dist/generators/generateUnifiedHandler.js.map +1 -1
- package/dist/generators/generateUnifiedScalarUI.d.ts +2 -0
- package/dist/generators/generateUnifiedScalarUI.js +19 -16
- package/dist/generators/generateUnifiedScalarUI.js.map +1 -1
- package/dist/index.js +21 -5
- package/dist/index.js.map +1 -1
- package/dist/utils/copyFiles.js +12 -0
- package/dist/utils/copyFiles.js.map +1 -1
- package/dist/utils/writeFileSafely.js +2 -2
- package/dist/utils/writeFileSafely.js.map +1 -1
- package/package.json +1 -1
- package/src/copy/autoIncludePlanner.ts +354 -0
- package/src/copy/autoIncludeRuntime.ts +362 -0
- package/src/copy/operationRuntime.ts +614 -0
- package/src/copy/routeConfig.express.ts +5 -3
- package/src/copy/routeConfig.fastify.ts +2 -2
- package/src/copy/routeConfig.hono.ts +3 -3
- package/src/copy/routeConfig.ts +20 -9
- package/src/generators/generateFastifyHandler.ts +23 -6
- package/src/generators/generateHonoHandler.ts +10 -6
- package/src/generators/generateOperationCore.ts +34 -546
- package/src/generators/generateRelationMeta.ts +160 -0
- package/src/generators/generateRouteConfigType.ts +13 -6
- package/src/generators/generateRouter.ts +83 -19
- package/src/generators/generateRouterFastify.ts +127 -384
- package/src/generators/generateRouterHono.ts +48 -36
- package/src/generators/generateUnifiedHandler.ts +30 -10
- package/src/generators/generateUnifiedScalarUI.ts +21 -16
- package/src/index.ts +31 -13
- package/src/utils/copyFiles.ts +13 -0
- package/src/utils/writeFileSafely.ts +2 -2
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { DMMF } from '@prisma/generator-helper'
|
|
2
|
+
import { ImportStyle } from '../utils/resolveImportStyle'
|
|
3
|
+
import { importExt } from '../utils/importExt'
|
|
4
|
+
|
|
5
|
+
type RelationDirection = 'parentOwnsFk' | 'childOwnsFk' | 'implicitM2M'
|
|
6
|
+
|
|
7
|
+
type RelationFieldMeta = {
|
|
8
|
+
name: string
|
|
9
|
+
type: string
|
|
10
|
+
isList: boolean
|
|
11
|
+
isRequired: boolean
|
|
12
|
+
direction: RelationDirection
|
|
13
|
+
parentLinkFields: string[]
|
|
14
|
+
childLinkFields: string[]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
type ModelMeta = {
|
|
18
|
+
name: string
|
|
19
|
+
delegateKey: string
|
|
20
|
+
scalarFields: string[]
|
|
21
|
+
idFields: string[]
|
|
22
|
+
relations: Record<string, RelationFieldMeta>
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function findOppositeField(
|
|
26
|
+
models: ReadonlyArray<DMMF.Model>,
|
|
27
|
+
targetModelName: string,
|
|
28
|
+
relationName: string | undefined,
|
|
29
|
+
selfModelName: string,
|
|
30
|
+
selfFieldName: string,
|
|
31
|
+
): DMMF.Field | null {
|
|
32
|
+
if (!relationName) return null
|
|
33
|
+
const target = models.find((m) => m.name === targetModelName)
|
|
34
|
+
if (!target) return null
|
|
35
|
+
const isSelfRelation = targetModelName === selfModelName
|
|
36
|
+
return target.fields.find(
|
|
37
|
+
(f) =>
|
|
38
|
+
f.kind === 'object' &&
|
|
39
|
+
f.relationName === relationName &&
|
|
40
|
+
f.type === selfModelName &&
|
|
41
|
+
!(isSelfRelation && f.name === selfFieldName),
|
|
42
|
+
) || null
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function computeRelation(
|
|
46
|
+
field: DMMF.Field,
|
|
47
|
+
selfModelName: string,
|
|
48
|
+
models: ReadonlyArray<DMMF.Model>,
|
|
49
|
+
): RelationFieldMeta {
|
|
50
|
+
const selfFrom = (field.relationFromFields ?? []) as string[]
|
|
51
|
+
const selfTo = (field.relationToFields ?? []) as string[]
|
|
52
|
+
|
|
53
|
+
if (selfFrom.length > 0) {
|
|
54
|
+
return {
|
|
55
|
+
name: field.name,
|
|
56
|
+
type: field.type,
|
|
57
|
+
isList: field.isList,
|
|
58
|
+
isRequired: field.isRequired,
|
|
59
|
+
direction: 'parentOwnsFk',
|
|
60
|
+
parentLinkFields: selfFrom,
|
|
61
|
+
childLinkFields: selfTo,
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const opposite = findOppositeField(models, field.type, field.relationName, selfModelName, field.name)
|
|
66
|
+
if (opposite) {
|
|
67
|
+
const oppFrom = (opposite.relationFromFields ?? []) as string[]
|
|
68
|
+
const oppTo = (opposite.relationToFields ?? []) as string[]
|
|
69
|
+
if (oppFrom.length > 0) {
|
|
70
|
+
return {
|
|
71
|
+
name: field.name,
|
|
72
|
+
type: field.type,
|
|
73
|
+
isList: field.isList,
|
|
74
|
+
isRequired: field.isRequired,
|
|
75
|
+
direction: 'childOwnsFk',
|
|
76
|
+
parentLinkFields: oppTo,
|
|
77
|
+
childLinkFields: oppFrom,
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
name: field.name,
|
|
84
|
+
type: field.type,
|
|
85
|
+
isList: field.isList,
|
|
86
|
+
isRequired: field.isRequired,
|
|
87
|
+
direction: 'implicitM2M',
|
|
88
|
+
parentLinkFields: [],
|
|
89
|
+
childLinkFields: [],
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function buildModelMeta(
|
|
94
|
+
model: DMMF.Model,
|
|
95
|
+
models: ReadonlyArray<DMMF.Model>,
|
|
96
|
+
): ModelMeta {
|
|
97
|
+
const scalarFields: string[] = []
|
|
98
|
+
const idFields: string[] = []
|
|
99
|
+
const relations: Record<string, RelationFieldMeta> = {}
|
|
100
|
+
|
|
101
|
+
for (const field of model.fields) {
|
|
102
|
+
if (field.kind === 'object') {
|
|
103
|
+
relations[field.name] = computeRelation(field, model.name, models)
|
|
104
|
+
} else if (field.kind === 'scalar' || field.kind === 'enum') {
|
|
105
|
+
scalarFields.push(field.name)
|
|
106
|
+
if (field.isId) idFields.push(field.name)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (model.primaryKey && Array.isArray(model.primaryKey.fields)) {
|
|
111
|
+
for (const f of model.primaryKey.fields) {
|
|
112
|
+
if (!idFields.includes(f)) idFields.push(f)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return {
|
|
117
|
+
name: model.name,
|
|
118
|
+
delegateKey: model.name.charAt(0).toLowerCase() + model.name.slice(1),
|
|
119
|
+
scalarFields,
|
|
120
|
+
idFields,
|
|
121
|
+
relations,
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export interface GenerateRelationMetaOptions {
|
|
126
|
+
model: DMMF.Model
|
|
127
|
+
allModels: ReadonlyArray<DMMF.Model>
|
|
128
|
+
importStyle: ImportStyle
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function generateRelationMeta(options: GenerateRelationMetaOptions): string {
|
|
132
|
+
const ext = importExt(options.importStyle)
|
|
133
|
+
const meta = buildModelMeta(options.model, options.allModels)
|
|
134
|
+
return `import type { ModelRelationMap } from '../autoIncludePlanner${ext}'
|
|
135
|
+
|
|
136
|
+
export const ${options.model.name}Relations: ModelRelationMap = ${JSON.stringify(meta, null, 2)}
|
|
137
|
+
`
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export interface GenerateRelationModelsIndexOptions {
|
|
141
|
+
modelNames: ReadonlyArray<string>
|
|
142
|
+
importStyle: ImportStyle
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function generateRelationModelsIndex(options: GenerateRelationModelsIndexOptions): string {
|
|
146
|
+
const ext = importExt(options.importStyle)
|
|
147
|
+
const imports = options.modelNames
|
|
148
|
+
.map((n) => `import { ${n}Relations } from './${n}/${n}Relations${ext}'`)
|
|
149
|
+
.join('\n')
|
|
150
|
+
const entries = options.modelNames
|
|
151
|
+
.map((n) => ` ${n}: ${n}Relations,`)
|
|
152
|
+
.join('\n')
|
|
153
|
+
return `import type { ModelRelationMap } from './autoIncludePlanner${ext}'
|
|
154
|
+
${imports}
|
|
155
|
+
|
|
156
|
+
export const relationModels: Record<string, ModelRelationMap> = {
|
|
157
|
+
${entries}
|
|
158
|
+
}
|
|
159
|
+
`
|
|
160
|
+
}
|
|
@@ -42,6 +42,12 @@ function capitalize(s: string): string {
|
|
|
42
42
|
return s.charAt(0).toUpperCase() + s.slice(1)
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
function requestTypeFor(target: Target): string {
|
|
46
|
+
if (target === 'fastify') return `import('fastify').FastifyRequest`
|
|
47
|
+
if (target === 'hono') return `import('hono').Context`
|
|
48
|
+
return `import('express').Request`
|
|
49
|
+
}
|
|
50
|
+
|
|
45
51
|
export function generateRouteConfigType(
|
|
46
52
|
modelName: string,
|
|
47
53
|
hookHandlerType: string,
|
|
@@ -52,9 +58,14 @@ export function generateRouteConfigType(
|
|
|
52
58
|
const ext = importExt(importStyle)
|
|
53
59
|
const m = modelName
|
|
54
60
|
const supportsProgressive = target === 'express'
|
|
61
|
+
const requestType = requestTypeFor(target)
|
|
62
|
+
|
|
63
|
+
const progressiveTypeImport = supportsProgressive
|
|
64
|
+
? `import type { ProgressiveVariantConfig, ProgressiveStage } from '../routeConfig.target${ext}'\n\n`
|
|
65
|
+
: ''
|
|
55
66
|
|
|
56
67
|
if (!guardShapesImport) {
|
|
57
|
-
return `export type ${m}RouteConfig<TCtx = unknown> = RouteConfig<Record<string, unknown>, TCtx>\n`
|
|
68
|
+
return progressiveTypeImport + `export type ${m}RouteConfig<TCtx = unknown> = RouteConfig<Record<string, unknown>, TCtx>\n`
|
|
58
69
|
}
|
|
59
70
|
|
|
60
71
|
const shapeOps = Object.values(ROUTER_OP_TO_SHAPE_OP).filter((v, i, a) => a.indexOf(v) === i)
|
|
@@ -78,10 +89,6 @@ export function generateRouteConfigType(
|
|
|
78
89
|
|
|
79
90
|
const omitKeys = ROUTER_OPERATIONS.map((k) => `'${k}'`).join('\n | ')
|
|
80
91
|
|
|
81
|
-
const progressiveTypeImport = supportsProgressive
|
|
82
|
-
? `import type { ProgressiveVariantConfig, ProgressiveStage } from '../routeConfig.target${ext}'\n\n`
|
|
83
|
-
: ''
|
|
84
|
-
|
|
85
92
|
return (
|
|
86
93
|
progressiveTypeImport +
|
|
87
94
|
`import type {\n ${opShapeImports}\n} from '${guardShapesImport}${ext}'\n\n` +
|
|
@@ -90,7 +97,7 @@ export function generateRouteConfigType(
|
|
|
90
97
|
` | ${omitKeys}\n` +
|
|
91
98
|
` | 'resolveContext'\n` +
|
|
92
99
|
`> & {\n` +
|
|
93
|
-
` resolveContext?: (request:
|
|
100
|
+
` resolveContext?: (request: ${requestType}) => TCtx | Promise<TCtx>\n` +
|
|
94
101
|
`${overrides}\n}\n`
|
|
95
102
|
)
|
|
96
103
|
}
|
|
@@ -20,6 +20,7 @@ export function generateRouterFunction({
|
|
|
20
20
|
const modelName = model.name
|
|
21
21
|
const prefix = toCamelCase(modelName)
|
|
22
22
|
const modelNameLower = modelName.toLowerCase()
|
|
23
|
+
const delegateKey = modelName.charAt(0).toLowerCase() + modelName.slice(1)
|
|
23
24
|
const routerFunctionName = `${prefix}Router`
|
|
24
25
|
|
|
25
26
|
const fieldsMeta = model.fields.map((f) => ({
|
|
@@ -69,7 +70,7 @@ import {
|
|
|
69
70
|
${prefix}GroupBy,
|
|
70
71
|
} from './${modelName}Handlers${ext}'
|
|
71
72
|
import * as core from './${modelName}Core${ext}'
|
|
72
|
-
import type { RouteConfig
|
|
73
|
+
import type { RouteConfig } from '../routeConfig.target${ext}'
|
|
73
74
|
import { parseQueryParams } from '../parseQueryParams${ext}'
|
|
74
75
|
import { sanitizeKeys } from '../misc${ext}'
|
|
75
76
|
import { buildModelOpenApi } from '../buildModelOpenApi${ext}'
|
|
@@ -79,7 +80,13 @@ import {
|
|
|
79
80
|
acceptsEventStream,
|
|
80
81
|
runProgressiveEndpoint,
|
|
81
82
|
runSingleResultSSE,
|
|
83
|
+
emitTerminalSSEError,
|
|
84
|
+
removeReqCloseListener,
|
|
85
|
+
mapError,
|
|
86
|
+
HttpError,
|
|
82
87
|
} from '../operationRuntime${ext}'
|
|
88
|
+
import { relationModels } from '../relationModels${ext}'
|
|
89
|
+
import { runAutoIncludeProgressive } from '../autoIncludeRuntime${ext}'
|
|
83
90
|
|
|
84
91
|
${generateRouteConfigType(modelName, 'RequestHandler', guardShapesImport, importStyle, 'express')}
|
|
85
92
|
const _env = typeof process !== 'undefined' && process.env ? process.env : {} as Record<string, string | undefined>
|
|
@@ -103,7 +110,7 @@ type ExtendedRequest = Request & {
|
|
|
103
110
|
|
|
104
111
|
type LocalsBag = {
|
|
105
112
|
parsedQuery?: Record<string, unknown>
|
|
106
|
-
routeConfig?:
|
|
113
|
+
routeConfig?: { pagination?: OperationContext['paginationConfig'] }
|
|
107
114
|
guardShape?: Record<string, unknown>
|
|
108
115
|
guardCaller?: string
|
|
109
116
|
data?: unknown
|
|
@@ -200,7 +207,9 @@ export function ${routerFunctionName}<TCtx = unknown>(config: ${modelName}RouteC
|
|
|
200
207
|
const setShape = (opConfig: OperationConfigLike): RequestHandler => {
|
|
201
208
|
return (req, res, next) => {
|
|
202
209
|
const locals = readLocals(res)
|
|
203
|
-
|
|
210
|
+
if (config.pagination) {
|
|
211
|
+
locals.routeConfig = { pagination: config.pagination }
|
|
212
|
+
}
|
|
204
213
|
const headerName = config.guard?.variantHeader || 'x-api-variant'
|
|
205
214
|
const headerValue = req.get(headerName)
|
|
206
215
|
const caller = config.guard?.resolveVariant?.(req) ?? headerValue ?? undefined
|
|
@@ -210,9 +219,10 @@ export function ${routerFunctionName}<TCtx = unknown>(config: ${modelName}RouteC
|
|
|
210
219
|
}
|
|
211
220
|
}
|
|
212
221
|
|
|
213
|
-
|
|
222
|
+
const maybeProgressiveSSE = (
|
|
214
223
|
opConfig: OperationConfigLike,
|
|
215
224
|
coreFn: (ctx: OperationContext) => Promise<unknown>,
|
|
225
|
+
baseOp: string,
|
|
216
226
|
): RequestHandler => {
|
|
217
227
|
return async (req, res, next) => {
|
|
218
228
|
if (res.headersSent || res.writableEnded) return next()
|
|
@@ -233,13 +243,61 @@ export function ${routerFunctionName}<TCtx = unknown>(config: ${modelName}RouteC
|
|
|
233
243
|
return
|
|
234
244
|
}
|
|
235
245
|
|
|
246
|
+
if (progressiveConfig.mode === 'autoInclude') {
|
|
247
|
+
const isSingleRecordRead =
|
|
248
|
+
baseOp === 'findUnique' || baseOp === 'findUniqueOrThrow' ||
|
|
249
|
+
baseOp === 'findFirst' || baseOp === 'findFirstOrThrow'
|
|
250
|
+
|
|
251
|
+
if (!isSingleRecordRead) {
|
|
252
|
+
if (progressiveConfig.fallback === 'error') {
|
|
253
|
+
emitTerminalSSEError(res, 'auto-progressive fallback: operation not single-record')
|
|
254
|
+
return
|
|
255
|
+
}
|
|
256
|
+
await runSingleResultSSE({
|
|
257
|
+
req,
|
|
258
|
+
res,
|
|
259
|
+
coreQueryFn: () => coreFn(buildContext(req, res)),
|
|
260
|
+
})
|
|
261
|
+
return
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const ctx = buildContext(req, res)
|
|
265
|
+
const args = (locals.parsedQuery ?? {}) as Record<string, unknown>
|
|
266
|
+
const controller = new AbortController()
|
|
267
|
+
const onClose = () => controller.abort()
|
|
268
|
+
req.on('close', onClose)
|
|
269
|
+
try {
|
|
270
|
+
await runAutoIncludeProgressive({
|
|
271
|
+
req,
|
|
272
|
+
res,
|
|
273
|
+
ctx,
|
|
274
|
+
args,
|
|
275
|
+
baseOp: baseOp as 'findUnique' | 'findUniqueOrThrow' | 'findFirst' | 'findFirstOrThrow',
|
|
276
|
+
modelName: '${modelName}',
|
|
277
|
+
delegateKey: '${delegateKey}',
|
|
278
|
+
models: relationModels,
|
|
279
|
+
variantConfig: progressiveConfig,
|
|
280
|
+
coreQueryFn: () => coreFn(ctx),
|
|
281
|
+
signal: controller.signal,
|
|
282
|
+
})
|
|
283
|
+
} finally {
|
|
284
|
+
removeReqCloseListener(req, onClose)
|
|
285
|
+
}
|
|
286
|
+
return
|
|
287
|
+
}
|
|
288
|
+
|
|
236
289
|
if (!Array.isArray(progressiveConfig.stages)) {
|
|
237
|
-
|
|
290
|
+
await runSingleResultSSE({
|
|
291
|
+
req,
|
|
292
|
+
res,
|
|
293
|
+
coreQueryFn: () => coreFn(buildContext(req, res)),
|
|
294
|
+
})
|
|
295
|
+
return
|
|
238
296
|
}
|
|
239
297
|
|
|
240
298
|
const stageRegistry = opConfig.progressiveStages ?? {}
|
|
241
299
|
const missingStage = progressiveConfig.stages.find(
|
|
242
|
-
(name) => typeof stageRegistry[name] !== 'function',
|
|
300
|
+
(name: string) => typeof stageRegistry[name] !== 'function',
|
|
243
301
|
)
|
|
244
302
|
if (missingStage) {
|
|
245
303
|
return next({ status: 500, message: 'Missing progressive stage: ' + missingStage })
|
|
@@ -297,63 +355,63 @@ export function ${routerFunctionName}<TCtx = unknown>(config: ${modelName}RouteC
|
|
|
297
355
|
const opConfig: OperationConfigLike = (config.findFirst as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
298
356
|
const { before = [], after = [] } = opConfig
|
|
299
357
|
const path = basePath ? \`\${basePath}/first\` : '/first'
|
|
300
|
-
router.get(path, parseQuery, setShape(opConfig), ...before, maybeProgressiveSSE(opConfig, core.findFirst), ${prefix}FindFirst as RequestHandler, ...after, respond)
|
|
358
|
+
router.get(path, parseQuery, setShape(opConfig), ...before, maybeProgressiveSSE(opConfig, core.findFirst, 'findFirst'), ${prefix}FindFirst as RequestHandler, ...after, respond)
|
|
301
359
|
if (postReadsEnabled) router.post(path, parseBodyAsQuery, setShape(opConfig), ...before, ${prefix}FindFirst as RequestHandler, ...after, respond)
|
|
302
360
|
}
|
|
303
361
|
if (config.enableAll || config.findFirstOrThrow) {
|
|
304
362
|
const opConfig: OperationConfigLike = (config.findFirstOrThrow as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
305
363
|
const { before = [], after = [] } = opConfig
|
|
306
364
|
const path = basePath ? \`\${basePath}/first/strict\` : '/first/strict'
|
|
307
|
-
router.get(path, parseQuery, setShape(opConfig), ...before, maybeProgressiveSSE(opConfig, core.findFirstOrThrow), ${prefix}FindFirstOrThrow as RequestHandler, ...after, respond)
|
|
365
|
+
router.get(path, parseQuery, setShape(opConfig), ...before, maybeProgressiveSSE(opConfig, core.findFirstOrThrow, 'findFirstOrThrow'), ${prefix}FindFirstOrThrow as RequestHandler, ...after, respond)
|
|
308
366
|
if (postReadsEnabled) router.post(path, parseBodyAsQuery, setShape(opConfig), ...before, ${prefix}FindFirstOrThrow as RequestHandler, ...after, respond)
|
|
309
367
|
}
|
|
310
368
|
if (config.enableAll || config.findManyPaginated) {
|
|
311
369
|
const opConfig: OperationConfigLike = (config.findManyPaginated as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
312
370
|
const { before = [], after = [] } = opConfig
|
|
313
371
|
const path = basePath ? \`\${basePath}/paginated\` : '/paginated'
|
|
314
|
-
router.get(path, parseQuery, setShape(opConfig), ...before, maybeProgressiveSSE(opConfig, core.findManyPaginated), ${prefix}FindManyPaginated as RequestHandler, ...after, respond)
|
|
372
|
+
router.get(path, parseQuery, setShape(opConfig), ...before, maybeProgressiveSSE(opConfig, core.findManyPaginated, 'findManyPaginated'), ${prefix}FindManyPaginated as RequestHandler, ...after, respond)
|
|
315
373
|
if (postReadsEnabled) router.post(path, parseBodyAsQuery, setShape(opConfig), ...before, ${prefix}FindManyPaginated as RequestHandler, ...after, respond)
|
|
316
374
|
}
|
|
317
375
|
if (config.enableAll || config.aggregate) {
|
|
318
376
|
const opConfig: OperationConfigLike = (config.aggregate as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
319
377
|
const { before = [], after = [] } = opConfig
|
|
320
378
|
const path = basePath ? \`\${basePath}/aggregate\` : '/aggregate'
|
|
321
|
-
router.get(path, parseQuery, setShape(opConfig), ...before, maybeProgressiveSSE(opConfig, core.aggregate), ${prefix}Aggregate as RequestHandler, ...after, respond)
|
|
379
|
+
router.get(path, parseQuery, setShape(opConfig), ...before, maybeProgressiveSSE(opConfig, core.aggregate, 'aggregate'), ${prefix}Aggregate as RequestHandler, ...after, respond)
|
|
322
380
|
if (postReadsEnabled) router.post(path, parseBodyAsQuery, setShape(opConfig), ...before, ${prefix}Aggregate as RequestHandler, ...after, respond)
|
|
323
381
|
}
|
|
324
382
|
if (config.enableAll || config.count) {
|
|
325
383
|
const opConfig: OperationConfigLike = (config.count as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
326
384
|
const { before = [], after = [] } = opConfig
|
|
327
385
|
const path = basePath ? \`\${basePath}/count\` : '/count'
|
|
328
|
-
router.get(path, parseQuery, setShape(opConfig), ...before, maybeProgressiveSSE(opConfig, core.count), ${prefix}Count as RequestHandler, ...after, respond)
|
|
386
|
+
router.get(path, parseQuery, setShape(opConfig), ...before, maybeProgressiveSSE(opConfig, core.count, 'count'), ${prefix}Count as RequestHandler, ...after, respond)
|
|
329
387
|
if (postReadsEnabled) router.post(path, parseBodyAsQuery, setShape(opConfig), ...before, ${prefix}Count as RequestHandler, ...after, respond)
|
|
330
388
|
}
|
|
331
389
|
if (config.enableAll || config.groupBy) {
|
|
332
390
|
const opConfig: OperationConfigLike = (config.groupBy as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
333
391
|
const { before = [], after = [] } = opConfig
|
|
334
392
|
const path = basePath ? \`\${basePath}/groupby\` : '/groupby'
|
|
335
|
-
router.get(path, parseQuery, setShape(opConfig), ...before, maybeProgressiveSSE(opConfig, core.groupBy), ${prefix}GroupBy as RequestHandler, ...after, respond)
|
|
393
|
+
router.get(path, parseQuery, setShape(opConfig), ...before, maybeProgressiveSSE(opConfig, core.groupBy, 'groupBy'), ${prefix}GroupBy as RequestHandler, ...after, respond)
|
|
336
394
|
if (postReadsEnabled) router.post(path, parseBodyAsQuery, setShape(opConfig), ...before, ${prefix}GroupBy as RequestHandler, ...after, respond)
|
|
337
395
|
}
|
|
338
396
|
if (config.enableAll || config.findUniqueOrThrow) {
|
|
339
397
|
const opConfig: OperationConfigLike = (config.findUniqueOrThrow as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
340
398
|
const { before = [], after = [] } = opConfig
|
|
341
399
|
const path = basePath ? \`\${basePath}/unique/strict\` : '/unique/strict'
|
|
342
|
-
router.get(path, parseQuery, setShape(opConfig), ...before, maybeProgressiveSSE(opConfig, core.findUniqueOrThrow), ${prefix}FindUniqueOrThrow as RequestHandler, ...after, respond)
|
|
400
|
+
router.get(path, parseQuery, setShape(opConfig), ...before, maybeProgressiveSSE(opConfig, core.findUniqueOrThrow, 'findUniqueOrThrow'), ${prefix}FindUniqueOrThrow as RequestHandler, ...after, respond)
|
|
343
401
|
if (postReadsEnabled) router.post(path, parseBodyAsQuery, setShape(opConfig), ...before, ${prefix}FindUniqueOrThrow as RequestHandler, ...after, respond)
|
|
344
402
|
}
|
|
345
403
|
if (config.enableAll || config.findUnique) {
|
|
346
404
|
const opConfig: OperationConfigLike = (config.findUnique as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
347
405
|
const { before = [], after = [] } = opConfig
|
|
348
406
|
const path = basePath ? \`\${basePath}/unique\` : '/unique'
|
|
349
|
-
router.get(path, parseQuery, setShape(opConfig), ...before, maybeProgressiveSSE(opConfig, core.findUnique), ${prefix}FindUnique as RequestHandler, ...after, respond)
|
|
407
|
+
router.get(path, parseQuery, setShape(opConfig), ...before, maybeProgressiveSSE(opConfig, core.findUnique, 'findUnique'), ${prefix}FindUnique as RequestHandler, ...after, respond)
|
|
350
408
|
if (postReadsEnabled) router.post(path, parseBodyAsQuery, setShape(opConfig), ...before, ${prefix}FindUnique as RequestHandler, ...after, respond)
|
|
351
409
|
}
|
|
352
410
|
if (config.enableAll || config.findMany) {
|
|
353
411
|
const opConfig: OperationConfigLike = (config.findMany as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
354
412
|
const { before = [], after = [] } = opConfig
|
|
355
413
|
const path = basePath || '/'
|
|
356
|
-
router.get(path, parseQuery, setShape(opConfig), ...before, maybeProgressiveSSE(opConfig, core.findMany), ${prefix}FindMany as RequestHandler, ...after, respond)
|
|
414
|
+
router.get(path, parseQuery, setShape(opConfig), ...before, maybeProgressiveSSE(opConfig, core.findMany, 'findMany'), ${prefix}FindMany as RequestHandler, ...after, respond)
|
|
357
415
|
if (postReadsEnabled) {
|
|
358
416
|
const postPath = basePath ? \`\${basePath}/read\` : '/read'
|
|
359
417
|
router.post(postPath, parseBodyAsQuery, setShape(opConfig), ...before, ${prefix}FindMany as RequestHandler, ...after, respond)
|
|
@@ -416,10 +474,16 @@ export function ${routerFunctionName}<TCtx = unknown>(config: ${modelName}RouteC
|
|
|
416
474
|
}
|
|
417
475
|
|
|
418
476
|
router.use((err: unknown, _req: Request, res: Response, next: NextFunction) => {
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
if (
|
|
477
|
+
let httpError: HttpError
|
|
478
|
+
if (err instanceof HttpError) {
|
|
479
|
+
httpError = err
|
|
480
|
+
} else if (err && typeof err === 'object' && typeof (err as { status?: number }).status === 'number') {
|
|
481
|
+
const e = err as { status: number; message?: string }
|
|
482
|
+
httpError = new HttpError(e.status, e.message || 'Internal server error')
|
|
483
|
+
} else {
|
|
484
|
+
httpError = mapError(err)
|
|
485
|
+
}
|
|
486
|
+
if (!res.headersSent) return res.status(httpError.status).json({ message: httpError.message })
|
|
423
487
|
next(err)
|
|
424
488
|
})
|
|
425
489
|
|