turbine-orm 0.19.1 → 0.21.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 (53) hide show
  1. package/README.md +156 -24
  2. package/dist/adapters/cockroachdb.js +4 -9
  3. package/dist/cjs/adapters/cockroachdb.js +4 -9
  4. package/dist/cjs/cli/index.js +23 -12
  5. package/dist/cjs/cli/observe-ui.js +12 -2
  6. package/dist/cjs/cli/observe.js +6 -7
  7. package/dist/cjs/cli/studio-ui.generated.js +1 -1
  8. package/dist/cjs/cli/studio.js +6 -37
  9. package/dist/cjs/client.js +45 -33
  10. package/dist/cjs/dialect.js +116 -0
  11. package/dist/cjs/errors.js +19 -1
  12. package/dist/cjs/generate.js +4 -0
  13. package/dist/cjs/index.js +3 -2
  14. package/dist/cjs/introspect.js +20 -0
  15. package/dist/cjs/mssql.js +1338 -0
  16. package/dist/cjs/mysql.js +1052 -0
  17. package/dist/cjs/query/builder.js +408 -122
  18. package/dist/cjs/query/utils.js +1 -0
  19. package/dist/cjs/sqlite.js +849 -0
  20. package/dist/cjs/typed-sql.js +9 -7
  21. package/dist/cli/index.js +23 -12
  22. package/dist/cli/migrate.d.ts +2 -2
  23. package/dist/cli/observe-ui.d.ts +1 -1
  24. package/dist/cli/observe-ui.js +12 -2
  25. package/dist/cli/observe.js +7 -8
  26. package/dist/cli/studio-ui.generated.js +1 -1
  27. package/dist/cli/studio.d.ts +0 -10
  28. package/dist/cli/studio.js +7 -37
  29. package/dist/client.d.ts +35 -14
  30. package/dist/client.js +46 -34
  31. package/dist/dialect.d.ts +258 -1
  32. package/dist/dialect.js +83 -0
  33. package/dist/errors.d.ts +12 -0
  34. package/dist/errors.js +17 -0
  35. package/dist/generate.js +4 -0
  36. package/dist/index.d.ts +4 -4
  37. package/dist/index.js +1 -1
  38. package/dist/introspect.d.ts +18 -0
  39. package/dist/introspect.js +19 -0
  40. package/dist/mssql.d.ts +233 -0
  41. package/dist/mssql.js +1298 -0
  42. package/dist/mysql.d.ts +174 -0
  43. package/dist/mysql.js +1012 -0
  44. package/dist/query/builder.d.ts +105 -6
  45. package/dist/query/builder.js +409 -123
  46. package/dist/query/index.d.ts +2 -2
  47. package/dist/query/types.d.ts +62 -12
  48. package/dist/query/utils.js +1 -0
  49. package/dist/sqlite.d.ts +144 -0
  50. package/dist/sqlite.js +842 -0
  51. package/dist/typed-sql.d.ts +7 -5
  52. package/dist/typed-sql.js +9 -7
  53. package/package.json +32 -3
@@ -5,11 +5,11 @@
5
5
  * `import { … } from './query/index.js'` is a drop-in replacement for the
6
6
  * former monolithic `import { … } from './query.js'`.
7
7
  */
8
- export type { AggregateArgs, AggregateResult, ArrayFilter, ConnectOrCreateOp, CountArgs, CreateArgs, CreateManyArgs, DeleteArgs, DeleteManyArgs, FieldResult, FindManyArgs, FindManyStreamArgs, FindUniqueArgs, GroupByArgs, HavingClause, JsonFilter, NestedCreateOp, NestedUpdateOp, OmitResult, OrderByClause, OrderDirection, QueryResult, RelationDescriptor, RelationFilter, SelectResult, TextSearchFilter, TypedWithClause, UpdateArgs, UpdateInput, UpdateManyArgs, UpdateOperatorInput, UpsertArgs, VectorDistanceFilter, VectorFilter, VectorMetric, VectorOrderBy, VectorOrderByDistance, WhereClause, WhereOperator, WhereValue, WithClause, WithOptions, WithResult, } from './types.js';
8
+ export type { AggregateArgs, AggregateResult, ArrayFilter, ConnectOrCreateOp, CountArgs, CreateArgs, CreateDataInput, CreateManyArgs, DeleteArgs, DeleteManyArgs, FieldResult, FindManyArgs, FindManyStreamArgs, FindUniqueArgs, GroupByArgs, HavingClause, JsonFilter, NestedCreateOp, NestedUpdateOp, NestedUpdateOpItem, NestedUpsertOpItem, OmitResult, OrderByClause, OrderDirection, QueryResult, RelationDescriptor, RelationFilter, SelectResult, TextSearchFilter, TypedWithClause, UpdateArgs, UpdateDataInput, UpdateInput, UpdateManyArgs, UpdateOperatorInput, UpsertArgs, VectorDistanceFilter, VectorFilter, VectorMetric, VectorOrderBy, VectorOrderByDistance, WhereClause, WhereOperator, WhereValue, WithClause, WithOptions, WithResult, } from './types.js';
9
9
  export type { BuiltStatement, BulkInsertStatementInput, ColumnDefinitionInput, ColumnTypeInput, CreateIndexStatementInput, CreateTableStatementInput, Dialect, InsertStatementInput, UpsertStatementInput, } from '../dialect.js';
