feat: init

This commit is contained in:
2026-02-13 22:02:30 +01:00
commit 8f9ff830fb
16711 changed files with 3307340 additions and 0 deletions

2
node_modules/nitropack/dist/presets/_all.gen.d.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
declare const _default: readonly [any, any, any, any, any, any, any, any, any, any, any, any, any, any, ...any[], any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any, any];
export default _default;

56
node_modules/nitropack/dist/presets/_all.gen.mjs generated vendored Normal file
View File

@@ -0,0 +1,56 @@
import _nitro from "./_nitro/preset.mjs";
import _static from "./_static/preset.mjs";
import _alwaysdata from "./alwaysdata/preset.mjs";
import _awsAmplify from "./aws-amplify/preset.mjs";
import _awsLambda from "./aws-lambda/preset.mjs";
import _azure from "./azure/preset.mjs";
import _bun from "./bun/preset.mjs";
import _cleavr from "./cleavr/preset.mjs";
import _cloudflare from "./cloudflare/preset.mjs";
import _deno from "./deno/preset.mjs";
import _digitalocean from "./digitalocean/preset.mjs";
import _edgio from "./edgio/preset.mjs";
import _firebase from "./firebase/preset.mjs";
import _flightcontrol from "./flightcontrol/preset.mjs";
import _genezio from "./genezio/preset.mjs";
import _heroku from "./heroku/preset.mjs";
import _iis from "./iis/preset.mjs";
import _koyeb from "./koyeb/preset.mjs";
import _netlify from "./netlify/preset.mjs";
import _node from "./node/preset.mjs";
import _platformSh from "./platform.sh/preset.mjs";
import _renderCom from "./render.com/preset.mjs";
import _stormkit from "./stormkit/preset.mjs";
import _vercel from "./vercel/preset.mjs";
import _winterjs from "./winterjs/preset.mjs";
import _zeabur from "./zeabur/preset.mjs";
import _zerops from "./zerops/preset.mjs";
export default [
..._nitro,
..._static,
..._alwaysdata,
..._awsAmplify,
..._awsLambda,
..._azure,
..._bun,
..._cleavr,
..._cloudflare,
..._deno,
..._digitalocean,
..._edgio,
..._firebase,
..._flightcontrol,
..._genezio,
..._heroku,
..._iis,
..._koyeb,
..._netlify,
..._node,
..._platformSh,
..._renderCom,
..._stormkit,
..._vercel,
..._winterjs,
..._zeabur,
..._zerops
];

View File

@@ -0,0 +1,2 @@
declare const _default: readonly [any];
export default _default;

View File

@@ -0,0 +1,25 @@
import { defineNitroPreset } from "nitropack/kit";
const baseWorker = defineNitroPreset(
{
entry: null,
// Abstract
node: false,
minify: true,
noExternals: true,
rollupConfig: {
output: {
format: "iife",
generatedCode: {
symbols: true
}
}
},
inlineDynamicImports: true
// iffe does not support code-splitting
},
{
name: "base-worker",
url: import.meta.url
}
);
export default [baseWorker];

View File

@@ -0,0 +1,2 @@
declare const _default: readonly [any];
export default _default;

View File

@@ -0,0 +1,22 @@
import { defineNitroPreset } from "nitropack/kit";
const nitroDev = defineNitroPreset(
{
entry: "./runtime/nitro-dev",
output: {
dir: "{{ buildDir }}/dev",
serverDir: "{{ buildDir }}/dev",
publicDir: "{{ buildDir }}/dev"
},
externals: { trace: false },
serveStatic: true,
inlineDynamicImports: true,
// externals plugin limitation
sourceMap: true
},
{
name: "nitro-dev",
dev: true,
url: import.meta.url
}
);
export default [nitroDev];

View File

@@ -0,0 +1,2 @@
declare const _default: readonly [any];
export default _default;

View File

@@ -0,0 +1,17 @@
import { defineNitroPreset } from "nitropack/kit";
const nitroPrerender = defineNitroPreset(
{
extends: "node",
serveStatic: true,
entry: "./runtime/nitro-prerenderer",
output: {
serverDir: "{{ buildDir }}/prerender"
},
externals: { trace: false }
},
{
name: "nitro-prerender",
url: import.meta.url
}
);
export default [nitroPrerender];

View File

@@ -0,0 +1,2 @@
declare const _default: readonly [any, any, any, any];
export default _default;

View File

@@ -0,0 +1,5 @@
import worker from "./base-worker.mjs";
import dev from "./nitro-dev.mjs";
import prerender from "./nitro-prerender.mjs";
import sw from "./service-worker.mjs";
export default [...worker, ...dev, ...prerender, ...sw];

View File

@@ -0,0 +1 @@
import "#nitro-internal-pollyfills";

View File

@@ -0,0 +1,111 @@
import "#nitro-internal-pollyfills";
import { tmpdir } from "node:os";
import { useNitroApp } from "nitropack/runtime";
import { runTask } from "nitropack/runtime";
import { trapUnhandledNodeErrors } from "nitropack/runtime/internal";
import { startScheduleRunner } from "nitropack/runtime/internal";
import { scheduledTasks, tasks } from "#nitro-internal-virtual/tasks";
import { Server } from "node:http";
import { join } from "node:path";
import nodeCrypto from "node:crypto";
import { parentPort, threadId } from "node:worker_threads";
import wsAdapter from "crossws/adapters/node";
import {
defineEventHandler,
getQuery,
getRouterParam,
readBody,
toNodeListener
} from "h3";
if (!globalThis.crypto) {
globalThis.crypto = nodeCrypto.webcrypto;
}
const { NITRO_NO_UNIX_SOCKET, NITRO_DEV_WORKER_ID } = process.env;
trapUnhandledNodeErrors();
parentPort?.on("message", (msg) => {
if (msg && msg.event === "shutdown") {
shutdown();
}
});
const nitroApp = useNitroApp();
const server = new Server(toNodeListener(nitroApp.h3App));
let listener;
listen().catch(() => listen(
true
/* use random port */
)).catch((error) => {
console.error("Dev worker failed to listen:", error);
return shutdown();
});
if (import.meta._websocket) {
const { handleUpgrade } = wsAdapter(nitroApp.h3App.websocket);
server.on("upgrade", handleUpgrade);
}
nitroApp.router.get(
"/_nitro/tasks",
defineEventHandler(async (event) => {
const _tasks = await Promise.all(
Object.entries(tasks).map(async ([name, task]) => {
const _task = await task.resolve?.();
return [name, { description: _task?.meta?.description }];
})
);
return {
tasks: Object.fromEntries(_tasks),
scheduledTasks
};
})
);
nitroApp.router.use(
"/_nitro/tasks/:name",
defineEventHandler(async (event) => {
const name = getRouterParam(event, "name");
const payload = {
...getQuery(event),
...await readBody(event).then((r) => r?.payload).catch(() => ({}))
};
return await runTask(name, { payload });
})
);
if (import.meta._tasks) {
startScheduleRunner();
}
function listen(useRandomPort = Boolean(
NITRO_NO_UNIX_SOCKET || process.versions.webcontainer || "Bun" in globalThis && process.platform === "win32"
)) {
return new Promise((resolve, reject) => {
try {
listener = server.listen(useRandomPort ? 0 : getSocketAddress(), () => {
const address = server.address();
parentPort?.postMessage({
event: "listen",
address: typeof address === "string" ? { socketPath: address } : { host: "localhost", port: address?.port }
});
resolve();
});
} catch (error) {
reject(error);
}
});
}
function getSocketAddress() {
const socketName = `nitro-worker-${process.pid}-${threadId}-${NITRO_DEV_WORKER_ID}-${Math.round(Math.random() * 1e4)}.sock`;
if (process.platform === "win32") {
return join(String.raw`\\.\pipe`, socketName);
}
if (process.platform === "linux") {
const nodeMajor = Number.parseInt(process.versions.node.split(".")[0], 10);
if (nodeMajor >= 20) {
return `\0${socketName}`;
}
}
return join(tmpdir(), socketName);
}
async function shutdown() {
server.closeAllConnections?.();
await Promise.all([
new Promise((resolve) => listener?.close(resolve)),
nitroApp.hooks.callHook("close").catch(console.error)
]);
parentPort?.postMessage({ event: "exit" });
}

View File

@@ -0,0 +1,3 @@
import "#nitro-internal-pollyfills";
export declare const localFetch: any;
export declare const closePrerenderer: () => any;

View File

@@ -0,0 +1,7 @@
import "#nitro-internal-pollyfills";
import { useNitroApp } from "nitropack/runtime";
import { trapUnhandledNodeErrors } from "nitropack/runtime/internal";
const nitroApp = useNitroApp();
export const localFetch = nitroApp.localFetch;
export const closePrerenderer = () => nitroApp.hooks.callHook("close");
trapUnhandledNodeErrors();

View File

@@ -0,0 +1 @@
import "#nitro-internal-pollyfills";

View File

@@ -0,0 +1,31 @@
import "#nitro-internal-pollyfills";
import { useNitroApp } from "nitropack/runtime";
import { isPublicAssetURL } from "#nitro-internal-virtual/public-assets";
const nitroApp = useNitroApp();
addEventListener("fetch", (event) => {
const url = new URL(event.request.url);
if (isPublicAssetURL(url.pathname) || url.pathname.includes("/_server/")) {
return;
}
event.respondWith(handleEvent(url, event));
});
async function handleEvent(url, event) {
let body;
if (event.request.body) {
body = await event.request.arrayBuffer();
}
return nitroApp.localFetch(url.pathname + url.search, {
host: url.hostname,
protocol: url.protocol,
headers: event.request.headers,
method: event.request.method,
redirect: event.request.redirect,
body
});
}
self.addEventListener("install", () => {
self.skipWaiting();
});
self.addEventListener("activate", (event) => {
event.waitUntil(self.clients.claim());
});

View File

@@ -0,0 +1,2 @@
declare const _default: readonly [any];
export default _default;

View File

@@ -0,0 +1,110 @@
import { existsSync, promises as fsp } from "node:fs";
import { defineNitroPreset } from "nitropack/kit";
import { resolve } from "pathe";
import { joinURL } from "ufo";
const serviceWorker = defineNitroPreset(
() => {
return {
extends: "base-worker",
entry: "./runtime/service-worker",
output: {
serverDir: "{{ output.dir }}/public/server"
},
commands: {
preview: "npx serve {{ output.publicDir }}"
},
hooks: {
"prerender:generate"(route, nitro) {
const script = scriptTemplate(nitro.options.baseURL);
route.contents = (route.contents || "").replace(
"</head>",
`${script}
</head>`
);
},
async compiled(nitro) {
await fsp.writeFile(
resolve(nitro.options.output.publicDir, "sw.js"),
`self.importScripts('${joinURL(
nitro.options.baseURL,
"server/index.mjs"
)}');`,
"utf8"
);
const html = htmlTemplate(nitro.options.baseURL);
if (!existsSync(resolve(nitro.options.output.publicDir, "index.html"))) {
await fsp.writeFile(
resolve(nitro.options.output.publicDir, "index.html"),
html,
"utf8"
);
}
if (!existsSync(resolve(nitro.options.output.publicDir, "200.html"))) {
await fsp.writeFile(
resolve(nitro.options.output.publicDir, "200.html"),
html,
"utf8"
);
}
if (!existsSync(resolve(nitro.options.output.publicDir, "404.html"))) {
await fsp.writeFile(
resolve(nitro.options.output.publicDir, "404.html"),
html,
"utf8"
);
}
}
}
};
},
{
name: "service-worker",
url: import.meta.url
}
);
export default [serviceWorker];
function htmlTemplate(baseURL = "/") {
return (
/* html */
`<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="prefetch" href="${joinURL(baseURL, "sw.js")}">
<link rel="prefetch" href="${joinURL(baseURL, "server/index.mjs")}">
${scriptTemplate(baseURL)}
</head>
<body>
Initializing nitro service worker...
</body>
</html>`
);
}
function scriptTemplate(baseURL = "/") {
return (
/* js */
`
<script>
async function register () {
const registration = await navigator.serviceWorker.register('${joinURL(
baseURL,
"sw.js"
)}')
await navigator.serviceWorker.ready
registration.active.addEventListener('statechange', (event) => {
if (event.target.state === 'activated') {
window.location.reload()
}
})
}
if ('serviceWorker' in navigator) {
if (location.hostname !== 'localhost' && location.protocol === 'http:') {
location.replace(location.href.replace('http://', 'https://'))
} else {
register()
}
}
<\/script>
`
);
}

9
node_modules/nitropack/dist/presets/_resolve.d.ts generated vendored Normal file
View File

@@ -0,0 +1,9 @@
import { type CompatibilityDateSpec } from "compatx";
import type { NitroPreset, NitroPresetMeta } from "nitropack/types";
export declare function resolvePreset(name: string, opts?: {
static?: boolean;
compatibilityDate?: false | CompatibilityDateSpec;
dev?: boolean;
}): Promise<(NitroPreset & {
_meta?: NitroPresetMeta;
}) | undefined>;

64
node_modules/nitropack/dist/presets/_resolve.mjs generated vendored Normal file
View File

@@ -0,0 +1,64 @@
import {
resolveCompatibilityDatesFromEnv,
formatCompatibilityDate
} from "compatx";
import { kebabCase } from "scule";
import { provider } from "std-env";
import allPresets from "./_all.gen.mjs";
const _stdProviderMap = {
aws_amplify: "aws",
azure_static: "azure",
cloudflare_pages: "cloudflare"
};
export async function resolvePreset(name, opts = {}) {
if (name === ".") {
return void 0;
}
const _name = kebabCase(name) || provider;
const _compatDates = opts.compatibilityDate ? resolveCompatibilityDatesFromEnv(opts.compatibilityDate) : false;
const matches = allPresets.filter((preset2) => {
const names = [preset2._meta.name, preset2._meta.stdName, ...preset2._meta.aliases || []].filter(Boolean);
if (!names.includes(_name)) {
return false;
}
if (opts.dev && !preset2._meta.dev || !opts.dev && preset2._meta.dev) {
return false;
}
if (_compatDates) {
const _date = _compatDates[_stdProviderMap[preset2._meta.stdName]] || _compatDates[preset2._meta.stdName] || _compatDates[preset2._meta.name] || _compatDates.default;
if (_date && preset2._meta.compatibilityDate && new Date(preset2._meta.compatibilityDate) > new Date(_date)) {
return false;
}
}
return true;
}).sort((a, b) => {
const aDate = new Date(a._meta.compatibilityDate || 0);
const bDate = new Date(b._meta.compatibilityDate || 0);
return bDate > aDate ? 1 : -1;
});
const preset = matches.find(
(p) => (p._meta.static || false) === (opts?.static || false)
) || matches[0];
if (typeof preset === "function") {
return preset();
}
if (!name && !preset) {
return opts?.static ? resolvePreset("static", opts) : resolvePreset("node-server", opts);
}
if (name && !preset) {
const options = allPresets.filter((p) => p._meta.name === name || p._meta.stdName === name || p._meta.aliases?.includes(name)).sort((a, b) => (a._meta.compatibilityDate || 0) > (b._meta.compatibilityDate || 0) ? 1 : -1);
if (options.length > 0) {
let msg = `Preset "${name}" cannot be resolved with current compatibilityDate: ${formatCompatibilityDate(_compatDates || "")}.
`;
for (const option of options) {
msg += `
- ${option._meta.name} (requires compatibilityDate >= ${option._meta.compatibilityDate})`;
}
const err = new Error(msg);
Error.captureStackTrace?.(err, resolvePreset);
throw err;
}
}
return preset;
}

