@reopt-ai/data-sdk-client 0.1.2 → 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/dist/next.d.ts CHANGED
@@ -1,9 +1,8 @@
1
1
  import * as react from 'react';
2
- export { R as ReoptClient, a as ReoptClientConfig, W as WebVitalMetric } from './client-B6gFgjju.js';
2
+ export { R as ReoptClient, a as ReoptClientConfig, W as WebVitalMetric } from './client-CW9DfTlm.js';
3
3
  import { ReoptProviderProps } from './react.js';
4
4
  export { ReoptContextValue, useConsent, useIdentify, usePageView, usePageViewOnMount, useReopt, useReoptClient, useTrack, useTrackOnMount } from './react.js';
5
5
  export { ReoptBootstrap } from '@reopt-ai/data-contract/identity';
6
- import '@reopt-ai/data-sdk-core';
7
6
 
8
7
  /**
9
8
  * `ReoptProvider` for the App Router. Identical to the React one except
package/dist/next.js CHANGED
@@ -35,7 +35,7 @@ function PageViewTracker() {
35
35
  const key = search ? `${pathname}?${search}` : pathname;
36
36
  if (lastKey.current === key) return;
37
37
  lastKey.current = key;
38
- pageView({ path: pathname, properties: search ? { search } : void 0 });
38
+ pageView({ properties: search ? { search } : void 0 });
39
39
  }, [pathname, searchParams, pageView]);
40
40
  return null;
41
41
  }
package/dist/next.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/next/index.tsx"],"sourcesContent":["\"use client\";\n\nimport { Suspense, useCallback, useEffect, useRef } from \"react\";\nimport { usePathname, useSearchParams } from \"next/navigation\";\nimport { useReportWebVitals } from \"next/web-vitals\";\nimport type { WebVitalMetric } from \"../capture/web-vitals.js\";\nimport { ReoptProvider as BaseProvider, useReopt, type ReoptProviderProps } from \"../react/index.js\";\n\n/**\n * `ReoptProvider` for the App Router. Identical to the React one except\n * that it does not send the first `$pageview` itself — `<ReoptPageView />`\n * owns page views, the first one included, so nothing is counted twice.\n *\n * Because this module starts with `\"use client\"`, importing it from a server\n * component (your `app/layout.tsx`) creates the client boundary for you.\n */\nexport function ReoptProvider(props: ReoptProviderProps) {\n return <BaseProvider {...props} initialPageView={false} />;\n}\n\n/**\n * Sends `$pageview` on every App Router navigation — pathname *and* query\n * string, so a filter change or a UTM landing counts. Render it as a\n * sibling of your page content, inside `<ReoptProvider>`; wrapping children\n * would rerender the whole tree on every navigation.\n *\n * It carries its own `<Suspense>` because `useSearchParams()` requires one\n * on prerendered routes; without it the nearest boundary — possibly your\n * entire layout — would fall back to client rendering.\n */\nexport function ReoptPageView() {\n return (\n <Suspense fallback={null}>\n <PageViewTracker />\n </Suspense>\n );\n}\n\nfunction PageViewTracker() {\n const pathname = usePathname();\n const searchParams = useSearchParams();\n const { pageView } = useReopt();\n const lastKey = useRef<string | null>(null);\n\n useEffect(() => {\n if (!pathname) return;\n const search = searchParams?.toString() ?? \"\";\n const key = search ? `${pathname}?${search}` : pathname;\n // StrictMode runs this effect twice for one navigation; the URL did not change, so neither should the count.\n if (lastKey.current === key) return;\n lastKey.current = key;\n pageView({ path: pathname, properties: search ? { search } : undefined });\n }, [pathname, searchParams, pageView]);\n\n return null;\n}\n\n/**\n * Sends `$web_vitals` for every Core Web Vital Next reports (TTFB, FCP,\n * LCP, CLS, INP, …). Place it next to `<ReoptPageView />`.\n */\nexport function ReoptWebVitals() {\n const { captureWebVital } = useReopt();\n // A changing callback would re-report metrics already delivered.\n const report = useCallback((metric: WebVitalMetric) => captureWebVital(metric), [captureWebVital]);\n useReportWebVitals(report);\n return null;\n}\n\nexport {\n useReopt,\n useReoptClient,\n useTrack,\n useIdentify,\n usePageView,\n useConsent,\n useTrackOnMount,\n usePageViewOnMount,\n} from \"../react/index.js\";\nexport type { ReoptContextValue, ReoptProviderProps } from \"../react/index.js\";\nexport type { ReoptBootstrap, ReoptClientConfig } from \"../config.js\";\nexport type { ReoptClient } from \"../client.js\";\nexport type { WebVitalMetric };\n"],"mappings":";;;;;;;;;;;;;;;;AAEA,SAAS,UAAU,aAAa,WAAW,cAAc;AACzD,SAAS,aAAa,uBAAuB;AAC7C,SAAS,0BAA0B;AAa1B;AADF,SAASA,eAAc,OAA2B;AACvD,SAAO,oBAAC,iBAAc,GAAG,OAAO,iBAAiB,OAAO;AAC1D;AAYO,SAAS,gBAAgB;AAC9B,SACE,oBAAC,YAAS,UAAU,MAClB,8BAAC,mBAAgB,GACnB;AAEJ;AAEA,SAAS,kBAAkB;AACzB,QAAM,WAAW,YAAY;AAC7B,QAAM,eAAe,gBAAgB;AACrC,QAAM,EAAE,SAAS,IAAI,SAAS;AAC9B,QAAM,UAAU,OAAsB,IAAI;AAE1C,YAAU,MAAM;AACd,QAAI,CAAC,SAAU;AACf,UAAM,SAAS,cAAc,SAAS,KAAK;AAC3C,UAAM,MAAM,SAAS,GAAG,QAAQ,IAAI,MAAM,KAAK;AAE/C,QAAI,QAAQ,YAAY,IAAK;AAC7B,YAAQ,UAAU;AAClB,aAAS,EAAE,MAAM,UAAU,YAAY,SAAS,EAAE,OAAO,IAAI,OAAU,CAAC;AAAA,EAC1E,GAAG,CAAC,UAAU,cAAc,QAAQ,CAAC;AAErC,SAAO;AACT;AAMO,SAAS,iBAAiB;AAC/B,QAAM,EAAE,gBAAgB,IAAI,SAAS;AAErC,QAAM,SAAS,YAAY,CAAC,WAA2B,gBAAgB,MAAM,GAAG,CAAC,eAAe,CAAC;AACjG,qBAAmB,MAAM;AACzB,SAAO;AACT;","names":["ReoptProvider"]}
1
+ {"version":3,"sources":["../src/next/index.tsx"],"sourcesContent":["\"use client\";\n\nimport { Suspense, useCallback, useEffect, useRef } from \"react\";\nimport { usePathname, useSearchParams } from \"next/navigation\";\nimport { useReportWebVitals } from \"next/web-vitals\";\nimport type { WebVitalMetric } from \"../capture/web-vitals.js\";\nimport { ReoptProvider as BaseProvider, useReopt, type ReoptProviderProps } from \"../react/index.js\";\n\n/**\n * `ReoptProvider` for the App Router. Identical to the React one except\n * that it does not send the first `$pageview` itself — `<ReoptPageView />`\n * owns page views, the first one included, so nothing is counted twice.\n *\n * Because this module starts with `\"use client\"`, importing it from a server\n * component (your `app/layout.tsx`) creates the client boundary for you.\n */\nexport function ReoptProvider(props: ReoptProviderProps) {\n return <BaseProvider {...props} initialPageView={false} />;\n}\n\n/**\n * Sends `$pageview` on every App Router navigation — pathname *and* query\n * string, so a filter change or a UTM landing counts. Render it as a\n * sibling of your page content, inside `<ReoptProvider>`; wrapping children\n * would rerender the whole tree on every navigation.\n *\n * It carries its own `<Suspense>` because `useSearchParams()` requires one\n * on prerendered routes; without it the nearest boundary — possibly your\n * entire layout — would fall back to client rendering.\n */\nexport function ReoptPageView() {\n return (\n <Suspense fallback={null}>\n <PageViewTracker />\n </Suspense>\n );\n}\n\nfunction PageViewTracker() {\n const pathname = usePathname();\n const searchParams = useSearchParams();\n const { pageView } = useReopt();\n const lastKey = useRef<string | null>(null);\n\n useEffect(() => {\n if (!pathname) return;\n const search = searchParams?.toString() ?? \"\";\n const key = search ? `${pathname}?${search}` : pathname;\n // StrictMode runs this effect twice for one navigation; the URL did not change, so neither should the count.\n if (lastKey.current === key) return;\n lastKey.current = key;\n // No explicit `path`: the runtime stamps it from `location.pathname`\n // (identical to `usePathname()` once the navigation has committed), and\n // that is the only path `normalizePath` applies to. Passing `pathname`\n // here would bypass the hook for the very event whose cardinality it\n // exists to control.\n pageView({ properties: search ? { search } : undefined });\n }, [pathname, searchParams, pageView]);\n\n return null;\n}\n\n/**\n * Sends `$web_vitals` for every Core Web Vital Next reports (TTFB, FCP,\n * LCP, CLS, INP, …). Place it next to `<ReoptPageView />`.\n */\nexport function ReoptWebVitals() {\n const { captureWebVital } = useReopt();\n // A changing callback would re-report metrics already delivered.\n const report = useCallback((metric: WebVitalMetric) => captureWebVital(metric), [captureWebVital]);\n useReportWebVitals(report);\n return null;\n}\n\nexport {\n useReopt,\n useReoptClient,\n useTrack,\n useIdentify,\n usePageView,\n useConsent,\n useTrackOnMount,\n usePageViewOnMount,\n} from \"../react/index.js\";\nexport type { ReoptContextValue, ReoptProviderProps } from \"../react/index.js\";\nexport type { ReoptBootstrap, ReoptClientConfig } from \"../config.js\";\nexport type { ReoptClient } from \"../client.js\";\nexport type { WebVitalMetric };\n"],"mappings":";;;;;;;;;;;;;;;;AAEA,SAAS,UAAU,aAAa,WAAW,cAAc;AACzD,SAAS,aAAa,uBAAuB;AAC7C,SAAS,0BAA0B;AAa1B;AADF,SAASA,eAAc,OAA2B;AACvD,SAAO,oBAAC,iBAAc,GAAG,OAAO,iBAAiB,OAAO;AAC1D;AAYO,SAAS,gBAAgB;AAC9B,SACE,oBAAC,YAAS,UAAU,MAClB,8BAAC,mBAAgB,GACnB;AAEJ;AAEA,SAAS,kBAAkB;AACzB,QAAM,WAAW,YAAY;AAC7B,QAAM,eAAe,gBAAgB;AACrC,QAAM,EAAE,SAAS,IAAI,SAAS;AAC9B,QAAM,UAAU,OAAsB,IAAI;AAE1C,YAAU,MAAM;AACd,QAAI,CAAC,SAAU;AACf,UAAM,SAAS,cAAc,SAAS,KAAK;AAC3C,UAAM,MAAM,SAAS,GAAG,QAAQ,IAAI,MAAM,KAAK;AAE/C,QAAI,QAAQ,YAAY,IAAK;AAC7B,YAAQ,UAAU;AAMlB,aAAS,EAAE,YAAY,SAAS,EAAE,OAAO,IAAI,OAAU,CAAC;AAAA,EAC1D,GAAG,CAAC,UAAU,cAAc,QAAQ,CAAC;AAErC,SAAO;AACT;AAMO,SAAS,iBAAiB;AAC/B,QAAM,EAAE,gBAAgB,IAAI,SAAS;AAErC,QAAM,SAAS,YAAY,CAAC,WAA2B,gBAAgB,MAAM,GAAG,CAAC,eAAe,CAAC;AACjG,qBAAmB,MAAM;AACzB,SAAO;AACT;","names":["ReoptProvider"]}
package/dist/react.d.ts CHANGED
@@ -2,9 +2,7 @@ import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
3
  import { ReoptBootstrap } from '@reopt-ai/data-contract/identity';
4
4
  export { ReoptBootstrap } from '@reopt-ai/data-contract/identity';
5
- import { TrackEventOptions, QueueResult, IdentifyOptions, IncrementOptions, DecrementOptions, PageViewOptions, FlushResult, ConsentCategory } from '@reopt-ai/data-sdk-core';
6
- export { ConsentCategory, DecrementOptions, FlushResult, IdentifyOptions, IncrementOptions, PageViewOptions, QueueResult, TrackEventOptions } from '@reopt-ai/data-sdk-core';
7
- import { R as ReoptClient, W as WebVitalMetric, a as ReoptClientConfig } from './client-B6gFgjju.js';
5
+ import { R as ReoptClient, T as TrackEventOptions, Q as QueueResult, I as IdentifyOptions, c as IncrementOptions, D as DecrementOptions, P as PageViewOptions, W as WebVitalMetric, F as FlushResult, C as ConsentCategory, a as ReoptClientConfig } from './client-CW9DfTlm.js';
8
6
 
9
7
  interface ReoptContextValue {
10
8
  /** `null` during server rendering and before hydration. */
@@ -73,4 +71,4 @@ declare function useTrackOnMount(name: string, properties?: Record<string, unkno
73
71
  /** Sends one `$pageview` on mount with the options current at that moment. */
74
72
  declare function usePageViewOnMount(options?: PageViewOptions): void;
75
73
 
76
- export { ReoptClient, ReoptClientConfig, type ReoptContextValue, ReoptProvider, type ReoptProviderProps, WebVitalMetric, useConsent, useIdentify, usePageView, usePageViewOnMount, useReopt, useReoptClient, useTrack, useTrackOnMount };
74
+ export { ConsentCategory, DecrementOptions, FlushResult, IdentifyOptions, IncrementOptions, PageViewOptions, QueueResult, ReoptClient, ReoptClientConfig, type ReoptContextValue, ReoptProvider, type ReoptProviderProps, TrackEventOptions, WebVitalMetric, useConsent, useIdentify, usePageView, usePageViewOnMount, useReopt, useReoptClient, useTrack, useTrackOnMount };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reopt-ai/data-sdk-client",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "reopt-data browser SDK — vanilla, React and Next.js App Router client components",
5
5
  "sideEffects": false,
6
6
  "license": "MIT",
@@ -51,7 +51,7 @@
51
51
  }
52
52
  },
53
53
  "dependencies": {
54
- "@reopt-ai/data-contract": "0.6.1"
54
+ "@reopt-ai/data-contract": "0.6.2"
55
55
  },
56
56
  "devDependencies": {
57
57
  "@testing-library/react": "^16.3.2",
@@ -64,8 +64,8 @@
64
64
  "tsup": "^8.5.1",
65
65
  "typescript": "^5.9.3",
66
66
  "vitest": "^4.1.11",
67
- "@reopt-ai/data-sdk-core": "0.0.0",
68
- "@repo/typescript-config": "0.0.0"
67
+ "@repo/typescript-config": "0.0.0",
68
+ "@reopt-ai/data-sdk-core": "0.0.0"
69
69
  },
70
70
  "scripts": {
71
71
  "build": "tsup && pnpm run check:dist && pnpm run check:size",
@@ -1,181 +0,0 @@
1
- import { ConsentConfig, BatchConfig, RetryConfig, CircuitBreakerConfig, StorageBackend, FetchLike, ReoptCore, PageViewOptions, QueueResult, IdentifyOptions, FlushResult } from '@reopt-ai/data-sdk-core';
2
- import { ReoptBootstrap, DeviceCookieState, ConsentCookieState } from '@reopt-ai/data-contract/identity';
3
-
4
- /**
5
- * The shape `next/web-vitals`' `useReportWebVitals` and the `web-vitals`
6
- * package both produce. Declared here so the vanilla entry does not have to
7
- * import either.
8
- */
9
- interface WebVitalMetric {
10
- id: string;
11
- name: string;
12
- value: number;
13
- delta?: number;
14
- rating?: "good" | "needs-improvement" | "poor";
15
- navigationType?: string;
16
- }
17
- type WebVitalProperties = {
18
- metric_name: string;
19
- metric_id: string;
20
- value: number;
21
- delta?: number;
22
- rating?: string;
23
- navigation_type?: string;
24
- path: string;
25
- };
26
-
27
- /**
28
- * Rewrites a pathname before it is attached to an event, and may lift the
29
- * parts it removed into properties so they stay available for breakdowns:
30
- * `/workspace/8f3…/crm/customers/2a1…` → `{ path: "/workspace/:id/crm/customers/:id",
31
- * properties: { workspace_id: "8f3…" } }`.
32
- *
33
- * Applied wherever the SDK fills in a path itself — the default `$pageview`
34
- * path, `$pageleave`, `$web_vitals`, `$exception`. A `path` you pass to
35
- * `pageView()` explicitly is used as-is, so run the same function on it
36
- * yourself; two different rules would give one visit two different paths.
37
- * Must be synchronous and pure. If it throws, the raw pathname is used.
38
- */
39
- type NormalizePath = (pathname: string) => string | {
40
- path: string;
41
- properties?: Record<string, unknown>;
42
- };
43
-
44
- type IdentityStorageKind = "auto" | "cookie" | "localStorage" | "memory";
45
- interface IdentityConfig {
46
- /**
47
- * Where the device id lives. `auto` (default) prefers a cookie: Safari
48
- * expires script-written `localStorage` after seven days of inactivity,
49
- * which turns every returning visitor into a new device. A cookie the
50
- * server also reads survives that, and lets server-side events join the
51
- * same device.
52
- */
53
- storage?: IdentityStorageKind;
54
- /** Cookie `Domain`; omit for host-only. Set to share across subdomains. */
55
- cookieDomain?: string;
56
- /** Cookie lifetime. Default 400 days (the longest Chrome honours). */
57
- cookieMaxAgeSeconds?: number;
58
- }
59
- interface CaptureConfig {
60
- /**
61
- * Send `$pageview` on `init()`. Default `true` for the vanilla entry.
62
- * The Next entry sets it to `false` because `<ReoptPageView />` owns page
63
- * views there — including the first one.
64
- */
65
- pageview?: boolean;
66
- /** Send `$pageleave` with time-on-page when the page is hidden or the route changes. Default `true`. */
67
- pageleave?: boolean;
68
- /** Attach max scroll depth to `$pageleave`. Default `true`. */
69
- scrollDepth?: boolean;
70
- /** Send `$exception` for uncaught errors and unhandled rejections. Default `false`. */
71
- exceptions?: boolean;
72
- }
73
- interface ReoptClientConfig {
74
- writeKey: string;
75
- /** reopt-data origin, or the same-origin proxy prefix (e.g. `/ingest`) the Next.js proxy rewrites. */
76
- baseUrl: string;
77
- /** What the server already knows about this visitor. `null` = nothing. */
78
- bootstrap?: ReoptBootstrap | null;
79
- identity?: IdentityConfig;
80
- capture?: CaptureConfig;
81
- /**
82
- * Hosts that receive the `reopt-device-id` header on outgoing `fetch`/XHR,
83
- * so a server-side `track()` lands on the same device. `true` = the page's
84
- * own hostname. **Default: off** — the trusted path is passing
85
- * `getDeviceId()` to your server call explicitly; this patches `fetch`
86
- * and loads as a separate chunk only when enabled.
87
- */
88
- tracingHeaders?: boolean | string[];
89
- /** See {@link NormalizePath}. */
90
- normalizePath?: NormalizePath;
91
- /**
92
- * Properties attached to every event from the very first one. Same as
93
- * calling `register()` right after `init()`, except that nothing can
94
- * slip out in between: web vitals arrive from a buffered
95
- * `PerformanceObserver` and can fire the instant the client exists.
96
- * Pass the page context the server already knows here; update it on
97
- * client-side navigation with `register()`.
98
- */
99
- properties?: Record<string, unknown>;
100
- consent?: ConsentConfig;
101
- batch?: BatchConfig;
102
- retry?: RetryConfig;
103
- circuitBreaker?: CircuitBreakerConfig;
104
- /** Upper bound on queued events. Default 10 000. */
105
- maxQueueSize?: number;
106
- /** Overrides the store for the offline queue. Default `localStorage`. */
107
- queueStorage?: StorageBackend;
108
- /** Prefix for storage keys. Default `reopt_`. */
109
- storagePrefix?: string;
110
- /**
111
- * Transport override. Tests hand in a recording function so a Playwright
112
- * spec can assert on the exact payload the SDK built, without intercepting
113
- * the network. Defaults to the page's `fetch` (captured at init, before the
114
- * tracing patch, so the SDK's own requests are never tagged twice).
115
- */
116
- fetch?: FetchLike;
117
- debug?: boolean;
118
- }
119
- interface ResolvedCaptureConfig {
120
- pageview: boolean;
121
- pageleave: boolean;
122
- scrollDepth: boolean;
123
- exceptions: boolean;
124
- }
125
-
126
- interface IdentityStore {
127
- readonly kind: Exclude<IdentityStorageKind, "auto">;
128
- readDevice(): DeviceCookieState | null;
129
- writeDevice(state: DeviceCookieState): void;
130
- clearDevice(): void;
131
- readConsent(): ConsentCookieState | null;
132
- writeConsent(state: ConsentCookieState): void;
133
- /** Engine-facing backend for the consent key, so consent decisions land in the same place. */
134
- consentBackend(): StorageBackend;
135
- }
136
-
137
- interface ReoptClientDefaults {
138
- /** Whether `init()` sends the first `$pageview`. The Next entry says no. */
139
- pageview: boolean;
140
- }
141
- /**
142
- * The browser client: the shared engine plus everything that only makes
143
- * sense in a document — cookie identity, tracing headers, page leave,
144
- * scroll depth, exception capture, and a clock corrected against the
145
- * server's.
146
- */
147
- declare class ReoptClient extends ReoptCore {
148
- readonly writeKey: string;
149
- readonly capture: ResolvedCaptureConfig;
150
- private readonly store;
151
- private readonly pageLeave;
152
- private readonly scroll;
153
- private readonly uninstallers;
154
- private torndown;
155
- private readonly session;
156
- private readonly normalize;
157
- /** True when `writeKey` or `baseUrl` was missing: every call is a silent no-op. */
158
- readonly disabled: boolean;
159
- constructor(config: ReoptClientConfig, defaults?: ReoptClientDefaults);
160
- /** Which store identity ended up in — `cookie`, `localStorage` or `memory`. */
161
- get identityStorage(): IdentityStore["kind"];
162
- pageView(options?: PageViewOptions): QueueResult;
163
- identify(options: IdentifyOptions): QueueResult;
164
- /** Feed a Web Vitals metric (from `next/web-vitals` or the `web-vitals` package). */
165
- captureWebVital(metric: WebVitalMetric): QueueResult;
166
- /** The page's path through `normalizePath`, for events the SDK stamps itself. */
167
- private currentPath;
168
- /** Report an error you caught yourself. */
169
- captureException(error: unknown, properties?: Record<string, unknown>): QueueResult;
170
- private trackException;
171
- private emitPageLeave;
172
- /**
173
- * Log out: forget the profile and the queue, and become a new device.
174
- * On a shared computer the next person must not inherit this one's
175
- * history.
176
- */
177
- reset(): void;
178
- close(): Promise<FlushResult>;
179
- }
180
-
181
- export { type CaptureConfig as C, type IdentityConfig as I, type NormalizePath as N, ReoptClient as R, type WebVitalMetric as W, type ReoptClientConfig as a, type ReoptClientDefaults as b, type IdentityStorageKind as c, type WebVitalProperties as d };