@ix-xs/node-comfort 1.2.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/CHANGELOG.md +340 -0
  2. package/README.md +137 -548
  3. package/index.js +80 -35
  4. package/package.json +161 -33
  5. package/src/Arr.js +1050 -418
  6. package/src/Async.js +817 -0
  7. package/src/Cache.js +433 -0
  8. package/src/Checker.js +1202 -539
  9. package/src/Cli.js +1293 -0
  10. package/src/Color.js +556 -0
  11. package/src/Crypto.js +1082 -0
  12. package/src/Emitter.js +356 -0
  13. package/src/Env.js +689 -0
  14. package/src/FS.js +1626 -894
  15. package/src/Func.js +823 -356
  16. package/src/Http.js +700 -0
  17. package/src/Id.js +568 -200
  18. package/src/Logger.js +963 -378
  19. package/src/Num.js +965 -360
  20. package/src/Obj.js +1077 -379
  21. package/src/SQLite.js +1629 -1005
  22. package/src/Schema.js +2101 -0
  23. package/src/Str.js +1209 -432
  24. package/src/Sys.js +654 -0
  25. package/src/Time.js +1533 -440
  26. package/src/Utils.js +342 -325
  27. package/src/errors.js +335 -0
  28. package/src/internal/shared.js +415 -0
  29. package/types/index.d.ts +735 -526
  30. package/types/src/Arr.d.ts +533 -145
  31. package/types/src/Arr.d.ts.map +1 -1
  32. package/types/src/Async.d.ts +372 -0
  33. package/types/src/Async.d.ts.map +1 -0
  34. package/types/src/Cache.d.ts +221 -0
  35. package/types/src/Cache.d.ts.map +1 -0
  36. package/types/src/Checker.d.ts +651 -232
  37. package/types/src/Checker.d.ts.map +1 -1
  38. package/types/src/Cli.d.ts +664 -0
  39. package/types/src/Cli.d.ts.map +1 -0
  40. package/types/src/Color.d.ts +300 -0
  41. package/types/src/Color.d.ts.map +1 -0
  42. package/types/src/Crypto.d.ts +620 -0
  43. package/types/src/Crypto.d.ts.map +1 -0
  44. package/types/src/Emitter.d.ts +189 -0
  45. package/types/src/Emitter.d.ts.map +1 -0
  46. package/types/src/Env.d.ts +412 -0
  47. package/types/src/Env.d.ts.map +1 -0
  48. package/types/src/FS.d.ts +717 -238
  49. package/types/src/FS.d.ts.map +1 -1
  50. package/types/src/Func.d.ts +508 -135
  51. package/types/src/Func.d.ts.map +1 -1
  52. package/types/src/Http.d.ts +444 -0
  53. package/types/src/Http.d.ts.map +1 -0
  54. package/types/src/Id.d.ts +199 -66
  55. package/types/src/Id.d.ts.map +1 -1
  56. package/types/src/Logger.d.ts +414 -46
  57. package/types/src/Logger.d.ts.map +1 -1
  58. package/types/src/Num.d.ts +514 -137
  59. package/types/src/Num.d.ts.map +1 -1
  60. package/types/src/Obj.d.ts +453 -104
  61. package/types/src/Obj.d.ts.map +1 -1
  62. package/types/src/SQLite.d.ts +754 -308
  63. package/types/src/SQLite.d.ts.map +1 -1
  64. package/types/src/Schema.d.ts +1189 -0
  65. package/types/src/Schema.d.ts.map +1 -0
  66. package/types/src/Str.d.ts +617 -166
  67. package/types/src/Str.d.ts.map +1 -1
  68. package/types/src/Sys.d.ts +314 -0
  69. package/types/src/Sys.d.ts.map +1 -0
  70. package/types/src/Time.d.ts +759 -204
  71. package/types/src/Time.d.ts.map +1 -1
  72. package/types/src/Utils.d.ts +158 -102
  73. package/types/src/Utils.d.ts.map +1 -1
  74. package/types/src/errors.d.ts +316 -0
  75. package/types/src/errors.d.ts.map +1 -0
  76. package/types/src/internal/shared.d.ts +123 -0
  77. package/types/src/internal/shared.d.ts.map +1 -0
  78. package/types/index.d.ts.map +0 -1
@@ -1,396 +1,842 @@
1
1
  export = SQLite;
