litestar-vite-plugin 0.17.0 → 0.18.3

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/js/astro.js CHANGED
@@ -129,7 +129,8 @@ function createProxyPlugin(config) {
129
129
  [config.apiPrefix]: {
130
130
  target: config.apiProxy,
131
131
  changeOrigin: true,
132
- secure: false
132
+ secure: false,
133
+ ws: true
133
134
  }
134
135
  }
135
136
  }
@@ -4,7 +4,7 @@
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>Litestar Vite Dev Server</title>
7
- <style rel="stylesheet" crossorigin>@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-space-x-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-blue-500:oklch(62.3% .214 259.815);--color-purple-500:oklch(62.7% .265 303.9);--color-gray-900:oklch(21% .034 264.665);--color-white:#fff;--spacing:.25rem;--container-2xl:42rem;--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5/2.25);--text-5xl:3rem;--text-5xl--line-height:1;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--tracking-wide:.025em;--leading-relaxed:1.625;--radius-2xl:1rem;--radius-3xl:1.5rem;--drop-shadow-lg:0 4px 4px #00000026;--animate-ping:ping 1s cubic-bezier(0,0,.2,1)infinite;--blur-lg:16px;--blur-xl:24px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-brand-primary:oklch(22% .03 265);--color-brand-accent:oklch(78% .16 85);--color-brand-accent-light:oklch(85% .12 85);--color-brand-gray:oklch(90% .01 265);--color-brand-success:oklch(65% .2 145);--color-brand-dots:oklch(26% .03 265);--animate-blob:blob 7s infinite ease-in-out}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.absolute{position:absolute}.relative{position:relative}.inset-0{inset:calc(var(--spacing)*0)}.top-0{top:calc(var(--spacing)*0)}.-right-4{right:calc(var(--spacing)*-4)}.-bottom-8{bottom:calc(var(--spacing)*-8)}.-left-4{left:calc(var(--spacing)*-4)}.left-20{left:calc(var(--spacing)*20)}.mt-1{margin-top:calc(var(--spacing)*1)}.mt-12{margin-top:calc(var(--spacing)*12)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.mb-10{margin-bottom:calc(var(--spacing)*10)}.ml-2{margin-left:calc(var(--spacing)*2)}.flex{display:flex}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.h-1{height:calc(var(--spacing)*1)}.h-3{height:calc(var(--spacing)*3)}.h-4{height:calc(var(--spacing)*4)}.h-6{height:calc(var(--spacing)*6)}.h-16{height:calc(var(--spacing)*16)}.h-20{height:calc(var(--spacing)*20)}.h-72{height:calc(var(--spacing)*72)}.h-full{height:100%}.h-px{height:1px}.min-h-screen{min-height:100vh}.w-3{width:calc(var(--spacing)*3)}.w-4{width:calc(var(--spacing)*4)}.w-6{width:calc(var(--spacing)*6)}.w-72{width:calc(var(--spacing)*72)}.w-auto{width:auto}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.animate-blob{animation:var(--animate-blob)}.animate-ping{animation:var(--animate-ping)}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-8>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*8)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*8)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-x-3>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing)*3)*var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing)*3)*calc(1 - var(--tw-space-x-reverse)))}:where(.space-x-8>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing)*8)*var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing)*8)*calc(1 - var(--tw-space-x-reverse)))}.overflow-hidden{overflow:hidden}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-3xl{border-radius:var(--radius-3xl)}.rounded-full{border-radius:3.40282e38px}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-white\/10{border-color:#ffffff1a}@supports (color:color-mix(in lab,red,red)){.border-white\/10{border-color:color-mix(in oklab,var(--color-white)10%,transparent)}}.bg-blue-500\/10{background-color:#3080ff1a}@supports (color:color-mix(in lab,red,red)){.bg-blue-500\/10{background-color:color-mix(in oklab,var(--color-blue-500)10%,transparent)}}.bg-brand-accent\/10{background-color:#e6ad001a}@supports (color:color-mix(in lab,red,red)){.bg-brand-accent\/10{background-color:color-mix(in oklab,var(--color-brand-accent)10%,transparent)}}.bg-brand-accent\/20{background-color:#e6ad0033}@supports (color:color-mix(in lab,red,red)){.bg-brand-accent\/20{background-color:color-mix(in oklab,var(--color-brand-accent)20%,transparent)}}.bg-brand-accent\/30{background-color:#e6ad004d}@supports (color:color-mix(in lab,red,red)){.bg-brand-accent\/30{background-color:color-mix(in oklab,var(--color-brand-accent)30%,transparent)}}.bg-brand-success{background-color:var(--color-brand-success)}.bg-gray-900\/60{background-color:#10182899}@supports (color:color-mix(in lab,red,red)){.bg-gray-900\/60{background-color:color-mix(in oklab,var(--color-gray-900)60%,transparent)}}.bg-purple-500\/10{background-color:#ac4bff1a}@supports (color:color-mix(in lab,red,red)){.bg-purple-500\/10{background-color:color-mix(in oklab,var(--color-purple-500)10%,transparent)}}.bg-purple-500\/20{background-color:#ac4bff33}@supports (color:color-mix(in lab,red,red)){.bg-purple-500\/20{background-color:color-mix(in oklab,var(--color-purple-500)20%,transparent)}}.bg-white\/5{background-color:#ffffff0d}@supports (color:color-mix(in lab,red,red)){.bg-white\/5{background-color:color-mix(in oklab,var(--color-white)5%,transparent)}}.bg-linear-to-r{--tw-gradient-position:to right}@supports (background-image:linear-gradient(in lab,red,red)){.bg-linear-to-r{--tw-gradient-position:to right in oklab}}.bg-linear-to-r{background-image:linear-gradient(var(--tw-gradient-stops))}.from-brand-accent{--tw-gradient-from:var(--color-brand-accent);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.from-transparent{--tw-gradient-from:transparent;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.via-brand-accent{--tw-gradient-via:var(--color-brand-accent);--tw-gradient-via-stops:var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-via)var(--tw-gradient-via-position),var(--tw-gradient-to)var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.to-brand-accent-light{--tw-gradient-to:var(--color-brand-accent-light);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.to-transparent{--tw-gradient-to:transparent;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.bg-clip-text{-webkit-background-clip:text;background-clip:text}.p-6{padding:calc(var(--spacing)*6)}.px-5{padding-inline:calc(var(--spacing)*5)}.px-6{padding-inline:calc(var(--spacing)*6)}.px-8{padding-inline:calc(var(--spacing)*8)}.py-2\.5{padding-block:calc(var(--spacing)*2.5)}.py-10{padding-block:calc(var(--spacing)*10)}.py-12{padding-block:calc(var(--spacing)*12)}.pt-8{padding-top:calc(var(--spacing)*8)}.text-center{text-align:center}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.text-brand-accent{color:var(--color-brand-accent)}.text-brand-gray{color:var(--color-brand-gray)}.text-brand-gray\/30{color:#dbdee54d}@supports (color:color-mix(in lab,red,red)){.text-brand-gray\/30{color:color-mix(in oklab,var(--color-brand-gray)30%,transparent)}}.text-brand-gray\/60{color:#dbdee599}@supports (color:color-mix(in lab,red,red)){.text-brand-gray\/60{color:color-mix(in oklab,var(--color-brand-gray)60%,transparent)}}.text-brand-gray\/80{color:#dbdee5cc}@supports (color:color-mix(in lab,red,red)){.text-brand-gray\/80{color:color-mix(in oklab,var(--color-brand-gray)80%,transparent)}}.text-brand-success{color:var(--color-brand-success)}.text-transparent{color:#0000}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.opacity-0{opacity:0}.opacity-50{opacity:.5}.opacity-70{opacity:.7}.opacity-75{opacity:.75}.mix-blend-multiply{mix-blend-mode:multiply}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-inner{--tw-shadow:inset 0 2px 4px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.blur-xl{--tw-blur:blur(var(--blur-xl));filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.drop-shadow-lg{--tw-drop-shadow-size:drop-shadow(0 4px 4px var(--tw-drop-shadow-color,#00000026));--tw-drop-shadow:drop-shadow(var(--drop-shadow-lg));filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.backdrop-blur-lg{--tw-backdrop-blur:blur(var(--blur-lg));-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-300{--tw-duration:.3s;transition-duration:.3s}.animation-delay-2000{animation-delay:2s}.animation-delay-4000{animation-delay:4s}@media(hover:hover){.group-hover\:translate-x-1:is(:where(.group):hover *){--tw-translate-x:calc(var(--spacing)*1);translate:var(--tw-translate-x)var(--tw-translate-y)}.group-hover\:bg-brand-accent:is(:where(.group):hover *){background-color:var(--color-brand-accent)}.group-hover\:text-brand-accent-light:is(:where(.group):hover *){color:var(--color-brand-accent-light)}.group-hover\:text-white:is(:where(.group):hover *){color:var(--color-white)}.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}.hover\:scale-110:hover{--tw-scale-x:110%;--tw-scale-y:110%;--tw-scale-z:110%;scale:var(--tw-scale-x)var(--tw-scale-y)}.hover\:border-brand-accent\/50:hover{border-color:#e6ad0080}@supports (color:color-mix(in lab,red,red)){.hover\:border-brand-accent\/50:hover{border-color:color-mix(in oklab,var(--color-brand-accent)50%,transparent)}}.hover\:bg-white\/10:hover{background-color:#ffffff1a}@supports (color:color-mix(in lab,red,red)){.hover\:bg-white\/10:hover{background-color:color-mix(in oklab,var(--color-white)10%,transparent)}}}@media(min-width:40rem){.sm\:px-12{padding-inline:calc(var(--spacing)*12)}.sm\:py-12{padding-block:calc(var(--spacing)*12)}.sm\:text-5xl{font-size:var(--text-5xl);line-height:var(--tw-leading,var(--text-5xl--line-height))}}}@keyframes blob{0%,to{transform:translate(0)scale(1)}33%{transform:translate(30px,-50px)scale(1.1)}66%{transform:translate(-20px,20px)scale(.9)}}body{background-color:var(--color-brand-primary);background-image:radial-gradient(var(--color-brand-dots)1px,transparent 1px);color:var(--color-brand-gray);background-size:24px 24px}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-space-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:"*";inherits:false}@property --tw-gradient-via-stops{syntax:"*";inherits:false}@property --tw-gradient-from-position{syntax:"<length-percentage>";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:"<length-percentage>";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:"<length-percentage>";inherits:false;initial-value:100%}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@keyframes ping{75%,to{opacity:0;transform:scale(2)}}</style>
7
+ <style rel="stylesheet" crossorigin>@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-space-x-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-blue-500:oklch(62.3% .214 259.815);--color-purple-500:oklch(62.7% .265 303.9);--color-gray-900:oklch(21% .034 264.665);--color-white:#fff;--spacing:.25rem;--container-2xl:42rem;--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5 / 2.25);--text-5xl:3rem;--text-5xl--line-height:1;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--tracking-wide:.025em;--leading-relaxed:1.625;--radius-2xl:1rem;--radius-3xl:1.5rem;--drop-shadow-lg:0 4px 4px #00000026;--animate-ping:ping 1s cubic-bezier(0, 0, .2, 1) infinite;--blur-lg:16px;--blur-xl:24px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-brand-primary:oklch(22% .03 265);--color-brand-accent:oklch(78% .16 85);--color-brand-accent-light:oklch(85% .12 85);--color-brand-gray:oklch(90% .01 265);--color-brand-success:oklch(65% .2 145);--color-brand-dots:oklch(26% .03 265);--animate-blob:blob 7s infinite ease-in-out}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.absolute{position:absolute}.relative{position:relative}.inset-0{inset:calc(var(--spacing) * 0)}.top-0{top:calc(var(--spacing) * 0)}.-right-4{right:calc(var(--spacing) * -4)}.-bottom-8{bottom:calc(var(--spacing) * -8)}.-left-4{left:calc(var(--spacing) * -4)}.left-20{left:calc(var(--spacing) * 20)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-12{margin-top:calc(var(--spacing) * 12)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-10{margin-bottom:calc(var(--spacing) * 10)}.ml-2{margin-left:calc(var(--spacing) * 2)}.flex{display:flex}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.h-1{height:calc(var(--spacing) * 1)}.h-3{height:calc(var(--spacing) * 3)}.h-4{height:calc(var(--spacing) * 4)}.h-6{height:calc(var(--spacing) * 6)}.h-16{height:calc(var(--spacing) * 16)}.h-20{height:calc(var(--spacing) * 20)}.h-72{height:calc(var(--spacing) * 72)}.h-full{height:100%}.h-px{height:1px}.min-h-screen{min-height:100vh}.w-3{width:calc(var(--spacing) * 3)}.w-4{width:calc(var(--spacing) * 4)}.w-6{width:calc(var(--spacing) * 6)}.w-72{width:calc(var(--spacing) * 72)}.w-auto{width:auto}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.animate-blob{animation:var(--animate-blob)}.animate-ping{animation:var(--animate-ping)}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-8>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 8) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 8) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-x-3>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing) * 3) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-x-reverse)))}:where(.space-x-8>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing) * 8) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing) * 8) * calc(1 - var(--tw-space-x-reverse)))}.overflow-hidden{overflow:hidden}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-3xl{border-radius:var(--radius-3xl)}.rounded-full{border-radius:3.40282e38px}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-white\/10{border-color:#ffffff1a}@supports (color:color-mix(in lab,red,red)){.border-white\/10{border-color:color-mix(in oklab,var(--color-white) 10%,transparent)}}.bg-blue-500\/10{background-color:#3080ff1a}@supports (color:color-mix(in lab,red,red)){.bg-blue-500\/10{background-color:color-mix(in oklab,var(--color-blue-500) 10%,transparent)}}.bg-brand-accent\/10{background-color:#e6ad001a}@supports (color:color-mix(in lab,red,red)){.bg-brand-accent\/10{background-color:color-mix(in oklab,var(--color-brand-accent) 10%,transparent)}}.bg-brand-accent\/20{background-color:#e6ad0033}@supports (color:color-mix(in lab,red,red)){.bg-brand-accent\/20{background-color:color-mix(in oklab,var(--color-brand-accent) 20%,transparent)}}.bg-brand-accent\/30{background-color:#e6ad004d}@supports (color:color-mix(in lab,red,red)){.bg-brand-accent\/30{background-color:color-mix(in oklab,var(--color-brand-accent) 30%,transparent)}}.bg-brand-success{background-color:var(--color-brand-success)}.bg-gray-900\/60{background-color:#10182899}@supports (color:color-mix(in lab,red,red)){.bg-gray-900\/60{background-color:color-mix(in oklab,var(--color-gray-900) 60%,transparent)}}.bg-purple-500\/10{background-color:#ac4bff1a}@supports (color:color-mix(in lab,red,red)){.bg-purple-500\/10{background-color:color-mix(in oklab,var(--color-purple-500) 10%,transparent)}}.bg-purple-500\/20{background-color:#ac4bff33}@supports (color:color-mix(in lab,red,red)){.bg-purple-500\/20{background-color:color-mix(in oklab,var(--color-purple-500) 20%,transparent)}}.bg-white\/5{background-color:#ffffff0d}@supports (color:color-mix(in lab,red,red)){.bg-white\/5{background-color:color-mix(in oklab,var(--color-white) 5%,transparent)}}.bg-linear-to-r{--tw-gradient-position:to right}@supports (background-image:linear-gradient(in lab,red,red)){.bg-linear-to-r{--tw-gradient-position:to right in oklab}}.bg-linear-to-r{background-image:linear-gradient(var(--tw-gradient-stops))}.from-brand-accent{--tw-gradient-from:var(--color-brand-accent);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-transparent{--tw-gradient-from:transparent;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.via-brand-accent{--tw-gradient-via:var(--color-brand-accent);--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.to-brand-accent-light{--tw-gradient-to:var(--color-brand-accent-light);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-transparent{--tw-gradient-to:transparent;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.bg-clip-text{-webkit-background-clip:text;background-clip:text}.p-6{padding:calc(var(--spacing) * 6)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.px-8{padding-inline:calc(var(--spacing) * 8)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-10{padding-block:calc(var(--spacing) * 10)}.py-12{padding-block:calc(var(--spacing) * 12)}.pt-8{padding-top:calc(var(--spacing) * 8)}.text-center{text-align:center}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.text-brand-accent{color:var(--color-brand-accent)}.text-brand-gray{color:var(--color-brand-gray)}.text-brand-gray\/30{color:#dbdee54d}@supports (color:color-mix(in lab,red,red)){.text-brand-gray\/30{color:color-mix(in oklab,var(--color-brand-gray) 30%,transparent)}}.text-brand-gray\/60{color:#dbdee599}@supports (color:color-mix(in lab,red,red)){.text-brand-gray\/60{color:color-mix(in oklab,var(--color-brand-gray) 60%,transparent)}}.text-brand-gray\/80{color:#dbdee5cc}@supports (color:color-mix(in lab,red,red)){.text-brand-gray\/80{color:color-mix(in oklab,var(--color-brand-gray) 80%,transparent)}}.text-brand-success{color:var(--color-brand-success)}.text-transparent{color:#0000}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.opacity-0{opacity:0}.opacity-50{opacity:.5}.opacity-70{opacity:.7}.opacity-75{opacity:.75}.mix-blend-multiply{mix-blend-mode:multiply}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-inner{--tw-shadow:inset 0 2px 4px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.blur-xl{--tw-blur:blur(var(--blur-xl));filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.drop-shadow-lg{--tw-drop-shadow-size:drop-shadow(0 4px 4px var(--tw-drop-shadow-color,#00000026));--tw-drop-shadow:drop-shadow(var(--drop-shadow-lg));filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-blur-lg{--tw-backdrop-blur:blur(var(--blur-lg));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-300{--tw-duration:.3s;transition-duration:.3s}.animation-delay-2000{animation-delay:2s}.animation-delay-4000{animation-delay:4s}@media(hover:hover){.group-hover\:translate-x-1:is(:where(.group):hover *){--tw-translate-x:calc(var(--spacing) * 1);translate:var(--tw-translate-x) var(--tw-translate-y)}.group-hover\:bg-brand-accent:is(:where(.group):hover *){background-color:var(--color-brand-accent)}.group-hover\:text-brand-accent-light:is(:where(.group):hover *){color:var(--color-brand-accent-light)}.group-hover\:text-white:is(:where(.group):hover *){color:var(--color-white)}.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}.hover\:scale-110:hover{--tw-scale-x:110%;--tw-scale-y:110%;--tw-scale-z:110%;scale:var(--tw-scale-x) var(--tw-scale-y)}.hover\:border-brand-accent\/50:hover{border-color:#e6ad0080}@supports (color:color-mix(in lab,red,red)){.hover\:border-brand-accent\/50:hover{border-color:color-mix(in oklab,var(--color-brand-accent) 50%,transparent)}}.hover\:bg-white\/10:hover{background-color:#ffffff1a}@supports (color:color-mix(in lab,red,red)){.hover\:bg-white\/10:hover{background-color:color-mix(in oklab,var(--color-white) 10%,transparent)}}}@media(min-width:40rem){.sm\:px-12{padding-inline:calc(var(--spacing) * 12)}.sm\:py-12{padding-block:calc(var(--spacing) * 12)}.sm\:text-5xl{font-size:var(--text-5xl);line-height:var(--tw-leading,var(--text-5xl--line-height))}}}@keyframes blob{0%,to{transform:translate(0)scale(1)}33%{transform:translate(30px,-50px)scale(1.1)}66%{transform:translate(-20px,20px)scale(.9)}}body{background-color:var(--color-brand-primary);background-image:radial-gradient(var(--color-brand-dots) 1px,transparent 1px);color:var(--color-brand-gray);background-size:24px 24px}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-space-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:"*";inherits:false}@property --tw-gradient-via-stops{syntax:"*";inherits:false}@property --tw-gradient-from-position{syntax:"<length-percentage>";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:"<length-percentage>";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:"<length-percentage>";inherits:false;initial-value:100%}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@keyframes ping{75%,to{opacity:0;transform:scale(2)}}</style>
8
8
  </head>
