@traffical/react-native 0.8.3 → 0.9.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 CHANGED
@@ -29,7 +29,8 @@ function App() {
29
29
  orgId: 'org_123',
30
30
  projectId: 'proj_456',
31
31
  env: 'production',
32
- apiKey: 'pk_...',
32
+ apiKey: 'traffical_pk_…',
33
+ evaluationMode: 'bundle', // required with a publishable key — see below
33
34
  }}
34
35
  loadingComponent={<ActivityIndicator size="large" />}
35
36
  >
@@ -39,6 +40,20 @@ function App() {
39
40
  }
40
41
  ```
41
42
 
43
+ > **Publishable keys need `evaluationMode: 'bundle'`.**
44
+ >
45
+ > This package defaults to `evaluationMode: 'server'`, which calls `/v1/resolve`.
46
+ > That endpoint rejects publishable (`traffical_pk_…`) keys, so leaving the
47
+ > default in place with a `pk` returns `403` on every resolution.
48
+ >
49
+ > Set `evaluationMode: 'bundle'` and the SDK fetches the config bundle once and
50
+ > resolves on-device — no per-decision network call, works offline, and it is the
51
+ > mode we recommend for mobile regardless of key type.
52
+ >
53
+ > If you specifically need server-evaluated mode, it requires a server-side SDK
54
+ > key (`traffical_sk_…`), which must not ship in a mobile binary. In practice that
55
+ > means proxying resolution through your own backend.
56
+
42
57
  ### 2. Use the `useTraffical` hook in your screens
43
58
 
44
59
  ```tsx
@@ -98,11 +113,11 @@ Initializes the Traffical client with React Native defaults and provides it to c
98
113
  | `config.env` | `string` | Yes | Environment (e.g., "production", "staging") |
99
114
  | `config.apiKey` | `string` | Yes | API key for authentication |
100
115
  | `config.baseUrl` | `string` | No | Base URL for the control plane API |
101
- | `config.evaluationMode` | `"server" \| "bundle"` | No | Resolution mode (default: `"server"`) |
116
+ | `config.evaluationMode` | `"server" \| "bundle"` | No | Resolution mode (default: `"server"`). Use `"bundle"` with a publishable key — `"server"` calls `/v1/resolve`, which rejects `traffical_pk_…` keys |
102
117
  | `config.refreshIntervalMs` | `number` | No | Background refresh interval (default: 60000) |
103
118
  | `config.unitKeyFn` | `() => string` | No | Function to get the unit key. If not provided, uses automatic stable ID |
104
119
  | `config.contextFn` | `() => Context` | No | Function to get additional context |
105
- | `config.deviceInfoProvider` | `DeviceInfoProvider` | No | Provider for device metadata (OS, model, etc.) |
120
+ | `config.deviceInfoProvider` | `DeviceInfoProvider` | No | Provider for device metadata. Pass the built-in `defaultDeviceInfoProvider` (see below) or your own |
106
121
  | `config.cacheMaxAgeMs` | `number` | No | Cache TTL for persisted responses (default: 24 hours) |
107
122
  | `config.trackDecisions` | `boolean` | No | Whether to track decision events (default: true) |
108
123
  | `config.decisionDeduplicationTtlMs` | `number` | No | Decision dedup TTL (default: 1 hour) |
@@ -116,6 +131,36 @@ Initializes the Traffical client with React Native defaults and provides it to c
116
131
 
117
132
  ---
118
133
 
