prisma-generator-express 1.62.2 → 1.62.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/generators/generateRouterFastify.js +66 -30
- package/dist/generators/generateRouterFastify.js.map +1 -1
- package/dist/generators/generateRouterHono.js +66 -27
- package/dist/generators/generateRouterHono.js.map +1 -1
- package/package.json +1 -1
- package/src/copy/projectionDefaults.ts +94 -1
- package/src/generators/generateRouterFastify.ts +75 -32
- package/src/generators/generateRouterHono.ts +67 -27
|
@@ -9,22 +9,56 @@ function pathExpr(suffix) {
|
|
|
9
9
|
return `basePath || '/'`;
|
|
10
10
|
return `\`\${basePath}${suffix}\``;
|
|
11
11
|
}
|
|
12
|
+
function opKindFor(opName) {
|
|
13
|
+
switch (opName) {
|
|
14
|
+
case 'findUnique':
|
|
15
|
+
case 'findUniqueOrThrow':
|
|
16
|
+
return 'readUnique';
|
|
17
|
+
case 'findMany':
|
|
18
|
+
case 'findFirst':
|
|
19
|
+
case 'findFirstOrThrow':
|
|
20
|
+
case 'findManyPaginated':
|
|
21
|
+
case 'count':
|
|
22
|
+
case 'aggregate':
|
|
23
|
+
case 'groupBy':
|
|
24
|
+
return 'read';
|
|
25
|
+
case 'create':
|
|
26
|
+
return 'create';
|
|
27
|
+
case 'createMany':
|
|
28
|
+
case 'createManyAndReturn':
|
|
29
|
+
return 'createMany';
|
|
30
|
+
case 'update':
|
|
31
|
+
return 'update';
|
|
32
|
+
case 'updateMany':
|
|
33
|
+
case 'updateManyAndReturn':
|
|
34
|
+
return 'updateMany';
|
|
35
|
+
case 'upsert':
|
|
36
|
+
return 'upsert';
|
|
37
|
+
case 'delete':
|
|
38
|
+
return 'delete';
|
|
39
|
+
case 'deleteMany':
|
|
40
|
+
return 'deleteMany';
|
|
41
|
+
default:
|
|
42
|
+
return 'noop';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
12
45
|
function emitReadOp(meta, modelName) {
|
|
13
46
|
const c = meta.name.charAt(0).toUpperCase() + meta.name.slice(1);
|
|
14
47
|
const handlerName = `${modelName}${c}`;
|
|
15
48
|
const pathValue = pathExpr(meta.pathSuffix);
|
|
49
|
+
const opKind = opKindFor(meta.name);
|
|
16
50
|
const postReadLine = meta.supportsPostRead
|
|
17
51
|
? meta.name === 'findMany'
|
|
18
52
|
? ` if (postReadsEnabled) {
|
|
19
53
|
const postPath = basePath ? \`\${basePath}/read\` : '/read'
|
|
20
|
-
instance.post(postPath, handleRead(opConfig, ${handlerName}, parseBodyAsQueryHook))
|
|
54
|
+
instance.post(postPath, handleRead(opConfig, ${handlerName}, parseBodyAsQueryHook, '${opKind}'))
|
|
21
55
|
}`
|
|
22
|
-
: ` if (postReadsEnabled) instance.post(path, handleRead(opConfig, ${handlerName}, parseBodyAsQueryHook))`
|
|
56
|
+
: ` if (postReadsEnabled) instance.post(path, handleRead(opConfig, ${handlerName}, parseBodyAsQueryHook, '${opKind}'))`
|
|
23
57
|
: '';
|
|
24
58
|
return ` if (isEnabled(config.${meta.configKey})) {
|
|
25
59
|
const opConfig: OperationConfigLike = (config.${meta.configKey} as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
26
60
|
const path = ${pathValue}
|
|
27
|
-
instance.get(path, handleRead(opConfig, ${handlerName}, parseQueryHook))
|
|
61
|
+
instance.get(path, handleRead(opConfig, ${handlerName}, parseQueryHook, '${opKind}'))
|
|
28
62
|
${postReadLine}
|
|
29
63
|
}`;
|
|
30
64
|
}
|
|
@@ -32,10 +66,11 @@ function emitWriteOp(meta, modelName) {
|
|
|
32
66
|
const c = meta.name.charAt(0).toUpperCase() + meta.name.slice(1);
|
|
33
67
|
const handlerName = `${modelName}${c}`;
|
|
34
68
|
const pathValue = pathExpr(meta.pathSuffix);
|
|
69
|
+
const opKind = opKindFor(meta.name);
|
|
35
70
|
return ` if (isEnabled(config.${meta.configKey})) {
|
|
36
71
|
const opConfig: OperationConfigLike = (config.${meta.configKey} as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
37
72
|
const path = ${pathValue}
|
|
38
|
-
instance.${meta.method}(path, handleWrite(opConfig, ${handlerName}))
|
|
73
|
+
instance.${meta.method}(path, handleWrite(opConfig, ${handlerName}, '${opKind}'))
|
|
39
74
|
}`;
|
|
40
75
|
}
|
|
41
76
|
function generateFastifyRouterFunction({ model, enums, guardShapesImport, importStyle, writeStrategy, findManyPaginatedMode, dropGuard, }) {
|
|
@@ -70,10 +105,8 @@ import type { OperationContext } from '../operationRuntime${ext}'
|
|
|
70
105
|
import { transformResult } from '../operationRuntime${ext}'
|
|
71
106
|
import { HttpError, mapError } from '../errorMapper${ext}'
|
|
72
107
|
import { mergePaginationConfig } from '../pagination${ext}'
|
|
73
|
-
import {
|
|
74
|
-
|
|
75
|
-
applyProjectionToTarget,
|
|
76
|
-
} from '../projectionDefaults${ext}'
|
|
108
|
+
import { applyDroppedGuard } from '../projectionDefaults${ext}'
|
|
109
|
+
import type { OpKind } from '../projectionDefaults${ext}'
|
|
77
110
|
import { MODEL_FIELDS, MODEL_ENUMS } from './${modelName}Metadata${ext}'
|
|
78
111
|
|
|
79
112
|
${(0, generateRouteConfigType_1.generateRouteConfigType)(modelName, 'FastifyHookHandler', guardShapesImport, importStyle, 'fastify')}
|
|
@@ -145,45 +178,46 @@ function buildResolveContext(
|
|
|
145
178
|
function makeShapeHook(
|
|
146
179
|
config: ${modelName}RouteConfig,
|
|
147
180
|
opConfig: OperationConfigLike,
|
|
148
|
-
|
|
181
|
+
opKind: OpKind,
|
|
149
182
|
): (request: FastifyRequest) => Promise<void> {
|
|
150
183
|
return async (request: FastifyRequest) => {
|
|
151
184
|
const fx = request as FastifyExtended
|
|
152
185
|
const merged = mergePaginationConfig(config.pagination, opConfig.pagination)
|
|
153
|
-
if (merged) {
|
|
154
|
-
|
|
155
|
-
}
|
|
186
|
+
if (merged) fx.routeConfig = { pagination: merged }
|
|
187
|
+
|
|
156
188
|
const headerName = (config.guard?.variantHeader || 'x-api-variant').toLowerCase()
|
|
157
189
|
const headerValue = request.headers[headerName]
|
|
158
190
|
const caller = config.guard?.resolveVariant?.(request)
|
|
159
191
|
?? (Array.isArray(headerValue) ? headerValue[0] : headerValue)
|
|
160
192
|
?? undefined
|
|
161
|
-
if (caller)
|
|
162
|
-
|
|
163
|
-
}
|
|
193
|
+
if (caller) fx.guardCaller = caller
|
|
194
|
+
|
|
164
195
|
if (opConfig.shape) {
|
|
165
196
|
if (!DROP_GUARD) {
|
|
166
197
|
fx.guardShape = opConfig.shape
|
|
167
198
|
} else {
|
|
168
|
-
|
|
199
|
+
await applyDroppedGuard(
|
|
169
200
|
opConfig.shape,
|
|
170
201
|
caller,
|
|
171
202
|
buildResolveContext(config, request),
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
203
|
+
opKind,
|
|
204
|
+
{
|
|
205
|
+
readQuery: fx.parsedQuery,
|
|
206
|
+
writeBody: isPlainObject(request.body)
|
|
207
|
+
? (request.body as Record<string, unknown>)
|
|
208
|
+
: undefined,
|
|
209
|
+
},
|
|
210
|
+
() => {
|
|
175
211
|
if (!fx.parsedQuery) fx.parsedQuery = {}
|
|
176
|
-
|
|
177
|
-
}
|
|
212
|
+
return fx.parsedQuery
|
|
213
|
+
},
|
|
214
|
+
() => {
|
|
178
215
|
if (!isPlainObject(request.body)) {
|
|
179
216
|
;(request as unknown as { body: unknown }).body = {}
|
|
180
217
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
)
|
|
185
|
-
}
|
|
186
|
-
}
|
|
218
|
+
return request.body as Record<string, unknown>
|
|
219
|
+
},
|
|
220
|
+
)
|
|
187
221
|
}
|
|
188
222
|
}
|
|
189
223
|
}
|
|
@@ -311,10 +345,11 @@ export async function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(
|
|
|
311
345
|
opConfig: OperationConfigLike,
|
|
312
346
|
handlerFn: (req: FastifyRequest, reply: FastifyReply) => Promise<void>,
|
|
313
347
|
parseFn: (req: FastifyRequest) => void,
|
|
348
|
+
opKind: OpKind,
|
|
314
349
|
) => async (request: FastifyRequest, reply: FastifyReply) => {
|
|
315
350
|
try {
|
|
316
351
|
parseFn(request)
|
|
317
|
-
await makeShapeHook(config, opConfig,
|
|
352
|
+
await makeShapeHook(config, opConfig, opKind)(request)
|
|
318
353
|
const { before = [], after = [] } = opConfig
|
|
319
354
|
if (await runHooks(before, request, reply)) return
|
|
320
355
|
await handlerFn(request, reply)
|
|
@@ -328,9 +363,10 @@ export async function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(
|
|
|
328
363
|
const handleWrite = (
|
|
329
364
|
opConfig: OperationConfigLike,
|
|
330
365
|
handlerFn: (req: FastifyRequest, reply: FastifyReply) => Promise<void>,
|
|
366
|
+
opKind: OpKind,
|
|
331
367
|
) => async (request: FastifyRequest, reply: FastifyReply) => {
|
|
332
368
|
try {
|
|
333
|
-
await makeShapeHook(config, opConfig,
|
|
369
|
+
await makeShapeHook(config, opConfig, opKind)(request)
|
|
334
370
|
const { before = [], after = [] } = opConfig
|
|
335
371
|
if (await runHooks(before, request, reply)) return
|
|
336
372
|
await handlerFn(request, reply)
|
|
@@ -359,7 +395,7 @@ ${writeOpBlocks}
|
|
|
359
395
|
if (!Array.isArray(request.body)) {
|
|
360
396
|
throw new HttpError(400, 'updateEach body must be an array of { where, data } items')
|
|
361
397
|
}
|
|
362
|
-
await makeShapeHook(config, opConfig, '
|
|
398
|
+
await makeShapeHook(config, opConfig, 'noop')(request)
|
|
363
399
|
const { before = [], after = [] } = opConfig
|
|
364
400
|
if (await runHooks(before, request, reply)) return
|
|
365
401
|
await ${modelName}UpdateEach(request, reply)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateRouterFastify.js","sourceRoot":"","sources":["../../src/generators/generateRouterFastify.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"generateRouterFastify.js","sourceRoot":"","sources":["../../src/generators/generateRouterFastify.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,22 +9,56 @@ function pathExpr(suffix) {
|
|
|
9
9
|
return `basePath || '/'`;
|
|
10
10
|
return `\`\${basePath}${suffix}\``;
|
|
11
11
|
}
|
|
12
|
+
function opKindFor(opName) {
|
|
13
|
+
switch (opName) {
|
|
14
|
+
case 'findUnique':
|
|
15
|
+
case 'findUniqueOrThrow':
|
|
16
|
+
return 'readUnique';
|
|
17
|
+
case 'findMany':
|
|
18
|
+
case 'findFirst':
|
|
19
|
+
case 'findFirstOrThrow':
|
|
20
|
+
case 'findManyPaginated':
|
|
21
|
+
case 'count':
|
|
22
|
+
case 'aggregate':
|
|
23
|
+
case 'groupBy':
|
|
24
|
+
return 'read';
|
|
25
|
+
case 'create':
|
|
26
|
+
return 'create';
|
|
27
|
+
case 'createMany':
|
|
28
|
+
case 'createManyAndReturn':
|
|
29
|
+
return 'createMany';
|
|
30
|
+
case 'update':
|
|
31
|
+
return 'update';
|
|
32
|
+
case 'updateMany':
|
|
33
|
+
case 'updateManyAndReturn':
|
|
34
|
+
return 'updateMany';
|
|
35
|
+
case 'upsert':
|
|
36
|
+
return 'upsert';
|
|
37
|
+
case 'delete':
|
|
38
|
+
return 'delete';
|
|
39
|
+
case 'deleteMany':
|
|
40
|
+
return 'deleteMany';
|
|
41
|
+
default:
|
|
42
|
+
return 'noop';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
12
45
|
function emitReadOp(meta, modelName) {
|
|
13
46
|
const c = meta.name.charAt(0).toUpperCase() + meta.name.slice(1);
|
|
14
47
|
const handlerName = `${modelName}${c}`;
|
|
15
48
|
const pathValue = pathExpr(meta.pathSuffix);
|
|
49
|
+
const opKind = opKindFor(meta.name);
|
|
16
50
|
const postReadLine = meta.supportsPostRead
|
|
17
51
|
? meta.name === 'findMany'
|
|
18
52
|
? ` if (postReadsEnabled) {
|
|
19
53
|
const postPath = basePath ? \`\${basePath}/read\` : '/read'
|
|
20
|
-
app.post(postPath, handleRead(opConfig, ${handlerName}, parseBodyAsQueryMiddleware))
|
|
54
|
+
app.post(postPath, handleRead(opConfig, ${handlerName}, parseBodyAsQueryMiddleware, '${opKind}'))
|
|
21
55
|
}`
|
|
22
|
-
: ` if (postReadsEnabled) app.post(path, handleRead(opConfig, ${handlerName}, parseBodyAsQueryMiddleware))`
|
|
56
|
+
: ` if (postReadsEnabled) app.post(path, handleRead(opConfig, ${handlerName}, parseBodyAsQueryMiddleware, '${opKind}'))`
|
|
23
57
|
: '';
|
|
24
58
|
return ` if (isEnabled(config.${meta.configKey})) {
|
|
25
59
|
const opConfig = opFor('${meta.configKey}')
|
|
26
60
|
const path = ${pathValue}
|
|
27
|
-
app.get(path, handleRead(opConfig, ${handlerName}, parseQueryMiddleware))
|
|
61
|
+
app.get(path, handleRead(opConfig, ${handlerName}, parseQueryMiddleware, '${opKind}'))
|
|
28
62
|
${postReadLine}
|
|
29
63
|
}`;
|
|
30
64
|
}
|
|
@@ -32,10 +66,11 @@ function emitWriteOp(meta, modelName) {
|
|
|
32
66
|
const c = meta.name.charAt(0).toUpperCase() + meta.name.slice(1);
|
|
33
67
|
const handlerName = `${modelName}${c}`;
|
|
34
68
|
const pathValue = pathExpr(meta.pathSuffix);
|
|
69
|
+
const opKind = opKindFor(meta.name);
|
|
35
70
|
return ` if (isEnabled(config.${meta.configKey})) {
|
|
36
71
|
const opConfig = opFor('${meta.configKey}')
|
|
37
72
|
const path = ${pathValue}
|
|
38
|
-
app.${meta.method}(path, handleWrite(opConfig, ${handlerName}))
|
|
73
|
+
app.${meta.method}(path, handleWrite(opConfig, ${handlerName}, '${opKind}'))
|
|
39
74
|
}`;
|
|
40
75
|
}
|
|
41
76
|
function generateHonoRouterFunction({ model, enums, guardShapesImport, importStyle, writeStrategy, dropGuard, }) {
|
|
@@ -74,10 +109,8 @@ import { validateCountSourceWhere } from '../routeConfig${ext}'
|
|
|
74
109
|
import { transformResult } from '../operationRuntime${ext}'
|
|
75
110
|
import { mapError } from '../errorMapper${ext}'
|
|
76
111
|
import { mergePaginationConfig } from '../pagination${ext}'
|
|
77
|
-
import {
|
|
78
|
-
|
|
79
|
-
applyProjectionToTarget,
|
|
80
|
-
} from '../projectionDefaults${ext}'
|
|
112
|
+
import { applyDroppedGuard } from '../projectionDefaults${ext}'
|
|
113
|
+
import type { OpKind } from '../projectionDefaults${ext}'
|
|
81
114
|
import { MODEL_FIELDS, MODEL_ENUMS } from './${modelName}Metadata${ext}'
|
|
82
115
|
|
|
83
116
|
${(0, generateRouteConfigType_1.generateRouteConfigType)(modelName, 'HonoBeforeHook', guardShapesImport, importStyle, 'hono')}
|
|
@@ -156,17 +189,17 @@ async function parseUpdateEachBodyMiddleware(c: HandlerContext): Promise<void> {
|
|
|
156
189
|
function makeShapeMiddleware<TCtx, TPrisma, TEnv extends HonoEnvBase>(
|
|
157
190
|
config: ${modelName}RouteConfig<TCtx, TPrisma, TEnv>,
|
|
158
191
|
opConfig: OperationConfigLike<TEnv>,
|
|
159
|
-
|
|
192
|
+
opKind: OpKind,
|
|
160
193
|
) {
|
|
161
194
|
return async (c: Context<GeneratedHonoEnv<TEnv>>): Promise<void> => {
|
|
162
195
|
const merged = mergePaginationConfig(config.pagination, opConfig.pagination)
|
|
163
|
-
if (merged) {
|
|
164
|
-
|
|
165
|
-
}
|
|
196
|
+
if (merged) c.set('routeConfig', { pagination: merged })
|
|
197
|
+
|
|
166
198
|
const headerName = config.guard?.variantHeader || 'x-api-variant'
|
|
167
199
|
const headerValue = c.req.header(headerName)
|
|
168
200
|
const caller = config.guard?.resolveVariant?.(c) ?? headerValue ?? undefined
|
|
169
201
|
if (caller) c.set('guardCaller', caller)
|
|
202
|
+
|
|
170
203
|
if (opConfig.shape) {
|
|
171
204
|
if (!DROP_GUARD) {
|
|
172
205
|
c.set('guardShape', opConfig.shape)
|
|
@@ -174,31 +207,35 @@ function makeShapeMiddleware<TCtx, TPrisma, TEnv extends HonoEnvBase>(
|
|
|
174
207
|
const resolveCtx = typeof config.resolveContext === 'function'
|
|
175
208
|
? () => (config.resolveContext as (ctx: Context<GeneratedHonoEnv<TEnv>>) => unknown | Promise<unknown>)(c)
|
|
176
209
|
: undefined
|
|
177
|
-
|
|
210
|
+
|
|
211
|
+
await applyDroppedGuard(
|
|
178
212
|
opConfig.shape,
|
|
179
213
|
caller,
|
|
180
214
|
resolveCtx,
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
215
|
+
opKind,
|
|
216
|
+
{
|
|
217
|
+
readQuery: c.get('parsedQuery'),
|
|
218
|
+
writeBody: isPlainObject(c.get('body'))
|
|
219
|
+
? (c.get('body') as Record<string, unknown>)
|
|
220
|
+
: undefined,
|
|
221
|
+
},
|
|
222
|
+
() => {
|
|
184
223
|
let target = c.get('parsedQuery')
|
|
185
224
|
if (!target) {
|
|
186
225
|
target = {}
|
|
187
226
|
c.set('parsedQuery', target)
|
|
188
227
|
}
|
|
189
|
-
|
|
190
|
-
}
|
|
228
|
+
return target
|
|
229
|
+
},
|
|
230
|
+
() => {
|
|
191
231
|
let target = c.get('body')
|
|
192
232
|
if (!isPlainObject(target)) {
|
|
193
233
|
target = {}
|
|
194
234
|
c.set('body', target)
|
|
195
235
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
)
|
|
200
|
-
}
|
|
201
|
-
}
|
|
236
|
+
return target as Record<string, unknown>
|
|
237
|
+
},
|
|
238
|
+
)
|
|
202
239
|
}
|
|
203
240
|
}
|
|
204
241
|
}
|
|
@@ -318,10 +355,11 @@ export function ${routerFunctionName}<TCtx = unknown, TPrisma = any, TEnv extend
|
|
|
318
355
|
opConfig: OperationConfigLike<TEnv>,
|
|
319
356
|
handlerFn: (c: HandlerContext) => Promise<void>,
|
|
320
357
|
parseFn: (c: HandlerContext) => Promise<void>,
|
|
358
|
+
opKind: OpKind,
|
|
321
359
|
) => async (c: Context<GeneratedHonoEnv<TEnv>>): Promise<Response> => {
|
|
322
360
|
try {
|
|
323
361
|
await parseFn(c as unknown as HandlerContext)
|
|
324
|
-
await makeShapeMiddleware<TCtx, TPrisma, TEnv>(config, opConfig,
|
|
362
|
+
await makeShapeMiddleware<TCtx, TPrisma, TEnv>(config, opConfig, opKind)(c)
|
|
325
363
|
const { before = [], after = [] } = opConfig
|
|
326
364
|
const beforeResp = await runBeforeHooks<TEnv>(before, c)
|
|
327
365
|
if (beforeResp) return beforeResp
|
|
@@ -337,10 +375,11 @@ export function ${routerFunctionName}<TCtx = unknown, TPrisma = any, TEnv extend
|
|
|
337
375
|
const handleWrite = (
|
|
338
376
|
opConfig: OperationConfigLike<TEnv>,
|
|
339
377
|
handlerFn: (c: HandlerContext) => Promise<void>,
|
|
378
|
+
opKind: OpKind,
|
|
340
379
|
) => async (c: Context<GeneratedHonoEnv<TEnv>>): Promise<Response> => {
|
|
341
380
|
try {
|
|
342
381
|
await parseWriteBodyMiddleware(c as unknown as HandlerContext)
|
|
343
|
-
await makeShapeMiddleware<TCtx, TPrisma, TEnv>(config, opConfig,
|
|
382
|
+
await makeShapeMiddleware<TCtx, TPrisma, TEnv>(config, opConfig, opKind)(c)
|
|
344
383
|
const { before = [], after = [] } = opConfig
|
|
345
384
|
const beforeResp = await runBeforeHooks<TEnv>(before, c)
|
|
346
385
|
if (beforeResp) return beforeResp
|
|
@@ -374,7 +413,7 @@ ${writeOpBlocks}
|
|
|
374
413
|
app.post(path, async (c: Context<GeneratedHonoEnv<TEnv>>): Promise<Response> => {
|
|
375
414
|
try {
|
|
376
415
|
await parseUpdateEachBodyMiddleware(c as unknown as HandlerContext)
|
|
377
|
-
await makeShapeMiddleware<TCtx, TPrisma, TEnv>(config, opConfig, '
|
|
416
|
+
await makeShapeMiddleware<TCtx, TPrisma, TEnv>(config, opConfig, 'noop')(c)
|
|
378
417
|
const { before = [], after = [] } = opConfig
|
|
379
418
|
const beforeResp = await runBeforeHooks<TEnv>(before, c)
|
|
380
419
|
if (beforeResp) return beforeResp
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateRouterHono.js","sourceRoot":"","sources":["../../src/generators/generateRouterHono.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"generateRouterHono.js","sourceRoot":"","sources":["../../src/generators/generateRouterHono.ts"],"names":[],"mappings":";;AAkFA,gEAuXC;AAxcD,uEAAmE;AAEnE,kDAA8C;AAE9C,uEAAiE;AAEjE,SAAS,QAAQ,CAAC,MAAc;IAC9B,IAAI,CAAC,MAAM;QAAE,OAAO,iBAAiB,CAAA;IACrC,OAAO,iBAAiB,MAAM,IAAI,CAAA;AACpC,CAAC;AAED,SAAS,SAAS,CAAC,MAAc;IAC/B,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,YAAY,CAAC;QAClB,KAAK,mBAAmB;YACtB,OAAO,YAAY,CAAA;QACrB,KAAK,UAAU,CAAC;QAChB,KAAK,WAAW,CAAC;QACjB,KAAK,kBAAkB,CAAC;QACxB,KAAK,mBAAmB,CAAC;QACzB,KAAK,OAAO,CAAC;QACb,KAAK,WAAW,CAAC;QACjB,KAAK,SAAS;YACZ,OAAO,MAAM,CAAA;QACf,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAA;QACjB,KAAK,YAAY,CAAC;QAClB,KAAK,qBAAqB;YACxB,OAAO,YAAY,CAAA;QACrB,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAA;QACjB,KAAK,YAAY,CAAC;QAClB,KAAK,qBAAqB;YACxB,OAAO,YAAY,CAAA;QACrB,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAA;QACjB,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAA;QACjB,KAAK,YAAY;YACf,OAAO,YAAY,CAAA;QACrB;YACE,OAAO,MAAM,CAAA;IACjB,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,IAAyC,EAAE,SAAiB;IAC9E,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAChE,MAAM,WAAW,GAAG,GAAG,SAAS,GAAG,CAAC,EAAE,CAAA;IACtC,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IAC3C,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAEnC,MAAM,YAAY,GAAG,IAAI,CAAC,gBAAgB;QACxC,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,UAAU;YACxB,CAAC,CAAC;;gDAEwC,WAAW,kCAAkC,MAAM;MAC7F;YACA,CAAC,CAAC,iEAAiE,WAAW,kCAAkC,MAAM,KAAK;QAC7H,CAAC,CAAC,EAAE,CAAA;IAEN,OAAO,0BAA0B,IAAI,CAAC,SAAS;8BACnB,IAAI,CAAC,SAAS;mBACzB,SAAS;yCACa,WAAW,4BAA4B,MAAM;EACpF,YAAY;IACV,CAAA;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,IAAyC,EAAE,SAAiB;IAC/E,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAChE,MAAM,WAAW,GAAG,GAAG,SAAS,GAAG,CAAC,EAAE,CAAA;IACtC,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IAC3C,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAEnC,OAAO,0BAA0B,IAAI,CAAC,SAAS;8BACnB,IAAI,CAAC,SAAS;mBACzB,SAAS;UAClB,IAAI,CAAC,MAAM,gCAAgC,WAAW,MAAM,MAAM;IACxE,CAAA;AACJ,CAAC;AAED,SAAgB,0BAA0B,CAAC,EACzC,KAAK,EACL,KAAK,EACL,iBAAiB,EACjB,WAAW,EACX,aAAa,EACb,SAAS,GAQV;IACC,MAAM,GAAG,GAAG,IAAA,qBAAS,EAAC,WAAW,CAAC,CAAA;IAClC,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAA;IAC5B,MAAM,cAAc,GAAG,SAAS,CAAC,WAAW,EAAE,CAAA;IAC9C,MAAM,kBAAkB,GAAG,GAAG,SAAS,QAAQ,CAAA;IAE/C,MAAM,cAAc,GAAG,yCAAkB;SACtC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;SAChF,IAAI,CAAC,IAAI,CAAC,CAAA;IAEb,MAAM,OAAO,GAAG,yCAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAA;IACnE,MAAM,QAAQ,GAAG,yCAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC;SACxF,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,CAAA;IAEzC,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAC9E,MAAM,aAAa,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAEjF,OAAO;;;;;EAKP,cAAc;YACJ,SAAS,WAAW,GAAG;;;;;;;;;+BASJ,GAAG;uDACqB,GAAG;+EACqB,GAAG;yDACzB,GAAG;0DACF,GAAG;sDACP,GAAG;0CACf,GAAG;sDACS,GAAG;0DACC,GAAG;oDACT,GAAG;+CACR,SAAS,WAAW,GAAG;;EAEpE,IAAA,iDAAuB,EAAC,SAAS,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,CAAC;;;qBAGzE,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAuElB,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA6FH,kBAAkB,mFAAmF,SAAS;8DAClE,SAAS;;;OAGhE,SAAS;;;;;;;;4DAQ4C,cAAc;;;;;;;;;;;;;;;WAe/D,SAAS;;;;4CAIwB,aAAa;;;;;;;;;WAS9C,SAAS;;;;4CAIwB,aAAa;;;;;;;;UAQ/C,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mCA4DgB,SAAS;;;;;EAK1C,YAAY;;EAEZ,aAAa;;;;;;YAMH,SAAS;;;;;;;;;;;;gBAYL,SAAS;;;;;;;;;;;;CAYxB,CAAA;AACD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prisma-generator-express",
|
|
3
3
|
"description": "Prisma generator for Express, Fastify, and Hono CRUD APIs with OpenAPI documentation",
|
|
4
|
-
"version": "1.62.
|
|
4
|
+
"version": "1.62.3",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"license": "MIT",
|
|
@@ -377,4 +377,97 @@ function applyForcedWhere(opts: WhereMergeOptions): void {
|
|
|
377
377
|
export async function applyDroppedGuard(
|
|
378
378
|
shape: unknown,
|
|
379
379
|
caller: string | undefined,
|
|
380
|
-
resolveContext: ContextResolver |
|
|
380
|
+
resolveContext: ContextResolver | undefined,
|
|
381
|
+
opKind: OpKind,
|
|
382
|
+
targets: {
|
|
383
|
+
readQuery?: Record<string, unknown>
|
|
384
|
+
writeBody?: Record<string, unknown>
|
|
385
|
+
},
|
|
386
|
+
ensureReadTarget: () => Record<string, unknown>,
|
|
387
|
+
ensureWriteTarget: () => Record<string, unknown>,
|
|
388
|
+
): Promise<void> {
|
|
389
|
+
const resolved = await resolveShape(shape, caller, resolveContext)
|
|
390
|
+
if (!resolved) return
|
|
391
|
+
|
|
392
|
+
const projection = buildDefaultProjectionBody(resolved)
|
|
393
|
+
|
|
394
|
+
if (opKind === 'read' || opKind === 'readUnique') {
|
|
395
|
+
const isUnique = opKind === 'readUnique'
|
|
396
|
+
const shapeWhere = isPlainObject(resolved.where)
|
|
397
|
+
? extractForcedFromWhereConfig(resolved.where)
|
|
398
|
+
: emptyForced()
|
|
399
|
+
|
|
400
|
+
if (projection || hasForced(shapeWhere)) {
|
|
401
|
+
const target = targets.readQuery ?? ensureReadTarget()
|
|
402
|
+
if (projection) applyProjectionToTarget(target, projection)
|
|
403
|
+
if (hasForced(shapeWhere)) {
|
|
404
|
+
applyForcedWhere({
|
|
405
|
+
targetContainer: target,
|
|
406
|
+
whereKey: 'where',
|
|
407
|
+
forced: shapeWhere,
|
|
408
|
+
isUnique,
|
|
409
|
+
})
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
return
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
if (opKind === 'noop') return
|
|
416
|
+
|
|
417
|
+
const shapeWhere = isPlainObject(resolved.where)
|
|
418
|
+
? extractForcedFromWhereConfig(resolved.where)
|
|
419
|
+
: emptyForced()
|
|
420
|
+
|
|
421
|
+
const forcedData =
|
|
422
|
+
opKind === 'create' || opKind === 'createMany' || opKind === 'update' || opKind === 'updateMany'
|
|
423
|
+
? isPlainObject(resolved.data)
|
|
424
|
+
? extractForcedFromDataConfig(resolved.data)
|
|
425
|
+
: {}
|
|
426
|
+
: {}
|
|
427
|
+
|
|
428
|
+
const forcedCreate =
|
|
429
|
+
opKind === 'upsert' && isPlainObject(resolved.create)
|
|
430
|
+
? extractForcedFromDataConfig(resolved.create)
|
|
431
|
+
: {}
|
|
432
|
+
|
|
433
|
+
const forcedUpdate =
|
|
434
|
+
opKind === 'upsert' && isPlainObject(resolved.update)
|
|
435
|
+
? extractForcedFromDataConfig(resolved.update)
|
|
436
|
+
: {}
|
|
437
|
+
|
|
438
|
+
const needsBody =
|
|
439
|
+
projection !== null ||
|
|
440
|
+
hasForced(shapeWhere) ||
|
|
441
|
+
Object.keys(forcedData).length > 0 ||
|
|
442
|
+
Object.keys(forcedCreate).length > 0 ||
|
|
443
|
+
Object.keys(forcedUpdate).length > 0
|
|
444
|
+
|
|
445
|
+
if (!needsBody) return
|
|
446
|
+
|
|
447
|
+
const target = targets.writeBody ?? ensureWriteTarget()
|
|
448
|
+
|
|
449
|
+
if (projection) applyProjectionToTarget(target, projection)
|
|
450
|
+
|
|
451
|
+
if (hasForced(shapeWhere)) {
|
|
452
|
+
const isUnique =
|
|
453
|
+
opKind === 'update' || opKind === 'delete' || opKind === 'upsert'
|
|
454
|
+
applyForcedWhere({
|
|
455
|
+
targetContainer: target,
|
|
456
|
+
whereKey: 'where',
|
|
457
|
+
forced: shapeWhere,
|
|
458
|
+
isUnique,
|
|
459
|
+
})
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
if (Object.keys(forcedData).length > 0) {
|
|
463
|
+
target.data = mergeForcedData(target.data, forcedData)
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
if (Object.keys(forcedCreate).length > 0) {
|
|
467
|
+
target.create = mergeForcedData(target.create, forcedCreate)
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
if (Object.keys(forcedUpdate).length > 0) {
|
|
471
|
+
target.update = mergeForcedData(target.update, forcedUpdate)
|
|
472
|
+
}
|
|
473
|
+
}
|
|
@@ -10,37 +10,79 @@ function pathExpr(suffix: string): string {
|
|
|
10
10
|
return `\`\${basePath}${suffix}\``
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
function
|
|
13
|
+
function opKindFor(opName: string): string {
|
|
14
|
+
switch (opName) {
|
|
15
|
+
case 'findUnique':
|
|
16
|
+
case 'findUniqueOrThrow':
|
|
17
|
+
return 'readUnique'
|
|
18
|
+
case 'findMany':
|
|
19
|
+
case 'findFirst':
|
|
20
|
+
case 'findFirstOrThrow':
|
|
21
|
+
case 'findManyPaginated':
|
|
22
|
+
case 'count':
|
|
23
|
+
case 'aggregate':
|
|
24
|
+
case 'groupBy':
|
|
25
|
+
return 'read'
|
|
26
|
+
case 'create':
|
|
27
|
+
return 'create'
|
|
28
|
+
case 'createMany':
|
|
29
|
+
case 'createManyAndReturn':
|
|
30
|
+
return 'createMany'
|
|
31
|
+
case 'update':
|
|
32
|
+
return 'update'
|
|
33
|
+
case 'updateMany':
|
|
34
|
+
case 'updateManyAndReturn':
|
|
35
|
+
return 'updateMany'
|
|
36
|
+
case 'upsert':
|
|
37
|
+
return 'upsert'
|
|
38
|
+
case 'delete':
|
|
39
|
+
return 'delete'
|
|
40
|
+
case 'deleteMany':
|
|
41
|
+
return 'deleteMany'
|
|
42
|
+
default:
|
|
43
|
+
return 'noop'
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function emitReadOp(
|
|
48
|
+
meta: (typeof OPERATION_METADATA)[number],
|
|
49
|
+
modelName: string,
|
|
50
|
+
): string {
|
|
14
51
|
const c = meta.name.charAt(0).toUpperCase() + meta.name.slice(1)
|
|
15
52
|
const handlerName = `${modelName}${c}`
|
|
16
53
|
const pathValue = pathExpr(meta.pathSuffix)
|
|
54
|
+
const opKind = opKindFor(meta.name)
|
|
17
55
|
|
|
18
56
|
const postReadLine = meta.supportsPostRead
|
|
19
57
|
? meta.name === 'findMany'
|
|
20
58
|
? ` if (postReadsEnabled) {
|
|
21
59
|
const postPath = basePath ? \`\${basePath}/read\` : '/read'
|
|
22
|
-
instance.post(postPath, handleRead(opConfig, ${handlerName}, parseBodyAsQueryHook))
|
|
60
|
+
instance.post(postPath, handleRead(opConfig, ${handlerName}, parseBodyAsQueryHook, '${opKind}'))
|
|
23
61
|
}`
|
|
24
|
-
: ` if (postReadsEnabled) instance.post(path, handleRead(opConfig, ${handlerName}, parseBodyAsQueryHook))`
|
|
62
|
+
: ` if (postReadsEnabled) instance.post(path, handleRead(opConfig, ${handlerName}, parseBodyAsQueryHook, '${opKind}'))`
|
|
25
63
|
: ''
|
|
26
64
|
|
|
27
65
|
return ` if (isEnabled(config.${meta.configKey})) {
|
|
28
66
|
const opConfig: OperationConfigLike = (config.${meta.configKey} as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
29
67
|
const path = ${pathValue}
|
|
30
|
-
instance.get(path, handleRead(opConfig, ${handlerName}, parseQueryHook))
|
|
68
|
+
instance.get(path, handleRead(opConfig, ${handlerName}, parseQueryHook, '${opKind}'))
|
|
31
69
|
${postReadLine}
|
|
32
70
|
}`
|
|
33
71
|
}
|
|
34
72
|
|
|
35
|
-
function emitWriteOp(
|
|
73
|
+
function emitWriteOp(
|
|
74
|
+
meta: (typeof OPERATION_METADATA)[number],
|
|
75
|
+
modelName: string,
|
|
76
|
+
): string {
|
|
36
77
|
const c = meta.name.charAt(0).toUpperCase() + meta.name.slice(1)
|
|
37
78
|
const handlerName = `${modelName}${c}`
|
|
38
79
|
const pathValue = pathExpr(meta.pathSuffix)
|
|
80
|
+
const opKind = opKindFor(meta.name)
|
|
39
81
|
|
|
40
82
|
return ` if (isEnabled(config.${meta.configKey})) {
|
|
41
83
|
const opConfig: OperationConfigLike = (config.${meta.configKey} as OperationConfigLike | undefined) ?? defaultOpConfig
|
|
42
84
|
const path = ${pathValue}
|
|
43
|
-
instance.${meta.method}(path, handleWrite(opConfig, ${handlerName}))
|
|
85
|
+
instance.${meta.method}(path, handleWrite(opConfig, ${handlerName}, '${opKind}'))
|
|
44
86
|
}`
|
|
45
87
|
}
|
|
46
88
|
|
|
@@ -96,10 +138,8 @@ import type { OperationContext } from '../operationRuntime${ext}'
|
|
|
96
138
|
import { transformResult } from '../operationRuntime${ext}'
|
|
97
139
|
import { HttpError, mapError } from '../errorMapper${ext}'
|
|
98
140
|
import { mergePaginationConfig } from '../pagination${ext}'
|
|
99
|
-
import {
|
|
100
|
-
|
|
101
|
-
applyProjectionToTarget,
|
|
102
|
-
} from '../projectionDefaults${ext}'
|
|
141
|
+
import { applyDroppedGuard } from '../projectionDefaults${ext}'
|
|
142
|
+
import type { OpKind } from '../projectionDefaults${ext}'
|
|
103
143
|
import { MODEL_FIELDS, MODEL_ENUMS } from './${modelName}Metadata${ext}'
|
|
104
144
|
|
|
105
145
|
${generateRouteConfigType(modelName, 'FastifyHookHandler', guardShapesImport, importStyle, 'fastify')}
|
|
@@ -171,45 +211,46 @@ function buildResolveContext(
|
|
|
171
211
|
function makeShapeHook(
|
|
172
212
|
config: ${modelName}RouteConfig,
|
|
173
213
|
opConfig: OperationConfigLike,
|
|
174
|
-
|
|
214
|
+
opKind: OpKind,
|
|
175
215
|
): (request: FastifyRequest) => Promise<void> {
|
|
176
216
|
return async (request: FastifyRequest) => {
|
|
177
217
|
const fx = request as FastifyExtended
|
|
178
218
|
const merged = mergePaginationConfig(config.pagination, opConfig.pagination)
|
|
179
|
-
if (merged) {
|
|
180
|
-
|
|
181
|
-
}
|
|
219
|
+
if (merged) fx.routeConfig = { pagination: merged }
|
|
220
|
+
|
|
182
221
|
const headerName = (config.guard?.variantHeader || 'x-api-variant').toLowerCase()
|
|
183
222
|
const headerValue = request.headers[headerName]
|
|
184
223
|
const caller = config.guard?.resolveVariant?.(request)
|
|
185
224
|
?? (Array.isArray(headerValue) ? headerValue[0] : headerValue)
|
|
186
225
|
?? undefined
|
|
187
|
-
if (caller)
|
|
188
|
-
|
|
189
|
-
}
|
|
226
|
+
if (caller) fx.guardCaller = caller
|
|
227
|
+
|
|
190
228
|
if (opConfig.shape) {
|
|
191
229
|
if (!DROP_GUARD) {
|
|
192
230
|
fx.guardShape = opConfig.shape
|
|
193
231
|
} else {
|
|
194
|
-
|
|
232
|
+
await applyDroppedGuard(
|
|
195
233
|
opConfig.shape,
|
|
196
234
|
caller,
|
|
197
235
|
buildResolveContext(config, request),
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
236
|
+
opKind,
|
|
237
|
+
{
|
|
238
|
+
readQuery: fx.parsedQuery,
|
|
239
|
+
writeBody: isPlainObject(request.body)
|
|
240
|
+
? (request.body as Record<string, unknown>)
|
|
241
|
+
: undefined,
|
|
242
|
+
},
|
|
243
|
+
() => {
|
|
201
244
|
if (!fx.parsedQuery) fx.parsedQuery = {}
|
|
202
|
-
|
|
203
|
-
}
|
|
245
|
+
return fx.parsedQuery
|
|
246
|
+
},
|
|
247
|
+
() => {
|
|
204
248
|
if (!isPlainObject(request.body)) {
|
|
205
249
|
;(request as unknown as { body: unknown }).body = {}
|
|
206
250
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
)
|
|
211
|
-
}
|
|
212
|
-
}
|
|
251
|
+
return request.body as Record<string, unknown>
|
|
252
|
+
},
|
|
253
|
+
)
|
|
213
254
|
}
|
|
214
255
|
}
|
|
215
256
|
}
|
|
@@ -337,10 +378,11 @@ export async function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(
|
|
|
337
378
|
opConfig: OperationConfigLike,
|
|
338
379
|
handlerFn: (req: FastifyRequest, reply: FastifyReply) => Promise<void>,
|
|
339
380
|
parseFn: (req: FastifyRequest) => void,
|
|
381
|
+
opKind: OpKind,
|
|
340
382
|
) => async (request: FastifyRequest, reply: FastifyReply) => {
|
|
341
383
|
try {
|
|
342
384
|
parseFn(request)
|
|
343
|
-
await makeShapeHook(config, opConfig,
|
|
385
|
+
await makeShapeHook(config, opConfig, opKind)(request)
|
|
344
386
|
const { before = [], after = [] } = opConfig
|
|
345
387
|
if (await runHooks(before, request, reply)) return
|
|
346
388
|
await handlerFn(request, reply)
|
|
@@ -354,9 +396,10 @@ export async function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(
|
|
|
354
396
|
const handleWrite = (
|
|
355
397
|
opConfig: OperationConfigLike,
|
|
356
398
|
handlerFn: (req: FastifyRequest, reply: FastifyReply) => Promise<void>,
|
|
399
|
+
opKind: OpKind,
|
|
357
400
|
) => async (request: FastifyRequest, reply: FastifyReply) => {
|
|
358
401
|
try {
|
|
359
|
-
await makeShapeHook(config, opConfig,
|
|
402
|
+
await makeShapeHook(config, opConfig, opKind)(request)
|
|
360
403
|
const { before = [], after = [] } = opConfig
|
|
361
404
|
if (await runHooks(before, request, reply)) return
|
|
362
405
|
await handlerFn(request, reply)
|
|
@@ -385,7 +428,7 @@ ${writeOpBlocks}
|
|
|
385
428
|
if (!Array.isArray(request.body)) {
|
|
386
429
|
throw new HttpError(400, 'updateEach body must be an array of { where, data } items')
|
|
387
430
|
}
|
|
388
|
-
await makeShapeHook(config, opConfig, '
|
|
431
|
+
await makeShapeHook(config, opConfig, 'noop')(request)
|
|
389
432
|
const { before = [], after = [] } = opConfig
|
|
390
433
|
if (await runHooks(before, request, reply)) return
|
|
391
434
|
await ${modelName}UpdateEach(request, reply)
|
|
@@ -10,24 +10,59 @@ function pathExpr(suffix: string): string {
|
|
|
10
10
|
return `\`\${basePath}${suffix}\``
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
function opKindFor(opName: string): string {
|
|
14
|
+
switch (opName) {
|
|
15
|
+
case 'findUnique':
|
|
16
|
+
case 'findUniqueOrThrow':
|
|
17
|
+
return 'readUnique'
|
|
18
|
+
case 'findMany':
|
|
19
|
+
case 'findFirst':
|
|
20
|
+
case 'findFirstOrThrow':
|
|
21
|
+
case 'findManyPaginated':
|
|
22
|
+
case 'count':
|
|
23
|
+
case 'aggregate':
|
|
24
|
+
case 'groupBy':
|
|
25
|
+
return 'read'
|
|
26
|
+
case 'create':
|
|
27
|
+
return 'create'
|
|
28
|
+
case 'createMany':
|
|
29
|
+
case 'createManyAndReturn':
|
|
30
|
+
return 'createMany'
|
|
31
|
+
case 'update':
|
|
32
|
+
return 'update'
|
|
33
|
+
case 'updateMany':
|
|
34
|
+
case 'updateManyAndReturn':
|
|
35
|
+
return 'updateMany'
|
|
36
|
+
case 'upsert':
|
|
37
|
+
return 'upsert'
|
|
38
|
+
case 'delete':
|
|
39
|
+
return 'delete'
|
|
40
|
+
case 'deleteMany':
|
|
41
|
+
return 'deleteMany'
|
|
42
|
+
default:
|
|
43
|
+
return 'noop'
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
13
47
|
function emitReadOp(meta: (typeof OPERATION_METADATA)[number], modelName: string): string {
|
|
14
48
|
const c = meta.name.charAt(0).toUpperCase() + meta.name.slice(1)
|
|
15
49
|
const handlerName = `${modelName}${c}`
|
|
16
50
|
const pathValue = pathExpr(meta.pathSuffix)
|
|
51
|
+
const opKind = opKindFor(meta.name)
|
|
17
52
|
|
|
18
53
|
const postReadLine = meta.supportsPostRead
|
|
19
54
|
? meta.name === 'findMany'
|
|
20
55
|
? ` if (postReadsEnabled) {
|
|
21
56
|
const postPath = basePath ? \`\${basePath}/read\` : '/read'
|
|
22
|
-
app.post(postPath, handleRead(opConfig, ${handlerName}, parseBodyAsQueryMiddleware))
|
|
57
|
+
app.post(postPath, handleRead(opConfig, ${handlerName}, parseBodyAsQueryMiddleware, '${opKind}'))
|
|
23
58
|
}`
|
|
24
|
-
: ` if (postReadsEnabled) app.post(path, handleRead(opConfig, ${handlerName}, parseBodyAsQueryMiddleware))`
|
|
59
|
+
: ` if (postReadsEnabled) app.post(path, handleRead(opConfig, ${handlerName}, parseBodyAsQueryMiddleware, '${opKind}'))`
|
|
25
60
|
: ''
|
|
26
61
|
|
|
27
62
|
return ` if (isEnabled(config.${meta.configKey})) {
|
|
28
63
|
const opConfig = opFor('${meta.configKey}')
|
|
29
64
|
const path = ${pathValue}
|
|
30
|
-
app.get(path, handleRead(opConfig, ${handlerName}, parseQueryMiddleware))
|
|
65
|
+
app.get(path, handleRead(opConfig, ${handlerName}, parseQueryMiddleware, '${opKind}'))
|
|
31
66
|
${postReadLine}
|
|
32
67
|
}`
|
|
33
68
|
}
|
|
@@ -36,11 +71,12 @@ function emitWriteOp(meta: (typeof OPERATION_METADATA)[number], modelName: strin
|
|
|
36
71
|
const c = meta.name.charAt(0).toUpperCase() + meta.name.slice(1)
|
|
37
72
|
const handlerName = `${modelName}${c}`
|
|
38
73
|
const pathValue = pathExpr(meta.pathSuffix)
|
|
74
|
+
const opKind = opKindFor(meta.name)
|
|
39
75
|
|
|
40
76
|
return ` if (isEnabled(config.${meta.configKey})) {
|
|
41
77
|
const opConfig = opFor('${meta.configKey}')
|
|
42
78
|
const path = ${pathValue}
|
|
43
|
-
app.${meta.method}(path, handleWrite(opConfig, ${handlerName}))
|
|
79
|
+
app.${meta.method}(path, handleWrite(opConfig, ${handlerName}, '${opKind}'))
|
|
44
80
|
}`
|
|
45
81
|
}
|
|
46
82
|
|
|
@@ -98,10 +134,8 @@ import { validateCountSourceWhere } from '../routeConfig${ext}'
|
|
|
98
134
|
import { transformResult } from '../operationRuntime${ext}'
|
|
99
135
|
import { mapError } from '../errorMapper${ext}'
|
|
100
136
|
import { mergePaginationConfig } from '../pagination${ext}'
|
|
101
|
-
import {
|
|
102
|
-
|
|
103
|
-
applyProjectionToTarget,
|
|
104
|
-
} from '../projectionDefaults${ext}'
|
|
137
|
+
import { applyDroppedGuard } from '../projectionDefaults${ext}'
|
|
138
|
+
import type { OpKind } from '../projectionDefaults${ext}'
|
|
105
139
|
import { MODEL_FIELDS, MODEL_ENUMS } from './${modelName}Metadata${ext}'
|
|
106
140
|
|
|
107
141
|
${generateRouteConfigType(modelName, 'HonoBeforeHook', guardShapesImport, importStyle, 'hono')}
|
|
@@ -180,17 +214,17 @@ async function parseUpdateEachBodyMiddleware(c: HandlerContext): Promise<void> {
|
|
|
180
214
|
function makeShapeMiddleware<TCtx, TPrisma, TEnv extends HonoEnvBase>(
|
|
181
215
|
config: ${modelName}RouteConfig<TCtx, TPrisma, TEnv>,
|
|
182
216
|
opConfig: OperationConfigLike<TEnv>,
|
|
183
|
-
|
|
217
|
+
opKind: OpKind,
|
|
184
218
|
) {
|
|
185
219
|
return async (c: Context<GeneratedHonoEnv<TEnv>>): Promise<void> => {
|
|
186
220
|
const merged = mergePaginationConfig(config.pagination, opConfig.pagination)
|
|
187
|
-
if (merged) {
|
|
188
|
-
|
|
189
|
-
}
|
|
221
|
+
if (merged) c.set('routeConfig', { pagination: merged })
|
|
222
|
+
|
|
190
223
|
const headerName = config.guard?.variantHeader || 'x-api-variant'
|
|
191
224
|
const headerValue = c.req.header(headerName)
|
|
192
225
|
const caller = config.guard?.resolveVariant?.(c) ?? headerValue ?? undefined
|
|
193
226
|
if (caller) c.set('guardCaller', caller)
|
|
227
|
+
|
|
194
228
|
if (opConfig.shape) {
|
|
195
229
|
if (!DROP_GUARD) {
|
|
196
230
|
c.set('guardShape', opConfig.shape)
|
|
@@ -198,31 +232,35 @@ function makeShapeMiddleware<TCtx, TPrisma, TEnv extends HonoEnvBase>(
|
|
|
198
232
|
const resolveCtx = typeof config.resolveContext === 'function'
|
|
199
233
|
? () => (config.resolveContext as (ctx: Context<GeneratedHonoEnv<TEnv>>) => unknown | Promise<unknown>)(c)
|
|
200
234
|
: undefined
|
|
201
|
-
|
|
235
|
+
|
|
236
|
+
await applyDroppedGuard(
|
|
202
237
|
opConfig.shape,
|
|
203
238
|
caller,
|
|
204
239
|
resolveCtx,
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
240
|
+
opKind,
|
|
241
|
+
{
|
|
242
|
+
readQuery: c.get('parsedQuery'),
|
|
243
|
+
writeBody: isPlainObject(c.get('body'))
|
|
244
|
+
? (c.get('body') as Record<string, unknown>)
|
|
245
|
+
: undefined,
|
|
246
|
+
},
|
|
247
|
+
() => {
|
|
208
248
|
let target = c.get('parsedQuery')
|
|
209
249
|
if (!target) {
|
|
210
250
|
target = {}
|
|
211
251
|
c.set('parsedQuery', target)
|
|
212
252
|
}
|
|
213
|
-
|
|
214
|
-
}
|
|
253
|
+
return target
|
|
254
|
+
},
|
|
255
|
+
() => {
|
|
215
256
|
let target = c.get('body')
|
|
216
257
|
if (!isPlainObject(target)) {
|
|
217
258
|
target = {}
|
|
218
259
|
c.set('body', target)
|
|
219
260
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
)
|
|
224
|
-
}
|
|
225
|
-
}
|
|
261
|
+
return target as Record<string, unknown>
|
|
262
|
+
},
|
|
263
|
+
)
|
|
226
264
|
}
|
|
227
265
|
}
|
|
228
266
|
}
|
|
@@ -342,10 +380,11 @@ export function ${routerFunctionName}<TCtx = unknown, TPrisma = any, TEnv extend
|
|
|
342
380
|
opConfig: OperationConfigLike<TEnv>,
|
|
343
381
|
handlerFn: (c: HandlerContext) => Promise<void>,
|
|
344
382
|
parseFn: (c: HandlerContext) => Promise<void>,
|
|
383
|
+
opKind: OpKind,
|
|
345
384
|
) => async (c: Context<GeneratedHonoEnv<TEnv>>): Promise<Response> => {
|
|
346
385
|
try {
|
|
347
386
|
await parseFn(c as unknown as HandlerContext)
|
|
348
|
-
await makeShapeMiddleware<TCtx, TPrisma, TEnv>(config, opConfig,
|
|
387
|
+
await makeShapeMiddleware<TCtx, TPrisma, TEnv>(config, opConfig, opKind)(c)
|
|
349
388
|
const { before = [], after = [] } = opConfig
|
|
350
389
|
const beforeResp = await runBeforeHooks<TEnv>(before, c)
|
|
351
390
|
if (beforeResp) return beforeResp
|
|
@@ -361,10 +400,11 @@ export function ${routerFunctionName}<TCtx = unknown, TPrisma = any, TEnv extend
|
|
|
361
400
|
const handleWrite = (
|
|
362
401
|
opConfig: OperationConfigLike<TEnv>,
|
|
363
402
|
handlerFn: (c: HandlerContext) => Promise<void>,
|
|
403
|
+
opKind: OpKind,
|
|
364
404
|
) => async (c: Context<GeneratedHonoEnv<TEnv>>): Promise<Response> => {
|
|
365
405
|
try {
|
|
366
406
|
await parseWriteBodyMiddleware(c as unknown as HandlerContext)
|
|
367
|
-
await makeShapeMiddleware<TCtx, TPrisma, TEnv>(config, opConfig,
|
|
407
|
+
await makeShapeMiddleware<TCtx, TPrisma, TEnv>(config, opConfig, opKind)(c)
|
|
368
408
|
const { before = [], after = [] } = opConfig
|
|
369
409
|
const beforeResp = await runBeforeHooks<TEnv>(before, c)
|
|
370
410
|
if (beforeResp) return beforeResp
|
|
@@ -398,7 +438,7 @@ ${writeOpBlocks}
|
|
|
398
438
|
app.post(path, async (c: Context<GeneratedHonoEnv<TEnv>>): Promise<Response> => {
|
|
399
439
|
try {
|
|
400
440
|
await parseUpdateEachBodyMiddleware(c as unknown as HandlerContext)
|
|
401
|
-
await makeShapeMiddleware<TCtx, TPrisma, TEnv>(config, opConfig, '
|
|
441
|
+
await makeShapeMiddleware<TCtx, TPrisma, TEnv>(config, opConfig, 'noop')(c)
|
|
402
442
|
const { before = [], after = [] } = opConfig
|
|
403
443
|
const beforeResp = await runBeforeHooks<TEnv>(before, c)
|
|
404
444
|
if (beforeResp) return beforeResp
|