prisma-generator-express 1.62.3 → 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 +245 -44
- 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 +246 -44
- package/src/generators/generateRouterFastify.ts +100 -28
- package/src/generators/generateRouterHono.ts +104 -36
- package/src/utils/copyFiles.ts +2 -0
|
@@ -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)
|