@whatitbroke/react 1.0.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.
@@ -0,0 +1,33 @@
1
+ /**
2
+ * WhatItBroke - React Adapter
3
+ * Captures React render errors, component stacks, props/state snapshots, and hook contexts.
4
+ */
5
+ import { ComponentContext, DebugAdapter, DebugContext, RuntimeContext } from '@whatitbroke/shared';
6
+ import { WhatItBrokeCore } from '@whatitbroke/core';
7
+ export interface ReactErrorExtras {
8
+ componentStack?: string;
9
+ componentName?: string;
10
+ props?: Record<string, unknown>;
11
+ state?: Record<string, unknown>;
12
+ lifecyclePhase?: ComponentContext['lifecyclePhase'];
13
+ }
14
+ export declare class ReactAdapter implements DebugAdapter {
15
+ readonly name = "@whatitbroke/react";
16
+ readonly framework: "react";
17
+ private core;
18
+ private currentComponentContext?;
19
+ constructor(core?: WhatItBrokeCore);
20
+ detect(): boolean;
21
+ getComponentContext(): ComponentContext | undefined;
22
+ getRuntimeContext(): RuntimeContext;
23
+ /**
24
+ * Parses React's componentStack string into an array of component names from top to bottom
25
+ */
26
+ parseComponentStack(componentStack?: string): {
27
+ renderPath: string[];
28
+ primaryComponent: string;
29
+ };
30
+ captureContext(error: unknown, extras?: ReactErrorExtras): DebugContext;
31
+ analyzeReactError(error: unknown, extras?: ReactErrorExtras): Promise<import("@whatitbroke/shared").RootCauseReport>;
32
+ }
33
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,YAAY,EAGZ,cAAc,EACf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAIL,eAAe,EAEhB,MAAM,mBAAmB,CAAC;AAG3B,MAAM,WAAW,gBAAgB;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,cAAc,CAAC,EAAE,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;CACrD;AAED,qBAAa,YAAa,YAAW,YAAY;IAC/C,SAAgB,IAAI,wBAAwB;IAC5C,SAAgB,SAAS,EAAG,OAAO,CAAU;IAE7C,OAAO,CAAC,IAAI,CAAkB;IAC9B,OAAO,CAAC,uBAAuB,CAAC,CAAmB;gBAEvC,IAAI,CAAC,EAAE,eAAe;IAI3B,MAAM,IAAI,OAAO;IASjB,mBAAmB,IAAI,gBAAgB,GAAG,SAAS;IAInD,iBAAiB,IAAI,cAAc;IAO1C;;OAEG;IACI,mBAAmB,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG;QAAE,UAAU,EAAE,MAAM,EAAE,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAE;IA4BhG,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,YAAY;IAoEjE,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,gBAAgB;CAIzE"}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * WhatItBroke - React Adapter
3
+ * Captures React render errors, component stacks, props/state snapshots, and hook contexts.
4
+ */
5
+ import { StackParser, SourceMapResolver, getGlobalTimeline, getCore, } from '@whatitbroke/core';
6
+ import { HooksDetector } from './hooks-detector.js';
7
+ export class ReactAdapter {
8
+ name = '@whatitbroke/react';
9
+ framework = 'react';
10
+ core;
11
+ currentComponentContext;
12
+ constructor(core) {
13
+ this.core = core || getCore();
14
+ }
15
+ detect() {
16
+ const g = globalThis;
17
+ return Boolean(g.React ||
18
+ g.__REACT_DEVTOOLS_GLOBAL_HOOK__ ||
19
+ (typeof document !== 'undefined' && document.getElementById('root')));
20
+ }
21
+ getComponentContext() {
22
+ return this.currentComponentContext;
23
+ }
24
+ getRuntimeContext() {
25
+ return {
26
+ environment: 'browser',
27
+ platform: typeof navigator !== 'undefined' ? navigator.platform : undefined,
28
+ };
29
+ }
30
+ /**
31
+ * Parses React's componentStack string into an array of component names from top to bottom
32
+ */
33
+ parseComponentStack(componentStack) {
34
+ if (!componentStack) {
35
+ return { renderPath: ['App', 'Component'], primaryComponent: 'Component' };
36
+ }
37
+ const lines = componentStack.split('\n');
38
+ const components = [];
39
+ for (const rawLine of lines) {
40
+ const line = rawLine.trim();
41
+ const match = line.match(/^in\s+([A-Za-z0-9_]+)/);
42
+ if (match) {
43
+ components.push(match[1]);
44
+ }
45
+ }
46
+ // In React componentStack, the top line is the crashing leaf component,
47
+ // and subsequent lines are parent components (e.g. leaf -> parent -> root).
48
+ // Reverse it to create chronological root-to-leaf renderPath.
49
+ const reversed = [...components].reverse();
50
+ const primary = components[0] || 'Component';
51
+ return {
52
+ renderPath: reversed.length > 0 ? reversed : [primary],
53
+ primaryComponent: primary,
54
+ };
55
+ }
56
+ captureContext(error, extras) {
57
+ const errObj = error instanceof Error ? error : new Error(String(error));
58
+ const stackFrames = StackParser.parse(errObj.stack);
59
+ const primaryFrame = StackParser.getPrimaryFrame(stackFrames);
60
+ const source = primaryFrame
61
+ ? SourceMapResolver.resolveLocation(primaryFrame)
62
+ : {
63
+ file: 'unknown',
64
+ line: 0,
65
+ column: 0,
66
+ };
67
+ const parsedStack = this.parseComponentStack(extras?.componentStack);
68
+ const componentName = extras?.componentName || parsedStack.primaryComponent;
69
+ const componentCtx = {
70
+ name: componentName,
71
+ props: extras?.props,
72
+ state: extras?.state,
73
+ renderPath: parsedStack.renderPath,
74
+ lifecyclePhase: extras?.lifecyclePhase || 'render',
75
+ file: source.file,
76
+ line: source.line,
77
+ };
78
+ this.currentComponentContext = componentCtx;
79
+ // Check for hook errors
80
+ const hookInfo = HooksDetector.analyze(errObj);
81
+ if (hookInfo.isHookError) {
82
+ getGlobalTimeline().record('undefined_value_detected', `React Hook Error: ${hookInfo.message}`, {
83
+ file: source.file,
84
+ line: source.line,
85
+ });
86
+ }
87
+ const errorInfo = {
88
+ name: errObj.name || 'ReactRenderError',
89
+ message: errObj.message || 'React rendering crashed',
90
+ rawStack: errObj.stack,
91
+ timestamp: Date.now(),
92
+ };
93
+ const executionPath = parsedStack.renderPath.map((comp, idx) => ({
94
+ id: `render_${idx}_${comp}`,
95
+ timestamp: Date.now(),
96
+ category: 'render',
97
+ name: comp,
98
+ description: `Rendered component <${comp} />`,
99
+ }));
100
+ return {
101
+ id: `ctx_react_${Date.now()}`,
102
+ timestamp: Date.now(),
103
+ error: errorInfo,
104
+ source,
105
+ stack: stackFrames,
106
+ runtime: this.getRuntimeContext(),
107
+ executionPath,
108
+ timeline: getGlobalTimeline().getEvents(),
109
+ framework: {
110
+ name: 'react',
111
+ component: componentCtx,
112
+ },
113
+ };
114
+ }
115
+ async analyzeReactError(error, extras) {
116
+ const context = this.captureContext(error, extras);
117
+ return this.core.analyze(context);
118
+ }
119
+ }
120
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * WhatItBroke - React Error Boundary Component
3
+ * Wraps React components, captures crashes, and renders an actionable root-cause overlay.
4
+ */
5
+ import { Component, ErrorInfo as ReactErrorInfo, ReactNode } from 'react';
6
+ import { RootCauseReport } from '@whatitbroke/shared';
7
+ export interface WhatItBrokeBoundaryProps {
8
+ children: ReactNode;
9
+ fallback?: (report: RootCauseReport | null, error: Error) => ReactNode;
10
+ onError?: (report: RootCauseReport, error: Error) => void;
11
+ showOverlay?: boolean;
12
+ }
13
+ interface WhatItBrokeBoundaryState {
14
+ hasError: boolean;
15
+ error: Error | null;
16
+ report: RootCauseReport | null;
17
+ }
18
+ export declare class WhatItBrokeBoundary extends Component<WhatItBrokeBoundaryProps, WhatItBrokeBoundaryState> {
19
+ private adapter;
20
+ constructor(props: WhatItBrokeBoundaryProps);
21
+ static getDerivedStateFromError(error: Error): Partial<WhatItBrokeBoundaryState>;
22
+ componentDidCatch(error: Error, errorInfo: ReactErrorInfo): Promise<void>;
23
+ render(): ReactNode;
24
+ }
25
+ export {};
26
+ //# sourceMappingURL=boundary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boundary.d.ts","sourceRoot":"","sources":["../src/boundary.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAc,EAAE,SAAS,EAAE,SAAS,IAAI,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAGtD,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,SAAS,CAAC;IACpB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,KAAK,SAAS,CAAC;IACvE,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAC1D,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,UAAU,wBAAwB;IAChC,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,eAAe,GAAG,IAAI,CAAC;CAChC;AAED,qBAAa,mBAAoB,SAAQ,SAAS,CAAC,wBAAwB,EAAE,wBAAwB,CAAC;IACpG,OAAO,CAAC,OAAO,CAAe;gBAElB,KAAK,EAAE,wBAAwB;IAU3C,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAIjE,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAY/E,MAAM,IAAI,SAAS;CA8G7B"}
@@ -0,0 +1,82 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * WhatItBroke - React Error Boundary Component
4
+ * Wraps React components, captures crashes, and renders an actionable root-cause overlay.
5
+ */
6
+ import { Component } from 'react';
7
+ import { ReactAdapter } from './adapter.js';
8
+ export class WhatItBrokeBoundary extends Component {
9
+ adapter;
10
+ constructor(props) {
11
+ super(props);
12
+ this.state = {
13
+ hasError: false,
14
+ error: null,
15
+ report: null,
16
+ };
17
+ this.adapter = new ReactAdapter();
18
+ }
19
+ static getDerivedStateFromError(error) {
20
+ return { hasError: true, error };
21
+ }
22
+ async componentDidCatch(error, errorInfo) {
23
+ const report = await this.adapter.analyzeReactError(error, {
24
+ componentStack: errorInfo.componentStack || undefined,
25
+ });
26
+ this.setState({ report });
27
+ if (this.props.onError) {
28
+ this.props.onError(report, error);
29
+ }
30
+ }
31
+ render() {
32
+ if (!this.state.hasError) {
33
+ return this.props.children;
34
+ }
35
+ if (this.props.fallback && this.state.error) {
36
+ return this.props.fallback(this.state.report, this.state.error);
37
+ }
38
+ // Default actionable overlay
39
+ const report = this.state.report;
40
+ const err = this.state.error;
41
+ return (_jsxs("div", { style: {
42
+ fontFamily: 'ui-sans-serif, system-ui, -apple-system, sans-serif',
43
+ background: '#0f172a',
44
+ color: '#f8fafc',
45
+ padding: '24px',
46
+ borderRadius: '12px',
47
+ border: '1px solid #ef4444',
48
+ margin: '20px',
49
+ boxShadow: '0 20px 25px -5px rgba(0, 0, 0, 0.5)',
50
+ }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '12px', marginBottom: '16px' }, children: [_jsx("span", { style: {
51
+ background: '#ef4444',
52
+ color: 'white',
53
+ fontWeight: 800,
54
+ padding: '4px 10px',
55
+ borderRadius: '6px',
56
+ fontSize: '12px',
57
+ letterSpacing: '1px',
58
+ }, children: "WHAT IT BROKE" }), _jsxs("h2", { style: { fontSize: '18px', margin: 0, color: '#f87171' }, children: [err?.name, ": ", err?.message] })] }), report ? (_jsxs("div", { children: [_jsxs("div", { style: { marginBottom: '12px', color: '#94a3b8', fontSize: '13px' }, children: ["\uD83D\uDCCD ", _jsxs("strong", { children: [report.affectedLocation.file, ":", report.affectedLocation.line] })] }), _jsxs("div", { style: {
59
+ background: 'rgba(239, 68, 68, 0.1)',
60
+ border: '1px solid rgba(239, 68, 68, 0.2)',
61
+ padding: '12px',
62
+ borderRadius: '8px',
63
+ marginBottom: '16px',
64
+ }, children: [_jsx("div", { style: { fontWeight: 700, fontSize: '12px', color: '#fca5a5', textTransform: 'uppercase' }, children: "Cause (Why)" }), _jsx("div", { style: { marginTop: '4px', fontSize: '14px', color: '#fef2f2' }, children: report.rootCause })] }), _jsxs("div", { style: {
65
+ background: 'rgba(16, 185, 129, 0.1)',
66
+ border: '1px solid rgba(16, 185, 129, 0.2)',
67
+ padding: '12px',
68
+ borderRadius: '8px',
69
+ marginBottom: '16px',
70
+ }, children: [_jsx("div", { style: { fontWeight: 700, fontSize: '12px', color: '#6ee7b7', textTransform: 'uppercase' }, children: "Recommended Fix (How)" }), _jsx("div", { style: { marginTop: '4px', fontSize: '14px', color: '#ecfdf5' }, children: report.suggestedFix.explanation })] }), report.suggestedFix.suggestedPatch && (_jsx("pre", { style: {
71
+ background: '#090d16',
72
+ padding: '12px',
73
+ borderRadius: '6px',
74
+ fontFamily: 'monospace',
75
+ fontSize: '12px',
76
+ overflowX: 'auto',
77
+ border: '1px solid #1e293b',
78
+ color: '#a7f3d0',
79
+ }, children: report.suggestedFix.suggestedPatch }))] })) : (_jsx("div", { style: { color: '#94a3b8', fontSize: '14px' }, children: "Analyzing component crash and reconstructing execution path..." }))] }));
80
+ }
81
+ }
82
+ //# sourceMappingURL=boundary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boundary.js","sourceRoot":"","sources":["../src/boundary.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * WhatItBroke - React Hook Rules Detector
3
+ * Analyzes hook order violations, conditional hooks, and lifecycle hook mismatches.
4
+ */
5
+ export interface HookErrorInfo {
6
+ isHookError: boolean;
7
+ type: 'conditional_hook' | 'invalid_call' | 'missing_dependency' | 'other';
8
+ message: string;
9
+ expectedOrder?: number;
10
+ actualOrder?: number;
11
+ advice: string;
12
+ }
13
+ export declare class HooksDetector {
14
+ static analyze(error: Error | {
15
+ message: string;
16
+ }): HookErrorInfo;
17
+ }
18
+ //# sourceMappingURL=hooks-detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks-detector.d.ts","sourceRoot":"","sources":["../src/hooks-detector.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,OAAO,CAAC;IACrB,IAAI,EAAE,kBAAkB,GAAG,cAAc,GAAG,oBAAoB,GAAG,OAAO,CAAC;IAC3E,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,aAAa;WACV,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,aAAa;CAgDzE"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * WhatItBroke - React Hook Rules Detector
3
+ * Analyzes hook order violations, conditional hooks, and lifecycle hook mismatches.
4
+ */
5
+ export class HooksDetector {
6
+ static analyze(error) {
7
+ const msg = error.message || '';
8
+ if (msg.includes('Rendered fewer hooks than expected') ||
9
+ msg.includes('Rendered more hooks than expected') ||
10
+ msg.includes('rendered more hooks than during the previous render') ||
11
+ msg.includes('rendered fewer hooks than during the previous render')) {
12
+ return {
13
+ isHookError: true,
14
+ type: 'conditional_hook',
15
+ message: msg,
16
+ advice: 'React Hooks must be executed in the exact same order on every render. Ensure hooks are never called inside if statements, loops, or after conditional early returns.',
17
+ };
18
+ }
19
+ if (msg.includes('Invalid hook call') ||
20
+ msg.includes('Hooks can only be called inside of the body of a function component')) {
21
+ return {
22
+ isHookError: true,
23
+ type: 'invalid_call',
24
+ message: msg,
25
+ advice: 'Hooks can only be called at the top level of a React function component or custom hook. Check for mismatched React versions or calling hooks from regular JavaScript functions.',
26
+ };
27
+ }
28
+ if (msg.includes('missing dependency') || msg.includes('react-hooks/exhaustive-deps')) {
29
+ return {
30
+ isHookError: true,
31
+ type: 'missing_dependency',
32
+ message: msg,
33
+ advice: 'useEffect/useCallback/useMemo dependency array is missing referenced state or prop variables, which may cause stale closures.',
34
+ };
35
+ }
36
+ return {
37
+ isHookError: false,
38
+ type: 'other',
39
+ message: msg,
40
+ advice: '',
41
+ };
42
+ }
43
+ }
44
+ //# sourceMappingURL=hooks-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks-detector.js","sourceRoot":"","sources":["../src/hooks-detector.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,MAAM,OAAO,aAAa;IACjB,MAAM,CAAC,OAAO,CAAC,KAAkC;QACtD,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC;QAEhC,IACE,GAAG,CAAC,QAAQ,CAAC,oCAAoC,CAAC;YAClD,GAAG,CAAC,QAAQ,CAAC,mCAAmC,CAAC;YACjD,GAAG,CAAC,QAAQ,CAAC,qDAAqD,CAAC;YACnE,GAAG,CAAC,QAAQ,CAAC,sDAAsD,CAAC,EACpE,CAAC;YACD,OAAO;gBACL,WAAW,EAAE,IAAI;gBACjB,IAAI,EAAE,kBAAkB;gBACxB,OAAO,EAAE,GAAG;gBACZ,MAAM,EACJ,sKAAsK;aACzK,CAAC;QACJ,CAAC;QAED,IACE,GAAG,CAAC,QAAQ,CAAC,mBAAmB,CAAC;YACjC,GAAG,CAAC,QAAQ,CAAC,qEAAqE,CAAC,EACnF,CAAC;YACD,OAAO;gBACL,WAAW,EAAE,IAAI;gBACjB,IAAI,EAAE,cAAc;gBACpB,OAAO,EAAE,GAAG;gBACZ,MAAM,EACJ,iLAAiL;aACpL,CAAC;QACJ,CAAC;QAED,IAAI,GAAG,CAAC,QAAQ,CAAC,oBAAoB,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,6BAA6B,CAAC,EAAE,CAAC;YACtF,OAAO;gBACL,WAAW,EAAE,IAAI;gBACjB,IAAI,EAAE,oBAAoB;gBAC1B,OAAO,EAAE,GAAG;gBACZ,MAAM,EACJ,+HAA+H;aAClI,CAAC;QACJ,CAAC;QAED,OAAO;YACL,WAAW,EAAE,KAAK;YAClB,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,GAAG;YACZ,MAAM,EAAE,EAAE;SACX,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,4 @@
1
+ export * from './adapter.js';
2
+ export * from './hooks-detector.js';
3
+ export * from './boundary.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export * from './adapter.js';
2
+ export * from './hooks-detector.js';
3
+ export * from './boundary.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,eAAe,CAAC"}
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@whatitbroke/react",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "description": "React adapter, Error Boundary, hook rule analyzer, and component tree inspector for WhatItBroke",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js",
15
+ "default": "./dist/index.js"
16
+ }
17
+ },
18
+ "scripts": {
19
+ "build": "tsc",
20
+ "prepublishOnly": "npm run build"
21
+ },
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "dependencies": {
26
+ "@whatitbroke/shared": "1.0.0",
27
+ "@whatitbroke/core": "1.0.0"
28
+ },
29
+ "peerDependencies": {
30
+ "react": ">=18.0.0"
31
+ },
32
+ "peerDependenciesMeta": {
33
+ "react": {
34
+ "optional": true
35
+ }
36
+ },
37
+ "devDependencies": {
38
+ "@types/react": "^19.0.10"
39
+ },
40
+ "keywords": ["debugger", "react", "error-boundary", "hooks", "root-cause"],
41
+ "author": "WhatItBroke Team",
42
+ "license": "MIT",
43
+ "engines": {
44
+ "node": ">=18.0.0"
45
+ }
46
+ }