js-bao 0.5.1 → 0.6.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 CHANGED
@@ -29,17 +29,21 @@ npm install js-bao yjs
29
29
  yarn add js-bao yjs
30
30
  # or
31
31
  pnpm add js-bao yjs
32
-
33
- # For SQL.js engine:
34
- npm install sql.js
35
32
  ```
36
33
 
34
+ The default **SQL.js** engine works out of the box in both the browser and
35
+ headless Node — `sql.js` is a direct dependency of `js-bao`, so there's nothing
36
+ extra to install. (In the browser you do need to serve `sql-wasm.wasm`; see
37
+ [SQL.js — the universal default](#sqljs-type-sqljs--the-universal-default).)
38
+
37
39
  ### Optional Dependencies
38
40
 
39
- For Node.js environments, you can install native database engines:
41
+ For native, file-backed SQLite in Node.js (the `node-sqlite` engine), install
42
+ `better-sqlite3`. This is a **one-line opt-in** — `js-bao` never switches engines
43
+ on you automatically:
40
44
 
41
45
  ```bash
42
- # For SQLite support in Node.js
46
+ # Native SQLite in Node.js (then set databaseConfig: { type: "node-sqlite" })
43
47
  npm install better-sqlite3
44
48
  ```
45
49
 
@@ -51,8 +55,10 @@ npm install better-sqlite3
51
55
 
52
56
  ### Node.js
53
57
 
54
- - **better-sqlite3**: Native SQLite with file system support
55
- - **SQL.js**: SQLite WASM (fallback option)
58
+ - **SQL.js (`sqljs`)**: SQLite WASM — the default; works out of the box in
59
+ headless Node (resolves its wasm automatically, no config).
60
+ - **better-sqlite3 (`node-sqlite`)**: native, file-backed SQLite. One-line opt-in
61
+ (`npm install better-sqlite3` + `databaseConfig: { type: "node-sqlite" }`).
56
62
 
57
63
  ## Core Concepts
58
64
 
@@ -787,6 +793,10 @@ const results = await Product.query({
787
793
  - **Text**: `$startsWith`, `$endsWith`, `$containsText` (case-insensitive by default)
788
794
  - **Existence**: `$exists`
789
795
 
796
+ **Absent fields.** `$ne`, `$nin` and `{ field: null }` **match records where the field is absent** — a record that never wrote the field is not equal to any value, as in MongoDB. Equality with a value, the comparison operators and `$in` **match only records that carry the field**. Presence is `$exists`, whose handling of an explicitly stored null is path-dependent: the server counts a **stored JSON null** as present, while the browser and Swift replicas keep each field in a typed column where a stored null is indistinguishable from absence.
797
+
798
+ **Breaking change (#3166).** `$ne`/`$nin` used to exclude records lacking the field. A negative-operator filter used to *exclude* records by a possibly-absent field — including hook-injected access filters and write conditions — now matches those records too. To keep the old result set, exclude the missing case with a `null` entry in `$nin` — `{ deleted: { $nin: [null, true] } }`, which matches only records carrying a non-null value other than the excluded one, on every path. `$exists: true` alongside the negative operator is not equivalent: the server counts an explicitly stored JSON null as present, so `{ deleted: { $ne: true, $exists: true } }` still matches a null-valued record the old filter excluded.
799
+
790
800
  ### Sorting and Pagination
791
801
 
792
802
  ```typescript
