@guidelytech/react 0.15.0 → 0.17.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/dist/index.d.cts CHANGED
@@ -1,9 +1,9 @@
1
1
  import * as react from 'react';
2
- import { ReactNode } from 'react';
2
+ import { ReactNode, Component, ErrorInfo, ComponentType } from 'react';
3
3
  import { JsonValue, FlagsClientOptions, FlagsBootstrap, FlagsClient, FlagValue, FlagDetails, Attributes } from '@guidelytech/flags';
4
4
  export { Attributes, EvaluationResult, FlagDetails, FlagsBootstrap, FlagsClient, FlagsClientOptions, FlagsPayload, JsonValue } from '@guidelytech/flags';
5
- import { PublishedGuide, GuidelyOptions, GuidelyUser, GuidelyClient, ChecklistProgressState, GuidelyEvents } from '@guidelytech/sdk-core';
6
- export { AgentTurnInput, AgentTurnRedactor, ChecklistProgressState, GuidelyClient, GuidelyEvents, GuidelyOptions, GuidelyUser, PublishedGuide } from '@guidelytech/sdk-core';
5
+ import { CaptureContext, ErrorLevelName, GuidelyClient, PublishedGuide, GuidelyOptions, GuidelyUser, ChecklistProgressState, GuidelyEvents } from '@guidelytech/sdk-core';
6
+ export { AgentTurnInput, AgentTurnRedactor, Breadcrumb, CaptureContext, ChecklistProgressState, ErrorEvent, ErrorLevelName, ErrorMonitoringOptions, ExceptionDetail, GuidelyClient, GuidelyEvents, GuidelyOptions, GuidelyUser, PublishedGuide } from '@guidelytech/sdk-core';
7
7
 
8
8
  /** Is the boolean flag on? `fallback` (default `false`) until flags load, or when missing. */
9
9
  declare function useFlag(key: string, fallback?: boolean): boolean;
