wolves-react-client 1.0.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 +367 -0
- package/dist/WolvesContext.d.ts +25 -0
- package/dist/WolvesContext.d.ts.map +1 -0
- package/dist/WolvesContext.js +13 -0
- package/dist/WolvesProvider.d.ts +24 -0
- package/dist/WolvesProvider.d.ts.map +1 -0
- package/dist/WolvesProvider.js +202 -0
- package/dist/hooks/useExperiment.d.ts +37 -0
- package/dist/hooks/useExperiment.d.ts.map +1 -0
- package/dist/hooks/useExperiment.js +87 -0
- package/dist/hooks/useWolvesClient.d.ts +30 -0
- package/dist/hooks/useWolvesClient.d.ts.map +1 -0
- package/dist/hooks/useWolvesClient.js +40 -0
- package/dist/hooks/useWolvesEvent.d.ts +27 -0
- package/dist/hooks/useWolvesEvent.d.ts.map +1 -0
- package/dist/hooks/useWolvesEvent.js +56 -0
- package/dist/hooks/useWolvesInitialization.d.ts +43 -0
- package/dist/hooks/useWolvesInitialization.d.ts.map +1 -0
- package/dist/hooks/useWolvesInitialization.js +59 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/types/index.d.ts +75 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/utils/ssrHelpers.d.ts +14 -0
- package/dist/utils/ssrHelpers.d.ts.map +1 -0
- package/dist/utils/ssrHelpers.js +21 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
# Wolves React Client SDK
|
|
2
|
+
|
|
3
|
+
React SDK for the Wolves A/B Testing & Experimentation Platform. This library provides React hooks and components for easy integration of Wolves into your React applications.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🎣 **React Hooks** - `useExperiment`, `useWolvesClient`, `useWolvesEvent`
|
|
8
|
+
- ⚡ **Fast Initialization** - Async and sync initialization modes with caching
|
|
9
|
+
- 🔄 **Automatic Exposure Logging** - Experiments automatically log exposures
|
|
10
|
+
- 📦 **TypeScript Support** - Full TypeScript type definitions
|
|
11
|
+
- 🌐 **SSR Compatible** - Works with Next.js and other SSR frameworks
|
|
12
|
+
- 🎯 **Zero Config** - Works out of the box with sensible defaults
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install wolves-react-client wolves-js-client react
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
or with yarn:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
yarn add wolves-react-client wolves-js-client react
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
### 1. Wrap your app with WolvesProvider
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
import { WolvesProvider } from 'wolves-react-client';
|
|
32
|
+
|
|
33
|
+
function App() {
|
|
34
|
+
const user = {
|
|
35
|
+
userID: 'user-123',
|
|
36
|
+
email: 'user@example.com',
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<WolvesProvider sdkKey="your-sdk-key" user={user}>
|
|
41
|
+
<YourApp />
|
|
42
|
+
</WolvesProvider>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 2. Use experiments in your components
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
import { useExperiment } from 'wolves-react-client';
|
|
51
|
+
|
|
52
|
+
function FeatureComponent() {
|
|
53
|
+
const experiment = useExperiment('my-experiment');
|
|
54
|
+
|
|
55
|
+
const buttonColor = experiment.get('button_color', 'blue');
|
|
56
|
+
const buttonText = experiment.get('button_text', 'Click Me');
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<button style={{ backgroundColor: buttonColor }}>
|
|
60
|
+
{buttonText}
|
|
61
|
+
</button>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 3. Log custom events
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
import { useWolvesEvent } from 'wolves-react-client';
|
|
70
|
+
|
|
71
|
+
function CheckoutButton() {
|
|
72
|
+
const { logEvent } = useWolvesEvent();
|
|
73
|
+
|
|
74
|
+
const handleCheckout = () => {
|
|
75
|
+
logEvent('checkout_completed', 99.99, {
|
|
76
|
+
currency: 'USD',
|
|
77
|
+
items: '3',
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
return <button onClick={handleCheckout}>Checkout</button>;
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## API Reference
|
|
86
|
+
|
|
87
|
+
### WolvesProvider
|
|
88
|
+
|
|
89
|
+
The root component that initializes the Wolves client and provides context to child components.
|
|
90
|
+
|
|
91
|
+
#### Props
|
|
92
|
+
|
|
93
|
+
| Prop | Type | Required | Description |
|
|
94
|
+
|------|------|----------|-------------|
|
|
95
|
+
| `sdkKey` | `string` | Yes | Your Wolves SDK key |
|
|
96
|
+
| `user` | `WolvesUser` | Yes | User identification and attributes |
|
|
97
|
+
| `children` | `React.ReactNode` | Yes | Child components |
|
|
98
|
+
| `options` | `WolvesProviderOptions` | No | Configuration options |
|
|
99
|
+
| `waitForInitialization` | `boolean` | No | Wait for init before rendering children |
|
|
100
|
+
| `loadingComponent` | `React.ReactNode` | No | Component to show while loading |
|
|
101
|
+
|
|
102
|
+
#### Example with Options
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
<WolvesProvider
|
|
106
|
+
sdkKey="your-sdk-key"
|
|
107
|
+
user={{ userID: 'user-123' }}
|
|
108
|
+
options={{
|
|
109
|
+
initMode: 'async',
|
|
110
|
+
onInitialized: (details) => console.log('Initialized:', details),
|
|
111
|
+
onError: (error) => console.error('Error:', error),
|
|
112
|
+
}}
|
|
113
|
+
waitForInitialization={true}
|
|
114
|
+
loadingComponent={<LoadingSpinner />}
|
|
115
|
+
>
|
|
116
|
+
<App />
|
|
117
|
+
</WolvesProvider>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### useExperiment
|
|
121
|
+
|
|
122
|
+
Hook to access experiment configurations and automatically log exposures.
|
|
123
|
+
|
|
124
|
+
```tsx
|
|
125
|
+
const experiment = useExperiment<T>(experimentName, options?);
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
#### Parameters
|
|
129
|
+
|
|
130
|
+
- `experimentName` (string): Name of the experiment
|
|
131
|
+
- `options` (optional):
|
|
132
|
+
- `skipExposure` (boolean): Skip automatic exposure logging
|
|
133
|
+
- `defaultValue` (T): Default value if experiment not found
|
|
134
|
+
|
|
135
|
+
#### Returns
|
|
136
|
+
|
|
137
|
+
- `value` (T): The experiment configuration value
|
|
138
|
+
- `groupName` (string | null): The assigned group/variant
|
|
139
|
+
- `experimentID` (string): The experiment ID
|
|
140
|
+
- `get<K>(key, defaultValue)`: Get a specific parameter
|
|
141
|
+
- `isLoading` (boolean): Whether client is still loading
|
|
142
|
+
|
|
143
|
+
#### Example
|
|
144
|
+
|
|
145
|
+
```tsx
|
|
146
|
+
function MyComponent() {
|
|
147
|
+
const experiment = useExperiment('button-test', {
|
|
148
|
+
defaultValue: { color: 'blue', text: 'Click' }
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
if (experiment.isLoading) {
|
|
152
|
+
return <div>Loading...</div>;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return (
|
|
156
|
+
<div>
|
|
157
|
+
<p>Group: {experiment.groupName}</p>
|
|
158
|
+
<button style={{ color: experiment.get('color', 'blue') }}>
|
|
159
|
+
{experiment.get('text', 'Click')}
|
|
160
|
+
</button>
|
|
161
|
+
</div>
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### useWolvesClient
|
|
167
|
+
|
|
168
|
+
Hook to access the Wolves client instance and initialization state.
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
const { client, isInitialized, isLoading, error, updateUser } = useWolvesClient();
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
#### Returns
|
|
175
|
+
|
|
176
|
+
- `client` (WolvesClient | null): The client instance
|
|
177
|
+
- `isInitialized` (boolean): Whether initialization completed
|
|
178
|
+
- `isLoading` (boolean): Whether currently loading
|
|
179
|
+
- `initializationDetails` (WolvesUpdateDetails | null): Init details
|
|
180
|
+
- `error` (Error | null): Any initialization error
|
|
181
|
+
- `updateUser` (function): Function to update the current user
|
|
182
|
+
|
|
183
|
+
### useWolvesEvent
|
|
184
|
+
|
|
185
|
+
Hook to log custom events.
|
|
186
|
+
|
|
187
|
+
```tsx
|
|
188
|
+
const { logEvent } = useWolvesEvent();
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
#### Returns
|
|
192
|
+
|
|
193
|
+
- `logEvent(eventName, value?, metadata?)`: Function to log events
|
|
194
|
+
- `eventName` (string): Event name
|
|
195
|
+
- `value` (string | number, optional): Event value
|
|
196
|
+
- `metadata` (Record<string, string>, optional): Event metadata
|
|
197
|
+
|
|
198
|
+
#### Example
|
|
199
|
+
|
|
200
|
+
```tsx
|
|
201
|
+
function PurchaseButton() {
|
|
202
|
+
const { logEvent } = useWolvesEvent();
|
|
203
|
+
|
|
204
|
+
const handlePurchase = () => {
|
|
205
|
+
logEvent('purchase', 49.99, {
|
|
206
|
+
product_id: 'abc123',
|
|
207
|
+
category: 'electronics'
|
|
208
|
+
});
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
return <button onClick={handlePurchase}>Buy Now</button>;
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### useWolvesInitialization
|
|
216
|
+
|
|
217
|
+
Hook to monitor initialization status.
|
|
218
|
+
|
|
219
|
+
```tsx
|
|
220
|
+
const { isLoading, isReady, loadingStatus, error, details } = useWolvesInitialization();
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Initialization Modes
|
|
224
|
+
|
|
225
|
+
### Async Mode (Default)
|
|
226
|
+
|
|
227
|
+
Loads from cache first (if available), then fetches from network. Waits for network response before completing initialization.
|
|
228
|
+
|
|
229
|
+
```tsx
|
|
230
|
+
<WolvesProvider
|
|
231
|
+
sdkKey="your-sdk-key"
|
|
232
|
+
user={user}
|
|
233
|
+
options={{ initMode: 'async' }}
|
|
234
|
+
>
|
|
235
|
+
<App />
|
|
236
|
+
</WolvesProvider>
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Sync Mode
|
|
240
|
+
|
|
241
|
+
Immediately loads from cache and starts rendering. Fetches from network in the background to update cache for next session.
|
|
242
|
+
|
|
243
|
+
```tsx
|
|
244
|
+
<WolvesProvider
|
|
245
|
+
sdkKey="your-sdk-key"
|
|
246
|
+
user={user}
|
|
247
|
+
options={{
|
|
248
|
+
initMode: 'sync',
|
|
249
|
+
syncOptions: {
|
|
250
|
+
disableBackgroundCacheRefresh: false
|
|
251
|
+
}
|
|
252
|
+
}}
|
|
253
|
+
>
|
|
254
|
+
<App />
|
|
255
|
+
</WolvesProvider>
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## Server-Side Rendering (SSR)
|
|
259
|
+
|
|
260
|
+
The SDK is SSR-compatible and works with Next.js and other SSR frameworks.
|
|
261
|
+
|
|
262
|
+
### Next.js App Router Example
|
|
263
|
+
|
|
264
|
+
```tsx
|
|
265
|
+
// app/layout.tsx
|
|
266
|
+
'use client';
|
|
267
|
+
|
|
268
|
+
import { WolvesProvider } from 'wolves-react-client';
|
|
269
|
+
|
|
270
|
+
export default function RootLayout({ children }) {
|
|
271
|
+
return (
|
|
272
|
+
<html>
|
|
273
|
+
<body>
|
|
274
|
+
<WolvesProvider
|
|
275
|
+
sdkKey={process.env.NEXT_PUBLIC_WOLVES_SDK_KEY!}
|
|
276
|
+
user={{ userID: 'user-123' }}
|
|
277
|
+
>
|
|
278
|
+
{children}
|
|
279
|
+
</WolvesProvider>
|
|
280
|
+
</body>
|
|
281
|
+
</html>
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Next.js Pages Router Example
|
|
287
|
+
|
|
288
|
+
```tsx
|
|
289
|
+
// pages/_app.tsx
|
|
290
|
+
import { WolvesProvider } from 'wolves-react-client';
|
|
291
|
+
|
|
292
|
+
function MyApp({ Component, pageProps }) {
|
|
293
|
+
return (
|
|
294
|
+
<WolvesProvider
|
|
295
|
+
sdkKey={process.env.NEXT_PUBLIC_WOLVES_SDK_KEY!}
|
|
296
|
+
user={{ userID: 'user-123' }}
|
|
297
|
+
>
|
|
298
|
+
<Component {...pageProps} />
|
|
299
|
+
</WolvesProvider>
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export default MyApp;
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## TypeScript
|
|
307
|
+
|
|
308
|
+
The SDK is written in TypeScript and provides full type safety.
|
|
309
|
+
|
|
310
|
+
```tsx
|
|
311
|
+
interface ButtonExperiment {
|
|
312
|
+
color: string;
|
|
313
|
+
text: string;
|
|
314
|
+
size: 'small' | 'medium' | 'large';
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function MyButton() {
|
|
318
|
+
const experiment = useExperiment<ButtonExperiment>('button-test');
|
|
319
|
+
|
|
320
|
+
// Fully typed!
|
|
321
|
+
const color = experiment.get('color', 'blue');
|
|
322
|
+
const size = experiment.get('size', 'medium');
|
|
323
|
+
|
|
324
|
+
return <button>{experiment.value.text}</button>;
|
|
325
|
+
}
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## Best Practices
|
|
329
|
+
|
|
330
|
+
1. **Initialize Once**: Place `WolvesProvider` at the root of your app, not in individual components
|
|
331
|
+
2. **Memoize User**: Use `useMemo` for the user object to prevent unnecessary re-initializations
|
|
332
|
+
3. **Handle Loading States**: Check `isLoading` before rendering experiment-dependent UI
|
|
333
|
+
4. **Use Default Values**: Always provide default values for experiment parameters
|
|
334
|
+
5. **Log Meaningful Events**: Use descriptive event names and include relevant metadata
|
|
335
|
+
|
|
336
|
+
## Troubleshooting
|
|
337
|
+
|
|
338
|
+
### Provider Error
|
|
339
|
+
|
|
340
|
+
If you see "useWolvesClient must be used within WolvesProvider", ensure that your component is a child of `WolvesProvider`.
|
|
341
|
+
|
|
342
|
+
### SSR Errors
|
|
343
|
+
|
|
344
|
+
The SDK automatically detects SSR environments and skips initialization on the server. Make sure to use `'use client'` directive in Next.js App Router.
|
|
345
|
+
|
|
346
|
+
### Experiments Not Loading
|
|
347
|
+
|
|
348
|
+
- Verify your SDK key is correct
|
|
349
|
+
- Check network requests in browser DevTools
|
|
350
|
+
- Ensure the experiment exists in your Wolves dashboard
|
|
351
|
+
- Check for initialization errors using `useWolvesClient().error`
|
|
352
|
+
|
|
353
|
+
## Examples
|
|
354
|
+
|
|
355
|
+
See the `examples/` directory for complete working examples:
|
|
356
|
+
|
|
357
|
+
- `basic-usage/` - Simple React app example
|
|
358
|
+
- `nextjs-ssr/` - Next.js with SSR support
|
|
359
|
+
- `typescript-example/` - TypeScript with full type safety
|
|
360
|
+
|
|
361
|
+
## License
|
|
362
|
+
|
|
363
|
+
ISC
|
|
364
|
+
|
|
365
|
+
## Support
|
|
366
|
+
|
|
367
|
+
For issues and questions, please open an issue on GitHub.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { WolvesClient, WolvesUpdateDetails, WolvesUser } from 'wolves-js-client';
|
|
3
|
+
/**
|
|
4
|
+
* Context value provided to consuming components.
|
|
5
|
+
*/
|
|
6
|
+
export interface WolvesContextValue {
|
|
7
|
+
/** The WolvesClient instance, null if not yet initialized */
|
|
8
|
+
client: WolvesClient | null;
|
|
9
|
+
/** Whether the client has completed initialization */
|
|
10
|
+
isInitialized: boolean;
|
|
11
|
+
/** Whether the client is currently initializing */
|
|
12
|
+
isLoading: boolean;
|
|
13
|
+
/** Details from the last initialization/update */
|
|
14
|
+
initializationDetails: WolvesUpdateDetails | null;
|
|
15
|
+
/** Any error that occurred during initialization */
|
|
16
|
+
error: Error | null;
|
|
17
|
+
/** Function to update the current user */
|
|
18
|
+
updateUser: (user: WolvesUser) => Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* React Context for sharing Wolves client state across the component tree.
|
|
22
|
+
* Use the useWolvesClient hook to access this context instead of using it directly.
|
|
23
|
+
*/
|
|
24
|
+
export declare const WolvesContext: React.Context<WolvesContextValue | null>;
|
|
25
|
+
//# sourceMappingURL=WolvesContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WolvesContext.d.ts","sourceRoot":"","sources":["../src/WolvesContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEjF;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,6DAA6D;IAC7D,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IAC5B,sDAAsD;IACtD,aAAa,EAAE,OAAO,CAAC;IACvB,mDAAmD;IACnD,SAAS,EAAE,OAAO,CAAC;IACnB,kDAAkD;IAClD,qBAAqB,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAClD,oDAAoD;IACpD,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,0CAA0C;IAC1C,UAAU,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACjD;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa,0CAAuD,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.WolvesContext = void 0;
|
|
7
|
+
const react_1 = __importDefault(require("react"));
|
|
8
|
+
/**
|
|
9
|
+
* React Context for sharing Wolves client state across the component tree.
|
|
10
|
+
* Use the useWolvesClient hook to access this context instead of using it directly.
|
|
11
|
+
*/
|
|
12
|
+
exports.WolvesContext = react_1.default.createContext(null);
|
|
13
|
+
exports.WolvesContext.displayName = 'WolvesContext';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { WolvesProviderProps } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* WolvesProvider is the root component for integrating Wolves SDK with React.
|
|
5
|
+
* It initializes the WolvesClient and provides it to child components via React Context.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* import { WolvesProvider } from 'wolves-react-client';
|
|
10
|
+
*
|
|
11
|
+
* function App() {
|
|
12
|
+
* return (
|
|
13
|
+
* <WolvesProvider
|
|
14
|
+
* sdkKey="your-sdk-key"
|
|
15
|
+
* user={{ userID: 'user-123' }}
|
|
16
|
+
* >
|
|
17
|
+
* <YourApp />
|
|
18
|
+
* </WolvesProvider>
|
|
19
|
+
* );
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare const WolvesProvider: React.FC<WolvesProviderProps>;
|
|
24
|
+
//# sourceMappingURL=WolvesProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WolvesProvider.d.ts","sourceRoot":"","sources":["../src/WolvesProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+C,MAAM,OAAO,CAAC;AAGpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAG9C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAoKxD,CAAC"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.WolvesProvider = void 0;
|
|
46
|
+
const react_1 = __importStar(require("react"));
|
|
47
|
+
const wolves_js_client_1 = require("wolves-js-client");
|
|
48
|
+
const WolvesContext_1 = require("./WolvesContext");
|
|
49
|
+
const ssrHelpers_1 = require("./utils/ssrHelpers");
|
|
50
|
+
/**
|
|
51
|
+
* WolvesProvider is the root component for integrating Wolves SDK with React.
|
|
52
|
+
* It initializes the WolvesClient and provides it to child components via React Context.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```tsx
|
|
56
|
+
* import { WolvesProvider } from 'wolves-react-client';
|
|
57
|
+
*
|
|
58
|
+
* function App() {
|
|
59
|
+
* return (
|
|
60
|
+
* <WolvesProvider
|
|
61
|
+
* sdkKey="your-sdk-key"
|
|
62
|
+
* user={{ userID: 'user-123' }}
|
|
63
|
+
* >
|
|
64
|
+
* <YourApp />
|
|
65
|
+
* </WolvesProvider>
|
|
66
|
+
* );
|
|
67
|
+
* }
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
const WolvesProvider = ({ sdkKey, user, children, options = {}, waitForInitialization = false, loadingComponent = null, }) => {
|
|
71
|
+
const [client, setClient] = (0, react_1.useState)(null);
|
|
72
|
+
const [isInitialized, setIsInitialized] = (0, react_1.useState)(false);
|
|
73
|
+
const [isLoading, setIsLoading] = (0, react_1.useState)(true);
|
|
74
|
+
const [initializationDetails, setInitializationDetails] = (0, react_1.useState)(null);
|
|
75
|
+
const [error, setError] = (0, react_1.useState)(null);
|
|
76
|
+
const userRef = (0, react_1.useRef)(user);
|
|
77
|
+
// Skip initialization on server
|
|
78
|
+
const shouldInitialize = !(0, ssrHelpers_1.isServer)();
|
|
79
|
+
// Initialize client on mount
|
|
80
|
+
(0, react_1.useEffect)(() => {
|
|
81
|
+
if (!shouldInitialize) {
|
|
82
|
+
setIsLoading(false);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
let isMounted = true;
|
|
86
|
+
const initMode = options.initMode || 'async';
|
|
87
|
+
const initializeClient = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
88
|
+
try {
|
|
89
|
+
const newClient = new wolves_js_client_1.WolvesClient(sdkKey, user, options.apiEnv || 'prod');
|
|
90
|
+
if (initMode === 'async') {
|
|
91
|
+
// Async initialization
|
|
92
|
+
const details = yield newClient.initializeAsync(options.asyncOptions);
|
|
93
|
+
if (!isMounted)
|
|
94
|
+
return;
|
|
95
|
+
setInitializationDetails(details);
|
|
96
|
+
setIsInitialized(true);
|
|
97
|
+
setIsLoading(false);
|
|
98
|
+
setClient(newClient);
|
|
99
|
+
if (options.onInitialized) {
|
|
100
|
+
options.onInitialized(details);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
// Sync initialization
|
|
105
|
+
const details = newClient.initializeSync(options.syncOptions);
|
|
106
|
+
if (!isMounted)
|
|
107
|
+
return;
|
|
108
|
+
setInitializationDetails(details);
|
|
109
|
+
setIsInitialized(true);
|
|
110
|
+
setIsLoading(false);
|
|
111
|
+
setClient(newClient);
|
|
112
|
+
if (options.onInitialized) {
|
|
113
|
+
options.onInitialized(details);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
if (!isMounted)
|
|
119
|
+
return;
|
|
120
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
121
|
+
setError(error);
|
|
122
|
+
setIsLoading(false);
|
|
123
|
+
if (options.onError) {
|
|
124
|
+
options.onError(error);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
initializeClient();
|
|
129
|
+
// Cleanup on unmount
|
|
130
|
+
return () => {
|
|
131
|
+
isMounted = false;
|
|
132
|
+
if (client) {
|
|
133
|
+
client.shutdown().catch((e) => {
|
|
134
|
+
console.error('Failed to shutdown Wolves client:', e);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
// Intentionally only depend on sdkKey and shouldInitialize
|
|
139
|
+
// User and options changes are handled separately
|
|
140
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
141
|
+
}, [sdkKey, shouldInitialize]);
|
|
142
|
+
// Handle user changes
|
|
143
|
+
(0, react_1.useEffect)(() => {
|
|
144
|
+
if (!client || !isInitialized)
|
|
145
|
+
return;
|
|
146
|
+
// Check if user actually changed
|
|
147
|
+
if (JSON.stringify(userRef.current) === JSON.stringify(user)) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
userRef.current = user;
|
|
151
|
+
const updateUser = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
152
|
+
try {
|
|
153
|
+
const details = yield client.updateUserAsync(user, options.asyncOptions);
|
|
154
|
+
setInitializationDetails(details);
|
|
155
|
+
if (options.onInitialized) {
|
|
156
|
+
options.onInitialized(details);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
catch (err) {
|
|
160
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
161
|
+
setError(error);
|
|
162
|
+
if (options.onError) {
|
|
163
|
+
options.onError(error);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
updateUser();
|
|
168
|
+
// Intentionally don't include options in deps as we only want to react to user changes
|
|
169
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
170
|
+
}, [user, client, isInitialized]);
|
|
171
|
+
// Create updateUser function for manual user updates
|
|
172
|
+
const updateUser = (newUser) => __awaiter(void 0, void 0, void 0, function* () {
|
|
173
|
+
if (!client) {
|
|
174
|
+
throw new Error('Wolves client is not initialized');
|
|
175
|
+
}
|
|
176
|
+
userRef.current = newUser;
|
|
177
|
+
const details = yield client.updateUserAsync(newUser, options.asyncOptions);
|
|
178
|
+
setInitializationDetails(details);
|
|
179
|
+
if (options.onInitialized) {
|
|
180
|
+
options.onInitialized(details);
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
// Memoize context value to prevent unnecessary re-renders
|
|
184
|
+
const contextValue = (0, react_1.useMemo)(() => ({
|
|
185
|
+
client,
|
|
186
|
+
isInitialized,
|
|
187
|
+
isLoading,
|
|
188
|
+
initializationDetails,
|
|
189
|
+
error,
|
|
190
|
+
updateUser,
|
|
191
|
+
}),
|
|
192
|
+
// updateUser function is stable (defined outside useEffect)
|
|
193
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
194
|
+
[client, isInitialized, isLoading, initializationDetails, error]);
|
|
195
|
+
// Show loading component if waiting for initialization
|
|
196
|
+
if (waitForInitialization && isLoading && !error) {
|
|
197
|
+
return react_1.default.createElement(react_1.default.Fragment, null, loadingComponent);
|
|
198
|
+
}
|
|
199
|
+
return (react_1.default.createElement(WolvesContext_1.WolvesContext.Provider, { value: contextValue }, children));
|
|
200
|
+
};
|
|
201
|
+
exports.WolvesProvider = WolvesProvider;
|
|
202
|
+
exports.WolvesProvider.displayName = 'WolvesProvider';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { UseExperimentOptions, UseExperimentReturn } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Hook to access experiment configurations and automatically log exposure events.
|
|
4
|
+
*
|
|
5
|
+
* This hook retrieves experiment values from the Wolves client and automatically
|
|
6
|
+
* logs an exposure event (unless skipExposure is true). It handles loading states
|
|
7
|
+
* and provides default values when experiments are not found.
|
|
8
|
+
*
|
|
9
|
+
* @param experimentName - The name of the experiment to retrieve
|
|
10
|
+
* @param options - Optional configuration
|
|
11
|
+
* @param options.skipExposure - If true, skip logging exposure event (default: false)
|
|
12
|
+
* @param options.defaultValue - Default value to return if experiment not found
|
|
13
|
+
*
|
|
14
|
+
* @returns Experiment configuration with typed value access
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* function MyButton() {
|
|
19
|
+
* const experiment = useExperiment('button-test', {
|
|
20
|
+
* defaultValue: { color: 'blue', text: 'Click Me' }
|
|
21
|
+
* });
|
|
22
|
+
*
|
|
23
|
+
* if (experiment.isLoading) {
|
|
24
|
+
* return <button>Loading...</button>;
|
|
25
|
+
* }
|
|
26
|
+
*
|
|
27
|
+
* return (
|
|
28
|
+
* <button style={{ backgroundColor: experiment.get('color', 'blue') }}>
|
|
29
|
+
* {experiment.get('text', 'Click Me')}
|
|
30
|
+
* </button>
|
|
31
|
+
* );
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare function useExperiment<T extends Record<string, any> = Record<string, any>>(// eslint-disable-line @typescript-eslint/no-explicit-any
|
|
36
|
+
experimentName: string, options?: UseExperimentOptions<T>): UseExperimentReturn<T>;
|
|
37
|
+
//# sourceMappingURL=useExperiment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useExperiment.d.ts","sourceRoot":"","sources":["../../src/hooks/useExperiment.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAErE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAG,yDAAyD;AAC3I,cAAc,EAAE,MAAM,EACtB,OAAO,CAAC,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAChC,mBAAmB,CAAC,CAAC,CAAC,CAmDxB"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useExperiment = useExperiment;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const useWolvesClient_1 = require("./useWolvesClient");
|
|
6
|
+
/**
|
|
7
|
+
* Hook to access experiment configurations and automatically log exposure events.
|
|
8
|
+
*
|
|
9
|
+
* This hook retrieves experiment values from the Wolves client and automatically
|
|
10
|
+
* logs an exposure event (unless skipExposure is true). It handles loading states
|
|
11
|
+
* and provides default values when experiments are not found.
|
|
12
|
+
*
|
|
13
|
+
* @param experimentName - The name of the experiment to retrieve
|
|
14
|
+
* @param options - Optional configuration
|
|
15
|
+
* @param options.skipExposure - If true, skip logging exposure event (default: false)
|
|
16
|
+
* @param options.defaultValue - Default value to return if experiment not found
|
|
17
|
+
*
|
|
18
|
+
* @returns Experiment configuration with typed value access
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* function MyButton() {
|
|
23
|
+
* const experiment = useExperiment('button-test', {
|
|
24
|
+
* defaultValue: { color: 'blue', text: 'Click Me' }
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* if (experiment.isLoading) {
|
|
28
|
+
* return <button>Loading...</button>;
|
|
29
|
+
* }
|
|
30
|
+
*
|
|
31
|
+
* return (
|
|
32
|
+
* <button style={{ backgroundColor: experiment.get('color', 'blue') }}>
|
|
33
|
+
* {experiment.get('text', 'Click Me')}
|
|
34
|
+
* </button>
|
|
35
|
+
* );
|
|
36
|
+
* }
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
function useExperiment(// eslint-disable-line @typescript-eslint/no-explicit-any
|
|
40
|
+
experimentName, options) {
|
|
41
|
+
var _a;
|
|
42
|
+
const { client, isLoading: clientIsLoading } = (0, useWolvesClient_1.useWolvesClient)();
|
|
43
|
+
const skipExposure = (_a = options === null || options === void 0 ? void 0 : options.skipExposure) !== null && _a !== void 0 ? _a : false;
|
|
44
|
+
// Memoize defaultValue to prevent unnecessary re-evaluations
|
|
45
|
+
const defaultValue = (0, react_1.useMemo)(() => { var _a; return ((_a = options === null || options === void 0 ? void 0 : options.defaultValue) !== null && _a !== void 0 ? _a : {}); }, [options === null || options === void 0 ? void 0 : options.defaultValue]);
|
|
46
|
+
// Memoize the experiment result to prevent unnecessary re-evaluations
|
|
47
|
+
const experimentResult = (0, react_1.useMemo)(() => {
|
|
48
|
+
// Return loading state if client is not ready
|
|
49
|
+
if (clientIsLoading || !client) {
|
|
50
|
+
return {
|
|
51
|
+
value: defaultValue,
|
|
52
|
+
groupName: null,
|
|
53
|
+
experimentID: '',
|
|
54
|
+
get: (key, fallback) => {
|
|
55
|
+
if (defaultValue && key in defaultValue) {
|
|
56
|
+
return defaultValue[key];
|
|
57
|
+
}
|
|
58
|
+
return fallback;
|
|
59
|
+
},
|
|
60
|
+
isLoading: true,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
// Get experiment from client (automatically logs exposure unless we skip it)
|
|
64
|
+
let experiment;
|
|
65
|
+
if (skipExposure) {
|
|
66
|
+
// TODO: Implement a way to get experiment without logging exposure
|
|
67
|
+
// For now, we'll use the regular method
|
|
68
|
+
experiment = client.getExperiment(experimentName);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
experiment = client.getExperiment(experimentName);
|
|
72
|
+
}
|
|
73
|
+
const value = experiment.value || defaultValue;
|
|
74
|
+
const groupName = experiment.groupName;
|
|
75
|
+
const experimentID = experiment.experimentID;
|
|
76
|
+
return {
|
|
77
|
+
value,
|
|
78
|
+
groupName,
|
|
79
|
+
experimentID,
|
|
80
|
+
get: (key, fallback) => {
|
|
81
|
+
return experiment.get(key, fallback);
|
|
82
|
+
},
|
|
83
|
+
isLoading: false,
|
|
84
|
+
};
|
|
85
|
+
}, [client, clientIsLoading, experimentName, skipExposure, defaultValue]);
|
|
86
|
+
return experimentResult;
|
|
87
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { WolvesContextValue } from '../WolvesContext';
|
|
2
|
+
/**
|
|
3
|
+
* Hook to access the Wolves client instance and initialization state.
|
|
4
|
+
*
|
|
5
|
+
* This hook must be used within a WolvesProvider. It provides access to:
|
|
6
|
+
* - The WolvesClient instance
|
|
7
|
+
* - Initialization status (loading, initialized, error)
|
|
8
|
+
* - Function to manually update the user
|
|
9
|
+
*
|
|
10
|
+
* @throws Error if used outside of WolvesProvider
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* function MyComponent() {
|
|
15
|
+
* const { client, isInitialized, isLoading, error } = useWolvesClient();
|
|
16
|
+
*
|
|
17
|
+
* if (isLoading) {
|
|
18
|
+
* return <div>Loading...</div>;
|
|
19
|
+
* }
|
|
20
|
+
*
|
|
21
|
+
* if (error) {
|
|
22
|
+
* return <div>Error: {error.message}</div>;
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* return <div>Client ready!</div>;
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function useWolvesClient(): WolvesContextValue;
|
|
30
|
+
//# sourceMappingURL=useWolvesClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useWolvesClient.d.ts","sourceRoot":"","sources":["../../src/hooks/useWolvesClient.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAErE;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,eAAe,IAAI,kBAAkB,CAWpD"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useWolvesClient = useWolvesClient;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const WolvesContext_1 = require("../WolvesContext");
|
|
6
|
+
/**
|
|
7
|
+
* Hook to access the Wolves client instance and initialization state.
|
|
8
|
+
*
|
|
9
|
+
* This hook must be used within a WolvesProvider. It provides access to:
|
|
10
|
+
* - The WolvesClient instance
|
|
11
|
+
* - Initialization status (loading, initialized, error)
|
|
12
|
+
* - Function to manually update the user
|
|
13
|
+
*
|
|
14
|
+
* @throws Error if used outside of WolvesProvider
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* function MyComponent() {
|
|
19
|
+
* const { client, isInitialized, isLoading, error } = useWolvesClient();
|
|
20
|
+
*
|
|
21
|
+
* if (isLoading) {
|
|
22
|
+
* return <div>Loading...</div>;
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* if (error) {
|
|
26
|
+
* return <div>Error: {error.message}</div>;
|
|
27
|
+
* }
|
|
28
|
+
*
|
|
29
|
+
* return <div>Client ready!</div>;
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
function useWolvesClient() {
|
|
34
|
+
const context = (0, react_1.useContext)(WolvesContext_1.WolvesContext);
|
|
35
|
+
if (context === null) {
|
|
36
|
+
throw new Error('useWolvesClient must be used within a WolvesProvider. ' +
|
|
37
|
+
'Wrap your component tree with <WolvesProvider> to use Wolves hooks.');
|
|
38
|
+
}
|
|
39
|
+
return context;
|
|
40
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { UseWolvesEventReturn } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Hook to log custom events to the Wolves platform.
|
|
4
|
+
*
|
|
5
|
+
* This hook provides a stable callback function to log events. The callback
|
|
6
|
+
* function reference remains the same across renders for performance.
|
|
7
|
+
*
|
|
8
|
+
* @returns Object containing the logEvent function
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* function PurchaseButton() {
|
|
13
|
+
* const { logEvent } = useWolvesEvent();
|
|
14
|
+
*
|
|
15
|
+
* const handlePurchase = () => {
|
|
16
|
+
* logEvent('purchase_completed', 99.99, {
|
|
17
|
+
* product_id: 'abc123',
|
|
18
|
+
* category: 'electronics'
|
|
19
|
+
* });
|
|
20
|
+
* };
|
|
21
|
+
*
|
|
22
|
+
* return <button onClick={handlePurchase}>Buy Now</button>;
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function useWolvesEvent(): UseWolvesEventReturn;
|
|
27
|
+
//# sourceMappingURL=useWolvesEvent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useWolvesEvent.d.ts","sourceRoot":"","sources":["../../src/hooks/useWolvesEvent.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,cAAc,IAAI,oBAAoB,CAqCrD"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useWolvesEvent = useWolvesEvent;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const useWolvesClient_1 = require("./useWolvesClient");
|
|
6
|
+
/**
|
|
7
|
+
* Hook to log custom events to the Wolves platform.
|
|
8
|
+
*
|
|
9
|
+
* This hook provides a stable callback function to log events. The callback
|
|
10
|
+
* function reference remains the same across renders for performance.
|
|
11
|
+
*
|
|
12
|
+
* @returns Object containing the logEvent function
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```tsx
|
|
16
|
+
* function PurchaseButton() {
|
|
17
|
+
* const { logEvent } = useWolvesEvent();
|
|
18
|
+
*
|
|
19
|
+
* const handlePurchase = () => {
|
|
20
|
+
* logEvent('purchase_completed', 99.99, {
|
|
21
|
+
* product_id: 'abc123',
|
|
22
|
+
* category: 'electronics'
|
|
23
|
+
* });
|
|
24
|
+
* };
|
|
25
|
+
*
|
|
26
|
+
* return <button onClick={handlePurchase}>Buy Now</button>;
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
function useWolvesEvent() {
|
|
31
|
+
const { client, isInitialized } = (0, useWolvesClient_1.useWolvesClient)();
|
|
32
|
+
/**
|
|
33
|
+
* Log a custom event with optional value and metadata.
|
|
34
|
+
*
|
|
35
|
+
* @param eventName - Name of the event (e.g., 'purchase', 'click', 'signup')
|
|
36
|
+
* @param value - Optional numeric or string value associated with the event
|
|
37
|
+
* @param metadata - Optional key-value metadata for additional context
|
|
38
|
+
*/
|
|
39
|
+
const logEvent = (0, react_1.useCallback)((eventName, value, metadata) => {
|
|
40
|
+
if (!client || !isInitialized) {
|
|
41
|
+
if (process.env.NODE_ENV === 'development') {
|
|
42
|
+
console.warn(`[Wolves] Cannot log event "${eventName}": Client is not initialized yet.`);
|
|
43
|
+
}
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
client.logEvent(eventName, value, metadata);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
if (process.env.NODE_ENV === 'development') {
|
|
51
|
+
console.error(`[Wolves] Failed to log event "${eventName}":`, error);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}, [client, isInitialized]);
|
|
55
|
+
return { logEvent };
|
|
56
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { LoadingStatus, WolvesUpdateDetails } from 'wolves-js-client';
|
|
2
|
+
/**
|
|
3
|
+
* Return type for useWolvesInitialization hook
|
|
4
|
+
*/
|
|
5
|
+
export interface UseWolvesInitializationReturn {
|
|
6
|
+
/** Whether the client is currently loading/initializing */
|
|
7
|
+
isLoading: boolean;
|
|
8
|
+
/** Whether the client is ready for use */
|
|
9
|
+
isReady: boolean;
|
|
10
|
+
/** The current loading status */
|
|
11
|
+
loadingStatus: LoadingStatus;
|
|
12
|
+
/** Any error that occurred during initialization */
|
|
13
|
+
error: Error | null;
|
|
14
|
+
/** Details from the initialization process */
|
|
15
|
+
details: WolvesUpdateDetails | null;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Hook to monitor the initialization status of the Wolves client.
|
|
19
|
+
*
|
|
20
|
+
* This hook provides detailed information about the client's initialization
|
|
21
|
+
* state, which is useful for displaying loading screens or handling errors.
|
|
22
|
+
*
|
|
23
|
+
* @returns Object containing initialization status information
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```tsx
|
|
27
|
+
* function InitializationStatus() {
|
|
28
|
+
* const { isLoading, isReady, loadingStatus, error } = useWolvesInitialization();
|
|
29
|
+
*
|
|
30
|
+
* if (error) {
|
|
31
|
+
* return <div>Error: {error.message}</div>;
|
|
32
|
+
* }
|
|
33
|
+
*
|
|
34
|
+
* if (isLoading) {
|
|
35
|
+
* return <div>Loading experiments... ({loadingStatus})</div>;
|
|
36
|
+
* }
|
|
37
|
+
*
|
|
38
|
+
* return <div>Ready! Experiments loaded.</div>;
|
|
39
|
+
* }
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare function useWolvesInitialization(): UseWolvesInitializationReturn;
|
|
43
|
+
//# sourceMappingURL=useWolvesInitialization.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useWolvesInitialization.d.ts","sourceRoot":"","sources":["../../src/hooks/useWolvesInitialization.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEtE;;GAEG;AACH,MAAM,WAAW,6BAA6B;IAC5C,2DAA2D;IAC3D,SAAS,EAAE,OAAO,CAAC;IACnB,0CAA0C;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,iCAAiC;IACjC,aAAa,EAAE,aAAa,CAAC;IAC7B,oDAAoD;IACpD,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,8CAA8C;IAC9C,OAAO,EAAE,mBAAmB,GAAG,IAAI,CAAC;CACrC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,uBAAuB,IAAI,6BAA6B,CA8BvE"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useWolvesInitialization = useWolvesInitialization;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const useWolvesClient_1 = require("./useWolvesClient");
|
|
6
|
+
/**
|
|
7
|
+
* Hook to monitor the initialization status of the Wolves client.
|
|
8
|
+
*
|
|
9
|
+
* This hook provides detailed information about the client's initialization
|
|
10
|
+
* state, which is useful for displaying loading screens or handling errors.
|
|
11
|
+
*
|
|
12
|
+
* @returns Object containing initialization status information
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```tsx
|
|
16
|
+
* function InitializationStatus() {
|
|
17
|
+
* const { isLoading, isReady, loadingStatus, error } = useWolvesInitialization();
|
|
18
|
+
*
|
|
19
|
+
* if (error) {
|
|
20
|
+
* return <div>Error: {error.message}</div>;
|
|
21
|
+
* }
|
|
22
|
+
*
|
|
23
|
+
* if (isLoading) {
|
|
24
|
+
* return <div>Loading experiments... ({loadingStatus})</div>;
|
|
25
|
+
* }
|
|
26
|
+
*
|
|
27
|
+
* return <div>Ready! Experiments loaded.</div>;
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
function useWolvesInitialization() {
|
|
32
|
+
const { client, isInitialized, isLoading, initializationDetails, error } = (0, useWolvesClient_1.useWolvesClient)();
|
|
33
|
+
// Determine the loading status from the client
|
|
34
|
+
const loadingStatus = (0, react_1.useMemo)(() => {
|
|
35
|
+
if (!client) {
|
|
36
|
+
return 'Uninitialized';
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
return client.getLoadingStatus();
|
|
40
|
+
}
|
|
41
|
+
catch (_a) {
|
|
42
|
+
// Fallback if method doesn't exist or errors
|
|
43
|
+
if (isInitialized) {
|
|
44
|
+
return 'Ready';
|
|
45
|
+
}
|
|
46
|
+
if (isLoading) {
|
|
47
|
+
return 'Loading';
|
|
48
|
+
}
|
|
49
|
+
return 'Uninitialized';
|
|
50
|
+
}
|
|
51
|
+
}, [client, isInitialized, isLoading]);
|
|
52
|
+
return {
|
|
53
|
+
isLoading,
|
|
54
|
+
isReady: isInitialized && !isLoading,
|
|
55
|
+
loadingStatus,
|
|
56
|
+
error,
|
|
57
|
+
details: initializationDetails,
|
|
58
|
+
};
|
|
59
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main entry point for the Wolves React SDK
|
|
3
|
+
*/
|
|
4
|
+
export { WolvesProvider } from './WolvesProvider';
|
|
5
|
+
export { WolvesContext } from './WolvesContext';
|
|
6
|
+
export type { WolvesContextValue } from './WolvesContext';
|
|
7
|
+
export { useWolvesClient } from './hooks/useWolvesClient';
|
|
8
|
+
export { useExperiment } from './hooks/useExperiment';
|
|
9
|
+
export { useWolvesEvent } from './hooks/useWolvesEvent';
|
|
10
|
+
export { useWolvesInitialization } from './hooks/useWolvesInitialization';
|
|
11
|
+
export type { UseWolvesInitializationReturn } from './hooks/useWolvesInitialization';
|
|
12
|
+
export type { WolvesUser, WolvesUpdateDetails, LoadingStatus, AsyncUpdateOptions, SyncUpdateOptions, } from 'wolves-js-client';
|
|
13
|
+
export type { WolvesProviderProps, WolvesProviderOptions, UseExperimentOptions, UseExperimentReturn, UseWolvesEventReturn, InitMode, } from './types';
|
|
14
|
+
export { isBrowser, isServer } from './utils/ssrHelpers';
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGlD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAG1D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,YAAY,EAAE,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AAGrF,YAAY,EACV,UAAU,EACV,mBAAmB,EACnB,aAAa,EACb,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAG1B,YAAY,EACV,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,QAAQ,GACT,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Main entry point for the Wolves React SDK
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.isServer = exports.isBrowser = exports.useWolvesInitialization = exports.useWolvesEvent = exports.useExperiment = exports.useWolvesClient = exports.WolvesContext = exports.WolvesProvider = void 0;
|
|
7
|
+
// Provider component
|
|
8
|
+
var WolvesProvider_1 = require("./WolvesProvider");
|
|
9
|
+
Object.defineProperty(exports, "WolvesProvider", { enumerable: true, get: function () { return WolvesProvider_1.WolvesProvider; } });
|
|
10
|
+
// Context (for advanced use cases)
|
|
11
|
+
var WolvesContext_1 = require("./WolvesContext");
|
|
12
|
+
Object.defineProperty(exports, "WolvesContext", { enumerable: true, get: function () { return WolvesContext_1.WolvesContext; } });
|
|
13
|
+
// Hooks
|
|
14
|
+
var useWolvesClient_1 = require("./hooks/useWolvesClient");
|
|
15
|
+
Object.defineProperty(exports, "useWolvesClient", { enumerable: true, get: function () { return useWolvesClient_1.useWolvesClient; } });
|
|
16
|
+
var useExperiment_1 = require("./hooks/useExperiment");
|
|
17
|
+
Object.defineProperty(exports, "useExperiment", { enumerable: true, get: function () { return useExperiment_1.useExperiment; } });
|
|
18
|
+
var useWolvesEvent_1 = require("./hooks/useWolvesEvent");
|
|
19
|
+
Object.defineProperty(exports, "useWolvesEvent", { enumerable: true, get: function () { return useWolvesEvent_1.useWolvesEvent; } });
|
|
20
|
+
var useWolvesInitialization_1 = require("./hooks/useWolvesInitialization");
|
|
21
|
+
Object.defineProperty(exports, "useWolvesInitialization", { enumerable: true, get: function () { return useWolvesInitialization_1.useWolvesInitialization; } });
|
|
22
|
+
// SSR utilities
|
|
23
|
+
var ssrHelpers_1 = require("./utils/ssrHelpers");
|
|
24
|
+
Object.defineProperty(exports, "isBrowser", { enumerable: true, get: function () { return ssrHelpers_1.isBrowser; } });
|
|
25
|
+
Object.defineProperty(exports, "isServer", { enumerable: true, get: function () { return ssrHelpers_1.isServer; } });
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for Wolves React SDK
|
|
3
|
+
*/
|
|
4
|
+
import { WolvesUser, WolvesUpdateDetails, AsyncUpdateOptions, SyncUpdateOptions } from 'wolves-js-client';
|
|
5
|
+
import React from 'react';
|
|
6
|
+
/**
|
|
7
|
+
* Initialization mode for the Wolves client
|
|
8
|
+
*/
|
|
9
|
+
export type InitMode = 'async' | 'sync';
|
|
10
|
+
/**
|
|
11
|
+
* Options for configuring WolvesProvider behavior
|
|
12
|
+
*/
|
|
13
|
+
export interface WolvesProviderOptions {
|
|
14
|
+
/** Initialization mode: 'async' (default) or 'sync' */
|
|
15
|
+
initMode?: InitMode;
|
|
16
|
+
/** API environment: 'local', 'dev', or 'prod' (default) */
|
|
17
|
+
apiEnv?: 'local' | 'dev' | 'prod';
|
|
18
|
+
/** Options for async initialization */
|
|
19
|
+
asyncOptions?: AsyncUpdateOptions;
|
|
20
|
+
/** Options for sync initialization */
|
|
21
|
+
syncOptions?: SyncUpdateOptions;
|
|
22
|
+
/** Callback invoked when initialization completes */
|
|
23
|
+
onInitialized?: (details: WolvesUpdateDetails) => void;
|
|
24
|
+
/** Callback invoked when an error occurs */
|
|
25
|
+
onError?: (error: Error) => void;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Props for the WolvesProvider component
|
|
29
|
+
*/
|
|
30
|
+
export interface WolvesProviderProps {
|
|
31
|
+
/** SDK key for authenticating with Wolves API */
|
|
32
|
+
sdkKey: string;
|
|
33
|
+
/** User object containing user identification and attributes */
|
|
34
|
+
user: WolvesUser;
|
|
35
|
+
/** Child components that will have access to Wolves context */
|
|
36
|
+
children: React.ReactNode;
|
|
37
|
+
/** Optional configuration options */
|
|
38
|
+
options?: WolvesProviderOptions;
|
|
39
|
+
/** Whether to wait for initialization before rendering children */
|
|
40
|
+
waitForInitialization?: boolean;
|
|
41
|
+
/** Component to display while waiting for initialization */
|
|
42
|
+
loadingComponent?: React.ReactNode;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Options for the useExperiment hook
|
|
46
|
+
*/
|
|
47
|
+
export interface UseExperimentOptions<T = Record<string, any>> {
|
|
48
|
+
/** Whether to skip logging exposure events */
|
|
49
|
+
skipExposure?: boolean;
|
|
50
|
+
/** Default value to return if experiment is not found */
|
|
51
|
+
defaultValue?: T;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Return type for the useExperiment hook
|
|
55
|
+
*/
|
|
56
|
+
export interface UseExperimentReturn<T = Record<string, any>> {
|
|
57
|
+
/** The experiment configuration value */
|
|
58
|
+
value: T;
|
|
59
|
+
/** The group/variant name assigned to the user */
|
|
60
|
+
groupName: string | null;
|
|
61
|
+
/** The experiment ID */
|
|
62
|
+
experimentID: string;
|
|
63
|
+
/** Get a specific parameter from the experiment with a default fallback */
|
|
64
|
+
get: <K extends keyof T>(key: K, defaultValue: T[K]) => T[K];
|
|
65
|
+
/** Whether the client is still loading */
|
|
66
|
+
isLoading: boolean;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Return type for the useWolvesEvent hook
|
|
70
|
+
*/
|
|
71
|
+
export interface UseWolvesEventReturn {
|
|
72
|
+
/** Function to log a custom event */
|
|
73
|
+
logEvent: (eventName: string, value?: string | number, metadata?: Record<string, string>) => void;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1G,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAExC;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,uDAAuD;IACvD,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;IAClC,uCAAuC;IACvC,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,sCAAsC;IACtC,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,qDAAqD;IACrD,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACvD,4CAA4C;IAC5C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,IAAI,EAAE,UAAU,CAAC;IACjB,+DAA+D;IAC/D,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,qCAAqC;IACrC,OAAO,CAAC,EAAE,qBAAqB,CAAC;IAChC,mEAAmE;IACnE,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,4DAA4D;IAC5D,gBAAgB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAC3D,8CAA8C;IAC9C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,yDAAyD;IACzD,YAAY,CAAC,EAAE,CAAC,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAC1D,yCAAyC;IACzC,KAAK,EAAE,CAAC,CAAC;IACT,kDAAkD;IAClD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,wBAAwB;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,2EAA2E;IAC3E,GAAG,EAAE,CAAC,CAAC,SAAS,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7D,0CAA0C;IAC1C,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,qCAAqC;IACrC,QAAQ,EAAE,CACR,SAAS,EAAE,MAAM,EACjB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EACvB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAC9B,IAAI,CAAC;CACX"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-Side Rendering (SSR) helper utilities
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Checks if the code is running in a browser environment.
|
|
6
|
+
* Returns false on the server (Node.js).
|
|
7
|
+
*/
|
|
8
|
+
export declare function isBrowser(): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Checks if the code is running in a server environment.
|
|
11
|
+
* Returns true on the server (Node.js).
|
|
12
|
+
*/
|
|
13
|
+
export declare function isServer(): boolean;
|
|
14
|
+
//# sourceMappingURL=ssrHelpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssrHelpers.d.ts","sourceRoot":"","sources":["../../src/utils/ssrHelpers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAEnC;AAED;;;GAGG;AACH,wBAAgB,QAAQ,IAAI,OAAO,CAElC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Server-Side Rendering (SSR) helper utilities
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.isBrowser = isBrowser;
|
|
7
|
+
exports.isServer = isServer;
|
|
8
|
+
/**
|
|
9
|
+
* Checks if the code is running in a browser environment.
|
|
10
|
+
* Returns false on the server (Node.js).
|
|
11
|
+
*/
|
|
12
|
+
function isBrowser() {
|
|
13
|
+
return typeof window !== 'undefined' && typeof window.document !== 'undefined';
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Checks if the code is running in a server environment.
|
|
17
|
+
* Returns true on the server (Node.js).
|
|
18
|
+
*/
|
|
19
|
+
function isServer() {
|
|
20
|
+
return !isBrowser();
|
|
21
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "wolves-react-client",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "React SDK for Wolves A/B Testing Platform",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"keywords": [
|
|
11
|
+
"wolves",
|
|
12
|
+
"ab-testing",
|
|
13
|
+
"experiment",
|
|
14
|
+
"sdk",
|
|
15
|
+
"react",
|
|
16
|
+
"hooks"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc",
|
|
20
|
+
"test": "jest",
|
|
21
|
+
"lint": "eslint src --ext .ts,.tsx",
|
|
22
|
+
"format": "prettier --write \"src/**/*.{ts,tsx}\"",
|
|
23
|
+
"prepublishOnly": "npm run build"
|
|
24
|
+
},
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
|
27
|
+
"wolves-js-client": "^1.0.6"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@testing-library/jest-dom": "^6.1.5",
|
|
31
|
+
"@testing-library/react": "^14.0.0",
|
|
32
|
+
"@types/jest": "^29.0.0",
|
|
33
|
+
"@types/react": "^18.0.0",
|
|
34
|
+
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
|
35
|
+
"@typescript-eslint/parser": "^6.0.0",
|
|
36
|
+
"eslint": "^8.0.0",
|
|
37
|
+
"eslint-plugin-react": "^7.33.0",
|
|
38
|
+
"eslint-plugin-react-hooks": "^4.6.0",
|
|
39
|
+
"jest": "^29.0.0",
|
|
40
|
+
"jest-environment-jsdom": "^29.0.0",
|
|
41
|
+
"prettier": "^3.0.0",
|
|
42
|
+
"react": "^18.2.0",
|
|
43
|
+
"react-dom": "^18.2.0",
|
|
44
|
+
"ts-jest": "^29.0.0",
|
|
45
|
+
"typescript": "^5.0.0",
|
|
46
|
+
"wolves-js-client": "^1.0.6"
|
|
47
|
+
},
|
|
48
|
+
"author": "",
|
|
49
|
+
"license": "ISC"
|
|
50
|
+
}
|