View File

@@ -0,0 +1,2 @@
declare const _default: readonly [any, any, any];
export default _default;

69
node_modules/nitropack/dist/presets/_static/preset.mjs generated vendored Normal file
View File

@@ -0,0 +1,69 @@
import fsp from "node:fs/promises";
import { defineNitroPreset } from "nitropack/kit";
import { join } from "pathe";
const _static = defineNitroPreset(
{
static: true,
output: {
dir: "{{ rootDir }}/.output",
publicDir: "{{ output.dir }}/public"
},
prerender: {
crawlLinks: true
},
commands: {
preview: "npx serve {{ output.publicDir }}"
}
},
{
name: "static",
static: true,
url: import.meta.url
}
);
const githubPages = defineNitroPreset(
{
extends: "static",
commands: {
deploy: "npx gh-pages --dotfiles -d {{ output.publicDir }}"
},
prerender: {
routes: [
"/",
// https://docs.github.com/en/pages/getting-started-with-github-pages/creating-a-custom-404-page-for-your-github-pages-site
"/404.html"
]
},
hooks: {
async compiled(nitro) {
await fsp.writeFile(
join(nitro.options.output.publicDir, ".nojekyll"),
""
);
}
}
},
{
name: "github-pages",
static: true,
url: import.meta.url
}
);
const gitlabPages = defineNitroPreset(
{
extends: "static",
prerender: {
routes: [
"/",
// https://docs.gitlab.com/ee/user/project/pages/introduction.html#custom-error-codes-pages
"/404.html"
]
}
},
{
name: "gitlab-pages",
static: true,
url: import.meta.url
}
);
export default [_static, githubPages, gitlabPages];

19
node_modules/nitropack/dist/presets/_types.gen.d.ts generated vendored Normal file
View File

@@ -0,0 +1,19 @@
import type { PresetOptions as AwsAmplifyOptions } from "./aws-amplify/preset";
import type { PresetOptions as AwsLambdaOptions } from "./aws-lambda/preset";
import type { PresetOptions as AzureOptions } from "./azure/preset";
import type { PresetOptions as CloudflareOptions } from "./cloudflare/preset";
import type { PresetOptions as FirebaseOptions } from "./firebase/preset";
import type { PresetOptions as NetlifyOptions } from "./netlify/preset";
import type { PresetOptions as VercelOptions } from "./vercel/preset";
export interface PresetOptions {
awsAmplify?: AwsAmplifyOptions;
awsLambda?: AwsLambdaOptions;
azure?: AzureOptions;
cloudflare?: CloudflareOptions;
firebase?: FirebaseOptions;
netlify?: NetlifyOptions;
vercel?: VercelOptions;
}
export declare const presetsWithConfig: readonly ["awsAmplify", "awsLambda", "azure", "cloudflare", "firebase", "netlify", "vercel"];
export type PresetName = "alwaysdata" | "aws-amplify" | "aws-lambda" | "azure" | "azure-functions" | "azure-swa" | "base-worker" | "bun" | "cleavr" | "cli" | "cloudflare" | "cloudflare-dev" | "cloudflare-durable" | "cloudflare-module" | "cloudflare-module-legacy" | "cloudflare-pages" | "cloudflare-pages-static" | "cloudflare-worker" | "deno" | "deno-deploy" | "deno-server" | "deno-server-legacy" | "digital-ocean" | "edgio" | "firebase" | "firebase-app-hosting" | "flight-control" | "genezio" | "github-pages" | "gitlab-pages" | "heroku" | "iis" | "iis-handler" | "iis-node" | "koyeb" | "layer0" | "netlify" | "netlify-builder" | "netlify-edge" | "netlify-legacy" | "netlify-static" | "nitro-dev" | "nitro-prerender" | "node" | "node-cluster" | "node-listener" | "node-server" | "platform-sh" | "render-com" | "service-worker" | "static" | "stormkit" | "vercel" | "vercel-edge" | "vercel-static" | "winterjs" | "zeabur" | "zeabur-static" | "zerops" | "zerops-static";
export type PresetNameInput = "alwaysdata" | "aws-amplify" | "awsAmplify" | "aws_amplify" | "aws-lambda" | "awsLambda" | "aws_lambda" | "azure" | "azure-functions" | "azureFunctions" | "azure_functions" | "azure-swa" | "azureSwa" | "azure_swa" | "base-worker" | "baseWorker" | "base_worker" | "bun" | "cleavr" | "cli" | "cloudflare" | "cloudflare-dev" | "cloudflareDev" | "cloudflare_dev" | "cloudflare-durable" | "cloudflareDurable" | "cloudflare_durable" | "cloudflare-module" | "cloudflareModule" | "cloudflare_module" | "cloudflare-module-legacy" | "cloudflareModuleLegacy" | "cloudflare_module_legacy" | "cloudflare-pages" | "cloudflarePages" | "cloudflare_pages" | "cloudflare-pages-static" | "cloudflarePagesStatic" | "cloudflare_pages_static" | "cloudflare-worker" | "cloudflareWorker" | "cloudflare_worker" | "deno" | "deno-deploy" | "denoDeploy" | "deno_deploy" | "deno-server" | "denoServer" | "deno_server" | "deno-server-legacy" | "denoServerLegacy" | "deno_server_legacy" | "digital-ocean" | "digitalOcean" | "digital_ocean" | "edgio" | "firebase" | "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" | "iis-handler" | "iisHandler" | "iis_handler" | "iis-node" | "iisNode" | "iis_node" | "koyeb" | "layer0" | "netlify" | "netlify-builder" | "netlifyBuilder" | "netlify_builder" | "netlify-edge" | "netlifyEdge" | "netlify_edge" | "netlify-legacy" | "netlifyLegacy" | "netlify_legacy" | "netlify-static" | "netlifyStatic" | "netlify_static" | "nitro-dev" | "nitroDev" | "nitro_dev" | "nitro-prerender" | "nitroPrerender" | "nitro_prerender" | "node" | "node-cluster" | "nodeCluster" | "node_cluster" | "node-listener" | "nodeListener" | "node_listener" | "node-server" | "nodeServer" | "node_server" | "platform-sh" | "platformSh" | "platform_sh" | "render-com" | "renderCom" | "render_com" | "service-worker" | "serviceWorker" | "service_worker" | "static" | "stormkit" | "vercel" | "vercel-edge" | "vercelEdge" | "vercel_edge" | "vercel-static" | "vercelStatic" | "vercel_static" | "winterjs" | "zeabur" | "zeabur-static" | "zeaburStatic" | "zeabur_static" | "zerops" | "zerops-static" | "zeropsStatic" | "zerops_static" | (string & {});

1
node_modules/nitropack/dist/presets/_types.gen.mjs generated vendored Normal file
View File

@@ -0,0 +1 @@
export const presetsWithConfig = ["awsAmplify", "awsLambda", "azure", "cloudflare", "firebase", "netlify", "vercel"];

View File

@@ -0,0 +1,3 @@
export declare const builtnNodeModules: string[];
export declare const hybridNodeModules: string[];
export declare const unsupportedNodeModules: string[];

View File

@@ -0,0 +1,81 @@
export const builtnNodeModules = [
"_stream_duplex",
"_stream_passthrough",
"_stream_readable",
"_stream_transform",
"_stream_writable",
"_tls_common",
"_tls_wrap",
// Missing exports: Server, createServer
"assert",
// Missing exports: CallTracker, partialDeepStrictEqual
"assert/strict",
// Missing exports: CallTracker, partialDeepStrictEqual
"async_hooks",
"buffer",
"constants",
// Missing exports: EXTENSIONLESS_FORMAT_JAVASCRIPT, EXTENSIONLESS_FORMAT_WASM, O_DIRECT, O_NOATIME, RTLD_DEEPBIND, SIGPOLL, SIGPWR, SIGSTKFLT, defaultCipherList
"crypto",
"diagnostics_channel",
"dns",
"dns/promises",
"events",
// Missing exports: captureRejections, init
"fs/promises",
"module",
"net",
"path",
"path/posix",
"path/win32",
"querystring",
"stream",
"stream/consumers",
"stream/promises",
"stream/web",
"string_decoder",
"timers",
"timers/promises",
"tls",
"url",
"util",
"util/types",
"zlib"
];
export const hybridNodeModules = [
"console",
"process"
// Missing exports: abort, allowedNodeEnvironmentFlags, arch, argv, argv0, assert, availableMemory, binding, chdir, config, constrainedMemory, cpuUsage, cwd, debugPort, dlopen, domain, emitWarning, execArgv, execPath, exitCode, finalization, getActiveResourcesInfo, getegid, geteuid, getgid, getgroups, getuid, hasUncaughtExceptionCaptureCallback, hrtime, initgroups, kill, loadEnvFile, memoryUsage, moduleLoadList, openStdin, pid, ppid, reallyExit, ref, release, report, resourceUsage, setSourceMapsEnabled, setUncaughtExceptionCaptureCallback, setegid, seteuid, setgid, setgroups, setuid, sourceMapsEnabled, stderr, stdin, stdout, title, umask, unref, uptime, version, versions
];
export const unsupportedNodeModules = [
"_http_agent",
"_http_client",
"_http_common",
"_http_incoming",
"_http_outgoing",
"_http_server",
"_stream_wrap",
"child_process",
"cluster",
"dgram",
"domain",
"fs",
"http",
"http2",
"https",
"inspector",
"inspector/promises",
"os",
"perf_hooks",
"punycode",
"readline",
"readline/promises",
"repl",
"sys",
"trace_events",
"tty",
"v8",
"vm",
"wasi",
"worker_threads",
"sqlite"
];

View File

@@ -0,0 +1,3 @@
export declare const builtnNodeModules: string[];
export declare const hybridNodeModules: never[];
export declare const unsupportedNodeModules: string[];

View File

@@ -0,0 +1,110 @@
export const builtnNodeModules = [
"_http_agent",
"_http_common",
// Missing exports: freeParser, isLenient, parsers, prepareError
"_http_outgoing",
"_http_server",
// Missing exports: Server, ServerResponse, httpServerPreClose, kConnectionsCheckingInterval, kServerResponse, setupConnectionsTracking, storeHTTPOptions
"_stream_duplex",
// Missing exports: from, fromWeb, toWeb
"_stream_passthrough",
"_stream_readable",
// Missing exports: ReadableState, from, fromWeb, toWeb, wrap
"_stream_transform",
"_stream_writable",
// Missing exports: WritableState, fromWeb, toWeb
"_tls_common",
// Missing exports: SecureContext, translatePeerCertificate
"_tls_wrap",
"assert",
// Missing exports: CallTracker, partialDeepStrictEqual
"assert/strict",
// Missing exports: CallTracker, partialDeepStrictEqual
"async_hooks",
"buffer",
// Missing exports: File, resolveObjectURL
"child_process",
"cluster",
"console",
// Missing exports: context, createTask
"constants",
// Missing exports: EXTENSIONLESS_FORMAT_JAVASCRIPT, EXTENSIONLESS_FORMAT_WASM, O_DIRECT, O_NOATIME, defaultCipherList
"crypto",
// Missing exports: Cipher, Decipher
"dgram",
"diagnostics_channel",
// Missing exports: Channel
"dns",
// Missing exports: getDefaultResultOrder, lookupService
"dns/promises",
// Missing exports: getDefaultResultOrder, lookupService
"domain",
"events",
// Missing exports: captureRejections, getMaxListeners, init, usingDomains
"fs",
// Missing exports: FileReadStream, FileWriteStream, fchmod, fchmodSync, fchown, fchownSync, glob, globSync, lchmod, lchmodSync, lchown, lchownSync, openAsBlob
"fs/promises",
// Missing exports: glob, lchmod, lchown, lutimes, statfs
"http",
// Missing exports: CloseEvent, MessageEvent, WebSocket, setMaxIdleHTTPParsers
"http2",
// Missing exports: performServerHandshake
"https",
"inspector",
"inspector/promises",
"module",
// Missing exports: SourceMap, constants, enableCompileCache, findPackageJSON, flushCompileCache, getCompileCacheDir, getSourceMapsSupport, runMain, setSourceMapsSupport, stripTypeScriptTypes, syncBuiltinESMExports
"net",
"os",
"path",
// Missing exports: matchesGlob
"path/posix",
// Missing exports: matchesGlob
"path/win32",
// Missing exports: matchesGlob
"perf_hooks",
// Missing exports: Performance, PerformanceMark, PerformanceMeasure, PerformanceObserverEntryList, PerformanceResourceTiming, createHistogram
"process",
// Missing exports: assert, availableMemory, binding, config, constrainedMemory, debugPort, domain, exitCode, features, finalization, getActiveResourcesInfo, getgroups, hasUncaughtExceptionCaptureCallback, initgroups, loadEnvFile, moduleLoadList, openStdin, ppid, reallyExit, ref, release, report, resourceUsage, setSourceMapsEnabled, setUncaughtExceptionCaptureCallback, setegid, seteuid, setgid, setgroups, setuid, sourceMapsEnabled, title, unref, uptime
"punycode",
"querystring",
"readline",
"readline/promises",
"repl",
// Missing exports: Recoverable, writer
"sqlite",
// Missing exports: StatementSync
"stream",
// Missing exports: destroy, promises
"stream/consumers",
"stream/promises",
"stream/web",
"string_decoder",
"sys",
// Missing exports: MIMEParams, MIMEType, getCallSite, getSystemErrorMap, getSystemErrorMessage, parseEnv, transferableAbortController, transferableAbortSignal
"timers",
// Missing exports: active, enroll, unenroll
"timers/promises",
"tls",
// Missing exports: SecureContext, convertALPNProtocols
"trace_events",
"tty",
"url",
"util",
// Missing exports: MIMEParams, MIMEType, getCallSite, getSystemErrorMap, getSystemErrorMessage, parseEnv, transferableAbortController, transferableAbortSignal
"util/types",
// Missing exports: isExternal
"v8",
// Missing exports: GCProfiler, promiseHooks, queryObjects, setHeapSnapshotNearHeapLimit, startupSnapshot
"vm",
"wasi",
"worker_threads",
// Missing exports: isInternalThread, isMarkedAsUntransferable, markAsUncloneable, postMessageToThread
"zlib"
];
export const hybridNodeModules = [];
export const unsupportedNodeModules = [
"_http_client",
"_http_incoming",
"_stream_wrap"
];

