tempest-react-sdk 0.1.3 → 0.1.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/README.md CHANGED
@@ -168,8 +168,8 @@ Every module is re-exported from the package root — `import { Button, useDebou
168
168
  | `theme` | `ThemeProvider`, `useTheme`, `getInitialTheme`, `themeInitScript`, types: `ThemeMode`, `ResolvedTheme` |
169
169
  | `i18n` | `createI18n`, `I18nProvider`, `useI18n`, `useTranslate`, types: `Catalog`, `Messages`, `I18n`, `InterpolationValues` |
170
170
  | `logger` | `createLogger`, `consoleSink`, types: `Logger`, `LogEntry`, `LogLevel`, `LoggerSink` |
171
- | `telemetry` | `TelemetryProvider`, `useTelemetry`, `consoleTelemetryAdapter`, `createSentryTelemetryAdapter`, types: `TelemetryAdapter`, `TelemetryEvent`, `TelemetryUser`, `CreateSentryTelemetryAdapterOptions`, `SentryLike` |
172
- | `feature-flags` | `FeatureFlagsProvider`, `useFeatureFlag`, `useFlagValue`, `createInMemoryFlags`, types: `FeatureFlagsAdapter`, `FlagValue` |
171
+ | `telemetry` | `TelemetryProvider`, `useTelemetry`, `consoleTelemetryAdapter`, `createSentryTelemetryAdapter`, `createPostHogTelemetryAdapter`, types: `TelemetryAdapter`, `TelemetryEvent`, `TelemetryUser`, `CreateSentryTelemetryAdapterOptions`, `SentryLike`, `CreatePostHogTelemetryAdapterOptions`, `PostHogLike` |
172
+ | `feature-flags` | `FeatureFlagsProvider`, `useFeatureFlag`, `useFlagValue`, `createInMemoryFlags`, `createGrowthBookFeatureFlagsAdapter`, `createLaunchDarklyFeatureFlagsAdapter`, types: `FeatureFlagsAdapter`, `FlagValue`, `GrowthBookLike`, `LDClientLike` |
173
173
  | `share` | `share`, `isShareSupported`, types: `SharePayload`, `ShareResult` |
174
174
  | `utils` | `cn`, `formatCurrency`, `formatDate`, `formatDateTime`, `formatPhone`, `formatCPF`, `formatPercent`, `storage` |
175
175
 
@@ -1241,7 +1241,7 @@ function Header() {
1241
1241
 
1242
1242
  ### Feature flags recipe
1243
1243
 
1244
- `FeatureFlagsProvider` takes an `adapter` matching the `FeatureFlagsAdapter` interface (`isEnabled`, `get`, `subscribe`). Ship the `InMemory` adapter while you build, swap for GrowthBook / LaunchDarkly when you're ready.
1244
+ `FeatureFlagsProvider` takes an `adapter` matching the `FeatureFlagsAdapter` interface (`isEnabled`, `get`, `onChange?`). Ship the `InMemory` adapter while you build, swap for GrowthBook / LaunchDarkly when you're ready.
1245
1245
 
1246
1246
  ```tsx
