@stacksjs/error-handling 0.72.49 → 0.72.51
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/dist/error-illustrations.d.ts +33 -0
- package/dist/error-illustrations.js +1 -0
- package/dist/error-page-styles.js +80 -14
- package/dist/error-page.d.ts +7 -1
- package/dist/error-page.js +12 -8
- package/dist/index.d.ts +7 -0
- package/dist/index.js +1 -1
- package/package.json +7 -7
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pick the illustration that fits an HTTP status.
|
|
3
|
+
*
|
|
4
|
+
* Four scenes have to cover every status in `HTTP_ERRORS`, so they are grouped
|
|
5
|
+
* by what the visitor is being told rather than by status class.
|
|
6
|
+
*/
|
|
7
|
+
export declare function illustrationForStatus(status: number): ErrorIllustration;
|
|
8
|
+
/** Inline SVG markup for the illustration matching `status`. */
|
|
9
|
+
export declare function errorIllustration(status: number): string;
|
|
10
|
+
/** Inline SVG markup for each illustration, keyed by name. */
|
|
11
|
+
export declare const ERROR_ILLUSTRATIONS: Record<ErrorIllustration, string>;
|
|
12
|
+
/**
|
|
13
|
+
* Error page illustrations.
|
|
14
|
+
*
|
|
15
|
+
* Four desert scenes drawn by Steve Schoger for Laravel 5.7, which shipped
|
|
16
|
+
* them in `public/svg/` and rendered them through `errors::illustrated-layout`.
|
|
17
|
+
* Laravel 5.8 moved its error views onto the minimal layout and the artwork
|
|
18
|
+
* was dropped. They are vendored here under Laravel's MIT licence:
|
|
19
|
+
* https://github.com/laravel/laravel/tree/v5.7.0/public/svg
|
|
20
|
+
*
|
|
21
|
+
* The markup is inlined as strings rather than read from disk or linked as
|
|
22
|
+
* `/svgs/<status>.svg`, for two reasons. The package build transpiles the
|
|
23
|
+
* TypeScript under `src/` and copies nothing else, so an `.svg` sitting next
|
|
24
|
+
* to this file would never reach `dist/`. And an error page that depends on a
|
|
25
|
+
* second request succeeding is an error page that fails in exactly the
|
|
26
|
+
* conditions it exists to cover.
|
|
27
|
+
*
|
|
28
|
+
* `public/svgs/` keeps the unmodified originals for app templates to use. The
|
|
29
|
+
* copies below differ only in the attributes added to the root `<svg>` element,
|
|
30
|
+
* which make them behave as a cover-fitted, decorative background when inlined.
|
|
31
|
+
*/
|
|
32
|
+
/** The four illustrations, each named for the status it was drawn for. */
|
|
33
|
+
export type ErrorIllustration = '403' | '404' | '500' | '503';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function illustrationForStatus(status){switch(status){case 401:case 403:return"403";case 404:case 405:case 410:return"404";case 408:case 429:case 502:case 503:case 504:return"503";case 400:case 409:case 422:case 500:return"500"}return status>=400&&status<500?"404":"500"}export function errorIllustration(status){return ERROR_ILLUSTRATIONS[illustrationForStatus(status)]}export const ERROR_ILLUSTRATIONS={"403":'<svg aria-hidden="true" focusable="false" preserveAspectRatio="xMidYMid slice" width="100%" height="100%" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient id="a" x1="50%" x2="50%" y1="100%" y2="0%"><stop offset="0" stop-color="#76c3c3"/><stop offset="1" stop-color="#183468"/></linearGradient><linearGradient id="b" x1="100%" x2="0%" y1="50%" y2="50%"><stop offset="0" stop-color="#486587"/><stop offset=".3323" stop-color="#183352"/><stop offset=".6667" stop-color="#264a6e"/><stop offset="1" stop-color="#183352"/></linearGradient><linearGradient id="c" x1="49.87%" x2="48.5%" y1="3.62%" y2="100%"><stop offset="0" stop-color="#e0f2fa"/><stop offset=".0898" stop-color="#89bed6"/><stop offset=".3298" stop-color="#1e3c6e"/><stop offset="1" stop-color="#1b376b"/></linearGradient><linearGradient id="d"><stop offset="0" stop-color="#b0ddf1"/><stop offset="1" stop-color="#325c82"/></linearGradient><linearGradient id="e" x1="49.87%" x2="49.87%" xlink:href="#d" y1="3.62%" y2="77.75%"/><linearGradient id="f"><stop offset="0" stop-color="#1d3a6d"/><stop offset="1" stop-color="#467994"/></linearGradient><linearGradient id="g" x1="91.59%" x2="66.97%" xlink:href="#f" y1="5.89%" y2="100%"/><linearGradient id="h" x1="97.27%" x2="52.53%" xlink:href="#f" y1="6.88%" y2="100%"/><linearGradient id="i" x1="82.73%" x2="41.46%" xlink:href="#f" y1="41.06%" y2="167.23%"/><linearGradient id="j" x1="49.87%" x2="49.87%" xlink:href="#d" y1="3.62%" y2="100.77%"/><linearGradient id="k" x1="100%" x2="72.45%" xlink:href="#f" y1="0%" y2="85.2%"/><linearGradient id="l" x1="100%" x2="62.1%" y1="0%" y2="68.86%"><stop offset="0" stop-color="#163055"/><stop offset="1" stop-color="#2f587f"/></linearGradient><circle id="m" cx="180" cy="102" r="40"/><filter id="n" height="340%" width="340%" x="-120%" y="-120%"><feOffset in="SourceAlpha" result="shadowOffsetOuter1"/><feGaussianBlur in="shadowOffsetOuter1" result="shadowBlurOuter1" stdDeviation="32"/><feColorMatrix in="shadowBlurOuter1" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.696473053 0"/></filter><linearGradient id="o" x1="0%" y1="50%" y2="50%"><stop offset="0" stop-color="#fff" stop-opacity="0"/><stop offset="1" stop-color="#fff"/></linearGradient></defs><g fill="none" fill-rule="evenodd"><path d="m0 0h1024v1024h-1024z" fill="url(#a)"/><g transform="translate(761 481)"><path d="m96 27 4-1v11h-4z" fill="#8dbcd2"/><path d="m76 23 4-1v15h-4z" fill="#8dbcd2"/><g fill="#183352"><path d="m40 22 4 1v14h-4z"/><path d="m20 26 4 1v14h-4z"/><path d="m59 0h2v20h-2z" opacity=".5"/></g><path d="m61 0c3 0 3 2 6 2s3-2 6-2 3 2 6 2v8c-3 0-3-2-6-2s-3 2-6 2-3-2-6-2z" fill="url(#b)"/><path d="m50 20 10-2v110h-60l10-100 10-2v10.92l10-.98v-11.94l10-2v12.96l10-.98z" fill="#8dbcd2"/><path d="m100 26 10 2 10 100h-60v-110l10 2v13.98l10 .98v-12.96l10 2v11.94l10 .98z" fill="#183352"/></g><g transform="translate(0 565)"><path d="m1024 385h-1024v-278.14c118.4 21.09 185.14 57.03 327.4 48.14 198.54-12.4 250-125 500-125 90.18 0 147.92 16.3 196.6 37.12z" fill="url(#c)"/><path d="m1024 355h-1024v-275.44c76.46-35.75 137.14-79.56 285-79.56 250 0 301.46 112.6 500 125 103.24 6.45 166.7-10.7 239-28.66z" fill="url(#e)"/><path d="m344.12 130.57c23.1 13.47-25.27 81.95-145.12 205.43h649c-344.06-141.7-512.02-210.17-503.88-205.43z" fill="url(#e)"/><path d="m0 336v-256.44c76.46-35.75 137.14-79.56 285-79.56 71.14 0 86.22 26.04 32.5 82-48 50 147.33 58.02 36 136.5-40.67 28.67 21.17 67.83 185.5 117.5z" fill="url(#g)"/><path d="m317.5 82c-48 50 147.33 58.02 36 136.5-40.67 28.67 21.17 67.83 185.5 117.5h-484z" fill="url(#h)"/><path d="m353.5 218.5c-40.67 28.67 21.17 67.83 185.5 117.5h-364z" fill="url(#i)"/><path d="m0 459v-194.46c100.25 21.2 167.18 50.29 296.67 42.19 198.57-12.43 250.04-125.15 500.07-125.15 109.75 0 171.47 24.16 227.26 51.25v226.17z" fill="url(#j)"/><path d="m1024 459h-177.84c51.95-58.9 48.86-97.16-9.28-114.78-186.64-56.58-101.76-162.64-39.97-162.64 109.64 0 171.34 24.12 227.09 51.19z" fill="url(#k)"/><path d="m1024 459h-177.81c52.01-59.01 48.94-97.34-9.22-115l187.03 53.48z" fill="url(#l)"/></g><g transform="translate(94 23)"><use fill="#000" filter="url(#n)" xlink:href="#m"/><use fill="#d2f1fe" xlink:href="#m"/><g fill="#fff"><circle cx="123" cy="255" fill-opacity=".4" r="3"/><circle cx="2" cy="234" r="2"/><circle cx="33" cy="65" r="3"/><circle cx="122" cy="2" r="2"/><circle cx="72" cy="144" r="2"/><circle cx="282" cy="224" r="2"/><circle cx="373" cy="65" opacity=".4" r="3"/><circle cx="433" cy="255" r="3"/></g><path d="m373.25 325.25a5 5 0 0 0 0-10h-75v10z" fill="url(#o)" opacity=".4" transform="matrix(.70710678 .70710678 -.70710678 .70710678 325.523078 -145.38023)"/><g fill="#fff"><circle cx="363" cy="345" r="3"/><circle cx="513" cy="115" r="3"/><circle cx="723" cy="5" opacity=".4" r="3"/><circle cx="422" cy="134" r="2"/><circle cx="752" cy="204" r="2"/><circle cx="672" cy="114" r="2"/><circle cx="853" cy="255" opacity=".4" r="3"/><circle cx="623" cy="225" r="3"/><circle cx="823" cy="55" r="3"/><circle cx="902" cy="144" r="2"/><circle cx="552" cy="14" r="2"/></g></g><path d="m796 535a4 4 0 0 1 4 4v20h-8v-20a4 4 0 0 1 4-4z" fill="#486587"/><path d="m798 535.54a4 4 0 0 0 -2 3.46v20h-4v-20a4 4 0 0 1 6-3.46zm48-.54a4 4 0 0 1 4 4v20h-8v-20a4 4 0 0 1 4-4z" fill="#071423"/><path d="m846 559v-20a4 4 0 0 0 -2-3.46 4 4 0 0 1 6 3.46v20z" fill="#8dbcd2"/><path d="m554.67 131.48a9.46 9.46 0 0 1 13.33 0 9.46 9.46 0 0 0 13.33 0l13.33-13.24a28.39 28.39 0 0 1 40 0l10 9.93a14.2 14.2 0 0 0 20 0 14.2 14.2 0 0 1 20 0l.6.6a31.8 31.8 0 0 1 9.4 22.56h-146.66v-3.84c0-6.01 2.4-11.78 6.67-16.01zm196.33-123.23c11.07-11 28.93-11 40 0l10 9.94a14.19 14.19 0 0 0 20 0 14.19 14.19 0 0 1 20 0 16.36 16.36 0 0 0 21.3 1.5l8.7-6.47a33.47 33.47 0 0 1 40 0l4.06 3.03a39.6 39.6 0 0 1 15.94 31.75h-200c0-12.72 8.93-28.75 20-39.75zm-736.9 66.89.9-.9a21.29 21.29 0 0 1 30 0 21.29 21.29 0 0 0 30 0l10-9.93a35.48 35.48 0 0 1 50 0l15 14.9a14.2 14.2 0 0 0 20 0 14.2 14.2 0 0 1 20 0c6.4 6.35 10 15 10 24.02v5.77h-200c0-12.71 5.07-24.9 14.1-33.86z" fill="#fff" opacity=".07" transform="translate(54 301)"/></g></svg>',"404":'<svg aria-hidden="true" focusable="false" preserveAspectRatio="xMidYMid slice" width="100%" height="100%" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient id="a" x1="50.31%" x2="50%" y1="74.74%" y2="0%"><stop offset="0" stop-color="#ffe98a"/><stop offset=".677" stop-color="#b63e59"/><stop offset="1" stop-color="#68126f"/></linearGradient><circle id="b" cx="603" cy="682" r="93"/><filter id="c" height="203.2%" width="203.2%" x="-51.6%" y="-51.6%"><feOffset in="SourceAlpha" result="shadowOffsetOuter1"/><feGaussianBlur in="shadowOffsetOuter1" result="shadowBlurOuter1" stdDeviation="32"/><feColorMatrix in="shadowBlurOuter1" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/></filter><linearGradient id="d"><stop offset="0" stop-color="#f7eab9"/><stop offset="1" stop-color="#e5765e"/></linearGradient><linearGradient id="e" x1="49.48%" x2="49.87%" xlink:href="#d" y1="11.66%" y2="77.75%"/><linearGradient id="f"><stop offset="0" stop-color="#a22a50"/><stop offset="1" stop-color="#ee7566"/></linearGradient><linearGradient id="g" x1="91.59%" x2="66.97%" xlink:href="#f" y1="5.89%" y2="100%"/><linearGradient id="h" x1="49.48%" x2="49.61%" xlink:href="#d" y1="11.66%" y2="98.34%"/><linearGradient id="i" x1="78.5%" x2="36.4%" xlink:href="#f" y1="106.76%" y2="26.41%"/></defs><g fill="none" fill-rule="evenodd"><path d="m0 0h1024v1024h-1024z" fill="url(#a)"/><use fill="#000" filter="url(#c)" xlink:href="#b"/><use fill="#fff6cb" xlink:href="#b"/><g fill="#fff" opacity=".3"><circle cx="217" cy="278" fill-opacity=".4" r="3"/><circle cx="96" cy="257" r="2"/><circle cx="36" cy="287" opacity=".4" r="2"/><circle cx="127" cy="88" r="3"/><circle cx="216" cy="25" r="2"/><circle cx="16" cy="137" r="2"/><circle cx="166" cy="167" r="2"/><circle cx="376" cy="247" r="2"/><circle cx="467" cy="88" opacity=".4" r="3"/><circle cx="527" cy="278" r="3"/><circle cx="607" cy="138" r="3"/><circle cx="817" cy="28" opacity=".4" r="3"/><circle cx="516" cy="157" r="2"/><circle cx="846" cy="227" r="2"/><circle cx="766" cy="137" r="2"/><circle cx="947" cy="278" opacity=".4" r="3"/><circle cx="717" cy="248" r="3"/><circle cx="917" cy="78" r="3"/><circle cx="996" cy="167" r="2"/><circle cx="646" cy="37" r="2"/></g><g transform="translate(0 550)"><path d="m259 5.47c0 5.33 3.33 9.5 10 12.5s9.67 9.16 9 18.5h1c.67-6.31 1-11.8 1-16.47 8.67 0 13.33-1.33 14-4 .67 4.98 1.67 8.3 3 9.97 1.33 1.66 2 5.16 2 10.5h1c0-5.65.33-9.64 1-11.97 1-3.5 4-10.03-1-14.53s-5-2.97-10-6.97-10-3-13 2-5 7-9 7-5-3.53-5-5.53 2-5-1.5-5-7.5 0-7.5 2c0 1.33 1.67 2 5 2z" fill="#8e2c15"/><path d="m1024 390h-1024v-284.92c77.3-33.68 155.26-70.08 297.4-70.08 250 0 250.76 125.25 500 125 84.03-.08 160.02-18.2 226.6-40.93z" fill="url(#e)"/><path d="m1024 442h-1024v-170.18c137.51-15.4 203.1-50.49 356.67-60.1 198.57-12.42 250.04-125.13 500.07-125.13 72.78 0 124.44 10.62 167.26 25.68z" fill="url(#e)"/><path d="m1024 112.21v299.79h-167.09c99.31-86.5 112.63-140.75 39.97-162.78-186.64-56.58-101.76-162.64-39.98-162.64 72.7 0 124.3 10.6 167.09 25.63z" fill="url(#g)"/><path d="m1024 285.32v126.68h-167c99.31-86.6 112.63-140.94 39.97-163z" fill="url(#g)"/><path d="m0 474v-250.07c67.12-33.24 129.55-68.93 263-68.93 250 0 331.46 162.6 530 175 107.42 6.71 163-26.77 231-58.92v202.92z" fill="url(#h)"/><path d="m353.02 474h-353.02v-250.07c67.12-33.24 129.55-68.93 263-68.93 71.14 0 151.5 12.76 151.5 70.5 0 54.5-45.5 79.72-112.5 109-82.26 35.95-54.57 111.68 51.02 139.5z" fill="url(#g)"/><path d="m353.02 474h-353.02v-14.8l302-124.7c-82.26 35.95-54.57 111.68 51.02 139.5z" fill="url(#i)"/></g><g fill="#fff"><g opacity=".2"><circle cx="538" cy="633" r="110"/><circle cx="708" cy="601" r="60"/><circle cx="358" cy="743" r="70"/></g><path d="m10 80.22a14.2 14.2 0 0 1 20 0 14.2 14.2 0 0 0 20 0l20-19.86a42.58 42.58 0 0 1 60 0l15 14.9a21.3 21.3 0 0 0 30 0 21.3 21.3 0 0 1 30 0l.9.9a47.69 47.69 0 0 1 14.1 33.84h-220v-5.76c0-9.02 3.6-17.67 10-24.02zm559.1-66.11 5.9-5.86c11.07-11 28.93-11 40 0l10 9.94a14.19 14.19 0 0 0 20 0 14.19 14.19 0 0 1 20 0 16.36 16.36 0 0 0 21.3 1.5l8.7-6.47a33.47 33.47 0 0 1 40 0l4.06 3.03a39.6 39.6 0 0 1 15.94 31.75h-200a47.77 47.77 0 0 1 14.1-33.89z" fill-rule="nonzero" opacity=".08" transform="translate(135 316)"/></g></g></svg>',"500":'<svg aria-hidden="true" focusable="false" preserveAspectRatio="xMidYMid slice" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1024 1024"><defs><linearGradient id="a" x1="50%" x2="50%" y1="100%" y2="0%"><stop offset="0%" stop-color="#F6EDAE"/><stop offset="100%" stop-color="#91D4D7"/></linearGradient><linearGradient id="b" x1="49.87%" x2="49.87%" y1="3.62%" y2="77.75%"><stop offset="0%" stop-color="#B0DDF1"/><stop offset="100%" stop-color="#325C82"/></linearGradient><linearGradient id="c" x1="100%" x2="72.45%" y1="0%" y2="85.2%"><stop offset="0%" stop-color="#1D3A6D"/><stop offset="100%" stop-color="#467994"/></linearGradient><linearGradient id="d" x1="54.81%" x2="50%" y1="-18.48%" y2="59.98%"><stop offset="0%" stop-color="#FFFFFF"/><stop offset="28.15%" stop-color="#F8E6B3"/><stop offset="100%" stop-color="#D5812F"/></linearGradient><linearGradient id="e" x1="52.84%" x2="49.87%" y1="2.8%" y2="77.75%"><stop offset="0%" stop-color="#FFFFFF"/><stop offset="22.15%" stop-color="#F8E6B3"/><stop offset="100%" stop-color="#F9D989"/></linearGradient><linearGradient id="f" x1="91.59%" x2="66.97%" y1="5.89%" y2="100%"><stop offset="0%" stop-color="#CE4014"/><stop offset="100%" stop-color="#FFD56E"/></linearGradient><linearGradient id="g" x1="40.28%" x2="66.37%" y1="30.88%" y2="108.51%"><stop offset="0%" stop-color="#A2491E"/><stop offset="100%" stop-color="#F4B35A"/></linearGradient><circle id="i" cx="825" cy="235" r="70"/><filter id="h" width="237.1%" height="237.1%" x="-68.6%" y="-68.6%" filterUnits="objectBoundingBox"><feOffset in="SourceAlpha" result="shadowOffsetOuter1"/><feGaussianBlur in="shadowOffsetOuter1" result="shadowBlurOuter1" stdDeviation="32"/><feColorMatrix in="shadowBlurOuter1" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/></filter><linearGradient id="j" x1="50%" x2="50%" y1="0%" y2="100%"><stop offset="0%" stop-color="#B29959"/><stop offset="100%" stop-color="#CEAD5B"/></linearGradient></defs><g fill="none" fill-rule="evenodd"><rect width="1024" height="1024" fill="url(#a)"/><path fill="#FFFFFF" d="M1024 378.13v39.37H790a71.59 71.59 0 0 1 21.14-50.8l1.36-1.34a31.93 31.93 0 0 1 45 0 31.93 31.93 0 0 0 45 0l15-14.9a53.21 53.21 0 0 1 75 0l22.5 22.35a21.2 21.2 0 0 0 9 5.32z" opacity=".15"/><g transform="translate(26 245)"><path fill="url(#b)" d="M289.12 450.57C312.22 464.04 263.85 532.52 144 656h649C448.94 514.3 280.98 445.83 289.12 450.57z"/><path fill="url(#c)" d="M262.5 402c-48 50 147.33 58.02 36 136.5-40.67 28.67 21.17 67.83 185.5 117.5H0l262.5-254z"/><path fill="url(#c)" d="M298.5 538.5C257.83 567.17 319.67 606.33 484 656H120l178.5-117.5z"/></g><path fill="#134F4E" d="M783 593.73a29.95 29.95 0 0 1-12-24c0-9.8 4.72-18.52 12-24-5.02 6.69-8 15-8 24 0 9.01 2.98 17.32 8 24z"/><g fill="#134F4E" transform="matrix(-1 0 0 1 876 532)"><path d="M24 66.73a29.95 29.95 0 0 1-12-24c0-9.8 4.72-18.52 12-24-5.02 6.69-8 15-8 24 0 9.01 2.98 17.32 8 24z"/><path d="M36 22.4l-3.96-3.98a5 5 0 0 0-6.5-.5 3 3 0 0 1 3.7-3.55l8.7 2.33a8 8 0 0 1 5.66 9.8l-1-1.73a2 2 0 0 0-1.21-.93L36 22.4zm-5.38-2.56L37 26.2a8 8 0 0 1 0 11.32v-2a2 2 0 0 0-.6-1.42L26.39 24.08a3 3 0 0 1 4.24-4.24zM14.21 9.8l-3.94-3.94a2 2 0 0 0-1.42-.59h-2a8 8 0 0 1 11.32 0l6.36 6.37a3 3 0 0 1-1.22 4.98 5 5 0 0 0-3.68-5.37l-5.42-1.45zm4.9 3.39a3 3 0 1 1-1.55 5.8L3.87 15.31a2 2 0 0 0-1.52.2l-1.73 1a8 8 0 0 1 9.8-5.65l8.7 2.33z"/></g><g transform="translate(0 245)"><path fill="url(#d)" d="M1024 423.16V645H58.09c-32.12-75.17-32.12-123.84 0-146 48.17-33.24 127.17-64.25 293.33-64 166.17.25 246.67-105 413.33-105 117.33 0 183.93 55.8 259.25 93.16z"/><path fill="url(#e)" d="M1024 778H0V398.62C75.53 363.05 136.43 320 283 320c111.86 0 358.86 69.82 741 209.47V778z"/><path fill="url(#f)" d="M0 778V398.62C75.53 363.05 136.43 320 283 320c71.14 0 85.96 26.04 32.5 82-79.5 83.22 279.7 2.01 336 131.5 26 59.8-69.83 141.3-287.48 244.5H0z"/><path fill="url(#g)" d="M364.02 778H0V638.4L315.5 402c-79.5 83.22 279.7 2.01 336 131.5 26 59.8-69.83 141.3-287.48 244.5z"/></g><path fill="#134F4E" d="M795 549.4l-3.96-3.98a5 5 0 0 0-6.5-.5 3 3 0 0 1 3.7-3.55l8.7 2.33a8 8 0 0 1 5.66 9.8l-1-1.73a2 2 0 0 0-1.21-.93L795 549.4zm-5.38-2.56l6.37 6.36a8 8 0 0 1 0 11.32v-2a2 2 0 0 0-.6-1.42l-10.01-10.02a3 3 0 0 1 4.24-4.24zm-16.41-10.03l-3.94-3.94a2 2 0 0 0-1.42-.59h-2a8 8 0 0 1 11.32 0l6.36 6.37a3 3 0 0 1-1.22 4.98 5 5 0 0 0-3.68-5.37l-5.42-1.45zm4.9 3.39a3 3 0 1 1-1.55 5.8l-13.69-3.68a2 2 0 0 0-1.52.2l-1.73 1a8 8 0 0 1 9.8-5.65l8.7 2.33z"/><path fill="#FFFFFF" d="M395.67 116.48a9.46 9.46 0 0 1 13.33 0 9.46 9.46 0 0 0 13.33 0l13.33-13.24a28.39 28.39 0 0 1 40 0l10 9.93a14.2 14.2 0 0 0 20 0 14.2 14.2 0 0 1 20 0l.6.6a31.8 31.8 0 0 1 9.4 22.56H389v-3.84c0-6.01 2.4-11.78 6.67-16.01zM98.1 249.1l5.9-5.86c11.07-11 28.93-11 40 0l10 9.94a14.19 14.19 0 0 0 20 0 14.19 14.19 0 0 1 20 0 16.36 16.36 0 0 0 21.3 1.5l8.7-6.47a33.47 33.47 0 0 1 40 0l4.06 3.03A39.6 39.6 0 0 1 284 283H84a47.77 47.77 0 0 1 14.1-33.89z" opacity=".15"/><use fill="black" filter="url(#h)" xlink:href="#i"/><use fill="#FFFFFF" xlink:href="#i"/><path fill="#FFFFFF" d="M702.69 960.64a4.32 4.32 0 0 1-1.04 6.87c-2.26 1.2-3.69 2.1-4.27 2.67-.51.52-1.17 1.4-1.97 2.62a3.53 3.53 0 0 1-5.45.56 3.53 3.53 0 0 1 .56-5.44c1.23-.8 2.1-1.46 2.62-1.98.58-.58 1.47-2 2.67-4.27a4.32 4.32 0 0 1 6.88-1.03z" opacity=".6"/><path fill="url(#j)" d="M700.32 962a4.32 4.32 0 0 1 4.13 5.6c-.75 2.45-1.13 4.08-1.13 4.9 0 .73.15 1.81.45 3.25a3.53 3.53 0 0 1-3.45 4.25 3.53 3.53 0 0 1-3.45-4.25c.3-1.44.45-2.52.45-3.25 0-.82-.37-2.45-1.13-4.9a4.32 4.32 0 0 1 4.13-5.6z" transform="rotate(45 700.323 971)"/><g transform="rotate(-15 3943.802 -2244.376)"><path fill="#FFFFFF" d="M16.65 3.9a4.32 4.32 0 0 1-1.03 6.87c-2.27 1.2-3.7 2.1-4.27 2.67-.52.52-1.18 1.4-1.98 2.62a3.53 3.53 0 0 1-5.44.56 3.53 3.53 0 0 1 .56-5.44c1.23-.8 2.1-1.46 2.62-1.98.58-.58 1.47-2 2.67-4.27a4.32 4.32 0 0 1 6.87-1.03z" opacity=".6"/><path fill="url(#j)" d="M13.32 5a4.32 4.32 0 0 1 4.13 5.6c-.75 2.45-1.13 4.08-1.13 4.9 0 .73.15 1.81.45 3.25A3.53 3.53 0 0 1 13.32 23a3.53 3.53 0 0 1-3.45-4.25c.3-1.44.45-2.52.45-3.25 0-.82-.37-2.45-1.13-4.9A4.32 4.32 0 0 1 13.32 5z" transform="rotate(45 13.323 14)"/></g><g transform="rotate(-15 4117.1 -2152.014)"><path fill="#FFFFFF" d="M16.65 3.9a4.32 4.32 0 0 1-1.03 6.87c-2.27 1.2-3.7 2.1-4.27 2.67-.52.52-1.18 1.4-1.98 2.62a3.53 3.53 0 0 1-5.44.56 3.53 3.53 0 0 1 .56-5.44c1.23-.8 2.1-1.46 2.62-1.98.58-.58 1.47-2 2.67-4.27a4.32 4.32 0 0 1 6.87-1.03z" opacity=".6"/><path fill="url(#j)" d="M13.32 5a4.32 4.32 0 0 1 4.13 5.6c-.75 2.45-1.13 4.08-1.13 4.9 0 .73.15 1.81.45 3.25A3.53 3.53 0 0 1 13.32 23a3.53 3.53 0 0 1-3.45-4.25c.3-1.44.45-2.52.45-3.25 0-.82-.37-2.45-1.13-4.9A4.32 4.32 0 0 1 13.32 5z" transform="rotate(45 13.323 14)"/></g><g transform="rotate(-15 4127.186 -2023.184)"><path fill="#FFFFFF" d="M16.65 3.9a4.32 4.32 0 0 1-1.03 6.87c-2.27 1.2-3.7 2.1-4.27 2.67-.52.52-1.18 1.4-1.98 2.62a3.53 3.53 0 0 1-5.44.56 3.53 3.53 0 0 1 .56-5.44c1.23-.8 2.1-1.46 2.62-1.98.58-.58 1.47-2 2.67-4.27a4.32 4.32 0 0 1 6.87-1.03z" opacity=".6"/><path fill="url(#j)" d="M13.32 5a4.32 4.32 0 0 1 4.13 5.6c-.75 2.45-1.13 4.08-1.13 4.9 0 .73.15 1.81.45 3.25A3.53 3.53 0 0 1 13.32 23a3.53 3.53 0 0 1-3.45-4.25c.3-1.44.45-2.52.45-3.25 0-.82-.37-2.45-1.13-4.9A4.32 4.32 0 0 1 13.32 5z" transform="rotate(45 13.323 14)"/></g><g transform="rotate(-30 2055.753 -866.842)"><path fill="#FFFFFF" d="M16.55 3.4a4.32 4.32 0 0 1-1.03 6.88c-2.27 1.2-3.7 2.1-4.27 2.67-.52.52-1.18 1.39-1.98 2.62a3.53 3.53 0 0 1-5.44.56 3.53 3.53 0 0 1 .56-5.44c1.23-.8 2.1-1.46 2.62-1.98.58-.58 1.47-2 2.67-4.27a4.32 4.32 0 0 1 6.87-1.04z" opacity=".6"/><path fill="url(#j)" d="M12.32 6a4.32 4.32 0 0 1 4.13 5.6c-.75 2.45-1.13 4.08-1.13 4.9 0 .73.15 1.81.45 3.25A3.53 3.53 0 0 1 12.32 24a3.53 3.53 0 0 1-3.45-4.25c.3-1.44.45-2.52.45-3.25 0-.82-.37-2.45-1.13-4.9A4.32 4.32 0 0 1 12.32 6z" transform="rotate(45 12.323 15)"/></g><g transform="rotate(-30 2046.995 -931.189)"><path fill="#FFFFFF" d="M16.55 3.4a4.32 4.32 0 0 1-1.03 6.88c-2.27 1.2-3.7 2.1-4.27 2.67-.52.52-1.18 1.39-1.98 2.62a3.53 3.53 0 0 1-5.44.56 3.53 3.53 0 0 1 .56-5.44c1.23-.8 2.1-1.46 2.62-1.98.58-.58 1.47-2 2.67-4.27a4.32 4.32 0 0 1 6.87-1.04z" opacity=".6"/><path fill="url(#j)" d="M12.32 6a4.32 4.32 0 0 1 4.13 5.6c-.75 2.45-1.13 4.08-1.13 4.9 0 .73.15 1.81.45 3.25A3.53 3.53 0 0 1 12.32 24a3.53 3.53 0 0 1-3.45-4.25c.3-1.44.45-2.52.45-3.25 0-.82-.37-2.45-1.13-4.9A4.32 4.32 0 0 1 12.32 6z" transform="rotate(45 12.323 15)"/></g><g transform="rotate(-45 1406.147 -409.132)"><path fill="#FFFFFF" d="M16.93 3.22a4.32 4.32 0 0 1-1.03 6.88c-2.27 1.2-3.7 2.09-4.27 2.67-.52.52-1.18 1.39-1.98 2.61a3.53 3.53 0 0 1-5.45.57 3.53 3.53 0 0 1 .57-5.45c1.22-.8 2.1-1.46 2.61-1.97.58-.58 1.47-2 2.67-4.27a4.32 4.32 0 0 1 6.88-1.04z" opacity=".6"/><path fill="url(#j)" d="M10.32 6a4.32 4.32 0 0 1 4.13 5.6c-.75 2.45-1.13 4.08-1.13 4.9 0 .73.15 1.81.45 3.25A3.53 3.53 0 0 1 10.32 24a3.53 3.53 0 0 1-3.45-4.25c.3-1.44.45-2.52.45-3.25 0-.82-.37-2.45-1.13-4.9A4.32 4.32 0 0 1 10.32 6z" transform="rotate(45 10.323 15)"/></g><g transform="rotate(-24 2389.63 -1296.285)"><path fill="#FFFFFF" d="M16.93 3.22a4.32 4.32 0 0 1-1.03 6.88c-2.27 1.2-3.7 2.09-4.27 2.67-.52.52-1.18 1.39-1.98 2.61a3.53 3.53 0 0 1-5.45.57 3.53 3.53 0 0 1 .57-5.45c1.22-.8 2.1-1.46 2.61-1.97.58-.58 1.47-2 2.67-4.27a4.32 4.32 0 0 1 6.88-1.04z" opacity=".6"/><path fill="url(#j)" d="M10.32 6a4.32 4.32 0 0 1 4.13 5.6c-.75 2.45-1.13 4.08-1.13 4.9 0 .73.15 1.81.45 3.25A3.53 3.53 0 0 1 10.32 24a3.53 3.53 0 0 1-3.45-4.25c.3-1.44.45-2.52.45-3.25 0-.82-.37-2.45-1.13-4.9A4.32 4.32 0 0 1 10.32 6z" transform="rotate(45 10.323 15)"/></g><g transform="rotate(-50 1258.425 -353.155)"><path fill="#FFFFFF" d="M16.93 3.22a4.32 4.32 0 0 1-1.03 6.88c-2.27 1.2-3.7 2.09-4.27 2.67-.52.52-1.18 1.39-1.98 2.61a3.53 3.53 0 0 1-5.45.57 3.53 3.53 0 0 1 .57-5.45c1.22-.8 2.1-1.46 2.61-1.97.58-.58 1.47-2 2.67-4.27a4.32 4.32 0 0 1 6.88-1.04z" opacity=".6"/><path fill="url(#j)" d="M10.32 6a4.32 4.32 0 0 1 4.13 5.6c-.75 2.45-1.13 4.08-1.13 4.9 0 .73.15 1.81.45 3.25A3.53 3.53 0 0 1 10.32 24a3.53 3.53 0 0 1-3.45-4.25c.3-1.44.45-2.52.45-3.25 0-.82-.37-2.45-1.13-4.9A4.32 4.32 0 0 1 10.32 6z" transform="rotate(45 10.323 15)"/></g><g transform="rotate(-35 1652.744 -777.703)"><path fill="#FFFFFF" d="M16.08 3.06a4.1 4.1 0 0 1-.98 6.53c-2.15 1.14-3.5 1.99-4.05 2.54-.5.5-1.12 1.32-1.88 2.49a3.35 3.35 0 0 1-5.18.53 3.35 3.35 0 0 1 .54-5.17c1.16-.76 2-1.39 2.48-1.88.55-.55 1.4-1.9 2.54-4.06a4.1 4.1 0 0 1 6.53-.98z" opacity=".6"/><path fill="url(#j)" d="M9.8 5.7a4.1 4.1 0 0 1 3.93 5.31c-.71 2.33-1.07 3.89-1.07 4.67 0 .69.14 1.72.43 3.08A3.35 3.35 0 0 1 9.8 22.8a3.35 3.35 0 0 1-3.28-4.04c.28-1.36.43-2.39.43-3.09 0-.77-.36-2.33-1.08-4.66A4.1 4.1 0 0 1 9.81 5.7z" transform="rotate(45 9.807 14.25)"/></g><g transform="rotate(-35 1605.77 -758.112)"><path fill="#FFFFFF" d="M15.24 2.9a3.89 3.89 0 0 1-.93 6.19c-2.04 1.08-3.33 1.88-3.85 2.4a15.6 15.6 0 0 0-1.78 2.36 3.17 3.17 0 0 1-4.9.5 3.17 3.17 0 0 1 .51-4.9 15.6 15.6 0 0 0 2.36-1.78c.52-.52 1.32-1.8 2.4-3.84a3.89 3.89 0 0 1 6.19-.93z" opacity=".6"/><path fill="url(#j)" d="M9.3 5.4a3.89 3.89 0 0 1 3.7 5.03c-.67 2.21-1 3.68-1 4.42 0 .66.13 1.63.4 2.92a3.17 3.17 0 0 1-3.1 3.83 3.17 3.17 0 0 1-3.12-3.83c.28-1.29.41-2.26.41-2.92 0-.74-.34-2.2-1.02-4.42A3.89 3.89 0 0 1 9.3 5.4z" transform="rotate(45 9.29 13.5)"/></g><g transform="rotate(-35 1591.812 -807.843)"><path fill="#FFFFFF" d="M15.24 2.9a3.89 3.89 0 0 1-.93 6.19c-2.04 1.08-3.33 1.88-3.85 2.4a15.6 15.6 0 0 0-1.78 2.36 3.17 3.17 0 0 1-4.9.5 3.17 3.17 0 0 1 .51-4.9 15.6 15.6 0 0 0 2.36-1.78c.52-.52 1.32-1.8 2.4-3.84a3.89 3.89 0 0 1 6.19-.93z" opacity=".6"/><path fill="url(#j)" d="M9.3 5.4a3.89 3.89 0 0 1 3.7 5.03c-.67 2.21-1 3.68-1 4.42 0 .66.13 1.63.4 2.92a3.17 3.17 0 0 1-3.1 3.83 3.17 3.17 0 0 1-3.12-3.83c.28-1.29.41-2.26.41-2.92 0-.74-.34-2.2-1.02-4.42A3.89 3.89 0 0 1 9.3 5.4z" transform="rotate(45 9.29 13.5)"/></g><g transform="rotate(-44 1287.793 -536.004)"><path fill="#FFFFFF" d="M15.24 2.9a3.89 3.89 0 0 1-.93 6.19c-2.04 1.08-3.33 1.88-3.85 2.4a15.6 15.6 0 0 0-1.78 2.36 3.17 3.17 0 0 1-4.9.5 3.17 3.17 0 0 1 .51-4.9 15.6 15.6 0 0 0 2.36-1.78c.52-.52 1.32-1.8 2.4-3.84a3.89 3.89 0 0 1 6.19-.93z" opacity=".6"/><path fill="url(#j)" d="M9.3 5.4a3.89 3.89 0 0 1 3.7 5.03c-.67 2.21-1 3.68-1 4.42 0 .66.13 1.63.4 2.92a3.17 3.17 0 0 1-3.1 3.83 3.17 3.17 0 0 1-3.12-3.83c.28-1.29.41-2.26.41-2.92 0-.74-.34-2.2-1.02-4.42A3.89 3.89 0 0 1 9.3 5.4z" transform="rotate(45 9.29 13.5)"/></g><g transform="rotate(-28 1831.874 -1151.097)"><path fill="#FFFFFF" d="M15.24 2.9a3.89 3.89 0 0 1-.93 6.19c-2.04 1.08-3.33 1.88-3.85 2.4a15.6 15.6 0 0 0-1.78 2.36 3.17 3.17 0 0 1-4.9.5 3.17 3.17 0 0 1 .51-4.9 15.6 15.6 0 0 0 2.36-1.78c.52-.52 1.32-1.8 2.4-3.84a3.89 3.89 0 0 1 6.19-.93z" opacity=".6"/><path fill="url(#j)" d="M9.3 5.4a3.89 3.89 0 0 1 3.7 5.03c-.67 2.21-1 3.68-1 4.42 0 .66.13 1.63.4 2.92a3.17 3.17 0 0 1-3.1 3.83 3.17 3.17 0 0 1-3.12-3.83c.28-1.29.41-2.26.41-2.92 0-.74-.34-2.2-1.02-4.42A3.89 3.89 0 0 1 9.3 5.4z" transform="rotate(45 9.29 13.5)"/></g><g transform="rotate(-41 1316.639 -621.138)"><path fill="#FFFFFF" d="M13.54 2.58a3.46 3.46 0 0 1-.82 5.5A17.18 17.18 0 0 0 9.3 10.2c-.41.42-.94 1.12-1.58 2.1a2.82 2.82 0 0 1-4.36.45 2.82 2.82 0 0 1 .45-4.36c.99-.64 1.68-1.17 2.1-1.58.46-.46 1.17-1.6 2.13-3.42a3.46 3.46 0 0 1 5.5-.82z" opacity=".6"/><path fill="url(#j)" d="M8.26 4.8a3.46 3.46 0 0 1 3.3 4.47c-.6 1.97-.9 3.27-.9 3.93 0 .59.12 1.45.36 2.6a2.82 2.82 0 0 1-2.76 3.4 2.82 2.82 0 0 1-2.76-3.4c.24-1.15.36-2.01.36-2.6 0-.66-.3-1.96-.9-3.93a3.46 3.46 0 0 1 3.3-4.47z" transform="rotate(45 8.258 12)"/></g><g transform="rotate(-41 1286.706 -646.924)"><path fill="#FFFFFF" d="M11.85 2.26a3.03 3.03 0 0 1-.72 4.8 15.04 15.04 0 0 0-3 1.88c-.35.36-.82.97-1.38 1.83a2.47 2.47 0 0 1-3.8.4 2.47 2.47 0 0 1 .39-3.82C4.2 6.8 4.8 6.33 5.17 5.97c.4-.4 1.03-1.4 1.87-3a3.03 3.03 0 0 1 4.81-.71z" opacity=".6"/><path fill="url(#j)" d="M7.23 4.2a3.03 3.03 0 0 1 2.89 3.91c-.53 1.72-.8 2.87-.8 3.44 0 .51.11 1.27.32 2.27a2.47 2.47 0 0 1-2.41 2.98 2.47 2.47 0 0 1-2.42-2.98c.21-1 .32-1.76.32-2.27 0-.57-.27-1.72-.8-3.44a3.03 3.03 0 0 1 2.9-3.91z" transform="rotate(45 7.226 10.5)"/></g><g transform="rotate(-24 2011.85 -1427.831)"><path fill="#FFFFFF" d="M13.54 2.58a3.46 3.46 0 0 1-.82 5.5A17.18 17.18 0 0 0 9.3 10.2c-.41.42-.94 1.12-1.58 2.1a2.82 2.82 0 0 1-4.36.45 2.82 2.82 0 0 1 .45-4.36c.99-.64 1.68-1.17 2.1-1.58.46-.46 1.17-1.6 2.13-3.42a3.46 3.46 0 0 1 5.5-.82z" opacity=".6"/><path fill="url(#j)" d="M8.26 4.8a3.46 3.46 0 0 1 3.3 4.47c-.6 1.97-.9 3.27-.9 3.93 0 .59.12 1.45.36 2.6a2.82 2.82 0 0 1-2.76 3.4 2.82 2.82 0 0 1-2.76-3.4c.24-1.15.36-2.01.36-2.6 0-.66-.3-1.96-.9-3.93a3.46 3.46 0 0 1 3.3-4.47z" transform="rotate(45 8.258 12)"/></g><circle cx="756" cy="209" r="110" fill="#FFFFFF" opacity=".2"/><circle cx="859" cy="139" r="40" fill="#FFFFFF" opacity=".2"/><circle cx="551" cy="383" r="70" fill="#FFFFFF" opacity=".2"/><circle cx="666" cy="359" r="30" fill="#FFFFFF" opacity=".2"/><rect width="60" height="6" x="722" y="547" fill="#FFFFFF" opacity=".4" rx="3"/><rect width="60" height="6" x="842" y="565" fill="#FFFFFF" opacity=".4" rx="3"/><rect width="40" height="6" x="762" y="559" fill="#FFFFFF" opacity=".4" rx="3"/><rect width="40" height="6" x="872" y="553" fill="#FFFFFF" opacity=".4" rx="3"/><rect width="40" height="6" x="811" y="547" fill="#FFFFFF" opacity=".4" rx="3"/></g></svg>',"503":'<svg aria-hidden="true" focusable="false" preserveAspectRatio="xMidYMid slice" width="100%" height="100%" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><linearGradient id="a" x1="50.31%" x2="50%" y1="74.74%" y2="0%"><stop offset="0" stop-color="#e26b6b"/><stop offset=".5028" stop-color="#f5bcf4"/><stop offset="1" stop-color="#8690e1"/></linearGradient><linearGradient id="b" x1="50%" x2="50%" y1="0%" y2="100%"><stop offset="0" stop-color="#8c9ce7"/><stop offset="1" stop-color="#4353a4"/></linearGradient><linearGradient id="c" x1="50%" x2="50%" y1="0%" y2="100%"><stop offset="0" stop-color="#d1d9ff"/><stop offset="1" stop-color="#8395eb"/></linearGradient><circle id="d" cx="622" cy="663" r="60"/><filter id="e" height="260%" width="260%" x="-80%" y="-80%"><feOffset in="SourceAlpha" result="shadowOffsetOuter1"/><feGaussianBlur in="shadowOffsetOuter1" result="shadowBlurOuter1" stdDeviation="32"/><feColorMatrix in="shadowBlurOuter1" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/></filter><linearGradient id="f" x1="49.87%" x2="49.87%" y1="3.62%" y2="77.75%"><stop offset="0" stop-color="#b0ddf1"/><stop offset="1" stop-color="#325c82"/></linearGradient><linearGradient id="g" x1="100%" x2="72.45%" y1="0%" y2="85.2%"><stop offset="0" stop-color="#1d3a6d"/><stop offset="1" stop-color="#467994"/></linearGradient><linearGradient id="h" x1="49.48%" x2="49.87%" y1="11.66%" y2="77.75%"><stop offset="0" stop-color="#b9c9f7"/><stop offset="1" stop-color="#301863"/></linearGradient><linearGradient id="i"><stop offset="0" stop-color="#2d3173"/><stop offset="1" stop-color="#7f90e0"/></linearGradient><linearGradient id="j" x1="91.59%" x2="70.98%" xlink:href="#i" y1="5.89%" y2="88%"/><linearGradient id="k" x1="70.98%" x2="70.98%" xlink:href="#i" y1="9.88%" y2="88%"/></defs><g fill="none" fill-rule="evenodd"><path d="m0 0h1024v1024h-1024z" fill="url(#a)"/><g transform="translate(211 420)"><path d="m65 0a2 2 0 0 1 2 2v23h-4v-23c0-1.1.9-2 2-2z" fill="#8c9ce7"/><path d="m64 24h2a3 3 0 0 1 3 3v2h-8v-2a3 3 0 0 1 3-3z" fill="#5263b8"/><path d="m65 108h40v-40a40 40 0 1 0 -80 0v40z" fill="url(#b)"/><path d="m0 118 30-6v106h-30z" fill="#2e3d87"/><path d="m60 118-30-6v106h30z" fill="#301862"/><path d="m45 107v-39a40.02 40.02 0 0 1 30.03-38.75c17.24 4.4 29.97 19.86 29.97 38.25v39.5z" fill="url(#c)"/><path d="m15 78 50-10 2 2v108h-52z" fill="#4353a4"/><path d="m115 78-50-10v2 108h50z" fill="#8c9ce7"/><path d="m75 118 30-6v106h-30z" fill="#4353a4"/><path d="m135 118-30-6v106h30z" fill="#8c9ce7"/></g><use fill="#000" filter="url(#e)" xlink:href="#d"/><use fill="#fff" xlink:href="#d"/><g transform="translate(146 245)"><path d="m169.12 450.57c23.1 13.47-25.27 81.95-145.12 205.43h649c-344.06-141.7-512.02-210.17-503.88-205.43z" fill="url(#f)"/><path d="m178.5 538.5c-40.67 28.67 21.17 67.83 185.5 117.5h-364z" fill="url(#g)"/></g><path d="m1024 685h-1024v-284.92c77.3-33.68 155.26-70.08 297.4-70.08 250 0 250.76 125.25 500 125 84.03-.08 160.02-18.2 226.6-40.93z" fill="url(#h)" transform="translate(0 255)"/><path d="m251 506a8 8 0 0 1 8 8v15l-16 1v-16a8 8 0 0 1 8-8z" fill="#1f2a68"/><path d="m253 506.25a8 8 0 0 0 -6 7.75v15.75l-4 .25v-16a8 8 0 0 1 10-7.75z" fill="#7c8cda"/><path d="m251 546a8 8 0 0 1 8 8v15l-16 1v-16a8 8 0 0 1 8-8z" fill="#1f2a68"/><path d="m253 546.25a8 8 0 0 0 -6 7.75v15.75l-4 .25v-16a8 8 0 0 1 10-7.75z" fill="#7c8cda"/><path d="m301 506a8 8 0 0 1 8 8v16l-16-1v-15a8 8 0 0 1 8-8z" fill="#5263b8"/><path d="m305 529.75v-15.75a8 8 0 0 0 -6-7.75 8.01 8.01 0 0 1 10 7.75v16z" fill="#293781"/><g transform="translate(0 636)"><path d="m1024 356h-1024v-170.18c137.51-15.4 203.1-50.49 356.67-60.1 198.57-12.42 250.04-125.13 500.07-125.13 72.78-.01 124.44 10.61 167.26 25.67z" fill="url(#h)"/><g fill="url(#j)"><path d="m1024 26.21v299.79h-167.09c99.31-86.5 112.63-140.75 39.97-162.78-186.64-56.58-101.76-162.64-39.98-162.64 72.7 0 124.3 10.6 167.09 25.63z"/><path d="m1024 199.32v126.68h-167c99.31-86.6 112.63-140.94 39.97-163z"/></g></g><circle cx="566" cy="599" fill="#fff" opacity=".1" r="110"/><circle cx="669" cy="539" fill="#fff" opacity=".1" r="60"/><g transform="translate(0 705)"><path d="m0 319v-250.07c67.12-33.24 129.55-68.93 263-68.93 250 0 331.46 162.6 530 175 107.42 6.71 163-26.77 231-58.92v202.92z" fill="url(#h)"/><path d="m353.02 319h-353.02v-250.07c67.12-33.24 129.55-68.93 263-68.93 71.14 0 151.5 12.76 151.5 70.5 0 54.5-45.5 79.72-112.5 109-82.26 35.95-54.57 111.68 51.02 139.5z" fill="url(#j)"/><path d="m353.02 319h-353.02v-14.8l302-124.7c-82.26 35.95-54.57 111.68 51.02 139.5z" fill="url(#k)"/></g><g fill="#fff"><circle cx="414" cy="799" opacity=".1" r="70"/><circle cx="479" cy="745" opacity=".1" r="30"/><path d="m554.67 131.48a9.46 9.46 0 0 1 13.33 0 9.46 9.46 0 0 0 13.33 0l13.33-13.24a28.39 28.39 0 0 1 40 0l10 9.93a14.2 14.2 0 0 0 20 0 14.2 14.2 0 0 1 20 0l.6.6a31.8 31.8 0 0 1 9.4 22.56h-146.66v-3.84c0-6.01 2.4-11.78 6.67-16.01zm196.33-123.23c11.07-11 28.93-11 40 0l10 9.94a14.19 14.19 0 0 0 20 0 14.19 14.19 0 0 1 20 0 16.36 16.36 0 0 0 21.3 1.5l8.7-6.47a33.47 33.47 0 0 1 40 0l4.06 3.03a39.6 39.6 0 0 1 15.94 31.75h-200c0-12.72 8.93-28.75 20-39.75zm-736.9 66.89.9-.9a21.29 21.29 0 0 1 30 0 21.29 21.29 0 0 0 30 0l10-9.93a35.48 35.48 0 0 1 50 0l15 14.9a14.2 14.2 0 0 0 20 0 14.2 14.2 0 0 1 20 0c6.4 6.35 10 15 10 24.02v5.77h-200c0-12.71 5.07-24.9 14.1-33.86z" opacity=".15" transform="translate(49 214)"/></g></g></svg>'};
|
|
@@ -571,27 +571,75 @@ export const ERROR_PAGE_CSS=`
|
|
|
571
571
|
}
|
|
572
572
|
}
|
|
573
573
|
|
|
574
|
-
/* \u2500\u2500 Production page \u2500\u2500
|
|
574
|
+
/* \u2500\u2500 Production page \u2500\u2500
|
|
575
|
+
Laravel 5.7's split layout, rebuilt on these tokens: the message on one
|
|
576
|
+
half, an illustration bled to the edge on the other. Stacked on narrow
|
|
577
|
+
screens, scene first, because a square-ish crop of it reads as artwork
|
|
578
|
+
while a 30vh-tall sliver of the copy would not. */
|
|
575
579
|
.production-page {
|
|
580
|
+
display: grid;
|
|
581
|
+
grid-template-rows: clamp(12rem, 34vh, 20rem) 1fr;
|
|
582
|
+
min-height: 100dvh;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
.production-scene {
|
|
586
|
+
grid-row: 1;
|
|
587
|
+
overflow: hidden;
|
|
588
|
+
/* Behind the artwork while it paints, and all the visitor sees if a
|
|
589
|
+
userland page drops the illustration but keeps these class names. */
|
|
590
|
+
background: var(--neutral-200);
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
@media (prefers-color-scheme: dark) {
|
|
594
|
+
.production-scene { background: var(--neutral-800); }
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
.production-scene svg {
|
|
598
|
+
display: block;
|
|
599
|
+
width: 100%;
|
|
600
|
+
height: 100%;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
.production-panel {
|
|
576
604
|
display: flex;
|
|
577
605
|
flex-direction: column;
|
|
578
|
-
|
|
606
|
+
grid-row: 2;
|
|
607
|
+
align-items: flex-start;
|
|
579
608
|
justify-content: center;
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
609
|
+
padding: clamp(2rem, 6vw, 4rem);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
@media (min-width: 48rem) {
|
|
613
|
+
.production-page {
|
|
614
|
+
grid-template-rows: 1fr;
|
|
615
|
+
grid-template-columns: 1fr 1fr;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
.production-scene { grid-area: 1 / 2; }
|
|
619
|
+
|
|
620
|
+
.production-panel {
|
|
621
|
+
grid-area: 1 / 1;
|
|
622
|
+
padding-inline: clamp(2.5rem, 7vw, 6rem);
|
|
623
|
+
}
|
|
583
624
|
}
|
|
584
625
|
|
|
585
626
|
.production-status {
|
|
586
|
-
font-size:
|
|
587
|
-
font-weight:
|
|
588
|
-
|
|
589
|
-
margin-bottom: 1rem;
|
|
627
|
+
font-size: clamp(3.5rem, 11vw, 7rem);
|
|
628
|
+
font-weight: 800;
|
|
629
|
+
letter-spacing: -0.03em;
|
|
590
630
|
line-height: 1;
|
|
591
631
|
}
|
|
592
632
|
|
|
633
|
+
.production-rule {
|
|
634
|
+
width: 3.5rem;
|
|
635
|
+
height: 0.25rem;
|
|
636
|
+
margin: 1.25rem 0 1.5rem;
|
|
637
|
+
border-radius: 999px;
|
|
638
|
+
background: var(--blue-600);
|
|
639
|
+
}
|
|
640
|
+
|
|
593
641
|
@media (prefers-color-scheme: dark) {
|
|
594
|
-
.production-
|
|
642
|
+
.production-rule { background: var(--blue-500); }
|
|
595
643
|
}
|
|
596
644
|
|
|
597
645
|
.production-title {
|
|
@@ -606,15 +654,33 @@ export const ERROR_PAGE_CSS=`
|
|
|
606
654
|
max-width: 28rem;
|
|
607
655
|
}
|
|
608
656
|
|
|
657
|
+
@media (prefers-color-scheme: dark) {
|
|
658
|
+
.production-message { color: var(--neutral-400); }
|
|
659
|
+
}
|
|
660
|
+
|
|
609
661
|
.production-link {
|
|
610
|
-
|
|
611
|
-
|
|
662
|
+
display: inline-block;
|
|
663
|
+
padding: 0.625rem 1.25rem;
|
|
664
|
+
border: 1px solid var(--neutral-300);
|
|
665
|
+
border-radius: var(--radius-lg);
|
|
666
|
+
color: inherit;
|
|
612
667
|
font-size: 0.875rem;
|
|
668
|
+
font-weight: 500;
|
|
669
|
+
text-decoration: none;
|
|
670
|
+
transition: border-color 0.15s ease, background-color 0.15s ease;
|
|
613
671
|
}
|
|
614
672
|
|
|
615
|
-
.production-link:hover {
|
|
673
|
+
.production-link:hover {
|
|
674
|
+
border-color: var(--neutral-400);
|
|
675
|
+
background: var(--neutral-100);
|
|
676
|
+
}
|
|
616
677
|
|
|
617
678
|
@media (prefers-color-scheme: dark) {
|
|
618
|
-
.production-link { color: var(--
|
|
679
|
+
.production-link { border-color: var(--neutral-700); }
|
|
680
|
+
|
|
681
|
+
.production-link:hover {
|
|
682
|
+
border-color: var(--neutral-600);
|
|
683
|
+
background: var(--neutral-800);
|
|
684
|
+
}
|
|
619
685
|
}
|
|
620
686
|
`;
|
package/dist/error-page.d.ts
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { ERROR_PAGE_CSS } from './error-page-styles';
|
|
2
2
|
export declare function isFrameworkFrame(file: string): boolean;
|
|
3
3
|
/**
|
|
4
|
-
* Render
|
|
4
|
+
* Render the production error page: the status and its message on one side,
|
|
5
|
+
* the illustration that fits it on the other.
|
|
5
6
|
*
|
|
6
7
|
* Checks for a userland override at `resources/views/errors/<status>.html`
|
|
7
8
|
* (or `error.html` as a generic fallback) first; renders the built-in
|
|
8
9
|
* template only when no custom page is provided. stacksjs/stacks#863.
|
|
10
|
+
*
|
|
11
|
+
* Everything the page needs is in the string it returns - the CSS, and the
|
|
12
|
+
* illustration as inline SVG. A production error page is served precisely
|
|
13
|
+
* when something is already wrong, so it never asks for a second request it
|
|
14
|
+
* cannot be sure will be answered.
|
|
9
15
|
*/
|
|
10
16
|
export declare function renderProductionErrorPage(status: number): string;
|
|
11
17
|
/**
|
package/dist/error-page.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var {require}=import.meta;const DOCS_BASE="https://stacksjs.org/docs/errors";export const HTTP_ERRORS={400:{status:400,title:"Bad Request",message:"The request was malformed or invalid.",docLink:`${DOCS_BASE}/400`,commonCauses:["JSON body is missing or has a syntax error","A required field is absent from the payload","Content-Type header does not match the body format"],suggestion:"Inspect the request body and Content-Type - most 400s come from malformed JSON or a missing required field."},401:{status:401,title:"Unauthorized",message:"Authentication is required to access this resource.",docLink:`${DOCS_BASE}/401`,commonCauses:["No Authorization header was sent","The bearer token expired","The session cookie was cleared"],suggestion:"Confirm a valid `Authorization: Bearer <token>` header is sent and the token has not expired."},403:{status:403,title:"Forbidden",message:"You do not have permission to access this resource.",docLink:`${DOCS_BASE}/403`,commonCauses:["The authenticated user lacks the required ability or role","A Gate or policy denied access (see app/Gates.ts)","The token was issued without the needed ability"],suggestion:"Check Gates / policies and the abilities encoded in the access token."},404:{status:404,title:"Not Found",message:"The requested resource could not be found.",docLink:`${DOCS_BASE}/404`,commonCauses:["The route is not registered in app/Routes.ts","A typo in the URL path","A model lookup returned no row (ModelNotFoundError)"],suggestion:"Run `buddy route:list` to see registered routes, or verify the model exists with the given id."},405:{status:405,title:"Method Not Allowed",message:"The request method is not supported for this resource.",docLink:`${DOCS_BASE}/405`,commonCauses:["The route is registered for a different HTTP method","A form posted GET when the route expects POST"],suggestion:"Confirm the HTTP method in `app/Routes.ts` matches what the client sent."},408:{status:408,title:"Request Timeout",message:"The request took too long to complete.",docLink:`${DOCS_BASE}/408`,commonCauses:["A long-running query or external API call exceeded the timeout","The client uploaded a slow body that stalled"],suggestion:"Move slow work into a queued job, or raise the route timeout if the work is genuinely long."},409:{status:409,title:"Conflict",message:"The request conflicts with the current state of the resource.",docLink:`${DOCS_BASE}/409`,commonCauses:["A unique-constraint violation (duplicate email, slug, etc.)","Optimistic locking detected a stale write"],suggestion:"Re-fetch the resource and retry, or surface the conflict to the user."},410:{status:410,title:"Gone",message:"The requested resource is no longer available.",docLink:`${DOCS_BASE}/410`,commonCauses:["The resource was permanently deleted","A signed URL expired"],suggestion:"Issue a fresh signed URL or fall back to the canonical resource."},422:{status:422,title:"Unprocessable Entity",message:"The request was well-formed but could not be processed.",docLink:`${DOCS_BASE}/422`,commonCauses:["Validation rules from the action / model rejected the payload","A field value is outside the allowed range or shape"],suggestion:"Inspect `errors` in the response body - each key maps to a failing field."},429:{status:429,title:"Too Many Requests",message:"You have exceeded the rate limit.",docLink:`${DOCS_BASE}/429`,commonCauses:["Rate-limit middleware tripped on this IP / token","A retry loop is hammering the endpoint"],suggestion:"Honor the `Retry-After` response header and back off before retrying."},500:{status:500,title:"Internal Server Error",message:"An unexpected error occurred on the server.",docLink:`${DOCS_BASE}/500`,commonCauses:["An unhandled exception in an action or middleware","A failing database connection or migration","A misconfigured environment variable"],suggestion:"Check server logs for the original stack trace - the error page above shows the throw site in dev."},502:{status:502,title:"Bad Gateway",message:"The server received an invalid response from an upstream server.",docLink:`${DOCS_BASE}/502`,commonCauses:["An upstream HTTP API returned a malformed response","A reverse proxy could not reach the origin"],suggestion:"Verify the upstream service is healthy and returning the expected content type."},503:{status:503,title:"Service Unavailable",message:"The service is temporarily unavailable.",docLink:`${DOCS_BASE}/503`,commonCauses:["Maintenance mode is enabled","A health check is failing","A dependency (db, redis, queue) is down"],suggestion:"Run `buddy doctor` and check dependent services."},504:{status:504,title:"Gateway Timeout",message:"The upstream server did not respond in time.",docLink:`${DOCS_BASE}/504`,commonCauses:["An upstream HTTP call exceeded its deadline","A long-running database query timed out"],suggestion:"Move the work to a queued job or raise the upstream timeout if the latency is expected."}};import{buildErrorMarkdown,escapeHtml,renderExceptionTrace,wrapErrorPage}from"./error-page-template";import{ERROR_PAGE_CSS}from"./error-page-styles";export{ERROR_PAGE_CSS};const FRAMEWORK_FRAME_FRAGMENTS=["/storage/framework/core/","/node_modules/@stacksjs/","node:internal/","bun:wrap"];export function isFrameworkFrame(file){if(!file)return!1;return FRAMEWORK_FRAME_FRAGMENTS.some((f)=>file.includes(f))}function parseStackTrace(stack,basePaths,options={}){if(!stack)return[];const lines=stack.split(`
|
|
1
|
+
var {require}=import.meta;const DOCS_BASE="https://stacksjs.org/docs/errors";export const HTTP_ERRORS={400:{status:400,title:"Bad Request",message:"The request was malformed or invalid.",docLink:`${DOCS_BASE}/400`,commonCauses:["JSON body is missing or has a syntax error","A required field is absent from the payload","Content-Type header does not match the body format"],suggestion:"Inspect the request body and Content-Type - most 400s come from malformed JSON or a missing required field."},401:{status:401,title:"Unauthorized",message:"Authentication is required to access this resource.",docLink:`${DOCS_BASE}/401`,commonCauses:["No Authorization header was sent","The bearer token expired","The session cookie was cleared"],suggestion:"Confirm a valid `Authorization: Bearer <token>` header is sent and the token has not expired."},403:{status:403,title:"Forbidden",message:"You do not have permission to access this resource.",docLink:`${DOCS_BASE}/403`,commonCauses:["The authenticated user lacks the required ability or role","A Gate or policy denied access (see app/Gates.ts)","The token was issued without the needed ability"],suggestion:"Check Gates / policies and the abilities encoded in the access token."},404:{status:404,title:"Not Found",message:"The requested resource could not be found.",docLink:`${DOCS_BASE}/404`,commonCauses:["The route is not registered in app/Routes.ts","A typo in the URL path","A model lookup returned no row (ModelNotFoundError)"],suggestion:"Run `buddy route:list` to see registered routes, or verify the model exists with the given id."},405:{status:405,title:"Method Not Allowed",message:"The request method is not supported for this resource.",docLink:`${DOCS_BASE}/405`,commonCauses:["The route is registered for a different HTTP method","A form posted GET when the route expects POST"],suggestion:"Confirm the HTTP method in `app/Routes.ts` matches what the client sent."},408:{status:408,title:"Request Timeout",message:"The request took too long to complete.",docLink:`${DOCS_BASE}/408`,commonCauses:["A long-running query or external API call exceeded the timeout","The client uploaded a slow body that stalled"],suggestion:"Move slow work into a queued job, or raise the route timeout if the work is genuinely long."},409:{status:409,title:"Conflict",message:"The request conflicts with the current state of the resource.",docLink:`${DOCS_BASE}/409`,commonCauses:["A unique-constraint violation (duplicate email, slug, etc.)","Optimistic locking detected a stale write"],suggestion:"Re-fetch the resource and retry, or surface the conflict to the user."},410:{status:410,title:"Gone",message:"The requested resource is no longer available.",docLink:`${DOCS_BASE}/410`,commonCauses:["The resource was permanently deleted","A signed URL expired"],suggestion:"Issue a fresh signed URL or fall back to the canonical resource."},422:{status:422,title:"Unprocessable Entity",message:"The request was well-formed but could not be processed.",docLink:`${DOCS_BASE}/422`,commonCauses:["Validation rules from the action / model rejected the payload","A field value is outside the allowed range or shape"],suggestion:"Inspect `errors` in the response body - each key maps to a failing field."},429:{status:429,title:"Too Many Requests",message:"You have exceeded the rate limit.",docLink:`${DOCS_BASE}/429`,commonCauses:["Rate-limit middleware tripped on this IP / token","A retry loop is hammering the endpoint"],suggestion:"Honor the `Retry-After` response header and back off before retrying."},500:{status:500,title:"Internal Server Error",message:"An unexpected error occurred on the server.",docLink:`${DOCS_BASE}/500`,commonCauses:["An unhandled exception in an action or middleware","A failing database connection or migration","A misconfigured environment variable"],suggestion:"Check server logs for the original stack trace - the error page above shows the throw site in dev."},502:{status:502,title:"Bad Gateway",message:"The server received an invalid response from an upstream server.",docLink:`${DOCS_BASE}/502`,commonCauses:["An upstream HTTP API returned a malformed response","A reverse proxy could not reach the origin"],suggestion:"Verify the upstream service is healthy and returning the expected content type."},503:{status:503,title:"Service Unavailable",message:"The service is temporarily unavailable.",docLink:`${DOCS_BASE}/503`,commonCauses:["Maintenance mode is enabled","A health check is failing","A dependency (db, redis, queue) is down"],suggestion:"Run `buddy doctor` and check dependent services."},504:{status:504,title:"Gateway Timeout",message:"The upstream server did not respond in time.",docLink:`${DOCS_BASE}/504`,commonCauses:["An upstream HTTP call exceeded its deadline","A long-running database query timed out"],suggestion:"Move the work to a queued job or raise the upstream timeout if the latency is expected."}};import{buildErrorMarkdown,escapeHtml,renderExceptionTrace,wrapErrorPage}from"./error-page-template";import{errorIllustration}from"./error-illustrations";import{ERROR_PAGE_CSS}from"./error-page-styles";export{ERROR_PAGE_CSS};const FRAMEWORK_FRAME_FRAGMENTS=["/storage/framework/core/","/node_modules/@stacksjs/","node:internal/","bun:wrap"];export function isFrameworkFrame(file){if(!file)return!1;return FRAMEWORK_FRAME_FRAGMENTS.some((f)=>file.includes(f))}function parseStackTrace(stack,basePaths,options={}){if(!stack)return[];const lines=stack.split(`
|
|
2
2
|
`).slice(1),frames=[],includeAll=options.includeFrameworkFrames===!0;for(const line of lines){const match=line.match(/^\s*at\s+(?:(.+?)\s+\()?(.+?):(\d+):(\d+)\)?$/);if(match){let file=match[2];if(file===void 0)continue;const original=file,isFramework=isFrameworkFrame(original);if(basePaths){for(const basePath of basePaths)if(file.startsWith(basePath)){file=file.slice(basePath.length+1);break}}if(!includeAll&&isFramework)continue;frames.push({function:match[1]||"<anonymous>",file,absoluteFile:original,isFramework,line:parseInt(match[3]??"0",10),column:parseInt(match[4]??"0",10)})}}if(!includeAll&&frames.length===0)return parseStackTrace(stack,basePaths,{includeFrameworkFrames:!0});return frames}function loadCustomErrorPage(status,title,message){let resourcesPath;try{const mod=require("@stacksjs/path");resourcesPath=mod.resourcesPath??mod.path?.resourcesPath}catch{}if(!resourcesPath)return null;const fs=require("node:fs"),candidates=[resourcesPath(`views/errors/${status}.html`),resourcesPath("views/errors/error.html")];for(const filePath of candidates)try{if(!fs.existsSync(filePath))continue;return fs.readFileSync(filePath,"utf-8").replace(/\{\{\s*status\s*\}\}/g,escapeHtml(String(status))).replace(/\{\{\s*title\s*\}\}/g,escapeHtml(title)).replace(/\{\{\s*message\s*\}\}/g,escapeHtml(message))}catch{}return null}export function renderProductionErrorPage(status){const httpError=HTTP_ERRORS[status]||{status,title:"Error",message:"An unexpected error occurred."},custom=loadCustomErrorPage(httpError.status,httpError.title,httpError.message);if(custom!==null)return custom;return`<!DOCTYPE html>
|
|
3
3
|
<html lang="en">
|
|
4
4
|
<head>
|
|
@@ -8,14 +8,18 @@ var {require}=import.meta;const DOCS_BASE="https://stacksjs.org/docs/errors";exp
|
|
|
8
8
|
<style>${ERROR_PAGE_CSS}</style>
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
|
-
<
|
|
12
|
-
<div class="production-
|
|
13
|
-
<
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
<main class="production-page">
|
|
12
|
+
<div class="production-scene">${errorIllustration(httpError.status)}</div>
|
|
13
|
+
<section class="production-panel">
|
|
14
|
+
<div class="production-status">${httpError.status}</div>
|
|
15
|
+
<div class="production-rule"></div>
|
|
16
|
+
<h1 class="production-title">${escapeHtml(httpError.title)}</h1>
|
|
17
|
+
<p class="production-message">${escapeHtml(httpError.message)}</p>
|
|
18
|
+
<a href="/" class="production-link">Back to home</a>
|
|
19
|
+
</section>
|
|
20
|
+
</main>
|
|
17
21
|
</body>
|
|
18
|
-
</html>`}export function renderHttpErrorHints(status){const info=HTTP_ERRORS[status];if(!info)return"";const hasCauses=Array.isArray(info.commonCauses)&&info.commonCauses.length>0,hasSuggestion=typeof info.suggestion==="string"&&info.suggestion.length>0,hasDoc=typeof info.docLink==="string"&&info.docLink.length>0;if(!hasCauses&&!hasSuggestion&&!hasDoc)return"";const causes=hasCauses?`<ul class="error-hint-causes">${info.commonCauses.map((c)=>`<li>${escapeHtml(c)}</li>`).join("")}</ul>`:"",suggestion=hasSuggestion?`<p class="error-hint-suggestion">${escapeHtml(info.suggestion)}</p>`:"",doc=hasDoc?`<a class="text-
|
|
22
|
+
</html>`}export function renderHttpErrorHints(status){const info=HTTP_ERRORS[status];if(!info)return"";const hasCauses=Array.isArray(info.commonCauses)&&info.commonCauses.length>0,hasSuggestion=typeof info.suggestion==="string"&&info.suggestion.length>0,hasDoc=typeof info.docLink==="string"&&info.docLink.length>0;if(!hasCauses&&!hasSuggestion&&!hasDoc)return"";const causes=hasCauses?`<ul class="error-hint-causes">${info.commonCauses.map((c)=>`<li>${escapeHtml(c)}</li>`).join("")}</ul>`:"",suggestion=hasSuggestion?`<p class="error-hint-suggestion">${escapeHtml(info.suggestion)}</p>`:"",doc=hasDoc?`<a class="text-[#a22a50] text-sm dark:text-[#f0a07e] hover:underline" href="${escapeHtml(info.docLink)}" target="_blank" rel="noreferrer noopener">Read the docs \u2192</a>`:"";return`<section class="p-4 bg-amber-200/30 dark:bg-amber-950/40 border border-amber-200 rounded-xl dark:border-amber-800 shadow-xs">
|
|
19
23
|
<div class="mb-2 font-semibold text-amber-900 text-sm dark:text-amber-300">Likely causes & next steps</div>
|
|
20
24
|
<div class="text-neutral-700 text-sm dark:text-neutral-300">${causes}${suggestion}${doc}</div>
|
|
21
25
|
</section>`}export class ErrorPageHandler{config;framework;request;routing;user;queries=[];constructor(config){this.config={appName:"App",theme:"auto",showEnvironment:!0,showQueries:!0,showRequest:!0,enableCopyMarkdown:!0,snippetLines:8,...config}}setFramework(name,version){this.framework={name,version};return this}setRequest(request){if(request instanceof Request){const url=new URL(request.url);this.request={method:request.method,url:request.url,headers:Object.fromEntries(request.headers.entries()),queryParams:Object.fromEntries(url.searchParams.entries())}}else this.request=request;return this}setRouting(routing){this.routing=routing;return this}setUser(user){this.user=user;return this}addQuery(query,time,connection){this.queries.push({query,time,connection});return this}async render(error,status=500){try{const{renderDevErrorPage}=await import("./error-page-renderer");return await renderDevErrorPage({error,status,config:this.config,framework:this.framework,request:this.request,routing:this.routing,user:this.user,queries:this.queries})}catch(renderError){console.error("[ErrorPageHandler] STX render failed, using fallback:",renderError);return this.renderFallback(error,status)}}renderFallback(error,status){const frames=parseStackTrace(error.stack,this.config.basePaths,{includeFrameworkFrames:this.config.showFrameworkFrames===!0}),statusTitle=HTTP_ERRORS[status]?.title??"Error",topFrame=frames[0],body=`
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ export type {
|
|
|
5
5
|
Result,
|
|
6
6
|
ResultAsync,
|
|
7
7
|
} from 'ts-error-handling';
|
|
8
|
+
// The four illustrations the production error page draws from
|
|
9
|
+
export type { ErrorIllustration } from './error-illustrations';
|
|
8
10
|
// Error page exports (Ignition-style) - local implementation
|
|
9
11
|
export type {
|
|
10
12
|
CodeSnippet,
|
|
@@ -29,6 +31,11 @@ export {
|
|
|
29
31
|
fromPromise,
|
|
30
32
|
ok,
|
|
31
33
|
} from 'ts-error-handling';
|
|
34
|
+
export {
|
|
35
|
+
ERROR_ILLUSTRATIONS,
|
|
36
|
+
errorIllustration,
|
|
37
|
+
illustrationForStatus,
|
|
38
|
+
} from './error-illustrations';
|
|
32
39
|
export {
|
|
33
40
|
createErrorHandler,
|
|
34
41
|
ERROR_PAGE_CSS,
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export*from"./handler";export*from"./http";export*from"./model";export*from"./utils";export{err,fromPromise,ok}from"ts-error-handling";export{createErrorHandler,ERROR_PAGE_CSS,ErrorPageHandler,errorResponse,HTTP_ERRORS,renderError,renderErrorPage,renderHttpErrorHints,renderProductionErrorPage}from"./error-page";
|
|
1
|
+
export*from"./handler";export*from"./http";export*from"./model";export*from"./utils";export{err,fromPromise,ok}from"ts-error-handling";export{ERROR_ILLUSTRATIONS,errorIllustration,illustrationForStatus}from"./error-illustrations";export{createErrorHandler,ERROR_PAGE_CSS,ErrorPageHandler,errorResponse,HTTP_ERRORS,renderError,renderErrorPage,renderHttpErrorHints,renderProductionErrorPage}from"./error-page";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacksjs/error-handling",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.72.
|
|
4
|
+
"version": "0.72.51",
|
|
5
5
|
"description": "Type safe error handling.",
|
|
6
6
|
"author": "Chris Breuer",
|
|
7
7
|
"contributors": [
|
|
@@ -57,17 +57,17 @@
|
|
|
57
57
|
"prepublishOnly": "bun run build"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@stacksjs/stx": "^0.2.
|
|
60
|
+
"@stacksjs/stx": "^0.2.219",
|
|
61
61
|
"ts-error-handling": "^0.1.1",
|
|
62
62
|
"ts-syntax-highlighter": "^0.2.1"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
|
-
"@stacksjs/cli": "0.72.
|
|
66
|
-
"@stacksjs/config": "0.72.
|
|
65
|
+
"@stacksjs/cli": "0.72.51",
|
|
66
|
+
"@stacksjs/config": "0.72.51",
|
|
67
67
|
"better-dx": "^0.2.24",
|
|
68
|
-
"@stacksjs/path": "0.72.
|
|
69
|
-
"@stacksjs/types": "0.72.
|
|
70
|
-
"@stacksjs/validation": "0.72.
|
|
68
|
+
"@stacksjs/path": "0.72.51",
|
|
69
|
+
"@stacksjs/types": "0.72.51",
|
|
70
|
+
"@stacksjs/validation": "0.72.51"
|
|
71
71
|
},
|
|
72
72
|
"sideEffects": false
|
|
73
73
|
}
|