9
9
  <body class="antialiased min-h-screen flex flex-col items-center justify-center overflow-hidden">
10
10
 
@@ -8,6 +8,39 @@
8
8
  *
9
9
  * @module
10
10
  */
11
+ let csrfTokenCache = null;
12
+ function getWindowToken() {
13
+ if (typeof window !== "undefined") {
14
+ return window.__LITESTAR_CSRF__;
15
+ }
16
+ return undefined;
17
+ }
18
+ function getMetaToken() {
19
+ if (typeof document !== "undefined") {
20
+ const meta = document.querySelector('meta[name="csrf-token"]');
21
+ if (meta) {
22
+ const content = meta.getAttribute("content");
23
+ if (content !== null && content.length > 0) {
24
+ return content;
25
+ }
26
+ }
27
+ }
28
+ return undefined;
29
+ }
30
+ function getInertiaToken() {
31
+ if (typeof window === "undefined") {
32
+ return undefined;
33
+ }
34
+ const win = window;
35
+ const inertiaPage = win.__INERTIA_PAGE__;
36
+ if (inertiaPage?.props) {
37
+ const props = inertiaPage.props;
38
+ if (typeof props.csrf_token === "string") {
39
+ return props.csrf_token;
40
+ }
41
+ }
42
+ return undefined;
43
+ }
11
44
  /**
12
45
  * Get the CSRF token from the page.
13
46
  *
@@ -32,29 +65,46 @@
32
65
  * ```
33
66
  */
