flagmint-react-sdk 0.7.11 → 0.7.13

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,609 @@
1
+ # flagmint-react-sdk
2
+
3
+ A React wrapper for [flagmint-js-sdk](https://www.npmjs.com/package/flagmint-js-sdk) that provides React-specific hooks and context with fine-grained reactivity powered by Zustand.
4
+
5
+ ## ✨ Features
6
+
7
+ - 🎯 **Fine-grained reactivity** - Only components using specific flags re-render when those flags change
8
+ - 🚀 **SSR-safe** - No global state leakage between server requests
9
+ - 📦 **TypeScript support** - Full type safety with generics for flag values and context
10
+ - 🔀 **Dual export strategy** - Separate server-safe types and client-only hooks
11
+ - ⚡ **Auto-initialization** - Direct integration with FlagClient from flagmint-js-sdk
12
+ - 🔐 **Deferred initialization** - Perfect for authentication flows
13
+ - 📱 **Framework agnostic** - Works with Next.js, Remix, Vite, and more
14
+
15
+ ## 📦 Installation
16
+
17
+ ```bash
18
+ npm install react-flagmint flagmint-js-sdk
19
+ # or
20
+ pnpm add react-flagmint flagmint-js-sdk
21
+ # or
22
+ yarn add react-flagmint flagmint-js-sdk
23
+ ```
24
+
25
+ ## 🚀 Quick Start
26
+
27
+ ### 1. Basic Setup
28
+
29
+ ```tsx
30
+ // app/providers.tsx (Next.js App Router)
31
+ 'use client'
32
+ import { FlagmintProvider } from 'react-flagmint/client'
33
+
34
+ export default function Providers({ children }: { children: React.ReactNode }) {
35
+ return (
36
+ <FlagmintProvider
37
+ options={{
38
+ apiKey: process.env.NEXT_PUBLIC_FLAGMINT_API_KEY!,
39
+ transportMode: 'websocket',
40
+ context: {
41
+ userId: 'user-123',
42
+ plan: 'premium'
43
+ }
44
+ }}
45
+ >
46
+ {children}
47
+ </FlagmintProvider>
48
+ )
49
+ }
50
+ ```
51
+
52
+ ```tsx
53
+ // app/layout.tsx
54
+ import Providers from './providers'
55
+
56
+ export default function RootLayout({
57
+ children,
58
+ }: {
59
+ children: React.ReactNode
60
+ }) {
61
+ return (
62
+ <html>
63
+ <body>
64
+ <Providers>
65
+ {children}
66
+ </Providers>
67
+ </body>
68
+ </html>
69
+ )
70
+ }
71
+ ```
72
+
73
+ ### 2. Using Flags in Components
74
+
75
+ ```tsx
76
+ // components/FeatureComponent.tsx
77
+ 'use client'
78
+ import { useFlag, useFlags, useFlagmintReady } from 'react-flagmint/client'
79
+
80
+ export default function FeatureComponent() {
81
+ const showNewFeature = useFlag('new-dashboard', false)
82
+ const userPlan = useFlag('user-plan', 'free')
83
+ const isReady = useFlagmintReady()
84
+
85
+ if (!isReady) {
86
+ return <div>Loading flags...</div>
87
+ }
88
+
89
+ return (
90
+ <div>
91
+ {showNewFeature && <NewDashboard />}
92
+ <div>Current plan: {userPlan}</div>
93
+ </div>
94
+ )
95
+ }
96
+ ```
97
+
98
+ ## 📚 API Reference
99
+
100
+ ### FlagmintProvider
101
+
102
+ The provider component that initializes the FlagClient and provides flag context to your app.
103
+
104
+ ```tsx
105
+ <FlagmintProvider
106
+ options={FlagClientOptions}
107
+ initialFlags={{}}
108
+ deferInitialization={false}
109
+ >
110
+ {children}
111
+ </FlagmintProvider>
112
+ ```
113
+
114
+ #### Props
115
+
116
+ | Prop | Type | Default | Description |
117
+ |------|------|---------|-------------|
118
+ | `options` | `FlagClientOptions` | Required | Configuration for the FlagClient |
119
+ | `initialFlags` | `Flags` | `{}` | Initial flag values for SSR/hydration |
120
+ | `deferInitialization` | `boolean` | `false` | If true, wait for manual initialization |
121
+
122
+ #### FlagClientOptions
123
+
124
+ ```tsx
125
+ interface FlagClientOptions<C extends Record<string, any> = Record<string, any>> {
126
+ apiKey: string
127
+ context?: C
128
+ transportMode?: 'auto' | 'websocket' | 'long-polling'
129
+ enableOfflineCache?: boolean
130
+ persistContext?: boolean
131
+ onError?: (error: Error) => void
132
+ previewMode?: boolean
133
+ rawFlags?: Record<string, FlagValue>
134
+ deferInitialization?: boolean
135
+ }
136
+ ```
137
+
138
+ ### Hooks
139
+
140
+ #### useFlag(key, fallback?)
141
+
142
+ Get a specific flag value with fine-grained reactivity.
143
+
144
+ ```tsx
145
+ const showFeature = useFlag('feature-name', false)
146
+ const userTier = useFlag('user-tier', 'free')
147
+ const config = useFlag('app-config', { theme: 'light' })
148
+ ```
149
+
150
+ **Parameters:**
151
+ - `key: string` - The flag key
152
+ - `fallback?: T` - Default value if flag is not found
153
+
154
+ **Returns:** The flag value or fallback
155
+
156
+ #### useFlags()
157
+
158
+ Get all currently loaded flags.
159
+
160
+ ```tsx
161
+ const allFlags = useFlags()
162
+ console.log(allFlags) // { 'feature-a': true, 'user-tier': 'pro' }
163
+ ```
164
+
165
+ **Returns:** Object containing all loaded flags
166
+
167
+ #### useFlagmint()
168
+
169
+ Get access to the FlagClient instance and utilities.
170
+
171
+ ```tsx
172
+ const { client, isReady, isInitialized, updateContext } = useFlagmint()
173
+
174
+ // Update user context
175
+ await updateContext({ userId: 'new-user', plan: 'enterprise' })
176
+ ```
177
+
178
+ **Returns:**
179
+ ```tsx
180
+ {
181
+ client: FlagClient | null
182
+ isReady: boolean
183
+ isInitialized: boolean
184
+ updateContext: (context: Record<string, any>) => Promise<void>
185
+ }
186
+ ```
187
+
188
+ #### useFlagmintReady()
189
+
190
+ Check if the FlagClient is ready to serve flags.
191
+
192
+ ```tsx
193
+ const isReady = useFlagmintReady()
194
+
195
+ if (!isReady) {
196
+ return <LoadingSpinner />
197
+ }
198
+ ```
199
+
200
+ #### useFlagClient()
201
+
202
+ Get direct access to the FlagClient instance.
203
+
204
+ ```tsx
205
+ const client = useFlagClient<MyFlagTypes>()
206
+ const specificFlag = client?.getFlag('feature-x', false)
207
+ ```
208
+
209
+ ## 🔧 Usage Patterns
210
+
211
+ ### 1. Auto-initialization (Default)
212
+
213
+ Best when user context is available immediately:
214
+
215
+ ```tsx
216
+ function App() {
217
+ return (
218
+ <FlagmintProvider
219
+ options={{
220
+ apiKey: 'your-api-key',
221
+ context: {
222
+ userId: getCurrentUser().id,
223
+ plan: getCurrentUser().plan
224
+ }
225
+ }}
226
+ >
227
+ <Dashboard />
228
+ </FlagmintProvider>
229
+ )
230
+ }
231
+ ```
232
+
233
+ ### 2. Deferred Initialization
234
+
235
+ Perfect for authentication flows:
236
+
237
+ ```tsx
238
+ // Provider with deferred initialization
239
+ <FlagmintProvider
240
+ options={{
241
+ apiKey: 'your-api-key',
242
+ context: {} // Empty initially
243
+ }}
244
+ deferInitialization={true}
245
+ >
246
+ <App />
247
+ </FlagmintProvider>
248
+
249
+ // Login component
250
+ function LoginPage() {
251
+ const { updateContext } = useFlagmint()
252
+
253
+ const handleLogin = async (user) => {
254
+ // First update context with user info
255
+ await updateContext({
256
+ userId: user.id,
257
+ plan: user.plan,
258
+ locale: user.locale
259
+ })
260
+
261
+ // Flags are now available with user context
262
+ navigate('/dashboard')
263
+ }
264
+
265
+ return <LoginForm onLogin={handleLogin} />
266
+ }
267
+ ```
268
+
269
+ ### 3. TypeScript Usage
270
+
271
+ Define your flag types for better type safety:
272
+
273
+ ```tsx
274
+ // types/flags.ts
275
+ export interface AppFlags {
276
+ 'show-beta-feature': boolean
277
+ 'user-plan': 'free' | 'pro' | 'enterprise'
278
+ 'theme-config': {
279
+ primaryColor: string
280
+ darkMode: boolean
281
+ }
282
+ }
283
+
284
+ export interface UserContext {
285
+ userId: string
286
+ plan: string
287
+ locale: string
288
+ }
289
+
290
+ // components/TypedComponent.tsx
291
+ import { useFlag } from 'react-flagmint/client'
292
+ import type { AppFlags } from '../types/flags'
293
+
294
+ export default function TypedComponent() {
295
+ // TypeScript knows this returns boolean
296
+ const showBeta = useFlag<AppFlags['show-beta-feature']>('show-beta-feature', false)
297
+
298
+ // TypeScript knows this returns the union type
299
+ const plan = useFlag<AppFlags['user-plan']>('user-plan', 'free')
300
+
301
+ return (
302
+ <div>
303
+ {showBeta && <BetaFeature />}
304
+ <div>Plan: {plan}</div>
305
+ </div>
306
+ )
307
+ }
308
+ ```
309
+
310
+ ### 4. Server-Side Rendering (SSR)
311
+
312
+ #### Next.js App Router
313
+
314
+ ```tsx
315
+ // app/providers.tsx
316
+ 'use client'
317
+ import { FlagmintProvider } from 'react-flagmint/client'
318
+
319
+ export default function Providers({ children, initialFlags = {} }) {
320
+ return (
321
+ <FlagmintProvider
322
+ options={{
323
+ apiKey: process.env.NEXT_PUBLIC_FLAGMINT_API_KEY!,
324
+ transportMode: 'websocket'
325
+ }}
326
+ initialFlags={initialFlags}
327
+ >
328
+ {children}
329
+ </FlagmintProvider>
330
+ )
331
+ }
332
+
333
+ // app/page.tsx
334
+ import { FlagClient } from 'flagmint-js-sdk'
335
+ import Providers from './providers'
336
+ import ClientComponent from './ClientComponent'
337
+
338
+ export default async function Page() {
339
+ // Optionally preload flags on server
340
+ let initialFlags = {}
341
+
342
+ try {
343
+ const serverClient = new FlagClient({
344
+ apiKey: process.env.FLAGMINT_API_KEY!,
345
+ context: { server: true }
346
+ })
347
+ await serverClient.ready()
348
+ initialFlags = await serverClient.getFlags() // If this method exists
349
+ } catch (error) {
350
+ console.warn('Failed to load initial flags:', error)
351
+ }
352
+
353
+ return (
354
+ <Providers initialFlags={initialFlags}>
355
+ <ClientComponent />
356
+ </Providers>
357
+ )
358
+ }
359
+ ```
360
+
361
+ ### 5. Context Updates
362
+
363
+ Update user context dynamically:
364
+
365
+ ```tsx
366
+ function UserSettings() {
367
+ const { updateContext } = useFlagmint()
368
+ const currentTheme = useFlag('user-theme', 'light')
369
+
370
+ const handleThemeChange = async (newTheme: string) => {
371
+ // Update context - flags will be re-evaluated
372
+ await updateContext({ theme: newTheme })
373
+ }
374
+
375
+ const handlePlanUpgrade = async (newPlan: string) => {
376
+ await updateContext({ plan: newPlan })
377
+ // Component will re-render with new plan-based flags
378
+ }
379
+
380
+ return (
381
+ <div>
382
+ <ThemeSelector onChange={handleThemeChange} />
383
+ <PlanUpgrade onUpgrade={handlePlanUpgrade} />
384
+ </div>
385
+ )
386
+ }
387
+ ```
388
+
389
+ ### 6. Loading States
390
+
391
+ Handle loading states gracefully:
392
+
393
+ ```tsx
394
+ function FeaturePage() {
395
+ const isReady = useFlagmintReady()
396
+ const showPremiumFeature = useFlag('premium-feature', false)
397
+
398
+ if (!isReady) {
399
+ return (
400
+ <div className="loading-container">
401
+ <Spinner />
402
+ <p>Loading personalized features...</p>
403
+ </div>
404
+ )
405
+ }
406
+
407
+ return (
408
+ <div>
409
+ <h1>Features</h1>
410
+ {showPremiumFeature ? (
411
+ <PremiumFeature />
412
+ ) : (
413
+ <UpgradeBanner />
414
+ )}
415
+ </div>
416
+ )
417
+ }
418
+ ```
419
+
420
+ ### 7. Error Handling
421
+
422
+ ```tsx
423
+ <FlagmintProvider
424
+ options={{
425
+ apiKey: 'your-api-key',
426
+ onError: (error) => {
427
+ console.error('Flagmint error:', error)
428
+ // Send to error reporting service
429
+ errorReporting.captureException(error)
430
+ }
431
+ }}
432
+ >
433
+ <App />
434
+ </FlagmintProvider>
435
+ ```
436
+
437
+ ## 🏗️ Framework Examples
438
+
439
+ ### Next.js (App Router)
440
+
441
+ ```tsx
442
+ // app/layout.tsx
443
+ import Providers from './providers'
444
+
445
+ export default function RootLayout({ children }) {
446
+ return (
447
+ <html lang="en">
448
+ <body>
449
+ <Providers>{children}</Providers>
450
+ </body>
451
+ </html>
452
+ )
453
+ }
454
+
455
+ // app/providers.tsx
456
+ 'use client'
457
+ import { FlagmintProvider } from 'react-flagmint/client'
458
+
459
+ export default function Providers({ children }) {
460
+ return (
461
+ <FlagmintProvider
462
+ options={{
463
+ apiKey: process.env.NEXT_PUBLIC_FLAGMINT_API_KEY!,
464
+ transportMode: 'long-polling'
465
+ }}
466
+ >
467
+ {children}
468
+ </FlagmintProvider>
469
+ )
470
+ }
471
+ ```
472
+
473
+ ### Vite + React
474
+
475
+ ```tsx
476
+ // src/main.tsx
477
+ import React from 'react'
478
+ import ReactDOM from 'react-dom/client'
479
+ import { FlagmintProvider } from 'react-flagmint/client'
480
+ import App from './App'
481
+
482
+ ReactDOM.createRoot(document.getElementById('root')!).render(
483
+ <React.StrictMode>
484
+ <FlagmintProvider
485
+ options={{
486
+ apiKey: import.meta.env.VITE_FLAGMINT_API_KEY,
487
+ transportMode: 'websocket'
488
+ }}
489
+ >
490
+ <App />
491
+ </FlagmintProvider>
492
+ </React.StrictMode>
493
+ )
494
+ ```
495
+
496
+ ### Remix
497
+
498
+ ```tsx
499
+ // app/root.tsx
500
+ import { FlagmintProvider } from 'react-flagmint/client'
501
+
502
+ export default function App() {
503
+ return (
504
+ <html>
505
+ <head>
506
+ <Meta />
507
+ <Links />
508
+ </head>
509
+ <body>
510
+ <FlagmintProvider
511
+ options={{
512
+ apiKey: process.env.FLAGMINT_API_KEY!,
513
+ transportMode: 'long-polling'
514
+ }}
515
+ >
516
+ <Outlet />
517
+ </FlagmintProvider>
518
+ <Scripts />
519
+ </body>
520
+ </html>
521
+ )
522
+ }
523
+ ```
524
+
525
+ ## ⚡ Performance
526
+
527
+ ### Fine-grained Reactivity
528
+
529
+ Only components that use specific flags will re-render when those flags change:
530
+
531
+ ```tsx
532
+ // ✅ Good: Only re-renders when 'feature-a' changes
533
+ function ComponentA() {
534
+ const featureA = useFlag('feature-a', false)
535
+ return <div>{featureA && <FeatureA />}</div>
536
+ }
537
+
538
+ // ✅ Good: Only re-renders when 'feature-b' changes
539
+ function ComponentB() {
540
+ const featureB = useFlag('feature-b', false)
541
+ return <div>{featureB && <FeatureB />}</div>
542
+ }
543
+
544
+ // ❌ Avoid: Re-renders when ANY flag changes
545
+ function ComponentAll() {
546
+ const allFlags = useFlags()
547
+ return <div>{allFlags['feature-a'] && <FeatureA />}</div>
548
+ }
549
+ ```
550
+
551
+ ### Bundle Size
552
+
553
+ - **react-flagmint**: ~3KB gzipped
554
+ - **zustand**: ~2KB gzipped
555
+ - **Total overhead**: ~5KB gzipped
556
+
557
+ ## 🔧 Development
558
+
559
+ ### Local Development
560
+
561
+ ```bash
562
+ # Clone the monorepo
563
+ git clone <repo-url>
564
+ cd flagmint-monorepo
565
+
566
+ # Install dependencies
567
+ pnpm install
568
+
569
+ # Build the library
570
+ pnpm --filter react-flagmint build
571
+
572
+ # Run the Next.js example
573
+ pnpm dev:next
574
+ ```
575
+
576
+ ### Testing
577
+
578
+ ```bash
579
+ # Run tests
580
+ pnpm test
581
+
582
+ # Type checking
583
+ pnpm typecheck
584
+
585
+ # Lint
586
+ pnpm lint
587
+ ```
588
+
589
+ ## 📄 License
590
+
591
+ MIT
592
+
593
+ ## 🤝 Contributing
594
+
595
+ 1. Fork the repository
596
+ 2. Create a feature branch
597
+ 3. Make your changes
598
+ 4. Add tests
599
+ 5. Submit a pull request
600
+
601
+ ## 📞 Support
602
+
603
+ - 📧 Email: support@flagmint.com
604
+ - 🐛 Issues: [GitHub Issues](https://github.com/jtad009/flagmint-react-sdk/issues)
605
+ - 📖 Docs: [Documentation](https://docs.flagmint.com)
606
+
607
+ ---
608
+
609
+ **Made with ❤️ by the Flagmint team**
package/dist/client.cjs CHANGED
@@ -107,15 +107,24 @@ function useFlagmint() {
107
107
  }
108
108
  function useFlags() {
109
109
  const store = useFlagmintStore();
110
+ if (!store) {
111
+ return {};
112
+ }
110
113
  return zustand.useStore(store, (state) => state.flags);
111
114
  }
112
115
  function useFlag(key, fallback) {
113
116
  const store = useFlagmintStore();
117
+ if (!store) {
118
+ return fallback;
119
+ }
114
120
  const flagValue = zustand.useStore(store, (state) => state.flags[key]);
115
121
  return flagValue != null ? flagValue : fallback;
116
122
  }
117
123
  function useFlagmintReady() {
118
124
  const store = useFlagmintStore();
125
+ if (!store) {
126
+ return false;
127
+ }
119
128
  const isReady = zustand.useStore(store, (state) => state.isReady);
120
129
  const isInitialized = zustand.useStore(store, (state) => state.isInitialized);
121
130
  return isReady && isInitialized;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/store/store.ts","../src/providers/FlagmintProvider.tsx","../src/hooks/index.ts"],"names":["createStore","createContext","useMemo","useRef","FlagClient","useEffect","useContext","useStore"],"mappings":"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","file":"client.cjs","sourcesContent":["'use client';\nimport { createStore, StoreApi } from \"zustand/vanilla\";\nimport { Flags, FlagStore } from \"@/types\";\n\n\nexport function createFlagStore(initialFlags: Flags = {}): StoreApi<FlagStore> {\n return createStore<FlagStore>((set, get) => ({\n flags: initialFlags,\n client: null,\n isInitialized: false,\n isReady: false,\n setFlags: (flags) => {\n set({ flags: { ...flags } })\n },\n setFlag: (key, value) => set((state) => ({\n flags: { ...state.flags, [key]: value }\n })),\n setClient: (client) => set({ client }),\n setInitialized: (initialized) => set({ isInitialized: initialized }),\n setReady: (ready) => set({ isReady: ready })\n }))\n}\n","'use client';\nimport { FlagClient } from \"flagmint-js-sdk\"\nimport { useMemo, useRef, useEffect, createContext } from \"react\"\nimport { createFlagStore } from \"@/store/store\"\nimport { FlagmintProviderProps, Flags, FlagStore } from \"@/types\"\nimport { StoreApi } from \"zustand\"\n\nexport const FlagmintStoreContext = createContext<StoreApi<FlagStore> | null>(null)\n\n/**\n * Provides the Flagmint flag store to React components and keeps it synced with FlagClient updates.\n * Lifecycle overview:\n * - App loads → FlagClient constructed → initialize() begins.\n * - Cached flags applied → subscribers notified → React renders cached values.\n * - Transport set up → initial fetch → store updated → subscribers notified.\n * - Subsequent server updates propagate via client.subscribe to re-render consumers.\n * - When context changes (updateContext), flags are re-fetched and the store is refreshed.\n *\n * @param props Component props: children, client options, optional initial flags, and deferInitialization flag.\n * @returns A provider that supplies the flag store context to its children.\n */\nexport function FlagmintProvider<\n T extends FlagClient<T, C>,\n C extends Record<string, any> = Record<string, any>\n>({\n children,\n options,\n initialFlags = {},\n deferInitialization = false\n}: FlagmintProviderProps<T, C>) {\n // Create a new store instance for each provider (per-request in SSR)\n const store = useMemo(() => createFlagStore(initialFlags), [])\n \n // Use ref to avoid recreating client on every render\n const clientRef = useRef<FlagClient<T, C> | null>(null)\n const initPromiseRef = useRef<Promise<FlagClient<T, C>> | null>(null)\n const unsubscribeRef = useRef<(() => void) | null>(null)\n \n // Initialization function similar to Vue plugin\n const init = async (): Promise<FlagClient<T, C>> => {\n if (clientRef.current) return clientRef.current // Avoid re-init\n \n // Return existing promise if init is already in progress\n if (initPromiseRef.current) return initPromiseRef.current\n \n const { setClient, setReady, setInitialized, setFlags } = store.getState()\n \n initPromiseRef.current = (async () => {\n try {\n // Create the FlagClient\n const client = new FlagClient<T, C>(options)\n \n // Wait for client to be ready\n await client.ready()\n \n // Get initial flags from client\n const initialClientFlags = client.getFlags()\n setFlags(initialClientFlags)\n \n // Subscribe to flag changes - THIS IS THE KEY FIX\n const unsubscribe = client.subscribe((updatedFlags: Flags) => {\n // Get fresh reference each time\n const currentStore = store.getState();\n currentStore.setFlags(updatedFlags);\n })\n \n unsubscribeRef.current = unsubscribe\n \n clientRef.current = client\n setClient(client)\n setReady(true)\n setInitialized(true)\n \n return client\n } catch (error) {\n console.error('Failed to initialize Flagmint client:', error)\n throw error\n }\n })()\n \n return initPromiseRef.current\n }\n\n useEffect(() => {\n if (!deferInitialization) {\n init().catch(error => {\n console.error('Auto-initialization failed:', error)\n })\n }\n\n return () => {\n // Unsubscribe from flag changes\n if (unsubscribeRef.current) {\n unsubscribeRef.current()\n unsubscribeRef.current = null\n }\n \n // Destroy client\n if (clientRef.current) {\n clientRef.current.destroy?.()\n clientRef.current = null\n initPromiseRef.current = null\n }\n }\n }, [deferInitialization])\n\n return (\n <FlagmintStoreContext.Provider value={store}>\n {children}\n </FlagmintStoreContext.Provider>\n )\n}\n","'use client';\nimport { FlagValue } from \"flagmint-js-sdk\"\nimport { useContext } from \"react\"\nimport { StoreApi, useStore } from \"zustand\"\nimport { FlagmintStoreContext } from \"@/providers/FlagmintProvider\"\nimport { FlagStore, Flags } from \"@/types\"\n\n// Helper to get the store from context\nexport function useFlagmintStore(): StoreApi<FlagStore> {\n const store = useContext(FlagmintStoreContext)\n if (!store) {\n throw new Error('useFlagmintStore must be used within a FlagmintProvider')\n }\n return store\n}\n\n// Hook to get the client instance and update context\nexport function useFlagmint() {\n const store = useFlagmintStore()\n const client = useStore(store, (state) => state.client)\n const isInitialized = useStore(store, (state) => state.isInitialized)\n\n const updateContext = async (context: Record<string, any>) => {\n if (!client) {\n throw new Error('Flagmint client not initialized')\n }\n await client.updateContext(context)\n }\n\n return {\n client,\n isInitialized,\n updateContext\n }\n}\n\n// Hook to get all flags - only re-renders when flags change\nexport function useFlags(): Flags {\n const store = useFlagmintStore()\n return useStore(store, (state) => state.flags)\n}\n\n// Simplified useFlag - just read from the reactive store\nexport function useFlag<T = FlagValue>(\n key: string,\n fallback?: T\n): T {\n const store = useFlagmintStore()\n \n // Subscribe to this specific flag in the store\n const flagValue = useStore(store, (state) => state.flags[key])\n \n // Return the flag value or fallback\n return (flagValue ?? fallback) as T\n}\n\n// Hook to check if the client is ready\nexport function useFlagmintReady(): boolean {\n const store = useFlagmintStore()\n \n // Subscribe to both isReady and isInitialized\n const isReady = useStore(store, (state) => state.isReady)\n const isInitialized = useStore(store, (state) => state.isInitialized)\n \n return isReady && isInitialized\n}"]}
1
+ {"version":3,"sources":["../src/store/store.ts","../src/providers/FlagmintProvider.tsx","../src/hooks/index.ts"],"names":["createStore","createContext","useMemo","useRef","FlagClient","useEffect","useContext","useStore"],"mappings":"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","file":"client.cjs","sourcesContent":["'use client';\nimport { createStore, StoreApi } from \"zustand/vanilla\";\nimport { Flags, FlagStore } from \"@/types\";\n\n\nexport function createFlagStore(initialFlags: Flags = {}): StoreApi<FlagStore> {\n return createStore<FlagStore>((set, get) => ({\n flags: initialFlags,\n client: null,\n isInitialized: false,\n isReady: false,\n setFlags: (flags) => {\n set({ flags: { ...flags } })\n },\n setFlag: (key, value) => set((state) => ({\n flags: { ...state.flags, [key]: value }\n })),\n setClient: (client) => set({ client }),\n setInitialized: (initialized) => set({ isInitialized: initialized }),\n setReady: (ready) => set({ isReady: ready })\n }))\n}\n","'use client';\nimport { FlagClient } from \"flagmint-js-sdk\"\nimport { useMemo, useRef, useEffect, createContext } from \"react\"\nimport { createFlagStore } from \"@/store/store\"\nimport { FlagmintProviderProps, Flags, FlagStore } from \"@/types\"\nimport { StoreApi } from \"zustand\"\n\nexport const FlagmintStoreContext = createContext<StoreApi<FlagStore> | null>(null)\n\n/**\n * Provides the Flagmint flag store to React components and keeps it synced with FlagClient updates.\n * Lifecycle overview:\n * - App loads → FlagClient constructed → initialize() begins.\n * - Cached flags applied → subscribers notified → React renders cached values.\n * - Transport set up → initial fetch → store updated → subscribers notified.\n * - Subsequent server updates propagate via client.subscribe to re-render consumers.\n * - When context changes (updateContext), flags are re-fetched and the store is refreshed.\n *\n * @param props Component props: children, client options, optional initial flags, and deferInitialization flag.\n * @returns A provider that supplies the flag store context to its children.\n */\nexport function FlagmintProvider<\n T extends FlagClient<T, C>,\n C extends Record<string, any> = Record<string, any>\n>({\n children,\n options,\n initialFlags = {},\n deferInitialization = false\n}: FlagmintProviderProps<T, C>) {\n // Create a new store instance for each provider (per-request in SSR)\n const store = useMemo(() => createFlagStore(initialFlags), [])\n \n // Use ref to avoid recreating client on every render\n const clientRef = useRef<FlagClient<T, C> | null>(null)\n const initPromiseRef = useRef<Promise<FlagClient<T, C>> | null>(null)\n const unsubscribeRef = useRef<(() => void) | null>(null)\n \n // Initialization function similar to Vue plugin\n const init = async (): Promise<FlagClient<T, C>> => {\n if (clientRef.current) return clientRef.current // Avoid re-init\n \n // Return existing promise if init is already in progress\n if (initPromiseRef.current) return initPromiseRef.current\n \n const { setClient, setReady, setInitialized, setFlags } = store.getState()\n \n initPromiseRef.current = (async () => {\n try {\n // Create the FlagClient\n const client = new FlagClient<T, C>(options)\n \n // Wait for client to be ready\n await client.ready()\n \n // Get initial flags from client\n const initialClientFlags = client.getFlags()\n setFlags(initialClientFlags)\n \n // Subscribe to flag changes - THIS IS THE KEY FIX\n const unsubscribe = client.subscribe((updatedFlags: Flags) => {\n // Get fresh reference each time\n const currentStore = store.getState();\n currentStore.setFlags(updatedFlags);\n })\n \n unsubscribeRef.current = unsubscribe\n \n clientRef.current = client\n setClient(client)\n setReady(true)\n setInitialized(true)\n \n return client\n } catch (error) {\n console.error('Failed to initialize Flagmint client:', error)\n throw error\n }\n })()\n \n return initPromiseRef.current\n }\n\n useEffect(() => {\n if (!deferInitialization) {\n init().catch(error => {\n console.error('Auto-initialization failed:', error)\n })\n }\n\n return () => {\n // Unsubscribe from flag changes\n if (unsubscribeRef.current) {\n unsubscribeRef.current()\n unsubscribeRef.current = null\n }\n \n // Destroy client\n if (clientRef.current) {\n clientRef.current.destroy?.()\n clientRef.current = null\n initPromiseRef.current = null\n }\n }\n }, [deferInitialization])\n\n return (\n <FlagmintStoreContext.Provider value={store}>\n {children}\n </FlagmintStoreContext.Provider>\n )\n}\n","'use client';\nimport { FlagValue } from \"flagmint-js-sdk\"\nimport { useContext } from \"react\"\nimport { StoreApi, useStore } from \"zustand\"\nimport { FlagmintStoreContext } from \"@/providers/FlagmintProvider\"\nimport { FlagStore, Flags } from \"@/types\"\n\n// Helper to get the store from context\nexport function useFlagmintStore(): StoreApi<FlagStore> {\n const store = useContext(FlagmintStoreContext)\n if (!store) {\n throw new Error('useFlagmintStore must be used within a FlagmintProvider')\n }\n return store\n}\n\n// Hook to get the client instance and update context\nexport function useFlagmint() {\n const store = useFlagmintStore()\n const client = useStore(store, (state) => state.client)\n const isInitialized = useStore(store, (state) => state.isInitialized)\n\n const updateContext = async (context: Record<string, any>) => {\n if (!client) {\n throw new Error('Flagmint client not initialized')\n }\n await client.updateContext(context)\n }\n\n return {\n client,\n isInitialized,\n updateContext\n }\n}\n\n// Hook to get all flags - only re-renders when flags change\nexport function useFlags(): Flags {\n const store = useFlagmintStore()\n if (!store) {\n return {};\n }\n return useStore(store, (state) => state.flags)\n}\n\n// Simplified useFlag - just read from the reactive store\nexport function useFlag<T = FlagValue>(\n key: string,\n fallback?: T\n): T {\n const store = useFlagmintStore()\n if (!store) {\n return fallback as T;\n }\n // Subscribe to this specific flag in the store\n const flagValue = useStore(store, (state) => state.flags[key])\n \n // Return the flag value or fallback\n return (flagValue ?? fallback) as T\n}\n\n// Hook to check if the client is ready\nexport function useFlagmintReady(): boolean {\n const store = useFlagmintStore()\n if (!store) {\n return false;\n }\n // Subscribe to both isReady and isInitialized\n const isReady = useStore(store, (state) => state.isReady)\n const isInitialized = useStore(store, (state) => state.isInitialized)\n \n return isReady && isInitialized\n}"]}
package/dist/client.js CHANGED
@@ -105,15 +105,24 @@ function useFlagmint() {
105
105
  }
106
106
  function useFlags() {
107
107
  const store = useFlagmintStore();
108
+ if (!store) {
109
+ return {};
110
+ }
108
111
  return useStore(store, (state) => state.flags);
109
112
  }
110
113
  function useFlag(key, fallback) {
111
114
  const store = useFlagmintStore();
115
+ if (!store) {
116
+ return fallback;
117
+ }
112
118
  const flagValue = useStore(store, (state) => state.flags[key]);
113
119
  return flagValue != null ? flagValue : fallback;
114
120
  }
115
121
  function useFlagmintReady() {
116
122
  const store = useFlagmintStore();
123
+ if (!store) {
124
+ return false;
125
+ }
117
126
  const isReady = useStore(store, (state) => state.isReady);
118
127
  const isInitialized = useStore(store, (state) => state.isInitialized);
119
128
  return isReady && isInitialized;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/store/store.ts","../src/providers/FlagmintProvider.tsx","../src/hooks/index.ts"],"names":[],"mappings":"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","file":"client.js","sourcesContent":["'use client';\nimport { createStore, StoreApi } from \"zustand/vanilla\";\nimport { Flags, FlagStore } from \"@/types\";\n\n\nexport function createFlagStore(initialFlags: Flags = {}): StoreApi<FlagStore> {\n return createStore<FlagStore>((set, get) => ({\n flags: initialFlags,\n client: null,\n isInitialized: false,\n isReady: false,\n setFlags: (flags) => {\n set({ flags: { ...flags } })\n },\n setFlag: (key, value) => set((state) => ({\n flags: { ...state.flags, [key]: value }\n })),\n setClient: (client) => set({ client }),\n setInitialized: (initialized) => set({ isInitialized: initialized }),\n setReady: (ready) => set({ isReady: ready })\n }))\n}\n","'use client';\nimport { FlagClient } from \"flagmint-js-sdk\"\nimport { useMemo, useRef, useEffect, createContext } from \"react\"\nimport { createFlagStore } from \"@/store/store\"\nimport { FlagmintProviderProps, Flags, FlagStore } from \"@/types\"\nimport { StoreApi } from \"zustand\"\n\nexport const FlagmintStoreContext = createContext<StoreApi<FlagStore> | null>(null)\n\n/**\n * Provides the Flagmint flag store to React components and keeps it synced with FlagClient updates.\n * Lifecycle overview:\n * - App loads → FlagClient constructed → initialize() begins.\n * - Cached flags applied → subscribers notified → React renders cached values.\n * - Transport set up → initial fetch → store updated → subscribers notified.\n * - Subsequent server updates propagate via client.subscribe to re-render consumers.\n * - When context changes (updateContext), flags are re-fetched and the store is refreshed.\n *\n * @param props Component props: children, client options, optional initial flags, and deferInitialization flag.\n * @returns A provider that supplies the flag store context to its children.\n */\nexport function FlagmintProvider<\n T extends FlagClient<T, C>,\n C extends Record<string, any> = Record<string, any>\n>({\n children,\n options,\n initialFlags = {},\n deferInitialization = false\n}: FlagmintProviderProps<T, C>) {\n // Create a new store instance for each provider (per-request in SSR)\n const store = useMemo(() => createFlagStore(initialFlags), [])\n \n // Use ref to avoid recreating client on every render\n const clientRef = useRef<FlagClient<T, C> | null>(null)\n const initPromiseRef = useRef<Promise<FlagClient<T, C>> | null>(null)\n const unsubscribeRef = useRef<(() => void) | null>(null)\n \n // Initialization function similar to Vue plugin\n const init = async (): Promise<FlagClient<T, C>> => {\n if (clientRef.current) return clientRef.current // Avoid re-init\n \n // Return existing promise if init is already in progress\n if (initPromiseRef.current) return initPromiseRef.current\n \n const { setClient, setReady, setInitialized, setFlags } = store.getState()\n \n initPromiseRef.current = (async () => {\n try {\n // Create the FlagClient\n const client = new FlagClient<T, C>(options)\n \n // Wait for client to be ready\n await client.ready()\n \n // Get initial flags from client\n const initialClientFlags = client.getFlags()\n setFlags(initialClientFlags)\n \n // Subscribe to flag changes - THIS IS THE KEY FIX\n const unsubscribe = client.subscribe((updatedFlags: Flags) => {\n // Get fresh reference each time\n const currentStore = store.getState();\n currentStore.setFlags(updatedFlags);\n })\n \n unsubscribeRef.current = unsubscribe\n \n clientRef.current = client\n setClient(client)\n setReady(true)\n setInitialized(true)\n \n return client\n } catch (error) {\n console.error('Failed to initialize Flagmint client:', error)\n throw error\n }\n })()\n \n return initPromiseRef.current\n }\n\n useEffect(() => {\n if (!deferInitialization) {\n init().catch(error => {\n console.error('Auto-initialization failed:', error)\n })\n }\n\n return () => {\n // Unsubscribe from flag changes\n if (unsubscribeRef.current) {\n unsubscribeRef.current()\n unsubscribeRef.current = null\n }\n \n // Destroy client\n if (clientRef.current) {\n clientRef.current.destroy?.()\n clientRef.current = null\n initPromiseRef.current = null\n }\n }\n }, [deferInitialization])\n\n return (\n <FlagmintStoreContext.Provider value={store}>\n {children}\n </FlagmintStoreContext.Provider>\n )\n}\n","'use client';\nimport { FlagValue } from \"flagmint-js-sdk\"\nimport { useContext } from \"react\"\nimport { StoreApi, useStore } from \"zustand\"\nimport { FlagmintStoreContext } from \"@/providers/FlagmintProvider\"\nimport { FlagStore, Flags } from \"@/types\"\n\n// Helper to get the store from context\nexport function useFlagmintStore(): StoreApi<FlagStore> {\n const store = useContext(FlagmintStoreContext)\n if (!store) {\n throw new Error('useFlagmintStore must be used within a FlagmintProvider')\n }\n return store\n}\n\n// Hook to get the client instance and update context\nexport function useFlagmint() {\n const store = useFlagmintStore()\n const client = useStore(store, (state) => state.client)\n const isInitialized = useStore(store, (state) => state.isInitialized)\n\n const updateContext = async (context: Record<string, any>) => {\n if (!client) {\n throw new Error('Flagmint client not initialized')\n }\n await client.updateContext(context)\n }\n\n return {\n client,\n isInitialized,\n updateContext\n }\n}\n\n// Hook to get all flags - only re-renders when flags change\nexport function useFlags(): Flags {\n const store = useFlagmintStore()\n return useStore(store, (state) => state.flags)\n}\n\n// Simplified useFlag - just read from the reactive store\nexport function useFlag<T = FlagValue>(\n key: string,\n fallback?: T\n): T {\n const store = useFlagmintStore()\n \n // Subscribe to this specific flag in the store\n const flagValue = useStore(store, (state) => state.flags[key])\n \n // Return the flag value or fallback\n return (flagValue ?? fallback) as T\n}\n\n// Hook to check if the client is ready\nexport function useFlagmintReady(): boolean {\n const store = useFlagmintStore()\n \n // Subscribe to both isReady and isInitialized\n const isReady = useStore(store, (state) => state.isReady)\n const isInitialized = useStore(store, (state) => state.isInitialized)\n \n return isReady && isInitialized\n}"]}
1
+ {"version":3,"sources":["../src/store/store.ts","../src/providers/FlagmintProvider.tsx","../src/hooks/index.ts"],"names":[],"mappings":"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","file":"client.js","sourcesContent":["'use client';\nimport { createStore, StoreApi } from \"zustand/vanilla\";\nimport { Flags, FlagStore } from \"@/types\";\n\n\nexport function createFlagStore(initialFlags: Flags = {}): StoreApi<FlagStore> {\n return createStore<FlagStore>((set, get) => ({\n flags: initialFlags,\n client: null,\n isInitialized: false,\n isReady: false,\n setFlags: (flags) => {\n set({ flags: { ...flags } })\n },\n setFlag: (key, value) => set((state) => ({\n flags: { ...state.flags, [key]: value }\n })),\n setClient: (client) => set({ client }),\n setInitialized: (initialized) => set({ isInitialized: initialized }),\n setReady: (ready) => set({ isReady: ready })\n }))\n}\n","'use client';\nimport { FlagClient } from \"flagmint-js-sdk\"\nimport { useMemo, useRef, useEffect, createContext } from \"react\"\nimport { createFlagStore } from \"@/store/store\"\nimport { FlagmintProviderProps, Flags, FlagStore } from \"@/types\"\nimport { StoreApi } from \"zustand\"\n\nexport const FlagmintStoreContext = createContext<StoreApi<FlagStore> | null>(null)\n\n/**\n * Provides the Flagmint flag store to React components and keeps it synced with FlagClient updates.\n * Lifecycle overview:\n * - App loads → FlagClient constructed → initialize() begins.\n * - Cached flags applied → subscribers notified → React renders cached values.\n * - Transport set up → initial fetch → store updated → subscribers notified.\n * - Subsequent server updates propagate via client.subscribe to re-render consumers.\n * - When context changes (updateContext), flags are re-fetched and the store is refreshed.\n *\n * @param props Component props: children, client options, optional initial flags, and deferInitialization flag.\n * @returns A provider that supplies the flag store context to its children.\n */\nexport function FlagmintProvider<\n T extends FlagClient<T, C>,\n C extends Record<string, any> = Record<string, any>\n>({\n children,\n options,\n initialFlags = {},\n deferInitialization = false\n}: FlagmintProviderProps<T, C>) {\n // Create a new store instance for each provider (per-request in SSR)\n const store = useMemo(() => createFlagStore(initialFlags), [])\n \n // Use ref to avoid recreating client on every render\n const clientRef = useRef<FlagClient<T, C> | null>(null)\n const initPromiseRef = useRef<Promise<FlagClient<T, C>> | null>(null)\n const unsubscribeRef = useRef<(() => void) | null>(null)\n \n // Initialization function similar to Vue plugin\n const init = async (): Promise<FlagClient<T, C>> => {\n if (clientRef.current) return clientRef.current // Avoid re-init\n \n // Return existing promise if init is already in progress\n if (initPromiseRef.current) return initPromiseRef.current\n \n const { setClient, setReady, setInitialized, setFlags } = store.getState()\n \n initPromiseRef.current = (async () => {\n try {\n // Create the FlagClient\n const client = new FlagClient<T, C>(options)\n \n // Wait for client to be ready\n await client.ready()\n \n // Get initial flags from client\n const initialClientFlags = client.getFlags()\n setFlags(initialClientFlags)\n \n // Subscribe to flag changes - THIS IS THE KEY FIX\n const unsubscribe = client.subscribe((updatedFlags: Flags) => {\n // Get fresh reference each time\n const currentStore = store.getState();\n currentStore.setFlags(updatedFlags);\n })\n \n unsubscribeRef.current = unsubscribe\n \n clientRef.current = client\n setClient(client)\n setReady(true)\n setInitialized(true)\n \n return client\n } catch (error) {\n console.error('Failed to initialize Flagmint client:', error)\n throw error\n }\n })()\n \n return initPromiseRef.current\n }\n\n useEffect(() => {\n if (!deferInitialization) {\n init().catch(error => {\n console.error('Auto-initialization failed:', error)\n })\n }\n\n return () => {\n // Unsubscribe from flag changes\n if (unsubscribeRef.current) {\n unsubscribeRef.current()\n unsubscribeRef.current = null\n }\n \n // Destroy client\n if (clientRef.current) {\n clientRef.current.destroy?.()\n clientRef.current = null\n initPromiseRef.current = null\n }\n }\n }, [deferInitialization])\n\n return (\n <FlagmintStoreContext.Provider value={store}>\n {children}\n </FlagmintStoreContext.Provider>\n )\n}\n","'use client';\nimport { FlagValue } from \"flagmint-js-sdk\"\nimport { useContext } from \"react\"\nimport { StoreApi, useStore } from \"zustand\"\nimport { FlagmintStoreContext } from \"@/providers/FlagmintProvider\"\nimport { FlagStore, Flags } from \"@/types\"\n\n// Helper to get the store from context\nexport function useFlagmintStore(): StoreApi<FlagStore> {\n const store = useContext(FlagmintStoreContext)\n if (!store) {\n throw new Error('useFlagmintStore must be used within a FlagmintProvider')\n }\n return store\n}\n\n// Hook to get the client instance and update context\nexport function useFlagmint() {\n const store = useFlagmintStore()\n const client = useStore(store, (state) => state.client)\n const isInitialized = useStore(store, (state) => state.isInitialized)\n\n const updateContext = async (context: Record<string, any>) => {\n if (!client) {\n throw new Error('Flagmint client not initialized')\n }\n await client.updateContext(context)\n }\n\n return {\n client,\n isInitialized,\n updateContext\n }\n}\n\n// Hook to get all flags - only re-renders when flags change\nexport function useFlags(): Flags {\n const store = useFlagmintStore()\n if (!store) {\n return {};\n }\n return useStore(store, (state) => state.flags)\n}\n\n// Simplified useFlag - just read from the reactive store\nexport function useFlag<T = FlagValue>(\n key: string,\n fallback?: T\n): T {\n const store = useFlagmintStore()\n if (!store) {\n return fallback as T;\n }\n // Subscribe to this specific flag in the store\n const flagValue = useStore(store, (state) => state.flags[key])\n \n // Return the flag value or fallback\n return (flagValue ?? fallback) as T\n}\n\n// Hook to check if the client is ready\nexport function useFlagmintReady(): boolean {\n const store = useFlagmintStore()\n if (!store) {\n return false;\n }\n // Subscribe to both isReady and isInitialized\n const isReady = useStore(store, (state) => state.isReady)\n const isInitialized = useStore(store, (state) => state.isInitialized)\n \n return isReady && isInitialized\n}"]}
package/dist/index.cjs CHANGED
@@ -108,15 +108,24 @@ function useFlagmint() {
108
108
  }
109
109
  function useFlags() {
110
110
  const store = useFlagmintStore();
111
+ if (!store) {
112
+ return {};
113
+ }
111
114
  return zustand.useStore(store, (state) => state.flags);
112
115
  }
113
116
  function useFlag(key, fallback) {
114
117
  const store = useFlagmintStore();
118
+ if (!store) {
119
+ return fallback;
120
+ }
115
121
  const flagValue = zustand.useStore(store, (state) => state.flags[key]);
116
122
  return flagValue != null ? flagValue : fallback;
117
123
  }
118
124
  function useFlagmintReady() {
119
125
  const store = useFlagmintStore();
126
+ if (!store) {
127
+ return false;
128
+ }
120
129
  const isReady = zustand.useStore(store, (state) => state.isReady);
121
130
  const isInitialized = zustand.useStore(store, (state) => state.isInitialized);
122
131
  return isReady && isInitialized;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/store/store.ts","../src/providers/FlagmintProvider.tsx","../src/hooks/index.ts"],"names":["createStore","createContext","useMemo","useRef","FlagClient","useEffect","useContext","useStore"],"mappings":"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","file":"index.cjs","sourcesContent":["'use client';\nimport { createStore, StoreApi } from \"zustand/vanilla\";\nimport { Flags, FlagStore } from \"@/types\";\n\n\nexport function createFlagStore(initialFlags: Flags = {}): StoreApi<FlagStore> {\n return createStore<FlagStore>((set, get) => ({\n flags: initialFlags,\n client: null,\n isInitialized: false,\n isReady: false,\n setFlags: (flags) => {\n set({ flags: { ...flags } })\n },\n setFlag: (key, value) => set((state) => ({\n flags: { ...state.flags, [key]: value }\n })),\n setClient: (client) => set({ client }),\n setInitialized: (initialized) => set({ isInitialized: initialized }),\n setReady: (ready) => set({ isReady: ready })\n }))\n}\n","'use client';\nimport { FlagClient } from \"flagmint-js-sdk\"\nimport { useMemo, useRef, useEffect, createContext } from \"react\"\nimport { createFlagStore } from \"@/store/store\"\nimport { FlagmintProviderProps, Flags, FlagStore } from \"@/types\"\nimport { StoreApi } from \"zustand\"\n\nexport const FlagmintStoreContext = createContext<StoreApi<FlagStore> | null>(null)\n\n/**\n * Provides the Flagmint flag store to React components and keeps it synced with FlagClient updates.\n * Lifecycle overview:\n * - App loads → FlagClient constructed → initialize() begins.\n * - Cached flags applied → subscribers notified → React renders cached values.\n * - Transport set up → initial fetch → store updated → subscribers notified.\n * - Subsequent server updates propagate via client.subscribe to re-render consumers.\n * - When context changes (updateContext), flags are re-fetched and the store is refreshed.\n *\n * @param props Component props: children, client options, optional initial flags, and deferInitialization flag.\n * @returns A provider that supplies the flag store context to its children.\n */\nexport function FlagmintProvider<\n T extends FlagClient<T, C>,\n C extends Record<string, any> = Record<string, any>\n>({\n children,\n options,\n initialFlags = {},\n deferInitialization = false\n}: FlagmintProviderProps<T, C>) {\n // Create a new store instance for each provider (per-request in SSR)\n const store = useMemo(() => createFlagStore(initialFlags), [])\n \n // Use ref to avoid recreating client on every render\n const clientRef = useRef<FlagClient<T, C> | null>(null)\n const initPromiseRef = useRef<Promise<FlagClient<T, C>> | null>(null)\n const unsubscribeRef = useRef<(() => void) | null>(null)\n \n // Initialization function similar to Vue plugin\n const init = async (): Promise<FlagClient<T, C>> => {\n if (clientRef.current) return clientRef.current // Avoid re-init\n \n // Return existing promise if init is already in progress\n if (initPromiseRef.current) return initPromiseRef.current\n \n const { setClient, setReady, setInitialized, setFlags } = store.getState()\n \n initPromiseRef.current = (async () => {\n try {\n // Create the FlagClient\n const client = new FlagClient<T, C>(options)\n \n // Wait for client to be ready\n await client.ready()\n \n // Get initial flags from client\n const initialClientFlags = client.getFlags()\n setFlags(initialClientFlags)\n \n // Subscribe to flag changes - THIS IS THE KEY FIX\n const unsubscribe = client.subscribe((updatedFlags: Flags) => {\n // Get fresh reference each time\n const currentStore = store.getState();\n currentStore.setFlags(updatedFlags);\n })\n \n unsubscribeRef.current = unsubscribe\n \n clientRef.current = client\n setClient(client)\n setReady(true)\n setInitialized(true)\n \n return client\n } catch (error) {\n console.error('Failed to initialize Flagmint client:', error)\n throw error\n }\n })()\n \n return initPromiseRef.current\n }\n\n useEffect(() => {\n if (!deferInitialization) {\n init().catch(error => {\n console.error('Auto-initialization failed:', error)\n })\n }\n\n return () => {\n // Unsubscribe from flag changes\n if (unsubscribeRef.current) {\n unsubscribeRef.current()\n unsubscribeRef.current = null\n }\n \n // Destroy client\n if (clientRef.current) {\n clientRef.current.destroy?.()\n clientRef.current = null\n initPromiseRef.current = null\n }\n }\n }, [deferInitialization])\n\n return (\n <FlagmintStoreContext.Provider value={store}>\n {children}\n </FlagmintStoreContext.Provider>\n )\n}\n","'use client';\nimport { FlagValue } from \"flagmint-js-sdk\"\nimport { useContext } from \"react\"\nimport { StoreApi, useStore } from \"zustand\"\nimport { FlagmintStoreContext } from \"@/providers/FlagmintProvider\"\nimport { FlagStore, Flags } from \"@/types\"\n\n// Helper to get the store from context\nexport function useFlagmintStore(): StoreApi<FlagStore> {\n const store = useContext(FlagmintStoreContext)\n if (!store) {\n throw new Error('useFlagmintStore must be used within a FlagmintProvider')\n }\n return store\n}\n\n// Hook to get the client instance and update context\nexport function useFlagmint() {\n const store = useFlagmintStore()\n const client = useStore(store, (state) => state.client)\n const isInitialized = useStore(store, (state) => state.isInitialized)\n\n const updateContext = async (context: Record<string, any>) => {\n if (!client) {\n throw new Error('Flagmint client not initialized')\n }\n await client.updateContext(context)\n }\n\n return {\n client,\n isInitialized,\n updateContext\n }\n}\n\n// Hook to get all flags - only re-renders when flags change\nexport function useFlags(): Flags {\n const store = useFlagmintStore()\n return useStore(store, (state) => state.flags)\n}\n\n// Simplified useFlag - just read from the reactive store\nexport function useFlag<T = FlagValue>(\n key: string,\n fallback?: T\n): T {\n const store = useFlagmintStore()\n \n // Subscribe to this specific flag in the store\n const flagValue = useStore(store, (state) => state.flags[key])\n \n // Return the flag value or fallback\n return (flagValue ?? fallback) as T\n}\n\n// Hook to check if the client is ready\nexport function useFlagmintReady(): boolean {\n const store = useFlagmintStore()\n \n // Subscribe to both isReady and isInitialized\n const isReady = useStore(store, (state) => state.isReady)\n const isInitialized = useStore(store, (state) => state.isInitialized)\n \n return isReady && isInitialized\n}"]}
