qubu 0.6.1 → 0.6.3
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/dist/{complete-DP7pliuY.mjs → canonical-B5_ouh-c.mjs} +466 -241
- package/dist/codegen.d.mts +2 -2
- package/dist/codegen.mjs +180 -90
- package/dist/column-Cyc2CMnG.mjs +116 -0
- package/dist/column-DDRvD7SF.mjs +721 -0
- package/dist/{constraints-DM_tarXc.mjs → constraints-CAmi18Uk.mjs} +8 -3
- package/dist/core.d.mts +3 -3
- package/dist/core.mjs +4 -4
- package/dist/diff.d.mts +9 -9
- package/dist/diff.mjs +152 -102
- package/dist/{explain-CkIK13L_.mjs → explain-BIqEmZha.mjs} +1 -1
- package/dist/{expressions-BCjc08zw.mjs → expressions-_6JF_J77.mjs} +2 -1
- package/dist/index-CaxrMD1A.d.mts +1 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +368 -74
- package/dist/introspection/mysql.d.mts +1 -1
- package/dist/introspection/mysql.mjs +156 -23
- package/dist/introspection/postgres.d.mts +6 -3
- package/dist/introspection/postgres.mjs +388 -53
- package/dist/introspection/sqlite.d.mts +1 -1
- package/dist/introspection/sqlite.mjs +198 -12
- package/dist/introspection.d.mts +26 -12
- package/dist/introspection.mjs +2 -672
- package/dist/mysql.d.mts +3 -3
- package/dist/mysql.mjs +6 -5
- package/dist/{errors-Dxv73YJu.mjs → omit-VEr9Ydux.mjs} +5 -1
- package/dist/{on-conflict-CnaY5qso.mjs → on-conflict-B2rFyHGF.mjs} +6 -8
- package/dist/on-duplicate-key-update-Czsw1Yq-.mjs +95 -0
- package/dist/{postgres-Dey7QXPL.mjs → postgres-hFhd0I9n.mjs} +4 -5
- package/dist/postgres.d.mts +2 -2
- package/dist/postgres.mjs +2 -2
- package/dist/{registry-oWDiqD7i.mjs → registry-BXE_4M9P.mjs} +1 -1
- package/dist/{relational-DSAJ-l58.mjs → relational-CoPBETjI.mjs} +3 -2
- package/dist/schema.d.mts +2 -2
- package/dist/schema.mjs +8 -8
- package/dist/{serialize-CE-gw5_s.mjs → serialize-CyobNEx-.mjs} +174 -30
- package/dist/serialize-Du2UPZMt.d.mts +92 -0
- package/dist/snapshot/mysql.d.mts +5 -5
- package/dist/snapshot/mysql.mjs +8 -8
- package/dist/snapshot/postgres.d.mts +3 -3
- package/dist/snapshot/postgres.mjs +9 -9
- package/dist/snapshot/sqlite.d.mts +3 -3
- package/dist/snapshot/sqlite.mjs +7 -7
- package/dist/snapshot-mIb-Zzb5.mjs +1489 -0
- package/dist/snapshot.d.mts +4 -5
- package/dist/snapshot.mjs +3 -4
- package/dist/{source-BDuUXmAk.mjs → source-DYSUqzvb.mjs} +2 -2
- package/dist/sqlite.d.mts +2 -2
- package/dist/sqlite.mjs +6 -6
- package/dist/{table-C1QGNe4P.mjs → table-B8zEq0az.mjs} +4 -4
- package/dist/{types-BLNRatG_.mjs → types-CYHpSPwj.mjs} +10 -5
- package/dist/{types-BEn0N_al.d.mts → types-CiMvKi5V.d.mts} +14 -4
- package/dist/{types-DUe6eeI0.d.mts → types-Dqr4o2I1.d.mts} +590 -168
- package/dist/value-CpaUFtjw.mjs +45 -0
- package/dist/vite/ambient.d.ts +2 -0
- package/dist/vite.d.mts +1 -1
- package/dist/vite.mjs +2 -0
- package/docs/dialects-and-execution.md +105 -26
- package/docs/getting-started.md +10 -10
- package/docs/guides/better-auth.md +16 -5
- package/docs/guides/compose-queries.md +21 -9
- package/docs/guides/drizzle.md +8 -3
- package/docs/guides/extensions/dialects.md +1 -1
- package/docs/guides/extensions/overview.md +1 -1
- package/docs/guides/extensions/sources-and-clauses.md +7 -3
- package/docs/guides/extensions/typed-expressions.md +26 -12
- package/docs/guides/extensions/unsafe-syntax.md +10 -6
- package/docs/guides/json.md +126 -8
- package/docs/guides/mutations.md +51 -6
- package/docs/guides/select/conditions.md +18 -11
- package/docs/guides/select/grouping-and-windows.md +5 -2
- package/docs/guides/select/ordering-and-pagination.md +5 -3
- package/docs/guides/select/overview.md +6 -3
- package/docs/guides/sql-templates.md +11 -5
- package/docs/guides/valtio-sync.md +11 -5
- package/docs/guides/vite-plugin.md +2 -2
- package/docs/index.md +25 -18
- package/docs/migrations/adapters.md +92 -27
- package/docs/migrations/artifacts-and-policy.md +49 -20
- package/docs/migrations/index.md +15 -8
- package/docs/migrations/lotta-adoption.md +16 -5
- package/docs/migrations/operations.md +29 -15
- package/docs/migrations/recovery.md +40 -17
- package/docs/query-model/fragments.md +33 -5
- package/docs/query-model/result-shapes.md +2 -2
- package/docs/query-model/source-scope.md +5 -3
- package/docs/reference/introspection-support.md +42 -37
- package/docs/reference/mysql-snapshot.md +19 -4
- package/docs/reference/postgres-snapshot.md +17 -4
- package/docs/reference/sqlite-snapshot.md +19 -2
- package/docs/reference/supported-surface.md +221 -84
- package/docs/schema/catalog-model.md +44 -14
- package/docs/schema/code-generation.md +40 -21
- package/docs/schema/columns-and-writes.md +21 -11
- package/docs/schema/constraints-and-indexes.md +12 -5
- package/docs/schema/ddl-emission.md +16 -5
- package/docs/schema/diff.md +13 -5
- package/docs/schema/introspection.md +64 -31
- package/docs/schema/migration-plans.md +18 -10
- package/docs/schema/snapshots.md +68 -30
- package/docs/schema/storage-and-schema-sql.md +16 -5
- package/docs/schema/tables-and-names.md +1 -1
- package/docs/sql-semantic-types.md +11 -8
- package/docs/troubleshooting.md +14 -6
- package/package.json +2 -1
- package/dist/canonical-DMvR9yBe.mjs +0 -972
- package/dist/column-BzN8KFJa.mjs +0 -364
- package/dist/column-CFvSbil0.mjs +0 -309
- package/dist/complete-types-CNMWBWap.d.mts +0 -371
- package/dist/index-CGui70hi.d.mts +0 -32
- package/dist/json-Db7XRD91.mjs +0 -169
- package/dist/omit-OxV58AwX.mjs +0 -5
- package/dist/serialize-OvXCLzjm.d.mts +0 -66
- package/dist/snapshot-DgsOhf_8.mjs +0 -354
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { A as fragment, E as makeSchemaExpression, U as resultValue, Y as standardJson, Z as createDialect } from "./column-DDRvD7SF.mjs";
|
|
2
|
+
//#region src/dialects/standard.ts
|
|
3
|
+
/** SQL:2008-style rendering defaults used by the core builder. */
|
|
4
|
+
function standardDialect() {
|
|
5
|
+
return createDialect({
|
|
6
|
+
name: "standard-sql",
|
|
7
|
+
placeholder: () => "?",
|
|
8
|
+
json: standardJson
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/core/primitives/parameter.ts
|
|
13
|
+
function parameter(_value, sqlType) {
|
|
14
|
+
return fragment((context) => context.parameter(_value, sqlType));
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
//#region src/expressions/value.ts
|
|
18
|
+
/** Build a parameterized value expression with an optional runtime SQL domain for the adapter. */
|
|
19
|
+
function value(input, sqlType) {
|
|
20
|
+
const expression = makeSchemaExpression("value", (context) => context.render(parameter(input, sqlType)), resultValue(void 0, void 0, sqlType));
|
|
21
|
+
return Object.freeze({
|
|
22
|
+
...expression,
|
|
23
|
+
value: input
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Bind a value while declaring its compile-time and runtime SQL semantic domain.
|
|
28
|
+
*
|
|
29
|
+
* @remarks
|
|
30
|
+
* The domain is a binding hint; it does not select a JavaScript result decoder.
|
|
31
|
+
*/
|
|
32
|
+
function typedValue(input, sqlType) {
|
|
33
|
+
return value(input, sqlType);
|
|
34
|
+
}
|
|
35
|
+
function isExpressionValue(valueToCheck) {
|
|
36
|
+
return typeof valueToCheck === "object" && valueToCheck !== null && "expressionKind" in valueToCheck && "render" in valueToCheck && typeof valueToCheck.render === "function";
|
|
37
|
+
}
|
|
38
|
+
function isValueExpression(valueToCheck) {
|
|
39
|
+
return isExpressionValue(valueToCheck) && valueToCheck.expressionKind === "value" && "value" in valueToCheck;
|
|
40
|
+
}
|
|
41
|
+
function asValue(input, sqlType) {
|
|
42
|
+
return isExpressionValue(input) ? input : value(input, sqlType);
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
export { parameter as a, value as i, isValueExpression as n, standardDialect as o, typedValue as r, asValue as t };
|
package/dist/vite/ambient.d.ts
CHANGED
|
@@ -68,6 +68,8 @@ declare global {
|
|
|
68
68
|
const isNull: typeof import("qubu").isNull
|
|
69
69
|
const isTrue: typeof import("qubu").isTrue
|
|
70
70
|
const json: typeof import("qubu").json
|
|
71
|
+
const jsonArrayFrom: typeof import("qubu").jsonArrayFrom
|
|
72
|
+
const jsonObjectFrom: typeof import("qubu").jsonObjectFrom
|
|
71
73
|
const jsonBoolean: typeof import("qubu").jsonBoolean
|
|
72
74
|
const jsonExists: typeof import("qubu").jsonExists
|
|
73
75
|
const jsonNumber: typeof import("qubu").jsonNumber
|
package/dist/vite.d.mts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* with the ordinary authoring surface of `qubu`; fragment internals, dialect construction, and
|
|
5
5
|
* schema extensions belong to the layered entrypoints.
|
|
6
6
|
*/
|
|
7
|
-
declare const qubuGlobals: readonly ["add", "alias", "all", "allowAll", "and", "asc", "asValue", "avg", "bigint", "between", "binary", "boolean", "call", "caseWhen", "cast", "check", "coalesce", "column", "concat", "count", "countDistinct", "correlate", "crossJoin", "cte", "date", "denseRank", "defaultValues", "deleteFrom", "desc", "distinct", "divide", "eq", "except", "execute", "executeRows", "externalDefault", "externalGeneratedColumn", "exists", "fetchFirst", "fetchNext", "foreignKey", "from", "fullJoin", "generatedColumn", "gt", "gte", "groupBy", "having", "identityColumn", "inList", "inQuery", "index", "innerJoin", "insertInto", "insertSelect", "integer", "intersect", "isDistinctFrom", "isNotDistinctFrom", "isNotNull", "isNull", "isTrue", "json", "jsonBoolean", "jsonExists", "jsonNumber", "jsonPath", "jsonText", "lateral", "leftJoin", "like", "lower", "lt", "lte", "max", "min", "modulo", "multiply", "naturalJoin", "nativeColumn", "nativeStorage", "ne", "not", "notExists", "notIn", "notLike", "nullsFirst", "nullsLast", "numeric", "nullable", "offset", "omit", "or", "order", "orderBy", "over", "portableStorage", "primaryKey", "qubu", "references", "recursiveCte", "render", "returning", "rightJoin", "rank", "rowNumber", "scalar", "schema", "schemaCall", "select", "sql", "stream", "subtract", "sum", "table", "text", "timestamp", "union", "unionAll", "unique", "uniqueConstraint", "update", "upper", "value", "values", "where", "withCte", "uuid"];
|
|
7
|
+
declare const qubuGlobals: readonly ["add", "alias", "all", "allowAll", "and", "asc", "asValue", "avg", "bigint", "between", "binary", "boolean", "call", "caseWhen", "cast", "check", "coalesce", "column", "concat", "count", "countDistinct", "correlate", "crossJoin", "cte", "date", "denseRank", "defaultValues", "deleteFrom", "desc", "distinct", "divide", "eq", "except", "execute", "executeRows", "externalDefault", "externalGeneratedColumn", "exists", "fetchFirst", "fetchNext", "foreignKey", "from", "fullJoin", "generatedColumn", "gt", "gte", "groupBy", "having", "identityColumn", "inList", "inQuery", "index", "innerJoin", "insertInto", "insertSelect", "integer", "intersect", "isDistinctFrom", "isNotDistinctFrom", "isNotNull", "isNull", "isTrue", "json", "jsonArrayFrom", "jsonObjectFrom", "jsonBoolean", "jsonExists", "jsonNumber", "jsonPath", "jsonText", "lateral", "leftJoin", "like", "lower", "lt", "lte", "max", "min", "modulo", "multiply", "naturalJoin", "nativeColumn", "nativeStorage", "ne", "not", "notExists", "notIn", "notLike", "nullsFirst", "nullsLast", "numeric", "nullable", "offset", "omit", "or", "order", "orderBy", "over", "portableStorage", "primaryKey", "qubu", "references", "recursiveCte", "render", "returning", "rightJoin", "rank", "rowNumber", "scalar", "schema", "schemaCall", "select", "sql", "stream", "subtract", "sum", "table", "text", "timestamp", "union", "unionAll", "unique", "uniqueConstraint", "update", "upper", "value", "values", "where", "withCte", "uuid"];
|
|
8
8
|
type QubuGlobal = (typeof qubuGlobals)[number];
|
|
9
9
|
//#endregion
|
|
10
10
|
//#region src/vite/index.d.ts
|
package/dist/vite.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Dialects and execution
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Choose a SQL dialect and connect Qubu queries to your database driver.
|
|
4
4
|
|
|
5
5
|
## Render once, choose a policy at the boundary
|
|
6
6
|
|
|
@@ -77,7 +77,12 @@ Qubu does not open connections or bind values for a particular client. An
|
|
|
77
77
|
adapter receives an `ExecutionRequest` and returns driver-normalized object
|
|
78
78
|
rows. Qubu then uses the query's result shape and the adapter's decoder policy
|
|
79
79
|
to produce the typed `ExecutionResult`. A `TransactionalQueryAdapter` can also
|
|
80
|
-
pin one driver connection for a callback transaction
|
|
80
|
+
pin one driver connection for a callback transaction.
|
|
81
|
+
|
|
82
|
+
`request.statement.parameterSqlTypes`, when present, lists SQL domains in
|
|
83
|
+
the same order as `statement.parameters`. Adapters can pass each domain to their
|
|
84
|
+
value encoder or driver binding layer when a client distinguishes values such
|
|
85
|
+
as `DATE`, `TIMESTAMP`, `UUID`, and `DECIMAL`.
|
|
81
86
|
|
|
82
87
|
```ts
|
|
83
88
|
import { qubu } from "qubu"
|
|
@@ -138,19 +143,23 @@ per request, binds Qubu's ordered parameters, copies object rows, and finalizes
|
|
|
138
143
|
the statement in a `finally` block. SQLite's change count and generated row ID
|
|
139
144
|
are returned as mutation metadata when the request is a mutation.
|
|
140
145
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
146
|
+
Your application manages the worker:
|
|
147
|
+
|
|
148
|
+
1. Initialize the official SQLite module inside a dedicated worker.
|
|
149
|
+
2. Construct the adapter around its `sqlite3.oo1.DB`.
|
|
150
|
+
3. Close the adapter before terminating the worker.
|
|
151
|
+
|
|
152
|
+
Serve the package’s `sqlite3.wasm` asset beside the bundled worker module. The
|
|
153
|
+
combo runner’s verified browser scenario demonstrates this setup.
|
|
147
154
|
|
|
148
155
|
### Decode schema-aware result values
|
|
149
156
|
|
|
150
|
-
Portable boolean, date, timestamp, and
|
|
151
|
-
result domains through projection aliases, derived queries, CTEs, set
|
|
152
|
-
operations, and mutation `RETURNING`.
|
|
153
|
-
|
|
157
|
+
Portable boolean, date, timestamp, JSON, and bigint columns retain their
|
|
158
|
+
logical result domains through projection aliases, derived queries, CTEs, set
|
|
159
|
+
operations, and mutation `RETURNING`. The result field exposes that domain as
|
|
160
|
+
`sqlType` before execution. Register only the conversions required by the
|
|
161
|
+
selected driver configuration. `sqlType` identifies the SQL domain; `type` and
|
|
162
|
+
the selected decoder determine whether Qubu converts the returned value:
|
|
154
163
|
|
|
155
164
|
```ts
|
|
156
165
|
import {
|
|
@@ -180,6 +189,11 @@ const adapter: QueryAdapter = {
|
|
|
180
189
|
}
|
|
181
190
|
```
|
|
182
191
|
|
|
192
|
+
Qubu can decode bigint values exactly when a driver returns a bigint, a safe
|
|
193
|
+
integer, or an integer string. For arbitrary-precision `DECIMAL` values, keep
|
|
194
|
+
the driver's exact representation (usually a string or decimal object) rather
|
|
195
|
+
than converting it to a JavaScript number.
|
|
196
|
+
|
|
183
197
|
Do not register `jsonTextResultDecoder` when the driver already returns parsed
|
|
184
198
|
JSON. A JSON string is otherwise ambiguous: it may be serialized JSON or an
|
|
185
199
|
already-decoded JSON string scalar. With no registered decoder, Qubu preserves
|
|
@@ -422,12 +436,16 @@ queries identify their parent transaction operation. Hooks are synchronous,
|
|
|
422
436
|
and their failures are sent to `onHookError` without changing the database
|
|
423
437
|
operation's result.
|
|
424
438
|
|
|
439
|
+
### What observations include
|
|
440
|
+
|
|
425
441
|
Hook metadata accepts only strings, numbers, and booleans. Observations include
|
|
426
442
|
rendered SQL and parameter count, but never parameter values, result rows,
|
|
427
443
|
decoded values, or insert identifiers. Rendered SQL can still contain literals
|
|
428
444
|
introduced by unsafe SQL helpers, so treat it according to the application's
|
|
429
445
|
logging policy.
|
|
430
446
|
|
|
447
|
+
### Stream observation timing
|
|
448
|
+
|
|
431
449
|
Streaming adapters are still called eagerly. A consumed stream completes its
|
|
432
450
|
observation when it is exhausted, closed early, or fails. A stream created but
|
|
433
451
|
never consumed has no completion observation. Hooks are available only on
|
|
@@ -453,19 +471,74 @@ const result = await transactionalDb.transaction(async (transaction) => {
|
|
|
453
471
|
})
|
|
454
472
|
```
|
|
455
473
|
|
|
456
|
-
The adapter
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
474
|
+
The adapter manages the transaction:
|
|
475
|
+
|
|
476
|
+
1. Acquire and pin one connection.
|
|
477
|
+
2. Begin the transaction.
|
|
478
|
+
3. Run the callback.
|
|
479
|
+
4. Commit if the callback resolves, or roll back if it rejects.
|
|
480
|
+
5. Release the connection in either case.
|
|
461
481
|
|
|
462
|
-
|
|
463
|
-
`
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
`TransactionOptions.signal` is passed to the adapter. Isolation
|
|
468
|
-
other driver-specific settings remain adapter-specific.
|
|
482
|
+
Qubu creates the scoped client and returns the callback result. The adapter
|
|
483
|
+
emits `BEGIN`, `COMMIT`, and `ROLLBACK`.
|
|
484
|
+
|
|
485
|
+
A scoped client's methods follow its adapter's capabilities: `execute()` and
|
|
486
|
+
`rows()` are always available; EXPLAIN and streaming require their respective
|
|
487
|
+
capabilities. `TransactionOptions.signal` is passed to the adapter. Isolation
|
|
488
|
+
levels and other driver-specific settings remain adapter-specific.
|
|
489
|
+
|
|
490
|
+
### Roll back part of a transaction
|
|
491
|
+
|
|
492
|
+
The pg, mysql2, and node:sqlite adapters expose `transaction()` on scoped
|
|
493
|
+
clients through the shared `NestedTransactionalQueryAdapter` capability.
|
|
494
|
+
Other adapters retain their existing transaction surface. For example, with a
|
|
495
|
+
bound pg client, catch a nested failure to keep earlier work:
|
|
496
|
+
|
|
497
|
+
```ts
|
|
498
|
+
await db.transaction(async (outer) => {
|
|
499
|
+
await outer.execute(firstMutation)
|
|
500
|
+
try {
|
|
501
|
+
await outer.transaction(async (inner) => {
|
|
502
|
+
await inner.execute(optionalMutation)
|
|
503
|
+
})
|
|
504
|
+
} catch (error) {
|
|
505
|
+
// The nested work was rolled back; the outer transaction can continue.
|
|
506
|
+
}
|
|
507
|
+
await outer.execute(secondMutation)
|
|
508
|
+
})
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
Each nested callback uses a uniquely named savepoint on the same connection.
|
|
512
|
+
Success releases it; failure rolls back to it and releases it. Letting the
|
|
513
|
+
failure escape also rolls back the outer transaction. Failed savepoint creation
|
|
514
|
+
or recovery makes the entire transaction unsafe to commit, even if the callback
|
|
515
|
+
catches the error. Primary and cleanup failures are retained in `AggregateError`.
|
|
516
|
+
|
|
517
|
+
#### Finish work before leaving a scope
|
|
518
|
+
|
|
519
|
+
Await every query and nested transaction before returning. These three adapters
|
|
520
|
+
reject:
|
|
521
|
+
|
|
522
|
+
- Calls on a finished scoped client.
|
|
523
|
+
- Overlapping sibling scopes.
|
|
524
|
+
- A child scope started while its parent has pending queries.
|
|
525
|
+
- Parent queries while a child is active.
|
|
526
|
+
|
|
527
|
+
If a callback finishes with work pending, the adapter waits for that work and
|
|
528
|
+
rolls back.
|
|
529
|
+
|
|
530
|
+
Use the active scoped client for all work on a directly supplied connection.
|
|
531
|
+
Its root client rejects unrelated operations during the transaction. A pg pool
|
|
532
|
+
can still run independent queries on other connections.
|
|
533
|
+
|
|
534
|
+
Your application remains responsible for raw driver calls and separately
|
|
535
|
+
constructed adapters.
|
|
536
|
+
|
|
537
|
+
EXPLAIN and result decoding remain available at every depth. Nested transaction
|
|
538
|
+
hooks identify their enclosing transaction with `parentId`; queries identify
|
|
539
|
+
their immediate scope. Cancellation does not interrupt savepoint recovery.
|
|
540
|
+
|
|
541
|
+
## Execute without a bound client
|
|
469
542
|
|
|
470
543
|
The standalone functions remain useful when the adapter varies by call or a
|
|
471
544
|
small module does not need a bound client:
|
|
@@ -477,6 +550,8 @@ const result = await execute(query, adapter)
|
|
|
477
550
|
const rows = await executeRows(readQuery, adapter)
|
|
478
551
|
```
|
|
479
552
|
|
|
553
|
+
### Result fields
|
|
554
|
+
|
|
480
555
|
| Result field | Adapter type | Contract |
|
|
481
556
|
| -------------- | ------------------------------------ | ------------------------------------------------------------------------------------- |
|
|
482
557
|
| `rows` | `readonly Record<string, unknown>[]` | Key by rendered aliases; Qubu returns the decoded `readonly TRow[]` |
|
|
@@ -489,11 +564,15 @@ The last three fields are optional. For example, an adapter can map PostgreSQL
|
|
|
489
564
|
`changes` and `lastInsertRowid`. Omit a fact that the selected driver cannot
|
|
490
565
|
report accurately. Qubu does not derive mutation metadata from returned rows.
|
|
491
566
|
|
|
567
|
+
### Dialect overrides and errors
|
|
568
|
+
|
|
492
569
|
The adapter's `dialect` becomes the default for standalone and bound execution.
|
|
493
570
|
A `dialect` in the execution options overrides that rendering policy. Qubu
|
|
494
571
|
passes `signal`, `queryKind`, and `resultShape` to the adapter without changing
|
|
495
|
-
them.
|
|
496
|
-
|
|
572
|
+
them.
|
|
573
|
+
|
|
574
|
+
The adapter decides whether and how its driver supports cancellation. Driver
|
|
575
|
+
errors pass through unchanged. Decoder failures become a
|
|
497
576
|
`ResultDecodingError` that identifies the row and field without exposing the
|
|
498
577
|
raw value.
|
|
499
578
|
|
package/docs/getting-started.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Getting started
|
|
2
2
|
|
|
3
|
-
> Define a
|
|
3
|
+
> Define a table and inspect your first query’s SQL and parameters.
|
|
4
4
|
|
|
5
5
|
## Install Qubu
|
|
6
6
|
|
|
@@ -13,10 +13,9 @@ pnpm add qubu
|
|
|
13
13
|
Import query-building functions from the package root. Qubu does not need a
|
|
14
14
|
database connection to construct or render a query.
|
|
15
15
|
|
|
16
|
-
The examples
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
keeping the final call in SQL order makes the query easy to scan and repair.
|
|
16
|
+
The examples write clauses in SQL order so the query is easy to scan.
|
|
17
|
+
`select()` also accepts independent clauses in any order and puts them in SQL
|
|
18
|
+
order when rendering.
|
|
20
19
|
|
|
21
20
|
## Define a table
|
|
22
21
|
|
|
@@ -38,10 +37,9 @@ nullable email column is inferred as `string | null` when selected.
|
|
|
38
37
|
|
|
39
38
|
## Build and render a query
|
|
40
39
|
|
|
41
|
-
Pass
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
`users` table from the previous section.
|
|
40
|
+
Pass the fields you want to return as a named object, called the projection.
|
|
41
|
+
Then add the clauses. This example uses the `users` table from the previous
|
|
42
|
+
section.
|
|
45
43
|
|
|
46
44
|
```ts
|
|
47
45
|
import { eq, from, render, select, where } from "qubu"
|
|
@@ -69,6 +67,8 @@ statement.parameters
|
|
|
69
67
|
// [7]
|
|
70
68
|
```
|
|
71
69
|
|
|
70
|
+
### Inspect the result type
|
|
71
|
+
|
|
72
72
|
The selected row type is available on the query value:
|
|
73
73
|
|
|
74
74
|
```ts
|
|
@@ -91,6 +91,6 @@ type UserRow = typeof query.row
|
|
|
91
91
|
inputs.
|
|
92
92
|
- [Choose a database dialect](dialects-and-execution.md) when the
|
|
93
93
|
driver expects different identifier, placeholder, or pagination syntax.
|
|
94
|
-
- [
|
|
94
|
+
- [Query nested JSON](guides/json.md) or read scalars from a JSON column.
|
|
95
95
|
- [Use the Vite compiler hint](guides/vite-plugin.md) for directive-based
|
|
96
96
|
imports.
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Better Auth
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Define auth tables with Qubu and connect Better Auth to a transactional Qubu client.
|
|
4
|
+
|
|
5
|
+
## Install the integration
|
|
4
6
|
|
|
5
7
|
Install the integration next to Qubu and Better Auth:
|
|
6
8
|
|
|
@@ -8,10 +10,15 @@ Install the integration next to Qubu and Better Auth:
|
|
|
8
10
|
pnpm add qubu @qubu/better-auth better-auth
|
|
9
11
|
```
|
|
10
12
|
|
|
11
|
-
Define the
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
## Define the auth schema
|
|
14
|
+
|
|
15
|
+
Define the Better Auth options once. Qubu derives its schema from Better Auth’s
|
|
16
|
+
resolved public metadata, including:
|
|
17
|
+
|
|
18
|
+
- Core tables and renamed models or fields.
|
|
19
|
+
- Additional fields and plugin tables.
|
|
20
|
+
- References and unique constraints.
|
|
21
|
+
- Compound indexes.
|
|
15
22
|
|
|
16
23
|
```ts
|
|
17
24
|
import { betterAuth } from "better-auth"
|
|
@@ -44,6 +51,8 @@ export const auth = betterAuth({
|
|
|
44
51
|
migration-plan, and DDL workflows. The adapter's Better Auth `createSchema`
|
|
45
52
|
hook emits a TypeScript module that reconstructs the same Qubu-owned metadata.
|
|
46
53
|
|
|
54
|
+
## Database requirements
|
|
55
|
+
|
|
47
56
|
The package never imports PostgreSQL, MySQL, or SQLite drivers. It executes
|
|
48
57
|
through Qubu's query and transaction boundaries. PostgreSQL and SQLite use one
|
|
49
58
|
limited mutation statement for atomic consume and guarded increment operations;
|
|
@@ -51,6 +60,8 @@ MySQL locks one selected row inside the Qubu-owned transaction. A client without
|
|
|
51
60
|
transaction support, or a dialect other than PostgreSQL, MySQL, or SQLite, is
|
|
52
61
|
rejected during adapter construction.
|
|
53
62
|
|
|
63
|
+
## Enum limitation
|
|
64
|
+
|
|
54
65
|
Better Auth enum metadata is currently rejected because Qubu cannot preserve
|
|
55
66
|
the closed value set as a portable column without adding a database constraint.
|
|
56
67
|
The error includes the model and field path instead of silently widening it to
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Compose queries
|
|
2
2
|
|
|
3
|
-
> Reuse a query
|
|
3
|
+
> Reuse a query as a CTE, a derived table, or a subquery, and combine query results.
|
|
4
4
|
|
|
5
5
|
## Turn a query into a CTE
|
|
6
6
|
|
|
@@ -28,6 +28,8 @@ The rendered statement includes the `WITH` clause before `SELECT`. Selected
|
|
|
28
28
|
camelCase keys use snake_case while they belong to the CTE relation; the outer
|
|
29
29
|
result projection aliases them back to camelCase for the returned row.
|
|
30
30
|
|
|
31
|
+
### Use a CTE in a mutation
|
|
32
|
+
|
|
31
33
|
Attach the same clause to an insert, update, or delete when the mutation reads
|
|
32
34
|
through the CTE. For example, an insert can consume a filtered CTE through
|
|
33
35
|
`insertSelect()`:
|
|
@@ -66,11 +68,20 @@ const numbers = recursiveCte("numbers", select({ value: cast(value(1), integer()
|
|
|
66
68
|
const query = select({ value: numbers.value }, withCte(numbers), from(numbers))
|
|
67
69
|
```
|
|
68
70
|
|
|
69
|
-
The anchor
|
|
70
|
-
|
|
71
|
-
|
|
71
|
+
The anchor defines the fields the CTE returns:
|
|
72
|
+
|
|
73
|
+
- Field names.
|
|
74
|
+
- Application types.
|
|
75
|
+
- Nullability.
|
|
76
|
+
- SQL domains.
|
|
77
|
+
|
|
78
|
+
The recursive member must select the same fields with compatible types.
|
|
79
|
+
|
|
80
|
+
Give bound anchor values an explicit SQL type with
|
|
72
81
|
`cast()` when the database cannot infer it from surrounding columns; PostgreSQL
|
|
73
|
-
requires this for recursive CTE anchors.
|
|
82
|
+
requires this for recursive CTE anchors.
|
|
83
|
+
|
|
84
|
+
Qubu renders `WITH RECURSIVE`, an
|
|
74
85
|
explicit relation column list, and `anchor UNION ALL member`; ordinary and
|
|
75
86
|
recursive CTEs can share one `withCte()` clause.
|
|
76
87
|
|
|
@@ -117,7 +128,9 @@ const query = select(
|
|
|
117
128
|
`scalar()` throws at runtime when the query selects more than one field. Its
|
|
118
129
|
type is the selected field's value type, widened with `null` when the query may
|
|
119
130
|
return no rows. An ordinary select and `fetchFirst(1)` are both nullable: the
|
|
120
|
-
limit proves at most one row, not that a row exists.
|
|
131
|
+
limit proves at most one row, not that a row exists.
|
|
132
|
+
|
|
133
|
+
A source-free select such
|
|
121
134
|
as `select({ value: value(42) })` is known to produce exactly one row.
|
|
122
135
|
|
|
123
136
|
Qubu does not treat an arbitrary predicate as proof of exactness. Use
|
|
@@ -163,9 +176,8 @@ code.
|
|
|
163
176
|
## Constrain a reusable fragment by required fields
|
|
164
177
|
|
|
165
178
|
Use `TableLike` when a fragment requires a physical table and `SourceLike`
|
|
166
|
-
when aliases, CTEs, derived tables, or custom sources are also valid. Both
|
|
167
|
-
|
|
168
|
-
generic function retains its exact source identity.
|
|
179
|
+
when aliases, CTEs, derived tables, or custom sources are also valid. Both allow the source to contain additional fields. The generic function
|
|
180
|
+
retains the source’s exact identity.
|
|
169
181
|
|
|
170
182
|
For an application-level requirement, describe the required JavaScript row:
|
|
171
183
|
|
package/docs/guides/drizzle.md
CHANGED
|
@@ -123,9 +123,14 @@ override.
|
|
|
123
123
|
## Runtime metadata
|
|
124
124
|
|
|
125
125
|
Each dialect adapter maps Qubu storage descriptors to its own Drizzle builders.
|
|
126
|
-
It also transfers
|
|
127
|
-
|
|
128
|
-
|
|
126
|
+
It also transfers:
|
|
127
|
+
|
|
128
|
+
- Concrete defaults and generated expressions.
|
|
129
|
+
- Common primary and unique constraints.
|
|
130
|
+
- Checks and foreign keys.
|
|
131
|
+
- Indexes.
|
|
132
|
+
|
|
133
|
+
Native storage must belong to the selected dialect:
|
|
129
134
|
|
|
130
135
|
```ts
|
|
131
136
|
import { nativeColumn, schema, table } from "qubu"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Add a dialect policy
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Customize how Qubu renders SQL for your driver.
|
|
4
4
|
|
|
5
5
|
Use `createDialect()` when the query is portable but the driver changes
|
|
6
6
|
identifiers, placeholders, or pagination:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Extend Qubu
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Add SQL features that Qubu’s built-in helpers do not cover.
|
|
4
4
|
|
|
5
5
|
Qubu extensions are values that render SQL and carry the metadata later
|
|
6
6
|
composition needs. Choose the page that matches the thing you are adding:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Add sources and clauses
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Add a SQL clause or table-like source that works with Qubu’s query checks.
|
|
4
4
|
|
|
5
5
|
## Add a custom clause
|
|
6
6
|
|
|
@@ -67,9 +67,13 @@ render(query)
|
|
|
67
67
|
```
|
|
68
68
|
|
|
69
69
|
`identity` is the source-scope key; `reference` is the SQL qualifier used by
|
|
70
|
-
the generated columns.
|
|
70
|
+
the generated columns.
|
|
71
|
+
|
|
72
|
+
A nullable column remains nullable, and a
|
|
71
73
|
`leftJoin(rows, ...)` adds outer-join nullability to every selected row
|
|
72
|
-
column.
|
|
74
|
+
column.
|
|
75
|
+
|
|
76
|
+
Render the complete relation in the producer and bind values with
|
|
73
77
|
`context.parameter()`; the normal renderer preserves parameter order.
|
|
74
78
|
|
|
75
79
|
## Read next
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Add typed expressions
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Build custom expressions that preserve result types and query checks.
|
|
4
4
|
|
|
5
5
|
## Build expressions from public helpers
|
|
6
6
|
|
|
@@ -47,30 +47,44 @@ const nameAsCitext = cast(users.name, citext)
|
|
|
47
47
|
```
|
|
48
48
|
|
|
49
49
|
The first three `column` type arguments are output, insert, and update values;
|
|
50
|
-
the fourth is the SQL domain.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
the fourth is the SQL domain.
|
|
51
|
+
|
|
52
|
+
The `text` equality and ordering groups make the custom domain compatible with `SqlText`. Use a distinct group when cross-type
|
|
53
|
+
comparison is not portable.
|
|
54
|
+
|
|
55
|
+
### Use the definition as a cast target
|
|
56
|
+
|
|
57
|
+
`castType` also makes this definition a cast target. Its SQL text is emitted
|
|
58
|
+
unchanged, so keep it in trusted extension code.
|
|
59
|
+
|
|
54
60
|
Definitions with schema flags are not accepted as cast targets because cast
|
|
55
61
|
nullability comes from the operand and write flags have no cast meaning.
|
|
56
62
|
|
|
63
|
+
### Type individual expressions
|
|
64
|
+
|
|
57
65
|
Declare result domains at other extension boundaries too:
|
|
58
66
|
|
|
59
67
|
```ts
|
|
60
68
|
import { typedCall, typedCast, typedValue, unsafeExpression } from "qubu/core"
|
|
61
69
|
import type { SqlText, SqlUuid } from "qubu"
|
|
62
70
|
|
|
63
|
-
const id = typedValue<SqlUuid, string>("108cb836-20d2-41b2-8c23-f0c94700aa7e")
|
|
71
|
+
const id = typedValue<SqlUuid, string>("108cb836-20d2-41b2-8c23-f0c94700aa7e", "uuid")
|
|
64
72
|
const normalized = typedCall<SqlText, string>()("custom_text", users.name)
|
|
65
73
|
const rawNameAsText = typedCast<string, SqlText>()(users.name, "TEXT")
|
|
66
74
|
const generated = unsafeExpression<string, SqlText>("custom_text()")
|
|
67
75
|
```
|
|
68
76
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
77
|
+
Choose the helper for the operation:
|
|
78
|
+
|
|
79
|
+
- `typedCall()` preserves source requirements from its arguments.
|
|
80
|
+
- `typedCast()` supplies a cast target when no reusable definition describes
|
|
81
|
+
it. It preserves operand nullability and source metadata, and emits the
|
|
82
|
+
supplied type name unchanged.
|
|
83
|
+
- `typedValue()` binds a parameter and declares its runtime SQL domain for
|
|
84
|
+
the adapter. It does not choose a JavaScript result decoder; schema columns
|
|
85
|
+
carry decoder metadata separately.
|
|
86
|
+
- `unsafeExpression()` emits its string unchanged. Use it only when the other
|
|
87
|
+
helpers cannot express the syntax.
|
|
74
88
|
|
|
75
89
|
The lower-level forms also expose the SQL domain in their generic lists:
|
|
76
90
|
`call<Output, Name, Arguments, NullableFrom, SqlType>()` and
|
|
@@ -78,7 +92,7 @@ The lower-level forms also expose the SQL domain in their generic lists:
|
|
|
78
92
|
argument or nullability types in its own generic signature.
|
|
79
93
|
|
|
80
94
|
Untyped `column()`, `value()`, `call()`, and custom expressions use
|
|
81
|
-
`SqlUnknown`, which
|
|
95
|
+
`SqlUnknown`, which allows composition without SQL-domain checks. Declaring a
|
|
82
96
|
known domain opts the extension into incompatible-operation errors. See
|
|
83
97
|
[SQL semantic types](../../sql-semantic-types.md) for the capability model and
|
|
84
98
|
its limits.
|
|
@@ -14,12 +14,16 @@ const query = select({
|
|
|
14
14
|
})
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
`
|
|
17
|
+
## Choose the right helper
|
|
18
|
+
|
|
19
|
+
Keep raw identifiers and values out of the string:
|
|
20
|
+
|
|
21
|
+
- Use a typed custom fragment for syntax you will reuse.
|
|
22
|
+
- Use the [`sql` template tag](../sql-templates.md) for fixed trusted syntax
|
|
23
|
+
with bound values or existing Qubu fragments.
|
|
24
|
+
- Use `unsafeExpression()` for trusted dynamic SQL text.
|
|
25
|
+
- Use `identifier()` or `qualifiedIdentifier()` from `qubu/core` for runtime
|
|
26
|
+
identifiers.
|
|
23
27
|
|
|
24
28
|
Read [Dialects and execution](../../dialects-and-execution.md) for the boundary
|
|
25
29
|
between rendering and driver behavior. Read [Add typed
|