flagmint-react-sdk 0.7.1 → 0.7.3
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/dist/client.cjs +8 -3
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +45 -7
- package/dist/client.d.ts +45 -7
- package/dist/client.js +8 -4
- package/dist/client.js.map +1 -1
- package/dist/index.cjs +133 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -40
- package/dist/index.d.ts +6 -40
- package/dist/index.js +125 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/client.cjs
CHANGED
|
@@ -12,7 +12,10 @@ function createFlagStore(initialFlags = {}) {
|
|
|
12
12
|
client: null,
|
|
13
13
|
isInitialized: false,
|
|
14
14
|
isReady: false,
|
|
15
|
-
setFlags: (flags) =>
|
|
15
|
+
setFlags: (flags) => {
|
|
16
|
+
console.log("Updating store flags:", flags);
|
|
17
|
+
set({ flags: { ...flags } });
|
|
18
|
+
},
|
|
16
19
|
setFlag: (key, value) => set((state) => ({
|
|
17
20
|
flags: { ...state.flags, [key]: value }
|
|
18
21
|
})),
|
|
@@ -28,7 +31,7 @@ function FlagmintProvider({
|
|
|
28
31
|
initialFlags = {},
|
|
29
32
|
deferInitialization = false
|
|
30
33
|
}) {
|
|
31
|
-
const store = react.useMemo(() => createFlagStore(initialFlags), [
|
|
34
|
+
const store = react.useMemo(() => createFlagStore(initialFlags), []);
|
|
32
35
|
const clientRef = react.useRef(null);
|
|
33
36
|
const initPromiseRef = react.useRef(null);
|
|
34
37
|
const unsubscribeRef = react.useRef(null);
|
|
@@ -44,7 +47,8 @@ function FlagmintProvider({
|
|
|
44
47
|
setFlags(initialClientFlags);
|
|
45
48
|
const unsubscribe = client.subscribe((updatedFlags) => {
|
|
46
49
|
console.log("FlagmintProvider - flags updated:", updatedFlags);
|
|
47
|
-
|
|
50
|
+
const currentStore = store.getState();
|
|
51
|
+
currentStore.setFlags(updatedFlags);
|
|
48
52
|
});
|
|
49
53
|
unsubscribeRef.current = unsubscribe;
|
|
50
54
|
clientRef.current = client;
|
|
@@ -122,6 +126,7 @@ function useFlagmintReady() {
|
|
|
122
126
|
|
|
123
127
|
exports.FlagmintProvider = FlagmintProvider;
|
|
124
128
|
exports.FlagmintStoreContext = FlagmintStoreContext;
|
|
129
|
+
exports.createFlagStore = createFlagStore;
|
|
125
130
|
exports.useFlag = useFlag;
|
|
126
131
|
exports.useFlagmint = useFlagmint;
|
|
127
132
|
exports.useFlagmintReady = useFlagmintReady;
|
package/dist/client.cjs.map
CHANGED
|
@@ -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) => set({ flags: { ...flags } }),\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), [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 console.log('FlagmintProvider - flags updated:', updatedFlags)\n setFlags(updatedFlags)\n })\n \n unsubscribeRef.current = unsubscribe\n \n clientRef.current = client\n setClient(client)\n setReady(true)\n setInitialized(true)\n \n console.log('FlagmintProvider - initialized with flags:', initialClientFlags)\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 console.log('Updating store flags:', 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 console.log('FlagmintProvider - flags updated:', updatedFlags)\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 console.log('FlagmintProvider - initialized with flags:', initialClientFlags)\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}"]}
|
package/dist/client.d.cts
CHANGED
|
@@ -1,10 +1,46 @@
|
|
|
1
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import * as react from 'react';
|
|
3
1
|
import * as flagmint_js_sdk from 'flagmint-js-sdk';
|
|
4
|
-
import { FlagClient, FlagValue } from 'flagmint-js-sdk';
|
|
5
|
-
import
|
|
6
|
-
|
|
2
|
+
import { FlagClientOptions, FlagClient, FlagValue as FlagValue$1 } from 'flagmint-js-sdk';
|
|
3
|
+
import * as react from 'react';
|
|
4
|
+
import { ReactNode } from 'react';
|
|
5
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
7
6
|
import { StoreApi } from 'zustand';
|
|
7
|
+
import { StoreApi as StoreApi$1 } from 'zustand/vanilla';
|
|
8
|
+
|
|
9
|
+
type FlagValue = string | number | boolean | object | null;
|
|
10
|
+
interface Flags {
|
|
11
|
+
[key: string]: FlagValue;
|
|
12
|
+
}
|
|
13
|
+
interface CoreClientLike {
|
|
14
|
+
getFlags(): Promise<Flags> | Flags;
|
|
15
|
+
getFlag(key: string, fallback?: FlagValue): Promise<FlagValue> | FlagValue;
|
|
16
|
+
subscribe(callback: (flags: Flags) => void): () => void;
|
|
17
|
+
updateContext(context: Record<string, any>): Promise<void> | void;
|
|
18
|
+
init(): Promise<void> | void;
|
|
19
|
+
close(): Promise<void> | void;
|
|
20
|
+
}
|
|
21
|
+
interface FlagStore {
|
|
22
|
+
flags: Flags;
|
|
23
|
+
client: FlagClient<any, any> | null;
|
|
24
|
+
isInitialized: boolean;
|
|
25
|
+
isReady: boolean;
|
|
26
|
+
setFlags: (flags: Flags) => void;
|
|
27
|
+
setFlag: (key: string, value: FlagValue) => void;
|
|
28
|
+
setClient: (client: FlagClient<any, any> | null) => void;
|
|
29
|
+
setInitialized: (initialized: boolean) => void;
|
|
30
|
+
setReady: (ready: boolean) => void;
|
|
31
|
+
}
|
|
32
|
+
interface FlagmintProviderProps {
|
|
33
|
+
children: ReactNode;
|
|
34
|
+
createClient?: () => CoreClientLike;
|
|
35
|
+
client: CoreClientLike;
|
|
36
|
+
initialFlags?: Flags;
|
|
37
|
+
}
|
|
38
|
+
interface FlagmintProviderProps<T = unknown, C extends Record<string, any> = Record<string, any>> {
|
|
39
|
+
children: ReactNode;
|
|
40
|
+
options: FlagClientOptions<C>;
|
|
41
|
+
initialFlags?: Flags;
|
|
42
|
+
deferInitialization?: boolean;
|
|
43
|
+
}
|
|
8
44
|
|
|
9
45
|
declare const FlagmintStoreContext: react.Context<StoreApi<FlagStore> | null>;
|
|
10
46
|
/**
|
|
@@ -28,7 +64,9 @@ declare function useFlagmint(): {
|
|
|
28
64
|
updateContext: (context: Record<string, any>) => Promise<void>;
|
|
29
65
|
};
|
|
30
66
|
declare function useFlags(): Flags;
|
|
31
|
-
declare function useFlag<T = FlagValue>(key: string, fallback?: T): T;
|
|
67
|
+
declare function useFlag<T = FlagValue$1>(key: string, fallback?: T): T;
|
|
32
68
|
declare function useFlagmintReady(): boolean;
|
|
33
69
|
|
|
34
|
-
|
|
70
|
+
declare function createFlagStore(initialFlags?: Flags): StoreApi$1<FlagStore>;
|
|
71
|
+
|
|
72
|
+
export { type CoreClientLike, type FlagStore, type FlagValue, FlagmintProvider, type FlagmintProviderProps, FlagmintStoreContext, type Flags, createFlagStore, useFlag, useFlagmint, useFlagmintReady, useFlagmintStore, useFlags };
|
package/dist/client.d.ts
CHANGED
|
@@ -1,10 +1,46 @@
|
|
|
1
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import * as react from 'react';
|
|
3
1
|
import * as flagmint_js_sdk from 'flagmint-js-sdk';
|
|
4
|
-
import { FlagClient, FlagValue } from 'flagmint-js-sdk';
|
|
5
|
-
import
|
|
6
|
-
|
|
2
|
+
import { FlagClientOptions, FlagClient, FlagValue as FlagValue$1 } from 'flagmint-js-sdk';
|
|
3
|
+
import * as react from 'react';
|
|
4
|
+
import { ReactNode } from 'react';
|
|
5
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
7
6
|
import { StoreApi } from 'zustand';
|
|
7
|
+
import { StoreApi as StoreApi$1 } from 'zustand/vanilla';
|
|
8
|
+
|
|
9
|
+
type FlagValue = string | number | boolean | object | null;
|
|
10
|
+
interface Flags {
|
|
11
|
+
[key: string]: FlagValue;
|
|
12
|
+
}
|
|
13
|
+
interface CoreClientLike {
|
|
14
|
+
getFlags(): Promise<Flags> | Flags;
|
|
15
|
+
getFlag(key: string, fallback?: FlagValue): Promise<FlagValue> | FlagValue;
|
|
16
|
+
subscribe(callback: (flags: Flags) => void): () => void;
|
|
17
|
+
updateContext(context: Record<string, any>): Promise<void> | void;
|
|
18
|
+
init(): Promise<void> | void;
|
|
19
|
+
close(): Promise<void> | void;
|
|
20
|
+
}
|
|
21
|
+
interface FlagStore {
|
|
22
|
+
flags: Flags;
|
|
23
|
+
client: FlagClient<any, any> | null;
|
|
24
|
+
isInitialized: boolean;
|
|
25
|
+
isReady: boolean;
|
|
26
|
+
setFlags: (flags: Flags) => void;
|
|
27
|
+
setFlag: (key: string, value: FlagValue) => void;
|
|
28
|
+
setClient: (client: FlagClient<any, any> | null) => void;
|
|
29
|
+
setInitialized: (initialized: boolean) => void;
|
|
30
|
+
setReady: (ready: boolean) => void;
|
|
31
|
+
}
|
|
32
|
+
interface FlagmintProviderProps {
|
|
33
|
+
children: ReactNode;
|
|
34
|
+
createClient?: () => CoreClientLike;
|
|
35
|
+
client: CoreClientLike;
|
|
36
|
+
initialFlags?: Flags;
|
|
37
|
+
}
|
|
38
|
+
interface FlagmintProviderProps<T = unknown, C extends Record<string, any> = Record<string, any>> {
|
|
39
|
+
children: ReactNode;
|
|
40
|
+
options: FlagClientOptions<C>;
|
|
41
|
+
initialFlags?: Flags;
|
|
42
|
+
deferInitialization?: boolean;
|
|
43
|
+
}
|
|
8
44
|
|
|
9
45
|
declare const FlagmintStoreContext: react.Context<StoreApi<FlagStore> | null>;
|
|
10
46
|
/**
|
|
@@ -28,7 +64,9 @@ declare function useFlagmint(): {
|
|
|
28
64
|
updateContext: (context: Record<string, any>) => Promise<void>;
|
|
29
65
|
};
|
|
30
66
|
declare function useFlags(): Flags;
|
|
31
|
-
declare function useFlag<T = FlagValue>(key: string, fallback?: T): T;
|
|
67
|
+
declare function useFlag<T = FlagValue$1>(key: string, fallback?: T): T;
|
|
32
68
|
declare function useFlagmintReady(): boolean;
|
|
33
69
|
|
|
34
|
-
|
|
70
|
+
declare function createFlagStore(initialFlags?: Flags): StoreApi$1<FlagStore>;
|
|
71
|
+
|
|
72
|
+
export { type CoreClientLike, type FlagStore, type FlagValue, FlagmintProvider, type FlagmintProviderProps, FlagmintStoreContext, type Flags, createFlagStore, useFlag, useFlagmint, useFlagmintReady, useFlagmintStore, useFlags };
|
package/dist/client.js
CHANGED
|
@@ -10,7 +10,10 @@ function createFlagStore(initialFlags = {}) {
|
|
|
10
10
|
client: null,
|
|
11
11
|
isInitialized: false,
|
|
12
12
|
isReady: false,
|
|
13
|
-
setFlags: (flags) =>
|
|
13
|
+
setFlags: (flags) => {
|
|
14
|
+
console.log("Updating store flags:", flags);
|
|
15
|
+
set({ flags: { ...flags } });
|
|
16
|
+
},
|
|
14
17
|
setFlag: (key, value) => set((state) => ({
|
|
15
18
|
flags: { ...state.flags, [key]: value }
|
|
16
19
|
})),
|
|
@@ -26,7 +29,7 @@ function FlagmintProvider({
|
|
|
26
29
|
initialFlags = {},
|
|
27
30
|
deferInitialization = false
|
|
28
31
|
}) {
|
|
29
|
-
const store = useMemo(() => createFlagStore(initialFlags), [
|
|
32
|
+
const store = useMemo(() => createFlagStore(initialFlags), []);
|
|
30
33
|
const clientRef = useRef(null);
|
|
31
34
|
const initPromiseRef = useRef(null);
|
|
32
35
|
const unsubscribeRef = useRef(null);
|
|
@@ -42,7 +45,8 @@ function FlagmintProvider({
|
|
|
42
45
|
setFlags(initialClientFlags);
|
|
43
46
|
const unsubscribe = client.subscribe((updatedFlags) => {
|
|
44
47
|
console.log("FlagmintProvider - flags updated:", updatedFlags);
|
|
45
|
-
|
|
48
|
+
const currentStore = store.getState();
|
|
49
|
+
currentStore.setFlags(updatedFlags);
|
|
46
50
|
});
|
|
47
51
|
unsubscribeRef.current = unsubscribe;
|
|
48
52
|
clientRef.current = client;
|
|
@@ -118,6 +122,6 @@ function useFlagmintReady() {
|
|
|
118
122
|
return isReady && isInitialized;
|
|
119
123
|
}
|
|
120
124
|
|
|
121
|
-
export { FlagmintProvider, FlagmintStoreContext, useFlag, useFlagmint, useFlagmintReady, useFlagmintStore, useFlags };
|
|
125
|
+
export { FlagmintProvider, FlagmintStoreContext, createFlagStore, useFlag, useFlagmint, useFlagmintReady, useFlagmintStore, useFlags };
|
|
122
126
|
//# sourceMappingURL=client.js.map
|
|
123
127
|
//# sourceMappingURL=client.js.map
|
package/dist/client.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":"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) => set({ flags: { ...flags } }),\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), [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 console.log('FlagmintProvider - flags updated:', updatedFlags)\n setFlags(updatedFlags)\n })\n \n unsubscribeRef.current = unsubscribe\n \n clientRef.current = client\n setClient(client)\n setReady(true)\n setInitialized(true)\n \n console.log('FlagmintProvider - initialized with flags:', initialClientFlags)\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":";;;;;;AAKO,SAAS,eAAA,CAAgB,YAAA,GAAsB,EAAC,EAAwB;AAC5E,EAAA,OAAO,WAAA,CAAuB,CAAC,GAAA,EAAK,GAAA,MAAS;AAAA,IAC5C,KAAA,EAAO,YAAA;AAAA,IACP,MAAA,EAAQ,IAAA;AAAA,IACR,aAAA,EAAe,KAAA;AAAA,IACf,OAAA,EAAS,KAAA;AAAA,IACT,QAAA,EAAU,CAAC,KAAA,KAAU;AACnB,MAAA,OAAA,CAAQ,GAAA,CAAI,yBAAyB,KAAK,CAAA;AAC1C,MAAA,GAAA,CAAI,EAAE,KAAA,EAAO,EAAE,GAAG,KAAA,IAAS,CAAA;AAAA,IAC7B,CAAA;AAAA,IACA,SAAS,CAAC,GAAA,EAAK,KAAA,KAAU,GAAA,CAAI,CAAC,KAAA,MAAW;AAAA,MACvC,KAAA,EAAO,EAAE,GAAG,KAAA,CAAM,OAAO,CAAC,GAAG,GAAG,KAAA;AAAM,KACxC,CAAE,CAAA;AAAA,IACF,WAAW,CAAC,MAAA,KAAW,GAAA,CAAI,EAAE,QAAQ,CAAA;AAAA,IACrC,gBAAgB,CAAC,WAAA,KAAgB,IAAI,EAAE,aAAA,EAAe,aAAa,CAAA;AAAA,IACnE,UAAU,CAAC,KAAA,KAAU,IAAI,EAAE,OAAA,EAAS,OAAO;AAAA,GAC7C,CAAE,CAAA;AACJ;ACfO,IAAM,oBAAA,GAAuB,cAA0C,IAAI;AAc3E,SAAS,gBAAA,CAGd;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,eAAe,EAAC;AAAA,EAChB,mBAAA,GAAsB;AACxB,CAAA,EAAgC;AAE9B,EAAA,MAAM,QAAQ,OAAA,CAAQ,MAAM,gBAAgB,YAAY,CAAA,EAAG,EAAE,CAAA;AAG7D,EAAA,MAAM,SAAA,GAAY,OAAgC,IAAI,CAAA;AACtD,EAAA,MAAM,cAAA,GAAiB,OAAyC,IAAI,CAAA;AACpE,EAAA,MAAM,cAAA,GAAiB,OAA4B,IAAI,CAAA;AAGvD,EAAA,MAAM,OAAO,YAAuC;AAClD,IAAA,IAAI,SAAA,CAAU,OAAA,EAAS,OAAO,SAAA,CAAU,OAAA;AAGxC,IAAA,IAAI,cAAA,CAAe,OAAA,EAAS,OAAO,cAAA,CAAe,OAAA;AAElD,IAAA,MAAM,EAAE,SAAA,EAAW,QAAA,EAAU,gBAAgB,QAAA,EAAS,GAAI,MAAM,QAAA,EAAS;AAEzE,IAAA,cAAA,CAAe,WAAW,YAAY;AACpC,MAAA,IAAI;AAEF,QAAA,MAAM,MAAA,GAAS,IAAI,UAAA,CAAiB,OAAO,CAAA;AAG3C,QAAA,MAAM,OAAO,KAAA,EAAM;AAGnB,QAAA,MAAM,kBAAA,GAAqB,OAAO,QAAA,EAAS;AAC3C,QAAA,QAAA,CAAS,kBAAkB,CAAA;AAG3B,QAAA,MAAM,WAAA,GAAc,MAAA,CAAO,SAAA,CAAU,CAAC,YAAA,KAAwB;AAC5D,UAAA,OAAA,CAAQ,GAAA,CAAI,qCAAqC,YAAY,CAAA;AAE7D,UAAA,MAAM,YAAA,GAAe,MAAM,QAAA,EAAS;AACpC,UAAA,YAAA,CAAa,SAAS,YAAY,CAAA;AAAA,QACpC,CAAC,CAAA;AAED,QAAA,cAAA,CAAe,OAAA,GAAU,WAAA;AAEzB,QAAA,SAAA,CAAU,OAAA,GAAU,MAAA;AACpB,QAAA,SAAA,CAAU,MAAM,CAAA;AAChB,QAAA,QAAA,CAAS,IAAI,CAAA;AACb,QAAA,cAAA,CAAe,IAAI,CAAA;AAEnB,QAAA,OAAA,CAAQ,GAAA,CAAI,8CAA8C,kBAAkB,CAAA;AAE5E,QAAA,OAAO,MAAA;AAAA,MACT,SAAS,KAAA,EAAO;AACd,QAAA,OAAA,CAAQ,KAAA,CAAM,yCAAyC,KAAK,CAAA;AAC5D,QAAA,MAAM,KAAA;AAAA,MACR;AAAA,IACF,CAAA,GAAG;AAEH,IAAA,OAAO,cAAA,CAAe,OAAA;AAAA,EACxB,CAAA;AAEA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,mBAAA,EAAqB;AACxB,MAAA,IAAA,EAAK,CAAE,MAAM,CAAA,KAAA,KAAS;AACpB,QAAA,OAAA,CAAQ,KAAA,CAAM,+BAA+B,KAAK,CAAA;AAAA,MACpD,CAAC,CAAA;AAAA,IACH;AAEA,IAAA,OAAO,MAAM;AA7FjB,MAAA,IAAA,EAAA,EAAA,EAAA;AA+FM,MAAA,IAAI,eAAe,OAAA,EAAS;AAC1B,QAAA,cAAA,CAAe,OAAA,EAAQ;AACvB,QAAA,cAAA,CAAe,OAAA,GAAU,IAAA;AAAA,MAC3B;AAGA,MAAA,IAAI,UAAU,OAAA,EAAS;AACrB,QAAA,CAAA,EAAA,GAAA,CAAA,EAAA,GAAA,SAAA,CAAU,SAAQ,OAAA,KAAlB,IAAA,GAAA,MAAA,GAAA,EAAA,CAAA,IAAA,CAAA,EAAA,CAAA;AACA,QAAA,SAAA,CAAU,OAAA,GAAU,IAAA;AACpB,QAAA,cAAA,CAAe,OAAA,GAAU,IAAA;AAAA,MAC3B;AAAA,IACF,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,mBAAmB,CAAC,CAAA;AAExB,EAAA,2BACG,oBAAA,CAAqB,QAAA,EAArB,EAA8B,KAAA,EAAO,OACnC,QAAA,EACH,CAAA;AAEJ;AC1GO,SAAS,gBAAA,GAAwC;AACtD,EAAA,MAAM,KAAA,GAAQ,WAAW,oBAAoB,CAAA;AAC7C,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,MAAM,IAAI,MAAM,yDAAyD,CAAA;AAAA,EAC3E;AACA,EAAA,OAAO,KAAA;AACT;AAGO,SAAS,WAAA,GAAc;AAC5B,EAAA,MAAM,QAAQ,gBAAA,EAAiB;AAC/B,EAAA,MAAM,SAAS,QAAA,CAAS,KAAA,EAAO,CAAC,KAAA,KAAU,MAAM,MAAM,CAAA;AACtD,EAAA,MAAM,gBAAgB,QAAA,CAAS,KAAA,EAAO,CAAC,KAAA,KAAU,MAAM,aAAa,CAAA;AAEpE,EAAA,MAAM,aAAA,GAAgB,OAAO,OAAA,KAAiC;AAC5D,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,MAAM,IAAI,MAAM,iCAAiC,CAAA;AAAA,IACnD;AACA,IAAA,MAAM,MAAA,CAAO,cAAc,OAAO,CAAA;AAAA,EACpC,CAAA;AAEA,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,aAAA;AAAA,IACA;AAAA,GACF;AACF;AAGO,SAAS,QAAA,GAAkB;AAChC,EAAA,MAAM,QAAQ,gBAAA,EAAiB;AAC/B,EAAA,OAAO,QAAA,CAAS,KAAA,EAAO,CAAC,KAAA,KAAU,MAAM,KAAK,CAAA;AAC/C;AAGO,SAAS,OAAA,CACd,KACA,QAAA,EACG;AACH,EAAA,MAAM,QAAQ,gBAAA,EAAiB;AAG/B,EAAA,MAAM,SAAA,GAAY,SAAS,KAAA,EAAO,CAAC,UAAU,KAAA,CAAM,KAAA,CAAM,GAAG,CAAC,CAAA;AAG7D,EAAA,OAAQ,SAAA,IAAA,IAAA,GAAA,SAAA,GAAa,QAAA;AACvB;AAGO,SAAS,gBAAA,GAA4B;AAC1C,EAAA,MAAM,QAAQ,gBAAA,EAAiB;AAG/B,EAAA,MAAM,UAAU,QAAA,CAAS,KAAA,EAAO,CAAC,KAAA,KAAU,MAAM,OAAO,CAAA;AACxD,EAAA,MAAM,gBAAgB,QAAA,CAAS,KAAA,EAAO,CAAC,KAAA,KAAU,MAAM,aAAa,CAAA;AAEpE,EAAA,OAAO,OAAA,IAAW,aAAA;AACpB","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 console.log('Updating store flags:', 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 console.log('FlagmintProvider - flags updated:', updatedFlags)\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 console.log('FlagmintProvider - initialized with flags:', initialClientFlags)\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}"]}
|
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,137 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var flagmintJsSdk = require('flagmint-js-sdk');
|
|
4
|
+
var react = require('react');
|
|
5
|
+
var vanilla = require('zustand/vanilla');
|
|
6
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
7
|
+
var zustand = require('zustand');
|
|
8
|
+
|
|
9
|
+
// src/providers/FlagmintProvider.tsx
|
|
10
|
+
function createFlagStore(initialFlags = {}) {
|
|
11
|
+
return vanilla.createStore((set, get) => ({
|
|
12
|
+
flags: initialFlags,
|
|
13
|
+
client: null,
|
|
14
|
+
isInitialized: false,
|
|
15
|
+
isReady: false,
|
|
16
|
+
setFlags: (flags) => {
|
|
17
|
+
console.log("Updating store flags:", flags);
|
|
18
|
+
set({ flags: { ...flags } });
|
|
19
|
+
},
|
|
20
|
+
setFlag: (key, value) => set((state) => ({
|
|
21
|
+
flags: { ...state.flags, [key]: value }
|
|
22
|
+
})),
|
|
23
|
+
setClient: (client) => set({ client }),
|
|
24
|
+
setInitialized: (initialized) => set({ isInitialized: initialized }),
|
|
25
|
+
setReady: (ready) => set({ isReady: ready })
|
|
26
|
+
}));
|
|
27
|
+
}
|
|
28
|
+
var FlagmintStoreContext = react.createContext(null);
|
|
29
|
+
function FlagmintProvider({
|
|
30
|
+
children,
|
|
31
|
+
options,
|
|
32
|
+
initialFlags = {},
|
|
33
|
+
deferInitialization = false
|
|
34
|
+
}) {
|
|
35
|
+
const store = react.useMemo(() => createFlagStore(initialFlags), []);
|
|
36
|
+
const clientRef = react.useRef(null);
|
|
37
|
+
const initPromiseRef = react.useRef(null);
|
|
38
|
+
const unsubscribeRef = react.useRef(null);
|
|
39
|
+
const init = async () => {
|
|
40
|
+
if (clientRef.current) return clientRef.current;
|
|
41
|
+
if (initPromiseRef.current) return initPromiseRef.current;
|
|
42
|
+
const { setClient, setReady, setInitialized, setFlags } = store.getState();
|
|
43
|
+
initPromiseRef.current = (async () => {
|
|
44
|
+
try {
|
|
45
|
+
const client = new flagmintJsSdk.FlagClient(options);
|
|
46
|
+
await client.ready();
|
|
47
|
+
const initialClientFlags = client.getFlags();
|
|
48
|
+
setFlags(initialClientFlags);
|
|
49
|
+
const unsubscribe = client.subscribe((updatedFlags) => {
|
|
50
|
+
console.log("FlagmintProvider - flags updated:", updatedFlags);
|
|
51
|
+
const currentStore = store.getState();
|
|
52
|
+
currentStore.setFlags(updatedFlags);
|
|
53
|
+
});
|
|
54
|
+
unsubscribeRef.current = unsubscribe;
|
|
55
|
+
clientRef.current = client;
|
|
56
|
+
setClient(client);
|
|
57
|
+
setReady(true);
|
|
58
|
+
setInitialized(true);
|
|
59
|
+
console.log("FlagmintProvider - initialized with flags:", initialClientFlags);
|
|
60
|
+
return client;
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error("Failed to initialize Flagmint client:", error);
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
})();
|
|
66
|
+
return initPromiseRef.current;
|
|
67
|
+
};
|
|
68
|
+
react.useEffect(() => {
|
|
69
|
+
if (!deferInitialization) {
|
|
70
|
+
init().catch((error) => {
|
|
71
|
+
console.error("Auto-initialization failed:", error);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return () => {
|
|
75
|
+
var _a, _b;
|
|
76
|
+
if (unsubscribeRef.current) {
|
|
77
|
+
unsubscribeRef.current();
|
|
78
|
+
unsubscribeRef.current = null;
|
|
79
|
+
}
|
|
80
|
+
if (clientRef.current) {
|
|
81
|
+
(_b = (_a = clientRef.current).destroy) == null ? void 0 : _b.call(_a);
|
|
82
|
+
clientRef.current = null;
|
|
83
|
+
initPromiseRef.current = null;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}, [deferInitialization]);
|
|
87
|
+
return /* @__PURE__ */ jsxRuntime.jsx(FlagmintStoreContext.Provider, { value: store, children });
|
|
88
|
+
}
|
|
89
|
+
function useFlagmintStore() {
|
|
90
|
+
const store = react.useContext(FlagmintStoreContext);
|
|
91
|
+
if (!store) {
|
|
92
|
+
throw new Error("useFlagmintStore must be used within a FlagmintProvider");
|
|
93
|
+
}
|
|
94
|
+
return store;
|
|
95
|
+
}
|
|
96
|
+
function useFlagmint() {
|
|
97
|
+
const store = useFlagmintStore();
|
|
98
|
+
const client = zustand.useStore(store, (state) => state.client);
|
|
99
|
+
const isInitialized = zustand.useStore(store, (state) => state.isInitialized);
|
|
100
|
+
const updateContext = async (context) => {
|
|
101
|
+
if (!client) {
|
|
102
|
+
throw new Error("Flagmint client not initialized");
|
|
103
|
+
}
|
|
104
|
+
await client.updateContext(context);
|
|
105
|
+
};
|
|
106
|
+
return {
|
|
107
|
+
client,
|
|
108
|
+
isInitialized,
|
|
109
|
+
updateContext
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function useFlags() {
|
|
113
|
+
const store = useFlagmintStore();
|
|
114
|
+
return zustand.useStore(store, (state) => state.flags);
|
|
115
|
+
}
|
|
116
|
+
function useFlag(key, fallback) {
|
|
117
|
+
const store = useFlagmintStore();
|
|
118
|
+
const flagValue = zustand.useStore(store, (state) => state.flags[key]);
|
|
119
|
+
return flagValue != null ? flagValue : fallback;
|
|
120
|
+
}
|
|
121
|
+
function useFlagmintReady() {
|
|
122
|
+
const store = useFlagmintStore();
|
|
123
|
+
const isReady = zustand.useStore(store, (state) => state.isReady);
|
|
124
|
+
const isInitialized = zustand.useStore(store, (state) => state.isInitialized);
|
|
125
|
+
return isReady && isInitialized;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
exports.FlagmintProvider = FlagmintProvider;
|
|
129
|
+
exports.FlagmintStoreContext = FlagmintStoreContext;
|
|
130
|
+
exports.createFlagStore = createFlagStore;
|
|
131
|
+
exports.useFlag = useFlag;
|
|
132
|
+
exports.useFlagmint = useFlagmint;
|
|
133
|
+
exports.useFlagmintReady = useFlagmintReady;
|
|
134
|
+
exports.useFlagmintStore = useFlagmintStore;
|
|
135
|
+
exports.useFlags = useFlags;
|
|
3
136
|
//# sourceMappingURL=index.cjs.map
|
|
4
137
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.cjs"}
|
|
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 console.log('Updating store flags:', 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 console.log('FlagmintProvider - flags updated:', updatedFlags)\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 console.log('FlagmintProvider - initialized with flags:', initialClientFlags)\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}"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,40 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
interface CoreClientLike {
|
|
9
|
-
getFlags(): Promise<Flags> | Flags;
|
|
10
|
-
getFlag(key: string, fallback?: FlagValue): Promise<FlagValue> | FlagValue;
|
|
11
|
-
subscribe(callback: (flags: Flags) => void): () => void;
|
|
12
|
-
updateContext(context: Record<string, any>): Promise<void> | void;
|
|
13
|
-
init(): Promise<void> | void;
|
|
14
|
-
close(): Promise<void> | void;
|
|
15
|
-
}
|
|
16
|
-
interface FlagStore {
|
|
17
|
-
flags: Flags;
|
|
18
|
-
client: FlagClient<any, any> | null;
|
|
19
|
-
isInitialized: boolean;
|
|
20
|
-
isReady: boolean;
|
|
21
|
-
setFlags: (flags: Flags) => void;
|
|
22
|
-
setFlag: (key: string, value: FlagValue) => void;
|
|
23
|
-
setClient: (client: FlagClient<any, any> | null) => void;
|
|
24
|
-
setInitialized: (initialized: boolean) => void;
|
|
25
|
-
setReady: (ready: boolean) => void;
|
|
26
|
-
}
|
|
27
|
-
interface FlagmintProviderProps {
|
|
28
|
-
children: ReactNode;
|
|
29
|
-
createClient?: () => CoreClientLike;
|
|
30
|
-
client: CoreClientLike;
|
|
31
|
-
initialFlags?: Flags;
|
|
32
|
-
}
|
|
33
|
-
interface FlagmintProviderProps<T = unknown, C extends Record<string, any> = Record<string, any>> {
|
|
34
|
-
children: ReactNode;
|
|
35
|
-
options: FlagClientOptions<C>;
|
|
36
|
-
initialFlags?: Flags;
|
|
37
|
-
deferInitialization?: boolean;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export type { CoreClientLike, FlagStore, FlagValue, FlagmintProviderProps, Flags };
|
|
1
|
+
export { CoreClientLike, FlagStore, FlagValue, FlagmintProvider, FlagmintProviderProps, FlagmintStoreContext, Flags, createFlagStore, useFlag, useFlagmint, useFlagmintReady, useFlagmintStore, useFlags } from './client.cjs';
|
|
2
|
+
import 'flagmint-js-sdk';
|
|
3
|
+
import 'react';
|
|
4
|
+
import 'react/jsx-runtime';
|
|
5
|
+
import 'zustand';
|
|
6
|
+
import 'zustand/vanilla';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,40 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
interface CoreClientLike {
|
|
9
|
-
getFlags(): Promise<Flags> | Flags;
|
|
10
|
-
getFlag(key: string, fallback?: FlagValue): Promise<FlagValue> | FlagValue;
|
|
11
|
-
subscribe(callback: (flags: Flags) => void): () => void;
|
|
12
|
-
updateContext(context: Record<string, any>): Promise<void> | void;
|
|
13
|
-
init(): Promise<void> | void;
|
|
14
|
-
close(): Promise<void> | void;
|
|
15
|
-
}
|
|
16
|
-
interface FlagStore {
|
|
17
|
-
flags: Flags;
|
|
18
|
-
client: FlagClient<any, any> | null;
|
|
19
|
-
isInitialized: boolean;
|
|
20
|
-
isReady: boolean;
|
|
21
|
-
setFlags: (flags: Flags) => void;
|
|
22
|
-
setFlag: (key: string, value: FlagValue) => void;
|
|
23
|
-
setClient: (client: FlagClient<any, any> | null) => void;
|
|
24
|
-
setInitialized: (initialized: boolean) => void;
|
|
25
|
-
setReady: (ready: boolean) => void;
|
|
26
|
-
}
|
|
27
|
-
interface FlagmintProviderProps {
|
|
28
|
-
children: ReactNode;
|
|
29
|
-
createClient?: () => CoreClientLike;
|
|
30
|
-
client: CoreClientLike;
|
|
31
|
-
initialFlags?: Flags;
|
|
32
|
-
}
|
|
33
|
-
interface FlagmintProviderProps<T = unknown, C extends Record<string, any> = Record<string, any>> {
|
|
34
|
-
children: ReactNode;
|
|
35
|
-
options: FlagClientOptions<C>;
|
|
36
|
-
initialFlags?: Flags;
|
|
37
|
-
deferInitialization?: boolean;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export type { CoreClientLike, FlagStore, FlagValue, FlagmintProviderProps, Flags };
|
|
1
|
+
export { CoreClientLike, FlagStore, FlagValue, FlagmintProvider, FlagmintProviderProps, FlagmintStoreContext, Flags, createFlagStore, useFlag, useFlagmint, useFlagmintReady, useFlagmintStore, useFlags } from './client.js';
|
|
2
|
+
import 'flagmint-js-sdk';
|
|
3
|
+
import 'react';
|
|
4
|
+
import 'react/jsx-runtime';
|
|
5
|
+
import 'zustand';
|
|
6
|
+
import 'zustand/vanilla';
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,128 @@
|
|
|
1
|
+
import { FlagClient } from 'flagmint-js-sdk';
|
|
2
|
+
import { createContext, useMemo, useRef, useEffect, useContext } from 'react';
|
|
3
|
+
import { createStore } from 'zustand/vanilla';
|
|
4
|
+
import { jsx } from 'react/jsx-runtime';
|
|
5
|
+
import { useStore } from 'zustand';
|
|
1
6
|
|
|
7
|
+
// src/providers/FlagmintProvider.tsx
|
|
8
|
+
function createFlagStore(initialFlags = {}) {
|
|
9
|
+
return createStore((set, get) => ({
|
|
10
|
+
flags: initialFlags,
|
|
11
|
+
client: null,
|
|
12
|
+
isInitialized: false,
|
|
13
|
+
isReady: false,
|
|
14
|
+
setFlags: (flags) => {
|
|
15
|
+
console.log("Updating store flags:", flags);
|
|
16
|
+
set({ flags: { ...flags } });
|
|
17
|
+
},
|
|
18
|
+
setFlag: (key, value) => set((state) => ({
|
|
19
|
+
flags: { ...state.flags, [key]: value }
|
|
20
|
+
})),
|
|
21
|
+
setClient: (client) => set({ client }),
|
|
22
|
+
setInitialized: (initialized) => set({ isInitialized: initialized }),
|
|
23
|
+
setReady: (ready) => set({ isReady: ready })
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
26
|
+
var FlagmintStoreContext = createContext(null);
|
|
27
|
+
function FlagmintProvider({
|
|
28
|
+
children,
|
|
29
|
+
options,
|
|
30
|
+
initialFlags = {},
|
|
31
|
+
deferInitialization = false
|
|
32
|
+
}) {
|
|
33
|
+
const store = useMemo(() => createFlagStore(initialFlags), []);
|
|
34
|
+
const clientRef = useRef(null);
|
|
35
|
+
const initPromiseRef = useRef(null);
|
|
36
|
+
const unsubscribeRef = useRef(null);
|
|
37
|
+
const init = async () => {
|
|
38
|
+
if (clientRef.current) return clientRef.current;
|
|
39
|
+
if (initPromiseRef.current) return initPromiseRef.current;
|
|
40
|
+
const { setClient, setReady, setInitialized, setFlags } = store.getState();
|
|
41
|
+
initPromiseRef.current = (async () => {
|
|
42
|
+
try {
|
|
43
|
+
const client = new FlagClient(options);
|
|
44
|
+
await client.ready();
|
|
45
|
+
const initialClientFlags = client.getFlags();
|
|
46
|
+
setFlags(initialClientFlags);
|
|
47
|
+
const unsubscribe = client.subscribe((updatedFlags) => {
|
|
48
|
+
console.log("FlagmintProvider - flags updated:", updatedFlags);
|
|
49
|
+
const currentStore = store.getState();
|
|
50
|
+
currentStore.setFlags(updatedFlags);
|
|
51
|
+
});
|
|
52
|
+
unsubscribeRef.current = unsubscribe;
|
|
53
|
+
clientRef.current = client;
|
|
54
|
+
setClient(client);
|
|
55
|
+
setReady(true);
|
|
56
|
+
setInitialized(true);
|
|
57
|
+
console.log("FlagmintProvider - initialized with flags:", initialClientFlags);
|
|
58
|
+
return client;
|
|
59
|
+
} catch (error) {
|
|
60
|
+
console.error("Failed to initialize Flagmint client:", error);
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
})();
|
|
64
|
+
return initPromiseRef.current;
|
|
65
|
+
};
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
if (!deferInitialization) {
|
|
68
|
+
init().catch((error) => {
|
|
69
|
+
console.error("Auto-initialization failed:", error);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
return () => {
|
|
73
|
+
var _a, _b;
|
|
74
|
+
if (unsubscribeRef.current) {
|
|
75
|
+
unsubscribeRef.current();
|
|
76
|
+
unsubscribeRef.current = null;
|
|
77
|
+
}
|
|
78
|
+
if (clientRef.current) {
|
|
79
|
+
(_b = (_a = clientRef.current).destroy) == null ? void 0 : _b.call(_a);
|
|
80
|
+
clientRef.current = null;
|
|
81
|
+
initPromiseRef.current = null;
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
}, [deferInitialization]);
|
|
85
|
+
return /* @__PURE__ */ jsx(FlagmintStoreContext.Provider, { value: store, children });
|
|
86
|
+
}
|
|
87
|
+
function useFlagmintStore() {
|
|
88
|
+
const store = useContext(FlagmintStoreContext);
|
|
89
|
+
if (!store) {
|
|
90
|
+
throw new Error("useFlagmintStore must be used within a FlagmintProvider");
|
|
91
|
+
}
|
|
92
|
+
return store;
|
|
93
|
+
}
|
|
94
|
+
function useFlagmint() {
|
|
95
|
+
const store = useFlagmintStore();
|
|
96
|
+
const client = useStore(store, (state) => state.client);
|
|
97
|
+
const isInitialized = useStore(store, (state) => state.isInitialized);
|
|
98
|
+
const updateContext = async (context) => {
|
|
99
|
+
if (!client) {
|
|
100
|
+
throw new Error("Flagmint client not initialized");
|
|
101
|
+
}
|
|
102
|
+
await client.updateContext(context);
|
|
103
|
+
};
|
|
104
|
+
return {
|
|
105
|
+
client,
|
|
106
|
+
isInitialized,
|
|
107
|
+
updateContext
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
function useFlags() {
|
|
111
|
+
const store = useFlagmintStore();
|
|
112
|
+
return useStore(store, (state) => state.flags);
|
|
113
|
+
}
|
|
114
|
+
function useFlag(key, fallback) {
|
|
115
|
+
const store = useFlagmintStore();
|
|
116
|
+
const flagValue = useStore(store, (state) => state.flags[key]);
|
|
117
|
+
return flagValue != null ? flagValue : fallback;
|
|
118
|
+
}
|
|
119
|
+
function useFlagmintReady() {
|
|
120
|
+
const store = useFlagmintStore();
|
|
121
|
+
const isReady = useStore(store, (state) => state.isReady);
|
|
122
|
+
const isInitialized = useStore(store, (state) => state.isInitialized);
|
|
123
|
+
return isReady && isInitialized;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export { FlagmintProvider, FlagmintStoreContext, createFlagStore, useFlag, useFlagmint, useFlagmintReady, useFlagmintStore, useFlags };
|
|
2
127
|
//# sourceMappingURL=index.js.map
|
|
3
128
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
|
1
|
+
{"version":3,"sources":["../src/store/store.ts","../src/providers/FlagmintProvider.tsx","../src/hooks/index.ts"],"names":[],"mappings":";;;;;;;AAKO,SAAS,eAAA,CAAgB,YAAA,GAAsB,EAAC,EAAwB;AAC5E,EAAA,OAAO,WAAA,CAAuB,CAAC,GAAA,EAAK,GAAA,MAAS;AAAA,IAC5C,KAAA,EAAO,YAAA;AAAA,IACP,MAAA,EAAQ,IAAA;AAAA,IACR,aAAA,EAAe,KAAA;AAAA,IACf,OAAA,EAAS,KAAA;AAAA,IACT,QAAA,EAAU,CAAC,KAAA,KAAU;AACnB,MAAA,OAAA,CAAQ,GAAA,CAAI,yBAAyB,KAAK,CAAA;AAC1C,MAAA,GAAA,CAAI,EAAE,KAAA,EAAO,EAAE,GAAG,KAAA,IAAS,CAAA;AAAA,IAC7B,CAAA;AAAA,IACA,SAAS,CAAC,GAAA,EAAK,KAAA,KAAU,GAAA,CAAI,CAAC,KAAA,MAAW;AAAA,MACvC,KAAA,EAAO,EAAE,GAAG,KAAA,CAAM,OAAO,CAAC,GAAG,GAAG,KAAA;AAAM,KACxC,CAAE,CAAA;AAAA,IACF,WAAW,CAAC,MAAA,KAAW,GAAA,CAAI,EAAE,QAAQ,CAAA;AAAA,IACrC,gBAAgB,CAAC,WAAA,KAAgB,IAAI,EAAE,aAAA,EAAe,aAAa,CAAA;AAAA,IACnE,UAAU,CAAC,KAAA,KAAU,IAAI,EAAE,OAAA,EAAS,OAAO;AAAA,GAC7C,CAAE,CAAA;AACJ;ACfO,IAAM,oBAAA,GAAuB,cAA0C,IAAI;AAc3E,SAAS,gBAAA,CAGd;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,eAAe,EAAC;AAAA,EAChB,mBAAA,GAAsB;AACxB,CAAA,EAAgC;AAE9B,EAAA,MAAM,QAAQ,OAAA,CAAQ,MAAM,gBAAgB,YAAY,CAAA,EAAG,EAAE,CAAA;AAG7D,EAAA,MAAM,SAAA,GAAY,OAAgC,IAAI,CAAA;AACtD,EAAA,MAAM,cAAA,GAAiB,OAAyC,IAAI,CAAA;AACpE,EAAA,MAAM,cAAA,GAAiB,OAA4B,IAAI,CAAA;AAGvD,EAAA,MAAM,OAAO,YAAuC;AAClD,IAAA,IAAI,SAAA,CAAU,OAAA,EAAS,OAAO,SAAA,CAAU,OAAA;AAGxC,IAAA,IAAI,cAAA,CAAe,OAAA,EAAS,OAAO,cAAA,CAAe,OAAA;AAElD,IAAA,MAAM,EAAE,SAAA,EAAW,QAAA,EAAU,gBAAgB,QAAA,EAAS,GAAI,MAAM,QAAA,EAAS;AAEzE,IAAA,cAAA,CAAe,WAAW,YAAY;AACpC,MAAA,IAAI;AAEF,QAAA,MAAM,MAAA,GAAS,IAAI,UAAA,CAAiB,OAAO,CAAA;AAG3C,QAAA,MAAM,OAAO,KAAA,EAAM;AAGnB,QAAA,MAAM,kBAAA,GAAqB,OAAO,QAAA,EAAS;AAC3C,QAAA,QAAA,CAAS,kBAAkB,CAAA;AAG3B,QAAA,MAAM,WAAA,GAAc,MAAA,CAAO,SAAA,CAAU,CAAC,YAAA,KAAwB;AAC5D,UAAA,OAAA,CAAQ,GAAA,CAAI,qCAAqC,YAAY,CAAA;AAE7D,UAAA,MAAM,YAAA,GAAe,MAAM,QAAA,EAAS;AACpC,UAAA,YAAA,CAAa,SAAS,YAAY,CAAA;AAAA,QACpC,CAAC,CAAA;AAED,QAAA,cAAA,CAAe,OAAA,GAAU,WAAA;AAEzB,QAAA,SAAA,CAAU,OAAA,GAAU,MAAA;AACpB,QAAA,SAAA,CAAU,MAAM,CAAA;AAChB,QAAA,QAAA,CAAS,IAAI,CAAA;AACb,QAAA,cAAA,CAAe,IAAI,CAAA;AAEnB,QAAA,OAAA,CAAQ,GAAA,CAAI,8CAA8C,kBAAkB,CAAA;AAE5E,QAAA,OAAO,MAAA;AAAA,MACT,SAAS,KAAA,EAAO;AACd,QAAA,OAAA,CAAQ,KAAA,CAAM,yCAAyC,KAAK,CAAA;AAC5D,QAAA,MAAM,KAAA;AAAA,MACR;AAAA,IACF,CAAA,GAAG;AAEH,IAAA,OAAO,cAAA,CAAe,OAAA;AAAA,EACxB,CAAA;AAEA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,mBAAA,EAAqB;AACxB,MAAA,IAAA,EAAK,CAAE,MAAM,CAAA,KAAA,KAAS;AACpB,QAAA,OAAA,CAAQ,KAAA,CAAM,+BAA+B,KAAK,CAAA;AAAA,MACpD,CAAC,CAAA;AAAA,IACH;AAEA,IAAA,OAAO,MAAM;AA7FjB,MAAA,IAAA,EAAA,EAAA,EAAA;AA+FM,MAAA,IAAI,eAAe,OAAA,EAAS;AAC1B,QAAA,cAAA,CAAe,OAAA,EAAQ;AACvB,QAAA,cAAA,CAAe,OAAA,GAAU,IAAA;AAAA,MAC3B;AAGA,MAAA,IAAI,UAAU,OAAA,EAAS;AACrB,QAAA,CAAA,EAAA,GAAA,CAAA,EAAA,GAAA,SAAA,CAAU,SAAQ,OAAA,KAAlB,IAAA,GAAA,MAAA,GAAA,EAAA,CAAA,IAAA,CAAA,EAAA,CAAA;AACA,QAAA,SAAA,CAAU,OAAA,GAAU,IAAA;AACpB,QAAA,cAAA,CAAe,OAAA,GAAU,IAAA;AAAA,MAC3B;AAAA,IACF,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,mBAAmB,CAAC,CAAA;AAExB,EAAA,2BACG,oBAAA,CAAqB,QAAA,EAArB,EAA8B,KAAA,EAAO,OACnC,QAAA,EACH,CAAA;AAEJ;AC1GO,SAAS,gBAAA,GAAwC;AACtD,EAAA,MAAM,KAAA,GAAQ,WAAW,oBAAoB,CAAA;AAC7C,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,MAAM,IAAI,MAAM,yDAAyD,CAAA;AAAA,EAC3E;AACA,EAAA,OAAO,KAAA;AACT;AAGO,SAAS,WAAA,GAAc;AAC5B,EAAA,MAAM,QAAQ,gBAAA,EAAiB;AAC/B,EAAA,MAAM,SAAS,QAAA,CAAS,KAAA,EAAO,CAAC,KAAA,KAAU,MAAM,MAAM,CAAA;AACtD,EAAA,MAAM,gBAAgB,QAAA,CAAS,KAAA,EAAO,CAAC,KAAA,KAAU,MAAM,aAAa,CAAA;AAEpE,EAAA,MAAM,aAAA,GAAgB,OAAO,OAAA,KAAiC;AAC5D,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,MAAM,IAAI,MAAM,iCAAiC,CAAA;AAAA,IACnD;AACA,IAAA,MAAM,MAAA,CAAO,cAAc,OAAO,CAAA;AAAA,EACpC,CAAA;AAEA,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,aAAA;AAAA,IACA;AAAA,GACF;AACF;AAGO,SAAS,QAAA,GAAkB;AAChC,EAAA,MAAM,QAAQ,gBAAA,EAAiB;AAC/B,EAAA,OAAO,QAAA,CAAS,KAAA,EAAO,CAAC,KAAA,KAAU,MAAM,KAAK,CAAA;AAC/C;AAGO,SAAS,OAAA,CACd,KACA,QAAA,EACG;AACH,EAAA,MAAM,QAAQ,gBAAA,EAAiB;AAG/B,EAAA,MAAM,SAAA,GAAY,SAAS,KAAA,EAAO,CAAC,UAAU,KAAA,CAAM,KAAA,CAAM,GAAG,CAAC,CAAA;AAG7D,EAAA,OAAQ,SAAA,IAAA,IAAA,GAAA,SAAA,GAAa,QAAA;AACvB;AAGO,SAAS,gBAAA,GAA4B;AAC1C,EAAA,MAAM,QAAQ,gBAAA,EAAiB;AAG/B,EAAA,MAAM,UAAU,QAAA,CAAS,KAAA,EAAO,CAAC,KAAA,KAAU,MAAM,OAAO,CAAA;AACxD,EAAA,MAAM,gBAAgB,QAAA,CAAS,KAAA,EAAO,CAAC,KAAA,KAAU,MAAM,aAAa,CAAA;AAEpE,EAAA,OAAO,OAAA,IAAW,aAAA;AACpB","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 console.log('Updating store flags:', 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 console.log('FlagmintProvider - flags updated:', updatedFlags)\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 console.log('FlagmintProvider - initialized with flags:', initialClientFlags)\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}"]}
|