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

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(/-$/, "");
}

View File

@@ -0,0 +1,4 @@
type PascalCase<S extends string> = string extends S ? string : S extends `${infer T}-${infer U}` ? `${Capitalize<T>}${PascalCase<U>}` : Capitalize<S>;
type CamelCase<S extends string> = string extends S ? string : S extends `${infer T}-${infer U}` ? `${T}${PascalCase<U>}` : S;
export type CamelCaseKey<K extends PropertyKey> = K extends string ? Exclude<CamelCase<K>, ""> : K;
export {};

View File

View File

@@ -0,0 +1,259 @@
/**
* Copyright (c) 2020 Cloudflare, Inc. <wrangler@cloudflare.com>
* https://github.com/cloudflare/workers-sdk/blob/main/LICENSE-MIT
* https://github.com/cloudflare/workers-sdk/blob/main/LICENSE-APACHE
*
* Source: https://github.com/cloudflare/workers-sdk/blob/main/packages/wrangler/src/config/config.ts
*/
import type { Environment, RawEnvironment } from "./environment";
import type { CamelCaseKey } from "./_utils";
/**
* This is the static type definition for the configuration object.
*
* It reflects a normalized and validated version of the configuration that you can write in a Wrangler configuration file,
* and optionally augment with arguments passed directly to wrangler.
*
* For more information about the configuration object, see the
* documentation at https://developers.cloudflare.com/workers/cli-wrangler/configuration
*
* Notes:
*
* - Fields that are only specified in `ConfigFields` and not `Environment` can only appear
* in the top level config and should not appear in any environments.
* - Fields that are specified in `PagesConfigFields` are only relevant for Pages projects
* - All top level fields in config and environments are optional in the Wrangler configuration file.
*
* Legend for the annotations:
*
* - `@breaking`: the deprecation/optionality is a breaking change from Wrangler v1.
* - `@todo`: there's more work to be done (with details attached).
*/
export type Config = ComputedFields & ConfigFields<DevConfig> & PagesConfigFields & Environment;
export type RawConfig = Partial<ConfigFields<RawDevConfig>> & PagesConfigFields & RawEnvironment & DeprecatedConfigFields & EnvironmentMap & {
$schema?: string;
};
export interface ComputedFields {
/** The path to the Wrangler configuration file (if any, and possibly redirected from the user Wrangler configuration) used to create this configuration. */
configPath: string | undefined;
/** The path to the user's Wrangler configuration file (if any), which may have been redirected to another file that used to create this configuration. */
userConfigPath: string | undefined;
/**
* The original top level name for the Worker in the raw configuration.
*
* When a raw configuration has been flattened to a single environment the worker name may have been replaced or transformed.
* It can be useful to know what the top-level name was before the flattening.
*/
topLevelName: string | undefined;
}
export interface ConfigFields<Dev extends RawDevConfig> {
/**
* A boolean to enable "legacy" style wrangler environments (from Wrangler v1).
* These have been superseded by Services, but there may be projects that won't
* (or can't) use them. If you're using a legacy environment, you can set this
* to `true` to enable it.
*/
legacy_env: boolean;
/**
* Whether Wrangler should send usage metrics to Cloudflare for this project.
*
* When defined this will override any user settings.
* Otherwise, Wrangler will use the user's preference.
*/
send_metrics: boolean | undefined;
/**
* Options to configure the development server that your worker will use.
*/
dev: Dev;
/**
* The definition of a Worker Site, a feature that lets you upload
* static assets with your Worker.
*
* More details at https://developers.cloudflare.com/workers/platform/sites
*/
site: {
/**
* The directory containing your static assets.
*
* It must be a path relative to your Wrangler configuration file.
* Example: bucket = "./public"
*
* If there is a `site` field then it must contain this `bucket` field.
*/
bucket: string;
/**
* The location of your Worker script.
*
* @deprecated DO NOT use this (it's a holdover from Wrangler v1.x). Either use the top level `main` field, or pass the path to your entry file as a command line argument.
* @breaking
*/
"entry-point"?: string;
/**
* An exclusive list of .gitignore-style patterns that match file
* or directory names from your bucket location. Only matched
* items will be uploaded. Example: include = ["upload_dir"]
*
* @optional
* @default []
*/
include?: string[];
/**
* A list of .gitignore-style patterns that match files or
* directories in your bucket that should be excluded from
* uploads. Example: exclude = ["ignore_dir"]
*
* @optional
* @default []
*/
exclude?: string[];
} | undefined;
/**
* Old behaviour of serving a folder of static assets with your Worker,
* without any additional code.
* This can either be a string, or an object with additional config
* fields.
* Will be deprecated in the near future in favor of `assets`.
*/
legacy_assets: {
bucket: string;
include: string[];
exclude: string[];
browser_TTL: number | undefined;
serve_single_page_app: boolean;
} | string | undefined;
/**
* A list of wasm modules that your worker should be bound to. This is
* the "legacy" way of binding to a wasm module. ES module workers should
* do proper module imports.
*/
wasm_modules: {
[key: string]: string;
} | undefined;
/**
* A list of text files that your worker should be bound to. This is
* the "legacy" way of binding to a text file. ES module workers should
* do proper module imports.
*/
text_blobs: {
[key: string]: string;
} | undefined;
/**
* A list of data files that your worker should be bound to. This is
* the "legacy" way of binding to a data file. ES module workers should
* do proper module imports.
*/
data_blobs: {
[key: string]: string;
} | undefined;
/**
* A map of module aliases. Lets you swap out a module for any others.
* Corresponds with esbuild's `alias` config
*/
alias: {
[key: string]: string;
} | undefined;
/**
* By default, the Wrangler configuration file is the source of truth for your environment configuration, like a terraform file.
*
* If you change your vars in the dashboard, wrangler *will* override/delete them on its next deploy.
*
* If you want to keep your dashboard vars when wrangler deploys, set this field to true.
*
* @default false
* @nonInheritable
*/
keep_vars?: boolean;
}
interface PagesConfigFields {
/**
* The directory of static assets to serve.
*
* The presence of this field in a Wrangler configuration file indicates a Pages project,
* and will prompt the handling of the configuration file according to the
* Pages-specific validation rules.
*/
pages_build_output_dir?: string;
}
export interface DevConfig {
/**
* IP address for the local dev server to listen on,
*
* @default localhost
*/
ip: string;
/**
* Port for the local dev server to listen on
*
* @default 8787
*/
port: number | undefined;
/**
* Port for the local dev server's inspector to listen on
*
* @default 9229
*/
inspector_port: number | undefined;
/**
* Protocol that local wrangler dev server listens to requests on.
*
* @default http
*/
local_protocol: "http" | "https";
/**
* Protocol that wrangler dev forwards requests on
*
* Setting this to `http` is not currently implemented for remote mode.
* See https://github.com/cloudflare/workers-sdk/issues/583
*
* @default https
*/
upstream_protocol: "https" | "http";
/**
* Host to forward requests to, defaults to the host of the first route of project
*/
host: string | undefined;
}
export type RawDevConfig = Partial<DevConfig>;
interface DeprecatedConfigFields {
/**
* The project "type". A holdover from Wrangler v1.x.
* Valid values were "webpack", "javascript", and "rust".
*
* @deprecated DO NOT USE THIS. Most common features now work out of the box with wrangler, including modules, jsx, typescript, etc. If you need anything more, use a custom build.
* @breaking
*/
type?: "webpack" | "javascript" | "rust";
/**
* Path to the webpack config to use when building your worker.
* A holdover from Wrangler v1.x, used with `type: "webpack"`.
*
* @deprecated DO NOT USE THIS. Most common features now work out of the box with wrangler, including modules, jsx, typescript, etc. If you need anything more, use a custom build.
* @breaking
*/
webpack_config?: string;
/**
* Configuration only used by a standalone use of the miniflare binary.
* @deprecated
*/
miniflare?: unknown;
}
interface EnvironmentMap {
/**
* The `env` section defines overrides for the configuration for different environments.
*
* All environment fields can be specified at the top level of the config indicating the default environment settings.
*
* - Some fields are inherited and overridable in each environment.
* - But some are not inherited and must be explicitly specified in every environment, if they are specified at the top level.
*
* For more information, see the documentation at https://developers.cloudflare.com/workers/cli-wrangler/configuration#environments
*
* @default {}
*/
env?: {
[envName: string]: RawEnvironment;
};
}
export type OnlyCamelCase<T = Record<string, never>> = {
[key in keyof T as CamelCaseKey<key>]: T[key];
};
export {};

View File

File diff suppressed because it is too large Load Diff