@hyphen/react-sdk 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,597 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ Toggle: () => Toggle,
24
+ ToggleContext: () => ToggleContext,
25
+ ToggleProvider: () => ToggleProvider,
26
+ useToggle: () => useToggle,
27
+ withToggleProvider: () => withToggleProvider
28
+ });
29
+ module.exports = __toCommonJS(index_exports);
30
+
31
+ // node_modules/.pnpm/@hyphen+browser-sdk@1.0.6/node_modules/@hyphen/browser-sdk/dist/index.js
32
+ var import_hookified = require("hookified");
33
+ var __defProp2 = Object.defineProperty;
34
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
35
+ var __name = (target, value) => __defProp2(target, "name", { value, configurable: true });
36
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
37
+ var ToggleEvents = /* @__PURE__ */ (function(ToggleEvents2) {
38
+ ToggleEvents2["Error"] = "error";
39
+ return ToggleEvents2;
40
+ })({});
41
+ var _Toggle = class _Toggle2 extends import_hookified.Hookified {
42
+ constructor(options) {
43
+ super();
44
+ __publicField(this, "_publicApiKey");
45
+ __publicField(this, "_organizationId");
46
+ __publicField(this, "_applicationId");
47
+ __publicField(this, "_environment");
48
+ __publicField(this, "_horizonUrls", []);
49
+ __publicField(this, "_defaultContext");
50
+ __publicField(this, "_defaultTargetingKey", `${Math.random().toString(36).substring(7)}`);
51
+ if (options == null ? void 0 : options.applicationId) {
52
+ this._applicationId = options.applicationId;
53
+ }
54
+ if (options == null ? void 0 : options.environment) {
55
+ this._environment = options.environment;
56
+ } else {
57
+ this._environment = "development";
58
+ }
59
+ if (options == null ? void 0 : options.defaultContext) {
60
+ this._defaultContext = options.defaultContext;
61
+ }
62
+ if (options == null ? void 0 : options.publicApiKey) {
63
+ this._publicApiKey = options.publicApiKey;
64
+ this._organizationId = this.getOrgIdFromPublicKey(this._publicApiKey);
65
+ }
66
+ if (options == null ? void 0 : options.horizonUrls) {
67
+ this._horizonUrls = options.horizonUrls;
68
+ } else {
69
+ this._horizonUrls = this.getDefaultHorizonUrls(this._publicApiKey);
70
+ }
71
+ if (options == null ? void 0 : options.defaultTargetKey) {
72
+ this._defaultTargetingKey = options == null ? void 0 : options.defaultTargetKey;
73
+ } else {
74
+ if (this._defaultContext) {
75
+ this._defaultTargetingKey = this.getTargetingKey(this._defaultContext);
76
+ } else {
77
+ this._defaultTargetingKey = this.generateTargetKey();
78
+ }
79
+ }
80
+ }
81
+ /**
82
+ * Gets the public API key used for authentication.
83
+ *
84
+ * @returns The current public API key or undefined if not set
85
+ */
86
+ get publicApiKey() {
87
+ return this._publicApiKey;
88
+ }
89
+ /**
90
+ * Sets the public API key used for authentication.
91
+ *
92
+ * @param value - The public API key string or undefined to clear
93
+ * @throws {Error} If the key doesn't start with "public_"
94
+ */
95
+ set publicApiKey(value) {
96
+ this.setPublicKey(value);
97
+ }
98
+ /**
99
+ * Gets the default context used for toggle evaluations.
100
+ *
101
+ * @returns The current default ToggleContext
102
+ */
103
+ get defaultContext() {
104
+ return this._defaultContext;
105
+ }
106
+ /**
107
+ * Sets the default context used for toggle evaluations.
108
+ *
109
+ * @param value - The ToggleContext to use as default
110
+ */
111
+ set defaultContext(value) {
112
+ this._defaultContext = value;
113
+ }
114
+ /**
115
+ * Gets the organization ID extracted from the public API key.
116
+ *
117
+ * @returns The organization ID string or undefined if not available
118
+ */
119
+ get organizationId() {
120
+ return this._organizationId;
121
+ }
122
+ /**
123
+ * Gets the Horizon endpoint URLs used for load balancing.
124
+ *
125
+ * These URLs are used to distribute requests across multiple Horizon endpoints.
126
+ * If endpoints fail, the system will attempt to use the default horizon endpoint service.
127
+ *
128
+ * @returns Array of Horizon endpoint URLs
129
+ * @see {@link https://hyphen.ai/horizon} for more information
130
+ */
131
+ get horizonUrls() {
132
+ return this._horizonUrls;
133
+ }
134
+ /**
135
+ * Sets the Horizon endpoint URLs for load balancing.
136
+ *
137
+ * Configures multiple Horizon endpoints that will be used for load balancing.
138
+ * When endpoints fail, the system will fall back to the default horizon endpoint service.
139
+ *
140
+ * @param value - Array of Horizon endpoint URLs or empty array to clear
141
+ * @see {@link https://hyphen.ai/horizon} for more information
142
+ *
143
+ * @example
144
+ * ```typescript
145
+ * const toggle = new Toggle();
146
+ * toggle.horizonUrls = [
147
+ * 'https://org1.toggle.hyphen.cloud',
148
+ * 'https://org2.toggle.hyphen.cloud'
149
+ * ];
150
+ * ```
151
+ */
152
+ set horizonUrls(value) {
153
+ this._horizonUrls = value;
154
+ }
155
+ /**
156
+ * Gets the application ID used for toggle context.
157
+ *
158
+ * @returns The current application ID or undefined if not set
159
+ */
160
+ get applicationId() {
161
+ return this._applicationId;
162
+ }
163
+ /**
164
+ * Sets the application ID used for toggle context.
165
+ *
166
+ * @param value - The application ID string or undefined to clear
167
+ */
168
+ set applicationId(value) {
169
+ this._applicationId = value;
170
+ }
171
+ /**
172
+ * Gets the environment used for toggle context.
173
+ *
174
+ * @returns The current environment (defaults to 'development')
175
+ */
176
+ get environment() {
177
+ return this._environment;
178
+ }
179
+ /**
180
+ * Sets the environment used for toggle context.
181
+ *
182
+ * @param value - The environment string or undefined to clear
183
+ */
184
+ set environment(value) {
185
+ this._environment = value;
186
+ }
187
+ /**
188
+ * Gets the default targeting key used for toggle evaluations.
189
+ *
190
+ * @returns The current default targeting key or undefined if not set
191
+ */
192
+ get defaultTargetingKey() {
193
+ return this._defaultTargetingKey;
194
+ }
195
+ /**
196
+ * Sets the default targeting key used for toggle evaluations.
197
+ *
198
+ * @param value - The targeting key string or undefined to clear
199
+ */
200
+ set defaultTargetingKey(value) {
201
+ this._defaultTargetingKey = value;
202
+ }
203
+ async get(toggleKey, defaultValue, options) {
204
+ var _a, _b, _c, _d, _e, _f;
205
+ try {
206
+ const context = {
207
+ application: (_a = this._applicationId) != null ? _a : "",
208
+ environment: (_b = this._environment) != null ? _b : "development"
209
+ };
210
+ if (options == null ? void 0 : options.context) {
211
+ context.targetingKey = options == null ? void 0 : options.context.targetingKey;
212
+ context.ipAddress = options == null ? void 0 : options.context.ipAddress;
213
+ context.user = options == null ? void 0 : options.context.user;
214
+ context.customAttributes = options == null ? void 0 : options.context.customAttributes;
215
+ } else {
216
+ context.targetingKey = (_c = this._defaultContext) == null ? void 0 : _c.targetingKey;
217
+ context.ipAddress = (_d = this._defaultContext) == null ? void 0 : _d.ipAddress;
218
+ context.user = (_e = this._defaultContext) == null ? void 0 : _e.user;
219
+ context.customAttributes = (_f = this._defaultContext) == null ? void 0 : _f.customAttributes;
220
+ }
221
+ const fetchOptions = {
222
+ headers: {}
223
+ };
224
+ if (!context.targetingKey) {
225
+ context.targetingKey = this.getTargetingKey(context);
226
+ }
227
+ if (this._publicApiKey) {
228
+ fetchOptions.headers["x-api-key"] = this._publicApiKey;
229
+ } else {
230
+ throw new Error("You must set the publicApiKey");
231
+ }
232
+ if (context.application === "") {
233
+ throw new Error("You must set the applicationId");
234
+ }
235
+ const result = await this.fetch("/toggle/evaluate", context, fetchOptions);
236
+ if (result == null ? void 0 : result.toggles) {
237
+ return result.toggles[toggleKey].value;
238
+ }
239
+ } catch (error) {
240
+ this.emit(ToggleEvents.Error, error);
241
+ }
242
+ return defaultValue;
243
+ }
244
+ /**
245
+ * Retrieves a boolean toggle value.
246
+ *
247
+ * This is a convenience method that wraps the generic get() method with boolean type safety.
248
+ *
249
+ * @param toggleKey - The key of the toggle to retrieve
250
+ * @param defaultValue - The boolean value to return if the toggle is not found or an error occurs
251
+ * @param options - Optional configuration including context for toggle evaluation
252
+ * @returns Promise resolving to the boolean toggle value or defaultValue
253
+ *
254
+ * @example
255
+ * ```typescript
256
+ * const toggle = new Toggle({ publicApiKey: 'public_key', applicationId: 'app-id' });
257
+ * const isFeatureEnabled = await toggle.getBoolean('feature-flag', false);
258
+ * console.log(isFeatureEnabled); // true or false
259
+ * ```
260
+ */
261
+ async getBoolean(toggleKey, defaultValue, options) {
262
+ return this.get(toggleKey, defaultValue, options);
263
+ }
264
+ /**
265
+ * Retrieves a string toggle value.
266
+ *
267
+ * This is a convenience method that wraps the generic get() method with string type safety.
268
+ *
269
+ * @param toggleKey - The key of the toggle to retrieve
270
+ * @param defaultValue - The string value to return if the toggle is not found or an error occurs
271
+ * @param options - Optional configuration including context for toggle evaluation
272
+ * @returns Promise resolving to the string toggle value or defaultValue
273
+ *
274
+ * @example
275
+ * ```typescript
276
+ * const toggle = new Toggle({ publicApiKey: 'public_key', applicationId: 'app-id' });
277
+ * const message = await toggle.getString('welcome-message', 'Hello World');
278
+ * console.log(message); // 'Welcome to our app!' or 'Hello World'
279
+ * ```
280
+ */
281
+ async getString(toggleKey, defaultValue, options) {
282
+ return this.get(toggleKey, defaultValue, options);
283
+ }
284
+ /**
285
+ * Retrieves an object toggle value.
286
+ *
287
+ * This is a convenience method that wraps the generic get() method with object type safety.
288
+ * Note that the toggle service may return JSON as a string, which should be parsed if needed.
289
+ *
290
+ * @template T - The expected object type
291
+ * @param toggleKey - The key of the toggle to retrieve
292
+ * @param defaultValue - The object value to return if the toggle is not found or an error occurs
293
+ * @param options - Optional configuration including context for toggle evaluation
294
+ * @returns Promise resolving to the object toggle value or defaultValue
295
+ *
296
+ * @example
297
+ * ```typescript
298
+ * const toggle = new Toggle({ publicApiKey: 'public_key', applicationId: 'app-id' });
299
+ * const config = await toggle.getObject('app-config', { theme: 'light' });
300
+ * console.log(config); // { theme: 'dark', features: ['a', 'b'] } or { theme: 'light' }
301
+ * ```
302
+ */
303
+ async getObject(toggleKey, defaultValue, options) {
304
+ return this.get(toggleKey, defaultValue, options);
305
+ }
306
+ /**
307
+ * Retrieves a number toggle value.
308
+ *
309
+ * This is a convenience method that wraps the generic get() method with number type safety.
310
+ *
311
+ * @param toggleKey - The key of the toggle to retrieve
312
+ * @param defaultValue - The number value to return if the toggle is not found or an error occurs
313
+ * @param options - Optional configuration including context for toggle evaluation
314
+ * @returns Promise resolving to the number toggle value or defaultValue
315
+ *
316
+ * @example
317
+ * ```typescript
318
+ * const toggle = new Toggle({ publicApiKey: 'public_key', applicationId: 'app-id' });
319
+ * const maxRetries = await toggle.getNumber('max-retries', 3);
320
+ * console.log(maxRetries); // 5 or 3
321
+ * ```
322
+ */
323
+ async getNumber(toggleKey, defaultValue, options) {
324
+ return this.get(toggleKey, defaultValue, options);
325
+ }
326
+ /**
327
+ * Makes an HTTP POST request to the specified URL with automatic authentication.
328
+ *
329
+ * This method uses browser-compatible fetch and automatically includes the
330
+ * public API key in the x-api-key header if available. It supports load
331
+ * balancing across multiple horizon URLs with fallback behavior.
332
+ *
333
+ * @template T - The expected response type
334
+ * @param path - The API path to request (e.g., '/api/toggles')
335
+ * @param payload - The JSON payload to send in the request body
336
+ * @param options - Optional fetch configuration
337
+ * @returns Promise resolving to the parsed JSON response
338
+ * @throws {Error} If no horizon URLs are configured or all requests fail
339
+ *
340
+ * @example
341
+ * ```typescript
342
+ * const toggle = new Toggle({
343
+ * publicApiKey: 'public_your-key-here',
344
+ * horizonUrls: ['https://api.hyphen.cloud']
345
+ * });
346
+ *
347
+ * interface ToggleResponse {
348
+ * enabled: boolean;
349
+ * value: string;
350
+ * }
351
+ *
352
+ * const result = await toggle.fetch<ToggleResponse>('/api/toggle/feature-flag', {
353
+ * context: { targetingKey: 'user-123' }
354
+ * });
355
+ * console.log(result.enabled); // true/false
356
+ * ```
357
+ */
358
+ async fetch(path, payload, options) {
359
+ if (this._horizonUrls.length === 0) {
360
+ throw new Error("No horizon URLs configured. Set horizonUrls or provide a valid publicApiKey.");
361
+ }
362
+ const headers = {
363
+ "Content-Type": "application/json"
364
+ };
365
+ if (options == null ? void 0 : options.headers) {
366
+ if (options.headers instanceof Headers) {
367
+ options.headers.forEach((value, key) => {
368
+ headers[key] = value;
369
+ });
370
+ } else if (Array.isArray(options.headers)) {
371
+ options.headers.forEach(([key, value]) => {
372
+ headers[key] = value;
373
+ });
374
+ } else {
375
+ Object.assign(headers, options.headers);
376
+ }
377
+ }
378
+ if (this._publicApiKey) {
379
+ headers["x-api-key"] = this._publicApiKey;
380
+ }
381
+ const fetchOptions = {
382
+ method: "POST",
383
+ ...options,
384
+ headers,
385
+ body: payload ? JSON.stringify(payload) : options == null ? void 0 : options.body
386
+ };
387
+ const errors = [];
388
+ for (const baseUrl of this._horizonUrls) {
389
+ try {
390
+ const url = `${baseUrl.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
391
+ const response = await fetch(url, fetchOptions);
392
+ if (!response.ok) {
393
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
394
+ }
395
+ const data = await response.json();
396
+ return data;
397
+ } catch (error) {
398
+ const fetchError = error instanceof Error ? error : new Error("Unknown fetch error");
399
+ errors.push(fetchError);
400
+ }
401
+ }
402
+ throw new Error(`All horizon URLs failed. Last errors: ${errors.map((e) => e.message).join(", ")}`);
403
+ }
404
+ /**
405
+ * Validates and sets the public API key. This is used internally
406
+ *
407
+ * @param key - The public API key string or undefined to clear
408
+ * @throws {Error} If the key doesn't start with "public_"
409
+ */
410
+ setPublicKey(key) {
411
+ if (key !== void 0 && !key.startsWith("public_")) {
412
+ throw new Error("Public API key must start with 'public_'");
413
+ }
414
+ this._publicApiKey = key;
415
+ }
416
+ /**
417
+ * Extracts the organization ID from a public API key.
418
+ *
419
+ * The public key format is: `public_<base64-encoded-data>`
420
+ * The base64 data contains: `orgId:secretData`
421
+ * Only alphanumeric characters, underscores, and hyphens are considered valid in org IDs.
422
+ *
423
+ * @param publicKey - The public API key to extract the organization ID from
424
+ * @returns The organization ID if valid and extractable, undefined otherwise
425
+ *
426
+ * @example
427
+ * ```typescript
428
+ * const toggle = new Toggle();
429
+ * const orgId = toggle.getOrgIdFromPublicKey('public_dGVzdC1vcmc6c2VjcmV0');
430
+ * console.log(orgId); // 'test-org'
431
+ * ```
432
+ */
433
+ getOrgIdFromPublicKey(publicKey) {
434
+ try {
435
+ const keyWithoutPrefix = publicKey.replace(/^public_/, "");
436
+ const decoded = globalThis.atob ? globalThis.atob(keyWithoutPrefix) : Buffer.from(keyWithoutPrefix, "base64").toString();
437
+ const [orgId] = decoded.split(":");
438
+ const isValidOrgId = /^[a-zA-Z0-9_-]+$/.test(orgId);
439
+ return isValidOrgId ? orgId : void 0;
440
+ } catch (e) {
441
+ return void 0;
442
+ }
443
+ }
444
+ /**
445
+ * Builds the default Horizon API URL for the given public key.
446
+ *
447
+ * If a valid organization ID can be extracted from the public key, returns an
448
+ * organization-specific URL. Otherwise, returns the default fallback URL.
449
+ *
450
+ * @param publicKey - The public API key to build the URL for
451
+ * @returns Organization-specific URL or default fallback URL
452
+ *
453
+ * @example
454
+ * ```typescript
455
+ * const toggle = new Toggle();
456
+ *
457
+ * // With valid org ID
458
+ * const orgUrl = toggle.buildDefaultHorizonUrl('public_dGVzdC1vcmc6c2VjcmV0');
459
+ * console.log(orgUrl); // 'https://test-org.toggle.hyphen.cloud'
460
+ *
461
+ * // With invalid key
462
+ * const defaultUrl = toggle.buildDefaultHorizonUrl('invalid-key');
463
+ * console.log(defaultUrl); // 'https://toggle.hyphen.cloud'
464
+ * ```
465
+ */
466
+ getDefaultHorizonUrl(publicKey) {
467
+ if (publicKey) {
468
+ const orgId = this.getOrgIdFromPublicKey(publicKey);
469
+ return orgId ? `https://${orgId}.toggle.hyphen.cloud` : "https://toggle.hyphen.cloud";
470
+ }
471
+ return "https://toggle.hyphen.cloud";
472
+ }
473
+ /**
474
+ * Will get the urls. If you pass in the public key it will provide two urls.
475
+ * @param publicKey
476
+ * @returns
477
+ */
478
+ getDefaultHorizonUrls(publicKey) {
479
+ let result = [
480
+ this.getDefaultHorizonUrl()
481
+ ];
482
+ if (publicKey) {
483
+ const defaultUrl = result[0];
484
+ const orgUrl = this.getDefaultHorizonUrl(publicKey);
485
+ result = [];
486
+ if (orgUrl !== defaultUrl) {
487
+ result.push(orgUrl);
488
+ }
489
+ result.push(defaultUrl);
490
+ }
491
+ return result;
492
+ }
493
+ /**
494
+ * Generates a unique targeting key based on available context.
495
+ *
496
+ * @returns A targeting key in the format: `[app]-[env]-[random]` or simplified versions
497
+ */
498
+ generateTargetKey() {
499
+ const randomSuffix = Math.random().toString(36).substring(7);
500
+ const app = this._applicationId || "";
501
+ const env = this._environment || "";
502
+ const components = [
503
+ app,
504
+ env,
505
+ randomSuffix
506
+ ].filter(Boolean);
507
+ return components.join("-");
508
+ }
509
+ /**
510
+ * Extracts targeting key from a toggle context with fallback logic.
511
+ *
512
+ * @param context - The toggle context to extract targeting key from
513
+ * @returns The targeting key string
514
+ */
515
+ getTargetingKey(context) {
516
+ if (context.targetingKey) {
517
+ return context.targetingKey;
518
+ }
519
+ if (context.user) {
520
+ return context.user.id;
521
+ }
522
+ return this._defaultTargetingKey;
523
+ }
524
+ };
525
+ __name(_Toggle, "Toggle");
526
+ var Toggle = _Toggle;
527
+
528
+ // src/toggle-provider.tsx
529
+ var import_react = require("react");
530
+ var import_jsx_runtime = require("react/jsx-runtime");
531
+ var ToggleContext = (0, import_react.createContext)(null);
532
+ function ToggleProvider({
533
+ children,
534
+ publicApiKey,
535
+ applicationId,
536
+ environment,
537
+ defaultContext,
538
+ horizonUrls,
539
+ defaultTargetKey
540
+ }) {
541
+ const toggle = (0, import_react.useMemo)(() => {
542
+ return new Toggle({
543
+ publicApiKey,
544
+ applicationId,
545
+ environment,
546
+ defaultContext,
547
+ horizonUrls,
548
+ defaultTargetKey
549
+ });
550
+ }, [
551
+ publicApiKey,
552
+ applicationId,
553
+ environment,
554
+ defaultContext,
555
+ horizonUrls,
556
+ defaultTargetKey
557
+ ]);
558
+ (0, import_react.useEffect)(() => {
559
+ return () => {
560
+ };
561
+ }, [toggle]);
562
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ToggleContext.Provider, { value: toggle, children });
563
+ }
564
+
565
+ // src/use-toggle.tsx
566
+ var import_react2 = require("react");
567
+ function useToggle() {
568
+ const toggle = (0, import_react2.useContext)(ToggleContext);
569
+ if (!toggle) {
570
+ throw new Error(
571
+ "useToggle must be used within a ToggleProvider. Wrap your component tree with <ToggleProvider> or use withToggleProvider()."
572
+ );
573
+ }
574
+ return toggle;
575
+ }
576
+
577
+ // src/with-toggle-provider.tsx
578
+ var import_jsx_runtime2 = require("react/jsx-runtime");
579
+ function withToggleProvider(options) {
580
+ return function(Component) {
581
+ const WrappedComponent = (props) => {
582
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ToggleProvider, { ...options, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Component, { ...props }) });
583
+ };
584
+ const componentName = Component.displayName || Component.name || "Component";
585
+ WrappedComponent.displayName = `withToggleProvider(${componentName})`;
586
+ return WrappedComponent;
587
+ };
588
+ }
589
+ // Annotate the CommonJS export names for ESM import in node:
590
+ 0 && (module.exports = {
591
+ Toggle,
592
+ ToggleContext,
593
+ ToggleProvider,
594
+ useToggle,
595
+ withToggleProvider
596
+ });
597
+ /* v8 ignore next -- @preserve */
@@ -0,0 +1,71 @@
1
+ import { ToggleOptions, Toggle } from '@hyphen/browser-sdk';
2
+ export { Toggle, ToggleOptions } from '@hyphen/browser-sdk';
3
+ import * as react_jsx_runtime from 'react/jsx-runtime';
4
+ import { ReactNode, Context, ComponentType } from 'react';
5
+
6
+ /**
7
+ * Props for the ToggleProvider component
8
+ * Extends ToggleOptions from @hyphen/browser-sdk
9
+ */
10
+ interface ToggleProviderProps extends ToggleOptions {
11
+ /**
12
+ * React children to be wrapped by the provider
13
+ */
14
+ children: ReactNode;
15
+ }
16
+
17
+ /**
18
+ * React Context for the Toggle instance
19
+ */
20
+ declare const ToggleContext: Context<Toggle | null>;
21
+ /**
22
+ * Provider component that creates and provides a Toggle instance to the React tree
23
+ *
24
+ * @example
25
+ * ```tsx
26
+ * <ToggleProvider publicApiKey="public_..." applicationId="my-app">
27
+ * <App />
28
+ * </ToggleProvider>
29
+ * ```
30
+ */
31
+ declare function ToggleProvider({ children, publicApiKey, applicationId, environment, defaultContext, horizonUrls, defaultTargetKey, }: ToggleProviderProps): react_jsx_runtime.JSX.Element;
32
+
33
+ /**
34
+ * Hook to access the Toggle instance from the ToggleProvider
35
+ *
36
+ * @throws {Error} If used outside of a ToggleProvider
37
+ * @returns {Toggle} The Toggle instance from the provider
38
+ *
39
+ * @example
40
+ * ```tsx
41
+ * function MyComponent() {
42
+ * const toggle = useToggle();
43
+ * const isEnabled = toggle.getBoolean('my-feature', false);
44
+ *
45
+ * return <div>{isEnabled ? 'Feature enabled' : 'Feature disabled'}</div>;
46
+ * }
47
+ * ```
48
+ */
49
+ declare function useToggle(): Toggle;
50
+
51
+ /**
52
+ * Higher-order component that wraps a component with ToggleProvider
53
+ *
54
+ * @param options - Configuration options for the Toggle instance
55
+ * @returns A function that wraps a component with ToggleProvider
56
+ *
57
+ * @example
58
+ * ```tsx
59
+ * export default withToggleProvider({
60
+ * publicApiKey: "public_...",
61
+ * applicationId: "my-app",
62
+ * environment: "production",
63
+ * defaultContext: {
64
+ * user: { id: "user-123" }
65
+ * }
66
+ * })(App);
67
+ * ```
68
+ */
69
+ declare function withToggleProvider(options: ToggleOptions): <P extends object>(Component: ComponentType<P>) => ComponentType<P>;
70
+
71
+ export { ToggleContext, ToggleProvider, type ToggleProviderProps, useToggle, withToggleProvider };
package/dist/index.js CHANGED
@@ -1,5 +1,499 @@
1
- // src/index.ts
2
- import { Toggle as Toggle2 } from "@hyphen/browser-sdk";
1
+ // node_modules/.pnpm/@hyphen+browser-sdk@1.0.6/node_modules/@hyphen/browser-sdk/dist/index.js
2
+ import { Hookified } from "hookified";
3
+ var __defProp = Object.defineProperty;
4
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
5
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
6
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
7
+ var ToggleEvents = /* @__PURE__ */ (function(ToggleEvents2) {
8
+ ToggleEvents2["Error"] = "error";
9
+ return ToggleEvents2;
10
+ })({});
11
+ var _Toggle = class _Toggle2 extends Hookified {
12
+ constructor(options) {
13
+ super();
14
+ __publicField(this, "_publicApiKey");
15
+ __publicField(this, "_organizationId");
16
+ __publicField(this, "_applicationId");
17
+ __publicField(this, "_environment");
18
+ __publicField(this, "_horizonUrls", []);
19
+ __publicField(this, "_defaultContext");
20
+ __publicField(this, "_defaultTargetingKey", `${Math.random().toString(36).substring(7)}`);
21
+ if (options == null ? void 0 : options.applicationId) {
22
+ this._applicationId = options.applicationId;
23
+ }
24
+ if (options == null ? void 0 : options.environment) {
25
+ this._environment = options.environment;
26
+ } else {
27
+ this._environment = "development";
28
+ }
29
+ if (options == null ? void 0 : options.defaultContext) {
30
+ this._defaultContext = options.defaultContext;
31
+ }
32
+ if (options == null ? void 0 : options.publicApiKey) {
33
+ this._publicApiKey = options.publicApiKey;
34
+ this._organizationId = this.getOrgIdFromPublicKey(this._publicApiKey);
35
+ }
36
+ if (options == null ? void 0 : options.horizonUrls) {
37
+ this._horizonUrls = options.horizonUrls;
38
+ } else {
39
+ this._horizonUrls = this.getDefaultHorizonUrls(this._publicApiKey);
40
+ }
41
+ if (options == null ? void 0 : options.defaultTargetKey) {
42
+ this._defaultTargetingKey = options == null ? void 0 : options.defaultTargetKey;
43
+ } else {
44
+ if (this._defaultContext) {
45
+ this._defaultTargetingKey = this.getTargetingKey(this._defaultContext);
46
+ } else {
47
+ this._defaultTargetingKey = this.generateTargetKey();
48
+ }
49
+ }
50
+ }
51
+ /**
52
+ * Gets the public API key used for authentication.
53
+ *
54
+ * @returns The current public API key or undefined if not set
55
+ */
56
+ get publicApiKey() {
57
+ return this._publicApiKey;
58
+ }
59
+ /**
60
+ * Sets the public API key used for authentication.
61
+ *
62
+ * @param value - The public API key string or undefined to clear
63
+ * @throws {Error} If the key doesn't start with "public_"
64
+ */
65
+ set publicApiKey(value) {
66
+ this.setPublicKey(value);
67
+ }
68
+ /**
69
+ * Gets the default context used for toggle evaluations.
70
+ *
71
+ * @returns The current default ToggleContext
72
+ */
73
+ get defaultContext() {
74
+ return this._defaultContext;
75
+ }
76
+ /**
77
+ * Sets the default context used for toggle evaluations.
78
+ *
79
+ * @param value - The ToggleContext to use as default
80
+ */
81
+ set defaultContext(value) {
82
+ this._defaultContext = value;
83
+ }
84
+ /**
85
+ * Gets the organization ID extracted from the public API key.
86
+ *
87
+ * @returns The organization ID string or undefined if not available
88
+ */
89
+ get organizationId() {
90
+ return this._organizationId;
91
+ }
92
+ /**
93
+ * Gets the Horizon endpoint URLs used for load balancing.
94
+ *
95
+ * These URLs are used to distribute requests across multiple Horizon endpoints.
96
+ * If endpoints fail, the system will attempt to use the default horizon endpoint service.
97
+ *
98
+ * @returns Array of Horizon endpoint URLs
99
+ * @see {@link https://hyphen.ai/horizon} for more information
100
+ */
101
+ get horizonUrls() {
102
+ return this._horizonUrls;
103
+ }
104
+ /**
105
+ * Sets the Horizon endpoint URLs for load balancing.
106
+ *
107
+ * Configures multiple Horizon endpoints that will be used for load balancing.
108
+ * When endpoints fail, the system will fall back to the default horizon endpoint service.
109
+ *
110
+ * @param value - Array of Horizon endpoint URLs or empty array to clear
111
+ * @see {@link https://hyphen.ai/horizon} for more information
112
+ *
113
+ * @example
114
+ * ```typescript
115
+ * const toggle = new Toggle();
116
+ * toggle.horizonUrls = [
117
+ * 'https://org1.toggle.hyphen.cloud',
118
+ * 'https://org2.toggle.hyphen.cloud'
119
+ * ];
120
+ * ```
121
+ */
122
+ set horizonUrls(value) {
123
+ this._horizonUrls = value;
124
+ }
125
+ /**
126
+ * Gets the application ID used for toggle context.
127
+ *
128
+ * @returns The current application ID or undefined if not set
129
+ */
130
+ get applicationId() {
131
+ return this._applicationId;
132
+ }
133
+ /**
134
+ * Sets the application ID used for toggle context.
135
+ *
136
+ * @param value - The application ID string or undefined to clear
137
+ */
138
+ set applicationId(value) {
139
+ this._applicationId = value;
140
+ }
141
+ /**
142
+ * Gets the environment used for toggle context.
143
+ *
144
+ * @returns The current environment (defaults to 'development')
145
+ */
146
+ get environment() {
147
+ return this._environment;
148
+ }
149
+ /**
150
+ * Sets the environment used for toggle context.
151
+ *
152
+ * @param value - The environment string or undefined to clear
153
+ */
154
+ set environment(value) {
155
+ this._environment = value;
156
+ }
157
+ /**
158
+ * Gets the default targeting key used for toggle evaluations.
159
+ *
160
+ * @returns The current default targeting key or undefined if not set
161
+ */
162
+ get defaultTargetingKey() {
163
+ return this._defaultTargetingKey;
164
+ }
165
+ /**
166
+ * Sets the default targeting key used for toggle evaluations.
167
+ *
168
+ * @param value - The targeting key string or undefined to clear
169
+ */
170
+ set defaultTargetingKey(value) {
171
+ this._defaultTargetingKey = value;
172
+ }
173
+ async get(toggleKey, defaultValue, options) {
174
+ var _a, _b, _c, _d, _e, _f;
175
+ try {
176
+ const context = {
177
+ application: (_a = this._applicationId) != null ? _a : "",
178
+ environment: (_b = this._environment) != null ? _b : "development"
179
+ };
180
+ if (options == null ? void 0 : options.context) {
181
+ context.targetingKey = options == null ? void 0 : options.context.targetingKey;
182
+ context.ipAddress = options == null ? void 0 : options.context.ipAddress;
183
+ context.user = options == null ? void 0 : options.context.user;
184
+ context.customAttributes = options == null ? void 0 : options.context.customAttributes;
185
+ } else {
186
+ context.targetingKey = (_c = this._defaultContext) == null ? void 0 : _c.targetingKey;
187
+ context.ipAddress = (_d = this._defaultContext) == null ? void 0 : _d.ipAddress;
188
+ context.user = (_e = this._defaultContext) == null ? void 0 : _e.user;
189
+ context.customAttributes = (_f = this._defaultContext) == null ? void 0 : _f.customAttributes;
190
+ }
191
+ const fetchOptions = {
192
+ headers: {}
193
+ };
194
+ if (!context.targetingKey) {
195
+ context.targetingKey = this.getTargetingKey(context);
196
+ }
197
+ if (this._publicApiKey) {
198
+ fetchOptions.headers["x-api-key"] = this._publicApiKey;
199
+ } else {
200
+ throw new Error("You must set the publicApiKey");
201
+ }
202
+ if (context.application === "") {
203
+ throw new Error("You must set the applicationId");
204
+ }
205
+ const result = await this.fetch("/toggle/evaluate", context, fetchOptions);
206
+ if (result == null ? void 0 : result.toggles) {
207
+ return result.toggles[toggleKey].value;
208
+ }
209
+ } catch (error) {
210
+ this.emit(ToggleEvents.Error, error);
211
+ }
212
+ return defaultValue;
213
+ }
214
+ /**
215
+ * Retrieves a boolean toggle value.
216
+ *
217
+ * This is a convenience method that wraps the generic get() method with boolean type safety.
218
+ *
219
+ * @param toggleKey - The key of the toggle to retrieve
220
+ * @param defaultValue - The boolean value to return if the toggle is not found or an error occurs
221
+ * @param options - Optional configuration including context for toggle evaluation
222
+ * @returns Promise resolving to the boolean toggle value or defaultValue
223
+ *
224
+ * @example
225
+ * ```typescript
226
+ * const toggle = new Toggle({ publicApiKey: 'public_key', applicationId: 'app-id' });
227
+ * const isFeatureEnabled = await toggle.getBoolean('feature-flag', false);
228
+ * console.log(isFeatureEnabled); // true or false
229
+ * ```
230
+ */
231
+ async getBoolean(toggleKey, defaultValue, options) {
232
+ return this.get(toggleKey, defaultValue, options);
233
+ }
234
+ /**
235
+ * Retrieves a string toggle value.
236
+ *
237
+ * This is a convenience method that wraps the generic get() method with string type safety.
238
+ *
239
+ * @param toggleKey - The key of the toggle to retrieve
240
+ * @param defaultValue - The string value to return if the toggle is not found or an error occurs
241
+ * @param options - Optional configuration including context for toggle evaluation
242
+ * @returns Promise resolving to the string toggle value or defaultValue
243
+ *
244
+ * @example
245
+ * ```typescript
246
+ * const toggle = new Toggle({ publicApiKey: 'public_key', applicationId: 'app-id' });
247
+ * const message = await toggle.getString('welcome-message', 'Hello World');
248
+ * console.log(message); // 'Welcome to our app!' or 'Hello World'
249
+ * ```
250
+ */
251
+ async getString(toggleKey, defaultValue, options) {
252
+ return this.get(toggleKey, defaultValue, options);
253
+ }
254
+ /**
255
+ * Retrieves an object toggle value.
256
+ *
257
+ * This is a convenience method that wraps the generic get() method with object type safety.
258
+ * Note that the toggle service may return JSON as a string, which should be parsed if needed.
259
+ *
260
+ * @template T - The expected object type
261
+ * @param toggleKey - The key of the toggle to retrieve
262
+ * @param defaultValue - The object value to return if the toggle is not found or an error occurs
263
+ * @param options - Optional configuration including context for toggle evaluation
264
+ * @returns Promise resolving to the object toggle value or defaultValue
265
+ *
266
+ * @example
267
+ * ```typescript
268
+ * const toggle = new Toggle({ publicApiKey: 'public_key', applicationId: 'app-id' });
269
+ * const config = await toggle.getObject('app-config', { theme: 'light' });
270
+ * console.log(config); // { theme: 'dark', features: ['a', 'b'] } or { theme: 'light' }
271
+ * ```
272
+ */
273
+ async getObject(toggleKey, defaultValue, options) {
274
+ return this.get(toggleKey, defaultValue, options);
275
+ }
276
+ /**
277
+ * Retrieves a number toggle value.
278
+ *
279
+ * This is a convenience method that wraps the generic get() method with number type safety.
280
+ *
281
+ * @param toggleKey - The key of the toggle to retrieve
282
+ * @param defaultValue - The number value to return if the toggle is not found or an error occurs
283
+ * @param options - Optional configuration including context for toggle evaluation
284
+ * @returns Promise resolving to the number toggle value or defaultValue
285
+ *
286
+ * @example
287
+ * ```typescript
288
+ * const toggle = new Toggle({ publicApiKey: 'public_key', applicationId: 'app-id' });
289
+ * const maxRetries = await toggle.getNumber('max-retries', 3);
290
+ * console.log(maxRetries); // 5 or 3
291
+ * ```
292
+ */
293
+ async getNumber(toggleKey, defaultValue, options) {
294
+ return this.get(toggleKey, defaultValue, options);
295
+ }
296
+ /**
297
+ * Makes an HTTP POST request to the specified URL with automatic authentication.
298
+ *
299
+ * This method uses browser-compatible fetch and automatically includes the
300
+ * public API key in the x-api-key header if available. It supports load
301
+ * balancing across multiple horizon URLs with fallback behavior.
302
+ *
303
+ * @template T - The expected response type
304
+ * @param path - The API path to request (e.g., '/api/toggles')
305
+ * @param payload - The JSON payload to send in the request body
306
+ * @param options - Optional fetch configuration
307
+ * @returns Promise resolving to the parsed JSON response
308
+ * @throws {Error} If no horizon URLs are configured or all requests fail
309
+ *
310
+ * @example
311
+ * ```typescript
312
+ * const toggle = new Toggle({
313
+ * publicApiKey: 'public_your-key-here',
314
+ * horizonUrls: ['https://api.hyphen.cloud']
315
+ * });
316
+ *
317
+ * interface ToggleResponse {
318
+ * enabled: boolean;
319
+ * value: string;
320
+ * }
321
+ *
322
+ * const result = await toggle.fetch<ToggleResponse>('/api/toggle/feature-flag', {
323
+ * context: { targetingKey: 'user-123' }
324
+ * });
325
+ * console.log(result.enabled); // true/false
326
+ * ```
327
+ */
328
+ async fetch(path, payload, options) {
329
+ if (this._horizonUrls.length === 0) {
330
+ throw new Error("No horizon URLs configured. Set horizonUrls or provide a valid publicApiKey.");
331
+ }
332
+ const headers = {
333
+ "Content-Type": "application/json"
334
+ };
335
+ if (options == null ? void 0 : options.headers) {
336
+ if (options.headers instanceof Headers) {
337
+ options.headers.forEach((value, key) => {
338
+ headers[key] = value;
339
+ });
340
+ } else if (Array.isArray(options.headers)) {
341
+ options.headers.forEach(([key, value]) => {
342
+ headers[key] = value;
343
+ });
344
+ } else {
345
+ Object.assign(headers, options.headers);
346
+ }
347
+ }
348
+ if (this._publicApiKey) {
349
+ headers["x-api-key"] = this._publicApiKey;
350
+ }
351
+ const fetchOptions = {
352
+ method: "POST",
353
+ ...options,
354
+ headers,
355
+ body: payload ? JSON.stringify(payload) : options == null ? void 0 : options.body
356
+ };
357
+ const errors = [];
358
+ for (const baseUrl of this._horizonUrls) {
359
+ try {
360
+ const url = `${baseUrl.replace(/\/$/, "")}${path.startsWith("/") ? path : `/${path}`}`;
361
+ const response = await fetch(url, fetchOptions);
362
+ if (!response.ok) {
363
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
364
+ }
365
+ const data = await response.json();
366
+ return data;
367
+ } catch (error) {
368
+ const fetchError = error instanceof Error ? error : new Error("Unknown fetch error");
369
+ errors.push(fetchError);
370
+ }
371
+ }
372
+ throw new Error(`All horizon URLs failed. Last errors: ${errors.map((e) => e.message).join(", ")}`);
373
+ }
374
+ /**
375
+ * Validates and sets the public API key. This is used internally
376
+ *
377
+ * @param key - The public API key string or undefined to clear
378
+ * @throws {Error} If the key doesn't start with "public_"
379
+ */
380
+ setPublicKey(key) {
381
+ if (key !== void 0 && !key.startsWith("public_")) {
382
+ throw new Error("Public API key must start with 'public_'");
383
+ }
384
+ this._publicApiKey = key;
385
+ }
386
+ /**
387
+ * Extracts the organization ID from a public API key.
388
+ *
389
+ * The public key format is: `public_<base64-encoded-data>`
390
+ * The base64 data contains: `orgId:secretData`
391
+ * Only alphanumeric characters, underscores, and hyphens are considered valid in org IDs.
392
+ *
393
+ * @param publicKey - The public API key to extract the organization ID from
394
+ * @returns The organization ID if valid and extractable, undefined otherwise
395
+ *
396
+ * @example
397
+ * ```typescript
398
+ * const toggle = new Toggle();
399
+ * const orgId = toggle.getOrgIdFromPublicKey('public_dGVzdC1vcmc6c2VjcmV0');
400
+ * console.log(orgId); // 'test-org'
401
+ * ```
402
+ */
403
+ getOrgIdFromPublicKey(publicKey) {
404
+ try {
405
+ const keyWithoutPrefix = publicKey.replace(/^public_/, "");
406
+ const decoded = globalThis.atob ? globalThis.atob(keyWithoutPrefix) : Buffer.from(keyWithoutPrefix, "base64").toString();
407
+ const [orgId] = decoded.split(":");
408
+ const isValidOrgId = /^[a-zA-Z0-9_-]+$/.test(orgId);
409
+ return isValidOrgId ? orgId : void 0;
410
+ } catch (e) {
411
+ return void 0;
412
+ }
413
+ }
414
+ /**
415
+ * Builds the default Horizon API URL for the given public key.
416
+ *
417
+ * If a valid organization ID can be extracted from the public key, returns an
418
+ * organization-specific URL. Otherwise, returns the default fallback URL.
419
+ *
420
+ * @param publicKey - The public API key to build the URL for
421
+ * @returns Organization-specific URL or default fallback URL
422
+ *
423
+ * @example
424
+ * ```typescript
425
+ * const toggle = new Toggle();
426
+ *
427
+ * // With valid org ID
428
+ * const orgUrl = toggle.buildDefaultHorizonUrl('public_dGVzdC1vcmc6c2VjcmV0');
429
+ * console.log(orgUrl); // 'https://test-org.toggle.hyphen.cloud'
430
+ *
431
+ * // With invalid key
432
+ * const defaultUrl = toggle.buildDefaultHorizonUrl('invalid-key');
433
+ * console.log(defaultUrl); // 'https://toggle.hyphen.cloud'
434
+ * ```
435
+ */
436
+ getDefaultHorizonUrl(publicKey) {
437
+ if (publicKey) {
438
+ const orgId = this.getOrgIdFromPublicKey(publicKey);
439
+ return orgId ? `https://${orgId}.toggle.hyphen.cloud` : "https://toggle.hyphen.cloud";
440
+ }
441
+ return "https://toggle.hyphen.cloud";
442
+ }
443
+ /**
444
+ * Will get the urls. If you pass in the public key it will provide two urls.
445
+ * @param publicKey
446
+ * @returns
447
+ */
448
+ getDefaultHorizonUrls(publicKey) {
449
+ let result = [
450
+ this.getDefaultHorizonUrl()
451
+ ];
452
+ if (publicKey) {
453
+ const defaultUrl = result[0];
454
+ const orgUrl = this.getDefaultHorizonUrl(publicKey);
455
+ result = [];
456
+ if (orgUrl !== defaultUrl) {
457
+ result.push(orgUrl);
458
+ }
459
+ result.push(defaultUrl);
460
+ }
461
+ return result;
462
+ }
463
+ /**
464
+ * Generates a unique targeting key based on available context.
465
+ *
466
+ * @returns A targeting key in the format: `[app]-[env]-[random]` or simplified versions
467
+ */
468
+ generateTargetKey() {
469
+ const randomSuffix = Math.random().toString(36).substring(7);
470
+ const app = this._applicationId || "";
471
+ const env = this._environment || "";
472
+ const components = [
473
+ app,
474
+ env,
475
+ randomSuffix
476
+ ].filter(Boolean);
477
+ return components.join("-");
478
+ }
479
+ /**
480
+ * Extracts targeting key from a toggle context with fallback logic.
481
+ *
482
+ * @param context - The toggle context to extract targeting key from
483
+ * @returns The targeting key string
484
+ */
485
+ getTargetingKey(context) {
486
+ if (context.targetingKey) {
487
+ return context.targetingKey;
488
+ }
489
+ if (context.user) {
490
+ return context.user.id;
491
+ }
492
+ return this._defaultTargetingKey;
493
+ }
494
+ };
495
+ __name(_Toggle, "Toggle");
496
+ var Toggle = _Toggle;
3
497
 
