encore.dev 1.46.17 → 1.46.19

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,5 +1,5 @@
1
1
  // The version of the runtime this JS bundle was generated for.
2
- const version = "v1.46.17";
2
+ const version = "v1.46.19";
3
3
 
4
4
  // Load the native module.
5
5
  const nativeModulePath = process.env.ENCORE_RUNTIME_LIB;
@@ -42,6 +42,7 @@ const {
42
42
  SqlConn,
43
43
  SqlDatabase,
44
44
  Stream,
45
+ Transaction,
45
46
  TypedObjectError,
46
47
  WebSocketClient,
47
48
  } = nativeModule;
@@ -78,6 +79,7 @@ module.exports = {
78
79
  SqlConn,
79
80
  SqlDatabase,
80
81
  Stream,
82
+ Transaction,
81
83
  TypedObjectError,
82
84
  WebSocketClient,
83
85
  };
@@ -303,6 +303,8 @@ export class SqlDatabase {
303
303
  acquire(): Promise<SQLConn>
304
304
  /** Reports the connection string to connect to this database. */
305
305
  connString(): string
306
+ /** Begins a transaction */
307
+ begin(source?: Request | undefined | null): Promise<Transaction>
306
308
  query(query: string, args: QueryArgs, source?: Request | undefined | null): Promise<Cursor>
307
309
  queryRow(query: string, args: QueryArgs, source?: Request | undefined | null): Promise<Row | null>
308
310
  }
@@ -320,6 +322,12 @@ export interface TraceData {
320
322
  extCorrelationId?: string
321
323
  }
322
324
 
