const APP_NAMESPACE = "ca-frontend"; export const STORAGE_REGISTRY = Object.freeze({ COLOR_SCHEME: defineStorageKey({ logicalName: "COLOR_SCHEME", scope: "preference", name: "color-scheme", backend: "localStorage", classification: "public-preference", schemaVersion: 1, ttl: null, migration: "discard", quotaFallback: "memory", }), CHUNK_RELOAD_GUARD: defineStorageKey({ logicalName: "CHUNK_RELOAD_GUARD", scope: "release", name: "chunk-reload-guard", backend: "sessionStorage", classification: "opaque-cache", schemaVersion: 1, ttl: "session", migration: "discard", quotaFallback: "no-persist", }), QUERY_PERSISTENCE: defineStorageKey({ logicalName: "QUERY_PERSISTENCE", scope: "cache", name: "query-persistence", backend: "disabled", classification: "sensitive-forbidden", schemaVersion: 1, ttl: null, migration: "discard", quotaFallback: "feature-disable", }), AUTH_TOKEN: defineStorageKey({ logicalName: "AUTH_TOKEN", scope: "auth", name: "auth-token", backend: "forbidden", classification: "sensitive-forbidden", schemaVersion: 1, ttl: null, migration: "discard", quotaFallback: "feature-disable", }), }); /** * @typedef {{ * logicalName: string, * scope: string, * name: string, * backend: "memory" | "sessionStorage" | "localStorage" | "indexedDB" | * "disabled" | "forbidden", * classification: "public-preference" | "opaque-cache" | "sensitive-forbidden", * schemaVersion: number, * ttl: number | "session" | null, * migration: "discard" | ((value: unknown) => unknown), * quotaFallback: "memory" | "no-persist" | "feature-disable" * }} StorageKeyInput */ /** @param {StorageKeyInput} definition */ export function defineStorageKey(definition) { if (definition.classification === "sensitive-forbidden") { if (!["disabled", "forbidden"].includes(definition.backend)) { throw new Error("Sensitive client storage registration is forbidden"); } } if (!Number.isInteger(definition.schemaVersion) || definition.schemaVersion < 1) { throw new Error("Storage schemaVersion must be a positive integer"); } return Object.freeze({ ...definition, physicalKey: buildPhysicalKey( definition.scope, definition.schemaVersion, definition.name, ), }); } /** @param {string} scope @param {number} schemaVersion @param {string} name */ export function buildPhysicalKey(scope, schemaVersion, name) { return `${APP_NAMESPACE}:${scope}:v${schemaVersion}:${name}`; } /** @param {string} logicalName */ export function getStorageDefinition(logicalName) { const registry = /** @type {Record>} */ ( STORAGE_REGISTRY ); const definition = registry[logicalName]; if (!definition) throw new Error(`Unregistered storage key: ${logicalName}`); if (definition.classification === "sensitive-forbidden") { throw new Error(`Forbidden storage key: ${logicalName}`); } return definition; }