@weapp-sqlite/wasm 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -1
- package/dist/index.cjs +51 -11
- package/dist/index.d.cts +11 -3
- package/dist/index.d.mts +11 -3
- package/dist/index.mjs +51 -11
- package/package.json +3 -7
package/README.md
CHANGED
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
可注入 SQLite WASM 引擎和持久化回调的宿主无关 adapter。它连接 sql.js 一类的 WASM 引擎与 `@weapp-sqlite/core`,本身不选择存储宿主。
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
|
-
pnpm add @weapp-sqlite/wasm @weapp-sqlite/core
|
|
6
|
+
pnpm add @weapp-sqlite/wasm @weapp-sqlite/core @weapp-sqlite/sqljs
|
|
7
7
|
```
|
|
8
8
|
|
|
9
9
|
```ts
|
|
10
|
+
import initializer from '@weapp-sqlite/sqljs/full'
|
|
10
11
|
import { openSqliteWasmDatabase } from '@weapp-sqlite/wasm'
|
|
11
12
|
|
|
12
13
|
const database = await openSqliteWasmDatabase(
|
|
@@ -20,6 +21,12 @@ const database = await openSqliteWasmDatabase(
|
|
|
20
21
|
|
|
21
22
|
`storage` 至少实现 `load(name)` 和 `save(name, bytes)`;连接的 `flush()` 会在写入后导出最新数据库快照。需要自定义资源路径时传入 `locateFile`。
|
|
22
23
|
|
|
24
|
+
自定义引擎必须提供 `exportSnapshot(): Uint8Array`,复制主数据库时不得关闭或重建连接。官方原版 sql.js 的 `export()` 不满足这一要求;可迁移到 `@weapp-sqlite/sqljs/full` 或 `/lite`。初始化失败后可以重试。
|
|
25
|
+
|
|
26
|
+
内置引擎的 `execWithMetadata()` 使用 SQLite 原生只读信息判断写入,`query('INSERT … RETURNING …')` 也会持久化;普通 SELECT 不保存快照。自定义引擎缺少该可选接口时,adapter 将执行保守地视作写入。事务内不会提前持久化,提交后统一保存。
|
|
27
|
+
|
|
28
|
+
`bigint` 参数仅允许 JavaScript 安全整数范围,超出时抛出 `RangeError`,避免静默舍入。保存失败保留待保存状态,可重试 `flush()`;事务提交后的失败使用 core 的 `SqlitePersistenceError` 表示。完整迁移步骤见[升级指南](https://sqlite.weapp.dev/docs/upgrading)。
|
|
29
|
+
|
|
23
30
|
本包不直接访问 IndexedDB、小程序文件系统或平台 runtime。Web 使用 `@weapp-sqlite/web`,小程序使用 `@weapp-sqlite/miniprogram`,weapp-vite 项目优先使用 `@weapp-sqlite/weapp-vite`。
|
|
24
31
|
|
|
25
32
|
通常不需要直接配置 WASM adapter:weapp-vite 会为当前目标自动选择资源。详见 [WASM API](https://sqlite.weapp.dev/docs/api/wasm)。
|
package/dist/index.cjs
CHANGED
|
@@ -2,7 +2,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
2
2
|
let _weapp_sqlite_core = require("@weapp-sqlite/core");
|
|
3
3
|
//#region src/driver.ts
|
|
4
4
|
function normalizeScalar(value) {
|
|
5
|
-
if (typeof value === "bigint")
|
|
5
|
+
if (typeof value === "bigint") {
|
|
6
|
+
if (value < BigInt(Number.MIN_SAFE_INTEGER) || value > BigInt(Number.MAX_SAFE_INTEGER)) throw new RangeError("SQLite WASM bigint parameters must be within the JavaScript safe integer range.");
|
|
7
|
+
return Number(value);
|
|
8
|
+
}
|
|
6
9
|
if (typeof value === "boolean") return value ? 1 : 0;
|
|
7
10
|
if (value instanceof ArrayBuffer) return new Uint8Array(value);
|
|
8
11
|
return value;
|
|
@@ -25,11 +28,27 @@ function rowsFromResult(result) {
|
|
|
25
28
|
};
|
|
26
29
|
}
|
|
27
30
|
function createConnection(database, name, storage) {
|
|
28
|
-
let
|
|
31
|
+
let revision = 0;
|
|
32
|
+
let savedRevision = 0;
|
|
33
|
+
let saving = Promise.resolve();
|
|
34
|
+
function execute(sql, parameters, fallback) {
|
|
35
|
+
const normalized = normalizeParameters(parameters);
|
|
36
|
+
const previousRevision = revision;
|
|
37
|
+
revision += 1;
|
|
38
|
+
if (database.execWithMetadata) {
|
|
39
|
+
const execution = database.execWithMetadata(sql, normalized);
|
|
40
|
+
if (execution.readOnly) revision = previousRevision;
|
|
41
|
+
return execution.results;
|
|
42
|
+
}
|
|
43
|
+
if (fallback === "run") {
|
|
44
|
+
database.run(sql, normalized);
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
return database.exec(sql, normalized);
|
|
48
|
+
}
|
|
29
49
|
return {
|
|
30
50
|
async exec(sql, parameters) {
|
|
31
|
-
|
|
32
|
-
dirty = true;
|
|
51
|
+
execute(sql, parameters, "run");
|
|
33
52
|
const row = database.exec("SELECT changes() AS changes, last_insert_rowid() AS lastInsertRowid")[0]?.values[0];
|
|
34
53
|
return {
|
|
35
54
|
changes: Number(row?.[0] ?? 0),
|
|
@@ -37,16 +56,21 @@ function createConnection(database, name, storage) {
|
|
|
37
56
|
};
|
|
38
57
|
},
|
|
39
58
|
async query(sql, parameters) {
|
|
40
|
-
const result =
|
|
59
|
+
const result = execute(sql, parameters, "exec")[0];
|
|
41
60
|
return result ? rowsFromResult(result) : {
|
|
42
61
|
columns: [],
|
|
43
62
|
rows: []
|
|
44
63
|
};
|
|
45
64
|
},
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
65
|
+
flush() {
|
|
66
|
+
const operation = saving.then(async () => {
|
|
67
|
+
if (revision === savedRevision) return;
|
|
68
|
+
const snapshotRevision = revision;
|
|
69
|
+
await storage.save(name, database.exportSnapshot());
|
|
70
|
+
savedRevision = snapshotRevision;
|
|
71
|
+
});
|
|
72
|
+
saving = operation.catch(() => void 0);
|
|
73
|
+
return operation;
|
|
50
74
|
},
|
|
51
75
|
async close() {
|
|
52
76
|
database.close();
|
|
@@ -58,10 +82,26 @@ function createSqliteWasmDriver(initializer, options) {
|
|
|
58
82
|
return {
|
|
59
83
|
kind: "wasm",
|
|
60
84
|
async open(name) {
|
|
61
|
-
|
|
85
|
+
if (!modulePromise) {
|
|
86
|
+
const pending = Promise.resolve().then(() => initializer(options.locateFile ? { locateFile: options.locateFile } : void 0));
|
|
87
|
+
modulePromise = pending;
|
|
88
|
+
pending.catch(() => {
|
|
89
|
+
if (modulePromise === pending) modulePromise = void 0;
|
|
90
|
+
});
|
|
91
|
+
}
|
|
62
92
|
const module = await modulePromise;
|
|
63
93
|
const data = await options.storage.load(name);
|
|
64
|
-
|
|
94
|
+
const database = new module.Database(data);
|
|
95
|
+
if (typeof database.exportSnapshot !== "function") {
|
|
96
|
+
const error = /* @__PURE__ */ new TypeError("SQLite WASM engines must implement exportSnapshot() without resetting the connection. Use @weapp-sqlite/sqljs or migrate the custom initializer.");
|
|
97
|
+
try {
|
|
98
|
+
database.close();
|
|
99
|
+
} catch (closeError) {
|
|
100
|
+
throw new AggregateError([error, closeError], error.message, { cause: error });
|
|
101
|
+
}
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
return createConnection(database, name, options.storage);
|
|
65
105
|
}
|
|
66
106
|
};
|
|
67
107
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -6,10 +6,18 @@ interface SqlJsResult {
|
|
|
6
6
|
readonly columns: readonly string[];
|
|
7
7
|
readonly values: readonly (readonly unknown[])[];
|
|
8
8
|
}
|
|
9
|
+
interface SqlJsExecutionResult {
|
|
10
|
+
readonly results: readonly SqlJsResult[];
|
|
11
|
+
readonly readOnly: boolean;
|
|
12
|
+
}
|
|
9
13
|
interface SqlJsDatabase {
|
|
10
14
|
run: (sql: string, parameters?: SqlJsParameters) => SqlJsDatabase;
|
|
11
15
|
exec: (sql: string, parameters?: SqlJsParameters) => readonly SqlJsResult[];
|
|
12
16
|
export: () => Uint8Array;
|
|
17
|
+
/** Copies the main database without closing or resetting the connection. */
|
|
18
|
+
exportSnapshot: () => Uint8Array;
|
|
19
|
+
/** Without metadata, the adapter conservatively treats queries as writes. */
|
|
20
|
+
execWithMetadata?: (sql: string, parameters?: SqlJsParameters) => SqlJsExecutionResult;
|
|
13
21
|
close: () => void;
|
|
14
22
|
}
|
|
15
23
|
interface SqlJsModule {
|
|
@@ -29,7 +37,7 @@ interface SqliteWasmDriverOptions {
|
|
|
29
37
|
type SqliteWasmParameters = SqliteParameters;
|
|
30
38
|
//#endregion
|
|
31
39
|
//#region src/driver.d.ts
|
|
32
|
-
declare function createSqliteWasmDriver(initializer: SqlJsInitializer, options: SqliteWasmDriverOptions): SqliteDriver;
|
|
33
|
-
declare function openSqliteWasmDatabase(initializer: SqlJsInitializer, name: string, options: SqliteWasmDriverOptions): Promise<SqliteDatabase>;
|
|
40
|
+
export declare function createSqliteWasmDriver(initializer: SqlJsInitializer, options: SqliteWasmDriverOptions): SqliteDriver;
|
|
41
|
+
export declare function openSqliteWasmDatabase(initializer: SqlJsInitializer, name: string, options: SqliteWasmDriverOptions): Promise<SqliteDatabase>;
|
|
34
42
|
//#endregion
|
|
35
|
-
export {
|
|
43
|
+
export type { SqlJsDatabase, SqlJsExecutionResult, SqlJsInitializer, SqlJsModule, SqlJsParameters, SqlJsResult, SqlJsScalar, SqliteWasmDriverOptions, SqliteWasmParameters, SqliteWasmStorage };
|
package/dist/index.d.mts
CHANGED
|
@@ -6,10 +6,18 @@ interface SqlJsResult {
|
|
|
6
6
|
readonly columns: readonly string[];
|
|
7
7
|
readonly values: readonly (readonly unknown[])[];
|
|
8
8
|
}
|
|
9
|
+
interface SqlJsExecutionResult {
|
|
10
|
+
readonly results: readonly SqlJsResult[];
|
|
11
|
+
readonly readOnly: boolean;
|
|
12
|
+
}
|
|
9
13
|
interface SqlJsDatabase {
|
|
10
14
|
run: (sql: string, parameters?: SqlJsParameters) => SqlJsDatabase;
|
|
11
15
|
exec: (sql: string, parameters?: SqlJsParameters) => readonly SqlJsResult[];
|
|
12
16
|
export: () => Uint8Array;
|
|
17
|
+
/** Copies the main database without closing or resetting the connection. */
|
|
18
|
+
exportSnapshot: () => Uint8Array;
|
|
19
|
+
/** Without metadata, the adapter conservatively treats queries as writes. */
|
|
20
|
+
execWithMetadata?: (sql: string, parameters?: SqlJsParameters) => SqlJsExecutionResult;
|
|
13
21
|
close: () => void;
|
|
14
22
|
}
|
|
15
23
|
interface SqlJsModule {
|
|
@@ -29,7 +37,7 @@ interface SqliteWasmDriverOptions {
|
|
|
29
37
|
type SqliteWasmParameters = SqliteParameters;
|
|
30
38
|
//#endregion
|
|
31
39
|
//#region src/driver.d.ts
|
|
32
|
-
declare function createSqliteWasmDriver(initializer: SqlJsInitializer, options: SqliteWasmDriverOptions): SqliteDriver;
|
|
33
|
-
declare function openSqliteWasmDatabase(initializer: SqlJsInitializer, name: string, options: SqliteWasmDriverOptions): Promise<SqliteDatabase>;
|
|
40
|
+
export declare function createSqliteWasmDriver(initializer: SqlJsInitializer, options: SqliteWasmDriverOptions): SqliteDriver;
|
|
41
|
+
export declare function openSqliteWasmDatabase(initializer: SqlJsInitializer, name: string, options: SqliteWasmDriverOptions): Promise<SqliteDatabase>;
|
|
34
42
|
//#endregion
|
|
35
|
-
export {
|
|
43
|
+
export type { SqlJsDatabase, SqlJsExecutionResult, SqlJsInitializer, SqlJsModule, SqlJsParameters, SqlJsResult, SqlJsScalar, SqliteWasmDriverOptions, SqliteWasmParameters, SqliteWasmStorage };
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { createSqliteDatabase } from "@weapp-sqlite/core";
|
|
2
2
|
//#region src/driver.ts
|
|
3
3
|
function normalizeScalar(value) {
|
|
4
|
-
if (typeof value === "bigint")
|
|
4
|
+
if (typeof value === "bigint") {
|
|
5
|
+
if (value < BigInt(Number.MIN_SAFE_INTEGER) || value > BigInt(Number.MAX_SAFE_INTEGER)) throw new RangeError("SQLite WASM bigint parameters must be within the JavaScript safe integer range.");
|
|
6
|
+
return Number(value);
|
|
7
|
+
}
|
|
5
8
|
if (typeof value === "boolean") return value ? 1 : 0;
|
|
6
9
|
if (value instanceof ArrayBuffer) return new Uint8Array(value);
|
|
7
10
|
return value;
|
|
@@ -24,11 +27,27 @@ function rowsFromResult(result) {
|
|
|
24
27
|
};
|
|
25
28
|
}
|
|
26
29
|
function createConnection(database, name, storage) {
|
|
27
|
-
let
|
|
30
|
+
let revision = 0;
|
|
31
|
+
let savedRevision = 0;
|
|
32
|
+
let saving = Promise.resolve();
|
|
33
|
+
function execute(sql, parameters, fallback) {
|
|
34
|
+
const normalized = normalizeParameters(parameters);
|
|
35
|
+
const previousRevision = revision;
|
|
36
|
+
revision += 1;
|
|
37
|
+
if (database.execWithMetadata) {
|
|
38
|
+
const execution = database.execWithMetadata(sql, normalized);
|
|
39
|
+
if (execution.readOnly) revision = previousRevision;
|
|
40
|
+
return execution.results;
|
|
41
|
+
}
|
|
42
|
+
if (fallback === "run") {
|
|
43
|
+
database.run(sql, normalized);
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
return database.exec(sql, normalized);
|
|
47
|
+
}
|
|
28
48
|
return {
|
|
29
49
|
async exec(sql, parameters) {
|
|
30
|
-
|
|
31
|
-
dirty = true;
|
|
50
|
+
execute(sql, parameters, "run");
|
|
32
51
|
const row = database.exec("SELECT changes() AS changes, last_insert_rowid() AS lastInsertRowid")[0]?.values[0];
|
|
33
52
|
return {
|
|
34
53
|
changes: Number(row?.[0] ?? 0),
|
|
@@ -36,16 +55,21 @@ function createConnection(database, name, storage) {
|
|
|
36
55
|
};
|
|
37
56
|
},
|
|
38
57
|
async query(sql, parameters) {
|
|
39
|
-
const result =
|
|
58
|
+
const result = execute(sql, parameters, "exec")[0];
|
|
40
59
|
return result ? rowsFromResult(result) : {
|
|
41
60
|
columns: [],
|
|
42
61
|
rows: []
|
|
43
62
|
};
|
|
44
63
|
},
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
64
|
+
flush() {
|
|
65
|
+
const operation = saving.then(async () => {
|
|
66
|
+
if (revision === savedRevision) return;
|
|
67
|
+
const snapshotRevision = revision;
|
|
68
|
+
await storage.save(name, database.exportSnapshot());
|
|
69
|
+
savedRevision = snapshotRevision;
|
|
70
|
+
});
|
|
71
|
+
saving = operation.catch(() => void 0);
|
|
72
|
+
return operation;
|
|
49
73
|
},
|
|
50
74
|
async close() {
|
|
51
75
|
database.close();
|
|
@@ -57,10 +81,26 @@ function createSqliteWasmDriver(initializer, options) {
|
|
|
57
81
|
return {
|
|
58
82
|
kind: "wasm",
|
|
59
83
|
async open(name) {
|
|
60
|
-
|
|
84
|
+
if (!modulePromise) {
|
|
85
|
+
const pending = Promise.resolve().then(() => initializer(options.locateFile ? { locateFile: options.locateFile } : void 0));
|
|
86
|
+
modulePromise = pending;
|
|
87
|
+
pending.catch(() => {
|
|
88
|
+
if (modulePromise === pending) modulePromise = void 0;
|
|
89
|
+
});
|
|
90
|
+
}
|
|
61
91
|
const module = await modulePromise;
|
|
62
92
|
const data = await options.storage.load(name);
|
|
63
|
-
|
|
93
|
+
const database = new module.Database(data);
|
|
94
|
+
if (typeof database.exportSnapshot !== "function") {
|
|
95
|
+
const error = /* @__PURE__ */ new TypeError("SQLite WASM engines must implement exportSnapshot() without resetting the connection. Use @weapp-sqlite/sqljs or migrate the custom initializer.");
|
|
96
|
+
try {
|
|
97
|
+
database.close();
|
|
98
|
+
} catch (closeError) {
|
|
99
|
+
throw new AggregateError([error, closeError], error.message, { cause: error });
|
|
100
|
+
}
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
return createConnection(database, name, options.storage);
|
|
64
104
|
}
|
|
65
105
|
};
|
|
66
106
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weapp-sqlite/wasm",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.0",
|
|
5
5
|
"description": "基于可注入 WASM SQLite 引擎的跨宿主 adapter",
|
|
6
6
|
"author": "weapp-sqlite contributors",
|
|
7
7
|
"license": "MIT",
|
|
@@ -45,16 +45,12 @@
|
|
|
45
45
|
"node": ">=18.0.0"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@weapp-sqlite/core": "0.
|
|
48
|
+
"@weapp-sqlite/core": "0.2.0"
|
|
49
49
|
},
|
|
50
50
|
"publishConfig": {
|
|
51
51
|
"access": "public",
|
|
52
52
|
"registry": "https://registry.npmjs.org/"
|
|
53
53
|
},
|
|
54
|
-
"devDependencies": {
|
|
55
|
-
"@types/sql.js": "^1.4.11",
|
|
56
|
-
"sql.js": "^1.14.2"
|
|
57
|
-
},
|
|
58
54
|
"scripts": {
|
|
59
55
|
"dev": "tsdown -w",
|
|
60
56
|
"build": "tsdown",
|
|
@@ -64,6 +60,6 @@
|
|
|
64
60
|
"lint": "eslint .",
|
|
65
61
|
"lint:fix": "eslint . --fix",
|
|
66
62
|
"typecheck": "tsc -p tsconfig.json",
|
|
67
|
-
"tsd": "pnpm build && tsd --files test-d/**/*.test-d.ts"
|
|
63
|
+
"tsd": "pnpm build && tsd --typings dist/index.d.mts --files test-d/**/*.test-d.ts"
|
|
68
64
|
}
|
|
69
65
|
}
|