@symbiote-native/sqlite 0.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 (128) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +283 -0
  3. package/build/angular/index.d.ts +2 -0
  4. package/build/angular/index.js +2 -0
  5. package/build/angular/sqlite.service.d.ts +41 -0
  6. package/build/angular/sqlite.service.js +127 -0
  7. package/build/core/index.d.ts +10 -0
  8. package/build/core/index.js +6 -0
  9. package/build/core/native-database.d.ts +65 -0
  10. package/build/core/native-database.js +13 -0
  11. package/build/core/native-module.d.ts +25 -0
  12. package/build/core/native-module.js +17 -0
  13. package/build/core/native-session.d.ts +20 -0
  14. package/build/core/native-session.js +1 -0
  15. package/build/core/native-statement.d.ts +45 -0
  16. package/build/core/native-statement.js +6 -0
  17. package/build/core/param-utils.d.ts +28 -0
  18. package/build/core/param-utils.js +126 -0
  19. package/build/core/path-utils.d.ts +6 -0
  20. package/build/core/path-utils.js +29 -0
  21. package/build/core/query-utils.d.ts +17 -0
  22. package/build/core/query-utils.js +37 -0
  23. package/build/core/sqlite-database.d.ts +246 -0
  24. package/build/core/sqlite-database.js +427 -0
  25. package/build/core/sqlite-session.d.ts +84 -0
  26. package/build/core/sqlite-session.js +121 -0
  27. package/build/core/sqlite-statement.d.ts +96 -0
  28. package/build/core/sqlite-statement.js +321 -0
  29. package/build/core/sqlite-tagged-query.d.ts +73 -0
  30. package/build/core/sqlite-tagged-query.js +119 -0
  31. package/build/core/storage.d.ts +107 -0
  32. package/build/core/storage.js +382 -0
  33. package/build/core/types.d.ts +30 -0
  34. package/build/core/types.js +1 -0
  35. package/build/react/index.d.ts +2 -0
  36. package/build/react/index.js +2 -0
  37. package/build/react/sqlite-context.d.ts +25 -0
  38. package/build/react/sqlite-context.js +129 -0
  39. package/build/solid/index.d.ts +2 -0
  40. package/build/solid/index.js +2 -0
  41. package/build/solid/sqlite-context.d.ts +23 -0
  42. package/build/solid/sqlite-context.js +106 -0
  43. package/build/svelte/SQLiteProvider.svelte +88 -0
  44. package/build/svelte/SQLiteProvider.svelte.d.ts +13 -0
  45. package/build/svelte/index.d.ts +3 -0
  46. package/build/svelte/index.js +5 -0
  47. package/build/svelte/sqlite-context.d.ts +11 -0
  48. package/build/svelte/sqlite-context.js +23 -0
  49. package/build/vue/index.d.ts +2 -0
  50. package/build/vue/index.js +2 -0
  51. package/build/vue/sqlite-context.d.ts +21 -0
  52. package/build/vue/sqlite-context.js +69 -0
  53. package/build-ngc/angular/index.d.ts +2 -0
  54. package/build-ngc/angular/index.js +3 -0
  55. package/build-ngc/angular/index.js.map +1 -0
  56. package/build-ngc/angular/sqlite.service.d.ts +44 -0
  57. package/build-ngc/angular/sqlite.service.js +85 -0
  58. package/build-ngc/angular/sqlite.service.js.map +1 -0
  59. package/build-ngc/core/index.d.ts +10 -0
  60. package/build-ngc/core/index.js +7 -0
  61. package/build-ngc/core/index.js.map +1 -0
  62. package/build-ngc/core/native-database.d.ts +65 -0
  63. package/build-ngc/core/native-database.js +14 -0
  64. package/build-ngc/core/native-database.js.map +1 -0
  65. package/build-ngc/core/native-module.d.ts +25 -0
  66. package/build-ngc/core/native-module.js +18 -0
  67. package/build-ngc/core/native-module.js.map +1 -0
  68. package/build-ngc/core/native-session.d.ts +20 -0
  69. package/build-ngc/core/native-session.js +2 -0
  70. package/build-ngc/core/native-session.js.map +1 -0
  71. package/build-ngc/core/native-statement.d.ts +45 -0
  72. package/build-ngc/core/native-statement.js +7 -0
  73. package/build-ngc/core/native-statement.js.map +1 -0
  74. package/build-ngc/core/param-utils.d.ts +28 -0
  75. package/build-ngc/core/param-utils.js +127 -0
  76. package/build-ngc/core/param-utils.js.map +1 -0
  77. package/build-ngc/core/path-utils.d.ts +6 -0
  78. package/build-ngc/core/path-utils.js +30 -0
  79. package/build-ngc/core/path-utils.js.map +1 -0
  80. package/build-ngc/core/query-utils.d.ts +17 -0
  81. package/build-ngc/core/query-utils.js +38 -0
  82. package/build-ngc/core/query-utils.js.map +1 -0
  83. package/build-ngc/core/sqlite-database.d.ts +246 -0
  84. package/build-ngc/core/sqlite-database.js +428 -0
  85. package/build-ngc/core/sqlite-database.js.map +1 -0
  86. package/build-ngc/core/sqlite-session.d.ts +84 -0
  87. package/build-ngc/core/sqlite-session.js +122 -0
  88. package/build-ngc/core/sqlite-session.js.map +1 -0
  89. package/build-ngc/core/sqlite-statement.d.ts +96 -0
  90. package/build-ngc/core/sqlite-statement.js +322 -0
  91. package/build-ngc/core/sqlite-statement.js.map +1 -0
  92. package/build-ngc/core/sqlite-tagged-query.d.ts +73 -0
  93. package/build-ngc/core/sqlite-tagged-query.js +120 -0
  94. package/build-ngc/core/sqlite-tagged-query.js.map +1 -0
  95. package/build-ngc/core/storage.d.ts +107 -0
  96. package/build-ngc/core/storage.js +383 -0
  97. package/build-ngc/core/storage.js.map +1 -0
  98. package/build-ngc/core/types.d.ts +30 -0
  99. package/build-ngc/core/types.js +2 -0
  100. package/build-ngc/core/types.js.map +1 -0
  101. package/native-link.json +12 -0
  102. package/package.json +141 -0
  103. package/src/angular/index.ts +2 -0
  104. package/src/angular/sqlite.service.ts +114 -0
  105. package/src/core/index.ts +40 -0
  106. package/src/core/native-database.ts +118 -0
  107. package/src/core/native-module.ts +57 -0
  108. package/src/core/native-session.ts +64 -0
  109. package/src/core/native-statement.ts +85 -0
  110. package/src/core/param-utils.ts +163 -0
  111. package/src/core/path-utils.ts +38 -0
  112. package/src/core/query-utils.ts +45 -0
  113. package/src/core/sqlite-database.ts +676 -0
  114. package/src/core/sqlite-session.ts +165 -0
  115. package/src/core/sqlite-statement.ts +578 -0
  116. package/src/core/sqlite-tagged-query.ts +160 -0
  117. package/src/core/storage.ts +492 -0
  118. package/src/core/types.ts +33 -0
  119. package/src/react/index.ts +2 -0
  120. package/src/react/sqlite-context.tsx +244 -0
  121. package/src/solid/index.ts +2 -0
  122. package/src/solid/sqlite-context.ts +156 -0
  123. package/src/svelte/SQLiteProvider.svelte +88 -0
  124. package/src/svelte/index.ts +6 -0
  125. package/src/svelte/sqlite-context.ts +32 -0
  126. package/src/svelte/svelte-compile.test-helper.ts +135 -0
  127. package/src/vue/index.ts +2 -0
  128. package/src/vue/sqlite-context.ts +105 -0