1
+ {"version":3,"sources":["../src/store/store.ts","../src/providers/FlagmintProvider.tsx","../src/hooks/index.ts"],"names":["createStore","createContext","useMemo","useRef","FlagClient","useEffect","useContext","useStore"],"mappings":"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","file":"index.cjs","sourcesContent":["'use client';\nimport { createStore, StoreApi } from \"zustand/vanilla\";\nimport { Flags, FlagStore } from \"@/types\";\n\n\nexport function createFlagStore(initialFlags: Flags = {}): StoreApi<FlagStore> {\n return createStore<FlagStore>((set, get) => ({\n flags: initialFlags,\n client: null,\n isInitialized: false,\n isReady: false,\n setFlags: (flags) => {\n set({ flags: { ...flags } })\n },\n setFlag: (key, value) => set((state) => ({\n flags: { ...state.flags, [key]: value }\n })),\n setClient: (client) => set({ client }),\n setInitialized: (initialized) => set({ isInitialized: initialized }),\n setReady: (ready) => set({ isReady: ready })\n }))\n}\n","'use client';\nimport { FlagClient } from \"flagmint-js-sdk\"\nimport { useMemo, useRef, useEffect, createContext } from \"react\"\nimport { createFlagStore } from \"@/store/store\"\nimport { FlagmintProviderProps, Flags, FlagStore } from \"@/types\"\nimport { StoreApi } from \"zustand\"\n\nexport const FlagmintStoreContext = createContext<StoreApi<FlagStore> | null>(null)\n\n/**\n * Provides the Flagmint flag store to React components and keeps it synced with FlagClient updates.\n * Lifecycle overview:\n * - App loads → FlagClient constructed → initialize() begins.\n * - Cached flags applied → subscribers notified → React renders cached values.\n * - Transport set up → initial fetch → store updated → subscribers notified.\n * - Subsequent server updates propagate via client.subscribe to re-render consumers.\n * - When context changes (updateContext), flags are re-fetched and the store is refreshed.\n *\n * @param props Component props: children, client options, optional initial flags, and deferInitialization flag.\n * @returns A provider that supplies the flag store context to its children.\n */\nexport function FlagmintProvider<\n T extends FlagClient<T, C>,\n C extends Record<string, any> = Record<string, any>\n>({\n children,\n options,\n initialFlags = {},\n deferInitialization = false\n}: FlagmintProviderProps<T, C>) {\n // Create a new store instance for each provider (per-request in SSR)\n const store = useMemo(() => createFlagStore(initialFlags), [])\n \n // Use ref to avoid recreating client on every render\n const clientRef = useRef<FlagClient<T, C> | null>(null)\n const initPromiseRef = useRef<Promise<FlagClient<T, C>> | null>(null)\n const unsubscribeRef = useRef<(() => void) | null>(null)\n \n // Initialization function similar to Vue plugin\n const init = async (): Promise<FlagClient<T, C>> => {\n if (clientRef.current) return clientRef.current // Avoid re-init\n \n // Return existing promise if init is already in progress\n if (initPromiseRef.current) return initPromiseRef.current\n \n const { setClient, setReady, setInitialized, setFlags } = store.getState()\n \n initPromiseRef.current = (async () => {\n try {\n // Create the FlagClient\n const client = new FlagClient<T, C>(options)\n \n // Wait for client to be ready\n await client.ready()\n \n // Get initial flags from client\n const initialClientFlags = client.getFlags()\n setFlags(initialClientFlags)\n \n // Subscribe to flag changes - THIS IS THE KEY FIX\n const unsubscribe = client.subscribe((updatedFlags: Flags) => {\n // Get fresh reference each time\n const currentStore = store.getState();\n currentStore.setFlags(updatedFlags);\n })\n \n unsubscribeRef.current = unsubscribe\n \n clientRef.current = client\n setClient(client)\n setReady(true)\n setInitialized(true)\n \n return client\n } catch (error) {\n console.error('Failed to initialize Flagmint client:', error)\n throw error\n }\n })()\n \n return initPromiseRef.current\n }\n\n useEffect(() => {\n if (!deferInitialization) {\n init().catch(error => {\n console.error('Auto-initialization failed:', error)\n })\n }\n\n return () => {\n // Unsubscribe from flag changes\n if (unsubscribeRef.current) {\n unsubscribeRef.current()\n unsubscribeRef.current = null\n }\n \n // Destroy client\n if (clientRef.current) {\n clientRef.current.destroy?.()\n clientRef.current = null\n initPromiseRef.current = null\n }\n }\n }, [deferInitialization])\n\n return (\n <FlagmintStoreContext.Provider value={store}>\n {children}\n </FlagmintStoreContext.Provider>\n )\n}\n","'use client';\nimport { FlagValue } from \"flagmint-js-sdk\"\nimport { useContext } from \"react\"\nimport { StoreApi, useStore } from \"zustand\"\nimport { FlagmintStoreContext } from \"@/providers/FlagmintProvider\"\nimport { FlagStore, Flags } from \"@/types\"\n\n// Helper to get the store from context\nexport function useFlagmintStore(): StoreApi<FlagStore> {\n const store = useContext(FlagmintStoreContext)\n if (!store) {\n throw new Error('useFlagmintStore must be used within a FlagmintProvider')\n }\n return store\n}\n\n// Hook to get the client instance and update context\nexport function useFlagmint() {\n const store = useFlagmintStore()\n const client = useStore(store, (state) => state.client)\n const isInitialized = useStore(store, (state) => state.isInitialized)\n\n const updateContext = async (context: Record<string, any>) => {\n if (!client) {\n throw new Error('Flagmint client not initialized')\n }\n await client.updateContext(context)\n }\n\n return {\n client,\n isInitialized,\n updateContext\n }\n}\n\n// Hook to get all flags - only re-renders when flags change\nexport function useFlags(): Flags {\n const store = useFlagmintStore()\n if (!store) {\n return {};\n }\n return useStore(store, (state) => state.flags)\n}\n\n// Simplified useFlag - just read from the reactive store\nexport function useFlag<T = FlagValue>(\n key: string,\n fallback?: T\n): T {\n const store = useFlagmintStore()\n if (!store) {\n return fallback as T;\n }\n // Subscribe to this specific flag in the store\n const flagValue = useStore(store, (state) => state.flags[key])\n \n // Return the flag value or fallback\n return (flagValue ?? fallback) as T\n}\n\n// Hook to check if the client is ready\nexport function useFlagmintReady(): boolean {\n const store = useFlagmintStore()\n if (!store) {\n return false;\n }\n // Subscribe to both isReady and isInitialized\n const isReady = useStore(store, (state) => state.isReady)\n const isInitialized = useStore(store, (state) => state.isInitialized)\n \n return isReady && isInitialized\n}"]}
package/dist/index.js CHANGED
@@ -106,15 +106,24 @@ function useFlagmint() {
106
106
  }
