bun-sqlite-for-rxdb 1.0.1
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/.serena/project.yml +84 -0
- package/CHANGELOG.md +300 -0
- package/LICENSE +21 -0
- package/README.md +87 -0
- package/ROADMAP.md +532 -0
- package/benchmarks/benchmark.ts +145 -0
- package/benchmarks/case-insensitive-10runs.ts +156 -0
- package/benchmarks/fts5-1m-scale.ts +126 -0
- package/benchmarks/fts5-before-after.ts +104 -0
- package/benchmarks/indexed-benchmark.ts +141 -0
- package/benchmarks/new-operators-benchmark.ts +140 -0
- package/benchmarks/query-builder-benchmark.ts +88 -0
- package/benchmarks/query-builder-consistency.ts +109 -0
- package/benchmarks/raw-better-sqlite3-10m.ts +85 -0
- package/benchmarks/raw-better-sqlite3.ts +86 -0
- package/benchmarks/raw-bun-sqlite-10m.ts +85 -0
- package/benchmarks/raw-bun-sqlite.ts +86 -0
- package/benchmarks/regex-10runs-all.ts +216 -0
- package/benchmarks/regex-comparison-benchmark.ts +161 -0
- package/benchmarks/regex-real-comparison.ts +213 -0
- package/benchmarks/run-10x.sh +19 -0
- package/benchmarks/smart-regex-benchmark.ts +148 -0
- package/benchmarks/sql-vs-mingo-benchmark.ts +210 -0
- package/benchmarks/sql-vs-mingo-comparison.ts +175 -0
- package/benchmarks/text-vs-jsonb.ts +167 -0
- package/benchmarks/wal-benchmark.ts +112 -0
- package/docs/architectural-patterns.md +1336 -0
- package/docs/id1-testsuite-journey.md +839 -0
- package/docs/official-test-suite-setup.md +393 -0
- package/nul +0 -0
- package/package.json +44 -0
- package/src/changestream.test.ts +182 -0
- package/src/cleanup.test.ts +110 -0
- package/src/collection-isolation.test.ts +74 -0
- package/src/connection-pool.test.ts +102 -0
- package/src/connection-pool.ts +38 -0
- package/src/findDocumentsById.test.ts +122 -0
- package/src/index.ts +2 -0
- package/src/instance.ts +382 -0
- package/src/multi-instance-events.test.ts +204 -0
- package/src/query/and-operator.test.ts +39 -0
- package/src/query/builder.test.ts +96 -0
- package/src/query/builder.ts +154 -0
- package/src/query/elemMatch-operator.test.ts +24 -0
- package/src/query/exists-operator.test.ts +28 -0
- package/src/query/in-operators.test.ts +54 -0
- package/src/query/mod-operator.test.ts +22 -0
- package/src/query/nested-query.test.ts +198 -0
- package/src/query/not-operators.test.ts +49 -0
- package/src/query/operators.test.ts +70 -0
- package/src/query/operators.ts +185 -0
- package/src/query/or-operator.test.ts +68 -0
- package/src/query/regex-escaping-regression.test.ts +43 -0
- package/src/query/regex-operator.test.ts +44 -0
- package/src/query/schema-mapper.ts +27 -0
- package/src/query/size-operator.test.ts +22 -0
- package/src/query/smart-regex.ts +52 -0
- package/src/query/type-operator.test.ts +37 -0
- package/src/query-cache.test.ts +286 -0
- package/src/rxdb-helpers.test.ts +348 -0
- package/src/rxdb-helpers.ts +262 -0
- package/src/schema-version-isolation.test.ts +126 -0
- package/src/statement-manager.ts +69 -0
- package/src/storage.test.ts +589 -0
- package/src/storage.ts +21 -0
- package/src/types.ts +14 -0
- package/test/rxdb-test-suite.ts +27 -0
- package/tsconfig.json +31 -0
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
# RxDB Official Test Suite Setup for Bun
|
|
2
|
+
|
|
3
|
+
**Status:** ✅ 112/112 tests pass (100%)
|
|
4
|
+
**Last Updated:** 2026-02-23
|
|
5
|
+
**RxDB Version:** 16.21.1
|
|
6
|
+
**Bun Version:** 1.3.9+
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Quick Start
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
cd .ignoreFolder/rxdb
|
|
14
|
+
|
|
15
|
+
# 1. Apply fixes to source config
|
|
16
|
+
# (See "Applying Fixes" section below)
|
|
17
|
+
|
|
18
|
+
# 2. Transpile TypeScript to JavaScript
|
|
19
|
+
npm run transpile
|
|
20
|
+
|
|
21
|
+
# 3. Run tests with Mocha through Bun
|
|
22
|
+
DEFAULT_STORAGE=custom NODE_ENV=fast bun run ./node_modules/mocha/bin/mocha test_tmp/unit/rx-storage-implementations.test.js --bail --timeout 60000
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Expected Result:** 112 passing tests
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## The Problem
|
|
30
|
+
|
|
31
|
+
RxDB's official test suite has two Bun compatibility issues:
|
|
32
|
+
|
|
33
|
+
### Issue #1: `node:sqlite` Import
|
|
34
|
+
```javascript
|
|
35
|
+
// test/unit/config.ts - sqlite-trial case
|
|
36
|
+
const nativeSqlitePromise = await import('node:sqlite'); // ❌ Fails in Bun
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Error:** `Could not resolve: "node:sqlite". Maybe you need to "bun install"?`
|
|
40
|
+
|
|
41
|
+
**Why:** Bun uses `bun:sqlite`, not `node:sqlite`. The import fails at parse time even if never executed.
|
|
42
|
+
|
|
43
|
+
### Issue #2: Missing Test Globals
|
|
44
|
+
```javascript
|
|
45
|
+
// Tests expect describe/it/expect as globals (Mocha provides them)
|
|
46
|
+
describe('test suite', () => { // ❌ ReferenceError: describe is not defined
|
|
47
|
+
it('should work', () => {
|
|
48
|
+
expect(true).toBe(true);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Why:** When running Mocha through Bun, globals aren't automatically available unless Mocha is properly initialized.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## The Solution
|
|
58
|
+
|
|
59
|
+
### Fix #1: Skip `node:sqlite` in Bun
|
|
60
|
+
|
|
61
|
+
**File:** `test/unit/config.ts`
|
|
62
|
+
**Location:** sqlite-trial case (around line 305)
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
case 'sqlite-trial':
|
|
66
|
+
if (isBun) {
|
|
67
|
+
return {
|
|
68
|
+
name: storageKey,
|
|
69
|
+
async init() {
|
|
70
|
+
throw new Error('sqlite-trial storage uses node:sqlite which is not compatible with Bun. Use DEFAULT_STORAGE=custom instead.');
|
|
71
|
+
},
|
|
72
|
+
getStorage() {
|
|
73
|
+
throw new Error('sqlite-trial storage is not available in Bun.');
|
|
74
|
+
},
|
|
75
|
+
getPerformanceStorage() {
|
|
76
|
+
throw new Error('sqlite-trial storage is not available in Bun.');
|
|
77
|
+
},
|
|
78
|
+
hasPersistence: false,
|
|
79
|
+
hasMultiInstance: false,
|
|
80
|
+
hasAttachments: false,
|
|
81
|
+
hasReplication: false
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
let initDone = false;
|
|
86
|
+
let sqliteStorage: any;
|
|
87
|
+
let sqliteBasics;
|
|
88
|
+
return {
|
|
89
|
+
name: storageKey,
|
|
90
|
+
async init() {
|
|
91
|
+
if (initDone) return;
|
|
92
|
+
initDone = true;
|
|
93
|
+
|
|
94
|
+
const nativeSqlitePromise = await import('node:sqlite').then(module => module.DatabaseSync);
|
|
95
|
+
// ... rest of init
|
|
96
|
+
},
|
|
97
|
+
// ... rest of config
|
|
98
|
+
};
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Key Points:**
|
|
102
|
+
- Early return when `isBun` is true
|
|
103
|
+
- Prevents `import('node:sqlite')` from being parsed
|
|
104
|
+
- Throws clear error if someone tries to use sqlite-trial in Bun
|
|
105
|
+
|
|
106
|
+
### Fix #2: Conditional Bun Test Imports
|
|
107
|
+
|
|
108
|
+
**File:** `test/unit/config.ts`
|
|
109
|
+
**Location:** After imports (around line 35)
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
import {
|
|
113
|
+
DEFAULT_STORAGE,
|
|
114
|
+
ENV_VARIABLES,
|
|
115
|
+
getConfig,
|
|
116
|
+
isDeno,
|
|
117
|
+
isBun,
|
|
118
|
+
isFastMode,
|
|
119
|
+
isNode,
|
|
120
|
+
setConfig
|
|
121
|
+
} from '../../plugins/test-utils/index.mjs';
|
|
122
|
+
|
|
123
|
+
// Only import Bun test globals if running with native bun test (not mocha)
|
|
124
|
+
if (typeof Bun !== 'undefined' && typeof describe === 'undefined') {
|
|
125
|
+
const { describe: bunDescribe, it: bunIt, expect: bunExpect, beforeEach: bunBeforeEach, afterEach: bunAfterEach } = await import('bun:test');
|
|
126
|
+
globalThis.describe = bunDescribe;
|
|
127
|
+
globalThis.it = bunIt;
|
|
128
|
+
globalThis.expect = bunExpect;
|
|
129
|
+
globalThis.beforeEach = bunBeforeEach;
|
|
130
|
+
globalThis.afterEach = bunAfterEach;
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Key Points:**
|
|
135
|
+
- Only imports Bun test globals if `describe` is undefined
|
|
136
|
+
- Prevents overriding Mocha's globals when running Mocha through Bun
|
|
137
|
+
- Allows both `bun test` and `bun run mocha` to work
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Applying Fixes
|
|
142
|
+
|
|
143
|
+
### Step 1: Add `isBun` to Imports
|
|
144
|
+
|
|
145
|
+
**File:** `test/unit/config.ts` (line ~34)
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
// BEFORE:
|
|
149
|
+
import {
|
|
150
|
+
DEFAULT_STORAGE,
|
|
151
|
+
ENV_VARIABLES,
|
|
152
|
+
getConfig,
|
|
153
|
+
isDeno,
|
|
154
|
+
isFastMode,
|
|
155
|
+
isNode,
|
|
156
|
+
setConfig
|
|
157
|
+
} from '../../plugins/test-utils/index.mjs';
|
|
158
|
+
|
|
159
|
+
// AFTER:
|
|
160
|
+
import {
|
|
161
|
+
DEFAULT_STORAGE,
|
|
162
|
+
ENV_VARIABLES,
|
|
163
|
+
getConfig,
|
|
164
|
+
isDeno,
|
|
165
|
+
isBun, // ← ADD THIS
|
|
166
|
+
isFastMode,
|
|
167
|
+
isNode,
|
|
168
|
+
setConfig
|
|
169
|
+
} from '../../plugins/test-utils/index.mjs';
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Step 2: Add Conditional Bun Test Imports
|
|
173
|
+
|
|
174
|
+
**File:** `test/unit/config.ts` (after imports, around line 35)
|
|
175
|
+
|
|
176
|
+
Add this block:
|
|
177
|
+
```typescript
|
|
178
|
+
if (typeof Bun !== 'undefined' && typeof describe === 'undefined') {
|
|
179
|
+
const { describe: bunDescribe, it: bunIt, expect: bunExpect, beforeEach: bunBeforeEach, afterEach: bunAfterEach } = await import('bun:test');
|
|
180
|
+
globalThis.describe = bunDescribe;
|
|
181
|
+
globalThis.it = bunIt;
|
|
182
|
+
globalThis.expect = bunExpect;
|
|
183
|
+
globalThis.beforeEach = bunBeforeEach;
|
|
184
|
+
globalThis.afterEach = bunAfterEach;
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Step 3: Add Bun Check in sqlite-trial Case
|
|
189
|
+
|
|
190
|
+
**File:** `test/unit/config.ts` (sqlite-trial case, around line 305)
|
|
191
|
+
|
|
192
|
+
Add early return at the start of the case:
|
|
193
|
+
```typescript
|
|
194
|
+
case 'sqlite-trial':
|
|
195
|
+
if (isBun) {
|
|
196
|
+
return {
|
|
197
|
+
name: storageKey,
|
|
198
|
+
async init() {
|
|
199
|
+
throw new Error('sqlite-trial storage uses node:sqlite which is not compatible with Bun. Use DEFAULT_STORAGE=custom instead.');
|
|
200
|
+
},
|
|
201
|
+
getStorage() {
|
|
202
|
+
throw new Error('sqlite-trial storage is not available in Bun.');
|
|
203
|
+
},
|
|
204
|
+
getPerformanceStorage() {
|
|
205
|
+
throw new Error('sqlite-trial storage is not available in Bun.');
|
|
206
|
+
},
|
|
207
|
+
hasPersistence: false,
|
|
208
|
+
hasMultiInstance: false,
|
|
209
|
+
hasAttachments: false,
|
|
210
|
+
hasReplication: false
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// ... existing code continues
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Step 4: Transpile
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
cd .ignoreFolder/rxdb
|
|
221
|
+
npm run transpile
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
This regenerates `test_tmp/unit/config.js` with your fixes.
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Running Tests
|
|
229
|
+
|
|
230
|
+
### Method 1: Mocha through Bun (Recommended)
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
cd .ignoreFolder/rxdb
|
|
234
|
+
DEFAULT_STORAGE=custom NODE_ENV=fast bun run ./node_modules/mocha/bin/mocha test_tmp/unit/rx-storage-implementations.test.js --bail --timeout 60000
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
**Result:** 112/112 tests pass ✅
|
|
238
|
+
|
|
239
|
+
**Why this works:**
|
|
240
|
+
- Runs Mocha's test runner through Bun's runtime
|
|
241
|
+
- Mocha provides its own globals (describe/it/expect)
|
|
242
|
+
- Mocha supports `this.timeout()` and other Mocha-specific features
|
|
243
|
+
- Our conditional imports don't interfere (describe is already defined)
|
|
244
|
+
|
|
245
|
+
### Method 2: Native Bun Test (Alternative)
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
cd .ignoreFolder/rxdb
|
|
249
|
+
DEFAULT_STORAGE=custom bun test test_tmp/unit/rx-storage-implementations.test.js
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
**Result:** 55/56 tests pass (98.2%)
|
|
253
|
+
|
|
254
|
+
**Why one test fails:**
|
|
255
|
+
- One test uses `this.timeout(30 * 1000)` which is Mocha-specific
|
|
256
|
+
- Bun's test framework doesn't support `this.timeout()`
|
|
257
|
+
- Bun uses Jest-style timeouts: `test('name', () => {}, 30000)`
|
|
258
|
+
|
|
259
|
+
**When to use:**
|
|
260
|
+
- Quick smoke tests
|
|
261
|
+
- When you don't need 100% compatibility
|
|
262
|
+
- When testing Bun-specific features
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## Test Commands Reference
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
# Full test suite (all storages)
|
|
270
|
+
npm run test
|
|
271
|
+
|
|
272
|
+
# Transpile TypeScript
|
|
273
|
+
npm run transpile
|
|
274
|
+
|
|
275
|
+
# Test with custom storage (our Bun SQLite adapter)
|
|
276
|
+
DEFAULT_STORAGE=custom NODE_ENV=fast bun run ./node_modules/mocha/bin/mocha test_tmp/unit/rx-storage-implementations.test.js --bail --timeout 60000
|
|
277
|
+
|
|
278
|
+
# Test with native bun test (55/56 pass)
|
|
279
|
+
DEFAULT_STORAGE=custom bun test test_tmp/unit/rx-storage-implementations.test.js
|
|
280
|
+
|
|
281
|
+
# Test specific storage (from package.json)
|
|
282
|
+
npm run test:bun:dexie
|
|
283
|
+
npm run test:bun:memory
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## Troubleshooting
|
|
289
|
+
|
|
290
|
+
### Error: `Could not resolve: "node:sqlite"`
|
|
291
|
+
|
|
292
|
+
**Cause:** You didn't apply Fix #1 or didn't transpile after applying it.
|
|
293
|
+
|
|
294
|
+
**Solution:**
|
|
295
|
+
1. Add Bun check in sqlite-trial case (see Fix #1)
|
|
296
|
+
2. Run `npm run transpile`
|
|
297
|
+
3. Verify fix is in `test_tmp/unit/config.js`
|
|
298
|
+
|
|
299
|
+
### Error: `describe is not defined`
|
|
300
|
+
|
|
301
|
+
**Cause:** You didn't apply Fix #2 or didn't transpile after applying it.
|
|
302
|
+
|
|
303
|
+
**Solution:**
|
|
304
|
+
1. Add conditional Bun imports (see Fix #2)
|
|
305
|
+
2. Run `npm run transpile`
|
|
306
|
+
3. Verify imports are in `test_tmp/unit/config.js`
|
|
307
|
+
|
|
308
|
+
### Error: `0 passing tests` when running Mocha
|
|
309
|
+
|
|
310
|
+
**Cause:** Bun test globals are overriding Mocha's globals.
|
|
311
|
+
|
|
312
|
+
**Solution:**
|
|
313
|
+
- Check that conditional import has `typeof describe === 'undefined'` check
|
|
314
|
+
- This prevents Bun imports when Mocha already provides globals
|
|
315
|
+
|
|
316
|
+
### Tests pass locally but fail after `npm run transpile`
|
|
317
|
+
|
|
318
|
+
**Cause:** You edited `test_tmp/unit/config.js` directly (transpiled output).
|
|
319
|
+
|
|
320
|
+
**Solution:**
|
|
321
|
+
- Always edit `test/unit/config.ts` (source file)
|
|
322
|
+
- Then run `npm run transpile` to regenerate output
|
|
323
|
+
- Never edit files in `test_tmp/` directly
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## Architecture Notes
|
|
328
|
+
|
|
329
|
+
### Why Mocha Through Bun?
|
|
330
|
+
|
|
331
|
+
RxDB's test suite is designed for Mocha:
|
|
332
|
+
- Uses Mocha's `describe/it/expect` globals
|
|
333
|
+
- Uses Mocha-specific features (`this.timeout()`, `this.skip()`)
|
|
334
|
+
- Uses `mocha.parallel` for parallel test execution
|
|
335
|
+
- Has `.mocharc.cjs` configuration
|
|
336
|
+
|
|
337
|
+
**Running Mocha through Bun gives us:**
|
|
338
|
+
- ✅ Full Mocha compatibility (100% tests pass)
|
|
339
|
+
- ✅ Bun's fast runtime (faster than Node.js)
|
|
340
|
+
- ✅ Access to Bun-specific APIs (`bun:sqlite`)
|
|
341
|
+
- ✅ No test rewrites needed
|
|
342
|
+
|
|
343
|
+
### Why Not Native `bun test`?
|
|
344
|
+
|
|
345
|
+
Bun's test framework is Jest/Vitest-compatible, not Mocha-compatible:
|
|
346
|
+
- Different timeout syntax
|
|
347
|
+
- Different global setup
|
|
348
|
+
- Different assertion library
|
|
349
|
+
- Would require rewriting all tests
|
|
350
|
+
|
|
351
|
+
**Use native `bun test` when:**
|
|
352
|
+
- Writing new Bun-specific tests
|
|
353
|
+
- Quick smoke tests (98.2% pass rate is acceptable)
|
|
354
|
+
- Testing Bun-specific features
|
|
355
|
+
|
|
356
|
+
### Why Conditional Imports?
|
|
357
|
+
|
|
358
|
+
```typescript
|
|
359
|
+
if (typeof Bun !== 'undefined' && typeof describe === 'undefined') {
|
|
360
|
+
// Import Bun test globals
|
|
361
|
+
}
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
**The check ensures:**
|
|
365
|
+
1. `typeof Bun !== 'undefined'` → We're running in Bun
|
|
366
|
+
2. `typeof describe === 'undefined'` → Mocha hasn't provided globals yet
|
|
367
|
+
|
|
368
|
+
**This allows:**
|
|
369
|
+
- `bun test` → Imports Bun globals (describe is undefined)
|
|
370
|
+
- `bun run mocha` → Skips import (describe already defined by Mocha)
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## Related Documentation
|
|
375
|
+
|
|
376
|
+
- [id1-testsuite-journey.md](./id1-testsuite-journey.md) - Debugging journey (Iterations 1-14)
|
|
377
|
+
- [architectural-patterns.md](./architectural-patterns.md) - Storage adapter patterns
|
|
378
|
+
- [RxDB Official Docs](https://rxdb.info/) - RxDB documentation
|
|
379
|
+
- [Bun Test Docs](https://bun.sh/docs/test/writing-tests) - Bun test framework
|
|
380
|
+
|
|
381
|
+
---
|
|
382
|
+
|
|
383
|
+
## Changelog
|
|
384
|
+
|
|
385
|
+
### 2026-02-23 - Initial Setup
|
|
386
|
+
- Added Bun compatibility fixes to config.ts
|
|
387
|
+
- Documented test setup process
|
|
388
|
+
- Achieved 112/112 tests passing with Mocha through Bun
|
|
389
|
+
- Documented alternative native `bun test` approach (55/56 pass)
|
|
390
|
+
|
|
391
|
+
---
|
|
392
|
+
|
|
393
|
+
_Last updated: 2026-02-23 by adam2am_
|
package/nul
ADDED
|
File without changes
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "bun-sqlite-for-rxdb",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"author": "adam2am",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/adam2am/bun-sqlite-for-rxdb.git"
|
|
8
|
+
},
|
|
9
|
+
"main": "dist/index.js",
|
|
10
|
+
"devDependencies": {
|
|
11
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
12
|
+
"@types/bun": "latest",
|
|
13
|
+
"@types/fast-stable-stringify": "^1.0.0",
|
|
14
|
+
"better-sqlite3": "^12.6.2",
|
|
15
|
+
"rxdb": "^16.21.1",
|
|
16
|
+
"typescript": "^5.0.0"
|
|
17
|
+
},
|
|
18
|
+
"peerDependencies": {
|
|
19
|
+
"rxdb": "^16.0.0 || ^17.0.0-beta"
|
|
20
|
+
},
|
|
21
|
+
"description": "RxDB storage adapter for Bun's native SQLite (bun:sqlite)",
|
|
22
|
+
"keywords": [
|
|
23
|
+
"rxdb",
|
|
24
|
+
"sqlite",
|
|
25
|
+
"bun",
|
|
26
|
+
"bun:sqlite",
|
|
27
|
+
"storage",
|
|
28
|
+
"adapter",
|
|
29
|
+
"database",
|
|
30
|
+
"reactive"
|
|
31
|
+
],
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "bun build src/index.ts --outdir dist --target bun",
|
|
35
|
+
"test": "bun test src/",
|
|
36
|
+
"typecheck": "tsc --noEmit"
|
|
37
|
+
},
|
|
38
|
+
"type": "module",
|
|
39
|
+
"types": "dist/index.d.ts",
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"fast-stable-stringify": "^1.0.0",
|
|
42
|
+
"mingo": "^7.2.0"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { describe, test, expect, afterEach } from 'bun:test';
|
|
2
|
+
import { getRxStorageBunSQLite } from './index';
|
|
3
|
+
import type { RxStorageInstance, EventBulk, RxStorageChangeEvent, RxDocumentData, RxStorageDefaultCheckpoint } from 'rxdb';
|
|
4
|
+
|
|
5
|
+
interface TestDoc {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
describe('Storage Instance ChangeStream', () => {
|
|
11
|
+
const instances: RxStorageInstance<TestDoc, unknown, unknown>[] = [];
|
|
12
|
+
|
|
13
|
+
afterEach(async () => {
|
|
14
|
+
for (const instance of instances) {
|
|
15
|
+
await instance.close();
|
|
16
|
+
}
|
|
17
|
+
instances.length = 0;
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test('bulkWrite emits to changeStream', async () => {
|
|
21
|
+
const storage = getRxStorageBunSQLite();
|
|
22
|
+
const instance = await storage.createStorageInstance<TestDoc>({
|
|
23
|
+
databaseName: 'testdb',
|
|
24
|
+
collectionName: 'users',
|
|
25
|
+
databaseInstanceToken: 'test-token',
|
|
26
|
+
schema: {
|
|
27
|
+
version: 0,
|
|
28
|
+
primaryKey: 'id',
|
|
29
|
+
type: 'object',
|
|
30
|
+
properties: {
|
|
31
|
+
id: { type: 'string', maxLength: 100 },
|
|
32
|
+
name: { type: 'string' },
|
|
33
|
+
_deleted: { type: 'boolean' },
|
|
34
|
+
_attachments: { type: 'object' },
|
|
35
|
+
_rev: { type: 'string' },
|
|
36
|
+
_meta: { type: 'object' }
|
|
37
|
+
},
|
|
38
|
+
required: ['id', 'name']
|
|
39
|
+
},
|
|
40
|
+
options: {},
|
|
41
|
+
devMode: false,
|
|
42
|
+
multiInstance: false
|
|
43
|
+
});
|
|
44
|
+
instances.push(instance);
|
|
45
|
+
|
|
46
|
+
const events: EventBulk<RxStorageChangeEvent<TestDoc>, unknown>[] = [];
|
|
47
|
+
instance.changeStream().subscribe(ev => events.push(ev));
|
|
48
|
+
|
|
49
|
+
const doc: RxDocumentData<TestDoc> = {
|
|
50
|
+
id: 'user1',
|
|
51
|
+
name: 'Alice',
|
|
52
|
+
_deleted: false,
|
|
53
|
+
_attachments: {},
|
|
54
|
+
_meta: { lwt: Date.now() },
|
|
55
|
+
_rev: '1-abc'
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
await instance.bulkWrite([{ document: doc }], 'test-context');
|
|
59
|
+
|
|
60
|
+
expect(events.length).toBe(1);
|
|
61
|
+
expect(events[0].events.length).toBe(1);
|
|
62
|
+
expect(events[0].events[0].operation).toBe('INSERT');
|
|
63
|
+
expect(events[0].events[0].documentId).toBe('user1');
|
|
64
|
+
expect(events[0].events[0].documentData.name).toBe('Alice');
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test('bulkWrite with multiple documents emits all events', async () => {
|
|
68
|
+
const storage = getRxStorageBunSQLite();
|
|
69
|
+
const instance = await storage.createStorageInstance<TestDoc>({
|
|
70
|
+
databaseName: 'testdb',
|
|
71
|
+
collectionName: 'users',
|
|
72
|
+
databaseInstanceToken: 'test-token',
|
|
73
|
+
schema: {
|
|
74
|
+
version: 0,
|
|
75
|
+
primaryKey: 'id',
|
|
76
|
+
type: 'object',
|
|
77
|
+
properties: {
|
|
78
|
+
id: { type: 'string', maxLength: 100 },
|
|
79
|
+
name: { type: 'string' },
|
|
80
|
+
_deleted: { type: 'boolean' },
|
|
81
|
+
_attachments: { type: 'object' },
|
|
82
|
+
_rev: { type: 'string' },
|
|
83
|
+
_meta: { type: 'object' }
|
|
84
|
+
},
|
|
85
|
+
required: ['id', 'name']
|
|
86
|
+
},
|
|
87
|
+
options: {},
|
|
88
|
+
devMode: false,
|
|
89
|
+
multiInstance: false
|
|
90
|
+
});
|
|
91
|
+
instances.push(instance);
|
|
92
|
+
|
|
93
|
+
const events: EventBulk<RxStorageChangeEvent<TestDoc>, unknown>[] = [];
|
|
94
|
+
instance.changeStream().subscribe(ev => events.push(ev));
|
|
95
|
+
|
|
96
|
+
const docs: RxDocumentData<TestDoc>[] = [
|
|
97
|
+
{
|
|
98
|
+
id: 'user1',
|
|
99
|
+
name: 'Alice',
|
|
100
|
+
_deleted: false,
|
|
101
|
+
_attachments: {},
|
|
102
|
+
_meta: { lwt: Date.now() },
|
|
103
|
+
_rev: '1-abc'
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
id: 'user2',
|
|
107
|
+
name: 'Bob',
|
|
108
|
+
_deleted: false,
|
|
109
|
+
_attachments: {},
|
|
110
|
+
_meta: { lwt: Date.now() + 1 },
|
|
111
|
+
_rev: '1-def'
|
|
112
|
+
}
|
|
113
|
+
];
|
|
114
|
+
|
|
115
|
+
await instance.bulkWrite(
|
|
116
|
+
docs.map(document => ({ document })),
|
|
117
|
+
'test-context'
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
expect(events.length).toBe(1);
|
|
121
|
+
expect(events[0].events.length).toBe(2);
|
|
122
|
+
expect(events[0].events[0].operation).toBe('INSERT');
|
|
123
|
+
expect(events[0].events[1].operation).toBe('INSERT');
|
|
124
|
+
expect(events[0].events[0].documentId).toBe('user1');
|
|
125
|
+
expect(events[0].events[1].documentId).toBe('user2');
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test('UPDATE operation emits to changeStream', async () => {
|
|
129
|
+
const storage = getRxStorageBunSQLite();
|
|
130
|
+
const instance = await storage.createStorageInstance<TestDoc>({
|
|
131
|
+
databaseName: 'testdb',
|
|
132
|
+
collectionName: 'users',
|
|
133
|
+
databaseInstanceToken: 'test-token',
|
|
134
|
+
schema: {
|
|
135
|
+
version: 0,
|
|
136
|
+
primaryKey: 'id',
|
|
137
|
+
type: 'object',
|
|
138
|
+
properties: {
|
|
139
|
+
id: { type: 'string', maxLength: 100 },
|
|
140
|
+
name: { type: 'string' },
|
|
141
|
+
_deleted: { type: 'boolean' },
|
|
142
|
+
_attachments: { type: 'object' },
|
|
143
|
+
_rev: { type: 'string' },
|
|
144
|
+
_meta: { type: 'object' }
|
|
145
|
+
},
|
|
146
|
+
required: ['id', 'name']
|
|
147
|
+
},
|
|
148
|
+
options: {},
|
|
149
|
+
devMode: false,
|
|
150
|
+
multiInstance: false
|
|
151
|
+
});
|
|
152
|
+
instances.push(instance);
|
|
153
|
+
|
|
154
|
+
const doc: RxDocumentData<TestDoc> = {
|
|
155
|
+
id: 'user1',
|
|
156
|
+
name: 'Alice',
|
|
157
|
+
_deleted: false,
|
|
158
|
+
_attachments: {},
|
|
159
|
+
_meta: { lwt: Date.now() },
|
|
160
|
+
_rev: '1-abc'
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
await instance.bulkWrite([{ document: doc }], 'test-context');
|
|
164
|
+
|
|
165
|
+
const events: EventBulk<RxStorageChangeEvent<TestDoc>, unknown>[] = [];
|
|
166
|
+
instance.changeStream().subscribe(ev => events.push(ev));
|
|
167
|
+
|
|
168
|
+
const updatedDoc: RxDocumentData<TestDoc> = {
|
|
169
|
+
...doc,
|
|
170
|
+
name: 'Alice Updated',
|
|
171
|
+
_meta: { lwt: Date.now() + 1 },
|
|
172
|
+
_rev: '2-def'
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
await instance.bulkWrite([{ document: updatedDoc, previous: doc }], 'test-context');
|
|
176
|
+
|
|
177
|
+
expect(events.length).toBe(1);
|
|
178
|
+
expect(events[0].events[0].operation).toBe('UPDATE');
|
|
179
|
+
expect(events[0].events[0].documentData.name).toBe('Alice Updated');
|
|
180
|
+
expect(events[0].events[0].previousDocumentData?.name).toBe('Alice');
|
|
181
|
+
});
|
|
182
|
+
});
|