@vtex/faststore-plugin-buyer-portal 1.1.104 → 1.1.107

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vtex/faststore-plugin-buyer-portal",
3
- "version": "1.1.104",
3
+ "version": "1.1.107",
4
4
  "description": "A plugin for faststore with buyer portal",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -2,14 +2,17 @@
2
2
  import { Icon } from "../Icon";
3
3
 
4
4
  export type ErrorProps = {
5
- error?: Error;
6
- tags?: {
7
- component: string;
8
- errorType: string;
5
+ error?: {
6
+ error: Error;
7
+ query?: unknown;
8
+ tags?: {
9
+ component: string;
10
+ errorType: string;
11
+ };
9
12
  };
10
13
  };
11
14
 
12
- export default function Error({ error, tags }: ErrorProps) {
15
+ export default function Error({ error }: ErrorProps) {
13
16
  return (
14
17
  <div data-fs-bp-error>
15
18
  <Icon name="Warning" width={48} height={48} data-fs-icon-loading="true" />
@@ -18,11 +21,16 @@ export default function Error({ error, tags }: ErrorProps) {
18
21
  Try again
19
22
  </button>
20
23
  <div data-fs-bp-error-details>
21
- <span data-fs-bp-error-details-type>{tags?.errorType}</span>
24
+ <span data-fs-bp-error-details-type>{error?.tags?.errorType}</span>
22
25
  <h2 data-fs-bp-error-details-title>Error Details</h2>
23
- <p data-fs-bp-error-details-message>{error?.message}</p>
24
- <p data-fs-bp-error-details-stack>Stack: {error?.stack}</p>
25
- <p data-fs-bp-error-details-component>Component: {tags?.component}</p>
26
+ <p data-fs-bp-error-details-message>{error?.error.message}</p>
27
+ <p data-fs-bp-error-details-stack>Stack: {error?.error.stack}</p>
28
+ <p data-fs-bp-error-details-component>
29
+ Component: {error?.tags?.component}
30
+ </p>
31
+ <p data-fs-bp-error-details-query>
32
+ Query: {JSON.stringify(error?.query)}
33
+ </p>
26
34
  </div>
27
35
  </div>
28
36
  );
@@ -3,6 +3,7 @@ export type ErrorBoundaryProps = {
3
3
  message: string;
4
4
  name: string;
5
5
  stack?: string;
6
+ query?: unknown;
6
7
  };
7
8
  tags: {
8
9
  component: string;
@@ -2,7 +2,7 @@
2
2
 
3
3
  import React from "react";
4
4
 
5
- import { ErrorBoundary } from "../ErrorBoundary/ErrorBoundary";
5
+ // import { ErrorBoundary } from "../ErrorBoundary/ErrorBoundary";
6
6
 
7
7
  type WithErrorBoundaryOptions = {
8
8
  fallback?: React.ReactNode;
@@ -15,15 +15,16 @@ type WithErrorBoundaryOptions = {
15
15
 
16
16
  export function withErrorBoundary<P extends Record<string, unknown>>(
17
17
  WrappedComponent: React.ComponentType<P>,
18
- options: WithErrorBoundaryOptions = {}
18
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
19
+ _options: WithErrorBoundaryOptions = {}
19
20
  ) {
20
- const { onError, tags } = options;
21
+ // const { onError, tags } = options;
21
22
 
22
23
  const ComponentWithErrorBoundary = (props: P) => {
23
24
  return (
24
- <ErrorBoundary onError={onError} tags={tags}>
25
- <WrappedComponent {...props} />
26
- </ErrorBoundary>
25
+ // <ErrorBoundary onError={onError} tags={tags}>
26
+ <WrappedComponent {...props} />
27
+ // </ErrorBoundary>
27
28
  );
28
29
  };
29
30
 
@@ -15,6 +15,8 @@ export type ErrorTabsLayoutContentProps = {
15
15
  title?: string;
16
16
  error?: {
17
17
  error: Error;
18
+ query?: unknown;
19
+ rawData?: unknown;
18
20
  tags: {
19
21
  component: string;
20
22
  errorType: string;
@@ -26,6 +28,8 @@ export type ErrorTabsLayoutProps = {
26
28
  children?: ReactNode;
27
29
  error?: {
28
30
  error: Error;
31
+ query?: unknown;
32
+ rawData?: unknown;
29
33
  tags: {
30
34
  component: string;
31
35
  errorType: string;
@@ -40,7 +44,7 @@ export const ErrorTabsLayoutContent = ({
40
44
  <div>
41
45
  <section data-fs-bp-profile>
42
46
  <HeaderInside title={title} />
43
- <Error error={error?.error} tags={error?.tags} />
47
+ <Error error={error} />
44
48
  </section>
45
49
  </div>
46
50
  );
@@ -34,5 +34,6 @@ export {
34
34
  export { toQueryParams } from "./toQueryParams";
35
35
  export { getValidPage } from "./getValidPage";
36
36
  export { isPluginError } from "./isPluginError";
37
+ export { serializeLoaderData } from "./serializeLoaderData";
37
38
  export { withLoaderErrorBoundary } from "./withLoaderErrorBoundary";
38
39
  export { withClientErrorBoundary } from "./withClientErrorBoundary";
@@ -0,0 +1,10 @@
1
+ export function serializeLoaderData<T>(data: T): T {
2
+ return JSON.parse(
3
+ JSON.stringify(data, (key, value) => {
4
+ if (value === undefined) {
5
+ return null;
6
+ }
7
+ return value;
8
+ })
9
+ );
10
+ }
@@ -1,3 +1,6 @@
1
+ // import { getClientContext } from "./getClientContext";
2
+ import { serializeLoaderData } from "./serializeLoaderData";
3
+
1
4
  import type { LoaderData } from "../types";
2
5
 
3
6
  interface WithLoaderErrorBoundaryOptions {
@@ -8,39 +11,85 @@ interface WithLoaderErrorBoundaryOptions {
8
11
 
9
12
  export function withLoaderErrorBoundary<TQuery, TReturn>(
10
13
  loaderFn: (data: LoaderData<TQuery>) => Promise<TReturn>,
11
- options: WithLoaderErrorBoundaryOptions = {}
14
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
15
+ _options: WithLoaderErrorBoundaryOptions = {}
12
16
  ) {
13
- const { componentName, onError, redirectToError = true } = options;
14
-
17
+ // Bypass: Just call the loader function and serialize the result
15
18
  return async (data: LoaderData<TQuery>): Promise<TReturn> => {
16
- try {
17
- return await loaderFn(data);
18
- } catch (error) {
19
- if (onError) {
20
- onError(error as Error, data.query);
21
- }
22
-
23
- if (redirectToError) {
24
- return {
25
- error: {
26
- error: {
27
- message: (error as Error).message,
28
- name: (error as Error).name,
29
- stack: (error as Error).stack,
30
- },
31
- tags: {
32
- component: componentName || "Unknown",
33
- errorType: "loader_error",
34
- },
35
- extra: {
36
- query: data.query,
37
- },
38
- },
39
- hasError: true,
40
- } as TReturn;
41
- }
42
-
43
- throw error;
44
- }
19
+ const result = await loaderFn(data);
20
+ return serializeLoaderData(result);
45
21
  };
22
+
23
+ // Old error handling code - commented out for bypass
24
+ // const { componentName, onError, redirectToError = true } = options;
25
+ //
26
+ // return async (data: LoaderData<TQuery>): Promise<TReturn> => {
27
+ // try {
28
+ // const result = await loaderFn(data);
29
+ // return serializeLoaderData(result);
30
+ // } catch (error) {
31
+ // console.error(`[${componentName || "Loader"}] Error:`, {
32
+ // message: (error as Error).message,
33
+ // query: data.query,
34
+ // });
35
+ //
36
+ // if (onError) {
37
+ // onError(error as Error, data.query);
38
+ // }
39
+ //
40
+ // if (redirectToError) {
41
+ // let clientContext;
42
+ // try {
43
+ // clientContext = await getClientContext(data);
44
+ // } catch (contextError) {
45
+ // console.error(
46
+ // `[${componentName || "Loader"}] Failed to get client context:`,
47
+ // contextError
48
+ // );
49
+ // clientContext = {
50
+ // cookie: "",
51
+ // customerId: "",
52
+ // userId: "",
53
+ // vtexIdclientAutCookie: "",
54
+ // };
55
+ // }
56
+ //
57
+ // // Serialize query to ensure it's JSON-safe (use null instead of undefined)
58
+ // const serializedQuery = data.query
59
+ // ? JSON.parse(JSON.stringify(data.query))
60
+ // : null;
61
+ //
62
+ // const errorResponse = {
63
+ // error: {
64
+ // error: {
65
+ // message: (error as Error).message,
66
+ // name: (error as Error).name,
67
+ // stack: (error as Error).stack || null,
68
+ // query: serializedQuery,
69
+ // },
70
+ // tags: {
71
+ // component: componentName || "Unknown",
72
+ // errorType: "loader_error",
73
+ // },
74
+ // extra: {
75
+ // query: serializedQuery,
76
+ // },
77
+ // },
78
+ // hasError: true,
79
+ // context: {
80
+ // clientContext,
81
+ // currentOrgUnit: null,
82
+ // currentContract: null,
83
+ // currentUser: null,
84
+ // },
85
+ // data: null,
86
+ // };
87
+ //
88
+ // // Ensure error response is also JSON-serializable
89
+ // return serializeLoaderData(errorResponse) as TReturn;
90
+ // }
91
+ //
92
+ // throw error;
93
+ // }
94
+ // };
46
95
  }
@@ -85,6 +85,22 @@ const loaderFunction = async (
85
85
  const { customerId, cookie, userId, ...clientContext } =
86
86
  await getClientContext(data);
87
87
 
88
+ if (!contractId || !orgUnitId) {
89
+ return {
90
+ data: {
91
+ addressDetails: null,
92
+ recipientsData: null,
93
+ locationsData: null,
94
+ },
95
+ context: {
96
+ clientContext: { customerId, cookie, userId, ...clientContext },
97
+ currentOrgUnit: null,
98
+ currentContract: null,
99
+ currentUser: null,
100
+ },
101
+ };
102
+ }
103
+
88
104
  const orgUnit = await getOrgUnitBasicDataService({ cookie, id: orgUnitId });
89
105
 
90
106
  const contract = await getContractDetailsService({
@@ -56,6 +56,21 @@ const loaderFunction = async (
56
56
  const { cookie, userId, customerId, ...clientContext } =
57
57
  await getClientContext(data);
58
58
 
59
+ if (!contractId || !orgUnitId) {
60
+ return {
61
+ data: [],
62
+ search: search ?? "",
63
+ total: 0,
64
+ page: page ?? 1,
65
+ context: {
66
+ clientContext: { customerId, cookie, userId, ...clientContext },
67
+ currentOrgUnit: null,
68
+ currentContract: null,
69
+ currentUser: null,
70
+ },
71
+ };
72
+ }
73
+
59
74
  const [currentOrgUnit, user, contract, addressesResponse] = await Promise.all(
60
75
  [
61
76
  getOrgUnitBasicDataService({
@@ -46,6 +46,18 @@ const loaderFunction = async (
46
46
 
47
47
  const { contractId, orgUnitId } = data.query;
48
48
 
49
+ if (!contractId || !orgUnitId) {
50
+ return {
51
+ data: { data: [], total: 0 },
52
+ context: {
53
+ clientContext: { cookie, userId, customerId, ...clientContext },
54
+ currentOrgUnit: null,
55
+ currentContract: null,
56
+ currentUser: null,
57
+ },
58
+ };
59
+ }
60
+
49
61
  const [orgUnit, contract, user, budgetsData] = await Promise.all([
50
62
  getOrgUnitBasicDataService({
51
63
  cookie,
@@ -57,6 +57,21 @@ const loaderFunction = async (
57
57
 
58
58
  const { cookie, userId, ...clientContext } = await getClientContext(data);
59
59
 
60
+ if (!contractId || !orgUnitId) {
61
+ return {
62
+ buyingPolicies: [],
63
+ total: 0,
64
+ search: search ?? "",
65
+ page: page ?? 1,
66
+ context: {
67
+ clientContext: { cookie, userId, ...clientContext },
68
+ currentOrgUnit: null,
69
+ currentContract: null,
70
+ currentUser: null,
71
+ },
72
+ };
73
+ }
74
+
60
75
  const [currentOrgUnit, user, contract, budgetData, buyingPoliciesResponse] =
61
76
  await Promise.all([
62
77
  getOrgUnitBasicDataService({
@@ -23,7 +23,7 @@ export type CostCentersPageData = {
23
23
  data: ContractData | null;
24
24
  context: {
25
25
  clientContext: ClientContext;
26
- currentOrgUnit: OrgUnitBasicData;
26
+ currentOrgUnit: OrgUnitBasicData | null;
27
27
  currentContract: ContractData | null;
28
28
  currentUser: UserData | null;
29
29
  search: string;
@@ -46,6 +46,19 @@ const loaderFunction = async (
46
46
 
47
47
  const { contractId, orgUnitId, search } = data.query;
48
48
 
49
+ if (!contractId || !orgUnitId) {
50
+ return {
51
+ data: null,
52
+ context: {
53
+ clientContext: { cookie, userId, customerId, ...clientContext },
54
+ currentContract: null,
55
+ currentUser: null,
56
+ currentOrgUnit: null,
57
+ search: "",
58
+ },
59
+ };
60
+ }
61
+
49
62
  const [orgUnit, contract, user] = await Promise.all([
50
63
  getOrgUnitBasicDataService({ id: orgUnitId, cookie }),
51
64
  getContractDetailsService({ contractId, unitId: orgUnitId, cookie }),
@@ -46,7 +46,11 @@ type OrgUnitDetailsPageQuery = {
46
46
  const loaderFunction = async (
47
47
  data: LoaderData<OrgUnitDetailsPageQuery>
48
48
  ): Promise<OrgUnitDetailsPageData> => {
49
- const { orgUnitId } = data.query;
49
+ const { orgUnitId } = data.query ?? {};
50
+
51
+ if (!orgUnitId) {
52
+ throw new Error(`Missing required query param: orgUnitId=${orgUnitId}`);
53
+ }
50
54
 
51
55
  const { cookie, userId, ...clientContext } = await getClientContext(data);
52
56
 
@@ -42,7 +42,19 @@ export async function loaderFunction(
42
42
  const { customerId, cookie, userId, ...clientContext } =
43
43
  await getClientContext(data);
44
44
 
45
- const { contractId, orgUnitId } = data.query;
45
+ const { contractId, orgUnitId } = data.query ?? {};
46
+
47
+ if (!contractId || !orgUnitId) {
48
+ return {
49
+ data: null,
50
+ context: {
51
+ clientContext: { customerId, cookie, userId, ...clientContext },
52
+ currentOrgUnit: null,
53
+ currentContract: null,
54
+ currentUser: null,
55
+ },
56
+ };
57
+ }
46
58
 
47
59
  const [orgUnit, contract, user] = await Promise.all([
48
60
  getOrgUnitBasicDataService({
@@ -58,6 +58,24 @@ const loaderFunction = async (
58
58
  const { orgUnitId, search = "", page = "1" } = data.query;
59
59
  const validPage = getValidPage(page);
60
60
 
61
+ if (!orgUnitId) {
62
+ return {
63
+ data: {
64
+ users: [],
65
+ total: 0,
66
+ search: "",
67
+ page: 1,
68
+ rolesOptions: [],
69
+ },
70
+ context: {
71
+ clientContext: { cookie, userId, ...clientContext },
72
+ currentUser: null,
73
+ currentOrgUnit: null,
74
+ rolesOptions: [],
75
+ },
76
+ };
77
+ }
78
+
61
79
  const [currentOrgUnit, usersResponse, user, rolesOptions] = await Promise.all(
62
80
  [
63
81
  getOrgUnitBasicDataService({