@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
|
@@ -414,6 +414,7 @@ function createLocalStorageProvider(config) {
|
|
|
414
414
|
var DB_NAME = "sphere-storage";
|
|
415
415
|
var DB_VERSION = 1;
|
|
416
416
|
var STORE_NAME = "kv";
|
|
417
|
+
var connectionSeq = 0;
|
|
417
418
|
var IndexedDBStorageProvider = class {
|
|
418
419
|
id = "indexeddb-storage";
|
|
419
420
|
name = "IndexedDB Storage";
|
|
@@ -425,6 +426,8 @@ var IndexedDBStorageProvider = class {
|
|
|
425
426
|
identity = null;
|
|
426
427
|
status = "disconnected";
|
|
427
428
|
db = null;
|
|
429
|
+
/** Monotonic connection ID for tracing open/close pairs */
|
|
430
|
+
connId = 0;
|
|
428
431
|
constructor(config) {
|
|
429
432
|
this.prefix = config?.prefix ?? "sphere_";
|
|
430
433
|
this.dbName = config?.dbName ?? DB_NAME;
|
|
@@ -437,7 +440,8 @@ var IndexedDBStorageProvider = class {
|
|
|
437
440
|
if (this.status === "connected" && this.db) return;
|
|
438
441
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
439
442
|
this.status = "connecting";
|
|
440
|
-
|
|
443
|
+
const t0 = Date.now();
|
|
444
|
+
console.log(`[IndexedDBStorage] connect: opening db=${this.dbName}, attempt=${attempt + 1}/2`);
|
|
441
445
|
try {
|
|
442
446
|
this.db = await Promise.race([
|
|
443
447
|
this.openDatabase(),
|
|
@@ -446,11 +450,11 @@ var IndexedDBStorageProvider = class {
|
|
|
446
450
|
)
|
|
447
451
|
]);
|
|
448
452
|
this.status = "connected";
|
|
449
|
-
console.log(`[IndexedDBStorage] connect: connected
|
|
453
|
+
console.log(`[IndexedDBStorage] connect: connected db=${this.dbName} connId=${this.connId} (${Date.now() - t0}ms)`);
|
|
450
454
|
return;
|
|
451
455
|
} catch (error) {
|
|
456
|
+
console.warn(`[IndexedDBStorage] connect: open failed db=${this.dbName} attempt=${attempt + 1} (${Date.now() - t0}ms):`, error);
|
|
452
457
|
if (attempt === 0) {
|
|
453
|
-
console.warn(`[IndexedDBStorage] connect: open failed, retrying in 1s...`);
|
|
454
458
|
this.status = "disconnected";
|
|
455
459
|
await new Promise((r) => setTimeout(r, 1e3));
|
|
456
460
|
continue;
|
|
@@ -461,7 +465,8 @@ var IndexedDBStorageProvider = class {
|
|
|
461
465
|
}
|
|
462
466
|
}
|
|
463
467
|
async disconnect() {
|
|
464
|
-
|
|
468
|
+
const cid = this.connId;
|
|
469
|
+
console.log(`[IndexedDBStorage] disconnect: db=${this.dbName} connId=${cid} wasConnected=${!!this.db}`);
|
|
465
470
|
if (this.db) {
|
|
466
471
|
this.db.close();
|
|
467
472
|
this.db = null;
|
|
@@ -518,37 +523,36 @@ var IndexedDBStorageProvider = class {
|
|
|
518
523
|
}
|
|
519
524
|
async clear(prefix) {
|
|
520
525
|
if (!prefix) {
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
req.onerror = () => {
|
|
540
|
-
clearTimeout(timer);
|
|
541
|
-
console.warn(`[IndexedDBStorage] clear: error deleting db=${this.dbName}`, req.error);
|
|
542
|
-
resolve();
|
|
543
|
-
};
|
|
544
|
-
req.onblocked = () => {
|
|
545
|
-
console.warn(`[IndexedDBStorage] clear: deleteDatabase blocked for db=${this.dbName}, waiting...`);
|
|
546
|
-
};
|
|
547
|
-
} catch {
|
|
548
|
-
resolve();
|
|
526
|
+
const t0 = Date.now();
|
|
527
|
+
const prevConnId = this.connId;
|
|
528
|
+
console.log(`[IndexedDBStorage] clear: starting db=${this.dbName} connId=${prevConnId} status=${this.status} hasDb=${!!this.db}`);
|
|
529
|
+
try {
|
|
530
|
+
if (!this.db || this.status !== "connected") {
|
|
531
|
+
if (this.db) {
|
|
532
|
+
console.log(`[IndexedDBStorage] clear: closing stale handle connId=${prevConnId}`);
|
|
533
|
+
this.db.close();
|
|
534
|
+
this.db = null;
|
|
535
|
+
}
|
|
536
|
+
console.log(`[IndexedDBStorage] clear: opening fresh connection for wipe`);
|
|
537
|
+
this.db = await Promise.race([
|
|
538
|
+
this.openDatabase(),
|
|
539
|
+
new Promise(
|
|
540
|
+
(_, reject) => setTimeout(() => reject(new Error("open timed out")), 3e3)
|
|
541
|
+
)
|
|
542
|
+
]);
|
|
543
|
+
this.status = "connected";
|
|
549
544
|
}
|
|
550
|
-
|
|
551
|
-
|
|
545
|
+
await this.idbClear();
|
|
546
|
+
console.log(`[IndexedDBStorage] clear: store cleared db=${this.dbName} connId=${this.connId} (${Date.now() - t0}ms)`);
|
|
547
|
+
} catch (err) {
|
|
548
|
+
console.warn(`[IndexedDBStorage] clear: failed db=${this.dbName} (${Date.now() - t0}ms)`, err);
|
|
549
|
+
} finally {
|
|
550
|
+
if (this.db) {
|
|
551
|
+
this.db.close();
|
|
552
|
+
this.db = null;
|
|
553
|
+
}
|
|
554
|
+
this.status = "disconnected";
|
|
555
|
+
}
|
|
552
556
|
return;
|
|
553
557
|
}
|
|
554
558
|
this.ensureConnected();
|
|
@@ -614,9 +618,22 @@ var IndexedDBStorageProvider = class {
|
|
|
614
618
|
return new Promise((resolve, reject) => {
|
|
615
619
|
const request = indexedDB.open(this.dbName, DB_VERSION);
|
|
616
620
|
request.onerror = () => reject(request.error);
|
|
617
|
-
request.onsuccess = () =>
|
|
621
|
+
request.onsuccess = () => {
|
|
622
|
+
const db = request.result;
|
|
623
|
+
const cid = ++connectionSeq;
|
|
624
|
+
this.connId = cid;
|
|
625
|
+
db.onversionchange = () => {
|
|
626
|
+
console.log(`[IndexedDBStorage] onversionchange: auto-closing db=${this.dbName} connId=${cid}`);
|
|
627
|
+
db.close();
|
|
628
|
+
if (this.db === db) {
|
|
629
|
+
this.db = null;
|
|
630
|
+
this.status = "disconnected";
|
|
631
|
+
}
|
|
632
|
+
};
|
|
633
|
+
resolve(db);
|
|
634
|
+
};
|
|
618
635
|
request.onblocked = () => {
|
|
619
|
-
console.warn(
|
|
636
|
+
console.warn(`[IndexedDBStorage] open blocked by another connection, db=${this.dbName}`);
|
|
620
637
|
};
|
|
621
638
|
request.onupgradeneeded = (event) => {
|
|
622
639
|
const db = event.target.result;
|
|
@@ -695,18 +712,23 @@ var DB_NAME2 = "sphere-token-storage";
|
|
|
695
712
|
var DB_VERSION2 = 1;
|
|
696
713
|
var STORE_TOKENS = "tokens";
|
|
697
714
|
var STORE_META = "meta";
|
|
715
|
+
var connectionSeq2 = 0;
|
|
698
716
|
var IndexedDBTokenStorageProvider = class {
|
|
699
717
|
id = "indexeddb-token-storage";
|
|
700
718
|
name = "IndexedDB Token Storage";
|
|
701
719
|
type = "local";
|
|
702
720
|
dbNamePrefix;
|
|
703
721
|
dbName;
|
|
722
|
+
debug;
|
|
704
723
|
db = null;
|
|
705
724
|
status = "disconnected";
|
|
706
725
|
identity = null;
|
|
726
|
+
/** Monotonic connection ID for tracing open/close pairs */
|
|
727
|
+
connId = 0;
|
|
707
728
|
constructor(config) {
|
|
708
729
|
this.dbNamePrefix = config?.dbNamePrefix ?? DB_NAME2;
|
|
709
730
|
this.dbName = this.dbNamePrefix;
|
|
731
|
+
this.debug = config?.debug ?? false;
|
|
710
732
|
}
|
|
711
733
|
setIdentity(identity) {
|
|
712
734
|
this.identity = identity;
|
|
@@ -714,28 +736,31 @@ var IndexedDBTokenStorageProvider = class {
|
|
|
714
736
|
const addressId = getAddressId(identity.directAddress);
|
|
715
737
|
this.dbName = `${this.dbNamePrefix}-${addressId}`;
|
|
716
738
|
}
|
|
717
|
-
console.log(`[IndexedDBTokenStorage] setIdentity
|
|
739
|
+
console.log(`[IndexedDBTokenStorage] setIdentity: db=${this.dbName}`);
|
|
718
740
|
}
|
|
719
741
|
async initialize() {
|
|
742
|
+
const prevConnId = this.connId;
|
|
743
|
+
const t0 = Date.now();
|
|
720
744
|
try {
|
|
721
745
|
if (this.db) {
|
|
722
|
-
console.log(`[IndexedDBTokenStorage] initialize: closing existing
|
|
746
|
+
console.log(`[IndexedDBTokenStorage] initialize: closing existing connId=${prevConnId} before re-open (db=${this.dbName})`);
|
|
723
747
|
this.db.close();
|
|
724
748
|
this.db = null;
|
|
725
749
|
}
|
|
726
750
|
console.log(`[IndexedDBTokenStorage] initialize: opening db=${this.dbName}`);
|
|
727
751
|
this.db = await this.openDatabase();
|
|
728
752
|
this.status = "connected";
|
|
729
|
-
console.log(`[IndexedDBTokenStorage] initialize: connected
|
|
753
|
+
console.log(`[IndexedDBTokenStorage] initialize: connected db=${this.dbName} connId=${this.connId} (${Date.now() - t0}ms)`);
|
|
730
754
|
return true;
|
|
731
755
|
} catch (error) {
|
|
732
|
-
console.error(
|
|
756
|
+
console.error(`[IndexedDBTokenStorage] initialize: failed db=${this.dbName} (${Date.now() - t0}ms):`, error);
|
|
733
757
|
this.status = "error";
|
|
734
758
|
return false;
|
|
735
759
|
}
|
|
736
760
|
}
|
|
737
761
|
async shutdown() {
|
|
738
|
-
|
|
762
|
+
const cid = this.connId;
|
|
763
|
+
console.log(`[IndexedDBTokenStorage] shutdown: db=${this.dbName} connId=${cid} wasConnected=${!!this.db}`);
|
|
739
764
|
if (this.db) {
|
|
740
765
|
this.db.close();
|
|
741
766
|
this.db = null;
|
|
@@ -893,56 +918,32 @@ var IndexedDBTokenStorageProvider = class {
|
|
|
893
918
|
return meta !== null;
|
|
894
919
|
}
|
|
895
920
|
async clear() {
|
|
921
|
+
const t0 = Date.now();
|
|
896
922
|
try {
|
|
897
|
-
console.log(`[IndexedDBTokenStorage] clear: starting, db=${this.dbName}, wasConnected=${!!this.db}`);
|
|
898
923
|
if (this.db) {
|
|
899
924
|
this.db.close();
|
|
900
925
|
this.db = null;
|
|
901
926
|
}
|
|
902
927
|
this.status = "disconnected";
|
|
903
|
-
const dbNames = [this.dbName];
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
const dbs = await Promise.race([
|
|
907
|
-
indexedDB.databases(),
|
|
908
|
-
new Promise(
|
|
909
|
-
(_, reject) => setTimeout(() => reject(new Error("timeout")), 1500)
|
|
910
|
-
)
|
|
911
|
-
]);
|
|
912
|
-
for (const dbInfo of dbs) {
|
|
913
|
-
if (dbInfo.name && dbInfo.name.startsWith(this.dbNamePrefix) && dbInfo.name !== this.dbName) {
|
|
914
|
-
dbNames.push(dbInfo.name);
|
|
915
|
-
}
|
|
916
|
-
}
|
|
917
|
-
} catch {
|
|
918
|
-
}
|
|
928
|
+
const dbNames = /* @__PURE__ */ new Set([this.dbName]);
|
|
929
|
+
for (const name of await this.findPrefixedDatabases()) {
|
|
930
|
+
dbNames.add(name);
|
|
919
931
|
}
|
|
920
|
-
console.log(`[IndexedDBTokenStorage] clear:
|
|
921
|
-
await Promise.
|
|
922
|
-
(name) =>
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
req.onblocked = () => {
|
|
934
|
-
console.warn(`[IndexedDBTokenStorage] clear: deleteDatabase blocked for db=${name}`);
|
|
935
|
-
resolve();
|
|
936
|
-
};
|
|
937
|
-
} catch {
|
|
938
|
-
resolve();
|
|
939
|
-
}
|
|
940
|
-
})
|
|
941
|
-
));
|
|
942
|
-
console.log(`[IndexedDBTokenStorage] clear: done`);
|
|
943
|
-
return true;
|
|
932
|
+
console.log(`[IndexedDBTokenStorage] clear: clearing ${dbNames.size} database(s) (${[...dbNames].join(", ")})`);
|
|
933
|
+
const results = await Promise.allSettled(
|
|
934
|
+
[...dbNames].map((name) => this.clearDatabaseStores(name))
|
|
935
|
+
);
|
|
936
|
+
const failed = results.filter((r) => r.status === "rejected");
|
|
937
|
+
if (failed.length > 0) {
|
|
938
|
+
console.warn(
|
|
939
|
+
`[IndexedDBTokenStorage] clear: ${failed.length}/${dbNames.size} failed (${Date.now() - t0}ms)`,
|
|
940
|
+
failed.map((r) => r.reason)
|
|
941
|
+
);
|
|
942
|
+
}
|
|
943
|
+
console.log(`[IndexedDBTokenStorage] clear: done ${dbNames.size} database(s) (${Date.now() - t0}ms)`);
|
|
944
|
+
return failed.length === 0;
|
|
944
945
|
} catch (err) {
|
|
945
|
-
console.warn(
|
|
946
|
+
console.warn(`[IndexedDBTokenStorage] clear: failed (${Date.now() - t0}ms)`, err);
|
|
946
947
|
return false;
|
|
947
948
|
}
|
|
948
949
|
}
|
|
@@ -952,11 +953,23 @@ var IndexedDBTokenStorageProvider = class {
|
|
|
952
953
|
openDatabase() {
|
|
953
954
|
return new Promise((resolve, reject) => {
|
|
954
955
|
const request = indexedDB.open(this.dbName, DB_VERSION2);
|
|
955
|
-
request.onerror = () =>
|
|
956
|
-
reject(request.error);
|
|
957
|
-
};
|
|
956
|
+
request.onerror = () => reject(request.error);
|
|
958
957
|
request.onsuccess = () => {
|
|
959
|
-
|
|
958
|
+
const db = request.result;
|
|
959
|
+
const cid = ++connectionSeq2;
|
|
960
|
+
this.connId = cid;
|
|
961
|
+
db.onversionchange = () => {
|
|
962
|
+
console.log(`[IndexedDBTokenStorage] onversionchange: auto-closing db=${this.dbName} connId=${cid}`);
|
|
963
|
+
db.close();
|
|
964
|
+
if (this.db === db) {
|
|
965
|
+
this.db = null;
|
|
966
|
+
this.status = "disconnected";
|
|
967
|
+
}
|
|
968
|
+
};
|
|
969
|
+
resolve(db);
|
|
970
|
+
};
|
|
971
|
+
request.onblocked = () => {
|
|
972
|
+
console.warn(`[IndexedDBTokenStorage] open blocked by another connection, db=${this.dbName}`);
|
|
960
973
|
};
|
|
961
974
|
request.onupgradeneeded = (event) => {
|
|
962
975
|
const db = event.target.result;
|
|
@@ -1021,18 +1034,70 @@ var IndexedDBTokenStorageProvider = class {
|
|
|
1021
1034
|
request.onsuccess = () => resolve();
|
|
1022
1035
|
});
|
|
1023
1036
|
}
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1037
|
+
/**
|
|
1038
|
+
* Find all IndexedDB databases with our prefix.
|
|
1039
|
+
* Returns empty array if indexedDB.databases() is unavailable (older browsers).
|
|
1040
|
+
*/
|
|
1041
|
+
async findPrefixedDatabases() {
|
|
1042
|
+
if (typeof indexedDB.databases !== "function") return [];
|
|
1043
|
+
try {
|
|
1044
|
+
const allDbs = await Promise.race([
|
|
1045
|
+
indexedDB.databases(),
|
|
1046
|
+
new Promise(
|
|
1047
|
+
(_, reject) => setTimeout(() => reject(new Error("databases() timed out")), 1500)
|
|
1048
|
+
)
|
|
1049
|
+
]);
|
|
1050
|
+
return allDbs.map((info) => info.name).filter((name) => !!name && name.startsWith(this.dbNamePrefix));
|
|
1051
|
+
} catch {
|
|
1052
|
+
return [];
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
/**
|
|
1056
|
+
* Clear all object stores in a single database.
|
|
1057
|
+
* Opens a temporary connection, clears STORE_TOKENS and STORE_META, then closes.
|
|
1058
|
+
* Uses IDBObjectStore.clear() which is a normal readwrite transaction — cannot
|
|
1059
|
+
* be blocked by other connections (unlike deleteDatabase()).
|
|
1060
|
+
*/
|
|
1061
|
+
async clearDatabaseStores(dbName) {
|
|
1062
|
+
const db = await Promise.race([
|
|
1063
|
+
new Promise((resolve, reject) => {
|
|
1064
|
+
const req = indexedDB.open(dbName, DB_VERSION2);
|
|
1065
|
+
req.onerror = () => reject(req.error);
|
|
1066
|
+
req.onsuccess = () => {
|
|
1067
|
+
const db2 = req.result;
|
|
1068
|
+
db2.onversionchange = () => {
|
|
1069
|
+
db2.close();
|
|
1070
|
+
};
|
|
1071
|
+
resolve(db2);
|
|
1072
|
+
};
|
|
1073
|
+
req.onupgradeneeded = (event) => {
|
|
1074
|
+
const db2 = event.target.result;
|
|
1075
|
+
if (!db2.objectStoreNames.contains(STORE_TOKENS)) {
|
|
1076
|
+
db2.createObjectStore(STORE_TOKENS, { keyPath: "id" });
|
|
1077
|
+
}
|
|
1078
|
+
if (!db2.objectStoreNames.contains(STORE_META)) {
|
|
1079
|
+
db2.createObjectStore(STORE_META);
|
|
1080
|
+
}
|
|
1081
|
+
};
|
|
1082
|
+
}),
|
|
1083
|
+
new Promise(
|
|
1084
|
+
(_, reject) => setTimeout(() => reject(new Error(`open timed out: ${dbName}`)), 3e3)
|
|
1085
|
+
)
|
|
1086
|
+
]);
|
|
1087
|
+
try {
|
|
1088
|
+
for (const storeName of [STORE_TOKENS, STORE_META]) {
|
|
1089
|
+
if (db.objectStoreNames.contains(storeName)) {
|
|
1090
|
+
await new Promise((resolve, reject) => {
|
|
1091
|
+
const tx = db.transaction(storeName, "readwrite");
|
|
1092
|
+
const req = tx.objectStore(storeName).clear();
|
|
1093
|
+
req.onerror = () => reject(req.error);
|
|
1094
|
+
req.onsuccess = () => resolve();
|
|
1095
|
+
});
|
|
1096
|
+
}
|
|
1029
1097
|
}
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
request.onerror = () => reject(request.error);
|
|
1034
|
-
request.onsuccess = () => resolve();
|
|
1035
|
-
});
|
|
1098
|
+
} finally {
|
|
1099
|
+
db.close();
|
|
1100
|
+
}
|
|
1036
1101
|
}
|
|
1037
1102
|
};
|
|
1038
1103
|
function createIndexedDBTokenStorageProvider(config) {
|