@sovereignbase/explorer 0.0.0-alpha.4 → 0.0.0-alpha.6
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/class.cjs +166 -70
- package/dist/class.cjs.map +1 -1
- package/dist/class.d.cts +122 -44
- package/dist/class.d.cts.map +1 -1
- package/dist/class.d.ts +122 -44
- package/dist/class.d.ts.map +1 -1
- package/dist/class.js +167 -72
- package/dist/class.js.map +1 -1
- package/package.json +5 -4
package/dist/class.js
CHANGED
|
@@ -18,7 +18,7 @@ import { deleteObject, loadObject, storeObject } from "@sovereignbase/storage";
|
|
|
18
18
|
import { afterIdleFor, isRecord } from "@sovereignbase/utils";
|
|
19
19
|
import { Bytes } from "@sovereignbase/bytecodec";
|
|
20
20
|
import { readableUserAgent } from "@sovereignbase/dom-utils";
|
|
21
|
-
import {
|
|
21
|
+
import { accessDeviceBinding, createDeviceBinding, invalidateDeviceBinding } from "@sovereignbase/hardware-bound";
|
|
22
22
|
import { Cryptographic } from "@sovereignbase/cryptosuite";
|
|
23
23
|
import { Sequenced } from "@sovereignbase/sequenced";
|
|
24
24
|
// src/.errors/class.ts
|
|
@@ -56,10 +56,11 @@ function unknownError(cause, operation) {
|
|
|
56
56
|
}
|
|
57
57
|
// src/CredentialEntries/class.ts
|
|
58
58
|
/**
|
|
59
|
-
* Maintains the database's
|
|
59
|
+
* Maintains the database's registered credentials.
|
|
60
60
|
*
|
|
61
|
-
* Entries are identified by
|
|
62
|
-
* a sequenced array
|
|
61
|
+
* Entries are identified by their object and credential identifiers.
|
|
62
|
+
* Changes are synchronized through a sequenced array and persisted
|
|
63
|
+
* as encrypted snapshots.
|
|
63
64
|
*/
|
|
64
65
|
var CredentialEntries = class {
|
|
65
66
|
id;
|
|
@@ -73,7 +74,7 @@ var CredentialEntries = class {
|
|
|
73
74
|
*
|
|
74
75
|
* @param id The identifier of the persisted entries object.
|
|
75
76
|
* @param cipherKey The key used to encrypt the entries object.
|
|
76
|
-
* @param sessionCredentialID The credential ID of the current session.
|
|
77
|
+
* @param sessionCredentialID The WebAuthn credential ID of the current session.
|
|
77
78
|
* @param actorID The actor identifier used by the sequenced array.
|
|
78
79
|
* @param trustedSnapshot An optional snapshot used to initialize the state.
|
|
79
80
|
*/
|
|
@@ -99,13 +100,17 @@ var CredentialEntries = class {
|
|
|
99
100
|
this.state.addEventListener("change", ({ detail }) => {
|
|
100
101
|
this.dispatchEvent("change", detail);
|
|
101
102
|
});
|
|
102
|
-
const
|
|
103
|
+
const seenObjects = /* @__PURE__ */ new Set();
|
|
104
|
+
const seenCredentials = /* @__PURE__ */ new Set();
|
|
103
105
|
const duplicates = [];
|
|
104
106
|
for (let index = 0; index < this.state.length; index++) {
|
|
105
107
|
const entry = this.state.at(index);
|
|
106
108
|
if (!entry) continue;
|
|
107
|
-
if (
|
|
108
|
-
else
|
|
109
|
+
if (seenObjects.has(entry.objectID) || seenCredentials.has(entry.credentialID)) duplicates.push(index);
|
|
110
|
+
else {
|
|
111
|
+
seenObjects.add(entry.objectID);
|
|
112
|
+
seenCredentials.add(entry.credentialID);
|
|
113
|
+
}
|
|
109
114
|
}
|
|
110
115
|
for (let index = duplicates.length - 1; index >= 0; index--) this.state.delete(duplicates[index]);
|
|
111
116
|
if (duplicates.length > 0 || this.deltaBuffer.length > 0) this.state.snapshot();
|
|
@@ -126,17 +131,17 @@ var CredentialEntries = class {
|
|
|
126
131
|
record(credentialEvent) {
|
|
127
132
|
try {
|
|
128
133
|
if (!credentialEvent || typeof credentialEvent !== "object") throw new ExplorerError("INVALID_CREDENTIAL_EVENT", "A credential event must be an object.");
|
|
129
|
-
const {
|
|
130
|
-
if (typeof
|
|
134
|
+
const { objectID, credentialID, timestamp, userAgent, name, entropy, storage } = credentialEvent;
|
|
135
|
+
if (typeof objectID !== "string" || typeof timestamp !== "number" || !Number.isFinite(timestamp) || typeof userAgent !== "string") throw new ExplorerError("INVALID_CREDENTIAL_EVENT", "A credential event requires an object ID, a finite timestamp, and a user agent.");
|
|
131
136
|
let existing;
|
|
132
137
|
for (let index = this.state.length - 1; index >= 0; index--) {
|
|
133
138
|
const entry = this.state.at(index);
|
|
134
|
-
if (entry?.
|
|
139
|
+
if (entry?.objectID === objectID || credentialID !== void 0 && entry?.credentialID === credentialID) {
|
|
135
140
|
existing = entry;
|
|
136
141
|
break;
|
|
137
142
|
}
|
|
138
143
|
}
|
|
139
|
-
if (!existing && (typeof name !== "string" || !(entropy instanceof Uint8Array) || typeof storage !== "string")) throw new ExplorerError("MISSING_CREDENTIAL_SETUP_PROPERTIES", "A new credential requires a name, entropy, and binding storage.");
|
|
144
|
+
if (!existing && (typeof credentialID !== "string" || typeof name !== "string" || !(entropy instanceof Uint8Array) || typeof storage !== "string")) throw new ExplorerError("MISSING_CREDENTIAL_SETUP_PROPERTIES", "A new credential requires a credential ID, name, entropy, and binding storage.");
|
|
140
145
|
const userAgents = existing?.userAgents.map((agent) => ({ ...agent })) ?? [];
|
|
141
146
|
const agent = userAgents.find((agent) => agent.name === userAgent);
|
|
142
147
|
if (agent) agent.lastSeen = Math.max(agent.lastSeen, timestamp);
|
|
@@ -145,14 +150,18 @@ var CredentialEntries = class {
|
|
|
145
150
|
lastSeen: timestamp
|
|
146
151
|
});
|
|
147
152
|
const entry = {
|
|
148
|
-
|
|
153
|
+
objectID,
|
|
154
|
+
credentialID: credentialID ?? existing.credentialID,
|
|
149
155
|
name: name ?? existing.name,
|
|
150
156
|
entropy: entropy ?? existing.entropy,
|
|
151
157
|
storage: storage ?? existing.storage,
|
|
152
158
|
lastUsed: Math.max(existing?.lastUsed ?? timestamp, timestamp),
|
|
153
159
|
userAgents
|
|
154
160
|
};
|
|
155
|
-
for (let index = this.state.length - 1; index >= 0; index--)
|
|
161
|
+
for (let index = this.state.length - 1; index >= 0; index--) {
|
|
162
|
+
const current = this.state.at(index);
|
|
163
|
+
if (current?.objectID === entry.objectID || current?.credentialID === entry.credentialID) this.state.delete(index);
|
|
164
|
+
}
|
|
156
165
|
this.state.unshift(entry);
|
|
157
166
|
this.state.snapshot();
|
|
158
167
|
} catch (cause) {
|
|
@@ -160,24 +169,33 @@ var CredentialEntries = class {
|
|
|
160
169
|
}
|
|
161
170
|
}
|
|
162
171
|
/**
|
|
163
|
-
* Revokes a credential
|
|
172
|
+
* Revokes a credential and removes its registered entries.
|
|
164
173
|
*
|
|
165
|
-
*
|
|
174
|
+
* Deletes the credential's persisted objects before removing its entries.
|
|
175
|
+
* The entries remain unchanged if deletion fails. Credential invalidation
|
|
176
|
+
* is requested on a best-effort basis after successful removal.
|
|
166
177
|
*
|
|
167
|
-
* @param credentialID The
|
|
178
|
+
* @param credentialID The WebAuthn credential identifier to revoke.
|
|
168
179
|
*/
|
|
169
180
|
async revoke(credentialID) {
|
|
170
181
|
try {
|
|
171
|
-
|
|
182
|
+
const objectIDs = /* @__PURE__ */ new Set();
|
|
172
183
|
for (let index = this.state.length - 1; index >= 0; index--) {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
break;
|
|
184
|
+
const entry = this.state.at(index);
|
|
185
|
+
if (entry?.credentialID === credentialID) objectIDs.add(entry.objectID);
|
|
176
186
|
}
|
|
177
|
-
if (
|
|
178
|
-
await Explorer.deleteObjectByID(
|
|
179
|
-
|
|
180
|
-
this.state.
|
|
187
|
+
if (objectIDs.size === 0) return;
|
|
188
|
+
for (const objectID of objectIDs) await Explorer.deleteObjectByID(objectID);
|
|
189
|
+
let removed = false;
|
|
190
|
+
for (let index = this.state.length - 1; index >= 0; index--) if (this.state.at(index)?.credentialID === credentialID) {
|
|
191
|
+
this.state.delete(index);
|
|
192
|
+
removed = true;
|
|
193
|
+
}
|
|
194
|
+
if (removed) this.state.snapshot();
|
|
195
|
+
try {
|
|
196
|
+
await invalidateDeviceBinding(credentialID);
|
|
197
|
+
} catch {}
|
|
198
|
+
if (credentialID === this.sessionCredentialID) window.location.reload();
|
|
181
199
|
} catch (cause) {
|
|
182
200
|
throw unknownError(cause, "CredentialEntries.revoke()");
|
|
183
201
|
}
|
|
@@ -185,11 +203,11 @@ var CredentialEntries = class {
|
|
|
185
203
|
/**
|
|
186
204
|
* Returns the credential entries ordered by most recent use.
|
|
187
205
|
*
|
|
188
|
-
* Entries with equal timestamps are ordered by identifier.
|
|
206
|
+
* Entries with equal timestamps are ordered by credential identifier.
|
|
189
207
|
*/
|
|
190
208
|
list() {
|
|
191
209
|
try {
|
|
192
|
-
return this.state.slice().sort((a, b) => b.lastUsed - a.lastUsed || a.
|
|
210
|
+
return this.state.slice().sort((a, b) => b.lastUsed - a.lastUsed || a.credentialID.localeCompare(b.credentialID));
|
|
193
211
|
} catch (cause) {
|
|
194
212
|
throw unknownError(cause, "CredentialEntries.list()");
|
|
195
213
|
}
|
|
@@ -438,20 +456,27 @@ var RecentEntries = class {
|
|
|
438
456
|
};
|
|
439
457
|
// src/class.ts
|
|
440
458
|
/**
|
|
441
|
-
* Provides
|
|
442
|
-
* the database's synchronized entries.
|
|
459
|
+
* Provides access to an authenticated Sovereignbase database.
|
|
443
460
|
*
|
|
444
|
-
*
|
|
445
|
-
*
|
|
461
|
+
* Manages database authentication, encrypted object storage, credential
|
|
462
|
+
* registration, database linking, and synchronized entries.
|
|
446
463
|
*/
|
|
447
464
|
var Explorer = class {
|
|
448
465
|
/** The identifier of the authenticated database. */
|
|
449
466
|
static databaseID;
|
|
450
|
-
/** Indicates whether
|
|
467
|
+
/** Indicates whether a database has been authenticated. */
|
|
451
468
|
static isAuthenticated;
|
|
469
|
+
/** The base URL used to access database objects. */
|
|
452
470
|
static storageURL;
|
|
471
|
+
/** The event target used for Explorer events. */
|
|
453
472
|
static eventTarget;
|
|
473
|
+
/** The data PIN associated with the current session. */
|
|
474
|
+
static dataPIN;
|
|
475
|
+
/** The virtual entropy associated with the authenticated database. */
|
|
476
|
+
static virtualEntropy;
|
|
477
|
+
/** The secret used to access the authenticated database. */
|
|
454
478
|
static databaseSecret;
|
|
479
|
+
/** The credential information associated with the current authentication. */
|
|
455
480
|
static sessionCredential = {};
|
|
456
481
|
/**
|
|
457
482
|
* Caches cipher keys by object identifier.
|
|
@@ -461,46 +486,50 @@ var Explorer = class {
|
|
|
461
486
|
*/
|
|
462
487
|
static cipherKeyCache = /* @__PURE__ */ new Map();
|
|
463
488
|
/**
|
|
464
|
-
* Authenticates a database using a data PIN and device
|
|
489
|
+
* Authenticates a database using a data PIN and an existing device binding.
|
|
490
|
+
*
|
|
491
|
+
* Establishes the authenticated database context and records the credential
|
|
492
|
+
* used for authentication.
|
|
465
493
|
*
|
|
466
|
-
*
|
|
467
|
-
*
|
|
468
|
-
* new credential. Otherwise, loads the existing credential.
|
|
494
|
+
* When setup parameters are provided, registers a credential using the
|
|
495
|
+
* supplied virtual entropy or generates new virtual entropy.
|
|
469
496
|
*
|
|
470
|
-
*
|
|
497
|
+
* @param dataPIN The PIN associated with the database.
|
|
498
|
+
* @param storageURL The base URL used to access database objects.
|
|
499
|
+
* @param setupParams Optional parameters for registering a credential.
|
|
471
500
|
*
|
|
472
|
-
* @param
|
|
473
|
-
* @param storageURL The base URL used to access persisted database objects.
|
|
474
|
-
* @param setupParams Optional parameters for creating a new credential.
|
|
501
|
+
* @param credentialId An optional credential identifier used to restrict credential selection.
|
|
475
502
|
* @returns The authentication result.
|
|
476
503
|
*/
|
|
477
|
-
static async authenticate(dataPIN, storageURL, setupParams) {
|
|
504
|
+
static async authenticate(dataPIN, storageURL, setupParams, credentialId) {
|
|
478
505
|
try {
|
|
506
|
+
this.dataPIN = dataPIN;
|
|
479
507
|
this.storageURL = storageURL;
|
|
480
|
-
const
|
|
481
|
-
if (!
|
|
508
|
+
const deviceBinding = await accessDeviceBinding(credentialId);
|
|
509
|
+
if (!Array.isArray(deviceBinding)) return "authenticator-error";
|
|
510
|
+
const [credentialID, deviceEntropy] = deviceBinding;
|
|
482
511
|
this.sessionCredential = {
|
|
483
512
|
timestamp: Date.now(),
|
|
484
513
|
userAgent: readableUserAgent()
|
|
485
514
|
};
|
|
486
515
|
const dataPINBytes = Bytes.utf8.decode(dataPIN);
|
|
487
516
|
const credentialSecret = await Bytes.derive(deviceEntropy, dataPINBytes, 32);
|
|
488
|
-
const
|
|
489
|
-
this.sessionCredential.
|
|
517
|
+
const credentialObjectID = await Cryptographic.identifier.derive(credentialSecret, Bytes.utf8.decode("@sovereignbase/explorer:CredentialObjectID"), 32);
|
|
518
|
+
this.sessionCredential.objectID = credentialObjectID;
|
|
519
|
+
this.sessionCredential.credentialID = credentialID;
|
|
490
520
|
const credentialCipherKey = await Cryptographic.cipherMessage.deriveKey(credentialSecret, Bytes.utf8.decode("@sovereignbase/explorer:CredentialCipherKey"));
|
|
491
|
-
let virtualEntropy;
|
|
492
521
|
if (isRecord(setupParams)) {
|
|
493
|
-
virtualEntropy = Bytes.generate(64);
|
|
494
|
-
await this.storeObjectByID(
|
|
522
|
+
this.virtualEntropy = setupParams.virtualEntropy instanceof Uint8Array ? setupParams.virtualEntropy : Bytes.generate(64);
|
|
523
|
+
await this.storeObjectByID(credentialObjectID, this.virtualEntropy, credentialCipherKey);
|
|
495
524
|
this.sessionCredential.name = setupParams.credentialName;
|
|
496
525
|
this.sessionCredential.entropy = deviceEntropy;
|
|
497
526
|
this.sessionCredential.storage = setupParams.bindingStorage;
|
|
498
527
|
} else {
|
|
499
|
-
const result = await this.loadObjectByID(
|
|
528
|
+
const result = await this.loadObjectByID(credentialObjectID, credentialCipherKey);
|
|
500
529
|
if (!(result instanceof Uint8Array) || result.byteLength !== 64) return "invalid-data-pin";
|
|
501
|
-
virtualEntropy = result;
|
|
530
|
+
this.virtualEntropy = result;
|
|
502
531
|
}
|
|
503
|
-
this.databaseSecret = await Bytes.derive(virtualEntropy, dataPINBytes, 64);
|
|
532
|
+
this.databaseSecret = await Bytes.derive(this.virtualEntropy, dataPINBytes, 64);
|
|
504
533
|
this.databaseID = await Cryptographic.identifier.derive(this.databaseSecret, Bytes.utf8.decode("@sovereignbase/explorer:DatabaseID"), 32);
|
|
505
534
|
this.isAuthenticated = true;
|
|
506
535
|
(await this.loadCredentialEntries()).record(this.sessionCredential);
|
|
@@ -511,10 +540,71 @@ var Explorer = class {
|
|
|
511
540
|
throw unknownError(cause, "Explorer.authenticate()");
|
|
512
541
|
}
|
|
513
542
|
}
|
|
543
|
+
/** The number of consecutive failed database linking PIN attempts. */
|
|
544
|
+
static failCounter = 0;
|
|
514
545
|
/**
|
|
515
|
-
*
|
|
546
|
+
* Prepares an authenticated database for linking to another device.
|
|
516
547
|
*
|
|
517
|
-
*
|
|
548
|
+
* Verifies the current data PIN and prepares an encrypted transfer
|
|
549
|
+
* containing the information required to access the same database.
|
|
550
|
+
*
|
|
551
|
+
* Repeated PIN failures cause the current page to reload.
|
|
552
|
+
*
|
|
553
|
+
* @param dataPIN The PIN associated with the authenticated database.
|
|
554
|
+
* @param encapsulateKey The key used to establish encryption for the transfer.
|
|
555
|
+
* @returns The key offer and encrypted transfer message, or `false`
|
|
556
|
+
* if the supplied PIN is incorrect.
|
|
557
|
+
*/
|
|
558
|
+
static async prepareDatabaseLink(dataPIN, encapsulateKey) {
|
|
559
|
+
try {
|
|
560
|
+
if (!this.isAuthenticated) throw new ExplorerError("NOT_AUTHENTICATED");
|
|
561
|
+
if (dataPIN !== this.dataPIN) {
|
|
562
|
+
if (this.failCounter >= 2) window.location.reload();
|
|
563
|
+
this.failCounter++;
|
|
564
|
+
return false;
|
|
565
|
+
}
|
|
566
|
+
this.failCounter = 0;
|
|
567
|
+
const { keyOffer, cipherKey } = await Cryptographic.keyAgreement.encapsulate(encapsulateKey);
|
|
568
|
+
return [keyOffer, await Cryptographic.cipherMessage.encrypt(cipherKey, Bytes.concat([this.virtualEntropy, Bytes.utf8.decode(dataPIN)]))];
|
|
569
|
+
} catch (cause) {
|
|
570
|
+
throw unknownError(cause, "Explorer.prepareDatabaseLink()");
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Links the current device to an existing database.
|
|
575
|
+
*
|
|
576
|
+
* Accesses the transferred database information, creates a device binding,
|
|
577
|
+
* and registers a credential for the existing database.
|
|
578
|
+
*
|
|
579
|
+
* @param keyOffer The key offer associated with the database link.
|
|
580
|
+
* @param cipherMessage The encrypted database linking message.
|
|
581
|
+
* @param decapsulateKey The key used to establish decryption for the transfer.
|
|
582
|
+
* @param credentialName The display name assigned to the new credential.
|
|
583
|
+
* @param storageURL The base URL used to access database objects.
|
|
584
|
+
* @returns `true` if the database was linked and authenticated;
|
|
585
|
+
* otherwise, `false`.
|
|
586
|
+
*/
|
|
587
|
+
static async linkToDatabase(keyOffer, cipherMessage, decapsulateKey, credentialName, storageURL) {
|
|
588
|
+
try {
|
|
589
|
+
const { cipherKey } = await Cryptographic.keyAgreement.decapsulate(keyOffer, decapsulateKey);
|
|
590
|
+
const raw = await Cryptographic.cipherMessage.decrypt(cipherKey, cipherMessage);
|
|
591
|
+
const setupResult = await createDeviceBinding(credentialName);
|
|
592
|
+
if (!Array.isArray(setupResult)) return false;
|
|
593
|
+
const [credentialId, bindingStorage] = setupResult;
|
|
594
|
+
return await this.authenticate(Bytes.utf8.encode(raw.slice(64)), storageURL, {
|
|
595
|
+
credentialName,
|
|
596
|
+
virtualEntropy: raw.slice(0, 64),
|
|
597
|
+
bindingStorage
|
|
598
|
+
}, credentialId) === "authenticated" ? true : false;
|
|
599
|
+
} catch (cause) {
|
|
600
|
+
throw unknownError(cause, "Explorer.linkToDatabase()");
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
/**
|
|
604
|
+
* Permanently revokes a registered database credential.
|
|
605
|
+
*
|
|
606
|
+
* Removes the credential's persisted data and registration from
|
|
607
|
+
* the authenticated database.
|
|
518
608
|
*
|
|
519
609
|
* @param credentialID The identifier of the credential to revoke.
|
|
520
610
|
* @throws {ExplorerError} If the database is not authenticated.
|
|
@@ -528,15 +618,14 @@ var Explorer = class {
|
|
|
528
618
|
}
|
|
529
619
|
}
|
|
530
620
|
/**
|
|
531
|
-
* Returns the registered credentials
|
|
621
|
+
* Returns the registered database credentials.
|
|
532
622
|
*
|
|
533
|
-
*
|
|
534
|
-
*
|
|
535
|
-
*
|
|
536
|
-
* The cleanup function removes the registered change listener, if any.
|
|
623
|
+
* Optionally registers a listener for changes to the credential entries.
|
|
624
|
+
* The returned cleanup function removes the registered listener.
|
|
537
625
|
*
|
|
538
626
|
* @param onChange An optional callback invoked when the entries change.
|
|
539
|
-
* @returns The cleanup function, credential entries, and
|
|
627
|
+
* @returns The cleanup function, credential entries, and identifier
|
|
628
|
+
* of the current session's credential.
|
|
540
629
|
* @throws {ExplorerError} If the database is not authenticated.
|
|
541
630
|
*/
|
|
542
631
|
static async listCredentialEntries(onChange) {
|
|
@@ -556,11 +645,10 @@ var Explorer = class {
|
|
|
556
645
|
}
|
|
557
646
|
}
|
|
558
647
|
/**
|
|
559
|
-
* Returns the recently accessed objects
|
|
648
|
+
* Returns the recently accessed database objects.
|
|
560
649
|
*
|
|
561
|
-
*
|
|
562
|
-
*
|
|
563
|
-
* if any.
|
|
650
|
+
* Optionally registers a listener for changes to the recent entries.
|
|
651
|
+
* The returned cleanup function removes the registered listener.
|
|
564
652
|
*
|
|
565
653
|
* @param onChange An optional callback invoked when the entries change.
|
|
566
654
|
* @returns The cleanup function and recent entries.
|
|
@@ -579,9 +667,9 @@ var Explorer = class {
|
|
|
579
667
|
}
|
|
580
668
|
}
|
|
581
669
|
/**
|
|
582
|
-
* Loads an encrypted object
|
|
670
|
+
* Loads an encrypted database object by its identifier.
|
|
583
671
|
*
|
|
584
|
-
* Caches the cipher key if
|
|
672
|
+
* Caches the supplied cipher key if no key has been cached for the object.
|
|
585
673
|
*
|
|
586
674
|
* @typeParam T The expected type of the loaded object.
|
|
587
675
|
* @param id The identifier of the object to load.
|
|
@@ -598,9 +686,9 @@ var Explorer = class {
|
|
|
598
686
|
}
|
|
599
687
|
}
|
|
600
688
|
/**
|
|
601
|
-
* Encrypts and stores
|
|
689
|
+
* Encrypts and stores a database object by its identifier.
|
|
602
690
|
*
|
|
603
|
-
* Caches the cipher key if
|
|
691
|
+
* Caches the supplied cipher key if no key has been cached for the object.
|
|
604
692
|
*
|
|
605
693
|
* @typeParam T The type of the object to store.
|
|
606
694
|
* @param id The identifier of the object to store.
|
|
@@ -617,7 +705,9 @@ var Explorer = class {
|
|
|
617
705
|
}
|
|
618
706
|
}
|
|
619
707
|
/**
|
|
620
|
-
* Deletes a
|
|
708
|
+
* Deletes a database object by its identifier.
|
|
709
|
+
*
|
|
710
|
+
* Removes the persisted object and its corresponding recent entry.
|
|
621
711
|
*
|
|
622
712
|
* @param id The identifier of the object to delete.
|
|
623
713
|
*/
|
|
@@ -657,8 +747,9 @@ var Explorer = class {
|
|
|
657
747
|
});
|
|
658
748
|
}
|
|
659
749
|
/**
|
|
660
|
-
* Registers an event listener for the specified event
|
|
750
|
+
* Registers an event listener for the specified Explorer event.
|
|
661
751
|
*
|
|
752
|
+
* @typeParam K The event name that determines the event detail type.
|
|
662
753
|
* @param type The event type.
|
|
663
754
|
* @param listener The event listener, or `null`.
|
|
664
755
|
* @param options The event listener options.
|
|
@@ -674,6 +765,7 @@ var Explorer = class {
|
|
|
674
765
|
* Removes an event listener previously registered with
|
|
675
766
|
* {@link addEventListener}.
|
|
676
767
|
*
|
|
768
|
+
* @typeParam K The event name that determines the listener type.
|
|
677
769
|
* @param type The event type.
|
|
678
770
|
* @param listener The event listener to remove, or `null`.
|
|
679
771
|
* @param options The event listener options.
|
|
@@ -686,8 +778,9 @@ var Explorer = class {
|
|
|
686
778
|
}
|
|
687
779
|
}
|
|
688
780
|
/**
|
|
689
|
-
* Dispatches an event to
|
|
781
|
+
* Dispatches an Explorer event to registered listeners.
|
|
690
782
|
*
|
|
783
|
+
* @typeParam K The event name that determines the event detail type.
|
|
691
784
|
* @param type The event type.
|
|
692
785
|
* @param detail The value exposed through `CustomEvent.detail`.
|
|
693
786
|
*/
|
|
@@ -707,6 +800,7 @@ var Explorer = class {
|
|
|
707
800
|
static isExplorerDelta(data) {
|
|
708
801
|
return Array.isArray(data) && typeof data[0] === "string";
|
|
709
802
|
}
|
|
803
|
+
/** The cached recent entries list. */
|
|
710
804
|
static recentEntries;
|
|
711
805
|
/**
|
|
712
806
|
* Loads or returns the cached recent entries list.
|
|
@@ -730,6 +824,7 @@ var Explorer = class {
|
|
|
730
824
|
throw unknownError(cause, "Explorer.loadRecentEntries()");
|
|
731
825
|
}
|
|
732
826
|
}
|
|
827
|
+
/** The cached credential entries list. */
|
|
733
828
|
static credentialEntries;
|
|
734
829
|
/**
|
|
735
830
|
* Loads or returns the cached credential entries list.
|
|
@@ -747,13 +842,13 @@ var Explorer = class {
|
|
|
747
842
|
const id = await Cryptographic.identifier.derive(this.databaseSecret, Bytes.utf8.decode("@sovereignbase/explorer:CredentialEntriesID"), 32);
|
|
748
843
|
const ck = await Cryptographic.cipherMessage.deriveKey(this.databaseSecret, Bytes.utf8.decode("@sovereignbase/explorer:CredentialEntriesCipherKey"));
|
|
749
844
|
const trustedSnapshot = await this.loadObjectByID(id, ck, (snapshot) => void this.credentialEntries.merge(snapshot));
|
|
750
|
-
this.credentialEntries = new CredentialEntries(id, ck, this.sessionCredential.
|
|
845
|
+
this.credentialEntries = new CredentialEntries(id, ck, this.sessionCredential.credentialID, 0, trustedSnapshot);
|
|
751
846
|
return this.credentialEntries;
|
|
752
847
|
} catch (cause) {
|
|
753
848
|
throw unknownError(cause, "Explorer.loadCredentialEntries()");
|
|
754
849
|
}
|
|
755
850
|
}
|
|
756
851
|
};
|
|
757
|
-
export { Explorer };
|
|
852
|
+
export { Explorer, ExplorerError };
|
|
758
853
|
|
|
759
854
|
//# sourceMappingURL=class.js.map
|