From 53f6523e56fcff4117bea04269da18c47ecdd23a Mon Sep 17 00:00:00 2001 From: wenyiqing Date: Thu, 18 Dec 2025 17:38:21 +0800 Subject: [PATCH 1/4] Added preset setting for edgeone; --- docs/2.deploy/20.providers/edgeone.md | 22 +++++ src/presets/_all.gen.ts | 2 + src/presets/_types.gen.ts | 4 +- src/presets/edgeone/preset.ts | 31 ++++++ src/presets/edgeone/runtime/_utils.ts | 9 ++ src/presets/edgeone/runtime/edgeone.ts | 30 ++++++ src/presets/edgeone/utils.ts | 128 +++++++++++++++++++++++++ 7 files changed, 224 insertions(+), 2 deletions(-) create mode 100644 docs/2.deploy/20.providers/edgeone.md create mode 100644 src/presets/edgeone/preset.ts create mode 100644 src/presets/edgeone/runtime/_utils.ts create mode 100644 src/presets/edgeone/runtime/edgeone.ts create mode 100644 src/presets/edgeone/utils.ts diff --git a/docs/2.deploy/20.providers/edgeone.md b/docs/2.deploy/20.providers/edgeone.md new file mode 100644 index 0000000000..2b5ff07b21 --- /dev/null +++ b/docs/2.deploy/20.providers/edgeone.md @@ -0,0 +1,22 @@ +# EdgeOne + +> Deploy Nitro apps to EdgeOne. + +**Preset:** `edgeone` + +:read-more{to="https://pages.edgeone.ai/"} + + +## Using the control panel + +1. In the [EdgeOne control panel](https://console.tencentcloud.com/edgeone/pages), click **Create project**. +2. Choose **Import Git repository** as your deployment method. We support deployment on Github, GitLab, Gitee, and CNB. +3. Choose the GitHub **repository** and **branch** containing your application code. +4. Complete your project setup. +5. Click the **Deploy** button. + +## Using the EdgeOne CLI + +You can also install the Pages scaffolding tool. For detailed installation and usage, refer to [EdgeOne CLI](https://pages.edgeone.ai/document/edgeone-cli). + +Once configured, use the edgeone pages deploy command to deploy the project. During deployment, the CLI will first automatically build the project, then upload and publish the build artifacts. diff --git a/src/presets/_all.gen.ts b/src/presets/_all.gen.ts index 0aabd48fde..352e150408 100644 --- a/src/presets/_all.gen.ts +++ b/src/presets/_all.gen.ts @@ -11,6 +11,7 @@ import _cleavr from "./cleavr/preset.ts"; import _cloudflare from "./cloudflare/preset.ts"; import _deno from "./deno/preset.ts"; import _digitalocean from "./digitalocean/preset.ts"; +import _edgeone from "./edgeone/preset.ts"; import _firebase from "./firebase/preset.ts"; import _flightcontrol from "./flightcontrol/preset.ts"; import _genezio from "./genezio/preset.ts"; @@ -40,6 +41,7 @@ export default [ ..._cloudflare, ..._deno, ..._digitalocean, + ..._edgeone, ..._firebase, ..._flightcontrol, ..._genezio, diff --git a/src/presets/_types.gen.ts b/src/presets/_types.gen.ts index 974925a21a..ddf0a9f12e 100644 --- a/src/presets/_types.gen.ts +++ b/src/presets/_types.gen.ts @@ -20,6 +20,6 @@ export interface PresetOptions { export const presetsWithConfig = ["awsAmplify","awsLambda","azure","cloudflare","firebase","netlify","vercel"] as const; -export type PresetName = "alwaysdata" | "aws-amplify" | "aws-lambda" | "azure-swa" | "base-worker" | "bun" | "cleavr" | "cloudflare-dev" | "cloudflare-durable" | "cloudflare-module" | "cloudflare-pages" | "cloudflare-pages-static" | "deno" | "deno-deploy" | "deno-server" | "digital-ocean" | "firebase-app-hosting" | "flight-control" | "genezio" | "github-pages" | "gitlab-pages" | "heroku" | "iis-handler" | "iis-node" | "koyeb" | "netlify" | "netlify-edge" | "netlify-static" | "nitro-dev" | "nitro-prerender" | "node" | "node-cluster" | "node-middleware" | "node-server" | "platform-sh" | "render-com" | "standard" | "static" | "stormkit" | "vercel" | "vercel-static" | "winterjs" | "zeabur" | "zeabur-static" | "zerops" | "zerops-static"; +export type PresetName = "alwaysdata" | "aws-amplify" | "aws-lambda" | "azure-swa" | "base-worker" | "bun" | "cleavr" | "cloudflare-dev" | "cloudflare-durable" | "cloudflare-module" | "cloudflare-pages" | "cloudflare-pages-static" | "deno" | "deno-deploy" | "deno-server" | "digital-ocean" | "edgeone" | "firebase-app-hosting" | "flight-control" | "genezio" | "github-pages" | "gitlab-pages" | "heroku" | "iis-handler" | "iis-node" | "koyeb" | "netlify" | "netlify-edge" | "netlify-static" | "nitro-dev" | "nitro-prerender" | "node" | "node-cluster" | "node-middleware" | "node-server" | "platform-sh" | "render-com" | "standard" | "static" | "stormkit" | "vercel" | "vercel-static" | "winterjs" | "zeabur" | "zeabur-static" | "zerops" | "zerops-static"; -export type PresetNameInput = "alwaysdata" | "aws-amplify" | "awsAmplify" | "aws_amplify" | "aws-lambda" | "awsLambda" | "aws_lambda" | "azure-swa" | "azureSwa" | "azure_swa" | "base-worker" | "baseWorker" | "base_worker" | "bun" | "cleavr" | "cloudflare-dev" | "cloudflareDev" | "cloudflare_dev" | "cloudflare-durable" | "cloudflareDurable" | "cloudflare_durable" | "cloudflare-module" | "cloudflareModule" | "cloudflare_module" | "cloudflare-pages" | "cloudflarePages" | "cloudflare_pages" | "cloudflare-pages-static" | "cloudflarePagesStatic" | "cloudflare_pages_static" | "deno" | "deno-deploy" | "denoDeploy" | "deno_deploy" | "deno-server" | "denoServer" | "deno_server" | "digital-ocean" | "digitalOcean" | "digital_ocean" | "firebase-app-hosting" | "firebaseAppHosting" | "firebase_app_hosting" | "flight-control" | "flightControl" | "flight_control" | "genezio" | "github-pages" | "githubPages" | "github_pages" | "gitlab-pages" | "gitlabPages" | "gitlab_pages" | "heroku" | "iis-handler" | "iisHandler" | "iis_handler" | "iis-node" | "iisNode" | "iis_node" | "koyeb" | "netlify" | "netlify-edge" | "netlifyEdge" | "netlify_edge" | "netlify-static" | "netlifyStatic" | "netlify_static" | "nitro-dev" | "nitroDev" | "nitro_dev" | "nitro-prerender" | "nitroPrerender" | "nitro_prerender" | "node" | "node-cluster" | "nodeCluster" | "node_cluster" | "node-middleware" | "nodeMiddleware" | "node_middleware" | "node-server" | "nodeServer" | "node_server" | "platform-sh" | "platformSh" | "platform_sh" | "render-com" | "renderCom" | "render_com" | "standard" | "static" | "stormkit" | "vercel" | "vercel-static" | "vercelStatic" | "vercel_static" | "winterjs" | "zeabur" | "zeabur-static" | "zeaburStatic" | "zeabur_static" | "zerops" | "zerops-static" | "zeropsStatic" | "zerops_static" | (string & {}); +export type PresetNameInput = "alwaysdata" | "aws-amplify" | "awsAmplify" | "aws_amplify" | "aws-lambda" | "awsLambda" | "aws_lambda" | "azure-swa" | "azureSwa" | "azure_swa" | "base-worker" | "baseWorker" | "base_worker" | "bun" | "cleavr" | "cloudflare-dev" | "cloudflareDev" | "cloudflare_dev" | "cloudflare-durable" | "cloudflareDurable" | "cloudflare_durable" | "cloudflare-module" | "cloudflareModule" | "cloudflare_module" | "cloudflare-pages" | "cloudflarePages" | "cloudflare_pages" | "cloudflare-pages-static" | "cloudflarePagesStatic" | "cloudflare_pages_static" | "deno" | "deno-deploy" | "denoDeploy" | "deno_deploy" | "deno-server" | "denoServer" | "deno_server" | "digital-ocean" | "digitalOcean" | "digital_ocean" | "edgeone" | "firebase-app-hosting" | "firebaseAppHosting" | "firebase_app_hosting" | "flight-control" | "flightControl" | "flight_control" | "genezio" | "github-pages" | "githubPages" | "github_pages" | "gitlab-pages" | "gitlabPages" | "gitlab_pages" | "heroku" | "iis-handler" | "iisHandler" | "iis_handler" | "iis-node" | "iisNode" | "iis_node" | "koyeb" | "netlify" | "netlify-edge" | "netlifyEdge" | "netlify_edge" | "netlify-static" | "netlifyStatic" | "netlify_static" | "nitro-dev" | "nitroDev" | "nitro_dev" | "nitro-prerender" | "nitroPrerender" | "nitro_prerender" | "node" | "node-cluster" | "nodeCluster" | "node_cluster" | "node-middleware" | "nodeMiddleware" | "node_middleware" | "node-server" | "nodeServer" | "node_server" | "platform-sh" | "platformSh" | "platform_sh" | "render-com" | "renderCom" | "render_com" | "standard" | "static" | "stormkit" | "vercel" | "vercel-static" | "vercelStatic" | "vercel_static" | "winterjs" | "zeabur" | "zeabur-static" | "zeaburStatic" | "zeabur_static" | "zerops" | "zerops-static" | "zeropsStatic" | "zerops_static" | (string & {}); diff --git a/src/presets/edgeone/preset.ts b/src/presets/edgeone/preset.ts new file mode 100644 index 0000000000..e73807fe86 --- /dev/null +++ b/src/presets/edgeone/preset.ts @@ -0,0 +1,31 @@ +import { defineNitroPreset } from "../_utils/preset.ts"; +import { writeEdgeOneRoutes } from "./utils.ts"; +import type { Nitro } from "nitro/types"; + +const edgeone = defineNitroPreset( + { + entry: "./edgeone/runtime/edgeone", + extends: "node-server", + serveStatic: true, + output: { + dir: "{{ rootDir }}/.edgeone", + serverDir: "{{ output.dir }}/server-handler", + publicDir: "{{ output.dir }}/assets", + }, + rollupConfig: { + output: { + entryFileNames: "handler.js", + }, + }, + hooks: { + async compiled(nitro: Nitro) { + await writeEdgeOneRoutes(nitro); + } + } + }, + { + name: "edgeone" as const, + } +); + +export default [edgeone] as const; diff --git a/src/presets/edgeone/runtime/_utils.ts b/src/presets/edgeone/runtime/_utils.ts new file mode 100644 index 0000000000..ee1caf4da8 --- /dev/null +++ b/src/presets/edgeone/runtime/_utils.ts @@ -0,0 +1,9 @@ +export function normalizeHeaders(headers: Record): HeadersInit { + const normalized: Record = {}; + for (const [key, value] of Object.entries(headers)) { + if (value !== undefined) { + normalized[key] = Array.isArray(value) ? value.join(', ') : value; + } + } + return normalized; +} \ No newline at end of file diff --git a/src/presets/edgeone/runtime/edgeone.ts b/src/presets/edgeone/runtime/edgeone.ts new file mode 100644 index 0000000000..c4b52b72bc --- /dev/null +++ b/src/presets/edgeone/runtime/edgeone.ts @@ -0,0 +1,30 @@ +import "#nitro-internal-polyfills"; +import { useNitroApp } from "nitro/app"; +import type { IncomingMessage } from "node:http"; +import { normalizeHeaders } from "./_utils.ts"; + +const nitroApp = useNitroApp(); + +interface EdgeOneRequest extends IncomingMessage { + url: string; + method: string; + headers: Record; +} + +// EdgeOne bootstrap expects: async (req, context) => Response +export default async function handle(req: EdgeOneRequest, context: unknown) { + // Build full URL from Node.js request headers + const host = req.headers['eo-pages-host'] || req.headers['host'] || 'localhost'; + const protocol = req.headers['x-forwarded-proto'] || 'http'; + const url = `${protocol}://${host}${req.url}`; + + // Create Web Request from Node.js request + const request = new Request(url, { + method: req.method || 'GET', + headers: normalizeHeaders(req.headers), + }); + + return nitroApp.fetch(request); +} + + diff --git a/src/presets/edgeone/utils.ts b/src/presets/edgeone/utils.ts new file mode 100644 index 0000000000..429afc6c17 --- /dev/null +++ b/src/presets/edgeone/utils.ts @@ -0,0 +1,128 @@ +import type { Nitro } from "nitro/types"; +import fsp from "node:fs/promises"; +import { relative, dirname, join } from "pathe"; +import consola from "consola"; +import { colors } from "consola/utils"; +interface FrameworkRoute { + path: string; + isStatic?: Boolean; +} + +export async function writeEdgeOneRoutes(nitro: Nitro) { + // Ensure routes are synced + nitro.routing.sync(); + const meta = { + conf: { + ssr404: true + }, + frameworkRoutes: [] as FrameworkRoute[], + }; + + // 1. Get all API routes (server-side route handlers) + const apiRoutes = nitro.routing.routes.routes + .filter((route) => { + // Filter out middleware and wildcard routes (e.g., /**) + const handler = Array.isArray(route.data) ? route.data[0] : route.data; + return handler && !handler.middleware && route.route !== "/**"; + }) + .map((route) => ({ + path: route.route, + method: route.method || "*", + handler: Array.isArray(route.data) ? route.data[0] : route.data, + })); + apiRoutes.forEach((route) => { + meta.frameworkRoutes.push({ + path: route.path, + }); + }); + + + // 2. Get all page routes (prerendered routes) + const pageRoutes = (nitro._prerenderedRoutes || []).map((route) => ({ + path: route.route, + fileName: route.fileName, + contentType: route.contentType, + })); + + // 3. Get user-defined prerender routes + const userPrerenderRoutes = nitro.options.prerender?.routes || []; + // 4. Get all routes marked as prerender in route rules + const prerenderRouteRules = Object.entries(nitro.options.routeRules || {}) + .filter(([_, rules]) => rules.prerender) + .map(([path]) => path); + + // 5. Get all routes with SWR/cache settings from route rules + // Note: `swr: true` shortcut is normalized to `cache: { swr: true }` after config resolution + const swrRouteRules = Object.entries(nitro.options.routeRules || {}) + .filter(([_, rules]) => { + // Check if cache.swr is enabled (normalized form) + if (rules.cache && typeof rules.cache === "object" && rules.cache.swr) { + return true; + } + return false; + }) + .map(([path, rules]) => ({ + path, + cache: rules.cache as { swr?: boolean; maxAge?: number }, + })); + swrRouteRules.forEach((route) => { + const maxAge = route.cache.maxAge; + meta.frameworkRoutes.map((frameworkRoute) => { + if (frameworkRoute.path === route.path) { + Reflect.set(frameworkRoute, "isStatic", false); + Reflect.set(frameworkRoute, "isr", maxAge); + } + return frameworkRoute; + }); + }); + + // Merge all prerender routes + const allPrerenderRoutes = [ + ...new Set([ + ...userPrerenderRoutes, + ...prerenderRouteRules, + ...pageRoutes.map((r) => r.path), + ]), + ]; + allPrerenderRoutes.forEach((route) => { + meta.frameworkRoutes.push({ + path: route, + isStatic: true, + }); + }); + + await writeFile(join(nitro.options.output.dir, "meta.json"), JSON.stringify(meta, null, 2)); + await writeFile(join(nitro.options.output.serverDir, "meta.json"), JSON.stringify(meta, null, 2)); + + // Return all route information + return { + apiRoutes, + pageRoutes, + userPrerenderRoutes, + prerenderRouteRules, + allPrerenderRoutes, + swrRouteRules, + }; +} + +function prettyPath(p: string, highlight = true) { + p = relative(process.cwd(), p); + return highlight ? colors.cyan(p) : p; +} + +async function writeFile( + file: string, + contents: Buffer | string, + log = false +) { + await fsp.mkdir(dirname(file), { recursive: true }); + await fsp.writeFile( + file, + contents, + typeof contents === "string" ? "utf8" : undefined + ); + if (log) { + consola.info("Generated", prettyPath(file)); + } +} + From e81d84886b22f77f91be524b750e5a2832347f37 Mon Sep 17 00:00:00 2001 From: wenyiqing Date: Thu, 18 Dec 2025 17:55:38 +0800 Subject: [PATCH 2/4] Complete the code modifications according to coderabbitai's suggestions. --- docs/2.deploy/20.providers/edgeone.md | 2 +- src/presets/edgeone/runtime/edgeone.ts | 4 +++- src/presets/edgeone/utils.ts | 6 +++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/2.deploy/20.providers/edgeone.md b/docs/2.deploy/20.providers/edgeone.md index 2b5ff07b21..5c0e3e075f 100644 --- a/docs/2.deploy/20.providers/edgeone.md +++ b/docs/2.deploy/20.providers/edgeone.md @@ -10,7 +10,7 @@ ## Using the control panel 1. In the [EdgeOne control panel](https://console.tencentcloud.com/edgeone/pages), click **Create project**. -2. Choose **Import Git repository** as your deployment method. We support deployment on Github, GitLab, Gitee, and CNB. +2. Choose **Import Git repository** as your deployment method. We support deployment on GitHub, GitLab, Gitee, and CNB. 3. Choose the GitHub **repository** and **branch** containing your application code. 4. Complete your project setup. 5. Click the **Deploy** button. diff --git a/src/presets/edgeone/runtime/edgeone.ts b/src/presets/edgeone/runtime/edgeone.ts index c4b52b72bc..2289753107 100644 --- a/src/presets/edgeone/runtime/edgeone.ts +++ b/src/presets/edgeone/runtime/edgeone.ts @@ -9,19 +9,21 @@ interface EdgeOneRequest extends IncomingMessage { url: string; method: string; headers: Record; + body: string; } // EdgeOne bootstrap expects: async (req, context) => Response export default async function handle(req: EdgeOneRequest, context: unknown) { // Build full URL from Node.js request headers const host = req.headers['eo-pages-host'] || req.headers['host'] || 'localhost'; - const protocol = req.headers['x-forwarded-proto'] || 'http'; + const protocol = req.headers['x-forwarded-proto'] || 'https'; const url = `${protocol}://${host}${req.url}`; // Create Web Request from Node.js request const request = new Request(url, { method: req.method || 'GET', headers: normalizeHeaders(req.headers), + body: req.body, }); return nitroApp.fetch(request); diff --git a/src/presets/edgeone/utils.ts b/src/presets/edgeone/utils.ts index 429afc6c17..e44be5d648 100644 --- a/src/presets/edgeone/utils.ts +++ b/src/presets/edgeone/utils.ts @@ -5,7 +5,8 @@ import consola from "consola"; import { colors } from "consola/utils"; interface FrameworkRoute { path: string; - isStatic?: Boolean; + isStatic?: boolean; + isr?: number; } export async function writeEdgeOneRoutes(nitro: Nitro) { @@ -67,12 +68,11 @@ export async function writeEdgeOneRoutes(nitro: Nitro) { })); swrRouteRules.forEach((route) => { const maxAge = route.cache.maxAge; - meta.frameworkRoutes.map((frameworkRoute) => { + meta.frameworkRoutes.forEach((frameworkRoute) => { if (frameworkRoute.path === route.path) { Reflect.set(frameworkRoute, "isStatic", false); Reflect.set(frameworkRoute, "isr", maxAge); } - return frameworkRoute; }); }); From bd99387c6231ee66eaef2b8675a4a57a43b67e37 Mon Sep 17 00:00:00 2001 From: wenyiqing Date: Mon, 22 Dec 2025 15:49:52 +0800 Subject: [PATCH 3/4] Fixed the issue mentioned by the reviewer on 2025-12-19. --- docs/2.deploy/20.providers/edgeone.md | 4 ++-- src/presets/_types.gen.ts | 4 ++-- src/presets/edgeone/preset.ts | 2 +- src/presets/edgeone/runtime/_utils.ts | 9 --------- src/presets/edgeone/runtime/edgeone.ts | 22 ++++++---------------- 5 files changed, 11 insertions(+), 30 deletions(-) delete mode 100644 src/presets/edgeone/runtime/_utils.ts diff --git a/docs/2.deploy/20.providers/edgeone.md b/docs/2.deploy/20.providers/edgeone.md index 5c0e3e075f..2984f49021 100644 --- a/docs/2.deploy/20.providers/edgeone.md +++ b/docs/2.deploy/20.providers/edgeone.md @@ -2,14 +2,14 @@ > Deploy Nitro apps to EdgeOne. -**Preset:** `edgeone` +**Preset:** `edgeone-pages` :read-more{to="https://pages.edgeone.ai/"} ## Using the control panel -1. In the [EdgeOne control panel](https://console.tencentcloud.com/edgeone/pages), click **Create project**. +1. In the [EdgeOne pages control panel](https://console.tencentcloud.com/edgeone/pages), click **Create project**. 2. Choose **Import Git repository** as your deployment method. We support deployment on GitHub, GitLab, Gitee, and CNB. 3. Choose the GitHub **repository** and **branch** containing your application code. 4. Complete your project setup. diff --git a/src/presets/_types.gen.ts b/src/presets/_types.gen.ts index ddf0a9f12e..7ab4e53265 100644 --- a/src/presets/_types.gen.ts +++ b/src/presets/_types.gen.ts @@ -20,6 +20,6 @@ export interface PresetOptions { export const presetsWithConfig = ["awsAmplify","awsLambda","azure","cloudflare","firebase","netlify","vercel"] as const; -export type PresetName = "alwaysdata" | "aws-amplify" | "aws-lambda" | "azure-swa" | "base-worker" | "bun" | "cleavr" | "cloudflare-dev" | "cloudflare-durable" | "cloudflare-module" | "cloudflare-pages" | "cloudflare-pages-static" | "deno" | "deno-deploy" | "deno-server" | "digital-ocean" | "edgeone" | "firebase-app-hosting" | "flight-control" | "genezio" | "github-pages" | "gitlab-pages" | "heroku" | "iis-handler" | "iis-node" | "koyeb" | "netlify" | "netlify-edge" | "netlify-static" | "nitro-dev" | "nitro-prerender" | "node" | "node-cluster" | "node-middleware" | "node-server" | "platform-sh" | "render-com" | "standard" | "static" | "stormkit" | "vercel" | "vercel-static" | "winterjs" | "zeabur" | "zeabur-static" | "zerops" | "zerops-static"; +export type PresetName = "alwaysdata" | "aws-amplify" | "aws-lambda" | "azure-swa" | "base-worker" | "bun" | "cleavr" | "cloudflare-dev" | "cloudflare-durable" | "cloudflare-module" | "cloudflare-pages" | "cloudflare-pages-static" | "deno" | "deno-deploy" | "deno-server" | "digital-ocean" | "edgeone-pages" | "firebase-app-hosting" | "flight-control" | "genezio" | "github-pages" | "gitlab-pages" | "heroku" | "iis-handler" | "iis-node" | "koyeb" | "netlify" | "netlify-edge" | "netlify-static" | "nitro-dev" | "nitro-prerender" | "node" | "node-cluster" | "node-middleware" | "node-server" | "platform-sh" | "render-com" | "standard" | "static" | "stormkit" | "vercel" | "vercel-static" | "winterjs" | "zeabur" | "zeabur-static" | "zerops" | "zerops-static"; -export type PresetNameInput = "alwaysdata" | "aws-amplify" | "awsAmplify" | "aws_amplify" | "aws-lambda" | "awsLambda" | "aws_lambda" | "azure-swa" | "azureSwa" | "azure_swa" | "base-worker" | "baseWorker" | "base_worker" | "bun" | "cleavr" | "cloudflare-dev" | "cloudflareDev" | "cloudflare_dev" | "cloudflare-durable" | "cloudflareDurable" | "cloudflare_durable" | "cloudflare-module" | "cloudflareModule" | "cloudflare_module" | "cloudflare-pages" | "cloudflarePages" | "cloudflare_pages" | "cloudflare-pages-static" | "cloudflarePagesStatic" | "cloudflare_pages_static" | "deno" | "deno-deploy" | "denoDeploy" | "deno_deploy" | "deno-server" | "denoServer" | "deno_server" | "digital-ocean" | "digitalOcean" | "digital_ocean" | "edgeone" | "firebase-app-hosting" | "firebaseAppHosting" | "firebase_app_hosting" | "flight-control" | "flightControl" | "flight_control" | "genezio" | "github-pages" | "githubPages" | "github_pages" | "gitlab-pages" | "gitlabPages" | "gitlab_pages" | "heroku" | "iis-handler" | "iisHandler" | "iis_handler" | "iis-node" | "iisNode" | "iis_node" | "koyeb" | "netlify" | "netlify-edge" | "netlifyEdge" | "netlify_edge" | "netlify-static" | "netlifyStatic" | "netlify_static" | "nitro-dev" | "nitroDev" | "nitro_dev" | "nitro-prerender" | "nitroPrerender" | "nitro_prerender" | "node" | "node-cluster" | "nodeCluster" | "node_cluster" | "node-middleware" | "nodeMiddleware" | "node_middleware" | "node-server" | "nodeServer" | "node_server" | "platform-sh" | "platformSh" | "platform_sh" | "render-com" | "renderCom" | "render_com" | "standard" | "static" | "stormkit" | "vercel" | "vercel-static" | "vercelStatic" | "vercel_static" | "winterjs" | "zeabur" | "zeabur-static" | "zeaburStatic" | "zeabur_static" | "zerops" | "zerops-static" | "zeropsStatic" | "zerops_static" | (string & {}); +export type PresetNameInput = "alwaysdata" | "aws-amplify" | "awsAmplify" | "aws_amplify" | "aws-lambda" | "awsLambda" | "aws_lambda" | "azure-swa" | "azureSwa" | "azure_swa" | "base-worker" | "baseWorker" | "base_worker" | "bun" | "cleavr" | "cloudflare-dev" | "cloudflareDev" | "cloudflare_dev" | "cloudflare-durable" | "cloudflareDurable" | "cloudflare_durable" | "cloudflare-module" | "cloudflareModule" | "cloudflare_module" | "cloudflare-pages" | "cloudflarePages" | "cloudflare_pages" | "cloudflare-pages-static" | "cloudflarePagesStatic" | "cloudflare_pages_static" | "deno" | "deno-deploy" | "denoDeploy" | "deno_deploy" | "deno-server" | "denoServer" | "deno_server" | "digital-ocean" | "digitalOcean" | "digital_ocean" | "edgeone-pages" | "edgeonePages" | "edgeone_pages" | "firebase-app-hosting" | "firebaseAppHosting" | "firebase_app_hosting" | "flight-control" | "flightControl" | "flight_control" | "genezio" | "github-pages" | "githubPages" | "github_pages" | "gitlab-pages" | "gitlabPages" | "gitlab_pages" | "heroku" | "iis-handler" | "iisHandler" | "iis_handler" | "iis-node" | "iisNode" | "iis_node" | "koyeb" | "netlify" | "netlify-edge" | "netlifyEdge" | "netlify_edge" | "netlify-static" | "netlifyStatic" | "netlify_static" | "nitro-dev" | "nitroDev" | "nitro_dev" | "nitro-prerender" | "nitroPrerender" | "nitro_prerender" | "node" | "node-cluster" | "nodeCluster" | "node_cluster" | "node-middleware" | "nodeMiddleware" | "node_middleware" | "node-server" | "nodeServer" | "node_server" | "platform-sh" | "platformSh" | "platform_sh" | "render-com" | "renderCom" | "render_com" | "standard" | "static" | "stormkit" | "vercel" | "vercel-static" | "vercelStatic" | "vercel_static" | "winterjs" | "zeabur" | "zeabur-static" | "zeaburStatic" | "zeabur_static" | "zerops" | "zerops-static" | "zeropsStatic" | "zerops_static" | (string & {}); diff --git a/src/presets/edgeone/preset.ts b/src/presets/edgeone/preset.ts index e73807fe86..ba8f75cf88 100644 --- a/src/presets/edgeone/preset.ts +++ b/src/presets/edgeone/preset.ts @@ -24,7 +24,7 @@ const edgeone = defineNitroPreset( } }, { - name: "edgeone" as const, + name: "edgeone-pages" as const, } ); diff --git a/src/presets/edgeone/runtime/_utils.ts b/src/presets/edgeone/runtime/_utils.ts deleted file mode 100644 index ee1caf4da8..0000000000 --- a/src/presets/edgeone/runtime/_utils.ts +++ /dev/null @@ -1,9 +0,0 @@ -export function normalizeHeaders(headers: Record): HeadersInit { - const normalized: Record = {}; - for (const [key, value] of Object.entries(headers)) { - if (value !== undefined) { - normalized[key] = Array.isArray(value) ? value.join(', ') : value; - } - } - return normalized; -} \ No newline at end of file diff --git a/src/presets/edgeone/runtime/edgeone.ts b/src/presets/edgeone/runtime/edgeone.ts index 2289753107..074d5d6eea 100644 --- a/src/presets/edgeone/runtime/edgeone.ts +++ b/src/presets/edgeone/runtime/edgeone.ts @@ -1,7 +1,7 @@ -import "#nitro-internal-polyfills"; +import "#nitro/virtual/polyfills"; +import { NodeRequest } from "srvx/node"; import { useNitroApp } from "nitro/app"; import type { IncomingMessage } from "node:http"; -import { normalizeHeaders } from "./_utils.ts"; const nitroApp = useNitroApp(); @@ -9,23 +9,13 @@ interface EdgeOneRequest extends IncomingMessage { url: string; method: string; headers: Record; - body: string; } // EdgeOne bootstrap expects: async (req, context) => Response -export default async function handle(req: EdgeOneRequest, context: unknown) { - // Build full URL from Node.js request headers - const host = req.headers['eo-pages-host'] || req.headers['host'] || 'localhost'; - const protocol = req.headers['x-forwarded-proto'] || 'https'; - const url = `${protocol}://${host}${req.url}`; - - // Create Web Request from Node.js request - const request = new Request(url, { - method: req.method || 'GET', - headers: normalizeHeaders(req.headers), - body: req.body, - }); - +export default async function handle(req: EdgeOneRequest) { + // Use srvx NodeRequest to convert Node.js request to Web Request + const request = new NodeRequest({ req }); + return nitroApp.fetch(request); } From 197f4abb579559ca944fba5570db73c3788cbc35 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Wed, 24 Dec 2025 10:26:16 +0000 Subject: [PATCH 4/4] chore: apply automated updates --- src/presets/edgeone/preset.ts | 4 +-- src/presets/edgeone/runtime/edgeone.ts | 4 +-- src/presets/edgeone/utils.ts | 36 +++++++++++++------------- 3 files changed, 21 insertions(+), 23 deletions(-) diff --git a/src/presets/edgeone/preset.ts b/src/presets/edgeone/preset.ts index ba8f75cf88..209057a5e3 100644 --- a/src/presets/edgeone/preset.ts +++ b/src/presets/edgeone/preset.ts @@ -20,8 +20,8 @@ const edgeone = defineNitroPreset( hooks: { async compiled(nitro: Nitro) { await writeEdgeOneRoutes(nitro); - } - } + }, + }, }, { name: "edgeone-pages" as const, diff --git a/src/presets/edgeone/runtime/edgeone.ts b/src/presets/edgeone/runtime/edgeone.ts index 074d5d6eea..63b0373a7d 100644 --- a/src/presets/edgeone/runtime/edgeone.ts +++ b/src/presets/edgeone/runtime/edgeone.ts @@ -15,8 +15,6 @@ interface EdgeOneRequest extends IncomingMessage { export default async function handle(req: EdgeOneRequest) { // Use srvx NodeRequest to convert Node.js request to Web Request const request = new NodeRequest({ req }); - + return nitroApp.fetch(request); } - - diff --git a/src/presets/edgeone/utils.ts b/src/presets/edgeone/utils.ts index e44be5d648..dd0108110e 100644 --- a/src/presets/edgeone/utils.ts +++ b/src/presets/edgeone/utils.ts @@ -14,7 +14,7 @@ export async function writeEdgeOneRoutes(nitro: Nitro) { nitro.routing.sync(); const meta = { conf: { - ssr404: true + ssr404: true, }, frameworkRoutes: [] as FrameworkRoute[], }; @@ -31,12 +31,11 @@ export async function writeEdgeOneRoutes(nitro: Nitro) { method: route.method || "*", handler: Array.isArray(route.data) ? route.data[0] : route.data, })); - apiRoutes.forEach((route) => { + for (const route of apiRoutes) { meta.frameworkRoutes.push({ path: route.path, }); - }); - + } // 2. Get all page routes (prerendered routes) const pageRoutes = (nitro._prerenderedRoutes || []).map((route) => ({ @@ -66,15 +65,15 @@ export async function writeEdgeOneRoutes(nitro: Nitro) { path, cache: rules.cache as { swr?: boolean; maxAge?: number }, })); - swrRouteRules.forEach((route) => { + for (const route of swrRouteRules) { const maxAge = route.cache.maxAge; - meta.frameworkRoutes.forEach((frameworkRoute) => { + for (const frameworkRoute of meta.frameworkRoutes) { if (frameworkRoute.path === route.path) { Reflect.set(frameworkRoute, "isStatic", false); Reflect.set(frameworkRoute, "isr", maxAge); } - }); - }); + } + } // Merge all prerender routes const allPrerenderRoutes = [ @@ -84,15 +83,21 @@ export async function writeEdgeOneRoutes(nitro: Nitro) { ...pageRoutes.map((r) => r.path), ]), ]; - allPrerenderRoutes.forEach((route) => { + for (const route of allPrerenderRoutes) { meta.frameworkRoutes.push({ path: route, isStatic: true, }); - }); + } - await writeFile(join(nitro.options.output.dir, "meta.json"), JSON.stringify(meta, null, 2)); - await writeFile(join(nitro.options.output.serverDir, "meta.json"), JSON.stringify(meta, null, 2)); + await writeFile( + join(nitro.options.output.dir, "meta.json"), + JSON.stringify(meta, null, 2) + ); + await writeFile( + join(nitro.options.output.serverDir, "meta.json"), + JSON.stringify(meta, null, 2) + ); // Return all route information return { @@ -110,11 +115,7 @@ function prettyPath(p: string, highlight = true) { return highlight ? colors.cyan(p) : p; } -async function writeFile( - file: string, - contents: Buffer | string, - log = false -) { +async function writeFile(file: string, contents: Buffer | string, log = false) { await fsp.mkdir(dirname(file), { recursive: true }); await fsp.writeFile( file, @@ -125,4 +126,3 @@ async function writeFile( consola.info("Generated", prettyPath(file)); } } -