@tursodatabase/serverless 1.0.0 → 1.1.0-pre.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/connection.d.ts +5 -4
- package/dist/connection.js +8 -8
- package/dist/error.d.ts +10 -0
- package/dist/error.js +14 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/protocol.d.ts +7 -2
- package/dist/protocol.js +60 -27
- package/dist/session.d.ts +9 -6
- package/dist/session.js +20 -13
- package/dist/statement.d.ts +5 -5
- package/dist/statement.js +8 -8
- package/package.json +1 -1
package/dist/connection.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type SessionConfig } from './session.js';
|
|
2
2
|
import { Statement } from './statement.js';
|
|
3
|
+
import { type QueryOptions } from './protocol.js';
|
|
3
4
|
/**
|
|
4
5
|
* Configuration options for connecting to a Turso database.
|
|
5
6
|
*/
|
|
@@ -91,7 +92,7 @@ export declare class Connection {
|
|
|
91
92
|
* console.log(result.rows);
|
|
92
93
|
* ```
|
|
93
94
|
*/
|
|
94
|
-
execute(sql: string, args?: any[]): Promise<any>;
|
|
95
|
+
execute(sql: string, args?: any[], queryOptions?: QueryOptions): Promise<any>;
|
|
95
96
|
/**
|
|
96
97
|
* Execute a SQL statement and return all results.
|
|
97
98
|
*
|
|
@@ -104,7 +105,7 @@ export declare class Connection {
|
|
|
104
105
|
* console.log(result.rows);
|
|
105
106
|
* ```
|
|
106
107
|
*/
|
|
107
|
-
exec(sql: string): Promise<any>;
|
|
108
|
+
exec(sql: string, queryOptions?: QueryOptions): Promise<any>;
|
|
108
109
|
/**
|
|
109
110
|
* Execute multiple SQL statements in a batch.
|
|
110
111
|
*
|
|
@@ -121,14 +122,14 @@ export declare class Connection {
|
|
|
121
122
|
* ]);
|
|
122
123
|
* ```
|
|
123
124
|
*/
|
|
124
|
-
batch(statements: string[], mode?: string): Promise<any>;
|
|
125
|
+
batch(statements: string[], mode?: string, queryOptions?: QueryOptions): Promise<any>;
|
|
125
126
|
/**
|
|
126
127
|
* Execute a pragma.
|
|
127
128
|
*
|
|
128
129
|
* @param pragma - The pragma to execute
|
|
129
130
|
* @returns Promise resolving to the result of the pragma
|
|
130
131
|
*/
|
|
131
|
-
pragma(pragma: string): Promise<any>;
|
|
132
|
+
pragma(pragma: string, queryOptions?: QueryOptions): Promise<any>;
|
|
132
133
|
/**
|
|
133
134
|
* Sets the default safe integers mode for all statements from this connection.
|
|
134
135
|
*
|
package/dist/connection.js
CHANGED
|
@@ -111,13 +111,13 @@ export class Connection {
|
|
|
111
111
|
* console.log(result.rows);
|
|
112
112
|
* ```
|
|
113
113
|
*/
|
|
114
|
-
async execute(sql, args) {
|
|
114
|
+
async execute(sql, args, queryOptions) {
|
|
115
115
|
if (!this.isOpen) {
|
|
116
116
|
throw new TypeError("The database connection is not open");
|
|
117
117
|
}
|
|
118
118
|
await this.execLock.acquire();
|
|
119
119
|
try {
|
|
120
|
-
return await this.session.execute(sql, args || [], this.defaultSafeIntegerMode);
|
|
120
|
+
return await this.session.execute(sql, args || [], this.defaultSafeIntegerMode, queryOptions);
|
|
121
121
|
}
|
|
122
122
|
finally {
|
|
123
123
|
this.execLock.release();
|
|
@@ -135,13 +135,13 @@ export class Connection {
|
|
|
135
135
|
* console.log(result.rows);
|
|
136
136
|
* ```
|
|
137
137
|
*/
|
|
138
|
-
async exec(sql) {
|
|
138
|
+
async exec(sql, queryOptions) {
|
|
139
139
|
if (!this.isOpen) {
|
|
140
140
|
throw new TypeError("The database connection is not open");
|
|
141
141
|
}
|
|
142
142
|
await this.execLock.acquire();
|
|
143
143
|
try {
|
|
144
|
-
return await this.session.sequence(sql);
|
|
144
|
+
return await this.session.sequence(sql, queryOptions);
|
|
145
145
|
}
|
|
146
146
|
finally {
|
|
147
147
|
this.execLock.release();
|
|
@@ -163,13 +163,13 @@ export class Connection {
|
|
|
163
163
|
* ]);
|
|
164
164
|
* ```
|
|
165
165
|
*/
|
|
166
|
-
async batch(statements, mode) {
|
|
166
|
+
async batch(statements, mode, queryOptions) {
|
|
167
167
|
if (!this.isOpen) {
|
|
168
168
|
throw new TypeError("The database connection is not open");
|
|
169
169
|
}
|
|
170
170
|
await this.execLock.acquire();
|
|
171
171
|
try {
|
|
172
|
-
return await this.session.batch(statements);
|
|
172
|
+
return await this.session.batch(statements, queryOptions);
|
|
173
173
|
}
|
|
174
174
|
finally {
|
|
175
175
|
this.execLock.release();
|
|
@@ -181,14 +181,14 @@ export class Connection {
|
|
|
181
181
|
* @param pragma - The pragma to execute
|
|
182
182
|
* @returns Promise resolving to the result of the pragma
|
|
183
183
|
*/
|
|
184
|
-
async pragma(pragma) {
|
|
184
|
+
async pragma(pragma, queryOptions) {
|
|
185
185
|
if (!this.isOpen) {
|
|
186
186
|
throw new TypeError("The database connection is not open");
|
|
187
187
|
}
|
|
188
188
|
await this.execLock.acquire();
|
|
189
189
|
try {
|
|
190
190
|
const sql = `PRAGMA ${pragma}`;
|
|
191
|
-
return await this.session.execute(sql);
|
|
191
|
+
return await this.session.execute(sql, [], false, queryOptions);
|
|
192
192
|
}
|
|
193
193
|
finally {
|
|
194
194
|
this.execLock.release();
|
package/dist/error.d.ts
CHANGED
|
@@ -7,3 +7,13 @@ export declare class DatabaseError extends Error {
|
|
|
7
7
|
cause?: Error;
|
|
8
8
|
constructor(message: string, code?: string, rawCode?: number, cause?: Error);
|
|
9
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Error thrown when a query exceeds the configured timeout.
|
|
12
|
+
*
|
|
13
|
+
* This is a subclass of `DatabaseError` with `code` set to `"TIMEOUT"`.
|
|
14
|
+
* Catch this type to distinguish timeouts from other database errors
|
|
15
|
+
* and decide whether to retry or fail gracefully.
|
|
16
|
+
*/
|
|
17
|
+
export declare class TimeoutError extends DatabaseError {
|
|
18
|
+
constructor(message?: string, cause?: Error);
|
|
19
|
+
}
|
package/dist/error.js
CHANGED
|
@@ -8,3 +8,17 @@ export class DatabaseError extends Error {
|
|
|
8
8
|
Object.setPrototypeOf(this, DatabaseError.prototype);
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Error thrown when a query exceeds the configured timeout.
|
|
13
|
+
*
|
|
14
|
+
* This is a subclass of `DatabaseError` with `code` set to `"TIMEOUT"`.
|
|
15
|
+
* Catch this type to distinguish timeouts from other database errors
|
|
16
|
+
* and decide whether to retry or fail gracefully.
|
|
17
|
+
*/
|
|
18
|
+
export class TimeoutError extends DatabaseError {
|
|
19
|
+
constructor(message = 'Query timed out', cause) {
|
|
20
|
+
super(message, 'TIMEOUT', undefined, cause);
|
|
21
|
+
this.name = 'TimeoutError';
|
|
22
|
+
Object.setPrototypeOf(this, TimeoutError.prototype);
|
|
23
|
+
}
|
|
24
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { Connection, connect, type Config } from './connection.js';
|
|
2
2
|
export { Statement } from './statement.js';
|
|
3
3
|
export { Session, type SessionConfig } from './session.js';
|
|
4
|
-
export { DatabaseError } from './error.js';
|
|
5
|
-
export { type Column, ENCRYPTION_KEY_HEADER } from './protocol.js';
|
|
4
|
+
export { DatabaseError, TimeoutError } from './error.js';
|
|
5
|
+
export { type Column, type QueryOptions, ENCRYPTION_KEY_HEADER } from './protocol.js';
|
package/dist/index.js
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
export { Connection, connect } from './connection.js';
|
|
3
3
|
export { Statement } from './statement.js';
|
|
4
4
|
export { Session } from './session.js';
|
|
5
|
-
export { DatabaseError } from './error.js';
|
|
5
|
+
export { DatabaseError, TimeoutError } from './error.js';
|
|
6
6
|
export { ENCRYPTION_KEY_HEADER } from './protocol.js';
|
package/dist/protocol.d.ts
CHANGED
|
@@ -108,8 +108,13 @@ export interface CursorEntry {
|
|
|
108
108
|
}
|
|
109
109
|
/** HTTP header key for the encryption key */
|
|
110
110
|
export declare const ENCRYPTION_KEY_HEADER = "x-turso-encryption-key";
|
|
111
|
-
|
|
111
|
+
/** Per-query timeout options. Overrides defaultQueryTimeout for this call. */
|
|
112
|
+
export interface QueryOptions {
|
|
113
|
+
/** Per-query timeout in milliseconds. Overrides defaultQueryTimeout for this call. */
|
|
114
|
+
queryTimeout?: number;
|
|
115
|
+
}
|
|
116
|
+
export declare function executeCursor(url: string, authToken: string | undefined, request: CursorRequest, remoteEncryptionKey?: string, signal?: AbortSignal): Promise<{
|
|
112
117
|
response: CursorResponse;
|
|
113
118
|
entries: AsyncGenerator<CursorEntry>;
|
|
114
119
|
}>;
|
|
115
|
-
export declare function executePipeline(url: string, authToken: string | undefined, request: PipelineRequest, remoteEncryptionKey?: string): Promise<PipelineResponse>;
|
|
120
|
+
export declare function executePipeline(url: string, authToken: string | undefined, request: PipelineRequest, remoteEncryptionKey?: string, signal?: AbortSignal): Promise<PipelineResponse>;
|
package/dist/protocol.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DatabaseError } from './error.js';
|
|
1
|
+
import { DatabaseError, TimeoutError } from './error.js';
|
|
2
2
|
export function encodeValue(value) {
|
|
3
3
|
if (value === null || value === undefined) {
|
|
4
4
|
return { type: 'null' };
|
|
@@ -53,7 +53,13 @@ export function decodeValue(value, safeIntegers = false) {
|
|
|
53
53
|
}
|
|
54
54
|
/** HTTP header key for the encryption key */
|
|
55
55
|
export const ENCRYPTION_KEY_HEADER = 'x-turso-encryption-key';
|
|
56
|
-
|
|
56
|
+
function wrapAbortError(error) {
|
|
57
|
+
if (error instanceof Error && (error.name === 'AbortError' || error.name === 'TimeoutError')) {
|
|
58
|
+
throw new TimeoutError('Query timed out');
|
|
59
|
+
}
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
export async function executeCursor(url, authToken, request, remoteEncryptionKey, signal) {
|
|
57
63
|
const headers = {
|
|
58
64
|
'Content-Type': 'application/json',
|
|
59
65
|
};
|
|
@@ -63,11 +69,18 @@ export async function executeCursor(url, authToken, request, remoteEncryptionKey
|
|
|
63
69
|
if (remoteEncryptionKey) {
|
|
64
70
|
headers[ENCRYPTION_KEY_HEADER] = remoteEncryptionKey;
|
|
65
71
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
72
|
+
let response;
|
|
73
|
+
try {
|
|
74
|
+
response = await fetch(`${url}/v3/cursor`, {
|
|
75
|
+
method: 'POST',
|
|
76
|
+
headers,
|
|
77
|
+
body: JSON.stringify(request),
|
|
78
|
+
signal,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
wrapAbortError(error);
|
|
83
|
+
}
|
|
71
84
|
if (!response.ok) {
|
|
72
85
|
let errorMessage = `HTTP error! status: ${response.status}`;
|
|
73
86
|
try {
|
|
@@ -90,22 +103,29 @@ export async function executeCursor(url, authToken, request, remoteEncryptionKey
|
|
|
90
103
|
let buffer = '';
|
|
91
104
|
let cursorResponse;
|
|
92
105
|
// First, read until we get the cursor response (first line)
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
buffer += decoder.decode(value, { stream: true });
|
|
98
|
-
const newlineIndex = buffer.indexOf('\n');
|
|
99
|
-
if (newlineIndex !== -1) {
|
|
100
|
-
const line = buffer.slice(0, newlineIndex).trim();
|
|
101
|
-
buffer = buffer.slice(newlineIndex + 1);
|
|
102
|
-
if (line) {
|
|
103
|
-
cursorResponse = JSON.parse(line);
|
|
106
|
+
try {
|
|
107
|
+
while (!cursorResponse) {
|
|
108
|
+
const { done, value } = await reader.read();
|
|
109
|
+
if (done)
|
|
104
110
|
break;
|
|
111
|
+
buffer += decoder.decode(value, { stream: true });
|
|
112
|
+
const newlineIndex = buffer.indexOf('\n');
|
|
113
|
+
if (newlineIndex !== -1) {
|
|
114
|
+
const line = buffer.slice(0, newlineIndex).trim();
|
|
115
|
+
buffer = buffer.slice(newlineIndex + 1);
|
|
116
|
+
if (line) {
|
|
117
|
+
cursorResponse = JSON.parse(line);
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
105
120
|
}
|
|
106
121
|
}
|
|
107
122
|
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
reader.releaseLock();
|
|
125
|
+
wrapAbortError(error);
|
|
126
|
+
}
|
|
108
127
|
if (!cursorResponse) {
|
|
128
|
+
reader.releaseLock();
|
|
109
129
|
throw new DatabaseError('No cursor response received');
|
|
110
130
|
}
|
|
111
131
|
async function* parseEntries() {
|
|
@@ -121,10 +141,16 @@ export async function executeCursor(url, authToken, request, remoteEncryptionKey
|
|
|
121
141
|
}
|
|
122
142
|
// Continue reading from the stream
|
|
123
143
|
while (true) {
|
|
124
|
-
|
|
125
|
-
|
|
144
|
+
let readResult;
|
|
145
|
+
try {
|
|
146
|
+
readResult = await reader.read();
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
wrapAbortError(error);
|
|
150
|
+
}
|
|
151
|
+
if (readResult.done)
|
|
126
152
|
break;
|
|
127
|
-
buffer += decoder.decode(value, { stream: true });
|
|
153
|
+
buffer += decoder.decode(readResult.value, { stream: true });
|
|
128
154
|
while ((newlineIndex = buffer.indexOf('\n')) !== -1) {
|
|
129
155
|
const line = buffer.slice(0, newlineIndex).trim();
|
|
130
156
|
buffer = buffer.slice(newlineIndex + 1);
|
|
@@ -144,7 +170,7 @@ export async function executeCursor(url, authToken, request, remoteEncryptionKey
|
|
|
144
170
|
}
|
|
145
171
|
return { response: cursorResponse, entries: parseEntries() };
|
|
146
172
|
}
|
|
147
|
-
export async function executePipeline(url, authToken, request, remoteEncryptionKey) {
|
|
173
|
+
export async function executePipeline(url, authToken, request, remoteEncryptionKey, signal) {
|
|
148
174
|
const headers = {
|
|
149
175
|
'Content-Type': 'application/json',
|
|
150
176
|
};
|
|
@@ -154,11 +180,18 @@ export async function executePipeline(url, authToken, request, remoteEncryptionK
|
|
|
154
180
|
if (remoteEncryptionKey) {
|
|
155
181
|
headers[ENCRYPTION_KEY_HEADER] = remoteEncryptionKey;
|
|
156
182
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
183
|
+
let response;
|
|
184
|
+
try {
|
|
185
|
+
response = await fetch(`${url}/v3/pipeline`, {
|
|
186
|
+
method: 'POST',
|
|
187
|
+
headers,
|
|
188
|
+
body: JSON.stringify(request),
|
|
189
|
+
signal,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
wrapAbortError(error);
|
|
194
|
+
}
|
|
162
195
|
if (!response.ok) {
|
|
163
196
|
throw new DatabaseError(`HTTP error! status: ${response.status}`);
|
|
164
197
|
}
|
package/dist/session.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type CursorResponse, type CursorEntry, type DescribeResult } from './protocol.js';
|
|
1
|
+
import { type CursorResponse, type CursorEntry, type DescribeResult, type QueryOptions } from './protocol.js';
|
|
2
2
|
/**
|
|
3
3
|
* Configuration options for a session.
|
|
4
4
|
*/
|
|
@@ -12,6 +12,8 @@ export interface SessionConfig {
|
|
|
12
12
|
* to enable access to encrypted Turso Cloud databases.
|
|
13
13
|
*/
|
|
14
14
|
remoteEncryptionKey?: string;
|
|
15
|
+
/** Default maximum query execution time in milliseconds before interruption. */
|
|
16
|
+
defaultQueryTimeout?: number;
|
|
15
17
|
}
|
|
16
18
|
/**
|
|
17
19
|
* A database session that manages the connection state and baton.
|
|
@@ -24,13 +26,14 @@ export declare class Session {
|
|
|
24
26
|
private baton;
|
|
25
27
|
private baseUrl;
|
|
26
28
|
constructor(config: SessionConfig);
|
|
29
|
+
private createAbortSignal;
|
|
27
30
|
/**
|
|
28
31
|
* Describe a SQL statement to get its column metadata.
|
|
29
32
|
*
|
|
30
33
|
* @param sql - The SQL statement to describe
|
|
31
34
|
* @returns Promise resolving to the statement description
|
|
32
35
|
*/
|
|
33
|
-
describe(sql: string): Promise<DescribeResult>;
|
|
36
|
+
describe(sql: string, queryOptions?: QueryOptions): Promise<DescribeResult>;
|
|
34
37
|
/**
|
|
35
38
|
* Execute a SQL statement and return all results.
|
|
36
39
|
*
|
|
@@ -39,7 +42,7 @@ export declare class Session {
|
|
|
39
42
|
* @param safeIntegers - Whether to return integers as BigInt
|
|
40
43
|
* @returns Promise resolving to the complete result set
|
|
41
44
|
*/
|
|
42
|
-
execute(sql: string, args?: any[] | Record<string, any>, safeIntegers?: boolean): Promise<any>;
|
|
45
|
+
execute(sql: string, args?: any[] | Record<string, any>, safeIntegers?: boolean, queryOptions?: QueryOptions): Promise<any>;
|
|
43
46
|
/**
|
|
44
47
|
* Execute a SQL statement and return the raw response and entries.
|
|
45
48
|
*
|
|
@@ -47,7 +50,7 @@ export declare class Session {
|
|
|
47
50
|
* @param args - Optional array of parameter values or object with named parameters
|
|
48
51
|
* @returns Promise resolving to the raw response and cursor entries
|
|
49
52
|
*/
|
|
50
|
-
executeRaw(sql: string, args?: any[] | Record<string, any
|
|
53
|
+
executeRaw(sql: string, args?: any[] | Record<string, any>, queryOptions?: QueryOptions): Promise<{
|
|
51
54
|
response: CursorResponse;
|
|
52
55
|
entries: AsyncGenerator<CursorEntry>;
|
|
53
56
|
}>;
|
|
@@ -72,14 +75,14 @@ export declare class Session {
|
|
|
72
75
|
* @param statements - Array of SQL statements to execute
|
|
73
76
|
* @returns Promise resolving to batch execution results
|
|
74
77
|
*/
|
|
75
|
-
batch(statements: string[]): Promise<any>;
|
|
78
|
+
batch(statements: string[], queryOptions?: QueryOptions): Promise<any>;
|
|
76
79
|
/**
|
|
77
80
|
* Execute a sequence of SQL statements separated by semicolons.
|
|
78
81
|
*
|
|
79
82
|
* @param sql - SQL string containing multiple statements separated by semicolons
|
|
80
83
|
* @returns Promise resolving when all statements are executed
|
|
81
84
|
*/
|
|
82
|
-
sequence(sql: string): Promise<void>;
|
|
85
|
+
sequence(sql: string, queryOptions?: QueryOptions): Promise<void>;
|
|
83
86
|
/**
|
|
84
87
|
* Close the session.
|
|
85
88
|
*
|
package/dist/session.js
CHANGED
|
@@ -18,13 +18,20 @@ export class Session {
|
|
|
18
18
|
this.config = config;
|
|
19
19
|
this.baseUrl = normalizeUrl(config.url);
|
|
20
20
|
}
|
|
21
|
+
createAbortSignal(queryOptions) {
|
|
22
|
+
const timeout = queryOptions?.queryTimeout ?? this.config.defaultQueryTimeout;
|
|
23
|
+
if (timeout != null && timeout > 0) {
|
|
24
|
+
return AbortSignal.timeout(timeout);
|
|
25
|
+
}
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
21
28
|
/**
|
|
22
29
|
* Describe a SQL statement to get its column metadata.
|
|
23
30
|
*
|
|
24
31
|
* @param sql - The SQL statement to describe
|
|
25
32
|
* @returns Promise resolving to the statement description
|
|
26
33
|
*/
|
|
27
|
-
async describe(sql) {
|
|
34
|
+
async describe(sql, queryOptions) {
|
|
28
35
|
const request = {
|
|
29
36
|
baton: this.baton,
|
|
30
37
|
requests: [{
|
|
@@ -32,7 +39,7 @@ export class Session {
|
|
|
32
39
|
sql: sql
|
|
33
40
|
}]
|
|
34
41
|
};
|
|
35
|
-
const response = await executePipeline(this.baseUrl, this.config.authToken, request, this.config.remoteEncryptionKey);
|
|
42
|
+
const response = await executePipeline(this.baseUrl, this.config.authToken, request, this.config.remoteEncryptionKey, this.createAbortSignal(queryOptions));
|
|
36
43
|
this.baton = response.baton;
|
|
37
44
|
if (response.base_url) {
|
|
38
45
|
this.baseUrl = response.base_url;
|
|
@@ -57,8 +64,8 @@ export class Session {
|
|
|
57
64
|
* @param safeIntegers - Whether to return integers as BigInt
|
|
58
65
|
* @returns Promise resolving to the complete result set
|
|
59
66
|
*/
|
|
60
|
-
async execute(sql, args = [], safeIntegers = false) {
|
|
61
|
-
const { response, entries } = await this.executeRaw(sql, args);
|
|
67
|
+
async execute(sql, args = [], safeIntegers = false, queryOptions) {
|
|
68
|
+
const { response, entries } = await this.executeRaw(sql, args, queryOptions);
|
|
62
69
|
const result = await this.processCursorEntries(entries, safeIntegers);
|
|
63
70
|
return result;
|
|
64
71
|
}
|
|
@@ -69,7 +76,7 @@ export class Session {
|
|
|
69
76
|
* @param args - Optional array of parameter values or object with named parameters
|
|
70
77
|
* @returns Promise resolving to the raw response and cursor entries
|
|
71
78
|
*/
|
|
72
|
-
async executeRaw(sql, args = []) {
|
|
79
|
+
async executeRaw(sql, args = [], queryOptions) {
|
|
73
80
|
let positionalArgs = [];
|
|
74
81
|
let namedArgs = [];
|
|
75
82
|
if (Array.isArray(args)) {
|
|
@@ -118,7 +125,7 @@ export class Session {
|
|
|
118
125
|
}]
|
|
119
126
|
}
|
|
120
127
|
};
|
|
121
|
-
const { response, entries } = await executeCursor(this.baseUrl, this.config.authToken, request, this.config.remoteEncryptionKey);
|
|
128
|
+
const { response, entries } = await executeCursor(this.baseUrl, this.config.authToken, request, this.config.remoteEncryptionKey, this.createAbortSignal(queryOptions));
|
|
122
129
|
this.baton = response.baton;
|
|
123
130
|
if (response.base_url) {
|
|
124
131
|
this.baseUrl = response.base_url;
|
|
@@ -202,7 +209,7 @@ export class Session {
|
|
|
202
209
|
* @param statements - Array of SQL statements to execute
|
|
203
210
|
* @returns Promise resolving to batch execution results
|
|
204
211
|
*/
|
|
205
|
-
async batch(statements) {
|
|
212
|
+
async batch(statements, queryOptions) {
|
|
206
213
|
const request = {
|
|
207
214
|
baton: this.baton,
|
|
208
215
|
batch: {
|
|
@@ -216,7 +223,7 @@ export class Session {
|
|
|
216
223
|
}))
|
|
217
224
|
}
|
|
218
225
|
};
|
|
219
|
-
const { response, entries } = await executeCursor(this.baseUrl, this.config.authToken, request, this.config.remoteEncryptionKey);
|
|
226
|
+
const { response, entries } = await executeCursor(this.baseUrl, this.config.authToken, request, this.config.remoteEncryptionKey, this.createAbortSignal(queryOptions));
|
|
220
227
|
this.baton = response.baton;
|
|
221
228
|
if (response.base_url) {
|
|
222
229
|
this.baseUrl = response.base_url;
|
|
@@ -249,7 +256,7 @@ export class Session {
|
|
|
249
256
|
* @param sql - SQL string containing multiple statements separated by semicolons
|
|
250
257
|
* @returns Promise resolving when all statements are executed
|
|
251
258
|
*/
|
|
252
|
-
async sequence(sql) {
|
|
259
|
+
async sequence(sql, queryOptions) {
|
|
253
260
|
const request = {
|
|
254
261
|
baton: this.baton,
|
|
255
262
|
requests: [{
|
|
@@ -257,7 +264,7 @@ export class Session {
|
|
|
257
264
|
sql: sql
|
|
258
265
|
}]
|
|
259
266
|
};
|
|
260
|
-
const response = await executePipeline(this.baseUrl, this.config.authToken, request, this.config.remoteEncryptionKey);
|
|
267
|
+
const response = await executePipeline(this.baseUrl, this.config.authToken, request, this.config.remoteEncryptionKey, this.createAbortSignal(queryOptions));
|
|
261
268
|
this.baton = response.baton;
|
|
262
269
|
if (response.base_url) {
|
|
263
270
|
this.baseUrl = response.base_url;
|
|
@@ -288,9 +295,9 @@ export class Session {
|
|
|
288
295
|
};
|
|
289
296
|
await executePipeline(this.baseUrl, this.config.authToken, request, this.config.remoteEncryptionKey);
|
|
290
297
|
}
|
|
291
|
-
catch
|
|
292
|
-
// Ignore errors during close
|
|
293
|
-
|
|
298
|
+
catch {
|
|
299
|
+
// Ignore errors during close — the connection might already be closed
|
|
300
|
+
// or the baton may be stale after a timeout.
|
|
294
301
|
}
|
|
295
302
|
}
|
|
296
303
|
// Reset local state
|
package/dist/statement.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Column } from './protocol.js';
|
|
1
|
+
import { type Column, type QueryOptions } from './protocol.js';
|
|
2
2
|
import { type SessionConfig } from './session.js';
|
|
3
3
|
/**
|
|
4
4
|
* A prepared SQL statement that can be executed in multiple ways.
|
|
@@ -94,7 +94,7 @@ export declare class Statement {
|
|
|
94
94
|
* console.log(`Inserted user with ID ${result.lastInsertRowid}`);
|
|
95
95
|
* ```
|
|
96
96
|
*/
|
|
97
|
-
run(args?: any): Promise<any>;
|
|
97
|
+
run(args?: any, queryOptions?: QueryOptions): Promise<any>;
|
|
98
98
|
/**
|
|
99
99
|
* Execute the statement and return the first row.
|
|
100
100
|
*
|
|
@@ -110,7 +110,7 @@ export declare class Statement {
|
|
|
110
110
|
* }
|
|
111
111
|
* ```
|
|
112
112
|
*/
|
|
113
|
-
get(args?: any): Promise<any>;
|
|
113
|
+
get(args?: any, queryOptions?: QueryOptions): Promise<any>;
|
|
114
114
|
/**
|
|
115
115
|
* Execute the statement and return all rows.
|
|
116
116
|
*
|
|
@@ -124,7 +124,7 @@ export declare class Statement {
|
|
|
124
124
|
* console.log(`Found ${activeUsers.length} active users`);
|
|
125
125
|
* ```
|
|
126
126
|
*/
|
|
127
|
-
all(args?: any): Promise<any[]>;
|
|
127
|
+
all(args?: any, queryOptions?: QueryOptions): Promise<any[]>;
|
|
128
128
|
/**
|
|
129
129
|
* Execute the statement and return an async iterator for streaming results.
|
|
130
130
|
*
|
|
@@ -143,7 +143,7 @@ export declare class Statement {
|
|
|
143
143
|
* }
|
|
144
144
|
* ```
|
|
145
145
|
*/
|
|
146
|
-
iterate(args?: any): AsyncGenerator<any>;
|
|
146
|
+
iterate(args?: any, queryOptions?: QueryOptions): AsyncGenerator<any>;
|
|
147
147
|
/**
|
|
148
148
|
* Normalize arguments to handle both single values and arrays.
|
|
149
149
|
* Matches the behavior of the native bindings.
|
package/dist/statement.js
CHANGED
|
@@ -112,9 +112,9 @@ export class Statement {
|
|
|
112
112
|
* console.log(`Inserted user with ID ${result.lastInsertRowid}`);
|
|
113
113
|
* ```
|
|
114
114
|
*/
|
|
115
|
-
async run(args) {
|
|
115
|
+
async run(args, queryOptions) {
|
|
116
116
|
const normalizedArgs = this.normalizeArgs(args);
|
|
117
|
-
const result = await this.session.execute(this.sql, normalizedArgs, this.safeIntegerMode);
|
|
117
|
+
const result = await this.session.execute(this.sql, normalizedArgs, this.safeIntegerMode, queryOptions);
|
|
118
118
|
return { changes: result.rowsAffected, lastInsertRowid: result.lastInsertRowid };
|
|
119
119
|
}
|
|
120
120
|
/**
|
|
@@ -132,9 +132,9 @@ export class Statement {
|
|
|
132
132
|
* }
|
|
133
133
|
* ```
|
|
134
134
|
*/
|
|
135
|
-
async get(args) {
|
|
135
|
+
async get(args, queryOptions) {
|
|
136
136
|
const normalizedArgs = this.normalizeArgs(args);
|
|
137
|
-
const result = await this.session.execute(this.sql, normalizedArgs, this.safeIntegerMode);
|
|
137
|
+
const result = await this.session.execute(this.sql, normalizedArgs, this.safeIntegerMode, queryOptions);
|
|
138
138
|
const row = result.rows[0];
|
|
139
139
|
if (!row) {
|
|
140
140
|
return undefined;
|
|
@@ -168,9 +168,9 @@ export class Statement {
|
|
|
168
168
|
* console.log(`Found ${activeUsers.length} active users`);
|
|
169
169
|
* ```
|
|
170
170
|
*/
|
|
171
|
-
async all(args) {
|
|
171
|
+
async all(args, queryOptions) {
|
|
172
172
|
const normalizedArgs = this.normalizeArgs(args);
|
|
173
|
-
const result = await this.session.execute(this.sql, normalizedArgs, this.safeIntegerMode);
|
|
173
|
+
const result = await this.session.execute(this.sql, normalizedArgs, this.safeIntegerMode, queryOptions);
|
|
174
174
|
if (this.presentationMode === 'pluck') {
|
|
175
175
|
// In pluck mode, return only the first column value from each row
|
|
176
176
|
return result.rows.map((row) => row[0]);
|
|
@@ -205,9 +205,9 @@ export class Statement {
|
|
|
205
205
|
* }
|
|
206
206
|
* ```
|
|
207
207
|
*/
|
|
208
|
-
async *iterate(args) {
|
|
208
|
+
async *iterate(args, queryOptions) {
|
|
209
209
|
const normalizedArgs = this.normalizeArgs(args);
|
|
210
|
-
const { response, entries } = await this.session.executeRaw(this.sql, normalizedArgs);
|
|
210
|
+
const { response, entries } = await this.session.executeRaw(this.sql, normalizedArgs, queryOptions);
|
|
211
211
|
let columns = [];
|
|
212
212
|
for await (const entry of entries) {
|
|
213
213
|
switch (entry.type) {
|