All files / storage/src persistent.ts

100% Statements 31/31
100% Branches 8/8
100% Functions 6/6
100% Lines 31/31

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 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 791x       1x               1x 1x 1x 1x           1x 23x 23x           1x 1x 1x                   1x 16x 16x 16x 16x 16x 16x 16x 1x                       1x 5x 5x 5x 5x 5x 5x               1x 1x 1x  
import { session, SessionStorage, STORAGE_KEY } from './session.js';
import type { LinkableSchema, ObjLike, StateOptions } from '@anchorlib/core';
import type { PersistentFn } from './types.js';
 
const hasLocalStorage = () => typeof sessionStorage !== 'undefined';
 
/**
 * PersistentStorage class that extends SessionStorage to provide persistent storage functionality.
 * This class uses localStorage to persist data across browser sessions.
 *
 * @template T - The type of the stored object, extending Record<string, unknown>
 */
export class PersistentStorage<T extends Record<string, unknown> = Record<string, unknown>> extends SessionStorage<T> {
  public static key(name: string, version = '1.0.0') {
    return `${STORAGE_KEY}-persistent://${name}@${version}`;
  }
 
  /**
   * Gets the storage key for the current version.
   * The key format is `${STORAGE_KEY}-persistent://${name}@${version}`
   */
  public get key(): string {
    return PersistentStorage.key(this.name, this.version);
  }
 
  /**
   * Gets the storage key for the previous version.
   * The key format is `${STORAGE_KEY}-persistent://${name}@${previousVersion}`
   */
  public get oldKey(): string {
    return PersistentStorage.key(this.name, this.previousVersion);
  }
 
  /**
   * Creates a new instance of PersistentStorage.
   *
   * @param name - The name of the storage instance
   * @param init - Optional initial data for the storage
   * @param version - The version of the storage schema (default: '1.0.0')
   * @param previousVersion - Optional previous version for migration purposes
   */
  constructor(
    protected name: string,
    protected init?: T,
    protected version = '1.0.0',
    protected previousVersion?: string
  ) {
    super(name, init, version, previousVersion, hasLocalStorage() ? localStorage : undefined);
  }
}
 
/**
 * Creates a persistent storage instance that automatically syncs with localStorage.
 *
 * @template T - The type of the initial data object
 * @template S - The type of the linkable schema
 * @param {string} name - The unique name for the persistent storage instance
 * @param {T} init - The initial data to populate the storage with
 * @param {StateOptions<S>} [options] - Optional configuration options for the storage
 * @returns {T} A reactive object that persists data to localStorage
 */
export const persistent = (<T extends ObjLike, S extends LinkableSchema = LinkableSchema>(
  name: string,
  init: T,
  options?: StateOptions<S>
): T => {
  return session(name, init, options, PersistentStorage);
}) as PersistentFn;
 
/**
 * Disconnects a reactive persistent object from localStorage synchronization.
 *
 * @template T - The type of the object to disconnect
 * @param {T} state - The reactive object to stop syncing with localStorage
 */
persistent.leave = <T extends ObjLike>(state: T) => {
  return session.leave(state);
};