@rolloutly/react 0.1.0

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,159 @@
1
+ # @rolloutly/react
2
+
3
+ React SDK for [Rolloutly](https://rolloutly.com) feature flags.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @rolloutly/react
9
+ # or
10
+ pnpm add @rolloutly/react
11
+ # or
12
+ yarn add @rolloutly/react
13
+ ```
14
+
15
+ ## Quick Start
16
+
17
+ ```tsx
18
+ import { RolloutlyProvider, useFlag, useFlagEnabled } from '@rolloutly/react';
19
+
20
+ // 1. Wrap your app with the provider
21
+ function App() {
22
+ return (
23
+ <RolloutlyProvider token="rly_your_project_production_xxx">
24
+ <MyApp />
25
+ </RolloutlyProvider>
26
+ );
27
+ }
28
+
29
+ // 2. Use hooks in your components
30
+ function MyFeature() {
31
+ const isNewCheckout = useFlagEnabled('new-checkout');
32
+ const rateLimit = useFlag<number>('api-rate-limit');
33
+
34
+ if (isNewCheckout) {
35
+ return <NewCheckout rateLimit={rateLimit} />;
36
+ }
37
+
38
+ return <OldCheckout />;
39
+ }
40
+ ```
41
+
42
+ ## Provider Configuration
43
+
44
+ ```tsx
45
+ <RolloutlyProvider
46
+ // Required: Your SDK token
47
+ token="rly_xxx"
48
+
49
+ // Optional: Custom API URL
50
+ baseUrl="https://your-instance.com"
51
+
52
+ // Optional: Enable real-time updates (default: true)
53
+ realtimeEnabled={true}
54
+
55
+ // Optional: Default values before flags load
56
+ defaultFlags={{
57
+ 'new-feature': false,
58
+ 'api-rate-limit': 100,
59
+ }}
60
+
61
+ // Optional: Enable debug logging
62
+ debug={false}
63
+
64
+ // Optional: Component to show while loading
65
+ loadingComponent={<Spinner />}
66
+ >
67
+ <App />
68
+ </RolloutlyProvider>
69
+ ```
70
+
71
+ ## Hooks
72
+
73
+ ### `useFlag<T>(key: string): T | undefined`
74
+
75
+ Get a single flag value with real-time updates.
76
+
77
+ ```tsx
78
+ const rateLimit = useFlag<number>('api-rate-limit');
79
+ const config = useFlag<{ maxUsers: number }>('app-config');
80
+ ```
81
+
82
+ ### `useFlagEnabled(key: string): boolean`
83
+
84
+ Check if a boolean flag is enabled. Returns `false` if the flag doesn't exist or is disabled.
85
+
86
+ ```tsx
87
+ const showBanner = useFlagEnabled('show-banner');
88
+
89
+ if (showBanner) {
90
+ return <PromoBanner />;
91
+ }
92
+ ```
93
+
94
+ ### `useFlags(): Record<string, FlagValue>`
95
+
96
+ Get all flags as a key-value object.
97
+
98
+ ```tsx
99
+ const flags = useFlags();
100
+ console.log(flags['my-feature']); // true
101
+ ```
102
+
103
+ ### `useRolloutly(): RolloutlyContextValue`
104
+
105
+ Get the Rolloutly context including loading and error states.
106
+
107
+ ```tsx
108
+ const { isLoading, isError, error, getFlag, isEnabled } = useRolloutly();
109
+
110
+ if (isLoading) return <Spinner />;
111
+ if (isError) return <Error message={error?.message} />;
112
+ ```
113
+
114
+ ### `useRolloutlyClient(): RolloutlyClient`
115
+
116
+ Get direct access to the Rolloutly client instance.
117
+
118
+ ```tsx
119
+ const client = useRolloutlyClient();
120
+ const allFlags = client.getFlags();
121
+ ```
122
+
123
+ ## TypeScript
124
+
125
+ All hooks are fully typed. Use generics for type-safe flag values:
126
+
127
+ ```tsx
128
+ // Boolean flag
129
+ const isEnabled = useFlagEnabled('feature');
130
+
131
+ // Typed flag values
132
+ const limit = useFlag<number>('rate-limit');
133
+ const config = useFlag<{ theme: string; maxItems: number }>('app-config');
134
+ ```
135
+
136
+ ## Server-Side Rendering (Next.js)
137
+
138
+ The provider includes `'use client'` directive and works with Next.js App Router. For server components, fetch flags server-side using `@rolloutly/core`:
139
+
140
+ ```tsx
141
+ // app/layout.tsx
142
+ import { RolloutlyProvider } from '@rolloutly/react';
143
+
144
+ export default function RootLayout({ children }) {
145
+ return (
146
+ <html>
147
+ <body>
148
+ <RolloutlyProvider token={process.env.NEXT_PUBLIC_ROLLOUTLY_TOKEN!}>
149
+ {children}
150
+ </RolloutlyProvider>
151
+ </body>
152
+ </html>
153
+ );
154
+ }
155
+ ```
156
+
157
+ ## License
158
+
159
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,153 @@
1
+ 'use strict';
2
+
3
+ var core = require('@rolloutly/core');
4
+ var react = require('react');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+
7
+ // src/provider.tsx
8
+ var RolloutlyContext = react.createContext({
9
+ client: null,
10
+ isLoading: true,
11
+ isError: false,
12
+ error: null
13
+ });
14
+ function RolloutlyProvider({
15
+ token,
16
+ children,
17
+ baseUrl,
18
+ realtimeEnabled = true,
19
+ defaultFlags,
20
+ debug = false,
21
+ loadingComponent
22
+ }) {
23
+ const [isLoading, setIsLoading] = react.useState(true);
24
+ const [isError, setIsError] = react.useState(false);
25
+ const [error, setError] = react.useState(null);
26
+ const client = react.useMemo(() => {
27
+ return new core.RolloutlyClient({
28
+ token,
29
+ baseUrl,
30
+ realtimeEnabled,
31
+ defaultFlags,
32
+ debug
33
+ });
34
+ }, [token, baseUrl, realtimeEnabled, defaultFlags, debug]);
35
+ react.useEffect(() => {
36
+ let mounted = true;
37
+ client.waitForInit().then(() => {
38
+ if (mounted) {
39
+ setIsLoading(false);
40
+ }
41
+ }).catch((err) => {
42
+ if (mounted) {
43
+ setIsError(true);
44
+ setError(err instanceof Error ? err : new Error(String(err)));
45
+ setIsLoading(false);
46
+ }
47
+ });
48
+ return () => {
49
+ mounted = false;
50
+ client.close();
51
+ };
52
+ }, [client]);
53
+ const contextValue = react.useMemo(
54
+ () => ({
55
+ client,
56
+ isLoading,
57
+ isError,
58
+ error
59
+ }),
60
+ [client, isLoading, isError, error]
61
+ );
62
+ if (isLoading && loadingComponent) {
63
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: loadingComponent });
64
+ }
65
+ return /* @__PURE__ */ jsxRuntime.jsx(RolloutlyContext.Provider, { value: contextValue, children });
66
+ }
67
+ function useRolloutlyClient() {
68
+ const { client } = react.useContext(RolloutlyContext);
69
+ if (!client) {
70
+ throw new Error("useRolloutlyClient must be used within RolloutlyProvider");
71
+ }
72
+ return client;
73
+ }
74
+ function useRolloutly() {
75
+ const { client, isLoading, isError, error } = react.useContext(RolloutlyContext);
76
+ if (!client) {
77
+ throw new Error("useRolloutly must be used within RolloutlyProvider");
78
+ }
79
+ const getFlag = react.useCallback(
80
+ (key) => {
81
+ return client.getFlag(key);
82
+ },
83
+ [client]
84
+ );
85
+ const isEnabled = react.useCallback(
86
+ (key) => {
87
+ return client.isEnabled(key);
88
+ },
89
+ [client]
90
+ );
91
+ return {
92
+ isLoading,
93
+ isError,
94
+ error,
95
+ getFlag,
96
+ isEnabled
97
+ };
98
+ }
99
+ function useFlag(key) {
100
+ const client = useRolloutlyClient();
101
+ const getSnapshot = react.useCallback(() => {
102
+ return client.getFlag(key);
103
+ }, [client, key]);
104
+ const subscribe = react.useCallback(
105
+ (onStoreChange) => {
106
+ return client.subscribe(onStoreChange);
107
+ },
108
+ [client]
109
+ );
110
+ return react.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
111
+ }
112
+ function useFlagEnabled(key) {
113
+ const client = useRolloutlyClient();
114
+ const getSnapshot = react.useCallback(() => {
115
+ return client.isEnabled(key);
116
+ }, [client, key]);
117
+ const subscribe = react.useCallback(
118
+ (onStoreChange) => {
119
+ return client.subscribe(onStoreChange);
120
+ },
121
+ [client]
122
+ );
123
+ return react.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
124
+ }
125
+ function useFlags() {
126
+ const client = useRolloutlyClient();
127
+ const getSnapshot = react.useCallback(() => {
128
+ const flags = client.getFlags();
129
+ return Object.entries(flags).reduce(
130
+ (acc, [key, flag]) => {
131
+ acc[key] = flag.enabled ? flag.value : void 0;
132
+ return acc;
133
+ },
134
+ {}
135
+ );
136
+ }, [client]);
137
+ const subscribe = react.useCallback(
138
+ (onStoreChange) => {
139
+ return client.subscribe(onStoreChange);
140
+ },
141
+ [client]
142
+ );
143
+ return react.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
144
+ }
145
+
146
+ exports.RolloutlyProvider = RolloutlyProvider;
147
+ exports.useFlag = useFlag;
148
+ exports.useFlagEnabled = useFlagEnabled;
149
+ exports.useFlags = useFlags;
150
+ exports.useRolloutly = useRolloutly;
151
+ exports.useRolloutlyClient = useRolloutlyClient;
152
+ //# sourceMappingURL=index.cjs.map
153
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/provider.tsx"],"names":["createContext","useState","useMemo","RolloutlyClient","useEffect","useContext","useCallback","useSyncExternalStore"],"mappings":"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","file":"index.cjs","sourcesContent":["'use client';\n\nimport { RolloutlyClient, type FlagValue } from '@rolloutly/core';\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n useSyncExternalStore,\n} from 'react';\n\nimport type { RolloutlyContextValue, RolloutlyProviderProps } from './types';\n\nconst RolloutlyContext = createContext<{\n client: RolloutlyClient | null;\n isLoading: boolean;\n isError: boolean;\n error: Error | null;\n}>({\n client: null,\n isLoading: true,\n isError: false,\n error: null,\n});\n\n/**\n * Provider component that initializes Rolloutly and provides context\n */\nexport function RolloutlyProvider({\n token,\n children,\n baseUrl,\n realtimeEnabled = true,\n defaultFlags,\n debug = false,\n loadingComponent,\n}: RolloutlyProviderProps): JSX.Element {\n const [isLoading, setIsLoading] = useState(true);\n const [isError, setIsError] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const client = useMemo(() => {\n return new RolloutlyClient({\n token,\n baseUrl,\n realtimeEnabled,\n defaultFlags,\n debug,\n });\n }, [token, baseUrl, realtimeEnabled, defaultFlags, debug]);\n\n useEffect(() => {\n let mounted = true;\n\n client\n .waitForInit()\n .then(() => {\n if (mounted) {\n setIsLoading(false);\n }\n })\n .catch((err) => {\n if (mounted) {\n setIsError(true);\n setError(err instanceof Error ? err : new Error(String(err)));\n setIsLoading(false);\n }\n });\n\n return () => {\n mounted = false;\n client.close();\n };\n }, [client]);\n\n const contextValue = useMemo(\n () => ({\n client,\n isLoading,\n isError,\n error,\n }),\n [client, isLoading, isError, error],\n );\n\n if (isLoading && loadingComponent) {\n return <>{loadingComponent}</>;\n }\n\n return (\n <RolloutlyContext.Provider value={contextValue}>\n {children}\n </RolloutlyContext.Provider>\n );\n}\n\n/**\n * Hook to access the Rolloutly client directly\n */\nexport function useRolloutlyClient(): RolloutlyClient {\n const { client } = useContext(RolloutlyContext);\n\n if (!client) {\n throw new Error('useRolloutlyClient must be used within RolloutlyProvider');\n }\n\n return client;\n}\n\n/**\n * Hook to get Rolloutly status\n */\nexport function useRolloutly(): RolloutlyContextValue {\n const { client, isLoading, isError, error } = useContext(RolloutlyContext);\n\n if (!client) {\n throw new Error('useRolloutly must be used within RolloutlyProvider');\n }\n\n const getFlag = useCallback(\n <T extends FlagValue = FlagValue>(key: string): T | undefined => {\n return client.getFlag<T>(key);\n },\n [client],\n );\n\n const isEnabled = useCallback(\n (key: string): boolean => {\n return client.isEnabled(key);\n },\n [client],\n );\n\n return {\n isLoading,\n isError,\n error,\n getFlag,\n isEnabled,\n };\n}\n\n/**\n * Hook to get a single flag value with real-time updates\n */\nexport function useFlag<T extends FlagValue = FlagValue>(\n key: string,\n): T | undefined {\n const client = useRolloutlyClient();\n\n const getSnapshot = useCallback((): T | undefined => {\n return client.getFlag<T>(key);\n }, [client, key]);\n\n const subscribe = useCallback(\n (onStoreChange: () => void): (() => void) => {\n return client.subscribe(onStoreChange);\n },\n [client],\n );\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n/**\n * Hook to check if a boolean flag is enabled with real-time updates\n */\nexport function useFlagEnabled(key: string): boolean {\n const client = useRolloutlyClient();\n\n const getSnapshot = useCallback((): boolean => {\n return client.isEnabled(key);\n }, [client, key]);\n\n const subscribe = useCallback(\n (onStoreChange: () => void): (() => void) => {\n return client.subscribe(onStoreChange);\n },\n [client],\n );\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n/**\n * Hook to get all flags with real-time updates\n */\nexport function useFlags(): Record<string, FlagValue> {\n const client = useRolloutlyClient();\n\n const getSnapshot = useCallback((): Record<string, FlagValue> => {\n const flags = client.getFlags();\n\n return Object.entries(flags).reduce<Record<string, FlagValue>>(\n (acc, [key, flag]) => {\n acc[key] = flag.enabled ? flag.value : undefined!;\n\n return acc;\n },\n {},\n );\n }, [client]);\n\n const subscribe = useCallback(\n (onStoreChange: () => void): (() => void) => {\n return client.subscribe(onStoreChange);\n },\n [client],\n );\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n"]}
@@ -0,0 +1,65 @@
1
+ import { FlagValue, RolloutlyClient } from '@rolloutly/core';
2
+ export { Flag, FlagMap, FlagValue } from '@rolloutly/core';
3
+ import { ReactNode } from 'react';
4
+
5
+ /**
6
+ * Props for the RolloutlyProvider component
7
+ */
8
+ type RolloutlyProviderProps = {
9
+ /** SDK token */
10
+ token: string;
11
+ /** Child components */
12
+ children: ReactNode;
13
+ /** Base URL for the API */
14
+ baseUrl?: string;
15
+ /** Enable real-time updates */
16
+ realtimeEnabled?: boolean;
17
+ /** Default flag values */
18
+ defaultFlags?: Record<string, FlagValue>;
19
+ /** Enable debug logging */
20
+ debug?: boolean;
21
+ /** Component to show while loading */
22
+ loadingComponent?: ReactNode;
23
+ };
24
+ /**
25
+ * Rolloutly context value
26
+ */
27
+ type RolloutlyContextValue = {
28
+ /** Whether the client is still loading */
29
+ isLoading: boolean;
30
+ /** Whether there was an error */
31
+ isError: boolean;
32
+ /** The error if any */
33
+ error: Error | null;
34
+ /** Get a flag value */
35
+ getFlag: <T extends FlagValue = FlagValue>(key: string) => T | undefined;
36
+ /** Check if a boolean flag is enabled */
37
+ isEnabled: (key: string) => boolean;
38
+ };
39
+
40
+ /**
41
+ * Provider component that initializes Rolloutly and provides context
42
+ */
43
+ declare function RolloutlyProvider({ token, children, baseUrl, realtimeEnabled, defaultFlags, debug, loadingComponent, }: RolloutlyProviderProps): JSX.Element;
44
+ /**
45
+ * Hook to access the Rolloutly client directly
46
+ */
47
+ declare function useRolloutlyClient(): RolloutlyClient;
48
+ /**
49
+ * Hook to get Rolloutly status
50
+ */
51
+ declare function useRolloutly(): RolloutlyContextValue;
52
+ /**
53
+ * Hook to get a single flag value with real-time updates
54
+ */
55
+ declare function useFlag<T extends FlagValue = FlagValue>(key: string): T | undefined;
56
+ /**
57
+ * Hook to check if a boolean flag is enabled with real-time updates
58
+ */
59
+ declare function useFlagEnabled(key: string): boolean;
60
+ /**
61
+ * Hook to get all flags with real-time updates
62
+ */
63
+ declare function useFlags(): Record<string, FlagValue>;
64
+
65
+ export { type RolloutlyContextValue, RolloutlyProvider, type RolloutlyProviderProps, useFlag, useFlagEnabled, useFlags, useRolloutly, useRolloutlyClient };
@@ -0,0 +1,65 @@
1
+ import { FlagValue, RolloutlyClient } from '@rolloutly/core';
2
+ export { Flag, FlagMap, FlagValue } from '@rolloutly/core';
3
+ import { ReactNode } from 'react';
4
+
5
+ /**
6
+ * Props for the RolloutlyProvider component
7
+ */
8
+ type RolloutlyProviderProps = {
9
+ /** SDK token */
10
+ token: string;
11
+ /** Child components */
12
+ children: ReactNode;
13
+ /** Base URL for the API */
14
+ baseUrl?: string;
15
+ /** Enable real-time updates */
16
+ realtimeEnabled?: boolean;
17
+ /** Default flag values */
18
+ defaultFlags?: Record<string, FlagValue>;
19
+ /** Enable debug logging */
20
+ debug?: boolean;
21
+ /** Component to show while loading */
22
+ loadingComponent?: ReactNode;
23
+ };
24
+ /**
25
+ * Rolloutly context value
26
+ */
27
+ type RolloutlyContextValue = {
28
+ /** Whether the client is still loading */
29
+ isLoading: boolean;
30
+ /** Whether there was an error */
31
+ isError: boolean;
32
+ /** The error if any */
33
+ error: Error | null;
34
+ /** Get a flag value */
35
+ getFlag: <T extends FlagValue = FlagValue>(key: string) => T | undefined;
36
+ /** Check if a boolean flag is enabled */
37
+ isEnabled: (key: string) => boolean;
38
+ };
39
+
40
+ /**
41
+ * Provider component that initializes Rolloutly and provides context
42
+ */
43
+ declare function RolloutlyProvider({ token, children, baseUrl, realtimeEnabled, defaultFlags, debug, loadingComponent, }: RolloutlyProviderProps): JSX.Element;
44
+ /**
45
+ * Hook to access the Rolloutly client directly
46
+ */
47
+ declare function useRolloutlyClient(): RolloutlyClient;
48
+ /**
49
+ * Hook to get Rolloutly status
50
+ */
51
+ declare function useRolloutly(): RolloutlyContextValue;
52
+ /**
53
+ * Hook to get a single flag value with real-time updates
54
+ */
55
+ declare function useFlag<T extends FlagValue = FlagValue>(key: string): T | undefined;
56
+ /**
57
+ * Hook to check if a boolean flag is enabled with real-time updates
58
+ */
59
+ declare function useFlagEnabled(key: string): boolean;
60
+ /**
61
+ * Hook to get all flags with real-time updates
62
+ */
63
+ declare function useFlags(): Record<string, FlagValue>;
64
+
65
+ export { type RolloutlyContextValue, RolloutlyProvider, type RolloutlyProviderProps, useFlag, useFlagEnabled, useFlags, useRolloutly, useRolloutlyClient };
package/dist/index.js ADDED
@@ -0,0 +1,146 @@
1
+ import { RolloutlyClient } from '@rolloutly/core';
2
+ import { createContext, useState, useMemo, useEffect, useContext, useCallback, useSyncExternalStore } from 'react';
3
+ import { jsx, Fragment } from 'react/jsx-runtime';
4
+
5
+ // src/provider.tsx
6
+ var RolloutlyContext = createContext({
7
+ client: null,
8
+ isLoading: true,
9
+ isError: false,
10
+ error: null
11
+ });
12
+ function RolloutlyProvider({
13
+ token,
14
+ children,
15
+ baseUrl,
16
+ realtimeEnabled = true,
17
+ defaultFlags,
18
+ debug = false,
19
+ loadingComponent
20
+ }) {
21
+ const [isLoading, setIsLoading] = useState(true);
22
+ const [isError, setIsError] = useState(false);
23
+ const [error, setError] = useState(null);
24
+ const client = useMemo(() => {
25
+ return new RolloutlyClient({
26
+ token,
27
+ baseUrl,
28
+ realtimeEnabled,
29
+ defaultFlags,
30
+ debug
31
+ });
32
+ }, [token, baseUrl, realtimeEnabled, defaultFlags, debug]);
33
+ useEffect(() => {
34
+ let mounted = true;
35
+ client.waitForInit().then(() => {
36
+ if (mounted) {
37
+ setIsLoading(false);
38
+ }
39
+ }).catch((err) => {
40
+ if (mounted) {
41
+ setIsError(true);
42
+ setError(err instanceof Error ? err : new Error(String(err)));
43
+ setIsLoading(false);
44
+ }
45
+ });
46
+ return () => {
47
+ mounted = false;
48
+ client.close();
49
+ };
50
+ }, [client]);
51
+ const contextValue = useMemo(
52
+ () => ({
53
+ client,
54
+ isLoading,
55
+ isError,
56
+ error
57
+ }),
58
+ [client, isLoading, isError, error]
59
+ );
60
+ if (isLoading && loadingComponent) {
61
+ return /* @__PURE__ */ jsx(Fragment, { children: loadingComponent });
62
+ }
63
+ return /* @__PURE__ */ jsx(RolloutlyContext.Provider, { value: contextValue, children });
64
+ }
65
+ function useRolloutlyClient() {
66
+ const { client } = useContext(RolloutlyContext);
67
+ if (!client) {
68
+ throw new Error("useRolloutlyClient must be used within RolloutlyProvider");
69
+ }
70
+ return client;
71
+ }
72
+ function useRolloutly() {
73
+ const { client, isLoading, isError, error } = useContext(RolloutlyContext);
74
+ if (!client) {
75
+ throw new Error("useRolloutly must be used within RolloutlyProvider");
76
+ }
77
+ const getFlag = useCallback(
78
+ (key) => {
79
+ return client.getFlag(key);
80
+ },
81
+ [client]
82
+ );
83
+ const isEnabled = useCallback(
84
+ (key) => {
85
+ return client.isEnabled(key);
86
+ },
87
+ [client]
88
+ );
89
+ return {
90
+ isLoading,
91
+ isError,
92
+ error,
93
+ getFlag,
94
+ isEnabled
95
+ };
96
+ }
97
+ function useFlag(key) {
98
+ const client = useRolloutlyClient();
99
+ const getSnapshot = useCallback(() => {
100
+ return client.getFlag(key);
101
+ }, [client, key]);
102
+ const subscribe = useCallback(
103
+ (onStoreChange) => {
104
+ return client.subscribe(onStoreChange);
105
+ },
106
+ [client]
107
+ );
108
+ return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
109
+ }
110
+ function useFlagEnabled(key) {
111
+ const client = useRolloutlyClient();
112
+ const getSnapshot = useCallback(() => {
113
+ return client.isEnabled(key);
114
+ }, [client, key]);
115
+ const subscribe = useCallback(
116
+ (onStoreChange) => {
117
+ return client.subscribe(onStoreChange);
118
+ },
119
+ [client]
120
+ );
121
+ return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
122
+ }
123
+ function useFlags() {
124
+ const client = useRolloutlyClient();
125
+ const getSnapshot = useCallback(() => {
126
+ const flags = client.getFlags();
127
+ return Object.entries(flags).reduce(
128
+ (acc, [key, flag]) => {
129
+ acc[key] = flag.enabled ? flag.value : void 0;
130
+ return acc;
131
+ },
132
+ {}
133
+ );
134
+ }, [client]);
135
+ const subscribe = useCallback(
136
+ (onStoreChange) => {
137
+ return client.subscribe(onStoreChange);
138
+ },
139
+ [client]
140
+ );
141
+ return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
142
+ }
143
+
144
+ export { RolloutlyProvider, useFlag, useFlagEnabled, useFlags, useRolloutly, useRolloutlyClient };
145
+ //# sourceMappingURL=index.js.map
146
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/provider.tsx"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["'use client';\n\nimport { RolloutlyClient, type FlagValue } from '@rolloutly/core';\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n useSyncExternalStore,\n} from 'react';\n\nimport type { RolloutlyContextValue, RolloutlyProviderProps } from './types';\n\nconst RolloutlyContext = createContext<{\n client: RolloutlyClient | null;\n isLoading: boolean;\n isError: boolean;\n error: Error | null;\n}>({\n client: null,\n isLoading: true,\n isError: false,\n error: null,\n});\n\n/**\n * Provider component that initializes Rolloutly and provides context\n */\nexport function RolloutlyProvider({\n token,\n children,\n baseUrl,\n realtimeEnabled = true,\n defaultFlags,\n debug = false,\n loadingComponent,\n}: RolloutlyProviderProps): JSX.Element {\n const [isLoading, setIsLoading] = useState(true);\n const [isError, setIsError] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const client = useMemo(() => {\n return new RolloutlyClient({\n token,\n baseUrl,\n realtimeEnabled,\n defaultFlags,\n debug,\n });\n }, [token, baseUrl, realtimeEnabled, defaultFlags, debug]);\n\n useEffect(() => {\n let mounted = true;\n\n client\n .waitForInit()\n .then(() => {\n if (mounted) {\n setIsLoading(false);\n }\n })\n .catch((err) => {\n if (mounted) {\n setIsError(true);\n setError(err instanceof Error ? err : new Error(String(err)));\n setIsLoading(false);\n }\n });\n\n return () => {\n mounted = false;\n client.close();\n };\n }, [client]);\n\n const contextValue = useMemo(\n () => ({\n client,\n isLoading,\n isError,\n error,\n }),\n [client, isLoading, isError, error],\n );\n\n if (isLoading && loadingComponent) {\n return <>{loadingComponent}</>;\n }\n\n return (\n <RolloutlyContext.Provider value={contextValue}>\n {children}\n </RolloutlyContext.Provider>\n );\n}\n\n/**\n * Hook to access the Rolloutly client directly\n */\nexport function useRolloutlyClient(): RolloutlyClient {\n const { client } = useContext(RolloutlyContext);\n\n if (!client) {\n throw new Error('useRolloutlyClient must be used within RolloutlyProvider');\n }\n\n return client;\n}\n\n/**\n * Hook to get Rolloutly status\n */\nexport function useRolloutly(): RolloutlyContextValue {\n const { client, isLoading, isError, error } = useContext(RolloutlyContext);\n\n if (!client) {\n throw new Error('useRolloutly must be used within RolloutlyProvider');\n }\n\n const getFlag = useCallback(\n <T extends FlagValue = FlagValue>(key: string): T | undefined => {\n return client.getFlag<T>(key);\n },\n [client],\n );\n\n const isEnabled = useCallback(\n (key: string): boolean => {\n return client.isEnabled(key);\n },\n [client],\n );\n\n return {\n isLoading,\n isError,\n error,\n getFlag,\n isEnabled,\n };\n}\n\n/**\n * Hook to get a single flag value with real-time updates\n */\nexport function useFlag<T extends FlagValue = FlagValue>(\n key: string,\n): T | undefined {\n const client = useRolloutlyClient();\n\n const getSnapshot = useCallback((): T | undefined => {\n return client.getFlag<T>(key);\n }, [client, key]);\n\n const subscribe = useCallback(\n (onStoreChange: () => void): (() => void) => {\n return client.subscribe(onStoreChange);\n },\n [client],\n );\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n/**\n * Hook to check if a boolean flag is enabled with real-time updates\n */\nexport function useFlagEnabled(key: string): boolean {\n const client = useRolloutlyClient();\n\n const getSnapshot = useCallback((): boolean => {\n return client.isEnabled(key);\n }, [client, key]);\n\n const subscribe = useCallback(\n (onStoreChange: () => void): (() => void) => {\n return client.subscribe(onStoreChange);\n },\n [client],\n );\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n/**\n * Hook to get all flags with real-time updates\n */\nexport function useFlags(): Record<string, FlagValue> {\n const client = useRolloutlyClient();\n\n const getSnapshot = useCallback((): Record<string, FlagValue> => {\n const flags = client.getFlags();\n\n return Object.entries(flags).reduce<Record<string, FlagValue>>(\n (acc, [key, flag]) => {\n acc[key] = flag.enabled ? flag.value : undefined!;\n\n return acc;\n },\n {},\n );\n }, [client]);\n\n const subscribe = useCallback(\n (onStoreChange: () => void): (() => void) => {\n return client.subscribe(onStoreChange);\n },\n [client],\n );\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@rolloutly/react",
3
+ "version": "0.1.0",
4
+ "description": "Rolloutly feature flags SDK - React hooks and provider",
5
+ "author": "Kevin Beltrão",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/KevBeltrao/rolloutly-sdk.git",
10
+ "directory": "packages/react"
11
+ },
12
+ "keywords": [
13
+ "feature-flags",
14
+ "feature-toggles",
15
+ "rolloutly",
16
+ "sdk",
17
+ "react",
18
+ "hooks"
19
+ ],
20
+ "type": "module",
21
+ "main": "./dist/index.cjs",
22
+ "module": "./dist/index.js",
23
+ "types": "./dist/index.d.ts",
24
+ "exports": {
25
+ ".": {
26
+ "import": {
27
+ "types": "./dist/index.d.ts",
28
+ "default": "./dist/index.js"
29
+ },
30
+ "require": {
31
+ "types": "./dist/index.d.cts",
32
+ "default": "./dist/index.cjs"
33
+ }
34
+ }
35
+ },
36
+ "files": [
37
+ "dist",
38
+ "README.md"
39
+ ],
40
+ "scripts": {
41
+ "build": "tsup",
42
+ "dev": "tsup --watch",
43
+ "typecheck": "tsc --noEmit",
44
+ "clean": "rm -rf dist"
45
+ },
46
+ "dependencies": {
47
+ "@rolloutly/core": "^0.1.0"
48
+ },
49
+ "peerDependencies": {
50
+ "react": ">=18.0.0"
51
+ },
52
+ "devDependencies": {
53
+ "@types/react": "^18.2.0",
54
+ "react": "^18.2.0",
55
+ "tsup": "^8.0.1",
56
+ "typescript": "^5.3.3"
57
+ }
58
+ }