@firtoz/drizzle-sqlite-wasm 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.
@@ -0,0 +1,148 @@
1
+ // Adapted from https://github.com/drizzle-team/drizzle-orm/blob/main/drizzle-orm/src/durable-sqlite/migrator.ts
2
+ // Adaptation date: 26/10/2025 20:28 commit 9cf0ed2
3
+
4
+ import { sql } from "drizzle-orm";
5
+ import type { MigrationMeta } from "drizzle-orm/migrator";
6
+ import type { SqliteRemoteDatabase } from "drizzle-orm/sqlite-proxy";
7
+ import type { migrate as durableSqliteMigrate } from "drizzle-orm/durable-sqlite/migrator";
8
+
9
+ export type DurableSqliteMigrationConfig = Parameters<
10
+ typeof durableSqliteMigrate
11
+ >[1];
12
+
13
+ function readMigrationFiles({
14
+ journal,
15
+ migrations,
16
+ }: DurableSqliteMigrationConfig): MigrationMeta[] {
17
+ const migrationQueries: MigrationMeta[] = [];
18
+
19
+ for (const journalEntry of journal.entries) {
20
+ const query =
21
+ migrations[`m${journalEntry.idx.toString().padStart(4, "0")}`];
22
+
23
+ if (!query) {
24
+ throw new Error(`Missing migration: ${journalEntry.tag}`);
25
+ }
26
+
27
+ try {
28
+ const result = query.split("--> statement-breakpoint").map((it) => {
29
+ return it;
30
+ });
31
+
32
+ migrationQueries.push({
33
+ sql: result,
34
+ bps: journalEntry.breakpoints,
35
+ folderMillis: journalEntry.when,
36
+ hash: "",
37
+ });
38
+ } catch {
39
+ throw new Error(`Failed to parse migration: ${journalEntry.tag}`);
40
+ }
41
+ }
42
+
43
+ return migrationQueries;
44
+ }
45
+
46
+ export async function customSqliteMigrate<
47
+ TSchema extends Record<string, unknown>,
48
+ >(
49
+ db: SqliteRemoteDatabase<TSchema>,
50
+ config: DurableSqliteMigrationConfig,
51
+ debug: boolean = false,
52
+ ): Promise<void> {
53
+ if (debug) {
54
+ console.log(
55
+ `[${new Date().toISOString()}] [SqliteWasmMigrator] migrating database`,
56
+ config,
57
+ );
58
+ }
59
+
60
+ const migrations = readMigrationFiles(config);
61
+ let currentStatement: string | null = null;
62
+
63
+ let migrationCount = 0;
64
+ let success = true;
65
+
66
+ await db.transaction(async (tx) => {
67
+ try {
68
+ const migrationsTable = "__drizzle_migrations";
69
+
70
+ await tx.run(sql`
71
+ CREATE TABLE IF NOT EXISTS ${sql.identifier(migrationsTable)} (
72
+ id SERIAL PRIMARY KEY,
73
+ hash text NOT NULL,
74
+ created_at numeric
75
+ )
76
+ `);
77
+
78
+ const dbMigrations = await tx.values<[number, string, string]>(
79
+ sql`SELECT id, hash, created_at FROM ${sql.identifier(migrationsTable)} ORDER BY created_at DESC LIMIT 1`,
80
+ );
81
+
82
+ const lastDbMigration = dbMigrations[0] ?? undefined;
83
+
84
+ if (debug) {
85
+ console.log(
86
+ `[${new Date().toISOString()}] [SqliteWasmMigrator] last db migration`,
87
+ lastDbMigration,
88
+ );
89
+ }
90
+
91
+ for (const migration of migrations) {
92
+ if (
93
+ !lastDbMigration ||
94
+ Number(lastDbMigration[2]) < migration.folderMillis
95
+ ) {
96
+ for (const stmt of migration.sql) {
97
+ currentStatement = stmt;
98
+ if (debug) {
99
+ console.log(
100
+ `[${new Date().toISOString()}] [SqliteWasmMigrator] running migration`,
101
+ stmt,
102
+ );
103
+ }
104
+ await tx.run(sql.raw(stmt));
105
+ currentStatement = null;
106
+ }
107
+ await tx.run(
108
+ sql`INSERT INTO ${sql.identifier(
109
+ migrationsTable,
110
+ )} ("hash", "created_at") VALUES(${migration.hash}, ${migration.folderMillis})`,
111
+ );
112
+ migrationCount++;
113
+ }
114
+ }
115
+ } catch (error: unknown) {
116
+ const e = error instanceof Error ? error : new Error(String(error));
117
+ console.error("[Sqlite WASM Migrator] Database migration failed:", {
118
+ error: e,
119
+ errorMessage: e.message,
120
+ errorStack: e.stack,
121
+ migrations: Object.keys(migrations),
122
+ ...(currentStatement && { failedStatement: currentStatement }),
123
+ });
124
+ tx.rollback();
125
+ success = false;
126
+ throw e;
127
+ }
128
+ });
129
+
130
+ if (debug) {
131
+ if (!success) {
132
+ console.log(
133
+ `[${new Date().toISOString()}] [SqliteWasmMigrator] migration failed.`,
134
+ );
135
+ return;
136
+ }
137
+
138
+ if (migrationCount > 0) {
139
+ console.log(
140
+ `[${new Date().toISOString()}] [SqliteWasmMigrator] migration completed. migrations count: ${migrationCount} migrations applied.`,
141
+ );
142
+ } else {
143
+ console.log(
144
+ `[${new Date().toISOString()}] [SqliteWasmMigrator] no migrations applied.`,
145
+ );
146
+ }
147
+ }
148
+ }
@@ -0,0 +1,11 @@
1
+ import type { SqliteWorkerRemoteCallbackClientMessage } from "./schema";
2
+
3
+ export interface ISqliteWorkerClient {
4
+ performRemoteCallback: (
5
+ data: Omit<SqliteWorkerRemoteCallbackClientMessage, "type" | "id" | "dbId">,
6
+ resolve: (value: { rows: unknown[] }) => void,
7
+ reject: (error: Error) => void,
8
+ ) => void;
9
+ onStarted: (callback: () => void) => void;
10
+ terminate: () => void;
11
+ }
@@ -0,0 +1,78 @@
1
+ import { SqliteWorkerManager } from "./manager";
2
+
3
+ let globalManager: SqliteWorkerManager | null = null;
4
+ let initPromise: Promise<SqliteWorkerManager> | null = null;
5
+
6
+ /**
7
+ * Initialize the global SQLite worker manager.
8
+ * Should be called once, early in your app (e.g., in entry.client.tsx).
9
+ * Subsequent calls return the same manager instance.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * // In entry.client.tsx
14
+ * import { initializeSqliteWorker } from "@firtoz/drizzle-sqlite-wasm";
15
+ * import SqliteWorker from "@firtoz/drizzle-sqlite-wasm/worker/sqlite.worker?worker";
16
+ *
17
+ * initializeSqliteWorker(SqliteWorker);
18
+ * ```
19
+ */
20
+ export function initializeSqliteWorker(
21
+ WorkerConstructor: new () => Worker,
22
+ debug: boolean = false,
23
+ ): Promise<SqliteWorkerManager> {
24
+ // Return existing init promise if initialization is in progress
25
+ if (initPromise) {
26
+ return initPromise;
27
+ }
28
+
29
+ // Return resolved promise if already initialized
30
+ if (globalManager) {
31
+ return Promise.resolve(globalManager);
32
+ }
33
+
34
+ // Start initialization
35
+ initPromise = (async () => {
36
+ const worker = new WorkerConstructor();
37
+ const manager = new SqliteWorkerManager(worker, debug);
38
+ globalManager = manager;
39
+
40
+ // Wait for the worker to actually send its Ready message
41
+ await manager.ready;
42
+
43
+ return manager;
44
+ })();
45
+
46
+ return initPromise;
47
+ }
48
+
49
+ /**
50
+ * Get the global SQLite worker manager.
51
+ * Throws an error if not initialized.
52
+ */
53
+ export function getSqliteWorkerManager(): SqliteWorkerManager {
54
+ if (!globalManager) {
55
+ throw new Error(
56
+ "SQLite worker manager not initialized. Call initializeSqliteWorker() first.",
57
+ );
58
+ }
59
+ return globalManager;
60
+ }
61
+
62
+ /**
63
+ * Check if the global manager has been initialized
64
+ */
65
+ export function isSqliteWorkerInitialized(): boolean {
66
+ return globalManager !== null;
67
+ }
68
+
69
+ /**
70
+ * Reset the global manager (mainly for testing)
71
+ */
72
+ export function resetSqliteWorkerManager() {
73
+ if (globalManager) {
74
+ globalManager.terminate();
75
+ }
76
+ globalManager = null;
77
+ initPromise = null;
78
+ }
@@ -0,0 +1,339 @@
1
+ import { exhaustiveGuard } from "@firtoz/maybe-error";
2
+ import { WorkerClient } from "@firtoz/worker-helper/WorkerClient";
3
+ import {
4
+ type SqliteWorkerClientMessage,
5
+ type SqliteWorkerServerMessage,
6
+ type RemoteCallbackId,
7
+ type DbId,
8
+ type StartRequestId,
9
+ type CheckpointId,
10
+ SqliteWorkerClientMessageSchema,
11
+ sqliteWorkerServerMessage,
12
+ SqliteWorkerServerMessageType,
13
+ SqliteWorkerClientMessageType,
14
+ type SqliteWorkerRemoteCallbackClientMessage,
15
+ RemoteCallbackIdSchema,
16
+ StartRequestIdSchema,
17
+ CheckpointIdSchema,
18
+ } from "./schema";
19
+
20
+ export interface ISqliteWorkerClient {
21
+ performRemoteCallback: (
22
+ data: Omit<SqliteWorkerRemoteCallbackClientMessage, "type" | "id" | "dbId">,
23
+ resolve: (value: { rows: unknown[] }) => void,
24
+ reject: (error: Error) => void,
25
+ ) => void;
26
+ checkpoint: () => Promise<void>;
27
+ onStarted: (callback: () => void) => void;
28
+ terminate: () => void;
29
+ }
30
+
31
+ /**
32
+ * Per-database instance that can perform operations on a specific database
33
+ */
34
+ export class DbInstance implements ISqliteWorkerClient {
35
+ private dbId: DbId | null = null;
36
+ private startedCallbacks: Array<() => void> = [];
37
+ private isStarted = false;
38
+
39
+ constructor(
40
+ private readonly manager: SqliteWorkerManager,
41
+ public readonly dbName: string,
42
+ private readonly debug: boolean = false,
43
+ ) {}
44
+
45
+ /**
46
+ * Internal method called by manager when database is started
47
+ */
48
+ _setStarted(dbId: DbId) {
49
+ this.dbId = dbId;
50
+ this.isStarted = true;
51
+
52
+ // Call all pending callbacks
53
+ for (const callback of this.startedCallbacks) {
54
+ callback();
55
+ }
56
+ this.startedCallbacks = [];
57
+ }
58
+
59
+ public performRemoteCallback(
60
+ data: Omit<SqliteWorkerRemoteCallbackClientMessage, "type" | "id" | "dbId">,
61
+ resolve: (value: { rows: unknown[] }) => void,
62
+ reject: (error: Error) => void,
63
+ ) {
64
+ if (!this.dbId) {
65
+ reject(
66
+ new Error(`Database not started - dbId is null for ${this.dbName}`),
67
+ );
68
+ return;
69
+ }
70
+
71
+ if (this.debug) {
72
+ console.log(
73
+ `[${new Date().toISOString()}] [DbInstance:${this.dbName}] performing remote callback`,
74
+ data,
75
+ );
76
+ }
77
+
78
+ this.manager.performRemoteCallback(this.dbId, data, resolve, reject);
79
+ }
80
+
81
+ public checkpoint(): Promise<void> {
82
+ return new Promise((resolve, reject) => {
83
+ if (!this.dbId) {
84
+ reject(
85
+ new Error(`Database not started - dbId is null for ${this.dbName}`),
86
+ );
87
+ return;
88
+ }
89
+
90
+ if (this.debug) {
91
+ console.log(
92
+ `[${new Date().toISOString()}] [DbInstance:${this.dbName}] checkpointing database`,
93
+ );
94
+ }
95
+
96
+ this.manager.checkpoint(this.dbId, resolve, reject);
97
+ });
98
+ }
99
+
100
+ public onStarted(callback: () => void) {
101
+ if (this.isStarted) {
102
+ // Already started, call immediately
103
+ callback();
104
+ } else {
105
+ this.startedCallbacks.push(callback);
106
+ }
107
+ }
108
+
109
+ public terminate() {
110
+ // Per-db instances don't terminate the worker
111
+ // That's managed by the SqliteWorkerManager
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Main worker manager that can create multiple database instances
117
+ */
118
+ export class SqliteWorkerManager extends WorkerClient<
119
+ SqliteWorkerClientMessage,
120
+ SqliteWorkerServerMessage
121
+ > {
122
+ private readonly remoteCallbacks = new Map<
123
+ RemoteCallbackId,
124
+ {
125
+ resolve: (value: { rows: unknown[] }) => void;
126
+ reject: (error: Error) => void;
127
+ }
128
+ >();
129
+
130
+ private readonly checkpointCallbacks = new Map<
131
+ CheckpointId,
132
+ {
133
+ resolve: () => void;
134
+ reject: (error: Error) => void;
135
+ }
136
+ >();
137
+
138
+ private readyResolve?: () => void;
139
+ private readyReject?: (error: Error) => void;
140
+ private readonly readyPromise: Promise<void>;
141
+ private isReady = false;
142
+
143
+ private readonly dbInstances = new Map<string, DbInstance>();
144
+ private readonly pendingStarts = new Map<
145
+ StartRequestId,
146
+ { dbName: string; instance: DbInstance }
147
+ >();
148
+
149
+ constructor(
150
+ worker: Worker,
151
+ private readonly debug: boolean = false,
152
+ ) {
153
+ super({
154
+ worker,
155
+ clientSchema: SqliteWorkerClientMessageSchema,
156
+ serverSchema: sqliteWorkerServerMessage,
157
+ onMessage: (message) => {
158
+ this.onMessage(message);
159
+ },
160
+ onValidationError: (error, rawMessage) => {
161
+ console.error(error, rawMessage);
162
+ // Reject promises if we get validation errors before being ready
163
+ if (!this.isReady && this.readyReject) {
164
+ this.readyReject(new Error(`Validation error: ${error.message}`));
165
+ }
166
+ },
167
+ onError: (event) => {
168
+ console.error(event);
169
+ // Reject promises if worker errors before being ready
170
+ if (!this.isReady && this.readyReject) {
171
+ this.readyReject(
172
+ new Error(`Worker error: ${event.message || "Unknown error"}`),
173
+ );
174
+ }
175
+ },
176
+ });
177
+
178
+ this.readyPromise = new Promise((resolve, reject) => {
179
+ this.readyResolve = resolve;
180
+ this.readyReject = reject;
181
+ });
182
+ }
183
+
184
+ /**
185
+ * Promise that resolves when the worker sends its first Ready message
186
+ */
187
+ public get ready(): Promise<void> {
188
+ return this.readyPromise;
189
+ }
190
+
191
+ private onMessage(message: SqliteWorkerServerMessage) {
192
+ const { type } = message;
193
+ switch (type) {
194
+ case SqliteWorkerServerMessageType.Ready:
195
+ {
196
+ this.isReady = true;
197
+ this.readyResolve?.();
198
+ if (this.debug) {
199
+ console.log("[SqliteWorkerManager] ready for databases");
200
+ }
201
+ }
202
+ break;
203
+ case SqliteWorkerServerMessageType.Started:
204
+ {
205
+ const pending = this.pendingStarts.get(message.requestId);
206
+ if (pending) {
207
+ pending.instance._setStarted(message.dbId);
208
+ this.pendingStarts.delete(message.requestId);
209
+ }
210
+ }
211
+ break;
212
+ case SqliteWorkerServerMessageType.RemoteCallbackResponse:
213
+ {
214
+ const { id, rows } = message;
215
+ const remoteCallback = this.remoteCallbacks.get(id);
216
+ if (remoteCallback) {
217
+ remoteCallback.resolve({ rows });
218
+ this.remoteCallbacks.delete(id);
219
+ }
220
+ }
221
+ break;
222
+ case SqliteWorkerServerMessageType.RemoteCallbackError:
223
+ {
224
+ const { id, error } = message;
225
+ const remoteCallback = this.remoteCallbacks.get(id);
226
+ if (remoteCallback) {
227
+ remoteCallback.reject(new Error(error));
228
+ this.remoteCallbacks.delete(id);
229
+ }
230
+ }
231
+ break;
232
+ case SqliteWorkerServerMessageType.CheckpointComplete:
233
+ {
234
+ const { id } = message;
235
+ const checkpointCallback = this.checkpointCallbacks.get(id);
236
+ if (checkpointCallback) {
237
+ checkpointCallback.resolve();
238
+ this.checkpointCallbacks.delete(id);
239
+ }
240
+ }
241
+ break;
242
+ case SqliteWorkerServerMessageType.CheckpointError:
243
+ {
244
+ const { id, error } = message;
245
+ const checkpointCallback = this.checkpointCallbacks.get(id);
246
+ if (checkpointCallback) {
247
+ checkpointCallback.reject(new Error(error));
248
+ this.checkpointCallbacks.delete(id);
249
+ }
250
+ }
251
+ break;
252
+ default:
253
+ return exhaustiveGuard(type);
254
+ }
255
+ }
256
+
257
+ /**
258
+ * Get or create a database instance
259
+ */
260
+ public async getDbInstance(dbName: string): Promise<DbInstance> {
261
+ // Check if instance already exists
262
+ let instance = this.dbInstances.get(dbName);
263
+ if (instance) {
264
+ return instance;
265
+ }
266
+
267
+ // Check again after waiting (another call might have created it)
268
+ instance = this.dbInstances.get(dbName);
269
+ if (instance) {
270
+ return instance;
271
+ }
272
+
273
+ // Create new instance
274
+ instance = new DbInstance(this, dbName, this.debug);
275
+ this.dbInstances.set(dbName, instance);
276
+
277
+ // Start the database
278
+
279
+ const startRequestId = StartRequestIdSchema.parse(crypto.randomUUID());
280
+ this.pendingStarts.set(startRequestId, { dbName, instance });
281
+
282
+ this.send({
283
+ type: SqliteWorkerClientMessageType.Start,
284
+ requestId: startRequestId,
285
+ dbName: dbName,
286
+ });
287
+
288
+ return instance;
289
+ }
290
+
291
+ /**
292
+ * Internal method for db instances to perform remote callbacks
293
+ */
294
+ public performRemoteCallback(
295
+ dbId: DbId,
296
+ data: Omit<SqliteWorkerRemoteCallbackClientMessage, "type" | "id" | "dbId">,
297
+ resolve: (value: { rows: unknown[] }) => void,
298
+ reject: (error: Error) => void,
299
+ ) {
300
+ if (this.debug) {
301
+ console.log(
302
+ `[${new Date().toISOString()}] [SqliteWorkerManager] performing remote callback for dbId: ${dbId}`,
303
+ data,
304
+ );
305
+ }
306
+ const id = RemoteCallbackIdSchema.parse(crypto.randomUUID());
307
+ this.remoteCallbacks.set(id, { resolve, reject });
308
+ this.send({
309
+ type: SqliteWorkerClientMessageType.RemoteCallbackRequest,
310
+ id,
311
+ dbId,
312
+ sql: data.sql,
313
+ params: data.params,
314
+ method: data.method,
315
+ });
316
+ }
317
+
318
+ /**
319
+ * Internal method for db instances to checkpoint the database
320
+ */
321
+ public checkpoint(
322
+ dbId: DbId,
323
+ resolve: () => void,
324
+ reject: (error: Error) => void,
325
+ ) {
326
+ if (this.debug) {
327
+ console.log(
328
+ `[${new Date().toISOString()}] [SqliteWorkerManager] checkpointing database for dbId: ${dbId}`,
329
+ );
330
+ }
331
+ const id = CheckpointIdSchema.parse(crypto.randomUUID());
332
+ this.checkpointCallbacks.set(id, { resolve, reject });
333
+ this.send({
334
+ type: SqliteWorkerClientMessageType.Checkpoint,
335
+ id,
336
+ dbId,
337
+ });
338
+ }
339
+ }
@@ -0,0 +1,111 @@
1
+ import z from "zod";
2
+
3
+ export const RemoteCallbackIdSchema = z.string().brand("remote-callback-id");
4
+ export type RemoteCallbackId = z.infer<typeof RemoteCallbackIdSchema>;
5
+
6
+ export const DbIdSchema = z.string().brand("db-id");
7
+ export type DbId = z.infer<typeof DbIdSchema>;
8
+
9
+ export const StartRequestIdSchema = z.string().brand("start-request-id");
10
+ export type StartRequestId = z.infer<typeof StartRequestIdSchema>;
11
+
12
+ export const CheckpointIdSchema = z.string().brand("checkpoint-id");
13
+ export type CheckpointId = z.infer<typeof CheckpointIdSchema>;
14
+
15
+ export enum SqliteWorkerClientMessageType {
16
+ Start = "start",
17
+ RemoteCallbackRequest = "remote-callback-request",
18
+ Checkpoint = "checkpoint",
19
+ }
20
+
21
+ export enum SqliteWorkerServerMessageType {
22
+ Ready = "ready",
23
+ Started = "started",
24
+ RemoteCallbackResponse = "remote-callback-response",
25
+ RemoteCallbackError = "remote-callback-error",
26
+ CheckpointComplete = "checkpoint-complete",
27
+ CheckpointError = "checkpoint-error",
28
+ }
29
+
30
+ export const RemoteCallbackRequestSchema = z.object({
31
+ type: z.literal(SqliteWorkerClientMessageType.RemoteCallbackRequest),
32
+ // AsyncRemoteCallback
33
+ // sql: string, params: any[], method: 'run' | 'all' | 'values' | 'get'
34
+ id: RemoteCallbackIdSchema,
35
+ dbId: DbIdSchema,
36
+ sql: z.string(),
37
+ params: z.array(z.any()),
38
+ method: z.enum(["run", "all", "values", "get"]),
39
+ });
40
+
41
+ export type SqliteWorkerRemoteCallbackClientMessage = z.infer<
42
+ typeof RemoteCallbackRequestSchema
43
+ >;
44
+
45
+ export const CheckpointRequestSchema = z.object({
46
+ type: z.literal(SqliteWorkerClientMessageType.Checkpoint),
47
+ id: CheckpointIdSchema,
48
+ dbId: DbIdSchema,
49
+ });
50
+
51
+ export type CheckpointRequest = z.infer<typeof CheckpointRequestSchema>;
52
+
53
+ export const SqliteWorkerClientMessageSchema = z.discriminatedUnion("type", [
54
+ z.object({
55
+ type: z.literal(SqliteWorkerClientMessageType.Start),
56
+ requestId: StartRequestIdSchema,
57
+ dbName: z.string(),
58
+ }),
59
+ RemoteCallbackRequestSchema,
60
+ CheckpointRequestSchema,
61
+ ]);
62
+
63
+ export const RemoteCallbackResponseSchema = z.object({
64
+ type: z.literal(SqliteWorkerServerMessageType.RemoteCallbackResponse),
65
+ id: RemoteCallbackIdSchema,
66
+ rows: z.array(z.any()),
67
+ });
68
+
69
+ export const RemoteCallbackErrorServerMessageSchema = z.object({
70
+ type: z.literal(SqliteWorkerServerMessageType.RemoteCallbackError),
71
+ id: RemoteCallbackIdSchema,
72
+ error: z.string(),
73
+ });
74
+
75
+ export const CheckpointCompleteSchema = z.object({
76
+ type: z.literal(SqliteWorkerServerMessageType.CheckpointComplete),
77
+ id: CheckpointIdSchema,
78
+ });
79
+
80
+ export const CheckpointErrorSchema = z.object({
81
+ type: z.literal(SqliteWorkerServerMessageType.CheckpointError),
82
+ id: CheckpointIdSchema,
83
+ error: z.string(),
84
+ });
85
+
86
+ export const sqliteWorkerServerMessage = z.discriminatedUnion("type", [
87
+ z.object({
88
+ type: z.literal(SqliteWorkerServerMessageType.Ready),
89
+ }),
90
+ z.object({
91
+ type: z.literal(SqliteWorkerServerMessageType.Started),
92
+ requestId: StartRequestIdSchema,
93
+ dbId: DbIdSchema,
94
+ }),
95
+ RemoteCallbackResponseSchema,
96
+ RemoteCallbackErrorServerMessageSchema,
97
+ CheckpointCompleteSchema,
98
+ CheckpointErrorSchema,
99
+ ]);
100
+
101
+ export type SqliteWorkerClientMessage = z.infer<
102
+ typeof SqliteWorkerClientMessageSchema
103
+ >;
104
+
105
+ export type SqliteWorkerServerMessage = z.infer<
106
+ typeof sqliteWorkerServerMessage
107
+ >;
108
+
109
+ export type SqliteClientRemoteCallbackServerMessage = z.infer<
110
+ typeof RemoteCallbackResponseSchema
111
+ >;