prisma-generator-express 1.65.2 → 1.67.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.
Files changed (106) hide show
  1. package/README.md +51 -3480
  2. package/dist/client/encodeQueryParams.js +3 -1
  3. package/dist/client/encodeQueryParams.js.map +1 -1
  4. package/dist/copy/misc.d.ts +1 -0
  5. package/dist/copy/misc.js +14 -0
  6. package/dist/copy/misc.js.map +1 -1
  7. package/dist/copy/operationDefinitions.js +69 -6
  8. package/dist/copy/operationDefinitions.js.map +1 -1
  9. package/dist/generators/generateFastifyHandler.d.ts +2 -2
  10. package/dist/generators/generateFastifyHandler.js +15 -5
  11. package/dist/generators/generateFastifyHandler.js.map +1 -1
  12. package/dist/generators/generateHonoHandler.d.ts +2 -2
  13. package/dist/generators/generateHonoHandler.js +12 -5
  14. package/dist/generators/generateHonoHandler.js.map +1 -1
  15. package/dist/generators/generateImportPrismaStatement.d.ts +1 -0
  16. package/dist/generators/generateImportPrismaStatement.js +6 -0
  17. package/dist/generators/generateImportPrismaStatement.js.map +1 -1
  18. package/dist/generators/generateModelMetadata.js +20 -10
  19. package/dist/generators/generateModelMetadata.js.map +1 -1
  20. package/dist/generators/generateOperationCore.d.ts +3 -3
  21. package/dist/generators/generateOperationCore.js +51 -16
  22. package/dist/generators/generateOperationCore.js.map +1 -1
  23. package/dist/generators/generateQueryBuilderHelper.d.ts +1 -1
  24. package/dist/generators/generateQueryBuilderHelper.js +2 -4
  25. package/dist/generators/generateQueryBuilderHelper.js.map +1 -1
  26. package/dist/generators/generateRelationMeta.js +2 -2
  27. package/dist/generators/generateRelationMeta.js.map +1 -1
  28. package/dist/generators/generateRouteConfigType.d.ts +2 -2
  29. package/dist/generators/generateRouteConfigType.js +29 -11
  30. package/dist/generators/generateRouteConfigType.js.map +1 -1
  31. package/dist/generators/generateRouter.d.ts +7 -4
  32. package/dist/generators/generateRouter.js +107 -14
  33. package/dist/generators/generateRouter.js.map +1 -1
  34. package/dist/generators/generateRouterFastify.d.ts +7 -4
  35. package/dist/generators/generateRouterFastify.js +56 -28
  36. package/dist/generators/generateRouterFastify.js.map +1 -1
  37. package/dist/generators/generateRouterHono.d.ts +7 -4
  38. package/dist/generators/generateRouterHono.js +84 -53
  39. package/dist/generators/generateRouterHono.js.map +1 -1
  40. package/dist/generators/generateUnifiedDocs.d.ts +1 -1
  41. package/dist/generators/generateUnifiedDocs.js +15 -8
  42. package/dist/generators/generateUnifiedDocs.js.map +1 -1
  43. package/dist/generators/generateUnifiedHandler.d.ts +2 -2
  44. package/dist/generators/generateUnifiedHandler.js +11 -3
  45. package/dist/generators/generateUnifiedHandler.js.map +1 -1
  46. package/dist/guardOptions.js +12 -7
  47. package/dist/guardOptions.js.map +1 -1
  48. package/dist/index.d.ts +1 -1
  49. package/dist/index.js +22 -1
  50. package/dist/index.js.map +1 -1
  51. package/dist/utils/copyFiles.js +22 -6
  52. package/dist/utils/copyFiles.js.map +1 -1
  53. package/dist/utils/importExt.d.ts +1 -1
  54. package/dist/utils/pathCasing.d.ts +4 -0
  55. package/dist/utils/pathCasing.js +40 -0
  56. package/dist/utils/pathCasing.js.map +1 -0
  57. package/dist/utils/resolveImportStyle.js +13 -5
  58. package/dist/utils/resolveImportStyle.js.map +1 -1
  59. package/dist/utils/writeFileSafely.js.map +1 -1
  60. package/package.json +16 -3
  61. package/src/bin.ts +1 -1
  62. package/src/client/encodeQueryParams.ts +39 -35
  63. package/src/constants.ts +1 -1
  64. package/src/copy/autoIncludePlanner.ts +93 -27
  65. package/src/copy/autoIncludePlannerGuarded.ts +171 -48
  66. package/src/copy/autoIncludeRuntimeGuarded.ts +25 -7
  67. package/src/copy/buildModelOpenApi.ts +153 -50
  68. package/src/copy/concurrency.ts +10 -8
  69. package/src/copy/errorMapper.ts +68 -19
  70. package/src/copy/guardHelpers.ts +30 -9
  71. package/src/copy/materializedCount.ts +17 -5
  72. package/src/copy/misc.ts +88 -68
  73. package/src/copy/ndjson.ts +72 -0
  74. package/src/copy/operationDefinitions.ts +99 -21
  75. package/src/copy/operationRuntime.ts +100 -12
  76. package/src/copy/pagination.ts +25 -11
  77. package/src/copy/parseQueryParams.ts +47 -48
  78. package/src/copy/projectionDefaults.ts +6 -4
  79. package/src/copy/routeConfig.express.ts +16 -4
  80. package/src/copy/routeConfig.fastify.ts +16 -2
  81. package/src/copy/routeConfig.hono.ts +19 -9
  82. package/src/copy/routeConfig.ts +174 -39
  83. package/src/copy/scalarTypes.ts +7 -2
  84. package/src/copy/sse.ts +72 -19
  85. package/src/generators/generateFastifyHandler.ts +24 -13
  86. package/src/generators/generateHonoHandler.ts +21 -13
  87. package/src/generators/generateImportPrismaStatement.ts +93 -81
  88. package/src/generators/generateModelMetadata.ts +24 -12
  89. package/src/generators/generateOperationCore.ts +81 -33
  90. package/src/generators/generateQueryBuilderHelper.ts +20 -4
  91. package/src/generators/generateRelationMeta.ts +23 -11
  92. package/src/generators/generateRouteConfigType.ts +39 -13
  93. package/src/generators/generateRouter.ts +114 -17
  94. package/src/generators/generateRouterFastify.ts +67 -31
  95. package/src/generators/generateRouterHono.ts +108 -60
  96. package/src/generators/generateUnifiedDocs.ts +29 -8
  97. package/src/generators/generateUnifiedHandler.ts +16 -8
  98. package/src/generators/generateUnifiedScalarUI.ts +1 -1
  99. package/src/guardOptions.ts +105 -92
  100. package/src/index.ts +46 -4
  101. package/src/utils/copyFiles.ts +199 -168
  102. package/src/utils/importExt.ts +2 -2
  103. package/src/utils/pathCasing.ts +42 -0
  104. package/src/utils/resolveImportStyle.ts +37 -15
  105. package/src/utils/strings.ts +2 -2
  106. package/src/utils/writeFileSafely.ts +6 -2