107
107
  function useFlags() {
108
108
  const store = useFlagmintStore();
109
+ if (!store) {
110
+ return {};
111
+ }
109
112
  return useStore(store, (state) => state.flags);
110
113
  }
111
114
  function useFlag(key, fallback) {
112
115
  const store = useFlagmintStore();
116
+ if (!store) {
117
+ return fallback;
118
+ }
113
119
  const flagValue = useStore(store, (state) => state.flags[key]);
114
120
  return flagValue != null ? flagValue : fallback;
115
121
  }
116
122
  function useFlagmintReady() {
117
123
  const store = useFlagmintStore();
124
+ if (!store) {
125
+ return false;
126
+ }
118
127
  const isReady = useStore(store, (state) => state.isReady);
119
128
  const isInitialized = useStore(store, (state) => state.isInitialized);
120
129
  return isReady && isInitialized;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/store/store.ts","../src/providers/FlagmintProvider.tsx","../src/hooks/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["'use client';\nimport { createStore, StoreApi } from \"zustand/vanilla\";\nimport { Flags, FlagStore } from \"@/types\";\n\n\nexport function createFlagStore(initialFlags: Flags = {}): StoreApi<FlagStore> {\n return createStore<FlagStore>((set, get) => ({\n flags: initialFlags,\n client: null,\n isInitialized: false,\n isReady: false,\n setFlags: (flags) => {\n set({ flags: { ...flags } })\n },\n setFlag: (key, value) => set((state) => ({\n flags: { ...state.flags, [key]: value }\n })),\n setClient: (client) => set({ client }),\n setInitialized: (initialized) => set({ isInitialized: initialized }),\n setReady: (ready) => set({ isReady: ready })\n }))\n}\n","'use client';\nimport { FlagClient } from \"flagmint-js-sdk\"\nimport { useMemo, useRef, useEffect, createContext } from \"react\"\nimport { createFlagStore } from \"@/store/store\"\nimport { FlagmintProviderProps, Flags, FlagStore } from \"@/types\"\nimport { StoreApi } from \"zustand\"\n\nexport const FlagmintStoreContext = createContext<StoreApi<FlagStore> | null>(null)\n\n/**\n * Provides the Flagmint flag store to React components and keeps it synced with FlagClient updates.\n * Lifecycle overview:\n * - App loads → FlagClient constructed → initialize() begins.\n * - Cached flags applied → subscribers notified → React renders cached values.\n * - Transport set up → initial fetch → store updated → subscribers notified.\n * - Subsequent server updates propagate via client.subscribe to re-render consumers.\n * - When context changes (updateContext), flags are re-fetched and the store is refreshed.\n *\n * @param props Component props: children, client options, optional initial flags, and deferInitialization flag.\n * @returns A provider that supplies the flag store context to its children.\n */\nexport function FlagmintProvider<\n T extends FlagClient<T, C>,\n C extends Record<string, any> = Record<string, any>\n>({\n children,\n options,\n initialFlags = {},\n deferInitialization = false\n}: FlagmintProviderProps<T, C>) {\n // Create a new store instance for each provider (per-request in SSR)\n const store = useMemo(() => createFlagStore(initialFlags), [])\n \n // Use ref to avoid recreating client on every render\n const clientRef = useRef<FlagClient<T, C> | null>(null)\n const initPromiseRef = useRef<Promise<FlagClient<T, C>> | null>(null)\n const unsubscribeRef = useRef<(() => void) | null>(null)\n \n // Initialization function similar to Vue plugin\n const init = async (): Promise<FlagClient<T, C>> => {\n if (clientRef.current) return clientRef.current // Avoid re-init\n \n // Return existing promise if init is already in progress\n if (initPromiseRef.current) return initPromiseRef.current\n \n const { setClient, setReady, setInitialized, setFlags } = store.getState()\n \n initPromiseRef.current = (async () => {\n try {\n // Create the FlagClient\n const client = new FlagClient<T, C>(options)\n \n // Wait for client to be ready\n await client.ready()\n \n // Get initial flags from client\n const initialClientFlags = client.getFlags()\n setFlags(initialClientFlags)\n \n // Subscribe to flag changes - THIS IS THE KEY FIX\n const unsubscribe = client.subscribe((updatedFlags: Flags) => {\n // Get fresh reference each time\n const currentStore = store.getState();\n currentStore.setFlags(updatedFlags);\n })\n \n unsubscribeRef.current = unsubscribe\n \n clientRef.current = client\n setClient(client)\n setReady(true)\n setInitialized(true)\n \n return client\n } catch (error) {\n console.error('Failed to initialize Flagmint client:', error)\n throw error\n }\n })()\n \n return initPromiseRef.current\n }\n\n useEffect(() => {\n if (!deferInitialization) {\n init().catch(error => {\n console.error('Auto-initialization failed:', error)\n })\n }\n\n return () => {\n // Unsubscribe from flag changes\n if (unsubscribeRef.current) {\n unsubscribeRef.current()\n unsubscribeRef.current = null\n }\n \n // Destroy client\n if (clientRef.current) {\n clientRef.current.destroy?.()\n clientRef.current = null\n initPromiseRef.current = null\n }\n }\n }, [deferInitialization])\n\n return (\n <FlagmintStoreContext.Provider value={store}>\n {children}\n </FlagmintStoreContext.Provider>\n )\n}\n","'use client';\nimport { FlagValue } from \"flagmint-js-sdk\"\nimport { useContext } from \"react\"\nimport { StoreApi, useStore } from \"zustand\"\nimport { FlagmintStoreContext } from \"@/providers/FlagmintProvider\"\nimport { FlagStore, Flags } from \"@/types\"\n\n// Helper to get the store from context\nexport function useFlagmintStore(): StoreApi<FlagStore> {\n const store = useContext(FlagmintStoreContext)\n if (!store) {\n throw new Error('useFlagmintStore must be used within a FlagmintProvider')\n }\n return store\n}\n\n// Hook to get the client instance and update context\nexport function useFlagmint() {\n const store = useFlagmintStore()\n const client = useStore(store, (state) => state.client)\n const isInitialized = useStore(store, (state) => state.isInitialized)\n\n const updateContext = async (context: Record<string, any>) => {\n if (!client) {\n throw new Error('Flagmint client not initialized')\n }\n await client.updateContext(context)\n }\n\n return {\n client,\n isInitialized,\n updateContext\n }\n}\n\n// Hook to get all flags - only re-renders when flags change\nexport function useFlags(): Flags {\n const store = useFlagmintStore()\n return useStore(store, (state) => state.flags)\n}\n\n// Simplified useFlag - just read from the reactive store\nexport function useFlag<T = FlagValue>(\n key: string,\n fallback?: T\n): T {\n const store = useFlagmintStore()\n \n // Subscribe to this specific flag in the store\n const flagValue = useStore(store, (state) => state.flags[key])\n \n // Return the flag value or fallback\n return (flagValue ?? fallback) as T\n}\n\n// Hook to check if the client is ready\nexport function useFlagmintReady(): boolean {\n const store = useFlagmintStore()\n \n // Subscribe to both isReady and isInitialized\n const isReady = useStore(store, (state) => state.isReady)\n const isInitialized = useStore(store, (state) => state.isInitialized)\n \n return isReady && isInitialized\n}"]}