134
+ #### Device attributes
135
+
136
+ `defaultDeviceInfoProvider` derives device metadata from `Platform`, `Dimensions` and `Intl` only (no native modules) and is **opt-in** — nothing is added to your context unless you pass it:
137
+
138
+ ```tsx
139
+ import { TrafficalRNProvider, defaultDeviceInfoProvider } from '@traffical/react-native';
140
+
141
+ <TrafficalRNProvider config={{ …, deviceInfoProvider: defaultDeviceInfoProvider }}>
142
+ ```
143
+
144
+ It emits the canonical `$`-prefixed system attributes shared by every Traffical SDK — registered as system attributes in the dashboard — plus the un-prefixed fields for compatibility with existing conditions:
145
+
146
+ | Key | Type | Value |
147
+ |-----|------|-------|
148
+ | `$os` | enum | `ios`, `android`, `macos`, `windows`, `other` (from `Platform.OS`) |
149
+ | `$os_version` | string | `Platform.Version` as a string |
150
+ | `$device_type` | enum | iOS: `Platform.isPad` → `tablet` else `mobile`; Android: shortest side ≥ 600dp → `tablet`; other platforms: width `< 768` mobile, `< 1024` tablet, else `desktop` |
151
+ | `$device_model` | string | Android only (`Platform.constants.Model`); iOS exposes no model without a native module |
152
+ | `$locale`, `$timezone` | string | `Intl.DateTimeFormat().resolvedOptions()` |
153
+ | `$app_version` | string | Only when supplied — RN has no app version without a native module |
154
+ | `osName`, `osVersion`, `locale`, `timezone`, `screenWidth`, `screenHeight`, `pixelRatio`, `deviceModel`, `appVersion`, `appBuildNumber` | | Compatibility fields, same values |
155
+
156
+ To populate `$app_version`, build the provider with the version from your own source (`expo-constants`, `react-native-device-info`, a generated constant):
157
+
158
+ ```tsx
159
+ import { createDefaultDeviceInfoProvider } from '@traffical/react-native';
160
+
161
+ const deviceInfoProvider = createDefaultDeviceInfoProvider({ appVersion: '2.3.1', appBuildNumber: '451' });
162
+ ```
163
+
119
164
  ### useTraffical
120
165
 
121
166
  Primary hook for parameter resolution and decision tracking. Identical API to `@traffical/react`.
