diff --git a/apps/tests/src/routes/server-function-ping.tsx b/apps/tests/src/routes/server-function-ping.tsx index 70f9d2617..677a35340 100644 --- a/apps/tests/src/routes/server-function-ping.tsx +++ b/apps/tests/src/routes/server-function-ping.tsx @@ -1,18 +1,38 @@ import { createEffect, createSignal } from "solid-js"; -async function ping(value: string) { +async function sleep(value: unknown, ms: number) { + return new Promise((res) => { + setTimeout(res, ms, value); + }) +} + +async function ping(value: Date) { "use server"; - return await Promise.resolve(value); + const current = [ + value, + { + name: 'example', + async *[Symbol.asyncIterator]() { + yield sleep('foo', 5000); + yield sleep('bar', 5000); + yield sleep('baz', 5000); + } + } + ]; + + return current; } export default function App() { const [output, setOutput] = createSignal<{ result?: boolean }>({}); createEffect(async () => { - const value = `${Math.random() * 1000}`; + const value = new Date(); const result = await ping(value); - setOutput(prev => ({ ...prev, result: value === result })); + await ping(value); + console.log(result); + setOutput((prev) => ({ ...prev, result: value.toString() === result[0].toString() })); }); return ( diff --git a/apps/tests/test-results/.last-run.json b/apps/tests/test-results/.last-run.json deleted file mode 100644 index cbcc1fbac..000000000 --- a/apps/tests/test-results/.last-run.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "status": "passed", - "failedTests": [] -} \ No newline at end of file diff --git a/packages/start/package.json b/packages/start/package.json index 9170468d3..ade59bba2 100644 --- a/packages/start/package.json +++ b/packages/start/package.json @@ -56,13 +56,13 @@ "path-to-regexp": "^8.2.0", "pathe": "^2.0.3", "radix3": "^1.1.2", - "seroval": "^1.4.1", + "seroval": "^1.4.2", "seroval-plugins": "^1.4.0", "shiki": "^1.26.1", "solid-js": "^1.9.9", "source-map-js": "^1.2.1", "srvx": "^0.9.1", - "terracotta": "^1.0.6", + "terracotta": "^1.1.0", "vite-plugin-solid": "^2.11.9" }, "engines": { diff --git a/packages/start/src/server/serialization.ts b/packages/start/src/server/serialization.ts index c157d157e..8c0d0c9fb 100644 --- a/packages/start/src/server/serialization.ts +++ b/packages/start/src/server/serialization.ts @@ -111,7 +111,7 @@ export function serializeToJSONStream(value: any) { }); } -class SerovalChunkReader { +export class SerovalChunkReader { reader: ReadableStreamDefaultReader; buffer: Uint8Array; done: boolean; diff --git a/packages/start/src/server/server-runtime.ts b/packages/start/src/server/server-runtime.ts index 3a31cc2f7..d0dc06a75 100644 --- a/packages/start/src/server/server-runtime.ts +++ b/packages/start/src/server/server-runtime.ts @@ -1,5 +1,8 @@ - import { type Component } from "solid-js"; +import { + pushRequest, + pushResponse, +} from "../shared/server-function-inspector/server-function-tracker"; import { deserializeJSONStream, deserializeJSStream, @@ -9,13 +12,13 @@ import { let INSTANCE = 0; -function createRequest( +async function createRequest( base: string, id: string, instance: string, options: RequestInit, ) { - return fetch(base, { + const request = new Request(base, { method: "POST", ...options, headers: { @@ -24,6 +27,14 @@ function createRequest( "X-Server-Instance": instance, }, }); + if (import.meta.env.DEV) { + pushRequest(id, instance, request.clone()); + } + const response = await fetch(request); + if (import.meta.env.DEV) { + pushResponse(id, instance, response.clone()); + } + return response; } async function fetchServerFunction( base: string, @@ -54,7 +65,7 @@ async function fetchServerFunction( headers: { ...options.headers, "x-serialized": "true", - "Content-Type": "text/plain" + "Content-Type": "text/plain", }, })); @@ -82,7 +93,7 @@ async function fetchServerFunction( result = await clone.text(); } else if (contentType?.startsWith("application/json")) { result = await clone.json(); - } else if (response.headers.get('x-serialized')) { + } else if (response.headers.get("x-serialized")) { if (import.meta.env.SEROVAL_MODE === "js") { result = await deserializeJSStream(instance, clone); } else { diff --git a/packages/start/src/shared/ErrorBoundary.tsx b/packages/start/src/shared/ErrorBoundary.tsx index 6be12348e..d3dfb783a 100644 --- a/packages/start/src/shared/ErrorBoundary.tsx +++ b/packages/start/src/shared/ErrorBoundary.tsx @@ -1,40 +1,50 @@ // @refresh skip -import { ErrorBoundary as DefaultErrorBoundary, catchError, type ParentProps } from "solid-js"; +import { + catchError, + ErrorBoundary as DefaultErrorBoundary, + type ParentProps, +} from "solid-js"; import { isServer } from "solid-js/web"; -import { HttpStatusCode } from "./HttpStatusCode.ts"; import { DevOverlay } from "./dev-overlay/index.tsx"; +import { HttpStatusCode } from "./HttpStatusCode.ts"; +import { ServerFunctionInspector } from "./server-function-inspector/index.tsx"; export const ErrorBoundary = import.meta.env.DEV && import.meta.env.START_DEV_OVERLAY - ? (props: ParentProps) => {props.children} + ? (props: ParentProps) => ( + + + {props.children} + + ) : (props: ParentProps) => { - const message = isServer - ? "500 | Internal Server Error" - : "Error | Uncaught Client Exception"; - return ( - { - console.error(error); - return ( - <> - - {message} - - - - ); - }} - > - {props.children} - - ); - }; + const message = isServer + ? "500 | Internal Server Error" + : "Error | Uncaught Client Exception"; + return ( + { + console.error(error); + return ( + <> + + {message} + + + + ); + }} + > + {props.children} + + ); + }; export const TopErrorBoundary = (props: ParentProps) => { let isError = false; const res = catchError( () => props.children, - err => { + (err) => { console.error(err); isError = !!err; }, diff --git a/packages/start/src/shared/dev-overlay/DevOverlayDialog.tsx b/packages/start/src/shared/dev-overlay/DevOverlayDialog.tsx index e3b836d7a..2ff9a266d 100644 --- a/packages/start/src/shared/dev-overlay/DevOverlayDialog.tsx +++ b/packages/start/src/shared/dev-overlay/DevOverlayDialog.tsx @@ -2,11 +2,19 @@ import ErrorStackParser from "error-stack-parser"; import * as htmlToImage from "html-to-image"; import type { JSX } from "solid-js"; -import { ErrorBoundary, For, Show, Suspense, createMemo, createSignal } from "solid-js"; +import { + createMemo, + createSignal, + ErrorBoundary, + For, + Show, + Suspense, +} from "solid-js"; import { Portal } from "solid-js/web"; -// @ts-ignore - terracotta module resolution issue with NodeNext -import { Dialog, DialogOverlay, DialogPanel, Select, SelectOption } from "terracotta"; import info from "../../../package.json" with { type: "json" }; +import IconButton from "../ui/IconButton.tsx"; +import { Select, SelectOption } from "../ui/Select.tsx"; +import { Dialog, DialogOverlay, DialogPanel } from "../ui/Dialog.tsx"; import { CodeView } from "./CodeView.tsx"; import { createStackFrame, type StackFrameSource } from "./createStackFrame.ts"; import download from "./download.ts"; @@ -23,7 +31,9 @@ import { } from "./icons.tsx"; import "./styles.css"; -export function classNames(...classes: (string | boolean | undefined)[]): string { +export function classNames( + ...classes: (string | boolean | undefined)[] +): string { return classes.filter(Boolean).join(" "); } @@ -61,7 +71,9 @@ interface StackFramesContentProps { function getFileName(source: string): string { try { - const path = source.startsWith("/") ? new URL(source, "file://") : new URL(source); + const path = source.startsWith("/") + ? new URL(source, "file://") + : new URL(source); const paths = path.pathname.split("/"); return paths[paths.length - 1]!; } catch (error) { @@ -93,13 +105,18 @@ function StackFramesContent(props: StackFramesContentProps) {
{(() => { - const data = createStackFrame(selectedFrame(), () => props.isCompiled); + const data = createStackFrame( + selectedFrame(), + () => props.isCompiled, + ); return ( }> }> - {source => ( + {(source) => ( <> - {source.source} + + {source.source} +
- {current => ( + {(current) => ( + {current.functionName ?? ""} @@ -137,7 +158,7 @@ function StackFramesContent(props: StackFramesContentProps) { name: current.getFunctionName(), })} -
+ } > {(() => { @@ -145,12 +166,17 @@ function StackFramesContent(props: StackFramesContentProps) { return ( - {source => ( - + {(source) => ( + {source.name ?? ""} - {getFilePath(source)} + + {getFilePath(source)} + )} @@ -173,7 +199,9 @@ interface StackFramesProps { function StackFrames(props: StackFramesProps) { return ( - {current => } + {(current) => ( + + )} ); } @@ -186,7 +214,9 @@ interface DevOverlayDialogProps { const ISSUE_THREAD = "https://github.com/solidjs/solid-start/issues/new"; const DISCORD_INVITE = "https://discord.com/invite/solidjs"; -export default function DevOverlayDialog(props: DevOverlayDialogProps): JSX.Element { +export default function DevOverlayDialog( + props: DevOverlayDialogProps, +): JSX.Element { const [currentPage, setCurrentPage] = createSignal(1); const [isCompiled, setIsCompiled] = createSignal(false); const length = createMemo(() => props.errors.length); @@ -196,7 +226,7 @@ export default function DevOverlayDialog(props: DevOverlayDialogProps): JSX.Elem }); function goPrev() { - setCurrentPage(c => { + setCurrentPage((c) => { if (c > 1) { return c - 1; } @@ -205,7 +235,7 @@ export default function DevOverlayDialog(props: DevOverlayDialogProps): JSX.Elem } function goNext() { - setCurrentPage(c => { + setCurrentPage((c) => { if (c < length()) { return c + 1; } @@ -214,7 +244,7 @@ export default function DevOverlayDialog(props: DevOverlayDialogProps): JSX.Elem } function toggleIsCompiled() { - setIsCompiled(c => !c); + setIsCompiled((c) => !c); } const [panel, setPanel] = createSignal(); @@ -228,7 +258,7 @@ export default function DevOverlayDialog(props: DevOverlayDialogProps): JSX.Elem transform: "scale(0.75)", }, }) - .then(url => { + .then((url) => { download(url, "start-screenshot.png"); }); } @@ -239,7 +269,10 @@ export default function DevOverlayDialog(props: DevOverlayDialogProps): JSX.Elem url.searchParams.append("labels", "bug"); url.searchParams.append("labels", "needs+triage"); url.searchParams.append("template", "bug.yml"); - url.searchParams.append("title", `[Bug?]:` + props.errors[truncated() - 1].toString()); + url.searchParams.append( + "title", + `[Bug?]:` + props.errors[truncated() - 1].toString(), + ); window.open(url, "_blank")!.focus(); } @@ -249,10 +282,10 @@ export default function DevOverlayDialog(props: DevOverlayDialogProps): JSX.Elem return ( - +
- - + +
@@ -264,43 +297,45 @@ export default function DevOverlayDialog(props: DevOverlayDialogProps): JSX.Elem
1}>
- +
{`${truncated()} of ${props.errors.length}`}
- +
- - - - - +
- {current => ( + {(current) => (
diff --git a/packages/start/src/shared/dev-overlay/styles.css b/packages/start/src/shared/dev-overlay/styles.css index 24a0e416d..ffe2b18b7 100644 --- a/packages/start/src/shared/dev-overlay/styles.css +++ b/packages/start/src/shared/dev-overlay/styles.css @@ -1,28 +1,8 @@ -.dev-overlay { - position: fixed; - inset: 0px; - z-index: 50; - overflow-y: auto; -} - -.dev-overlay>div { - position: relative; - display: flex; - align-items: center; - justify-content: center; - min-height: 100vh; -} - -.dev-overlay-background { - position: absolute; - inset: 0px; - background-color: rgb(17 24 39 / 0.5); -} - .dev-overlay-panel { display: flex; flex-direction: column; width: 75vw; + max-height: 75vh; margin-top: 2rem; margin-bottom: 2rem; gap: 0.5rem; @@ -30,11 +10,6 @@ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; } -.dev-overlay-panel-container { - margin: 2rem; - z-index: 10; -} - .dev-overlay-navbar { display: flex; flex-direction: row; @@ -54,44 +29,6 @@ padding: 0.25rem; } -.dev-overlay-button { - display: flex; - padding: 0.125rem; - border-radius: 9999px; - border-width: 0px; - align-items: center; - justify-content: center; - background-color: rgb(249 250 251); - color: rgb(17 24 39); - transition-property: color, background-color, border-color, box-shadow; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} - -.dev-overlay-button:hover { - background-color: rgb(229 231 235); - color: rgb(55 65 81); -} - -.dev-overlay-button:focus { - outline: 2px solid transparent; - outline-offset: 2px -} - -.dev-overlay-button:focus-visible { - box-shadow: 0 0 0 calc(3px) rgb(17 24 39 / 0.75); -} - -.dev-overlay-button:active { - background-color: rgb(243 244 246); - color: rgb(31 41 55); -} - -.dev-overlay-button>svg { - height: 1.5rem; - width: 1.5rem; -} - .dev-overlay-page-counter { font-size: 0.875rem; line-height: 1.25rem; @@ -174,15 +111,8 @@ .dev-overlay-stack-frames { flex: 1 1 0%; - display: flex; - flex-direction: column; - margin: 0; - margin-block: 0; - list-style-type: none; - padding-inline: 0; max-height: 16rem; overflow-y: auto; - border-radius: 0.5rem; } .dev-overlay-stack-frame { @@ -191,23 +121,6 @@ align-items: center; justify-content: space-between; gap: 1rem; - color: rgb(17 24 39); - cursor: default; - user-select: none; - padding-top: 0.5rem; - padding-bottom: 0.5rem; - padding-left: 1rem; - padding-right: 1rem; - font-size: 0.875rem; - line-height: 1.25rem; - outline: none; -} - -.dev-overlay-stack-frame[tc-active], -.dev-overlay-stack-frame[tc-selected], -.dev-overlay-stack-frame:focus { - background-color: rgb(219 234 254); - color: rgb(30 58 138); } .dev-overlay-stack-frame-function { @@ -254,7 +167,7 @@ width: 100%; overflow: hidden; min-width: 100%; - min-height: 16rem; + max-height: 16rem; border-top-width: 1px; border-top-style: solid; border-top-color: rgb(249 250 251); @@ -263,7 +176,6 @@ .dev-overlay-code-view { overflow: auto; min-width: 100%; - min-height: 16rem; } .dev-overlay-code-view>.shiki { diff --git a/packages/start/src/shared/server-function-inspector/HeadersViewer.css b/packages/start/src/shared/server-function-inspector/HeadersViewer.css new file mode 100644 index 000000000..fbc235d92 --- /dev/null +++ b/packages/start/src/shared/server-function-inspector/HeadersViewer.css @@ -0,0 +1,12 @@ +[data-start-headers-viewer] { + font-size: 0.75rem; + line-height: 1rem; +} + +[data-start-header-key] { + white-space: nowrap; +} + +[data-start-header-value] { + white-space: nowrap; +} diff --git a/packages/start/src/shared/server-function-inspector/HeadersViewer.tsx b/packages/start/src/shared/server-function-inspector/HeadersViewer.tsx new file mode 100644 index 000000000..9465043c7 --- /dev/null +++ b/packages/start/src/shared/server-function-inspector/HeadersViewer.tsx @@ -0,0 +1,20 @@ +import { Properties } from "../ui/Properties.tsx"; +import { Text } from "../ui/Text.tsx"; + +import './HeadersViewer.css'; + +interface HeadersViewerProps { + headers: Headers; +} + +export function HeadersViewer(props: HeadersViewerProps) { + return ( +
+ {key}:} + renderValue = {(value) => {value}} + /> +
+ ); +} \ No newline at end of file diff --git a/packages/start/src/shared/server-function-inspector/SerovalViewer.css b/packages/start/src/shared/server-function-inspector/SerovalViewer.css new file mode 100644 index 000000000..4e7677090 --- /dev/null +++ b/packages/start/src/shared/server-function-inspector/SerovalViewer.css @@ -0,0 +1,86 @@ +[data-start-seroval-viewer] { + display: grid; + grid-template-columns: 1fr 2fr; + border: 1px oklch(70.7% 0.165 254.624) solid; + overflow: auto; + width: 100%; + max-height: 50vh; +} + +[data-start-seroval-value] { + display: flex; + gap: 0.25rem; + align-items: center; +} + +[data-start-seroval-promise] { + display: flex; + gap: 0.25rem; + align-items: center; +} + +[data-start-seroval-renderer] { + display: flex; +} + +[data-start-seroval-renderer] > * + * { + border-left: 1px oklch(70.7% 0.165 254.624) solid; +} + +[data-start-seroval-renderer]:last-child { + border-right: 1px oklch(70.7% 0.165 254.624) solid; +} + +[data-start-seroval-node] { + display: flex; + flex-direction: column; + gap: 0.25rem; + padding: 0.25rem; + + width: 100%; + max-width: 16rem; +} + +[data-start-seroval-node-header] { + position: sticky; + top: 0; + display: flex; + align-items: center; + justify-content: space-between; + background-color: rgb(249 250 251); +} + +[data-start-seroval-node-content] { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +[data-start-seroval-value] { + color: oklch(62.3% 0.214 259.815); +} + +[data-start-seroval-link] { + display: inline-flex; + gap: 0.25rem; + align-items: center; +} + +[data-start-seroval-link] > svg { + width: 1rem; + height: 1rem; +} + +[data-start-seroval-properties] { + display: flex; + flex-direction: column; + gap: 0.25rem; + margin: 0rem 0.25rem; +} + +[data-start-seroval-property] { + display: flex; + flex-direction: row; + align-items: center; + flex-wrap: nowrap; +} diff --git a/packages/start/src/shared/server-function-inspector/SerovalViewer.tsx b/packages/start/src/shared/server-function-inspector/SerovalViewer.tsx new file mode 100644 index 000000000..4d53d5dcc --- /dev/null +++ b/packages/start/src/shared/server-function-inspector/SerovalViewer.tsx @@ -0,0 +1,836 @@ +import type { SerovalNode } from "seroval"; +import { createEffect, createSignal, For, type JSX, Show, splitProps } from "solid-js"; +import { SerovalChunkReader } from "../../server/serialization.ts"; +import { Badge } from "../ui/Badge.tsx"; +import { Cascade, CascadeOption } from "../ui/Cascade.tsx"; +import { Section } from "../ui/Section.tsx"; +import { Text } from "../ui/Text.tsx"; +import './SerovalViewer.css'; + +function LinkIcon( + props: JSX.IntrinsicElements["svg"] & { title: string }, +): JSX.Element { + return ( + + {props.title} + + + ); +} + +export interface SerovalViewerProps { + stream: Request | Response; +} + +function getNodeType(node: SerovalNode) { + switch (node.t) { + // Number = 0, + case 0: return 'number'; + // String = 1, + case 1: return 'string'; + // Constant = 2, + case 2: + switch (node.s) { + case 0: return 'null'; + case 1: return 'undefined'; + case 2: return 'true'; + case 3: return 'false'; + case 4: return '-0'; + case 5: return 'Infinity'; + case 6: return '-Infinity'; + case 7: return 'NaN'; + } + break; + // BigInt = 3, + case 3: return 'bigint' + // Date = 5, + case 5: return 'Date'; + // RegExp = 6, + case 6: return 'RegExp'; + // Set = 7, + case 7: return 'Set'; + // Map = 8, + case 8: return 'Map'; + // Array = 9, + case 9: return 'Array'; + // Object = 10, + case 10: + // NullConstructor = 11, + case 11: return 'Object'; + // Promise = 12, + case 12: return 'Promise'; + // Error = 13, + case 13: + switch (node.s) { + case 0: return 'Error'; + case 1: return 'EvalError'; + case 2: return 'RangeError'; + case 3: return 'ReferenceError'; + case 4: return 'SyntaxError'; + case 5: return 'TypeError'; + case 6: return 'URIError'; + } + return 'Error'; + // AggregateError = 14, + case 14: return 'AggregateError'; + // TypedArray = 15, + case 15: + // BigIntTypedArray = 16, + case 16: return node.c; + // WKSymbol = 17, + case 17: return 'symbol'; + // ArrayBuffer = 19, + case 19: return 'ArrayBuffer' + // DataView = 20, + case 20: return 'DataView' + // Boxed = 21, + case 21: return 'Boxed'; + // PromiseConstructor = 22, + case 22: return 'Promise'; + // Plugin = 25, + case 25: + // due to the nature of this node, we have to traverse it ourselves + return 'Plugin'; + // IteratorFactoryInstance = 28, + case 28: return 'Iterator'; + // AsyncIteratorFactoryInstance = 30, + case 30: return 'AsyncIterator'; + // StreamConstructor = 31, + case 31: return 'Stream'; + } + throw new Error('unsupported node type'); +} + +function traverse( + node: SerovalNode, + handler: (node: SerovalNode) => void, +): void { + handler(node); + switch (node.t) { + // Number = 0, + case 0: + // String = 1, + case 1: + // Constant = 2, + case 2: + // BigInt = 3, + case 3: + // IndexedValue = 4, + case 4: + // Date = 5, + case 5: + // RegExp = 6, + case 6: + break; + // Set = 7, + case 7: + // Traverse items + for (const child of node.a) { + traverse(child, handler); + } + break; + // Map = 8, + case 8: + // Traverse keys + for (const key of node.e.k) { + traverse(key, handler); + } + for (const value of node.e.v) { + traverse(value, handler); + } + break; + // Array = 9, + case 9: + // Traverse items + for (const child of node.a) { + if (child) { + traverse(child, handler); + } + } + break; + // Object = 10, + case 10: + // NullConstructor = 11, + case 11: + for (const child of node.p.k) { + if (typeof child !== "string") { + traverse(child, handler); + } + } + for (const child of node.p.v) { + traverse(child, handler); + } + break; + // Promise = 12, + case 12: + traverse(node.f, handler); + break; + // Error = 13, + case 13: + // AggregateError = 14, + case 14: + if (node.p) { + for (const child of node.p.k) { + if (typeof child !== "string") { + traverse(child, handler); + } + } + for (const child of node.p.v) { + traverse(child, handler); + } + } + break; + // TypedArray = 15, + case 15: + // BigIntTypedArray = 16, + case 16: + traverse(node.f, handler); + break; + // WKSymbol = 17, + case 17: + // Reference = 18, + case 18: + break; + // ArrayBuffer = 19, + case 19: + // DataView = 20, + case 20: + // Boxed = 21, + case 21: + traverse(node.f, handler); + break; + // PromiseConstructor = 22, + case 22: + break; + // PromiseSuccess = 23, + case 23: + // PromiseFailure = 24, + case 24: + traverse(node.a[1], handler); + break; + // Plugin = 25, + case 25: + // due to the nature of this node, we have to traverse it ourselves + break; + // SpecialReference = 26, + case 26: + break; + // IteratorFactory = 27, + case 27: + traverse(node.f, handler); + break; + // IteratorFactoryInstance = 28, + case 28: + traverse(node.a[0], handler); + traverse(node.a[1], handler); + break + // AsyncIteratorFactory = 29, + case 29: + traverse(node.a[1], handler); + break; + // AsyncIteratorFactoryInstance = 30, + case 30: + traverse(node.a[0], handler); + traverse(node.a[1], handler); + break + // StreamConstructor = 31, + case 31: + // Traverse items + for (const child of node.a) { + traverse(child, handler); + } + break; + // StreamNext = 32, + case 32: + // StreamThrow = 33, + case 33: + // StreamReturn = 34 + case 34: + traverse(node.f, handler); + break; + } +} + +interface SerovalValueProps { + value: string | number | boolean | undefined | null; +} + +function SerovalValue(props: SerovalValueProps) { + return ( + + {`${props.value}`} + + ); +} + +function getConstantValue(value: number) { + switch (value) { + case 0: return 'null'; + case 1: return 'undefined'; + case 2: return 'true'; + case 3: return 'false'; + case 4: return '-0'; + case 5: return 'Infinity'; + case 6: return '-Infinity'; + case 7: return 'NaN'; + } + return ''; +} + +function getSymbolValue(value: number) { + switch (value) { + case 0: return 'Symbol.asyncIterator'; + case 1: return 'Symbol.hasInstance'; + case 2: return 'Symbol.isConcatSpreadable'; + case 3: return 'Symbol.iterator'; + case 4: return 'Symbol.match'; + case 5: return 'Symbol.matchAll'; + case 6: return 'Symbol.replace'; + case 7: return 'Symbol.search'; + case 8: return 'Symbol.species'; + case 9: return 'Symbol.toPrimitive'; + case 10: return 'Symbol.toStringTag'; + case 11: return 'Symbol.unscopables'; + } + return ''; +} + +function getObjectFlag(value: number) { + switch (value) { + case 1: return 'non-extensible'; + case 2: return 'sealed'; + case 3: return 'frozen'; + default: return 'none'; + } +} + +function zip(keys: Key[], values: Value[]): [key: Key, value: Value][] { + const zipped: [key: Key, value: Value][] = []; + + for (let i = 0, len = keys.length; i < len; i++) { + zipped[i] = [keys[i]!, values[i]!]; + } + + return zipped; +} + +interface RenderContext { + getNode: (index: number) => SerovalNode | undefined; + getPromise: (index: number) => Extract | undefined; + getStream: (index: number) => Extract[] | undefined; +} + +function getStreamKeyword(t: 32 | 33 | 34): string { + switch (t) { + case 32: return 'next'; + case 33: return 'throw'; + case 34: return 'return'; + } +} + +function PropertySeparator() { + return :; +} + +function renderSerovalNode( + ctx: RenderContext, + node: SerovalNode, + onSelect: (index: number | undefined) => void, + inner?: boolean, +): JSX.Element { + if (node.t >= 4 && (inner || node.t === 4) && node.i != null && !(node.t === 5 || node.t === 6 || node.t === 17)) { + const index = node.i; + const description = `id: ${index}`; + const lookup = ctx.getNode(index)!; + return ( + + + + + + ); + } + switch (node.t) { + // Number = 0, + case 0: + return + // String = 1, + case 1: + return + // Constant = 2, + case 2: + return + // BigInt = 3, + case 3: + return ( + <> + + + + ); + // Date = 5, + case 5: + return + // RegExp = 6, + case 6: + return + // Set = 7, + case 7: + return ( + <> +
+
+ + + +
+
+
+ data-start-seroval-properties defaultValue={undefined} onChange={onSelect}> + [index, node] as const)}> + {([key, value]) => ( +
+ + + {renderSerovalNode(ctx, value, onSelect, true)} +
+ )} +
+ +
+ + ); + // Map = 8, + case 8: + return ( + <> +
+
+ + + +
+
+
+ data-start-seroval-properties defaultValue={undefined} onChange={onSelect}> + + {([key, value]) => ( +
+ {renderSerovalNode(ctx, key, onSelect, true)} + + {renderSerovalNode(ctx, value, onSelect, true)} +
+ )} +
+ +
+ + ); + // Array = 9, + case 9: + return ( + <> +
+
+ + + +
+
+ + + +
+
+
+ data-start-seroval-properties defaultValue={undefined} onChange={onSelect}> + [index, node] as const)}> + {([key, value]) => ( +
+ + + { + value === 0 + ? + : renderSerovalNode(ctx, value, onSelect, true) + } +
+ )} +
+ +
+ + ); + // Object = 10, + case 10: + // NullConstructor = 11, + case 11: + return ( + <> +
+
+ + + +
+
+ + + +
+
+
+ data-start-seroval-properties defaultValue={undefined} onChange={onSelect}> + + {([key, value]) => ( +
+ {( + typeof key === 'string' + ? + : renderSerovalNode(ctx, key, onSelect, true) + )} + + {renderSerovalNode(ctx, value, onSelect, true)} +
+ )} +
+ +
+ + ); + // Promise = 12, + case 12: + return ( + data-start-seroval-properties defaultValue={undefined} onChange={onSelect}> + {renderSerovalNode(ctx, node.f, onSelect, true)} + + ); + // Error = 13, + case 13: + // AggregateError = 14, + case 14: + return ( + <> +
+
+ + + +
+
+ + {current => ( +
+ data-start-seroval-properties defaultValue={undefined} onChange={onSelect}> + + {([key, value]) => ( +
+ {typeof key === 'string' + ? + : renderSerovalNode(ctx, key, onSelect, true)} + + {renderSerovalNode(ctx, value, onSelect, true)} +
+ )} +
+ +
+ )} +
+ + ); + // TypedArray = 15, + case 15: + // BigIntTypedArray = 16, + case 16: + return ( + data-start-seroval-properties defaultValue={undefined} onChange={onSelect}> + {renderSerovalNode(ctx, node.f, onSelect, true)} + + ); + // WKSymbol = 17, + case 17: + return + // Reference = 18, + case 18: + break; + // ArrayBuffer = 19, + case 19: + return ; + // DataView = 20, + case 20: + return ( + <> +
+
+ + + +
+
+ + + +
+
+
+ data-start-seroval-properties defaultValue={undefined} onChange={onSelect}> + {renderSerovalNode(ctx, node.f, onSelect, true)} + +
+ + ); + // Boxed = 21, + case 21: + return ( + data-start-seroval-properties defaultValue={undefined} onChange={onSelect}> + {renderSerovalNode(ctx, node.f, onSelect, true)} + + ); + case 22: + return <> + {(() => { + const result = ctx.getPromise(node.s); + if (result) { + const status = result.t === 23 ? 'success' : 'failure' as const; + return ( + data-start-seroval-properties defaultValue={undefined} onChange={onSelect}> +
+ + + +
+ + + + {renderSerovalNode(ctx, result.a[1], onSelect, true)} + + + ); + } + return + })()} + ; + // Plugin = 25 + case 25: + // due to the nature of this node, we have to traverse it ourselves + break; + // IteratorFactory = 27, + case 27: + break; + // IteratorFactoryInstance = 28, + case 28: + return renderSerovalNode(ctx, node.a[1], onSelect, true); + // AsyncIteratorFactory = 29, + case 29: + break; + // AsyncIteratorFactoryInstance = 30, + case 30: + return renderSerovalNode(ctx, node.a[1], onSelect, true); + // StreamConstructor = 31, + case 31: + return ( + <> + {(() => { + const result = ctx.getStream(node.i) || []; + return ( + data-start-seroval-properties defaultValue={undefined} onChange={onSelect}> + + {(current) => ( +
+ + + {renderSerovalNode(ctx, current.f, onSelect, true)} +
+ )} +
+ + ); + })()} + + ); + } +} + +interface SerovalNodeRendererProps extends RenderContext { + node: SerovalNode; +} + +function SerovalNodeRenderer(props: SerovalNodeRendererProps): JSX.Element { + const [, rest] = splitProps(props, ['node']); + const [next, setNext] = createSignal() + + function onSelect(index: number | undefined) { + if (index == null) { + setNext(undefined); + } else { + setNext(props.getNode(index)); + } + } + + return ( + <> +
+
+ {props.node.i != null && ( + + )} + +
+
+ {renderSerovalNode(props, props.node, onSelect)} +
+
+ + {(current) => ( + + )} + + + ); +} + +interface SerovalRendererProps extends Omit { + node?: SerovalNode; +} + +function SerovalRenderer(props: SerovalRendererProps): JSX.Element { + const [, rest] = splitProps(props, ['node']); + return ( +
+ + {(current) => ( + + )} + +
+ ); +} + +function createSimpleStore>(initial: T) { + const [state, setState] = createSignal(initial); + + return { + get(): T { + return state(); + }, + read(key: K): T[K] { + return state()[key]; + }, + write(key: K, value: T[K]): void { + setState((current) => ({ + ...current, + [key]: value, + })); + }, + update(key: K, value: (current: T[K]) => T[K]): void { + setState((current) => ({ + ...current, + [key]: value(current[key]), + })); + } + } +} + +export function SerovalViewer(props: SerovalViewerProps): JSX.Element { + const [selected, setSelected] = createSignal(); + + const references = createSimpleStore | undefined>>({}); + const streams = createSimpleStore[] | undefined>>({}); + const promises = createSimpleStore | undefined>>({}); + + createEffect(async () => { + setSelected(undefined); + if (!props.stream.body) { + throw new Error("missing body"); + } + const reader = new SerovalChunkReader(props.stream.body); + const result = await reader.next(); + if (!result.done) { + function traverseNode(node: SerovalNode): void { + // Check for promises + switch (node.t) { + case 0: + case 1: + case 2: + case 3: + case 4: + break; + case 23: + case 24: + promises.write(node.i, node); + break; + case 32: + case 33: + case 34: + streams.update(node.i, (current) => { + if (current) { + return [...current, node]; + } + return [node]; + }); + break; + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 18: + case 19: + case 20: + case 21: + case 25: + case 26: + case 27: + case 29: + case 31: + references.write(node.i, node); + break; + case 28: { + break; + } + case 30: + break; + } + } + + function interpretChunk(chunk: string): SerovalNode { + const result = JSON.parse(chunk) as SerovalNode; + traverse(result, traverseNode); + return result; + } + + void reader.drain(interpretChunk); + const root = interpretChunk(result.value); + setSelected(root); + } + }); + + return ( +
+ references.read(index)} + getPromise={(index) => promises.read(index)} + getStream={(index) => streams.read(index)} + /> +
+ ); +} diff --git a/packages/start/src/shared/server-function-inspector/index.tsx b/packages/start/src/shared/server-function-inspector/index.tsx new file mode 100644 index 000000000..e3893f5c1 --- /dev/null +++ b/packages/start/src/shared/server-function-inspector/index.tsx @@ -0,0 +1,209 @@ +import { + createEffect, + createSignal, + For, + type JSX, + onCleanup, + Show, +} from "solid-js"; +import { createStore } from "solid-js/store"; +import { Portal } from "solid-js/web"; +import { Badge } from "../ui/Badge.tsx"; +import Button from "../ui/Button.tsx"; +import { Dialog, DialogOverlay, DialogPanel } from "../ui/Dialog.tsx"; +import { Select, SelectOption } from "../ui/Select.tsx"; +import { Tab, TabGroup, TabList, TabPanel } from "../ui/Tabs.tsx"; +import { HeadersViewer } from "./HeadersViewer.tsx"; +import { SerovalViewer } from "./SerovalViewer.tsx"; +import { + captureServerFunctionCall, + type ServerFunctionRequest, + type ServerFunctionResponse, +} from "./server-function-tracker.ts"; +import "./styles.css"; +import { Section } from "../ui/Section.tsx"; + +interface ContentViewerProps { + source: ServerFunctionRequest | ServerFunctionResponse; +} + +function ContentViewer(props: ContentViewerProps): JSX.Element { + return ( + <> +
+ +
+
+ {(() => { + if (props.source.source.headers.has('x-serialized')) { + return + } + })()} +
+ + ); +} + +interface RequestViewerProps { + request: ServerFunctionRequest; +} + +function RequestViewer(props: RequestViewerProps): JSX.Element { + return ( + + + + ); +} + +interface ResponseViewerProps { + response?: ServerFunctionResponse; +} + +function ResponseViewer(props: ResponseViewerProps): JSX.Element { + return ( + + + {(instance) => ( + + )} + + + ); +} + +interface ServerFunctionInstance { + request: ServerFunctionRequest; + response?: ServerFunctionResponse; +} + +interface ServerFunctionInstanceViewerProps { + instance: ServerFunctionInstance; + onDelete: () => void; +} + +function ServerFunctionInstanceViewer( + props: ServerFunctionInstanceViewerProps, +): JSX.Element { + const [tab, setTab] = createSignal<"request" | "response">("request"); + return ( + setTab(value ?? "request")} + > +
+ + Request + Response + +
+ +
+
+ + +
+ ); +} + +export function ServerFunctionInspector(): JSX.Element { + const [currentInstance, setCurrentInstance] = createSignal(); + + const [store, setStore] = createStore({ + instances: {} as Record, + }); + + createEffect(() => { + onCleanup( + captureServerFunctionCall((call) => { + if (call.type === "request") { + setStore("instances", call.instance, { + request: call, + }); + } else { + setStore("instances", call.instance, "response", call); + } + }), + ); + }); + + const [isOpen, setIsOpen] = createSignal(false); + + createEffect(() => { + (window as any).__START__SERVER_FN__ = setIsOpen; + }); + + return ( + + +
+ + +
+ {/* list of calls */} +
+ +
+ {/* request/response viewer */} + + {(value) => ( + + {(instance) => ( + { + setStore("instances", value(), undefined); + }} + /> + )} + + )} + +
+
+
+
+
+ ); +} diff --git a/packages/start/src/shared/server-function-inspector/server-function-tracker.ts b/packages/start/src/shared/server-function-inspector/server-function-tracker.ts new file mode 100644 index 000000000..2fd56f264 --- /dev/null +++ b/packages/start/src/shared/server-function-inspector/server-function-tracker.ts @@ -0,0 +1,61 @@ +export type ServerFunctionRequest = { + type: "request"; + id: string; + instance: string; + source: Request; + time: number; +}; +export type ServerFunctionResponse = { + type: "response"; + id: string; + instance: string; + source: Response; + time: number; +}; + +export type ServerFunctionCall = ServerFunctionRequest | ServerFunctionResponse; + +export type ServerFunctionCallListener = (event: ServerFunctionCall) => void; + +const LISTENERS = new Set(); + +export function captureServerFunctionCall( + listener: ServerFunctionCallListener, +): () => void { + LISTENERS.add(listener); + return () => LISTENERS.delete(listener); +} + +export function pushRequest( + id: string, + instance: string, + source: Request, +): void { + const event: ServerFunctionCall = { + type: "request", + id, + instance, + source, + time: performance.now(), + }; + for (const listener of new Set(LISTENERS)) { + listener(event); + } +} + +export function pushResponse( + id: string, + instance: string, + source: Response, +): void { + const event: ServerFunctionCall = { + type: "response", + id, + instance, + source, + time: performance.now(), + }; + for (const listener of new Set(LISTENERS)) { + listener(event); + } +} diff --git a/packages/start/src/shared/server-function-inspector/styles.css b/packages/start/src/shared/server-function-inspector/styles.css new file mode 100644 index 000000000..437a0c4e7 --- /dev/null +++ b/packages/start/src/shared/server-function-inspector/styles.css @@ -0,0 +1,75 @@ + + +.server-function-instance-detail { + display: flex; + align-items: center; + gap: 0.25rem; +} + + +.server-function-inspector { + display: grid; + grid-template-columns: 1fr 2fr; + width: 75vw; + height: 75vh; + margin-top: 2rem; + margin-bottom: 2rem; + gap: 0.5rem; + color: rgb(17 24 39); +} + +.server-function-instances-container { + border-radius: 0.5rem; + background-color: rgb(249 250 251); + overflow: auto; +} + + +.server-function-instances { + list-style: none; + display: flex; + flex-direction: column; + padding: 0px; +} + +.server-function-instances > [data-start-select-option] { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0.25rem; +} + +.server-function-instance-viewer { + display: flex; + flex-direction: column; + gap: 0.25rem; + height: 100%; + overflow: hidden; +} + +.server-function-instance-viewer-toolbar { + display: flex; + align-items: center; + justify-content: space-between; +} + +.server-function-instance-tab-panel { + overflow: auto; +} + +[data-start-headers] { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +[data-start-headers-title] { + font-weight: 500; +} + +.server-function-instance-tab-panel { + display: flex; + flex-direction: column; + gap: 1rem; +} + diff --git a/packages/start/src/shared/ui/Badge.css b/packages/start/src/shared/ui/Badge.css new file mode 100644 index 000000000..1a2276f9f --- /dev/null +++ b/packages/start/src/shared/ui/Badge.css @@ -0,0 +1,33 @@ +[data-start-badge] { + display: inline-flex; + align-items: center; + justify-content: center; + + border-radius: 0.375rem; + padding: 0.125rem 0.25rem; + + background-color: var(--background); + border: 1px var(--foreground) solid; + color: var(--foreground); +} + +[data-start-badge="success"] { + --background: oklch(98.2% 0.018 155.826); + --foreground: oklch(52.7% 0.154 150.069); +} + +[data-start-badge="failure"] { + --background: oklch(97.1% 0.013 17.38); + --foreground: oklch(50.5% 0.213 27.518); +} + +[data-start-badge="warning"] { + --background: oklch(98.7% 0.026 102.212); + --foreground: oklch(47.6% 0.114 61.907); +} + + +[data-start-badge="info"] { + --background: oklch(97% 0.014 254.604); + --foreground: oklch(48.8% 0.243 264.376); +} diff --git a/packages/start/src/shared/ui/Badge.tsx b/packages/start/src/shared/ui/Badge.tsx new file mode 100644 index 000000000..3b3513c94 --- /dev/null +++ b/packages/start/src/shared/ui/Badge.tsx @@ -0,0 +1,17 @@ +import type { JSX } from 'solid-js'; +import './Badge.css'; +import { Text } from './Text.tsx'; + + +export interface BadgeProps { + value: string | number; + type: 'info' | 'success' | 'failure' | 'warning'; +} + +export function Badge(props: BadgeProps): JSX.Element { + return ( + + {props.value} + + ); +} diff --git a/packages/start/src/shared/ui/Button.css b/packages/start/src/shared/ui/Button.css new file mode 100644 index 000000000..985ae4972 --- /dev/null +++ b/packages/start/src/shared/ui/Button.css @@ -0,0 +1,35 @@ +[data-start-button] { + display: flex; + align-items: center; + justify-content: center; + + cursor: pointer; + + border-radius: 0.5rem; + + background-color: oklch(97% 0.014 254.604); + + color: rgb(17 24 39); + padding-top: 0.5rem; + padding-bottom: 0.5rem; + padding-left: 1rem; + padding-right: 1rem; + font-size: 0.875rem; + line-height: 1.25rem; + border: none; + outline: none; + + transition-property: color, background-color, border-color, box-shadow; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; + + white-space: nowrap; +} + +[data-start-button][tc-active], +[data-start-button][tc-selected], +[data-start-button]:hover, +[data-start-button]:focus { + background-color: rgb(219 234 254); + color: rgb(30 58 138); +} diff --git a/packages/start/src/shared/ui/Button.tsx b/packages/start/src/shared/ui/Button.tsx new file mode 100644 index 000000000..a32756439 --- /dev/null +++ b/packages/start/src/shared/ui/Button.tsx @@ -0,0 +1,8 @@ +import { Button as BaseButton } from "terracotta"; +import "./Button.css"; + +const Button: typeof BaseButton = (props) => ( + +); + +export default Button; diff --git a/packages/start/src/shared/ui/Cascade.css b/packages/start/src/shared/ui/Cascade.css new file mode 100644 index 000000000..dbda77829 --- /dev/null +++ b/packages/start/src/shared/ui/Cascade.css @@ -0,0 +1,30 @@ +[data-start-cascade] { + display: flex; + flex-direction: column; + margin: 0; + margin-block: 0; + list-style-type: none; + padding-inline: 0; +} + +[data-start-cascade-option] { + color: rgb(17 24 39); + border-radius: 0.25rem; + font-size: 0.875rem; + line-height: 1.25rem; + outline: none; + cursor: pointer; + + transition-property: color, background-color, border-color, box-shadow; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; + + white-space: nowrap; +} + +[data-start-cascade-option][tc-active], +[data-start-cascade-option][tc-selected], +[data-start-cascade-option]:focus { + background-color: rgb(219 234 254); + color: rgb(30 58 138); +} diff --git a/packages/start/src/shared/ui/Cascade.tsx b/packages/start/src/shared/ui/Cascade.tsx new file mode 100644 index 000000000..459b2af25 --- /dev/null +++ b/packages/start/src/shared/ui/Cascade.tsx @@ -0,0 +1,13 @@ +import { + Select as BaseSelect, + SelectOption as BaseSelectOption, +} from "terracotta"; + +import "./Cascade.css"; + +export const Cascade: typeof BaseSelect = (props) => ( + +); +export const CascadeOption: typeof BaseSelectOption = (props) => ( + +); diff --git a/packages/start/src/shared/ui/Dialog.css b/packages/start/src/shared/ui/Dialog.css new file mode 100644 index 000000000..198f22735 --- /dev/null +++ b/packages/start/src/shared/ui/Dialog.css @@ -0,0 +1,26 @@ +[data-start-dialog] { + position: fixed; + inset: 0px; + z-index: 50; + overflow-y: auto; +} + + +[data-start-dialog]>div { + position: relative; + display: flex; + align-items: center; + justify-content: center; + min-height: 100vh; +} + +[data-start-dialog-overlay] { + position: absolute; + inset: 0px; + background-color: rgb(17 24 39 / 0.5); +} + +[data-start-dialog-panel] { + margin: 2rem; + z-index: 10; +} diff --git a/packages/start/src/shared/ui/Dialog.tsx b/packages/start/src/shared/ui/Dialog.tsx new file mode 100644 index 000000000..1e765a05b --- /dev/null +++ b/packages/start/src/shared/ui/Dialog.tsx @@ -0,0 +1,17 @@ +import { + Dialog as BaseDialog, + DialogOverlay as BaseDialogOverlay, + DialogPanel as BaseDialogPanel, +} from "terracotta"; + +import "./Dialog.css"; + +export const Dialog: typeof BaseDialog = (props) => ( + +); +export const DialogOverlay: typeof BaseDialogOverlay = (props) => ( + +); +export const DialogPanel: typeof BaseDialogPanel = (props) => ( + +); diff --git a/packages/start/src/shared/ui/IconButton.css b/packages/start/src/shared/ui/IconButton.css new file mode 100644 index 000000000..3582bbaec --- /dev/null +++ b/packages/start/src/shared/ui/IconButton.css @@ -0,0 +1,39 @@ +[data-start-icon-button] { + display: flex; + padding: 0.125rem; + border-radius: 9999px; + border-width: 0px; + align-items: center; + justify-content: center; + cursor: pointer; + background-color: rgb(249 250 251); + color: rgb(17 24 39); + transition-property: color, background-color, border-color, box-shadow; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + + +[data-start-icon-button]:hover { + background-color: rgb(229 231 235); + color: rgb(55 65 81); +} + +[data-start-icon-button]:focus { + outline: 2px solid transparent; + outline-offset: 2px +} + +[data-start-icon-button]:focus-visible { + box-shadow: 0 0 0 calc(3px) rgb(17 24 39 / 0.75); +} + +[data-start-icon-button]:active { + background-color: rgb(243 244 246); + color: rgb(31 41 55); +} + +[data-start-icon-button]>svg { + height: 1.5rem; + width: 1.5rem; +} diff --git a/packages/start/src/shared/ui/IconButton.tsx b/packages/start/src/shared/ui/IconButton.tsx new file mode 100644 index 000000000..57417f601 --- /dev/null +++ b/packages/start/src/shared/ui/IconButton.tsx @@ -0,0 +1,8 @@ +import { Button as BaseButton } from "terracotta"; +import "./IconButton.css"; + +const IconButton: typeof BaseButton = (props) => ( + +); + +export default IconButton; diff --git a/packages/start/src/shared/ui/Properties.css b/packages/start/src/shared/ui/Properties.css new file mode 100644 index 000000000..5cb7343fc --- /dev/null +++ b/packages/start/src/shared/ui/Properties.css @@ -0,0 +1,15 @@ +[data-start-properties] { + display: flex; + flex-direction: column; + gap: 0.25rem; + + overflow: auto; +} + +[data-start-property] { + display: flex; + flex-direction: row; + gap: 0.25rem; + + align-items: center; +} diff --git a/packages/start/src/shared/ui/Properties.tsx b/packages/start/src/shared/ui/Properties.tsx new file mode 100644 index 000000000..7127f2a69 --- /dev/null +++ b/packages/start/src/shared/ui/Properties.tsx @@ -0,0 +1,29 @@ +import { For, type JSX } from 'solid-js'; + +import './Properties.css'; + +export type PropertyEntry = [key: unknown, value: unknown]; + +export interface PropertiesProps { + entries: T[]; + + renderKey: (key: T[0]) => JSX.Element; + renderValue: (value: T[1]) => JSX.Element; +} + +export function Properties( + props: PropertiesProps, +): JSX.Element { + return ( +
+ + {(entry) => ( +
+ {props.renderKey(entry[0])} + {props.renderValue(entry[1])} +
+ )} +
+
+ ); +} diff --git a/packages/start/src/shared/ui/Section.css b/packages/start/src/shared/ui/Section.css new file mode 100644 index 000000000..f32df90c6 --- /dev/null +++ b/packages/start/src/shared/ui/Section.css @@ -0,0 +1,16 @@ +[data-start-section] { + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +[data-start-section-title] { + +} + + +[data-start-section-content] { + width: 100%; + + overflow: auto; +} diff --git a/packages/start/src/shared/ui/Section.tsx b/packages/start/src/shared/ui/Section.tsx new file mode 100644 index 000000000..3c532132f --- /dev/null +++ b/packages/start/src/shared/ui/Section.tsx @@ -0,0 +1,23 @@ +import type { JSX } from "solid-js"; +import { Text, type TextProps } from "./Text.tsx"; + +import './Section.css'; + +export interface SectionProps { + title: string; + options?: TextProps<'span'>['options']; + children: JSX.Element; +} + +export function Section(props: SectionProps): JSX.Element { + return ( +
+ + {props.title} + +
+ {props.children} +
+
+ ); +} diff --git a/packages/start/src/shared/ui/Select.css b/packages/start/src/shared/ui/Select.css new file mode 100644 index 000000000..bc95e9770 --- /dev/null +++ b/packages/start/src/shared/ui/Select.css @@ -0,0 +1,38 @@ + +[data-start-select] { + display: flex; + flex-direction: column; + margin: 0; + margin-block: 0; + list-style-type: none; + padding-inline: 0; +} + +[data-start-select] > * + * { + border-top: 1px oklch(70.7% 0.165 254.624) solid; +} + +[data-start-select-option] { + color: rgb(17 24 39); + padding-top: 0.5rem; + padding-bottom: 0.5rem; + padding-left: 1rem; + padding-right: 1rem; + font-size: 0.875rem; + line-height: 1.25rem; + outline: none; + cursor: pointer; + + transition-property: color, background-color, border-color, box-shadow; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; + + white-space: nowrap; +} + +[data-start-select-option][tc-active], +[data-start-select-option][tc-selected], +[data-start-select-option]:focus { + background-color: rgb(219 234 254); + color: rgb(30 58 138); +} diff --git a/packages/start/src/shared/ui/Select.tsx b/packages/start/src/shared/ui/Select.tsx new file mode 100644 index 000000000..2d648832a --- /dev/null +++ b/packages/start/src/shared/ui/Select.tsx @@ -0,0 +1,13 @@ +import { + Select as BaseSelect, + SelectOption as BaseSelectOption, +} from "terracotta"; + +import "./Select.css"; + +export const Select: typeof BaseSelect = (props) => ( + +); +export const SelectOption: typeof BaseSelectOption = (props) => ( + +); diff --git a/packages/start/src/shared/ui/Table.css b/packages/start/src/shared/ui/Table.css new file mode 100644 index 000000000..bf1ed368f --- /dev/null +++ b/packages/start/src/shared/ui/Table.css @@ -0,0 +1,22 @@ +[data-start-table] { + border: 1px oklch(70.7% 0.165 254.624) solid; +} + +[data-start-table-header] { + display: flex; + flex-direction: row; + background-color: oklch(93.2% 0.032 255.585); + font-weight: 600; +} + +[data-start-table-row] { + display: flex; + flex-direction: row; + border-top: 1px oklch(70.7% 0.165 254.624) solid; +} + +[data-start-table-cell] { + flex: 1; + padding: 0.25rem 0.75rem; + overflow: auto; +} diff --git a/packages/start/src/shared/ui/Table.tsx b/packages/start/src/shared/ui/Table.tsx new file mode 100644 index 000000000..87eeb18f0 --- /dev/null +++ b/packages/start/src/shared/ui/Table.tsx @@ -0,0 +1,35 @@ +import type { ComponentProps, JSX } from 'solid-js'; + +import './Table.css'; + +type TableProps = ComponentProps<'div'>; + +export function Table(props: TableProps): JSX.Element { + return ( +
+ ); +} + +type TableHeaderProps = ComponentProps<'div'>; + +export function TableHeader(props: TableHeaderProps): JSX.Element { + return ( +
+ ); +} + +type TableRowProps = ComponentProps<'div'>; + +export function TableRow(props: TableRowProps): JSX.Element { + return ( +
+ ); +} + +type TableCellProps = ComponentProps<'div'>; + +export function TableCell(props: TableCellProps): JSX.Element { + return ( +
+ ); +} diff --git a/packages/start/src/shared/ui/Tabs.css b/packages/start/src/shared/ui/Tabs.css new file mode 100644 index 000000000..c7ac400fe --- /dev/null +++ b/packages/start/src/shared/ui/Tabs.css @@ -0,0 +1,48 @@ +[data-start-tab] { + display: flex; + align-items: center; + justify-content: center; + + border-radius: 0.5rem; + cursor: pointer; + + color: rgb(17 24 39); + padding-top: 0.5rem; + padding-bottom: 0.5rem; + padding-left: 1rem; + padding-right: 1rem; + font-size: 0.875rem; + line-height: 1.25rem; + border: none; + outline: none; + + transition-property: color, background-color, border-color, box-shadow; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +[data-start-tab][tc-active], +[data-start-tab][tc-selected], +[data-start-tab]:hover, +[data-start-tab]:focus { + background-color: rgb(219 234 254); + color: rgb(30 58 138); +} + +[data-start-tab-group] { +} + +[data-start-tab-list] { + display: flex; + gap: 0.25rem; + padding: 0.25rem; + background-color: rgb(249 250 251); + border-radius: 0.5rem; +} + +[data-start-tab-panel] { + padding: 0.5rem; + background-color: rgb(249 250 251); + border-radius: 0.5rem; + height: 100%; +} diff --git a/packages/start/src/shared/ui/Tabs.tsx b/packages/start/src/shared/ui/Tabs.tsx new file mode 100644 index 000000000..1ef39f24e --- /dev/null +++ b/packages/start/src/shared/ui/Tabs.tsx @@ -0,0 +1,22 @@ +import { + Tab as BaseTab, + TabGroup as BaseTabGroup, + TabList as BaseTabList, + TabPanel as BaseTabPanel, +} from "terracotta"; + +import "./Tabs.css"; + +export const Tab: typeof BaseTab = (props) => ( + +); +export const TabGroup: typeof BaseTabGroup = (props) => ( + +); +export const TabPanel: typeof BaseTabPanel = (props) => ( + +); +export const TabList: typeof BaseTabList = (props) => ( + +); + diff --git a/packages/start/src/shared/ui/Text.css b/packages/start/src/shared/ui/Text.css new file mode 100644 index 000000000..a67b817da --- /dev/null +++ b/packages/start/src/shared/ui/Text.css @@ -0,0 +1,69 @@ +[data-start-text-size="xs"] { + font-size: 0.75rem; + line-height: calc(1 / 0.75); +} +[data-start-text-size="sm"] { + font-size: 0.875rem; + line-height: calc(1.25 / 0.875); +} +[data-start-text-size="base"] { + font-size: 1rem; + line-height: 1.5; +} +[data-start-text-size="lg"] { + font-size: 1.125rem; + line-height: calc(1.75 / 1.125); +} +[data-start-text-size="xl"] { + font-size: 1.25rem; + line-height: calc(1.75 / 1.25); +} +[data-start-text-size="2xl"] { + font-size: 1.5rem; + line-height: calc(2 / 1.5); +} + +[data-start-text-font="sans"] { + font-family: system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; +} +[data-start-text-font="serif"] { + font-family: ui-serif, Georgia, Cambria, 'Times New Roman', Times, serif; +} +[data-start-text-font="mono"] { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; +} + +[data-start-text-weight="thin"] { + font-weight: 100; +} +[data-start-text-weight="extralight"] { + font-weight: 200; +} +[data-start-text-weight="light"] { + font-weight: 300; +} +[data-start-text-weight="normal"] { + font-weight: 400; +} +[data-start-text-weight="medium"] { + font-weight: 500; +} +[data-start-text-weight="semibold"] { + font-weight: 600; +} +[data-start-text-weight="bold"] { + font-weight: 700; +} +[data-start-text-weight="extrabold"] { + font-weight: 800; +} +[data-start-text-weight="black"] { + font-weight: 900; +} + +[data-start-text-wrap="wrap"] { + white-space: wrap; +} +[data-start-text-wrap="nowrap"] { + white-space: nowrap; +} diff --git a/packages/start/src/shared/ui/Text.tsx b/packages/start/src/shared/ui/Text.tsx new file mode 100644 index 000000000..44bad1b2d --- /dev/null +++ b/packages/start/src/shared/ui/Text.tsx @@ -0,0 +1,37 @@ +import { type ComponentProps, createMemo, type JSX, splitProps } from 'solid-js'; +import { Dynamic } from 'solid-js/web'; + +import './Text.css'; + +export type TextProps = ComponentProps & { + options?: { + as?: T; + size?: 'xs' | 'sm' | 'base' | 'lg' | 'xl' | '2xl'; + font?: 'sans' | 'serif' | 'mono'; + weight?: 'thin' | 'extralight' | 'light' | 'normal' | 'medium' | 'semibold' | 'bold' | 'extrabold'; + wrap?: 'wrap' | 'nowrap'; + }; +}; + +export function Text(props: TextProps): JSX.Element { + const [current, rest] = splitProps(props, ['options']); + + const customization = createMemo>(() => { + const options = Object.assign({}, { + size: 'base', + font: 'mono', + weight: 'normal', + wrap: 'wrap', + }, current.options); + const entries = Object.entries(options); + return Object.fromEntries(entries.map(([key, value]) => [`data-start-text-${key}`, value])) as TextProps; + }); + + return ( + + ); +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 25d67e8e2..8023c711c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,7 +15,7 @@ importers: devDependencies: '@changesets/cli': specifier: ^2.29.8 - version: 2.29.8(@types/node@25.0.1) + version: 2.29.8(@types/node@25.0.3) citty: specifier: ^0.1.5 version: 0.1.6 @@ -42,7 +42,7 @@ importers: version: 1.9.9 vite: specifier: 7.1.10 - version: 7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) + version: 7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) apps/fixtures/basic: dependencies: @@ -60,7 +60,7 @@ importers: version: 1.9.9 vite: specifier: 7.1.10 - version: 7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) + version: 7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) apps/fixtures/css: dependencies: @@ -78,11 +78,11 @@ importers: version: 1.9.9 vite: specifier: 7.1.10 - version: 7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) + version: 7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) devDependencies: '@tailwindcss/vite': specifier: ^4.1.12 - version: 4.1.17(vite@7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)) + version: 4.1.17(vite@7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)) tailwindcss: specifier: ^4.1.12 version: 4.1.17 @@ -103,7 +103,7 @@ importers: version: 1.9.9 vite: specifier: 7.1.10 - version: 7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) + version: 7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) apps/fixtures/hackernews: dependencies: @@ -115,13 +115,13 @@ importers: version: link:../../../packages/start nitro: specifier: 3.0.1-alpha.0 - version: 3.0.1-alpha.0(@netlify/blobs@10.4.1)(better-sqlite3@11.8.1)(chokidar@4.0.3)(drizzle-orm@0.31.4(@opentelemetry/api@1.9.0)(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.12)(better-sqlite3@11.8.1)(prisma@5.22.0))(ioredis@5.6.1)(vite@7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)) + version: 3.0.1-alpha.0(@netlify/blobs@10.4.1)(better-sqlite3@11.8.1)(chokidar@4.0.3)(drizzle-orm@0.31.4(@opentelemetry/api@1.9.0)(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.12)(better-sqlite3@11.8.1)(prisma@5.22.0))(ioredis@5.6.1)(vite@7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)) solid-js: specifier: ^1.9.9 version: 1.9.9 vite: specifier: 7.1.10 - version: 7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) + version: 7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) apps/fixtures/nitro-3: dependencies: @@ -136,13 +136,13 @@ importers: version: link:../../../packages/start nitro: specifier: ^3.0.1-alpha.1 - version: 3.0.1-alpha.1(@netlify/blobs@10.4.1)(better-sqlite3@11.8.1)(chokidar@4.0.3)(drizzle-orm@0.31.4(@opentelemetry/api@1.9.0)(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.12)(better-sqlite3@11.8.1)(prisma@5.22.0))(ioredis@5.6.1)(rollup@4.52.5)(vite@7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)) + version: 3.0.1-alpha.1(@netlify/blobs@10.4.1)(better-sqlite3@11.8.1)(chokidar@4.0.3)(drizzle-orm@0.31.4(@opentelemetry/api@1.9.0)(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.12)(better-sqlite3@11.8.1)(prisma@5.22.0))(ioredis@5.6.1)(rollup@4.52.5)(vite@7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)) solid-js: specifier: ^1.9.9 version: 1.9.9 vite: specifier: 7.1.10 - version: 7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) + version: 7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) apps/fixtures/notes: dependencies: @@ -166,7 +166,7 @@ importers: version: 1.10.2(ioredis@5.6.1) vite: specifier: 7.1.10 - version: 7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) + version: 7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) apps/fixtures/todomvc: dependencies: @@ -178,7 +178,7 @@ importers: version: link:../../../packages/start nitro: specifier: 3.0.1-alpha.0 - version: 3.0.1-alpha.0(@netlify/blobs@10.4.1)(better-sqlite3@11.8.1)(chokidar@4.0.3)(drizzle-orm@0.31.4(@opentelemetry/api@1.9.0)(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.12)(better-sqlite3@11.8.1)(prisma@5.22.0))(ioredis@5.6.1)(vite@7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)) + version: 3.0.1-alpha.0(@netlify/blobs@10.4.1)(better-sqlite3@11.8.1)(chokidar@4.0.3)(drizzle-orm@0.31.4(@opentelemetry/api@1.9.0)(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.12)(better-sqlite3@11.8.1)(prisma@5.22.0))(ioredis@5.6.1)(vite@7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)) solid-js: specifier: ^1.9.9 version: 1.9.9 @@ -187,7 +187,7 @@ importers: version: 1.10.2(ioredis@5.6.1) vite: specifier: 7.1.10 - version: 7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) + version: 7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) apps/landing-page: dependencies: @@ -248,7 +248,7 @@ importers: version: 6.3.7 vite: specifier: ^7.1.10 - version: 7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) + version: 7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) apps/tests: dependencies: @@ -284,13 +284,13 @@ importers: version: 1.9.9 vite: specifier: ^7.1.10 - version: 7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) + version: 7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) vite-plugin-solid: specifier: ^2.11.9 - version: 2.11.9(patch_hash=71233f1afab9e3ea2dbb03dbda3d84894ef1c6bfbbe69df9f864d03bfe67b6f5)(@testing-library/jest-dom@6.6.2)(solid-js@1.9.9)(vite@7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)) + version: 2.11.9(patch_hash=71233f1afab9e3ea2dbb03dbda3d84894ef1c6bfbbe69df9f864d03bfe67b6f5)(@testing-library/jest-dom@6.6.2)(solid-js@1.9.9)(vite@7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)) vitest: specifier: ^4.0.10 - version: 4.0.10(@types/debug@4.1.12)(@types/node@25.0.1)(@vitest/browser-playwright@4.0.10)(@vitest/ui@4.0.10)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.30.2)(msw@2.7.0(@types/node@25.0.1)(typescript@5.7.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) + version: 4.0.10(@types/debug@4.1.12)(@types/node@25.0.3)(@vitest/browser-playwright@4.0.10)(@vitest/ui@4.0.10)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.30.2)(msw@2.7.0(@types/node@25.0.3)(typescript@5.7.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) devDependencies: '@playwright/test': specifier: ^1.56.1 @@ -300,10 +300,10 @@ importers: version: 4.17.14 '@vitest/browser': specifier: ^4.0.10 - version: 4.0.10(msw@2.7.0(@types/node@25.0.1)(typescript@5.7.3))(vite@7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))(vitest@4.0.10) + version: 4.0.10(msw@2.7.0(@types/node@25.0.3)(typescript@5.7.3))(vite@7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))(vitest@4.0.10) '@vitest/browser-playwright': specifier: ^4.0.10 - version: 4.0.10(msw@2.7.0(@types/node@25.0.1)(typescript@5.7.3))(playwright@1.56.1)(vite@7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))(vitest@4.0.10) + version: 4.0.10(msw@2.7.0(@types/node@25.0.3)(typescript@5.7.3))(playwright@1.56.1)(vite@7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))(vitest@4.0.10) playwright: specifier: ^1.56.1 version: 1.56.1 @@ -324,7 +324,7 @@ importers: version: 0.29.4(solid-js@1.9.9) '@tanstack/server-functions-plugin': specifier: 1.134.5 - version: 1.134.5(vite@7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)) + version: 1.134.5(vite@7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)) '@types/babel__traverse': specifier: ^7.28.0 version: 7.28.0 @@ -368,11 +368,11 @@ importers: specifier: ^1.1.2 version: 1.1.2 seroval: - specifier: ^1.4.1 - version: 1.4.1 + specifier: ^1.4.2 + version: 1.4.2 seroval-plugins: specifier: ^1.4.0 - version: 1.4.0(seroval@1.4.1) + version: 1.4.0(seroval@1.4.2) shiki: specifier: ^1.26.1 version: 1.26.1 @@ -386,21 +386,21 @@ importers: specifier: ^0.9.1 version: 0.9.6 terracotta: - specifier: ^1.0.6 - version: 1.0.6(solid-js@1.9.9) + specifier: ^1.1.0 + version: 1.1.0(solid-js@1.9.9) vite-plugin-solid: specifier: ^2.11.9 - version: 2.11.9(patch_hash=71233f1afab9e3ea2dbb03dbda3d84894ef1c6bfbbe69df9f864d03bfe67b6f5)(@testing-library/jest-dom@6.6.2)(solid-js@1.9.9)(vite@7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)) + version: 2.11.9(patch_hash=71233f1afab9e3ea2dbb03dbda3d84894ef1c6bfbbe69df9f864d03bfe67b6f5)(@testing-library/jest-dom@6.6.2)(solid-js@1.9.9)(vite@7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)) devDependencies: '@types/babel__core': specifier: ^7.20.5 version: 7.20.5 vite: specifier: ^7.1.10 - version: 7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) + version: 7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) vitest: specifier: ^4.0.10 - version: 4.0.10(@types/debug@4.1.12)(@types/node@25.0.1)(@vitest/browser-playwright@4.0.10)(@vitest/ui@4.0.10)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.30.2)(msw@2.7.0(@types/node@25.0.1)(typescript@5.7.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) + version: 4.0.10(@types/debug@4.1.12)(@types/node@25.0.3)(@vitest/browser-playwright@4.0.10)(@vitest/ui@4.0.10)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.30.2)(msw@2.7.0(@types/node@25.0.3)(typescript@5.7.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) packages/start-nitro-v2-vite-plugin: dependencies: @@ -410,7 +410,7 @@ importers: devDependencies: vite: specifier: ^7.1.10 - version: 7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) + version: 7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) packages: @@ -2221,9 +2221,6 @@ packages: '@types/node@24.9.1': resolution: {integrity: sha512-QoiaXANRkSXK6p0Duvt56W208du4P9Uye9hWLWgGMDTEoKPhuenzNcC4vGUmrNkiOKTlIrBoyNQYNpSwfEZXSg==} - '@types/node@25.0.1': - resolution: {integrity: sha512-czWPzKIAXucn9PtsttxmumiQ9N0ok9FrBwgRWrwmVLlp86BrMExzvXRLFYRJ+Ex3g6yqj+KuaxfX1JTgV2lpfg==} - '@types/node@25.0.3': resolution: {integrity: sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==} @@ -4854,8 +4851,8 @@ packages: resolution: {integrity: sha512-RbcPH1n5cfwKrru7v7+zrZvjLurgHhGyso3HTyGtRivGWgYjbOmGuivCQaORNELjNONoK35nj28EoWul9sb1zQ==} engines: {node: '>=10'} - seroval@1.4.1: - resolution: {integrity: sha512-9GOc+8T6LN4aByLN75uRvMbrwY5RDBW6lSlknsY4LEa9ZmWcxKcRe1G/Q3HZXjltxMHTrStnvrwAICxZrhldtg==} + seroval@1.4.2: + resolution: {integrity: sha512-N3HEHRCZYn3cQbsC4B5ldj9j+tHdf4JZoYPlcI4rRYu0Xy4qN8MQf1Z08EibzB0WpgRG5BGK08FTrmM66eSzKQ==} engines: {node: '>=10'} serve-placeholder@2.0.2: @@ -4961,8 +4958,8 @@ packages: peerDependencies: solid-js: ^1.6.12 - solid-use@0.9.0: - resolution: {integrity: sha512-8TGwB4m3qQ7qKo8Lg0pi/ZyyGVmQIjC4sPyxRCH7VPds0BzSsT734PhP3jhR6zMJxoYHM+uoivjq0XdpzXeOJg==} + solid-use@0.9.1: + resolution: {integrity: sha512-UwvXDVPlrrbj/9ewG9ys5uL2IO4jSiwys2KPzK4zsnAcmEl7iDafZWW1Mo4BSEWOmQCGK6IvpmGHo1aou8iOFw==} engines: {node: '>=10'} peerDependencies: solid-js: ^1.7 @@ -5152,8 +5149,8 @@ packages: resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} engines: {node: '>=8'} - terracotta@1.0.6: - resolution: {integrity: sha512-yVrmT/Lg6a3tEbeYEJH8ksb1PYkR5FA9k5gr1TchaSNIiA2ZWs5a+koEbePXwlBP0poaV7xViZ/v50bQFcMgqw==} + terracotta@1.1.0: + resolution: {integrity: sha512-kfQciWUBUBgYkXu7gh3CK3FAJng/iqZslAaY08C+k1Hdx17aVEpcFFb/WPaysxAfcupNH3y53s/pc53xxZauww==} engines: {node: '>=10'} peerDependencies: solid-js: ^1.8 @@ -6163,7 +6160,7 @@ snapshots: dependencies: '@changesets/types': 6.1.0 - '@changesets/cli@2.29.8(@types/node@25.0.1)': + '@changesets/cli@2.29.8(@types/node@25.0.3)': dependencies: '@changesets/apply-release-plan': 7.0.14 '@changesets/assemble-release-plan': 6.0.9 @@ -6179,7 +6176,7 @@ snapshots: '@changesets/should-skip-package': 0.1.2 '@changesets/types': 6.1.0 '@changesets/write': 0.4.0 - '@inquirer/external-editor': 1.0.3(@types/node@25.0.1) + '@inquirer/external-editor': 1.0.3(@types/node@25.0.3) '@manypkg/get-packages': 1.1.3 ansi-colors: 4.1.3 ci-info: 3.9.0 @@ -6562,41 +6559,41 @@ snapshots: '@inquirer/ansi@1.0.2': optional: true - '@inquirer/confirm@5.1.21(@types/node@25.0.1)': + '@inquirer/confirm@5.1.21(@types/node@25.0.3)': dependencies: - '@inquirer/core': 10.3.2(@types/node@25.0.1) - '@inquirer/type': 3.0.10(@types/node@25.0.1) + '@inquirer/core': 10.3.2(@types/node@25.0.3) + '@inquirer/type': 3.0.10(@types/node@25.0.3) optionalDependencies: - '@types/node': 25.0.1 + '@types/node': 25.0.3 optional: true - '@inquirer/core@10.3.2(@types/node@25.0.1)': + '@inquirer/core@10.3.2(@types/node@25.0.3)': dependencies: '@inquirer/ansi': 1.0.2 '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@25.0.1) + '@inquirer/type': 3.0.10(@types/node@25.0.3) cli-width: 4.1.0 mute-stream: 2.0.0 signal-exit: 4.1.0 wrap-ansi: 6.2.0 yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 25.0.1 + '@types/node': 25.0.3 optional: true - '@inquirer/external-editor@1.0.3(@types/node@25.0.1)': + '@inquirer/external-editor@1.0.3(@types/node@25.0.3)': dependencies: chardet: 2.1.1 iconv-lite: 0.7.1 optionalDependencies: - '@types/node': 25.0.1 + '@types/node': 25.0.3 '@inquirer/figures@1.0.15': optional: true - '@inquirer/type@3.0.10(@types/node@25.0.1)': + '@inquirer/type@3.0.10(@types/node@25.0.3)': optionalDependencies: - '@types/node': 25.0.1 + '@types/node': 25.0.3 optional: true '@internationalized/date@3.5.4': @@ -7548,14 +7545,14 @@ snapshots: postcss-selector-parser: 6.0.10 tailwindcss: 3.4.17 - '@tailwindcss/vite@4.1.17(vite@7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))': + '@tailwindcss/vite@4.1.17(vite@7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))': dependencies: '@tailwindcss/node': 4.1.17 '@tailwindcss/oxide': 4.1.17 tailwindcss: 4.1.17 - vite: 7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) + vite: 7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) - '@tanstack/directive-functions-plugin@1.134.5(vite@7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))': + '@tanstack/directive-functions-plugin@1.134.5(vite@7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))': dependencies: '@babel/code-frame': 7.27.1 '@babel/core': 7.28.3 @@ -7565,7 +7562,7 @@ snapshots: babel-dead-code-elimination: 1.0.10 pathe: 2.0.3 tiny-invariant: 1.3.3 - vite: 7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) + vite: 7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) transitivePeerDependencies: - supports-color @@ -7582,7 +7579,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/server-functions-plugin@1.134.5(vite@7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))': + '@tanstack/server-functions-plugin@1.134.5(vite@7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))': dependencies: '@babel/code-frame': 7.27.1 '@babel/core': 7.28.3 @@ -7591,7 +7588,7 @@ snapshots: '@babel/template': 7.27.2 '@babel/traverse': 7.28.5 '@babel/types': 7.28.5 - '@tanstack/directive-functions-plugin': 1.134.5(vite@7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)) + '@tanstack/directive-functions-plugin': 1.134.5(vite@7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)) babel-dead-code-elimination: 1.0.10 tiny-invariant: 1.3.3 transitivePeerDependencies: @@ -7699,11 +7696,6 @@ snapshots: undici-types: 7.16.0 optional: true - '@types/node@25.0.1': - dependencies: - undici-types: 7.16.0 - optional: true - '@types/node@25.0.3': dependencies: undici-types: 7.16.0 @@ -7789,29 +7781,29 @@ snapshots: - rollup - supports-color - '@vitest/browser-playwright@4.0.10(msw@2.7.0(@types/node@25.0.1)(typescript@5.7.3))(playwright@1.56.1)(vite@7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))(vitest@4.0.10)': + '@vitest/browser-playwright@4.0.10(msw@2.7.0(@types/node@25.0.3)(typescript@5.7.3))(playwright@1.56.1)(vite@7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))(vitest@4.0.10)': dependencies: - '@vitest/browser': 4.0.10(msw@2.7.0(@types/node@25.0.1)(typescript@5.7.3))(vite@7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))(vitest@4.0.10) - '@vitest/mocker': 4.0.10(msw@2.7.0(@types/node@25.0.1)(typescript@5.7.3))(vite@7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)) + '@vitest/browser': 4.0.10(msw@2.7.0(@types/node@25.0.3)(typescript@5.7.3))(vite@7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))(vitest@4.0.10) + '@vitest/mocker': 4.0.10(msw@2.7.0(@types/node@25.0.3)(typescript@5.7.3))(vite@7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)) playwright: 1.56.1 tinyrainbow: 3.0.3 - vitest: 4.0.10(@types/debug@4.1.12)(@types/node@25.0.1)(@vitest/browser-playwright@4.0.10)(@vitest/ui@4.0.10)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.30.2)(msw@2.7.0(@types/node@25.0.1)(typescript@5.7.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) + vitest: 4.0.10(@types/debug@4.1.12)(@types/node@25.0.3)(@vitest/browser-playwright@4.0.10)(@vitest/ui@4.0.10)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.30.2)(msw@2.7.0(@types/node@25.0.3)(typescript@5.7.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) transitivePeerDependencies: - bufferutil - msw - utf-8-validate - vite - '@vitest/browser@4.0.10(msw@2.7.0(@types/node@25.0.1)(typescript@5.7.3))(vite@7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))(vitest@4.0.10)': + '@vitest/browser@4.0.10(msw@2.7.0(@types/node@25.0.3)(typescript@5.7.3))(vite@7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))(vitest@4.0.10)': dependencies: - '@vitest/mocker': 4.0.10(msw@2.7.0(@types/node@25.0.1)(typescript@5.7.3))(vite@7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)) + '@vitest/mocker': 4.0.10(msw@2.7.0(@types/node@25.0.3)(typescript@5.7.3))(vite@7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)) '@vitest/utils': 4.0.10 magic-string: 0.30.21 pixelmatch: 7.1.0 pngjs: 7.0.0 sirv: 3.0.2 tinyrainbow: 3.0.3 - vitest: 4.0.10(@types/debug@4.1.12)(@types/node@25.0.1)(@vitest/browser-playwright@4.0.10)(@vitest/ui@4.0.10)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.30.2)(msw@2.7.0(@types/node@25.0.1)(typescript@5.7.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) + vitest: 4.0.10(@types/debug@4.1.12)(@types/node@25.0.3)(@vitest/browser-playwright@4.0.10)(@vitest/ui@4.0.10)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.30.2)(msw@2.7.0(@types/node@25.0.3)(typescript@5.7.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) ws: 8.18.3 transitivePeerDependencies: - bufferutil @@ -7828,14 +7820,14 @@ snapshots: chai: 6.2.1 tinyrainbow: 3.0.3 - '@vitest/mocker@4.0.10(msw@2.7.0(@types/node@25.0.1)(typescript@5.7.3))(vite@7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))': + '@vitest/mocker@4.0.10(msw@2.7.0(@types/node@25.0.3)(typescript@5.7.3))(vite@7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))': dependencies: '@vitest/spy': 4.0.10 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - msw: 2.7.0(@types/node@25.0.1)(typescript@5.7.3) - vite: 7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) + msw: 2.7.0(@types/node@25.0.3)(typescript@5.7.3) + vite: 7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) '@vitest/pretty-format@4.0.10': dependencies: @@ -7863,7 +7855,7 @@ snapshots: sirv: 3.0.2 tinyglobby: 0.2.15 tinyrainbow: 3.0.3 - vitest: 4.0.10(@types/debug@4.1.12)(@types/node@25.0.1)(@vitest/browser-playwright@4.0.10)(@vitest/ui@4.0.10)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.30.2)(msw@2.7.0(@types/node@25.0.1)(typescript@5.7.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) + vitest: 4.0.10(@types/debug@4.1.12)(@types/node@25.0.3)(@vitest/browser-playwright@4.0.10)(@vitest/ui@4.0.10)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.30.2)(msw@2.7.0(@types/node@25.0.3)(typescript@5.7.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) '@vitest/utils@4.0.10': dependencies: @@ -9589,12 +9581,12 @@ snapshots: ms@2.1.3: {} - msw@2.7.0(@types/node@25.0.1)(typescript@5.7.3): + msw@2.7.0(@types/node@25.0.3)(typescript@5.7.3): dependencies: '@bundled-es-modules/cookie': 2.0.1 '@bundled-es-modules/statuses': 1.0.1 '@bundled-es-modules/tough-cookie': 0.1.6 - '@inquirer/confirm': 5.1.21(@types/node@25.0.1) + '@inquirer/confirm': 5.1.21(@types/node@25.0.3) '@mswjs/interceptors': 0.37.6 '@open-draft/deferred-promise': 2.2.0 '@open-draft/until': 2.1.0 @@ -9642,7 +9634,7 @@ snapshots: nf3@0.1.12: {} - nitro@3.0.1-alpha.0(@netlify/blobs@10.4.1)(better-sqlite3@11.8.1)(chokidar@4.0.3)(drizzle-orm@0.31.4(@opentelemetry/api@1.9.0)(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.12)(better-sqlite3@11.8.1)(prisma@5.22.0))(ioredis@5.6.1)(vite@7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)): + nitro@3.0.1-alpha.0(@netlify/blobs@10.4.1)(better-sqlite3@11.8.1)(chokidar@4.0.3)(drizzle-orm@0.31.4(@opentelemetry/api@1.9.0)(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.12)(better-sqlite3@11.8.1)(prisma@5.22.0))(ioredis@5.6.1)(vite@7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)): dependencies: consola: 3.4.2 cookie-es: 2.0.0 @@ -9662,7 +9654,7 @@ snapshots: unenv: 2.0.0-rc.21 unstorage: 2.0.0-alpha.3(@netlify/blobs@10.4.1)(chokidar@4.0.3)(db0@0.3.4(better-sqlite3@11.8.1)(drizzle-orm@0.31.4(@opentelemetry/api@1.9.0)(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.12)(better-sqlite3@11.8.1)(prisma@5.22.0)))(ioredis@5.6.1)(ofetch@1.4.1) optionalDependencies: - vite: 7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) + vite: 7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -9692,7 +9684,7 @@ snapshots: - sqlite3 - uploadthing - nitro@3.0.1-alpha.1(@netlify/blobs@10.4.1)(better-sqlite3@11.8.1)(chokidar@4.0.3)(drizzle-orm@0.31.4(@opentelemetry/api@1.9.0)(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.12)(better-sqlite3@11.8.1)(prisma@5.22.0))(ioredis@5.6.1)(rollup@4.52.5)(vite@7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)): + nitro@3.0.1-alpha.1(@netlify/blobs@10.4.1)(better-sqlite3@11.8.1)(chokidar@4.0.3)(drizzle-orm@0.31.4(@opentelemetry/api@1.9.0)(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.12)(better-sqlite3@11.8.1)(prisma@5.22.0))(ioredis@5.6.1)(rollup@4.52.5)(vite@7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)): dependencies: consola: 3.4.2 crossws: 0.4.1(srvx@0.9.6) @@ -9710,7 +9702,7 @@ snapshots: unstorage: 2.0.0-alpha.4(@netlify/blobs@10.4.1)(chokidar@4.0.3)(db0@0.3.4(better-sqlite3@11.8.1)(drizzle-orm@0.31.4(@opentelemetry/api@1.9.0)(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.12)(better-sqlite3@11.8.1)(prisma@5.22.0)))(ioredis@5.6.1)(ofetch@2.0.0-alpha.3) optionalDependencies: rollup: 4.52.5 - vite: 7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) + vite: 7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -10518,13 +10510,13 @@ snapshots: dependencies: seroval: 1.3.2 - seroval-plugins@1.4.0(seroval@1.4.1): + seroval-plugins@1.4.0(seroval@1.4.2): dependencies: - seroval: 1.4.1 + seroval: 1.4.2 seroval@1.3.2: {} - seroval@1.4.1: {} + seroval@1.4.2: {} serve-placeholder@2.0.2: dependencies: @@ -10661,7 +10653,7 @@ snapshots: '@solid-primitives/transition-group': 1.1.2(solid-js@1.9.9) solid-js: 1.9.9 - solid-use@0.9.0(solid-js@1.9.9): + solid-use@0.9.1(solid-js@1.9.9): dependencies: solid-js: 1.9.9 @@ -10878,10 +10870,10 @@ snapshots: term-size@2.2.1: {} - terracotta@1.0.6(solid-js@1.9.9): + terracotta@1.1.0(solid-js@1.9.9): dependencies: solid-js: 1.9.9 - solid-use: 0.9.0(solid-js@1.9.9) + solid-use: 0.9.1(solid-js@1.9.9) terser@5.44.0: dependencies: @@ -11205,7 +11197,7 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.2 - vite-plugin-solid@2.11.9(patch_hash=71233f1afab9e3ea2dbb03dbda3d84894ef1c6bfbbe69df9f864d03bfe67b6f5)(@testing-library/jest-dom@6.6.2)(solid-js@1.9.9)(vite@7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)): + vite-plugin-solid@2.11.9(patch_hash=71233f1afab9e3ea2dbb03dbda3d84894ef1c6bfbbe69df9f864d03bfe67b6f5)(@testing-library/jest-dom@6.6.2)(solid-js@1.9.9)(vite@7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)): dependencies: '@babel/core': 7.28.3 '@types/babel__core': 7.20.5 @@ -11213,14 +11205,14 @@ snapshots: merge-anything: 5.1.7 solid-js: 1.9.9 solid-refresh: 0.6.3(solid-js@1.9.9) - vite: 7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) - vitefu: 1.1.1(vite@7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)) + vite: 7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) + vitefu: 1.1.1(vite@7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)) optionalDependencies: '@testing-library/jest-dom': 6.6.2 transitivePeerDependencies: - supports-color - vite@7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1): + vite@7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1): dependencies: esbuild: 0.25.11 fdir: 6.5.0(picomatch@4.0.3) @@ -11229,7 +11221,7 @@ snapshots: rollup: 4.52.5 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 25.0.1 + '@types/node': 25.0.3 fsevents: 2.3.3 jiti: 2.6.1 lightningcss: 1.30.2 @@ -11237,14 +11229,14 @@ snapshots: tsx: 4.19.2 yaml: 2.8.1 - vitefu@1.1.1(vite@7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)): + vitefu@1.1.1(vite@7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)): optionalDependencies: - vite: 7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) + vite: 7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) - vitest@4.0.10(@types/debug@4.1.12)(@types/node@25.0.1)(@vitest/browser-playwright@4.0.10)(@vitest/ui@4.0.10)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.30.2)(msw@2.7.0(@types/node@25.0.1)(typescript@5.7.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1): + vitest@4.0.10(@types/debug@4.1.12)(@types/node@25.0.3)(@vitest/browser-playwright@4.0.10)(@vitest/ui@4.0.10)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.30.2)(msw@2.7.0(@types/node@25.0.3)(typescript@5.7.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1): dependencies: '@vitest/expect': 4.0.10 - '@vitest/mocker': 4.0.10(msw@2.7.0(@types/node@25.0.1)(typescript@5.7.3))(vite@7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)) + '@vitest/mocker': 4.0.10(msw@2.7.0(@types/node@25.0.3)(typescript@5.7.3))(vite@7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)) '@vitest/pretty-format': 4.0.10 '@vitest/runner': 4.0.10 '@vitest/snapshot': 4.0.10 @@ -11261,12 +11253,12 @@ snapshots: tinyexec: 0.3.2 tinyglobby: 0.2.15 tinyrainbow: 3.0.3 - vite: 7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) + vite: 7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 - '@types/node': 25.0.1 - '@vitest/browser-playwright': 4.0.10(msw@2.7.0(@types/node@25.0.1)(typescript@5.7.3))(playwright@1.56.1)(vite@7.1.10(@types/node@25.0.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))(vitest@4.0.10) + '@types/node': 25.0.3 + '@vitest/browser-playwright': 4.0.10(msw@2.7.0(@types/node@25.0.3)(typescript@5.7.3))(playwright@1.56.1)(vite@7.1.10(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))(vitest@4.0.10) '@vitest/ui': 4.0.10(vitest@4.0.10) jsdom: 25.0.1 transitivePeerDependencies: