prisma-generator-express 1.62.4 → 1.63.1
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 +234 -95
- package/dist/generators/generateRouteConfigType.js +26 -6
- package/dist/generators/generateRouteConfigType.js.map +1 -1
- package/dist/generators/generateRouter.js +196 -27
- package/dist/generators/generateRouter.js.map +1 -1
- package/dist/generators/generateRouterFastify.js +100 -28
- package/dist/generators/generateRouterFastify.js.map +1 -1
- package/dist/generators/generateRouterHono.js +104 -36
- package/dist/generators/generateRouterHono.js.map +1 -1
- package/dist/utils/copyFiles.js +2 -0
- package/dist/utils/copyFiles.js.map +1 -1
- package/package.json +1 -1
- package/src/copy/docsRenderer.ts +1 -0
- package/src/copy/guardVariantError.ts +28 -0
- package/src/copy/guardVariantRouting.ts +109 -0
- package/src/copy/projectionDefaults.ts +5 -6
- package/src/copy/routeConfig.hono.ts +15 -5
- package/src/copy/routeConfig.ts +220 -27
- package/src/generators/generateRouteConfigType.ts +37 -6
- package/src/generators/generateRouter.ts +196 -27
- package/src/generators/generateRouterFastify.ts +100 -28
- package/src/generators/generateRouterHono.ts +104 -36
- package/src/utils/copyFiles.ts +2 -0
|
@@ -52,14 +52,36 @@ function emitReadOp(meta, modelName) {
|
|
|
52
52
|
const postReadBlock = meta.supportsPostRead
|
|
53
53
|
? ` if (postReadsEnabled) {
|
|
54
54
|
const postPath = ${meta.name === 'findMany' ? "basePath ? `${basePath}/read` : '/read'" : `path`}
|
|
55
|
-
router.post(
|
|
55
|
+
router.post(
|
|
56
|
+
postPath,
|
|
57
|
+
parseBodyAsQuery,
|
|
58
|
+
setShape(opConfig, '${opKind}'),
|
|
59
|
+
...opConfig.operationBefore,
|
|
60
|
+
requireVariantKey(),
|
|
61
|
+
variantBeforeDispatcher(opConfig),
|
|
62
|
+
${handlerName} as RequestHandler,
|
|
63
|
+
variantAfterDispatcher(opConfig),
|
|
64
|
+
...opConfig.operationAfter,
|
|
65
|
+
respond,
|
|
66
|
+
)
|
|
56
67
|
}`
|
|
57
68
|
: '';
|
|
58
69
|
return ` if (isEnabled(config.${meta.configKey})) {
|
|
59
|
-
const opConfig
|
|
60
|
-
const { before = [], after = [] } = opConfig
|
|
70
|
+
const opConfig = opFor('${meta.configKey}')
|
|
61
71
|
const path = ${pathValue}
|
|
62
|
-
router.get(
|
|
72
|
+
router.get(
|
|
73
|
+
path,
|
|
74
|
+
parseQuery,
|
|
75
|
+
setShape(opConfig, '${opKind}'),
|
|
76
|
+
...opConfig.operationBefore,
|
|
77
|
+
requireVariantKey(),
|
|
78
|
+
variantBeforeDispatcher(opConfig),
|
|
79
|
+
maybeProgressiveSSE(opConfig, core.${meta.coreName}, '${meta.name}'),
|
|
80
|
+
${handlerName} as RequestHandler,
|
|
81
|
+
variantAfterDispatcher(opConfig),
|
|
82
|
+
...opConfig.operationAfter,
|
|
83
|
+
respond,
|
|
84
|
+
)
|
|
63
85
|
${postReadBlock}
|
|
64
86
|
}`;
|
|
65
87
|
}
|
|
@@ -70,10 +92,19 @@ function emitWriteOp(meta, modelName) {
|
|
|
70
92
|
const respondFn = meta.successStatus === 201 ? 'respondCreated' : 'respond';
|
|
71
93
|
const opKind = opKindFor(meta.name);
|
|
72
94
|
return ` if (isEnabled(config.${meta.configKey})) {
|
|
73
|
-
const opConfig
|
|
74
|
-
const { before = [], after = [] } = opConfig
|
|
95
|
+
const opConfig = opFor('${meta.configKey}')
|
|
75
96
|
const path = ${pathValue}
|
|
76
|
-
router.${meta.method}(
|
|
97
|
+
router.${meta.method}(
|
|
98
|
+
path,
|
|
99
|
+
setShape(opConfig, '${opKind}'),
|
|
100
|
+
...opConfig.operationBefore,
|
|
101
|
+
requireVariantKey(),
|
|
102
|
+
variantBeforeDispatcher(opConfig),
|
|
103
|
+
${handlerName} as RequestHandler,
|
|
104
|
+
variantAfterDispatcher(opConfig),
|
|
105
|
+
...opConfig.operationAfter,
|
|
106
|
+
${respondFn},
|
|
107
|
+
)
|
|
77
108
|
}`;
|
|
78
109
|
}
|
|
79
110
|
function generateRouterFunction({ model, enums, guardShapesImport, importStyle, writeStrategy, findManyPaginatedMode, dropGuard, }) {
|
|
@@ -107,10 +138,19 @@ import type {
|
|
|
107
138
|
import { parseQueryParams } from '../parseQueryParams${ext}'
|
|
108
139
|
import { sanitizeKeys, normalizePrefix, getEnv, isPlainObject } from '../misc${ext}'
|
|
109
140
|
import { buildModelOpenApi } from '../buildModelOpenApi${ext}'
|
|
110
|
-
import {
|
|
141
|
+
import {
|
|
142
|
+
normalizeOperation,
|
|
143
|
+
resolveOperationVariantKey,
|
|
144
|
+
validateCountSourceWhere,
|
|
145
|
+
validateOperationConfig,
|
|
146
|
+
validateUpdateEachConfig,
|
|
147
|
+
} from '../routeConfig${ext}'
|
|
148
|
+
import type { NormalizedOperationConfig } from '../routeConfig${ext}'
|
|
111
149
|
import type { OperationContext } from '../operationRuntime${ext}'
|
|
112
150
|
import { transformResult } from '../operationRuntime${ext}'
|
|
113
151
|
import { HttpError, mapError } from '../errorMapper${ext}'
|
|
152
|
+
import { formatGuardVariantResolutionError } from '../guardVariantError${ext}'
|
|
153
|
+
import type { GuardVariantResolution } from '../guardVariantRouting${ext}'
|
|
114
154
|
import { mergePaginationConfig } from '../pagination${ext}'
|
|
115
155
|
import {
|
|
116
156
|
acceptsEventStream,
|
|
@@ -134,12 +174,25 @@ const DROP_GUARD = ${dropGuard} || _env.E2E === 'true'
|
|
|
134
174
|
type OperationConfigLike = {
|
|
135
175
|
before?: RequestHandler[]
|
|
136
176
|
after?: RequestHandler[]
|
|
137
|
-
shape?:
|
|
177
|
+
shape?: unknown
|
|
178
|
+
variants?: Record<
|
|
179
|
+
string,
|
|
180
|
+
{
|
|
181
|
+
shape?: unknown
|
|
182
|
+
before?: RequestHandler[]
|
|
183
|
+
after?: RequestHandler[]
|
|
184
|
+
}
|
|
185
|
+
>
|
|
138
186
|
pagination?: Partial<PaginationConfig>
|
|
139
187
|
progressive?: Record<string, ProgressiveVariantConfig>
|
|
140
188
|
progressiveStages?: Record<string, ProgressiveStage<unknown>>
|
|
141
189
|
}
|
|
142
190
|
|
|
191
|
+
type NormalizedOp = NormalizedOperationConfig<RequestHandler, RequestHandler> & {
|
|
192
|
+
progressive?: Record<string, ProgressiveVariantConfig>
|
|
193
|
+
progressiveStages?: Record<string, ProgressiveStage<unknown>>
|
|
194
|
+
}
|
|
195
|
+
|
|
143
196
|
type ExtendedRequest = Request & {
|
|
144
197
|
prisma?: unknown
|
|
145
198
|
postgres?: unknown
|
|
@@ -151,13 +204,20 @@ type LocalsBag = {
|
|
|
151
204
|
routeConfig?: { pagination?: PaginationConfig }
|
|
152
205
|
guardShape?: Record<string, unknown>
|
|
153
206
|
guardCaller?: string
|
|
207
|
+
guardVariantKey?: string
|
|
208
|
+
guardVariantFailure?: Extract<GuardVariantResolution, { ok: false }>
|
|
154
209
|
data?: unknown
|
|
155
210
|
}
|
|
156
211
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
212
|
+
function normalizeExpressOperation(
|
|
213
|
+
config: OperationConfigLike | undefined,
|
|
214
|
+
): NormalizedOp {
|
|
215
|
+
return {
|
|
216
|
+
...normalizeOperation<RequestHandler, RequestHandler>(config),
|
|
217
|
+
progressive: config?.progressive,
|
|
218
|
+
progressiveStages: config?.progressiveStages,
|
|
219
|
+
}
|
|
220
|
+
}
|
|
161
221
|
|
|
162
222
|
function isQueryBuilderEnabled(config: { queryBuilder?: QueryBuilderConfig | false }): boolean {
|
|
163
223
|
if (config.queryBuilder === false) return false
|
|
@@ -176,6 +236,91 @@ function readLocals(res: Response): LocalsBag {
|
|
|
176
236
|
return res.locals as LocalsBag
|
|
177
237
|
}
|
|
178
238
|
|
|
239
|
+
function runHandlerSequence(
|
|
240
|
+
handlers: readonly RequestHandler[],
|
|
241
|
+
req: Request,
|
|
242
|
+
res: Response,
|
|
243
|
+
done: (error?: unknown) => void,
|
|
244
|
+
): void {
|
|
245
|
+
let index = 0
|
|
246
|
+
|
|
247
|
+
const dispatch = (error?: unknown): void => {
|
|
248
|
+
if (error !== undefined) {
|
|
249
|
+
done(error)
|
|
250
|
+
return
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (res.writableEnded || res.destroyed) return
|
|
254
|
+
|
|
255
|
+
const handler = handlers[index++]
|
|
256
|
+
if (!handler) {
|
|
257
|
+
done()
|
|
258
|
+
return
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
let settled = false
|
|
262
|
+
const next = (nextError?: unknown): void => {
|
|
263
|
+
if (settled) return
|
|
264
|
+
settled = true
|
|
265
|
+
dispatch(nextError)
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
try {
|
|
269
|
+
const result: unknown = handler(req, res, next)
|
|
270
|
+
if (
|
|
271
|
+
typeof result === 'object' &&
|
|
272
|
+
result !== null &&
|
|
273
|
+
typeof (result as Promise<unknown>).then === 'function'
|
|
274
|
+
) {
|
|
275
|
+
void (result as Promise<unknown>).catch((promiseError) => {
|
|
276
|
+
if (settled) return
|
|
277
|
+
settled = true
|
|
278
|
+
dispatch(promiseError)
|
|
279
|
+
})
|
|
280
|
+
}
|
|
281
|
+
} catch (handlerError) {
|
|
282
|
+
if (settled) return
|
|
283
|
+
settled = true
|
|
284
|
+
dispatch(handlerError)
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
dispatch()
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function variantBeforeDispatcher(opConfig: NormalizedOp): RequestHandler {
|
|
292
|
+
return (req, res, next) => {
|
|
293
|
+
const key = readLocals(res).guardVariantKey
|
|
294
|
+
const hooks =
|
|
295
|
+
key !== undefined
|
|
296
|
+
? (opConfig.variantHooks[key]?.before ?? [])
|
|
297
|
+
: []
|
|
298
|
+
runHandlerSequence(hooks, req, res, next)
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function variantAfterDispatcher(opConfig: NormalizedOp): RequestHandler {
|
|
303
|
+
return (req, res, next) => {
|
|
304
|
+
const key = readLocals(res).guardVariantKey
|
|
305
|
+
const hooks =
|
|
306
|
+
key !== undefined
|
|
307
|
+
? (opConfig.variantHooks[key]?.after ?? [])
|
|
308
|
+
: []
|
|
309
|
+
runHandlerSequence(hooks, req, res, next)
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function requireVariantKey(): RequestHandler {
|
|
314
|
+
return (_req, res, next) => {
|
|
315
|
+
const failure = readLocals(res).guardVariantFailure
|
|
316
|
+
if (!failure) {
|
|
317
|
+
next()
|
|
318
|
+
return
|
|
319
|
+
}
|
|
320
|
+
next(new HttpError(400, formatGuardVariantResolutionError(failure)))
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
179
324
|
export function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(config: ${modelName}RouteConfig<TCtx, TPrisma> = {}) {
|
|
180
325
|
validateCountSourceWhere(config.pagination?.countSource, '${modelName} pagination')
|
|
181
326
|
validateCountSourceWhere(
|
|
@@ -187,6 +332,12 @@ export function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(config: ${m
|
|
|
187
332
|
|
|
188
333
|
const isEnabled = (value: unknown): boolean => value !== false && !!(config.enableAll || value)
|
|
189
334
|
|
|
335
|
+
const opFor = (key: string): NormalizedOp => {
|
|
336
|
+
const raw = (config as unknown as Record<string, unknown>)[key] as OperationConfigLike | undefined
|
|
337
|
+
validateOperationConfig(raw, '${modelName}.' + key)
|
|
338
|
+
return normalizeExpressOperation(raw)
|
|
339
|
+
}
|
|
340
|
+
|
|
190
341
|
const customPrefix = normalizePrefix(config.customUrlPrefix || '')
|
|
191
342
|
const modelPrefix = config.addModelPrefix !== false ? '/${modelNameLower}' : ''
|
|
192
343
|
const basePath = customPrefix + modelPrefix
|
|
@@ -273,7 +424,7 @@ export function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(config: ${m
|
|
|
273
424
|
next()
|
|
274
425
|
}
|
|
275
426
|
|
|
276
|
-
const setShape = (opConfig:
|
|
427
|
+
const setShape = (opConfig: NormalizedOp, opKind: OpKind): RequestHandler => {
|
|
277
428
|
return async (req, res, next) => {
|
|
278
429
|
try {
|
|
279
430
|
const locals = readLocals(res)
|
|
@@ -281,17 +432,32 @@ export function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(config: ${m
|
|
|
281
432
|
if (merged) {
|
|
282
433
|
locals.routeConfig = { pagination: merged }
|
|
283
434
|
}
|
|
435
|
+
|
|
284
436
|
const headerName = config.guard?.variantHeader || 'x-api-variant'
|
|
285
437
|
const headerValue = req.get(headerName)
|
|
286
438
|
const caller = config.guard?.resolveVariant?.(req) ?? headerValue ?? undefined
|
|
287
|
-
if (caller) locals.guardCaller = caller
|
|
288
|
-
|
|
439
|
+
if (typeof caller === 'string') locals.guardCaller = caller
|
|
440
|
+
|
|
441
|
+
const resolution = resolveOperationVariantKey(opConfig.guardRouting, caller)
|
|
442
|
+
if (!resolution.ok) {
|
|
443
|
+
locals.guardVariantFailure = resolution
|
|
444
|
+
next()
|
|
445
|
+
return
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
const resolvedKey =
|
|
449
|
+
opConfig.guardRouting.kind === 'named'
|
|
450
|
+
? resolution.key
|
|
451
|
+
: undefined
|
|
452
|
+
if (resolvedKey !== undefined) locals.guardVariantKey = resolvedKey
|
|
453
|
+
|
|
454
|
+
if (opConfig.guardShape) {
|
|
289
455
|
if (!DROP_GUARD) {
|
|
290
|
-
locals.guardShape = opConfig.
|
|
456
|
+
locals.guardShape = opConfig.guardShape
|
|
291
457
|
} else {
|
|
292
458
|
await applyDroppedGuard(
|
|
293
|
-
opConfig.
|
|
294
|
-
|
|
459
|
+
opConfig.guardShape,
|
|
460
|
+
resolvedKey,
|
|
295
461
|
buildResolveContext(req),
|
|
296
462
|
opKind,
|
|
297
463
|
{
|
|
@@ -313,6 +479,7 @@ export function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(config: ${m
|
|
|
313
479
|
)
|
|
314
480
|
}
|
|
315
481
|
}
|
|
482
|
+
|
|
316
483
|
next()
|
|
317
484
|
} catch (err) {
|
|
318
485
|
next(mapError(err))
|
|
@@ -321,7 +488,7 @@ export function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(config: ${m
|
|
|
321
488
|
}
|
|
322
489
|
|
|
323
490
|
const maybeProgressiveSSE = (
|
|
324
|
-
opConfig:
|
|
491
|
+
opConfig: NormalizedOp,
|
|
325
492
|
coreFn: (ctx: OperationContext) => Promise<unknown>,
|
|
326
493
|
baseOp: string,
|
|
327
494
|
): RequestHandler => {
|
|
@@ -331,8 +498,9 @@ export function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(config: ${m
|
|
|
331
498
|
if (!acceptsEventStream(req.headers.accept)) return next()
|
|
332
499
|
|
|
333
500
|
const locals = readLocals(res)
|
|
334
|
-
const variant = locals.guardCaller
|
|
335
|
-
const progressiveConfig =
|
|
501
|
+
const variant = locals.guardVariantKey ?? locals.guardCaller
|
|
502
|
+
const progressiveConfig =
|
|
503
|
+
variant !== undefined ? opConfig.progressive?.[variant] : undefined
|
|
336
504
|
|
|
337
505
|
try {
|
|
338
506
|
if (!progressiveConfig || progressiveConfig.enabled === false) {
|
|
@@ -460,19 +628,20 @@ ${readOpBlocks}
|
|
|
460
628
|
${writeOpBlocks}
|
|
461
629
|
|
|
462
630
|
if (config.updateEach) {
|
|
463
|
-
const
|
|
464
|
-
|
|
631
|
+
const rawUpdateEach = config.updateEach as unknown as OperationConfigLike
|
|
632
|
+
validateUpdateEachConfig(rawUpdateEach, '${modelName}.updateEach')
|
|
633
|
+
const opConfig = normalizeExpressOperation(rawUpdateEach)
|
|
634
|
+
if (opConfig.operationBefore.length === 0 && _env.NODE_ENV !== 'production') {
|
|
465
635
|
console.warn(
|
|
466
636
|
'[${modelName}Router] updateEach is enabled without a before hook. ' +
|
|
467
637
|
'This endpoint bypasses guard shapes and should be protected by authentication middleware.',
|
|
468
638
|
)
|
|
469
639
|
}
|
|
470
|
-
const { before = [], after = [] } = opConfig
|
|
471
640
|
const path = basePath ? \`\${basePath}/each\` : '/each'
|
|
472
641
|
router.post(
|
|
473
642
|
path,
|
|
474
643
|
setShape(opConfig, 'noop'),
|
|
475
|
-
...
|
|
644
|
+
...opConfig.operationBefore,
|
|
476
645
|
async (req: Request, res: Response, next: NextFunction) => {
|
|
477
646
|
try {
|
|
478
647
|
if (!Array.isArray(req.body)) {
|
|
@@ -485,7 +654,7 @@ ${writeOpBlocks}
|
|
|
485
654
|
next(mapError(err))
|
|
486
655
|
}
|
|
487
656
|
},
|
|
488
|
-
...
|
|
657
|
+
...opConfig.operationAfter,
|
|
489
658
|
respond,
|
|
490
659
|
)
|
|
491
660
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateRouter.js","sourceRoot":"","sources":["../../src/generators/generateRouter.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"generateRouter.js","sourceRoot":"","sources":["../../src/generators/generateRouter.ts"],"names":[],"mappings":"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"}
|
|
@@ -56,7 +56,7 @@ function emitReadOp(meta, modelName) {
|
|
|
56
56
|
: ` if (postReadsEnabled) instance.post(path, handleRead(opConfig, ${handlerName}, parseBodyAsQueryHook, '${opKind}'))`
|
|
57
57
|
: '';
|
|
58
58
|
return ` if (isEnabled(config.${meta.configKey})) {
|
|
59
|
-
const opConfig
|
|
59
|
+
const opConfig = opFor('${meta.configKey}')
|
|
60
60
|
const path = ${pathValue}
|
|
61
61
|
instance.get(path, handleRead(opConfig, ${handlerName}, parseQueryHook, '${opKind}'))
|
|
62
62
|
${postReadLine}
|
|
@@ -68,7 +68,7 @@ function emitWriteOp(meta, modelName) {
|
|
|
68
68
|
const pathValue = pathExpr(meta.pathSuffix);
|
|
69
69
|
const opKind = opKindFor(meta.name);
|
|
70
70
|
return ` if (isEnabled(config.${meta.configKey})) {
|
|
71
|
-
const opConfig
|
|
71
|
+
const opConfig = opFor('${meta.configKey}')
|
|
72
72
|
const path = ${pathValue}
|
|
73
73
|
instance.${meta.method}(path, handleWrite(opConfig, ${handlerName}, '${opKind}'))
|
|
74
74
|
}`;
|
|
@@ -100,10 +100,19 @@ import type {
|
|
|
100
100
|
import { parseQueryParams } from '../parseQueryParams${ext}'
|
|
101
101
|
import { sanitizeKeys, normalizePrefix, getEnv, isPlainObject } from '../misc${ext}'
|
|
102
102
|
import { buildModelOpenApi } from '../buildModelOpenApi${ext}'
|
|
103
|
-
import {
|
|
103
|
+
import {
|
|
104
|
+
normalizeOperation,
|
|
105
|
+
resolveOperationVariantKey,
|
|
106
|
+
validateCountSourceWhere,
|
|
107
|
+
validateOperationConfig,
|
|
108
|
+
validateUpdateEachConfig,
|
|
109
|
+
} from '../routeConfig${ext}'
|
|
110
|
+
import type { NormalizedOperationConfig } from '../routeConfig${ext}'
|
|
104
111
|
import type { OperationContext } from '../operationRuntime${ext}'
|
|
105
112
|
import { transformResult } from '../operationRuntime${ext}'
|
|
106
113
|
import { HttpError, mapError } from '../errorMapper${ext}'
|
|
114
|
+
import { formatGuardVariantResolutionError } from '../guardVariantError${ext}'
|
|
115
|
+
import type { GuardVariantResolution } from '../guardVariantRouting${ext}'
|
|
107
116
|
import { mergePaginationConfig } from '../pagination${ext}'
|
|
108
117
|
import { applyDroppedGuard } from '../projectionDefaults${ext}'
|
|
109
118
|
import type { OpKind } from '../projectionDefaults${ext}'
|
|
@@ -118,10 +127,23 @@ const DROP_GUARD = ${dropGuard} || _env.E2E === 'true'
|
|
|
118
127
|
type OperationConfigLike = {
|
|
119
128
|
before?: FastifyHookHandler[]
|
|
120
129
|
after?: FastifyHookHandler[]
|
|
121
|
-
shape?:
|
|
130
|
+
shape?: unknown
|
|
131
|
+
variants?: Record<
|
|
132
|
+
string,
|
|
133
|
+
{
|
|
134
|
+
shape?: unknown
|
|
135
|
+
before?: FastifyHookHandler[]
|
|
136
|
+
after?: FastifyHookHandler[]
|
|
137
|
+
}
|
|
138
|
+
>
|
|
122
139
|
pagination?: Partial<PaginationConfig>
|
|
123
140
|
}
|
|
124
141
|
|
|
142
|
+
type NormalizedOp = NormalizedOperationConfig<
|
|
143
|
+
FastifyHookHandler,
|
|
144
|
+
FastifyHookHandler
|
|
145
|
+
>
|
|
146
|
+
|
|
125
147
|
type FastifyExtended = FastifyRequest & {
|
|
126
148
|
prisma?: unknown
|
|
127
149
|
postgres?: unknown
|
|
@@ -130,14 +152,17 @@ type FastifyExtended = FastifyRequest & {
|
|
|
130
152
|
routeConfig?: { pagination?: PaginationConfig }
|
|
131
153
|
guardShape?: Record<string, unknown>
|
|
132
154
|
guardCaller?: string
|
|
155
|
+
guardVariantKey?: string
|
|
156
|
+
guardVariantFailure?: Extract<GuardVariantResolution, { ok: false }>
|
|
133
157
|
resultData?: unknown
|
|
134
158
|
resultStatus?: number
|
|
135
159
|
}
|
|
136
160
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
161
|
+
function normalizeFastifyOperation(
|
|
162
|
+
config: OperationConfigLike | undefined,
|
|
163
|
+
): NormalizedOp {
|
|
164
|
+
return normalizeOperation<FastifyHookHandler, FastifyHookHandler>(config)
|
|
165
|
+
}
|
|
141
166
|
|
|
142
167
|
function isQueryBuilderEnabled(config: RouteConfig): boolean {
|
|
143
168
|
if (config.queryBuilder === false) return false
|
|
@@ -177,7 +202,7 @@ function buildResolveContext(
|
|
|
177
202
|
|
|
178
203
|
function makeShapeHook(
|
|
179
204
|
config: ${modelName}RouteConfig,
|
|
180
|
-
opConfig:
|
|
205
|
+
opConfig: NormalizedOp,
|
|
181
206
|
opKind: OpKind,
|
|
182
207
|
): (request: FastifyRequest) => Promise<void> {
|
|
183
208
|
return async (request: FastifyRequest) => {
|
|
@@ -190,15 +215,27 @@ function makeShapeHook(
|
|
|
190
215
|
const caller = config.guard?.resolveVariant?.(request)
|
|
191
216
|
?? (Array.isArray(headerValue) ? headerValue[0] : headerValue)
|
|
192
217
|
?? undefined
|
|
193
|
-
if (caller) fx.guardCaller = caller
|
|
218
|
+
if (typeof caller === 'string') fx.guardCaller = caller
|
|
219
|
+
|
|
220
|
+
const resolution = resolveOperationVariantKey(opConfig.guardRouting, caller)
|
|
221
|
+
if (!resolution.ok) {
|
|
222
|
+
fx.guardVariantFailure = resolution
|
|
223
|
+
return
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const resolvedKey =
|
|
227
|
+
opConfig.guardRouting.kind === 'named'
|
|
228
|
+
? resolution.key
|
|
229
|
+
: undefined
|
|
230
|
+
if (resolvedKey !== undefined) fx.guardVariantKey = resolvedKey
|
|
194
231
|
|
|
195
|
-
if (opConfig.
|
|
232
|
+
if (opConfig.guardShape) {
|
|
196
233
|
if (!DROP_GUARD) {
|
|
197
|
-
fx.guardShape = opConfig.
|
|
234
|
+
fx.guardShape = opConfig.guardShape
|
|
198
235
|
} else {
|
|
199
236
|
await applyDroppedGuard(
|
|
200
|
-
opConfig.
|
|
201
|
-
|
|
237
|
+
opConfig.guardShape,
|
|
238
|
+
resolvedKey,
|
|
202
239
|
buildResolveContext(config, request),
|
|
203
240
|
opKind,
|
|
204
241
|
{
|
|
@@ -224,7 +261,7 @@ function makeShapeHook(
|
|
|
224
261
|
}
|
|
225
262
|
|
|
226
263
|
async function runHooks(
|
|
227
|
-
hooks: FastifyHookHandler[],
|
|
264
|
+
hooks: readonly FastifyHookHandler[],
|
|
228
265
|
request: FastifyRequest,
|
|
229
266
|
reply: FastifyReply,
|
|
230
267
|
): Promise<boolean> {
|
|
@@ -265,6 +302,12 @@ export async function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(
|
|
|
265
302
|
await fastify.register(async (instance) => {
|
|
266
303
|
const isEnabled = (value: unknown): boolean => value !== false && !!(config.enableAll || value)
|
|
267
304
|
|
|
305
|
+
const opFor = (key: string): NormalizedOp => {
|
|
306
|
+
const raw = (config as unknown as Record<string, unknown>)[key] as OperationConfigLike | undefined
|
|
307
|
+
validateOperationConfig(raw, '${modelName}.' + key)
|
|
308
|
+
return normalizeFastifyOperation(raw)
|
|
309
|
+
}
|
|
310
|
+
|
|
268
311
|
const customPrefix = normalizePrefix(config.customUrlPrefix || '')
|
|
269
312
|
const modelPrefix = config.addModelPrefix !== false ? '/${modelNameLower}' : ''
|
|
270
313
|
const basePath = customPrefix + modelPrefix
|
|
@@ -342,7 +385,7 @@ export async function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(
|
|
|
342
385
|
}
|
|
343
386
|
|
|
344
387
|
const handleRead = (
|
|
345
|
-
opConfig:
|
|
388
|
+
opConfig: NormalizedOp,
|
|
346
389
|
handlerFn: (req: FastifyRequest, reply: FastifyReply) => Promise<void>,
|
|
347
390
|
parseFn: (req: FastifyRequest) => void,
|
|
348
391
|
opKind: OpKind,
|
|
@@ -350,10 +393,24 @@ export async function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(
|
|
|
350
393
|
try {
|
|
351
394
|
parseFn(request)
|
|
352
395
|
await makeShapeHook(config, opConfig, opKind)(request)
|
|
353
|
-
|
|
354
|
-
|
|
396
|
+
if (await runHooks(opConfig.operationBefore, request, reply)) return
|
|
397
|
+
|
|
398
|
+
const fx = request as FastifyExtended
|
|
399
|
+
if (fx.guardVariantFailure) {
|
|
400
|
+
throw new HttpError(
|
|
401
|
+
400,
|
|
402
|
+
formatGuardVariantResolutionError(fx.guardVariantFailure),
|
|
403
|
+
)
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
const key = fx.guardVariantKey
|
|
407
|
+
const variantHooks =
|
|
408
|
+
key !== undefined ? opConfig.variantHooks[key] : undefined
|
|
409
|
+
|
|
410
|
+
if (await runHooks(variantHooks?.before ?? [], request, reply)) return
|
|
355
411
|
await handlerFn(request, reply)
|
|
356
|
-
if (await runHooks(after, request, reply)) return
|
|
412
|
+
if (await runHooks(variantHooks?.after ?? [], request, reply)) return
|
|
413
|
+
if (await runHooks(opConfig.operationAfter, request, reply)) return
|
|
357
414
|
sendResult(request, reply)
|
|
358
415
|
} catch (error: unknown) {
|
|
359
416
|
sendError(reply, error)
|
|
@@ -361,16 +418,30 @@ export async function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(
|
|
|
361
418
|
}
|
|
362
419
|
|
|
363
420
|
const handleWrite = (
|
|
364
|
-
opConfig:
|
|
421
|
+
opConfig: NormalizedOp,
|
|
365
422
|
handlerFn: (req: FastifyRequest, reply: FastifyReply) => Promise<void>,
|
|
366
423
|
opKind: OpKind,
|
|
367
424
|
) => async (request: FastifyRequest, reply: FastifyReply) => {
|
|
368
425
|
try {
|
|
369
426
|
await makeShapeHook(config, opConfig, opKind)(request)
|
|
370
|
-
|
|
371
|
-
|
|
427
|
+
if (await runHooks(opConfig.operationBefore, request, reply)) return
|
|
428
|
+
|
|
429
|
+
const fx = request as FastifyExtended
|
|
430
|
+
if (fx.guardVariantFailure) {
|
|
431
|
+
throw new HttpError(
|
|
432
|
+
400,
|
|
433
|
+
formatGuardVariantResolutionError(fx.guardVariantFailure),
|
|
434
|
+
)
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
const key = fx.guardVariantKey
|
|
438
|
+
const variantHooks =
|
|
439
|
+
key !== undefined ? opConfig.variantHooks[key] : undefined
|
|
440
|
+
|
|
441
|
+
if (await runHooks(variantHooks?.before ?? [], request, reply)) return
|
|
372
442
|
await handlerFn(request, reply)
|
|
373
|
-
if (await runHooks(after, request, reply)) return
|
|
443
|
+
if (await runHooks(variantHooks?.after ?? [], request, reply)) return
|
|
444
|
+
if (await runHooks(opConfig.operationAfter, request, reply)) return
|
|
374
445
|
sendResult(request, reply)
|
|
375
446
|
} catch (error: unknown) {
|
|
376
447
|
sendError(reply, error)
|
|
@@ -382,8 +453,10 @@ ${readOpBlocks}
|
|
|
382
453
|
${writeOpBlocks}
|
|
383
454
|
|
|
384
455
|
if (config.updateEach) {
|
|
385
|
-
const
|
|
386
|
-
|
|
456
|
+
const rawUpdateEach = config.updateEach as unknown as OperationConfigLike
|
|
457
|
+
validateUpdateEachConfig(rawUpdateEach, '${modelName}.updateEach')
|
|
458
|
+
const opConfig = normalizeFastifyOperation(rawUpdateEach)
|
|
459
|
+
if (opConfig.operationBefore.length === 0 && _env.NODE_ENV !== 'production') {
|
|
387
460
|
console.warn(
|
|
388
461
|
'[${modelName}Router] updateEach is enabled without a before hook. ' +
|
|
389
462
|
'This endpoint bypasses guard shapes and should be protected by authentication middleware.',
|
|
@@ -396,10 +469,9 @@ ${writeOpBlocks}
|
|
|
396
469
|
throw new HttpError(400, 'updateEach body must be an array of { where, data } items')
|
|
397
470
|
}
|
|
398
471
|
await makeShapeHook(config, opConfig, 'noop')(request)
|
|
399
|
-
|
|
400
|
-
if (await runHooks(before, request, reply)) return
|
|
472
|
+
if (await runHooks(opConfig.operationBefore, request, reply)) return
|
|
401
473
|
await ${modelName}UpdateEach(request, reply)
|
|
402
|
-
if (await runHooks(
|
|
474
|
+
if (await runHooks(opConfig.operationAfter, request, reply)) return
|
|
403
475
|
sendResult(request, reply)
|
|
404
476
|
} catch (error: unknown) {
|
|
405
477
|
sendError(reply, error)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateRouterFastify.js","sourceRoot":"","sources":["../../src/generators/generateRouterFastify.ts"],"names":[],"mappings":";;AAwFA,
|
|
1
|
+
{"version":3,"file":"generateRouterFastify.js","sourceRoot":"","sources":["../../src/generators/generateRouterFastify.ts"],"names":[],"mappings":"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"}
|