All files session.ts

100% Statements 40/40
100% Branches 18/18
100% Functions 8/8
100% Lines 34/34

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60        126x 126x 317x 126x 199x 199x 94x 94x 94x     126x   176x 176x 154x     111x 102x 102x   9x 9x     6x 6x 6x   3x       14x 14x 6x 6x   13x     8x     23x 23x 23x 22x 22x   21x        
import { metadata, type StorageBackend, sessionScope, stored } from "./storage";
 
/** @internal */
export function sessionStorageBackend(namespace: string, schemaVersion: number, sessionId: string): StorageBackend {
  const base = `${sessionScope(namespace, sessionId)}:`;
  const prefix = `${base}${schemaVersion}:`;
  const identity = (key: string) => prefix + JSON.stringify(key);
  const record = (key: string) => {
    const text = globalThis.sessionStorage.getItem(identity(key));
    if (text === null) return undefined;
    const raw: unknown = JSON.parse(text);
    const meta = metadata(raw);
    return meta ? stored(meta, raw) : undefined;
  };
 
  return {
    async read(key, version) {
      const value = record(key);
      if (value && value.meta.version === version) return { meta: value.meta };
      return value;
    },
    async write(key, entry, modified) {
      if (modified) {
        globalThis.sessionStorage.setItem(identity(key), JSON.stringify(entry));
        return true;
      } else {
        const value = record(key);
        if (value?.meta.version === entry.version) {
          // Retain the original JSON body. Decoded data may have been restored to
          // a different runtime shape, and a 304 must only change validators.
          const { data: _data, ...meta } = entry;
          globalThis.sessionStorage.setItem(identity(key), JSON.stringify({ ...meta, data: value.body.data }));
          return true;
        }
        return false;
      }
    },
    async invalidate(key) {
      const value = record(key);
      if (value) {
        value.meta.invalidated = true;
        globalThis.sessionStorage.setItem(identity(key), JSON.stringify({ ...value.meta, ...value.body }));
      }
      return value;
    },
    async remove(key) {
      globalThis.sessionStorage.removeItem(identity(key));
    },
    async clear(allVersions) {
      const storage = globalThis.sessionStorage;
      const matches: string[] = [];
      for (let i = 0; i < storage.length; i++) {
        const key = storage.key(i) as string;
        if (key.startsWith(allVersions ? base : prefix)) matches.push(key);
      }
      for (const key of matches) storage.removeItem(key);
    },
  };
}