@@ -1251,22 +1261,106 @@ const tagStats = await Article.aggregate({
1251
1261
 
1252
1262
  ## Database Engine Specifics
1253
1263
 
1254
- ### SQL.js (`type: 'sqljs'`)
1255
-
1256
- - **WASM File**: `sql-wasm.wasm` (from the `sql.js` package) must be publicly accessible in your application.
1257
- - By default, the library expects it at `/sql-wasm.wasm` (root of your public server path).
1258
- - **Vite/Create React App**: Place `sql-wasm.wasm` in your project's `public` directory.
1259
- - **Custom Path**: If the WASM file is located elsewhere, configure it in `DatabaseConfig`:
1260
- ```typescript
1261
- const dbConfig: DatabaseConfig = {
1262
- type: "sqljs",
1263
- options: {
1264
- wasmURL: "/path/to/your/sql-wasm.wasm",
1265
- // or use locateFile for more complex scenarios:
1266
- // locateFile: (file) => `/assets/wasm/${file}`
1267
- },
1268
- };
1269
- ```
1264
+ ### SQL.js (`type: 'sqljs'`) — the universal default
1265
+
1266
+ `sqljs` is SQLite compiled to WebAssembly. It is the **default engine** and now
1267
+ works **out of the box in both the browser and headless Node** — no manual wasm
1268
+ configuration required in either environment.
1269
+
1270
+ #### Browser
1271
+
1272
+ The `sql-wasm.wasm` file (from the `sql.js` package) must be served from your
1273
+ app. By default the library expects it at `/sql-wasm.wasm` (the root of your
1274
+ public server path).
1275
+
1276
+ - **Vite / Create React App**: copy `node_modules/sql.js/dist/sql-wasm.wasm` into
1277
+ your project's `public/` directory so it is served at `/sql-wasm.wasm`.
1278
+ - **Custom path**: if the wasm lives elsewhere, point at it via `DatabaseConfig`:
1279
+
1280
+ ```typescript
1281
+ const dbConfig: DatabaseConfig = {
1282
+ type: "sqljs",
1283
+ options: {
1284
+ wasmURL: "/assets/wasm/sql-wasm.wasm",
1285
+ // or, for more complex layouts:
1286
+ // locateFile: (file) => `/assets/wasm/${file}`,
1287
+ },
1288
+ };
1289
+ ```
1290
+
1291
+ #### Headless Node
1292
+
1293
+ Under Node, `sqljs` automatically resolves sql.js's bundled
1294
+ `sql-wasm.wasm` **relative to the installed js-bao package** (using
1295
+ `createRequire(import.meta.url).resolve("sql.js/dist/sql-wasm.wasm")`, with a
1296
+ `__dirname`-based fallback for the CommonJS build). **No `wasmURL` / `locateFile`
1297
+ override and no extra setup is needed** — `new SqljsEngine()` (or the client's
1298
+ default `{ type: "sqljs" }`) just works:
1299
+
1300
+ ```typescript
1301
+ import { SqljsEngine } from "js-bao/node";
1302
+
1303
+ const engine = new SqljsEngine(); // resolves sql.js's wasm automatically
1304
+ await engine.ensureReady();
1305
+ ```
1306
+
1307
+ An explicit `wasmURL` / `locateFile` still takes precedence if you provide one.
1308
+
1309
+ ##### Graceful, catchable failure
1310
+
1311
+ If the wasm genuinely cannot be located (e.g. you pass a bad `locateFile`),
1312
+ initialization now **rejects with a single, catchable `Error`** carrying
1313
+ remediation guidance:
1314
+
1315
+ ```typescript
1316
+ try {
1317
+ const engine = new SqljsEngine({ locateFile: () => "/bad/path.wasm" });
1318
+ await engine.ensureReady();
1319
+ } catch (err) {
1320
+ // "sql.js wasm not found at "/bad/path.wasm". Pass `locateFile`/`wasmURL` ...,
1321
+ // or install `better-sqlite3` and use the `node-sqlite` engine ..."
1322
+ console.error(err.message);
1323
+ }
1324
+ ```
1325
+
1326
+ Previously a missing/corrupt wasm caused sql.js's emscripten runtime to abort
1327
+ asynchronously with an **uncatchable `RuntimeError: Aborted`** that escaped
1328
+ `try/catch` and crashed the Node process. The engine now preflights the wasm path
1329
+ and installs a defensive `onAbort` handler so the failure surfaces as a normal
1330
+ rejected promise instead.
1331
+
1332
+ ### Native SQLite in Node (`type: 'node-sqlite'`) — easy opt-in
1333
+
1334
+ `sqljs` is fine for most Node usage, but if you want native, file-backed SQLite
1335
+ (via the `better-sqlite3` addon) it is a **one-line opt-in** — `sqljs` is never
1336
+ silently swapped out for you. Install the optional dependency and set the engine
1337
+ type:
1338
+
1339
+ ```bash
1340
+ npm install better-sqlite3
1341
+ ```
1342
+
1343
+ ```typescript
1344
+ // Flip the client (or initJsBao) to native SQLite in one line:
1345
+ const client = new JsBaoClient({
1346
+ // ...other options...
1347
+ databaseConfig: {
1348
+ type: "node-sqlite",
1349
+ options: { filePath: ":memory:" }, // or "/path/to/app.db" for persistence
1350
+ },
1351
+ });
1352
+ ```
1353
+
1354
+ To pick the engine programmatically based on what's installed, use the helper
1355
+ exported from `js-bao/node`:
1356
+
1357
+ ```typescript
1358
+ import { getRecommendedNodeEngine } from "js-bao/node";
1359
+
1360
+ // Returns "node-sqlite" when better-sqlite3 is installed, else "sqljs".
1361
+ const type = await getRecommendedNodeEngine();
1362
+ const databaseConfig = { type, options: { filePath: ":memory:" } };
1363
+ ```
1270
1364
 
1271
1365
  ## Building the Library (for Contributors)
1272
1366
 
@@ -1405,25 +1499,29 @@ Key exports: `connectDoDb`, `DOClientEngine`, and types (`DoDb`, `DocumentFilter
1405
1499
 
1406
1500
  ## Database Configuration
1407
1501
 
1408
- ### SQLite (Node.js)
1502
+ ### SQL.js (Browser / Node.js) — default
1409
1503
 
1410
1504
  ```javascript
1411
1505
  {
1412
- type: 'node-sqlite',
1506
+ type: 'sqljs',
1413
1507
  options: {
1414
- filePath: ':memory:' // or '/path/to/database.db'
1508
+ // Browser: serves /sql-wasm.wasm (place it in public/), or override via
1509
+ // wasmURL / locateFile.
1510
+ // Node.js: resolves sql.js's bundled wasm automatically — no config needed.
1415
1511
  }
1416
1512
  }
1417
1513
  ```
1418
1514
 
1419
- ### SQL.js (Browser/Node.js)
1515
+ ### Native SQLite (Node.js) — `node-sqlite` (better-sqlite3)
1516
+
1517
+ One-line opt-in for native, file-backed SQLite. Requires `better-sqlite3`
1518
+ (`npm install better-sqlite3`):
1420
1519
 
1421
1520
  ```javascript
1422
1521
  {
1423
- type: 'sqljs',
1522
+ type: 'node-sqlite',
1424
1523
  options: {
1425
- // Browser: automatically loads WASM
1426
- // Node.js: fallback option
1524
+ filePath: ':memory:' // or '/path/to/database.db'
1427
1525
  }
1428
1526
  }
1429
1527
  ```