View File

@@ -0,0 +1,3 @@
export declare const builtnNodeModules: string[];
export declare const hybridNodeModules: never[];
export declare const unsupportedNodeModules: string[];

View File

@@ -0,0 +1,110 @@
export const builtnNodeModules = [
"_http_agent",
"_http_common",
// Missing exports: freeParser, isLenient, parsers, prepareError
"_http_outgoing",
"_http_server",
// Missing exports: Server, ServerResponse, httpServerPreClose, kConnectionsCheckingInterval, kServerResponse, setupConnectionsTracking, storeHTTPOptions
"_stream_duplex",
// Missing exports: from, fromWeb, toWeb
"_stream_passthrough",
"_stream_readable",
// Missing exports: ReadableState, from, fromWeb, toWeb, wrap
"_stream_transform",
"_stream_writable",
// Missing exports: WritableState, fromWeb, toWeb
"_tls_common",
// Missing exports: SecureContext, translatePeerCertificate
"_tls_wrap",
"assert",
// Missing exports: CallTracker, partialDeepStrictEqual
"assert/strict",
// Missing exports: CallTracker, partialDeepStrictEqual
"async_hooks",
"buffer",
// Missing exports: File, resolveObjectURL
"child_process",
"cluster",
"console",
// Missing exports: context, createTask
"constants",
// Missing exports: EXTENSIONLESS_FORMAT_JAVASCRIPT, EXTENSIONLESS_FORMAT_WASM, O_DIRECT, O_NOATIME, defaultCipherList
"crypto",
// Missing exports: Cipher, Decipher
"dgram",
"diagnostics_channel",
// Missing exports: Channel
"dns",
// Missing exports: getDefaultResultOrder, lookupService
"dns/promises",
// Missing exports: getDefaultResultOrder, lookupService
"domain",
"events",
// Missing exports: captureRejections, getMaxListeners, init, usingDomains
"fs",
// Missing exports: FileReadStream, FileWriteStream, fchmod, fchmodSync, fchown, fchownSync, glob, globSync, lchmod, lchmodSync, lchown, lchownSync, openAsBlob
"fs/promises",
// Missing exports: glob, lchmod, lchown, lutimes, statfs
"http",
// Missing exports: CloseEvent, MessageEvent, WebSocket, setMaxIdleHTTPParsers
"http2",
// Missing exports: performServerHandshake
"https",
"inspector",
"inspector/promises",
"module",
// Missing exports: SourceMap, constants, enableCompileCache, findPackageJSON, flushCompileCache, getCompileCacheDir, getSourceMapsSupport, runMain, setSourceMapsSupport, stripTypeScriptTypes, syncBuiltinESMExports
"net",
"os",
"path",
// Missing exports: matchesGlob
"path/posix",
// Missing exports: matchesGlob
"path/win32",
// Missing exports: matchesGlob
"perf_hooks",
// Missing exports: Performance, PerformanceMark, PerformanceMeasure, PerformanceObserverEntryList, PerformanceResourceTiming, createHistogram
"process",
// Missing exports: assert, availableMemory, binding, config, constrainedMemory, debugPort, domain, exitCode, features, finalization, getActiveResourcesInfo, getgroups, hasUncaughtExceptionCaptureCallback, initgroups, loadEnvFile, moduleLoadList, openStdin, ppid, reallyExit, ref, release, report, resourceUsage, setSourceMapsEnabled, setUncaughtExceptionCaptureCallback, setegid, seteuid, setgid, setgroups, setuid, sourceMapsEnabled, title, unref, uptime
"punycode",
"querystring",
"readline",
"readline/promises",
"repl",
// Missing exports: Recoverable, writer
"sqlite",
// Missing exports: StatementSync
"stream",
// Missing exports: destroy, promises
"stream/consumers",
"stream/promises",
"stream/web",
"string_decoder",
"sys",
// Missing exports: MIMEParams, MIMEType, getCallSite, getSystemErrorMap, getSystemErrorMessage, parseEnv, transferableAbortController, transferableAbortSignal
"timers",
// Missing exports: active, enroll, unenroll
"timers/promises",
"tls",
// Missing exports: SecureContext, convertALPNProtocols
"trace_events",
"tty",
"url",
"util",
// Missing exports: MIMEParams, MIMEType, getCallSite, getSystemErrorMap, getSystemErrorMessage, parseEnv, transferableAbortController, transferableAbortSignal
"util/types",
// Missing exports: isExternal
"v8",
// Missing exports: GCProfiler, promiseHooks, queryObjects, setHeapSnapshotNearHeapLimit, startupSnapshot
"vm",
"wasi",
"worker_threads",
// Missing exports: isInternalThread, isMarkedAsUntransferable, markAsUncloneable, postMessageToThread
"zlib"
];
export const hybridNodeModules = [];
export const unsupportedNodeModules = [
"_http_client",
"_http_incoming",
"_stream_wrap"
];

View File

@@ -0,0 +1,3 @@
export declare const builtnNodeModules: string[];
export declare const hybridNodeModules: never[];
export declare const unsupportedNodeModules: string[];

View File

@@ -0,0 +1,77 @@
export const builtnNodeModules = [
"assert",
// Missing exports: CallTracker, partialDeepStrictEqual
"async_hooks",
// Missing exports: asyncWrapProviders, createHook, executionAsyncId, executionAsyncResource, triggerAsyncId
"buffer",
"events",
"util"
// Missing exports: getCallSites, getSystemErrorMap, getSystemErrorMessage, getSystemErrorName, isBoolean, isBuffer, isDate, isError, isFunction, isNull, isNullOrUndefined, isNumber, isObject, isPrimitive, isRegExp, isString, isSymbol, isUndefined, parseEnv, styleText
];
export const hybridNodeModules = [];
export const unsupportedNodeModules = [
"_http_agent",
"_http_client",
"_http_common",
"_http_incoming",
"_http_outgoing",
"_http_server",
"_stream_duplex",
"_stream_passthrough",
"_stream_readable",
"_stream_transform",
"_stream_wrap",
"_stream_writable",
"_tls_common",
"_tls_wrap",
"assert/strict",
"child_process",
"cluster",
"console",
"constants",
"crypto",
"dgram",
"diagnostics_channel",
"dns",
"dns/promises",
"domain",
"fs",
"fs/promises",
"http",
"http2",
"https",
"inspector",
"inspector/promises",
"module",
"net",
"os",
"path",
"path/posix",
"path/win32",
"perf_hooks",
"process",
"punycode",
"querystring",
"readline",
"readline/promises",
"repl",
"stream",
"stream/consumers",
"stream/promises",
"stream/web",
"string_decoder",
"sys",
"timers",
"timers/promises",
"tls",
"trace_events",
"tty",
"url",
"util/types",
"v8",
"vm",
"wasi",
"worker_threads",
"zlib",
"sqlite"
];

View File

@@ -0,0 +1,2 @@
import type { Preset } from "unenv";
export declare const unenvDenoPreset: Preset;

View File

@@ -0,0 +1,20 @@
import { builtnNodeModules } from "./node-compat/deno.mjs";
export const unenvDenoPreset = {
meta: {
name: "nitro-deno",
url: import.meta.url
},
external: builtnNodeModules.map((m) => `node:${m}`),
alias: {
// (native)
...Object.fromEntries(
[...builtnNodeModules, "sys"].flatMap((m) => [
[m, `node:${m}`],
[`node:${m}`, `node:${m}`]
])
)
},
inject: {
performance: false
}
};

View File

@@ -0,0 +1,5 @@
import type { Preset } from "unenv";
import type { Plugin } from "rollup";
export declare const unenvCfExternals: Preset;
export declare const unenvWorkerdWithNodeCompat: Preset;
export declare const workerdHybridNodeCompatPlugin: Plugin;

View File

@@ -0,0 +1,61 @@
import { fileURLToPath } from "mlly";
import { join } from "pathe";
import { builtnNodeModules, hybridNodeModules } from "./node-compat/cloudflare.mjs";
const workerdDir = fileURLToPath(new URL("workerd/", import.meta.url));
const resolvePresetRuntime = (m) => join(workerdDir, `${m}.mjs`);
export const unenvCfExternals = {
meta: {
name: "nitro-cloudflare:externals",
url: import.meta.url
},
external: [
"cloudflare:email",
"cloudflare:sockets",
"cloudflare:workers",
"cloudflare:workflows"
]
};
export const unenvWorkerdWithNodeCompat = {
meta: {
name: "nitro-cloudflare:node-compat",
url: import.meta.url
},
external: builtnNodeModules.map((m) => `node:${m}`),
alias: {
// (native)
...Object.fromEntries(
builtnNodeModules.flatMap((m) => [
[m, `node:${m}`],
[`node:${m}`, `node:${m}`]
])
),
// (hybrid)
...Object.fromEntries(
hybridNodeModules.flatMap((m) => {
const resolved = resolvePresetRuntime(m);
return [
[`node:${m}`, resolved],
[m, resolved]
];
})
)
}
};
export const workerdHybridNodeCompatPlugin = {
name: "nitro:cloudflare:hybrid-node-compat",
resolveId(id) {
if (id.startsWith("cloudflare:")) {
return { id, external: true, moduleSideEffects: false };
}
if (id.startsWith("#workerd/node:")) {
return {
id: id.slice("#workerd/".length),
external: true,
moduleSideEffects: false
};
}
if (id.startsWith(workerdDir)) {
return { id, moduleSideEffects: false };
}
}
};

View File

@@ -0,0 +1,26 @@
export const assert: any;
export const clear: any;
export const context: any;
export const count: any;
export const countReset: any;
export const createTask: any;
export const debug: any;
export const dir: any;
export const dirxml: any;
export const error: any;
export const group: any;
export const groupCollapsed: any;
export const groupEnd: any;
export const info: any;
export const log: any;
export const profile: any;
export const profileEnd: any;
export const table: any;
export const time: any;
export const timeEnd: any;
export const timeLog: any;
export const timeStamp: any;
export const trace: any;
export const warn: any;
export default consoleModule;
declare const consoleModule: any;

View File

@@ -0,0 +1,69 @@
import workerdConsole from "#workerd/node:console";
import {
Console,
_ignoreErrors,
_stderr,
_stderrErrorHandler,
_stdout,
_stdoutErrorHandler,
_times,
} from "unenv/node/console";
export {
Console,
_ignoreErrors,
_stderr,
_stderrErrorHandler,
_stdout,
_stdoutErrorHandler,
_times,
} from "unenv/node/console";
export const {
assert,
clear,
context,
count,
countReset,
createTask,
debug,
dir,
dirxml,
error,
group,
groupCollapsed,
groupEnd,
info,
log,
profile,
profileEnd,
table,
time,
timeEnd,
timeLog,
timeStamp,
trace,
warn,
} = workerdConsole;
const consolePolyfill = {
Console,
_ignoreErrors,
_stderr,
_stderrErrorHandler,
_stdout,
_stdoutErrorHandler,
_times,
};
const consoleModule = /*@__PURE__*/ new Proxy(workerdConsole, {
get(target, prop) {
if (Reflect.has(target, prop)) {
return Reflect.get(target, prop);
}
return Reflect.get(consolePolyfill, prop);
},
});
export default consoleModule;

View File

@@ -0,0 +1,107 @@
export default mixedProcess;
export const abort: any;
export const addListener: any;
export const allowedNodeEnvironmentFlags: any;
export const hasUncaughtExceptionCaptureCallback: any;
export const setUncaughtExceptionCaptureCallback: any;
export const loadEnvFile: any;
export const sourceMapsEnabled: any;
export const arch: any;
export const argv: any;
export const argv0: any;
export const chdir: any;
export const config: any;
export const connected: any;
export const constrainedMemory: any;
export const availableMemory: any;
export const cpuUsage: any;
export const cwd: any;
export const debugPort: any;
export const dlopen: any;
export const disconnect: any;
export const emit: any;
export const emitWarning: any;
export const env: any;
export const eventNames: any;
export const execArgv: any;
export const execPath: any;
export const exit: any;
export const finalization: any;
export const features: any;
export const getBuiltinModule: any;
export const getActiveResourcesInfo: any;
export const getMaxListeners: any;
export const hrtime: any;
export const kill: any;
export const listeners: any;
export const listenerCount: any;
export const memoryUsage: any;
export const nextTick: any;
export const on: any;
export const off: any;
export const once: any;
export const pid: any;
export const platform: any;
export const ppid: any;
export const prependListener: any;
export const prependOnceListener: any;
export const rawListeners: any;
export const release: any;
export const removeAllListeners: any;
export const removeListener: any;
export const report: any;
export const resourceUsage: any;
export const setMaxListeners: any;
export const setSourceMapsEnabled: any;
export const stderr: any;
export const stdin: any;
export const stdout: any;
export const title: any;
export const umask: any;
export const uptime: any;
export const version: any;
export const versions: any;
export const domain: any;
export const initgroups: any;
export const moduleLoadList: any;
export const reallyExit: any;
export const openStdin: any;
export const assert: any;
export const binding: any;
export const send: any;
export const exitCode: any;
export const channel: any;
export const getegid: any;
export const geteuid: any;
export const getgid: any;
export const getgroups: any;
export const getuid: any;
export const setegid: any;
export const seteuid: any;
export const setgid: any;
export const setgroups: any;
export const setuid: any;
export const permission: any;
export const mainModule: any;
export const _events: any;
export const _eventsCount: any;
export const _exiting: any;
export const _maxListeners: any;
export const _debugEnd: any;
export const _debugProcess: any;
export const _fatalException: any;
export const _getActiveHandles: any;
export const _getActiveRequests: any;
export const _kill: any;
export const _preload_modules: any;
export const _rawDebug: any;
export const _startProfilerIdleNotifier: any;
export const _stopProfilerIdleNotifier: any;
export const _tickCallback: any;
export const _disconnect: any;
export const _handleQueue: any;
export const _pendingMessage: any;
export const _channel: any;
export const _send: any;
export const _linkedBinding: any;
declare const mixedProcess: any;

View File

