nitropack-nightly 2.12.0-20250713-204442.4753575e → 2.12.0-20250714-151334.b56c4684

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -790,9 +790,7 @@ async function _loadUserConfig(configOverrides = {}, opts = {}) {
790
790
  options.compatibilityDate
791
791
  );
792
792
  if (options.dev && options.preset !== "nitro-dev") {
793
- consola.info(
794
- `Enabled \`${options.preset}\` emulation in development mode.`
795
- );
793
+ consola.info(`Using \`${options.preset}\` emulation in development mode.`);
796
794
  }
797
795
  return options;
798
796
  }
@@ -1,4 +1,4 @@
1
- const version = "2.12.0-20250713-204442.4753575e";
1
+ const version = "2.12.0-20250714-151334.b56c4684";
2
2
 
3
3
  const compatibilityChanges = [
4
4
  {
@@ -15,5 +15,5 @@ export interface PresetOptions {
15
15
  vercel: VercelOptions;
16
16
  }
17
17
  export declare const presetsWithConfig: readonly ["awsAmplify", "awsLambda", "azure", "cloudflare", "firebase", "netlify", "vercel"];
18
- export type PresetName = "alwaysdata" | "aws-amplify" | "aws-lambda" | "azure" | "azure-functions" | "azure-swa" | "base-worker" | "bun" | "cleavr" | "cli" | "cloudflare" | "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";
19
- 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-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 & {});
18
+ 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";
19
+ 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 & {});
@@ -0,0 +1,2 @@
1
+ import type { Nitro } from "nitropack";
2
+ export declare function cloudflareDev(nitro: Nitro): Promise<void>;
@@ -0,0 +1,64 @@
1
+ import { resolve } from "node:path";
2
+ import { promises as fs } from "node:fs";
3
+ import { fileURLToPath } from "mlly";
4
+ import { findFile } from "pkg-types";
5
+ import { resolveModulePath } from "exsolve";
6
+ export async function cloudflareDev(nitro) {
7
+ if (!nitro.options.dev) {
8
+ return;
9
+ }
10
+ const wranglerPath = await resolveModulePath("wrangler", {
11
+ from: nitro.options.nodeModulesDirs,
12
+ try: true
13
+ });
14
+ if (!wranglerPath) {
15
+ nitro.logger.warn(
16
+ "Wrangler is not installed. Please install it using `npx nypm i wrangler` to enable dev emulation."
17
+ );
18
+ return;
19
+ }
20
+ const config = {
21
+ // compatibility with legacy nitro-cloudflare-dev module
22
+ ...nitro.options.cloudflareDev,
23
+ ...nitro.options.cloudflare?.dev
24
+ };
25
+ let configPath = config.configPath;
26
+ if (!configPath) {
27
+ configPath = await findFile(
28
+ ["wrangler.json", "wrangler.jsonc", "wrangler.toml"],
29
+ {
30
+ startingFrom: nitro.options.srcDir
31
+ }
32
+ ).catch(() => void 0);
33
+ }
34
+ const persistDir = resolve(
35
+ nitro.options.rootDir,
36
+ config.persistDir || ".wrangler/state/v3"
37
+ );
38
+ const gitIgnorePath = await findFile(".gitignore", {
39
+ startingFrom: nitro.options.rootDir
40
+ }).catch(() => void 0);
41
+ let addedToGitIgnore = false;
42
+ if (gitIgnorePath && persistDir === ".wrangler/state/v3") {
43
+ const gitIgnore = await fs.readFile(gitIgnorePath, "utf8");
44
+ if (!gitIgnore.includes(".wrangler/state/v3")) {
45
+ await fs.writeFile(gitIgnorePath, gitIgnore + "\n.wrangler/state/v3\n").catch(() => {
46
+ });
47
+ addedToGitIgnore = true;
48
+ }
49
+ }
50
+ nitro.options.runtimeConfig.wrangler = {
51
+ ...nitro.options.runtimeConfig.wrangler,
52
+ configPath,
53
+ persistDir,
54
+ environment: config.environment
55
+ };
56
+ nitro.options.externals.inline = nitro.options.externals.inline || [];
57
+ nitro.options.externals.inline.push(
58
+ fileURLToPath(new URL("runtime/", import.meta.url))
59
+ );
60
+ nitro.options.plugins = nitro.options.plugins || [];
61
+ nitro.options.plugins.push(
62
+ fileURLToPath(new URL("runtime/plugin.dev", import.meta.url))
63
+ );
64
+ }
@@ -1,3 +1,4 @@
1
1
  export type { CloudflareOptions as PresetOptions } from "./types";
