@athrio/loom 0.0.9 → 0.0.10

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.
@@ -0,0 +1,1048 @@
1
+ #!/usr/bin/env node
2
+ import { r as __exportAll } from "./rolldown-runtime-YU9U6SYh.js";
3
+ import { Ao as make$1, Bd as succeedNone, Cm as isExit, Dh as dual, Do as get$1, Ef as merge, Jd as updateContext, Ju as ClockRef, Md as onExit, Mo as set$1, No as size$1, Np as failVoid, Op as map$1, Qp as isSome, Rp as succeed$1, Tp as filterMap, Ud as sync, Vd as succeedSome, Yd as void_, Zp as isNone, _u as makeUnsafe, cf as infinity, du as _await, fd as exitIsFailure, id as catchCause, jd as map, jo as remove, ld as contextWith, lf as isFinite, pd as exitIsSuccess, pf as toMillis, pu as doneUnsafe, rd as asSome, sf as fromInputUnsafe, uf as isZero, wm as withFiber, wo as clear, xm as exitSucceed, ym as PipeInspectableProto, zd as succeed } from "./SqlClient-BHo_uVyk.js";
4
+ //#region ../../node_modules/effect/dist/Cache.js
5
+ /**
6
+ * Caches values loaded by an Effect lookup function.
7
+ *
8
+ * A cache stores successful and failed lookup results, shares an in-progress
9
+ * lookup when multiple callers request the same missing key, and limits entries
10
+ * by capacity and optional time-to-live rules. This module includes helpers for
11
+ * reading, setting, refreshing, invalidating, and inspecting cache contents.
12
+ *
13
+ * @since 4.0.0
14
+ */
15
+ var Cache_exports = /* @__PURE__ */ __exportAll({
16
+ entries: () => entries,
17
+ get: () => get,
18
+ getOption: () => getOption,
19
+ getSuccess: () => getSuccess,
20
+ has: () => has,
21
+ invalidate: () => invalidate,
22
+ invalidateAll: () => invalidateAll,
23
+ invalidateWhen: () => invalidateWhen,
24
+ keys: () => keys,
25
+ make: () => make,
26
+ makeWith: () => makeWith,
27
+ refresh: () => refresh,
28
+ set: () => set,
29
+ size: () => size,
30
+ values: () => values
31
+ });
32
+ var TypeId = "~effect/Cache";
33
+ /**
34
+ * Creates a cache with dynamic time-to-live based on the result and key.
35
+ *
36
+ * **When to use**
37
+ *
38
+ * Use when you need different cache entry lifetimes based on the lookup result
39
+ * or key characteristics.
40
+ *
41
+ * **Details**
42
+ *
43
+ * The timeToLive function receives both the exit result and the key, allowing
44
+ * for flexible TTL policies based on success/failure state and key characteristics.
45
+ *
46
+ * **Example** (Configuring dynamic time to live)
47
+ *
48
+ * ```ts
49
+ * import { Cache, Effect, Exit } from "effect"
50
+ *
51
+ * // Cache with TTL based on computed value
52
+ * const userCache = Effect.gen(function*() {
53
+ * const cache = yield* Cache.makeWith(
54
+ * (id: number) => Effect.succeed({ id, active: id % 2 === 0 }),
55
+ * {
56
+ * capacity: 1000,
57
+ * timeToLive(exit) {
58
+ * if (Exit.isSuccess(exit)) {
59
+ * const user = exit.value
60
+ * return user.active ? "1 hour" : "5 minutes"
61
+ * }
62
+ * return "30 seconds"
63
+ * }
64
+ * }
65
+ * )
66
+ *
67
+ * return cache
68
+ * })
69
+ * ```
70
+ *
71
+ * @see {@link make} for a simpler cache constructor with a fixed time-to-live for all entries
72
+ * @category constructors
73
+ * @since 2.0.0
74
+ */
75
+ var makeWith = (lookup, options) => contextWith((context) => {
76
+ const self = Object.create(Proto);
77
+ self.lookup = (key) => updateContext(lookup(key), (input) => merge(context, input));
78
+ self.map = make$1();
79
+ self.capacity = options.capacity;
80
+ self.timeToLive = options.timeToLive ? (exit, key) => fromInputUnsafe(options.timeToLive(exit, key)) : defaultTimeToLive;
81
+ return succeed(self);
82
+ });
83
+ /**
84
+ * Creates a cache with a fixed time-to-live for all entries.
85
+ *
86
+ * **Details**
87
+ *
88
+ * This is the basic cache constructor where all entries share the same TTL.
89
+ * The lookup function will be called when a key is not found or has expired.
90
+ *
91
+ * **Example** (Creating a basic cache)
92
+ *
93
+ * ```ts
94
+ * import { Cache, Effect } from "effect"
95
+ *
96
+ * // Basic cache with string keys
97
+ * const program = Effect.gen(function*() {
98
+ * const cache = yield* Cache.make<string, number>({
99
+ * capacity: 100,
100
+ * lookup: (key) => Effect.succeed(key.length)
101
+ * })
102
+ *
103
+ * const result1 = yield* Cache.get(cache, "hello")
104
+ * const result2 = yield* Cache.get(cache, "world")
105
+ * console.log({ result1, result2 }) // { result1: 5, result2: 5 }
106
+ * })
107
+ * ```
108
+ *
109
+ * **Example** (Creating a cache with TTL)
110
+ *
111
+ * ```ts
112
+ * import { Cache, Effect } from "effect"
113
+ *
114
+ * const program = Effect.gen(function*() {
115
+ * const users = new Map([
116
+ * [123, { name: "Ada", email: "ada@example.com" }],
117
+ * [456, { name: "Grace", email: "grace@example.com" }]
118
+ * ])
119
+ *
120
+ * const cache = yield* Cache.make<
121
+ * number,
122
+ * { name: string; email: string },
123
+ * string
124
+ * >({
125
+ * capacity: 500,
126
+ * lookup: (userId) =>
127
+ * Effect.suspend(() => {
128
+ * const user = users.get(userId)
129
+ * return user === undefined
130
+ * ? Effect.fail(`User ${userId} not found`)
131
+ * : Effect.succeed(user)
132
+ * }),
133
+ * timeToLive: "15 minutes"
134
+ * })
135
+ *
136
+ * const user1 = yield* Cache.get(cache, 123)
137
+ * console.log(user1) // { name: "Ada", email: "ada@example.com" }
138
+ *
139
+ * const user2 = yield* Cache.get(cache, 123)
140
+ * console.log(user2) // { name: "Ada", email: "ada@example.com" }
141
+ * })
142
+ * ```
143
+ *
144
+ * @category constructors
145
+ * @since 2.0.0
146
+ */
147
+ var make = (options) => makeWith(options.lookup, {
148
+ ...options,
149
+ timeToLive: options.timeToLive ? () => options.timeToLive : defaultTimeToLive
150
+ });
151
+ var Proto = {
152
+ ...PipeInspectableProto,
153
+ [TypeId]: TypeId,
154
+ toJSON() {
155
+ return {
156
+ _id: "Cache",
157
+ capacity: this.capacity,
158
+ map: this.map
159
+ };
160
+ }
161
+ };
162
+ var defaultTimeToLive = (_, _key) => infinity;
163
+ /**
164
+ * Retrieves the value for a key, invoking the lookup function on a cache miss
165
+ * or expired entry.
166
+ *
167
+ * **Details**
168
+ *
169
+ * Concurrent `get` calls for the same missing key share the same pending
170
+ * lookup. The cache stores the lookup `Exit`, so failed lookups are cached and
171
+ * will fail again until the entry expires, is invalidated, or is refreshed.
172
+ *
173
+ * **Example** (Getting cached values)
174
+ *
175
+ * ```ts
176
+ * import { Cache, Effect } from "effect"
177
+ *
178
+ * const program = Effect.gen(function*() {
179
+ * const cache = yield* Cache.make({
180
+ * capacity: 10,
181
+ * lookup: (key: string) => Effect.succeed(key.length)
182
+ * })
183
+ *
184
+ * // Cache miss - triggers lookup function
185
+ * const result1 = yield* Cache.get(cache, "hello")
186
+ * console.log(result1) // 5
187
+ *
188
+ * // Cache hit - returns cached value without lookup
189
+ * const result2 = yield* Cache.get(cache, "hello")
190
+ * console.log(result2) // 5 (from cache)
191
+ *
192
+ * return { result1, result2 }
193
+ * })
194
+ * ```
195
+ *
196
+ * **Example** (Handling lookup failures)
197
+ *
198
+ * ```ts
199
+ * import { Cache, Effect } from "effect"
200
+ *
201
+ * // Error handling when lookup fails
202
+ * const program = Effect.gen(function*() {
203
+ * const cache = yield* Cache.make<string, number, string>({
204
+ * capacity: 10,
205
+ * lookup: (key: string) =>
206
+ * key === "error"
207
+ * ? Effect.fail("Lookup failed")
208
+ * : Effect.succeed(key.length)
209
+ * })
210
+ *
211
+ * // Successful lookup
212
+ * const success = yield* Cache.get(cache, "hello")
213
+ * console.log(success) // 5
214
+ *
215
+ * // Failed lookup - returns error
216
+ * const failure = yield* Effect.exit(Cache.get(cache, "error"))
217
+ * console.log(failure) // Exit.fail("Lookup failed")
218
+ * })
219
+ * ```
220
+ *
221
+ * **Example** (Sharing concurrent lookups)
222
+ *
223
+ * ```ts
224
+ * import { Cache, Effect } from "effect"
225
+ *
226
+ * // Concurrent access - multiple gets of same key only invoke lookup once
227
+ * const program = Effect.gen(function*() {
228
+ * let lookupCount = 0
229
+ * const cache = yield* Cache.make({
230
+ * capacity: 10,
231
+ * lookup: (key: string) =>
232
+ * Effect.sync(() => {
233
+ * lookupCount++
234
+ * return key.length
235
+ * })
236
+ * })
237
+ *
238
+ * // Multiple concurrent gets
239
+ * const results = yield* Effect.all([
240
+ * Cache.get(cache, "hello"),
241
+ * Cache.get(cache, "hello"),
242
+ * Cache.get(cache, "hello")
243
+ * ], { concurrency: "unbounded" })
244
+ *
245
+ * console.log(results) // [5, 5, 5]
246
+ * console.log(lookupCount) // 1 (lookup called only once)
247
+ * })
248
+ * ```
249
+ *
250
+ * @category combinators
251
+ * @since 4.0.0
252
+ */
253
+ var get = /*#__PURE__*/ dual(2, (self, key) => withFiber((fiber) => {
254
+ const oentry = get$1(self.map, key);
255
+ if (isSome(oentry) && !hasExpired(oentry.value, fiber)) {
256
+ remove(self.map, key);
257
+ set$1(self.map, key, oentry.value);
258
+ return _await(oentry.value.deferred);
259
+ }
260
+ const deferred = makeUnsafe();
261
+ const entry = {
262
+ expiresAt: void 0,
263
+ deferred
264
+ };
265
+ set$1(self.map, key, entry);
266
+ if (Number.isFinite(self.capacity)) checkCapacity(self);
267
+ return onExit(self.lookup(key), (exit) => {
268
+ doneUnsafe(deferred, exit);
269
+ const ttl = self.timeToLive(exit, key);
270
+ if (isFinite(ttl)) entry.expiresAt = fiber.getRef(ClockRef).currentTimeMillisUnsafe() + toMillis(ttl);
271
+ else if (isZero(ttl)) remove(self.map, key);
272
+ return void_;
273
+ });
274
+ }));
275
+ var hasExpired = (entry, fiber) => {
276
+ if (entry.expiresAt === void 0) return false;
277
+ return fiber.getRef(ClockRef).currentTimeMillisUnsafe() >= entry.expiresAt;
278
+ };
279
+ var checkCapacity = (self) => {
280
+ let diff = size$1(self.map) - self.capacity;
281
+ if (diff <= 0) return;
282
+ for (const [key] of self.map) {
283
+ remove(self.map, key);
284
+ diff--;
285
+ if (diff === 0) return;
286
+ }
287
+ };
288
+ /**
289
+ * Reads an existing cache entry without invoking the lookup function.
290
+ *
291
+ * **Details**
292
+ *
293
+ * Returns `Option.none()` when the key is missing or expired, and `Option.some`
294
+ * when a cached lookup has succeeded. If the entry is still pending, waits for
295
+ * it to complete. If the cached or pending lookup fails, this effect fails with
296
+ * the same error.
297
+ *
298
+ * **Example** (Reading cached values without lookup)
299
+ *
300
+ * ```ts
301
+ * import { Cache, Effect } from "effect"
302
+ *
303
+ * const program = Effect.gen(function*() {
304
+ * const cache = yield* Cache.make({
305
+ * capacity: 10,
306
+ * lookup: (key: string) => Effect.succeed(key.length)
307
+ * })
308
+ *
309
+ * // No value in cache yet - returns None without lookup
310
+ * const empty = yield* Cache.getOption(cache, "hello")
311
+ * console.log(empty) // Option.none()
312
+ *
313
+ * // Populate cache using get
314
+ * yield* Cache.get(cache, "hello")
315
+ *
316
+ * // Now getOption returns the cached value
317
+ * const cached = yield* Cache.getOption(cache, "hello")
318
+ * console.log(cached) // Option.some(5)
319
+ *
320
+ * return { empty, cached }
321
+ * })
322
+ * ```
323
+ *
324
+ * **Example** (Skipping expired entries)
325
+ *
326
+ * ```ts
327
+ * import { Cache, Effect } from "effect"
328
+ * import { TestClock } from "effect/testing"
329
+ *
330
+ * // Expired entries return None
331
+ * const program = Effect.gen(function*() {
332
+ * const cache = yield* Cache.make({
333
+ * capacity: 10,
334
+ * lookup: (key: string) => Effect.succeed(key.length),
335
+ * timeToLive: "1 hour"
336
+ * })
337
+ *
338
+ * // Add value to cache
339
+ * yield* Cache.get(cache, "hello")
340
+ *
341
+ * // Value exists before expiration
342
+ * const beforeExpiry = yield* Cache.getOption(cache, "hello")
343
+ * console.log(beforeExpiry) // Option.some(5)
344
+ *
345
+ * // Simulate time passing
346
+ * yield* TestClock.adjust("2 hours")
347
+ *
348
+ * // Value expired - returns None
349
+ * const afterExpiry = yield* Cache.getOption(cache, "hello")
350
+ * console.log(afterExpiry) // Option.none()
351
+ * })
352
+ * ```
353
+ *
354
+ * **Example** (Waiting for pending lookups)
355
+ *
356
+ * ```ts
357
+ * import { Cache, Deferred, Effect, Fiber } from "effect"
358
+ *
359
+ * // Waits for ongoing computation to complete
360
+ * const program = Effect.gen(function*() {
361
+ * const deferred = yield* Deferred.make<void>()
362
+ * const cache = yield* Cache.make({
363
+ * capacity: 10,
364
+ * lookup: (_key: string) => Deferred.await(deferred).pipe(Effect.as(42))
365
+ * })
366
+ *
367
+ * // Start lookup in background
368
+ * const getFiber = yield* Effect.forkChild(Cache.get(cache, "key"))
369
+ *
370
+ * // getOption waits for ongoing computation
371
+ * const optionFiber = yield* Effect.forkChild(Cache.getOption(cache, "key"))
372
+ *
373
+ * // Complete the computation
374
+ * yield* Deferred.succeed(deferred, void 0)
375
+ *
376
+ * const result = yield* Fiber.join(optionFiber)
377
+ * console.log(result) // Option.some(42)
378
+ *
379
+ * const value = yield* Fiber.join(getFiber)
380
+ * console.log(value) // 42
381
+ * })
382
+ * ```
383
+ *
384
+ * @category combinators
385
+ * @since 4.0.0
386
+ */
387
+ var getOption = /*#__PURE__*/ dual(2, (self, key) => withFiber((fiber) => {
388
+ const entry = getImpl(self, key, fiber);
389
+ return entry ? asSome(_await(entry.deferred)) : succeedNone;
390
+ }));
391
+ var getImpl = (self, key, fiber, isRead = true) => {
392
+ const oentry = get$1(self.map, key);
393
+ if (isNone(oentry)) return;
394
+ else if (hasExpired(oentry.value, fiber)) {
395
+ remove(self.map, key);
396
+ return;
397
+ } else if (isRead) {
398
+ remove(self.map, key);
399
+ set$1(self.map, key, oentry.value);
400
+ }
401
+ return oentry.value;
402
+ };
403
+ /**
404
+ * Retrieves the value associated with the specified key from the cache, only if
405
+ * it contains a resolved successful value.
406
+ *
407
+ * **Details**
408
+ *
409
+ * This checks only an existing non-expired entry. It returns `Option.some` when
410
+ * the entry has already resolved successfully, and `Option.none` for missing,
411
+ * expired, failed, or still-pending entries.
412
+ *
413
+ * @see {@link get} for triggering or awaiting the cache lookup
414
+ * @see {@link getOption} for reading an existing entry as an optional effect
415
+ *
416
+ * @category combinators
417
+ * @since 4.0.0
418
+ */
419
+ var getSuccess = /*#__PURE__*/ dual(2, (self, key) => withFiber((fiber) => {
420
+ const exit = getImpl(self, key, fiber)?.deferred.effect;
421
+ if (exit && exitIsSuccess(exit)) return succeedSome(exit.value);
422
+ return succeedNone;
423
+ }));
424
+ /**
425
+ * Sets the value associated with the specified key in the cache. This will
426
+ * overwrite any existing value for that key, skipping the lookup function.
427
+ *
428
+ * **Example** (Setting values directly)
429
+ *
430
+ * ```ts
431
+ * import { Cache, Effect } from "effect"
432
+ *
433
+ * const program = Effect.gen(function*() {
434
+ * const cache = yield* Cache.make({
435
+ * capacity: 100,
436
+ * lookup: (key: string) => Effect.succeed(key.length)
437
+ * })
438
+ *
439
+ * // Set a value directly without invoking lookup
440
+ * yield* Cache.set(cache, "hello", 42)
441
+ * const result = yield* Cache.get(cache, "hello")
442
+ * console.log(result) // 42 (not 5 from lookup)
443
+ * })
444
+ * ```
445
+ *
446
+ * **Example** (Overwriting cached values)
447
+ *
448
+ * ```ts
449
+ * import { Cache, Effect } from "effect"
450
+ *
451
+ * // Overwriting existing cached values
452
+ * const program = Effect.gen(function*() {
453
+ * const cache = yield* Cache.make({
454
+ * capacity: 100,
455
+ * lookup: (key: string) => Effect.succeed(key.length)
456
+ * })
457
+ *
458
+ * // First get populates via lookup
459
+ * const original = yield* Cache.get(cache, "test") // 4
460
+ *
461
+ * // Set overwrites the cached value
462
+ * yield* Cache.set(cache, "test", 999)
463
+ * const updated = yield* Cache.get(cache, "test") // 999
464
+ *
465
+ * console.log({ original, updated })
466
+ * })
467
+ * ```
468
+ *
469
+ * **Example** (Applying TTL to set values)
470
+ *
471
+ * ```ts
472
+ * import { Cache, Effect } from "effect"
473
+ * import { TestClock } from "effect/testing"
474
+ *
475
+ * // TTL behavior with set operations
476
+ * const program = Effect.gen(function*() {
477
+ * const cache = yield* Cache.make({
478
+ * capacity: 100,
479
+ * lookup: (key: string) => Effect.succeed(key.length),
480
+ * timeToLive: "1 hour"
481
+ * })
482
+ *
483
+ * // Set value with TTL applied
484
+ * yield* Cache.set(cache, "temporary", 123)
485
+ * console.log(yield* Cache.has(cache, "temporary")) // true
486
+ *
487
+ * // Advance time past TTL
488
+ * yield* TestClock.adjust("2 hours")
489
+ * console.log(yield* Cache.has(cache, "temporary")) // false
490
+ * })
491
+ * ```
492
+ *
493
+ * **Example** (Enforcing capacity when setting values)
494
+ *
495
+ * ```ts
496
+ * import { Cache, Effect } from "effect"
497
+ *
498
+ * // Capacity enforcement with set operations
499
+ * const program = Effect.gen(function*() {
500
+ * const cache = yield* Cache.make({
501
+ * capacity: 2,
502
+ * lookup: (key: string) => Effect.succeed(key.length)
503
+ * })
504
+ *
505
+ * // Fill cache to capacity
506
+ * yield* Cache.set(cache, "a", 1)
507
+ * yield* Cache.set(cache, "b", 2)
508
+ * console.log(yield* Cache.size(cache)) // 2
509
+ *
510
+ * // Adding another entry evicts oldest
511
+ * yield* Cache.set(cache, "c", 3)
512
+ * console.log(yield* Cache.size(cache)) // 2
513
+ * console.log(yield* Cache.has(cache, "a")) // false (evicted)
514
+ * console.log(yield* Cache.has(cache, "c")) // true
515
+ * })
516
+ * ```
517
+ *
518
+ * @category combinators
519
+ * @since 4.0.0
520
+ */
521
+ var set = /*#__PURE__*/ dual(3, (self, key, value) => withFiber((fiber) => {
522
+ const exit = exitSucceed(value);
523
+ const deferred = makeUnsafe();
524
+ doneUnsafe(deferred, exit);
525
+ const ttl = self.timeToLive(exit, key);
526
+ if (isZero(ttl)) {
527
+ remove(self.map, key);
528
+ return void_;
529
+ }
530
+ set$1(self.map, key, {
531
+ deferred,
532
+ expiresAt: isFinite(ttl) ? fiber.getRef(ClockRef).currentTimeMillisUnsafe() + toMillis(ttl) : void 0
533
+ });
534
+ checkCapacity(self);
535
+ return void_;
536
+ }));
537
+ /**
538
+ * Checks whether the cache contains an entry for the specified key.
539
+ *
540
+ * **Details**
541
+ *
542
+ * This checks for an existing non-expired entry without invoking the cache
543
+ * lookup function. Expired entries are treated as absent.
544
+ *
545
+ * **Example** (Checking for cached keys)
546
+ *
547
+ * ```ts
548
+ * import { Cache, Effect } from "effect"
549
+ *
550
+ * const program = Effect.gen(function*() {
551
+ * const cache = yield* Cache.make({
552
+ * capacity: 100,
553
+ * lookup: (key: string) => Effect.succeed(key.length)
554
+ * })
555
+ *
556
+ * // Check non-existent key
557
+ * console.log(yield* Cache.has(cache, "missing")) // false
558
+ *
559
+ * // Add entry and check existence
560
+ * yield* Cache.get(cache, "hello")
561
+ * console.log(yield* Cache.has(cache, "hello")) // true
562
+ * })
563
+ * ```
564
+ *
565
+ * **Example** (Checking TTL expiration)
566
+ *
567
+ * ```ts
568
+ * import { Cache, Effect } from "effect"
569
+ * import { TestClock } from "effect/testing"
570
+ *
571
+ * // TTL expiration behavior
572
+ * const program = Effect.gen(function*() {
573
+ * const cache = yield* Cache.make({
574
+ * capacity: 100,
575
+ * lookup: (key: string) => Effect.succeed(key.length),
576
+ * timeToLive: "1 hour"
577
+ * })
578
+ *
579
+ * // Add entry with TTL
580
+ * yield* Cache.get(cache, "expires")
581
+ * console.log(yield* Cache.has(cache, "expires")) // true
582
+ *
583
+ * // Still valid before expiration
584
+ * yield* TestClock.adjust("30 minutes")
585
+ * console.log(yield* Cache.has(cache, "expires")) // true
586
+ *
587
+ * // Expired after TTL
588
+ * yield* TestClock.adjust("31 minutes")
589
+ * console.log(yield* Cache.has(cache, "expires")) // false
590
+ * })
591
+ * ```
592
+ *
593
+ * **Example** (Checking multiple keys)
594
+ *
595
+ * ```ts
596
+ * import { Cache, Effect } from "effect"
597
+ *
598
+ * // Checking multiple keys efficiently
599
+ * const program = Effect.gen(function*() {
600
+ * const cache = yield* Cache.make({
601
+ * capacity: 100,
602
+ * lookup: (key: string) => Effect.succeed(key.length)
603
+ * })
604
+ *
605
+ * // Populate some entries
606
+ * yield* Cache.set(cache, "apple", 5)
607
+ * yield* Cache.set(cache, "banana", 6)
608
+ *
609
+ * // Check multiple keys
610
+ * const keys = ["apple", "banana", "cherry", "date"]
611
+ * for (const key of keys) {
612
+ * const exists = yield* Cache.has(cache, key)
613
+ * console.log(`${key}: ${exists}`)
614
+ * }
615
+ * // Output:
616
+ * // apple: true
617
+ * // banana: true
618
+ * // cherry: false
619
+ * // date: false
620
+ * })
621
+ * ```
622
+ *
623
+ * @category combinators
624
+ * @since 4.0.0
625
+ */
626
+ var has = /*#__PURE__*/ dual(2, (self, key) => withFiber((fiber) => {
627
+ return succeed(getImpl(self, key, fiber, false) !== void 0);
628
+ }));
629
+ /**
630
+ * Invalidates the entry associated with the specified key in the cache.
631
+ *
632
+ * **Example** (Invalidating cached entries)
633
+ *
634
+ * ```ts
635
+ * import { Cache, Effect } from "effect"
636
+ *
637
+ * const program = Effect.gen(function*() {
638
+ * const cache = yield* Cache.make({
639
+ * capacity: 10,
640
+ * lookup: (key: string) => Effect.succeed(key.length)
641
+ * })
642
+ *
643
+ * // Add a value to the cache
644
+ * yield* Cache.get(cache, "hello")
645
+ * console.log(yield* Cache.has(cache, "hello")) // true
646
+ *
647
+ * // Invalidate the entry
648
+ * yield* Cache.invalidate(cache, "hello")
649
+ * console.log(yield* Cache.has(cache, "hello")) // false
650
+ *
651
+ * // Invalidating non-existent keys doesn't error
652
+ * yield* Cache.invalidate(cache, "nonexistent")
653
+ *
654
+ * // Get after invalidation will invoke lookup again
655
+ * let lookupCount = 0
656
+ * const cache2 = yield* Cache.make({
657
+ * capacity: 10,
658
+ * lookup: (key: string) =>
659
+ * Effect.sync(() => {
660
+ * lookupCount++
661
+ * return key.length
662
+ * })
663
+ * })
664
+ *
665
+ * yield* Cache.get(cache2, "test") // lookupCount = 1
666
+ * yield* Cache.invalidate(cache2, "test")
667
+ * yield* Cache.get(cache2, "test") // lookupCount = 2 (lookup called again)
668
+ * })
669
+ * ```
670
+ *
671
+ * @category combinators
672
+ * @since 4.0.0
673
+ */
674
+ var invalidate = /*#__PURE__*/ dual(2, (self, key) => sync(() => {
675
+ remove(self.map, key);
676
+ }));
677
+ /**
678
+ * Invalidates the entry associated with the specified key in the cache when the
679
+ * predicate returns true for the cached value.
680
+ *
681
+ * **Example** (Invalidating entries conditionally)
682
+ *
683
+ * ```ts
684
+ * import { Cache, Effect } from "effect"
685
+ *
686
+ * const program = Effect.gen(function*() {
687
+ * const cache = yield* Cache.make({
688
+ * capacity: 10,
689
+ * lookup: (key: string) => Effect.succeed(key.length)
690
+ * })
691
+ *
692
+ * // Add values to the cache
693
+ * yield* Cache.get(cache, "hello") // value = 5
694
+ * yield* Cache.get(cache, "hi") // value = 2
695
+ *
696
+ * // Invalidate when value equals 5
697
+ * const invalidated1 = yield* Cache.invalidateWhen(
698
+ * cache,
699
+ * "hello",
700
+ * (value) => value === 5
701
+ * )
702
+ * console.log(invalidated1) // true
703
+ * console.log(yield* Cache.has(cache, "hello")) // false
704
+ *
705
+ * // Don't invalidate when predicate doesn't match
706
+ * const invalidated2 = yield* Cache.invalidateWhen(
707
+ * cache,
708
+ * "hi",
709
+ * (value) => value === 5
710
+ * )
711
+ * console.log(invalidated2) // false
712
+ * console.log(yield* Cache.has(cache, "hi")) // true (still present)
713
+ *
714
+ * // Returns false for non-existent keys
715
+ * const invalidated3 = yield* Cache.invalidateWhen(
716
+ * cache,
717
+ * "nonexistent",
718
+ * () => true
719
+ * )
720
+ * console.log(invalidated3) // false
721
+ *
722
+ * // Returns false for failed cached values
723
+ * const cacheWithErrors = yield* Cache.make<string, number, string>({
724
+ * capacity: 10,
725
+ * lookup: (key: string) =>
726
+ * key === "fail" ? Effect.fail("error") : Effect.succeed(key.length)
727
+ * })
728
+ *
729
+ * yield* Effect.exit(Cache.get(cacheWithErrors, "fail"))
730
+ * const invalidated4 = yield* Cache.invalidateWhen(
731
+ * cacheWithErrors,
732
+ * "fail",
733
+ * () => true
734
+ * )
735
+ * console.log(invalidated4) // false (can't invalidate failed values)
736
+ * })
737
+ * ```
738
+ *
739
+ * @category combinators
740
+ * @since 4.0.0
741
+ */
742
+ var invalidateWhen = /*#__PURE__*/ dual(3, (self, key, f) => withFiber((fiber) => {
743
+ const oentry = getImpl(self, key, fiber, false);
744
+ if (oentry === void 0) return succeed(false);
745
+ return _await(oentry.deferred).pipe(map((value) => {
746
+ if (f(value)) {
747
+ remove(self.map, key);
748
+ return true;
749
+ }
750
+ return false;
751
+ }), catchCause(() => succeed(false)));
752
+ }));
753
+ /**
754
+ * Forces a refresh of the value associated with the specified key in the cache.
755
+ *
756
+ * **Details**
757
+ *
758
+ * It will always invoke the lookup function to construct a new value,
759
+ * overwriting any existing value for that key.
760
+ *
761
+ * **Example** (Refreshing cached values)
762
+ *
763
+ * ```ts
764
+ * import { Cache, Effect } from "effect"
765
+ *
766
+ * // Force refresh of existing cached values
767
+ * const program = Effect.gen(function*() {
768
+ * let counter = 0
769
+ * const cache = yield* Cache.make({
770
+ * capacity: 10,
771
+ * lookup: (key: string) => Effect.sync(() => `${key}-${++counter}`)
772
+ * })
773
+ *
774
+ * // Initial cache population
775
+ * const value1 = yield* Cache.get(cache, "user")
776
+ * console.log(value1) // "user-1"
777
+ *
778
+ * // Get from cache (no lookup)
779
+ * const value2 = yield* Cache.get(cache, "user")
780
+ * console.log(value2) // "user-1" (same value)
781
+ *
782
+ * // Force refresh - always calls lookup
783
+ * const refreshed = yield* Cache.refresh(cache, "user")
784
+ * console.log(refreshed) // "user-2" (new value)
785
+ *
786
+ * // Subsequent gets return refreshed value
787
+ * const value3 = yield* Cache.get(cache, "user")
788
+ * console.log(value3) // "user-2"
789
+ * })
790
+ * ```
791
+ *
792
+ * **Example** (Resetting TTL on refresh)
793
+ *
794
+ * ```ts
795
+ * import { Cache, Effect } from "effect"
796
+ * import { TestClock } from "effect/testing"
797
+ *
798
+ * // Refresh resets TTL (Time To Live)
799
+ * const program = Effect.gen(function*() {
800
+ * const cache = yield* Cache.make({
801
+ * capacity: 10,
802
+ * lookup: (key: string) => Effect.succeed(key.length),
803
+ * timeToLive: "1 hour"
804
+ * })
805
+ *
806
+ * yield* Cache.get(cache, "test")
807
+ * yield* TestClock.adjust("45 minutes")
808
+ *
809
+ * // Entry would normally expire in 15 minutes
810
+ * console.log(yield* Cache.has(cache, "test")) // true
811
+ *
812
+ * // Refresh resets the TTL to full 1 hour
813
+ * yield* Cache.refresh(cache, "test")
814
+ * yield* TestClock.adjust("30 minutes")
815
+ *
816
+ * // Still valid because TTL was reset
817
+ * console.log(yield* Cache.has(cache, "test")) // true
818
+ * })
819
+ * ```
820
+ *
821
+ * **Example** (Refreshing missing keys)
822
+ *
823
+ * ```ts
824
+ * import { Cache, Effect } from "effect"
825
+ *
826
+ * // Refresh non-existent keys
827
+ * const program = Effect.gen(function*() {
828
+ * const cache = yield* Cache.make({
829
+ * capacity: 10,
830
+ * lookup: (key: string) => Effect.succeed(`value-for-${key}`)
831
+ * })
832
+ *
833
+ * // Refresh non-existent key creates new entry
834
+ * const result = yield* Cache.refresh(cache, "newKey")
835
+ * console.log(result) // "value-for-newKey"
836
+ *
837
+ * // Verify it's now cached
838
+ * console.log(yield* Cache.has(cache, "newKey")) // true
839
+ * })
840
+ * ```
841
+ *
842
+ * @category combinators
843
+ * @since 4.0.0
844
+ */
845
+ var refresh = /*#__PURE__*/ dual(2, (self, key) => withFiber((fiber) => {
846
+ const deferred = makeUnsafe();
847
+ const entry = {
848
+ expiresAt: void 0,
849
+ deferred
850
+ };
851
+ const existing = getImpl(self, key, fiber, false) !== void 0;
852
+ if (!existing) {
853
+ set$1(self.map, key, entry);
854
+ checkCapacity(self);
855
+ }
856
+ return onExit(self.lookup(key), (exit) => {
857
+ doneUnsafe(deferred, exit);
858
+ const ttl = self.timeToLive(exit, key);
859
+ if (isZero(ttl)) {
860
+ remove(self.map, key);
861
+ return void_;
862
+ }
863
+ entry.expiresAt = isFinite(ttl) ? fiber.getRef(ClockRef).currentTimeMillisUnsafe() + toMillis(ttl) : void 0;
864
+ if (existing) set$1(self.map, key, entry);
865
+ return void_;
866
+ });
867
+ }));
868
+ /**
869
+ * Invalidates all entries in the cache.
870
+ *
871
+ * **Example** (Invalidating all entries)
872
+ *
873
+ * ```ts
874
+ * import { Cache, Effect } from "effect"
875
+ *
876
+ * // Clear all cached entries at once
877
+ * const program = Effect.gen(function*() {
878
+ * const cache = yield* Cache.make({
879
+ * capacity: 10,
880
+ * lookup: (key: string) => Effect.succeed(key.length)
881
+ * })
882
+ *
883
+ * // Populate cache with multiple entries
884
+ * yield* Cache.get(cache, "apple")
885
+ * yield* Cache.get(cache, "banana")
886
+ * yield* Cache.get(cache, "cherry")
887
+ *
888
+ * console.log(yield* Cache.size(cache)) // 3
889
+ * console.log(yield* Cache.has(cache, "apple")) // true
890
+ *
891
+ * // Clear all entries
892
+ * yield* Cache.invalidateAll(cache)
893
+ *
894
+ * // Verify cache is empty
895
+ * console.log(yield* Cache.size(cache)) // 0
896
+ * console.log(yield* Cache.has(cache, "apple")) // false
897
+ * console.log(yield* Cache.has(cache, "banana")) // false
898
+ * console.log(yield* Cache.has(cache, "cherry")) // false
899
+ * })
900
+ * ```
901
+ *
902
+ * @category combinators
903
+ * @since 4.0.0
904
+ */
905
+ var invalidateAll = (self) => sync(() => {
906
+ clear(self.map);
907
+ });
908
+ /**
909
+ * Retrieves the approximate number of entries in the cache.
910
+ *
911
+ * **Details**
912
+ *
913
+ * Note that expired entries are counted until they are accessed and removed.
914
+ * The size reflects the current number of entries stored, not the number
915
+ * of valid entries.
916
+ *
917
+ * **Example** (Reading cache size)
918
+ *
919
+ * ```ts
920
+ * import { Cache, Effect } from "effect"
921
+ *
922
+ * const program = Effect.gen(function*() {
923
+ * const cache = yield* Cache.make({
924
+ * capacity: 10,
925
+ * lookup: (key: string) => Effect.succeed(key.length)
926
+ * })
927
+ *
928
+ * // Empty cache has size 0
929
+ * const emptySize = yield* Cache.size(cache)
930
+ * console.log(emptySize) // 0
931
+ *
932
+ * // Add entries and check size
933
+ * yield* Cache.get(cache, "hello")
934
+ * yield* Cache.get(cache, "world")
935
+ * const sizeAfterAdding = yield* Cache.size(cache)
936
+ * console.log(sizeAfterAdding) // 2
937
+ *
938
+ * // Size decreases after invalidation
939
+ * yield* Cache.invalidate(cache, "hello")
940
+ * const sizeAfterInvalidation = yield* Cache.size(cache)
941
+ * console.log(sizeAfterInvalidation) // 1
942
+ * })
943
+ * ```
944
+ *
945
+ * @category combinators
946
+ * @since 4.0.0
947
+ */
948
+ var size = (self) => sync(() => size$1(self.map));
949
+ /**
950
+ * Retrieves all active keys from the cache, automatically filtering out expired entries.
951
+ *
952
+ * **Example** (Reading active keys)
953
+ *
954
+ * ```ts
955
+ * import { Cache, Effect } from "effect"
956
+ *
957
+ * // Basic key enumeration
958
+ * const program = Effect.gen(function*() {
959
+ * const cache = yield* Cache.make({
960
+ * capacity: 10,
961
+ * lookup: (key: string) => Effect.succeed(key.length)
962
+ * })
963
+ *
964
+ * // Add some entries to the cache
965
+ * yield* Cache.get(cache, "hello")
966
+ * yield* Cache.get(cache, "world")
967
+ * yield* Cache.get(cache, "cache")
968
+ *
969
+ * // Retrieve all active keys
970
+ * const keys = yield* Cache.keys(cache)
971
+ *
972
+ * console.log(Array.from(keys).sort()) // ["cache", "hello", "world"]
973
+ * })
974
+ * ```
975
+ *
976
+ * @category combinators
977
+ * @since 4.0.0
978
+ */
979
+ var keys = (self) => withFiber((fiber) => {
980
+ const now = fiber.getRef(ClockRef).currentTimeMillisUnsafe();
981
+ return succeed(filterMap(self.map, ([key, entry]) => {
982
+ if (entry.expiresAt === void 0 || entry.expiresAt > now) return succeed$1(key);
983
+ remove(self.map, key);
984
+ return failVoid;
985
+ }));
986
+ });
987
+ /**
988
+ * Retrieves all successfully cached values from the cache, excluding failed
989
+ * lookups and expired entries.
990
+ *
991
+ * **Example** (Reading all cached values)
992
+ *
993
+ * ```ts
994
+ * import { Cache, Effect } from "effect"
995
+ *
996
+ * const program = Effect.gen(function*() {
997
+ * const cache = yield* Cache.make({
998
+ * capacity: 10,
999
+ * lookup: (key: string) => Effect.succeed(key.length)
1000
+ * })
1001
+ *
1002
+ * // Add some values to the cache
1003
+ * yield* Cache.get(cache, "a")
1004
+ * yield* Cache.get(cache, "ab")
1005
+ * yield* Cache.get(cache, "abc")
1006
+ *
1007
+ * // Retrieve all cached values
1008
+ * const values = yield* Cache.values(cache)
1009
+ * const valuesArray = Array.from(values).sort()
1010
+ *
1011
+ * console.log(valuesArray) // [1, 2, 3]
1012
+ * })
1013
+ * ```
1014
+ *
1015
+ * @category combinators
1016
+ * @since 4.0.0
1017
+ */
1018
+ var values = (self) => map(entries(self), map$1(([, value]) => value));
1019
+ /**
1020
+ * Retrieves all key-value pairs from the cache as an iterable. This function
1021
+ * only returns entries with successfully resolved values, filtering out any
1022
+ * failed lookups or expired entries.
1023
+ *
1024
+ * **Gotchas**
1025
+ *
1026
+ * Expired entries are removed from the cache while `entries` filters them out.
1027
+ *
1028
+ * @see {@link keys} for retrieving only cached keys
1029
+ * @see {@link values} for retrieving only cached values
1030
+ *
1031
+ * @category combinators
1032
+ * @since 4.0.0
1033
+ */
1034
+ var entries = (self) => withFiber((fiber) => {
1035
+ const now = fiber.getRef(ClockRef).currentTimeMillisUnsafe();
1036
+ return succeed(filterMap(self.map, ([key, entry]) => {
1037
+ if (entry.expiresAt === void 0 || entry.expiresAt > now) {
1038
+ const exit = entry.deferred.effect;
1039
+ return !isExit(exit) || exitIsFailure(exit) ? failVoid : succeed$1([key, exit.value]);
1040
+ }
1041
+ remove(self.map, key);
1042
+ return failVoid;
1043
+ }));
1044
+ });
1045
+ //#endregion
1046
+ export { makeWith as i, get as n, make as r, Cache_exports as t };
1047
+
1048
+ //# sourceMappingURL=Cache-Dv3Qogvb.js.map