ff-serv 0.1.10 → 0.1.11
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.
- package/dist/adapter-DLhjFlOu.d.cts +31 -0
- package/dist/adapter-DLhjFlOu.d.ts +31 -0
- package/dist/cli.js +47 -47
- package/dist/exports/cache-bun-redis.cjs +50 -0
- package/dist/exports/cache-bun-redis.cjs.map +1 -0
- package/dist/exports/cache-bun-redis.d.cts +11 -0
- package/dist/exports/cache-bun-redis.d.ts +11 -0
- package/dist/exports/cache-bun-redis.js +23 -0
- package/dist/exports/cache-bun-redis.js.map +1 -0
- package/dist/exports/cache-ioredis.cjs +51 -0
- package/dist/exports/cache-ioredis.cjs.map +1 -0
- package/dist/exports/cache-ioredis.d.cts +11 -0
- package/dist/exports/cache-ioredis.d.ts +11 -0
- package/dist/exports/cache-ioredis.js +24 -0
- package/dist/exports/cache-ioredis.js.map +1 -0
- package/dist/exports/cache.cjs +220 -0
- package/dist/exports/cache.cjs.map +1 -0
- package/dist/exports/cache.d.cts +30 -0
- package/dist/exports/cache.d.ts +30 -0
- package/dist/exports/cache.js +199 -0
- package/dist/exports/cache.js.map +1 -0
- package/dist/exports/orpc.cjs +15 -10
- package/dist/exports/orpc.cjs.map +1 -1
- package/dist/exports/orpc.js +16 -11
- package/dist/exports/orpc.js.map +1 -1
- package/dist/index.cjs +15 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -7
- package/dist/index.d.ts +10 -7
- package/dist/index.js +17 -12
- package/dist/index.js.map +1 -1
- package/package.json +26 -2
- package/src/cache/AGENTS.md +8 -0
- package/src/cache/adapter.test.ts +181 -0
- package/src/cache/adapter.ts +120 -0
- package/src/cache/adapters/bun-redis.ts +29 -0
- package/src/cache/adapters/ioredis.ts +30 -0
- package/src/cache/cache.test.ts +461 -0
- package/src/cache/cache.ts +184 -0
- package/src/cli/commands/db/pull.ts +5 -15
- package/src/cli/commands/db/shared.ts +7 -7
- package/src/cli/config/index.ts +1 -3
- package/src/cli/index.ts +1 -1
- package/src/cli/utils/database-source.ts +1 -4
- package/src/exports/cache-bun-redis.ts +1 -0
- package/src/exports/cache-ioredis.ts +1 -0
- package/src/exports/cache.ts +6 -0
- package/src/exports/orpc.ts +1 -1
- package/src/http/fetch-handler.test.ts +1 -1
- package/src/index.ts +1 -0
- package/src/logger.test.ts +168 -0
- package/src/logger.ts +41 -19
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/exports/cache-bun-redis.ts
|
|
21
|
+
var cache_bun_redis_exports = {};
|
|
22
|
+
__export(cache_bun_redis_exports, {
|
|
23
|
+
bunRedis: () => bunRedis
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(cache_bun_redis_exports);
|
|
26
|
+
|
|
27
|
+
// src/cache/adapters/bun-redis.ts
|
|
28
|
+
var import_effect = require("effect");
|
|
29
|
+
function bunRedis(client) {
|
|
30
|
+
return {
|
|
31
|
+
get: (key) => import_effect.Effect.tryPromise(() => client.get(key)).pipe(
|
|
32
|
+
import_effect.Effect.map(
|
|
33
|
+
(value) => value !== null ? import_effect.Option.some(value) : import_effect.Option.none()
|
|
34
|
+
),
|
|
35
|
+
import_effect.Effect.orDie
|
|
36
|
+
),
|
|
37
|
+
set: (key, value, ttlMs) => import_effect.Effect.tryPromise(
|
|
38
|
+
() => client.send("SET", [key, value, "PX", String(ttlMs)])
|
|
39
|
+
).pipe(import_effect.Effect.asVoid, import_effect.Effect.orDie),
|
|
40
|
+
del: (key) => import_effect.Effect.tryPromise(() => client.del(key)).pipe(
|
|
41
|
+
import_effect.Effect.asVoid,
|
|
42
|
+
import_effect.Effect.orDie
|
|
43
|
+
)
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
47
|
+
0 && (module.exports = {
|
|
48
|
+
bunRedis
|
|
49
|
+
});
|
|
50
|
+
//# sourceMappingURL=cache-bun-redis.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/exports/cache-bun-redis.ts","../../src/cache/adapters/bun-redis.ts"],"sourcesContent":["export { bunRedis } from '../cache/adapters/bun-redis.js';\n","import { Effect, Option } from 'effect';\nimport type { RedisClient } from '../adapter.js';\n\ntype BunRedisClient = {\n\tget(key: string): Promise<string | null>;\n\tsend(command: string, args: string[]): Promise<unknown>;\n\tdel(key: string): Promise<number>;\n};\n\nexport function bunRedis(client: BunRedisClient): RedisClient {\n\treturn {\n\t\tget: (key) =>\n\t\t\tEffect.tryPromise(() => client.get(key)).pipe(\n\t\t\t\tEffect.map((value) =>\n\t\t\t\t\tvalue !== null ? Option.some(value) : Option.none(),\n\t\t\t\t),\n\t\t\t\tEffect.orDie,\n\t\t\t),\n\t\tset: (key, value, ttlMs) =>\n\t\t\tEffect.tryPromise(() =>\n\t\t\t\tclient.send('SET', [key, value, 'PX', String(ttlMs)]),\n\t\t\t).pipe(Effect.asVoid, Effect.orDie),\n\t\tdel: (key) =>\n\t\t\tEffect.tryPromise(() => client.del(key)).pipe(\n\t\t\t\tEffect.asVoid,\n\t\t\t\tEffect.orDie,\n\t\t\t),\n\t};\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,oBAA+B;AASxB,SAAS,SAAS,QAAqC;AAC7D,SAAO;AAAA,IACN,KAAK,CAAC,QACL,qBAAO,WAAW,MAAM,OAAO,IAAI,GAAG,CAAC,EAAE;AAAA,MACxC,qBAAO;AAAA,QAAI,CAAC,UACX,UAAU,OAAO,qBAAO,KAAK,KAAK,IAAI,qBAAO,KAAK;AAAA,MACnD;AAAA,MACA,qBAAO;AAAA,IACR;AAAA,IACD,KAAK,CAAC,KAAK,OAAO,UACjB,qBAAO;AAAA,MAAW,MACjB,OAAO,KAAK,OAAO,CAAC,KAAK,OAAO,MAAM,OAAO,KAAK,CAAC,CAAC;AAAA,IACrD,EAAE,KAAK,qBAAO,QAAQ,qBAAO,KAAK;AAAA,IACnC,KAAK,CAAC,QACL,qBAAO,WAAW,MAAM,OAAO,IAAI,GAAG,CAAC,EAAE;AAAA,MACxC,qBAAO;AAAA,MACP,qBAAO;AAAA,IACR;AAAA,EACF;AACD;","names":[]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { R as RedisClient } from '../adapter-DLhjFlOu.cjs';
|
|
2
|
+
import 'effect';
|
|
3
|
+
|
|
4
|
+
type BunRedisClient = {
|
|
5
|
+
get(key: string): Promise<string | null>;
|
|
6
|
+
send(command: string, args: string[]): Promise<unknown>;
|
|
7
|
+
del(key: string): Promise<number>;
|
|
8
|
+
};
|
|
9
|
+
declare function bunRedis(client: BunRedisClient): RedisClient;
|
|
10
|
+
|
|
11
|
+
export { bunRedis };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { R as RedisClient } from '../adapter-DLhjFlOu.js';
|
|
2
|
+
import 'effect';
|
|
3
|
+
|
|
4
|
+
type BunRedisClient = {
|
|
5
|
+
get(key: string): Promise<string | null>;
|
|
6
|
+
send(command: string, args: string[]): Promise<unknown>;
|
|
7
|
+
del(key: string): Promise<number>;
|
|
8
|
+
};
|
|
9
|
+
declare function bunRedis(client: BunRedisClient): RedisClient;
|
|
10
|
+
|
|
11
|
+
export { bunRedis };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// src/cache/adapters/bun-redis.ts
|
|
2
|
+
import { Effect, Option } from "effect";
|
|
3
|
+
function bunRedis(client) {
|
|
4
|
+
return {
|
|
5
|
+
get: (key) => Effect.tryPromise(() => client.get(key)).pipe(
|
|
6
|
+
Effect.map(
|
|
7
|
+
(value) => value !== null ? Option.some(value) : Option.none()
|
|
8
|
+
),
|
|
9
|
+
Effect.orDie
|
|
10
|
+
),
|
|
11
|
+
set: (key, value, ttlMs) => Effect.tryPromise(
|
|
12
|
+
() => client.send("SET", [key, value, "PX", String(ttlMs)])
|
|
13
|
+
).pipe(Effect.asVoid, Effect.orDie),
|
|
14
|
+
del: (key) => Effect.tryPromise(() => client.del(key)).pipe(
|
|
15
|
+
Effect.asVoid,
|
|
16
|
+
Effect.orDie
|
|
17
|
+
)
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export {
|
|
21
|
+
bunRedis
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=cache-bun-redis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cache/adapters/bun-redis.ts"],"sourcesContent":["import { Effect, Option } from 'effect';\nimport type { RedisClient } from '../adapter.js';\n\ntype BunRedisClient = {\n\tget(key: string): Promise<string | null>;\n\tsend(command: string, args: string[]): Promise<unknown>;\n\tdel(key: string): Promise<number>;\n};\n\nexport function bunRedis(client: BunRedisClient): RedisClient {\n\treturn {\n\t\tget: (key) =>\n\t\t\tEffect.tryPromise(() => client.get(key)).pipe(\n\t\t\t\tEffect.map((value) =>\n\t\t\t\t\tvalue !== null ? Option.some(value) : Option.none(),\n\t\t\t\t),\n\t\t\t\tEffect.orDie,\n\t\t\t),\n\t\tset: (key, value, ttlMs) =>\n\t\t\tEffect.tryPromise(() =>\n\t\t\t\tclient.send('SET', [key, value, 'PX', String(ttlMs)]),\n\t\t\t).pipe(Effect.asVoid, Effect.orDie),\n\t\tdel: (key) =>\n\t\t\tEffect.tryPromise(() => client.del(key)).pipe(\n\t\t\t\tEffect.asVoid,\n\t\t\t\tEffect.orDie,\n\t\t\t),\n\t};\n}\n"],"mappings":";AAAA,SAAS,QAAQ,cAAc;AASxB,SAAS,SAAS,QAAqC;AAC7D,SAAO;AAAA,IACN,KAAK,CAAC,QACL,OAAO,WAAW,MAAM,OAAO,IAAI,GAAG,CAAC,EAAE;AAAA,MACxC,OAAO;AAAA,QAAI,CAAC,UACX,UAAU,OAAO,OAAO,KAAK,KAAK,IAAI,OAAO,KAAK;AAAA,MACnD;AAAA,MACA,OAAO;AAAA,IACR;AAAA,IACD,KAAK,CAAC,KAAK,OAAO,UACjB,OAAO;AAAA,MAAW,MACjB,OAAO,KAAK,OAAO,CAAC,KAAK,OAAO,MAAM,OAAO,KAAK,CAAC,CAAC;AAAA,IACrD,EAAE,KAAK,OAAO,QAAQ,OAAO,KAAK;AAAA,IACnC,KAAK,CAAC,QACL,OAAO,WAAW,MAAM,OAAO,IAAI,GAAG,CAAC,EAAE;AAAA,MACxC,OAAO;AAAA,MACP,OAAO;AAAA,IACR;AAAA,EACF;AACD;","names":[]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/exports/cache-ioredis.ts
|
|
21
|
+
var cache_ioredis_exports = {};
|
|
22
|
+
__export(cache_ioredis_exports, {
|
|
23
|
+
ioredis: () => ioredis
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(cache_ioredis_exports);
|
|
26
|
+
|
|
27
|
+
// src/cache/adapters/ioredis.ts
|
|
28
|
+
var import_effect = require("effect");
|
|
29
|
+
function ioredis(client) {
|
|
30
|
+
return {
|
|
31
|
+
get: (key) => import_effect.Effect.tryPromise(() => client.get(key)).pipe(
|
|
32
|
+
import_effect.Effect.map(
|
|
33
|
+
(value) => value !== null ? import_effect.Option.some(value) : import_effect.Option.none()
|
|
34
|
+
),
|
|
35
|
+
import_effect.Effect.orDie
|
|
36
|
+
),
|
|
37
|
+
set: (key, value, ttlMs) => import_effect.Effect.tryPromise(() => client.set(key, value, "PX", ttlMs)).pipe(
|
|
38
|
+
import_effect.Effect.asVoid,
|
|
39
|
+
import_effect.Effect.orDie
|
|
40
|
+
),
|
|
41
|
+
del: (key) => import_effect.Effect.tryPromise(() => client.del(key)).pipe(
|
|
42
|
+
import_effect.Effect.asVoid,
|
|
43
|
+
import_effect.Effect.orDie
|
|
44
|
+
)
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
48
|
+
0 && (module.exports = {
|
|
49
|
+
ioredis
|
|
50
|
+
});
|
|
51
|
+
//# sourceMappingURL=cache-ioredis.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/exports/cache-ioredis.ts","../../src/cache/adapters/ioredis.ts"],"sourcesContent":["export { ioredis } from '../cache/adapters/ioredis.js';\n","import { Effect, Option } from 'effect';\nimport type { RedisClient } from '../adapter.js';\n\ntype IORedisClient = {\n\tget(key: string): Promise<string | null>;\n\tset(key: string, value: string, px: 'PX', ttlMs: number): Promise<unknown>;\n\tdel(key: string): Promise<number>;\n};\n\nexport function ioredis(client: IORedisClient): RedisClient {\n\treturn {\n\t\tget: (key) =>\n\t\t\tEffect.tryPromise(() => client.get(key)).pipe(\n\t\t\t\tEffect.map((value) =>\n\t\t\t\t\tvalue !== null ? Option.some(value) : Option.none(),\n\t\t\t\t),\n\t\t\t\tEffect.orDie,\n\t\t\t),\n\t\tset: (key, value, ttlMs) =>\n\t\t\tEffect.tryPromise(() => client.set(key, value, 'PX', ttlMs)).pipe(\n\t\t\t\tEffect.asVoid,\n\t\t\t\tEffect.orDie,\n\t\t\t),\n\t\tdel: (key) =>\n\t\t\tEffect.tryPromise(() => client.del(key)).pipe(\n\t\t\t\tEffect.asVoid,\n\t\t\t\tEffect.orDie,\n\t\t\t),\n\t};\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,oBAA+B;AASxB,SAAS,QAAQ,QAAoC;AAC3D,SAAO;AAAA,IACN,KAAK,CAAC,QACL,qBAAO,WAAW,MAAM,OAAO,IAAI,GAAG,CAAC,EAAE;AAAA,MACxC,qBAAO;AAAA,QAAI,CAAC,UACX,UAAU,OAAO,qBAAO,KAAK,KAAK,IAAI,qBAAO,KAAK;AAAA,MACnD;AAAA,MACA,qBAAO;AAAA,IACR;AAAA,IACD,KAAK,CAAC,KAAK,OAAO,UACjB,qBAAO,WAAW,MAAM,OAAO,IAAI,KAAK,OAAO,MAAM,KAAK,CAAC,EAAE;AAAA,MAC5D,qBAAO;AAAA,MACP,qBAAO;AAAA,IACR;AAAA,IACD,KAAK,CAAC,QACL,qBAAO,WAAW,MAAM,OAAO,IAAI,GAAG,CAAC,EAAE;AAAA,MACxC,qBAAO;AAAA,MACP,qBAAO;AAAA,IACR;AAAA,EACF;AACD;","names":[]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { R as RedisClient } from '../adapter-DLhjFlOu.cjs';
|
|
2
|
+
import 'effect';
|
|
3
|
+
|
|
4
|
+
type IORedisClient = {
|
|
5
|
+
get(key: string): Promise<string | null>;
|
|
6
|
+
set(key: string, value: string, px: 'PX', ttlMs: number): Promise<unknown>;
|
|
7
|
+
del(key: string): Promise<number>;
|
|
8
|
+
};
|
|
9
|
+
declare function ioredis(client: IORedisClient): RedisClient;
|
|
10
|
+
|
|
11
|
+
export { ioredis };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { R as RedisClient } from '../adapter-DLhjFlOu.js';
|
|
2
|
+
import 'effect';
|
|
3
|
+
|
|
4
|
+
type IORedisClient = {
|
|
5
|
+
get(key: string): Promise<string | null>;
|
|
6
|
+
set(key: string, value: string, px: 'PX', ttlMs: number): Promise<unknown>;
|
|
7
|
+
del(key: string): Promise<number>;
|
|
8
|
+
};
|
|
9
|
+
declare function ioredis(client: IORedisClient): RedisClient;
|
|
10
|
+
|
|
11
|
+
export { ioredis };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// src/cache/adapters/ioredis.ts
|
|
2
|
+
import { Effect, Option } from "effect";
|
|
3
|
+
function ioredis(client) {
|
|
4
|
+
return {
|
|
5
|
+
get: (key) => Effect.tryPromise(() => client.get(key)).pipe(
|
|
6
|
+
Effect.map(
|
|
7
|
+
(value) => value !== null ? Option.some(value) : Option.none()
|
|
8
|
+
),
|
|
9
|
+
Effect.orDie
|
|
10
|
+
),
|
|
11
|
+
set: (key, value, ttlMs) => Effect.tryPromise(() => client.set(key, value, "PX", ttlMs)).pipe(
|
|
12
|
+
Effect.asVoid,
|
|
13
|
+
Effect.orDie
|
|
14
|
+
),
|
|
15
|
+
del: (key) => Effect.tryPromise(() => client.del(key)).pipe(
|
|
16
|
+
Effect.asVoid,
|
|
17
|
+
Effect.orDie
|
|
18
|
+
)
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
ioredis
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=cache-ioredis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cache/adapters/ioredis.ts"],"sourcesContent":["import { Effect, Option } from 'effect';\nimport type { RedisClient } from '../adapter.js';\n\ntype IORedisClient = {\n\tget(key: string): Promise<string | null>;\n\tset(key: string, value: string, px: 'PX', ttlMs: number): Promise<unknown>;\n\tdel(key: string): Promise<number>;\n};\n\nexport function ioredis(client: IORedisClient): RedisClient {\n\treturn {\n\t\tget: (key) =>\n\t\t\tEffect.tryPromise(() => client.get(key)).pipe(\n\t\t\t\tEffect.map((value) =>\n\t\t\t\t\tvalue !== null ? Option.some(value) : Option.none(),\n\t\t\t\t),\n\t\t\t\tEffect.orDie,\n\t\t\t),\n\t\tset: (key, value, ttlMs) =>\n\t\t\tEffect.tryPromise(() => client.set(key, value, 'PX', ttlMs)).pipe(\n\t\t\t\tEffect.asVoid,\n\t\t\t\tEffect.orDie,\n\t\t\t),\n\t\tdel: (key) =>\n\t\t\tEffect.tryPromise(() => client.del(key)).pipe(\n\t\t\t\tEffect.asVoid,\n\t\t\t\tEffect.orDie,\n\t\t\t),\n\t};\n}\n"],"mappings":";AAAA,SAAS,QAAQ,cAAc;AASxB,SAAS,QAAQ,QAAoC;AAC3D,SAAO;AAAA,IACN,KAAK,CAAC,QACL,OAAO,WAAW,MAAM,OAAO,IAAI,GAAG,CAAC,EAAE;AAAA,MACxC,OAAO;AAAA,QAAI,CAAC,UACX,UAAU,OAAO,OAAO,KAAK,KAAK,IAAI,OAAO,KAAK;AAAA,MACnD;AAAA,MACA,OAAO;AAAA,IACR;AAAA,IACD,KAAK,CAAC,KAAK,OAAO,UACjB,OAAO,WAAW,MAAM,OAAO,IAAI,KAAK,OAAO,MAAM,KAAK,CAAC,EAAE;AAAA,MAC5D,OAAO;AAAA,MACP,OAAO;AAAA,IACR;AAAA,IACD,KAAK,CAAC,QACL,OAAO,WAAW,MAAM,OAAO,IAAI,GAAG,CAAC,EAAE;AAAA,MACxC,OAAO;AAAA,MACP,OAAO;AAAA,IACR;AAAA,EACF;AACD;","names":[]}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/exports/cache.ts
|
|
21
|
+
var cache_exports = {};
|
|
22
|
+
__export(cache_exports, {
|
|
23
|
+
Cache: () => Cache,
|
|
24
|
+
CacheAdapter: () => CacheAdapter
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(cache_exports);
|
|
27
|
+
|
|
28
|
+
// src/cache/adapter.ts
|
|
29
|
+
var import_effect = require("effect");
|
|
30
|
+
var CacheAdapter;
|
|
31
|
+
((CacheAdapter2) => {
|
|
32
|
+
function memory(opts) {
|
|
33
|
+
return {
|
|
34
|
+
get: () => import_effect.Effect.succeed(import_effect.Option.none()),
|
|
35
|
+
set: () => import_effect.Effect.void,
|
|
36
|
+
remove: () => import_effect.Effect.void,
|
|
37
|
+
removeAll: import_effect.Effect.void,
|
|
38
|
+
capacity: opts?.capacity
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
CacheAdapter2.memory = memory;
|
|
42
|
+
function redis(opts) {
|
|
43
|
+
const encodeKey = (key) => `${opts.keyPrefix}:${JSON.stringify(key)}`;
|
|
44
|
+
const encodeEntry = (entry) => {
|
|
45
|
+
if (opts.schema) {
|
|
46
|
+
return import_effect.Schema.encode(opts.schema)(entry.value).pipe(
|
|
47
|
+
import_effect.Effect.map(
|
|
48
|
+
(encoded) => JSON.stringify({ value: encoded, storedAt: entry.storedAt })
|
|
49
|
+
),
|
|
50
|
+
import_effect.Effect.orDie
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
return import_effect.Effect.succeed(JSON.stringify(entry));
|
|
54
|
+
};
|
|
55
|
+
const decodeEntry = (raw) => {
|
|
56
|
+
const parsed = JSON.parse(raw);
|
|
57
|
+
if (opts.schema) {
|
|
58
|
+
return import_effect.Schema.decode(opts.schema)(parsed.value).pipe(
|
|
59
|
+
import_effect.Effect.map((value) => ({
|
|
60
|
+
value,
|
|
61
|
+
storedAt: parsed.storedAt
|
|
62
|
+
})),
|
|
63
|
+
import_effect.Effect.orDie
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
return import_effect.Effect.succeed(parsed);
|
|
67
|
+
};
|
|
68
|
+
return {
|
|
69
|
+
get: (key) => import_effect.Effect.gen(function* () {
|
|
70
|
+
const raw = yield* opts.client.get(encodeKey(key));
|
|
71
|
+
if (import_effect.Option.isNone(raw)) return import_effect.Option.none();
|
|
72
|
+
const entry = yield* decodeEntry(raw.value);
|
|
73
|
+
return import_effect.Option.some(entry);
|
|
74
|
+
}),
|
|
75
|
+
set: (key, entry, ttl) => import_effect.Effect.gen(function* () {
|
|
76
|
+
const encoded = yield* encodeEntry(entry);
|
|
77
|
+
yield* opts.client.set(
|
|
78
|
+
encodeKey(key),
|
|
79
|
+
encoded,
|
|
80
|
+
import_effect.Duration.toMillis(ttl)
|
|
81
|
+
);
|
|
82
|
+
}),
|
|
83
|
+
remove: (key) => opts.client.del(encodeKey(key)),
|
|
84
|
+
removeAll: import_effect.Effect.void
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
CacheAdapter2.redis = redis;
|
|
88
|
+
function tiered(l1, l2) {
|
|
89
|
+
return {
|
|
90
|
+
get: (key) => import_effect.Effect.gen(function* () {
|
|
91
|
+
const fromL1 = yield* l1.get(key);
|
|
92
|
+
if (import_effect.Option.isSome(fromL1)) return fromL1;
|
|
93
|
+
return yield* l2.get(key);
|
|
94
|
+
}),
|
|
95
|
+
set: (key, entry, ttl) => import_effect.Effect.all([l1.set(key, entry, ttl), l2.set(key, entry, ttl)], {
|
|
96
|
+
discard: true
|
|
97
|
+
}),
|
|
98
|
+
remove: (key) => import_effect.Effect.all([l1.remove(key), l2.remove(key)], { discard: true }),
|
|
99
|
+
removeAll: import_effect.Effect.all([l1.removeAll, l2.removeAll], { discard: true }),
|
|
100
|
+
capacity: l1.capacity
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
CacheAdapter2.tiered = tiered;
|
|
104
|
+
})(CacheAdapter || (CacheAdapter = {}));
|
|
105
|
+
|
|
106
|
+
// src/cache/cache.ts
|
|
107
|
+
var import_effect2 = require("effect");
|
|
108
|
+
var Cache;
|
|
109
|
+
((Cache2) => {
|
|
110
|
+
function entry(value, opts) {
|
|
111
|
+
return { _tag: "CacheEntry", value, ttl: opts.ttl, swr: opts.swr };
|
|
112
|
+
}
|
|
113
|
+
Cache2.entry = entry;
|
|
114
|
+
function make(opts) {
|
|
115
|
+
return import_effect2.Effect.gen(function* () {
|
|
116
|
+
const adapter = opts.adapter;
|
|
117
|
+
const defaultTtlMs = import_effect2.Duration.toMillis(import_effect2.Duration.decode(opts.ttl));
|
|
118
|
+
const defaultSwrMs = opts.swr ? import_effect2.Duration.toMillis(import_effect2.Duration.decode(opts.swr)) : 0;
|
|
119
|
+
const capacity = adapter?.capacity ?? Number.MAX_SAFE_INTEGER;
|
|
120
|
+
const refreshingKeys = /* @__PURE__ */ new Set();
|
|
121
|
+
const inner = yield* import_effect2.Cache.makeWith({
|
|
122
|
+
capacity,
|
|
123
|
+
lookup: (key) => import_effect2.Effect.gen(function* () {
|
|
124
|
+
const isRefreshing = refreshingKeys.has(JSON.stringify(key));
|
|
125
|
+
if (adapter && !isRefreshing) {
|
|
126
|
+
const cached = yield* adapter.get(key);
|
|
127
|
+
if (import_effect2.Option.isSome(cached)) {
|
|
128
|
+
const now = yield* import_effect2.Clock.currentTimeMillis;
|
|
129
|
+
const age = now - cached.value.storedAt;
|
|
130
|
+
const totalWindow = defaultTtlMs + defaultSwrMs;
|
|
131
|
+
if (age < totalWindow) {
|
|
132
|
+
return {
|
|
133
|
+
value: cached.value.value,
|
|
134
|
+
ttlMs: Math.max(0, defaultTtlMs - age),
|
|
135
|
+
swrMs: Math.max(
|
|
136
|
+
0,
|
|
137
|
+
defaultSwrMs - Math.max(0, age - defaultTtlMs)
|
|
138
|
+
)
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
const result = yield* opts.lookup(key);
|
|
144
|
+
const cv = resolveLookupResult(result, defaultTtlMs, defaultSwrMs);
|
|
145
|
+
if (adapter) {
|
|
146
|
+
const now = yield* import_effect2.Clock.currentTimeMillis;
|
|
147
|
+
yield* adapter.set(
|
|
148
|
+
key,
|
|
149
|
+
{ value: cv.value, storedAt: now },
|
|
150
|
+
import_effect2.Duration.millis(cv.ttlMs + cv.swrMs)
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
return cv;
|
|
154
|
+
}),
|
|
155
|
+
timeToLive: (exit) => {
|
|
156
|
+
if (import_effect2.Exit.isSuccess(exit)) {
|
|
157
|
+
return import_effect2.Duration.millis(exit.value.ttlMs + exit.value.swrMs);
|
|
158
|
+
}
|
|
159
|
+
return import_effect2.Duration.zero;
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
const get = (key) => import_effect2.Effect.gen(function* () {
|
|
163
|
+
const cv = yield* inner.get(key);
|
|
164
|
+
if (cv.swrMs > 0) {
|
|
165
|
+
const stats = yield* inner.entryStats(key);
|
|
166
|
+
if (import_effect2.Option.isSome(stats)) {
|
|
167
|
+
const now = yield* import_effect2.Clock.currentTimeMillis;
|
|
168
|
+
const age = now - stats.value.loadedMillis;
|
|
169
|
+
if (age > cv.ttlMs) {
|
|
170
|
+
const keyStr = JSON.stringify(key);
|
|
171
|
+
if (!refreshingKeys.has(keyStr)) {
|
|
172
|
+
refreshingKeys.add(keyStr);
|
|
173
|
+
yield* import_effect2.Effect.forkDaemon(
|
|
174
|
+
inner.refresh(key).pipe(
|
|
175
|
+
import_effect2.Effect.ensuring(
|
|
176
|
+
import_effect2.Effect.sync(() => {
|
|
177
|
+
refreshingKeys.delete(keyStr);
|
|
178
|
+
})
|
|
179
|
+
),
|
|
180
|
+
import_effect2.Effect.ignore
|
|
181
|
+
)
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return cv.value;
|
|
188
|
+
});
|
|
189
|
+
const invalidate = (key) => import_effect2.Effect.gen(function* () {
|
|
190
|
+
yield* inner.invalidate(key);
|
|
191
|
+
if (adapter) yield* adapter.remove(key);
|
|
192
|
+
});
|
|
193
|
+
const invalidateAll = import_effect2.Effect.gen(function* () {
|
|
194
|
+
yield* inner.invalidateAll;
|
|
195
|
+
if (adapter) yield* adapter.removeAll;
|
|
196
|
+
});
|
|
197
|
+
return { get, invalidate, invalidateAll };
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
Cache2.make = make;
|
|
201
|
+
})(Cache || (Cache = {}));
|
|
202
|
+
function isCacheEntry(result) {
|
|
203
|
+
return typeof result === "object" && result !== null && "_tag" in result && result._tag === "CacheEntry";
|
|
204
|
+
}
|
|
205
|
+
function resolveLookupResult(result, defaultTtlMs, defaultSwrMs) {
|
|
206
|
+
if (isCacheEntry(result)) {
|
|
207
|
+
return {
|
|
208
|
+
value: result.value,
|
|
209
|
+
ttlMs: import_effect2.Duration.toMillis(import_effect2.Duration.decode(result.ttl)),
|
|
210
|
+
swrMs: result.swr ? import_effect2.Duration.toMillis(import_effect2.Duration.decode(result.swr)) : 0
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
return { value: result, ttlMs: defaultTtlMs, swrMs: defaultSwrMs };
|
|
214
|
+
}
|
|
215
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
216
|
+
0 && (module.exports = {
|
|
217
|
+
Cache,
|
|
218
|
+
CacheAdapter
|
|
219
|
+
});
|
|
220
|
+
//# sourceMappingURL=cache.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/exports/cache.ts","../../src/cache/adapter.ts","../../src/cache/cache.ts"],"sourcesContent":["export {\n\tCacheAdapter,\n\ttype CacheEntry,\n\ttype RedisClient,\n} from '../cache/adapter.js';\nexport { Cache, type CacheInstance } from '../cache/cache.js';\n","import { Duration, Effect, Option, Schema } from 'effect';\n\nexport type CacheEntry<Value> = {\n\treadonly value: Value;\n\treadonly storedAt: number;\n};\n\nexport type RedisClient = {\n\treadonly get: (key: string) => Effect.Effect<Option.Option<string>>;\n\treadonly set: (\n\t\tkey: string,\n\t\tvalue: string,\n\t\tttlMs: number,\n\t) => Effect.Effect<void>;\n\treadonly del: (key: string) => Effect.Effect<void>;\n};\n\nexport type CacheAdapter<Key, Value> = {\n\treadonly get: (key: Key) => Effect.Effect<Option.Option<CacheEntry<Value>>>;\n\treadonly set: (\n\t\tkey: Key,\n\t\tentry: CacheEntry<Value>,\n\t\tttl: Duration.Duration,\n\t) => Effect.Effect<void>;\n\treadonly remove: (key: Key) => Effect.Effect<void>;\n\treadonly removeAll: Effect.Effect<void>;\n\treadonly capacity?: number;\n};\n\nexport namespace CacheAdapter {\n\t// No-op adapter — Effect Cache IS the in-memory store. This only carries `capacity`.\n\texport function memory<Key, Value>(opts?: {\n\t\tcapacity?: number;\n\t}): CacheAdapter<Key, Value> {\n\t\treturn {\n\t\t\tget: () => Effect.succeed(Option.none()),\n\t\t\tset: () => Effect.void,\n\t\t\tremove: () => Effect.void,\n\t\t\tremoveAll: Effect.void,\n\t\t\tcapacity: opts?.capacity,\n\t\t};\n\t}\n\n\texport function redis<Key, Value>(opts: {\n\t\tclient: RedisClient;\n\t\tkeyPrefix: string;\n\t\tschema?: Schema.Schema<Value, string>;\n\t}): CacheAdapter<Key, Value> {\n\t\tconst encodeKey = (key: Key) => `${opts.keyPrefix}:${JSON.stringify(key)}`;\n\n\t\tconst encodeEntry = (entry: CacheEntry<Value>): Effect.Effect<string> => {\n\t\t\tif (opts.schema) {\n\t\t\t\treturn Schema.encode(opts.schema)(entry.value).pipe(\n\t\t\t\t\tEffect.map((encoded) =>\n\t\t\t\t\t\tJSON.stringify({ value: encoded, storedAt: entry.storedAt }),\n\t\t\t\t\t),\n\t\t\t\t\tEffect.orDie,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn Effect.succeed(JSON.stringify(entry));\n\t\t};\n\n\t\tconst decodeEntry = (raw: string): Effect.Effect<CacheEntry<Value>> => {\n\t\t\tconst parsed = JSON.parse(raw);\n\t\t\tif (opts.schema) {\n\t\t\t\treturn Schema.decode(opts.schema)(parsed.value).pipe(\n\t\t\t\t\tEffect.map((value) => ({\n\t\t\t\t\t\tvalue,\n\t\t\t\t\t\tstoredAt: parsed.storedAt as number,\n\t\t\t\t\t})),\n\t\t\t\t\tEffect.orDie,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn Effect.succeed(parsed as CacheEntry<Value>);\n\t\t};\n\n\t\treturn {\n\t\t\tget: (key) =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst raw = yield* opts.client.get(encodeKey(key));\n\t\t\t\t\tif (Option.isNone(raw)) return Option.none<CacheEntry<Value>>();\n\t\t\t\t\tconst entry = yield* decodeEntry(raw.value);\n\t\t\t\t\treturn Option.some(entry);\n\t\t\t\t}),\n\t\t\tset: (key, entry, ttl) =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst encoded = yield* encodeEntry(entry);\n\t\t\t\t\tyield* opts.client.set(\n\t\t\t\t\t\tencodeKey(key),\n\t\t\t\t\t\tencoded,\n\t\t\t\t\t\tDuration.toMillis(ttl),\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\tremove: (key) => opts.client.del(encodeKey(key)),\n\t\t\tremoveAll: Effect.void,\n\t\t};\n\t}\n\n\texport function tiered<Key, Value>(\n\t\tl1: CacheAdapter<Key, Value>,\n\t\tl2: CacheAdapter<Key, Value>,\n\t): CacheAdapter<Key, Value> {\n\t\treturn {\n\t\t\tget: (key) =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst fromL1 = yield* l1.get(key);\n\t\t\t\t\tif (Option.isSome(fromL1)) return fromL1;\n\t\t\t\t\treturn yield* l2.get(key);\n\t\t\t\t}),\n\t\t\tset: (key, entry, ttl) =>\n\t\t\t\tEffect.all([l1.set(key, entry, ttl), l2.set(key, entry, ttl)], {\n\t\t\t\t\tdiscard: true,\n\t\t\t\t}),\n\t\t\tremove: (key) =>\n\t\t\t\tEffect.all([l1.remove(key), l2.remove(key)], { discard: true }),\n\t\t\tremoveAll: Effect.all([l1.removeAll, l2.removeAll], { discard: true }),\n\t\t\tcapacity: l1.capacity,\n\t\t};\n\t}\n}\n","import {\n\tClock,\n\tDuration,\n\tEffect,\n\tCache as EffectCache,\n\tExit,\n\tOption,\n} from 'effect';\nimport type { CacheAdapter, CacheEntry } from './adapter.js';\n\n// Bundles value with resolved TTL/SWR so the SWR check at read time uses per-entry durations\ntype CacheValue<Value> = {\n\treadonly value: Value;\n\treadonly ttlMs: number;\n\treadonly swrMs: number;\n};\n\nexport type CacheInstance<Key, Value, Error> = {\n\treadonly get: (key: Key) => Effect.Effect<Value, Error>;\n\treadonly invalidate: (key: Key) => Effect.Effect<void>;\n\treadonly invalidateAll: Effect.Effect<void>;\n};\n\nexport namespace Cache {\n\texport type Entry<Value> = {\n\t\treadonly _tag: 'CacheEntry';\n\t\treadonly value: Value;\n\t\treadonly ttl: Duration.DurationInput;\n\t\treadonly swr?: Duration.DurationInput;\n\t};\n\n\texport function entry<Value>(\n\t\tvalue: Value,\n\t\topts: { ttl: Duration.DurationInput; swr?: Duration.DurationInput },\n\t): Entry<Value> {\n\t\treturn { _tag: 'CacheEntry', value, ttl: opts.ttl, swr: opts.swr };\n\t}\n\n\texport type LookupResult<Value> = Value | Entry<Value>;\n\n\texport function make<Key, Value, Error = never, R = never>(opts: {\n\t\tttl: Duration.DurationInput;\n\t\tswr?: Duration.DurationInput;\n\t\tlookup: (key: Key) => Effect.Effect<LookupResult<Value>, Error, R>;\n\t\tadapter?: CacheAdapter<Key, Value>;\n\t}): Effect.Effect<CacheInstance<Key, Value, Error>, never, R> {\n\t\treturn Effect.gen(function* () {\n\t\t\tconst adapter = opts.adapter;\n\t\t\tconst defaultTtlMs = Duration.toMillis(Duration.decode(opts.ttl));\n\t\t\tconst defaultSwrMs = opts.swr\n\t\t\t\t? Duration.toMillis(Duration.decode(opts.swr))\n\t\t\t\t: 0;\n\t\t\tconst capacity = adapter?.capacity ?? Number.MAX_SAFE_INTEGER;\n\n\t\t\t// Safe without synchronization — no yield points between has() and add() (cooperative scheduling)\n\t\t\tconst refreshingKeys = new Set<string>();\n\n\t\t\t// makeWith uses `timeToLive: (exit) => Duration` — the lookup stores CacheValue\n\t\t\t// so timeToLive can extract the total window (ttl + swr) from the exit result\n\t\t\tconst inner = yield* EffectCache.makeWith({\n\t\t\t\tcapacity,\n\t\t\t\tlookup: (key: Key) =>\n\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\tconst isRefreshing = refreshingKeys.has(JSON.stringify(key));\n\n\t\t\t\t\t\tif (adapter && !isRefreshing) {\n\t\t\t\t\t\t\tconst cached = yield* adapter.get(key);\n\t\t\t\t\t\t\tif (Option.isSome(cached)) {\n\t\t\t\t\t\t\t\tconst now = yield* Clock.currentTimeMillis;\n\t\t\t\t\t\t\t\tconst age = now - cached.value.storedAt;\n\t\t\t\t\t\t\t\tconst totalWindow = defaultTtlMs + defaultSwrMs;\n\t\t\t\t\t\t\t\tif (age < totalWindow) {\n\t\t\t\t\t\t\t\t\t// Adjust remaining TTL/SWR for elapsed age so SWR triggers at correct real-world time\n\t\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\t\tvalue: cached.value.value,\n\t\t\t\t\t\t\t\t\t\tttlMs: Math.max(0, defaultTtlMs - age),\n\t\t\t\t\t\t\t\t\t\tswrMs: Math.max(\n\t\t\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\t\t\tdefaultSwrMs - Math.max(0, age - defaultTtlMs),\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t} satisfies CacheValue<Value>;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst result = yield* opts.lookup(key);\n\t\t\t\t\t\tconst cv = resolveLookupResult(result, defaultTtlMs, defaultSwrMs);\n\n\t\t\t\t\t\tif (adapter) {\n\t\t\t\t\t\t\tconst now = yield* Clock.currentTimeMillis;\n\t\t\t\t\t\t\tyield* adapter.set(\n\t\t\t\t\t\t\t\tkey,\n\t\t\t\t\t\t\t\t{ value: cv.value, storedAt: now } satisfies CacheEntry<Value>,\n\t\t\t\t\t\t\t\tDuration.millis(cv.ttlMs + cv.swrMs),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn cv;\n\t\t\t\t\t}),\n\t\t\t\ttimeToLive: (exit) => {\n\t\t\t\t\tif (Exit.isSuccess(exit)) {\n\t\t\t\t\t\treturn Duration.millis(exit.value.ttlMs + exit.value.swrMs);\n\t\t\t\t\t}\n\t\t\t\t\treturn Duration.zero;\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tconst get = (key: Key) =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst cv = yield* inner.get(key);\n\n\t\t\t\t\tif (cv.swrMs > 0) {\n\t\t\t\t\t\tconst stats = yield* inner.entryStats(key);\n\t\t\t\t\t\tif (Option.isSome(stats)) {\n\t\t\t\t\t\t\tconst now = yield* Clock.currentTimeMillis;\n\t\t\t\t\t\t\tconst age = now - stats.value.loadedMillis;\n\t\t\t\t\t\t\tif (age > cv.ttlMs) {\n\t\t\t\t\t\t\t\tconst keyStr = JSON.stringify(key);\n\t\t\t\t\t\t\t\tif (!refreshingKeys.has(keyStr)) {\n\t\t\t\t\t\t\t\t\trefreshingKeys.add(keyStr);\n\t\t\t\t\t\t\t\t\t// refresh() recomputes without invalidating, so stale value remains available during recomputation\n\t\t\t\t\t\t\t\t\tyield* Effect.forkDaemon(\n\t\t\t\t\t\t\t\t\t\tinner.refresh(key).pipe(\n\t\t\t\t\t\t\t\t\t\t\tEffect.ensuring(\n\t\t\t\t\t\t\t\t\t\t\t\tEffect.sync(() => {\n\t\t\t\t\t\t\t\t\t\t\t\t\trefreshingKeys.delete(keyStr);\n\t\t\t\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\tEffect.ignore,\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn cv.value;\n\t\t\t\t});\n\n\t\t\tconst invalidate = (key: Key) =>\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tyield* inner.invalidate(key);\n\t\t\t\t\tif (adapter) yield* adapter.remove(key);\n\t\t\t\t});\n\n\t\t\tconst invalidateAll = Effect.gen(function* () {\n\t\t\t\tyield* inner.invalidateAll;\n\t\t\t\tif (adapter) yield* adapter.removeAll;\n\t\t\t});\n\n\t\t\treturn { get, invalidate, invalidateAll } satisfies CacheInstance<\n\t\t\t\tKey,\n\t\t\t\tValue,\n\t\t\t\tError\n\t\t\t>;\n\t\t});\n\t}\n}\n\nfunction isCacheEntry<Value>(\n\tresult: Cache.LookupResult<Value>,\n): result is Cache.Entry<Value> {\n\treturn (\n\t\ttypeof result === 'object' &&\n\t\tresult !== null &&\n\t\t'_tag' in result &&\n\t\t(result as Cache.Entry<Value>)._tag === 'CacheEntry'\n\t);\n}\n\nfunction resolveLookupResult<Value>(\n\tresult: Cache.LookupResult<Value>,\n\tdefaultTtlMs: number,\n\tdefaultSwrMs: number,\n): CacheValue<Value> {\n\tif (isCacheEntry(result)) {\n\t\treturn {\n\t\t\tvalue: result.value,\n\t\t\tttlMs: Duration.toMillis(Duration.decode(result.ttl)),\n\t\t\tswrMs: result.swr ? Duration.toMillis(Duration.decode(result.swr)) : 0,\n\t\t};\n\t}\n\treturn { value: result, ttlMs: defaultTtlMs, swrMs: defaultSwrMs };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,oBAAiD;AA6B1C,IAAU;AAAA,CAAV,CAAUA,kBAAV;AAEC,WAAS,OAAmB,MAEN;AAC5B,WAAO;AAAA,MACN,KAAK,MAAM,qBAAO,QAAQ,qBAAO,KAAK,CAAC;AAAA,MACvC,KAAK,MAAM,qBAAO;AAAA,MAClB,QAAQ,MAAM,qBAAO;AAAA,MACrB,WAAW,qBAAO;AAAA,MAClB,UAAU,MAAM;AAAA,IACjB;AAAA,EACD;AAVO,EAAAA,cAAS;AAYT,WAAS,MAAkB,MAIL;AAC5B,UAAM,YAAY,CAAC,QAAa,GAAG,KAAK,SAAS,IAAI,KAAK,UAAU,GAAG,CAAC;AAExE,UAAM,cAAc,CAAC,UAAoD;AACxE,UAAI,KAAK,QAAQ;AAChB,eAAO,qBAAO,OAAO,KAAK,MAAM,EAAE,MAAM,KAAK,EAAE;AAAA,UAC9C,qBAAO;AAAA,YAAI,CAAC,YACX,KAAK,UAAU,EAAE,OAAO,SAAS,UAAU,MAAM,SAAS,CAAC;AAAA,UAC5D;AAAA,UACA,qBAAO;AAAA,QACR;AAAA,MACD;AACA,aAAO,qBAAO,QAAQ,KAAK,UAAU,KAAK,CAAC;AAAA,IAC5C;AAEA,UAAM,cAAc,CAAC,QAAkD;AACtE,YAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,UAAI,KAAK,QAAQ;AAChB,eAAO,qBAAO,OAAO,KAAK,MAAM,EAAE,OAAO,KAAK,EAAE;AAAA,UAC/C,qBAAO,IAAI,CAAC,WAAW;AAAA,YACtB;AAAA,YACA,UAAU,OAAO;AAAA,UAClB,EAAE;AAAA,UACF,qBAAO;AAAA,QACR;AAAA,MACD;AACA,aAAO,qBAAO,QAAQ,MAA2B;AAAA,IAClD;AAEA,WAAO;AAAA,MACN,KAAK,CAAC,QACL,qBAAO,IAAI,aAAa;AACvB,cAAM,MAAM,OAAO,KAAK,OAAO,IAAI,UAAU,GAAG,CAAC;AACjD,YAAI,qBAAO,OAAO,GAAG,EAAG,QAAO,qBAAO,KAAwB;AAC9D,cAAM,QAAQ,OAAO,YAAY,IAAI,KAAK;AAC1C,eAAO,qBAAO,KAAK,KAAK;AAAA,MACzB,CAAC;AAAA,MACF,KAAK,CAAC,KAAK,OAAO,QACjB,qBAAO,IAAI,aAAa;AACvB,cAAM,UAAU,OAAO,YAAY,KAAK;AACxC,eAAO,KAAK,OAAO;AAAA,UAClB,UAAU,GAAG;AAAA,UACb;AAAA,UACA,uBAAS,SAAS,GAAG;AAAA,QACtB;AAAA,MACD,CAAC;AAAA,MACF,QAAQ,CAAC,QAAQ,KAAK,OAAO,IAAI,UAAU,GAAG,CAAC;AAAA,MAC/C,WAAW,qBAAO;AAAA,IACnB;AAAA,EACD;AArDO,EAAAA,cAAS;AAuDT,WAAS,OACf,IACA,IAC2B;AAC3B,WAAO;AAAA,MACN,KAAK,CAAC,QACL,qBAAO,IAAI,aAAa;AACvB,cAAM,SAAS,OAAO,GAAG,IAAI,GAAG;AAChC,YAAI,qBAAO,OAAO,MAAM,EAAG,QAAO;AAClC,eAAO,OAAO,GAAG,IAAI,GAAG;AAAA,MACzB,CAAC;AAAA,MACF,KAAK,CAAC,KAAK,OAAO,QACjB,qBAAO,IAAI,CAAC,GAAG,IAAI,KAAK,OAAO,GAAG,GAAG,GAAG,IAAI,KAAK,OAAO,GAAG,CAAC,GAAG;AAAA,QAC9D,SAAS;AAAA,MACV,CAAC;AAAA,MACF,QAAQ,CAAC,QACR,qBAAO,IAAI,CAAC,GAAG,OAAO,GAAG,GAAG,GAAG,OAAO,GAAG,CAAC,GAAG,EAAE,SAAS,KAAK,CAAC;AAAA,MAC/D,WAAW,qBAAO,IAAI,CAAC,GAAG,WAAW,GAAG,SAAS,GAAG,EAAE,SAAS,KAAK,CAAC;AAAA,MACrE,UAAU,GAAG;AAAA,IACd;AAAA,EACD;AApBO,EAAAA,cAAS;AAAA,GArEA;;;AC7BjB,IAAAC,iBAOO;AAgBA,IAAU;AAAA,CAAV,CAAUC,WAAV;AAQC,WAAS,MACf,OACA,MACe;AACf,WAAO,EAAE,MAAM,cAAc,OAAO,KAAK,KAAK,KAAK,KAAK,KAAK,IAAI;AAAA,EAClE;AALO,EAAAA,OAAS;AAST,WAAS,KAA2C,MAKG;AAC7D,WAAO,sBAAO,IAAI,aAAa;AAC9B,YAAM,UAAU,KAAK;AACrB,YAAM,eAAe,wBAAS,SAAS,wBAAS,OAAO,KAAK,GAAG,CAAC;AAChE,YAAM,eAAe,KAAK,MACvB,wBAAS,SAAS,wBAAS,OAAO,KAAK,GAAG,CAAC,IAC3C;AACH,YAAM,WAAW,SAAS,YAAY,OAAO;AAG7C,YAAM,iBAAiB,oBAAI,IAAY;AAIvC,YAAM,QAAQ,OAAO,eAAAC,MAAY,SAAS;AAAA,QACzC;AAAA,QACA,QAAQ,CAAC,QACR,sBAAO,IAAI,aAAa;AACvB,gBAAM,eAAe,eAAe,IAAI,KAAK,UAAU,GAAG,CAAC;AAE3D,cAAI,WAAW,CAAC,cAAc;AAC7B,kBAAM,SAAS,OAAO,QAAQ,IAAI,GAAG;AACrC,gBAAI,sBAAO,OAAO,MAAM,GAAG;AAC1B,oBAAM,MAAM,OAAO,qBAAM;AACzB,oBAAM,MAAM,MAAM,OAAO,MAAM;AAC/B,oBAAM,cAAc,eAAe;AACnC,kBAAI,MAAM,aAAa;AAEtB,uBAAO;AAAA,kBACN,OAAO,OAAO,MAAM;AAAA,kBACpB,OAAO,KAAK,IAAI,GAAG,eAAe,GAAG;AAAA,kBACrC,OAAO,KAAK;AAAA,oBACX;AAAA,oBACA,eAAe,KAAK,IAAI,GAAG,MAAM,YAAY;AAAA,kBAC9C;AAAA,gBACD;AAAA,cACD;AAAA,YACD;AAAA,UACD;AAEA,gBAAM,SAAS,OAAO,KAAK,OAAO,GAAG;AACrC,gBAAM,KAAK,oBAAoB,QAAQ,cAAc,YAAY;AAEjE,cAAI,SAAS;AACZ,kBAAM,MAAM,OAAO,qBAAM;AACzB,mBAAO,QAAQ;AAAA,cACd;AAAA,cACA,EAAE,OAAO,GAAG,OAAO,UAAU,IAAI;AAAA,cACjC,wBAAS,OAAO,GAAG,QAAQ,GAAG,KAAK;AAAA,YACpC;AAAA,UACD;AAEA,iBAAO;AAAA,QACR,CAAC;AAAA,QACF,YAAY,CAAC,SAAS;AACrB,cAAI,oBAAK,UAAU,IAAI,GAAG;AACzB,mBAAO,wBAAS,OAAO,KAAK,MAAM,QAAQ,KAAK,MAAM,KAAK;AAAA,UAC3D;AACA,iBAAO,wBAAS;AAAA,QACjB;AAAA,MACD,CAAC;AAED,YAAM,MAAM,CAAC,QACZ,sBAAO,IAAI,aAAa;AACvB,cAAM,KAAK,OAAO,MAAM,IAAI,GAAG;AAE/B,YAAI,GAAG,QAAQ,GAAG;AACjB,gBAAM,QAAQ,OAAO,MAAM,WAAW,GAAG;AACzC,cAAI,sBAAO,OAAO,KAAK,GAAG;AACzB,kBAAM,MAAM,OAAO,qBAAM;AACzB,kBAAM,MAAM,MAAM,MAAM,MAAM;AAC9B,gBAAI,MAAM,GAAG,OAAO;AACnB,oBAAM,SAAS,KAAK,UAAU,GAAG;AACjC,kBAAI,CAAC,eAAe,IAAI,MAAM,GAAG;AAChC,+BAAe,IAAI,MAAM;AAEzB,uBAAO,sBAAO;AAAA,kBACb,MAAM,QAAQ,GAAG,EAAE;AAAA,oBAClB,sBAAO;AAAA,sBACN,sBAAO,KAAK,MAAM;AACjB,uCAAe,OAAO,MAAM;AAAA,sBAC7B,CAAC;AAAA,oBACF;AAAA,oBACA,sBAAO;AAAA,kBACR;AAAA,gBACD;AAAA,cACD;AAAA,YACD;AAAA,UACD;AAAA,QACD;AAEA,eAAO,GAAG;AAAA,MACX,CAAC;AAEF,YAAM,aAAa,CAAC,QACnB,sBAAO,IAAI,aAAa;AACvB,eAAO,MAAM,WAAW,GAAG;AAC3B,YAAI,QAAS,QAAO,QAAQ,OAAO,GAAG;AAAA,MACvC,CAAC;AAEF,YAAM,gBAAgB,sBAAO,IAAI,aAAa;AAC7C,eAAO,MAAM;AACb,YAAI,QAAS,QAAO,QAAQ;AAAA,MAC7B,CAAC;AAED,aAAO,EAAE,KAAK,YAAY,cAAc;AAAA,IAKzC,CAAC;AAAA,EACF;AApHO,EAAAD,OAAS;AAAA,GAjBA;AAwIjB,SAAS,aACR,QAC+B;AAC/B,SACC,OAAO,WAAW,YAClB,WAAW,QACX,UAAU,UACT,OAA8B,SAAS;AAE1C;AAEA,SAAS,oBACR,QACA,cACA,cACoB;AACpB,MAAI,aAAa,MAAM,GAAG;AACzB,WAAO;AAAA,MACN,OAAO,OAAO;AAAA,MACd,OAAO,wBAAS,SAAS,wBAAS,OAAO,OAAO,GAAG,CAAC;AAAA,MACpD,OAAO,OAAO,MAAM,wBAAS,SAAS,wBAAS,OAAO,OAAO,GAAG,CAAC,IAAI;AAAA,IACtE;AAAA,EACD;AACA,SAAO,EAAE,OAAO,QAAQ,OAAO,cAAc,OAAO,aAAa;AAClE;","names":["CacheAdapter","import_effect","Cache","EffectCache"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { C as CacheAdapter } from '../adapter-DLhjFlOu.cjs';
|
|
2
|
+
export { a as CacheEntry, R as RedisClient } from '../adapter-DLhjFlOu.cjs';
|
|
3
|
+
import { Duration, Effect } from 'effect';
|
|
4
|
+
|
|
5
|
+
type CacheInstance<Key, Value, Error> = {
|
|
6
|
+
readonly get: (key: Key) => Effect.Effect<Value, Error>;
|
|
7
|
+
readonly invalidate: (key: Key) => Effect.Effect<void>;
|
|
8
|
+
readonly invalidateAll: Effect.Effect<void>;
|
|
9
|
+
};
|
|
10
|
+
declare namespace Cache {
|
|
11
|
+
type Entry<Value> = {
|
|
12
|
+
readonly _tag: 'CacheEntry';
|
|
13
|
+
readonly value: Value;
|
|
14
|
+
readonly ttl: Duration.DurationInput;
|
|
15
|
+
readonly swr?: Duration.DurationInput;
|
|
16
|
+
};
|
|
17
|
+
function entry<Value>(value: Value, opts: {
|
|
18
|
+
ttl: Duration.DurationInput;
|
|
19
|
+
swr?: Duration.DurationInput;
|
|
20
|
+
}): Entry<Value>;
|
|
21
|
+
type LookupResult<Value> = Value | Entry<Value>;
|
|
22
|
+
function make<Key, Value, Error = never, R = never>(opts: {
|
|
23
|
+
ttl: Duration.DurationInput;
|
|
24
|
+
swr?: Duration.DurationInput;
|
|
25
|
+
lookup: (key: Key) => Effect.Effect<LookupResult<Value>, Error, R>;
|
|
26
|
+
adapter?: CacheAdapter<Key, Value>;
|
|
27
|
+
}): Effect.Effect<CacheInstance<Key, Value, Error>, never, R>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export { Cache, CacheAdapter, type CacheInstance };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { C as CacheAdapter } from '../adapter-DLhjFlOu.js';
|
|
2
|
+
export { a as CacheEntry, R as RedisClient } from '../adapter-DLhjFlOu.js';
|
|
3
|
+
import { Duration, Effect } from 'effect';
|
|
4
|
+
|
|
5
|
+
type CacheInstance<Key, Value, Error> = {
|
|
6
|
+
readonly get: (key: Key) => Effect.Effect<Value, Error>;
|
|
7
|
+
readonly invalidate: (key: Key) => Effect.Effect<void>;
|
|
8
|
+
readonly invalidateAll: Effect.Effect<void>;
|
|
9
|
+
};
|
|
10
|
+
declare namespace Cache {
|
|
11
|
+
type Entry<Value> = {
|
|
12
|
+
readonly _tag: 'CacheEntry';
|
|
13
|
+
readonly value: Value;
|
|
14
|
+
readonly ttl: Duration.DurationInput;
|
|
15
|
+
readonly swr?: Duration.DurationInput;
|
|
16
|
+
};
|
|
17
|
+
function entry<Value>(value: Value, opts: {
|
|
18
|
+
ttl: Duration.DurationInput;
|
|
19
|
+
swr?: Duration.DurationInput;
|
|
20
|
+
}): Entry<Value>;
|
|
21
|
+
type LookupResult<Value> = Value | Entry<Value>;
|
|
22
|
+
function make<Key, Value, Error = never, R = never>(opts: {
|
|
23
|
+
ttl: Duration.DurationInput;
|
|
24
|
+
swr?: Duration.DurationInput;
|
|
25
|
+
lookup: (key: Key) => Effect.Effect<LookupResult<Value>, Error, R>;
|
|
26
|
+
adapter?: CacheAdapter<Key, Value>;
|
|
27
|
+
}): Effect.Effect<CacheInstance<Key, Value, Error>, never, R>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export { Cache, CacheAdapter, type CacheInstance };
|