@replanejs/react 0.1.1 → 0.7.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 ADDED
@@ -0,0 +1,185 @@
1
+ # @replanejs/react
2
+
3
+ React SDK for [Replane](https://github.com/replane-dev/replane-javascript) - feature flags and remote configuration.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @replanejs/react
9
+ # or
10
+ pnpm add @replanejs/react
11
+ # or
12
+ yarn add @replanejs/react
13
+ ```
14
+
15
+ ## Requirements
16
+
17
+ - React 18.0.0 or higher
18
+ - Node.js 18.0.0 or higher
19
+
20
+ ## Quick Start
21
+
22
+ ```tsx
23
+ import { ReplaneProvider, useConfig } from '@replanejs/react';
24
+
25
+ function App() {
26
+ return (
27
+ <ReplaneProvider
28
+ options={{
29
+ baseUrl: 'https://your-replane-server.com',
30
+ sdkKey: 'your-sdk-key',
31
+ }}
32
+ loader={<div>Loading...</div>}
33
+ >
34
+ <MyComponent />
35
+ </ReplaneProvider>
36
+ );
37
+ }
38
+
39
+ function MyComponent() {
40
+ const isFeatureEnabled = useConfig<boolean>('feature-flag-name');
41
+
42
+ return (
43
+ <div>
44
+ {isFeatureEnabled ? 'Feature is enabled!' : 'Feature is disabled'}
45
+ </div>
46
+ );
47
+ }
48
+ ```
49
+
50
+ ## API
51
+
52
+ ### ReplaneProvider
53
+
54
+ Provider component that makes the Replane client available to your component tree. Supports three usage patterns:
55
+
56
+ #### 1. With options (recommended)
57
+
58
+ The provider creates and manages the client internally:
59
+
60
+ ```tsx
61
+ <ReplaneProvider
62
+ options={{
63
+ baseUrl: 'https://your-replane-server.com',
64
+ sdkKey: 'your-sdk-key',
65
+ }}
66
+ loader={<LoadingSpinner />}
67
+ onError={(error) => console.error('Failed to initialize:', error)}
68
+ >
69
+ <App />
70
+ </ReplaneProvider>
71
+ ```
72
+
73
+ #### 2. With pre-created client
74
+
75
+ Use this when you need more control over client lifecycle:
76
+
77
+ ```tsx
78
+ import { createReplaneClient } from '@replanejs/sdk';
79
+
80
+ const client = await createReplaneClient({
81
+ baseUrl: 'https://your-replane-server.com',
82
+ sdkKey: 'your-sdk-key',
83
+ });
84
+
85
+ <ReplaneProvider client={client}>
86
+ <App />
87
+ </ReplaneProvider>
88
+ ```
89
+
90
+ #### 3. With Suspense
91
+
92
+ Integrates with React Suspense for loading states:
93
+
94
+ ```tsx
95
+ <Suspense fallback={<LoadingSpinner />}>
96
+ <ReplaneProvider
97
+ options={{
98
+ baseUrl: 'https://your-replane-server.com',
99
+ sdkKey: 'your-sdk-key',
100
+ }}
101
+ suspense
102
+ >
103
+ <App />
104
+ </ReplaneProvider>
105
+ </Suspense>
106
+ ```
107
+
108
+ ### useConfig
109
+
110
+ Hook to retrieve a configuration value. Automatically subscribes to updates and re-renders when the value changes.
111
+
112
+ ```tsx
113
+ function MyComponent() {
114
+ // Basic usage
115
+ const theme = useConfig<string>('theme');
116
+
117
+ // With evaluation context
118
+ const discount = useConfig<number>('discount-percentage', {
119
+ context: {
120
+ userId: '123',
121
+ isPremium: true,
122
+ },
123
+ });
124
+
125
+ return <div>Theme: {theme}, Discount: {discount}%</div>;
126
+ }
127
+ ```
128
+
129
+ ### useReplane
130
+
131
+ Hook to access the underlying Replane client directly:
132
+
133
+ ```tsx
134
+ function MyComponent() {
135
+ const { client } = useReplane();
136
+
137
+ const handleClick = () => {
138
+ // Access client methods directly
139
+ const value = client.get('some-config');
140
+ console.log(value);
141
+ };
142
+
143
+ return <button onClick={handleClick}>Get Config</button>;
144
+ }
145
+ ```
146
+
147
+ ### clearSuspenseCache
148
+
149
+ Utility function to clear the suspense cache. Useful for testing or forcing re-initialization:
150
+
151
+ ```tsx
152
+ import { clearSuspenseCache } from '@replanejs/react';
153
+
154
+ // Clear cache for specific options
155
+ clearSuspenseCache({
156
+ baseUrl: 'https://your-replane-server.com',
157
+ sdkKey: 'your-sdk-key',
158
+ });
159
+
160
+ // Clear entire cache
161
+ clearSuspenseCache();
162
+ ```
163
+
164
+ ## TypeScript
165
+
166
+ The SDK is fully typed. You can provide a type parameter to get type-safe configuration values:
167
+
168
+ ```tsx
169
+ interface MyConfig {
170
+ theme: 'light' | 'dark';
171
+ maxItems: number;
172
+ features: {
173
+ analytics: boolean;
174
+ notifications: boolean;
175
+ };
176
+ }
177
+
178
+ // Type-safe hooks
179
+ const { client } = useReplane<MyConfig>();
180
+ const theme = useConfig<MyConfig['theme']>('theme');
181
+ ```
182
+
183
+ ## License
184
+
185
+ MIT
package/dist/index.d.cts CHANGED
@@ -82,7 +82,7 @@ declare function ReplaneProvider<T extends object>(props: ReplaneProviderProps<T
82
82
  //# sourceMappingURL=provider.d.ts.map
83
83
  //#endregion
84
84
  //#region src/hooks.d.ts
85
- declare function useReplane<T extends object = any>(): ReplaneContextValue<T>;
85
+ declare function useReplane<T extends object = Record<string, unknown>>(): ReplaneContextValue<T>;
86
86
  declare function useConfig<T>(name: string, options?: {
87
87
  context?: Record<string, string | number | boolean | null>;
88
88
  }): T;
@@ -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":";;;;;UAIiB;UACP,cAAc;;AADxB;;;AACU,UAOO,8BAPP,CAAA,UAAA,MAAA,GAAA,GAAA,CAAA,CAAA;EAAa;EAON,MAAA,EAEP,aAFO,CAEO,CAFP,CAAA;EAA8B,QAAA,EAGnC,SAHmC;;;;AAG1B;AAOJ,UAAA,+BAA+B,CAAA,UAAA,MAAA,GAAA,GAAA,CAAA,CAAA;EAAA;EAAA,OAEhB,EAArB,oBAAqB,CAAA,CAAA,CAAA;EAAC,QAAtB,EACC,SADD;EAAoB;;;AAgBN;EAIb,MAAA,CAAA,EAdD,SAcC;EAAoB;;;;;EAEG,QAAA,CAAA,EAAA,OAAA;;;;ECgDnB,OAAA,CAAA,EAAA,CAAA,KAAA,EDtDI,KCsDW,EAAA,GAAA,IAAA;;AAA+C,KDlDlE,oBCkDkE,CAAA,UAAA,MAAA,GAAA,GAAA,CAAA,GDjD1E,8BCiD0E,CDjD3C,CCiD2C,CAAA,GDhD1E,+BCgD0E,CDhD1C,CCgD0C,CAAA;;;AAAE;;;;;;;AD1FhF;;;;AACuB;AAOvB;;;;;AAGqB;AAOrB;;;;;;;AAkByB;AAIzB;;;;;;AAEmC;;;;ACgDnC;;AAA8E,iBAA9D,eAA8D,CAAA,UAAA,MAAA,CAAA,CAAA,KAAA,EAArB,oBAAqB,CAAA,CAAA,CAAA,CAAA,EAAE,kBAAA,CAAA,GAAA,CAAA,OAAF;;;;iBCzF9D,sCAAsC,oBAAoB;iBAQ1D;YAEQ;IACrB;AFZH;;;;AAwCA;;;;AAEoC,iBGgFpB,kBHhFoB,CAAA,UAAA,MAAA,CAAA,CAAA,OAAA,CAAA,EGgF2B,oBHhF3B,CGgFgD,CHhFhD,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":";;;;;UAIiB;UACP,cAAc;;AADxB;;;AACU,UAOO,8BAPP,CAAA,UAAA,MAAA,GAAA,GAAA,CAAA,CAAA;EAAa;EAON,MAAA,EAEP,aAFO,CAEO,CAFP,CAAA;EAA8B,QAAA,EAGnC,SAHmC;;;;AAG1B;AAOJ,UAAA,+BAA+B,CAAA,UAAA,MAAA,GAAA,GAAA,CAAA,CAAA;EAAA;EAAA,OAEhB,EAArB,oBAAqB,CAAA,CAAA,CAAA;EAAC,QAAtB,EACC,SADD;EAAoB;;;AAgBN;EAIb,MAAA,CAAA,EAdD,SAcC;EAAoB;;;;;EAEG,QAAA,CAAA,EAAA,OAAA;;;;ECgDnB,OAAA,CAAA,EAAA,CAAA,KAAA,EDtDI,KCsDW,EAAA,GAAA,IAAA;;AAA+C,KDlDlE,oBCkDkE,CAAA,UAAA,MAAA,GAAA,GAAA,CAAA,GDjD1E,8BCiD0E,CDjD3C,CCiD2C,CAAA,GDhD1E,+BCgD0E,CDhD1C,CCgD0C,CAAA;;;AAAE;;;;;;;AD1FhF;;;;AACuB;AAOvB;;;;;AAGqB;AAOrB;;;;;;;AAkByB;AAIzB;;;;;;AAEmC;;;;ACgDnC;;AAA8E,iBAA9D,eAA8D,CAAA,UAAA,MAAA,CAAA,CAAA,KAAA,EAArB,oBAAqB,CAAA,CAAA,CAAA,CAAA,EAAE,kBAAA,CAAA,GAAA,CAAA,OAAF;;;;iBC1F9D,8BAA8B,4BAA4B,oBAAoB;iBAQ9E;YAEQ;IACrB;AFXH;;;;AAwCA;;;;AAEoC,iBGgFpB,kBHhFoB,CAAA,UAAA,MAAA,CAAA,CAAA,OAAA,CAAA,EGgF2B,oBHhF3B,CGgFgD,CHhFhD,CAAA,CAAA,EAAA,IAAA"}
package/dist/index.d.ts CHANGED
@@ -82,7 +82,7 @@ declare function ReplaneProvider<T extends object>(props: ReplaneProviderProps<T
82
82
  //# sourceMappingURL=provider.d.ts.map
83
83
  //#endregion
84
84
  //#region src/hooks.d.ts
85
- declare function useReplane<T extends object = any>(): ReplaneContextValue<T>;
85
+ declare function useReplane<T extends object = Record<string, unknown>>(): ReplaneContextValue<T>;
86
86
  declare function useConfig<T>(name: string, options?: {
87
87
  context?: Record<string, string | number | boolean | null>;
88
88
  }): T;
@@ -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":";;;;;UAIiB;UACP,cAAc;;AADxB;;;AACU,UAOO,8BAPP,CAAA,UAAA,MAAA,GAAA,GAAA,CAAA,CAAA;EAAa;EAON,MAAA,EAEP,aAFO,CAEO,CAFP,CAAA;EAA8B,QAAA,EAGnC,SAHmC;;;;AAG1B;AAOJ,UAAA,+BAA+B,CAAA,UAAA,MAAA,GAAA,GAAA,CAAA,CAAA;EAAA;EAAA,OAEhB,EAArB,oBAAqB,CAAA,CAAA,CAAA;EAAC,QAAtB,EACC,SADD;EAAoB;;;AAgBN;EAIb,MAAA,CAAA,EAdD,SAcC;EAAoB;;;;;EAEG,QAAA,CAAA,EAAA,OAAA;;;;ECgDnB,OAAA,CAAA,EAAA,CAAA,KAAA,EDtDI,KCsDW,EAAA,GAAA,IAAA;;AAA+C,KDlDlE,oBCkDkE,CAAA,UAAA,MAAA,GAAA,GAAA,CAAA,GDjD1E,8BCiD0E,CDjD3C,CCiD2C,CAAA,GDhD1E,+BCgD0E,CDhD1C,CCgD0C,CAAA;;;AAAE;;;;;;;AD1FhF;;;;AACuB;AAOvB;;;;;AAGqB;AAOrB;;;;;;;AAkByB;AAIzB;;;;;;AAEmC;;;;ACgDnC;;AAA8E,iBAA9D,eAA8D,CAAA,UAAA,MAAA,CAAA,CAAA,KAAA,EAArB,oBAAqB,CAAA,CAAA,CAAA,CAAA,EAAE,kBAAA,CAAA,GAAA,CAAA,OAAF;;;;iBCzF9D,sCAAsC,oBAAoB;iBAQ1D;YAEQ;IACrB;AFZH;;;;AAwCA;;;;AAEoC,iBGgFpB,kBHhFoB,CAAA,UAAA,MAAA,CAAA,CAAA,OAAA,CAAA,EGgF2B,oBHhF3B,CGgFgD,CHhFhD,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":";;;;;UAIiB;UACP,cAAc;;AADxB;;;AACU,UAOO,8BAPP,CAAA,UAAA,MAAA,GAAA,GAAA,CAAA,CAAA;EAAa;EAON,MAAA,EAEP,aAFO,CAEO,CAFP,CAAA;EAA8B,QAAA,EAGnC,SAHmC;;;;AAG1B;AAOJ,UAAA,+BAA+B,CAAA,UAAA,MAAA,GAAA,GAAA,CAAA,CAAA;EAAA;EAAA,OAEhB,EAArB,oBAAqB,CAAA,CAAA,CAAA;EAAC,QAAtB,EACC,SADD;EAAoB;;;AAgBN;EAIb,MAAA,CAAA,EAdD,SAcC;EAAoB;;;;;EAEG,QAAA,CAAA,EAAA,OAAA;;;;ECgDnB,OAAA,CAAA,EAAA,CAAA,KAAA,EDtDI,KCsDW,EAAA,GAAA,IAAA;;AAA+C,KDlDlE,oBCkDkE,CAAA,UAAA,MAAA,GAAA,GAAA,CAAA,GDjD1E,8BCiD0E,CDjD3C,CCiD2C,CAAA,GDhD1E,+BCgD0E,CDhD1C,CCgD0C,CAAA;;;AAAE;;;;;;;AD1FhF;;;;AACuB;AAOvB;;;;;AAGqB;AAOrB;;;;;;;AAkByB;AAIzB;;;;;;AAEmC;;;;ACgDnC;;AAA8E,iBAA9D,eAA8D,CAAA,UAAA,MAAA,CAAA,CAAA,KAAA,EAArB,oBAAqB,CAAA,CAAA,CAAA,CAAA,EAAE,kBAAA,CAAA,GAAA,CAAA,OAAF;;;;iBC1F9D,8BAA8B,4BAA4B,oBAAoB;iBAQ9E;YAEQ;IACrB;AFXH;;;;AAwCA;;;;AAEoC,iBGgFpB,kBHhFoB,CAAA,UAAA,MAAA,CAAA,CAAA,OAAA,CAAA,EGgF2B,oBHhF3B,CGgFgD,CHhFhD,CAAA,CAAA,EAAA,IAAA"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["options: ReplaneClientOptions<T>","onError?: (error: Error) => void","options?: ReplaneClientOptions<T>","props: ReplaneProviderProps<T>","value: ReplaneContextValue<T>","props: ReplaneProviderProps<T>","name: string","options?: { context?: Record<string, string | number | boolean | null> }"],"sources":["../src/context.ts","../src/useReplaneClient.ts","../src/types.ts","../src/provider.tsx","../src/hooks.ts"],"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\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 useReplaneClient<T extends object = any>(\n options: ReplaneClientOptions<T>,\n onError?: (error: Error) => void\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 = err instanceof Error ? err : new Error(String(err));\n setState({ status: \"error\", client: null, error });\n onError?.(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 // We intentionally only run this effect once on mount\n // Options changes would require remounting the provider\n // eslint-disable-next-line react-hooks/exhaustive-deps\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 type { ReplaneClient, ReplaneClientOptions } from \"@replanejs/sdk\";\nimport type { ReactNode } from \"react\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface ReplaneContextValue<T extends object = any> {\n client: ReplaneClient<T>;\n}\n\n/**\n * Props for ReplaneProvider when using a pre-created client.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface ReplaneProviderWithClientProps<T extends object = any> {\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 */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface ReplaneProviderWithOptionsProps<T extends object = any> {\n /** Options to create the ReplaneClient */\n options: ReplaneClientOptions<T>;\n children: ReactNode;\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 */\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 * @default false\n */\n suspense?: boolean;\n /**\n * Callback when client initialization fails.\n */\n onError?: (error: Error) => void;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type ReplaneProviderProps<T extends object = any> =\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","import { useMemo } from \"react\";\nimport { ReplaneContext } from \"./context\";\nimport { useReplaneClient, useReplaneClientSuspense } from \"./useReplaneClient\";\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 options-based client creation (non-suspense).\n */\nfunction ReplaneProviderWithOptions<T extends object>({\n options,\n children,\n loader,\n onError,\n}: ReplaneProviderWithOptionsProps<T>) {\n const state = useReplaneClient<T>(options, onError);\n\n if (state.status === \"loading\") {\n return <>{loader ?? null}</>;\n }\n\n if (state.status === \"error\") {\n // Error was already reported via onError callback\n // Return loader or null to prevent rendering children without a client\n return <>{loader ?? null}</>;\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 two 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 * <ReplaneProvider\n * options={{ baseUrl: '...', sdkKey: '...' }}\n * loader={<LoadingSpinner />}\n * >\n * <App />\n * </ReplaneProvider>\n * ```\n *\n * 3. With Suspense:\n * ```tsx\n * <Suspense fallback={<LoadingSpinner />}>\n * <ReplaneProvider\n * options={{ baseUrl: '...', sdkKey: '...' }}\n * suspense\n * >\n * <App />\n * </ReplaneProvider>\n * </Suspense>\n * ```\n */\nexport function ReplaneProvider<T extends object>(props: ReplaneProviderProps<T>) {\n if (hasClient(props)) {\n return <ReplaneProviderWithClient {...props} />;\n }\n\n if (props.suspense) {\n return <ReplaneProviderWithSuspense {...props} />;\n }\n\n return <ReplaneProviderWithOptions {...props} />;\n}\n","import { useContext, useSyncExternalStore } from \"react\";\nimport { ReplaneContext } from \"./context\";\nimport type { ReplaneContextValue } from \"./types\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function useReplane<T extends object = any>(): ReplaneContextValue<T> {\n const context = useContext(ReplaneContext);\n if (!context) {\n throw new Error(\"useReplane must be used within a ReplaneProvider\");\n }\n return context as ReplaneContextValue<T>;\n}\n\nexport function useConfig<T>(\n name: string,\n options?: { context?: Record<string, string | number | boolean | null> }\n): T {\n const { client } = useReplane();\n\n const value = useSyncExternalStore(\n (onStoreChange) => {\n return client.subscribe(name, onStoreChange);\n },\n () => client.get(name, options) as T,\n () => client.get(name, options) as T\n );\n\n return value;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["options: ReplaneClientOptions<T>","onError?: (error: Error) => void","options?: ReplaneClientOptions<T>","props: ReplaneProviderProps<T>","value: ReplaneContextValue<T>","props: ReplaneProviderProps<T>","name: string","options?: { context?: Record<string, string | number | boolean | null> }"],"sources":["../src/context.ts","../src/useReplaneClient.ts","../src/types.ts","../src/provider.tsx","../src/hooks.ts"],"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\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 useReplaneClient<T extends object = any>(\n options: ReplaneClientOptions<T>,\n onError?: (error: Error) => void\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 = err instanceof Error ? err : new Error(String(err));\n setState({ status: \"error\", client: null, error });\n onError?.(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 // We intentionally only run this effect once on mount\n // Options changes would require remounting the provider\n // eslint-disable-next-line react-hooks/exhaustive-deps\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 type { ReplaneClient, ReplaneClientOptions } from \"@replanejs/sdk\";\nimport type { ReactNode } from \"react\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface ReplaneContextValue<T extends object = any> {\n client: ReplaneClient<T>;\n}\n\n/**\n * Props for ReplaneProvider when using a pre-created client.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface ReplaneProviderWithClientProps<T extends object = any> {\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 */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface ReplaneProviderWithOptionsProps<T extends object = any> {\n /** Options to create the ReplaneClient */\n options: ReplaneClientOptions<T>;\n children: ReactNode;\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 */\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 * @default false\n */\n suspense?: boolean;\n /**\n * Callback when client initialization fails.\n */\n onError?: (error: Error) => void;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type ReplaneProviderProps<T extends object = any> =\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","import { useMemo } from \"react\";\nimport { ReplaneContext } from \"./context\";\nimport { useReplaneClient, useReplaneClientSuspense } from \"./useReplaneClient\";\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 options-based client creation (non-suspense).\n */\nfunction ReplaneProviderWithOptions<T extends object>({\n options,\n children,\n loader,\n onError,\n}: ReplaneProviderWithOptionsProps<T>) {\n const state = useReplaneClient<T>(options, onError);\n\n if (state.status === \"loading\") {\n return <>{loader ?? null}</>;\n }\n\n if (state.status === \"error\") {\n // Error was already reported via onError callback\n // Return loader or null to prevent rendering children without a client\n return <>{loader ?? null}</>;\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 two 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 * <ReplaneProvider\n * options={{ baseUrl: '...', sdkKey: '...' }}\n * loader={<LoadingSpinner />}\n * >\n * <App />\n * </ReplaneProvider>\n * ```\n *\n * 3. With Suspense:\n * ```tsx\n * <Suspense fallback={<LoadingSpinner />}>\n * <ReplaneProvider\n * options={{ baseUrl: '...', sdkKey: '...' }}\n * suspense\n * >\n * <App />\n * </ReplaneProvider>\n * </Suspense>\n * ```\n */\nexport function ReplaneProvider<T extends object>(props: ReplaneProviderProps<T>) {\n if (hasClient(props)) {\n return <ReplaneProviderWithClient {...props} />;\n }\n\n if (props.suspense) {\n return <ReplaneProviderWithSuspense {...props} />;\n }\n\n return <ReplaneProviderWithOptions {...props} />;\n}\n","import { useContext, useSyncExternalStore } from \"react\";\nimport { ReplaneContext } from \"./context\";\nimport type { ReplaneContextValue } from \"./types\";\n\nexport function useReplane<T extends object = Record<string, unknown>>(): ReplaneContextValue<T> {\n const context = useContext(ReplaneContext);\n if (!context) {\n throw new Error(\"useReplane must be used within a ReplaneProvider\");\n }\n return context as ReplaneContextValue<T>;\n}\n\nexport function useConfig<T>(\n name: string,\n options?: { context?: Record<string, string | number | boolean | null> }\n): T {\n const { client } = useReplane();\n\n const value = useSyncExternalStore(\n (onStoreChange) => {\n return client.subscribe(name, onStoreChange);\n },\n () => client.get(name, options) as T,\n () => client.get(name, options) as T\n );\n\n return value;\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.1.1",
3
+ "version": "0.7.1",
4
4
  "description": "React SDK for Replane - feature flags and remote configuration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -40,11 +40,10 @@
40
40
  "react": ">=18.0.0"
41
41
  },
42
42
  "dependencies": {
43
- "@replanejs/sdk": "0.6.2"
43
+ "@replanejs/sdk": "^0.7.1"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@testing-library/jest-dom": "^6.9.1",
47
- "bumpp": "^10.1.0",
48
47
  "@testing-library/react": "^16.3.1",
49
48
  "@types/node": "^22.19.3",
50
49
  "@types/react": "^18.2.0",
@@ -67,7 +66,6 @@
67
66
  "dev": "tsdown --watch",
68
67
  "typecheck": "tsc --noEmit",
69
68
  "test": "vitest run",
70
- "test:watch": "vitest",
71
- "release": "pnpm run build && bumpp && npm publish"
69
+ "test:watch": "vitest"
72
70
  }
73
71
  }