{"version":3,"file":"index.mjs","names":["defaultCryptoOptions: ConcretCryptoOptions","merged: ConcretCryptoOptions","unit: <T>(a: T) => T","result: session.SessionData","session","options: ConcretConnectMongoOptions<T>","_clientP: Promise<MongoClient>","parsed: unknown","result: T | undefined","s: InternalSessionType<T>","update: Record<string, unknown>","updateFields: {\n          lastModified?: Date\n          expires?: Date\n          session?: T\n        }","updateQuery: Record<string, unknown>","results: T[]"],"sources":["../src/lib/cryptoAdapters.ts","../src/lib/MongoStore.ts","../src/index.ts"],"sourcesContent":["import util from 'node:util'\nimport { webcrypto } from 'node:crypto'\nimport kruptein from 'kruptein'\n\nexport interface CryptoAdapter {\n  encrypt: (unencryptedPayload: string) => Promise<string>\n  decrypt: (encryptedPayload: string) => Promise<string>\n}\n\nexport type CryptoOptions = {\n  secret: false | string\n  algorithm?: string\n  hashing?: string\n  encodeas?: string\n  key_size?: number\n  iv_size?: number\n  at_size?: number\n}\n\nexport type ConcretCryptoOptions = Required<CryptoOptions>\n\n/* eslint-disable camelcase */\nexport const defaultCryptoOptions: ConcretCryptoOptions = {\n  secret: false,\n  algorithm: 'aes-256-gcm',\n  hashing: 'sha512',\n  encodeas: 'base64',\n  key_size: 32,\n  iv_size: 16,\n  at_size: 16,\n}\n/* eslint-enable camelcase */\n\nexport const createKrupteinAdapter = (\n  options: CryptoOptions\n): CryptoAdapter => {\n  const merged: ConcretCryptoOptions = {\n    ...defaultCryptoOptions,\n    ...options,\n  }\n  if (!merged.secret) {\n    throw new Error('createKrupteinAdapter requires a non-empty secret')\n  }\n  const instance = kruptein(merged)\n  const encrypt = util.promisify(instance.set).bind(instance)\n  const decrypt = util.promisify(instance.get).bind(instance)\n\n  return {\n    async encrypt(plaintext: string): Promise<string> {\n      const ciphertext = await encrypt(merged.secret as string, plaintext)\n      return String(ciphertext)\n    },\n    async decrypt(ciphertext: string): Promise<string> {\n      const plaintext = await decrypt(merged.secret as string, ciphertext)\n      if (typeof plaintext === 'string') {\n        return plaintext\n      }\n      return JSON.stringify(plaintext)\n    },\n  }\n}\n\nexport type WebCryptoEncoding = 'base64' | 'base64url' | 'hex'\n\nexport type WebCryptoAdapterOptions = {\n  secret: string | ArrayBuffer | ArrayBufferView\n  ivLength?: number\n  encoding?: WebCryptoEncoding\n  algorithm?: 'AES-GCM' | 'AES-CBC'\n  salt?: string | ArrayBuffer | ArrayBufferView\n  iterations?: number\n}\n\nconst encoder = new TextEncoder()\nconst decoder = new TextDecoder()\n\nconst toUint8Array = (\n  input: string | ArrayBuffer | ArrayBufferView\n): Uint8Array => {\n  if (typeof input === 'string') {\n    return encoder.encode(input)\n  }\n  if (ArrayBuffer.isView(input)) {\n    return new Uint8Array(input.buffer, input.byteOffset, input.byteLength)\n  }\n  if (input instanceof ArrayBuffer) {\n    return new Uint8Array(input)\n  }\n  throw new TypeError('Unsupported secret type for Web Crypto adapter')\n}\n\nconst encodeBytes = (\n  bytes: Uint8Array,\n  encoding: WebCryptoEncoding\n): string => {\n  switch (encoding) {\n    case 'hex':\n      return Buffer.from(bytes).toString('hex')\n    case 'base64url':\n      return Buffer.from(bytes).toString('base64url')\n    case 'base64':\n    default:\n      return Buffer.from(bytes).toString('base64')\n  }\n}\n\nconst decodeBytes = (\n  payload: string,\n  encoding: WebCryptoEncoding\n): Uint8Array => {\n  switch (encoding) {\n    case 'hex':\n      return new Uint8Array(Buffer.from(payload, 'hex'))\n    case 'base64url':\n      return new Uint8Array(Buffer.from(payload, 'base64url'))\n    case 'base64':\n    default:\n      return new Uint8Array(Buffer.from(payload, 'base64'))\n  }\n}\n\nexport const createWebCryptoAdapter = ({\n  secret,\n  ivLength,\n  encoding = 'base64',\n  algorithm = 'AES-GCM',\n  salt,\n  iterations = 310000,\n}: WebCryptoAdapterOptions): CryptoAdapter => {\n  if (!secret) {\n    throw new Error('createWebCryptoAdapter requires a secret')\n  }\n  const { subtle } = webcrypto\n\n  if (!subtle?.decrypt || !webcrypto?.getRandomValues) {\n    throw new Error('Web Crypto API is not available in this runtime')\n  }\n\n  const resolvedIvLength = ivLength ?? (algorithm === 'AES-GCM' ? 12 : 16)\n  const resolvedSalt =\n    salt ?? encoder.encode('connect-mongo:webcrypto-default-salt')\n\n  const deriveKey = async () => {\n    const secretBytes = toUint8Array(secret)\n    const baseKey = await subtle.importKey(\n      'raw',\n      secretBytes,\n      'PBKDF2',\n      false,\n      ['deriveKey']\n    )\n    const saltBytes =\n      typeof resolvedSalt === 'string'\n        ? encoder.encode(resolvedSalt)\n        : toUint8Array(resolvedSalt)\n    return subtle.deriveKey(\n      {\n        name: 'PBKDF2',\n        salt: saltBytes,\n        iterations,\n        hash: 'SHA-256',\n      },\n      baseKey,\n      { name: algorithm, length: 256 },\n      false,\n      ['encrypt', 'decrypt']\n    )\n  }\n\n  const keyPromise = deriveKey()\n\n  return {\n    async encrypt(plaintext: string): Promise<string> {\n      const key = await keyPromise\n      const iv = webcrypto.getRandomValues(new Uint8Array(resolvedIvLength))\n      const data = encoder.encode(plaintext)\n      const encrypted = await subtle.encrypt({ name: algorithm, iv }, key, data)\n      const cipherBytes = new Uint8Array(encrypted)\n      const combined = new Uint8Array(resolvedIvLength + cipherBytes.byteLength)\n      combined.set(iv, 0)\n      combined.set(cipherBytes, resolvedIvLength)\n      return encodeBytes(combined, encoding)\n    },\n    async decrypt(ciphertext: string): Promise<string> {\n      const key = await keyPromise\n      const combined = decodeBytes(ciphertext, encoding)\n      const iv = combined.slice(0, resolvedIvLength)\n      const data = combined.slice(resolvedIvLength)\n      const decrypted = await subtle.decrypt({ name: algorithm, iv }, key, data)\n      return decoder.decode(decrypted)\n    },\n  }\n}\n","import assert from 'node:assert/strict'\nimport * as session from 'express-session'\nimport {\n  Collection,\n  MongoClient,\n  MongoClientOptions,\n  WriteConcernSettings,\n} from 'mongodb'\nimport Debug from 'debug'\nimport { createKrupteinAdapter } from './cryptoAdapters.js'\nimport type { CryptoAdapter, CryptoOptions } from './cryptoAdapters.js'\nexport type {\n  CryptoAdapter,\n  CryptoOptions,\n  WebCryptoAdapterOptions,\n} from './cryptoAdapters.js'\nexport {\n  createKrupteinAdapter,\n  createWebCryptoAdapter,\n} from './cryptoAdapters.js'\n\nconst debug = Debug('connect-mongo')\n\ntype StoredSessionValue = session.SessionData | string\ntype Serialize<T extends session.SessionData> = (\n  session: T\n) => StoredSessionValue\ntype Unserialize<T extends session.SessionData> = (\n  payload: StoredSessionValue\n) => T\ntype TransformFunctions<T extends session.SessionData> = {\n  serialize: Serialize<T>\n  unserialize: Unserialize<T>\n}\n\nexport type ConnectMongoOptions<\n  T extends session.SessionData = session.SessionData,\n> = {\n  mongoUrl?: string\n  clientPromise?: Promise<MongoClient>\n  client?: MongoClient\n  collectionName?: string\n  mongoOptions?: MongoClientOptions\n  dbName?: string\n  ttl?: number\n  touchAfter?: number\n  stringify?: boolean\n  createAutoRemoveIdx?: boolean\n  autoRemove?: 'native' | 'interval' | 'disabled'\n  autoRemoveInterval?: number\n  serialize?: Serialize<T>\n  unserialize?: Unserialize<T>\n  writeOperationOptions?: WriteConcernSettings\n  transformId?: (sid: string) => string\n  crypto?: CryptoOptions\n  cryptoAdapter?: CryptoAdapter\n  timestamps?: boolean\n}\n\ntype ConcretConnectMongoOptions<\n  T extends session.SessionData = session.SessionData,\n> = {\n  mongoUrl?: string\n  clientPromise?: Promise<MongoClient>\n  client?: MongoClient\n  collectionName: string\n  mongoOptions: MongoClientOptions\n  dbName?: string\n  ttl: number\n  createAutoRemoveIdx?: boolean\n  autoRemove: 'native' | 'interval' | 'disabled'\n  autoRemoveInterval: number\n  touchAfter: number\n  stringify: boolean\n  timestamps: boolean\n  serialize?: Serialize<T>\n  unserialize?: Unserialize<T>\n  writeOperationOptions?: WriteConcernSettings\n  transformId?: (sid: string) => string\n  crypto?: CryptoOptions\n  cryptoAdapter?: CryptoAdapter | null\n}\n\ntype InternalSessionType<T extends session.SessionData> = {\n  _id: string\n  session: StoredSessionValue | T\n  expires?: Date\n  lastModified?: Date\n  createdAt?: Date\n  updatedAt?: Date\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-function\nconst noop = () => {}\nconst unit: <T>(a: T) => T = (a) => a\n\nfunction defaultSerializeFunction<T extends session.SessionData>(\n  currentSession: T\n): T {\n  const result: session.SessionData = {\n    cookie: currentSession.cookie,\n  } as session.SessionData\n  Object.entries(currentSession).forEach(([key, value]) => {\n    if (\n      key === 'cookie' &&\n      value &&\n      typeof (value as { toJSON?: () => unknown }).toJSON === 'function'\n    ) {\n      result.cookie = (\n        value as { toJSON: () => unknown }\n      ).toJSON() as session.Cookie\n    } else {\n      ;(result as Record<string, unknown>)[key] = value as unknown\n    }\n  })\n\n  return result as T\n}\n\nfunction computeTransformFunctions<T extends session.SessionData>(\n  options: ConcretConnectMongoOptions<T>\n): TransformFunctions<T> {\n  if (options.serialize || options.unserialize) {\n    return {\n      serialize: options.serialize || defaultSerializeFunction,\n      unserialize: (options.unserialize || unit) as Unserialize<T>,\n    }\n  }\n\n  if (options.stringify === false) {\n    return {\n      serialize: defaultSerializeFunction,\n      unserialize: unit as Unserialize<T>,\n    }\n  }\n  // Default case\n  return {\n    serialize: (value) => JSON.stringify(value),\n    unserialize: (payload) => JSON.parse(payload as string) as T,\n  }\n}\n\nfunction computeExpires(\n  session: session.SessionData | undefined,\n  fallbackTtlSeconds: number\n): Date {\n  const cookie = session?.cookie as session.Cookie | undefined\n  if (cookie?.expires) {\n    return new Date(cookie.expires)\n  }\n  const now = Date.now()\n  return new Date(now + fallbackTtlSeconds * 1000)\n}\n\nexport default class MongoStore<\n  T extends session.SessionData = session.SessionData,\n>\n  extends session.Store\n{\n  private clientP: Promise<MongoClient>\n  private readonly cryptoAdapter: CryptoAdapter | null = null\n  private timer?: NodeJS.Timeout\n  collectionP: Promise<Collection<InternalSessionType<T>>>\n  private options: ConcretConnectMongoOptions<T>\n  private transformFunctions: TransformFunctions<T>\n\n  constructor({\n    collectionName = 'sessions',\n    ttl = 1209600,\n    mongoOptions = {},\n    autoRemove = 'native',\n    autoRemoveInterval = 10,\n    touchAfter = 0,\n    stringify = true,\n    timestamps = false,\n    crypto,\n    cryptoAdapter,\n    ...required\n  }: ConnectMongoOptions<T>) {\n    super()\n    debug('create MongoStore instance')\n    const options: ConcretConnectMongoOptions<T> = {\n      collectionName,\n      ttl,\n      mongoOptions,\n      autoRemove,\n      autoRemoveInterval,\n      touchAfter,\n      stringify,\n      timestamps,\n      crypto,\n      cryptoAdapter: cryptoAdapter ?? null,\n      ...required,\n    }\n    // Check params\n    assert(\n      options.mongoUrl || options.clientPromise || options.client,\n      'You must provide either mongoUrl|clientPromise|client in options'\n    )\n    assert(\n      options.createAutoRemoveIdx === null ||\n        options.createAutoRemoveIdx === undefined,\n      'options.createAutoRemoveIdx has been reverted to autoRemove and autoRemoveInterval'\n    )\n    assert(\n      !options.autoRemoveInterval || options.autoRemoveInterval <= 71582,\n      /* (Math.pow(2, 32) - 1) / (1000 * 60) */ 'autoRemoveInterval is too large. options.autoRemoveInterval is in minutes but not seconds nor mills'\n    )\n    if (crypto !== undefined && cryptoAdapter !== undefined) {\n      throw new Error(\n        'Provide either the legacy crypto option or cryptoAdapter, not both'\n      )\n    }\n\n    const legacyCryptoRequested =\n      crypto !== undefined && crypto.secret !== false\n    if (options.cryptoAdapter) {\n      this.cryptoAdapter = options.cryptoAdapter\n    } else if (legacyCryptoRequested) {\n      this.cryptoAdapter = createKrupteinAdapter(options.crypto!)\n    }\n    options.cryptoAdapter = this.cryptoAdapter\n\n    this.transformFunctions = computeTransformFunctions(options)\n    let _clientP: Promise<MongoClient>\n    if (options.mongoUrl) {\n      _clientP = MongoClient.connect(options.mongoUrl, options.mongoOptions)\n    } else if (options.clientPromise) {\n      _clientP = options.clientPromise\n    } else if (options.client) {\n      _clientP = Promise.resolve(options.client)\n    } else {\n      throw new Error('Cannot init client. Please provide correct options')\n    }\n    assert(!!_clientP, 'Client is null|undefined')\n    this.clientP = _clientP\n    this.options = options\n    this.collectionP = _clientP.then(async (con) => {\n      const collection = con\n        .db(options.dbName)\n        .collection<InternalSessionType<T>>(options.collectionName)\n      await this.setAutoRemove(collection)\n      return collection\n    })\n  }\n\n  static create<U extends session.SessionData = session.SessionData>(\n    options: ConnectMongoOptions<U>\n  ): MongoStore<U> {\n    return new MongoStore<U>(options)\n  }\n\n  private setAutoRemove(\n    collection: Collection<InternalSessionType<T>>\n  ): Promise<unknown> {\n    const removeQuery = () => ({\n      expires: {\n        $lt: new Date(),\n      },\n    })\n    switch (this.options.autoRemove) {\n      case 'native':\n        debug('Creating MongoDB TTL index')\n        return collection.createIndex(\n          { expires: 1 },\n          {\n            background: true,\n            expireAfterSeconds: 0,\n          }\n        )\n      case 'interval': {\n        debug('create Timer to remove expired sessions')\n        const runIntervalRemove = () =>\n          collection\n            .deleteMany(removeQuery(), {\n              writeConcern: {\n                w: 0,\n              },\n            })\n            .catch((err) => {\n              debug(\n                'autoRemove interval cleanup failed: %s',\n                (err as Error)?.message ?? err\n              )\n            })\n        this.timer = setInterval(\n          () => {\n            void runIntervalRemove()\n          },\n          this.options.autoRemoveInterval * 1000 * 60\n        )\n        this.timer.unref()\n        return Promise.resolve()\n      }\n      case 'disabled':\n      default:\n        return Promise.resolve()\n    }\n  }\n\n  private computeStorageId(sessionId: string) {\n    if (\n      this.options.transformId &&\n      typeof this.options.transformId === 'function'\n    ) {\n      return this.options.transformId(sessionId)\n    }\n    return sessionId\n  }\n\n  /**\n   * Normalize payload before encryption so decrypt can restore the original\n   * serialized session value.\n   */\n  private serializeForCrypto(payload: StoredSessionValue): string {\n    if (typeof payload === 'string') {\n      return payload\n    }\n    try {\n      return JSON.stringify(payload)\n    } catch (error) {\n      debug(\n        'Falling back to string serialization for crypto payload: %O',\n        error\n      )\n      return String(payload)\n    }\n  }\n\n  private parseDecryptedPayload(plaintext: string): StoredSessionValue {\n    let parsed: unknown\n    try {\n      parsed = JSON.parse(plaintext)\n    } catch {\n      parsed = plaintext\n    }\n\n    if (this.options.stringify === false) {\n      if (typeof parsed === 'string') {\n        try {\n          return JSON.parse(parsed) as StoredSessionValue\n        } catch {\n          return parsed as StoredSessionValue\n        }\n      }\n      return parsed as StoredSessionValue\n    }\n\n    // Default stringify path expects a string for unserialize(JSON.parse)\n    if (!this.options.serialize && !this.options.unserialize) {\n      return typeof parsed === 'string'\n        ? (parsed as StoredSessionValue)\n        : (JSON.stringify(parsed) as StoredSessionValue)\n    }\n\n    return parsed as StoredSessionValue\n  }\n\n  /**\n   * Decrypt given session data\n   * @param session session data to be decrypt. Mutate the input session.\n   */\n  private async decryptSession(\n    sessionDoc: InternalSessionType<T> | undefined | null\n  ) {\n    if (\n      this.cryptoAdapter &&\n      sessionDoc &&\n      typeof sessionDoc.session === 'string'\n    ) {\n      const plaintext = await this.cryptoAdapter.decrypt(sessionDoc.session)\n      sessionDoc.session = this.parseDecryptedPayload(plaintext)\n    }\n  }\n\n  /**\n   * Get a session from the store given a session ID (sid)\n   * @param sid session ID\n   */\n  get(sid: string, callback: (err: any, session?: T | null) => void): void {\n    ;(async () => {\n      try {\n        debug(`MongoStore#get=${sid}`)\n        const collection = await this.collectionP\n        const sessionDoc = await collection.findOne({\n          _id: this.computeStorageId(sid),\n          $or: [\n            { expires: { $exists: false } },\n            { expires: { $gt: new Date() } },\n          ],\n        })\n        if (this.cryptoAdapter && sessionDoc) {\n          try {\n            await this.decryptSession(sessionDoc)\n          } catch (error) {\n            callback(error)\n            return\n          }\n        }\n        let result: T | undefined\n        if (sessionDoc) {\n          result = this.transformFunctions.unserialize(sessionDoc.session)\n          if (this.options.touchAfter > 0 && sessionDoc.lastModified) {\n            ;(result as T & { lastModified?: Date }).lastModified =\n              sessionDoc.lastModified\n          }\n        }\n        this.emit('get', sid)\n        callback(null, result ?? null)\n      } catch (error) {\n        callback(error)\n      }\n    })()\n  }\n\n  /**\n   * Upsert a session into the store given a session ID (sid) and session (session) object.\n   * @param sid session ID\n   * @param session session object\n   */\n  set(sid: string, session: T, callback: (err: any) => void = noop): void {\n    ;(async () => {\n      try {\n        debug(`MongoStore#set=${sid}`)\n        // Removing the lastModified prop from the session object before update\n        if (this.options.touchAfter > 0 && session?.lastModified) {\n          delete (session as T & { lastModified?: Date }).lastModified\n        }\n        const s: InternalSessionType<T> = {\n          _id: this.computeStorageId(sid),\n          session: this.transformFunctions.serialize(session),\n        }\n        // Expire handling\n        s.expires = computeExpires(session, this.options.ttl)\n        // Last modify handling\n        if (this.options.touchAfter > 0) {\n          s.lastModified = new Date()\n        }\n        if (this.cryptoAdapter) {\n          const plaintext = this.serializeForCrypto(s.session)\n          const encrypted = await this.cryptoAdapter.encrypt(plaintext)\n          s.session = encrypted as StoredSessionValue\n        }\n        const collection = await this.collectionP\n        const update: Record<string, unknown> = { $set: s }\n        if (this.options.timestamps) {\n          update.$setOnInsert = { createdAt: new Date() }\n          update.$currentDate = { updatedAt: true }\n        }\n        const rawResp = await collection.updateOne({ _id: s._id }, update, {\n          upsert: true,\n          writeConcern: this.options.writeOperationOptions,\n        })\n        if (rawResp.upsertedCount > 0) {\n          this.emit('create', sid)\n        } else {\n          this.emit('update', sid)\n        }\n        this.emit('set', sid)\n      } catch (error) {\n        return callback(error)\n      }\n      return callback(null)\n    })()\n  }\n\n  touch(\n    sid: string,\n    session: T & { lastModified?: Date },\n    callback: (err: any) => void = noop\n  ): void {\n    ;(async () => {\n      try {\n        debug(`MongoStore#touch=${sid}`)\n        const updateFields: {\n          lastModified?: Date\n          expires?: Date\n          session?: T\n        } = {}\n        const touchAfter = this.options.touchAfter * 1000\n        const lastModified = session.lastModified\n          ? session.lastModified.getTime()\n          : 0\n        const currentDate = new Date()\n\n        // If the given options has a touchAfter property, check if the\n        // current timestamp - lastModified timestamp is bigger than\n        // the specified, if it's not, don't touch the session\n        if (touchAfter > 0 && lastModified > 0) {\n          const timeElapsed = currentDate.getTime() - lastModified\n          if (timeElapsed < touchAfter) {\n            debug(`Skip touching session=${sid}`)\n            return callback(null)\n          }\n          updateFields.lastModified = currentDate\n        }\n\n        updateFields.expires = computeExpires(session, this.options.ttl)\n        const collection = await this.collectionP\n        const updateQuery: Record<string, unknown> = { $set: updateFields }\n        if (this.options.timestamps) {\n          updateQuery.$currentDate = { updatedAt: true }\n        }\n        const rawResp = await collection.updateOne(\n          { _id: this.computeStorageId(sid) },\n          updateQuery,\n          { writeConcern: this.options.writeOperationOptions }\n        )\n        if (rawResp.matchedCount === 0) {\n          return callback(new Error('Unable to find the session to touch'))\n        } else {\n          this.emit('touch', sid, session)\n          return callback(null)\n        }\n      } catch (error) {\n        return callback(error)\n      }\n    })()\n  }\n\n  /**\n   * Get all sessions in the store as an array\n   */\n  all(\n    callback: (err: any, obj?: T[] | { [sid: string]: T } | null) => void\n  ): void {\n    ;(async () => {\n      try {\n        debug('MongoStore#all()')\n        const collection = await this.collectionP\n        const sessions = collection.find({\n          $or: [\n            { expires: { $exists: false } },\n            { expires: { $gt: new Date() } },\n          ],\n        })\n        const results: T[] = []\n        for await (const sessionDoc of sessions) {\n          if (this.cryptoAdapter && sessionDoc) {\n            await this.decryptSession(sessionDoc)\n          }\n          results.push(this.transformFunctions.unserialize(sessionDoc.session))\n        }\n        this.emit('all', results)\n        callback(null, results)\n      } catch (error) {\n        callback(error)\n      }\n    })()\n  }\n\n  /**\n   * Destroy/delete a session from the store given a session ID (sid)\n   * @param sid session ID\n   */\n  destroy(sid: string, callback: (err: any) => void = noop): void {\n    debug(`MongoStore#destroy=${sid}`)\n    this.collectionP\n      .then((colleciton) =>\n        colleciton.deleteOne(\n          { _id: this.computeStorageId(sid) },\n          { writeConcern: this.options.writeOperationOptions }\n        )\n      )\n      .then(() => {\n        this.emit('destroy', sid)\n        callback(null)\n      })\n      .catch((err) => callback(err))\n  }\n\n  /**\n   * Get the count of all sessions in the store\n   */\n  length(callback: (err: any, length: number) => void): void {\n    debug('MongoStore#length()')\n    this.collectionP\n      .then((collection) => collection.countDocuments())\n      .then((c) => callback(null, c))\n      .catch((err: unknown) => callback(err, 0))\n  }\n\n  /**\n   * Delete all sessions from the store.\n   */\n  clear(callback: (err: any) => void = noop): void {\n    debug('MongoStore#clear()')\n    this.collectionP\n      .then((collection) =>\n        collection.deleteMany(\n          {},\n          { writeConcern: this.options.writeOperationOptions }\n        )\n      )\n      .then(() => callback(null))\n      .catch((err: unknown) => {\n        const message = (err as Error | undefined)?.message ?? ''\n        // NamespaceNotFound (code 26) occurs if the collection was dropped earlier; treat as success to keep clear() idempotent.\n        if (\n          (err as { code?: number })?.code === 26 ||\n          /ns not found/i.test(message)\n        ) {\n          callback(null)\n          return\n        }\n        callback(err)\n      })\n  }\n\n  /**\n   * Close database connection\n   */\n  close(): Promise<void> {\n    debug('MongoStore#close()')\n    if (this.timer) {\n      clearInterval(this.timer)\n      this.timer = undefined\n    }\n    return this.clientP.then((c) => c.close())\n  }\n}\n","import MongoStore from './lib/MongoStore.js'\nexport {\n  createKrupteinAdapter,\n  createWebCryptoAdapter,\n  type CryptoAdapter,\n  type CryptoOptions,\n  type WebCryptoAdapterOptions,\n} from './lib/cryptoAdapters.js'\n\nexport default MongoStore\nexport { MongoStore }\n"],"mappings":"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"}