prisma-generator-express 1.62.3 → 1.63.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +234 -95
- package/dist/generators/generateRouteConfigType.js +26 -6
- package/dist/generators/generateRouteConfigType.js.map +1 -1
- package/dist/generators/generateRouter.js +245 -44
- package/dist/generators/generateRouter.js.map +1 -1
- package/dist/generators/generateRouterFastify.js +100 -28
- package/dist/generators/generateRouterFastify.js.map +1 -1
- package/dist/generators/generateRouterHono.js +104 -36
- package/dist/generators/generateRouterHono.js.map +1 -1
- package/dist/utils/copyFiles.js +2 -0
- package/dist/utils/copyFiles.js.map +1 -1
- package/package.json +1 -1
- package/src/copy/docsRenderer.ts +1 -0
- package/src/copy/guardVariantError.ts +28 -0
- package/src/copy/guardVariantRouting.ts +109 -0
- package/src/copy/projectionDefaults.ts +5 -6
- package/src/copy/routeConfig.hono.ts +15 -5
- package/src/copy/routeConfig.ts +220 -27
- package/src/generators/generateRouteConfigType.ts +37 -6
- package/src/generators/generateRouter.ts +246 -44
- package/src/generators/generateRouterFastify.ts +100 -28
- package/src/generators/generateRouterHono.ts +104 -36
- package/src/utils/copyFiles.ts +2 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
export type GuardVariantResolutionInput =
|
|
2
|
+
| { kind: 'single' }
|
|
3
|
+
| {
|
|
4
|
+
kind: 'named'
|
|
5
|
+
keys: readonly string[]
|
|
6
|
+
caller?: string
|
|
7
|
+
reservedKeys: ReadonlySet<string>
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type GuardVariantResolution =
|
|
11
|
+
| { ok: true; key: string }
|
|
12
|
+
| {
|
|
13
|
+
ok: false
|
|
14
|
+
code:
|
|
15
|
+
| 'reserved-key'
|
|
16
|
+
| 'missing-caller'
|
|
17
|
+
| 'ambiguous-caller'
|
|
18
|
+
| 'unknown-caller'
|
|
19
|
+
caller?: string
|
|
20
|
+
key?: string
|
|
21
|
+
keys: readonly string[]
|
|
22
|
+
matches?: readonly string[]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function matchVariantPatterns(
|
|
26
|
+
keys: readonly string[],
|
|
27
|
+
caller: string,
|
|
28
|
+
): string[] {
|
|
29
|
+
const callerParts = caller.split('/')
|
|
30
|
+
const matches: string[] = []
|
|
31
|
+
|
|
32
|
+
for (const pattern of keys) {
|
|
33
|
+
if (!pattern.includes(':')) continue
|
|
34
|
+
|
|
35
|
+
const patternParts = pattern.split('/')
|
|
36
|
+
if (patternParts.length !== callerParts.length) continue
|
|
37
|
+
|
|
38
|
+
let matchesCaller = true
|
|
39
|
+
|
|
40
|
+
for (let index = 0; index < patternParts.length; index++) {
|
|
41
|
+
if (patternParts[index].startsWith(':')) continue
|
|
42
|
+
if (patternParts[index] !== callerParts[index]) {
|
|
43
|
+
matchesCaller = false
|
|
44
|
+
break
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (matchesCaller) matches.push(pattern)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return matches
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function resolveGuardVariantKey(
|
|
55
|
+
input: GuardVariantResolutionInput,
|
|
56
|
+
): GuardVariantResolution {
|
|
57
|
+
if (input.kind === 'single') {
|
|
58
|
+
return { ok: true, key: '_default' }
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const { keys, caller, reservedKeys } = input
|
|
62
|
+
|
|
63
|
+
for (const key of keys) {
|
|
64
|
+
if (reservedKeys.has(key)) {
|
|
65
|
+
return {
|
|
66
|
+
ok: false,
|
|
67
|
+
code: 'reserved-key',
|
|
68
|
+
key,
|
|
69
|
+
keys,
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const hasDefault = keys.includes('default')
|
|
75
|
+
|
|
76
|
+
if (typeof caller !== 'string') {
|
|
77
|
+
if (hasDefault) return { ok: true, key: 'default' }
|
|
78
|
+
return { ok: false, code: 'missing-caller', keys }
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (caller.trim().length === 0) {
|
|
82
|
+
if (hasDefault) return { ok: true, key: 'default' }
|
|
83
|
+
return { ok: false, code: 'unknown-caller', caller, keys }
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (keys.includes(caller)) {
|
|
87
|
+
return { ok: true, key: caller }
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const matches = matchVariantPatterns(keys, caller)
|
|
91
|
+
|
|
92
|
+
if (matches.length === 1) {
|
|
93
|
+
return { ok: true, key: matches[0] }
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (matches.length > 1) {
|
|
97
|
+
return {
|
|
98
|
+
ok: false,
|
|
99
|
+
code: 'ambiguous-caller',
|
|
100
|
+
caller,
|
|
101
|
+
keys,
|
|
102
|
+
matches,
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (hasDefault) return { ok: true, key: 'default' }
|
|
107
|
+
|
|
108
|
+
return { ok: false, code: 'unknown-caller', caller, keys }
|
|
109
|
+
}
|
|
@@ -88,7 +88,7 @@ async function callShapeFn(
|
|
|
88
88
|
|
|
89
89
|
async function resolveShape(
|
|
90
90
|
input: unknown,
|
|
91
|
-
|
|
91
|
+
resolvedKey: string | undefined,
|
|
92
92
|
resolveContext: ContextResolver | undefined,
|
|
93
93
|
): Promise<Record<string, unknown> | null> {
|
|
94
94
|
if (!input) return null
|
|
@@ -100,9 +100,8 @@ async function resolveShape(
|
|
|
100
100
|
if (!isPlainObject(input)) return null
|
|
101
101
|
if (isDirectGuardShape(input)) return input
|
|
102
102
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
if (entry === undefined && 'default' in input) entry = input['default']
|
|
103
|
+
if (resolvedKey === undefined) return null
|
|
104
|
+
const entry = input[resolvedKey]
|
|
106
105
|
if (entry === undefined) return null
|
|
107
106
|
|
|
108
107
|
if (typeof entry === 'function') {
|
|
@@ -376,7 +375,7 @@ function applyForcedWhere(opts: WhereMergeOptions): void {
|
|
|
376
375
|
|
|
377
376
|
export async function applyDroppedGuard(
|
|
378
377
|
shape: unknown,
|
|
379
|
-
|
|
378
|
+
resolvedKey: string | undefined,
|
|
380
379
|
resolveContext: ContextResolver | undefined,
|
|
381
380
|
opKind: OpKind,
|
|
382
381
|
targets: {
|
|
@@ -386,7 +385,7 @@ export async function applyDroppedGuard(
|
|
|
386
385
|
ensureReadTarget: () => Record<string, unknown>,
|
|
387
386
|
ensureWriteTarget: () => Record<string, unknown>,
|
|
388
387
|
): Promise<void> {
|
|
389
|
-
const resolved = await resolveShape(shape,
|
|
388
|
+
const resolved = await resolveShape(shape, resolvedKey, resolveContext)
|
|
390
389
|
if (!resolved) return
|
|
391
390
|
|
|
392
391
|
const projection = buildDefaultProjectionBody(resolved)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Context } from 'hono'
|
|
2
|
+
import type { GuardVariantResolution } from './guardVariantRouting'
|
|
2
3
|
import type {
|
|
3
4
|
BaseOperationConfig,
|
|
4
5
|
BaseRouteConfig,
|
|
@@ -35,6 +36,8 @@ export type HonoInternalVariables = {
|
|
|
35
36
|
routeConfig?: { pagination?: PaginationConfig }
|
|
36
37
|
guardShape?: Record<string, unknown>
|
|
37
38
|
guardCaller?: string
|
|
39
|
+
guardVariantKey?: string
|
|
40
|
+
guardVariantFailure?: Extract<GuardVariantResolution, { ok: false }>
|
|
38
41
|
resultData?: unknown
|
|
39
42
|
resultStatus?: number
|
|
40
43
|
}
|
|
@@ -58,10 +61,11 @@ export type HonoHookHandler<TEnv extends HonoEnvBase = HonoEnvBase> = HonoBefore
|
|
|
58
61
|
export type OperationConfig<
|
|
59
62
|
TShape = Record<string, unknown>,
|
|
60
63
|
TEnv extends HonoEnvBase = HonoEnvBase,
|
|
61
|
-
> =
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
> = BaseOperationConfig<
|
|
65
|
+
HonoBeforeHook<TEnv>,
|
|
66
|
+
TShape,
|
|
67
|
+
HonoAfterHook<TEnv>
|
|
68
|
+
>
|
|
65
69
|
|
|
66
70
|
export type UpdateEachConfig<TEnv extends HonoEnvBase = HonoEnvBase> = {
|
|
67
71
|
before?: HonoBeforeHook<TEnv>[]
|
|
@@ -94,7 +98,13 @@ export type RouteConfig<
|
|
|
94
98
|
TCtx = unknown,
|
|
95
99
|
TEnv extends HonoEnvBase = HonoEnvBase,
|
|
96
100
|
> = Omit<
|
|
97
|
-
BaseRouteConfig<
|
|
101
|
+
BaseRouteConfig<
|
|
102
|
+
HonoBeforeHook<TEnv>,
|
|
103
|
+
Context<GeneratedHonoEnv<TEnv>>,
|
|
104
|
+
TShape,
|
|
105
|
+
TCtx,
|
|
106
|
+
HonoAfterHook<TEnv>
|
|
107
|
+
>,
|
|
98
108
|
HonoOpKeys
|
|
99
109
|
> & {
|
|
100
110
|
findUnique?: OperationConfig<TShape, TEnv> | false
|
package/src/copy/routeConfig.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import { GUARD_SHAPE_CONFIG_KEYS } from './guardHelpers'
|
|
2
|
+
import { isPlainObject } from './misc'
|
|
3
|
+
import {
|
|
4
|
+
resolveGuardVariantKey,
|
|
5
|
+
type GuardVariantResolution,
|
|
6
|
+
} from './guardVariantRouting'
|
|
7
|
+
|
|
1
8
|
export interface QueryBuilderConfig {
|
|
2
9
|
enabled?: boolean
|
|
3
10
|
port?: number
|
|
@@ -87,23 +94,43 @@ export type ProgressiveVariantConfig =
|
|
|
87
94
|
| ManualProgressiveVariantConfig
|
|
88
95
|
| AutoIncludeProgressiveVariantConfig
|
|
89
96
|
|
|
90
|
-
export
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
97
|
+
export type VariantEntry<TShape, TBefore, TAfter> = {
|
|
98
|
+
shape: TShape
|
|
99
|
+
before?: TBefore[]
|
|
100
|
+
after?: TAfter[]
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
type OperationShapeConfig<TShape, TBefore, TAfter> =
|
|
104
|
+
| {
|
|
105
|
+
shape?: TShape
|
|
106
|
+
variants?: never
|
|
107
|
+
}
|
|
108
|
+
| {
|
|
109
|
+
shape?: never
|
|
110
|
+
variants: Record<string, VariantEntry<TShape, TBefore, TAfter>>
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export type BaseOperationConfig<
|
|
114
|
+
TBefore,
|
|
115
|
+
TShape = Record<string, unknown>,
|
|
116
|
+
TAfter = TBefore,
|
|
117
|
+
> = OperationShapeConfig<TShape, TBefore, TAfter> & {
|
|
118
|
+
before?: TBefore[]
|
|
119
|
+
after?: TAfter[]
|
|
94
120
|
pagination?: Partial<PaginationConfig>
|
|
95
121
|
}
|
|
96
122
|
|
|
97
|
-
export interface BaseUpdateEachConfig<
|
|
98
|
-
before?:
|
|
99
|
-
after?:
|
|
123
|
+
export interface BaseUpdateEachConfig<TBefore, TAfter = TBefore> {
|
|
124
|
+
before?: TBefore[]
|
|
125
|
+
after?: TAfter[]
|
|
100
126
|
}
|
|
101
127
|
|
|
102
128
|
export interface BaseRouteConfig<
|
|
103
|
-
|
|
129
|
+
TBefore,
|
|
104
130
|
RequestType,
|
|
105
131
|
TShape = Record<string, unknown>,
|
|
106
132
|
TCtx = unknown,
|
|
133
|
+
TAfter = TBefore,
|
|
107
134
|
> {
|
|
108
135
|
enableAll?: boolean
|
|
109
136
|
addModelPrefix?: boolean
|
|
@@ -125,30 +152,196 @@ export interface BaseRouteConfig<
|
|
|
125
152
|
resolveContext?: (request: RequestType) => TCtx | Promise<TCtx>
|
|
126
153
|
queryBuilder?: QueryBuilderConfig | false
|
|
127
154
|
pagination?: PaginationConfig
|
|
128
|
-
findUnique?: BaseOperationConfig<
|
|
129
|
-
findUniqueOrThrow?: BaseOperationConfig<
|
|
130
|
-
findFirst?: BaseOperationConfig<
|
|
131
|
-
findFirstOrThrow?: BaseOperationConfig<
|
|
132
|
-
findMany?: BaseOperationConfig<
|
|
133
|
-
findManyPaginated?: BaseOperationConfig<
|
|
134
|
-
create?: BaseOperationConfig<
|
|
135
|
-
createMany?: BaseOperationConfig<
|
|
136
|
-
createManyAndReturn?: BaseOperationConfig<
|
|
137
|
-
update?: BaseOperationConfig<
|
|
138
|
-
updateMany?: BaseOperationConfig<
|
|
139
|
-
updateManyAndReturn?: BaseOperationConfig<
|
|
140
|
-
upsert?: BaseOperationConfig<
|
|
141
|
-
delete?: BaseOperationConfig<
|
|
142
|
-
deleteMany?: BaseOperationConfig<
|
|
143
|
-
updateEach?: BaseUpdateEachConfig<
|
|
144
|
-
aggregate?: BaseOperationConfig<
|
|
145
|
-
count?: BaseOperationConfig<
|
|
146
|
-
groupBy?: BaseOperationConfig<
|
|
155
|
+
findUnique?: BaseOperationConfig<TBefore, TShape, TAfter> | false
|
|
156
|
+
findUniqueOrThrow?: BaseOperationConfig<TBefore, TShape, TAfter> | false
|
|
157
|
+
findFirst?: BaseOperationConfig<TBefore, TShape, TAfter> | false
|
|
158
|
+
findFirstOrThrow?: BaseOperationConfig<TBefore, TShape, TAfter> | false
|
|
159
|
+
findMany?: BaseOperationConfig<TBefore, TShape, TAfter> | false
|
|
160
|
+
findManyPaginated?: BaseOperationConfig<TBefore, TShape, TAfter> | false
|
|
161
|
+
create?: BaseOperationConfig<TBefore, TShape, TAfter> | false
|
|
162
|
+
createMany?: BaseOperationConfig<TBefore, TShape, TAfter> | false
|
|
163
|
+
createManyAndReturn?: BaseOperationConfig<TBefore, TShape, TAfter> | false
|
|
164
|
+
update?: BaseOperationConfig<TBefore, TShape, TAfter> | false
|
|
165
|
+
updateMany?: BaseOperationConfig<TBefore, TShape, TAfter> | false
|
|
166
|
+
updateManyAndReturn?: BaseOperationConfig<TBefore, TShape, TAfter> | false
|
|
167
|
+
upsert?: BaseOperationConfig<TBefore, TShape, TAfter> | false
|
|
168
|
+
delete?: BaseOperationConfig<TBefore, TShape, TAfter> | false
|
|
169
|
+
deleteMany?: BaseOperationConfig<TBefore, TShape, TAfter> | false
|
|
170
|
+
updateEach?: BaseUpdateEachConfig<TBefore, TAfter>
|
|
171
|
+
aggregate?: BaseOperationConfig<TBefore, TShape, TAfter> | false
|
|
172
|
+
count?: BaseOperationConfig<TBefore, TShape, TAfter> | false
|
|
173
|
+
groupBy?: BaseOperationConfig<TBefore, TShape, TAfter> | false
|
|
147
174
|
}
|
|
148
175
|
|
|
149
176
|
export type OperationConfig = BaseOperationConfig<unknown>
|
|
150
177
|
export type RouteConfig = BaseRouteConfig<unknown, unknown>
|
|
151
178
|
|
|
179
|
+
export type NormalizedGuardRouting =
|
|
180
|
+
| { kind: 'none' }
|
|
181
|
+
| { kind: 'single' }
|
|
182
|
+
| { kind: 'named'; keys: readonly string[] }
|
|
183
|
+
|
|
184
|
+
export type NormalizedVariantHooks<TBefore, TAfter> = Readonly<
|
|
185
|
+
Record<
|
|
186
|
+
string,
|
|
187
|
+
{
|
|
188
|
+
before: readonly TBefore[]
|
|
189
|
+
after: readonly TAfter[]
|
|
190
|
+
}
|
|
191
|
+
>
|
|
192
|
+
>
|
|
193
|
+
|
|
194
|
+
export interface NormalizedOperationConfig<TBefore, TAfter> {
|
|
195
|
+
guardShape?: Record<string, unknown>
|
|
196
|
+
guardRouting: NormalizedGuardRouting
|
|
197
|
+
operationBefore: readonly TBefore[]
|
|
198
|
+
operationAfter: readonly TAfter[]
|
|
199
|
+
variantHooks: NormalizedVariantHooks<TBefore, TAfter>
|
|
200
|
+
pagination?: Readonly<Partial<PaginationConfig>>
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
type OperationConfigInput<TBefore, TAfter> = {
|
|
204
|
+
before?: TBefore[]
|
|
205
|
+
after?: TAfter[]
|
|
206
|
+
shape?: unknown
|
|
207
|
+
variants?: Record<
|
|
208
|
+
string,
|
|
209
|
+
{
|
|
210
|
+
shape?: unknown
|
|
211
|
+
before?: TBefore[]
|
|
212
|
+
after?: TAfter[]
|
|
213
|
+
}
|
|
214
|
+
>
|
|
215
|
+
pagination?: Partial<PaginationConfig>
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function classifyGuardRouting(shape: unknown): NormalizedGuardRouting {
|
|
219
|
+
if (shape === undefined) return { kind: 'none' }
|
|
220
|
+
if (typeof shape === 'function') return { kind: 'single' }
|
|
221
|
+
if (!isPlainObject(shape)) return { kind: 'single' }
|
|
222
|
+
|
|
223
|
+
const keys = Object.keys(shape)
|
|
224
|
+
const isSingle =
|
|
225
|
+
keys.length === 0 ||
|
|
226
|
+
keys.every((key) => GUARD_SHAPE_CONFIG_KEYS.has(key))
|
|
227
|
+
|
|
228
|
+
return isSingle ? { kind: 'single' } : { kind: 'named', keys }
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export function validateOperationConfig(
|
|
232
|
+
config: { shape?: unknown; variants?: unknown } | undefined,
|
|
233
|
+
location: string,
|
|
234
|
+
): void {
|
|
235
|
+
if (!config) return
|
|
236
|
+
|
|
237
|
+
const hasShape = config.shape !== undefined
|
|
238
|
+
const hasVariants = config.variants !== undefined
|
|
239
|
+
|
|
240
|
+
if (hasShape && hasVariants) {
|
|
241
|
+
throw new Error(location + ': shape and variants cannot both be defined')
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (!hasVariants) return
|
|
245
|
+
|
|
246
|
+
const variants = config.variants
|
|
247
|
+
if (!isPlainObject(variants)) {
|
|
248
|
+
throw new Error(location + ': variants must be a non-array object')
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const entries = Object.entries(variants)
|
|
252
|
+
if (entries.length === 0) {
|
|
253
|
+
throw new Error(location + ': variants must contain at least one entry')
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
for (const [key, rawEntry] of entries) {
|
|
257
|
+
if (GUARD_SHAPE_CONFIG_KEYS.has(key)) {
|
|
258
|
+
throw new Error(
|
|
259
|
+
location + ': variant name "' + key +
|
|
260
|
+
'" collides with a reserved guard shape key',
|
|
261
|
+
)
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (!isPlainObject(rawEntry)) {
|
|
265
|
+
throw new Error(
|
|
266
|
+
location + ': variant "' + key + '" must be an object with a shape',
|
|
267
|
+
)
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (rawEntry.shape === undefined) {
|
|
271
|
+
throw new Error(
|
|
272
|
+
location + ': variant "' + key + '" is missing "shape"',
|
|
273
|
+
)
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export function validateUpdateEachConfig(
|
|
279
|
+
config: { variants?: unknown } | undefined,
|
|
280
|
+
location: string,
|
|
281
|
+
): void {
|
|
282
|
+
if (config?.variants !== undefined) {
|
|
283
|
+
throw new Error(location + ': updateEach does not support variants')
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
export function normalizeOperation<TBefore, TAfter>(
|
|
288
|
+
config: OperationConfigInput<TBefore, TAfter> | undefined,
|
|
289
|
+
): NormalizedOperationConfig<TBefore, TAfter> {
|
|
290
|
+
const operationBefore = config?.before ?? []
|
|
291
|
+
const operationAfter = config?.after ?? []
|
|
292
|
+
|
|
293
|
+
if (config?.variants !== undefined) {
|
|
294
|
+
const entries = Object.entries(config.variants)
|
|
295
|
+
|
|
296
|
+
return {
|
|
297
|
+
guardShape: Object.fromEntries(
|
|
298
|
+
entries.map(([key, entry]) => [key, entry.shape]),
|
|
299
|
+
),
|
|
300
|
+
guardRouting: {
|
|
301
|
+
kind: 'named',
|
|
302
|
+
keys: entries.map(([key]) => key),
|
|
303
|
+
},
|
|
304
|
+
operationBefore,
|
|
305
|
+
operationAfter,
|
|
306
|
+
variantHooks: Object.fromEntries(
|
|
307
|
+
entries.map(([key, entry]) => [
|
|
308
|
+
key,
|
|
309
|
+
{
|
|
310
|
+
before: entry.before ?? [],
|
|
311
|
+
after: entry.after ?? [],
|
|
312
|
+
},
|
|
313
|
+
]),
|
|
314
|
+
),
|
|
315
|
+
pagination: config.pagination,
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
return {
|
|
320
|
+
guardShape: config?.shape as Record<string, unknown> | undefined,
|
|
321
|
+
guardRouting: classifyGuardRouting(config?.shape),
|
|
322
|
+
operationBefore,
|
|
323
|
+
operationAfter,
|
|
324
|
+
variantHooks: {},
|
|
325
|
+
pagination: config?.pagination,
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
export function resolveOperationVariantKey(
|
|
330
|
+
routing: NormalizedGuardRouting,
|
|
331
|
+
caller: string | undefined,
|
|
332
|
+
): GuardVariantResolution {
|
|
333
|
+
if (routing.kind === 'none' || routing.kind === 'single') {
|
|
334
|
+
return resolveGuardVariantKey({ kind: 'single' })
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return resolveGuardVariantKey({
|
|
338
|
+
kind: 'named',
|
|
339
|
+
keys: routing.keys,
|
|
340
|
+
caller,
|
|
341
|
+
reservedKeys: GUARD_SHAPE_CONFIG_KEYS,
|
|
342
|
+
})
|
|
343
|
+
}
|
|
344
|
+
|
|
152
345
|
export function validateCountSourceWhere(
|
|
153
346
|
cs: PaginationCountSource | undefined,
|
|
154
347
|
location: string,
|
|
@@ -74,25 +74,55 @@ export function generateRouteConfigType(
|
|
|
74
74
|
|
|
75
75
|
const shapeOps = Array.from(new Set(ROUTER_OPERATIONS))
|
|
76
76
|
const opShapeImports = shapeOps
|
|
77
|
-
.
|
|
77
|
+
.flatMap((op) => {
|
|
78
|
+
const prefix = `${m}${capitalize(op)}Shape`
|
|
79
|
+
return [prefix, `${prefix}Input`]
|
|
80
|
+
})
|
|
78
81
|
.join(',\n ')
|
|
79
82
|
|
|
83
|
+
const shapeOrFnAliases = shapeOps
|
|
84
|
+
.map((op) => {
|
|
85
|
+
const prefix = `${m}${capitalize(op)}Shape`
|
|
86
|
+
return (
|
|
87
|
+
`type ${prefix}OrFn<TCtx = unknown> =\n` +
|
|
88
|
+
` | ${prefix}\n` +
|
|
89
|
+
` | ((ctx: TCtx) => ${prefix})`
|
|
90
|
+
)
|
|
91
|
+
})
|
|
92
|
+
.join('\n\n')
|
|
93
|
+
|
|
80
94
|
const overrides = ROUTER_OPERATIONS.map((routerOp) => {
|
|
81
95
|
const c = capitalize(routerOp)
|
|
82
96
|
const isRead = READ_OPERATION_NAMES.has(routerOp)
|
|
83
|
-
const
|
|
97
|
+
const commonLines = [
|
|
84
98
|
` before?: ${beforeRef}[]`,
|
|
85
99
|
` after?: ${afterRef}[]`,
|
|
86
|
-
` shape?: ${m}${c}ShapeInput<TCtx>`,
|
|
87
100
|
` pagination?: Partial<PaginationConfig>`,
|
|
88
101
|
]
|
|
102
|
+
|
|
89
103
|
if (isRead && supportsProgressive) {
|
|
90
|
-
|
|
91
|
-
|
|
104
|
+
commonLines.push(
|
|
105
|
+
` progressive?: Record<string, ProgressiveVariantConfig>`,
|
|
106
|
+
)
|
|
107
|
+
commonLines.push(
|
|
92
108
|
` progressiveStages?: Record<string, ProgressiveStage<TCtx, TPrisma>>`,
|
|
93
109
|
)
|
|
94
110
|
}
|
|
95
|
-
|
|
111
|
+
|
|
112
|
+
const commonConfig = `{\n${commonLines.join('\n')}\n }`
|
|
113
|
+
const variantsConfig =
|
|
114
|
+
`Record<string, {\n` +
|
|
115
|
+
` shape: ${m}${c}ShapeOrFn<TCtx>\n` +
|
|
116
|
+
` before?: ${beforeRef}[]\n` +
|
|
117
|
+
` after?: ${afterRef}[]\n` +
|
|
118
|
+
` }>`
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
` ${routerOp}?: (${commonConfig} & (\n` +
|
|
122
|
+
` | { shape?: ${m}${c}ShapeInput<TCtx>; variants?: never }\n` +
|
|
123
|
+
` | { shape?: never; variants: ${variantsConfig} }\n` +
|
|
124
|
+
` )) | false`
|
|
125
|
+
)
|
|
96
126
|
}).join('\n')
|
|
97
127
|
|
|
98
128
|
const omitKeys = ROUTER_OPERATIONS.map((k) => `'${k}'`).join('\n | ')
|
|
@@ -100,6 +130,7 @@ export function generateRouteConfigType(
|
|
|
100
130
|
return (
|
|
101
131
|
progressiveTypeImport +
|
|
102
132
|
`import type {\n ${opShapeImports}\n} from '${guardShapesImport}${ext}'\n\n` +
|
|
133
|
+
`${shapeOrFnAliases}\n\n` +
|
|
103
134
|
`export type ${m}RouteConfig${generics} = Omit<\n` +
|
|
104
135
|
` ${baseConfig},\n` +
|
|
105
136
|
` | ${omitKeys}\n` +
|