web_lib

Common web application libraries
git clone https://radroots.dev/git/web_lib.git
Log | Files | Refs | LICENSE

encrypted_store.ts (2843B)


      1 import { err_msg, handle_err, type IdbClientConfig, type ResolveError } from "@radroots/utils";
      2 import { createStore, type UseStore } from "idb-keyval";
      3 import type { CryptoDecryptOutcome, CryptoStoreConfig, IWebCryptoService, LegacyKeyConfig } from "../crypto/types.js";
      4 import { WebCryptoService } from "../crypto/service.js";
      5 import { idb_store_ensure } from "./store.js";
      6 
      7 export type WebEncryptedStoreConfig = {
      8     idb_config: IdbClientConfig;
      9     store_id: string;
     10     idb_error: string;
     11     legacy_key?: LegacyKeyConfig | null;
     12     iv_length?: number;
     13     crypto_service?: IWebCryptoService;
     14 };
     15 
     16 export interface IWebEncryptedStore {
     17     get_config(): IdbClientConfig;
     18     get_store_id(): string;
     19     get_store(): Promise<ResolveError<UseStore>>;
     20     encrypt_bytes(bytes: Uint8Array): Promise<ResolveError<Uint8Array>>;
     21     decrypt_record(blob: Uint8Array): Promise<ResolveError<CryptoDecryptOutcome>>;
     22 }
     23 
     24 export class WebEncryptedStore implements IWebEncryptedStore {
     25     private readonly config: IdbClientConfig;
     26     private readonly store_id: string;
     27     private readonly idb_error: string;
     28     private readonly crypto: IWebCryptoService;
     29     private store: UseStore | null = null;
     30     private store_ready: Promise<void> | null = null;
     31 
     32     constructor(config: WebEncryptedStoreConfig) {
     33         this.config = config.idb_config;
     34         this.store_id = config.store_id;
     35         this.idb_error = config.idb_error;
     36         this.crypto = config.crypto_service ?? new WebCryptoService();
     37         const store_config: CryptoStoreConfig = {
     38             store_id: this.store_id,
     39             iv_length: config.iv_length
     40         };
     41         if (config.legacy_key) store_config.legacy_key = config.legacy_key;
     42         this.crypto.register_store_config(store_config);
     43     }
     44 
     45     public get_config(): IdbClientConfig {
     46         return {
     47             database: this.config.database,
     48             store: this.config.store
     49         };
     50     }
     51 
     52     public get_store_id(): string {
     53         return this.store_id;
     54     }
     55 
     56     public async get_store(): Promise<ResolveError<UseStore>> {
     57         if (typeof indexedDB === "undefined") return err_msg(this.idb_error);
     58         try {
     59             if (!this.store_ready) this.store_ready = idb_store_ensure(this.config.database, this.config.store);
     60             await this.store_ready;
     61             if (!this.store) this.store = createStore(this.config.database, this.config.store);
     62             return this.store;
     63         } catch (e) {
     64             return handle_err(e);
     65         }
     66     }
     67 
     68     public async encrypt_bytes(bytes: Uint8Array): Promise<ResolveError<Uint8Array>> {
     69         return await this.crypto.encrypt(this.store_id, bytes);
     70     }
     71 
     72     public async decrypt_record(blob: Uint8Array): Promise<ResolveError<CryptoDecryptOutcome>> {
     73         return await this.crypto.decrypt_record(this.store_id, blob);
     74     }
     75 }