@@ -0,0 +1,144 @@
// https://github.com/cloudflare/workerd/blob/main/src/node/internal/process.ts
// https://github.com/unjs/unenv/blob/main/src/runtime/node/process.ts
import workerdProcess from "#workerd/node:process";
import { env as WorkerEnv } from "cloudflare:workers";
import { Process as UnenvProcess } from "unenv/node/internal/process/process";
import { env as UnenvEnv } from "unenv/node/internal/process/env";
import { hrtime as UnenvHrTime } from "unenv/node/internal/process/hrtime";
// Polyfill for unenv (without Node.js compatibility)
globalThis.__env__ = WorkerEnv;
const mixedProcess = new UnenvProcess({
env: UnenvEnv,
hrtime: UnenvHrTime,
nextTick: workerdProcess.nextTick,
});
// https://github.com/cloudflare/workerd/blob/main/src/node/internal/process.ts#L94
for (const key of ["exit", "getBuiltinModule", "platform"]) {
if (key in workerdProcess) {
mixedProcess[key] = workerdProcess[key];
}
}
if (workerdProcess.features) {
Object.defineProperty(mixedProcess, "features", {
get() {
return workerdProcess.features;
},
});
}
export default mixedProcess;
export const {
abort,
addListener,
allowedNodeEnvironmentFlags,
hasUncaughtExceptionCaptureCallback,
setUncaughtExceptionCaptureCallback,
loadEnvFile,
sourceMapsEnabled,
arch,
argv,
argv0,
chdir,
config,
connected,
constrainedMemory,
availableMemory,
cpuUsage,
cwd,
debugPort,
dlopen,
disconnect,
emit,
emitWarning,
env,
eventNames,
execArgv,
execPath,
exit,
finalization,
features,
getBuiltinModule,
getActiveResourcesInfo,
getMaxListeners,
hrtime,
kill,
listeners,
listenerCount,
memoryUsage,
nextTick,
on,
off,
once,
pid,
platform,
ppid,
prependListener,
prependOnceListener,
rawListeners,
release,
removeAllListeners,
removeListener,
report,
resourceUsage,
setMaxListeners,
setSourceMapsEnabled,
stderr,
stdin,
stdout,
title,
umask,
uptime,
version,
versions,
domain,
initgroups,
moduleLoadList,
reallyExit,
openStdin,
assert,
binding,
send,
exitCode,
channel,
getegid,
geteuid,
getgid,
getgroups,
getuid,
setegid,
seteuid,
setgid,
setgroups,
setuid,
permission,
mainModule,
_events,
_eventsCount,
_exiting,
_maxListeners,
_debugEnd,
_debugProcess,
_fatalException,
_getActiveHandles,
_getActiveRequests,
_kill,
_preload_modules,
_rawDebug,
_startProfilerIdleNotifier,
_stopProfilerIdleNotifier,
_tickCallback,
_disconnect,
_handleQueue,
_pendingMessage,
_channel,
_send,
_linkedBinding,
} = mixedProcess;

View File

@@ -0,0 +1,2 @@
declare const _default: readonly [any];
export default _default;

View File

@@ -0,0 +1,14 @@
import { defineNitroPreset } from "nitropack/kit";
const alwaysdata = defineNitroPreset(
{
extends: "node-server",
commands: {
deploy: "rsync -rRt --info=progress2 ./ [account]@ssh-[account].alwaysdata.net:www/my-app"
}
},
{
name: "alwaysdata",
url: import.meta.url
}
);
export default [alwaysdata];

View File

@@ -0,0 +1,3 @@
export type { AWSAmplifyOptions as PresetOptions } from "./types";
declare const _default: readonly [any];
export default _default;

View File

@@ -0,0 +1,27 @@
import { defineNitroPreset } from "nitropack/kit";
import { writeAmplifyFiles } from "./utils.mjs";
const awsAmplify = defineNitroPreset(
{
extends: "node-server",
entry: "./runtime/aws-amplify",
output: {
dir: "{{ rootDir }}/.amplify-hosting",
serverDir: "{{ output.dir }}/compute/default",
publicDir: "{{ output.dir }}/static{{ baseURL }}"
},
commands: {
preview: "node {{ output.serverDir }}/server.js"
},
hooks: {
async compiled(nitro) {
await writeAmplifyFiles(nitro);
}
}
},
{
name: "aws-amplify",
stdName: "aws_amplify",
url: import.meta.url
}
);
export default [awsAmplify];

View File

@@ -0,0 +1 @@
import "#nitro-internal-pollyfills";

View File

@@ -0,0 +1,13 @@
import "#nitro-internal-pollyfills";
import { useNitroApp } from "nitropack/runtime";
import { Server } from "node:http";
import { toNodeListener } from "h3";
const nitroApp = useNitroApp();
const server = new Server(toNodeListener(nitroApp.h3App));
server.listen(3e3, (err) => {
if (err) {
console.error(err);
} else {
console.log(`Listening on http://localhost:3000 (AWS Amplify Hosting)`);
}
});

View File

@@ -0,0 +1,142 @@
export interface AmplifyComputeConfig {
/**
* The name property dictates the name of the provisioned compute resource. It is also the name
* of the sub-directory in the `compute` folder in the deployment bundle.
*/
name: string;
/**
* The runtime property dictates the runtime of the provisioned compute resource.
* Values are subset of https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html
*/
runtime: "nodejs16.x" | "nodejs18.x" | "nodejs20.x";
/**
* Specifies the starting file from which code will run for the given compute resource.
* The specified file should exist inside the given sub-directory that represents a compute resource.
*
* @example `"entrypoint.js"`
*/
entrypoint: string;
}
export type AmplifyRouteTarget = {
kind: "Static";
cacheControl?: string;
} | {
kind: "ImageOptimization";
cacheControl?: string;
} | {
kind: "Compute";
/**
* A string that indicates the name of the sub-directory in the given deployment bundle that
* contains the primitive's executable code. Valid and required only for the Compute primitive.
* The value here should point to one of the compute resources present in the given
* deployment bundle. The only supported value for this field is default.
*/
src: string;
};
export type AmplifyRoute = {
/**
* The path defines a glob pattern that matches incoming request paths (excluding querystring).
* The first match in a given list of rules determines which routing rule is applied to the incoming request.
* Only the following wildcard characters are supported as far as pattern matching is concerned: `*` (matches 0 or more characters)
*
* _Note_: The "/*" pattern is called a catch-all pattern and will match all incoming requests.
* It is special because fallback routing is only supported for catch-all routes.
*
*/
path: string;
/**
* An object that dictates the target to route the matched request to.
*/
target: AmplifyRouteTarget;
/** An object that dictates the target to fallback to if the original target returns a 404. */
fallback?: AmplifyRouteTarget;
};
export type AmplifyImageSettings = {
/** Array of supported image widths */
sizes: number[];
/**
* Array of allowed external domains that can use Image Optimization.
* Leave empty for only allowing the deployment domain to use Image Optimization.
*/
domains: string[];
/**
* Array of allowed external patterns that can use Image Optimization.
* Similar to `domains` but provides more control with RegExp.
*/
remotePatterns: {
/** The protocol of the allowed remote pattern. Can be `http` or `https`. */
protocol?: "http" | "https";
/**
* The hostname of the allowed remote pattern.
* Can be literal or wildcard. Single `*` matches a single subdomain.
* Double `**` matches any number of subdomains.
* We will disallow blanket wildcards of `**` with nothing else.
*/
hostname: string;
/** The port of the allowed remote pattern. */
port?: string;
/** The pathname of the allowed remote pattern. */
pathname?: string;
}[];
/** Array of allowed output image formats. */
formats: ("image/avif" | "image/webp" | "image/gif" | "image/png" | "image/jpeg")[];
/** Cache duration (in seconds) for the optimized images. */
minimumCacheTTL: number;
/** Allow SVG input image URLs. This is disabled by default for security purposes. */
dangerouslyAllowSVG: boolean;
};
export interface AmplifyDeployManifest {
/** The `version` property dictates the version of the Deployment Specification that has been implemented */
version: 1;
/**
* The routes property allows framework authors to leverage the routing rules primitive.
* Routing rules provide a mechanism by which incoming request paths can be routed to a specific target
* in the deployment bundle. Routing rules only dictate the destination of an incoming request and they are
* applied after rewrite/redirect rules have already transformed the request.
*
* Limits for routing rules:
* - A limit of 25 rules will be enforced on the routes array
*/
routes?: AmplifyRoute[];
/**
* The imageSettings property allows framework authors to customize the behavior of the image optimization primitive,
* which provides on-demand optimization of images at runtime.
*/
imageSettings?: AmplifyImageSettings;
/**
* Metadata about the provisioned compute resource(s). Each item in the array is an object that contains metadata
* about that compute resource.
*
* For example, given the following directory structure:
* ```
* .amplify
* └── compute
* └── default
* └── index.js
* ```
* The `computeResources` property would look like:
* ```
* [
* {
* name: 'default',
* runtime: 'nodejs16.x',
* entrypoint: 'index.js',
* }
* ]
* ```
*/
computeResources?: AmplifyComputeConfig[];
framework: {
name: string;
version: string;
};
}
export interface AWSAmplifyOptions {
catchAllStaticFallback?: boolean;
imageOptimization?: {
path?: string;
cacheControl?: string;
};
imageSettings?: AmplifyImageSettings;
runtime?: "nodejs16.x" | "nodejs18.x" | "nodejs20.x";
}

View File

View File

@@ -0,0 +1,2 @@
import type { Nitro } from "nitropack/types";
export declare function writeAmplifyFiles(nitro: Nitro): Promise<void>;

View File

@@ -0,0 +1,82 @@
import { writeFile } from "node:fs/promises";
import { resolve } from "node:path";
import { joinURL } from "ufo";
export async function writeAmplifyFiles(nitro) {
const outDir = nitro.options.output.dir;
const routes = [];
let hasWildcardPublicAsset = false;
if (nitro.options.awsAmplify?.imageOptimization && !nitro.options.static) {
const { path, cacheControl } = nitro.options.awsAmplify?.imageOptimization || {};
if (path) {
routes.push({
path,
target: {
kind: "ImageOptimization",
cacheControl
}
});
}
}
const computeTarget = nitro.options.static ? { kind: "Static" } : { kind: "Compute", src: "default" };
for (const publicAsset of nitro.options.publicAssets) {
if (!publicAsset.baseURL || publicAsset.baseURL === "/") {
hasWildcardPublicAsset = true;
continue;
}
routes.push({
path: `${publicAsset.baseURL.replace(/\/$/, "")}/*`,
target: {
kind: "Static",
cacheControl: publicAsset.maxAge > 0 ? `public, max-age=${publicAsset.maxAge}, immutable` : void 0
},
fallback: publicAsset.fallthrough ? computeTarget : void 0
});
}
if (hasWildcardPublicAsset && !nitro.options.static) {
routes.push({
path: "/*.*",
target: {
kind: "Static"
},
fallback: computeTarget
});
}
routes.push({
path: "/*",
target: computeTarget,
fallback: hasWildcardPublicAsset && nitro.options.awsAmplify?.catchAllStaticFallback ? {
kind: "Static"
} : void 0
});
for (const route of routes) {
if (route.path !== "/*") {
route.path = joinURL(nitro.options.baseURL, route.path);
}
}
const deployManifest = {
version: 1,
routes,
imageSettings: nitro.options.awsAmplify?.imageSettings || void 0,
computeResources: nitro.options.static ? void 0 : [
{
name: "default",
entrypoint: "server.js",
runtime: nitro.options.awsAmplify?.runtime || "nodejs20.x"
}
],
framework: {
name: nitro.options.framework.name || "nitro",
version: nitro.options.framework.version || "0.0.0"
}
};
await writeFile(
resolve(outDir, "deploy-manifest.json"),
JSON.stringify(deployManifest, null, 2)
);
if (!nitro.options.static) {
await writeFile(
resolve(outDir, "compute/default/server.js"),
`import("./index.mjs")`
);
}
}

View File

@@ -0,0 +1,3 @@
export type { AwsLambdaOptions as PresetOptions } from "./types";
declare const _default: readonly [any];
export default _default;

View File

@@ -0,0 +1,21 @@
import { defineNitroPreset } from "nitropack/kit";
const awsLambda = defineNitroPreset(
{
entry: "./runtime/aws-lambda",
awsLambda: {
streaming: false
},
hooks: {
"rollup:before": (nitro, rollupConfig) => {
if (nitro.options.awsLambda?.streaming) {
rollupConfig.input += "-streaming";
}
}
}
},
{
name: "aws-lambda",
url: import.meta.url
}
);
export default [awsLambda];

View File

@@ -0,0 +1,3 @@
import type { APIGatewayProxyEventV2 } from "aws-lambda";
import "#nitro-internal-pollyfills";
export declare const handler: import("aws-lambda").StreamifyHandler<APIGatewayProxyEventV2, void>;

View File

@@ -0,0 +1,72 @@
import "#nitro-internal-pollyfills";
import { useNitroApp } from "nitropack/runtime";
import {
normalizeCookieHeader,
normalizeLambdaIncomingHeaders,
normalizeLambdaOutgoingHeaders
} from "nitropack/runtime/internal";
import { withQuery } from "ufo";
const nitroApp = useNitroApp();
export const handler = awslambda.streamifyResponse(
async (event, responseStream, context) => {
const query = {
...event.queryStringParameters
};
const url = withQuery(event.rawPath, query);
const method = event.requestContext?.http?.method || "get";
if ("cookies" in event && event.cookies) {
event.headers.cookie = event.cookies.join(";");
}
const r = await nitroApp.localCall({
event,
url,
context,
headers: normalizeLambdaIncomingHeaders(event.headers),
method,
query,
body: event.isBase64Encoded ? Buffer.from(event.body || "", "base64").toString("utf8") : event.body
});
const isApiGwV2 = "cookies" in event || "rawPath" in event;
const cookies = normalizeCookieHeader(r.headers["set-cookie"]);
const httpResponseMetadata = {
statusCode: r.status,
...cookies.length > 0 && {
...isApiGwV2 ? { cookies } : { multiValueHeaders: { "set-cookie": cookies } }
},
headers: {
...normalizeLambdaOutgoingHeaders(r.headers, true),
"Transfer-Encoding": "chunked"
}
};
const body = r.body ?? new ReadableStream({
start(controller) {
controller.enqueue("");
controller.close();
}
});
const writer = awslambda.HttpResponseStream.from(
// @ts-ignore TODO: IMPORTANT! It should be a Writable according to the aws-lambda types
responseStream,
httpResponseMetadata
);
if (!body.getReader) {
writer.write(
r.body
/* TODO */
);
writer.end();
return;
}
const reader = body.getReader();
await streamToNodeStream(reader, responseStream);
writer.end();
}
);
async function streamToNodeStream(reader, writer) {
let readResult = await reader.read();
while (!readResult.done) {
writer.write(readResult.value);
readResult = await reader.read();
}
writer.end();
}

