@vtex/faststore-plugin-buyer-portal 1.1.98 → 1.1.100
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/package.json
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import React, { Component, type ReactNode } from "react";
|
|
4
4
|
|
|
5
5
|
import { ErrorTabsLayout } from "../../layouts/ErrorTabsLayout/ErrorTabsLayout";
|
|
6
|
+
import { isPluginError } from "../../utils/isPluginError";
|
|
6
7
|
|
|
7
8
|
interface Props {
|
|
8
9
|
children: ReactNode;
|
|
@@ -26,11 +27,15 @@ export class ErrorBoundary extends Component<Props, State> {
|
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
static getDerivedStateFromError(error: Error): State {
|
|
29
|
-
|
|
30
|
+
if (isPluginError(error)) {
|
|
31
|
+
return { hasError: true, error };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return { hasError: false };
|
|
30
35
|
}
|
|
31
36
|
|
|
32
37
|
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
|
|
33
|
-
if (this.props.onError) {
|
|
38
|
+
if (isPluginError(error) && this.props.onError) {
|
|
34
39
|
this.props.onError(error, errorInfo);
|
|
35
40
|
}
|
|
36
41
|
}
|
|
@@ -33,5 +33,6 @@ export {
|
|
|
33
33
|
} from "./search";
|
|
34
34
|
export { toQueryParams } from "./toQueryParams";
|
|
35
35
|
export { getValidPage } from "./getValidPage";
|
|
36
|
+
export { isPluginError } from "./isPluginError";
|
|
36
37
|
export { withLoaderErrorBoundary } from "./withLoaderErrorBoundary";
|
|
37
38
|
export { withClientErrorBoundary } from "./withClientErrorBoundary";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks if an error originates from the plugin's source files
|
|
3
|
+
* @param error - The error object to check
|
|
4
|
+
* @returns {boolean} True if the error comes from plugin source files, false otherwise
|
|
5
|
+
*/
|
|
6
|
+
export function isPluginError(error: Error): boolean {
|
|
7
|
+
if (!error.stack) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const stackLines = error.stack.split("\n");
|
|
12
|
+
|
|
13
|
+
const pluginSourcePattern = /\/src\//;
|
|
14
|
+
|
|
15
|
+
for (const line of stackLines) {
|
|
16
|
+
if (pluginSourcePattern.test(line)) {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
@@ -105,64 +105,138 @@ export const ROUTE_TABS_LAYOUT_MAPPING: Record<string, RouteTabsLayoutConfig> =
|
|
|
105
105
|
export function getTabsLayoutConfigFromRoute(
|
|
106
106
|
pathname: string
|
|
107
107
|
): RouteTabsLayoutConfig | null {
|
|
108
|
-
|
|
108
|
+
try {
|
|
109
|
+
if (!pathname) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
109
112
|
|
|
110
|
-
|
|
111
|
-
return ROUTE_TABS_LAYOUT_MAPPING[normalizedPath];
|
|
112
|
-
}
|
|
113
|
+
const normalizedPath = pathname.split("?")[0].split("#")[0];
|
|
113
114
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
115
|
+
if (ROUTE_TABS_LAYOUT_MAPPING[normalizedPath]) {
|
|
116
|
+
return ROUTE_TABS_LAYOUT_MAPPING[normalizedPath];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
for (const [routePattern, config] of Object.entries(
|
|
120
|
+
ROUTE_TABS_LAYOUT_MAPPING
|
|
121
|
+
)) {
|
|
122
|
+
if (matchesRoutePattern(normalizedPath, routePattern)) {
|
|
123
|
+
return config;
|
|
124
|
+
}
|
|
119
125
|
}
|
|
120
|
-
}
|
|
121
126
|
|
|
122
|
-
|
|
127
|
+
return null;
|
|
128
|
+
} catch (error) {
|
|
129
|
+
console.warn(
|
|
130
|
+
`Failed to get tabs layout config for pathname "${pathname}":`,
|
|
131
|
+
error
|
|
132
|
+
);
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
123
135
|
}
|
|
124
136
|
|
|
125
137
|
function matchesRoutePattern(pathname: string, pattern: string): boolean {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
138
|
+
try {
|
|
139
|
+
if (!pathname || !pattern) {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
129
142
|
|
|
130
|
-
|
|
131
|
-
|
|
143
|
+
const regexPattern = pattern
|
|
144
|
+
.replace(/\[([^\]]+)\]/g, "([^/]+)")
|
|
145
|
+
.replace(/\//g, "\\/");
|
|
146
|
+
|
|
147
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
148
|
+
return regex.test(pathname);
|
|
149
|
+
} catch (error) {
|
|
150
|
+
console.warn(
|
|
151
|
+
`Failed to match route pattern "${pattern}" with pathname "${pathname}":`,
|
|
152
|
+
error
|
|
153
|
+
);
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
132
156
|
}
|
|
133
157
|
|
|
134
158
|
export function extractRouteParams(pathname: string): Record<string, string> {
|
|
135
159
|
const params: Record<string, string> = {};
|
|
136
160
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const paramNames =
|
|
142
|
-
routePattern.match(/\[([^\]]+)\]/g)?.map((p) => p.slice(1, -1)) || [];
|
|
143
|
-
|
|
144
|
-
const regexPattern = routePattern
|
|
145
|
-
.replace(/\[([^\]]+)\]/g, "([^/]+)")
|
|
146
|
-
.replace(/\//g, "\\/");
|
|
147
|
-
const regex = new RegExp(`^${regexPattern}$`);
|
|
161
|
+
try {
|
|
162
|
+
if (!pathname) {
|
|
163
|
+
return params;
|
|
164
|
+
}
|
|
148
165
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
166
|
+
const normalizedPath = pathname.split("?")[0].split("#")[0];
|
|
167
|
+
|
|
168
|
+
for (const [routePattern] of Object.entries(ROUTE_TABS_LAYOUT_MAPPING)) {
|
|
169
|
+
if (matchesRoutePattern(normalizedPath, routePattern)) {
|
|
170
|
+
const paramNames =
|
|
171
|
+
routePattern.match(/\[([^\]]+)\]/g)?.map((p) => p.slice(1, -1)) || [];
|
|
172
|
+
|
|
173
|
+
try {
|
|
174
|
+
const regexPattern = routePattern
|
|
175
|
+
.replace(/\[([^\]]+)\]/g, "([^/]+)")
|
|
176
|
+
.replace(/\//g, "\\/");
|
|
177
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
178
|
+
|
|
179
|
+
const match = normalizedPath.match(regex);
|
|
180
|
+
if (match) {
|
|
181
|
+
paramNames.forEach((name, index) => {
|
|
182
|
+
params[name] = match[index + 1];
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
} catch (regexError) {
|
|
186
|
+
console.warn(
|
|
187
|
+
`Failed to create regex for pattern "${routePattern}":`,
|
|
188
|
+
regexError
|
|
189
|
+
);
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
break;
|
|
154
193
|
}
|
|
155
|
-
break;
|
|
156
194
|
}
|
|
195
|
+
} catch (error) {
|
|
196
|
+
console.warn(
|
|
197
|
+
`Failed to extract route params from pathname "${pathname}":`,
|
|
198
|
+
error
|
|
199
|
+
);
|
|
157
200
|
}
|
|
158
201
|
|
|
159
202
|
return params;
|
|
160
203
|
}
|
|
161
204
|
|
|
162
205
|
export function useRouteTabsLayout(pathname: string) {
|
|
163
|
-
|
|
206
|
+
try {
|
|
207
|
+
if (!pathname) {
|
|
208
|
+
return {
|
|
209
|
+
hasTabsLayout: false,
|
|
210
|
+
layoutType: null,
|
|
211
|
+
layoutConfig: null,
|
|
212
|
+
routeParams: {},
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const config = getTabsLayoutConfigFromRoute(pathname);
|
|
217
|
+
|
|
218
|
+
if (!config) {
|
|
219
|
+
return {
|
|
220
|
+
hasTabsLayout: false,
|
|
221
|
+
layoutType: null,
|
|
222
|
+
layoutConfig: null,
|
|
223
|
+
routeParams: {},
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const params = extractRouteParams(pathname);
|
|
164
228
|
|
|
165
|
-
|
|
229
|
+
return {
|
|
230
|
+
hasTabsLayout: true,
|
|
231
|
+
layoutType: config.layout,
|
|
232
|
+
layoutConfig: config,
|
|
233
|
+
routeParams: params,
|
|
234
|
+
};
|
|
235
|
+
} catch (error) {
|
|
236
|
+
console.warn(
|
|
237
|
+
`Failed to get route tabs layout for pathname "${pathname}":`,
|
|
238
|
+
error
|
|
239
|
+
);
|
|
166
240
|
return {
|
|
167
241
|
hasTabsLayout: false,
|
|
168
242
|
layoutType: null,
|
|
@@ -170,13 +244,4 @@ export function useRouteTabsLayout(pathname: string) {
|
|
|
170
244
|
routeParams: {},
|
|
171
245
|
};
|
|
172
246
|
}
|
|
173
|
-
|
|
174
|
-
const params = extractRouteParams(pathname);
|
|
175
|
-
|
|
176
|
-
return {
|
|
177
|
-
hasTabsLayout: true,
|
|
178
|
-
layoutType: config.layout,
|
|
179
|
-
layoutConfig: config,
|
|
180
|
-
routeParams: params,
|
|
181
|
-
};
|
|
182
247
|
}
|