prisma-generator-express 1.40.0 → 1.42.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/README.md +444 -12
- package/dist/generators/generateOperationCore.d.ts +3 -1
- package/dist/generators/generateOperationCore.js +266 -160
- package/dist/generators/generateOperationCore.js.map +1 -1
- package/dist/generators/generateRouteConfigType.d.ts +3 -1
- package/dist/generators/generateRouteConfigType.js +36 -31
- package/dist/generators/generateRouteConfigType.js.map +1 -1
- package/dist/generators/generateRouter.d.ts +4 -2
- package/dist/generators/generateRouter.js +186 -132
- package/dist/generators/generateRouter.js.map +1 -1
- package/dist/generators/generateRouterFastify.d.ts +3 -1
- package/dist/generators/generateRouterFastify.js +12 -10
- package/dist/generators/generateRouterFastify.js.map +1 -1
- package/dist/generators/generateRouterHono.d.ts +3 -1
- package/dist/generators/generateRouterHono.js +12 -9
- package/dist/generators/generateRouterHono.js.map +1 -1
- package/dist/generators/generateUnifiedDocs.d.ts +2 -1
- package/dist/generators/generateUnifiedDocs.js +6 -4
- package/dist/generators/generateUnifiedDocs.js.map +1 -1
- package/dist/index.js +16 -21
- package/dist/index.js.map +1 -1
- package/dist/utils/copyFiles.d.ts +2 -1
- package/dist/utils/copyFiles.js +39 -34
- package/dist/utils/copyFiles.js.map +1 -1
- package/dist/utils/importExt.d.ts +2 -0
- package/dist/utils/importExt.js +11 -0
- package/dist/utils/importExt.js.map +1 -0
- package/dist/utils/resolveImportStyle.d.ts +3 -0
- package/dist/utils/resolveImportStyle.js +211 -0
- package/dist/utils/resolveImportStyle.js.map +1 -0
- package/dist/utils/writeFileSafely.js +6 -9
- package/dist/utils/writeFileSafely.js.map +1 -1
- package/package.json +1 -1
- package/src/copy/routeConfig.express.ts +39 -5
- package/src/copy/routeConfig.fastify.ts +8 -4
- package/src/copy/routeConfig.hono.ts +7 -3
- package/src/copy/routeConfig.ts +42 -2
- package/src/generators/generateOperationCore.ts +273 -169
- package/src/generators/generateRouteConfigType.ts +43 -36
- package/src/generators/generateRouter.ts +189 -133
- package/src/generators/generateRouterFastify.ts +14 -9
- package/src/generators/generateRouterHono.ts +14 -8
- package/src/generators/generateUnifiedDocs.ts +8 -3
- package/src/index.ts +25 -47
- package/src/utils/copyFiles.ts +45 -45
- package/src/utils/importExt.ts +7 -0
- package/src/utils/resolveImportStyle.ts +187 -0
- package/src/utils/writeFileSafely.ts +6 -22
|
@@ -1,26 +1,22 @@
|
|
|
1
|
+
import { ImportStyle } from '../utils/resolveImportStyle'
|
|
2
|
+
import { importExt } from '../utils/importExt'
|
|
3
|
+
import type { Target } from '../constants'
|
|
4
|
+
|
|
1
5
|
const ROUTER_OPERATIONS = [
|
|
2
|
-
'findUnique',
|
|
3
|
-
'
|
|
4
|
-
'
|
|
5
|
-
'
|
|
6
|
-
'
|
|
7
|
-
'findManyPaginated',
|
|
8
|
-
'count',
|
|
9
|
-
'aggregate',
|
|
10
|
-
'groupBy',
|
|
11
|
-
'create',
|
|
12
|
-
'createMany',
|
|
13
|
-
'createManyAndReturn',
|
|
14
|
-
'update',
|
|
15
|
-
'updateMany',
|
|
16
|
-
'updateManyAndReturn',
|
|
17
|
-
'upsert',
|
|
18
|
-
'delete',
|
|
19
|
-
'deleteMany',
|
|
6
|
+
'findUnique', 'findUniqueOrThrow', 'findFirst', 'findFirstOrThrow',
|
|
7
|
+
'findMany', 'findManyPaginated', 'count', 'aggregate', 'groupBy',
|
|
8
|
+
'create', 'createMany', 'createManyAndReturn',
|
|
9
|
+
'update', 'updateMany', 'updateManyAndReturn',
|
|
10
|
+
'upsert', 'delete', 'deleteMany',
|
|
20
11
|
] as const
|
|
21
12
|
|
|
22
13
|
type RouterOperation = (typeof ROUTER_OPERATIONS)[number]
|
|
23
14
|
|
|
15
|
+
const READ_OPERATIONS: ReadonlySet<RouterOperation> = new Set<RouterOperation>([
|
|
16
|
+
'findUnique', 'findUniqueOrThrow', 'findFirst', 'findFirstOrThrow',
|
|
17
|
+
'findMany', 'findManyPaginated', 'count', 'aggregate', 'groupBy',
|
|
18
|
+
])
|
|
19
|
+
|
|
24
20
|
const ROUTER_OP_TO_SHAPE_OP: Record<RouterOperation, string> = {
|
|
25
21
|
findUnique: 'findUnique',
|
|
26
22
|
findUniqueOrThrow: 'findUniqueOrThrow',
|
|
@@ -50,40 +46,51 @@ export function generateRouteConfigType(
|
|
|
50
46
|
modelName: string,
|
|
51
47
|
hookHandlerType: string,
|
|
52
48
|
guardShapesImport: string | null,
|
|
49
|
+
importStyle: ImportStyle,
|
|
50
|
+
target: Target,
|
|
53
51
|
): string {
|
|
52
|
+
const ext = importExt(importStyle)
|
|
54
53
|
const m = modelName
|
|
54
|
+
const supportsProgressive = target === 'express'
|
|
55
55
|
|
|
56
56
|
if (!guardShapesImport) {
|
|
57
|
-
return `export type ${m}RouteConfig<TCtx = unknown> = RouteConfig
|
|
57
|
+
return `export type ${m}RouteConfig<TCtx = unknown> = RouteConfig<Record<string, unknown>, TCtx>\n`
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
const shapeOps = Object.values(ROUTER_OP_TO_SHAPE_OP).filter(
|
|
61
|
-
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
const opShapeImports = shapeOps
|
|
65
|
-
.map((op) => `${m}${capitalize(op)}ShapeInput`)
|
|
66
|
-
.join(',\n ')
|
|
60
|
+
const shapeOps = Object.values(ROUTER_OP_TO_SHAPE_OP).filter((v, i, a) => a.indexOf(v) === i)
|
|
61
|
+
const opShapeImports = shapeOps.map((op) => `${m}${capitalize(op)}ShapeInput`).join(',\n ')
|
|
67
62
|
|
|
68
63
|
const overrides = ROUTER_OPERATIONS.map((routerOp) => {
|
|
69
64
|
const shapeOp = ROUTER_OP_TO_SHAPE_OP[routerOp]
|
|
70
65
|
const c = capitalize(shapeOp)
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
` before?: ${hookHandlerType}[]
|
|
74
|
-
` after?: ${hookHandlerType}[]
|
|
75
|
-
` shape?: ${m}${c}ShapeInput<TCtx
|
|
76
|
-
|
|
77
|
-
)
|
|
66
|
+
const isRead = READ_OPERATIONS.has(routerOp)
|
|
67
|
+
const lines = [
|
|
68
|
+
` before?: ${hookHandlerType}[]`,
|
|
69
|
+
` after?: ${hookHandlerType}[]`,
|
|
70
|
+
` shape?: ${m}${c}ShapeInput<TCtx>`,
|
|
71
|
+
]
|
|
72
|
+
if (isRead && supportsProgressive) {
|
|
73
|
+
lines.push(` progressive?: Record<string, ProgressiveVariantConfig>`)
|
|
74
|
+
lines.push(` progressiveStages?: Record<string, ProgressiveStage<TCtx>>`)
|
|
75
|
+
}
|
|
76
|
+
return ` ${routerOp}?: {\n${lines.join('\n')}\n }`
|
|
78
77
|
}).join('\n')
|
|
79
78
|
|
|
80
79
|
const omitKeys = ROUTER_OPERATIONS.map((k) => `'${k}'`).join('\n | ')
|
|
81
80
|
|
|
81
|
+
const progressiveTypeImport = supportsProgressive
|
|
82
|
+
? `import type { ProgressiveVariantConfig, ProgressiveStage } from '../routeConfig.target${ext}'\n\n`
|
|
83
|
+
: ''
|
|
84
|
+
|
|
82
85
|
return (
|
|
83
|
-
|
|
86
|
+
progressiveTypeImport +
|
|
87
|
+
`import type {\n ${opShapeImports}\n} from '${guardShapesImport}${ext}'\n\n` +
|
|
84
88
|
`export type ${m}RouteConfig<TCtx = unknown> = Omit<\n` +
|
|
85
|
-
` RouteConfig
|
|
89
|
+
` RouteConfig<Record<string, unknown>, TCtx>,\n` +
|
|
86
90
|
` | ${omitKeys}\n` +
|
|
87
|
-
|
|
91
|
+
` | 'resolveContext'\n` +
|
|
92
|
+
`> & {\n` +
|
|
93
|
+
` resolveContext?: (request: import('express').Request) => TCtx | Promise<TCtx>\n` +
|
|
94
|
+
`${overrides}\n}\n`
|
|
88
95
|
)
|
|
89
96
|
}
|
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
import { DMMF } from '@prisma/generator-helper'
|
|
2
2
|
import { toCamelCase } from '../utils/strings'
|
|
3
3
|
import { generateRouteConfigType } from './generateRouteConfigType'
|
|
4
|
+
import { ImportStyle } from '../utils/resolveImportStyle'
|
|
5
|
+
import { importExt } from '../utils/importExt'
|
|
4
6
|
|
|
5
7
|
export function generateRouterFunction({
|
|
6
8
|
model,
|
|
7
9
|
enums,
|
|
8
|
-
relativeClientPath,
|
|
9
10
|
guardShapesImport,
|
|
11
|
+
importStyle,
|
|
10
12
|
}: {
|
|
11
13
|
model: DMMF.Model
|
|
12
14
|
enums: DMMF.DatamodelEnum[]
|
|
13
|
-
relativeClientPath
|
|
15
|
+
relativeClientPath?: string
|
|
14
16
|
guardShapesImport: string | null
|
|
17
|
+
importStyle: ImportStyle
|
|
15
18
|
}): string {
|
|
19
|
+
const ext = importExt(importStyle)
|
|
16
20
|
const modelName = model.name
|
|
17
21
|
const prefix = toCamelCase(modelName)
|
|
18
22
|
const modelNameLower = modelName.toLowerCase()
|
|
@@ -41,8 +45,9 @@ export function generateRouterFunction({
|
|
|
41
45
|
values: e.values.map((v) => ({ name: v.name })),
|
|
42
46
|
}))
|
|
43
47
|
|
|
44
|
-
return `import express
|
|
45
|
-
import type {
|
|
48
|
+
return `import express from 'express'
|
|
49
|
+
import type { Request, Response, NextFunction, RequestHandler } from 'express'
|
|
50
|
+
import { startQueryBuilder } from '../queryBuilder${ext}'
|
|
46
51
|
import {
|
|
47
52
|
${prefix}FindUnique,
|
|
48
53
|
${prefix}FindUniqueOrThrow,
|
|
@@ -61,24 +66,52 @@ import {
|
|
|
61
66
|
${prefix}DeleteMany,
|
|
62
67
|
${prefix}Aggregate,
|
|
63
68
|
${prefix}Count,
|
|
64
|
-
${prefix}GroupBy
|
|
65
|
-
} from './${modelName}Handlers'
|
|
66
|
-
import
|
|
67
|
-
import {
|
|
68
|
-
import {
|
|
69
|
-
import {
|
|
70
|
-
import {
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
${prefix}GroupBy,
|
|
70
|
+
} from './${modelName}Handlers${ext}'
|
|
71
|
+
import * as core from './${modelName}Core${ext}'
|
|
72
|
+
import type { RouteConfig, ProgressiveVariantConfig, ProgressiveStage } from '../routeConfig.target${ext}'
|
|
73
|
+
import { parseQueryParams } from '../parseQueryParams${ext}'
|
|
74
|
+
import { sanitizeKeys } from '../misc${ext}'
|
|
75
|
+
import { buildModelOpenApi } from '../buildModelOpenApi${ext}'
|
|
76
|
+
import type { OperationContext } from '../operationRuntime${ext}'
|
|
77
|
+
import {
|
|
78
|
+
transformResult,
|
|
79
|
+
acceptsEventStream,
|
|
80
|
+
runProgressiveEndpoint,
|
|
81
|
+
runSingleResultSSE,
|
|
82
|
+
} from '../operationRuntime${ext}'
|
|
83
|
+
|
|
84
|
+
${generateRouteConfigType(modelName, 'RequestHandler', guardShapesImport, importStyle, 'express')}
|
|
73
85
|
const _env = typeof process !== 'undefined' && process.env ? process.env : {} as Record<string, string | undefined>
|
|
74
86
|
|
|
75
87
|
const MODEL_FIELDS = ${JSON.stringify(fieldsMeta, null, 2)} as const
|
|
76
|
-
|
|
77
88
|
const MODEL_ENUMS = ${JSON.stringify(enumsMeta, null, 2)} as const
|
|
78
89
|
|
|
79
|
-
|
|
80
|
-
before
|
|
81
|
-
after
|
|
90
|
+
type OperationConfigLike = {
|
|
91
|
+
before?: RequestHandler[]
|
|
92
|
+
after?: RequestHandler[]
|
|
93
|
+
shape?: Record<string, unknown>
|
|
94
|
+
progressive?: Record<string, ProgressiveVariantConfig>
|
|
95
|
+
progressiveStages?: Record<string, ProgressiveStage<unknown>>
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
type ExtendedRequest = Request & {
|
|
99
|
+
prisma?: unknown
|
|
100
|
+
postgres?: unknown
|
|
101
|
+
sqlite?: unknown
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
type LocalsBag = {
|
|
105
|
+
parsedQuery?: Record<string, unknown>
|
|
106
|
+
routeConfig?: ${modelName}RouteConfig
|
|
107
|
+
guardShape?: Record<string, unknown>
|
|
108
|
+
guardCaller?: string
|
|
109
|
+
data?: unknown
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const defaultOpConfig: OperationConfigLike = {
|
|
113
|
+
before: [],
|
|
114
|
+
after: [],
|
|
82
115
|
}
|
|
83
116
|
|
|
84
117
|
function normalizePrefix(p: string): string {
|
|
@@ -103,9 +136,12 @@ function getQueryBuilderConfig(config: RouteConfig) {
|
|
|
103
136
|
return {}
|
|
104
137
|
}
|
|
105
138
|
|
|
139
|
+
function readLocals(res: Response): LocalsBag {
|
|
140
|
+
return res.locals as LocalsBag
|
|
141
|
+
}
|
|
142
|
+
|
|
106
143
|
export function ${routerFunctionName}<TCtx = unknown>(config: ${modelName}RouteConfig<TCtx> = {}) {
|
|
107
144
|
const router = express.Router()
|
|
108
|
-
|
|
109
145
|
router.use(express.json())
|
|
110
146
|
|
|
111
147
|
const customPrefix = normalizePrefix(config.customUrlPrefix || '')
|
|
@@ -113,26 +149,42 @@ export function ${routerFunctionName}<TCtx = unknown>(config: ${modelName}RouteC
|
|
|
113
149
|
const basePath = customPrefix + modelPrefix
|
|
114
150
|
|
|
115
151
|
const openApiDisabled = config.disableOpenApi === true
|
|
116
|
-
|| (config.disableOpenApi !== false && (
|
|
117
|
-
_env.DISABLE_OPENAPI === 'true'
|
|
118
|
-
|| _env.NODE_ENV === 'production'
|
|
119
|
-
))
|
|
152
|
+
|| (config.disableOpenApi !== false && (_env.DISABLE_OPENAPI === 'true' || _env.NODE_ENV === 'production'))
|
|
120
153
|
|
|
121
154
|
const postReadsEnabled = !config.disablePostReads
|
|
122
155
|
|
|
123
156
|
const qbEnabled = isQueryBuilderEnabled(config)
|
|
124
|
-
|
|
125
157
|
if (qbEnabled) {
|
|
126
158
|
const qbConfig = getQueryBuilderConfig(config)
|
|
127
159
|
if (qbConfig) {
|
|
128
|
-
try {
|
|
160
|
+
try {
|
|
161
|
+
startQueryBuilder(qbConfig)
|
|
162
|
+
} catch (err) {
|
|
163
|
+
if (_env.NODE_ENV !== 'production') console.warn('[query-builder]', err)
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const buildContext = (req: Request, res: Response): OperationContext => {
|
|
169
|
+
const extReq = req as ExtendedRequest
|
|
170
|
+
const locals = readLocals(res)
|
|
171
|
+
return {
|
|
172
|
+
prisma: extReq.prisma,
|
|
173
|
+
postgres: extReq.postgres,
|
|
174
|
+
sqlite: extReq.sqlite,
|
|
175
|
+
parsedQuery: locals.parsedQuery,
|
|
176
|
+
body: req.body,
|
|
177
|
+
guardShape: locals.guardShape,
|
|
178
|
+
guardCaller: locals.guardCaller,
|
|
179
|
+
paginationConfig: locals.routeConfig?.pagination,
|
|
129
180
|
}
|
|
130
181
|
}
|
|
131
182
|
|
|
132
183
|
const parseQuery: RequestHandler = (req, res, next) => {
|
|
133
184
|
const rawQuery = req.query
|
|
134
185
|
if (rawQuery && Object.keys(rawQuery).length > 0) {
|
|
135
|
-
|
|
186
|
+
const parsed = parseQueryParams(rawQuery as Record<string, unknown>) as Record<string, unknown>
|
|
187
|
+
readLocals(res).parsedQuery = parsed
|
|
136
188
|
}
|
|
137
189
|
next()
|
|
138
190
|
}
|
|
@@ -141,154 +193,167 @@ export function ${routerFunctionName}<TCtx = unknown>(config: ${modelName}RouteC
|
|
|
141
193
|
if (!req.body || typeof req.body !== 'object' || Array.isArray(req.body)) {
|
|
142
194
|
return next({ status: 400, message: 'Request body must be a JSON object' })
|
|
143
195
|
}
|
|
144
|
-
res.
|
|
196
|
+
readLocals(res).parsedQuery = sanitizeKeys(req.body as Record<string, unknown>)
|
|
145
197
|
next()
|
|
146
198
|
}
|
|
147
199
|
|
|
148
|
-
const setShape = (opConfig:
|
|
200
|
+
const setShape = (opConfig: OperationConfigLike): RequestHandler => {
|
|
149
201
|
return (req, res, next) => {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
202
|
+
const locals = readLocals(res)
|
|
203
|
+
locals.routeConfig = config
|
|
204
|
+
const headerName = config.guard?.variantHeader || 'x-api-variant'
|
|
205
|
+
const headerValue = req.get(headerName)
|
|
206
|
+
const caller = config.guard?.resolveVariant?.(req) ?? headerValue ?? undefined
|
|
207
|
+
if (caller) locals.guardCaller = caller
|
|
208
|
+
if (opConfig.shape) locals.guardShape = opConfig.shape
|
|
209
|
+
next()
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const maybeProgressiveSSE = (
|
|
214
|
+
opConfig: OperationConfigLike,
|
|
215
|
+
coreFn: (ctx: OperationContext) => Promise<unknown>,
|
|
216
|
+
): RequestHandler => {
|
|
217
|
+
return async (req, res, next) => {
|
|
218
|
+
if (res.headersSent || res.writableEnded) return next()
|
|
219
|
+
if (req.method !== 'GET') return next()
|
|
220
|
+
if (!acceptsEventStream(req.headers.accept)) return next()
|
|
221
|
+
|
|
222
|
+
const locals = readLocals(res)
|
|
223
|
+
const variant = locals.guardCaller
|
|
224
|
+
const progressiveConfig = variant ? opConfig.progressive?.[variant] : undefined
|
|
225
|
+
|
|
226
|
+
try {
|
|
227
|
+
if (!progressiveConfig || progressiveConfig.enabled === false) {
|
|
228
|
+
await runSingleResultSSE({
|
|
229
|
+
req,
|
|
230
|
+
res,
|
|
231
|
+
coreQueryFn: () => coreFn(buildContext(req, res)),
|
|
232
|
+
})
|
|
233
|
+
return
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (!Array.isArray(progressiveConfig.stages)) {
|
|
237
|
+
return next({ status: 500, message: 'Progressive endpoint requires stages array' })
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const stageRegistry = opConfig.progressiveStages ?? {}
|
|
241
|
+
const missingStage = progressiveConfig.stages.find(
|
|
242
|
+
(name) => typeof stageRegistry[name] !== 'function',
|
|
243
|
+
)
|
|
244
|
+
if (missingStage) {
|
|
245
|
+
return next({ status: 500, message: 'Missing progressive stage: ' + missingStage })
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (typeof config.resolveContext !== 'function') {
|
|
249
|
+
return next({ status: 500, message: 'Progressive endpoint requires config.resolveContext' })
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const ctx = await config.resolveContext(req)
|
|
253
|
+
await runProgressiveEndpoint({
|
|
254
|
+
req,
|
|
255
|
+
res,
|
|
256
|
+
ctx,
|
|
257
|
+
prisma: (req as ExtendedRequest).prisma,
|
|
258
|
+
variant: variant as string,
|
|
259
|
+
stages: progressiveConfig.stages,
|
|
260
|
+
stageRegistry,
|
|
261
|
+
})
|
|
262
|
+
} catch (err) {
|
|
263
|
+
console.error('[progressive] dispatch error:', err)
|
|
264
|
+
if (!res.headersSent) {
|
|
265
|
+
return next({ status: 500, message: 'Internal server error' })
|
|
158
266
|
}
|
|
159
267
|
}
|
|
160
|
-
next()
|
|
161
268
|
}
|
|
162
269
|
}
|
|
163
270
|
|
|
164
271
|
const respond: RequestHandler = (_req, res) => {
|
|
165
|
-
const data = res.
|
|
166
|
-
if (data === undefined) {
|
|
167
|
-
return res.status(500).json({ message: 'No data set by handler' })
|
|
168
|
-
}
|
|
272
|
+
const data = readLocals(res).data
|
|
273
|
+
if (data === undefined) return res.status(500).json({ message: 'No data set by handler' })
|
|
169
274
|
return res.json(transformResult(data))
|
|
170
275
|
}
|
|
171
276
|
|
|
172
277
|
const respondCreated: RequestHandler = (_req, res) => {
|
|
173
|
-
const data = res.
|
|
174
|
-
if (data === undefined) {
|
|
175
|
-
return res.status(500).json({ message: 'No data set by handler' })
|
|
176
|
-
}
|
|
278
|
+
const data = readLocals(res).data
|
|
279
|
+
if (data === undefined) return res.status(500).json({ message: 'No data set by handler' })
|
|
177
280
|
return res.status(201).json(transformResult(data))
|
|
178
281
|
}
|
|
179
282
|
|
|
180
283
|
if (!openApiDisabled) {
|
|
181
284
|
const openapiJsonPath = basePath ? \`\${basePath}/openapi.json\` : '/openapi.json'
|
|
182
285
|
const openapiYamlPath = basePath ? \`\${basePath}/openapi.yaml\` : '/openapi.yaml'
|
|
183
|
-
|
|
184
286
|
router.get(openapiJsonPath, (_req, res) => {
|
|
185
|
-
const spec = buildModelOpenApi(
|
|
186
|
-
'${modelName}',
|
|
187
|
-
MODEL_FIELDS as any,
|
|
188
|
-
MODEL_ENUMS as any,
|
|
189
|
-
config,
|
|
190
|
-
{ format: 'json' }
|
|
191
|
-
)
|
|
287
|
+
const spec = buildModelOpenApi('${modelName}', MODEL_FIELDS as unknown as Parameters<typeof buildModelOpenApi>[1], MODEL_ENUMS as unknown as Parameters<typeof buildModelOpenApi>[2], config, { format: 'json' })
|
|
192
288
|
res.json(spec)
|
|
193
289
|
})
|
|
194
|
-
|
|
195
290
|
router.get(openapiYamlPath, (_req, res) => {
|
|
196
|
-
const spec = buildModelOpenApi(
|
|
197
|
-
'${modelName}',
|
|
198
|
-
MODEL_FIELDS as any,
|
|
199
|
-
MODEL_ENUMS as any,
|
|
200
|
-
config,
|
|
201
|
-
{ format: 'yaml' }
|
|
202
|
-
)
|
|
291
|
+
const spec = buildModelOpenApi('${modelName}', MODEL_FIELDS as unknown as Parameters<typeof buildModelOpenApi>[1], MODEL_ENUMS as unknown as Parameters<typeof buildModelOpenApi>[2], config, { format: 'yaml' })
|
|
203
292
|
res.type('application/yaml').send(spec as string)
|
|
204
293
|
})
|
|
205
294
|
}
|
|
206
295
|
|
|
207
296
|
if (config.enableAll || config.findFirst) {
|
|
208
|
-
const opConfig = config.findFirst
|
|
297
|
+
const opConfig: OperationConfigLike = (config.findFirst as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
209
298
|
const { before = [], after = [] } = opConfig
|
|
210
299
|
const path = basePath ? \`\${basePath}/first\` : '/first'
|
|
211
|
-
router.get(path, parseQuery, setShape(opConfig), ...before, ${prefix}FindFirst as RequestHandler, ...after, respond)
|
|
212
|
-
if (postReadsEnabled) {
|
|
213
|
-
router.post(path, parseBodyAsQuery, setShape(opConfig), ...before, ${prefix}FindFirst as RequestHandler, ...after, respond)
|
|
214
|
-
}
|
|
300
|
+
router.get(path, parseQuery, setShape(opConfig), ...before, maybeProgressiveSSE(opConfig, core.findFirst), ${prefix}FindFirst as RequestHandler, ...after, respond)
|
|
301
|
+
if (postReadsEnabled) router.post(path, parseBodyAsQuery, setShape(opConfig), ...before, ${prefix}FindFirst as RequestHandler, ...after, respond)
|
|
215
302
|
}
|
|
216
|
-
|
|
217
303
|
if (config.enableAll || config.findFirstOrThrow) {
|
|
218
|
-
const opConfig = config.findFirstOrThrow
|
|
304
|
+
const opConfig: OperationConfigLike = (config.findFirstOrThrow as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
219
305
|
const { before = [], after = [] } = opConfig
|
|
220
306
|
const path = basePath ? \`\${basePath}/first/strict\` : '/first/strict'
|
|
221
|
-
router.get(path, parseQuery, setShape(opConfig), ...before, ${prefix}FindFirstOrThrow as RequestHandler, ...after, respond)
|
|
222
|
-
if (postReadsEnabled) {
|
|
223
|
-
router.post(path, parseBodyAsQuery, setShape(opConfig), ...before, ${prefix}FindFirstOrThrow as RequestHandler, ...after, respond)
|
|
224
|
-
}
|
|
307
|
+
router.get(path, parseQuery, setShape(opConfig), ...before, maybeProgressiveSSE(opConfig, core.findFirstOrThrow), ${prefix}FindFirstOrThrow as RequestHandler, ...after, respond)
|
|
308
|
+
if (postReadsEnabled) router.post(path, parseBodyAsQuery, setShape(opConfig), ...before, ${prefix}FindFirstOrThrow as RequestHandler, ...after, respond)
|
|
225
309
|
}
|
|
226
|
-
|
|
227
310
|
if (config.enableAll || config.findManyPaginated) {
|
|
228
|
-
const opConfig = config.findManyPaginated
|
|
311
|
+
const opConfig: OperationConfigLike = (config.findManyPaginated as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
229
312
|
const { before = [], after = [] } = opConfig
|
|
230
313
|
const path = basePath ? \`\${basePath}/paginated\` : '/paginated'
|
|
231
|
-
router.get(path, parseQuery, setShape(opConfig), ...before, ${prefix}FindManyPaginated as RequestHandler, ...after, respond)
|
|
232
|
-
if (postReadsEnabled) {
|
|
233
|
-
router.post(path, parseBodyAsQuery, setShape(opConfig), ...before, ${prefix}FindManyPaginated as RequestHandler, ...after, respond)
|
|
234
|
-
}
|
|
314
|
+
router.get(path, parseQuery, setShape(opConfig), ...before, maybeProgressiveSSE(opConfig, core.findManyPaginated), ${prefix}FindManyPaginated as RequestHandler, ...after, respond)
|
|
315
|
+
if (postReadsEnabled) router.post(path, parseBodyAsQuery, setShape(opConfig), ...before, ${prefix}FindManyPaginated as RequestHandler, ...after, respond)
|
|
235
316
|
}
|
|
236
|
-
|
|
237
317
|
if (config.enableAll || config.aggregate) {
|
|
238
|
-
const opConfig = config.aggregate
|
|
318
|
+
const opConfig: OperationConfigLike = (config.aggregate as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
239
319
|
const { before = [], after = [] } = opConfig
|
|
240
320
|
const path = basePath ? \`\${basePath}/aggregate\` : '/aggregate'
|
|
241
|
-
router.get(path, parseQuery, setShape(opConfig), ...before, ${prefix}Aggregate as RequestHandler, ...after, respond)
|
|
242
|
-
if (postReadsEnabled) {
|
|
243
|
-
router.post(path, parseBodyAsQuery, setShape(opConfig), ...before, ${prefix}Aggregate as RequestHandler, ...after, respond)
|
|
244
|
-
}
|
|
321
|
+
router.get(path, parseQuery, setShape(opConfig), ...before, maybeProgressiveSSE(opConfig, core.aggregate), ${prefix}Aggregate as RequestHandler, ...after, respond)
|
|
322
|
+
if (postReadsEnabled) router.post(path, parseBodyAsQuery, setShape(opConfig), ...before, ${prefix}Aggregate as RequestHandler, ...after, respond)
|
|
245
323
|
}
|
|
246
|
-
|
|
247
324
|
if (config.enableAll || config.count) {
|
|
248
|
-
const opConfig = config.count
|
|
325
|
+
const opConfig: OperationConfigLike = (config.count as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
249
326
|
const { before = [], after = [] } = opConfig
|
|
250
327
|
const path = basePath ? \`\${basePath}/count\` : '/count'
|
|
251
|
-
router.get(path, parseQuery, setShape(opConfig), ...before, ${prefix}Count as RequestHandler, ...after, respond)
|
|
252
|
-
if (postReadsEnabled) {
|
|
253
|
-
router.post(path, parseBodyAsQuery, setShape(opConfig), ...before, ${prefix}Count as RequestHandler, ...after, respond)
|
|
254
|
-
}
|
|
328
|
+
router.get(path, parseQuery, setShape(opConfig), ...before, maybeProgressiveSSE(opConfig, core.count), ${prefix}Count as RequestHandler, ...after, respond)
|
|
329
|
+
if (postReadsEnabled) router.post(path, parseBodyAsQuery, setShape(opConfig), ...before, ${prefix}Count as RequestHandler, ...after, respond)
|
|
255
330
|
}
|
|
256
|
-
|
|
257
331
|
if (config.enableAll || config.groupBy) {
|
|
258
|
-
const opConfig = config.groupBy
|
|
332
|
+
const opConfig: OperationConfigLike = (config.groupBy as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
259
333
|
const { before = [], after = [] } = opConfig
|
|
260
334
|
const path = basePath ? \`\${basePath}/groupby\` : '/groupby'
|
|
261
|
-
router.get(path, parseQuery, setShape(opConfig), ...before, ${prefix}GroupBy as RequestHandler, ...after, respond)
|
|
262
|
-
if (postReadsEnabled) {
|
|
263
|
-
router.post(path, parseBodyAsQuery, setShape(opConfig), ...before, ${prefix}GroupBy as RequestHandler, ...after, respond)
|
|
264
|
-
}
|
|
335
|
+
router.get(path, parseQuery, setShape(opConfig), ...before, maybeProgressiveSSE(opConfig, core.groupBy), ${prefix}GroupBy as RequestHandler, ...after, respond)
|
|
336
|
+
if (postReadsEnabled) router.post(path, parseBodyAsQuery, setShape(opConfig), ...before, ${prefix}GroupBy as RequestHandler, ...after, respond)
|
|
265
337
|
}
|
|
266
|
-
|
|
267
338
|
if (config.enableAll || config.findUniqueOrThrow) {
|
|
268
|
-
const opConfig = config.findUniqueOrThrow
|
|
339
|
+
const opConfig: OperationConfigLike = (config.findUniqueOrThrow as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
269
340
|
const { before = [], after = [] } = opConfig
|
|
270
341
|
const path = basePath ? \`\${basePath}/unique/strict\` : '/unique/strict'
|
|
271
|
-
router.get(path, parseQuery, setShape(opConfig), ...before, ${prefix}FindUniqueOrThrow as RequestHandler, ...after, respond)
|
|
272
|
-
if (postReadsEnabled) {
|
|
273
|
-
router.post(path, parseBodyAsQuery, setShape(opConfig), ...before, ${prefix}FindUniqueOrThrow as RequestHandler, ...after, respond)
|
|
274
|
-
}
|
|
342
|
+
router.get(path, parseQuery, setShape(opConfig), ...before, maybeProgressiveSSE(opConfig, core.findUniqueOrThrow), ${prefix}FindUniqueOrThrow as RequestHandler, ...after, respond)
|
|
343
|
+
if (postReadsEnabled) router.post(path, parseBodyAsQuery, setShape(opConfig), ...before, ${prefix}FindUniqueOrThrow as RequestHandler, ...after, respond)
|
|
275
344
|
}
|
|
276
|
-
|
|
277
345
|
if (config.enableAll || config.findUnique) {
|
|
278
|
-
const opConfig = config.findUnique
|
|
346
|
+
const opConfig: OperationConfigLike = (config.findUnique as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
279
347
|
const { before = [], after = [] } = opConfig
|
|
280
348
|
const path = basePath ? \`\${basePath}/unique\` : '/unique'
|
|
281
|
-
router.get(path, parseQuery, setShape(opConfig), ...before, ${prefix}FindUnique as RequestHandler, ...after, respond)
|
|
282
|
-
if (postReadsEnabled) {
|
|
283
|
-
router.post(path, parseBodyAsQuery, setShape(opConfig), ...before, ${prefix}FindUnique as RequestHandler, ...after, respond)
|
|
284
|
-
}
|
|
349
|
+
router.get(path, parseQuery, setShape(opConfig), ...before, maybeProgressiveSSE(opConfig, core.findUnique), ${prefix}FindUnique as RequestHandler, ...after, respond)
|
|
350
|
+
if (postReadsEnabled) router.post(path, parseBodyAsQuery, setShape(opConfig), ...before, ${prefix}FindUnique as RequestHandler, ...after, respond)
|
|
285
351
|
}
|
|
286
|
-
|
|
287
352
|
if (config.enableAll || config.findMany) {
|
|
288
|
-
const opConfig = config.findMany
|
|
353
|
+
const opConfig: OperationConfigLike = (config.findMany as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
289
354
|
const { before = [], after = [] } = opConfig
|
|
290
355
|
const path = basePath || '/'
|
|
291
|
-
router.get(path, parseQuery, setShape(opConfig), ...before, ${prefix}FindMany as RequestHandler, ...after, respond)
|
|
356
|
+
router.get(path, parseQuery, setShape(opConfig), ...before, maybeProgressiveSSE(opConfig, core.findMany), ${prefix}FindMany as RequestHandler, ...after, respond)
|
|
292
357
|
if (postReadsEnabled) {
|
|
293
358
|
const postPath = basePath ? \`\${basePath}/read\` : '/read'
|
|
294
359
|
router.post(postPath, parseBodyAsQuery, setShape(opConfig), ...before, ${prefix}FindMany as RequestHandler, ...after, respond)
|
|
@@ -296,74 +361,65 @@ export function ${routerFunctionName}<TCtx = unknown>(config: ${modelName}RouteC
|
|
|
296
361
|
}
|
|
297
362
|
|
|
298
363
|
if (config.enableAll || config.createManyAndReturn) {
|
|
299
|
-
const opConfig = config.createManyAndReturn
|
|
364
|
+
const opConfig: OperationConfigLike = (config.createManyAndReturn as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
300
365
|
const { before = [], after = [] } = opConfig
|
|
301
366
|
const path = basePath ? \`\${basePath}/many/return\` : '/many/return'
|
|
302
367
|
router.post(path, setShape(opConfig), ...before, ${prefix}CreateManyAndReturn as RequestHandler, ...after, respondCreated)
|
|
303
368
|
}
|
|
304
|
-
|
|
305
369
|
if (config.enableAll || config.createMany) {
|
|
306
|
-
const opConfig = config.createMany
|
|
370
|
+
const opConfig: OperationConfigLike = (config.createMany as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
307
371
|
const { before = [], after = [] } = opConfig
|
|
308
372
|
const path = basePath ? \`\${basePath}/many\` : '/many'
|
|
309
373
|
router.post(path, setShape(opConfig), ...before, ${prefix}CreateMany as RequestHandler, ...after, respondCreated)
|
|
310
374
|
}
|
|
311
|
-
|
|
312
375
|
if (config.enableAll || config.create) {
|
|
313
|
-
const opConfig = config.create
|
|
376
|
+
const opConfig: OperationConfigLike = (config.create as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
314
377
|
const { before = [], after = [] } = opConfig
|
|
315
378
|
const path = basePath || '/'
|
|
316
379
|
router.post(path, setShape(opConfig), ...before, ${prefix}Create as RequestHandler, ...after, respondCreated)
|
|
317
380
|
}
|
|
318
|
-
|
|
319
381
|
if (config.enableAll || config.updateManyAndReturn) {
|
|
320
|
-
const opConfig = config.updateManyAndReturn
|
|
382
|
+
const opConfig: OperationConfigLike = (config.updateManyAndReturn as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
321
383
|
const { before = [], after = [] } = opConfig
|
|
322
384
|
const path = basePath ? \`\${basePath}/many/return\` : '/many/return'
|
|
323
385
|
router.put(path, setShape(opConfig), ...before, ${prefix}UpdateManyAndReturn as RequestHandler, ...after, respond)
|
|
324
386
|
}
|
|
325
|
-
|
|
326
387
|
if (config.enableAll || config.updateMany) {
|
|
327
|
-
const opConfig = config.updateMany
|
|
388
|
+
const opConfig: OperationConfigLike = (config.updateMany as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
328
389
|
const { before = [], after = [] } = opConfig
|
|
329
390
|
const path = basePath ? \`\${basePath}/many\` : '/many'
|
|
330
391
|
router.put(path, setShape(opConfig), ...before, ${prefix}UpdateMany as RequestHandler, ...after, respond)
|
|
331
392
|
}
|
|
332
|
-
|
|
333
393
|
if (config.enableAll || config.update) {
|
|
334
|
-
const opConfig = config.update
|
|
394
|
+
const opConfig: OperationConfigLike = (config.update as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
335
395
|
const { before = [], after = [] } = opConfig
|
|
336
396
|
const path = basePath || '/'
|
|
337
397
|
router.put(path, setShape(opConfig), ...before, ${prefix}Update as RequestHandler, ...after, respond)
|
|
338
398
|
}
|
|
339
|
-
|
|
340
399
|
if (config.enableAll || config.upsert) {
|
|
341
|
-
const opConfig = config.upsert
|
|
400
|
+
const opConfig: OperationConfigLike = (config.upsert as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
342
401
|
const { before = [], after = [] } = opConfig
|
|
343
402
|
const path = basePath || '/'
|
|
344
403
|
router.patch(path, setShape(opConfig), ...before, ${prefix}Upsert as RequestHandler, ...after, respond)
|
|
345
404
|
}
|
|
346
|
-
|
|
347
405
|
if (config.enableAll || config.deleteMany) {
|
|
348
|
-
const opConfig = config.deleteMany
|
|
406
|
+
const opConfig: OperationConfigLike = (config.deleteMany as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
349
407
|
const { before = [], after = [] } = opConfig
|
|
350
408
|
const path = basePath ? \`\${basePath}/many\` : '/many'
|
|
351
409
|
router.delete(path, setShape(opConfig), ...before, ${prefix}DeleteMany as RequestHandler, ...after, respond)
|
|
352
410
|
}
|
|
353
|
-
|
|
354
411
|
if (config.enableAll || config.delete) {
|
|
355
|
-
const opConfig = config.delete
|
|
412
|
+
const opConfig: OperationConfigLike = (config.delete as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
356
413
|
const { before = [], after = [] } = opConfig
|
|
357
414
|
const path = basePath || '/'
|
|
358
415
|
router.delete(path, setShape(opConfig), ...before, ${prefix}Delete as RequestHandler, ...after, respond)
|
|
359
416
|
}
|
|
360
417
|
|
|
361
|
-
router.use((err:
|
|
362
|
-
const
|
|
363
|
-
const
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
}
|
|
418
|
+
router.use((err: unknown, _req: Request, res: Response, next: NextFunction) => {
|
|
419
|
+
const e = err as { status?: number; message?: string }
|
|
420
|
+
const status = typeof e.status === 'number' ? e.status : 500
|
|
421
|
+
const message = e.message || 'Internal server error'
|
|
422
|
+
if (!res.headersSent) return res.status(status).json({ message })
|
|
367
423
|
next(err)
|
|
368
424
|
})
|
|
369
425
|
|