View File

@@ -0,0 +1,4 @@
import type { APIGatewayProxyEvent, APIGatewayProxyEventV2, APIGatewayProxyResult, APIGatewayProxyResultV2, Context } from "aws-lambda";
import "#nitro-internal-pollyfills";
export declare function handler(event: APIGatewayProxyEvent, context: Context): Promise<APIGatewayProxyResult>;
export declare function handler(event: APIGatewayProxyEventV2, context: Context): Promise<APIGatewayProxyResultV2>;

View File

@@ -0,0 +1,45 @@
import "#nitro-internal-pollyfills";
import { useNitroApp } from "nitropack/runtime";
import {
normalizeCookieHeader,
normalizeLambdaIncomingHeaders,
normalizeLambdaOutgoingBody,
normalizeLambdaOutgoingHeaders
} from "nitropack/runtime/internal";
import { withQuery } from "ufo";
const nitroApp = useNitroApp();
export async function handler(event, context) {
const query = {
...event.queryStringParameters,
...event.multiValueQueryStringParameters
};
const url = withQuery(
event.path || event.rawPath,
query
);
const method = event.httpMethod || event.requestContext?.http?.method || "get";
if ("cookies" in event && event.cookies) {
event.headers.cookie = event.cookies.join(";");
}
const r = await nitroApp.localCall({
event,
url,
context,
headers: normalizeLambdaIncomingHeaders(event.headers),
method,
query,
body: event.isBase64Encoded ? Buffer.from(event.body || "", "base64").toString("utf8") : event.body
});
const isApiGwV2 = "cookies" in event || "rawPath" in event;
const awsBody = await normalizeLambdaOutgoingBody(r.body, r.headers);
const cookies = normalizeCookieHeader(r.headers["set-cookie"]);
return {
...cookies.length > 0 && {
...isApiGwV2 ? { cookies } : { multiValueHeaders: { "set-cookie": cookies } }
},
statusCode: r.status,
headers: normalizeLambdaOutgoingHeaders(r.headers, true),
body: awsBody.body,
isBase64Encoded: awsBody.type === "binary"
};
}

View File

@@ -0,0 +1,3 @@
export interface AwsLambdaOptions {
streaming?: boolean;
}

View File

View File

@@ -0,0 +1,3 @@
export type { AzureOptions as PresetOptions } from "./types";
declare const _default: readonly [any, any];
export default _default;

44
node_modules/nitropack/dist/presets/azure/preset.mjs generated vendored Normal file
View File

@@ -0,0 +1,44 @@
import { defineNitroPreset } from "nitropack/kit";
import { writeFunctionsRoutes, writeSWARoutes } from "./utils.mjs";
const azure = defineNitroPreset(
{
entry: "./runtime/azure-swa",
output: {
serverDir: "{{ output.dir }}/server/functions",
publicDir: "{{ output.dir }}/public/{{ baseURL }}"
},
commands: {
preview: "npx @azure/static-web-apps-cli start {{ output.publicDir }} --api-location {{ output.serverDir }}"
},
hooks: {
async compiled(ctx) {
await writeSWARoutes(ctx);
}
}
},
{
name: "azure-swa",
aliases: ["azure"],
stdName: "azure_static",
url: import.meta.url
}
);
const azureFunctions = defineNitroPreset(
{
serveStatic: true,
entry: "./runtime/azure-functions",
commands: {
deploy: "az functionapp deployment source config-zip -g <resource-group> -n <app-name> --src {{ output.dir }}/deploy.zip"
},
hooks: {
async compiled(ctx) {
await writeFunctionsRoutes(ctx);
}
}
},
{
name: "azure-functions",
url: import.meta.url
}
);
export default [azure, azureFunctions];

View File

@@ -0,0 +1,5 @@
import "#nitro-internal-pollyfills";
import type { HttpRequest, HttpResponse } from "@azure/functions";
export declare function handle(context: {
res: HttpResponse;
}, req: HttpRequest): Promise<void>;

View File

@@ -0,0 +1,24 @@
import "#nitro-internal-pollyfills";
import { useNitroApp } from "nitropack/runtime";
import {
getAzureParsedCookiesFromHeaders,
normalizeLambdaOutgoingHeaders
} from "nitropack/runtime/internal";
const nitroApp = useNitroApp();
export async function handle(context, req) {
const url = "/" + (req.params.url || "");
const { body, status, statusText, headers } = await nitroApp.localCall({
url,
headers: req.headers,
method: req.method || void 0,
// https://github.com/Azure/azure-functions-host/issues/293
body: req.rawBody
});
context.res = {
status,
// cookies https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-node?tabs=typescript%2Cwindows%2Cazure-cli&pivots=nodejs-model-v4#http-response
cookies: getAzureParsedCookiesFromHeaders(headers),
headers: normalizeLambdaOutgoingHeaders(headers, true),
body: body ?? statusText
};
}

View File

@@ -0,0 +1,5 @@
import "#nitro-internal-pollyfills";
import type { HttpRequest, HttpResponse } from "@azure/functions";
export declare function handle(context: {
res: HttpResponse;
}, req: HttpRequest): Promise<void>;

View File

@@ -0,0 +1,31 @@
import "#nitro-internal-pollyfills";
import { useNitroApp } from "nitropack/runtime";
import {
getAzureParsedCookiesFromHeaders,
normalizeLambdaOutgoingHeaders
} from "nitropack/runtime/internal";
import { parseURL } from "ufo";
const nitroApp = useNitroApp();
export async function handle(context, req) {
let url;
if (req.headers["x-ms-original-url"]) {
const parsedURL = parseURL(req.headers["x-ms-original-url"]);
url = parsedURL.pathname + parsedURL.search;
} else {
url = "/api/" + (req.params.url || "");
}
const { body, status, headers } = await nitroApp.localCall({
url,
headers: req.headers,
method: req.method || void 0,
// https://github.com/Azure/azure-functions-nodejs-worker/issues/294
// https://github.com/Azure/azure-functions-host/issues/293
body: req.bufferBody ?? req.rawBody
});
context.res = {
status,
cookies: getAzureParsedCookiesFromHeaders(headers),
headers: normalizeLambdaOutgoingHeaders(headers, true),
body
};
}

13
node_modules/nitropack/dist/presets/azure/types.d.ts generated vendored Normal file
View File

@@ -0,0 +1,13 @@
export interface AzureOptions {
config?: {
platform?: {
apiRuntime?: string;
[key: string]: unknown;
};
navigationFallback?: {
rewrite?: string;
[key: string]: unknown;
};
[key: string]: unknown;
};
}

0
node_modules/nitropack/dist/presets/azure/types.mjs generated vendored Normal file
View File

3
node_modules/nitropack/dist/presets/azure/utils.d.ts generated vendored Normal file
View File

@@ -0,0 +1,3 @@
import type { Nitro } from "nitropack/types";
export declare function writeFunctionsRoutes(nitro: Nitro): Promise<void>;
export declare function writeSWARoutes(nitro: Nitro): Promise<void>;

183
node_modules/nitropack/dist/presets/azure/utils.mjs generated vendored Normal file
View File

@@ -0,0 +1,183 @@
import { createWriteStream } from "node:fs";
import fsp from "node:fs/promises";
import archiver from "archiver";
import { writeFile } from "nitropack/kit";
import { join, resolve } from "pathe";
export async function writeFunctionsRoutes(nitro) {
const host = {
version: "2.0",
extensions: { http: { routePrefix: "" } }
};
const functionDefinition = {
entryPoint: "handle",
bindings: [
{
authLevel: "anonymous",
type: "httpTrigger",
direction: "in",
name: "req",
route: "{*url}",
methods: ["delete", "get", "head", "options", "patch", "post", "put"]
},
{
type: "http",
direction: "out",
name: "res"
}
]
};
await writeFile(
resolve(nitro.options.output.serverDir, "function.json"),
JSON.stringify(functionDefinition)
);
await writeFile(
resolve(nitro.options.output.dir, "host.json"),
JSON.stringify(host)
);
await _zipDirectory(
nitro.options.output.dir,
join(nitro.options.output.dir, "deploy.zip")
);
}
export async function writeSWARoutes(nitro) {
const host = {
version: "2.0"
};
const supportedNodeVersions = /* @__PURE__ */ new Set(["16", "18", "20"]);
let nodeVersion = "18";
try {
const currentNodeVersion = JSON.parse(
await fsp.readFile(join(nitro.options.rootDir, "package.json"), "utf8")
).engines.node;
if (supportedNodeVersions.has(currentNodeVersion)) {
nodeVersion = currentNodeVersion;
}
} catch {
const currentNodeVersion = process.versions.node.slice(0, 2);
if (supportedNodeVersions.has(currentNodeVersion)) {
nodeVersion = currentNodeVersion;
}
}
const config = {
...nitro.options.azure?.config,
// Overwrite routes for now, we will add existing routes after generating routes
routes: [],
platform: {
apiRuntime: `node:${nodeVersion}`,
...nitro.options.azure?.config?.platform
},
navigationFallback: {
rewrite: "/api/server",
...nitro.options.azure?.config?.navigationFallback
}
};
const routeFiles = nitro._prerenderedRoutes || [];
const indexFileExists = routeFiles.some(
(route) => route.fileName === "/index.html"
);
if (!indexFileExists) {
config.routes.unshift(
{
route: "/index.html",
redirect: "/"
},
{
route: "/",
rewrite: "/api/server"
}
);
}
const suffix = "/index.html".length;
for (const { fileName } of routeFiles) {
if (!fileName || !fileName.endsWith("/index.html")) {
continue;
}
config.routes.unshift({
route: fileName.slice(0, -suffix) || "/",
rewrite: fileName
});
}
for (const { fileName } of routeFiles) {
if (!fileName || !fileName.endsWith(".html") || fileName.endsWith("index.html")) {
continue;
}
const route = fileName.slice(0, -".html".length);
const existingRouteIndex = config.routes.findIndex(
(_route) => _route.route === route
);
if (existingRouteIndex !== -1) {
config.routes.splice(existingRouteIndex, 1);
}
config.routes.unshift({
route,
rewrite: fileName
});
}
if (nitro.options.azure?.config && "routes" in nitro.options.azure.config && Array.isArray(nitro.options.azure.config.routes)) {
for (const customRoute of nitro.options.azure.config.routes.reverse()) {
const existingRouteMatchIndex = config.routes.findIndex(
(value) => value.route === customRoute.route
);
if (existingRouteMatchIndex === -1) {
config.routes.unshift(customRoute);
} else {
config.routes[existingRouteMatchIndex] = customRoute;
}
}
}
const functionDefinition = {
entryPoint: "handle",
bindings: [
{
authLevel: "anonymous",
type: "httpTrigger",
direction: "in",
name: "req",
route: "{*url}",
methods: ["delete", "get", "head", "options", "patch", "post", "put"]
},
{
type: "http",
direction: "out",
name: "res"
}
]
};
await writeFile(
resolve(nitro.options.output.serverDir, "function.json"),
JSON.stringify(functionDefinition, null, 2)
);
await writeFile(
resolve(nitro.options.output.serverDir, "../host.json"),
JSON.stringify(host, null, 2)
);
const stubPackageJson = resolve(
nitro.options.output.serverDir,
"../package.json"
);
await writeFile(stubPackageJson, JSON.stringify({ private: true }));
await writeFile(
resolve(nitro.options.rootDir, "staticwebapp.config.json"),
JSON.stringify(config, null, 2)
);
if (!indexFileExists) {
const baseURLSegments = nitro.options.baseURL.split("/").filter(Boolean);
const relativePrefix = baseURLSegments.map(() => "..").join("/");
await writeFile(
resolve(
nitro.options.output.publicDir,
relativePrefix ? `${relativePrefix}/index.html` : "index.html"
),
""
);
}
}
function _zipDirectory(dir, outfile) {
const archive = archiver("zip", { zlib: { level: 9 } });
const stream = createWriteStream(outfile);
return new Promise((resolve2, reject) => {
archive.glob("**/*", { cwd: dir, nodir: true, dot: true, follow: true }).on("error", (err) => reject(err)).pipe(stream);
stream.on("close", () => resolve2(void 0));
archive.finalize();
});
}

2
node_modules/nitropack/dist/presets/bun/preset.d.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
declare const _default: readonly [any];
export default _default;

17
node_modules/nitropack/dist/presets/bun/preset.mjs generated vendored Normal file
View File

@@ -0,0 +1,17 @@
import { defineNitroPreset } from "nitropack/kit";
const bun = defineNitroPreset(
{
extends: "node-server",
entry: "./runtime/bun",
// https://bun.sh/docs/runtime/modules#resolution
exportConditions: ["bun", "worker", "node", "import", "default"],
commands: {
preview: "bun run {{ output.serverDir }}/index.mjs"
}
},
{
name: "bun",
url: import.meta.url
}
);
export default [bun];

View File

@@ -0,0 +1 @@
import "#nitro-internal-pollyfills";

View File

@@ -0,0 +1,34 @@
import "#nitro-internal-pollyfills";
import { useNitroApp } from "nitropack/runtime";
import { startScheduleRunner } from "nitropack/runtime/internal";
import wsAdapter from "crossws/adapters/bun";
const nitroApp = useNitroApp();
const ws = import.meta._websocket ? wsAdapter(nitroApp.h3App.websocket) : void 0;
const server = Bun.serve({
port: process.env.NITRO_PORT || process.env.PORT || 3e3,
host: process.env.NITRO_HOST || process.env.HOST,
idleTimeout: Number.parseInt(process.env.NITRO_BUN_IDLE_TIMEOUT) || void 0,
websocket: import.meta._websocket ? ws.websocket : void 0,
async fetch(req, server2) {
if (import.meta._websocket && req.headers.get("upgrade") === "websocket") {
return ws.handleUpgrade(req, server2);
}
const url = new URL(req.url);
let body;
if (req.body) {
body = await req.arrayBuffer();
}
return nitroApp.localFetch(url.pathname + url.search, {
host: url.hostname,
protocol: url.protocol,
headers: req.headers,
method: req.method,
redirect: req.redirect,
body
});
}
});
console.log(`Listening on ${server.url}...`);
if (import.meta._tasks) {
startScheduleRunner();
}

View File

@@ -0,0 +1,2 @@
declare const _default: readonly [any];
export default _default;

12
node_modules/nitropack/dist/presets/cleavr/preset.mjs generated vendored Normal file
View File

