@askdepth/react 0.1.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 ADDED
@@ -0,0 +1,133 @@
1
+ # @askdepth/react
2
+
3
+ React 18+ and Next.js adapter for Askdepth. It mounts `@askdepth/core` from a client component, maps frustration clicks back to React components, and can stamp JSX with source locations at compile time.
4
+
5
+ - **Client-only:** the package entry starts with `'use client'`. Server Components import the provider without starting listeners.
6
+ - **Idempotent mount:** a second provider with the same config does not attach another set of core listeners.
7
+ - **Route changes:** `history.pushState`, `replaceState`, and `popstate` emit `page_view` events. Query strings and fragments are omitted; dynamic path segments are redacted, while a small allowlist of common static route names is retained. Next.js App Router navigation has not been verified end to end.
8
+ - **Component location:** `data-askdepth-src` / `data-askdepth-id` when the compiler plugin is installed, otherwise a React Fiber walk.
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ pnpm add @askdepth/react @askdepth/core react react-dom
14
+ ```
15
+
16
+ Peer dependencies: `react` and `react-dom` `>=18`. The compiler plugin dependencies (`unplugin`, Babel parser) install with this package and stay out of the browser runtime bundle.
17
+
18
+ ## Provider
19
+
20
+ ```tsx
21
+ 'use client';
22
+
23
+ import { AskdepthProvider } from '@askdepth/react';
24
+
25
+ export function Providers({ children }: { children: React.ReactNode }) {
26
+ return (
27
+ <AskdepthProvider
28
+ writeKey={process.env.NEXT_PUBLIC_ASKDEPTH_WRITE_KEY!}
29
+ endpoint={process.env.NEXT_PUBLIC_ASKDEPTH_ENDPOINT!}
30
+ consent="granted"
31
+ environment={process.env.NODE_ENV === 'production' ? 'production' : 'development'}
32
+ replay={true}
33
+ >
34
+ {children}
35
+ </AskdepthProvider>
36
+ );
37
+ }
38
+ ```
39
+
40
+ `useAskdepth()` returns `track`, `identify`, `getTraceparent`, `isReady`, and `getSessionId`. Outside the provider those methods are no-ops.
41
+
42
+ ## Error boundary
43
+
44
+ `<AskdepthCatch>` reports a handled `ERROR_CLICK` through core's frustration event path, which triggers the replay flash when replay is enabled. Core uses a recent click selector when available, attaches the resolved component location, and sanitizes and bounds the error and React component stacks. The error message sent in telemetry is generic.
45
+
46
+ ```tsx
47
+ import { AskdepthCatch } from '@askdepth/react';
48
+
49
+ <AskdepthCatch fallback={(error, reset) => <button onClick={reset}>{error.message}</button>}>
50
+ <Checkout />
51
+ </AskdepthCatch>
52
+ ```
53
+
54
+ ## Compiler plugin
55
+
56
+ Development and staging add `data-askdepth-src="src/components/Button.tsx:42:10"`. Production adds `data-askdepth-id="cmp_"` plus the first 8 hex characters of SHA-256 over that same `path:line:column` label, so source paths stay out of the bundle. Production builds also write private lookup files to `.askdepth/component-maps/<build-id>/`; set `ASKDEPTH_BUILD_ID` to your deployment ID and retain these files in private build artifacts for resolving IDs later. Set `ASKDEPTH_COMPONENT_MAP_DIR` to move the output, including for Turbopack. For the Vite, Webpack, and Rspack plugins, `buildId` and `mappingDir` override the environment defaults. Keep the mapping directory outside publicly served assets.
57
+
58
+ ```ts
59
+ import { askdepthVitePlugin } from '@askdepth/react/plugin';
60
+
61
+ export default defineConfig({
62
+ plugins: [react(), askdepthVitePlugin({ environment: process.env.NODE_ENV })],
63
+ });
64
+ ```
65
+
66
+ ```js
67
+ const { withAskdepth } = require('@askdepth/react/plugin');
68
+
69
+ module.exports = withAskdepth({
70
+ // existing Next config; the helper adds the plugin to client and server webpack builds
71
+ });
72
+ ```
73
+
74
+ Or push the plugin yourself in a Webpack build:
75
+
76
+ ```js
77
+ const { askdepthWebpackPlugin } = require('@askdepth/react/plugin');
78
+
79
+ webpack(config) {
80
+ config.plugins.push(askdepthWebpackPlugin({ environment: process.env.NODE_ENV }));
81
+ return config;
82
+ }
83
+ ```
84
+
85
+ `withAskdepth` configures the webpack compiler. For Turbopack, configure the package's separate loader in `next.config.js`. The rules below cover both `.tsx` and `.jsx` files and use the current `turbopack` key (Next.js 15.3+ and 16):
86
+
87
+ ```js
88
+ module.exports = {
89
+ turbopack: {
90
+ rules: {
91
+ '*.tsx': {
92
+ loaders: ['@askdepth/react/turbopack-loader'],
93
+ as: '*.tsx',
94
+ },
95
+ '*.jsx': {
96
+ loaders: ['@askdepth/react/turbopack-loader'],
97
+ as: '*.jsx',
98
+ },
99
+ },
100
+ },
101
+ };
102
+ ```
103
+
104
+ For Next.js 15.0–15.2, put the same `rules` object under `experimental.turbo` instead of `turbopack`. In Next.js 16, Turbopack is the default and does not apply the `webpack()` hook; use `next dev --webpack` / `next build --webpack` when using `withAskdepth`.
105
+
106
+ The loader passes its generated source map through the webpack loader callback. Rspack uses `askdepthRspackPlugin` from `@askdepth/react/plugin`. The Vite, Next.js, and Rspack integrations have unit coverage; a real Next.js/Vite application build is not part of this repository's current checks.
107
+
108
+ Without the plugin, `resolveComponentLocation` walks the Fiber tree from the DOM node and returns the nearest composite component name plus its ancestors.
109
+
110
+ ## Props
111
+
112
+ | Prop | Type | Default | Description |
113
+ |---|---|---|---|
114
+ | `writeKey` | `string` | *(required)* | Client write key sent as `x-askdepth-write-key`. `apiKey` is an alias. |
115
+ | `projectId` | `string` | | UUID/CUID project identifier. Required when the write key is not itself a UUID/CUID. |
116
+ | `endpoint` | `string` | | Ingest URL. Required before collectors start. |
117
+ | `consent` | `'granted' \| 'denied' \| 'unknown'` | `'unknown'` | User consent state. |
118
+ | `replay` | `boolean \| object` | `false` | Session replay, forwarded to core. |
119
+ | `sampleRate` | `number` | `1` | Session sampling probability. |
120
+ | `environment` | `'production' \| 'staging' \| 'development'` | `'production'` | Forwarded to core. |
121
+ | `allowedTracingOrigins` | `string[]` | `[]` | Origins that receive `traceparent`. |
122
+
123
+ ## Bundle budget
124
+
125
+ The runtime entry (`dist/index.mjs`) stays under 4.8 KB gzip. The compiler plugin is a separate Node entry and is not part of that budget.
126
+
127
+ ## Ingest compatibility status
128
+
129
+ The local SDK and `apps/analytics-ingest` worktrees currently share protocol version `0.1.0`, telemetry envelope schemas, and the `x-askdepth-write-key` project-binding flow. Replay uploads use bounded binary chunks. The package version stays at its published `0.1.1`; this source change needs a Changesets-generated release before external consumers receive protocol `0.1.0`. The ingest Docker build has not been validated against that published dependency, and shared network conformance tests have not run. Treat browser write keys as publishable restricted keys, not secrets.
130
+
131
+ ## License
132
+
133
+ MIT © [Askdepth](https://github.com/askdepth)
package/dist/index.cjs ADDED
@@ -0,0 +1,357 @@
1
+ 'use client';
2
+ 'use strict';
3
+
4
+ var core = require('@askdepth/core');
5
+ var react = require('react');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+
8
+ // src/constants.ts
9
+ var ASKDEPTH_SRC_ATTR = "data-askdepth-src";
10
+ var ASKDEPTH_ID_ATTR = "data-askdepth-id";
11
+ var FIBER_KEY_PREFIX = "__reactFiber$";
12
+ var LEGACY_FIBER_KEY_PREFIX = "__reactInternalInstance$";
13
+ var PAGE_VIEW_EVENT = "page_view";
14
+ var COMPOSITE_FIBER_TAGS = /* @__PURE__ */ new Set([0, 1, 2, 11, 14, 15, 16]);
15
+
16
+ // src/fiber.ts
17
+ var MAX_FIBER_DEPTH = 64;
18
+ function componentNameOf(type, seen) {
19
+ if (!type || typeof type === "string" || typeof type === "symbol") return null;
20
+ if (typeof type === "function") {
21
+ const fn = type;
22
+ return fn.displayName || fn.name || null;
23
+ }
24
+ if (typeof type !== "object" || seen.has(type)) return null;
25
+ seen.add(type);
26
+ return type.displayName || type.name || componentNameOf(type.render, seen) || componentNameOf(type.type, seen) || type._payload?._result?.displayName || type._payload?._result?.name || null;
27
+ }
28
+ function readAttr(props, key) {
29
+ const value = props?.[key];
30
+ return typeof value === "string" && value.length > 0 ? value : void 0;
31
+ }
32
+ function fiberKey(target) {
33
+ return Object.getOwnPropertyNames(target).find(
34
+ (name) => name.startsWith(FIBER_KEY_PREFIX) || name.startsWith(LEGACY_FIBER_KEY_PREFIX)
35
+ );
36
+ }
37
+ function locationFrom(componentName, componentStack, sourceAttr, hashId) {
38
+ const location = { componentName, componentStack };
39
+ if (sourceAttr) location.sourceAttr = sourceAttr;
40
+ if (hashId) location.hashId = hashId;
41
+ return location;
42
+ }
43
+ function resolveComponentLocation(target) {
44
+ const directSrc = target.getAttribute(ASKDEPTH_SRC_ATTR) ?? void 0;
45
+ const directId = target.getAttribute(ASKDEPTH_ID_ATTR) ?? void 0;
46
+ const key = fiberKey(target);
47
+ if (!key && !directSrc && !directId) return null;
48
+ const stack = [];
49
+ let primaryName = "";
50
+ let sourceAttr = directSrc;
51
+ let hashId = directId;
52
+ let fiber = key ? target[key] ?? null : null;
53
+ let depth = 0;
54
+ while (fiber && depth < MAX_FIBER_DEPTH) {
55
+ depth += 1;
56
+ const tag = fiber.tag;
57
+ if (typeof tag === "number" && COMPOSITE_FIBER_TAGS.has(tag) && fiber.type && typeof fiber.type !== "symbol" && typeof fiber.type !== "string") {
58
+ const name = componentNameOf(fiber.type, /* @__PURE__ */ new Set()) ?? "Anonymous";
59
+ if (!name.startsWith("Askdepth")) {
60
+ if (!primaryName) primaryName = name;
61
+ stack.push(name);
62
+ }
63
+ }
64
+ if (!sourceAttr) {
65
+ sourceAttr = readAttr(fiber.memoizedProps, ASKDEPTH_SRC_ATTR) ?? readAttr(fiber.pendingProps, ASKDEPTH_SRC_ATTR) ?? readAttr(fiber.alternate?.memoizedProps, ASKDEPTH_SRC_ATTR);
66
+ }
67
+ if (!hashId) {
68
+ hashId = readAttr(fiber.memoizedProps, ASKDEPTH_ID_ATTR) ?? readAttr(fiber.pendingProps, ASKDEPTH_ID_ATTR) ?? readAttr(fiber.alternate?.memoizedProps, ASKDEPTH_ID_ATTR);
69
+ }
70
+ fiber = fiber.return ?? null;
71
+ }
72
+ if (!primaryName && !sourceAttr && !hashId) return null;
73
+ return locationFrom(
74
+ primaryName || target.tagName.toLowerCase(),
75
+ stack.length > 0 ? stack : [target.tagName.toLowerCase()],
76
+ sourceAttr,
77
+ hashId
78
+ );
79
+ }
80
+
81
+ // src/interaction.ts
82
+ var DEFAULT_MAX_INTERACTION_AGE_MS = 5e3;
83
+ var last = null;
84
+ var activeRefCount = 0;
85
+ var clickListener = null;
86
+ function elementFrom(target) {
87
+ if (typeof Element === "undefined") return null;
88
+ if (target instanceof Element) return target;
89
+ if (typeof Node !== "undefined" && target instanceof Node) return target.parentElement;
90
+ return null;
91
+ }
92
+ function getLastUserInteraction(maxAgeMs = DEFAULT_MAX_INTERACTION_AGE_MS) {
93
+ if (!last) return null;
94
+ if (Date.now() - last.timestamp > maxAgeMs) {
95
+ last = null;
96
+ return null;
97
+ }
98
+ return last;
99
+ }
100
+ function clearLastUserInteraction() {
101
+ last = null;
102
+ }
103
+ function installInteractionMemory() {
104
+ if (typeof window === "undefined") return () => void 0;
105
+ activeRefCount += 1;
106
+ if (!clickListener) {
107
+ clickListener = (event) => {
108
+ const target = elementFrom(event.target);
109
+ if (!target) return;
110
+ last = { targetElement: target, timestamp: Date.now() };
111
+ };
112
+ window.addEventListener("click", clickListener, { capture: true, passive: true });
113
+ }
114
+ let unsubscribed = false;
115
+ return () => {
116
+ if (unsubscribed) return;
117
+ unsubscribed = true;
118
+ activeRefCount = Math.max(0, activeRefCount - 1);
119
+ if (activeRefCount === 0 && clickListener) {
120
+ window.removeEventListener("click", clickListener, { capture: true });
121
+ clickListener = null;
122
+ last = null;
123
+ }
124
+ };
125
+ }
126
+ var activeRefCount2 = 0;
127
+ var restore = null;
128
+ var pageViewNotify = null;
129
+ var unsubscribeConsent = null;
130
+ var initialPageViewPending = false;
131
+ var MAX_INPUT_PATH_LENGTH = 4096;
132
+ var MAX_PATH_SEGMENTS = 12;
133
+ var STATIC_ROUTE_SEGMENTS = /* @__PURE__ */ new Set([
134
+ "about",
135
+ "account",
136
+ "admin",
137
+ "api",
138
+ "app",
139
+ "auth",
140
+ "billing",
141
+ "blog",
142
+ "cart",
143
+ "checkout",
144
+ "contact",
145
+ "dashboard",
146
+ "docs",
147
+ "home",
148
+ "login",
149
+ "logout",
150
+ "orders",
151
+ "pricing",
152
+ "products",
153
+ "profile",
154
+ "search",
155
+ "settings",
156
+ "signup",
157
+ "support",
158
+ "users",
159
+ "v1"
160
+ ]);
161
+ function currentUrl() {
162
+ const pathname = window.location.pathname || "/";
163
+ const bounded = pathname.slice(0, MAX_INPUT_PATH_LENGTH);
164
+ const segments = bounded.split("/").filter(Boolean);
165
+ const safe = segments.slice(0, MAX_PATH_SEGMENTS).map(
166
+ (segment) => STATIC_ROUTE_SEGMENTS.has(segment) ? segment : ":redacted"
167
+ );
168
+ if (pathname.length > MAX_INPUT_PATH_LENGTH || segments.length > MAX_PATH_SEGMENTS) {
169
+ safe.push(":truncated");
170
+ }
171
+ return safe.length > 0 ? `/${safe.join("/")}` : "/";
172
+ }
173
+ function startPageViews() {
174
+ if (typeof window === "undefined" || typeof window.history?.pushState !== "function") {
175
+ return () => void 0;
176
+ }
177
+ activeRefCount2 += 1;
178
+ if (!restore) {
179
+ const notify = () => {
180
+ if (activeRefCount2 > 0) {
181
+ core.Askdepth.track(PAGE_VIEW_EVENT, { url: currentUrl() });
182
+ }
183
+ };
184
+ pageViewNotify = notify;
185
+ initialPageViewPending = !core.Askdepth.isInitialized();
186
+ notify();
187
+ const currentPushState = window.history.pushState;
188
+ const currentReplaceState = window.history.replaceState;
189
+ const originalPushState = currentPushState.__askdepth_original__ ?? currentPushState;
190
+ const originalReplaceState = currentReplaceState.__askdepth_original__ ?? currentReplaceState;
191
+ const isPushWrapped = Boolean(
192
+ currentPushState.__askdepth_page_view__
193
+ );
194
+ const isReplaceWrapped = Boolean(
195
+ currentReplaceState.__askdepth_page_view__
196
+ );
197
+ const wrap = (original) => {
198
+ const fn = function(...args) {
199
+ const result = original.apply(this, args);
200
+ notify();
201
+ return result;
202
+ };
203
+ fn.__askdepth_original__ = original;
204
+ fn.__askdepth_page_view__ = true;
205
+ return fn;
206
+ };
207
+ const wrappedPushState = isPushWrapped ? currentPushState : wrap(originalPushState);
208
+ const wrappedReplaceState = isReplaceWrapped ? currentReplaceState : wrap(originalReplaceState);
209
+ if (!isPushWrapped) {
210
+ window.history.pushState = wrappedPushState;
211
+ }
212
+ if (!isReplaceWrapped) {
213
+ window.history.replaceState = wrappedReplaceState;
214
+ }
215
+ restore = () => {
216
+ if (window.history.pushState !== wrappedPushState || window.history.replaceState !== wrappedReplaceState) return;
217
+ window.history.pushState = originalPushState;
218
+ window.history.replaceState = originalReplaceState;
219
+ restore = null;
220
+ pageViewNotify = null;
221
+ initialPageViewPending = false;
222
+ };
223
+ }
224
+ if (activeRefCount2 === 1 && pageViewNotify) {
225
+ window.addEventListener("popstate", pageViewNotify);
226
+ unsubscribeConsent = core.Askdepth.onConsentChange((consent) => {
227
+ if (consent === "granted" && initialPageViewPending) {
228
+ initialPageViewPending = false;
229
+ pageViewNotify?.();
230
+ }
231
+ });
232
+ }
233
+ let unsubscribed = false;
234
+ return () => {
235
+ if (unsubscribed) return;
236
+ unsubscribed = true;
237
+ activeRefCount2 = Math.max(0, activeRefCount2 - 1);
238
+ if (activeRefCount2 === 0) {
239
+ if (pageViewNotify) window.removeEventListener("popstate", pageViewNotify);
240
+ unsubscribeConsent?.();
241
+ unsubscribeConsent = null;
242
+ restore?.();
243
+ }
244
+ };
245
+ }
246
+ var AskdepthContext = react.createContext(null);
247
+ var noopContext = {
248
+ track: () => void 0,
249
+ identify: () => void 0,
250
+ getTraceparent: () => null,
251
+ isReady: () => false,
252
+ getSessionId: () => null
253
+ };
254
+ function getNoopAskdepth() {
255
+ return noopContext;
256
+ }
257
+ var AskdepthProvider = (props) => {
258
+ const { children, apiKey, writeKey: propWriteKey, ...restOptions } = props;
259
+ const writeKey = propWriteKey ?? apiKey ?? "";
260
+ const options = {
261
+ ...restOptions,
262
+ writeKey
263
+ };
264
+ const key = JSON.stringify(options);
265
+ const stable = react.useMemo(() => options, [key]);
266
+ const booted = react.useRef(null);
267
+ const [initializedKey, setInitializedKey] = react.useState(null);
268
+ react.useEffect(() => {
269
+ if (typeof window === "undefined") return;
270
+ if (booted.current !== key) {
271
+ core.Askdepth.init(stable);
272
+ booted.current = key;
273
+ setInitializedKey(key);
274
+ }
275
+ const unbindResolver = core.Askdepth.registerComponentResolver(resolveComponentLocation);
276
+ const unbindInteraction = installInteractionMemory();
277
+ const unbindPageViews = startPageViews();
278
+ return () => {
279
+ unbindResolver();
280
+ unbindInteraction();
281
+ unbindPageViews();
282
+ };
283
+ }, [key, stable]);
284
+ const value = react.useMemo(
285
+ () => ({
286
+ track: (name, properties) => {
287
+ if (properties === void 0) core.Askdepth.track(name);
288
+ else core.Askdepth.track(name, properties);
289
+ },
290
+ identify: (userId, traits) => {
291
+ if (traits === void 0) core.Askdepth.identify(userId);
292
+ else core.Askdepth.identify(userId, traits);
293
+ },
294
+ getTraceparent: () => core.Askdepth.getTraceparent(),
295
+ isReady: () => core.Askdepth.isInitialized(),
296
+ getSessionId: () => core.Askdepth.getSessionId()
297
+ }),
298
+ [initializedKey]
299
+ );
300
+ return /* @__PURE__ */ jsxRuntime.jsx(AskdepthContext.Provider, { value, children });
301
+ };
302
+ AskdepthProvider.displayName = "AskdepthProvider";
303
+ function useAskdepth() {
304
+ return react.useContext(AskdepthContext) ?? getNoopAskdepth();
305
+ }
306
+ var AskdepthCatch = class extends react.Component {
307
+ static displayName = "AskdepthCatch";
308
+ reportTimer = null;
309
+ state = {
310
+ hasError: false,
311
+ error: null
312
+ };
313
+ static getDerivedStateFromError(error) {
314
+ return { hasError: true, error };
315
+ }
316
+ componentDidCatch(error, info) {
317
+ const target = getLastUserInteraction(500)?.targetElement ?? null;
318
+ const componentStack = info.componentStack ?? void 0;
319
+ if (core.Askdepth.isInitialized()) {
320
+ core.Askdepth.reportCaughtError(error, target, componentStack);
321
+ } else {
322
+ if (this.reportTimer) clearTimeout(this.reportTimer);
323
+ this.reportTimer = setTimeout(() => {
324
+ this.reportTimer = null;
325
+ core.Askdepth.reportCaughtError(error, target, componentStack);
326
+ }, 0);
327
+ }
328
+ clearLastUserInteraction();
329
+ }
330
+ componentWillUnmount() {
331
+ if (this.reportTimer) clearTimeout(this.reportTimer);
332
+ }
333
+ resetErrorBoundary = () => {
334
+ this.setState({ hasError: false, error: null });
335
+ };
336
+ render() {
337
+ if (this.state.hasError && this.state.error) {
338
+ const { fallback } = this.props;
339
+ if (typeof fallback === "function") return fallback(this.state.error, this.resetErrorBoundary);
340
+ if (fallback !== void 0) return fallback;
341
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "alert", style: { padding: "16px", border: "1px solid #EF4444", borderRadius: "6px" }, children: [
342
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { children: "Something went wrong" }),
343
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Please try again." }),
344
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: this.resetErrorBoundary, children: "Try again" })
345
+ ] });
346
+ }
347
+ return this.props.children;
348
+ }
349
+ };
350
+
351
+ exports.AskdepthCatch = AskdepthCatch;
352
+ exports.AskdepthContext = AskdepthContext;
353
+ exports.AskdepthProvider = AskdepthProvider;
354
+ exports.resolveComponentLocation = resolveComponentLocation;
355
+ exports.useAskdepth = useAskdepth;
356
+ //# sourceMappingURL=index.cjs.map
357
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/constants.ts","../src/fiber.ts","../src/interaction.ts","../src/page-view.ts","../src/provider.tsx","../src/hooks/use-askdepth.ts","../src/components/error-boundary.tsx"],"names":["activeRefCount","Askdepth","createContext","useMemo","useRef","useState","useEffect","jsx","useContext","Component","jsxs"],"mappings":"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","file":"index.cjs","sourcesContent":["export const ASKDEPTH_SRC_ATTR = 'data-askdepth-src';\nexport const ASKDEPTH_ID_ATTR = 'data-askdepth-id';\nexport const FIBER_KEY_PREFIX = '__reactFiber$';\nexport const LEGACY_FIBER_KEY_PREFIX = '__reactInternalInstance$';\nexport const PAGE_VIEW_EVENT = 'page_view';\nexport const ERROR_CLICK_EVENT = 'ERROR_CLICK';\n\n/** Function, Class, Indeterminate, ForwardRef, Memo, SimpleMemo, Lazy. */\nexport const COMPOSITE_FIBER_TAGS = new Set([0, 1, 2, 11, 14, 15, 16]);\n","import { ASKDEPTH_ID_ATTR, ASKDEPTH_SRC_ATTR, COMPOSITE_FIBER_TAGS, FIBER_KEY_PREFIX, LEGACY_FIBER_KEY_PREFIX } from './constants.js';\nimport type { ResolvedComponentLocation } from './types.js';\n\nconst MAX_FIBER_DEPTH = 64;\n\ninterface FiberType {\n displayName?: string;\n name?: string;\n render?: FiberType;\n type?: FiberType;\n _payload?: {\n _result?: {\n displayName?: string;\n name?: string;\n };\n };\n}\n\ninterface FiberNode {\n tag?: number;\n type?: FiberType | string | symbol | null;\n return?: FiberNode | null;\n memoizedProps?: Record<string, unknown> | null;\n pendingProps?: Record<string, unknown> | null;\n alternate?: FiberNode | null;\n}\n\nfunction componentNameOf(type: FiberNode['type'], seen: Set<object>): string | null {\n if (!type || typeof type === 'string' || typeof type === 'symbol') return null;\n if (typeof type === 'function') {\n const fn = type as FiberType;\n return fn.displayName || fn.name || null;\n }\n if (typeof type !== 'object' || seen.has(type)) return null;\n seen.add(type);\n return (\n type.displayName ||\n type.name ||\n componentNameOf(type.render, seen) ||\n componentNameOf(type.type, seen) ||\n type._payload?._result?.displayName ||\n type._payload?._result?.name ||\n null\n );\n}\n\nfunction readAttr(props: Record<string, unknown> | null | undefined, key: string): string | undefined {\n const value = props?.[key];\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\nfunction fiberKey(target: Element): string | undefined {\n return Object.getOwnPropertyNames(target).find(\n (name) => name.startsWith(FIBER_KEY_PREFIX) || name.startsWith(LEGACY_FIBER_KEY_PREFIX),\n );\n}\n\nfunction locationFrom(\n componentName: string,\n componentStack: string[],\n sourceAttr: string | undefined,\n hashId: string | undefined,\n): ResolvedComponentLocation {\n const location: ResolvedComponentLocation = { componentName, componentStack };\n if (sourceAttr) location.sourceAttr = sourceAttr;\n if (hashId) location.hashId = hashId;\n return location;\n}\n\nexport function resolveComponentLocation(target: Element): ResolvedComponentLocation | null {\n const directSrc = target.getAttribute(ASKDEPTH_SRC_ATTR) ?? undefined;\n const directId = target.getAttribute(ASKDEPTH_ID_ATTR) ?? undefined;\n const key = fiberKey(target);\n if (!key && !directSrc && !directId) return null;\n\n const stack: string[] = [];\n let primaryName = '';\n let sourceAttr = directSrc;\n let hashId = directId;\n let fiber = key ? ((target as unknown as Record<string, FiberNode | undefined>)[key] ?? null) : null;\n let depth = 0;\n\n while (fiber && depth < MAX_FIBER_DEPTH) {\n depth += 1;\n const tag = fiber.tag;\n if (\n typeof tag === 'number' &&\n COMPOSITE_FIBER_TAGS.has(tag) &&\n fiber.type &&\n typeof fiber.type !== 'symbol' &&\n typeof fiber.type !== 'string'\n ) {\n const name = componentNameOf(fiber.type, new Set()) ?? 'Anonymous';\n if (!name.startsWith('Askdepth')) {\n if (!primaryName) primaryName = name;\n stack.push(name);\n }\n }\n if (!sourceAttr) {\n sourceAttr =\n readAttr(fiber.memoizedProps, ASKDEPTH_SRC_ATTR) ??\n readAttr(fiber.pendingProps, ASKDEPTH_SRC_ATTR) ??\n readAttr(fiber.alternate?.memoizedProps, ASKDEPTH_SRC_ATTR);\n }\n if (!hashId) {\n hashId =\n readAttr(fiber.memoizedProps, ASKDEPTH_ID_ATTR) ??\n readAttr(fiber.pendingProps, ASKDEPTH_ID_ATTR) ??\n readAttr(fiber.alternate?.memoizedProps, ASKDEPTH_ID_ATTR);\n }\n fiber = fiber.return ?? null;\n }\n\n if (!primaryName && !sourceAttr && !hashId) return null;\n\n return locationFrom(\n primaryName || target.tagName.toLowerCase(),\n stack.length > 0 ? stack : [target.tagName.toLowerCase()],\n sourceAttr,\n hashId,\n );\n}\n","export interface LastUserInteraction {\n targetElement: Element;\n timestamp: number;\n}\n\nexport const DEFAULT_MAX_INTERACTION_AGE_MS = 5_000;\n\nlet last: LastUserInteraction | null = null;\nlet activeRefCount = 0;\nlet clickListener: ((event: MouseEvent) => void) | null = null;\n\nfunction elementFrom(target: EventTarget | null): Element | null {\n if (typeof Element === 'undefined') return null;\n if (target instanceof Element) return target;\n if (typeof Node !== 'undefined' && target instanceof Node) return target.parentElement;\n return null;\n}\n\n/**\n * Returns the last user interaction if it occurred within `maxAgeMs`.\n * Automatically purges stale references to prevent retaining detached DOM trees.\n */\nexport function getLastUserInteraction(\n maxAgeMs = DEFAULT_MAX_INTERACTION_AGE_MS,\n): LastUserInteraction | null {\n if (!last) return null;\n if (Date.now() - last.timestamp > maxAgeMs) {\n last = null;\n return null;\n }\n return last;\n}\n\n/**\n * Releases the stored DOM element immediately to facilitate garbage collection.\n */\nexport function clearLastUserInteraction(): void {\n last = null;\n}\n\n/**\n * Installs interaction tracking with reference counting.\n * Returns an unsubscribe callback that removes the window listener once all providers unmount.\n */\nexport function installInteractionMemory(): () => void {\n if (typeof window === 'undefined') return () => undefined;\n\n activeRefCount += 1;\n if (!clickListener) {\n clickListener = (event: MouseEvent) => {\n const target = elementFrom(event.target);\n if (!target) return;\n last = { targetElement: target, timestamp: Date.now() };\n };\n window.addEventListener('click', clickListener, { capture: true, passive: true });\n }\n\n let unsubscribed = false;\n return () => {\n if (unsubscribed) return;\n unsubscribed = true;\n activeRefCount = Math.max(0, activeRefCount - 1);\n if (activeRefCount === 0 && clickListener) {\n window.removeEventListener('click', clickListener, { capture: true });\n clickListener = null;\n last = null;\n }\n };\n}\n\nexport function resetInteractionMemoryForTests(): void {\n if (clickListener && typeof window !== 'undefined') {\n window.removeEventListener('click', clickListener, { capture: true });\n }\n clickListener = null;\n activeRefCount = 0;\n last = null;\n}\n","import { Askdepth } from '@askdepth/core';\nimport { PAGE_VIEW_EVENT } from './constants.js';\n\nlet activeRefCount = 0;\nlet restore: (() => void) | null = null;\nlet pageViewNotify: (() => void) | null = null;\nlet unsubscribeConsent: (() => void) | null = null;\nlet initialPageViewPending = false;\n\nconst MAX_INPUT_PATH_LENGTH = 4_096;\nconst MAX_PATH_SEGMENTS = 12;\nconst STATIC_ROUTE_SEGMENTS = new Set([\n 'about', 'account', 'admin', 'api', 'app', 'auth', 'billing', 'blog', 'cart',\n 'checkout', 'contact', 'dashboard', 'docs', 'home', 'login', 'logout',\n 'orders', 'pricing', 'products', 'profile', 'search', 'settings', 'signup',\n 'support', 'users', 'v1',\n]);\n\nexport function currentUrl(): string {\n const pathname = window.location.pathname || '/';\n const bounded = pathname.slice(0, MAX_INPUT_PATH_LENGTH);\n const segments = bounded.split('/').filter(Boolean);\n const safe = segments.slice(0, MAX_PATH_SEGMENTS).map((segment) =>\n STATIC_ROUTE_SEGMENTS.has(segment) ? segment : ':redacted',\n );\n if (pathname.length > MAX_INPUT_PATH_LENGTH || segments.length > MAX_PATH_SEGMENTS) {\n safe.push(':truncated');\n }\n return safe.length > 0 ? `/${safe.join('/')}` : '/';\n}\n\n/**\n * Starts automatic SPA route tracking.\n * Returns an unsubscription function that cleans up history overrides and listeners\n * when all providers unmount.\n */\nexport function startPageViews(): () => void {\n if (typeof window === 'undefined' || typeof window.history?.pushState !== 'function') {\n return () => undefined;\n }\n\n activeRefCount += 1;\n\n if (!restore) {\n const notify = () => {\n if (activeRefCount > 0) {\n Askdepth.track(PAGE_VIEW_EVENT, { url: currentUrl() });\n }\n };\n pageViewNotify = notify;\n\n // Emit initial page view on mount\n initialPageViewPending = !Askdepth.isInitialized();\n notify();\n\n const currentPushState = window.history.pushState;\n const currentReplaceState = window.history.replaceState;\n\n const originalPushState =\n ((currentPushState as unknown as { __askdepth_original__?: History['pushState'] }).__askdepth_original__) ??\n currentPushState;\n const originalReplaceState =\n ((currentReplaceState as unknown as { __askdepth_original__?: History['replaceState'] }).__askdepth_original__) ??\n currentReplaceState;\n\n const isPushWrapped = Boolean(\n (currentPushState as unknown as { __askdepth_page_view__?: boolean }).__askdepth_page_view__,\n );\n const isReplaceWrapped = Boolean(\n (currentReplaceState as unknown as { __askdepth_page_view__?: boolean }).__askdepth_page_view__,\n );\n\n const wrap = (original: History['pushState']) => {\n const fn = function (this: History, ...args: Parameters<History['pushState']>) {\n const result = original.apply(this, args);\n notify();\n return result;\n };\n (fn as unknown as { __askdepth_original__: History['pushState']; __askdepth_page_view__: boolean }).__askdepth_original__ = original;\n (fn as unknown as { __askdepth_page_view__: boolean }).__askdepth_page_view__ = true;\n return fn;\n };\n\n const wrappedPushState = isPushWrapped ? currentPushState : wrap(originalPushState);\n const wrappedReplaceState = isReplaceWrapped ? currentReplaceState : wrap(originalReplaceState);\n\n if (!isPushWrapped) {\n window.history.pushState = wrappedPushState;\n }\n if (!isReplaceWrapped) {\n window.history.replaceState = wrappedReplaceState;\n }\n restore = () => {\n // A replay or router wrapper may still sit above ours. Keep our wrapper so a remount can reuse it.\n if (window.history.pushState !== wrappedPushState || window.history.replaceState !== wrappedReplaceState) return;\n window.history.pushState = originalPushState;\n window.history.replaceState = originalReplaceState;\n restore = null;\n pageViewNotify = null;\n initialPageViewPending = false;\n };\n }\n\n if (activeRefCount === 1 && pageViewNotify) {\n window.addEventListener('popstate', pageViewNotify);\n unsubscribeConsent = Askdepth.onConsentChange((consent) => {\n if (consent === 'granted' && initialPageViewPending) {\n initialPageViewPending = false;\n pageViewNotify?.();\n }\n });\n }\n\n let unsubscribed = false;\n return () => {\n if (unsubscribed) return;\n unsubscribed = true;\n activeRefCount = Math.max(0, activeRefCount - 1);\n if (activeRefCount === 0) {\n if (pageViewNotify) window.removeEventListener('popstate', pageViewNotify);\n unsubscribeConsent?.();\n unsubscribeConsent = null;\n restore?.();\n }\n };\n}\n\nexport function resetPageViewsForTests(): void {\n if (pageViewNotify && typeof window !== 'undefined') window.removeEventListener('popstate', pageViewNotify);\n unsubscribeConsent?.();\n const currentPush = typeof window !== 'undefined' ? window.history?.pushState : undefined;\n const currentReplace = typeof window !== 'undefined' ? window.history?.replaceState : undefined;\n const origPush = (currentPush as unknown as { __askdepth_original__?: History['pushState'] })?.__askdepth_original__;\n const origReplace = (currentReplace as unknown as { __askdepth_original__?: History['replaceState'] })?.__askdepth_original__;\n restore?.();\n if (origPush && typeof window !== 'undefined' && window.history) {\n window.history.pushState = origPush;\n }\n if (origReplace && typeof window !== 'undefined' && window.history) {\n window.history.replaceState = origReplace;\n }\n activeRefCount = 0;\n restore = null;\n pageViewNotify = null;\n unsubscribeConsent = null;\n initialPageViewPending = false;\n}\n","'use client';\n\nimport { Askdepth, type AskdepthInitOptions } from '@askdepth/core';\nimport React, { createContext, useEffect, useMemo, useRef, useState } from 'react';\nimport { resolveComponentLocation } from './fiber.js';\nimport { installInteractionMemory } from './interaction.js';\nimport { startPageViews } from './page-view.js';\nimport type { AskdepthContextValue, AskdepthProviderProps } from './types.js';\n\nexport const AskdepthContext = createContext<AskdepthContextValue | null>(null);\n\nconst noopContext: AskdepthContextValue = {\n track: () => undefined,\n identify: () => undefined,\n getTraceparent: () => null,\n isReady: () => false,\n getSessionId: () => null,\n};\n\nexport function getNoopAskdepth(): AskdepthContextValue {\n return noopContext;\n}\n\nexport const AskdepthProvider: React.FC<AskdepthProviderProps> = (props) => {\n const { children, apiKey, writeKey: propWriteKey, ...restOptions } = props;\n const writeKey = propWriteKey ?? apiKey ?? '';\n const options: AskdepthInitOptions = {\n ...restOptions,\n writeKey,\n };\n const key = JSON.stringify(options);\n const stable = useMemo(() => options, [key]);\n const booted = useRef<string | null>(null);\n const [initializedKey, setInitializedKey] = useState<string | null>(null);\n\n useEffect(() => {\n if (typeof window === 'undefined') return;\n if (booted.current !== key) {\n Askdepth.init(stable);\n booted.current = key;\n setInitializedKey(key);\n }\n const unbindResolver = Askdepth.registerComponentResolver(resolveComponentLocation);\n const unbindInteraction = installInteractionMemory();\n const unbindPageViews = startPageViews();\n return () => {\n unbindResolver();\n unbindInteraction();\n unbindPageViews();\n };\n }, [key, stable]);\n\n const value = useMemo<AskdepthContextValue>(\n () => ({\n track: (name, properties) => {\n if (properties === undefined) Askdepth.track(name);\n else Askdepth.track(name, properties);\n },\n identify: (userId, traits) => {\n if (traits === undefined) Askdepth.identify(userId);\n else Askdepth.identify(userId, traits);\n },\n getTraceparent: () => Askdepth.getTraceparent(),\n isReady: () => Askdepth.isInitialized(),\n getSessionId: () => Askdepth.getSessionId(),\n }),\n [initializedKey],\n );\n\n return <AskdepthContext.Provider value={value}>{children}</AskdepthContext.Provider>;\n};\n\nAskdepthProvider.displayName = 'AskdepthProvider';\n","'use client';\n\nimport { useContext } from 'react';\nimport { AskdepthContext, getNoopAskdepth } from '../provider.js';\nimport type { AskdepthContextValue } from '../types.js';\n\nexport function useAskdepth(): AskdepthContextValue {\n return useContext(AskdepthContext) ?? getNoopAskdepth();\n}\n","'use client';\n\nimport { Askdepth } from '@askdepth/core';\nimport React, { Component, type ErrorInfo, type ReactNode } from 'react';\nimport { clearLastUserInteraction, getLastUserInteraction } from '../interaction.js';\nimport type { AskdepthFallback } from '../types.js';\n\ninterface Props {\n children?: ReactNode;\n fallback?: AskdepthFallback;\n}\n\ninterface State {\n hasError: boolean;\n error: Error | null;\n}\n\nexport class AskdepthCatch extends Component<Props, State> {\n public static displayName = 'AskdepthCatch';\n private reportTimer: ReturnType<typeof setTimeout> | null = null;\n\n public override state: State = {\n hasError: false,\n error: null,\n };\n\n public static getDerivedStateFromError(error: Error): State {\n return { hasError: true, error };\n }\n\n public override componentDidCatch(error: Error, info: ErrorInfo): void {\n const target = getLastUserInteraction(500)?.targetElement ?? null;\n const componentStack = info.componentStack ?? undefined;\n if (Askdepth.isInitialized()) {\n Askdepth.reportCaughtError(error, target, componentStack);\n } else {\n if (this.reportTimer) clearTimeout(this.reportTimer);\n this.reportTimer = setTimeout(() => {\n this.reportTimer = null;\n Askdepth.reportCaughtError(error, target, componentStack);\n }, 0);\n }\n clearLastUserInteraction();\n }\n\n public override componentWillUnmount(): void {\n if (this.reportTimer) clearTimeout(this.reportTimer);\n }\n\n private resetErrorBoundary = (): void => {\n this.setState({ hasError: false, error: null });\n };\n\n public override render(): ReactNode {\n if (this.state.hasError && this.state.error) {\n const { fallback } = this.props;\n if (typeof fallback === 'function') return fallback(this.state.error, this.resetErrorBoundary);\n if (fallback !== undefined) return fallback;\n return (\n <div role=\"alert\" style={{ padding: '16px', border: '1px solid #EF4444', borderRadius: '6px' }}>\n <h2>Something went wrong</h2>\n <p>Please try again.</p>\n <button type=\"button\" onClick={this.resetErrorBoundary}>\n Try again\n </button>\n </div>\n );\n }\n return this.props.children;\n }\n}\n"]}
@@ -0,0 +1,63 @@
1
+ import React, { ReactNode, Component, ErrorInfo } from 'react';
2
+ import { AskdepthInitOptions } from '@askdepth/core';
3
+ export { AskdepthInitOptions, ConsentState } from '@askdepth/core';
4
+
5
+ interface AskdepthContextValue {
6
+ track: (name: string, properties?: Record<string, unknown>) => void;
7
+ identify: (userId: string, traits?: Record<string, unknown>) => void;
8
+ getTraceparent: () => string | null;
9
+ isReady: () => boolean;
10
+ getSessionId: () => string | null;
11
+ }
12
+ type BaseProviderProps = Omit<AskdepthInitOptions, 'writeKey'> & {
13
+ children?: ReactNode;
14
+ };
15
+ type ProviderWithWriteKey = BaseProviderProps & {
16
+ /** Project write key */
17
+ writeKey: string;
18
+ /** Alias for writeKey */
19
+ apiKey?: string;
20
+ };
21
+ type ProviderWithApiKey = BaseProviderProps & {
22
+ /** Project write key */
23
+ writeKey?: string;
24
+ /** Alias for writeKey */
25
+ apiKey: string;
26
+ };
27
+ type AskdepthProviderProps = ProviderWithWriteKey | ProviderWithApiKey;
28
+ interface ResolvedComponentLocation {
29
+ componentName: string;
30
+ /** Innermost composite component first. */
31
+ componentStack: string[];
32
+ sourceAttr?: string;
33
+ hashId?: string;
34
+ }
35
+ type AskdepthFallback = ReactNode | ((error: Error, reset: () => void) => ReactNode);
36
+
37
+ declare const AskdepthContext: React.Context<AskdepthContextValue | null>;
38
+ declare const AskdepthProvider: React.FC<AskdepthProviderProps>;
39
+
40
+ declare function useAskdepth(): AskdepthContextValue;
41
+
42
+ interface Props {
43
+ children?: ReactNode;
44
+ fallback?: AskdepthFallback;
45
+ }
46
+ interface State {
47
+ hasError: boolean;
48
+ error: Error | null;
49
+ }
50
+ declare class AskdepthCatch extends Component<Props, State> {
51
+ static displayName: string;
52
+ private reportTimer;
53
+ state: State;
54
+ static getDerivedStateFromError(error: Error): State;
55
+ componentDidCatch(error: Error, info: ErrorInfo): void;
56
+ componentWillUnmount(): void;
57
+ private resetErrorBoundary;
58
+ render(): ReactNode;
59
+ }
60
+
61
+ declare function resolveComponentLocation(target: Element): ResolvedComponentLocation | null;
62
+
63
+ export { AskdepthCatch, AskdepthContext, type AskdepthContextValue, type AskdepthFallback, AskdepthProvider, type AskdepthProviderProps, type ResolvedComponentLocation, resolveComponentLocation, useAskdepth };