@firtoz/drizzle-sqlite-wasm 1.0.4 → 1.1.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/CHANGELOG.md +32 -0
- package/README.md +9 -1
- package/dist/chunk-6LNYKOKR.js +24 -0
- package/dist/chunk-6LNYKOKR.js.map +1 -0
- package/dist/chunk-7JJHY44Q.js +19 -0
- package/dist/chunk-7JJHY44Q.js.map +1 -0
- package/dist/chunk-AEYHRJVN.js +130 -0
- package/dist/chunk-AEYHRJVN.js.map +1 -0
- package/dist/chunk-AGMKOHXO.js +238 -0
- package/dist/chunk-AGMKOHXO.js.map +1 -0
- package/dist/chunk-BJDPMGFF.js +87 -0
- package/dist/chunk-BJDPMGFF.js.map +1 -0
- package/dist/chunk-BZVMUTJ7.js +49 -0
- package/dist/chunk-BZVMUTJ7.js.map +1 -0
- package/dist/chunk-FIVEPVOM.js +43 -0
- package/dist/chunk-FIVEPVOM.js.map +1 -0
- package/dist/chunk-FRONXNEA.js +123 -0
- package/dist/chunk-FRONXNEA.js.map +1 -0
- package/dist/chunk-GVUNHU6J.js +85 -0
- package/dist/chunk-GVUNHU6J.js.map +1 -0
- package/dist/chunk-H2F2HZ2A.js +22 -0
- package/dist/chunk-H2F2HZ2A.js.map +1 -0
- package/dist/chunk-NSPVPJKE.js +117 -0
- package/dist/chunk-NSPVPJKE.js.map +1 -0
- package/dist/chunk-TZP4AIBR.js +22 -0
- package/dist/chunk-TZP4AIBR.js.map +1 -0
- package/dist/chunk-WFFFP6DB.js +124 -0
- package/dist/chunk-WFFFP6DB.js.map +1 -0
- package/dist/collections/sqlite-collection.d.ts +40 -0
- package/dist/collections/sqlite-collection.js +3 -0
- package/dist/collections/sqlite-collection.js.map +1 -0
- package/dist/collections/synced-sqlite-collection.d.ts +19 -0
- package/dist/collections/synced-sqlite-collection.js +4 -0
- package/dist/collections/synced-sqlite-collection.js.map +1 -0
- package/dist/collections/websocket-collection.d.ts +18 -0
- package/dist/collections/websocket-collection.js +185 -0
- package/dist/collections/websocket-collection.js.map +1 -0
- package/dist/context/DrizzleSqliteProvider.d.ts +50 -0
- package/dist/context/DrizzleSqliteProvider.js +11 -0
- package/dist/context/DrizzleSqliteProvider.js.map +1 -0
- package/dist/context/useDrizzleSqlite.d.ts +23 -0
- package/dist/context/useDrizzleSqlite.js +12 -0
- package/dist/context/useDrizzleSqlite.js.map +1 -0
- package/dist/drizzle/direct.d.ts +8 -0
- package/dist/drizzle/direct.js +4 -0
- package/dist/drizzle/direct.js.map +1 -0
- package/dist/drizzle/handle-callback.d.ts +15 -0
- package/dist/drizzle/handle-callback.js +3 -0
- package/dist/drizzle/handle-callback.js.map +1 -0
- package/dist/drizzle/worker.d.ts +15 -0
- package/dist/drizzle/worker.js +3 -0
- package/dist/drizzle/worker.js.map +1 -0
- package/dist/hooks/useDrizzleSqliteDb.d.ts +24 -0
- package/dist/hooks/useDrizzleSqliteDb.js +9 -0
- package/dist/hooks/useDrizzleSqliteDb.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/migration/migrator.d.ts +7 -0
- package/dist/migration/migrator.js +3 -0
- package/dist/migration/migrator.js.map +1 -0
- package/dist/types.d.ts +6 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/worker/client.d.ts +12 -0
- package/dist/worker/client.js +3 -0
- package/dist/worker/client.js.map +1 -0
- package/dist/worker/global-manager.d.ts +36 -0
- package/dist/worker/global-manager.js +6 -0
- package/dist/worker/global-manager.js.map +1 -0
- package/dist/worker/manager.d.ts +71 -0
- package/dist/worker/manager.js +5 -0
- package/dist/worker/manager.js.map +1 -0
- package/dist/worker/schema.d.ts +125 -0
- package/dist/worker/schema.js +4 -0
- package/dist/worker/schema.js.map +1 -0
- package/dist/worker/sqlite-open-options.d.ts +45 -0
- package/dist/worker/sqlite-open-options.js +3 -0
- package/dist/worker/sqlite-open-options.js.map +1 -0
- package/dist/worker/sqlite.worker.d.ts +2 -0
- package/dist/worker/sqlite.worker.js +196 -0
- package/dist/worker/sqlite.worker.js.map +1 -0
- package/package.json +25 -25
- package/src/collections/sqlite-collection.ts +4 -4
- package/src/hooks/useDrizzleSqliteDb.ts +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# @firtoz/drizzle-sqlite-wasm
|
|
2
2
|
|
|
3
|
+
## 1.1.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`258feef`](https://github.com/firtoz/fullstack-toolkit/commit/258feef02802ebfe1f1284d1033e20f62a0c9643) Thanks [@firtoz](https://github.com/firtoz)! - Fix `compilerOptions.lib` in tsconfig (was at top level instead of inside `compilerOptions`); add `DOM` so `window` resolves during DTS generation.
|
|
8
|
+
|
|
9
|
+
## 1.1.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- [`c3a3cc7`](https://github.com/firtoz/fullstack-toolkit/commit/c3a3cc778ba9ce4b5efe1bcdd8d541f46dec3bfd) Thanks [@firtoz](https://github.com/firtoz)! - Publish compiled ESM and TypeScript declarations from `dist/` for each package (`tsup`, `prepack` build). `exports`, `main`, and `types` resolve to `dist/`; CLI bins point at built JS with a Node shebang where applicable. Shared `scripts/tsup-lib.ts` discovers `src` entries and externals; workspace test apps map `@firtoz/*` to package sources in `tsconfig` for accurate generics during typecheck. `@firtoz/socka` is published under the scoped name with the same `dist/` layout.
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- [`f78c988`](https://github.com/firtoz/fullstack-toolkit/commit/f78c988d37a9cc48490ee3372dccc14a42810bfe) Thanks [@firtoz](https://github.com/firtoz)! - Improve READMEs: npm shields, contextual stack badges, clearer taglines, and new docs for `@firtoz/idb-collections` and `@firtoz/collection-sync`. Align `@firtoz/db-helpers` copy with published `dist/` builds.
|
|
18
|
+
|
|
19
|
+
- Updated dependencies [[`c3a3cc7`](https://github.com/firtoz/fullstack-toolkit/commit/c3a3cc778ba9ce4b5efe1bcdd8d541f46dec3bfd), [`f78c988`](https://github.com/firtoz/fullstack-toolkit/commit/f78c988d37a9cc48490ee3372dccc14a42810bfe)]:
|
|
20
|
+
- @firtoz/collection-sync@6.0.0
|
|
21
|
+
- @firtoz/db-helpers@2.2.0
|
|
22
|
+
- @firtoz/drizzle-utils@1.3.0
|
|
23
|
+
- @firtoz/maybe-error@1.6.0
|
|
24
|
+
- @firtoz/worker-helper@1.6.0
|
|
25
|
+
|
|
26
|
+
## 1.0.5
|
|
27
|
+
|
|
28
|
+
### Patch Changes
|
|
29
|
+
|
|
30
|
+
- Updated dependencies [[`d35e718`](https://github.com/firtoz/fullstack-toolkit/commit/d35e718bf3292258c2b0006affc7aad5ecc35208), [`138c394`](https://github.com/firtoz/fullstack-toolkit/commit/138c3944b491ebf2e76b7f2c00d651fd5d788bac), [`d35e718`](https://github.com/firtoz/fullstack-toolkit/commit/d35e718bf3292258c2b0006affc7aad5ecc35208)]:
|
|
31
|
+
- @firtoz/collection-sync@5.0.0
|
|
32
|
+
- @firtoz/db-helpers@2.1.1
|
|
33
|
+
- @firtoz/drizzle-utils@1.2.1
|
|
34
|
+
|
|
3
35
|
## 1.0.4
|
|
4
36
|
|
|
5
37
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
# @firtoz/drizzle-sqlite-wasm
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@firtoz/drizzle-sqlite-wasm)
|
|
4
|
+
[](https://www.npmjs.com/package/@firtoz/drizzle-sqlite-wasm)
|
|
5
|
+
[](https://github.com/firtoz/fullstack-toolkit/blob/main/LICENSE)
|
|
6
|
+
|
|
7
|
+
[](https://www.typescriptlang.org/)
|
|
8
|
+
[](https://orm.drizzle.team/)
|
|
9
|
+
[](https://tanstack.com/db)
|
|
10
|
+
|
|
11
|
+
**SQLite WASM in a worker, Drizzle ORM, TanStack DB collections** — reactive, non-blocking browser databases with migrations and React hooks when you need them.
|
|
4
12
|
|
|
5
13
|
> **⚠️ Early WIP Notice:** This package is in very early development and is **not production-ready**. It is TypeScript-only and may have breaking changes. While I (the maintainer) have limited time, I'm open to PRs for features, bug fixes, or additional support (like JS builds). Please feel free to try it out and contribute! See [CONTRIBUTING.md](../../CONTRIBUTING.md) for details.
|
|
6
14
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
|
|
3
|
+
// src/worker/sqlite-open-options.ts
|
|
4
|
+
var SqliteWasmSynchronousModeSchema = z.enum([
|
|
5
|
+
"OFF",
|
|
6
|
+
"NORMAL",
|
|
7
|
+
"FULL",
|
|
8
|
+
"EXTRA"
|
|
9
|
+
]);
|
|
10
|
+
var SqliteWasmJournalModeSchema = z.enum([
|
|
11
|
+
"WAL",
|
|
12
|
+
"DELETE",
|
|
13
|
+
"TRUNCATE",
|
|
14
|
+
"MEMORY",
|
|
15
|
+
"OFF"
|
|
16
|
+
]);
|
|
17
|
+
var SqliteWasmWorkerOpenOptionsSchema = z.object({
|
|
18
|
+
synchronous: SqliteWasmSynchronousModeSchema.optional(),
|
|
19
|
+
journalMode: SqliteWasmJournalModeSchema.optional()
|
|
20
|
+
}).strict();
|
|
21
|
+
|
|
22
|
+
export { SqliteWasmJournalModeSchema, SqliteWasmSynchronousModeSchema, SqliteWasmWorkerOpenOptionsSchema };
|
|
23
|
+
//# sourceMappingURL=chunk-6LNYKOKR.js.map
|
|
24
|
+
//# sourceMappingURL=chunk-6LNYKOKR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/worker/sqlite-open-options.ts"],"names":[],"mappings":";;;AAOO,IAAM,+BAAA,GAAkC,EAAE,IAAA,CAAK;AAAA,EACrD,KAAA;AAAA,EACA,QAAA;AAAA,EACA,MAAA;AAAA,EACA;AACD,CAAC;AASM,IAAM,2BAAA,GAA8B,EAAE,IAAA,CAAK;AAAA,EACjD,KAAA;AAAA,EACA,QAAA;AAAA,EACA,UAAA;AAAA,EACA,QAAA;AAAA,EACA;AACD,CAAC;AAIM,IAAM,iCAAA,GAAoC,EAC/C,MAAA,CAAO;AAAA,EACP,WAAA,EAAa,gCAAgC,QAAA,EAAS;AAAA,EACtD,WAAA,EAAa,4BAA4B,QAAA;AAC1C,CAAC,EACA,MAAA","file":"chunk-6LNYKOKR.js","sourcesContent":["import z from \"zod\";\n\n/**\n * SQLite `PRAGMA synchronous` levels (see SQLite docs). Default worker behavior\n * remains `FULL` for maximum durability with OPFS; `NORMAL` is often much faster\n * for interactive UIs at the cost of a narrower crash window.\n */\nexport const SqliteWasmSynchronousModeSchema = z.enum([\n\t\"OFF\",\n\t\"NORMAL\",\n\t\"FULL\",\n\t\"EXTRA\",\n]);\nexport type SqliteWasmSynchronousMode = z.infer<\n\ttypeof SqliteWasmSynchronousModeSchema\n>;\n\n/**\n * SQLite `PRAGMA journal_mode` values the worker will pass through as\n * `PRAGMA journal_mode=<value>;` (uppercase).\n */\nexport const SqliteWasmJournalModeSchema = z.enum([\n\t\"WAL\",\n\t\"DELETE\",\n\t\"TRUNCATE\",\n\t\"MEMORY\",\n\t\"OFF\",\n]);\nexport type SqliteWasmJournalMode = z.infer<typeof SqliteWasmJournalModeSchema>;\n\n/** Options applied once when the worker opens a database file (OPFS or transient). */\nexport const SqliteWasmWorkerOpenOptionsSchema = z\n\t.object({\n\t\tsynchronous: SqliteWasmSynchronousModeSchema.optional(),\n\t\tjournalMode: SqliteWasmJournalModeSchema.optional(),\n\t})\n\t.strict();\n\nexport type SqliteWasmWorkerOpenOptions = z.infer<\n\ttypeof SqliteWasmWorkerOpenOptionsSchema\n>;\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { sqliteCollectionOptions } from './chunk-BZVMUTJ7.js';
|
|
2
|
+
import { createSyncedCollection } from '@firtoz/collection-sync';
|
|
3
|
+
|
|
4
|
+
function createSyncedSqliteCollection(config, syncOptions) {
|
|
5
|
+
const options = sqliteCollectionOptions(config);
|
|
6
|
+
const { collection, bridge, setTransportSend } = createSyncedCollection(
|
|
7
|
+
options,
|
|
8
|
+
syncOptions
|
|
9
|
+
);
|
|
10
|
+
return {
|
|
11
|
+
collection,
|
|
12
|
+
bridge,
|
|
13
|
+
setTransportSend
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export { createSyncedSqliteCollection };
|
|
18
|
+
//# sourceMappingURL=chunk-7JJHY44Q.js.map
|
|
19
|
+
//# sourceMappingURL=chunk-7JJHY44Q.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/collections/synced-sqlite-collection.ts"],"names":[],"mappings":";;;AAsBO,SAAS,4BAAA,CAKf,QACA,WAAA,EAKC;AAGD,EAAA,MAAM,OAAA,GAAU,wBAAwB,MAAM,CAAA;AAC9C,EAAA,MAAM,EAAE,UAAA,EAAY,MAAA,EAAQ,gBAAA,EAAiB,GAAI,sBAAA;AAAA,IAChD,OAAA;AAAA,IACA;AAAA,GACD;AACA,EAAA,OAAO;AAAA,IACN,UAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACD;AACD","file":"chunk-7JJHY44Q.js","sourcesContent":["import {\n\tcreateSyncedCollection,\n\ttype SyncableCollectionItem,\n\ttype SyncClientBridge,\n\ttype SyncClientMessage,\n\ttype WithSyncOptions,\n} from \"@firtoz/collection-sync\";\nimport type { Collection } from \"@tanstack/db\";\nimport type { TableWithRequiredFields } from \"@firtoz/drizzle-utils\";\nimport type { InferSelectModel } from \"drizzle-orm\";\nimport type {\n\tAnyDrizzleDatabase,\n\tDrizzleSchema,\n\tDrizzleSqliteCollectionConfig,\n\tValidTableNames,\n} from \"./sqlite-collection\";\nimport { sqliteCollectionOptions } from \"./sqlite-collection\";\n\n/**\n * Like {@link createSyncedCollection} from `@firtoz/collection-sync`, but row type uses Drizzle’s\n * {@link InferSelectModel} so branded columns (e.g. ids) match `$inferSelect`, not Valibot schema output.\n */\nexport function createSyncedSqliteCollection<\n\tconst TDrizzle extends AnyDrizzleDatabase,\n\tconst TTableName extends string & ValidTableNames<DrizzleSchema<TDrizzle>>,\n\tTTable extends DrizzleSchema<TDrizzle>[TTableName] & TableWithRequiredFields,\n>(\n\tconfig: DrizzleSqliteCollectionConfig<TDrizzle, TTableName>,\n\tsyncOptions?: WithSyncOptions,\n): {\n\tcollection: Collection<InferSelectModel<TTable>>;\n\tbridge: SyncClientBridge<InferSelectModel<TTable> & SyncableCollectionItem>;\n\tsetTransportSend: (send: (msg: SyncClientMessage) => void) => void;\n} {\n\ttype TRow = InferSelectModel<TTable>;\n\ttype TBridgeItem = TRow & SyncableCollectionItem;\n\tconst options = sqliteCollectionOptions(config);\n\tconst { collection, bridge, setTransportSend } = createSyncedCollection(\n\t\toptions,\n\t\tsyncOptions,\n\t);\n\treturn {\n\t\tcollection: collection as unknown as Collection<TRow>,\n\t\tbridge: bridge as unknown as SyncClientBridge<TBridgeItem>,\n\t\tsetTransportSend,\n\t};\n}\n"]}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { useDrizzleSqliteDb } from './chunk-WFFFP6DB.js';
|
|
2
|
+
import { sqliteCollectionOptions } from './chunk-BZVMUTJ7.js';
|
|
3
|
+
import { createContext, useMemo, useCallback, useEffect } from 'react';
|
|
4
|
+
import { createCollection } from '@tanstack/db';
|
|
5
|
+
import { jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
var DrizzleSqliteContext = (
|
|
8
|
+
// biome-ignore lint/suspicious/noExplicitAny: Context needs to accept any schema type
|
|
9
|
+
createContext(null)
|
|
10
|
+
);
|
|
11
|
+
function DrizzleSqliteProvider({
|
|
12
|
+
children,
|
|
13
|
+
worker,
|
|
14
|
+
dbName,
|
|
15
|
+
schema,
|
|
16
|
+
migrations,
|
|
17
|
+
debug,
|
|
18
|
+
enableCheckpoint = false,
|
|
19
|
+
syncMode = "eager",
|
|
20
|
+
interceptor,
|
|
21
|
+
workerOpenOptions
|
|
22
|
+
}) {
|
|
23
|
+
const { drizzle, readyPromise, sqliteClient } = useDrizzleSqliteDb(
|
|
24
|
+
worker,
|
|
25
|
+
dbName,
|
|
26
|
+
schema,
|
|
27
|
+
migrations,
|
|
28
|
+
debug,
|
|
29
|
+
interceptor,
|
|
30
|
+
// Pass interceptor to log ALL Drizzle queries
|
|
31
|
+
workerOpenOptions
|
|
32
|
+
);
|
|
33
|
+
const collections = useMemo(
|
|
34
|
+
() => /* @__PURE__ */ new Map(),
|
|
35
|
+
[]
|
|
36
|
+
);
|
|
37
|
+
const getCollection = useCallback(
|
|
38
|
+
(tableName) => {
|
|
39
|
+
const cacheKey = tableName;
|
|
40
|
+
if (!collections.has(cacheKey)) {
|
|
41
|
+
const options = sqliteCollectionOptions({
|
|
42
|
+
drizzle,
|
|
43
|
+
tableName,
|
|
44
|
+
readyPromise,
|
|
45
|
+
syncMode,
|
|
46
|
+
checkpoint: enableCheckpoint && sqliteClient ? () => sqliteClient.checkpoint() : void 0,
|
|
47
|
+
interceptor,
|
|
48
|
+
debug
|
|
49
|
+
});
|
|
50
|
+
const collection = createCollection(options);
|
|
51
|
+
collections.set(cacheKey, {
|
|
52
|
+
collection,
|
|
53
|
+
refCount: 0
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return collections.get(cacheKey).collection;
|
|
57
|
+
},
|
|
58
|
+
[
|
|
59
|
+
drizzle,
|
|
60
|
+
collections,
|
|
61
|
+
schema,
|
|
62
|
+
readyPromise,
|
|
63
|
+
sqliteClient,
|
|
64
|
+
enableCheckpoint,
|
|
65
|
+
syncMode,
|
|
66
|
+
interceptor,
|
|
67
|
+
debug
|
|
68
|
+
]
|
|
69
|
+
);
|
|
70
|
+
const incrementRefCount = useCallback(
|
|
71
|
+
(tableName) => {
|
|
72
|
+
const entry = collections.get(tableName);
|
|
73
|
+
if (entry) {
|
|
74
|
+
entry.refCount++;
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
[collections]
|
|
78
|
+
);
|
|
79
|
+
const decrementRefCount = useCallback(
|
|
80
|
+
(tableName) => {
|
|
81
|
+
const entry = collections.get(tableName);
|
|
82
|
+
if (entry) {
|
|
83
|
+
entry.refCount--;
|
|
84
|
+
if (entry.refCount <= 0) {
|
|
85
|
+
collections.delete(tableName);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
[collections]
|
|
90
|
+
);
|
|
91
|
+
const contextValue = useMemo(
|
|
92
|
+
() => ({
|
|
93
|
+
drizzle,
|
|
94
|
+
readyPromise,
|
|
95
|
+
getCollection,
|
|
96
|
+
incrementRefCount,
|
|
97
|
+
decrementRefCount
|
|
98
|
+
}),
|
|
99
|
+
[
|
|
100
|
+
drizzle,
|
|
101
|
+
readyPromise,
|
|
102
|
+
getCollection,
|
|
103
|
+
incrementRefCount,
|
|
104
|
+
decrementRefCount
|
|
105
|
+
]
|
|
106
|
+
);
|
|
107
|
+
return /* @__PURE__ */ jsx(DrizzleSqliteContext.Provider, { value: contextValue, children });
|
|
108
|
+
}
|
|
109
|
+
function useSqliteCollection(context, tableName) {
|
|
110
|
+
const { collection, unsubscribe } = useMemo(() => {
|
|
111
|
+
const col = context.getCollection(tableName);
|
|
112
|
+
context.incrementRefCount(tableName);
|
|
113
|
+
return {
|
|
114
|
+
collection: col,
|
|
115
|
+
unsubscribe: () => {
|
|
116
|
+
context.decrementRefCount(tableName);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
}, [context, tableName]);
|
|
120
|
+
useEffect(() => {
|
|
121
|
+
return () => {
|
|
122
|
+
unsubscribe();
|
|
123
|
+
};
|
|
124
|
+
}, [unsubscribe]);
|
|
125
|
+
return collection;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export { DrizzleSqliteContext, DrizzleSqliteProvider, useSqliteCollection };
|
|
129
|
+
//# sourceMappingURL=chunk-AEYHRJVN.js.map
|
|
130
|
+
//# sourceMappingURL=chunk-AEYHRJVN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/context/DrizzleSqliteProvider.tsx"],"names":[],"mappings":"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","file":"chunk-AEYHRJVN.js","sourcesContent":["import type { PropsWithChildren } from \"react\";\nimport { createContext, useMemo, useCallback, useEffect } from \"react\";\nimport type { SqliteRemoteDatabase } from \"drizzle-orm/sqlite-proxy\";\nimport {\n\tcreateCollection,\n\ttype Collection,\n\ttype InferSchemaOutput,\n\ttype UtilsRecord,\n} from \"@tanstack/db\";\nimport {\n\ttype AnyDrizzleDatabase,\n\ttype ValidTableNames,\n\ttype DrizzleSchema,\n\tsqliteCollectionOptions,\n\ttype SQLInterceptor,\n} from \"../collections/sqlite-collection\";\nimport { useDrizzleSqliteDb } from \"../hooks/useDrizzleSqliteDb\";\nimport type { DurableSqliteMigrationConfig } from \"../migration/migrator\";\nimport type { SqliteWasmWorkerOpenOptions } from \"../worker/sqlite-open-options\";\nimport type {\n\tIdOf,\n\tGetTableFromSchema,\n\tInferCollectionFromTable,\n} from \"@firtoz/drizzle-utils\";\n\ninterface CollectionCacheEntry {\n\t// biome-ignore lint/suspicious/noExplicitAny: Cache needs to store collections of various types\n\tcollection: Collection<any, string>;\n\trefCount: number;\n}\n\ntype SqliteCollection<\n\tTSchema extends Record<string, unknown>,\n\tTTableName extends string & ValidTableNames<TSchema>,\n> = Collection<\n\tInferSchemaOutput<GetTableFromSchema<TSchema, TTableName>[\"$inferSelect\"]>,\n\tIdOf<GetTableFromSchema<TSchema, TTableName>>,\n\t// biome-ignore lint/suspicious/noExplicitAny: We need to use any here to match the Collection type\n\tany,\n\t// biome-ignore lint/suspicious/noExplicitAny: We need to use any here to match the Collection type\n\tany,\n\tOmit<GetTableFromSchema<TSchema, TTableName>[\"$inferInsert\"], \"id\"> & {\n\t\tid?: IdOf<GetTableFromSchema<TSchema, TTableName>>;\n\t}\n>;\n\nexport type DrizzleSqliteContextValue<TSchema extends Record<string, unknown>> =\n\t{\n\t\tdrizzle: SqliteRemoteDatabase<TSchema>;\n\t\treadyPromise: Promise<void>;\n\t\tgetCollection: <TTableName extends string & ValidTableNames<TSchema>>(\n\t\t\ttableName: TTableName,\n\t\t) => SqliteCollection<TSchema, TTableName>;\n\t\tincrementRefCount: (tableName: string) => void;\n\t\tdecrementRefCount: (tableName: string) => void;\n\t};\n\nexport const DrizzleSqliteContext =\n\t// biome-ignore lint/suspicious/noExplicitAny: Context needs to accept any schema type\n\tcreateContext<DrizzleSqliteContextValue<any> | null>(null);\n\ntype DrizzleSqliteProviderProps<TSchema extends Record<string, unknown>> =\n\tPropsWithChildren<{\n\t\tworker: new () => Worker;\n\t\tdbName: string;\n\t\tschema: TSchema;\n\t\tmigrations: DurableSqliteMigrationConfig;\n\t\tdebug?: boolean;\n\t\tenableCheckpoint?: boolean;\n\t\t/**\n\t\t * Sync mode: 'eager' (immediate) or 'on-demand' (lazy)\n\t\t */\n\t\tsyncMode?: \"eager\" | \"on-demand\";\n\t\t/**\n\t\t * Optional interceptor for tracking SQLite operations (for testing/debugging)\n\t\t */\n\t\tinterceptor?: SQLInterceptor;\n\t\t/**\n\t\t * Worker DB pragmas on first open of `dbName` this session (see `useDrizzleSqliteDb`).\n\t\t */\n\t\tworkerOpenOptions?: SqliteWasmWorkerOpenOptions;\n\t}>;\n\nexport function DrizzleSqliteProvider<TSchema extends Record<string, unknown>>({\n\tchildren,\n\tworker,\n\tdbName,\n\tschema,\n\tmigrations,\n\tdebug,\n\tenableCheckpoint = false,\n\tsyncMode = \"eager\",\n\tinterceptor,\n\tworkerOpenOptions,\n}: DrizzleSqliteProviderProps<TSchema>) {\n\tconst { drizzle, readyPromise, sqliteClient } = useDrizzleSqliteDb(\n\t\tworker,\n\t\tdbName,\n\t\tschema,\n\t\tmigrations,\n\t\tdebug,\n\t\tinterceptor, // Pass interceptor to log ALL Drizzle queries\n\t\tworkerOpenOptions,\n\t);\n\n\t// Collection cache with ref counting\n\tconst collections = useMemo<Map<string, CollectionCacheEntry>>(\n\t\t() => new Map(),\n\t\t[],\n\t);\n\n\tconst getCollection = useCallback(\n\t\t<TTableName extends string & ValidTableNames<TSchema>>(\n\t\t\ttableName: TTableName,\n\t\t): SqliteCollection<TSchema, TTableName> => {\n\t\t\tconst cacheKey = tableName;\n\n\t\t\t// Check if collection already exists in cache\n\t\t\tif (!collections.has(cacheKey)) {\n\t\t\t\t// Create new collection and cache it with ref count 0\n\t\t\t\tconst options = sqliteCollectionOptions({\n\t\t\t\t\tdrizzle,\n\t\t\t\t\ttableName: tableName as string &\n\t\t\t\t\t\tValidTableNames<DrizzleSchema<AnyDrizzleDatabase>>,\n\t\t\t\t\treadyPromise,\n\t\t\t\t\tsyncMode,\n\t\t\t\t\tcheckpoint:\n\t\t\t\t\t\tenableCheckpoint && sqliteClient\n\t\t\t\t\t\t\t? () => sqliteClient.checkpoint()\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\tinterceptor,\n\t\t\t\t\tdebug,\n\t\t\t\t});\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: Table type degenerates through AnyDrizzleDatabase; collection is re-typed on cache retrieval\n\t\t\t\tconst collection = createCollection(options as any) as Collection<\n\t\t\t\t\tRecord<string, unknown>,\n\t\t\t\t\tstring,\n\t\t\t\t\tUtilsRecord\n\t\t\t\t>;\n\t\t\t\tcollections.set(cacheKey, {\n\t\t\t\t\tcollection,\n\t\t\t\t\trefCount: 0,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// biome-ignore lint/style/noNonNullAssertion: We just ensured the collection exists\n\t\t\treturn collections.get(cacheKey)!\n\t\t\t\t.collection as unknown as SqliteCollection<TSchema, TTableName>;\n\t\t},\n\t\t[\n\t\t\tdrizzle,\n\t\t\tcollections,\n\t\t\tschema,\n\t\t\treadyPromise,\n\t\t\tsqliteClient,\n\t\t\tenableCheckpoint,\n\t\t\tsyncMode,\n\t\t\tinterceptor,\n\t\t\tdebug,\n\t\t],\n\t);\n\n\tconst incrementRefCount: DrizzleSqliteContextValue<TSchema>[\"incrementRefCount\"] =\n\t\tuseCallback(\n\t\t\t(tableName: string) => {\n\t\t\t\tconst entry = collections.get(tableName);\n\t\t\t\tif (entry) {\n\t\t\t\t\tentry.refCount++;\n\t\t\t\t}\n\t\t\t},\n\t\t\t[collections],\n\t\t);\n\n\tconst decrementRefCount: DrizzleSqliteContextValue<TSchema>[\"decrementRefCount\"] =\n\t\tuseCallback(\n\t\t\t(tableName: string) => {\n\t\t\t\tconst entry = collections.get(tableName);\n\t\t\t\tif (entry) {\n\t\t\t\t\tentry.refCount--;\n\n\t\t\t\t\t// If ref count reaches 0, remove from cache\n\t\t\t\t\tif (entry.refCount <= 0) {\n\t\t\t\t\t\tcollections.delete(tableName);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t[collections],\n\t\t);\n\n\tconst contextValue: DrizzleSqliteContextValue<TSchema> = useMemo(\n\t\t() => ({\n\t\t\tdrizzle,\n\t\t\treadyPromise,\n\t\t\tgetCollection,\n\t\t\tincrementRefCount,\n\t\t\tdecrementRefCount,\n\t\t}),\n\t\t[\n\t\t\tdrizzle,\n\t\t\treadyPromise,\n\t\t\tgetCollection,\n\t\t\tincrementRefCount,\n\t\t\tdecrementRefCount,\n\t\t],\n\t);\n\n\treturn (\n\t\t<DrizzleSqliteContext.Provider value={contextValue}>\n\t\t\t{children}\n\t\t</DrizzleSqliteContext.Provider>\n\t);\n}\n\n// Hook that components use to get a collection with automatic ref counting\nexport function useSqliteCollection<\n\tTSchema extends Record<string, unknown>,\n\tTTableName extends string & ValidTableNames<TSchema>,\n>(\n\tcontext: DrizzleSqliteContextValue<TSchema>,\n\ttableName: TTableName,\n): InferCollectionFromTable<GetTableFromSchema<TSchema, TTableName>> {\n\tconst { collection, unsubscribe } = useMemo(() => {\n\t\t// Get the collection and increment ref count\n\t\tconst col = context.getCollection(tableName);\n\t\tcontext.incrementRefCount(tableName);\n\n\t\t// Return collection and unsubscribe function\n\t\treturn {\n\t\t\tcollection: col,\n\t\t\tunsubscribe: () => {\n\t\t\t\tcontext.decrementRefCount(tableName);\n\t\t\t},\n\t\t};\n\t}, [context, tableName]);\n\n\t// Cleanup on unmount\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tunsubscribe();\n\t\t};\n\t}, [unsubscribe]);\n\n\treturn collection as unknown as InferCollectionFromTable<\n\t\tGetTableFromSchema<TSchema, TTableName>\n\t>;\n}\n"]}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { sqliteWorkerServerMessage, SqliteWorkerClientMessageSchema, StartRequestIdSchema, RemoteCallbackIdSchema, CheckpointIdSchema } from './chunk-GVUNHU6J.js';
|
|
2
|
+
import { exhaustiveGuard } from '@firtoz/maybe-error';
|
|
3
|
+
import { WorkerClient } from '@firtoz/worker-helper/WorkerClient';
|
|
4
|
+
|
|
5
|
+
var DbInstance = class {
|
|
6
|
+
constructor(manager, dbName, debug = false) {
|
|
7
|
+
this.manager = manager;
|
|
8
|
+
this.dbName = dbName;
|
|
9
|
+
this.debug = debug;
|
|
10
|
+
this.dbId = null;
|
|
11
|
+
this.startedCallbacks = [];
|
|
12
|
+
this.isStarted = false;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Internal method called by manager when database is started
|
|
16
|
+
*/
|
|
17
|
+
_setStarted(dbId) {
|
|
18
|
+
this.dbId = dbId;
|
|
19
|
+
this.isStarted = true;
|
|
20
|
+
for (const callback of this.startedCallbacks) {
|
|
21
|
+
callback();
|
|
22
|
+
}
|
|
23
|
+
this.startedCallbacks = [];
|
|
24
|
+
}
|
|
25
|
+
performRemoteCallback(data, resolve, reject) {
|
|
26
|
+
if (!this.dbId) {
|
|
27
|
+
reject(
|
|
28
|
+
new Error(`Database not started - dbId is null for ${this.dbName}`)
|
|
29
|
+
);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (this.debug) {
|
|
33
|
+
console.log(
|
|
34
|
+
`[${(/* @__PURE__ */ new Date()).toISOString()}] [DbInstance:${this.dbName}] performing remote callback`,
|
|
35
|
+
data
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
this.manager.performRemoteCallback(this.dbId, data, resolve, reject);
|
|
39
|
+
}
|
|
40
|
+
checkpoint() {
|
|
41
|
+
return new Promise((resolve, reject) => {
|
|
42
|
+
if (!this.dbId) {
|
|
43
|
+
reject(
|
|
44
|
+
new Error(`Database not started - dbId is null for ${this.dbName}`)
|
|
45
|
+
);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (this.debug) {
|
|
49
|
+
console.log(
|
|
50
|
+
`[${(/* @__PURE__ */ new Date()).toISOString()}] [DbInstance:${this.dbName}] checkpointing database`
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
this.manager.checkpoint(this.dbId, resolve, reject);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
onStarted(callback) {
|
|
57
|
+
if (this.isStarted) {
|
|
58
|
+
callback();
|
|
59
|
+
} else {
|
|
60
|
+
this.startedCallbacks.push(callback);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
terminate() {
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
var SqliteWorkerManager = class extends WorkerClient {
|
|
67
|
+
constructor(worker, debug = false) {
|
|
68
|
+
super({
|
|
69
|
+
worker,
|
|
70
|
+
clientSchema: SqliteWorkerClientMessageSchema,
|
|
71
|
+
serverSchema: sqliteWorkerServerMessage,
|
|
72
|
+
onMessage: (message) => {
|
|
73
|
+
this.onMessage(message);
|
|
74
|
+
},
|
|
75
|
+
onValidationError: (error, rawMessage) => {
|
|
76
|
+
console.error(error, rawMessage);
|
|
77
|
+
if (!this.isReady && this.readyReject) {
|
|
78
|
+
this.readyReject(new Error(`Validation error: ${error.message}`));
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
onError: (event) => {
|
|
82
|
+
console.error(event);
|
|
83
|
+
if (!this.isReady && this.readyReject) {
|
|
84
|
+
this.readyReject(
|
|
85
|
+
new Error(`Worker error: ${event.message || "Unknown error"}`)
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
this.debug = debug;
|
|
91
|
+
this.remoteCallbacks = /* @__PURE__ */ new Map();
|
|
92
|
+
this.checkpointCallbacks = /* @__PURE__ */ new Map();
|
|
93
|
+
this.isReady = false;
|
|
94
|
+
this.dbInstances = /* @__PURE__ */ new Map();
|
|
95
|
+
this.pendingStarts = /* @__PURE__ */ new Map();
|
|
96
|
+
this.readyPromise = new Promise((resolve, reject) => {
|
|
97
|
+
this.readyResolve = resolve;
|
|
98
|
+
this.readyReject = reject;
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Promise that resolves when the worker sends its first Ready message
|
|
103
|
+
*/
|
|
104
|
+
get ready() {
|
|
105
|
+
return this.readyPromise;
|
|
106
|
+
}
|
|
107
|
+
onMessage(message) {
|
|
108
|
+
const { type } = message;
|
|
109
|
+
switch (type) {
|
|
110
|
+
case "ready" /* Ready */:
|
|
111
|
+
{
|
|
112
|
+
this.isReady = true;
|
|
113
|
+
this.readyResolve?.();
|
|
114
|
+
if (this.debug) {
|
|
115
|
+
console.log("[SqliteWorkerManager] ready for databases");
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
break;
|
|
119
|
+
case "started" /* Started */:
|
|
120
|
+
{
|
|
121
|
+
const pending = this.pendingStarts.get(message.requestId);
|
|
122
|
+
if (pending) {
|
|
123
|
+
pending.instance._setStarted(message.dbId);
|
|
124
|
+
this.pendingStarts.delete(message.requestId);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
break;
|
|
128
|
+
case "remote-callback-response" /* RemoteCallbackResponse */:
|
|
129
|
+
{
|
|
130
|
+
const { id, rows } = message;
|
|
131
|
+
const remoteCallback = this.remoteCallbacks.get(id);
|
|
132
|
+
if (remoteCallback) {
|
|
133
|
+
remoteCallback.resolve({ rows });
|
|
134
|
+
this.remoteCallbacks.delete(id);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
break;
|
|
138
|
+
case "remote-callback-error" /* RemoteCallbackError */:
|
|
139
|
+
{
|
|
140
|
+
const { id, error } = message;
|
|
141
|
+
const remoteCallback = this.remoteCallbacks.get(id);
|
|
142
|
+
if (remoteCallback) {
|
|
143
|
+
remoteCallback.reject(new Error(error));
|
|
144
|
+
this.remoteCallbacks.delete(id);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
break;
|
|
148
|
+
case "checkpoint-complete" /* CheckpointComplete */:
|
|
149
|
+
{
|
|
150
|
+
const { id } = message;
|
|
151
|
+
const checkpointCallback = this.checkpointCallbacks.get(id);
|
|
152
|
+
if (checkpointCallback) {
|
|
153
|
+
checkpointCallback.resolve();
|
|
154
|
+
this.checkpointCallbacks.delete(id);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
break;
|
|
158
|
+
case "checkpoint-error" /* CheckpointError */:
|
|
159
|
+
{
|
|
160
|
+
const { id, error } = message;
|
|
161
|
+
const checkpointCallback = this.checkpointCallbacks.get(id);
|
|
162
|
+
if (checkpointCallback) {
|
|
163
|
+
checkpointCallback.reject(new Error(error));
|
|
164
|
+
this.checkpointCallbacks.delete(id);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
break;
|
|
168
|
+
default:
|
|
169
|
+
return exhaustiveGuard(type);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Get or create a database instance
|
|
174
|
+
*/
|
|
175
|
+
async getDbInstance(dbName, openOptions) {
|
|
176
|
+
let instance = this.dbInstances.get(dbName);
|
|
177
|
+
if (instance) {
|
|
178
|
+
return instance;
|
|
179
|
+
}
|
|
180
|
+
instance = this.dbInstances.get(dbName);
|
|
181
|
+
if (instance) {
|
|
182
|
+
return instance;
|
|
183
|
+
}
|
|
184
|
+
instance = new DbInstance(this, dbName, this.debug);
|
|
185
|
+
this.dbInstances.set(dbName, instance);
|
|
186
|
+
const startRequestId = StartRequestIdSchema.parse(crypto.randomUUID());
|
|
187
|
+
this.pendingStarts.set(startRequestId, { dbName, instance });
|
|
188
|
+
this.send({
|
|
189
|
+
type: "start" /* Start */,
|
|
190
|
+
requestId: startRequestId,
|
|
191
|
+
dbName,
|
|
192
|
+
...openOptions !== void 0 ? { openOptions } : {}
|
|
193
|
+
});
|
|
194
|
+
return instance;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Internal method for db instances to perform remote callbacks
|
|
198
|
+
*/
|
|
199
|
+
performRemoteCallback(dbId, data, resolve, reject) {
|
|
200
|
+
if (this.debug) {
|
|
201
|
+
console.log(
|
|
202
|
+
`[${(/* @__PURE__ */ new Date()).toISOString()}] [SqliteWorkerManager] performing remote callback for dbId: ${dbId}`,
|
|
203
|
+
data
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
const id = RemoteCallbackIdSchema.parse(crypto.randomUUID());
|
|
207
|
+
this.remoteCallbacks.set(id, { resolve, reject });
|
|
208
|
+
this.send({
|
|
209
|
+
type: "remote-callback-request" /* RemoteCallbackRequest */,
|
|
210
|
+
id,
|
|
211
|
+
dbId,
|
|
212
|
+
sql: data.sql,
|
|
213
|
+
params: data.params,
|
|
214
|
+
method: data.method
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Internal method for db instances to checkpoint the database
|
|
219
|
+
*/
|
|
220
|
+
checkpoint(dbId, resolve, reject) {
|
|
221
|
+
if (this.debug) {
|
|
222
|
+
console.log(
|
|
223
|
+
`[${(/* @__PURE__ */ new Date()).toISOString()}] [SqliteWorkerManager] checkpointing database for dbId: ${dbId}`
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
const id = CheckpointIdSchema.parse(crypto.randomUUID());
|
|
227
|
+
this.checkpointCallbacks.set(id, { resolve, reject });
|
|
228
|
+
this.send({
|
|
229
|
+
type: "checkpoint" /* Checkpoint */,
|
|
230
|
+
id,
|
|
231
|
+
dbId
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
export { DbInstance, SqliteWorkerManager };
|
|
237
|
+
//# sourceMappingURL=chunk-AGMKOHXO.js.map
|
|
238
|
+
//# sourceMappingURL=chunk-AGMKOHXO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/worker/manager.ts"],"names":[],"mappings":"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","file":"chunk-AGMKOHXO.js","sourcesContent":["import { exhaustiveGuard } from \"@firtoz/maybe-error\";\nimport { WorkerClient } from \"@firtoz/worker-helper/WorkerClient\";\nimport type { SqliteWasmWorkerOpenOptions } from \"./sqlite-open-options\";\nimport {\n\ttype SqliteWorkerClientMessage,\n\ttype SqliteWorkerServerMessage,\n\ttype RemoteCallbackId,\n\ttype DbId,\n\ttype StartRequestId,\n\ttype CheckpointId,\n\tSqliteWorkerClientMessageSchema,\n\tsqliteWorkerServerMessage,\n\tSqliteWorkerServerMessageType,\n\tSqliteWorkerClientMessageType,\n\ttype SqliteWorkerRemoteCallbackClientMessage,\n\tRemoteCallbackIdSchema,\n\tStartRequestIdSchema,\n\tCheckpointIdSchema,\n} from \"./schema\";\n\nexport interface ISqliteWorkerClient {\n\tperformRemoteCallback: (\n\t\tdata: Omit<SqliteWorkerRemoteCallbackClientMessage, \"type\" | \"id\" | \"dbId\">,\n\t\tresolve: (value: { rows: unknown[] }) => void,\n\t\treject: (error: Error) => void,\n\t) => void;\n\tcheckpoint: () => Promise<void>;\n\tonStarted: (callback: () => void) => void;\n\tterminate: () => void;\n}\n\n/**\n * Per-database instance that can perform operations on a specific database\n */\nexport class DbInstance implements ISqliteWorkerClient {\n\tprivate dbId: DbId | null = null;\n\tprivate startedCallbacks: Array<() => void> = [];\n\tprivate isStarted = false;\n\n\tconstructor(\n\t\tprivate readonly manager: SqliteWorkerManager,\n\t\tpublic readonly dbName: string,\n\t\tprivate readonly debug: boolean = false,\n\t) {}\n\n\t/**\n\t * Internal method called by manager when database is started\n\t */\n\t_setStarted(dbId: DbId) {\n\t\tthis.dbId = dbId;\n\t\tthis.isStarted = true;\n\n\t\t// Call all pending callbacks\n\t\tfor (const callback of this.startedCallbacks) {\n\t\t\tcallback();\n\t\t}\n\t\tthis.startedCallbacks = [];\n\t}\n\n\tpublic performRemoteCallback(\n\t\tdata: Omit<SqliteWorkerRemoteCallbackClientMessage, \"type\" | \"id\" | \"dbId\">,\n\t\tresolve: (value: { rows: unknown[] }) => void,\n\t\treject: (error: Error) => void,\n\t) {\n\t\tif (!this.dbId) {\n\t\t\treject(\n\t\t\t\tnew Error(`Database not started - dbId is null for ${this.dbName}`),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.debug) {\n\t\t\tconsole.log(\n\t\t\t\t`[${new Date().toISOString()}] [DbInstance:${this.dbName}] performing remote callback`,\n\t\t\t\tdata,\n\t\t\t);\n\t\t}\n\n\t\tthis.manager.performRemoteCallback(this.dbId, data, resolve, reject);\n\t}\n\n\tpublic checkpoint(): Promise<void> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tif (!this.dbId) {\n\t\t\t\treject(\n\t\t\t\t\tnew Error(`Database not started - dbId is null for ${this.dbName}`),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (this.debug) {\n\t\t\t\tconsole.log(\n\t\t\t\t\t`[${new Date().toISOString()}] [DbInstance:${this.dbName}] checkpointing database`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.manager.checkpoint(this.dbId, resolve, reject);\n\t\t});\n\t}\n\n\tpublic onStarted(callback: () => void) {\n\t\tif (this.isStarted) {\n\t\t\t// Already started, call immediately\n\t\t\tcallback();\n\t\t} else {\n\t\t\tthis.startedCallbacks.push(callback);\n\t\t}\n\t}\n\n\tpublic terminate() {\n\t\t// Per-db instances don't terminate the worker\n\t\t// That's managed by the SqliteWorkerManager\n\t}\n}\n\n/**\n * Main worker manager that can create multiple database instances\n */\nexport class SqliteWorkerManager extends WorkerClient<\n\tSqliteWorkerClientMessage,\n\tSqliteWorkerServerMessage\n> {\n\tprivate readonly remoteCallbacks = new Map<\n\t\tRemoteCallbackId,\n\t\t{\n\t\t\tresolve: (value: { rows: unknown[] }) => void;\n\t\t\treject: (error: Error) => void;\n\t\t}\n\t>();\n\n\tprivate readonly checkpointCallbacks = new Map<\n\t\tCheckpointId,\n\t\t{\n\t\t\tresolve: () => void;\n\t\t\treject: (error: Error) => void;\n\t\t}\n\t>();\n\n\tprivate readyResolve?: () => void;\n\tprivate readyReject?: (error: Error) => void;\n\tprivate readonly readyPromise: Promise<void>;\n\tprivate isReady = false;\n\n\tprivate readonly dbInstances = new Map<string, DbInstance>();\n\tprivate readonly pendingStarts = new Map<\n\t\tStartRequestId,\n\t\t{ dbName: string; instance: DbInstance }\n\t>();\n\n\tconstructor(\n\t\tworker: Worker,\n\t\tprivate readonly debug: boolean = false,\n\t) {\n\t\tsuper({\n\t\t\tworker,\n\t\t\tclientSchema: SqliteWorkerClientMessageSchema,\n\t\t\tserverSchema: sqliteWorkerServerMessage,\n\t\t\tonMessage: (message) => {\n\t\t\t\tthis.onMessage(message);\n\t\t\t},\n\t\t\tonValidationError: (error, rawMessage) => {\n\t\t\t\tconsole.error(error, rawMessage);\n\t\t\t\t// Reject promises if we get validation errors before being ready\n\t\t\t\tif (!this.isReady && this.readyReject) {\n\t\t\t\t\tthis.readyReject(new Error(`Validation error: ${error.message}`));\n\t\t\t\t}\n\t\t\t},\n\t\t\tonError: (event) => {\n\t\t\t\tconsole.error(event);\n\t\t\t\t// Reject promises if worker errors before being ready\n\t\t\t\tif (!this.isReady && this.readyReject) {\n\t\t\t\t\tthis.readyReject(\n\t\t\t\t\t\tnew Error(`Worker error: ${event.message || \"Unknown error\"}`),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\n\t\tthis.readyPromise = new Promise((resolve, reject) => {\n\t\t\tthis.readyResolve = resolve;\n\t\t\tthis.readyReject = reject;\n\t\t});\n\t}\n\n\t/**\n\t * Promise that resolves when the worker sends its first Ready message\n\t */\n\tpublic get ready(): Promise<void> {\n\t\treturn this.readyPromise;\n\t}\n\n\tprivate onMessage(message: SqliteWorkerServerMessage) {\n\t\tconst { type } = message;\n\t\tswitch (type) {\n\t\t\tcase SqliteWorkerServerMessageType.Ready:\n\t\t\t\t{\n\t\t\t\t\tthis.isReady = true;\n\t\t\t\t\tthis.readyResolve?.();\n\t\t\t\t\tif (this.debug) {\n\t\t\t\t\t\tconsole.log(\"[SqliteWorkerManager] ready for databases\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase SqliteWorkerServerMessageType.Started:\n\t\t\t\t{\n\t\t\t\t\tconst pending = this.pendingStarts.get(message.requestId);\n\t\t\t\t\tif (pending) {\n\t\t\t\t\t\tpending.instance._setStarted(message.dbId);\n\t\t\t\t\t\tthis.pendingStarts.delete(message.requestId);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase SqliteWorkerServerMessageType.RemoteCallbackResponse:\n\t\t\t\t{\n\t\t\t\t\tconst { id, rows } = message;\n\t\t\t\t\tconst remoteCallback = this.remoteCallbacks.get(id);\n\t\t\t\t\tif (remoteCallback) {\n\t\t\t\t\t\tremoteCallback.resolve({ rows });\n\t\t\t\t\t\tthis.remoteCallbacks.delete(id);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase SqliteWorkerServerMessageType.RemoteCallbackError:\n\t\t\t\t{\n\t\t\t\t\tconst { id, error } = message;\n\t\t\t\t\tconst remoteCallback = this.remoteCallbacks.get(id);\n\t\t\t\t\tif (remoteCallback) {\n\t\t\t\t\t\tremoteCallback.reject(new Error(error));\n\t\t\t\t\t\tthis.remoteCallbacks.delete(id);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase SqliteWorkerServerMessageType.CheckpointComplete:\n\t\t\t\t{\n\t\t\t\t\tconst { id } = message;\n\t\t\t\t\tconst checkpointCallback = this.checkpointCallbacks.get(id);\n\t\t\t\t\tif (checkpointCallback) {\n\t\t\t\t\t\tcheckpointCallback.resolve();\n\t\t\t\t\t\tthis.checkpointCallbacks.delete(id);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase SqliteWorkerServerMessageType.CheckpointError:\n\t\t\t\t{\n\t\t\t\t\tconst { id, error } = message;\n\t\t\t\t\tconst checkpointCallback = this.checkpointCallbacks.get(id);\n\t\t\t\t\tif (checkpointCallback) {\n\t\t\t\t\t\tcheckpointCallback.reject(new Error(error));\n\t\t\t\t\t\tthis.checkpointCallbacks.delete(id);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn exhaustiveGuard(type);\n\t\t}\n\t}\n\n\t/**\n\t * Get or create a database instance\n\t */\n\tpublic async getDbInstance(\n\t\tdbName: string,\n\t\topenOptions?: SqliteWasmWorkerOpenOptions,\n\t): Promise<DbInstance> {\n\t\t// Check if instance already exists\n\t\tlet instance = this.dbInstances.get(dbName);\n\t\tif (instance) {\n\t\t\treturn instance;\n\t\t}\n\n\t\t// Check again after waiting (another call might have created it)\n\t\tinstance = this.dbInstances.get(dbName);\n\t\tif (instance) {\n\t\t\treturn instance;\n\t\t}\n\n\t\t// Create new instance\n\t\tinstance = new DbInstance(this, dbName, this.debug);\n\t\tthis.dbInstances.set(dbName, instance);\n\n\t\t// Start the database\n\n\t\tconst startRequestId = StartRequestIdSchema.parse(crypto.randomUUID());\n\t\tthis.pendingStarts.set(startRequestId, { dbName, instance });\n\n\t\tthis.send({\n\t\t\ttype: SqliteWorkerClientMessageType.Start,\n\t\t\trequestId: startRequestId,\n\t\t\tdbName: dbName,\n\t\t\t...(openOptions !== undefined ? { openOptions } : {}),\n\t\t});\n\n\t\treturn instance;\n\t}\n\n\t/**\n\t * Internal method for db instances to perform remote callbacks\n\t */\n\tpublic performRemoteCallback(\n\t\tdbId: DbId,\n\t\tdata: Omit<SqliteWorkerRemoteCallbackClientMessage, \"type\" | \"id\" | \"dbId\">,\n\t\tresolve: (value: { rows: unknown[] }) => void,\n\t\treject: (error: Error) => void,\n\t) {\n\t\tif (this.debug) {\n\t\t\tconsole.log(\n\t\t\t\t`[${new Date().toISOString()}] [SqliteWorkerManager] performing remote callback for dbId: ${dbId}`,\n\t\t\t\tdata,\n\t\t\t);\n\t\t}\n\t\tconst id = RemoteCallbackIdSchema.parse(crypto.randomUUID());\n\t\tthis.remoteCallbacks.set(id, { resolve, reject });\n\t\tthis.send({\n\t\t\ttype: SqliteWorkerClientMessageType.RemoteCallbackRequest,\n\t\t\tid,\n\t\t\tdbId,\n\t\t\tsql: data.sql,\n\t\t\tparams: data.params,\n\t\t\tmethod: data.method,\n\t\t});\n\t}\n\n\t/**\n\t * Internal method for db instances to checkpoint the database\n\t */\n\tpublic checkpoint(\n\t\tdbId: DbId,\n\t\tresolve: () => void,\n\t\treject: (error: Error) => void,\n\t) {\n\t\tif (this.debug) {\n\t\t\tconsole.log(\n\t\t\t\t`[${new Date().toISOString()}] [SqliteWorkerManager] checkpointing database for dbId: ${dbId}`,\n\t\t\t);\n\t\t}\n\t\tconst id = CheckpointIdSchema.parse(crypto.randomUUID());\n\t\tthis.checkpointCallbacks.set(id, { resolve, reject });\n\t\tthis.send({\n\t\t\ttype: SqliteWorkerClientMessageType.Checkpoint,\n\t\t\tid,\n\t\t\tdbId,\n\t\t});\n\t}\n}\n"]}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { fail, success, exhaustiveGuard } from '@firtoz/maybe-error';
|
|
2
|
+
|
|
3
|
+
// src/drizzle/handle-callback.ts
|
|
4
|
+
var handleRemoteCallback = async ({
|
|
5
|
+
sqliteDb,
|
|
6
|
+
sql,
|
|
7
|
+
params,
|
|
8
|
+
method,
|
|
9
|
+
debug: _debug = false
|
|
10
|
+
}) => {
|
|
11
|
+
switch (method) {
|
|
12
|
+
case "run": {
|
|
13
|
+
try {
|
|
14
|
+
sqliteDb.exec({
|
|
15
|
+
sql,
|
|
16
|
+
bind: params,
|
|
17
|
+
callback: () => {
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
return success({ rows: [] });
|
|
21
|
+
} catch (e) {
|
|
22
|
+
const errorMsg = e instanceof Error ? e.message : String(e);
|
|
23
|
+
console.error("Error executing run query:", errorMsg);
|
|
24
|
+
return fail(errorMsg);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
case "get": {
|
|
28
|
+
const columnNames = [];
|
|
29
|
+
let rowData = [];
|
|
30
|
+
let callbackReceived = false;
|
|
31
|
+
try {
|
|
32
|
+
sqliteDb.exec({
|
|
33
|
+
sql,
|
|
34
|
+
bind: params,
|
|
35
|
+
columnNames,
|
|
36
|
+
callback: (row) => {
|
|
37
|
+
callbackReceived = true;
|
|
38
|
+
if (Array.isArray(row)) {
|
|
39
|
+
rowData = row;
|
|
40
|
+
} else {
|
|
41
|
+
rowData = columnNames.map((col) => row[col]);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
} catch (e) {
|
|
46
|
+
const errorMsg = e instanceof Error ? e.message : String(e);
|
|
47
|
+
console.error("Error getting row data:", errorMsg);
|
|
48
|
+
return fail(errorMsg);
|
|
49
|
+
}
|
|
50
|
+
if (!callbackReceived) {
|
|
51
|
+
const errorMsg = "No callback received for get method";
|
|
52
|
+
console.error(errorMsg);
|
|
53
|
+
return fail(errorMsg);
|
|
54
|
+
}
|
|
55
|
+
return success({ rows: rowData });
|
|
56
|
+
}
|
|
57
|
+
case "all":
|
|
58
|
+
case "values": {
|
|
59
|
+
const columnNames = [];
|
|
60
|
+
const rowsData = [];
|
|
61
|
+
try {
|
|
62
|
+
sqliteDb.exec({
|
|
63
|
+
sql,
|
|
64
|
+
bind: params,
|
|
65
|
+
columnNames,
|
|
66
|
+
callback: (row) => {
|
|
67
|
+
if (Array.isArray(row)) {
|
|
68
|
+
rowsData.push(row);
|
|
69
|
+
} else {
|
|
70
|
+
rowsData.push(columnNames.map((col) => row[col]));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
} catch (e) {
|
|
75
|
+
const errorMsg = e instanceof Error ? e.message : String(e);
|
|
76
|
+
console.error("Error getting all/values data:", errorMsg);
|
|
77
|
+
return fail(errorMsg);
|
|
78
|
+
}
|
|
79
|
+
return success({ rows: rowsData });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return exhaustiveGuard(method);
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export { handleRemoteCallback };
|
|
86
|
+
//# sourceMappingURL=chunk-BJDPMGFF.js.map
|
|
87
|
+
//# sourceMappingURL=chunk-BJDPMGFF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/drizzle/handle-callback.ts"],"names":[],"mappings":"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","file":"chunk-BJDPMGFF.js","sourcesContent":["import {\n\texhaustiveGuard,\n\tfail,\n\tsuccess,\n\ttype MaybeError,\n} from \"@firtoz/maybe-error\";\nimport type { Database } from \"../types\";\n\nexport const handleRemoteCallback = async ({\n\tsqliteDb,\n\tsql,\n\tparams,\n\tmethod,\n\tdebug: _debug = false,\n}: {\n\tsqliteDb: Database;\n\tsql: string;\n\t// biome-ignore lint/suspicious/noExplicitAny: This is what drizzle-orm expects.\n\tparams: any[];\n\tmethod: \"run\" | \"all\" | \"values\" | \"get\";\n\tdebug?: boolean;\n}): Promise<MaybeError<{ rows: unknown[] }, string>> => {\n\tswitch (method) {\n\t\tcase \"run\": {\n\t\t\t// For INSERT, UPDATE, DELETE operations\n\t\t\ttry {\n\t\t\t\tsqliteDb.exec({\n\t\t\t\t\tsql,\n\t\t\t\t\tbind: params,\n\t\t\t\t\tcallback: () => {},\n\t\t\t\t});\n\n\t\t\t\treturn success({ rows: [] });\n\t\t\t} catch (e: unknown) {\n\t\t\t\tconst errorMsg = e instanceof Error ? e.message : String(e);\n\t\t\t\tconsole.error(\"Error executing run query:\", errorMsg);\n\t\t\t\treturn fail(errorMsg);\n\t\t\t}\n\t\t}\n\t\tcase \"get\": {\n\t\t\t// For getting a single row\n\t\t\tconst columnNames: string[] = [];\n\t\t\tlet rowData: unknown[] = [];\n\t\t\tlet callbackReceived = false;\n\n\t\t\ttry {\n\t\t\t\t// Get column names and data in one go\n\t\t\t\tsqliteDb.exec({\n\t\t\t\t\tsql,\n\t\t\t\t\tbind: params,\n\t\t\t\t\tcolumnNames,\n\t\t\t\t\tcallback: (row) => {\n\t\t\t\t\t\tcallbackReceived = true;\n\t\t\t\t\t\tif (Array.isArray(row)) {\n\t\t\t\t\t\t\t// Store the first row's values\n\t\t\t\t\t\t\trowData = row;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Convert object to array if needed\n\t\t\t\t\t\t\trowData = columnNames.map((col) => row[col]);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} catch (e: unknown) {\n\t\t\t\tconst errorMsg = e instanceof Error ? e.message : String(e);\n\t\t\t\tconsole.error(\"Error getting row data:\", errorMsg);\n\t\t\t\treturn fail(errorMsg);\n\t\t\t}\n\n\t\t\tif (!callbackReceived) {\n\t\t\t\tconst errorMsg = \"No callback received for get method\";\n\t\t\t\tconsole.error(errorMsg);\n\t\t\t\treturn fail(errorMsg);\n\t\t\t}\n\n\t\t\t// For get method, return a single array of values\n\t\t\treturn success({ rows: rowData });\n\t\t}\n\n\t\tcase \"all\":\n\t\tcase \"values\": {\n\t\t\t// For getting multiple rows\n\t\t\tconst columnNames: string[] = [];\n\t\t\tconst rowsData: unknown[][] = [];\n\n\t\t\ttry {\n\t\t\t\t// Get column names and data in one go\n\t\t\t\tsqliteDb.exec({\n\t\t\t\t\tsql,\n\t\t\t\t\tbind: params,\n\t\t\t\t\tcolumnNames,\n\t\t\t\t\tcallback: (row) => {\n\t\t\t\t\t\tif (Array.isArray(row)) {\n\t\t\t\t\t\t\t// Convert all values to strings\n\t\t\t\t\t\t\trowsData.push(row);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Convert object to array if needed\n\t\t\t\t\t\t\trowsData.push(columnNames.map((col) => row[col]));\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} catch (e: unknown) {\n\t\t\t\tconst errorMsg = e instanceof Error ? e.message : String(e);\n\t\t\t\tconsole.error(\"Error getting all/values data:\", errorMsg);\n\t\t\t\treturn fail(errorMsg);\n\t\t\t}\n\n\t\t\t// For all/values methods, return an array of arrays\n\t\t\treturn success({ rows: rowsData });\n\t\t}\n\t}\n\n\treturn exhaustiveGuard(method);\n};\n"]}
|