1247
1247
  import {
@@ -1252,7 +1252,7 @@ import {
1252
1252
  } from "tempest-react-sdk";
1253
1253
 
1254
1254
  const flags = createInMemoryFlags({
1255
- flags: { "new-checkout": true, "max-items": 10 },
1255
+ initial: { "new-checkout": true, "max-items": 10 },
1256
1256
  });
1257
1257
 
1258
1258
  <FeatureFlagsProvider adapter={flags}>
@@ -1266,7 +1266,52 @@ function CheckoutButton() {
1266
1266
  }
1267
1267
  ```
1268
1268
 
1269
- The interface is intentionally tiny any third-party SDK can be wrapped into an adapter in ~20 lines.
1269
+ **GrowthBook adapter** wraps a `GrowthBook` instance. The app initialises GrowthBook (so it controls `apiHost`, `clientKey`, attributes, `loadFeatures()`), the adapter only routes lookups.
1270
+
1271
+ ```ts
1272
+ import { GrowthBook } from "@growthbook/growthbook";
1273
+ import { FeatureFlagsProvider, createGrowthBookFeatureFlagsAdapter } from "tempest-react-sdk";
1274
+
1275
+ const gb = new GrowthBook({
1276
+ apiHost: import.meta.env.VITE_GROWTHBOOK_API_HOST,
1277
+ clientKey: import.meta.env.VITE_GROWTHBOOK_KEY,
1278
+ attributes: { id: userId },
1279
+ });
1280
+ await gb.loadFeatures();
1281
+
1282
+ const adapter = createGrowthBookFeatureFlagsAdapter({ growthbook: gb });
1283
+
1284
+ <FeatureFlagsProvider adapter={adapter}>
1285
+ <App />
1286
+ </FeatureFlagsProvider>;
1287
+ ```
1288
+
1289
+ Mapping: `isEnabled(key)` → `growthbook.isOn(key)`; `get(key, default)` → `growthbook.getFeatureValue(key, default)`; `onChange(listener)` → `growthbook.setRenderer(...)` (installed lazily on first subscription, multiplexes to all listeners).
1290
+
1291
+ **LaunchDarkly adapter** — wraps `launchdarkly-js-client-sdk`.
1292
+
1293
+ ```ts
1294
+ import * as LDClient from "launchdarkly-js-client-sdk";
1295
+ import { FeatureFlagsProvider, createLaunchDarklyFeatureFlagsAdapter } from "tempest-react-sdk";
1296
+
1297
+ const client = LDClient.initialize(import.meta.env.VITE_LD_CLIENT_ID, {
1298
+ kind: "user",
1299
+ key: userId,
1300
+ });
1301
+ await client.waitUntilReady();
1302
+
1303
+ const adapter = createLaunchDarklyFeatureFlagsAdapter({ client });
1304
+
1305
+ <FeatureFlagsProvider adapter={adapter}>
1306
+ <App />
1307
+ </FeatureFlagsProvider>;
1308
+ ```
1309
+
1310
+ Mapping: `isEnabled(key)` → `client.variation(key, default) === true`; `get(key, default)` → `client.variation(key, default)`; `onChange(listener)` → `client.on("change", listener)` + `client.off` on unsubscribe.
1311
+
1312
+ Neither `@growthbook/growthbook` nor `launchdarkly-js-client-sdk` is declared as a peer dep — the adapter only touches the instance you hand it. Install whichever you opt into: `npm install @growthbook/growthbook` or `npm install launchdarkly-js-client-sdk`.
1313
+
1314
+ The `FeatureFlagsAdapter` interface is intentionally tiny — any third-party SDK can be wrapped into an adapter in ~20 lines.
1270
1315
 
1271
1316
  ### Telemetry recipe
1272
1317
 
@@ -1329,7 +1374,38 @@ Mapping:
1329
1374
 
1330
1375
  `@sentry/browser` is **not** declared as a peer dep — the adapter only ever touches the namespace you hand it, so apps that don't use Sentry never pay for it. Install Sentry yourself when you opt in: `npm install @sentry/browser`.
1331
1376
 
1332
- Concrete adapters for PostHog / Datadog / GrowthBook are part of the v0.2 roadmap for now you can write one in ~20 lines following the Sentry adapter as a template.
1377
+ **PostHog adapter**wraps `posthog-js`.
1378
+
1379
+ ```ts
1380
+ import posthog from "posthog-js";
1381
+ import { createPostHogTelemetryAdapter, TelemetryProvider } from "tempest-react-sdk";
1382
+
1383
+ const adapter = createPostHogTelemetryAdapter({
1384
+ posthog,
1385
+ init: {
1386
+ apiKey: import.meta.env.VITE_POSTHOG_KEY,
1387
+ options: { api_host: "https://us.i.posthog.com" },
1388
+ },
1389
+ });
1390
+
1391
+ <TelemetryProvider adapter={adapter}>
1392
+ <App />
1393
+ </TelemetryProvider>;
1394
+ ```
1395
+
1396
+ Mapping:
1397
+
1398
+ | `TelemetryAdapter` call | `posthog-js` API |
1399
+ | ----------------------------- | ------------------------------------------------------------------------------------------------ |
1400
+ | `init()` | `posthog.init(apiKey, options)` (only when `init` is provided) |
1401
+ | `identify({id, ...})` | `posthog.identify(id, { email, name, ...traits })` |
1402
+ | `identify(null)` | `posthog.reset()` |
1403
+ | `track({ name, properties })` | `posthog.capture(name, properties)` |
1404
+ | `captureException(err, ctx)` | `posthog.captureException(err, ctx)` when available, else `posthog.capture("$exception", { … })` |
1405
+
1406
+ `posthog-js` is **not** declared as a peer dep — install only when you opt in: `npm install posthog-js`.
1407
+
1408
+ Concrete adapters for Datadog / Amplitude / others are part of the v0.2 roadmap — for now you can write one in ~20 lines following the Sentry / PostHog adapters as templates.
1333
1409
 
1334
1410
  ### Logger recipe
1335
1411
 
package/dist/index.d.ts CHANGED
@@ -376,6 +376,33 @@ export declare interface CreateEventStreamOptions<T> {
376
376
  onStatusChange?: (status: EventStreamStatus) => void;
377
377
  }
378
378
 
379
+ /**
380
+ * Build a [[FeatureFlagsAdapter]] backed by a GrowthBook instance. Apps
381
+ * initialise GrowthBook themselves (so they can load features over the
382
+ * network, set attributes, etc.) — the adapter just routes lookups.
383
+ *
384
+ * Mapping:
385
+ * - `isEnabled(key, default)` → `growthbook.isOn(key)` (falls back to `default` if no value)
386
+ * - `get(key, default)` → `growthbook.getFeatureValue(key, default)`
387
+ * - `onChange(listener)` → `growthbook.setRenderer(listener)` (single-renderer SDK constraint)
388
+ *
389
+ * @example
390
+ * import { GrowthBook } from "@growthbook/growthbook";
391
+ * import { FeatureFlagsProvider, createGrowthBookFeatureFlagsAdapter } from "tempest-react-sdk";
392
+ *
393
+ * const gb = new GrowthBook({ apiHost: "...", clientKey: "..." });
394
+ * await gb.loadFeatures();
395
+ * const adapter = createGrowthBookFeatureFlagsAdapter({ growthbook: gb });
396
+ *
397
+ * <FeatureFlagsProvider adapter={adapter}><App /></FeatureFlagsProvider>;
398
+ */
399
+ export declare function createGrowthBookFeatureFlagsAdapter(options: CreateGrowthBookFeatureFlagsAdapterOptions): FeatureFlagsAdapter;
400
+
401
+ export declare interface CreateGrowthBookFeatureFlagsAdapterOptions {
402
+ /** The GrowthBook instance. Required. */
403
+ growthbook: GrowthBookLike;
404
+ }
405
+
379
406
  /**
380
407
  * Create an i18n object with translation, pluralization and Intl helpers.
381
408
  *
@@ -418,6 +445,33 @@ export declare function createInMemoryFlags(options?: InMemoryFlagsOptions): Fea
418
445
  set: (key: string, value: FlagValue) => void;
419
446
  };
420
447
 
448
+ /**
449
+ * Build a [[FeatureFlagsAdapter]] backed by a LaunchDarkly JS client. Apps
450
+ * initialise the client themselves (`LDClient.initialize(envKey, ctx)`) and
451
+ * pass it in.
452
+ *
453
+ * Mapping:
454
+ * - `isEnabled(key, default)` → `client.variation(key, default) === true`
455
+ * - `get(key, default)` → `client.variation(key, default)`
456
+ * - `onChange(listener)` → `client.on("change", listener)` / `client.off("change", listener)`
457
+ *
458
+ * @example
459
+ * import * as LDClient from "launchdarkly-js-client-sdk";
460
+ * import { FeatureFlagsProvider, createLaunchDarklyFeatureFlagsAdapter } from "tempest-react-sdk";
461
+ *
462
+ * const client = LDClient.initialize(import.meta.env.VITE_LD_CLIENT_ID, { kind: "user", key: userId });
463
+ * await client.waitUntilReady();
464
+ * const adapter = createLaunchDarklyFeatureFlagsAdapter({ client });
465
+ *
466
+ * <FeatureFlagsProvider adapter={adapter}><App /></FeatureFlagsProvider>;
467
+ */
468
+ export declare function createLaunchDarklyFeatureFlagsAdapter(options: CreateLaunchDarklyFeatureFlagsAdapterOptions): FeatureFlagsAdapter;
469
+
470
+ export declare interface CreateLaunchDarklyFeatureFlagsAdapterOptions {
471
+ /** The LaunchDarkly JS client. Required. */
472
+ client: LDClientLike;
473
+ }
474
+
421
475
  /**
422
476
  * Create a structured leveled logger. Plug arbitrary sinks (Sentry, Datadog,
423
477
  * remote ingestion) by implementing the `LoggerSink` interface.
@@ -455,6 +509,39 @@ export declare interface CreateLoggerOptions {
455
509
  */
456
510
  export declare function createOfflineStore<TItem, TKey extends string | number = string>(config: OfflineStoreConfig<TItem>): OfflineStore<TItem, TKey>;
457
511
 
512
+ /**
513
+ * Build a [[TelemetryAdapter]] backed by [`posthog-js`](https://posthog.com/docs/libraries/js).
514
+ * The PostHog client is supplied by the caller (not bundled).
515
+ *
516
+ * Mapping:
517
+ * - `identify(user)` → `posthog.identify(user.id, { email, name, ...traits })` (or `posthog.reset()` when `null`)
518
+ * - `track({ name, properties })` → `posthog.capture(name, properties)`
519
+ * - `captureException(err, ctx)` → `posthog.captureException(err, ctx)` when available, otherwise `posthog.capture("$exception", { …err, …ctx })`
520
+ * - `flush()` → no-op (PostHog batches automatically)
521
+ *
522
+ * @example
523
+ * import posthog from "posthog-js";
524
+ * import { createPostHogTelemetryAdapter, TelemetryProvider } from "tempest-react-sdk";
525
+ *
526
+ * const adapter = createPostHogTelemetryAdapter({
527
+ * posthog,
528
+ * init: { apiKey: import.meta.env.VITE_POSTHOG_KEY, options: { api_host: "https://us.i.posthog.com" } },
529
+ * });
530
+ *
531
+ * <TelemetryProvider adapter={adapter}><App /></TelemetryProvider>;
532
+ */
533
+ export declare function createPostHogTelemetryAdapter(options: CreatePostHogTelemetryAdapterOptions): TelemetryAdapter;
534
+
535
+ export declare interface CreatePostHogTelemetryAdapterOptions {
536
+ /** The PostHog JS client (the default export of `posthog-js`). Required. */
537
+ posthog: PostHogLike;
538
+ /** Project API key + options. When provided, `Provider.init` calls `posthog.init(apiKey, options)`. */
539
+ init?: {
540
+ apiKey: string;
541
+ options?: Record<string, unknown>;
542
+ };
543
+ }
544
+
458
545
  /**
459
546
  * Build a typed query-key factory for a domain. Each entry can be a static
460
547
  * tuple or a function returning a tuple. The returned object is `as const`
@@ -945,6 +1032,17 @@ export declare interface GridProps extends HTMLAttributes<HTMLDivElement> {
945
1032
  children?: ReactNode;
946
1033
  }
947
1034
 
1035
+ /**
1036
+ * Minimal subset of [`@growthbook/growthbook`](https://docs.growthbook.io/lib/js)
1037
+ * used by the adapter. Pass a `GrowthBook` instance directly.
1038
+ */
1039
+ export declare interface GrowthBookLike {
1040
+ isOn: (key: string) => boolean;
1041
+ getFeatureValue: <T>(key: string, defaultValue: T) => T;
1042
+ /** Registers a renderer fired whenever GrowthBook re-evaluates features. */
1043
+ setRenderer?: (renderer: () => void) => void;
1044
+ }
1045
+
948
1046
  export declare interface I18n {
949
1047
  /** Currently active locale. */
950
1048
  locale: string;
@@ -1116,6 +1214,16 @@ export declare interface LazyWithRetryOptions {
1116
1214
  reloadOnFinalFailure?: boolean;
1117
1215
  }
1118
1216
 
1217
+ /**
1218
+ * Minimal subset of [`launchdarkly-js-client-sdk`](https://docs.launchdarkly.com/sdk/client-side/javascript)
1219
+ * used by the adapter. Pass an existing `LDClient`.
1220
+ */
1221
+ export declare interface LDClientLike {
1222
+ variation: <T = unknown>(key: string, defaultValue: T) => T;
1223
+ on?: (event: string, handler: () => void) => void;
1224
+ off?: (event: string, handler: () => void) => void;
1225
+ }
1226
+
1119
1227
  export declare interface ListOptions<TItem> {
1120
1228
  /** Property to order by. Default: `keyPath`. */
1121
1229
  orderBy?: keyof TItem & string;
@@ -1298,6 +1406,19 @@ export declare interface PlayAudioOptions {
1298
1406
  onError?: (error: unknown) => void;
1299
1407
  }
1300
1408
 
1409
+ /**
1410
+ * Minimal subset of `posthog-js` used by the adapter. Pass either the real
1411
+ * default export (`import posthog from "posthog-js"`) or a stubbed object
1412
+ * in tests.
1413
+ */
1414
+ export declare interface PostHogLike {
1415
+ init?: (apiKey: string, options?: Record<string, unknown>) => void;
1416
+ identify: (distinctId: string, properties?: Record<string, unknown>) => void;
1417
+ capture: (eventName: string, properties?: Record<string, unknown>) => void;
1418
+ captureException?: (error: unknown, properties?: Record<string, unknown>) => void;
1419
+ reset?: () => void;
1420
+ }
1421
+
1301
1422
  /** Linear progress bar with determinate / indeterminate modes. */
1302
1423
  export declare function Progress({ value, max, variant, indeterminate, showLabel, label, className, }: ProgressProps): JSX.Element;
1303
1424