@igniter-js/caller 0.1.4 → 0.1.5

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
@@ -44,7 +44,7 @@ The package follows these core principles:
44
44
 
45
45
  `@igniter-js/caller` is a standalone library that can be used independently or alongside other Igniter.js packages. It integrates with:
46
46
 
47
- - **`@igniter-js/core`:** Uses `IgniterError` base class, `IgniterLogger` interface, and `StandardSchemaV1` type.
47
+ - **`@igniter-js/common`:** Uses `IgniterError` base class, `IgniterLogger` interface, and `StandardSchemaV1` type.
48
48
 
49
49
  - **`@igniter-js/telemetry`:** Emits structured telemetry events for request lifecycle monitoring.
50
50
 
@@ -54,6 +54,11 @@ The package follows these core principles:
54
54
 
55
55
  Unlike most Igniter.js packages, `@igniter-js/caller` is **explicitly designed to work in both server and client environments**. It does NOT have a server-only shim because HTTP clients are a valid use case for browser applications.
56
56
 
57
+ Additional constraints for client usage:
58
+
59
+ - The React layer is exported from `@igniter-js/caller/client` to avoid bundling React into non-React consumers.
60
+ - If a caller instance is configured with server-only store adapters or telemetry managers, do not bundle that instance in browser code. Create a browser-safe instance instead.
61
+
57
62
  ---
58
63
 
59
64
  ## I. MAINTAINER GUIDE (Internal Architecture)
@@ -73,6 +78,15 @@ packages/caller/src/
73
78
  │ ├── schema.builder.ts # IgniterCallerSchema (schema registry builder)
74
79
  │ ├── schema.builder.spec.ts # Schema builder tests
75
80
  │ └── schema-path.builder.ts # IgniterCallerSchemaPathBuilder (path+methods)
81
+ ├── client/ # React client layer (Provider + hooks)
82
+ │ ├── index.ts # React client entrypoint barrel
83
+ │ ├── builders/ # Provider + hook factories
84
+ │ ├── interfaces/ # Client-specific types
85
+ │ └── utils/ # Client-only helpers (cache, keys, cookies)
86
+ ├── mock/ # Typed mock registry for schemas
87
+ │ ├── index.ts # Mock exports barrel
88
+ │ ├── main.builder.ts # IgniterCallerMockBuilder
89
+ │ └── manager.ts # IgniterCallerMockManager
76
90
  ├── core/ # Runtime execution layer
77
91
  │ ├── index.ts # Core exports barrel
78
92
  │ ├── manager.ts # IgniterCallerManager (HTTP client runtime)
@@ -122,7 +136,18 @@ packages/caller/src/
122
136
  | `schema.builder.ts` | `IgniterCallerSchema` class - schema registry builder with `$Infer` type helpers and `get` runtime helpers. Prevents duplicate keys and paths. |
123
137
  | `schema-path.builder.ts` | `IgniterCallerSchemaPathBuilder` class - path-first fluent API for defining HTTP methods (GET, POST, PUT, PATCH, DELETE, HEAD) on a path. Provides `ref()` helper for registry references. |
124
138
 
125
- #### 2.2 Core Directory (`src/core/`)
139
+ #### 2.2 Client Directory (`src/client/`)
140
+
141
+ **Purpose:** React-specific layer that provides Provider + hooks for multiple callers.
142
+
143
+ | Folder/File | Responsibility |
144
+ | -------------------- | -------------------------------------------------------------------------------------------------------- |
145
+ | `builders/` | `IgniterCallerProvider`, `useIgniterCaller`, and hook factories for `useQuery`/`useMutate`. |
146
+ | `interfaces/` | Client-only types for config, hooks, context, and the wrapper client API. |
147
+ | `utils/` | Client-only helpers (query keys, in-memory cache, cookie header merge). |
148
+ | `index.ts` | Client entrypoint barrel used by `@igniter-js/caller/client`. |
149
+
150
+ #### 2.3 Core Directory (`src/core/`)
126
151
 
127
152
  **Purpose:** Runtime execution and event handling.
128
153
 
@@ -131,7 +156,7 @@ packages/caller/src/
131
156
  | `manager.ts` | `IgniterCallerManager` class - the main HTTP client runtime. Creates request builders, executes direct requests, manages global event emission, and provides static methods for cache invalidation and batch requests. |
