@peerbit/indexer-sqlite3 3.0.0-e6ea5c0 → 3.0.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/assets/sqlite3/sqlite3.worker.min.js +168 -52
- package/dist/index.min.js +277 -53
- package/dist/index.min.js.map +3 -3
- package/dist/src/engine.d.ts +9 -3
- package/dist/src/engine.d.ts.map +1 -1
- package/dist/src/engine.js +75 -9
- package/dist/src/engine.js.map +1 -1
- package/dist/src/index.d.ts +7 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +5 -4
- package/dist/src/index.js.map +1 -1
- package/dist/src/schema.d.ts +5 -1
- package/dist/src/schema.d.ts.map +1 -1
- package/dist/src/schema.js +42 -12
- package/dist/src/schema.js.map +1 -1
- package/dist/src/sqlite3-messages.worker.d.ts +47 -8
- package/dist/src/sqlite3-messages.worker.d.ts.map +1 -1
- package/dist/src/sqlite3-messages.worker.js +42 -3
- package/dist/src/sqlite3-messages.worker.js.map +1 -1
- package/dist/src/sqlite3.browser.d.ts +22 -1
- package/dist/src/sqlite3.browser.d.ts.map +1 -1
- package/dist/src/sqlite3.browser.js +138 -31
- package/dist/src/sqlite3.browser.js.map +1 -1
- package/dist/src/sqlite3.d.ts +4 -1
- package/dist/src/sqlite3.d.ts.map +1 -1
- package/dist/src/sqlite3.js +14 -5
- package/dist/src/sqlite3.js.map +1 -1
- package/dist/src/sqlite3.wasm.d.ts +4 -1
- package/dist/src/sqlite3.wasm.d.ts.map +1 -1
- package/dist/src/sqlite3.wasm.js +15 -3
- package/dist/src/sqlite3.wasm.js.map +1 -1
- package/dist/src/sqlite3.worker.js +146 -53
- package/dist/src/sqlite3.worker.js.map +1 -1
- package/dist/src/utils.d.ts +1 -0
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/src/utils.js +11 -0
- package/dist/src/utils.js.map +1 -1
- package/package.json +10 -9
- package/src/engine.ts +99 -11
- package/src/index.ts +39 -4
- package/src/schema.ts +67 -11
- package/src/sqlite3-messages.worker.ts +104 -10
- package/src/sqlite3.browser.ts +246 -88
- package/src/sqlite3.ts +19 -5
- package/src/sqlite3.wasm.ts +25 -3
- package/src/sqlite3.worker.ts +170 -49
- package/src/utils.ts +14 -0
package/src/sqlite3.browser.ts
CHANGED
|
@@ -9,109 +9,264 @@ import {
|
|
|
9
9
|
type StatementGetResult,
|
|
10
10
|
} from "./types.js";
|
|
11
11
|
|
|
12
|
+
type RequestType =
|
|
13
|
+
| messages.DatabaseMessages["type"]
|
|
14
|
+
| messages.StatementMessages["type"];
|
|
15
|
+
|
|
16
|
+
export type SQLiteBrowserOptions = {
|
|
17
|
+
protocol?: messages.SqliteWorkerProtocol;
|
|
18
|
+
pragmas?: messages.SQLitePragmaOptions;
|
|
19
|
+
profile?: boolean;
|
|
20
|
+
onProfile?: (sample: SQLiteProfileSample) => void;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type SQLiteProfileSample = {
|
|
24
|
+
requestType: RequestType;
|
|
25
|
+
protocol: messages.SqliteWorkerProtocol;
|
|
26
|
+
databaseId: string;
|
|
27
|
+
databaseDirectory?: string;
|
|
28
|
+
sql?: string;
|
|
29
|
+
clientEncodeMs: number;
|
|
30
|
+
clientRoundTripMs: number;
|
|
31
|
+
valueCount: number;
|
|
32
|
+
blobValueCount: number;
|
|
33
|
+
blobBytes: number;
|
|
34
|
+
worker?: messages.WorkerTiming;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
type SendMetrics = messages.ClientEncodeMetrics & {
|
|
38
|
+
requestType: RequestType;
|
|
39
|
+
sql?: string;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
type ResponseMessage = Extract<messages.ResponseMessages, { type: "response" }>;
|
|
43
|
+
type ErrorMessage = Extract<messages.ResponseMessages, { type: "error" }>;
|
|
44
|
+
|
|
45
|
+
const DEFAULT_PROTOCOL: messages.SqliteWorkerProtocol = "clone";
|
|
46
|
+
const EMPTY_ENCODE_METRICS: messages.ClientEncodeMetrics = {
|
|
47
|
+
encodeMs: 0,
|
|
48
|
+
valueCount: 0,
|
|
49
|
+
blobValueCount: 0,
|
|
50
|
+
blobBytes: 0,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const getProtocol = (
|
|
54
|
+
options?: SQLiteBrowserOptions,
|
|
55
|
+
): messages.SqliteWorkerProtocol => options?.protocol ?? DEFAULT_PROTOCOL;
|
|
56
|
+
|
|
12
57
|
class ProxyStatement implements IStatement {
|
|
13
58
|
id: string;
|
|
14
|
-
|
|
15
|
-
[hash in string]: {
|
|
16
|
-
resolve: (...args: any) => void;
|
|
17
|
-
reject: (...args: any) => void;
|
|
18
|
-
};
|
|
19
|
-
} = {};
|
|
59
|
+
private needsReset = false;
|
|
20
60
|
|
|
21
61
|
constructor(
|
|
22
62
|
readonly send: <T>(
|
|
23
63
|
message: messages.DatabaseMessages | messages.StatementMessages,
|
|
64
|
+
metrics?: SendMetrics,
|
|
24
65
|
) => Promise<T>,
|
|
25
66
|
readonly databaseId: string,
|
|
26
67
|
readonly statementId: string,
|
|
68
|
+
readonly sql: string,
|
|
69
|
+
readonly options?: SQLiteBrowserOptions,
|
|
27
70
|
) {
|
|
28
71
|
this.id = statementId;
|
|
29
72
|
}
|
|
30
73
|
|
|
31
74
|
async bind(values: any[]) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
75
|
+
const encoded = messages.encodeValues(values, getProtocol(this.options));
|
|
76
|
+
await this.send(
|
|
77
|
+
{
|
|
78
|
+
type: "bind",
|
|
79
|
+
values: encoded.values ?? [],
|
|
80
|
+
id: uuid(),
|
|
81
|
+
databaseId: this.databaseId,
|
|
82
|
+
statementId: this.statementId,
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
requestType: "bind",
|
|
86
|
+
sql: this.sql,
|
|
87
|
+
...encoded.metrics,
|
|
88
|
+
},
|
|
89
|
+
);
|
|
90
|
+
this.needsReset = true;
|
|
39
91
|
return this;
|
|
40
92
|
}
|
|
41
93
|
|
|
42
94
|
async finalize() {
|
|
43
|
-
await this.send(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
95
|
+
await this.send(
|
|
96
|
+
{
|
|
97
|
+
type: "finalize",
|
|
98
|
+
id: uuid(),
|
|
99
|
+
databaseId: this.databaseId,
|
|
100
|
+
statementId: this.statementId,
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
requestType: "finalize",
|
|
104
|
+
sql: this.sql,
|
|
105
|
+
...EMPTY_ENCODE_METRICS,
|
|
106
|
+
},
|
|
107
|
+
);
|
|
108
|
+
this.needsReset = false;
|
|
49
109
|
}
|
|
50
110
|
|
|
51
|
-
get(values?: BindableValue[]) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
111
|
+
async get(values?: BindableValue[]) {
|
|
112
|
+
const encoded = messages.encodeValues(values, getProtocol(this.options));
|
|
113
|
+
const result = await this.send<StatementGetResult>(
|
|
114
|
+
{
|
|
115
|
+
type: "get",
|
|
116
|
+
values: encoded.values,
|
|
117
|
+
id: uuid(),
|
|
118
|
+
databaseId: this.databaseId,
|
|
119
|
+
statementId: this.statementId,
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
requestType: "get",
|
|
123
|
+
sql: this.sql,
|
|
124
|
+
...encoded.metrics,
|
|
125
|
+
},
|
|
126
|
+
);
|
|
127
|
+
this.needsReset = false;
|
|
128
|
+
return result;
|
|
59
129
|
}
|
|
60
130
|
|
|
61
131
|
async run(values: BindableValue[]) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
132
|
+
const encoded = messages.encodeValues(values, getProtocol(this.options));
|
|
133
|
+
await this.send(
|
|
134
|
+
{
|
|
135
|
+
type: "run-statement",
|
|
136
|
+
values: encoded.values ?? [],
|
|
137
|
+
id: uuid(),
|
|
138
|
+
databaseId: this.databaseId,
|
|
139
|
+
statementId: this.statementId,
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
requestType: "run-statement",
|
|
143
|
+
sql: this.sql,
|
|
144
|
+
...encoded.metrics,
|
|
145
|
+
},
|
|
146
|
+
);
|
|
147
|
+
this.needsReset = false;
|
|
69
148
|
}
|
|
70
149
|
|
|
71
150
|
async reset() {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
151
|
+
if (!this.needsReset) {
|
|
152
|
+
return this;
|
|
153
|
+
}
|
|
154
|
+
await this.send(
|
|
155
|
+
{
|
|
156
|
+
type: "reset",
|
|
157
|
+
id: uuid(),
|
|
158
|
+
databaseId: this.databaseId,
|
|
159
|
+
statementId: this.statementId,
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
requestType: "reset",
|
|
163
|
+
sql: this.sql,
|
|
164
|
+
...EMPTY_ENCODE_METRICS,
|
|
165
|
+
},
|
|
166
|
+
);
|
|
167
|
+
this.needsReset = false;
|
|
78
168
|
return this;
|
|
79
169
|
}
|
|
80
170
|
|
|
81
171
|
async all(values: BindableValue[]) {
|
|
82
|
-
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
172
|
+
const encoded = messages.encodeValues(values, getProtocol(this.options));
|
|
173
|
+
const result = await this.send(
|
|
174
|
+
{
|
|
175
|
+
type: "all",
|
|
176
|
+
values: encoded.values ?? [],
|
|
177
|
+
id: uuid(),
|
|
178
|
+
databaseId: this.databaseId,
|
|
179
|
+
statementId: this.statementId,
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
requestType: "all",
|
|
183
|
+
sql: this.sql,
|
|
184
|
+
...encoded.metrics,
|
|
185
|
+
},
|
|
186
|
+
);
|
|
187
|
+
this.needsReset = false;
|
|
188
|
+
return result;
|
|
91
189
|
}
|
|
92
190
|
}
|
|
93
191
|
|
|
94
192
|
class ProxyDatabase implements IDatabase {
|
|
95
193
|
statements: Map<string, ProxyStatement> = new Map();
|
|
96
|
-
|
|
97
|
-
resolvers: {
|
|
98
|
-
[hash in string]: {
|
|
99
|
-
resolve: (...args: any) => void;
|
|
100
|
-
reject: (...args: any) => void;
|
|
101
|
-
};
|
|
102
|
-
} = {};
|
|
103
194
|
databaseId!: string;
|
|
195
|
+
private directory?: string;
|
|
196
|
+
|
|
104
197
|
constructor(
|
|
105
|
-
readonly
|
|
198
|
+
readonly postMessage: (
|
|
106
199
|
message: messages.DatabaseMessages | messages.StatementMessages,
|
|
107
|
-
) => Promise<
|
|
200
|
+
) => Promise<ResponseMessage>,
|
|
201
|
+
readonly options?: SQLiteBrowserOptions,
|
|
108
202
|
) {}
|
|
109
203
|
|
|
204
|
+
private async send<T>(
|
|
205
|
+
message: messages.DatabaseMessages | messages.StatementMessages,
|
|
206
|
+
metrics?: SendMetrics,
|
|
207
|
+
): Promise<T> {
|
|
208
|
+
const startedAt = performance.now();
|
|
209
|
+
const protocol = getProtocol(this.options);
|
|
210
|
+
const shouldProfile = Boolean(this.options?.profile || this.options?.onProfile);
|
|
211
|
+
const requestType = metrics?.requestType ?? message.type;
|
|
212
|
+
|
|
213
|
+
try {
|
|
214
|
+
const response = await this.postMessage({
|
|
215
|
+
...message,
|
|
216
|
+
protocol,
|
|
217
|
+
profile: shouldProfile,
|
|
218
|
+
});
|
|
219
|
+
this.options?.onProfile?.({
|
|
220
|
+
requestType,
|
|
221
|
+
protocol,
|
|
222
|
+
databaseId: this.databaseId,
|
|
223
|
+
databaseDirectory: this.directory,
|
|
224
|
+
sql:
|
|
225
|
+
metrics?.sql ??
|
|
226
|
+
("sql" in message && typeof message.sql === "string"
|
|
227
|
+
? message.sql
|
|
228
|
+
: undefined),
|
|
229
|
+
clientEncodeMs: metrics?.encodeMs ?? 0,
|
|
230
|
+
clientRoundTripMs: performance.now() - startedAt,
|
|
231
|
+
valueCount: metrics?.valueCount ?? 0,
|
|
232
|
+
blobValueCount: metrics?.blobValueCount ?? 0,
|
|
233
|
+
blobBytes: metrics?.blobBytes ?? 0,
|
|
234
|
+
worker: response.timing,
|
|
235
|
+
});
|
|
236
|
+
return response.result as T;
|
|
237
|
+
} catch (error: any) {
|
|
238
|
+
const responseError = error as ErrorMessage | undefined;
|
|
239
|
+
this.options?.onProfile?.({
|
|
240
|
+
requestType,
|
|
241
|
+
protocol,
|
|
242
|
+
databaseId: this.databaseId,
|
|
243
|
+
databaseDirectory: this.directory,
|
|
244
|
+
sql:
|
|
245
|
+
metrics?.sql ??
|
|
246
|
+
("sql" in message && typeof message.sql === "string"
|
|
247
|
+
? message.sql
|
|
248
|
+
: undefined),
|
|
249
|
+
clientEncodeMs: metrics?.encodeMs ?? 0,
|
|
250
|
+
clientRoundTripMs: performance.now() - startedAt,
|
|
251
|
+
valueCount: metrics?.valueCount ?? 0,
|
|
252
|
+
blobValueCount: metrics?.blobValueCount ?? 0,
|
|
253
|
+
blobBytes: metrics?.blobBytes ?? 0,
|
|
254
|
+
worker: responseError?.timing,
|
|
255
|
+
});
|
|
256
|
+
if (responseError?.type === "error") {
|
|
257
|
+
throw new Error(responseError.message);
|
|
258
|
+
}
|
|
259
|
+
throw error;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
110
263
|
async init(directory?: string) {
|
|
111
264
|
this.databaseId = uuid();
|
|
265
|
+
this.directory = directory;
|
|
112
266
|
return this.send({
|
|
113
267
|
type: "create",
|
|
114
268
|
directory,
|
|
269
|
+
pragmas: this.options?.pragmas,
|
|
115
270
|
databaseId: this.databaseId,
|
|
116
271
|
id: uuid(),
|
|
117
272
|
});
|
|
@@ -141,9 +296,11 @@ class ProxyDatabase implements IDatabase {
|
|
|
141
296
|
databaseId: this.databaseId,
|
|
142
297
|
});
|
|
143
298
|
const statement = new ProxyStatement(
|
|
144
|
-
this.send,
|
|
299
|
+
this.send.bind(this),
|
|
145
300
|
this.databaseId,
|
|
146
301
|
statementId,
|
|
302
|
+
sql,
|
|
303
|
+
this.options,
|
|
147
304
|
);
|
|
148
305
|
this.statements.set(statementId, statement);
|
|
149
306
|
|
|
@@ -181,18 +338,10 @@ class ProxyDatabase implements IDatabase {
|
|
|
181
338
|
databaseId: this.databaseId,
|
|
182
339
|
});
|
|
183
340
|
}
|
|
184
|
-
|
|
185
|
-
/* async get(sql: string) {
|
|
186
|
-
return this.send({ type: 'get', sql, id: uuid() });
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
async run(sql: string, bind: any[]) {
|
|
190
|
-
return this.send({ type: 'run', sql, bind, id: uuid() });
|
|
191
|
-
} */
|
|
192
341
|
}
|
|
193
342
|
|
|
194
343
|
interface DatabaseCreator {
|
|
195
|
-
create(directory?: string): Promise<ProxyDatabase>;
|
|
344
|
+
create(directory?: string, options?: SQLiteBrowserOptions): Promise<ProxyDatabase>;
|
|
196
345
|
close(): Promise<void> | void;
|
|
197
346
|
}
|
|
198
347
|
|
|
@@ -202,21 +351,22 @@ const init = async (): Promise<DatabaseCreator> => {
|
|
|
202
351
|
return initialized;
|
|
203
352
|
}
|
|
204
353
|
|
|
205
|
-
|
|
354
|
+
const worker = new Worker(
|
|
206
355
|
new URL("/peerbit/sqlite3/sqlite3.worker.min.js", import.meta.url),
|
|
207
356
|
{ type: "module" },
|
|
208
357
|
);
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
358
|
+
const resolvers: Record<
|
|
359
|
+
string,
|
|
360
|
+
{
|
|
361
|
+
resolve: (message: ResponseMessage) => void;
|
|
362
|
+
reject: (message: ErrorMessage) => void;
|
|
363
|
+
}
|
|
364
|
+
> = {};
|
|
365
|
+
|
|
366
|
+
const postMessage = (
|
|
217
367
|
message: messages.DatabaseMessages | messages.StatementMessages,
|
|
218
368
|
) => {
|
|
219
|
-
const promise = new Promise<
|
|
369
|
+
const promise = new Promise<ResponseMessage>((resolve, reject) => {
|
|
220
370
|
resolvers[message.id] = { resolve, reject };
|
|
221
371
|
});
|
|
222
372
|
worker.postMessage(message);
|
|
@@ -224,7 +374,7 @@ const init = async (): Promise<DatabaseCreator> => {
|
|
|
224
374
|
return promise.finally(() => delete resolvers[message.id]);
|
|
225
375
|
};
|
|
226
376
|
|
|
227
|
-
|
|
377
|
+
const isReady = pDefer();
|
|
228
378
|
|
|
229
379
|
worker.onmessage = async (ev) => {
|
|
230
380
|
const message = ev.data as messages.ResponseMessages | messages.IsReady;
|
|
@@ -235,15 +385,21 @@ const init = async (): Promise<DatabaseCreator> => {
|
|
|
235
385
|
}
|
|
236
386
|
|
|
237
387
|
const resolver = resolvers[message.id];
|
|
388
|
+
if (!resolver) {
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
238
391
|
if (message.type === "error") {
|
|
239
|
-
resolver.reject(
|
|
240
|
-
} else
|
|
241
|
-
resolver.resolve(message
|
|
392
|
+
resolver.reject(message);
|
|
393
|
+
} else {
|
|
394
|
+
resolver.resolve(message);
|
|
242
395
|
}
|
|
243
396
|
};
|
|
244
397
|
|
|
245
|
-
const create = async (
|
|
246
|
-
|
|
398
|
+
const create = async (
|
|
399
|
+
directory?: string,
|
|
400
|
+
options?: SQLiteBrowserOptions,
|
|
401
|
+
) => {
|
|
402
|
+
const db = new ProxyDatabase(postMessage, options);
|
|
247
403
|
await isReady.promise;
|
|
248
404
|
await db.init(directory);
|
|
249
405
|
await db.open();
|
|
@@ -258,12 +414,14 @@ const init = async (): Promise<DatabaseCreator> => {
|
|
|
258
414
|
});
|
|
259
415
|
};
|
|
260
416
|
|
|
261
|
-
const create = (
|
|
417
|
+
const create = (
|
|
418
|
+
directory?: string,
|
|
419
|
+
options?: SQLiteBrowserOptions,
|
|
420
|
+
): Promise<IDatabase> => {
|
|
262
421
|
if (directory) {
|
|
263
422
|
// persist the database
|
|
264
|
-
return init().then((creator) => creator.create(directory));
|
|
265
|
-
} else {
|
|
266
|
-
return createDatabase();
|
|
423
|
+
return init().then((creator) => creator.create(directory, options));
|
|
267
424
|
}
|
|
425
|
+
return createDatabase(directory, options);
|
|
268
426
|
};
|
|
269
427
|
export { create };
|
package/src/sqlite3.ts
CHANGED
|
@@ -1,11 +1,28 @@
|
|
|
1
1
|
import DB from "better-sqlite3";
|
|
2
2
|
import fs from "fs";
|
|
3
|
+
import type { SQLitePragmaOptions } from "./sqlite3-messages.worker.js";
|
|
3
4
|
import type {
|
|
4
5
|
Database as IDatabase,
|
|
5
6
|
Statement as IStatement,
|
|
6
7
|
} from "./types.js";
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
const applyPragmas = (db: DB.Database, pragmas?: SQLitePragmaOptions) => {
|
|
10
|
+
db.pragma("journal_mode = WAL");
|
|
11
|
+
db.pragma("foreign_keys = on");
|
|
12
|
+
db.pragma(`synchronous = ${(pragmas?.synchronous ?? "FULL").toUpperCase()}`);
|
|
13
|
+
if (pragmas?.lockingMode) {
|
|
14
|
+
db.pragma(`locking_mode = ${pragmas.lockingMode.toUpperCase()}`);
|
|
15
|
+
}
|
|
16
|
+
if (pragmas?.tempStore && pragmas.tempStore !== "DEFAULT") {
|
|
17
|
+
db.pragma(`temp_store = ${pragmas.tempStore.toUpperCase()}`);
|
|
18
|
+
}
|
|
19
|
+
db.defaultSafeIntegers(true);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
let create = async (
|
|
23
|
+
directory?: string,
|
|
24
|
+
options?: { pragmas?: SQLitePragmaOptions },
|
|
25
|
+
) => {
|
|
9
26
|
let db: DB.Database | undefined = undefined;
|
|
10
27
|
let statements: Map<string, IStatement> = new Map();
|
|
11
28
|
let dbFileName: string;
|
|
@@ -50,10 +67,7 @@ let create = async (directory?: string) => {
|
|
|
50
67
|
});
|
|
51
68
|
}
|
|
52
69
|
|
|
53
|
-
|
|
54
|
-
db.pragma("journal_mode = WAL");
|
|
55
|
-
db.pragma("foreign_keys = on");
|
|
56
|
-
db.defaultSafeIntegers(true);
|
|
70
|
+
applyPragmas(db, options?.pragmas);
|
|
57
71
|
};
|
|
58
72
|
|
|
59
73
|
return {
|
package/src/sqlite3.wasm.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
type Statement as IStatement,
|
|
13
13
|
type StatementGetResult,
|
|
14
14
|
} from "./types.js";
|
|
15
|
+
import type { SQLitePragmaOptions } from "./sqlite3-messages.worker.js";
|
|
15
16
|
|
|
16
17
|
export const encodeName = (name: string): string => {
|
|
17
18
|
// since "/" and perhaps other characters might not be allowed we do encode
|
|
@@ -183,7 +184,29 @@ const getSqlite3 = async (): Promise<Sqlite3Module> => {
|
|
|
183
184
|
return sqlite3Promise;
|
|
184
185
|
};
|
|
185
186
|
|
|
186
|
-
const
|
|
187
|
+
const applyPragmas = (
|
|
188
|
+
db: SQLDatabase | OpfsSAHPoolDatabase,
|
|
189
|
+
pragmas?: SQLitePragmaOptions,
|
|
190
|
+
) => {
|
|
191
|
+
db.exec("PRAGMA journal_mode = WAL");
|
|
192
|
+
db.exec("PRAGMA foreign_keys = on");
|
|
193
|
+
// Browser SQLite state is a rebuildable materialized view over the log, so
|
|
194
|
+
// NORMAL is a better default tradeoff than FULL for OPFS-backed write latency.
|
|
195
|
+
db.exec(
|
|
196
|
+
`PRAGMA synchronous = ${(pragmas?.synchronous ?? "NORMAL").toUpperCase()}`,
|
|
197
|
+
);
|
|
198
|
+
if (pragmas?.lockingMode) {
|
|
199
|
+
db.exec(`PRAGMA locking_mode = ${pragmas.lockingMode.toUpperCase()}`);
|
|
200
|
+
}
|
|
201
|
+
if (pragmas?.tempStore && pragmas.tempStore !== "DEFAULT") {
|
|
202
|
+
db.exec(`PRAGMA temp_store = ${pragmas.tempStore.toUpperCase()}`);
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const create = async (
|
|
207
|
+
directory?: string,
|
|
208
|
+
options?: { pragmas?: SQLitePragmaOptions },
|
|
209
|
+
) => {
|
|
187
210
|
let statements: Map<string, Statement> = new Map();
|
|
188
211
|
|
|
189
212
|
const sqlite3 = await getSqlite3();
|
|
@@ -299,8 +322,7 @@ const create = async (directory?: string) => {
|
|
|
299
322
|
if (!sqliteDb) {
|
|
300
323
|
throw new Error("Failed to open sqlite database");
|
|
301
324
|
}
|
|
302
|
-
sqliteDb
|
|
303
|
-
sqliteDb.exec("PRAGMA foreign_keys = on");
|
|
325
|
+
applyPragmas(sqliteDb, options?.pragmas);
|
|
304
326
|
};
|
|
305
327
|
|
|
306
328
|
return {
|