@memberjunction/react-runtime 2.70.0 → 2.72.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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +24 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -1
- package/dist/utilities/component-error-analyzer.d.ts +20 -0
- package/dist/utilities/component-error-analyzer.d.ts.map +1 -0
- package/dist/utilities/component-error-analyzer.js +204 -0
- package/dist/utilities/component-styles.d.ts +4 -0
- package/dist/utilities/component-styles.d.ts.map +1 -0
- package/dist/utilities/component-styles.js +97 -0
- package/dist/utilities/index.d.ts +6 -0
- package/dist/utilities/index.d.ts.map +1 -0
- package/dist/utilities/index.js +21 -0
- package/dist/utilities/library-loader.d.ts +33 -0
- package/dist/utilities/library-loader.d.ts.map +1 -0
- package/dist/utilities/library-loader.js +193 -0
- package/dist/utilities/runtime-utilities.d.ts +10 -0
- package/dist/utilities/runtime-utilities.d.ts.map +1 -0
- package/dist/utilities/runtime-utilities.js +92 -0
- package/dist/utilities/standard-libraries.d.ts +27 -0
- package/dist/utilities/standard-libraries.d.ts.map +1 -0
- package/dist/utilities/standard-libraries.js +55 -0
- package/package.json +4 -1
- package/src/index.ts +31 -0
- package/src/utilities/component-error-analyzer.ts +315 -0
- package/src/utilities/component-styles.ts +121 -0
- package/src/utilities/index.ts +10 -0
- package/src/utilities/library-loader.ts +307 -0
- package/src/utilities/runtime-utilities.ts +122 -0
- package/src/utilities/standard-libraries.ts +97 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Component error analysis utilities
|
|
3
|
+
* Provides methods to analyze component errors and identify failed components
|
|
4
|
+
* @module @memberjunction/react-runtime/utilities
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Information about a failed component
|
|
9
|
+
*/
|
|
10
|
+
export interface FailedComponentInfo {
|
|
11
|
+
/** Component name that failed */
|
|
12
|
+
componentName: string;
|
|
13
|
+
/** Error type (e.g., 'not_defined', 'render_error', 'property_error') */
|
|
14
|
+
errorType: string;
|
|
15
|
+
/** Original error message */
|
|
16
|
+
errorMessage: string;
|
|
17
|
+
/** Line number if available */
|
|
18
|
+
lineNumber?: number;
|
|
19
|
+
/** Additional context */
|
|
20
|
+
context?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Analyzes component errors to provide detailed failure information
|
|
25
|
+
*/
|
|
26
|
+
export class ComponentErrorAnalyzer {
|
|
27
|
+
/**
|
|
28
|
+
* Common error patterns for component failures
|
|
29
|
+
*/
|
|
30
|
+
private static readonly ERROR_PATTERNS = [
|
|
31
|
+
{
|
|
32
|
+
// Component is not defined
|
|
33
|
+
pattern: /ReferenceError: (\w+) is not defined/,
|
|
34
|
+
errorType: 'not_defined',
|
|
35
|
+
extractComponent: (match: RegExpMatchArray) => match[1]
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
// Cannot read property of undefined (component reference)
|
|
39
|
+
pattern: /Cannot read propert(?:y|ies) '(\w+)' of undefined/,
|
|
40
|
+
errorType: 'property_error',
|
|
41
|
+
extractComponent: (match: RegExpMatchArray) => match[1]
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
// Component render errors
|
|
45
|
+
pattern: /(\w+)\(\.\.\.\): Nothing was returned from render/,
|
|
46
|
+
errorType: 'render_error',
|
|
47
|
+
extractComponent: (match: RegExpMatchArray) => match[1]
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
// Component in stack trace
|
|
51
|
+
pattern: /at (\w+Component\w*)/,
|
|
52
|
+
errorType: 'stack_trace',
|
|
53
|
+
extractComponent: (match: RegExpMatchArray) => match[1]
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
// React component errors
|
|
57
|
+
pattern: /Error: Unable to find node on an unmounted component/,
|
|
58
|
+
errorType: 'unmounted_component',
|
|
59
|
+
extractComponent: () => null // Need to look at stack trace
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
// Hook errors
|
|
63
|
+
pattern: /Invalid hook call.*component (\w+)/,
|
|
64
|
+
errorType: 'invalid_hook',
|
|
65
|
+
extractComponent: (match: RegExpMatchArray) => match[1]
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
// Type errors in components
|
|
69
|
+
pattern: /TypeError:.*in (\w+) \(at/,
|
|
70
|
+
errorType: 'type_error',
|
|
71
|
+
extractComponent: (match: RegExpMatchArray) => match[1]
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
// Missing imports/components
|
|
75
|
+
pattern: /Module not found: Error: Can't resolve '\.\/(\w+)'/,
|
|
76
|
+
errorType: 'missing_import',
|
|
77
|
+
extractComponent: (match: RegExpMatchArray) => match[1]
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
// Component is not a function
|
|
81
|
+
pattern: /(\w+) is not a function/,
|
|
82
|
+
errorType: 'not_a_function',
|
|
83
|
+
extractComponent: (match: RegExpMatchArray) => match[1]
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
// Minified React error with component hint
|
|
87
|
+
pattern: /Minified React error.*Visit.*for the full message.*component[: ](\w+)/s,
|
|
88
|
+
errorType: 'react_error',
|
|
89
|
+
extractComponent: (match: RegExpMatchArray) => match[1]
|
|
90
|
+
}
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Analyzes error messages to identify which components failed
|
|
95
|
+
* @param errors Array of error messages
|
|
96
|
+
* @returns Array of failed component names
|
|
97
|
+
*/
|
|
98
|
+
static identifyFailedComponents(errors: string[]): string[] {
|
|
99
|
+
const failedComponents = new Set<string>();
|
|
100
|
+
|
|
101
|
+
for (const error of errors) {
|
|
102
|
+
const components = this.extractComponentsFromError(error);
|
|
103
|
+
components.forEach(comp => failedComponents.add(comp));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return Array.from(failedComponents);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Analyzes errors and returns detailed information about failures
|
|
111
|
+
* @param errors Array of error messages
|
|
112
|
+
* @returns Array of detailed failure information
|
|
113
|
+
*/
|
|
114
|
+
static analyzeComponentErrors(errors: string[]): FailedComponentInfo[] {
|
|
115
|
+
const failures: FailedComponentInfo[] = [];
|
|
116
|
+
|
|
117
|
+
for (const error of errors) {
|
|
118
|
+
const failureInfo = this.analyzeError(error);
|
|
119
|
+
failures.push(...failureInfo);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Remove duplicates based on component name and error type
|
|
123
|
+
const uniqueFailures = new Map<string, FailedComponentInfo>();
|
|
124
|
+
failures.forEach(failure => {
|
|
125
|
+
const key = `${failure.componentName}-${failure.errorType}`;
|
|
126
|
+
if (!uniqueFailures.has(key)) {
|
|
127
|
+
uniqueFailures.set(key, failure);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
return Array.from(uniqueFailures.values());
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Extract component names from a single error message
|
|
136
|
+
*/
|
|
137
|
+
private static extractComponentsFromError(error: string): string[] {
|
|
138
|
+
const components: string[] = [];
|
|
139
|
+
|
|
140
|
+
for (const errorPattern of this.ERROR_PATTERNS) {
|
|
141
|
+
const match = error.match(errorPattern.pattern);
|
|
142
|
+
if (match) {
|
|
143
|
+
const componentName = errorPattern.extractComponent(match);
|
|
144
|
+
if (componentName && this.isLikelyComponentName(componentName)) {
|
|
145
|
+
components.push(componentName);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Also check for components in stack traces
|
|
151
|
+
const stackComponents = this.extractComponentsFromStackTrace(error);
|
|
152
|
+
components.push(...stackComponents);
|
|
153
|
+
|
|
154
|
+
return components;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Analyze a single error and return detailed information
|
|
159
|
+
*/
|
|
160
|
+
private static analyzeError(error: string): FailedComponentInfo[] {
|
|
161
|
+
const failures: FailedComponentInfo[] = [];
|
|
162
|
+
|
|
163
|
+
for (const errorPattern of this.ERROR_PATTERNS) {
|
|
164
|
+
const match = error.match(errorPattern.pattern);
|
|
165
|
+
if (match) {
|
|
166
|
+
const componentName = errorPattern.extractComponent(match);
|
|
167
|
+
if (componentName && this.isLikelyComponentName(componentName)) {
|
|
168
|
+
failures.push({
|
|
169
|
+
componentName,
|
|
170
|
+
errorType: errorPattern.errorType,
|
|
171
|
+
errorMessage: error,
|
|
172
|
+
lineNumber: this.extractLineNumber(error),
|
|
173
|
+
context: this.extractContext(error)
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// If no specific pattern matched, try to extract from stack trace
|
|
180
|
+
if (failures.length === 0) {
|
|
181
|
+
const stackComponents = this.extractComponentsFromStackTrace(error);
|
|
182
|
+
stackComponents.forEach(componentName => {
|
|
183
|
+
failures.push({
|
|
184
|
+
componentName,
|
|
185
|
+
errorType: 'unknown',
|
|
186
|
+
errorMessage: error,
|
|
187
|
+
lineNumber: this.extractLineNumber(error)
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return failures;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Extract component names from stack trace
|
|
197
|
+
*/
|
|
198
|
+
private static extractComponentsFromStackTrace(error: string): string[] {
|
|
199
|
+
const components: string[] = [];
|
|
200
|
+
|
|
201
|
+
// Look for React component patterns in stack traces
|
|
202
|
+
const stackPatterns = [
|
|
203
|
+
/at (\w+Component\w*)/g,
|
|
204
|
+
/at (\w+)\s*\(/g,
|
|
205
|
+
/in (\w+)\s*\(at/g,
|
|
206
|
+
/in (\w+)\s*\(created by/g
|
|
207
|
+
];
|
|
208
|
+
|
|
209
|
+
for (const pattern of stackPatterns) {
|
|
210
|
+
let match;
|
|
211
|
+
while ((match = pattern.exec(error)) !== null) {
|
|
212
|
+
const name = match[1];
|
|
213
|
+
if (this.isLikelyComponentName(name)) {
|
|
214
|
+
components.push(name);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return [...new Set(components)]; // Remove duplicates
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Check if a string is likely to be a React component name
|
|
224
|
+
*/
|
|
225
|
+
private static isLikelyComponentName(name: string): boolean {
|
|
226
|
+
// Component names typically:
|
|
227
|
+
// - Start with uppercase letter
|
|
228
|
+
// - Are not JavaScript built-ins
|
|
229
|
+
// - Are not common non-component names
|
|
230
|
+
|
|
231
|
+
const jsBuiltins = new Set([
|
|
232
|
+
'Object', 'Array', 'String', 'Number', 'Boolean', 'Function',
|
|
233
|
+
'Promise', 'Error', 'TypeError', 'ReferenceError', 'SyntaxError',
|
|
234
|
+
'undefined', 'null', 'console', 'window', 'document'
|
|
235
|
+
]);
|
|
236
|
+
|
|
237
|
+
const nonComponents = new Set([
|
|
238
|
+
'render', 'setState', 'forceUpdate', 'props', 'state', 'context',
|
|
239
|
+
'componentDidMount', 'componentWillUnmount', 'useEffect', 'useState'
|
|
240
|
+
]);
|
|
241
|
+
|
|
242
|
+
return (
|
|
243
|
+
name.length > 0 &&
|
|
244
|
+
/^[A-Z]/.test(name) && // Starts with uppercase
|
|
245
|
+
!jsBuiltins.has(name) &&
|
|
246
|
+
!nonComponents.has(name) &&
|
|
247
|
+
!/^use[A-Z]/.test(name) // Not a hook
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Extract line number from error message
|
|
253
|
+
*/
|
|
254
|
+
private static extractLineNumber(error: string): number | undefined {
|
|
255
|
+
// Look for patterns like ":12:34" or "line 12"
|
|
256
|
+
const patterns = [
|
|
257
|
+
/:(\d+):\d+/,
|
|
258
|
+
/line (\d+)/i,
|
|
259
|
+
/Line (\d+)/
|
|
260
|
+
];
|
|
261
|
+
|
|
262
|
+
for (const pattern of patterns) {
|
|
263
|
+
const match = error.match(pattern);
|
|
264
|
+
if (match) {
|
|
265
|
+
return parseInt(match[1], 10);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return undefined;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Extract additional context from error
|
|
274
|
+
*/
|
|
275
|
+
private static extractContext(error: string): string | undefined {
|
|
276
|
+
// Extract file names or additional context
|
|
277
|
+
const fileMatch = error.match(/\(at ([^)]+)\)/);
|
|
278
|
+
if (fileMatch) {
|
|
279
|
+
return fileMatch[1];
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Extract "created by" information
|
|
283
|
+
const createdByMatch = error.match(/created by (\w+)/);
|
|
284
|
+
if (createdByMatch) {
|
|
285
|
+
return `Created by ${createdByMatch[1]}`;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return undefined;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Format error analysis results for logging
|
|
293
|
+
*/
|
|
294
|
+
static formatAnalysisResults(failures: FailedComponentInfo[]): string {
|
|
295
|
+
if (failures.length === 0) {
|
|
296
|
+
return 'No component failures detected';
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
let result = `Detected ${failures.length} component failure(s):\n`;
|
|
300
|
+
|
|
301
|
+
failures.forEach((failure, index) => {
|
|
302
|
+
result += `\n${index + 1}. Component: ${failure.componentName}\n`;
|
|
303
|
+
result += ` Error Type: ${failure.errorType}\n`;
|
|
304
|
+
if (failure.lineNumber) {
|
|
305
|
+
result += ` Line: ${failure.lineNumber}\n`;
|
|
306
|
+
}
|
|
307
|
+
if (failure.context) {
|
|
308
|
+
result += ` Context: ${failure.context}\n`;
|
|
309
|
+
}
|
|
310
|
+
result += ` Message: ${failure.errorMessage.substring(0, 200)}${failure.errorMessage.length > 200 ? '...' : ''}\n`;
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
return result;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Default component styles for React runtime
|
|
3
|
+
* @module @memberjunction/react-runtime/utilities
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { ComponentStyles } from '@memberjunction/interactive-component-types';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Creates the default component styles for Skip components
|
|
10
|
+
* These provide a modern, contemporary look and feel
|
|
11
|
+
* Copied from skip-chat implementation
|
|
12
|
+
*/
|
|
13
|
+
export function SetupStyles(): ComponentStyles {
|
|
14
|
+
// Return modern, contemporary styles for generated components
|
|
15
|
+
return {
|
|
16
|
+
colors: {
|
|
17
|
+
// Primary colors - modern purple/blue gradient feel
|
|
18
|
+
primary: '#5B4FE9',
|
|
19
|
+
primaryHover: '#4940D4',
|
|
20
|
+
primaryLight: '#E8E6FF',
|
|
21
|
+
|
|
22
|
+
// Secondary colors - sophisticated gray
|
|
23
|
+
secondary: '#64748B',
|
|
24
|
+
secondaryHover: '#475569',
|
|
25
|
+
|
|
26
|
+
// Status colors
|
|
27
|
+
success: '#10B981',
|
|
28
|
+
successLight: '#D1FAE5',
|
|
29
|
+
warning: '#F59E0B',
|
|
30
|
+
warningLight: '#FEF3C7',
|
|
31
|
+
error: '#EF4444',
|
|
32
|
+
errorLight: '#FEE2E2',
|
|
33
|
+
info: '#3B82F6',
|
|
34
|
+
infoLight: '#DBEAFE',
|
|
35
|
+
|
|
36
|
+
// Base colors
|
|
37
|
+
background: '#FFFFFF',
|
|
38
|
+
surface: '#F8FAFC',
|
|
39
|
+
surfaceHover: '#F1F5F9',
|
|
40
|
+
|
|
41
|
+
// Text colors with better contrast
|
|
42
|
+
text: '#1E293B',
|
|
43
|
+
textSecondary: '#64748B',
|
|
44
|
+
textTertiary: '#94A3B8',
|
|
45
|
+
textInverse: '#FFFFFF',
|
|
46
|
+
|
|
47
|
+
// Border colors
|
|
48
|
+
border: '#E2E8F0',
|
|
49
|
+
borderLight: '#F1F5F9',
|
|
50
|
+
borderFocus: '#5B4FE9',
|
|
51
|
+
|
|
52
|
+
// Shadows (as color strings for easy use)
|
|
53
|
+
shadow: 'rgba(0, 0, 0, 0.05)',
|
|
54
|
+
shadowMedium: 'rgba(0, 0, 0, 0.1)',
|
|
55
|
+
shadowLarge: 'rgba(0, 0, 0, 0.15)',
|
|
56
|
+
},
|
|
57
|
+
spacing: {
|
|
58
|
+
xs: '4px',
|
|
59
|
+
sm: '8px',
|
|
60
|
+
md: '16px',
|
|
61
|
+
lg: '24px',
|
|
62
|
+
xl: '32px',
|
|
63
|
+
xxl: '48px',
|
|
64
|
+
xxxl: '64px',
|
|
65
|
+
},
|
|
66
|
+
typography: {
|
|
67
|
+
fontFamily: '-apple-system, BlinkMacSystemFont, "Inter", "Segoe UI", Roboto, sans-serif',
|
|
68
|
+
fontSize: {
|
|
69
|
+
xs: '11px',
|
|
70
|
+
sm: '12px',
|
|
71
|
+
md: '14px',
|
|
72
|
+
lg: '16px',
|
|
73
|
+
xl: '20px',
|
|
74
|
+
xxl: '24px',
|
|
75
|
+
xxxl: '32px',
|
|
76
|
+
},
|
|
77
|
+
fontWeight: {
|
|
78
|
+
light: '300',
|
|
79
|
+
regular: '400',
|
|
80
|
+
medium: '500',
|
|
81
|
+
semibold: '600',
|
|
82
|
+
bold: '700',
|
|
83
|
+
},
|
|
84
|
+
lineHeight: {
|
|
85
|
+
tight: '1.25',
|
|
86
|
+
normal: '1.5',
|
|
87
|
+
relaxed: '1.75',
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
borders: {
|
|
91
|
+
radius: {
|
|
92
|
+
sm: '6px',
|
|
93
|
+
md: '8px',
|
|
94
|
+
lg: '12px',
|
|
95
|
+
xl: '16px',
|
|
96
|
+
full: '9999px',
|
|
97
|
+
},
|
|
98
|
+
width: {
|
|
99
|
+
thin: '1px',
|
|
100
|
+
medium: '2px',
|
|
101
|
+
thick: '3px',
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
shadows: {
|
|
105
|
+
sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
|
|
106
|
+
md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
|
|
107
|
+
lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
|
|
108
|
+
xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
|
|
109
|
+
inner: 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)',
|
|
110
|
+
},
|
|
111
|
+
transitions: {
|
|
112
|
+
fast: '150ms ease-in-out',
|
|
113
|
+
normal: '250ms ease-in-out',
|
|
114
|
+
slow: '350ms ease-in-out',
|
|
115
|
+
},
|
|
116
|
+
overflow: 'auto' // Default overflow style
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Also export with the original name for backward compatibility
|
|
121
|
+
export const createDefaultComponentStyles = SetupStyles;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Utilities module exports
|
|
3
|
+
* @module @memberjunction/react-runtime/utilities
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export * from './runtime-utilities';
|
|
7
|
+
export * from './component-styles';
|
|
8
|
+
export * from './standard-libraries';
|
|
9
|
+
export * from './library-loader';
|
|
10
|
+
export * from './component-error-analyzer';
|