@replanejs/react 0.8.20 → 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,29 +73,44 @@ 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 all options from `@replanejs/sdk`. Key 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) |
79
88
 
80
- | Option | Type | Required | Description |
81
- | ------------------------- | ---------------------- | -------- | ------------------------------------------ |
82
- | `baseUrl` | `string` | Yes | Replane server URL |
83
- | `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
- | `required` | `string[]` or `object` | No | Configs that must exist for initialization |
87
- | `initializationTimeoutMs` | `number` | No | SDK initialization timeout (default: 5000) |
89
+ #### Connection Options
88
90
 
89
- See [`@replanejs/sdk` documentation](https://github.com/replane-dev/replane-javascript/tree/main/packages/sdk#options) for the complete list of options.
91
+ The `connection` prop accepts the following options:
92
+
93
+ | Option | Type | Required | Description |
94
+ | -------------------- | --------------------- | -------- | -------------------------------------------- |
95
+ | `baseUrl` | `string` | Yes | Replane server URL |
96
+ | `sdkKey` | `string` | Yes | SDK key for authentication |
97
+ | `connectTimeoutMs` | `number` | No | SDK connection timeout (default: 5000) |
98
+ | `requestTimeoutMs` | `number` | No | Timeout for SSE requests (default: 2000) |
99
+ | `retryDelayMs` | `number` | No | Base delay between retries (default: 200) |
100
+ | `inactivityTimeoutMs`| `number` | No | SSE inactivity timeout (default: 30000) |
101
+ | `fetchFn` | `typeof fetch` | No | Custom fetch implementation |
102
+
103
+ See [`@replanejs/sdk` documentation](https://github.com/replane-dev/replane-javascript/tree/main/packages/sdk#api) for more details.
90
104
 
91
105
  #### 2. With pre-created client
92
106
 
93
107
  Use this when you need more control over client lifecycle:
94
108
 
95
109
  ```tsx
96
- import { createReplaneClient } from "@replanejs/sdk";
110
+ import { Replane } from "@replanejs/sdk";
97
111
 
