@monlite/wasm 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +26 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -72,6 +72,32 @@ var WasmDriver = class {
|
|
|
72
72
|
throw err;
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
|
+
async transactionAsync(fn) {
|
|
76
|
+
const savepoint = `monlite_sp_${this.depth}`;
|
|
77
|
+
if (this.depth === 0) this.raw.run("BEGIN IMMEDIATE");
|
|
78
|
+
else this.raw.run(`SAVEPOINT ${savepoint}`);
|
|
79
|
+
this.depth++;
|
|
80
|
+
try {
|
|
81
|
+
const result = await fn();
|
|
82
|
+
this.depth--;
|
|
83
|
+
if (this.depth === 0) this.raw.run("COMMIT");
|
|
84
|
+
else this.raw.run(`RELEASE ${savepoint}`);
|
|
85
|
+
return result;
|
|
86
|
+
} catch (err) {
|
|
87
|
+
this.depth--;
|
|
88
|
+
try {
|
|
89
|
+
if (this.depth === 0) this.raw.run("ROLLBACK");
|
|
90
|
+
else this.raw.run(`ROLLBACK TO ${savepoint}; RELEASE ${savepoint}`);
|
|
91
|
+
} catch {
|
|
92
|
+
this.depth = 0;
|
|
93
|
+
try {
|
|
94
|
+
this.raw.run("ROLLBACK");
|
|
95
|
+
} catch {
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
throw err;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
75
101
|
/** Serialize the whole database to bytes (for persistence). */
|
|
76
102
|
export() {
|
|
77
103
|
return this.raw.export();
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["import type { Driver, PreparedStatement, RunResult } from \"@monlite/core\";\n\n/**\n * The subset of the sql.js module/`Database` we rely on. Passing `sql.js`'s\n * `SqlJsStatic` (the result of `initSqlJs()`) satisfies this.\n */\nexport interface SqlJsStatic {\n Database: new (data?: Uint8Array | null) => SqlJsDatabase;\n}\nexport interface SqlJsDatabase {\n run(sql: string, params?: any[]): void;\n prepare(sql: string): SqlJsStatement;\n exec(sql: string): Array<{ columns: string[]; values: any[][] }>;\n getRowsModified(): number;\n export(): Uint8Array;\n close(): void;\n}\nexport interface SqlJsStatement {\n bind(params?: any[]): boolean;\n step(): boolean;\n getAsObject(): Record<string, any>;\n run(params?: any[]): void;\n reset(): void;\n free(): void;\n}\n\nexport interface WasmDriverOptions {\n /** Existing database bytes to open (e.g. restored from IndexedDB/OPFS). */\n data?: Uint8Array | null;\n}\n\n/**\n * A monlite {@link Driver} backed by SQLite-WASM (sql.js). Runs in the browser\n * (and Node). Construction is synchronous — initialise sql.js yourself first:\n *\n * ```ts\n * import initSqlJs from \"sql.js\";\n * import { wasmDriver } from \"@monlite/wasm\";\n * import { createDb } from \"@monlite/core\";\n *\n * const SQL = await initSqlJs({ locateFile: (f) => `/sqljs/${f}` });\n * const db = createDb(\":memory:\", { driver: wasmDriver(SQL) });\n * ```\n *\n * sql.js is in-memory; use {@link exportDatabase}/`{ data }` to persist (see the\n * README for IndexedDB/OPFS recipes).\n */\nexport class WasmDriver implements Driver {\n readonly name = \"wasm-sqlite\";\n readonly raw: SqlJsDatabase;\n private readonly cache = new Map<\n string,\n { stmt: SqlJsStatement; wrapped: PreparedStatement }\n >();\n private depth = 0;\n\n constructor(SQL: SqlJsStatic, options: WasmDriverOptions = {}) {\n this.raw = new SQL.Database(options.data ?? null);\n this.raw.run(\"PRAGMA foreign_keys = ON\");\n }\n\n exec(sql: string): void {\n this.raw.run(sql);\n }\n\n private lastInsertRowid(): number {\n const res = this.raw.exec(\"SELECT last_insert_rowid() AS id\");\n return (res[0]?.values?.[0]?.[0] as number) ?? 0;\n }\n\n prepare(sql: string): PreparedStatement {\n const cached = this.cache.get(sql);\n if (cached) return cached.wrapped;\n\n const stmt = this.raw.prepare(sql);\n // Arrow functions capture the driver's `this` lexically.\n const wrapped: PreparedStatement = {\n run: (...params: any[]): RunResult => {\n stmt.run(params);\n return {\n changes: this.raw.getRowsModified(),\n lastInsertRowid: this.lastInsertRowid(),\n };\n },\n get: (...params: any[]): any => {\n stmt.bind(params);\n const row = stmt.step() ? stmt.getAsObject() : undefined;\n stmt.reset();\n return row;\n },\n all: (...params: any[]): any[] => {\n stmt.bind(params);\n const rows: any[] = [];\n while (stmt.step()) rows.push(stmt.getAsObject());\n stmt.reset();\n return rows;\n },\n };\n this.cache.set(sql, { stmt, wrapped });\n return wrapped;\n }\n\n transaction<T>(fn: () => T): T {\n const savepoint = `monlite_sp_${this.depth}`;\n if (this.depth === 0) this.raw.run(\"BEGIN\");\n else this.raw.run(`SAVEPOINT ${savepoint}`);\n this.depth++;\n try {\n const result = fn();\n this.depth--;\n if (this.depth === 0) this.raw.run(\"COMMIT\");\n else this.raw.run(`RELEASE ${savepoint}`);\n return result;\n } catch (err) {\n this.depth--;\n try {\n if (this.depth === 0) this.raw.run(\"ROLLBACK\");\n else this.raw.run(`ROLLBACK TO ${savepoint}; RELEASE ${savepoint}`);\n } catch {\n this.depth = 0;\n try {\n this.raw.run(\"ROLLBACK\");\n } catch {\n /* no active transaction */\n }\n }\n throw err;\n }\n }\n\n /** Serialize the whole database to bytes (for persistence). */\n export(): Uint8Array {\n return this.raw.export();\n }\n\n close(): void {\n for (const { stmt } of this.cache.values()) stmt.free();\n this.cache.clear();\n this.raw.close();\n }\n}\n\n/** Create a WASM-backed monlite driver from an initialised sql.js module. */\nexport function wasmDriver(\n SQL: SqlJsStatic,\n options?: WasmDriverOptions,\n): WasmDriver {\n return new WasmDriver(SQL, options);\n}\n\n/**\n * Serialize a monlite database opened with the WASM driver to bytes — persist\n * these (IndexedDB/OPFS/file) and reopen with `wasmDriver(SQL, { data })`.\n */\nexport function exportDatabase(db: { driver: Driver }): Uint8Array {\n const driver = db.driver;\n if (!(driver instanceof WasmDriver)) {\n throw new Error(\n \"exportDatabase requires a database opened with the WASM driver\",\n );\n }\n return driver.export();\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;AA+CO,IAAM,aAAN,MAAmC;AAAA,EAC/B,IAAA,GAAO,aAAA;AAAA,EACP,GAAA;AAAA,EACQ,KAAA,uBAAY,GAAA,EAG3B;AAAA,EACM,KAAA,GAAQ,CAAA;AAAA,EAEhB,WAAA,CAAY,GAAA,EAAkB,OAAA,GAA6B,EAAC,EAAG;AAC7D,IAAA,IAAA,CAAK,MAAM,IAAI,GAAA,CAAI,QAAA,CAAS,OAAA,CAAQ,QAAQ,IAAI,CAAA;AAChD,IAAA,IAAA,CAAK,GAAA,CAAI,IAAI,0BAA0B,CAAA;AAAA,EACzC;AAAA,EAEA,KAAK,GAAA,EAAmB;AACtB,IAAA,IAAA,CAAK,GAAA,CAAI,IAAI,GAAG,CAAA;AAAA,EAClB;AAAA,EAEQ,eAAA,GAA0B;AAChC,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,kCAAkC,CAAA;AAC5D,IAAA,OAAQ,IAAI,CAAC,CAAA,EAAG,SAAS,CAAC,CAAA,GAAI,CAAC,CAAA,IAAgB,CAAA;AAAA,EACjD;AAAA,EAEA,QAAQ,GAAA,EAAgC;AACtC,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA;AACjC,IAAA,IAAI,MAAA,SAAe,MAAA,CAAO,OAAA;AAE1B,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,OAAA,CAAQ,GAAG,CAAA;AAEjC,IAAA,MAAM,OAAA,GAA6B;AAAA,MACjC,GAAA,EAAK,IAAI,MAAA,KAA6B;AACpC,QAAA,IAAA,CAAK,IAAI,MAAM,CAAA;AACf,QAAA,OAAO;AAAA,UACL,OAAA,EAAS,IAAA,CAAK,GAAA,CAAI,eAAA,EAAgB;AAAA,UAClC,eAAA,EAAiB,KAAK,eAAA;AAAgB,SACxC;AAAA,MACF,CAAA;AAAA,MACA,GAAA,EAAK,IAAI,MAAA,KAAuB;AAC9B,QAAA,IAAA,CAAK,KAAK,MAAM,CAAA;AAChB,QAAA,MAAM,MAAM,IAAA,CAAK,IAAA,EAAK,GAAI,IAAA,CAAK,aAAY,GAAI,MAAA;AAC/C,QAAA,IAAA,CAAK,KAAA,EAAM;AACX,QAAA,OAAO,GAAA;AAAA,MACT,CAAA;AAAA,MACA,GAAA,EAAK,IAAI,MAAA,KAAyB;AAChC,QAAA,IAAA,CAAK,KAAK,MAAM,CAAA;AAChB,QAAA,MAAM,OAAc,EAAC;AACrB,QAAA,OAAO,KAAK,IAAA,EAAK,OAAQ,IAAA,CAAK,IAAA,CAAK,aAAa,CAAA;AAChD,QAAA,IAAA,CAAK,KAAA,EAAM;AACX,QAAA,OAAO,IAAA;AAAA,MACT;AAAA,KACF;AACA,IAAA,IAAA,CAAK,MAAM,GAAA,CAAI,GAAA,EAAK,EAAE,IAAA,EAAM,SAAS,CAAA;AACrC,IAAA,OAAO,OAAA;AAAA,EACT;AAAA,EAEA,YAAe,EAAA,EAAgB;AAC7B,IAAA,MAAM,SAAA,GAAY,CAAA,WAAA,EAAc,IAAA,CAAK,KAAK,CAAA,CAAA;AAC1C,IAAA,IAAI,KAAK,KAAA,KAAU,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,IAAI,OAAO,CAAA;AAAA,SACrC,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,CAAA,UAAA,EAAa,SAAS,CAAA,CAAE,CAAA;AAC1C,IAAA,IAAA,CAAK,KAAA,EAAA;AACL,IAAA,IAAI;AACF,MAAA,MAAM,SAAS,EAAA,EAAG;AAClB,MAAA,IAAA,CAAK,KAAA,EAAA;AACL,MAAA,IAAI,KAAK,KAAA,KAAU,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,IAAI,QAAQ,CAAA;AAAA,WACtC,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,CAAA,QAAA,EAAW,SAAS,CAAA,CAAE,CAAA;AACxC,MAAA,OAAO,MAAA;AAAA,IACT,SAAS,GAAA,EAAK;AACZ,MAAA,IAAA,CAAK,KAAA,EAAA;AACL,MAAA,IAAI;AACF,QAAA,IAAI,KAAK,KAAA,KAAU,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,IAAI,UAAU,CAAA;AAAA,kBACnC,GAAA,CAAI,GAAA,CAAI,eAAe,SAAS,CAAA,UAAA,EAAa,SAAS,CAAA,CAAE,CAAA;AAAA,MACpE,CAAA,CAAA,MAAQ;AACN,QAAA,IAAA,CAAK,KAAA,GAAQ,CAAA;AACb,QAAA,IAAI;AACF,UAAA,IAAA,CAAK,GAAA,CAAI,IAAI,UAAU,CAAA;AAAA,QACzB,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACF;AACA,MAAA,MAAM,GAAA;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,iBAAoB,EAAA,EAAkC;AAC1D,IAAA,MAAM,SAAA,GAAY,CAAA,WAAA,EAAc,IAAA,CAAK,KAAK,CAAA,CAAA;AAC1C,IAAA,IAAI,KAAK,KAAA,KAAU,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,IAAI,iBAAiB,CAAA;AAAA,SAC/C,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,CAAA,UAAA,EAAa,SAAS,CAAA,CAAE,CAAA;AAC1C,IAAA,IAAA,CAAK,KAAA,EAAA;AACL,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,MAAM,EAAA,EAAG;AACxB,MAAA,IAAA,CAAK,KAAA,EAAA;AACL,MAAA,IAAI,KAAK,KAAA,KAAU,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,IAAI,QAAQ,CAAA;AAAA,WACtC,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,CAAA,QAAA,EAAW,SAAS,CAAA,CAAE,CAAA;AACxC,MAAA,OAAO,MAAA;AAAA,IACT,SAAS,GAAA,EAAK;AACZ,MAAA,IAAA,CAAK,KAAA,EAAA;AACL,MAAA,IAAI;AACF,QAAA,IAAI,KAAK,KAAA,KAAU,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,IAAI,UAAU,CAAA;AAAA,kBACnC,GAAA,CAAI,GAAA,CAAI,eAAe,SAAS,CAAA,UAAA,EAAa,SAAS,CAAA,CAAE,CAAA;AAAA,MACpE,CAAA,CAAA,MAAQ;AACN,QAAA,IAAA,CAAK,KAAA,GAAQ,CAAA;AACb,QAAA,IAAI;AACF,UAAA,IAAA,CAAK,GAAA,CAAI,IAAI,UAAU,CAAA;AAAA,QACzB,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACF;AACA,MAAA,MAAM,GAAA;AAAA,IACR;AAAA,EACF;AAAA;AAAA,EAGA,MAAA,GAAqB;AACnB,IAAA,OAAO,IAAA,CAAK,IAAI,MAAA,EAAO;AAAA,EACzB;AAAA,EAEA,KAAA,GAAc;AACZ,IAAA,KAAA,MAAW,EAAE,MAAK,IAAK,IAAA,CAAK,MAAM,MAAA,EAAO,OAAQ,IAAA,EAAK;AACtD,IAAA,IAAA,CAAK,MAAM,KAAA,EAAM;AACjB,IAAA,IAAA,CAAK,IAAI,KAAA,EAAM;AAAA,EACjB;AACF;AAGO,SAAS,UAAA,CACd,KACA,OAAA,EACY;AACZ,EAAA,OAAO,IAAI,UAAA,CAAW,GAAA,EAAK,OAAO,CAAA;AACpC;AAMO,SAAS,eAAe,EAAA,EAAoC;AACjE,EAAA,MAAM,SAAS,EAAA,CAAG,MAAA;AAClB,EAAA,IAAI,EAAE,kBAAkB,UAAA,CAAA,EAAa;AACnC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AACA,EAAA,OAAO,OAAO,MAAA,EAAO;AACvB","file":"index.cjs","sourcesContent":["import type { Driver, PreparedStatement, RunResult } from \"@monlite/core\";\n\n/**\n * The subset of the sql.js module/`Database` we rely on. Passing `sql.js`'s\n * `SqlJsStatic` (the result of `initSqlJs()`) satisfies this.\n */\nexport interface SqlJsStatic {\n Database: new (data?: Uint8Array | null) => SqlJsDatabase;\n}\nexport interface SqlJsDatabase {\n run(sql: string, params?: any[]): void;\n prepare(sql: string): SqlJsStatement;\n exec(sql: string): Array<{ columns: string[]; values: any[][] }>;\n getRowsModified(): number;\n export(): Uint8Array;\n close(): void;\n}\nexport interface SqlJsStatement {\n bind(params?: any[]): boolean;\n step(): boolean;\n getAsObject(): Record<string, any>;\n run(params?: any[]): void;\n reset(): void;\n free(): void;\n}\n\nexport interface WasmDriverOptions {\n /** Existing database bytes to open (e.g. restored from IndexedDB/OPFS). */\n data?: Uint8Array | null;\n}\n\n/**\n * A monlite {@link Driver} backed by SQLite-WASM (sql.js). Runs in the browser\n * (and Node). Construction is synchronous — initialise sql.js yourself first:\n *\n * ```ts\n * import initSqlJs from \"sql.js\";\n * import { wasmDriver } from \"@monlite/wasm\";\n * import { createDb } from \"@monlite/core\";\n *\n * const SQL = await initSqlJs({ locateFile: (f) => `/sqljs/${f}` });\n * const db = createDb(\":memory:\", { driver: wasmDriver(SQL) });\n * ```\n *\n * sql.js is in-memory; use {@link exportDatabase}/`{ data }` to persist (see the\n * README for IndexedDB/OPFS recipes).\n */\nexport class WasmDriver implements Driver {\n readonly name = \"wasm-sqlite\";\n readonly raw: SqlJsDatabase;\n private readonly cache = new Map<\n string,\n { stmt: SqlJsStatement; wrapped: PreparedStatement }\n >();\n private depth = 0;\n\n constructor(SQL: SqlJsStatic, options: WasmDriverOptions = {}) {\n this.raw = new SQL.Database(options.data ?? null);\n this.raw.run(\"PRAGMA foreign_keys = ON\");\n }\n\n exec(sql: string): void {\n this.raw.run(sql);\n }\n\n private lastInsertRowid(): number {\n const res = this.raw.exec(\"SELECT last_insert_rowid() AS id\");\n return (res[0]?.values?.[0]?.[0] as number) ?? 0;\n }\n\n prepare(sql: string): PreparedStatement {\n const cached = this.cache.get(sql);\n if (cached) return cached.wrapped;\n\n const stmt = this.raw.prepare(sql);\n // Arrow functions capture the driver's `this` lexically.\n const wrapped: PreparedStatement = {\n run: (...params: any[]): RunResult => {\n stmt.run(params);\n return {\n changes: this.raw.getRowsModified(),\n lastInsertRowid: this.lastInsertRowid(),\n };\n },\n get: (...params: any[]): any => {\n stmt.bind(params);\n const row = stmt.step() ? stmt.getAsObject() : undefined;\n stmt.reset();\n return row;\n },\n all: (...params: any[]): any[] => {\n stmt.bind(params);\n const rows: any[] = [];\n while (stmt.step()) rows.push(stmt.getAsObject());\n stmt.reset();\n return rows;\n },\n };\n this.cache.set(sql, { stmt, wrapped });\n return wrapped;\n }\n\n transaction<T>(fn: () => T): T {\n const savepoint = `monlite_sp_${this.depth}`;\n if (this.depth === 0) this.raw.run(\"BEGIN\");\n else this.raw.run(`SAVEPOINT ${savepoint}`);\n this.depth++;\n try {\n const result = fn();\n this.depth--;\n if (this.depth === 0) this.raw.run(\"COMMIT\");\n else this.raw.run(`RELEASE ${savepoint}`);\n return result;\n } catch (err) {\n this.depth--;\n try {\n if (this.depth === 0) this.raw.run(\"ROLLBACK\");\n else this.raw.run(`ROLLBACK TO ${savepoint}; RELEASE ${savepoint}`);\n } catch {\n this.depth = 0;\n try {\n this.raw.run(\"ROLLBACK\");\n } catch {\n /* no active transaction */\n }\n }\n throw err;\n }\n }\n\n async transactionAsync<T>(fn: () => Promise<T>): Promise<T> {\n const savepoint = `monlite_sp_${this.depth}`;\n if (this.depth === 0) this.raw.run(\"BEGIN IMMEDIATE\");\n else this.raw.run(`SAVEPOINT ${savepoint}`);\n this.depth++;\n try {\n const result = await fn();\n this.depth--;\n if (this.depth === 0) this.raw.run(\"COMMIT\");\n else this.raw.run(`RELEASE ${savepoint}`);\n return result;\n } catch (err) {\n this.depth--;\n try {\n if (this.depth === 0) this.raw.run(\"ROLLBACK\");\n else this.raw.run(`ROLLBACK TO ${savepoint}; RELEASE ${savepoint}`);\n } catch {\n this.depth = 0;\n try {\n this.raw.run(\"ROLLBACK\");\n } catch {\n /* already rolled back */\n }\n }\n throw err;\n }\n }\n\n /** Serialize the whole database to bytes (for persistence). */\n export(): Uint8Array {\n return this.raw.export();\n }\n\n close(): void {\n for (const { stmt } of this.cache.values()) stmt.free();\n this.cache.clear();\n this.raw.close();\n }\n}\n\n/** Create a WASM-backed monlite driver from an initialised sql.js module. */\nexport function wasmDriver(\n SQL: SqlJsStatic,\n options?: WasmDriverOptions,\n): WasmDriver {\n return new WasmDriver(SQL, options);\n}\n\n/**\n * Serialize a monlite database opened with the WASM driver to bytes — persist\n * these (IndexedDB/OPFS/file) and reopen with `wasmDriver(SQL, { data })`.\n */\nexport function exportDatabase(db: { driver: Driver }): Uint8Array {\n const driver = db.driver;\n if (!(driver instanceof WasmDriver)) {\n throw new Error(\n \"exportDatabase requires a database opened with the WASM driver\",\n );\n }\n return driver.export();\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -56,6 +56,7 @@ declare class WasmDriver implements Driver {
|
|
|
56
56
|
private lastInsertRowid;
|
|
57
57
|
prepare(sql: string): PreparedStatement;
|
|
58
58
|
transaction<T>(fn: () => T): T;
|
|
59
|
+
transactionAsync<T>(fn: () => Promise<T>): Promise<T>;
|
|
59
60
|
/** Serialize the whole database to bytes (for persistence). */
|
|
60
61
|
export(): Uint8Array;
|
|
61
62
|
close(): void;
|
package/dist/index.d.ts
CHANGED
|
@@ -56,6 +56,7 @@ declare class WasmDriver implements Driver {
|
|
|
56
56
|
private lastInsertRowid;
|
|
57
57
|
prepare(sql: string): PreparedStatement;
|
|
58
58
|
transaction<T>(fn: () => T): T;
|
|
59
|
+
transactionAsync<T>(fn: () => Promise<T>): Promise<T>;
|
|
59
60
|
/** Serialize the whole database to bytes (for persistence). */
|
|
60
61
|
export(): Uint8Array;
|
|
61
62
|
close(): void;
|
package/dist/index.js
CHANGED
|
@@ -70,6 +70,32 @@ var WasmDriver = class {
|
|
|
70
70
|
throw err;
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
|
+
async transactionAsync(fn) {
|
|
74
|
+
const savepoint = `monlite_sp_${this.depth}`;
|
|
75
|
+
if (this.depth === 0) this.raw.run("BEGIN IMMEDIATE");
|
|
76
|
+
else this.raw.run(`SAVEPOINT ${savepoint}`);
|
|
77
|
+
this.depth++;
|
|
78
|
+
try {
|
|
79
|
+
const result = await fn();
|
|
80
|
+
this.depth--;
|
|
81
|
+
if (this.depth === 0) this.raw.run("COMMIT");
|
|
82
|
+
else this.raw.run(`RELEASE ${savepoint}`);
|
|
83
|
+
return result;
|
|
84
|
+
} catch (err) {
|
|
85
|
+
this.depth--;
|
|
86
|
+
try {
|
|
87
|
+
if (this.depth === 0) this.raw.run("ROLLBACK");
|
|
88
|
+
else this.raw.run(`ROLLBACK TO ${savepoint}; RELEASE ${savepoint}`);
|
|
89
|
+
} catch {
|
|
90
|
+
this.depth = 0;
|
|
91
|
+
try {
|
|
92
|
+
this.raw.run("ROLLBACK");
|
|
93
|
+
} catch {
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
throw err;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
73
99
|
/** Serialize the whole database to bytes (for persistence). */
|
|
74
100
|
export() {
|
|
75
101
|
return this.raw.export();
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { Driver, PreparedStatement, RunResult } from \"@monlite/core\";\n\n/**\n * The subset of the sql.js module/`Database` we rely on. Passing `sql.js`'s\n * `SqlJsStatic` (the result of `initSqlJs()`) satisfies this.\n */\nexport interface SqlJsStatic {\n Database: new (data?: Uint8Array | null) => SqlJsDatabase;\n}\nexport interface SqlJsDatabase {\n run(sql: string, params?: any[]): void;\n prepare(sql: string): SqlJsStatement;\n exec(sql: string): Array<{ columns: string[]; values: any[][] }>;\n getRowsModified(): number;\n export(): Uint8Array;\n close(): void;\n}\nexport interface SqlJsStatement {\n bind(params?: any[]): boolean;\n step(): boolean;\n getAsObject(): Record<string, any>;\n run(params?: any[]): void;\n reset(): void;\n free(): void;\n}\n\nexport interface WasmDriverOptions {\n /** Existing database bytes to open (e.g. restored from IndexedDB/OPFS). */\n data?: Uint8Array | null;\n}\n\n/**\n * A monlite {@link Driver} backed by SQLite-WASM (sql.js). Runs in the browser\n * (and Node). Construction is synchronous — initialise sql.js yourself first:\n *\n * ```ts\n * import initSqlJs from \"sql.js\";\n * import { wasmDriver } from \"@monlite/wasm\";\n * import { createDb } from \"@monlite/core\";\n *\n * const SQL = await initSqlJs({ locateFile: (f) => `/sqljs/${f}` });\n * const db = createDb(\":memory:\", { driver: wasmDriver(SQL) });\n * ```\n *\n * sql.js is in-memory; use {@link exportDatabase}/`{ data }` to persist (see the\n * README for IndexedDB/OPFS recipes).\n */\nexport class WasmDriver implements Driver {\n readonly name = \"wasm-sqlite\";\n readonly raw: SqlJsDatabase;\n private readonly cache = new Map<\n string,\n { stmt: SqlJsStatement; wrapped: PreparedStatement }\n >();\n private depth = 0;\n\n constructor(SQL: SqlJsStatic, options: WasmDriverOptions = {}) {\n this.raw = new SQL.Database(options.data ?? null);\n this.raw.run(\"PRAGMA foreign_keys = ON\");\n }\n\n exec(sql: string): void {\n this.raw.run(sql);\n }\n\n private lastInsertRowid(): number {\n const res = this.raw.exec(\"SELECT last_insert_rowid() AS id\");\n return (res[0]?.values?.[0]?.[0] as number) ?? 0;\n }\n\n prepare(sql: string): PreparedStatement {\n const cached = this.cache.get(sql);\n if (cached) return cached.wrapped;\n\n const stmt = this.raw.prepare(sql);\n // Arrow functions capture the driver's `this` lexically.\n const wrapped: PreparedStatement = {\n run: (...params: any[]): RunResult => {\n stmt.run(params);\n return {\n changes: this.raw.getRowsModified(),\n lastInsertRowid: this.lastInsertRowid(),\n };\n },\n get: (...params: any[]): any => {\n stmt.bind(params);\n const row = stmt.step() ? stmt.getAsObject() : undefined;\n stmt.reset();\n return row;\n },\n all: (...params: any[]): any[] => {\n stmt.bind(params);\n const rows: any[] = [];\n while (stmt.step()) rows.push(stmt.getAsObject());\n stmt.reset();\n return rows;\n },\n };\n this.cache.set(sql, { stmt, wrapped });\n return wrapped;\n }\n\n transaction<T>(fn: () => T): T {\n const savepoint = `monlite_sp_${this.depth}`;\n if (this.depth === 0) this.raw.run(\"BEGIN\");\n else this.raw.run(`SAVEPOINT ${savepoint}`);\n this.depth++;\n try {\n const result = fn();\n this.depth--;\n if (this.depth === 0) this.raw.run(\"COMMIT\");\n else this.raw.run(`RELEASE ${savepoint}`);\n return result;\n } catch (err) {\n this.depth--;\n try {\n if (this.depth === 0) this.raw.run(\"ROLLBACK\");\n else this.raw.run(`ROLLBACK TO ${savepoint}; RELEASE ${savepoint}`);\n } catch {\n this.depth = 0;\n try {\n this.raw.run(\"ROLLBACK\");\n } catch {\n /* no active transaction */\n }\n }\n throw err;\n }\n }\n\n /** Serialize the whole database to bytes (for persistence). */\n export(): Uint8Array {\n return this.raw.export();\n }\n\n close(): void {\n for (const { stmt } of this.cache.values()) stmt.free();\n this.cache.clear();\n this.raw.close();\n }\n}\n\n/** Create a WASM-backed monlite driver from an initialised sql.js module. */\nexport function wasmDriver(\n SQL: SqlJsStatic,\n options?: WasmDriverOptions,\n): WasmDriver {\n return new WasmDriver(SQL, options);\n}\n\n/**\n * Serialize a monlite database opened with the WASM driver to bytes — persist\n * these (IndexedDB/OPFS/file) and reopen with `wasmDriver(SQL, { data })`.\n */\nexport function exportDatabase(db: { driver: Driver }): Uint8Array {\n const driver = db.driver;\n if (!(driver instanceof WasmDriver)) {\n throw new Error(\n \"exportDatabase requires a database opened with the WASM driver\",\n );\n }\n return driver.export();\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { Driver, PreparedStatement, RunResult } from \"@monlite/core\";\n\n/**\n * The subset of the sql.js module/`Database` we rely on. Passing `sql.js`'s\n * `SqlJsStatic` (the result of `initSqlJs()`) satisfies this.\n */\nexport interface SqlJsStatic {\n Database: new (data?: Uint8Array | null) => SqlJsDatabase;\n}\nexport interface SqlJsDatabase {\n run(sql: string, params?: any[]): void;\n prepare(sql: string): SqlJsStatement;\n exec(sql: string): Array<{ columns: string[]; values: any[][] }>;\n getRowsModified(): number;\n export(): Uint8Array;\n close(): void;\n}\nexport interface SqlJsStatement {\n bind(params?: any[]): boolean;\n step(): boolean;\n getAsObject(): Record<string, any>;\n run(params?: any[]): void;\n reset(): void;\n free(): void;\n}\n\nexport interface WasmDriverOptions {\n /** Existing database bytes to open (e.g. restored from IndexedDB/OPFS). */\n data?: Uint8Array | null;\n}\n\n/**\n * A monlite {@link Driver} backed by SQLite-WASM (sql.js). Runs in the browser\n * (and Node). Construction is synchronous — initialise sql.js yourself first:\n *\n * ```ts\n * import initSqlJs from \"sql.js\";\n * import { wasmDriver } from \"@monlite/wasm\";\n * import { createDb } from \"@monlite/core\";\n *\n * const SQL = await initSqlJs({ locateFile: (f) => `/sqljs/${f}` });\n * const db = createDb(\":memory:\", { driver: wasmDriver(SQL) });\n * ```\n *\n * sql.js is in-memory; use {@link exportDatabase}/`{ data }` to persist (see the\n * README for IndexedDB/OPFS recipes).\n */\nexport class WasmDriver implements Driver {\n readonly name = \"wasm-sqlite\";\n readonly raw: SqlJsDatabase;\n private readonly cache = new Map<\n string,\n { stmt: SqlJsStatement; wrapped: PreparedStatement }\n >();\n private depth = 0;\n\n constructor(SQL: SqlJsStatic, options: WasmDriverOptions = {}) {\n this.raw = new SQL.Database(options.data ?? null);\n this.raw.run(\"PRAGMA foreign_keys = ON\");\n }\n\n exec(sql: string): void {\n this.raw.run(sql);\n }\n\n private lastInsertRowid(): number {\n const res = this.raw.exec(\"SELECT last_insert_rowid() AS id\");\n return (res[0]?.values?.[0]?.[0] as number) ?? 0;\n }\n\n prepare(sql: string): PreparedStatement {\n const cached = this.cache.get(sql);\n if (cached) return cached.wrapped;\n\n const stmt = this.raw.prepare(sql);\n // Arrow functions capture the driver's `this` lexically.\n const wrapped: PreparedStatement = {\n run: (...params: any[]): RunResult => {\n stmt.run(params);\n return {\n changes: this.raw.getRowsModified(),\n lastInsertRowid: this.lastInsertRowid(),\n };\n },\n get: (...params: any[]): any => {\n stmt.bind(params);\n const row = stmt.step() ? stmt.getAsObject() : undefined;\n stmt.reset();\n return row;\n },\n all: (...params: any[]): any[] => {\n stmt.bind(params);\n const rows: any[] = [];\n while (stmt.step()) rows.push(stmt.getAsObject());\n stmt.reset();\n return rows;\n },\n };\n this.cache.set(sql, { stmt, wrapped });\n return wrapped;\n }\n\n transaction<T>(fn: () => T): T {\n const savepoint = `monlite_sp_${this.depth}`;\n if (this.depth === 0) this.raw.run(\"BEGIN\");\n else this.raw.run(`SAVEPOINT ${savepoint}`);\n this.depth++;\n try {\n const result = fn();\n this.depth--;\n if (this.depth === 0) this.raw.run(\"COMMIT\");\n else this.raw.run(`RELEASE ${savepoint}`);\n return result;\n } catch (err) {\n this.depth--;\n try {\n if (this.depth === 0) this.raw.run(\"ROLLBACK\");\n else this.raw.run(`ROLLBACK TO ${savepoint}; RELEASE ${savepoint}`);\n } catch {\n this.depth = 0;\n try {\n this.raw.run(\"ROLLBACK\");\n } catch {\n /* no active transaction */\n }\n }\n throw err;\n }\n }\n\n async transactionAsync<T>(fn: () => Promise<T>): Promise<T> {\n const savepoint = `monlite_sp_${this.depth}`;\n if (this.depth === 0) this.raw.run(\"BEGIN IMMEDIATE\");\n else this.raw.run(`SAVEPOINT ${savepoint}`);\n this.depth++;\n try {\n const result = await fn();\n this.depth--;\n if (this.depth === 0) this.raw.run(\"COMMIT\");\n else this.raw.run(`RELEASE ${savepoint}`);\n return result;\n } catch (err) {\n this.depth--;\n try {\n if (this.depth === 0) this.raw.run(\"ROLLBACK\");\n else this.raw.run(`ROLLBACK TO ${savepoint}; RELEASE ${savepoint}`);\n } catch {\n this.depth = 0;\n try {\n this.raw.run(\"ROLLBACK\");\n } catch {\n /* already rolled back */\n }\n }\n throw err;\n }\n }\n\n /** Serialize the whole database to bytes (for persistence). */\n export(): Uint8Array {\n return this.raw.export();\n }\n\n close(): void {\n for (const { stmt } of this.cache.values()) stmt.free();\n this.cache.clear();\n this.raw.close();\n }\n}\n\n/** Create a WASM-backed monlite driver from an initialised sql.js module. */\nexport function wasmDriver(\n SQL: SqlJsStatic,\n options?: WasmDriverOptions,\n): WasmDriver {\n return new WasmDriver(SQL, options);\n}\n\n/**\n * Serialize a monlite database opened with the WASM driver to bytes — persist\n * these (IndexedDB/OPFS/file) and reopen with `wasmDriver(SQL, { data })`.\n */\nexport function exportDatabase(db: { driver: Driver }): Uint8Array {\n const driver = db.driver;\n if (!(driver instanceof WasmDriver)) {\n throw new Error(\n \"exportDatabase requires a database opened with the WASM driver\",\n );\n }\n return driver.export();\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@monlite/wasm",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Run @monlite/core in the browser (or anywhere) on SQLite-WASM via sql.js — a custom driver.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"node": ">=18"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@monlite/core": "^
|
|
52
|
+
"@monlite/core": "^2.2.0"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
55
|
"sql.js": ">=1.8"
|