@orkestrel/database 0.0.1 → 0.0.2

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.
@@ -1,169 +0,0 @@
1
- import type { ColumnType, Condition, Criteria, Order, TableSchema } from '@src/core';
2
- import type { CompiledSQL } from './types.js';
3
- /**
4
- * Escape `\`, `%`, and `_` (each with a leading `\`) so a `starts` / `ends`
5
- * operand is matched literally under the `LIKE … ESCAPE '\'` clause.
6
- *
7
- * @param text - The raw operand text
8
- * @returns The text with LIKE metacharacters escaped
9
- *
10
- * @example
11
- * ```ts
12
- * escapeLike('50%_off') // '50\\%\\_off'
13
- * ```
14
- */
15
- export declare function escapeLike(text: string): string;
16
- /**
17
- * The declared storage type of a flat (string) column, read from the schema.
18
- *
19
- * @param column - The column name
20
- * @param schema - The table's schema
21
- * @returns The column's {@link ColumnType}, or `undefined` if the schema does not carry it
22
- *
23
- * @example
24
- * ```ts
25
- * declaredType('age', schema) // 'integer'
26
- * ```
27
- */
28
- export declare function declaredType(column: string, schema: TableSchema): ColumnType | undefined;
29
- /**
30
- * The storage type a nested (`json_extract`) operand encodes as, derived from its
31
- * RUNTIME value — NOT `json`.
32
- *
33
- * @remarks
34
- * `json_extract` returns the unquoted, natively-typed scalar (a JSON boolean as
35
- * `1` / `0`, a number as-is, a string as-is), so the operand must encode to that
36
- * same scalar to compare. A boolean → `'boolean'` (→ `1` / `0`); a number →
37
- * `'integer'` / `'real'`; a bigint → `'integer'`; a string → `'text'`; `null` /
38
- * `undefined` → `'text'` (encodes to `null`); an object / array → `'json'` (the
39
- * edge of comparing against a json subtree).
40
- *
41
- * @param value - The runtime operand value
42
- * @returns The {@link ColumnType} to encode it as
43
- *
44
- * @example
45
- * ```ts
46
- * valueType(true) // 'boolean'
47
- * valueType(9) // 'integer'
48
- * ```
49
- */
50
- export declare function valueType(value: unknown): ColumnType;
51
- /**
52
- * Compile one condition to its `<column> <operator>` SQL fragment and the params
53
- * it binds.
54
- *
55
- * @remarks
56
- * Every operand is run through `encodeValue`, so a bound value matches the SQL
57
- * the column side compiles to. A flat column encodes operands with its DECLARED
58
- * schema type (a flat `json` column → `JSON.stringify`); a nested `FieldPath`
59
- * encodes each operand as the NATIVE scalar `json_extract` returns, derived from
60
- * the operand's runtime type (per-operand, since `between` / `any` / `none` can
61
- * mix types). `any` / `none` collapse an empty list to a constant (`0` matches
62
- * nothing, `1` matches all) with no params. A nested field with a null/undefined
63
- * operand under `equals` / `not` compiles to `IS NULL` / `IS NOT NULL` (no bound
64
- * param) instead of `= ?` / `!= ?`, matching the engine's treatment of a
65
- * present-but-null nested value.
66
- *
67
- * @param condition - The condition to compile
68
- * @param schema - The table's schema (for declared column types)
69
- * @returns The SQL fragment and its bound parameters
70
- *
71
- * @example
72
- * ```ts
73
- * fragment({ column: 'age', operator: 'above', values: [18], connector: 'and' }, schema)
74
- * // { sql: '"age" > ?', params: [18] }
75
- * ```
76
- */
77
- export declare function fragment(condition: Condition, schema: TableSchema): CompiledSQL;
78
- /**
79
- * Fold the conditions into one WHERE clause, parenthesizing progressively
80
- * left-to-right so the grouping matches the engine's `matchesCriteria` fold.
81
- *
82
- * @remarks
83
- * The first condition's connector is ignored, per the {@link Condition} types.
84
- *
85
- * @param conditions - The conditions to fold
86
- * @param schema - The table's schema
87
- * @returns The `WHERE …` clause and its bound parameters, or an empty clause for zero conditions
88
- *
89
- * @example
90
- * ```ts
91
- * compileWhere([{ column: 'age', operator: 'from', values: [18], connector: 'and' }], schema)
92
- * // { sql: 'WHERE "age" >= ?', params: [18] }
93
- * ```
94
- */
95
- export declare function compileWhere(conditions: readonly Condition[], schema: TableSchema): CompiledSQL;
96
- /**
97
- * Compile the ORDER BY clause from the order terms, always ending with the
98
- * primary key as the final determinant.
99
- *
100
- * @remarks
101
- * The native `records` read then resolves ties in key order, matching a
102
- * primary-key-ordered `scan` and the core engine's stable `sortRows` over a
103
- * key-ordered scan (and IndexedDB's key-ordered reads), so a native read equals
104
- * the scan path (AGENTS §21 / §22 native ↔ engine parity). SQLite without an
105
- * `ORDER BY` returns rowid (insertion) order, and an explicit order alone breaks
106
- * ties by rowid too — both diverge from every key-ordered backend. The
107
- * tie-breaker is ASCENDING regardless of the explicit directions: the engine's
108
- * stable sort runs over key-ascending input, so equal rows stay in
109
- * ascending-key order whichever way the explicit terms point. Skipped when the
110
- * primary is already an explicit order term (no double-append).
111
- *
112
- * @param order - The explicit order terms, or `undefined`
113
- * @param schema - The table's schema (for the primary key)
114
- * @returns The `ORDER BY …` clause, or an empty string when there is nothing to order by
115
- *
116
- * @example
117
- * ```ts
118
- * compileOrder([{ column: 'age', direction: 'descending' }], schema)
119
- * // 'ORDER BY "age" DESC, "id"'
120
- * ```
121
- */
122
- export declare function compileOrder(order: readonly Order[] | undefined, schema: TableSchema): string;
123
- /**
124
- * Compile the LIMIT / OFFSET clause.
125
- *
126
- * @remarks
127
- * An offset without a limit uses `LIMIT -1` (SQLite's "no limit") so OFFSET is
128
- * still honored.
129
- *
130
- * @param limit - The maximum row count, or `undefined`
131
- * @param offset - The row count to skip, or `undefined`
132
- * @returns The `LIMIT …` clause and its bound parameters, or an empty clause when neither is set
133
- *
134
- * @example
135
- * ```ts
136
- * compilePage(undefined, 5) // { sql: 'LIMIT -1 OFFSET ?', params: [5] }
137
- * ```
138
- */
139
- export declare function compilePage(limit: number | undefined, offset: number | undefined): CompiledSQL;
140
- /**
141
- * Compile a {@link Criteria} into the SQL clause that follows a table name, with
142
- * its bound parameters in clause order.
143
- *
144
- * @remarks
145
- * The driver's native `records` / `count` path: it assembles
146
- * `[where, orderBy, limitOffset]` (each possibly empty) into one clause so a
147
- * `SELECT * FROM <table> <clause>` runs the whole read in the engine instead of
148
- * over a JS `scan`. The WHERE fold is parenthesized **left-to-right** to mirror
149
- * the core engine's `matchesCriteria` (not SQL's native AND-over-OR precedence),
150
- * so a native and an engine read return identical rows. Each operand is encoded
151
- * via `encodeValue`: a flat column uses its declared schema type, while a nested
152
- * `FieldPath` (a `json_extract` read) encodes each operand as the native scalar
153
- * the extract returns — derived from the operand's runtime type — so it compares.
154
- * The 15 operators map per the databases guide's operator table, with
155
- * `starts` / `ends` using `LIKE … ESCAPE '\'` and an empty `any` / `none` list
156
- * collapsing to a constant. A `undefined` criteria (or one with no parts)
157
- * compiles to an empty clause.
158
- *
159
- * @param criteria - The read specification, or `undefined` for all rows
160
- * @param schema - The table's schema (column types for operand encoding)
161
- * @returns The SQL tail and its bound parameters
162
- *
163
- * @example
164
- * ```ts
165
- * compileCriteria({ conditions: [{ column: 'age', operator: 'from', values: [18], connector: 'and' }] }, schema)
166
- * // { sql: 'WHERE "age" >= ? ORDER BY "id"', params: [18] }
167
- * ```
168
- */
169
- export declare function compileCriteria(criteria: Criteria | undefined, schema: TableSchema): CompiledSQL;
@@ -1,106 +0,0 @@
1
- import type { Criteria, DriverInterface, DriverMeta, Key, Migration, Row, TableSchema, TransactionInterface } from '@src/core';
2
- /**
3
- * A persistent {@link DriverInterface} backed by a single JSON file — the
4
- * reference {@link MemoryDriver} plus file load / flush.
5
- *
6
- * @remarks
7
- * A decorator, not a reimplementation: every primitive delegates to an inner
8
- * {@link MemoryDriver}, so querying, key-order `scan` / `keys`, and capture-replay
9
- * `snapshot` are inherited unchanged — this layer adds only persistence. `open`
10
- * loads the file into memory; every mutation (`write` / `delete` / `clear`) flushes
11
- * the whole store back. The file is one JSON object, `{ meta?: DriverMeta, tables: {
12
- * [name]: rows } }` — `meta` is present only once the store has been `stamp`ed
13
- * (an unstamped store serializes the old `{ tables }` shape, preserving
14
- * backward compatibility); a per-table array of rows, each row carrying its own
15
- * primary (the table contract), so the key is recovered on load with
16
- * {@link extractKey} and the file need not store it. The parsed JSON crosses the
17
- * boundary as `unknown` and is narrowed with {@link isRecord} / {@link extractKey},
18
- * never asserted (AGENTS §14): a missing, corrupt, or wrong-shaped file starts
19
- * empty rather than throwing, and a malformed row (or malformed `meta`) is
20
- * skipped/dropped rather than thrown on. It is scan-only — it implements none of
21
- * the optional native `records` / `count` / `aggregate` hooks, so the core engine
22
- * over `scan` answers every query. For development, small datasets, and portable /
23
- * inspectable data; for large or concurrent workloads reach for a SQLite-backed
24
- * driver.
25
- *
26
- * A failure in the write path ({@link JSONDriver.#serialize} — `mkdir` /
27
- * `writeFile` / `rename`) is wrapped and rethrown as `DatabaseError` `DRIVER`,
28
- * carrying the target `path` in its context; the read path ({@link
29
- * JSONDriver.#load}) tolerance above is a separate, deliberate contract and is
30
- * never touched by this wrapping.
31
- */
32
- export declare class JSONDriver implements DriverInterface {
33
- #private;
34
- constructor(path: string);
35
- open(schema: readonly TableSchema[]): Promise<void>;
36
- close(): Promise<void>;
37
- read(table: string, key: Key): Promise<Row | undefined>;
38
- write(table: string, key: Key, row: Row): Promise<void>;
39
- delete(table: string, key: Key): Promise<boolean>;
40
- keys(table: string): Promise<readonly Key[]>;
41
- scan(table: string): AsyncIterable<Row>;
42
- /**
43
- * Natively filtered lazy iteration — delegates to the inner {@link MemoryDriver}.
44
- *
45
- * @remarks
46
- * Semantics are the memory driver's own: `criteria.conditions` filters, `offset`
47
- * / `limit` page lazily, and `criteria.order` is ignored (streaming yields key
48
- * order; sorted output is `records()`'s job).
49
- *
50
- * @param table - The table to stream
51
- * @param criteria - The filter / offset / limit to apply lazily
52
- */
53
- stream(table: string, criteria: Criteria): AsyncIterable<Row>;
54
- clear(table: string): Promise<void>;
55
- /**
56
- * Begin a native transaction — flush-coalescing over the inner {@link MemoryDriver}.
57
- *
58
- * @remarks
59
- * Single-writer: throws `DatabaseError` `CONFLICT` if a transaction is already
60
- * active — this driver does not support nesting. On begin, captures the inner
61
- * memory rollback thunk via `#memory.snapshot()` and suppresses per-mutation
62
- * `#flush` — `write` / `delete` / `clear` still mutate memory but no longer
63
- * touch the file, so N mutations under the handle cost ONE file write instead
64
- * of N. `commit()` releases the suppression and performs that one atomic
65
- * `#flush()`, persisting the transaction's net state. `rollback()` restores
66
- * memory via the captured snapshot thunk, then `#flush()`s so the file reflects
67
- * the restored state. Outside a transaction, behavior is unchanged — every
68
- * mutation flushes on its own. Calling `commit` / `rollback` a second time (on
69
- * either method, in either order) throws `DatabaseError` `CONFLICT`.
70
- *
71
- * @returns A {@link TransactionInterface} handle to `commit` or `rollback`
72
- */
73
- transaction(): Promise<TransactionInterface>;
74
- snapshot(tables?: readonly string[]): Promise<() => Promise<void>>;
75
- meta(): Promise<DriverMeta | undefined>;
76
- /**
77
- * Persist `meta` verbatim for a later `meta()` to return.
78
- *
79
- * @remarks
80
- * Respects the same defer-flush suppression as `write` / `delete` / `clear`
81
- * (see {@link JSONDriver.transaction} @remarks) — stamping inside an active
82
- * transaction updates memory but does not flush until the transaction settles.
83
- *
84
- * @param meta - The {@link DriverMeta} to persist
85
- */
86
- stamp(meta: DriverMeta): Promise<void>;
87
- /**
88
- * Apply a {@link Migration} plan by delegating to the inner {@link MemoryDriver},
89
- * then persist the migrated state.
90
- *
91
- * @remarks
92
- * The inner `MemoryDriver.migrate` applies each step (adding/removing tables,
93
- * adding/removing columns from stored rows, no-op index steps) and throws
94
- * `DatabaseError` `MIGRATION` for a step referencing an unknown table — that
95
- * error propagates untouched. `table.add` / `table.remove` steps also update
96
- * this driver's own declared `#schema`, mirroring the bookkeeping `open` does,
97
- * so a subsequent `#flush` / `#load` round-trip includes (or drops) the table.
98
- * A successful migration ends with one atomic `#flush()` so the new state
99
- * survives a close and reopen. A multi-step plan applies its steps
100
- * sequentially and is NOT atomic — a failure partway through a plan leaves
101
- * the earlier steps already applied.
102
- *
103
- * @param plan - The migration plan to apply
104
- */
105
- migrate(plan: Migration): Promise<void>;
106
- }
@@ -1,31 +0,0 @@
1
- import type { DriverInterface } from '@src/core';
2
- /**
3
- * Create a persistent JSON-file {@link DriverInterface} for the core database layer.
4
- *
5
- * @remarks
6
- * Pass it to `createDatabase` from `@src/core` to run the whole typed database +
7
- * relations stack against a single JSON file instead of memory — the `Database` /
8
- * `Table` / `Query` / relations API is unchanged; only where the bytes live changes.
9
- * The driver is the reference `MemoryDriver` plus JSON-file persistence: `open` loads
10
- * the file, every mutation flushes the whole store back, and querying runs through
11
- * the core engine over `scan` (it is scan-only — no native `records` / `count` /
12
- * `aggregate`). A missing, corrupt, or wrong-shaped file starts empty rather than
13
- * throwing.
14
- *
15
- * @param path - The JSON file path data is loaded from and flushed to
16
- * @returns A {@link DriverInterface} backed by a JSON file
17
- *
18
- * @example
19
- * ```ts
20
- * import { createDatabase } from '@orkestrel/database'
21
- * import { stringShape } from '@orkestrel/contract'
22
- * import { createJSONDriver } from '@orkestrel/database/server'
23
- *
24
- * const db = createDatabase({
25
- * driver: createJSONDriver('data/app.json'),
26
- * tables: { users: { id: stringShape(), name: stringShape() } },
27
- * })
28
- * await db.table('users').set({ id: 'u1', name: 'Ada' }) // persisted to app.json
29
- * ```
30
- */
31
- export declare function createJSONDriver(path: string): DriverInterface;
@@ -1,222 +0,0 @@
1
- import type { AggregateFunction, ColumnType, Row, TableSchema } from '@src/core';
2
- import type { FieldPath } from '@orkestrel/contract';
3
- import type { SQLiteRow, SQLiteValue } from './types.js';
4
- /**
5
- * Generate a fresh unique key — a v4 UUID string, backed by `node:crypto`.
6
- *
7
- * @remarks
8
- * Supply this as {@link import('@src/core').DatabaseOptions.key} so a table mints
9
- * a key when a written row lacks its primary-key value. Strings work as keys on
10
- * every backend; supply your own key values directly to use numeric keys instead.
11
- *
12
- * @returns A new UUID string
13
- *
14
- * @example
15
- * ```ts
16
- * const db = createDatabase({ driver, tables, key: generateKey })
17
- * ```
18
- */
19
- export declare function generateKey(): string;
20
- /**
21
- * Map a portable {@link ColumnType} to its SQLite column type.
22
- *
23
- * @remarks
24
- * `text` / `json` → `TEXT` (JSON is stored as text and read back with
25
- * `json_extract` for nested-field queries); `integer` / `boolean` → `INTEGER`
26
- * (a boolean stores `1` / `0`); `real` → `REAL`; `blob` → `BLOB`. No `NOT NULL`
27
- * is ever emitted — the contract validates required-ness; the database is just
28
- * storage (AGENTS §14, the typed layer above imposes the shape).
29
- *
30
- * @param type - The portable column type
31
- * @returns The SQLite column type keyword
32
- *
33
- * @example
34
- * ```ts
35
- * columnSQL('integer') // 'INTEGER'
36
- * columnSQL('json') // 'TEXT'
37
- * ```
38
- */
39
- export declare function columnSQL(type: ColumnType): string;
40
- /**
41
- * Quote a SQL identifier (a table or column name) so any characters are literal.
42
- *
43
- * @remarks
44
- * Wraps the name in double quotes and doubles any embedded quote — the standard
45
- * SQL identifier-quoting that lets a column named `order` or `from` be referenced
46
- * safely. Identifiers cannot be bound as parameters, so they are quoted instead.
47
- *
48
- * @param identifier - The raw identifier
49
- * @returns The double-quoted identifier
50
- *
51
- * @example
52
- * ```ts
53
- * quote('order') // '"order"'
54
- * ```
55
- */
56
- export declare function quote(identifier: string): string;
57
- /**
58
- * Compile a {@link FieldPath} to the SQL expression that reads it.
59
- *
60
- * @remarks
61
- * A single string is ONE column — `quote(path)`. An array descends a JSON column:
62
- * the first element is the (quoted) column, the rest a `json_extract` path
63
- * (`json_extract("payload", '$.user.id')`), matching the guide's nested-field
64
- * examples (simple identifier keys). The string's value is never split on `.`
65
- * (AGENTS — `FieldPath` semantics): a dotted string is one column literally.
66
- *
67
- * @param path - The field path (a column, or a column + nested keys)
68
- * @returns The SQL expression selecting the value
69
- *
70
- * @example
71
- * ```ts
72
- * fieldColumn('payload') // '"payload"'
73
- * fieldColumn(['payload', 'user', 'id']) // 'json_extract("payload", \'$.user.id\')'
74
- * ```
75
- */
76
- export declare function fieldColumn(path: FieldPath): string;
77
- /**
78
- * Compile an {@link AggregateFunction} over a {@link FieldPath} to its SQL
79
- * aggregate expression — the SELECT body the SQLite driver's native `aggregate`
80
- * runs.
81
- *
82
- * @remarks
83
- * `count` → `COUNT(*)` (counting all matched ROWS, not non-null column values —
84
- * mirroring the engine's `computeAggregate('count')`, which is `rows.length`); the
85
- * numeric aggregates wrap the column's read expression (a flat column, or a nested
86
- * `json_extract` path) in `SUM` / `AVG` / `MIN` / `MAX`. Over zero matched rows
87
- * `COUNT(*)` is `0` and the numeric aggregates are SQL `NULL` (→ `undefined`),
88
- * matching the engine.
89
- *
90
- * @param operation - The aggregate to compute
91
- * @param column - The column (or nested path) to aggregate
92
- * @returns The SQL aggregate expression
93
- *
94
- * @example
95
- * ```ts
96
- * aggregateSQL('count', 'age') // 'COUNT(*)'
97
- * aggregateSQL('sum', 'age') // 'SUM("age")'
98
- * aggregateSQL('average', ['payload', 'score']) // 'AVG(json_extract("payload", \'$.score\'))'
99
- * ```
100
- */
101
- export declare function aggregateSQL(operation: AggregateFunction, column: FieldPath): string;
102
- /**
103
- * Encode a JS value to its stored {@link SQLiteValue} for a column's type.
104
- *
105
- * @remarks
106
- * The forward half of the bridge, total (AGENTS §14): a value that does not fit
107
- * its column's storage type encodes to `null` rather than throwing. A `boolean`
108
- * column stores `1` / `0` (and `null` / `undefined` → `null`); a `json` column
109
- * stores `JSON.stringify` (or `null` for `null` / `undefined`); `integer` /
110
- * `real` keep a `number` / `bigint`, else `null`; `text` keeps a `string`, else
111
- * `null`; `blob` keeps a `Uint8Array`, else `null`. Narrowed with `typeof` /
112
- * `instanceof`, never `as`.
113
- *
114
- * @param value - The JS value to store
115
- * @param type - The column's portable storage type
116
- * @returns The value SQLite stores
117
- *
118
- * @example
119
- * ```ts
120
- * encodeValue(true, 'boolean') // 1
121
- * encodeValue({ a: 1 }, 'json') // '{"a":1}'
122
- * ```
123
- */
124
- export declare function encodeValue(value: unknown, type: ColumnType): SQLiteValue;
125
- /**
126
- * Decode a stored {@link SQLiteValue} back to its JS value for a column's type —
127
- * the exact inverse of {@link encodeValue}.
128
- *
129
- * @remarks
130
- * A `boolean` column reads `1` / `0` back to `true` / `false` (a stored `null`
131
- * → `undefined`); a `json` column `JSON.parse`s a string (anything else →
132
- * `undefined`); every other type passes the value through, mapping a stored
133
- * `NULL` to `undefined`. NULL decodes to `undefined` so {@link decodeRow} can
134
- * omit absent columns.
135
- *
136
- * @param value - The stored SQLite value
137
- * @param type - The column's portable storage type
138
- * @returns The decoded JS value (`undefined` for a stored `NULL`)
139
- *
140
- * @example
141
- * ```ts
142
- * decodeValue(1, 'boolean') // true
143
- * decodeValue('{"a":1}', 'json') // { a: 1 }
144
- * ```
145
- */
146
- export declare function decodeValue(value: SQLiteValue, type: ColumnType): unknown;
147
- /**
148
- * Encode a whole {@link Row} to a {@link SQLiteRow} by its table's schema.
149
- *
150
- * @remarks
151
- * Encodes each declared column's value with {@link encodeValue}; columns the row
152
- * does not carry encode from `undefined` (so they store `null`). Only the
153
- * schema's columns appear in the result — an extra row key is dropped.
154
- *
155
- * @param row - The JS row to store
156
- * @param schema - The table's schema
157
- * @returns The storable SQLite row
158
- *
159
- * @example
160
- * ```ts
161
- * encodeRow({ id: 'u1', active: true }, schema) // { id: 'u1', active: 1, ... }
162
- * ```
163
- */
164
- export declare function encodeRow(row: Row, schema: TableSchema): SQLiteRow;
165
- /**
166
- * Decode a stored {@link SQLiteRow} back to a {@link Row} by its table's schema.
167
- *
168
- * @remarks
169
- * Decodes each declared column with {@link decodeValue} and **omits** any column
170
- * whose decoded value is `undefined` — so an absent / `NULL` optional column does
171
- * not surface as `{ bio: undefined }`, matching how the contract's optional
172
- * columns expect absence. A known, documented edge: a non-optional `nullableShape`
173
- * column storing `null` round-trips to absent (a `null` cell decodes to
174
- * `undefined`, and an `undefined` value is omitted).
175
- *
176
- * @param row - The stored SQLite row
177
- * @param schema - The table's schema
178
- * @returns The decoded JS row (absent columns omitted)
179
- *
180
- * @example
181
- * ```ts
182
- * decodeRow({ id: 'u1', active: 1, bio: null }, schema) // { id: 'u1', active: true }
183
- * ```
184
- */
185
- export declare function decodeRow(row: SQLiteRow, schema: TableSchema): Row;
186
- /**
187
- * Project a {@link TableSchema} to the `CREATE TABLE IF NOT EXISTS` statement a
188
- * SQLite driver's `open` issues for it.
189
- *
190
- * @remarks
191
- * Each column compiles to `<quoted name> <columnSQL(type)>`; the statement ends
192
- * with `PRIMARY KEY (<quoted primary>)`. No `NOT NULL` is emitted — the contract
193
- * validates required-ness, the database is just storage (AGENTS §14).
194
- *
195
- * @param schema - The table's schema
196
- * @returns The `CREATE TABLE IF NOT EXISTS …` statement
197
- *
198
- * @example
199
- * ```ts
200
- * schemaToTable(schema)
201
- * // 'CREATE TABLE IF NOT EXISTS "users" ("id" TEXT, "age" INTEGER, PRIMARY KEY ("id"))'
202
- * ```
203
- */
204
- export declare function schemaToTable(schema: TableSchema): string;
205
- /**
206
- * Project a {@link TableSchema} to the `CREATE INDEX IF NOT EXISTS` statements a
207
- * SQLite driver's `open` issues for its declared indexes.
208
- *
209
- * @remarks
210
- * One statement per index group; the index name is `idx_<table>_<columns joined
211
- * by _>`, matching the driver's naming so a repeated `open` is idempotent.
212
- *
213
- * @param schema - The table's schema
214
- * @returns One `CREATE INDEX IF NOT EXISTS …` statement per declared index
215
- *
216
- * @example
217
- * ```ts
218
- * schemaToIndexes(schema)
219
- * // ['CREATE INDEX IF NOT EXISTS "idx_users_name" ON "users" ("name")']
220
- * ```
221
- */
222
- export declare function schemaToIndexes(schema: TableSchema): readonly string[];
@@ -1,36 +0,0 @@
1
- /**
2
- * The value domain a SQLite binding accepts as a bound parameter and returns
3
- * from a row.
4
- *
5
- * @remarks
6
- * Mirrors SQLite's storage classes (`NULL`, `INTEGER`, `REAL`, `TEXT`, `BLOB`)
7
- * at the TypeScript boundary: `null`, `number` / `bigint` for integer and
8
- * floating-point values, `string` for text, and `Uint8Array` for blobs. This
9
- * type is pure — it names the shape a value must have to cross the binding,
10
- * independent of any concrete sqlite package (`node:sqlite`, `better-sqlite3`,
11
- * etc.), so a driver can encode/decode against it without importing one.
12
- */
13
- export type SQLiteValue = null | number | bigint | string | Uint8Array;
14
- /**
15
- * One row as a SQLite binding returns it — a plain object keyed by column name.
16
- *
17
- * @remarks
18
- * Every column value is a {@link SQLiteValue}. The SQLite driver decodes each
19
- * raw row into this shape before handing it to the core query engine; nothing
20
- * above the driver ever sees SQLite's native row representation directly.
21
- */
22
- export type SQLiteRow = Record<string, SQLiteValue>;
23
- /**
24
- * A parameterized SQL fragment or statement plus its bind values.
25
- *
26
- * @remarks
27
- * Produced by the pure SQL compilers (`compilers.ts`) that turn a core
28
- * `Criteria` (or a table definition) into SQL text with `?` placeholders, and
29
- * consumed by the SQLite driver, which runs `sql` with `params` bound in
30
- * order — no further assembly. Keeping `sql` and `params` together prevents
31
- * the two from drifting apart across compile and execute.
32
- */
33
- export interface CompiledSQL {
34
- readonly sql: string;
35
- readonly params: readonly SQLiteValue[];
36
- }