10
10
  export { postgresDialect } from '../dialect.js';
11
11
  export type { SqlCacheEntry } from './utils.js';
12
12
  export { buildCorrelation, escapeLike, escSingleQuote, fnv1a64Hex, LRUCache, OPERATOR_KEYS, quoteIdent, sqlToPreparedName, } from './utils.js';
13
- export type { DeferredQuery, MiddlewareFn, QueryEvent, QueryEventListener, QueryInterfaceOptions } from './builder.js';
13
+ export type { DeferredQuery, MiddlewareFn, QueryEvent, QueryEventListener, QueryInterfaceOptions, ReselectExecutor, } from './builder.js';
14
14
  export { QueryInterface } from './builder.js';
15
15
  //# sourceMappingURL=index.d.ts.map
@@ -6,6 +6,13 @@
6
6
  export type OrderDirection = 'asc' | 'desc';
7
7
  /** Operator object for advanced where filtering */
8
8
  export interface WhereOperator<V = unknown> {
9
+ /**
10
+ * Explicit equality: `{ equals: value }` → `column = $n`.
11
+ * `{ equals: null }` → `column IS NULL`.
12
+ * On json/jsonb columns `equals` routes to the JSONB containment filter
13
+ * ({@link JsonFilter}) instead.
14
+ */
15
+ equals?: V | null;
9
16
  gt?: V;
10
17
  gte?: V;
11
18
  lt?: V;
@@ -225,8 +232,12 @@ export interface FindManyStreamArgs<T, R extends object = {}, W extends TypedWit
225
232
  */
226
233
  batchSize?: number;
227
234
  }