34
67
  export function getCsrfToken() {
35
- // Check window global (SPA mode)
36
- if (typeof window !== "undefined" && window.__LITESTAR_CSRF__) {
37
- return window.__LITESTAR_CSRF__;
38
- }
39
- // Check meta tag (template mode)
40
- if (typeof document !== "undefined") {
41
- const meta = document.querySelector('meta[name="csrf-token"]');
42
- if (meta) {
43
- return meta.getAttribute("content") || "";
68
+ const windowToken = getWindowToken();
69
+ if (windowToken) {
70
+ if (csrfTokenCache?.windowToken === windowToken && csrfTokenCache.token === windowToken) {
71
+ return csrfTokenCache.token;
44
72
  }
73
+ csrfTokenCache = {
74
+ token: windowToken,
75
+ windowToken,
76
+ };
77
+ return windowToken;
45
78
  }
46
- // Check Inertia page props
47
- if (typeof window !== "undefined") {
48
- const win = window;
49
- const inertiaPage = win.__INERTIA_PAGE__;
50
- if (inertiaPage?.props) {
51
- const props = inertiaPage.props;
52
- if (typeof props.csrf_token === "string") {
53
- return props.csrf_token;
54
- }
55
- }
79
+ const metaToken = getMetaToken();
80
+ const inertiaToken = getInertiaToken();
81
+ const token = metaToken ?? inertiaToken ?? "";
82
+ if (csrfTokenCache &&
83
+ csrfTokenCache.windowToken === undefined &&
84
+ csrfTokenCache.metaToken === metaToken &&
85
+ csrfTokenCache.inertiaToken === inertiaToken &&
86
+ csrfTokenCache.token === token) {
87
+ return csrfTokenCache.token;
56
88
  }
57
- return "";
89
+ csrfTokenCache = {
90
+ token,
91
+ windowToken: undefined,
92
+ metaToken,
93
+ inertiaToken,
94
+ };
95
+ return token;
96
+ }
97
+ function hasCsrfHeader(headers) {
98
+ if (headers == null) {
99
+ return false;
100
+ }
101
+ if (headers instanceof Headers) {
102
+ return headers.has("X-CSRF-Token");
103
+ }
104
+ if (Array.isArray(headers)) {
105
+ return headers.some((entry) => Array.isArray(entry) && entry.length >= 2 && typeof entry[0] === "string" && entry[0].toLowerCase() === "x-csrf-token");
106
+ }
107
+ return Object.keys(headers).some((key) => key.toLowerCase() === "x-csrf-token");
58
108
  }
59
109
  /**
60
110
  * Create headers object with CSRF token included.
@@ -75,9 +125,16 @@ export function getCsrfToken() {
75
125
  */
76
126
  export function csrfHeaders(additionalHeaders = {}) {
77
127
  const token = getCsrfToken();
128
+ if (!token) {
129
+ return additionalHeaders;
130
+ }
131
+ const existingTokenHeader = Object.keys(additionalHeaders).find((key) => key.toLowerCase() === "x-csrf-token");
132
+ if (existingTokenHeader !== undefined) {
133
+ return additionalHeaders;
134
+ }
78
135
  return {
79
136
  ...additionalHeaders,
80
- ...(token ? { "X-CSRF-Token": token } : {}),
137
+ "X-CSRF-Token": token,
81
138
  };
82
139
  }
83
140
  /**
@@ -103,12 +160,36 @@ export function csrfFetch(input, init) {
103
160
  if (!token) {
104
161
  return fetch(input, init);
105
162
  }
106
- const headers = new Headers(init?.headers);
107
- if (!headers.has("X-CSRF-Token")) {
108
- headers.set("X-CSRF-Token", token);
163
+ if (!hasCsrfHeader(init?.headers)) {
164
+ if (!init || typeof init.headers === "undefined") {
165
+ return fetch(input, {
166
+ ...init,
167
+ headers: { "X-CSRF-Token": token },
168
+ });
169
+ }
170
+ if (typeof init.headers === "object" && init.headers !== null && !(init.headers instanceof Headers)) {
171
+ if (Array.isArray(init.headers)) {
172
+ return fetch(input, {
173
+ ...init,
174
+ headers: [...init.headers, ["X-CSRF-Token", token]],
175
+ });
176
+ }
177
+ return fetch(input, {
178
+ ...init,
179
+ headers: {
180
+ ...init.headers,
181
+ "X-CSRF-Token": token,
182
+ },
183
+ });
184
+ }
185
+ if (init.headers instanceof Headers) {
186
+ const headers = new Headers(init.headers);
187
+ headers.set("X-CSRF-Token", token);
188
+ return fetch(input, {
189
+ ...init,
190
+ headers,
191
+ });
192
+ }
109
193
  }
110
- return fetch(input, {
111
- ...init,
112
- headers,
113
- });
194
+ return fetch(input, init);
114
195
  }
@@ -69,5 +69,18 @@ interface Dir {
69
69
  * @param on - Whether to enable debug logging.
70
70
  */
71
71
  export declare function setDebug(on: boolean): void;
72
+ /**
73
+ * @internal
74
+ * Exposed for tests/diagnostics only.
75
+ */
76
+ export declare function __getExpressionCacheSize(): number;
77
+ /** @internal */
78
+ export declare function __getExpressionCacheKeys(): string[];
79
+ /** @internal */
80
+ export declare function __setExpressionCacheLimit(limit: number): void;
81
+ /** @internal */
82
+ export declare function __clearExpressionCache(): void;
83
+ /** @internal */
84
+ export declare function __compileExpressionForTest(expression: string): ((c: Ctx) => unknown) | null;
72
85
  export declare function addDirective(dir: Dir): void;
73
86
  export {};
@@ -38,9 +38,26 @@ function getHeadersFromConfigRequestEvent(evt) {
38
38
  return headers;
39
39
  }
40
40
  let debug = false;
41
- const cache = new Map();
41
+ const DEFAULT_EXPRESSION_CACHE_MAX_SIZE = 1024;
42
+ const expressionCache = new Map();
43
+ let expressionCacheMaxSize = DEFAULT_EXPRESSION_CACHE_MAX_SIZE;
42
44
  const memoStore = new WeakMap();
43
45
  const registeredHtmxInstances = new WeakSet();
46
+ function trimExpressionCache() {
47
+ while (expressionCache.size > expressionCacheMaxSize) {
48
+ const first = expressionCache.keys().next().value;
49
+ if (first === undefined)
50
+ return;
51
+ expressionCache.delete(first);
52
+ }
53
+ }
54
+ function cacheExpression(key, value) {
55
+ if (expressionCache.has(key)) {
56
+ expressionCache.delete(key);
57
+ }
58
+ expressionCache.set(key, value);
59
+ trimExpressionCache();
60
+ }
44
61
  function runtime(node) {
45
62
  let store = memoStore.get(node);
46
63
  if (!store) {
@@ -435,16 +452,17 @@ function childCtx(parent, data, index, key) {
435
452
  function expr(s) {
436
453
  if (!s)
437
454
  return null;
438
- const cached = cache.get(s);
439
- if (cached !== undefined)
455
+ const cached = expressionCache.get(s);
456
+ if (cached !== undefined) {
440
457
  return cached;
458
+ }
441
459
  try {
442
460
  const fn = new Function("ctx", `with(ctx){return(${s})}`);
443
- cache.set(s, fn);
461
+ cacheExpression(s, fn);
444
462
  return fn;
445
463
  }
446
464
  catch {
447
- cache.set(s, null);
465
+ cacheExpression(s, null);
448
466
  return null;
449
467
  }
450
468
  }
@@ -526,6 +544,31 @@ function removeBetween(start, end) {
526
544
  export function setDebug(on) {
527
545
  debug = on;
528
546
  }
547
+ /**
548
+ * @internal
549
+ * Exposed for tests/diagnostics only.
550
+ */
551
+ export function __getExpressionCacheSize() {
552
+ return expressionCache.size;
553
+ }
554
+ /** @internal */
555
+ export function __getExpressionCacheKeys() {
556
+ return [...expressionCache.keys()];
557
+ }
558
+ /** @internal */
559
+ export function __setExpressionCacheLimit(limit) {
560
+ const normalized = Number.isFinite(limit) ? Math.max(1, Math.floor(limit)) : DEFAULT_EXPRESSION_CACHE_MAX_SIZE;
561
+ expressionCacheMaxSize = normalized;
562
+ trimExpressionCache();
563
+ }
564
+ /** @internal */
565
+ export function __clearExpressionCache() {
566
+ expressionCache.clear();
567
+ }
568
+ /** @internal */
569
+ export function __compileExpressionForTest(expression) {
570
+ return expr(expression);
571
+ }
529
572
  export function addDirective(dir) {
530
573
  directives.push(dir);
531
574
  }
@@ -100,6 +100,10 @@ export declare function isRoute<T extends string>(url: string, pattern: string,
100
100
  * isCurrentRoute('*_page', routeDefinitions) // true (wildcard)
101
101
  */
102
102
  export declare function isCurrentRoute<T extends string>(pattern: string, routes: Record<T, RouteDefinition>): boolean;
103
+ /** @internal */
104
+ export declare function __getRouteWildcardRegexCacheSize(): number;
105
+ /** @internal */
106
+ export declare function __clearRouteHelperCachesForTest(): void;
103
107
  /**
104
108
  * Route helpers interface returned by createRouteHelpers.
105
109
  */
@@ -27,6 +27,8 @@
27
27
  */
28
28
  /** Cache for compiled route patterns */
29
29
  const patternCache = new Map();
30
+ /** Cache for wildcard route-name pattern matching */
31
+ const wildcardPatternCache = new Map();
30
32
  /**
31
33
  * Compile a route path pattern to a regex for URL matching.
32
34
  * Results are cached for performance.
@@ -58,6 +60,16 @@ function compilePattern(path) {
58
60
  patternCache.set(path, regex);
59
61
  return regex;
60
62
  }
63
+ /** Compile a wildcard route pattern to regex for route-name matching. */
64
+ function compileWildcardPattern(pattern) {
65
+ const cached = wildcardPatternCache.get(pattern);
66
+ if (cached)
67
+ return cached;
68
+ const escaped = pattern.replace(/[.+?^$|()[\]{}]/g, "\\$&");
69
+ const regex = new RegExp(`^${escaped.replace(/\*/g, ".*")}$`);
70
+ wildcardPatternCache.set(pattern, regex);
71
+ return regex;
72
+ }
61
73
  /**
62
74
  * Convert a URL to its corresponding route name.
63
75
  *
@@ -119,9 +131,7 @@ export function isRoute(url, pattern, routes) {
119
131
  const routeName = toRoute(url, routes);
120
132
  if (!routeName)
121
133
  return false;
122
- // Escape special regex chars (except *), then convert * to .*
123
- const escaped = pattern.replace(/[.+?^$|()[\]{}]/g, "\\$&");
124
- const regex = new RegExp(`^${escaped.replace(/\*/g, ".*")}$`);
134
+ const regex = compileWildcardPattern(pattern);
125
135
  return regex.test(routeName);
126
136
  }
127
137
  /**
@@ -144,11 +154,18 @@ export function isCurrentRoute(pattern, routes) {
144
154
  const current = currentRoute(routes);
145
155
  if (!current)
146
156
  return false;
147
- // Escape special regex chars (except *), then convert * to .*
148
- const escaped = pattern.replace(/[.+?^$|()[\]{}]/g, "\\$&");
149
- const regex = new RegExp(`^${escaped.replace(/\*/g, ".*")}$`);
157
+ const regex = compileWildcardPattern(pattern);
150
158
  return regex.test(current);
151
159
  }
160
+ /** @internal */
161
+ export function __getRouteWildcardRegexCacheSize() {
162
+ return wildcardPatternCache.size;
163
+ }
164
+ /** @internal */
165
+ export function __clearRouteHelperCachesForTest() {
166
+ patternCache.clear();
167
+ wildcardPatternCache.clear();
168
+ }
152
169
  /**
153
170
  * Create route helpers bound to a specific routeDefinitions object.
154
171
  *
package/dist/js/index.js CHANGED
@@ -11,6 +11,7 @@ import { createLogger } from "./shared/logger.js";
11
11
  import { createLitestarTypeGenPlugin } from "./shared/typegen-plugin.js";
12
12
  let exitHandlersBound = false;
13
13
  let warnedMissingRuntimeConfig = false;
14
+ const MAX_TRANSFORM_PAYLOAD_BYTES = 1e6;
14
15
  const refreshPaths = ["src/**", "resources/**", "assets/**"].filter((path2) => fs.existsSync(path2.replace(/\*\*$/, "")));
15
16
  function litestar(config) {
16
17
  const pluginConfig = resolvePluginConfig(config);
@@ -91,10 +92,11 @@ function resolveLitestarPlugin(pluginConfig) {
91
92
  return [key, value];
92
93
  }
93
94
  const existingConfigure = value.configure;
95
+ const valueWithWebsocket = Object.hasOwn(value, "ws") ? value : { ...value, ws: true };
94
96
  return [
95
97
  key,
96
98
  {
97
- ...value,
99
+ ...valueWithWebsocket,
98
100
  configure(proxy, opts) {
99
101
  proxy.on("error", (err) => {
100
102
  const msg = String(err?.message ?? "");
@@ -143,11 +145,13 @@ function resolveLitestarPlugin(pluginConfig) {
143
145
  userConfig.server?.proxy ?? (env.APP_URL ? {
144
146
  "/api": {
145
147
  target: env.APP_URL,
146
- changeOrigin: true
148
+ changeOrigin: true,
149
+ ws: true
147
150
  },
148
151
  "/schema": {
149
152
  target: env.APP_URL,
150
- changeOrigin: true
153
+ changeOrigin: true,
154
+ ws: true
151
155
  }
152
156
  } : void 0)
153
157
  ),
@@ -327,24 +331,64 @@ function resolveLitestarPlugin(pluginConfig) {
327
331
  const requestUrl = req.originalUrl ?? req.url ?? "/";
328
332
  const requestPath = requestUrl.split("?")[0];
329
333
  const isRootRequest = requestPath === "/" || requestPath === "/index.html";
334
+ const isJsonContentType = (value) => {
335
+ if (!value) {
336
+ return false;
337
+ }
338
+ const normalized = Array.isArray(value) ? value[0] : value;
339
+ return normalized.toLowerCase().split(";")[0].trim() === "application/json";
340
+ };
341
+ const readBody = async () => new Promise((resolve, reject) => {
342
+ const chunks = [];
343
+ let bytesRead = 0;
344
+ req.on("data", (chunk) => {
345
+ const bodyChunk = Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk));
346
+ bytesRead += bodyChunk.length;
347
+ if (bytesRead > MAX_TRANSFORM_PAYLOAD_BYTES) {
348
+ req.removeAllListeners();
349
+ reject(new Error("Request payload too large"));
350
+ return;
351
+ }
352
+ chunks.push(bodyChunk);
353
+ });
354
+ req.on("error", (error) => reject(error));
355
+ req.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8")));
356
+ });
330
357
  if (requestPath === "/__litestar__/transform-index") {
358
+ const reqHeaders = req.headers ?? {};
331
359
  if (req.method !== "POST") {
332
360
  res.statusCode = 405;
333
361
  res.setHeader("Content-Type", "text/plain");
334
362
  res.end("Method Not Allowed");
335
363
  return;
336
364
  }
337
- const readBody = async () => new Promise((resolve, reject) => {
338
- let data = "";
339
- req.on("data", (chunk) => {
340
- data += chunk;
341
- });
342
- req.on("end", () => resolve(data));
343
- req.on("error", (err) => reject(err));
344
- });
365
+ const contentLengthHeader = reqHeaders["content-length"];
366
+ const contentLengthHeaderValue = Array.isArray(contentLengthHeader) ? contentLengthHeader[0] : contentLengthHeader;
367
+ const contentLength = typeof contentLengthHeaderValue === "string" ? Number(contentLengthHeaderValue) : Number.NaN;
368
+ if (!Number.isNaN(contentLength) && contentLength > MAX_TRANSFORM_PAYLOAD_BYTES) {
369
+ res.statusCode = 413;
370
+ res.setHeader("Content-Type", "text/plain");
371
+ res.end("Payload too large");
372
+ return;
373
+ }
374
+ const contentType = reqHeaders["content-type"];
375
+ if (contentType !== void 0 && !isJsonContentType(contentType)) {
376
+ res.statusCode = 415;
377
+ res.setHeader("Content-Type", "text/plain");
378
+ res.end("Unsupported content type");
379
+ return;
380
+ }
345
381
  try {
346
382
  const body = await readBody();
347
- const payload = JSON.parse(body);
383
+ let payload;
384
+ try {
385
+ payload = JSON.parse(body);
386
+ } catch {
387
+ res.statusCode = 400;
388
+ res.setHeader("Content-Type", "text/plain");
389
+ res.end("Invalid payload");
390
+ return;
391
+ }
348
392
  if (!payload.html || typeof payload.html !== "string") {
349
393
  res.statusCode = 400;
350
394
  res.setHeader("Content-Type", "text/plain");
@@ -357,6 +401,12 @@ function resolveLitestarPlugin(pluginConfig) {
357
401
  res.setHeader("Content-Type", "text/html");
358
402
  res.end(transformedHtml);
359
403
  } catch (e) {
404
+ if (e instanceof Error && e.message === "Request payload too large") {
405
+ res.statusCode = 413;
406
+ res.setHeader("Content-Type", "text/plain");
407
+ res.end("Payload too large");
408
+ return;
409
+ }
360
410
  resolvedConfig.logger.error(`Error transforming index.html: ${e instanceof Error ? e.message : e}`);
361
411
  res.statusCode = 500;
362
412
  res.setHeader("Content-Type", "text/plain");
@@ -370,8 +420,7 @@ function resolveLitestarPlugin(pluginConfig) {
370
420
  }
371
421
  if (pluginConfig.inertiaMode) {
372
422
  try {
373
- const placeholderPath = path.join(dirname(), "dev-server-index.html");
374
- const placeholderContent = await fs.promises.readFile(placeholderPath, "utf-8");
423
+ const placeholderContent = await loadDevServerPlaceholder();
375
424
  res.statusCode = 200;
376
425
  res.setHeader("Content-Type", "text/html");
377
426
  res.end(placeholderContent.replace(/{{ APP_URL }}/g, appUrl));
@@ -399,8 +448,7 @@ function resolveLitestarPlugin(pluginConfig) {
399
448
  }
400
449
  }
401
450
  try {
402
- const placeholderPath = path.join(dirname(), "dev-server-index.html");
403
- const placeholderContent = await fs.promises.readFile(placeholderPath, "utf-8");
451
+ const placeholderContent = await loadDevServerPlaceholder();
404
452
  res.statusCode = 200;
405
453
  res.setHeader("Content-Type", "text/html");
406
454
  res.end(placeholderContent.replace(/{{ APP_URL }}/g, appUrl));
@@ -838,11 +886,44 @@ function resolveDevelopmentEnvironmentTld(configPath) {
838
886
  return config.tld;
839
887
  }
840
888
  function dirname() {
889
+ let moduleDir = "";
841
890
  try {
842
- return fileURLToPath(new URL(".", import.meta.url));
891
+ moduleDir = fileURLToPath(new URL(".", import.meta.url));
843
892
  } catch {
844
- return path.resolve(process.cwd(), "dist/js");
893
+ moduleDir = path.resolve(process.cwd(), "src", "js", "src");
894
+ }
895
+ const candidates = [path.resolve(moduleDir, "../../../dist/js"), path.resolve(process.cwd(), "../dist/js"), path.resolve(process.cwd(), "dist/js"), moduleDir];
896
+ for (const candidate of candidates) {
897
+ if (fs.existsSync(path.join(candidate, "dev-server-index.html"))) {
898
+ return candidate;
899
+ }
900
+ }
901
+ return path.resolve(process.cwd(), "../dist/js");
902
+ }
903
+ function getDevServerPlaceholderCandidates() {
904
+ const distJsRoot = "dist/js";
905
+ const placeholderName = "dev-server-index.html";
906
+ const moduleDir = dirname();
907
+ const candidates = [
908
+ path.join(dirname(), placeholderName),
909
+ path.join(process.cwd(), distJsRoot, placeholderName),
910
+ path.join(process.cwd(), "src", "js", distJsRoot, placeholderName),
911
+ path.resolve(process.cwd(), "..", distJsRoot, placeholderName),
912
+ path.join(moduleDir, distJsRoot, placeholderName)
913
+ ];
914
+ return [...new Set(candidates)];
915
+ }
916
+ async function loadDevServerPlaceholder() {
917
+ const candidates = getDevServerPlaceholderCandidates();
918
+ let lastError = new Error("Failed to load dev server placeholder index.html");
919
+ for (const candidatePath of candidates) {
920
+ try {
921
+ return await fs.promises.readFile(candidatePath, "utf-8");
922
+ } catch (error) {
923
+ lastError = error;
924
+ }
845
925
  }
926
+ throw lastError;
846
927
  }
847
928
  function normalizeAssetUrl(url) {
848
929
  const trimmed = url.trim();
@@ -25,17 +25,42 @@ async function hashFile(filePath) {
25
25
  return "";
26
26
  }
27
27
  }
28
+ async function readFileMetadata(filePath) {
29
+ try {
30
+ const stat = await fs.promises.stat(filePath);
31
+ return {
32
+ size: stat.size,
33
+ mtimeMs: stat.mtimeMs
34
+ };
35
+ } catch {
36
+ return null;
37
+ }
38
+ }
39
+ function isMetadataMatch(a, b) {
40
+ return a !== null && b !== null && a.size === b.size && a.mtimeMs === b.mtimeMs;
41
+ }
42
+ function isOptionalMetadataMatch(a, b) {
43
+ if (a === null && b === null) {
44
+ return true;
45
+ }
46
+ return isMetadataMatch(a, b);
47
+ }
28
48
  function hashObject(obj) {
29
49
  const sorted = JSON.stringify(obj, Object.keys(obj).sort());
30
50
  return crypto.createHash("sha256").update(sorted).digest("hex");
31
51
  }
32
52
  async function shouldRunOpenApiTs(openapiPath, configPath, options) {
33
53
  const cache = await loadCache();
34
- const inputHash = await hashFile(openapiPath);
35
- const configHash = configPath ? await hashFile(configPath) : "";
36
54
  const optionsHash = hashObject(options);
37
55
  const cacheKey = "openapi-ts";
38
56
  const entry = cache[cacheKey];
57
+ const currentInputMetadata = await readFileMetadata(openapiPath);
58
+ const currentConfigMetadata = configPath ? await readFileMetadata(configPath) : null;
59
+ if (entry && entry.optionsHash === optionsHash && isMetadataMatch(entry.inputMeta ?? null, currentInputMetadata) && isOptionalMetadataMatch(entry.configMeta ?? null, currentConfigMetadata)) {
60
+ return false;
61
+ }
62
+ const inputHash = await hashFile(openapiPath);
63
+ const configHash = configPath ? await hashFile(configPath) : "";
39
64
  if (entry && entry.inputHash === inputHash && entry.configHash === configHash && entry.optionsHash === optionsHash) {
40
65
  return false;
41
66
  }
@@ -47,6 +72,8 @@ async function updateOpenApiTsCache(openapiPath, configPath, options) {
47
72
  inputHash: await hashFile(openapiPath),
48
73
  configHash: configPath ? await hashFile(configPath) : "",
49
74
  optionsHash: hashObject(options),
75
+ inputMeta: await readFileMetadata(openapiPath) ?? void 0,
76
+ configMeta: configPath ? await readFileMetadata(configPath) ?? void 0 : void 0,
50
77
  timestamp: Date.now()
51
78
  };
52
79
  await saveCache(cache);
@@ -56,9 +83,13 @@ async function computePagePropsHash(pagePropsPath) {
56
83
  }
57
84
  async function shouldRegeneratePageProps(pagePropsPath) {
58
85
  const cache = await loadCache();
59
- const currentHash = await hashFile(pagePropsPath);
86
+ const currentMetadata = await readFileMetadata(pagePropsPath);
60
87
  const cacheKey = "page-props";
61
88
  const entry = cache[cacheKey];
89
+ if (entry && isMetadataMatch(entry.inputMeta ?? null, currentMetadata)) {
90
+ return false;
91
+ }
92
+ const currentHash = await hashFile(pagePropsPath);
62
93
  if (entry && entry.inputHash === currentHash) {
63
94
  return false;
64
95
  }
@@ -68,6 +99,7 @@ async function updatePagePropsCache(pagePropsPath) {
68
99
  const cache = await loadCache();
69
100
  cache["page-props"] = {
70
101
  inputHash: await hashFile(pagePropsPath),
102
+ inputMeta: await readFileMetadata(pagePropsPath) ?? void 0,
71
103
  configHash: "",
72
104
  optionsHash: "",
73
105
  timestamp: Date.now()
@@ -46,7 +46,7 @@ async function runHeyApiGeneration(config, configPath, plugins, logger) {
46
46
  try {
47
47
  nodeRequire.resolve("zod", { paths: [projectRoot] });
48
48
  } catch {
49
- logger?.warn(`zod not installed - run: ${resolveInstallHint()} zod`);
49
+ logger?.warn(`zod not installed - run: ${resolveInstallHint("zod")}`);
50
50
  }
51
51
  }
52
52
  const cmd = resolvePackageExecutor(args.join(" "), executor);
@@ -83,11 +83,16 @@ async function runTypeGeneration(config, options = {}) {
83
83
  result.generated = true;
84
84
  } catch (error) {
85
85
  const message = error instanceof Error ? error.message : String(error);
86
- if (message.includes("not found") || message.includes("ENOENT") || message.includes("not installed")) {
86
+ const isPackageNotInstalled = message.includes("not installed");
87
+ const isRuntimeEnoent = !isPackageNotInstalled && (message.includes("ENOENT") || error instanceof Error && "code" in error && error.code === "ENOENT");
88
+ if (isPackageNotInstalled) {
87
89
  const zodHint = config.generateZod ? " zod" : "";
88
- const warning = `@hey-api/openapi-ts not installed - run: ${resolveInstallHint()} -D @hey-api/openapi-ts${zodHint}`;
90
+ const warning = `@hey-api/openapi-ts not installed - run: ${resolveInstallHint(`@hey-api/openapi-ts${zodHint}`)}`;
89
91
  result.warnings.push(warning);
90
92
  logger?.warn(warning);
93
+ } else if (isRuntimeEnoent) {
94
+ result.errors.push(`File not found during type generation: ${message}`);
95
+ logger?.error(`Type generation failed (file not found): ${message}`);
91
96
  } else {
92
97
  result.errors.push(message);
93
98
  logger?.error(`Type generation failed: ${message}`);
@@ -6,7 +6,7 @@ import { emitPagePropsTypes } from "./emit-page-props-types.js";
6
6
  import { emitSchemasTypes } from "./emit-schemas-types.js";
7
7
  import { emitStaticPropsTypes } from "./emit-static-props-types.js";
8
8
  import { formatPath } from "./format-path.js";
9
- import { shouldRunOpenApiTs, updateOpenApiTsCache } from "./typegen-cache.js";
9
+ import { shouldRegeneratePageProps, shouldRunOpenApiTs, updateOpenApiTsCache, updatePagePropsCache } from "./typegen-cache.js";
10
10
  import { buildHeyApiPlugins, findOpenApiTsConfig, runHeyApiGeneration } from "./typegen-core.js";
11
11
  async function getFileMtime(filePath) {
12
12
  const stat = await fs.promises.stat(filePath);
@@ -90,9 +90,15 @@ function createLitestarTypeGenPlugin(typesConfig, options) {
90
90
  }
91
91
  if (typesConfig.generatePageProps && fs.existsSync(absolutePagePropsPath)) {
92
92
  try {
93
- const changed = await emitPagePropsTypes(absolutePagePropsPath, typesConfig.output);
94
- if (changed) {
95
- generated = true;
93
+ const shouldRun = await shouldRegeneratePageProps(absolutePagePropsPath);
94
+ if (shouldRun) {
95
+ const changed = await emitPagePropsTypes(absolutePagePropsPath, typesConfig.output);
96
+ await updatePagePropsCache(absolutePagePropsPath);
97
+ if (changed) {
98
+ generated = true;
99
+ } else {
100
+ resolvedConfig?.logger.info(`${colors.cyan("\u2022")} Page props types ${colors.dim("(unchanged)")}`);
101
+ }
96
102
  } else {
97
103
  resolvedConfig?.logger.info(`${colors.cyan("\u2022")} Page props types ${colors.dim("(unchanged)")}`);
98
104
  }
@@ -133,7 +133,8 @@ function litestarSvelteKit(userConfig = {}) {
133
133
  [config.apiPrefix]: {
134
134
  target: config.apiProxy,
135
135
  changeOrigin: true,
136
- secure: false
136
+ secure: false,
137
+ ws: true
137
138
  }
138
139
  }
139
140
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "litestar-vite-plugin",
3
- "version": "0.17.0",
3
+ "version": "0.18.3",
4
4
  "type": "module",
5
5
  "description": "Litestar plugin for Vite.",
6
6
  "keywords": [