@togglely/sdk-react 1.1.10 → 1.2.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 +163 -83
- package/package.json +38 -38
package/README.md
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Togglely React SDK
|
|
2
2
|
|
|
3
|
-
React
|
|
3
|
+
React hooks and components for [Togglely](https://togglely.io) feature flag management.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🎣 **React Hooks** - `useToggle`, `useStringToggle`, `useNumberToggle`, `useJSONToggle`
|
|
8
|
+
- 🏗️ **Components** - `FeatureToggle`, `FeatureToggleSwitch` for declarative UI
|
|
9
|
+
- ⚡ **SSR Support** - Works with Next.js, Remix, and other SSR frameworks
|
|
10
|
+
- 💾 **Offline Support** - Built-in offline fallback
|
|
11
|
+
- 🔒 **TypeScript** - Full type safety
|
|
6
12
|
|
|
7
13
|
## Installation
|
|
8
14
|
|
|
@@ -10,153 +16,227 @@ No automatic polling - manual refresh or use WebSockets for real-time updates.
|
|
|
10
16
|
npm install @togglely/sdk-react
|
|
11
17
|
```
|
|
12
18
|
|
|
13
|
-
##
|
|
14
|
-
|
|
15
|
-
### Provider
|
|
16
|
-
|
|
17
|
-
Wrap your app with `TogglelyProvider`. You can provide an `initialContext` for multi-tenant setups:
|
|
19
|
+
## Quick Start
|
|
18
20
|
|
|
19
21
|
```tsx
|
|
20
|
-
import { TogglelyProvider } from '@togglely/sdk-react';
|
|
22
|
+
import { TogglelyProvider, useToggle, FeatureToggle } from '@togglely/sdk-react';
|
|
21
23
|
|
|
22
24
|
function App() {
|
|
23
25
|
return (
|
|
24
26
|
<TogglelyProvider
|
|
25
27
|
apiKey="your-api-key"
|
|
26
|
-
project="
|
|
28
|
+
project="my-project"
|
|
27
29
|
environment="production"
|
|
28
|
-
baseUrl="https://
|
|
29
|
-
initialContext={{
|
|
30
|
-
tenantId: 'customer-123',
|
|
31
|
-
plan: 'premium'
|
|
32
|
-
}}
|
|
30
|
+
baseUrl="https://togglely.io"
|
|
33
31
|
>
|
|
34
|
-
<
|
|
32
|
+
<MyComponent />
|
|
35
33
|
</TogglelyProvider>
|
|
36
34
|
);
|
|
37
35
|
}
|
|
38
|
-
```
|
|
39
36
|
|
|
40
|
-
|
|
37
|
+
function MyComponent() {
|
|
38
|
+
// Using hook
|
|
39
|
+
const isEnabled = useToggle('new-feature', false);
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<div>
|
|
43
|
+
{isEnabled && <NewFeature />}
|
|
44
|
+
|
|
45
|
+
{/* Or using component */}
|
|
46
|
+
<FeatureToggle toggle="premium-feature" fallback={<FreeVersion />}>
|
|
47
|
+
<PremiumVersion />
|
|
48
|
+
</FeatureToggle>
|
|
49
|
+
</div>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
```
|
|
41
53
|
|
|
42
|
-
|
|
54
|
+
## Provider Configuration
|
|
43
55
|
|
|
44
56
|
```tsx
|
|
45
|
-
|
|
46
|
-
|
|
57
|
+
<TogglelyProvider
|
|
58
|
+
apiKey="your-api-key"
|
|
59
|
+
project="my-project"
|
|
60
|
+
environment="production"
|
|
61
|
+
baseUrl="https://togglely.io"
|
|
62
|
+
tenantId="brand-a" // For multi-brand projects
|
|
63
|
+
offlineJsonPath="/toggles.json" // Offline fallback
|
|
64
|
+
initialContext={{ userId: '123' }}
|
|
65
|
+
>
|
|
66
|
+
{children}
|
|
67
|
+
</TogglelyProvider>
|
|
68
|
+
```
|
|
47
69
|
|
|
48
|
-
|
|
49
|
-
const toggles = await getTogglelyState({
|
|
50
|
-
apiKey: process.env.TOGGLELY_API_KEY,
|
|
51
|
-
project: 'web-app',
|
|
52
|
-
environment: 'production',
|
|
53
|
-
baseUrl: 'https://your-togglely-instance.com'
|
|
54
|
-
}, {
|
|
55
|
-
tenantId: 'customer-123'
|
|
56
|
-
});
|
|
70
|
+
## Hooks
|
|
57
71
|
|
|
58
|
-
|
|
59
|
-
}
|
|
72
|
+
### useToggle
|
|
60
73
|
|
|
61
|
-
|
|
62
|
-
<TogglelyProvider initialToggles={props.initialToggles} ...>
|
|
63
|
-
```
|
|
74
|
+
Check if a boolean feature is enabled:
|
|
64
75
|
|
|
65
|
-
|
|
76
|
+
```tsx
|
|
77
|
+
const isEnabled = useToggle('new-feature', false);
|
|
78
|
+
```
|
|
66
79
|
|
|
67
|
-
|
|
80
|
+
### useStringToggle
|
|
68
81
|
|
|
69
|
-
|
|
82
|
+
Get a string value:
|
|
70
83
|
|
|
71
84
|
```tsx
|
|
72
|
-
|
|
73
|
-
const client = useTogglelyClient();
|
|
74
|
-
|
|
75
|
-
const handleLogin = (user) => {
|
|
76
|
-
client.setContext({
|
|
77
|
-
userId: user.id,
|
|
78
|
-
tenantId: user.companyId
|
|
79
|
-
});
|
|
80
|
-
};
|
|
81
|
-
}
|
|
85
|
+
const message = useStringToggle('welcome-message', 'Hello!');
|
|
82
86
|
```
|
|
83
87
|
|
|
84
|
-
|
|
88
|
+
### useNumberToggle
|
|
85
89
|
|
|
86
|
-
|
|
90
|
+
Get a number value:
|
|
87
91
|
|
|
88
92
|
```tsx
|
|
89
|
-
|
|
90
|
-
const isEnabled = useToggle('new-feature', false);
|
|
91
|
-
return isEnabled ? <NewFeature /> : <OldFeature />;
|
|
92
|
-
}
|
|
93
|
+
const timeout = useNumberToggle('api-timeout', 5000);
|
|
93
94
|
```
|
|
94
95
|
|
|
95
|
-
|
|
96
|
+
### useJSONToggle
|
|
96
97
|
|
|
97
|
-
Get a
|
|
98
|
+
Get a JSON value:
|
|
98
99
|
|
|
99
100
|
```tsx
|
|
100
|
-
const
|
|
101
|
+
const config = useJSONToggle('app-config', { theme: 'dark' });
|
|
101
102
|
```
|
|
102
103
|
|
|
103
|
-
|
|
104
|
+
### useTogglelyClient
|
|
104
105
|
|
|
105
|
-
|
|
106
|
+
Access the client directly:
|
|
106
107
|
|
|
107
108
|
```tsx
|
|
108
|
-
const
|
|
109
|
+
const client = useTogglelyClient();
|
|
110
|
+
client.setContext({ userId: '123' });
|
|
109
111
|
```
|
|
110
112
|
|
|
111
|
-
|
|
113
|
+
### useTogglelyState
|
|
112
114
|
|
|
113
|
-
Get
|
|
115
|
+
Get the current state:
|
|
114
116
|
|
|
115
117
|
```tsx
|
|
116
|
-
const
|
|
118
|
+
const { isReady, isOffline, lastError } = useTogglelyState();
|
|
117
119
|
```
|
|
118
120
|
|
|
119
|
-
|
|
121
|
+
## Components
|
|
120
122
|
|
|
121
|
-
|
|
123
|
+
### FeatureToggle
|
|
122
124
|
|
|
123
125
|
```tsx
|
|
124
|
-
|
|
125
|
-
|
|
126
|
+
<FeatureToggle
|
|
127
|
+
toggle="new-feature"
|
|
128
|
+
fallback={<OldVersion />}
|
|
129
|
+
defaultValue={false}
|
|
130
|
+
>
|
|
131
|
+
<NewVersion />
|
|
132
|
+
</FeatureToggle>
|
|
126
133
|
```
|
|
127
134
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
Get the SDK state:
|
|
135
|
+
### FeatureToggleSwitch
|
|
131
136
|
|
|
132
137
|
```tsx
|
|
133
|
-
|
|
134
|
-
|
|
138
|
+
<FeatureToggleSwitch toggle="plan-type" defaultValue="free">
|
|
139
|
+
<FeatureToggleCase when="premium">
|
|
140
|
+
<PremiumFeatures />
|
|
141
|
+
</FeatureToggleCase>
|
|
142
|
+
<FeatureToggleCase when="pro">
|
|
143
|
+
<ProFeatures />
|
|
144
|
+
</FeatureToggleCase>
|
|
145
|
+
<FeatureToggleCase>
|
|
146
|
+
<FreeFeatures />
|
|
147
|
+
</FeatureToggleCase>
|
|
148
|
+
</FeatureToggleSwitch>
|
|
135
149
|
```
|
|
136
150
|
|
|
137
|
-
|
|
151
|
+
## Server-Side Rendering (SSR)
|
|
138
152
|
|
|
139
|
-
|
|
153
|
+
### Next.js App Router
|
|
140
154
|
|
|
141
|
-
|
|
155
|
+
```tsx
|
|
156
|
+
// app/layout.tsx
|
|
157
|
+
import { TogglelyProvider } from '@togglely/sdk-react';
|
|
158
|
+
|
|
159
|
+
export default async function RootLayout({ children }) {
|
|
160
|
+
// Fetch toggles on server
|
|
161
|
+
const response = await fetch(
|
|
162
|
+
`https://togglely.io/sdk/flags/my-project/production?apiKey=${process.env.TOGGLELY_APIKEY}`
|
|
163
|
+
);
|
|
164
|
+
const initialToggles = await response.json();
|
|
165
|
+
|
|
166
|
+
return (
|
|
167
|
+
<html>
|
|
168
|
+
<body>
|
|
169
|
+
<TogglelyProvider
|
|
170
|
+
apiKey={process.env.TOGGLELY_APIKEY!}
|
|
171
|
+
project="my-project"
|
|
172
|
+
environment="production"
|
|
173
|
+
baseUrl="https://togglely.io"
|
|
174
|
+
initialToggles={initialToggles}
|
|
175
|
+
>
|
|
176
|
+
{children}
|
|
177
|
+
</TogglelyProvider>
|
|
178
|
+
</body>
|
|
179
|
+
</html>
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Next.js Pages Router
|
|
142
185
|
|
|
143
186
|
```tsx
|
|
144
|
-
|
|
187
|
+
// pages/index.tsx
|
|
188
|
+
import { TogglelyProvider, getTogglelyState } from '@togglely/sdk-react';
|
|
145
189
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
190
|
+
export async function getServerSideProps() {
|
|
191
|
+
const initialToggles = await getTogglelyState({
|
|
192
|
+
apiKey: process.env.TOGGLELY_APIKEY!,
|
|
193
|
+
project: 'my-project',
|
|
194
|
+
environment: 'production',
|
|
195
|
+
baseUrl: 'https://togglely.io',
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
return { props: { initialToggles } };
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export default function Page({ initialToggles }) {
|
|
202
|
+
return (
|
|
203
|
+
<TogglelyProvider
|
|
204
|
+
apiKey={process.env.TOGGLELY_APIKEY!}
|
|
205
|
+
project="my-project"
|
|
206
|
+
environment="production"
|
|
207
|
+
baseUrl="https://togglely.io"
|
|
208
|
+
initialToggles={initialToggles}
|
|
209
|
+
>
|
|
210
|
+
<MyComponent />
|
|
211
|
+
</TogglelyProvider>
|
|
212
|
+
);
|
|
213
|
+
}
|
|
149
214
|
```
|
|
150
215
|
|
|
151
|
-
|
|
216
|
+
## Build-Time JSON Generation
|
|
217
|
+
|
|
218
|
+
Generate offline JSON during build:
|
|
152
219
|
|
|
153
|
-
|
|
220
|
+
```json
|
|
221
|
+
{
|
|
222
|
+
"scripts": {
|
|
223
|
+
"build": "togglely-pull --apiKey=$TOGGLELY_APIKEY --project=my-project --environment=production --output=./public/toggles.json && next build"
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Then use in your app:
|
|
154
229
|
|
|
155
230
|
```tsx
|
|
156
231
|
<TogglelyProvider
|
|
157
232
|
apiKey="your-api-key"
|
|
233
|
+
project="my-project"
|
|
158
234
|
environment="production"
|
|
159
|
-
baseUrl="https://
|
|
160
|
-
|
|
235
|
+
baseUrl="https://togglely.io"
|
|
236
|
+
offlineJsonPath="/toggles.json"
|
|
161
237
|
>
|
|
162
238
|
```
|
|
239
|
+
|
|
240
|
+
## License
|
|
241
|
+
|
|
242
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@togglely/sdk-react",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "React SDK for Togglely - Feature toggles with hooks",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"module": "dist/index.esm.js",
|
|
7
|
-
"types": "dist/index.d.ts",
|
|
8
|
-
"files": [
|
|
9
|
-
"dist"
|
|
10
|
-
],
|
|
11
|
-
"scripts": {
|
|
12
|
-
"build": "tsc && rollup -c",
|
|
13
|
-
"test": "jest"
|
|
14
|
-
},
|
|
15
|
-
"keywords": [
|
|
16
|
-
"feature-flags",
|
|
17
|
-
"feature-toggles",
|
|
18
|
-
"togglely",
|
|
19
|
-
"react",
|
|
20
|
-
"hooks"
|
|
21
|
-
],
|
|
22
|
-
"author": "Togglely",
|
|
23
|
-
"license": "MIT",
|
|
24
|
-
"peerDependencies": {
|
|
25
|
-
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
|
26
|
-
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
|
27
|
-
},
|
|
28
|
-
"dependencies": {
|
|
29
|
-
"@togglely/sdk-core": "^1.0.0"
|
|
30
|
-
},
|
|
31
|
-
"devDependencies": {
|
|
32
|
-
"@rollup/plugin-typescript": "^11.1.5",
|
|
33
|
-
"@types/react": "^18.2.45",
|
|
34
|
-
"rollup": "^4.9.1",
|
|
35
|
-
"tslib": "^2.6.2",
|
|
36
|
-
"typescript": "^5.3.3"
|
|
37
|
-
}
|
|
38
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@togglely/sdk-react",
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "React SDK for Togglely - Feature toggles with hooks",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.esm.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc && rollup -c",
|
|
13
|
+
"test": "jest"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"feature-flags",
|
|
17
|
+
"feature-toggles",
|
|
18
|
+
"togglely",
|
|
19
|
+
"react",
|
|
20
|
+
"hooks"
|
|
21
|
+
],
|
|
22
|
+
"author": "Togglely",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"peerDependencies": {
|
|
25
|
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
|
26
|
+
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@togglely/sdk-core": "^1.0.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@rollup/plugin-typescript": "^11.1.5",
|
|
33
|
+
"@types/react": "^18.2.45",
|
|
34
|
+
"rollup": "^4.9.1",
|
|
35
|
+
"tslib": "^2.6.2",
|
|
36
|
+
"typescript": "^5.3.3"
|
|
37
|
+
}
|
|
38
|
+
}
|