{"version":3,"file":"storage.cjs","names":[],"sources":["../src/storage/create-key.ts","../src/storage/create-storage.ts"],"sourcesContent":["/**\n * Builds a storage key from a prefix, optional namespace and key.\n *\n * @example\n * ```ts\n * createKey('app', 'token', 'auth'); // 'app/auth/token'\n * ```\n */\nexport const createKey = (prefix: string, key: string, namespace?: string) =>\n  `${prefix}${namespace ? `/${namespace}` : ''}/${key}`;\n","import { createKey } from './create-key.js';\nimport type { StorageType } from './storage-type.js';\n\nconst storages: Record<StorageType, Storage> = {\n  session: sessionStorage,\n  local: localStorage,\n};\n\nconst parseStorageValue = <V>(value: unknown): V | null => {\n  if (typeof value !== 'string') {\n    return value as V;\n  }\n\n  try {\n    const parsed = JSON.parse(value);\n    return parsed;\n  } catch {\n    return null;\n  }\n};\n\nconst formatValueToStorage = (value: unknown): string => {\n  return JSON.stringify(value);\n};\n\nexport interface SetToStorageConfig<V>\n  extends Omit<GetFromStorageConfig<V>, 'fallback'> {\n  value: V;\n}\n\nexport interface UnsetFromStorageConfig\n  extends Omit<GetFromStorageConfig<any>, 'fallback'> {}\n\nexport interface GetFromStorageConfig<V> {\n  /**\n   * Storage key used to retrieve the value.\n   * The full key is extended with the project namespace.\n   */\n  key: string;\n  /**\n   * Storage type.\n   */\n  type: StorageType;\n  /**\n   * Default value used when there is no value in storage.\n   */\n  fallback?: V;\n  /**\n   * Optional namespace segment used in the generated key.\n   */\n  namespace?: string;\n  /**\n   * Optional key prefix.\n   */\n  prefix?: string;\n}\n\nexport type SetToStorageWrappedConfig<\n  V,\n  BaseConfig extends StorageConfigBase,\n> = Omit<\n  SetToStorageConfig<V>,\n  Extract<keyof SetToStorageConfig<V>, keyof BaseConfig>\n> &\n  Partial<\n    Pick<\n      SetToStorageConfig<V>,\n      Extract<keyof SetToStorageConfig<V>, keyof BaseConfig>\n    >\n  > &\n  Pick<BaseConfig, Exclude<keyof BaseConfig, keyof SetToStorageConfig<V>>>;\n\nexport type UnsetFromStorageWrappedConfig<\n  BaseConfig extends StorageConfigBase,\n> = Omit<\n  UnsetFromStorageConfig,\n  Extract<keyof UnsetFromStorageConfig, keyof BaseConfig>\n> &\n  Partial<\n    Pick<\n      UnsetFromStorageConfig,\n      Extract<keyof UnsetFromStorageConfig, keyof BaseConfig>\n    >\n  > &\n  Pick<BaseConfig, Exclude<keyof BaseConfig, keyof UnsetFromStorageConfig>>;\n\nexport type GetFromStorageWrappedConfig<\n  V,\n  BaseConfig extends StorageConfigBase,\n> = Omit<\n  GetFromStorageConfig<V>,\n  Extract<keyof GetFromStorageConfig<V>, keyof BaseConfig>\n> &\n  Partial<\n    Pick<\n      GetFromStorageConfig<V>,\n      Extract<keyof GetFromStorageConfig<V>, keyof BaseConfig>\n    >\n  > &\n  Pick<BaseConfig, Exclude<keyof BaseConfig, keyof GetFromStorageConfig<V>>>;\n\nexport type StorageConfigBase = Partial<\n  Pick<GetFromStorageConfig<any>, 'prefix' | 'type'>\n>;\n\nexport interface StorageApi<BaseConfig extends StorageConfigBase> {\n  set<Value>(config: SetToStorageWrappedConfig<Value, BaseConfig>): void;\n  unset(config: UnsetFromStorageWrappedConfig<BaseConfig>): void;\n  get<Value>(\n    config: GetFromStorageWrappedConfig<Value, BaseConfig>,\n  ): Value | null;\n}\n\n/**\n * Creates an interface for working with storage (`localStorage`, `sessionStorage`).\n */\nexport function createStorage<BaseConfig extends StorageConfigBase>(\n  storageConfig: BaseConfig,\n): StorageApi<BaseConfig> {\n  return {\n    set: <Value>(cfg: SetToStorageWrappedConfig<Value, BaseConfig>) => {\n      const config = cfg as unknown as SetToStorageConfig<Value>;\n      const storageType = (config.type ?? storageConfig.type!) as StorageType;\n      const storagePrefix = (config.prefix ?? storageConfig.prefix!) as string;\n\n      const storage = storages[storageType];\n\n      storage.setItem(\n        createKey(storagePrefix, config.key, config.namespace),\n        formatValueToStorage(config.value),\n      );\n    },\n    unset: <Value>(cfg: UnsetFromStorageWrappedConfig<BaseConfig>) => {\n      const config = cfg as unknown as SetToStorageConfig<Value>;\n      const storageType = (config.type ?? storageConfig.type!) as StorageType;\n      const storagePrefix = (config.prefix ?? storageConfig.prefix!) as string;\n      const storage = storages[storageType];\n\n      storage.removeItem(\n        createKey(storagePrefix, config.key, config.namespace),\n      );\n    },\n    get: <Value>(cfg: GetFromStorageWrappedConfig<Value, BaseConfig>) => {\n      const config = cfg as unknown as GetFromStorageConfig<Value>;\n      const storageType = (config.type ?? storageConfig.type!) as StorageType;\n      const storagePrefix = (config.prefix ?? storageConfig.prefix!) as string;\n\n      const storage = storages[storageType];\n\n      return (\n        parseStorageValue<Value>(\n          storage.getItem(\n            createKey(storagePrefix, config.key, config.namespace),\n          ),\n        ) ??\n        config.fallback ??\n        null\n      );\n    },\n  } as const;\n}\n"],"mappings":";;;;;;;;;;AAQA,IAAa,aAAa,QAAgB,KAAa,cACrD,GAAG,SAAS,YAAY,IAAI,cAAc,GAAG,GAAG;;;ACNlD,IAAM,WAAyC;CAC7C,SAAS;CACT,OAAO;AACT;AAEA,IAAM,qBAAwB,UAA6B;CACzD,IAAI,OAAO,UAAU,UACnB,OAAO;CAGT,IAAI;EAEF,OADe,KAAK,MAAM,KACnB;CACT,QAAQ;EACN,OAAO;CACT;AACF;AAEA,IAAM,wBAAwB,UAA2B;CACvD,OAAO,KAAK,UAAU,KAAK;AAC7B;;;;AA6FA,SAAgB,cACd,eACwB;CACxB,OAAO;EACL,MAAa,QAAsD;GACjE,MAAM,SAAS;GACf,MAAM,cAAe,OAAO,QAAQ,cAAc;GAClD,MAAM,gBAAiB,OAAO,UAAU,cAAc;GAItD,SAFyB,aAEjB,QACN,UAAU,eAAe,OAAO,KAAK,OAAO,SAAS,GACrD,qBAAqB,OAAO,KAAK,CACnC;EACF;EACA,QAAe,QAAmD;GAChE,MAAM,SAAS;GACf,MAAM,cAAe,OAAO,QAAQ,cAAc;GAClD,MAAM,gBAAiB,OAAO,UAAU,cAAc;GAGtD,SAFyB,aAEjB,WACN,UAAU,eAAe,OAAO,KAAK,OAAO,SAAS,CACvD;EACF;EACA,MAAa,QAAwD;GACnE,MAAM,SAAS;GACf,MAAM,cAAe,OAAO,QAAQ,cAAc;GAClD,MAAM,gBAAiB,OAAO,UAAU,cAAc;GAEtD,MAAM,UAAU,SAAS;GAEzB,OACE,kBACE,QAAQ,QACN,UAAU,eAAe,OAAO,KAAK,OAAO,SAAS,CACvD,CACF,KACA,OAAO,YACP;EAEJ;CACF;AACF"}