@@ -51,6 +51,101 @@ interface FlagsProviderProps extends Omit<FlagsClientOptions, "payload"> {
51
51
  */
52
52
  declare function FlagsProvider({ children, client: external, payload, ...options }: FlagsProviderProps): react.JSX.Element;
53
53
 
54
+ /** `captureException`'s second argument. */
55
+ type Hint = CaptureContext & Record<string, unknown>;
56
+ interface ErrorBoundaryFallbackProps {
57
+ error: unknown;
58
+ componentStack: string;
59
+ /** The Guidely event id ("" when nothing was sent: error tracking off, no consent, filtered). */
60
+ eventId: string;
61
+ /** Clears the error and renders the children again. */
62
+ resetError(): void;
63
+ }
64
+ interface GuidelyErrorBoundaryProps {
65
+ children?: ReactNode;
66
+ /** Rendered instead of the children after an error (an element, or a function of the error). Nothing is rendered without one. */
67
+ fallback?: ReactNode | ((props: ErrorBoundaryFallbackProps) => ReactNode);
68
+ /** Called after the error is reported (`eventId` is "" when it waits for the provider's client, or was not sent). */
69
+ onError?: (error: unknown, componentStack: string, eventId: string) => void;
70
+ /** Edit what is sent (`context.tags.area = "checkout"`), like Sentry's `beforeCapture(scope, …)`. */
71
+ beforeCapture?: (context: CaptureContext, error: unknown, componentStack: string) => void;
72
+ /** Called by `resetError()`, before the children render again. */
73
+ onReset?: (error: unknown, componentStack: string, eventId: string) => void;
74
+ /** Opens the bug-report dialog for the event, when this SDK version has one. */
75
+ showDialog?: boolean;
76
+ tags?: CaptureContext["tags"];
77
+ extra?: CaptureContext["extra"];
78
+ fingerprint?: string[];
79
+ /** Default `error`. */
80
+ level?: ErrorLevelName;
81
+ /** Marks the error handled (default: true when a `fallback` is given, as Sentry does). */
82
+ handled?: boolean;
83
+ /** The client to report to (default: the `GuidelyProvider`'s, else the live `createGuidely()` client). */
84
+ client?: GuidelyClient | null;
85
+ }
86
+ interface BoundaryState {
87
+ error: unknown;
88
+ componentStack: string;
89
+ eventId: string;
90
+ }
91
+ /**
92
+ * Catches render errors in its children, reports them (`mechanism: react.errorboundary`) and
93
+ * renders `fallback`. Works without a provider when a client was made with `createGuidely()`.
94
+ *
95
+ * ```tsx
96
+ * <GuidelyErrorBoundary fallback={({ resetError }) => <button onClick={resetError}>Try again</button>} tags={{ area: "checkout" }}>
97
+ * <Checkout />
98
+ * </GuidelyErrorBoundary>
99
+ * ```
100
+ */
101
+ declare class GuidelyErrorBoundary extends Component<GuidelyErrorBoundaryProps, BoundaryState & {
102
+ failed: boolean;
103
+ }> {
104
+ static contextType: react.Context<GuidelyClient | null>;
105
+ context: GuidelyClient | null;
106
+ state: {
107
+ failed: boolean;
108
+ error: unknown;
109
+ componentStack: string;
110
+ eventId: string;
111
+ };
112
+ static getDerivedStateFromError(error: unknown): Partial<BoundaryState & {
113
+ failed: boolean;
114
+ }>;
115
+ componentDidCatch(error: unknown, info: ErrorInfo): void;
116
+ resetError: () => void;
117
+ render(): ReactNode;
118
+ }
119
+ /** Wraps a component in a `GuidelyErrorBoundary` (Sentry's `withErrorBoundary`). */
120
+ declare function withGuidelyErrorBoundary<P extends object>(Wrapped: ComponentType<P>, options?: Omit<GuidelyErrorBoundaryProps, "children">): ComponentType<P>;
121
+ /**
122
+ * Reports `error` once (per error object) when it is set: for error pages that receive the error as
123
+ * a prop, such as Next.js `error.tsx` or React Router's `errorElement`. Returns the event id.
124
+ */
125
+ declare function useCaptureException(error: unknown, hint?: Hint): string;
126
+ /** What React 19 passes to `onUncaughtError` / `onCaughtError` / `onRecoverableError`. */
127
+ interface ReactErrorInfo {
128
+ componentStack?: string | null;
129
+ /** `onCaughtError` only: the boundary that caught the error. */
130
+ errorBoundary?: unknown;
131
+ }
132
+ /**
133
+ * React 19 root error hooks (Sentry's `reactErrorHandler`):
134
+ *
135
+ * ```ts
136
+ * createRoot(el, {
137
+ * onUncaughtError: guidelyReactErrorHandler(),
138
+ * onCaughtError: guidelyReactErrorHandler(),
139
+ * onRecoverableError: guidelyReactErrorHandler(),
140
+ * });
141
+ * ```
142
+ *
143
+ * Errors caught by a boundary are reported as handled; errors a `GuidelyErrorBoundary` caught are
144
+ * left to it. The client defaults to the live `createGuidely()` / provider client at the time of
145
+ * the error. `callback` replaces React's default logging (the error is `console.error`ed without one).
146
+ */
147
+ declare function guidelyReactErrorHandler(client?: GuidelyClient | null, callback?: (error: unknown, errorInfo: ReactErrorInfo, eventId: string) => void): (error: unknown, errorInfo?: ReactErrorInfo) => void;
148
+
54
149
  interface GuidelyProviderProps extends Omit<GuidelyOptions, "user"> {
55
150
  /** Identify this user as soon as the client is ready; `undefined` resets the identity. */
56
151
  user?: GuidelyUser | null;
@@ -91,4 +186,4 @@ interface GuideState {
91
186
  /** Live state of a guide (by id or key): active, completed, current step. */
92
187
  declare function useGuideState(idOrKey: string): GuideState;
93
188
 
94
- export { Feature, FeatureFlag, type FeatureProps, FeatureValue, type FeatureValueProps, FlagsProvider, type FlagsProviderProps, type GuideState, GuidelyProvider, type GuidelyProviderProps, noopClient, useChecklistProgress, useFeatureValue, useFlag, useFlagDetails, useFlags, useFlagsClient, useFlagsReady, useGuideState, useGuidely, useGuidelyEvent, useGuidelyIdentify, useGuidelyReady };
189
+ export { type ErrorBoundaryFallbackProps, Feature, FeatureFlag, type FeatureProps, FeatureValue, type FeatureValueProps, FlagsProvider, type FlagsProviderProps, type GuideState, GuidelyErrorBoundary, type GuidelyErrorBoundaryProps, GuidelyProvider, type GuidelyProviderProps, type ReactErrorInfo, guidelyReactErrorHandler, noopClient, useCaptureException, useChecklistProgress, useFeatureValue, useFlag, useFlagDetails, useFlags, useFlagsClient, useFlagsReady, useGuideState, useGuidely, useGuidelyEvent, useGuidelyIdentify, useGuidelyReady, withGuidelyErrorBoundary };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import * as react from 'react';
2
- import { ReactNode } from 'react';
2
+ import { ReactNode, Component, ErrorInfo, ComponentType } from 'react';
3
3
  import { JsonValue, FlagsClientOptions, FlagsBootstrap, FlagsClient, FlagValue, FlagDetails, Attributes } from '@guidelytech/flags';
4
4
  export { Attributes, EvaluationResult, FlagDetails, FlagsBootstrap, FlagsClient, FlagsClientOptions, FlagsPayload, JsonValue } from '@guidelytech/flags';
5
- import { PublishedGuide, GuidelyOptions, GuidelyUser, GuidelyClient, ChecklistProgressState, GuidelyEvents } from '@guidelytech/sdk-core';
6
- export { AgentTurnInput, AgentTurnRedactor, ChecklistProgressState, GuidelyClient, GuidelyEvents, GuidelyOptions, GuidelyUser, PublishedGuide } from '@guidelytech/sdk-core';
5
+ import { CaptureContext, ErrorLevelName, GuidelyClient, PublishedGuide, GuidelyOptions, GuidelyUser, ChecklistProgressState, GuidelyEvents } from '@guidelytech/sdk-core';
6
+ export { AgentTurnInput, AgentTurnRedactor, Breadcrumb, CaptureContext, ChecklistProgressState, ErrorEvent, ErrorLevelName, ErrorMonitoringOptions, ExceptionDetail, GuidelyClient, GuidelyEvents, GuidelyOptions, GuidelyUser, PublishedGuide } from '@guidelytech/sdk-core';
7
7
 
8
8
  /** Is the boolean flag on? `fallback` (default `false`) until flags load, or when missing. */
9
9
  declare function useFlag(key: string, fallback?: boolean): boolean;
@@ -51,6 +51,101 @@ interface FlagsProviderProps extends Omit<FlagsClientOptions, "payload"> {
51
51
  */
52
52
  declare function FlagsProvider({ children, client: external, payload, ...options }: FlagsProviderProps): react.JSX.Element;
53
53
 
54
+ /** `captureException`'s second argument. */
55
+ type Hint = CaptureContext & Record<string, unknown>;
56
+ interface ErrorBoundaryFallbackProps {
57
+ error: unknown;
58
+ componentStack: string;
59
+ /** The Guidely event id ("" when nothing was sent: error tracking off, no consent, filtered). */
60
+ eventId: string;
61
+ /** Clears the error and renders the children again. */
62
+ resetError(): void;
63
+ }
64
+ interface GuidelyErrorBoundaryProps {
65
+ children?: ReactNode;
66
+ /** Rendered instead of the children after an error (an element, or a function of the error). Nothing is rendered without one. */
67
+ fallback?: ReactNode | ((props: ErrorBoundaryFallbackProps) => ReactNode);
68
+ /** Called after the error is reported (`eventId` is "" when it waits for the provider's client, or was not sent). */
69
+ onError?: (error: unknown, componentStack: string, eventId: string) => void;
70
+ /** Edit what is sent (`context.tags.area = "checkout"`), like Sentry's `beforeCapture(scope, …)`. */
71
+ beforeCapture?: (context: CaptureContext, error: unknown, componentStack: string) => void;
72
+ /** Called by `resetError()`, before the children render again. */
73
+ onReset?: (error: unknown, componentStack: string, eventId: string) => void;
74
+ /** Opens the bug-report dialog for the event, when this SDK version has one. */
75
+ showDialog?: boolean;
76
+ tags?: CaptureContext["tags"];
77
+ extra?: CaptureContext["extra"];
78
+ fingerprint?: string[];
79
+ /** Default `error`. */
80
+ level?: ErrorLevelName;
81
+ /** Marks the error handled (default: true when a `fallback` is given, as Sentry does). */
82
+ handled?: boolean;
83
+ /** The client to report to (default: the `GuidelyProvider`'s, else the live `createGuidely()` client). */
84
+ client?: GuidelyClient | null;
85
+ }
86
+ interface BoundaryState {
87
+ error: unknown;
88
+ componentStack: string;
89
+ eventId: string;
90
+ }
91
+ /**
92
+ * Catches render errors in its children, reports them (`mechanism: react.errorboundary`) and
93
+ * renders `fallback`. Works without a provider when a client was made with `createGuidely()`.
94
+ *
95
+ * ```tsx
96
+ * <GuidelyErrorBoundary fallback={({ resetError }) => <button onClick={resetError}>Try again</button>} tags={{ area: "checkout" }}>
97
+ * <Checkout />
98
+ * </GuidelyErrorBoundary>
99
+ * ```
100
+ */
101
+ declare class GuidelyErrorBoundary extends Component<GuidelyErrorBoundaryProps, BoundaryState & {
102
+ failed: boolean;
103
+ }> {
104
+ static contextType: react.Context<GuidelyClient | null>;
105
+ context: GuidelyClient | null;
106
+ state: {
107
+ failed: boolean;
108
+ error: unknown;
109
+ componentStack: string;
110
+ eventId: string;
111
+ };
112
+ static getDerivedStateFromError(error: unknown): Partial<BoundaryState & {
113
+ failed: boolean;
114
+ }>;
115
+ componentDidCatch(error: unknown, info: ErrorInfo): void;
116
+ resetError: () => void;
117
+ render(): ReactNode;
118
+ }
119
+ /** Wraps a component in a `GuidelyErrorBoundary` (Sentry's `withErrorBoundary`). */
120
+ declare function withGuidelyErrorBoundary<P extends object>(Wrapped: ComponentType<P>, options?: Omit<GuidelyErrorBoundaryProps, "children">): ComponentType<P>;
121
+ /**
122
+ * Reports `error` once (per error object) when it is set: for error pages that receive the error as
123
+ * a prop, such as Next.js `error.tsx` or React Router's `errorElement`. Returns the event id.
124
+ */
125
+ declare function useCaptureException(error: unknown, hint?: Hint): string;
126
+ /** What React 19 passes to `onUncaughtError` / `onCaughtError` / `onRecoverableError`. */
127
+ interface ReactErrorInfo {
128
+ componentStack?: string | null;
129
+ /** `onCaughtError` only: the boundary that caught the error. */
130
+ errorBoundary?: unknown;
131
+ }
132
+ /**
133
+ * React 19 root error hooks (Sentry's `reactErrorHandler`):
134
+ *
135
+ * ```ts
136
+ * createRoot(el, {
137
+ * onUncaughtError: guidelyReactErrorHandler(),
138
+ * onCaughtError: guidelyReactErrorHandler(),
139
+ * onRecoverableError: guidelyReactErrorHandler(),
140
+ * });
141
+ * ```
142
+ *
143
+ * Errors caught by a boundary are reported as handled; errors a `GuidelyErrorBoundary` caught are
144
+ * left to it. The client defaults to the live `createGuidely()` / provider client at the time of
145
+ * the error. `callback` replaces React's default logging (the error is `console.error`ed without one).
146
+ */
147
+ declare function guidelyReactErrorHandler(client?: GuidelyClient | null, callback?: (error: unknown, errorInfo: ReactErrorInfo, eventId: string) => void): (error: unknown, errorInfo?: ReactErrorInfo) => void;
148
+
54
149
  interface GuidelyProviderProps extends Omit<GuidelyOptions, "user"> {
55
150
  /** Identify this user as soon as the client is ready; `undefined` resets the identity. */
56
151
  user?: GuidelyUser | null;
@@ -91,4 +186,4 @@ interface GuideState {
91
186
  /** Live state of a guide (by id or key): active, completed, current step. */
92
187
  declare function useGuideState(idOrKey: string): GuideState;
93
188
 
94
- export { Feature, FeatureFlag, type FeatureProps, FeatureValue, type FeatureValueProps, FlagsProvider, type FlagsProviderProps, type GuideState, GuidelyProvider, type GuidelyProviderProps, noopClient, useChecklistProgress, useFeatureValue, useFlag, useFlagDetails, useFlags, useFlagsClient, useFlagsReady, useGuideState, useGuidely, useGuidelyEvent, useGuidelyIdentify, useGuidelyReady };
189
+ export { type ErrorBoundaryFallbackProps, Feature, FeatureFlag, type FeatureProps, FeatureValue, type FeatureValueProps, FlagsProvider, type FlagsProviderProps, type GuideState, GuidelyErrorBoundary, type GuidelyErrorBoundaryProps, GuidelyProvider, type GuidelyProviderProps, type ReactErrorInfo, guidelyReactErrorHandler, noopClient, useCaptureException, useChecklistProgress, useFeatureValue, useFlag, useFlagDetails, useFlags, useFlagsClient, useFlagsReady, useGuideState, useGuidely, useGuidelyEvent, useGuidelyIdentify, useGuidelyReady, withGuidelyErrorBoundary };
package/dist/index.js CHANGED
@@ -1,19 +1,146 @@
1
1
  "use client";
2
+ var __defProp = Object.defineProperty;
3
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
2
5
 
3
6
  // src/index.tsx
4
7
  import { createStaticFlags as createStaticFlags2, stableStringify as stableStringify2 } from "@guidelytech/flags";
5
8
  import { createGuidely } from "@guidelytech/sdk-core";
6
- import { createContext as createContext2, useContext as useContext2, useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
9
+ import { useContext as useContext3, useEffect as useEffect3, useMemo as useMemo2, useRef as useRef2, useState as useState3 } from "react";
10
+
11
+ // src/context.ts
12
+ import { createContext } from "react";
13
+ var GuidelyContext = createContext(null);
14
+
15
+ // src/errors.tsx
16
+ import { GuidelyClient } from "@guidelytech/sdk-core";
17
+ import { Component, useContext, useEffect, useState, version } from "react";
18
+ import { jsx } from "react/jsx-runtime";
19
+ var reported = /* @__PURE__ */ new WeakSet();
20
+ var stackOf = (info) => (info?.componentStack ?? "").slice(0, 8e3);
21
+ function liveClient(client) {
22
+ try {
23
+ if (client && !client.getState().destroyed) return client;
24
+ const current = GuidelyClient.get();
25
+ return current && !current.getState().destroyed ? current : null;
26
+ } catch {
27
+ return null;
28
+ }
29
+ }
30
+ var pending = [];
31
+ function drainPendingErrors(client) {
32
+ for (const p of pending.splice(0)) {
33
+ let eventId = "";
34
+ try {
35
+ eventId = client.captureException(p.error, p.ctx) || "";
36
+ } catch {
37
+ }
38
+ if (eventId) p.done?.(eventId);
39
+ }
40
+ }
41
+ function capture(client, error, ctx, done) {
42
+ if (error && typeof error === "object") {
43
+ if (reported.has(error)) return "";
44
+ reported.add(error);
45
+ }
46
+ const c = liveClient(client);
47
+ if (!c) {
48
+ if (pending.length < 10) pending.push({ error, ctx, done });
49
+ return "";
50
+ }
51
+ try {
52
+ return c.captureException(error, ctx) || "";
53
+ } catch {
54
+ return "";
55
+ }
56
+ }
57
+ var EMPTY = { error: null, componentStack: "", eventId: "" };
58
+ var GuidelyErrorBoundary = class extends Component {
59
+ constructor() {
60
+ super(...arguments);
61
+ __publicField(this, "state", { ...EMPTY, failed: false });
62
+ __publicField(this, "resetError", () => {
63
+ const { error, componentStack, eventId } = this.state;
64
+ this.props.onReset?.(error, componentStack, eventId);
65
+ this.setState({ ...EMPTY, failed: false });
66
+ });
67
+ }
68
+ static getDerivedStateFromError(error) {
69
+ return { error, failed: true };
70
+ }
71
+ componentDidCatch(error, info) {
72
+ const { tags, extra, fingerprint, level, handled, fallback, beforeCapture, onError, showDialog } = this.props;
73
+ const componentStack = stackOf(info);
74
+ const ctx = {
75
+ level: level ?? "error",
76
+ ...tags ? { tags: { ...tags } } : {},
77
+ ...extra ? { extra: { ...extra } } : {},
78
+ ...fingerprint ? { fingerprint } : {},
79
+ contexts: { react: { version, componentStack } },
80
+ mechanism: { type: "react.errorboundary", handled: handled ?? !!fallback }
81
+ };
82
+ try {
83
+ beforeCapture?.(ctx, error, componentStack);
84
+ } catch {
85
+ }
86
+ const client = this.props.client ?? this.context;
87
+ const eventId = capture(client, error, ctx, (id) => {
88
+ if (this.state.error === error) this.setState({ eventId: id });
89
+ });
90
+ this.setState({ componentStack, eventId });
91
+ onError?.(error, componentStack, eventId);
92
+ if (showDialog && eventId) {
93
+ try {
94
+ liveClient(client)?.showBugReport?.();
95
+ } catch {
96
+ }
97
+ }
98
+ }
99
+ render() {
100
+ if (!this.state.failed) return this.props.children;
101
+ const { fallback } = this.props;
102
+ if (typeof fallback === "function") return fallback({ error: this.state.error, componentStack: this.state.componentStack, eventId: this.state.eventId, resetError: this.resetError });
103
+ return fallback ?? null;
104
+ }
105
+ };
106
+ __publicField(GuidelyErrorBoundary, "contextType", GuidelyContext);
107
+ function withGuidelyErrorBoundary(Wrapped, options = {}) {
108
+ const name = Wrapped.displayName || Wrapped.name || "Component";
109
+ const WithBoundary = (props) => /* @__PURE__ */ jsx(GuidelyErrorBoundary, { ...options, children: /* @__PURE__ */ jsx(Wrapped, { ...props }) });
110
+ WithBoundary.displayName = `guidelyErrorBoundary(${name})`;
111
+ return WithBoundary;
112
+ }
113
+ function useCaptureException(error, hint) {
114
+ const client = useContext(GuidelyContext);
115
+ const [eventId, setEventId] = useState("");
116
+ useEffect(() => {
117
+ if (error === null || error === void 0) return;
118
+ const id = capture(client, error, { ...hint ?? {}, mechanism: hint?.mechanism ?? { type: "react.errorpage", handled: true } }, setEventId);
119
+ if (id) setEventId(id);
120
+ }, [client, error]);
121
+ return eventId;
122
+ }
123
+ function guidelyReactErrorHandler(client, callback) {
124
+ return (error, errorInfo = {}) => {
125
+ let eventId = "";
126
+ if (!(errorInfo.errorBoundary instanceof GuidelyErrorBoundary)) {
127
+ const caught = errorInfo.errorBoundary !== void 0 && errorInfo.errorBoundary !== null;
128
+ eventId = capture(client ?? null, error, { contexts: { react: { version, componentStack: stackOf(errorInfo) } }, mechanism: { type: "react", handled: caught } });
129
+ }
130
+ if (callback) callback(error, errorInfo, eventId);
131
+ else console.error(error);
132
+ };
133
+ }
7
134
 
8
135
  // src/flags.tsx
9
136
  import { createFlagsClient, createStaticFlags, jsonEquals, stableStringify } from "@guidelytech/flags";
10
- import { createContext, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
11
- import { Fragment, jsx } from "react/jsx-runtime";
12
- var FlagsContext = createContext(null);
13
- var EMPTY = createStaticFlags();
137
+ import { createContext as createContext2, useContext as useContext2, useEffect as useEffect2, useMemo, useRef, useState as useState2, useSyncExternalStore } from "react";
138
+ import { Fragment, jsx as jsx2 } from "react/jsx-runtime";
139
+ var FlagsContext = createContext2(null);
140
+ var EMPTY2 = createStaticFlags();
14
141
  function useReader() {
15
- const src = useContext(FlagsContext);
16
- return src?.client ?? src?.bootstrap ?? EMPTY;
142
+ const src = useContext2(FlagsContext);
143
+ return src?.client ?? src?.bootstrap ?? EMPTY2;
17
144
  }
18
145
  function useFlagsValue(select) {
19
146
  const reader = useReader();
@@ -43,29 +170,29 @@ function useFlagsReady() {
43
170
  return useFlagsValue((r) => r.isReady());
44
171
  }
45
172
  function useFlagsClient() {
46
- return useContext(FlagsContext)?.client ?? null;
173
+ return useContext2(FlagsContext)?.client ?? null;
47
174
  }
48
175
  function Feature({ flag, children, fallback = null }) {
49
- return /* @__PURE__ */ jsx(Fragment, { children: useFlag(flag) ? children : fallback });
176
+ return /* @__PURE__ */ jsx2(Fragment, { children: useFlag(flag) ? children : fallback });
50
177
  }
51
178
  var FeatureFlag = Feature;
52
179
  function FeatureValue({ flag, value, children, fallback = null }) {
53
180
  const current = useFeatureValue(flag, null);
54
- return /* @__PURE__ */ jsx(Fragment, { children: jsonEquals(current, value) ? children : fallback });
181
+ return /* @__PURE__ */ jsx2(Fragment, { children: jsonEquals(current, value) ? children : fallback });
55
182
  }
56
183
  function useBootstrap(payload, attributes) {
57
184
  const key = stableStringify(attributes);
58
- return useMemo(() => payload ? createStaticFlags({ payload, attributes }) : EMPTY, [payload, key]);
185
+ return useMemo(() => payload ? createStaticFlags({ payload, attributes }) : EMPTY2, [payload, key]);
59
186
  }
60
187
  function FlagsProvider({ children, client: external, payload, ...options }) {
61
- const [created, setCreated] = useState(null);
188
+ const [created, setCreated] = useState2(null);
62
189
  const optionsRef = useRef(options);
63
190
  optionsRef.current = options;
64
191
  const sdkKey = options.sdkKey ?? options.projectId;
65
192
  const { apiUrl, environment } = options;
66
193
  const payloadRef = useRef(payload);
67
194
  payloadRef.current = payload;
68
- useEffect(() => {
195
+ useEffect2(() => {
69
196
  if (external || !sdkKey || typeof window === "undefined") return;
70
197
  let c;
71
198
  try {
@@ -83,23 +210,22 @@ function FlagsProvider({ children, client: external, payload, ...options }) {
83
210
  const client = external ?? created;
84
211
  const attributes = options.attributes ?? {};
85
212
  const attrsKey = stableStringify(attributes);
86
- useEffect(() => {
213
+ useEffect2(() => {
87
214
  if (client && options.attributes) client.setAttributes(options.attributes);
88
215
  }, [client, attrsKey]);
89
216
  const bootstrap = useBootstrap(payload, attributes);
90
217
  const value = useMemo(() => ({ client, bootstrap }), [client, bootstrap]);
91
- return /* @__PURE__ */ jsx(FlagsContext.Provider, { value, children });
218
+ return /* @__PURE__ */ jsx2(FlagsContext.Provider, { value, children });
92
219
  }
93
220
 
94
221
  // src/index.tsx
95
- import { jsx as jsx2 } from "react/jsx-runtime";
96
- var GuidelyContext = createContext2(null);
222
+ import { jsx as jsx3 } from "react/jsx-runtime";
97
223
  function userAttributes(user) {
98
224
  if (!user?.id) return {};
99
225
  return { ...user.traits ?? {}, id: user.id, ...user.account ? { account: { ...user.account.traits ?? {}, id: user.account.id } } : {} };
100
226
  }
101
227
  function GuidelyProvider({ children, user, flagsPayload, flagAttributes, ...options }) {
102
- const [client, setClient] = useState2(null);
228
+ const [client, setClient] = useState3(null);
103
229
  const optionsRef = useRef2(options);
104
230
  optionsRef.current = options;
105
231
  const userRef = useRef2(user);
@@ -112,22 +238,23 @@ function GuidelyProvider({ children, user, flagsPayload, flagAttributes, ...opti
112
238
  const appAttributesRef = useRef2(appAttributes);
113
239
  appAttributesRef.current = appAttributes;
114
240
  const { projectId, environment, apiUrl } = options;
115
- useEffect2(() => {
241
+ useEffect3(() => {
116
242
  if (typeof window === "undefined" || !projectId) return;
117
243
  const o = optionsRef.current;
118
244
  const c = createGuidely({ ...o, projectId, environment, apiUrl, user: userRef.current?.id ? userRef.current : void 0, flags: o.flags === false ? false : { ...o.flags ?? {}, payload: payloadRef.current ?? void 0, attributes: appAttributesRef.current } });
119
245
  setClient(c);
246
+ drainPendingErrors(c);
120
247
  return () => {
121
248
  c.destroy();
122
249
  setClient((cur) => cur === c ? null : cur);
123
250
  };
124
251
  }, [projectId, environment, apiUrl]);
125
- useEffect2(() => {
252
+ useEffect3(() => {
126
253
  client?.flags.setAttributes(appAttributes);
127
254
  }, [client, appAttributes]);
128
255
  const userKey = user ? JSON.stringify([user.id, user.traits ?? null, user.account ?? null]) : "";
129
256
  const hadUser = useRef2(false);
130
- useEffect2(() => {
257
+ useEffect3(() => {
131
258
  if (!client) return;
132
259
  if (user && user.id) {
133
260
  hadUser.current = true;
@@ -139,7 +266,7 @@ function GuidelyProvider({ children, user, flagsPayload, flagAttributes, ...opti
139
266
  }, [client, userKey]);
140
267
  const bootstrap = useBootstrap(payload, { ...userAttributes(user), ...appAttributes });
141
268
  const flags = useMemo2(() => ({ client: client?.flags ?? null, bootstrap }), [client, bootstrap]);
142
- return /* @__PURE__ */ jsx2(GuidelyContext.Provider, { value: client, children: /* @__PURE__ */ jsx2(FlagsContext.Provider, { value: flags, children }) });
269
+ return /* @__PURE__ */ jsx3(GuidelyContext.Provider, { value: client, children: /* @__PURE__ */ jsx3(FlagsContext.Provider, { value: flags, children }) });
143
270
  }
144
271
  var NOOP_RESULTS = {
145
272
  init: Promise.resolve(),
@@ -160,7 +287,9 @@ var NOOP_RESULTS = {
160
287
  getSessionId: "",
161
288
  isRecording: false,
162
289
  agentConversation: false,
163
- trackAgentTurn: false
290
+ trackAgentTurn: false,
291
+ captureException: "",
292
+ captureMessage: ""
164
293
  };
165
294
  var noopFlags = new Proxy(createStaticFlags2(), {
166
295
  get(target, prop, receiver) {
@@ -188,12 +317,12 @@ var noopClient = new Proxy({}, {
188
317
  }
189
318
  });
190
319
  function useGuidely() {
191
- return useContext2(GuidelyContext) ?? noopClient;
320
+ return useContext3(GuidelyContext) ?? noopClient;
192
321
  }
193
322
  function useGuidelyReady() {
194
- const client = useContext2(GuidelyContext);
195
- const [ready, setReady] = useState2(false);
196
- useEffect2(() => {
323
+ const client = useContext3(GuidelyContext);
324
+ const [ready, setReady] = useState3(false);
325
+ useEffect3(() => {
197
326
  if (!client) {
198
327
  setReady(false);
199
328
  return;
@@ -204,27 +333,27 @@ function useGuidelyReady() {
204
333
  return ready;
205
334
  }
206
335
  function useGuidelyIdentify(userId, traits, account) {
207
- const client = useContext2(GuidelyContext);
336
+ const client = useContext3(GuidelyContext);
208
337
  const key = JSON.stringify([userId ?? null, traits ?? null, account ?? null]);
209
- useEffect2(() => {
338
+ useEffect3(() => {
210
339
  if (!client || !userId) return;
211
340
  void client.identify(userId, traits, account);
212
341
  }, [client, key]);
213
342
  }
214
343
  function useGuidelyEvent(event, handler) {
215
- const client = useContext2(GuidelyContext);
344
+ const client = useContext3(GuidelyContext);
216
345
  const ref = useRef2(handler);
217
346
  ref.current = handler;
218
- useEffect2(() => {
347
+ useEffect3(() => {
219
348
  if (!client) return;
220
349
  const cb = ((...args) => ref.current(...args));
221
350
  return client.on(event, cb);
222
351
  }, [client, event]);
223
352
  }
224
353
  function useChecklistProgress(idOrKey) {
225
- const client = useContext2(GuidelyContext);
226
- const [progress, setProgress] = useState2({ completedTaskIds: [], completedAt: null, dismissedAt: null });
227
- useEffect2(() => {
354
+ const client = useContext3(GuidelyContext);
355
+ const [progress, setProgress] = useState3({ completedTaskIds: [], completedAt: null, dismissedAt: null });
356
+ useEffect3(() => {
228
357
  if (!client) return;
229
358
  const update = () => setProgress(client.getChecklistProgress(idOrKey));
230
359
  update();
@@ -234,9 +363,9 @@ function useChecklistProgress(idOrKey) {
234
363
  return progress;
235
364
  }
236
365
  function useGuideState(idOrKey) {
237
- const client = useContext2(GuidelyContext);
238
- const [state, setState] = useState2({ active: false, completed: false, stepId: null, stepIndex: -1, guide: null });
239
- useEffect2(() => {
366
+ const client = useContext3(GuidelyContext);
367
+ const [state, setState] = useState3({ active: false, completed: false, stepId: null, stepIndex: -1, guide: null });
368
+ useEffect3(() => {
240
369
  if (!client) return;
241
370
  const matches = (g) => g.id === idOrKey || g.key === idOrKey;
242
371
  const compute = () => {
@@ -256,8 +385,11 @@ export {
256
385
  FeatureFlag,
257
386
  FeatureValue,
258
387
  FlagsProvider,
388
+ GuidelyErrorBoundary,
259
389
  GuidelyProvider,
390
+ guidelyReactErrorHandler,
260
391
  noopClient,
392
+ useCaptureException,
261
393
  useChecklistProgress,
262
394
  useFeatureValue,
263
395
  useFlag,
@@ -269,6 +401,7 @@ export {
269
401
  useGuidely,
270
402
  useGuidelyEvent,
271
403
  useGuidelyIdentify,
272
- useGuidelyReady
404
+ useGuidelyReady,
405
+ withGuidelyErrorBoundary
273
406
  };
274
407
  //# sourceMappingURL=index.js.map