@quereus/plugin-nativescript-sqlite 4.14.0 → 4.15.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/README.md CHANGED
@@ -1,231 +1,231 @@
1
- # @quereus/plugin-nativescript-sqlite
2
-
3
- > **Stability: Beta** — complete and tested, but the surface is still being shaped; a
4
- > breaking change may land in a minor release. It rides `@quereus/store`'s on-disk key
5
- > encoding, which is not frozen. See [Stability Tiers](../../docs/stability.md#tiers).
6
-
7
- SQLite storage plugin for Quereus on NativeScript. Provides persistent storage for iOS and Android mobile apps using the [`@quereus/store`](../quereus-store/) module.
8
-
9
- ## Features
10
-
11
- - **Native SQLite**: Uses the device's built-in SQLite via `@nativescript-community/sqlite`
12
- - **Transaction isolation**: Read-committed + read-your-own-writes by default (no write-write conflict detection; not snapshot isolation)
13
- - **Order-preserving keys**: BLOB keys with `memcmp()` comparison ensure correct lexicographic byte ordering
14
- - **Single database file**: All stores share one SQLite database (separate tables)
15
- - **ACID transactions**: SQLite transactions for atomic batch writes
16
- - **WITHOUT ROWID**: Optimized key-value table structure
17
-
18
- ## Table naming
19
-
20
- Each logical store — a table's row data, or one of its secondary indexes — gets its own
21
- SQLite table. The name comes from `@quereus/store`'s shared builders and is then escaped
22
- into a legal bare SQLite identifier: digits and `a`-`z` pass through, every other byte
23
- becomes `_XX` (uppercase hex of the UTF-8 byte). `_` is therefore always an escape
24
- introducer and never a literal, which is what makes the escape reversible in principle — so
25
- two differently-named tables can never land on one SQLite table.
26
-
27
- | Logical store | SQLite table |
28
- | --- | --- |
29
- | table `t` in schema `main` | `quereus_main_2Et` |
30
- | table `a-b` in schema `main` | `quereus_main_2Ea_2Db` |
31
- | table `a b` in schema `main` | `quereus_main_2Ea_20b` |
32
- | index `x` on table `t` | `quereus_main_2Et_5Fidx_5Fx` |
33
- | table `café` in schema `main` | `quereus_main_2Ecaf_C3_A9` |
34
- | unified stats | `quereus___stats__` |
35
- | catalog (DDL) | `quereus___catalog__` |
36
-
37
- The two reserved tables are deliberately **not** escaped, which is what keeps them
38
- unreachable from any user table: an escaped name can never contain a bare `_` followed by a
39
- non-hex character, so no table name can produce `__stats__` or `__catalog__`. The
40
- `quereus_` part is the configurable `tablePrefix`.
41
-
42
- > **Hard cutover (no on-disk migration).** An earlier version named its tables
43
- > `{prefix}{schema}_{table}` with every character outside `[a-zA-Z0-9_]` folded to `_`.
44
- > That mapping was many-to-one — tables `a-b` and `a b` shared one SQLite table and
45
- > interleaved their rows — so it has been replaced outright. Databases written by the older
46
- > version are **not** read by this version and must be re-created. Pre-1.0 dev data is
47
- > expected to be thrown away; there is no migration importer.
48
-
49
- ## Installation
50
-
51
- ```bash
52
- npm install @quereus/plugin-nativescript-sqlite @quereus/store @quereus/isolation @nativescript-community/sqlite
53
- ```
54
-
55
- Or with NativeScript CLI:
56
-
57
- ```bash
58
- ns plugin add @quereus/plugin-nativescript-sqlite
59
- ns plugin add @nativescript-community/sqlite
60
- ```
61
-
62
- ## Quick Start
63
-
64
- ### With registerPlugin (Recommended)
65
-
66
- ```typescript
67
- import { openOrCreate } from '@nativescript-community/sqlite';
68
- import { Database, registerPlugin } from '@quereus/quereus';
69
- import sqlitePlugin from '@quereus/plugin-nativescript-sqlite/plugin';
70
-
71
- // Open or create the SQLite database
72
- const sqliteDb = openOrCreate('quereus.db');
73
-
74
- // Create Quereus database and register the plugin
75
- const db = new Database();
76
- await registerPlugin(db, sqlitePlugin, { db: sqliteDb });
77
-
78
- // Create tables using the 'store' module
79
- await db.exec(`
80
- create table users (id integer primary key, name text)
81
- using store
82
- `);
83
-
84
- // Full transaction isolation enabled by default
85
- await db.exec('BEGIN');
86
- await db.exec(`insert into users values (1, 'Alice')`);
87
- const user = await db.get(`select * from users where id = 1`); // Sees uncommitted insert
88
- await db.exec('COMMIT');
89
- ```
90
-
91
- ### Disabling Isolation
92
-
93
- If you need maximum performance and don't require read-your-own-writes within transactions:
94
-
95
- ```typescript
96
- await registerPlugin(db, sqlitePlugin, {
97
- db: sqliteDb,
98
- isolation: false // Disable isolation layer
99
- });
100
- ```
101
-
102
- ### Direct Usage with Provider
103
-
104
- ```typescript
105
- import { openOrCreate } from '@nativescript-community/sqlite';
106
- import { Database } from '@quereus/quereus';
107
- import { createSQLiteProvider } from '@quereus/plugin-nativescript-sqlite';
108
- import { createIsolatedStoreModule } from '@quereus/store';
109
-
110
-
111
- const sqliteDb = openOrCreate('quereus.db');
112
- const provider = createSQLiteProvider({ db: sqliteDb });
113
- const storeModule = new StoreModule(provider);
114
-
115
- const db = new Database();
116
- db.registerModule('store', storeModule);
117
-
118
- await db.exec(`
119
- create table users (id integer primary key, name text)
120
- using store
121
- `);
122
- ```
123
-
124
- ## API
125
-
126
- ### SQLiteStore
127
-
128
- Low-level KVStore implementation backed by a SQLite table:
129
-
130
- ```typescript
131
- import { openOrCreate } from '@nativescript-community/sqlite';
132
- import { SQLiteStore } from '@quereus/plugin-nativescript-sqlite';
133
-
134
- const sqliteDb = openOrCreate('myapp.db');
135
- const store = SQLiteStore.create(sqliteDb, 'my_kv_table');
136
-
137
- // Key-value operations (keys and values are Uint8Array)
138
- await store.put(key, value);
139
- const data = await store.get(key);
140
- await store.delete(key);
141
-
142
- // Range iteration
143
- for await (const { key, value } of store.iterate({ gte: startKey, lt: endKey })) {
144
- console.log(key, value);
145
- }
146
-
147
- // Batch writes (atomic)
148
- const batch = store.batch();
149
- batch.put(key1, value1);
150
- batch.put(key2, value2);
151
- batch.delete(key3);
152
- await batch.write();
153
-
154
- await store.close();
155
- ```
156
-
157
- ### SQLiteProvider
158
-
159
- Factory for managing multiple stores in a single SQLite database:
160
-
161
- ```typescript
162
- import { openOrCreate } from '@nativescript-community/sqlite';
163
- import { createSQLiteProvider } from '@quereus/plugin-nativescript-sqlite';
164
-
165
- const sqliteDb = openOrCreate('quereus.db');
166
- const provider = createSQLiteProvider({ db: sqliteDb });
167
-
168
- // Each store gets its own table: quereus_main_2Eusers, quereus_main_2Eorders, etc.
169
- // (see "Table naming" above for how the name is escaped)
170
- const userStore = await provider.getStore('main', 'users');
171
- const orderStore = await provider.getStore('main', 'orders');
172
- const catalogStore = await provider.getCatalogStore();
173
-
174
- await provider.closeStore('main', 'users');
175
- await provider.closeAll(); // Also closes the SQLite database
176
- ```
177
-
178
- ## Configuration
179
-
180
- ### Plugin Settings
181
-
182
- | Setting | Type | Default | Description |
183
- |---------|------|---------|-------------|
184
- | `db` | SQLiteDatabase | **required** | SQLite database from `openOrCreate()` |
185
- | `tablePrefix` | string | `'quereus_'` | Prefix for all table names |
186
- | `moduleName` | string | `'store'` | Virtual table module name for `USING` clause |
187
-
188
- ### SQLiteStore Options
189
-
190
- | Option | Type | Default | Description |
191
- |--------|------|---------|-------------|
192
- | `db` | SQLiteDatabase | **required** | The SQLite database instance |
193
- | `tableName` | string | `'kv'` | Table name for this store |
194
-
195
- ## How It Works
196
-
197
- ### Key Storage
198
-
199
- Keys and values are stored as BLOBs (binary). SQLite compares BLOBs using `memcmp()`, which provides correct lexicographic byte ordering - exactly what's needed for range scans.
200
-
201
- ### Table Structure
202
-
203
- Each store creates a table with this schema:
204
-
205
- ```sql
206
- create table quereus_main_2Eusers (
207
- key blob primary key,
208
- value blob
209
- ) without rowid
210
- ```
211
-
212
- The `WITHOUT ROWID` optimization is ideal for key-value workloads where the key is the primary lookup.
213
-
214
- ## Platform Support
215
-
216
- | Platform | Status |
217
- |----------|--------|
218
- | iOS | ✅ Supported |
219
- | Android | ✅ Supported |
220
- | NativeScript 8+ | ✅ Supported |
221
-
222
- ## Related Packages
223
-
224
- - [`@quereus/store`](../quereus-store/) - Core storage module (StoreModule, StoreTable)
225
- - [`@quereus/plugin-leveldb`](../quereus-plugin-leveldb/) - LevelDB plugin for Node.js
226
- - [`@quereus/plugin-indexeddb`](../quereus-plugin-indexeddb/) - IndexedDB plugin for browsers
227
-
228
- ## License
229
-
230
- MIT
231
-
1
+ # @quereus/plugin-nativescript-sqlite
2
+
3
+ > **Stability: Beta** — complete and tested, but the surface is still being shaped; a
4
+ > breaking change may land in a minor release. It rides `@quereus/store`'s on-disk key
5
+ > encoding, which is not frozen. See [Stability Tiers](../../docs/stability.md#tiers).
6
+
7
+ SQLite storage plugin for Quereus on NativeScript. Provides persistent storage for iOS and Android mobile apps using the [`@quereus/store`](../quereus-store/) module.
8
+
9
+ ## Features
10
+
11
+ - **Native SQLite**: Uses the device's built-in SQLite via `@nativescript-community/sqlite`
12
+ - **Transaction isolation**: Read-committed + read-your-own-writes by default (no write-write conflict detection; not snapshot isolation)
13
+ - **Order-preserving keys**: BLOB keys with `memcmp()` comparison ensure correct lexicographic byte ordering
14
+ - **Single database file**: All stores share one SQLite database (separate tables)
15
+ - **ACID transactions**: SQLite transactions for atomic batch writes
16
+ - **WITHOUT ROWID**: Optimized key-value table structure
17
+
18
+ ## Table naming
19
+
20
+ Each logical store — a table's row data, or one of its secondary indexes — gets its own
21
+ SQLite table. The name comes from `@quereus/store`'s shared builders and is then escaped
22
+ into a legal bare SQLite identifier: digits and `a`-`z` pass through, every other byte
23
+ becomes `_XX` (uppercase hex of the UTF-8 byte). `_` is therefore always an escape
24
+ introducer and never a literal, which is what makes the escape reversible in principle — so
25
+ two differently-named tables can never land on one SQLite table.
26
+
27
+ | Logical store | SQLite table |
28
+ | --- | --- |
29
+ | table `t` in schema `main` | `quereus_main_2Et` |
30
+ | table `a-b` in schema `main` | `quereus_main_2Ea_2Db` |
31
+ | table `a b` in schema `main` | `quereus_main_2Ea_20b` |
32
+ | index `x` on table `t` | `quereus_main_2Et_5Fidx_5Fx` |
33
+ | table `café` in schema `main` | `quereus_main_2Ecaf_C3_A9` |
34
+ | unified stats | `quereus___stats__` |
35
+ | catalog (DDL) | `quereus___catalog__` |
36
+
37
+ The two reserved tables are deliberately **not** escaped, which is what keeps them
38
+ unreachable from any user table: an escaped name can never contain a bare `_` followed by a
39
+ non-hex character, so no table name can produce `__stats__` or `__catalog__`. The
40
+ `quereus_` part is the configurable `tablePrefix`.
41
+
42
+ > **Hard cutover (no on-disk migration).** An earlier version named its tables
43
+ > `{prefix}{schema}_{table}` with every character outside `[a-zA-Z0-9_]` folded to `_`.
44
+ > That mapping was many-to-one — tables `a-b` and `a b` shared one SQLite table and
45
+ > interleaved their rows — so it has been replaced outright. Databases written by the older
46
+ > version are **not** read by this version and must be re-created. Pre-1.0 dev data is
47
+ > expected to be thrown away; there is no migration importer.
48
+
49
+ ## Installation
50
+
51
+ ```bash
52
+ npm install @quereus/plugin-nativescript-sqlite @quereus/store @quereus/isolation @nativescript-community/sqlite
53
+ ```
54
+
55
+ Or with NativeScript CLI:
56
+
57
+ ```bash
58
+ ns plugin add @quereus/plugin-nativescript-sqlite
59
+ ns plugin add @nativescript-community/sqlite
60
+ ```
61
+
62
+ ## Quick Start
63
+
64
+ ### With registerPlugin (Recommended)
65
+
66
+ ```typescript
67
+ import { openOrCreate } from '@nativescript-community/sqlite';
68
+ import { Database, registerPlugin } from '@quereus/quereus';
69
+ import sqlitePlugin from '@quereus/plugin-nativescript-sqlite/plugin';
70
+
71
+ // Open or create the SQLite database
72
+ const sqliteDb = openOrCreate('quereus.db');
73
+
74
+ // Create Quereus database and register the plugin
75
+ const db = new Database();
76
+ await registerPlugin(db, sqlitePlugin, { db: sqliteDb });
77
+
78
+ // Create tables using the 'store' module
79
+ await db.exec(`
80
+ create table users (id integer primary key, name text)
81
+ using store
82
+ `);
83
+
84
+ // Full transaction isolation enabled by default
85
+ await db.exec('BEGIN');
86
+ await db.exec(`insert into users values (1, 'Alice')`);
87
+ const user = await db.get(`select * from users where id = 1`); // Sees uncommitted insert
88
+ await db.exec('COMMIT');
89
+ ```
90
+
91
+ ### Disabling Isolation
92
+
93
+ If you need maximum performance and don't require read-your-own-writes within transactions:
94
+
95
+ ```typescript
96
+ await registerPlugin(db, sqlitePlugin, {
97
+ db: sqliteDb,
98
+ isolation: false // Disable isolation layer
99
+ });
100
+ ```
101
+
102
+ ### Direct Usage with Provider
103
+
104
+ ```typescript
105
+ import { openOrCreate } from '@nativescript-community/sqlite';
106
+ import { Database } from '@quereus/quereus';
107
+ import { createSQLiteProvider } from '@quereus/plugin-nativescript-sqlite';
108
+ import { createIsolatedStoreModule } from '@quereus/store';
109
+
110
+
111
+ const sqliteDb = openOrCreate('quereus.db');
112
+ const provider = createSQLiteProvider({ db: sqliteDb });
113
+ const storeModule = new StoreModule(provider);
114
+
115
+ const db = new Database();
116
+ db.registerModule('store', storeModule);
117
+
118
+ await db.exec(`
119
+ create table users (id integer primary key, name text)
120
+ using store
121
+ `);
122
+ ```
123
+
124
+ ## API
125
+
126
+ ### SQLiteStore
127
+
128
+ Low-level KVStore implementation backed by a SQLite table:
129
+
130
+ ```typescript
131
+ import { openOrCreate } from '@nativescript-community/sqlite';
132
+ import { SQLiteStore } from '@quereus/plugin-nativescript-sqlite';
133
+
134
+ const sqliteDb = openOrCreate('myapp.db');
135
+ const store = SQLiteStore.create(sqliteDb, 'my_kv_table');
136
+
137
+ // Key-value operations (keys and values are Uint8Array)
138
+ await store.put(key, value);
139
+ const data = await store.get(key);
140
+ await store.delete(key);
141
+
142
+ // Range iteration
143
+ for await (const { key, value } of store.iterate({ gte: startKey, lt: endKey })) {
144
+ console.log(key, value);
145
+ }
146
+
147
+ // Batch writes (atomic)
148
+ const batch = store.batch();
149
+ batch.put(key1, value1);
150
+ batch.put(key2, value2);
151
+ batch.delete(key3);
152
+ await batch.write();
153
+
154
+ await store.close();
155
+ ```
156
+
157
+ ### SQLiteProvider
158
+
159
+ Factory for managing multiple stores in a single SQLite database:
160
+
161
+ ```typescript
162
+ import { openOrCreate } from '@nativescript-community/sqlite';
163
+ import { createSQLiteProvider } from '@quereus/plugin-nativescript-sqlite';
164
+
165
+ const sqliteDb = openOrCreate('quereus.db');
166
+ const provider = createSQLiteProvider({ db: sqliteDb });
167
+
168
+ // Each store gets its own table: quereus_main_2Eusers, quereus_main_2Eorders, etc.
169
+ // (see "Table naming" above for how the name is escaped)
170
+ const userStore = await provider.getStore('main', 'users');
171
+ const orderStore = await provider.getStore('main', 'orders');
172
+ const catalogStore = await provider.getCatalogStore();
173
+
174
+ await provider.closeStore('main', 'users');
175
+ await provider.closeAll(); // Also closes the SQLite database
176
+ ```
177
+
178
+ ## Configuration
179
+
180
+ ### Plugin Settings
181
+
182
+ | Setting | Type | Default | Description |
183
+ |---------|------|---------|-------------|
184
+ | `db` | SQLiteDatabase | **required** | SQLite database from `openOrCreate()` |
185
+ | `tablePrefix` | string | `'quereus_'` | Prefix for all table names |
186
+ | `moduleName` | string | `'store'` | Virtual table module name for `USING` clause |
187
+
188
+ ### SQLiteStore Options
189
+
190
+ | Option | Type | Default | Description |
191
+ |--------|------|---------|-------------|
192
+ | `db` | SQLiteDatabase | **required** | The SQLite database instance |
193
+ | `tableName` | string | `'kv'` | Table name for this store |
194
+
195
+ ## How It Works
196
+
197
+ ### Key Storage
198
+
199
+ Keys and values are stored as BLOBs (binary). SQLite compares BLOBs using `memcmp()`, which provides correct lexicographic byte ordering - exactly what's needed for range scans.
200
+
201
+ ### Table Structure
202
+
203
+ Each store creates a table with this schema:
204
+
205
+ ```sql
206
+ create table quereus_main_2Eusers (
207
+ key blob primary key,
208
+ value blob
209
+ ) without rowid
210
+ ```
211
+
212
+ The `WITHOUT ROWID` optimization is ideal for key-value workloads where the key is the primary lookup.
213
+
214
+ ## Platform Support
215
+
216
+ | Platform | Status |
217
+ |----------|--------|
218
+ | iOS | ✅ Supported |
219
+ | Android | ✅ Supported |
220
+ | NativeScript 8+ | ✅ Supported |
221
+
222
+ ## Related Packages
223
+
224
+ - [`@quereus/store`](../quereus-store/) - Core storage module (StoreModule, StoreTable)
225
+ - [`@quereus/plugin-leveldb`](../quereus-plugin-leveldb/) - LevelDB plugin for Node.js
226
+ - [`@quereus/plugin-indexeddb`](../quereus-plugin-indexeddb/) - IndexedDB plugin for browsers
227
+
228
+ ## License
229
+
230
+ MIT
231
+
package/dist/src/store.js CHANGED
@@ -57,11 +57,11 @@ export class SQLiteStore {
57
57
  ensureTable() {
58
58
  // Use WITHOUT ROWID for better key-value performance
59
59
  // Keys are BLOBs - SQLite uses memcmp() for correct byte ordering
60
- this.db.execute(`
61
- create table if not exists ${this.tableName} (
62
- key blob primary key,
63
- value blob
64
- ) without rowid
60
+ this.db.execute(`
61
+ create table if not exists ${this.tableName} (
62
+ key blob primary key,
63
+ value blob
64
+ ) without rowid
65
65
  `);
66
66
  }
67
67
  async get(key) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quereus/plugin-nativescript-sqlite",
3
- "version": "4.14.0",
3
+ "version": "4.15.2",
4
4
  "type": "module",
5
5
  "description": "NativeScript SQLite storage plugin for Quereus - mobile persistent storage",
6
6
  "keywords": [
@@ -42,9 +42,9 @@
42
42
  },
43
43
  "peerDependencies": {
44
44
  "@nativescript-community/sqlite": "^3.0.0",
45
- "@quereus/isolation": "^4.14.0",
46
- "@quereus/quereus": "^4.14.0",
47
- "@quereus/store": "^4.14.0"
45
+ "@quereus/isolation": "^4.15.2",
46
+ "@quereus/quereus": "^4.15.2",
47
+ "@quereus/store": "^4.15.2"
48
48
  },
49
49
  "engines": {
50
50
  "quereus": "^0.24.0"
@@ -87,8 +87,8 @@
87
87
  "test": "cd ../.. && node --import ./packages/quereus-plugin-nativescript-sqlite/register.mjs node_modules/mocha/bin/mocha.js \"packages/quereus-plugin-nativescript-sqlite/test/**/*.spec.ts\" --reporter min --colors"
88
88
  },
89
89
  "dependencies": {
90
- "@quereus/quereus": "^4.14.0",
91
- "@quereus/store": "^4.14.0"
90
+ "@quereus/quereus": "^4.15.2",
91
+ "@quereus/store": "^4.15.2"
92
92
  },
93
93
  "devDependencies": {
94
94
  "@quereus/isolation": "*",