@lunora/sql-store 1.0.0-alpha.33 → 1.0.0-alpha.34
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/dialect.d.mts +46 -46
- package/dist/dialect.d.ts +46 -46
- package/dist/index.d.mts +106 -106
- package/dist/index.d.ts +106 -106
- package/package.json +3 -3
package/dist/dialect.d.mts
CHANGED
|
@@ -5,18 +5,18 @@ interface SqlRunResult {
|
|
|
5
5
|
rowsAffected: number;
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
8
|
-
* The async SQL surface the store core consumes. Satisfied by a
|
|
9
|
-
* `D1Session`/`D1Client` (D1), a `node:sqlite` adapter (tests), or a
|
|
10
|
-
* Hyperdrive-backed `postgres`/`pg`/`mysql2` driver (PlanetScale).
|
|
11
|
-
*
|
|
12
|
-
* `all` runs a row-returning statement (incl. `... RETURNING ...`); `run` runs a
|
|
13
|
-
* write and reports `rowsAffected` — the matched-rows count that drives the
|
|
14
|
-
* MySQL optimistic-concurrency guard (which has no `RETURNING`).
|
|
15
|
-
*
|
|
16
|
-
* Note: companion writes (aggregate/rank/FTS/CDC) run as separate sequential
|
|
17
|
-
* statements after the row write on every engine, so they share D1's
|
|
18
|
-
* at-least-once caveat — there is no cross-statement transaction here.
|
|
19
|
-
*/
|
|
8
|
+
* The async SQL surface the store core consumes. Satisfied by a
|
|
9
|
+
* `D1Session`/`D1Client` (D1), a `node:sqlite` adapter (tests), or a
|
|
10
|
+
* Hyperdrive-backed `postgres`/`pg`/`mysql2` driver (PlanetScale).
|
|
11
|
+
*
|
|
12
|
+
* `all` runs a row-returning statement (incl. `... RETURNING ...`); `run` runs a
|
|
13
|
+
* write and reports `rowsAffected` — the matched-rows count that drives the
|
|
14
|
+
* MySQL optimistic-concurrency guard (which has no `RETURNING`).
|
|
15
|
+
*
|
|
16
|
+
* Note: companion writes (aggregate/rank/FTS/CDC) run as separate sequential
|
|
17
|
+
* statements after the row write on every engine, so they share D1's
|
|
18
|
+
* at-least-once caveat — there is no cross-statement transaction here.
|
|
19
|
+
*/
|
|
20
20
|
interface SqlExec {
|
|
21
21
|
all: (sql: string, params: ReadonlyArray<unknown>) => Promise<Record<string, unknown>[]>;
|
|
22
22
|
run: (sql: string, params: ReadonlyArray<unknown>) => Promise<SqlRunResult>;
|
|
@@ -26,19 +26,19 @@ interface SqlDialect {
|
|
|
26
26
|
/** Affected-rows extractor for the OCC fallback when `supportsReturning` is false (MySQL). */
|
|
27
27
|
affectedRows?: (result: SqlRunResult) => number;
|
|
28
28
|
/**
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
* Storage SQL column type for a validator `kind`. SQLite affinity
|
|
30
|
+
* (`TEXT`/`INTEGER`/`REAL`/`BLOB`); Postgres `TEXT`/`DOUBLE PRECISION`/
|
|
31
|
+
* `BOOLEAN`/`JSONB`/`BYTEA`; MySQL `VARCHAR(255)`/`TEXT`/`DOUBLE`/
|
|
32
|
+
* `TINYINT(1)`/`JSON`/`LONGBLOB`.
|
|
33
|
+
*/
|
|
34
34
|
columnType: (kind: string | undefined) => string;
|
|
35
35
|
/**
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
* Engine SQL types for the **internal companion tables** (aggregate / rank /
|
|
37
|
+
* CDC), which are built from raw SQL types, not validator kinds. SQLite uses
|
|
38
|
+
* `TEXT`/`REAL`/`INTEGER`/`BLOB` and `INTEGER PRIMARY KEY AUTOINCREMENT`;
|
|
39
|
+
* Postgres `TEXT`/`DOUBLE PRECISION`/`INTEGER`/`BYTEA` + `BIGSERIAL`; MySQL
|
|
40
|
+
* needs a bounded `VARCHAR` key, `DOUBLE`, `LONGBLOB`, `AUTO_INCREMENT`.
|
|
41
|
+
*/
|
|
42
42
|
companionTypes: {
|
|
43
43
|
autoincrementPrimaryKey: string;
|
|
44
44
|
integer: string;
|
|
@@ -47,18 +47,18 @@ interface SqlDialect {
|
|
|
47
47
|
text: string;
|
|
48
48
|
};
|
|
49
49
|
/**
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
* Map a stored value back to its JS form, by effective validator `kind`
|
|
51
|
+
* (inverse of `encode`). NOTE: currently **unused** by the store core, which
|
|
52
|
+
* hard-codes `sqliteDecode` in `decodeGlobalRow` on every engine. Kept on the
|
|
53
|
+
* seam for a future engine-native codec; an override here does not run today.
|
|
54
|
+
*/
|
|
55
55
|
decode: (value: unknown, kind: string | undefined) => unknown;
|
|
56
56
|
/**
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
57
|
+
* Map a JS value to its bound storage form (boolean→1/0, bigint→string,
|
|
58
|
+
* object→JSON on SQLite). NOTE: currently **unused** by the store core, which
|
|
59
|
+
* hard-codes `sqliteEncode` as `serializeColumnValue` on every engine. Kept on
|
|
60
|
+
* the seam for a future engine-native codec; an override here does not run today.
|
|
61
|
+
*/
|
|
62
62
|
encode: (value: unknown) => unknown;
|
|
63
63
|
/** The framework columns every global table carries — the `id` primary key and `_creationTime` — as `{ name, type }` so the DDL builder can quote each name through the engine's dialect. */
|
|
64
64
|
frameworkColumns: () => ReadonlyArray<{
|
|
@@ -66,12 +66,12 @@ interface SqlDialect {
|
|
|
66
66
|
type: string;
|
|
67
67
|
}>;
|
|
68
68
|
/**
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
69
|
+
* Optional: the key-prefix length an indexed column of this `kind` needs.
|
|
70
|
+
* MySQL/InnoDB can't index a `TEXT`/`LONGTEXT`/`BLOB` column without a prefix
|
|
71
|
+
* (the store appends `(<n>)` to the column reference); SQLite/Postgres index
|
|
72
|
+
* text columns directly and omit this hook (or return `undefined`). `kind` is
|
|
73
|
+
* the column's effective validator kind.
|
|
74
|
+
*/
|
|
75
75
|
indexKeyPrefix?: (kind: string | undefined) => number | undefined;
|
|
76
76
|
/** True when an `error` thrown by a write is a UNIQUE-constraint breach (mapped to a 409 ConflictError). */
|
|
77
77
|
isUniqueViolation: (error: unknown) => boolean;
|
|
@@ -80,13 +80,13 @@ interface SqlDialect {
|
|
|
80
80
|
/** True when the engine supports `UPDATE/DELETE ... RETURNING` (SQLite/PG yes, MySQL no → use `affectedRows`). */
|
|
81
81
|
supportsReturning: boolean;
|
|
82
82
|
/**
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
83
|
+
* The catalog probe for whether a physical `table` exists — backs the opt-in
|
|
84
|
+
* companion-table (`__agg_`/`__rank_`) existence checks. Returns a drizzle
|
|
85
|
+
* {@link SQL} (a non-empty result ⇒ the table exists) so it renders through
|
|
86
|
+
* the same per-engine path as every other statement, never a hand-built
|
|
87
|
+
* placeholder string. SQLite reads `sqlite_master`; Postgres/MySQL read
|
|
88
|
+
* `information_schema.tables`.
|
|
89
|
+
*/
|
|
90
90
|
tableExists: (table: string) => SQL;
|
|
91
91
|
}
|
|
92
92
|
export { SqlDialect, SqlExec, SqlRunResult };
|
package/dist/dialect.d.ts
CHANGED
|
@@ -5,18 +5,18 @@ interface SqlRunResult {
|
|
|
5
5
|
rowsAffected: number;
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
8
|
-
* The async SQL surface the store core consumes. Satisfied by a
|
|
9
|
-
* `D1Session`/`D1Client` (D1), a `node:sqlite` adapter (tests), or a
|
|
10
|
-
* Hyperdrive-backed `postgres`/`pg`/`mysql2` driver (PlanetScale).
|
|
11
|
-
*
|
|
12
|
-
* `all` runs a row-returning statement (incl. `... RETURNING ...`); `run` runs a
|
|
13
|
-
* write and reports `rowsAffected` — the matched-rows count that drives the
|
|
14
|
-
* MySQL optimistic-concurrency guard (which has no `RETURNING`).
|
|
15
|
-
*
|
|
16
|
-
* Note: companion writes (aggregate/rank/FTS/CDC) run as separate sequential
|
|
17
|
-
* statements after the row write on every engine, so they share D1's
|
|
18
|
-
* at-least-once caveat — there is no cross-statement transaction here.
|
|
19
|
-
*/
|
|
8
|
+
* The async SQL surface the store core consumes. Satisfied by a
|
|
9
|
+
* `D1Session`/`D1Client` (D1), a `node:sqlite` adapter (tests), or a
|
|
10
|
+
* Hyperdrive-backed `postgres`/`pg`/`mysql2` driver (PlanetScale).
|
|
11
|
+
*
|
|
12
|
+
* `all` runs a row-returning statement (incl. `... RETURNING ...`); `run` runs a
|
|
13
|
+
* write and reports `rowsAffected` — the matched-rows count that drives the
|
|
14
|
+
* MySQL optimistic-concurrency guard (which has no `RETURNING`).
|
|
15
|
+
*
|
|
16
|
+
* Note: companion writes (aggregate/rank/FTS/CDC) run as separate sequential
|
|
17
|
+
* statements after the row write on every engine, so they share D1's
|
|
18
|
+
* at-least-once caveat — there is no cross-statement transaction here.
|
|
19
|
+
*/
|
|
20
20
|
interface SqlExec {
|
|
21
21
|
all: (sql: string, params: ReadonlyArray<unknown>) => Promise<Record<string, unknown>[]>;
|
|
22
22
|
run: (sql: string, params: ReadonlyArray<unknown>) => Promise<SqlRunResult>;
|
|
@@ -26,19 +26,19 @@ interface SqlDialect {
|
|
|
26
26
|
/** Affected-rows extractor for the OCC fallback when `supportsReturning` is false (MySQL). */
|
|
27
27
|
affectedRows?: (result: SqlRunResult) => number;
|
|
28
28
|
/**
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
* Storage SQL column type for a validator `kind`. SQLite affinity
|
|
30
|
+
* (`TEXT`/`INTEGER`/`REAL`/`BLOB`); Postgres `TEXT`/`DOUBLE PRECISION`/
|
|
31
|
+
* `BOOLEAN`/`JSONB`/`BYTEA`; MySQL `VARCHAR(255)`/`TEXT`/`DOUBLE`/
|
|
32
|
+
* `TINYINT(1)`/`JSON`/`LONGBLOB`.
|
|
33
|
+
*/
|
|
34
34
|
columnType: (kind: string | undefined) => string;
|
|
35
35
|
/**
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
* Engine SQL types for the **internal companion tables** (aggregate / rank /
|
|
37
|
+
* CDC), which are built from raw SQL types, not validator kinds. SQLite uses
|
|
38
|
+
* `TEXT`/`REAL`/`INTEGER`/`BLOB` and `INTEGER PRIMARY KEY AUTOINCREMENT`;
|
|
39
|
+
* Postgres `TEXT`/`DOUBLE PRECISION`/`INTEGER`/`BYTEA` + `BIGSERIAL`; MySQL
|
|
40
|
+
* needs a bounded `VARCHAR` key, `DOUBLE`, `LONGBLOB`, `AUTO_INCREMENT`.
|
|
41
|
+
*/
|
|
42
42
|
companionTypes: {
|
|
43
43
|
autoincrementPrimaryKey: string;
|
|
44
44
|
integer: string;
|
|
@@ -47,18 +47,18 @@ interface SqlDialect {
|
|
|
47
47
|
text: string;
|
|
48
48
|
};
|
|
49
49
|
/**
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
* Map a stored value back to its JS form, by effective validator `kind`
|
|
51
|
+
* (inverse of `encode`). NOTE: currently **unused** by the store core, which
|
|
52
|
+
* hard-codes `sqliteDecode` in `decodeGlobalRow` on every engine. Kept on the
|
|
53
|
+
* seam for a future engine-native codec; an override here does not run today.
|
|
54
|
+
*/
|
|
55
55
|
decode: (value: unknown, kind: string | undefined) => unknown;
|
|
56
56
|
/**
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
57
|
+
* Map a JS value to its bound storage form (boolean→1/0, bigint→string,
|
|
58
|
+
* object→JSON on SQLite). NOTE: currently **unused** by the store core, which
|
|
59
|
+
* hard-codes `sqliteEncode` as `serializeColumnValue` on every engine. Kept on
|
|
60
|
+
* the seam for a future engine-native codec; an override here does not run today.
|
|
61
|
+
*/
|
|
62
62
|
encode: (value: unknown) => unknown;
|
|
63
63
|
/** The framework columns every global table carries — the `id` primary key and `_creationTime` — as `{ name, type }` so the DDL builder can quote each name through the engine's dialect. */
|
|
64
64
|
frameworkColumns: () => ReadonlyArray<{
|
|
@@ -66,12 +66,12 @@ interface SqlDialect {
|
|
|
66
66
|
type: string;
|
|
67
67
|
}>;
|
|
68
68
|
/**
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
69
|
+
* Optional: the key-prefix length an indexed column of this `kind` needs.
|
|
70
|
+
* MySQL/InnoDB can't index a `TEXT`/`LONGTEXT`/`BLOB` column without a prefix
|
|
71
|
+
* (the store appends `(<n>)` to the column reference); SQLite/Postgres index
|
|
72
|
+
* text columns directly and omit this hook (or return `undefined`). `kind` is
|
|
73
|
+
* the column's effective validator kind.
|
|
74
|
+
*/
|
|
75
75
|
indexKeyPrefix?: (kind: string | undefined) => number | undefined;
|
|
76
76
|
/** True when an `error` thrown by a write is a UNIQUE-constraint breach (mapped to a 409 ConflictError). */
|
|
77
77
|
isUniqueViolation: (error: unknown) => boolean;
|
|
@@ -80,13 +80,13 @@ interface SqlDialect {
|
|
|
80
80
|
/** True when the engine supports `UPDATE/DELETE ... RETURNING` (SQLite/PG yes, MySQL no → use `affectedRows`). */
|
|
81
81
|
supportsReturning: boolean;
|
|
82
82
|
/**
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
83
|
+
* The catalog probe for whether a physical `table` exists — backs the opt-in
|
|
84
|
+
* companion-table (`__agg_`/`__rank_`) existence checks. Returns a drizzle
|
|
85
|
+
* {@link SQL} (a non-empty result ⇒ the table exists) so it renders through
|
|
86
|
+
* the same per-engine path as every other statement, never a hand-built
|
|
87
|
+
* placeholder string. SQLite reads `sqlite_master`; Postgres/MySQL read
|
|
88
|
+
* `information_schema.tables`.
|
|
89
|
+
*/
|
|
90
90
|
tableExists: (table: string) => SQL;
|
|
91
91
|
}
|
|
92
92
|
export { SqlDialect, SqlExec, SqlRunResult };
|
package/dist/index.d.mts
CHANGED
|
@@ -3,118 +3,118 @@ import { SqlDialect, SqlRunResult } from "./dialect.mjs";
|
|
|
3
3
|
export type { SqlExec } from "./dialect.mjs";
|
|
4
4
|
import 'drizzle-orm';
|
|
5
5
|
/**
|
|
6
|
-
* Async SQL surface the D1 ORM needs: `all` for reads, `run` for writes.
|
|
7
|
-
* Satisfied by a `D1Session`/`D1Client` in production and a `node:sqlite`
|
|
8
|
-
* adapter in tests, so the query logic runs against a real SQLite engine.
|
|
9
|
-
*/
|
|
6
|
+
* Async SQL surface the D1 ORM needs: `all` for reads, `run` for writes.
|
|
7
|
+
* Satisfied by a `D1Session`/`D1Client` in production and a `node:sqlite`
|
|
8
|
+
* adapter in tests, so the query logic runs against a real SQLite engine.
|
|
9
|
+
*/
|
|
10
10
|
interface SqlCtxExec {
|
|
11
11
|
all: (sql: string, parameters: ReadonlyArray<unknown>) => Promise<Record<string, unknown>[]>;
|
|
12
12
|
run: (sql: string, parameters: ReadonlyArray<unknown>) => Promise<SqlRunResult | void>;
|
|
13
13
|
}
|
|
14
14
|
interface SqlCtxDbOptions {
|
|
15
15
|
/**
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
* Resolved request auth handed to `.serverDefault(fn)` column factories so
|
|
17
|
+
* server-trusted columns (owner/tenant ids) stamp from the verified caller,
|
|
18
|
+
* never the client. The generated worker passes the per-request identity;
|
|
19
|
+
* absent it, server-trusted columns stamp the anonymous slice (`userId: null`).
|
|
20
|
+
*/
|
|
21
21
|
auth?: ServerDefaultContextLike["auth"];
|
|
22
22
|
/**
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
* Opt into change-data-capture: when `true`, every committed write appends a
|
|
24
|
+
* post-image to the `__cdc_log` table (created lazily alongside the other
|
|
25
|
+
* companion tables). Backs CDC streaming export for `.global()` tables — the
|
|
26
|
+
* log is for export/CDC consumers, NOT point-in-time recovery: D1's PITR is
|
|
27
|
+
* the platform's own Time Travel (`wrangler d1 time-travel restore`), an
|
|
28
|
+
* atomic restore, not a changelog replay. Leave undefined for zero-cost
|
|
29
|
+
* legacy behaviour.
|
|
30
|
+
*/
|
|
31
31
|
cdc?: boolean;
|
|
32
32
|
clock?: () => number;
|
|
33
33
|
/**
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
* Cross-shard counter for **reverse cross-backend relations** — the `_count`
|
|
35
|
+
* mirror of the `crossShardReader` option below.
|
|
36
|
+
*/
|
|
37
37
|
crossShardCounter?: DatabaseWriterLike["count"];
|
|
38
38
|
/**
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
39
|
+
* Optional cross-shard reader for **reverse cross-backend relations**: a
|
|
40
|
+
* `.global()` (D1) parent loading a shard-local (`.shardBy()`/root) child.
|
|
41
|
+
* Such a child's rows are partitioned across every shard DO, so the local D1
|
|
42
|
+
* writer can't resolve it. When provided, the relation loader routes the
|
|
43
|
+
* child's read through this (the host wires it to the Query Coordinator's
|
|
44
|
+
* RLS-correct `fanOut`, with identity forwarded so each shard applies its own
|
|
45
|
+
* RLS). Absent it, loading such a relation throws a clear "not supported"
|
|
46
|
+
* error (legacy behaviour). The forward direction (shard-local parent →
|
|
47
|
+
* global child) and same-backend relations never touch this.
|
|
48
|
+
*/
|
|
49
49
|
crossShardReader?: DatabaseWriterLike["findMany"];
|
|
50
50
|
/**
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
* The SQL dialect that shapes every statement (identifier quoting, value
|
|
52
|
+
* encode/decode, column types, upserts, RETURNING vs affected-rows).
|
|
53
|
+
* `@lunora/d1` passes its `sqliteDialect`; the PlanetScale/Hyperdrive backend
|
|
54
|
+
* passes its Postgres/MySQL dialect. Required — the core is engine-blind.
|
|
55
|
+
*/
|
|
56
56
|
dialect: SqlDialect;
|
|
57
57
|
exec: SqlCtxExec;
|
|
58
58
|
idGenerator?: () => string;
|
|
59
59
|
/**
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
* Ceiling on the number of child join keys a relation-crossing `where`
|
|
61
|
+
* predicate may materialize before the semijoin pre-resolver fails closed
|
|
62
|
+
* (`relation predicate … exceeding the N-key limit`). D1 has no EXISTS
|
|
63
|
+
* push-down, so an overflow here can only fail closed — never truncate the
|
|
64
|
+
* `IN (...)` and silently mis-match. Defaults to the pre-resolver's shared
|
|
65
|
+
* key cap when omitted.
|
|
66
|
+
*/
|
|
67
67
|
maxRelationKeys?: number;
|
|
68
68
|
/**
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
* Scheduler exposed to global-table trigger handlers as `ctx.scheduler`.
|
|
70
|
+
* Absent it, `ctx.scheduler` is a stub that throws on use — pass one when
|
|
71
|
+
* triggers on `.global()` tables need to enqueue follow-up work.
|
|
72
|
+
*/
|
|
73
73
|
scheduler?: SchedulerLike;
|
|
74
74
|
schema: SchemaLike;
|
|
75
75
|
}
|
|
76
76
|
/**
|
|
77
|
-
* Decode a SELECTed row back into a document: `id` → `_id`, `_creationTime`
|
|
78
|
-
* preserved, and every column run through the shared {@link sqliteDecode} so the
|
|
79
|
-
* stored form is reversed back into its JS shape. Exported so the data-browser
|
|
80
|
-
* (`introspect.ts`) and admin export/import paths share the exact same decode.
|
|
81
|
-
*
|
|
82
|
-
* The decode is engine-agnostic: every backend stores SQLite-shaped values
|
|
83
|
-
* (boolean → 1/0, JSON → text, bigint → decimal string), and `sqliteDecode` is
|
|
84
|
-
* robust to a driver returning either the stored string OR a natively-parsed
|
|
85
|
-
* value (e.g. mysql2 returns JSON columns pre-parsed) — so the same decoder is
|
|
86
|
-
* correct on SQLite, Postgres and MySQL.
|
|
87
|
-
*/
|
|
77
|
+
* Decode a SELECTed row back into a document: `id` → `_id`, `_creationTime`
|
|
78
|
+
* preserved, and every column run through the shared {@link sqliteDecode} so the
|
|
79
|
+
* stored form is reversed back into its JS shape. Exported so the data-browser
|
|
80
|
+
* (`introspect.ts`) and admin export/import paths share the exact same decode.
|
|
81
|
+
*
|
|
82
|
+
* The decode is engine-agnostic: every backend stores SQLite-shaped values
|
|
83
|
+
* (boolean → 1/0, JSON → text, bigint → decimal string), and `sqliteDecode` is
|
|
84
|
+
* robust to a driver returning either the stored string OR a natively-parsed
|
|
85
|
+
* value (e.g. mysql2 returns JSON columns pre-parsed) — so the same decoder is
|
|
86
|
+
* correct on SQLite, Postgres and MySQL.
|
|
87
|
+
*/
|
|
88
88
|
declare const decodeGlobalRow: (definition: TableDefinitionLike, row: Record<string, unknown>) => Record<string, unknown>;
|
|
89
89
|
declare const runSqlGlobalTableMigrations: (exec: SqlCtxExec, schema: SchemaLike, dialect: SqlDialect) => Promise<void>;
|
|
90
90
|
/**
|
|
91
|
-
* Materialize the `__agg_<index>` companion tables for every declared
|
|
92
|
-
* `aggregateIndex` on a global table. Global tables in Lunora ship their own
|
|
93
|
-
* DDL — counter tables are opt-in so production hosts can decide where they
|
|
94
|
-
* live. Tests and dev hosts can call this once after their schema migration to
|
|
95
|
-
* unlock O(1) counts.
|
|
96
|
-
*
|
|
97
|
-
* Idempotent (`CREATE TABLE IF NOT EXISTS`).
|
|
98
|
-
*/
|
|
91
|
+
* Materialize the `__agg_<index>` companion tables for every declared
|
|
92
|
+
* `aggregateIndex` on a global table. Global tables in Lunora ship their own
|
|
93
|
+
* DDL — counter tables are opt-in so production hosts can decide where they
|
|
94
|
+
* live. Tests and dev hosts can call this once after their schema migration to
|
|
95
|
+
* unlock O(1) counts.
|
|
96
|
+
*
|
|
97
|
+
* Idempotent (`CREATE TABLE IF NOT EXISTS`).
|
|
98
|
+
*/
|
|
99
99
|
declare const runSqlAggregateMigrations: (exec: SqlCtxExec, schema: SchemaLike, dialect: SqlDialect) => Promise<void>;
|
|
100
100
|
/**
|
|
101
|
-
* Materialize the `__rank_<index>` companion tables for every declared
|
|
102
|
-
* `rankIndex` on a global table. Mirrors `runSqlAggregateMigrations` — same
|
|
103
|
-
* opt-in pattern so production hosts decide whether to spend the DDL.
|
|
104
|
-
*
|
|
105
|
-
* Idempotent (`CREATE TABLE IF NOT EXISTS` + `createIndexIfNotExists`).
|
|
106
|
-
*/
|
|
101
|
+
* Materialize the `__rank_<index>` companion tables for every declared
|
|
102
|
+
* `rankIndex` on a global table. Mirrors `runSqlAggregateMigrations` — same
|
|
103
|
+
* opt-in pattern so production hosts decide whether to spend the DDL.
|
|
104
|
+
*
|
|
105
|
+
* Idempotent (`CREATE TABLE IF NOT EXISTS` + `createIndexIfNotExists`).
|
|
106
|
+
*/
|
|
107
107
|
declare const runSqlRankMigrations: (exec: SqlCtxExec, schema: SchemaLike, dialect: SqlDialect) => Promise<void>;
|
|
108
108
|
/**
|
|
109
|
-
* Materialize the `__fts_<index>` FTS5 shadow tables for every declared
|
|
110
|
-
* `.searchIndex()` on a global table. Mirrors `runSqlAggregateMigrations` — same
|
|
111
|
-
* opt-in pattern so production hosts decide whether to spend the DDL. Only runs
|
|
112
|
-
* on engines that ship FTS5 (D1 does; the `node:sqlite` test runner doesn't,
|
|
113
|
-
* where `.search()` transparently falls back to a scan). `__text__` holds the
|
|
114
|
-
* indexed field; `__id__` (UNINDEXED) joins back to the row.
|
|
115
|
-
*
|
|
116
|
-
* Idempotent (`CREATE VIRTUAL TABLE IF NOT EXISTS`).
|
|
117
|
-
*/
|
|
109
|
+
* Materialize the `__fts_<index>` FTS5 shadow tables for every declared
|
|
110
|
+
* `.searchIndex()` on a global table. Mirrors `runSqlAggregateMigrations` — same
|
|
111
|
+
* opt-in pattern so production hosts decide whether to spend the DDL. Only runs
|
|
112
|
+
* on engines that ship FTS5 (D1 does; the `node:sqlite` test runner doesn't,
|
|
113
|
+
* where `.search()` transparently falls back to a scan). `__text__` holds the
|
|
114
|
+
* indexed field; `__id__` (UNINDEXED) joins back to the row.
|
|
115
|
+
*
|
|
116
|
+
* Idempotent (`CREATE VIRTUAL TABLE IF NOT EXISTS`).
|
|
117
|
+
*/
|
|
118
118
|
declare const runSqlSearchMigrations: (exec: SqlCtxExec, schema: SchemaLike, dialect: SqlDialect) => Promise<void>;
|
|
119
119
|
/** One change-data-capture entry: a committed mutation, in monotonic `seq` order. Mirrors the DO twin. */
|
|
120
120
|
interface CdcChange {
|
|
@@ -131,9 +131,9 @@ interface CdcChange {
|
|
|
131
131
|
/** Create the `__cdc_log` table. Idempotent; only run when CDC is enabled. */
|
|
132
132
|
declare const runSqlCdcMigration: (exec: SqlCtxExec, dialect: SqlDialect) => Promise<void>;
|
|
133
133
|
/**
|
|
134
|
-
* Read changelog entries newer than `sinceSeq` in commit order, up to `limit`
|
|
135
|
-
* (clamped to [1, 10000]); plus the cursor to resume from.
|
|
136
|
-
*/
|
|
134
|
+
* Read changelog entries newer than `sinceSeq` in commit order, up to `limit`
|
|
135
|
+
* (clamped to [1, 10000]); plus the cursor to resume from.
|
|
136
|
+
*/
|
|
137
137
|
declare const readSqlCdcChanges: (exec: SqlCtxExec, options: {
|
|
138
138
|
limit?: number;
|
|
139
139
|
sinceSeq?: number;
|
|
@@ -151,30 +151,30 @@ declare const tryJsonParse: (raw: string) => unknown;
|
|
|
151
151
|
/** Decode a `bigint` column: a decimal string back into a `BigInt`, else verbatim. */
|
|
152
152
|
declare const decodeBigint: (raw: unknown) => unknown;
|
|
153
153
|
/**
|
|
154
|
-
* Resolve the *effective* storage kind of a column validator. Encoding keys off
|
|
155
|
-
* the runtime value's JS type, so a `v.optional(inner)` column stores its
|
|
156
|
-
* present value exactly as `inner` would. The validator's own `kind` is
|
|
157
|
-
* `"optional"`, which hides that — unwrap to the inner validator's kind so the
|
|
158
|
-
* decode reverses the real storage form. The inner validator is stashed on
|
|
159
|
-
* `_meta.inner` by `@lunora/values`' `createValidator`.
|
|
160
|
-
*/
|
|
154
|
+
* Resolve the *effective* storage kind of a column validator. Encoding keys off
|
|
155
|
+
* the runtime value's JS type, so a `v.optional(inner)` column stores its
|
|
156
|
+
* present value exactly as `inner` would. The validator's own `kind` is
|
|
157
|
+
* `"optional"`, which hides that — unwrap to the inner validator's kind so the
|
|
158
|
+
* decode reverses the real storage form. The inner validator is stashed on
|
|
159
|
+
* `_meta.inner` by `@lunora/values`' `createValidator`.
|
|
160
|
+
*/
|
|
161
161
|
declare const effectiveColumnKind: (validator: ValidatorLike) => string | undefined;
|
|
162
162
|
/**
|
|
163
|
-
* Inverse of {@link sqliteEncode}: map a SQLite storage value back onto its JS
|
|
164
|
-
* form, driven by the field's effective validator `kind`:
|
|
165
|
-
*
|
|
166
|
-
* - `boolean`: 1/0 → true/false (SQLite has no boolean type).
|
|
167
|
-
* - `bigint`: decimal string → `BigInt`.
|
|
168
|
-
* - `object`/`array`/`record`: JSON string → parsed value.
|
|
169
|
-
* - `union`/`any`: parsed back only when the stored string is a JSON non-scalar
|
|
170
|
-
* (a scalar union member round-trips through SQLite's native column type).
|
|
171
|
-
* CAVEAT: a union/any member is stored verbatim by {@link sqliteEncode}, so a
|
|
172
|
-
* legitimate *string* value that itself looks like JSON (`'{"a":1}'`, `'[1,2]'`)
|
|
173
|
-
* is ambiguous on read and decodes back to the parsed object/array, not the
|
|
174
|
-
* original string. This is inherent to sharing one TEXT column between a string
|
|
175
|
-
* and an object member; disambiguating would require a breaking storage-format
|
|
176
|
-
* change (tagging encoded non-scalars), so it is documented rather than fixed.
|
|
177
|
-
* - everything else (string/number/date/timestamp/id/literal): verbatim.
|
|
178
|
-
*/
|
|
163
|
+
* Inverse of {@link sqliteEncode}: map a SQLite storage value back onto its JS
|
|
164
|
+
* form, driven by the field's effective validator `kind`:
|
|
165
|
+
*
|
|
166
|
+
* - `boolean`: 1/0 → true/false (SQLite has no boolean type).
|
|
167
|
+
* - `bigint`: decimal string → `BigInt`.
|
|
168
|
+
* - `object`/`array`/`record`: JSON string → parsed value.
|
|
169
|
+
* - `union`/`any`: parsed back only when the stored string is a JSON non-scalar
|
|
170
|
+
* (a scalar union member round-trips through SQLite's native column type).
|
|
171
|
+
* CAVEAT: a union/any member is stored verbatim by {@link sqliteEncode}, so a
|
|
172
|
+
* legitimate *string* value that itself looks like JSON (`'{"a":1}'`, `'[1,2]'`)
|
|
173
|
+
* is ambiguous on read and decodes back to the parsed object/array, not the
|
|
174
|
+
* original string. This is inherent to sharing one TEXT column between a string
|
|
175
|
+
* and an object member; disambiguating would require a breaking storage-format
|
|
176
|
+
* change (tagging encoded non-scalars), so it is documented rather than fixed.
|
|
177
|
+
* - everything else (string/number/date/timestamp/id/literal): verbatim.
|
|
178
|
+
*/
|
|
179
179
|
declare const sqliteDecode: (raw: unknown, kind: string | undefined) => unknown;
|
|
180
180
|
export { type SqlCtxDbOptions, type SqlCtxExec, type SqlDialect, type SqlRunResult, createSqlCtxDb, decodeBigint, decodeGlobalRow, effectiveColumnKind, readSqlCdcChanges, runSqlAggregateMigrations, runSqlCdcMigration, runSqlGlobalTableMigrations, runSqlRankMigrations, runSqlSearchMigrations, sqliteDecode, sqliteEncode, trimSqlCdcChanges, tryJsonParse };
|
package/dist/index.d.ts
CHANGED
|
@@ -3,118 +3,118 @@ import { SqlDialect, SqlRunResult } from "./dialect.js";
|
|
|
3
3
|
export type { SqlExec } from "./dialect.js";
|
|
4
4
|
import 'drizzle-orm';
|
|
5
5
|
/**
|
|
6
|
-
* Async SQL surface the D1 ORM needs: `all` for reads, `run` for writes.
|
|
7
|
-
* Satisfied by a `D1Session`/`D1Client` in production and a `node:sqlite`
|
|
8
|
-
* adapter in tests, so the query logic runs against a real SQLite engine.
|
|
9
|
-
*/
|
|
6
|
+
* Async SQL surface the D1 ORM needs: `all` for reads, `run` for writes.
|
|
7
|
+
* Satisfied by a `D1Session`/`D1Client` in production and a `node:sqlite`
|
|
8
|
+
* adapter in tests, so the query logic runs against a real SQLite engine.
|
|
9
|
+
*/
|
|
10
10
|
interface SqlCtxExec {
|
|
11
11
|
all: (sql: string, parameters: ReadonlyArray<unknown>) => Promise<Record<string, unknown>[]>;
|
|
12
12
|
run: (sql: string, parameters: ReadonlyArray<unknown>) => Promise<SqlRunResult | void>;
|
|
13
13
|
}
|
|
14
14
|
interface SqlCtxDbOptions {
|
|
15
15
|
/**
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
* Resolved request auth handed to `.serverDefault(fn)` column factories so
|
|
17
|
+
* server-trusted columns (owner/tenant ids) stamp from the verified caller,
|
|
18
|
+
* never the client. The generated worker passes the per-request identity;
|
|
19
|
+
* absent it, server-trusted columns stamp the anonymous slice (`userId: null`).
|
|
20
|
+
*/
|
|
21
21
|
auth?: ServerDefaultContextLike["auth"];
|
|
22
22
|
/**
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
* Opt into change-data-capture: when `true`, every committed write appends a
|
|
24
|
+
* post-image to the `__cdc_log` table (created lazily alongside the other
|
|
25
|
+
* companion tables). Backs CDC streaming export for `.global()` tables — the
|
|
26
|
+
* log is for export/CDC consumers, NOT point-in-time recovery: D1's PITR is
|
|
27
|
+
* the platform's own Time Travel (`wrangler d1 time-travel restore`), an
|
|
28
|
+
* atomic restore, not a changelog replay. Leave undefined for zero-cost
|
|
29
|
+
* legacy behaviour.
|
|
30
|
+
*/
|
|
31
31
|
cdc?: boolean;
|
|
32
32
|
clock?: () => number;
|
|
33
33
|
/**
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
* Cross-shard counter for **reverse cross-backend relations** — the `_count`
|
|
35
|
+
* mirror of the `crossShardReader` option below.
|
|
36
|
+
*/
|
|
37
37
|
crossShardCounter?: DatabaseWriterLike["count"];
|
|
38
38
|
/**
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
39
|
+
* Optional cross-shard reader for **reverse cross-backend relations**: a
|
|
40
|
+
* `.global()` (D1) parent loading a shard-local (`.shardBy()`/root) child.
|
|
41
|
+
* Such a child's rows are partitioned across every shard DO, so the local D1
|
|
42
|
+
* writer can't resolve it. When provided, the relation loader routes the
|
|
43
|
+
* child's read through this (the host wires it to the Query Coordinator's
|
|
44
|
+
* RLS-correct `fanOut`, with identity forwarded so each shard applies its own
|
|
45
|
+
* RLS). Absent it, loading such a relation throws a clear "not supported"
|
|
46
|
+
* error (legacy behaviour). The forward direction (shard-local parent →
|
|
47
|
+
* global child) and same-backend relations never touch this.
|
|
48
|
+
*/
|
|
49
49
|
crossShardReader?: DatabaseWriterLike["findMany"];
|
|
50
50
|
/**
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
* The SQL dialect that shapes every statement (identifier quoting, value
|
|
52
|
+
* encode/decode, column types, upserts, RETURNING vs affected-rows).
|
|
53
|
+
* `@lunora/d1` passes its `sqliteDialect`; the PlanetScale/Hyperdrive backend
|
|
54
|
+
* passes its Postgres/MySQL dialect. Required — the core is engine-blind.
|
|
55
|
+
*/
|
|
56
56
|
dialect: SqlDialect;
|
|
57
57
|
exec: SqlCtxExec;
|
|
58
58
|
idGenerator?: () => string;
|
|
59
59
|
/**
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
* Ceiling on the number of child join keys a relation-crossing `where`
|
|
61
|
+
* predicate may materialize before the semijoin pre-resolver fails closed
|
|
62
|
+
* (`relation predicate … exceeding the N-key limit`). D1 has no EXISTS
|
|
63
|
+
* push-down, so an overflow here can only fail closed — never truncate the
|
|
64
|
+
* `IN (...)` and silently mis-match. Defaults to the pre-resolver's shared
|
|
65
|
+
* key cap when omitted.
|
|
66
|
+
*/
|
|
67
67
|
maxRelationKeys?: number;
|
|
68
68
|
/**
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
* Scheduler exposed to global-table trigger handlers as `ctx.scheduler`.
|
|
70
|
+
* Absent it, `ctx.scheduler` is a stub that throws on use — pass one when
|
|
71
|
+
* triggers on `.global()` tables need to enqueue follow-up work.
|
|
72
|
+
*/
|
|
73
73
|
scheduler?: SchedulerLike;
|
|
74
74
|
schema: SchemaLike;
|
|
75
75
|
}
|
|
76
76
|
/**
|
|
77
|
-
* Decode a SELECTed row back into a document: `id` → `_id`, `_creationTime`
|
|
78
|
-
* preserved, and every column run through the shared {@link sqliteDecode} so the
|
|
79
|
-
* stored form is reversed back into its JS shape. Exported so the data-browser
|
|
80
|
-
* (`introspect.ts`) and admin export/import paths share the exact same decode.
|
|
81
|
-
*
|
|
82
|
-
* The decode is engine-agnostic: every backend stores SQLite-shaped values
|
|
83
|
-
* (boolean → 1/0, JSON → text, bigint → decimal string), and `sqliteDecode` is
|
|
84
|
-
* robust to a driver returning either the stored string OR a natively-parsed
|
|
85
|
-
* value (e.g. mysql2 returns JSON columns pre-parsed) — so the same decoder is
|
|
86
|
-
* correct on SQLite, Postgres and MySQL.
|
|
87
|
-
*/
|
|
77
|
+
* Decode a SELECTed row back into a document: `id` → `_id`, `_creationTime`
|
|
78
|
+
* preserved, and every column run through the shared {@link sqliteDecode} so the
|
|
79
|
+
* stored form is reversed back into its JS shape. Exported so the data-browser
|
|
80
|
+
* (`introspect.ts`) and admin export/import paths share the exact same decode.
|
|
81
|
+
*
|
|
82
|
+
* The decode is engine-agnostic: every backend stores SQLite-shaped values
|
|
83
|
+
* (boolean → 1/0, JSON → text, bigint → decimal string), and `sqliteDecode` is
|
|
84
|
+
* robust to a driver returning either the stored string OR a natively-parsed
|
|
85
|
+
* value (e.g. mysql2 returns JSON columns pre-parsed) — so the same decoder is
|
|
86
|
+
* correct on SQLite, Postgres and MySQL.
|
|
87
|
+
*/
|
|
88
88
|
declare const decodeGlobalRow: (definition: TableDefinitionLike, row: Record<string, unknown>) => Record<string, unknown>;
|
|
89
89
|
declare const runSqlGlobalTableMigrations: (exec: SqlCtxExec, schema: SchemaLike, dialect: SqlDialect) => Promise<void>;
|
|
90
90
|
/**
|
|
91
|
-
* Materialize the `__agg_<index>` companion tables for every declared
|
|
92
|
-
* `aggregateIndex` on a global table. Global tables in Lunora ship their own
|
|
93
|
-
* DDL — counter tables are opt-in so production hosts can decide where they
|
|
94
|
-
* live. Tests and dev hosts can call this once after their schema migration to
|
|
95
|
-
* unlock O(1) counts.
|
|
96
|
-
*
|
|
97
|
-
* Idempotent (`CREATE TABLE IF NOT EXISTS`).
|
|
98
|
-
*/
|
|
91
|
+
* Materialize the `__agg_<index>` companion tables for every declared
|
|
92
|
+
* `aggregateIndex` on a global table. Global tables in Lunora ship their own
|
|
93
|
+
* DDL — counter tables are opt-in so production hosts can decide where they
|
|
94
|
+
* live. Tests and dev hosts can call this once after their schema migration to
|
|
95
|
+
* unlock O(1) counts.
|
|
96
|
+
*
|
|
97
|
+
* Idempotent (`CREATE TABLE IF NOT EXISTS`).
|
|
98
|
+
*/
|
|
99
99
|
declare const runSqlAggregateMigrations: (exec: SqlCtxExec, schema: SchemaLike, dialect: SqlDialect) => Promise<void>;
|
|
100
100
|
/**
|
|
101
|
-
* Materialize the `__rank_<index>` companion tables for every declared
|
|
102
|
-
* `rankIndex` on a global table. Mirrors `runSqlAggregateMigrations` — same
|
|
103
|
-
* opt-in pattern so production hosts decide whether to spend the DDL.
|
|
104
|
-
*
|
|
105
|
-
* Idempotent (`CREATE TABLE IF NOT EXISTS` + `createIndexIfNotExists`).
|
|
106
|
-
*/
|
|
101
|
+
* Materialize the `__rank_<index>` companion tables for every declared
|
|
102
|
+
* `rankIndex` on a global table. Mirrors `runSqlAggregateMigrations` — same
|
|
103
|
+
* opt-in pattern so production hosts decide whether to spend the DDL.
|
|
104
|
+
*
|
|
105
|
+
* Idempotent (`CREATE TABLE IF NOT EXISTS` + `createIndexIfNotExists`).
|
|
106
|
+
*/
|
|
107
107
|
declare const runSqlRankMigrations: (exec: SqlCtxExec, schema: SchemaLike, dialect: SqlDialect) => Promise<void>;
|
|
108
108
|
/**
|
|
109
|
-
* Materialize the `__fts_<index>` FTS5 shadow tables for every declared
|
|
110
|
-
* `.searchIndex()` on a global table. Mirrors `runSqlAggregateMigrations` — same
|
|
111
|
-
* opt-in pattern so production hosts decide whether to spend the DDL. Only runs
|
|
112
|
-
* on engines that ship FTS5 (D1 does; the `node:sqlite` test runner doesn't,
|
|
113
|
-
* where `.search()` transparently falls back to a scan). `__text__` holds the
|
|
114
|
-
* indexed field; `__id__` (UNINDEXED) joins back to the row.
|
|
115
|
-
*
|
|
116
|
-
* Idempotent (`CREATE VIRTUAL TABLE IF NOT EXISTS`).
|
|
117
|
-
*/
|
|
109
|
+
* Materialize the `__fts_<index>` FTS5 shadow tables for every declared
|
|
110
|
+
* `.searchIndex()` on a global table. Mirrors `runSqlAggregateMigrations` — same
|
|
111
|
+
* opt-in pattern so production hosts decide whether to spend the DDL. Only runs
|
|
112
|
+
* on engines that ship FTS5 (D1 does; the `node:sqlite` test runner doesn't,
|
|
113
|
+
* where `.search()` transparently falls back to a scan). `__text__` holds the
|
|
114
|
+
* indexed field; `__id__` (UNINDEXED) joins back to the row.
|
|
115
|
+
*
|
|
116
|
+
* Idempotent (`CREATE VIRTUAL TABLE IF NOT EXISTS`).
|
|
117
|
+
*/
|
|
118
118
|
declare const runSqlSearchMigrations: (exec: SqlCtxExec, schema: SchemaLike, dialect: SqlDialect) => Promise<void>;
|
|
119
119
|
/** One change-data-capture entry: a committed mutation, in monotonic `seq` order. Mirrors the DO twin. */
|
|
120
120
|
interface CdcChange {
|
|
@@ -131,9 +131,9 @@ interface CdcChange {
|
|
|
131
131
|
/** Create the `__cdc_log` table. Idempotent; only run when CDC is enabled. */
|
|
132
132
|
declare const runSqlCdcMigration: (exec: SqlCtxExec, dialect: SqlDialect) => Promise<void>;
|
|
133
133
|
/**
|
|
134
|
-
* Read changelog entries newer than `sinceSeq` in commit order, up to `limit`
|
|
135
|
-
* (clamped to [1, 10000]); plus the cursor to resume from.
|
|
136
|
-
*/
|
|
134
|
+
* Read changelog entries newer than `sinceSeq` in commit order, up to `limit`
|
|
135
|
+
* (clamped to [1, 10000]); plus the cursor to resume from.
|
|
136
|
+
*/
|
|
137
137
|
declare const readSqlCdcChanges: (exec: SqlCtxExec, options: {
|
|
138
138
|
limit?: number;
|
|
139
139
|
sinceSeq?: number;
|
|
@@ -151,30 +151,30 @@ declare const tryJsonParse: (raw: string) => unknown;
|
|
|
151
151
|
/** Decode a `bigint` column: a decimal string back into a `BigInt`, else verbatim. */
|
|
152
152
|
declare const decodeBigint: (raw: unknown) => unknown;
|
|
153
153
|
/**
|
|
154
|
-
* Resolve the *effective* storage kind of a column validator. Encoding keys off
|
|
155
|
-
* the runtime value's JS type, so a `v.optional(inner)` column stores its
|
|
156
|
-
* present value exactly as `inner` would. The validator's own `kind` is
|
|
157
|
-
* `"optional"`, which hides that — unwrap to the inner validator's kind so the
|
|
158
|
-
* decode reverses the real storage form. The inner validator is stashed on
|
|
159
|
-
* `_meta.inner` by `@lunora/values`' `createValidator`.
|
|
160
|
-
*/
|
|
154
|
+
* Resolve the *effective* storage kind of a column validator. Encoding keys off
|
|
155
|
+
* the runtime value's JS type, so a `v.optional(inner)` column stores its
|
|
156
|
+
* present value exactly as `inner` would. The validator's own `kind` is
|
|
157
|
+
* `"optional"`, which hides that — unwrap to the inner validator's kind so the
|
|
158
|
+
* decode reverses the real storage form. The inner validator is stashed on
|
|
159
|
+
* `_meta.inner` by `@lunora/values`' `createValidator`.
|
|
160
|
+
*/
|
|
161
161
|
declare const effectiveColumnKind: (validator: ValidatorLike) => string | undefined;
|
|
162
162
|
/**
|
|
163
|
-
* Inverse of {@link sqliteEncode}: map a SQLite storage value back onto its JS
|
|
164
|
-
* form, driven by the field's effective validator `kind`:
|
|
165
|
-
*
|
|
166
|
-
* - `boolean`: 1/0 → true/false (SQLite has no boolean type).
|
|
167
|
-
* - `bigint`: decimal string → `BigInt`.
|
|
168
|
-
* - `object`/`array`/`record`: JSON string → parsed value.
|
|
169
|
-
* - `union`/`any`: parsed back only when the stored string is a JSON non-scalar
|
|
170
|
-
* (a scalar union member round-trips through SQLite's native column type).
|
|
171
|
-
* CAVEAT: a union/any member is stored verbatim by {@link sqliteEncode}, so a
|
|
172
|
-
* legitimate *string* value that itself looks like JSON (`'{"a":1}'`, `'[1,2]'`)
|
|
173
|
-
* is ambiguous on read and decodes back to the parsed object/array, not the
|
|
174
|
-
* original string. This is inherent to sharing one TEXT column between a string
|
|
175
|
-
* and an object member; disambiguating would require a breaking storage-format
|
|
176
|
-
* change (tagging encoded non-scalars), so it is documented rather than fixed.
|
|
177
|
-
* - everything else (string/number/date/timestamp/id/literal): verbatim.
|
|
178
|
-
*/
|
|
163
|
+
* Inverse of {@link sqliteEncode}: map a SQLite storage value back onto its JS
|
|
164
|
+
* form, driven by the field's effective validator `kind`:
|
|
165
|
+
*
|
|
166
|
+
* - `boolean`: 1/0 → true/false (SQLite has no boolean type).
|
|
167
|
+
* - `bigint`: decimal string → `BigInt`.
|
|
168
|
+
* - `object`/`array`/`record`: JSON string → parsed value.
|
|
169
|
+
* - `union`/`any`: parsed back only when the stored string is a JSON non-scalar
|
|
170
|
+
* (a scalar union member round-trips through SQLite's native column type).
|
|
171
|
+
* CAVEAT: a union/any member is stored verbatim by {@link sqliteEncode}, so a
|
|
172
|
+
* legitimate *string* value that itself looks like JSON (`'{"a":1}'`, `'[1,2]'`)
|
|
173
|
+
* is ambiguous on read and decodes back to the parsed object/array, not the
|
|
174
|
+
* original string. This is inherent to sharing one TEXT column between a string
|
|
175
|
+
* and an object member; disambiguating would require a breaking storage-format
|
|
176
|
+
* change (tagging encoded non-scalars), so it is documented rather than fixed.
|
|
177
|
+
* - everything else (string/number/date/timestamp/id/literal): verbatim.
|
|
178
|
+
*/
|
|
179
179
|
declare const sqliteDecode: (raw: unknown, kind: string | undefined) => unknown;
|
|
180
180
|
export { type SqlCtxDbOptions, type SqlCtxExec, type SqlDialect, type SqlRunResult, createSqlCtxDb, decodeBigint, decodeGlobalRow, effectiveColumnKind, readSqlCdcChanges, runSqlAggregateMigrations, runSqlCdcMigration, runSqlGlobalTableMigrations, runSqlRankMigrations, runSqlSearchMigrations, sqliteDecode, sqliteEncode, trimSqlCdcChanges, tryJsonParse };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/sql-store",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.34",
|
|
4
4
|
"description": "Internal dialect-parameterized SQL store core for Lunora .global() backends (D1, PlanetScale)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -50,8 +50,8 @@
|
|
|
50
50
|
"access": "public"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@lunora/do": "1.0.0-alpha.
|
|
54
|
-
"@lunora/errors": "1.0.0-alpha.
|
|
53
|
+
"@lunora/do": "1.0.0-alpha.34",
|
|
54
|
+
"@lunora/errors": "1.0.0-alpha.6",
|
|
55
55
|
"drizzle-orm": "^0.45.2"
|
|
56
56
|
},
|
|
57
57
|
"engines": {
|