@@ -0,0 +1,12 @@
import { defineNitroPreset } from "nitropack/kit";
const cleavr = defineNitroPreset(
{
extends: "node-server"
},
{
name: "cleavr",
stdName: "cleavr",
url: import.meta.url
}
);
export default [cleavr];

View File

@@ -0,0 +1,2 @@
import type { Nitro } from "nitropack";
export declare function cloudflareDev(nitro: Nitro): Promise<void>;

64
node_modules/nitropack/dist/presets/cloudflare/dev.mjs generated vendored Normal file
View File

@@ -0,0 +1,64 @@
import { resolve } from "node:path";
import { promises as fs } from "node:fs";
import { fileURLToPath } from "mlly";
import { findFile } from "pkg-types";
import { resolveModulePath } from "exsolve";
export async function cloudflareDev(nitro) {
if (!nitro.options.dev) {
return;
}
const wranglerPath = await resolveModulePath("wrangler", {
from: nitro.options.nodeModulesDirs,
try: true
});
if (!wranglerPath) {
nitro.logger.warn(
"Wrangler is not installed. Please install it using `npx nypm i wrangler` to enable dev emulation."
);
return;
}
const config = {
// compatibility with legacy nitro-cloudflare-dev module
...nitro.options.cloudflareDev,
...nitro.options.cloudflare?.dev
};
let configPath = config.configPath;
if (!configPath) {
configPath = await findFile(
["wrangler.json", "wrangler.jsonc", "wrangler.toml"],
{
startingFrom: nitro.options.srcDir
}
).catch(() => void 0);
}
const persistDir = resolve(
nitro.options.rootDir,
config.persistDir || ".wrangler/state/v3"
);
const gitIgnorePath = await findFile(".gitignore", {
startingFrom: nitro.options.rootDir
}).catch(() => void 0);
let addedToGitIgnore = false;
if (gitIgnorePath && persistDir === ".wrangler/state/v3") {
const gitIgnore = await fs.readFile(gitIgnorePath, "utf8");
if (!gitIgnore.includes(".wrangler/state/v3")) {
await fs.writeFile(gitIgnorePath, gitIgnore + "\n.wrangler/state/v3\n").catch(() => {
});
addedToGitIgnore = true;
}
}
nitro.options.runtimeConfig.wrangler = {
...nitro.options.runtimeConfig.wrangler,
configPath,
persistDir,
environment: config.environment
};
nitro.options.externals.inline = nitro.options.externals.inline || [];
nitro.options.externals.inline.push(
fileURLToPath(new URL("runtime/", import.meta.url))
);
nitro.options.plugins = nitro.options.plugins || [];
nitro.options.plugins.unshift(
fileURLToPath(new URL("runtime/plugin.dev", import.meta.url))
);
}

View File

@@ -0,0 +1,3 @@
export type { CloudflareOptions as PresetOptions } from "./types";
declare const _default: any[];
export default _default;

View File

@@ -0,0 +1,75 @@
import { defineNitroPreset } from "nitropack/kit";
import { writeFile } from "nitropack/kit";
import { resolve } from "pathe";
const cloudflare = defineNitroPreset(
{
extends: "base-worker",
entry: "./runtime/cloudflare-worker",
exportConditions: ["workerd"],
commands: {
preview: "npx wrangler dev {{ output.serverDir }}/index.mjs --site {{ output.publicDir }}",
deploy: "npx wrangler deploy"
},
wasm: {
lazy: true
},
hooks: {
async compiled(nitro) {
await writeFile(
resolve(nitro.options.output.dir, "package.json"),
JSON.stringify({ private: true, main: "./server/index.mjs" }, null, 2)
);
await writeFile(
resolve(nitro.options.output.dir, "package-lock.json"),
JSON.stringify({ lockfileVersion: 1 }, null, 2)
);
}
}
},
{
name: "cloudflare-worker",
aliases: ["cloudflare"],
url: import.meta.url
}
);
const cloudflareModuleLegacy = defineNitroPreset(
{
extends: "base-worker",
entry: "./runtime/cloudflare-module-legacy",
exportConditions: ["workerd"],
commands: {
preview: "npx wrangler dev {{ output.serverDir }}/index.mjs --site {{ output.publicDir }}",
deploy: "npx wrangler deploy"
},
rollupConfig: {
external: "__STATIC_CONTENT_MANIFEST",
output: {
format: "esm",
exports: "named",
inlineDynamicImports: false
}
},
wasm: {
lazy: false,
esmImport: true
},
hooks: {
async compiled(nitro) {
await writeFile(
resolve(nitro.options.output.dir, "package.json"),
JSON.stringify({ private: true, main: "./server/index.mjs" }, null, 2)
);
await writeFile(
resolve(nitro.options.output.dir, "package-lock.json"),
JSON.stringify({ lockfileVersion: 1 }, null, 2)
);
}
}
},
{
name: "cloudflare-module-legacy",
aliases: ["cloudflare-module"],
url: import.meta.url
}
);
export default [cloudflare, cloudflareModuleLegacy];

View File

@@ -0,0 +1,4 @@
export type { CloudflareOptions as PresetOptions } from "./types";
export declare const cloudflareDev: any;
declare const _default: any[];
export default _default;

View File

@@ -0,0 +1,196 @@
import { defineNitroPreset } from "nitropack/kit";
import { writeFile } from "nitropack/kit";
import { resolve } from "pathe";
import { unenvCfExternals } from "../_unenv/preset-workerd.mjs";
import {
enableNodeCompat,
writeWranglerConfig,
writeCFRoutes,
writeCFHeaders,
writeCFPagesRedirects
} from "./utils.mjs";
import cfLegacyPresets from "./preset-legacy.mjs";
const cloudflarePages = defineNitroPreset(
{
extends: "cloudflare",
entry: "./runtime/cloudflare-pages",
exportConditions: ["workerd"],
commands: {
preview: "npx wrangler --cwd {{ output.dir }} pages dev",
deploy: "npx wrangler --cwd {{ output.dir }} pages deploy"
},
output: {
dir: "{{ rootDir }}/dist",
publicDir: "{{ output.dir }}/{{ baseURL }}",
serverDir: "{{ output.dir }}/_worker.js"
},
unenv: [unenvCfExternals],
alias: {
// Hotfix: Cloudflare appends /index.html if mime is not found and things like ico are not in standard lite.js!
// https://github.com/nitrojs/nitro/pull/933
_mime: "mime/index.js"
},
wasm: {
lazy: false,
esmImport: true
},
rollupConfig: {
output: {
entryFileNames: "index.js",
format: "esm",
inlineDynamicImports: false
}
},
hooks: {
"build:before": async (nitro) => {
await enableNodeCompat(nitro);
if (!nitro.options.cloudflare?.deployConfig) {
nitro.options.commands.preview = "npx wrangler pages dev {{ output.dir }}";
nitro.options.commands.deploy = "npx wrangler pages deploy {{ output.dir }}";
}
},
async compiled(nitro) {
await writeWranglerConfig(nitro, "pages");
await writeCFRoutes(nitro);
await writeCFHeaders(nitro, "output");
await writeCFPagesRedirects(nitro);
}
}
},
{
name: "cloudflare-pages",
stdName: "cloudflare_pages",
url: import.meta.url
}
);
const cloudflarePagesStatic = defineNitroPreset(
{
extends: "static",
output: {
dir: "{{ rootDir }}/dist",
publicDir: "{{ output.dir }}/{{ baseURL }}"
},
commands: {
preview: "npx wrangler --cwd {{ output.dir }} pages dev",
deploy: "npx wrangler --cwd {{ output.dir }} pages deploy"
},
hooks: {
"build:before": async (nitro) => {
if (!nitro.options.cloudflare?.deployConfig) {
nitro.options.commands.preview = "npx wrangler pages dev {{ output.dir }}";
nitro.options.commands.deploy = "npx wrangler pages deploy {{ output.dir }}";
}
},
async compiled(nitro) {
await writeCFHeaders(nitro, "output");
await writeCFPagesRedirects(nitro);
}
}
},
{
name: "cloudflare-pages-static",
stdName: "cloudflare_pages",
url: import.meta.url,
static: true
}
);
export const cloudflareDev = defineNitroPreset(
{
extends: "nitro-dev",
modules: [
async (nitro) => await import("./dev.mjs").then((m) => m.cloudflareDev(nitro))
],
esbuild: {
options: {
target: "es2022"
}
},
unenv: {
meta: {
name: "cloudflare-dev"
},
alias: {
"cloudflare:workers": "nitropack/presets/cloudflare/runtime/shims/workers.dev"
}
}
},
{
name: "cloudflare-dev",
aliases: ["cloudflare-module", "cloudflare-durable", "cloudflare-pages"],
compatibilityDate: "2025-07-15",
url: import.meta.url,
dev: true
}
);
const cloudflareModule = defineNitroPreset(
{
extends: "base-worker",
entry: "./runtime/cloudflare-module",
output: {
publicDir: "{{ output.dir }}/public/{{ baseURL }}"
},
exportConditions: ["workerd"],
commands: {
preview: "npx wrangler --cwd {{ output.dir }} dev",
deploy: "npx wrangler --cwd {{ output.dir }} deploy"
},
unenv: [unenvCfExternals],
rollupConfig: {
output: {
format: "esm",
exports: "named",
inlineDynamicImports: false
}
},
wasm: {
lazy: false,
esmImport: true
},
hooks: {
"build:before": async (nitro) => {
await enableNodeCompat(nitro);
if (!nitro.options.cloudflare?.deployConfig) {
nitro.options.commands.preview = "npx wrangler dev {{ output.serverDir }}/index.mjs --assets {{ output.publicDir }}";
nitro.options.commands.deploy = "npx wrangler deploy {{ output.serverDir }}/index.mjs --assets {{ output.publicDir }}";
}
},
async compiled(nitro) {
await writeWranglerConfig(nitro, "module");
await writeCFHeaders(nitro, "public");
await writeFile(
resolve(nitro.options.output.dir, "package.json"),
JSON.stringify({ private: true, main: "./server/index.mjs" }, null, 2)
);
await writeFile(
resolve(nitro.options.output.dir, "package-lock.json"),
JSON.stringify({ lockfileVersion: 1 }, null, 2)
);
}
}
},
{
name: "cloudflare-module",
stdName: "cloudflare_workers",
compatibilityDate: "2024-09-19",
url: import.meta.url
}
);
const cloudflareDurable = defineNitroPreset(
{
extends: "cloudflare-module",
entry: "./runtime/cloudflare-durable"
},
{
name: "cloudflare-durable",
compatibilityDate: "2024-09-19",
url: import.meta.url
}
);
export default [
...cfLegacyPresets,
cloudflarePages,
cloudflarePagesStatic,
cloudflareModule,
cloudflareDurable,
cloudflareDev
];

View File

@@ -0,0 +1,13 @@
import "#nitro-internal-pollyfills";
import type * as CF from "@cloudflare/workers-types";
import type { ExportedHandler } from "@cloudflare/workers-types";
type MaybePromise<T> = T | Promise<T>;
export declare function createHandler<Env>(hooks: {
fetch: (...params: [
...Parameters<NonNullable<ExportedHandler<Env>["fetch"]>>,
url: URL,
cfContextExtras: any
]) => MaybePromise<Response | CF.Response | undefined>;
}): ExportedHandler<Env>;
export declare function fetchHandler(request: Request | CF.Request, env: unknown, context: CF.ExecutionContext | DurableObjectState, url: URL | undefined, nitroApp: any, ctxExt: any): Promise<Response>;
export {};

View File

@@ -0,0 +1,112 @@
import "#nitro-internal-pollyfills";
import { useNitroApp } from "nitropack/runtime";
import { requestHasBody, runCronTasks } from "nitropack/runtime/internal";
export function createHandler(hooks) {
const nitroApp = useNitroApp();
return {
async fetch(request, env, context) {
const ctxExt = {};
const url = new URL(request.url);
if (hooks.fetch) {
const res = await hooks.fetch(request, env, context, url, ctxExt);
if (res) {
return res;
}
}
return fetchHandler(request, env, context, url, nitroApp, ctxExt);
},
scheduled(controller, env, context) {
globalThis.__env__ = env;
context.waitUntil(
nitroApp.hooks.callHook("cloudflare:scheduled", {
controller,
env,
context
})
);
if (import.meta._tasks) {
context.waitUntil(
runCronTasks(controller.cron, {
context: {
cloudflare: {
env,
context
}
},
payload: {}
})
);
}
},
email(message, env, context) {
globalThis.__env__ = env;
context.waitUntil(
nitroApp.hooks.callHook("cloudflare:email", {
message,
event: message,
// backward compat
env,
context
})
);
},
queue(batch, env, context) {
globalThis.__env__ = env;
context.waitUntil(
nitroApp.hooks.callHook("cloudflare:queue", {
batch,
event: batch,
env,
context
})
);
},
tail(traces, env, context) {
globalThis.__env__ = env;
context.waitUntil(
nitroApp.hooks.callHook("cloudflare:tail", {
traces,
env,
context
})
);
},
trace(traces, env, context) {
globalThis.__env__ = env;
context.waitUntil(
nitroApp.hooks.callHook("cloudflare:trace", {
traces,
env,
context
})
);
}
};
}
export async function fetchHandler(request, env, context, url = new URL(request.url), nitroApp = useNitroApp(), ctxExt) {
let body;
if (requestHasBody(request)) {
body = Buffer.from(await request.arrayBuffer());
}
globalThis.__env__ = env;
return nitroApp.localFetch(url.pathname + url.search, {
context: {
waitUntil: (promise) => context.waitUntil(promise),
_platform: {
cf: request.cf,
cloudflare: {
request,
env,
context,
url,
...ctxExt
}
}
},
host: url.hostname,
protocol: url.protocol,
method: request.method,
headers: request.headers,
body
});
}

View File

@@ -0,0 +1,20 @@
import "#nitro-internal-pollyfills";
import type * as CF from "@cloudflare/workers-types";
import { DurableObject } from "cloudflare:workers";
declare const DURABLE_BINDING = "$DurableObject";
interface Env {
ASSETS?: {
fetch: typeof CF.fetch;
};
[DURABLE_BINDING]?: CF.DurableObjectNamespace;
}
declare const _default: CF.ExportedHandler<Env, unknown, unknown>;
export default _default;
export declare class $DurableObject extends DurableObject {
constructor(state: DurableObjectState, env: Record<string, any>);
fetch(request: Request): Promise<Response>;
publish(topic: string, data: unknown, opts: any): void;
alarm(): void | Promise<void>;
webSocketMessage(client: WebSocket, message: ArrayBuffer | string): Promise<void>;
webSocketClose(client: WebSocket, code: number, reason: string, wasClean: boolean): Promise<void>;
}