132
157
  | `events.ts` | `IgniterCallerEvents` class - global event emitter supporting exact URL matches and RegExp patterns. Handles listener registration, cleanup, and error-safe emission. |
133
158
 
134
- #### 2.3 Types Directory (`src/types/`)
159
+ #### 2.4 Types Directory (`src/types/`)
135
160
 
136
161
  **Purpose:** Pure TypeScript contracts—no implementation code.
137
162
 
@@ -150,7 +175,7 @@ packages/caller/src/
150
175
  | `schemas.ts` | Core schema types: `IgniterCallerSchemaMethod`, `IgniterCallerEndpointSchema`, `IgniterCallerSchemaMap`, path extraction types (`ExtractPathParams`), inference types (`InferRequestType`, `InferResponseType`, `InferSuccessResponseType`, `InferAllResponseTypes`), path filtering types (`GetPaths`, `PostPaths`, etc.), endpoint info types, validation options. |
151
176
  | `store.ts` | `IgniterCallerStoreAdapter<TClient>`, `IgniterCallerStoreOptions`. |
152
177
 
153
- #### 2.4 Utils Directory (`src/utils/`)
178
+ #### 2.5 Utils Directory (`src/utils/`)
154
179
 
155
180
  **Purpose:** Pure functions for specific operations.
156
181
 
@@ -672,7 +697,7 @@ This section provides step-by-step flow documentation for every public method.
672
697
 
673
698
  | Package | Purpose | Peer Dependency |
674
699
  | ----------------------- | --------------------------------------------------- | ---------------------------------------- |
675
- | `@igniter-js/core` | `IgniterError`, `IgniterLogger`, `StandardSchemaV1` | ✅ Required |
700
+ | `@igniter-js/common` | `IgniterError`, `IgniterLogger`, `StandardSchemaV1` | ✅ Required |
676
701
  | `@igniter-js/telemetry` | `IgniterTelemetryManager`, `IgniterTelemetryEvents` | ⚙️ Optional |
677
702
  | `zod` | Schema validation (v4+) | ⚙️ Optional (any StandardSchemaV1 works) |
678
703
 
@@ -907,6 +932,10 @@ The package is distributed as a standard npm package with multiple entry points.
907
932
  │ ├── index.js # CommonJS main entry
908
933
  │ ├── index.mjs # ESM main entry
909
934
  │ ├── index.d.ts # TypeScript definitions
935
+ │ ├── client/
936
+ │ │ ├── index.js # React client entry (CJS)
937
+ │ │ ├── index.mjs # React client entry (ESM)
938
+ │ │ └── index.d.ts # React client types
910
939
  │ ├── telemetry/
911
940
  │ │ ├── index.js # Telemetry definitions (CJS)
912
941
  │ │ ├── index.mjs # Telemetry definitions (ESM)
@@ -930,6 +959,12 @@ import { IgniterCallerTelemetryEvents } from "@igniter-js/caller/telemetry";
930
959
  // Mock adapter - for testing
931
960
  import { MockCallerStoreAdapter } from "@igniter-js/caller/adapters";
932
961
 
962
+ // React client - Provider + hooks
963
+ import { IgniterCallerProvider, useIgniterCaller } from "@igniter-js/caller/client";
964
+
965
+ // Typed mock registry
966
+ import { IgniterCallerMock } from "@igniter-js/caller";
967
+
933
968
  // Types - for extending or advanced usage
