lunibee 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/dist/builders/attachment.d.ts +1 -0
  2. package/dist/builders/clone.d.ts +10 -0
  3. package/dist/builders/commands.d.ts +1 -1
  4. package/dist/builders/components.d.ts +24 -5
  5. package/dist/builders/index.js +64 -17
  6. package/dist/builders/index.js.map +10 -9
  7. package/dist/collection/index.d.ts +1 -0
  8. package/dist/collection/index.js +297 -19
  9. package/dist/collection/index.js.map +5 -4
  10. package/dist/collection/redis.d.ts +98 -0
  11. package/dist/core/collector.d.ts +8 -0
  12. package/dist/core/events.d.ts +1 -0
  13. package/dist/core/index.d.ts +3 -0
  14. package/dist/core/index.js +6242 -4733
  15. package/dist/core/index.js.map +47 -40
  16. package/dist/core/permissions.d.ts +3 -402
  17. package/dist/core/redis-cache.d.ts +85 -0
  18. package/dist/formatters/index.d.ts +5 -1
  19. package/dist/formatters/index.js +7 -3
  20. package/dist/formatters/index.js.map +3 -3
  21. package/dist/handlers/index.js +11 -2
  22. package/dist/handlers/index.js.map +3 -3
  23. package/dist/index.js +8688 -6136
  24. package/dist/index.js.map +67 -59
  25. package/dist/managers/application.d.ts +10 -6
  26. package/dist/managers/base.d.ts +11 -1
  27. package/dist/managers/guild.d.ts +3 -1
  28. package/dist/managers/index.d.ts +6 -1
  29. package/dist/managers/index.js +383 -109
  30. package/dist/managers/index.js.map +20 -23
  31. package/dist/managers/member.d.ts +3 -1
  32. package/dist/managers/message.d.ts +13 -4
  33. package/dist/managers/thread.d.ts +3 -3
  34. package/dist/rest/decoder.d.ts +2 -0
  35. package/dist/rest/errors.d.ts +5 -2
  36. package/dist/rest/headers.d.ts +31 -0
  37. package/dist/rest/identity.d.ts +31 -0
  38. package/dist/rest/index.d.ts +97 -6
  39. package/dist/rest/index.js +1355 -220
  40. package/dist/rest/index.js.map +16 -13
  41. package/dist/rest/limiter.d.ts +75 -10
  42. package/dist/rest/redis.d.ts +103 -22
  43. package/dist/rest/scheduler.d.ts +13 -0
  44. package/dist/rest/store.d.ts +135 -12
  45. package/dist/rest/telemetry.d.ts +151 -0
  46. package/dist/rest/webhook.d.ts +18 -6
  47. package/dist/sharding/bus.d.ts +4 -2
  48. package/dist/sharding/cluster.d.ts +29 -1
  49. package/dist/sharding/health.d.ts +1 -1
  50. package/dist/sharding/host.d.ts +13 -2
  51. package/dist/sharding/identify.d.ts +2 -0
  52. package/dist/sharding/index.d.ts +8 -0
  53. package/dist/sharding/index.js +579 -65
  54. package/dist/sharding/index.js.map +17 -15
  55. package/dist/sharding/leader.d.ts +34 -0
  56. package/dist/sharding/remote.d.ts +36 -2
  57. package/dist/sharding/supervisor.d.ts +1 -1
  58. package/dist/sharding/thread.d.ts +30 -0
  59. package/dist/sharding/transport.d.ts +6 -5
  60. package/dist/sharding/worker.d.ts +11 -1
  61. package/dist/structures/base.d.ts +16 -5
  62. package/dist/structures/index.d.ts +1 -1
  63. package/dist/structures/index.js +57 -91
  64. package/dist/structures/index.js.map +10 -18
  65. package/dist/structures/options.d.ts +3 -2
  66. package/dist/structures/permissions.d.ts +409 -0
  67. package/dist/structures/resources.d.ts +4 -1
  68. package/dist/types/gateway.d.ts +4 -0
  69. package/dist/types/index.d.ts +14 -4
  70. package/dist/types/index.js.map +3 -3
  71. package/dist/utils/args.d.ts +3 -1
  72. package/dist/utils/index.d.ts +6 -1
  73. package/dist/utils/index.js +17 -10
  74. package/dist/utils/index.js.map +4 -4
  75. package/dist/voice/index.d.ts +7 -1
  76. package/dist/voice/index.js +33 -10
  77. package/dist/voice/index.js.map +3 -3
  78. package/dist/ws/index.d.ts +2 -0
  79. package/dist/ws/index.js +32 -4
  80. package/dist/ws/index.js.map +5 -5
  81. package/package.json +21 -17
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../packages/collection/src/cache.ts", "../../packages/collection/src/index.ts"],
3
+ "sources": ["../../packages/collection/src/cache.ts", "../../packages/collection/src/redis.ts", "../../packages/collection/src/index.ts"],
4
4
  "sourcesContent": [
5
5
  "import { Collection } from \"./index.js\";\n\n/** Cache policy for bounded resource storage. */\nexport interface CacheOptions {\n /** Maximum number of entries retained. */\n maxSize?: number;\n /** Time-to-live in milliseconds. Omit to disable expiration. */\n ttl?: number;\n /** Fraction (0-1) of `ttl` randomly shaved off each entry's lifetime. Default `0`. */\n jitter?: number;\n /**\n * Accepted for compatibility and still validated. Expired entries are now\n * dropped at their deadline, so no periodic sweep is needed.\n */\n sweepInterval?: number;\n}\n\n/**\n * Bounded cache with a fixed TTL, least-recently-used eviction and explicit\n * invalidation. A thin policy layer over {@link Collection}: reads promote an\n * entry but do not extend its TTL.\n */\nexport class Cache<K, V> {\n readonly #entries: Collection<K, V>;\n\n /** Creates a cache using the supplied retention policy. */\n public constructor(options: CacheOptions = {}) {\n const maxSize = options.maxSize ?? Infinity;\n const ttl = options.ttl ?? 0;\n if ((!Number.isInteger(maxSize) && maxSize !== Infinity) || maxSize < 1)\n throw new RangeError(\"Cache maxSize must be a positive integer.\");\n if (!Number.isFinite(ttl) || ttl < 0)\n throw new RangeError(\n \"Cache ttl must be a non-negative finite number.\",\n );\n if (!((options.jitter ?? 0) >= 0 && (options.jitter ?? 0) <= 1))\n throw new RangeError(\"Cache jitter must be between 0 and 1.\");\n if (ttl > 0) {\n const interval = options.sweepInterval ?? Math.min(ttl, 60_000);\n if (!Number.isFinite(interval) || interval < 1)\n throw new RangeError(\"Cache sweepInterval must be positive.\");\n }\n this.#entries = new Collection<K, V>(null, {\n ttl: ttl > 0 ? ttl : undefined,\n jitter: options.jitter,\n maxSize: maxSize === Infinity ? undefined : maxSize,\n slide: false,\n });\n }\n\n /** Number of currently live entries. */\n public get size(): number {\n return this.#entries.size;\n }\n /** Reads a live entry and marks it most recently used. */\n public get(key: K): V | undefined {\n return this.#entries.get(key);\n }\n /** Returns whether a live entry exists. */\n public has(key: K): boolean {\n return this.#entries.has(key);\n }\n /** Stores an entry and evicts the least recently used ones when the bound is exceeded. */\n public set(key: K, value: V): this {\n this.#entries.set(key, value);\n return this;\n }\n /** Invalidates one key. */\n public delete(key: K): boolean {\n return this.#entries.delete(key);\n }\n /** Invalidates every cached resource. */\n public clear(): void {\n this.#entries.clear();\n }\n /** Invalidates every entry matching a predicate. */\n public invalidate(predicate: (value: V, key: K) => boolean): number {\n return this.#entries.sweep(predicate);\n }\n /** Removes expired entries now and returns the number removed. */\n public sweep(): number {\n return this.#entries.purge();\n }\n /** Kept for compatibility: there is no background sweeper to stop. */\n public dispose(): void {}\n /** Returns live cached values. */\n public values(): V[] {\n return [...this.#entries.values()];\n }\n /** Returns live cached entries. */\n public entries(): [K, V][] {\n return [...this.#entries.entries()];\n }\n}\n",
6
- "/** Retention policy for a {@link Collection}. */\nexport interface CollectionOptions<K = unknown, V = unknown> {\n /** Default sliding TTL in ms for `set()`. Omit for no expiry. */\n ttl?: number;\n /** Fraction (0-1) of each entry's TTL randomly shaved off when it is set, so entries stored together do not expire together. Default `0`. */\n jitter?: number;\n /** Maximum entries stored with `set()`; least-recently-used are evicted past it. `setWithoutTTL()` entries are never counted or evicted. */\n maxSize?: number;\n /** Whether a read restarts a TTL entry's window. Default `true`; with `false` an entry lapses a fixed time after it was set, and reads only mark it recently used. */\n slide?: boolean;\n /** Called after an entry is removed automatically, with why. Exceptions are swallowed. */\n onEvict?: (key: K, value: V, reason: EvictionReason) => void;\n}\n\n/** Why an entry was removed automatically. */\nexport type EvictionReason = \"expired\" | \"evicted\";\n\n/** Cumulative counters from {@link Collection.stats}. */\nexport interface CollectionStats {\n /** `get`/`peek` calls that found a value. */\n hits: number;\n /** `get`/`peek` calls that found nothing. */\n misses: number;\n /** Entries removed because their TTL lapsed. */\n expired: number;\n /** Entries removed to stay within `maxSize`. */\n evicted: number;\n}\n\n/**\n * Everything the policy knows about one key: its place in the recency list\n * and its TTL. One record serves the policy map, the recency list and the\n * expiry heap, so a write touches one extra hash entry and allocates once.\n */\ntype Entry<K, V> = {\n key: K;\n /** A copy of the stored value, so a read needs one lookup instead of two. */\n value: V;\n /** Neighbours in recency order; meaningful while `inLru`. */\n older: Entry<K, V> | undefined;\n newer: Entry<K, V> | undefined;\n inLru: boolean;\n /** TTL window in ms; 0 when the entry does not expire (and is not in the heap). */\n window: number;\n /** The current deadline; a read moves it later without touching the heap. */\n deadline: number;\n /** The deadline the heap ordered this record by. */\n filed: number;\n};\n\n/**\n * Everything a retention policy needs. A Collection without `ttl` or\n * `maxSize` never creates one, so plain collections cost no more than a Map.\n */\ntype Policy<K, V> = {\n /** Keys with a TTL or a recency position; `setWithoutTTL()` keys are absent. */\n entries: Map<K, Entry<K, V>>;\n /** Oldest and newest entries of the recency list; only `maxSize` collections use it. */\n oldest: Entry<K, V> | undefined;\n newest: Entry<K, V> | undefined;\n lruSize: number;\n /** Min-heap by `filed`. A record that is no longer its key's map value is stale and dropped lazily. */\n heap: Entry<K, V>[];\n timer?: ReturnType<typeof setTimeout>;\n armedFor: number;\n /** The options, kept here so a plain collection carries none of them. */\n ttl: number | undefined;\n jitter: number;\n maxSize: number | undefined;\n slide: boolean;\n /** Stored loosely typed so the callback does not make Collection invariant in K and V. */\n onEvict:\n | ((key: unknown, value: unknown, reason: EvictionReason) => void)\n | undefined;\n expired: number;\n evicted: number;\n};\n\nfunction newPolicy<K, V>(options: CollectionOptions<K, V> = {}): Policy<K, V> {\n return {\n ttl: options.ttl,\n jitter: options.jitter ?? 0,\n maxSize: options.maxSize,\n slide: options.slide ?? true,\n onEvict: options.onEvict as Policy<K, V>[\"onEvict\"],\n expired: 0,\n evicted: 0,\n entries: new Map(),\n oldest: undefined,\n newest: undefined,\n lruSize: 0,\n heap: [],\n armedFor: Infinity,\n };\n}\n\n/**\n * Reads a value that `has()` just confirmed, without touching a Lunibee\n * collection's TTL, recency or hit counters.\n */\nfunction peekOf<K, V>(\n collection: ReadonlyCollection<K, V>,\n key: K,\n): V | undefined {\n return collection instanceof Map\n ? (Map.prototype.get.call(collection, key) as V | undefined)\n : collection.get(key);\n}\n\n/** What `merge()` does with one entry: keep it with `value`, or drop it. */\nexport type Keep<V> = { keep: true; value: V } | { keep: false };\n\n/**\n * A `Collection` seen read-only: every method that does not change it. Pass it\n * where you only read, so a function cannot add to or remove from the cache.\n */\nexport type ReadonlyCollection<K, V> = Omit<\n Collection<K, V>,\n | \"set\"\n | \"setWithoutTTL\"\n | \"delete\"\n | \"clear\"\n | \"ensure\"\n | \"forEach\"\n | \"get\"\n | \"sweep\"\n | \"purge\"\n> &\n ReadonlyMap<K, V>;\n\nconst mapGet = Map.prototype.get as (\n this: Map<unknown, unknown>,\n key: unknown,\n) => unknown;\nconst mapHas = Map.prototype.has as (\n this: Map<unknown, unknown>,\n key: unknown,\n) => boolean;\n\n/** Picks `amount` different items at random (a partial Fisher-Yates shuffle of `items`). */\nfunction sample<T>(items: T[], amount: number): T[] {\n if (!Number.isInteger(amount) || amount < 0)\n throw new RangeError(\"amount must be a non-negative integer.\");\n const count = Math.min(amount, items.length);\n for (let i = 0; i < count; i++) {\n const j = i + Math.floor(Math.random() * (items.length - i));\n [items[i], items[j]] = [items[j]!, items[i]!];\n }\n items.length = count;\n return items;\n}\n\nfunction assertTTL(ttl: number | undefined): void {\n if (ttl !== undefined && (!Number.isFinite(ttl) || ttl <= 0))\n throw new RangeError(\"TTL must be a positive number, or omitted.\");\n}\n\n/**\n * A keyed collection for Lunibee resource and application state.\n *\n * - `set(key, value, ttl?)` is TTL/LRU-aware: with a TTL (the default from\n * options, or per call) the entry expires after that window of inactivity,\n * and with `maxSize` it counts toward the cap.\n * - `setWithoutTTL(key, value)` never expires: no deadline, no heap record,\n * no timer, and exempt from `maxSize` eviction. Resource managers store\n * Discord state this way, so it leaves only through an explicit delete.\n *\n * Without options, a Collection behaves like a plain Map.\n */\nexport class Collection<K, V> extends Map<K, V> {\n /** Created with any option, or by the first `set()` with its own TTL. */\n #policy?: Policy<K, V>;\n #hits = 0;\n #misses = 0;\n\n /**\n * @param entries Initial entries, stored with `set()`.\n * @param options TTL and size policy.\n * @throws {RangeError} On a non-positive TTL or non-integer `maxSize`.\n */\n public constructor(\n entries?: Iterable<readonly [K, V]> | null,\n options: CollectionOptions<K, V> = {},\n ) {\n super();\n assertTTL(options.ttl);\n if (\n options.jitter !== undefined &&\n !(options.jitter >= 0 && options.jitter <= 1)\n )\n throw new RangeError(\"jitter must be between 0 and 1.\");\n if (\n options.maxSize !== undefined &&\n (!Number.isInteger(options.maxSize) || options.maxSize <= 0)\n )\n throw new RangeError(\"maxSize must be a positive integer.\");\n if (\n options.ttl !== undefined ||\n options.jitter !== undefined ||\n options.maxSize !== undefined ||\n options.slide !== undefined ||\n options.onEvict !== undefined\n )\n this.#policy = newPolicy(options);\n if (entries) for (const [key, value] of entries) this.set(key, value);\n }\n\n /**\n * Stores an entry with the default TTL (or `ttl`), marks it most recently\n * used, and enforces `maxSize`. Turns a `setWithoutTTL()` entry back into\n * a TTL/LRU entry.\n */\n public override set(key: K, value: V, ttl?: number): this {\n if (ttl === undefined && this.#policy === undefined)\n return super.set(key, value);\n assertTTL(ttl);\n let window = ttl ?? this.#policy?.ttl;\n const jitter = this.#policy?.jitter ?? 0;\n if (window !== undefined && jitter > 0)\n window = Math.max(1, window * (1 - jitter * Math.random()));\n if (window !== undefined) this.#policy ??= newPolicy();\n if (!this.#policy) return super.set(key, value);\n // A key that was not stored before has no policy entry.\n const before = super.size;\n super.set(key, value);\n this.#track(key, value, window, super.size !== before);\n this.#enforceCap();\n return this;\n }\n\n /**\n * Stores an entry that never expires: no deadline, heap record, timer or\n * LRU eviction. It leaves only through `delete`, `sweep`, `clear`, or a\n * later `set()`.\n */\n public setWithoutTTL(key: K, value: V): this {\n if (this.#policy) this.#forget(key);\n super.set(key, value);\n return this;\n }\n\n /** Reads a value; restarts a TTL entry's window and promotes it. */\n public override get(key: K): V | undefined {\n const policy = this.#policy;\n const entry = policy?.entries.get(key);\n if (entry === undefined) {\n const value = mapGet.call(this, key) as V | undefined;\n if (value !== undefined || mapHas.call(this, key)) {\n this.#hits++;\n return value;\n }\n this.#misses++;\n return undefined;\n }\n const timed = entry.window !== 0;\n const now = timed ? Date.now() : 0;\n if (timed && entry.deadline <= now) {\n this.#expire(entry);\n this.#misses++;\n return undefined;\n }\n this.#hits++;\n if (timed && policy!.slide) entry.deadline = now + entry.window;\n if (entry.inLru) this.#promote(policy!, entry);\n return entry.value;\n }\n\n /**\n * Returns the value for `key`, or stores and returns what `factory`\n * makes. Reading counts as a `get()` (restarts the TTL, marks it recently\n * used); creating stores with `set()`, so `ttl` applies.\n * @param factory Called with the key and this collection only when the key is missing; if it throws, nothing is stored.\n * @param ttl TTL in ms for a created entry; defaults to the collection's.\n */\n public ensure(\n key: K,\n factory: (key: K, collection: this) => V,\n ttl?: number,\n ): V {\n const existing = this.get(key);\n if (existing !== undefined || super.has(key)) return existing as V;\n const created = factory(key, this);\n this.set(key, created, ttl);\n return created;\n }\n\n /** Reads a value without restarting its TTL or promoting it. */\n public peek(key: K): V | undefined {\n if (!this.#expireIfDue(key) && super.has(key)) {\n this.#hits++;\n return super.get(key);\n }\n this.#misses++;\n return undefined;\n }\n\n /** Cumulative hit, miss, expiry and eviction counters (a copy). */\n public get stats(): CollectionStats {\n return {\n hits: this.#hits,\n misses: this.#misses,\n expired: this.#policy?.expired ?? 0,\n evicted: this.#policy?.evicted ?? 0,\n };\n }\n\n public override has(key: K): boolean {\n return !this.#expireIfDue(key) && super.has(key);\n }\n\n public override delete(key: K): boolean {\n if (this.#expireIfDue(key)) return false;\n if (this.#policy) this.#forget(key);\n return super.delete(key);\n }\n\n public override clear(): void {\n super.clear();\n const policy = this.#policy;\n if (!policy) return;\n policy.entries.clear();\n policy.oldest = policy.newest = undefined;\n policy.lruSize = 0;\n policy.heap.length = 0;\n if (policy.timer) clearTimeout(policy.timer);\n policy.timer = undefined;\n policy.armedFor = Infinity;\n }\n\n public override get size(): number {\n this.purge();\n return super.size;\n }\n\n public override entries(): MapIterator<[K, V]> {\n this.purge();\n return super.entries();\n }\n\n public override keys(): MapIterator<K> {\n this.purge();\n return super.keys();\n }\n\n public override values(): MapIterator<V> {\n this.purge();\n return super.values();\n }\n\n public override [Symbol.iterator](): MapIterator<[K, V]> {\n return this.entries();\n }\n\n public override forEach(\n callback: (value: V, key: K, map: Map<K, V>) => void,\n thisArg?: unknown,\n ): void {\n this.purge();\n super.forEach(callback, thisArg);\n }\n\n /** Milliseconds until a key lapses, or undefined if absent or never expiring. */\n public ttlRemaining(key: K): number | undefined {\n if (this.#expireIfDue(key)) return undefined;\n const entry = this.#policy?.entries.get(key);\n return entry && entry.window !== 0\n ? Math.max(0, entry.deadline - Date.now())\n : undefined;\n }\n\n /** Drops every lapsed TTL entry now. @returns How many were dropped. */\n public purge(): number {\n if (!this.#policy || this.#policy.heap.length === 0) return 0;\n const now = Date.now();\n let removed = 0;\n const dropped: [K, V][] = [];\n while (this.#nextDeadline() <= now) {\n const due = this.#heapPop()!;\n dropped.push([due.key, super.get(due.key)!]);\n this.#remove(due.key);\n removed++;\n }\n this.#policy!.expired += removed;\n this.#rearm();\n for (const [key, value] of dropped) this.#notify(key, value, \"expired\");\n return removed;\n }\n\n /** Drops `key` if its TTL has lapsed. @returns Whether it did. */\n #expireIfDue(key: K): boolean {\n const entry = this.#policy?.entries.get(key);\n if (!entry || entry.window === 0 || entry.deadline > Date.now())\n return false;\n this.#expire(entry);\n return true;\n }\n\n #expire(entry: Entry<K, V>): void {\n const value = super.get(entry.key)!;\n this.#remove(entry.key);\n this.#policy!.expired++;\n this.#notify(entry.key, value, \"expired\");\n }\n\n #remove(key: K): void {\n this.#forget(key);\n super.delete(key);\n }\n\n /** Drops a key's policy entry (recency position and TTL); its heap record goes stale. */\n #forget(key: K): void {\n const policy = this.#policy!;\n const entry = policy.entries.get(key);\n if (!entry) return;\n if (entry.inLru) this.#unlink(policy, entry);\n policy.entries.delete(key);\n }\n\n /**\n * Brings the key's policy entry in line with a `set()`: marks it newest\n * when `maxSize` is set, and gives it a deadline when `window` is defined.\n * Only a new entry, or a deadline that moves earlier, gets a heap record;\n * a later one is a number write and the record re-files itself when it\n * surfaces.\n */\n #track(key: K, value: V, window: number | undefined, isNew: boolean): void {\n const policy = this.#policy!;\n const lru = policy.maxSize !== undefined;\n let entry = isNew ? undefined : policy.entries.get(key);\n if (entry) entry.value = value;\n if (window === undefined) {\n if (entry && entry.window !== 0) {\n // It had a TTL and now has none.\n if (lru) entry = this.#replace(policy, entry, 0, 0);\n else {\n this.#forget(key);\n return;\n }\n }\n if (!entry && lru) {\n entry = this.#create(key, value, 0, 0);\n policy.entries.set(key, entry);\n }\n if (entry) this.#promote(policy, entry);\n return;\n }\n const deadline = Date.now() + window;\n if (entry && entry.window !== 0) {\n entry.deadline = deadline;\n entry.window = window;\n if (deadline < entry.filed)\n // The heap cannot move a record up, and this one is in it: file a fresh one.\n entry = this.#replace(policy, entry, window, deadline);\n else {\n if (entry.inLru) this.#promote(policy, entry);\n return;\n }\n } else if (entry) {\n entry.window = window;\n entry.deadline = entry.filed = deadline;\n } else {\n entry = this.#create(key, value, window, deadline);\n policy.entries.set(key, entry);\n }\n if (lru) this.#promote(policy, entry);\n this.#heapPush(entry);\n if (policy.heap.length > 2 * policy.entries.size + 8) this.#compact();\n // A timer already armed for an earlier deadline stays correct.\n if (policy.timer === undefined || deadline < policy.armedFor)\n this.#rearm();\n }\n\n #create(key: K, value: V, window: number, deadline: number): Entry<K, V> {\n return {\n key,\n value,\n older: undefined,\n newer: undefined,\n inLru: false,\n window,\n deadline,\n filed: deadline,\n };\n }\n\n /** Swaps in a fresh record for `old` (which goes stale), keeping its recency position. */\n #replace(\n policy: Policy<K, V>,\n old: Entry<K, V>,\n window: number,\n deadline: number,\n ): Entry<K, V> {\n const entry: Entry<K, V> = {\n ...old,\n window,\n deadline,\n filed: deadline,\n };\n if (old.inLru) {\n if (old.older) old.older.newer = entry;\n else policy.oldest = entry;\n if (old.newer) old.newer.older = entry;\n else policy.newest = entry;\n }\n policy.entries.set(old.key, entry);\n return entry;\n }\n\n /** Makes an entry the newest in recency order, linking it first if needed. */\n #promote(policy: Policy<K, V>, entry: Entry<K, V>): void {\n if (entry === policy.newest) return;\n if (entry.inLru) this.#unlink(policy, entry, true);\n else {\n entry.inLru = true;\n policy.lruSize++;\n }\n entry.older = policy.newest;\n entry.newer = undefined;\n if (policy.newest) policy.newest.newer = entry;\n else policy.oldest = entry;\n policy.newest = entry;\n }\n\n /** Takes an entry out of the recency list; `keepCount` is for a move within it. */\n #unlink(policy: Policy<K, V>, entry: Entry<K, V>, keepCount = false): void {\n if (entry.older) entry.older.newer = entry.newer;\n else policy.oldest = entry.newer;\n if (entry.newer) entry.newer.older = entry.older;\n else policy.newest = entry.older;\n entry.older = entry.newer = undefined;\n if (!keepCount) {\n entry.inLru = false;\n policy.lruSize--;\n }\n }\n\n /**\n * An empty collection of the species this one derives, so `filter()` and\n * friends on a subclass return the subclass. It is built without\n * arguments and carries no `ttl` or `maxSize`.\n */\n #derived(): this {\n const Species =\n (\n this.constructor as {\n [Symbol.species]?: new () => Collection<K, V>;\n }\n )[Symbol.species] ?? Collection;\n return new Species() as this;\n }\n\n #notify(key: K, value: V, reason: EvictionReason): void {\n const onEvict = this.#policy?.onEvict;\n if (!onEvict) return;\n try {\n onEvict(key, value, reason);\n } catch {\n // A throwing callback must not leave the collection inconsistent.\n }\n }\n\n /** Evicts least-recently-used `set()` entries past `maxSize`; O(1) per eviction. */\n #enforceCap(): void {\n const policy = this.#policy!;\n const max = policy.maxSize;\n if (max === undefined) return;\n // Lapsed entries must not push live ones out.\n if (\n policy.lruSize > max &&\n policy.heap.length > 0 &&\n policy.heap[0]!.filed <= Date.now()\n )\n this.purge();\n while (policy.lruSize > max) {\n const oldest = policy.oldest!;\n const value = policy.onEvict ? super.get(oldest.key) : undefined;\n this.#unlink(policy, oldest);\n policy.entries.delete(oldest.key);\n super.delete(oldest.key);\n policy.evicted++;\n this.#notify(oldest.key, value as V, \"evicted\");\n }\n }\n\n #nextDeadline(): number {\n const policy = this.#policy!;\n for (;;) {\n const top = policy.heap[0];\n if (top === undefined) return Infinity;\n if (policy.entries.get(top.key) !== top) {\n this.#heapPop();\n continue;\n }\n if (top.deadline === top.filed) return top.filed;\n // Extended since it was filed: re-file for its current deadline.\n this.#heapPop();\n top.filed = top.deadline;\n this.#heapPush(top);\n }\n }\n\n #compact(): void {\n const policy = this.#policy!;\n const live = policy.heap.filter(\n (entry) => policy.entries.get(entry.key) === entry,\n );\n policy.heap.length = 0;\n for (const entry of live) this.#heapPush(entry);\n }\n\n #rearm(): void {\n const p = this.#policy!;\n const deadline = this.#nextDeadline();\n if (p.timer !== undefined && deadline >= p.armedFor) return;\n if (p.timer) clearTimeout(p.timer);\n p.timer = undefined;\n p.armedFor = deadline;\n if (deadline === Infinity) return;\n p.timer = setTimeout(\n () => {\n p.timer = undefined;\n p.armedFor = Infinity;\n this.purge();\n },\n Math.max(0, deadline - Date.now()),\n );\n // Pending expiry is housekeeping, not a reason to keep the process alive.\n (p.timer as { unref?: () => void }).unref?.();\n }\n\n #heapPush(entry: Entry<K, V>): void {\n const heap = this.#policy!.heap;\n let i = heap.length;\n heap.push(entry);\n while (i > 0) {\n const parent = (i - 1) >> 1;\n const above = heap[parent]!;\n if (above.filed <= entry.filed) break;\n heap[i] = above;\n i = parent;\n }\n heap[i] = entry;\n }\n\n #heapPop(): Entry<K, V> | undefined {\n const heap = this.#policy!.heap;\n const top = heap[0];\n const last = heap.pop();\n if (top === undefined || heap.length === 0) return top;\n let i = 0;\n for (;;) {\n let child = 2 * i + 1;\n if (child >= heap.length) break;\n if (\n child + 1 < heap.length &&\n heap[child + 1]!.filed < heap[child]!.filed\n )\n child++;\n if (heap[child]!.filed >= last!.filed) break;\n heap[i] = heap[child]!;\n i = child;\n }\n heap[i] = last!;\n return top;\n }\n\n /** Returns the first stored value. */\n public first(): V | undefined {\n for (const value of this.values()) return value;\n return undefined;\n }\n /** Returns the first stored key. */\n public firstKey(): K | undefined {\n for (const key of this.keys()) return key;\n return undefined;\n }\n /** Returns the last stored value. */\n public last(): V | undefined {\n let value: V | undefined;\n for (const item of this.values()) value = item;\n return value;\n }\n /** Returns the last stored key. */\n public lastKey(): K | undefined {\n let key: K | undefined;\n for (const item of this.keys()) key = item;\n return key;\n }\n /** Finds the first value matching a predicate. */\n public find(\n predicate: (value: V, key: K, collection: this) => boolean,\n ): V | undefined {\n for (const [key, value] of this) {\n if (predicate(value, key, this)) return value;\n }\n return undefined;\n }\n /** Finds the last value (in insertion order) matching a predicate. */\n public findLast(\n predicate: (value: V, key: K, collection: this) => boolean,\n ): V | undefined {\n const keys = this.keyArray();\n const values = this.array();\n for (let i = values.length - 1; i >= 0; i--)\n if (predicate(values[i]!, keys[i]!, this)) return values[i];\n return undefined;\n }\n /** Finds the key of the last entry (in insertion order) matching a predicate. */\n public findLastKey(\n predicate: (value: V, key: K, collection: this) => boolean,\n ): K | undefined {\n const keys = this.keyArray();\n const values = this.array();\n for (let i = values.length - 1; i >= 0; i--)\n if (predicate(values[i]!, keys[i]!, this)) return keys[i];\n return undefined;\n }\n /** Returns all values matching a predicate. */\n public filter(\n predicate: (value: V, key: K, collection: this) => boolean,\n ): this {\n const result = this.#derived();\n // forEach walks the entries without allocating a [key, value] pair each.\n this.forEach((value, key) => {\n if (predicate(value, key, this)) result.set(key, value);\n });\n return result;\n }\n /** Transforms every stored value into an array. */\n public map<T>(transform: (value: V, key: K, collection: this) => T): T[] {\n const result: T[] = [];\n this.forEach((value, key) => {\n result.push(transform(value, key, this));\n });\n return result;\n }\n /** Returns whether at least one stored value satisfies a predicate. */\n public some(\n predicate: (value: V, key: K, collection: this) => boolean,\n ): boolean {\n for (const [key, value] of this) {\n if (predicate(value, key, this)) return true;\n }\n return false;\n }\n /** Returns whether every stored value satisfies a predicate. */\n public every(\n predicate: (value: V, key: K, collection: this) => boolean,\n ): boolean {\n for (const [key, value] of this) {\n if (!predicate(value, key, this)) return false;\n }\n return true;\n }\n /** Runs a callback for each stored value. */\n public each(\n callback: (value: V, key: K, collection: this) => unknown,\n ): this {\n this.forEach((value, key) => {\n callback(value, key, this);\n });\n return this;\n }\n /** Returns an array containing all stored values. */\n public array(): V[] {\n return [...this.values()];\n }\n /** Returns an array containing all stored keys. */\n public keyArray(): K[] {\n return [...this.keys()];\n }\n /** Returns a plain array of entries. */\n public entriesArray(): [K, V][] {\n return [...this.entries()];\n }\n /** Returns a new collection with the same entries. */\n public clone(): this {\n const copy = this.#derived();\n this.forEach((value, key) => {\n copy.set(key, value);\n });\n return copy;\n }\n /** Returns whether all supplied keys are present. */\n public hasAll(...keys: K[]): boolean {\n for (let i = 0; i < keys.length; i++) {\n if (!this.has(keys[i]!)) return false;\n }\n return true;\n }\n /** Returns whether at least one supplied key is present. */\n public hasAny(...keys: K[]): boolean {\n for (let i = 0; i < keys.length; i++) {\n if (this.has(keys[i]!)) return true;\n }\n return false;\n }\n /** Returns the first key whose value matches a predicate. */\n public findKey(\n predicate: (value: V, key: K, collection: this) => boolean,\n ): K | undefined {\n for (const [key, value] of this) {\n if (predicate(value, key, this)) return key;\n }\n return undefined;\n }\n /** Returns whether a predicate matches at least one entry. */\n public someEntry(\n predicate: (value: V, key: K, collection: this) => boolean,\n ): boolean {\n return this.some(predicate);\n }\n /** Removes every entry matching a predicate and returns the number removed. */\n public sweep(\n predicate: (value: V, key: K, collection: this) => boolean,\n ): number {\n let removed = 0;\n for (const [key, value] of this) {\n if (predicate(value, key, this) && this.delete(key)) removed++;\n }\n return removed;\n }\n /** Returns the collection's first matching entry as a tuple. */\n public firstEntry(): [K, V] | undefined {\n for (const [key, value] of this) return [key, value];\n return undefined;\n }\n /** Returns the collection's last matching entry as a tuple. */\n public lastEntry(): [K, V] | undefined {\n let entry: [K, V] | undefined;\n for (const item of this) entry = [item[0], item[1]];\n return entry;\n }\n /** Returns a new Collection containing elements from both collections. */\n public union(other: ReadonlyCollection<K, V>): this {\n const result = this.clone();\n for (const [key, value] of other) result.set(key, value);\n return result;\n }\n /** Returns a new Collection containing only elements present in both collections. */\n public intersection(other: ReadonlyCollection<K, V>): this {\n const result = this.#derived();\n for (const [key, value] of this) {\n if (other.has(key)) result.set(key, value);\n }\n return result;\n }\n /** Returns a new Collection containing elements present in this collection but not the other. */\n public difference(other: ReadonlyCollection<K, V>): this {\n const result = this.#derived();\n for (const [key, value] of this) {\n if (!other.has(key)) result.set(key, value);\n }\n return result;\n }\n /** Splits the collection into two collections based on a predicate.\n * @returns `[passing, failing]` — entries satisfying the predicate, then those that don't.\n */\n public partition(\n predicate: (value: V, key: K, collection: this) => boolean,\n ): [this, this] {\n const pass = this.#derived();\n const fail = this.#derived();\n for (const [key, value] of this) {\n if (predicate(value, key, this)) pass.set(key, value);\n else fail.set(key, value);\n }\n return [pass, fail];\n }\n /** Returns the entries of both collections that are in only one of them. */\n public symmetricDifference(other: ReadonlyCollection<K, V>): this {\n const result = this.#derived();\n for (const [key, value] of this)\n if (!other.has(key)) result.set(key, value);\n for (const [key, value] of other)\n if (!this.has(key)) result.set(key, value);\n return result;\n }\n /** Returns a new Collection with this one's entries followed by each of `collections`'; a later collection wins a shared key. */\n public concat(...collections: ReadonlyCollection<K, V>[]): this {\n const result = this.clone();\n for (const collection of collections)\n for (const [key, value] of collection) result.set(key, value);\n return result;\n }\n /**\n * Combines this collection with `other`, deciding per key what to keep.\n * @param whenInSelf Called for a key only in this collection.\n * @param whenInOther Called for a key only in `other`.\n * @param whenInBoth Called for a key in both.\n * @returns A new collection of the entries the callbacks kept, in this collection's order, then `other`'s new keys.\n */\n public merge<T, R>(\n other: ReadonlyCollection<K, T>,\n whenInSelf: (value: V, key: K) => Keep<R>,\n whenInOther: (valueOther: T, key: K) => Keep<R>,\n whenInBoth: (value: V, valueOther: T, key: K) => Keep<R>,\n ): Collection<K, R> {\n const result = this.#derived() as unknown as Collection<K, R>;\n const decide = (key: K, kept: Keep<R>): void => {\n if (kept.keep) result.set(key, kept.value);\n };\n for (const [key, value] of this) {\n decide(\n key,\n other.has(key)\n ? whenInBoth(value, peekOf(other, key) as T, key)\n : whenInSelf(value, key),\n );\n }\n for (const [key, value] of other)\n if (!this.has(key)) decide(key, whenInOther(value, key));\n return result;\n }\n /** Returns whether `other` holds the same keys with `===` equal values. Neither side's TTL or recency is touched. */\n public equals(other: ReadonlyCollection<K, V> | null | undefined): boolean {\n if (!other) return false;\n if (other === (this as unknown)) return true;\n if (this.size !== other.size) return false;\n for (const [key, value] of this) {\n if (!other.has(key)) return false;\n if (value !== peekOf(other, key)) return false;\n }\n return true;\n }\n /** Returns a new collection with the same keys and each value passed through `transform`. */\n public mapValues<T>(\n transform: (value: V, key: K, collection: this) => T,\n ): Collection<K, T> {\n const result = this.#derived() as unknown as Collection<K, T>;\n for (const [key, value] of this)\n result.set(key, transform(value, key, this));\n return result;\n }\n /** Returns a new collection with the entries in reverse order. */\n public toReversed(): this {\n const result = this.#derived();\n const entries = [...this];\n for (let i = entries.length - 1; i >= 0; i--)\n result.set(entries[i]![0], entries[i]![1]);\n return result;\n }\n /** Same as {@link sorted}, under the name the standard `Array` uses. */\n public toSorted(\n comparator?: (a: V, b: V, aKey: K, bKey: K) => number,\n ): this {\n return this.sorted(comparator);\n }\n /**\n * Groups `items` by the key `keySelector` returns for each.\n * @param keySelector Called with each item and its index.\n * @returns A new collection from each key to its items, in input order.\n */\n public static override groupBy<K, V>(\n items: Iterable<V>,\n keySelector: (item: V, index: number) => K,\n ): Collection<K, V[]> {\n const groups = new Collection<K, V[]>();\n let index = 0;\n for (const item of items)\n groups.ensure(keySelector(item, index++), () => []).push(item);\n return groups;\n }\n /**\n * Builds a collection from `entries`, merging values that share a key.\n * @param combine Called with the value stored so far, the new one and the key; its result is stored.\n */\n public static combineEntries<K, V>(\n entries: Iterable<readonly [K, V]>,\n combine: (firstValue: V, secondValue: V, key: K) => V,\n ): Collection<K, V> {\n const result = new Collection<K, V>();\n for (const [key, value] of entries)\n result.set(\n key,\n result.has(key) ? combine(result.get(key)!, value, key) : value,\n );\n return result;\n }\n /** Calls `fn` with this collection and returns the collection unchanged.\n * Useful for inserting debug side-effects in a chain without breaking the flow.\n */\n public tap(fn: (collection: this) => unknown): this {\n fn(this);\n return this;\n }\n /** Maps every entry to an array of items and flattens the results. */\n public flatMap<T>(\n transform: (value: V, key: K, collection: this) => T[],\n ): T[] {\n const result: T[] = [];\n for (const [key, value] of this) {\n for (const item of transform(value, key, this)) result.push(item);\n }\n return result;\n }\n /** Reduces the collection to a single value. */\n public reduce<T>(\n fn: (accumulator: T, value: V, key: K, collection: this) => T,\n initialValue: T,\n ): T {\n let acc = initialValue;\n for (const [key, value] of this) acc = fn(acc, value, key, this);\n return acc;\n }\n /** Like {@link reduce}, but from the last entry to the first. */\n public reduceRight<T>(\n fn: (accumulator: T, value: V, key: K, collection: this) => T,\n initialValue: T,\n ): T {\n const entries = [...this];\n let acc = initialValue;\n for (let i = entries.length - 1; i >= 0; i--)\n acc = fn(acc, entries[i]![1], entries[i]![0], this);\n return acc;\n }\n /** Returns a new Collection with entries sorted by comparator (non-mutating).\n * Defaults to insertion order if no comparator is provided.\n */\n public sorted(comparator?: (a: V, b: V, aKey: K, bKey: K) => number): this {\n // Decorate with the original insertion index and use it as a tiebreaker so\n // equal elements keep their insertion order (a stable sort independent of\n // the engine's Array.prototype.sort stability guarantees).\n const decorated = [...this.entries()].map((entry, index) => ({\n entry,\n index,\n }));\n if (comparator)\n decorated.sort((x, y) => {\n const comparison = comparator(\n x.entry[1],\n y.entry[1],\n x.entry[0],\n y.entry[0],\n );\n return comparison !== 0 ? comparison : x.index - y.index;\n });\n const result = this.#derived();\n for (const { entry } of decorated) result.set(entry[0], entry[1]);\n return result;\n }\n /**\n * Returns a random value, or `undefined` if empty. With `amount`, returns\n * that many different values (all of them, shuffled, when `amount` is at\n * least the size).\n * Uses `Math.random()` (fast, non-cryptographic): do not use it for\n * security-sensitive selection such as tokens or secrets.\n * @param amount How many values to pick.\n * @throws {RangeError} If `amount` is not a non-negative integer.\n */\n public random(): V | undefined;\n public random(amount: number): V[];\n public random(amount?: number): V | V[] | undefined {\n if (amount !== undefined) return sample([...this.values()], amount);\n const size = this.size;\n if (size === 0) return undefined;\n let index = Math.floor(Math.random() * size);\n for (const value of this.values()) if (index-- === 0) return value;\n return undefined;\n }\n /**\n * Returns a random key, or `undefined` if empty. With `amount`, returns\n * that many different keys. Same randomness and errors as {@link random}.\n * @param amount How many keys to pick.\n */\n public randomKey(): K | undefined;\n public randomKey(amount: number): K[];\n public randomKey(amount?: number): K | K[] | undefined {\n if (amount !== undefined) return sample([...this.keys()], amount);\n const size = this.size;\n if (size === 0) return undefined;\n let index = Math.floor(Math.random() * size);\n for (const key of this.keys()) if (index-- === 0) return key;\n return undefined;\n }\n /** Returns the value at a given insertion-order index (supports negative indices). */\n public at(index: number): V | undefined {\n let remaining = index < 0 ? this.size + index : index;\n if (remaining < 0) return undefined;\n for (const value of this.values()) if (remaining-- === 0) return value;\n return undefined;\n }\n /** Returns the key at a given insertion-order index (supports negative indices). */\n public keyAt(index: number): K | undefined {\n let remaining = index < 0 ? this.size + index : index;\n if (remaining < 0) return undefined;\n for (const key of this.keys()) if (remaining-- === 0) return key;\n return undefined;\n }\n /** Serializes the collection to a plain `[key, value]` array. */\n public toJSON(): [K, V][] {\n return [...this.entries()];\n }\n}\n\nexport { Cache } from \"./cache.js\";\nexport type { CacheOptions } from \"./cache.js\";\n"
6
+ "import type { CollectionStats, EvictionReason } from \"./index.js\";\n\n/** Anything that runs one Redis command: `Bun.RedisClient` as it is, or an adapter. */\nexport interface RedisCommandClient {\n send(command: string, args: string[]): Promise<unknown>;\n}\n\n/** Turns values into strings for Redis and back. */\nexport interface RedisSerializer<V> {\n serialize(value: V): string;\n deserialize(raw: string): V;\n}\n\n/** Options for {@link RedisCollection}. */\nexport interface RedisCollectionOptions<V> {\n /** The Redis client. `Bun.RedisClient` works as it is; for ioredis pass `{ send: (c, a) => redis.call(c, ...a) }`. */\n client: RedisCommandClient;\n /** The collection's name: every process using the same name and prefix shares it. */\n name: string;\n /** Key prefix. Default `\"lunibee:collection:\"`; keys are versioned under it (`…v1:…`). */\n prefix?: string;\n /** Default TTL in ms for `set()`. Omit for no expiry. */\n ttl?: number;\n /** Whether a `get()` restarts a TTL entry's window. Default `true`. */\n slide?: boolean;\n /** Most entries; the least recently used (across every process) are evicted past it. */\n maxSize?: number;\n /** Default JSON. Provide one for values JSON cannot carry (bigint, Map, Date…). */\n serializer?: RedisSerializer<V>;\n /** Called when an operation of this instance removes entries automatically. Exceptions are swallowed. */\n onEvict?: (\n key: string,\n value: V | undefined,\n reason: EvictionReason,\n ) => void;\n}\n\n/**\n * Shared Lua helpers. Entries are `<ep><key>` strings holding `<ttl>:<payload>`;\n * `exp` is a sorted set of expiry times, `lru` one of access order (from an\n * `INCR` clock, so two writes in one millisecond still order). Every script\n * reads the time from Redis, so processes with skewed clocks agree.\n */\nconst PRELUDE = `\nlocal exp, lru, clock, ep = KEYS[1], KEYS[2], KEYS[3], ARGV[1]\nlocal t = redis.call('TIME')\nlocal now = tonumber(t[1]) * 1000 + math.floor(tonumber(t[2]) / 1000)\nlocal out = {}\nlocal function drop(m, reason)\n local v = redis.call('GET', ep .. m)\n redis.call('DEL', ep .. m)\n redis.call('ZREM', exp, m)\n redis.call('ZREM', lru, m)\n if reason then\n table.insert(out, m)\n table.insert(out, v or false)\n table.insert(out, reason)\n end\nend\nlocal gone = redis.call('ZRANGEBYSCORE', exp, '-inf', now, 'LIMIT', 0, 1000)\nfor _, m in ipairs(gone) do drop(m, 'expired') end\nlocal function touch(m) redis.call('ZADD', lru, redis.call('INCR', clock), m) end\n`;\n\n/** `ARGV`: ep, key, payload, ttl (0 none), maxSize (0 none), mode (`set` | `nx`). Returns `{existing|false, ...evictions}`. */\nexport const SET_SCRIPT = `${PRELUDE}\nlocal m, payload, ttl, max, mode = ARGV[2], ARGV[3], tonumber(ARGV[4]), tonumber(ARGV[5]), ARGV[6]\nif mode == 'nx' then\n local cur = redis.call('GET', ep .. m)\n if cur then\n touch(m)\n table.insert(out, 1, cur)\n return out\n end\nend\nlocal env = ttl .. ':' .. payload\nif ttl > 0 then\n -- The key outlives its logical expiry by a grace second, so the prune\n -- that reports the expiry can still hand the value to onEvict.\n redis.call('SET', ep .. m, env, 'PX', ttl + 1000)\n redis.call('ZADD', exp, now + ttl, m)\nelse\n redis.call('SET', ep .. m, env)\n redis.call('ZREM', exp, m)\nend\ntouch(m)\nif max > 0 then\n local n = redis.call('ZCARD', lru)\n while n > max do\n local popped = redis.call('ZPOPMIN', lru)\n local victim = popped[1]\n if victim == nil then break end\n if victim ~= m then drop(victim, 'evicted') end\n n = n - 1\n end\nend\ntable.insert(out, 1, false)\nreturn out\n`;\n\n/** `ARGV`: ep, key, slide (1/0), touch (1/0). Returns `{envelope|false, ...evictions}`. */\nexport const GET_SCRIPT = `${PRELUDE}\nlocal m, slide, mark = ARGV[2], ARGV[3], ARGV[4]\nlocal env = redis.call('GET', ep .. m)\nif not env then\n redis.call('ZREM', exp, m)\n redis.call('ZREM', lru, m)\n table.insert(out, 1, false)\n return out\nend\nif mark == '1' then touch(m) end\nif slide == '1' then\n local ttl = tonumber(string.match(env, '^(%d+):'))\n if ttl and ttl > 0 then\n redis.call('PEXPIRE', ep .. m, ttl + 1000)\n redis.call('ZADD', exp, now + ttl, m)\n end\nend\ntable.insert(out, 1, env)\nreturn out\n`;\n\n/** `ARGV`: ep, key. Returns `{1|0, ...evictions}`. */\nexport const DELETE_SCRIPT = `${PRELUDE}\nlocal m = ARGV[2]\nlocal existed = redis.call('EXISTS', ep .. m)\ndrop(m, nil)\ntable.insert(out, 1, existed)\nreturn out\n`;\n\n/** `ARGV`: ep, what (`size` | `keys` | `clear`). */\nexport const LIST_SCRIPT = `${PRELUDE}\nlocal what = ARGV[2]\nif what == 'clear' then\n local n = 0\n repeat\n local batch = redis.call('ZRANGE', lru, 0, 999)\n for _, m in ipairs(batch) do drop(m, nil) end\n n = n + #batch\n until #batch == 0\n redis.call('DEL', exp, lru, clock)\n return {n}\nend\nlocal result = what == 'size' and redis.call('ZCARD', lru) or redis.call('ZRANGE', lru, 0, -1)\nreturn {result, unpack(out)}\n`;\n\n/** How long an entry's key outlives its logical expiry, for `onEvict` (ms). */\nconst EXPIRY_GRACE_MS = 1000;\n\nconst JSON_SERIALIZER: RedisSerializer<never> = {\n serialize: (value) => JSON.stringify(value),\n deserialize: (raw) => JSON.parse(raw) as never,\n};\n\n/**\n * A key-value collection kept in Redis and shared by every process that opens\n * it with the same `name`, with the retention policy of `Collection`: a TTL\n * (sliding by default), a `maxSize` evicting the least recently used across\n * every process, and `onEvict`.\n *\n * Every operation is one atomic script, so two processes never see a\n * half-applied write. The API is async, and values travel as strings\n * (JSON by default).\n *\n * ```ts\n * const sessions = new RedisCollection<Session>({\n * client: new Bun.RedisClient(process.env.REDIS_URL),\n * name: \"sessions\",\n * ttl: 15 * 60_000,\n * maxSize: 10_000,\n * });\n * await sessions.set(userId, session);\n * const session = await sessions.get(userId); // from any process\n * ```\n */\nexport class RedisCollection<V = unknown> {\n readonly #redis: RedisCommandClient;\n readonly #keys: [string, string, string];\n readonly #ep: string;\n readonly #ttl: number;\n readonly #slide: boolean;\n readonly #maxSize: number;\n readonly #serializer: RedisSerializer<V>;\n readonly #onEvict?: RedisCollectionOptions<V>[\"onEvict\"];\n readonly #stats: CollectionStats = {\n hits: 0,\n misses: 0,\n expired: 0,\n evicted: 0,\n };\n /** The collection's name. */\n public readonly name: string;\n\n public constructor(options: RedisCollectionOptions<V>) {\n if (\n typeof options.name !== \"string\" ||\n !/^[\\w.:-]{1,100}$/.test(options.name)\n )\n throw new TypeError(\n \"name must be 1-100 letters, digits, '_', '.', ':' or '-'.\",\n );\n checkTTL(options.ttl);\n if (\n options.maxSize !== undefined &&\n !(Number.isInteger(options.maxSize) && options.maxSize > 0)\n )\n throw new RangeError(\"maxSize must be a positive integer.\");\n this.#redis = options.client;\n this.name = options.name;\n // A hash tag keeps one collection's keys in one Redis Cluster slot.\n const base = `${options.prefix ?? \"lunibee:collection:\"}v1:{${options.name}}:`;\n this.#keys = [`${base}exp`, `${base}lru`, `${base}clock`];\n this.#ep = `${base}e:`;\n this.#ttl = options.ttl ?? 0;\n this.#slide = options.slide ?? true;\n this.#maxSize = options.maxSize ?? 0;\n this.#serializer =\n options.serializer ?? (JSON_SERIALIZER as RedisSerializer<V>);\n this.#onEvict = options.onEvict;\n }\n\n /** Hits, misses and removals seen by this instance. */\n public get stats(): CollectionStats {\n return { ...this.#stats };\n }\n\n async #run(script: string, ...argv: string[]): Promise<unknown[]> {\n const reply = (await this.#redis.send(\"EVAL\", [\n script,\n \"3\",\n ...this.#keys,\n this.#ep,\n ...argv,\n ])) as unknown[];\n if (!Array.isArray(reply))\n throw new Error(\"Unexpected reply from a RedisCollection script.\");\n return reply;\n }\n\n /** Reports what a script removed, then returns its first value. */\n #settle(reply: unknown[], skip: number): unknown {\n for (let i = skip; i + 2 < reply.length + 0; i += 3) {\n const key = String(reply[i]);\n const raw = reply[i + 1];\n const reason = reply[i + 2] as EvictionReason;\n if (reason === \"expired\") this.#stats.expired++;\n else this.#stats.evicted++;\n if (!this.#onEvict) continue;\n let value: V | undefined;\n try {\n value = typeof raw === \"string\" ? this.#decode(raw) : undefined;\n } catch {\n value = undefined;\n }\n try {\n this.#onEvict(key, value, reason);\n } catch {\n // A listener never breaks the collection.\n }\n }\n return reply[0];\n }\n\n #decode(envelope: string): V {\n const colon = envelope.indexOf(\":\");\n return this.#serializer.deserialize(envelope.slice(colon + 1));\n }\n\n /**\n * The value for `key`, or `undefined`. Marks it recently used and, with\n * `slide`, restarts its TTL window.\n */\n public async get(key: string | number): Promise<V | undefined> {\n const raw = this.#settle(\n await this.#run(\n GET_SCRIPT,\n String(key),\n this.#slide ? \"1\" : \"0\",\n \"1\",\n ),\n 1,\n );\n if (typeof raw !== \"string\") {\n this.#stats.misses++;\n return undefined;\n }\n this.#stats.hits++;\n return this.#decode(raw);\n }\n\n /** The value without marking it used or restarting its window. */\n public async peek(key: string | number): Promise<V | undefined> {\n const raw = this.#settle(\n await this.#run(GET_SCRIPT, String(key), \"0\", \"0\"),\n 1,\n );\n return typeof raw === \"string\" ? this.#decode(raw) : undefined;\n }\n\n /** Whether `key` is present (does not count as a use). */\n public async has(key: string | number): Promise<boolean> {\n return (await this.peek(key)) !== undefined;\n }\n\n /** Stores `value` with the default TTL, or `ttl` ms (`0`: never expires). */\n public async set(\n key: string | number,\n value: V,\n ttl?: number,\n ): Promise<this> {\n checkTTL(ttl, true);\n this.#settle(\n await this.#run(\n SET_SCRIPT,\n String(key),\n this.#serializer.serialize(value),\n String(Math.ceil(ttl ?? this.#ttl)),\n String(this.#maxSize),\n \"set\",\n ),\n 1,\n );\n return this;\n }\n\n /** Stores `value` with no expiry. It still counts towards `maxSize`. */\n public setWithoutTTL(key: string | number, value: V): Promise<this> {\n return this.set(key, value, 0);\n }\n\n /**\n * Returns the value for `key`, or stores and returns what `factory`\n * gives. If two processes race, one value wins and both get it.\n */\n public async ensure(\n key: string | number,\n factory: (key: string) => V | Promise<V>,\n ttl?: number,\n ): Promise<V> {\n const existing = await this.get(key);\n if (existing !== undefined) return existing;\n checkTTL(ttl, true);\n const value = await factory(String(key));\n const raw = this.#settle(\n await this.#run(\n SET_SCRIPT,\n String(key),\n this.#serializer.serialize(value),\n String(Math.ceil(ttl ?? this.#ttl)),\n String(this.#maxSize),\n \"nx\",\n ),\n 1,\n );\n return typeof raw === \"string\" ? this.#decode(raw) : value;\n }\n\n /** Removes `key`. Returns whether it was present. */\n public async delete(key: string | number): Promise<boolean> {\n const reply = await this.#run(DELETE_SCRIPT, String(key));\n return Number(this.#settle(reply, 1)) === 1;\n }\n\n /** Removes every entry. Returns how many there were. */\n public async clear(): Promise<number> {\n const reply = await this.#run(LIST_SCRIPT, \"clear\");\n return Number(reply[0]);\n }\n\n /** Live entries. */\n public async size(): Promise<number> {\n return Number(this.#settle(await this.#run(LIST_SCRIPT, \"size\"), 1));\n }\n\n /** Live keys, least recently used first. */\n public async keys(): Promise<string[]> {\n return (\n this.#settle(await this.#run(LIST_SCRIPT, \"keys\"), 1) as string[]\n ).map(String);\n }\n\n /** Live entries, least recently used first. Reading them does not count as a use. */\n public async entries(): Promise<Array<[string, V]>> {\n const keys = await this.keys();\n if (keys.length === 0) return [];\n const out: Array<[string, V]> = [];\n for (let i = 0; i < keys.length; i += 1000) {\n const batch = keys.slice(i, i + 1000);\n const raws = (await this.#redis.send(\n \"MGET\",\n batch.map((k) => this.#ep + k),\n )) as Array<string | null>;\n raws.forEach((raw, j) => {\n if (typeof raw === \"string\")\n out.push([batch[j]!, this.#decode(raw)]);\n });\n }\n return out;\n }\n\n /** Live values, least recently used first. */\n public async values(): Promise<V[]> {\n return (await this.entries()).map(([, value]) => value);\n }\n\n /** Milliseconds left before `key` expires; `undefined` when it never expires or is absent. */\n public async ttlRemaining(\n key: string | number,\n ): Promise<number | undefined> {\n const ms = Number(\n await this.#redis.send(\"PTTL\", [this.#ep + String(key)]),\n );\n // Less the grace second the key outlives its expiry by.\n return ms >= 0 ? Math.max(0, ms - EXPIRY_GRACE_MS) : undefined;\n }\n}\n\nfunction checkTTL(ttl: number | undefined, allowZero = false): void {\n if (ttl === undefined) return;\n if (!Number.isFinite(ttl) || ttl < 0 || (!allowZero && ttl === 0))\n throw new RangeError(\n allowZero\n ? \"ttl must be 0 or a positive number.\"\n : \"ttl must be a positive number.\",\n );\n}\n",
7
+ "/** Retention policy for a {@link Collection}. */\nexport interface CollectionOptions<K = unknown, V = unknown> {\n /** Default sliding TTL in ms for `set()`. Omit for no expiry. */\n ttl?: number;\n /** Fraction (0-1) of each entry's TTL randomly shaved off when it is set, so entries stored together do not expire together. Default `0`. */\n jitter?: number;\n /** Maximum entries stored with `set()`; least-recently-used are evicted past it. `setWithoutTTL()` entries are never counted or evicted. */\n maxSize?: number;\n /** Whether a read restarts a TTL entry's window. Default `true`; with `false` an entry lapses a fixed time after it was set, and reads only mark it recently used. */\n slide?: boolean;\n /** Called after an entry is removed automatically, with why. Exceptions are swallowed. */\n onEvict?: (key: K, value: V, reason: EvictionReason) => void;\n}\n\n/** Why an entry was removed automatically. */\nexport type EvictionReason = \"expired\" | \"evicted\";\n\n/** Cumulative counters from {@link Collection.stats}. */\nexport interface CollectionStats {\n /** `get`/`peek` calls that found a value. */\n hits: number;\n /** `get`/`peek` calls that found nothing. */\n misses: number;\n /** Entries removed because their TTL lapsed. */\n expired: number;\n /** Entries removed to stay within `maxSize`. */\n evicted: number;\n}\n\n/**\n * Everything the policy knows about one key: its place in the recency list\n * and its TTL. One record serves the policy map, the recency list and the\n * expiry heap, so a write touches one extra hash entry and allocates once.\n */\ntype Entry<K, V> = {\n key: K;\n /** A copy of the stored value, so a read needs one lookup instead of two. */\n value: V;\n /** Neighbours in recency order; meaningful while `inLru`. */\n older: Entry<K, V> | undefined;\n newer: Entry<K, V> | undefined;\n inLru: boolean;\n /** TTL window in ms; 0 when the entry does not expire (and is not in the heap). */\n window: number;\n /** The current deadline; a read moves it later without touching the heap. */\n deadline: number;\n /** The deadline the heap ordered this record by. */\n filed: number;\n};\n\n/**\n * Everything a retention policy needs. A Collection without `ttl` or\n * `maxSize` never creates one, so plain collections cost no more than a Map.\n */\ntype Policy<K, V> = {\n /** Keys with a TTL or a recency position; `setWithoutTTL()` keys are absent. */\n entries: Map<K, Entry<K, V>>;\n /** Oldest and newest entries of the recency list; only `maxSize` collections use it. */\n oldest: Entry<K, V> | undefined;\n newest: Entry<K, V> | undefined;\n lruSize: number;\n /** Min-heap by `filed`. A record that is no longer its key's map value is stale and dropped lazily. */\n heap: Entry<K, V>[];\n timer?: ReturnType<typeof setTimeout>;\n armedFor: number;\n /** The options, kept here so a plain collection carries none of them. */\n ttl: number | undefined;\n jitter: number;\n maxSize: number | undefined;\n slide: boolean;\n /** Stored loosely typed so the callback does not make Collection invariant in K and V. */\n onEvict:\n | ((key: unknown, value: unknown, reason: EvictionReason) => void)\n | undefined;\n expired: number;\n evicted: number;\n};\n\nfunction newPolicy<K, V>(options: CollectionOptions<K, V> = {}): Policy<K, V> {\n return {\n ttl: options.ttl,\n jitter: options.jitter ?? 0,\n maxSize: options.maxSize,\n slide: options.slide ?? true,\n onEvict: options.onEvict as Policy<K, V>[\"onEvict\"],\n expired: 0,\n evicted: 0,\n entries: new Map(),\n oldest: undefined,\n newest: undefined,\n lruSize: 0,\n heap: [],\n armedFor: Infinity,\n };\n}\n\n/**\n * Reads a value that `has()` just confirmed, without touching a Lunibee\n * collection's TTL, recency or hit counters.\n */\nfunction peekOf<K, V>(\n collection: ReadonlyCollection<K, V>,\n key: K,\n): V | undefined {\n return collection instanceof Map\n ? (Map.prototype.get.call(collection, key) as V | undefined)\n : collection.get(key);\n}\n\n/** What `merge()` does with one entry: keep it with `value`, or drop it. */\nexport type Keep<V> = { keep: true; value: V } | { keep: false };\n\n/**\n * A `Collection` seen read-only: every method that does not change it. Pass it\n * where you only read, so a function cannot add to or remove from the cache.\n */\nexport type ReadonlyCollection<K, V> = Omit<\n Collection<K, V>,\n | \"set\"\n | \"setWithoutTTL\"\n | \"delete\"\n | \"clear\"\n | \"ensure\"\n | \"forEach\"\n | \"get\"\n | \"sweep\"\n | \"purge\"\n> &\n ReadonlyMap<K, V>;\n\nconst mapGet = Map.prototype.get as (\n this: Map<unknown, unknown>,\n key: unknown,\n) => unknown;\nconst mapHas = Map.prototype.has as (\n this: Map<unknown, unknown>,\n key: unknown,\n) => boolean;\n\n/** Picks `amount` different items at random (a partial Fisher-Yates shuffle of `items`). */\nfunction sample<T>(items: T[], amount: number): T[] {\n if (!Number.isInteger(amount) || amount < 0)\n throw new RangeError(\"amount must be a non-negative integer.\");\n const count = Math.min(amount, items.length);\n for (let i = 0; i < count; i++) {\n const j = i + Math.floor(Math.random() * (items.length - i));\n [items[i], items[j]] = [items[j]!, items[i]!];\n }\n items.length = count;\n return items;\n}\n\nfunction assertTTL(ttl: number | undefined): void {\n if (ttl !== undefined && (!Number.isFinite(ttl) || ttl <= 0))\n throw new RangeError(\"TTL must be a positive number, or omitted.\");\n}\n\n/**\n * A keyed collection for Lunibee resource and application state.\n *\n * - `set(key, value, ttl?)` is TTL/LRU-aware: with a TTL (the default from\n * options, or per call) the entry expires after that window of inactivity,\n * and with `maxSize` it counts toward the cap.\n * - `setWithoutTTL(key, value)` never expires: no deadline, no heap record,\n * no timer, and exempt from `maxSize` eviction. Resource managers store\n * Discord state this way, so it leaves only through an explicit delete.\n *\n * Without options, a Collection behaves like a plain Map.\n */\nexport class Collection<K, V> extends Map<K, V> {\n /** Created with any option, or by the first `set()` with its own TTL. */\n #policy?: Policy<K, V>;\n #hits = 0;\n #misses = 0;\n\n /**\n * @param entries Initial entries, stored with `set()`.\n * @param options TTL and size policy.\n * @throws {RangeError} On a non-positive TTL or non-integer `maxSize`.\n */\n public constructor(\n entries?: Iterable<readonly [K, V]> | null,\n options: CollectionOptions<K, V> = {},\n ) {\n super();\n assertTTL(options.ttl);\n if (\n options.jitter !== undefined &&\n !(options.jitter >= 0 && options.jitter <= 1)\n )\n throw new RangeError(\"jitter must be between 0 and 1.\");\n if (\n options.maxSize !== undefined &&\n (!Number.isInteger(options.maxSize) || options.maxSize <= 0)\n )\n throw new RangeError(\"maxSize must be a positive integer.\");\n if (\n options.ttl !== undefined ||\n options.jitter !== undefined ||\n options.maxSize !== undefined ||\n options.slide !== undefined ||\n options.onEvict !== undefined\n )\n this.#policy = newPolicy(options);\n if (entries) for (const [key, value] of entries) this.set(key, value);\n }\n\n /**\n * Stores an entry with the default TTL (or `ttl`), marks it most recently\n * used, and enforces `maxSize`. Turns a `setWithoutTTL()` entry back into\n * a TTL/LRU entry.\n */\n public override set(key: K, value: V, ttl?: number): this {\n let policy = this.#policy;\n if (ttl === undefined && policy === undefined)\n return super.set(key, value);\n if (ttl !== undefined) assertTTL(ttl);\n let window = ttl ?? policy?.ttl;\n if (window !== undefined && policy !== undefined && policy.jitter > 0)\n window = Math.max(1, window * (1 - policy.jitter * Math.random()));\n if (policy === undefined) {\n if (window === undefined) return super.set(key, value);\n policy = this.#policy = newPolicy();\n }\n const entry = policy.entries.get(key);\n super.set(key, value);\n // The common rewrite: a timed entry whose deadline only moves later\n // is a field write; its heap record re-files itself when it surfaces,\n // and the entry count (so the cap) is unchanged.\n if (entry !== undefined && window !== undefined && entry.window !== 0) {\n const deadline = Date.now() + window;\n if (deadline >= entry.filed) {\n entry.value = value;\n entry.deadline = deadline;\n entry.window = window;\n if (entry.inLru) this.#promote(policy, entry);\n return this;\n }\n }\n this.#track(key, value, window, entry);\n if (policy.maxSize !== undefined && policy.lruSize > policy.maxSize)\n this.#enforceCap();\n return this;\n }\n\n /**\n * Stores an entry that never expires: no deadline, heap record, timer or\n * LRU eviction. It leaves only through `delete`, `sweep`, `clear`, or a\n * later `set()`.\n */\n public setWithoutTTL(key: K, value: V): this {\n if (this.#policy) this.#forget(key);\n super.set(key, value);\n return this;\n }\n\n /** Reads a value; restarts a TTL entry's window and promotes it. */\n public override get(key: K): V | undefined {\n const policy = this.#policy;\n const entry = policy?.entries.get(key);\n if (entry === undefined) {\n const value = mapGet.call(this, key) as V | undefined;\n if (value !== undefined || mapHas.call(this, key)) {\n this.#hits++;\n return value;\n }\n this.#misses++;\n return undefined;\n }\n const timed = entry.window !== 0;\n const now = timed ? Date.now() : 0;\n if (timed && entry.deadline <= now) {\n this.#expire(entry);\n this.#misses++;\n return undefined;\n }\n this.#hits++;\n if (timed && policy!.slide) entry.deadline = now + entry.window;\n if (entry.inLru) this.#promote(policy!, entry);\n return entry.value;\n }\n\n /**\n * Returns the value for `key`, or stores and returns what `factory`\n * makes. Reading counts as a `get()` (restarts the TTL, marks it recently\n * used); creating stores with `set()`, so `ttl` applies.\n * @param factory Called with the key and this collection only when the key is missing; if it throws, nothing is stored.\n * @param ttl TTL in ms for a created entry; defaults to the collection's.\n */\n public ensure(\n key: K,\n factory: (key: K, collection: this) => V,\n ttl?: number,\n ): V {\n const existing = this.get(key);\n if (existing !== undefined || super.has(key)) return existing as V;\n const created = factory(key, this);\n this.set(key, created, ttl);\n return created;\n }\n\n /** Reads a value without restarting its TTL or promoting it. */\n public peek(key: K): V | undefined {\n if (!this.#expireIfDue(key) && super.has(key)) {\n this.#hits++;\n return super.get(key);\n }\n this.#misses++;\n return undefined;\n }\n\n /** Cumulative hit, miss, expiry and eviction counters (a copy). */\n public get stats(): CollectionStats {\n return {\n hits: this.#hits,\n misses: this.#misses,\n expired: this.#policy?.expired ?? 0,\n evicted: this.#policy?.evicted ?? 0,\n };\n }\n\n public override has(key: K): boolean {\n return !this.#expireIfDue(key) && super.has(key);\n }\n\n public override delete(key: K): boolean {\n if (this.#expireIfDue(key)) return false;\n if (this.#policy) this.#forget(key);\n return super.delete(key);\n }\n\n public override clear(): void {\n super.clear();\n const policy = this.#policy;\n if (!policy) return;\n policy.entries.clear();\n policy.oldest = policy.newest = undefined;\n policy.lruSize = 0;\n policy.heap.length = 0;\n if (policy.timer) clearTimeout(policy.timer);\n policy.timer = undefined;\n policy.armedFor = Infinity;\n }\n\n public override get size(): number {\n this.purge();\n return super.size;\n }\n\n public override entries(): MapIterator<[K, V]> {\n this.purge();\n return super.entries();\n }\n\n public override keys(): MapIterator<K> {\n this.purge();\n return super.keys();\n }\n\n public override values(): MapIterator<V> {\n this.purge();\n return super.values();\n }\n\n public override [Symbol.iterator](): MapIterator<[K, V]> {\n return this.entries();\n }\n\n public override forEach(\n callback: (value: V, key: K, map: Map<K, V>) => void,\n thisArg?: unknown,\n ): void {\n this.purge();\n super.forEach(callback, thisArg);\n }\n\n /** Milliseconds until a key lapses, or undefined if absent or never expiring. */\n public ttlRemaining(key: K): number | undefined {\n if (this.#expireIfDue(key)) return undefined;\n const entry = this.#policy?.entries.get(key);\n return entry && entry.window !== 0\n ? Math.max(0, entry.deadline - Date.now())\n : undefined;\n }\n\n /** Drops every lapsed TTL entry now. @returns How many were dropped. */\n public purge(): number {\n if (!this.#policy || this.#policy.heap.length === 0) return 0;\n const now = Date.now();\n let removed = 0;\n const dropped: [K, V][] = [];\n while (this.#nextDeadline() <= now) {\n const due = this.#heapPop()!;\n dropped.push([due.key, super.get(due.key)!]);\n this.#remove(due.key);\n removed++;\n }\n this.#policy!.expired += removed;\n this.#rearm();\n for (const [key, value] of dropped) this.#notify(key, value, \"expired\");\n return removed;\n }\n\n /** Drops `key` if its TTL has lapsed. @returns Whether it did. */\n #expireIfDue(key: K): boolean {\n const entry = this.#policy?.entries.get(key);\n if (!entry || entry.window === 0 || entry.deadline > Date.now())\n return false;\n this.#expire(entry);\n return true;\n }\n\n #expire(entry: Entry<K, V>): void {\n const value = super.get(entry.key)!;\n this.#remove(entry.key);\n this.#policy!.expired++;\n this.#notify(entry.key, value, \"expired\");\n }\n\n #remove(key: K): void {\n this.#forget(key);\n super.delete(key);\n }\n\n /** Drops a key's policy entry (recency position and TTL); its heap record goes stale. */\n #forget(key: K): void {\n const policy = this.#policy!;\n const entry = policy.entries.get(key);\n if (!entry) return;\n if (entry.inLru) this.#unlink(policy, entry);\n policy.entries.delete(key);\n }\n\n /**\n * Brings the key's policy entry in line with a `set()`: marks it newest\n * when `maxSize` is set, and gives it a deadline when `window` is defined.\n * Only a new entry, or a deadline that moves earlier, gets a heap record;\n * a later one is a number write and the record re-files itself when it\n * surfaces.\n */\n #track(\n key: K,\n value: V,\n window: number | undefined,\n existing: Entry<K, V> | undefined,\n ): void {\n const policy = this.#policy!;\n const lru = policy.maxSize !== undefined;\n let entry = existing;\n if (entry) entry.value = value;\n if (window === undefined) {\n if (entry && entry.window !== 0) {\n // It had a TTL and now has none.\n if (lru) entry = this.#replace(policy, entry, 0, 0);\n else {\n this.#forget(key);\n return;\n }\n }\n if (!entry && lru) {\n entry = this.#create(key, value, 0, 0);\n policy.entries.set(key, entry);\n }\n if (entry) this.#promote(policy, entry);\n return;\n }\n const deadline = Date.now() + window;\n if (entry && entry.window !== 0) {\n entry.deadline = deadline;\n entry.window = window;\n if (deadline < entry.filed)\n // The heap cannot move a record up, and this one is in it: file a fresh one.\n entry = this.#replace(policy, entry, window, deadline);\n else {\n if (entry.inLru) this.#promote(policy, entry);\n return;\n }\n } else if (entry) {\n entry.window = window;\n entry.deadline = entry.filed = deadline;\n } else {\n entry = this.#create(key, value, window, deadline);\n policy.entries.set(key, entry);\n }\n if (lru) this.#promote(policy, entry);\n this.#heapPush(entry);\n if (policy.heap.length > 2 * policy.entries.size + 8) this.#compact();\n // A timer already armed for an earlier deadline stays correct.\n if (policy.timer === undefined || deadline < policy.armedFor)\n this.#rearm();\n }\n\n #create(key: K, value: V, window: number, deadline: number): Entry<K, V> {\n return {\n key,\n value,\n older: undefined,\n newer: undefined,\n inLru: false,\n window,\n deadline,\n filed: deadline,\n };\n }\n\n /** Swaps in a fresh record for `old` (which goes stale), keeping its recency position. */\n #replace(\n policy: Policy<K, V>,\n old: Entry<K, V>,\n window: number,\n deadline: number,\n ): Entry<K, V> {\n const entry: Entry<K, V> = {\n ...old,\n window,\n deadline,\n filed: deadline,\n };\n if (old.inLru) {\n if (old.older) old.older.newer = entry;\n else policy.oldest = entry;\n if (old.newer) old.newer.older = entry;\n else policy.newest = entry;\n }\n policy.entries.set(old.key, entry);\n return entry;\n }\n\n /** Makes an entry the newest in recency order, linking it first if needed. */\n #promote(policy: Policy<K, V>, entry: Entry<K, V>): void {\n if (entry === policy.newest) return;\n if (entry.inLru) this.#unlink(policy, entry, true);\n else {\n entry.inLru = true;\n policy.lruSize++;\n }\n entry.older = policy.newest;\n entry.newer = undefined;\n if (policy.newest) policy.newest.newer = entry;\n else policy.oldest = entry;\n policy.newest = entry;\n }\n\n /** Takes an entry out of the recency list; `keepCount` is for a move within it. */\n #unlink(policy: Policy<K, V>, entry: Entry<K, V>, keepCount = false): void {\n if (entry.older) entry.older.newer = entry.newer;\n else policy.oldest = entry.newer;\n if (entry.newer) entry.newer.older = entry.older;\n else policy.newest = entry.older;\n entry.older = entry.newer = undefined;\n if (!keepCount) {\n entry.inLru = false;\n policy.lruSize--;\n }\n }\n\n /**\n * An empty collection of the species this one derives, so `filter()` and\n * friends on a subclass return the subclass. It is built without\n * arguments and carries no `ttl` or `maxSize`.\n */\n #derived(): this {\n const Species =\n (\n this.constructor as {\n [Symbol.species]?: new () => Collection<K, V>;\n }\n )[Symbol.species] ?? Collection;\n return new Species() as this;\n }\n\n #notify(key: K, value: V, reason: EvictionReason): void {\n const onEvict = this.#policy?.onEvict;\n if (!onEvict) return;\n try {\n onEvict(key, value, reason);\n } catch {\n // A throwing callback must not leave the collection inconsistent.\n }\n }\n\n /** Evicts least-recently-used `set()` entries past `maxSize`; O(1) per eviction. */\n #enforceCap(): void {\n const policy = this.#policy!;\n const max = policy.maxSize;\n if (max === undefined) return;\n // Lapsed entries must not push live ones out.\n if (\n policy.lruSize > max &&\n policy.heap.length > 0 &&\n policy.heap[0]!.filed <= Date.now()\n )\n this.purge();\n while (policy.lruSize > max) {\n const oldest = policy.oldest!;\n const value = policy.onEvict ? super.get(oldest.key) : undefined;\n // Unlink the oldest in place: it is never the only other entry\n // here, since a cap of at least 1 keeps the newest.\n const next = oldest.newer;\n policy.oldest = next;\n if (next) next.older = undefined;\n else policy.newest = undefined;\n oldest.newer = undefined;\n oldest.inLru = false;\n policy.lruSize--;\n policy.entries.delete(oldest.key);\n super.delete(oldest.key);\n policy.evicted++;\n if (policy.onEvict) this.#notify(oldest.key, value as V, \"evicted\");\n }\n }\n\n #nextDeadline(): number {\n const policy = this.#policy!;\n for (;;) {\n const top = policy.heap[0];\n if (top === undefined) return Infinity;\n if (policy.entries.get(top.key) !== top) {\n this.#heapPop();\n continue;\n }\n if (top.deadline === top.filed) return top.filed;\n // Extended since it was filed: re-file for its current deadline.\n this.#heapPop();\n top.filed = top.deadline;\n this.#heapPush(top);\n }\n }\n\n #compact(): void {\n const policy = this.#policy!;\n const live = policy.heap.filter(\n (entry) => policy.entries.get(entry.key) === entry,\n );\n policy.heap.length = 0;\n for (const entry of live) this.#heapPush(entry);\n }\n\n #rearm(): void {\n const p = this.#policy!;\n const deadline = this.#nextDeadline();\n if (p.timer !== undefined && deadline >= p.armedFor) return;\n if (p.timer) clearTimeout(p.timer);\n p.timer = undefined;\n p.armedFor = deadline;\n if (deadline === Infinity) return;\n p.timer = setTimeout(\n () => {\n p.timer = undefined;\n p.armedFor = Infinity;\n this.purge();\n },\n Math.max(0, deadline - Date.now()),\n );\n // Pending expiry is housekeeping, not a reason to keep the process alive.\n (p.timer as { unref?: () => void }).unref?.();\n }\n\n #heapPush(entry: Entry<K, V>): void {\n const heap = this.#policy!.heap;\n let i = heap.length;\n heap.push(entry);\n while (i > 0) {\n const parent = (i - 1) >> 1;\n const above = heap[parent]!;\n if (above.filed <= entry.filed) break;\n heap[i] = above;\n i = parent;\n }\n heap[i] = entry;\n }\n\n #heapPop(): Entry<K, V> | undefined {\n const heap = this.#policy!.heap;\n const top = heap[0];\n const last = heap.pop();\n if (top === undefined || heap.length === 0) return top;\n let i = 0;\n for (;;) {\n let child = 2 * i + 1;\n if (child >= heap.length) break;\n if (\n child + 1 < heap.length &&\n heap[child + 1]!.filed < heap[child]!.filed\n )\n child++;\n if (heap[child]!.filed >= last!.filed) break;\n heap[i] = heap[child]!;\n i = child;\n }\n heap[i] = last!;\n return top;\n }\n\n /** Returns the first stored value. */\n public first(): V | undefined {\n for (const value of this.values()) return value;\n return undefined;\n }\n /** Returns the first stored key. */\n public firstKey(): K | undefined {\n for (const key of this.keys()) return key;\n return undefined;\n }\n /** Returns the last stored value. */\n public last(): V | undefined {\n let value: V | undefined;\n for (const item of this.values()) value = item;\n return value;\n }\n /** Returns the last stored key. */\n public lastKey(): K | undefined {\n let key: K | undefined;\n for (const item of this.keys()) key = item;\n return key;\n }\n /** Finds the first value matching a predicate. */\n public find(\n predicate: (value: V, key: K, collection: this) => boolean,\n ): V | undefined {\n for (const [key, value] of this) {\n if (predicate(value, key, this)) return value;\n }\n return undefined;\n }\n /** Finds the last value (in insertion order) matching a predicate. */\n public findLast(\n predicate: (value: V, key: K, collection: this) => boolean,\n ): V | undefined {\n const keys = this.keyArray();\n const values = this.array();\n for (let i = values.length - 1; i >= 0; i--)\n if (predicate(values[i]!, keys[i]!, this)) return values[i];\n return undefined;\n }\n /** Finds the key of the last entry (in insertion order) matching a predicate. */\n public findLastKey(\n predicate: (value: V, key: K, collection: this) => boolean,\n ): K | undefined {\n const keys = this.keyArray();\n const values = this.array();\n for (let i = values.length - 1; i >= 0; i--)\n if (predicate(values[i]!, keys[i]!, this)) return keys[i];\n return undefined;\n }\n /** Returns all values matching a predicate. */\n public filter(\n predicate: (value: V, key: K, collection: this) => boolean,\n ): this {\n const result = this.#derived();\n // forEach walks the entries without allocating a [key, value] pair each.\n this.forEach((value, key) => {\n if (predicate(value, key, this)) result.set(key, value);\n });\n return result;\n }\n /** Transforms every stored value into an array. */\n public map<T>(transform: (value: V, key: K, collection: this) => T): T[] {\n const result: T[] = [];\n this.forEach((value, key) => {\n result.push(transform(value, key, this));\n });\n return result;\n }\n /** Returns whether at least one stored value satisfies a predicate. */\n public some(\n predicate: (value: V, key: K, collection: this) => boolean,\n ): boolean {\n for (const [key, value] of this) {\n if (predicate(value, key, this)) return true;\n }\n return false;\n }\n /** Returns whether every stored value satisfies a predicate. */\n public every(\n predicate: (value: V, key: K, collection: this) => boolean,\n ): boolean {\n for (const [key, value] of this) {\n if (!predicate(value, key, this)) return false;\n }\n return true;\n }\n /** Runs a callback for each stored value. */\n public each(\n callback: (value: V, key: K, collection: this) => unknown,\n ): this {\n this.forEach((value, key) => {\n callback(value, key, this);\n });\n return this;\n }\n /** Returns an array containing all stored values. */\n public array(): V[] {\n return [...this.values()];\n }\n /** Returns an array containing all stored keys. */\n public keyArray(): K[] {\n return [...this.keys()];\n }\n /** Returns a plain array of entries. */\n public entriesArray(): [K, V][] {\n return [...this.entries()];\n }\n /** Returns a new collection with the same entries. */\n public clone(): this {\n const copy = this.#derived();\n this.forEach((value, key) => {\n copy.set(key, value);\n });\n return copy;\n }\n /** Returns whether all supplied keys are present. */\n public hasAll(...keys: K[]): boolean {\n for (let i = 0; i < keys.length; i++) {\n if (!this.has(keys[i]!)) return false;\n }\n return true;\n }\n /** Returns whether at least one supplied key is present. */\n public hasAny(...keys: K[]): boolean {\n for (let i = 0; i < keys.length; i++) {\n if (this.has(keys[i]!)) return true;\n }\n return false;\n }\n /** Returns the first key whose value matches a predicate. */\n public findKey(\n predicate: (value: V, key: K, collection: this) => boolean,\n ): K | undefined {\n for (const [key, value] of this) {\n if (predicate(value, key, this)) return key;\n }\n return undefined;\n }\n /** Returns whether a predicate matches at least one entry. */\n public someEntry(\n predicate: (value: V, key: K, collection: this) => boolean,\n ): boolean {\n return this.some(predicate);\n }\n /** Removes every entry matching a predicate and returns the number removed. */\n public sweep(\n predicate: (value: V, key: K, collection: this) => boolean,\n ): number {\n let removed = 0;\n for (const [key, value] of this) {\n if (predicate(value, key, this) && this.delete(key)) removed++;\n }\n return removed;\n }\n /** Returns the collection's first matching entry as a tuple. */\n public firstEntry(): [K, V] | undefined {\n for (const [key, value] of this) return [key, value];\n return undefined;\n }\n /** Returns the collection's last matching entry as a tuple. */\n public lastEntry(): [K, V] | undefined {\n let entry: [K, V] | undefined;\n for (const item of this) entry = [item[0], item[1]];\n return entry;\n }\n /** Returns a new Collection containing elements from both collections. */\n public union(other: ReadonlyCollection<K, V>): this {\n const result = this.clone();\n for (const [key, value] of other) result.set(key, value);\n return result;\n }\n /** Returns a new Collection containing only elements present in both collections. */\n public intersection(other: ReadonlyCollection<K, V>): this {\n const result = this.#derived();\n for (const [key, value] of this) {\n if (other.has(key)) result.set(key, value);\n }\n return result;\n }\n /** Returns a new Collection containing elements present in this collection but not the other. */\n public difference(other: ReadonlyCollection<K, V>): this {\n const result = this.#derived();\n for (const [key, value] of this) {\n if (!other.has(key)) result.set(key, value);\n }\n return result;\n }\n /** Splits the collection into two collections based on a predicate.\n * @returns `[passing, failing]` — entries satisfying the predicate, then those that don't.\n */\n public partition(\n predicate: (value: V, key: K, collection: this) => boolean,\n ): [this, this] {\n const pass = this.#derived();\n const fail = this.#derived();\n for (const [key, value] of this) {\n if (predicate(value, key, this)) pass.set(key, value);\n else fail.set(key, value);\n }\n return [pass, fail];\n }\n /** Returns the entries of both collections that are in only one of them. */\n public symmetricDifference(other: ReadonlyCollection<K, V>): this {\n const result = this.#derived();\n for (const [key, value] of this)\n if (!other.has(key)) result.set(key, value);\n for (const [key, value] of other)\n if (!this.has(key)) result.set(key, value);\n return result;\n }\n /** Returns a new Collection with this one's entries followed by each of `collections`'; a later collection wins a shared key. */\n public concat(...collections: ReadonlyCollection<K, V>[]): this {\n const result = this.clone();\n for (const collection of collections)\n for (const [key, value] of collection) result.set(key, value);\n return result;\n }\n /**\n * Combines this collection with `other`, deciding per key what to keep.\n * @param whenInSelf Called for a key only in this collection.\n * @param whenInOther Called for a key only in `other`.\n * @param whenInBoth Called for a key in both.\n * @returns A new collection of the entries the callbacks kept, in this collection's order, then `other`'s new keys.\n */\n public merge<T, R>(\n other: ReadonlyCollection<K, T>,\n whenInSelf: (value: V, key: K) => Keep<R>,\n whenInOther: (valueOther: T, key: K) => Keep<R>,\n whenInBoth: (value: V, valueOther: T, key: K) => Keep<R>,\n ): Collection<K, R> {\n const result = this.#derived() as unknown as Collection<K, R>;\n const decide = (key: K, kept: Keep<R>): void => {\n if (kept.keep) result.set(key, kept.value);\n };\n for (const [key, value] of this) {\n decide(\n key,\n other.has(key)\n ? whenInBoth(value, peekOf(other, key) as T, key)\n : whenInSelf(value, key),\n );\n }\n for (const [key, value] of other)\n if (!this.has(key)) decide(key, whenInOther(value, key));\n return result;\n }\n /** Returns whether `other` holds the same keys with `===` equal values. Neither side's TTL or recency is touched. */\n public equals(other: ReadonlyCollection<K, V> | null | undefined): boolean {\n if (!other) return false;\n if (other === (this as unknown)) return true;\n if (this.size !== other.size) return false;\n for (const [key, value] of this) {\n if (!other.has(key)) return false;\n if (value !== peekOf(other, key)) return false;\n }\n return true;\n }\n /** Returns a new collection with the same keys and each value passed through `transform`. */\n public mapValues<T>(\n transform: (value: V, key: K, collection: this) => T,\n ): Collection<K, T> {\n const result = this.#derived() as unknown as Collection<K, T>;\n for (const [key, value] of this)\n result.set(key, transform(value, key, this));\n return result;\n }\n /** Returns a new collection with the entries in reverse order. */\n public toReversed(): this {\n const result = this.#derived();\n const entries = [...this];\n for (let i = entries.length - 1; i >= 0; i--)\n result.set(entries[i]![0], entries[i]![1]);\n return result;\n }\n /** Same as {@link sorted}, under the name the standard `Array` uses. */\n public toSorted(\n comparator?: (a: V, b: V, aKey: K, bKey: K) => number,\n ): this {\n return this.sorted(comparator);\n }\n /**\n * Groups `items` by the key `keySelector` returns for each.\n * @param keySelector Called with each item and its index.\n * @returns A new collection from each key to its items, in input order.\n */\n public static override groupBy<K, V>(\n items: Iterable<V>,\n keySelector: (item: V, index: number) => K,\n ): Collection<K, V[]> {\n const groups = new Collection<K, V[]>();\n let index = 0;\n for (const item of items)\n groups.ensure(keySelector(item, index++), () => []).push(item);\n return groups;\n }\n /**\n * Builds a collection from `entries`, merging values that share a key.\n * @param combine Called with the value stored so far, the new one and the key; its result is stored.\n */\n public static combineEntries<K, V>(\n entries: Iterable<readonly [K, V]>,\n combine: (firstValue: V, secondValue: V, key: K) => V,\n ): Collection<K, V> {\n const result = new Collection<K, V>();\n for (const [key, value] of entries)\n result.set(\n key,\n result.has(key) ? combine(result.get(key)!, value, key) : value,\n );\n return result;\n }\n /** Calls `fn` with this collection and returns the collection unchanged.\n * Useful for inserting debug side-effects in a chain without breaking the flow.\n */\n public tap(fn: (collection: this) => unknown): this {\n fn(this);\n return this;\n }\n /** Maps every entry to an array of items and flattens the results. */\n public flatMap<T>(\n transform: (value: V, key: K, collection: this) => T[],\n ): T[] {\n const result: T[] = [];\n for (const [key, value] of this) {\n for (const item of transform(value, key, this)) result.push(item);\n }\n return result;\n }\n /** Reduces the collection to a single value. */\n public reduce<T>(\n fn: (accumulator: T, value: V, key: K, collection: this) => T,\n initialValue: T,\n ): T {\n let acc = initialValue;\n for (const [key, value] of this) acc = fn(acc, value, key, this);\n return acc;\n }\n /** Like {@link reduce}, but from the last entry to the first. */\n public reduceRight<T>(\n fn: (accumulator: T, value: V, key: K, collection: this) => T,\n initialValue: T,\n ): T {\n const entries = [...this];\n let acc = initialValue;\n for (let i = entries.length - 1; i >= 0; i--)\n acc = fn(acc, entries[i]![1], entries[i]![0], this);\n return acc;\n }\n /** Returns a new Collection with entries sorted by comparator (non-mutating).\n * Defaults to insertion order if no comparator is provided.\n */\n public sorted(comparator?: (a: V, b: V, aKey: K, bKey: K) => number): this {\n // Decorate with the original insertion index and use it as a tiebreaker so\n // equal elements keep their insertion order (a stable sort independent of\n // the engine's Array.prototype.sort stability guarantees).\n const decorated = [...this.entries()].map((entry, index) => ({\n entry,\n index,\n }));\n if (comparator)\n decorated.sort((x, y) => {\n const comparison = comparator(\n x.entry[1],\n y.entry[1],\n x.entry[0],\n y.entry[0],\n );\n return comparison !== 0 ? comparison : x.index - y.index;\n });\n const result = this.#derived();\n for (const { entry } of decorated) result.set(entry[0], entry[1]);\n return result;\n }\n /**\n * Returns a random value, or `undefined` if empty. With `amount`, returns\n * that many different values (all of them, shuffled, when `amount` is at\n * least the size).\n * Uses `Math.random()` (fast, non-cryptographic): do not use it for\n * security-sensitive selection such as tokens or secrets.\n * @param amount How many values to pick.\n * @throws {RangeError} If `amount` is not a non-negative integer.\n */\n public random(): V | undefined;\n public random(amount: number): V[];\n public random(amount?: number): V | V[] | undefined {\n if (amount !== undefined) return sample([...this.values()], amount);\n const size = this.size;\n if (size === 0) return undefined;\n let index = Math.floor(Math.random() * size);\n for (const value of this.values()) if (index-- === 0) return value;\n return undefined;\n }\n /**\n * Returns a random key, or `undefined` if empty. With `amount`, returns\n * that many different keys. Same randomness and errors as {@link random}.\n * @param amount How many keys to pick.\n */\n public randomKey(): K | undefined;\n public randomKey(amount: number): K[];\n public randomKey(amount?: number): K | K[] | undefined {\n if (amount !== undefined) return sample([...this.keys()], amount);\n const size = this.size;\n if (size === 0) return undefined;\n let index = Math.floor(Math.random() * size);\n for (const key of this.keys()) if (index-- === 0) return key;\n return undefined;\n }\n /** Returns the value at a given insertion-order index (supports negative indices). */\n public at(index: number): V | undefined {\n let remaining = index < 0 ? this.size + index : index;\n if (remaining < 0) return undefined;\n for (const value of this.values()) if (remaining-- === 0) return value;\n return undefined;\n }\n /** Returns the key at a given insertion-order index (supports negative indices). */\n public keyAt(index: number): K | undefined {\n let remaining = index < 0 ? this.size + index : index;\n if (remaining < 0) return undefined;\n for (const key of this.keys()) if (remaining-- === 0) return key;\n return undefined;\n }\n /** Serializes the collection to a plain `[key, value]` array. */\n public toJSON(): [K, V][] {\n return [...this.entries()];\n }\n}\n\nexport { Cache } from \"./cache.js\";\nexport type { CacheOptions } from \"./cache.js\";\nexport {\n RedisCollection,\n type RedisCollectionOptions,\n type RedisCommandClient,\n type RedisSerializer,\n} from \"./redis.js\";\n"
7
8
  ],