@@ -398,10 +443,10 @@ function PaywallScreen() {
398
443
 
399
444
  ### 1. Always Provide Sensible Defaults
400
445
 
401
- Defaults are used when no experiment is running, the user doesn't match targeting, or the SDK is still loading.
446
+ Defaults are used when no policy is running, the user doesn't match targeting, or the SDK is still loading.
402
447
 
403
448
  ```tsx
404
- // ✅ Good: works without any experiment
449
+ // ✅ Good: works without any policy
405
450
  const { params } = useTraffical({
406
451
  defaults: {
407
452
  'pricing.discount': 0,
@@ -448,7 +493,7 @@ category.subcategory.name
448
493
 
449
494
  feature.* → Feature flags (boolean)
450
495
  ui.* → Visual variations (string, number)
451
- pricing.* → Pricing experiments (number)
496
+ pricing.* → Pricing policies (number)
452
497
  copy.* → Copywriting tests (string)
453
498
  onboarding.* → Onboarding flow (mixed)
454
499
  ```
@@ -1,3 +1,30 @@
1
+ /** The subset of react-native's `Platform` the default provider reads. */
2
+ export interface PlatformLike {
3
+ OS: string;
4
+ Version?: string | number;
5
+ isPad?: boolean;
6
+ constants?: Record<string, unknown>;
7
+ }
8
+ /** The subset of react-native's `Dimensions` the default provider reads. */
9
+ export interface DimensionsLike {
10
+ get(which: "window" | "screen"): {
11
+ width: number;
12
+ height: number;
13
+ scale?: number;
14
+ };
15
+ }
16
+ /**
17
+ * Device metadata merged into every decision context by `TrafficalRNProvider`
18
+ * when a `deviceInfoProvider` is configured.
19
+ *
20
+ * Two key families:
21
+ * - The canonical `$`-prefixed system attributes shared by every Traffical SDK
22
+ * (`$os`, `$os_version`, `$app_version`, `$locale`, `$timezone`,
23
+ * `$device_model`, `$device_type`). The dashboard registers them as system
24
+ * attributes; use these in new conditions.
25
+ * - The original un-prefixed fields, kept for compatibility with existing
26
+ * conditions.
27
+ */
1
28
  export interface DeviceInfo {
2
29
  appVersion?: string;
3
30
  appBuildNumber?: string;
@@ -10,8 +37,46 @@ export interface DeviceInfo {
10
37
  screenWidth?: number;
11
38
  screenHeight?: number;
12
39
  pixelRatio?: number;
40
+ $os?: "ios" | "android" | "macos" | "windows" | "linux" | "other";
41
+ $os_version?: string;
42
+ $app_version?: string;
43
+ $locale?: string;
44
+ $timezone?: string;
45
+ $device_model?: string;
46
+ $device_type?: "mobile" | "tablet" | "desktop";
13
47
  }
14
48
  export interface DeviceInfoProvider {
15
49
  getDeviceInfo(): DeviceInfo;
16
50
  }
51
+ export interface DefaultDeviceInfoOptions {
52
+ /**
53
+ * App version (semver). React Native exposes no app version without a native
54
+ * module, so pass it from your build config (e.g. `expo-constants`,
55
+ * `react-native-device-info`, or a generated constant) to populate
56
+ * `$app_version` / `appVersion`.
57
+ */
58
+ appVersion?: string;
59
+ /** App build number, same caveat as `appVersion`. */
60
+ appBuildNumber?: string;
61
+ /** Override react-native's `Platform` (tests, custom hosts). */
62
+ platform?: PlatformLike;
63
+ /** Override react-native's `Dimensions` (tests, custom hosts). */
64
+ dimensions?: DimensionsLike;
65
+ }
66
+ /**
67
+ * Builds a `DeviceInfoProvider` from `Platform`, `Dimensions` and `Intl` only
68
+ * (no native modules). Emits the `$`-prefixed system attributes plus the
69
+ * un-prefixed compatibility fields. Values are re-read on every call, so
70
+ * rotation and locale changes are picked up on the next decision.
71
+ *
72
+ * Opt in explicitly — the provider is not wired by default so existing apps
73
+ * see no change in the context they send:
74
+ *
75
+ * ```tsx
76
+ * <TrafficalRNProvider config={{ …, deviceInfoProvider: defaultDeviceInfoProvider }}>
77
+ * ```
78
+ */
79
+ export declare function createDefaultDeviceInfoProvider(options?: DefaultDeviceInfoOptions): DeviceInfoProvider;
80
+ /** Ready-made provider with no app version; see `createDefaultDeviceInfoProvider`. */
81
+ export declare const defaultDeviceInfoProvider: DeviceInfoProvider;
17
82
  //# sourceMappingURL=device-info.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"device-info.d.ts","sourceRoot":"","sources":["../src/device-info.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,aAAa,IAAI,UAAU,CAAC;CAC7B"}
1
+ {"version":3,"file":"device-info.d.ts","sourceRoot":"","sources":["../src/device-info.ts"],"names":[],"mappings":"AAKA,0EAA0E;AAC1E,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAED,4EAA4E;AAC5E,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,QAAQ,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACpF;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,UAAU;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,GAAG,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;CAChD;AAED,MAAM,WAAW,kBAAkB;IACjC,aAAa,IAAI,UAAU,CAAC;CAC7B;AAED,MAAM,WAAW,wBAAwB;IACvC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,kEAAkE;IAClE,UAAU,CAAC,EAAE,cAAc,CAAC;CAC7B;AAyCD;;;;;;;;;;;;GAYG;AACH,wBAAgB,+BAA+B,CAAC,OAAO,GAAE,wBAA6B,GAAG,kBAAkB,CA8D1G;AAED,sFAAsF;AACtF,eAAO,MAAM,yBAAyB,EAAE,kBAAsD,CAAC"}
@@ -1,2 +1,112 @@
1
- export {};
1
+ // Namespace import with lazy property access: react-native's entry is a
2
+ // CommonJS module with getter-based exports, and bun's static named-export
3
+ // detection does not see every member (CI failed on `Dimensions` with RN 0.84).
4
+ import * as RN from "react-native";
5
+ function mapOS(os) {
6
+ switch (os) {
7
+ case "ios":
8
+ case "android":
9
+ case "macos":
10
+ case "windows":
11
+ return os;
12
+ default:
13
+ return "other";
14
+ }
15
+ }
16
+ function deviceType(platform, os, width, height) {
17
+ if (os === "ios") {
18
+ // `Platform.isPad` is only defined on iOS builds of RN.
19
+ return platform.isPad === true ? "tablet" : "mobile";
20
+ }
21
+ if (os === "android") {
22
+ // Android convention: a 600dp shortest side is the phone/tablet boundary.
23
+ return Math.min(width, height) >= 600 ? "tablet" : "mobile";
24
+ }
25
+ // Desktop-class platforms (web, windows, macos): same width heuristic as the
26
+ // web plugin (mobile < 768, tablet < 1024, else desktop).
27
+ if (width < 768)
28
+ return "mobile";
29
+ if (width < 1024)
30
+ return "tablet";
31
+ return "desktop";
32
+ }
33
+ function androidModel(platform) {
34
+ const constants = platform.constants;
35
+ const model = constants?.Model;
36
+ return typeof model === "string" && model ? model : undefined;
37
+ }
38
+ /**
39
+ * Builds a `DeviceInfoProvider` from `Platform`, `Dimensions` and `Intl` only
40
+ * (no native modules). Emits the `$`-prefixed system attributes plus the
41
+ * un-prefixed compatibility fields. Values are re-read on every call, so
42
+ * rotation and locale changes are picked up on the next decision.
43
+ *
44
+ * Opt in explicitly — the provider is not wired by default so existing apps
45
+ * see no change in the context they send:
46
+ *
47
+ * ```tsx
48
+ * <TrafficalRNProvider config={{ …, deviceInfoProvider: defaultDeviceInfoProvider }}>
49
+ * ```
50
+ */
51
+ export function createDefaultDeviceInfoProvider(options = {}) {
52
+ // Resolved per call so a host that installs/mocks react-native late still wins.
53
+ const Platform = () => options.platform ?? RN.Platform;
54
+ const Dimensions = () => options.dimensions ?? RN.Dimensions;
55
+ return {
56
+ getDeviceInfo() {
57
+ const info = {};
58
+ const os = String(Platform().OS);
59
+ info.osName = os;
60
+ info.$os = mapOS(os);
61
+ const version = Platform().Version;
62
+ if (version !== undefined && version !== null) {
63
+ const v = String(version);
64
+ info.osVersion = v;
65
+ info.$os_version = v;
66
+ }
67
+ if (options.appVersion) {
68
+ info.appVersion = options.appVersion;
69
+ info.$app_version = options.appVersion;
70
+ }
71
+ if (options.appBuildNumber)
72
+ info.appBuildNumber = options.appBuildNumber;
73
+ let width = 0;
74
+ let height = 0;
75
+ try {
76
+ const win = Dimensions().get("window");
77
+ width = win.width;
78
+ height = win.height;
79
+ info.screenWidth = width;
80
+ info.screenHeight = height;
81
+ info.pixelRatio = win.scale;
82
+ }
83
+ catch {
84
+ // Dimensions unavailable (headless / test)
85
+ }
86
+ info.$device_type = deviceType(Platform(), os, width, height);
87
+ const model = os === "android" ? androidModel(Platform()) : undefined;
88
+ if (model) {
89
+ info.deviceModel = model;
90
+ info.$device_model = model;
91
+ }
92
+ try {
93
+ const resolved = Intl.DateTimeFormat().resolvedOptions();
94
+ if (resolved.locale) {
95
+ info.locale = resolved.locale;
96
+ info.$locale = resolved.locale;
97
+ }
98
+ if (resolved.timeZone) {
99
+ info.timezone = resolved.timeZone;
100
+ info.$timezone = resolved.timeZone;
101
+ }
102
+ }
103
+ catch {
104
+ // Intl not available on this JS engine
105
+ }
106
+ return info;
107
+ },
108
+ };
109
+ }
110
+ /** Ready-made provider with no app version; see `createDefaultDeviceInfoProvider`. */
111
+ export const defaultDeviceInfoProvider = createDefaultDeviceInfoProvider();
2
112
  //# sourceMappingURL=device-info.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"device-info.js","sourceRoot":"","sources":["../src/device-info.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"device-info.js","sourceRoot":"","sources":["../src/device-info.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ export { TrafficalClient, type TrafficalClientOptions, type LifecycleProvider, t
3
3
  export { TrafficalRNClient, type TrafficalRNClientOptions, } from "./client.js";
4
4
  export { createPreloadedAsyncStorage, type PreloadedAsyncStorageProvider, } from "./storage.js";
5
5
  export { createRNLifecycleProvider } from "./lifecycle.js";
6
- export { type DeviceInfo, type DeviceInfoProvider } from "./device-info.js";
6
+ export { type DeviceInfo, type DeviceInfoProvider, type DefaultDeviceInfoOptions, createDefaultDeviceInfoProvider, defaultDeviceInfoProvider, } from "./device-info.js";
7
7
  export { TrafficalRNProvider, type TrafficalRNProviderProps, } from "./provider.js";
8
8
  export { TrafficalContext, useTrafficalContext, type TrafficalRNProviderConfig, type TrafficalContextValue, } from "./context.js";
9
9
  export { useTraffical, type UseTrafficalOptions, type UseTrafficalResult, useTrafficalTrack, useTrafficalPlugin, useTrafficalClient, } from "./hooks.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,iBAAiB,CAAC;AAGhC,OAAO,EACL,eAAe,EACf,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,qBAAqB,EACrB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,aAAa,EACb,KAAK,oBAAoB,EACzB,iCAAiC,EACjC,2BAA2B,EAC3B,KAAK,4BAA4B,GAClC,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,iBAAiB,EACjB,KAAK,wBAAwB,GAC9B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,2BAA2B,EAC3B,KAAK,6BAA6B,GACnC,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAG5E,OAAO,EACL,mBAAmB,EACnB,KAAK,wBAAwB,GAC9B,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,KAAK,yBAAyB,EAC9B,KAAK,qBAAqB,GAC3B,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,YAAY,EACZ,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,iBAAiB,CAAC;AAGhC,OAAO,EACL,eAAe,EACf,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,qBAAqB,EACrB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,aAAa,EACb,KAAK,oBAAoB,EACzB,iCAAiC,EACjC,2BAA2B,EAC3B,KAAK,4BAA4B,GAClC,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,iBAAiB,EACjB,KAAK,wBAAwB,GAC9B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,2BAA2B,EAC3B,KAAK,6BAA6B,GACnC,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EACL,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC7B,+BAA+B,EAC/B,yBAAyB,GAC1B,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,mBAAmB,EACnB,KAAK,wBAAwB,GAC9B,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,KAAK,yBAAyB,EAC9B,KAAK,qBAAqB,GAC3B,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,YAAY,EACZ,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -6,6 +6,7 @@ export { TrafficalClient, MemoryStorageProvider, ErrorBoundary, createWarehouseN
6
6
  export { TrafficalRNClient, } from "./client.js";
7
7
  export { createPreloadedAsyncStorage, } from "./storage.js";
8
8
  export { createRNLifecycleProvider } from "./lifecycle.js";
9
+ export { createDefaultDeviceInfoProvider, defaultDeviceInfoProvider, } from "./device-info.js";
9
10
  // Provider and hooks
10
11
  export { TrafficalRNProvider, } from "./provider.js";
11
12
  export { TrafficalContext, useTrafficalContext, } from "./context.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,cAAc,iBAAiB,CAAC;AAEhC,4FAA4F;AAC5F,OAAO,EACL,eAAe,EAMf,qBAAqB,EAGrB,aAAa,EAEb,iCAAiC,EACjC,2BAA2B,GAE5B,MAAM,sBAAsB,CAAC;AAE9B,sBAAsB;AACtB,OAAO,EACL,iBAAiB,GAElB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,2BAA2B,GAE5B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAG3D,qBAAqB;AACrB,OAAO,EACL,mBAAmB,GAEpB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,gBAAgB,EAChB,mBAAmB,GAGpB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,YAAY,EAGZ,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,cAAc,iBAAiB,CAAC;AAEhC,4FAA4F;AAC5F,OAAO,EACL,eAAe,EAMf,qBAAqB,EAGrB,aAAa,EAEb,iCAAiC,EACjC,2BAA2B,GAE5B,MAAM,sBAAsB,CAAC;AAE9B,sBAAsB;AACtB,OAAO,EACL,iBAAiB,GAElB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,2BAA2B,GAE5B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAIL,+BAA+B,EAC/B,yBAAyB,GAC1B,MAAM,kBAAkB,CAAC;AAE1B,qBAAqB;AACrB,OAAO,EACL,mBAAmB,GAEpB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,gBAAgB,EAChB,mBAAmB,GAGpB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,YAAY,EAGZ,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,YAAY,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@traffical/react-native",
3
- "version": "0.8.3",
3
+ "version": "0.9.0",
4
4
  "description": "Traffical SDK for React Native - server-evaluated feature flags, A/B testing, and adaptive optimization",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -22,8 +22,8 @@
22
22
  "typecheck": "tsc --noEmit"
23
23
  },
24
24
  "dependencies": {
25
- "@traffical/core": "0.12.0",
26
- "@traffical/js-client": "0.17.0"
25
+ "@traffical/core": "0.12.1",
26
+ "@traffical/js-client": "0.19.0"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/bun": "latest",