prisma-generator-express 1.54.0 → 1.56.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 +186 -11
- package/dist/constants.d.ts +2 -0
- package/dist/generators/generateFastifyHandler.js +3 -1
- package/dist/generators/generateFastifyHandler.js.map +1 -1
- package/dist/generators/generateHonoHandler.js +3 -1
- package/dist/generators/generateHonoHandler.js.map +1 -1
- package/dist/generators/generateOperationCore.d.ts +3 -0
- package/dist/generators/generateOperationCore.js +68 -39
- package/dist/generators/generateOperationCore.js.map +1 -1
- package/dist/generators/generateRouteConfigType.js +4 -1
- package/dist/generators/generateRouteConfigType.js.map +1 -1
- package/dist/generators/generateRouter.d.ts +4 -1
- package/dist/generators/generateRouter.js +20 -7
- package/dist/generators/generateRouter.js.map +1 -1
- package/dist/generators/generateRouterFastify.d.ts +4 -1
- package/dist/generators/generateRouterFastify.js +23 -9
- package/dist/generators/generateRouterFastify.js.map +1 -1
- package/dist/generators/generateRouterHono.d.ts +4 -1
- package/dist/generators/generateRouterHono.js +29 -16
- 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 +42 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/constants.ts +5 -1
- package/src/copy/autoIncludeRuntime.ts +60 -35
- package/src/copy/buildModelOpenApi.ts +144 -23
- package/src/copy/docsRenderer.ts +125 -98
- package/src/copy/operationRuntime.ts +94 -9
- package/src/copy/routeConfig.express.ts +8 -0
- package/src/copy/routeConfig.fastify.ts +8 -0
- package/src/copy/routeConfig.hono.ts +9 -1
- package/src/copy/routeConfig.ts +23 -5
- package/src/generators/generateFastifyHandler.ts +3 -1
- package/src/generators/generateHonoHandler.ts +3 -1
- package/src/generators/generateOperationCore.ts +84 -39
- package/src/generators/generateRouteConfigType.ts +5 -2
- package/src/generators/generateRouter.ts +24 -6
- package/src/generators/generateRouterFastify.ts +27 -8
- package/src/generators/generateRouterHono.ts +33 -15
- package/src/generators/generateUnifiedScalarUI.ts +15 -11
- package/src/index.ts +49 -7
package/README.md
CHANGED
|
@@ -10,6 +10,8 @@ Prisma generator that creates Express, Fastify, or Hono CRUD API routes with Ope
|
|
|
10
10
|
Running `npx prisma generate` produces:
|
|
11
11
|
|
|
12
12
|
- Handler functions for all Prisma operations (findMany, create, update, delete, etc.)
|
|
13
|
+
- Schema-level `findManyPaginated` execution mode selection (`Promise.all` or interactive transaction)
|
|
14
|
+
- Per-route and per-endpoint pagination config, including optional materialized-view count sources
|
|
13
15
|
- Router generator with middleware support (before/after hooks per operation)
|
|
14
16
|
- POST read endpoints for all read operations (for complex queries exceeding URL length limits)
|
|
15
17
|
- Express-only progressive read streaming over Server-Sent Events (SSE), using manual stages or auto-include splitting for supported relation reads, including deep `findMany` / `findManyPaginated` auto-include paths
|
|
@@ -26,6 +28,8 @@ Supports **Express**, **Fastify**, and **Hono** targets via the `target` configu
|
|
|
26
28
|
- [Compatibility](#compatibility)
|
|
27
29
|
- [Installation](#installation)
|
|
28
30
|
- [Setup](#setup)
|
|
31
|
+
- [Write strategy](#write-strategy)
|
|
32
|
+
- [findManyPaginated execution mode](#findmanypaginated-execution-mode)
|
|
29
33
|
- [Path casing in generated endpoints](#path-casing-in-generated-endpoints)
|
|
30
34
|
- [Usage (Express)](#usage-express)
|
|
31
35
|
- [Usage (Fastify)](#usage-fastify)
|
|
@@ -62,6 +66,7 @@ Some operations require newer versions:
|
|
|
62
66
|
| Operation | Minimum Prisma version | Notes |
|
|
63
67
|
| --------------------- | ---------------------- | ------------------------------------ |
|
|
64
68
|
| `omit` parameter | 6.2.0 | Returns 400 on versions 6.0.x–6.1.x |
|
|
69
|
+
| `createManyAndReturn` | 5.14.0 | PostgreSQL, CockroachDB, SQLite only |
|
|
65
70
|
| `updateManyAndReturn` | 6.2.0 | PostgreSQL, CockroachDB, SQLite only |
|
|
66
71
|
|
|
67
72
|
### Framework support
|
|
@@ -160,6 +165,69 @@ Generate:
|
|
|
160
165
|
npx prisma generate
|
|
161
166
|
```
|
|
162
167
|
|
|
168
|
+
## Write strategy
|
|
169
|
+
|
|
170
|
+
`writeStrategy` is a schema-wide generator option. It controls only non-returning bulk data writes that have Prisma returning counterparts: `createMany` and `updateMany`. It does not affect `deleteMany`.
|
|
171
|
+
|
|
172
|
+
```prisma
|
|
173
|
+
generator express {
|
|
174
|
+
provider = "prisma-generator-express"
|
|
175
|
+
writeStrategy = "regular"
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Valid values:
|
|
180
|
+
|
|
181
|
+
| Value | Behavior |
|
|
182
|
+
| ----- | -------- |
|
|
183
|
+
| `regular` | Default. `createMany` and `updateMany` call the normal Prisma methods and return `{ count }`. |
|
|
184
|
+
| `throwOnNonReturning` | Disables the generated `createMany` and `updateMany` endpoints (`POST /{modelname}/many` and `PUT /{modelname}/many`). Direct calls return `501`. Use `createManyAndReturn` and `updateManyAndReturn` endpoints instead. |
|
|
185
|
+
| `forceReturn` | `createMany` silently invokes `createManyAndReturn`, and `updateMany` silently invokes `updateManyAndReturn`. These endpoints return arrays of records instead of `{ count }` and support `select`, `include`, and `omit`. |
|
|
186
|
+
|
|
187
|
+
`forceReturn` still follows Prisma provider support. If the current provider does not support `createManyAndReturn` or `updateManyAndReturn`, the generated endpoint returns `501 Not Implemented` at runtime.
|
|
188
|
+
|
|
189
|
+
Example:
|
|
190
|
+
|
|
191
|
+
```prisma
|
|
192
|
+
generator express {
|
|
193
|
+
provider = "prisma-generator-express"
|
|
194
|
+
target = "express"
|
|
195
|
+
writeStrategy = "forceReturn"
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## findManyPaginated execution mode
|
|
200
|
+
|
|
201
|
+
`findManyPaginatedMode` is a schema-wide generator option. It controls how generated `findManyPaginated` handlers execute the root `findMany` query and the total-count query.
|
|
202
|
+
|
|
203
|
+
```prisma
|
|
204
|
+
generator express {
|
|
205
|
+
provider = "prisma-generator-express"
|
|
206
|
+
findManyPaginatedMode = "promiseAll"
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Valid values:
|
|
211
|
+
|
|
212
|
+
| Value | Behavior |
|
|
213
|
+
| ----- | -------- |
|
|
214
|
+
| `promiseAll` | Default. Generates `Promise.all([findMany, count])`. This is faster and works on clients without interactive transaction support, but the returned `data` and `total` are not atomic under concurrent writes. |
|
|
215
|
+
| `transaction` | Generates an interactive transaction around `findMany` and `count`. This keeps `data` and `total` consistent inside the transaction, but returns `500` if the Prisma client does not expose `$transaction`. There is no implicit fallback. |
|
|
216
|
+
|
|
217
|
+
This option affects normal JSON `findManyPaginated` responses and Express SSE auto-include `findManyPaginated` responses.
|
|
218
|
+
|
|
219
|
+
Use `transaction` when atomic page metadata matters more than latency. Use `promiseAll` when throughput and broad runtime compatibility matter more than strict consistency between `data` and `total`.
|
|
220
|
+
|
|
221
|
+
Example:
|
|
222
|
+
|
|
223
|
+
```prisma
|
|
224
|
+
generator express {
|
|
225
|
+
provider = "prisma-generator-express"
|
|
226
|
+
target = "express"
|
|
227
|
+
findManyPaginatedMode = "transaction"
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
163
231
|
## Path casing in generated endpoints
|
|
164
232
|
|
|
165
233
|
Model names are converted to **flat lowercase** in URL paths. There is no kebab-case or snake_case conversion — the model name is lowercased character by character.
|
|
@@ -961,7 +1029,7 @@ const userConfig = {
|
|
|
961
1029
|
}
|
|
962
1030
|
```
|
|
963
1031
|
|
|
964
|
-
The client can include `include` or `select` in the request body. If the shape does not define projection, the client cannot request one.
|
|
1032
|
+
The client can include `include` or `select` in the request body. If the shape does not define projection, the client cannot request one. Non-returning batch methods (`createMany`, `updateMany`, `deleteMany`) do not support projection. When `writeStrategy = "forceReturn"`, the generated `createMany` and `updateMany` endpoints invoke returning methods and can use `select`, `include`, and `omit` like `createManyAndReturn` and `updateManyAndReturn`.
|
|
965
1033
|
|
|
966
1034
|
For mutations, projection shapes only validate and constrain client-requested projections by default — if the client omits `select`/`include`, Prisma returns the full record. This differs from read operations, where the shape's projection is automatically applied as default. Enable `enforceProjection` in the prisma-guard generator config to always apply mutation projection shapes.
|
|
967
1035
|
|
|
@@ -1230,7 +1298,7 @@ All write operations accept the full Prisma args object as the JSON request body
|
|
|
1230
1298
|
{ "where": { "id": 1 }, "create": { "name": "Alice" }, "update": { "name": "Bob" } }
|
|
1231
1299
|
```
|
|
1232
1300
|
|
|
1233
|
-
Write operations that return records (create
|
|
1301
|
+
Write operations that return records (`create`, `update`, `delete`, `upsert`, `createManyAndReturn`, `updateManyAndReturn`) support `select`, `include`, and `omit` in the request body to control the response shape. When `writeStrategy = "forceReturn"`, the generated `createMany` and `updateMany` endpoints are rewritten to returning methods and also support `select`, `include`, and `omit`.
|
|
1234
1302
|
|
|
1235
1303
|
For Express, mount `express.json()` before the router so request bodies are parsed. For Hono, malformed JSON bodies are rejected with 400 (`{ "message": "Invalid JSON in request body" }`) before reaching the handler.
|
|
1236
1304
|
|
|
@@ -1238,6 +1306,8 @@ For Express, mount `express.json()` before the router so request bodies are pars
|
|
|
1238
1306
|
|
|
1239
1307
|
`createMany`, `createManyAndReturn`, `updateMany`, and `updateManyAndReturn` accept scalar-only data inputs. Nested relation writes are not supported in bulk operations.
|
|
1240
1308
|
|
|
1309
|
+
By default, `createMany` and `updateMany` return `{ count }`, while `createManyAndReturn` and `updateManyAndReturn` return arrays of records. With `writeStrategy = "forceReturn"`, the generated `createMany` and `updateMany` endpoints return arrays of records because they invoke the returning Prisma methods internally.
|
|
1310
|
+
|
|
1241
1311
|
### Batch operation safety
|
|
1242
1312
|
|
|
1243
1313
|
`deleteMany`, `updateMany`, and `updateManyAndReturn` require a `where` field in the request body. Requests without `where` are rejected with 400 to prevent accidental mass operations. Sending `{ "where": {} }` is valid and matches all records — this protection catches accidental omission, not intentional broad operations.
|
|
@@ -2282,11 +2352,11 @@ On the client side, `encodeQueryParams` handles BigInt serialization automatical
|
|
|
2282
2352
|
|
|
2283
2353
|
## Pagination
|
|
2284
2354
|
|
|
2285
|
-
`findManyPaginated` returns `{ data, total, hasMore }`.
|
|
2355
|
+
`findManyPaginated` returns `{ data, total, hasMore }`. Execution is controlled by the schema-wide `findManyPaginatedMode` generator option. The default is `"promiseAll"`, which runs `findMany` and `count` concurrently with `Promise.all`. This is faster but not atomic under concurrent writes. `"transaction"` runs both queries inside an interactive transaction and returns `500` if transaction support is missing.
|
|
2286
2356
|
|
|
2287
2357
|
The `hasMore` field is reliable for forward offset pagination (`skip` + `take`) only. When using cursor-based pagination or negative `take` (backward pagination), `hasMore` may be inaccurate.
|
|
2288
2358
|
|
|
2289
|
-
When `distinct` is used with `findManyPaginated`, the total count is determined by executing a distinct query up to the configured limit (default: 100,000 rows). If the number of distinct values exceeds this limit, the total falls back to an approximate non-distinct count. When guard
|
|
2359
|
+
When `distinct` is used with `findManyPaginated`, the total count is determined by executing a distinct query up to the configured limit (default: 100,000 rows). If the number of distinct values exceeds this limit, the total falls back to an approximate non-distinct count. When a guard shape is configured together with `distinct`, the total falls back to a guarded non-distinct count so the internal count query does not need to reuse the public read projection.
|
|
2290
2360
|
|
|
2291
2361
|
Configure default and maximum page sizes and the distinct count limit:
|
|
2292
2362
|
|
|
@@ -2303,6 +2373,68 @@ UserRouter({
|
|
|
2303
2373
|
|
|
2304
2374
|
`pagination.defaultLimit` is applied when the client omits `take`. `pagination.maxLimit` caps `take` by absolute value. `pagination.distinctCountLimit` overrides the default 100,000 row threshold for distinct count estimation. All settings apply to `findMany` and `findManyPaginated`.
|
|
2305
2375
|
|
|
2376
|
+
### Materialized count source
|
|
2377
|
+
|
|
2378
|
+
`findManyPaginated` can read `total` from a materialized view instead of calling Prisma `count`. This is useful for large static or periodically refreshed datasets where a precomputed count is cheaper than a live count.
|
|
2379
|
+
|
|
2380
|
+
Configure it globally for the router:
|
|
2381
|
+
|
|
2382
|
+
```ts
|
|
2383
|
+
UserRouter({
|
|
2384
|
+
findManyPaginated: {},
|
|
2385
|
+
pagination: {
|
|
2386
|
+
countSource: {
|
|
2387
|
+
type: 'materializedView',
|
|
2388
|
+
schema: 'public',
|
|
2389
|
+
relation: 'mv_user_count',
|
|
2390
|
+
column: 'total',
|
|
2391
|
+
},
|
|
2392
|
+
},
|
|
2393
|
+
})
|
|
2394
|
+
```
|
|
2395
|
+
|
|
2396
|
+
Or override it per endpoint:
|
|
2397
|
+
|
|
2398
|
+
```ts
|
|
2399
|
+
UserRouter({
|
|
2400
|
+
pagination: {
|
|
2401
|
+
defaultLimit: 20,
|
|
2402
|
+
maxLimit: 100,
|
|
2403
|
+
},
|
|
2404
|
+
findManyPaginated: {
|
|
2405
|
+
pagination: {
|
|
2406
|
+
countSource: {
|
|
2407
|
+
type: 'materializedView',
|
|
2408
|
+
schema: 'public',
|
|
2409
|
+
relation: 'mv_active_user_count',
|
|
2410
|
+
column: 'total',
|
|
2411
|
+
},
|
|
2412
|
+
},
|
|
2413
|
+
},
|
|
2414
|
+
})
|
|
2415
|
+
```
|
|
2416
|
+
|
|
2417
|
+
The materialized-view count source is used only when the request has no dynamic `where`, no `distinct`, and no guard shape. If any of those are present, the handler falls back to the normal delegate count so `total` stays consistent with the filtered data.
|
|
2418
|
+
|
|
2419
|
+
The materialized count query uses PostgreSQL-style `$N` placeholders and `LIMIT 1`, so it is intended for PostgreSQL and CockroachDB-style clients. The optional `countSource.where` supports flat equality and `null` only. Operators and nested objects are not supported.
|
|
2420
|
+
|
|
2421
|
+
Example with a static filter on the count view:
|
|
2422
|
+
|
|
2423
|
+
```ts
|
|
2424
|
+
UserRouter({
|
|
2425
|
+
findManyPaginated: {
|
|
2426
|
+
pagination: {
|
|
2427
|
+
countSource: {
|
|
2428
|
+
type: 'materializedView',
|
|
2429
|
+
relation: 'mv_user_count_by_status',
|
|
2430
|
+
column: 'total',
|
|
2431
|
+
where: { status: 'active' },
|
|
2432
|
+
},
|
|
2433
|
+
},
|
|
2434
|
+
},
|
|
2435
|
+
})
|
|
2436
|
+
```
|
|
2437
|
+
|
|
2306
2438
|
## Error handling
|
|
2307
2439
|
|
|
2308
2440
|
All errors are returned as JSON with a `message` field:
|
|
@@ -2321,7 +2453,7 @@ For the Hono target, thrown `HTTPException` instances are caught by `app.onError
|
|
|
2321
2453
|
| 403 | Guard policy rejected |
|
|
2322
2454
|
| 404 | Record not found |
|
|
2323
2455
|
| 409 | Unique constraint or transaction conflict |
|
|
2324
|
-
| 500 | Internal server error
|
|
2456
|
+
| 500 | Internal server error, including transaction mode without transaction support |
|
|
2325
2457
|
| 501 | Feature not supported by database provider |
|
|
2326
2458
|
| 503 | Database connection pool timeout |
|
|
2327
2459
|
|
|
@@ -2605,6 +2737,10 @@ Paths shown are relative suffixes. Actual paths include the model prefix (e.g.,
|
|
|
2605
2737
|
|
|
2606
2738
|
POST read endpoints are enabled by default. Set `disablePostReads: true` to remove them.
|
|
2607
2739
|
|
|
2740
|
+
The schema-wide `writeStrategy` option can change the behavior of `POST /{modelname}/many` and `PUT /{modelname}/many`. It does not change `DELETE /{modelname}/many`.
|
|
2741
|
+
|
|
2742
|
+
The schema-wide `findManyPaginatedMode` option changes the generated implementation behind `GET` and `POST /{modelname}/paginated`, but not the public response shape.
|
|
2743
|
+
|
|
2608
2744
|
For the Express target, GET read endpoints can also stream SSE events when the request sends `Accept: text/event-stream`. SSE uses the same GET paths shown above; no additional routes are generated. See [Progressive Endpoint Composition](#progressive-endpoint-composition-express-sse).
|
|
2609
2745
|
|
|
2610
2746
|
## Skipping models
|
|
@@ -2620,9 +2756,45 @@ model InternalLog {
|
|
|
2620
2756
|
|
|
2621
2757
|
## Configuration
|
|
2622
2758
|
|
|
2759
|
+
### Generator options
|
|
2760
|
+
|
|
2761
|
+
Generator options are configured in `schema.prisma` and apply schema-wide.
|
|
2762
|
+
|
|
2763
|
+
```prisma
|
|
2764
|
+
generator express {
|
|
2765
|
+
provider = "prisma-generator-express"
|
|
2766
|
+
target = "express"
|
|
2767
|
+
writeStrategy = "regular"
|
|
2768
|
+
findManyPaginatedMode = "promiseAll"
|
|
2769
|
+
}
|
|
2770
|
+
```
|
|
2771
|
+
|
|
2772
|
+
| Option | Values | Default | Description |
|
|
2773
|
+
| ------ | ------ | ------- | ----------- |
|
|
2774
|
+
| `target` | `"express"`, `"fastify"`, `"hono"` | `"express"` | Selects the generated router target. |
|
|
2775
|
+
| `writeStrategy` | `"regular"`, `"throwOnNonReturning"`, `"forceReturn"` | `"regular"` | Controls only `createMany` and `updateMany`. See [Write strategy](#write-strategy). |
|
|
2776
|
+
| `findManyPaginatedMode` | `"promiseAll"`, `"transaction"` | `"promiseAll"` | Controls whether generated `findManyPaginated` handlers run data and count with `Promise.all` or inside an interactive transaction. See [findManyPaginated execution mode](#findmanypaginated-execution-mode). |
|
|
2777
|
+
|
|
2623
2778
|
### Express
|
|
2624
2779
|
|
|
2625
2780
|
```ts
|
|
2781
|
+
type PaginationCountSource =
|
|
2782
|
+
| { type?: 'delegate' }
|
|
2783
|
+
| {
|
|
2784
|
+
type: 'materializedView'
|
|
2785
|
+
relation: string
|
|
2786
|
+
schema?: string
|
|
2787
|
+
column?: string
|
|
2788
|
+
where?: Record<string, unknown>
|
|
2789
|
+
}
|
|
2790
|
+
|
|
2791
|
+
interface PaginationConfig {
|
|
2792
|
+
defaultLimit?: number
|
|
2793
|
+
maxLimit?: number
|
|
2794
|
+
distinctCountLimit?: number
|
|
2795
|
+
countSource?: PaginationCountSource
|
|
2796
|
+
}
|
|
2797
|
+
|
|
2626
2798
|
interface RouteConfig<TCtx = unknown> {
|
|
2627
2799
|
enableAll?: boolean
|
|
2628
2800
|
addModelPrefix?: boolean // default: true
|
|
@@ -2648,11 +2820,7 @@ interface RouteConfig<TCtx = unknown> {
|
|
|
2648
2820
|
|
|
2649
2821
|
queryBuilder?: QueryBuilderConfig | false
|
|
2650
2822
|
|
|
2651
|
-
pagination?:
|
|
2652
|
-
defaultLimit?: number
|
|
2653
|
-
maxLimit?: number
|
|
2654
|
-
distinctCountLimit?: number // default: 100000
|
|
2655
|
-
}
|
|
2823
|
+
pagination?: PaginationConfig
|
|
2656
2824
|
|
|
2657
2825
|
// read operation config
|
|
2658
2826
|
findMany?: ReadOperationConfig<TCtx>
|
|
@@ -2681,6 +2849,7 @@ interface OperationConfig {
|
|
|
2681
2849
|
before?: RequestHandler[]
|
|
2682
2850
|
after?: RequestHandler[]
|
|
2683
2851
|
shape?: Record<string, any>
|
|
2852
|
+
pagination?: Partial<PaginationConfig>
|
|
2684
2853
|
}
|
|
2685
2854
|
|
|
2686
2855
|
interface ReadOperationConfig<TCtx = unknown> extends OperationConfig {
|
|
@@ -2752,6 +2921,7 @@ interface OperationConfig {
|
|
|
2752
2921
|
before?: FastifyHookHandler[]
|
|
2753
2922
|
after?: FastifyHookHandler[]
|
|
2754
2923
|
shape?: Record<string, any>
|
|
2924
|
+
pagination?: Partial<PaginationConfig>
|
|
2755
2925
|
}
|
|
2756
2926
|
|
|
2757
2927
|
type FastifyHookHandler = (
|
|
@@ -2771,6 +2941,7 @@ interface OperationConfig {
|
|
|
2771
2941
|
before?: HonoHookHandler[]
|
|
2772
2942
|
after?: HonoHookHandler[]
|
|
2773
2943
|
shape?: Record<string, any>
|
|
2944
|
+
pagination?: Partial<PaginationConfig>
|
|
2774
2945
|
}
|
|
2775
2946
|
|
|
2776
2947
|
type HonoHookHandler<Env extends { Variables: any } = any> = (
|
|
@@ -2783,7 +2954,9 @@ The `guard.resolveVariant` callback receives Hono's `Context`. Hooks are native
|
|
|
2783
2954
|
|
|
2784
2955
|
The Hono router does not auto-start the Query Builder. Set `queryBuilder: false` to make the playground route return 404, or run `prisma-query-builder-ui` manually for development.
|
|
2785
2956
|
|
|
2786
|
-
### Shared options
|
|
2957
|
+
### Shared route options
|
|
2958
|
+
|
|
2959
|
+
These options are passed to the generated router at runtime. They are separate from schema-wide generator options such as `target`, `writeStrategy`, and `findManyPaginatedMode`.
|
|
2787
2960
|
|
|
2788
2961
|
`customUrlPrefix` is normalized to ensure a leading slash and strip trailing slashes.
|
|
2789
2962
|
|
|
@@ -2793,6 +2966,8 @@ The Hono router does not auto-start the Query Builder. Set `queryBuilder: false`
|
|
|
2793
2966
|
|
|
2794
2967
|
`resolveContext` is Express-only and is required for enabled progressive SSE variants. It is called before progressive stages run and its return value is passed to each stage as `ctx`.
|
|
2795
2968
|
|
|
2969
|
+
`pagination` can be set at the router level and overridden per operation with `operation.pagination`. Endpoint-level pagination config is shallow-merged over router-level pagination config. `countSource` is only used by `findManyPaginated`.
|
|
2970
|
+
|
|
2796
2971
|
`openApiServers` sets the `servers` array in the OpenAPI spec:
|
|
2797
2972
|
|
|
2798
2973
|
```ts
|
package/dist/constants.d.ts
CHANGED
|
@@ -65,7 +65,7 @@ export async function ${exportName}(
|
|
|
65
65
|
}).join('\n');
|
|
66
66
|
return `import type { FastifyRequest, FastifyReply } from 'fastify'
|
|
67
67
|
import * as core from './${modelName}Core${ext}'
|
|
68
|
-
import type { OperationContext } from '../operationRuntime${ext}'
|
|
68
|
+
import type { OperationContext, FindManyPaginatedMode } from '../operationRuntime${ext}'
|
|
69
69
|
|
|
70
70
|
type FastifyExtended = FastifyRequest & {
|
|
71
71
|
prisma?: unknown
|
|
@@ -75,6 +75,7 @@ type FastifyExtended = FastifyRequest & {
|
|
|
75
75
|
routeConfig?: { pagination?: OperationContext['paginationConfig'] }
|
|
76
76
|
guardShape?: Record<string, unknown>
|
|
77
77
|
guardCaller?: string
|
|
78
|
+
findManyPaginatedMode?: FindManyPaginatedMode
|
|
78
79
|
resultData?: unknown
|
|
79
80
|
resultStatus?: number
|
|
80
81
|
}
|
|
@@ -90,6 +91,7 @@ function buildContext(request: FastifyRequest): OperationContext {
|
|
|
90
91
|
guardShape: req.guardShape,
|
|
91
92
|
guardCaller: req.guardCaller,
|
|
92
93
|
paginationConfig: req.routeConfig?.pagination,
|
|
94
|
+
findManyPaginatedMode: req.findManyPaginatedMode,
|
|
93
95
|
}
|
|
94
96
|
}
|
|
95
97
|
${readHandlers}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateFastifyHandler.js","sourceRoot":"","sources":["../../src/generators/generateFastifyHandler.ts"],"names":[],"mappings":";;AA0CA,
|
|
1
|
+
{"version":3,"file":"generateFastifyHandler.js","sourceRoot":"","sources":["../../src/generators/generateFastifyHandler.ts"],"names":[],"mappings":";;AA0CA,wDAqEC;AA7GD,kDAA8C;AAE9C,MAAM,aAAa,GAA2B;IAC5C,MAAM,EAAE,cAAc;CACvB,CAAA;AAED,SAAS,UAAU,CAAC,EAAU;IAC5B,OAAO,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,CAAA;AAChC,CAAC;AAED,MAAM,QAAQ,GAAG;IACf,UAAU;IACV,WAAW;IACX,kBAAkB;IAClB,YAAY;IACZ,mBAAmB;IACnB,mBAAmB;IACnB,WAAW;IACX,OAAO;IACP,SAAS;CACV,CAAA;AAED,MAAM,SAAS,GAAG;IAChB,QAAQ;IACR,YAAY;IACZ,qBAAqB;IACrB,QAAQ;IACR,YAAY;IACZ,qBAAqB;IACrB,QAAQ;IACR,QAAQ;IACR,YAAY;CACb,CAAA;AAED,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC;IAC1B,QAAQ;IACR,YAAY;IACZ,qBAAqB;CACtB,CAAC,CAAA;AAEF,SAAgB,sBAAsB,CAAC,OAGtC;IACC,MAAM,GAAG,GAAG,IAAA,qBAAS,EAAC,OAAO,CAAC,WAAW,CAAC,CAAA;IAC1C,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAA;IAEpC,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;QACvC,MAAM,UAAU,GAAG,GAAG,SAAS,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;QAC5E,OAAO;wBACa,UAAU;;;;4BAIN,UAAU,CAAC,EAAE,CAAC;;EAExC,CAAA;IACA,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAEb,MAAM,aAAa,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;QACzC,MAAM,UAAU,GAAG,GAAG,SAAS,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;QAC5E,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAA;QAElD,OAAO;wBACa,UAAU;;;;4BAIN,UAAU,CAAC,EAAE,CAAC;;;uBAGnB,UAAU;EAC/B,CAAA;IACA,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAEb,OAAO;2BACkB,SAAS,OAAO,GAAG;mFACqC,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6BpF,YAAY;EACZ,aAAa;CACd,CAAA;AACD,CAAC"}
|
|
@@ -58,7 +58,7 @@ export async function ${exportName}(c: Context<HonoEnv>): Promise<void> {
|
|
|
58
58
|
}).join('\n');
|
|
59
59
|
return `import type { Context } from 'hono'
|
|
60
60
|
import * as core from './${modelName}Core${ext}'
|
|
61
|
-
import type { OperationContext } from '../operationRuntime${ext}'
|
|
61
|
+
import type { OperationContext, FindManyPaginatedMode } from '../operationRuntime${ext}'
|
|
62
62
|
|
|
63
63
|
type HonoVariables = {
|
|
64
64
|
prisma: unknown
|
|
@@ -69,6 +69,7 @@ type HonoVariables = {
|
|
|
69
69
|
routeConfig?: { pagination?: OperationContext['paginationConfig'] }
|
|
70
70
|
guardShape?: Record<string, unknown>
|
|
71
71
|
guardCaller?: string
|
|
72
|
+
findManyPaginatedMode?: FindManyPaginatedMode
|
|
72
73
|
resultData?: unknown
|
|
73
74
|
resultStatus?: number
|
|
74
75
|
}
|
|
@@ -85,6 +86,7 @@ function buildContext(c: Context<HonoEnv>): OperationContext {
|
|
|
85
86
|
guardShape: c.get('guardShape'),
|
|
86
87
|
guardCaller: c.get('guardCaller'),
|
|
87
88
|
paginationConfig: c.get('routeConfig')?.pagination,
|
|
89
|
+
findManyPaginatedMode: c.get('findManyPaginatedMode'),
|
|
88
90
|
}
|
|
89
91
|
}
|
|
90
92
|
${readHandlers}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateHonoHandler.js","sourceRoot":"","sources":["../../src/generators/generateHonoHandler.ts"],"names":[],"mappings":";;AA0CA,
|
|
1
|
+
{"version":3,"file":"generateHonoHandler.js","sourceRoot":"","sources":["../../src/generators/generateHonoHandler.ts"],"names":[],"mappings":";;AA0CA,kDAgEC;AAxGD,kDAA8C;AAE9C,MAAM,aAAa,GAA2B;IAC5C,MAAM,EAAE,cAAc;CACvB,CAAA;AAED,SAAS,UAAU,CAAC,EAAU;IAC5B,OAAO,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,CAAA;AAChC,CAAC;AAED,MAAM,QAAQ,GAAG;IACf,UAAU;IACV,WAAW;IACX,kBAAkB;IAClB,YAAY;IACZ,mBAAmB;IACnB,mBAAmB;IACnB,WAAW;IACX,OAAO;IACP,SAAS;CACV,CAAA;AAED,MAAM,SAAS,GAAG;IAChB,QAAQ;IACR,YAAY;IACZ,qBAAqB;IACrB,QAAQ;IACR,YAAY;IACZ,qBAAqB;IACrB,QAAQ;IACR,QAAQ;IACR,YAAY;CACb,CAAA;AAED,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC;IAC1B,QAAQ;IACR,YAAY;IACZ,qBAAqB;CACtB,CAAC,CAAA;AAEF,SAAgB,mBAAmB,CAAC,OAGnC;IACC,MAAM,GAAG,GAAG,IAAA,qBAAS,EAAC,OAAO,CAAC,WAAW,CAAC,CAAA;IAC1C,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAA;IAEpC,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;QACvC,MAAM,UAAU,GAAG,GAAG,SAAS,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;QAC5E,OAAO;wBACa,UAAU;4BACN,UAAU,CAAC,EAAE,CAAC;;EAExC,CAAA;IACA,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAEb,MAAM,aAAa,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;QACzC,MAAM,UAAU,GAAG,GAAG,SAAS,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;QAC5E,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAA;QAElD,OAAO;wBACa,UAAU;4BACN,UAAU,CAAC,EAAE,CAAC;;0BAEhB,UAAU;EAClC,CAAA;IACA,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAEb,OAAO;2BACkB,SAAS,OAAO,GAAG;mFACqC,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+BpF,YAAY;EACZ,aAAa;CACd,CAAA;AACD,CAAC"}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { DMMF } from '@prisma/generator-helper';
|
|
2
2
|
import { ImportStyle } from '../utils/resolveImportStyle';
|
|
3
|
+
import { WriteStrategy, FindManyPaginatedMode } from '../constants';
|
|
3
4
|
export interface ModelCoreOptions {
|
|
4
5
|
model: DMMF.Model;
|
|
5
6
|
importStyle: ImportStyle;
|
|
7
|
+
writeStrategy: WriteStrategy;
|
|
8
|
+
findManyPaginatedMode: FindManyPaginatedMode;
|
|
6
9
|
}
|
|
7
10
|
export declare function generateModelCore(options: ModelCoreOptions): string;
|
|
@@ -2,10 +2,63 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.generateModelCore = generateModelCore;
|
|
4
4
|
const importExt_1 = require("../utils/importExt");
|
|
5
|
+
function decideWriteOp(name, defaultMethod, strategy) {
|
|
6
|
+
if (strategy === 'regular') {
|
|
7
|
+
return { mode: 'normal', method: defaultMethod };
|
|
8
|
+
}
|
|
9
|
+
if (strategy === 'throwOnNonReturning') {
|
|
10
|
+
if (name === 'createMany' || name === 'updateMany') {
|
|
11
|
+
return { mode: 'throw' };
|
|
12
|
+
}
|
|
13
|
+
return { mode: 'normal', method: defaultMethod };
|
|
14
|
+
}
|
|
15
|
+
if (name === 'createMany')
|
|
16
|
+
return { mode: 'redirect', method: 'createManyAndReturn' };
|
|
17
|
+
if (name === 'updateMany')
|
|
18
|
+
return { mode: 'redirect', method: 'updateManyAndReturn' };
|
|
19
|
+
return { mode: 'normal', method: defaultMethod };
|
|
20
|
+
}
|
|
21
|
+
function renderPaginatedBody(modelNameLower, mode) {
|
|
22
|
+
if (mode === 'transaction') {
|
|
23
|
+
return `
|
|
24
|
+
const txClient = extended as { $transaction?: <T>(fn: (tx: unknown) => Promise<T>) => Promise<T> }
|
|
25
|
+
if (typeof txClient.$transaction !== 'function') {
|
|
26
|
+
throw new HttpError(500, 'findManyPaginatedMode="transaction" requires transaction support on the Prisma client')
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const txResult = await txClient.$transaction(async (tx: unknown) => {
|
|
30
|
+
const txDelegate = getDelegate(tx, '${modelNameLower}')
|
|
31
|
+
if (shape) assertGuard(txDelegate)
|
|
32
|
+
const findP = shape
|
|
33
|
+
? (txDelegate.guard as NonNullable<typeof txDelegate.guard>)(shape, caller).findMany(query)
|
|
34
|
+
: txDelegate.findMany(query)
|
|
35
|
+
const countP = countForPagination(
|
|
36
|
+
txDelegate, query, shape, caller, distinctCountLimit, countSource, tx,
|
|
37
|
+
)
|
|
38
|
+
const [data, count] = await Promise.all([findP, countP])
|
|
39
|
+
return { data, count }
|
|
40
|
+
})
|
|
41
|
+
items = txResult.data as unknown[]
|
|
42
|
+
total = txResult.count`;
|
|
43
|
+
}
|
|
44
|
+
return `
|
|
45
|
+
const delegate = getDelegate(extended, '${modelNameLower}')
|
|
46
|
+
if (shape) assertGuard(delegate)
|
|
47
|
+
const [data, count] = await Promise.all([
|
|
48
|
+
shape
|
|
49
|
+
? (delegate.guard as NonNullable<typeof delegate.guard>)(shape, caller).findMany(query)
|
|
50
|
+
: delegate.findMany(query),
|
|
51
|
+
countForPagination(delegate, query, shape, caller, distinctCountLimit, countSource, extended),
|
|
52
|
+
])
|
|
53
|
+
items = data as unknown[]
|
|
54
|
+
total = count`;
|
|
55
|
+
}
|
|
5
56
|
function generateModelCore(options) {
|
|
6
57
|
const ext = (0, importExt_1.importExt)(options.importStyle);
|
|
7
58
|
const modelName = options.model.name;
|
|
8
59
|
const modelNameLower = modelName.charAt(0).toLowerCase() + modelName.slice(1);
|
|
60
|
+
const writeStrategy = options.writeStrategy;
|
|
61
|
+
const paginatedBody = renderPaginatedBody(modelNameLower, options.findManyPaginatedMode);
|
|
9
62
|
const standardReadOps = [
|
|
10
63
|
'findFirst', 'findUnique', 'findUniqueOrThrow', 'findFirstOrThrow',
|
|
11
64
|
'count', 'aggregate', 'groupBy',
|
|
@@ -35,7 +88,17 @@ export async function ${op}(ctx: OperationContext): Promise<unknown> {
|
|
|
35
88
|
{ name: 'upsert', method: 'upsert', requiredFields: ['where', 'create', 'update'] },
|
|
36
89
|
];
|
|
37
90
|
const writeHandlers = writeOps.map((op) => {
|
|
38
|
-
const
|
|
91
|
+
const decision = decideWriteOp(op.name, op.method, writeStrategy);
|
|
92
|
+
if (decision.mode === 'throw') {
|
|
93
|
+
return `
|
|
94
|
+
export async function ${op.name}(_ctx: OperationContext): Promise<unknown> {
|
|
95
|
+
throw new HttpError(501, '${op.name} is disabled by writeStrategy="${writeStrategy}"')
|
|
96
|
+
}`;
|
|
97
|
+
}
|
|
98
|
+
const method = decision.method;
|
|
99
|
+
const validationLines = op.requiredFields
|
|
100
|
+
.map((field) => ` requireBodyField(body, '${field}')`)
|
|
101
|
+
.join('\n');
|
|
39
102
|
return `
|
|
40
103
|
export async function ${op.name}(ctx: OperationContext): Promise<unknown> {
|
|
41
104
|
const body = validateBody(ctx.body)
|
|
@@ -44,9 +107,9 @@ ${validationLines}
|
|
|
44
107
|
const delegate = getDelegate(extended, '${modelNameLower}')
|
|
45
108
|
if (ctx.guardShape) {
|
|
46
109
|
assertGuard(delegate)
|
|
47
|
-
return delegate.guard(ctx.guardShape, ctx.guardCaller).${
|
|
110
|
+
return delegate.guard(ctx.guardShape, ctx.guardCaller).${method}(body)
|
|
48
111
|
}
|
|
49
|
-
return delegate.${
|
|
112
|
+
return delegate.${method}(body)
|
|
50
113
|
}`;
|
|
51
114
|
}).join('\n');
|
|
52
115
|
return `import {
|
|
@@ -86,45 +149,11 @@ export async function findManyPaginated(
|
|
|
86
149
|
const shape = ctx.guardShape
|
|
87
150
|
const caller = ctx.guardCaller
|
|
88
151
|
const distinctCountLimit = ctx.paginationConfig?.distinctCountLimit
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
if (shape) assertGuard(delegate)
|
|
152
|
+
const countSource = ctx.paginationConfig?.countSource
|
|
92
153
|
|
|
93
154
|
let items: unknown[]
|
|
94
155
|
let total: number
|
|
95
|
-
|
|
96
|
-
const txClient = extended as { $transaction?: <T>(fn: (tx: unknown) => Promise<T>) => Promise<T> }
|
|
97
|
-
|
|
98
|
-
if (shape || typeof txClient.$transaction !== 'function') {
|
|
99
|
-
const [data, count] = await Promise.all([
|
|
100
|
-
shape
|
|
101
|
-
? (delegate.guard as NonNullable<typeof delegate.guard>)(shape, caller).findMany(query)
|
|
102
|
-
: delegate.findMany(query),
|
|
103
|
-
countForPagination(delegate, query, shape, caller, distinctCountLimit),
|
|
104
|
-
])
|
|
105
|
-
items = data as unknown[]
|
|
106
|
-
total = count
|
|
107
|
-
} else {
|
|
108
|
-
try {
|
|
109
|
-
const txResult = await txClient.$transaction(async (tx: unknown) => {
|
|
110
|
-
const txDelegate = getDelegate(tx, '${modelNameLower}')
|
|
111
|
-
const d = await txDelegate.findMany(query)
|
|
112
|
-
const t = await countForPagination(txDelegate, query, undefined, undefined, distinctCountLimit)
|
|
113
|
-
return { d, t }
|
|
114
|
-
})
|
|
115
|
-
items = txResult.d as unknown[]
|
|
116
|
-
total = txResult.t
|
|
117
|
-
} catch (txError: unknown) {
|
|
118
|
-
const txe = txError as { message?: string; code?: string }
|
|
119
|
-
if (txe?.code === 'P2028') {
|
|
120
|
-
console.warn('[prisma-generator-express] Interactive transactions not available, pagination queries are non-atomic')
|
|
121
|
-
items = (await delegate.findMany(query)) as unknown[]
|
|
122
|
-
total = await countForPagination(delegate, query, undefined, undefined, distinctCountLimit)
|
|
123
|
-
} else {
|
|
124
|
-
throw txError
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
156
|
+
${paginatedBody}
|
|
128
157
|
|
|
129
158
|
const skip = (typeof query.skip === 'number' ? query.skip : 0)
|
|
130
159
|
const takeRaw = (typeof query.take === 'number' ? query.take : items.length)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateOperationCore.js","sourceRoot":"","sources":["../../src/generators/generateOperationCore.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"generateOperationCore.js","sourceRoot":"","sources":["../../src/generators/generateOperationCore.ts"],"names":[],"mappings":"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"}
|
|
@@ -70,11 +70,12 @@ function generateRouteConfigType(modelName, hookHandlerType, guardShapesImport,
|
|
|
70
70
|
const hookRef = hookHandlerTypeRef(target, hookHandlerType);
|
|
71
71
|
const requestType = requestTypeFor(target);
|
|
72
72
|
const progressiveTypeImport = supportsProgressive
|
|
73
|
-
? `import type { ProgressiveVariantConfig, ProgressiveStage } from '../routeConfig.target${ext}'\n
|
|
73
|
+
? `import type { ProgressiveVariantConfig, ProgressiveStage } from '../routeConfig.target${ext}'\n`
|
|
74
74
|
: '';
|
|
75
75
|
if (!guardShapesImport) {
|
|
76
76
|
return progressiveTypeImport + `export type ${m}RouteConfig${generics} = ${baseConfig}\n`;
|
|
77
77
|
}
|
|
78
|
+
const paginationImport = `import type { PaginationConfig } from '../routeConfig.target${ext}'\n`;
|
|
78
79
|
const shapeOps = Object.values(ROUTER_OP_TO_SHAPE_OP).filter((v, i, a) => a.indexOf(v) === i);
|
|
79
80
|
const opShapeImports = shapeOps.map((op) => `${m}${(0, strings_1.capitalize)(op)}ShapeInput`).join(',\n ');
|
|
80
81
|
const overrides = ROUTER_OPERATIONS.map((routerOp) => {
|
|
@@ -85,6 +86,7 @@ function generateRouteConfigType(modelName, hookHandlerType, guardShapesImport,
|
|
|
85
86
|
` before?: ${hookRef}[]`,
|
|
86
87
|
` after?: ${hookRef}[]`,
|
|
87
88
|
` shape?: ${m}${c}ShapeInput<TCtx>`,
|
|
89
|
+
` pagination?: Partial<PaginationConfig>`,
|
|
88
90
|
];
|
|
89
91
|
if (isRead && supportsProgressive) {
|
|
90
92
|
lines.push(` progressive?: Record<string, ProgressiveVariantConfig>`);
|
|
@@ -94,6 +96,7 @@ function generateRouteConfigType(modelName, hookHandlerType, guardShapesImport,
|
|
|
94
96
|
}).join('\n');
|
|
95
97
|
const omitKeys = ROUTER_OPERATIONS.map((k) => `'${k}'`).join('\n | ');
|
|
96
98
|
return (progressiveTypeImport +
|
|
99
|
+
paginationImport +
|
|
97
100
|
`import type {\n ${opShapeImports}\n} from '${guardShapesImport}${ext}'\n\n` +
|
|
98
101
|
`export type ${m}RouteConfig${generics} = Omit<\n` +
|
|
99
102
|
` ${baseConfig},\n` +
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateRouteConfigType.js","sourceRoot":"","sources":["../../src/generators/generateRouteConfigType.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"generateRouteConfigType.js","sourceRoot":"","sources":["../../src/generators/generateRouteConfigType.ts"],"names":[],"mappings":";;AAqEA,0DA4DC;AAhID,kDAA8C;AAE9C,8CAA6C;AAE7C,MAAM,iBAAiB,GAAG;IACxB,YAAY,EAAE,mBAAmB,EAAE,WAAW,EAAE,kBAAkB;IAClE,UAAU,EAAE,mBAAmB,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS;IAChE,QAAQ,EAAE,YAAY,EAAE,qBAAqB;IAC7C,QAAQ,EAAE,YAAY,EAAE,qBAAqB;IAC7C,QAAQ,EAAE,QAAQ,EAAE,YAAY;CACxB,CAAA;AAIV,MAAM,eAAe,GAAiC,IAAI,GAAG,CAAkB;IAC7E,YAAY,EAAE,mBAAmB,EAAE,WAAW,EAAE,kBAAkB;IAClE,UAAU,EAAE,mBAAmB,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS;CACjE,CAAC,CAAA;AAEF,MAAM,qBAAqB,GAAoC;IAC7D,UAAU,EAAE,YAAY;IACxB,iBAAiB,EAAE,mBAAmB;IACtC,SAAS,EAAE,WAAW;IACtB,gBAAgB,EAAE,kBAAkB;IACpC,QAAQ,EAAE,UAAU;IACpB,iBAAiB,EAAE,mBAAmB;IACtC,KAAK,EAAE,OAAO;IACd,SAAS,EAAE,WAAW;IACtB,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;IAChB,UAAU,EAAE,YAAY;IACxB,mBAAmB,EAAE,qBAAqB;IAC1C,MAAM,EAAE,QAAQ;IAChB,UAAU,EAAE,YAAY;IACxB,mBAAmB,EAAE,qBAAqB;IAC1C,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,UAAU,EAAE,YAAY;CACzB,CAAA;AAED,SAAS,cAAc,CAAC,MAAc;IACpC,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,kCAAkC,CAAA;IACnE,IAAI,MAAM,KAAK,MAAM;QAAE,OAAO,8BAA8B,CAAA;IAC5D,OAAO,2BAA2B,CAAA;AACpC,CAAC;AAED,SAAS,iBAAiB,CAAC,MAAc;IACvC,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,+HAA+H,CAAA;IACxI,CAAC;IACD,OAAO,iCAAiC,CAAA;AAC1C,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAc;IACxC,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,kDAAkD,CAAA;IAC3D,CAAC;IACD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,qDAAqD,CAAA;IAC9D,CAAC;IACD,OAAO,4CAA4C,CAAA;AACrD,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAc,EAAE,eAAuB;IACjE,IAAI,MAAM,KAAK,MAAM;QAAE,OAAO,GAAG,eAAe,QAAQ,CAAA;IACxD,OAAO,eAAe,CAAA;AACxB,CAAC;AAED,SAAgB,uBAAuB,CACrC,SAAiB,EACjB,eAAuB,EACvB,iBAAgC,EAChC,WAAwB,EACxB,MAAc;IAEd,MAAM,GAAG,GAAG,IAAA,qBAAS,EAAC,WAAW,CAAC,CAAA;IAClC,MAAM,CAAC,GAAG,SAAS,CAAA;IACnB,MAAM,mBAAmB,GAAG,MAAM,KAAK,SAAS,CAAA;IAEhD,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAA;IAC1C,MAAM,UAAU,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAA;IAC7C,MAAM,OAAO,GAAG,kBAAkB,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;IAC3D,MAAM,WAAW,GAAG,cAAc,CAAC,MAAM,CAAC,CAAA;IAE1C,MAAM,qBAAqB,GAAG,mBAAmB;QAC/C,CAAC,CAAC,yFAAyF,GAAG,KAAK;QACnG,CAAC,CAAC,EAAE,CAAA;IAEN,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvB,OAAO,qBAAqB,GAAG,eAAe,CAAC,cAAc,QAAQ,MAAM,UAAU,IAAI,CAAA;IAC3F,CAAC;IAED,MAAM,gBAAgB,GAAG,+DAA+D,GAAG,KAAK,CAAA;IAEhG,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAA;IAC7F,MAAM,cAAc,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,IAAA,oBAAU,EAAC,EAAE,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAE5F,MAAM,SAAS,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;QACnD,MAAM,OAAO,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAA;QAC/C,MAAM,CAAC,GAAG,IAAA,oBAAU,EAAC,OAAO,CAAC,CAAA;QAC7B,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAC5C,MAAM,KAAK,GAAG;YACZ,gBAAgB,OAAO,IAAI;YAC3B,eAAe,OAAO,IAAI;YAC1B,eAAe,CAAC,GAAG,CAAC,kBAAkB;YACtC,4CAA4C;SAC7C,CAAA;QACD,IAAI,MAAM,IAAI,mBAAmB,EAAE,CAAC;YAClC,KAAK,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAA;YACxE,KAAK,CAAC,IAAI,CAAC,yEAAyE,CAAC,CAAA;QACvF,CAAC;QACD,OAAO,KAAK,QAAQ,SAAS,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAA;IACtD,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAEb,MAAM,QAAQ,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IAEtE,OAAO,CACL,qBAAqB;QACrB,gBAAgB;QAChB,oBAAoB,cAAc,aAAa,iBAAiB,GAAG,GAAG,OAAO;QAC7E,eAAe,CAAC,cAAc,QAAQ,YAAY;QAClD,KAAK,UAAU,KAAK;QACpB,OAAO,QAAQ,IAAI;QACnB,wBAAwB;QACxB,SAAS;QACT,gCAAgC,WAAW,6BAA6B;QACxE,GAAG,SAAS,OAAO,CACpB,CAAA;AACH,CAAC"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { DMMF } from '@prisma/generator-helper';
|
|
2
2
|
import { ImportStyle } from '../utils/resolveImportStyle';
|
|
3
|
-
|
|
3
|
+
import { WriteStrategy, FindManyPaginatedMode } from '../constants';
|
|
4
|
+
export declare function generateRouterFunction({ model, enums, guardShapesImport, importStyle, writeStrategy, findManyPaginatedMode, }: {
|
|
4
5
|
model: DMMF.Model;
|
|
5
6
|
enums: DMMF.DatamodelEnum[];
|
|
6
7
|
guardShapesImport: string | null;
|
|
7
8
|
importStyle: ImportStyle;
|
|
9
|
+
writeStrategy: WriteStrategy;
|
|
10
|
+
findManyPaginatedMode: FindManyPaginatedMode;
|
|
8
11
|
}): string;
|