@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.
Files changed (85) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +9 -1
  3. package/dist/chunk-6LNYKOKR.js +24 -0
  4. package/dist/chunk-6LNYKOKR.js.map +1 -0
  5. package/dist/chunk-7JJHY44Q.js +19 -0
  6. package/dist/chunk-7JJHY44Q.js.map +1 -0
  7. package/dist/chunk-AEYHRJVN.js +130 -0
  8. package/dist/chunk-AEYHRJVN.js.map +1 -0
  9. package/dist/chunk-AGMKOHXO.js +238 -0
  10. package/dist/chunk-AGMKOHXO.js.map +1 -0
  11. package/dist/chunk-BJDPMGFF.js +87 -0
  12. package/dist/chunk-BJDPMGFF.js.map +1 -0
  13. package/dist/chunk-BZVMUTJ7.js +49 -0
  14. package/dist/chunk-BZVMUTJ7.js.map +1 -0
  15. package/dist/chunk-FIVEPVOM.js +43 -0
  16. package/dist/chunk-FIVEPVOM.js.map +1 -0
  17. package/dist/chunk-FRONXNEA.js +123 -0
  18. package/dist/chunk-FRONXNEA.js.map +1 -0
  19. package/dist/chunk-GVUNHU6J.js +85 -0
  20. package/dist/chunk-GVUNHU6J.js.map +1 -0
  21. package/dist/chunk-H2F2HZ2A.js +22 -0
  22. package/dist/chunk-H2F2HZ2A.js.map +1 -0
  23. package/dist/chunk-NSPVPJKE.js +117 -0
  24. package/dist/chunk-NSPVPJKE.js.map +1 -0
  25. package/dist/chunk-TZP4AIBR.js +22 -0
  26. package/dist/chunk-TZP4AIBR.js.map +1 -0
  27. package/dist/chunk-WFFFP6DB.js +124 -0
  28. package/dist/chunk-WFFFP6DB.js.map +1 -0
  29. package/dist/collections/sqlite-collection.d.ts +40 -0
  30. package/dist/collections/sqlite-collection.js +3 -0
  31. package/dist/collections/sqlite-collection.js.map +1 -0
  32. package/dist/collections/synced-sqlite-collection.d.ts +19 -0
  33. package/dist/collections/synced-sqlite-collection.js +4 -0
  34. package/dist/collections/synced-sqlite-collection.js.map +1 -0
  35. package/dist/collections/websocket-collection.d.ts +18 -0
  36. package/dist/collections/websocket-collection.js +185 -0
  37. package/dist/collections/websocket-collection.js.map +1 -0
  38. package/dist/context/DrizzleSqliteProvider.d.ts +50 -0
  39. package/dist/context/DrizzleSqliteProvider.js +11 -0
  40. package/dist/context/DrizzleSqliteProvider.js.map +1 -0
  41. package/dist/context/useDrizzleSqlite.d.ts +23 -0
  42. package/dist/context/useDrizzleSqlite.js +12 -0
  43. package/dist/context/useDrizzleSqlite.js.map +1 -0
  44. package/dist/drizzle/direct.d.ts +8 -0
  45. package/dist/drizzle/direct.js +4 -0
  46. package/dist/drizzle/direct.js.map +1 -0
  47. package/dist/drizzle/handle-callback.d.ts +15 -0
  48. package/dist/drizzle/handle-callback.js +3 -0
  49. package/dist/drizzle/handle-callback.js.map +1 -0
  50. package/dist/drizzle/worker.d.ts +15 -0
  51. package/dist/drizzle/worker.js +3 -0
  52. package/dist/drizzle/worker.js.map +1 -0
  53. package/dist/hooks/useDrizzleSqliteDb.d.ts +24 -0
  54. package/dist/hooks/useDrizzleSqliteDb.js +9 -0
  55. package/dist/hooks/useDrizzleSqliteDb.js.map +1 -0
  56. package/dist/index.d.ts +25 -0
  57. package/dist/index.js +16 -0
  58. package/dist/index.js.map +1 -0
  59. package/dist/migration/migrator.d.ts +7 -0
  60. package/dist/migration/migrator.js +3 -0
  61. package/dist/migration/migrator.js.map +1 -0
  62. package/dist/types.d.ts +6 -0
  63. package/dist/types.js +3 -0
  64. package/dist/types.js.map +1 -0
  65. package/dist/worker/client.d.ts +12 -0
  66. package/dist/worker/client.js +3 -0
  67. package/dist/worker/client.js.map +1 -0
  68. package/dist/worker/global-manager.d.ts +36 -0
  69. package/dist/worker/global-manager.js +6 -0
  70. package/dist/worker/global-manager.js.map +1 -0
  71. package/dist/worker/manager.d.ts +71 -0
  72. package/dist/worker/manager.js +5 -0
  73. package/dist/worker/manager.js.map +1 -0
  74. package/dist/worker/schema.d.ts +125 -0
  75. package/dist/worker/schema.js +4 -0
  76. package/dist/worker/schema.js.map +1 -0
  77. package/dist/worker/sqlite-open-options.d.ts +45 -0
  78. package/dist/worker/sqlite-open-options.js +3 -0
  79. package/dist/worker/sqlite-open-options.js.map +1 -0
  80. package/dist/worker/sqlite.worker.d.ts +2 -0
  81. package/dist/worker/sqlite.worker.js +196 -0
  82. package/dist/worker/sqlite.worker.js.map +1 -0
  83. package/package.json +25 -25
  84. package/src/collections/sqlite-collection.ts +4 -4
  85. 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
- TanStack DB collections backed by SQLite WASM running in Web Workers, with full Drizzle ORM integration. Build reactive, type-safe SQLite applications in the browser with non-blocking database operations.
3
+ [![npm version](https://img.shields.io/npm/v/%40firtoz%2Fdrizzle-sqlite-wasm.svg)](https://www.npmjs.com/package/@firtoz/drizzle-sqlite-wasm)
4
+ [![npm downloads](https://img.shields.io/npm/dm/%40firtoz%2Fdrizzle-sqlite-wasm.svg)](https://www.npmjs.com/package/@firtoz/drizzle-sqlite-wasm)
5
+ [![license](https://img.shields.io/npm/l/%40firtoz%2Fdrizzle-sqlite-wasm.svg)](https://github.com/firtoz/fullstack-toolkit/blob/main/LICENSE)
6
+
7
+ [![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
8
+ [![Drizzle ORM](https://img.shields.io/badge/Drizzle-ORM-000000)](https://orm.drizzle.team/)
9
+ [![TanStack DB](https://img.shields.io/badge/TanStack_DB-000000?logo=react&logoColor=61DAFB)](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"]}