98
- const client = await createReplaneClient({
112
+ const client = new Replane();
113
+ await client.connect({
99
114
  baseUrl: "https://your-replane-server.com",
100
115
  sdkKey: "your-sdk-key",
101
116
  });
@@ -113,7 +128,7 @@ Integrates with React Suspense for loading states:
113
128
  <ErrorBoundary fallback={<div>Failed to load configuration</div>}>
114
129
  <Suspense fallback={<LoadingSpinner />}>
115
130
  <ReplaneProvider
116
- options={{
131
+ connection={{
117
132
  baseUrl: "https://your-replane-server.com",
118
133
  sdkKey: "your-sdk-key",
119
134
  }}
@@ -125,32 +140,47 @@ Integrates with React Suspense for loading states:
125
140
  </ErrorBoundary>
126
141
  ```
127
142
 
128
- #### 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)
129
161
 
130
162
  Restore a client from a snapshot obtained on the server. This is synchronous and useful for SSR scenarios:
131
163
 
132
164
  ```tsx
133
165
  // On the server
134
- const serverClient = await createReplaneClient({ baseUrl: "...", sdkKey: "..." });
166
+ const serverClient = new Replane();
167
+ await serverClient.connect({ baseUrl: "...", sdkKey: "..." });
135
168
  const snapshot = serverClient.getSnapshot();
136
169
  // Pass snapshot to client via props, context, or serialized HTML
137
170
 
138
171
  // On the client
139
172
  <ReplaneProvider
140
- restoreOptions={{
141
- snapshot,
142
- // Optional: connect for live updates
143
- connection: {
144
- baseUrl: "https://your-replane-server.com",
145
- sdkKey: "your-sdk-key",
146
- },
173
+ connection={{
174
+ baseUrl: "https://your-replane-server.com",
175
+ sdkKey: "your-sdk-key",
147
176
  }}
177
+ snapshot={snapshot}
148
178
  >
149
179
  <App />
150
180
  </ReplaneProvider>;
151
181
  ```
152
182
 
153
- 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.
183
+ The restored client is immediately available with no loading state. The provider will establish a connection for real-time updates in the background.
154
184
 
155
185
  ### useConfig
156
186
 
@@ -350,7 +380,7 @@ class ErrorBoundary extends Component<
350
380
 
351
381
  // Usage
352
382
  <ErrorBoundary fallback={<div>Configuration failed to load</div>}>
353
- <ReplaneProvider options={options} loader={<Loading />}>
383
+ <ReplaneProvider connection={connection} loader={<Loading />}>
354
384
  <App />
355
385
  </ReplaneProvider>
356
386
  </ErrorBoundary>;
@@ -370,7 +400,7 @@ import { ErrorBoundary } from "react-error-boundary";
370
400
  )}
371
401
  onReset={() => clearSuspenseCache()}
372
402
  >
373
- <ReplaneProvider options={options} loader={<Loading />}>
403
+ <ReplaneProvider connection={connection} loader={<Loading />}>
374
404
  <App />
375
405
  </ReplaneProvider>
376
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.8.20";
37
- const DEFAULT_AGENT = `replane-js-react/${VERSION}`;
38
-
39
34
  //#endregion
40
35
  //#region src/useReplaneClient.ts
41
36
  const suspenseCache = new Map();
@@ -43,10 +38,23 @@ function getCacheKey(options) {
43
38
  return `${options.baseUrl}:${options.sdkKey}`;
44
39
  }
45
40
  /**
46
- * Hook to manage ReplaneClient creation internally.
41
+ * Creates a Replane client and connects it.
42
+ */
43
+ async function createAndConnectClient(options, connection) {
44
+ const client = new __replanejs_sdk.Replane({
45
+ logger: options.logger,
46
+ context: options.context,
47
+ defaults: options.defaults
48
+ });
49
+ if (!connection) return client;
50
+ await client.connect(connection);
51
+ return client;
52
+ }
53
+ /**
54
+ * Hook to manage Replane client creation internally.
47
55
  * Handles loading state and cleanup.
48
56
  */
49
- function useReplaneClientInternal(options) {
57
+ function useReplaneClientInternal(options, originalConnection) {
50
58
  const [state, setState] = (0, react.useState)({
51
59
  status: "loading",
52
60
  client: null,
@@ -54,16 +62,15 @@ function useReplaneClientInternal(options) {
54
62
  });
55
63
  const clientRef = (0, react.useRef)(null);
56
64
  const optionsRef = (0, react.useRef)(options);
65
+ const connectionJson = JSON.stringify(originalConnection);
57
66
  (0, react.useEffect)(() => {
67
+ const connection = JSON.parse(connectionJson);
58
68
  let cancelled = false;
59
69
  async function initClient() {
60
70
  try {
61
- const client = await (0, __replanejs_sdk.createReplaneClient)({
62
- ...optionsRef.current,
63
- agent: optionsRef.current.agent ?? DEFAULT_AGENT
64
- });
71
+ const client = await createAndConnectClient(optionsRef.current, connection);
65
72
  if (cancelled) {
66
- client.close();
73
+ client.disconnect();
67
74
  return;
68
75
  }
69
76
  clientRef.current = client;
@@ -86,29 +93,26 @@ function useReplaneClientInternal(options) {
86
93
  return () => {
87
94
  cancelled = true;
88
95
  if (clientRef.current) {
89
- clientRef.current.close();
96
+ clientRef.current.disconnect();
90
97
  clientRef.current = null;
91
98
  }
92
99
  };
93
- }, []);
100
+ }, [connectionJson]);
94
101
  return state;
95
102
  }
96
103
  /**
97
104
  * Hook for Suspense-based client creation.
98
105
  * Throws a promise while loading, throws error on failure.
99
106
  */
100
- function useReplaneClientSuspense(options) {
101
- const cacheKey = getCacheKey(options);
107
+ function useReplaneClientSuspense(options, connection) {
108
+ const cacheKey = getCacheKey(connection);
102
109
  const cached = suspenseCache.get(cacheKey);
103
110
  if (cached) {
104
111
  if (cached.error) throw cached.error;
105
112
  if (cached.result) return cached.result;
106
113
  throw cached.promise;
107
114
  }
108
- const promise = (0, __replanejs_sdk.createReplaneClient)({
109
- ...options,
110
- agent: options.agent ?? DEFAULT_AGENT
111
- }).then((client) => {
115
+ const promise = createAndConnectClient(options, connection).then((client) => {
112
116
  const entry = suspenseCache.get(cacheKey);
113
117
  if (entry) entry.result = client;
114
118
  return client;
@@ -121,150 +125,59 @@ function useReplaneClientSuspense(options) {
121
125
  throw promise;
122
126
  }
123
127
  /**
124
- * Clear the suspense cache for a specific options configuration.
128
+ * Clear the suspense cache for a specific connection configuration.
125
129
  * Useful for testing or when you need to force re-initialization.
126
130
  */
127
- function clearSuspenseCache(options) {
128
- if (options) suspenseCache.delete(getCacheKey(options));
131
+ function clearSuspenseCache(connection) {
132
+ if (connection) suspenseCache.delete(getCacheKey(connection));
129
133
  else suspenseCache.clear();
130
134
  }
131
135
 
132
- //#endregion
133
- //#region src/hooks.ts
134
- function useReplane() {
135
- const context = (0, react.useContext)(ReplaneContext);
136
- if (!context) throw new Error("useReplane must be used within a ReplaneProvider");
137
- return context.client;
138
- }
139
- function useConfig(name, options) {
140
- const client = useReplane();
141
- const subscribe = (0, react.useCallback)((callback) => {
142
- return client.subscribe(name, callback);
143
- }, [client, name]);
144
- const get = (0, react.useCallback)(() => {
145
- return client.get(name, options);
146
- }, [
147
- client,
148
- name,
149
- options
150
- ]);
151
- const value = (0, react.useSyncExternalStore)(subscribe, get, get);
152
- return value;
153
- }
154
- /**
155
- * Creates a typed version of useReplane hook.
156
- *
157
- * @example
158
- * ```tsx
159
- * interface AppConfigs {
160
- * theme: { darkMode: boolean };
161
- * features: { beta: boolean };
162
- * }
163
- *
164
- * const useAppReplane = createReplaneHook<AppConfigs>();
165
- *
166
- * function MyComponent() {
167
- * const replane = useAppReplane();
168
- * // replane.get("theme") returns { darkMode: boolean }
169
- * }
170
- * ```
171
- */
172
- function createReplaneHook() {
173
- return function useTypedReplane() {
174
- return useReplane();
175
- };
176
- }
177
- /**
178
- * Creates a typed version of useConfig hook.
179
- *
180
- * @example
181
- * ```tsx
182
- * interface AppConfigs {
183
- * theme: { darkMode: boolean };
184
- * features: { beta: boolean };
185
- * }
186
- *
187
- * const useAppConfig = createConfigHook<AppConfigs>();
188
- *
189
- * function MyComponent() {
190
- * const theme = useAppConfig("theme");
191
- * // theme is typed as { darkMode: boolean }
192
- * }
193
- * ```
194
- */
195
- function createConfigHook() {
196
- return function useTypedConfig(name, options) {
197
- return useConfig(String(name), options);
198
- };
199
- }
200
- /**
201
- * Hook for creating stateful resources with cleanup support.
202
- * Unlike useMemo, this guarantees cleanup when dependencies change or on unmount.
203
- *
204
- * @param factory - Function that creates the resource
205
- * @param cleanup - Function that cleans up the resource
206
- * @param deps - Dependencies array (resource is recreated when these change)
207
- */
208
- function useStateful(factory, cleanup, deps) {
209
- const valueRef = (0, react.useRef)(null);
210
- const initializedRef = (0, react.useRef)(false);
211
- if (!initializedRef.current) {
212
- valueRef.current = factory();
213
- initializedRef.current = true;
214
- }
215
- (0, react.useEffect)(() => {
216
- if (valueRef.current === null) valueRef.current = factory();
217
- return () => {
218
- if (valueRef.current !== null) {
219
- cleanup(valueRef.current);
220
- valueRef.current = null;
221
- }
222
- };
223
- }, deps);
224
- return valueRef.current;
225
- }
226
-
227
136
  //#endregion
228
137
  //#region src/types.ts
229
138
  /**
230
139
  * Type guard to check if props contain a pre-created client.
231
140
  */
232
141
  function hasClient(props) {
233
- return "client" in props && props.client !== void 0;
142
+ return "client" in props && !!props.client;
234
143
  }
235
144
 
145
+ //#endregion
146
+ //#region src/version.ts
147
+ const VERSION = "0.9.2";
148
+ const DEFAULT_AGENT = `replane-js-react/${VERSION}`;
149
+
236
150
  //#endregion
237
151
  //#region src/provider.tsx
238
152
  /**
239
153
  * Internal provider component for pre-created client.
240
154
  */
241
155
  function ReplaneProviderWithClient({ client, children }) {
242
- const value = (0, react.useMemo)(() => ({ client }), [client]);
156
+ const value = (0, react.useMemo)(() => ({ replane: client }), [client]);
243
157
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReplaneContext.Provider, {
244
158
  value,
245
159
  children
246
160
  });
247
161
  }
248
162
  /**
249
- * Internal provider component for restoring client from snapshot.
250
- * Uses restoreReplaneClient which is synchronous.
163
+ * Internal provider component for creating a Replane client asynchronously.
164
+ * Creates a Replane client synchronously and connects in background.
251
165
  */
252
- function ReplaneProviderWithSnapshot({ options, snapshot, children }) {
253
- const client = useStateful(() => (0, __replanejs_sdk.restoreReplaneClient)({
254
- snapshot,
255
- connection: {
256
- baseUrl: options.baseUrl,
257
- sdkKey: options.sdkKey,
258
- fetchFn: options.fetchFn,
259
- requestTimeoutMs: options.requestTimeoutMs,
260
- retryDelayMs: options.retryDelayMs,
261
- inactivityTimeoutMs: options.inactivityTimeoutMs,
262
- logger: options.logger,
263
- agent: options.agent ?? DEFAULT_AGENT
264
- },
265
- context: options.context
266
- }), (c) => c.close(), [snapshot, options]);
267
- const value = (0, react.useMemo)(() => ({ client }), [client]);
166
+ function AsyncReplaneProvider({ children, connection,...options }) {
167
+ const replaneRef = (0, react.useRef)(void 0);
168
+ if (!replaneRef.current) replaneRef.current = new __replanejs_sdk.Replane(options);
169
+ const connectionJson = connection ? JSON.stringify(connection) : void 0;
170
+ (0, react.useEffect)(() => {
171
+ const parsedConnection = connectionJson ? JSON.parse(connectionJson) : void 0;
172
+ if (!parsedConnection) return;
173
+ replaneRef.current.connect(parsedConnection).catch((err) => {
174
+ (options.logger ?? console)?.error("Failed to connect Replane client", err);
175
+ });
176
+ return () => {
177
+ replaneRef.current.disconnect();
178
+ };
179
+ }, [connectionJson, options.logger]);
180
+ const value = (0, react.useMemo)(() => ({ replane: replaneRef.current }), []);
268
181
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReplaneContext.Provider, {
269
182
  value,
270
183
  children
@@ -274,11 +187,12 @@ function ReplaneProviderWithSnapshot({ options, snapshot, children }) {
274
187
  * Internal provider component for options-based client creation (non-suspense).
275
188
  * Throws errors during rendering so they can be caught by Error Boundaries.
276
189
  */
277
- function ReplaneProviderWithOptions({ options, children, loader }) {
278
- 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);
279
193
  if (state.status === "loading") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: loader ?? null });
280
194
  if (state.status === "error") throw state.error;
281
- const value = { client: state.client };
195
+ const value = { replane: state.client };
282
196
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReplaneContext.Provider, {
283
197
  value,
284
198
  children
@@ -287,22 +201,24 @@ function ReplaneProviderWithOptions({ options, children, loader }) {
287
201
  /**
288
202
  * Internal provider component for options-based client creation with Suspense.
289
203
  */
290
- function ReplaneProviderWithSuspense({ options, children }) {
291
- const client = useReplaneClientSuspense(options);
292
- const value = (0, react.useMemo)(() => ({ client }), [client]);
204
+ function SuspenseReplaneProvider({ connection, children,...options }) {
205
+ if (!connection) throw new Error("Connection is required when using Suspense");
206
+ const client = useReplaneClientSuspense(options, connection);
207
+ const value = (0, react.useMemo)(() => ({ replane: client }), [client]);
293
208
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReplaneContext.Provider, {
294
209
  value,
295
210
  children
296
211
  });
297
212
  }
298
213
  /**
299
- * Provider component that makes a ReplaneClient available to the component tree.
214
+ * Provider component that makes a Replane client available to the component tree.
300
215
  *
301
- * Can be used in three ways:
216
+ * Can be used in several ways:
302
217
  *
303
218
  * 1. With a pre-created client:
304
219
  * ```tsx
305
- * const client = await createReplaneClient({ ... });
220
+ * const client = new Replane({ defaults: { ... } });
221
+ * await client.connect({ baseUrl: '...', sdkKey: '...' });
306
222
  * <ReplaneProvider client={client}>
307
223
  * <App />
308
224
  * </ReplaneProvider>
@@ -352,16 +268,111 @@ function ReplaneProviderWithSuspense({ options, children }) {
352
268
  * allowing them to be caught by React Error Boundaries.
353
269
  */
354
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]);
355
276
  if (hasClient(props)) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReplaneProviderWithClient, { ...props });
356
- 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, {
357
279
  ...props,
358
- snapshot: props.snapshot
280
+ connection
359
281
  });
360
- if (props.suspense) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReplaneProviderWithSuspense, { ...props });
361
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReplaneProviderWithOptions, { ...props });
282
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LoaderReplaneProvider, {
283
+ ...props,
284
+ connection
285
+ });
286
+ }
287
+
288
+ //#endregion
289
+ //#region src/hooks.ts
290
+ function useReplane() {
291
+ const context = (0, react.useContext)(ReplaneContext);
292
+ if (!context) throw new Error("useReplane must be used within a ReplaneProvider");
293
+ return context.replane;
294
+ }
295
+ function useConfig(name, options) {
296
+ const client = useReplane();
297
+ const subscribe = (0, react.useCallback)((callback) => {
298
+ return client.subscribe(name, callback);
299
+ }, [client, name]);
300
+ const get = (0, react.useCallback)(() => {
301
+ return client.get(name, options);
302
+ }, [
303
+ client,
304
+ name,
305
+ options
306
+ ]);
307
+ const value = (0, react.useSyncExternalStore)(subscribe, get, get);
308
+ return value;
309
+ }
310
+ /**
311
+ * Creates a typed version of useReplane hook.
312
+ *
313
+ * @example
314
+ * ```tsx
315
+ * interface AppConfigs {
316
+ * theme: { darkMode: boolean };
317
+ * features: { beta: boolean };
318
+ * }
319
+ *
320
+ * const useAppReplane = createReplaneHook<AppConfigs>();
321
+ *
322
+ * function MyComponent() {
323
+ * const replane = useAppReplane();
324
+ * // replane.get("theme") returns { darkMode: boolean }
325
+ * }
326
+ * ```
327
+ */
328
+ function createReplaneHook() {
329
+ return function useTypedReplane() {
330
+ return useReplane();
331
+ };
332
+ }
333
+ /**
334
+ * Creates a typed version of useConfig hook.
335
+ *
336
+ * @example
337
+ * ```tsx
338
+ * interface AppConfigs {
339
+ * theme: { darkMode: boolean };
340
+ * features: { beta: boolean };
341
+ * }
342
+ *
343
+ * const useAppConfig = createConfigHook<AppConfigs>();
344
+ *
345
+ * function MyComponent() {
346
+ * const theme = useAppConfig("theme");
347
+ * // theme is typed as { darkMode: boolean }
348
+ * }
349
+ * ```
350
+ */
351
+ function createConfigHook() {
352
+ return function useTypedConfig(name, options) {
353
+ return useConfig(String(name), options);
354
+ };
362
355
  }
363
356
 
364
357
  //#endregion
358
+ Object.defineProperty(exports, 'Replane', {
359
+ enumerable: true,
360
+ get: function () {
361
+ return __replanejs_sdk.Replane;
362
+ }
363
+ });
364
+ Object.defineProperty(exports, 'ReplaneError', {
365
+ enumerable: true,
366
+ get: function () {
367
+ return __replanejs_sdk.ReplaneError;
368
+ }
369
+ });
370
+ Object.defineProperty(exports, 'ReplaneErrorCode', {
371
+ enumerable: true,
372
+ get: function () {
373
+ return __replanejs_sdk.ReplaneErrorCode;
374
+ }
375
+ });
365
376
  exports.ReplaneProvider = ReplaneProvider;
366
377
  exports.clearSuspenseCache = clearSuspenseCache;
367
378
  exports.createConfigHook = createConfigHook;