turbine-orm 0.50.0 → 0.51.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 +66 -66
- package/dist/adapters/cockroachdb.d.ts +5 -5
- package/dist/adapters/cockroachdb.js +10 -10
- package/dist/adapters/index.d.ts +5 -5
- package/dist/adapters/index.js +7 -7
- package/dist/adapters/yugabytedb.d.ts +7 -7
- package/dist/adapters/yugabytedb.js +10 -10
- package/dist/cjs/adapters/cockroachdb.d.ts +5 -5
- package/dist/cjs/adapters/cockroachdb.js +10 -10
- package/dist/cjs/adapters/index.d.ts +5 -5
- package/dist/cjs/adapters/index.js +7 -7
- package/dist/cjs/adapters/yugabytedb.d.ts +7 -7
- package/dist/cjs/adapters/yugabytedb.js +10 -10
- package/dist/cjs/cli/config.d.ts +13 -2
- package/dist/cjs/cli/config.js +3 -2
- package/dist/cjs/cli/destructive.d.ts +1 -1
- package/dist/cjs/cli/destructive.js +1 -1
- package/dist/cjs/cli/index.d.ts +10 -10
- package/dist/cjs/cli/index.js +49 -45
- package/dist/cjs/cli/loader.d.ts +7 -7
- package/dist/cjs/cli/loader.js +9 -9
- package/dist/cjs/cli/mcp.js +4 -4
- package/dist/cjs/cli/migrate.d.ts +5 -5
- package/dist/cjs/cli/migrate.js +11 -11
- package/dist/cjs/cli/studio-ui.generated.js +1 -1
- package/dist/cjs/cli/ui.d.ts +2 -2
- package/dist/cjs/cli/ui.js +2 -2
- package/dist/cjs/client.d.ts +49 -38
- package/dist/cjs/client.js +57 -56
- package/dist/cjs/dialect.d.ts +62 -18
- package/dist/cjs/dialect.js +40 -2
- package/dist/cjs/errors.d.ts +5 -5
- package/dist/cjs/errors.js +11 -11
- package/dist/cjs/generate.d.ts +6 -6
- package/dist/cjs/generate.js +31 -29
- package/dist/cjs/index-advisor.d.ts +5 -5
- package/dist/cjs/index-advisor.js +0 -0
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.js +7 -7
- package/dist/cjs/introspect.d.ts +35 -9
- package/dist/cjs/introspect.js +83 -32
- package/dist/cjs/mssql.d.ts +11 -11
- package/dist/cjs/mssql.js +64 -29
- package/dist/cjs/mysql.d.ts +8 -8
- package/dist/cjs/mysql.js +61 -23
- package/dist/cjs/nested-write.d.ts +21 -2
- package/dist/cjs/nested-write.js +51 -14
- package/dist/cjs/optional-peer-import.cjs +7 -7
- package/dist/cjs/optional-peer-import.d.cts +7 -7
- package/dist/cjs/pipeline-submittable.d.ts +2 -2
- package/dist/cjs/pipeline-submittable.js +6 -6
- package/dist/cjs/pipeline.d.ts +1 -1
- package/dist/cjs/pipeline.js +4 -4
- package/dist/cjs/powdb-introspect.d.ts +1 -1
- package/dist/cjs/powdb-introspect.js +1 -1
- package/dist/cjs/powdb.d.ts +28 -28
- package/dist/cjs/powdb.js +66 -66
- package/dist/cjs/powql.d.ts +27 -27
- package/dist/cjs/powql.js +73 -52
- package/dist/cjs/query/aggregates.d.ts +1 -1
- package/dist/cjs/query/aggregates.js +5 -5
- package/dist/cjs/query/batched-loader.d.ts +11 -11
- package/dist/cjs/query/batched-loader.js +24 -24
- package/dist/cjs/query/builder.d.ts +39 -21
- package/dist/cjs/query/builder.js +99 -57
- package/dist/cjs/query/compound-unique.d.ts +1 -1
- package/dist/cjs/query/compound-unique.js +0 -0
- package/dist/cjs/query/deferred.d.ts +12 -6
- package/dist/cjs/query/deferred.js +1 -1
- package/dist/cjs/query/filters.d.ts +31 -11
- package/dist/cjs/query/filters.js +67 -14
- package/dist/cjs/query/index.d.ts +1 -1
- package/dist/cjs/query/index.js +1 -1
- package/dist/cjs/query/relations.d.ts +9 -9
- package/dist/cjs/query/relations.js +164 -57
- package/dist/cjs/query/types.d.ts +86 -35
- package/dist/cjs/query/types.js +1 -1
- package/dist/cjs/query/utils.d.ts +27 -10
- package/dist/cjs/query/utils.js +86 -14
- package/dist/cjs/query/where.d.ts +47 -28
- package/dist/cjs/query/where.js +130 -31
- package/dist/cjs/query/writes.d.ts +24 -5
- package/dist/cjs/query/writes.js +102 -13
- package/dist/cjs/realtime.d.ts +7 -7
- package/dist/cjs/realtime.js +9 -9
- package/dist/cjs/schema-builder.d.ts +18 -7
- package/dist/cjs/schema-builder.js +17 -10
- package/dist/cjs/schema-metadata.d.ts +3 -3
- package/dist/cjs/schema-metadata.js +9 -9
- package/dist/cjs/schema-sql.d.ts +9 -9
- package/dist/cjs/schema-sql.js +20 -20
- package/dist/cjs/schema.d.ts +19 -9
- package/dist/cjs/schema.js +6 -6
- package/dist/cjs/serverless.d.ts +15 -15
- package/dist/cjs/serverless.js +16 -16
- package/dist/cjs/sqlite.d.ts +8 -8
- package/dist/cjs/sqlite.js +53 -22
- package/dist/cjs/typed-sql.d.ts +4 -4
- package/dist/cjs/typed-sql.js +5 -5
- package/dist/cli/config.d.ts +13 -2
- package/dist/cli/config.js +3 -2
- package/dist/cli/destructive.d.ts +1 -1
- package/dist/cli/destructive.js +1 -1
- package/dist/cli/index.d.ts +10 -10
- package/dist/cli/index.js +49 -45
- package/dist/cli/loader.d.ts +7 -7
- package/dist/cli/loader.js +9 -9
- package/dist/cli/mcp.js +4 -4
- package/dist/cli/migrate.d.ts +5 -5
- package/dist/cli/migrate.js +11 -11
- package/dist/cli/studio-ui.generated.js +1 -1
- package/dist/cli/ui.d.ts +2 -2
- package/dist/cli/ui.js +2 -2
- package/dist/client.d.ts +49 -38
- package/dist/client.js +57 -56
- package/dist/dialect.d.ts +62 -18
- package/dist/dialect.js +40 -2
- package/dist/errors.d.ts +5 -5
- package/dist/errors.js +11 -11
- package/dist/generate.d.ts +6 -6
- package/dist/generate.js +31 -29
- package/dist/index-advisor.d.ts +5 -5
- package/dist/index-advisor.js +0 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +7 -7
- package/dist/introspect.d.ts +35 -9
- package/dist/introspect.js +82 -32
- package/dist/mssql.d.ts +11 -11
- package/dist/mssql.js +64 -29
- package/dist/mysql.d.ts +8 -8
- package/dist/mysql.js +61 -23
- package/dist/nested-write.d.ts +21 -2
- package/dist/nested-write.js +51 -14
- package/dist/optional-peer-import.cjs +7 -7
- package/dist/optional-peer-import.d.cts +7 -7
- package/dist/pipeline-submittable.d.ts +2 -2
- package/dist/pipeline-submittable.js +6 -6
- package/dist/pipeline.d.ts +1 -1
- package/dist/pipeline.js +4 -4
- package/dist/powdb-introspect.d.ts +1 -1
- package/dist/powdb-introspect.js +1 -1
- package/dist/powdb.d.ts +28 -28
- package/dist/powdb.js +66 -66
- package/dist/powql.d.ts +27 -27
- package/dist/powql.js +73 -52
- package/dist/query/aggregates.d.ts +1 -1
- package/dist/query/aggregates.js +5 -5
- package/dist/query/batched-loader.d.ts +11 -11
- package/dist/query/batched-loader.js +24 -24
- package/dist/query/builder.d.ts +39 -21
- package/dist/query/builder.js +100 -58
- package/dist/query/compound-unique.d.ts +1 -1
- package/dist/query/compound-unique.js +0 -0
- package/dist/query/deferred.d.ts +12 -6
- package/dist/query/deferred.js +1 -1
- package/dist/query/filters.d.ts +31 -11
- package/dist/query/filters.js +66 -13
- package/dist/query/index.d.ts +1 -1
- package/dist/query/index.js +1 -1
- package/dist/query/relations.d.ts +9 -9
- package/dist/query/relations.js +165 -58
- package/dist/query/types.d.ts +86 -35
- package/dist/query/types.js +1 -1
- package/dist/query/utils.d.ts +27 -10
- package/dist/query/utils.js +84 -14
- package/dist/query/where.d.ts +47 -28
- package/dist/query/where.js +129 -32
- package/dist/query/writes.d.ts +24 -5
- package/dist/query/writes.js +101 -13
- package/dist/realtime.d.ts +7 -7
- package/dist/realtime.js +9 -9
- package/dist/schema-builder.d.ts +18 -7
- package/dist/schema-builder.js +17 -10
- package/dist/schema-metadata.d.ts +3 -3
- package/dist/schema-metadata.js +9 -9
- package/dist/schema-sql.d.ts +9 -9
- package/dist/schema-sql.js +20 -20
- package/dist/schema.d.ts +19 -9
- package/dist/schema.js +6 -6
- package/dist/serverless.d.ts +15 -15
- package/dist/serverless.js +16 -16
- package/dist/sqlite.d.ts +8 -8
- package/dist/sqlite.js +53 -22
- package/dist/typed-sql.d.ts +4 -4
- package/dist/typed-sql.js +5 -5
- package/package.json +2 -2
package/dist/cjs/sqlite.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* turbine-orm/sqlite
|
|
3
|
+
* turbine-orm/sqlite, zero-dependency SQLite engine
|
|
4
4
|
*
|
|
5
5
|
* Binds Turbine to SQLite via Node's built-in `node:sqlite` driver
|
|
6
6
|
* (`DatabaseSync`), so SQLite is a **zero new dependency** engine: the root
|
|
7
7
|
* package's runtime dependency stays exactly `pg`. This is the in-process
|
|
8
|
-
* test / edge / "try it in 10 seconds" engine
|
|
8
|
+
* test / edge / "try it in 10 seconds" engine, `:memory:` databases run
|
|
9
9
|
* entirely in-process with no service container.
|
|
10
10
|
*
|
|
11
11
|
* ## Driver
|
|
12
12
|
*
|
|
13
13
|
* - **Primary:** `node:sqlite` `DatabaseSync` (Node ≥ 22.5, experimental). Emits
|
|
14
|
-
* an `ExperimentalWarning
|
|
14
|
+
* an `ExperimentalWarning`, harmless. No native build, no extra dependency.
|
|
15
15
|
* - **Fallback:** `better-sqlite3` for Node < 22.5. Not bundled and not required;
|
|
16
16
|
* wrap a `better-sqlite3` handle in the same `PgCompatPool` shape if needed.
|
|
17
17
|
*
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
* WAL` is enabled for file databases to allow concurrent readers.
|
|
26
26
|
* - **Unsupported (throw `UnsupportedFeatureError`):** pgvector distance ops,
|
|
27
27
|
* LISTEN/NOTIFY (`$listen` / `$notify`), RLS `sessionContext`. Advisory-lock
|
|
28
|
-
* migration locking is unavailable
|
|
28
|
+
* migration locking is unavailable, SQLite is single-writer, so migrations
|
|
29
29
|
* serialize naturally.
|
|
30
30
|
* - **Type affinity caveats:** SQLite has no native `BOOLEAN` (0/1 integers) or
|
|
31
31
|
* `DATE` (TEXT/INTEGER). Booleans bind as 1/0; `Date` values bind as ISO-8601
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
* - **Case-insensitive matching** uses `COLLATE NOCASE`, which is **ASCII-only**
|
|
36
36
|
* (no Unicode case folding).
|
|
37
37
|
*
|
|
38
|
-
* ## Example
|
|
38
|
+
* ## Example, `:memory:` database
|
|
39
39
|
*
|
|
40
40
|
* ```ts
|
|
41
41
|
* import { turbineSqlite } from 'turbine-orm/sqlite';
|
|
@@ -63,8 +63,8 @@ let cachedDatabaseSync;
|
|
|
63
63
|
* Lazily load `node:sqlite`'s `DatabaseSync` constructor.
|
|
64
64
|
*
|
|
65
65
|
* `node:sqlite` is a built-in only on Node >= 22.5, so importing it at module
|
|
66
|
-
* top-level would make `import 'turbine-orm/sqlite'
|
|
67
|
-
* merely re-exports `sqliteDialect` (e.g. the dialect test suite)
|
|
66
|
+
* top-level would make `import 'turbine-orm/sqlite'`, and any module that
|
|
67
|
+
* merely re-exports `sqliteDialect` (e.g. the dialect test suite), throw
|
|
68
68
|
* `ERR_UNKNOWN_BUILTIN_MODULE` on Node 20. Deferring the require to the moment a
|
|
69
69
|
* connection is actually opened keeps the dialect (pure SQL generation) usable
|
|
70
70
|
* everywhere and scopes the Node-version requirement to `turbineSqlite()`.
|
|
@@ -86,7 +86,7 @@ function loadDatabaseSync() {
|
|
|
86
86
|
`Upgrade Node to >= 22.5, or pass an already-open better-sqlite3-compatible handle. (${err.message})`);
|
|
87
87
|
}
|
|
88
88
|
if (typeof ctor !== 'function') {
|
|
89
|
-
throw new errors_js_1.ConnectionError("[turbine] 'node:sqlite' loaded but did not export a DatabaseSync constructor
|
|
89
|
+
throw new errors_js_1.ConnectionError("[turbine] 'node:sqlite' loaded but did not export a DatabaseSync constructor, this Node build may lack SQLite support.");
|
|
90
90
|
}
|
|
91
91
|
cachedDatabaseSync = ctor;
|
|
92
92
|
return cachedDatabaseSync;
|
|
@@ -119,7 +119,7 @@ function toSqliteParam(value) {
|
|
|
119
119
|
/**
|
|
120
120
|
* Normalize a single column value read from SQLite. With `setReadBigInts(true)`
|
|
121
121
|
* every integer column comes back as a `bigint`; apply the same safe-integer
|
|
122
|
-
* policy Turbine uses for Postgres `int8
|
|
122
|
+
* policy Turbine uses for Postgres `int8`, number when it fits in a JS safe
|
|
123
123
|
* integer, otherwise the decimal string to avoid precision loss. Never mutates
|
|
124
124
|
* any global parser state (the policy lives entirely in this shim).
|
|
125
125
|
*/
|
|
@@ -160,7 +160,7 @@ function statementReturnsRows(sql) {
|
|
|
160
160
|
* recognizable SQLite error.
|
|
161
161
|
*
|
|
162
162
|
* `wrapPgError` is invoked downstream (in the query executor and the
|
|
163
|
-
* transaction proxy), so we only annotate here
|
|
163
|
+
* transaction proxy), so we only annotate here, we never throw a `new`
|
|
164
164
|
* Turbine error from the driver itself.
|
|
165
165
|
*/
|
|
166
166
|
function augmentSqliteError(err) {
|
|
@@ -228,7 +228,7 @@ function normalizeQueryArgs(arg, values) {
|
|
|
228
228
|
/**
|
|
229
229
|
* Bind the positional `params[]` (in 1-indexed generation order) to the named
|
|
230
230
|
* `:p1`, `:p2`, … placeholders the dialect emits. Mapping by NAME makes binding
|
|
231
|
-
* independent of where each placeholder lands in the SQL text
|
|
231
|
+
* independent of where each placeholder lands in the SQL text, the same
|
|
232
232
|
* guarantee Postgres' numbered `$N` gives. Returns `undefined` when there are no
|
|
233
233
|
* params so parameter-less statements (BEGIN/COMMIT/DDL) bind nothing.
|
|
234
234
|
*/
|
|
@@ -268,12 +268,12 @@ function runStatement(db, sql, values) {
|
|
|
268
268
|
/**
|
|
269
269
|
* A `PgCompatPool` backed by a single `node:sqlite` `DatabaseSync` connection.
|
|
270
270
|
* SQLite is single-connection by nature (a `:memory:` database is per-handle),
|
|
271
|
-
* so `connect()` hands back a client over the **same** handle
|
|
271
|
+
* so `connect()` hands back a client over the **same** handle, transactions
|
|
272
272
|
* (`BEGIN`/`COMMIT`/`ROLLBACK`, `SAVEPOINT` nesting) just run on it. Queries are
|
|
273
273
|
* serialized; this is the documented single-writer model.
|
|
274
274
|
*/
|
|
275
275
|
class SqlitePool {
|
|
276
|
-
/** The underlying `node:sqlite` handle
|
|
276
|
+
/** The underlying `node:sqlite` handle, exposed as an escape hatch (seed/DDL). */
|
|
277
277
|
db;
|
|
278
278
|
closed = false;
|
|
279
279
|
constructor(db) {
|
|
@@ -293,7 +293,7 @@ class SqlitePool {
|
|
|
293
293
|
return runStatement(db, sql, params);
|
|
294
294
|
},
|
|
295
295
|
release: () => {
|
|
296
|
-
// Single shared connection
|
|
296
|
+
// Single shared connection, nothing to return to a pool.
|
|
297
297
|
},
|
|
298
298
|
};
|
|
299
299
|
}
|
|
@@ -357,7 +357,7 @@ function sqliteColumnAffinity(type) {
|
|
|
357
357
|
return 'TEXT';
|
|
358
358
|
}
|
|
359
359
|
// ---------------------------------------------------------------------------
|
|
360
|
-
// sqliteDialect
|
|
360
|
+
// sqliteDialect, the full Dialect contract for SQLite
|
|
361
361
|
// ---------------------------------------------------------------------------
|
|
362
362
|
/**
|
|
363
363
|
* SQLite implementation of the {@link Dialect} contract. Standardizes on `"…"`
|
|
@@ -394,7 +394,7 @@ exports.sqliteDialect = {
|
|
|
394
394
|
jsonPathSupport: 'function',
|
|
395
395
|
emptyJsonArrayLiteral: "json('[]')",
|
|
396
396
|
nullJsonLiteral: 'NULL',
|
|
397
|
-
// Named placeholders (`:p1`, `:p2`, …)
|
|
397
|
+
// Named placeholders (`:p1`, `:p2`, …), NOT positional `?`. Turbine pushes
|
|
398
398
|
// params in 1-indexed generation order but may EMIT them in a different SQL
|
|
399
399
|
// text position (e.g. a `with`-relation LIMIT lands in the SELECT list, ahead
|
|
400
400
|
// of the outer WHERE). Postgres reconciles this via numbered `$N`; positional
|
|
@@ -426,6 +426,37 @@ exports.sqliteDialect = {
|
|
|
426
426
|
wrapJsonSubresult(subquery, fallback) {
|
|
427
427
|
return `COALESCE(json((${subquery})), ${fallback})`;
|
|
428
428
|
},
|
|
429
|
+
jsonWireRule(columnType) {
|
|
430
|
+
// SQLite's storage classes, as introspection records them.
|
|
431
|
+
const t = columnType.toUpperCase();
|
|
432
|
+
// INTEGER is 64-bit, and `json_object` renders it as a JSON number, which
|
|
433
|
+
// is an IEEE double: 9007199254740993 came back through a `with` join as
|
|
434
|
+
// …992 while a top-level read and the batched loader both returned the
|
|
435
|
+
// exact decimal string. Carry the text and re-apply the SAME safe-integer
|
|
436
|
+
// policy `normalizeValue` applies to the driver's bigint, so all three
|
|
437
|
+
// paths agree for both small and large values.
|
|
438
|
+
if (t.includes('INT')) {
|
|
439
|
+
return {
|
|
440
|
+
sql: (ref) => `CAST(${ref} AS TEXT)`,
|
|
441
|
+
decode: (value) => {
|
|
442
|
+
if (typeof value !== 'string' || !/^-?\d+$/.test(value))
|
|
443
|
+
return value;
|
|
444
|
+
const asNumber = Number(value);
|
|
445
|
+
return Number.isSafeInteger(asNumber) ? asNumber : value;
|
|
446
|
+
},
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
// A BLOB cannot go into JSON at all: SQLite raises "JSON cannot hold BLOB
|
|
450
|
+
// values" and the whole query fails with a raw SQL logic error, where the
|
|
451
|
+
// batched loader returns the row fine. Carry hex and rebuild the bytes.
|
|
452
|
+
if (t.includes('BLOB')) {
|
|
453
|
+
return {
|
|
454
|
+
sql: (ref) => `hex(${ref})`,
|
|
455
|
+
decode: (value) => (typeof value === 'string' ? Uint8Array.from(Buffer.from(value, 'hex')) : value),
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
return undefined;
|
|
459
|
+
},
|
|
429
460
|
castAggregate(expr, target) {
|
|
430
461
|
return `CAST(${expr} AS ${target === 'int' ? 'INTEGER' : 'REAL'})`;
|
|
431
462
|
},
|
|
@@ -446,7 +477,7 @@ exports.sqliteDialect = {
|
|
|
446
477
|
`VALUES (${input.valuePlaceholders.join(', ')})${this.buildReturningClause(input.returning)}`);
|
|
447
478
|
},
|
|
448
479
|
buildBulkInsertStatement(input) {
|
|
449
|
-
// No UNNEST in SQLite
|
|
480
|
+
// No UNNEST in SQLite, emit multi-row VALUES with flattened, named
|
|
450
481
|
// placeholders (`:p1`, `:p2`, …) matching the flat param order.
|
|
451
482
|
let n = 0;
|
|
452
483
|
const placeholders = input.rowValues
|
|
@@ -469,12 +500,12 @@ exports.sqliteDialect = {
|
|
|
469
500
|
this.buildReturningClause(input.returning));
|
|
470
501
|
},
|
|
471
502
|
buildInsensitiveLike(column, paramRef) {
|
|
472
|
-
// COLLATE NOCASE is ASCII-only (no Unicode case folding)
|
|
503
|
+
// COLLATE NOCASE is ASCII-only (no Unicode case folding), documented limit.
|
|
473
504
|
return `${column} LIKE ${paramRef} COLLATE NOCASE`;
|
|
474
505
|
},
|
|
475
506
|
buildJsonContains(column, paramRef) {
|
|
476
507
|
// Emulated containment: true when any top-level JSON value equals the param.
|
|
477
|
-
// Limited vs Postgres `@>` (no deep/object containment)
|
|
508
|
+
// Limited vs Postgres `@>` (no deep/object containment), jsonPathSupport='function'.
|
|
478
509
|
return `EXISTS (SELECT 1 FROM json_each(${column}) WHERE json_each.value = ${paramRef})`;
|
|
479
510
|
},
|
|
480
511
|
buildJsonPathExtract(column, pathParamRef) {
|
|
@@ -555,7 +586,7 @@ exports.sqliteDialect = {
|
|
|
555
586
|
},
|
|
556
587
|
};
|
|
557
588
|
function pragma(db, sql) {
|
|
558
|
-
// PRAGMA / SELECT against sqlite_master
|
|
589
|
+
// PRAGMA / SELECT against sqlite_master, read-only, identifiers are SQLite
|
|
559
590
|
// catalog names (never user input here), values normalized for safe ints.
|
|
560
591
|
return db.prepare(sql).all().map(normalizeRow);
|
|
561
592
|
}
|
|
@@ -658,7 +689,7 @@ function introspectSqliteDatabase(db, options = {}) {
|
|
|
658
689
|
// ----- Build relations from foreign keys (belongsTo + hasMany + m2m) -----
|
|
659
690
|
// Delegated to the SHARED introspection pipeline (introspect.ts) so SQLite
|
|
660
691
|
// derives IDENTICAL relation names to the Postgres introspector for the
|
|
661
|
-
// same logical schema
|
|
692
|
+
// same logical schema, legacy-first naming, per-column disambiguation,
|
|
662
693
|
// collision resolution against scalar column fields, and the conservative
|
|
663
694
|
// pure-junction manyToMany auto-detection included.
|
|
664
695
|
const relationsByTable = (0, introspect_js_1.deriveEngineRelations)(tableNames, foreignKeys, pkByTable, columnsByTable);
|
|
@@ -740,7 +771,7 @@ function openSqliteDatabase(target, options) {
|
|
|
740
771
|
db.exec('PRAGMA journal_mode = WAL');
|
|
741
772
|
}
|
|
742
773
|
catch {
|
|
743
|
-
// Some filesystems (network mounts) reject WAL
|
|
774
|
+
// Some filesystems (network mounts) reject WAL, fall back silently.
|
|
744
775
|
}
|
|
745
776
|
}
|
|
746
777
|
return db;
|
package/dist/cjs/typed-sql.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* turbine-orm
|
|
2
|
+
* turbine-orm, Typed raw SQL (Turbine's answer to Prisma's TypedSQL)
|
|
3
3
|
*
|
|
4
4
|
* `client.raw()` returns untyped rows. This module adds a *typed* escape hatch:
|
|
5
5
|
* a generic tagged template where the caller supplies the row shape, and the
|
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
* Design goals & guarantees:
|
|
10
10
|
*
|
|
11
11
|
* 1. **Compile-time only types.** `T` is supplied by the caller and never
|
|
12
|
-
* validated at runtime
|
|
12
|
+
* validated at runtime, exactly like Prisma's TypedSQL and the existing
|
|
13
13
|
* `raw<T>()`. Postgres still returns whatever the SQL selects; the generic
|
|
14
14
|
* is a convenience for autocomplete and downstream type-checking.
|
|
15
15
|
*
|
|
16
16
|
* 2. **Mandatory parameterization.** Only the *static* string segments of the
|
|
17
17
|
* template literal ever reach the SQL text. Every interpolated `${value}`
|
|
18
|
-
* becomes a `$N` placeholder and is passed in the params array
|
|
18
|
+
* becomes a `$N` placeholder and is passed in the params array, it is
|
|
19
19
|
* impossible to string-concatenate a value into the query through this API.
|
|
20
20
|
* This is the whole point of the tagged-template shape: the literal segments
|
|
21
21
|
* are frozen by the compiler (`TemplateStringsArray`), and the only way to
|
|
@@ -69,7 +69,7 @@ export declare function buildTypedSql(strings: TemplateStringsArray, values: rea
|
|
|
69
69
|
* `await`ed directly to get `T[]`, or refined via `.one()` / `.scalar()` first.
|
|
70
70
|
*
|
|
71
71
|
* The query is executed lazily and exactly once per terminal call (`then`,
|
|
72
|
-
* `one`, `scalar`). Each terminal method runs the query independently
|
|
72
|
+
* `one`, `scalar`). Each terminal method runs the query independently, this is
|
|
73
73
|
* an escape hatch, not a cached query object, so don't call two terminals on
|
|
74
74
|
* the same builder expecting a single round-trip; build a fresh template each
|
|
75
75
|
* time (the common pattern is `await db.sql\`...\`` inline).
|
package/dist/cjs/typed-sql.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* turbine-orm
|
|
3
|
+
* turbine-orm, Typed raw SQL (Turbine's answer to Prisma's TypedSQL)
|
|
4
4
|
*
|
|
5
5
|
* `client.raw()` returns untyped rows. This module adds a *typed* escape hatch:
|
|
6
6
|
* a generic tagged template where the caller supplies the row shape, and the
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
* Design goals & guarantees:
|
|
11
11
|
*
|
|
12
12
|
* 1. **Compile-time only types.** `T` is supplied by the caller and never
|
|
13
|
-
* validated at runtime
|
|
13
|
+
* validated at runtime, exactly like Prisma's TypedSQL and the existing
|
|
14
14
|
* `raw<T>()`. Postgres still returns whatever the SQL selects; the generic
|
|
15
15
|
* is a convenience for autocomplete and downstream type-checking.
|
|
16
16
|
*
|
|
17
17
|
* 2. **Mandatory parameterization.** Only the *static* string segments of the
|
|
18
18
|
* template literal ever reach the SQL text. Every interpolated `${value}`
|
|
19
|
-
* becomes a `$N` placeholder and is passed in the params array
|
|
19
|
+
* becomes a `$N` placeholder and is passed in the params array, it is
|
|
20
20
|
* impossible to string-concatenate a value into the query through this API.
|
|
21
21
|
* This is the whole point of the tagged-template shape: the literal segments
|
|
22
22
|
* are frozen by the compiler (`TemplateStringsArray`), and the only way to
|
|
@@ -86,7 +86,7 @@ function buildTypedSql(strings, values, dialect = dialect_js_1.postgresDialect)
|
|
|
86
86
|
* `await`ed directly to get `T[]`, or refined via `.one()` / `.scalar()` first.
|
|
87
87
|
*
|
|
88
88
|
* The query is executed lazily and exactly once per terminal call (`then`,
|
|
89
|
-
* `one`, `scalar`). Each terminal method runs the query independently
|
|
89
|
+
* `one`, `scalar`). Each terminal method runs the query independently, this is
|
|
90
90
|
* an escape hatch, not a cached query object, so don't call two terminals on
|
|
91
91
|
* the same builder expecting a single round-trip; build a fresh template each
|
|
92
92
|
* time (the common pattern is `await db.sql\`...\`` inline).
|
|
@@ -118,7 +118,7 @@ class TypedSqlQuery {
|
|
|
118
118
|
/**
|
|
119
119
|
* PromiseLike implementation: `await db.sql<T>\`...\`` resolves to `T[]`.
|
|
120
120
|
*/
|
|
121
|
-
// biome-ignore lint/suspicious/noThenProperty: intentional thenable
|
|
121
|
+
// biome-ignore lint/suspicious/noThenProperty: intentional thenable, this IS the PromiseLike contract that makes `await db.sql\`...\`` resolve to rows
|
|
122
122
|
then(onfulfilled, onrejected) {
|
|
123
123
|
return this.run().then(onfulfilled, onrejected);
|
|
124
124
|
}
|
package/dist/cli/config.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* turbine-orm CLI
|
|
2
|
+
* turbine-orm CLI, Configuration file support
|
|
3
3
|
*
|
|
4
4
|
* Loads turbine.config.ts (or .js/.mjs) via dynamic import.
|
|
5
5
|
* Falls back to CLI args and environment variables.
|
|
@@ -15,6 +15,15 @@ export interface TurbineCliConfig {
|
|
|
15
15
|
include?: string[];
|
|
16
16
|
/** Tables to exclude */
|
|
17
17
|
exclude?: string[];
|
|
18
|
+
/**
|
|
19
|
+
* Rename derived relations, as `{ table: { derivedName: desiredName } }`.
|
|
20
|
+
*
|
|
21
|
+
* Relation names are composed by introspection (a database does not name its
|
|
22
|
+
* relationships), so two foreign keys to the same table produce names nobody
|
|
23
|
+
* would predict, and a port from another ORM that named them differently has
|
|
24
|
+
* to hand-edit every call site. A typo here is an error, not a silent no-op.
|
|
25
|
+
*/
|
|
26
|
+
relationNames?: Record<string, Record<string, string>>;
|
|
18
27
|
/**
|
|
19
28
|
* Extension for the generated `index.ts` sibling imports (F3):
|
|
20
29
|
* `'js'` (`./types.js`), `'none'` (`./types`), or `'auto'` (default:
|
|
@@ -69,7 +78,7 @@ export type TurbineConfig = TurbineCliConfig;
|
|
|
69
78
|
* path rather than a Postgres schema name? `schema` is the Postgres namespace
|
|
70
79
|
* to introspect (default `public`); the schema-builder file goes in `schemaFile`.
|
|
71
80
|
* A value containing a path separator or a JS/TS extension is almost certainly a
|
|
72
|
-
* mis-set `schemaFile
|
|
81
|
+
* mis-set `schemaFile`, introspecting `WHERE table_schema = './turbine/schema.ts'`
|
|
73
82
|
* silently matches zero tables. Used by `turbine generate` to fail loudly.
|
|
74
83
|
*/
|
|
75
84
|
export declare function looksLikeSchemaFilePath(schema: string): boolean;
|
|
@@ -156,6 +165,8 @@ export interface ResolvedConfig {
|
|
|
156
165
|
keepColumnNames: boolean;
|
|
157
166
|
/** Resolved opt-out of the unique-FK → hasOne introspection flip (F2). */
|
|
158
167
|
legacyToManyUniques: boolean;
|
|
168
|
+
/** Resolved derived-relation rename map, or undefined when none is declared. */
|
|
169
|
+
relationNames?: Record<string, Record<string, string>>;
|
|
159
170
|
}
|
|
160
171
|
export interface CliOverrides {
|
|
161
172
|
url?: string;
|
package/dist/cli/config.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* turbine-orm CLI
|
|
2
|
+
* turbine-orm CLI, Configuration file support
|
|
3
3
|
*
|
|
4
4
|
* Loads turbine.config.ts (or .js/.mjs) via dynamic import.
|
|
5
5
|
* Falls back to CLI args and environment variables.
|
|
@@ -12,7 +12,7 @@ import { pathToFileURL } from 'node:url';
|
|
|
12
12
|
* path rather than a Postgres schema name? `schema` is the Postgres namespace
|
|
13
13
|
* to introspect (default `public`); the schema-builder file goes in `schemaFile`.
|
|
14
14
|
* A value containing a path separator or a JS/TS extension is almost certainly a
|
|
15
|
-
* mis-set `schemaFile
|
|
15
|
+
* mis-set `schemaFile`, introspecting `WHERE table_schema = './turbine/schema.ts'`
|
|
16
16
|
* silently matches zero tables. Used by `turbine generate` to fail loudly.
|
|
17
17
|
*/
|
|
18
18
|
export function looksLikeSchemaFilePath(schema) {
|
|
@@ -158,6 +158,7 @@ export function resolveConfig(fileConfig, overrides) {
|
|
|
158
158
|
out: overrides.out ?? fileConfig.out ?? './generated/turbine',
|
|
159
159
|
schema: overrides.schema ?? fileConfig.schema ?? 'public',
|
|
160
160
|
include: overrides.include ?? fileConfig.include ?? [],
|
|
161
|
+
relationNames: fileConfig.relationNames,
|
|
161
162
|
exclude: overrides.exclude ?? fileConfig.exclude ?? [],
|
|
162
163
|
migrationsDir: fileConfig.migrationsDir ?? './turbine/migrations',
|
|
163
164
|
// `seedFile` is canonical (what the docs and `turbine init` use); `seed` is a
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
*/
|
|
24
24
|
export type DestructiveKind = 'drop-table' | 'drop-schema' | 'drop-database' | 'drop-owned' | 'drop-matview' | 'drop-column' | 'truncate' | 'delete' | 'update-without-where' | 'alter-column-type' | 'merge-delete';
|
|
25
25
|
export interface DestructiveStatement {
|
|
26
|
-
/** The offending SQL statement (trimmed, possibly long
|
|
26
|
+
/** The offending SQL statement (trimmed, possibly long, display truncated) */
|
|
27
27
|
statement: string;
|
|
28
28
|
kind: DestructiveKind;
|
|
29
29
|
/** Best-effort extracted object name (table, schema, or table.column) */
|
package/dist/cli/destructive.js
CHANGED
|
@@ -129,7 +129,7 @@ function isEscapeStringPrefix(sql, quoteAt) {
|
|
|
129
129
|
/** Unquote a "quoted" identifier for display. */
|
|
130
130
|
const ident = (raw) => (raw ?? '?').replace(/^"|"$/g, '');
|
|
131
131
|
const IDENT = String.raw `("[^"]+"|[a-zA-Z_][\w$]*)(\.("[^"]+"|[a-zA-Z_][\w$]*))?`;
|
|
132
|
-
/** Ordered rules
|
|
132
|
+
/** Ordered rules, first match per statement wins. */
|
|
133
133
|
const RULES = [
|
|
134
134
|
{
|
|
135
135
|
kind: 'drop-table',
|
package/dist/cli/index.d.ts
CHANGED
|
@@ -3,21 +3,21 @@
|
|
|
3
3
|
* turbine-orm CLI
|
|
4
4
|
*
|
|
5
5
|
* Commands:
|
|
6
|
-
* turbine init
|
|
7
|
-
* turbine generate | pull
|
|
6
|
+
* turbine init , Initialize a Turbine project
|
|
7
|
+
* turbine generate | pull , Introspect database and generate TypeScript types
|
|
8
8
|
* turbine migrate-from-prisma - Parse a schema.prisma and emit a Prisma->Turbine name map + report
|
|
9
9
|
* turbine push - Apply schema-builder definitions to database (destructive ops gated)
|
|
10
10
|
* turbine migrate create <name> - Create a new SQL migration file (--auto | --from-diff | --recipe <name>)
|
|
11
|
-
* turbine migrate up
|
|
12
|
-
* turbine migrate deploy
|
|
13
|
-
* turbine migrate down
|
|
14
|
-
* turbine migrate status
|
|
15
|
-
* turbine seed
|
|
16
|
-
* turbine status
|
|
11
|
+
* turbine migrate up , Apply pending migrations
|
|
12
|
+
* turbine migrate deploy , Apply pending migrations without prompts
|
|
13
|
+
* turbine migrate down , Rollback last migration
|
|
14
|
+
* turbine migrate status , Show migration status
|
|
15
|
+
* turbine seed , Run seed file
|
|
16
|
+
* turbine status , Show schema summary
|
|
17
17
|
* turbine doctor - Cost-aware missing-FK-index triage (--fix, --json, --no-concurrently, --unused, --audit)
|
|
18
18
|
* turbine studio : Launch local read-only web UI (--demo for a seeded sample DB)
|
|
19
|
-
* turbine mcp
|
|
20
|
-
* turbine observe
|
|
19
|
+
* turbine mcp , Start read-only MCP server over JSON-RPC stdio
|
|
20
|
+
* turbine observe , Launch metrics dashboard (requires TURBINE_OBSERVE_URL)
|
|
21
21
|
*
|
|
22
22
|
* Usage:
|
|
23
23
|
* DATABASE_URL=postgres://... npx turbine generate
|