prisma-generator-express 1.54.0 → 1.55.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 +59 -3
- package/dist/constants.d.ts +1 -0
- package/dist/generators/generateOperationCore.d.ts +2 -0
- package/dist/generators/generateOperationCore.js +30 -3
- package/dist/generators/generateOperationCore.js.map +1 -1
- package/dist/generators/generateRouter.d.ts +3 -1
- package/dist/generators/generateRouter.js +6 -4
- package/dist/generators/generateRouter.js.map +1 -1
- package/dist/generators/generateRouterFastify.d.ts +3 -1
- package/dist/generators/generateRouterFastify.js +6 -4
- package/dist/generators/generateRouterFastify.js.map +1 -1
- package/dist/generators/generateRouterHono.d.ts +3 -1
- package/dist/generators/generateRouterHono.js +6 -3
- package/dist/generators/generateRouterHono.js.map +1 -1
- package/dist/generators/generateUnifiedScalarUI.d.ts +2 -1
- package/dist/generators/generateUnifiedScalarUI.js +13 -10
- package/dist/generators/generateUnifiedScalarUI.js.map +1 -1
- package/dist/index.js +23 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/constants.ts +3 -1
- package/src/copy/buildModelOpenApi.ts +144 -23
- package/src/copy/docsRenderer.ts +121 -95
- package/src/copy/routeConfig.express.ts +2 -0
- package/src/copy/routeConfig.fastify.ts +2 -0
- package/src/copy/routeConfig.hono.ts +2 -0
- package/src/copy/routeConfig.ts +2 -0
- package/src/generators/generateOperationCore.ts +43 -3
- package/src/generators/generateRouter.ts +8 -3
- package/src/generators/generateRouterFastify.ts +8 -3
- package/src/generators/generateRouterHono.ts +8 -2
- package/src/generators/generateUnifiedScalarUI.ts +15 -11
- package/src/index.ts +27 -7
package/dist/index.js
CHANGED
|
@@ -28,6 +28,21 @@ function getTarget(options) {
|
|
|
28
28
|
return raw;
|
|
29
29
|
throw new Error(`Invalid target "${raw}". Expected "express", "fastify", or "hono".`);
|
|
30
30
|
}
|
|
31
|
+
function getWriteStrategy(options) {
|
|
32
|
+
const raw = String(options.generator.config.writeStrategy ?? 'regular');
|
|
33
|
+
const lower = raw.toLowerCase();
|
|
34
|
+
if (lower === 'regular')
|
|
35
|
+
return 'regular';
|
|
36
|
+
if (lower === 'throwonnonreturning')
|
|
37
|
+
return 'throwOnNonReturning';
|
|
38
|
+
if (lower === 'throwonregular') {
|
|
39
|
+
console.warn('[prisma-generator-express] writeStrategy="throwOnRegular" is deprecated. Use "throwOnNonReturning" instead.');
|
|
40
|
+
return 'throwOnNonReturning';
|
|
41
|
+
}
|
|
42
|
+
if (lower === 'forcereturn')
|
|
43
|
+
return 'forceReturn';
|
|
44
|
+
throw new Error(`Invalid writeStrategy "${raw}". Expected "regular", "throwOnNonReturning", or "forceReturn".`);
|
|
45
|
+
}
|
|
31
46
|
function validateClientGeneratorPresent(options) {
|
|
32
47
|
(0, generateImportPrismaStatement_1.getRelativeClientPath)(options, options.dmmf.datamodel.models[0]?.name ?? 'Model');
|
|
33
48
|
}
|
|
@@ -41,6 +56,7 @@ function validateClientGeneratorPresent(options) {
|
|
|
41
56
|
},
|
|
42
57
|
async onGenerate(options) {
|
|
43
58
|
const target = getTarget(options);
|
|
59
|
+
const writeStrategy = getWriteStrategy(options);
|
|
44
60
|
const hasExplicitOutput = !!options.generator.output?.fromEnvVar ||
|
|
45
61
|
options.generator.config.output !== undefined;
|
|
46
62
|
if (!hasExplicitOutput) {
|
|
@@ -53,6 +69,7 @@ function validateClientGeneratorPresent(options) {
|
|
|
53
69
|
console.log(` Target: ${target}`);
|
|
54
70
|
console.log(` Output: ${options.generator.output?.value}`);
|
|
55
71
|
console.log(` Import style: ${importStyle}`);
|
|
72
|
+
console.log(` Write strategy: ${writeStrategy}`);
|
|
56
73
|
if (options.dmmf.datamodel.models.length > 0) {
|
|
57
74
|
validateClientGeneratorPresent(options);
|
|
58
75
|
}
|
|
@@ -65,15 +82,14 @@ function validateClientGeneratorPresent(options) {
|
|
|
65
82
|
: generateUnifiedHandler_1.generateUnifiedHandler;
|
|
66
83
|
const allModels = options.dmmf.datamodel.models;
|
|
67
84
|
for (const model of options.dmmf.datamodel.models) {
|
|
68
|
-
if (model.documentation &&
|
|
69
|
-
GENERATOR_OFF_RE.test(model.documentation)) {
|
|
85
|
+
if (model.documentation && GENERATOR_OFF_RE.test(model.documentation)) {
|
|
70
86
|
console.log(` Skipping: ${model.name} (generator off)`);
|
|
71
87
|
continue;
|
|
72
88
|
}
|
|
73
89
|
modelNames.push(model.name);
|
|
74
90
|
const guardShapesImport = (0, generateImportPrismaStatement_1.getGuardShapesImport)(options, model.name);
|
|
75
91
|
await (0, writeFileSafely_1.writeFileSafely)({
|
|
76
|
-
content: (0, generateOperationCore_1.generateModelCore)({ model: model, importStyle }),
|
|
92
|
+
content: (0, generateOperationCore_1.generateModelCore)({ model: model, importStyle, writeStrategy }),
|
|
77
93
|
options,
|
|
78
94
|
model: model,
|
|
79
95
|
operation: 'Core',
|
|
@@ -90,6 +106,7 @@ function validateClientGeneratorPresent(options) {
|
|
|
90
106
|
enums: options.dmmf.datamodel.enums,
|
|
91
107
|
guardShapesImport,
|
|
92
108
|
importStyle,
|
|
109
|
+
writeStrategy,
|
|
93
110
|
})
|
|
94
111
|
: target === 'hono'
|
|
95
112
|
? (0, generateRouterHono_1.generateHonoRouterFunction)({
|
|
@@ -97,12 +114,14 @@ function validateClientGeneratorPresent(options) {
|
|
|
97
114
|
enums: options.dmmf.datamodel.enums,
|
|
98
115
|
guardShapesImport,
|
|
99
116
|
importStyle,
|
|
117
|
+
writeStrategy,
|
|
100
118
|
})
|
|
101
119
|
: (0, generateRouter_1.generateRouterFunction)({
|
|
102
120
|
model: model,
|
|
103
121
|
enums: options.dmmf.datamodel.enums,
|
|
104
122
|
guardShapesImport,
|
|
105
123
|
importStyle,
|
|
124
|
+
writeStrategy,
|
|
106
125
|
});
|
|
107
126
|
await (0, writeFileSafely_1.writeFileSafely)({
|
|
108
127
|
content: routerContent,
|
|
@@ -116,6 +135,7 @@ function validateClientGeneratorPresent(options) {
|
|
|
116
135
|
enums: options.dmmf.datamodel.enums,
|
|
117
136
|
target,
|
|
118
137
|
importStyle,
|
|
138
|
+
writeStrategy,
|
|
119
139
|
}),
|
|
120
140
|
options,
|
|
121
141
|
model: model,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;AAAA,+DAIiC;AACjC,gDAAuB;AACvB,gFAA4E;AAC5E,gFAA4E;AAC5E,0EAAsE;AACtE,gEAAoE;AACpE,8EAAkF;AAClF,wEAA4E;AAC5E,kFAA8E;AAC9E,0EAAsE;AACtE,wFAAoF;AACpF,8EAAsE;AACtE,4EAG0C;AAC1C,8FAGmD;AACnD,6DAAyD;AACzD,iDAA6C;AAC7C,mEAA4E;AAC5E,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
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.
|
|
4
|
+
"version": "1.55.0",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"license": "MIT",
|
package/src/constants.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RouteConfig } from './routeConfig'
|
|
1
|
+
import type { RouteConfig, WriteStrategy } from './routeConfig'
|
|
2
2
|
import { OPERATION_DEFS, isOperationEnabled } from './operationDefinitions'
|
|
3
3
|
import { normalizePrefix, removeTrailingSlash } from './misc'
|
|
4
4
|
|
|
@@ -51,6 +51,7 @@ type BuildOptions = {
|
|
|
51
51
|
title?: string
|
|
52
52
|
description?: string
|
|
53
53
|
version?: string
|
|
54
|
+
writeStrategy?: WriteStrategy
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
const OP_MAP = new Map(OPERATION_DEFS.map((d) => [d.name, d]))
|
|
@@ -130,10 +131,7 @@ function scalarUpdateOperations(
|
|
|
130
131
|
}
|
|
131
132
|
|
|
132
133
|
return {
|
|
133
|
-
oneOf: [
|
|
134
|
-
baseSchema,
|
|
135
|
-
{ type: 'object', properties: ops },
|
|
136
|
-
],
|
|
134
|
+
oneOf: [baseSchema, { type: 'object', properties: ops }],
|
|
137
135
|
}
|
|
138
136
|
}
|
|
139
137
|
|
|
@@ -193,7 +191,10 @@ function countBodySchema(): SchemaObject {
|
|
|
193
191
|
take: { type: 'integer', description: 'Limit results' },
|
|
194
192
|
skip: { type: 'integer', description: 'Skip results' },
|
|
195
193
|
cursor: { type: 'object', description: 'Cursor for pagination' },
|
|
196
|
-
select: {
|
|
194
|
+
select: {
|
|
195
|
+
description:
|
|
196
|
+
'Count specific fields. When provided, returns per-field counts as an object instead of a single integer.',
|
|
197
|
+
},
|
|
197
198
|
},
|
|
198
199
|
}
|
|
199
200
|
}
|
|
@@ -207,11 +208,25 @@ function aggregateBodySchema(): SchemaObject {
|
|
|
207
208
|
cursor: { type: 'object', description: 'Cursor for pagination' },
|
|
208
209
|
take: { type: 'integer', description: 'Limit results' },
|
|
209
210
|
skip: { type: 'integer', description: 'Skip results' },
|
|
210
|
-
_count: {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
211
|
+
_count: {
|
|
212
|
+
description: 'Count aggregate (true or field selection object)',
|
|
213
|
+
},
|
|
214
|
+
_avg: {
|
|
215
|
+
type: 'object',
|
|
216
|
+
description: 'Average aggregate (field selection object)',
|
|
217
|
+
},
|
|
218
|
+
_sum: {
|
|
219
|
+
type: 'object',
|
|
220
|
+
description: 'Sum aggregate (field selection object)',
|
|
221
|
+
},
|
|
222
|
+
_min: {
|
|
223
|
+
type: 'object',
|
|
224
|
+
description: 'Min aggregate (field selection object)',
|
|
225
|
+
},
|
|
226
|
+
_max: {
|
|
227
|
+
type: 'object',
|
|
228
|
+
description: 'Max aggregate (field selection object)',
|
|
229
|
+
},
|
|
215
230
|
},
|
|
216
231
|
}
|
|
217
232
|
}
|
|
@@ -220,17 +235,38 @@ function groupByBodySchema(): SchemaObject {
|
|
|
220
235
|
return {
|
|
221
236
|
type: 'object',
|
|
222
237
|
properties: {
|
|
223
|
-
by: {
|
|
238
|
+
by: {
|
|
239
|
+
type: 'array',
|
|
240
|
+
items: { type: 'string' },
|
|
241
|
+
description: 'Fields to group by',
|
|
242
|
+
},
|
|
224
243
|
where: { type: 'object', description: 'Filter conditions' },
|
|
225
244
|
orderBy: { description: 'Sort order. Required when using skip or take.' },
|
|
226
|
-
having: {
|
|
245
|
+
having: {
|
|
246
|
+
type: 'object',
|
|
247
|
+
description: 'Having conditions (filter object)',
|
|
248
|
+
},
|
|
227
249
|
take: { type: 'integer', description: 'Limit results' },
|
|
228
250
|
skip: { type: 'integer', description: 'Skip results' },
|
|
229
|
-
_count: {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
251
|
+
_count: {
|
|
252
|
+
description: 'Count aggregate (true or field selection object)',
|
|
253
|
+
},
|
|
254
|
+
_avg: {
|
|
255
|
+
type: 'object',
|
|
256
|
+
description: 'Average aggregate (field selection object)',
|
|
257
|
+
},
|
|
258
|
+
_sum: {
|
|
259
|
+
type: 'object',
|
|
260
|
+
description: 'Sum aggregate (field selection object)',
|
|
261
|
+
},
|
|
262
|
+
_min: {
|
|
263
|
+
type: 'object',
|
|
264
|
+
description: 'Min aggregate (field selection object)',
|
|
265
|
+
},
|
|
266
|
+
_max: {
|
|
267
|
+
type: 'object',
|
|
268
|
+
description: 'Max aggregate (field selection object)',
|
|
269
|
+
},
|
|
234
270
|
},
|
|
235
271
|
required: ['by'],
|
|
236
272
|
}
|
|
@@ -257,6 +293,82 @@ function getPostReadBodySchema(opName: string): SchemaObject {
|
|
|
257
293
|
}
|
|
258
294
|
}
|
|
259
295
|
|
|
296
|
+
function applyWriteStrategy(
|
|
297
|
+
spec: OpenApiSpec,
|
|
298
|
+
modelName: string,
|
|
299
|
+
basePath: string,
|
|
300
|
+
writeStrategy: WriteStrategy | undefined,
|
|
301
|
+
): void {
|
|
302
|
+
if (!writeStrategy || writeStrategy === 'regular') return
|
|
303
|
+
|
|
304
|
+
const manyPath = basePath + '/many'
|
|
305
|
+
const node = spec.paths[manyPath]
|
|
306
|
+
if (!node) return
|
|
307
|
+
|
|
308
|
+
if (writeStrategy === 'throwOnNonReturning') {
|
|
309
|
+
delete node.post
|
|
310
|
+
delete node.put
|
|
311
|
+
if (Object.keys(node).length === 0) {
|
|
312
|
+
delete spec.paths[manyPath]
|
|
313
|
+
}
|
|
314
|
+
return
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const responseRef: RefObject = {
|
|
318
|
+
$ref: '#/components/schemas/' + modelName + 'Response',
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const injectProjectionAndArrayResponse = (
|
|
322
|
+
op: any,
|
|
323
|
+
successCode: '200' | '201',
|
|
324
|
+
summary: string,
|
|
325
|
+
description: string,
|
|
326
|
+
): void => {
|
|
327
|
+
op.summary = summary
|
|
328
|
+
op.description = description
|
|
329
|
+
const r = op.responses?.[successCode]
|
|
330
|
+
if (r?.content?.['application/json']) {
|
|
331
|
+
r.content['application/json'].schema = {
|
|
332
|
+
type: 'array',
|
|
333
|
+
items: responseRef,
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
const reqSchema = op.requestBody?.content?.['application/json']?.schema
|
|
337
|
+
if (reqSchema && reqSchema.properties) {
|
|
338
|
+
reqSchema.properties.select = {
|
|
339
|
+
type: 'object',
|
|
340
|
+
description: 'Select fields to return',
|
|
341
|
+
}
|
|
342
|
+
reqSchema.properties.include = {
|
|
343
|
+
type: 'object',
|
|
344
|
+
description: 'Include relations to return',
|
|
345
|
+
}
|
|
346
|
+
reqSchema.properties.omit = {
|
|
347
|
+
type: 'object',
|
|
348
|
+
description: 'Omit fields from response',
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
if (node.post) {
|
|
354
|
+
injectProjectionAndArrayResponse(
|
|
355
|
+
node.post,
|
|
356
|
+
'201',
|
|
357
|
+
'Create many ' + modelName + ' (forceReturn)',
|
|
358
|
+
'writeStrategy="forceReturn": this endpoint silently invokes createManyAndReturn and returns the created records instead of { count }.',
|
|
359
|
+
)
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
if (node.put) {
|
|
363
|
+
injectProjectionAndArrayResponse(
|
|
364
|
+
node.put,
|
|
365
|
+
'200',
|
|
366
|
+
'Update many ' + modelName + ' (forceReturn)',
|
|
367
|
+
'writeStrategy="forceReturn": this endpoint silently invokes updateManyAndReturn and returns the updated records instead of { count }.',
|
|
368
|
+
)
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
260
372
|
export function buildModelOpenApi(
|
|
261
373
|
modelName: string,
|
|
262
374
|
modelFields: ModelField[],
|
|
@@ -321,6 +433,8 @@ export function buildModelOpenApi(
|
|
|
321
433
|
|
|
322
434
|
generatePaths(spec, modelName, basePath, config, modelFields)
|
|
323
435
|
|
|
436
|
+
applyWriteStrategy(spec, modelName, basePath, options.writeStrategy)
|
|
437
|
+
|
|
324
438
|
if (options.format === 'yaml') {
|
|
325
439
|
return toYaml(spec)
|
|
326
440
|
}
|
|
@@ -644,7 +758,8 @@ function addPostReadOperation(
|
|
|
644
758
|
tags: [modelName],
|
|
645
759
|
summary: summary + ' (POST)',
|
|
646
760
|
operationId: `${modelName}${opName.charAt(0).toUpperCase() + opName.slice(1)}Post`,
|
|
647
|
-
description:
|
|
761
|
+
description:
|
|
762
|
+
(description ? description + ' ' : '') +
|
|
648
763
|
'POST alternative for requests with complex query parameters that may exceed URL length limits. Accepts the same arguments as the GET endpoint but as a JSON request body instead of query parameters.',
|
|
649
764
|
requestBody: {
|
|
650
765
|
required: true,
|
|
@@ -1291,8 +1406,14 @@ function generatePaths(
|
|
|
1291
1406
|
`Count ${modelName}`,
|
|
1292
1407
|
{
|
|
1293
1408
|
oneOf: [
|
|
1294
|
-
{
|
|
1295
|
-
|
|
1409
|
+
{
|
|
1410
|
+
type: 'integer',
|
|
1411
|
+
description: 'Total count when select is not provided',
|
|
1412
|
+
},
|
|
1413
|
+
{
|
|
1414
|
+
type: 'object',
|
|
1415
|
+
description: 'Per-field count object when select is provided',
|
|
1416
|
+
},
|
|
1296
1417
|
],
|
|
1297
1418
|
},
|
|
1298
1419
|
[400, 403, 500, 501, 503],
|
|
@@ -1730,7 +1851,7 @@ function mapFieldToWriteSchema(
|
|
|
1730
1851
|
description: field.documentation,
|
|
1731
1852
|
}
|
|
1732
1853
|
} else if (!('$ref' in schema)) {
|
|
1733
|
-
(schema as SchemaObject).description = field.documentation
|
|
1854
|
+
;(schema as SchemaObject).description = field.documentation
|
|
1734
1855
|
}
|
|
1735
1856
|
}
|
|
1736
1857
|
|
|
@@ -1896,4 +2017,4 @@ function toYaml(obj: any, indent = 0): string {
|
|
|
1896
2017
|
}
|
|
1897
2018
|
|
|
1898
2019
|
return yaml
|
|
1899
|
-
}
|
|
2020
|
+
}
|