@igniter-js/caller 0.1.0 → 0.1.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.
package/AGENTS.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # @igniter-js/caller - AI Agent Instructions
2
2
 
3
3
  > **Package Version:** 0.1.0
4
- > **Last Updated:** 2025-12-13
4
+ > **Last Updated:** 2025-12-14
5
5
  > **Status:** Ready for Publication
6
6
 
7
7
  ---
@@ -14,13 +14,16 @@
14
14
 
15
15
  ### Core Features
16
16
 
17
- - Fluent request builder API (`IgniterCaller.create()` + `.get()/.post()/.request()`)
17
+ - Fluent request builder API (`api.get('/users').execute()`)
18
+ - axios-style requests (`api.request({ method, url, body })`)
19
+ - Auto content-type detection (JSON, XML, Blob, Stream, etc.)
18
20
  - Request and response interceptors
19
21
  - Retry support (linear/exponential backoff + status-based retries)
20
22
  - Caching (in-memory + optional persistent store adapter)
21
23
  - Global response events (observe responses across the app)
22
24
  - Schema validation using `StandardSchemaV1` from `@igniter-js/core`
23
25
  - Optional Zod response validation via `responseType(zodSchema)`
26
+ - Auto-conversion of GET body to query params
24
27
 
25
28
  ---
26
29
 
@@ -38,32 +41,121 @@ This package is intentionally small and split into predictable layers:
38
41
 
39
42
  1. **Fetch-first**
40
43
  - Uses the global `fetch` API.
41
- - Works in Node.js (18+), Bun, and modern runtimes.
44
+ - Works in Node.js (18+), Bun, Deno, and modern browsers.
42
45
 
43
- 2. **Typed error surface**
46
+ 2. **Auto content-type detection**
47
+ - Response parsing is automatic based on `Content-Type` header.
48
+ - JSON, XML, CSV → parsed and validated if schema provided.
49
+ - Blob, Stream, ArrayBuffer → returned as-is, no validation.
50
+
51
+ 3. **Typed error surface**
44
52
  - Predictable errors are `IgniterCallerError` with stable error codes.
45
53
 
46
- 3. **Separation of concerns**
54
+ 4. **Separation of concerns**
47
55
  - `IgniterCallerRequestBuilder` focuses on request composition and execution.
48
56
  - `IgniterCallerCacheUtils` focuses on caching.
49
57
  - `IgniterCallerSchemaUtils` focuses on schema matching and validation.
50
58
 
51
- 4. **Stable public API**
59
+ 5. **Stable public API**
52
60
  - Keep exports in `src/index.ts` stable and backwards-compatible.
53
61
 
54
62
  ---
55
63
 
64
+ ## API Design
65
+
66
+ ### HTTP Methods
67
+
68
+ HTTP methods accept an optional URL directly and return a builder **without** the `.method()` function (since method is already set):
69
+
70
+ ```typescript
71
+ // These are equivalent:
72
+ api.get('/users').execute()
73
+ api.get().url('/users').execute()
74
+
75
+ // POST, PUT, PATCH, DELETE, HEAD work the same way:
76
+ api.post('/users').body({ name: 'John' }).execute()
77
+ api.delete('/users/1').execute()
78
+ ```
79
+
80
+ ### axios-style Requests
81
+
82
+ The `.request()` method executes immediately with all options:
83
+
84
+ ```typescript
85
+ const result = await api.request({
86
+ method: 'POST',
87
+ url: '/users',
88
+ body: { name: 'John' },
89
+ headers: { 'X-Custom': 'value' },
90
+ timeout: 5000,
91
+ staleTime: 30000,
92
+ retry: { maxAttempts: 3 },
93
+ })
94
+ ```
95
+
96
+ ### Response Type Detection
97
+
98
+ Response is parsed automatically based on `Content-Type` header:
99
+
100
+ | Content-Type | Parsed As |
101
+ |-------------|-----------|
102
+ | `application/json` | JSON object |
103
+ | `text/xml`, `application/xml` | Text |
104
+ | `text/csv` | Text |
105
+ | `text/html`, `text/plain` | Text |
106
+ | `image/*`, `audio/*`, `video/*` | Blob |
107
+ | `application/octet-stream` | Blob |
108
+
109
+ ### GET Body → Query Params
110
+
111
+ Body in GET/HEAD requests is automatically converted to query params:
112
+
113
+ ```typescript
114
+ api.get('/search').body({ q: 'test', page: 1 }).execute()
115
+ // → GET /search?q=test&page=1
116
+ ```
117
+
118
+ ---
119
+
120
+ ## CLI Integration
121
+
122
+ - The Igniter CLI provides `igniter generate caller` to ingest an OpenAPI 3 spec (URL or file) and emit `schema.ts` + `index.ts` under `src/callers/<hostname>` by default.
123
+ - Generated schemas must follow `IgniterCallerSchemaMap` (`{ [path]: { METHOD: { request?: ..., responses: { <status>: zod } } } }`) to work with `.withSchemas()`.
124
+ - The CLI prefixes schemas and the exported caller with `--name` (e.g., `facebookCaller`, `FacebookSchema`).
125
+ - If runtime schema expectations change, update both the CLI generator and this documentation so consumers stay aligned.
126
+
127
+ ---
128
+
56
129
  ## File Structure
