web-sqlite-js 1.1.2 → 2.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 +152 -48
- package/dist/index.d.ts +28 -0
- package/dist/index.js +2 -2
- package/package.json +83 -83
package/README.md
CHANGED
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
<a href="https://www.npmjs.com/package/web-sqlite-js" target="_blank">
|
|
14
14
|
<img src="https://img.shields.io/npm/v/web-sqlite-js.svg" alt="NPM Version" />
|
|
15
15
|
</a>
|
|
16
|
+
<a href="https://github.com/wuchuheng/web-sqlite-js/discussions" target="_blank">
|
|
17
|
+
<img src="https://img.shields.io/badge/v2.0.0-new%20features-blue" alt="v2.0.0" />
|
|
18
|
+
</a>
|
|
16
19
|
<a href="https://github.com/wuchuheng/web-sqlite-js/blob/main/LICENSE" target="_blank">
|
|
17
20
|
<img src="https://img.shields.io/github/license/wuchuheng/web-sqlite-js.svg" alt="License" />
|
|
18
21
|
</a>
|
|
@@ -33,8 +36,10 @@ Designed to be truly effortless, it allows you to get a high-performance relatio
|
|
|
33
36
|
- [Quick start](#quick-start)
|
|
34
37
|
- [Setup HTTP headers](#setup-http-headers)
|
|
35
38
|
- [Usage](#usage)
|
|
36
|
-
- [Debug mode](#debug-mode)
|
|
37
39
|
- [Transactions](#transactions)
|
|
40
|
+
- [Schema Migrations](#schema-migrations)
|
|
41
|
+
- [Debug mode](#debug-mode)
|
|
42
|
+
- [Structured Logging](#structured-logging)
|
|
38
43
|
|
|
39
44
|
## Features
|
|
40
45
|
|
|
@@ -43,6 +48,8 @@ Designed to be truly effortless, it allows you to get a high-performance relatio
|
|
|
43
48
|
- **Concurrency Safe**: Built-in mutex ensures safe, sequential execution of commands.
|
|
44
49
|
- **Type-Safe**: Written in TypeScript with full type definitions.
|
|
45
50
|
- **Transactions**: Supports atomic transactions with automatic rollback on error.
|
|
51
|
+
- **Schema Migrations**: Built-in versioning system for database schema changes.
|
|
52
|
+
- **Structured Logging**: Subscribe to SQL execution logs via `onLog()`.
|
|
46
53
|
|
|
47
54
|
## Quick start
|
|
48
55
|
|
|
@@ -66,8 +73,8 @@ For quick demos or plain HTML pages you can load the prebuilt module directly:
|
|
|
66
73
|
|
|
67
74
|
```html
|
|
68
75
|
<script type="module">
|
|
69
|
-
|
|
70
|
-
|
|
76
|
+
import openDB from "https://cdn.jsdelivr.net/npm/web-sqlite-js@1.0.9/dist/index.js";
|
|
77
|
+
// ...
|
|
71
78
|
</script>
|
|
72
79
|
```
|
|
73
80
|
|
|
@@ -95,18 +102,18 @@ Update your `vite.config.ts`:
|
|
|
95
102
|
import { defineConfig } from "vite";
|
|
96
103
|
|
|
97
104
|
export default defineConfig({
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
},
|
|
105
|
+
server: {
|
|
106
|
+
headers: {
|
|
107
|
+
"Cross-Origin-Opener-Policy": "same-origin",
|
|
108
|
+
"Cross-Origin-Embedder-Policy": "require-corp",
|
|
103
109
|
},
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
110
|
+
},
|
|
111
|
+
preview: {
|
|
112
|
+
headers: {
|
|
113
|
+
"Cross-Origin-Opener-Policy": "same-origin",
|
|
114
|
+
"Cross-Origin-Embedder-Policy": "require-corp",
|
|
109
115
|
},
|
|
116
|
+
},
|
|
110
117
|
});
|
|
111
118
|
```
|
|
112
119
|
|
|
@@ -120,23 +127,23 @@ Update your `next.config.js`:
|
|
|
120
127
|
```javascript
|
|
121
128
|
/** @type {import('next').NextConfig} */
|
|
122
129
|
const nextConfig = {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
130
|
+
async headers() {
|
|
131
|
+
return [
|
|
132
|
+
{
|
|
133
|
+
source: "/(.*)",
|
|
134
|
+
headers: [
|
|
135
|
+
{
|
|
136
|
+
key: "Cross-Origin-Opener-Policy",
|
|
137
|
+
value: "same-origin",
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
key: "Cross-Origin-Embedder-Policy",
|
|
141
|
+
value: "require-corp",
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
},
|
|
145
|
+
];
|
|
146
|
+
},
|
|
140
147
|
};
|
|
141
148
|
|
|
142
149
|
module.exports = nextConfig;
|
|
@@ -151,13 +158,13 @@ Update your `webpack.config.js`:
|
|
|
151
158
|
|
|
152
159
|
```javascript
|
|
153
160
|
module.exports = {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
},
|
|
161
|
+
// ...
|
|
162
|
+
devServer: {
|
|
163
|
+
headers: {
|
|
164
|
+
"Cross-Origin-Opener-Policy": "same-origin",
|
|
165
|
+
"Cross-Origin-Embedder-Policy": "require-corp",
|
|
160
166
|
},
|
|
167
|
+
},
|
|
161
168
|
};
|
|
162
169
|
```
|
|
163
170
|
|
|
@@ -189,9 +196,9 @@ const express = require("express");
|
|
|
189
196
|
const app = express();
|
|
190
197
|
|
|
191
198
|
app.use((req, res, next) => {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
199
|
+
res.setHeader("Cross-Origin-Opener-Policy", "same-origin");
|
|
200
|
+
res.setHeader("Cross-Origin-Embedder-Policy", "require-corp");
|
|
201
|
+
next();
|
|
195
202
|
});
|
|
196
203
|
|
|
197
204
|
// ...
|
|
@@ -227,12 +234,12 @@ await db.exec(`
|
|
|
227
234
|
|
|
228
235
|
// 3. Insert data (Parameterized)
|
|
229
236
|
await db.exec("INSERT INTO users (name, email) VALUES (?, ?)", [
|
|
230
|
-
|
|
231
|
-
|
|
237
|
+
"Alice",
|
|
238
|
+
"alice@example.com",
|
|
232
239
|
]);
|
|
233
240
|
await db.exec("INSERT INTO users (name, email) VALUES ($name, $email)", {
|
|
234
|
-
|
|
235
|
-
|
|
241
|
+
$name: "Bob",
|
|
242
|
+
$email: "bob@example.com",
|
|
236
243
|
});
|
|
237
244
|
|
|
238
245
|
// 4. Query data
|
|
@@ -266,13 +273,110 @@ Transactions are atomic. If any command inside the callback fails, the entire tr
|
|
|
266
273
|
|
|
267
274
|
```typescript
|
|
268
275
|
await db.transaction(async (tx) => {
|
|
269
|
-
|
|
276
|
+
await tx.exec("INSERT INTO users (name) VALUES (?)", ["Charlie"]);
|
|
277
|
+
|
|
278
|
+
// You can perform multiple operations safely
|
|
279
|
+
await tx.exec("INSERT INTO logs (action) VALUES (?)", ["User Created"]);
|
|
280
|
+
|
|
281
|
+
// If you throw an error here, both INSERTs will be rolled back!
|
|
282
|
+
// throw new Error('Something went wrong');
|
|
283
|
+
});
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## Schema Migrations
|
|
270
287
|
|
|
271
|
-
|
|
272
|
-
await tx.exec("INSERT INTO logs (action) VALUES (?)", ["User Created"]);
|
|
288
|
+
Manage database schema changes across releases using the built-in versioning system. Define releases with migration SQL and optional seed data.
|
|
273
289
|
|
|
274
|
-
|
|
275
|
-
|
|
290
|
+
### Basic Usage
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
const db = await openDB("myapp", {
|
|
294
|
+
releases: [
|
|
295
|
+
{
|
|
296
|
+
version: "1.0.0",
|
|
297
|
+
migrationSQL: `
|
|
298
|
+
CREATE TABLE users (
|
|
299
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
300
|
+
name TEXT NOT NULL,
|
|
301
|
+
email TEXT UNIQUE
|
|
302
|
+
);
|
|
303
|
+
`,
|
|
304
|
+
seedSQL: `
|
|
305
|
+
INSERT INTO users (name, email) VALUES
|
|
306
|
+
('Alice', 'alice@example.com'),
|
|
307
|
+
('Bob', 'bob@example.com');
|
|
308
|
+
`,
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
version: "1.1.0",
|
|
312
|
+
migrationSQL: `
|
|
313
|
+
ALTER TABLE users ADD COLUMN created_at TEXT DEFAULT (datetime('now'));
|
|
314
|
+
`,
|
|
315
|
+
},
|
|
316
|
+
],
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
// Database is now at version 1.1.0 with all migrations applied
|
|
320
|
+
const users = await db.query("SELECT * FROM users");
|
|
321
|
+
console.log(users);
|
|
322
|
+
// Output: [{ id: 1, name: 'Alice', email: 'alice@example.com', created_at: '...' }, ...]
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### How It Works
|
|
326
|
+
|
|
327
|
+
1. **Version Tracking**: Each release has a semantic version (e.g., "1.0.0")
|
|
328
|
+
2. **Automatic Migration**: When opening a database, new releases are applied in order
|
|
329
|
+
3. **Hash Verification**: Migration SQL is hashed to prevent tampering
|
|
330
|
+
4. **OPFS Storage**: Each version is stored as a separate file (`1.0.0.sqlite3`, `1.1.0.sqlite3`)
|
|
331
|
+
|
|
332
|
+
### Best Practices
|
|
333
|
+
|
|
334
|
+
- **Use Semantic Versioning**: Follow `MAJOR.MINOR.PATCH` format
|
|
335
|
+
- **Idempotent Migrations**: Each migration should handle re-runs safely
|
|
336
|
+
- **Test Migrations**: Always test migrations on a clean database
|
|
337
|
+
- **Incremental Changes**: Keep migrations focused on single schema changes
|
|
338
|
+
|
|
339
|
+
## Structured Logging
|
|
340
|
+
|
|
341
|
+
Subscribe to structured log events for monitoring, debugging, and analytics. The `onLog()` API allows you to capture SQL execution details, errors, and application events.
|
|
342
|
+
|
|
343
|
+
```typescript
|
|
344
|
+
const db = await openDB("myapp");
|
|
345
|
+
|
|
346
|
+
// Register log listener
|
|
347
|
+
const cancelLog = db.onLog((log) => {
|
|
348
|
+
if (log.level === "error") {
|
|
349
|
+
// Send errors to tracking service
|
|
350
|
+
errorTracking.capture(log.data);
|
|
351
|
+
} else if (log.level === "debug") {
|
|
352
|
+
// Log SQL execution details
|
|
353
|
+
console.log(`SQL: ${log.data.sql}, Duration: ${log.data.duration}ms`);
|
|
354
|
+
} else if (log.level === "info") {
|
|
355
|
+
// Track application events (open, close, transactions)
|
|
356
|
+
console.log(`Event: ${log.data.action}`);
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
// Execute some SQL to generate logs
|
|
361
|
+
await db.exec("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)");
|
|
362
|
+
await db.exec("INSERT INTO users (name) VALUES (?)", ["Alice"]);
|
|
363
|
+
|
|
364
|
+
// Later: stop listening
|
|
365
|
+
cancelLog();
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
**Log Levels**:
|
|
369
|
+
|
|
370
|
+
- `"debug"` - SQL execution details (sql, duration, bind parameters)
|
|
371
|
+
- `"info"` - Application events (open, close, commit, rollback)
|
|
372
|
+
- `"error"` - SQL errors and exceptions
|
|
373
|
+
|
|
374
|
+
**Multiple Callbacks**: You can register multiple log listeners simultaneously:
|
|
375
|
+
|
|
376
|
+
```typescript
|
|
377
|
+
const cancel1 = db.onLog((log) => console.log("Logger 1:", log));
|
|
378
|
+
const cancel2 = db.onLog((log) => {
|
|
379
|
+
if (log.level === "error") sendToAlerting(log.data);
|
|
276
380
|
});
|
|
277
381
|
```
|
|
278
382
|
|
package/dist/index.d.ts
CHANGED
|
@@ -21,6 +21,20 @@ declare interface DBInterface {
|
|
|
21
21
|
transaction<T>(fn: transactionCallback<T>): Promise<T>;
|
|
22
22
|
/** Close the database and release resources. */
|
|
23
23
|
close(): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Subscribe to log events
|
|
26
|
+
* Logs include SQL execution, timing, errors, and application events
|
|
27
|
+
*
|
|
28
|
+
* @param callback - Called for each log entry
|
|
29
|
+
* @returns Unsubscribe function
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* const unsubscribe = db.onLog((log) => {
|
|
33
|
+
* console.log(`[${log.level}]`, log.data);
|
|
34
|
+
* });
|
|
35
|
+
* // Later: unsubscribe();
|
|
36
|
+
*/
|
|
37
|
+
onLog(callback: (log: LogEntry) => void): () => void;
|
|
24
38
|
/** Dev tooling APIs for release testing. */
|
|
25
39
|
devTool: DevTool;
|
|
26
40
|
}
|
|
@@ -46,6 +60,20 @@ declare type ExecResult = {
|
|
|
46
60
|
lastInsertRowid?: number | bigint;
|
|
47
61
|
};
|
|
48
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Log entry with level and structured data
|
|
65
|
+
*/
|
|
66
|
+
declare type LogEntry = {
|
|
67
|
+
/**
|
|
68
|
+
* Log level: 'info' | 'debug' | 'error'
|
|
69
|
+
*/
|
|
70
|
+
level: "info" | "debug" | "error";
|
|
71
|
+
/**
|
|
72
|
+
* Log data (SQL, timing, errors, events, etc.)
|
|
73
|
+
*/
|
|
74
|
+
data: unknown;
|
|
75
|
+
};
|
|
76
|
+
|
|
49
77
|
/**
|
|
50
78
|
* Opens a SQLite database connection with release-versioning support.
|
|
51
79
|
*
|