8
- "mappings": "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",
9
- "debugId": "44902D8F098C340964756E2164756E21",
9
+ "mappings": ";;AAsBO,MAAM,MAAY;AAAA,EACZ;AAAA,EAGF,WAAW,CAAC,UAAwB,CAAC,GAAG;AAAA,IAC3C,MAAM,UAAU,QAAQ,WAAW;AAAA,IACnC,MAAM,MAAM,QAAQ,OAAO;AAAA,IAC3B,IAAK,CAAC,OAAO,UAAU,OAAO,KAAK,YAAY,YAAa,UAAU;AAAA,MAClE,MAAM,IAAI,WAAW,2CAA2C;AAAA,IACpE,IAAI,CAAC,OAAO,SAAS,GAAG,KAAK,MAAM;AAAA,MAC/B,MAAM,IAAI,WACN,iDACJ;AAAA,IACJ,IAAI,GAAG,QAAQ,UAAU,MAAM,MAAM,QAAQ,UAAU,MAAM;AAAA,MACzD,MAAM,IAAI,WAAW,uCAAuC;AAAA,IAChE,IAAI,MAAM,GAAG;AAAA,MACT,MAAM,WAAW,QAAQ,iBAAiB,KAAK,IAAI,KAAK,KAAM;AAAA,MAC9D,IAAI,CAAC,OAAO,SAAS,QAAQ,KAAK,WAAW;AAAA,QACzC,MAAM,IAAI,WAAW,uCAAuC;AAAA,IACpE;AAAA,IACA,KAAK,WAAW,IAAI,WAAiB,MAAM;AAAA,MACvC,KAAK,MAAM,IAAI,MAAM;AAAA,MACrB,QAAQ,QAAQ;AAAA,MAChB,SAAS,YAAY,WAAW,YAAY;AAAA,MAC5C,OAAO;AAAA,IACX,CAAC;AAAA;AAAA,MAIM,IAAI,GAAW;AAAA,IACtB,OAAO,KAAK,SAAS;AAAA;AAAA,EAGlB,GAAG,CAAC,KAAuB;AAAA,IAC9B,OAAO,KAAK,SAAS,IAAI,GAAG;AAAA;AAAA,EAGzB,GAAG,CAAC,KAAiB;AAAA,IACxB,OAAO,KAAK,SAAS,IAAI,GAAG;AAAA;AAAA,EAGzB,GAAG,CAAC,KAAQ,OAAgB;AAAA,IAC/B,KAAK,SAAS,IAAI,KAAK,KAAK;AAAA,IAC5B,OAAO;AAAA;AAAA,EAGJ,MAAM,CAAC,KAAiB;AAAA,IAC3B,OAAO,KAAK,SAAS,OAAO,GAAG;AAAA;AAAA,EAG5B,KAAK,GAAS;AAAA,IACjB,KAAK,SAAS,MAAM;AAAA;AAAA,EAGjB,UAAU,CAAC,WAAkD;AAAA,IAChE,OAAO,KAAK,SAAS,MAAM,SAAS;AAAA;AAAA,EAGjC,KAAK,GAAW;AAAA,IACnB,OAAO,KAAK,SAAS,MAAM;AAAA;AAAA,EAGxB,OAAO,GAAS;AAAA,EAEhB,MAAM,GAAQ;AAAA,IACjB,OAAO,CAAC,GAAG,KAAK,SAAS,OAAO,CAAC;AAAA;AAAA,EAG9B,OAAO,GAAa;AAAA,IACvB,OAAO,CAAC,GAAG,KAAK,SAAS,QAAQ,CAAC;AAAA;AAE1C;;AClDA,IAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsBT,IAAM,aAAa,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoCtB,IAAM,aAAa,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsBtB,IAAM,gBAAgB,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASzB,IAAM,cAAc,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiB9B,IAAM,kBAAkB;AAExB,IAAM,kBAA0C;AAAA,EAC5C,WAAW,CAAC,UAAU,KAAK,UAAU,KAAK;AAAA,EAC1C,aAAa,CAAC,QAAQ,KAAK,MAAM,GAAG;AACxC;AAAA;AAuBO,MAAM,gBAA6B;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAA0B;AAAA,IAC/B,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,SAAS;AAAA,EACb;AAAA,EAEgB;AAAA,EAET,WAAW,CAAC,SAAoC;AAAA,IACnD,IACI,OAAO,QAAQ,SAAS,YACxB,CAAC,mBAAmB,KAAK,QAAQ,IAAI;AAAA,MAErC,MAAM,IAAI,UACN,2DACJ;AAAA,IACJ,SAAS,QAAQ,GAAG;AAAA,IACpB,IACI,QAAQ,YAAY,aACpB,EAAE,OAAO,UAAU,QAAQ,OAAO,KAAK,QAAQ,UAAU;AAAA,MAEzD,MAAM,IAAI,WAAW,qCAAqC;AAAA,IAC9D,KAAK,SAAS,QAAQ;AAAA,IACtB,KAAK,OAAO,QAAQ;AAAA,IAEpB,MAAM,OAAO,GAAG,QAAQ,UAAU,4BAA4B,QAAQ;AAAA,IACtE,KAAK,QAAQ,CAAC,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW;AAAA,IACxD,KAAK,MAAM,GAAG;AAAA,IACd,KAAK,OAAO,QAAQ,OAAO;AAAA,IAC3B,KAAK,SAAS,QAAQ,SAAS;AAAA,IAC/B,KAAK,WAAW,QAAQ,WAAW;AAAA,IACnC,KAAK,cACD,QAAQ,cAAe;AAAA,IAC3B,KAAK,WAAW,QAAQ;AAAA;AAAA,MAIjB,KAAK,GAAoB;AAAA,IAChC,OAAO,KAAK,KAAK,OAAO;AAAA;AAAA,OAGtB,IAAI,CAAC,WAAmB,MAAoC;AAAA,IAC9D,MAAM,QAAS,MAAM,KAAK,OAAO,KAAK,QAAQ;AAAA,MAC1C;AAAA,MACA;AAAA,MACA,GAAG,KAAK;AAAA,MACR,KAAK;AAAA,MACL,GAAG;AAAA,IACP,CAAC;AAAA,IACD,IAAI,CAAC,MAAM,QAAQ,KAAK;AAAA,MACpB,MAAM,IAAI,MAAM,iDAAiD;AAAA,IACrE,OAAO;AAAA;AAAA,EAIX,OAAO,CAAC,OAAkB,MAAuB;AAAA,IAC7C,SAAS,IAAI,KAAM,IAAI,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG;AAAA,MACjD,MAAM,MAAM,OAAO,MAAM,EAAE;AAAA,MAC3B,MAAM,MAAM,MAAM,IAAI;AAAA,MACtB,MAAM,SAAS,MAAM,IAAI;AAAA,MACzB,IAAI,WAAW;AAAA,QAAW,KAAK,OAAO;AAAA,MACjC;AAAA,aAAK,OAAO;AAAA,MACjB,IAAI,CAAC,KAAK;AAAA,QAAU;AAAA,MACpB,IAAI;AAAA,MACJ,IAAI;AAAA,QACA,QAAQ,OAAO,QAAQ,WAAW,KAAK,QAAQ,GAAG,IAAI;AAAA,QACxD,MAAM;AAAA,QACJ,QAAQ;AAAA;AAAA,MAEZ,IAAI;AAAA,QACA,KAAK,SAAS,KAAK,OAAO,MAAM;AAAA,QAClC,MAAM;AAAA,IAGZ;AAAA,IACA,OAAO,MAAM;AAAA;AAAA,EAGjB,OAAO,CAAC,UAAqB;AAAA,IACzB,MAAM,QAAQ,SAAS,QAAQ,GAAG;AAAA,IAClC,OAAO,KAAK,YAAY,YAAY,SAAS,MAAM,QAAQ,CAAC,CAAC;AAAA;AAAA,OAOpD,IAAG,CAAC,KAA8C;AAAA,IAC3D,MAAM,MAAM,KAAK,QACb,MAAM,KAAK,KACP,YACA,OAAO,GAAG,GACV,KAAK,SAAS,MAAM,KACpB,GACJ,GACA,CACJ;AAAA,IACA,IAAI,OAAO,QAAQ,UAAU;AAAA,MACzB,KAAK,OAAO;AAAA,MACZ;AAAA,IACJ;AAAA,IACA,KAAK,OAAO;AAAA,IACZ,OAAO,KAAK,QAAQ,GAAG;AAAA;AAAA,OAId,KAAI,CAAC,KAA8C;AAAA,IAC5D,MAAM,MAAM,KAAK,QACb,MAAM,KAAK,KAAK,YAAY,OAAO,GAAG,GAAG,KAAK,GAAG,GACjD,CACJ;AAAA,IACA,OAAO,OAAO,QAAQ,WAAW,KAAK,QAAQ,GAAG,IAAI;AAAA;AAAA,OAI5C,IAAG,CAAC,KAAwC;AAAA,IACrD,OAAQ,MAAM,KAAK,KAAK,GAAG,MAAO;AAAA;AAAA,OAIzB,IAAG,CACZ,KACA,OACA,KACa;AAAA,IACb,SAAS,KAAK,IAAI;AAAA,IAClB,KAAK,QACD,MAAM,KAAK,KACP,YACA,OAAO,GAAG,GACV,KAAK,YAAY,UAAU,KAAK,GAChC,OAAO,KAAK,KAAK,OAAO,KAAK,IAAI,CAAC,GAClC,OAAO,KAAK,QAAQ,GACpB,KACJ,GACA,CACJ;AAAA,IACA,OAAO;AAAA;AAAA,EAIJ,aAAa,CAAC,KAAsB,OAAyB;AAAA,IAChE,OAAO,KAAK,IAAI,KAAK,OAAO,CAAC;AAAA;AAAA,OAOpB,OAAM,CACf,KACA,SACA,KACU;AAAA,IACV,MAAM,WAAW,MAAM,KAAK,IAAI,GAAG;AAAA,IACnC,IAAI,aAAa;AAAA,MAAW,OAAO;AAAA,IACnC,SAAS,KAAK,IAAI;AAAA,IAClB,MAAM,QAAQ,MAAM,QAAQ,OAAO,GAAG,CAAC;AAAA,IACvC,MAAM,MAAM,KAAK,QACb,MAAM,KAAK,KACP,YACA,OAAO,GAAG,GACV,KAAK,YAAY,UAAU,KAAK,GAChC,OAAO,KAAK,KAAK,OAAO,KAAK,IAAI,CAAC,GAClC,OAAO,KAAK,QAAQ,GACpB,IACJ,GACA,CACJ;AAAA,IACA,OAAO,OAAO,QAAQ,WAAW,KAAK,QAAQ,GAAG,IAAI;AAAA;AAAA,OAI5C,OAAM,CAAC,KAAwC;AAAA,IACxD,MAAM,QAAQ,MAAM,KAAK,KAAK,eAAe,OAAO,GAAG,CAAC;AAAA,IACxD,OAAO,OAAO,KAAK,QAAQ,OAAO,CAAC,CAAC,MAAM;AAAA;AAAA,OAIjC,MAAK,GAAoB;AAAA,IAClC,MAAM,QAAQ,MAAM,KAAK,KAAK,aAAa,OAAO;AAAA,IAClD,OAAO,OAAO,MAAM,EAAE;AAAA;AAAA,OAIb,KAAI,GAAoB;AAAA,IACjC,OAAO,OAAO,KAAK,QAAQ,MAAM,KAAK,KAAK,aAAa,MAAM,GAAG,CAAC,CAAC;AAAA;AAAA,OAI1D,KAAI,GAAsB;AAAA,IACnC,OACI,KAAK,QAAQ,MAAM,KAAK,KAAK,aAAa,MAAM,GAAG,CAAC,EACtD,IAAI,MAAM;AAAA;AAAA,OAIH,QAAO,GAAgC;AAAA,IAChD,MAAM,OAAO,MAAM,KAAK,KAAK;AAAA,IAC7B,IAAI,KAAK,WAAW;AAAA,MAAG,OAAO,CAAC;AAAA,IAC/B,MAAM,MAA0B,CAAC;AAAA,IACjC,SAAS,IAAI,EAAG,IAAI,KAAK,QAAQ,KAAK,MAAM;AAAA,MACxC,MAAM,QAAQ,KAAK,MAAM,GAAG,IAAI,IAAI;AAAA,MACpC,MAAM,OAAQ,MAAM,KAAK,OAAO,KAC5B,QACA,MAAM,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC,CACjC;AAAA,MACA,KAAK,QAAQ,CAAC,KAAK,MAAM;AAAA,QACrB,IAAI,OAAO,QAAQ;AAAA,UACf,IAAI,KAAK,CAAC,MAAM,IAAK,KAAK,QAAQ,GAAG,CAAC,CAAC;AAAA,OAC9C;AAAA,IACL;AAAA,IACA,OAAO;AAAA;AAAA,OAIE,OAAM,GAAiB;AAAA,IAChC,QAAQ,MAAM,KAAK,QAAQ,GAAG,IAAI,IAAI,WAAW,KAAK;AAAA;AAAA,OAI7C,aAAY,CACrB,KAC2B;AAAA,IAC3B,MAAM,KAAK,OACP,MAAM,KAAK,OAAO,KAAK,QAAQ,CAAC,KAAK,MAAM,OAAO,GAAG,CAAC,CAAC,CAC3D;AAAA,IAEA,OAAO,MAAM,IAAI,KAAK,IAAI,GAAG,KAAK,eAAe,IAAI;AAAA;AAE7D;AAEA,SAAS,QAAQ,CAAC,KAAyB,YAAY,OAAa;AAAA,EAChE,IAAI,QAAQ;AAAA,IAAW;AAAA,EACvB,IAAI,CAAC,OAAO,SAAS,GAAG,KAAK,MAAM,KAAM,CAAC,aAAa,QAAQ;AAAA,IAC3D,MAAM,IAAI,WACN,YACM,wCACA,gCACV;AAAA;;;AC5VR,SAAS,SAAe,CAAC,UAAmC,CAAC,GAAiB;AAAA,EAC1E,OAAO;AAAA,IACH,KAAK,QAAQ;AAAA,IACb,QAAQ,QAAQ,UAAU;AAAA,IAC1B,SAAS,QAAQ;AAAA,IACjB,OAAO,QAAQ,SAAS;AAAA,IACxB,SAAS,QAAQ;AAAA,IACjB,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS,IAAI;AAAA,IACb,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,MAAM,CAAC;AAAA,IACP,UAAU;AAAA,EACd;AAAA;AAOJ,SAAS,MAAY,CACjB,YACA,KACa;AAAA,EACb,OAAO,sBAAsB,MACtB,IAAI,UAAU,IAAI,KAAK,YAAY,GAAG,IACvC,WAAW,IAAI,GAAG;AAAA;AAwB5B,IAAM,SAAS,IAAI,UAAU;AAI7B,IAAM,SAAS,IAAI,UAAU;AAM7B,SAAS,MAAS,CAAC,OAAY,QAAqB;AAAA,EAChD,IAAI,CAAC,OAAO,UAAU,MAAM,KAAK,SAAS;AAAA,IACtC,MAAM,IAAI,WAAW,wCAAwC;AAAA,EACjE,MAAM,QAAQ,KAAK,IAAI,QAAQ,MAAM,MAAM;AAAA,EAC3C,SAAS,IAAI,EAAG,IAAI,OAAO,KAAK;AAAA,IAC5B,MAAM,IAAI,IAAI,KAAK,MAAM,KAAK,OAAO,KAAK,MAAM,SAAS,EAAE;AAAA,IAC3D,CAAC,MAAM,IAAI,MAAM,EAAE,IAAI,CAAC,MAAM,IAAK,MAAM,EAAG;AAAA,EAChD;AAAA,EACA,MAAM,SAAS;AAAA,EACf,OAAO;AAAA;AAGX,SAAS,SAAS,CAAC,KAA+B;AAAA,EAC9C,IAAI,QAAQ,cAAc,CAAC,OAAO,SAAS,GAAG,KAAK,OAAO;AAAA,IACtD,MAAM,IAAI,WAAW,4CAA4C;AAAA;AAAA;AAelE,MAAM,mBAAyB,IAAU;AAAA,EAE5C;AAAA,EACA,QAAQ;AAAA,EACR,UAAU;AAAA,EAOH,WAAW,CACd,SACA,UAAmC,CAAC,GACtC;AAAA,IACE,MAAM;AAAA,IACN,UAAU,QAAQ,GAAG;AAAA,IACrB,IACI,QAAQ,WAAW,aACnB,EAAE,QAAQ,UAAU,KAAK,QAAQ,UAAU;AAAA,MAE3C,MAAM,IAAI,WAAW,iCAAiC;AAAA,IAC1D,IACI,QAAQ,YAAY,cACnB,CAAC,OAAO,UAAU,QAAQ,OAAO,KAAK,QAAQ,WAAW;AAAA,MAE1D,MAAM,IAAI,WAAW,qCAAqC;AAAA,IAC9D,IACI,QAAQ,QAAQ,aAChB,QAAQ,WAAW,aACnB,QAAQ,YAAY,aACpB,QAAQ,UAAU,aAClB,QAAQ,YAAY;AAAA,MAEpB,KAAK,UAAU,UAAU,OAAO;AAAA,IACpC,IAAI;AAAA,MAAS,YAAY,KAAK,UAAU;AAAA,QAAS,KAAK,IAAI,KAAK,KAAK;AAAA;AAAA,EAQxD,GAAG,CAAC,KAAQ,OAAU,KAAoB;AAAA,IACtD,IAAI,SAAS,KAAK;AAAA,IAClB,IAAI,QAAQ,aAAa,WAAW;AAAA,MAChC,OAAO,MAAM,IAAI,KAAK,KAAK;AAAA,IAC/B,IAAI,QAAQ;AAAA,MAAW,UAAU,GAAG;AAAA,IACpC,IAAI,SAAS,OAAO,QAAQ;AAAA,IAC5B,IAAI,WAAW,aAAa,WAAW,aAAa,OAAO,SAAS;AAAA,MAChE,SAAS,KAAK,IAAI,GAAG,UAAU,IAAI,OAAO,SAAS,KAAK,OAAO,EAAE;AAAA,IACrE,IAAI,WAAW,WAAW;AAAA,MACtB,IAAI,WAAW;AAAA,QAAW,OAAO,MAAM,IAAI,KAAK,KAAK;AAAA,MACrD,SAAS,KAAK,UAAU,UAAU;AAAA,IACtC;AAAA,IACA,MAAM,QAAQ,OAAO,QAAQ,IAAI,GAAG;AAAA,IACpC,MAAM,IAAI,KAAK,KAAK;AAAA,IAIpB,IAAI,UAAU,aAAa,WAAW,aAAa,MAAM,WAAW,GAAG;AAAA,MACnE,MAAM,WAAW,KAAK,IAAI,IAAI;AAAA,MAC9B,IAAI,YAAY,MAAM,OAAO;AAAA,QACzB,MAAM,QAAQ;AAAA,QACd,MAAM,WAAW;AAAA,QACjB,MAAM,SAAS;AAAA,QACf,IAAI,MAAM;AAAA,UAAO,KAAK,SAAS,QAAQ,KAAK;AAAA,QAC5C,OAAO;AAAA,MACX;AAAA,IACJ;AAAA,IACA,KAAK,OAAO,KAAK,OAAO,QAAQ,KAAK;AAAA,IACrC,IAAI,OAAO,YAAY,aAAa,OAAO,UAAU,OAAO;AAAA,MACxD,KAAK,YAAY;AAAA,IACrB,OAAO;AAAA;AAAA,EAQJ,aAAa,CAAC,KAAQ,OAAgB;AAAA,IACzC,IAAI,KAAK;AAAA,MAAS,KAAK,QAAQ,GAAG;AAAA,IAClC,MAAM,IAAI,KAAK,KAAK;AAAA,IACpB,OAAO;AAAA;AAAA,EAIK,GAAG,CAAC,KAAuB;AAAA,IACvC,MAAM,SAAS,KAAK;AAAA,IACpB,MAAM,QAAQ,QAAQ,QAAQ,IAAI,GAAG;AAAA,IACrC,IAAI,UAAU,WAAW;AAAA,MACrB,MAAM,QAAQ,OAAO,KAAK,MAAM,GAAG;AAAA,MACnC,IAAI,UAAU,aAAa,OAAO,KAAK,MAAM,GAAG,GAAG;AAAA,QAC/C,KAAK;AAAA,QACL,OAAO;AAAA,MACX;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACJ;AAAA,IACA,MAAM,QAAQ,MAAM,WAAW;AAAA,IAC/B,MAAM,MAAM,QAAQ,KAAK,IAAI,IAAI;AAAA,IACjC,IAAI,SAAS,MAAM,YAAY,KAAK;AAAA,MAChC,KAAK,QAAQ,KAAK;AAAA,MAClB,KAAK;AAAA,MACL;AAAA,IACJ;AAAA,IACA,KAAK;AAAA,IACL,IAAI,SAAS,OAAQ;AAAA,MAAO,MAAM,WAAW,MAAM,MAAM;AAAA,IACzD,IAAI,MAAM;AAAA,MAAO,KAAK,SAAS,QAAS,KAAK;AAAA,IAC7C,OAAO,MAAM;AAAA;AAAA,EAUV,MAAM,CACT,KACA,SACA,KACC;AAAA,IACD,MAAM,WAAW,KAAK,IAAI,GAAG;AAAA,IAC7B,IAAI,aAAa,aAAa,MAAM,IAAI,GAAG;AAAA,MAAG,OAAO;AAAA,IACrD,MAAM,UAAU,QAAQ,KAAK,IAAI;AAAA,IACjC,KAAK,IAAI,KAAK,SAAS,GAAG;AAAA,IAC1B,OAAO;AAAA;AAAA,EAIJ,IAAI,CAAC,KAAuB;AAAA,IAC/B,IAAI,CAAC,KAAK,aAAa,GAAG,KAAK,MAAM,IAAI,GAAG,GAAG;AAAA,MAC3C,KAAK;AAAA,MACL,OAAO,MAAM,IAAI,GAAG;AAAA,IACxB;AAAA,IACA,KAAK;AAAA,IACL;AAAA;AAAA,MAIO,KAAK,GAAoB;AAAA,IAChC,OAAO;AAAA,MACH,MAAM,KAAK;AAAA,MACX,QAAQ,KAAK;AAAA,MACb,SAAS,KAAK,SAAS,WAAW;AAAA,MAClC,SAAS,KAAK,SAAS,WAAW;AAAA,IACtC;AAAA;AAAA,EAGY,GAAG,CAAC,KAAiB;AAAA,IACjC,OAAO,CAAC,KAAK,aAAa,GAAG,KAAK,MAAM,IAAI,GAAG;AAAA;AAAA,EAGnC,MAAM,CAAC,KAAiB;AAAA,IACpC,IAAI,KAAK,aAAa,GAAG;AAAA,MAAG,OAAO;AAAA,IACnC,IAAI,KAAK;AAAA,MAAS,KAAK,QAAQ,GAAG;AAAA,IAClC,OAAO,MAAM,OAAO,GAAG;AAAA;AAAA,EAGX,KAAK,GAAS;AAAA,IAC1B,MAAM,MAAM;AAAA,IACZ,MAAM,SAAS,KAAK;AAAA,IACpB,IAAI,CAAC;AAAA,MAAQ;AAAA,IACb,OAAO,QAAQ,MAAM;AAAA,IACrB,OAAO,SAAS,OAAO,SAAS;AAAA,IAChC,OAAO,UAAU;AAAA,IACjB,OAAO,KAAK,SAAS;AAAA,IACrB,IAAI,OAAO;AAAA,MAAO,aAAa,OAAO,KAAK;AAAA,IAC3C,OAAO,QAAQ;AAAA,IACf,OAAO,WAAW;AAAA;AAAA,MAGF,IAAI,GAAW;AAAA,IAC/B,KAAK,MAAM;AAAA,IACX,OAAO,MAAM;AAAA;AAAA,EAGD,OAAO,GAAwB;AAAA,IAC3C,KAAK,MAAM;AAAA,IACX,OAAO,MAAM,QAAQ;AAAA;AAAA,EAGT,IAAI,GAAmB;AAAA,IACnC,KAAK,MAAM;AAAA,IACX,OAAO,MAAM,KAAK;AAAA;AAAA,EAGN,MAAM,GAAmB;AAAA,IACrC,KAAK,MAAM;AAAA,IACX,OAAO,MAAM,OAAO;AAAA;AAAA,GAGP,OAAO,SAAS,GAAwB;AAAA,IACrD,OAAO,KAAK,QAAQ;AAAA;AAAA,EAGR,OAAO,CACnB,UACA,SACI;AAAA,IACJ,KAAK,MAAM;AAAA,IACX,MAAM,QAAQ,UAAU,OAAO;AAAA;AAAA,EAI5B,YAAY,CAAC,KAA4B;AAAA,IAC5C,IAAI,KAAK,aAAa,GAAG;AAAA,MAAG;AAAA,IAC5B,MAAM,QAAQ,KAAK,SAAS,QAAQ,IAAI,GAAG;AAAA,IAC3C,OAAO,SAAS,MAAM,WAAW,IAC3B,KAAK,IAAI,GAAG,MAAM,WAAW,KAAK,IAAI,CAAC,IACvC;AAAA;AAAA,EAIH,KAAK,GAAW;AAAA,IACnB,IAAI,CAAC,KAAK,WAAW,KAAK,QAAQ,KAAK,WAAW;AAAA,MAAG,OAAO;AAAA,IAC5D,MAAM,MAAM,KAAK,IAAI;AAAA,IACrB,IAAI,UAAU;AAAA,IACd,MAAM,UAAoB,CAAC;AAAA,IAC3B,OAAO,KAAK,cAAc,KAAK,KAAK;AAAA,MAChC,MAAM,MAAM,KAAK,SAAS;AAAA,MAC1B,QAAQ,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,GAAG,CAAE,CAAC;AAAA,MAC3C,KAAK,QAAQ,IAAI,GAAG;AAAA,MACpB;AAAA,IACJ;AAAA,IACA,KAAK,QAAS,WAAW;AAAA,IACzB,KAAK,OAAO;AAAA,IACZ,YAAY,KAAK,UAAU;AAAA,MAAS,KAAK,QAAQ,KAAK,OAAO,SAAS;AAAA,IACtE,OAAO;AAAA;AAAA,EAIX,YAAY,CAAC,KAAiB;AAAA,IAC1B,MAAM,QAAQ,KAAK,SAAS,QAAQ,IAAI,GAAG;AAAA,IAC3C,IAAI,CAAC,SAAS,MAAM,WAAW,KAAK,MAAM,WAAW,KAAK,IAAI;AAAA,MAC1D,OAAO;AAAA,IACX,KAAK,QAAQ,KAAK;AAAA,IAClB,OAAO;AAAA;AAAA,EAGX,OAAO,CAAC,OAA0B;AAAA,IAC9B,MAAM,QAAQ,MAAM,IAAI,MAAM,GAAG;AAAA,IACjC,KAAK,QAAQ,MAAM,GAAG;AAAA,IACtB,KAAK,QAAS;AAAA,IACd,KAAK,QAAQ,MAAM,KAAK,OAAO,SAAS;AAAA;AAAA,EAG5C,OAAO,CAAC,KAAc;AAAA,IAClB,KAAK,QAAQ,GAAG;AAAA,IAChB,MAAM,OAAO,GAAG;AAAA;AAAA,EAIpB,OAAO,CAAC,KAAc;AAAA,IAClB,MAAM,SAAS,KAAK;AAAA,IACpB,MAAM,QAAQ,OAAO,QAAQ,IAAI,GAAG;AAAA,IACpC,IAAI,CAAC;AAAA,MAAO;AAAA,IACZ,IAAI,MAAM;AAAA,MAAO,KAAK,QAAQ,QAAQ,KAAK;AAAA,IAC3C,OAAO,QAAQ,OAAO,GAAG;AAAA;AAAA,EAU7B,MAAM,CACF,KACA,OACA,QACA,UACI;AAAA,IACJ,MAAM,SAAS,KAAK;AAAA,IACpB,MAAM,MAAM,OAAO,YAAY;AAAA,IAC/B,IAAI,QAAQ;AAAA,IACZ,IAAI;AAAA,MAAO,MAAM,QAAQ;AAAA,IACzB,IAAI,WAAW,WAAW;AAAA,MACtB,IAAI,SAAS,MAAM,WAAW,GAAG;AAAA,QAE7B,IAAI;AAAA,UAAK,QAAQ,KAAK,SAAS,QAAQ,OAAO,GAAG,CAAC;AAAA,QAC7C;AAAA,UACD,KAAK,QAAQ,GAAG;AAAA,UAChB;AAAA;AAAA,MAER;AAAA,MACA,IAAI,CAAC,SAAS,KAAK;AAAA,QACf,QAAQ,KAAK,QAAQ,KAAK,OAAO,GAAG,CAAC;AAAA,QACrC,OAAO,QAAQ,IAAI,KAAK,KAAK;AAAA,MACjC;AAAA,MACA,IAAI;AAAA,QAAO,KAAK,SAAS,QAAQ,KAAK;AAAA,MACtC;AAAA,IACJ;AAAA,IACA,MAAM,WAAW,KAAK,IAAI,IAAI;AAAA,IAC9B,IAAI,SAAS,MAAM,WAAW,GAAG;AAAA,MAC7B,MAAM,WAAW;AAAA,MACjB,MAAM,SAAS;AAAA,MACf,IAAI,WAAW,MAAM;AAAA,QAEjB,QAAQ,KAAK,SAAS,QAAQ,OAAO,QAAQ,QAAQ;AAAA,MACpD;AAAA,QACD,IAAI,MAAM;AAAA,UAAO,KAAK,SAAS,QAAQ,KAAK;AAAA,QAC5C;AAAA;AAAA,IAER,EAAO,SAAI,OAAO;AAAA,MACd,MAAM,SAAS;AAAA,MACf,MAAM,WAAW,MAAM,QAAQ;AAAA,IACnC,EAAO;AAAA,MACH,QAAQ,KAAK,QAAQ,KAAK,OAAO,QAAQ,QAAQ;AAAA,MACjD,OAAO,QAAQ,IAAI,KAAK,KAAK;AAAA;AAAA,IAEjC,IAAI;AAAA,MAAK,KAAK,SAAS,QAAQ,KAAK;AAAA,IACpC,KAAK,UAAU,KAAK;AAAA,IACpB,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,QAAQ,OAAO;AAAA,MAAG,KAAK,SAAS;AAAA,IAEpE,IAAI,OAAO,UAAU,aAAa,WAAW,OAAO;AAAA,MAChD,KAAK,OAAO;AAAA;AAAA,EAGpB,OAAO,CAAC,KAAQ,OAAU,QAAgB,UAA+B;AAAA,IACrE,OAAO;AAAA,MACH;AAAA,MACA;AAAA,MACA,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,OAAO;AAAA,IACX;AAAA;AAAA,EAIJ,QAAQ,CACJ,QACA,KACA,QACA,UACW;AAAA,IACX,MAAM,QAAqB;AAAA,SACpB;AAAA,MACH;AAAA,MACA;AAAA,MACA,OAAO;AAAA,IACX;AAAA,IACA,IAAI,IAAI,OAAO;AAAA,MACX,IAAI,IAAI;AAAA,QAAO,IAAI,MAAM,QAAQ;AAAA,MAC5B;AAAA,eAAO,SAAS;AAAA,MACrB,IAAI,IAAI;AAAA,QAAO,IAAI,MAAM,QAAQ;AAAA,MAC5B;AAAA,eAAO,SAAS;AAAA,IACzB;AAAA,IACA,OAAO,QAAQ,IAAI,IAAI,KAAK,KAAK;AAAA,IACjC,OAAO;AAAA;AAAA,EAIX,QAAQ,CAAC,QAAsB,OAA0B;AAAA,IACrD,IAAI,UAAU,OAAO;AAAA,MAAQ;AAAA,IAC7B,IAAI,MAAM;AAAA,MAAO,KAAK,QAAQ,QAAQ,OAAO,IAAI;AAAA,IAC5C;AAAA,MACD,MAAM,QAAQ;AAAA,MACd,OAAO;AAAA;AAAA,IAEX,MAAM,QAAQ,OAAO;AAAA,IACrB,MAAM,QAAQ;AAAA,IACd,IAAI,OAAO;AAAA,MAAQ,OAAO,OAAO,QAAQ;AAAA,IACpC;AAAA,aAAO,SAAS;AAAA,IACrB,OAAO,SAAS;AAAA;AAAA,EAIpB,OAAO,CAAC,QAAsB,OAAoB,YAAY,OAAa;AAAA,IACvE,IAAI,MAAM;AAAA,MAAO,MAAM,MAAM,QAAQ,MAAM;AAAA,IACtC;AAAA,aAAO,SAAS,MAAM;AAAA,IAC3B,IAAI,MAAM;AAAA,MAAO,MAAM,MAAM,QAAQ,MAAM;AAAA,IACtC;AAAA,aAAO,SAAS,MAAM;AAAA,IAC3B,MAAM,QAAQ,MAAM,QAAQ;AAAA,IAC5B,IAAI,CAAC,WAAW;AAAA,MACZ,MAAM,QAAQ;AAAA,MACd,OAAO;AAAA,IACX;AAAA;AAAA,EAQJ,QAAQ,GAAS;AAAA,IACb,MAAM,UAEE,KAAK,YAGP,OAAO,YAAY;AAAA,IACzB,OAAO,IAAI;AAAA;AAAA,EAGf,OAAO,CAAC,KAAQ,OAAU,QAA8B;AAAA,IACpD,MAAM,UAAU,KAAK,SAAS;AAAA,IAC9B,IAAI,CAAC;AAAA,MAAS;AAAA,IACd,IAAI;AAAA,MACA,QAAQ,KAAK,OAAO,MAAM;AAAA,MAC5B,MAAM;AAAA;AAAA,EAMZ,WAAW,GAAS;AAAA,IAChB,MAAM,SAAS,KAAK;AAAA,IACpB,MAAM,MAAM,OAAO;AAAA,IACnB,IAAI,QAAQ;AAAA,MAAW;AAAA,IAEvB,IACI,OAAO,UAAU,OACjB,OAAO,KAAK,SAAS,KACrB,OAAO,KAAK,GAAI,SAAS,KAAK,IAAI;AAAA,MAElC,KAAK,MAAM;AAAA,IACf,OAAO,OAAO,UAAU,KAAK;AAAA,MACzB,MAAM,SAAS,OAAO;AAAA,MACtB,MAAM,QAAQ,OAAO,UAAU,MAAM,IAAI,OAAO,GAAG,IAAI;AAAA,MAGvD,MAAM,OAAO,OAAO;AAAA,MACpB,OAAO,SAAS;AAAA,MAChB,IAAI;AAAA,QAAM,KAAK,QAAQ;AAAA,MAClB;AAAA,eAAO,SAAS;AAAA,MACrB,OAAO,QAAQ;AAAA,MACf,OAAO,QAAQ;AAAA,MACf,OAAO;AAAA,MACP,OAAO,QAAQ,OAAO,OAAO,GAAG;AAAA,MAChC,MAAM,OAAO,OAAO,GAAG;AAAA,MACvB,OAAO;AAAA,MACP,IAAI,OAAO;AAAA,QAAS,KAAK,QAAQ,OAAO,KAAK,OAAY,SAAS;AAAA,IACtE;AAAA;AAAA,EAGJ,aAAa,GAAW;AAAA,IACpB,MAAM,SAAS,KAAK;AAAA,IACpB,UAAS;AAAA,MACL,MAAM,MAAM,OAAO,KAAK;AAAA,MACxB,IAAI,QAAQ;AAAA,QAAW,OAAO;AAAA,MAC9B,IAAI,OAAO,QAAQ,IAAI,IAAI,GAAG,MAAM,KAAK;AAAA,QACrC,KAAK,SAAS;AAAA,QACd;AAAA,MACJ;AAAA,MACA,IAAI,IAAI,aAAa,IAAI;AAAA,QAAO,OAAO,IAAI;AAAA,MAE3C,KAAK,SAAS;AAAA,MACd,IAAI,QAAQ,IAAI;AAAA,MAChB,KAAK,UAAU,GAAG;AAAA,IACtB;AAAA;AAAA,EAGJ,QAAQ,GAAS;AAAA,IACb,MAAM,SAAS,KAAK;AAAA,IACpB,MAAM,OAAO,OAAO,KAAK,OACrB,CAAC,UAAU,OAAO,QAAQ,IAAI,MAAM,GAAG,MAAM,KACjD;AAAA,IACA,OAAO,KAAK,SAAS;AAAA,IACrB,WAAW,SAAS;AAAA,MAAM,KAAK,UAAU,KAAK;AAAA;AAAA,EAGlD,MAAM,GAAS;AAAA,IACX,MAAM,IAAI,KAAK;AAAA,IACf,MAAM,WAAW,KAAK,cAAc;AAAA,IACpC,IAAI,EAAE,UAAU,aAAa,YAAY,EAAE;AAAA,MAAU;AAAA,IACrD,IAAI,EAAE;AAAA,MAAO,aAAa,EAAE,KAAK;AAAA,IACjC,EAAE,QAAQ;AAAA,IACV,EAAE,WAAW;AAAA,IACb,IAAI,aAAa;AAAA,MAAU;AAAA,IAC3B,EAAE,QAAQ,WACN,MAAM;AAAA,MACF,EAAE,QAAQ;AAAA,MACV,EAAE,WAAW;AAAA,MACb,KAAK,MAAM;AAAA,OAEf,KAAK,IAAI,GAAG,WAAW,KAAK,IAAI,CAAC,CACrC;AAAA,IAEC,EAAE,MAAiC,QAAQ;AAAA;AAAA,EAGhD,SAAS,CAAC,OAA0B;AAAA,IAChC,MAAM,OAAO,KAAK,QAAS;AAAA,IAC3B,IAAI,IAAI,KAAK;AAAA,IACb,KAAK,KAAK,KAAK;AAAA,IACf,OAAO,IAAI,GAAG;AAAA,MACV,MAAM,SAAU,IAAI,KAAM;AAAA,MAC1B,MAAM,QAAQ,KAAK;AAAA,MACnB,IAAI,MAAM,SAAS,MAAM;AAAA,QAAO;AAAA,MAChC,KAAK,KAAK;AAAA,MACV,IAAI;AAAA,IACR;AAAA,IACA,KAAK,KAAK;AAAA;AAAA,EAGd,QAAQ,GAA4B;AAAA,IAChC,MAAM,OAAO,KAAK,QAAS;AAAA,IAC3B,MAAM,MAAM,KAAK;AAAA,IACjB,MAAM,OAAO,KAAK,IAAI;AAAA,IACtB,IAAI,QAAQ,aAAa,KAAK,WAAW;AAAA,MAAG,OAAO;AAAA,IACnD,IAAI,IAAI;AAAA,IACR,UAAS;AAAA,MACL,IAAI,QAAQ,IAAI,IAAI;AAAA,MACpB,IAAI,SAAS,KAAK;AAAA,QAAQ;AAAA,MAC1B,IACI,QAAQ,IAAI,KAAK,UACjB,KAAK,QAAQ,GAAI,QAAQ,KAAK,OAAQ;AAAA,QAEtC;AAAA,MACJ,IAAI,KAAK,OAAQ,SAAS,KAAM;AAAA,QAAO;AAAA,MACvC,KAAK,KAAK,KAAK;AAAA,MACf,IAAI;AAAA,IACR;AAAA,IACA,KAAK,KAAK;AAAA,IACV,OAAO;AAAA;AAAA,EAIJ,KAAK,GAAkB;AAAA,IAC1B,WAAW,SAAS,KAAK,OAAO;AAAA,MAAG,OAAO;AAAA,IAC1C;AAAA;AAAA,EAGG,QAAQ,GAAkB;AAAA,IAC7B,WAAW,OAAO,KAAK,KAAK;AAAA,MAAG,OAAO;AAAA,IACtC;AAAA;AAAA,EAGG,IAAI,GAAkB;AAAA,IACzB,IAAI;AAAA,IACJ,WAAW,QAAQ,KAAK,OAAO;AAAA,MAAG,QAAQ;AAAA,IAC1C,OAAO;AAAA;AAAA,EAGJ,OAAO,GAAkB;AAAA,IAC5B,IAAI;AAAA,IACJ,WAAW,QAAQ,KAAK,KAAK;AAAA,MAAG,MAAM;AAAA,IACtC,OAAO;AAAA;AAAA,EAGJ,IAAI,CACP,WACa;AAAA,IACb,YAAY,KAAK,UAAU,MAAM;AAAA,MAC7B,IAAI,UAAU,OAAO,KAAK,IAAI;AAAA,QAAG,OAAO;AAAA,IAC5C;AAAA,IACA;AAAA;AAAA,EAGG,QAAQ,CACX,WACa;AAAA,IACb,MAAM,OAAO,KAAK,SAAS;AAAA,IAC3B,MAAM,SAAS,KAAK,MAAM;AAAA,IAC1B,SAAS,IAAI,OAAO,SAAS,EAAG,KAAK,GAAG;AAAA,MACpC,IAAI,UAAU,OAAO,IAAK,KAAK,IAAK,IAAI;AAAA,QAAG,OAAO,OAAO;AAAA,IAC7D;AAAA;AAAA,EAGG,WAAW,CACd,WACa;AAAA,IACb,MAAM,OAAO,KAAK,SAAS;AAAA,IAC3B,MAAM,SAAS,KAAK,MAAM;AAAA,IAC1B,SAAS,IAAI,OAAO,SAAS,EAAG,KAAK,GAAG;AAAA,MACpC,IAAI,UAAU,OAAO,IAAK,KAAK,IAAK,IAAI;AAAA,QAAG,OAAO,KAAK;AAAA,IAC3D;AAAA;AAAA,EAGG,MAAM,CACT,WACI;AAAA,IACJ,MAAM,SAAS,KAAK,SAAS;AAAA,IAE7B,KAAK,QAAQ,CAAC,OAAO,QAAQ;AAAA,MACzB,IAAI,UAAU,OAAO,KAAK,IAAI;AAAA,QAAG,OAAO,IAAI,KAAK,KAAK;AAAA,KACzD;AAAA,IACD,OAAO;AAAA;AAAA,EAGJ,GAAM,CAAC,WAA2D;AAAA,IACrE,MAAM,SAAc,CAAC;AAAA,IACrB,KAAK,QAAQ,CAAC,OAAO,QAAQ;AAAA,MACzB,OAAO,KAAK,UAAU,OAAO,KAAK,IAAI,CAAC;AAAA,KAC1C;AAAA,IACD,OAAO;AAAA;AAAA,EAGJ,IAAI,CACP,WACO;AAAA,IACP,YAAY,KAAK,UAAU,MAAM;AAAA,MAC7B,IAAI,UAAU,OAAO,KAAK,IAAI;AAAA,QAAG,OAAO;AAAA,IAC5C;AAAA,IACA,OAAO;AAAA;AAAA,EAGJ,KAAK,CACR,WACO;AAAA,IACP,YAAY,KAAK,UAAU,MAAM;AAAA,MAC7B,IAAI,CAAC,UAAU,OAAO,KAAK,IAAI;AAAA,QAAG,OAAO;AAAA,IAC7C;AAAA,IACA,OAAO;AAAA;AAAA,EAGJ,IAAI,CACP,UACI;AAAA,IACJ,KAAK,QAAQ,CAAC,OAAO,QAAQ;AAAA,MACzB,SAAS,OAAO,KAAK,IAAI;AAAA,KAC5B;AAAA,IACD,OAAO;AAAA;AAAA,EAGJ,KAAK,GAAQ;AAAA,IAChB,OAAO,CAAC,GAAG,KAAK,OAAO,CAAC;AAAA;AAAA,EAGrB,QAAQ,GAAQ;AAAA,IACnB,OAAO,CAAC,GAAG,KAAK,KAAK,CAAC;AAAA;AAAA,EAGnB,YAAY,GAAa;AAAA,IAC5B,OAAO,CAAC,GAAG,KAAK,QAAQ,CAAC;AAAA;AAAA,EAGtB,KAAK,GAAS;AAAA,IACjB,MAAM,OAAO,KAAK,SAAS;AAAA,IAC3B,KAAK,QAAQ,CAAC,OAAO,QAAQ;AAAA,MACzB,KAAK,IAAI,KAAK,KAAK;AAAA,KACtB;AAAA,IACD,OAAO;AAAA;AAAA,EAGJ,MAAM,IAAI,MAAoB;AAAA,IACjC,SAAS,IAAI,EAAG,IAAI,KAAK,QAAQ,KAAK;AAAA,MAClC,IAAI,CAAC,KAAK,IAAI,KAAK,EAAG;AAAA,QAAG,OAAO;AAAA,IACpC;AAAA,IACA,OAAO;AAAA;AAAA,EAGJ,MAAM,IAAI,MAAoB;AAAA,IACjC,SAAS,IAAI,EAAG,IAAI,KAAK,QAAQ,KAAK;AAAA,MAClC,IAAI,KAAK,IAAI,KAAK,EAAG;AAAA,QAAG,OAAO;AAAA,IACnC;AAAA,IACA,OAAO;AAAA;AAAA,EAGJ,OAAO,CACV,WACa;AAAA,IACb,YAAY,KAAK,UAAU,MAAM;AAAA,MAC7B,IAAI,UAAU,OAAO,KAAK,IAAI;AAAA,QAAG,OAAO;AAAA,IAC5C;AAAA,IACA;AAAA;AAAA,EAGG,SAAS,CACZ,WACO;AAAA,IACP,OAAO,KAAK,KAAK,SAAS;AAAA;AAAA,EAGvB,KAAK,CACR,WACM;AAAA,IACN,IAAI,UAAU;AAAA,IACd,YAAY,KAAK,UAAU,MAAM;AAAA,MAC7B,IAAI,UAAU,OAAO,KAAK,IAAI,KAAK,KAAK,OAAO,GAAG;AAAA,QAAG;AAAA,IACzD;AAAA,IACA,OAAO;AAAA;AAAA,EAGJ,UAAU,GAAuB;AAAA,IACpC,YAAY,KAAK,UAAU;AAAA,MAAM,OAAO,CAAC,KAAK,KAAK;AAAA,IACnD;AAAA;AAAA,EAGG,SAAS,GAAuB;AAAA,IACnC,IAAI;AAAA,IACJ,WAAW,QAAQ;AAAA,MAAM,QAAQ,CAAC,KAAK,IAAI,KAAK,EAAE;AAAA,IAClD,OAAO;AAAA;AAAA,EAGJ,KAAK,CAAC,OAAuC;AAAA,IAChD,MAAM,SAAS,KAAK,MAAM;AAAA,IAC1B,YAAY,KAAK,UAAU;AAAA,MAAO,OAAO,IAAI,KAAK,KAAK;AAAA,IACvD,OAAO;AAAA;AAAA,EAGJ,YAAY,CAAC,OAAuC;AAAA,IACvD,MAAM,SAAS,KAAK,SAAS;AAAA,IAC7B,YAAY,KAAK,UAAU,MAAM;AAAA,MAC7B,IAAI,MAAM,IAAI,GAAG;AAAA,QAAG,OAAO,IAAI,KAAK,KAAK;AAAA,IAC7C;AAAA,IACA,OAAO;AAAA;AAAA,EAGJ,UAAU,CAAC,OAAuC;AAAA,IACrD,MAAM,SAAS,KAAK,SAAS;AAAA,IAC7B,YAAY,KAAK,UAAU,MAAM;AAAA,MAC7B,IAAI,CAAC,MAAM,IAAI,GAAG;AAAA,QAAG,OAAO,IAAI,KAAK,KAAK;AAAA,IAC9C;AAAA,IACA,OAAO;AAAA;AAAA,EAKJ,SAAS,CACZ,WACY;AAAA,IACZ,MAAM,OAAO,KAAK,SAAS;AAAA,IAC3B,MAAM,OAAO,KAAK,SAAS;AAAA,IAC3B,YAAY,KAAK,UAAU,MAAM;AAAA,MAC7B,IAAI,UAAU,OAAO,KAAK,IAAI;AAAA,QAAG,KAAK,IAAI,KAAK,KAAK;AAAA,MAC/C;AAAA,aAAK,IAAI,KAAK,KAAK;AAAA,IAC5B;AAAA,IACA,OAAO,CAAC,MAAM,IAAI;AAAA;AAAA,EAGf,mBAAmB,CAAC,OAAuC;AAAA,IAC9D,MAAM,SAAS,KAAK,SAAS;AAAA,IAC7B,YAAY,KAAK,UAAU;AAAA,MACvB,IAAI,CAAC,MAAM,IAAI,GAAG;AAAA,QAAG,OAAO,IAAI,KAAK,KAAK;AAAA,IAC9C,YAAY,KAAK,UAAU;AAAA,MACvB,IAAI,CAAC,KAAK,IAAI,GAAG;AAAA,QAAG,OAAO,IAAI,KAAK,KAAK;AAAA,IAC7C,OAAO;AAAA;AAAA,EAGJ,MAAM,IAAI,aAA+C;AAAA,IAC5D,MAAM,SAAS,KAAK,MAAM;AAAA,IAC1B,WAAW,cAAc;AAAA,MACrB,YAAY,KAAK,UAAU;AAAA,QAAY,OAAO,IAAI,KAAK,KAAK;AAAA,IAChE,OAAO;AAAA;AAAA,EASJ,KAAW,CACd,OACA,YACA,aACA,YACgB;AAAA,IAChB,MAAM,SAAS,KAAK,SAAS;AAAA,IAC7B,MAAM,SAAS,CAAC,KAAQ,SAAwB;AAAA,MAC5C,IAAI,KAAK;AAAA,QAAM,OAAO,IAAI,KAAK,KAAK,KAAK;AAAA;AAAA,IAE7C,YAAY,KAAK,UAAU,MAAM;AAAA,MAC7B,OACI,KACA,MAAM,IAAI,GAAG,IACP,WAAW,OAAO,OAAO,OAAO,GAAG,GAAQ,GAAG,IAC9C,WAAW,OAAO,GAAG,CAC/B;AAAA,IACJ;AAAA,IACA,YAAY,KAAK,UAAU;AAAA,MACvB,IAAI,CAAC,KAAK,IAAI,GAAG;AAAA,QAAG,OAAO,KAAK,YAAY,OAAO,GAAG,CAAC;AAAA,IAC3D,OAAO;AAAA;AAAA,EAGJ,MAAM,CAAC,OAA6D;AAAA,IACvE,IAAI,CAAC;AAAA,MAAO,OAAO;AAAA,IACnB,IAAI,UAAW;AAAA,MAAkB,OAAO;AAAA,IACxC,IAAI,KAAK,SAAS,MAAM;AAAA,MAAM,OAAO;AAAA,IACrC,YAAY,KAAK,UAAU,MAAM;AAAA,MAC7B,IAAI,CAAC,MAAM,IAAI,GAAG;AAAA,QAAG,OAAO;AAAA,MAC5B,IAAI,UAAU,OAAO,OAAO,GAAG;AAAA,QAAG,OAAO;AAAA,IAC7C;AAAA,IACA,OAAO;AAAA;AAAA,EAGJ,SAAY,CACf,WACgB;AAAA,IAChB,MAAM,SAAS,KAAK,SAAS;AAAA,IAC7B,YAAY,KAAK,UAAU;AAAA,MACvB,OAAO,IAAI,KAAK,UAAU,OAAO,KAAK,IAAI,CAAC;AAAA,IAC/C,OAAO;AAAA;AAAA,EAGJ,UAAU,GAAS;AAAA,IACtB,MAAM,SAAS,KAAK,SAAS;AAAA,IAC7B,MAAM,UAAU,CAAC,GAAG,IAAI;AAAA,IACxB,SAAS,IAAI,QAAQ,SAAS,EAAG,KAAK,GAAG;AAAA,MACrC,OAAO,IAAI,QAAQ,GAAI,IAAI,QAAQ,GAAI,EAAE;AAAA,IAC7C,OAAO;AAAA;AAAA,EAGJ,QAAQ,CACX,YACI;AAAA,IACJ,OAAO,KAAK,OAAO,UAAU;AAAA;AAAA,SAOV,OAAa,CAChC,OACA,aACkB;AAAA,IAClB,MAAM,SAAS,IAAI;AAAA,IACnB,IAAI,QAAQ;AAAA,IACZ,WAAW,QAAQ;AAAA,MACf,OAAO,OAAO,YAAY,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,EAAE,KAAK,IAAI;AAAA,IACjE,OAAO;AAAA;AAAA,SAMG,cAAoB,CAC9B,SACA,SACgB;AAAA,IAChB,MAAM,SAAS,IAAI;AAAA,IACnB,YAAY,KAAK,UAAU;AAAA,MACvB,OAAO,IACH,KACA,OAAO,IAAI,GAAG,IAAI,QAAQ,OAAO,IAAI,GAAG,GAAI,OAAO,GAAG,IAAI,KAC9D;AAAA,IACJ,OAAO;AAAA;AAAA,EAKJ,GAAG,CAAC,IAAyC;AAAA,IAChD,GAAG,IAAI;AAAA,IACP,OAAO;AAAA;AAAA,EAGJ,OAAU,CACb,WACG;AAAA,IACH,MAAM,SAAc,CAAC;AAAA,IACrB,YAAY,KAAK,UAAU,MAAM;AAAA,MAC7B,WAAW,QAAQ,UAAU,OAAO,KAAK,IAAI;AAAA,QAAG,OAAO,KAAK,IAAI;AAAA,IACpE;AAAA,IACA,OAAO;AAAA;AAAA,EAGJ,MAAS,CACZ,IACA,cACC;AAAA,IACD,IAAI,MAAM;AAAA,IACV,YAAY,KAAK,UAAU;AAAA,MAAM,MAAM,GAAG,KAAK,OAAO,KAAK,IAAI;AAAA,IAC/D,OAAO;AAAA;AAAA,EAGJ,WAAc,CACjB,IACA,cACC;AAAA,IACD,MAAM,UAAU,CAAC,GAAG,IAAI;AAAA,IACxB,IAAI,MAAM;AAAA,IACV,SAAS,IAAI,QAAQ,SAAS,EAAG,KAAK,GAAG;AAAA,MACrC,MAAM,GAAG,KAAK,QAAQ,GAAI,IAAI,QAAQ,GAAI,IAAI,IAAI;AAAA,IACtD,OAAO;AAAA;AAAA,EAKJ,MAAM,CAAC,YAA6D;AAAA,IAIvE,MAAM,YAAY,CAAC,GAAG,KAAK,QAAQ,CAAC,EAAE,IAAI,CAAC,OAAO,WAAW;AAAA,MACzD;AAAA,MACA;AAAA,IACJ,EAAE;AAAA,IACF,IAAI;AAAA,MACA,UAAU,KAAK,CAAC,GAAG,MAAM;AAAA,QACrB,MAAM,aAAa,WACf,EAAE,MAAM,IACR,EAAE,MAAM,IACR,EAAE,MAAM,IACR,EAAE,MAAM,EACZ;AAAA,QACA,OAAO,eAAe,IAAI,aAAa,EAAE,QAAQ,EAAE;AAAA,OACtD;AAAA,IACL,MAAM,SAAS,KAAK,SAAS;AAAA,IAC7B,aAAa,WAAW;AAAA,MAAW,OAAO,IAAI,MAAM,IAAI,MAAM,EAAE;AAAA,IAChE,OAAO;AAAA;AAAA,EAaJ,MAAM,CAAC,QAAsC;AAAA,IAChD,IAAI,WAAW;AAAA,MAAW,OAAO,OAAO,CAAC,GAAG,KAAK,OAAO,CAAC,GAAG,MAAM;AAAA,IAClE,MAAM,OAAO,KAAK;AAAA,IAClB,IAAI,SAAS;AAAA,MAAG;AAAA,IAChB,IAAI,QAAQ,KAAK,MAAM,KAAK,OAAO,IAAI,IAAI;AAAA,IAC3C,WAAW,SAAS,KAAK,OAAO;AAAA,MAAG,IAAI,YAAY;AAAA,QAAG,OAAO;AAAA,IAC7D;AAAA;AAAA,EASG,SAAS,CAAC,QAAsC;AAAA,IACnD,IAAI,WAAW;AAAA,MAAW,OAAO,OAAO,CAAC,GAAG,KAAK,KAAK,CAAC,GAAG,MAAM;AAAA,IAChE,MAAM,OAAO,KAAK;AAAA,IAClB,IAAI,SAAS;AAAA,MAAG;AAAA,IAChB,IAAI,QAAQ,KAAK,MAAM,KAAK,OAAO,IAAI,IAAI;AAAA,IAC3C,WAAW,OAAO,KAAK,KAAK;AAAA,MAAG,IAAI,YAAY;AAAA,QAAG,OAAO;AAAA,IACzD;AAAA;AAAA,EAGG,EAAE,CAAC,OAA8B;AAAA,IACpC,IAAI,YAAY,QAAQ,IAAI,KAAK,OAAO,QAAQ;AAAA,IAChD,IAAI,YAAY;AAAA,MAAG;AAAA,IACnB,WAAW,SAAS,KAAK,OAAO;AAAA,MAAG,IAAI,gBAAgB;AAAA,QAAG,OAAO;AAAA,IACjE;AAAA;AAAA,EAGG,KAAK,CAAC,OAA8B;AAAA,IACvC,IAAI,YAAY,QAAQ,IAAI,KAAK,OAAO,QAAQ;AAAA,IAChD,IAAI,YAAY;AAAA,MAAG;AAAA,IACnB,WAAW,OAAO,KAAK,KAAK;AAAA,MAAG,IAAI,gBAAgB;AAAA,QAAG,OAAO;AAAA,IAC7D;AAAA;AAAA,EAGG,MAAM,GAAa;AAAA,IACtB,OAAO,CAAC,GAAG,KAAK,QAAQ,CAAC;AAAA;AAEjC;",
10
+ "debugId": "8859F4CE73F8594764756E2164756E21",
10
11
  "names": []
