{"version":3,"sources":["../src/middleware/metrics.ts","../src/errors.ts","../src/middleware/encryption.ts"],"names":[],"mappings":";;;;AA+BO,SAAS,YAAY,OAAA,EAAqD;AAC/E,EAAA,SAAS,KACP,KAAA,EAC2B;AAC3B,IAAA,OAAO,IAAI,gBAAA,CAAiB,EAAE,KAAA,EAAO,SAAS,CAAA;AAAA,EAChD;AACA,EAAA,OAAO,EAAE,IAAA,EAAK;AAChB;AAEA,IAAM,mBAAN,MAA+F;AAAA,EACtF,IAAA;AAAA,EACU,KAAA;AAAA,EAEA,OAAA;AAAA,EAEjB,YAAY,IAAA,EAGT;AACD,IAAA,IAAA,CAAK,IAAA,GAAO,KAAK,KAAA,CAAM,IAAA;AACvB,IAAA,IAAA,CAAK,QAAQ,IAAA,CAAK,KAAA;AAClB,IAAA,IAAA,CAAK,UAAU,IAAA,CAAK,OAAA;AAAA,EACtB;AAAA,EAEA,MAAa,GAAA,CACX,SAAA,EACA,GAAA,EACwD;AACxD,IAAA,MAAM,KAAA,GAAQ,YAAY,GAAA,EAAI;AAC9B,IAAA,MAAM,MAAM,MAAM,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,WAAW,GAAG,CAAA;AAE/C,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AAErB,IAAA,IAAA,CAAK,QAAQ,IAAA,CAAK;AAAA,MAChB,MAAA,EAAQ,mBAAA;AAAA,MACR,GAAA,EAAK,OAAO,GAAA,CAAI,GAAA,KAAQ,WAAA;AAAA,MACxB,MAAA,EAAQ,GAAA,CAAI,GAAA,GACR,GAAA,IAAO,GAAA,CAAI,GAAA,CAAI,UAAA,GACb,OAAA,GACA,GAAA,IAAO,GAAA,CAAI,GAAA,CAAI,UAAA,GACb,UACA,MAAA,GACJ,MAAA;AAAA,MACJ,SAAS,IAAA,CAAK,KAAA,CAAM,WAAA,CAAY,GAAA,KAAQ,KAAK,CAAA;AAAA,MAC7C,IAAA,EAAM,KAAK,KAAA,CAAM,IAAA;AAAA,MACjB,GAAA;AAAA,MACA;AAAA,KACD,CAAA;AAED,IAAA,OAAO,GAAA;AAAA,EACT;AAAA,EAEA,MAAa,GAAA,CACX,SAAA,EACA,GAAA,EACA,KAAA,EACmC;AACnC,IAAA,MAAM,KAAA,GAAQ,YAAY,GAAA,EAAI;AAE9B,IAAA,MAAM,MAAM,MAAM,IAAA,CAAK,MAAM,GAAA,CAAI,SAAA,EAAW,KAAK,KAAK,CAAA;AACtD,IAAA,IAAA,CAAK,QAAQ,IAAA,CAAK;AAAA,MAChB,MAAA,EAAQ,oBAAA;AAAA,MACR,SAAS,IAAA,CAAK,KAAA,CAAM,WAAA,CAAY,GAAA,KAAQ,KAAK,CAAA;AAAA,MAC7C,IAAA,EAAM,KAAK,KAAA,CAAM,IAAA;AAAA,MACjB,GAAA;AAAA,MACA;AAAA,KACD,CAAA;AACD,IAAA,OAAO,GAAA;AAAA,EACT;AAAA,EAEA,MAAa,MAAA,CAAO,SAAA,EAAuB,GAAA,EAAgD;AACzF,IAAA,MAAM,KAAA,GAAQ,YAAY,GAAA,EAAI;AAC9B,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,WAAW,GAAG,CAAA;AAC5C,IAAA,IAAA,CAAK,QAAQ,IAAA,CAAK;AAAA,MAChB,MAAA,EAAQ,qBAAA;AAAA,MACR,IAAA,EAAM,KAAK,KAAA,CAAM,IAAA;AAAA,MACjB,SAAS,IAAA,CAAK,KAAA,CAAM,WAAA,CAAY,GAAA,KAAQ,KAAK,CAAA;AAAA,MAC7C,GAAA;AAAA,MACA;AAAA,KACD,CAAA;AACD,IAAA,OAAO,GAAA;AAAA,EACT;AACF,CAAA;AC/GO,IAAM,UAAA,GAAN,cAAyB,SAAA,CAAU;AAAA,EACxB,IAAA,GAAO,YAAA;AAAA,EACP,KAAA,GAAQ,KAAA;AAAA,EAER,IAAA;AAAA,EACA,GAAA;AAAA,EAEhB,YAAY,IAAA,EAIT;AACD,IAAA,KAAA,CAAM,IAAI,CAAA;AACV,IAAA,IAAA,CAAK,IAAA,GAAO,YAAA;AACZ,IAAA,IAAA,CAAK,OAAO,IAAA,CAAK,IAAA;AACjB,IAAA,IAAA,CAAK,MAAM,IAAA,CAAK,GAAA;AAAA,EAClB;AACF,CAAA;;;ACKO,IAAM,cAAA,GAAN,MAAM,eAAA,CAEb;AAAA,EACS,IAAA;AAAA,EACU,aAAA;AAAA,EACA,iBAAA;AAAA,EACA,KAAA;AAAA,EAEjB,YAAY,IAAA,EAIT;AACD,IAAA,IAAA,CAAK,IAAA,GAAO,KAAK,KAAA,CAAM,IAAA;AACvB,IAAA,IAAA,CAAK,QAAQ,IAAA,CAAK,KAAA;AAClB,IAAA,IAAA,CAAK,gBAAgB,IAAA,CAAK,aAAA;AAC1B,IAAA,IAAA,CAAK,oBAAoB,IAAA,CAAK,iBAAA;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAc,GAAA,EAAqB;AACzC,IAAA,OAAO,CAAC,GAAA,EAAK,IAAA,CAAK,iBAAiB,CAAA,CAAE,KAAK,GAAG,CAAA;AAAA,EAC/C;AAAA,EAEA,MAAa,GAAA,CACX,SAAA,EACA,GAAA,EACwD;AACxD,IAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,KAAA,CAAM,IAAI,SAAA,EAAW,IAAA,CAAK,aAAA,CAAc,GAAG,CAAC,CAAA;AAEnE,IAAA,IAAI,IAAI,GAAA,EAAK;AACX,MAAA,OAAO,GAAA;AAAA,IACT;AACA,IAAA,IAAI,CAAC,IAAI,GAAA,EAAK;AACZ,MAAA,OAAO,GAAA;AAAA,IACT;AACA,IAAA,IAAI;AACF,MAAA,MAAM,EAAE,EAAA,EAAI,UAAA,EAAW,GAAI,IAAI,GAAA,CAAI,KAAA;AACnC,MAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,OAAA,CAAQ,IAAI,UAAU,CAAA;AAEnD,MAAA,GAAA,CAAI,GAAA,CAAI,KAAA,GAAQ,SAAA,CAAU,KAAA,CAAM,SAAS,CAAA;AAAA,IAC3C,SAAS,CAAA,EAAG;AACV,MAAA,OAAO,GAAA,CAAI,IAAI,UAAA,CAAW,EAAE,IAAA,EAAM,IAAA,CAAK,IAAA,EAAM,GAAA,EAAK,OAAA,EAAU,CAAA,CAAY,OAAA,EAAS,CAAC,CAAA;AAAA,IACpF;AAEA,IAAA,OAAO,GAAA;AAAA,EACT;AAAA,EAEA,MAAa,GAAA,CACX,SAAA,EACA,GAAA,EACA,KAAA,EACmC;AACnC,IAAA,MAAM,EAAE,EAAA,EAAI,UAAA,EAAW,GAAI,MAAM,IAAA,CAAK,OAAA,CAAQ,SAAA,CAAU,SAAA,CAAU,KAAA,CAAM,KAAK,CAAC,CAAA;AAE9E,IAAA,KAAA,CAAM,KAAA,GAAQ,EAAE,EAAA,EAAI,UAAA,EAAW;AAE/B,IAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,WAAW,IAAA,CAAK,aAAA,CAAc,GAAG,CAAA,EAAG,KAAK,CAAA;AAE1E,IAAA,OAAO,GAAA;AAAA,EACT;AAAA,EAEA,MAAa,MAAA,CAAO,SAAA,EAAuB,GAAA,EAAgD;AACzF,IAAA,MAAM,GAAA,GAAM,KAAK,KAAA,CAAM,MAAA,CAAO,WAAW,IAAA,CAAK,aAAA,CAAc,GAAG,CAAC,CAAA;AAEhE,IAAA,OAAO,GAAA;AAAA,EACT;AAAA,EAEA,MAAc,QAAQ,MAAA,EAA6D;AACjF,IAAA,MAAM,KAAK,MAAA,CAAO,eAAA,CAAgB,IAAI,UAAA,CAAW,EAAE,CAAC,CAAA;AACpD,IAAA,MAAM,UAAA,GAAa,MAAM,MAAA,CAAO,MAAA,CAAO,OAAA;AAAA,MACrC;AAAA,QACE,IAAA,EAAM,SAAA;AAAA,QACN;AAAA,OACF;AAAA,MACA,IAAA,CAAK,aAAA;AAAA,MACL,IAAI,WAAA,EAAY,CAAE,MAAA,CAAO,MAAM;AAAA,KACjC;AACA,IAAA,OAAO,EAAE,IAAI,MAAA,CAAO,EAAE,GAAG,UAAA,EAAY,MAAA,CAAO,UAAU,CAAA,EAAE;AAAA,EAC1D;AAAA,EAEA,MAAc,OAAA,CAAQ,EAAA,EAAY,UAAA,EAAqC;AACrE,IAAA,MAAM,eAAA,GAAkB,MAAM,MAAA,CAAO,MAAA,CAAO,OAAA;AAAA,MAC1C;AAAA,QACE,IAAA,EAAM,SAAA;AAAA,QACN,EAAA,EAAI,OAAO,EAAE;AAAA,OACf;AAAA,MACA,IAAA,CAAK,aAAA;AAAA,MACL,OAAO,UAAU;AAAA,KACnB;AAEA,IAAA,OAAO,IAAI,WAAA,EAAY,CAAE,MAAA,CAAO,eAAe,CAAA;AAAA,EACjD;AAAA,EAEA,aAAa,cACX,gBAAA,EACoF;AACpF,IAAA,MAAM,SAAA,GAAY,MAAM,MAAA,CAAO,MAAA,CAAO,SAAA;AAAA,MACpC,KAAA;AAAA,MACA,OAAO,gBAAgB,CAAA;AAAA,MACvB,EAAE,IAAA,EAAM,SAAA,EAAW,MAAA,EAAQ,GAAA,EAAI;AAAA,MAC/B,KAAA;AAAA,MACA,CAAC,WAAW,SAAS;AAAA,KACvB;AAEA,IAAA,MAAM,IAAA,GAAO,MAAA,CAAO,MAAM,MAAA,CAAO,MAAA,CAAO,OAAO,SAAA,EAAW,MAAA,CAAO,gBAAgB,CAAC,CAAC,CAAA;AAEnF,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,CAAC,KAAA,KACL,IAAI,eAAA,CAAe,EAAE,KAAA,EAAO,aAAA,EAAe,SAAA,EAAW,iBAAA,EAAmB,IAAA,EAAM;AAAA,KACnF;AAAA,EACF;AACF;AAEA,IAAM,SAAA,GAAY;AAAA,EAChB,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA;AACF,CAAA;AAOA,SAAS,OAAO,IAAA,EAAoC;AAClD,EAAA,MAAM,KAAA,GACJ,OAAO,IAAA,KAAS,QAAA,GACZ,IAAI,WAAA,EAAY,CAAE,MAAA,CAAO,IAAI,IAC7B,IAAA,YAAgB,UAAA,GACd,IAAA,GACA,IAAI,WAAW,IAAI,CAAA;AAC3B,EAAA,IAAI,MAAA,GAAS,EAAA;AACb,EAAA,IAAI,CAAA;AACJ,EAAA,MAAM,IAAI,KAAA,CAAM,MAAA;AAChB,EAAA,KAAK,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,EAAG,KAAK,CAAA,EAAG;AACzB,IAAA,MAAA,IAAU,SAAA,CAAU,KAAA,CAAM,CAAA,GAAI,CAAC,KAAK,CAAC,CAAA;AACrC,IAAA,MAAA,IAAU,SAAA,CAAA,CAAY,KAAA,CAAM,CAAA,GAAI,CAAC,CAAA,GAAI,CAAA,KAAS,CAAA,GAAM,KAAA,CAAM,CAAA,GAAI,CAAC,CAAA,IAAK,CAAE,CAAA;AACtE,IAAA,MAAA,IAAU,SAAA,CAAA,CAAY,KAAA,CAAM,CAAA,GAAI,CAAC,CAAA,GAAI,OAAS,CAAA,GAAM,KAAA,CAAM,CAAC,CAAA,IAAK,CAAE,CAAA;AAClE,IAAA,MAAA,IAAU,SAAA,CAAU,KAAA,CAAM,CAAC,CAAA,GAAI,EAAI,CAAA;AAAA,EACrC;AACA,EAAA,IAAI,CAAA,KAAM,IAAI,CAAA,EAAG;AAEf,IAAA,MAAA,IAAU,SAAA,CAAU,KAAA,CAAM,CAAA,GAAI,CAAC,KAAK,CAAC,CAAA;AACrC,IAAA,MAAA,IAAU,WAAW,KAAA,CAAM,CAAA,GAAI,CAAC,CAAA,GAAI,MAAS,CAAC,CAAA;AAC9C,IAAA,MAAA,IAAU,IAAA;AAAA,EACZ;AACA,EAAA,IAAI,MAAM,CAAA,EAAG;AAEX,IAAA,MAAA,IAAU,SAAA,CAAU,KAAA,CAAM,CAAA,GAAI,CAAC,KAAK,CAAC,CAAA;AACrC,IAAA,MAAA,IAAU,SAAA,CAAA,CAAY,KAAA,CAAM,CAAA,GAAI,CAAC,CAAA,GAAI,CAAA,KAAS,CAAA,GAAM,KAAA,CAAM,CAAA,GAAI,CAAC,CAAA,IAAK,CAAE,CAAA;AACtE,IAAA,MAAA,IAAU,WAAW,KAAA,CAAM,CAAA,GAAI,CAAC,CAAA,GAAI,OAAS,CAAC,CAAA;AAC9C,IAAA,MAAA,IAAU,GAAA;AAAA,EACZ;AACA,EAAA,OAAO,MAAA,CAAO,UAAA,CAAW,GAAA,EAAK,GAAG,CAAA,CAAE,UAAA,CAAW,GAAA,EAAK,GAAG,CAAA,CAAE,UAAA,CAAW,GAAA,EAAK,EAAE,CAAA;AAC5E;AAMA,SAAS,OAAO,GAAA,EAAyB;AACvC,EAAA,MAAM,eAAe,GAAA,CAAI,MAAA,GAAA,CAAW,CAAA,GAAK,GAAA,CAAI,SAAS,CAAA,IAAM,CAAA;AAC5D,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,GAAA,CAAI,UAAA,CAAW,KAAK,GAAG,CAAA,CAAE,UAAA,CAAW,GAAA,EAAK,GAAG,CAAA,CAAE,MAAA,CAAO,YAAA,EAAc,GAAG,CAAC,CAAA;AAC9F,EAAA,MAAM,OAAO,SAAA,CAAU,MAAA;AACvB,EAAA,MAAM,KAAA,GAAQ,IAAI,UAAA,CAAW,IAAI,CAAA;AACjC,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,IAAA,EAAM,CAAA,EAAA,EAAK;AAC7B,IAAA,KAAA,CAAM,CAAC,CAAA,GAAI,SAAA,CAAU,UAAA,CAAW,CAAC,CAAA;AAAA,EACnC;AACA,EAAA,OAAO,KAAA;AACT;AAEA,eAAsB,eACpB,SAAA,EAC8C;AAC9C,EAAA,OAAO,MAAM,cAAA,CAAe,aAAA,CAAc,SAAS,CAAA;AACrD","file":"middleware.mjs","sourcesContent":["import type { Result } from \"@unkey/error\";\nimport type { CacheError } from \"../errors\";\nimport type { Metrics } from \"../metrics\";\nimport type { Entry, Store } from \"../stores\";\nimport type { StoreMiddleware } from \"./interface\";\n\ntype Metric =\n  | {\n      metric: \"metric.cache.read\";\n      key: string;\n      hit: boolean;\n      status?: \"fresh\" | \"stale\";\n      latency: number;\n      tier: string;\n      namespace: string;\n    }\n  | {\n      metric: \"metric.cache.write\";\n      key: string;\n      latency: number;\n      tier: string;\n      namespace: string;\n    }\n  | {\n      metric: \"metric.cache.remove\";\n      key: string;\n      latency: number;\n      tier: string;\n      namespace: string;\n    };\n\nexport function withMetrics(metrics: Metrics<Metric>): StoreMiddleware<any, any> {\n  function wrap<TNamespace extends string, TValue>(\n    store: Store<TNamespace, TValue>,\n  ): Store<TNamespace, TValue> {\n    return new StoreWithMetrics({ store, metrics });\n  }\n  return { wrap };\n}\n\nclass StoreWithMetrics<TNamespace extends string, TValue> implements Store<TNamespace, TValue> {\n  public name: string;\n  private readonly store: Store<TNamespace, TValue>;\n\n  private readonly metrics: Metrics;\n\n  constructor(opts: {\n    store: Store<TNamespace, TValue>;\n    metrics: Metrics;\n  }) {\n    this.name = opts.store.name;\n    this.store = opts.store;\n    this.metrics = opts.metrics;\n  }\n\n  public async get(\n    namespace: TNamespace,\n    key: string,\n  ): Promise<Result<Entry<TValue> | undefined, CacheError>> {\n    const start = performance.now();\n    const res = await this.store.get(namespace, key);\n\n    const now = Date.now();\n\n    this.metrics.emit({\n      metric: \"metric.cache.read\",\n      hit: typeof res.val !== \"undefined\",\n      status: res.val\n        ? now <= res.val.freshUntil\n          ? \"fresh\"\n          : now <= res.val.staleUntil\n            ? \"stale\"\n            : undefined\n        : undefined,\n      latency: Math.round(performance.now() - start),\n      tier: this.store.name,\n      key,\n      namespace,\n    });\n\n    return res;\n  }\n\n  public async set(\n    namespace: TNamespace,\n    key: string,\n    value: Entry<TValue>,\n  ): Promise<Result<void, CacheError>> {\n    const start = performance.now();\n\n    const res = await this.store.set(namespace, key, value);\n    this.metrics.emit({\n      metric: \"metric.cache.write\",\n      latency: Math.round(performance.now() - start),\n      tier: this.store.name,\n      key,\n      namespace,\n    });\n    return res;\n  }\n\n  public async remove(namespace: TNamespace, key: string): Promise<Result<void, CacheError>> {\n    const start = performance.now();\n    const res = this.store.remove(namespace, key);\n    this.metrics.emit({\n      metric: \"metric.cache.remove\",\n      tier: this.store.name,\n      latency: Math.round(performance.now() - start),\n      key,\n      namespace,\n    });\n    return res;\n  }\n}\n","import { BaseError } from \"@unkey/error\";\n\nexport class CacheError extends BaseError {\n  public readonly name = \"CacheError\";\n  public readonly retry = false;\n\n  public readonly tier: string;\n  public readonly key: string;\n\n  constructor(opts: {\n    tier: string;\n    key: string;\n    message: string;\n  }) {\n    super(opts);\n    this.name = \"CacheError\";\n    this.tier = opts.tier;\n    this.key = opts.key;\n  }\n}\n","import { Err, type Result } from \"@unkey/error\";\nimport SuperJSON from \"superjson\";\nimport { CacheError } from \"../errors\";\nimport type { Entry, Store } from \"../stores\";\nimport type { StoreMiddleware } from \"./interface\";\n\n/**\n * EncryptedStore is a wrapper around a Store that encrypts and decrypts values using the Web Crypto API.\n *\n * The encryption key is stored in memory and a hash is injected into the cache key to allow rolling the key\n * without causing issues with decryption errors.\n *\n * Rolling the encryption key will therefore invalidate all cache entries.\n *\n * @example\n * ```ts\n * let store // some existing store implementation\n *\n * // generate a key with `openssl rand -base64 32` and load it from the environment\n * const encryptionKey = \"\"\n * store = EncryptedStore.fromBase64Key(store, encryptionKey)\n * ```\n */\n\nexport class EncryptedStore<TNamespace extends string, TValue = any>\n  implements Store<TNamespace, TValue>\n{\n  public name: string;\n  private readonly encryptionKey: CryptoKey;\n  private readonly encryptionKeyHash: string;\n  private readonly store: Store<TNamespace, TValue>;\n\n  constructor(opts: {\n    store: Store<TNamespace, TValue>;\n    encryptionKey: CryptoKey;\n    encryptionKeyHash: string;\n  }) {\n    this.name = opts.store.name;\n    this.store = opts.store;\n    this.encryptionKey = opts.encryptionKey;\n    this.encryptionKeyHash = opts.encryptionKeyHash;\n  }\n\n  /**\n   *\n   */\n  private buildCacheKey(key: string): string {\n    return [key, this.encryptionKeyHash].join(\"/\");\n  }\n\n  public async get(\n    namespace: TNamespace,\n    key: string,\n  ): Promise<Result<Entry<TValue> | undefined, CacheError>> {\n    const res = await this.store.get(namespace, this.buildCacheKey(key));\n\n    if (res.err) {\n      return res;\n    }\n    if (!res.val) {\n      return res;\n    }\n    try {\n      const { iv, ciphertext } = res.val.value as { iv: string; ciphertext: string };\n      const decrypted = await this.decrypt(iv, ciphertext);\n\n      res.val.value = SuperJSON.parse(decrypted);\n    } catch (e) {\n      return Err(new CacheError({ tier: this.name, key, message: (e as Error).message }));\n    }\n\n    return res;\n  }\n\n  public async set(\n    namespace: TNamespace,\n    key: string,\n    value: Entry<TValue>,\n  ): Promise<Result<void, CacheError>> {\n    const { iv, ciphertext } = await this.encrypt(SuperJSON.stringify(value.value));\n    // @ts-expect-error\n    value.value = { iv, ciphertext };\n\n    const res = await this.store.set(namespace, this.buildCacheKey(key), value);\n\n    return res;\n  }\n\n  public async remove(namespace: TNamespace, key: string): Promise<Result<void, CacheError>> {\n    const res = this.store.remove(namespace, this.buildCacheKey(key));\n\n    return res;\n  }\n\n  private async encrypt(secret: string): Promise<{ iv: string; ciphertext: string }> {\n    const iv = crypto.getRandomValues(new Uint8Array(32));\n    const ciphertext = await crypto.subtle.encrypt(\n      {\n        name: \"AES-GCM\",\n        iv,\n      },\n      this.encryptionKey,\n      new TextEncoder().encode(secret),\n    );\n    return { iv: encode(iv), ciphertext: encode(ciphertext) };\n  }\n\n  private async decrypt(iv: string, ciphertext: string): Promise<string> {\n    const decryptedBuffer = await crypto.subtle.decrypt(\n      {\n        name: \"AES-GCM\",\n        iv: decode(iv),\n      },\n      this.encryptionKey,\n      decode(ciphertext),\n    );\n\n    return new TextDecoder().decode(decryptedBuffer);\n  }\n\n  static async fromBase64Key<TNamespace extends string, TValue>(\n    base64EncodedKey: string,\n  ): Promise<{ wrap: (store: Store<TNamespace, TValue>) => Store<TNamespace, TValue> }> {\n    const cryptoKey = await crypto.subtle.importKey(\n      \"raw\",\n      decode(base64EncodedKey),\n      { name: \"AES-GCM\", length: 256 },\n      false,\n      [\"encrypt\", \"decrypt\"],\n    );\n\n    const hash = encode(await crypto.subtle.digest(\"SHA-256\", decode(base64EncodedKey)));\n\n    return {\n      wrap: (store) =>\n        new EncryptedStore({ store, encryptionKey: cryptoKey, encryptionKeyHash: hash }),\n    };\n  }\n}\n\nconst base64abc = [\n  \"A\",\n  \"B\",\n  \"C\",\n  \"D\",\n  \"E\",\n  \"F\",\n  \"G\",\n  \"H\",\n  \"I\",\n  \"J\",\n  \"K\",\n  \"L\",\n  \"M\",\n  \"N\",\n  \"O\",\n  \"P\",\n  \"Q\",\n  \"R\",\n  \"S\",\n  \"T\",\n  \"U\",\n  \"V\",\n  \"W\",\n  \"X\",\n  \"Y\",\n  \"Z\",\n  \"a\",\n  \"b\",\n  \"c\",\n  \"d\",\n  \"e\",\n  \"f\",\n  \"g\",\n  \"h\",\n  \"i\",\n  \"j\",\n  \"k\",\n  \"l\",\n  \"m\",\n  \"n\",\n  \"o\",\n  \"p\",\n  \"q\",\n  \"r\",\n  \"s\",\n  \"t\",\n  \"u\",\n  \"v\",\n  \"w\",\n  \"x\",\n  \"y\",\n  \"z\",\n  \"0\",\n  \"1\",\n  \"2\",\n  \"3\",\n  \"4\",\n  \"5\",\n  \"6\",\n  \"7\",\n  \"8\",\n  \"9\",\n  \"+\",\n  \"/\",\n];\n\n/**\n * CREDIT: https://gist.github.com/enepomnyaschih/72c423f727d395eeaa09697058238727\n * Encodes a given Uint8Array, ArrayBuffer or string into RFC4648 base64 representation\n * @param data\n */\nfunction encode(data: ArrayBuffer | string): string {\n  const uint8 =\n    typeof data === \"string\"\n      ? new TextEncoder().encode(data)\n      : data instanceof Uint8Array\n        ? data\n        : new Uint8Array(data);\n  let result = \"\";\n  let i: number;\n  const l = uint8.length;\n  for (i = 2; i < l; i += 3) {\n    result += base64abc[uint8[i - 2] >> 2];\n    result += base64abc[((uint8[i - 2] & 0x03) << 4) | (uint8[i - 1] >> 4)];\n    result += base64abc[((uint8[i - 1] & 0x0f) << 2) | (uint8[i] >> 6)];\n    result += base64abc[uint8[i] & 0x3f];\n  }\n  if (i === l + 1) {\n    // 1 octet yet to write\n    result += base64abc[uint8[i - 2] >> 2];\n    result += base64abc[(uint8[i - 2] & 0x03) << 4];\n    result += \"==\";\n  }\n  if (i === l) {\n    // 2 octets yet to write\n    result += base64abc[uint8[i - 2] >> 2];\n    result += base64abc[((uint8[i - 2] & 0x03) << 4) | (uint8[i - 1] >> 4)];\n    result += base64abc[(uint8[i - 1] & 0x0f) << 2];\n    result += \"=\";\n  }\n  return result.replaceAll(\"+\", \"-\").replaceAll(\"/\", \"_\").replaceAll(\"=\", \"\");\n}\n\n/**\n * Decodes a given RFC4648 base64 encoded string\n * @param b64\n */\nfunction decode(b64: string): Uint8Array {\n  const paddedLength = b64.length + ((4 - (b64.length % 4)) % 4);\n  const binString = atob(b64.replaceAll(\"-\", \"+\").replaceAll(\"_\", \"/\").padEnd(paddedLength, \"=\"));\n  const size = binString.length;\n  const bytes = new Uint8Array(size);\n  for (let i = 0; i < size; i++) {\n    bytes[i] = binString.charCodeAt(i);\n  }\n  return bytes;\n}\n\nexport async function withEncryption<TNamespace extends string, TValue = any>(\n  base64Key: string,\n): Promise<StoreMiddleware<TNamespace, TValue>> {\n  return await EncryptedStore.fromBase64Key(base64Key);\n}\n"]}