litestar-vite-plugin 0.18.0 → 0.18.4

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 ?? "");
@@ -111,6 +113,8 @@ function resolveLitestarPlugin(pluginConfig) {
111
113
  })
112
114
  );
113
115
  };
116
+ const explicitServerOrigin = typeof userConfig.server?.origin === "string" && userConfig.server.origin.length > 0 ? userConfig.server.origin : void 0;
117
+ const shouldForceDirectServerOrigin = explicitServerOrigin !== void 0 || pythonDefaults?.proxyMode === "direct";
114
118
  const devBase = pluginConfig.assetUrl.startsWith("/") ? pluginConfig.assetUrl : pluginConfig.assetUrl.replace(/\/+$/, "");
115
119
  ensureCommandShouldRunInEnvironment(command, env, mode);
116
120
  return {
@@ -127,7 +131,7 @@ function resolveLitestarPlugin(pluginConfig) {
127
131
  assetsInlineLimit: userConfig.build?.assetsInlineLimit ?? 0
128
132
  },
129
133
  server: {
130
- origin: userConfig.server?.origin ?? "__litestar_vite_placeholder__",
134
+ origin: shouldForceDirectServerOrigin ? explicitServerOrigin ?? "__litestar_vite_placeholder__" : void 0,
131
135
  // Auto-configure HMR to use a path that routes through Litestar proxy
132
136
  // Note: Vite automatically prepends `base` to `hmr.path`, so we just use "vite-hmr"
133
137
  // Result: base="/static/" + path="vite-hmr" = "/static/vite-hmr"
@@ -143,11 +147,13 @@ function resolveLitestarPlugin(pluginConfig) {
143
147
  userConfig.server?.proxy ?? (env.APP_URL ? {
144
148
  "/api": {
145
149
  target: env.APP_URL,
146
- changeOrigin: true
150
+ changeOrigin: true,
151
+ ws: true
147
152
  },
148
153
  "/schema": {
149
154
  target: env.APP_URL,
150
- changeOrigin: true
155
+ changeOrigin: true,
156
+ ws: true
151
157
  }
152
158
  } : void 0)
153
159
  ),
@@ -235,7 +241,8 @@ function resolveLitestarPlugin(pluginConfig) {
235
241
  const address = server.httpServer?.address();
236
242
  const isAddressInfo = (x) => typeof x === "object";
237
243
  if (isAddressInfo(address)) {
238
- viteDevServerUrl = userConfig.server?.origin ? userConfig.server.origin : resolveDevServerUrl(address, server.config, userConfig);
244
+ const explicitServerOrigin = typeof userConfig.server?.origin === "string" && userConfig.server.origin.length > 0 ? userConfig.server.origin : void 0;
245
+ viteDevServerUrl = explicitServerOrigin ? explicitServerOrigin : resolveDevServerUrl(address, server.config, userConfig);
239
246
  fs.mkdirSync(path.dirname(pluginConfig.hotFile), { recursive: true });
240
247
  fs.writeFileSync(pluginConfig.hotFile, viteDevServerUrl);
241
248
  setTimeout(async () => {
@@ -327,24 +334,64 @@ function resolveLitestarPlugin(pluginConfig) {
327
334
  const requestUrl = req.originalUrl ?? req.url ?? "/";
328
335
  const requestPath = requestUrl.split("?")[0];
329
336
  const isRootRequest = requestPath === "/" || requestPath === "/index.html";
337
+ const isJsonContentType = (value) => {
338
+ if (!value) {
339
+ return false;
340
+ }
341
+ const normalized = Array.isArray(value) ? value[0] : value;
342
+ return normalized.toLowerCase().split(";")[0].trim() === "application/json";
343
+ };
344
+ const readBody = async () => new Promise((resolve, reject) => {
345
+ const chunks = [];
346
+ let bytesRead = 0;
347
+ req.on("data", (chunk) => {
348
+ const bodyChunk = Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk));
349
+ bytesRead += bodyChunk.length;
350
+ if (bytesRead > MAX_TRANSFORM_PAYLOAD_BYTES) {
351
+ req.removeAllListeners();
352
+ reject(new Error("Request payload too large"));
353
+ return;
354
+ }
355
+ chunks.push(bodyChunk);
356
+ });
357
+ req.on("error", (error) => reject(error));
358
+ req.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8")));
359
+ });
330
360
  if (requestPath === "/__litestar__/transform-index") {
361
+ const reqHeaders = req.headers ?? {};
331
362
  if (req.method !== "POST") {
332
363
  res.statusCode = 405;
333
364
  res.setHeader("Content-Type", "text/plain");
334
365
  res.end("Method Not Allowed");
335
366
  return;
336
367
  }
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
- });
368
+ const contentLengthHeader = reqHeaders["content-length"];
369
+ const contentLengthHeaderValue = Array.isArray(contentLengthHeader) ? contentLengthHeader[0] : contentLengthHeader;
370
+ const contentLength = typeof contentLengthHeaderValue === "string" ? Number(contentLengthHeaderValue) : Number.NaN;
371
+ if (!Number.isNaN(contentLength) && contentLength > MAX_TRANSFORM_PAYLOAD_BYTES) {
372
+ res.statusCode = 413;
373
+ res.setHeader("Content-Type", "text/plain");
374
+ res.end("Payload too large");
375
+ return;
376
+ }
377
+ const contentType = reqHeaders["content-type"];
378
+ if (contentType !== void 0 && !isJsonContentType(contentType)) {
379
+ res.statusCode = 415;
380
+ res.setHeader("Content-Type", "text/plain");
381
+ res.end("Unsupported content type");
382
+ return;
383
+ }
345
384
  try {
346
385
  const body = await readBody();
347
- const payload = JSON.parse(body);
386
+ let payload;
387
+ try {
388
+ payload = JSON.parse(body);
389
+ } catch {
390
+ res.statusCode = 400;
391
+ res.setHeader("Content-Type", "text/plain");
392
+ res.end("Invalid payload");
393
+ return;
394
+ }
348
395
  if (!payload.html || typeof payload.html !== "string") {
349
396
  res.statusCode = 400;
350
397
  res.setHeader("Content-Type", "text/plain");
@@ -357,6 +404,12 @@ function resolveLitestarPlugin(pluginConfig) {
357
404
  res.setHeader("Content-Type", "text/html");
358
405
  res.end(transformedHtml);
359
406
  } catch (e) {
407
+ if (e instanceof Error && e.message === "Request payload too large") {
408
+ res.statusCode = 413;
409
+ res.setHeader("Content-Type", "text/plain");
410
+ res.end("Payload too large");
411
+ return;
412
+ }
360
413
  resolvedConfig.logger.error(`Error transforming index.html: ${e instanceof Error ? e.message : e}`);
361
414
  res.statusCode = 500;
362
415
  res.setHeader("Content-Type", "text/plain");
@@ -370,8 +423,7 @@ function resolveLitestarPlugin(pluginConfig) {
370
423
  }
371
424
  if (pluginConfig.inertiaMode) {
372
425
  try {
373
- const placeholderPath = path.join(dirname(), "dev-server-index.html");
374
- const placeholderContent = await fs.promises.readFile(placeholderPath, "utf-8");
426
+ const placeholderContent = await loadDevServerPlaceholder();
375
427
  res.statusCode = 200;
376
428
  res.setHeader("Content-Type", "text/html");
377
429
  res.end(placeholderContent.replace(/{{ APP_URL }}/g, appUrl));
@@ -399,8 +451,7 @@ function resolveLitestarPlugin(pluginConfig) {
399
451
  }
400
452
  }
401
453
  try {
402
- const placeholderPath = path.join(dirname(), "dev-server-index.html");
403
- const placeholderContent = await fs.promises.readFile(placeholderPath, "utf-8");
454
+ const placeholderContent = await loadDevServerPlaceholder();
404
455
  res.statusCode = 200;
405
456
  res.setHeader("Content-Type", "text/html");
406
457
  res.end(placeholderContent.replace(/{{ APP_URL }}/g, appUrl));
@@ -738,12 +789,15 @@ function resolveDevServerUrl(address, config, userConfig) {
738
789
  const serverProtocol = config.server.https ? "https" : "http";
739
790
  const protocol = clientProtocol ?? serverProtocol;
740
791
  const configHmrHost = typeof config.server.hmr === "object" ? config.server.hmr.host : null;
792
+ const userHost = typeof userConfig.server?.host === "string" ? userConfig.server.host : null;
741
793
  const configHost = typeof config.server.host === "string" ? config.server.host : null;
742
- const remoteHost = process.env.VITE_ALLOW_REMOTE && !userConfig.server?.host ? "localhost" : null;
794
+ const remoteHost = process.env.VITE_ALLOW_REMOTE && !userConfig.server?.host ? isIpv6(address) ? "[::1]" : "127.0.0.1" : null;
743
795
  const serverAddress = isIpv6(address) ? `[${address.address}]` : address.address;
744
- let host = configHmrHost ?? remoteHost ?? configHost ?? serverAddress;
796
+ let host = configHmrHost ?? userHost ?? remoteHost ?? configHost ?? serverAddress;
745
797
  if (host === "0.0.0.0") {
746
798
  host = "127.0.0.1";
799
+ } else if (host === "::" || host === "[::]") {
800
+ host = "[::1]";
747
801
  }
748
802
  const configHmrClientPort = typeof config.server.hmr === "object" ? config.server.hmr.clientPort : null;
749
803
  const port = configHmrClientPort ?? address.port;
@@ -838,11 +892,44 @@ function resolveDevelopmentEnvironmentTld(configPath) {
838
892
  return config.tld;
839
893
  }
840
894
  function dirname() {
895
+ let moduleDir = "";
841
896
  try {
842
- return fileURLToPath(new URL(".", import.meta.url));
897
+ moduleDir = fileURLToPath(new URL(".", import.meta.url));
843
898
  } catch {
844
- return path.resolve(process.cwd(), "dist/js");
899
+ moduleDir = path.resolve(process.cwd(), "src", "js", "src");
900
+ }
901
+ const candidates = [path.resolve(moduleDir, "../../../dist/js"), path.resolve(process.cwd(), "../dist/js"), path.resolve(process.cwd(), "dist/js"), moduleDir];
902
+ for (const candidate of candidates) {
903
+ if (fs.existsSync(path.join(candidate, "dev-server-index.html"))) {
904
+ return candidate;
905
+ }
906
+ }
907
+ return path.resolve(process.cwd(), "../dist/js");
908
+ }
909
+ function getDevServerPlaceholderCandidates() {
910
+ const distJsRoot = "dist/js";
911
+ const placeholderName = "dev-server-index.html";
912
+ const moduleDir = dirname();
913
+ const candidates = [
914
+ path.join(dirname(), placeholderName),
915
+ path.join(process.cwd(), distJsRoot, placeholderName),
916
+ path.join(process.cwd(), "src", "js", distJsRoot, placeholderName),
917
+ path.resolve(process.cwd(), "..", distJsRoot, placeholderName),
918
+ path.join(moduleDir, distJsRoot, placeholderName)
919
+ ];
920
+ return [...new Set(candidates)];
921
+ }
922
+ async function loadDevServerPlaceholder() {
923
+ const candidates = getDevServerPlaceholderCandidates();
924
+ let lastError = new Error("Failed to load dev server placeholder index.html");
925
+ for (const candidatePath of candidates) {
926
+ try {
927
+ return await fs.promises.readFile(candidatePath, "utf-8");
928
+ } catch (error) {
929
+ lastError = error;
930
+ }
845
931
  }
932
+ throw lastError;
846
933
  }
847
934
  function normalizeAssetUrl(url) {
848
935
  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.18.0",
3
+ "version": "0.18.4",
4
4
  "type": "module",
5
5
  "description": "Litestar plugin for Vite.",
6
6
  "keywords": [