@syncular/dialect-wa-sqlite 0.0.1-60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @syncular/dialect-wa-sqlite - wa-sqlite dialect for sync
3
+ *
4
+ * Provides a Kysely dialect for wa-sqlite (browser SQLite via WebAssembly).
5
+ * Uses kysely-wasqlite-worker for running SQL in a web worker with OPFS or IndexedDB storage.
6
+ */
7
+ import { SerializePlugin } from '@syncular/core';
8
+ import { Kysely } from 'kysely';
9
+ import { WaSqliteWorkerDialect, type WaSqliteWorkerDialectConfig } from 'kysely-wasqlite-worker';
10
+ export interface WaSqliteOptions extends Omit<WaSqliteWorkerDialectConfig, 'fileName'> {
11
+ /** Database filename for persistence (defaults to 'diego.sqlite') */
12
+ fileName?: string;
13
+ }
14
+ /**
15
+ * Create a Kysely instance with wa-sqlite dialect.
16
+ *
17
+ * @example
18
+ * // In-memory database
19
+ * const db = createWaSqliteDb<MyDb>();
20
+ *
21
+ * // OPFS-persisted database
22
+ * const db = createWaSqliteDb<MyDb>({
23
+ * fileName: 'mydb.sqlite',
24
+ * });
25
+ */
26
+ export declare function createWaSqliteDb<T>(options?: WaSqliteOptions): Kysely<T>;
27
+ /**
28
+ * Create the wa-sqlite dialect directly.
29
+ */
30
+ export declare function createWaSqliteDialect(options?: WaSqliteOptions): WaSqliteWorkerDialect;
31
+ export declare function createSerializePlugin(): SerializePlugin;
32
+ export declare function getWaSqliteWorkerEntrypointPaths(): {
33
+ moduleWorkerPath: string;
34
+ };
35
+ export declare function getWaSqliteWasmPaths(): {
36
+ asyncWasmPath: string;
37
+ syncWasmPath: string;
38
+ };
39
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EACL,qBAAqB,EACrB,KAAK,2BAA2B,EACjC,MAAM,wBAAwB,CAAC;AAEhC,MAAM,WAAW,eACf,SAAQ,IAAI,CAAC,2BAA2B,EAAE,UAAU,CAAC;IACrD,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAWD;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,MAAM,CAAC,CAAC,CAAC,CAKxE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,CAAC,EAAE,eAAe,GACxB,qBAAqB,CAEvB;AAED,wBAAgB,qBAAqB,IAAI,eAAe,CAEvD;AAED,wBAAgB,gCAAgC,IAAI;IAClD,gBAAgB,EAAE,MAAM,CAAC;CAC1B,CAIA;AAED,wBAAgB,oBAAoB,IAAI;IACtC,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB,CAQA"}
package/dist/index.js ADDED
@@ -0,0 +1,55 @@
1
+ /**
2
+ * @syncular/dialect-wa-sqlite - wa-sqlite dialect for sync
3
+ *
4
+ * Provides a Kysely dialect for wa-sqlite (browser SQLite via WebAssembly).
5
+ * Uses kysely-wasqlite-worker for running SQL in a web worker with OPFS or IndexedDB storage.
6
+ */
7
+ import { SerializePlugin } from '@syncular/core';
8
+ import { Kysely } from 'kysely';
9
+ import { WaSqliteWorkerDialect, } from 'kysely-wasqlite-worker';
10
+ function toDialectConfig(options) {
11
+ return {
12
+ fileName: options?.fileName ?? 'diego.sqlite',
13
+ ...options,
14
+ };
15
+ }
16
+ /**
17
+ * Create a Kysely instance with wa-sqlite dialect.
18
+ *
19
+ * @example
20
+ * // In-memory database
21
+ * const db = createWaSqliteDb<MyDb>();
22
+ *
23
+ * // OPFS-persisted database
24
+ * const db = createWaSqliteDb<MyDb>({
25
+ * fileName: 'mydb.sqlite',
26
+ * });
27
+ */
28
+ export function createWaSqliteDb(options) {
29
+ return new Kysely({
30
+ dialect: new WaSqliteWorkerDialect(toDialectConfig(options)),
31
+ plugins: [new SerializePlugin()],
32
+ });
33
+ }
34
+ /**
35
+ * Create the wa-sqlite dialect directly.
36
+ */
37
+ export function createWaSqliteDialect(options) {
38
+ return new WaSqliteWorkerDialect(toDialectConfig(options));
39
+ }
40
+ export function createSerializePlugin() {
41
+ return new SerializePlugin();
42
+ }
43
+ export function getWaSqliteWorkerEntrypointPaths() {
44
+ return {
45
+ moduleWorkerPath: new URL('./worker-module.ts', import.meta.url).pathname,
46
+ };
47
+ }
48
+ export function getWaSqliteWasmPaths() {
49
+ return {
50
+ asyncWasmPath: new URL(import.meta.resolve('@subframe7536/sqlite-wasm/wasm-async')).pathname,
51
+ syncWasmPath: new URL(import.meta.resolve('@subframe7536/sqlite-wasm/wasm'))
52
+ .pathname,
53
+ };
54
+ }
55
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EACL,qBAAqB,GAEtB,MAAM,wBAAwB,CAAC;AAQhC,SAAS,eAAe,CACtB,OAAyB,EACI;IAC7B,OAAO;QACL,QAAQ,EAAE,OAAO,EAAE,QAAQ,IAAI,cAAc;QAC7C,GAAG,OAAO;KACX,CAAC;AAAA,CACH;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,gBAAgB,CAAI,OAAyB,EAAa;IACxE,OAAO,IAAI,MAAM,CAAI;QACnB,OAAO,EAAE,IAAI,qBAAqB,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QAC5D,OAAO,EAAE,CAAC,IAAI,eAAe,EAAE,CAAC;KACjC,CAAC,CAAC;AAAA,CACJ;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CACnC,OAAyB,EACF;IACvB,OAAO,IAAI,qBAAqB,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;AAAA,CAC5D;AAED,MAAM,UAAU,qBAAqB,GAAoB;IACvD,OAAO,IAAI,eAAe,EAAE,CAAC;AAAA,CAC9B;AAED,MAAM,UAAU,gCAAgC,GAE9C;IACA,OAAO;QACL,gBAAgB,EAAE,IAAI,GAAG,CAAC,oBAAoB,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ;KAC1E,CAAC;AAAA,CACH;AAED,MAAM,UAAU,oBAAoB,GAGlC;IACA,OAAO;QACL,aAAa,EAAE,IAAI,GAAG,CACpB,OAAO,IAAI,CAAC,OAAO,CAAC,sCAAsC,CAAC,CAC5D,CAAC,QAAQ;QACV,YAAY,EAAE,IAAI,GAAG,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,gCAAgC,CAAC,CAAC;aACzE,QAAQ;KACZ,CAAC;AAAA,CACH"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=worker-module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-module.d.ts","sourceRoot":"","sources":["../src/worker-module.ts"],"names":[],"mappings":""}
@@ -0,0 +1,60 @@
1
+ import { changes, close, lastInsertRowId } from '@subframe7536/sqlite-wasm';
2
+ import { SQLITE_ROW } from '@subframe7536/sqlite-wasm/constant';
3
+ import { parseBigInt } from 'kysely-generic-sqlite';
4
+ import { createWebOnMessageCallback } from 'kysely-generic-sqlite/worker-helper-web';
5
+ async function defaultCreateDatabaseFn({ fileName, url, useOPFS, }) {
6
+ const sqlite = await import('@subframe7536/sqlite-wasm');
7
+ const storage = useOPFS
8
+ ? (await import('@subframe7536/sqlite-wasm/opfs')).useOpfsStorage
9
+ : (await import('@subframe7536/sqlite-wasm/idb')).useIdbStorage;
10
+ return sqlite.initSQLiteCore(storage(fileName, { url }));
11
+ }
12
+ function createRowMapper(sqlite, stmt) {
13
+ const cols = sqlite.column_names(stmt);
14
+ return (row) => Object.fromEntries(cols.map((key, i) => [key, row[i]]));
15
+ }
16
+ async function queryData(core, sql, parameters) {
17
+ const iterator = core.sqlite
18
+ .statements(core.pointer, sql)[Symbol.asyncIterator]();
19
+ const first = await iterator.next();
20
+ if (first.done || !first.value) {
21
+ throw new Error('Failed to prepare statement');
22
+ }
23
+ const stmt = first.value;
24
+ try {
25
+ if (parameters?.length) {
26
+ core.sqlite.bind_collection(stmt, Array.from(parameters));
27
+ }
28
+ const size = core.sqlite.column_count(stmt);
29
+ if (size === 0) {
30
+ await core.sqlite.step(stmt);
31
+ return {
32
+ rows: [],
33
+ insertId: parseBigInt(lastInsertRowId(core)),
34
+ numAffectedRows: parseBigInt(changes(core)),
35
+ };
36
+ }
37
+ const mapRow = createRowMapper(core.sqlite, stmt);
38
+ const result = [];
39
+ let idx = 0;
40
+ while ((await core.sqlite.step(stmt)) === SQLITE_ROW) {
41
+ result[idx++] = mapRow(core.sqlite.row(stmt));
42
+ }
43
+ return { rows: result };
44
+ }
45
+ finally {
46
+ await iterator.return?.();
47
+ }
48
+ }
49
+ createWebOnMessageCallback(async (initData) => {
50
+ const core = await defaultCreateDatabaseFn(initData);
51
+ return {
52
+ db: core,
53
+ query: async (_isSelect, sql, parameters) => await queryData(core, sql, parameters),
54
+ close: async () => await close(core),
55
+ iterator: () => {
56
+ throw new Error('Streaming is not supported by wa-sqlite worker dialect');
57
+ },
58
+ };
59
+ });
60
+ //# sourceMappingURL=worker-module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-module.js","sourceRoot":"","sources":["../src/worker-module.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@syncular/dialect-wa-sqlite",
3
+ "version": "0.0.1-60",
4
+ "description": "WA-SQLite (WASM) dialect for the Syncular client",
5
+ "license": "MIT",
6
+ "author": "Benjamin Kniffler",
7
+ "homepage": "https://syncular.dev",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/syncular/syncular.git",
11
+ "directory": "packages/dialect-wa-sqlite"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/syncular/syncular/issues"
15
+ },
16
+ "keywords": [
17
+ "sync",
18
+ "offline-first",
19
+ "realtime",
20
+ "database",
21
+ "typescript",
22
+ "wa-sqlite",
23
+ "wasm",
24
+ "sqlite"
25
+ ],
26
+ "private": false,
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "type": "module",
31
+ "exports": {
32
+ ".": {
33
+ "bun": "./src/index.ts",
34
+ "import": {
35
+ "types": "./dist/index.d.ts",
36
+ "default": "./dist/index.js"
37
+ }
38
+ }
39
+ },
40
+ "scripts": {
41
+ "tsgo": "tsgo --noEmit",
42
+ "build": "rm -rf dist && tsgo",
43
+ "release": "bun pm pack --destination . && npm publish ./*.tgz --tag latest && rm -f ./*.tgz"
44
+ },
45
+ "dependencies": {
46
+ "@subframe7536/sqlite-wasm": "^0.5.8",
47
+ "@syncular/core": "0.0.1",
48
+ "kysely-generic-sqlite": "^1.2.1",
49
+ "kysely-wasqlite-worker": "^1.2.1"
50
+ },
51
+ "peerDependencies": {
52
+ "kysely": "^0.28.0"
53
+ },
54
+ "devDependencies": {
55
+ "@syncular/config": "0.0.0",
56
+ "kysely": "*"
57
+ },
58
+ "files": [
59
+ "dist",
60
+ "src"
61
+ ]
62
+ }
package/src/index.ts ADDED
@@ -0,0 +1,81 @@
1
+ /**
2
+ * @syncular/dialect-wa-sqlite - wa-sqlite dialect for sync
3
+ *
4
+ * Provides a Kysely dialect for wa-sqlite (browser SQLite via WebAssembly).
5
+ * Uses kysely-wasqlite-worker for running SQL in a web worker with OPFS or IndexedDB storage.
6
+ */
7
+
8
+ import { SerializePlugin } from '@syncular/core';
9
+ import { Kysely } from 'kysely';
10
+ import {
11
+ WaSqliteWorkerDialect,
12
+ type WaSqliteWorkerDialectConfig,
13
+ } from 'kysely-wasqlite-worker';
14
+
15
+ export interface WaSqliteOptions
16
+ extends Omit<WaSqliteWorkerDialectConfig, 'fileName'> {
17
+ /** Database filename for persistence (defaults to 'diego.sqlite') */
18
+ fileName?: string;
19
+ }
20
+
21
+ function toDialectConfig(
22
+ options?: WaSqliteOptions
23
+ ): WaSqliteWorkerDialectConfig {
24
+ return {
25
+ fileName: options?.fileName ?? 'diego.sqlite',
26
+ ...options,
27
+ };
28
+ }
29
+
30
+ /**
31
+ * Create a Kysely instance with wa-sqlite dialect.
32
+ *
33
+ * @example
34
+ * // In-memory database
35
+ * const db = createWaSqliteDb<MyDb>();
36
+ *
37
+ * // OPFS-persisted database
38
+ * const db = createWaSqliteDb<MyDb>({
39
+ * fileName: 'mydb.sqlite',
40
+ * });
41
+ */
42
+ export function createWaSqliteDb<T>(options?: WaSqliteOptions): Kysely<T> {
43
+ return new Kysely<T>({
44
+ dialect: new WaSqliteWorkerDialect(toDialectConfig(options)),
45
+ plugins: [new SerializePlugin()],
46
+ });
47
+ }
48
+
49
+ /**
50
+ * Create the wa-sqlite dialect directly.
51
+ */
52
+ export function createWaSqliteDialect(
53
+ options?: WaSqliteOptions
54
+ ): WaSqliteWorkerDialect {
55
+ return new WaSqliteWorkerDialect(toDialectConfig(options));
56
+ }
57
+
58
+ export function createSerializePlugin(): SerializePlugin {
59
+ return new SerializePlugin();
60
+ }
61
+
62
+ export function getWaSqliteWorkerEntrypointPaths(): {
63
+ moduleWorkerPath: string;
64
+ } {
65
+ return {
66
+ moduleWorkerPath: new URL('./worker-module.ts', import.meta.url).pathname,
67
+ };
68
+ }
69
+
70
+ export function getWaSqliteWasmPaths(): {
71
+ asyncWasmPath: string;
72
+ syncWasmPath: string;
73
+ } {
74
+ return {
75
+ asyncWasmPath: new URL(
76
+ import.meta.resolve('@subframe7536/sqlite-wasm/wasm-async')
77
+ ).pathname,
78
+ syncWasmPath: new URL(import.meta.resolve('@subframe7536/sqlite-wasm/wasm'))
79
+ .pathname,
80
+ };
81
+ }
@@ -0,0 +1,90 @@
1
+ import type { SQLiteDBCore } from '@subframe7536/sqlite-wasm';
2
+ import { changes, close, lastInsertRowId } from '@subframe7536/sqlite-wasm';
3
+ import { SQLITE_ROW } from '@subframe7536/sqlite-wasm/constant';
4
+ import type { QueryResult } from 'kysely';
5
+ import { parseBigInt } from 'kysely-generic-sqlite';
6
+ import { createWebOnMessageCallback } from 'kysely-generic-sqlite/worker-helper-web';
7
+
8
+ type InitData = {
9
+ fileName: string;
10
+ url?: string;
11
+ useOPFS?: boolean;
12
+ };
13
+
14
+ async function defaultCreateDatabaseFn({
15
+ fileName,
16
+ url,
17
+ useOPFS,
18
+ }: InitData): Promise<SQLiteDBCore> {
19
+ const sqlite = await import('@subframe7536/sqlite-wasm');
20
+ const storage = useOPFS
21
+ ? (await import('@subframe7536/sqlite-wasm/opfs')).useOpfsStorage
22
+ : (await import('@subframe7536/sqlite-wasm/idb')).useIdbStorage;
23
+ return sqlite.initSQLiteCore(storage(fileName, { url }));
24
+ }
25
+
26
+ function createRowMapper(
27
+ sqlite: SQLiteDBCore['sqlite'],
28
+ stmt: Parameters<SQLiteDBCore['sqlite']['column_names']>[0]
29
+ ) {
30
+ const cols = sqlite.column_names(stmt);
31
+ return (row: unknown[]) =>
32
+ Object.fromEntries(cols.map((key, i) => [key, row[i]]));
33
+ }
34
+
35
+ async function queryData(
36
+ core: SQLiteDBCore,
37
+ sql: string,
38
+ parameters?: readonly unknown[]
39
+ ): Promise<QueryResult<Record<string, unknown>>> {
40
+ const iterator = core.sqlite
41
+ .statements(core.pointer, sql)
42
+ [Symbol.asyncIterator]();
43
+ const first = await iterator.next();
44
+ if (first.done || !first.value) {
45
+ throw new Error('Failed to prepare statement');
46
+ }
47
+
48
+ const stmt = first.value;
49
+ try {
50
+ if (parameters?.length) {
51
+ core.sqlite.bind_collection(stmt, Array.from(parameters));
52
+ }
53
+
54
+ const size = core.sqlite.column_count(stmt);
55
+ if (size === 0) {
56
+ await core.sqlite.step(stmt);
57
+ return {
58
+ rows: [] as Record<string, unknown>[],
59
+ insertId: parseBigInt(lastInsertRowId(core)),
60
+ numAffectedRows: parseBigInt(changes(core)),
61
+ };
62
+ }
63
+
64
+ const mapRow = createRowMapper(core.sqlite, stmt);
65
+ const result: Record<string, unknown>[] = [];
66
+ let idx = 0;
67
+ while ((await core.sqlite.step(stmt)) === SQLITE_ROW) {
68
+ result[idx++] = mapRow(core.sqlite.row(stmt));
69
+ }
70
+ return { rows: result };
71
+ } finally {
72
+ await iterator.return?.();
73
+ }
74
+ }
75
+
76
+ createWebOnMessageCallback(async (initData: InitData) => {
77
+ const core = await defaultCreateDatabaseFn(initData);
78
+ return {
79
+ db: core,
80
+ query: async (
81
+ _isSelect: boolean,
82
+ sql: string,
83
+ parameters?: readonly unknown[]
84
+ ) => await queryData(core, sql, parameters),
85
+ close: async () => await close(core),
86
+ iterator: () => {
87
+ throw new Error('Streaming is not supported by wa-sqlite worker dialect');
88
+ },
89
+ };
90
+ });