@akinon/projectzero 2.0.63-beta.0 → 2.0.63
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/CHANGELOG.md +5 -1
- package/app-template/CHANGELOG.md +33 -32
- package/app-template/package.json +29 -29
- package/app-template/src/app/[pz]/404/page.tsx +24 -0
- package/app-template/src/app/[pz]/500/page.tsx +23 -0
- package/app-template/src/app/[pz]/error.tsx +27 -0
- package/app-template/src/app/[pz]/layout.tsx +11 -1
- package/app-template/src/app/[pz]/not-found.tsx +9 -16
- package/app-template/src/views/not-found-content.tsx +22 -0
- package/app-template/src/views/server-error-content.tsx +37 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,37 +1,38 @@
|
|
|
1
1
|
# projectzeronext
|
|
2
2
|
|
|
3
|
-
## 2.0.63
|
|
4
|
-
|
|
5
|
-
### Patch Changes
|
|
6
|
-
|
|
7
|
-
-
|
|
8
|
-
|
|
9
|
-
- @akinon/pz-theme@2.0.63
|
|
10
|
-
- @akinon/pz-virtual-try-on@2.0.63
|
|
11
|
-
- @akinon/
|
|
12
|
-
- @akinon/pz-
|
|
13
|
-
- @akinon/pz-
|
|
14
|
-
- @akinon/pz-
|
|
15
|
-
- @akinon/pz-
|
|
16
|
-
- @akinon/pz-
|
|
17
|
-
- @akinon/pz-
|
|
18
|
-
- @akinon/pz-
|
|
19
|
-
- @akinon/pz-
|
|
20
|
-
- @akinon/pz-
|
|
21
|
-
- @akinon/pz-
|
|
22
|
-
- @akinon/pz-
|
|
23
|
-
- @akinon/pz-
|
|
24
|
-
- @akinon/pz-
|
|
25
|
-
- @akinon/pz-
|
|
26
|
-
- @akinon/pz-masterpass
|
|
27
|
-
- @akinon/pz-
|
|
28
|
-
- @akinon/pz-
|
|
29
|
-
- @akinon/pz-
|
|
30
|
-
- @akinon/pz-
|
|
31
|
-
- @akinon/pz-
|
|
32
|
-
- @akinon/pz-
|
|
33
|
-
- @akinon/pz-
|
|
34
|
-
- @akinon/pz-
|
|
3
|
+
## 2.0.63
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 72a62c6: ZERO-4823: Implement 404 and 500 pages for theme editor
|
|
8
|
+
- Updated dependencies [72a62c6]
|
|
9
|
+
- @akinon/pz-theme@2.0.63
|
|
10
|
+
- @akinon/pz-virtual-try-on@2.0.63
|
|
11
|
+
- @akinon/next@2.0.63
|
|
12
|
+
- @akinon/pz-akifast@2.0.63
|
|
13
|
+
- @akinon/pz-apple-pay@2.0.63
|
|
14
|
+
- @akinon/pz-b2b@2.0.63
|
|
15
|
+
- @akinon/pz-basket-gift-pack@2.0.63
|
|
16
|
+
- @akinon/pz-bkm@2.0.63
|
|
17
|
+
- @akinon/pz-checkout-gift-pack@2.0.63
|
|
18
|
+
- @akinon/pz-click-collect@2.0.63
|
|
19
|
+
- @akinon/pz-credit-payment@2.0.63
|
|
20
|
+
- @akinon/pz-cybersource-uc@2.0.63
|
|
21
|
+
- @akinon/pz-flow-payment@2.0.63
|
|
22
|
+
- @akinon/pz-google-pay@2.0.63
|
|
23
|
+
- @akinon/pz-gpay@2.0.63
|
|
24
|
+
- @akinon/pz-haso@2.0.63
|
|
25
|
+
- @akinon/pz-hepsipay@2.0.63
|
|
26
|
+
- @akinon/pz-masterpass@2.0.63
|
|
27
|
+
- @akinon/pz-masterpass-rest@2.0.63
|
|
28
|
+
- @akinon/pz-multi-basket@2.0.63
|
|
29
|
+
- @akinon/pz-one-click-checkout@2.0.63
|
|
30
|
+
- @akinon/pz-otp@2.0.63
|
|
31
|
+
- @akinon/pz-pay-on-delivery@2.0.63
|
|
32
|
+
- @akinon/pz-saved-card@2.0.63
|
|
33
|
+
- @akinon/pz-similar-products@2.0.63
|
|
34
|
+
- @akinon/pz-tabby-extension@2.0.63
|
|
35
|
+
- @akinon/pz-tamara-extension@2.0.63
|
|
35
36
|
|
|
36
37
|
## 2.0.62
|
|
37
38
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "projectzeronext",
|
|
3
|
-
"version": "2.0.63
|
|
3
|
+
"version": "2.0.63",
|
|
4
4
|
"private": true,
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"scripts": {
|
|
@@ -24,33 +24,33 @@
|
|
|
24
24
|
"test:middleware": "jest middleware-matcher.test.ts --bail"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@akinon/next": "2.0.63
|
|
28
|
-
"@akinon/pz-akifast": "2.0.63
|
|
29
|
-
"@akinon/pz-apple-pay": "2.0.63
|
|
30
|
-
"@akinon/pz-b2b": "2.0.63
|
|
31
|
-
"@akinon/pz-basket-gift-pack": "2.0.63
|
|
32
|
-
"@akinon/pz-bkm": "2.0.63
|
|
33
|
-
"@akinon/pz-checkout-gift-pack": "2.0.63
|
|
34
|
-
"@akinon/pz-click-collect": "2.0.63
|
|
35
|
-
"@akinon/pz-credit-payment": "2.0.63
|
|
36
|
-
"@akinon/pz-cybersource-uc": "2.0.63
|
|
37
|
-
"@akinon/pz-flow-payment": "2.0.63
|
|
38
|
-
"@akinon/pz-google-pay": "2.0.63
|
|
39
|
-
"@akinon/pz-gpay": "2.0.63
|
|
40
|
-
"@akinon/pz-haso": "2.0.63
|
|
41
|
-
"@akinon/pz-hepsipay": "2.0.63
|
|
42
|
-
"@akinon/pz-masterpass": "2.0.63
|
|
43
|
-
"@akinon/pz-masterpass-rest": "2.0.63
|
|
44
|
-
"@akinon/pz-multi-basket": "2.0.63
|
|
45
|
-
"@akinon/pz-one-click-checkout": "2.0.63
|
|
46
|
-
"@akinon/pz-otp": "2.0.63
|
|
47
|
-
"@akinon/pz-pay-on-delivery": "2.0.63
|
|
48
|
-
"@akinon/pz-saved-card": "2.0.63
|
|
49
|
-
"@akinon/pz-similar-products": "2.0.63
|
|
50
|
-
"@akinon/pz-tabby-extension": "2.0.63
|
|
51
|
-
"@akinon/pz-tamara-extension": "2.0.63
|
|
52
|
-
"@akinon/pz-theme": "2.0.63
|
|
53
|
-
"@akinon/pz-virtual-try-on": "2.0.63
|
|
27
|
+
"@akinon/next": "2.0.63",
|
|
28
|
+
"@akinon/pz-akifast": "2.0.63",
|
|
29
|
+
"@akinon/pz-apple-pay": "2.0.63",
|
|
30
|
+
"@akinon/pz-b2b": "2.0.63",
|
|
31
|
+
"@akinon/pz-basket-gift-pack": "2.0.63",
|
|
32
|
+
"@akinon/pz-bkm": "2.0.63",
|
|
33
|
+
"@akinon/pz-checkout-gift-pack": "2.0.63",
|
|
34
|
+
"@akinon/pz-click-collect": "2.0.63",
|
|
35
|
+
"@akinon/pz-credit-payment": "2.0.63",
|
|
36
|
+
"@akinon/pz-cybersource-uc": "2.0.63",
|
|
37
|
+
"@akinon/pz-flow-payment": "2.0.63",
|
|
38
|
+
"@akinon/pz-google-pay": "2.0.63",
|
|
39
|
+
"@akinon/pz-gpay": "2.0.63",
|
|
40
|
+
"@akinon/pz-haso": "2.0.63",
|
|
41
|
+
"@akinon/pz-hepsipay": "2.0.63",
|
|
42
|
+
"@akinon/pz-masterpass": "2.0.63",
|
|
43
|
+
"@akinon/pz-masterpass-rest": "2.0.63",
|
|
44
|
+
"@akinon/pz-multi-basket": "2.0.63",
|
|
45
|
+
"@akinon/pz-one-click-checkout": "2.0.63",
|
|
46
|
+
"@akinon/pz-otp": "2.0.63",
|
|
47
|
+
"@akinon/pz-pay-on-delivery": "2.0.63",
|
|
48
|
+
"@akinon/pz-saved-card": "2.0.63",
|
|
49
|
+
"@akinon/pz-similar-products": "2.0.63",
|
|
50
|
+
"@akinon/pz-tabby-extension": "2.0.63",
|
|
51
|
+
"@akinon/pz-tamara-extension": "2.0.63",
|
|
52
|
+
"@akinon/pz-theme": "2.0.63",
|
|
53
|
+
"@akinon/pz-virtual-try-on": "2.0.63",
|
|
54
54
|
"@hookform/resolvers": "2.9.0",
|
|
55
55
|
"@next/third-parties": "16.2.6",
|
|
56
56
|
"@react-google-maps/api": "2.17.1",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"yup": "0.32.11"
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
77
|
-
"@akinon/eslint-plugin-projectzero": "2.0.63
|
|
77
|
+
"@akinon/eslint-plugin-projectzero": "2.0.63",
|
|
78
78
|
"@semantic-release/changelog": "6.0.2",
|
|
79
79
|
"@semantic-release/exec": "6.0.3",
|
|
80
80
|
"@semantic-release/git": "10.0.1",
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import 'server-only';
|
|
2
|
+
import ChromeSlot from '@akinon/pz-theme/src/chrome/chrome-slot';
|
|
3
|
+
import { PLACEHOLDER_SLUGS } from '@akinon/pz-theme/src/chrome/placeholder-slugs';
|
|
4
|
+
import { buildNotFoundPageContext } from '@akinon/pz-theme/src/chrome/page-context';
|
|
5
|
+
import { withSegmentDefaults } from '@akinon/next/hocs/server';
|
|
6
|
+
import NotFoundContent from '@theme/views/not-found-content';
|
|
7
|
+
|
|
8
|
+
// The not-found boundary is not routable, so the theme editor could never
|
|
9
|
+
// open it in the preview iframe. This page serves that preview: it mounts
|
|
10
|
+
// the same slot with the same fallback, so the designer composes exactly
|
|
11
|
+
// what a shopper sees on a real 404.
|
|
12
|
+
export const dynamic = 'force-dynamic';
|
|
13
|
+
|
|
14
|
+
async function Page() {
|
|
15
|
+
return (
|
|
16
|
+
<ChromeSlot
|
|
17
|
+
slug={PLACEHOLDER_SLUGS.notFound}
|
|
18
|
+
pageContext={buildNotFoundPageContext()}
|
|
19
|
+
fallback={<NotFoundContent />}
|
|
20
|
+
/>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default withSegmentDefaults(Page, { segmentType: 'page' });
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import 'server-only';
|
|
2
|
+
import ChromeSlot from '@akinon/pz-theme/src/chrome/chrome-slot';
|
|
3
|
+
import { PLACEHOLDER_SLUGS } from '@akinon/pz-theme/src/chrome/placeholder-slugs';
|
|
4
|
+
import { buildErrorPageContext } from '@akinon/pz-theme/src/chrome/page-context';
|
|
5
|
+
import { withSegmentDefaults } from '@akinon/next/hocs/server';
|
|
6
|
+
import ServerErrorContent from '@theme/views/server-error-content';
|
|
7
|
+
|
|
8
|
+
// The error boundary cannot be opened by URL, so the theme editor could never
|
|
9
|
+
// preview it. This page serves that preview: it mounts the same slot the
|
|
10
|
+
// boundary reads its composition from, with the same code-owned fallback.
|
|
11
|
+
export const dynamic = 'force-dynamic';
|
|
12
|
+
|
|
13
|
+
async function Page() {
|
|
14
|
+
return (
|
|
15
|
+
<ChromeSlot
|
|
16
|
+
slug={PLACEHOLDER_SLUGS.serverError}
|
|
17
|
+
pageContext={buildErrorPageContext()}
|
|
18
|
+
fallback={<ServerErrorContent />}
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default withSegmentDefaults(Page, { segmentType: 'page' });
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
import { useSentryUncaughtErrors } from '@akinon/next/hooks';
|
|
4
4
|
import PzErrorPage from '@akinon/next/views/error-page';
|
|
5
|
+
import { useErrorComposition } from '@akinon/pz-theme/src/chrome/error-composition';
|
|
6
|
+
import ThemePlaceholderClient from '@akinon/pz-theme/src/theme-placeholder-client';
|
|
7
|
+
import { ThemePageContextProvider } from '@akinon/pz-theme/src/theme-page-context';
|
|
8
|
+
import { ThemeSettingsProvider } from '@akinon/pz-theme/src/theme-settings-context';
|
|
5
9
|
|
|
6
10
|
export default function ErrorPage({
|
|
7
11
|
error,
|
|
@@ -13,5 +17,28 @@ export default function ErrorPage({
|
|
|
13
17
|
// DO NOT REMOVE THIS LINE TO REPORT UNCAUGHT ERRORS TO SENTRY
|
|
14
18
|
useSentryUncaughtErrors(error);
|
|
15
19
|
|
|
20
|
+
// Prefetched by the layout provider before anything failed; null until a
|
|
21
|
+
// designer composes the server-error placeholder in the theme editor.
|
|
22
|
+
const composition = useErrorComposition();
|
|
23
|
+
|
|
24
|
+
if (composition) {
|
|
25
|
+
return (
|
|
26
|
+
<>
|
|
27
|
+
{composition.themeCSS && (
|
|
28
|
+
<style dangerouslySetInnerHTML={{ __html: composition.themeCSS }} />
|
|
29
|
+
)}
|
|
30
|
+
<ThemeSettingsProvider value={composition.themeSettings}>
|
|
31
|
+
<ThemePageContextProvider value={composition.pageContext}>
|
|
32
|
+
<ThemePlaceholderClient
|
|
33
|
+
slug={composition.slug}
|
|
34
|
+
initialSections={composition.sections}
|
|
35
|
+
initialPlaceholderId={composition.placeholderId}
|
|
36
|
+
/>
|
|
37
|
+
</ThemePageContextProvider>
|
|
38
|
+
</ThemeSettingsProvider>
|
|
39
|
+
</>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
16
43
|
return <PzErrorPage error={error} reset={reset} />;
|
|
17
44
|
}
|
|
@@ -20,6 +20,8 @@ import { PreviewAuthStateReporter } from '@akinon/pz-theme/src/chrome/preview-au
|
|
|
20
20
|
import ChromeSlot from '@akinon/pz-theme/src/chrome/chrome-slot';
|
|
21
21
|
import ThemeModals from '@akinon/pz-theme/src/overlays/theme-modals';
|
|
22
22
|
import { PLACEHOLDER_SLUGS } from '@akinon/pz-theme/src/chrome/placeholder-slugs';
|
|
23
|
+
import { ErrorCompositionProvider } from '@akinon/pz-theme/src/chrome/error-composition';
|
|
24
|
+
import { loadErrorComposition } from '@akinon/pz-theme/src/chrome/error-composition-source';
|
|
23
25
|
import './configure-page-context';
|
|
24
26
|
|
|
25
27
|
export const viewport: Viewport = {
|
|
@@ -55,6 +57,12 @@ async function RootLayout({
|
|
|
55
57
|
translations,
|
|
56
58
|
children
|
|
57
59
|
}: ResolvedRootLayoutProps) {
|
|
60
|
+
// Reconstructed here, above the error boundary, because the boundary is a
|
|
61
|
+
// client component that can neither fetch nor receive server props — see
|
|
62
|
+
// pz-theme's error-composition.tsx. Costs one memoized widget read until a
|
|
63
|
+
// designer composes the server-error placeholder.
|
|
64
|
+
const errorComposition = await loadErrorComposition();
|
|
65
|
+
|
|
58
66
|
return (
|
|
59
67
|
<html lang={locale.isoCode} {...(locale.rtl ? { dir: 'rtl' } : {})}>
|
|
60
68
|
<head />
|
|
@@ -69,7 +77,9 @@ async function RootLayout({
|
|
|
69
77
|
/>
|
|
70
78
|
</MobileAppToggler>
|
|
71
79
|
<main>
|
|
72
|
-
<
|
|
80
|
+
<ErrorCompositionProvider composition={errorComposition}>
|
|
81
|
+
<OfflineFallback>{children}</OfflineFallback>
|
|
82
|
+
</ErrorCompositionProvider>
|
|
73
83
|
<RouteHandler />
|
|
74
84
|
<PreviewAuthStateReporter />
|
|
75
85
|
<RootModal />
|
|
@@ -1,22 +1,15 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
1
|
import React from 'react';
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
2
|
+
import ChromeSlot from '@akinon/pz-theme/src/chrome/chrome-slot';
|
|
3
|
+
import { PLACEHOLDER_SLUGS } from '@akinon/pz-theme/src/chrome/placeholder-slugs';
|
|
4
|
+
import { buildNotFoundPageContext } from '@akinon/pz-theme/src/chrome/page-context';
|
|
5
|
+
import NotFoundContent from '@theme/views/not-found-content';
|
|
6
6
|
|
|
7
7
|
export default function NotFound() {
|
|
8
|
-
const { t } = useLocalization();
|
|
9
|
-
|
|
10
8
|
return (
|
|
11
|
-
<
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
<Button className="h-auto mt-4 text-base py-3 px-6">
|
|
17
|
-
{t('not_found.button')}
|
|
18
|
-
</Button>
|
|
19
|
-
</Link>
|
|
20
|
-
</div>
|
|
9
|
+
<ChromeSlot
|
|
10
|
+
slug={PLACEHOLDER_SLUGS.notFound}
|
|
11
|
+
pageContext={buildNotFoundPageContext()}
|
|
12
|
+
fallback={<NotFoundContent />}
|
|
13
|
+
/>
|
|
21
14
|
);
|
|
22
15
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { Button, Link } from '@theme/components';
|
|
5
|
+
import { useLocalization } from '@akinon/next/hooks';
|
|
6
|
+
|
|
7
|
+
export default function NotFoundContent() {
|
|
8
|
+
const { t } = useLocalization();
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<div className="py-10 flex flex-col items-center justify-center">
|
|
12
|
+
<div className="text-8xl font-bold text-gray-400">404</div>
|
|
13
|
+
<h1 className="text-4xl font-bold mb-4">{t('not_found.title')}</h1>
|
|
14
|
+
<p className="text-lg mb-6 text-gray-600">{t('not_found.sub_title')}</p>
|
|
15
|
+
<Link href={'/'}>
|
|
16
|
+
<Button className="h-auto mt-4 text-base py-3 px-6">
|
|
17
|
+
{t('not_found.button')}
|
|
18
|
+
</Button>
|
|
19
|
+
</Link>
|
|
20
|
+
</div>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { Button, Link } from '@theme/components';
|
|
5
|
+
import { useLocalization } from '@akinon/next/hooks';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The code-owned 500 markup, shared by the real error boundary's fallback and
|
|
9
|
+
* the /500 preview page. Mirrors PzErrorPage's server-error branch, minus the
|
|
10
|
+
* `reset` dependency an error boundary alone can provide.
|
|
11
|
+
*/
|
|
12
|
+
export default function ServerErrorContent() {
|
|
13
|
+
const { t } = useLocalization();
|
|
14
|
+
|
|
15
|
+
const reloadPage = () => {
|
|
16
|
+
if (typeof window !== 'undefined') {
|
|
17
|
+
window.location.reload();
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<section className="text-center px-6 my-14 md:px-0 md:m-14">
|
|
23
|
+
<div className="text-7xl font-bold md:text-8xl">500</div>
|
|
24
|
+
<h1 className="text-lg md:text-xl"> {t('common.page_500.title')} </h1>
|
|
25
|
+
<p className="text-lg md:text-xl"> {t('common.page_500.description')} </p>
|
|
26
|
+
|
|
27
|
+
<div className="mt-6 flex flex-col gap-4 items-center justify-center">
|
|
28
|
+
<Link href="/" className="text-lg underline">
|
|
29
|
+
{t('common.page_500.link_text')}
|
|
30
|
+
</Link>
|
|
31
|
+
<Button onClick={reloadPage} className="text-lg">
|
|
32
|
+
{t('common.try_again')}
|
|
33
|
+
</Button>
|
|
34
|
+
</div>
|
|
35
|
+
</section>
|
|
36
|
+
);
|
|
37
|
+
}
|