@@ -1,6 +1,9 @@
1
1
  import { isPlainObject } from './misc'
2
2
 
3
- export type ModelRelationDirection = 'parentOwnsFk' | 'childOwnsFk' | 'implicitM2M'
3
+ export type ModelRelationDirection =
4
+ | 'parentOwnsFk'
5
+ | 'childOwnsFk'
6
+ | 'implicitM2M'
4
7
 
5
8
  export type ModelRelationField = {
6
9
  name: string
@@ -48,10 +51,21 @@ export const DEFAULT_AUTO_INCLUDE_MAX_STAGES = 20
48
51
 
49
52
  const ALLOWED_TO_ONE_ARGS = new Set(['select', 'include', 'omit'])
50
53
  const ALLOWED_TO_MANY_ARGS = new Set([
51
- 'select', 'include', 'omit', 'where', 'orderBy', 'take', 'skip', 'cursor', 'distinct',
54
+ 'select',
55
+ 'include',
56
+ 'omit',
57
+ 'where',
58
+ 'orderBy',
59
+ 'take',
60
+ 'skip',
61
+ 'cursor',
62
+ 'distinct',
52
63
  ])
53
64
 
54
- function isPubliclySelected(projection: Record<string, unknown>, field: string): boolean {
65
+ function isPubliclySelected(
66
+ projection: Record<string, unknown>,
67
+ field: string,
68
+ ): boolean {
55
69
  return projection[field] === true
56
70
  }
57
71
 
@@ -120,7 +134,9 @@ function walk(
120
134
  depth: number,
121
135
  ): WalkResult {
122
136
  if (depth >= ctx.maxDepth) {
123
- return { unsupportedReason: 'nested depth reached maxDepth=' + ctx.maxDepth }
137
+ return {
138
+ unsupportedReason: 'nested depth reached maxDepth=' + ctx.maxDepth,
139
+ }
124
140
  }
125
141
  if (ctx.stages.length >= ctx.maxStages) {
126
142
  return { unsupportedReason: 'stages reached maxStages=' + ctx.maxStages }
@@ -128,7 +144,9 @@ function walk(
128
144
 
129
145
  const model = ctx.models[modelName]
130
146
  if (!model) {
131
- return { unsupportedReason: 'model ' + modelName + ' not in relation metadata' }
147
+ return {
148
+ unsupportedReason: 'model ' + modelName + ' not in relation metadata',
149
+ }
132
150
  }
133
151
 
134
152
  const select = parentArgs.select
@@ -145,10 +163,17 @@ function walk(
145
163
  return { unsupportedReason: '_count not supported in MVP' }
146
164
  }
147
165
  if (hasWhereLikeRelationReference(parentArgs, model)) {
148
- return { unsupportedReason: 'relation used in where/orderBy/cursor is not supported in MVP' }
166
+ return {
167
+ unsupportedReason:
168
+ 'relation used in where/orderBy/cursor is not supported in MVP',
169
+ }
149
170
  }
150
171
 
151
- const projection = isPlainObject(select) ? select : (isPlainObject(include) ? include : null)
172
+ const projection = isPlainObject(select)
173
+ ? select
174
+ : isPlainObject(include)
175
+ ? include
176
+ : null
152
177
  if (!projection) {
153
178
  return {}
154
179
  }
@@ -174,7 +199,9 @@ function walk(
174
199
  }
175
200
 
176
201
  if (relationBranches.length === 0) {
177
- return { projectionAfterStrip: isSelectMode ? updatedProjection : undefined }
202
+ return {
203
+ projectionAfterStrip: isSelectMode ? updatedProjection : undefined,
204
+ }
178
205
  }
179
206
 
180
207
  for (const branch of relationBranches) {
@@ -187,22 +214,35 @@ function walk(
187
214
  if (relation.direction === 'implicitM2M') {
188
215
  return { unsupportedReason: 'implicit many-to-many not supported in MVP' }
189
216
  }
190
- if (relation.parentLinkFields.length === 0 || relation.childLinkFields.length === 0) {
191
- return { unsupportedReason: 'ambiguous relation metadata for ' + relation.name }
217
+ if (
218
+ relation.parentLinkFields.length === 0 ||
219
+ relation.childLinkFields.length === 0
220
+ ) {
221
+ return {
222
+ unsupportedReason: 'ambiguous relation metadata for ' + relation.name,
223
+ }
192
224
  }
193
225
  if (relation.parentLinkFields.length !== relation.childLinkFields.length) {
194
- return { unsupportedReason: 'mismatched link field counts for ' + relation.name }
226
+ return {
227
+ unsupportedReason: 'mismatched link field counts for ' + relation.name,
228
+ }
195
229
  }
196
230
  if (!ctx.models[relation.type]) {
197
231
  return {
198
- unsupportedReason: 'target model ' + relation.type +
199
- ' not in relation metadata for ' + (parentPath ? parentPath + '.' : '') + branch.name,
232
+ unsupportedReason:
233
+ 'target model ' +
234
+ relation.type +
235
+ ' not in relation metadata for ' +
236
+ (parentPath ? parentPath + '.' : '') +
237
+ branch.name,
200
238
  }
201
239
  }
202
240
 
203
241
  if (branch.value !== true && !isPlainObject(branch.value)) {
204
242
  return {
205
- unsupportedReason: 'invalid relation projection value for ' + branch.name +
243
+ unsupportedReason:
244
+ 'invalid relation projection value for ' +
245
+ branch.name +
206
246
  ' (expected true or plain object)',
207
247
  }
208
248
  }
@@ -210,7 +250,10 @@ function walk(
210
250
  for (const linkField of relation.parentLinkFields) {
211
251
  if (localOmit && localOmit[linkField] === true) {
212
252
  const where = parentPath ? parentPath + '.' : 'root.'
213
- return { unsupportedReason: 'required parent link field omitted: ' + where + linkField }
253
+ return {
254
+ unsupportedReason:
255
+ 'required parent link field omitted: ' + where + linkField,
256
+ }
214
257
  }
215
258
  }
216
259
 
@@ -222,14 +265,22 @@ function walk(
222
265
  }
223
266
  }
224
267
 
225
- const relationArgs: Record<string, unknown> = branch.value === true ? {} : branch.value
268
+ const relationArgs: Record<string, unknown> =
269
+ branch.value === true ? {} : branch.value
226
270
 
227
- const allowedArgs = relation.isList ? ALLOWED_TO_MANY_ARGS : ALLOWED_TO_ONE_ARGS
271
+ const allowedArgs = relation.isList
272
+ ? ALLOWED_TO_MANY_ARGS
273
+ : ALLOWED_TO_ONE_ARGS
228
274
  for (const key of Object.keys(relationArgs)) {
229
275
  if (!allowedArgs.has(key)) {
230
276
  return {
231
- unsupportedReason: 'unsupported arg "' + key + '" for ' +
232
- (relation.isList ? 'to-many' : 'to-one') + ' relation ' + relation.name,
277
+ unsupportedReason:
278
+ 'unsupported arg "' +
279
+ key +
280
+ '" for ' +
281
+ (relation.isList ? 'to-many' : 'to-one') +
282
+ ' relation ' +
283
+ relation.name,
233
284
  }
234
285
  }
235
286
  }
@@ -237,12 +288,16 @@ function walk(
237
288
  const targetModel = ctx.models[relation.type]
238
289
  if (hasWhereLikeRelationReference(relationArgs, targetModel)) {
239
290
  return {
240
- unsupportedReason: 'nested relation used in where/orderBy/cursor for ' +
241
- relation.name + ' is not supported in MVP',
291
+ unsupportedReason:
292
+ 'nested relation used in where/orderBy/cursor for ' +
293
+ relation.name +
294
+ ' is not supported in MVP',
242
295
  }
243
296
  }
244
297
 
245
- const relationPath = parentPath ? parentPath + '.' + branch.name : branch.name
298
+ const relationPath = parentPath
299
+ ? parentPath + '.' + branch.name
300
+ : branch.name
246
301
 
247
302
  const { select: _s, include: _i, omit: _o, ...stageArgs } = relationArgs
248
303
 
@@ -263,7 +318,13 @@ function walk(
263
318
  isPlainObject(relationArgs.omit)
264
319
 
265
320
  if (hasNestedProjection) {
266
- const nested = walk(ctx, relation.type, relationPath, relationArgs, depth + 1)
321
+ const nested = walk(
322
+ ctx,
323
+ relation.type,
324
+ relationPath,
325
+ relationArgs,
326
+ depth + 1,
327
+ )
267
328
  if (nested.unsupportedReason) return nested
268
329
 
269
330
  if (nested.projectionAfterStrip) {
@@ -278,7 +339,9 @@ function walk(
278
339
  return { projectionAfterStrip: isSelectMode ? updatedProjection : undefined }
279
340
  }
280
341
 
281
- export function planAutoInclude(input: AutoIncludePlannerInput): AutoIncludePlan {
342
+ export function planAutoInclude(
343
+ input: AutoIncludePlannerInput,
344
+ ): AutoIncludePlan {
282
345
  const maxDepth = input.maxDepth ?? DEFAULT_AUTO_INCLUDE_MAX_DEPTH
283
346
  const maxStages = input.maxStages ?? DEFAULT_AUTO_INCLUDE_MAX_STAGES
284
347
 
@@ -297,7 +360,8 @@ export function planAutoInclude(input: AutoIncludePlannerInput): AutoIncludePlan
297
360
  rootArgs: input.args,
298
361
  stages: [],
299
362
  internalFieldPaths: [],
300
- unsupportedReason: 'auto-progressive fallback: ' + result.unsupportedReason,
363
+ unsupportedReason:
364
+ 'auto-progressive fallback: ' + result.unsupportedReason,
301
365
  }
302
366
  }
303
367
 
@@ -309,7 +373,9 @@ export function planAutoInclude(input: AutoIncludePlannerInput): AutoIncludePlan
309
373
  delete rootArgs.include
310
374
  } else if (rootModel && isPlainObject(input.args.include)) {
311
375
  const stripped = Object.fromEntries(
312
- Object.entries(input.args.include).filter(([k]) => !rootModel.relations[k]),
376
+ Object.entries(input.args.include).filter(
377
+ ([k]) => !rootModel.relations[k],
378
+ ),
313
379
  )
314
380
  if (Object.keys(stripped).length > 0) {
315
381
  rootArgs.include = stripped
@@ -323,4 +389,4 @@ export function planAutoInclude(input: AutoIncludePlannerInput): AutoIncludePlan
323
389
  stages: ctx.stages,
324
390
  internalFieldPaths: ctx.internalFieldPaths,
325
391
  }
326
- }
392
+ }
@@ -1,8 +1,5 @@
1
1
  import { isPlainObject } from './misc'
2
- import type {
3
- ModelRelationField,
4
- ModelRelationMap,
5
- } from './autoIncludePlanner'
2
+ import type { ModelRelationField, ModelRelationMap } from './autoIncludePlanner'
6
3
 
7
4
  export type GuardedAutoIncludeStage = {
8
5
  relationPath: string
@@ -36,7 +33,15 @@ export const DEFAULT_GUARDED_MAX_STAGES = 20
36
33
 
37
34
  const ALLOWED_TO_ONE_STAGE_ARGS = new Set(['select', 'include', 'omit'])
38
35
  const ALLOWED_TO_MANY_STAGE_ARGS = new Set([
39
- 'select', 'include', 'omit', 'where', 'orderBy', 'take', 'skip', 'cursor', 'distinct',
36
+ 'select',
37
+ 'include',
38
+ 'omit',
39
+ 'where',
40
+ 'orderBy',
41
+ 'take',
42
+ 'skip',
43
+ 'cursor',
44
+ 'distinct',
40
45
  ])
41
46
 
42
47
  function containsCountProjection(value: unknown): boolean {
@@ -49,7 +54,10 @@ function containsCountProjection(value: unknown): boolean {
49
54
  }
50
55
 
51
56
  function projectionHasCount(node: Record<string, unknown>): boolean {
52
- return containsCountProjection(node.select) || containsCountProjection(node.include)
57
+ return (
58
+ containsCountProjection(node.select) ||
59
+ containsCountProjection(node.include)
60
+ )
53
61
  }
54
62
 
55
63
  function rootHasRelationRefInFilter(
@@ -120,7 +128,8 @@ function whereMentionsField(where: unknown, fieldName: string): boolean {
120
128
  if (key === 'AND' || key === 'OR' || key === 'NOT') {
121
129
  const sub = where[key]
122
130
  if (Array.isArray(sub)) {
123
- for (const item of sub) if (whereMentionsField(item, fieldName)) return true
131
+ for (const item of sub)
132
+ if (whereMentionsField(item, fieldName)) return true
124
133
  } else if (whereMentionsField(sub, fieldName)) {
125
134
  return true
126
135
  }
@@ -129,7 +138,10 @@ function whereMentionsField(where: unknown, fieldName: string): boolean {
129
138
  return false
130
139
  }
131
140
 
132
- function rejectIncludeOrOmit(node: Record<string, unknown>, label: string): string | null {
141
+ function rejectIncludeOrOmit(
142
+ node: Record<string, unknown>,
143
+ label: string,
144
+ ): string | null {
133
145
  if (isPlainObject(node.include)) {
134
146
  return label + ' uses include (guarded MVP supports select only)'
135
147
  }
@@ -169,7 +181,9 @@ function walkRoot(
169
181
 
170
182
  const model = ctx.models[modelName]
171
183
  if (!model) {
172
- return { unsupportedReason: 'model ' + modelName + ' not in relation metadata' }
184
+ return {
185
+ unsupportedReason: 'model ' + modelName + ' not in relation metadata',
186
+ }
173
187
  }
174
188
 
175
189
  const bodyIncludeOmit = rejectIncludeOrOmit(parentBody, 'root body')
@@ -178,10 +192,14 @@ function walkRoot(
178
192
  if (shapeIncludeOmit) return { unsupportedReason: shapeIncludeOmit }
179
193
 
180
194
  if (projectionHasCount(parentBody)) {
181
- return { unsupportedReason: '_count in root body not supported in guarded MVP' }
195
+ return {
196
+ unsupportedReason: '_count in root body not supported in guarded MVP',
197
+ }
182
198
  }
183
199
  if (projectionHasCount(parentShape)) {
184
- return { unsupportedReason: '_count in root shape not supported in guarded MVP' }
200
+ return {
201
+ unsupportedReason: '_count in root shape not supported in guarded MVP',
202
+ }
185
203
  }
186
204
 
187
205
  if (isRejectableWhere(parentBody.where)) {
@@ -192,10 +210,16 @@ function walkRoot(
192
210
  }
193
211
 
194
212
  if (rootHasRelationRefInFilter(parentBody, model)) {
195
- return { unsupportedReason: 'root body where/orderBy/cursor relation ref not supported' }
213
+ return {
214
+ unsupportedReason:
215
+ 'root body where/orderBy/cursor relation ref not supported',
216
+ }
196
217
  }
197
218
  if (rootHasRelationRefInFilter(parentShape, model)) {
198
- return { unsupportedReason: 'root shape where/orderBy/cursor relation ref not supported' }
219
+ return {
220
+ unsupportedReason:
221
+ 'root shape where/orderBy/cursor relation ref not supported',
222
+ }
199
223
  }
200
224
 
201
225
  const bodySelect = parentBody.select
@@ -229,10 +253,17 @@ function walkRoot(
229
253
  const shapeBranch = shapeProjection[key]
230
254
  if (shapeBranch === undefined) {
231
255
  return {
232
- unsupportedReason: 'body projects relation "' + key + '" not present in guard shape at root',
256
+ unsupportedReason:
257
+ 'body projects relation "' +
258
+ key +
259
+ '" not present in guard shape at root',
233
260
  }
234
261
  }
235
- relationBranches.push({ name: key, bodyValue: value, shapeValue: shapeBranch })
262
+ relationBranches.push({
263
+ name: key,
264
+ bodyValue: value,
265
+ shapeValue: shapeBranch,
266
+ })
236
267
  } else {
237
268
  updatedBodyProjection[key] = value
238
269
  if (key in shapeProjection) {
@@ -249,30 +280,51 @@ function walkRoot(
249
280
  const relation = model.relations[branch.name]
250
281
 
251
282
  if (relation.direction === 'implicitM2M') {
252
- return { unsupportedReason: 'implicit many-to-many not supported in guarded MVP' }
283
+ return {
284
+ unsupportedReason: 'implicit many-to-many not supported in guarded MVP',
285
+ }
253
286
  }
254
- if (relation.parentLinkFields.length === 0 || relation.childLinkFields.length === 0) {
255
- return { unsupportedReason: 'ambiguous relation metadata for ' + relation.name }
287
+ if (
288
+ relation.parentLinkFields.length === 0 ||
289
+ relation.childLinkFields.length === 0
290
+ ) {
291
+ return {
292
+ unsupportedReason: 'ambiguous relation metadata for ' + relation.name,
293
+ }
256
294
  }
257
295
  if (relation.parentLinkFields.length !== relation.childLinkFields.length) {
258
- return { unsupportedReason: 'mismatched link field counts for ' + relation.name }
296
+ return {
297
+ unsupportedReason: 'mismatched link field counts for ' + relation.name,
298
+ }
259
299
  }
260
300
  if (relation.parentLinkFields.length !== 1) {
261
301
  return {
262
- unsupportedReason: 'composite link fields not supported for guarded stage ' + relation.name,
302
+ unsupportedReason:
303
+ 'composite link fields not supported for guarded stage ' +
304
+ relation.name,
263
305
  }
264
306
  }
265
307
  if (!ctx.models[relation.type]) {
266
308
  return {
267
- unsupportedReason: 'target model ' + relation.type + ' not in relation metadata for ' + branch.name,
309
+ unsupportedReason:
310
+ 'target model ' +
311
+ relation.type +
312
+ ' not in relation metadata for ' +
313
+ branch.name,
268
314
  }
269
315
  }
270
316
 
271
317
  if (branch.bodyValue !== true && !isPlainObject(branch.bodyValue)) {
272
- return { unsupportedReason: 'invalid relation projection body for ' + branch.name }
318
+ return {
319
+ unsupportedReason:
320
+ 'invalid relation projection body for ' + branch.name,
321
+ }
273
322
  }
274
323
  if (branch.shapeValue !== true && !isPlainObject(branch.shapeValue)) {
275
- return { unsupportedReason: 'invalid relation projection shape for ' + branch.name }
324
+ return {
325
+ unsupportedReason:
326
+ 'invalid relation projection shape for ' + branch.name,
327
+ }
276
328
  }
277
329
 
278
330
  const parentKey = relation.parentLinkFields[0]
@@ -286,71 +338,141 @@ function walkRoot(
286
338
  updatedShapeProjection[parentKey] = true
287
339
  }
288
340
 
289
- const relationBodyArgs: Record<string, unknown> = branch.bodyValue === true ? {} : branch.bodyValue
290
- const relationShapeArgs: Record<string, unknown> = branch.shapeValue === true ? {} : branch.shapeValue
341
+ const relationBodyArgs: Record<string, unknown> =
342
+ branch.bodyValue === true ? {} : branch.bodyValue
343
+ const relationShapeArgs: Record<string, unknown> =
344
+ branch.shapeValue === true ? {} : branch.shapeValue
291
345
 
292
- const allowedArgs = relation.isList ? ALLOWED_TO_MANY_STAGE_ARGS : ALLOWED_TO_ONE_STAGE_ARGS
346
+ const allowedArgs = relation.isList
347
+ ? ALLOWED_TO_MANY_STAGE_ARGS
348
+ : ALLOWED_TO_ONE_STAGE_ARGS
293
349
  for (const key of Object.keys(relationBodyArgs)) {
294
350
  if (!allowedArgs.has(key)) {
295
351
  return {
296
- unsupportedReason: 'unsupported body arg "' + key + '" for ' +
297
- (relation.isList ? 'to-many' : 'to-one') + ' relation ' + relation.name,
352
+ unsupportedReason:
353
+ 'unsupported body arg "' +
354
+ key +
355
+ '" for ' +
356
+ (relation.isList ? 'to-many' : 'to-one') +
357
+ ' relation ' +
358
+ relation.name,
298
359
  }
299
360
  }
300
361
  }
301
362
  for (const key of Object.keys(relationShapeArgs)) {
302
363
  if (!allowedArgs.has(key)) {
303
364
  return {
304
- unsupportedReason: 'unsupported shape arg "' + key + '" for ' +
305
- (relation.isList ? 'to-many' : 'to-one') + ' relation ' + relation.name,
365
+ unsupportedReason:
366
+ 'unsupported shape arg "' +
367
+ key +
368
+ '" for ' +
369
+ (relation.isList ? 'to-many' : 'to-one') +
370
+ ' relation ' +
371
+ relation.name,
306
372
  }
307
373
  }
308
374
  }
309
375
 
310
376
  if (isPlainObject(relationBodyArgs.include)) {
311
- return { unsupportedReason: 'stage body uses include for ' + relation.name + ' (guarded MVP supports select only)' }
377
+ return {
378
+ unsupportedReason:
379
+ 'stage body uses include for ' +
380
+ relation.name +
381
+ ' (guarded MVP supports select only)',
382
+ }
312
383
  }
313
384
  if (isPlainObject(relationBodyArgs.omit)) {
314
- return { unsupportedReason: 'stage body uses omit for ' + relation.name + ' (guarded MVP supports select only)' }
385
+ return {
386
+ unsupportedReason:
387
+ 'stage body uses omit for ' +
388
+ relation.name +
389
+ ' (guarded MVP supports select only)',
390
+ }
315
391
  }
316
392
  if (isPlainObject(relationShapeArgs.include)) {
317
- return { unsupportedReason: 'stage shape uses include for ' + relation.name + ' (guarded MVP supports select only)' }
393
+ return {
394
+ unsupportedReason:
395
+ 'stage shape uses include for ' +
396
+ relation.name +
397
+ ' (guarded MVP supports select only)',
398
+ }
318
399
  }
319
400
  if (isPlainObject(relationShapeArgs.omit)) {
320
- return { unsupportedReason: 'stage shape uses omit for ' + relation.name + ' (guarded MVP supports select only)' }
401
+ return {
402
+ unsupportedReason:
403
+ 'stage shape uses omit for ' +
404
+ relation.name +
405
+ ' (guarded MVP supports select only)',
406
+ }
321
407
  }
322
408
 
323
409
  if (projectionHasCount(relationBodyArgs)) {
324
- return { unsupportedReason: '_count in stage body for ' + relation.name + ' not supported in guarded MVP' }
410
+ return {
411
+ unsupportedReason:
412
+ '_count in stage body for ' +
413
+ relation.name +
414
+ ' not supported in guarded MVP',
415
+ }
325
416
  }
326
417
  if (projectionHasCount(relationShapeArgs)) {
327
- return { unsupportedReason: '_count in stage shape for ' + relation.name + ' not supported in guarded MVP' }
418
+ return {
419
+ unsupportedReason:
420
+ '_count in stage shape for ' +
421
+ relation.name +
422
+ ' not supported in guarded MVP',
423
+ }
328
424
  }
329
425
 
330
426
  if (isRejectableWhere(relationBodyArgs.where)) {
331
- return { unsupportedReason: 'stage body where must be a plain object for ' + relation.name }
427
+ return {
428
+ unsupportedReason:
429
+ 'stage body where must be a plain object for ' + relation.name,
430
+ }
332
431
  }
333
432
  if (isRejectableWhere(relationShapeArgs.where)) {
334
- return { unsupportedReason: 'stage shape where must be a plain object for ' + relation.name }
433
+ return {
434
+ unsupportedReason:
435
+ 'stage shape where must be a plain object for ' + relation.name,
436
+ }
335
437
  }
336
438
 
337
- if (stageHasBlockedRelationRef(relationBodyArgs, ctx.models[relation.type])) {
338
- return { unsupportedReason: 'stage body orderBy/cursor relation ref not supported for ' + relation.name }
439
+ if (
440
+ stageHasBlockedRelationRef(relationBodyArgs, ctx.models[relation.type])
441
+ ) {
442
+ return {
443
+ unsupportedReason:
444
+ 'stage body orderBy/cursor relation ref not supported for ' +
445
+ relation.name,
446
+ }
339
447
  }
340
- if (stageHasBlockedRelationRef(relationShapeArgs, ctx.models[relation.type])) {
341
- return { unsupportedReason: 'stage shape orderBy/cursor relation ref not supported for ' + relation.name }
448
+ if (
449
+ stageHasBlockedRelationRef(relationShapeArgs, ctx.models[relation.type])
450
+ ) {
451
+ return {
452
+ unsupportedReason:
453
+ 'stage shape orderBy/cursor relation ref not supported for ' +
454
+ relation.name,
455
+ }
342
456
  }
343
457
 
344
458
  if (whereMentionsField(relationBodyArgs.where, childKey)) {
345
459
  return {
346
- unsupportedReason: 'FK collision: stage body where for ' + relation.name +
347
- ' already mentions child link field "' + childKey + '"',
460
+ unsupportedReason:
461
+ 'FK collision: stage body where for ' +
462
+ relation.name +
463
+ ' already mentions child link field "' +
464
+ childKey +
465
+ '"',
348
466
  }
349
467
  }
350
468
  if (whereMentionsField(relationShapeArgs.where, childKey)) {
351
469
  return {
352
- unsupportedReason: 'FK collision: stage shape where for ' + relation.name +
353
- ' already mentions child link field "' + childKey + '"',
470
+ unsupportedReason:
471
+ 'FK collision: stage shape where for ' +
472
+ relation.name +
473
+ ' already mentions child link field "' +
474
+ childKey +
475
+ '"',
354
476
  }
355
477
  }
356
478
 
@@ -449,7 +571,8 @@ export function planGuardedAutoInclude(
449
571
  rootShape: input.shape,
450
572
  stages: [],
451
573
  internalFieldPaths: [],
452
- unsupportedReason: 'guarded auto-progressive fallback: ' + result.unsupportedReason,
574
+ unsupportedReason:
575
+ 'guarded auto-progressive fallback: ' + result.unsupportedReason,
453
576
  }
454
577
  }
455
578
 
@@ -474,4 +597,4 @@ export function planGuardedAutoInclude(
474
597
  stages: ctx.stages,
475
598
  internalFieldPaths: ctx.internalFieldPaths,
476
599
  }
477
- }
600
+ }
@@ -90,7 +90,10 @@ function guarded(
90
90
  return d.guard(shape, caller) as GuardedDelegate
91
91
  }
92
92
 
93
- function createClientGoneChecker(res: Response, signal?: AbortSignal): () => boolean {
93
+ function createClientGoneChecker(
94
+ res: Response,
95
+ signal?: AbortSignal,
96
+ ): () => boolean {
94
97
  return () => signal?.aborted === true || res.writableEnded || res.destroyed
95
98
  }
96
99
 
@@ -178,7 +181,10 @@ async function runStage(
178
181
 
179
182
  const targetModel = models[rel.type]
180
183
  if (!targetModel) {
181
- throw new HttpError(500, 'Target model not in relation metadata: ' + rel.type)
184
+ throw new HttpError(
185
+ 500,
186
+ 'Target model not in relation metadata: ' + rel.type,
187
+ )
182
188
  }
183
189
 
184
190
  const stageArgs: Record<string, unknown> = { ...stage.stageArgs }
@@ -289,14 +295,24 @@ async function runGuardedAutoIncludeSingle(
289
295
  if (!okField) return
290
296
  } catch (err) {
291
297
  if (isAborted()) return
292
- console.error(LOG_PREFIX, 'guarded stage failed:', stage.relationPath, err)
298
+ console.error(
299
+ LOG_PREFIX,
300
+ 'guarded stage failed:',
301
+ stage.relationPath,
302
+ err,
303
+ )
293
304
  stageErrorMessage = mapError(err).message
294
305
  return
295
306
  }
296
307
 
297
308
  if (isAborted()) return
298
309
  completed++
299
- const okProg = sendSSEProgress(res, stage.relationPath, completed, plan.stages.length)
310
+ const okProg = sendSSEProgress(
311
+ res,
312
+ stage.relationPath,
313
+ completed,
314
+ plan.stages.length,
315
+ )
300
316
  if (!okProg) return
301
317
  })
302
318
 
@@ -336,7 +352,8 @@ export async function runGuardedAutoIncludeProgressive(
336
352
  } catch (err) {
337
353
  return handleGuardedFallback(
338
354
  options,
339
- 'guarded auto-progressive fallback: getExtendedClient failed: ' + mapError(err).message,
355
+ 'guarded auto-progressive fallback: getExtendedClient failed: ' +
356
+ mapError(err).message,
340
357
  )
341
358
  }
342
359
 
@@ -352,7 +369,8 @@ export async function runGuardedAutoIncludeProgressive(
352
369
  } catch (err) {
353
370
  return handleGuardedFallback(
354
371
  options,
355
- 'guarded auto-progressive fallback: resolve failed: ' + mapError(err).message,
372
+ 'guarded auto-progressive fallback: resolve failed: ' +
373
+ mapError(err).message,
356
374
  )
357
375
  }
358
376
 
@@ -376,4 +394,4 @@ export async function runGuardedAutoIncludeProgressive(
376
394
  }
377
395
 
378
396
  return runGuardedAutoIncludeSingle(options, plan, extended)
379
- }
397
+ }