4
498
  // src/toggle-provider.tsx
5
499
  import {
@@ -7,7 +501,6 @@ import {
7
501
  useMemo,
8
502
  useEffect
9
503
  } from "react";
10
- import { Toggle } from "@hyphen/browser-sdk";
11
504
  import { jsx } from "react/jsx-runtime";
12
505
  var ToggleContext = createContext(null);
13
506
  function ToggleProvider({
@@ -68,7 +561,7 @@ function withToggleProvider(options) {
68
561
  };
69
562
  }
70
563
  export {
71
- Toggle2 as Toggle,
564
+ Toggle,
72
565
  ToggleContext,
73
566
  ToggleProvider,
74
567
  useToggle,
package/package.json CHANGED
@@ -1,13 +1,15 @@
1
1
  {
2
2
  "name": "@hyphen/react-sdk",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Hyphen SDK for React",
5
5
  "type": "module",
6
+ "main": "dist/index.js",
6
7
  "module": "dist/index.js",
7
8
  "exports": {
8
9
  ".": {
10
+ "types": "./dist/index.d.ts",
9
11
  "import": "./dist/index.js",
10
- "types": "./dist/index.d.ts"
12
+ "require": "./dist/index.cjs"
11
13
  }
12
14
  },
13
15
  "types": "dist/index.d.ts",
@@ -22,30 +24,30 @@
22
24
  "author": "Team Hyphen <hello@hyphen.ai>",
23
25
  "license": "MIT",
24
26
  "devDependencies": {
25
- "@biomejs/biome": "2.3.10",
26
- "@faker-js/faker": "10.1.0",
27
- "@swc/core": "1.15.7",
27
+ "@biomejs/biome": "2.3.11",
28
+ "@faker-js/faker": "10.2.0",
29
+ "@swc/core": "1.15.8",
28
30
  "@testing-library/react": "16.3.1",
29
- "@types/node": "25.0.3",
30
- "@types/react": "19.2.7",
31
- "@vitest/coverage-v8": "4.0.16",
31
+ "@types/node": "25.0.9",
32
+ "@types/react": "19.2.8",
33
+ "@vitest/coverage-v8": "4.0.17",
32
34
  "dotenv": "17.2.3",
33
- "happy-dom": "20.0.11",
35
+ "happy-dom": "20.3.1",
34
36
  "react": "19.2.3",
35
37
  "react-dom": "19.2.3",
36
38
  "rimraf": "6.1.2",
37
39
  "tsd": "0.33.0",
38
40
  "tsup": "8.5.1",
39
41
  "typescript": "5.9.3",
40
- "vitest": "4.0.16"
42
+ "vitest": "4.0.17"
41
43
  },
42
44
  "files": [
43
45
  "dist",
44
46
  "LICENSE"
45
47
  ],
46
48
  "dependencies": {
47
- "@hyphen/browser-sdk": "1.0.5",
48
- "hookified": "1.14.0"
49
+ "@hyphen/browser-sdk": "1.0.6",
50
+ "hookified": "1.15.0"
49
51
  },
50
52
  "peerDependencies": {
51
53
  "react": "^18.0.0 || ^19.0.0"