57
130
 
58
131
  ```
59
132
  packages/caller/
60
133
  ├── src/
61
- │ ├── index.ts
134
+ │ ├── index.ts # Public exports
135
+ │ ├── igniter-caller.spec.ts # Tests
62
136
  │ ├── core/
137
+ │ │ ├── igniter-caller.ts # Main IgniterCaller class
138
+ │ │ └── igniter-caller-events.ts # Event emitter
63
139
  │ ├── builder/
140
+ │ │ ├── igniter-caller.builder.ts # Builder for configuration
141
+ │ │ └── igniter-caller-request.builder.ts # Request builder
64
142
  │ ├── errors/
143
+ │ │ └── igniter-caller.error.ts # Error class
65
144
  │ ├── types/
145
+ │ │ ├── events.ts
146
+ │ │ ├── http.ts
147
+ │ │ ├── interceptors.ts
148
+ │ │ ├── request.ts
149
+ │ │ ├── response.ts
150
+ │ │ ├── retry.ts
151
+ │ │ ├── schemas.ts
152
+ │ │ └── store.ts
66
153
  │ └── utils/
154
+ │ ├── body.ts
155
+ │ ├── cache.ts
156
+ │ ├── schema.ts
157
+ │ ├── testing.ts
158
+ │ └── url.ts
67
159
  ├── package.json
68
160
  ├── tsconfig.json
69
161
  ├── tsup.config.ts
@@ -89,10 +181,20 @@ packages/caller/
89
181
  - Use `IgniterCallerError` for predictable failures.
90
182
  - Prefer stable `code` values over new ad-hoc error messages.
91
183
 
184
+ ### Error Codes
185
+
186
+ | Code | Description |
187
+ |------|-------------|
188
+ | `IGNITER_CALLER_HTTP_ERROR` | HTTP response with non-2xx status |
189
+ | `IGNITER_CALLER_TIMEOUT` | Request timeout |
190
+ | `IGNITER_CALLER_REQUEST_VALIDATION_FAILED` | Request body schema validation failed |
191
+ | `IGNITER_CALLER_RESPONSE_VALIDATION_FAILED` | Response schema validation failed |
192
+ | `IGNITER_CALLER_UNKNOWN_ERROR` | Unexpected error |
193
+
92
194
  ### Dependencies
93
195
 
94
- - `@igniter-js/core` is a **peer dependency** (for shared types like `IgniterError` and `StandardSchemaV1`).
95
- - `zod` is a **peer dependency** (used when consumers call `responseType(zodSchema)` and referenced in public types).
196
+ - `@igniter-js/core` is a **peer dependency** (for shared types like `IgniterLogger` and `StandardSchemaV1`).
197
+ - `zod` is a **peer dependency** (used when consumers call `responseType(zodSchema)`).
96
198
 
97
199
  ---
98
200
 
@@ -104,6 +206,9 @@ packages/caller/
104
206
  - Response schema validation returns `IgniterCallerError` on invalid payload.
105
207
  - Caching returns cached data without calling `fetch` again.
106
208
  - Event emission happens for responses.
209
+ - URL is passed correctly to HTTP methods.
210
+ - Body is converted to query params for GET requests.
211
+ - Content-type detection works correctly.
107
212
 
108
213
  Run tests:
109
214
 
@@ -113,6 +218,43 @@ npm test --filter @igniter-js/caller
113
218
 
114
219
  ---
115
220
 
221
+ ## Key Implementation Details
222
+
223
+ ### IgniterCallerMethodRequestBuilder
224
+
225
+ When using specific HTTP methods (get, post, etc.), the builder returns a type that omits internal methods:
226
+
227
+ ```typescript
228
+ export type IgniterCallerMethodRequestBuilder<TResponse = unknown> = Omit<
229
+ IgniterCallerRequestBuilder<TResponse>,
230
+ '_setMethod' | '_setUrl'
231
+ >
232
+ ```
233
+
234
+ This prevents calling `.method()` on a request that already has a method set.
235
+
236
+ ### Content-Type Detection
237
+
238
+ The `detectContentType` function maps headers to response types:
239
+
240
+ ```typescript
241
+ function detectContentType(contentType: string | null): IgniterCallerResponseContentType
242
+ ```
243
+
244
+ Returns one of: `'json' | 'xml' | 'csv' | 'text' | 'html' | 'blob' | 'stream' | 'arraybuffer' | 'formdata'`
245
+
246
+ ### Schema Validation
247
+
248
+ Schema validation only runs for validatable content types:
249
+
250
+ ```typescript
251
+ const VALIDATABLE_CONTENT_TYPES = ['json', 'xml', 'csv']
252
+ ```
253
+
254
+ Binary responses (Blob, Stream, ArrayBuffer) are never validated.
255
+
256
+ ---
257
+
116
258
  ## Publishing Checklist
117
259
 
118
260
  - [ ] `npm run build --filter @igniter-js/caller`
package/CHANGELOG.md CHANGED
@@ -2,6 +2,60 @@
2
2
 
3
3
  All notable changes to this package will be documented in this file.
4
4
 
5
+ ## 0.1.1
6
+
7
+ ### New Features
8
+
9
+ - **URL in HTTP methods** - All HTTP methods (`get`, `post`, `put`, `patch`, `delete`, `head`) now accept URL directly:
10
+ ```ts
11
+ // Before
12
+ api.get().url('/users').execute()
13
+
14
+ // After
15
+ api.get('/users').execute()
16
+ ```
17
+
18
+ - **axios-style requests** - New `.request()` method for object-based API:
19
+ ```ts
20
+ const result = await api.request({
21
+ method: 'POST',
22
+ url: '/users',
23
+ body: { name: 'John' },
24
+ timeout: 5000,
25
+ })
26
+ ```
27
+
28
+ - **Auto content-type detection** - Response is automatically parsed based on `Content-Type` header:
29
+ - `application/json` → JSON object
30
+ - `text/xml`, `text/csv`, `text/html`, `text/plain` → Text
31
+ - `image/*`, `audio/*`, `video/*`, `application/pdf` → Blob
32
+ - `application/octet-stream` → Blob
33
+
34
+ - **GET body → query params** - Body in GET/HEAD requests is automatically converted to query parameters:
35
+ ```ts
36
+ api.get('/search').body({ q: 'test' }).execute()
37
+ // → GET /search?q=test
38
+ ```
39
+
40
+ - **Response includes status and headers** - API response now includes HTTP status and headers:
41
+ ```ts
42
+ const result = await api.get('/users').execute()
43
+ console.log(result.status) // 200
44
+ console.log(result.headers?.get('x-request-id'))
45
+ ```
46
+
47
+ - **HEAD method** - Added `.head()` method for HEAD requests.
48
+
49
+ ### Improvements
50
+
51
+ - `responseType()` now serves primarily for TypeScript typing. Schema validation only runs for validatable content types (JSON, XML, CSV).
52
+ - `.method()` is no longer available when using specific HTTP methods (`get`, `post`, etc.) to prevent confusion.
53
+ - Better type inference for schema maps with new utility types.
54
+
55
+ ### Deprecated
56
+
57
+ - `getFile()` is deprecated. Use `.responseType<Blob>().execute()` or `.responseType<File>().execute()` instead. Content-type detection is automatic.
58
+
5
59
  ## 0.1.0
6
60
 
7
61
  - Initial release of `@igniter-js/caller`.
package/README.md CHANGED
@@ -7,13 +7,16 @@ Type-safe HTTP client for Igniter.js apps. Built on top of `fetch`, it gives you
7
7
 
8
8
  ## Features
9
9
 
10
- - ✅ **Fluent API** - `IgniterCaller.create().withBaseUrl(...).build()`
10
+ - ✅ **Fluent API** - `api.get('/users').execute()` or builder pattern
11
+ - ✅ **axios-style requests** - `api.request({ method, url, body, ... })`
12
+ - ✅ **Auto content-type detection** - JSON, XML, CSV, Blob, Stream, etc.
11
13
  - ✅ **Interceptors** - modify requests and responses in one place
12
14
  - ✅ **Retries** - linear or exponential backoff + status-based retry
13
15
  - ✅ **Caching** - in-memory cache + optional persistent store adapter
14
16
  - ✅ **Schema Validation** - validate request/response using `StandardSchemaV1`
15
17
  - ✅ **Zod Support** - optional per-request `responseType(zodSchema)` validation
16
18
  - ✅ **Global Events** - observe responses for logging/telemetry/cache invalidation
19
+ - ✅ **Auto query encoding** - body in GET requests converts to query params
17
20
 
18
21
  ## Installation
19
22
 
@@ -43,12 +46,14 @@ export const api = IgniterCaller.create()
43
46
  .withHeaders({ Authorization: `Bearer ${process.env.API_TOKEN}` })
44
47
  .build()
45
48
 
46
- const result = await api
47
- .get()
48
- .url('/users')
49
- .params({ page: 1 })
50
- .stale(10_000) // cache for 10s
51
- .execute<{ id: string; name: string }[]>()
49
+ // Simple GET request with URL directly
50
+ const result = await api.get('/users').execute()
51
+
52
+ // With query params
53
+ const result = await api.get('/users').params({ page: 1 }).execute()
54
+
55
+ // With caching
56
+ const result = await api.get('/users').stale(10_000).execute()
52
57
 
53
58
  if (result.error) {
54
59
  throw result.error
@@ -57,13 +62,105 @@ if (result.error) {
57
62
  console.log(result.data)
58
63
  ```
59
64
 
65
+ ## HTTP Methods
66
+
67
+ All HTTP methods accept an optional URL directly:
68
+
69
+ ```ts
70
+ // GET
71
+ const users = await api.get('/users').execute()
72
+
73
+ // POST with body
74
+ const created = await api.post('/users').body({ name: 'John' }).execute()
75
+
76
+ // PUT
77
+ const updated = await api.put('/users/1').body({ name: 'Jane' }).execute()
78
+
79
+ // PATCH
80
+ const patched = await api.patch('/users/1').body({ name: 'Jane' }).execute()
81
+
82
+ // DELETE
83
+ const deleted = await api.delete('/users/1').execute()
84
+
85
+ // HEAD
86
+ const head = await api.head('/users').execute()
87
+ ```
88
+
89
+ You can also use the traditional builder pattern:
90
+
91
+ ```ts
92
+ const result = await api.get().url('/users').params({ page: 1 }).execute()
93
+ ```
94
+
95
+ ## axios-style Requests
96
+
97
+ For dynamic requests or when you prefer an object-based API:
98
+
99
+ ```ts
100
+ const result = await api.request({
101
+ method: 'POST',
102
+ url: '/users',
103
+ body: { name: 'John' },
104
+ headers: { 'X-Custom': 'value' },
105
+ timeout: 5000,
106
+ })
107
+
108
+ // With caching
109
+ const result = await api.request({
110
+ method: 'GET',
111
+ url: '/users',
112
+ staleTime: 30000,
113
+ })
114
+
115
+ // With retry
116
+ const result = await api.request({
117
+ method: 'GET',
118
+ url: '/health',
119
+ retry: { maxAttempts: 3, backoff: 'exponential' },
120
+ })
121
+ ```
122
+
123
+ ## Auto Content-Type Detection
124
+
125
+ The response is automatically parsed based on the `Content-Type` header:
126
+
127
+ | Content-Type | Parsed As |
128
+ |-------------|-----------|
129
+ | `application/json` | JSON object |
130
+ | `text/xml`, `application/xml` | Text (parse with your XML library) |
131
+ | `text/csv` | Text |
132
+ | `text/html`, `text/plain` | Text |
133
+ | `image/*`, `audio/*`, `video/*` | Blob |
134
+ | `application/pdf`, `application/zip` | Blob |
135
+ | `application/octet-stream` | Blob |
136
+
137
+ ```ts
138
+ // JSON response - automatically parsed
139
+ const { data } = await api.get('/users').execute()
140
+
141
+ // Blob response - automatically detected
142
+ const { data } = await api.get('/file.pdf').responseType<Blob>().execute()
143
+
144
+ // Stream response
145
+ const { data } = await api.get('/stream').responseType<ReadableStream>().execute()
146
+ ```
147
+
148
+ ## GET with Body → Query Params
149
+
150
+ When you pass a body to a GET request, it's automatically converted to query parameters:
151
+
152
+ ```ts
153
+ // This:
154
+ await api.get('/search').body({ q: 'test', page: 1 }).execute()
155
+
156
+ // Becomes: GET /search?q=test&page=1
157
+ ```
158
+
60
159
  ## Interceptors
61
160
 
62
161
  Interceptors are great for cross-cutting concerns like auth headers, request ids, logging, and response normalization.
63
162
 
64
163
  ```ts
65
- import { IgniterCaller } from '@igniter-js/caller'
66
-
67
164
  const api = IgniterCaller.create()
68
165
  .withBaseUrl('https://api.example.com')
69
166
  .withRequestInterceptor(async (request) => {
@@ -80,7 +177,6 @@ const api = IgniterCaller.create()
80
177
  if (response.data === '') {
81
178
  return { ...response, data: null as any }
82
179
  }
83
-
84
180
  return response
85
181
  })
86
182
  .build()
@@ -92,8 +188,7 @@ Configure retry behavior for transient errors:
92
188
 
93
189
  ```ts
94
190
  const result = await api
95
- .get()
96
- .url('/health')
191
+ .get('/health')
97
192
  .retry(3, {
98
193
  baseDelay: 250,
99
194
  backoff: 'exponential',
@@ -109,7 +204,7 @@ const result = await api
109
204
  Use `.stale(ms)` to enable caching. The cache key defaults to the request URL, or you can set it via `.cache(cache, key)`.
110
205
 
111
206
  ```ts
112
- const users = await api.get().url('/users').stale(30_000).execute()
207
+ const users = await api.get('/users').stale(30_000).execute()
113
208
  ```
114
209
 
115
210
  ### Store-based caching
@@ -121,26 +216,18 @@ import { IgniterCaller } from '@igniter-js/caller'
121
216
 
122
217
  const store = {
123
218
  client: null,
124
- async get(key) {
125
- return null
126
- },
127
- async set(key, value) {
128
- void key
129
- void value
130
- },
131
- async delete(key) {
132
- void key
133
- },
134
- async has(key) {
135
- void key
136
- return false
137
- },
219
+ async get(key) { return null },
220
+ async set(key, value) { void key; void value },
221
+ async delete(key) { void key },
222
+ async has(key) { void key; return false },
138
223
  }
139
224
 
140
- const api = IgniterCaller.create().withStore(store, {
141
- ttl: 3600,
142
- keyPrefix: 'igniter:caller:',
143
- }).build()
225
+ const api = IgniterCaller.create()
226
+ .withStore(store, {
227
+ ttl: 3600,
228
+ keyPrefix: 'igniter:caller:',
229
+ })
230
+ .build()
144
231
  ```
145
232
 
146
233
  ## Schema Validation (StandardSchemaV1)
@@ -166,21 +253,45 @@ const api = IgniterCaller.create()
166
253
  .withSchemas(schemas, { mode: 'strict' })
167
254
  .build()
168
255
 
169
- const result = await api.get().url('/users/123').execute()
256
+ const result = await api.get('/users/123').execute()
257
+ ```
258
+
259
+ **Note:** Schema validation only runs for validatable content types (JSON, XML, CSV). Binary responses (Blob, Stream) are not validated.
260
+
261
+ ## Generate schemas via CLI
262
+
263
+ You can bootstrap Zod schemas and a ready-to-use caller from an OpenAPI 3 spec using the Igniter CLI:
264
+
265
+ ```bash
266
+ npx @igniter-js/cli generate caller --name facebook --url https://api.example.com/openapi.json
267
+ ```
268
+
269
+ By default this outputs `src/callers/<hostname>/schema.ts` and `index.ts`:
270
+
271
+ ```ts
272
+ import { facebookCaller } from './src/callers/api.example.com'
273
+
274
+ const result = await facebookCaller.get('/products').execute()
170
275
  ```
171
276
 
172
- ## Zod `responseType()`
277
+ ## `responseType()` for Typing and Validation
173
278
 
174
- For one-off validation, you can attach a Zod schema to a request:
279
+ Use `responseType()` to:
280
+
281
+ 1. **Type the response** - for TypeScript inference
282
+ 2. **Validate the response** - if you pass a Zod/StandardSchema (only for JSON/XML/CSV)
175
283
 
176
284
  ```ts
177
285
  import { z } from 'zod'
178
286
 
287
+ // With Zod schema - validates JSON response
179
288
  const result = await api
180
- .get()
181
- .url('/users')
289
+ .get('/users')
182
290
  .responseType(z.array(z.object({ id: z.string(), name: z.string() })))
183
291
  .execute()
292
+
293
+ // With type marker - typing only, no validation
294
+ const result = await api.get('/file').responseType<Blob>().execute()
184
295
  ```
185
296
 
186
297
  ## Global Events
@@ -193,6 +304,7 @@ import { IgniterCaller } from '@igniter-js/caller'
193
304
  const unsubscribe = IgniterCaller.on(/^\/users/, (result, ctx) => {
194
305
  console.log(`[${ctx.method}] ${ctx.url}`, {
195
306
  ok: !result.error,
307
+ status: result.status,
196
308
  })
197
309
  })
198
310
 
@@ -207,7 +319,7 @@ All predictable failures return an `IgniterCallerError` with stable error codes.
207
319
  ```ts
208
320
  import { IgniterCallerError } from '@igniter-js/caller'
209
321
 
210
- const result = await api.get().url('/users').execute()
322
+ const result = await api.get('/users').execute()
211
323
 
212
324
  if (result.error) {
213
325
  if (IgniterCallerError.is(result.error)) {
@@ -215,8 +327,70 @@ if (result.error) {
215
327
  }
216
328
  throw result.error
217
329
  }
330
+
331
+ // Response includes status and headers
332
+ console.log(result.status) // 200
333
+ console.log(result.headers?.get('x-request-id'))
218
334
  ```
219
335
 
336
+ ## API Reference
337
+
338
+ ### `IgniterCaller.create()`
339
+
340
+ Creates a new caller builder.
341
+
342
+ ### Builder Methods
343
+
344
+ | Method | Description |
345
+ |--------|-------------|
346
+ | `.withBaseUrl(url)` | Sets the base URL for all requests |
347
+ | `.withHeaders(headers)` | Sets default headers |
348
+ | `.withCookies(cookies)` | Sets default cookies |
349
+ | `.withLogger(logger)` | Attaches a logger |
350
+ | `.withRequestInterceptor(fn)` | Adds a request interceptor |
351
+ | `.withResponseInterceptor(fn)` | Adds a response interceptor |
352
+ | `.withStore(store, options)` | Configures a persistent store |
353
+ | `.withSchemas(schemas, options)` | Configures schema validation |
354
+ | `.build()` | Builds the caller instance |
355
+
356
+ ### Request Methods
357
+
358
+ | Method | Description |
359
+ |--------|-------------|
360
+ | `.get(url?)` | Creates a GET request |
361
+ | `.post(url?)` | Creates a POST request |
362
+ | `.put(url?)` | Creates a PUT request |
363
+ | `.patch(url?)` | Creates a PATCH request |
364
+ | `.delete(url?)` | Creates a DELETE request |
365
+ | `.head(url?)` | Creates a HEAD request |
366
+ | `.request(options)` | Executes request directly (axios-style) |
367
+
368
+ ### Request Builder Methods
369
+
370
+ | Method | Description |
371
+ |--------|-------------|
372
+ | `.url(url)` | Sets the URL |
373
+ | `.body(body)` | Sets the request body |
374
+ | `.params(params)` | Sets query parameters |
375
+ | `.headers(headers)` | Merges additional headers |
376
+ | `.timeout(ms)` | Sets request timeout |
377
+ | `.cache(cache, key?)` | Sets cache strategy |
378
+ | `.stale(ms)` | Sets cache stale time |
379
+ | `.retry(attempts, options)` | Configures retry behavior |
380
+ | `.fallback(fn)` | Provides fallback value |
381
+ | `.responseType(schema?)` | Sets expected response type |
382
+ | `.execute()` | Executes the request |
383
+
384
+ ### Static Methods
385
+
386
+ | Method | Description |
387
+ |--------|-------------|
388
+ | `IgniterCaller.on(pattern, callback)` | Registers event listener |
389
+ | `IgniterCaller.off(pattern, callback?)` | Removes event listener |
390
+ | `IgniterCaller.invalidate(key)` | Invalidates cache entry |
391
+ | `IgniterCaller.invalidatePattern(pattern)` | Invalidates cache by pattern |
392
+ | `IgniterCaller.batch(requests)` | Executes requests in parallel |
393
+
220
394
  ## Contributing
221
395
 
222
396
  Contributions are welcome! Please see the main [CONTRIBUTING.md](https://github.com/felipebarcelospro/igniter-js/blob/main/CONTRIBUTING.md) for details.