11
12
  }
@@ -0,0 +1,98 @@
1
+ import type { CollectionStats, EvictionReason } from "./index.js";
2
+ /** Anything that runs one Redis command: `Bun.RedisClient` as it is, or an adapter. */
3
+ export interface RedisCommandClient {
4
+ send(command: string, args: string[]): Promise<unknown>;
5
+ }
6
+ /** Turns values into strings for Redis and back. */
7
+ export interface RedisSerializer<V> {
8
+ serialize(value: V): string;
9
+ deserialize(raw: string): V;
10
+ }
11
+ /** Options for {@link RedisCollection}. */
12
+ export interface RedisCollectionOptions<V> {
13
+ /** The Redis client. `Bun.RedisClient` works as it is; for ioredis pass `{ send: (c, a) => redis.call(c, ...a) }`. */
14
+ client: RedisCommandClient;
15
+ /** The collection's name: every process using the same name and prefix shares it. */
16
+ name: string;
17
+ /** Key prefix. Default `"lunibee:collection:"`; keys are versioned under it (`…v1:…`). */
18
+ prefix?: string;
19
+ /** Default TTL in ms for `set()`. Omit for no expiry. */
20
+ ttl?: number;
21
+ /** Whether a `get()` restarts a TTL entry's window. Default `true`. */
22
+ slide?: boolean;
23
+ /** Most entries; the least recently used (across every process) are evicted past it. */
24
+ maxSize?: number;
25
+ /** Default JSON. Provide one for values JSON cannot carry (bigint, Map, Date…). */
26
+ serializer?: RedisSerializer<V>;
27
+ /** Called when an operation of this instance removes entries automatically. Exceptions are swallowed. */
28
+ onEvict?: (key: string, value: V | undefined, reason: EvictionReason) => void;
29
+ }
30
+ /** `ARGV`: ep, key, payload, ttl (0 none), maxSize (0 none), mode (`set` | `nx`). Returns `{existing|false, ...evictions}`. */
31
+ export declare const SET_SCRIPT = "\nlocal exp, lru, clock, ep = KEYS[1], KEYS[2], KEYS[3], ARGV[1]\nlocal t = redis.call('TIME')\nlocal now = tonumber(t[1]) * 1000 + math.floor(tonumber(t[2]) / 1000)\nlocal out = {}\nlocal function drop(m, reason)\n local v = redis.call('GET', ep .. m)\n redis.call('DEL', ep .. m)\n redis.call('ZREM', exp, m)\n redis.call('ZREM', lru, m)\n if reason then\n table.insert(out, m)\n table.insert(out, v or false)\n table.insert(out, reason)\n end\nend\nlocal gone = redis.call('ZRANGEBYSCORE', exp, '-inf', now, 'LIMIT', 0, 1000)\nfor _, m in ipairs(gone) do drop(m, 'expired') end\nlocal function touch(m) redis.call('ZADD', lru, redis.call('INCR', clock), m) end\n\nlocal m, payload, ttl, max, mode = ARGV[2], ARGV[3], tonumber(ARGV[4]), tonumber(ARGV[5]), ARGV[6]\nif mode == 'nx' then\n local cur = redis.call('GET', ep .. m)\n if cur then\n touch(m)\n table.insert(out, 1, cur)\n return out\n end\nend\nlocal env = ttl .. ':' .. payload\nif ttl > 0 then\n -- The key outlives its logical expiry by a grace second, so the prune\n -- that reports the expiry can still hand the value to onEvict.\n redis.call('SET', ep .. m, env, 'PX', ttl + 1000)\n redis.call('ZADD', exp, now + ttl, m)\nelse\n redis.call('SET', ep .. m, env)\n redis.call('ZREM', exp, m)\nend\ntouch(m)\nif max > 0 then\n local n = redis.call('ZCARD', lru)\n while n > max do\n local popped = redis.call('ZPOPMIN', lru)\n local victim = popped[1]\n if victim == nil then break end\n if victim ~= m then drop(victim, 'evicted') end\n n = n - 1\n end\nend\ntable.insert(out, 1, false)\nreturn out\n";
32
+ /** `ARGV`: ep, key, slide (1/0), touch (1/0). Returns `{envelope|false, ...evictions}`. */
33
+ export declare const GET_SCRIPT = "\nlocal exp, lru, clock, ep = KEYS[1], KEYS[2], KEYS[3], ARGV[1]\nlocal t = redis.call('TIME')\nlocal now = tonumber(t[1]) * 1000 + math.floor(tonumber(t[2]) / 1000)\nlocal out = {}\nlocal function drop(m, reason)\n local v = redis.call('GET', ep .. m)\n redis.call('DEL', ep .. m)\n redis.call('ZREM', exp, m)\n redis.call('ZREM', lru, m)\n if reason then\n table.insert(out, m)\n table.insert(out, v or false)\n table.insert(out, reason)\n end\nend\nlocal gone = redis.call('ZRANGEBYSCORE', exp, '-inf', now, 'LIMIT', 0, 1000)\nfor _, m in ipairs(gone) do drop(m, 'expired') end\nlocal function touch(m) redis.call('ZADD', lru, redis.call('INCR', clock), m) end\n\nlocal m, slide, mark = ARGV[2], ARGV[3], ARGV[4]\nlocal env = redis.call('GET', ep .. m)\nif not env then\n redis.call('ZREM', exp, m)\n redis.call('ZREM', lru, m)\n table.insert(out, 1, false)\n return out\nend\nif mark == '1' then touch(m) end\nif slide == '1' then\n local ttl = tonumber(string.match(env, '^(%d+):'))\n if ttl and ttl > 0 then\n redis.call('PEXPIRE', ep .. m, ttl + 1000)\n redis.call('ZADD', exp, now + ttl, m)\n end\nend\ntable.insert(out, 1, env)\nreturn out\n";
34
+ /** `ARGV`: ep, key. Returns `{1|0, ...evictions}`. */
35
+ export declare const DELETE_SCRIPT = "\nlocal exp, lru, clock, ep = KEYS[1], KEYS[2], KEYS[3], ARGV[1]\nlocal t = redis.call('TIME')\nlocal now = tonumber(t[1]) * 1000 + math.floor(tonumber(t[2]) / 1000)\nlocal out = {}\nlocal function drop(m, reason)\n local v = redis.call('GET', ep .. m)\n redis.call('DEL', ep .. m)\n redis.call('ZREM', exp, m)\n redis.call('ZREM', lru, m)\n if reason then\n table.insert(out, m)\n table.insert(out, v or false)\n table.insert(out, reason)\n end\nend\nlocal gone = redis.call('ZRANGEBYSCORE', exp, '-inf', now, 'LIMIT', 0, 1000)\nfor _, m in ipairs(gone) do drop(m, 'expired') end\nlocal function touch(m) redis.call('ZADD', lru, redis.call('INCR', clock), m) end\n\nlocal m = ARGV[2]\nlocal existed = redis.call('EXISTS', ep .. m)\ndrop(m, nil)\ntable.insert(out, 1, existed)\nreturn out\n";
36
+ /** `ARGV`: ep, what (`size` | `keys` | `clear`). */
37
+ export declare const LIST_SCRIPT = "\nlocal exp, lru, clock, ep = KEYS[1], KEYS[2], KEYS[3], ARGV[1]\nlocal t = redis.call('TIME')\nlocal now = tonumber(t[1]) * 1000 + math.floor(tonumber(t[2]) / 1000)\nlocal out = {}\nlocal function drop(m, reason)\n local v = redis.call('GET', ep .. m)\n redis.call('DEL', ep .. m)\n redis.call('ZREM', exp, m)\n redis.call('ZREM', lru, m)\n if reason then\n table.insert(out, m)\n table.insert(out, v or false)\n table.insert(out, reason)\n end\nend\nlocal gone = redis.call('ZRANGEBYSCORE', exp, '-inf', now, 'LIMIT', 0, 1000)\nfor _, m in ipairs(gone) do drop(m, 'expired') end\nlocal function touch(m) redis.call('ZADD', lru, redis.call('INCR', clock), m) end\n\nlocal what = ARGV[2]\nif what == 'clear' then\n local n = 0\n repeat\n local batch = redis.call('ZRANGE', lru, 0, 999)\n for _, m in ipairs(batch) do drop(m, nil) end\n n = n + #batch\n until #batch == 0\n redis.call('DEL', exp, lru, clock)\n return {n}\nend\nlocal result = what == 'size' and redis.call('ZCARD', lru) or redis.call('ZRANGE', lru, 0, -1)\nreturn {result, unpack(out)}\n";
38
+ /**
39
+ * A key-value collection kept in Redis and shared by every process that opens
40
+ * it with the same `name`, with the retention policy of `Collection`: a TTL
41
+ * (sliding by default), a `maxSize` evicting the least recently used across
42
+ * every process, and `onEvict`.
43
+ *
44
+ * Every operation is one atomic script, so two processes never see a
45
+ * half-applied write. The API is async, and values travel as strings
46
+ * (JSON by default).
47
+ *
48
+ * ```ts
49
+ * const sessions = new RedisCollection<Session>({
50
+ * client: new Bun.RedisClient(process.env.REDIS_URL),
51
+ * name: "sessions",
52
+ * ttl: 15 * 60_000,
53
+ * maxSize: 10_000,
54
+ * });
55
+ * await sessions.set(userId, session);
56
+ * const session = await sessions.get(userId); // from any process
57
+ * ```
58
+ */
59
+ export declare class RedisCollection<V = unknown> {
60
+ #private;
61
+ /** The collection's name. */
62
+ readonly name: string;
63
+ constructor(options: RedisCollectionOptions<V>);
64
+ /** Hits, misses and removals seen by this instance. */
65
+ get stats(): CollectionStats;
66
+ /**
67
+ * The value for `key`, or `undefined`. Marks it recently used and, with
68
+ * `slide`, restarts its TTL window.
69
+ */
70
+ get(key: string | number): Promise<V | undefined>;
71
+ /** The value without marking it used or restarting its window. */
72
+ peek(key: string | number): Promise<V | undefined>;
73
+ /** Whether `key` is present (does not count as a use). */
74
+ has(key: string | number): Promise<boolean>;
75
+ /** Stores `value` with the default TTL, or `ttl` ms (`0`: never expires). */
76
+ set(key: string | number, value: V, ttl?: number): Promise<this>;
77
+ /** Stores `value` with no expiry. It still counts towards `maxSize`. */
78
+ setWithoutTTL(key: string | number, value: V): Promise<this>;
79
+ /**
80
+ * Returns the value for `key`, or stores and returns what `factory`
81
+ * gives. If two processes race, one value wins and both get it.
82
+ */
83
+ ensure(key: string | number, factory: (key: string) => V | Promise<V>, ttl?: number): Promise<V>;
84
+ /** Removes `key`. Returns whether it was present. */
85
+ delete(key: string | number): Promise<boolean>;
86
+ /** Removes every entry. Returns how many there were. */
87
+ clear(): Promise<number>;
88
+ /** Live entries. */
89
+ size(): Promise<number>;
90
+ /** Live keys, least recently used first. */
91
+ keys(): Promise<string[]>;
92
+ /** Live entries, least recently used first. Reading them does not count as a use. */
93
+ entries(): Promise<Array<[string, V]>>;
94
+ /** Live values, least recently used first. */
95
+ values(): Promise<V[]>;
96
+ /** Milliseconds left before `key` expires; `undefined` when it never expires or is absent. */
97
+ ttlRemaining(key: string | number): Promise<number | undefined>;
98
+ }
@@ -21,6 +21,14 @@ export declare class Collector<K, V> extends EventEmitter {
21
21
  ended: boolean;
22
22
  endReason?: string;
23
23
  totalProcessed: number;
24
+ /** `collect` receives each collected item; `end` the collected map and the reason. */
25
+ on(event: "collect", listener: (item: V) => void): this;
26
+ on(event: "end", listener: (collected: Map<K, V>, reason: string) => void): this;
27
+ on(event: string | symbol, listener: (...args: never[]) => void): this;
28
+ /** Like {@link Collector.on}, for one call. */
29
+ once(event: "collect", listener: (item: V) => void): this;
30
+ once(event: "end", listener: (collected: Map<K, V>, reason: string) => void): this;
31
+ once(event: string | symbol, listener: (...args: never[]) => void): this;
24
32
  constructor(options?: CollectorOptions<V>);
25
33
  /** Registers a function to run once when the collector ends. Runs immediately if it already has. */
26
34
  onDispose(cleanup: () => void): this;
@@ -79,6 +79,7 @@ export declare enum ClientEvent {
79
79
  export type ClientEventName = keyof ClientEvents;
80
80
  /** Listener signature for a Lunibee client event. */
81
81
  export type ClientListener<K extends ClientEventName> = (...args: ClientEvents[K]) => unknown;
82
+ /** Every `Client` event name mapped to its listener arguments. */
82
83
  export type ClientEvents = {
83
84
  ready: [user: ClientUser];
84
85
  resumed: [];
@@ -3,6 +3,7 @@ export { ClientEvent,
3
3
  /** Discord.js-familiar alias for {@link ClientEvent}. */
4
4
  ClientEvent as Events, type ClientEventName, type ClientEvents, type ClientListener, } from "./events.js";
5
5
  export { Collector, type CollectorOptions } from "./collector.js";
6
+ export { RedisCache, type RedisCacheOptions, type RedisCacheDiagnostics, type RedisCommandClient, type RawDispatchSource, } from "./redis-cache.js";
6
7
  export { createApi, type Api, type ApplicationNode, type ChannelNode, type GuildNode, type ListRoute, type MemberNode, type MembersRoute, type MessageNode, type MessagesRoute, type PageOptions, type Route, type RouteId, type RouteOptions, type UserNode, type WebhookNode, } from "./api.js";
7
8
  export { command, option, CommandRegistry, type ChannelConfig, type ChoiceConfig, type BooleanConfig, type Command, type CommandContext, type CommandDefinition, type MentionableValue, type NumberConfig, type OptionDef, type OptionMap, type OptionValues, type StringConfig, } from "./commands.js";
8
9
  export { channelCreatePayload, type CreateCategoryChannel, type CreateChannelOptions, type CreateForumChannel, type CreateTextChannel, type CreateVoiceChannel, type ForumTagInput, } from "./channel-create.js";
@@ -34,6 +35,8 @@ declare class EventEmitter<Events extends {
34
35
  off<K extends keyof Events>(event: K, listener: Listener<Events[K]>): this;
35
36
  /** Alias of {@link off}, provided for Node.js/Discord.js familiarity. */
36
37
  removeListener<K extends keyof Events>(event: K, listener: Listener<Events[K]>): this;
38
+ /** Number of listeners for `event`, as Node's `EventEmitter` reports it. */
39
+ listenerCount<K extends keyof Events>(event: K): number;
37
40
  removeAllListeners<K extends keyof Events>(event?: K): this;
38
41
  protected emit<K extends keyof Events>(event: K, ...args: Events[K]): boolean;
39
42
  }