@replanejs/react 0.9.0 → 0.9.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/README.md CHANGED
@@ -29,7 +29,7 @@ import { ReplaneProvider, useConfig } from "@replanejs/react";
29
29
  function App() {
30
30
  return (
31
31
  <ReplaneProvider
32
- options={{
32
+ connection={{
33
33
  baseUrl: "https://your-replane-server.com",
34
34
  sdkKey: "your-sdk-key",
35
35
  }}
@@ -51,9 +51,9 @@ function MyComponent() {
51
51
 
52
52
  ### ReplaneProvider
53
53
 
54
- Provider component that makes the Replane client available to your component tree. Supports four usage patterns:
54
+ Provider component that makes the Replane client available to your component tree. Supports multiple usage patterns:
55
55
 
56
- #### 1. With options (recommended)
56
+ #### 1. With connection (recommended)
57
57
 
58
58
  The provider creates and manages the client internally. Use an Error Boundary to handle initialization errors:
59
59
 
@@ -62,7 +62,7 @@ import { ErrorBoundary } from "react-error-boundary";
62
62
 
63
63
  <ErrorBoundary fallback={<div>Failed to load configuration</div>}>
64
64
  <ReplaneProvider
65
- options={{
65
+ connection={{
66
66
  baseUrl: "https://your-replane-server.com",
67
67
  sdkKey: "your-sdk-key",
68
68
  }}
@@ -73,22 +73,32 @@ import { ErrorBoundary } from "react-error-boundary";
73
73
  </ErrorBoundary>;
74
74
  ```
75
75
 
76
- #### Client Options
76
+ #### Provider Props
77
77
 
78
- The `options` prop accepts the following options:
78
+ | Prop | Type | Required | Description |
79
+ | ------------ | --------------------------- | -------- | ------------------------------------------------------- |
80
+ | `connection` | `ConnectOptions \| null` | Yes | Connection options (see below), or `null` to skip connection |
81
+ | `defaults` | `Record<string, unknown>` | No | Default values if server is unavailable |
82
+ | `context` | `Record<string, unknown>` | No | Default context for override evaluations |
83
+ | `snapshot` | `ReplaneSnapshot` | No | Snapshot for SSR hydration |
84
+ | `logger` | `ReplaneLogger` | No | Custom logger (default: console) |
85
+ | `loader` | `ReactNode` | No | Component to show while loading |
86
+ | `suspense` | `boolean` | No | Use React Suspense for loading state |
87
+ | `async` | `boolean` | No | Connect asynchronously (renders immediately with defaults) |
88
+
89
+ #### Connection Options
90
+
91
+ The `connection` prop accepts the following options:
79
92
 
80
93
  | Option | Type | Required | Description |
81
94
  | -------------------- | --------------------- | -------- | -------------------------------------------- |
82
95
  | `baseUrl` | `string` | Yes | Replane server URL |
83
96
  | `sdkKey` | `string` | Yes | SDK key for authentication |
84
- | `context` | `Record<string, any>` | No | Default context for override evaluations |
85
- | `defaults` | `Record<string, any>` | No | Default values if server is unavailable |
86
97
  | `connectTimeoutMs` | `number` | No | SDK connection timeout (default: 5000) |
87
98
  | `requestTimeoutMs` | `number` | No | Timeout for SSE requests (default: 2000) |
88
99
  | `retryDelayMs` | `number` | No | Base delay between retries (default: 200) |
89
100
  | `inactivityTimeoutMs`| `number` | No | SSE inactivity timeout (default: 30000) |
90
101
  | `fetchFn` | `typeof fetch` | No | Custom fetch implementation |
91
- | `logger` | `ReplaneLogger` | No | Custom logger (default: console) |
92
102
 
93
103
  See [`@replanejs/sdk` documentation](https://github.com/replane-dev/replane-javascript/tree/main/packages/sdk#api) for more details.
94
104
 
@@ -118,7 +128,7 @@ Integrates with React Suspense for loading states:
118
128
  <ErrorBoundary fallback={<div>Failed to load configuration</div>}>
119
129
  <Suspense fallback={<LoadingSpinner />}>
120
130
  <ReplaneProvider
121
- options={{
131
+ connection={{
122
132
  baseUrl: "https://your-replane-server.com",
123
133
  sdkKey: "your-sdk-key",
124
134
  }}
@@ -130,7 +140,24 @@ Integrates with React Suspense for loading states:
130
140
  </ErrorBoundary>
131
141
  ```
132
142
 
133
- #### 4. With snapshot (for SSR/hydration)
143
+ #### 4. With async mode
144
+
145
+ Connect in the background while rendering immediately with defaults:
146
+
147
+ ```tsx
148
+ <ReplaneProvider
149
+ connection={{
150
+ baseUrl: "https://your-replane-server.com",
151
+ sdkKey: "your-sdk-key",
152
+ }}
153
+ defaults={{ featureEnabled: false }}
154
+ async
155
+ >
156
+ <App />
157
+ </ReplaneProvider>
158
+ ```
159
+
160
+ #### 5. With snapshot (for SSR/hydration)
134
161
 
135
162
  Restore a client from a snapshot obtained on the server. This is synchronous and useful for SSR scenarios:
136
163
 
@@ -143,7 +170,7 @@ const snapshot = serverClient.getSnapshot();
143
170
 
144
171
  // On the client
145
172
  <ReplaneProvider
146
- options={{
173
+ connection={{
147
174
  baseUrl: "https://your-replane-server.com",
148
175
  sdkKey: "your-sdk-key",
149
176
  }}
@@ -353,7 +380,7 @@ class ErrorBoundary extends Component<
353
380
 
354
381
  // Usage
355
382
  <ErrorBoundary fallback={<div>Configuration failed to load</div>}>
356
- <ReplaneProvider options={options} loader={<Loading />}>
383
+ <ReplaneProvider connection={connection} loader={<Loading />}>
357
384
  <App />
358
385
  </ReplaneProvider>
359
386
  </ErrorBoundary>;
@@ -373,7 +400,7 @@ import { ErrorBoundary } from "react-error-boundary";
373
400
  )}
374
401
  onReset={() => clearSuspenseCache()}
375
402
  >
376
- <ReplaneProvider options={options} loader={<Loading />}>
403
+ <ReplaneProvider connection={connection} loader={<Loading />}>
377
404
  <App />
378
405
  </ReplaneProvider>
379
406
  </ErrorBoundary>;
package/dist/index.cjs CHANGED
@@ -31,11 +31,6 @@ const react_jsx_runtime = __toESM(require("react/jsx-runtime"));
31
31
  //#region src/context.ts
32
32
  const ReplaneContext = (0, react.createContext)(null);
33
33
 
34
- //#endregion
35
- //#region src/version.ts
36
- const VERSION = "0.9.0";
37
- const DEFAULT_AGENT = `replane-js-react/${VERSION}`;
38
-
39
34
  //#endregion
40
35
  //#region src/useReplaneClient.ts
41
36
  const suspenseCache = new Map();
@@ -45,29 +40,21 @@ function getCacheKey(options) {
45
40
  /**
46
41
  * Creates a Replane client and connects it.
47
42
  */
48
- async function createAndConnectClient(options) {
43
+ async function createAndConnectClient(options, connection) {
49
44
  const client = new __replanejs_sdk.Replane({
50
45
  logger: options.logger,
51
46
  context: options.context,
52
47
  defaults: options.defaults
53
48
  });
54
- await client.connect({
55
- baseUrl: options.baseUrl,
56
- sdkKey: options.sdkKey,
57
- connectTimeoutMs: options.connectTimeoutMs,
58
- retryDelayMs: options.retryDelayMs,
59
- requestTimeoutMs: options.requestTimeoutMs,
60
- inactivityTimeoutMs: options.inactivityTimeoutMs,
61
- fetchFn: options.fetchFn,
62
- agent: options.agent ?? DEFAULT_AGENT
63
- });
49
+ if (!connection) return client;
50
+ await client.connect(connection);
64
51
  return client;
65
52
  }
66
53
  /**
67
54
  * Hook to manage Replane client creation internally.
68
55
  * Handles loading state and cleanup.
69
56
  */
70
- function useReplaneClientInternal(options) {
57
+ function useReplaneClientInternal(options, originalConnection) {
71
58
  const [state, setState] = (0, react.useState)({
72
59
  status: "loading",
73
60
  client: null,
@@ -75,11 +62,13 @@ function useReplaneClientInternal(options) {
75
62
  });
76
63
  const clientRef = (0, react.useRef)(null);
77
64
  const optionsRef = (0, react.useRef)(options);
65
+ const connectionJson = JSON.stringify(originalConnection);
78
66
  (0, react.useEffect)(() => {
67
+ const connection = JSON.parse(connectionJson);
79
68
  let cancelled = false;
80
69
  async function initClient() {
81
70
  try {
82
- const client = await createAndConnectClient(optionsRef.current);
71
+ const client = await createAndConnectClient(optionsRef.current, connection);
83
72
  if (cancelled) {
84
73
  client.disconnect();
85
74
  return;
@@ -108,22 +97,22 @@ function useReplaneClientInternal(options) {
108
97
  clientRef.current = null;
109
98
  }
110
99
  };
111
- }, []);
100
+ }, [connectionJson]);
112
101
  return state;
113
102
  }
114
103
  /**
115
104
  * Hook for Suspense-based client creation.
116
105
  * Throws a promise while loading, throws error on failure.
117
106
  */
118
- function useReplaneClientSuspense(options) {
119
- const cacheKey = getCacheKey(options);
107
+ function useReplaneClientSuspense(options, connection) {
108
+ const cacheKey = getCacheKey(connection);
120
109
  const cached = suspenseCache.get(cacheKey);
121
110
  if (cached) {
122
111
  if (cached.error) throw cached.error;
123
112
  if (cached.result) return cached.result;
124
113
  throw cached.promise;
125
114
  }
126
- const promise = createAndConnectClient(options).then((client) => {
115
+ const promise = createAndConnectClient(options, connection).then((client) => {
127
116
  const entry = suspenseCache.get(cacheKey);
128
117
  if (entry) entry.result = client;
129
118
  return client;
@@ -136,11 +125,11 @@ function useReplaneClientSuspense(options) {
136
125
  throw promise;
137
126
  }
138
127
  /**
139
- * Clear the suspense cache for a specific options configuration.
128
+ * Clear the suspense cache for a specific connection configuration.
140
129
  * Useful for testing or when you need to force re-initialization.
141
130
  */
142
- function clearSuspenseCache(options) {
143
- if (options) suspenseCache.delete(getCacheKey(options));
131
+ function clearSuspenseCache(connection) {
132
+ if (connection) suspenseCache.delete(getCacheKey(connection));
144
133
  else suspenseCache.clear();
145
134
  }
146
135
 
@@ -150,9 +139,14 @@ function clearSuspenseCache(options) {
150
139
  * Type guard to check if props contain a pre-created client.
151
140
  */
152
141
  function hasClient(props) {
153
- return "client" in props && props.client !== void 0;
142
+ return "client" in props && !!props.client;
154
143
  }
155
144
 
145
+ //#endregion
146
+ //#region src/version.ts
147
+ const VERSION = "0.9.2";
148
+ const DEFAULT_AGENT = `replane-js-react/${VERSION}`;
149
+
156
150
  //#endregion
157
151
  //#region src/provider.tsx
158
152
  /**
@@ -166,44 +160,23 @@ function ReplaneProviderWithClient({ client, children }) {
166
160
  });
167
161
  }
168
162
  /**
169
- * Internal provider component for restoring client from snapshot.
163
+ * Internal provider component for creating a Replane client asynchronously.
170
164
  * Creates a Replane client synchronously and connects in background.
171
165
  */
172
- function ReplaneProviderWithSnapshot({ options, snapshot, children }) {
166
+ function AsyncReplaneProvider({ children, connection,...options }) {
173
167
  const replaneRef = (0, react.useRef)(void 0);
174
- if (!replaneRef.current) replaneRef.current = new __replanejs_sdk.Replane({
175
- snapshot,
176
- logger: options.logger,
177
- context: options.context,
178
- defaults: options.defaults
179
- });
168
+ if (!replaneRef.current) replaneRef.current = new __replanejs_sdk.Replane(options);
169
+ const connectionJson = connection ? JSON.stringify(connection) : void 0;
180
170
  (0, react.useEffect)(() => {
181
- replaneRef.current.connect({
182
- baseUrl: options.baseUrl,
183
- sdkKey: options.sdkKey,
184
- connectTimeoutMs: options.connectTimeoutMs,
185
- retryDelayMs: options.retryDelayMs,
186
- requestTimeoutMs: options.requestTimeoutMs,
187
- inactivityTimeoutMs: options.inactivityTimeoutMs,
188
- fetchFn: options.fetchFn,
189
- agent: options.agent ?? DEFAULT_AGENT
190
- }).catch((err) => {
171
+ const parsedConnection = connectionJson ? JSON.parse(connectionJson) : void 0;
172
+ if (!parsedConnection) return;
173
+ replaneRef.current.connect(parsedConnection).catch((err) => {
191
174
  (options.logger ?? console)?.error("Failed to connect Replane client", err);
192
175
  });
193
176
  return () => {
194
177
  replaneRef.current.disconnect();
195
178
  };
196
- }, [
197
- options.agent,
198
- options.baseUrl,
199
- options.connectTimeoutMs,
200
- options.fetchFn,
201
- options.inactivityTimeoutMs,
202
- options.logger,
203
- options.requestTimeoutMs,
204
- options.retryDelayMs,
205
- options.sdkKey
206
- ]);
179
+ }, [connectionJson, options.logger]);
207
180
  const value = (0, react.useMemo)(() => ({ replane: replaneRef.current }), []);
208
181
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReplaneContext.Provider, {
209
182
  value,
@@ -214,8 +187,9 @@ function ReplaneProviderWithSnapshot({ options, snapshot, children }) {
214
187
  * Internal provider component for options-based client creation (non-suspense).
215
188
  * Throws errors during rendering so they can be caught by Error Boundaries.
216
189
  */
217
- function ReplaneProviderWithOptions({ options, children, loader }) {
218
- const state = useReplaneClientInternal(options);
190
+ function LoaderReplaneProvider({ children, loader, connection,...options }) {
191
+ if (!connection) throw new Error("Connection is required when using Loader");
192
+ const state = useReplaneClientInternal(options, connection);
219
193
  if (state.status === "loading") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: loader ?? null });
220
194
  if (state.status === "error") throw state.error;
221
195
  const value = { replane: state.client };
@@ -227,8 +201,9 @@ function ReplaneProviderWithOptions({ options, children, loader }) {
227
201
  /**
228
202
  * Internal provider component for options-based client creation with Suspense.
229
203
  */
230
- function ReplaneProviderWithSuspense({ options, children }) {
231
- const client = useReplaneClientSuspense(options);
204
+ function SuspenseReplaneProvider({ connection, children,...options }) {
205
+ if (!connection) throw new Error("Connection is required when using Suspense");
206
+ const client = useReplaneClientSuspense(options, connection);
232
207
  const value = (0, react.useMemo)(() => ({ replane: client }), [client]);
233
208
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReplaneContext.Provider, {
234
209
  value,
@@ -293,13 +268,21 @@ function ReplaneProviderWithSuspense({ options, children }) {
293
268
  * allowing them to be caught by React Error Boundaries.
294
269
  */
295
270
  function ReplaneProvider(props) {
271
+ const originalConnection = props.connection;
272
+ const connection = (0, react.useMemo)(() => originalConnection ? {
273
+ ...originalConnection,
274
+ agent: originalConnection.agent ?? DEFAULT_AGENT
275
+ } : void 0, [originalConnection]);
296
276
  if (hasClient(props)) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReplaneProviderWithClient, { ...props });
297
- if (props.snapshot) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReplaneProviderWithSnapshot, {
277
+ if (props.snapshot || !connection || props.async) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AsyncReplaneProvider, { ...props });
278
+ if (props.suspense) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SuspenseReplaneProvider, {
279
+ ...props,
280
+ connection
281
+ });
282
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LoaderReplaneProvider, {
298
283
  ...props,
299
- snapshot: props.snapshot
284
+ connection
300
285
  });
301
- if (props.suspense) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReplaneProviderWithSuspense, { ...props });
302
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReplaneProviderWithOptions, { ...props });
303
286
  }
304
287
 
305
288
  //#endregion
package/dist/index.d.cts CHANGED
@@ -1,66 +1,9 @@
1
1
  import * as react_jsx_runtime0 from "react/jsx-runtime";
2
- import { ConnectOptions, GetConfigOptions, GetConfigOptions as GetConfigOptions$1, GetReplaneSnapshotOptions, Replane, Replane as Replane$1, ReplaneContext, ReplaneContext as ReplaneContext$1, ReplaneError, ReplaneErrorCode, ReplaneLogger, ReplaneLogger as ReplaneLogger$1, ReplaneOptions, ReplaneSnapshot, ReplaneSnapshot as ReplaneSnapshot$1, getReplaneSnapshot } from "@replanejs/sdk";
2
+ import { ConnectOptions, ConnectOptions as ConnectOptions$1, GetConfigOptions, GetConfigOptions as GetConfigOptions$1, GetReplaneSnapshotOptions, Replane, Replane as Replane$1, ReplaneContext, ReplaneError, ReplaneErrorCode, ReplaneLogger, ReplaneOptions, ReplaneOptions as ReplaneOptions$1, ReplaneSnapshot, getReplaneSnapshot } from "@replanejs/sdk";
3
3
  import { ReactNode } from "react";
4
4
 
5
5
  //#region src/types.d.ts
6
6
  type UntypedReplaneConfig = Record<string, unknown>;
7
- /**
8
- * Combined options for ReplaneProvider.
9
- * Includes both constructor options (context, logger, defaults) and connection options.
10
- */
11
- interface ReplaneProviderOptions<T extends object = UntypedReplaneConfig> {
12
- /**
13
- * Base URL of the Replane instance (no trailing slash).
14
- * @example "https://app.replane.dev"
15
- */
16
- baseUrl: string;
17
- /**
18
- * Project SDK key for authorization.
19
- * @example "rp_XXXXXXXXX"
20
- */
21
- sdkKey: string;
22
- /**
23
- * Default context for all config evaluations.
24
- * Can be overridden per-request in `client.get()`.
25
- */
26
- context?: ReplaneContext$1;
27
- /**
28
- * Optional logger (defaults to console).
29
- */
30
- logger?: ReplaneLogger$1;
31
- /**
32
- * Default values to use before connection is established.
33
- */
34
- defaults?: { [K in keyof T]?: T[K] };
35
- /**
36
- * Optional timeout in ms for the initial connection.
37
- * @default 5000
38
- */
39
- connectTimeoutMs?: number;
40
- /**
41
- * Delay between retries in ms.
42
- * @default 200
43
- */
44
- retryDelayMs?: number;
45
- /**
46
- * Optional timeout in ms for individual requests.
47
- * @default 2000
48
- */
49
- requestTimeoutMs?: number;
50
- /**
51
- * Timeout in ms for SSE connection inactivity.
52
- * @default 30000
53
- */
54
- inactivityTimeoutMs?: number;
55
- /**
56
- * Custom fetch implementation (useful for tests / polyfills).
57
- */
58
- fetchFn?: typeof fetch;
59
- /**
60
- * Agent identifier sent in User-Agent header.
61
- */
62
- agent?: string;
63
- }
64
7
  /**
65
8
  * Props for ReplaneProvider when using a pre-created client.
66
9
  */
@@ -72,17 +15,13 @@ interface ReplaneProviderWithClientProps<T extends object = UntypedReplaneConfig
72
15
  /**
73
16
  * Props for ReplaneProvider when letting it manage the client internally.
74
17
  */
75
- interface ReplaneProviderWithOptionsProps<T extends object = UntypedReplaneConfig> {
76
- /** Options to create or restore the Replane client */
77
- options: ReplaneProviderOptions<T>;
18
+ interface ReplaneProviderWithOptionsProps<T extends object = UntypedReplaneConfig> extends ReplaneOptions$1<T> {
78
19
  children: ReactNode;
79
20
  /**
80
- * Optional snapshot from server-side rendering.
81
- * When provided, the client will be restored from the snapshot synchronously
82
- * instead of fetching configs from the server.
83
- * The `options` will be used for live updates connection if provided.
21
+ * Connection options for connecting to the Replane server.
22
+ * Pass null to explicitly skip connection (client will use defaults/snapshot only).
84
23
  */
85
- snapshot?: ReplaneSnapshot$1<T>;
24
+ connection: ConnectOptions$1 | null;
86
25
  /**
87
26
  * Optional loading component to show while the client is initializing.
88
27
  * If not provided and suspense is false/undefined, children will not render until ready.
@@ -96,11 +35,17 @@ interface ReplaneProviderWithOptionsProps<T extends object = UntypedReplaneConfi
96
35
  * @default false
97
36
  */
98
37
  suspense?: boolean;
38
+ /**
39
+ * If true, the client will be connected asynchronously. Make sure to provide defaults or snapshot.
40
+ * @default false
41
+ */
42
+ async?: boolean;
99
43
  }
100
44
  type ReplaneProviderProps<T extends object = UntypedReplaneConfig> = ReplaneProviderWithClientProps<T> | ReplaneProviderWithOptionsProps<T>;
101
45
  /**
102
46
  * Type guard to check if props contain a pre-created client.
103
47
  */
48
+
104
49
  //#endregion
105
50
  //#region src/provider.d.ts
106
51
  /**
@@ -208,10 +153,10 @@ declare function createConfigHook<TConfigs extends object>(): <K extends keyof T
208
153
  //#endregion
209
154
  //#region src/useReplaneClient.d.ts
210
155
  /**
211
- * Clear the suspense cache for a specific options configuration.
156
+ * Clear the suspense cache for a specific connection configuration.
212
157
  * Useful for testing or when you need to force re-initialization.
213
158
  */
214
- declare function clearSuspenseCache<T extends object>(options?: ReplaneProviderOptions<T>): void;
159
+ declare function clearSuspenseCache(connection?: ConnectOptions$1): void;
215
160
  //#endregion
216
- export { type ConnectOptions, type GetConfigOptions, type GetReplaneSnapshotOptions, Replane, type ReplaneContext, ReplaneError, ReplaneErrorCode, type ReplaneLogger, type ReplaneOptions, ReplaneProvider, type ReplaneProviderOptions, type ReplaneProviderProps, type ReplaneProviderWithClientProps, type ReplaneProviderWithOptionsProps, type ReplaneSnapshot, clearSuspenseCache, createConfigHook, createReplaneHook, getReplaneSnapshot, useConfig, useReplane };
161
+ export { type ConnectOptions, type GetConfigOptions, type GetReplaneSnapshotOptions, Replane, type ReplaneContext, ReplaneError, ReplaneErrorCode, type ReplaneLogger, type ReplaneOptions, ReplaneProvider, type ReplaneProviderProps, type ReplaneProviderWithClientProps, type ReplaneProviderWithOptionsProps, type ReplaneSnapshot, clearSuspenseCache, createConfigHook, createReplaneHook, getReplaneSnapshot, useConfig, useReplane };
217
162
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/provider.tsx","../src/hooks.ts","../src/useReplaneClient.ts"],"sourcesContent":[],"mappings":";;;;;KAGY,oBAAA,GAAuB;AAUnC;;;;AAmBW,UAnBM,sBAmBN,CAAA,UAAA,MAAA,GAnBgD,oBAmBhD,CAAA,CAAA;EAAa;;;;EA4BA,OAAA,EAAA,MAAA;EAUP;;;;EAEE,MAAT,EAAA,MAAA;EAAO;AACI;AAMrB;;EAAgD,OAAoB,CAAA,EAnDxD,gBAmDwD;EAAoB;;;EAGnE,MAOQ,CAAA,EAzDlB,eAyDkB;EAAC;;AAMV;EAUR,QAAA,CAAA,EAAA,QAAoB,MArEL,CAqEK,IArEA,CAqEA,CArEE,CAqEF,CAAA,EAAA;EAAwC;;;;EAErC,gBAAA,CAAA,EAAA,MAAA;;;;ACqEnC;EAA+B,YAAA,CAAA,EAAA,MAAA;EAAA;;;AAAiD;;;;ACzKhF;;EAA0B,mBAAoB,CAAA,EAAA,MAAA;EAAoB;;AAAY;EAQ9D,OAAA,CAAA,EAAA,OF6CG,KE7CM;EAAA;;;EAA4C,KAAM,CAAA,EAAA,MAAA;AAAC;AAqC5E;;;AACqC,UFiBpB,8BEjBoB,CAAA,UAAA,MAAA,GFiB8B,oBEjB9B,CAAA,CAAA;EAAO;EAuB5B,MAAA,EFJN,SEIM,CFJE,CEIF,CAAA;EAAgB,QAAA,EFHpB,SEGoB;;;;;AAGlB,UFAG,+BEAH,CAAA,UAAA,MAAA,GFAsD,oBEAtD,CAAA,CAAA;EAAgB;EACjB,OAAC,EFCH,sBEDG,CFCoB,CEDpB,CAAA;EAAC,QAAA,EFEH,SEFG;;;;ACyEf;;;EAAuF,QAAxB,CAAA,EHhElD,iBGgEkD,CHhElC,CGgEkC,CAAA;EAAsB;;;;;WH1D1E;;;;;;;;;KAUC,wCAAwC,wBAChD,+BAA+B,KAC/B,gCAAgC;;;;;;;;;;AAxGpC;AAUA;;;;;;;;;AA+CwB;AAUxB;;;;;;AAGqB;AAMrB;;;;;;;;;AAgBoB;AAUpB;;;;;;;AAEmC;;;;ACqEnC;;;;;AAAgF;;;;ACzKhF;;;;;AAA8E,iBDyK9D,eCzK8D,CAAA,UAAA,MAAA,CAAA,CAAA,KAAA,EDyKrB,oBCzKqB,CDyKA,CCzKA,CAAA,CAAA,EDyKE,kBAAA,CAAA,GAAA,CAAA,OCzKF;AAQ9E;;;iBARgB,8BAA8B,yBAAyB,UAAQ;iBAQ/D,qCAAqC,mBAAiB,KAAK;;AFZ3E;AAUA;;;;;;;;;AA+CwB;AAUxB;;;;;;AAGqB,iBErBL,iBFqBK,CAAA,iBAAA,MAAA,CAAA,CAAA,CAAA,EAAA,GAAA,GEpBgB,SFoBhB,CEpBwB,QFoBxB,CAAA;AAMrB;;;;;;;;;AAgBoB;AAUpB;;;;;;;AAEmC;iBE/BnB,8DACiC,gBACvC,aACI,mBAAiB,SAAS,QACnC,SAAS;;;;;;;;AFSe,iBGgEb,kBHhEa,CAAA,UAAA,MAAA,CAAA,CAAA,OAAA,CAAA,EGgEkC,sBHhElC,CGgEyD,CHhEzD,CAAA,CAAA,EAAA,IAAA"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/provider.tsx","../src/hooks.ts","../src/useReplaneClient.ts"],"sourcesContent":[],"mappings":";;;;;KAGY,oBAAA,GAAuB;AASnC;;;AAEkB,UAFD,8BAEC,CAAA,UAAA,MAAA,GAFiD,oBAEjD,CAAA,CAAA;EAAC;EAAF,MACL,EADF,SACE,CADM,CACN,CAAA;EAAS,QAAA,EAAT,SAAS;AAMrB;;;;AAGY,UAHK,+BAGL,CAAA,UAAA,MAAA,GAFS,oBAET,CAAA,SADF,gBACE,CADa,CACb,CAAA,CAAA;EAAS,QAKP,EALF,SAKE;EAAc;;AANJ;AA2BxB;EAAgC,UAAA,EArBlB,gBAqBkB,GAAA,IAAA;EAAA;;;;;EAEG,MAAA,CAAA,EAjBxB,SAiBwB;;;;AC+GnC;;;EAA+E,QAAtB,CAAA,EAAA,OAAA;EAAoB;AAAG;;;;AC5JhF;AAA0B,KF2Cd,oBE3Cc,CAAA,UAAA,MAAA,GF2C0B,oBE3C1B,CAAA,GF4CtB,8BE5CsB,CF4CS,CE5CT,CAAA,GF6CtB,+BE7CsB,CF6CU,CE7CV,CAAA;;;;;;;;;;;AFJ1B;AASA;;;;;;AAGqB;AAMrB;;;;;;;;AAEwB;AA2BxB;;;;;;;AAEmC;;;;AC+GnC;;;;;AAAgF;;;;AC5JhF;;;;;AAA8E;AAQ9E;;;;;AAA4E;AAqC5E;;;;AAC4C,iBD8G5B,eC9G4B,CAAA,UAAA,MAAA,CAAA,CAAA,KAAA,ED8Ga,oBC9Gb,CD8GkC,CC9GlC,CAAA,CAAA,ED8GoC,kBAAA,CAAA,GAAA,CAAA,OC9GpC;AAuB5C;;;iBArEgB,8BAA8B,yBAAyB,UAAQ;iBAQ/D,qCAAqC,mBAAiB,KAAK;;AFZ3E;AASA;;;;;;AAGqB;AAMrB;;;;;;;;AAEwB;AA2BZ,iBEEI,iBFFgB,CAAA,iBAAA,MAAA,CAAA,CAAA,CAAA,EAAA,GAAA,GEGK,SFHL,CEGa,QFHb,CAAA;;;;;;;AAEG;;;;AC+GnC;;;;;AAAgF;;;iBCvFhE,8DACiC,gBACvC,aACI,mBAAiB,SAAS,QACnC,SAAS;AAzEd;;;;;;;AF6CI,iBGmGY,kBAAA,CHnGZ,UAAA,CAAA,EGmG4C,gBHnG5C,CAAA,EAAA,IAAA"}
package/dist/index.d.ts CHANGED
@@ -1,66 +1,9 @@
1
1
  import { ReactNode } from "react";
2
- import { ConnectOptions, GetConfigOptions, GetConfigOptions as GetConfigOptions$1, GetReplaneSnapshotOptions, Replane, Replane as Replane$1, ReplaneContext, ReplaneContext as ReplaneContext$1, ReplaneError, ReplaneErrorCode, ReplaneLogger, ReplaneLogger as ReplaneLogger$1, ReplaneOptions, ReplaneSnapshot, ReplaneSnapshot as ReplaneSnapshot$1, getReplaneSnapshot } from "@replanejs/sdk";
2
+ import { ConnectOptions, ConnectOptions as ConnectOptions$1, GetConfigOptions, GetConfigOptions as GetConfigOptions$1, GetReplaneSnapshotOptions, Replane, Replane as Replane$1, ReplaneContext, ReplaneError, ReplaneErrorCode, ReplaneLogger, ReplaneOptions, ReplaneOptions as ReplaneOptions$1, ReplaneSnapshot, getReplaneSnapshot } from "@replanejs/sdk";
3
3
  import * as react_jsx_runtime0 from "react/jsx-runtime";
4
4
 
5
5
  //#region src/types.d.ts
6
6
  type UntypedReplaneConfig = Record<string, unknown>;
7
- /**
8
- * Combined options for ReplaneProvider.
9
- * Includes both constructor options (context, logger, defaults) and connection options.
10
- */
11
- interface ReplaneProviderOptions<T extends object = UntypedReplaneConfig> {
12
- /**
13
- * Base URL of the Replane instance (no trailing slash).
14
- * @example "https://app.replane.dev"
15
- */
16
- baseUrl: string;
17
- /**
18
- * Project SDK key for authorization.
19
- * @example "rp_XXXXXXXXX"
20
- */
21
- sdkKey: string;
22
- /**
23
- * Default context for all config evaluations.
24
- * Can be overridden per-request in `client.get()`.
25
- */
26
- context?: ReplaneContext$1;
27
- /**
28
- * Optional logger (defaults to console).
29
- */
30
- logger?: ReplaneLogger$1;
31
- /**
32
- * Default values to use before connection is established.
33
- */
34
- defaults?: { [K in keyof T]?: T[K] };
35
- /**
36
- * Optional timeout in ms for the initial connection.
37
- * @default 5000
38
- */
39
- connectTimeoutMs?: number;
40
- /**
41
- * Delay between retries in ms.
42
- * @default 200
43
- */
44
- retryDelayMs?: number;
45
- /**
46
- * Optional timeout in ms for individual requests.
47
- * @default 2000
48
- */
49
- requestTimeoutMs?: number;
50
- /**
51
- * Timeout in ms for SSE connection inactivity.
52
- * @default 30000
53
- */
54
- inactivityTimeoutMs?: number;
55
- /**
56
- * Custom fetch implementation (useful for tests / polyfills).
57
- */
58
- fetchFn?: typeof fetch;
59
- /**
60
- * Agent identifier sent in User-Agent header.
61
- */
62
- agent?: string;
63
- }
64
7
  /**
65
8
  * Props for ReplaneProvider when using a pre-created client.
66
9
  */
@@ -72,17 +15,13 @@ interface ReplaneProviderWithClientProps<T extends object = UntypedReplaneConfig
72
15
  /**
73
16
  * Props for ReplaneProvider when letting it manage the client internally.
74
17
  */
75
- interface ReplaneProviderWithOptionsProps<T extends object = UntypedReplaneConfig> {
76
- /** Options to create or restore the Replane client */
77
- options: ReplaneProviderOptions<T>;
18
+ interface ReplaneProviderWithOptionsProps<T extends object = UntypedReplaneConfig> extends ReplaneOptions$1<T> {
78
19
  children: ReactNode;
79
20
  /**
80
- * Optional snapshot from server-side rendering.
81
- * When provided, the client will be restored from the snapshot synchronously
82
- * instead of fetching configs from the server.
83
- * The `options` will be used for live updates connection if provided.
21
+ * Connection options for connecting to the Replane server.
22
+ * Pass null to explicitly skip connection (client will use defaults/snapshot only).
84
23
  */
85
- snapshot?: ReplaneSnapshot$1<T>;
24
+ connection: ConnectOptions$1 | null;
86
25
  /**
87
26
  * Optional loading component to show while the client is initializing.
88
27
  * If not provided and suspense is false/undefined, children will not render until ready.
@@ -96,11 +35,17 @@ interface ReplaneProviderWithOptionsProps<T extends object = UntypedReplaneConfi
96
35
  * @default false
97
36
  */
98
37
  suspense?: boolean;
38
+ /**
39
+ * If true, the client will be connected asynchronously. Make sure to provide defaults or snapshot.
40
+ * @default false
41
+ */
42
+ async?: boolean;
99
43
  }
100
44
  type ReplaneProviderProps<T extends object = UntypedReplaneConfig> = ReplaneProviderWithClientProps<T> | ReplaneProviderWithOptionsProps<T>;
101
45
  /**
102
46
  * Type guard to check if props contain a pre-created client.
103
47
  */
48
+
104
49
  //#endregion
105
50
  //#region src/provider.d.ts
106
51
  /**
@@ -208,10 +153,10 @@ declare function createConfigHook<TConfigs extends object>(): <K extends keyof T
208
153
  //#endregion
209
154
  //#region src/useReplaneClient.d.ts
210
155
  /**
211
- * Clear the suspense cache for a specific options configuration.
156
+ * Clear the suspense cache for a specific connection configuration.
212
157
  * Useful for testing or when you need to force re-initialization.
213
158
  */
214
- declare function clearSuspenseCache<T extends object>(options?: ReplaneProviderOptions<T>): void;
159
+ declare function clearSuspenseCache(connection?: ConnectOptions$1): void;
215
160
  //#endregion
216
- export { type ConnectOptions, type GetConfigOptions, type GetReplaneSnapshotOptions, Replane, type ReplaneContext, ReplaneError, ReplaneErrorCode, type ReplaneLogger, type ReplaneOptions, ReplaneProvider, type ReplaneProviderOptions, type ReplaneProviderProps, type ReplaneProviderWithClientProps, type ReplaneProviderWithOptionsProps, type ReplaneSnapshot, clearSuspenseCache, createConfigHook, createReplaneHook, getReplaneSnapshot, useConfig, useReplane };
161
+ export { type ConnectOptions, type GetConfigOptions, type GetReplaneSnapshotOptions, Replane, type ReplaneContext, ReplaneError, ReplaneErrorCode, type ReplaneLogger, type ReplaneOptions, ReplaneProvider, type ReplaneProviderProps, type ReplaneProviderWithClientProps, type ReplaneProviderWithOptionsProps, type ReplaneSnapshot, clearSuspenseCache, createConfigHook, createReplaneHook, getReplaneSnapshot, useConfig, useReplane };
217
162
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/provider.tsx","../src/hooks.ts","../src/useReplaneClient.ts"],"sourcesContent":[],"mappings":";;;;;KAGY,oBAAA,GAAuB;AAUnC;;;;AAmBW,UAnBM,sBAmBN,CAAA,UAAA,MAAA,GAnBgD,oBAmBhD,CAAA,CAAA;EAAa;;;;EA4BA,OAAA,EAAA,MAAA;EAUP;;;;EAEE,MAAT,EAAA,MAAA;EAAO;AACI;AAMrB;;EAAgD,OAAoB,CAAA,EAnDxD,gBAmDwD;EAAoB;;;EAGnE,MAOQ,CAAA,EAzDlB,eAyDkB;EAAC;;AAMV;EAUR,QAAA,CAAA,EAAA,QAAoB,MArEL,CAqEK,IArEA,CAqEA,CArEE,CAqEF,CAAA,EAAA;EAAwC;;;;EAErC,gBAAA,CAAA,EAAA,MAAA;;;;ACqEnC;EAA+B,YAAA,CAAA,EAAA,MAAA;EAAA;;;AAAiD;;;;ACzKhF;;EAA0B,mBAAoB,CAAA,EAAA,MAAA;EAAoB;;AAAY;EAQ9D,OAAA,CAAA,EAAA,OF6CG,KE7CM;EAAA;;;EAA4C,KAAM,CAAA,EAAA,MAAA;AAAC;AAqC5E;;;AACqC,UFiBpB,8BEjBoB,CAAA,UAAA,MAAA,GFiB8B,oBEjB9B,CAAA,CAAA;EAAO;EAuB5B,MAAA,EFJN,SEIM,CFJE,CEIF,CAAA;EAAgB,QAAA,EFHpB,SEGoB;;;;;AAGlB,UFAG,+BEAH,CAAA,UAAA,MAAA,GFAsD,oBEAtD,CAAA,CAAA;EAAgB;EACjB,OAAC,EFCH,sBEDG,CFCoB,CEDpB,CAAA;EAAC,QAAA,EFEH,SEFG;;;;ACyEf;;;EAAuF,QAAxB,CAAA,EHhElD,iBGgEkD,CHhElC,CGgEkC,CAAA;EAAsB;;;;;WH1D1E;;;;;;;;;KAUC,wCAAwC,wBAChD,+BAA+B,KAC/B,gCAAgC;;;;;;;;;;AAxGpC;AAUA;;;;;;;;;AA+CwB;AAUxB;;;;;;AAGqB;AAMrB;;;;;;;;;AAgBoB;AAUpB;;;;;;;AAEmC;;;;ACqEnC;;;;;AAAgF;;;;ACzKhF;;;;;AAA8E,iBDyK9D,eCzK8D,CAAA,UAAA,MAAA,CAAA,CAAA,KAAA,EDyKrB,oBCzKqB,CDyKA,CCzKA,CAAA,CAAA,EDyKE,kBAAA,CAAA,GAAA,CAAA,OCzKF;AAQ9E;;;iBARgB,8BAA8B,yBAAyB,UAAQ;iBAQ/D,qCAAqC,mBAAiB,KAAK;;AFZ3E;AAUA;;;;;;;;;AA+CwB;AAUxB;;;;;;AAGqB,iBErBL,iBFqBK,CAAA,iBAAA,MAAA,CAAA,CAAA,CAAA,EAAA,GAAA,GEpBgB,SFoBhB,CEpBwB,QFoBxB,CAAA;AAMrB;;;;;;;;;AAgBoB;AAUpB;;;;;;;AAEmC;iBE/BnB,8DACiC,gBACvC,aACI,mBAAiB,SAAS,QACnC,SAAS;;;;;;;;AFSe,iBGgEb,kBHhEa,CAAA,UAAA,MAAA,CAAA,CAAA,OAAA,CAAA,EGgEkC,sBHhElC,CGgEyD,CHhEzD,CAAA,CAAA,EAAA,IAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/provider.tsx","../src/hooks.ts","../src/useReplaneClient.ts"],"sourcesContent":[],"mappings":";;;;;KAGY,oBAAA,GAAuB;AASnC;;;AAEkB,UAFD,8BAEC,CAAA,UAAA,MAAA,GAFiD,oBAEjD,CAAA,CAAA;EAAC;EAAF,MACL,EADF,SACE,CADM,CACN,CAAA;EAAS,QAAA,EAAT,SAAS;AAMrB;;;;AAGY,UAHK,+BAGL,CAAA,UAAA,MAAA,GAFS,oBAET,CAAA,SADF,gBACE,CADa,CACb,CAAA,CAAA;EAAS,QAKP,EALF,SAKE;EAAc;;AANJ;AA2BxB;EAAgC,UAAA,EArBlB,gBAqBkB,GAAA,IAAA;EAAA;;;;;EAEG,MAAA,CAAA,EAjBxB,SAiBwB;;;;AC+GnC;;;EAA+E,QAAtB,CAAA,EAAA,OAAA;EAAoB;AAAG;;;;AC5JhF;AAA0B,KF2Cd,oBE3Cc,CAAA,UAAA,MAAA,GF2C0B,oBE3C1B,CAAA,GF4CtB,8BE5CsB,CF4CS,CE5CT,CAAA,GF6CtB,+BE7CsB,CF6CU,CE7CV,CAAA;;;;;;;;;;;AFJ1B;AASA;;;;;;AAGqB;AAMrB;;;;;;;;AAEwB;AA2BxB;;;;;;;AAEmC;;;;AC+GnC;;;;;AAAgF;;;;AC5JhF;;;;;AAA8E;AAQ9E;;;;;AAA4E;AAqC5E;;;;AAC4C,iBD8G5B,eC9G4B,CAAA,UAAA,MAAA,CAAA,CAAA,KAAA,ED8Ga,oBC9Gb,CD8GkC,CC9GlC,CAAA,CAAA,ED8GoC,kBAAA,CAAA,GAAA,CAAA,OC9GpC;AAuB5C;;;iBArEgB,8BAA8B,yBAAyB,UAAQ;iBAQ/D,qCAAqC,mBAAiB,KAAK;;AFZ3E;AASA;;;;;;AAGqB;AAMrB;;;;;;;;AAEwB;AA2BZ,iBEEI,iBFFgB,CAAA,iBAAA,MAAA,CAAA,CAAA,CAAA,EAAA,GAAA,GEGK,SFHL,CEGa,QFHb,CAAA;;;;;;;AAEG;;;;AC+GnC;;;;;AAAgF;;;iBCvFhE,8DACiC,gBACvC,aACI,mBAAiB,SAAS,QACnC,SAAS;AAzEd;;;;;;;AF6CI,iBGmGY,kBAAA,CHnGZ,UAAA,CAAA,EGmG4C,gBHnG5C,CAAA,EAAA,IAAA"}
package/dist/index.js CHANGED
@@ -6,12 +6,7 @@ import { Replane, Replane as Replane$1, ReplaneError, ReplaneErrorCode, getRepla
6
6
  import { Fragment, jsx } from "react/jsx-runtime";
7
7
 
8
8
  //#region src/context.ts
9
- const ReplaneContext$1 = createContext(null);
10
-
11
- //#endregion
12
- //#region src/version.ts
13
- const VERSION = "0.9.0";
14
- const DEFAULT_AGENT = `replane-js-react/${VERSION}`;
9
+ const ReplaneContext = createContext(null);
15
10
 
16
11
  //#endregion
17
12
  //#region src/useReplaneClient.ts
@@ -22,29 +17,21 @@ function getCacheKey(options) {
22
17
  /**
23
18
  * Creates a Replane client and connects it.
24
19
  */
25
- async function createAndConnectClient(options) {
20
+ async function createAndConnectClient(options, connection) {
26
21
  const client = new Replane$1({
27
22
  logger: options.logger,
28
23
  context: options.context,
29
24
  defaults: options.defaults
30
25
  });
31
- await client.connect({
32
- baseUrl: options.baseUrl,
33
- sdkKey: options.sdkKey,
34
- connectTimeoutMs: options.connectTimeoutMs,
35
- retryDelayMs: options.retryDelayMs,
36
- requestTimeoutMs: options.requestTimeoutMs,
37
- inactivityTimeoutMs: options.inactivityTimeoutMs,
38
- fetchFn: options.fetchFn,
39
- agent: options.agent ?? DEFAULT_AGENT
40
- });
26
+ if (!connection) return client;
27
+ await client.connect(connection);
41
28
  return client;
42
29
  }
43
30
  /**
44
31
  * Hook to manage Replane client creation internally.
45
32
  * Handles loading state and cleanup.
46
33
  */
47
- function useReplaneClientInternal(options) {
34
+ function useReplaneClientInternal(options, originalConnection) {
48
35
  const [state, setState] = useState({
49
36
  status: "loading",
50
37
  client: null,
@@ -52,11 +39,13 @@ function useReplaneClientInternal(options) {
52
39
  });
53
40
  const clientRef = useRef(null);
54
41
  const optionsRef = useRef(options);
42
+ const connectionJson = JSON.stringify(originalConnection);
55
43
  useEffect(() => {
44
+ const connection = JSON.parse(connectionJson);
56
45
  let cancelled = false;
57
46
  async function initClient() {
58
47
  try {
59
- const client = await createAndConnectClient(optionsRef.current);
48
+ const client = await createAndConnectClient(optionsRef.current, connection);
60
49
  if (cancelled) {
61
50
  client.disconnect();
62
51
  return;
@@ -85,22 +74,22 @@ function useReplaneClientInternal(options) {
85
74
  clientRef.current = null;
86
75
  }
87
76
  };
88
- }, []);
77
+ }, [connectionJson]);
89
78
  return state;
90
79
  }
91
80
  /**
92
81
  * Hook for Suspense-based client creation.
93
82
  * Throws a promise while loading, throws error on failure.
94
83
  */
95
- function useReplaneClientSuspense(options) {
96
- const cacheKey = getCacheKey(options);
84
+ function useReplaneClientSuspense(options, connection) {
85
+ const cacheKey = getCacheKey(connection);
97
86
  const cached = suspenseCache.get(cacheKey);
98
87
  if (cached) {
99
88
  if (cached.error) throw cached.error;
100
89
  if (cached.result) return cached.result;
101
90
  throw cached.promise;
102
91
  }
103
- const promise = createAndConnectClient(options).then((client) => {
92
+ const promise = createAndConnectClient(options, connection).then((client) => {
104
93
  const entry = suspenseCache.get(cacheKey);
105
94
  if (entry) entry.result = client;
106
95
  return client;
@@ -113,11 +102,11 @@ function useReplaneClientSuspense(options) {
113
102
  throw promise;
114
103
  }
115
104
  /**
116
- * Clear the suspense cache for a specific options configuration.
105
+ * Clear the suspense cache for a specific connection configuration.
117
106
  * Useful for testing or when you need to force re-initialization.
118
107
  */
119
- function clearSuspenseCache(options) {
120
- if (options) suspenseCache.delete(getCacheKey(options));
108
+ function clearSuspenseCache(connection) {
109
+ if (connection) suspenseCache.delete(getCacheKey(connection));
121
110
  else suspenseCache.clear();
122
111
  }
123
112
 
@@ -127,9 +116,14 @@ function clearSuspenseCache(options) {
127
116
  * Type guard to check if props contain a pre-created client.
128
117
  */
129
118
  function hasClient(props) {
130
- return "client" in props && props.client !== void 0;
119
+ return "client" in props && !!props.client;
131
120
  }
132
121
 
122
+ //#endregion
123
+ //#region src/version.ts
124
+ const VERSION = "0.9.2";
125
+ const DEFAULT_AGENT = `replane-js-react/${VERSION}`;
126
+
133
127
  //#endregion
134
128
  //#region src/provider.tsx
135
129
  /**
@@ -137,52 +131,31 @@ function hasClient(props) {
137
131
  */
138
132
  function ReplaneProviderWithClient({ client, children }) {
139
133
  const value = useMemo(() => ({ replane: client }), [client]);
140
- return /* @__PURE__ */ jsx(ReplaneContext$1.Provider, {
134
+ return /* @__PURE__ */ jsx(ReplaneContext.Provider, {
141
135
  value,
142
136
  children
143
137
  });
144
138
  }
145
139
  /**
146
- * Internal provider component for restoring client from snapshot.
140
+ * Internal provider component for creating a Replane client asynchronously.
147
141
  * Creates a Replane client synchronously and connects in background.
148
142
  */
149
- function ReplaneProviderWithSnapshot({ options, snapshot, children }) {
143
+ function AsyncReplaneProvider({ children, connection,...options }) {
150
144
  const replaneRef = useRef(void 0);
151
- if (!replaneRef.current) replaneRef.current = new Replane$1({
152
- snapshot,
153
- logger: options.logger,
154
- context: options.context,
155
- defaults: options.defaults
156
- });
145
+ if (!replaneRef.current) replaneRef.current = new Replane$1(options);
146
+ const connectionJson = connection ? JSON.stringify(connection) : void 0;
157
147
  useEffect(() => {
158
- replaneRef.current.connect({
159
- baseUrl: options.baseUrl,
160
- sdkKey: options.sdkKey,
161
- connectTimeoutMs: options.connectTimeoutMs,
162
- retryDelayMs: options.retryDelayMs,
163
- requestTimeoutMs: options.requestTimeoutMs,
164
- inactivityTimeoutMs: options.inactivityTimeoutMs,
165
- fetchFn: options.fetchFn,
166
- agent: options.agent ?? DEFAULT_AGENT
167
- }).catch((err) => {
148
+ const parsedConnection = connectionJson ? JSON.parse(connectionJson) : void 0;
149
+ if (!parsedConnection) return;
150
+ replaneRef.current.connect(parsedConnection).catch((err) => {
168
151
  (options.logger ?? console)?.error("Failed to connect Replane client", err);
169
152
  });
170
153
  return () => {
171
154
  replaneRef.current.disconnect();
172
155
  };
173
- }, [
174
- options.agent,
175
- options.baseUrl,
176
- options.connectTimeoutMs,
177
- options.fetchFn,
178
- options.inactivityTimeoutMs,
179
- options.logger,
180
- options.requestTimeoutMs,
181
- options.retryDelayMs,
182
- options.sdkKey
183
- ]);
156
+ }, [connectionJson, options.logger]);
184
157
  const value = useMemo(() => ({ replane: replaneRef.current }), []);
185
- return /* @__PURE__ */ jsx(ReplaneContext$1.Provider, {
158
+ return /* @__PURE__ */ jsx(ReplaneContext.Provider, {
186
159
  value,
187
160
  children
188
161
  });
@@ -191,12 +164,13 @@ function ReplaneProviderWithSnapshot({ options, snapshot, children }) {
191
164
  * Internal provider component for options-based client creation (non-suspense).
192
165
  * Throws errors during rendering so they can be caught by Error Boundaries.
193
166
  */
194
- function ReplaneProviderWithOptions({ options, children, loader }) {
195
- const state = useReplaneClientInternal(options);
167
+ function LoaderReplaneProvider({ children, loader, connection,...options }) {
168
+ if (!connection) throw new Error("Connection is required when using Loader");
169
+ const state = useReplaneClientInternal(options, connection);
196
170
  if (state.status === "loading") return /* @__PURE__ */ jsx(Fragment, { children: loader ?? null });
197
171
  if (state.status === "error") throw state.error;
198
172
  const value = { replane: state.client };
199
- return /* @__PURE__ */ jsx(ReplaneContext$1.Provider, {
173
+ return /* @__PURE__ */ jsx(ReplaneContext.Provider, {
200
174
  value,
201
175
  children
202
176
  });
@@ -204,10 +178,11 @@ function ReplaneProviderWithOptions({ options, children, loader }) {
204
178
  /**
205
179
  * Internal provider component for options-based client creation with Suspense.
206
180
  */
207
- function ReplaneProviderWithSuspense({ options, children }) {
208
- const client = useReplaneClientSuspense(options);
181
+ function SuspenseReplaneProvider({ connection, children,...options }) {
182
+ if (!connection) throw new Error("Connection is required when using Suspense");
183
+ const client = useReplaneClientSuspense(options, connection);
209
184
  const value = useMemo(() => ({ replane: client }), [client]);
210
- return /* @__PURE__ */ jsx(ReplaneContext$1.Provider, {
185
+ return /* @__PURE__ */ jsx(ReplaneContext.Provider, {
211
186
  value,
212
187
  children
213
188
  });
@@ -270,19 +245,27 @@ function ReplaneProviderWithSuspense({ options, children }) {
270
245
  * allowing them to be caught by React Error Boundaries.
271
246
  */
272
247
  function ReplaneProvider(props) {
248
+ const originalConnection = props.connection;
249
+ const connection = useMemo(() => originalConnection ? {
250
+ ...originalConnection,
251
+ agent: originalConnection.agent ?? DEFAULT_AGENT
252
+ } : void 0, [originalConnection]);
273
253
  if (hasClient(props)) return /* @__PURE__ */ jsx(ReplaneProviderWithClient, { ...props });
274
- if (props.snapshot) return /* @__PURE__ */ jsx(ReplaneProviderWithSnapshot, {
254
+ if (props.snapshot || !connection || props.async) return /* @__PURE__ */ jsx(AsyncReplaneProvider, { ...props });
255
+ if (props.suspense) return /* @__PURE__ */ jsx(SuspenseReplaneProvider, {
256
+ ...props,
257
+ connection
258
+ });
259
+ return /* @__PURE__ */ jsx(LoaderReplaneProvider, {
275
260
  ...props,
276
- snapshot: props.snapshot
261
+ connection
277
262
  });
278
- if (props.suspense) return /* @__PURE__ */ jsx(ReplaneProviderWithSuspense, { ...props });
279
- return /* @__PURE__ */ jsx(ReplaneProviderWithOptions, { ...props });
280
263
  }
281
264
 
282
265
  //#endregion
283
266
  //#region src/hooks.ts
284
267
  function useReplane() {
285
- const context = useContext(ReplaneContext$1);
268
+ const context = useContext(ReplaneContext);
286
269
  if (!context) throw new Error("useReplane must be used within a ReplaneProvider");
287
270
  return context.replane;
288
271
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["ReplaneContext","options: ReplaneProviderOptions<T>","Replane","err: unknown","options?: ReplaneProviderOptions<T>","props: ReplaneProviderProps<T>","ReplaneContext","Replane","value: ReplaneContextValue<T>","props: ReplaneProviderProps<T>","ReplaneContext","name: string","options?: GetConfigOptions<T>","callback: () => void","name: K","options?: GetConfigOptions<TConfigs[K]>"],"sources":["../src/context.ts","../src/version.ts","../src/useReplaneClient.ts","../src/types.ts","../src/provider.tsx","../src/hooks.ts"],"sourcesContent":["\"use client\";\n\nimport { createContext } from \"react\";\nimport type { ReplaneContextValue } from \"./types\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const ReplaneContext = createContext<ReplaneContextValue<any> | null>(null);\n","// Auto-generated - do not edit manually\nexport const VERSION = \"0.9.0\";\nexport const DEFAULT_AGENT = `replane-js-react/${VERSION}`;\n","\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { Replane } from \"@replanejs/sdk\";\nimport { DEFAULT_AGENT } from \"./version\";\nimport type { ReplaneProviderOptions } from \"./types\";\n\ntype ClientState<T extends object> =\n | { status: \"loading\"; client: null; error: null }\n | { status: \"ready\"; client: Replane<T>; error: null }\n | { status: \"error\"; client: null; error: Error };\n\n// Cache for suspense promise tracking\nconst suspenseCache = new Map<\n string,\n {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n promise: Promise<Replane<any>>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n result?: Replane<any>;\n error?: Error;\n }\n>();\n\nfunction getCacheKey<T extends object>(options: ReplaneProviderOptions<T>): string {\n return `${options.baseUrl}:${options.sdkKey}`;\n}\n\n/**\n * Creates a Replane client and connects it.\n */\nasync function createAndConnectClient<T extends object>(\n options: ReplaneProviderOptions<T>\n): Promise<Replane<T>> {\n const client = new Replane<T>({\n logger: options.logger,\n context: options.context,\n defaults: options.defaults,\n });\n\n await client.connect({\n baseUrl: options.baseUrl,\n sdkKey: options.sdkKey,\n connectTimeoutMs: options.connectTimeoutMs,\n retryDelayMs: options.retryDelayMs,\n requestTimeoutMs: options.requestTimeoutMs,\n inactivityTimeoutMs: options.inactivityTimeoutMs,\n fetchFn: options.fetchFn,\n agent: options.agent ?? DEFAULT_AGENT,\n });\n\n return client;\n}\n\ntype ErrorConstructor = new (message: string, options?: { cause?: unknown }) => Error;\n\n/**\n * Hook to manage Replane client creation internally.\n * Handles loading state and cleanup.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function useReplaneClientInternal<T extends object = any>(\n options: ReplaneProviderOptions<T>\n): ClientState<T> {\n const [state, setState] = useState<ClientState<T>>({\n status: \"loading\",\n client: null,\n error: null,\n });\n const clientRef = useRef<Replane<T> | null>(null);\n const optionsRef = useRef(options);\n\n useEffect(() => {\n let cancelled = false;\n\n async function initClient() {\n try {\n const client = await createAndConnectClient<T>(optionsRef.current);\n if (cancelled) {\n client.disconnect();\n return;\n }\n clientRef.current = client;\n setState({ status: \"ready\", client, error: null });\n } catch (err) {\n if (cancelled) return;\n const error =\n err instanceof Error ? err : new (Error as ErrorConstructor)(String(err), { cause: err });\n setState({ status: \"error\", client: null, error });\n }\n }\n\n initClient();\n\n return () => {\n cancelled = true;\n if (clientRef.current) {\n clientRef.current.disconnect();\n clientRef.current = null;\n }\n };\n }, []);\n\n return state;\n}\n\n/**\n * Hook for Suspense-based client creation.\n * Throws a promise while loading, throws error on failure.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function useReplaneClientSuspense<T extends object = any>(\n options: ReplaneProviderOptions<T>\n): Replane<T> {\n const cacheKey = getCacheKey(options);\n const cached = suspenseCache.get(cacheKey);\n\n if (cached) {\n if (cached.error) {\n throw cached.error;\n }\n if (cached.result) {\n return cached.result as Replane<T>;\n }\n // Still loading, throw the promise\n throw cached.promise;\n }\n\n // First time - create the promise\n const promise = createAndConnectClient<T>(options)\n .then((client) => {\n const entry = suspenseCache.get(cacheKey);\n if (entry) {\n entry.result = client;\n }\n return client;\n })\n .catch((err: unknown) => {\n const entry = suspenseCache.get(cacheKey);\n if (entry) {\n entry.error = err instanceof Error ? err : new Error(String(err));\n }\n throw err;\n });\n\n suspenseCache.set(cacheKey, { promise });\n throw promise;\n}\n\n/**\n * Clear the suspense cache for a specific options configuration.\n * Useful for testing or when you need to force re-initialization.\n */\nexport function clearSuspenseCache<T extends object>(options?: ReplaneProviderOptions<T>): void {\n if (options) {\n suspenseCache.delete(getCacheKey(options));\n } else {\n suspenseCache.clear();\n }\n}\n","import type { Replane, ReplaneSnapshot, ReplaneContext, ReplaneLogger } from \"@replanejs/sdk\";\nimport type { ReactNode } from \"react\";\n\nexport type UntypedReplaneConfig = Record<string, unknown>;\n\nexport interface ReplaneContextValue<T extends object = UntypedReplaneConfig> {\n replane: Replane<T>;\n}\n\n/**\n * Combined options for ReplaneProvider.\n * Includes both constructor options (context, logger, defaults) and connection options.\n */\nexport interface ReplaneProviderOptions<T extends object = UntypedReplaneConfig> {\n /**\n * Base URL of the Replane instance (no trailing slash).\n * @example \"https://app.replane.dev\"\n */\n baseUrl: string;\n /**\n * Project SDK key for authorization.\n * @example \"rp_XXXXXXXXX\"\n */\n sdkKey: string;\n /**\n * Default context for all config evaluations.\n * Can be overridden per-request in `client.get()`.\n */\n context?: ReplaneContext;\n /**\n * Optional logger (defaults to console).\n */\n logger?: ReplaneLogger;\n /**\n * Default values to use before connection is established.\n */\n defaults?: { [K in keyof T]?: T[K] };\n /**\n * Optional timeout in ms for the initial connection.\n * @default 5000\n */\n connectTimeoutMs?: number;\n /**\n * Delay between retries in ms.\n * @default 200\n */\n retryDelayMs?: number;\n /**\n * Optional timeout in ms for individual requests.\n * @default 2000\n */\n requestTimeoutMs?: number;\n /**\n * Timeout in ms for SSE connection inactivity.\n * @default 30000\n */\n inactivityTimeoutMs?: number;\n /**\n * Custom fetch implementation (useful for tests / polyfills).\n */\n fetchFn?: typeof fetch;\n /**\n * Agent identifier sent in User-Agent header.\n */\n agent?: string;\n}\n\n/**\n * Props for ReplaneProvider when using a pre-created client.\n */\nexport interface ReplaneProviderWithClientProps<T extends object = UntypedReplaneConfig> {\n /** Pre-created Replane client instance */\n client: Replane<T>;\n children: ReactNode;\n}\n\n/**\n * Props for ReplaneProvider when letting it manage the client internally.\n */\nexport interface ReplaneProviderWithOptionsProps<T extends object = UntypedReplaneConfig> {\n /** Options to create or restore the Replane client */\n options: ReplaneProviderOptions<T>;\n children: ReactNode;\n /**\n * Optional snapshot from server-side rendering.\n * When provided, the client will be restored from the snapshot synchronously\n * instead of fetching configs from the server.\n * The `options` will be used for live updates connection if provided.\n */\n snapshot?: ReplaneSnapshot<T>;\n /**\n * Optional loading component to show while the client is initializing.\n * If not provided and suspense is false/undefined, children will not render until ready.\n * Ignored when snapshot is provided (restoration is synchronous).\n */\n loader?: ReactNode;\n /**\n * If true, uses React Suspense for loading state.\n * The provider will throw a promise that Suspense can catch.\n * Ignored when snapshot is provided (restoration is synchronous).\n * @default false\n */\n suspense?: boolean;\n}\n\nexport type ReplaneProviderProps<T extends object = UntypedReplaneConfig> =\n | ReplaneProviderWithClientProps<T>\n | ReplaneProviderWithOptionsProps<T>;\n\n/**\n * Type guard to check if props contain a pre-created client.\n */\nexport function hasClient<T extends object>(\n props: ReplaneProviderProps<T>\n): props is ReplaneProviderWithClientProps<T> {\n return \"client\" in props && props.client !== undefined;\n}\n\n/**\n * Type guard to check if props contain options (with or without snapshot).\n */\nexport function hasOptions<T extends object>(\n props: ReplaneProviderProps<T>\n): props is ReplaneProviderWithOptionsProps<T> {\n return \"options\" in props && props.options !== undefined;\n}\n","\"use client\";\n\nimport { useEffect, useMemo, useRef } from \"react\";\nimport { Replane } from \"@replanejs/sdk\";\nimport { ReplaneContext } from \"./context\";\nimport { useReplaneClientInternal, useReplaneClientSuspense } from \"./useReplaneClient\";\nimport type {\n ReplaneProviderProps,\n ReplaneProviderWithClientProps,\n ReplaneProviderWithOptionsProps,\n ReplaneContextValue,\n} from \"./types\";\nimport { hasClient } from \"./types\";\nimport { DEFAULT_AGENT } from \"./version\";\n\n/**\n * Internal provider component for pre-created client.\n */\nfunction ReplaneProviderWithClient<T extends object>({\n client,\n children,\n}: ReplaneProviderWithClientProps<T>) {\n const value = useMemo<ReplaneContextValue<T>>(() => ({ replane: client }), [client]);\n return <ReplaneContext.Provider value={value}>{children}</ReplaneContext.Provider>;\n}\n\n/**\n * Internal provider component for restoring client from snapshot.\n * Creates a Replane client synchronously and connects in background.\n */\nfunction ReplaneProviderWithSnapshot<T extends object>({\n options,\n snapshot,\n children,\n}: ReplaneProviderWithOptionsProps<T> & {\n snapshot: NonNullable<ReplaneProviderWithOptionsProps<T>[\"snapshot\"]>;\n}) {\n const replaneRef = useRef<Replane<T>>(undefined as unknown as Replane<T>);\n\n if (!replaneRef.current) {\n replaneRef.current = new Replane<T>({\n snapshot,\n logger: options.logger,\n context: options.context,\n defaults: options.defaults,\n });\n }\n\n useEffect(() => {\n replaneRef.current\n .connect({\n baseUrl: options.baseUrl,\n sdkKey: options.sdkKey,\n connectTimeoutMs: options.connectTimeoutMs,\n retryDelayMs: options.retryDelayMs,\n requestTimeoutMs: options.requestTimeoutMs,\n inactivityTimeoutMs: options.inactivityTimeoutMs,\n fetchFn: options.fetchFn,\n agent: options.agent ?? DEFAULT_AGENT,\n })\n .catch((err) => {\n (options.logger ?? console)?.error(\"Failed to connect Replane client\", err);\n });\n\n return () => {\n replaneRef.current.disconnect();\n };\n }, [\n options.agent,\n options.baseUrl,\n options.connectTimeoutMs,\n options.fetchFn,\n options.inactivityTimeoutMs,\n options.logger,\n options.requestTimeoutMs,\n options.retryDelayMs,\n options.sdkKey,\n ]);\n\n const value = useMemo<ReplaneContextValue<T>>(() => ({ replane: replaneRef.current }), []);\n return <ReplaneContext.Provider value={value}>{children}</ReplaneContext.Provider>;\n}\n\n/**\n * Internal provider component for options-based client creation (non-suspense).\n * Throws errors during rendering so they can be caught by Error Boundaries.\n */\nfunction ReplaneProviderWithOptions<T extends object>({\n options,\n children,\n loader,\n}: ReplaneProviderWithOptionsProps<T>) {\n const state = useReplaneClientInternal<T>(options);\n\n if (state.status === \"loading\") {\n return <>{loader ?? null}</>;\n }\n\n if (state.status === \"error\") {\n // Throw error during render so it can be caught by Error Boundary\n throw state.error;\n }\n\n const value: ReplaneContextValue<T> = { replane: state.client };\n return <ReplaneContext.Provider value={value}>{children}</ReplaneContext.Provider>;\n}\n\n/**\n * Internal provider component for options-based client creation with Suspense.\n */\nfunction ReplaneProviderWithSuspense<T extends object>({\n options,\n children,\n}: ReplaneProviderWithOptionsProps<T>) {\n const client = useReplaneClientSuspense<T>(options);\n const value = useMemo<ReplaneContextValue<T>>(() => ({ replane: client }), [client]);\n return <ReplaneContext.Provider value={value}>{children}</ReplaneContext.Provider>;\n}\n\n/**\n * Provider component that makes a Replane client available to the component tree.\n *\n * Can be used in several ways:\n *\n * 1. With a pre-created client:\n * ```tsx\n * const client = new Replane({ defaults: { ... } });\n * await client.connect({ baseUrl: '...', sdkKey: '...' });\n * <ReplaneProvider client={client}>\n * <App />\n * </ReplaneProvider>\n * ```\n *\n * 2. With options (client managed internally):\n * ```tsx\n * <ErrorBoundary fallback={<ErrorMessage />}>\n * <ReplaneProvider\n * options={{ baseUrl: '...', sdkKey: '...' }}\n * loader={<LoadingSpinner />}\n * >\n * <App />\n * </ReplaneProvider>\n * </ErrorBoundary>\n * ```\n *\n * 3. With Suspense:\n * ```tsx\n * <ErrorBoundary fallback={<ErrorMessage />}>\n * <Suspense fallback={<LoadingSpinner />}>\n * <ReplaneProvider\n * options={{ baseUrl: '...', sdkKey: '...' }}\n * suspense\n * >\n * <App />\n * </ReplaneProvider>\n * </Suspense>\n * </ErrorBoundary>\n * ```\n *\n * 4. With a snapshot (for SSR/hydration):\n * ```tsx\n * // On the server, get a snapshot from the client\n * const snapshot = serverClient.getSnapshot();\n *\n * // On the client, restore from the snapshot with live updates\n * <ReplaneProvider\n * options={{ baseUrl: '...', sdkKey: '...' }}\n * snapshot={snapshot}\n * >\n * <App />\n * </ReplaneProvider>\n * ```\n *\n * Errors during client initialization are thrown during rendering,\n * allowing them to be caught by React Error Boundaries.\n */\nexport function ReplaneProvider<T extends object>(props: ReplaneProviderProps<T>) {\n if (hasClient(props)) {\n return <ReplaneProviderWithClient {...props} />;\n }\n\n // Has options - check if snapshot is provided\n if (props.snapshot) {\n return <ReplaneProviderWithSnapshot {...props} snapshot={props.snapshot} />;\n }\n\n if (props.suspense) {\n return <ReplaneProviderWithSuspense {...props} />;\n }\n\n return <ReplaneProviderWithOptions {...props} />;\n}\n","\"use client\";\n\nimport { useCallback, useContext, useSyncExternalStore } from \"react\";\nimport { ReplaneContext } from \"./context\";\nimport type { UntypedReplaneConfig } from \"./types\";\nimport type { Replane, GetConfigOptions } from \"@replanejs/sdk\";\n\nexport function useReplane<T extends object = UntypedReplaneConfig>(): Replane<T> {\n const context = useContext(ReplaneContext);\n if (!context) {\n throw new Error(\"useReplane must be used within a ReplaneProvider\");\n }\n return context.replane as Replane<T>;\n}\n\nexport function useConfig<T>(name: string, options?: GetConfigOptions<T>): T {\n const client = useReplane();\n\n const subscribe = useCallback(\n (callback: () => void) => {\n return client.subscribe(name, callback);\n },\n [client, name]\n );\n\n const get = useCallback(() => {\n return client.get(name, options) as T;\n }, [client, name, options]);\n\n const value = useSyncExternalStore(subscribe, get, get);\n\n return value;\n}\n\n/**\n * Creates a typed version of useReplane hook.\n *\n * @example\n * ```tsx\n * interface AppConfigs {\n * theme: { darkMode: boolean };\n * features: { beta: boolean };\n * }\n *\n * const useAppReplane = createReplaneHook<AppConfigs>();\n *\n * function MyComponent() {\n * const replane = useAppReplane();\n * // replane.get(\"theme\") returns { darkMode: boolean }\n * }\n * ```\n */\nexport function createReplaneHook<TConfigs extends object>() {\n return function useTypedReplane(): Replane<TConfigs> {\n return useReplane<TConfigs>();\n };\n}\n\n/**\n * Creates a typed version of useConfig hook.\n *\n * @example\n * ```tsx\n * interface AppConfigs {\n * theme: { darkMode: boolean };\n * features: { beta: boolean };\n * }\n *\n * const useAppConfig = createConfigHook<AppConfigs>();\n *\n * function MyComponent() {\n * const theme = useAppConfig(\"theme\");\n * // theme is typed as { darkMode: boolean }\n * }\n * ```\n */\nexport function createConfigHook<TConfigs extends object>() {\n return function useTypedConfig<K extends keyof TConfigs>(\n name: K,\n options?: GetConfigOptions<TConfigs[K]>\n ): TConfigs[K] {\n return useConfig<TConfigs[K]>(String(name), options);\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["options: ConnectOptions","options: ReplaneOptions<T>","connection: ConnectOptions","Replane","originalConnection: ConnectOptions","err: unknown","connection?: ConnectOptions","props: ReplaneProviderProps<T>","Replane","value: ReplaneContextValue<T>","props: ReplaneProviderProps<T>","name: string","options?: GetConfigOptions<T>","callback: () => void","name: K","options?: GetConfigOptions<TConfigs[K]>"],"sources":["../src/context.ts","../src/useReplaneClient.ts","../src/types.ts","../src/version.ts","../src/provider.tsx","../src/hooks.ts"],"sourcesContent":["\"use client\";\n\nimport { createContext } from \"react\";\nimport type { ReplaneContextValue } from \"./types\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const ReplaneContext = createContext<ReplaneContextValue<any> | null>(null);\n","\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { Replane, type ConnectOptions, type ReplaneOptions } from \"@replanejs/sdk\";\n\ntype ClientState<T extends object> =\n | { status: \"loading\"; client: null; error: null }\n | { status: \"ready\"; client: Replane<T>; error: null }\n | { status: \"error\"; client: null; error: Error };\n\n// Cache for suspense promise tracking\nconst suspenseCache = new Map<\n string,\n {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n promise: Promise<Replane<any>>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n result?: Replane<any>;\n error?: Error;\n }\n>();\n\nfunction getCacheKey(options: ConnectOptions): string {\n return `${options.baseUrl}:${options.sdkKey}`;\n}\n\n/**\n * Creates a Replane client and connects it.\n */\nasync function createAndConnectClient<T extends object>(\n options: ReplaneOptions<T>,\n connection: ConnectOptions\n): Promise<Replane<T>> {\n const client = new Replane<T>({\n logger: options.logger,\n context: options.context,\n defaults: options.defaults,\n });\n\n if (!connection) {\n return client;\n }\n\n await client.connect(connection);\n\n return client;\n}\n\ntype ErrorConstructor = new (message: string, options?: { cause?: unknown }) => Error;\n\n/**\n * Hook to manage Replane client creation internally.\n * Handles loading state and cleanup.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function useReplaneClientInternal<T extends object = any>(\n options: ReplaneOptions<T>,\n originalConnection: ConnectOptions\n): ClientState<T> {\n const [state, setState] = useState<ClientState<T>>({\n status: \"loading\",\n client: null,\n error: null,\n });\n const clientRef = useRef<Replane<T> | null>(null);\n const optionsRef = useRef(options);\n\n const connectionJson = JSON.stringify(originalConnection);\n useEffect(() => {\n const connection = JSON.parse(connectionJson);\n let cancelled = false;\n\n async function initClient() {\n try {\n const client = await createAndConnectClient<T>(optionsRef.current, connection);\n if (cancelled) {\n client.disconnect();\n return;\n }\n clientRef.current = client;\n setState({ status: \"ready\", client, error: null });\n } catch (err) {\n if (cancelled) return;\n const error =\n err instanceof Error ? err : new (Error as ErrorConstructor)(String(err), { cause: err });\n setState({ status: \"error\", client: null, error });\n }\n }\n\n initClient();\n\n return () => {\n cancelled = true;\n if (clientRef.current) {\n clientRef.current.disconnect();\n clientRef.current = null;\n }\n };\n }, [connectionJson]);\n\n return state;\n}\n\n/**\n * Hook for Suspense-based client creation.\n * Throws a promise while loading, throws error on failure.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function useReplaneClientSuspense<T extends object = any>(\n options: ReplaneOptions<T>,\n connection: ConnectOptions\n): Replane<T> {\n const cacheKey = getCacheKey(connection);\n const cached = suspenseCache.get(cacheKey);\n\n if (cached) {\n if (cached.error) {\n throw cached.error;\n }\n if (cached.result) {\n return cached.result as Replane<T>;\n }\n // Still loading, throw the promise\n throw cached.promise;\n }\n\n // First time - create the promise\n const promise = createAndConnectClient<T>(options, connection)\n .then((client) => {\n const entry = suspenseCache.get(cacheKey);\n if (entry) {\n entry.result = client;\n }\n return client;\n })\n .catch((err: unknown) => {\n const entry = suspenseCache.get(cacheKey);\n if (entry) {\n entry.error = err instanceof Error ? err : new Error(String(err));\n }\n throw err;\n });\n\n suspenseCache.set(cacheKey, { promise });\n throw promise;\n}\n\n/**\n * Clear the suspense cache for a specific connection configuration.\n * Useful for testing or when you need to force re-initialization.\n */\nexport function clearSuspenseCache(connection?: ConnectOptions): void {\n if (connection) {\n suspenseCache.delete(getCacheKey(connection));\n } else {\n suspenseCache.clear();\n }\n}\n","import type { Replane, ReplaneOptions, ConnectOptions } from \"@replanejs/sdk\";\nimport type { ReactNode } from \"react\";\n\nexport type UntypedReplaneConfig = Record<string, unknown>;\n\nexport interface ReplaneContextValue<T extends object = UntypedReplaneConfig> {\n replane: Replane<T>;\n}\n\n/**\n * Props for ReplaneProvider when using a pre-created client.\n */\nexport interface ReplaneProviderWithClientProps<T extends object = UntypedReplaneConfig> {\n /** Pre-created Replane client instance */\n client: Replane<T>;\n children: ReactNode;\n}\n\n/**\n * Props for ReplaneProvider when letting it manage the client internally.\n */\nexport interface ReplaneProviderWithOptionsProps<\n T extends object = UntypedReplaneConfig,\n> extends ReplaneOptions<T> {\n children: ReactNode;\n /**\n * Connection options for connecting to the Replane server.\n * Pass null to explicitly skip connection (client will use defaults/snapshot only).\n */\n connection: ConnectOptions | null;\n /**\n * Optional loading component to show while the client is initializing.\n * If not provided and suspense is false/undefined, children will not render until ready.\n * Ignored when snapshot is provided (restoration is synchronous).\n */\n loader?: ReactNode;\n /**\n * If true, uses React Suspense for loading state.\n * The provider will throw a promise that Suspense can catch.\n * Ignored when snapshot is provided (restoration is synchronous).\n * @default false\n */\n suspense?: boolean;\n /**\n * If true, the client will be connected asynchronously. Make sure to provide defaults or snapshot.\n * @default false\n */\n async?: boolean;\n}\n\nexport type ReplaneProviderProps<T extends object = UntypedReplaneConfig> =\n | ReplaneProviderWithClientProps<T>\n | ReplaneProviderWithOptionsProps<T>;\n\n/**\n * Type guard to check if props contain a pre-created client.\n */\nexport function hasClient<T extends object>(\n props: ReplaneProviderProps<T>\n): props is ReplaneProviderWithClientProps<T> {\n return \"client\" in props && !!props.client;\n}\n\n/**\n * Type guard to check if props contain options (with or without snapshot).\n */\nexport function hasOptions<T extends object>(\n props: ReplaneProviderProps<T>\n): props is ReplaneProviderWithOptionsProps<T> {\n return !hasClient(props);\n}\n","// Auto-generated - do not edit manually\nexport const VERSION = \"0.9.2\";\nexport const DEFAULT_AGENT = `replane-js-react/${VERSION}`;\n","\"use client\";\n\nimport { useEffect, useMemo, useRef } from \"react\";\nimport { Replane, type ConnectOptions } from \"@replanejs/sdk\";\nimport { ReplaneContext } from \"./context\";\nimport { useReplaneClientInternal, useReplaneClientSuspense } from \"./useReplaneClient\";\nimport type {\n ReplaneProviderProps,\n ReplaneProviderWithClientProps,\n ReplaneProviderWithOptionsProps,\n ReplaneContextValue,\n} from \"./types\";\nimport { hasClient } from \"./types\";\nimport { DEFAULT_AGENT } from \"./version\";\n\n/**\n * Internal provider component for pre-created client.\n */\nfunction ReplaneProviderWithClient<T extends object>({\n client,\n children,\n}: ReplaneProviderWithClientProps<T>) {\n const value = useMemo<ReplaneContextValue<T>>(() => ({ replane: client }), [client]);\n return <ReplaneContext.Provider value={value}>{children}</ReplaneContext.Provider>;\n}\n\n/**\n * Internal provider component for creating a Replane client asynchronously.\n * Creates a Replane client synchronously and connects in background.\n */\nfunction AsyncReplaneProvider<T extends object>({\n children,\n connection,\n ...options\n}: ReplaneProviderWithOptionsProps<T>) {\n const replaneRef = useRef<Replane<T>>(undefined as unknown as Replane<T>);\n\n if (!replaneRef.current) {\n replaneRef.current = new Replane<T>(options);\n }\n\n const connectionJson = connection ? JSON.stringify(connection) : undefined;\n\n useEffect(() => {\n const parsedConnection = connectionJson ? JSON.parse(connectionJson) : undefined;\n if (!parsedConnection) {\n return;\n }\n\n replaneRef.current.connect(parsedConnection).catch((err) => {\n (options.logger ?? console)?.error(\"Failed to connect Replane client\", err);\n });\n\n return () => {\n replaneRef.current.disconnect();\n };\n }, [connectionJson, options.logger]);\n\n const value = useMemo<ReplaneContextValue<T>>(() => ({ replane: replaneRef.current }), []);\n return <ReplaneContext.Provider value={value}>{children}</ReplaneContext.Provider>;\n}\n\n/**\n * Internal provider component for options-based client creation (non-suspense).\n * Throws errors during rendering so they can be caught by Error Boundaries.\n */\nfunction LoaderReplaneProvider<T extends object>({\n children,\n loader,\n connection,\n ...options\n}: ReplaneProviderWithOptionsProps<T> & { connection: ConnectOptions }) {\n if (!connection) {\n throw new Error(\"Connection is required when using Loader\");\n }\n const state = useReplaneClientInternal<T>(options, connection);\n\n if (state.status === \"loading\") {\n return <>{loader ?? null}</>;\n }\n\n if (state.status === \"error\") {\n // Throw error during render so it can be caught by Error Boundary\n throw state.error;\n }\n\n const value: ReplaneContextValue<T> = { replane: state.client };\n return <ReplaneContext.Provider value={value}>{children}</ReplaneContext.Provider>;\n}\n\n/**\n * Internal provider component for options-based client creation with Suspense.\n */\nfunction SuspenseReplaneProvider<T extends object>({\n connection,\n children,\n ...options\n}: ReplaneProviderWithOptionsProps<T> & { connection: ConnectOptions }) {\n if (!connection) {\n throw new Error(\"Connection is required when using Suspense\");\n }\n const client = useReplaneClientSuspense<T>(options, connection);\n const value = useMemo<ReplaneContextValue<T>>(() => ({ replane: client }), [client]);\n return <ReplaneContext.Provider value={value}>{children}</ReplaneContext.Provider>;\n}\n\n/**\n * Provider component that makes a Replane client available to the component tree.\n *\n * Can be used in several ways:\n *\n * 1. With a pre-created client:\n * ```tsx\n * const client = new Replane({ defaults: { ... } });\n * await client.connect({ baseUrl: '...', sdkKey: '...' });\n * <ReplaneProvider client={client}>\n * <App />\n * </ReplaneProvider>\n * ```\n *\n * 2. With options (client managed internally):\n * ```tsx\n * <ErrorBoundary fallback={<ErrorMessage />}>\n * <ReplaneProvider\n * options={{ baseUrl: '...', sdkKey: '...' }}\n * loader={<LoadingSpinner />}\n * >\n * <App />\n * </ReplaneProvider>\n * </ErrorBoundary>\n * ```\n *\n * 3. With Suspense:\n * ```tsx\n * <ErrorBoundary fallback={<ErrorMessage />}>\n * <Suspense fallback={<LoadingSpinner />}>\n * <ReplaneProvider\n * options={{ baseUrl: '...', sdkKey: '...' }}\n * suspense\n * >\n * <App />\n * </ReplaneProvider>\n * </Suspense>\n * </ErrorBoundary>\n * ```\n *\n * 4. With a snapshot (for SSR/hydration):\n * ```tsx\n * // On the server, get a snapshot from the client\n * const snapshot = serverClient.getSnapshot();\n *\n * // On the client, restore from the snapshot with live updates\n * <ReplaneProvider\n * options={{ baseUrl: '...', sdkKey: '...' }}\n * snapshot={snapshot}\n * >\n * <App />\n * </ReplaneProvider>\n * ```\n *\n * Errors during client initialization are thrown during rendering,\n * allowing them to be caught by React Error Boundaries.\n */\nexport function ReplaneProvider<T extends object>(props: ReplaneProviderProps<T>) {\n const originalConnection = (props as { connection?: ConnectOptions }).connection;\n const connection = useMemo(\n () =>\n originalConnection\n ? {\n ...originalConnection,\n agent: originalConnection.agent ?? DEFAULT_AGENT,\n }\n : undefined,\n [originalConnection]\n );\n\n if (hasClient(props)) {\n return <ReplaneProviderWithClient {...props} />;\n }\n\n if (props.snapshot || !connection || props.async) {\n return <AsyncReplaneProvider {...props} />;\n }\n\n if (props.suspense) {\n return <SuspenseReplaneProvider {...props} connection={connection} />;\n }\n\n return <LoaderReplaneProvider {...props} connection={connection} />;\n}\n","\"use client\";\n\nimport { useCallback, useContext, useSyncExternalStore } from \"react\";\nimport { ReplaneContext } from \"./context\";\nimport type { UntypedReplaneConfig } from \"./types\";\nimport type { Replane, GetConfigOptions } from \"@replanejs/sdk\";\n\nexport function useReplane<T extends object = UntypedReplaneConfig>(): Replane<T> {\n const context = useContext(ReplaneContext);\n if (!context) {\n throw new Error(\"useReplane must be used within a ReplaneProvider\");\n }\n return context.replane as Replane<T>;\n}\n\nexport function useConfig<T>(name: string, options?: GetConfigOptions<T>): T {\n const client = useReplane();\n\n const subscribe = useCallback(\n (callback: () => void) => {\n return client.subscribe(name, callback);\n },\n [client, name]\n );\n\n const get = useCallback(() => {\n return client.get(name, options) as T;\n }, [client, name, options]);\n\n const value = useSyncExternalStore(subscribe, get, get);\n\n return value;\n}\n\n/**\n * Creates a typed version of useReplane hook.\n *\n * @example\n * ```tsx\n * interface AppConfigs {\n * theme: { darkMode: boolean };\n * features: { beta: boolean };\n * }\n *\n * const useAppReplane = createReplaneHook<AppConfigs>();\n *\n * function MyComponent() {\n * const replane = useAppReplane();\n * // replane.get(\"theme\") returns { darkMode: boolean }\n * }\n * ```\n */\nexport function createReplaneHook<TConfigs extends object>() {\n return function useTypedReplane(): Replane<TConfigs> {\n return useReplane<TConfigs>();\n };\n}\n\n/**\n * Creates a typed version of useConfig hook.\n *\n * @example\n * ```tsx\n * interface AppConfigs {\n * theme: { darkMode: boolean };\n * features: { beta: boolean };\n * }\n *\n * const useAppConfig = createConfigHook<AppConfigs>();\n *\n * function MyComponent() {\n * const theme = useAppConfig(\"theme\");\n * // theme is typed as { darkMode: boolean }\n * }\n * ```\n */\nexport function createConfigHook<TConfigs extends object>() {\n return function useTypedConfig<K extends keyof TConfigs>(\n name: K,\n options?: GetConfigOptions<TConfigs[K]>\n ): TConfigs[K] {\n return useConfig<TConfigs[K]>(String(name), options);\n };\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@replanejs/react",
3
- "version": "0.9.0",
3
+ "version": "0.9.2",
4
4
  "description": "React SDK for Replane - feature flags and remote configuration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -40,7 +40,7 @@
40
40
  "react": ">=18.0.0"
41
41
  },
42
42
  "dependencies": {
43
- "@replanejs/sdk": "^0.9.0"
43
+ "@replanejs/sdk": "^0.9.2"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@testing-library/jest-dom": "^6.9.1",