turbine-orm 0.40.1 → 0.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/README.md +22 -4
  2. package/dist/cjs/cli/config.js +3 -0
  3. package/dist/cjs/cli/index.js +179 -0
  4. package/dist/cjs/cli/prisma-report.js +216 -0
  5. package/dist/cjs/cli/prisma-resolve.js +335 -0
  6. package/dist/cjs/cli/prisma-schema.js +484 -0
  7. package/dist/cjs/client.js +1 -0
  8. package/dist/cjs/generate.js +279 -22
  9. package/dist/cjs/index.js +3 -2
  10. package/dist/cjs/introspect.js +203 -26
  11. package/dist/cjs/mssql.js +9 -10
  12. package/dist/cjs/mysql.js +3 -9
  13. package/dist/cjs/powdb-introspect.js +5 -10
  14. package/dist/cjs/powql.js +13 -0
  15. package/dist/cjs/prisma-compat.js +1147 -0
  16. package/dist/cjs/query/aggregates.js +67 -7
  17. package/dist/cjs/query/builder.js +388 -17
  18. package/dist/cjs/query/compound-unique.js +0 -0
  19. package/dist/cjs/query/relations.js +7 -5
  20. package/dist/cjs/query/warn-registry.js +98 -0
  21. package/dist/cjs/query/writes.js +13 -5
  22. package/dist/cjs/schema.js +47 -0
  23. package/dist/cjs/sqlite.js +4 -9
  24. package/dist/cli/config.d.ts +26 -0
  25. package/dist/cli/config.js +3 -0
  26. package/dist/cli/index.d.ts +11 -0
  27. package/dist/cli/index.js +180 -1
  28. package/dist/cli/prisma-report.d.ts +19 -0
  29. package/dist/cli/prisma-report.js +211 -0
  30. package/dist/cli/prisma-resolve.d.ts +87 -0
  31. package/dist/cli/prisma-resolve.js +330 -0
  32. package/dist/cli/prisma-schema.d.ts +116 -0
  33. package/dist/cli/prisma-schema.js +479 -0
  34. package/dist/cli/ui.d.ts +1 -1
  35. package/dist/client.d.ts +18 -2
  36. package/dist/client.js +1 -0
  37. package/dist/generate.d.ts +80 -1
  38. package/dist/generate.js +277 -25
  39. package/dist/index.d.ts +2 -2
  40. package/dist/index.js +1 -1
  41. package/dist/introspect.d.ts +92 -2
  42. package/dist/introspect.js +198 -26
  43. package/dist/mssql.js +10 -11
  44. package/dist/mysql.js +4 -10
  45. package/dist/powdb-introspect.js +5 -10
  46. package/dist/powql.js +13 -0
  47. package/dist/prisma-compat.d.ts +281 -0
  48. package/dist/prisma-compat.js +1143 -0
  49. package/dist/query/aggregates.js +67 -7
  50. package/dist/query/builder.d.ts +77 -4
  51. package/dist/query/builder.js +390 -19
  52. package/dist/query/compound-unique.d.ts +49 -0
  53. package/dist/query/compound-unique.js +0 -0
  54. package/dist/query/deferred.d.ts +18 -0
  55. package/dist/query/relations.js +7 -5
  56. package/dist/query/types.d.ts +70 -9
  57. package/dist/query/warn-registry.d.ts +57 -0
  58. package/dist/query/warn-registry.js +92 -0
  59. package/dist/query/writes.js +13 -5
  60. package/dist/schema.d.ts +75 -0
  61. package/dist/schema.js +46 -0
  62. package/dist/sqlite.js +5 -10
  63. package/package.json +6 -1
