@interocitor/core 0.0.0-beta.7 → 0.0.0-beta.9
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 +45 -4
- package/dist/core/ids.js +3 -3
- package/dist/core/internals.js +1 -1
- package/dist/core/manifest.js +7 -7
- package/dist/core/sync-engine.d.ts +6 -2
- package/dist/core/sync-engine.d.ts.map +1 -1
- package/dist/core/sync-engine.js +41 -23
- package/dist/core/table.d.ts.map +1 -1
- package/dist/core/table.js +4 -1
- package/dist/crypto/encryption.js +1 -1
- package/dist/handshake/channel.js +1 -1
- package/dist/handshake/qr-public.d.ts +3 -0
- package/dist/handshake/qr-public.d.ts.map +1 -0
- package/dist/handshake/qr-public.js +1 -0
- package/dist/handshake/qr.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/storage/credential-store.js +2 -2
- package/dist/storage/local-store.d.ts.map +1 -1
- package/dist/storage/local-store.js +12 -6
- package/dist/storage/reset.d.ts +10 -0
- package/dist/storage/reset.d.ts.map +1 -0
- package/dist/storage/reset.js +18 -0
- package/package.json +9 -1
package/README.md
CHANGED
|
@@ -236,15 +236,56 @@ Joining a new device to an existing mesh requires three things:
|
|
|
236
236
|
3. Access to the same **remote mailbox** (the same `remotePath` on a
|
|
237
237
|
storage backend the new device can reach).
|
|
238
238
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
239
|
+
A production app should keep CRUD, sync lifecycle, and pairing separate:
|
|
240
|
+
|
|
241
|
+
```text
|
|
242
|
+
lib/interocitor-db.ts engine, schema, local repository, credential primitives
|
|
243
|
+
lib/interocitor-sync.ts mesh id lifecycle, adapter, connect/disconnect, recovery
|
|
244
|
+
lib/interocitor-pairing.ts QR handshake only
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
The pairing flow ships credentials over an ECDH relay handshake. The handshake relay base and sync adapter base are different concepts: a relay base is the temporary handshake-file path, such as `/Taska`; the Cloudflare adapter base URL is the concrete Worker route, such as `/sync/io/{meshId}`. The engine `remotePath` is still the mesh folder path used inside that adapter, such as `/Taska`.
|
|
248
|
+
|
|
249
|
+
### Pairing intents
|
|
250
|
+
|
|
251
|
+
**Join QR** is for a device that does not have credentials yet:
|
|
252
|
+
|
|
253
|
+
1. Joiner mints a fresh mesh id.
|
|
254
|
+
2. Joiner creates a Cloudflare adapter with base URL `/sync/io/{meshId}`.
|
|
255
|
+
3. Joiner calls `generateJoinQR()`.
|
|
256
|
+
4. Existing paired device scans and pushes credentials.
|
|
257
|
+
5. Joiner receives credentials from `credentials` on the result.
|
|
258
|
+
6. Joiner applies the passphrase and connects to the minted mesh.
|
|
259
|
+
|
|
260
|
+
**Share QR** is for an existing mesh member inviting a new device:
|
|
261
|
+
|
|
262
|
+
1. Existing device connects to the active mesh.
|
|
263
|
+
2. Existing device calls `generateShareQR()` with `remotePath` and `passphrase`.
|
|
264
|
+
3. New device scans and receives credentials from `handleScannedQR()`.
|
|
265
|
+
4. New device applies credentials and connects using the adapter config from the payload.
|
|
266
|
+
|
|
267
|
+
`handleScannedQR()` returns `null` for join intent because the scanner pushed its own credentials. It returns credentials for share intent because the scanner received credentials. Always handle the return value:
|
|
268
|
+
|
|
269
|
+
```ts
|
|
270
|
+
import { decodeQRPayload, handleScannedQR, parseQRFromUrl } from '@interocitor/core';
|
|
271
|
+
// Raw QR payload decoder is also available from '@interocitor/core/handshake/qr'.
|
|
272
|
+
|
|
273
|
+
const payload = parseQRFromUrl(location.hash) ?? decodeQRPayload(rawPastedPayload);
|
|
274
|
+
const received = await handleScannedQR({ adapter, relayBase: '/Taska', payload });
|
|
275
|
+
|
|
276
|
+
if (received) {
|
|
277
|
+
if (received.passphrase) db.setPassphrase(received.passphrase);
|
|
278
|
+
await connectFromPayload(received.remotePath);
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
After the handshake the new device:
|
|
242
283
|
|
|
243
284
|
```ts
|
|
244
285
|
const db = new Interocitor(adapter, {
|
|
245
286
|
dbName: 'my-app',
|
|
246
287
|
appName: 'My App',
|
|
247
|
-
remotePath: '/
|
|
288
|
+
remotePath: '/Taska',
|
|
248
289
|
passphrase: 'base58-from-handshake',
|
|
249
290
|
encrypted: true,
|
|
250
291
|
});
|
package/dist/core/ids.js
CHANGED
|
@@ -117,8 +117,8 @@ async function computeTag(data, secret) {
|
|
|
117
117
|
function base64url(bytes) {
|
|
118
118
|
let binary = '';
|
|
119
119
|
for (let i = 0; i < bytes.length; i++)
|
|
120
|
-
binary += String.
|
|
121
|
-
return btoa(binary).
|
|
120
|
+
binary += String.fromCodePoint(bytes[i]);
|
|
121
|
+
return btoa(binary).replaceAll('+', '-').replaceAll('/', '_').replace(/=+$/, '');
|
|
122
122
|
}
|
|
123
123
|
/** Constant-time string comparison to prevent timing attacks on tag. */
|
|
124
124
|
function timingSafeEqual(a, b) {
|
|
@@ -126,7 +126,7 @@ function timingSafeEqual(a, b) {
|
|
|
126
126
|
return false;
|
|
127
127
|
let result = 0;
|
|
128
128
|
for (let i = 0; i < a.length; i++) {
|
|
129
|
-
result |= a.
|
|
129
|
+
result |= a.codePointAt(i) ^ b.codePointAt(i);
|
|
130
130
|
}
|
|
131
131
|
return result === 0;
|
|
132
132
|
}
|
package/dist/core/internals.js
CHANGED
|
@@ -48,7 +48,7 @@ export function getDeviceId(override) {
|
|
|
48
48
|
if (override)
|
|
49
49
|
return override;
|
|
50
50
|
const KEY = 'interocitor-device-id';
|
|
51
|
-
const storage = typeof localStorage
|
|
51
|
+
const storage = typeof localStorage === 'undefined' ? null : localStorage;
|
|
52
52
|
let id = storage?.getItem(KEY) ?? null;
|
|
53
53
|
if (!id) {
|
|
54
54
|
id = createDeviceId();
|
package/dist/core/manifest.js
CHANGED
|
@@ -91,7 +91,13 @@ export async function loadOrCreateManifest(ctx, codecState, local, poisonRemote,
|
|
|
91
91
|
let pointer;
|
|
92
92
|
let manifest;
|
|
93
93
|
let bootstrapped = false;
|
|
94
|
-
if (
|
|
94
|
+
if (globalPointer) {
|
|
95
|
+
pointer = globalPointer;
|
|
96
|
+
const manifestPath = `${ctx.remotePath}/${pointer.file}`;
|
|
97
|
+
ctx.emit({ type: 'trace:manifest', op: 'read', reason, path: manifestPath, generation: pointer.currentGeneration });
|
|
98
|
+
manifest = await readJson(ctx.adapter, manifestPath);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
95
101
|
bootstrapped = true;
|
|
96
102
|
ctx.emit({ type: 'trace:manifest', op: 'bootstrap-create', reason, path: p.manifestPointer });
|
|
97
103
|
const existingMeshId = await local.getMeta('meshId');
|
|
@@ -101,12 +107,6 @@ export async function loadOrCreateManifest(ctx, codecState, local, poisonRemote,
|
|
|
101
107
|
pointer = bootstrap.pointer;
|
|
102
108
|
manifest = bootstrap.manifest;
|
|
103
109
|
}
|
|
104
|
-
else {
|
|
105
|
-
pointer = globalPointer;
|
|
106
|
-
const manifestPath = `${ctx.remotePath}/${pointer.file}`;
|
|
107
|
-
ctx.emit({ type: 'trace:manifest', op: 'read', reason, path: manifestPath, generation: pointer.currentGeneration });
|
|
108
|
-
manifest = await readJson(ctx.adapter, manifestPath);
|
|
109
|
-
}
|
|
110
110
|
const manifestPath = `${ctx.remotePath}/${pointer.file}`;
|
|
111
111
|
await validateManifestHash(manifest);
|
|
112
112
|
try {
|
|
@@ -208,8 +208,12 @@ export declare class Interocitor<S extends Record<string, Record<string, unknown
|
|
|
208
208
|
private applyInitialState;
|
|
209
209
|
configureMesh(state: SyncInitialState): void;
|
|
210
210
|
/**
|
|
211
|
-
* Set the mesh encryption passphrase.
|
|
212
|
-
*
|
|
211
|
+
* Set or replace the mesh encryption passphrase before connecting.
|
|
212
|
+
*
|
|
213
|
+
* Apps may call this before init(), after init(), or after credentials
|
|
214
|
+
* arrive from pairing. It intentionally does not rebuild the engine or
|
|
215
|
+
* change remotePath/deviceId; it only invalidates the derived key so the
|
|
216
|
+
* next connect/flush uses the new passphrase.
|
|
213
217
|
*/
|
|
214
218
|
setPassphrase(passphrase: string): void;
|
|
215
219
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-engine.d.ts","sourceRoot":"","sources":["../../src/core/sync-engine.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"sync-engine.d.ts","sourceRoot":"","sources":["../../src/core/sync-engine.ts"],"names":[],"mappings":"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"}
|
package/dist/core/sync-engine.js
CHANGED
|
@@ -292,6 +292,7 @@ export class Interocitor {
|
|
|
292
292
|
if (!descriptor.orderBy)
|
|
293
293
|
return rows;
|
|
294
294
|
const { field, dir } = descriptor.orderBy;
|
|
295
|
+
// eslint-disable-next-line unicorn/no-array-sort -- package target/browser tests do not provide Array.prototype.toSorted.
|
|
295
296
|
const sorted = [...rows].sort((a, b) => {
|
|
296
297
|
const av = readColumn(a, field);
|
|
297
298
|
const bv = readColumn(b, field);
|
|
@@ -392,7 +393,7 @@ export class Interocitor {
|
|
|
392
393
|
await this.ensureReady();
|
|
393
394
|
const row = await this.local.getRow(descriptor.table, descriptor.rowId);
|
|
394
395
|
if (!row || row._meta.deleted)
|
|
395
|
-
return
|
|
396
|
+
return;
|
|
396
397
|
return row;
|
|
397
398
|
})();
|
|
398
399
|
const previous = this.rowCache.get(key);
|
|
@@ -452,7 +453,8 @@ export class Interocitor {
|
|
|
452
453
|
}
|
|
453
454
|
}
|
|
454
455
|
get initContext() {
|
|
455
|
-
|
|
456
|
+
let context;
|
|
457
|
+
context = {
|
|
456
458
|
put: this.putNow.bind(this),
|
|
457
459
|
delete: this.deleteNow.bind(this),
|
|
458
460
|
// Cache APIs (ReadinessAwareQueryExecutor). Init-time tables need them
|
|
@@ -469,12 +471,13 @@ export class Interocitor {
|
|
|
469
471
|
loadRow: this.loadRow.bind(this),
|
|
470
472
|
query: this.queryNow.bind(this),
|
|
471
473
|
queryWhere: this.queryWhereNow.bind(this),
|
|
472
|
-
table: (name) => new Table(
|
|
474
|
+
table: (name) => new Table(context, name),
|
|
473
475
|
on: this.on.bind(this),
|
|
474
476
|
getDeviceId: this.getDeviceId.bind(this),
|
|
475
477
|
getMeshId: this.getMeshId.bind(this),
|
|
476
478
|
isEncrypted: this.isEncrypted.bind(this),
|
|
477
479
|
};
|
|
480
|
+
return context;
|
|
478
481
|
}
|
|
479
482
|
// ── Internal accessors ─────────────────────────────────────────────
|
|
480
483
|
requireAdapter(operation) {
|
|
@@ -613,12 +616,10 @@ export class Interocitor {
|
|
|
613
616
|
this.log('debug', '[interocitor:poll] activity detected, poll interval reset', { intervalMs: this.pollCurrentIntervalMs });
|
|
614
617
|
}
|
|
615
618
|
}
|
|
616
|
-
else {
|
|
619
|
+
else if (this.pollCurrentIntervalMs < MAX_POLL_INTERVAL_MS) {
|
|
617
620
|
// Idle — back off toward max.
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
this.log('debug', '[interocitor:poll] idle, poll interval backed off', { intervalMs: this.pollCurrentIntervalMs });
|
|
621
|
-
}
|
|
621
|
+
this.pollCurrentIntervalMs = Math.min(this.pollCurrentIntervalMs * 2, MAX_POLL_INTERVAL_MS);
|
|
622
|
+
this.log('debug', '[interocitor:poll] idle, poll interval backed off', { intervalMs: this.pollCurrentIntervalMs });
|
|
622
623
|
}
|
|
623
624
|
}
|
|
624
625
|
stopRemoteInvalidations() {
|
|
@@ -997,11 +998,27 @@ export class Interocitor {
|
|
|
997
998
|
});
|
|
998
999
|
}
|
|
999
1000
|
/**
|
|
1000
|
-
* Set the mesh encryption passphrase.
|
|
1001
|
-
*
|
|
1001
|
+
* Set or replace the mesh encryption passphrase before connecting.
|
|
1002
|
+
*
|
|
1003
|
+
* Apps may call this before init(), after init(), or after credentials
|
|
1004
|
+
* arrive from pairing. It intentionally does not rebuild the engine or
|
|
1005
|
+
* change remotePath/deviceId; it only invalidates the derived key so the
|
|
1006
|
+
* next connect/flush uses the new passphrase.
|
|
1002
1007
|
*/
|
|
1003
1008
|
setPassphrase(passphrase) {
|
|
1004
|
-
this.
|
|
1009
|
+
if (this.connected)
|
|
1010
|
+
throw new Error('Cannot set passphrase while connected; disconnect first');
|
|
1011
|
+
this.passphrase = passphrase;
|
|
1012
|
+
this.encryptionKey = null;
|
|
1013
|
+
this.encrypted = true;
|
|
1014
|
+
this.emit({
|
|
1015
|
+
type: 'mesh:configured',
|
|
1016
|
+
dbName: this.dbName,
|
|
1017
|
+
remotePath: this.config.remotePath,
|
|
1018
|
+
deviceId: this.deviceId,
|
|
1019
|
+
encrypted: this.encrypted,
|
|
1020
|
+
hadPassphrase: true,
|
|
1021
|
+
});
|
|
1005
1022
|
}
|
|
1006
1023
|
/**
|
|
1007
1024
|
* Get the current mesh passphrase.
|
|
@@ -1255,6 +1272,8 @@ export class Interocitor {
|
|
|
1255
1272
|
hasInFlight: !!this.connectPromise,
|
|
1256
1273
|
});
|
|
1257
1274
|
await this.ensureReady();
|
|
1275
|
+
if (this.encrypted && !this.encryptionKey)
|
|
1276
|
+
await this.resolveEncryption();
|
|
1258
1277
|
if (!this.config.remotePath)
|
|
1259
1278
|
throw new Error('connect() requires remotePath; configure mesh before connecting');
|
|
1260
1279
|
// Idempotent. If we are already connected to a live mesh on this
|
|
@@ -1383,7 +1402,7 @@ export class Interocitor {
|
|
|
1383
1402
|
return e;
|
|
1384
1403
|
};
|
|
1385
1404
|
const stageOk = (s, extra) => {
|
|
1386
|
-
console.log('[interocitor:connect] doConnect() — stage ok', { stage: s, dbName: this.dbName, deviceId: this.deviceId, ...
|
|
1405
|
+
console.log('[interocitor:connect] doConnect() — stage ok', { stage: s, dbName: this.dbName, deviceId: this.deviceId, ...extra });
|
|
1387
1406
|
};
|
|
1388
1407
|
this.log('debug', 'connect() — authenticating with adapter', { adapter: adapter.name });
|
|
1389
1408
|
if (!adapter.isAuthenticated()) {
|
|
@@ -1751,21 +1770,20 @@ export class Interocitor {
|
|
|
1751
1770
|
this.batchTimer = null;
|
|
1752
1771
|
}
|
|
1753
1772
|
appendOpToPendingBatch(op, hlc) {
|
|
1754
|
-
if (
|
|
1755
|
-
this.pendingBatch = {
|
|
1756
|
-
id: generateId('chg'),
|
|
1757
|
-
ts: Date.now(),
|
|
1758
|
-
device: this.deviceId,
|
|
1759
|
-
hlc,
|
|
1760
|
-
ops: [op],
|
|
1761
|
-
};
|
|
1762
|
-
}
|
|
1763
|
-
else {
|
|
1773
|
+
if (this.pendingBatch) {
|
|
1764
1774
|
this.pendingBatch.ops.push(op);
|
|
1765
1775
|
// Carry the highest HLC seen in this batch
|
|
1766
1776
|
if (hlcCompareStr(hlc, this.pendingBatch.hlc) > 0)
|
|
1767
1777
|
this.pendingBatch.hlc = hlc;
|
|
1778
|
+
return;
|
|
1768
1779
|
}
|
|
1780
|
+
this.pendingBatch = {
|
|
1781
|
+
id: generateId('chg'),
|
|
1782
|
+
ts: Date.now(),
|
|
1783
|
+
device: this.deviceId,
|
|
1784
|
+
hlc,
|
|
1785
|
+
ops: [op],
|
|
1786
|
+
};
|
|
1769
1787
|
}
|
|
1770
1788
|
armImplicitBatchTimer() {
|
|
1771
1789
|
if (this.isBatching())
|
|
@@ -1986,7 +2004,7 @@ export class Interocitor {
|
|
|
1986
2004
|
trigger: 'delayed',
|
|
1987
2005
|
remotePath: this.config.remotePath,
|
|
1988
2006
|
deviceId: this.deviceId,
|
|
1989
|
-
reason:
|
|
2007
|
+
reason: this.connected ? (this.config.autoCompact ? 'missing-remote' : 'disabled') : 'not-connected',
|
|
1990
2008
|
});
|
|
1991
2009
|
return;
|
|
1992
2010
|
}
|
package/dist/core/table.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../src/core/table.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAIpD,KAAK,SAAS,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;AAClC,OAAO,KAAK,EAAO,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,KAAK,EACV,eAAe,EACf,qBAAqB,EACrB,oBAAoB,EACpB,aAAa,EAEb,cAAc,EACf,MAAM,YAAY,CAAC;AAGpB;;;;;;;;;;;;GAYG;AACH,qBAAa,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAE,YAAW,WAAW,CAAC,CAAC,EAAE,CAAC;IAQnF,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,kEAAkE;IAClE,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,gFAAgF;IAChF,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IAXnC,mCAAmC;IACnC,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;IACrC,wDAAwD;IACxD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAGxB,UAAU,EAAE,eAAe,EACV,OAAO,EAAE,SAAS,GAAG,IAAI;IAC1C,kEAAkE;IACjD,UAAU,GAAE,aAAa,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,CAAM;IACnE,gFAAgF;IAC/D,gBAAgB,GAAE,OAAO,CAAC,CAAC,EAAE,CAAC,GAAG,IAAW;IAQ/D,sDAAsD;IACtD,IAAI,QAAQ;;;MAEX;IAED;;;OAGG;IACH,IAAI,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAInD;;;;;;;;;;;;;OAaG;IACH,SAAS,IAAI,CAAC,EAAE,GAAG,SAAS;IAO5B;;;OAGG;IACH,UAAU,IAAI;QAAE,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,KAAK,CAAA;KAAE;IAMhF;;;;;OAKG;IACH,aAAa,CAAC,MAAM,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE;
|
|
1
|
+
{"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../src/core/table.ts"],"names":[],"mappings":"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"}
|
package/dist/core/table.js
CHANGED
|
@@ -97,6 +97,7 @@ export class QueryResult {
|
|
|
97
97
|
return cached;
|
|
98
98
|
return this.load({ bypassCache: policy?.mode === 'bypass-cache' });
|
|
99
99
|
}
|
|
100
|
+
// eslint-disable-next-line unicorn/no-thenable -- QueryResult intentionally supports await/db.table(...).where(...).
|
|
100
101
|
then(onfulfilled, onrejected) {
|
|
101
102
|
return this.load().then(onfulfilled, onrejected);
|
|
102
103
|
}
|
|
@@ -105,6 +106,7 @@ export class QueryResult {
|
|
|
105
106
|
* Sync-only. Does NOT change `cacheKey` — this is post-load derivation.
|
|
106
107
|
*/
|
|
107
108
|
sort(compareFn) {
|
|
109
|
+
// eslint-disable-next-line unicorn/no-array-sort -- package target/browser tests do not provide Array.prototype.toSorted.
|
|
108
110
|
const next = (rows) => [...rows].sort(compareFn);
|
|
109
111
|
return new QueryResult(this.descriptor, this._engine, [...this._sortChain, next], this._explicitPromise);
|
|
110
112
|
}
|
|
@@ -257,7 +259,7 @@ export class RowResult {
|
|
|
257
259
|
}
|
|
258
260
|
load(options) {
|
|
259
261
|
if (!this._engine)
|
|
260
|
-
return Promise.resolve(
|
|
262
|
+
return Promise.resolve(void 0);
|
|
261
263
|
return this._engine.loadRow(this.descriptor, options).then(r => this._project(r));
|
|
262
264
|
}
|
|
263
265
|
/**
|
|
@@ -282,6 +284,7 @@ export class RowResult {
|
|
|
282
284
|
return cached;
|
|
283
285
|
return this.load({ bypassCache: policy?.mode === 'bypass-cache' });
|
|
284
286
|
}
|
|
287
|
+
// eslint-disable-next-line unicorn/no-thenable -- RowResult intentionally supports await/db.table(...).row(...).
|
|
285
288
|
then(onfulfilled, onrejected) {
|
|
286
289
|
return this.load().then(onfulfilled, onrejected);
|
|
287
290
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qr-public.d.ts","sourceRoot":"","sources":["../../src/handshake/qr-public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,eAAe,EACf,eAAe,EACf,cAAc,GACf,MAAM,SAAS,CAAC;AAEjB,YAAY,EACV,eAAe,EACf,kBAAkB,GACnB,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { buildPairUrl, decodeQRPayload, encodeQRPayload, parseQRFromUrl, } from "./qr.js";
|
package/dist/handshake/qr.js
CHANGED
|
@@ -63,7 +63,7 @@ export function decodeQRPayload(encoded) {
|
|
|
63
63
|
const binary = atob(b64);
|
|
64
64
|
const bytes = new Uint8Array(binary.length);
|
|
65
65
|
for (let i = 0; i < binary.length; i++) {
|
|
66
|
-
bytes[i] = binary.
|
|
66
|
+
bytes[i] = binary.codePointAt(i);
|
|
67
67
|
}
|
|
68
68
|
const json = new TextDecoder().decode(bytes);
|
|
69
69
|
const payload = JSON.parse(json);
|
package/dist/index.d.ts
CHANGED
|
@@ -36,6 +36,7 @@ export { generateShareQR, generateJoinQR, handleScannedQR, buildPairUrl, parseQR
|
|
|
36
36
|
export type { HandshakeCredentials, HandshakeQRPayload, HandshakeIntent, GenerateShareQROptions, GenerateShareQRResult, GenerateJoinQROptions, GenerateJoinQRResult, HandleScannedQROptions, } from './handshake/index.ts';
|
|
37
37
|
export { Interocitor, type InterocitorInitContext, } from './core/sync-engine.ts';
|
|
38
38
|
export { LocalStore } from './storage/local-store.ts';
|
|
39
|
+
export { resetLocalDatabase } from './storage/reset.ts';
|
|
39
40
|
export { type CredentialStore, type StoredCredentials, LocalStorageCredentialStore, WebAuthnCredentialStore, createCredentialStore, } from './storage/credential-store.ts';
|
|
40
41
|
export { Table, QueryResult, RowResult } from './core/table.ts';
|
|
41
42
|
export { types } from './core/schema-types.ts';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAIH,OAAO,EACL,eAAe,EACf,cAAc,EACd,eAAe,EACf,YAAY,EACZ,cAAc,EACd,eAAe,EACf,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EACV,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,EACf,sBAAsB,EACtB,qBAAqB,EACrB,qBAAqB,EACrB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,sBAAsB,CAAC;AAI9B,OAAO,EACL,WAAW,EACX,KAAK,sBAAsB,GAC5B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,2BAA2B,EAC3B,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAI/C,OAAO,EACL,2BAA2B,EAC3B,2BAA2B,GAC5B,MAAM,kBAAkB,CAAC;AAI1B,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EACL,MAAM,EACN,cAAc,EACd,eAAe,EACf,WAAW,EACX,aAAa,EACb,WAAW,EACX,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAI3D,YAAY,EAEV,cAAc,EACd,SAAS,EAGT,iBAAiB,EACjB,iBAAiB,EAGjB,UAAU,EACV,gBAAgB,EAChB,QAAQ,EACR,wBAAwB,EACxB,qBAAqB,EACrB,eAAe,EACf,cAAc,EACd,UAAU,EACV,kBAAkB,EAClB,oBAAoB,EACpB,eAAe,EACf,wBAAwB,EACxB,WAAW,EACX,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACb,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,oBAAoB,EACpB,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,2BAA2B,EAC3B,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,cAAc,EACd,aAAa,EAGb,SAAS,EACT,iBAAiB,EAGjB,GAAG,EAGH,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EACnB,UAAU,EACV,cAAc,EACd,UAAU,EACV,UAAU,EACV,WAAW,EACX,aAAa,GACd,MAAM,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAIH,OAAO,EACL,eAAe,EACf,cAAc,EACd,eAAe,EACf,YAAY,EACZ,cAAc,EACd,eAAe,EACf,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EACV,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,EACf,sBAAsB,EACtB,qBAAqB,EACrB,qBAAqB,EACrB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,sBAAsB,CAAC;AAI9B,OAAO,EACL,WAAW,EACX,KAAK,sBAAsB,GAC5B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,2BAA2B,EAC3B,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAI/C,OAAO,EACL,2BAA2B,EAC3B,2BAA2B,GAC5B,MAAM,kBAAkB,CAAC;AAI1B,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EACL,MAAM,EACN,cAAc,EACd,eAAe,EACf,WAAW,EACX,aAAa,EACb,WAAW,EACX,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAI3D,YAAY,EAEV,cAAc,EACd,SAAS,EAGT,iBAAiB,EACjB,iBAAiB,EAGjB,UAAU,EACV,gBAAgB,EAChB,QAAQ,EACR,wBAAwB,EACxB,qBAAqB,EACrB,eAAe,EACf,cAAc,EACd,UAAU,EACV,kBAAkB,EAClB,oBAAoB,EACpB,eAAe,EACf,wBAAwB,EACxB,WAAW,EACX,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACb,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,oBAAoB,EACpB,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,2BAA2B,EAC3B,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,cAAc,EACd,aAAa,EAGb,SAAS,EACT,iBAAiB,EAGjB,GAAG,EAGH,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EACnB,UAAU,EACV,cAAc,EACd,UAAU,EACV,UAAU,EACV,WAAW,EACX,aAAa,GACd,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -37,6 +37,7 @@ export { generateShareQR, generateJoinQR, handleScannedQR, buildPairUrl, parseQR
|
|
|
37
37
|
// ─── Engine ───────────────────────────────────────────────────────────
|
|
38
38
|
export { Interocitor, } from "./core/sync-engine.js";
|
|
39
39
|
export { LocalStore } from "./storage/local-store.js";
|
|
40
|
+
export { resetLocalDatabase } from "./storage/reset.js";
|
|
40
41
|
export { LocalStorageCredentialStore, WebAuthnCredentialStore, createCredentialStore, } from "./storage/credential-store.js";
|
|
41
42
|
export { Table, QueryResult, RowResult } from "./core/table.js";
|
|
42
43
|
export { types } from "./core/schema-types.js";
|
|
@@ -124,7 +124,7 @@ export class WebAuthnCredentialStore {
|
|
|
124
124
|
const stored = localStorage.getItem(this.credIdKey());
|
|
125
125
|
if (!stored)
|
|
126
126
|
return null;
|
|
127
|
-
const raw = Uint8Array.from(atob(stored), c => c.
|
|
127
|
+
const raw = Uint8Array.from(atob(stored), c => c.codePointAt(0));
|
|
128
128
|
return raw.buffer;
|
|
129
129
|
}
|
|
130
130
|
catch {
|
|
@@ -138,7 +138,7 @@ export class WebAuthnCredentialStore {
|
|
|
138
138
|
const bytes = new Uint8Array(rawId);
|
|
139
139
|
let binary = '';
|
|
140
140
|
for (let i = 0; i < bytes.length; i++)
|
|
141
|
-
binary += String.
|
|
141
|
+
binary += String.fromCodePoint(bytes[i]);
|
|
142
142
|
const b64 = btoa(binary);
|
|
143
143
|
localStorage.setItem(this.credIdKey(), b64);
|
|
144
144
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-store.d.ts","sourceRoot":"","sources":["../../src/storage/local-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EACV,GAAG,EACH,WAAW,EACX,iBAAiB,EACjB,wBAAwB,EAGxB,WAAW,EAEZ,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"local-store.d.ts","sourceRoot":"","sources":["../../src/storage/local-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EACV,GAAG,EACH,WAAW,EACX,iBAAiB,EACjB,wBAAwB,EAGxB,WAAW,EAEZ,MAAM,kBAAkB,CAAC;AAmP1B;;;;;;GAMG;AACH,qBAAa,UAAW,YAAW,iBAAiB;IAClD,OAAO,CAAC,EAAE,CAA4B;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAA2B;IAEnD;;;;;OAKG;gBACS,MAAM,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,wBAAwB;IAO5E,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,KAAK,IAAI,IAAI;IAKb,OAAO,CAAC,QAAQ;IAOhB,OAAO,CAAC,MAAM;IAIR,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,SAAS,CAAC;IAQpE,kEAAkE;IAClE,OAAO,CAAC,OAAO;IAQT,MAAM,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ/B,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAWnC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IASvC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAgC9D,aAAa,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAgBlC,UAAU,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAO5B,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAS1B,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7C,iBAAiB,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IASxD,WAAW,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAUrC,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAQ7B,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAO5C,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO1D,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAehD,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAMtC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAOzD,qDAAqD;IAC/C,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAQhC"}
|
|
@@ -138,17 +138,23 @@ function hasSchemaIndex(schema, table, field) {
|
|
|
138
138
|
};
|
|
139
139
|
}
|
|
140
140
|
function rangeForClause(table, clause) {
|
|
141
|
+
// Schema indexes are keyed as [table, fieldValue]. Range queries must bound
|
|
142
|
+
// both sides of the compound key; lowerBound([table, value]) alone would also
|
|
143
|
+
// include later table names, and upperBound([table, value]) would include
|
|
144
|
+
// earlier table names.
|
|
145
|
+
const tableLowerBound = [table];
|
|
146
|
+
const tableUpperBound = [table, []];
|
|
141
147
|
switch (clause.op) {
|
|
142
148
|
case 'equals':
|
|
143
149
|
return IDBKeyRange.only([table, clause.value]);
|
|
144
150
|
case 'above':
|
|
145
|
-
return IDBKeyRange.
|
|
151
|
+
return IDBKeyRange.bound([table, clause.value], tableUpperBound, true, false);
|
|
146
152
|
case 'aboveOrEqual':
|
|
147
|
-
return IDBKeyRange.
|
|
153
|
+
return IDBKeyRange.bound([table, clause.value], tableUpperBound, false, false);
|
|
148
154
|
case 'below':
|
|
149
|
-
return IDBKeyRange.
|
|
155
|
+
return IDBKeyRange.bound(tableLowerBound, [table, clause.value], false, true);
|
|
150
156
|
case 'belowOrEqual':
|
|
151
|
-
return IDBKeyRange.
|
|
157
|
+
return IDBKeyRange.bound(tableLowerBound, [table, clause.value], false, false);
|
|
152
158
|
case 'between':
|
|
153
159
|
return IDBKeyRange.bound([table, clause.lower], [table, clause.upper], clause.lowerOpen ?? false, clause.upperOpen ?? false);
|
|
154
160
|
case 'startsWith': {
|
|
@@ -311,7 +317,7 @@ export class LocalStore {
|
|
|
311
317
|
for (const value of values) {
|
|
312
318
|
const matches = await reqToPromise(index.getAll(IDBKeyRange.only([table, value])));
|
|
313
319
|
for (const row of matches) {
|
|
314
|
-
if (!row._meta.deleted) {
|
|
320
|
+
if (!row._meta.deleted && row._meta.table === table) {
|
|
315
321
|
merged.set(`${row._meta.table}/${row._meta.rowId}`, row);
|
|
316
322
|
}
|
|
317
323
|
}
|
|
@@ -320,7 +326,7 @@ export class LocalStore {
|
|
|
320
326
|
}
|
|
321
327
|
const range = rangeForClause(table, clause);
|
|
322
328
|
const results = await reqToPromise(index.getAll(range ?? undefined));
|
|
323
|
-
return results.filter(row => !row._meta.deleted);
|
|
329
|
+
return results.filter(row => !row._meta.deleted && row._meta.table === table);
|
|
324
330
|
}
|
|
325
331
|
async getTableNames() {
|
|
326
332
|
const db = this.ensureDB();
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delete an Interocitor IndexedDB database after callers have disconnected
|
|
3
|
+
* and cleared credentials.
|
|
4
|
+
*
|
|
5
|
+
* This is intentionally low-level: it only deletes the local IndexedDB
|
|
6
|
+
* database named by `dbName`. Apps should call it as the final destructive
|
|
7
|
+
* local reset step, then reload before creating or joining a new mesh.
|
|
8
|
+
*/
|
|
9
|
+
export declare function resetLocalDatabase(dbName?: string): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=reset.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reset.d.ts","sourceRoot":"","sources":["../../src/storage/reset.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,SAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CASxE"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delete an Interocitor IndexedDB database after callers have disconnected
|
|
3
|
+
* and cleared credentials.
|
|
4
|
+
*
|
|
5
|
+
* This is intentionally low-level: it only deletes the local IndexedDB
|
|
6
|
+
* database named by `dbName`. Apps should call it as the final destructive
|
|
7
|
+
* local reset step, then reload before creating or joining a new mesh.
|
|
8
|
+
*/
|
|
9
|
+
export function resetLocalDatabase(dbName = 'interocitor') {
|
|
10
|
+
return new Promise((resolve, reject) => {
|
|
11
|
+
const req = indexedDB.deleteDatabase(dbName);
|
|
12
|
+
req.onsuccess = () => resolve();
|
|
13
|
+
req.onerror = () => reject(req.error ?? new Error(`Failed to delete IndexedDB database "${dbName}"`));
|
|
14
|
+
req.onblocked = () => {
|
|
15
|
+
reject(new Error(`Cannot delete IndexedDB database "${dbName}" while another connection is open`));
|
|
16
|
+
};
|
|
17
|
+
});
|
|
18
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@interocitor/core",
|
|
3
|
-
"version": "0.0.0-beta.
|
|
3
|
+
"version": "0.0.0-beta.9",
|
|
4
4
|
"description": "Encrypted local-first CRDT database that syncs over cloud storage without a purpose-built backend.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -30,6 +30,14 @@
|
|
|
30
30
|
"import": "./dist/storage/local-store.js",
|
|
31
31
|
"types": "./dist/storage/local-store.d.ts"
|
|
32
32
|
},
|
|
33
|
+
"./storage/reset": {
|
|
34
|
+
"import": "./dist/storage/reset.js",
|
|
35
|
+
"types": "./dist/storage/reset.d.ts"
|
|
36
|
+
},
|
|
37
|
+
"./handshake/qr": {
|
|
38
|
+
"import": "./dist/handshake/qr-public.js",
|
|
39
|
+
"types": "./dist/handshake/qr-public.d.ts"
|
|
40
|
+
},
|
|
33
41
|
"./crypto/keys": {
|
|
34
42
|
"import": "./dist/crypto/keys.js",
|
|
35
43
|
"types": "./dist/crypto/keys.d.ts"
|