2
+ export declare const cloudflareDev: any;
2
3
  declare const _default: any[];
3
4
  export default _default;
@@ -84,6 +84,21 @@ const cloudflarePagesStatic = defineNitroPreset(
84
84
  static: true
85
85
  }
86
86
  );
87
+ export const cloudflareDev = defineNitroPreset(
88
+ {
89
+ extends: "nitro-dev",
90
+ modules: [
91
+ async (nitro) => await import("./dev.mjs").then((m) => m.cloudflareDev(nitro))
92
+ ]
93
+ },
94
+ {
95
+ name: "cloudflare-dev",
96
+ aliases: ["cloudflare-module", "cloudflare-durable", "cloudflare-pages"],
97
+ compatibilityDate: "2025-07-13",
98
+ url: import.meta.url,
99
+ dev: true
100
+ }
101
+ );
87
102
  const cloudflareModule = defineNitroPreset(
88
103
  {
89
104
  extends: "base-worker",
@@ -149,5 +164,6 @@ export default [
149
164
  cloudflarePages,
150
165
  cloudflarePagesStatic,
151
166
  cloudflareModule,
152
- cloudflareDurable
167
+ cloudflareDurable,
168
+ cloudflareDev
153
169
  ];
@@ -0,0 +1,3 @@
1
+ import type { NitroAppPlugin } from "nitropack";
2
+ declare const _default: NitroAppPlugin;
3
+ export default _default;
@@ -0,0 +1,87 @@
1
+ import { useRuntimeConfig, getRequestURL } from "#imports";
2
+ const _proxy = _getPlatformProxy().catch((error) => {
3
+ console.error("Failed to initialize wrangler bindings proxy", error);
4
+ return _createStubProxy();
5
+ }).then((proxy) => {
6
+ globalThis.__env__ = proxy.env;
7
+ return proxy;
8
+ });
9
+ globalThis.__env__ = _proxy.then((proxy) => proxy.env);
10
+ export default (function(nitroApp) {
11
+ nitroApp.hooks.hook("request", async (event) => {
12
+ const proxy = await _proxy;
13
+ event.context.cf = proxy.cf;
14
+ event.context.waitUntil = proxy.ctx.waitUntil.bind(proxy.ctx);
15
+ const request = new Request(getRequestURL(event));
16
+ request.cf = proxy.cf;
17
+ event.context.cloudflare = {
18
+ ...event.context.cloudflare,
19
+ request,
20
+ env: proxy.env,
21
+ context: proxy.ctx
22
+ };
23
+ event.node.req.__unenv__ = {
24
+ ...event.node.req.__unenv__,
25
+ waitUntil: event.context.waitUntil
26
+ };
27
+ });
28
+ nitroApp.hooks._hooks.request.unshift(nitroApp.hooks._hooks.request.pop());
29
+ nitroApp.hooks.hook("close", () => {
30
+ return _proxy?.then((proxy) => proxy.dispose);
31
+ });
32
+ });
33
+ async function _getPlatformProxy() {
34
+ const _pkg = "wrangler";
35
+ const { getPlatformProxy } = await import(_pkg).catch(() => {
36
+ throw new Error(
37
+ "Package `wrangler` not found, please install it with: `npx nypm@latest add -D wrangler`"
38
+ );
39
+ });
40
+ const runtimeConfig = useRuntimeConfig();
41
+ const proxyOptions = {
42
+ configPath: runtimeConfig.wrangler.configPath,
43
+ persist: { path: runtimeConfig.wrangler.persistDir }
44
+ };
45
+ if (runtimeConfig.wrangler.environment) {
46
+ proxyOptions.environment = runtimeConfig.wrangler.environment;
47
+ }
48
+ const proxy = await getPlatformProxy(proxyOptions);
49
+ return proxy;
50
+ }
51
+ function _createStubProxy() {
52
+ return {
53
+ env: {},
54
+ cf: {},
55
+ ctx: {
56
+ waitUntil() {
57
+ },
58
+ passThroughOnException() {
59
+ },
60
+ props: {}
61
+ },
62
+ caches: {
63
+ open() {
64
+ const result = Promise.resolve(new _CacheStub());
65
+ return result;
66
+ },
67
+ get default() {
68
+ return new _CacheStub();
69
+ }
70
+ },
71
+ dispose: () => Promise.resolve()
72
+ };
73
+ }
74
+ class _CacheStub {
75
+ delete() {
76
+ const result = Promise.resolve(false);
77
+ return result;
78
+ }
79
+ match() {
80
+ const result = Promise.resolve(void 0);
81
+ return result;
82
+ }
83
+ put() {
84
+ const result = Promise.resolve();
85
+ return result;
86
+ }
87
+ }
@@ -36,6 +36,14 @@ export interface CloudflareOptions {
36
36
  * If not set, will be auto enabled if `nodejs_compat` or `nodejs_compat_v2` is detected in `wrangler.toml` or `wrangler.json`.
37
37
  */
38
38
  nodeCompat?: boolean;
39
+ /**
40
+ * Options for dev emulation.
41
+ */
42
+ dev?: {
43
+ configPath?: string;
44
+ environment?: string;
45
+ persistDir?: string;
46
+ };
39
47
  pages?: {
40
48
  /**
41
49
  * Nitro will automatically generate a `_routes.json` that controls which files get served statically and
@@ -5,8 +5,9 @@ import { dirname, relative, resolve } from "pathe";
5
5
  import { joinURL, withoutLeadingSlash } from "ufo";
6
6
  import { isTest } from "std-env";
7
7
  export async function generateFunctionFiles(nitro) {
8
+ const o11Routes = getObservibilityRoutes(nitro);
8
9
  const buildConfigPath = resolve(nitro.options.output.dir, "config.json");
9
- const buildConfig = generateBuildConfig(nitro);
10
+ const buildConfig = generateBuildConfig(nitro, o11Routes);
10
11
  await writeFile(buildConfigPath, JSON.stringify(buildConfig, null, 2));
11
12
  const systemNodeVersion = process.versions.node.split(".")[0];
12
13
  const runtimeVersion = `nodejs${systemNodeVersion}.x`;
@@ -61,6 +62,19 @@ export async function generateFunctionFiles(nitro) {
61
62
  JSON.stringify(prerenderConfig, null, 2)
62
63
  );
63
64
  }
65
+ for (const route of o11Routes) {
66
+ const funcPrefix = resolve(
67
+ nitro.options.output.serverDir,
68
+ "..",
69
+ route.dest
70
+ );
71
+ await fsp.mkdir(dirname(funcPrefix), { recursive: true });
72
+ await fsp.symlink(
73
+ "./" + relative(dirname(funcPrefix), nitro.options.output.serverDir),
74
+ funcPrefix + ".func",
75
+ "junction"
76
+ );
77
+ }
64
78
  }
65
79
  export async function generateEdgeFunctionFiles(nitro) {
66
80
  const buildConfigPath = resolve(nitro.options.output.dir, "config.json");
@@ -82,7 +96,7 @@ export async function generateStaticFiles(nitro) {
82
96
  const buildConfig = generateBuildConfig(nitro);
83
97
  await writeFile(buildConfigPath, JSON.stringify(buildConfig, null, 2));
84
98
  }
85
- function generateBuildConfig(nitro) {
99
+ function generateBuildConfig(nitro, o11Routes) {
86
100
  const rules = Object.entries(nitro.options.routeRules).sort(
87
101
  (a, b) => b[0].split(/\/(?!\*)/).length - a[0].split(/\/(?!\*)/).length
88
102
  );
@@ -155,6 +169,10 @@ function generateBuildConfig(nitro) {
155
169
  dest: "/__nitro-index?url=$url"
156
170
  }
157
171
  ] : [],
172
+ ...(o11Routes || []).map((route) => ({
173
+ src: route.src,
174
+ dest: "/" + route.dest
175
+ })),
158
176
  ...nitro.options.routeRules["/**"]?.isr ? [] : [
159
177
  {
160
178
  src: "/(.*)",
@@ -200,3 +218,70 @@ export function deprecateSWR(nitro) {
200
218
  function _hasProp(obj, prop) {
201
219
  return obj && typeof obj === "object" && prop in obj;
202
220
  }
221
+ function getObservibilityRoutes(nitro) {
222
+ const routePatterns = [
223
+ ...new Set(
224
+ [...nitro.scannedHandlers, ...nitro.options.handlers].filter((h) => !h.middleware && h.route).map((h) => h.route)
225
+ )
226
+ ];
227
+ const staticRoutes = [];
228
+ const dynamicRoutes = [];
229
+ const catchAllRoutes = [];
230
+ for (const route of routePatterns) {
231
+ if (route.includes("**")) {
232
+ catchAllRoutes.push(route);
233
+ } else if (route.includes(":") || route.includes("*")) {
234
+ dynamicRoutes.push(route);
235
+ } else {
236
+ staticRoutes.push(route);
237
+ }
238
+ }
239
+ return [
240
+ ...normalizeRoutes(staticRoutes),
241
+ ...normalizeRoutes(dynamicRoutes),
242
+ ...normalizeRoutes(catchAllRoutes)
243
+ ];
244
+ }
245
+ function normalizeRoutes(routes) {
246
+ return routes.sort(
247
+ (a, b) => (
248
+ // a.split("/").length - b.split("/").length ||
249
+ b.localeCompare(a)
250
+ )
251
+ ).map((route) => ({
252
+ src: normalizeRouteSrc(route),
253
+ dest: normalizeRouteDest(route)
254
+ }));
255
+ }
256
+ function normalizeRouteSrc(route) {
257
+ let idCtr = 0;
258
+ return route.split("/").map((segment) => {
259
+ if (segment.startsWith("**")) {
260
+ return segment === "**" ? "?(?<_>.*)" : `?(?<${segment.slice(3)}>.+)`;
261
+ }
262
+ if (segment === "*") {
263
+ return `(?<_${idCtr++}>[^/]*)`;
264
+ }
265
+ if (segment.includes(":")) {
266
+ return segment.replace(/:(\w+)/g, (_, id) => `(?<${id}>[^/]+)`).replace(/\./g, String.raw`\.`);
267
+ }
268
+ return segment;
269
+ }).join("/");
270
+ }
271
+ function normalizeRouteDest(route) {
272
+ return route.split("/").slice(1).map((segment) => {
273
+ if (segment.startsWith("**")) {
274
+ return `[...${segment.replace(/[*:]/g, "")}]`;
275
+ }
276
+ if (segment === "*") {
277
+ return "[-]";
278
+ }
279
+ if (segment.startsWith(":")) {
280
+ return `[${segment.slice(1)}]`;
281
+ }
282
+ if (segment.includes(":")) {
283
+ return `[${segment.replace(/:/g, "_")}]`;
284
+ }
285
+ return segment;
286
+ }).map((segment) => segment.replace(/[^a-zA-Z0-9_.[\]]/g, "-")).join("/");
287
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nitropack-nightly",
3
- "version": "2.12.0-20250713-204442.4753575e",
3
+ "version": "2.12.0-20250714-151334.b56c4684",
4
4
  "description": "Build and Deploy Universal JavaScript Servers",
5
5
  "repository": "nitrojs/nitro",
6
6
  "license": "MIT",
@@ -204,6 +204,7 @@
204
204
  "unbuild": "^3.5.0",
205
205
  "undici": "^7.11.0",
206
206
  "vitest": "^3.2.4",
207
+ "wrangler": "^4.24.3",
207
208
  "xml2js": "^0.6.2"
208
209
  },
209
210
  "peerDependencies": {