@studiocms/cfetch 0.2.1 → 0.3.1

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.
@@ -1,42 +1,41 @@
1
- /**
2
- * @module cfetch/wrappers
3
- *
4
- * Provides cached fetch wrappers using Effect for caching capabilities.
5
- *
6
- * This module exports functions to perform HTTP requests with built-in caching logic.
7
- * It defines types for cached responses and errors, and implements functions to fetch
8
- * data with various parsing options (JSON, text, Blob) while leveraging an in-memory
9
- * cache layer.
10
- */
11
- import { type Duration, Effect } from 'effect';
12
- export type { CacheConfig } from './types.js';
13
- export { Duration } from 'effect';
14
- declare const FetchError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
15
- readonly _tag: "FetchError";
1
+ import { CacheConfig } from "./types.mjs";
2
+ import { Duration, Duration as Duration$1, Effect } from "effect";
3
+ import * as effect_Types0 from "effect/Types";
4
+ import * as effect_Cause0 from "effect/Cause";
5
+
6
+ //#region src/wrappers.d.ts
7
+ declare const FetchError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => effect_Cause0.YieldableError & {
8
+ readonly _tag: "FetchError";
16
9
  } & Readonly<A>;
17
10
  /**
18
11
  * Custom error type for fetch-related errors.
19
12
  */