228
- export interface CreateArgs<T> {
229
- data: Partial<T>;
235
+ export interface CreateArgs<T, R extends object = {}> {
236
+ /**
237
+ * Row data. On typed clients, relation names additionally accept nested
238
+ * write ops ({@link NestedCreateOp}): `create` / `connect` / `connectOrCreate`.
239
+ */
240
+ data: CreateDataInput<T, R>;
230
241
  /** Query timeout in milliseconds. Rejects with an error if exceeded. */
231
242
  timeout?: number;
232
243
  }
@@ -267,9 +278,14 @@ export type UpdateOperatorInput<V> = {
267
278
  export type UpdateInput<T> = {
268
279
  [K in keyof T]?: T[K] | UpdateOperatorInput<T[K]>;
269
280
  };
270
- export interface UpdateArgs<T> {
281
+ export interface UpdateArgs<T, R extends object = {}> {
271
282
  where: WhereClause<T>;
272
- data: UpdateInput<T>;
283
+ /**
284
+ * Update data. On typed clients, relation names additionally accept nested
285
+ * write ops ({@link NestedUpdateOp}): `create` / `connect` / `connectOrCreate`
286
+ * / `disconnect` / `set` / `delete` / `update` / `upsert`.
287
+ */
288
+ data: UpdateDataInput<T, R>;
273
289
  /** Query timeout in milliseconds. Rejects with an error if exceeded. */
274
290
  timeout?: number;
275
291
  /**
@@ -331,23 +347,57 @@ export interface UpsertArgs<T> {
331
347
  /** Query timeout in milliseconds. Rejects with an error if exceeded. */
332
348
  timeout?: number;
333
349
  }
334
- export interface ConnectOrCreateOp<T> {
350
+ /** `connectOrCreate` op: connect to the row matching `where`, or create it. */
351
+ export interface ConnectOrCreateOp<T, TR extends object = {}> {
335
352
  where: Partial<T>;
336
- create: Partial<T>;
353
+ create: CreateDataInput<T, TR>;
337
354
  }
338
- export interface NestedCreateOp<T> {
339
- create?: Partial<T> | Partial<T>[];
355
+ /** Nested write ops valid inside `create()` data for a relation field. */
356
+ export interface NestedCreateOp<T, TR extends object = {}> {
357
+ create?: CreateDataInput<T, TR> | CreateDataInput<T, TR>[];
340
358
  connect?: Partial<T> | Partial<T>[];
341
- connectOrCreate?: ConnectOrCreateOp<T> | ConnectOrCreateOp<T>[];
359
+ connectOrCreate?: ConnectOrCreateOp<T, TR> | ConnectOrCreateOp<T, TR>[];
360
+ }
361
+ /** A nested `update` op item: update the related row(s) matching `where`. `where` is optional for belongsTo relations (derived from the parent's FK). */
362
+ export interface NestedUpdateOpItem<T, TR extends object = {}> {
363
+ where?: Partial<T>;
364
+ data: UpdateDataInput<T, TR>;
342
365
  }
343
- export interface NestedUpdateOp<T> {
344
- create?: Partial<T> | Partial<T>[];
366
+ /** A nested `upsert` op item: update the row matching `where` or create it. */
367
+ export interface NestedUpsertOpItem<T, TR extends object = {}> {
368
+ where: Partial<T>;
369
+ create: CreateDataInput<T, TR>;
370
+ update: UpdateDataInput<T, TR>;
371
+ }
372
+ /** Nested write ops valid inside `update()` data for a relation field. */
373
+ export interface NestedUpdateOp<T, TR extends object = {}> {
374
+ create?: CreateDataInput<T, TR> | CreateDataInput<T, TR>[];
345
375
  connect?: Partial<T> | Partial<T>[];
346
- connectOrCreate?: ConnectOrCreateOp<T> | ConnectOrCreateOp<T>[];
376
+ connectOrCreate?: ConnectOrCreateOp<T, TR> | ConnectOrCreateOp<T, TR>[];
347
377
  disconnect?: Partial<T> | Partial<T>[];
348
378
  set?: Partial<T>[];
349
379
  delete?: Partial<T> | Partial<T>[];
380
+ update?: NestedUpdateOpItem<T, TR> | NestedUpdateOpItem<T, TR>[];
381
+ upsert?: NestedUpsertOpItem<T, TR> | NestedUpsertOpItem<T, TR>[];
350
382
  }
383
+ /**
384
+ * `create()` data input. When the relations map `R` is known (typed clients),
385
+ * each relation name additionally accepts a {@link NestedCreateOp} for the
386
+ * relation's target entity — recursively, via the target's own relations map.
387
+ * When `R` is `{}` (untyped escape hatch) this collapses to plain `Partial<T>`.
388
+ */
389
+ export type CreateDataInput<T, R extends object = {}> = [keyof R] extends [never] ? Partial<T> : Partial<T> & {
390
+ [K in keyof R]?: NestedCreateOp<RelationTarget<R[K]> & object, RelationRelations<R[K]> & object>;
391
+ };
392
+ /**
393
+ * `update()` data input. Like {@link CreateDataInput} but relation fields
394
+ * accept the full {@link NestedUpdateOp} surface (disconnect / set / delete /
395
+ * update / upsert in addition to the create-context ops), and scalar fields
396
+ * accept atomic {@link UpdateOperatorInput} objects.
397
+ */
398
+ export type UpdateDataInput<T, R extends object = {}> = [keyof R] extends [never] ? UpdateInput<T> : UpdateInput<T> & {
399
+ [K in keyof R]?: NestedUpdateOp<RelationTarget<R[K]> & object, RelationRelations<R[K]> & object>;
400
+ };
351
401
  export interface CountArgs<T> {
352
402
  where?: WhereClause<T>;
353
403
  /** Query timeout in milliseconds. Rejects with an error if exceeded. */
@@ -99,6 +99,7 @@ export function sqlToPreparedName(sql) {
99
99
  }
100
100
  /** Known operator keys — used to detect operator objects vs plain values */
101
101
  export const OPERATOR_KEYS = new Set([
102
+ 'equals',
102
103
  'gt',
103
104
  'gte',
104
105
  'lt',
@@ -0,0 +1,144 @@
1
+ /**
2
+ * turbine-orm/sqlite — zero-dependency SQLite engine
3
+ *
4
+ * Binds Turbine to SQLite via Node's built-in `node:sqlite` driver
5
+ * (`DatabaseSync`), so SQLite is a **zero new dependency** engine: the root
6
+ * package's runtime dependency stays exactly `pg`. This is the in-process
7
+ * test / edge / "try it in 10 seconds" engine — `:memory:` databases run
8
+ * entirely in-process with no service container.
9
+ *
10
+ * ## Driver
11
+ *
12
+ * - **Primary:** `node:sqlite` `DatabaseSync` (Node ≥ 22.5, experimental). Emits
13
+ * an `ExperimentalWarning` — harmless. No native build, no extra dependency.
14
+ * - **Fallback:** `better-sqlite3` for Node < 22.5. Not bundled and not required;
15
+ * wrap a `better-sqlite3` handle in the same `PgCompatPool` shape if needed.
16
+ *
17
+ * ## Capabilities & limits (vs PostgreSQL)
18
+ *
19
+ * - `RETURNING` + `ON CONFLICT … DO UPDATE` (SQLite ≥ 3.35) → create / upsert /
20
+ * update / delete return real rows in a single statement (`resultStrategy =
21
+ * 'returning'`, same as Postgres).
22
+ * - **Single-writer:** one connection / one write transaction at a time;
23
+ * concurrent writers get `SQLITE_BUSY` (treated as retryable). `journal_mode =
24
+ * WAL` is enabled for file databases to allow concurrent readers.
25
+ * - **Unsupported (throw `UnsupportedFeatureError`):** pgvector distance ops,
26
+ * LISTEN/NOTIFY (`$listen` / `$notify`), RLS `sessionContext`. Advisory-lock
27
+ * migration locking is unavailable — SQLite is single-writer, so migrations
28
+ * serialize naturally.
29
+ * - **Type affinity caveats:** SQLite has no native `BOOLEAN` (0/1 integers) or
30
+ * `DATE` (TEXT/INTEGER). Booleans bind as 1/0; `Date` values bind as ISO-8601
31
+ * text; columns declared `TIMESTAMP`/`DATETIME`/`DATE` are coerced back to
32
+ * `Date`. Integers wider than `Number.MAX_SAFE_INTEGER` come back as strings
33
+ * (the same safe-int policy Turbine uses for Postgres `int8`).
34
+ * - **Case-insensitive matching** uses `COLLATE NOCASE`, which is **ASCII-only**
35
+ * (no Unicode case folding).
36
+ *
37
+ * ## Example — `:memory:` database
38
+ *
39
+ * ```ts
40
+ * import { turbineSqlite } from 'turbine-orm/sqlite';
41
+ * import { SCHEMA } from './generated/turbine/metadata.js';
42
+ *
43
+ * const db = turbineSqlite(':memory:', SCHEMA);
44
+ * const users = await db.users.findMany({ with: { posts: true }, limit: 10 });
45
+ * await db.disconnect();
46
+ * ```
47
+ */
48
+ import type { DatabaseSync } from 'node:sqlite';
49
+ import { type PgCompatPool, type PgCompatPoolClient, TurbineClient, type TurbineConfig } from './client.js';
50
+ import { type Dialect, type IntrospectOptions } from './dialect.js';
51
+ import { type SchemaMetadata, type TableMetadata } from './schema.js';
52
+ /** pg-style query argument: a SQL string or a `{ text, values }` config object. */
53
+ type QueryArg = string | {
54
+ name?: string;
55
+ text: string;
56
+ values?: unknown[];
57
+ };
58
+ /**
59
+ * A `PgCompatPool` backed by a single `node:sqlite` `DatabaseSync` connection.
60
+ * SQLite is single-connection by nature (a `:memory:` database is per-handle),
61
+ * so `connect()` hands back a client over the **same** handle — transactions
62
+ * (`BEGIN`/`COMMIT`/`ROLLBACK`, `SAVEPOINT` nesting) just run on it. Queries are
63
+ * serialized; this is the documented single-writer model.
64
+ */
65
+ export declare class SqlitePool implements PgCompatPool {
66
+ /** The underlying `node:sqlite` handle — exposed as an escape hatch (seed/DDL). */
67
+ readonly db: DatabaseSync;
68
+ private closed;
69
+ constructor(db: DatabaseSync);
70
+ query(text: QueryArg, values?: unknown[]): Promise<any>;
71
+ connect(): Promise<PgCompatPoolClient>;
72
+ end(): Promise<void>;
73
+ }
74
+ /**
75
+ * Map a SQLite declared column type (type affinity) to a TypeScript type.
76
+ * SQLite is dynamically typed; we read the declared `PRAGMA table_info` type.
77
+ */
78
+ export declare function sqliteTypeToTs(declaredType: string, nullable: boolean): string;
79
+ /**
80
+ * SQLite implementation of the {@link Dialect} contract. Standardizes on `"…"`
81
+ * identifier quoting and positional `?` placeholders, uses `json_object` /
82
+ * `json_group_array` for the single-query nested-relation engine (with the
83
+ * critical `json(...)` subresult wrap so nested objects are real JSON, not
84
+ * SQLite's strings-of-strings double-encoding), keeps `RETURNING` + `ON CONFLICT`
85
+ * (SQLite ≥ 3.35), and disables the Postgres-only capabilities (vector,
86
+ * LISTEN/NOTIFY, RLS, advisory locks).
87
+ */
88
+ export declare const sqliteDialect: Dialect;
89
+ /**
90
+ * Read a live SQLite database (an open `DatabaseSync` handle) into the same
91
+ * {@link SchemaMetadata} shape the Postgres catalog introspector produces.
92
+ * Exposed directly so callers (and tests) can introspect an in-process
93
+ * `:memory:` database without round-tripping through a file path.
94
+ */
95
+ export declare function introspectSqliteDatabase(db: DatabaseSync, options?: {
96
+ include?: string[];
97
+ exclude?: string[];
98
+ }): {
99
+ tables: Record<string, TableMetadata>;
100
+ enums: {};
101
+ };
102
+ /**
103
+ * Open the SQLite database named by `options.connectionString` (a file path or
104
+ * `':memory:'`), introspect it, and close it. Wraps
105
+ * {@link introspectSqliteDatabase} for the {@link DialectIntrospector} seam used
106
+ * by `introspect()` / `npx turbine generate`.
107
+ *
108
+ * Note: introspecting `':memory:'` opens a *fresh, empty* database (memory DBs
109
+ * are per-handle), so codegen should target a real file.
110
+ */
111
+ export declare function introspectSqlite(options: IntrospectOptions): Promise<SchemaMetadata>;
112
+ /** Options for {@link turbineSqlite}. Mirrors the relevant {@link TurbineConfig} fields. */
113
+ export interface TurbineSqliteOptions extends Pick<TurbineConfig, 'logging' | 'defaultLimit' | 'warnOnUnlimited'> {
114
+ /**
115
+ * Enable WAL journal mode for file databases (better read concurrency).
116
+ * Ignored for `':memory:'`. Default: `true`.
117
+ */
118
+ wal?: boolean;
119
+ /** `PRAGMA busy_timeout` in ms — how long a writer waits on `SQLITE_BUSY`. Default: 5000. */
120
+ busyTimeoutMs?: number;
121
+ /** Enable `PRAGMA foreign_keys` enforcement. Default: `true`. */
122
+ foreignKeys?: boolean;
123
+ }
124
+ /**
125
+ * Create a {@link TurbineClient} bound to SQLite via `node:sqlite`.
126
+ *
127
+ * Pass a file path, `':memory:'`, or an already-open `DatabaseSync` handle (so
128
+ * you can seed / introspect it first and reuse the same connection). The
129
+ * returned client uses {@link sqliteDialect} and disables prepared-statement
130
+ * names (SQLite caches plans internally).
131
+ *
132
+ * @param target A SQLite file path, `':memory:'`, or an open `DatabaseSync`.
133
+ * @param schema Introspected or hand-written {@link SchemaMetadata}.
134
+ * @param options Optional pragmas + logging / defaultLimit / warnOnUnlimited.
135
+ *
136
+ * @example
137
+ * ```ts
138
+ * import { turbineSqlite } from 'turbine-orm/sqlite';
139
+ * const db = turbineSqlite(':memory:', SCHEMA);
140
+ * ```
141
+ */
142
+ export declare function turbineSqlite(target: string | DatabaseSync, schema: SchemaMetadata, options?: TurbineSqliteOptions): TurbineClient;
143
+ export {};
144
+ //# sourceMappingURL=sqlite.d.ts.map