deepbase-sqlite 3.5.1 → 3.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
@@ -77,6 +77,8 @@ Efficiently stores nested objects using a key-value schema:
77
77
  - Values are stored as JSON
78
78
  - Fast lookups for both exact keys and partial paths
79
79
 
80
+ Each row also stores a monotonic `seq` so reads that rebuild objects use `ORDER BY seq, key`. That matches JavaScript insertion order for sibling keys and keeps `shift()` / `pop()` (via `DeepBase.keys()`) aligned with `JsonDriver`. Existing databases pick up `seq` via `ALTER TABLE` on connect (legacy rows default to `0`, then tie-break by `key`).
81
+
80
82
  ### ACID Compliance
81
83
 
82
84
  SQLite provides:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepbase-sqlite",
3
- "version": "3.5.1",
3
+ "version": "3.6.0",
4
4
  "description": "⚡ DeepBase SQLite - SQLite database driver",
5
5
  "type": "module",
6
6
  "main": "src/index.cjs",
@@ -17,7 +17,7 @@
17
17
  "better-sqlite3": "^11.8.1"
18
18
  },
19
19
  "peerDependencies": {
20
- "deepbase": "^3.5.1"
20
+ "deepbase": "^3.6.0"
21
21
  },
22
22
  "scripts": {
23
23
  "test": "mocha test/test.js"
@@ -52,7 +52,7 @@ export class SqliteDriver extends DeepBaseDriver {
52
52
  SqliteDriver._instances[this.fileName] = this;
53
53
  }
54
54
 
55
- async connect() {
55
+ _connectSync() {
56
56
  if (this._connected) return;
57
57
 
58
58
  if (!fs.existsSync(this.path)) {
@@ -75,15 +75,27 @@ export class SqliteDriver extends DeepBaseDriver {
75
75
  this.db.exec(`
76
76
  CREATE TABLE IF NOT EXISTS deepbase (
77
77
  key TEXT PRIMARY KEY,
78
- value TEXT NOT NULL
78
+ value TEXT NOT NULL,
79
+ seq INTEGER NOT NULL DEFAULT 0
79
80
  )${withoutRowid}
80
81
  `);
81
82
 
83
+ const tableCols = this.db.prepare('PRAGMA table_info(deepbase)').all();
84
+ if (!tableCols.some((c) => c.name === 'seq')) {
85
+ this.db.exec('ALTER TABLE deepbase ADD COLUMN seq INTEGER NOT NULL DEFAULT 0');
86
+ }
87
+
82
88
  this.getStmt = this.db.prepare('SELECT value FROM deepbase WHERE key = ?');
83
- this.setStmt = this.db.prepare('INSERT OR REPLACE INTO deepbase (key, value) VALUES (?, ?)');
89
+ this.setStmt = this.db.prepare(`
90
+ INSERT INTO deepbase (key, value, seq)
91
+ VALUES (?, ?, (SELECT IFNULL(MAX(seq), 0) + 1 FROM deepbase))
92
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value
93
+ `);
84
94
  this.delStmt = this.db.prepare('DELETE FROM deepbase WHERE key = ?');
85
- this.getAllStmt = this.db.prepare('SELECT key, value FROM deepbase');
86
- this.getKeysLikeStmt = this.db.prepare("SELECT key, value FROM deepbase WHERE key LIKE ? ESCAPE '!'");
95
+ this.getAllStmt = this.db.prepare('SELECT key, value FROM deepbase ORDER BY seq, key');
96
+ this.getKeysLikeStmt = this.db.prepare(
97
+ "SELECT key, value FROM deepbase WHERE key LIKE ? ESCAPE '!' ORDER BY seq, key",
98
+ );
87
99
  this.delChildrenStmt = this.db.prepare("DELETE FROM deepbase WHERE key LIKE ? ESCAPE '!'");
88
100
  this.hasChildrenStmt = this.db.prepare("SELECT 1 FROM deepbase WHERE key LIKE ? ESCAPE '!' LIMIT 1");
89
101
 
@@ -116,6 +128,10 @@ export class SqliteDriver extends DeepBaseDriver {
116
128
  this._connected = true;
117
129
  }
118
130
 
131
+ async connect() {
132
+ this._connectSync();
133
+ }
134
+
119
135
  async disconnect() {
120
136
  if (this.db) {
121
137
  this.db.close();
@@ -128,6 +144,11 @@ export class SqliteDriver extends DeepBaseDriver {
128
144
  return this._getSync(args);
129
145
  }
130
146
 
147
+ getSync(...args) {
148
+ this._connectSync();
149
+ return this._getSync(args);
150
+ }
151
+
131
152
  _getSync(args) {
132
153
  if (args.length === 0) {
133
154
  return this._getRootObject();
package/test/test.js CHANGED
@@ -85,6 +85,21 @@ for (const pragma of PRAGMA_MODES) {
85
85
  await db.set('complex', complexObj);
86
86
  assert.deepStrictEqual(await db.get('complex'), complexObj);
87
87
  });
88
+
89
+ it('getSync returns same value as get (sync API)', async function () {
90
+ await db.set('syncKey', 'syncValue');
91
+ await db.set('syncNested', 'a', 1);
92
+ const driver = db.getDriver(0);
93
+ assert.strictEqual(driver.getSync('syncKey'), 'syncValue');
94
+ assert.strictEqual(driver.getSync('syncNested', 'a'), 1);
95
+ assert.strictEqual(driver.getSync('nonexistent'), null);
96
+ });
97
+
98
+ it('getSync lazy-connects when not connected', function () {
99
+ const driver = new SqliteDriver({ name: 'getSync-lazy', path: testDataPath });
100
+ assert.strictEqual(driver.getSync('key'), null);
101
+ assert.ok(driver._connected);
102
+ });
88
103
  });
89
104
 
90
105
  describe('Keys with Dots', function () {