{"version":3,"sources":["../src/RedisStringsHandler.ts","../src/SyncedMap.ts","../src/DeduplicatedRequestHandler.ts","../src/CachedHandler.ts","../src/index.ts"],"sourcesContent":["import { commandOptions, createClient } from 'redis';\nimport { SyncedMap } from './SyncedMap';\nimport { DeduplicatedRequestHandler } from './DeduplicatedRequestHandler';\nimport {\n  CacheHandler,\n  CacheHandlerValue,\n  IncrementalCache,\n} from 'next/dist/server/lib/incremental-cache';\n\nexport type CommandOptions = ReturnType<typeof commandOptions>;\ntype GetParams = Parameters<IncrementalCache['get']>;\ntype SetParams = Parameters<IncrementalCache['set']>;\ntype RevalidateParams = Parameters<IncrementalCache['revalidateTag']>;\nexport type Client = ReturnType<typeof createClient>;\n\nexport type CreateRedisStringsHandlerOptions = {\n  database?: number;\n  keyPrefix?: string;\n  timeoutMs?: number;\n  revalidateTagQuerySize?: number;\n  sharedTagsKey?: string;\n  avgResyncIntervalMs?: number;\n  redisGetDeduplication?: boolean;\n  inMemoryCachingTime?: number;\n  defaultStaleAge?: number;\n  estimateExpireAge?: (staleAge: number) => number;\n};\n\nconst NEXT_CACHE_IMPLICIT_TAG_ID = '_N_T_';\nconst REVALIDATED_TAGS_KEY = '__revalidated_tags__';\n\nfunction isImplicitTag(tag: string): boolean {\n  return tag.startsWith(NEXT_CACHE_IMPLICIT_TAG_ID);\n}\n\nexport function getTimeoutRedisCommandOptions(\n  timeoutMs: number,\n): CommandOptions {\n  return commandOptions({ signal: AbortSignal.timeout(timeoutMs) });\n}\n\nexport default class RedisStringsHandler implements CacheHandler {\n  private client: Client;\n  private sharedTagsMap: SyncedMap<string[]>;\n  private revalidatedTagsMap: SyncedMap<number>;\n  private inMemoryDeduplicationCache: SyncedMap<\n    Promise<ReturnType<Client['get']>>\n  >;\n  private redisGet: Client['get'];\n  private redisDeduplicationHandler: DeduplicatedRequestHandler<\n    Client['get'],\n    string | Buffer | null\n  >;\n  private deduplicatedRedisGet: (key: string) => Client['get'];\n  private timeoutMs: number;\n  private keyPrefix: string;\n  private redisGetDeduplication: boolean;\n  private inMemoryCachingTime: number;\n  private defaultStaleAge: number;\n  private estimateExpireAge: (staleAge: number) => number;\n\n  constructor({\n    database = process.env.VERCEL_ENV === 'production' ? 0 : 1,\n    keyPrefix = process.env.VERCEL_URL || 'UNDEFINED_URL_',\n    sharedTagsKey = '__sharedTags__',\n    timeoutMs = 5000,\n    revalidateTagQuerySize = 250,\n    avgResyncIntervalMs = 60 * 60 * 1000,\n    redisGetDeduplication = true,\n    inMemoryCachingTime = 10_000,\n    defaultStaleAge = 60 * 60 * 24 * 14,\n    estimateExpireAge = (staleAge) =>\n      process.env.VERCEL_ENV === 'preview' ? staleAge * 1.2 : staleAge * 2,\n  }: CreateRedisStringsHandlerOptions) {\n    this.keyPrefix = keyPrefix;\n    this.timeoutMs = timeoutMs;\n    this.redisGetDeduplication = redisGetDeduplication;\n    this.inMemoryCachingTime = inMemoryCachingTime;\n    this.defaultStaleAge = defaultStaleAge;\n    this.estimateExpireAge = estimateExpireAge;\n\n    try {\n      this.client = createClient({\n        ...(database !== 0 ? { database } : {}),\n        url: process.env.REDISHOST\n          ? `redis://${process.env.REDISHOST}:${process.env.REDISPORT}`\n          : 'redis://localhost:6379',\n      });\n\n      this.client.on('error', (error) => {\n        console.error('Redis client error', error);\n      });\n\n      this.client\n        .connect()\n        .then(() => {\n          console.info('Redis client connected.');\n        })\n        .catch((error) => {\n          console.error('Failed to connect Redis client:', error);\n          this.client.disconnect();\n        });\n    } catch (error: unknown) {\n      console.error('Failed to initialize Redis client');\n      throw error;\n    }\n\n    const filterKeys = (key: string): boolean =>\n      key !== REVALIDATED_TAGS_KEY && key !== sharedTagsKey;\n\n    this.sharedTagsMap = new SyncedMap<string[]>({\n      client: this.client,\n      keyPrefix,\n      redisKey: sharedTagsKey,\n      database,\n      timeoutMs,\n      querySize: revalidateTagQuerySize,\n      filterKeys,\n      resyncIntervalMs:\n        avgResyncIntervalMs -\n        avgResyncIntervalMs / 10 +\n        Math.random() * (avgResyncIntervalMs / 10),\n    });\n\n    this.revalidatedTagsMap = new SyncedMap<number>({\n      client: this.client,\n      keyPrefix,\n      redisKey: REVALIDATED_TAGS_KEY,\n      database,\n      timeoutMs,\n      querySize: revalidateTagQuerySize,\n      filterKeys,\n      resyncIntervalMs:\n        avgResyncIntervalMs +\n        avgResyncIntervalMs / 10 +\n        Math.random() * (avgResyncIntervalMs / 10),\n    });\n\n    this.inMemoryDeduplicationCache = new SyncedMap({\n      client: this.client,\n      keyPrefix,\n      redisKey: 'inMemoryDeduplicationCache',\n      database,\n      timeoutMs,\n      querySize: revalidateTagQuerySize,\n      filterKeys,\n      customizedSync: {\n        withoutRedisHashmap: true,\n        withoutSetSync: true,\n      },\n    });\n\n    const redisGet: Client['get'] = this.client.get.bind(this.client);\n    this.redisDeduplicationHandler = new DeduplicatedRequestHandler(\n      redisGet,\n      inMemoryCachingTime,\n      this.inMemoryDeduplicationCache,\n    );\n    this.redisGet = redisGet;\n    this.deduplicatedRedisGet =\n      this.redisDeduplicationHandler.deduplicatedFunction;\n  }\n  resetRequestCache(...args: never[]): void {\n    console.warn('WARNING resetRequestCache() was called', args);\n  }\n\n  private async assertClientIsReady(): Promise<void> {\n    await Promise.all([\n      this.sharedTagsMap.waitUntilReady(),\n      this.revalidatedTagsMap.waitUntilReady(),\n    ]);\n    if (!this.client.isReady) {\n      throw new Error('Redis client is not ready yet or connection is lost.');\n    }\n  }\n\n  public async get(key: GetParams[0], ctx: GetParams[1]) {\n    await this.assertClientIsReady();\n\n    const clientGet = this.redisGetDeduplication\n      ? this.deduplicatedRedisGet(key)\n      : this.redisGet;\n    const result = await clientGet(\n      getTimeoutRedisCommandOptions(this.timeoutMs),\n      this.keyPrefix + key,\n    );\n\n    if (!result) {\n      return null;\n    }\n\n    const cacheValue = JSON.parse(result) as\n      | (CacheHandlerValue & { lastModified: number })\n      | null;\n\n    if (!cacheValue) {\n      return null;\n    }\n\n    if (cacheValue.value?.kind === 'FETCH') {\n      cacheValue.value.data.body = Buffer.from(\n        cacheValue.value.data.body,\n      ).toString('base64');\n    }\n\n    const combinedTags = new Set([\n      ...(ctx?.softTags || []),\n      ...(ctx?.tags || []),\n    ]);\n\n    if (combinedTags.size === 0) {\n      return cacheValue;\n    }\n\n    for (const tag of combinedTags) {\n      // TODO: check how this revalidatedTagsMap is used or if it can be deleted\n      const revalidationTime = this.revalidatedTagsMap.get(tag);\n      if (revalidationTime && revalidationTime > cacheValue.lastModified) {\n        const redisKey = this.keyPrefix + key;\n        // Do not await here as this can happen in the background while we can already serve the cacheValue\n        this.client\n          .unlink(getTimeoutRedisCommandOptions(this.timeoutMs), redisKey)\n          .catch((err) => {\n            console.error(\n              'Error occurred while unlinking stale data. Retrying now. Error was:',\n              err,\n            );\n            this.client.unlink(\n              getTimeoutRedisCommandOptions(this.timeoutMs),\n              redisKey,\n            );\n          })\n          .finally(async () => {\n            await this.sharedTagsMap.delete(key);\n            await this.revalidatedTagsMap.delete(tag);\n          });\n        return null;\n      }\n    }\n\n    return cacheValue;\n  }\n  public async set(\n    key: SetParams[0],\n    data: SetParams[1] & { lastModified: number },\n    ctx: SetParams[2],\n  ) {\n    if (data.kind === 'FETCH') {\n      console.time('encoding' + key);\n      data.data.body = Buffer.from(data.data.body, 'base64').toString();\n      console.timeEnd('encoding' + key);\n    }\n    await this.assertClientIsReady();\n\n    data.lastModified = Date.now();\n\n    const value = JSON.stringify(data);\n\n    // pre seed data into deduplicated get client. This will reduce redis load by not requesting\n    // the same value from redis which was just set.\n    if (this.redisGetDeduplication) {\n      this.redisDeduplicationHandler.seedRequestReturn(key, value);\n    }\n\n    const expireAt =\n      ctx.revalidate &&\n      Number.isSafeInteger(ctx.revalidate) &&\n      ctx.revalidate > 0\n        ? this.estimateExpireAge(ctx.revalidate)\n        : this.estimateExpireAge(this.defaultStaleAge);\n    const options = getTimeoutRedisCommandOptions(this.timeoutMs);\n    const setOperation: Promise<string | null> = this.client.set(\n      options,\n      this.keyPrefix + key,\n      value,\n      {\n        EX: expireAt,\n      },\n    );\n\n    let setTagsOperation: Promise<void> | undefined;\n    if (ctx.tags && ctx.tags.length > 0) {\n      const currentTags = this.sharedTagsMap.get(key);\n      const currentIsSameAsNew =\n        currentTags?.length === ctx.tags.length &&\n        currentTags.every((v) => ctx.tags!.includes(v)) &&\n        ctx.tags.every((v) => currentTags.includes(v));\n\n      if (!currentIsSameAsNew) {\n        setTagsOperation = this.sharedTagsMap.set(\n          key,\n          structuredClone(ctx.tags) as string[],\n        );\n      }\n    }\n\n    await Promise.all([setOperation, setTagsOperation]);\n  }\n  public async revalidateTag(tagOrTags: RevalidateParams[0]) {\n    const tags = new Set([tagOrTags || []].flat());\n    await this.assertClientIsReady();\n\n    // TODO: check how this revalidatedTagsMap is used or if it can be deleted\n    for (const tag of tags) {\n      if (isImplicitTag(tag)) {\n        const now = Date.now();\n        await this.revalidatedTagsMap.set(tag, now);\n      }\n    }\n\n    const keysToDelete: string[] = [];\n\n    for (const [key, sharedTags] of this.sharedTagsMap.entries()) {\n      if (sharedTags.some((tag) => tags.has(tag))) {\n        keysToDelete.push(key);\n      }\n    }\n\n    if (keysToDelete.length === 0) {\n      return;\n    }\n\n    const fullRedisKeys = keysToDelete.map((key) => this.keyPrefix + key);\n\n    const options = getTimeoutRedisCommandOptions(this.timeoutMs);\n\n    const deleteKeysOperation = this.client.unlink(options, fullRedisKeys);\n\n    // delete entries from in-memory deduplication cache\n    if (this.redisGetDeduplication && this.inMemoryCachingTime > 0) {\n      for (const key of keysToDelete) {\n        this.inMemoryDeduplicationCache.delete(key);\n      }\n    }\n\n    const deleteTagsOperation = this.sharedTagsMap.delete(keysToDelete);\n\n    await Promise.all([deleteKeysOperation, deleteTagsOperation]);\n  }\n}\n","// SyncedMap.ts\nimport { Client, getTimeoutRedisCommandOptions } from './RedisStringsHandler';\n\ntype CustomizedSync = {\n  withoutRedisHashmap?: boolean;\n  withoutSetSync?: boolean;\n};\n\ntype SyncedMapOptions = {\n  client: Client;\n  keyPrefix: string;\n  redisKey: string; // Redis Hash key\n  database: number;\n  timeoutMs: number;\n  querySize: number;\n  filterKeys: (key: string) => boolean;\n  resyncIntervalMs?: number;\n  customizedSync?: CustomizedSync;\n};\n\nexport type SyncMessage<V> = {\n  type: 'insert' | 'delete';\n  key?: string;\n  value?: V;\n  keys?: string[];\n};\n\nconst SYNC_CHANNEL_SUFFIX = ':sync-channel:';\nexport class SyncedMap<V> {\n  private client: Client;\n  private subscriberClient: Client;\n  private map: Map<string, V>;\n  private keyPrefix: string;\n  private syncChannel: string;\n  private redisKey: string;\n  private database: number;\n  private timeoutMs: number;\n  private querySize: number;\n  private filterKeys: (key: string) => boolean;\n  private resyncIntervalMs?: number;\n  private customizedSync?: CustomizedSync;\n\n  private setupLock: Promise<void>;\n  private setupLockResolve!: () => void;\n\n  constructor(options: SyncedMapOptions) {\n    this.client = options.client;\n    this.keyPrefix = options.keyPrefix;\n    this.redisKey = options.redisKey;\n    this.syncChannel = `${options.keyPrefix}${SYNC_CHANNEL_SUFFIX}${options.redisKey}`;\n    this.database = options.database;\n    this.timeoutMs = options.timeoutMs;\n    this.querySize = options.querySize;\n    this.filterKeys = options.filterKeys;\n    this.resyncIntervalMs = options.resyncIntervalMs;\n    this.customizedSync = options.customizedSync;\n\n    this.map = new Map<string, V>();\n    this.subscriberClient = this.client.duplicate();\n    this.setupLock = new Promise<void>((resolve) => {\n      this.setupLockResolve = resolve;\n    });\n\n    this.setup().catch((error) => {\n      console.error('Failed to setup SyncedMap:', error);\n      throw error;\n    });\n  }\n\n  private async setup() {\n    let setupPromises: Promise<void>[] = [];\n    if (!this.customizedSync?.withoutRedisHashmap) {\n      setupPromises.push(this.initialSync());\n      this.setupPeriodicResync();\n    }\n    setupPromises.push(this.setupPubSub());\n    await Promise.all(setupPromises);\n    this.setupLockResolve();\n  }\n\n  private async initialSync() {\n    let cursor = 0;\n    const hScanOptions = { COUNT: this.querySize };\n\n    try {\n      do {\n        const remoteItems = await this.client.hScan(\n          getTimeoutRedisCommandOptions(this.timeoutMs),\n          this.keyPrefix + this.redisKey,\n          cursor,\n          hScanOptions,\n        );\n        for (const { field, value } of remoteItems.tuples) {\n          if (this.filterKeys(field)) {\n            const parsedValue = JSON.parse(value);\n            this.map.set(field, parsedValue);\n          }\n        }\n        cursor = remoteItems.cursor;\n      } while (cursor !== 0);\n\n      // Clean up keys not in Redis\n      await this.cleanupKeysNotInRedis();\n    } catch (error) {\n      console.error('Error during initial sync:', error);\n      throw error;\n    }\n  }\n\n  private async cleanupKeysNotInRedis() {\n    let cursor = 0;\n    const scanOptions = { COUNT: this.querySize, MATCH: `${this.keyPrefix}*` };\n    let remoteKeys: string[] = [];\n    try {\n      do {\n        const remoteKeysPortion = await this.client.scan(\n          getTimeoutRedisCommandOptions(this.timeoutMs),\n          cursor,\n          scanOptions,\n        );\n        remoteKeys = remoteKeys.concat(remoteKeysPortion.keys);\n        cursor = remoteKeysPortion.cursor;\n      } while (cursor !== 0);\n\n      const remoteKeysSet = new Set(\n        remoteKeys.map((key) => key.substring(this.keyPrefix.length)),\n      );\n\n      const keysToDelete: string[] = [];\n      for (const key of this.map.keys()) {\n        const keyStr = key as unknown as string;\n        if (!remoteKeysSet.has(keyStr) && this.filterKeys(keyStr)) {\n          keysToDelete.push(keyStr);\n        }\n      }\n\n      if (keysToDelete.length > 0) {\n        await this.delete(keysToDelete);\n      }\n    } catch (error) {\n      console.error('Error during cleanup of keys not in Redis:', error);\n      throw error;\n    }\n  }\n\n  private setupPeriodicResync() {\n    if (this.resyncIntervalMs && this.resyncIntervalMs > 0) {\n      setInterval(() => {\n        this.initialSync().catch((error) => {\n          console.error('Error during periodic resync:', error);\n        });\n      }, this.resyncIntervalMs);\n    }\n  }\n\n  private async setupPubSub() {\n    const syncHandler = async (message: string) => {\n      const syncMessage: SyncMessage<V> = JSON.parse(message);\n      if (syncMessage.type === 'insert') {\n        if (syncMessage.key !== undefined && syncMessage.value !== undefined) {\n          this.map.set(syncMessage.key, syncMessage.value);\n        }\n      } else if (syncMessage.type === 'delete') {\n        if (syncMessage.keys) {\n          for (const key of syncMessage.keys) {\n            this.map.delete(key);\n          }\n        }\n      }\n    };\n\n    const keyEventHandler = async (_channel: string, message: string) => {\n      const key = message;\n      if (key.startsWith(this.keyPrefix)) {\n        const keyInMap = key.substring(this.keyPrefix.length);\n        if (this.filterKeys(keyInMap)) {\n          await this.delete(keyInMap, true);\n        }\n      }\n    };\n\n    try {\n      await this.subscriberClient.connect();\n\n      await Promise.all([\n        // We use a custom channel for insert/delete For the following reason:\n        // With custom channel we can delete multiple entries in one message. If we would listen to unlink / del we\n        // could get thousands of messages for one revalidateTag (For example revalidateTag(\"algolia\") would send an enormous amount of network packages)\n        // Also we can send the value in the message for insert\n        this.subscriberClient.subscribe(this.syncChannel, syncHandler),\n        // Subscribe to Redis keyspace notifications for evicted and expired keys\n        this.subscriberClient.subscribe(\n          `__keyevent@${this.database}__:evicted`,\n          keyEventHandler,\n        ),\n        this.subscriberClient.subscribe(\n          `__keyevent@${this.database}__:expired`,\n          keyEventHandler,\n        ),\n      ]);\n\n      // Error handling for reconnection\n      this.subscriberClient.on('error', async (err) => {\n        console.error('Subscriber client error:', err);\n        try {\n          await this.subscriberClient.quit();\n          this.subscriberClient = this.client.duplicate();\n          await this.setupPubSub();\n        } catch (reconnectError) {\n          console.error(\n            'Failed to reconnect subscriber client:',\n            reconnectError,\n          );\n        }\n      });\n    } catch (error) {\n      console.error('Error setting up pub/sub client:', error);\n      throw error;\n    }\n  }\n\n  public async waitUntilReady() {\n    await this.setupLock;\n  }\n\n  public get(key: string): V | undefined {\n    return this.map.get(key);\n  }\n\n  public async set(key: string, value: V): Promise<void> {\n    this.map.set(key, value);\n    const operations = [];\n\n    // This is needed if we only want to sync delete commands. This is especially useful for non serializable data like a promise map\n    if (this.customizedSync?.withoutSetSync) {\n      return;\n    }\n    if (!this.customizedSync?.withoutRedisHashmap) {\n      const options = getTimeoutRedisCommandOptions(this.timeoutMs);\n      operations.push(\n        this.client.hSet(\n          options,\n          this.keyPrefix + this.redisKey,\n          key as unknown as string,\n          JSON.stringify(value),\n        ),\n      );\n    }\n\n    const insertMessage: SyncMessage<V> = {\n      type: 'insert',\n      key: key as unknown as string,\n      value,\n    };\n    operations.push(\n      this.client.publish(this.syncChannel, JSON.stringify(insertMessage)),\n    );\n    await Promise.all(operations);\n  }\n\n  public async delete(\n    keys: string[] | string,\n    withoutSyncMessage = false,\n  ): Promise<void> {\n    const keysArray = Array.isArray(keys) ? keys : [keys];\n    const operations = [];\n\n    for (const key of keysArray) {\n      this.map.delete(key);\n    }\n\n    if (!this.customizedSync?.withoutRedisHashmap) {\n      const options = getTimeoutRedisCommandOptions(this.timeoutMs);\n      operations.push(\n        this.client.hDel(options, this.keyPrefix + this.redisKey, keysArray),\n      );\n    }\n\n    if (!withoutSyncMessage) {\n      const deletionMessage: SyncMessage<V> = {\n        type: 'delete',\n        keys: keysArray,\n      };\n      operations.push(\n        this.client.publish(this.syncChannel, JSON.stringify(deletionMessage)),\n      );\n    }\n    await Promise.all(operations);\n  }\n\n  public has(key: string): boolean {\n    return this.map.has(key);\n  }\n\n  public entries(): IterableIterator<[string, V]> {\n    return this.map.entries();\n  }\n}\n","import { SyncedMap } from './SyncedMap';\nexport class DeduplicatedRequestHandler<\n  T extends (...args: [never, never]) => Promise<K>,\n  K,\n> {\n  private inMemoryDeduplicationCache: SyncedMap<Promise<K>>;\n  private cachingTimeMs: number;\n  private fn: T;\n\n  constructor(\n    fn: T,\n    cachingTimeMs: number,\n    inMemoryDeduplicationCache: SyncedMap<Promise<K>>,\n  ) {\n    this.fn = fn;\n    this.cachingTimeMs = cachingTimeMs;\n    this.inMemoryDeduplicationCache = inMemoryDeduplicationCache;\n  }\n\n  // Method to manually seed a result into the cache\n  seedRequestReturn(key: string, value: K): void {\n    const resultPromise = new Promise<K>((res) => res(value));\n    this.inMemoryDeduplicationCache.set(key, resultPromise);\n    setTimeout(() => {\n      this.inMemoryDeduplicationCache.delete(key);\n    }, this.cachingTimeMs);\n  }\n\n  // Method to handle deduplicated requests\n  deduplicatedFunction = (key: string): T => {\n    //eslint-disable-next-line @typescript-eslint/no-this-alias\n    const self = this;\n    const dedupedFn = async (...args: [never, never]): Promise<K> => {\n      // If there's already a pending request with the same key, return it\n      if (\n        self.inMemoryDeduplicationCache &&\n        self.inMemoryDeduplicationCache.has(key)\n      ) {\n        const res = await self.inMemoryDeduplicationCache\n          .get(key)!\n          .then((v) => structuredClone(v));\n        return res;\n      }\n\n      // If no pending request, call the original function and store the promise\n      const promise = self.fn(...args);\n      self.inMemoryDeduplicationCache.set(key, promise);\n\n      try {\n        const result = await promise;\n        return structuredClone(result);\n      } finally {\n        // Once the promise is resolved/rejected, remove it from the map\n        setTimeout(() => {\n          self.inMemoryDeduplicationCache.delete(key);\n        }, self.cachingTimeMs);\n      }\n    };\n    return dedupedFn as T;\n  };\n}\n","import { CacheHandler } from \"next/dist/server/lib/incremental-cache\";\nimport RedisStringsHandler, { CreateRedisStringsHandlerOptions } from \"./RedisStringsHandler\";\n\nlet cachedHandler: RedisStringsHandler;\n\nexport default class CachedHandler implements CacheHandler {\n  constructor(options: CreateRedisStringsHandlerOptions) {\n    if (!cachedHandler) {\n      console.log(\"created cached handler\");\n      cachedHandler = new RedisStringsHandler(options);\n    }\n  }\n  get(...args: Parameters<RedisStringsHandler[\"get\"]>): ReturnType<RedisStringsHandler[\"get\"]> {\n    return cachedHandler.get(...args);\n  }\n  set(...args: Parameters<RedisStringsHandler[\"set\"]>): ReturnType<RedisStringsHandler[\"set\"]> {\n    return cachedHandler.set(...args);\n  }\n  revalidateTag(...args: Parameters<RedisStringsHandler[\"revalidateTag\"]>): ReturnType<RedisStringsHandler[\"revalidateTag\"]> {\n    return cachedHandler.revalidateTag(...args);\n  }\n  resetRequestCache(...args: Parameters<RedisStringsHandler[\"resetRequestCache\"]>): ReturnType<RedisStringsHandler[\"resetRequestCache\"]> {\n    return cachedHandler.resetRequestCache(...args);\n  }\n}","import CachedHandler from \"./CachedHandler\";\nexport default CachedHandler;"],"mappings":";AAAA,SAAS,gBAAgB,oBAAoB;;;AC2B7C,IAAM,sBAAsB;AACrB,IAAM,YAAN,MAAmB;AAAA,EAiBxB,YAAY,SAA2B;AACrC,SAAK,SAAS,QAAQ;AACtB,SAAK,YAAY,QAAQ;AACzB,SAAK,WAAW,QAAQ;AACxB,SAAK,cAAc,GAAG,QAAQ,SAAS,GAAG,mBAAmB,GAAG,QAAQ,QAAQ;AAChF,SAAK,WAAW,QAAQ;AACxB,SAAK,YAAY,QAAQ;AACzB,SAAK,YAAY,QAAQ;AACzB,SAAK,aAAa,QAAQ;AAC1B,SAAK,mBAAmB,QAAQ;AAChC,SAAK,iBAAiB,QAAQ;AAE9B,SAAK,MAAM,oBAAI,IAAe;AAC9B,SAAK,mBAAmB,KAAK,OAAO,UAAU;AAC9C,SAAK,YAAY,IAAI,QAAc,CAAC,YAAY;AAC9C,WAAK,mBAAmB;AAAA,IAC1B,CAAC;AAED,SAAK,MAAM,EAAE,MAAM,CAAC,UAAU;AAC5B,cAAQ,MAAM,8BAA8B,KAAK;AACjD,YAAM;AAAA,IACR,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,QAAQ;AACpB,QAAI,gBAAiC,CAAC;AACtC,QAAI,CAAC,KAAK,gBAAgB,qBAAqB;AAC7C,oBAAc,KAAK,KAAK,YAAY,CAAC;AACrC,WAAK,oBAAoB;AAAA,IAC3B;AACA,kBAAc,KAAK,KAAK,YAAY,CAAC;AACrC,UAAM,QAAQ,IAAI,aAAa;AAC/B,SAAK,iBAAiB;AAAA,EACxB;AAAA,EAEA,MAAc,cAAc;AAC1B,QAAI,SAAS;AACb,UAAM,eAAe,EAAE,OAAO,KAAK,UAAU;AAE7C,QAAI;AACF,SAAG;AACD,cAAM,cAAc,MAAM,KAAK,OAAO;AAAA,UACpC,8BAA8B,KAAK,SAAS;AAAA,UAC5C,KAAK,YAAY,KAAK;AAAA,UACtB;AAAA,UACA;AAAA,QACF;AACA,mBAAW,EAAE,OAAO,MAAM,KAAK,YAAY,QAAQ;AACjD,cAAI,KAAK,WAAW,KAAK,GAAG;AAC1B,kBAAM,cAAc,KAAK,MAAM,KAAK;AACpC,iBAAK,IAAI,IAAI,OAAO,WAAW;AAAA,UACjC;AAAA,QACF;AACA,iBAAS,YAAY;AAAA,MACvB,SAAS,WAAW;AAGpB,YAAM,KAAK,sBAAsB;AAAA,IACnC,SAAS,OAAO;AACd,cAAQ,MAAM,8BAA8B,KAAK;AACjD,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAc,wBAAwB;AACpC,QAAI,SAAS;AACb,UAAM,cAAc,EAAE,OAAO,KAAK,WAAW,OAAO,GAAG,KAAK,SAAS,IAAI;AACzE,QAAI,aAAuB,CAAC;AAC5B,QAAI;AACF,SAAG;AACD,cAAM,oBAAoB,MAAM,KAAK,OAAO;AAAA,UAC1C,8BAA8B,KAAK,SAAS;AAAA,UAC5C;AAAA,UACA;AAAA,QACF;AACA,qBAAa,WAAW,OAAO,kBAAkB,IAAI;AACrD,iBAAS,kBAAkB;AAAA,MAC7B,SAAS,WAAW;AAEpB,YAAM,gBAAgB,IAAI;AAAA,QACxB,WAAW,IAAI,CAAC,QAAQ,IAAI,UAAU,KAAK,UAAU,MAAM,CAAC;AAAA,MAC9D;AAEA,YAAM,eAAyB,CAAC;AAChC,iBAAW,OAAO,KAAK,IAAI,KAAK,GAAG;AACjC,cAAM,SAAS;AACf,YAAI,CAAC,cAAc,IAAI,MAAM,KAAK,KAAK,WAAW,MAAM,GAAG;AACzD,uBAAa,KAAK,MAAM;AAAA,QAC1B;AAAA,MACF;AAEA,UAAI,aAAa,SAAS,GAAG;AAC3B,cAAM,KAAK,OAAO,YAAY;AAAA,MAChC;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,8CAA8C,KAAK;AACjE,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEQ,sBAAsB;AAC5B,QAAI,KAAK,oBAAoB,KAAK,mBAAmB,GAAG;AACtD,kBAAY,MAAM;AAChB,aAAK,YAAY,EAAE,MAAM,CAAC,UAAU;AAClC,kBAAQ,MAAM,iCAAiC,KAAK;AAAA,QACtD,CAAC;AAAA,MACH,GAAG,KAAK,gBAAgB;AAAA,IAC1B;AAAA,EACF;AAAA,EAEA,MAAc,cAAc;AAC1B,UAAM,cAAc,OAAO,YAAoB;AAC7C,YAAM,cAA8B,KAAK,MAAM,OAAO;AACtD,UAAI,YAAY,SAAS,UAAU;AACjC,YAAI,YAAY,QAAQ,UAAa,YAAY,UAAU,QAAW;AACpE,eAAK,IAAI,IAAI,YAAY,KAAK,YAAY,KAAK;AAAA,QACjD;AAAA,MACF,WAAW,YAAY,SAAS,UAAU;AACxC,YAAI,YAAY,MAAM;AACpB,qBAAW,OAAO,YAAY,MAAM;AAClC,iBAAK,IAAI,OAAO,GAAG;AAAA,UACrB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,UAAM,kBAAkB,OAAO,UAAkB,YAAoB;AACnE,YAAM,MAAM;AACZ,UAAI,IAAI,WAAW,KAAK,SAAS,GAAG;AAClC,cAAM,WAAW,IAAI,UAAU,KAAK,UAAU,MAAM;AACpD,YAAI,KAAK,WAAW,QAAQ,GAAG;AAC7B,gBAAM,KAAK,OAAO,UAAU,IAAI;AAAA,QAClC;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AACF,YAAM,KAAK,iBAAiB,QAAQ;AAEpC,YAAM,QAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,QAKhB,KAAK,iBAAiB,UAAU,KAAK,aAAa,WAAW;AAAA;AAAA,QAE7D,KAAK,iBAAiB;AAAA,UACpB,cAAc,KAAK,QAAQ;AAAA,UAC3B;AAAA,QACF;AAAA,QACA,KAAK,iBAAiB;AAAA,UACpB,cAAc,KAAK,QAAQ;AAAA,UAC3B;AAAA,QACF;AAAA,MACF,CAAC;AAGD,WAAK,iBAAiB,GAAG,SAAS,OAAO,QAAQ;AAC/C,gBAAQ,MAAM,4BAA4B,GAAG;AAC7C,YAAI;AACF,gBAAM,KAAK,iBAAiB,KAAK;AACjC,eAAK,mBAAmB,KAAK,OAAO,UAAU;AAC9C,gBAAM,KAAK,YAAY;AAAA,QACzB,SAAS,gBAAgB;AACvB,kBAAQ;AAAA,YACN;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH,SAAS,OAAO;AACd,cAAQ,MAAM,oCAAoC,KAAK;AACvD,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAa,iBAAiB;AAC5B,UAAM,KAAK;AAAA,EACb;AAAA,EAEO,IAAI,KAA4B;AACrC,WAAO,KAAK,IAAI,IAAI,GAAG;AAAA,EACzB;AAAA,EAEA,MAAa,IAAI,KAAa,OAAyB;AACrD,SAAK,IAAI,IAAI,KAAK,KAAK;AACvB,UAAM,aAAa,CAAC;AAGpB,QAAI,KAAK,gBAAgB,gBAAgB;AACvC;AAAA,IACF;AACA,QAAI,CAAC,KAAK,gBAAgB,qBAAqB;AAC7C,YAAM,UAAU,8BAA8B,KAAK,SAAS;AAC5D,iBAAW;AAAA,QACT,KAAK,OAAO;AAAA,UACV;AAAA,UACA,KAAK,YAAY,KAAK;AAAA,UACtB;AAAA,UACA,KAAK,UAAU,KAAK;AAAA,QACtB;AAAA,MACF;AAAA,IACF;AAEA,UAAM,gBAAgC;AAAA,MACpC,MAAM;AAAA,MACN;AAAA,MACA;AAAA,IACF;AACA,eAAW;AAAA,MACT,KAAK,OAAO,QAAQ,KAAK,aAAa,KAAK,UAAU,aAAa,CAAC;AAAA,IACrE;AACA,UAAM,QAAQ,IAAI,UAAU;AAAA,EAC9B;AAAA,EAEA,MAAa,OACX,MACA,qBAAqB,OACN;AACf,UAAM,YAAY,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAC,IAAI;AACpD,UAAM,aAAa,CAAC;AAEpB,eAAW,OAAO,WAAW;AAC3B,WAAK,IAAI,OAAO,GAAG;AAAA,IACrB;AAEA,QAAI,CAAC,KAAK,gBAAgB,qBAAqB;AAC7C,YAAM,UAAU,8BAA8B,KAAK,SAAS;AAC5D,iBAAW;AAAA,QACT,KAAK,OAAO,KAAK,SAAS,KAAK,YAAY,KAAK,UAAU,SAAS;AAAA,MACrE;AAAA,IACF;AAEA,QAAI,CAAC,oBAAoB;AACvB,YAAM,kBAAkC;AAAA,QACtC,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AACA,iBAAW;AAAA,QACT,KAAK,OAAO,QAAQ,KAAK,aAAa,KAAK,UAAU,eAAe,CAAC;AAAA,MACvE;AAAA,IACF;AACA,UAAM,QAAQ,IAAI,UAAU;AAAA,EAC9B;AAAA,EAEO,IAAI,KAAsB;AAC/B,WAAO,KAAK,IAAI,IAAI,GAAG;AAAA,EACzB;AAAA,EAEO,UAAyC;AAC9C,WAAO,KAAK,IAAI,QAAQ;AAAA,EAC1B;AACF;;;ACxSO,IAAM,6BAAN,MAGL;AAAA,EAKA,YACE,IACA,eACA,4BACA;AAgBF;AAAA,gCAAuB,CAAC,QAAmB;AAEzC,YAAM,OAAO;AACb,YAAM,YAAY,UAAU,SAAqC;AAE/D,YACE,KAAK,8BACL,KAAK,2BAA2B,IAAI,GAAG,GACvC;AACA,gBAAM,MAAM,MAAM,KAAK,2BACpB,IAAI,GAAG,EACP,KAAK,CAAC,MAAM,gBAAgB,CAAC,CAAC;AACjC,iBAAO;AAAA,QACT;AAGA,cAAM,UAAU,KAAK,GAAG,GAAG,IAAI;AAC/B,aAAK,2BAA2B,IAAI,KAAK,OAAO;AAEhD,YAAI;AACF,gBAAM,SAAS,MAAM;AACrB,iBAAO,gBAAgB,MAAM;AAAA,QAC/B,UAAE;AAEA,qBAAW,MAAM;AACf,iBAAK,2BAA2B,OAAO,GAAG;AAAA,UAC5C,GAAG,KAAK,aAAa;AAAA,QACvB;AAAA,MACF;AACA,aAAO;AAAA,IACT;AA7CE,SAAK,KAAK;AACV,SAAK,gBAAgB;AACrB,SAAK,6BAA6B;AAAA,EACpC;AAAA;AAAA,EAGA,kBAAkB,KAAa,OAAgB;AAC7C,UAAM,gBAAgB,IAAI,QAAW,CAAC,QAAQ,IAAI,KAAK,CAAC;AACxD,SAAK,2BAA2B,IAAI,KAAK,aAAa;AACtD,eAAW,MAAM;AACf,WAAK,2BAA2B,OAAO,GAAG;AAAA,IAC5C,GAAG,KAAK,aAAa;AAAA,EACvB;AAkCF;;;AFhCA,IAAM,6BAA6B;AACnC,IAAM,uBAAuB;AAE7B,SAAS,cAAc,KAAsB;AAC3C,SAAO,IAAI,WAAW,0BAA0B;AAClD;AAEO,SAAS,8BACd,WACgB;AAChB,SAAO,eAAe,EAAE,QAAQ,YAAY,QAAQ,SAAS,EAAE,CAAC;AAClE;AAEA,IAAqB,sBAArB,MAAiE;AAAA,EAoB/D,YAAY;AAAA,IACV,WAAW,QAAQ,IAAI,eAAe,eAAe,IAAI;AAAA,IACzD,YAAY,QAAQ,IAAI,cAAc;AAAA,IACtC,gBAAgB;AAAA,IAChB,YAAY;AAAA,IACZ,yBAAyB;AAAA,IACzB,sBAAsB,KAAK,KAAK;AAAA,IAChC,wBAAwB;AAAA,IACxB,sBAAsB;AAAA,IACtB,kBAAkB,KAAK,KAAK,KAAK;AAAA,IACjC,oBAAoB,CAAC,aACnB,QAAQ,IAAI,eAAe,YAAY,WAAW,MAAM,WAAW;AAAA,EACvE,GAAqC;AACnC,SAAK,YAAY;AACjB,SAAK,YAAY;AACjB,SAAK,wBAAwB;AAC7B,SAAK,sBAAsB;AAC3B,SAAK,kBAAkB;AACvB,SAAK,oBAAoB;AAEzB,QAAI;AACF,WAAK,SAAS,aAAa;AAAA,QACzB,GAAI,aAAa,IAAI,EAAE,SAAS,IAAI,CAAC;AAAA,QACrC,KAAK,QAAQ,IAAI,YACb,WAAW,QAAQ,IAAI,SAAS,IAAI,QAAQ,IAAI,SAAS,KACzD;AAAA,MACN,CAAC;AAED,WAAK,OAAO,GAAG,SAAS,CAAC,UAAU;AACjC,gBAAQ,MAAM,sBAAsB,KAAK;AAAA,MAC3C,CAAC;AAED,WAAK,OACF,QAAQ,EACR,KAAK,MAAM;AACV,gBAAQ,KAAK,yBAAyB;AAAA,MACxC,CAAC,EACA,MAAM,CAAC,UAAU;AAChB,gBAAQ,MAAM,mCAAmC,KAAK;AACtD,aAAK,OAAO,WAAW;AAAA,MACzB,CAAC;AAAA,IACL,SAAS,OAAgB;AACvB,cAAQ,MAAM,mCAAmC;AACjD,YAAM;AAAA,IACR;AAEA,UAAM,aAAa,CAAC,QAClB,QAAQ,wBAAwB,QAAQ;AAE1C,SAAK,gBAAgB,IAAI,UAAoB;AAAA,MAC3C,QAAQ,KAAK;AAAA,MACb;AAAA,MACA,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA,WAAW;AAAA,MACX;AAAA,MACA,kBACE,sBACA,sBAAsB,KACtB,KAAK,OAAO,KAAK,sBAAsB;AAAA,IAC3C,CAAC;AAED,SAAK,qBAAqB,IAAI,UAAkB;AAAA,MAC9C,QAAQ,KAAK;AAAA,MACb;AAAA,MACA,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA,WAAW;AAAA,MACX;AAAA,MACA,kBACE,sBACA,sBAAsB,KACtB,KAAK,OAAO,KAAK,sBAAsB;AAAA,IAC3C,CAAC;AAED,SAAK,6BAA6B,IAAI,UAAU;AAAA,MAC9C,QAAQ,KAAK;AAAA,MACb;AAAA,MACA,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA,WAAW;AAAA,MACX;AAAA,MACA,gBAAgB;AAAA,QACd,qBAAqB;AAAA,QACrB,gBAAgB;AAAA,MAClB;AAAA,IACF,CAAC;AAED,UAAM,WAA0B,KAAK,OAAO,IAAI,KAAK,KAAK,MAAM;AAChE,SAAK,4BAA4B,IAAI;AAAA,MACnC;AAAA,MACA;AAAA,MACA,KAAK;AAAA,IACP;AACA,SAAK,WAAW;AAChB,SAAK,uBACH,KAAK,0BAA0B;AAAA,EACnC;AAAA,EACA,qBAAqB,MAAqB;AACxC,YAAQ,KAAK,0CAA0C,IAAI;AAAA,EAC7D;AAAA,EAEA,MAAc,sBAAqC;AACjD,UAAM,QAAQ,IAAI;AAAA,MAChB,KAAK,cAAc,eAAe;AAAA,MAClC,KAAK,mBAAmB,eAAe;AAAA,IACzC,CAAC;AACD,QAAI,CAAC,KAAK,OAAO,SAAS;AACxB,YAAM,IAAI,MAAM,sDAAsD;AAAA,IACxE;AAAA,EACF;AAAA,EAEA,MAAa,IAAI,KAAmB,KAAmB;AACrD,UAAM,KAAK,oBAAoB;AAE/B,UAAM,YAAY,KAAK,wBACnB,KAAK,qBAAqB,GAAG,IAC7B,KAAK;AACT,UAAM,SAAS,MAAM;AAAA,MACnB,8BAA8B,KAAK,SAAS;AAAA,MAC5C,KAAK,YAAY;AAAA,IACnB;AAEA,QAAI,CAAC,QAAQ;AACX,aAAO;AAAA,IACT;AAEA,UAAM,aAAa,KAAK,MAAM,MAAM;AAIpC,QAAI,CAAC,YAAY;AACf,aAAO;AAAA,IACT;AAEA,QAAI,WAAW,OAAO,SAAS,SAAS;AACtC,iBAAW,MAAM,KAAK,OAAO,OAAO;AAAA,QAClC,WAAW,MAAM,KAAK;AAAA,MACxB,EAAE,SAAS,QAAQ;AAAA,IACrB;AAEA,UAAM,eAAe,oBAAI,IAAI;AAAA,MAC3B,GAAI,KAAK,YAAY,CAAC;AAAA,MACtB,GAAI,KAAK,QAAQ,CAAC;AAAA,IACpB,CAAC;AAED,QAAI,aAAa,SAAS,GAAG;AAC3B,aAAO;AAAA,IACT;AAEA,eAAW,OAAO,cAAc;AAE9B,YAAM,mBAAmB,KAAK,mBAAmB,IAAI,GAAG;AACxD,UAAI,oBAAoB,mBAAmB,WAAW,cAAc;AAClE,cAAM,WAAW,KAAK,YAAY;AAElC,aAAK,OACF,OAAO,8BAA8B,KAAK,SAAS,GAAG,QAAQ,EAC9D,MAAM,CAAC,QAAQ;AACd,kBAAQ;AAAA,YACN;AAAA,YACA;AAAA,UACF;AACA,eAAK,OAAO;AAAA,YACV,8BAA8B,KAAK,SAAS;AAAA,YAC5C;AAAA,UACF;AAAA,QACF,CAAC,EACA,QAAQ,YAAY;AACnB,gBAAM,KAAK,cAAc,OAAO,GAAG;AACnC,gBAAM,KAAK,mBAAmB,OAAO,GAAG;AAAA,QAC1C,CAAC;AACH,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EACA,MAAa,IACX,KACA,MACA,KACA;AACA,QAAI,KAAK,SAAS,SAAS;AACzB,cAAQ,KAAK,aAAa,GAAG;AAC7B,WAAK,KAAK,OAAO,OAAO,KAAK,KAAK,KAAK,MAAM,QAAQ,EAAE,SAAS;AAChE,cAAQ,QAAQ,aAAa,GAAG;AAAA,IAClC;AACA,UAAM,KAAK,oBAAoB;AAE/B,SAAK,eAAe,KAAK,IAAI;AAE7B,UAAM,QAAQ,KAAK,UAAU,IAAI;AAIjC,QAAI,KAAK,uBAAuB;AAC9B,WAAK,0BAA0B,kBAAkB,KAAK,KAAK;AAAA,IAC7D;AAEA,UAAM,WACJ,IAAI,cACJ,OAAO,cAAc,IAAI,UAAU,KACnC,IAAI,aAAa,IACb,KAAK,kBAAkB,IAAI,UAAU,IACrC,KAAK,kBAAkB,KAAK,eAAe;AACjD,UAAM,UAAU,8BAA8B,KAAK,SAAS;AAC5D,UAAM,eAAuC,KAAK,OAAO;AAAA,MACvD;AAAA,MACA,KAAK,YAAY;AAAA,MACjB;AAAA,MACA;AAAA,QACE,IAAI;AAAA,MACN;AAAA,IACF;AAEA,QAAI;AACJ,QAAI,IAAI,QAAQ,IAAI,KAAK,SAAS,GAAG;AACnC,YAAM,cAAc,KAAK,cAAc,IAAI,GAAG;AAC9C,YAAM,qBACJ,aAAa,WAAW,IAAI,KAAK,UACjC,YAAY,MAAM,CAAC,MAAM,IAAI,KAAM,SAAS,CAAC,CAAC,KAC9C,IAAI,KAAK,MAAM,CAAC,MAAM,YAAY,SAAS,CAAC,CAAC;AAE/C,UAAI,CAAC,oBAAoB;AACvB,2BAAmB,KAAK,cAAc;AAAA,UACpC;AAAA,UACA,gBAAgB,IAAI,IAAI;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAEA,UAAM,QAAQ,IAAI,CAAC,cAAc,gBAAgB,CAAC;AAAA,EACpD;AAAA,EACA,MAAa,cAAc,WAAgC;AACzD,UAAM,OAAO,IAAI,IAAI,CAAC,aAAa,CAAC,CAAC,EAAE,KAAK,CAAC;AAC7C,UAAM,KAAK,oBAAoB;AAG/B,eAAW,OAAO,MAAM;AACtB,UAAI,cAAc,GAAG,GAAG;AACtB,cAAM,MAAM,KAAK,IAAI;AACrB,cAAM,KAAK,mBAAmB,IAAI,KAAK,GAAG;AAAA,MAC5C;AAAA,IACF;AAEA,UAAM,eAAyB,CAAC;AAEhC,eAAW,CAAC,KAAK,UAAU,KAAK,KAAK,cAAc,QAAQ,GAAG;AAC5D,UAAI,WAAW,KAAK,CAAC,QAAQ,KAAK,IAAI,GAAG,CAAC,GAAG;AAC3C,qBAAa,KAAK,GAAG;AAAA,MACvB;AAAA,IACF;AAEA,QAAI,aAAa,WAAW,GAAG;AAC7B;AAAA,IACF;AAEA,UAAM,gBAAgB,aAAa,IAAI,CAAC,QAAQ,KAAK,YAAY,GAAG;AAEpE,UAAM,UAAU,8BAA8B,KAAK,SAAS;AAE5D,UAAM,sBAAsB,KAAK,OAAO,OAAO,SAAS,aAAa;AAGrE,QAAI,KAAK,yBAAyB,KAAK,sBAAsB,GAAG;AAC9D,iBAAW,OAAO,cAAc;AAC9B,aAAK,2BAA2B,OAAO,GAAG;AAAA,MAC5C;AAAA,IACF;AAEA,UAAM,sBAAsB,KAAK,cAAc,OAAO,YAAY;AAElE,UAAM,QAAQ,IAAI,CAAC,qBAAqB,mBAAmB,CAAC;AAAA,EAC9D;AACF;;;AGhVA,IAAI;AAEJ,IAAqB,gBAArB,MAA2D;AAAA,EACzD,YAAY,SAA2C;AACrD,QAAI,CAAC,eAAe;AAClB,cAAQ,IAAI,wBAAwB;AACpC,sBAAgB,IAAI,oBAAoB,OAAO;AAAA,IACjD;AAAA,EACF;AAAA,EACA,OAAO,MAAsF;AAC3F,WAAO,cAAc,IAAI,GAAG,IAAI;AAAA,EAClC;AAAA,EACA,OAAO,MAAsF;AAC3F,WAAO,cAAc,IAAI,GAAG,IAAI;AAAA,EAClC;AAAA,EACA,iBAAiB,MAA0G;AACzH,WAAO,cAAc,cAAc,GAAG,IAAI;AAAA,EAC5C;AAAA,EACA,qBAAqB,MAAkH;AACrI,WAAO,cAAc,kBAAkB,GAAG,IAAI;AAAA,EAChD;AACF;;;ACvBA,IAAO,gBAAQ;","names":[]}