Skip to content

Commit 45d29fc

Browse files
committed
Render error page on theme asset upload error
1 parent 7db60d6 commit 45d29fc

File tree

2 files changed

+101
-20
lines changed

2 files changed

+101
-20
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
interface Error {
2+
message: string
3+
code: string
4+
}
5+
6+
const POLARIS_STYLESHEET_URL = 'https://unpkg.com/@shopify/[email protected]/build/esm/styles.css'
7+
8+
export function getErrorPage(options: {title: string; header: string; errors: Error[]}) {
9+
const html = String.raw
10+
return html`<!DOCTYPE html>
11+
<html>
12+
<head>
13+
<title>${options.title ?? 'Upload Errors'}</title>
14+
<link rel="stylesheet" href="${POLARIS_STYLESHEET_URL}" />
15+
</head>
16+
<body>
17+
<div style="display: flex; justify-content: center; padding-top: 2rem;">
18+
<div style="width: 80%;">
19+
<div class="Polaris-Banner Polaris-Banner--withinPage" tabindex="0" role="alert" aria-live="polite">
20+
<div class="Polaris-Box" style="--pc-box-width:100%">
21+
<div
22+
class="Polaris-BlockStack"
23+
style="--pc-block-stack-align:space-between;--pc-block-stack-order:column"
24+
>
25+
<div
26+
class="Polaris-Box"
27+
style="--pc-box-color: var(--p-color-text-critical-on-bg-fill); --pc-box-background: var(--p-color-bg-fill-critical); --pc-box-padding-block-start-xs: var(--p-space-300); --pc-box-padding-block-end-xs: var(--p-space-300); --pc-box-padding-inline-start-xs: var(--p-space-300); --pc-box-padding-inline-end-xs: var(--p-space-300); --pc-box-border-start-start-radius: var(--p-border-radius-300); --pc-box-border-start-end-radius: var(--p-border-radius-300);"
28+
>
29+
<div
30+
class="Polaris-InlineStack"
31+
style="--pc-inline-stack-align:space-between;--pc-inline-stack-block-align:center;--pc-inline-stack-wrap:nowrap;--pc-inline-stack-gap-xs:var(--p-space-200);--pc-inline-stack-flex-direction-xs:row"
32+
>
33+
<div
34+
class="Polaris-InlineStack"
35+
style="--pc-inline-stack-wrap:nowrap;--pc-inline-stack-gap-xs:var(--p-space-100);--pc-inline-stack-flex-direction-xs:row"
36+
>
37+
<span class="Polaris-Banner--textCriticalOnBgFill">
38+
<span class="Polaris-Icon">
39+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
40+
<path d="M10 6a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-1.5 0v-3.5a.75.75 0 0 1 .75-.75Z" />
41+
<path d="M11 13a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z" />
42+
<path
43+
fill-rule="evenodd"
44+
d="M17 10a7 7 0 1 1-14 0 7 7 0 0 1 14 0Zm-1.5 0a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0Z"
45+
/>
46+
</svg>
47+
</span>
48+
</span>
49+
<h2 class="Polaris-Text--root Polaris-Text--headingSm Polaris-Text--break">
50+
${options.header}
51+
</h2>
52+
</div>
53+
</div>
54+
</div>
55+
<div
56+
class="Polaris-Box"
57+
style="--pc-box-padding-block-start-xs:var(--p-space-300);--pc-box-padding-block-end-xs:var(--p-space-300);--pc-box-padding-block-end-md:var(--p-space-400);--pc-box-padding-inline-start-xs:var(--p-space-300);--pc-box-padding-inline-start-md:var(--p-space-400);--pc-box-padding-inline-end-xs:var(--p-space-300);--pc-box-padding-inline-end-md:var(--p-space-400)"
58+
>
59+
<div
60+
class="Polaris-BlockStack"
61+
style="--pc-block-stack-order:column;--pc-block-stack-gap-xs:var(--p-space-300)"
62+
>
63+
${options.errors
64+
.map(
65+
(error) => `
66+
<div>
67+
<span class="Polaris-Text--root Polaris-Text--headingSm">${error.message}</span>
68+
<ul class="Polaris-List">
69+
<li class="Polaris-List__Item">${error.code}</li>
70+
</ul>
71+
</div>`,
72+
)
73+
.join('')}
74+
</div>
75+
</div>
76+
</div>
77+
</div>
78+
</div>
79+
</div>
80+
</div>
81+
</body>
82+
</html>`
83+
}

packages/theme/src/cli/utilities/theme-environment/html.ts

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {getProxyStorefrontHeaders, patchRenderingResponse} from './proxy.js'
22
import {getInMemoryTemplates, injectHotReloadScript} from './hot-reload/server.js'
33
import {render} from './storefront-renderer.js'
4+
import {getErrorPage} from './hot-reload/error-page.js'
45
import {getExtensionInMemoryTemplates} from '../theme-ext-environment/theme-ext-server.js'
56
import {logRequestLine} from '../log-request-line.js'
67
import {defineEventHandler, getCookie, setResponseHeader, setResponseStatus, type H3Error} from 'h3'
@@ -31,6 +32,17 @@ export function getHtmlHandler(theme: Theme, ctx: DevServerContext) {
3132

3233
assertThemeId(response, html, String(theme.id))
3334

35+
if (ctx.localThemeFileSystem.uploadErrors.size > 0) {
36+
html = getErrorPage({
37+
title: 'Failed to Upload Theme Files',
38+
header: 'Upload Errors',
39+
errors: Array.from(ctx.localThemeFileSystem.uploadErrors.entries()).map(([file, errors]) => ({
40+
message: file,
41+
code: errors.join('\n'),
42+
})),
43+
})
44+
}
45+
3446
if (ctx.options.liveReload !== 'off') {
3547
html = injectHotReloadScript(html)
3648
}
@@ -52,8 +64,12 @@ export function getHtmlHandler(theme: Theme, ctx: DevServerContext) {
5264
let errorPageHtml = getErrorPage({
5365
title,
5466
header: title,
55-
message: [...rest, cause?.message ?? error.message].join('<br>'),
56-
code: error.stack?.replace(`${error.message}\n`, '') ?? '',
67+
errors: [
68+
{
69+
message: [...rest, cause?.message ?? error.message].join('<br>'),
70+
code: error.stack?.replace(`${error.message}\n`, '') ?? '',
71+
},
72+
],
5773
})
5874

5975
if (ctx.options.liveReload !== 'off') {
@@ -65,24 +81,6 @@ export function getHtmlHandler(theme: Theme, ctx: DevServerContext) {
6581
})
6682
}
6783

68-
function getErrorPage(options: {title: string; header: string; message: string; code: string}) {
69-
const html = String.raw
70-
71-
return html`<html>
72-
<head>
73-
<title>${options.title ?? 'Unknown error'}</title>
74-
</head>
75-
<body
76-
id="full-error-page"
77-
style="display: flex; flex-direction: column; align-items: center; padding-top: 20px; font-family: Arial"
78-
>
79-
<h2>${options.header}</h2>
80-
<p>${options.message}</p>
81-
<pre>${options.code}</pre>
82-
</body>
83-
</html>`
84-
}
85-
8684
function assertThemeId(response: Response, html: string, expectedThemeId: string) {
8785
/**
8886
* DOM example:

0 commit comments

Comments
 (0)