prisma-generator-express 1.66.0 → 1.68.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 +188 -3432
- package/dist/client/encodeQueryParams.js +3 -1
- package/dist/client/encodeQueryParams.js.map +1 -1
- package/dist/copy/misc.d.ts +1 -0
- package/dist/copy/misc.js +14 -0
- package/dist/copy/misc.js.map +1 -1
- package/dist/copy/operationDefinitions.d.ts +4 -1
- package/dist/copy/operationDefinitions.js +133 -9
- package/dist/copy/operationDefinitions.js.map +1 -1
- package/dist/generators/generateFastifyHandler.d.ts +2 -2
- package/dist/generators/generateFastifyHandler.js +68 -12
- package/dist/generators/generateFastifyHandler.js.map +1 -1
- package/dist/generators/generateHonoHandler.d.ts +2 -2
- package/dist/generators/generateHonoHandler.js +53 -6
- package/dist/generators/generateHonoHandler.js.map +1 -1
- package/dist/generators/generateHonoOpenApi.d.ts +13 -0
- package/dist/generators/generateHonoOpenApi.js +70 -0
- package/dist/generators/generateHonoOpenApi.js.map +1 -0
- package/dist/generators/generateImportPrismaStatement.d.ts +1 -0
- package/dist/generators/generateImportPrismaStatement.js +6 -0
- package/dist/generators/generateImportPrismaStatement.js.map +1 -1
- package/dist/generators/generateMcpApp.d.ts +10 -0
- package/dist/generators/generateMcpApp.js +113 -0
- package/dist/generators/generateMcpApp.js.map +1 -0
- package/dist/generators/generateModelMcp.d.ts +9 -0
- package/dist/generators/generateModelMcp.js +145 -0
- package/dist/generators/generateModelMcp.js.map +1 -0
- package/dist/generators/generateModelMetadata.js +29 -15
- package/dist/generators/generateModelMetadata.js.map +1 -1
- package/dist/generators/generateOperationCore.d.ts +3 -3
- package/dist/generators/generateOperationCore.js +51 -16
- package/dist/generators/generateOperationCore.js.map +1 -1
- package/dist/generators/generateRelationMeta.js +2 -2
- package/dist/generators/generateRelationMeta.js.map +1 -1
- package/dist/generators/generateRouteConfigType.d.ts +2 -2
- package/dist/generators/generateRouteConfigType.js +29 -11
- package/dist/generators/generateRouteConfigType.js.map +1 -1
- package/dist/generators/generateRouter.d.ts +7 -4
- package/dist/generators/generateRouter.js +164 -65
- package/dist/generators/generateRouter.js.map +1 -1
- package/dist/generators/generateRouterFastify.d.ts +7 -4
- package/dist/generators/generateRouterFastify.js +106 -86
- package/dist/generators/generateRouterFastify.js.map +1 -1
- package/dist/generators/generateRouterHono.d.ts +7 -4
- package/dist/generators/generateRouterHono.js +59 -414
- package/dist/generators/generateRouterHono.js.map +1 -1
- package/dist/generators/generateRouterPartsHono.d.ts +14 -0
- package/dist/generators/generateRouterPartsHono.js +180 -0
- package/dist/generators/generateRouterPartsHono.js.map +1 -0
- package/dist/generators/generateUnifiedDocs.d.ts +1 -1
- package/dist/generators/generateUnifiedDocs.js +15 -8
- package/dist/generators/generateUnifiedDocs.js.map +1 -1
- package/dist/generators/generateUnifiedHandler.d.ts +2 -2
- package/dist/generators/generateUnifiedHandler.js +42 -18
- package/dist/generators/generateUnifiedHandler.js.map +1 -1
- package/dist/guardOptions.js +12 -7
- package/dist/guardOptions.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +123 -4
- package/dist/index.js.map +1 -1
- package/dist/utils/copyFiles.d.ts +1 -1
- package/dist/utils/copyFiles.js +42 -7
- package/dist/utils/copyFiles.js.map +1 -1
- package/dist/utils/importExt.d.ts +1 -1
- package/dist/utils/mcpGate.d.ts +10 -0
- package/dist/utils/mcpGate.js +118 -0
- package/dist/utils/mcpGate.js.map +1 -0
- package/dist/utils/pathCasing.d.ts +4 -0
- package/dist/utils/pathCasing.js +40 -0
- package/dist/utils/pathCasing.js.map +1 -0
- package/dist/utils/resolveImportStyle.js +13 -5
- package/dist/utils/resolveImportStyle.js.map +1 -1
- package/dist/utils/writeFileSafely.js +6 -0
- package/dist/utils/writeFileSafely.js.map +1 -1
- package/package.json +22 -5
- package/src/bin.ts +1 -1
- package/src/client/encodeQueryParams.ts +39 -35
- package/src/constants.ts +1 -1
- package/src/copy/autoIncludePlanner.ts +93 -27
- package/src/copy/autoIncludePlannerGuarded.ts +171 -48
- package/src/copy/autoIncludeRuntimeGuarded.ts +25 -7
- package/src/copy/buildModelOpenApi.ts +229 -176
- package/src/copy/concurrency.ts +10 -8
- package/src/copy/docsRenderer.ts +14 -15
- package/src/copy/errorMapper.ts +68 -19
- package/src/copy/guardHelpers.ts +30 -9
- package/src/copy/materializedCount.ts +17 -5
- package/src/copy/mcpRuntime.ts +1017 -0
- package/src/copy/misc.ts +88 -68
- package/src/copy/ndjson.ts +72 -0
- package/src/copy/operationDefinitions.ts +177 -25
- package/src/copy/operationPipeline.ts +267 -0
- package/src/copy/operationRuntime.ts +124 -26
- package/src/copy/operationSchemas.ts +2773 -0
- package/src/copy/pagination.ts +35 -13
- package/src/copy/parseQueryParams.ts +47 -48
- package/src/copy/projectionDefaults.ts +6 -4
- package/src/copy/routeConfig.express.ts +16 -4
- package/src/copy/routeConfig.fastify.ts +16 -2
- package/src/copy/routeConfig.hono.ts +46 -14
- package/src/copy/routeConfig.ts +175 -40
- package/src/copy/routerParts.ts +524 -0
- package/src/copy/scalarTypes.ts +7 -2
- package/src/copy/sse.ts +72 -19
- package/src/generators/generateFastifyHandler.ts +77 -20
- package/src/generators/generateHonoHandler.ts +62 -14
- package/src/generators/generateHonoOpenApi.ts +93 -0
- package/src/generators/generateImportPrismaStatement.ts +93 -81
- package/src/generators/generateMcpApp.ts +133 -0
- package/src/generators/generateModelMcp.ts +208 -0
- package/src/generators/generateModelMetadata.ts +40 -22
- package/src/generators/generateOperationCore.ts +81 -33
- package/src/generators/generateRelationMeta.ts +23 -11
- package/src/generators/generateRouteConfigType.ts +39 -13
- package/src/generators/generateRouter.ts +171 -68
- package/src/generators/generateRouterFastify.ts +117 -89
- package/src/generators/generateRouterHono.ts +84 -464
- package/src/generators/generateRouterPartsHono.ts +220 -0
- package/src/generators/generateUnifiedDocs.ts +29 -8
- package/src/generators/generateUnifiedHandler.ts +47 -24
- package/src/generators/generateUnifiedScalarUI.ts +1 -1
- package/src/guardOptions.ts +105 -92
- package/src/index.ts +161 -6
- package/src/utils/copyFiles.ts +235 -168
- package/src/utils/importExt.ts +2 -2
- package/src/utils/mcpGate.ts +157 -0
- package/src/utils/pathCasing.ts +42 -0
- package/src/utils/resolveImportStyle.ts +37 -15
- package/src/utils/strings.ts +2 -2
- package/src/utils/writeFileSafely.ts +12 -2
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.generateRouterFunction = generateRouterFunction;
|
|
4
4
|
const generateRouteConfigType_1 = require("./generateRouteConfigType");
|
|
5
5
|
const importExt_1 = require("../utils/importExt");
|
|
6
|
+
const pathCasing_1 = require("../utils/pathCasing");
|
|
6
7
|
const operationDefinitions_1 = require("../copy/operationDefinitions");
|
|
7
8
|
function pathExpr(basePath, suffix) {
|
|
8
9
|
if (!suffix)
|
|
@@ -50,10 +51,11 @@ function emitReadOp(meta, modelName) {
|
|
|
50
51
|
const pathValue = pathExpr('basePath', meta.pathSuffix);
|
|
51
52
|
const opKind = opKindFor(meta.name);
|
|
52
53
|
const postReadBlock = meta.supportsPostRead
|
|
53
|
-
? ` if (
|
|
54
|
+
? ` if (resolvePostReadsEnabled(config.disablePostReads, opConfig.disablePostReads)) {
|
|
54
55
|
const postPath = ${meta.name === 'findMany' ? "basePath ? `${basePath}/read` : '/read'" : `path`}
|
|
55
56
|
router.post(
|
|
56
57
|
postPath,
|
|
58
|
+
...(opConfig.authorize ? [opConfig.authorize] : []),
|
|
57
59
|
parseBodyAsQuery,
|
|
58
60
|
setShape(opConfig, '${opKind}'),
|
|
59
61
|
...opConfig.operationBefore,
|
|
@@ -71,12 +73,14 @@ function emitReadOp(meta, modelName) {
|
|
|
71
73
|
const path = ${pathValue}
|
|
72
74
|
router.get(
|
|
73
75
|
path,
|
|
76
|
+
...(opConfig.authorize ? [opConfig.authorize] : []),
|
|
74
77
|
parseQuery,
|
|
75
78
|
setShape(opConfig, '${opKind}'),
|
|
76
79
|
...opConfig.operationBefore,
|
|
77
80
|
requireVariantKey(),
|
|
78
81
|
variantBeforeDispatcher(opConfig),
|
|
79
82
|
maybeProgressiveSSE(opConfig, core.${meta.coreName}, '${meta.name}'),
|
|
83
|
+
${meta.name === 'findMany' ? 'maybeNdjsonFindMany(core.findMany),' : ''}
|
|
80
84
|
${handlerName} as RequestHandler,
|
|
81
85
|
variantAfterDispatcher(opConfig),
|
|
82
86
|
...opConfig.operationAfter,
|
|
@@ -96,6 +100,7 @@ function emitWriteOp(meta, modelName) {
|
|
|
96
100
|
const path = ${pathValue}
|
|
97
101
|
router.${meta.method}(
|
|
98
102
|
path,
|
|
103
|
+
...(opConfig.authorize ? [opConfig.authorize] : []),
|
|
99
104
|
setShape(opConfig, '${opKind}'),
|
|
100
105
|
...opConfig.operationBefore,
|
|
101
106
|
requireVariantKey(),
|
|
@@ -107,10 +112,10 @@ function emitWriteOp(meta, modelName) {
|
|
|
107
112
|
)
|
|
108
113
|
}`;
|
|
109
114
|
}
|
|
110
|
-
function generateRouterFunction({ model, enums, guardShapesImport, importStyle, writeStrategy, findManyPaginatedMode, dropGuard, }) {
|
|
115
|
+
function generateRouterFunction({ model, enums, guardShapesImport, clientImport, importStyle, writeStrategy, findManyPaginatedMode, dropGuard, pathCase, }) {
|
|
111
116
|
const ext = (0, importExt_1.importExt)(importStyle);
|
|
112
117
|
const modelName = model.name;
|
|
113
|
-
const
|
|
118
|
+
const modelSegment = (0, pathCasing_1.modelPathSegment)(modelName, pathCase);
|
|
114
119
|
const delegateKey = modelName.charAt(0).toLowerCase() + modelName.slice(1);
|
|
115
120
|
const routerFunctionName = `${modelName}Router`;
|
|
116
121
|
const handlerImports = operationDefinitions_1.OPERATION_METADATA.filter((m) => m.name !== 'updateEach')
|
|
@@ -134,24 +139,34 @@ import type {
|
|
|
134
139
|
QueryBuilderConfig,
|
|
135
140
|
FindManyPaginatedMode,
|
|
136
141
|
PaginationConfig,
|
|
142
|
+
PrismaClientLike,
|
|
137
143
|
} from '../routeConfig.target${ext}'
|
|
138
144
|
import { parseQueryParams } from '../parseQueryParams${ext}'
|
|
139
|
-
import { sanitizeKeys, normalizePrefix, getEnv, isPlainObject } from '../misc${ext}'
|
|
145
|
+
import { sanitizeKeys, normalizePrefix, getEnv, isPlainObject, resolveDropGuardEnv } from '../misc${ext}'
|
|
140
146
|
import { buildModelOpenApi } from '../buildModelOpenApi${ext}'
|
|
141
147
|
import {
|
|
142
148
|
normalizeOperation,
|
|
143
|
-
resolveOperationVariantKey,
|
|
144
149
|
validateCountSourceWhere,
|
|
145
150
|
validateOperationConfig,
|
|
146
151
|
validateUpdateEachConfig,
|
|
152
|
+
resolvePostReadsEnabled,
|
|
153
|
+
warnIfUnguardedRoutes,
|
|
147
154
|
} from '../routeConfig${ext}'
|
|
155
|
+
import type { RuntimeOperationOverride } from '../operationRuntime${ext}'
|
|
148
156
|
import type { NormalizedOperationConfig } from '../routeConfig${ext}'
|
|
149
157
|
import type { OperationContext } from '../operationRuntime${ext}'
|
|
150
158
|
import { transformResult } from '../operationRuntime${ext}'
|
|
151
159
|
import { HttpError, mapError } from '../errorMapper${ext}'
|
|
152
|
-
import {
|
|
153
|
-
|
|
160
|
+
import {
|
|
161
|
+
routeOperation,
|
|
162
|
+
prepareGuardOperation,
|
|
163
|
+
settleStage,
|
|
164
|
+
classifyError,
|
|
165
|
+
memoizeContext,
|
|
166
|
+
type ArgsChannel,
|
|
167
|
+
} from '../operationPipeline${ext}'
|
|
154
168
|
import { mergePaginationConfig } from '../pagination${ext}'
|
|
169
|
+
import { acceptsNdjson, runNdjsonFindMany } from '../ndjson${ext}'
|
|
155
170
|
import {
|
|
156
171
|
acceptsEventStream,
|
|
157
172
|
runProgressiveEndpoint,
|
|
@@ -161,17 +176,21 @@ import {
|
|
|
161
176
|
} from '../sse${ext}'
|
|
162
177
|
import { relationModels } from '../relationModels${ext}'
|
|
163
178
|
import { runAutoIncludeProgressive } from '../autoIncludeRuntime${ext}'
|
|
164
|
-
import { applyDroppedGuard } from '../projectionDefaults${ext}'
|
|
165
179
|
import type { OpKind } from '../projectionDefaults${ext}'
|
|
166
180
|
import { MODEL_FIELDS, MODEL_ENUMS } from './${modelName}Metadata${ext}'
|
|
167
181
|
|
|
168
|
-
${(0, generateRouteConfigType_1.generateRouteConfigType)(modelName, 'RequestHandler', guardShapesImport, importStyle, 'express')}
|
|
182
|
+
${(0, generateRouteConfigType_1.generateRouteConfigType)(modelName, 'RequestHandler', guardShapesImport, importStyle, 'express', clientImport)}
|
|
169
183
|
const _env = getEnv()
|
|
170
184
|
|
|
171
185
|
const FIND_MANY_PAGINATED_MODE: FindManyPaginatedMode = '${findManyPaginatedMode}'
|
|
172
|
-
|
|
186
|
+
// Fixed at generation time. The environment bypass is resolved per router,
|
|
187
|
+
// because it requires the configuration's explicit \`allowE2EGuardBypass: true\`:
|
|
188
|
+
// false or omitted means the environment cannot drop guards for this target.
|
|
189
|
+
const DROP_GUARD = ${dropGuard}
|
|
173
190
|
|
|
174
191
|
type OperationConfigLike = {
|
|
192
|
+
authorize?: RequestHandler
|
|
193
|
+
override?: RuntimeOperationOverride
|
|
175
194
|
before?: RequestHandler[]
|
|
176
195
|
after?: RequestHandler[]
|
|
177
196
|
shape?: unknown
|
|
@@ -194,7 +213,7 @@ type NormalizedOp = NormalizedOperationConfig<RequestHandler, RequestHandler> &
|
|
|
194
213
|
}
|
|
195
214
|
|
|
196
215
|
type ExtendedRequest = Request & {
|
|
197
|
-
prisma?:
|
|
216
|
+
prisma?: PrismaClientLike
|
|
198
217
|
postgres?: unknown
|
|
199
218
|
sqlite?: unknown
|
|
200
219
|
}
|
|
@@ -204,11 +223,35 @@ type LocalsBag = {
|
|
|
204
223
|
routeConfig?: { pagination?: PaginationConfig }
|
|
205
224
|
guardShape?: Record<string, unknown>
|
|
206
225
|
guardCaller?: string
|
|
226
|
+
operationOverride?: RuntimeOperationOverride
|
|
227
|
+
getContext?: () => Promise<unknown>
|
|
207
228
|
guardVariantKey?: string
|
|
208
|
-
|
|
229
|
+
routeFailure?: { ok: false; failure: HttpError }
|
|
230
|
+
guardFailure?: { ok: false; failure: HttpError }
|
|
209
231
|
data?: unknown
|
|
210
232
|
}
|
|
211
233
|
|
|
234
|
+
function queryChannel(res: Response): ArgsChannel {
|
|
235
|
+
return {
|
|
236
|
+
read: () => readLocals(res).parsedQuery,
|
|
237
|
+
write: (next) => {
|
|
238
|
+
readLocals(res).parsedQuery = next
|
|
239
|
+
},
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function bodyChannel(req: Request): ArgsChannel {
|
|
244
|
+
return {
|
|
245
|
+
read: () =>
|
|
246
|
+
isPlainObject(req.body)
|
|
247
|
+
? (req.body as Record<string, unknown>)
|
|
248
|
+
: undefined,
|
|
249
|
+
write: (next) => {
|
|
250
|
+
req.body = next
|
|
251
|
+
},
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
212
255
|
function normalizeExpressOperation(
|
|
213
256
|
config: OperationConfigLike | undefined,
|
|
214
257
|
): NormalizedOp {
|
|
@@ -312,16 +355,19 @@ function variantAfterDispatcher(opConfig: NormalizedOp): RequestHandler {
|
|
|
312
355
|
|
|
313
356
|
function requireVariantKey(): RequestHandler {
|
|
314
357
|
return (_req, res, next) => {
|
|
315
|
-
const
|
|
316
|
-
|
|
317
|
-
|
|
358
|
+
const locals = readLocals(res)
|
|
359
|
+
try {
|
|
360
|
+
if (locals.routeFailure) settleStage(locals.routeFailure)
|
|
361
|
+
if (locals.guardFailure) settleStage(locals.guardFailure)
|
|
362
|
+
} catch (err) {
|
|
363
|
+
next(err)
|
|
318
364
|
return
|
|
319
365
|
}
|
|
320
|
-
next(
|
|
366
|
+
next()
|
|
321
367
|
}
|
|
322
368
|
}
|
|
323
369
|
|
|
324
|
-
export function ${routerFunctionName}<TCtx = unknown, TPrisma =
|
|
370
|
+
export function ${routerFunctionName}<TCtx = unknown, TPrisma extends PrismaClientLike = PrismaClientLike>(config: ${modelName}RouteConfig<TCtx, TPrisma> = {}) {
|
|
325
371
|
validateCountSourceWhere(config.pagination?.countSource, '${modelName} pagination')
|
|
326
372
|
validateCountSourceWhere(
|
|
327
373
|
(config.findManyPaginated && typeof config.findManyPaginated === 'object' ? config.findManyPaginated : undefined)?.pagination?.countSource,
|
|
@@ -331,6 +377,7 @@ export function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(config: ${m
|
|
|
331
377
|
const router = express.Router()
|
|
332
378
|
|
|
333
379
|
const isEnabled = (value: unknown): boolean => value !== false && !!(config.enableAll || value)
|
|
380
|
+
warnIfUnguardedRoutes('${modelName}', ['findMany', 'findUnique', 'findUniqueOrThrow', 'findFirst', 'findFirstOrThrow', 'findManyPaginated', 'count', 'aggregate', 'groupBy', 'create', 'createMany', 'createManyAndReturn', 'update', 'updateMany', 'updateManyAndReturn', 'upsert', 'delete', 'deleteMany'], config, isEnabled)
|
|
334
381
|
|
|
335
382
|
const opFor = (key: string): NormalizedOp => {
|
|
336
383
|
const raw = (config as unknown as Record<string, unknown>)[key] as OperationConfigLike | undefined
|
|
@@ -339,13 +386,12 @@ export function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(config: ${m
|
|
|
339
386
|
}
|
|
340
387
|
|
|
341
388
|
const customPrefix = normalizePrefix(config.customUrlPrefix || '')
|
|
342
|
-
const modelPrefix = config.addModelPrefix !== false ? '/${
|
|
389
|
+
const modelPrefix = config.addModelPrefix !== false ? '/${modelSegment}' : ''
|
|
343
390
|
const basePath = customPrefix + modelPrefix
|
|
344
391
|
|
|
345
392
|
const openApiDisabled = config.disableOpenApi === true
|
|
346
393
|
|| (config.disableOpenApi !== false && (_env.DISABLE_OPENAPI === 'true' || _env.NODE_ENV === 'production'))
|
|
347
394
|
|
|
348
|
-
const postReadsEnabled = !config.disablePostReads
|
|
349
395
|
|
|
350
396
|
let _openApiJsonCache: unknown = undefined
|
|
351
397
|
const getOpenApiJson = (): unknown => {
|
|
@@ -355,7 +401,7 @@ export function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(config: ${m
|
|
|
355
401
|
MODEL_FIELDS as unknown as Parameters<typeof buildModelOpenApi>[1],
|
|
356
402
|
MODEL_ENUMS as unknown as Parameters<typeof buildModelOpenApi>[2],
|
|
357
403
|
config as unknown as Parameters<typeof buildModelOpenApi>[3],
|
|
358
|
-
{ format: 'json', writeStrategy: '${writeStrategy}' },
|
|
404
|
+
{ format: 'json', writeStrategy: '${writeStrategy}', pathSegment: '${modelSegment}' },
|
|
359
405
|
)
|
|
360
406
|
}
|
|
361
407
|
return _openApiJsonCache
|
|
@@ -368,7 +414,7 @@ export function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(config: ${m
|
|
|
368
414
|
MODEL_FIELDS as unknown as Parameters<typeof buildModelOpenApi>[1],
|
|
369
415
|
MODEL_ENUMS as unknown as Parameters<typeof buildModelOpenApi>[2],
|
|
370
416
|
config as unknown as Parameters<typeof buildModelOpenApi>[3],
|
|
371
|
-
{ format: 'yaml', writeStrategy: '${writeStrategy}' },
|
|
417
|
+
{ format: 'yaml', writeStrategy: '${writeStrategy}', pathSegment: '${modelSegment}' },
|
|
372
418
|
) as string
|
|
373
419
|
}
|
|
374
420
|
return _openApiYamlCache
|
|
@@ -390,6 +436,8 @@ export function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(config: ${m
|
|
|
390
436
|
const extReq = req as ExtendedRequest
|
|
391
437
|
const locals = readLocals(res)
|
|
392
438
|
return {
|
|
439
|
+
operationOverride: locals.operationOverride,
|
|
440
|
+
resolveOperationContext: locals.getContext,
|
|
393
441
|
prisma: extReq.prisma,
|
|
394
442
|
postgres: extReq.postgres,
|
|
395
443
|
sqlite: extReq.sqlite,
|
|
@@ -397,16 +445,12 @@ export function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(config: ${m
|
|
|
397
445
|
body: req.body,
|
|
398
446
|
guardShape: locals.guardShape,
|
|
399
447
|
guardCaller: locals.guardCaller,
|
|
448
|
+
guardVariantKey: locals.guardVariantKey,
|
|
400
449
|
paginationConfig: locals.routeConfig?.pagination,
|
|
401
450
|
findManyPaginatedMode: FIND_MANY_PAGINATED_MODE,
|
|
402
451
|
}
|
|
403
452
|
}
|
|
404
453
|
|
|
405
|
-
const buildResolveContext = (req: Request): (() => unknown | Promise<unknown>) | undefined => {
|
|
406
|
-
if (typeof config.resolveContext !== 'function') return undefined
|
|
407
|
-
return () => (config.resolveContext as (r: Request) => unknown | Promise<unknown>)(req)
|
|
408
|
-
}
|
|
409
|
-
|
|
410
454
|
const parseQuery: RequestHandler = (req, res, next) => {
|
|
411
455
|
const rawQuery = req.query
|
|
412
456
|
if (rawQuery && Object.keys(rawQuery).length > 0) {
|
|
@@ -424,10 +468,24 @@ export function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(config: ${m
|
|
|
424
468
|
next()
|
|
425
469
|
}
|
|
426
470
|
|
|
471
|
+
/**
|
|
472
|
+
* The environment bypass, and it is OPT-IN for this target.
|
|
473
|
+
*
|
|
474
|
+
* \`PGE_DROP_GUARD=true\` (deprecated alias \`E2E=true\`) downgrading enforcement
|
|
475
|
+
* in a deployed environment is a real hazard: on most platforms it is an
|
|
476
|
+
* ordinary config var, set on staging, copied forward, flagged as
|
|
477
|
+
* security-relevant nowhere. It is honoured only when this configuration
|
|
478
|
+
* states \`allowE2EGuardBypass: true\` — false or omitted means the environment
|
|
479
|
+
* cannot drop guards. The generation-time \`DROP_GUARD\` literal is unchanged.
|
|
480
|
+
*/
|
|
481
|
+
const dropGuard = DROP_GUARD || (config.allowE2EGuardBypass === true && resolveDropGuardEnv(_env))
|
|
482
|
+
|
|
427
483
|
const setShape = (opConfig: NormalizedOp, opKind: OpKind): RequestHandler => {
|
|
428
484
|
return async (req, res, next) => {
|
|
485
|
+
const locals = readLocals(res)
|
|
429
486
|
try {
|
|
430
|
-
|
|
487
|
+
locals.operationOverride = opConfig.override
|
|
488
|
+
locals.getContext = memoizeContext(() => config.resolveContext?.(req))
|
|
431
489
|
const merged = mergePaginationConfig(config.pagination, opConfig.pagination)
|
|
432
490
|
if (merged) {
|
|
433
491
|
locals.routeConfig = { pagination: merged }
|
|
@@ -438,51 +496,69 @@ export function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(config: ${m
|
|
|
438
496
|
const caller = config.guard?.resolveVariant?.(req) ?? headerValue ?? undefined
|
|
439
497
|
if (typeof caller === 'string') locals.guardCaller = caller
|
|
440
498
|
|
|
441
|
-
const
|
|
442
|
-
if (!
|
|
443
|
-
locals.
|
|
499
|
+
const routed = routeOperation({ guardRouting: opConfig.guardRouting, caller })
|
|
500
|
+
if (!routed.ok) {
|
|
501
|
+
locals.routeFailure = routed
|
|
444
502
|
next()
|
|
445
503
|
return
|
|
446
504
|
}
|
|
447
505
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
opKind,
|
|
463
|
-
{
|
|
464
|
-
readQuery: locals.parsedQuery,
|
|
465
|
-
writeBody: isPlainObject(req.body)
|
|
466
|
-
? (req.body as Record<string, unknown>)
|
|
467
|
-
: undefined,
|
|
468
|
-
},
|
|
469
|
-
() => {
|
|
470
|
-
if (!locals.parsedQuery) locals.parsedQuery = {}
|
|
471
|
-
return locals.parsedQuery
|
|
472
|
-
},
|
|
473
|
-
() => {
|
|
474
|
-
if (!isPlainObject(req.body)) {
|
|
475
|
-
req.body = {}
|
|
476
|
-
}
|
|
477
|
-
return req.body as Record<string, unknown>
|
|
478
|
-
},
|
|
479
|
-
)
|
|
480
|
-
}
|
|
506
|
+
if (routed.variantKey !== undefined) locals.guardVariantKey = routed.variantKey
|
|
507
|
+
|
|
508
|
+
const guard = await prepareGuardOperation(routed, {
|
|
509
|
+
guardShape: opConfig.guardShape,
|
|
510
|
+
opKind,
|
|
511
|
+
policy: { dropGuard, validateResolvedShapes: false },
|
|
512
|
+
getContext: typeof config.resolveContext === 'function' ? locals.getContext : undefined,
|
|
513
|
+
args: queryChannel(res),
|
|
514
|
+
writeArgs: bodyChannel(req),
|
|
515
|
+
})
|
|
516
|
+
if (!guard.ok) {
|
|
517
|
+
locals.guardFailure = guard
|
|
518
|
+
next()
|
|
519
|
+
return
|
|
481
520
|
}
|
|
482
521
|
|
|
522
|
+
locals.guardShape = guard.guardShape
|
|
523
|
+
|
|
483
524
|
next()
|
|
484
525
|
} catch (err) {
|
|
485
|
-
next(
|
|
526
|
+
next(classifyError(err))
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
const maybeNdjsonFindMany = (
|
|
532
|
+
coreFn: (ctx: OperationContext) => Promise<unknown>,
|
|
533
|
+
): RequestHandler => {
|
|
534
|
+
return async (req, res, next) => {
|
|
535
|
+
if (res.headersSent || res.writableEnded) return next()
|
|
536
|
+
if (req.method !== 'GET') return next()
|
|
537
|
+
if (!acceptsNdjson(req.headers.accept)) return next()
|
|
538
|
+
|
|
539
|
+
const locals = readLocals(res)
|
|
540
|
+
const rawArgs = (locals.parsedQuery ?? {}) as Record<string, unknown>
|
|
541
|
+
const args = { ...rawArgs }
|
|
542
|
+
const paginationCfg = mergePaginationConfig(config.pagination, undefined)
|
|
543
|
+
const requestedTake = typeof rawArgs.take === 'number' ? rawArgs.take : undefined
|
|
544
|
+
const initialSkip = typeof rawArgs.skip === 'number' ? rawArgs.skip : 0
|
|
545
|
+
|
|
546
|
+
try {
|
|
547
|
+
await runNdjsonFindMany({
|
|
548
|
+
res,
|
|
549
|
+
isClosed: () => req.destroyed,
|
|
550
|
+
fetchPage: (skip, pageTake) =>
|
|
551
|
+
coreFn({
|
|
552
|
+
...buildContext(req, res),
|
|
553
|
+
parsedQuery: { ...args, skip, take: pageTake },
|
|
554
|
+
}),
|
|
555
|
+
initialSkip,
|
|
556
|
+
requestedTake,
|
|
557
|
+
defaultLimit: paginationCfg?.defaultLimit,
|
|
558
|
+
maxLimit: paginationCfg?.maxLimit ?? 1000,
|
|
559
|
+
})
|
|
560
|
+
} catch (err) {
|
|
561
|
+
next(err)
|
|
486
562
|
}
|
|
487
563
|
}
|
|
488
564
|
}
|
|
@@ -513,6 +589,23 @@ export function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(config: ${m
|
|
|
513
589
|
}
|
|
514
590
|
|
|
515
591
|
if (progressiveConfig.mode === 'autoInclude') {
|
|
592
|
+
if (progressiveConfig.experimental !== true) {
|
|
593
|
+
if (_env.NODE_ENV !== 'production') {
|
|
594
|
+
console.warn(
|
|
595
|
+
'[prisma-generator-express] auto-include progressive is experimental; set \`experimental: true\` on the progressive config to enable it. Falling back.'
|
|
596
|
+
)
|
|
597
|
+
}
|
|
598
|
+
if (progressiveConfig.fallback === 'error') {
|
|
599
|
+
emitTerminalSSEError(res, 'auto-include requires experimental: true')
|
|
600
|
+
return
|
|
601
|
+
}
|
|
602
|
+
await runSingleResultSSE({
|
|
603
|
+
req,
|
|
604
|
+
res,
|
|
605
|
+
coreQueryFn: () => coreFn(buildContext(req, res)),
|
|
606
|
+
})
|
|
607
|
+
return
|
|
608
|
+
}
|
|
516
609
|
const isAutoIncludeReadable =
|
|
517
610
|
baseOp === 'findUnique' || baseOp === 'findUniqueOrThrow' ||
|
|
518
611
|
baseOp === 'findFirst' || baseOp === 'findFirstOrThrow' ||
|
|
@@ -580,11 +673,16 @@ export function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(config: ${m
|
|
|
580
673
|
}
|
|
581
674
|
|
|
582
675
|
const ctx = await config.resolveContext(req)
|
|
676
|
+
const prismaClient = (req as ExtendedRequest).prisma
|
|
677
|
+
if (!prismaClient) {
|
|
678
|
+
emitTerminalSSEError(res, 'Progressive endpoint requires req.prisma to be set')
|
|
679
|
+
return
|
|
680
|
+
}
|
|
583
681
|
await runProgressiveEndpoint({
|
|
584
682
|
req,
|
|
585
683
|
res,
|
|
586
684
|
ctx,
|
|
587
|
-
prisma:
|
|
685
|
+
prisma: prismaClient,
|
|
588
686
|
variant: variant as string,
|
|
589
687
|
stages: progressiveConfig.stages,
|
|
590
688
|
stageRegistry,
|
|
@@ -640,6 +738,7 @@ ${writeOpBlocks}
|
|
|
640
738
|
const path = basePath ? \`\${basePath}/each\` : '/each'
|
|
641
739
|
router.post(
|
|
642
740
|
path,
|
|
741
|
+
...(opConfig.authorize ? [opConfig.authorize] : []),
|
|
643
742
|
setShape(opConfig, 'noop'),
|
|
644
743
|
...opConfig.operationBefore,
|
|
645
744
|
async (req: Request, res: Response, next: NextFunction) => {
|
|
@@ -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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"}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import { DMMF } from '@prisma/generator-helper';
|
|
2
|
-
import { ImportStyle } from '../utils/resolveImportStyle';
|
|
3
|
-
import { WriteStrategy, FindManyPaginatedMode } from '../constants';
|
|
4
|
-
|
|
1
|
+
import type { DMMF } from '@prisma/generator-helper';
|
|
2
|
+
import type { ImportStyle } from '../utils/resolveImportStyle';
|
|
3
|
+
import type { WriteStrategy, FindManyPaginatedMode } from '../constants';
|
|
4
|
+
import { type PathCase } from '../utils/pathCasing';
|
|
5
|
+
export declare function generateFastifyRouterFunction({ model, enums, guardShapesImport, clientImport, importStyle, writeStrategy, findManyPaginatedMode, dropGuard, pathCase, }: {
|
|
5
6
|
model: DMMF.Model;
|
|
6
7
|
enums: DMMF.DatamodelEnum[];
|
|
7
8
|
guardShapesImport: string | null;
|
|
9
|
+
clientImport?: string;
|
|
8
10
|
importStyle: ImportStyle;
|
|
9
11
|
writeStrategy: WriteStrategy;
|
|
10
12
|
findManyPaginatedMode: FindManyPaginatedMode;
|
|
11
13
|
dropGuard: boolean;
|
|
14
|
+
pathCase: PathCase;
|
|
12
15
|
}): string;
|