@@ -0,0 +1,281 @@
1
+ /**
2
+ * turbine-orm/prisma-compat, a typed PrismaClient-surface adapter over a
3
+ * {@link TurbineClient}.
4
+ *
5
+ * This subpath lets a codebase that speaks Prisma's `db.model.findMany(...)`
6
+ * surface run on Turbine with minimal churn. It is a **pure TypeScript shim**:
7
+ * zero new runtime dependencies, never imported by Turbine core, and driven
8
+ * entirely by the {@link PrismaCompatMap} that `turbine migrate-from-prisma`
9
+ * emits (`prisma-map.ts`). Every Prisma model / field / relation / compound
10
+ * unique name in the map was resolved against live introspected metadata, so
11
+ * the adapter only ever translates names it can prove exist.
12
+ *
13
+ * ## What it does
14
+ *
15
+ * - **Model delegates** under both the Prisma model name (`compat.User`) and
16
+ * Prisma's client-property spelling with the first letter lowercased
17
+ * (`compat.user`, what generated Prisma call sites actually use),
18
+ * translating args recursively: `include`→`with`, `select` split into scalar
19
+ * selection + relations, field/relation renames both ways through the map,
20
+ * `take`/`skip`→`limit`/`offset`, cursor pagination, and compound-unique
21
+ * selectors (including custom `@@unique(name:)` names the core `findUnique`
22
+ * derivation cannot know).
23
+ * - **`$transaction`** in both forms: a callback (`$transaction(async (tx) => …)`)
24
+ * and Prisma's lazy array batching (`$transaction([a.create(...), b.update(...)])`)
25
+ * , the un-awaited delegate calls defer to Turbine's `build*()` methods and
26
+ * run atomically through the core batch `$transaction([...])` path.
27
+ * - **Raw SQL**: `$queryRaw` / `$executeRaw` tagged templates (with
28
+ * `Prisma.sql`-style nested-fragment flattening) and the `*Unsafe` variants.
29
+ * - **Result reshaping**: `_count` objects keyed back to Prisma relation names,
30
+ * and to-one relations surfaced as `object | null`.
31
+ *
32
+ * ## What it deliberately does NOT do (documented divergences)
33
+ *
34
+ * These cannot be faithfully translated and are not attempted; each throws or is
35
+ * documented rather than silently returning wrong data:
36
+ *
37
+ * - `$extends` / client extensions, `$use` with Prisma's middleware param shape.
38
+ * - `instanceof PrismaClientKnownRequestError`, `.meta`/message byte parity
39
+ * (opt into `prismaErrorCodes` for a `.code` like `P2002`, without pretending
40
+ * `instanceof` identity).
41
+ * - `Prisma.join` / `Prisma.raw` composition beyond plain fragment flattening.
42
+ * - Fluent relation chaining (`prisma.user.findUnique().posts()`).
43
+ * - Accelerate / Pulse / driver-adapter preview features, the Mongo API, and the
44
+ * `prisma migrate`/`db` CLI family (Turbine ships its own migrations).
45
+ * - **Inclusive bare cursors whose field is not the sort key**, see
46
+ * {@link translateCursor}. A bare Prisma cursor is inclusive; translating it
47
+ * correctly needs the anchor row's sort-key value. When the cursor field is
48
+ * the single `orderBy` field (or the cursor is the single-column PK with no
49
+ * `orderBy`) it compiles to a `gte`/`lte` keyset predicate; **otherwise it
50
+ * throws** an {@link UnsupportedFeatureError} rather than emit an off-by-one
51
+ * page. Pair the cursor with `skip: 1` (Prisma's idiom) for the exact
52
+ * exclusive-cursor + `offset` translation.
53
+ * - **Negative `take`** (take-from-end) and **`skip` on a nested relation
54
+ * include** throw, Turbine's `with` clause has no offset and no reverse-take.
55
+ *
56
+ * ## Type dependencies (0.41.0)
57
+ *
58
+ * - Field-name identity fast path pairs with the generator's
59
+ * `--keep-column-names` output (byte-shaped like a snake_case Prisma client).
60
+ * - Compound-unique default selectors are handled by the core
61
+ * `findUnique`-family derivation; this adapter only translates custom
62
+ * `@@unique(name:)` names on top.
63
+ * - To-one relations return `object | null` natively once the unique-FK hasOne
64
+ * introspection default is in effect (0.41.0). Until a schema is regenerated,
65
+ * the map's `cardinality: 'one'` still drives the first-element-or-null guard,
66
+ * so the surface is correct either way.
67
+ *
68
+ * @example
69
+ * ```ts
70
+ * import { TurbineClient } from 'turbine-orm';
71
+ * import { createPrismaCompatClient } from 'turbine-orm/prisma-compat';
72
+ * import { SCHEMA } from './generated/turbine/metadata.js';
73
+ * import { PRISMA_MAP } from './generated/turbine/prisma-map.js';
74
+ *
75
+ * const db = new TurbineClient({ connectionString: process.env.DATABASE_URL }, SCHEMA);
76
+ * const prisma = createPrismaCompatClient(db, PRISMA_MAP);
77
+ *
78
+ * const users = await prisma.User.findMany({
79
+ * where: { email: { contains: '@acme.com' } },
80
+ * include: { posts: { orderBy: { createdAt: 'desc' }, take: 5 } },
81
+ * });
82
+ * ```
83
+ */
84
+ import type { TurbineClient } from './client.js';
85
+ import type { DeferredQuery } from './query/index.js';
86
+ import type { PrismaCompatMap, SchemaMetadata } from './schema.js';
87
+ /** A build-only query object with the `build*` methods the adapter drives. */
88
+ export interface CompatQueryInterface {
89
+ findMany(args?: Record<string, unknown>): Promise<unknown>;
90
+ findFirst(args?: Record<string, unknown>): Promise<unknown>;
91
+ findUnique(args: Record<string, unknown>): Promise<unknown>;
92
+ findFirstOrThrow(args?: Record<string, unknown>): Promise<unknown>;
93
+ findUniqueOrThrow(args: Record<string, unknown>): Promise<unknown>;
94
+ create(args: Record<string, unknown>): Promise<unknown>;
95
+ createMany(args: Record<string, unknown>): Promise<unknown[]>;
96
+ update(args: Record<string, unknown>): Promise<unknown>;
97
+ updateMany(args: Record<string, unknown>): Promise<{
98
+ count: number;
99
+ }>;
100
+ delete(args: Record<string, unknown>): Promise<unknown>;
101
+ deleteMany(args: Record<string, unknown>): Promise<{
102
+ count: number;
103
+ }>;
104
+ upsert(args: Record<string, unknown>): Promise<unknown>;
105
+ count(args?: Record<string, unknown>): Promise<number>;
106
+ aggregate(args: Record<string, unknown>): Promise<unknown>;
107
+ groupBy(args: Record<string, unknown>): Promise<unknown[]>;
108
+ buildFindMany(args?: Record<string, unknown>): DeferredQuery<unknown>;
109
+ buildFindFirst(args?: Record<string, unknown>): DeferredQuery<unknown>;
110
+ buildFindUnique(args: Record<string, unknown>): DeferredQuery<unknown>;
111
+ buildFindFirstOrThrow(args?: Record<string, unknown>): DeferredQuery<unknown>;
112
+ buildFindUniqueOrThrow(args: Record<string, unknown>): DeferredQuery<unknown>;
113
+ buildCreate(args: Record<string, unknown>): DeferredQuery<unknown>;
114
+ buildCreateMany(args: Record<string, unknown>): DeferredQuery<unknown[]>;
115
+ buildUpdate(args: Record<string, unknown>): DeferredQuery<unknown>;
116
+ buildUpdateMany(args: Record<string, unknown>): DeferredQuery<{
117
+ count: number;
118
+ }>;
119
+ buildDelete(args: Record<string, unknown>): DeferredQuery<unknown>;
120
+ buildDeleteMany(args: Record<string, unknown>): DeferredQuery<{
121
+ count: number;
122
+ }>;
123
+ buildUpsert(args: Record<string, unknown>): DeferredQuery<unknown>;
124
+ buildCount(args?: Record<string, unknown>): DeferredQuery<number>;
125
+ buildAggregate(args: Record<string, unknown>): DeferredQuery<unknown>;
126
+ buildGroupBy(args: Record<string, unknown>): DeferredQuery<unknown[]>;
127
+ }
128
+ /** A transaction-scoped client handed to a `$transaction(callback)`. */
129
+ export interface CompatTransactionClient {
130
+ table(name: string): CompatQueryInterface;
131
+ }
132
+ /** The minimal `TurbineClient` surface the adapter consumes. */
133
+ export interface CompatTurbineClient extends CompatTransactionClient {
134
+ readonly schema: SchemaMetadata;
135
+ $transaction<R>(fn: (tx: CompatTransactionClient) => Promise<R>, options?: unknown): Promise<R>;
136
+ $transaction(queries: readonly DeferredQuery<unknown>[]): Promise<unknown[]>;
137
+ }
138
+ declare const SQL_FRAGMENT: unique symbol;
139
+ /** A composable SQL fragment, the local stand-in for `Prisma.Sql`. */
140
+ export interface Sql {
141
+ /** Literal string segments; `strings.length === values.length + 1`. */
142
+ readonly strings: readonly string[];
143
+ /** Interpolated values, one between each pair of `strings`. */
144
+ readonly values: readonly unknown[];
145
+ readonly [SQL_FRAGMENT]: true;
146
+ }
147
+ /**
148
+ * `Prisma`-compatible raw-SQL helpers, a minimal local implementation so
149
+ * migrated `Prisma.sql\`…\`` / `Prisma.join(...)` / `Prisma.raw(...)` calls keep
150
+ * composing. Fragments are flattened at execution time into a single
151
+ * parameterized statement (values become `$N`), so composition is injection-safe
152
+ * by construction.
153
+ */
154
+ export declare const Prisma: {
155
+ /** Tagged-template fragment: `Prisma.sql\`id = ${id}\``. */
156
+ sql(strings: TemplateStringsArray, ...values: unknown[]): Sql;
157
+ /**
158
+ * Join fragments/values with a separator: `Prisma.join([1, 2, 3])` →
159
+ * `$1, $2, $3`. Each element that is not already a fragment becomes a bound
160
+ * value.
161
+ */
162
+ join(items: readonly unknown[], separator?: string, prefix?: string, suffix?: string): Sql;
163
+ /**
164
+ * A raw, unparameterized SQL fragment. The string is spliced verbatim, never
165
+ * pass user input here (matches Prisma's `Prisma.raw` contract).
166
+ */
167
+ raw(sql: string): Sql;
168
+ /** An empty fragment. */
169
+ empty: Sql;
170
+ };
171
+ /** Options for {@link createPrismaCompatClient}. */
172
+ export interface PrismaCompatOptions {
173
+ /**
174
+ * When `true`, every to-many `with` relation lacking an explicit `orderBy` is
175
+ * loaded ordered by the target table's primary key ascending (Prisma's
176
+ * relation rows come back in a stable order). This passes through to Turbine's
177
+ * core `stableRelationOrder` flag, it never re-walks the `with` tree. An
178
+ * explicit per-relation `orderBy` always wins. Default `false`.
179
+ */
180
+ stablePkOrder?: boolean;
181
+ /**
182
+ * When `true`, thrown {@link TurbineError}s are decorated with a `.code` equal
183
+ * to the nearest Prisma error code (e.g. `P2002` for a unique violation),
184
+ * WITHOUT pretending `instanceof PrismaClientKnownRequestError`. Default
185
+ * `false` (Turbine's own `TURBINE_E0NN` codes are preserved untouched).
186
+ */
187
+ prismaErrorCodes?: boolean;
188
+ }
189
+ /** Symbol under which a lazy delegate call exposes its batchable plan. */
190
+ export declare const COMPAT_DEFERRED: unique symbol;
191
+ /**
192
+ * The per-model type bundle a consumer supplies to type a model delegate.
193
+ * Populate `Row` (and optionally the arg shapes) from the generated entity
194
+ * types; unspecified members fall back to permissive shapes.
195
+ */
196
+ export interface PrismaModelTypes {
197
+ Row: object;
198
+ Create?: object;
199
+ Update?: object;
200
+ Where?: object;
201
+ OrderBy?: object;
202
+ Select?: object;
203
+ Include?: object;
204
+ }
205
+ type Args = Record<string, unknown>;
206
+ /** A typed model delegate mirroring Prisma's `db.model.*` surface. */
207
+ export interface PrismaModelDelegate<M extends PrismaModelTypes> {
208
+ findMany(args?: Args): Promise<M['Row'][]>;
209
+ findFirst(args?: Args): Promise<M['Row'] | null>;
210
+ findUnique(args: Args): Promise<M['Row'] | null>;
211
+ findFirstOrThrow(args?: Args): Promise<M['Row']>;
212
+ findUniqueOrThrow(args: Args): Promise<M['Row']>;
213
+ create(args: Args): Promise<M['Row']>;
214
+ createMany(args: Args): Promise<{
215
+ count: number;
216
+ }>;
217
+ update(args: Args): Promise<M['Row']>;
218
+ updateMany(args: Args): Promise<{
219
+ count: number;
220
+ }>;
221
+ delete(args: Args): Promise<M['Row']>;
222
+ deleteMany(args?: Args): Promise<{
223
+ count: number;
224
+ }>;
225
+ upsert(args: Args): Promise<M['Row']>;
226
+ count(args?: Args): Promise<number>;
227
+ aggregate(args: Args): Promise<Record<string, unknown>>;
228
+ groupBy(args: Args): Promise<Record<string, unknown>[]>;
229
+ }
230
+ /** The client-level surface (`$transaction` / raw), added to the model map. */
231
+ export interface PrismaCompatClientBase<S extends Record<string, PrismaModelTypes> = Record<string, PrismaModelTypes>> {
232
+ $transaction<R>(fn: (tx: PrismaCompatTransactionClient<S>) => Promise<R>, options?: PrismaCompatTxOptions): Promise<R>;
233
+ $transaction<P extends readonly PromiseLike<unknown>[]>(promises: readonly [...P]): Promise<{
234
+ [K in keyof P]: Awaited<P[K]>;
235
+ }>;
236
+ $queryRaw<T = unknown>(strings: TemplateStringsArray, ...values: unknown[]): Promise<T[]>;
237
+ $queryRawUnsafe<T = unknown>(sql: string, ...params: unknown[]): Promise<T[]>;
238
+ $executeRaw(strings: TemplateStringsArray, ...values: unknown[]): Promise<number>;
239
+ $executeRawUnsafe(sql: string, ...params: unknown[]): Promise<number>;
240
+ $connect(): Promise<void>;
241
+ $disconnect(): Promise<void>;
242
+ }
243
+ /** Options accepted by the callback form of `$transaction`. */
244
+ export interface PrismaCompatTxOptions {
245
+ isolationLevel?: 'ReadUncommitted' | 'ReadCommitted' | 'RepeatableRead' | 'Serializable';
246
+ timeout?: number;
247
+ maxWait?: number;
248
+ }
249
+ /** The transaction-scoped client handed to a `$transaction(callback)`. */
250
+ export type PrismaCompatTransactionClient<S extends Record<string, PrismaModelTypes> = Record<string, PrismaModelTypes>> = {
251
+ [K in keyof S]: PrismaModelDelegate<S[K]>;
252
+ };
253
+ /**
254
+ * The full typed compat client: a model delegate per Prisma model name, plus the
255
+ * client-level `$transaction` / raw surface. Parameterize `S` with your
256
+ * generated entity types for full autocompletion.
257
+ */
258
+ export type PrismaCompatClient<S extends Record<string, PrismaModelTypes> = Record<string, PrismaModelTypes>> = {
259
+ [K in keyof S]: PrismaModelDelegate<S[K]>;
260
+ } & {
261
+ [K in keyof S as Uncapitalize<K & string>]: PrismaModelDelegate<S[K]>;
262
+ } & PrismaCompatClientBase<S>;
263
+ /**
264
+ * Create a PrismaClient-surface adapter over a {@link TurbineClient}, driven by a
265
+ * {@link PrismaCompatMap} (the `prisma-map.ts` that `turbine
266
+ * migrate-from-prisma` emits).
267
+ *
268
+ * The returned object exposes a delegate per Prisma model name (by the map's
269
+ * keys) plus the client-level `$transaction` / `$queryRaw` / `$executeRaw`
270
+ * surface. Model and field names are translated through the map in both
271
+ * directions; when field names are identity (the `--keep-column-names` pairing)
272
+ * result rekeying is skipped entirely.
273
+ *
274
+ * @typeParam S - Per-model type bundles (from your generated entity types) for
275
+ * full autocompletion. Defaults to a permissive shape.
276
+ * @param client - The TurbineClient (or generated subclass / `turbineHttp` client).
277
+ * @param map - The resolved `PRISMA_MAP`.
278
+ * @param options - {@link PrismaCompatOptions}.
279
+ */
280
+ export declare function createPrismaCompatClient<S extends Record<string, PrismaModelTypes> = Record<string, PrismaModelTypes>>(client: TurbineClient, map: PrismaCompatMap, options?: PrismaCompatOptions): PrismaCompatClient<S>;
281
+ export {};