934
969
  import type {
935
970
  IgniterCallerApiResponse,
@@ -1008,6 +1043,78 @@ const result = await api
1008
1043
  .execute();
1009
1044
  ```
1010
1045
 
1046
+ #### 9.6 React Client (Provider + Hooks)
1047
+
1048
+ ```tsx
1049
+ import { IgniterCallerProvider, useIgniterCaller } from "@igniter-js/caller/client";
1050
+
1051
+ export function CallerProvider() {
1052
+ return (
1053
+ <IgniterCallerProvider callers={{ github: githubApi }}>
1054
+ <App />
1055
+ </IgniterCallerProvider>
1056
+ );
1057
+ }
1058
+
1059
+ export const useCaller = useIgniterCaller<{
1060
+ github: typeof githubApi;
1061
+ }>();
1062
+
1063
+ function Profile() {
1064
+ const github = useCaller("github");
1065
+ const { data, isLoading, error, refetch, invalidate } = github
1066
+ .get("/me")
1067
+ .useQuery({ staleTime: 5000 });
1068
+
1069
+ if (isLoading) return <div>Loading...</div>;
1070
+ if (error) return <div>Error</div>;
1071
+ return <pre>{JSON.stringify(data, null, 2)}</pre>;
1072
+ }
1073
+ ```
1074
+
1075
+ Notes:
1076
+
1077
+ - `@igniter-js/caller/client` is the only entrypoint that depends on React.
1078
+ - Global defaults can be set via `github.config.set(...)`.
1079
+ - Invalidation supports an optional data payload for optimistic updates.
1080
+
1081
+ #### 9.7 Typed Mocks (IgniterCallerMock)
1082
+
1083
+ ```typescript
1084
+ import { IgniterCaller, IgniterCallerMock } from "@igniter-js/caller";
1085
+
1086
+ const schemas = {
1087
+ "/users/:id": {
1088
+ GET: {
1089
+ responses: {
1090
+ 200: UserSchema,
1091
+ },
1092
+ },
1093
+ },
1094
+ };
1095
+
1096
+ const mock = IgniterCallerMock.create()
1097
+ .withSchemas(schemas)
1098
+ .mock("/users/:id", {
1099
+ GET: (request) => ({
1100
+ response: { id: request.params.id },
1101
+ status: 200,
1102
+ delayMs: 150,
1103
+ }),
1104
+ })
1105
+ .build();
1106
+
1107
+ const api = IgniterCaller.create()
1108
+ .withSchemas(schemas)
1109
+ .withMock({ enabled: true, mock })
1110
+ .build();
1111
+ ```
1112
+
1113
+ Notes:
1114
+
1115
+ - Mock handlers receive the full request context (method, url, headers, query, params, body).
1116
+ - When mock is enabled and no handler is registered, the request falls back to the real transport.
1117
+
1011
1118
  ---
1012
1119
 
1013
1120
  ### 10. Real-World Use Case Library
package/README.md CHANGED
@@ -23,16 +23,16 @@ Type-safe HTTP client for Igniter.js apps. Built on top of `fetch`, it gives you
23
23
 
24
24
  ```bash
25
25
  # npm
26
- npm install @igniter-js/caller @igniter-js/core
26
+ npm install @igniter-js/caller @igniter-js/common
27
27
 
28
28
  # pnpm
29
- pnpm add @igniter-js/caller @igniter-js/core
29
+ pnpm add @igniter-js/caller @igniter-js/common
30
30
 
31
31
  # yarn
32
- yarn add @igniter-js/caller @igniter-js/core
32
+ yarn add @igniter-js/caller @igniter-js/common
33
33
 
34
34
  # bun
35
- bun add @igniter-js/caller @igniter-js/core
35
+ bun add @igniter-js/caller @igniter-js/common
36
36
  ```
37
37
 
38
38
  Optional dependencies:
@@ -45,7 +45,7 @@ npm install @igniter-js/telemetry
45
45
  npm install zod
46
46
  ```
47
47
 
48
- > `@igniter-js/core` is required. `@igniter-js/telemetry` and `zod` are optional peer dependencies.
48
+ > `@igniter-js/common` is required. `@igniter-js/telemetry` and `zod` are optional peer dependencies.
49
49
 
50
50
  ## Quick Start
51
51
 
@@ -73,6 +73,124 @@ if (result.error) {
73
73
  console.log(result.data)
74
74
  ```
75
75
 
76
+ ## React Client (Provider + Hooks)
77
+
78
+ The React client is exposed via the dedicated subpath export:
79
+
80
+ ```ts
81
+ import { IgniterCallerProvider, useIgniterCaller } from '@igniter-js/caller/client'
82
+ ```
83
+
84
+ This keeps the root entrypoint server-safe and avoids bundling React in non-React environments.
85
+
86
+ ### Basic usage
87
+
88
+ ```tsx
89
+ import { IgniterCallerProvider, useIgniterCaller } from '@igniter-js/caller/client'
90
+
91
+ export function CallerProvider() {
92
+ return (
93
+ <IgniterCallerProvider callers={{ github: githubApi }}>
94
+ <UserProfile />
95
+ </IgniterCallerProvider>
96
+ )
97
+ }
98
+
99
+ export const useCaller = useIgniterCaller<{
100
+ github: typeof githubApi
101
+ }>()
102
+
103
+ function UserProfile() {
104
+ const github = useCaller('github')
105
+ const { data, isLoading, error, refetch, invalidate } = github
106
+ .get('/me')
107
+ .useQuery({
108
+ params: {},
109
+ query: {},
110
+ headers: {},
111
+ cookies: {},
112
+ staleTime: 5000,
113
+ enabled: true,
114
+ })
115
+
116
+ if (isLoading) return <div>Loading...</div>
117
+ if (error) return <div>Error</div>
118
+ return <pre>{JSON.stringify(data, null, 2)}</pre>
119
+ }
120
+ ```
121
+
122
+ ### Global config and invalidation
123
+
124
+ ```tsx
125
+ const github = useCaller('github')
126
+
127
+ // Global defaults
128
+ github.config.set('headers', { Authorization: 'Bearer ...' })
129
+ github.config.set('cookies', { session: '...' })
130
+ github.config.set('query', { locale: 'en' })
131
+
132
+ // Typed invalidation with optional optimistic data
133
+ github.invalidate('/me', { id: 'user_123' })
134
+ ```
135
+
136
+ ### Client safety notes
137
+
138
+ - If your Caller instance uses store adapters or telemetry managers that are server-only,
139
+ do not bundle that instance into browser code. Create a browser-safe instance instead.
140
+ - The React client does not automatically wire store/telemetry to avoid bundler contamination.
141
+
142
+ ## Mocking (IgniterCallerMock)
143
+
144
+ Use `IgniterCallerMock` to create a type-safe mock registry based on your schemas.
145
+
146
+ ```ts
147
+ import { IgniterCaller, IgniterCallerMock } from '@igniter-js/caller'
148
+
149
+ const schemas = {
150
+ '/users/:id': {
151
+ GET: {
152
+ responses: {
153
+ 200: UserSchema,
154
+ },
155
+ },
156
+ },
157
+ }
158
+
159
+ const mock = IgniterCallerMock.create()
160
+ .withSchemas(schemas)
161
+ .mock('/users/:id', {
162
+ GET: {
163
+ response: { id: 'user_1' },
164
+ },
165
+ })
166
+ .build()
167
+
168
+ const api = IgniterCaller.create()
169
+ .withSchemas(schemas)
170
+ .withMock({ enabled: true, mock })
171
+ .build()
172
+ ```
173
+
174
+ Mock handlers receive the full request context:
175
+
176
+ ```ts
177
+ const mock = IgniterCallerMock.create()
178
+ .withSchemas(schemas)
179
+ .mock('/users/:id', {
180
+ GET: (request) => ({
181
+ response: { id: request.params.id },
182
+ status: 200,
183
+ delayMs: 150,
184
+ }),
185
+ })
186
+ .build()
187
+ ```
188
+
189
+ Notes:
190
+
191
+ - If mock is enabled but there is no handler for a request, it falls back to the real request.
192
+ - Mock responses can include `status`, `headers`, and optional `delayMs`.
193
+
76
194
  ## HTTP Methods
77
195
 
78
196
  All HTTP methods accept an optional URL directly:
@@ -1 +1,70 @@
1
- export { M as MockCallerStoreAdapter } from '../index-COZVROi_.mjs';
1
+ import { I as IgniterCallerStoreAdapter, a as IgniterCallerStoreOptions } from '../store-D2p2dqGN.mjs';
2
+
3
+ /**
4
+ * @fileoverview In-memory mock store adapter for @igniter-js/caller.
5
+ * @module @igniter-js/caller/adapters/mock
6
+ */
7
+
8
+ /**
9
+ * In-memory mock adapter for request caching in tests.
10
+ */
11
+ declare class MockCallerStoreAdapter implements IgniterCallerStoreAdapter<Map<string, unknown>> {
12
+ /** Creates a new mock adapter instance. */
13
+ static create(): MockCallerStoreAdapter;
14
+ /** Underlying in-memory store. */
15
+ readonly client: Map<string, unknown>;
16
+ /** Tracks all calls for assertions. */
17
+ readonly calls: {
18
+ get: number;
19
+ set: number;
20
+ delete: number;
21
+ has: number;
22
+ };
23
+ /** Captures recent operations. */
24
+ readonly history: {
25
+ get: string[];
26
+ set: Array<{
27
+ key: string;
28
+ value: unknown;
29
+ options?: IgniterCallerStoreOptions;
30
+ }>;
31
+ delete: string[];
32
+ has: string[];
33
+ };
34
+ /**
35
+ * Retrieves a cached value by key.
36
+ *
37
+ * @param key - Cache key (without prefix).
38
+ * @returns Cached value or null.
39
+ */
40
+ get<T = any>(key: string): Promise<T | null>;
41
+ /**
42
+ * Stores a cached value.
43
+ *
44
+ * @param key - Cache key (without prefix).
45
+ * @param value - Value to store.
46
+ * @param options - Cache options (ttl, etc).
47
+ */
48
+ set(key: string, value: any, options?: IgniterCallerStoreOptions): Promise<void>;
49
+ /**
50
+ * Removes a cached value.
51
+ *
52
+ * @param key - Cache key (without prefix).
53
+ */
54
+ delete(key: string): Promise<void>;
55
+ /**
56
+ * Checks if a cached value exists.
57
+ *
58
+ * @param key - Cache key (without prefix).
59
+ * @returns True when the key exists.
60
+ */
61
+ has(key: string): Promise<boolean>;
62
+ /**
63
+ * Clears all tracked state.
64
+ *
65
+ * @returns Nothing.
66
+ */
67
+ clear(): void;
68
+ }
69
+
70
+ export { MockCallerStoreAdapter };
@@ -1 +1,70 @@
1
- export { M as MockCallerStoreAdapter } from '../index-COZVROi_.js';
1
+ import { I as IgniterCallerStoreAdapter, a as IgniterCallerStoreOptions } from '../store-D2p2dqGN.js';
2
+
3
+ /**
4
+ * @fileoverview In-memory mock store adapter for @igniter-js/caller.
5
+ * @module @igniter-js/caller/adapters/mock
6
+ */
7
+
8
+ /**
9
+ * In-memory mock adapter for request caching in tests.
10
+ */
11
+ declare class MockCallerStoreAdapter implements IgniterCallerStoreAdapter<Map<string, unknown>> {
12
+ /** Creates a new mock adapter instance. */
13
+ static create(): MockCallerStoreAdapter;
14
+ /** Underlying in-memory store. */
15
+ readonly client: Map<string, unknown>;
16
+ /** Tracks all calls for assertions. */
17
+ readonly calls: {
18
+ get: number;
19
+ set: number;
20
+ delete: number;
21
+ has: number;
22
+ };
23
+ /** Captures recent operations. */
24
+ readonly history: {
25
+ get: string[];
26
+ set: Array<{
27
+ key: string;
28
+ value: unknown;
29
+ options?: IgniterCallerStoreOptions;
30
+ }>;
31
+ delete: string[];
32
+ has: string[];
33
+ };
34
+ /**
35
+ * Retrieves a cached value by key.
36
+ *
37
+ * @param key - Cache key (without prefix).
38
+ * @returns Cached value or null.
39
+ */
40
+ get<T = any>(key: string): Promise<T | null>;
41
+ /**
42
+ * Stores a cached value.
43
+ *
44
+ * @param key - Cache key (without prefix).
45
+ * @param value - Value to store.
46
+ * @param options - Cache options (ttl, etc).
47
+ */
48
+ set(key: string, value: any, options?: IgniterCallerStoreOptions): Promise<void>;
49
+ /**
50
+ * Removes a cached value.
51
+ *
52
+ * @param key - Cache key (without prefix).
53
+ */
54
+ delete(key: string): Promise<void>;
55
+ /**
56
+ * Checks if a cached value exists.
57
+ *
58
+ * @param key - Cache key (without prefix).
59
+ * @returns True when the key exists.
60
+ */
61
+ has(key: string): Promise<boolean>;
62
+ /**
63
+ * Clears all tracked state.
64
+ *
65
+ * @returns Nothing.
66
+ */
67
+ clear(): void;
68
+ }
69
+
70
+ export { MockCallerStoreAdapter };