@unicitylabs/sphere-sdk 0.4.3 → 0.4.4
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/dist/core/index.cjs +21 -3
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.js +21 -3
- package/dist/core/index.js.map +1 -1
- package/dist/impl/browser/index.cjs +163 -98
- package/dist/impl/browser/index.cjs.map +1 -1
- package/dist/impl/browser/index.js +163 -98
- package/dist/impl/browser/index.js.map +1 -1
- package/dist/index.cjs +21 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +21 -3
- package/dist/index.js.map +1 -1
- package/dist/l1/index.cjs +21 -3
- package/dist/l1/index.cjs.map +1 -1
- package/dist/l1/index.js +21 -3
- package/dist/l1/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -354,6 +354,7 @@ function createLocalStorageProvider(config) {
|
|
|
354
354
|
var DB_NAME = "sphere-storage";
|
|
355
355
|
var DB_VERSION = 1;
|
|
356
356
|
var STORE_NAME = "kv";
|
|
357
|
+
var connectionSeq = 0;
|
|
357
358
|
var IndexedDBStorageProvider = class {
|
|
358
359
|
id = "indexeddb-storage";
|
|
359
360
|
name = "IndexedDB Storage";
|
|
@@ -365,6 +366,8 @@ var IndexedDBStorageProvider = class {
|
|
|
365
366
|
identity = null;
|
|
366
367
|
status = "disconnected";
|
|
367
368
|
db = null;
|
|
369
|
+
/** Monotonic connection ID for tracing open/close pairs */
|
|
370
|
+
connId = 0;
|
|
368
371
|
constructor(config) {
|
|
369
372
|
this.prefix = config?.prefix ?? "sphere_";
|
|
370
373
|
this.dbName = config?.dbName ?? DB_NAME;
|
|
@@ -377,7 +380,8 @@ var IndexedDBStorageProvider = class {
|
|
|
377
380
|
if (this.status === "connected" && this.db) return;
|
|
378
381
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
379
382
|
this.status = "connecting";
|
|
380
|
-
|
|
383
|
+
const t0 = Date.now();
|
|
384
|
+
console.log(`[IndexedDBStorage] connect: opening db=${this.dbName}, attempt=${attempt + 1}/2`);
|
|
381
385
|
try {
|
|
382
386
|
this.db = await Promise.race([
|
|
383
387
|
this.openDatabase(),
|
|
@@ -386,11 +390,11 @@ var IndexedDBStorageProvider = class {
|
|
|
386
390
|
)
|
|
387
391
|
]);
|
|
388
392
|
this.status = "connected";
|
|
389
|
-
console.log(`[IndexedDBStorage] connect: connected
|
|
393
|
+
console.log(`[IndexedDBStorage] connect: connected db=${this.dbName} connId=${this.connId} (${Date.now() - t0}ms)`);
|
|
390
394
|
return;
|
|
391
395
|
} catch (error) {
|
|
396
|
+
console.warn(`[IndexedDBStorage] connect: open failed db=${this.dbName} attempt=${attempt + 1} (${Date.now() - t0}ms):`, error);
|
|
392
397
|
if (attempt === 0) {
|
|
393
|
-
console.warn(`[IndexedDBStorage] connect: open failed, retrying in 1s...`);
|
|
394
398
|
this.status = "disconnected";
|
|
395
399
|
await new Promise((r) => setTimeout(r, 1e3));
|
|
396
400
|
continue;
|
|
@@ -401,7 +405,8 @@ var IndexedDBStorageProvider = class {
|
|
|
401
405
|
}
|
|
402
406
|
}
|
|
403
407
|
async disconnect() {
|
|
404
|
-
|
|
408
|
+
const cid = this.connId;
|
|
409
|
+
console.log(`[IndexedDBStorage] disconnect: db=${this.dbName} connId=${cid} wasConnected=${!!this.db}`);
|
|
405
410
|
if (this.db) {
|
|
406
411
|
this.db.close();
|
|
407
412
|
this.db = null;
|
|
@@ -458,37 +463,36 @@ var IndexedDBStorageProvider = class {
|
|
|
458
463
|
}
|
|
459
464
|
async clear(prefix) {
|
|
460
465
|
if (!prefix) {
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
req.onerror = () => {
|
|
480
|
-
clearTimeout(timer);
|
|
481
|
-
console.warn(`[IndexedDBStorage] clear: error deleting db=${this.dbName}`, req.error);
|
|
482
|
-
resolve();
|
|
483
|
-
};
|
|
484
|
-
req.onblocked = () => {
|
|
485
|
-
console.warn(`[IndexedDBStorage] clear: deleteDatabase blocked for db=${this.dbName}, waiting...`);
|
|
486
|
-
};
|
|
487
|
-
} catch {
|
|
488
|
-
resolve();
|
|
466
|
+
const t0 = Date.now();
|
|
467
|
+
const prevConnId = this.connId;
|
|
468
|
+
console.log(`[IndexedDBStorage] clear: starting db=${this.dbName} connId=${prevConnId} status=${this.status} hasDb=${!!this.db}`);
|
|
469
|
+
try {
|
|
470
|
+
if (!this.db || this.status !== "connected") {
|
|
471
|
+
if (this.db) {
|
|
472
|
+
console.log(`[IndexedDBStorage] clear: closing stale handle connId=${prevConnId}`);
|
|
473
|
+
this.db.close();
|
|
474
|
+
this.db = null;
|
|
475
|
+
}
|
|
476
|
+
console.log(`[IndexedDBStorage] clear: opening fresh connection for wipe`);
|
|
477
|
+
this.db = await Promise.race([
|
|
478
|
+
this.openDatabase(),
|
|
479
|
+
new Promise(
|
|
480
|
+
(_, reject) => setTimeout(() => reject(new Error("open timed out")), 3e3)
|
|
481
|
+
)
|
|
482
|
+
]);
|
|
483
|
+
this.status = "connected";
|
|
489
484
|
}
|
|
490
|
-
|
|
491
|
-
|
|
485
|
+
await this.idbClear();
|
|
486
|
+
console.log(`[IndexedDBStorage] clear: store cleared db=${this.dbName} connId=${this.connId} (${Date.now() - t0}ms)`);
|
|
487
|
+
} catch (err) {
|
|
488
|
+
console.warn(`[IndexedDBStorage] clear: failed db=${this.dbName} (${Date.now() - t0}ms)`, err);
|
|
489
|
+
} finally {
|
|
490
|
+
if (this.db) {
|
|
491
|
+
this.db.close();
|
|
492
|
+
this.db = null;
|
|
493
|
+
}
|
|
494
|
+
this.status = "disconnected";
|
|
495
|
+
}
|
|
492
496
|
return;
|
|
493
497
|
}
|
|
494
498
|
this.ensureConnected();
|
|
@@ -554,9 +558,22 @@ var IndexedDBStorageProvider = class {
|
|
|
554
558
|
return new Promise((resolve, reject) => {
|
|
555
559
|
const request = indexedDB.open(this.dbName, DB_VERSION);
|
|
556
560
|
request.onerror = () => reject(request.error);
|
|
557
|
-
request.onsuccess = () =>
|
|
561
|
+
request.onsuccess = () => {
|
|
562
|
+
const db = request.result;
|
|
563
|
+
const cid = ++connectionSeq;
|
|
564
|
+
this.connId = cid;
|
|
565
|
+
db.onversionchange = () => {
|
|
566
|
+
console.log(`[IndexedDBStorage] onversionchange: auto-closing db=${this.dbName} connId=${cid}`);
|
|
567
|
+
db.close();
|
|
568
|
+
if (this.db === db) {
|
|
569
|
+
this.db = null;
|
|
570
|
+
this.status = "disconnected";
|
|
571
|
+
}
|
|
572
|
+
};
|
|
573
|
+
resolve(db);
|
|
574
|
+
};
|
|
558
575
|
request.onblocked = () => {
|
|
559
|
-
console.warn(
|
|
576
|
+
console.warn(`[IndexedDBStorage] open blocked by another connection, db=${this.dbName}`);
|
|
560
577
|
};
|
|
561
578
|
request.onupgradeneeded = (event) => {
|
|
562
579
|
const db = event.target.result;
|
|
@@ -635,18 +652,23 @@ var DB_NAME2 = "sphere-token-storage";
|
|
|
635
652
|
var DB_VERSION2 = 1;
|
|
636
653
|
var STORE_TOKENS = "tokens";
|
|
637
654
|
var STORE_META = "meta";
|
|
655
|
+
var connectionSeq2 = 0;
|
|
638
656
|
var IndexedDBTokenStorageProvider = class {
|
|
639
657
|
id = "indexeddb-token-storage";
|
|
640
658
|
name = "IndexedDB Token Storage";
|
|
641
659
|
type = "local";
|
|
642
660
|
dbNamePrefix;
|
|
643
661
|
dbName;
|
|
662
|
+
debug;
|
|
644
663
|
db = null;
|
|
645
664
|
status = "disconnected";
|
|
646
665
|
identity = null;
|
|
666
|
+
/** Monotonic connection ID for tracing open/close pairs */
|
|
667
|
+
connId = 0;
|
|
647
668
|
constructor(config) {
|
|
648
669
|
this.dbNamePrefix = config?.dbNamePrefix ?? DB_NAME2;
|
|
649
670
|
this.dbName = this.dbNamePrefix;
|
|
671
|
+
this.debug = config?.debug ?? false;
|
|
650
672
|
}
|
|
651
673
|
setIdentity(identity) {
|
|
652
674
|
this.identity = identity;
|
|
@@ -654,28 +676,31 @@ var IndexedDBTokenStorageProvider = class {
|
|
|
654
676
|
const addressId = getAddressId(identity.directAddress);
|
|
655
677
|
this.dbName = `${this.dbNamePrefix}-${addressId}`;
|
|
656
678
|
}
|
|
657
|
-
console.log(`[IndexedDBTokenStorage] setIdentity
|
|
679
|
+
console.log(`[IndexedDBTokenStorage] setIdentity: db=${this.dbName}`);
|
|
658
680
|
}
|
|
659
681
|
async initialize() {
|
|
682
|
+
const prevConnId = this.connId;
|
|
683
|
+
const t0 = Date.now();
|
|
660
684
|
try {
|
|
661
685
|
if (this.db) {
|
|
662
|
-
console.log(`[IndexedDBTokenStorage] initialize: closing existing
|
|
686
|
+
console.log(`[IndexedDBTokenStorage] initialize: closing existing connId=${prevConnId} before re-open (db=${this.dbName})`);
|
|
663
687
|
this.db.close();
|
|
664
688
|
this.db = null;
|
|
665
689
|
}
|
|
666
690
|
console.log(`[IndexedDBTokenStorage] initialize: opening db=${this.dbName}`);
|
|
667
691
|
this.db = await this.openDatabase();
|
|
668
692
|
this.status = "connected";
|
|
669
|
-
console.log(`[IndexedDBTokenStorage] initialize: connected
|
|
693
|
+
console.log(`[IndexedDBTokenStorage] initialize: connected db=${this.dbName} connId=${this.connId} (${Date.now() - t0}ms)`);
|
|
670
694
|
return true;
|
|
671
695
|
} catch (error) {
|
|
672
|
-
console.error(
|
|
696
|
+
console.error(`[IndexedDBTokenStorage] initialize: failed db=${this.dbName} (${Date.now() - t0}ms):`, error);
|
|
673
697
|
this.status = "error";
|
|
674
698
|
return false;
|
|
675
699
|
}
|
|
676
700
|
}
|
|
677
701
|
async shutdown() {
|
|
678
|
-
|
|
702
|
+
const cid = this.connId;
|
|
703
|
+
console.log(`[IndexedDBTokenStorage] shutdown: db=${this.dbName} connId=${cid} wasConnected=${!!this.db}`);
|
|
679
704
|
if (this.db) {
|
|
680
705
|
this.db.close();
|
|
681
706
|
this.db = null;
|
|
@@ -833,56 +858,32 @@ var IndexedDBTokenStorageProvider = class {
|
|
|
833
858
|
return meta !== null;
|
|
834
859
|
}
|
|
835
860
|
async clear() {
|
|
861
|
+
const t0 = Date.now();
|
|
836
862
|
try {
|
|
837
|
-
console.log(`[IndexedDBTokenStorage] clear: starting, db=${this.dbName}, wasConnected=${!!this.db}`);
|
|
838
863
|
if (this.db) {
|
|
839
864
|
this.db.close();
|
|
840
865
|
this.db = null;
|
|
841
866
|
}
|
|
842
867
|
this.status = "disconnected";
|
|
843
|
-
const dbNames = [this.dbName];
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
const dbs = await Promise.race([
|
|
847
|
-
indexedDB.databases(),
|
|
848
|
-
new Promise(
|
|
849
|
-
(_, reject) => setTimeout(() => reject(new Error("timeout")), 1500)
|
|
850
|
-
)
|
|
851
|
-
]);
|
|
852
|
-
for (const dbInfo of dbs) {
|
|
853
|
-
if (dbInfo.name && dbInfo.name.startsWith(this.dbNamePrefix) && dbInfo.name !== this.dbName) {
|
|
854
|
-
dbNames.push(dbInfo.name);
|
|
855
|
-
}
|
|
856
|
-
}
|
|
857
|
-
} catch {
|
|
858
|
-
}
|
|
868
|
+
const dbNames = /* @__PURE__ */ new Set([this.dbName]);
|
|
869
|
+
for (const name of await this.findPrefixedDatabases()) {
|
|
870
|
+
dbNames.add(name);
|
|
859
871
|
}
|
|
860
|
-
console.log(`[IndexedDBTokenStorage] clear:
|
|
861
|
-
await Promise.
|
|
862
|
-
(name) =>
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
req.onblocked = () => {
|
|
874
|
-
console.warn(`[IndexedDBTokenStorage] clear: deleteDatabase blocked for db=${name}`);
|
|
875
|
-
resolve();
|
|
876
|
-
};
|
|
877
|
-
} catch {
|
|
878
|
-
resolve();
|
|
879
|
-
}
|
|
880
|
-
})
|
|
881
|
-
));
|
|
882
|
-
console.log(`[IndexedDBTokenStorage] clear: done`);
|
|
883
|
-
return true;
|
|
872
|
+
console.log(`[IndexedDBTokenStorage] clear: clearing ${dbNames.size} database(s) (${[...dbNames].join(", ")})`);
|
|
873
|
+
const results = await Promise.allSettled(
|
|
874
|
+
[...dbNames].map((name) => this.clearDatabaseStores(name))
|
|
875
|
+
);
|
|
876
|
+
const failed = results.filter((r) => r.status === "rejected");
|
|
877
|
+
if (failed.length > 0) {
|
|
878
|
+
console.warn(
|
|
879
|
+
`[IndexedDBTokenStorage] clear: ${failed.length}/${dbNames.size} failed (${Date.now() - t0}ms)`,
|
|
880
|
+
failed.map((r) => r.reason)
|
|
881
|
+
);
|
|
882
|
+
}
|
|
883
|
+
console.log(`[IndexedDBTokenStorage] clear: done ${dbNames.size} database(s) (${Date.now() - t0}ms)`);
|
|
884
|
+
return failed.length === 0;
|
|
884
885
|
} catch (err) {
|
|
885
|
-
console.warn(
|
|
886
|
+
console.warn(`[IndexedDBTokenStorage] clear: failed (${Date.now() - t0}ms)`, err);
|
|
886
887
|
return false;
|
|
887
888
|
}
|
|
888
889
|
}
|
|
@@ -892,11 +893,23 @@ var IndexedDBTokenStorageProvider = class {
|
|
|
892
893
|
openDatabase() {
|
|
893
894
|
return new Promise((resolve, reject) => {
|
|
894
895
|
const request = indexedDB.open(this.dbName, DB_VERSION2);
|
|
895
|
-
request.onerror = () =>
|
|
896
|
-
reject(request.error);
|
|
897
|
-
};
|
|
896
|
+
request.onerror = () => reject(request.error);
|
|
898
897
|
request.onsuccess = () => {
|
|
899
|
-
|
|
898
|
+
const db = request.result;
|
|
899
|
+
const cid = ++connectionSeq2;
|
|
900
|
+
this.connId = cid;
|
|
901
|
+
db.onversionchange = () => {
|
|
902
|
+
console.log(`[IndexedDBTokenStorage] onversionchange: auto-closing db=${this.dbName} connId=${cid}`);
|
|
903
|
+
db.close();
|
|
904
|
+
if (this.db === db) {
|
|
905
|
+
this.db = null;
|
|
906
|
+
this.status = "disconnected";
|
|
907
|
+
}
|
|
908
|
+
};
|
|
909
|
+
resolve(db);
|
|
910
|
+
};
|
|
911
|
+
request.onblocked = () => {
|
|
912
|
+
console.warn(`[IndexedDBTokenStorage] open blocked by another connection, db=${this.dbName}`);
|
|
900
913
|
};
|
|
901
914
|
request.onupgradeneeded = (event) => {
|
|
902
915
|
const db = event.target.result;
|
|
@@ -961,18 +974,70 @@ var IndexedDBTokenStorageProvider = class {
|
|
|
961
974
|
request.onsuccess = () => resolve();
|
|
962
975
|
});
|
|
963
976
|
}
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
977
|
+
/**
|
|
978
|
+
* Find all IndexedDB databases with our prefix.
|
|
979
|
+
* Returns empty array if indexedDB.databases() is unavailable (older browsers).
|
|
980
|
+
*/
|
|
981
|
+
async findPrefixedDatabases() {
|
|
982
|
+
if (typeof indexedDB.databases !== "function") return [];
|
|
983
|
+
try {
|
|
984
|
+
const allDbs = await Promise.race([
|
|
985
|
+
indexedDB.databases(),
|
|
986
|
+
new Promise(
|
|
987
|
+
(_, reject) => setTimeout(() => reject(new Error("databases() timed out")), 1500)
|
|
988
|
+
)
|
|
989
|
+
]);
|
|
990
|
+
return allDbs.map((info) => info.name).filter((name) => !!name && name.startsWith(this.dbNamePrefix));
|
|
991
|
+
} catch {
|
|
992
|
+
return [];
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
/**
|
|
996
|
+
* Clear all object stores in a single database.
|
|
997
|
+
* Opens a temporary connection, clears STORE_TOKENS and STORE_META, then closes.
|
|
998
|
+
* Uses IDBObjectStore.clear() which is a normal readwrite transaction — cannot
|
|
999
|
+
* be blocked by other connections (unlike deleteDatabase()).
|
|
1000
|
+
*/
|
|
1001
|
+
async clearDatabaseStores(dbName) {
|
|
1002
|
+
const db = await Promise.race([
|
|
1003
|
+
new Promise((resolve, reject) => {
|
|
1004
|
+
const req = indexedDB.open(dbName, DB_VERSION2);
|
|
1005
|
+
req.onerror = () => reject(req.error);
|
|
1006
|
+
req.onsuccess = () => {
|
|
1007
|
+
const db2 = req.result;
|
|
1008
|
+
db2.onversionchange = () => {
|
|
1009
|
+
db2.close();
|
|
1010
|
+
};
|
|
1011
|
+
resolve(db2);
|
|
1012
|
+
};
|
|
1013
|
+
req.onupgradeneeded = (event) => {
|
|
1014
|
+
const db2 = event.target.result;
|
|
1015
|
+
if (!db2.objectStoreNames.contains(STORE_TOKENS)) {
|
|
1016
|
+
db2.createObjectStore(STORE_TOKENS, { keyPath: "id" });
|
|
1017
|
+
}
|
|
1018
|
+
if (!db2.objectStoreNames.contains(STORE_META)) {
|
|
1019
|
+
db2.createObjectStore(STORE_META);
|
|
1020
|
+
}
|
|
1021
|
+
};
|
|
1022
|
+
}),
|
|
1023
|
+
new Promise(
|
|
1024
|
+
(_, reject) => setTimeout(() => reject(new Error(`open timed out: ${dbName}`)), 3e3)
|
|
1025
|
+
)
|
|
1026
|
+
]);
|
|
1027
|
+
try {
|
|
1028
|
+
for (const storeName of [STORE_TOKENS, STORE_META]) {
|
|
1029
|
+
if (db.objectStoreNames.contains(storeName)) {
|
|
1030
|
+
await new Promise((resolve, reject) => {
|
|
1031
|
+
const tx = db.transaction(storeName, "readwrite");
|
|
1032
|
+
const req = tx.objectStore(storeName).clear();
|
|
1033
|
+
req.onerror = () => reject(req.error);
|
|
1034
|
+
req.onsuccess = () => resolve();
|
|
1035
|
+
});
|
|
1036
|
+
}
|
|
969
1037
|
}
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
request.onerror = () => reject(request.error);
|
|
974
|
-
request.onsuccess = () => resolve();
|
|
975
|
-
});
|
|
1038
|
+
} finally {
|
|
1039
|
+
db.close();
|
|
1040
|
+
}
|
|
976
1041
|
}
|
|
977
1042
|
};
|
|
978
1043
|
function createIndexedDBTokenStorageProvider(config) {
|