@effect-native/fetch-hooks 0.0.1-placeholder → 0.0.2

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 (48) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +35 -0
  3. package/dist/binary-extractor.d.ts +9 -0
  4. package/dist/binary-extractor.d.ts.map +1 -0
  5. package/dist/binary-extractor.js +85 -0
  6. package/dist/binary-extractor.js.map +1 -0
  7. package/dist/cache-manager.d.ts +8 -0
  8. package/dist/cache-manager.d.ts.map +1 -0
  9. package/dist/cache-manager.js +408 -0
  10. package/dist/cache-manager.js.map +1 -0
  11. package/dist/environment.d.ts +5 -0
  12. package/dist/environment.d.ts.map +1 -0
  13. package/dist/environment.js +25 -0
  14. package/dist/environment.js.map +1 -0
  15. package/dist/filesystem-storage.d.ts +10 -0
  16. package/dist/filesystem-storage.d.ts.map +1 -0
  17. package/dist/filesystem-storage.js +112 -0
  18. package/dist/filesystem-storage.js.map +1 -0
  19. package/dist/flat-file-storage.d.ts +33 -0
  20. package/dist/flat-file-storage.d.ts.map +1 -0
  21. package/dist/flat-file-storage.js +153 -0
  22. package/dist/flat-file-storage.js.map +1 -0
  23. package/dist/index.d.ts +9 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +183 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/request-hasher.d.ts +5 -0
  28. package/dist/request-hasher.d.ts.map +1 -0
  29. package/dist/request-hasher.js +74 -0
  30. package/dist/request-hasher.js.map +1 -0
  31. package/dist/sse-handler.d.ts +9 -0
  32. package/dist/sse-handler.d.ts.map +1 -0
  33. package/dist/sse-handler.js +225 -0
  34. package/dist/sse-handler.js.map +1 -0
  35. package/dist/types.d.ts +116 -0
  36. package/dist/types.d.ts.map +1 -0
  37. package/dist/types.js +2 -0
  38. package/dist/types.js.map +1 -0
  39. package/package.json +52 -3
  40. package/src/binary-extractor.ts +104 -0
  41. package/src/cache-manager.ts +499 -0
  42. package/src/environment.ts +27 -0
  43. package/src/filesystem-storage.ts +125 -0
  44. package/src/flat-file-storage.ts +170 -0
  45. package/src/index.ts +249 -0
  46. package/src/request-hasher.ts +86 -0
  47. package/src/sse-handler.ts +281 -0
  48. package/src/types.ts +140 -0
