@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 CHANGED
@@ -1,6 +1,10 @@
1
1
  # @akinon/projectzero
2
2
 
3
- ## 2.0.63-beta.0
3
+ ## 2.0.63
4
+
5
+ ### Patch Changes
6
+
7
+ - 72a62c6: ZERO-4823: Implement 404 and 500 pages for theme editor
4
8
 
5
9
  ## 2.0.62
6
10
 
@@ -1,37 +1,38 @@
1
1
  # projectzeronext
2
2
 
3
- ## 2.0.63-beta.0
4
-
5
- ### Patch Changes
6
-
7
- - Updated dependencies [cbbbfd75]
8
- - @akinon/next@2.0.63-beta.0
9
- - @akinon/pz-theme@2.0.63-beta.0
10
- - @akinon/pz-virtual-try-on@2.0.63-beta.0
11
- - @akinon/pz-akifast@2.0.63-beta.0
12
- - @akinon/pz-apple-pay@2.0.63-beta.0
13
- - @akinon/pz-b2b@2.0.63-beta.0
14
- - @akinon/pz-basket-gift-pack@2.0.63-beta.0
15
- - @akinon/pz-bkm@2.0.63-beta.0
16
- - @akinon/pz-checkout-gift-pack@2.0.63-beta.0
17
- - @akinon/pz-click-collect@2.0.63-beta.0
18
- - @akinon/pz-credit-payment@2.0.63-beta.0
19
- - @akinon/pz-cybersource-uc@2.0.63-beta.0
20
- - @akinon/pz-flow-payment@2.0.63-beta.0
21
- - @akinon/pz-google-pay@2.0.63-beta.0
22
- - @akinon/pz-gpay@2.0.63-beta.0
23
- - @akinon/pz-haso@2.0.63-beta.0
24
- - @akinon/pz-hepsipay@2.0.63-beta.0
25
- - @akinon/pz-masterpass@2.0.63-beta.0
26
- - @akinon/pz-masterpass-rest@2.0.63-beta.0
27
- - @akinon/pz-multi-basket@2.0.63-beta.0
28
- - @akinon/pz-one-click-checkout@2.0.63-beta.0
29
- - @akinon/pz-otp@2.0.63-beta.0
30
- - @akinon/pz-pay-on-delivery@2.0.63-beta.0
31
- - @akinon/pz-saved-card@2.0.63-beta.0
32
- - @akinon/pz-similar-products@2.0.63-beta.0
33
- - @akinon/pz-tabby-extension@2.0.63-beta.0
34
- - @akinon/pz-tamara-extension@2.0.63-beta.0
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-beta.0",
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-beta.0",
28
- "@akinon/pz-akifast": "2.0.63-beta.0",
29
- "@akinon/pz-apple-pay": "2.0.63-beta.0",
30
- "@akinon/pz-b2b": "2.0.63-beta.0",
31
- "@akinon/pz-basket-gift-pack": "2.0.63-beta.0",
32
- "@akinon/pz-bkm": "2.0.63-beta.0",
33
- "@akinon/pz-checkout-gift-pack": "2.0.63-beta.0",
34
- "@akinon/pz-click-collect": "2.0.63-beta.0",
35
- "@akinon/pz-credit-payment": "2.0.63-beta.0",
36
- "@akinon/pz-cybersource-uc": "2.0.63-beta.0",
37
- "@akinon/pz-flow-payment": "2.0.63-beta.0",
38
- "@akinon/pz-google-pay": "2.0.63-beta.0",
39
- "@akinon/pz-gpay": "2.0.63-beta.0",
40
- "@akinon/pz-haso": "2.0.63-beta.0",
41
- "@akinon/pz-hepsipay": "2.0.63-beta.0",
42
- "@akinon/pz-masterpass": "2.0.63-beta.0",
43
- "@akinon/pz-masterpass-rest": "2.0.63-beta.0",
44
- "@akinon/pz-multi-basket": "2.0.63-beta.0",
45
- "@akinon/pz-one-click-checkout": "2.0.63-beta.0",
46
- "@akinon/pz-otp": "2.0.63-beta.0",
47
- "@akinon/pz-pay-on-delivery": "2.0.63-beta.0",
48
- "@akinon/pz-saved-card": "2.0.63-beta.0",
49
- "@akinon/pz-similar-products": "2.0.63-beta.0",
50
- "@akinon/pz-tabby-extension": "2.0.63-beta.0",
51
- "@akinon/pz-tamara-extension": "2.0.63-beta.0",
52
- "@akinon/pz-theme": "2.0.63-beta.0",
53
- "@akinon/pz-virtual-try-on": "2.0.63-beta.0",
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-beta.0",
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
- <OfflineFallback>{children}</OfflineFallback>
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 { Button, Link } from '@theme/components';
5
- import { useLocalization } from '@akinon/next/hooks';
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
- <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>
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
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akinon/projectzero",
3
- "version": "2.0.63-beta.0",
3
+ "version": "2.0.63",
4
4
  "private": false,
5
5
  "description": "CLI tool to manage your Project Zero Next project",
6
6
  "bin": {