@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/README.md +40 -1
- package/dist/index.cjs +188 -52
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +99 -4
- package/dist/index.d.ts +99 -4
- package/dist/index.js +171 -38
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
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,
|
|
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,
|
|
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 {
|
|
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 =
|
|
13
|
-
var
|
|
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 =
|
|
16
|
-
return src?.client ?? src?.bootstrap ??
|
|
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
|
|
173
|
+
return useContext2(FlagsContext)?.client ?? null;
|
|
47
174
|
}
|
|
48
175
|
function Feature({ flag, children, fallback = null }) {
|
|
49
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
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 }) :
|
|
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] =
|
|
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
|
-
|
|
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
|
-
|
|
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__ */
|
|
218
|
+
return /* @__PURE__ */ jsx2(FlagsContext.Provider, { value, children });
|
|
92
219
|
}
|
|
93
220
|
|
|
94
221
|
// src/index.tsx
|
|
95
|
-
import { jsx as
|
|
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] =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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__ */
|
|
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
|
|
320
|
+
return useContext3(GuidelyContext) ?? noopClient;
|
|
192
321
|
}
|
|
193
322
|
function useGuidelyReady() {
|
|
194
|
-
const client =
|
|
195
|
-
const [ready, setReady] =
|
|
196
|
-
|
|
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 =
|
|
336
|
+
const client = useContext3(GuidelyContext);
|
|
208
337
|
const key = JSON.stringify([userId ?? null, traits ?? null, account ?? null]);
|
|
209
|
-
|
|
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 =
|
|
344
|
+
const client = useContext3(GuidelyContext);
|
|
216
345
|
const ref = useRef2(handler);
|
|
217
346
|
ref.current = handler;
|
|
218
|
-
|
|
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 =
|
|
226
|
-
const [progress, setProgress] =
|
|
227
|
-
|
|
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 =
|
|
238
|
-
const [state, setState] =
|
|
239
|
-
|
|
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
|