prisma-generator-express 1.55.0 → 1.56.1
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 +131 -12
- package/dist/constants.d.ts +1 -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 +2 -1
- package/dist/generators/generateOperationCore.js +38 -36
- package/dist/generators/generateOperationCore.js.map +1 -1
- package/dist/generators/generateRouteConfigType.js +2 -1
- package/dist/generators/generateRouteConfigType.js.map +1 -1
- package/dist/generators/generateRouter.d.ts +3 -2
- package/dist/generators/generateRouter.js +16 -5
- package/dist/generators/generateRouter.js.map +1 -1
- package/dist/generators/generateRouterFastify.d.ts +3 -2
- package/dist/generators/generateRouterFastify.js +19 -7
- package/dist/generators/generateRouterFastify.js.map +1 -1
- package/dist/generators/generateRouterHono.d.ts +3 -2
- package/dist/generators/generateRouterHono.js +24 -14
- package/dist/generators/generateRouterHono.js.map +1 -1
- package/dist/index.js +20 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/constants.ts +3 -1
- package/src/copy/autoIncludeRuntime.ts +60 -35
- package/src/copy/docsRenderer.ts +5 -4
- package/src/copy/operationRuntime.ts +94 -9
- package/src/copy/routeConfig.express.ts +6 -0
- package/src/copy/routeConfig.fastify.ts +7 -1
- package/src/copy/routeConfig.hono.ts +8 -2
- package/src/copy/routeConfig.ts +21 -5
- package/src/generators/generateFastifyHandler.ts +3 -1
- package/src/generators/generateHonoHandler.ts +3 -1
- package/src/generators/generateOperationCore.ts +42 -37
- package/src/generators/generateRouteConfigType.ts +2 -2
- package/src/generators/generateRouter.ts +18 -5
- package/src/generators/generateRouterFastify.ts +21 -7
- package/src/generators/generateRouterHono.ts +26 -14
- package/src/index.ts +24 -2
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
|
|
@@ -27,6 +29,7 @@ Supports **Express**, **Fastify**, and **Hono** targets via the `target` configu
|
|
|
27
29
|
- [Installation](#installation)
|
|
28
30
|
- [Setup](#setup)
|
|
29
31
|
- [Write strategy](#write-strategy)
|
|
32
|
+
- [findManyPaginated execution mode](#findmanypaginated-execution-mode)
|
|
30
33
|
- [Path casing in generated endpoints](#path-casing-in-generated-endpoints)
|
|
31
34
|
- [Usage (Express)](#usage-express)
|
|
32
35
|
- [Usage (Fastify)](#usage-fastify)
|
|
@@ -193,6 +196,38 @@ generator express {
|
|
|
193
196
|
}
|
|
194
197
|
```
|
|
195
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
|
+
|
|
196
231
|
## Path casing in generated endpoints
|
|
197
232
|
|
|
198
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.
|
|
@@ -2317,11 +2352,11 @@ On the client side, `encodeQueryParams` handles BigInt serialization automatical
|
|
|
2317
2352
|
|
|
2318
2353
|
## Pagination
|
|
2319
2354
|
|
|
2320
|
-
`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.
|
|
2321
2356
|
|
|
2322
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.
|
|
2323
2358
|
|
|
2324
|
-
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.
|
|
2325
2360
|
|
|
2326
2361
|
Configure default and maximum page sizes and the distinct count limit:
|
|
2327
2362
|
|
|
@@ -2338,6 +2373,68 @@ UserRouter({
|
|
|
2338
2373
|
|
|
2339
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`.
|
|
2340
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
|
+
|
|
2341
2438
|
## Error handling
|
|
2342
2439
|
|
|
2343
2440
|
All errors are returned as JSON with a `message` field:
|
|
@@ -2356,7 +2453,7 @@ For the Hono target, thrown `HTTPException` instances are caught by `app.onError
|
|
|
2356
2453
|
| 403 | Guard policy rejected |
|
|
2357
2454
|
| 404 | Record not found |
|
|
2358
2455
|
| 409 | Unique constraint or transaction conflict |
|
|
2359
|
-
| 500 | Internal server error
|
|
2456
|
+
| 500 | Internal server error, including transaction mode without transaction support |
|
|
2360
2457
|
| 501 | Feature not supported by database provider |
|
|
2361
2458
|
| 503 | Database connection pool timeout |
|
|
2362
2459
|
|
|
@@ -2642,6 +2739,8 @@ POST read endpoints are enabled by default. Set `disablePostReads: true` to remo
|
|
|
2642
2739
|
|
|
2643
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`.
|
|
2644
2741
|
|
|
2742
|
+
The schema-wide `findManyPaginatedMode` option changes the generated implementation behind `GET` and `POST /{modelname}/paginated`, but not the public response shape.
|
|
2743
|
+
|
|
2645
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).
|
|
2646
2745
|
|
|
2647
2746
|
## Skipping models
|
|
@@ -2663,9 +2762,10 @@ Generator options are configured in `schema.prisma` and apply schema-wide.
|
|
|
2663
2762
|
|
|
2664
2763
|
```prisma
|
|
2665
2764
|
generator express {
|
|
2666
|
-
provider
|
|
2667
|
-
target
|
|
2668
|
-
writeStrategy
|
|
2765
|
+
provider = "prisma-generator-express"
|
|
2766
|
+
target = "express"
|
|
2767
|
+
writeStrategy = "regular"
|
|
2768
|
+
findManyPaginatedMode = "promiseAll"
|
|
2669
2769
|
}
|
|
2670
2770
|
```
|
|
2671
2771
|
|
|
@@ -2673,10 +2773,28 @@ generator express {
|
|
|
2673
2773
|
| ------ | ------ | ------- | ----------- |
|
|
2674
2774
|
| `target` | `"express"`, `"fastify"`, `"hono"` | `"express"` | Selects the generated router target. |
|
|
2675
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). |
|
|
2676
2777
|
|
|
2677
2778
|
### Express
|
|
2678
2779
|
|
|
2679
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
|
+
|
|
2680
2798
|
interface RouteConfig<TCtx = unknown> {
|
|
2681
2799
|
enableAll?: boolean
|
|
2682
2800
|
addModelPrefix?: boolean // default: true
|
|
@@ -2702,11 +2820,7 @@ interface RouteConfig<TCtx = unknown> {
|
|
|
2702
2820
|
|
|
2703
2821
|
queryBuilder?: QueryBuilderConfig | false
|
|
2704
2822
|
|
|
2705
|
-
pagination?:
|
|
2706
|
-
defaultLimit?: number
|
|
2707
|
-
maxLimit?: number
|
|
2708
|
-
distinctCountLimit?: number // default: 100000
|
|
2709
|
-
}
|
|
2823
|
+
pagination?: PaginationConfig
|
|
2710
2824
|
|
|
2711
2825
|
// read operation config
|
|
2712
2826
|
findMany?: ReadOperationConfig<TCtx>
|
|
@@ -2735,6 +2849,7 @@ interface OperationConfig {
|
|
|
2735
2849
|
before?: RequestHandler[]
|
|
2736
2850
|
after?: RequestHandler[]
|
|
2737
2851
|
shape?: Record<string, any>
|
|
2852
|
+
pagination?: Partial<PaginationConfig>
|
|
2738
2853
|
}
|
|
2739
2854
|
|
|
2740
2855
|
interface ReadOperationConfig<TCtx = unknown> extends OperationConfig {
|
|
@@ -2806,6 +2921,7 @@ interface OperationConfig {
|
|
|
2806
2921
|
before?: FastifyHookHandler[]
|
|
2807
2922
|
after?: FastifyHookHandler[]
|
|
2808
2923
|
shape?: Record<string, any>
|
|
2924
|
+
pagination?: Partial<PaginationConfig>
|
|
2809
2925
|
}
|
|
2810
2926
|
|
|
2811
2927
|
type FastifyHookHandler = (
|
|
@@ -2825,6 +2941,7 @@ interface OperationConfig {
|
|
|
2825
2941
|
before?: HonoHookHandler[]
|
|
2826
2942
|
after?: HonoHookHandler[]
|
|
2827
2943
|
shape?: Record<string, any>
|
|
2944
|
+
pagination?: Partial<PaginationConfig>
|
|
2828
2945
|
}
|
|
2829
2946
|
|
|
2830
2947
|
type HonoHookHandler<Env extends { Variables: any } = any> = (
|
|
@@ -2839,7 +2956,7 @@ The Hono router does not auto-start the Query Builder. Set `queryBuilder: false`
|
|
|
2839
2956
|
|
|
2840
2957
|
### Shared route options
|
|
2841
2958
|
|
|
2842
|
-
These options are passed to the generated router at runtime. They are separate from schema-wide generator options such as `target` and `
|
|
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`.
|
|
2843
2960
|
|
|
2844
2961
|
`customUrlPrefix` is normalized to ensure a leading slash and strip trailing slashes.
|
|
2845
2962
|
|
|
@@ -2849,6 +2966,8 @@ These options are passed to the generated router at runtime. They are separate f
|
|
|
2849
2966
|
|
|
2850
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`.
|
|
2851
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
|
+
|
|
2852
2971
|
`openApiServers` sets the `servers` array in the OpenAPI spec:
|
|
2853
2972
|
|
|
2854
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,9 +1,10 @@
|
|
|
1
1
|
import { DMMF } from '@prisma/generator-helper';
|
|
2
2
|
import { ImportStyle } from '../utils/resolveImportStyle';
|
|
3
|
-
import { WriteStrategy } from '../constants';
|
|
3
|
+
import { WriteStrategy, FindManyPaginatedMode } from '../constants';
|
|
4
4
|
export interface ModelCoreOptions {
|
|
5
5
|
model: DMMF.Model;
|
|
6
6
|
importStyle: ImportStyle;
|
|
7
7
|
writeStrategy: WriteStrategy;
|
|
8
|
+
findManyPaginatedMode: FindManyPaginatedMode;
|
|
8
9
|
}
|
|
9
10
|
export declare function generateModelCore(options: ModelCoreOptions): string;
|
|
@@ -18,11 +18,47 @@ function decideWriteOp(name, defaultMethod, strategy) {
|
|
|
18
18
|
return { mode: 'redirect', method: 'updateManyAndReturn' };
|
|
19
19
|
return { mode: 'normal', method: defaultMethod };
|
|
20
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
|
+
}
|
|
21
56
|
function generateModelCore(options) {
|
|
22
57
|
const ext = (0, importExt_1.importExt)(options.importStyle);
|
|
23
58
|
const modelName = options.model.name;
|
|
24
59
|
const modelNameLower = modelName.charAt(0).toLowerCase() + modelName.slice(1);
|
|
25
60
|
const writeStrategy = options.writeStrategy;
|
|
61
|
+
const paginatedBody = renderPaginatedBody(modelNameLower, options.findManyPaginatedMode);
|
|
26
62
|
const standardReadOps = [
|
|
27
63
|
'findFirst', 'findUnique', 'findUniqueOrThrow', 'findFirstOrThrow',
|
|
28
64
|
'count', 'aggregate', 'groupBy',
|
|
@@ -113,45 +149,11 @@ export async function findManyPaginated(
|
|
|
113
149
|
const shape = ctx.guardShape
|
|
114
150
|
const caller = ctx.guardCaller
|
|
115
151
|
const distinctCountLimit = ctx.paginationConfig?.distinctCountLimit
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
if (shape) assertGuard(delegate)
|
|
152
|
+
const countSource = ctx.paginationConfig?.countSource
|
|
119
153
|
|
|
120
154
|
let items: unknown[]
|
|
121
155
|
let total: number
|
|
122
|
-
|
|
123
|
-
const txClient = extended as { $transaction?: <T>(fn: (tx: unknown) => Promise<T>) => Promise<T> }
|
|
124
|
-
|
|
125
|
-
if (shape || typeof txClient.$transaction !== 'function') {
|
|
126
|
-
const [data, count] = await Promise.all([
|
|
127
|
-
shape
|
|
128
|
-
? (delegate.guard as NonNullable<typeof delegate.guard>)(shape, caller).findMany(query)
|
|
129
|
-
: delegate.findMany(query),
|
|
130
|
-
countForPagination(delegate, query, shape, caller, distinctCountLimit),
|
|
131
|
-
])
|
|
132
|
-
items = data as unknown[]
|
|
133
|
-
total = count
|
|
134
|
-
} else {
|
|
135
|
-
try {
|
|
136
|
-
const txResult = await txClient.$transaction(async (tx: unknown) => {
|
|
137
|
-
const txDelegate = getDelegate(tx, '${modelNameLower}')
|
|
138
|
-
const d = await txDelegate.findMany(query)
|
|
139
|
-
const t = await countForPagination(txDelegate, query, undefined, undefined, distinctCountLimit)
|
|
140
|
-
return { d, t }
|
|
141
|
-
})
|
|
142
|
-
items = txResult.d as unknown[]
|
|
143
|
-
total = txResult.t
|
|
144
|
-
} catch (txError: unknown) {
|
|
145
|
-
const txe = txError as { message?: string; code?: string }
|
|
146
|
-
if (txe?.code === 'P2028') {
|
|
147
|
-
console.warn('[prisma-generator-express] Interactive transactions not available, pagination queries are non-atomic')
|
|
148
|
-
items = (await delegate.findMany(query)) as unknown[]
|
|
149
|
-
total = await countForPagination(delegate, query, undefined, undefined, distinctCountLimit)
|
|
150
|
-
} else {
|
|
151
|
-
throw txError
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
156
|
+
${paginatedBody}
|
|
155
157
|
|
|
156
158
|
const skip = (typeof query.skip === 'number' ? query.skip : 0)
|
|
157
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,7 +70,7 @@ 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`;
|
|
@@ -85,6 +85,7 @@ function generateRouteConfigType(modelName, hookHandlerType, guardShapesImport,
|
|
|
85
85
|
` before?: ${hookRef}[]`,
|
|
86
86
|
` after?: ${hookRef}[]`,
|
|
87
87
|
` shape?: ${m}${c}ShapeInput<TCtx>`,
|
|
88
|
+
` pagination?: Partial<PaginationConfig>`,
|
|
88
89
|
];
|
|
89
90
|
if (isRead && supportsProgressive) {
|
|
90
91
|
lines.push(` progressive?: Record<string, ProgressiveVariantConfig>`);
|
|
@@ -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":"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"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { DMMF } from '@prisma/generator-helper';
|
|
2
2
|
import { ImportStyle } from '../utils/resolveImportStyle';
|
|
3
|
-
import { WriteStrategy } from '../constants';
|
|
4
|
-
export declare function generateRouterFunction({ model, enums, guardShapesImport, importStyle, writeStrategy, }: {
|
|
3
|
+
import { WriteStrategy, FindManyPaginatedMode } from '../constants';
|
|
4
|
+
export declare function generateRouterFunction({ model, enums, guardShapesImport, importStyle, writeStrategy, findManyPaginatedMode, }: {
|
|
5
5
|
model: DMMF.Model;
|
|
6
6
|
enums: DMMF.DatamodelEnum[];
|
|
7
7
|
guardShapesImport: string | null;
|
|
8
8
|
importStyle: ImportStyle;
|
|
9
9
|
writeStrategy: WriteStrategy;
|
|
10
|
+
findManyPaginatedMode: FindManyPaginatedMode;
|
|
10
11
|
}): string;
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.generateRouterFunction = generateRouterFunction;
|
|
4
4
|
const generateRouteConfigType_1 = require("./generateRouteConfigType");
|
|
5
5
|
const importExt_1 = require("../utils/importExt");
|
|
6
|
-
function generateRouterFunction({ model, enums, guardShapesImport, importStyle, writeStrategy, }) {
|
|
6
|
+
function generateRouterFunction({ model, enums, guardShapesImport, importStyle, writeStrategy, findManyPaginatedMode, }) {
|
|
7
7
|
const ext = (0, importExt_1.importExt)(importStyle);
|
|
8
8
|
const modelName = model.name;
|
|
9
9
|
const modelNameLower = modelName.toLowerCase();
|
|
@@ -51,7 +51,13 @@ import {
|
|
|
51
51
|
${modelName}GroupBy,
|
|
52
52
|
} from './${modelName}Handlers${ext}'
|
|
53
53
|
import * as core from './${modelName}Core${ext}'
|
|
54
|
-
import type {
|
|
54
|
+
import type {
|
|
55
|
+
RouteConfig,
|
|
56
|
+
QueryBuilderConfig,
|
|
57
|
+
WriteStrategy,
|
|
58
|
+
FindManyPaginatedMode,
|
|
59
|
+
PaginationConfig,
|
|
60
|
+
} from '../routeConfig.target${ext}'
|
|
55
61
|
import { parseQueryParams } from '../parseQueryParams${ext}'
|
|
56
62
|
import { sanitizeKeys, normalizePrefix, getEnv } from '../misc${ext}'
|
|
57
63
|
import { buildModelOpenApi } from '../buildModelOpenApi${ext}'
|
|
@@ -63,6 +69,7 @@ import {
|
|
|
63
69
|
runSingleResultSSE,
|
|
64
70
|
emitTerminalSSEError,
|
|
65
71
|
removeReqCloseListener,
|
|
72
|
+
mergePaginationConfig,
|
|
66
73
|
mapError,
|
|
67
74
|
HttpError,
|
|
68
75
|
} from '../operationRuntime${ext}'
|
|
@@ -73,6 +80,7 @@ ${(0, generateRouteConfigType_1.generateRouteConfigType)(modelName, 'RequestHand
|
|
|
73
80
|
const _env = getEnv()
|
|
74
81
|
|
|
75
82
|
const WRITE_STRATEGY: WriteStrategy = '${writeStrategy}'
|
|
83
|
+
const FIND_MANY_PAGINATED_MODE: FindManyPaginatedMode = '${findManyPaginatedMode}'
|
|
76
84
|
|
|
77
85
|
const MODEL_FIELDS = ${JSON.stringify(fieldsMeta, null, 2)} as const
|
|
78
86
|
const MODEL_ENUMS = ${JSON.stringify(enumsMeta, null, 2)} as const
|
|
@@ -81,6 +89,7 @@ type OperationConfigLike = {
|
|
|
81
89
|
before?: RequestHandler[]
|
|
82
90
|
after?: RequestHandler[]
|
|
83
91
|
shape?: Record<string, unknown>
|
|
92
|
+
pagination?: Partial<PaginationConfig>
|
|
84
93
|
progressive?: Record<string, ProgressiveVariantConfig>
|
|
85
94
|
progressiveStages?: Record<string, ProgressiveStage<unknown>>
|
|
86
95
|
}
|
|
@@ -93,7 +102,7 @@ type ExtendedRequest = Request & {
|
|
|
93
102
|
|
|
94
103
|
type LocalsBag = {
|
|
95
104
|
parsedQuery?: Record<string, unknown>
|
|
96
|
-
routeConfig?: { pagination?:
|
|
105
|
+
routeConfig?: { pagination?: PaginationConfig }
|
|
97
106
|
guardShape?: Record<string, unknown>
|
|
98
107
|
guardCaller?: string
|
|
99
108
|
data?: unknown
|
|
@@ -176,6 +185,7 @@ export function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(config: ${m
|
|
|
176
185
|
guardShape: locals.guardShape,
|
|
177
186
|
guardCaller: locals.guardCaller,
|
|
178
187
|
paginationConfig: locals.routeConfig?.pagination,
|
|
188
|
+
findManyPaginatedMode: FIND_MANY_PAGINATED_MODE,
|
|
179
189
|
}
|
|
180
190
|
}
|
|
181
191
|
|
|
@@ -199,8 +209,9 @@ export function ${routerFunctionName}<TCtx = unknown, TPrisma = any>(config: ${m
|
|
|
199
209
|
const setShape = (opConfig: OperationConfigLike): RequestHandler => {
|
|
200
210
|
return (req, res, next) => {
|
|
201
211
|
const locals = readLocals(res)
|
|
202
|
-
|
|
203
|
-
|
|
212
|
+
const merged = mergePaginationConfig(config.pagination, opConfig.pagination)
|
|
213
|
+
if (merged) {
|
|
214
|
+
locals.routeConfig = { pagination: merged }
|
|
204
215
|
}
|
|
205
216
|
const headerName = config.guard?.variantHeader || 'x-api-variant'
|
|
206
217
|
const headerValue = req.get(headerName)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateRouter.js","sourceRoot":"","sources":["../../src/generators/generateRouter.ts"],"names":[],"mappings":";;AAMA,
|
|
1
|
+
{"version":3,"file":"generateRouter.js","sourceRoot":"","sources":["../../src/generators/generateRouter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { DMMF } from '@prisma/generator-helper';
|
|
2
2
|
import { ImportStyle } from '../utils/resolveImportStyle';
|
|
3
|
-
import { WriteStrategy } from '../constants';
|
|
4
|
-
export declare function generateFastifyRouterFunction({ model, enums, guardShapesImport, importStyle, writeStrategy, }: {
|
|
3
|
+
import { WriteStrategy, FindManyPaginatedMode } from '../constants';
|
|
4
|
+
export declare function generateFastifyRouterFunction({ model, enums, guardShapesImport, importStyle, writeStrategy, findManyPaginatedMode, }: {
|
|
5
5
|
model: DMMF.Model;
|
|
6
6
|
enums: DMMF.DatamodelEnum[];
|
|
7
7
|
guardShapesImport: string | null;
|
|
8
8
|
importStyle: ImportStyle;
|
|
9
9
|
writeStrategy: WriteStrategy;
|
|
10
|
+
findManyPaginatedMode: FindManyPaginatedMode;
|
|
10
11
|
}): string;
|