View File

@@ -0,0 +1,82 @@
import "#nitro-internal-pollyfills";
import { DurableObject } from "cloudflare:workers";
import wsAdapter from "crossws/adapters/cloudflare-durable";
import { useNitroApp } from "nitropack/runtime";
import { isPublicAssetURL } from "#nitro-internal-virtual/public-assets";
import { createHandler, fetchHandler } from "./_module-handler.mjs";
const DURABLE_BINDING = "$DurableObject";
const DURABLE_INSTANCE = "server";
const nitroApp = useNitroApp();
const getDurableStub = (env) => {
const binding = env[DURABLE_BINDING];
if (!binding) {
throw new Error(
`Durable Object binding "${DURABLE_BINDING}" not available.`
);
}
const id = binding.idFromName(DURABLE_INSTANCE);
return binding.get(id);
};
const ws = import.meta._websocket ? wsAdapter({
...nitroApp.h3App.websocket,
instanceName: DURABLE_INSTANCE,
bindingName: DURABLE_BINDING
}) : void 0;
export default createHandler({
fetch(request, env, context, url, ctxExt) {
if (env.ASSETS && isPublicAssetURL(url.pathname)) {
return env.ASSETS.fetch(request);
}
ctxExt.durableFetch = (req = request) => getDurableStub(env).fetch(req);
if (import.meta._websocket && request.headers.get("upgrade") === "websocket") {
return ws.handleUpgrade(request, env, context);
}
}
});
export class $DurableObject extends DurableObject {
constructor(state, env) {
super(state, env);
state.waitUntil(
nitroApp.hooks.callHook("cloudflare:durable:init", this, {
state,
env
})
);
if (import.meta._websocket) {
ws.handleDurableInit(this, state, env);
}
}
fetch(request) {
globalThis.__env__ = this.env;
if (import.meta._websocket && request.headers.get("upgrade") === "websocket") {
return ws.handleDurableUpgrade(this, request);
}
const url = new URL(request.url);
return fetchHandler(request, this.env, this.ctx, url, nitroApp, {
durable: this
});
}
publish(topic, data, opts) {
if (!ws) {
throw new Error("WebSocket not available");
}
return ws.publish(topic, data, opts);
}
alarm() {
this.ctx.waitUntil(
nitroApp.hooks.callHook("cloudflare:durable:alarm", this)
);
}
async webSocketMessage(client, message) {
globalThis.__env__ = this.env;
if (import.meta._websocket) {
return ws.handleDurableMessage(this, client, message);
}
}
async webSocketClose(client, code, reason, wasClean) {
globalThis.__env__ = this.env;
if (import.meta._websocket) {
return ws.handleDurableClose(this, client, code, reason, wasClean);
}
}
}

View File

@@ -0,0 +1,6 @@
import "#nitro-internal-pollyfills";
interface Env {
__STATIC_CONTENT?: any;
}
declare const _default: import("@cloudflare/workers-types").ExportedHandler<Env, unknown, unknown>;
export default _default;

View File

@@ -0,0 +1,52 @@
import "#nitro-internal-pollyfills";
import {
getAssetFromKV,
mapRequestToAsset
} from "@cloudflare/kv-asset-handler";
import wsAdapter from "crossws/adapters/cloudflare";
import { withoutBase } from "ufo";
import { useNitroApp, useRuntimeConfig } from "nitropack/runtime";
import { getPublicAssetMeta } from "#nitro-internal-virtual/public-assets";
import { createHandler } from "./_module-handler.mjs";
import manifest from "__STATIC_CONTENT_MANIFEST";
const nitroApp = useNitroApp();
const ws = import.meta._websocket ? wsAdapter(nitroApp.h3App.websocket) : void 0;
export default createHandler({
async fetch(request, env, context) {
if (import.meta._websocket && request.headers.get("upgrade") === "websocket") {
return ws.handleUpgrade(request, env, context);
}
try {
return await getAssetFromKV(
{
request,
waitUntil(promise) {
return context.waitUntil(promise);
}
},
{
cacheControl: assetsCacheControl,
mapRequestToAsset: baseURLModifier,
ASSET_NAMESPACE: env.__STATIC_CONTENT,
ASSET_MANIFEST: JSON.parse(manifest)
}
);
} catch {
}
}
});
function assetsCacheControl(_request) {
const url = new URL(_request.url);
const meta = getPublicAssetMeta(url.pathname);
if (meta.maxAge) {
return {
browserTTL: meta.maxAge,
edgeTTL: meta.maxAge
};
}
return {};
}
const baseURLModifier = (request) => {
const url = withoutBase(request.url, useRuntimeConfig().app.baseURL);
return mapRequestToAsset(new Request(url, request));
};

View File

@@ -0,0 +1,9 @@
import "#nitro-internal-pollyfills";
import type { fetch } from "@cloudflare/workers-types";
interface Env {
ASSETS?: {
fetch: typeof fetch;
};
}
declare const _default: import("@cloudflare/workers-types").ExportedHandler<Env, unknown, unknown>;
export default _default;

View File

@@ -0,0 +1,17 @@
import "#nitro-internal-pollyfills";
import wsAdapter from "crossws/adapters/cloudflare";
import { useNitroApp } from "nitropack/runtime";
import { isPublicAssetURL } from "#nitro-internal-virtual/public-assets";
import { createHandler } from "./_module-handler.mjs";
const nitroApp = useNitroApp();
const ws = import.meta._websocket ? wsAdapter(nitroApp.h3App.websocket) : void 0;
export default createHandler({
fetch(request, env, context, url) {
if (env.ASSETS && isPublicAssetURL(url.pathname)) {
return env.ASSETS.fetch(request);
}
if (import.meta._websocket && request.headers.get("upgrade") === "websocket") {
return ws.handleUpgrade(request, env, context);
}
}
});

View File

@@ -0,0 +1,20 @@
import "#nitro-internal-pollyfills";
import type { Request as CFRequest, EventContext, ExecutionContext } from "@cloudflare/workers-types";
/**
* Reference: https://developers.cloudflare.com/workers/runtime-apis/fetch-event/#parameters
*/
interface CFPagesEnv {
ASSETS: {
fetch: (request: CFRequest) => Promise<Response>;
};
CF_PAGES: "1";
CF_PAGES_BRANCH: string;
CF_PAGES_COMMIT_SHA: string;
CF_PAGES_URL: string;
[key: string]: any;
}
declare const _default: {
fetch(request: CFRequest, env: CFPagesEnv, context: EventContext<CFPagesEnv, string, any>): Promise<any>;
scheduled(event: any, env: CFPagesEnv, context: ExecutionContext): void;
};
export default _default;

View File

@@ -0,0 +1,61 @@
import "#nitro-internal-pollyfills";
import { useNitroApp } from "nitropack/runtime";
import { requestHasBody, runCronTasks } from "nitropack/runtime/internal";
import { isPublicAssetURL } from "#nitro-internal-virtual/public-assets";
import wsAdapter from "crossws/adapters/cloudflare";
const nitroApp = useNitroApp();
const ws = import.meta._websocket ? wsAdapter(nitroApp.h3App.websocket) : void 0;
export default {
async fetch(request, env, context) {
if (import.meta._websocket && request.headers.get("upgrade") === "websocket") {
return ws.handleUpgrade(
request,
env,
context
);
}
const url = new URL(request.url);
if (env.ASSETS && isPublicAssetURL(url.pathname)) {
return env.ASSETS.fetch(request);
}
let body;
if (requestHasBody(request)) {
body = Buffer.from(await request.arrayBuffer());
}
globalThis.__env__ = env;
return nitroApp.localFetch(url.pathname + url.search, {
context: {
waitUntil: (promise) => context.waitUntil(promise),
_platform: {
cf: request.cf,
cloudflare: {
request,
env,
context
}
}
},
host: url.hostname,
protocol: url.protocol,
method: request.method,
headers: request.headers,
body
});
},
scheduled(event, env, context) {
if (import.meta._tasks) {
globalThis.__env__ = env;
context.waitUntil(
runCronTasks(event.cron, {
context: {
cloudflare: {
env,
context
}
},
payload: {}
})
);
}
}
};

View File

@@ -0,0 +1 @@
import "#nitro-internal-pollyfills";

View File

@@ -0,0 +1,65 @@
import "#nitro-internal-pollyfills";
import { useNitroApp, useRuntimeConfig } from "nitropack/runtime";
import { requestHasBody } from "nitropack/runtime/internal";
import { getPublicAssetMeta } from "#nitro-internal-virtual/public-assets";
import {
getAssetFromKV,
mapRequestToAsset
} from "@cloudflare/kv-asset-handler";
import wsAdapter from "crossws/adapters/cloudflare";
import { withoutBase } from "ufo";
addEventListener("fetch", (event) => {
event.respondWith(handleEvent(event));
});
const nitroApp = useNitroApp();
const ws = import.meta._websocket ? wsAdapter(nitroApp.h3App.websocket) : void 0;
async function handleEvent(event) {
if (import.meta._websocket && event.request.headers.get("upgrade") === "websocket") {
return ws.handleUpgrade(event.request, {}, event);
}
try {
return await getAssetFromKV(event, {
cacheControl: assetsCacheControl,
mapRequestToAsset: baseURLModifier
});
} catch {
}
const url = new URL(event.request.url);
let body;
if (requestHasBody(event.request)) {
body = Buffer.from(await event.request.arrayBuffer());
}
return nitroApp.localFetch(url.pathname + url.search, {
context: {
waitUntil: (promise) => event.waitUntil(promise),
_platform: {
// https://developers.cloudflare.com/workers/runtime-apis/request#incomingrequestcfproperties
cf: event.request.cf,
cloudflare: {
event
}
}
},
host: url.hostname,
protocol: url.protocol,
headers: event.request.headers,
method: event.request.method,
redirect: event.request.redirect,
body
});
}
function assetsCacheControl(_request) {
const url = new URL(_request.url);
const meta = getPublicAssetMeta(url.pathname);
if (meta.maxAge) {
return {
browserTTL: meta.maxAge,
edgeTTL: meta.maxAge
};
}
return {};
}
const baseURLModifier = (request) => {
const url = withoutBase(request.url, useRuntimeConfig().app.baseURL);
return mapRequestToAsset(new Request(url, request));
};

View File

@@ -0,0 +1,3 @@
import type { NitroAppPlugin } from "nitropack";
declare const _default: NitroAppPlugin;
export default _default;

View File

@@ -0,0 +1,84 @@
import { useRuntimeConfig, getRequestURL } from "#imports";
const proxy = await _getPlatformProxy().catch((error) => {
console.error("Failed to initialize wrangler bindings proxy", error);
return _createStubProxy();
});
globalThis.__env__ = proxy.env;
globalThis.__wait_until__ = proxy.ctx.waitUntil.bind(proxy.ctx);
export default (function(nitroApp) {
nitroApp.hooks.hook("request", async (event) => {
event.context.cf = proxy.cf;
event.context.waitUntil = proxy.ctx.waitUntil.bind(proxy.ctx);
const request = new Request(getRequestURL(event));
request.cf = proxy.cf;
event.context.cloudflare = {
...event.context.cloudflare,
request,
env: proxy.env,
context: proxy.ctx
};
event.node.req.__unenv__ = {
...event.node.req.__unenv__,
waitUntil: event.context.waitUntil
};
});
nitroApp.hooks._hooks.request.unshift(nitroApp.hooks._hooks.request.pop());
nitroApp.hooks.hook("close", () => {
return proxy?.dispose();
});
});
async function _getPlatformProxy() {
const _pkg = "wrangler";
const { getPlatformProxy } = await import(_pkg).catch(() => {
throw new Error(
"Package `wrangler` not found, please install it with: `npx nypm@latest add -D wrangler`"
);
});
const runtimeConfig = useRuntimeConfig();
const proxyOptions = {
configPath: runtimeConfig.wrangler.configPath,
persist: { path: runtimeConfig.wrangler.persistDir }
};
if (runtimeConfig.wrangler.environment) {
proxyOptions.environment = runtimeConfig.wrangler.environment;
}
const proxy2 = await getPlatformProxy(proxyOptions);
return proxy2;
}
function _createStubProxy() {
return {
env: {},
cf: {},
ctx: {
waitUntil() {
},
passThroughOnException() {
},
props: {}
},
caches: {
open() {
const result = Promise.resolve(new _CacheStub());
return result;
},
get default() {
return new _CacheStub();
}
},
dispose: () => Promise.resolve()
};
}
class _CacheStub {
delete() {
const result = Promise.resolve(false);
return result;
}
match() {
const result = Promise.resolve(void 0);
return result;
}
put() {
const result = Promise.resolve();
return result;
}
}

View File

@@ -0,0 +1,21 @@
export function waitUntil(promise: any): Promise<void>;
export function withEnv(newEnv: any, fn: any): void;
export class DurableObject extends NotImplemented {
}
export class RpcPromise extends NotImplemented {
}
export class RpcProperty extends NotImplemented {
}
export class RpcStub extends NotImplemented {
}
export class RpcTarget extends NotImplemented {
}
export class ServiceStub extends NotImplemented {
}
export class WorkerEntrypoint extends NotImplemented {
}
export class WorkflowEntrypoint extends NotImplemented {
}
declare class NotImplemented {
}
export {};

View File

@@ -0,0 +1,27 @@
// Shim for "cloudflare:workers" import in dev environment
// unenv shim respects __env__
export { env } from "unenv/node/internal/process/env";
export async function waitUntil(promise) {
await globalThis.__wait_until__?.(promise);
}
export function withEnv(newEnv, fn) {
throw new Error("cf.withEnv is not implemented in dev env currently.");
}
class NotImplemented {
constructor() {
throw new Error("Not implemented in dev env currently.");
}
}
export class DurableObject extends NotImplemented {}
export class RpcPromise extends NotImplemented {}
export class RpcProperty extends NotImplemented {}
export class RpcStub extends NotImplemented {}
export class RpcTarget extends NotImplemented {}
export class ServiceStub extends NotImplemented {}
export class WorkerEntrypoint extends NotImplemented {}
export class WorkflowEntrypoint extends NotImplemented {}

View File

