From c5ec5d11b4480da901b123a80e3b4f22d5ae27d7 Mon Sep 17 00:00:00 2001
From: Darko Bozhinovski
Date: Mon, 24 Nov 2025 11:53:14 +0100
Subject: [PATCH 1/3] feat: adds oxfmt; migrates all rules over to oxfmt
config; updates CONTRIBUTING; formats full codebase; makes editorconfig as
consistens as possible with oxfmt; removes prettierrc.
---
.editorconfig | 4 +-
.oxfmtrc.json | 11 +
.prettierrc | 8 -
CONTRIBUTING.md | 4 +
apps/fixtures/bare/vite.config.ts | 2 +-
apps/fixtures/basic/vite.config.ts | 2 +-
apps/fixtures/css/src/components/layout.tsx | 4 +-
apps/fixtures/css/src/components/lazy.tsx | 4 +-
apps/fixtures/css/src/components/lazyGlob.tsx | 4 +-
apps/fixtures/css/src/components/lazyLink.tsx | 2 +-
.../css/src/components/lazyLinkTmp.tsx | 2 +-
apps/fixtures/css/src/components/test.tsx | 2 +-
apps/fixtures/css/src/routes/[...404].tsx | 2 +-
.../src/components/BreaksOnServer.tsx | 4 +-
.../fixtures/experiments/src/entry-server.tsx | 38 +-
apps/fixtures/experiments/src/middleware.ts | 30 +-
.../experiments/src/routes/(group).tsx | 14 +-
.../experiments/src/routes/(group)/other.tsx | 6 +-
.../experiments/src/routes/(group2).tsx | 14 +-
.../src/routes/(group2)/something.tsx | 6 +-
.../experiments/src/routes/[...404].tsx | 3 +-
.../src/routes/[[option]]/thing.tsx | 6 +-
.../src/routes/api/hello/[name].ts | 2 +-
.../fixtures/experiments/src/routes/index.tsx | 2 +-
.../src/routes/test(named)/[name]/home.tsx | 6 +-
.../experiments/src/routes/test/(hi).tsx | 6 +-
.../experiments/src/routes/test/[name].tsx | 6 +-
.../src/routes/\346\274\242\345\255\227.tsx" | 6 +-
apps/fixtures/experiments/vite.config.ts | 4 +-
apps/fixtures/hackernews/public/sw.js | 8 +-
.../hackernews/src/components/comment.tsx | 4 +-
apps/fixtures/hackernews/src/lib/api.ts | 11 +-
.../hackernews/src/routes/users/[id].tsx | 2 +-
apps/fixtures/hackernews/vite.config.ts | 2 +-
.../notes/src/components/NoteList.tsx | 40 +-
.../notes/src/components/SidebarNote.tsx | 4 +-
apps/fixtures/notes/src/lib/db.ts | 2 +-
apps/fixtures/notes/src/lib/types.ts | 2 +-
apps/fixtures/notes/src/routes/(home).tsx | 2 +-
apps/fixtures/todomvc/src/global.d.ts | 2 +-
apps/fixtures/todomvc/src/lib/db.ts | 2 +-
apps/fixtures/todomvc/src/types.ts | 2 +-
apps/fixtures/todomvc/vite.config.ts | 2 +-
apps/landing-page/postcss.config.js | 10 +-
.../src/components/icons/lego-icon.tsx | 20 +-
.../src/components/icons/solid-logo.tsx | 33 +-
.../src/components/theme-toggle.tsx | 8 +-
.../src/components/ui/accordion.tsx | 24 +-
.../landing-page/src/components/ui/button.tsx | 26 +-
.../landing-page/src/components/ui/dialog.tsx | 42 +-
.../landing-page/src/components/ui/drawer.tsx | 36 +-
.../src/components/ui/dropdown-menu.tsx | 105 +--
apps/landing-page/src/components/ui/input.tsx | 2 +-
apps/landing-page/src/components/ui/label.tsx | 2 +-
.../src/components/ui/skeleton.tsx | 9 +-
apps/landing-page/src/components/ui/tabs.tsx | 8 +-
apps/landing-page/src/lib/utils.ts | 10 +-
apps/tests/src/app.tsx | 4 +-
apps/tests/src/e2e/api-call.test.ts | 6 +-
apps/tests/src/e2e/http-header.test.ts | 10 +-
apps/tests/src/routes/(basic).tsx | 6 +-
apps/tests/src/routes/[...404].tsx | 4 +-
apps/tests/src/routes/api/header-merging.ts | 8 +-
.../src/routes/client-only/_component.tsx | 18 +-
apps/tests/src/routes/client-only/index.tsx | 5 +-
.../src/routes/generator-server-function.tsx | 28 +-
apps/tests/src/routes/http-header.tsx | 12 +-
apps/tests/src/routes/is-server-const.tsx | 22 +-
apps/tests/src/routes/is-server-nested.tsx | 4 +-
apps/tests/src/routes/is-server-toplevel.tsx | 4 +-
.../is-server-with-anon-default-export.tsx | 22 +-
.../src/routes/nested/(ignored)route0.tsx | 1 -
.../nested/(level1)/(ignored)route1.tsx | 1 -
.../(level1)/(level2)/(ignored)route2.tsx | 1 -
.../nested/(level1)/(level2)/route3.tsx | 1 -
apps/tests/src/routes/node-builtin-nested.tsx | 6 +-
.../src/routes/node-builtin-toplevel.tsx | 1 -
...xport-named-functions-in-the-same-file.tsx | 16 +-
apps/tests/src/routes/text-plain-response.tsx | 2 +-
apps/tests/vite.config.ts | 8 +-
package.json | 5 +-
.../start-nitro-v2-vite-plugin/src/index.ts | 356 +++++----
packages/start/src/config/constants.ts | 2 +-
packages/start/src/config/dev-server.ts | 194 +++--
packages/start/src/config/fs-router.ts | 295 ++++----
.../start/src/config/fs-routes/fs-watcher.ts | 118 ++-
packages/start/src/config/fs-routes/index.ts | 236 +++---
.../start/src/config/fs-routes/tree-shake.ts | 705 +++++++++---------
packages/start/src/config/vite-utils.ts | 10 +-
packages/start/src/env.d.ts | 36 +-
packages/start/src/http/index.ts | 247 +++---
packages/start/src/index.tsx | 21 +-
packages/start/src/internal.d.ts | 2 +-
packages/start/src/middleware/index.ts | 88 +--
packages/start/src/router.tsx | 3 +-
packages/start/src/server/StartServer.tsx | 8 +-
packages/start/src/server/assets/render.tsx | 6 +-
packages/start/src/server/collect-styles.ts | 133 ++--
packages/start/src/server/fetchEvent.spec.ts | 146 ++--
packages/start/src/server/fetchEvent.ts | 34 +-
packages/start/src/server/handler.ts | 242 +++---
.../src/server/manifest/client-manifest.ts | 2 +-
.../server/manifest/dev-client-manifest.ts | 14 +-
.../src/server/manifest/dev-ssr-manifest.ts | 16 +-
.../server/manifest/prod-client-manifest.ts | 13 +-
.../src/server/manifest/prod-ssr-manifest.ts | 172 ++---
.../start/src/server/manifest/ssr-manifest.ts | 6 +-
packages/start/src/server/routes.ts | 204 +++--
.../start/src/server/server-fns-runtime.ts | 2 +-
.../src/server/server-functions-handler.ts | 613 ++++++++-------
packages/start/src/server/server-runtime.ts | 4 +-
packages/start/src/server/spa/handler.ts | 24 +-
packages/start/src/server/types.ts | 92 +--
packages/start/src/server/util.ts | 8 +-
packages/start/src/shared/HttpHeader.tsx | 40 +-
packages/start/src/shared/HttpStatusCode.ts | 28 +-
.../start/src/shared/dev-overlay/CodeView.tsx | 89 ++-
.../shared/dev-overlay/createStackFrame.ts | 121 ++-
.../start/src/shared/dev-overlay/env.d.ts | 4 +-
.../src/shared/dev-overlay/get-source-map.ts | 14 +-
.../start/src/shared/dev-overlay/icons.tsx | 410 +++++++---
packages/start/src/shared/lazy.ts | 5 +-
packages/start/src/shared/serverFunction.ts | 2 +-
packages/start/src/virtual.d.ts | 20 +-
pnpm-lock.yaml | 83 +++
scripts/bump.js | 7 +-
126 files changed, 2847 insertions(+), 2847 deletions(-)
create mode 100644 .oxfmtrc.json
delete mode 100644 .prettierrc
diff --git a/.editorconfig b/.editorconfig
index 54c8a9183..de279a9ee 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -5,4 +5,6 @@ indent_style = space
indent_size = 2
end_of_line = LF
charset = utf-8
-insert_final_newline = true
\ No newline at end of file
+insert_final_newline = true
+max_line_length = 100
+quote_type = double
diff --git a/.oxfmtrc.json b/.oxfmtrc.json
new file mode 100644
index 000000000..e5599ddda
--- /dev/null
+++ b/.oxfmtrc.json
@@ -0,0 +1,11 @@
+{
+ "$schema": "https://raw.githubusercontent.com/oxc-project/oxc/main/npm/oxfmt/configuration_schema.json",
+ "tabWidth": 2,
+ "useTabs": false,
+ "endOfLine": "lf",
+ "trailingComma": "none",
+ "semi": true,
+ "singleQuote": false,
+ "arrowParens": "avoid",
+ "printWidth": 100
+}
diff --git a/.prettierrc b/.prettierrc
deleted file mode 100644
index 6aeb7ea15..000000000
--- a/.prettierrc
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "trailingComma": "none",
- "tabWidth": 2,
- "semi": true,
- "singleQuote": false,
- "arrowParens": "avoid",
- "printWidth": 100
-}
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 318496622..a882e9714 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -74,6 +74,10 @@ Once the PR is there, **create an issue** and link the PR (mention the PR as you
> [!IMPORTANT]
> Mark the **allow edit by the maintainers** so we can more easily investigate the failing test and propose a fix. Otherwise we may need to close your PR and cherry-pick your commit.
+### Formatting your code
+
+We have a set of rules defined in the `.editorconfig` and `.oxfmtrc.json` files. Please format your code before opening a PR, so that we keep the codebase consistent. Regardless of what editor you use, running `pnpm format` will format your code according to our rules.
+
---
If you have read all the way here, you're already a champ! 🏆
diff --git a/apps/fixtures/bare/vite.config.ts b/apps/fixtures/bare/vite.config.ts
index 2d2e72458..fad292267 100644
--- a/apps/fixtures/bare/vite.config.ts
+++ b/apps/fixtures/bare/vite.config.ts
@@ -3,5 +3,5 @@ import { solidStart } from "../../../packages/start/src/config";
import { nitroV2Plugin } from "../../../packages/start-nitro-v2-vite-plugin/src";
export default defineConfig({
- plugins: [solidStart(), nitroV2Plugin()],
+ plugins: [solidStart(), nitroV2Plugin()]
});
diff --git a/apps/fixtures/basic/vite.config.ts b/apps/fixtures/basic/vite.config.ts
index 2d2e72458..fad292267 100644
--- a/apps/fixtures/basic/vite.config.ts
+++ b/apps/fixtures/basic/vite.config.ts
@@ -3,5 +3,5 @@ import { solidStart } from "../../../packages/start/src/config";
import { nitroV2Plugin } from "../../../packages/start-nitro-v2-vite-plugin/src";
export default defineConfig({
- plugins: [solidStart(), nitroV2Plugin()],
+ plugins: [solidStart(), nitroV2Plugin()]
});
diff --git a/apps/fixtures/css/src/components/layout.tsx b/apps/fixtures/css/src/components/layout.tsx
index 91d077054..99763f047 100644
--- a/apps/fixtures/css/src/components/layout.tsx
+++ b/apps/fixtures/css/src/components/layout.tsx
@@ -26,8 +26,8 @@ const Layout = (props: FlowProps<{ title: string }>) => {
- Enable throttling & disable cache in the network tab to see eventual FOUC's (frames of unstyled
- content)
+ Enable throttling & disable cache in the network tab to see eventual FOUC's (frames of
+ unstyled content)
Click on routes to test client navigation
diff --git a/apps/fixtures/css/src/components/lazy.tsx b/apps/fixtures/css/src/components/lazy.tsx
index 462362ec2..1a64df9d1 100644
--- a/apps/fixtures/css/src/components/lazy.tsx
+++ b/apps/fixtures/css/src/components/lazy.tsx
@@ -1,7 +1,7 @@
import "../styles/lazy.css";
const Lazy = () => {
- return <>>
-}
+ return <>>;
+};
export default Lazy;
diff --git a/apps/fixtures/css/src/components/lazyGlob.tsx b/apps/fixtures/css/src/components/lazyGlob.tsx
index 75dca500b..0256e799e 100644
--- a/apps/fixtures/css/src/components/lazyGlob.tsx
+++ b/apps/fixtures/css/src/components/lazyGlob.tsx
@@ -1,7 +1,7 @@
import "../styles/lazyGlob.css";
const Lazy = () => {
- return <>>
-}
+ return <>>;
+};
export default Lazy;
diff --git a/apps/fixtures/css/src/components/lazyLink.tsx b/apps/fixtures/css/src/components/lazyLink.tsx
index f3b9084e7..5d352d41b 100644
--- a/apps/fixtures/css/src/components/lazyLink.tsx
+++ b/apps/fixtures/css/src/components/lazyLink.tsx
@@ -1,5 +1,5 @@
import url from "../styles/lazyLink.css?url";
-const Lazy = () =>
+const Lazy = () => ;
export default Lazy;
diff --git a/apps/fixtures/css/src/components/lazyLinkTmp.tsx b/apps/fixtures/css/src/components/lazyLinkTmp.tsx
index 3a04dd96e..6061f995b 100644
--- a/apps/fixtures/css/src/components/lazyLinkTmp.tsx
+++ b/apps/fixtures/css/src/components/lazyLinkTmp.tsx
@@ -1,5 +1,5 @@
import url from "../styles/lazyLinkTmp.css?url";
-const Lazy = () =>
+const Lazy = () => ;
export default Lazy;
diff --git a/apps/fixtures/css/src/components/test.tsx b/apps/fixtures/css/src/components/test.tsx
index 8f3e8ea1a..970d70b02 100644
--- a/apps/fixtures/css/src/components/test.tsx
+++ b/apps/fixtures/css/src/components/test.tsx
@@ -6,7 +6,7 @@ const integrations = {
import: "import",
module: "import module",
url: "?url without render",
- link: "?url + ",
+ link: "?url + "
};
const Test = (props: {
invert?: boolean;
diff --git a/apps/fixtures/css/src/routes/[...404].tsx b/apps/fixtures/css/src/routes/[...404].tsx
index 53b221ce7..4ea71ec7f 100644
--- a/apps/fixtures/css/src/routes/[...404].tsx
+++ b/apps/fixtures/css/src/routes/[...404].tsx
@@ -16,4 +16,4 @@ export default function NotFound() {
);
-}
\ No newline at end of file
+}
diff --git a/apps/fixtures/experiments/src/components/BreaksOnServer.tsx b/apps/fixtures/experiments/src/components/BreaksOnServer.tsx
index 8e6ae7eec..f6b161610 100644
--- a/apps/fixtures/experiments/src/components/BreaksOnServer.tsx
+++ b/apps/fixtures/experiments/src/components/BreaksOnServer.tsx
@@ -2,5 +2,5 @@
const location = window.document.location;
export default function BreaksOnServer() {
- return Breaks on server {location.href}
-}
\ No newline at end of file
+ return Breaks on server {location.href}
;
+}
diff --git a/apps/fixtures/experiments/src/entry-server.tsx b/apps/fixtures/experiments/src/entry-server.tsx
index 9ac19e964..3cc2ec0c5 100644
--- a/apps/fixtures/experiments/src/entry-server.tsx
+++ b/apps/fixtures/experiments/src/entry-server.tsx
@@ -8,23 +8,21 @@ declare module "@solidjs/start/server" {
}
}
-export default createHandler(
- () => (
- (
-
-
-
-
-
- {assets}
-
-
- {children}
- {scripts}
-
-
- )}
- />
- )
-);
+export default createHandler(() => (
+ (
+
+
+
+
+
+ {assets}
+
+
+ {children}
+ {scripts}
+
+
+ )}
+ />
+));
diff --git a/apps/fixtures/experiments/src/middleware.ts b/apps/fixtures/experiments/src/middleware.ts
index 83072a35c..bd6942254 100644
--- a/apps/fixtures/experiments/src/middleware.ts
+++ b/apps/fixtures/experiments/src/middleware.ts
@@ -2,19 +2,19 @@ import { getRequestURL } from "@solidjs/start/http";
import { createMiddleware } from "@solidjs/start/middleware";
export default createMiddleware({
- onRequest: [
- (event) => {
- event.locals.foo = "bar";
- console.log("REQUEST", event.request.url);
- console.log(
- "SEARCH PARAM KEYS FROM ASYNC CONTEXT",
- Array.from(getRequestURL().searchParams.keys()),
- );
- },
- ],
- onBeforeResponse: [
- (event, { body }) => {
- console.log("BEFORE RESPONSE", body);
- },
- ],
+ onRequest: [
+ event => {
+ event.locals.foo = "bar";
+ console.log("REQUEST", event.request.url);
+ console.log(
+ "SEARCH PARAM KEYS FROM ASYNC CONTEXT",
+ Array.from(getRequestURL().searchParams.keys())
+ );
+ }
+ ],
+ onBeforeResponse: [
+ (event, { body }) => {
+ console.log("BEFORE RESPONSE", body);
+ }
+ ]
});
diff --git a/apps/fixtures/experiments/src/routes/(group).tsx b/apps/fixtures/experiments/src/routes/(group).tsx
index cd362dfeb..f8b17d8fd 100644
--- a/apps/fixtures/experiments/src/routes/(group).tsx
+++ b/apps/fixtures/experiments/src/routes/(group).tsx
@@ -1,8 +1,10 @@
import { RouteSectionProps } from "@solidjs/router";
-export default function(props: RouteSectionProps) {
- return <>
- Group
- {props.children}
- >
-}
\ No newline at end of file
+export default function (props: RouteSectionProps) {
+ return (
+ <>
+ Group
+ {props.children}
+ >
+ );
+}
diff --git a/apps/fixtures/experiments/src/routes/(group)/other.tsx b/apps/fixtures/experiments/src/routes/(group)/other.tsx
index ec973e9b2..64c3cec02 100644
--- a/apps/fixtures/experiments/src/routes/(group)/other.tsx
+++ b/apps/fixtures/experiments/src/routes/(group)/other.tsx
@@ -1,3 +1,3 @@
-export default function() {
- return
-}
\ No newline at end of file
+export default function () {
+ return ;
+}
diff --git a/apps/fixtures/experiments/src/routes/(group2).tsx b/apps/fixtures/experiments/src/routes/(group2).tsx
index 9da3d63e2..b6f213fb2 100644
--- a/apps/fixtures/experiments/src/routes/(group2).tsx
+++ b/apps/fixtures/experiments/src/routes/(group2).tsx
@@ -1,8 +1,10 @@
import { RouteSectionProps } from "@solidjs/router";
-export default function(props: RouteSectionProps) {
- return <>
- Group 2
- {props.children}
- >
-}
\ No newline at end of file
+export default function (props: RouteSectionProps) {
+ return (
+ <>
+ Group 2
+ {props.children}
+ >
+ );
+}
diff --git a/apps/fixtures/experiments/src/routes/(group2)/something.tsx b/apps/fixtures/experiments/src/routes/(group2)/something.tsx
index e8e024771..0cab8149c 100644
--- a/apps/fixtures/experiments/src/routes/(group2)/something.tsx
+++ b/apps/fixtures/experiments/src/routes/(group2)/something.tsx
@@ -1,3 +1,3 @@
-export default function() {
- return
-}
\ No newline at end of file
+export default function () {
+ return ;
+}
diff --git a/apps/fixtures/experiments/src/routes/[...404].tsx b/apps/fixtures/experiments/src/routes/[...404].tsx
index f979d513f..c2329dac9 100644
--- a/apps/fixtures/experiments/src/routes/[...404].tsx
+++ b/apps/fixtures/experiments/src/routes/[...404].tsx
@@ -2,10 +2,9 @@ import { Title } from "@solidjs/meta";
import { HttpStatusCode } from "@solidjs/start";
import type { APIEvent } from "@solidjs/start/server";
-
export const GET = (event: APIEvent) => {
if (event.request.headers.get("accept") !== "application/json") return;
- return { notFound: "API"}
+ return { notFound: "API" };
};
export default function NotFound() {
diff --git a/apps/fixtures/experiments/src/routes/[[option]]/thing.tsx b/apps/fixtures/experiments/src/routes/[[option]]/thing.tsx
index 325fd74d0..4135b83e8 100644
--- a/apps/fixtures/experiments/src/routes/[[option]]/thing.tsx
+++ b/apps/fixtures/experiments/src/routes/[[option]]/thing.tsx
@@ -1,5 +1,5 @@
import type { RouteSectionProps } from "@solidjs/router";
-export default function(props: RouteSectionProps) {
- return THING: {props.params.option || "NO"}
-}
\ No newline at end of file
+export default function (props: RouteSectionProps) {
+ return THING: {props.params.option || "NO"} ;
+}
diff --git a/apps/fixtures/experiments/src/routes/api/hello/[name].ts b/apps/fixtures/experiments/src/routes/api/hello/[name].ts
index 55873210b..98a0d9713 100644
--- a/apps/fixtures/experiments/src/routes/api/hello/[name].ts
+++ b/apps/fixtures/experiments/src/routes/api/hello/[name].ts
@@ -2,4 +2,4 @@ import type { APIHandler } from "@solidjs/start/server";
export const GET: APIHandler = async ({ params }) => {
return `Hello ${params.name}!`;
-};
\ No newline at end of file
+};
diff --git a/apps/fixtures/experiments/src/routes/index.tsx b/apps/fixtures/experiments/src/routes/index.tsx
index 1201bd2c0..c8c40decb 100644
--- a/apps/fixtures/experiments/src/routes/index.tsx
+++ b/apps/fixtures/experiments/src/routes/index.tsx
@@ -22,7 +22,7 @@ export default function Home() {
console.log(v);
console.log(await v.hello);
});
- const port = isServer ? new URL(getRequestEvent()!.request.url).port: location.port;
+ const port = isServer ? new URL(getRequestEvent()!.request.url).port : location.port;
fetch(`http://localhost:${port}${import.meta.env.BASE_URL}/unknown`, {
headers: { Accept: "application/json" }
}).then(async res => console.log(await res.json()));
diff --git a/apps/fixtures/experiments/src/routes/test(named)/[name]/home.tsx b/apps/fixtures/experiments/src/routes/test(named)/[name]/home.tsx
index 09379129c..ed60ca55d 100644
--- a/apps/fixtures/experiments/src/routes/test(named)/[name]/home.tsx
+++ b/apps/fixtures/experiments/src/routes/test(named)/[name]/home.tsx
@@ -1,3 +1,3 @@
-export default function() {
- return
-}
\ No newline at end of file
+export default function () {
+ return ;
+}
diff --git a/apps/fixtures/experiments/src/routes/test/(hi).tsx b/apps/fixtures/experiments/src/routes/test/(hi).tsx
index e48dba856..5e6a5aa68 100644
--- a/apps/fixtures/experiments/src/routes/test/(hi).tsx
+++ b/apps/fixtures/experiments/src/routes/test/(hi).tsx
@@ -1,3 +1,3 @@
-export default function() {
- return
-}
\ No newline at end of file
+export default function () {
+ return ;
+}
diff --git a/apps/fixtures/experiments/src/routes/test/[name].tsx b/apps/fixtures/experiments/src/routes/test/[name].tsx
index 5a6a3e216..9ea84914d 100644
--- a/apps/fixtures/experiments/src/routes/test/[name].tsx
+++ b/apps/fixtures/experiments/src/routes/test/[name].tsx
@@ -1,5 +1,5 @@
import { RouteSectionProps } from "@solidjs/router";
-export default function(props: RouteSectionProps) {
- return
-}
\ No newline at end of file
+export default function (props: RouteSectionProps) {
+ return ;
+}
diff --git "a/apps/fixtures/experiments/src/routes/\346\274\242\345\255\227.tsx" "b/apps/fixtures/experiments/src/routes/\346\274\242\345\255\227.tsx"
index 589296b5f..c8920b4a5 100644
--- "a/apps/fixtures/experiments/src/routes/\346\274\242\345\255\227.tsx"
+++ "b/apps/fixtures/experiments/src/routes/\346\274\242\345\255\227.tsx"
@@ -1,3 +1,3 @@
-export default function() {
- return
-}
\ No newline at end of file
+export default function () {
+ return ;
+}
diff --git a/apps/fixtures/experiments/vite.config.ts b/apps/fixtures/experiments/vite.config.ts
index 96122c421..953f4d83d 100644
--- a/apps/fixtures/experiments/vite.config.ts
+++ b/apps/fixtures/experiments/vite.config.ts
@@ -1,7 +1,7 @@
import { defineConfig } from "vite";
import { solidStart } from "../../../packages/start/src/config";
-import { nitroV2Plugin } from '../../../packages/start-nitro-v2-vite-plugin/src'
+import { nitroV2Plugin } from "../../../packages/start-nitro-v2-vite-plugin/src";
export default defineConfig({
- plugins: [solidStart({ middleware: "./src/middleware.ts" }), nitroV2Plugin()],
+ plugins: [solidStart({ middleware: "./src/middleware.ts" }), nitroV2Plugin()]
});
diff --git a/apps/fixtures/hackernews/public/sw.js b/apps/fixtures/hackernews/public/sw.js
index b2ecb5056..ec8f30ceb 100644
--- a/apps/fixtures/hackernews/public/sw.js
+++ b/apps/fixtures/hackernews/public/sw.js
@@ -1,14 +1,14 @@
-self.addEventListener("fetch", (e) => {
+self.addEventListener("fetch", e => {
(e.request.url.includes("localhost") || e.request.url.includes("workers")) &&
e.respondWith(
caches
.open("solid-hn")
- .then((t) =>
+ .then(t =>
t
.match(e.request)
- .then((n) => n || fetch(e.request).then((n) => (t.put(e.request, n.clone()), n)))
+ .then(n => n || fetch(e.request).then(n => (t.put(e.request, n.clone()), n)))
)
);
});
-self.addEventListener("activate", (e) => e.waitUntil(caches.delete("solid-hn")));
+self.addEventListener("activate", e => e.waitUntil(caches.delete("solid-hn")));
diff --git a/apps/fixtures/hackernews/src/components/comment.tsx b/apps/fixtures/hackernews/src/components/comment.tsx
index 5fac5d45f..8a85eb9df 100644
--- a/apps/fixtures/hackernews/src/components/comment.tsx
+++ b/apps/fixtures/hackernews/src/components/comment.tsx
@@ -7,8 +7,8 @@ const Comment: Component<{ comment: CommentDefinition }> = props => {
return (
- referencing multiple export named functions in the same file
+
+ referencing multiple export named functions in the same file
+
{props.children}
diff --git a/apps/tests/src/e2e/api-call.test.ts b/apps/tests/src/e2e/api-call.test.ts
index 07dbd2a82..f6a750b27 100644
--- a/apps/tests/src/e2e/api-call.test.ts
+++ b/apps/tests/src/e2e/api-call.test.ts
@@ -13,10 +13,12 @@ test.describe("api calls", () => {
expect(okResp.headers.get("x-return-header")).toBe("value");
expect(okResp.headers.get("x-shared-header")).toBe("event");
- const redirectResp = await fetch("http://localhost:3000/api/header-merging?status=redirect", { redirect: "manual" });
+ const redirectResp = await fetch("http://localhost:3000/api/header-merging?status=redirect", {
+ redirect: "manual"
+ });
expect(redirectResp.headers.get("Set-Cookie")).toBeTruthy();
expect(redirectResp.headers.get("x-event-header")).toBe("value");
expect(redirectResp.headers.get("x-return-header")).toBe("value");
expect(redirectResp.headers.get("x-shared-header")).toBe("event");
- })
+ });
});
diff --git a/apps/tests/src/e2e/http-header.test.ts b/apps/tests/src/e2e/http-header.test.ts
index 572a77721..c26f5a19f 100644
--- a/apps/tests/src/e2e/http-header.test.ts
+++ b/apps/tests/src/e2e/http-header.test.ts
@@ -1,10 +1,10 @@
import { expect, test } from "@playwright/test";
test.describe("http header", () => {
- // couldn't get this to see the headers but verified in chrome devtools
- test.skip("should set http header", async ({ page }) => {
- const response = await page.goto("/http-header");
+ // couldn't get this to see the headers but verified in chrome devtools
+ test.skip("should set http header", async ({ page }) => {
+ const response = await page.goto("/http-header");
- expect(response?.headers()["test-header"]).toBe("test-value");
- });
+ expect(response?.headers()["test-header"]).toBe("test-value");
+ });
});
diff --git a/apps/tests/src/routes/(basic).tsx b/apps/tests/src/routes/(basic).tsx
index 13c3aeeb1..54d1741b5 100644
--- a/apps/tests/src/routes/(basic).tsx
+++ b/apps/tests/src/routes/(basic).tsx
@@ -2,11 +2,13 @@ import { createSignal } from "solid-js";
export default function App() {
const [counter, setCounter] = createSignal(0);
-
+
return (
{counter()}
- setCounter(n => n + 1)}>one more
+ setCounter(n => n + 1)}>
+ one more
+
);
}
diff --git a/apps/tests/src/routes/[...404].tsx b/apps/tests/src/routes/[...404].tsx
index 7d71e47bc..f1d7221c8 100644
--- a/apps/tests/src/routes/[...404].tsx
+++ b/apps/tests/src/routes/[...404].tsx
@@ -13,9 +13,7 @@ export default function NotFound() {
Not Found
Page Not Found
-
- {"Your page cannot be found... >_<"}
-
+ {"Your page cannot be found... >_<"}
);
}
diff --git a/apps/tests/src/routes/api/header-merging.ts b/apps/tests/src/routes/api/header-merging.ts
index 0b85a77ea..cd1f30745 100644
--- a/apps/tests/src/routes/api/header-merging.ts
+++ b/apps/tests/src/routes/api/header-merging.ts
@@ -4,12 +4,12 @@ export async function GET() {
const url = getRequestURL();
const s = await useSession({ password: "0".repeat(32) });
- await s.update(d => ({count: (d.count || 0) + 1}))
+ await s.update(d => ({ count: (d.count || 0) + 1 }));
setHeader("x-event-header", "value");
setHeader("x-shared-header", "event");
- if(url.searchParams.get("status") === "redirect") {
+ if (url.searchParams.get("status") === "redirect") {
return new Response(null, {
status: 301,
headers: {
@@ -17,13 +17,13 @@ export async function GET() {
"x-return-header": "value",
"x-shared-header": "return"
}
- })
+ });
} else {
return new Response(null, {
headers: {
"x-return-header": "value",
"x-shared-header": "return"
}
- })
+ });
}
}
diff --git a/apps/tests/src/routes/client-only/_component.tsx b/apps/tests/src/routes/client-only/_component.tsx
index d8737ad84..687d2b85d 100644
--- a/apps/tests/src/routes/client-only/_component.tsx
+++ b/apps/tests/src/routes/client-only/_component.tsx
@@ -1,14 +1,14 @@
import { createSignal } from "solid-js";
import { isServer } from "solid-js/web";
-
export default function ClientOnlyComponent() {
- const [output, setOutput] = createSignal<{ clientWithIsServer?: boolean; }>({});
+ const [output, setOutput] = createSignal<{ clientWithIsServer?: boolean }>({});
+
+ setOutput(prev => ({ ...prev, clientWithIsServer: isServer }));
- setOutput(prev => ({ ...prev, clientWithIsServer: isServer }));
-
- return (
-
- {JSON.stringify(output())}
- )
-}
\ No newline at end of file
+ return (
+
+ {JSON.stringify(output())}
+
+ );
+}
diff --git a/apps/tests/src/routes/client-only/index.tsx b/apps/tests/src/routes/client-only/index.tsx
index e456d13ee..8e44c8d30 100644
--- a/apps/tests/src/routes/client-only/index.tsx
+++ b/apps/tests/src/routes/client-only/index.tsx
@@ -1,12 +1,11 @@
import { clientOnly } from "@solidjs/start";
-const Component = clientOnly(() => import('./_component'))
+const Component = clientOnly(() => import("./_component"));
export default function App() {
-
return (
<>
-
+
>
);
}
diff --git a/apps/tests/src/routes/generator-server-function.tsx b/apps/tests/src/routes/generator-server-function.tsx
index 03ba7b308..8757f8452 100644
--- a/apps/tests/src/routes/generator-server-function.tsx
+++ b/apps/tests/src/routes/generator-server-function.tsx
@@ -1,19 +1,19 @@
import { createSignal, onMount } from "solid-js";
-import { sayHello } from '~/functions/use-generator-server-function';
+import { sayHello } from "~/functions/use-generator-server-function";
export default function GeneratorServerFunction() {
- const [output, setOutput] = createSignal('');
+ const [output, setOutput] = createSignal("");
- onMount(async () => {
- const greetings = await sayHello();
- for await (const greeting of greetings) {
- setOutput(greeting);
- }
- });
+ onMount(async () => {
+ const greetings = await sayHello();
+ for await (const greeting of greetings) {
+ setOutput(greeting);
+ }
+ });
- return (
-
- {output()}
-
- );
-}
\ No newline at end of file
+ return (
+
+ {output()}
+
+ );
+}
diff --git a/apps/tests/src/routes/http-header.tsx b/apps/tests/src/routes/http-header.tsx
index a12d99293..8259da4b0 100644
--- a/apps/tests/src/routes/http-header.tsx
+++ b/apps/tests/src/routes/http-header.tsx
@@ -1,10 +1,10 @@
import { HttpHeader } from "@solidjs/start";
export default function HttpHeaderRoute() {
- return (
-
- Http Header
-
-
- );
+ return (
+
+ Http Header
+
+
+ );
}
diff --git a/apps/tests/src/routes/is-server-const.tsx b/apps/tests/src/routes/is-server-const.tsx
index 6c8821e17..7304392f4 100644
--- a/apps/tests/src/routes/is-server-const.tsx
+++ b/apps/tests/src/routes/is-server-const.tsx
@@ -2,18 +2,16 @@ import { createEffect, createSignal } from "solid-js";
import { serverFnWithIsServer } from "~/functions/use-is-server-const";
export default function App() {
- const [output, setOutput] = createSignal<{ serverFnWithIsServer?: boolean }>({});
+ const [output, setOutput] = createSignal<{ serverFnWithIsServer?: boolean }>({});
+ createEffect(async () => {
+ const result = await serverFnWithIsServer();
+ setOutput(prev => ({ ...prev, serverFnWithIsServer: result }));
+ });
- createEffect(async () => {
- const result = await serverFnWithIsServer();
- setOutput(prev => ({ ...prev, serverFnWithIsServer: result }));
- });
-
-
- return (
-
- {JSON.stringify(output())}
-
- );
+ return (
+
+ {JSON.stringify(output())}
+
+ );
}
diff --git a/apps/tests/src/routes/is-server-nested.tsx b/apps/tests/src/routes/is-server-nested.tsx
index 3e6086453..f670c6350 100644
--- a/apps/tests/src/routes/is-server-nested.tsx
+++ b/apps/tests/src/routes/is-server-nested.tsx
@@ -8,15 +8,13 @@ function serverFnWithIsServer() {
}
export default function App() {
- const [output, setOutput] = createSignal<{ serverFnWithIsServer?: boolean }>({});
-
+ const [output, setOutput] = createSignal<{ serverFnWithIsServer?: boolean }>({});
createEffect(async () => {
const result = await serverFnWithIsServer();
setOutput(prev => ({ ...prev, serverFnWithIsServer: result }));
});
-
return (
{JSON.stringify(output())}
diff --git a/apps/tests/src/routes/is-server-toplevel.tsx b/apps/tests/src/routes/is-server-toplevel.tsx
index b829cef9d..e145db8f3 100644
--- a/apps/tests/src/routes/is-server-toplevel.tsx
+++ b/apps/tests/src/routes/is-server-toplevel.tsx
@@ -2,15 +2,13 @@ import { createEffect, createSignal } from "solid-js";
import { serverFnWithIsServer } from "~/functions/use-is-server";
export default function App() {
- const [output, setOutput] = createSignal<{ serverFnWithIsServer?: boolean }>({});
-
+ const [output, setOutput] = createSignal<{ serverFnWithIsServer?: boolean }>({});
createEffect(async () => {
const result = await serverFnWithIsServer();
setOutput(prev => ({ ...prev, serverFnWithIsServer: result }));
});
-
return (
{JSON.stringify(output())}
diff --git a/apps/tests/src/routes/is-server-with-anon-default-export.tsx b/apps/tests/src/routes/is-server-with-anon-default-export.tsx
index 47922b2c8..a46876dfd 100644
--- a/apps/tests/src/routes/is-server-with-anon-default-export.tsx
+++ b/apps/tests/src/routes/is-server-with-anon-default-export.tsx
@@ -2,18 +2,16 @@ import { createEffect, createSignal } from "solid-js";
import { serverFnWithIsServer } from "~/functions/use-is-server-with-anon-default-export";
export default function App() {
- const [output, setOutput] = createSignal<{ serverFnWithIsServer?: boolean }>({});
+ const [output, setOutput] = createSignal<{ serverFnWithIsServer?: boolean }>({});
+ createEffect(async () => {
+ const result = await serverFnWithIsServer();
+ setOutput(prev => ({ ...prev, serverFnWithIsServer: result }));
+ });
- createEffect(async () => {
- const result = await serverFnWithIsServer();
- setOutput(prev => ({ ...prev, serverFnWithIsServer: result }));
- });
-
-
- return (
-
- {JSON.stringify(output())}
-
- );
+ return (
+
+ {JSON.stringify(output())}
+
+ );
}
diff --git a/apps/tests/src/routes/nested/(ignored)route0.tsx b/apps/tests/src/routes/nested/(ignored)route0.tsx
index be352577d..c7092deef 100644
--- a/apps/tests/src/routes/nested/(ignored)route0.tsx
+++ b/apps/tests/src/routes/nested/(ignored)route0.tsx
@@ -1,4 +1,3 @@
-
export default function nested() {
return nested route 0 ;
}
diff --git a/apps/tests/src/routes/nested/(level1)/(ignored)route1.tsx b/apps/tests/src/routes/nested/(level1)/(ignored)route1.tsx
index 471db7aaa..ec6169cd4 100644
--- a/apps/tests/src/routes/nested/(level1)/(ignored)route1.tsx
+++ b/apps/tests/src/routes/nested/(level1)/(ignored)route1.tsx
@@ -1,4 +1,3 @@
-
export default function nested() {
return nested route 1 ;
}
diff --git a/apps/tests/src/routes/nested/(level1)/(level2)/(ignored)route2.tsx b/apps/tests/src/routes/nested/(level1)/(level2)/(ignored)route2.tsx
index fcc953235..b59f52e94 100644
--- a/apps/tests/src/routes/nested/(level1)/(level2)/(ignored)route2.tsx
+++ b/apps/tests/src/routes/nested/(level1)/(level2)/(ignored)route2.tsx
@@ -1,4 +1,3 @@
-
export default function nested() {
return nested route 2 ;
}
diff --git a/apps/tests/src/routes/nested/(level1)/(level2)/route3.tsx b/apps/tests/src/routes/nested/(level1)/(level2)/route3.tsx
index 3d0eea984..61e0b761f 100644
--- a/apps/tests/src/routes/nested/(level1)/(level2)/route3.tsx
+++ b/apps/tests/src/routes/nested/(level1)/(level2)/route3.tsx
@@ -1,4 +1,3 @@
-
export default function nested() {
return nested route 3 ;
}
diff --git a/apps/tests/src/routes/node-builtin-nested.tsx b/apps/tests/src/routes/node-builtin-nested.tsx
index e1f27c2df..988de7139 100644
--- a/apps/tests/src/routes/node-builtin-nested.tsx
+++ b/apps/tests/src/routes/node-builtin-nested.tsx
@@ -1,17 +1,15 @@
-import { join } from 'node:path';
+import { join } from "node:path";
import { createEffect, createSignal } from "solid-js";
function serverFnWithNodeBuiltin() {
"use server";
- return join('can','externalize');
+ return join("can", "externalize");
}
export default function App() {
const [output, setOutput] = createSignal<{ serverFnWithNodeBuiltin?: string }>({});
-
-
createEffect(async () => {
const result = await serverFnWithNodeBuiltin();
setOutput(prev => ({ ...prev, serverFnWithNodeBuiltin: result }));
diff --git a/apps/tests/src/routes/node-builtin-toplevel.tsx b/apps/tests/src/routes/node-builtin-toplevel.tsx
index b9ca3db82..3f5fb170c 100644
--- a/apps/tests/src/routes/node-builtin-toplevel.tsx
+++ b/apps/tests/src/routes/node-builtin-toplevel.tsx
@@ -1,4 +1,3 @@
-
import { createEffect, createSignal } from "solid-js";
import { serverFnWithNodeBuiltin } from "~/functions/use-node-builtin";
diff --git a/apps/tests/src/routes/referencing-multiple-export-named-functions-in-the-same-file.tsx b/apps/tests/src/routes/referencing-multiple-export-named-functions-in-the-same-file.tsx
index 6d477bd43..3068ca105 100644
--- a/apps/tests/src/routes/referencing-multiple-export-named-functions-in-the-same-file.tsx
+++ b/apps/tests/src/routes/referencing-multiple-export-named-functions-in-the-same-file.tsx
@@ -1,4 +1,4 @@
-import { TextRenderTestComponent as ExternalCuteFaceDisplay} from "../functions/text-render-test-component";
+import { TextRenderTestComponent as ExternalCuteFaceDisplay } from "../functions/text-render-test-component";
export function TextRenderTestComponent() {
return <>(´。• ᵕ •。`) ♡>;
@@ -11,13 +11,15 @@ export function VariableImportTestComponent() {
export const testStringExport = "♡(˃͈ દ ˂͈ ༶ )";
export const testObjectExport = {
- stringValue: testStringExport,
+ stringValue: testStringExport
};
export default function () {
- return <>
-
-
-
- >;
+ return (
+ <>
+
+
+
+ >
+ );
}
diff --git a/apps/tests/src/routes/text-plain-response.tsx b/apps/tests/src/routes/text-plain-response.tsx
index 5fc11d61d..ab8fbfd8a 100644
--- a/apps/tests/src/routes/text-plain-response.tsx
+++ b/apps/tests/src/routes/text-plain-response.tsx
@@ -12,4 +12,4 @@ export default function App() {
);
-};
+}
diff --git a/apps/tests/vite.config.ts b/apps/tests/vite.config.ts
index fc5997e4f..63d9d93b2 100644
--- a/apps/tests/vite.config.ts
+++ b/apps/tests/vite.config.ts
@@ -3,8 +3,8 @@ import { solidStart } from "../../packages/start/src/config";
import { nitroV2Plugin } from "../../packages/start-nitro-v2-vite-plugin/src";
export default defineConfig({
- server: {
- port: 3000,
- },
- plugins: [solidStart(), nitroV2Plugin()],
+ server: {
+ port: 3000
+ },
+ plugins: [solidStart(), nitroV2Plugin()]
});
diff --git a/package.json b/package.json
index d432c488c..e9b55a1e9 100644
--- a/package.json
+++ b/package.json
@@ -24,16 +24,17 @@
"packages:build": "pnpm --filter=./packages/* build",
"packages:clean": "pnpx rimraf ./packages/*/node_modules/ ./packages/*/dist/",
"clean:test": "pnpx rimraf .tmp",
- "release": "pnpm build && changeset publish"
+ "release": "pnpm build && changeset publish",
+ "format": "pnpm oxfmt"
},
"devDependencies": {
"@changesets/cli": "^2.27.12",
"citty": "^0.1.5",
+ "oxfmt": "^0.14.0",
"tinyglobby": "^0.2.2",
"tippy.js": "^6.3.7",
"typescript": "^5.7.0"
},
- "dependencies": {},
"engines": {
"pnpm": "^10.8.1",
"node": ">=22"
diff --git a/packages/start-nitro-v2-vite-plugin/src/index.ts b/packages/start-nitro-v2-vite-plugin/src/index.ts
index 222d4122f..96b9ed0e8 100644
--- a/packages/start-nitro-v2-vite-plugin/src/index.ts
+++ b/packages/start-nitro-v2-vite-plugin/src/index.ts
@@ -1,206 +1,198 @@
import { promises as fsp } from "node:fs";
import path, { dirname, resolve } from "node:path";
import {
- build,
- copyPublicAssets,
- createNitro,
- type Nitro,
- type NitroConfig,
- prepare,
- prerender,
+ build,
+ copyPublicAssets,
+ createNitro,
+ type Nitro,
+ type NitroConfig,
+ prepare,
+ prerender
} from "nitropack";
import type { PluginOption, Rollup } from "vite";
let ssrBundle: Rollup.OutputBundle;
let ssrEntryFile: string;
-export type UserNitroConfig = Omit<
- NitroConfig,
- "dev" | "publicAssets" | "renderer"
->;
+export type UserNitroConfig = Omit;
export function nitroV2Plugin(nitroConfig?: UserNitroConfig): PluginOption {
- return [
- {
- name: "solid-start-vite-plugin-nitro",
- generateBundle: {
- handler(_options, bundle) {
- if (this.environment.name !== "ssr") {
- return;
- }
-
- // find entry point of ssr bundle
- let entryFile: string | undefined;
- for (const [_name, file] of Object.entries(bundle)) {
- if (file.type === "chunk") {
- if (file.isEntry) {
- if (entryFile !== undefined) {
- this.error(
- `Multiple entry points found for service "${this.environment.name}". Only one entry point is allowed.`,
- );
- }
- entryFile = file.fileName;
- }
- }
- }
- if (entryFile === undefined) {
- this.error(
- `No entry point found for service "${this.environment.name}".`,
- );
- }
- ssrEntryFile = entryFile!;
- ssrBundle = bundle;
- },
- },
- config() {
- return {
- environments: {
- ssr: {
- consumer: "server",
- build: {
- commonjsOptions: {
- include: [],
- },
- ssr: true,
- sourcemap: true,
- },
- },
- },
- builder: {
- sharedPlugins: true,
- async buildApp(builder) {
- const client = builder.environments.client;
- const server = builder.environments.ssr;
-
- if (!client) throw new Error("Client environment not found");
- if (!server) throw new Error("SSR environment not found");
-
- await builder.build(client);
- await builder.build(server);
-
- const virtualEntry = "#solid-start/entry";
- const resolvedNitroConfig: NitroConfig = {
- compatibilityDate: "2024-11-19",
- logLevel: 3,
- preset: "node-server",
- typescript: {
- generateTsConfig: false,
- generateRuntimeConfigTypes: false,
- },
- ...nitroConfig,
- dev: false,
- publicAssets: [
- {
- dir: client.config.build.outDir,
- maxAge: 31536000, // 1 year
- baseURL: "/",
- },
- ],
- renderer: virtualEntry,
- rollupConfig: {
- ...nitroConfig?.rollupConfig,
- plugins: [virtualBundlePlugin(ssrBundle) as any],
- },
- experimental: {
- ...nitroConfig?.experimental,
- asyncContext: true,
- },
- virtual: {
- ...nitroConfig?.virtual,
- [virtualEntry]: `import { fromWebHandler } from 'h3'
+ return [
+ {
+ name: "solid-start-vite-plugin-nitro",
+ generateBundle: {
+ handler(_options, bundle) {
+ if (this.environment.name !== "ssr") {
+ return;
+ }
+
+ // find entry point of ssr bundle
+ let entryFile: string | undefined;
+ for (const [_name, file] of Object.entries(bundle)) {
+ if (file.type === "chunk") {
+ if (file.isEntry) {
+ if (entryFile !== undefined) {
+ this.error(
+ `Multiple entry points found for service "${this.environment.name}". Only one entry point is allowed.`
+ );
+ }
+ entryFile = file.fileName;
+ }
+ }
+ }
+ if (entryFile === undefined) {
+ this.error(`No entry point found for service "${this.environment.name}".`);
+ }
+ ssrEntryFile = entryFile!;
+ ssrBundle = bundle;
+ }
+ },
+ config() {
+ return {
+ environments: {
+ ssr: {
+ consumer: "server",
+ build: {
+ commonjsOptions: {
+ include: []
+ },
+ ssr: true,
+ sourcemap: true
+ }
+ }
+ },
+ builder: {
+ sharedPlugins: true,
+ async buildApp(builder) {
+ const client = builder.environments.client;
+ const server = builder.environments.ssr;
+
+ if (!client) throw new Error("Client environment not found");
+ if (!server) throw new Error("SSR environment not found");
+
+ await builder.build(client);
+ await builder.build(server);
+
+ const virtualEntry = "#solid-start/entry";
+ const resolvedNitroConfig: NitroConfig = {
+ compatibilityDate: "2024-11-19",
+ logLevel: 3,
+ preset: "node-server",
+ typescript: {
+ generateTsConfig: false,
+ generateRuntimeConfigTypes: false
+ },
+ ...nitroConfig,
+ dev: false,
+ publicAssets: [
+ {
+ dir: client.config.build.outDir,
+ maxAge: 31536000, // 1 year
+ baseURL: "/"
+ }
+ ],
+ renderer: virtualEntry,
+ rollupConfig: {
+ ...nitroConfig?.rollupConfig,
+ plugins: [virtualBundlePlugin(ssrBundle) as any]
+ },
+ experimental: {
+ ...nitroConfig?.experimental,
+ asyncContext: true
+ },
+ virtual: {
+ ...nitroConfig?.virtual,
+ [virtualEntry]: `import { fromWebHandler } from 'h3'
import handler from '${ssrEntryFile}'
- export default fromWebHandler(handler.fetch)`,
- },
- };
-
- const nitro = await createNitro(resolvedNitroConfig);
-
- await buildNitroEnvironment(nitro, () => build(nitro));
- },
- },
- };
- },
- },
- nitroConfig?.preset === "netlify" && {
- name: "solid-start-nitro-netlify-fix",
+ export default fromWebHandler(handler.fetch)`
+ }
+ };
+
+ const nitro = await createNitro(resolvedNitroConfig);
+
+ await buildNitroEnvironment(nitro, () => build(nitro));
+ }
+ }
+ };
+ }
+ },
+ nitroConfig?.preset === "netlify" && {
+ name: "solid-start-nitro-netlify-fix",
enforce: "post",
- config() {
+ config() {
return {
environments: {
client: { build: { outDir: ".solid-start/client" } },
ssr: { build: { outDir: ".solid-start/server" } }
}
- }
- }
- }
- ];
+ };
+ }
+ }
+ ];
}
-export async function buildNitroEnvironment(
- nitro: Nitro,
- build: () => Promise,
-) {
- await prepare(nitro);
- await copyPublicAssets(nitro);
- await prerender(nitro);
- await build();
-
- const publicDir = nitro.options.output.publicDir;
-
- // As a part of the build process, the `.vite/` directory
- // is copied over from `node_modules/.tanstack-start/client-dist/`
- // to the `publicDir` (e.g. `.output/public/`).
- // This directory (containing the vite manifest) should not be
- // included in the final build, so we remove it here.
- const viteDir = path.resolve(publicDir, ".vite");
- if (await fsp.stat(viteDir).catch(() => false)) {
- await fsp.rm(viteDir, { recursive: true, force: true });
- }
-
- await nitro.close();
+export async function buildNitroEnvironment(nitro: Nitro, build: () => Promise) {
+ await prepare(nitro);
+ await copyPublicAssets(nitro);
+ await prerender(nitro);
+ await build();
+
+ const publicDir = nitro.options.output.publicDir;
+
+ // As a part of the build process, the `.vite/` directory
+ // is copied over from `node_modules/.tanstack-start/client-dist/`
+ // to the `publicDir` (e.g. `.output/public/`).
+ // This directory (containing the vite manifest) should not be
+ // included in the final build, so we remove it here.
+ const viteDir = path.resolve(publicDir, ".vite");
+ if (await fsp.stat(viteDir).catch(() => false)) {
+ await fsp.rm(viteDir, { recursive: true, force: true });
+ }
+
+ await nitro.close();
}
function virtualBundlePlugin(ssrBundle: Rollup.OutputBundle): PluginOption {
- type VirtualModule = { code: string; map: string | null };
- const _modules = new Map();
-
- // group chunks and source maps
- for (const [fileName, content] of Object.entries(ssrBundle)) {
- if (content.type === "chunk") {
- const virtualModule: VirtualModule = {
- code: content.code,
- map: null,
- };
- const maybeMap = ssrBundle[`${fileName}.map`];
- if (maybeMap && maybeMap.type === "asset") {
- virtualModule.map = maybeMap.source as string;
- }
- _modules.set(fileName, virtualModule);
- _modules.set(resolve(fileName), virtualModule);
- }
- }
-
- return {
- name: "virtual-bundle",
- resolveId(id, importer) {
- if (_modules.has(id)) {
- return resolve(id);
- }
-
- if (importer) {
- const resolved = resolve(dirname(importer), id);
- if (_modules.has(resolved)) {
- return resolved;
- }
- }
- return null;
- },
- load(id) {
- const m = _modules.get(id);
- if (!m) {
- return null;
- }
- return m;
- },
- };
+ type VirtualModule = { code: string; map: string | null };
+ const _modules = new Map();
+
+ // group chunks and source maps
+ for (const [fileName, content] of Object.entries(ssrBundle)) {
+ if (content.type === "chunk") {
+ const virtualModule: VirtualModule = {
+ code: content.code,
+ map: null
+ };
+ const maybeMap = ssrBundle[`${fileName}.map`];
+ if (maybeMap && maybeMap.type === "asset") {
+ virtualModule.map = maybeMap.source as string;
+ }
+ _modules.set(fileName, virtualModule);
+ _modules.set(resolve(fileName), virtualModule);
+ }
+ }
+
+ return {
+ name: "virtual-bundle",
+ resolveId(id, importer) {
+ if (_modules.has(id)) {
+ return resolve(id);
+ }
+
+ if (importer) {
+ const resolved = resolve(dirname(importer), id);
+ if (_modules.has(resolved)) {
+ return resolved;
+ }
+ }
+ return null;
+ },
+ load(id) {
+ const m = _modules.get(id);
+ if (!m) {
+ return null;
+ }
+ return m;
+ }
+ };
}
diff --git a/packages/start/src/config/constants.ts b/packages/start/src/config/constants.ts
index 2dbf16159..93561604f 100644
--- a/packages/start/src/config/constants.ts
+++ b/packages/start/src/config/constants.ts
@@ -16,4 +16,4 @@ export const VIRTUAL_MODULES = {
export const VITE_ENVIRONMENTS = {
client: "client",
server: "ssr"
-}
+};
diff --git a/packages/start/src/config/dev-server.ts b/packages/start/src/config/dev-server.ts
index 2913d0dff..42ddb62b1 100644
--- a/packages/start/src/config/dev-server.ts
+++ b/packages/start/src/config/dev-server.ts
@@ -1,84 +1,80 @@
import { NodeRequest, sendNodeResponse } from "srvx/node";
import {
- type Connect,
- isRunnableDevEnvironment,
- type PluginOption,
- type ViteDevServer,
+ type Connect,
+ isRunnableDevEnvironment,
+ type PluginOption,
+ type ViteDevServer
} from "vite";
import { VITE_ENVIRONMENTS } from "./constants.ts";
export function devServer(): Array {
- return [
- {
- name: "solid-start-dev-server",
- configureServer(viteDevServer) {
- (globalThis as any).VITE_DEV_SERVER = viteDevServer;
- return async () => {
- if (viteDevServer.config.server.middlewareMode) return
+ return [
+ {
+ name: "solid-start-dev-server",
+ configureServer(viteDevServer) {
+ (globalThis as any).VITE_DEV_SERVER = viteDevServer;
+ return async () => {
+ if (viteDevServer.config.server.middlewareMode) return;
- const serverEnv =
- viteDevServer.environments[VITE_ENVIRONMENTS.server];
+ const serverEnv = viteDevServer.environments[VITE_ENVIRONMENTS.server];
- if (!serverEnv) throw new Error("Server environment not found");
- if (
- // do not check via `isFetchableDevEnvironment` since nitro does implement the `FetchableDevEnvironment` interface but not via inheritance (which this helper checks)
- "dispatchFetch" in serverEnv
- )
- return;
- // another plugin is controlling the dev server
- if (!isRunnableDevEnvironment(serverEnv)) {
+ if (!serverEnv) throw new Error("Server environment not found");
+ if (
+ // do not check via `isFetchableDevEnvironment` since nitro does implement the `FetchableDevEnvironment` interface but not via inheritance (which this helper checks)
+ "dispatchFetch" in serverEnv
+ )
return;
- }
+ // another plugin is controlling the dev server
+ if (!isRunnableDevEnvironment(serverEnv)) {
+ return;
+ }
globalThis.USING_SOLID_START_DEV_SERVER = true;
- removeHtmlMiddlewares(viteDevServer);
+ removeHtmlMiddlewares(viteDevServer);
- viteDevServer.middlewares.use(async (req, res) => {
- if (req.originalUrl) {
- req.url = req.originalUrl;
- }
- const webReq = new NodeRequest({ req, res });
+ viteDevServer.middlewares.use(async (req, res) => {
+ if (req.originalUrl) {
+ req.url = req.originalUrl;
+ }
+ const webReq = new NodeRequest({ req, res });
- try {
- const serverEntry: {
- default: { fetch: (req: Request) => Promise };
- } = await serverEnv.runner.import("./src/entry-server.tsx");
+ try {
+ const serverEntry: {
+ default: { fetch: (req: Request) => Promise };
+ } = await serverEnv.runner.import("./src/entry-server.tsx");
- const webRes = await serverEntry.default.fetch(webReq);
+ const webRes = await serverEntry.default.fetch(webReq);
- return sendNodeResponse(res, webRes);
- } catch (e: unknown) {
- console.error(e);
- viteDevServer.ssrFixStacktrace(e as Error);
+ return sendNodeResponse(res, webRes);
+ } catch (e: unknown) {
+ console.error(e);
+ viteDevServer.ssrFixStacktrace(e as Error);
- if (
- webReq.headers.get("content-type")?.includes("application/json")
- ) {
- return sendNodeResponse(
- res,
- Response.json(
- {
- status: 500,
- error: "Internal Server Error",
- message:
- "An unexpected error occurred. Please try again later.",
- timestamp: new Date().toISOString(),
- },
- {
- status: 500,
- headers: {
- "Content-Type": "application/json",
- },
- },
- ),
- );
- }
+ if (webReq.headers.get("content-type")?.includes("application/json")) {
+ return sendNodeResponse(
+ res,
+ Response.json(
+ {
+ status: 500,
+ error: "Internal Server Error",
+ message: "An unexpected error occurred. Please try again later.",
+ timestamp: new Date().toISOString()
+ },
+ {
+ status: 500,
+ headers: {
+ "Content-Type": "application/json"
+ }
+ }
+ )
+ );
+ }
- return sendNodeResponse(
- res,
- new Response(
- `
+ return sendNodeResponse(
+ res,
+ new Response(
+ `
@@ -87,26 +83,26 @@ export function devServer(): Array {
`,
- {
- status: 500,
- headers: { "Content-Type": "text/html" },
- },
- ),
- );
- }
- });
- };
- },
- },
- ];
+ {
+ status: 500,
+ headers: { "Content-Type": "text/html" }
+ }
+ )
+ );
+ }
+ });
+ };
+ }
+ }
+ ];
}
/**
@@ -115,21 +111,21 @@ export function devServer(): Array {
* @param server
*/
function removeHtmlMiddlewares(server: ViteDevServer) {
- const html_middlewares = [
- "viteIndexHtmlMiddleware",
- "vite404Middleware",
- "viteSpaFallbackMiddleware",
- ];
- for (let i = server.middlewares.stack.length - 1; i > 0; i--) {
- if (
- html_middlewares.includes(
- // @ts-expect-error
- server.middlewares.stack[i].handle.name,
- )
- ) {
- server.middlewares.stack.splice(i, 1);
- }
- }
+ const html_middlewares = [
+ "viteIndexHtmlMiddleware",
+ "vite404Middleware",
+ "viteSpaFallbackMiddleware"
+ ];
+ for (let i = server.middlewares.stack.length - 1; i > 0; i--) {
+ if (
+ html_middlewares.includes(
+ // @ts-expect-error
+ server.middlewares.stack[i].handle.name
+ )
+ ) {
+ server.middlewares.stack.splice(i, 1);
+ }
+ }
}
/**
@@ -139,11 +135,11 @@ function removeHtmlMiddlewares(server: ViteDevServer) {
* @returns
*/
function prepareError(req: Connect.IncomingMessage, error: unknown) {
- const e = error as Error;
- return {
- message: `An error occured while server rendering ${req.url}:\n\n\t${
- typeof e === "string" ? e : e.message
- } `,
- stack: typeof e === "string" ? "" : e.stack,
- };
+ const e = error as Error;
+ return {
+ message: `An error occured while server rendering ${req.url}:\n\n\t${
+ typeof e === "string" ? e : e.message
+ } `,
+ stack: typeof e === "string" ? "" : e.stack
+ };
}
diff --git a/packages/start/src/config/fs-router.ts b/packages/start/src/config/fs-router.ts
index 668d61a95..17011d95b 100644
--- a/packages/start/src/config/fs-router.ts
+++ b/packages/start/src/config/fs-router.ts
@@ -1,177 +1,162 @@
import type { ExportSpecifier } from "es-module-lexer";
import {
- analyzeModule,
- BaseFileSystemRouter,
- cleanPath,
- type FileSystemRouterConfig,
+ analyzeModule,
+ BaseFileSystemRouter,
+ cleanPath,
+ type FileSystemRouterConfig
} from "./fs-routes/router.ts";
export class SolidStartClientFileRouter extends BaseFileSystemRouter {
- toPath(src: string) {
- const routePath = cleanPath(src, this.config)
- // remove the initial slash
- .slice(1)
- .replace(/index$/, "")
- .replace(/\[([^/]+)\]/g, (_, m) => {
- if (m.length > 3 && m.startsWith("...")) {
- return `*${m.slice(3)}`;
- }
- if (m.length > 2 && m.startsWith("[") && m.endsWith("]")) {
- return `:${m.slice(1, -1)}?`;
- }
- return `:${m}`;
- });
+ toPath(src: string) {
+ const routePath = cleanPath(src, this.config)
+ // remove the initial slash
+ .slice(1)
+ .replace(/index$/, "")
+ .replace(/\[([^/]+)\]/g, (_, m) => {
+ if (m.length > 3 && m.startsWith("...")) {
+ return `*${m.slice(3)}`;
+ }
+ if (m.length > 2 && m.startsWith("[") && m.endsWith("]")) {
+ return `:${m.slice(1, -1)}?`;
+ }
+ return `:${m}`;
+ });
- return routePath?.length > 0 ? `/${routePath}` : "/";
- }
+ return routePath?.length > 0 ? `/${routePath}` : "/";
+ }
- toRoute(src: string) {
- const path = this.toPath(src);
+ toRoute(src: string) {
+ const path = this.toPath(src);
- if (src.endsWith(".md") || src.endsWith(".mdx")) {
- return {
- page: true,
- $component: {
- src: src,
- pick: ["$css"],
- },
- $$route: undefined,
- path,
- // filePath: src
- };
- }
+ if (src.endsWith(".md") || src.endsWith(".mdx")) {
+ return {
+ page: true,
+ $component: {
+ src: src,
+ pick: ["$css"]
+ },
+ $$route: undefined,
+ path
+ // filePath: src
+ };
+ }
- const [_, exports] = analyzeModule(src);
- const hasDefault = !!exports.find((e) => e.n === "default");
- const hasRouteConfig = !!exports.find((e) => e.n === "route");
- if (hasDefault) {
- return {
- page: true,
- $component: {
- src: src,
- pick: [
- ...exports
- .filter((e) => e.n === e.ln && e.n !== "route")
- .map((e) => e.n),
- "default",
- "$css",
- ],
- },
- $$route: hasRouteConfig
- ? {
- src: src,
- pick: ["route"],
- }
- : undefined,
- path,
- // filePath: src
- };
- }
- }
+ const [_, exports] = analyzeModule(src);
+ const hasDefault = !!exports.find(e => e.n === "default");
+ const hasRouteConfig = !!exports.find(e => e.n === "route");
+ if (hasDefault) {
+ return {
+ page: true,
+ $component: {
+ src: src,
+ pick: [
+ ...exports.filter(e => e.n === e.ln && e.n !== "route").map(e => e.n),
+ "default",
+ "$css"
+ ]
+ },
+ $$route: hasRouteConfig
+ ? {
+ src: src,
+ pick: ["route"]
+ }
+ : undefined,
+ path
+ // filePath: src
+ };
+ }
+ }
}
-const HTTP_METHODS = [
- "HEAD",
- "GET",
- "POST",
- "PUT",
- "DELETE",
- "PATCH",
- "OPTIONS",
-];
+const HTTP_METHODS = ["HEAD", "GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"];
function createHTTPHandlers(src: string, exports: readonly ExportSpecifier[]) {
- const handlers: Record = {};
- for (const exp of exports) {
- if (HTTP_METHODS.includes(exp.n)) {
- handlers[`$${exp.n}`] = {
- src: src,
- pick: [exp.n],
- };
- if (exp.n === "GET" && !exports.find((exp) => exp.n === "HEAD")) {
- handlers.$HEAD = {
- src: src,
- pick: [exp.n],
- };
- }
- }
- }
+ const handlers: Record = {};
+ for (const exp of exports) {
+ if (HTTP_METHODS.includes(exp.n)) {
+ handlers[`$${exp.n}`] = {
+ src: src,
+ pick: [exp.n]
+ };
+ if (exp.n === "GET" && !exports.find(exp => exp.n === "HEAD")) {
+ handlers.$HEAD = {
+ src: src,
+ pick: [exp.n]
+ };
+ }
+ }
+ }
- return handlers;
+ return handlers;
}
export class SolidStartServerFileRouter extends BaseFileSystemRouter {
- declare config: FileSystemRouterConfig & { dataOnly?: boolean };
+ declare config: FileSystemRouterConfig & { dataOnly?: boolean };
- constructor(config: FileSystemRouterConfig & { dataOnly?: boolean }) {
- super(config);
- }
+ constructor(config: FileSystemRouterConfig & { dataOnly?: boolean }) {
+ super(config);
+ }
- toPath(src: string) {
- const routePath = cleanPath(src, this.config)
- // remove the initial slash
- .slice(1)
- .replace(/index$/, "")
- .replace(/\[([^/]+)\]/g, (_, m) => {
- if (m.length > 3 && m.startsWith("...")) {
- return `*${m.slice(3)}`;
- }
- if (m.length > 2 && m.startsWith("[") && m.endsWith("]")) {
- return `:${m.slice(1, -1)}?`;
- }
- return `:${m}`;
- });
+ toPath(src: string) {
+ const routePath = cleanPath(src, this.config)
+ // remove the initial slash
+ .slice(1)
+ .replace(/index$/, "")
+ .replace(/\[([^/]+)\]/g, (_, m) => {
+ if (m.length > 3 && m.startsWith("...")) {
+ return `*${m.slice(3)}`;
+ }
+ if (m.length > 2 && m.startsWith("[") && m.endsWith("]")) {
+ return `:${m.slice(1, -1)}?`;
+ }
+ return `:${m}`;
+ });
- return routePath?.length > 0 ? `/${routePath}` : "/";
- }
+ return routePath?.length > 0 ? `/${routePath}` : "/";
+ }
- toRoute(src: string) {
- const path = this.toPath(src);
- if (src.endsWith(".md") || src.endsWith(".mdx")) {
- return {
- page: true,
- $component: {
- src: src,
- pick: ["$css"],
- },
- $$route: undefined,
- path,
- };
- }
+ toRoute(src: string) {
+ const path = this.toPath(src);
+ if (src.endsWith(".md") || src.endsWith(".mdx")) {
+ return {
+ page: true,
+ $component: {
+ src: src,
+ pick: ["$css"]
+ },
+ $$route: undefined,
+ path
+ };
+ }
- const [_, exports] = analyzeModule(src);
- const hasRouteConfig = exports.find((e) => e.n === "route");
- const hasDefault = !!exports.find((e) => e.n === "default");
- const hasAPIRoutes = !!exports.find((exp) => HTTP_METHODS.includes(exp.n));
- if (hasDefault || hasAPIRoutes) {
- return {
- page: hasDefault,
- $component:
- !this.config.dataOnly && hasDefault
- ? {
- src: src,
- pick: [
- ...exports
- .filter(
- (e) =>
- e.n === e.ln &&
- e.n !== "route" &&
- !HTTP_METHODS.includes(e.n),
- )
- .map((e) => e.n),
- "default",
- "$css",
- ],
- }
- : undefined,
- $$route: hasRouteConfig
- ? {
- src: src,
- pick: ["route"],
- }
- : undefined,
- ...createHTTPHandlers(src, exports),
- path,
- };
- }
- }
+ const [_, exports] = analyzeModule(src);
+ const hasRouteConfig = exports.find(e => e.n === "route");
+ const hasDefault = !!exports.find(e => e.n === "default");
+ const hasAPIRoutes = !!exports.find(exp => HTTP_METHODS.includes(exp.n));
+ if (hasDefault || hasAPIRoutes) {
+ return {
+ page: hasDefault,
+ $component:
+ !this.config.dataOnly && hasDefault
+ ? {
+ src: src,
+ pick: [
+ ...exports
+ .filter(e => e.n === e.ln && e.n !== "route" && !HTTP_METHODS.includes(e.n))
+ .map(e => e.n),
+ "default",
+ "$css"
+ ]
+ }
+ : undefined,
+ $$route: hasRouteConfig
+ ? {
+ src: src,
+ pick: ["route"]
+ }
+ : undefined,
+ ...createHTTPHandlers(src, exports),
+ path
+ };
+ }
+ }
}
diff --git a/packages/start/src/config/fs-routes/fs-watcher.ts b/packages/start/src/config/fs-routes/fs-watcher.ts
index 5e7543293..c9fbab3b7 100644
--- a/packages/start/src/config/fs-routes/fs-watcher.ts
+++ b/packages/start/src/config/fs-routes/fs-watcher.ts
@@ -1,81 +1,77 @@
import type {
- EnvironmentModuleNode,
- FSWatcher,
- ModuleGraph,
- ModuleNode,
- PluginOption,
- ViteDevServer,
+ EnvironmentModuleNode,
+ FSWatcher,
+ ModuleGraph,
+ ModuleNode,
+ PluginOption,
+ ViteDevServer
} from "vite";
import { moduleId } from "./index.ts";
import type { BaseFileSystemRouter } from "./router.ts";
interface CompiledRouter {
- removeRoute(path: string): void;
- addRoute(path: string): void;
- updateRoute(path: string): void;
- addEventListener(event: "reload", handler: () => void): void;
- removeEventListener(event: "reload", handler: () => void): void;
+ removeRoute(path: string): void;
+ addRoute(path: string): void;
+ updateRoute(path: string): void;
+ addEventListener(event: "reload", handler: () => void): void;
+ removeEventListener(event: "reload", handler: () => void): void;
}
function setupWatcher(watcher: FSWatcher, routes: CompiledRouter): void {
- watcher.on("unlink", (path) => routes.removeRoute(path));
- watcher.on("add", (path) => routes.addRoute(path));
- watcher.on("change", (path) => routes.updateRoute(path));
+ watcher.on("unlink", path => routes.removeRoute(path));
+ watcher.on("add", path => routes.addRoute(path));
+ watcher.on("change", path => routes.updateRoute(path));
}
function createRoutesReloader(
- server: ViteDevServer,
- routes: CompiledRouter,
- environment: "client" | "ssr",
+ server: ViteDevServer,
+ routes: CompiledRouter,
+ environment: "client" | "ssr"
): () => void {
- routes.addEventListener("reload", handleRoutesReload);
- return () => routes.removeEventListener("reload", handleRoutesReload);
+ routes.addEventListener("reload", handleRoutesReload);
+ return () => routes.removeEventListener("reload", handleRoutesReload);
- function handleRoutesReload(): void {
- if (environment === "ssr") {
- // Handle server environment HMR reload
- const serverEnv = server.environments.server;
- if (serverEnv && serverEnv.moduleGraph) {
- const mod: EnvironmentModuleNode | undefined =
- serverEnv.moduleGraph.getModuleById(moduleId);
- if (mod) {
- const seen = new Set();
- serverEnv.moduleGraph.invalidateModule(mod, seen);
- }
- }
- } else {
- // Handle client environment HMR reload
- const { moduleGraph }: { moduleGraph: ModuleGraph } = server;
- const mod: ModuleNode | undefined = moduleGraph.getModuleById(moduleId);
- if (mod) {
- const seen = new Set();
- moduleGraph.invalidateModule(mod, seen);
- server.reloadModule(mod);
- }
- }
+ function handleRoutesReload(): void {
+ if (environment === "ssr") {
+ // Handle server environment HMR reload
+ const serverEnv = server.environments.server;
+ if (serverEnv && serverEnv.moduleGraph) {
+ const mod: EnvironmentModuleNode | undefined =
+ serverEnv.moduleGraph.getModuleById(moduleId);
+ if (mod) {
+ const seen = new Set();
+ serverEnv.moduleGraph.invalidateModule(mod, seen);
+ }
+ }
+ } else {
+ // Handle client environment HMR reload
+ const { moduleGraph }: { moduleGraph: ModuleGraph } = server;
+ const mod: ModuleNode | undefined = moduleGraph.getModuleById(moduleId);
+ if (mod) {
+ const seen = new Set();
+ moduleGraph.invalidateModule(mod, seen);
+ server.reloadModule(mod);
+ }
+ }
- if (!server.hot) {
- server.ws.send({ type: "full-reload" });
- }
- }
+ if (!server.hot) {
+ server.ws.send({ type: "full-reload" });
+ }
+ }
}
export const fileSystemWatcher = (
- routers: Record<"client" | "ssr", BaseFileSystemRouter>,
+ routers: Record<"client" | "ssr", BaseFileSystemRouter>
): PluginOption => {
- const plugin: PluginOption = {
- name: "fs-watcher",
- async configureServer(server: ViteDevServer) {
- Object.keys(routers).forEach((environment) => {
- const router = (globalThis as any).ROUTERS[environment];
- setupWatcher(server.watcher, router);
- createRoutesReloader(
- server,
- router,
- environment as keyof typeof routers,
- );
- });
- },
- };
- return plugin;
+ const plugin: PluginOption = {
+ name: "fs-watcher",
+ async configureServer(server: ViteDevServer) {
+ Object.keys(routers).forEach(environment => {
+ const router = (globalThis as any).ROUTERS[environment];
+ setupWatcher(server.watcher, router);
+ createRoutesReloader(server, router, environment as keyof typeof routers);
+ });
+ }
+ };
+ return plugin;
};
diff --git a/packages/start/src/config/fs-routes/index.ts b/packages/start/src/config/fs-routes/index.ts
index 81bad92fe..584e17b0d 100644
--- a/packages/start/src/config/fs-routes/index.ts
+++ b/packages/start/src/config/fs-routes/index.ts
@@ -8,131 +8,129 @@ import { treeShake } from "./tree-shake.ts";
export const moduleId = "solid-start:routes";
export interface FsRoutesArgs {
- routers: Record<"client" | "ssr", BaseFileSystemRouter>;
+ routers: Record<"client" | "ssr", BaseFileSystemRouter>;
}
export function fsRoutes({ routers }: FsRoutesArgs): Array {
- (globalThis as any).ROUTERS = routers;
-
- return [
- {
- name: "solid-start-fs-routes",
- enforce: "pre",
- resolveId(id) {
- if (id === moduleId) return id;
- },
- async load(id) {
- const root = this.environment.config.root;
- const isBuild = this.environment.mode === "build";
-
- if (id !== moduleId) return;
- const js = jsCode();
-
- const router = (globalThis as any).ROUTERS[this.environment.name];
-
- const routes = await router.getRoutes();
-
- let routesCode = JSON.stringify(routes ?? [], (k, v) => {
- if (v === undefined) return undefined;
-
- if (k.startsWith("$$")) {
- const buildId = `${v.src}?${v.pick.map((p: any) => `pick=${p}`).join("&")}`;
-
- /**
- * @type {{ [key: string]: string }}
- */
- const refs: Record = {};
- for (var pick of v.pick) {
- refs[pick] = js.addNamedImport(pick, buildId);
- }
- return {
- require: `_$() => ({ ${Object.entries(refs)
- .map(([pick, namedImport]) => `'${pick}': ${namedImport}`)
- .join(", ")} })$_`,
- // src: isBuild ? relative(root, buildId) : buildId
- };
- } else if (k.startsWith("$")) {
- const buildId = `${v.src}?${v.pick.map((p: any) => `pick=${p}`).join("&")}`;
- return {
- src: relative(root, buildId),
- build: isBuild
- ? `_$() => import(/* @vite-ignore */ '${buildId}')$_`
- : undefined,
- import: `_$() => import(/* @vite-ignore */ '${buildId}')$_`
- };
- }
- return v;
- });
-
- routesCode = routesCode.replaceAll('"_$(', "(").replaceAll(')$_"', ")");
-
- const code = `
+ (globalThis as any).ROUTERS = routers;
+
+ return [
+ {
+ name: "solid-start-fs-routes",
+ enforce: "pre",
+ resolveId(id) {
+ if (id === moduleId) return id;
+ },
+ async load(id) {
+ const root = this.environment.config.root;
+ const isBuild = this.environment.mode === "build";
+
+ if (id !== moduleId) return;
+ const js = jsCode();
+
+ const router = (globalThis as any).ROUTERS[this.environment.name];
+
+ const routes = await router.getRoutes();
+
+ let routesCode = JSON.stringify(routes ?? [], (k, v) => {
+ if (v === undefined) return undefined;
+
+ if (k.startsWith("$$")) {
+ const buildId = `${v.src}?${v.pick.map((p: any) => `pick=${p}`).join("&")}`;
+
+ /**
+ * @type {{ [key: string]: string }}
+ */
+ const refs: Record = {};
+ for (var pick of v.pick) {
+ refs[pick] = js.addNamedImport(pick, buildId);
+ }
+ return {
+ require: `_$() => ({ ${Object.entries(refs)
+ .map(([pick, namedImport]) => `'${pick}': ${namedImport}`)
+ .join(", ")} })$_`
+ // src: isBuild ? relative(root, buildId) : buildId
+ };
+ } else if (k.startsWith("$")) {
+ const buildId = `${v.src}?${v.pick.map((p: any) => `pick=${p}`).join("&")}`;
+ return {
+ src: relative(root, buildId),
+ build: isBuild ? `_$() => import(/* @vite-ignore */ '${buildId}')$_` : undefined,
+ import: `_$() => import(/* @vite-ignore */ '${buildId}')$_`
+ };
+ }
+ return v;
+ });
+
+ routesCode = routesCode.replaceAll('"_$(', "(").replaceAll(')$_"', ")");
+
+ const code = `
${js.getImportStatements()}
export default ${routesCode}`;
- return code;
- },
- },
- treeShake(),
- fileSystemWatcher(routers),
- ];
+ return code;
+ }
+ },
+ treeShake(),
+ fileSystemWatcher(routers)
+ ];
}
function jsCode() {
- const imports = new Map();
- let vars = 0;
-
- function addImport(p: any) {
- let id = imports.get(p);
- if (!id) {
- id = {};
- imports.set(p, id);
- }
-
- const d = "routeData" + vars++;
- id["default"] = d;
- return d;
- }
-
- function addNamedImport(name: string | number, p: any) {
- let id = imports.get(p);
- if (!id) {
- id = {};
- imports.set(p, id);
- }
-
- const d = "routeData" + vars++;
- id[name] = d;
- return d;
- }
-
- const getNamedExport = (p: any) => {
- const id = imports.get(p);
-
- delete id["default"];
-
- return Object.keys(id).length > 0
- ? `{ ${Object.keys(id)
- .map((k) => `${k} as ${id[k]}`)
- .join(", ")} }`
- : "";
- };
-
- const getImportStatements = () => {
- return `${[...imports.keys()]
- .map(
- (i) =>
- `import ${
- imports.get(i).default
- ? `${imports.get(i).default}${Object.keys(imports.get(i)).length > 1 ? ", " : ""}`
- : ""
- } ${getNamedExport(i)} from '${i}';`,
- )
- .join("\n")}`;
- };
-
- return {
- addImport,
- addNamedImport,
- getImportStatements,
- };
+ const imports = new Map();
+ let vars = 0;
+
+ function addImport(p: any) {
+ let id = imports.get(p);
+ if (!id) {
+ id = {};
+ imports.set(p, id);
+ }
+
+ const d = "routeData" + vars++;
+ id["default"] = d;
+ return d;
+ }
+
+ function addNamedImport(name: string | number, p: any) {
+ let id = imports.get(p);
+ if (!id) {
+ id = {};
+ imports.set(p, id);
+ }
+
+ const d = "routeData" + vars++;
+ id[name] = d;
+ return d;
+ }
+
+ const getNamedExport = (p: any) => {
+ const id = imports.get(p);
+
+ delete id["default"];
+
+ return Object.keys(id).length > 0
+ ? `{ ${Object.keys(id)
+ .map(k => `${k} as ${id[k]}`)
+ .join(", ")} }`
+ : "";
+ };
+
+ const getImportStatements = () => {
+ return `${[...imports.keys()]
+ .map(
+ i =>
+ `import ${
+ imports.get(i).default
+ ? `${imports.get(i).default}${Object.keys(imports.get(i)).length > 1 ? ", " : ""}`
+ : ""
+ } ${getNamedExport(i)} from '${i}';`
+ )
+ .join("\n")}`;
+ };
+
+ return {
+ addImport,
+ addNamedImport,
+ getImportStatements
+ };
}
diff --git a/packages/start/src/config/fs-routes/tree-shake.ts b/packages/start/src/config/fs-routes/tree-shake.ts
index b27ff1c86..63019292f 100644
--- a/packages/start/src/config/fs-routes/tree-shake.ts
+++ b/packages/start/src/config/fs-routes/tree-shake.ts
@@ -9,384 +9,363 @@ import { basename } from "pathe";
import type { Plugin, ResolvedConfig, ViteDevServer } from "vite";
type State = Omit & {
- opts: { pick: string[] };
- refs: Set;
- done: boolean;
+ opts: { pick: string[] };
+ refs: Set;
+ done: boolean;
};
function treeShakeTransform({ types: t }: typeof Babel): PluginObj {
- function getIdentifier(path: any) {
- const parentPath = path.parentPath;
- if (parentPath.type === "VariableDeclarator") {
- const pp = parentPath;
- const name = pp.get("id");
- return name.node.type === "Identifier" ? name : null;
- }
- if (parentPath.type === "AssignmentExpression") {
- const pp = parentPath;
- const name = pp.get("left");
- return name.node.type === "Identifier" ? name : null;
- }
- if (path.node.type === "ArrowFunctionExpression") {
- return null;
- }
- return path.node.id && path.node.id.type === "Identifier"
- ? path.get("id")
- : null;
- }
+ function getIdentifier(path: any) {
+ const parentPath = path.parentPath;
+ if (parentPath.type === "VariableDeclarator") {
+ const pp = parentPath;
+ const name = pp.get("id");
+ return name.node.type === "Identifier" ? name : null;
+ }
+ if (parentPath.type === "AssignmentExpression") {
+ const pp = parentPath;
+ const name = pp.get("left");
+ return name.node.type === "Identifier" ? name : null;
+ }
+ if (path.node.type === "ArrowFunctionExpression") {
+ return null;
+ }
+ return path.node.id && path.node.id.type === "Identifier" ? path.get("id") : null;
+ }
- function isIdentifierReferenced(ident: any) {
- const b: Binding | undefined = ident.scope.getBinding(ident.node.name);
- if (b?.referenced) {
- if (b.path.type === "FunctionDeclaration") {
- return !b.constantViolations
- .concat(b.referencePaths)
- .every((ref) => ref.findParent((p) => p === b.path));
- }
- return true;
- }
- return false;
- }
- function markFunction(path: any, state: any) {
- const ident = getIdentifier(path);
- if (ident && ident.node && isIdentifierReferenced(ident)) {
- state.refs.add(ident);
- }
- }
- function markImport(path: any, state: any) {
- const local = path.get("local");
- if (isIdentifierReferenced(local)) {
- state.refs.add(local);
- }
- }
+ function isIdentifierReferenced(ident: any) {
+ const b: Binding | undefined = ident.scope.getBinding(ident.node.name);
+ if (b?.referenced) {
+ if (b.path.type === "FunctionDeclaration") {
+ return !b.constantViolations
+ .concat(b.referencePaths)
+ .every(ref => ref.findParent(p => p === b.path));
+ }
+ return true;
+ }
+ return false;
+ }
+ function markFunction(path: any, state: any) {
+ const ident = getIdentifier(path);
+ if (ident && ident.node && isIdentifierReferenced(ident)) {
+ state.refs.add(ident);
+ }
+ }
+ function markImport(path: any, state: any) {
+ const local = path.get("local");
+ if (isIdentifierReferenced(local)) {
+ state.refs.add(local);
+ }
+ }
- return {
- visitor: {
- Program: {
- enter(path, state) {
- state.refs = new Set();
- state.done = false;
- path.traverse(
- {
- VariableDeclarator(variablePath, variableState: any) {
- if (variablePath.node.id.type === "Identifier") {
- const local = variablePath.get("id");
- if (isIdentifierReferenced(local)) {
- variableState.refs.add(local);
- }
- } else if (variablePath.node.id.type === "ObjectPattern") {
- const pattern = variablePath.get("id");
- const properties = pattern.get(
- "properties",
- ) as Array;
- properties.forEach((p) => {
- const local = p.get(
- p.node.type === "ObjectProperty"
- ? "value"
- : p.node.type === "RestElement"
- ? "argument"
- : (() => {
- throw new Error("invariant");
- })(),
- );
- if (isIdentifierReferenced(local)) {
- variableState.refs.add(local);
- }
- });
- } else if (variablePath.node.id.type === "ArrayPattern") {
- const pattern = variablePath.get("id");
- const elements = pattern.get("elements") as Array;
- elements.forEach((e) => {
- let local: NodePath;
- if (e.node && e.node.type === "Identifier") {
- local = e;
- } else if (e.node && e.node.type === "RestElement") {
- local = e.get("argument");
- } else {
- return;
- }
- if (isIdentifierReferenced(local)) {
- variableState.refs.add(local);
- }
- });
- }
- },
- ExportDefaultDeclaration(exportNamedPath) {
- // if opts.keep is true, we don't remove the routeData export
- if (state.opts.pick && !state.opts.pick.includes("default")) {
- exportNamedPath.remove();
- }
- },
- ExportNamedDeclaration(exportNamedPath) {
- // if opts.keep is false, we don't remove the routeData export
- if (!state.opts.pick) {
- return;
- }
- const specifiers = exportNamedPath.get("specifiers");
- if (specifiers.length) {
- specifiers.forEach((s) => {
- if (
- t.isIdentifier(s.node.exported)
- ? s.node.exported.name
- : state.opts.pick.includes(s.node.exported.value)
- ) {
- s.remove();
- }
- });
- if (exportNamedPath.node.specifiers.length < 1) {
- exportNamedPath.remove();
- }
- return;
- }
- const decl = exportNamedPath.get("declaration");
- if (decl == null || decl.node == null) {
- return;
- }
- switch (decl.node.type) {
- case "FunctionDeclaration": {
- const name = decl.node.id?.name;
- if (
- name &&
- state.opts.pick &&
- !state.opts.pick.includes(name)
- ) {
- exportNamedPath.remove();
- }
- break;
- }
- case "VariableDeclaration": {
- const inner = decl.get("declarations") as Array<
- NodePath
- >;
- inner.forEach((d) => {
- if (d.node.id.type !== "Identifier") {
- return;
- }
- const name = d.node.id.name;
- if (state.opts.pick && !state.opts.pick.includes(name)) {
- d.remove();
- }
- });
- break;
- }
- default: {
- break;
- }
- }
- },
- FunctionDeclaration: markFunction,
- FunctionExpression: markFunction,
- ArrowFunctionExpression: markFunction,
- ImportSpecifier: markImport,
- ImportDefaultSpecifier: markImport,
- ImportNamespaceSpecifier: markImport,
- ImportDeclaration: (path, state) => {
- if (
- path.node.source.value.endsWith(".css") &&
- state.opts.pick &&
- !state.opts.pick.includes("$css")
- ) {
- path.remove();
- }
- },
- },
- state,
- );
+ return {
+ visitor: {
+ Program: {
+ enter(path, state) {
+ state.refs = new Set();
+ state.done = false;
+ path.traverse(
+ {
+ VariableDeclarator(variablePath, variableState: any) {
+ if (variablePath.node.id.type === "Identifier") {
+ const local = variablePath.get("id");
+ if (isIdentifierReferenced(local)) {
+ variableState.refs.add(local);
+ }
+ } else if (variablePath.node.id.type === "ObjectPattern") {
+ const pattern = variablePath.get("id");
+ const properties = pattern.get("properties") as Array;
+ properties.forEach(p => {
+ const local = p.get(
+ p.node.type === "ObjectProperty"
+ ? "value"
+ : p.node.type === "RestElement"
+ ? "argument"
+ : (() => {
+ throw new Error("invariant");
+ })()
+ );
+ if (isIdentifierReferenced(local)) {
+ variableState.refs.add(local);
+ }
+ });
+ } else if (variablePath.node.id.type === "ArrayPattern") {
+ const pattern = variablePath.get("id");
+ const elements = pattern.get("elements") as Array;
+ elements.forEach(e => {
+ let local: NodePath;
+ if (e.node && e.node.type === "Identifier") {
+ local = e;
+ } else if (e.node && e.node.type === "RestElement") {
+ local = e.get("argument");
+ } else {
+ return;
+ }
+ if (isIdentifierReferenced(local)) {
+ variableState.refs.add(local);
+ }
+ });
+ }
+ },
+ ExportDefaultDeclaration(exportNamedPath) {
+ // if opts.keep is true, we don't remove the routeData export
+ if (state.opts.pick && !state.opts.pick.includes("default")) {
+ exportNamedPath.remove();
+ }
+ },
+ ExportNamedDeclaration(exportNamedPath) {
+ // if opts.keep is false, we don't remove the routeData export
+ if (!state.opts.pick) {
+ return;
+ }
+ const specifiers = exportNamedPath.get("specifiers");
+ if (specifiers.length) {
+ specifiers.forEach(s => {
+ if (
+ t.isIdentifier(s.node.exported)
+ ? s.node.exported.name
+ : state.opts.pick.includes(s.node.exported.value)
+ ) {
+ s.remove();
+ }
+ });
+ if (exportNamedPath.node.specifiers.length < 1) {
+ exportNamedPath.remove();
+ }
+ return;
+ }
+ const decl = exportNamedPath.get("declaration");
+ if (decl == null || decl.node == null) {
+ return;
+ }
+ switch (decl.node.type) {
+ case "FunctionDeclaration": {
+ const name = decl.node.id?.name;
+ if (name && state.opts.pick && !state.opts.pick.includes(name)) {
+ exportNamedPath.remove();
+ }
+ break;
+ }
+ case "VariableDeclaration": {
+ const inner = decl.get("declarations") as Array>;
+ inner.forEach(d => {
+ if (d.node.id.type !== "Identifier") {
+ return;
+ }
+ const name = d.node.id.name;
+ if (state.opts.pick && !state.opts.pick.includes(name)) {
+ d.remove();
+ }
+ });
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ },
+ FunctionDeclaration: markFunction,
+ FunctionExpression: markFunction,
+ ArrowFunctionExpression: markFunction,
+ ImportSpecifier: markImport,
+ ImportDefaultSpecifier: markImport,
+ ImportNamespaceSpecifier: markImport,
+ ImportDeclaration: (path, state) => {
+ if (
+ path.node.source.value.endsWith(".css") &&
+ state.opts.pick &&
+ !state.opts.pick.includes("$css")
+ ) {
+ path.remove();
+ }
+ }
+ },
+ state
+ );
- const refs = state.refs;
- let count = 0;
- const sweepFunction = (sweepPath: any) => {
- const ident = getIdentifier(sweepPath);
- if (
- ident &&
- ident.node &&
- refs.has(ident) &&
- !isIdentifierReferenced(ident)
- ) {
- ++count;
- if (
- t.isAssignmentExpression(sweepPath.parentPath) ||
- t.isVariableDeclarator(sweepPath.parentPath)
- ) {
- sweepPath.parentPath.remove();
- } else {
- sweepPath.remove();
- }
- }
- };
- function sweepImport(sweepPath: any) {
- const local = sweepPath.get("local");
- if (refs.has(local) && !isIdentifierReferenced(local)) {
- ++count;
- sweepPath.remove();
- if (sweepPath.parent.specifiers.length === 0) {
- sweepPath.parentPath.remove();
- }
- }
- }
- do {
- path.scope.crawl();
- count = 0;
- path.traverse({
- VariableDeclarator(variablePath) {
- if (variablePath.node.id.type === "Identifier") {
- const local = variablePath.get("id");
- if (refs.has(local) && !isIdentifierReferenced(local)) {
- ++count;
- variablePath.remove();
- }
- } else if (variablePath.node.id.type === "ObjectPattern") {
- const pattern = variablePath.get("id");
- const beforeCount = count;
- const properties = pattern.get("properties");
- properties.forEach((p) => {
- const local = p.get(
- p.node.type === "ObjectProperty"
- ? "value"
- : p.node.type === "RestElement"
- ? "argument"
- : (() => {
- throw new Error("invariant");
- })(),
- );
- if (refs.has(local) && !isIdentifierReferenced(local)) {
- ++count;
- p.remove();
- }
- });
- if (
- beforeCount !== count &&
- pattern.get("properties").length < 1
- ) {
- variablePath.remove();
- }
- } else if (variablePath.node.id.type === "ArrayPattern") {
- const pattern = variablePath.get("id");
- const beforeCount = count;
- const elements = pattern.get("elements");
- elements.forEach((e) => {
- let local: NodePath | undefined;
- if (e.node && e.node.type === "Identifier") {
- local = e;
- } else if (e.node && e.node.type === "RestElement") {
- local = e.get("argument");
- } else {
- return;
- }
- if (refs.has(local) && !isIdentifierReferenced(local)) {
- ++count;
- e.remove();
- }
- });
- if (
- beforeCount !== count &&
- pattern.get("elements").length < 1
- ) {
- variablePath.remove();
- }
- }
- },
- FunctionDeclaration: sweepFunction,
- FunctionExpression: sweepFunction,
- ArrowFunctionExpression: sweepFunction,
- ImportSpecifier: sweepImport,
- ImportDefaultSpecifier: sweepImport,
- ImportNamespaceSpecifier: sweepImport,
- });
- } while (count);
- },
- },
- },
- };
+ const refs = state.refs;
+ let count = 0;
+ const sweepFunction = (sweepPath: any) => {
+ const ident = getIdentifier(sweepPath);
+ if (ident && ident.node && refs.has(ident) && !isIdentifierReferenced(ident)) {
+ ++count;
+ if (
+ t.isAssignmentExpression(sweepPath.parentPath) ||
+ t.isVariableDeclarator(sweepPath.parentPath)
+ ) {
+ sweepPath.parentPath.remove();
+ } else {
+ sweepPath.remove();
+ }
+ }
+ };
+ function sweepImport(sweepPath: any) {
+ const local = sweepPath.get("local");
+ if (refs.has(local) && !isIdentifierReferenced(local)) {
+ ++count;
+ sweepPath.remove();
+ if (sweepPath.parent.specifiers.length === 0) {
+ sweepPath.parentPath.remove();
+ }
+ }
+ }
+ do {
+ path.scope.crawl();
+ count = 0;
+ path.traverse({
+ VariableDeclarator(variablePath) {
+ if (variablePath.node.id.type === "Identifier") {
+ const local = variablePath.get("id");
+ if (refs.has(local) && !isIdentifierReferenced(local)) {
+ ++count;
+ variablePath.remove();
+ }
+ } else if (variablePath.node.id.type === "ObjectPattern") {
+ const pattern = variablePath.get("id");
+ const beforeCount = count;
+ const properties = pattern.get("properties");
+ properties.forEach(p => {
+ const local = p.get(
+ p.node.type === "ObjectProperty"
+ ? "value"
+ : p.node.type === "RestElement"
+ ? "argument"
+ : (() => {
+ throw new Error("invariant");
+ })()
+ );
+ if (refs.has(local) && !isIdentifierReferenced(local)) {
+ ++count;
+ p.remove();
+ }
+ });
+ if (beforeCount !== count && pattern.get("properties").length < 1) {
+ variablePath.remove();
+ }
+ } else if (variablePath.node.id.type === "ArrayPattern") {
+ const pattern = variablePath.get("id");
+ const beforeCount = count;
+ const elements = pattern.get("elements");
+ elements.forEach(e => {
+ let local: NodePath | undefined;
+ if (e.node && e.node.type === "Identifier") {
+ local = e;
+ } else if (e.node && e.node.type === "RestElement") {
+ local = e.get("argument");
+ } else {
+ return;
+ }
+ if (refs.has(local) && !isIdentifierReferenced(local)) {
+ ++count;
+ e.remove();
+ }
+ });
+ if (beforeCount !== count && pattern.get("elements").length < 1) {
+ variablePath.remove();
+ }
+ }
+ },
+ FunctionDeclaration: sweepFunction,
+ FunctionExpression: sweepFunction,
+ ArrowFunctionExpression: sweepFunction,
+ ImportSpecifier: sweepImport,
+ ImportDefaultSpecifier: sweepImport,
+ ImportNamespaceSpecifier: sweepImport
+ });
+ } while (count);
+ }
+ }
+ }
+ };
}
export function treeShake(): Plugin {
- let config: ResolvedConfig;
- const cache: Record = {};
- let server: ViteDevServer;
+ let config: ResolvedConfig;
+ const cache: Record = {};
+ let server: ViteDevServer;
- async function transform(id: string, code: string) {
- const [path, queryString] = id.split("?");
- const query = new URLSearchParams(queryString);
- if (query.has("pick")) {
- const babel = await import("@babel/core");
- const transformed = await babel.transformAsync(code, {
- plugins: [[treeShakeTransform, { pick: query.getAll("pick") }]],
- parserOpts: {
- plugins: ["jsx", "typescript"],
- },
- filename: basename(id),
- ast: false,
- sourceMaps: true,
- configFile: false,
- babelrc: false,
- sourceFileName: id,
- });
+ async function transform(id: string, code: string) {
+ const [path, queryString] = id.split("?");
+ const query = new URLSearchParams(queryString);
+ if (query.has("pick")) {
+ const babel = await import("@babel/core");
+ const transformed = await babel.transformAsync(code, {
+ plugins: [[treeShakeTransform, { pick: query.getAll("pick") }]],
+ parserOpts: {
+ plugins: ["jsx", "typescript"]
+ },
+ filename: basename(id),
+ ast: false,
+ sourceMaps: true,
+ configFile: false,
+ babelrc: false,
+ sourceFileName: id
+ });
- return transformed;
- }
- }
- return {
- name: "tree-shake",
- enforce: "pre",
- configResolved(resolvedConfig) {
- config = resolvedConfig;
- },
- configureServer(s) {
- server = s;
- },
- async handleHotUpdate(ctx) {
- if (cache[ctx.file]) {
- const mods = [];
- const newCode = await ctx.read();
- for (const [id, code] of Object.entries(cache[ctx.file])) {
- const transformed = await transform(id, newCode);
- if (!transformed) continue;
+ return transformed;
+ }
+ }
+ return {
+ name: "tree-shake",
+ enforce: "pre",
+ configResolved(resolvedConfig) {
+ config = resolvedConfig;
+ },
+ configureServer(s) {
+ server = s;
+ },
+ async handleHotUpdate(ctx) {
+ if (cache[ctx.file]) {
+ const mods = [];
+ const newCode = await ctx.read();
+ for (const [id, code] of Object.entries(cache[ctx.file])) {
+ const transformed = await transform(id, newCode);
+ if (!transformed) continue;
- const { code: transformedCode } = transformed;
+ const { code: transformedCode } = transformed;
- if (transformedCode !== code) {
- const mod = server.moduleGraph.getModuleById(id);
- if (mod) mods.push(mod);
- }
+ if (transformedCode !== code) {
+ const mod = server.moduleGraph.getModuleById(id);
+ if (mod) mods.push(mod);
+ }
- cache[ctx.file] ??= {};
- cache[ctx.file][id] = transformedCode;
- // server.moduleGraph.setModuleSource(id, code);
- }
+ cache[ctx.file] ??= {};
+ cache[ctx.file][id] = transformedCode;
+ // server.moduleGraph.setModuleSource(id, code);
+ }
- return mods;
- }
- // const mods = [];
- // [...server.moduleGraph.urlToModuleMap.entries()].forEach(([url, m]) => {
- // if (m.file === ctx.file && m.id.includes("pick=")) {
- // if (!m.id.includes("pick=loader")) {
- // mods.push(m);
- // }
- // }
- // });
- // return mods;
- // // this.router.updateRoute(ctx.path);
- // }
- },
- async transform(code, id) {
- const [path, queryString] = id.split("?");
- if (!path) return;
- const query = new URLSearchParams(queryString);
- const ext = path.split(".").pop();
- if (!ext) return;
- if (query.has("pick") && ["js", "jsx", "ts", "tsx"].includes(ext)) {
- const transformed = await transform(id, code);
- if (!transformed?.code) return;
+ return mods;
+ }
+ // const mods = [];
+ // [...server.moduleGraph.urlToModuleMap.entries()].forEach(([url, m]) => {
+ // if (m.file === ctx.file && m.id.includes("pick=")) {
+ // if (!m.id.includes("pick=loader")) {
+ // mods.push(m);
+ // }
+ // }
+ // });
+ // return mods;
+ // // this.router.updateRoute(ctx.path);
+ // }
+ },
+ async transform(code, id) {
+ const [path, queryString] = id.split("?");
+ if (!path) return;
+ const query = new URLSearchParams(queryString);
+ const ext = path.split(".").pop();
+ if (!ext) return;
+ if (query.has("pick") && ["js", "jsx", "ts", "tsx"].includes(ext)) {
+ const transformed = await transform(id, code);
+ if (!transformed?.code) return;
- cache[path] ??= {};
- cache[path][id] = transformed.code;
+ cache[path] ??= {};
+ cache[path][id] = transformed.code;
- return {
- code: transformed.code,
- map: transformed.map,
- };
- }
- },
- };
+ return {
+ code: transformed.code,
+ map: transformed.map
+ };
+ }
+ }
+ };
}
diff --git a/packages/start/src/config/vite-utils.ts b/packages/start/src/config/vite-utils.ts
index de44bd9ea..bb7641c7d 100644
--- a/packages/start/src/config/vite-utils.ts
+++ b/packages/start/src/config/vite-utils.ts
@@ -16,7 +16,7 @@ export const NULL_BYTE_PLACEHOLDER = `__x00__`;
export function normalizeResolvedIdToUrl(
environment: DevEnvironment,
url: string,
- resolved: Rollup.PartialResolvedId,
+ resolved: Rollup.PartialResolvedId
): string {
const root = environment.config.root;
const depsOptimizer = environment.depsOptimizer;
@@ -64,10 +64,7 @@ export function unwrapId(id: string): string {
: id;
}
-export function normalizeViteImportAnalysisUrl(
- environment: DevEnvironment,
- id: string,
-): string {
+export function normalizeViteImportAnalysisUrl(environment: DevEnvironment, id: string): string {
let url = normalizeResolvedIdToUrl(environment, id, { id });
// https://github.com/vitejs/vite/blob/c18ce868c4d70873406e9f7d1b2d0a03264d2168/packages/vite/src/node/plugins/importAnalysis.ts#L416
@@ -101,8 +98,7 @@ export function slash(p: string): string {
return p.replace(windowsSlashRE, "/");
}
-const isWindows =
- typeof process !== "undefined" && process.platform === "win32";
+const isWindows = typeof process !== "undefined" && process.platform === "win32";
export function injectQuery(url: string, queryToInject: string): string {
const { file, postfix } = splitFileAndPostfix(url);
diff --git a/packages/start/src/env.d.ts b/packages/start/src/env.d.ts
index 3ba015c32..a2c99e4fb 100644
--- a/packages/start/src/env.d.ts
+++ b/packages/start/src/env.d.ts
@@ -5,31 +5,29 @@
/* eslint-disable @typescript-eslint/consistent-type-imports */
declare namespace App {
- export interface RequestEventLocals {
- [key: string | symbol]: any;
- }
+ export interface RequestEventLocals {
+ [key: string | symbol]: any;
+ }
}
declare module "solidstart:server-fn-manifest" {
- type ServerFn = (...args: Array) => Promise;
- export function getServerFnById(id: string): Promise;
+ type ServerFn = (...args: Array) => Promise;
+ export function getServerFnById(id: string): Promise;
}
-interface ImportMetaEnv
- extends Record<`VITE_${string}`, any>,
- SolidStartMetaEnv {
- BASE_URL: string;
- MODE: string;
- DEV: boolean;
- PROD: boolean;
- SSR: boolean;
+interface ImportMetaEnv extends Record<`VITE_${string}`, any>, SolidStartMetaEnv {
+ BASE_URL: string;
+ MODE: string;
+ DEV: boolean;
+ PROD: boolean;
+ SSR: boolean;
}
interface SolidStartMetaEnv {
- START_SSR: boolean;
- START_APP_ENTRY: string;
- START_CLIENT_ENTRY: string;
- // START_ISLANDS: boolean;
- // START_DEV_OVERLAY: boolean;
- // SERVER_BASE_URL: string;
+ START_SSR: boolean;
+ START_APP_ENTRY: string;
+ START_CLIENT_ENTRY: string;
+ // START_ISLANDS: boolean;
+ // START_DEV_OVERLAY: boolean;
+ // SERVER_BASE_URL: string;
}
diff --git a/packages/start/src/http/index.ts b/packages/start/src/http/index.ts
index e748dfb5d..e07c87563 100644
--- a/packages/start/src/http/index.ts
+++ b/packages/start/src/http/index.ts
@@ -3,121 +3,105 @@ import * as h3 from "h3";
import { getRequestEvent } from "solid-js/web";
function _setContext(event: H3Event, key: string, value: any) {
- event.context[key] = value;
+ event.context[key] = value;
}
function _getContext(event: H3Event, key: string) {
- return event.context[key];
+ return event.context[key];
}
function getEvent() {
- return getRequestEvent()!.nativeEvent;
+ return getRequestEvent()!.nativeEvent;
}
export function getWebRequest(): Request {
- return getEvent().req;
+ return getEvent().req;
}
export const HTTPEventSymbol = Symbol("$HTTPEvent");
-export function isEvent(
- obj: any,
-): obj is h3.H3Event | { [HTTPEventSymbol]: h3.H3Event } {
- return (
- typeof obj === "object" &&
- (obj instanceof h3.H3Event ||
- obj?.[HTTPEventSymbol] instanceof h3.H3Event ||
- obj?.__is_event__ === true)
- );
- // Implement logic to check if obj is an H3Event
+export function isEvent(obj: any): obj is h3.H3Event | { [HTTPEventSymbol]: h3.H3Event } {
+ return (
+ typeof obj === "object" &&
+ (obj instanceof h3.H3Event ||
+ obj?.[HTTPEventSymbol] instanceof h3.H3Event ||
+ obj?.__is_event__ === true)
+ );
+ // Implement logic to check if obj is an H3Event
}
type Tail = T extends [any, ...infer U] ? U : never;
type PrependOverload<
- TOriginal extends (...args: Array) => any,
- TOverload extends (...args: Array) => any,
+ TOriginal extends (...args: Array) => any,
+ TOverload extends (...args: Array) => any
> = TOverload & TOriginal;
// add an overload to the function without the event argument
type WrapFunction) => any> = PrependOverload<
- TFn,
- (
- ...args: Parameters extends [
- h3.HTTPEvent | h3.H3Event,
- ...infer TArgs,
- ]
- ? TArgs
- : Parameters
- ) => ReturnType
+ TFn,
+ (
+ ...args: Parameters extends [h3.HTTPEvent | h3.H3Event, ...infer TArgs]
+ ? TArgs
+ : Parameters
+ ) => ReturnType
>;
function createWrapperFunction) => any>(
- h3Function: TFn,
+ h3Function: TFn
): WrapFunction {
- return ((...args: Array) => {
- const event = args[0];
- if (!isEvent(event)) {
- args.unshift(getEvent());
- } else {
- args[0] =
- event instanceof h3.H3Event || (event as any).__is_event__
- ? event
- : event[HTTPEventSymbol];
- }
-
- return (h3Function as any)(...args);
- }) as any;
+ return ((...args: Array) => {
+ const event = args[0];
+ if (!isEvent(event)) {
+ args.unshift(getEvent());
+ } else {
+ args[0] =
+ event instanceof h3.H3Event || (event as any).__is_event__ ? event : event[HTTPEventSymbol];
+ }
+
+ return (h3Function as any)(...args);
+ }) as any;
}
// Creating wrappers for each utility and exporting them with their original names
// readRawBody => getWebRequest().text()/.arrayBuffer()
type WrappedReadBody = >(
- ...args: Tail>>
+ ...args: Tail>>
) => ReturnType>;
export const readBody = createWrapperFunction(h3.readBody) as PrependOverload<
- typeof h3.readBody,
- WrappedReadBody
+ typeof h3.readBody,
+ WrappedReadBody
>;
-type WrappedGetQuery = <
- T,
- TEventInput = Exclude, undefined>,
->(
- ...args: Tail>>
+type WrappedGetQuery = , undefined>>(
+ ...args: Tail>>
) => ReturnType>;
export const getQuery = createWrapperFunction(h3.getQuery) as PrependOverload<
- typeof h3.getQuery,
- WrappedGetQuery
+ typeof h3.getQuery,
+ WrappedGetQuery
>;
export const isMethod = createWrapperFunction(h3.isMethod);
export const isPreflightRequest = createWrapperFunction(h3.isPreflightRequest);
type WrappedGetValidatedQuery = <
- T extends HTTPEvent,
- TEventInput = InferEventInput<"query", H3Event, T>,
+ T extends HTTPEvent,
+ TEventInput = InferEventInput<"query", H3Event, T>
>(
- ...args: Tail<
- Parameters>
- >
+ ...args: Tail>>
) => ReturnType>;
-export const getValidatedQuery = createWrapperFunction(
- h3.getValidatedQuery,
-) as PrependOverload;
+export const getValidatedQuery = createWrapperFunction(h3.getValidatedQuery) as PrependOverload<
+ typeof h3.getValidatedQuery,
+ WrappedGetValidatedQuery
+>;
export const getRouterParams = createWrapperFunction(h3.getRouterParams);
export const getRouterParam = createWrapperFunction(h3.getRouterParam);
type WrappedGetValidatedRouterParams = <
- T extends HTTPEvent,
- TEventInput = InferEventInput<"routerParams", H3Event, T>,
+ T extends HTTPEvent,
+ TEventInput = InferEventInput<"routerParams", H3Event, T>
>(
- ...args: Tail<
- Parameters>
- >
+ ...args: Tail>>
) => ReturnType>;
export const getValidatedRouterParams = createWrapperFunction(
- h3.getValidatedRouterParams,
-) as PrependOverload<
- typeof h3.getValidatedRouterParams,
- WrappedGetValidatedRouterParams
->;
+ h3.getValidatedRouterParams
+) as PrependOverload;
export const assertMethod = createWrapperFunction(h3.assertMethod);
export const getRequestHeaders = createWrapperFunction(h3.getRequestHeaders);
export const getRequestHeader = createWrapperFunction(h3.getRequestHeader);
@@ -126,53 +110,46 @@ export const getRequestHost = createWrapperFunction(h3.getRequestHost);
export const getRequestProtocol = createWrapperFunction(h3.getRequestProtocol);
export const getRequestIP = createWrapperFunction(h3.getRequestIP);
export const setResponseStatus = (code?: number, text?: string) => {
- const e = getEvent();
+ const e = getEvent();
- if (e.res.status !== undefined) e.res.status = code;
- if (e.res.statusText !== undefined) e.res.statusText = text;
+ if (e.res.status !== undefined) e.res.status = code;
+ if (e.res.statusText !== undefined) e.res.statusText = text;
};
export const getResponseStatus = () => getEvent().res.status;
export const getResponseStatusText = () => getEvent().res.statusText;
-export const getResponseHeaders = () =>
- Object.fromEntries(getEvent().res.headers.entries());
-export const getResponseHeader = (name: string) =>
- getEvent().res.headers.get(name);
+export const getResponseHeaders = () => Object.fromEntries(getEvent().res.headers.entries());
+export const getResponseHeader = (name: string) => getEvent().res.headers.get(name);
export const setResponseHeaders = (values: Record) => {
- const headers = getEvent().res.headers;
- for (const [name, value] of Object.entries(values)) {
- headers.set(name, value);
- }
+ const headers = getEvent().res.headers;
+ for (const [name, value] of Object.entries(values)) {
+ headers.set(name, value);
+ }
};
export const setResponseHeader = (name: string, value: string | string[]) => {
- const headers = getEvent().res.headers;
+ const headers = getEvent().res.headers;
- (Array.isArray(value) ? value : [value]).forEach((value) => {
- headers.set(name, value);
- });
+ (Array.isArray(value) ? value : [value]).forEach(value => {
+ headers.set(name, value);
+ });
};
export const appendResponseHeaders = (values: Record) => {
- const headers = getEvent().res.headers;
- for (const [name, value] of Object.entries(values)) {
- headers.append(name, value);
- }
+ const headers = getEvent().res.headers;
+ for (const [name, value] of Object.entries(values)) {
+ headers.append(name, value);
+ }
};
-export const appendResponseHeader = (
- name: string,
- value: string | string[],
-) => {
- const headers = getEvent().res.headers;
-
- (Array.isArray(value) ? value : [value]).forEach((value) => {
- headers.append(name, value);
- });
+export const appendResponseHeader = (name: string, value: string | string[]) => {
+ const headers = getEvent().res.headers;
+
+ (Array.isArray(value) ? value : [value]).forEach(value => {
+ headers.append(name, value);
+ });
};
export const defaultContentType = (type: string) =>
- getEvent().res.headers.set("content-type", type);
+ getEvent().res.headers.set("content-type", type);
export const proxyRequest = createWrapperFunction(h3.proxyRequest);
export const fetchWithEvent = createWrapperFunction(h3.fetchWithEvent);
-export const getProxyRequestHeaders = createWrapperFunction(
- h3.getProxyRequestHeaders,
-);
+export const getProxyRequestHeaders = createWrapperFunction(h3.getProxyRequestHeaders);
export const parseCookies = createWrapperFunction(h3.parseCookies);
export const getCookie = createWrapperFunction(h3.getCookie);
@@ -181,73 +158,59 @@ export const deleteCookie = createWrapperFunction(h3.deleteCookie);
// not exported :(
type SessionDataT = Record;
type WrappedUseSession = (
- ...args: Tail>>
+ ...args: Tail>>
) => ReturnType>;
-export const useSession: WrappedUseSession = createWrapperFunction(
- h3.useSession,
-);
+export const useSession: WrappedUseSession = createWrapperFunction(h3.useSession);
type WrappedGetSession = (
- ...args: Tail>>
+ ...args: Tail>>
) => ReturnType>;
-export const getSession: WrappedGetSession = createWrapperFunction(
- h3.getSession,
-);
+export const getSession: WrappedGetSession = createWrapperFunction(h3.getSession);
type WrappedUpdateSession = (
- ...args: Tail>>
+ ...args: Tail>>
) => ReturnType>;
-export const updateSession: WrappedUpdateSession = createWrapperFunction(
- h3.updateSession,
-);
+export const updateSession: WrappedUpdateSession = createWrapperFunction(h3.updateSession);
type WrappedSealSession = (
- ...args: Tail>>
+ ...args: Tail>>
) => ReturnType>;
-export const sealSession: WrappedSealSession = createWrapperFunction(
- h3.sealSession,
-);
+export const sealSession: WrappedSealSession = createWrapperFunction(h3.sealSession);
export const unsealSession = createWrapperFunction(h3.unsealSession);
export const clearSession = createWrapperFunction(h3.clearSession);
export const handleCacheHeaders = createWrapperFunction(h3.handleCacheHeaders);
export const handleCors = createWrapperFunction(h3.handleCors);
export const appendCorsHeaders = createWrapperFunction(h3.appendCorsHeaders);
-export const appendCorsPreflightHeaders = createWrapperFunction(
- h3.appendCorsPreflightHeaders,
-);
+export const appendCorsPreflightHeaders = createWrapperFunction(h3.appendCorsPreflightHeaders);
export const appendHeader = appendResponseHeader;
export const appendHeaders = appendResponseHeaders;
export const setHeader = setResponseHeader;
export const setHeaders = setResponseHeaders;
export const getHeader = getRequestHeader;
export const getHeaders = getRequestHeaders;
-export const getRequestFingerprint = createWrapperFunction(
- h3.getRequestFingerprint,
-);
+export const getRequestFingerprint = createWrapperFunction(h3.getRequestFingerprint);
export const getRequestWebStream = () => getEvent().req.body;
export const readFormData = () => getEvent().req.formData();
type WrappedReadValidatedBody = <
- T extends HTTPEvent,
- TEventInput = InferEventInput<"body", H3Event, T>,
+ T extends HTTPEvent,
+ TEventInput = InferEventInput<"body", H3Event, T>
>(
- ...args: Tail<
- Parameters>
- >
+ ...args: Tail>>
) => ReturnType>;
-export const readValidatedBody = createWrapperFunction(
- h3.readValidatedBody,
-) as PrependOverload;
+export const readValidatedBody = createWrapperFunction(h3.readValidatedBody) as PrependOverload<
+ typeof h3.readValidatedBody,
+ WrappedReadValidatedBody
+>;
export const getContext = createWrapperFunction(_getContext);
export const setContext = createWrapperFunction(_setContext);
-export const removeResponseHeader = (name: string) =>
- getEvent().res.headers.delete(name);
+export const removeResponseHeader = (name: string) => getEvent().res.headers.delete(name);
export const clearResponseHeaders = (headerNames?: string[]) => {
- const headers = getEvent().res.headers;
-
- if (headerNames && headerNames.length > 0) {
- for (const name of headerNames) {
- headers.delete(name);
- }
- } else {
- for (const name of headers.keys()) {
- headers.delete(name);
- }
- }
+ const headers = getEvent().res.headers;
+
+ if (headerNames && headerNames.length > 0) {
+ for (const name of headerNames) {
+ headers.delete(name);
+ }
+ } else {
+ for (const name of headers.keys()) {
+ headers.delete(name);
+ }
+ }
};
diff --git a/packages/start/src/index.tsx b/packages/start/src/index.tsx
index be39a77a3..8d877e714 100644
--- a/packages/start/src/index.tsx
+++ b/packages/start/src/index.tsx
@@ -1,17 +1,18 @@
// @refresh skip
export type {
- APIEvent,
- APIHandler,
- Asset,
- ContextMatches,
- DocumentComponentProps,
- FetchEvent,
- HandlerOptions,
- PageEvent,
- ResponseStub,
- ServerFunctionMeta
+ APIEvent,
+ APIHandler,
+ Asset,
+ ContextMatches,
+ DocumentComponentProps,
+ FetchEvent,
+ HandlerOptions,
+ PageEvent,
+ ResponseStub,
+ ServerFunctionMeta,
} from "./server/types.ts";
+
export { default as clientOnly } from "./shared/clientOnly.ts";
export { GET } from "./shared/GET.ts";
export { HttpHeader } from "./shared/HttpHeader.tsx";
diff --git a/packages/start/src/internal.d.ts b/packages/start/src/internal.d.ts
index 7aee6253e..dd4ef0e40 100644
--- a/packages/start/src/internal.d.ts
+++ b/packages/start/src/internal.d.ts
@@ -10,5 +10,5 @@ declare module "h3" {
import type { Rollup } from "vite";
declare global {
var START_CLIENT_BUNDLE: Rollup.OutputBundle;
- var USING_SOLID_START_DEV_SERVER: boolean | undefined
+ var USING_SOLID_START_DEV_SERVER: boolean | undefined;
}
diff --git a/packages/start/src/middleware/index.ts b/packages/start/src/middleware/index.ts
index 692379bb0..3e4ecc8f0 100644
--- a/packages/start/src/middleware/index.ts
+++ b/packages/start/src/middleware/index.ts
@@ -10,73 +10,63 @@ export type MiddlewareFn = (event: FetchEvent) => Promise | unknown;
/** This composes an array of Exchanges into a single ExchangeIO function */
export type RequestMiddleware = (
- event: FetchEvent,
-) =>
- | Response
- | Promise
- | void
- | Promise
- | Promise;
+ event: FetchEvent
+) => Response | Promise | void | Promise | Promise;
// copy-pasted from h3/dist/index.d.ts
type EventHandlerResponse = T | Promise;
type ResponseMiddlewareResponseParam = { body?: Awaited };
export type ResponseMiddleware = (
- event: FetchEvent,
- response: ResponseMiddlewareResponseParam,
+ event: FetchEvent,
+ response: ResponseMiddlewareResponseParam
) => Response | Promise | void | Promise;
function wrapRequestMiddleware(onRequest: RequestMiddleware) {
- return async (h3Event: H3Event) => {
- const fetchEvent = getFetchEvent(h3Event);
- const response = await onRequest(fetchEvent);
- if (response) return response;
- };
+ return async (h3Event: H3Event) => {
+ const fetchEvent = getFetchEvent(h3Event);
+ const response = await onRequest(fetchEvent);
+ if (response) return response;
+ };
}
-function wrapResponseMiddleware(
- onBeforeResponse: ResponseMiddleware,
-): Middleware {
- return async (h3Event, next) => {
- const resp = await next();
+function wrapResponseMiddleware(onBeforeResponse: ResponseMiddleware): Middleware {
+ return async (h3Event, next) => {
+ const resp = await next();
- const fetchEvent = getFetchEvent(h3Event);
- const mwResponse = await onBeforeResponse(fetchEvent, {
- body: (resp as any)?.body,
- });
- if (mwResponse) return mwResponse;
- };
+ const fetchEvent = getFetchEvent(h3Event);
+ const mwResponse = await onBeforeResponse(fetchEvent, {
+ body: (resp as any)?.body
+ });
+ if (mwResponse) return mwResponse;
+ };
}
export function createMiddleware(
- args:
- | {
- /** @deprecated Use H3 `Middleware` */
- onRequest?: RequestMiddleware | RequestMiddleware[] | undefined;
- /** @deprecated Use H3 `Middleware` */
- onBeforeResponse?:
- | ResponseMiddleware
- | ResponseMiddleware[]
- | undefined;
- }
- | Middleware[],
+ args:
+ | {
+ /** @deprecated Use H3 `Middleware` */
+ onRequest?: RequestMiddleware | RequestMiddleware[] | undefined;
+ /** @deprecated Use H3 `Middleware` */
+ onBeforeResponse?: ResponseMiddleware | ResponseMiddleware[] | undefined;
+ }
+ | Middleware[]
): Middleware[] {
- if (Array.isArray(args)) return args;
+ if (Array.isArray(args)) return args;
- const mw: Middleware[] = [];
+ const mw: Middleware[] = [];
- if (typeof args.onRequest === "function") {
- mw.push(wrapRequestMiddleware(args.onRequest));
- } else if (Array.isArray(args.onRequest)) {
- mw.push(...args.onRequest.map(wrapRequestMiddleware));
- }
+ if (typeof args.onRequest === "function") {
+ mw.push(wrapRequestMiddleware(args.onRequest));
+ } else if (Array.isArray(args.onRequest)) {
+ mw.push(...args.onRequest.map(wrapRequestMiddleware));
+ }
- if (typeof args.onBeforeResponse === "function") {
- mw.push(wrapResponseMiddleware(args.onBeforeResponse));
- } else if (Array.isArray(args.onBeforeResponse)) {
- mw.push(...args.onBeforeResponse.map(wrapResponseMiddleware));
- }
+ if (typeof args.onBeforeResponse === "function") {
+ mw.push(wrapResponseMiddleware(args.onBeforeResponse));
+ } else if (Array.isArray(args.onBeforeResponse)) {
+ mw.push(...args.onBeforeResponse.map(wrapResponseMiddleware));
+ }
- return mw;
+ return mw;
}
diff --git a/packages/start/src/router.tsx b/packages/start/src/router.tsx
index 7b2116e25..19e7ec140 100644
--- a/packages/start/src/router.tsx
+++ b/packages/start/src/router.tsx
@@ -8,7 +8,8 @@ const components: Record = {};
export function createRoutes() {
function createRoute(route: any) {
- const component = route.$component && (components[route.$component.src] ??= lazy(route.$component.import));
+ const component =
+ route.$component && (components[route.$component.src] ??= lazy(route.$component.import));
return {
...route,
diff --git a/packages/start/src/server/StartServer.tsx b/packages/start/src/server/StartServer.tsx
index 1059412bf..97419175c 100644
--- a/packages/start/src/server/StartServer.tsx
+++ b/packages/start/src/server/StartServer.tsx
@@ -1,12 +1,6 @@
// @refresh skip
import type { Component } from "solid-js";
-import {
- Hydration,
- HydrationScript,
- NoHydration,
- getRequestEvent,
- ssr
-} from "solid-js/web";
+import { Hydration, HydrationScript, NoHydration, getRequestEvent, ssr } from "solid-js/web";
import App from "solid-start:app";
import { ErrorBoundary, TopErrorBoundary } from "../shared/ErrorBoundary.tsx";
diff --git a/packages/start/src/server/assets/render.tsx b/packages/start/src/server/assets/render.tsx
index 4b458e645..2b7d8a457 100644
--- a/packages/start/src/server/assets/render.tsx
+++ b/packages/start/src/server/assets/render.tsx
@@ -22,7 +22,11 @@ const assetMap = {
};
export function renderAsset(asset: Asset, nonce?: string) {
- let { tag, attrs: { key, ...attrs } = { key: undefined }, children } = asset as any;
+ let {
+ tag,
+ attrs: { key, ...attrs } = { key: undefined },
+ children
+ } = asset as any;
return (assetMap as any)[tag]({ attrs: { ...attrs, nonce }, key, children });
}
diff --git a/packages/start/src/server/collect-styles.ts b/packages/start/src/server/collect-styles.ts
index 85079ae0e..e2316a2d9 100644
--- a/packages/start/src/server/collect-styles.ts
+++ b/packages/start/src/server/collect-styles.ts
@@ -2,93 +2,86 @@ import path from "node:path";
import { resolve } from "pathe";
import type { DevEnvironment, EnvironmentModuleNode } from "vite";
-async function getViteModuleNode(
- vite: DevEnvironment,
- file: string,
-) {
- let nodePath = file;
- let node = vite.moduleGraph.getModuleById(file);
+async function getViteModuleNode(vite: DevEnvironment, file: string) {
+ let nodePath = file;
+ let node = vite.moduleGraph.getModuleById(file);
- if (!node) {
- const resolvedId = await vite.pluginContainer.resolveId(file, undefined);
- if (!resolvedId) return;
+ if (!node) {
+ const resolvedId = await vite.pluginContainer.resolveId(file, undefined);
+ if (!resolvedId) return;
- nodePath = resolvedId.id;
- node = vite.moduleGraph.getModuleById(file);
- }
+ nodePath = resolvedId.id;
+ node = vite.moduleGraph.getModuleById(file);
+ }
- if (!node) {
- nodePath = resolve(nodePath);
- node = await vite.moduleGraph.getModuleByUrl(file);
- }
+ if (!node) {
+ nodePath = resolve(nodePath);
+ node = await vite.moduleGraph.getModuleByUrl(file);
+ }
- if (!node) {
- await vite.moduleGraph.ensureEntryFromUrl(nodePath, false);
- node = vite.moduleGraph.getModuleById(nodePath);
- }
+ if (!node) {
+ await vite.moduleGraph.ensureEntryFromUrl(nodePath, false);
+ node = vite.moduleGraph.getModuleById(nodePath);
+ }
- return node;
+ return node;
}
async function findModuleDependencies(
- vite: DevEnvironment,
- file: string,
- deps: Set,
- crawledFiles = new Set()
+ vite: DevEnvironment,
+ file: string,
+ deps: Set,
+ crawledFiles = new Set()
) {
- crawledFiles.add(file);
- const module = await getViteModuleNode(vite, file);
- if (!module?.id || deps.has(module)) return;
-
- deps.add(module);
-
- if (module.url.endsWith(".css") || module.url.includes("node_modules")) return;
-
- if (!module.transformResult) {
- await vite.transformRequest(module.id).catch(() => {});
- }
- if (!module.transformResult?.deps) return;
-
- // Relying on module.transformResult.deps instead of module.importedModules because:
- // transformResult properly separates imports into deps and dynamicDeps, importedModules doesn't
- // Style crawling has to skip dynamic imports as such modules load their styles themselves
- for (const dep of module.transformResult.deps) {
- if (crawledFiles.has(dep)) {
- continue;
- }
- await findModuleDependencies(vite, dep, deps, crawledFiles);
- }
+ crawledFiles.add(file);
+ const module = await getViteModuleNode(vite, file);
+ if (!module?.id || deps.has(module)) return;
+
+ deps.add(module);
+
+ if (module.url.endsWith(".css") || module.url.includes("node_modules")) return;
+
+ if (!module.transformResult) {
+ await vite.transformRequest(module.id).catch(() => {});
+ }
+ if (!module.transformResult?.deps) return;
+
+ // Relying on module.transformResult.deps instead of module.importedModules because:
+ // transformResult properly separates imports into deps and dynamicDeps, importedModules doesn't
+ // Style crawling has to skip dynamic imports as such modules load their styles themselves
+ for (const dep of module.transformResult.deps) {
+ if (crawledFiles.has(dep)) {
+ continue;
+ }
+ await findModuleDependencies(vite, dep, deps, crawledFiles);
+ }
}
// Vite doesn't expose these so we just copy the list for now
// https://github.com/vitejs/vite/blob/d6bde8b03d433778aaed62afc2be0630c8131908/packages/vite/src/node/constants.ts#L49C23-L50
-const cssFileRegExp =
- /\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)$/;
+const cssFileRegExp = /\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)$/;
// https://github.com/vitejs/vite/blob/d6bde8b03d433778aaed62afc2be0630c8131908/packages/vite/src/node/plugins/css.ts#L160
const cssModulesRegExp = new RegExp(`\\.module${cssFileRegExp.source}`);
const isCssFile = (file: string) => cssFileRegExp.test(file);
export const isCssModulesFile = (file: string) => cssModulesRegExp.test(file);
-export async function findStylesInModuleGraph(
- vite: DevEnvironment,
- id: string,
-) {
- const absolute = path.resolve(process.cwd(), id);
- const dependencies = new Set();
-
- try {
- await findModuleDependencies(vite, absolute, dependencies);
- } catch (e) {
- console.error(e);
- }
-
- const styles: Record = {};
- for (const dep of dependencies) {
- if (dep.id && isCssFile(dep.url)) {
- styles[dep.id] = dep.url;
- }
- }
-
- return styles;
+export async function findStylesInModuleGraph(vite: DevEnvironment, id: string) {
+ const absolute = path.resolve(process.cwd(), id);
+ const dependencies = new Set();
+
+ try {
+ await findModuleDependencies(vite, absolute, dependencies);
+ } catch (e) {
+ console.error(e);
+ }
+
+ const styles: Record = {};
+ for (const dep of dependencies) {
+ if (dep.id && isCssFile(dep.url)) {
+ styles[dep.id] = dep.url;
+ }
+ }
+
+ return styles;
}
diff --git a/packages/start/src/server/fetchEvent.spec.ts b/packages/start/src/server/fetchEvent.spec.ts
index 9949eab22..5779dfad3 100644
--- a/packages/start/src/server/fetchEvent.spec.ts
+++ b/packages/start/src/server/fetchEvent.spec.ts
@@ -1,89 +1,85 @@
import * as h3 from "h3";
import { beforeEach, describe, expect, it, vi } from "vitest";
-import {
- createFetchEvent,
- getFetchEvent,
- mergeResponseHeaders,
-} from "./fetchEvent.ts";
-
-vi.mock(import("h3"), async (mod) => {
- return {
- ...(await mod()),
- getRequestIP: vi.fn(),
- };
+import { createFetchEvent, getFetchEvent, mergeResponseHeaders } from "./fetchEvent.ts";
+
+vi.mock(import("h3"), async mod => {
+ return {
+ ...(await mod()),
+ getRequestIP: vi.fn()
+ };
});
const mockedH3 = vi.mocked(h3);
const createMockH3Event = (): h3.H3Event => {
- const event = new h3.H3Event(new Request("http://localhost/test"));
+ const event = new h3.H3Event(new Request("http://localhost/test"));
- event.res.status = 200;
- event.res.statusText = "OK";
+ event.res.status = 200;
+ event.res.statusText = "OK";
- return event;
+ return event;
};
describe("fetchEvent", () => {
- let mockH3Event: h3.H3Event;
-
- beforeEach(() => {
- mockH3Event = createMockH3Event();
- vi.clearAllMocks();
-
- mockedH3.getRequestIP.mockReturnValue("127.0.0.1");
- });
-
- describe("createFetchEvent", () => {
- it("should create a FetchEvent from H3Event", () => {
- const fetchEvent = createFetchEvent(mockH3Event);
-
- expect(fetchEvent).toEqual({
- request: mockH3Event.req,
- response: expect.any(Object),
- clientAddress: "127.0.0.1",
- locals: {},
- nativeEvent: mockH3Event,
- });
- });
-
- it("should create response stub with correct properties", () => {
- const fetchEvent = createFetchEvent(mockH3Event);
-
- expect(fetchEvent.response).toHaveProperty("status");
- expect(fetchEvent.response).toHaveProperty("statusText");
- expect(fetchEvent.response).toHaveProperty("headers");
- });
- });
-
- describe("getFetchEvent", () => {
- it("should create and cache FetchEvent on first call", () => {
- const fetchEvent = getFetchEvent(mockH3Event);
-
- expect(mockH3Event.context.solidFetchEvent).toBe(fetchEvent);
- expect(fetchEvent.nativeEvent).toBe(mockH3Event);
- });
-
- it("should return cached FetchEvent on subsequent calls", () => {
- const firstCall = getFetchEvent(mockH3Event);
- const secondCall = getFetchEvent(mockH3Event);
-
- expect(firstCall).toBe(secondCall);
- });
- });
-
- describe("mergeResponseHeaders", () => {
- it("should merge headers from Headers object to H3Event", () => {
- const headers = new Headers({
- "content-type": "application/json",
- "x-custom": "value",
- });
-
- mergeResponseHeaders(mockH3Event, headers);
-
- expect(headers.get("content-type")).toBe("application/json");
- expect(headers.get("x-custom")).toBe("value");
- });
- });
+ let mockH3Event: h3.H3Event;
+
+ beforeEach(() => {
+ mockH3Event = createMockH3Event();
+ vi.clearAllMocks();
+
+ mockedH3.getRequestIP.mockReturnValue("127.0.0.1");
+ });
+
+ describe("createFetchEvent", () => {
+ it("should create a FetchEvent from H3Event", () => {
+ const fetchEvent = createFetchEvent(mockH3Event);
+
+ expect(fetchEvent).toEqual({
+ request: mockH3Event.req,
+ response: expect.any(Object),
+ clientAddress: "127.0.0.1",
+ locals: {},
+ nativeEvent: mockH3Event
+ });
+ });
+
+ it("should create response stub with correct properties", () => {
+ const fetchEvent = createFetchEvent(mockH3Event);
+
+ expect(fetchEvent.response).toHaveProperty("status");
+ expect(fetchEvent.response).toHaveProperty("statusText");
+ expect(fetchEvent.response).toHaveProperty("headers");
+ });
+ });
+
+ describe("getFetchEvent", () => {
+ it("should create and cache FetchEvent on first call", () => {
+ const fetchEvent = getFetchEvent(mockH3Event);
+
+ expect(mockH3Event.context.solidFetchEvent).toBe(fetchEvent);
+ expect(fetchEvent.nativeEvent).toBe(mockH3Event);
+ });
+
+ it("should return cached FetchEvent on subsequent calls", () => {
+ const firstCall = getFetchEvent(mockH3Event);
+ const secondCall = getFetchEvent(mockH3Event);
+
+ expect(firstCall).toBe(secondCall);
+ });
+ });
+
+ describe("mergeResponseHeaders", () => {
+ it("should merge headers from Headers object to H3Event", () => {
+ const headers = new Headers({
+ "content-type": "application/json",
+ "x-custom": "value"
+ });
+
+ mergeResponseHeaders(mockH3Event, headers);
+
+ expect(headers.get("content-type")).toBe("application/json");
+ expect(headers.get("x-custom")).toBe("value");
+ });
+ });
});
diff --git a/packages/start/src/server/fetchEvent.ts b/packages/start/src/server/fetchEvent.ts
index ffbae0080..0f16c084c 100644
--- a/packages/start/src/server/fetchEvent.ts
+++ b/packages/start/src/server/fetchEvent.ts
@@ -5,32 +5,32 @@ import type { FetchEvent } from "./types.ts";
const FETCH_EVENT_CONTEXT = "solidFetchEvent";
export function createFetchEvent(event: H3Event): FetchEvent {
- return {
- request: event.req,
- response: event.res,
- clientAddress: getRequestIP(event),
- locals: {},
- nativeEvent: event,
- };
+ return {
+ request: event.req,
+ response: event.res,
+ clientAddress: getRequestIP(event),
+ locals: {},
+ nativeEvent: event
+ };
}
export function getFetchEvent(h3Event: H3Event): FetchEvent {
- if (!h3Event.context[FETCH_EVENT_CONTEXT]) {
- const fetchEvent = createFetchEvent(h3Event);
- h3Event.context[FETCH_EVENT_CONTEXT] = fetchEvent;
- }
+ if (!h3Event.context[FETCH_EVENT_CONTEXT]) {
+ const fetchEvent = createFetchEvent(h3Event);
+ h3Event.context[FETCH_EVENT_CONTEXT] = fetchEvent;
+ }
- return h3Event.context[FETCH_EVENT_CONTEXT] as any;
+ return h3Event.context[FETCH_EVENT_CONTEXT] as any;
}
export function mergeResponseHeaders(h3Event: H3Event, headers: Headers) {
- for (const [key, value] of headers.entries()) {
- h3Event.res.headers.append(key, value);
- }
+ for (const [key, value] of headers.entries()) {
+ h3Event.res.headers.append(key, value);
+ }
}
export const decorateHandler = (fn: T) =>
- (event => provideRequestEvent(getFetchEvent(event), () => fn(event))) as T;
+ (event => provideRequestEvent(getFetchEvent(event), () => fn(event))) as T;
export const decorateMiddleware = (fn: T) =>
- ((event, next) => provideRequestEvent(getFetchEvent(event), () => fn(event, next))) as T;
+ ((event, next) => provideRequestEvent(getFetchEvent(event), () => fn(event, next))) as T;
diff --git a/packages/start/src/server/handler.ts b/packages/start/src/server/handler.ts
index cdcacc600..c5be30309 100644
--- a/packages/start/src/server/handler.ts
+++ b/packages/start/src/server/handler.ts
@@ -10,89 +10,80 @@ import { decorateHandler, decorateMiddleware } from "./fetchEvent.ts";
import { getSsrManifest } from "./manifest/ssr-manifest.ts";
import { matchAPIRoute } from "./routes.ts";
import { handleServerFunction } from "./server-functions-handler.ts";
-import type {
- APIEvent,
- FetchEvent,
- HandlerOptions,
- PageEvent,
-} from "./types.ts";
+import type { APIEvent, FetchEvent, HandlerOptions, PageEvent } from "./types.ts";
import { getExpectedRedirectStatus } from "./util.ts";
const SERVER_FN_BASE = "/_server";
export function createBaseHandler(
- createPageEvent: (e: FetchEvent) => Promise,
- fn: (context: PageEvent) => JSX.Element,
- options:
- | HandlerOptions
- | ((context: PageEvent) => HandlerOptions | Promise) = {},
+ createPageEvent: (e: FetchEvent) => Promise,
+ fn: (context: PageEvent) => JSX.Element,
+ options: HandlerOptions | ((context: PageEvent) => HandlerOptions | Promise) = {}
) {
- const handler = defineHandler({
- middleware: middleware.length ? middleware.map(decorateMiddleware): undefined,
- handler: decorateHandler(async (e: H3Event) => {
- const event = getRequestEvent()!;
- const url = new URL(event.request.url);
- const pathname = url.pathname;
+ const handler = defineHandler({
+ middleware: middleware.length ? middleware.map(decorateMiddleware) : undefined,
+ handler: decorateHandler(async (e: H3Event) => {
+ const event = getRequestEvent()!;
+ const url = new URL(event.request.url);
+ const pathname = url.pathname;
- const serverFunctionTest = join(import.meta.env.BASE_URL, SERVER_FN_BASE);
- if (pathname.startsWith(serverFunctionTest)) {
- const serverFnResponse = await handleServerFunction(e);
+ const serverFunctionTest = join(import.meta.env.BASE_URL, SERVER_FN_BASE);
+ if (pathname.startsWith(serverFunctionTest)) {
+ const serverFnResponse = await handleServerFunction(e);
if (serverFnResponse instanceof Response)
return produceResponseWithEventHeaders(serverFnResponse);
- return new Response(serverFnResponse as any, {
- headers: e.res.headers,
- });
- }
-
- const match = matchAPIRoute(pathname, event.request.method);
- if (match) {
- const mod = await match.handler.import();
- const fn =
- event.request.method === "HEAD"
- ? mod["HEAD"] || mod["GET"]
- : mod[event.request.method];
- (event as APIEvent).params = match.params || {};
- // @ts-expect-error
- sharedConfig.context = { event };
- const res = await fn!(event);
+ return new Response(serverFnResponse as any, {
+ headers: e.res.headers
+ });
+ }
+
+ const match = matchAPIRoute(pathname, event.request.method);
+ if (match) {
+ const mod = await match.handler.import();
+ const fn =
+ event.request.method === "HEAD" ? mod["HEAD"] || mod["GET"] : mod[event.request.method];
+ (event as APIEvent).params = match.params || {};
+ // @ts-expect-error
+ sharedConfig.context = { event };
+ const res = await fn!(event);
if (res !== undefined) {
- if(res instanceof Response) return produceResponseWithEventHeaders(res)
+ if (res instanceof Response) return produceResponseWithEventHeaders(res);
return res;
}
- if (event.request.method !== "GET") {
- throw new Error(
- `API handler for ${event.request.method} "${event.request.url}" did not return a response.`,
- );
- }
- if (!match.isPage) return;
- }
-
- const context = await createPageEvent(event);
-
- const resolvedOptions =
- typeof options === "function" ? await options(context) : { ...options };
- const mode = resolvedOptions.mode || "stream";
- if (resolvedOptions.nonce) context.nonce = resolvedOptions.nonce;
-
- if (mode === "sync" || !import.meta.env.START_SSR) {
- const html = renderToString(() => {
- (sharedConfig.context as any).event = context;
- return fn(context);
- });
- context.complete = true;
-
- if (context.response && context.response.headers.get("Location")) {
+ if (event.request.method !== "GET") {
+ throw new Error(
+ `API handler for ${event.request.method} "${event.request.url}" did not return a response.`
+ );
+ }
+ if (!match.isPage) return;
+ }
+
+ const context = await createPageEvent(event);
+
+ const resolvedOptions =
+ typeof options === "function" ? await options(context) : { ...options };
+ const mode = resolvedOptions.mode || "stream";
+ if (resolvedOptions.nonce) context.nonce = resolvedOptions.nonce;
+
+ if (mode === "sync" || !import.meta.env.START_SSR) {
+ const html = renderToString(() => {
+ (sharedConfig.context as any).event = context;
+ return fn(context);
+ });
+ context.complete = true;
+
+ if (context.response && context.response.headers.get("Location")) {
const status = getExpectedRedirectStatus(context.response);
return redirect(context.response.headers.get("Location")!, status);
}
- return html;
- }
+ return html;
+ }
- if (resolvedOptions.onCompleteAll) {
+ if (resolvedOptions.onCompleteAll) {
const og = resolvedOptions.onCompleteAll;
resolvedOptions.onCompleteAll = options => {
handleStreamCompleteRedirect(context)(options);
@@ -107,10 +98,10 @@ export function createBaseHandler(
};
} else resolvedOptions.onCompleteShell = handleShellCompleteRedirect(context, e);
- const _stream = renderToStream(() => {
- (sharedConfig.context as any).event = context;
- return fn(context);
- }, resolvedOptions);
+ const _stream = renderToStream(() => {
+ (sharedConfig.context as any).event = context;
+ return fn(context);
+ }, resolvedOptions);
const stream = _stream as typeof _stream & PromiseLike; // stream has a hidden 'then' method
if (context.response && context.response.headers.get("Location")) {
@@ -118,103 +109,98 @@ export function createBaseHandler(
return redirect(context.response.headers.get("Location")!, status);
}
- if (mode === "async") return await stream
+ if (mode === "async") return await stream;
delete (stream as any).then;
// using TransformStream in dev can cause solid-start-dev-server to crash
// when stream is cancelled
- if(globalThis.USING_SOLID_START_DEV_SERVER) return stream
+ if (globalThis.USING_SOLID_START_DEV_SERVER) return stream;
// returning stream directly breaks cloudflare workers
const { writable, readable } = new TransformStream();
stream.pipeTo(writable);
- return readable
- }),
- });
+ return readable;
+ })
+ });
- const app = new H3();
+ const app = new H3();
app.use(handler);
- return app;
+ return app;
}
export function createHandler(
- fn: (context: PageEvent) => JSX.Element,
- options:
- | HandlerOptions
- | ((context: PageEvent) => HandlerOptions | Promise) = {},
+ fn: (context: PageEvent) => JSX.Element,
+ options: HandlerOptions | ((context: PageEvent) => HandlerOptions | Promise) = {}
) {
- return createBaseHandler(createPageEvent, fn, options);
+ return createBaseHandler(createPageEvent, fn, options);
}
export async function createPageEvent(ctx: FetchEvent) {
- ctx.response.headers.set("Content-Type", "text/html");
- // const prevPath = ctx.request.headers.get("x-solid-referrer");
- // const mutation = ctx.request.headers.get("x-solid-mutation") === "true";
- const manifest = getSsrManifest(import.meta.env.SSR && import.meta.env.DEV ? "ssr": "client");
+ ctx.response.headers.set("Content-Type", "text/html");
+ // const prevPath = ctx.request.headers.get("x-solid-referrer");
+ // const mutation = ctx.request.headers.get("x-solid-mutation") === "true";
+ const manifest = getSsrManifest(import.meta.env.SSR && import.meta.env.DEV ? "ssr" : "client");
- // Handle Vite build.cssCodeSplit
- // When build.cssCodeSplit is false, a single CSS file is generated with the key style.css
- const mergedCSS = import.meta.env.PROD ? await manifest.getAssets('style.css'): [];
+ // Handle Vite build.cssCodeSplit
+ // When build.cssCodeSplit is false, a single CSS file is generated with the key style.css
+ const mergedCSS = import.meta.env.PROD ? await manifest.getAssets("style.css") : [];
- const assets = [
+ const assets = [
...mergedCSS,
...(await manifest.getAssets(import.meta.env.START_CLIENT_ENTRY)),
- ...(await manifest.getAssets(import.meta.env.START_APP_ENTRY)),
+ ...(await manifest.getAssets(import.meta.env.START_APP_ENTRY))
// ...(import.meta.env.START_ISLANDS
// ? (await serverManifest.inputs[serverManifest.handler]!.assets()).filter(
// s => (s as any).attrs.rel !== "modulepreload"
// )
// : [])
];
- const pageEvent: PageEvent = Object.assign(ctx, {
- assets,
- router: {
- submission: initFromFlash(ctx) as any,
- },
- routes: createRoutes(),
- // prevUrl: prevPath || "",
- // mutation: mutation,
- // $type: FETCH_EVENT,
- complete: false,
- $islands: new Set(),
- });
-
- return pageEvent;
+ const pageEvent: PageEvent = Object.assign(ctx, {
+ assets,
+ router: {
+ submission: initFromFlash(ctx) as any
+ },
+ routes: createRoutes(),
+ // prevUrl: prevPath || "",
+ // mutation: mutation,
+ // $type: FETCH_EVENT,
+ complete: false,
+ $islands: new Set()
+ });
+
+ return pageEvent;
}
function initFromFlash(ctx: FetchEvent) {
- const flash = getCookie(ctx.nativeEvent, "flash");
- if (!flash) return;
- try {
- const param = JSON.parse(flash);
- if (!param || !param.result) return;
- const input = [
- ...param.input.slice(0, -1),
- new Map(param.input[param.input.length - 1]),
- ];
- const result = param.error ? new Error(param.result) : param.result;
- return {
- input,
- url: param.url,
- pending: false,
- result: param.thrown ? undefined : result,
- error: param.thrown ? result : undefined,
- };
- } catch (e) {
- console.error(e);
- } finally {
- setCookie(ctx.nativeEvent, "flash", "", { maxAge: 0 });
- }
+ const flash = getCookie(ctx.nativeEvent, "flash");
+ if (!flash) return;
+ try {
+ const param = JSON.parse(flash);
+ if (!param || !param.result) return;
+ const input = [...param.input.slice(0, -1), new Map(param.input[param.input.length - 1])];
+ const result = param.error ? new Error(param.result) : param.result;
+ return {
+ input,
+ url: param.url,
+ pending: false,
+ result: param.thrown ? undefined : result,
+ error: param.thrown ? result : undefined
+ };
+ } catch (e) {
+ console.error(e);
+ } finally {
+ setCookie(ctx.nativeEvent, "flash", "", { maxAge: 0 });
+ }
}
function handleShellCompleteRedirect(context: PageEvent, e: H3Event) {
return () => {
if (context.response && context.response.headers.get("Location")) {
const status = getExpectedRedirectStatus(context.response);
- e.res.status = status
+ e.res.status = status;
e.res.headers.set("Location", context.response.headers.get("Location")!);
}
};
@@ -234,7 +220,7 @@ function produceResponseWithEventHeaders(res: Response) {
let ret = res;
// Response.redirect returns an immutable value, so we clone on any redirect just in case
- if(300 <= res.status && res.status < 400) {
+ if (300 <= res.status && res.status < 400) {
ret = new Response(res.body, {
status: res.status,
statusText: res.statusText,
@@ -242,9 +228,9 @@ function produceResponseWithEventHeaders(res: Response) {
});
}
- for(const [name, value] of event.response.headers) {
+ for (const [name, value] of event.response.headers) {
ret.headers.set(name, value);
}
- return ret
+ return ret;
}
diff --git a/packages/start/src/server/manifest/client-manifest.ts b/packages/start/src/server/manifest/client-manifest.ts
index e511d5627..c9702bb7a 100644
--- a/packages/start/src/server/manifest/client-manifest.ts
+++ b/packages/start/src/server/manifest/client-manifest.ts
@@ -2,7 +2,7 @@ import { getClientDevManifest } from "./dev-client-manifest.ts";
import { getClientProdManifest } from "./prod-client-manifest.ts";
export function getClientManifest() {
- return import.meta.env.DEV ? getClientDevManifest() : getClientProdManifest();
+ return import.meta.env.DEV ? getClientDevManifest() : getClientProdManifest();
}
export { getClientManifest as getManifest };
diff --git a/packages/start/src/server/manifest/dev-client-manifest.ts b/packages/start/src/server/manifest/dev-client-manifest.ts
index 0d15c4d54..e3883c7a7 100644
--- a/packages/start/src/server/manifest/dev-client-manifest.ts
+++ b/packages/start/src/server/manifest/dev-client-manifest.ts
@@ -3,17 +3,19 @@ import { join } from "pathe";
export function getClientDevManifest() {
return {
import(id) {
- return import(/* @vite-ignore */ join("/", id))
+ return import(/* @vite-ignore */ join("/", id));
},
async getAssets(id) {
const assetsPath = `/@manifest/client/${Date.now()}/assets?id=${id}`;
const assets = (await import(/* @vite-ignore */ assetsPath)).default;
- return await Promise.all(assets.map(async (v: any) => ({
- ...v,
- children: await v.children()
- })));
- },
+ return await Promise.all(
+ assets.map(async (v: any) => ({
+ ...v,
+ children: await v.children()
+ }))
+ );
+ }
} satisfies StartManifest & { import(id: string): Promise };
}
diff --git a/packages/start/src/server/manifest/dev-ssr-manifest.ts b/packages/start/src/server/manifest/dev-ssr-manifest.ts
index 735ec073f..ac766dc26 100644
--- a/packages/start/src/server/manifest/dev-ssr-manifest.ts
+++ b/packages/start/src/server/manifest/dev-ssr-manifest.ts
@@ -8,14 +8,16 @@ export function getSsrDevManifest(environment: "client" | "ssr") {
const assets = (await import(/* @vite-ignore */ assetsPath)).default;
- return await Promise.all(assets.map(async (v: any) => ({
- ...v,
- children: await v.children()
- })));
- },
+ return await Promise.all(
+ assets.map(async (v: any) => ({
+ ...v,
+ children: await v.children()
+ }))
+ );
+ }
} satisfies StartManifest & {
- path(id: string): string;
- };
+ path(id: string): string;
+ };
}
export { getSsrDevManifest as getSsrManifest };
diff --git a/packages/start/src/server/manifest/prod-client-manifest.ts b/packages/start/src/server/manifest/prod-client-manifest.ts
index 2487abaf7..65333790c 100644
--- a/packages/start/src/server/manifest/prod-client-manifest.ts
+++ b/packages/start/src/server/manifest/prod-client-manifest.ts
@@ -2,17 +2,20 @@ export function getClientProdManifest() {
return {
import(id) {
// @ts-ignore
- return import(/* @vite-ignore */ window.manifest[id].output)
+ return import(/* @vite-ignore */ window.manifest[id].output);
},
async getAssets(id) {
if (id.startsWith("./")) id = id.slice(2);
// @ts-ignore
- return window.manifest[id]?.assets ?? []
+ return window.manifest[id]?.assets ?? [];
},
async json() {
// @ts-ignore
- return window.manifest
- },
- } satisfies StartManifest & { json(): Promise>, import(id: string): Promise; }
+ return window.manifest;
+ }
+ } satisfies StartManifest & {
+ json(): Promise>;
+ import(id: string): Promise;
+ };
}
diff --git a/packages/start/src/server/manifest/prod-ssr-manifest.ts b/packages/start/src/server/manifest/prod-ssr-manifest.ts
index 6d3ccd732..45a93f9f2 100644
--- a/packages/start/src/server/manifest/prod-ssr-manifest.ts
+++ b/packages/start/src/server/manifest/prod-ssr-manifest.ts
@@ -5,121 +5,105 @@ import type { Asset } from "../assets/render.tsx";
// Only reads from client manifest atm, might need server support for islands
export function getSsrProdManifest() {
- const viteManifest = clientViteManifest;
- return {
- path(id: string) {
+ const viteManifest = clientViteManifest;
+ return {
+ path(id: string) {
if (id.startsWith("./")) id = id.slice(2);
- const viteManifestEntry =
- clientViteManifest[id /*import.meta.env.START_CLIENT_ENTRY*/];
- if (!viteManifestEntry)
- throw new Error(`No entry found in vite manifest for '${id}'`);
+ const viteManifestEntry = clientViteManifest[id /*import.meta.env.START_CLIENT_ENTRY*/];
+ if (!viteManifestEntry) throw new Error(`No entry found in vite manifest for '${id}'`);
- return join("/", viteManifestEntry.file);
- },
- async getAssets(id) {
+ return join("/", viteManifestEntry.file);
+ },
+ async getAssets(id) {
if (id.startsWith("./")) id = id.slice(2);
- return createHtmlTagsForAssets(
- findAssetsInViteManifest(clientViteManifest, id),
- );
- },
- async json() {
- const json: Record = {};
+ return createHtmlTagsForAssets(findAssetsInViteManifest(clientViteManifest, id));
+ },
+ async json() {
+ const json: Record = {};
- const entryKeys = Object.keys(viteManifest)
- .filter((id) => viteManifest[id]?.isEntry || viteManifest[id]?.isDynamicEntry)
- .map((id) => id);
+ const entryKeys = Object.keys(viteManifest)
+ .filter(id => viteManifest[id]?.isEntry || viteManifest[id]?.isDynamicEntry)
+ .map(id => id);
- for (const entryKey of entryKeys) {
- json[entryKey] = {
- output: join("/", viteManifest[entryKey]!.file),
- assets: await this.getAssets(entryKey),
- };
- }
+ for (const entryKey of entryKeys) {
+ json[entryKey] = {
+ output: join("/", viteManifest[entryKey]!.file),
+ assets: await this.getAssets(entryKey)
+ };
+ }
- return json;
- },
- } satisfies StartManifest & {
- json(): Promise>;
- path(id: string): string;
- };
+ return json;
+ }
+ } satisfies StartManifest & {
+ json(): Promise>;
+ path(id: string): string;
+ };
}
function createHtmlTagsForAssets(assets: string[]) {
- return assets
- .filter(
- (asset) =>
- asset.endsWith(".css") ||
- asset.endsWith(".js") ||
- asset.endsWith(".ts") ||
- asset.endsWith(".mjs"),
- )
- .map((asset) => ({
- tag: "link",
- attrs: {
- href: '/' + asset,
- key: asset,
- ...(asset.endsWith(".css")
- ? { rel: "stylesheet" }
- : { rel: "modulepreload" }),
- },
- }));
+ return assets
+ .filter(
+ asset =>
+ asset.endsWith(".css") ||
+ asset.endsWith(".js") ||
+ asset.endsWith(".ts") ||
+ asset.endsWith(".mjs")
+ )
+ .map(asset => ({
+ tag: "link",
+ attrs: {
+ href: "/" + asset,
+ key: asset,
+ ...(asset.endsWith(".css") ? { rel: "stylesheet" } : { rel: "modulepreload" })
+ }
+ }));
}
const entryId = import.meta.env.START_CLIENT_ENTRY.slice(2);
let entryImports: string[] | undefined = undefined;
function findAssetsInViteManifest(
- manifest: Manifest,
- id: string,
- assetMap = new Map(),
- stack: string[] = [],
+ manifest: Manifest,
+ id: string,
+ assetMap = new Map(),
+ stack: string[] = []
) {
- if (stack.includes(id)) {
- return [];
- }
+ if (stack.includes(id)) {
+ return [];
+ }
- const cached = assetMap.get(id);
- if (cached) {
- return cached;
- }
- const chunk = manifest[id];
- if (!chunk) {
- return [];
- }
+ const cached = assetMap.get(id);
+ if (cached) {
+ return cached;
+ }
+ const chunk = manifest[id];
+ if (!chunk) {
+ return [];
+ }
- if (!entryImports) {
- entryImports = [
- entryId,
- ...(manifest[entryId]?.imports ?? [])
- ];
- }
+ if (!entryImports) {
+ entryImports = [entryId, ...(manifest[entryId]?.imports ?? [])];
+ }
- // Only include entry imports, if we are specifically crawling the entry
- // Chunks (e.g. routes) that import something from entry, should not render entry css redundantly
- const excludeEntryImports = id !== entryId;
+ // Only include entry imports, if we are specifically crawling the entry
+ // Chunks (e.g. routes) that import something from entry, should not render entry css redundantly
+ const excludeEntryImports = id !== entryId;
- const assets = chunk.css?.filter(Boolean) || [];
- if (chunk.imports) {
- stack.push(id);
- for (let i = 0, l = chunk.imports.length; i < l; i++) {
- const importId = chunk.imports[i];
- if (!importId || (excludeEntryImports && entryImports.includes(importId))) continue;
- assets.push(
- ...findAssetsInViteManifest(
- manifest,
- importId,
- assetMap,
- stack,
- ),
- );
- }
- stack.pop();
- }
- assets.push(chunk.file);
- const all = Array.from(new Set(assets));
- assetMap.set(id, all);
+ const assets = chunk.css?.filter(Boolean) || [];
+ if (chunk.imports) {
+ stack.push(id);
+ for (let i = 0, l = chunk.imports.length; i < l; i++) {
+ const importId = chunk.imports[i];
+ if (!importId || (excludeEntryImports && entryImports.includes(importId))) continue;
+ assets.push(...findAssetsInViteManifest(manifest, importId, assetMap, stack));
+ }
+ stack.pop();
+ }
+ assets.push(chunk.file);
+ const all = Array.from(new Set(assets));
+ assetMap.set(id, all);
- return all;
+ return all;
}
diff --git a/packages/start/src/server/manifest/ssr-manifest.ts b/packages/start/src/server/manifest/ssr-manifest.ts
index 8c83fe246..e0f9eac40 100644
--- a/packages/start/src/server/manifest/ssr-manifest.ts
+++ b/packages/start/src/server/manifest/ssr-manifest.ts
@@ -1,8 +1,10 @@
import { getSsrDevManifest } from "./dev-ssr-manifest.ts";
import { getSsrProdManifest } from "./prod-ssr-manifest.ts";
-export function getSsrManifest(target: "client" | "ssr"): ReturnType | ReturnType {
- return import.meta.env.DEV ? getSsrDevManifest(target) : getSsrProdManifest();
+export function getSsrManifest(
+ target: "client" | "ssr"
+): ReturnType | ReturnType {
+ return import.meta.env.DEV ? getSsrDevManifest(target) : getSsrProdManifest();
}
export { getSsrManifest as getManifest };
diff --git a/packages/start/src/server/routes.ts b/packages/start/src/server/routes.ts
index 0c6807908..37b5076d8 100644
--- a/packages/start/src/server/routes.ts
+++ b/packages/start/src/server/routes.ts
@@ -5,134 +5,122 @@ import { createRouter } from "radix3";
import type { FetchEvent } from "./types.ts";
interface Route {
- path: string;
- id: string;
- children?: Route[];
- page?: boolean;
- $component?: any;
- $HEAD?: any;
- $GET?: any;
- $POST?: any;
- $PUT?: any;
- $PATCH?: any;
- $DELETE?: any;
+ path: string;
+ id: string;
+ children?: Route[];
+ page?: boolean;
+ $component?: any;
+ $HEAD?: any;
+ $GET?: any;
+ $POST?: any;
+ $PUT?: any;
+ $PATCH?: any;
+ $DELETE?: any;
}
-export const pageRoutes = defineRoutes(
- (fileRoutes as unknown as Route[]).filter((o) => o.page),
-);
+export const pageRoutes = defineRoutes((fileRoutes as unknown as Route[]).filter(o => o.page));
function defineRoutes(fileRoutes: Route[]) {
- function processRoute(
- routes: Route[],
- route: Route,
- id: string,
- full: string,
- ) {
- const parentRoute = Object.values(routes).find((o) => {
- return id.startsWith(o.id + "/");
- });
+ function processRoute(routes: Route[], route: Route, id: string, full: string) {
+ const parentRoute = Object.values(routes).find(o => {
+ return id.startsWith(o.id + "/");
+ });
- if (!parentRoute) {
- routes.push({
- ...route,
- id,
- path: id.replace(/\([^)/]+\)/g, "").replace(/\/+/g, "/"),
- });
- return routes;
- }
- processRoute(
- parentRoute.children || (parentRoute.children = []),
- route,
- id.slice(parentRoute.id.length),
- full,
- );
+ if (!parentRoute) {
+ routes.push({
+ ...route,
+ id,
+ path: id.replace(/\([^)/]+\)/g, "").replace(/\/+/g, "/")
+ });
+ return routes;
+ }
+ processRoute(
+ parentRoute.children || (parentRoute.children = []),
+ route,
+ id.slice(parentRoute.id.length),
+ full
+ );
- return routes;
- }
+ return routes;
+ }
- return fileRoutes
- .sort((a, b) => a.path.length - b.path.length)
- .reduce((prevRoutes: Route[], route) => {
- return processRoute(prevRoutes, route, route.path, route.path);
- }, []);
+ return fileRoutes
+ .sort((a, b) => a.path.length - b.path.length)
+ .reduce((prevRoutes: Route[], route) => {
+ return processRoute(prevRoutes, route, route.path, route.path);
+ }, []);
}
const router = createRouter({
- routes: (fileRoutes as unknown as Route[]).reduce(
- (memo, route) => {
- if (!containsHTTP(route)) return memo;
- const path = route.path
- .replace(/\([^)/]+\)/g, "")
- .replace(/\/+/g, "/")
- .replace(/\*([^/]*)/g, (_, m) => `**:${m}`)
- .split("/")
- .map((s) =>
- s.startsWith(":") || s.startsWith("*") ? s : encodeURIComponent(s),
- )
- .join("/");
- if (/:[^/]*\?/g.test(path)) {
- throw new Error(
- `Optional parameters are not supported in API routes: ${path}`,
- );
- }
- if (memo[path]) {
- throw new Error(
- `Duplicate API routes for "${path}" found at "${memo[path]!.route.path}" and "${
- route.path
- }"`,
- );
- }
- memo[path] = { route };
- return memo;
- },
- {} as Record,
- ),
+ routes: (fileRoutes as unknown as Route[]).reduce(
+ (memo, route) => {
+ if (!containsHTTP(route)) return memo;
+ const path = route.path
+ .replace(/\([^)/]+\)/g, "")
+ .replace(/\/+/g, "/")
+ .replace(/\*([^/]*)/g, (_, m) => `**:${m}`)
+ .split("/")
+ .map(s => (s.startsWith(":") || s.startsWith("*") ? s : encodeURIComponent(s)))
+ .join("/");
+ if (/:[^/]*\?/g.test(path)) {
+ throw new Error(`Optional parameters are not supported in API routes: ${path}`);
+ }
+ if (memo[path]) {
+ throw new Error(
+ `Duplicate API routes for "${path}" found at "${memo[path]!.route.path}" and "${
+ route.path
+ }"`
+ );
+ }
+ memo[path] = { route };
+ return memo;
+ },
+ {} as Record
+ )
});
function containsHTTP(route: Route) {
- return (
- route["$HEAD"] ||
- route["$GET"] ||
- route["$POST"] ||
- route["$PUT"] ||
- route["$PATCH"] ||
- route["$DELETE"]
- );
+ return (
+ route["$HEAD"] ||
+ route["$GET"] ||
+ route["$POST"] ||
+ route["$PUT"] ||
+ route["$PATCH"] ||
+ route["$DELETE"]
+ );
}
export function matchAPIRoute(
- path: string,
- method: string,
+ path: string,
+ method: string
):
- | {
- params?: Record;
- handler: {
- import: () => Promise Promise>>;
- };
- isPage: boolean;
- }
- | undefined {
- const match = router.lookup(path);
- if (match && match.route) {
- const route = match.route;
+ | {
+ params?: Record;
+ handler: {
+ import: () => Promise Promise>>;
+ };
+ isPage: boolean;
+ }
+ | undefined {
+ const match = router.lookup(path);
+ if (match && match.route) {
+ const route = match.route;
- // Find the appropriate handler for the HTTP method
- const handler =
- method === "HEAD" ? route.$HEAD || route.$GET : route[`$${method}`];
+ // Find the appropriate handler for the HTTP method
+ const handler = method === "HEAD" ? route.$HEAD || route.$GET : route[`$${method}`];
- if (handler === undefined) return;
+ if (handler === undefined) return;
- // Check if this is a page route
- const isPage = route.page === true && route.$component !== undefined;
+ // Check if this is a page route
+ const isPage = route.page === true && route.$component !== undefined;
- // Return comprehensive route information
- return {
- handler,
- params: match.params,
- isPage,
- };
- }
+ // Return comprehensive route information
+ return {
+ handler,
+ params: match.params,
+ isPage
+ };
+ }
- return undefined;
+ return undefined;
}
diff --git a/packages/start/src/server/server-fns-runtime.ts b/packages/start/src/server/server-fns-runtime.ts
index f56fdad72..f10c8c10b 100644
--- a/packages/start/src/server/server-fns-runtime.ts
+++ b/packages/start/src/server/server-fns-runtime.ts
@@ -5,7 +5,7 @@ export function createServerReference(fn: Function, id: string) {
if (typeof fn !== "function")
throw new Error("Export from a 'use server' module must be a function");
let baseURL = import.meta.env.BASE_URL ?? "/";
- if(!baseURL.endsWith("/")) baseURL += "/"
+ if (!baseURL.endsWith("/")) baseURL += "/";
return new Proxy(fn, {
get(target, prop, receiver) {
diff --git a/packages/start/src/server/server-functions-handler.ts b/packages/start/src/server/server-functions-handler.ts
index 2466567d0..b81c6067f 100644
--- a/packages/start/src/server/server-functions-handler.ts
+++ b/packages/start/src/server/server-functions-handler.ts
@@ -1,22 +1,18 @@
import { getServerFnById } from "solidstart:server-fn-manifest";
import { parseSetCookie } from "cookie-es";
import { type H3Event, parseCookies } from "h3";
+import { crossSerializeStream, fromJSON, getCrossReferenceHeader } from "seroval";
import {
- crossSerializeStream,
- fromJSON,
- getCrossReferenceHeader,
-} from "seroval";
-import {
- CustomEventPlugin,
- DOMExceptionPlugin,
- EventPlugin,
- FormDataPlugin,
- HeadersPlugin,
- ReadableStreamPlugin,
- RequestPlugin,
- ResponsePlugin,
- URLPlugin,
- URLSearchParamsPlugin,
+ CustomEventPlugin,
+ DOMExceptionPlugin,
+ EventPlugin,
+ FormDataPlugin,
+ HeadersPlugin,
+ ReadableStreamPlugin,
+ RequestPlugin,
+ ResponsePlugin,
+ URLPlugin,
+ URLSearchParamsPlugin
} from "seroval-plugins/web";
import { sharedConfig } from "solid-js";
import { renderToString } from "solid-js/web";
@@ -28,337 +24,316 @@ import type { FetchEvent, PageEvent } from "./types.ts";
import { getExpectedRedirectStatus } from "./util.ts";
function createChunk(data: string) {
- const encodeData = new TextEncoder().encode(data);
- const bytes = encodeData.length;
- const baseHex = bytes.toString(16);
- const totalHex = "00000000".substring(0, 8 - baseHex.length) + baseHex; // 32-bit
- const head = new TextEncoder().encode(`;0x${totalHex};`);
+ const encodeData = new TextEncoder().encode(data);
+ const bytes = encodeData.length;
+ const baseHex = bytes.toString(16);
+ const totalHex = "00000000".substring(0, 8 - baseHex.length) + baseHex; // 32-bit
+ const head = new TextEncoder().encode(`;0x${totalHex};`);
- const chunk = new Uint8Array(12 + bytes);
- chunk.set(head);
- chunk.set(encodeData, 12);
- return chunk;
+ const chunk = new Uint8Array(12 + bytes);
+ chunk.set(head);
+ chunk.set(encodeData, 12);
+ return chunk;
}
function serializeToStream(id: string, value: any) {
- return new ReadableStream({
- start(controller) {
- crossSerializeStream(value, {
- scopeId: id,
- plugins: [
- CustomEventPlugin,
- DOMExceptionPlugin,
- EventPlugin,
- FormDataPlugin,
- HeadersPlugin,
- ReadableStreamPlugin,
- RequestPlugin,
- ResponsePlugin,
- URLSearchParamsPlugin,
- URLPlugin,
- ],
- onSerialize(data: string, initial: boolean) {
- controller.enqueue(
- createChunk(
- initial ? `(${getCrossReferenceHeader(id)},${data})` : data,
- ),
- );
- },
- onDone() {
- controller.close();
- },
- onError(error: any) {
- controller.error(error);
- },
- });
- },
- });
+ return new ReadableStream({
+ start(controller) {
+ crossSerializeStream(value, {
+ scopeId: id,
+ plugins: [
+ CustomEventPlugin,
+ DOMExceptionPlugin,
+ EventPlugin,
+ FormDataPlugin,
+ HeadersPlugin,
+ ReadableStreamPlugin,
+ RequestPlugin,
+ ResponsePlugin,
+ URLSearchParamsPlugin,
+ URLPlugin
+ ],
+ onSerialize(data: string, initial: boolean) {
+ controller.enqueue(
+ createChunk(initial ? `(${getCrossReferenceHeader(id)},${data})` : data)
+ );
+ },
+ onDone() {
+ controller.close();
+ },
+ onError(error: any) {
+ controller.error(error);
+ }
+ });
+ }
+ });
}
export async function handleServerFunction(h3Event: H3Event) {
- const event = getFetchEvent(h3Event);
- const request = event.request;
+ const event = getFetchEvent(h3Event);
+ const request = event.request;
- const serverReference = request.headers.get("X-Server-Id");
- const instance = request.headers.get("X-Server-Instance");
- const singleFlight = request.headers.has("X-Single-Flight");
- const url = new URL(request.url);
- let functionId: string | undefined | null;
- if (serverReference) {
- // invariant(typeof serverReference === "string", "Invalid server function");
- [functionId] = serverReference.split("#");
- } else {
- functionId = url.searchParams.get("id");
+ const serverReference = request.headers.get("X-Server-Id");
+ const instance = request.headers.get("X-Server-Instance");
+ const singleFlight = request.headers.has("X-Single-Flight");
+ const url = new URL(request.url);
+ let functionId: string | undefined | null;
+ if (serverReference) {
+ // invariant(typeof serverReference === "string", "Invalid server function");
+ [functionId] = serverReference.split("#");
+ } else {
+ functionId = url.searchParams.get("id");
- if (!functionId) {
- return process.env.NODE_ENV === "development"
- ? new Response("Server function not found", { status: 404 })
- : new Response(null, { status: 404 });
- }
- }
+ if (!functionId) {
+ return process.env.NODE_ENV === "development"
+ ? new Response("Server function not found", { status: 404 })
+ : new Response(null, { status: 404 });
+ }
+ }
- const serverFunction = await getServerFnById(functionId!);
+ const serverFunction = await getServerFnById(functionId!);
- let parsed: any[] = [];
+ let parsed: any[] = [];
- // grab bound arguments from url when no JS
- if (!instance || h3Event.method === "GET") {
- const args = url.searchParams.get("args");
- if (args) {
- const json = JSON.parse(args);
- (json.t
- ? (fromJSON(json, {
- plugins: [
- CustomEventPlugin,
- DOMExceptionPlugin,
- EventPlugin,
- FormDataPlugin,
- HeadersPlugin,
- ReadableStreamPlugin,
- RequestPlugin,
- ResponsePlugin,
- URLSearchParamsPlugin,
- URLPlugin,
- ],
- }) as any)
- : json
- ).forEach((arg: any) => {
- parsed.push(arg);
- });
- }
- }
- if (h3Event.method === "POST") {
- const contentType = request.headers.get("content-type");
+ // grab bound arguments from url when no JS
+ if (!instance || h3Event.method === "GET") {
+ const args = url.searchParams.get("args");
+ if (args) {
+ const json = JSON.parse(args);
+ (json.t
+ ? (fromJSON(json, {
+ plugins: [
+ CustomEventPlugin,
+ DOMExceptionPlugin,
+ EventPlugin,
+ FormDataPlugin,
+ HeadersPlugin,
+ ReadableStreamPlugin,
+ RequestPlugin,
+ ResponsePlugin,
+ URLSearchParamsPlugin,
+ URLPlugin
+ ]
+ }) as any)
+ : json
+ ).forEach((arg: any) => {
+ parsed.push(arg);
+ });
+ }
+ }
+ if (h3Event.method === "POST") {
+ const contentType = request.headers.get("content-type");
- if (
- contentType?.startsWith("multipart/form-data") ||
- contentType?.startsWith("application/x-www-form-urlencoded")
- ) {
- parsed.push(await event.request.formData());
- } else if (contentType?.startsWith("application/json")) {
- parsed = fromJSON(await event.request.json(), {
- plugins: [
- CustomEventPlugin,
- DOMExceptionPlugin,
- EventPlugin,
- FormDataPlugin,
- HeadersPlugin,
- ReadableStreamPlugin,
- RequestPlugin,
- ResponsePlugin,
- URLSearchParamsPlugin,
- URLPlugin,
- ],
- });
- }
- }
- try {
- let result = await provideRequestEvent(event, async () => {
- /* @ts-expect-error */
- sharedConfig.context = { event };
- event.locals.serverFunctionMeta = {
- id: functionId
- };
- return serverFunction(...parsed);
- });
+ if (
+ contentType?.startsWith("multipart/form-data") ||
+ contentType?.startsWith("application/x-www-form-urlencoded")
+ ) {
+ parsed.push(await event.request.formData());
+ } else if (contentType?.startsWith("application/json")) {
+ parsed = fromJSON(await event.request.json(), {
+ plugins: [
+ CustomEventPlugin,
+ DOMExceptionPlugin,
+ EventPlugin,
+ FormDataPlugin,
+ HeadersPlugin,
+ ReadableStreamPlugin,
+ RequestPlugin,
+ ResponsePlugin,
+ URLSearchParamsPlugin,
+ URLPlugin
+ ]
+ });
+ }
+ }
+ try {
+ let result = await provideRequestEvent(event, async () => {
+ /* @ts-expect-error */
+ sharedConfig.context = { event };
+ event.locals.serverFunctionMeta = {
+ id: functionId
+ };
+ return serverFunction(...parsed);
+ });
- if (singleFlight && instance) {
- result = await handleSingleFlight(event, result);
- }
+ if (singleFlight && instance) {
+ result = await handleSingleFlight(event, result);
+ }
- // handle responses
- if (result instanceof Response) {
- if (result.headers && result.headers.has("X-Content-Raw")) return result;
- if (instance) {
- // forward headers
- if (result.headers) mergeResponseHeaders(h3Event, result.headers);
- // forward non-redirect statuses
- if (result.status && (result.status < 300 || result.status >= 400))
- h3Event.res.status = result.status;
- if ((result as any).customBody) {
- result = await (result as any).customBody();
- } else if (result.body == undefined) result = null;
- }
- }
+ // handle responses
+ if (result instanceof Response) {
+ if (result.headers && result.headers.has("X-Content-Raw")) return result;
+ if (instance) {
+ // forward headers
+ if (result.headers) mergeResponseHeaders(h3Event, result.headers);
+ // forward non-redirect statuses
+ if (result.status && (result.status < 300 || result.status >= 400))
+ h3Event.res.status = result.status;
+ if ((result as any).customBody) {
+ result = await (result as any).customBody();
+ } else if (result.body == undefined) result = null;
+ }
+ }
- // handle no JS success case
- if (!instance) return handleNoJS(result, request, parsed);
+ // handle no JS success case
+ if (!instance) return handleNoJS(result, request, parsed);
- h3Event.res.headers.set("content-type", "text/javascript");
+ h3Event.res.headers.set("content-type", "text/javascript");
- return serializeToStream(instance, result);
- } catch (x) {
- if (x instanceof Response) {
- if (singleFlight && instance) {
- x = await handleSingleFlight(event, x);
- }
- // forward headers
- if ((x as any).headers) mergeResponseHeaders(h3Event, (x as any).headers);
- // forward non-redirect statuses
- if (
- (x as any).status &&
- (!instance || (x as any).status < 300 || (x as any).status >= 400)
- )
- h3Event.res.status = (x as any).status;
- if ((x as any).customBody) {
- x = (x as any).customBody();
- } else if ((x as any).body === undefined) x = null;
- h3Event.res.headers.set("X-Error", "true");
- } else if (instance) {
- const error =
- x instanceof Error ? x.message : typeof x === "string" ? x : "true";
+ return serializeToStream(instance, result);
+ } catch (x) {
+ if (x instanceof Response) {
+ if (singleFlight && instance) {
+ x = await handleSingleFlight(event, x);
+ }
+ // forward headers
+ if ((x as any).headers) mergeResponseHeaders(h3Event, (x as any).headers);
+ // forward non-redirect statuses
+ if ((x as any).status && (!instance || (x as any).status < 300 || (x as any).status >= 400))
+ h3Event.res.status = (x as any).status;
+ if ((x as any).customBody) {
+ x = (x as any).customBody();
+ } else if ((x as any).body === undefined) x = null;
+ h3Event.res.headers.set("X-Error", "true");
+ } else if (instance) {
+ const error = x instanceof Error ? x.message : typeof x === "string" ? x : "true";
- h3Event.res.headers.set("X-Error", error.replace(/[\r\n]+/g, ""));
- } else {
- x = handleNoJS(x, request, parsed, true);
- }
- if (instance) {
- h3Event.res.headers.set("content-type", "text/javascript");
- return serializeToStream(instance, x);
- }
- return x;
- }
+ h3Event.res.headers.set("X-Error", error.replace(/[\r\n]+/g, ""));
+ } else {
+ x = handleNoJS(x, request, parsed, true);
+ }
+ if (instance) {
+ h3Event.res.headers.set("content-type", "text/javascript");
+ return serializeToStream(instance, x);
+ }
+ return x;
+ }
}
-function handleNoJS(
- result: any,
- request: Request,
- parsed: any[],
- thrown?: boolean,
-) {
- const url = new URL(request.url);
- const isError = result instanceof Error;
- let statusCode = 302;
- let headers: Headers;
- if (result instanceof Response) {
- headers = new Headers(result.headers);
- if (result.headers.has("Location")) {
- headers.set(
- `Location`,
- new URL(
- result.headers.get("Location")!,
- url.origin + import.meta.env.BASE_URL,
- ).toString(),
- );
- statusCode = getExpectedRedirectStatus(result);
- }
- } else
- headers = new Headers({
- Location: new URL(request.headers.get("referer")!).toString(),
- });
- if (result) {
- headers.append(
- "Set-Cookie",
- `flash=${encodeURIComponent(
- JSON.stringify({
- url: url.pathname + url.search,
- result: isError ? result.message : result,
- thrown: thrown,
- error: isError,
- input: [
- ...parsed.slice(0, -1),
- [...parsed[parsed.length - 1].entries()],
- ],
- }),
- )}; Secure; HttpOnly;`,
- );
- }
- return new Response(null, {
- status: statusCode,
- headers,
- });
+function handleNoJS(result: any, request: Request, parsed: any[], thrown?: boolean) {
+ const url = new URL(request.url);
+ const isError = result instanceof Error;
+ let statusCode = 302;
+ let headers: Headers;
+ if (result instanceof Response) {
+ headers = new Headers(result.headers);
+ if (result.headers.has("Location")) {
+ headers.set(
+ `Location`,
+ new URL(result.headers.get("Location")!, url.origin + import.meta.env.BASE_URL).toString()
+ );
+ statusCode = getExpectedRedirectStatus(result);
+ }
+ } else
+ headers = new Headers({
+ Location: new URL(request.headers.get("referer")!).toString()
+ });
+ if (result) {
+ headers.append(
+ "Set-Cookie",
+ `flash=${encodeURIComponent(
+ JSON.stringify({
+ url: url.pathname + url.search,
+ result: isError ? result.message : result,
+ thrown: thrown,
+ error: isError,
+ input: [...parsed.slice(0, -1), [...parsed[parsed.length - 1].entries()]]
+ })
+ )}; Secure; HttpOnly;`
+ );
+ }
+ return new Response(null, {
+ status: statusCode,
+ headers
+ });
}
let App: any;
function createSingleFlightHeaders(sourceEvent: FetchEvent) {
- // cookie handling logic is pretty simplistic so this might be imperfect
- // unclear if h3 internals are available on all platforms but we need a way to
- // update request headers on the underlying H3 event.
+ // cookie handling logic is pretty simplistic so this might be imperfect
+ // unclear if h3 internals are available on all platforms but we need a way to
+ // update request headers on the underlying H3 event.
- const headers = sourceEvent.request.headers;
- const cookies = parseCookies(sourceEvent.nativeEvent);
- const SetCookies = sourceEvent.response.headers.getSetCookie();
- headers.delete("cookie");
- // let useH3Internals = false;
- // if (sourceEvent.nativeEvent.node?.req) {
- // useH3Internals = true;
- // sourceEvent.nativeEvent.node.req.headers.cookie = "";
- // }
- SetCookies.forEach((cookie) => {
- if (!cookie) return;
- const { maxAge, expires, name, value } = parseSetCookie(cookie);
- if (maxAge != null && maxAge <= 0) {
- delete cookies[name];
- return;
- }
- if (expires != null && expires.getTime() <= Date.now()) {
- delete cookies[name];
- return;
- }
- cookies[name] = value;
- });
- Object.entries(cookies).forEach(([key, value]) => {
- headers.append("cookie", `${key}=${value}`);
- // useH3Internals &&
- // (sourceEvent.nativeEvent.node.req.headers.cookie += `${key}=${value};`);
- });
+ const headers = sourceEvent.request.headers;
+ const cookies = parseCookies(sourceEvent.nativeEvent);
+ const SetCookies = sourceEvent.response.headers.getSetCookie();
+ headers.delete("cookie");
+ // let useH3Internals = false;
+ // if (sourceEvent.nativeEvent.node?.req) {
+ // useH3Internals = true;
+ // sourceEvent.nativeEvent.node.req.headers.cookie = "";
+ // }
+ SetCookies.forEach(cookie => {
+ if (!cookie) return;
+ const { maxAge, expires, name, value } = parseSetCookie(cookie);
+ if (maxAge != null && maxAge <= 0) {
+ delete cookies[name];
+ return;
+ }
+ if (expires != null && expires.getTime() <= Date.now()) {
+ delete cookies[name];
+ return;
+ }
+ cookies[name] = value;
+ });
+ Object.entries(cookies).forEach(([key, value]) => {
+ headers.append("cookie", `${key}=${value}`);
+ // useH3Internals &&
+ // (sourceEvent.nativeEvent.node.req.headers.cookie += `${key}=${value};`);
+ });
- return headers;
+ return headers;
}
-async function handleSingleFlight(
- sourceEvent: FetchEvent,
- result: any,
-): Promise {
- let revalidate: string[];
- let url = new URL(sourceEvent.request.headers.get("referer")!).toString();
- if (result instanceof Response) {
- if (result.headers.has("X-Revalidate"))
- revalidate = result.headers.get("X-Revalidate")!.split(",");
- if (result.headers.has("Location"))
- url = new URL(
- result.headers.get("Location")!,
- new URL(sourceEvent.request.url).origin +
- import.meta.env.BASE_URL,
- ).toString();
- }
- const event = { ...sourceEvent } as PageEvent;
- event.request = new Request(url, {
- headers: createSingleFlightHeaders(sourceEvent),
- });
- return await provideRequestEvent(event, async () => {
- await createPageEvent(event);
- App || (App = (await import("solid-start:app")).default);
- /* @ts-expect-error */
- event.router.dataOnly = revalidate || true;
- /* @ts-expect-error */
- event.router.previousUrl = sourceEvent.request.headers.get("referer");
- try {
- renderToString(() => {
- /* @ts-expect-error */
- sharedConfig.context.event = event;
- App();
- });
- } catch (e) {
- console.log(e);
- }
+async function handleSingleFlight(sourceEvent: FetchEvent, result: any): Promise {
+ let revalidate: string[];
+ let url = new URL(sourceEvent.request.headers.get("referer")!).toString();
+ if (result instanceof Response) {
+ if (result.headers.has("X-Revalidate"))
+ revalidate = result.headers.get("X-Revalidate")!.split(",");
+ if (result.headers.has("Location"))
+ url = new URL(
+ result.headers.get("Location")!,
+ new URL(sourceEvent.request.url).origin + import.meta.env.BASE_URL
+ ).toString();
+ }
+ const event = { ...sourceEvent } as PageEvent;
+ event.request = new Request(url, {
+ headers: createSingleFlightHeaders(sourceEvent)
+ });
+ return await provideRequestEvent(event, async () => {
+ await createPageEvent(event);
+ App || (App = (await import("solid-start:app")).default);
+ /* @ts-expect-error */
+ event.router.dataOnly = revalidate || true;
+ /* @ts-expect-error */
+ event.router.previousUrl = sourceEvent.request.headers.get("referer");
+ try {
+ renderToString(() => {
+ /* @ts-expect-error */
+ sharedConfig.context.event = event;
+ App();
+ });
+ } catch (e) {
+ console.log(e);
+ }
- /* @ts-expect-error */
- const body = event.router.data;
- if (!body) return result;
- let containsKey = false;
- for (const key in body) {
- if (body[key] === undefined) delete body[key];
- else containsKey = true;
- }
- if (!containsKey) return result;
- if (!(result instanceof Response)) {
- body["_$value"] = result;
- result = new Response(null, { status: 200 });
- } else if ((result as any).customBody) {
- body["_$value"] = (result as any).customBody();
- }
- result.customBody = () => body;
- result.headers.set("X-Single-Flight", "true");
- return result;
- });
+ /* @ts-expect-error */
+ const body = event.router.data;
+ if (!body) return result;
+ let containsKey = false;
+ for (const key in body) {
+ if (body[key] === undefined) delete body[key];
+ else containsKey = true;
+ }
+ if (!containsKey) return result;
+ if (!(result instanceof Response)) {
+ body["_$value"] = result;
+ result = new Response(null, { status: 200 });
+ } else if ((result as any).customBody) {
+ body["_$value"] = (result as any).customBody();
+ }
+ result.customBody = () => body;
+ result.headers.set("X-Single-Flight", "true");
+ return result;
+ });
}
diff --git a/packages/start/src/server/server-runtime.ts b/packages/start/src/server/server-runtime.ts
index 0af198aea..3a3c915dc 100644
--- a/packages/start/src/server/server-runtime.ts
+++ b/packages/start/src/server/server-runtime.ts
@@ -195,7 +195,7 @@ async function fetchServerFunction(
export function createServerReference(id: string) {
let baseURL = import.meta.env.BASE_URL ?? "/";
- if(!baseURL.endsWith("/")) baseURL += "/"
+ if (!baseURL.endsWith("/")) baseURL += "/";
const fn = (...args: any[]) => fetchServerFunction(`${baseURL}_server`, id, {}, args);
@@ -231,7 +231,7 @@ export function createServerReference(id: string) {
};
}
return (target as any)[prop];
- },
+ }
});
}
diff --git a/packages/start/src/server/spa/handler.ts b/packages/start/src/server/spa/handler.ts
index a9234d0c8..8b53af6a3 100644
--- a/packages/start/src/server/spa/handler.ts
+++ b/packages/start/src/server/spa/handler.ts
@@ -9,21 +9,21 @@ import type { FetchEvent, HandlerOptions, PageEvent } from "../types.ts";
* Read more: https://docs.solidjs.com/solid-start/reference/server/create-handler
*/
export function createHandler(
- fn: (context: PageEvent) => JSX.Element,
- options?: HandlerOptions | ((context: PageEvent) => HandlerOptions),
+ fn: (context: PageEvent) => JSX.Element,
+ options?: HandlerOptions | ((context: PageEvent) => HandlerOptions)
) {
- return createBaseHandler(createPageEvent, fn, options);
+ return createBaseHandler(createPageEvent, fn, options);
}
async function createPageEvent(ctx: FetchEvent) {
- const manifest = getSsrManifest("ssr");
- const pageEvent: PageEvent = Object.assign(ctx, {
- manifest: "json" in manifest ? await manifest.json() : {},
- assets: await manifest.getAssets(import.meta.env.START_CLIENT_ENTRY),
- routes: [],
- complete: false,
- $islands: new Set(),
- });
+ const manifest = getSsrManifest("ssr");
+ const pageEvent: PageEvent = Object.assign(ctx, {
+ manifest: "json" in manifest ? await manifest.json() : {},
+ assets: await manifest.getAssets(import.meta.env.START_CLIENT_ENTRY),
+ routes: [],
+ complete: false,
+ $islands: new Set()
+ });
- return pageEvent;
+ return pageEvent;
}
diff --git a/packages/start/src/server/types.ts b/packages/start/src/server/types.ts
index 52998b597..b59467f78 100644
--- a/packages/start/src/server/types.ts
+++ b/packages/start/src/server/types.ts
@@ -5,78 +5,78 @@ import type { RequestEvent } from "solid-js/web";
// export const FETCH_EVENT = "$FETCH";
export type DocumentComponentProps = {
- assets?: JSX.Element;
- scripts: JSX.Element;
- children?: JSX.Element;
+ assets?: JSX.Element;
+ scripts: JSX.Element;
+ children?: JSX.Element;
};
export type Asset =
- | {
- tag: "style";
- attrs: JSX.StyleHTMLAttributes & { key?: string };
- children?: JSX.Element;
- }
- | {
- tag: "script";
- attrs: JSX.ScriptHTMLAttributes & { key?: string };
- }
- | {
- tag: "link";
- attrs: JSX.LinkHTMLAttributes & { key?: string };
- };
+ | {
+ tag: "style";
+ attrs: JSX.StyleHTMLAttributes & { key?: string };
+ children?: JSX.Element;
+ }
+ | {
+ tag: "script";
+ attrs: JSX.ScriptHTMLAttributes & { key?: string };
+ }
+ | {
+ tag: "link";
+ attrs: JSX.LinkHTMLAttributes & { key?: string };
+ };
export type HandlerOptions = {
- mode?: "sync" | "async" | "stream";
- nonce?: string;
- renderId?: string;
- onCompleteAll?: (options: { write: (v: any) => void }) => void;
- onCompleteShell?: (options: { write: (v: any) => void }) => void;
+ mode?: "sync" | "async" | "stream";
+ nonce?: string;
+ renderId?: string;
+ onCompleteAll?: (options: { write: (v: any) => void }) => void;
+ onCompleteShell?: (options: { write: (v: any) => void }) => void;
};
export type ContextMatches = {
- originalPath: string;
- pattern: string;
- path: string;
- params: unknown;
+ originalPath: string;
+ pattern: string;
+ path: string;
+ params: unknown;
};
export interface ResponseStub {
- status?: number;
- statusText?: string;
- headers: Headers;
+ status?: number;
+ statusText?: string;
+ headers: Headers;
}
export interface FetchEvent {
- request: Request;
- response: ResponseStub;
- clientAddress?: string;
- locals: App.RequestEventLocals;
- nativeEvent: H3Event;
+ request: Request;
+ response: ResponseStub;
+ clientAddress?: string;
+ locals: App.RequestEventLocals;
+ nativeEvent: H3Event;
}
export interface PageEvent extends RequestEvent {
- assets: any[];
- routes: any[];
- // prevUrl: string | null;
- // $type: typeof FETCH_EVENT;
- $islands: Set;
- complete: boolean;
- nonce?: string;
- // mutation: boolean;
+ assets: any[];
+ routes: any[];
+ // prevUrl: string | null;
+ // $type: typeof FETCH_EVENT;
+ $islands: Set;
+ complete: boolean;
+ nonce?: string;
+ // mutation: boolean;
}
export interface APIEvent extends FetchEvent {
- params: { [key: string]: string };
+ params: { [key: string]: string };
}
export type APIHandler = (event: APIEvent) => Promise;
export interface ServerFunctionMeta {
- id: string;
+ id: string;
}
declare module "solid-js/web" {
- interface RequestEvent extends FetchEvent {
- serverOnly?: boolean;
- }
+ interface RequestEvent extends FetchEvent {
+ serverOnly?: boolean;
+ }
}
diff --git a/packages/start/src/server/util.ts b/packages/start/src/server/util.ts
index 5aa7f0d07..da325bf49 100644
--- a/packages/start/src/server/util.ts
+++ b/packages/start/src/server/util.ts
@@ -4,9 +4,9 @@ import type { ResponseStub } from "./types.ts";
const validRedirectStatuses = new Set([301, 302, 303, 307, 308]);
export function getExpectedRedirectStatus(response: ResponseStub): number {
- if (response.status && validRedirectStatuses.has(response.status)) {
- return response.status;
- }
+ if (response.status && validRedirectStatuses.has(response.status)) {
+ return response.status;
+ }
- return 302;
+ return 302;
}
diff --git a/packages/start/src/shared/HttpHeader.tsx b/packages/start/src/shared/HttpHeader.tsx
index 30e061a4c..6dcb504b6 100644
--- a/packages/start/src/shared/HttpHeader.tsx
+++ b/packages/start/src/shared/HttpHeader.tsx
@@ -17,26 +17,26 @@ export interface HttpHeaderProps {
*/
export const HttpHeader = isServer
? (props: HttpHeaderProps) => {
- const event = getRequestEvent() as PageEvent;
+ const event = getRequestEvent() as PageEvent;
- if (props.append) appendHeader(props.name, props.value);
- else setHeader(props.name, props.value);
+ if (props.append) appendHeader(props.name, props.value);
+ else setHeader(props.name, props.value);
- onCleanup(() => {
- // @ts-expect-error
- if (event.nativeEvent.handled || event.complete) return;
- const value = event.response.headers.get(props.name);
- if (!value) return;
- if (!value.includes(", ")) {
- if (value === props.value) event.response.headers.delete(props.name);
- return;
- }
- const values = value.split(", ");
- const index = values.indexOf(props.value);
- index !== -1 && values.splice(index, 1);
- if (values.length) event.response.headers.set(props.name, values.join(","));
- else event.response.headers.delete(props.name);
- });
- return null;
- }
+ onCleanup(() => {
+ // @ts-expect-error
+ if (event.nativeEvent.handled || event.complete) return;
+ const value = event.response.headers.get(props.name);
+ if (!value) return;
+ if (!value.includes(", ")) {
+ if (value === props.value) event.response.headers.delete(props.name);
+ return;
+ }
+ const values = value.split(", ");
+ const index = values.indexOf(props.value);
+ index !== -1 && values.splice(index, 1);
+ if (values.length) event.response.headers.set(props.name, values.join(","));
+ else event.response.headers.delete(props.name);
+ });
+ return null;
+ }
: (_props: HttpHeaderProps) => null;
diff --git a/packages/start/src/shared/HttpStatusCode.ts b/packages/start/src/shared/HttpStatusCode.ts
index b378f93cb..aa1655409 100644
--- a/packages/start/src/shared/HttpStatusCode.ts
+++ b/packages/start/src/shared/HttpStatusCode.ts
@@ -4,8 +4,8 @@ import { getRequestEvent, isServer } from "solid-js/web";
import type { PageEvent } from "../server/types.ts";
export interface HttpStatusCodeProps {
- code: number;
- text?: string;
+ code: number;
+ text?: string;
}
/**
@@ -13,15 +13,15 @@ export interface HttpStatusCodeProps {
* Read more: https://docs.solidjs.com/solid-start/reference/server/http-status-code
*/
export const HttpStatusCode = isServer
- ? (props: HttpStatusCodeProps) => {
- const event = getRequestEvent() as PageEvent;
- event.response.status = props.code;
- event.response.statusText = props.text;
- onCleanup(
- () =>
- // !event.nativeEvent.handled &&
- !event.complete && (event.response.status = 200),
- );
- return null;
- }
- : (_props: HttpStatusCodeProps) => null;
+ ? (props: HttpStatusCodeProps) => {
+ const event = getRequestEvent() as PageEvent;
+ event.response.status = props.code;
+ event.response.statusText = props.text;
+ onCleanup(
+ () =>
+ // !event.nativeEvent.handled &&
+ !event.complete && (event.response.status = 200)
+ );
+ return null;
+ }
+ : (_props: HttpStatusCodeProps) => null;
diff --git a/packages/start/src/shared/dev-overlay/CodeView.tsx b/packages/start/src/shared/dev-overlay/CodeView.tsx
index 3116ce5e5..6397fed89 100644
--- a/packages/start/src/shared/dev-overlay/CodeView.tsx
+++ b/packages/start/src/shared/dev-overlay/CodeView.tsx
@@ -1,31 +1,24 @@
// @refresh skip
-import { getSingletonHighlighter, type BuiltinLanguage, type Highlighter } from 'shiki';
-import { loadWasm } from 'shiki/engine/oniguruma';
-import { createEffect, createResource, type JSX } from 'solid-js';
+import { getSingletonHighlighter, type BuiltinLanguage, type Highlighter } from "shiki";
+import { loadWasm } from "shiki/engine/oniguruma";
+import { createEffect, createResource, type JSX } from "solid-js";
-import url from 'shiki/onig.wasm?url';
+import url from "shiki/onig.wasm?url";
-import langJS from 'shiki/langs/javascript.mjs';
-import langJSX from 'shiki/langs/jsx.mjs';
-import langTSX from 'shiki/langs/tsx.mjs';
-import langTS from 'shiki/langs/typescript.mjs';
-import darkPlus from 'shiki/themes/dark-plus.mjs';
+import langJS from "shiki/langs/javascript.mjs";
+import langJSX from "shiki/langs/jsx.mjs";
+import langTSX from "shiki/langs/tsx.mjs";
+import langTS from "shiki/langs/typescript.mjs";
+import darkPlus from "shiki/themes/dark-plus.mjs";
let HIGHLIGHTER: Highlighter;
async function loadHighlighter() {
if (!HIGHLIGHTER) {
- await loadWasm(await fetch(url))
+ await loadWasm(await fetch(url));
HIGHLIGHTER = await getSingletonHighlighter({
- themes: [
- darkPlus,
- ],
- langs: [
- langJS,
- langJSX,
- langTS,
- langTSX,
- ],
+ themes: [darkPlus],
+ langs: [langJS, langJSX, langTS, langTSX]
});
}
return HIGHLIGHTER;
@@ -41,9 +34,9 @@ const RANGE = 8;
export function CodeView(props: CodeViewProps): JSX.Element | null {
const lines = () =>
- props.content.split('\n').map((item, index) => ({
+ props.content.split("\n").map((item, index) => ({
index: index + 1,
- line: item,
+ line: item
}));
const minLine = () => Math.max(props.line - (1 + RANGE), 0);
@@ -51,27 +44,25 @@ export function CodeView(props: CodeViewProps): JSX.Element | null {
let ref: HTMLDivElement | undefined;
- const [data] = createResource(() => (
- lines()
- .slice(minLine(), maxLine())
- .map(item => item.line)
- .join('\n')
- ) ,async (value) => {
- const highlighter = await loadHighlighter();
- const fileExtension = props.fileName
- .split(/[#?]/)[0]!
- .split('.')
- .pop()
- ?.trim();
- let lang = fileExtension as BuiltinLanguage;
- if (fileExtension === 'mjs' || fileExtension === 'cjs') {
- lang = 'js';
+ const [data] = createResource(
+ () =>
+ lines()
+ .slice(minLine(), maxLine())
+ .map(item => item.line)
+ .join("\n"),
+ async value => {
+ const highlighter = await loadHighlighter();
+ const fileExtension = props.fileName.split(/[#?]/)[0]!.split(".").pop()?.trim();
+ let lang = fileExtension as BuiltinLanguage;
+ if (fileExtension === "mjs" || fileExtension === "cjs") {
+ lang = "js";
+ }
+ return highlighter.codeToHtml(value, {
+ theme: "dark-plus",
+ lang
+ });
}
- return highlighter.codeToHtml(value, {
- theme: 'dark-plus',
- lang,
- });
- });
+ );
createEffect(() => {
const result = data();
@@ -82,14 +73,20 @@ export function CodeView(props: CodeViewProps): JSX.Element | null {
for (let i = 0, len = lines.length; i < len; i++) {
const el = lines[i] as HTMLElement;
- if ((props.line - minLine() - 1) === i) {
- el.classList.add('dev-overlay-error-line');
+ if (props.line - minLine() - 1 === i) {
+ el.classList.add("dev-overlay-error-line");
}
}
}
});
- return
;
+ return (
+
+ );
}
diff --git a/packages/start/src/shared/dev-overlay/createStackFrame.ts b/packages/start/src/shared/dev-overlay/createStackFrame.ts
index 7d5bd8e90..4cd2ce89d 100644
--- a/packages/start/src/shared/dev-overlay/createStackFrame.ts
+++ b/packages/start/src/shared/dev-overlay/createStackFrame.ts
@@ -2,76 +2,73 @@ import { type Accessor, createMemo, createResource } from "solid-js";
import getSourceMap from "./get-source-map.ts";
export interface StackFrameSource {
- content: string;
- source: string;
- name?: string;
- line: number;
- column: number;
+ content: string;
+ source: string;
+ name?: string;
+ line: number;
+ column: number;
}
function getActualFileSource(path: string): string {
- if (path.startsWith("file://")) {
- return "/_build/@fs" + path.substring("file://".length);
- }
- return path;
+ if (path.startsWith("file://")) {
+ return "/_build/@fs" + path.substring("file://".length);
+ }
+ return path;
}
-export function createStackFrame(
- stackframe: StackFrame,
- isCompiled: () => boolean,
-) {
- const [data] = createResource(
- () => ({
- fileName: stackframe.fileName,
- line: stackframe.lineNumber,
- column: stackframe.columnNumber,
- functionName: stackframe.functionName,
- }),
- async (source) => {
- if (!source.fileName) {
- return null;
- }
- const response = await fetch(getActualFileSource(source.fileName));
- if (!response.ok) {
- return null;
- }
- const content = await response.text();
- const sourceMap = await getSourceMap(source.fileName, content);
- return {
- source,
- content,
- sourceMap,
- };
- },
- );
+export function createStackFrame(stackframe: StackFrame, isCompiled: () => boolean) {
+ const [data] = createResource(
+ () => ({
+ fileName: stackframe.fileName,
+ line: stackframe.lineNumber,
+ column: stackframe.columnNumber,
+ functionName: stackframe.functionName
+ }),
+ async source => {
+ if (!source.fileName) {
+ return null;
+ }
+ const response = await fetch(getActualFileSource(source.fileName));
+ if (!response.ok) {
+ return null;
+ }
+ const content = await response.text();
+ const sourceMap = await getSourceMap(source.fileName, content);
+ return {
+ source,
+ content,
+ sourceMap
+ };
+ }
+ );
- const info = createMemo(() => {
- const current = data();
- if (!current) {
- return undefined;
- }
- const { source, content, sourceMap } = current;
+ const info = createMemo(() => {
+ const current = data();
+ if (!current) {
+ return undefined;
+ }
+ const { source, content, sourceMap } = current;
- if (!isCompiled() && source.line && source.column && sourceMap) {
- const result = sourceMap.originalPositionFor({
- line: source.line,
- column: source.column,
- });
+ if (!isCompiled() && source.line && source.column && sourceMap) {
+ const result = sourceMap.originalPositionFor({
+ line: source.line,
+ column: source.column
+ });
- return {
- ...result,
- content: sourceMap.sourceContentFor(result.source),
- } as StackFrameSource;
- }
+ return {
+ ...result,
+ content: sourceMap.sourceContentFor(result.source)
+ } as StackFrameSource;
+ }
- return {
- source: source.fileName,
- line: source.line,
- column: source.column,
- name: source.functionName,
- content,
- } as StackFrameSource;
- });
+ return {
+ source: source.fileName,
+ line: source.line,
+ column: source.column,
+ name: source.functionName,
+ content
+ } as StackFrameSource;
+ });
- return info as Accessor;
+ return info as Accessor;
}
diff --git a/packages/start/src/shared/dev-overlay/env.d.ts b/packages/start/src/shared/dev-overlay/env.d.ts
index 8c54073db..ac68ef8f4 100644
--- a/packages/start/src/shared/dev-overlay/env.d.ts
+++ b/packages/start/src/shared/dev-overlay/env.d.ts
@@ -1,4 +1,4 @@
-declare module '*.json' {
+declare module "*.json" {
const data: Record;
export default data;
-}
\ No newline at end of file
+}
diff --git a/packages/start/src/shared/dev-overlay/get-source-map.ts b/packages/start/src/shared/dev-overlay/get-source-map.ts
index 2b8b164d6..3be94e8c6 100644
--- a/packages/start/src/shared/dev-overlay/get-source-map.ts
+++ b/packages/start/src/shared/dev-overlay/get-source-map.ts
@@ -1,4 +1,4 @@
-import { RawSourceMap, SourceMapConsumer } from 'source-map-js';
+import { RawSourceMap, SourceMapConsumer } from "source-map-js";
const INLINE_SOURCEMAP_REGEX = /^data:application\/json[^,]+base64,/;
const SOURCEMAP_REGEX =
@@ -6,9 +6,9 @@ const SOURCEMAP_REGEX =
export default async function getSourceMap(
url: string,
- content: string,
+ content: string
): Promise {
- const lines = content.split('\n');
+ const lines = content.split("\n");
let sourceMapUrl: string | undefined;
for (let i = lines.length - 1; i >= 0 && !sourceMapUrl; i--) {
const result = lines[i]!.match(SOURCEMAP_REGEX);
@@ -21,13 +21,11 @@ export default async function getSourceMap(
return null;
}
- if (
- !(INLINE_SOURCEMAP_REGEX.test(sourceMapUrl) || sourceMapUrl.startsWith('/'))
- ) {
+ if (!(INLINE_SOURCEMAP_REGEX.test(sourceMapUrl) || sourceMapUrl.startsWith("/"))) {
// Resolve path if it's a relative access
- const parsedURL = url.split('/');
+ const parsedURL = url.split("/");
parsedURL[parsedURL.length - 1] = sourceMapUrl;
- sourceMapUrl = parsedURL.join('/');
+ sourceMapUrl = parsedURL.join("/");
}
const response = await fetch(sourceMapUrl);
const rawSourceMap: RawSourceMap = await response.json();
diff --git a/packages/start/src/shared/dev-overlay/icons.tsx b/packages/start/src/shared/dev-overlay/icons.tsx
index 210d328fa..16156f817 100644
--- a/packages/start/src/shared/dev-overlay/icons.tsx
+++ b/packages/start/src/shared/dev-overlay/icons.tsx
@@ -1,8 +1,8 @@
// @refresh skip
-import type { JSX } from 'solid-js';
+import type { JSX } from "solid-js";
export function ArrowRightIcon(
- props: JSX.IntrinsicElements['svg'] & { title: string },
+ props: JSX.IntrinsicElements["svg"] & { title: string }
): JSX.Element {
return (
{props.title}
-
+
{props.title}
-
+
);
}
export function SolidStartIcon(
- props: JSX.IntrinsicElements['svg'] & { title: string },
+ props: JSX.IntrinsicElements["svg"] & { title: string }
): JSX.Element {
return (
-
+
{props.title}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
}
-
diff --git a/packages/start/src/shared/lazy.ts b/packages/start/src/shared/lazy.ts
index df961921b..5964cf12d 100644
--- a/packages/start/src/shared/lazy.ts
+++ b/packages/start/src/shared/lazy.ts
@@ -45,7 +45,8 @@ const withAssets = function Promise<{ default: Component }
return wrapper as T;
};
-const lazy = !isServer ? solidLazy: >(fn: () => Promise<{ default: T }>) =>
- solidLazy(withAssets(fn));
+const lazy = !isServer
+ ? solidLazy
+ : >(fn: () => Promise<{ default: T }>) => solidLazy(withAssets(fn));
export default lazy;
diff --git a/packages/start/src/shared/serverFunction.ts b/packages/start/src/shared/serverFunction.ts
index 394d4e533..8de3b0a3b 100644
--- a/packages/start/src/shared/serverFunction.ts
+++ b/packages/start/src/shared/serverFunction.ts
@@ -6,5 +6,5 @@ import type { ServerFunctionMeta } from "../server/types.ts";
* Read more: https://docs.solidjs.com/solid-start/reference/server/get-server-function-meta
*/
export function getServerFunctionMeta(): ServerFunctionMeta | undefined {
- return getRequestEvent()?.locals.serverFunctionMeta;
+ return getRequestEvent()?.locals.serverFunctionMeta;
}
diff --git a/packages/start/src/virtual.d.ts b/packages/start/src/virtual.d.ts
index 68ab708ee..53083c11d 100644
--- a/packages/start/src/virtual.d.ts
+++ b/packages/start/src/virtual.d.ts
@@ -1,27 +1,27 @@
declare module "solid-start:client-vite-manifest" {
- export const clientViteManifest: Record<
- string,
- { css?: Array; file: string; [key: string]: unknown }
- >;
+ export const clientViteManifest: Record<
+ string,
+ { css?: Array; file: string; [key: string]: unknown }
+ >;
}
interface StartManifest {
- getAssets(id: string): Promise;
+ getAssets(id: string): Promise;
}
declare module "solid-start:get-client-manifest" {
- export const getClientManifest: () => StartManifest;
+ export const getClientManifest: () => StartManifest;
}
declare module "solid-start:get-manifest" {
- export const getManifest: (target: "client" | "ssr") => StartManifest;
+ export const getManifest: (target: "client" | "ssr") => StartManifest;
}
declare module "solid-start:app" {
- export default App as import("solid-js").Component;
+ export default App as import("solid-js").Component;
}
declare module "solid-start:middleware" {
- type MaybeArray = T | Array;
- export default Middleware as import("h3").Middleware[];
+ type MaybeArray = T | Array;
+ export default Middleware as import("h3").Middleware[];
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 7dede6b22..431773c1c 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -19,6 +19,9 @@ importers:
citty:
specifier: ^0.1.5
version: 0.1.6
+ oxfmt:
+ specifier: ^0.14.0
+ version: 0.14.0
tinyglobby:
specifier: ^0.2.2
version: 0.2.15
@@ -1542,6 +1545,46 @@ packages:
cpu: [x64]
os: [win32]
+ '@oxfmt/darwin-arm64@0.14.0':
+ resolution: {integrity: sha512-g8FANFTuzEcB2KLsE2IcQYXjdgDi8x9GUf8c4t7iyFD7oj0HGucKHhoMz3XsRWTx8szBZoJJD+t4bzs4+AMFdQ==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@oxfmt/darwin-x64@0.14.0':
+ resolution: {integrity: sha512-Hd/DI+a8PKhl33CmaR3eQdx2P4zpaeoUwjOJQd090cFEbEX9auoCo6+t4LLm/JlzgnRSnFq0EaZOWJVK3wDu8Q==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@oxfmt/linux-arm64-gnu@0.14.0':
+ resolution: {integrity: sha512-JzMyMKuDY9UmxRRnHWFdzYIXYZ2SK2/RmJKhYS47lcRELQC64nzuFe0d5JkRnt7KIJoM7RdUmYqEr+UKdiZ5mg==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@oxfmt/linux-arm64-musl@0.14.0':
+ resolution: {integrity: sha512-sPLA+jvL5kArpnUpxlt6v/EZCGvIhe8Z6hnNuGUa4gdYfzVf2XhAK1jO6hrrjFMT+2cnkbqmxa5iuZqCT6Y5xg==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@oxfmt/linux-x64-gnu@0.14.0':
+ resolution: {integrity: sha512-2hWVwIBa756NHs3+19om1mQp2C4vnGhFGe75AmsRRlkLq1vttC1iuQoF6slQQTS6n0/d7o4Pg1wGY3kldY6Msw==}
+ cpu: [x64]
+ os: [linux]
+
+ '@oxfmt/linux-x64-musl@0.14.0':
+ resolution: {integrity: sha512-bk98BFY2wArfWTVJ+T0zTCqF1deFfcyzrJ0/zppupQDFVdKUTga2XeKY8S1ImdyG+N7XcixdCrcT9db+SVNKMA==}
+ cpu: [x64]
+ os: [linux]
+
+ '@oxfmt/win32-arm64@0.14.0':
+ resolution: {integrity: sha512-UxctetV+XOXGXYcJp8uwP+/cUq3GSTAxq6UBbeGUq+0j1je3zC4XCQ6Kh/dm6kxOnAzrmMkX1uG4Su4bwvMq8w==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@oxfmt/win32-x64@0.14.0':
+ resolution: {integrity: sha512-P/Cw1aP0UIf42HDH6t3+5IY0xx8e4HxCfDHQz/PDbJ+Vc2JhAB6rzkVFAOEo9inQsXoZVdApF/xklp4NJtrkqQ==}
+ cpu: [x64]
+ os: [win32]
+
'@parcel/watcher-android-arm64@2.4.1':
resolution: {integrity: sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==}
engines: {node: '>= 10.0.0'}
@@ -4288,6 +4331,11 @@ packages:
resolution: {integrity: sha512-dQPNIF+gHpSkmC0+Vg9IktNyhcn28Y8R3eTLyzn52UNymkasLicl3sFAtz7oEVuFmCpgGjaUTKkwk+jW2cHpDQ==}
engines: {node: ^20.19.0 || >=22.12.0}
+ oxfmt@0.14.0:
+ resolution: {integrity: sha512-cZpXmiiEIHxEWq1bkqgCM/9vMv4TQ8RCSA9l+5PPEuCewL+2qNP/7vZynIrQnByvUnJc/G3YOj95XH+GXYLaKg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ hasBin: true
+
p-event@5.0.1:
resolution: {integrity: sha512-dd589iCQ7m1L0bmC5NLlVYfy3TbBEsMUfWx9PyAgPeIcFZ/E2yaTZ4Rz4MiBmmJShviiftHVXOqfnfzJ6kyMrQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@@ -6988,6 +7036,30 @@ snapshots:
'@oxc-transform/binding-win32-x64-msvc@0.96.0':
optional: true
+ '@oxfmt/darwin-arm64@0.14.0':
+ optional: true
+
+ '@oxfmt/darwin-x64@0.14.0':
+ optional: true
+
+ '@oxfmt/linux-arm64-gnu@0.14.0':
+ optional: true
+
+ '@oxfmt/linux-arm64-musl@0.14.0':
+ optional: true
+
+ '@oxfmt/linux-x64-gnu@0.14.0':
+ optional: true
+
+ '@oxfmt/linux-x64-musl@0.14.0':
+ optional: true
+
+ '@oxfmt/win32-arm64@0.14.0':
+ optional: true
+
+ '@oxfmt/win32-x64@0.14.0':
+ optional: true
+
'@parcel/watcher-android-arm64@2.4.1':
optional: true
@@ -9879,6 +9951,17 @@ snapshots:
'@oxc-transform/binding-win32-arm64-msvc': 0.96.0
'@oxc-transform/binding-win32-x64-msvc': 0.96.0
+ oxfmt@0.14.0:
+ optionalDependencies:
+ '@oxfmt/darwin-arm64': 0.14.0
+ '@oxfmt/darwin-x64': 0.14.0
+ '@oxfmt/linux-arm64-gnu': 0.14.0
+ '@oxfmt/linux-arm64-musl': 0.14.0
+ '@oxfmt/linux-x64-gnu': 0.14.0
+ '@oxfmt/linux-x64-musl': 0.14.0
+ '@oxfmt/win32-arm64': 0.14.0
+ '@oxfmt/win32-x64': 0.14.0
+
p-event@5.0.1:
dependencies:
p-timeout: 5.1.0
diff --git a/scripts/bump.js b/scripts/bump.js
index 6e8304f58..3c824f62f 100644
--- a/scripts/bump.js
+++ b/scripts/bump.js
@@ -34,8 +34,8 @@ const command = defineCommand({
);
await Promise.all(
- globSync(["package.json", "packages/*/package.json", "examples/*/package.json"])
- .map(async path => {
+ globSync(["package.json", "packages/*/package.json", "examples/*/package.json"]).map(
+ async path => {
const packageJson = JSON.parse(await fs.readFile(path));
let deps = packages;
for (const dep of deps) {
@@ -45,7 +45,8 @@ const command = defineCommand({
(packageJson.devDependencies[dep.name] = `^${dep.version}`);
}
await fs.writeFile(path, JSON.stringify(packageJson, null, 2) + "\n");
- })
+ }
+ )
);
console.log("Updating lock file...\n");
From b99789edba64a6eec6d4c202299016ee332a4274 Mon Sep 17 00:00:00 2001
From: Darko Bozhinovski
Date: Sun, 14 Dec 2025 12:28:41 +0100
Subject: [PATCH 2/3] trailing comma to oxfmt
---
.oxfmtrc.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.oxfmtrc.json b/.oxfmtrc.json
index e5599ddda..45c63abd9 100644
--- a/.oxfmtrc.json
+++ b/.oxfmtrc.json
@@ -3,7 +3,7 @@
"tabWidth": 2,
"useTabs": false,
"endOfLine": "lf",
- "trailingComma": "none",
+ "trailingComma": "all",
"semi": true,
"singleQuote": false,
"arrowParens": "avoid",
From c79a6c62d5e75d396f76ba172dbf353a52fb6953 Mon Sep 17 00:00:00 2001
From: Brendan Allan
Date: Sun, 14 Dec 2025 20:55:40 +0800
Subject: [PATCH 3/3] reformat
---
apps/fixtures/bare/vite.config.ts | 2 +-
apps/fixtures/basic/vite.config.ts | 2 +-
apps/fixtures/css/src/components/test.tsx | 4 +-
apps/fixtures/css/vite.config.ts | 2 +-
apps/fixtures/experiments/src/middleware.ts | 8 +-
.../fixtures/experiments/src/routes/index.tsx | 4 +-
apps/fixtures/experiments/vite.config.ts | 2 +-
apps/fixtures/hackernews/public/sw.js | 4 +-
apps/fixtures/hackernews/src/lib/api.ts | 4 +-
.../hackernews/src/routes/[...stories].tsx | 2 +-
.../hackernews/src/routes/stories/[id].tsx | 2 +-
.../hackernews/src/routes/users/[id].tsx | 2 +-
apps/fixtures/hackernews/vite.config.ts | 2 +-
apps/fixtures/nitro-3/vite.config.ts | 2 +-
.../notes/src/components/SearchField.tsx | 2 +-
.../notes/src/components/SidebarNote.tsx | 6 +-
apps/fixtures/notes/src/lib/api.ts | 14 ++--
apps/fixtures/notes/src/lib/db.ts | 4 +-
.../notes/src/routes/notes/[id]/(preview).tsx | 2 +-
.../notes/src/routes/notes/[id]/edit.tsx | 2 +-
apps/fixtures/notes/vite.config.ts | 2 +-
apps/fixtures/todomvc/src/lib/api.ts | 16 ++--
apps/fixtures/todomvc/src/lib/db.ts | 4 +-
apps/fixtures/todomvc/src/routes/index.tsx | 10 +--
apps/fixtures/todomvc/vite.config.ts | 2 +-
apps/landing-page/postcss.config.js | 4 +-
apps/landing-page/src/components/bento.tsx | 16 ++--
.../src/components/download-logos-menu.tsx | 2 +-
.../src/components/nested-grid.tsx | 16 ++--
.../components/sections/deploy-anywhere.tsx | 16 ++--
.../src/components/sections/hero.tsx | 2 +-
.../src/components/theme-toggle.tsx | 2 +-
.../src/components/ui/accordion.tsx | 6 +-
.../landing-page/src/components/ui/button.tsx | 12 +--
.../src/components/ui/context-menu.tsx | 30 ++++----
.../landing-page/src/components/ui/dialog.tsx | 8 +-
.../landing-page/src/components/ui/drawer.tsx | 8 +-
.../src/components/ui/dropdown-menu.tsx | 26 +++----
apps/landing-page/src/components/ui/input.tsx | 2 +-
apps/landing-page/src/components/ui/label.tsx | 2 +-
.../src/components/ui/mystic/dot-pattern.tsx | 8 +-
.../src/components/ui/mystic/shine.tsx | 4 +-
.../src/components/ui/mystic/sparkle-text.tsx | 12 +--
apps/landing-page/src/components/ui/tabs.tsx | 10 +--
apps/landing-page/tailwind.config.ts | 22 +++---
apps/landing-page/ui.preset.ts | 50 ++++++-------
apps/landing-page/vite.config.ts | 6 +-
apps/tests/playwright.config.ts | 10 +--
apps/tests/src/e2e/api-call.test.ts | 4 +-
apps/tests/src/e2e/route-groups.test.ts | 8 +-
apps/tests/src/e2e/server-function.test.ts | 12 +--
apps/tests/src/routes/api/header-merging.ts | 8 +-
.../routes/api/multi-set-cookie-redirect.ts | 2 +-
...xport-named-functions-in-the-same-file.tsx | 2 +-
.../treeshaking/treeshake.server.test.ts | 2 +-
apps/tests/vite.config.ts | 4 +-
apps/tests/vitest.config.ts | 16 ++--
.../start-nitro-v2-vite-plugin/src/index.ts | 46 ++++++------
packages/start/scripts/build.js | 6 +-
packages/start/scripts/validate-imports.js | 16 ++--
packages/start/src/client/mount.ts | 10 +--
packages/start/src/config/constants.ts | 4 +-
packages/start/src/config/dev-server.ts | 30 ++++----
packages/start/src/config/fs-router.ts | 30 ++++----
.../start/src/config/fs-routes/fs-watcher.ts | 8 +-
packages/start/src/config/fs-routes/index.ts | 12 +--
packages/start/src/config/fs-routes/router.ts | 14 ++--
.../start/src/config/fs-routes/tree-shake.ts | 24 +++---
packages/start/src/config/index.ts | 74 +++++++++----------
packages/start/src/config/lazy.ts | 26 +++----
packages/start/src/config/manifest.ts | 10 +--
packages/start/src/config/vite-utils.ts | 2 +-
packages/start/src/http/index.ts | 12 +--
packages/start/src/index.tsx | 2 +-
packages/start/src/middleware/index.ts | 8 +-
packages/start/src/router.tsx | 4 +-
packages/start/src/server/assets/index.ts | 2 +-
packages/start/src/server/assets/render.tsx | 4 +-
packages/start/src/server/collect-styles.ts | 2 +-
packages/start/src/server/fetchEvent.spec.ts | 6 +-
packages/start/src/server/fetchEvent.ts | 2 +-
packages/start/src/server/handler.ts | 20 ++---
.../server/manifest/dev-client-manifest.ts | 6 +-
.../src/server/manifest/dev-ssr-manifest.ts | 6 +-
.../server/manifest/prod-client-manifest.ts | 2 +-
.../src/server/manifest/prod-ssr-manifest.ts | 12 +--
.../start/src/server/manifest/ssr-manifest.ts | 2 +-
packages/start/src/server/routes.ts | 14 ++--
.../start/src/server/server-fns-runtime.ts | 4 +-
.../src/server/server-functions-handler.ts | 36 ++++-----
packages/start/src/server/server-runtime.ts | 26 +++----
packages/start/src/server/spa/handler.ts | 4 +-
packages/start/src/shared/ErrorBoundary.tsx | 2 +-
packages/start/src/shared/HttpStatusCode.ts | 2 +-
packages/start/src/shared/clientOnly.ts | 6 +-
.../start/src/shared/dev-overlay/CodeView.tsx | 10 +--
.../shared/dev-overlay/DevOverlayDialog.tsx | 8 +-
.../shared/dev-overlay/createStackFrame.ts | 12 +--
.../src/shared/dev-overlay/get-source-map.ts | 2 +-
.../start/src/shared/dev-overlay/icons.tsx | 10 +--
.../start/src/shared/dev-overlay/index.tsx | 2 +-
packages/start/src/shared/lazy.ts | 2 +-
packages/start/vitest.config.ts | 4 +-
scripts/bump.js | 16 ++--
104 files changed, 500 insertions(+), 500 deletions(-)
diff --git a/apps/fixtures/bare/vite.config.ts b/apps/fixtures/bare/vite.config.ts
index fad292267..27a23708d 100644
--- a/apps/fixtures/bare/vite.config.ts
+++ b/apps/fixtures/bare/vite.config.ts
@@ -3,5 +3,5 @@ import { solidStart } from "../../../packages/start/src/config";
import { nitroV2Plugin } from "../../../packages/start-nitro-v2-vite-plugin/src";
export default defineConfig({
- plugins: [solidStart(), nitroV2Plugin()]
+ plugins: [solidStart(), nitroV2Plugin()],
});
diff --git a/apps/fixtures/basic/vite.config.ts b/apps/fixtures/basic/vite.config.ts
index fad292267..27a23708d 100644
--- a/apps/fixtures/basic/vite.config.ts
+++ b/apps/fixtures/basic/vite.config.ts
@@ -3,5 +3,5 @@ import { solidStart } from "../../../packages/start/src/config";
import { nitroV2Plugin } from "../../../packages/start-nitro-v2-vite-plugin/src";
export default defineConfig({
- plugins: [solidStart(), nitroV2Plugin()]
+ plugins: [solidStart(), nitroV2Plugin()],
});
diff --git a/apps/fixtures/css/src/components/test.tsx b/apps/fixtures/css/src/components/test.tsx
index 970d70b02..43b7de1b9 100644
--- a/apps/fixtures/css/src/components/test.tsx
+++ b/apps/fixtures/css/src/components/test.tsx
@@ -6,7 +6,7 @@ const integrations = {
import: "import",
module: "import module",
url: "?url without render",
- link: "?url + "
+ link: "?url + ",
};
const Test = (props: {
invert?: boolean;
@@ -23,7 +23,7 @@ const Test = (props: {
"grid grid-cols-subgrid col-span-full items-center rounded text-white font-medium py-1 px-2 border-4 transition-colors duration-[1.5s]",
props.invert ? "bg-success" : "bg-error",
props.noSupport ? "border-warn" : "border-transparent",
- props.class
+ props.class,
)}
>
{props.component}
diff --git a/apps/fixtures/css/vite.config.ts b/apps/fixtures/css/vite.config.ts
index 598584d4b..636b0a385 100644
--- a/apps/fixtures/css/vite.config.ts
+++ b/apps/fixtures/css/vite.config.ts
@@ -4,5 +4,5 @@ import { nitroV2Plugin } from "../../../packages/start-nitro-v2-vite-plugin/src"
import { solidStart } from "../../../packages/start/src/config";
export default defineConfig({
- plugins: [solidStart(), nitroV2Plugin(), tailwindcss()]
+ plugins: [solidStart(), nitroV2Plugin(), tailwindcss()],
});
diff --git a/apps/fixtures/experiments/src/middleware.ts b/apps/fixtures/experiments/src/middleware.ts
index bd6942254..4b54dfb5e 100644
--- a/apps/fixtures/experiments/src/middleware.ts
+++ b/apps/fixtures/experiments/src/middleware.ts
@@ -8,13 +8,13 @@ export default createMiddleware({
console.log("REQUEST", event.request.url);
console.log(
"SEARCH PARAM KEYS FROM ASYNC CONTEXT",
- Array.from(getRequestURL().searchParams.keys())
+ Array.from(getRequestURL().searchParams.keys()),
);
- }
+ },
],
onBeforeResponse: [
(event, { body }) => {
console.log("BEFORE RESPONSE", body);
- }
- ]
+ },
+ ],
});
diff --git a/apps/fixtures/experiments/src/routes/index.tsx b/apps/fixtures/experiments/src/routes/index.tsx
index c8c40decb..189744fb1 100644
--- a/apps/fixtures/experiments/src/routes/index.tsx
+++ b/apps/fixtures/experiments/src/routes/index.tsx
@@ -13,7 +13,7 @@ const hello = GET(async (name: string) => {
console.log("ID", id, e.locals.foo);
return json(
{ hello: new Promise(r => setTimeout(() => r(name), 1000)) },
- { headers: { "cache-control": "max-age=60" } }
+ { headers: { "cache-control": "max-age=60" } },
);
});
@@ -24,7 +24,7 @@ export default function Home() {
});
const port = isServer ? new URL(getRequestEvent()!.request.url).port : location.port;
fetch(`http://localhost:${port}${import.meta.env.BASE_URL}/unknown`, {
- headers: { Accept: "application/json" }
+ headers: { Accept: "application/json" },
}).then(async res => console.log(await res.json()));
return (
diff --git a/apps/fixtures/experiments/vite.config.ts b/apps/fixtures/experiments/vite.config.ts
index 953f4d83d..57596416d 100644
--- a/apps/fixtures/experiments/vite.config.ts
+++ b/apps/fixtures/experiments/vite.config.ts
@@ -3,5 +3,5 @@ import { solidStart } from "../../../packages/start/src/config";
import { nitroV2Plugin } from "../../../packages/start-nitro-v2-vite-plugin/src";
export default defineConfig({
- plugins: [solidStart({ middleware: "./src/middleware.ts" }), nitroV2Plugin()]
+ plugins: [solidStart({ middleware: "./src/middleware.ts" }), nitroV2Plugin()],
});
diff --git a/apps/fixtures/hackernews/public/sw.js b/apps/fixtures/hackernews/public/sw.js
index ec8f30ceb..fcf9d79af 100644
--- a/apps/fixtures/hackernews/public/sw.js
+++ b/apps/fixtures/hackernews/public/sw.js
@@ -6,8 +6,8 @@ self.addEventListener("fetch", e => {
.then(t =>
t
.match(e.request)
- .then(n => n || fetch(e.request).then(n => (t.put(e.request, n.clone()), n)))
- )
+ .then(n => n || fetch(e.request).then(n => (t.put(e.request, n.clone()), n))),
+ ),
);
});
diff --git a/apps/fixtures/hackernews/src/lib/api.ts b/apps/fixtures/hackernews/src/lib/api.ts
index 658bcace9..6b69a444b 100644
--- a/apps/fixtures/hackernews/src/lib/api.ts
+++ b/apps/fixtures/hackernews/src/lib/api.ts
@@ -31,7 +31,7 @@ const mapStories = {
new: "newest",
show: "show",
ask: "ask",
- job: "jobs"
+ job: "jobs",
} as const;
export const getStories = query(
@@ -39,7 +39,7 @@ export const getStories = query(
"use server";
return fetchAPI(`${mapStories[type]}?page=${page}`);
},
- "stories"
+ "stories",
);
export const getStory = query(async (id: string): Promise => {
diff --git a/apps/fixtures/hackernews/src/routes/[...stories].tsx b/apps/fixtures/hackernews/src/routes/[...stories].tsx
index 6b0aae992..b219dfb0f 100644
--- a/apps/fixtures/hackernews/src/routes/[...stories].tsx
+++ b/apps/fixtures/hackernews/src/routes/[...stories].tsx
@@ -7,7 +7,7 @@ import { StoryTypes } from "~/types";
export const route = {
preload({ location, params }) {
void getStories((params.stories as StoryTypes) || "top", +location.query.page || 1);
- }
+ },
} satisfies RouteDefinition;
export default function Stories(props: RouteSectionProps) {
diff --git a/apps/fixtures/hackernews/src/routes/stories/[id].tsx b/apps/fixtures/hackernews/src/routes/stories/[id].tsx
index 9aa19502f..59350e70d 100644
--- a/apps/fixtures/hackernews/src/routes/stories/[id].tsx
+++ b/apps/fixtures/hackernews/src/routes/stories/[id].tsx
@@ -6,7 +6,7 @@ import { getStory } from "~/lib/api";
export const route = {
preload({ params }) {
void getStory(params.id);
- }
+ },
} satisfies RouteDefinition;
export default function Story(props: RouteSectionProps) {
diff --git a/apps/fixtures/hackernews/src/routes/users/[id].tsx b/apps/fixtures/hackernews/src/routes/users/[id].tsx
index bf4910c19..7a14752de 100644
--- a/apps/fixtures/hackernews/src/routes/users/[id].tsx
+++ b/apps/fixtures/hackernews/src/routes/users/[id].tsx
@@ -5,7 +5,7 @@ import { getUser } from "~/lib/api";
export const route = {
preload({ params }) {
void getUser(params.id);
- }
+ },
} satisfies RouteDefinition;
export default function User(props: RouteSectionProps) {
diff --git a/apps/fixtures/hackernews/vite.config.ts b/apps/fixtures/hackernews/vite.config.ts
index 416acc821..96aa23a3c 100644
--- a/apps/fixtures/hackernews/vite.config.ts
+++ b/apps/fixtures/hackernews/vite.config.ts
@@ -4,5 +4,5 @@ import { solidStart } from "../../../packages/start/src/config";
import { nitroV2Plugin } from "../../../packages/start-nitro-v2-vite-plugin/src";
export default defineConfig({
- plugins: [solidStart()]
+ plugins: [solidStart()],
});
diff --git a/apps/fixtures/nitro-3/vite.config.ts b/apps/fixtures/nitro-3/vite.config.ts
index 72eeabf4e..8e7a17f88 100644
--- a/apps/fixtures/nitro-3/vite.config.ts
+++ b/apps/fixtures/nitro-3/vite.config.ts
@@ -3,5 +3,5 @@ import { nitro } from "nitro/vite";
import { defineConfig } from "vite";
export default defineConfig({
- plugins: [solidStart(), nitro({ preset: "node-server" })]
+ plugins: [solidStart(), nitro({ preset: "node-server" })],
});
diff --git a/apps/fixtures/notes/src/components/SearchField.tsx b/apps/fixtures/notes/src/components/SearchField.tsx
index 62a4685f6..f64c5f2da 100644
--- a/apps/fixtures/notes/src/components/SearchField.tsx
+++ b/apps/fixtures/notes/src/components/SearchField.tsx
@@ -22,7 +22,7 @@ export default function SearchField() {
value={search.searchText || ""}
onInput={e => {
setParams({
- searchText: e.target.value
+ searchText: e.target.value,
});
}}
/>
diff --git a/apps/fixtures/notes/src/components/SidebarNote.tsx b/apps/fixtures/notes/src/components/SidebarNote.tsx
index 0f58dab6b..ec2a53cfa 100644
--- a/apps/fixtures/notes/src/components/SidebarNote.tsx
+++ b/apps/fixtures/notes/src/components/SidebarNote.tsx
@@ -34,7 +34,7 @@ export default function SidebarNote(props: { note: Note }) {
itemRef.classList.remove("flash");
}}
style={{
- color: "black"
+ color: "black",
}}
class={["sidebar-note-list-item", isExpanded() ? "note-expanded" : ""].join(" ")}
>
@@ -51,7 +51,7 @@ export default function SidebarNote(props: { note: Note }) {
: isActive()
? "var(--tertiary-blue)"
: "",
- border: isActive() ? "1px solid var(--primary-border)" : "1px solid transparent"
+ border: isActive() ? "1px solid var(--primary-border)" : "1px solid transparent",
}}
>
Open note for preview
@@ -72,7 +72,7 @@ export default function SidebarNote(props: { note: Note }) {