@replanejs/react 0.7.8 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,10 @@
1
1
  # @replanejs/react
2
2
 
3
- React SDK for [Replane](https://github.com/replane-dev/replane-javascript) - feature flags and remote configuration.
3
+ [![npm](https://img.shields.io/npm/v/@replanejs/react)](https://www.npmjs.com/package/@replanejs/react)
4
+ [![License](https://img.shields.io/github/license/replane-dev/replane-javascript)](https://github.com/replane-dev/replane-javascript/blob/main/LICENSE)
5
+ [![Community](https://img.shields.io/badge/discussions-join-blue?logo=github)](https://github.com/orgs/replane-dev/discussions)
6
+
7
+ React SDK for [Replane](https://github.com/replane-dev/replane) - feature flags and remote configuration.
4
8
 
5
9
  ## Installation
6
10
 
@@ -20,14 +24,14 @@ yarn add @replanejs/react
20
24
  ## Quick Start
21
25
 
22
26
  ```tsx
23
- import { ReplaneProvider, useConfig } from '@replanejs/react';
27
+ import { ReplaneProvider, useConfig } from "@replanejs/react";
24
28
 
25
29
  function App() {
26
30
  return (
27
31
  <ReplaneProvider
28
32
  options={{
29
- baseUrl: 'https://your-replane-server.com',
30
- sdkKey: 'your-sdk-key',
33
+ baseUrl: "https://your-replane-server.com",
34
+ sdkKey: "your-sdk-key",
31
35
  }}
32
36
  loader={<div>Loading...</div>}
33
37
  >
@@ -37,13 +41,9 @@ function App() {
37
41
  }
38
42
 
39
43
  function MyComponent() {
40
- const isFeatureEnabled = useConfig<boolean>('feature-flag-name');
44
+ const isFeatureEnabled = useConfig<boolean>("feature-flag-name");
41
45
 
42
- return (
43
- <div>
44
- {isFeatureEnabled ? 'Feature is enabled!' : 'Feature is disabled'}
45
- </div>
46
- );
46
+ return <div>{isFeatureEnabled ? "Feature is enabled!" : "Feature is disabled"}</div>;
47
47
  }
48
48
  ```
49
49
 
@@ -58,19 +58,19 @@ Provider component that makes the Replane client available to your component tre
58
58
  The provider creates and manages the client internally. Use an Error Boundary to handle initialization errors:
59
59
 
60
60
  ```tsx
61
- import { ErrorBoundary } from 'react-error-boundary';
61
+ import { ErrorBoundary } from "react-error-boundary";
62
62
 
63
63
  <ErrorBoundary fallback={<div>Failed to load configuration</div>}>
64
64
  <ReplaneProvider
65
65
  options={{
66
- baseUrl: 'https://your-replane-server.com',
67
- sdkKey: 'your-sdk-key',
66
+ baseUrl: "https://your-replane-server.com",
67
+ sdkKey: "your-sdk-key",
68
68
  }}
69
69
  loader={<LoadingSpinner />}
70
70
  >
71
71
  <App />
72
72
  </ReplaneProvider>
73
- </ErrorBoundary>
73
+ </ErrorBoundary>;
74
74
  ```
75
75
 
76
76
  #### 2. With pre-created client
@@ -78,16 +78,16 @@ import { ErrorBoundary } from 'react-error-boundary';
78
78
  Use this when you need more control over client lifecycle:
79
79
 
80
80
  ```tsx
81
- import { createReplaneClient } from '@replanejs/sdk';
81
+ import { createReplaneClient } from "@replanejs/sdk";
82
82
 
83
83
  const client = await createReplaneClient({
84
- baseUrl: 'https://your-replane-server.com',
85
- sdkKey: 'your-sdk-key',
84
+ baseUrl: "https://your-replane-server.com",
85
+ sdkKey: "your-sdk-key",
86
86
  });
87
87
 
88
88
  <ReplaneProvider client={client}>
89
89
  <App />
90
- </ReplaneProvider>
90
+ </ReplaneProvider>;
91
91
  ```
92
92
 
93
93
  #### 3. With Suspense
@@ -99,8 +99,8 @@ Integrates with React Suspense for loading states:
99
99
  <Suspense fallback={<LoadingSpinner />}>
100
100
  <ReplaneProvider
101
101
  options={{
102
- baseUrl: 'https://your-replane-server.com',
103
- sdkKey: 'your-sdk-key',
102
+ baseUrl: "https://your-replane-server.com",
103
+ sdkKey: "your-sdk-key",
104
104
  }}
105
105
  suspense
106
106
  >
@@ -116,7 +116,7 @@ Restore a client from a snapshot obtained on the server. This is synchronous and
116
116
 
117
117
  ```tsx
118
118
  // On the server
119
- const serverClient = await createReplaneClient({ baseUrl: '...', sdkKey: '...' });
119
+ const serverClient = await createReplaneClient({ baseUrl: "...", sdkKey: "..." });
120
120
  const snapshot = serverClient.getSnapshot();
121
121
  // Pass snapshot to client via props, context, or serialized HTML
122
122
 
@@ -126,13 +126,13 @@ const snapshot = serverClient.getSnapshot();
126
126
  snapshot,
127
127
  // Optional: connect for live updates
128
128
  connection: {
129
- baseUrl: 'https://your-replane-server.com',
130
- sdkKey: 'your-sdk-key',
129
+ baseUrl: "https://your-replane-server.com",
130
+ sdkKey: "your-sdk-key",
131
131
  },
132
132
  }}
133
133
  >
134
134
  <App />
135
- </ReplaneProvider>
135
+ </ReplaneProvider>;
136
136
  ```
137
137
 
138
138
  The restored client is immediately available with no loading state. If `connection` is provided, it will establish a connection for real-time updates in the background.
@@ -144,17 +144,21 @@ Hook to retrieve a configuration value. Automatically subscribes to updates and
144
144
  ```tsx
145
145
  function MyComponent() {
146
146
  // Basic usage
147
- const theme = useConfig<string>('theme');
147
+ const theme = useConfig<string>("theme");
148
148
 
149
149
  // With evaluation context
150
- const discount = useConfig<number>('discount-percentage', {
150
+ const discount = useConfig<number>("discount-percentage", {
151
151
  context: {
152
- userId: '123',
152
+ userId: "123",
153
153
  isPremium: true,
154
154
  },
155
155
  });
156
156
 
157
- return <div>Theme: {theme}, Discount: {discount}%</div>;
157
+ return (
158
+ <div>
159
+ Theme: {theme}, Discount: {discount}%
160
+ </div>
161
+ );
158
162
  }
159
163
  ```
160
164
 
@@ -168,7 +172,7 @@ function MyComponent() {
168
172
 
169
173
  const handleClick = () => {
170
174
  // Access replane methods directly
171
- const value = replane.get('some-config');
175
+ const value = replane.get("some-config");
172
176
  console.log(value);
173
177
  };
174
178
 
@@ -181,7 +185,7 @@ function MyComponent() {
181
185
  Factory function to create a typed version of `useReplane`. Returns a hook that provides the typed client directly:
182
186
 
183
187
  ```tsx
184
- import { createReplaneHook } from '@replanejs/react';
188
+ import { createReplaneHook } from "@replanejs/react";
185
189
 
186
190
  // Define your config types
187
191
  interface AppConfigs {
@@ -197,10 +201,10 @@ function MyComponent() {
197
201
  const replane = useAppReplane();
198
202
 
199
203
  // replane.get is now typed - autocomplete works!
200
- const theme = replane.get('theme');
204
+ const theme = replane.get("theme");
201
205
  // ^? { darkMode: boolean; primaryColor: string }
202
206
 
203
- return <div>Dark mode: {theme.darkMode ? 'on' : 'off'}</div>;
207
+ return <div>Dark mode: {theme.darkMode ? "on" : "off"}</div>;
204
208
  }
205
209
  ```
206
210
 
@@ -209,7 +213,7 @@ function MyComponent() {
209
213
  Factory function to create a typed version of `useConfig`. This provides autocomplete for config names and type inference for values:
210
214
 
211
215
  ```tsx
212
- import { createConfigHook } from '@replanejs/react';
216
+ import { createConfigHook } from "@replanejs/react";
213
217
 
214
218
  // Define your config types
215
219
  interface AppConfigs {
@@ -223,24 +227,24 @@ const useAppConfig = createConfigHook<AppConfigs>();
223
227
 
224
228
  function MyComponent() {
225
229
  // Autocomplete for config names, automatic type inference
226
- const theme = useAppConfig('theme');
230
+ const theme = useAppConfig("theme");
227
231
  // ^? { darkMode: boolean; primaryColor: string }
228
232
 
229
- const features = useAppConfig('features');
233
+ const features = useAppConfig("features");
230
234
  // ^? { beta: boolean; analytics: boolean }
231
235
 
232
- const maxItems = useAppConfig('maxItems');
236
+ const maxItems = useAppConfig("maxItems");
233
237
  // ^? number
234
238
 
235
239
  // With context override
236
- const premiumFeatures = useAppConfig('features', {
237
- context: { userId: '123', plan: 'premium' },
240
+ const premiumFeatures = useAppConfig("features", {
241
+ context: { userId: "123", plan: "premium" },
238
242
  });
239
243
 
240
244
  return (
241
245
  <div>
242
- <p>Dark mode: {theme.darkMode ? 'on' : 'off'}</p>
243
- <p>Beta enabled: {features.beta ? 'yes' : 'no'}</p>
246
+ <p>Dark mode: {theme.darkMode ? "on" : "off"}</p>
247
+ <p>Beta enabled: {features.beta ? "yes" : "no"}</p>
244
248
  <p>Max items: {maxItems}</p>
245
249
  </div>
246
250
  );
@@ -252,12 +256,12 @@ function MyComponent() {
252
256
  Utility function to clear the suspense cache. Useful for testing or forcing re-initialization:
253
257
 
254
258
  ```tsx
255
- import { clearSuspenseCache } from '@replanejs/react';
259
+ import { clearSuspenseCache } from "@replanejs/react";
256
260
 
257
261
  // Clear cache for specific options
258
262
  clearSuspenseCache({
259
- baseUrl: 'https://your-replane-server.com',
260
- sdkKey: 'your-sdk-key',
263
+ baseUrl: "https://your-replane-server.com",
264
+ sdkKey: "your-sdk-key",
261
265
  });
262
266
 
263
267
  // Clear entire cache
@@ -271,16 +275,16 @@ The SDK is fully typed. For the best TypeScript experience, use the hook factory
271
275
  ```tsx
272
276
  // Define all your config types in one interface
273
277
  interface AppConfigs {
274
- 'theme-config': {
278
+ "theme-config": {
275
279
  darkMode: boolean;
276
280
  primaryColor: string;
277
281
  };
278
- 'feature-flags': {
282
+ "feature-flags": {
279
283
  newUI: boolean;
280
284
  beta: boolean;
281
285
  };
282
- 'max-items': number;
283
- 'welcome-message': string;
286
+ "max-items": number;
287
+ "welcome-message": string;
284
288
  }
285
289
 
286
290
  // Create typed hooks once
@@ -289,7 +293,7 @@ const useAppConfig = createConfigHook<AppConfigs>();
289
293
 
290
294
  // Use throughout your app with full type safety
291
295
  function Settings() {
292
- const theme = useAppConfig('theme-config');
296
+ const theme = useAppConfig("theme-config");
293
297
  // ^? { darkMode: boolean; primaryColor: string }
294
298
 
295
299
  const replane = useAppReplane();
@@ -298,7 +302,7 @@ function Settings() {
298
302
 
299
303
  return (
300
304
  <div style={{ color: theme.primaryColor }}>
301
- Dark mode: {theme.darkMode ? 'enabled' : 'disabled'}
305
+ Dark mode: {theme.darkMode ? "enabled" : "disabled"}
302
306
  </div>
303
307
  );
304
308
  }
@@ -309,7 +313,7 @@ function Settings() {
309
313
  The provider throws errors during rendering so they can be caught by React Error Boundaries:
310
314
 
311
315
  ```tsx
312
- import { Component, ReactNode } from 'react';
316
+ import { Component, ReactNode } from "react";
313
317
 
314
318
  class ErrorBoundary extends Component<
315
319
  { children: ReactNode; fallback: ReactNode },
@@ -334,13 +338,13 @@ class ErrorBoundary extends Component<
334
338
  <ReplaneProvider options={options} loader={<Loading />}>
335
339
  <App />
336
340
  </ReplaneProvider>
337
- </ErrorBoundary>
341
+ </ErrorBoundary>;
338
342
  ```
339
343
 
340
344
  Or use a library like `react-error-boundary`:
341
345
 
342
346
  ```tsx
343
- import { ErrorBoundary } from 'react-error-boundary';
347
+ import { ErrorBoundary } from "react-error-boundary";
344
348
 
345
349
  <ErrorBoundary
346
350
  fallbackRender={({ error, resetErrorBoundary }) => (
@@ -354,9 +358,13 @@ import { ErrorBoundary } from 'react-error-boundary';
354
358
  <ReplaneProvider options={options} loader={<Loading />}>
355
359
  <App />
356
360
  </ReplaneProvider>
357
- </ErrorBoundary>
361
+ </ErrorBoundary>;
358
362
  ```
359
363
 
364
+ ## Community
365
+
366
+ Have questions or want to discuss Replane? Join the conversation in [GitHub Discussions](https://github.com/orgs/replane-dev/discussions).
367
+
360
368
  ## License
361
369
 
362
370
  MIT
package/dist/index.cjs CHANGED
@@ -348,12 +348,6 @@ function ReplaneProvider(props) {
348
348
 
349
349
  //#endregion
350
350
  exports.ReplaneProvider = ReplaneProvider;
351
- Object.defineProperty(exports, 'clearSnapshotCache', {
352
- enumerable: true,
353
- get: function () {
354
- return __replanejs_sdk.clearSnapshotCache;
355
- }
356
- });
357
351
  exports.clearSuspenseCache = clearSuspenseCache;
358
352
  exports.createConfigHook = createConfigHook;
359
353
  exports.createReplaneHook = createReplaneHook;
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as react_jsx_runtime0 from "react/jsx-runtime";
2
- import { GetConfigOptions, GetReplaneSnapshotOptions, ReplaneClient, ReplaneClientOptions, ReplaneSnapshot, clearSnapshotCache, getReplaneSnapshot } from "@replanejs/sdk";
2
+ import { GetConfigOptions, GetReplaneSnapshotOptions, ReplaneClient, ReplaneClientOptions, ReplaneSnapshot, getReplaneSnapshot } from "@replanejs/sdk";
3
3
  import { ReactNode } from "react";
4
4
 
5
5
  //#region src/types.d.ts
@@ -108,7 +108,7 @@ declare function ReplaneProvider<T extends object>(props: ReplaneProviderProps<T
108
108
  //#endregion
109
109
  //#region src/hooks.d.ts
110
110
  declare function useReplane<T extends object = UntypedReplaneConfig>(): ReplaneClient<T>;
111
- declare function useConfig<T>(name: string, options?: GetConfigOptions): T;
111
+ declare function useConfig<T>(name: string, options?: GetConfigOptions<T>): T;
112
112
  /**
113
113
  * Creates a typed version of useReplane hook.
114
114
  *
@@ -146,7 +146,7 @@ declare function createReplaneHook<TConfigs extends object>(): () => ReplaneClie
146
146
  * }
147
147
  * ```
148
148
  */
149
- declare function createConfigHook<TConfigs extends object>(): <K extends keyof TConfigs>(name: K, options?: GetConfigOptions) => TConfigs[K];
149
+ declare function createConfigHook<TConfigs extends object>(): <K extends keyof TConfigs>(name: K, options?: GetConfigOptions<TConfigs[K]>) => TConfigs[K];
150
150
  /**
151
151
  * Hook for creating stateful resources with cleanup support.
152
152
  * Unlike useMemo, this guarantees cleanup when dependencies change or on unmount.
@@ -163,5 +163,5 @@ declare function createConfigHook<TConfigs extends object>(): <K extends keyof T
163
163
  */
164
164
  declare function clearSuspenseCache<T extends object>(options?: ReplaneClientOptions<T>): void;
165
165
  //#endregion
166
- export { type GetReplaneSnapshotOptions, ReplaneProvider, type ReplaneProviderProps, type ReplaneProviderWithClientProps, type ReplaneProviderWithOptionsProps, clearSnapshotCache, clearSuspenseCache, createConfigHook, createReplaneHook, getReplaneSnapshot, useConfig, useReplane };
166
+ export { type GetReplaneSnapshotOptions, ReplaneProvider, type ReplaneProviderProps, type ReplaneProviderWithClientProps, type ReplaneProviderWithOptionsProps, clearSuspenseCache, createConfigHook, createReplaneHook, getReplaneSnapshot, useConfig, useReplane };
167
167
  //# 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":";;;;;KAOY,oBAAA,GAAuB;AASnC;;;AAEwB,UAFP,8BAEO,CAAA,UAAA,MAAA,GAF2C,oBAE3C,CAAA,CAAA;EAAC;EAAF,MACX,EADF,aACE,CADY,CACZ,CAAA;EAAS,QAAA,EAAT,SAAS;AAMrB;;;;AAEW,UAFM,+BAEN,CAAA,UAAA,MAAA,GAFyD,oBAEzD,CAAA,CAAA;EAAoB;EACV,OAOQ,EARlB,oBAQkB,CARG,CAQH,CAAA;EAAC,QAAjB,EAPD,SAOC;EAAe;AAMR;AAUpB;;;;EACoC,QAAhC,CAAA,EAjBS,eAiBT,CAjByB,CAiBzB,CAAA;EAA8B;;AACC;;;WAZxB;EC0GK;;;;;AAAgE;;;KDhGpE,wCAAwC,wBAChD,+BAA+B,KAC/B,gCAAgC;AEhDpC;;;;;;;;;;AFEA;AASA;;;;;;AAGqB;AAMrB;;;;;;;;;AAgBoB;AAUpB;;;;;;;AAEmC;;;;AC8FnC;;;;;AAAgF;;;;AC9IhF;;;;;AAAoF;AAQpF;;;;AAAyE;AAqCzE;;;AACqC,iBDgGrB,eChGqB,CAAA,UAAA,MAAA,CAAA,CAAA,KAAA,EDgGoB,oBChGpB,CDgGyC,CChGzC,CAAA,CAAA,EDgG2C,kBAAA,CAAA,GAAA,CAAA,OChG3C;AAAa;;;iBA9ClC,8BAA8B,yBAAyB,cAAc;iBAQrE,qCAAqC,mBAAmB;;AFNxE;AASA;;;;;;AAGqB;AAMrB;;;;;;;;;AAgBoB,iBESJ,iBFTI,CAAA,iBAAA,MAAA,CAAA,CAAA,CAAA,EAAA,GAAA,GEUiB,aFVjB,CEU+B,QFV/B,CAAA;AAUpB;;;;;;;AAEmC;;;;AC8FnC;;;;;AAAgF;;iBCzEhE,8DACiC,gBACvC,aACI,qBACT,SAAS;;AAzEd;;;;;AAAoF;AAQpF;;;;;;;AFwCoC,iBGuEpB,kBHvEoB,CAAA,UAAA,MAAA,CAAA,CAAA,OAAA,CAAA,EGuE2B,oBHvE3B,CGuEgD,CHvEhD,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":";;;;;KAOY,oBAAA,GAAuB;AASnC;;;AAEwB,UAFP,8BAEO,CAAA,UAAA,MAAA,GAF2C,oBAE3C,CAAA,CAAA;EAAC;EAAF,MACX,EADF,aACE,CADY,CACZ,CAAA;EAAS,QAAA,EAAT,SAAS;AAMrB;;;;AAEW,UAFM,+BAEN,CAAA,UAAA,MAAA,GAFyD,oBAEzD,CAAA,CAAA;EAAoB;EACV,OAOQ,EARlB,oBAQkB,CARG,CAQH,CAAA;EAAC,QAAjB,EAPD,SAOC;EAAe;AAMR;AAUpB;;;;EACoC,QAAhC,CAAA,EAjBS,eAiBT,CAjByB,CAiBzB,CAAA;EAA8B;;AACC;;;WAZxB;EC4GK;;;;;AAAgE;;;KDlGpE,wCAAwC,wBAChD,+BAA+B,KAC/B,gCAAgC;AE9CpC;;;;;;;;;;AFAA;AASA;;;;;;AAGqB;AAMrB;;;;;;;;;AAgBoB;AAUpB;;;;;;;AAEmC;;;;ACgGnC;;;;;AAAgF;;;;AC9IhF;;;;;AAAoF;AAQpF;;;;;AAA4E;AAqC5E;;AACmD,iBDgGnC,eChGmC,CAAA,UAAA,MAAA,CAAA,CAAA,KAAA,EDgGM,oBChGN,CDgG2B,CChG3B,CAAA,CAAA,EDgG6B,kBAAA,CAAA,GAAA,CAAA,OChG7B;;;;iBA9CnC,8BAA8B,yBAAyB,cAAc;iBAQrE,qCAAqC,iBAAiB,KAAK;;AFR3E;AASA;;;;;;AAGqB;AAMrB;;;;;;;;;AAgBoB,iBEWJ,iBFXI,CAAA,iBAAA,MAAA,CAAA,CAAA,CAAA,EAAA,GAAA,GEYiB,aFZjB,CEY+B,QFZ/B,CAAA;AAUpB;;;;;;;AAEmC;;;;ACgGnC;;;;;AAAgF;;iBCzEhE,8DACiC,gBACvC,aACI,iBAAiB,SAAS,QACnC,SAAS;;AAzEd;;;;;AAAoF;AAQpF;;;;;;;AFsCoC,iBGyEpB,kBHzEoB,CAAA,UAAA,MAAA,CAAA,CAAA,OAAA,CAAA,EGyE2B,oBHzE3B,CGyEgD,CHzEhD,CAAA,CAAA,EAAA,IAAA"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ReactNode } from "react";
2
- import { GetConfigOptions, GetReplaneSnapshotOptions, ReplaneClient, ReplaneClientOptions, ReplaneSnapshot, clearSnapshotCache, getReplaneSnapshot } from "@replanejs/sdk";
2
+ import { GetConfigOptions, GetReplaneSnapshotOptions, ReplaneClient, ReplaneClientOptions, 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
@@ -108,7 +108,7 @@ declare function ReplaneProvider<T extends object>(props: ReplaneProviderProps<T
108
108
  //#endregion
109
109
  //#region src/hooks.d.ts
110
110
  declare function useReplane<T extends object = UntypedReplaneConfig>(): ReplaneClient<T>;
111
- declare function useConfig<T>(name: string, options?: GetConfigOptions): T;
111
+ declare function useConfig<T>(name: string, options?: GetConfigOptions<T>): T;
112
112
  /**
113
113
  * Creates a typed version of useReplane hook.
114
114
  *
@@ -146,7 +146,7 @@ declare function createReplaneHook<TConfigs extends object>(): () => ReplaneClie
146
146
  * }
147
147
  * ```
148
148
  */
149
- declare function createConfigHook<TConfigs extends object>(): <K extends keyof TConfigs>(name: K, options?: GetConfigOptions) => TConfigs[K];
149
+ declare function createConfigHook<TConfigs extends object>(): <K extends keyof TConfigs>(name: K, options?: GetConfigOptions<TConfigs[K]>) => TConfigs[K];
150
150
  /**
151
151
  * Hook for creating stateful resources with cleanup support.
152
152
  * Unlike useMemo, this guarantees cleanup when dependencies change or on unmount.
@@ -163,5 +163,5 @@ declare function createConfigHook<TConfigs extends object>(): <K extends keyof T
163
163
  */
164
164
  declare function clearSuspenseCache<T extends object>(options?: ReplaneClientOptions<T>): void;
165
165
  //#endregion
166
- export { type GetReplaneSnapshotOptions, ReplaneProvider, type ReplaneProviderProps, type ReplaneProviderWithClientProps, type ReplaneProviderWithOptionsProps, clearSnapshotCache, clearSuspenseCache, createConfigHook, createReplaneHook, getReplaneSnapshot, useConfig, useReplane };
166
+ export { type GetReplaneSnapshotOptions, ReplaneProvider, type ReplaneProviderProps, type ReplaneProviderWithClientProps, type ReplaneProviderWithOptionsProps, clearSuspenseCache, createConfigHook, createReplaneHook, getReplaneSnapshot, useConfig, useReplane };
167
167
  //# 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":";;;;;KAOY,oBAAA,GAAuB;AASnC;;;AAEwB,UAFP,8BAEO,CAAA,UAAA,MAAA,GAF2C,oBAE3C,CAAA,CAAA;EAAC;EAAF,MACX,EADF,aACE,CADY,CACZ,CAAA;EAAS,QAAA,EAAT,SAAS;AAMrB;;;;AAEW,UAFM,+BAEN,CAAA,UAAA,MAAA,GAFyD,oBAEzD,CAAA,CAAA;EAAoB;EACV,OAOQ,EARlB,oBAQkB,CARG,CAQH,CAAA;EAAC,QAAjB,EAPD,SAOC;EAAe;AAMR;AAUpB;;;;EACoC,QAAhC,CAAA,EAjBS,eAiBT,CAjByB,CAiBzB,CAAA;EAA8B;;AACC;;;WAZxB;EC0GK;;;;;AAAgE;;;KDhGpE,wCAAwC,wBAChD,+BAA+B,KAC/B,gCAAgC;AEhDpC;;;;;;;;;;AFEA;AASA;;;;;;AAGqB;AAMrB;;;;;;;;;AAgBoB;AAUpB;;;;;;;AAEmC;;;;AC8FnC;;;;;AAAgF;;;;AC9IhF;;;;;AAAoF;AAQpF;;;;AAAyE;AAqCzE;;;AACqC,iBDgGrB,eChGqB,CAAA,UAAA,MAAA,CAAA,CAAA,KAAA,EDgGoB,oBChGpB,CDgGyC,CChGzC,CAAA,CAAA,EDgG2C,kBAAA,CAAA,GAAA,CAAA,OChG3C;AAAa;;;iBA9ClC,8BAA8B,yBAAyB,cAAc;iBAQrE,qCAAqC,mBAAmB;;AFNxE;AASA;;;;;;AAGqB;AAMrB;;;;;;;;;AAgBoB,iBESJ,iBFTI,CAAA,iBAAA,MAAA,CAAA,CAAA,CAAA,EAAA,GAAA,GEUiB,aFVjB,CEU+B,QFV/B,CAAA;AAUpB;;;;;;;AAEmC;;;;AC8FnC;;;;;AAAgF;;iBCzEhE,8DACiC,gBACvC,aACI,qBACT,SAAS;;AAzEd;;;;;AAAoF;AAQpF;;;;;;;AFwCoC,iBGuEpB,kBHvEoB,CAAA,UAAA,MAAA,CAAA,CAAA,OAAA,CAAA,EGuE2B,oBHvE3B,CGuEgD,CHvEhD,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":";;;;;KAOY,oBAAA,GAAuB;AASnC;;;AAEwB,UAFP,8BAEO,CAAA,UAAA,MAAA,GAF2C,oBAE3C,CAAA,CAAA;EAAC;EAAF,MACX,EADF,aACE,CADY,CACZ,CAAA;EAAS,QAAA,EAAT,SAAS;AAMrB;;;;AAEW,UAFM,+BAEN,CAAA,UAAA,MAAA,GAFyD,oBAEzD,CAAA,CAAA;EAAoB;EACV,OAOQ,EARlB,oBAQkB,CARG,CAQH,CAAA;EAAC,QAAjB,EAPD,SAOC;EAAe;AAMR;AAUpB;;;;EACoC,QAAhC,CAAA,EAjBS,eAiBT,CAjByB,CAiBzB,CAAA;EAA8B;;AACC;;;WAZxB;EC4GK;;;;;AAAgE;;;KDlGpE,wCAAwC,wBAChD,+BAA+B,KAC/B,gCAAgC;AE9CpC;;;;;;;;;;AFAA;AASA;;;;;;AAGqB;AAMrB;;;;;;;;;AAgBoB;AAUpB;;;;;;;AAEmC;;;;ACgGnC;;;;;AAAgF;;;;AC9IhF;;;;;AAAoF;AAQpF;;;;;AAA4E;AAqC5E;;AACmD,iBDgGnC,eChGmC,CAAA,UAAA,MAAA,CAAA,CAAA,KAAA,EDgGM,oBChGN,CDgG2B,CChG3B,CAAA,CAAA,EDgG6B,kBAAA,CAAA,GAAA,CAAA,OChG7B;;;;iBA9CnC,8BAA8B,yBAAyB,cAAc;iBAQrE,qCAAqC,iBAAiB,KAAK;;AFR3E;AASA;;;;;;AAGqB;AAMrB;;;;;;;;;AAgBoB,iBEWJ,iBFXI,CAAA,iBAAA,MAAA,CAAA,CAAA,CAAA,EAAA,GAAA,GEYiB,aFZjB,CEY+B,QFZ/B,CAAA;AAUpB;;;;;;;AAEmC;;;;ACgGnC;;;;;AAAgF;;iBCzEhE,8DACiC,gBACvC,aACI,iBAAiB,SAAS,QACnC,SAAS;;AAzEd;;;;;AAAoF;AAQpF;;;;;;;AFsCoC,iBGyEpB,kBHzEoB,CAAA,UAAA,MAAA,CAAA,CAAA,OAAA,CAAA,EGyE2B,oBHzE3B,CGyEgD,CHzEhD,CAAA,CAAA,EAAA,IAAA"}
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
2
- import { clearSnapshotCache, createReplaneClient, getReplaneSnapshot, restoreReplaneClient } from "@replanejs/sdk";
2
+ import { createReplaneClient, getReplaneSnapshot, restoreReplaneClient } from "@replanejs/sdk";
3
3
  import { Fragment, jsx } from "react/jsx-runtime";
4
4
 
5
5
  //#region src/context.ts
@@ -324,5 +324,5 @@ function ReplaneProvider(props) {
324
324
  }
325
325
 
326
326
  //#endregion
327
- export { ReplaneProvider, clearSnapshotCache, clearSuspenseCache, createConfigHook, createReplaneHook, getReplaneSnapshot, useConfig, useReplane };
327
+ export { ReplaneProvider, clearSuspenseCache, createConfigHook, createReplaneHook, getReplaneSnapshot, useConfig, useReplane };
328
328
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["options: ReplaneClientOptions<T>","options?: ReplaneClientOptions<T>","name: string","options?: GetConfigOptions","callback: () => void","name: K","factory: () => T","cleanup: (value: T) => void","deps: React.DependencyList","props: ReplaneProviderProps<T>","value: ReplaneContextValue<T>","props: ReplaneProviderProps<T>"],"sources":["../src/context.ts","../src/useReplaneClient.ts","../src/hooks.ts","../src/types.ts","../src/provider.tsx"],"sourcesContent":["import { 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","import { useEffect, useRef, useState } from \"react\";\nimport { createReplaneClient } from \"@replanejs/sdk\";\nimport type { ReplaneClient, ReplaneClientOptions } from \"@replanejs/sdk\";\n\ntype ClientState<T extends object> =\n | { status: \"loading\"; client: null; error: null }\n | { status: \"ready\"; client: ReplaneClient<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<ReplaneClient<any>>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n result?: ReplaneClient<any>;\n error?: Error;\n }\n>();\n\nfunction getCacheKey<T extends object>(options: ReplaneClientOptions<T>): string {\n return `${options.baseUrl}:${options.sdkKey}`;\n}\n\ntype ErrorConstructor = new (message: string, options?: { cause?: unknown }) => Error;\n\n/**\n * Hook to manage ReplaneClient 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: ReplaneClientOptions<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<ReplaneClient<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 createReplaneClient<T>(optionsRef.current);\n if (cancelled) {\n client.close();\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.close();\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: ReplaneClientOptions<T>\n): ReplaneClient<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 ReplaneClient<T>;\n }\n // Still loading, throw the promise\n throw cached.promise;\n }\n\n // First time - create the promise\n const promise = createReplaneClient<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) => {\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?: ReplaneClientOptions<T>): void {\n if (options) {\n suspenseCache.delete(getCacheKey(options));\n } else {\n suspenseCache.clear();\n }\n}\n","import { useCallback, useContext, useEffect, useRef, useSyncExternalStore } from \"react\";\nimport { ReplaneContext } from \"./context\";\nimport type { UntypedReplaneConfig } from \"./types\";\nimport type { ReplaneClient, GetConfigOptions } from \"@replanejs/sdk\";\n\nexport function useReplane<T extends object = UntypedReplaneConfig>(): ReplaneClient<T> {\n const context = useContext(ReplaneContext);\n if (!context) {\n throw new Error(\"useReplane must be used within a ReplaneProvider\");\n }\n return context.client as ReplaneClient<T>;\n}\n\nexport function useConfig<T>(name: string, options?: GetConfigOptions): 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(): ReplaneClient<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\n ): TConfigs[K] {\n return useConfig<TConfigs[K]>(String(name), options);\n };\n}\n\n/**\n * Hook for creating stateful resources with cleanup support.\n * Unlike useMemo, this guarantees cleanup when dependencies change or on unmount.\n *\n * @param factory - Function that creates the resource\n * @param cleanup - Function that cleans up the resource\n * @param deps - Dependencies array (resource is recreated when these change)\n */\nexport function useStateful<T>(\n factory: () => T,\n cleanup: (value: T) => void,\n deps: React.DependencyList\n): T {\n const valueRef = useRef<T | null>(null);\n const initializedRef = useRef(false);\n\n // Create initial value synchronously on first render\n if (!initializedRef.current) {\n valueRef.current = factory();\n initializedRef.current = true;\n }\n\n useEffect(() => {\n // On mount or deps change, we may need to recreate\n // If this is not the initial mount, recreate the value\n if (valueRef.current === null) {\n valueRef.current = factory();\n }\n\n return () => {\n if (valueRef.current !== null) {\n cleanup(valueRef.current);\n valueRef.current = null;\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, deps);\n\n return valueRef.current as T;\n}\n","import type {\n ReplaneClient,\n ReplaneClientOptions,\n ReplaneSnapshot,\n} from \"@replanejs/sdk\";\nimport type { ReactNode } from \"react\";\n\nexport type UntypedReplaneConfig = Record<string, unknown>;\n\nexport interface ReplaneContextValue<T extends object = UntypedReplaneConfig> {\n client: ReplaneClient<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 ReplaneClient instance */\n client: ReplaneClient<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 ReplaneClient */\n options: ReplaneClientOptions<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","import { useMemo } from \"react\";\nimport { restoreReplaneClient } from \"@replanejs/sdk\";\nimport { ReplaneContext } from \"./context\";\nimport { useReplaneClientInternal, useReplaneClientSuspense } from \"./useReplaneClient\";\nimport { useStateful } from \"./hooks\";\nimport type {\n ReplaneProviderProps,\n ReplaneProviderWithClientProps,\n ReplaneProviderWithOptionsProps,\n ReplaneContextValue,\n} from \"./types\";\nimport { hasClient } from \"./types\";\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>>(() => ({ client }), [client]);\n return <ReplaneContext.Provider value={value}>{children}</ReplaneContext.Provider>;\n}\n\n/**\n * Internal provider component for restoring client from snapshot.\n * Uses restoreReplaneClient which is synchronous.\n */\nfunction ReplaneProviderWithSnapshot<T extends object>({\n options,\n snapshot,\n children,\n}: ReplaneProviderWithOptionsProps<T> & { snapshot: NonNullable<ReplaneProviderWithOptionsProps<T>[\"snapshot\"]> }) {\n const client = useStateful(\n () =>\n restoreReplaneClient<T>({\n snapshot,\n connection: {\n baseUrl: options.baseUrl,\n sdkKey: options.sdkKey,\n fetchFn: options.fetchFn,\n requestTimeoutMs: options.requestTimeoutMs,\n retryDelayMs: options.retryDelayMs,\n inactivityTimeoutMs: options.inactivityTimeoutMs,\n logger: options.logger,\n },\n context: options.context,\n }),\n (c) => c.close(),\n [snapshot, options]\n );\n const value = useMemo<ReplaneContextValue<T>>(() => ({ client }), [client]);\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> = { client: 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>>(() => ({ client }), [client]);\n return <ReplaneContext.Provider value={value}>{children}</ReplaneContext.Provider>;\n}\n\n/**\n * Provider component that makes a ReplaneClient available to the component tree.\n *\n * Can be used in three ways:\n *\n * 1. With a pre-created client:\n * ```tsx\n * const client = await createReplaneClient({ ... });\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"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["options: ReplaneClientOptions<T>","options?: ReplaneClientOptions<T>","name: string","options?: GetConfigOptions<T>","callback: () => void","name: K","options?: GetConfigOptions<TConfigs[K]>","factory: () => T","cleanup: (value: T) => void","deps: React.DependencyList","props: ReplaneProviderProps<T>","value: ReplaneContextValue<T>","props: ReplaneProviderProps<T>"],"sources":["../src/context.ts","../src/useReplaneClient.ts","../src/hooks.ts","../src/types.ts","../src/provider.tsx"],"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 { createReplaneClient } from \"@replanejs/sdk\";\nimport type { ReplaneClient, ReplaneClientOptions } from \"@replanejs/sdk\";\n\ntype ClientState<T extends object> =\n | { status: \"loading\"; client: null; error: null }\n | { status: \"ready\"; client: ReplaneClient<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<ReplaneClient<any>>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n result?: ReplaneClient<any>;\n error?: Error;\n }\n>();\n\nfunction getCacheKey<T extends object>(options: ReplaneClientOptions<T>): string {\n return `${options.baseUrl}:${options.sdkKey}`;\n}\n\ntype ErrorConstructor = new (message: string, options?: { cause?: unknown }) => Error;\n\n/**\n * Hook to manage ReplaneClient 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: ReplaneClientOptions<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<ReplaneClient<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 createReplaneClient<T>(optionsRef.current);\n if (cancelled) {\n client.close();\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.close();\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: ReplaneClientOptions<T>\n): ReplaneClient<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 ReplaneClient<T>;\n }\n // Still loading, throw the promise\n throw cached.promise;\n }\n\n // First time - create the promise\n const promise = createReplaneClient<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) => {\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?: ReplaneClientOptions<T>): void {\n if (options) {\n suspenseCache.delete(getCacheKey(options));\n } else {\n suspenseCache.clear();\n }\n}\n","'use client';\n\nimport { useCallback, useContext, useEffect, useRef, useSyncExternalStore } from \"react\";\nimport { ReplaneContext } from \"./context\";\nimport type { UntypedReplaneConfig } from \"./types\";\nimport type { ReplaneClient, GetConfigOptions } from \"@replanejs/sdk\";\n\nexport function useReplane<T extends object = UntypedReplaneConfig>(): ReplaneClient<T> {\n const context = useContext(ReplaneContext);\n if (!context) {\n throw new Error(\"useReplane must be used within a ReplaneProvider\");\n }\n return context.client as ReplaneClient<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(): ReplaneClient<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\n/**\n * Hook for creating stateful resources with cleanup support.\n * Unlike useMemo, this guarantees cleanup when dependencies change or on unmount.\n *\n * @param factory - Function that creates the resource\n * @param cleanup - Function that cleans up the resource\n * @param deps - Dependencies array (resource is recreated when these change)\n */\nexport function useStateful<T>(\n factory: () => T,\n cleanup: (value: T) => void,\n deps: React.DependencyList\n): T {\n const valueRef = useRef<T | null>(null);\n const initializedRef = useRef(false);\n\n // Create initial value synchronously on first render\n if (!initializedRef.current) {\n valueRef.current = factory();\n initializedRef.current = true;\n }\n\n useEffect(() => {\n // On mount or deps change, we may need to recreate\n // If this is not the initial mount, recreate the value\n if (valueRef.current === null) {\n valueRef.current = factory();\n }\n\n return () => {\n if (valueRef.current !== null) {\n cleanup(valueRef.current);\n valueRef.current = null;\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, deps);\n\n return valueRef.current as T;\n}\n","import type {\n ReplaneClient,\n ReplaneClientOptions,\n ReplaneSnapshot,\n} from \"@replanejs/sdk\";\nimport type { ReactNode } from \"react\";\n\nexport type UntypedReplaneConfig = Record<string, unknown>;\n\nexport interface ReplaneContextValue<T extends object = UntypedReplaneConfig> {\n client: ReplaneClient<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 ReplaneClient instance */\n client: ReplaneClient<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 ReplaneClient */\n options: ReplaneClientOptions<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 { useMemo } from \"react\";\nimport { restoreReplaneClient } from \"@replanejs/sdk\";\nimport { ReplaneContext } from \"./context\";\nimport { useReplaneClientInternal, useReplaneClientSuspense } from \"./useReplaneClient\";\nimport { useStateful } from \"./hooks\";\nimport type {\n ReplaneProviderProps,\n ReplaneProviderWithClientProps,\n ReplaneProviderWithOptionsProps,\n ReplaneContextValue,\n} from \"./types\";\nimport { hasClient } from \"./types\";\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>>(() => ({ client }), [client]);\n return <ReplaneContext.Provider value={value}>{children}</ReplaneContext.Provider>;\n}\n\n/**\n * Internal provider component for restoring client from snapshot.\n * Uses restoreReplaneClient which is synchronous.\n */\nfunction ReplaneProviderWithSnapshot<T extends object>({\n options,\n snapshot,\n children,\n}: ReplaneProviderWithOptionsProps<T> & { snapshot: NonNullable<ReplaneProviderWithOptionsProps<T>[\"snapshot\"]> }) {\n const client = useStateful(\n () =>\n restoreReplaneClient<T>({\n snapshot,\n connection: {\n baseUrl: options.baseUrl,\n sdkKey: options.sdkKey,\n fetchFn: options.fetchFn,\n requestTimeoutMs: options.requestTimeoutMs,\n retryDelayMs: options.retryDelayMs,\n inactivityTimeoutMs: options.inactivityTimeoutMs,\n logger: options.logger,\n },\n context: options.context,\n }),\n (c) => c.close(),\n [snapshot, options]\n );\n const value = useMemo<ReplaneContextValue<T>>(() => ({ client }), [client]);\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> = { client: 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>>(() => ({ client }), [client]);\n return <ReplaneContext.Provider value={value}>{children}</ReplaneContext.Provider>;\n}\n\n/**\n * Provider component that makes a ReplaneClient available to the component tree.\n *\n * Can be used in three ways:\n *\n * 1. With a pre-created client:\n * ```tsx\n * const client = await createReplaneClient({ ... });\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"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@replanejs/react",
3
- "version": "0.7.8",
3
+ "version": "0.8.1",
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.7.8"
43
+ "@replanejs/sdk": "^0.8.1"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@testing-library/jest-dom": "^6.9.1",