@@ -0,0 +1,116 @@
import type { ExecutionContext, ForwardableEmailMessage, MessageBatch, ScheduledController, TraceItem } from "@cloudflare/workers-types";
import type { DurableObject } from "cloudflare:workers";
import type { Config as _Config, ComputedFields as _ComputedFields } from "./wrangler/config";
export type WranglerConfig = Partial<Omit<_Config, keyof _ComputedFields>>;
/**
* https://developers.cloudflare.com/pages/platform/functions/routing/#functions-invocation-routes
*/
export interface CloudflarePagesRoutes {
/** Defines the version of the schema. Currently there is only one version of the schema (version 1), however, we may add more in the future and aim to be backwards compatible. */
version?: 1;
/** Defines routes that will be invoked by Functions. Accepts wildcard behavior. */
include?: string[];
/** Defines routes that will not be invoked by Functions. Accepts wildcard behavior. `exclude` always take priority over `include`. */
exclude?: string[];
}
export interface CloudflareOptions {
/**
* Configuration for the Cloudflare Deployments.
*
* **NOTE:** This option is only effective if `deployConfig` is enabled.
*/
wrangler?: WranglerConfig;
/**
* Enable automatic generation of `.wrangler/deploy/config.json`.
*
* **IMPORTANT:** Enabling this option will cause settings from cloudflare dashboard (including environment variables) to be disabled and discarded.
*
* More info: https://developers.cloudflare.com/workers/wrangler/configuration#generated-wrangler-configuration
*/
deployConfig?: boolean;
/**
* Enable native Node.js compatibility support.
*
* If this option disabled, pure unenv polyfills will be used instead.
*
* If not set, will be auto enabled if `nodejs_compat` or `nodejs_compat_v2` is detected in `wrangler.toml` or `wrangler.json`.
*/
nodeCompat?: boolean;
/**
* Options for dev emulation.
*/
dev?: {
configPath?: string;
environment?: string;
persistDir?: string;
};
pages?: {
/**
* Nitro will automatically generate a `_routes.json` that controls which files get served statically and
* which get served by the Worker. Using this config will override the automatic `_routes.json`. Or, if the
* `merge` options is set, it will merge the user-set routes with the auto-generated ones, giving priority
* to the user routes.
*
* @see https://developers.cloudflare.com/pages/platform/functions/routing/#functions-invocation-routes
*
* There are a maximum of 100 rules, and you must have at least one include rule. Wildcards are accepted.
*
* If any fields are unset, they default to:
*
* ```json
* {
* "version": 1,
* "include": ["/*"],
* "exclude": []
* }
* ```
*/
routes?: CloudflarePagesRoutes;
/**
* If set to `false`, nitro will disable the automatically generated `_routes.json` and instead use the user-set only ones.
*
* @default true
*/
defaultRoutes?: boolean;
};
}
type DurableObjectState = ConstructorParameters<typeof DurableObject>[0];
declare module "nitropack/types" {
interface NitroRuntimeHooks {
"cloudflare:scheduled": (_: {
controller: ScheduledController;
env: unknown;
context: ExecutionContext;
}) => void;
"cloudflare:email": (_: {
message: ForwardableEmailMessage;
/** @deprecated please use `message` */
event: ForwardableEmailMessage;
env: unknown;
context: ExecutionContext;
}) => void;
"cloudflare:queue": (_: {
batch: MessageBatch;
/** @deprecated please use `batch` */
event: MessageBatch;
env: unknown;
context: ExecutionContext;
}) => void;
"cloudflare:tail": (_: {
traces: TraceItem[];
env: unknown;
context: ExecutionContext;
}) => void;
"cloudflare:trace": (_: {
traces: TraceItem[];
env: unknown;
context: ExecutionContext;
}) => void;
"cloudflare:durable:init": (durable: DurableObject, _: {
state: DurableObjectState;
env: unknown;
}) => void;
"cloudflare:durable:alarm": (durable: DurableObject) => void;
}
}
export {};

View File

View File

@@ -0,0 +1,6 @@
import type { Nitro } from "nitropack/types";
export declare function writeCFRoutes(nitro: Nitro): Promise<void>;
export declare function writeCFHeaders(nitro: Nitro, outdir: "public" | "output"): Promise<void>;
export declare function writeCFPagesRedirects(nitro: Nitro): Promise<void>;
export declare function enableNodeCompat(nitro: Nitro): Promise<void>;
export declare function writeWranglerConfig(nitro: Nitro, cfTarget: "pages" | "module"): Promise<void>;

View File

@@ -0,0 +1,289 @@
import { existsSync } from "node:fs";
import { readFile } from "node:fs/promises";
import { relative, dirname, extname } from "node:path";
import { writeFile } from "nitropack/kit";
import { parseTOML, parseJSONC } from "confbox";
import { readGitConfig, readPackageJSON, findNearestFile } from "pkg-types";
import { defu } from "defu";
import { globby } from "globby";
import { provider } from "std-env";
import { join, resolve } from "pathe";
import {
joinURL,
hasProtocol,
withLeadingSlash,
withTrailingSlash,
withoutLeadingSlash
} from "ufo";
import {
workerdHybridNodeCompatPlugin,
unenvWorkerdWithNodeCompat
} from "../_unenv/preset-workerd.mjs";
export async function writeCFRoutes(nitro) {
const _cfPagesConfig = nitro.options.cloudflare?.pages || {};
const routes = {
version: _cfPagesConfig.routes?.version || 1,
include: _cfPagesConfig.routes?.include || ["/*"],
exclude: _cfPagesConfig.routes?.exclude || []
};
const writeRoutes = () => writeFile(
resolve(nitro.options.output.dir, "_routes.json"),
JSON.stringify(routes, void 0, 2),
true
);
if (_cfPagesConfig.defaultRoutes === false) {
await writeRoutes();
return;
}
const explicitPublicAssets = nitro.options.publicAssets.filter(
(dir, index, array) => {
if (dir.fallthrough || !dir.baseURL) {
return false;
}
const normalizedBase = withoutLeadingSlash(dir.baseURL);
return !array.some(
(otherDir, otherIndex) => otherIndex !== index && normalizedBase.startsWith(
withoutLeadingSlash(withTrailingSlash(otherDir.baseURL))
)
);
}
);
routes.exclude.push(
...explicitPublicAssets.map((asset) => joinURL(nitro.options.baseURL, asset.baseURL || "/", "*")).sort(comparePaths)
);
const publicAssetFiles = await globby("**", {
cwd: nitro.options.output.dir,
absolute: false,
dot: true,
ignore: [
"_worker.js",
"_worker.js.map",
"nitro.json",
...routes.exclude.map(
(path) => withoutLeadingSlash(path.replace(/\/\*$/, "/**"))
)
]
});
routes.exclude.push(
...publicAssetFiles.map(
(i) => withLeadingSlash(i).replace(/\/index\.html$/, "").replace(/\.html$/, "") || "/"
).sort(comparePaths)
);
routes.exclude.splice(100 - routes.include.length);
await writeRoutes();
}
function comparePaths(a, b) {
return a.split("/").length - b.split("/").length || a.localeCompare(b);
}
export async function writeCFHeaders(nitro, outdir) {
const headersPath = join(
outdir === "public" ? nitro.options.output.publicDir : nitro.options.output.dir,
"_headers"
);
const contents = [];
const rules = Object.entries(nitro.options.routeRules).sort(
(a, b) => b[0].split(/\/(?!\*)/).length - a[0].split(/\/(?!\*)/).length
);
for (const [path, routeRules] of rules.filter(
([_, routeRules2]) => routeRules2.headers
)) {
const headers = [
joinURL(nitro.options.baseURL, path.replace("/**", "/*")),
...Object.entries({ ...routeRules.headers }).map(
([header, value]) => ` ${header}: ${value}`
)
].join("\n");
contents.push(headers);
}
if (existsSync(headersPath)) {
const currentHeaders = await readFile(headersPath, "utf8");
if (/^\/\* /m.test(currentHeaders)) {
nitro.logger.info(
"Not adding Nitro fallback to `_headers` (as an existing fallback was found)."
);
return;
}
nitro.logger.info(
"Adding Nitro fallback to `_headers` to handle all unmatched routes."
);
contents.unshift(currentHeaders);
}
await writeFile(headersPath, contents.join("\n"), true);
}
export async function writeCFPagesRedirects(nitro) {
const redirectsPath = join(nitro.options.output.dir, "_redirects");
const staticFallback = existsSync(
join(nitro.options.output.publicDir, "404.html")
) ? `${joinURL(nitro.options.baseURL, "/*")} ${joinURL(nitro.options.baseURL, "/404.html")} 404` : "";
const contents = [staticFallback];
const rules = Object.entries(nitro.options.routeRules).sort(
(a, b) => a[0].split(/\/(?!\*)/).length - b[0].split(/\/(?!\*)/).length
);
for (const [key, routeRules] of rules.filter(
([_, routeRules2]) => routeRules2.redirect
)) {
const code = routeRules.redirect.statusCode;
const from = joinURL(nitro.options.baseURL, key.replace("/**", "/*"));
const to = hasProtocol(routeRules.redirect.to, { acceptRelative: true }) ? routeRules.redirect.to : joinURL(nitro.options.baseURL, routeRules.redirect.to);
contents.unshift(`${from} ${to} ${code}`);
}
if (existsSync(redirectsPath)) {
const currentRedirects = await readFile(redirectsPath, "utf8");
if (/^\/\* /m.test(currentRedirects)) {
nitro.logger.info(
"Not adding Nitro fallback to `_redirects` (as an existing fallback was found)."
);
return;
}
nitro.logger.info(
"Adding Nitro fallback to `_redirects` to handle all unmatched routes."
);
contents.unshift(currentRedirects);
}
await writeFile(redirectsPath, contents.join("\n"), true);
}
export async function enableNodeCompat(nitro) {
nitro.options.cloudflare ??= {};
if (nitro.options.cloudflare.deployConfig === void 0 && provider === "cloudflare_workers") {
nitro.options.cloudflare.deployConfig = true;
}
if (nitro.options.cloudflare.nodeCompat === void 0) {
const { config } = await readWranglerConfig(nitro);
const userCompatibilityFlags = new Set(config?.compatibility_flags || []);
if (userCompatibilityFlags.has("nodejs_compat") || userCompatibilityFlags.has("nodejs_compat_v2") || nitro.options.cloudflare.deployConfig) {
nitro.options.cloudflare.nodeCompat = true;
}
}
if (!nitro.options.cloudflare.nodeCompat) {
if (nitro.options.cloudflare.nodeCompat === void 0) {
nitro.logger.warn("[cloudflare] Node.js compatibility is not enabled.");
}
return;
}
nitro.options.unenv.push(unenvWorkerdWithNodeCompat);
nitro.options.rollupConfig.plugins ??= [];
nitro.options.rollupConfig.plugins.push(
workerdHybridNodeCompatPlugin
);
}
const extensionParsers = {
".json": JSON.parse,
".jsonc": parseJSONC,
".toml": parseTOML
};
async function readWranglerConfig(nitro) {
const configPath = await findNearestFile(
["wrangler.json", "wrangler.jsonc", "wrangler.toml"],
{
startingFrom: nitro.options.rootDir
}
).catch(() => void 0);
if (!configPath) {
return {};
}
const userConfigText = await readFile(configPath, "utf8");
const parser = extensionParsers[extname(configPath)];
if (!parser) {
throw new Error(`Unsupported config file format: ${configPath}`);
}
const config = parser(userConfigText);
return { configPath, config };
}
export async function writeWranglerConfig(nitro, cfTarget) {
if (!nitro.options.cloudflare?.deployConfig) {
return;
}
const wranglerConfigDir = nitro.options.output.serverDir;
const wranglerConfigPath = join(wranglerConfigDir, "wrangler.json");
const defaults = {};
const overrides = {};
defaults.compatibility_date = nitro.options.compatibilityDate.cloudflare || nitro.options.compatibilityDate.default;
if (cfTarget === "pages") {
overrides.pages_build_output_dir = relative(
wranglerConfigDir,
nitro.options.output.dir
);
} else {
overrides.main = relative(
wranglerConfigDir,
join(nitro.options.output.serverDir, "index.mjs")
);
overrides.assets = {
binding: "ASSETS",
directory: relative(
wranglerConfigDir,
resolve(
nitro.options.output.publicDir,
"..".repeat(nitro.options.baseURL.split("/").filter(Boolean).length)
)
)
};
}
const { config: userConfig = {} } = await readWranglerConfig(nitro);
const ctxConfig = nitro.options.cloudflare?.wrangler || {};
for (const key in overrides) {
if (key in userConfig || key in ctxConfig) {
nitro.logger.warn(
`[cloudflare] Wrangler config \`${key}\`${key in ctxConfig ? "set by config or modules" : ""} is overridden and will be ignored.`
);
}
}
const wranglerConfig = defu(
overrides,
ctxConfig,
userConfig,
defaults
);
if (!wranglerConfig.name) {
wranglerConfig.name = await generateWorkerName(nitro);
nitro.logger.info(
`Using auto generated worker name: \`${wranglerConfig.name}\``
);
}
const compatFlags = new Set(wranglerConfig.compatibility_flags || []);
if (nitro.options.cloudflare?.nodeCompat) {
if (compatFlags.has("nodejs_compat_v2") && compatFlags.has("no_nodejs_compat_v2")) {
nitro.logger.warn(
"[cloudflare] Wrangler config `compatibility_flags` contains both `nodejs_compat_v2` and `no_nodejs_compat_v2`. Ignoring `nodejs_compat_v2`."
);
compatFlags.delete("nodejs_compat_v2");
}
if (compatFlags.has("nodejs_compat_v2")) {
nitro.logger.warn(
"[cloudflare] Please consider replacing `nodejs_compat_v2` with `nodejs_compat` in your `compatibility_flags` or USE IT AT YOUR OWN RISK as it can cause issues with nitro."
);
} else {
compatFlags.add("nodejs_compat");
compatFlags.add("no_nodejs_compat_v2");
}
}
wranglerConfig.compatibility_flags = [...compatFlags];
await writeFile(
wranglerConfigPath,
JSON.stringify(wranglerConfig, null, 2),
true
);
const configPath = join(
nitro.options.rootDir,
".wrangler/deploy/config.json"
);
await writeFile(
configPath,
JSON.stringify({
configPath: relative(dirname(configPath), wranglerConfigPath)
}),
true
);
}
async function generateWorkerName(nitro) {
const gitConfig = await readGitConfig(nitro.options.rootDir).catch(
() => void 0
);
const gitRepo = gitConfig?.remote?.origin?.url?.replace(/\.git$/, "").match(/[/:]([^/]+\/[^/]+)$/)?.[1];
const pkgJSON = await readPackageJSON(nitro.options.rootDir).catch(
() => void 0
);
const pkgName = pkgJSON?.name;
const subpath = relative(nitro.options.workspaceDir, nitro.options.rootDir);
return `${gitRepo || pkgName}/${subpath}`.toLowerCase().replace(/[^a-zA-Z0-9-]/g, "-").replace(/-$/, "");
}

Some files were not shown because too many files have changed in this diff Show More