Files
clean-architecture-frontend…/src/contracts/storage-keys.js
T

103 lines
3.0 KiB
JavaScript

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<string, ReturnType<typeof defineStorageKey>>} */ (
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;
}