20
- export declare class FetchError extends FetchError_base<{
21
- message: string;
22
- cause?: unknown;
23
- }> {
24
- }
25
- export interface CachedResponse<T> {
26
- data: T;
27
- ok: boolean;
28
- status: number;
29
- statusText: string;
30
- headers: Record<string, string>;
13
+ declare class FetchError extends FetchError_base<{
14
+ message: string;
15
+ cause?: unknown;
16
+ }> {}
17
+ interface CachedResponse<T> {
18
+ data: T;
19
+ ok: boolean;
20
+ status: number;
21
+ statusText: string;
22
+ headers: Record<string, string>;
31
23
  }
32
24
  /**
33
25
  * Configuration options for cached fetch requests.
34
26
  */
35
- export interface CFetchConfig {
36
- ttl?: Duration.DurationInput;
37
- tags?: string[];
38
- key?: string;
39
- verbose?: boolean;
27
+ interface CFetchConfig {
28
+ ttl?: Duration$1.DurationInput;
29
+ tags?: string[];
30
+ key?: string;
31
+ verbose?: boolean;
32
+ }
33
+ /**
34
+ * Options for cache invalidation.
35
+ */
36
+ interface InvalidateCacheOptions {
37
+ keys?: string[];
38
+ tags?: string[];
40
39
  }
41
40
  /**
42
41
  * No-op parser for HEAD requests.
@@ -45,7 +44,7 @@ export interface CFetchConfig {
45
44
  * @param _ - The Response object (ignored)
46
45
  * @returns A Promise that resolves to undefined
47
46
  */
48
- export declare const noOpParser: <U>(_: Response) => Promise<U>;
47
+ declare const noOpParser: <U>(_: Response) => Promise<U>;
49
48
  /**
50
49
  * Fetches data from a URL with caching capabilities using Effect.
51
50
  *
@@ -87,7 +86,25 @@ export declare const noOpParser: <U>(_: Response) => Promise<U>;
87
86
  * );
88
87
  * ```
89
88
  */
90
- export declare const cFetchEffect: <T>(url: string | URL, parser: (response: Response) => Promise<T>, options?: RequestInit, cacheConfig?: CFetchConfig) => Effect.Effect<CachedResponse<T>, FetchError, never>;
89
+ declare const cFetchEffect: <T>(url: string | URL, parser: (response: Response) => Promise<T>, options?: RequestInit, cacheConfig?: CFetchConfig) => Effect.Effect<CachedResponse<T>, FetchError, never>;
90
+ /**
91
+ * Invalidates cache entries based on specified keys or tags.
92
+ *
93
+ * @param opts - An object containing optional keys and tags for cache invalidation
94
+ * @param opts.keys - An array of specific cache keys to invalidate
95
+ * @param opts.tags - An array of tags; all cache entries associated with these tags will be invalidated
96
+ *
97
+ * @returns An Effect that performs the cache invalidation when executed
98
+ *
99
+ * @example
100
+ * ```typescript
101
+ * yield* invalidateCacheEffect({
102
+ * tags: ['user'],
103
+ * keys: ['user:123', 'user:456']
104
+ * });
105
+ * ```
106
+ */
107
+ declare const invalidateCacheEffect: (opts: InvalidateCacheOptions) => Effect.Effect<void, never, never>;
91
108
  /**
92
109
  * Creates an Effect that fetches JSON data from a URL with caching support.
93
110
  *
@@ -109,7 +126,7 @@ export declare const cFetchEffect: <T>(url: string | URL, parser: (response: Res
109
126
  * );
110
127
  * ```
111
128
  */
112
- export declare const cFetchEffectJson: <T>(url: string | URL, options?: RequestInit, cacheConfig?: CFetchConfig) => Effect.Effect<CachedResponse<T>, FetchError, never>;
129
+ declare const cFetchEffectJson: <T>(url: string | URL, options?: RequestInit, cacheConfig?: CFetchConfig) => Effect.Effect<CachedResponse<T>, FetchError, never>;
113
130
  /**
114
131
  * Fetches a resource from the specified URL and returns the response body as text.
115
132
  *
@@ -132,7 +149,7 @@ export declare const cFetchEffectJson: <T>(url: string | URL, options?: RequestI
132
149
  * );
133
150
  * ```
134
151
  */
135
- export declare const cFetchEffectText: (url: string | URL, options?: RequestInit, cacheConfig?: CFetchConfig) => Effect.Effect<CachedResponse<string>, FetchError, never>;
152
+ declare const cFetchEffectText: (url: string | URL, options?: RequestInit, cacheConfig?: CFetchConfig) => Effect.Effect<CachedResponse<string>, FetchError, never>;
136
153
  /**
137
154
  * Fetches a resource and returns it as a Blob with caching support.
138
155
  *
@@ -154,7 +171,7 @@ export declare const cFetchEffectText: (url: string | URL, options?: RequestInit
154
171
  * );
155
172
  * ```
156
173
  */
157
- export declare const cFetchEffectBlob: (url: string | URL, options?: RequestInit, cacheConfig?: CFetchConfig) => Effect.Effect<CachedResponse<Blob>, FetchError, never>;
174
+ declare const cFetchEffectBlob: (url: string | URL, options?: RequestInit, cacheConfig?: CFetchConfig) => Effect.Effect<CachedResponse<Blob>, FetchError, never>;
158
175
  /**
159
176
  * Executes a cached fetch request with configurable caching behavior.
160
177
  *
@@ -178,7 +195,7 @@ export declare const cFetchEffectBlob: (url: string | URL, options?: RequestInit
178
195
  * );
179
196
  * ```
180
197
  */
181
- export declare const cFetch: <T>(url: string | URL, parser: (response: Response) => Promise<T>, options?: RequestInit, cacheConfig?: CFetchConfig) => Promise<CachedResponse<T>>;
198
+ declare const cFetch: <T>(url: string | URL, parser: (response: Response) => Promise<T>, options?: RequestInit, cacheConfig?: CFetchConfig) => Promise<CachedResponse<T>>;
182
199
  /**
183
200
  * Fetches and parses JSON data from the specified URL with caching support.
184
201
  *
@@ -202,7 +219,7 @@ export declare const cFetch: <T>(url: string | URL, parser: (response: Response)
202
219
  * });
203
220
  * ```
204
221
  */
205
- export declare const cFetchJson: <T>(url: string | URL, options?: RequestInit, cacheConfig?: CFetchConfig) => Promise<CachedResponse<T>>;
222
+ declare const cFetchJson: <T>(url: string | URL, options?: RequestInit, cacheConfig?: CFetchConfig) => Promise<CachedResponse<T>>;
206
223
  /**
207
224
  * Fetches a URL and returns the response as text with caching support.
208
225
  *
@@ -224,7 +241,7 @@ export declare const cFetchJson: <T>(url: string | URL, options?: RequestInit, c
224
241
  * });
225
242
  * ```
226
243
  */
227
- export declare const cFetchText: (url: string | URL, options?: RequestInit, cacheConfig?: CFetchConfig) => Promise<CachedResponse<string>>;
244
+ declare const cFetchText: (url: string | URL, options?: RequestInit, cacheConfig?: CFetchConfig) => Promise<CachedResponse<string>>;
228
245
  /**
229
246
  * Fetches a Blob resource from the specified URL with optional caching configuration.
230
247
  *
@@ -242,4 +259,24 @@ export declare const cFetchText: (url: string | URL, options?: RequestInit, cach
242
259
  * const blob = response.data;
243
260
  * ```
244
261
  */
245
- export declare const cFetchBlob: (url: string | URL, options?: RequestInit, cacheConfig?: CFetchConfig) => Promise<CachedResponse<Blob>>;
262
+ declare const cFetchBlob: (url: string | URL, options?: RequestInit, cacheConfig?: CFetchConfig) => Promise<CachedResponse<Blob>>;
263
+ /**
264
+ * Invalidates cache entries based on specified keys or tags.
265
+ *
266
+ * @param opts - An object containing optional keys and tags for cache invalidation
267
+ * @param opts.keys - An array of specific cache keys to invalidate
268
+ * @param opts.tags - An array of tags; all cache entries associated with these tags will be invalidated
269
+ *
270
+ * @returns A Promise that resolves when the cache invalidation is complete
271
+ *
272
+ * @example
273
+ * ```typescript
274
+ * await invalidateCache({
275
+ * tags: ['user'],
276
+ * keys: ['user:123', 'user:456']
277
+ * });
278
+ * ```
279
+ */
280
+ declare const invalidateCache: (opts: InvalidateCacheOptions) => Promise<void>;
281
+ //#endregion
282
+ export { CFetchConfig, type CacheConfig, CachedResponse, Duration, FetchError, InvalidateCacheOptions, cFetch, cFetchBlob, cFetchEffect, cFetchEffectBlob, cFetchEffectJson, cFetchEffectText, cFetchJson, cFetchText, invalidateCache, invalidateCacheEffect, noOpParser };
@@ -0,0 +1,364 @@
1
+ import { CacheMaps, CacheService } from "./cache.mjs";
2
+ import { Data, Duration, Effect, Layer, Pretty, Schema } from "effect";
3
+
4
+ //#region src/wrappers.ts
5
+ /**
6
+ * @module cfetch/wrappers
7
+ *
8
+ * Provides cached fetch wrappers using Effect for caching capabilities.
9
+ *
10
+ * This module exports functions to perform HTTP requests with built-in caching logic.
11
+ * It defines types for cached responses and errors, and implements functions to fetch
12
+ * data with various parsing options (JSON, text, Blob) while leveraging an in-memory
13
+ * cache layer.
14
+ */
15
+ const store = /* @__PURE__ */ new Map();
16
+ const tagIndex = /* @__PURE__ */ new Map();
17
+ const CacheMapLayer = Layer.succeed(CacheMaps, {
18
+ store,
19
+ tagIndex
20
+ });
21
+ const CacheLive = CacheService.Default.pipe(Layer.provide(CacheMapLayer));
22
+ /**
23
+ * Custom error type for fetch-related errors.
24
+ */
25
+ var FetchError = class extends Data.TaggedError("FetchError") {};
26
+ /**
27
+ * Schema for validating cache-relevant fetch options.
28
+ *
29
+ * This schema is used to ensure that only serializable and relevant options are considered
30
+ * when generating cache keys. It includes the HTTP method, headers (as a record of key-value pairs),
31
+ * and body (only if it's a string). Non-serializable options are excluded to prevent cache key collisions.
32
+ */
33
+ const CacheRelevantOptionsSchema = Schema.Struct({
34
+ method: Schema.optional(Schema.Union(Schema.String, Schema.Undefined)),
35
+ headers: Schema.optional(Schema.Union(Schema.Record({
36
+ key: Schema.String,
37
+ value: Schema.Any
38
+ }), Schema.Undefined)),
39
+ body: Schema.optional(Schema.Union(Schema.String, Schema.Undefined))
40
+ });
41
+ /**
42
+ * Utility to stringify cache-relevant options for generating cache keys.
43
+ */
44
+ const stringifyRelevantOptions = Pretty.make(CacheRelevantOptionsSchema);
45
+ /**
46
+ * Helper to run an Effect and return a Promise.
47
+ */
48
+ const runEffect = (effect) => Effect.runPromise(effect);
49
+ const cacheableMethods = ["GET", "HEAD"];
50
+ /**
51
+ * No-op parser for HEAD requests.
52
+ *
53
+ * @template U - The type of the parsed data
54
+ * @param _ - The Response object (ignored)
55
+ * @returns A Promise that resolves to undefined
56
+ */
57
+ const noOpParser = (_) => Promise.resolve(void 0);
58
+ /**
59
+ * Fetches data from a URL and parses the response using a provided parser function.
60
+ *
61
+ * @template T - The type of the parsed data
62
+ * @param url - The URL to fetch from, either as a string or URL object
63
+ * @param parser - An async function that takes a Response and returns the parsed data of type T
64
+ * @param options - Optional fetch configuration options (headers, method, body, etc.)
65
+ * @returns An Effect that yields a CachedResponse containing the parsed data, response status, headers, and metadata
66
+ * @throws {FetchError} When the fetch operation fails or when response parsing fails
67
+ *
68
+ * @example
69
+ * ```typescript
70
+ * const result = await Effect.runPromise(
71
+ * fetchAndParse('https://api.example.com/data', (res) => res.json())
72
+ * );
73
+ * ```
74
+ */
75
+ const fetchAndParse = (url, parser, options) => Effect.gen(function* () {
76
+ const response = yield* Effect.tryPromise({
77
+ try: () => fetch(url, options),
78
+ catch: (cause) => new FetchError({
79
+ message: "Failed to fetch",
80
+ cause
81
+ })
82
+ });
83
+ return {
84
+ data: yield* Effect.tryPromise({
85
+ try: () => parser(response),
86
+ catch: (cause) => new FetchError({
87
+ message: "Failed to parse response",
88
+ cause
89
+ })
90
+ }),
91
+ ok: response.ok,
92
+ status: response.status,
93
+ statusText: response.statusText,
94
+ headers: Object.fromEntries(response.headers.entries())
95
+ };
96
+ });
97
+ /**
98
+ * Fetches data from a URL with caching capabilities using Effect.
99
+ *
100
+ * This function performs an HTTP request with built-in caching logic. It first checks
101
+ * the cache for existing data, and if not found, fetches from the network, parses the
102
+ * response, and caches successful responses for future use.
103
+ *
104
+ * @template T - The type of the parsed response data
105
+ *
106
+ * @param url - The URL to fetch data from
107
+ * @param parser - A function that parses the Response object into type T
108
+ * @param options - Optional RequestInit configuration for the fetch request
109
+ * @param cacheConfig - Optional cache configuration object
110
+ * @param cacheConfig.ttl - Time-to-live duration for the cached entry
111
+ * @param cacheConfig.tags - Tags to associate with the cached entry for invalidation
112
+ * @param cacheConfig.key - Custom cache key (defaults to URL and options hash)
113
+ *
114
+ * @returns An Effect that yields a CachedResponse containing the parsed data and response metadata
115
+ *
116
+ * @throws {FetchError} When the network request fails or response parsing fails
117
+ *
118
+ * @remarks
119
+ * - Cache keys are automatically generated from the URL and options if not provided
120
+ * - Only successful responses (response.ok === true) are cached
121
+ * - Only 2xx responses are cached
122
+ * - Users needing negative caching should implement custom logic
123
+ * - The effect is provided with CacheLive layer automatically
124
+ * - Non-cacheable HTTP methods (e.g. POST, PUT) bypass the cache entirely
125
+ * - The parser function is bypassed for HEAD requests, returning undefined data
126
+ * - Verbose logging can be enabled via cacheConfig.verbose
127
+ *
128
+ * @example
129
+ * ```typescript
130
+ * const effect = cFetchEffect(
131
+ * 'https://api.example.com/data',
132
+ * (res) => res.json(),
133
+ * { method: 'GET' },
134
+ * { ttl: Duration.minutes(5), tags: ['api-data'] }
135
+ * );
136
+ * ```
137
+ */
138
+ const cFetchEffect = (url, parser, options, cacheConfig) => Effect.gen(function* () {
139
+ const cache = yield* CacheService;
140
+ const { key, verbose = false, ...cacheOpts } = cacheConfig || {};
141
+ const method = options?.method?.toUpperCase() || "GET";
142
+ if (!cacheableMethods.includes(method)) {
143
+ if (verbose) console.log(`[c:fetch] Bypassing cache for non-cacheable method: ${method}`);
144
+ return yield* fetchAndParse(url, parser, options);
145
+ }
146
+ const urlString = typeof url === "string" ? url : url.href;
147
+ const cacheRelevantOptions = options ? {
148
+ method: options.method,
149
+ headers: options.headers instanceof Headers ? Object.fromEntries([...options.headers.entries()].sort(([a], [b]) => a.localeCompare(b))) : options.headers ? Object.fromEntries(Object.entries(options.headers).sort(([a], [b]) => a.localeCompare(b))) : void 0,
150
+ body: typeof options.body === "string" ? options.body : void 0
151
+ } : {};
152
+ if (options?.body && typeof options.body !== "string" && !key && verbose) console.warn(`[c:fetch] Non-serializable request body detected for ${urlString}. Consider providing an explicit cache key via cacheConfig.key to avoid collisions.`);
153
+ const cacheKey = key ?? `${urlString}-${stringifyRelevantOptions(cacheRelevantOptions)}`;
154
+ const cached = yield* cache.get(cacheKey);
155
+ if (cached) {
156
+ if (verbose) console.log(`[c:fetch] Cache hit for: ${cacheKey}, returning cached response.`);
157
+ return cached;
158
+ }
159
+ if (verbose) console.log(`[c:fetch] Cache miss for: ${cacheKey}, fetching from network.`);
160
+ const cachedResponse = yield* fetchAndParse(url, method === "HEAD" ? noOpParser : parser, options);
161
+ if (cachedResponse.ok) {
162
+ yield* cache.set(cacheKey, cachedResponse, cacheOpts);
163
+ if (verbose) console.log(`[c:fetch] Cached response for: ${cacheKey}`);
164
+ }
165
+ return cachedResponse;
166
+ }).pipe(Effect.provide(CacheLive));
167
+ /**
168
+ * Invalidates cache entries based on specified keys or tags.
169
+ *
170
+ * @param opts - An object containing optional keys and tags for cache invalidation
171
+ * @param opts.keys - An array of specific cache keys to invalidate
172
+ * @param opts.tags - An array of tags; all cache entries associated with these tags will be invalidated
173
+ *
174
+ * @returns An Effect that performs the cache invalidation when executed
175
+ *
176
+ * @example
177
+ * ```typescript
178
+ * yield* invalidateCacheEffect({
179
+ * tags: ['user'],
180
+ * keys: ['user:123', 'user:456']
181
+ * });
182
+ * ```
183
+ */
184
+ const invalidateCacheEffect = (opts) => Effect.gen(function* () {
185
+ const cache = yield* CacheService;
186
+ if (opts.keys) for (const key of opts.keys) yield* cache.delete(key);
187
+ if (opts.tags) yield* cache.invalidateTags(opts.tags);
188
+ }).pipe(Effect.provide(CacheLive));
189
+ /**
190
+ * Creates an Effect that fetches JSON data from a URL with caching support.
191
+ *
192
+ * @template T - The expected type of the JSON response data
193
+ * @param url - The URL to fetch data from
194
+ * @param options - Optional fetch configuration options (headers, method, etc.)
195
+ * @param cacheConfig - Optional cache configuration
196
+ * @param cacheConfig.ttl - Time-to-live duration for the cached response
197
+ * @param cacheConfig.tags - Tags to associate with the cached entry for invalidation
198
+ * @param cacheConfig.key - Custom cache key to use instead of the default URL-based key
199
+ * @returns An Effect that yields a CachedResponse containing the parsed JSON data, or fails with a FetchError
200
+ *
201
+ * @example
202
+ * ```typescript
203
+ * const effect = cFetchEffectJson<User>(
204
+ * 'https://api.example.com/user/123',
205
+ * { method: 'GET' },
206
+ * { ttl: Duration.minutes(5), tags: ['user'] }
207
+ * );
208
+ * ```
209
+ */
210
+ const cFetchEffectJson = (url, options, cacheConfig) => cFetchEffect(url, (res) => res.json(), options, cacheConfig);
211
+ /**
212
+ * Fetches a resource from the specified URL and returns the response body as text.
213
+ *
214
+ * @param url - The URL to fetch the resource from.
215
+ * @param options - Optional fetch configuration including method, headers, body, etc.
216
+ * @param cacheConfig - Optional cache configuration.
217
+ * @param cacheConfig.ttl - Time-to-live duration for the cached response.
218
+ * @param cacheConfig.tags - Array of tags to associate with the cached entry for invalidation purposes.
219
+ * @param cacheConfig.key - Custom cache key. If not provided, the URL will be used as the key.
220
+ *
221
+ * @returns An Effect that resolves to a CachedResponse containing the response text,
222
+ * or fails with a FetchError if the request fails.
223
+ *
224
+ * @example
225
+ * ```typescript
226
+ * const textEffect = cFetchEffectText(
227
+ * 'https://api.example.com/data',
228
+ * { method: 'GET' },
229
+ * { ttl: Duration.minutes(5), tags: ['api', 'data'] }
230
+ * );
231
+ * ```
232
+ */
233
+ const cFetchEffectText = (url, options, cacheConfig) => cFetchEffect(url, (res) => res.text(), options, cacheConfig);
234
+ /**
235
+ * Fetches a resource and returns it as a Blob with caching support.
236
+ *
237
+ * @param url - The URL of the resource to fetch
238
+ * @param options - Optional fetch request configuration (headers, method, etc.)
239
+ * @param cacheConfig - Optional cache configuration object
240
+ * @param cacheConfig.ttl - Time-to-live duration for the cached response
241
+ * @param cacheConfig.tags - Array of tags to associate with the cached entry
242
+ * @param cacheConfig.key - Custom cache key to use instead of the default
243
+ *
244
+ * @returns An Effect that resolves to a CachedResponse containing a Blob, or fails with a FetchError
245
+ *
246
+ * @example
247
+ * ```typescript
248
+ * const imageEffect = cFetchEffectBlob(
249
+ * 'https://example.com/image.png',
250
+ * { method: 'GET' },
251
+ * { ttl: Duration.hours(1), tags: ['images'] }
252
+ * );
253
+ * ```
254
+ */
255
+ const cFetchEffectBlob = (url, options, cacheConfig) => cFetchEffect(url, (res) => res.blob(), options, cacheConfig);
256
+ /**
257
+ * Executes a cached fetch request with configurable caching behavior.
258
+ *
259
+ * @template T - The type of data returned after parsing the response
260
+ * @param url - The URL to fetch from
261
+ * @param parser - A function that parses the Response object into the desired type T
262
+ * @param options - Optional fetch request configuration (headers, method, body, etc.)
263
+ * @param cacheConfig - Optional cache configuration object
264
+ * @param cacheConfig.ttl - Time-to-live duration for the cached response
265
+ * @param cacheConfig.tags - Array of tags to associate with the cached entry for invalidation purposes
266
+ * @param cacheConfig.key - Custom cache key; if not provided, a key will be generated from the URL and options
267
+ * @returns A Promise that resolves to a CachedResponse containing the parsed data
268
+ *
269
+ * @example
270
+ * ```typescript
271
+ * const result = await cFetch(
272
+ * 'https://api.example.com/data',
273
+ * (res) => res.json(),
274
+ * { method: 'GET' },
275
+ * { ttl: Duration.minutes(5), tags: ['api-data'] }
276
+ * );
277
+ * ```
278
+ */
279
+ const cFetch = (url, parser, options, cacheConfig) => runEffect(cFetchEffect(url, parser, options, cacheConfig));
280
+ /**
281
+ * Fetches and parses JSON data from the specified URL with caching support.
282
+ *
283
+ * @template T - The expected type of the parsed JSON response data
284
+ * @param url - The URL to fetch data from
285
+ * @param options - Optional fetch configuration options (headers, method, body, etc.)
286
+ * @param cacheConfig - Optional cache configuration object
287
+ * @param cacheConfig.ttl - Time-to-live duration for the cached response
288
+ * @param cacheConfig.tags - Array of tags to associate with the cached entry for invalidation purposes
289
+ * @param cacheConfig.key - Custom cache key to use instead of the default
290
+ * @returns A Promise that resolves to a CachedResponse containing the parsed JSON data of type T
291
+ *
292
+ * @example
293
+ * ```typescript
294
+ * const result = await cFetchJson<User>('https://api.example.com/user/123', {
295
+ * method: 'GET',
296
+ * headers: { 'Authorization': 'Bearer token' }
297
+ * }, {
298
+ * ttl: Duration.minutes(5),
299
+ * tags: ['user-data']
300
+ * });
301
+ * ```
302
+ */
303
+ const cFetchJson = (url, options, cacheConfig) => runEffect(cFetchEffectJson(url, options, cacheConfig));
304
+ /**
305
+ * Fetches a URL and returns the response as text with caching support.
306
+ *
307
+ * @param url - The URL to fetch
308
+ * @param options - Optional fetch configuration options (headers, method, etc.)
309
+ * @param cacheConfig - Optional cache configuration
310
+ * @param cacheConfig.ttl - Time-to-live duration for the cached response
311
+ * @param cacheConfig.tags - Tags to associate with the cached response for invalidation
312
+ * @param cacheConfig.key - Custom cache key (defaults to URL if not provided)
313
+ * @returns A promise that resolves to a CachedResponse containing the response text
314
+ *
315
+ * @example
316
+ * ```typescript
317
+ * const result = await cFetchText('https://api.example.com/data', {
318
+ * method: 'GET'
319
+ * }, {
320
+ * ttl: Duration.hours(1),
321
+ * tags: ['api', 'data']
322
+ * });
323
+ * ```
324
+ */
325
+ const cFetchText = (url, options, cacheConfig) => runEffect(cFetchEffectText(url, options, cacheConfig));
326
+ /**
327
+ * Fetches a Blob resource from the specified URL with optional caching configuration.
328
+ *
329
+ * @param url - The URL to fetch the Blob resource from
330
+ * @param options - Optional fetch request configuration (headers, method, etc.)
331
+ * @param cacheConfig - Optional cache configuration object
332
+ * @param cacheConfig.ttl - Time-to-live duration for the cached response
333
+ * @param cacheConfig.tags - Array of cache tags for cache invalidation
334
+ * @param cacheConfig.key - Custom cache key for storing the response
335
+ * @returns A Promise that resolves to a CachedResponse containing a Blob
336
+ *
337
+ * @example
338
+ * ```typescript
339
+ * const response = await cFetchBlob('https://example.com/image.png', {}, { ttl: Duration.minutes(5) });
340
+ * const blob = response.data;
341
+ * ```
342
+ */
343
+ const cFetchBlob = (url, options, cacheConfig) => runEffect(cFetchEffectBlob(url, options, cacheConfig));
344
+ /**
345
+ * Invalidates cache entries based on specified keys or tags.
346
+ *
347
+ * @param opts - An object containing optional keys and tags for cache invalidation
348
+ * @param opts.keys - An array of specific cache keys to invalidate
349
+ * @param opts.tags - An array of tags; all cache entries associated with these tags will be invalidated
350
+ *
351
+ * @returns A Promise that resolves when the cache invalidation is complete
352
+ *
353
+ * @example
354
+ * ```typescript
355
+ * await invalidateCache({
356
+ * tags: ['user'],
357
+ * keys: ['user:123', 'user:456']
358
+ * });
359
+ * ```
360
+ */
361
+ const invalidateCache = (opts) => runEffect(invalidateCacheEffect(opts));
362
+
363
+ //#endregion
364
+ export { Duration, FetchError, cFetch, cFetchBlob, cFetchEffect, cFetchEffectBlob, cFetchEffectJson, cFetchEffectText, cFetchJson, cFetchText, invalidateCache, invalidateCacheEffect, noOpParser };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@studiocms/cfetch",
3
- "version": "0.2.1",
3
+ "version": "0.3.1",
4
4
  "description": "Astro integration that allows you to have a cached fetch function in your Astro SSR project.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://studiocms.dev",
@@ -41,29 +41,32 @@
41
41
  ],
42
42
  "exports": {
43
43
  ".": {
44
- "types": "./dist/index.d.ts",
45
- "default": "./dist/index.js"
44
+ "types": "./dist/index.d.mts",
45
+ "default": "./dist/index.mjs"
46
46
  },
47
47
  "./types": {
48
- "types": "./dist/types.d.ts",
49
- "default": "./dist/types.js"
48
+ "types": "./dist/types.d.mts",
49
+ "default": "./dist/types.mjs"
50
50
  }
51
51
  },
52
52
  "devDependencies": {
53
53
  "@inox-tools/astro-tests": "^0.8.1",
54
54
  "@types/node": "^22.0.0",
55
55
  "jest-extended": "^7.0.0",
56
- "astro": "^5.16.16",
57
- "effect": "^3.19.15"
56
+ "astro": "^5.17.1",
57
+ "effect": "^3.19.16"
58
58
  },
59
59
  "peerDependencies": {
60
- "astro": "^5.16.6",
60
+ "astro": ">=5.16.6",
61
61
  "effect": "^3.19.13",
62
62
  "vite": "^6.4.1"
63
63
  },
64
64
  "scripts": {
65
- "build": "buildkit build 'src/**/*.{ts,astro,css,js}'",
66
- "dev": "buildkit dev 'src/**/*.{ts,astro,css,js}'",
67
- "jsr": "jsr publish"
65
+ "build": "tsdown --config ./tsdown.config.ts --clean",
66
+ "dev": "tsdown --config ./tsdown.config.ts --watch",
67
+ "effect-check": "pnpm effect-language-service diagnostics --project tsconfig.tspc.json",
68
+ "typecheck": "tspc -p tsconfig.tspc.json",
69
+ "jsr": "jsr publish",
70
+ "ci:effect-check": "pnpm effect-check --format github-actions"
68
71
  }
69
72
  }