1
+ {"version":3,"sources":["../src/store/store.ts","../src/providers/FlagmintProvider.tsx","../src/hooks/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["'use client';\nimport { createStore, StoreApi } from \"zustand/vanilla\";\nimport { Flags, FlagStore } from \"@/types\";\n\n\nexport function createFlagStore(initialFlags: Flags = {}): StoreApi<FlagStore> {\n return createStore<FlagStore>((set, get) => ({\n flags: initialFlags,\n client: null,\n isInitialized: false,\n isReady: false,\n setFlags: (flags) => {\n set({ flags: { ...flags } })\n },\n setFlag: (key, value) => set((state) => ({\n flags: { ...state.flags, [key]: value }\n })),\n setClient: (client) => set({ client }),\n setInitialized: (initialized) => set({ isInitialized: initialized }),\n setReady: (ready) => set({ isReady: ready })\n }))\n}\n","'use client';\nimport { FlagClient } from \"flagmint-js-sdk\"\nimport { useMemo, useRef, useEffect, createContext } from \"react\"\nimport { createFlagStore } from \"@/store/store\"\nimport { FlagmintProviderProps, Flags, FlagStore } from \"@/types\"\nimport { StoreApi } from \"zustand\"\n\nexport const FlagmintStoreContext = createContext<StoreApi<FlagStore> | null>(null)\n\n/**\n * Provides the Flagmint flag store to React components and keeps it synced with FlagClient updates.\n * Lifecycle overview:\n * - App loads → FlagClient constructed → initialize() begins.\n * - Cached flags applied → subscribers notified → React renders cached values.\n * - Transport set up → initial fetch → store updated → subscribers notified.\n * - Subsequent server updates propagate via client.subscribe to re-render consumers.\n * - When context changes (updateContext), flags are re-fetched and the store is refreshed.\n *\n * @param props Component props: children, client options, optional initial flags, and deferInitialization flag.\n * @returns A provider that supplies the flag store context to its children.\n */\nexport function FlagmintProvider<\n T extends FlagClient<T, C>,\n C extends Record<string, any> = Record<string, any>\n>({\n children,\n options,\n initialFlags = {},\n deferInitialization = false\n}: FlagmintProviderProps<T, C>) {\n // Create a new store instance for each provider (per-request in SSR)\n const store = useMemo(() => createFlagStore(initialFlags), [])\n \n // Use ref to avoid recreating client on every render\n const clientRef = useRef<FlagClient<T, C> | null>(null)\n const initPromiseRef = useRef<Promise<FlagClient<T, C>> | null>(null)\n const unsubscribeRef = useRef<(() => void) | null>(null)\n \n // Initialization function similar to Vue plugin\n const init = async (): Promise<FlagClient<T, C>> => {\n if (clientRef.current) return clientRef.current // Avoid re-init\n \n // Return existing promise if init is already in progress\n if (initPromiseRef.current) return initPromiseRef.current\n \n const { setClient, setReady, setInitialized, setFlags } = store.getState()\n \n initPromiseRef.current = (async () => {\n try {\n // Create the FlagClient\n const client = new FlagClient<T, C>(options)\n \n // Wait for client to be ready\n await client.ready()\n \n // Get initial flags from client\n const initialClientFlags = client.getFlags()\n setFlags(initialClientFlags)\n \n // Subscribe to flag changes - THIS IS THE KEY FIX\n const unsubscribe = client.subscribe((updatedFlags: Flags) => {\n // Get fresh reference each time\n const currentStore = store.getState();\n currentStore.setFlags(updatedFlags);\n })\n \n unsubscribeRef.current = unsubscribe\n \n clientRef.current = client\n setClient(client)\n setReady(true)\n setInitialized(true)\n \n return client\n } catch (error) {\n console.error('Failed to initialize Flagmint client:', error)\n throw error\n }\n })()\n \n return initPromiseRef.current\n }\n\n useEffect(() => {\n if (!deferInitialization) {\n init().catch(error => {\n console.error('Auto-initialization failed:', error)\n })\n }\n\n return () => {\n // Unsubscribe from flag changes\n if (unsubscribeRef.current) {\n unsubscribeRef.current()\n unsubscribeRef.current = null\n }\n \n // Destroy client\n if (clientRef.current) {\n clientRef.current.destroy?.()\n clientRef.current = null\n initPromiseRef.current = null\n }\n }\n }, [deferInitialization])\n\n return (\n <FlagmintStoreContext.Provider value={store}>\n {children}\n </FlagmintStoreContext.Provider>\n )\n}\n","'use client';\nimport { FlagValue } from \"flagmint-js-sdk\"\nimport { useContext } from \"react\"\nimport { StoreApi, useStore } from \"zustand\"\nimport { FlagmintStoreContext } from \"@/providers/FlagmintProvider\"\nimport { FlagStore, Flags } from \"@/types\"\n\n// Helper to get the store from context\nexport function useFlagmintStore(): StoreApi<FlagStore> {\n const store = useContext(FlagmintStoreContext)\n if (!store) {\n throw new Error('useFlagmintStore must be used within a FlagmintProvider')\n }\n return store\n}\n\n// Hook to get the client instance and update context\nexport function useFlagmint() {\n const store = useFlagmintStore()\n const client = useStore(store, (state) => state.client)\n const isInitialized = useStore(store, (state) => state.isInitialized)\n\n const updateContext = async (context: Record<string, any>) => {\n if (!client) {\n throw new Error('Flagmint client not initialized')\n }\n await client.updateContext(context)\n }\n\n return {\n client,\n isInitialized,\n updateContext\n }\n}\n\n// Hook to get all flags - only re-renders when flags change\nexport function useFlags(): Flags {\n const store = useFlagmintStore()\n if (!store) {\n return {};\n }\n return useStore(store, (state) => state.flags)\n}\n\n// Simplified useFlag - just read from the reactive store\nexport function useFlag<T = FlagValue>(\n key: string,\n fallback?: T\n): T {\n const store = useFlagmintStore()\n if (!store) {\n return fallback as T;\n }\n // Subscribe to this specific flag in the store\n const flagValue = useStore(store, (state) => state.flags[key])\n \n // Return the flag value or fallback\n return (flagValue ?? fallback) as T\n}\n\n// Hook to check if the client is ready\nexport function useFlagmintReady(): boolean {\n const store = useFlagmintStore()\n if (!store) {\n return false;\n }\n // Subscribe to both isReady and isInitialized\n const isReady = useStore(store, (state) => state.isReady)\n const isInitialized = useStore(store, (state) => state.isInitialized)\n \n return isReady && isInitialized\n}"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flagmint-react-sdk",
3
- "version": "0.7.11",
3
+ "version": "0.7.13",
4
4
  "description": "React wrapper for flagmint-js-sdk",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -31,7 +31,7 @@
31
31
  "react-dom": ">=18.0.0"
32
32
  },
33
33
  "dependencies": {
34
- "flagmint-js-sdk": "^1.2.4",
34
+ "flagmint-js-sdk": "^1.2.5",
35
35
  "zustand": "^4.4.0"
36
36
  },
37
37
  "devDependencies": {