UNPKG

@embrace-io/web-sdk

Version:
110 lines (109 loc) 3.43 kB
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); let _opentelemetry_api = require("@opentelemetry/api"); //#region src/utils/NamespacedStorage/NamespacedStorage.ts /** * `Storage`-shaped wrapper that isolates the SDK from storage errors and * optionally namespaces keys with a prefix. Mutation methods return `true` * on success and `false` when the call failed or writes have been disabled. * * Read failures (`getItem`, `key`, `length`) log at warn level and degrade * to `null`/empty results. * * The first `setItem` failure flips a sticky `_writeDisabled` flag and * emits one error; subsequent `setItem` calls silently return `false` * without attempting the underlying write, so a one-time quota error or * revoked permission does not keep throwing on every attempt. Reads, * removes, and clears continue to work. * * An empty namespace skips the key prefix; the wrapper then exposes the * underlying storage's full keyspace with only the safety layer applied. */ var NamespacedStorage = class { _diag; _keyPrefix; _storage; _writeDisabled = false; constructor({ namespace, storage, diag: diagParam }) { this._diag = diagParam ?? _opentelemetry_api.diag.createComponentLogger({ namespace: "NamespacedStorage" }); this._keyPrefix = namespace ? `${namespace}__` : ""; this._storage = storage; } /** * Logical keys when namespaced; raw underlying keys otherwise (may include * foreign keys sharing the origin's storage). Best-effort: indices that * throw are skipped, returns empty on bulk failure. */ keys() { let length; try { length = this._storage.length; } catch (e) { this._diag.warn("failed to read storage length", String(e)); return []; } const result = []; for (let i = 0; i < length; i++) try { const key = this._storage.key(i); if (key === null) continue; if (this._keyPrefix) { if (key.startsWith(this._keyPrefix)) result.push(key.substring(this._keyPrefix.length)); } else result.push(key); } catch (e) { this._diag.warn(`failed to read storage key at index ${i.toString()}`, String(e)); } return result; } get length() { return this.keys().length; } clear() { let allRemoved = true; for (const key of this.keys()) if (!this._safeRemove(this._keyName(key))) allRemoved = false; return allRemoved; } getItem(key) { try { return this._storage.getItem(this._keyName(key)); } catch (e) { this._diag.warn(`failed to read ${key}`, String(e)); return null; } } key(index) { return this.keys()[index] ?? null; } removeItem(key) { return this._safeRemove(this._keyName(key)); } setItem(key, value) { if (this._writeDisabled) return false; try { this._storage.setItem(this._keyName(key), value); return true; } catch (e) { this._disableWrites(e); return false; } } _keyName(key) { return `${this._keyPrefix}${key}`; } _safeRemove(keyName) { try { this._storage.removeItem(keyName); return true; } catch (e) { this._diag.warn(`failed to remove ${keyName}`, String(e)); return false; } } _disableWrites(error) { if (this._writeDisabled) return; this._writeDisabled = true; const errorName = error instanceof Error ? error.name : "UnknownError"; this._diag.error("writes disabled after failure; continuing in-memory only", errorName); } }; //#endregion exports.NamespacedStorage = NamespacedStorage; //# sourceMappingURL=NamespacedStorage.cjs.map