@@ -0,0 +1,96 @@
1
+ import type { NativeDatabase } from './native-database';
2
+ import type { NativeStatement, ISQLiteBindParams, ISQLiteVariadicBindParams } from './native-statement';
3
+ export type { ISQLiteBindParams, ISQLiteBindValue, ISQLiteRunResult, ISQLiteVariadicBindParams, } from './native-statement';
4
+ type IValuesOf<T extends object> = T[keyof T][];
5
+ /**
6
+ * A prepared statement returned by `SQLiteDatabase.prepareAsync()`/`prepareSync()`, bound with
7
+ * parameters and executed.
8
+ */
9
+ export declare class SQLiteStatement {
10
+ private readonly nativeDatabase;
11
+ private readonly nativeStatement;
12
+ constructor(nativeDatabase: NativeDatabase, nativeStatement: NativeStatement);
13
+ /** Runs the prepared statement and returns an `ISQLiteExecuteAsyncResult`. */
14
+ executeAsync<T>(params: ISQLiteBindParams): Promise<ISQLiteExecuteAsyncResult<T>>;
15
+ /** @hidden */
16
+ executeAsync<T>(...params: ISQLiteVariadicBindParams): Promise<ISQLiteExecuteAsyncResult<T>>;
17
+ /**
18
+ * Like `executeAsync()` but returns the raw value-array result instead of row objects.
19
+ * @hidden Advanced use only.
20
+ */
21
+ executeForRawResultAsync<T extends object>(params: ISQLiteBindParams): Promise<ISQLiteExecuteAsyncResult<IValuesOf<T>>>;
22
+ /** @hidden */
23
+ executeForRawResultAsync<T extends object>(...params: ISQLiteVariadicBindParams): Promise<ISQLiteExecuteAsyncResult<IValuesOf<T>>>;
24
+ /** Gets the column names of the prepared statement. */
25
+ getColumnNamesAsync(): Promise<string[]>;
26
+ /**
27
+ * Finalizes the prepared statement — calls
28
+ * [`sqlite3_finalize()`](https://www.sqlite.org/c3ref/finalize.html) under the hood.
29
+ * Accessing a finalized statement afterward throws. `expo-sqlite` finalizes any orphaned
30
+ * statement automatically when its database closes, but finalize as soon as you no longer
31
+ * need one — wrap the call in `try...finally` so it runs even if an earlier step throws.
32
+ */
33
+ finalizeAsync(): Promise<void>;
34
+ /**
35
+ * Runs the prepared statement and returns an `ISQLiteExecuteSyncResult`.
36
+ * > **Note:** Running heavy tasks with this function can block the JavaScript thread.
37
+ */
38
+ executeSync<T>(params: ISQLiteBindParams): ISQLiteExecuteSyncResult<T>;
39
+ /** @hidden */
40
+ executeSync<T>(...params: ISQLiteVariadicBindParams): ISQLiteExecuteSyncResult<T>;
41
+ /**
42
+ * Like `executeSync()` but returns the raw value-array result instead of row objects.
43
+ * @hidden Advanced use only.
44
+ */
45
+ executeForRawResultSync<T extends object>(params: ISQLiteBindParams): ISQLiteExecuteSyncResult<IValuesOf<T>>;
46
+ /** @hidden */
47
+ executeForRawResultSync<T extends object>(...params: ISQLiteVariadicBindParams): ISQLiteExecuteSyncResult<IValuesOf<T>>;
48
+ /** Gets the column names of the prepared statement. */
49
+ getColumnNamesSync(): string[];
50
+ /**
51
+ * Finalizes the prepared statement synchronously.
52
+ * > **Note:** Running heavy tasks with this function can block the JavaScript thread.
53
+ */
54
+ finalizeSync(): void;
55
+ }
56
+ /** A result returned by `SQLiteStatement.executeAsync()`. */
57
+ export type ISQLiteExecuteAsyncResult<T> = AsyncIterableIterator<T> & {
58
+ /** The last inserted row ID, from `sqlite3_last_insert_rowid()`. */
59
+ readonly lastInsertRowId: number;
60
+ /** The number of rows affected, from `sqlite3_changes()`. */
61
+ readonly changes: number;
62
+ /**
63
+ * Gets the first row of the result set. Requires the cursor to be in its initial state —
64
+ * call `resetAsync()` first if rows have already been retrieved, or this throws.
65
+ */
66
+ getFirstAsync(): Promise<T | null>;
67
+ /**
68
+ * Gets all rows of the result set. Requires the cursor to be in its initial state — call
69
+ * `resetAsync()` first if rows have already been retrieved, or this throws.
70
+ */
71
+ getAllAsync(): Promise<T[]>;
72
+ /** Resets the prepared statement's cursor — calls `sqlite3_reset()` under the hood. */
73
+ resetAsync(): Promise<void>;
74
+ };
75
+ /**
76
+ * A result returned by `SQLiteStatement.executeSync()`.
77
+ * > **Note:** Running heavy tasks with this function can block the JavaScript thread.
78
+ */
79
+ export type ISQLiteExecuteSyncResult<T> = IterableIterator<T> & {
80
+ /** The last inserted row ID, from `sqlite3_last_insert_rowid()`. */
81
+ readonly lastInsertRowId: number;
82
+ /** The number of rows affected, from `sqlite3_changes()`. */
83
+ readonly changes: number;
84
+ /**
85
+ * Gets the first row of the result set. Requires the cursor to be in its initial state — call
86
+ * `resetSync()` first if rows have already been retrieved, or this throws.
87
+ */
88
+ getFirstSync(): T | null;
89
+ /**
90
+ * Gets all rows of the result set. Requires the cursor to be in its initial state — call
91
+ * `resetSync()` first if rows have already been retrieved, or this throws.
92
+ */
93
+ getAllSync(): T[];
94
+ /** Resets the prepared statement's cursor — calls `sqlite3_reset()` under the hood. */
95
+ resetSync(): void;
96
+ };
@@ -0,0 +1,321 @@
1
+ import { composeRow, composeRows, normalizeParams } from './param-utils.js';
2
+ /**
3
+ * A prepared statement returned by `SQLiteDatabase.prepareAsync()`/`prepareSync()`, bound with
4
+ * parameters and executed.
5
+ */
6
+ export class SQLiteStatement {
7
+ nativeDatabase;
8
+ nativeStatement;
9
+ constructor(nativeDatabase, nativeStatement) {
10
+ this.nativeDatabase = nativeDatabase;
11
+ this.nativeStatement = nativeStatement;
12
+ }
13
+ async executeAsync(...params) {
14
+ const { lastInsertRowId, changes, firstRowValues } = await this.nativeStatement.runAsync(this.nativeDatabase, ...normalizeParams(...params));
15
+ return createSQLiteExecuteAsyncResult(this.nativeDatabase, this.nativeStatement, firstRowValues, { rawResult: false, lastInsertRowId, changes });
16
+ }
17
+ async executeForRawResultAsync(...params) {
18
+ const { lastInsertRowId, changes, firstRowValues } = await this.nativeStatement.runAsync(this.nativeDatabase, ...normalizeParams(...params));
19
+ return createSQLiteExecuteAsyncResult(this.nativeDatabase, this.nativeStatement, firstRowValues, { rawResult: true, lastInsertRowId, changes });
20
+ }
21
+ /** Gets the column names of the prepared statement. */
22
+ getColumnNamesAsync() {
23
+ return this.nativeStatement.getColumnNamesAsync();
24
+ }
25
+ /**
26
+ * Finalizes the prepared statement — calls
27
+ * [`sqlite3_finalize()`](https://www.sqlite.org/c3ref/finalize.html) under the hood.
28
+ * Accessing a finalized statement afterward throws. `expo-sqlite` finalizes any orphaned
29
+ * statement automatically when its database closes, but finalize as soon as you no longer
30
+ * need one — wrap the call in `try...finally` so it runs even if an earlier step throws.
31
+ */
32
+ async finalizeAsync() {
33
+ await this.nativeStatement.finalizeAsync(this.nativeDatabase);
34
+ }
35
+ executeSync(...params) {
36
+ const { lastInsertRowId, changes, firstRowValues } = this.nativeStatement.runSync(this.nativeDatabase, ...normalizeParams(...params));
37
+ return createSQLiteExecuteSyncResult(this.nativeDatabase, this.nativeStatement, firstRowValues, { rawResult: false, lastInsertRowId, changes });
38
+ }
39
+ executeForRawResultSync(...params) {
40
+ const { lastInsertRowId, changes, firstRowValues } = this.nativeStatement.runSync(this.nativeDatabase, ...normalizeParams(...params));
41
+ return createSQLiteExecuteSyncResult(this.nativeDatabase, this.nativeStatement, firstRowValues, { rawResult: true, lastInsertRowId, changes });
42
+ }
43
+ /** Gets the column names of the prepared statement. */
44
+ getColumnNamesSync() {
45
+ return this.nativeStatement.getColumnNamesSync();
46
+ }
47
+ /**
48
+ * Finalizes the prepared statement synchronously.
49
+ * > **Note:** Running heavy tasks with this function can block the JavaScript thread.
50
+ */
51
+ finalizeSync() {
52
+ this.nativeStatement.finalizeSync(this.nativeDatabase);
53
+ }
54
+ }
55
+ /**
56
+ * Creates the `ISQLiteExecuteAsyncResult` — an async generator with the extra fields/methods
57
+ * attached via `Object.defineProperties`, since Hermes does not support `Symbol.asyncIterator`
58
+ * on a plain object literal.
59
+ */
60
+ async function createSQLiteExecuteAsyncResult(database, statement, firstRowValues, options) {
61
+ const instance = new SQLiteExecuteAsyncResultImpl(database, statement, firstRowValues ? processNativeRow(firstRowValues) : null, options);
62
+ const generator = instance.generatorAsync();
63
+ Object.defineProperties(generator, {
64
+ lastInsertRowId: {
65
+ value: options.lastInsertRowId,
66
+ enumerable: true,
67
+ writable: false,
68
+ configurable: true,
69
+ },
70
+ changes: {
71
+ value: options.changes,
72
+ enumerable: true,
73
+ writable: false,
74
+ configurable: true,
75
+ },
76
+ getFirstAsync: {
77
+ value: instance.getFirstAsync.bind(instance),
78
+ enumerable: true,
79
+ writable: false,
80
+ configurable: true,
81
+ },
82
+ getAllAsync: {
83
+ value: instance.getAllAsync.bind(instance),
84
+ enumerable: true,
85
+ writable: false,
86
+ configurable: true,
87
+ },
88
+ resetAsync: {
89
+ value: instance.resetAsync.bind(instance),
90
+ enumerable: true,
91
+ writable: false,
92
+ configurable: true,
93
+ },
94
+ });
95
+ // I/O edge: the generator is given the four extra members above at runtime via
96
+ // `Object.defineProperties` — nothing narrower can describe that to the type checker.
97
+ return generator;
98
+ }
99
+ /** Creates the `ISQLiteExecuteSyncResult`. */
100
+ function createSQLiteExecuteSyncResult(database, statement, firstRowValues, options) {
101
+ const instance = new SQLiteExecuteSyncResultImpl(database, statement, firstRowValues ? processNativeRow(firstRowValues) : firstRowValues, options);
102
+ const generator = instance.generatorSync();
103
+ Object.defineProperties(generator, {
104
+ lastInsertRowId: {
105
+ value: options.lastInsertRowId,
106
+ enumerable: true,
107
+ writable: false,
108
+ configurable: true,
109
+ },
110
+ changes: {
111
+ value: options.changes,
112
+ enumerable: true,
113
+ writable: false,
114
+ configurable: true,
115
+ },
116
+ getFirstSync: {
117
+ value: instance.getFirstSync.bind(instance),
118
+ enumerable: true,
119
+ writable: false,
120
+ configurable: true,
121
+ },
122
+ getAllSync: {
123
+ value: instance.getAllSync.bind(instance),
124
+ enumerable: true,
125
+ writable: false,
126
+ configurable: true,
127
+ },
128
+ resetSync: {
129
+ value: instance.resetSync.bind(instance),
130
+ enumerable: true,
131
+ writable: false,
132
+ configurable: true,
133
+ },
134
+ });
135
+ // I/O edge: see createSQLiteExecuteAsyncResult above.
136
+ return generator;
137
+ }
138
+ class SQLiteExecuteAsyncResultImpl {
139
+ database;
140
+ statement;
141
+ firstRowValues;
142
+ options;
143
+ columnNames = null;
144
+ isStepCalled = false;
145
+ constructor(database, statement, firstRowValues, options) {
146
+ this.database = database;
147
+ this.statement = statement;
148
+ this.firstRowValues = firstRowValues;
149
+ this.options = options;
150
+ }
151
+ async getFirstAsync() {
152
+ if (this.isStepCalled) {
153
+ throw new Error('The SQLite cursor has been shifted and is unable to retrieve the first row without being reset. Invoke `resetAsync()` to reset the cursor first if you want to retrieve the first row.');
154
+ }
155
+ this.isStepCalled = true;
156
+ const columnNames = await this.getColumnNamesAsync();
157
+ const firstRowValues = this.popFirstRowValues();
158
+ if (firstRowValues != null) {
159
+ return composeRowIfNeeded(this.options.rawResult, columnNames, firstRowValues);
160
+ }
161
+ const firstRow = await this.statement.stepAsync(this.database);
162
+ return firstRow != null
163
+ ? composeRowIfNeeded(this.options.rawResult, columnNames, processNativeRow(firstRow))
164
+ : null;
165
+ }
166
+ async getAllAsync() {
167
+ if (this.isStepCalled) {
168
+ throw new Error('The SQLite cursor has been shifted and is unable to retrieve all rows without being reset. Invoke `resetAsync()` to reset the cursor first if you want to retrieve all rows.');
169
+ }
170
+ this.isStepCalled = true;
171
+ const firstRowValues = this.popFirstRowValues();
172
+ if (firstRowValues == null) {
173
+ // An empty first row means this SQL was a write operation — calling getAllAsync() again
174
+ // would write a second time.
175
+ return [];
176
+ }
177
+ const columnNames = await this.getColumnNamesAsync();
178
+ const nativeRows = await this.statement.getAllAsync(this.database);
179
+ const allRows = processNativeRows(nativeRows);
180
+ if (firstRowValues.length > 0) {
181
+ return composeRowsIfNeeded(this.options.rawResult, columnNames, [
182
+ firstRowValues,
183
+ ...allRows,
184
+ ]);
185
+ }
186
+ return composeRowsIfNeeded(this.options.rawResult, columnNames, allRows);
187
+ }
188
+ async *generatorAsync() {
189
+ this.isStepCalled = true;
190
+ const columnNames = await this.getColumnNamesAsync();
191
+ const firstRowValues = this.popFirstRowValues();
192
+ if (firstRowValues != null) {
193
+ yield composeRowIfNeeded(this.options.rawResult, columnNames, firstRowValues);
194
+ }
195
+ let result;
196
+ do {
197
+ result = await this.statement.stepAsync(this.database);
198
+ if (result != null) {
199
+ yield composeRowIfNeeded(this.options.rawResult, columnNames, processNativeRow(result));
200
+ }
201
+ } while (result != null);
202
+ }
203
+ resetAsync() {
204
+ const result = this.statement.resetAsync(this.database);
205
+ this.isStepCalled = false;
206
+ return result;
207
+ }
208
+ popFirstRowValues() {
209
+ if (this.firstRowValues != null) {
210
+ const firstRowValues = this.firstRowValues;
211
+ this.firstRowValues = null;
212
+ return firstRowValues.length > 0 ? firstRowValues : null;
213
+ }
214
+ return null;
215
+ }
216
+ async getColumnNamesAsync() {
217
+ if (this.columnNames == null) {
218
+ this.columnNames = await this.statement.getColumnNamesAsync();
219
+ }
220
+ return this.columnNames;
221
+ }
222
+ }
223
+ class SQLiteExecuteSyncResultImpl {
224
+ database;
225
+ statement;
226
+ firstRowValues;
227
+ options;
228
+ columnNames = null;
229
+ isStepCalled = false;
230
+ constructor(database, statement, firstRowValues, options) {
231
+ this.database = database;
232
+ this.statement = statement;
233
+ this.firstRowValues = firstRowValues;
234
+ this.options = options;
235
+ }
236
+ getFirstSync() {
237
+ if (this.isStepCalled) {
238
+ throw new Error('The SQLite cursor has been shifted and is unable to retrieve the first row without being reset. Invoke `resetSync()` to reset the cursor first if you want to retrieve the first row.');
239
+ }
240
+ const columnNames = this.getColumnNamesSync();
241
+ const firstRowValues = this.popFirstRowValues();
242
+ if (firstRowValues != null) {
243
+ return composeRowIfNeeded(this.options.rawResult, columnNames, firstRowValues);
244
+ }
245
+ const firstRow = this.statement.stepSync(this.database);
246
+ return firstRow != null
247
+ ? composeRowIfNeeded(this.options.rawResult, columnNames, processNativeRow(firstRow))
248
+ : null;
249
+ }
250
+ getAllSync() {
251
+ if (this.isStepCalled) {
252
+ throw new Error('The SQLite cursor has been shifted and is unable to retrieve all rows without being reset. Invoke `resetSync()` to reset the cursor first if you want to retrieve all rows.');
253
+ }
254
+ const firstRowValues = this.popFirstRowValues();
255
+ if (firstRowValues == null) {
256
+ return [];
257
+ }
258
+ const columnNames = this.getColumnNamesSync();
259
+ const nativeRows = this.statement.getAllSync(this.database);
260
+ const allRows = processNativeRows(nativeRows);
261
+ if (firstRowValues.length > 0) {
262
+ return composeRowsIfNeeded(this.options.rawResult, columnNames, [
263
+ firstRowValues,
264
+ ...allRows,
265
+ ]);
266
+ }
267
+ return composeRowsIfNeeded(this.options.rawResult, columnNames, allRows);
268
+ }
269
+ *generatorSync() {
270
+ const columnNames = this.getColumnNamesSync();
271
+ const firstRowValues = this.popFirstRowValues();
272
+ if (firstRowValues != null) {
273
+ yield composeRowIfNeeded(this.options.rawResult, columnNames, firstRowValues);
274
+ }
275
+ let result;
276
+ do {
277
+ result = this.statement.stepSync(this.database);
278
+ if (result != null) {
279
+ yield composeRowIfNeeded(this.options.rawResult, columnNames, processNativeRow(result));
280
+ }
281
+ } while (result != null);
282
+ }
283
+ resetSync() {
284
+ const result = this.statement.resetSync(this.database);
285
+ this.isStepCalled = false;
286
+ return result;
287
+ }
288
+ popFirstRowValues() {
289
+ if (this.firstRowValues != null) {
290
+ const firstRowValues = this.firstRowValues;
291
+ this.firstRowValues = null;
292
+ return firstRowValues.length > 0 ? firstRowValues : null;
293
+ }
294
+ return null;
295
+ }
296
+ getColumnNamesSync() {
297
+ if (this.columnNames == null) {
298
+ this.columnNames = this.statement.getColumnNamesSync();
299
+ }
300
+ return this.columnNames;
301
+ }
302
+ }
303
+ function composeRowIfNeeded(rawResult, columnNames, columnValues) {
304
+ // I/O edge: `rawResult` selects between two shapes of T (a row object, or `IValuesOf<T>`) that
305
+ // only the caller's own generic parameter distinguishes — see the two call sites above.
306
+ return rawResult
307
+ ? columnValues
308
+ : composeRow(columnNames, columnValues);
309
+ }
310
+ function composeRowsIfNeeded(rawResult, columnNames, columnValuesList) {
311
+ return rawResult
312
+ ? columnValuesList
313
+ : composeRows(columnNames, columnValuesList);
314
+ }
315
+ function processNativeRow(nativeRow) {
316
+ return nativeRow.map(column => column instanceof ArrayBuffer ? new Uint8Array(column) : column);
317
+ }
318
+ function processNativeRows(nativeRows) {
319
+ return nativeRows.map(processNativeRow);
320
+ }
321
+ //#endregion
@@ -0,0 +1,73 @@
1
+ import type { ISQLiteRunResult } from './native-statement';
2
+ import type { SQLiteDatabase } from './sqlite-database';
3
+ /**
4
+ * Returns `T[]` when a type parameter is explicitly given, or a union of the possible shapes
5
+ * when relying on the default `unknown` type.
6
+ */
7
+ type ISQLiteTaggedQueryResult<T> = [unknown] extends [T] ? unknown[] | ISQLiteRunResult : T[];
8
+ /**
9
+ * A SQL query built from a tagged template literal, awaitable directly (returns an array of
10
+ * objects by default) or reshaped via `.values()` / `.first()` / `.each()`. Bun's `sql` API is
11
+ * the inspiration (credited upstream).
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * const users = await sql`SELECT * FROM users WHERE age > ${21}`;
16
+ * const values = await sql`SELECT name, age FROM users`.values(); // [["Alice", 30], ...]
17
+ * const user = await sql`SELECT * FROM users WHERE id = ${1}`.first();
18
+ * const users = await sql<User>`SELECT * FROM users`; // typed
19
+ * const result = (await sql`INSERT INTO users (name) VALUES (${'Alice'})`) as ISQLiteRunResult;
20
+ * const users = sql<User>`SELECT * FROM users WHERE age > ${21}`.allSync();
21
+ * ```
22
+ */
23
+ export declare class SQLiteTaggedQuery<T = unknown> implements PromiseLike<ISQLiteTaggedQueryResult<T>> {
24
+ private readonly database;
25
+ private readonly source;
26
+ private readonly params;
27
+ private readonly parsedInfo;
28
+ constructor(database: SQLiteDatabase, strings: TemplateStringsArray, values: unknown[]);
29
+ /**
30
+ * Makes the query awaitable, returning rows or metadata depending on the query's shape — called
31
+ * automatically when the tagged query is `await`ed.
32
+ */
33
+ then<TResult1 = ISQLiteTaggedQueryResult<T>, TResult2 = never>(onfulfilled?: ((value: ISQLiteTaggedQueryResult<T>) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null): PromiseLike<TResult1 | TResult2>;
34
+ /**
35
+ * Executes the query and returns rows as arrays of values (Bun-style) instead of objects.
36
+ * @example
37
+ * ```ts
38
+ * const rows = await sql`SELECT name, age FROM users`.values(); // [["Alice", 30], ...]
39
+ * ```
40
+ */
41
+ values(): Promise<unknown[][]>;
42
+ /** Executes the query and returns the first row only, or `null` if no rows match. */
43
+ first(): Promise<T | null>;
44
+ /**
45
+ * Executes the query and returns an async iterator over the rows.
46
+ * @example
47
+ * ```ts
48
+ * for await (const user of sql`SELECT * FROM users`.each()) { console.log(user.name); }
49
+ * ```
50
+ */
51
+ each(): AsyncIterableIterator<T>;
52
+ /**
53
+ * Executes the query synchronously, returning rows or metadata depending on the query's shape.
54
+ * > **Note:** Running heavy tasks with this function can block the JavaScript thread.
55
+ */
56
+ allSync(): ISQLiteTaggedQueryResult<T>;
57
+ /**
58
+ * Executes the query synchronously and returns rows as arrays of values.
59
+ * > **Note:** Running heavy tasks with this function can block the JavaScript thread.
60
+ */
61
+ valuesSync(): unknown[][];
62
+ /**
63
+ * Executes the query synchronously and returns the first row.
64
+ * > **Note:** Running heavy tasks with this function can block the JavaScript thread.
65
+ */
66
+ firstSync(): T | null;
67
+ /**
68
+ * Executes the query synchronously and returns an iterator.
69
+ * > **Note:** Running heavy tasks with this function can block the JavaScript thread.
70
+ */
71
+ eachSync(): IterableIterator<T>;
72
+ }
73
+ export {};
@@ -0,0 +1,119 @@
1
+ import { parseSQLQuery } from './query-utils.js';
2
+ /**
3
+ * A SQL query built from a tagged template literal, awaitable directly (returns an array of
4
+ * objects by default) or reshaped via `.values()` / `.first()` / `.each()`. Bun's `sql` API is
5
+ * the inspiration (credited upstream).
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * const users = await sql`SELECT * FROM users WHERE age > ${21}`;
10
+ * const values = await sql`SELECT name, age FROM users`.values(); // [["Alice", 30], ...]
11
+ * const user = await sql`SELECT * FROM users WHERE id = ${1}`.first();
12
+ * const users = await sql<User>`SELECT * FROM users`; // typed
13
+ * const result = (await sql`INSERT INTO users (name) VALUES (${'Alice'})`) as ISQLiteRunResult;
14
+ * const users = sql<User>`SELECT * FROM users WHERE age > ${21}`.allSync();
15
+ * ```
16
+ */
17
+ export class SQLiteTaggedQuery {
18
+ database;
19
+ source;
20
+ params;
21
+ parsedInfo;
22
+ constructor(database, strings, values) {
23
+ this.database = database;
24
+ const sql = strings.join('?');
25
+ this.source = sql;
26
+ // I/O edge: a tagged-template interpolation site (`${...}`) is only constrained to
27
+ // ISQLiteBindValue by the public overload of `SQLiteDatabase.sql`; nothing narrower can be
28
+ // inferred from `TemplateStringsArray`'s own interpolated-value type (`unknown[]` by design).
29
+ this.params = values;
30
+ this.parsedInfo = parseSQLQuery(sql);
31
+ }
32
+ /**
33
+ * Makes the query awaitable, returning rows or metadata depending on the query's shape — called
34
+ * automatically when the tagged query is `await`ed.
35
+ */
36
+ then(onfulfilled, onrejected) {
37
+ if (this.parsedInfo.canReturnRows) {
38
+ return this.database
39
+ .getAllAsync(this.source, this.params)
40
+ .then(rows => rows)
41
+ .then(onfulfilled, onrejected);
42
+ }
43
+ return this.database
44
+ .runAsync(this.source, this.params)
45
+ .then(result => result)
46
+ .then(onfulfilled, onrejected);
47
+ }
48
+ /**
49
+ * Executes the query and returns rows as arrays of values (Bun-style) instead of objects.
50
+ * @example
51
+ * ```ts
52
+ * const rows = await sql`SELECT name, age FROM users`.values(); // [["Alice", 30], ...]
53
+ * ```
54
+ */
55
+ async values() {
56
+ const statement = await this.database.prepareAsync(this.source);
57
+ try {
58
+ const result = await statement.executeForRawResultAsync(this.params);
59
+ return await result.getAllAsync();
60
+ }
61
+ finally {
62
+ await statement.finalizeAsync();
63
+ }
64
+ }
65
+ /** Executes the query and returns the first row only, or `null` if no rows match. */
66
+ async first() {
67
+ return this.database.getFirstAsync(this.source, this.params);
68
+ }
69
+ /**
70
+ * Executes the query and returns an async iterator over the rows.
71
+ * @example
72
+ * ```ts
73
+ * for await (const user of sql`SELECT * FROM users`.each()) { console.log(user.name); }
74
+ * ```
75
+ */
76
+ each() {
77
+ return this.database.getEachAsync(this.source, this.params);
78
+ }
79
+ //#region Synchronous variants
80
+ /**
81
+ * Executes the query synchronously, returning rows or metadata depending on the query's shape.
82
+ * > **Note:** Running heavy tasks with this function can block the JavaScript thread.
83
+ */
84
+ allSync() {
85
+ // I/O edge: see `ISQLiteTaggedQueryResult`'s own definition — the conditional type cannot be
86
+ // narrowed from `canReturnRows`, a plain runtime boolean.
87
+ return this.parsedInfo.canReturnRows
88
+ ? this.database.getAllSync(this.source, this.params)
89
+ : this.database.runSync(this.source, this.params);
90
+ }
91
+ /**
92
+ * Executes the query synchronously and returns rows as arrays of values.
93
+ * > **Note:** Running heavy tasks with this function can block the JavaScript thread.
94
+ */
95
+ valuesSync() {
96
+ const statement = this.database.prepareSync(this.source);
97
+ try {
98
+ const result = statement.executeForRawResultSync(this.params);
99
+ return result.getAllSync();
100
+ }
101
+ finally {
102
+ statement.finalizeSync();
103
+ }
104
+ }
105
+ /**
106
+ * Executes the query synchronously and returns the first row.
107
+ * > **Note:** Running heavy tasks with this function can block the JavaScript thread.
108
+ */
109
+ firstSync() {
110
+ return this.database.getFirstSync(this.source, this.params);
111
+ }
112
+ /**
113
+ * Executes the query synchronously and returns an iterator.
114
+ * > **Note:** Running heavy tasks with this function can block the JavaScript thread.
115
+ */
116
+ eachSync() {
117
+ return this.database.getEachSync(this.source, this.params);
118
+ }
119
+ }