@@ -0,0 +1,10 @@
1
+ import type { CacheKey, CacheStorage, KV, KVStream, TimedChunk } from "./types.js";
2
+ /** Create a KV store backed by JSON files */
3
+ export declare function createJsonFileKV<T>(baseDir: string, filename: string): KV<CacheKey, T>;
4
+ /** Create a KV store backed by binary files */
5
+ export declare function createBinaryFileKV(baseDir: string, filename: string): KV<CacheKey, Uint8Array>;
6
+ /** Create a streaming KV store for SSE chunks backed by JSONL files */
7
+ export declare function createJsonlFileKVStream(baseDir: string, filename: string): KVStream<CacheKey, TimedChunk>;
8
+ /** Create a complete CacheStorage backed by the filesystem */
9
+ export declare function createFilesystemStorage(baseDir: string): CacheStorage;
10
+ //# sourceMappingURL=filesystem-storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filesystem-storage.d.ts","sourceRoot":"","sources":["../src/filesystem-storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAqC,QAAQ,EAAE,YAAY,EAAE,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAqBrH,6CAA6C;AAC7C,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,CAsBtF;AAED,+CAA+C;AAC/C,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC,CAsB9F;AAED,uEAAuE;AACvE,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC,CAyCzG;AAED,8DAA8D;AAC9D,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CAQrE"}
@@ -0,0 +1,112 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { jsonlToTimedChunks, timedChunksToJsonl } from "./sse-handler.js";
4
+ function ensureCacheDir(baseDir, cacheKey) {
5
+ const cacheDir = join(baseDir, cacheKey);
6
+ if (!existsSync(cacheDir)) {
7
+ try {
8
+ mkdirSync(cacheDir, { recursive: true });
9
+ }
10
+ catch (error) {
11
+ // Handle race condition where directory was created between check and mkdir
12
+ if (!(error instanceof Error && error.code === "EEXIST")) {
13
+ throw error;
14
+ }
15
+ }
16
+ }
17
+ return cacheDir;
18
+ }
19
+ /** Create a KV store backed by JSON files */
20
+ export function createJsonFileKV(baseDir, filename) {
21
+ return {
22
+ async get([key]) {
23
+ const filePath = join(baseDir, key, filename);
24
+ if (!existsSync(filePath)) {
25
+ return null;
26
+ }
27
+ const content = readFileSync(filePath, "utf-8");
28
+ return JSON.parse(content);
29
+ },
30
+ async set([key], value) {
31
+ const cacheDir = ensureCacheDir(baseDir, key);
32
+ const filePath = join(cacheDir, filename);
33
+ writeFileSync(filePath, JSON.stringify(value, null, 2), "utf-8");
34
+ },
35
+ async has([key]) {
36
+ const filePath = join(baseDir, key, filename);
37
+ return existsSync(filePath);
38
+ }
39
+ };
40
+ }
41
+ /** Create a KV store backed by binary files */
42
+ export function createBinaryFileKV(baseDir, filename) {
43
+ return {
44
+ async get([key]) {
45
+ const filePath = join(baseDir, key, filename);
46
+ if (!existsSync(filePath)) {
47
+ return null;
48
+ }
49
+ const buffer = readFileSync(filePath);
50
+ return new Uint8Array(buffer);
51
+ },
52
+ async set([key], value) {
53
+ const cacheDir = ensureCacheDir(baseDir, key);
54
+ const filePath = join(cacheDir, filename);
55
+ writeFileSync(filePath, value);
56
+ },
57
+ async has([key]) {
58
+ const filePath = join(baseDir, key, filename);
59
+ return existsSync(filePath);
60
+ }
61
+ };
62
+ }
63
+ /** Create a streaming KV store for SSE chunks backed by JSONL files */
64
+ export function createJsonlFileKVStream(baseDir, filename) {
65
+ return {
66
+ async *get([key]) {
67
+ const filePath = join(baseDir, key, filename);
68
+ if (!existsSync(filePath)) {
69
+ return;
70
+ }
71
+ // Read entire file and parse - streaming line-by-line is complex due to JSONL format
72
+ // Future optimization: could stream lines and parse incrementally
73
+ const content = readFileSync(filePath, "utf-8");
74
+ const chunks = jsonlToTimedChunks(content);
75
+ for (const chunk of chunks) {
76
+ yield chunk;
77
+ }
78
+ },
79
+ async set([key], values) {
80
+ const cacheDir = ensureCacheDir(baseDir, key);
81
+ const filePath = join(cacheDir, filename);
82
+ // Collect all values if async iterable
83
+ let chunks;
84
+ if (Array.isArray(values)) {
85
+ chunks = values;
86
+ }
87
+ else {
88
+ chunks = [];
89
+ for await (const chunk of values) {
90
+ chunks.push(chunk);
91
+ }
92
+ }
93
+ const jsonl = timedChunksToJsonl(chunks);
94
+ writeFileSync(filePath, jsonl, "utf-8");
95
+ },
96
+ async has([key]) {
97
+ const filePath = join(baseDir, key, filename);
98
+ return existsSync(filePath);
99
+ }
100
+ };
101
+ }
102
+ /** Create a complete CacheStorage backed by the filesystem */
103
+ export function createFilesystemStorage(baseDir) {
104
+ return {
105
+ requests: createJsonFileKV(baseDir, "request.json"),
106
+ responseMeta: createJsonFileKV(baseDir, "response.meta.json"),
107
+ responseBody: createJsonFileKV(baseDir, "response.json"),
108
+ binaryBody: createBinaryFileKV(baseDir, "response.bin"),
109
+ sseChunks: createJsonlFileKVStream(baseDir, "response.jsonl")
110
+ };
111
+ }
112
+ //# sourceMappingURL=filesystem-storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filesystem-storage.js","sourceRoot":"","sources":["../src/filesystem-storage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Flat file storage - stores cache files in subdirectories named by the key.
3
+ * Each key gets its own folder with standard cache filenames inside:
4
+ * baseDir/001/request.json
5
+ * baseDir/001/response.meta.json
6
+ * baseDir/001/response.jsonl
7
+ * baseDir/002/request.json
8
+ * ...
9
+ *
10
+ * This is similar to filesystem-storage but the key IS the subdirectory name
11
+ * (no hashing), making it suitable for conversation turn folders.
12
+ */
13
+ import type { CacheKey, CacheStorage, KV, KVStream, TimedChunk } from "./types.js";
14
+ /** Create a KV store backed by JSON files in subdirectories: baseDir/{key}/{filename} */
15
+ export declare function createFlatJsonFileKV<T>(baseDir: string, filename: string): KV<CacheKey, T>;
16
+ /** Create a KV store backed by plain text files in subdirectories (no JSON serialization) */
17
+ export declare function createFlatTextFileKV(baseDir: string, filename: string): KV<CacheKey, string>;
18
+ /** Create a KV store backed by binary files in subdirectories */
19
+ export declare function createFlatBinaryFileKV(baseDir: string, filename: string): KV<CacheKey, Uint8Array>;
20
+ /** Create a streaming KV store for SSE chunks in subdirectories */
21
+ export declare function createFlatJsonlFileKVStream(baseDir: string, filename: string): KVStream<CacheKey, TimedChunk>;
22
+ /**
23
+ * Create a CacheStorage that stores files in subdirectories named by the key.
24
+ *
25
+ * @example
26
+ * const storage = createFlatFileStorage("/path/to/conversation")
27
+ * // With transformCacheKey returning "001", files will be:
28
+ * // /path/to/conversation/001/request.json
29
+ * // /path/to/conversation/001/response.meta.json
30
+ * // /path/to/conversation/001/response.jsonl
31
+ */
32
+ export declare function createFlatFileStorage(baseDir: string): CacheStorage;
33
+ //# sourceMappingURL=flat-file-storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flat-file-storage.d.ts","sourceRoot":"","sources":["../src/flat-file-storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAqC,QAAQ,EAAE,YAAY,EAAE,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAkBrH,yFAAyF;AACzF,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,CAuB1F;AAED,6FAA6F;AAC7F,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,CAsB5F;AAED,iEAAiE;AACjE,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC,CAuBlG;AAED,mEAAmE;AACnE,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC,CAuC7G;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CASnE"}
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Flat file storage - stores cache files in subdirectories named by the key.
3
+ * Each key gets its own folder with standard cache filenames inside:
4
+ * baseDir/001/request.json
5
+ * baseDir/001/response.meta.json
6
+ * baseDir/001/response.jsonl
7
+ * baseDir/002/request.json
8
+ * ...
9
+ *
10
+ * This is similar to filesystem-storage but the key IS the subdirectory name
11
+ * (no hashing), making it suitable for conversation turn folders.
12
+ */
13
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
14
+ import { join } from "node:path";
15
+ import { jsonlToTimedChunks, timedChunksToJsonl } from "./sse-handler.js";
16
+ function ensureDir(dir) {
17
+ if (!existsSync(dir)) {
18
+ try {
19
+ mkdirSync(dir, { recursive: true });
20
+ }
21
+ catch (error) {
22
+ if (!(error instanceof Error && error.code === "EEXIST")) {
23
+ throw error;
24
+ }
25
+ }
26
+ }
27
+ }
28
+ /** Create a KV store backed by JSON files in subdirectories: baseDir/{key}/{filename} */
29
+ export function createFlatJsonFileKV(baseDir, filename) {
30
+ return {
31
+ async get([key]) {
32
+ const filePath = join(baseDir, key, filename);
33
+ if (!existsSync(filePath)) {
34
+ return null;
35
+ }
36
+ const content = readFileSync(filePath, "utf-8");
37
+ return JSON.parse(content);
38
+ },
39
+ async set([key], value) {
40
+ const dir = join(baseDir, key);
41
+ ensureDir(dir);
42
+ const filePath = join(dir, filename);
43
+ writeFileSync(filePath, JSON.stringify(value, null, 2), "utf-8");
44
+ },
45
+ async has([key]) {
46
+ const filePath = join(baseDir, key, filename);
47
+ return existsSync(filePath);
48
+ }
49
+ };
50
+ }
51
+ /** Create a KV store backed by plain text files in subdirectories (no JSON serialization) */
52
+ export function createFlatTextFileKV(baseDir, filename) {
53
+ return {
54
+ async get([key]) {
55
+ const filePath = join(baseDir, key, filename);
56
+ if (!existsSync(filePath)) {
57
+ return null;
58
+ }
59
+ return readFileSync(filePath, "utf-8");
60
+ },
61
+ async set([key], value) {
62
+ const dir = join(baseDir, key);
63
+ ensureDir(dir);
64
+ const filePath = join(dir, filename);
65
+ writeFileSync(filePath, value, "utf-8");
66
+ },
67
+ async has([key]) {
68
+ const filePath = join(baseDir, key, filename);
69
+ return existsSync(filePath);
70
+ }
71
+ };
72
+ }
73
+ /** Create a KV store backed by binary files in subdirectories */
74
+ export function createFlatBinaryFileKV(baseDir, filename) {
75
+ return {
76
+ async get([key]) {
77
+ const filePath = join(baseDir, key, filename);
78
+ if (!existsSync(filePath)) {
79
+ return null;
80
+ }
81
+ const buffer = readFileSync(filePath);
82
+ return new Uint8Array(buffer);
83
+ },
84
+ async set([key], value) {
85
+ const dir = join(baseDir, key);
86
+ ensureDir(dir);
87
+ const filePath = join(dir, filename);
88
+ writeFileSync(filePath, value);
89
+ },
90
+ async has([key]) {
91
+ const filePath = join(baseDir, key, filename);
92
+ return existsSync(filePath);
93
+ }
94
+ };
95
+ }
96
+ /** Create a streaming KV store for SSE chunks in subdirectories */
97
+ export function createFlatJsonlFileKVStream(baseDir, filename) {
98
+ return {
99
+ async *get([key]) {
100
+ const filePath = join(baseDir, key, filename);
101
+ if (!existsSync(filePath)) {
102
+ return;
103
+ }
104
+ const content = readFileSync(filePath, "utf-8");
105
+ const chunks = jsonlToTimedChunks(content);
106
+ for (const chunk of chunks) {
107
+ yield chunk;
108
+ }
109
+ },
110
+ async set([key], values) {
111
+ const dir = join(baseDir, key);
112
+ ensureDir(dir);
113
+ const filePath = join(dir, filename);
114
+ let chunks;
115
+ if (Array.isArray(values)) {
116
+ chunks = values;
117
+ }
118
+ else {
119
+ chunks = [];
120
+ for await (const chunk of values) {
121
+ chunks.push(chunk);
122
+ }
123
+ }
124
+ const jsonl = timedChunksToJsonl(chunks);
125
+ writeFileSync(filePath, jsonl, "utf-8");
126
+ },
127
+ async has([key]) {
128
+ const filePath = join(baseDir, key, filename);
129
+ return existsSync(filePath);
130
+ }
131
+ };
132
+ }
133
+ /**
134
+ * Create a CacheStorage that stores files in subdirectories named by the key.
135
+ *
136
+ * @example
137
+ * const storage = createFlatFileStorage("/path/to/conversation")
138
+ * // With transformCacheKey returning "001", files will be:
139
+ * // /path/to/conversation/001/request.json
140
+ * // /path/to/conversation/001/response.meta.json
141
+ * // /path/to/conversation/001/response.jsonl
142
+ */
143
+ export function createFlatFileStorage(baseDir) {
144
+ return {
145
+ requests: createFlatJsonFileKV(baseDir, "request.json"),
146
+ responseMeta: createFlatJsonFileKV(baseDir, "response.meta.json"),
147
+ // Use text storage for responseBody to preserve raw JSON without double-escaping
148
+ responseBody: createFlatTextFileKV(baseDir, "response.json"),
149
+ binaryBody: createFlatBinaryFileKV(baseDir, "response.bin"),
150
+ sseChunks: createFlatJsonlFileKVStream(baseDir, "response.jsonl")
151
+ };
152
+ }
153
+ //# sourceMappingURL=flat-file-storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flat-file-storage.js","sourceRoot":"","sources":["../src/flat-file-storage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { CacheOptions } from "./types.js";
2
+ export type { CacheKey, CacheOptions, CacheStorage, GeneratorTransformHook, HashableRequest, KV, KVStream, StorableResponse, TimedChunk, TransformHook } from "./types.js";
3
+ export { createFilesystemStorage } from "./filesystem-storage.js";
4
+ export { createFlatFileStorage } from "./flat-file-storage.js";
5
+ export declare function createCachedFetch(baseFetch: typeof globalThis.fetch, options?: CacheOptions): (input: Request | string | URL, init?: RequestInit) => Promise<Response>;
6
+ export declare function enableDevFetchCache(options?: CacheOptions): void;
7
+ export declare function disableDevFetchCache(): void;
8
+ export declare function isDevFetchCacheEnabled(): boolean;
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAgB,MAAM,YAAY,CAAA;AAc5D,YAAY,EACV,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,sBAAsB,EACtB,eAAe,EACf,EAAE,EACF,QAAQ,EACR,gBAAgB,EAChB,UAAU,EACV,aAAa,EACd,MAAM,YAAY,CAAA;AAGnB,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA;AAsF9D,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,OAAO,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,YAAY,IAYxD,OAAO,OAAO,GAAG,MAAM,GAAG,GAAG,EAAE,OAAO,WAAW,KAAG,OAAO,CAAC,QAAQ,CAAC,CAkFxG;AAED,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI,CAwBhE;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAO3C;AAED,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD"}
package/dist/index.js ADDED
@@ -0,0 +1,183 @@
1
+ import { getCachedResponse, getCacheKeyFromUrl, setInternalFetchForCache, storeRequest, storeResponse } from "./cache-manager.js";
2
+ import { getCacheDir, isCacheEnabled, isProduction, isReplayOnly } from "./environment.js";
3
+ import { createFilesystemStorage } from "./filesystem-storage.js";
4
+ import { hashRequest, headersToRecord } from "./request-hasher.js";
5
+ // Export storage factories for custom implementations
6
+ export { createFilesystemStorage } from "./filesystem-storage.js";
7
+ export { createFlatFileStorage } from "./flat-file-storage.js";
8
+ const CACHE_ENABLED_BANNER = `
9
+ ╔══════════════════════════════════════════════════════════════╗
10
+ ║ DEV-FETCH-CACHE ENABLED ║
11
+ ║ Responses are being cached/replayed from .cache/fetch/ ║
12
+ ║ To disable: DEV_FETCH_CACHE=0 or --no-fetch-cache ║
13
+ ╚══════════════════════════════════════════════════════════════╝
14
+ `;
15
+ let originalFetch = null;
16
+ function getUrlFromInput(input) {
17
+ if (typeof input === "string") {
18
+ return input;
19
+ }
20
+ if (input instanceof URL) {
21
+ return input.href;
22
+ }
23
+ return input.url;
24
+ }
25
+ function normalizeHeadersInit(headersInit) {
26
+ if (!headersInit) {
27
+ return {};
28
+ }
29
+ if (headersInit instanceof Headers) {
30
+ return headersToRecord(headersInit);
31
+ }
32
+ if (Array.isArray(headersInit)) {
33
+ return Object.fromEntries(headersInit);
34
+ }
35
+ return headersInit;
36
+ }
37
+ async function extractBodyInit(bodyInit) {
38
+ if (!bodyInit) {
39
+ return undefined;
40
+ }
41
+ if (typeof bodyInit === "string") {
42
+ return bodyInit;
43
+ }
44
+ if (bodyInit instanceof URLSearchParams) {
45
+ return bodyInit.toString();
46
+ }
47
+ if (bodyInit instanceof Blob) {
48
+ return bodyInit.text();
49
+ }
50
+ if (bodyInit instanceof FormData) {
51
+ const pairs = [];
52
+ for (const [key, value] of bodyInit.entries()) {
53
+ // FormDataEntryValue can be File or string; File needs to be converted to string
54
+ const stringValue = typeof value === "string" ? value : value.name;
55
+ pairs.push(`${encodeURIComponent(key)}=${encodeURIComponent(stringValue)}`);
56
+ }
57
+ return pairs.join("&");
58
+ }
59
+ if (bodyInit instanceof ArrayBuffer) {
60
+ return new TextDecoder().decode(bodyInit);
61
+ }
62
+ if (ArrayBuffer.isView(bodyInit)) {
63
+ return new TextDecoder().decode(new Uint8Array(bodyInit.buffer, bodyInit.byteOffset, bodyInit.byteLength));
64
+ }
65
+ if (bodyInit instanceof ReadableStream) {
66
+ const reader = bodyInit.getReader();
67
+ const chunks = [];
68
+ while (true) {
69
+ const { done, value } = await reader.read();
70
+ if (done)
71
+ break;
72
+ if (value)
73
+ chunks.push(value);
74
+ }
75
+ const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
76
+ const combined = new Uint8Array(totalLength);
77
+ let offset = 0;
78
+ for (const chunk of chunks) {
79
+ combined.set(chunk, offset);
80
+ offset += chunk.length;
81
+ }
82
+ return new TextDecoder().decode(combined);
83
+ }
84
+ return undefined;
85
+ }
86
+ /** Default identity transform hook */
87
+ const identity = (value) => value;
88
+ export function createCachedFetch(baseFetch, options) {
89
+ const replayOnly = options?.replayOnly ?? isReplayOnly();
90
+ const beforeHash = options?.beforeHash ?? identity;
91
+ const beforeStoreRequest = options?.beforeStoreRequest ?? identity;
92
+ const transformCacheKey = options?.transformCacheKey ?? ((key) => key);
93
+ // Create or use provided storage
94
+ const storage = options?.storage ?? createFilesystemStorage(getCacheDir());
95
+ // Set internal fetch for dev-fs-logs communication (defaults to baseFetch)
96
+ setInternalFetchForCache(options?.internalFetch ?? baseFetch);
97
+ return async function cachedFetch(input, init) {
98
+ if (isProduction()) {
99
+ return baseFetch(input, init);
100
+ }
101
+ const url = getUrlFromInput(input);
102
+ // Skip caching for localhost requests (including dev-fs-logs on port 1090)
103
+ if (url.includes("localhost") || url.includes("127.0.0.1")) {
104
+ return baseFetch(input, init);
105
+ }
106
+ const method = init?.method ?? (typeof input === "object" && "method" in input ? input.method : "GET");
107
+ const cacheKeyFromUrl = getCacheKeyFromUrl(url);
108
+ if (cacheKeyFromUrl) {
109
+ const cached = await getCachedResponse(cacheKeyFromUrl, options?.afterLoadResponse, options?.transformSSEChunk, storage);
110
+ if (cached) {
111
+ return cached;
112
+ }
113
+ return new Response("Cache entry not found", {
114
+ status: 404
115
+ });
116
+ }
117
+ const headersInit = init?.headers ?? (typeof input === "object" && "headers" in input ? input.headers : undefined);
118
+ const headers = normalizeHeadersInit(headersInit);
119
+ let body;
120
+ // Extract body from Request object or init
121
+ if (input instanceof Request && input.body) {
122
+ // Clone the request so we can read the body without consuming the original
123
+ const clonedRequest = input.clone();
124
+ body = await extractBodyInit(clonedRequest.body);
125
+ }
126
+ else if (init?.body !== null && init?.body !== undefined) {
127
+ body = await extractBodyInit(init.body);
128
+ }
129
+ // Apply beforeHash transform to affect cache key generation, then transformCacheKey for custom prefixes/suffixes
130
+ const hashableRequest = await beforeHash({ url, method, headers, body });
131
+ const cacheKey = transformCacheKey(hashRequest(hashableRequest), hashableRequest);
132
+ const cached = await getCachedResponse(cacheKey, options?.afterLoadResponse, options?.transformSSEChunk, storage);
133
+ if (cached) {
134
+ return cached;
135
+ }
136
+ if (replayOnly) {
137
+ return new Response("Cache miss in replay-only mode", {
138
+ status: 503
139
+ });
140
+ }
141
+ const requestToStore = await beforeStoreRequest({ url, method, headers, body });
142
+ await storeRequest({
143
+ url: requestToStore.url,
144
+ method: requestToStore.method,
145
+ headers: requestToStore.headers,
146
+ body: requestToStore.body
147
+ }, cacheKey, options?.beforeStoreRequest !== undefined, // skip header filtering if hook provided
148
+ storage, hashableRequest);
149
+ const response = await baseFetch(input, init);
150
+ return storeResponse(cacheKey, response, options?.beforeStoreResponse, storage, hashableRequest);
151
+ };
152
+ }
153
+ export function enableDevFetchCache(options) {
154
+ if (isProduction()) {
155
+ return;
156
+ }
157
+ if (!isCacheEnabled()) {
158
+ return;
159
+ }
160
+ if (originalFetch !== null) {
161
+ return;
162
+ }
163
+ originalFetch = globalThis.fetch;
164
+ const cachedFetch = createCachedFetch(originalFetch, {
165
+ ...options,
166
+ internalFetch: options?.internalFetch ?? originalFetch
167
+ });
168
+ // Cast to typeof fetch to include preconnect method
169
+ globalThis.fetch = cachedFetch;
170
+ // biome-ignore lint/suspicious/noConsole: Banner display is intentional for dev tooling
171
+ console.info(CACHE_ENABLED_BANNER);
172
+ }
173
+ export function disableDevFetchCache() {
174
+ if (originalFetch === null) {
175
+ return;
176
+ }
177
+ globalThis.fetch = originalFetch;
178
+ originalFetch = null;
179
+ }
180
+ export function isDevFetchCacheEnabled() {
181
+ return originalFetch !== null;
182
+ }
183
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { RawCachedRequest } from "./types.js";
2
+ export declare function hashRequest({ body, headers, method, url }: RawCachedRequest): string;
3
+ export declare function getStorableHeaders(headers: Record<string, string>): Record<string, string>;
4
+ export declare function headersToRecord(headers: Headers): Record<string, string>;
5
+ //# sourceMappingURL=request-hasher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-hasher.d.ts","sourceRoot":"","sources":["../src/request-hasher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAyDlD,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,gBAAgB,GAAG,MAAM,CAepF;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAE1F;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAMxE"}
@@ -0,0 +1,74 @@
1
+ import { createHash } from "node:crypto";
2
+ const BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
3
+ function toBase62(n) {
4
+ if (n === 0n)
5
+ return "0";
6
+ let result = "";
7
+ while (n > 0n) {
8
+ result = BASE62[Number(n % 62n)] + result;
9
+ n = n / 62n;
10
+ }
11
+ return result;
12
+ }
13
+ const SENSITIVE_HEADERS = new Set([
14
+ "authorization",
15
+ "x-api-key",
16
+ "api-key",
17
+ "x-openrouter-api-key",
18
+ "cookie",
19
+ "set-cookie",
20
+ "x-auth-token",
21
+ "x-access-token",
22
+ "bearer"
23
+ ]);
24
+ function normalizeUrl(url) {
25
+ const parsed = new URL(url);
26
+ parsed.searchParams.sort();
27
+ const pathname = parsed.pathname.replace(/\/+$/, "") || "/";
28
+ return `${parsed.protocol}//${parsed.host}${pathname}${parsed.search}`;
29
+ }
30
+ function filterHeaders(headers, getOutputKey) {
31
+ const result = {};
32
+ for (const [key, value] of Object.entries(headers)) {
33
+ const lowerKey = key.toLowerCase();
34
+ if (SENSITIVE_HEADERS.has(lowerKey)) {
35
+ continue;
36
+ }
37
+ const outputKey = getOutputKey(key, lowerKey);
38
+ result[outputKey] = value;
39
+ }
40
+ return result;
41
+ }
42
+ function normalizeHeaders(headers) {
43
+ return filterHeaders(headers, (_originalKey, lowerKey) => lowerKey);
44
+ }
45
+ function filterSensitiveHeaders(headers) {
46
+ return filterHeaders(headers, (originalKey) => originalKey);
47
+ }
48
+ export function hashRequest({ body, headers, method, url }) {
49
+ // Build content string for hashing
50
+ let content = normalizeUrl(url) + "\n" + method.toUpperCase();
51
+ const normalizedHeaders = normalizeHeaders(headers);
52
+ const sortedHeaderKeys = Object.keys(normalizedHeaders).sort();
53
+ for (const key of sortedHeaderKeys) {
54
+ content += `\n${key}:${normalizedHeaders[key]}`;
55
+ }
56
+ if (body) {
57
+ content += `\n${body}`;
58
+ }
59
+ // Create a SHA256 hash and convert to base62 for a short string
60
+ const hash = createHash("sha256").update(content).digest();
61
+ const hashBigInt = BigInt("0x" + hash.toString("hex"));
62
+ return toBase62(hashBigInt % 62n ** 11n); // Limit to base62 with ~11 chars max
63
+ }
64
+ export function getStorableHeaders(headers) {
65
+ return filterSensitiveHeaders(headers);
66
+ }
67
+ export function headersToRecord(headers) {
68
+ const record = {};
69
+ headers.forEach((value, key) => {
70
+ record[key] = value;
71
+ });
72
+ return record;
73
+ }
74
+ //# sourceMappingURL=request-hasher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-hasher.js","sourceRoot":"","sources":["../src/request-hasher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAGxC,MAAM,MAAM,GAAG,gEAAgE,CAAA;AAE/E,SAAS,QAAQ,CAAC,CAAS;IACzB,IAAI,CAAC,KAAK,EAAE;QAAE,OAAO,GAAG,CAAA;IACxB,IAAI,MAAM,GAAG,EAAE,CAAA;IACf,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC;QACd,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,MAAM,CAAA;QACzC,CAAC,GAAG,CAAC,GAAG,GAAG,CAAA;IACb,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC;IAChC,eAAe;IACf,WAAW;IACX,SAAS;IACT,sBAAsB;IACtB,QAAQ;IACR,YAAY;IACZ,cAAc;IACd,gBAAgB;IAChB,QAAQ;CACT,CAAC,CAAA;AAEF,SAAS,YAAY,CAAC,GAAW;IAC/B,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;IAC3B,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,CAAA;IAC1B,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,GAAG,CAAA;IAC3D,OAAO,GAAG,MAAM,CAAC,QAAQ,KAAK,MAAM,CAAC,IAAI,GAAG,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,CAAA;AACxE,CAAC;AAED,SAAS,aAAa,CACpB,OAA+B,EAC/B,YAA+D;IAE/D,MAAM,MAAM,GAA2B,EAAE,CAAA;IACzC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACnD,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,EAAE,CAAA;QAClC,IAAI,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YACpC,SAAQ;QACV,CAAC;QACD,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;QAC7C,MAAM,CAAC,SAAS,CAAC,GAAG,KAAK,CAAA;IAC3B,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAS,gBAAgB,CAAC,OAA+B;IACvD,OAAO,aAAa,CAAC,OAAO,EAAE,CAAC,YAAY,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAA;AACrE,CAAC;AAED,SAAS,sBAAsB,CAAC,OAA+B;IAC7D,OAAO,aAAa,CAAC,OAAO,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,WAAW,CAAC,CAAA;AAC7D,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAoB;IAC1E,mCAAmC;IACnC,IAAI,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,MAAM,CAAC,WAAW,EAAE,CAAA;IAC7D,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAA;IACnD,MAAM,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,IAAI,EAAE,CAAA;IAC9D,KAAK,MAAM,GAAG,IAAI,gBAAgB,EAAE,CAAC;QACnC,OAAO,IAAI,KAAK,GAAG,IAAI,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAA;IACjD,CAAC;IACD,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,IAAI,KAAK,IAAI,EAAE,CAAA;IACxB,CAAC;IACD,gEAAgE;IAChE,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAA;IAC1D,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAA;IACtD,OAAO,QAAQ,CAAC,UAAU,GAAG,GAAG,IAAI,GAAG,CAAC,CAAA,CAAC,qCAAqC;AAChF,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAA+B;IAChE,OAAO,sBAAsB,CAAC,OAAO,CAAC,CAAA;AACxC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAgB;IAC9C,MAAM,MAAM,GAA2B,EAAE,CAAA;IACzC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QAC7B,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;IACrB,CAAC,CAAC,CAAA;IACF,OAAO,MAAM,CAAA;AACf,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { TimedChunk } from "./types.js";
2
+ export declare function isSSEResponse(headers: Headers): boolean;
3
+ export declare function recordStreamWithTiming(stream: ReadableStream<Uint8Array>): Promise<Array<TimedChunk>>;
4
+ export declare function replayStreamWithTiming(timedChunks: Array<TimedChunk>): ReadableStream<Uint8Array>;
5
+ /** Replay stream from an async iterable of timed chunks (for generator transforms) */
6
+ export declare function replayStreamFromAsyncIterable(chunks: AsyncIterable<TimedChunk>): ReadableStream<Uint8Array>;
7
+ export declare function timedChunksToJsonl(chunks: Array<TimedChunk>): string;
8
+ export declare function jsonlToTimedChunks(jsonl: string): Array<TimedChunk>;
9
+ //# sourceMappingURL=sse-handler.d.ts.map