prisma-generator-express 1.62.4 → 1.63.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 +234 -95
- package/dist/generators/generateRouteConfigType.js +26 -6
- package/dist/generators/generateRouteConfigType.js.map +1 -1
- package/dist/generators/generateRouter.js +192 -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 +192 -27
- package/src/generators/generateRouterFastify.ts +100 -28
- package/src/generators/generateRouterHono.ts +104 -36
- package/src/utils/copyFiles.ts +2 -0
|
@@ -63,7 +63,7 @@ function emitReadOp(
|
|
|
63
63
|
: ''
|
|
64
64
|
|
|
65
65
|
return ` if (isEnabled(config.${meta.configKey})) {
|
|
66
|
-
const opConfig
|
|
66
|
+
const opConfig = opFor('${meta.configKey}')
|
|
67
67
|
const path = ${pathValue}
|
|
68
68
|
instance.get(path, handleRead(opConfig, ${handlerName}, parseQueryHook, '${opKind}'))
|
|
69
69
|
${postReadLine}
|
|
@@ -80,7 +80,7 @@ function emitWriteOp(
|
|
|
80
80
|
const opKind = opKindFor(meta.name)
|
|
81
81
|
|
|
82
82
|
return ` if (isEnabled(config.${meta.configKey})) {
|
|
83
|
-
const opConfig
|
|
83
|
+
const opConfig = opFor('${meta.configKey}')
|
|
84
84
|
const path = ${pathValue}
|
|
85
85
|
instance.${meta.method}(path, handleWrite(opConfig, ${handlerName}, '${opKind}'))
|
|
86
86
|
}`
|
|
@@ -133,10 +133,19 @@ import type {
|
|
|
133
133
|
import { parseQueryParams } from '../parseQueryParams${ext}'
|
|
134
134
|
import { sanitizeKeys, normalizePrefix, getEnv, isPlainObject } from '../misc${ext}'
|
|
135
135
|
import { buildModelOpenApi } from '../buildModelOpenApi${ext}'
|
|
136
|
-
import {
|
|
136
|
+
import {
|
|
137
|
+
normalizeOperation,
|
|
138
|
+
resolveOperationVariantKey,
|
|
139
|
+
validateCountSourceWhere,
|
|
140
|
+
validateOperationConfig,
|
|
141
|
+
validateUpdateEachConfig,
|
|
142
|
+
} from '../routeConfig${ext}'
|
|
143
|
+
import type { NormalizedOperationConfig } from '../routeConfig${ext}'
|
|
137
144
|
import type { OperationContext } from '../operationRuntime${ext}'
|
|
138
145
|
import { transformResult } from '../operationRuntime${ext}'
|
|
139
146
|
import { HttpError, mapError } from '../errorMapper${ext}'
|
|
147
|
+
import { formatGuardVariantResolutionError } from '../guardVariantError${ext}'
|
|
148
|
+
import type { GuardVariantResolution } from '../guardVariantRouting${ext}'
|
|
140
149
|
import { mergePaginationConfig } from '../pagination${ext}'
|
|
141
150
|
import { applyDroppedGuard } from '../projectionDefaults${ext}'
|
|
142
151
|
import type { OpKind } from '../projectionDefaults${ext}'
|
|
@@ -151,10 +160,23 @@ const DROP_GUARD = ${dropGuard} || _env.E2E === 'true'
|
|
|
151
160
|
type OperationConfigLike = {
|
|
152
161
|
before?: FastifyHookHandler[]
|
|
153
162
|
after?: FastifyHookHandler[]
|
|
154
|
-
shape?:
|
|
163
|
+
shape?: unknown
|
|
164
|
+
variants?: Record<
|
|
165
|
+
string,
|
|
166
|
+
{
|
|
167
|
+
shape?: unknown
|
|
168
|
+
before?: FastifyHookHandler[]
|
|
169
|
+
after?: FastifyHookHandler[]
|
|
170
|
+
}
|
|
171
|
+
>
|
|
155
172
|
pagination?: Partial<PaginationConfig>
|
|
156
173
|
}
|
|
157
174
|
|
|
175
|
+
type NormalizedOp = NormalizedOperationConfig<
|
|
176
|
+
FastifyHookHandler,
|
|
177
|
+
FastifyHookHandler
|
|
178
|
+
>
|
|
179
|
+
|
|
158
180
|
type FastifyExtended = FastifyRequest & {
|
|
159
181
|
prisma?: unknown
|
|
160
182
|
postgres?: unknown
|
|
@@ -163,14 +185,17 @@ type FastifyExtended = FastifyRequest & {
|
|
|
163
185
|
routeConfig?: { pagination?: PaginationConfig }
|
|
164
186
|
guardShape?: Record<string, unknown>
|
|
165
187
|
guardCaller?: string
|
|
188
|
+
guardVariantKey?: string
|
|
189
|
+
guardVariantFailure?: Extract<GuardVariantResolution, { ok: false }>
|
|
166
190
|
resultData?: unknown
|
|
167
191
|
resultStatus?: number
|
|
168
192
|
}
|
|
169
193
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
194
|
+
function normalizeFastifyOperation(
|
|
195
|
+
config: OperationConfigLike | undefined,
|
|
196
|
+
): NormalizedOp {
|
|
197
|
+
return normalizeOperation<FastifyHookHandler, FastifyHookHandler>(config)
|
|
198
|
+
}
|
|
174
199
|
|
|
175
200
|
function isQueryBuilderEnabled(config: RouteConfig): boolean {
|
|
176
201
|
if (config.queryBuilder === false) return false
|
|
@@ -210,7 +235,7 @@ function buildResolveContext(
|
|
|
210
235
|
|
|
211
236
|
function makeShapeHook(
|
|
212
237
|
config: ${modelName}RouteConfig,
|
|
213
|
-
opConfig:
|
|
238
|
+
opConfig: NormalizedOp,
|
|
214
239
|
opKind: OpKind,
|
|
215
240
|
): (request: FastifyRequest) => Promise<void> {
|
|
216
241
|
return async (request: FastifyRequest) => {
|
|
@@ -223,15 +248,27 @@ function makeShapeHook(
|
|
|
223
248
|
const caller = config.guard?.resolveVariant?.(request)
|
|
224
249
|
?? (Array.isArray(headerValue) ? headerValue[0] : headerValue)
|
|
225
250
|
?? undefined
|
|
226
|
-
if (caller) fx.guardCaller = caller
|
|
251
|
+
if (typeof caller === 'string') fx.guardCaller = caller
|
|
252
|
+
|
|
253
|
+
const resolution = resolveOperationVariantKey(opConfig.guardRouting, caller)
|
|
254
|
+
if (!resolution.ok) {
|
|
255
|
+
fx.guardVariantFailure = resolution
|
|
256
|
+
return
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const resolvedKey =
|
|
260
|
+
opConfig.guardRouting.kind === 'named'
|
|
261
|
+
? resolution.key
|
|
262
|
+
: undefined
|
|
263
|
+
if (resolvedKey !== undefined) fx.guardVariantKey = resolvedKey
|
|
227
264
|
|
|
228
|
-
if (opConfig.
|
|
265
|
+
if (opConfig.guardShape) {
|
|
229
266
|
if (!DROP_GUARD) {
|
|
230
|
-
fx.guardShape = opConfig.
|
|
267
|
+
fx.guardShape = opConfig.guardShape
|
|
231
268
|
} else {
|
|
232
269
|
await applyDroppedGuard(
|
|
233
|
-
opConfig.
|
|
234
|
-
|
|
270
|
+
opConfig.guardShape,
|
|
271
|
+
resolvedKey,
|
|
235
272
|
buildResolveContext(config, request),
|
|
236
273
|
opKind,
|
|
237
274
|
{
|
|
@@ -257,7 +294,7 @@ function makeShapeHook(
|
|
|
257
294
|
}
|
|
258
295
|
|
|
259
296
|
async function runHooks(
|
|
260
|
-
hooks: FastifyHookHandler[],
|
|
297
|
+
hooks: readonly FastifyHookHandler[],
|
|
261
298
|
request: FastifyRequest,
|
|
262
299
|
reply: FastifyReply,
|
|
263
300
|
): Promise<boolean> {
|
|
@@ -298,6 +335,12 @@ export async function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(
|
|
|
298
335
|
await fastify.register(async (instance) => {
|
|
299
336
|
const isEnabled = (value: unknown): boolean => value !== false && !!(config.enableAll || value)
|
|
300
337
|
|
|
338
|
+
const opFor = (key: string): NormalizedOp => {
|
|
339
|
+
const raw = (config as unknown as Record<string, unknown>)[key] as OperationConfigLike | undefined
|
|
340
|
+
validateOperationConfig(raw, '${modelName}.' + key)
|
|
341
|
+
return normalizeFastifyOperation(raw)
|
|
342
|
+
}
|
|
343
|
+
|
|
301
344
|
const customPrefix = normalizePrefix(config.customUrlPrefix || '')
|
|
302
345
|
const modelPrefix = config.addModelPrefix !== false ? '/${modelNameLower}' : ''
|
|
303
346
|
const basePath = customPrefix + modelPrefix
|
|
@@ -375,7 +418,7 @@ export async function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(
|
|
|
375
418
|
}
|
|
376
419
|
|
|
377
420
|
const handleRead = (
|
|
378
|
-
opConfig:
|
|
421
|
+
opConfig: NormalizedOp,
|
|
379
422
|
handlerFn: (req: FastifyRequest, reply: FastifyReply) => Promise<void>,
|
|
380
423
|
parseFn: (req: FastifyRequest) => void,
|
|
381
424
|
opKind: OpKind,
|
|
@@ -383,10 +426,24 @@ export async function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(
|
|
|
383
426
|
try {
|
|
384
427
|
parseFn(request)
|
|
385
428
|
await makeShapeHook(config, opConfig, opKind)(request)
|
|
386
|
-
|
|
387
|
-
|
|
429
|
+
if (await runHooks(opConfig.operationBefore, request, reply)) return
|
|
430
|
+
|
|
431
|
+
const fx = request as FastifyExtended
|
|
432
|
+
if (fx.guardVariantFailure) {
|
|
433
|
+
throw new HttpError(
|
|
434
|
+
400,
|
|
435
|
+
formatGuardVariantResolutionError(fx.guardVariantFailure),
|
|
436
|
+
)
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
const key = fx.guardVariantKey
|
|
440
|
+
const variantHooks =
|
|
441
|
+
key !== undefined ? opConfig.variantHooks[key] : undefined
|
|
442
|
+
|
|
443
|
+
if (await runHooks(variantHooks?.before ?? [], request, reply)) return
|
|
388
444
|
await handlerFn(request, reply)
|
|
389
|
-
if (await runHooks(after, request, reply)) return
|
|
445
|
+
if (await runHooks(variantHooks?.after ?? [], request, reply)) return
|
|
446
|
+
if (await runHooks(opConfig.operationAfter, request, reply)) return
|
|
390
447
|
sendResult(request, reply)
|
|
391
448
|
} catch (error: unknown) {
|
|
392
449
|
sendError(reply, error)
|
|
@@ -394,16 +451,30 @@ export async function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(
|
|
|
394
451
|
}
|
|
395
452
|
|
|
396
453
|
const handleWrite = (
|
|
397
|
-
opConfig:
|
|
454
|
+
opConfig: NormalizedOp,
|
|
398
455
|
handlerFn: (req: FastifyRequest, reply: FastifyReply) => Promise<void>,
|
|
399
456
|
opKind: OpKind,
|
|
400
457
|
) => async (request: FastifyRequest, reply: FastifyReply) => {
|
|
401
458
|
try {
|
|
402
459
|
await makeShapeHook(config, opConfig, opKind)(request)
|
|
403
|
-
|
|
404
|
-
|
|
460
|
+
if (await runHooks(opConfig.operationBefore, request, reply)) return
|
|
461
|
+
|
|
462
|
+
const fx = request as FastifyExtended
|
|
463
|
+
if (fx.guardVariantFailure) {
|
|
464
|
+
throw new HttpError(
|
|
465
|
+
400,
|
|
466
|
+
formatGuardVariantResolutionError(fx.guardVariantFailure),
|
|
467
|
+
)
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
const key = fx.guardVariantKey
|
|
471
|
+
const variantHooks =
|
|
472
|
+
key !== undefined ? opConfig.variantHooks[key] : undefined
|
|
473
|
+
|
|
474
|
+
if (await runHooks(variantHooks?.before ?? [], request, reply)) return
|
|
405
475
|
await handlerFn(request, reply)
|
|
406
|
-
if (await runHooks(after, request, reply)) return
|
|
476
|
+
if (await runHooks(variantHooks?.after ?? [], request, reply)) return
|
|
477
|
+
if (await runHooks(opConfig.operationAfter, request, reply)) return
|
|
407
478
|
sendResult(request, reply)
|
|
408
479
|
} catch (error: unknown) {
|
|
409
480
|
sendError(reply, error)
|
|
@@ -415,8 +486,10 @@ ${readOpBlocks}
|
|
|
415
486
|
${writeOpBlocks}
|
|
416
487
|
|
|
417
488
|
if (config.updateEach) {
|
|
418
|
-
const
|
|
419
|
-
|
|
489
|
+
const rawUpdateEach = config.updateEach as unknown as OperationConfigLike
|
|
490
|
+
validateUpdateEachConfig(rawUpdateEach, '${modelName}.updateEach')
|
|
491
|
+
const opConfig = normalizeFastifyOperation(rawUpdateEach)
|
|
492
|
+
if (opConfig.operationBefore.length === 0 && _env.NODE_ENV !== 'production') {
|
|
420
493
|
console.warn(
|
|
421
494
|
'[${modelName}Router] updateEach is enabled without a before hook. ' +
|
|
422
495
|
'This endpoint bypasses guard shapes and should be protected by authentication middleware.',
|
|
@@ -429,10 +502,9 @@ ${writeOpBlocks}
|
|
|
429
502
|
throw new HttpError(400, 'updateEach body must be an array of { where, data } items')
|
|
430
503
|
}
|
|
431
504
|
await makeShapeHook(config, opConfig, 'noop')(request)
|
|
432
|
-
|
|
433
|
-
if (await runHooks(before, request, reply)) return
|
|
505
|
+
if (await runHooks(opConfig.operationBefore, request, reply)) return
|
|
434
506
|
await ${modelName}UpdateEach(request, reply)
|
|
435
|
-
if (await runHooks(
|
|
507
|
+
if (await runHooks(opConfig.operationAfter, request, reply)) return
|
|
436
508
|
sendResult(request, reply)
|
|
437
509
|
} catch (error: unknown) {
|
|
438
510
|
sendError(reply, error)
|
|
@@ -130,9 +130,17 @@ import type {
|
|
|
130
130
|
import { parseQueryParams } from '../parseQueryParams${ext}'
|
|
131
131
|
import { normalizePrefix, getEnv, sanitizeKeys, isPlainObject } from '../misc${ext}'
|
|
132
132
|
import { buildModelOpenApi } from '../buildModelOpenApi${ext}'
|
|
133
|
-
import {
|
|
133
|
+
import {
|
|
134
|
+
normalizeOperation,
|
|
135
|
+
resolveOperationVariantKey,
|
|
136
|
+
validateCountSourceWhere,
|
|
137
|
+
validateOperationConfig,
|
|
138
|
+
validateUpdateEachConfig,
|
|
139
|
+
} from '../routeConfig${ext}'
|
|
140
|
+
import type { NormalizedOperationConfig } from '../routeConfig${ext}'
|
|
134
141
|
import { transformResult } from '../operationRuntime${ext}'
|
|
135
142
|
import { mapError } from '../errorMapper${ext}'
|
|
143
|
+
import { formatGuardVariantResolutionError } from '../guardVariantError${ext}'
|
|
136
144
|
import { mergePaginationConfig } from '../pagination${ext}'
|
|
137
145
|
import { applyDroppedGuard } from '../projectionDefaults${ext}'
|
|
138
146
|
import type { OpKind } from '../projectionDefaults${ext}'
|
|
@@ -154,14 +162,28 @@ type JsonLike =
|
|
|
154
162
|
type OperationConfigLike<TEnv extends HonoEnvBase> = {
|
|
155
163
|
before?: HonoBeforeHook<TEnv>[]
|
|
156
164
|
after?: HonoAfterHook<TEnv>[]
|
|
157
|
-
shape?:
|
|
165
|
+
shape?: unknown
|
|
166
|
+
variants?: Record<
|
|
167
|
+
string,
|
|
168
|
+
{
|
|
169
|
+
shape?: unknown
|
|
170
|
+
before?: HonoBeforeHook<TEnv>[]
|
|
171
|
+
after?: HonoAfterHook<TEnv>[]
|
|
172
|
+
}
|
|
173
|
+
>
|
|
158
174
|
pagination?: Partial<PaginationConfig>
|
|
159
175
|
}
|
|
160
176
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
177
|
+
type NormalizedOp<TEnv extends HonoEnvBase> = NormalizedOperationConfig<
|
|
178
|
+
HonoBeforeHook<TEnv>,
|
|
179
|
+
HonoAfterHook<TEnv>
|
|
180
|
+
>
|
|
181
|
+
|
|
182
|
+
function normalizeHonoOperation<TEnv extends HonoEnvBase>(
|
|
183
|
+
config: OperationConfigLike<TEnv> | undefined,
|
|
184
|
+
): NormalizedOp<TEnv> {
|
|
185
|
+
return normalizeOperation<HonoBeforeHook<TEnv>, HonoAfterHook<TEnv>>(config)
|
|
186
|
+
}
|
|
165
187
|
|
|
166
188
|
type HandlerContext = Context<{ Variables: HonoInternalVariables }>
|
|
167
189
|
|
|
@@ -213,7 +235,7 @@ async function parseUpdateEachBodyMiddleware(c: HandlerContext): Promise<void> {
|
|
|
213
235
|
|
|
214
236
|
function makeShapeMiddleware<TCtx, TPrisma, TEnv extends HonoEnvBase>(
|
|
215
237
|
config: ${modelName}RouteConfig<TCtx, TPrisma, TEnv>,
|
|
216
|
-
opConfig:
|
|
238
|
+
opConfig: NormalizedOp<TEnv>,
|
|
217
239
|
opKind: OpKind,
|
|
218
240
|
) {
|
|
219
241
|
return async (c: Context<GeneratedHonoEnv<TEnv>>): Promise<void> => {
|
|
@@ -223,19 +245,31 @@ function makeShapeMiddleware<TCtx, TPrisma, TEnv extends HonoEnvBase>(
|
|
|
223
245
|
const headerName = config.guard?.variantHeader || 'x-api-variant'
|
|
224
246
|
const headerValue = c.req.header(headerName)
|
|
225
247
|
const caller = config.guard?.resolveVariant?.(c) ?? headerValue ?? undefined
|
|
226
|
-
if (caller) c.set('guardCaller', caller)
|
|
248
|
+
if (typeof caller === 'string') c.set('guardCaller', caller)
|
|
249
|
+
|
|
250
|
+
const resolution = resolveOperationVariantKey(opConfig.guardRouting, caller)
|
|
251
|
+
if (!resolution.ok) {
|
|
252
|
+
c.set('guardVariantFailure', resolution)
|
|
253
|
+
return
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const resolvedKey =
|
|
257
|
+
opConfig.guardRouting.kind === 'named'
|
|
258
|
+
? resolution.key
|
|
259
|
+
: undefined
|
|
260
|
+
if (resolvedKey !== undefined) c.set('guardVariantKey', resolvedKey)
|
|
227
261
|
|
|
228
|
-
if (opConfig.
|
|
262
|
+
if (opConfig.guardShape) {
|
|
229
263
|
if (!DROP_GUARD) {
|
|
230
|
-
c.set('guardShape', opConfig.
|
|
264
|
+
c.set('guardShape', opConfig.guardShape)
|
|
231
265
|
} else {
|
|
232
266
|
const resolveCtx = typeof config.resolveContext === 'function'
|
|
233
267
|
? () => (config.resolveContext as (ctx: Context<GeneratedHonoEnv<TEnv>>) => unknown | Promise<unknown>)(c)
|
|
234
268
|
: undefined
|
|
235
269
|
|
|
236
270
|
await applyDroppedGuard(
|
|
237
|
-
opConfig.
|
|
238
|
-
|
|
271
|
+
opConfig.guardShape,
|
|
272
|
+
resolvedKey,
|
|
239
273
|
resolveCtx,
|
|
240
274
|
opKind,
|
|
241
275
|
{
|
|
@@ -267,7 +301,7 @@ function makeShapeMiddleware<TCtx, TPrisma, TEnv extends HonoEnvBase>(
|
|
|
267
301
|
}
|
|
268
302
|
|
|
269
303
|
async function runBeforeHooks<TEnv extends HonoEnvBase>(
|
|
270
|
-
hooks: HonoBeforeHook<TEnv>[],
|
|
304
|
+
hooks: readonly HonoBeforeHook<TEnv>[],
|
|
271
305
|
c: Context<GeneratedHonoEnv<TEnv>>,
|
|
272
306
|
): Promise<Response | undefined> {
|
|
273
307
|
for (const hook of hooks) {
|
|
@@ -278,7 +312,7 @@ async function runBeforeHooks<TEnv extends HonoEnvBase>(
|
|
|
278
312
|
}
|
|
279
313
|
|
|
280
314
|
async function runAfterHooks<TEnv extends HonoEnvBase>(
|
|
281
|
-
hooks: HonoAfterHook<TEnv>[],
|
|
315
|
+
hooks: readonly HonoAfterHook<TEnv>[],
|
|
282
316
|
c: Context<GeneratedHonoEnv<TEnv>>,
|
|
283
317
|
): Promise<Response | undefined> {
|
|
284
318
|
for (const hook of hooks) {
|
|
@@ -377,7 +411,7 @@ export function ${routerFunctionName}<TCtx = unknown, TPrisma = any, TEnv extend
|
|
|
377
411
|
}
|
|
378
412
|
|
|
379
413
|
const handleRead = (
|
|
380
|
-
opConfig:
|
|
414
|
+
opConfig: NormalizedOp<TEnv>,
|
|
381
415
|
handlerFn: (c: HandlerContext) => Promise<void>,
|
|
382
416
|
parseFn: (c: HandlerContext) => Promise<void>,
|
|
383
417
|
opKind: OpKind,
|
|
@@ -385,12 +419,27 @@ export function ${routerFunctionName}<TCtx = unknown, TPrisma = any, TEnv extend
|
|
|
385
419
|
try {
|
|
386
420
|
await parseFn(c as unknown as HandlerContext)
|
|
387
421
|
await makeShapeMiddleware<TCtx, TPrisma, TEnv>(config, opConfig, opKind)(c)
|
|
388
|
-
const
|
|
389
|
-
|
|
390
|
-
|
|
422
|
+
const operationBefore = await runBeforeHooks<TEnv>(opConfig.operationBefore, c)
|
|
423
|
+
if (operationBefore) return operationBefore
|
|
424
|
+
|
|
425
|
+
const failure = c.get('guardVariantFailure')
|
|
426
|
+
if (failure) {
|
|
427
|
+
throw new HTTPException(400, {
|
|
428
|
+
message: formatGuardVariantResolutionError(failure),
|
|
429
|
+
})
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
const key = c.get('guardVariantKey')
|
|
433
|
+
const variantHooks =
|
|
434
|
+
key !== undefined ? opConfig.variantHooks[key] : undefined
|
|
435
|
+
|
|
436
|
+
const variantBefore = await runBeforeHooks<TEnv>(variantHooks?.before ?? [], c)
|
|
437
|
+
if (variantBefore) return variantBefore
|
|
391
438
|
await handlerFn(c as unknown as HandlerContext)
|
|
392
|
-
const
|
|
393
|
-
if (
|
|
439
|
+
const variantAfter = await runAfterHooks<TEnv>(variantHooks?.after ?? [], c)
|
|
440
|
+
if (variantAfter) return variantAfter
|
|
441
|
+
const operationAfter = await runAfterHooks<TEnv>(opConfig.operationAfter, c)
|
|
442
|
+
if (operationAfter) return operationAfter
|
|
394
443
|
return sendResult(c as unknown as HandlerContext)
|
|
395
444
|
} catch (error: unknown) {
|
|
396
445
|
return sendError(c as unknown as HandlerContext, error)
|
|
@@ -398,28 +447,46 @@ export function ${routerFunctionName}<TCtx = unknown, TPrisma = any, TEnv extend
|
|
|
398
447
|
}
|
|
399
448
|
|
|
400
449
|
const handleWrite = (
|
|
401
|
-
opConfig:
|
|
450
|
+
opConfig: NormalizedOp<TEnv>,
|
|
402
451
|
handlerFn: (c: HandlerContext) => Promise<void>,
|
|
403
452
|
opKind: OpKind,
|
|
404
453
|
) => async (c: Context<GeneratedHonoEnv<TEnv>>): Promise<Response> => {
|
|
405
454
|
try {
|
|
406
455
|
await parseWriteBodyMiddleware(c as unknown as HandlerContext)
|
|
407
456
|
await makeShapeMiddleware<TCtx, TPrisma, TEnv>(config, opConfig, opKind)(c)
|
|
408
|
-
const
|
|
409
|
-
|
|
410
|
-
|
|
457
|
+
const operationBefore = await runBeforeHooks<TEnv>(opConfig.operationBefore, c)
|
|
458
|
+
if (operationBefore) return operationBefore
|
|
459
|
+
|
|
460
|
+
const failure = c.get('guardVariantFailure')
|
|
461
|
+
if (failure) {
|
|
462
|
+
throw new HTTPException(400, {
|
|
463
|
+
message: formatGuardVariantResolutionError(failure),
|
|
464
|
+
})
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
const key = c.get('guardVariantKey')
|
|
468
|
+
const variantHooks =
|
|
469
|
+
key !== undefined ? opConfig.variantHooks[key] : undefined
|
|
470
|
+
|
|
471
|
+
const variantBefore = await runBeforeHooks<TEnv>(variantHooks?.before ?? [], c)
|
|
472
|
+
if (variantBefore) return variantBefore
|
|
411
473
|
await handlerFn(c as unknown as HandlerContext)
|
|
412
|
-
const
|
|
413
|
-
if (
|
|
474
|
+
const variantAfter = await runAfterHooks<TEnv>(variantHooks?.after ?? [], c)
|
|
475
|
+
if (variantAfter) return variantAfter
|
|
476
|
+
const operationAfter = await runAfterHooks<TEnv>(opConfig.operationAfter, c)
|
|
477
|
+
if (operationAfter) return operationAfter
|
|
414
478
|
return sendResult(c as unknown as HandlerContext)
|
|
415
479
|
} catch (error: unknown) {
|
|
416
480
|
return sendError(c as unknown as HandlerContext, error)
|
|
417
481
|
}
|
|
418
482
|
}
|
|
419
483
|
|
|
420
|
-
const opFor = <K extends keyof ${modelName}RouteConfig<TCtx, TPrisma, TEnv>>(
|
|
421
|
-
|
|
422
|
-
|
|
484
|
+
const opFor = <K extends keyof ${modelName}RouteConfig<TCtx, TPrisma, TEnv>>(
|
|
485
|
+
key: K,
|
|
486
|
+
): NormalizedOp<TEnv> => {
|
|
487
|
+
const raw = config[key] as unknown as OperationConfigLike<TEnv> | undefined
|
|
488
|
+
validateOperationConfig(raw, '${modelName}.' + String(key))
|
|
489
|
+
return normalizeHonoOperation(raw)
|
|
423
490
|
}
|
|
424
491
|
|
|
425
492
|
${readOpBlocks}
|
|
@@ -427,8 +494,10 @@ ${readOpBlocks}
|
|
|
427
494
|
${writeOpBlocks}
|
|
428
495
|
|
|
429
496
|
if (config.updateEach) {
|
|
430
|
-
const
|
|
431
|
-
|
|
497
|
+
const rawUpdateEach = config.updateEach as unknown as OperationConfigLike<TEnv>
|
|
498
|
+
validateUpdateEachConfig(rawUpdateEach, '${modelName}.updateEach')
|
|
499
|
+
const opConfig = normalizeHonoOperation(rawUpdateEach)
|
|
500
|
+
if (opConfig.operationBefore.length === 0 && _env.NODE_ENV !== 'production') {
|
|
432
501
|
console.warn(
|
|
433
502
|
'[${modelName}Router] updateEach is enabled without a before hook. ' +
|
|
434
503
|
'This endpoint bypasses guard shapes and should be protected by authentication middleware.',
|
|
@@ -439,12 +508,11 @@ ${writeOpBlocks}
|
|
|
439
508
|
try {
|
|
440
509
|
await parseUpdateEachBodyMiddleware(c as unknown as HandlerContext)
|
|
441
510
|
await makeShapeMiddleware<TCtx, TPrisma, TEnv>(config, opConfig, 'noop')(c)
|
|
442
|
-
const
|
|
443
|
-
|
|
444
|
-
if (beforeResp) return beforeResp
|
|
511
|
+
const beforeResponse = await runBeforeHooks<TEnv>(opConfig.operationBefore, c)
|
|
512
|
+
if (beforeResponse) return beforeResponse
|
|
445
513
|
await ${modelName}UpdateEach(c as unknown as HandlerContext)
|
|
446
|
-
const
|
|
447
|
-
if (
|
|
514
|
+
const afterResponse = await runAfterHooks<TEnv>(opConfig.operationAfter, c)
|
|
515
|
+
if (afterResponse) return afterResponse
|
|
448
516
|
return sendResult(c as unknown as HandlerContext)
|
|
449
517
|
} catch (error: unknown) {
|
|
450
518
|
return sendError(c as unknown as HandlerContext, error)
|