@reopt-ai/data-sdk-client 0.1.3 → 0.1.5

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,5 +1,5 @@
1
1
  import * as react from 'react';
2
- export { R as ReoptClient, a as ReoptClientConfig, W as WebVitalMetric } from './client-CW9DfTlm.js';
2
+ export { R as ReoptClient, a as ReoptClientConfig, W as WebVitalMetric } from './client-TesmBLXd.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';
package/dist/next.js CHANGED
@@ -9,8 +9,8 @@ import {
9
9
  useReoptClient,
10
10
  useTrack,
11
11
  useTrackOnMount
12
- } from "./chunk-JNIOYR44.js";
13
- import "./chunk-SRHWNG2G.js";
12
+ } from "./chunk-2UPF3C7D.js";
13
+ import "./chunk-BJGIHFDA.js";
14
14
  import "./chunk-4MTDZBRS.js";
15
15
 
16
16
  // src/next/index.tsx
@@ -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.cjs CHANGED
@@ -1549,6 +1549,7 @@ var ReoptClient = class extends ReoptCore {
1549
1549
  uninstallers = [];
1550
1550
  torndown = false;
1551
1551
  session;
1552
+ optedOut;
1552
1553
  normalize;
1553
1554
  /** True when `writeKey` or `baseUrl` was missing: every call is a silent no-op. */
1554
1555
  disabled;
@@ -1559,7 +1560,16 @@ var ReoptClient = class extends ReoptCore {
1559
1560
  }
1560
1561
  const writeKey = config.writeKey || "disabled";
1561
1562
  const storagePrefix = config.storagePrefix ?? DEFAULT_STORAGE_PREFIX;
1562
- const store = createIdentityStore(writeKey, { ...config.identity, ...disabled ? { storage: "memory" } : {} });
1563
+ const rawStore = createIdentityStore(writeKey, { ...config.identity, ...disabled ? { storage: "memory" } : {} });
1564
+ const optedOut = {
1565
+ value: (0, import_identity5.isOptedOut)(rawStore.readConsent() ?? config.bootstrap?.consent ?? null) || config.consent?.defaultConsent === false
1566
+ };
1567
+ const store = {
1568
+ ...rawStore,
1569
+ writeDevice: (state) => {
1570
+ if (!optedOut.value) rawStore.writeDevice(state);
1571
+ }
1572
+ };
1563
1573
  const identity = resolveDeviceId(store, config.bootstrap?.deviceId, storagePrefix);
1564
1574
  const now = correctedClock(config.bootstrap);
1565
1575
  const queueStorage = disabled ? memoryStorage() : config.queueStorage ?? localStorageBackend() ?? memoryStorage();
@@ -1612,6 +1622,7 @@ var ReoptClient = class extends ReoptCore {
1612
1622
  this.writeKey = config.writeKey;
1613
1623
  this.disabled = disabled;
1614
1624
  this.session = session;
1625
+ this.optedOut = optedOut;
1615
1626
  this.normalize = config.normalizePath;
1616
1627
  this.store = store;
1617
1628
  this.capture = resolveCapture(config.capture, defaults.pageview);
@@ -1670,6 +1681,34 @@ var ReoptClient = class extends ReoptCore {
1670
1681
  this.scroll?.reset();
1671
1682
  return super.pageView(options);
1672
1683
  }
1684
+ setConsent(category, allowed) {
1685
+ super.setConsent(category, allowed);
1686
+ this.syncOptOut();
1687
+ }
1688
+ setAllConsent(allowed) {
1689
+ super.setAllConsent(allowed);
1690
+ this.syncOptOut();
1691
+ }
1692
+ replaceConsentState(state) {
1693
+ super.replaceConsentState(state);
1694
+ this.syncOptOut();
1695
+ }
1696
+ /**
1697
+ * Refusing `analytics` removes the stored identity (the proxy does the
1698
+ * same on its side); granting it again writes the current device through
1699
+ * so the visit is attributable from that point on.
1700
+ */
1701
+ syncOptOut() {
1702
+ const now = (0, import_identity5.isOptedOut)(this.getConsentState());
1703
+ if (now === this.optedOut.value) return;
1704
+ this.optedOut.value = now;
1705
+ if (now) {
1706
+ this.store.clearDevice();
1707
+ this.session.header = null;
1708
+ } else {
1709
+ this.store.writeDevice({ deviceId: this.getDeviceId() });
1710
+ }
1711
+ }
1673
1712
  identify(options) {
1674
1713
  const result = super.identify(options);
1675
1714
  if (!options.identity && result.queued) {