2
- declare class SQLite {
2
+ /**
3
+ * A SQLite database connection.
4
+ *
5
+ * @template [R=Record<string, any>] The row type read methods return by default. Each call can override it.
6
+ */
7
+ declare class SQLite<R = Record<string, any>> {
3
8
  /**
4
- * Creates a new SQLite database connection.
9
+ * Opens a database, creating the file and its folders if needed. Use
10
+ * `":memory:"` for a throwaway in-memory database.
5
11
  *
6
- * The database file and its parent folders are created if necessary.
7
- * WAL journal mode and foreign key support are enabled automatically.
8
- *
9
- * Pass `":memory:"` to create a transient in-memory database.
12
+ * @example
13
+ * const db = new nc.SQLite(); // ./db.sqlite
14
+ * const app = new nc.SQLite("data/app.sqlite", { dates: true });
15
+ * const mem = new nc.SQLite(":memory:");
10
16
  *
11
- * @param {string} [path="db.sqlite"] - Path to the SQLite database file.
17
+ * @param {string} [path="db.sqlite"] Relative to the working directory.
18
+ * @param {SQLiteOptions} [options]
19
+ * @throws {SQLiteError} If the file can't be opened.
20
+ */
21
+ constructor(path?: string, options?: SQLiteOptions);
22
+ /**
23
+ * Runs SQL that doesn't return rows. Without parameters, you can pass
24
+ * several statements at once.
12
25
  *
13
26
  * @example
14
- * const db = new SQLite();
27
+ * db.exec("UPDATE users SET active = ? WHERE last_login < ?", [false, cutoff]);
28
+ * db.exec("DELETE FROM sessions WHERE user_id = $id", { $id: 42 });
29
+ * db.exec(`
30
+ * CREATE TABLE tags (id INTEGER PRIMARY KEY, label TEXT UNIQUE);
31
+ * CREATE INDEX idx_tags_label ON tags (label);
32
+ * `);
33
+ *
34
+ * @param {string} sql
35
+ * @param {unknown[] | Record<string, unknown> | string | number | bigint | boolean | Date | null} [params] An array, named parameters like `{ $id: 1 }`, or a single value.
36
+ * @returns {{ changes: number, lastInsertRowid: number | bigint }}
37
+ * @throws {SQLiteError}
38
+ */
39
+ exec(sql: string, params?: unknown[] | Record<string, unknown> | string | number | bigint | boolean | Date | null): {
40
+ changes: number;
41
+ lastInsertRowid: number | bigint;
42
+ };
43
+ /**
44
+ * Runs a query and returns the first row. JSON and boolean columns are
45
+ * converted like in `get()`, joins and renamed columns included. On Node.js
46
+ * before 22.16, that only works for a query on a single table.
15
47
  *
16
48
  * @example
17
- * const db = new SQLite("data/my-app.sqlite");
49
+ * const user = db.queryOne("SELECT * FROM users WHERE email = ?", [email]);
18
50
  *
19
- * @example
20
- * const db = new SQLite(":memory:");
51
+ * @template [T=R]
52
+ * @param {string} sql
53
+ * @param {unknown[] | Record<string, unknown> | string | number | bigint | boolean | Date | null} [params]
54
+ * @returns {T | undefined}
55
+ * @throws {SQLiteError}
21
56
  */
22
- constructor(path?: string);
57
+ queryOne<T = R>(sql: string, params?: unknown[] | Record<string, unknown> | string | number | bigint | boolean | Date | null): T | undefined;
23
58
  /**
24
- * Executes a raw SQL statement using `run()`.
59
+ * Runs a query and returns every row.
25
60
  *
26
- * Use this for custom SQL that is not covered by the helper methods.
27
- * This method is intended for statements such as:
28
- * - `INSERT`
29
- * - `UPDATE`
30
- * - `DELETE`
31
- * - `CREATE INDEX`
32
- * - PRAGMA writes
61
+ * @example
62
+ * const stats = db.queryAll("SELECT role, COUNT(*) AS n FROM users GROUP BY role");
33
63
  *
34
- * @param {string} sql - SQL statement.
35
- * @param {any[]|any} [params=[]] - Parameters to bind.
36
- * @returns {Promise<{ changes: number, lastInsertRowid: bigint|number } | { error: string }>}
64
+ * @template [T=R]
65
+ * @param {string} sql
66
+ * @param {unknown[] | Record<string, unknown> | string | number | bigint | boolean | Date | null} [params]
67
+ * @returns {T[]}
68
+ * @throws {SQLiteError}
37
69
  */
38
- exec(sql: string, params?: any[] | any): Promise<{
39
- changes: number;
40
- lastInsertRowid: bigint | number;
41
- } | {
42
- error: string;
43
- }>;
44
- /**
45
- * Executes a raw SQL query and returns the first row.
46
- *
47
- * @param {string} sql - SQL query.
48
- * @param {any[]|any} [params=[]] - Parameters to bind.
49
- * @returns {Promise<object|undefined|{ error: string }>}
50
- */
51
- queryOne(sql: string, params?: any[] | any): Promise<object | undefined | {
52
- error: string;
53
- }>;
54
- /**
55
- * Executes a raw SQL query and returns all rows.
56
- *
57
- * @param {string} sql - SQL query.
58
- * @param {any[]|any} [params=[]] - Parameters to bind.
59
- * @returns {Promise<object[]|{ error: string }>}
60
- */
61
- queryAll(sql: string, params?: any[] | any): Promise<object[] | {
62
- error: string;
63
- }>;
64
- /**
65
- * Creates a table and stores its schema in memory.
66
- *
67
- * This method supports both the new `columns` property and the legacy
68
- * `options` property for backward compatibility.
69
- *
70
- * @param {{
71
- * name: string,
72
- * columns?: Record<string, {
73
- * type: "INTEGER"|"TEXT"|"REAL"|"BLOB"|"NUMERIC",
74
- * primaryKey?: boolean,
75
- * autoincrement?: boolean,
76
- * notNull?: boolean,
77
- * unique?: boolean,
78
- * defaultValue?: any,
79
- * values?: any[],
80
- * references?: { table: string, column: string },
81
- * onDelete?: string,
82
- * onUpdate?: string
83
- * }>,
84
- * options?: Record<string, any>,
85
- * constraints?: Array<
86
- * | { type: "unique", columns: string[] }
87
- * | { type: "primaryKey", columns: string[] }
88
- * | { type: "check", expression: string }
89
- * | {
90
- * type: "foreignKey",
91
- * columns: string[],
92
- * references: { table: string, columns: string[] },
93
- * onDelete?: string,
94
- * onUpdate?: string
95
- * }
96
- * >,
97
- * indexes?: Array<{
98
- * name?: string,
99
- * columns: string[],
100
- * unique?: boolean
101
- * }>
102
- * }} table - Table definition.
103
- * @returns {Promise<{ ok: true } | { error: string }>}
70
+ queryAll<T = R>(sql: string, params?: unknown[] | Record<string, unknown> | string | number | bigint | boolean | Date | null): T[];
71
+ /**
72
+ * Goes through the rows of a query one at a time, without loading them all.
73
+ * For big exports.
104
74
  *
105
75
  * @example
106
- * await db.createTable({
107
- * name: "Post",
76
+ * for (const row of db.iterate("SELECT * FROM events WHERE day = ?", [day])) {
77
+ * stream.write(JSON.stringify(row) + "\n");
78
+ * }
79
+ *
80
+ * @template [T=R]
81
+ * @param {string} sql
82
+ * @param {unknown[] | Record<string, unknown> | string | number | bigint | boolean | Date | null} [params]
83
+ * @returns {Generator<T, void, undefined>}
84
+ * @throws {SQLiteError}
85
+ */
86
+ iterate<T = R>(sql: string, params?: unknown[] | Record<string, unknown> | string | number | bigint | boolean | Date | null): Generator<T, void, undefined>;
87
+ /**
88
+ * Creates a table with its constraints and indexes, unless it already
89
+ * exists. To change an existing table, use `migrate()`.
90
+ *
91
+ * @example
92
+ * db.createTable({
93
+ * name: "posts",
108
94
  * columns: {
109
95
  * id: { type: "INTEGER", primaryKey: true, autoincrement: true },
110
- * userId: {
111
- * type: "INTEGER",
112
- * notNull: true,
113
- * references: { table: "User", column: "id" },
114
- * onDelete: "CASCADE"
115
- * },
116
- * title: { type: "TEXT", notNull: true }
96
+ * user_id: { type: "INTEGER", notNull: true, references: { table: "users", column: "id" }, onDelete: "CASCADE" },
97
+ * status: { type: "TEXT", values: ["draft", "published"], defaultValue: "draft" },
98
+ * tags: { type: "JSON", defaultValue: [] },
117
99
  * },
118
- * indexes: [{ columns: ["userId"] }]
100
+ * indexes: [{ columns: ["user_id", "status"] }],
119
101
  * });
102
+ *
103
+ * @param {TableDefinition} table
104
+ * @returns {{ ok: true }}
105
+ * @throws {SQLiteError} If the definition is invalid.
120
106
  */
121
- createTable(table: {
122
- name: string;
123
- columns?: Record<string, {
124
- type: "INTEGER" | "TEXT" | "REAL" | "BLOB" | "NUMERIC";
125
- primaryKey?: boolean;
126
- autoincrement?: boolean;
127
- notNull?: boolean;
128
- unique?: boolean;
129
- defaultValue?: any;
130
- values?: any[];
131
- references?: {
132
- table: string;
133
- column: string;
134
- };
135
- onDelete?: string;
136
- onUpdate?: string;
137
- }>;
138
- options?: Record<string, any>;
139
- constraints?: Array<{
140
- type: "unique";
141
- columns: string[];
142
- } | {
143
- type: "primaryKey";
144
- columns: string[];
145
- } | {
146
- type: "check";
147
- expression: string;
148
- } | {
149
- type: "foreignKey";
150
- columns: string[];
151
- references: {
152
- table: string;
153
- columns: string[];
154
- };
155
- onDelete?: string;
156
- onUpdate?: string;
157
- }>;
158
- indexes?: Array<{
159
- name?: string;
160
- columns: string[];
161
- unique?: boolean;
162
- }>;
163
- }): Promise<{
107
+ createTable(table: TableDefinition): {
164
108
  ok: true;
165
- } | {
166
- error: string;
167
- }>;
109
+ };
168
110
  /**
169
- * Creates an index on an existing table.
170
- *
171
- * Composite indexes are supported by passing multiple columns.
172
- *
173
- * @param {string} tableName - Table name.
174
- * @param {{
175
- * name?: string,
176
- * columns: string[],
177
- * unique?: boolean
178
- * }} index - Index definition.
179
- * @returns {Promise<{ ok: true } | { error: string }>}
111
+ * Creates an index, unless it already exists.
180
112
  *
181
113
  * @example
182
- * await db.createIndex("UserAuthMethod", {
183
- * columns: ["provider", "providerUserId"],
184
- * unique: true
185
- * });
114
+ * db.createIndex("users", { columns: ["email"], unique: true });
115
+ * db.createIndex("posts", { columns: ["slug"], unique: true, where: "deleted_at IS NULL" });
116
+ *
117
+ * @param {string} tableName
118
+ * @param {IndexDefinition} index
119
+ * @returns {{ ok: true }}
120
+ * @throws {SQLiteError}
186
121
  */
187
- createIndex(tableName: string, index: {
188
- name?: string;
189
- columns: string[];
190
- unique?: boolean;
191
- }): Promise<{
122
+ createIndex(tableName: string, index: IndexDefinition): {
192
123
  ok: true;
193
- } | {
194
- error: string;
195
- }>;
124
+ };
196
125
  /**
197
- * Drops a table and removes its model definition.
126
+ * Drops a table and everything in it.
198
127
  *
199
- * @param {string} tableName - Table name.
200
- * @returns {Promise<{ ok: true } | { error: string }>}
128
+ * @param {string} tableName
129
+ * @returns {{ ok: true }}
130
+ * @throws {SQLiteError} If the table doesn't exist.
201
131
  */
202
- deleteTable(tableName: string): Promise<{
132
+ deleteTable(tableName: string): {
203
133
  ok: true;
204
- } | {
205
- error: string;
206
- }>;
134
+ };
207
135
  /**
208
- * Deletes all rows from a table.
136
+ * Deletes every row, keeping the table.
209
137
  *
210
- * @param {string} tableName - Table name.
211
- * @returns {Promise<{ ok: true } | { error: string }>}
138
+ * @param {string} tableName
139
+ * @returns {{ ok: true }}
140
+ * @throws {SQLiteError} If the table doesn't exist.
212
141
  */
213
- clearTable(tableName: string): Promise<{
142
+ clearTable(tableName: string): {
214
143
  ok: true;
215
- } | {
216
- error: string;
217
- }>;
144
+ };
145
+ /**
146
+ * Does the table exist?
147
+ *
148
+ * @param {string} tableName
149
+ * @returns {boolean}
150
+ */
151
+ hasTable(tableName: string): boolean;
218
152
  /**
219
- * Returns a single row matching a plain-object WHERE clause.
153
+ * The tables in the database, sorted.
220
154
  *
221
- * @param {string} tableName - Table name.
222
- * @param {Record<string, any>} [where={}] - Conditions.
223
- * @returns {Promise<object|undefined|{ error: string }>}
155
+ * @returns {string[]}
224
156
  */
225
- get(tableName: string, where?: Record<string, any>): Promise<object | undefined | {
226
- error: string;
227
- }>;
157
+ tables(): string[];
228
158
  /**
229
- * Returns multiple rows from a table.
159
+ * The columns of a table.
160
+ *
161
+ * @example
162
+ * db.columns("users");
163
+ * // [{ name: "id", type: "INTEGER", notNull: false, defaultValue: null, primaryKey: true }, ...]
230
164
  *
231
- * Supports:
232
- * - exact-match filters via `where`
233
- * - custom ordering
234
- * - pagination via `limit` and `offset`
165
+ * @param {string} tableName
166
+ * @returns {ColumnInfo[]}
167
+ * @throws {SQLiteError} If the table doesn't exist.
168
+ */
169
+ columns(tableName: string): ColumnInfo[];
170
+ /**
171
+ * The first row that matches.
235
172
  *
236
- * @param {string} tableName - Table name.
237
- * @param {Record<string, any>} [where={}] - Exact-match conditions.
238
- * @param {{
239
- * limit?: number,
240
- * offset?: number,
241
- * orderBy?: string,
242
- * direction?: "ASC"|"DESC"
243
- * }} [options={}] - Query options.
244
- * @returns {Promise<object[] | { error: string }>}
173
+ * @example
174
+ * const user = db.get("users", { email: "ada@example.com" });
175
+ * const latest = db.get("posts", { status: "published" }, { orderBy: "created_at", direction: "DESC" });
176
+ *
177
+ * @template [T=R]
178
+ * @param {string} tableName
179
+ * @param {Where<R>} [where]
180
+ * @param {Pick<QueryOptions, "columns" | "orderBy" | "direction">} [options]
181
+ * @returns {T | undefined}
182
+ * @throws {SQLiteError}
183
+ */
184
+ get<T = R>(tableName: string, where?: Where<R>, options?: Pick<QueryOptions, "columns" | "orderBy" | "direction">): T | undefined;
185
+ /**
186
+ * The rows that match, with sorting and pagination.
245
187
  *
246
188
  * @example
247
- * const posts = await db.getAll("Post", { userId: 1 }, {
189
+ * db.getAll("users");
190
+ * db.getAll("users", { role: ["admin", "editor"], age: { gte: 18 } });
191
+ * db.getAll("posts", { $or: [{ pinned: true }, { views: { gt: 1000 } }] }, {
192
+ * orderBy: [["views", "DESC"], "title"],
248
193
  * limit: 20,
249
- * offset: 0,
250
- * orderBy: "createdAt",
251
- * direction: "DESC"
194
+ * offset: 40,
252
195
  * });
196
+ *
197
+ * @template [T=R]
198
+ * @param {string} tableName
199
+ * @param {Where<R>} [where]
200
+ * @param {QueryOptions} [options]
201
+ * @returns {T[]}
202
+ * @throws {SQLiteError}
253
203
  */
254
- getAll(tableName: string, where?: Record<string, any>, options?: {
255
- limit?: number;
256
- offset?: number;
257
- orderBy?: string;
258
- direction?: "ASC" | "DESC";
259
- }): Promise<object[] | {
260
- error: string;
261
- }>;
204
+ getAll<T = R>(tableName: string, where?: Where<R>, options?: QueryOptions): T[];
262
205
  /**
263
- * Inserts a new row into a table.
206
+ * One page of the rows that match, with what a pager needs to draw itself.
264
207
  *
265
- * This method performs a plain `INSERT`.
266
- * If a unique constraint is violated, SQLite will throw an error.
208
+ * @example
209
+ * const { items, pages, hasNext } = db.paginate("posts", { status: "published" }, {
210
+ * page: 3,
211
+ * perPage: 20,
212
+ * orderBy: "created_at",
213
+ * direction: "DESC",
214
+ * });
267
215
  *
268
- * @param {string} tableName - Table name.
269
- * @param {Record<string, any>} data - Row to insert.
270
- * @returns {Promise<{ ok: true, lastInsertRowid: bigint|number, changes: number } | { error: string }>}
216
+ * @template [T=R]
217
+ * @param {string} tableName
218
+ * @param {Where<R>} [where]
219
+ * @param {PaginateOptions} [options]
220
+ * @returns {import("./Arr").Page<T>} A page past the end gives the last one.
221
+ * @throws {SQLiteError}
271
222
  */
272
- insert(tableName: string, data: Record<string, any>): Promise<{
273
- ok: true;
274
- lastInsertRowid: bigint | number;
275
- changes: number;
276
- } | {
277
- error: string;
278
- }>;
223
+ paginate<T = R>(tableName: string, where?: Where<R>, options?: PaginateOptions): import("./Arr").Page<T>;
279
224
  /**
280
- * Updates one or more rows matching a WHERE clause.
225
+ * Counts the rows that match.
281
226
  *
282
- * This method performs a plain `UPDATE`.
227
+ * @example
228
+ * db.count("users", { active: true });
283
229
  *
284
- * @param {string} tableName - Table name.
285
- * @param {Record<string, any>} data - Fields to update.
286
- * @param {Record<string, any>} where - Conditions used to select rows.
287
- * @returns {Promise<{ ok: true, changes: number } | { error: string }>}
230
+ * @param {string} tableName
231
+ * @param {Where<R>} [where]
232
+ * @returns {number}
233
+ * @throws {SQLiteError}
288
234
  */
289
- update(tableName: string, data: Record<string, any>, where: Record<string, any>): Promise<{
290
- ok: true;
291
- changes: number;
292
- } | {
293
- error: string;
294
- }>;
235
+ count(tableName: string, where?: Where<R>): number;
295
236
  /**
296
- * Inserts or updates a row using SQLite `ON CONFLICT DO UPDATE`.
237
+ * Does any row match?
297
238
  *
298
- * This is safer than `INSERT OR REPLACE` because it does not delete
299
- * and recreate the row.
239
+ * @example
240
+ * if (db.exists("users", { email })) throw new Error("Email already registered");
300
241
  *
301
- * @param {string} tableName - Table name.
302
- * @param {Record<string, any>} data - Row data.
303
- * @param {string[]} conflict - Columns that define the conflict target.
304
- * @returns {Promise<{ ok: true, changes: number, lastInsertRowid: bigint|number } | { error: string }>}
242
+ * @param {string} tableName
243
+ * @param {Where<R>} [where]
244
+ * @returns {boolean}
245
+ * @throws {SQLiteError}
246
+ */
247
+ exists(tableName: string, where?: Where<R>): boolean;
248
+ /**
249
+ * Inserts a row. Objects and arrays are stored as JSON, booleans as 1 and
250
+ * 0, dates as ISO strings. `undefined` values are skipped, so column
251
+ * defaults apply.
305
252
  *
306
253
  * @example
307
- * await db.upsert("UserAuthMethod", {
308
- * userId: 1,
309
- * provider: "google",
310
- * providerUserId: "123"
311
- * }, ["provider", "providerUserId"]);
254
+ * const { lastInsertRowid } = db.insert("users", { email: "ada@example.com", settings: { theme: "dark" } });
255
+ * db.insert("tags", { label: "news" }, { onConflict: "ignore" }); // no error if it's already there
256
+ *
257
+ * @param {string} tableName
258
+ * @param {Partial<R> & Record<string, unknown>} data
259
+ * @param {InsertOptions} [options]
260
+ * @returns {InsertResult}
261
+ * @throws {SQLiteError} On a constraint failure; `sqliteCode` tells you which, like `"SQLITE_CONSTRAINT_UNIQUE"`.
312
262
  */
313
- upsert(tableName: string, data: Record<string, any>, conflict?: string[]): Promise<{
314
- ok: true;
315
- changes: number;
316
- lastInsertRowid: bigint | number;
317
- } | {
318
- error: string;
319
- }>;
263
+ insert(tableName: string, data: Partial<R> & Record<string, unknown>, options?: InsertOptions): InsertResult;
320
264
  /**
321
- * Backward-compatible helper that inserts or updates a row.
265
+ * Inserts many rows in one transaction: all or nothing, and much faster
266
+ * than one by one.
322
267
  *
323
- * Behavior:
324
- * - If `where` is provided, the existing row is loaded and merged with `data`,
325
- * then updated if found or inserted if not found.
326
- * - If `where` is not provided but `data.id` exists, lookup is performed on `id`.
327
- * - If no existing row is found, a new row is inserted.
268
+ * @example
269
+ * db.insertMany("products", rowsFromCsv);
270
+ * db.insertMany("tags", labels.map((label) => ({ label })), { onConflict: "ignore" });
271
+ *
272
+ * @param {string} tableName
273
+ * @param {Iterable<Partial<R> & Record<string, unknown>>} rows
274
+ * @param {InsertOptions} [options]
275
+ * @returns {ChangeResult}
276
+ * @throws {SQLiteError} If a row fails; nothing is inserted then.
277
+ */
278
+ insertMany(tableName: string, rows: Iterable<Partial<R> & Record<string, unknown>>, options?: InsertOptions): ChangeResult;
279
+ /**
280
+ * Updates the rows that match. The filter is required, so a forgotten
281
+ * condition can't rewrite the whole table.
328
282
  *
329
- * This method is intentionally simple, but for production-grade control,
330
- * prefer using `insert()`, `update()`, or `upsert()`.
283
+ * @example
284
+ * db.update("users", { active: false }, { last_login: { lt: "2025-01-01" } });
331
285
  *
332
- * @param {string} tableName - Table name.
333
- * @param {Record<string, any>} data - Row data.
334
- * @param {Record<string, any>|null} [where=null] - Lookup condition.
335
- * @returns {Promise<{ ok: true } | { error: string }>}
286
+ * @param {string} tableName
287
+ * @param {Partial<R> & Record<string, unknown>} data `undefined` values are skipped.
288
+ * @param {Where<R>} where
289
+ * @returns {ChangeResult}
290
+ * @throws {SQLiteError}
336
291
  */
337
- set(tableName: string, data: Record<string, any>, where?: Record<string, any> | null): Promise<{
338
- ok: true;
339
- } | {
340
- error: string;
341
- }>;
292
+ update(tableName: string, data: Partial<R> & Record<string, unknown>, where: Where<R>): ChangeResult;
342
293
  /**
343
- * Deletes rows matching a WHERE clause.
294
+ * Inserts a row, or updates it in place if it clashes with an existing one
295
+ * on the `conflict` columns.
344
296
  *
345
- * @param {string} tableName - Table name.
346
- * @param {Record<string, any>} where - Conditions.
347
- * @returns {Promise<{ ok: true, changes: number } | { error: string }>}
297
+ * @example
298
+ * db.upsert("settings", { user_id: 1, key: "theme", value: "dark" }, ["user_id", "key"]);
299
+ *
300
+ * @param {string} tableName
301
+ * @param {Partial<R> & Record<string, unknown>} data
302
+ * @param {string[]} conflict The unique columns that identify the row.
303
+ * @returns {InsertResult}
304
+ * @throws {SQLiteError} If `conflict` doesn't match a unique constraint.
305
+ */
306
+ upsert(tableName: string, data: Partial<R> & Record<string, unknown>, conflict: string[]): InsertResult;
307
+ /**
308
+ * Updates the row matching `where` (or `{ id: data.id }`), or inserts it.
309
+ * Kept from 1.x; `upsert()` does the same in one atomic statement.
310
+ *
311
+ * @param {string} tableName
312
+ * @param {Partial<R> & Record<string, unknown>} data
313
+ * @param {Where<R> | null} [where]
314
+ * @returns {{ ok: true }}
315
+ * @throws {SQLiteError}
348
316
  */
349
- delete(tableName: string, where: Record<string, any>): Promise<{
317
+ set(tableName: string, data: Partial<R> & Record<string, unknown>, where?: Where<R> | null): {
350
318
  ok: true;
351
- changes: number;
352
- } | {
353
- error: string;
354
- }>;
319
+ };
355
320
  /**
356
- * Counts rows matching a WHERE clause.
321
+ * Deletes the rows that match. The filter is required; `clearTable()`
322
+ * deletes everything on purpose.
357
323
  *
358
- * @param {string} tableName - Table name.
359
- * @param {Record<string, any>} [where={}] - Conditions.
360
- * @returns {Promise<number | { error: string }>}
324
+ * @example
325
+ * db.delete("sessions", { expires_at: { lt: new Date() } });
326
+ *
327
+ * @param {string} tableName
328
+ * @param {Where<R>} where
329
+ * @returns {ChangeResult}
330
+ * @throws {SQLiteError}
361
331
  */
362
- count(tableName: string, where?: Record<string, any>): Promise<number | {
363
- error: string;
364
- }>;
332
+ delete(tableName: string, where: Where<R>): ChangeResult;
365
333
  /**
366
- * Runs multiple operations inside a transaction.
334
+ * Adds to number columns in one statement, so two requests at the same
335
+ * moment both count. Reading the value, adding to it and writing it back
336
+ * would lose one of them. Negative numbers subtract; an empty column
337
+ * counts as 0.
367
338
  *
368
- * If the callback throws, the transaction is rolled back.
369
- * If the callback completes successfully, the transaction is committed.
339
+ * @example
340
+ * db.increment("posts", { views: 1 }, { id: post.id });
341
+ * db.increment("accounts", { balance: -25, withdrawals: 1 }, { id: account.id });
342
+ *
343
+ * @param {string} tableName
344
+ * @param {Partial<Record<keyof R & string, number>> & Record<string, number>} amounts Column names and how much to add.
345
+ * @param {Where<R>} where
346
+ * @returns {ChangeResult}
347
+ * @throws {SQLiteError}
348
+ */
349
+ increment(tableName: string, amounts: Partial<Record<keyof R & string, number>> & Record<string, number>, where: Where<R>): ChangeResult;
350
+ /**
351
+ * Shortcuts bound to one table, so you don't repeat its name.
370
352
  *
371
- * The callback may be synchronous or asynchronous.
353
+ * @example
354
+ * const users = db.table("users"); // in TypeScript: db.table<User>("users")
355
+ * users.insert({ email: "ada@example.com" });
356
+ * users.count({ active: true });
372
357
  *
373
- * @template T
374
- * @param {() => T|Promise<T>} callback - Function to execute inside the transaction.
375
- * @returns {Promise<T | { error: string }>}
358
+ * @template [T=R]
359
+ * @param {string} tableName The table can be created later.
360
+ * @returns {TableHandle<T>}
361
+ */
362
+ table<T = R>(tableName: string): TableHandle<T>;
363
+ /**
364
+ * Runs `callback` in a transaction: all its changes are saved together, or
365
+ * none are if it throws. The error is then thrown again. Transactions can
366
+ * nest; an inner failure can be caught without losing the outer work.
376
367
  *
377
368
  * @example
378
- * const result = await db.transaction(async () => {
379
- * await db.insert("User", { email: "a@b.com", createdAt: Date.now() });
380
- * await db.insert("Profile", { userId: 1, nickname: "John" });
381
- * return { ok: true };
369
+ * db.transaction(() => {
370
+ * db.increment("accounts", { balance: -amount }, { id: from.id });
371
+ * db.increment("accounts", { balance: amount }, { id: to.id });
382
372
  * });
373
+ *
374
+ * @template T
375
+ * @param {() => T} callback Can be async; the commit then waits for it.
376
+ * @param {TransactionOptions} [options]
377
+ * @returns {T}
378
+ * @throws Whatever `callback` threw, after rolling back.
379
+ */
380
+ transaction<T>(callback: () => T, options?: TransactionOptions): T;
381
+ /** Whether a transaction is open. */
382
+ get inTransaction(): boolean;
383
+ /**
384
+ * Applies migrations in order, each one once. The current version is kept
385
+ * in the database, and each migration runs in its own transaction. Only
386
+ * ever add migrations at the end of the list.
387
+ *
388
+ * @example
389
+ * db.migrate([
390
+ * "CREATE TABLE users (id INTEGER PRIMARY KEY, email TEXT NOT NULL UNIQUE)",
391
+ * "ALTER TABLE users ADD COLUMN name TEXT",
392
+ * (db) => db.update("users", { name: "unknown" }, { name: null }),
393
+ * ]);
394
+ *
395
+ * @param {Migration[]} migrations All of them, from the first.
396
+ * @returns {{ from: number, to: number }} The version before and after.
397
+ * @throws {SQLiteError} If a migration fails. It's rolled back; earlier ones stay.
383
398
  */
384
- transaction<T>(callback: () => T | Promise<T>): Promise<T | {
385
- error: string;
386
- }>;
399
+ migrate(migrations: Migration[]): {
400
+ from: number;
401
+ to: number;
402
+ };
403
+ /** The migration version, stored in `PRAGMA user_version`. */
404
+ get version(): number;
387
405
  /**
388
- * Closes the underlying SQLite connection.
406
+ * Copies the database to a new file. Safe while the app is running.
389
407
  *
390
408
  * @example
391
- * db.close();
409
+ * db.backup(`backups/app-${nc.time.format(new Date(), "YYYY-MM-DD")}.sqlite`);
410
+ *
411
+ * @param {string} path Must not exist yet.
412
+ * @returns {string} The absolute path of the copy.
413
+ * @throws {SQLiteError} If the file exists or can't be written.
414
+ */
415
+ backup(path: string): string;
416
+ /**
417
+ * Compacts the database file to reclaim unused space.
418
+ *
419
+ * @returns {void}
420
+ */
421
+ vacuum(): void;
422
+ /**
423
+ * Makes a JavaScript function callable from SQL.
424
+ *
425
+ * @example
426
+ * db.fn("slugify", (text) => nc.str.slugify(String(text)));
427
+ * db.queryAll("SELECT slugify(title) AS slug FROM posts");
428
+ *
429
+ * @param {string} name
430
+ * @param {(...args: any[]) => null | number | bigint | string | Uint8Array} implementation
431
+ * @param {{ deterministic?: boolean, varargs?: boolean }} [options] `deterministic` (on by default) lets indexes use it; `varargs` accepts any number of arguments.
432
+ * @returns {this}
433
+ */
434
+ fn(name: string, implementation: (...args: any[]) => null | number | bigint | string | Uint8Array, options?: {
435
+ deterministic?: boolean;
436
+ varargs?: boolean;
437
+ }): this;
438
+ /** The absolute path of the database file, or `":memory:"`. */
439
+ get path(): string;
440
+ /** Whether the connection is open. */
441
+ get isOpen(): boolean;
442
+ /**
443
+ * The underlying `node:sqlite` database, for anything not covered here.
444
+ * @returns {import("node:sqlite").DatabaseSync}
445
+ */
446
+ get native(): import("node:sqlite").DatabaseSync;
447
+ /**
448
+ * Closes the connection. Calling it twice is fine.
449
+ *
450
+ * @returns {void}
392
451
  */
393
452
  close(): void;
453
+ /**
454
+ * Closes the connection at the end of a `using` block.
455
+ * @returns {void}
456
+ */
457
+ [Symbol.dispose](): void;
394
458
  #private;
395
459
  }
460
+ declare namespace SQLite {
461
+ export { ColumnType, ForeignKeyAction, ColumnDefinition, TableConstraint, IndexDefinition, TableDefinition, WhereOperators, Where, WhereValue, SortDirection, QueryOptions, SQLiteOptions, InsertResult, ChangeResult, ColumnInfo, Migration, TableHandle, InsertOptions, PaginateOptions, TransactionOptions, _Reader };
462
+ }
463
+ /**
464
+ * A column type. `JSON` and `BOOLEAN` columns give you back objects and
465
+ * `true`/`false`.
466
+ */
467
+ type ColumnType = "INTEGER" | "TEXT" | "REAL" | "BLOB" | "NUMERIC" | "JSON" | "BOOLEAN" | "DATETIME" | (string & {});
468
+ /**
469
+ * What happens to a row when the row it references changes.
470
+ */
471
+ type ForeignKeyAction = "CASCADE" | "SET NULL" | "SET DEFAULT" | "RESTRICT" | "NO ACTION";
472
+ /**
473
+ * A column.
474
+ */
475
+ type ColumnDefinition = {
476
+ /**
477
+ * Like `"INTEGER"`, `"TEXT"`, `"JSON"` or `"VARCHAR(255)"`.
478
+ */
479
+ type: ColumnType;
480
+ primaryKey?: boolean | undefined;
481
+ /**
482
+ * With an `INTEGER` primary key: ids are never reused.
483
+ */
484
+ autoincrement?: boolean | undefined;
485
+ notNull?: boolean | undefined;
486
+ unique?: boolean | undefined;
487
+ /**
488
+ * Objects work for JSON columns, booleans for BOOLEAN ones. `"CURRENT_TIMESTAMP"`, `"CURRENT_DATE"` and `"CURRENT_TIME"` mean the moment of the insert.
489
+ */
490
+ defaultValue?: unknown;
491
+ /**
492
+ * A default computed by SQLite, like `"(unixepoch())"` or `"(lower(hex(randomblob(16))))"`. Written into the table as is: never build it from user input.
493
+ */
494
+ defaultExpression?: string | undefined;
495
+ /**
496
+ * Allowed values.
497
+ */
498
+ values?: unknown[] | undefined;
499
+ /**
500
+ * A `CHECK` expression, like `"price >= 0"`.
501
+ */
502
+ check?: string | undefined;
503
+ /**
504
+ * Foreign key target.
505
+ */
506
+ references?: {
507
+ table: string;
508
+ column: string;
509
+ } | undefined;
510
+ /**
511
+ * When the referenced row is deleted.
512
+ */
513
+ onDelete?: ForeignKeyAction | undefined;
514
+ /**
515
+ * When the referenced key changes.
516
+ */
517
+ onUpdate?: ForeignKeyAction | undefined;
518
+ };
519
+ /**
520
+ * A constraint on several columns.
521
+ */
522
+ type TableConstraint = {
523
+ type: "unique";
524
+ columns: string[];
525
+ } | {
526
+ type: "primaryKey";
527
+ columns: string[];
528
+ } | {
529
+ type: "check";
530
+ expression: string;
531
+ } | {
532
+ type: "foreignKey";
533
+ columns: string[];
534
+ references: {
535
+ table: string;
536
+ columns: string[];
537
+ };
538
+ onDelete?: ForeignKeyAction;
539
+ onUpdate?: ForeignKeyAction;
540
+ };
541
+ /**
542
+ * An index.
543
+ */
544
+ type IndexDefinition = {
545
+ /**
546
+ * Several columns make a composite index.
547
+ */
548
+ columns: string[];
549
+ unique?: boolean | undefined;
550
+ /**
551
+ * Defaults to `idx_<table>_<columns>`.
552
+ */
553
+ name?: string | undefined;
554
+ /**
555
+ * Makes it a partial index, like `"deleted_at IS NULL"`.
556
+ */
557
+ where?: string | undefined;
558
+ };
559
+ /**
560
+ * A table for `createTable()`.
561
+ */
562
+ type TableDefinition = {
563
+ name: string;
564
+ columns?: Record<string, ColumnDefinition> | undefined;
565
+ /**
566
+ * Old name for `columns`, still accepted.
567
+ */
568
+ options?: Record<string, ColumnDefinition> | undefined;
569
+ constraints?: TableConstraint[] | undefined;
570
+ indexes?: IndexDefinition[] | undefined;
571
+ };
572
+ /**
573
+ * Operators for a column in a filter.
574
+ */
575
+ type WhereOperators = {
576
+ /**
577
+ * Equal. `null` means `IS NULL`.
578
+ */
579
+ eq?: unknown;
580
+ /**
581
+ * Not equal. Rows where the column is `NULL` match too.
582
+ */
583
+ ne?: unknown;
584
+ /**
585
+ * Greater than.
586
+ */
587
+ gt?: string | number | bigint | Date | undefined;
588
+ /**
589
+ * Greater than or equal.
590
+ */
591
+ gte?: string | number | bigint | Date | undefined;
592
+ /**
593
+ * Less than.
594
+ */
595
+ lt?: string | number | bigint | Date | undefined;
596
+ /**
597
+ * Less than or equal.
598
+ */
599
+ lte?: string | number | bigint | Date | undefined;
600
+ /**
601
+ * One of these values.
602
+ */
603
+ in?: unknown[] | undefined;
604
+ /**
605
+ * None of these values.
606
+ */
607
+ notIn?: unknown[] | undefined;
608
+ /**
609
+ * A `LIKE` pattern: `%` any text, `_` one character.
610
+ */
611
+ like?: string | undefined;
612
+ notLike?: string | undefined;
613
+ /**
614
+ * A case-sensitive pattern: `*` any text, `?` one character.
615
+ */
616
+ glob?: string | undefined;
617
+ /**
618
+ * From `min` to `max`, both included.
619
+ */
620
+ between?: [unknown, unknown] | undefined;
621
+ /**
622
+ * `true` for `IS NULL`, `false` for `IS NOT NULL`.
623
+ */
624
+ isNull?: boolean | undefined;
625
+ };
626
+ /**
627
+ * A filter. Each key is a column: a value means "equals", `null` means
628
+ * `IS NULL`, an array means "one of", and an object uses operators. Keys
629
+ * combine with AND; use `$or` and `$and` for the rest.
630
+ *
631
+ * A key with dots looks inside a JSON column: `"settings.theme"` is the
632
+ * `theme` key of the `settings` column, `"tags.0"` the first item of `tags`.
633
+ */
634
+ type Where<R = Record<string, any>> = { [K in keyof R]?: WhereValue; } & {
635
+ [path: `${string}.${string}`]: WhereValue;
636
+ } & {
637
+ $or?: Where<R>[];
638
+ $and?: Where<R>[];
639
+ };
640
+ /**
641
+ * The condition for one column: a value, `null`, an array, or operators.
642
+ */
643
+ type WhereValue = null | string | number | bigint | boolean | Date | Uint8Array | readonly unknown[] | WhereOperators;
644
+ /**
645
+ * Sort direction.
646
+ */
647
+ type SortDirection = "ASC" | "DESC" | "asc" | "desc";
648
+ /**
649
+ * Options for `getAll()`.
650
+ */
651
+ type QueryOptions = {
652
+ /**
653
+ * Like `"created_at"` or `[["age", "DESC"], "name"]`.
654
+ */
655
+ orderBy?: string | (string | [string, SortDirection])[] | undefined;
656
+ /**
657
+ * For a single `orderBy` column. Defaults to `"ASC"`.
658
+ */
659
+ direction?: SortDirection | undefined;
660
+ limit?: number | undefined;
661
+ /**
662
+ * Rows to skip, for pagination.
663
+ */
664
+ offset?: number | undefined;
665
+ /**
666
+ * Columns to return. Defaults to all.
667
+ */
668
+ columns?: string[] | undefined;
669
+ };
670
+ /**
671
+ * Options for `new SQLite()`.
672
+ */
673
+ type SQLiteOptions = {
674
+ /**
675
+ * Parse `JSON` columns. Defaults to `true`.
676
+ */
677
+ json?: boolean | undefined;
678
+ /**
679
+ * Return `BOOLEAN` columns as `true`/`false`. Defaults to `true`.
680
+ */
681
+ booleans?: boolean | undefined;
682
+ /**
683
+ * Return `DATE`, `DATETIME` and `TIMESTAMP` columns as `Date`s.
684
+ */
685
+ dates?: boolean | undefined;
686
+ /**
687
+ * Write-ahead logging: faster, and reads don't wait for writes. Defaults to `true`.
688
+ */
689
+ wal?: boolean | undefined;
690
+ /**
691
+ * Enforce foreign keys. Defaults to `true`.
692
+ */
693
+ foreignKeys?: boolean | undefined;
694
+ /**
695
+ * How long to wait for a lock held by another connection, in ms or like `"5s"`. Defaults to 5 seconds.
696
+ */
697
+ busyTimeout?: string | number | undefined;
698
+ /**
699
+ * How hard SQLite pushes each commit to the disk. With `wal`, `"NORMAL"` writes several times faster and can't corrupt the file; a power cut may undo the last commits. Defaults to SQLite's own setting, `"FULL"`.
700
+ */
701
+ synchronous?: "OFF" | "NORMAL" | "FULL" | "EXTRA" | undefined;
702
+ readOnly?: boolean | undefined;
703
+ };
704
+ /**
705
+ * What an insert returns.
706
+ */
707
+ type InsertResult = {
708
+ ok: true;
709
+ changes: number;
710
+ lastInsertRowid: number | bigint;
711
+ };
712
+ /**
713
+ * What an update or delete returns.
714
+ */
715
+ type ChangeResult = {
716
+ ok: true;
717
+ changes: number;
718
+ };
719
+ /**
720
+ * A column, as returned by `columns()`.
721
+ */
722
+ type ColumnInfo = {
723
+ name: string;
724
+ /**
725
+ * `""` when there's none.
726
+ */
727
+ type: string;
728
+ notNull: boolean;
729
+ /**
730
+ * As SQL text, or `null`.
731
+ */
732
+ defaultValue: unknown;
733
+ primaryKey: boolean;
734
+ };
735
+ /**
736
+ * A migration: SQL (several statements are fine), or a function that gets
737
+ * the database.
738
+ */
739
+ type Migration = string | ((db: SQLite<any>) => void);
740
+ /**
741
+ * Shortcuts bound to one table, from `table()`.
742
+ */
743
+ type TableHandle<R = Record<string, any>> = {
744
+ name: string;
745
+ /**
746
+ * The first matching row.
747
+ */
748
+ get: (where?: Where<R>, options?: Pick<QueryOptions, "columns" | "orderBy" | "direction">) => R | undefined;
749
+ /**
750
+ * All matching rows.
751
+ */
752
+ getAll: (where?: Where<R>, options?: QueryOptions) => R[];
753
+ /**
754
+ * One page of matching rows.
755
+ */
756
+ paginate: (where?: Where<R>, options?: PaginateOptions) => import("./Arr").Page<R>;
757
+ /**
758
+ * Inserts a row.
759
+ */
760
+ insert: (data: Partial<R>, options?: InsertOptions) => InsertResult;
761
+ /**
762
+ * Inserts rows in one transaction.
763
+ */
764
+ insertMany: (rows: Iterable<Partial<R>>, options?: InsertOptions) => ChangeResult;
765
+ /**
766
+ * Updates matching rows.
767
+ */
768
+ update: (data: Partial<R>, where: Where<R>) => ChangeResult;
769
+ /**
770
+ * Adds to number columns.
771
+ */
772
+ increment: (amounts: Partial<Record<keyof R & string, number>>, where: Where<R>) => ChangeResult;
773
+ /**
774
+ * Inserts, or updates on conflict.
775
+ */
776
+ upsert: (data: Partial<R>, conflict: string[]) => InsertResult;
777
+ /**
778
+ * Deletes matching rows.
779
+ */
780
+ delete: (where: Where<R>) => ChangeResult;
781
+ /**
782
+ * Counts matching rows.
783
+ */
784
+ count: (where?: Where<R>) => number;
785
+ /**
786
+ * Does any row match?
787
+ */
788
+ exists: (where?: Where<R>) => boolean;
789
+ /**
790
+ * Deletes every row.
791
+ */
792
+ clear: () => {
793
+ ok: true;
794
+ };
795
+ };
796
+ /**
797
+ * Options for `insert()` and `insertMany()`.
798
+ */
799
+ type InsertOptions = {
800
+ /**
801
+ * What to do when a row clashes with an existing one: `"ignore"` skips it, `"replace"` deletes the old row first. By default, the insert fails.
802
+ */
803
+ onConflict?: "replace" | "ignore" | undefined;
804
+ };
805
+ /**
806
+ * Options for `paginate()`.
807
+ */
808
+ type PaginateOptions = {
809
+ /**
810
+ * Starts at 1, which is the default.
811
+ */
812
+ page?: number | undefined;
813
+ /**
814
+ * Defaults to `20`.
815
+ */
816
+ perPage?: number | undefined;
817
+ /**
818
+ * Give one: without it, SQLite is free to return the rows in any order.
819
+ */
820
+ orderBy?: string | (string | [string, SortDirection])[] | undefined;
821
+ direction?: SortDirection | undefined;
822
+ columns?: string[] | undefined;
823
+ };
824
+ /**
825
+ * Options for `transaction()`.
826
+ */
827
+ type TransactionOptions = {
828
+ /**
829
+ * Take the write lock right away, instead of on the first write. Use it for read-then-write work when several processes share the database: they then wait for each other instead of failing with `SQLITE_BUSY`.
830
+ */
831
+ immediate?: boolean | undefined;
832
+ };
833
+ /**
834
+ * A prepared query and what's needed to turn its rows into objects.
835
+ */
836
+ type _Reader = {
837
+ stmt: import("node:sqlite").StatementSync;
838
+ names: string[] | undefined;
839
+ kinds: Uint8Array | undefined;
840
+ table: string | undefined;
841
+ };
396
842
  //# sourceMappingURL=SQLite.d.ts.map