325
+ export class Transaction {
326
+ commit(source?: Request | undefined | null): Promise<void>
327
+ rollback(source?: Request | undefined | null): Promise<void>
328
+ query(query: string, args: QueryArgs, source?: Request | undefined | null): Promise<Cursor>
329
+ }
330
+
323
331
  export class TypedObjectError {
324
332
  kind: ObjectErrorKind
325
333
  message: string
@@ -1,4 +1,5 @@
1
1
  /// <reference types="node" />
2
+ /// <reference types="node" />
2
3
  import * as runtime from "../../internal/runtime/mod.js";
3
4
  import { StringLiteral } from "../../internal/utils/constraints.js";
4
5
  export interface SQLMigrationsConfig {
@@ -14,28 +15,11 @@ export interface SQLDatabaseConfig {
14
15
  export type Row = Record<string, any>;
15
16
  /** Represents a type that can be used in query template literals */
16
17
  export type Primitive = string | string[] | number | number[] | boolean | boolean[] | Buffer | Date | Date[] | Record<string, any> | Record<string, any>[] | null | undefined;
17
- /**
18
- * Constructing a new database object will result in Encore provisioning a database with
19
- * that name and returning this object to represent it.
20
- *
21
- * If you want to reference an existing database, use `Database.Named(name)` as it is a
22
- * compile error to create duplicate databases.
23
- */
24
- export declare class SQLDatabase {
25
- private readonly impl;
26
- /**
27
- * Creates a new database with the given name and configuration
28
- */
29
- constructor(name: string, cfg?: SQLDatabaseConfig);
30
- /**
31
- * Reference an existing database by name, if the database doesn't
32
- * exist yet, use `new Database(name)` instead.
33
- */
34
- static named<name extends string>(name: StringLiteral<name>): SQLDatabase;
35
- /**
36
- * Returns the connection string for the database
37
- */
38
- get connectionString(): string;
18
+ type SQLQueryExecutor = runtime.SQLConn | runtime.SQLDatabase | runtime.Transaction;
19
+ /** Base class containing shared query functionality */
20
+ declare class BaseQueryExecutor {
21
+ protected readonly impl: SQLQueryExecutor;
22
+ constructor(impl: SQLQueryExecutor);
39
23
  /**
40
24
  * query queries the database using a template string, replacing your placeholders in the template
41
25
  * with parametrised values without risking SQL injections.
@@ -142,128 +126,64 @@ export declare class SQLDatabase {
142
126
  * @returns A promise that resolves when the query has been executed.
143
127
  */
144
128
  rawExec(query: string, ...params: Primitive[]): Promise<void>;
145
- /**
146
- * Acquires a database connection from the database pool.
147
- *
148
- * When the connection is closed or is garbage-collected, it is returned to the pool.
149
- * @returns a new connection to the database
150
- */
151
- acquire(): Promise<Connection>;
152
129
  }
153
130
  /**
154
- * Represents a dedicated connection to a database.
131
+ * Constructing a new database object will result in Encore provisioning a database with
132
+ * that name and returning this object to represent it.
133
+ *
134
+ * If you want to reference an existing database, use `Database.Named(name)` as it is a
135
+ * compile error to create duplicate databases.
155
136
  */
156
- export declare class Connection {
157
- private readonly impl;
158
- constructor(impl: runtime.SQLConn);
159
- /**
160
- * Returns the connection to the database pool.
161
- */
162
- close(): Promise<void>;
163
- /**
164
- * query queries the database using a template string, replacing your placeholders in the template
165
- * with parametrised values without risking SQL injections.
166
- *
167
- * It returns an async generator, that allows iterating over the results
168
- * in a streaming fashion using `for await`.
169
- *
170
- * @example
171
- *
172
- * const email = "foo@example.com";
173
- * const result = database.query`SELECT id FROM users WHERE email=${email}`
174
- *
175
- * This produces the query: "SELECT id FROM users WHERE email=$1".
176
- */
177
- query<T extends Row = Record<string, any>>(strings: TemplateStringsArray, ...params: Primitive[]): AsyncGenerator<T>;
137
+ export declare class SQLDatabase extends BaseQueryExecutor {
138
+ protected readonly impl: runtime.SQLDatabase;
139
+ constructor(name: string, cfg?: SQLDatabaseConfig);
178
140
  /**
179
- * rawQuery queries the database using a raw parametrised SQL query and parameters.
180
- *
181
- * It returns an async generator, that allows iterating over the results
182
- * in a streaming fashion using `for await`.
183
- *
184
- * @example
185
- * const query = "SELECT id FROM users WHERE email=$1";
186
- * const email = "foo@example.com";
187
- * for await (const row of database.rawQuery(query, email)) {
188
- * console.log(row);
189
- * }
190
- *
191
- * @param query - The raw SQL query string.
192
- * @param params - The parameters to be used in the query.
193
- * @returns An async generator that yields rows from the query result.
141
+ * Reference an existing database by name, if the database doesn't
142
+ * exist yet, use `new Database(name)` instead.
194
143
  */
195
- rawQuery<T extends Row = Record<string, any>>(query: string, ...params: Primitive[]): AsyncGenerator<T>;
144
+ static named<name extends string>(name: StringLiteral<name>): SQLDatabase;
196
145
  /**
197
- * queryAll queries the database using a template string, replacing your placeholders in the template
198
- * with parametrised values without risking SQL injections.
199
- *
200
- * It returns an array of all results.
201
- *
202
- * @example
203
- *
204
- * const email = "foo@example.com";
205
- * const result = database.queryAll`SELECT id FROM users WHERE email=${email}`
206
- *
207
- * This produces the query: "SELECT id FROM users WHERE email=$1".
146
+ * Returns the connection string for the database
208
147
  */
209
- queryAll<T extends Row = Record<string, any>>(strings: TemplateStringsArray, ...params: Primitive[]): Promise<T[]>;
148
+ get connectionString(): string;
210
149
  /**
211
- * rawQueryAll queries the database using a raw parametrised SQL query and parameters.
212
- *
213
- * It returns an array of all results.
214
- *
215
- * @example
150
+ * Acquires a database connection from the database pool.
216
151
  *
217
- * const query = "SELECT id FROM users WHERE email=$1";
218
- * const email = "foo@example.com";
219
- * const rows = await database.rawQueryAll(query, email);
152
+ * When the connection is closed or is garbage-collected, it is returned to the pool.
153
+ * @returns a new connection to the database
220
154
  */
221
- rawQueryAll<T extends Row = Record<string, any>>(query: string, ...params: Primitive[]): Promise<T[]>;
155
+ acquire(): Promise<Connection>;
222
156
  /**
223
- * queryRow is like query but returns only a single row.
224
- * If the query selects no rows it returns null.
225
- * Otherwise it returns the first row and discards the rest.
157
+ * Begins a database transaction.
226
158
  *
227
- * @example
228
- * const email = "foo@example.com";
229
- * const result = database.queryRow`SELECT id FROM users WHERE email=${email}`
159
+ * Make sure to always call `rollback` or `commit` to prevent hanging transactions.
160
+ * @returns a transaction object that implements AsycDisposable
230
161
  */
231
- queryRow<T extends Row = Record<string, any>>(strings: TemplateStringsArray, ...params: Primitive[]): Promise<T | null>;
162
+ begin(): Promise<Transaction>;
163
+ }
164
+ export declare class Transaction extends BaseQueryExecutor implements AsyncDisposable {
165
+ protected readonly impl: runtime.Transaction;
166
+ private done;
167
+ constructor(impl: runtime.Transaction);
232
168
  /**
233
- * rawQueryRow is like rawQuery but returns only a single row.
234
- * If the query selects no rows, it returns null.
235
- * Otherwise, it returns the first row and discards the rest.
236
- *
237
- * @example
238
- * const query = "SELECT id FROM users WHERE email=$1";
239
- * const email = "foo@example.com";
240
- * const result = await database.rawQueryRow(query, email);
241
- * console.log(result);
242
- *
243
- * @param query - The raw SQL query string.
244
- * @param params - The parameters to be used in the query.
245
- * @returns A promise that resolves to a single row or null.
169
+ * Commit the transaction.
246
170
  */
247
- rawQueryRow<T extends Row = Record<string, any>>(query: string, ...params: Primitive[]): Promise<T | null>;
171
+ commit(): Promise<void>;
248
172
  /**
249
- * exec executes a query without returning any rows.
250
- *
251
- * @example
252
- * const email = "foo@example.com";
253
- * const result = database.exec`DELETE FROM users WHERE email=${email}`
173
+ * Rollback the transaction.
254
174
  */
255
- exec(strings: TemplateStringsArray, ...params: Primitive[]): Promise<void>;
175
+ rollback(): Promise<void>;
176
+ [Symbol.asyncDispose](): Promise<void>;
177
+ }
178
+ /**
179
+ * Represents a dedicated connection to a database.
180
+ */
181
+ export declare class Connection extends BaseQueryExecutor {
182
+ protected readonly impl: runtime.SQLConn;
183
+ constructor(impl: runtime.SQLConn);
256
184
  /**
257
- * rawExec executes a query without returning any rows.
258
- *
259
- * @example
260
- * const query = "DELETE FROM users WHERE email=$1";
261
- * const email = "foo@example.com";
262
- * await database.rawExec(query, email);
263
- *
264
- * @param query - The raw SQL query string.
265
- * @param params - The parameters to be used in the query.
266
- * @returns A promise that resolves when the query has been executed.
185
+ * Returns the connection to the database pool.
267
186
  */
268
- rawExec(query: string, ...params: Primitive[]): Promise<void>;
187
+ close(): Promise<void>;
269
188
  }
189
+ export {};
@@ -1,34 +1,11 @@
1
1
  import { getCurrentRequest } from "../../internal/reqtrack/mod.js";
2
2
  import * as runtime from "../../internal/runtime/mod.js";
3
3
  const driverName = "node-pg";
4
- /**
5
- * Constructing a new database object will result in Encore provisioning a database with
6
- * that name and returning this object to represent it.
7
- *
8
- * If you want to reference an existing database, use `Database.Named(name)` as it is a
9
- * compile error to create duplicate databases.
10
- */
11
- export class SQLDatabase {
4
+ /** Base class containing shared query functionality */
5
+ class BaseQueryExecutor {
12
6
  impl;
13
- /**
14
- * Creates a new database with the given name and configuration
15
- */
16
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
17
- constructor(name, cfg) {
18
- this.impl = runtime.RT.sqlDatabase(name);
19
- }
20
- /**
21
- * Reference an existing database by name, if the database doesn't
22
- * exist yet, use `new Database(name)` instead.
23
- */
24
- static named(name) {
25
- return new SQLDatabase(name);
26
- }
27
- /**
28
- * Returns the connection string for the database
29
- */
30
- get connectionString() {
31
- return this.impl.connString();
7
+ constructor(impl) {
8
+ this.impl = impl;
32
9
  }
33
10
  /**
34
11
  * query queries the database using a template string, replacing your placeholders in the template
@@ -52,9 +29,8 @@ export class SQLDatabase {
52
29
  const cursor = await this.impl.query(query, args, source);
53
30
  while (true) {
54
31
  const row = await cursor.next();
55
- if (row === null) {
32
+ if (row === null)
56
33
  break;
57
- }
58
34
  yield row.values();
59
35
  }
60
36
  }
@@ -81,9 +57,8 @@ export class SQLDatabase {
81
57
  const result = await this.impl.query(query, args, source);
82
58
  while (true) {
83
59
  const row = await result.next();
84
- if (row === null) {
60
+ if (row === null)
85
61
  break;
86
- }
87
62
  yield row.values();
88
63
  }
89
64
  }
@@ -109,9 +84,8 @@ export class SQLDatabase {
109
84
  const result = [];
110
85
  while (true) {
111
86
  const row = await cursor.next();
112
- if (row === null) {
87
+ if (row === null)
113
88
  break;
114
- }
115
89
  result.push(row.values());
116
90
  }
117
91
  return result;
@@ -135,9 +109,8 @@ export class SQLDatabase {
135
109
  const result = [];
136
110
  while (true) {
137
111
  const row = await cursor.next();
138
- if (row === null) {
112
+ if (row === null)
139
113
  break;
140
- }
141
114
  result.push(row.values());
142
115
  }
143
116
  return result;
@@ -157,10 +130,8 @@ export class SQLDatabase {
157
130
  const args = buildQueryArgs(params);
158
131
  const source = getCurrentRequest();
159
132
  const result = await this.impl.query(query, args, source);
160
- while (true) {
161
- const row = await result.next();
162
- return row ? row.values() : null;
163
- }
133
+ const row = await result.next();
134
+ return row ? row.values() : null;
164
135
  }
165
136
  /**
166
137
  * rawQueryRow is like rawQuery but returns only a single row.
@@ -181,10 +152,8 @@ export class SQLDatabase {
181
152
  const args = buildQueryArgs(params);
182
153
  const source = getCurrentRequest();
183
154
  const result = await this.impl.query(query, args, source);
184
- while (true) {
185
- const row = await result.next();
186
- return row ? row.values() : null;
187
- }
155
+ const row = await result.next();
156
+ return row ? row.values() : null;
188
157
  }
189
158
  /**
190
159
  * exec executes a query without returning any rows.
@@ -199,7 +168,7 @@ export class SQLDatabase {
199
168
  const source = getCurrentRequest();
200
169
  // Need to await the cursor to process any errors from things like
201
170
  // unique constraint violations.
202
- let cur = await this.impl.query(query, args, source);
171
+ const cur = await this.impl.query(query, args, source);
203
172
  await cur.next();
204
173
  }
205
174
  /**
@@ -219,225 +188,95 @@ export class SQLDatabase {
219
188
  const source = getCurrentRequest();
220
189
  // Need to await the cursor to process any errors from things like
221
190
  // unique constraint violations.
222
- let cur = await this.impl.query(query, args, source);
191
+ const cur = await this.impl.query(query, args, source);
223
192
  await cur.next();
224
193
  }
225
- /**
226
- * Acquires a database connection from the database pool.
227
- *
228
- * When the connection is closed or is garbage-collected, it is returned to the pool.
229
- * @returns a new connection to the database
230
- */
231
- async acquire() {
232
- const impl = await this.impl.acquire();
233
- return new Connection(impl);
234
- }
235
194
  }
236
195
  /**
237
- * Represents a dedicated connection to a database.
196
+ * Constructing a new database object will result in Encore provisioning a database with
197
+ * that name and returning this object to represent it.
198
+ *
199
+ * If you want to reference an existing database, use `Database.Named(name)` as it is a
200
+ * compile error to create duplicate databases.
238
201
  */
239
- export class Connection {
240
- impl;
241
- constructor(impl) {
242
- this.impl = impl;
202
+ export class SQLDatabase extends BaseQueryExecutor {
203
+ constructor(name, cfg) {
204
+ super(runtime.RT.sqlDatabase(name));
243
205
  }
244
206
  /**
245
- * Returns the connection to the database pool.
207
+ * Reference an existing database by name, if the database doesn't
208
+ * exist yet, use `new Database(name)` instead.
246
209
  */
247
- async close() {
248
- await this.impl.close();
210
+ static named(name) {
211
+ return new SQLDatabase(name);
249
212
  }
250
213
  /**
251
- * query queries the database using a template string, replacing your placeholders in the template
252
- * with parametrised values without risking SQL injections.
253
- *
254
- * It returns an async generator, that allows iterating over the results
255
- * in a streaming fashion using `for await`.
256
- *
257
- * @example
258
- *
259
- * const email = "foo@example.com";
260
- * const result = database.query`SELECT id FROM users WHERE email=${email}`
261
- *
262
- * This produces the query: "SELECT id FROM users WHERE email=$1".
214
+ * Returns the connection string for the database
263
215
  */
264
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
265
- async *query(strings, ...params) {
266
- const query = buildQuery(strings, params);
267
- const args = buildQueryArgs(params);
268
- const source = getCurrentRequest();
269
- const cursor = await this.impl.query(query, args, source);
270
- while (true) {
271
- const row = await cursor.next();
272
- if (row === null) {
273
- break;
274
- }
275
- yield row.values();
276
- }
216
+ get connectionString() {
217
+ return this.impl.connString();
277
218
  }
278
219
  /**
279
- * rawQuery queries the database using a raw parametrised SQL query and parameters.
280
- *
281
- * It returns an async generator, that allows iterating over the results
282
- * in a streaming fashion using `for await`.
283
- *
284
- * @example
285
- * const query = "SELECT id FROM users WHERE email=$1";
286
- * const email = "foo@example.com";
287
- * for await (const row of database.rawQuery(query, email)) {
288
- * console.log(row);
289
- * }
220
+ * Acquires a database connection from the database pool.
290
221
  *
291
- * @param query - The raw SQL query string.
292
- * @param params - The parameters to be used in the query.
293
- * @returns An async generator that yields rows from the query result.
222
+ * When the connection is closed or is garbage-collected, it is returned to the pool.
223
+ * @returns a new connection to the database
294
224
  */
295
- async *rawQuery(query, ...params) {
296
- const args = buildQueryArgs(params);
297
- const source = getCurrentRequest();
298
- const result = await this.impl.query(query, args, source);
299
- while (true) {
300
- const row = await result.next();
301
- if (row === null) {
302
- break;
303
- }
304
- yield row.values();
305
- }
225
+ async acquire() {
226
+ const impl = await this.impl.acquire();
227
+ return new Connection(impl);
306
228
  }
307
229
  /**
308
- * queryAll queries the database using a template string, replacing your placeholders in the template
309
- * with parametrised values without risking SQL injections.
310
- *
311
- * It returns an array of all results.
312
- *
313
- * @example
314
- *
315
- * const email = "foo@example.com";
316
- * const result = database.queryAll`SELECT id FROM users WHERE email=${email}`
230
+ * Begins a database transaction.
317
231
  *
318
- * This produces the query: "SELECT id FROM users WHERE email=$1".
232
+ * Make sure to always call `rollback` or `commit` to prevent hanging transactions.
233
+ * @returns a transaction object that implements AsycDisposable
319
234
  */
320
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
321
- async queryAll(strings, ...params) {
322
- const query = buildQuery(strings, params);
323
- const args = buildQueryArgs(params);
235
+ async begin() {
324
236
  const source = getCurrentRequest();
325
- const cursor = await this.impl.query(query, args, source);
326
- const result = [];
327
- while (true) {
328
- const row = await cursor.next();
329
- if (row === null) {
330
- break;
331
- }
332
- result.push(row.values());
333
- }
334
- return result;
237
+ const impl = await this.impl.begin(source);
238
+ return new Transaction(impl);
335
239
  }
336
- /**
337
- * rawQueryAll queries the database using a raw parametrised SQL query and parameters.
338
- *
339
- * It returns an array of all results.
340
- *
341
- * @example
342
- *
343
- * const query = "SELECT id FROM users WHERE email=$1";
344
- * const email = "foo@example.com";
345
- * const rows = await database.rawQueryAll(query, email);
346
- */
347
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
348
- async rawQueryAll(query, ...params) {
349
- const args = buildQueryArgs(params);
350
- const source = getCurrentRequest();
351
- const cursor = await this.impl.query(query, args, source);
352
- const result = [];
353
- while (true) {
354
- const row = await cursor.next();
355
- if (row === null) {
356
- break;
357
- }
358
- result.push(row.values());
359
- }
360
- return result;
240
+ }
241
+ export class Transaction extends BaseQueryExecutor {
242
+ done = false;
243
+ constructor(impl) {
244
+ super(impl);
361
245
  }
362
246
  /**
363
- * queryRow is like query but returns only a single row.
364
- * If the query selects no rows it returns null.
365
- * Otherwise it returns the first row and discards the rest.
366
- *
367
- * @example
368
- * const email = "foo@example.com";
369
- * const result = database.queryRow`SELECT id FROM users WHERE email=${email}`
247
+ * Commit the transaction.
370
248
  */
371
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
372
- async queryRow(strings, ...params) {
373
- const query = buildQuery(strings, params);
374
- const args = buildQueryArgs(params);
249
+ async commit() {
250
+ this.done = true;
375
251
  const source = getCurrentRequest();
376
- const result = await this.impl.query(query, args, source);
377
- while (true) {
378
- const row = await result.next();
379
- return row ? row.values() : null;
380
- }
252
+ await this.impl.commit(source);
381
253
  }
382
254
  /**
383
- * rawQueryRow is like rawQuery but returns only a single row.
384
- * If the query selects no rows, it returns null.
385
- * Otherwise, it returns the first row and discards the rest.
386
- *
387
- * @example
388
- * const query = "SELECT id FROM users WHERE email=$1";
389
- * const email = "foo@example.com";
390
- * const result = await database.rawQueryRow(query, email);
391
- * console.log(result);
392
- *
393
- * @param query - The raw SQL query string.
394
- * @param params - The parameters to be used in the query.
395
- * @returns A promise that resolves to a single row or null.
255
+ * Rollback the transaction.
396
256
  */
397
- async rawQueryRow(query, ...params) {
398
- const args = buildQueryArgs(params);
257
+ async rollback() {
258
+ this.done = true;
399
259
  const source = getCurrentRequest();
400
- const result = await this.impl.query(query, args, source);
401
- while (true) {
402
- const row = await result.next();
403
- return row ? row.values() : null;
260
+ await this.impl.rollback(source);
261
+ }
262
+ async [Symbol.asyncDispose]() {
263
+ if (!this.done) {
264
+ await this.rollback();
404
265
  }
405
266
  }
406
- /**
407
- * exec executes a query without returning any rows.
408
- *
409
- * @example
410
- * const email = "foo@example.com";
411
- * const result = database.exec`DELETE FROM users WHERE email=${email}`
412
- */
413
- async exec(strings, ...params) {
414
- const query = buildQuery(strings, params);
415
- const args = buildQueryArgs(params);
416
- const source = getCurrentRequest();
417
- // Need to await the cursor to process any errors from things like
418
- // unique constraint violations.
419
- let cur = await this.impl.query(query, args, source);
420
- await cur.next();
267
+ }
268
+ /**
269
+ * Represents a dedicated connection to a database.
270
+ */
271
+ export class Connection extends BaseQueryExecutor {
272
+ constructor(impl) {
273
+ super(impl);
421
274
  }
422
275
  /**
423
- * rawExec executes a query without returning any rows.
424
- *
425
- * @example
426
- * const query = "DELETE FROM users WHERE email=$1";
427
- * const email = "foo@example.com";
428
- * await database.rawExec(query, email);
429
- *
430
- * @param query - The raw SQL query string.
431
- * @param params - The parameters to be used in the query.
432
- * @returns A promise that resolves when the query has been executed.
276
+ * Returns the connection to the database pool.
433
277
  */
434
- async rawExec(query, ...params) {
435
- const args = buildQueryArgs(params);
436
- const source = getCurrentRequest();
437
- // Need to await the cursor to process any errors from things like
438
- // unique constraint violations.
439
- let cur = await this.impl.query(query, args, source);
440
- await cur.next();
278
+ async close() {
279
+ await this.impl.close();
441
280
  }
442
281
  }
443
282
  function buildQuery(strings, expr) {