nitro-nightly 3.1.0-20251030-005056-3637ebe2 → 4.0.0-20251030-091344-d4418b98
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.
- package/dist/_build/build.mjs +3 -3
- package/dist/_build/build2.mjs +3 -3
- package/dist/_build/prepare.mjs +1 -1
- package/dist/_build/snapshot.mjs +1 -1
- package/dist/_build/vite.mjs +8 -8
- package/dist/_chunks/{index.mjs → builder.mjs} +429 -429
- package/dist/_cli/build.mjs +1 -5
- package/dist/_cli/dev.mjs +1 -1
- package/dist/_cli/list.mjs +1 -1
- package/dist/_cli/prepare.mjs +1 -1
- package/dist/_cli/run.mjs +1 -1
- package/dist/{index.d.mts → builder.d.mts} +11 -11
- package/dist/{index.mjs → builder.mjs} +3 -3
- package/dist/presets/_nitro/runtime/nitro-dev.mjs +0 -4
- package/lib/index.mjs +1 -0
- package/lib/indexd.mts +1 -0
- package/package.json +3 -2
package/dist/_build/build.mjs
CHANGED
|
@@ -9,7 +9,7 @@ import { watch } from '../_chunks/_deps/chokidar.mjs';
|
|
|
9
9
|
import { watch as watch$1 } from 'node:fs';
|
|
10
10
|
import { d as debounce } from '../_chunks/_deps/perfect-debounce.mjs';
|
|
11
11
|
import { s as scanHandlers } from './prepare.mjs';
|
|
12
|
-
import { w as writeTypes } from '../_chunks/
|
|
12
|
+
import { w as writeTypes } from '../_chunks/builder.mjs';
|
|
13
13
|
import { f as formatCompatibilityDate } from '../_chunks/_deps/compatx.mjs';
|
|
14
14
|
import '../_chunks/_deps/acorn.mjs';
|
|
15
15
|
import 'ufo';
|
|
@@ -91,7 +91,7 @@ import '../_chunks/_deps/escape-string-regexp.mjs';
|
|
|
91
91
|
import 'ofetch';
|
|
92
92
|
import '../_chunks/_deps/rou3.mjs';
|
|
93
93
|
import '../_chunks/_deps/dot-prop.mjs';
|
|
94
|
-
import '../_chunks/_deps/
|
|
94
|
+
import '../_chunks/_deps/untyped.mjs';
|
|
95
95
|
import '../_chunks/server.mjs';
|
|
96
96
|
import '../_chunks/app.mjs';
|
|
97
97
|
import 'node:worker_threads';
|
|
@@ -128,7 +128,7 @@ import 'youch';
|
|
|
128
128
|
import 'source-map';
|
|
129
129
|
import 'srvx';
|
|
130
130
|
import 'srvx/node';
|
|
131
|
-
import '../_chunks/_deps/
|
|
131
|
+
import '../_chunks/_deps/ultrahtml.mjs';
|
|
132
132
|
|
|
133
133
|
const getRolldownConfig = (nitro) => {
|
|
134
134
|
const base = baseBuildConfig(nitro);
|
package/dist/_build/build2.mjs
CHANGED
|
@@ -16,7 +16,7 @@ import { watch } from '../_chunks/_deps/chokidar.mjs';
|
|
|
16
16
|
import { watch as watch$1 } from 'node:fs';
|
|
17
17
|
import { d as debounce } from '../_chunks/_deps/perfect-debounce.mjs';
|
|
18
18
|
import { s as scanHandlers } from './prepare.mjs';
|
|
19
|
-
import { w as writeTypes } from '../_chunks/
|
|
19
|
+
import { w as writeTypes } from '../_chunks/builder.mjs';
|
|
20
20
|
import { f as formatCompatibilityDate } from '../_chunks/_deps/compatx.mjs';
|
|
21
21
|
import '../_chunks/_deps/acorn.mjs';
|
|
22
22
|
import 'ufo';
|
|
@@ -105,7 +105,7 @@ import '../_chunks/_deps/escape-string-regexp.mjs';
|
|
|
105
105
|
import 'ofetch';
|
|
106
106
|
import '../_chunks/_deps/rou3.mjs';
|
|
107
107
|
import '../_chunks/_deps/dot-prop.mjs';
|
|
108
|
-
import '../_chunks/_deps/
|
|
108
|
+
import '../_chunks/_deps/untyped.mjs';
|
|
109
109
|
import '../_chunks/server.mjs';
|
|
110
110
|
import '../_chunks/app.mjs';
|
|
111
111
|
import 'node:worker_threads';
|
|
@@ -141,7 +141,7 @@ import 'youch';
|
|
|
141
141
|
import 'source-map';
|
|
142
142
|
import 'srvx';
|
|
143
143
|
import 'srvx/node';
|
|
144
|
-
import '../_chunks/_deps/
|
|
144
|
+
import '../_chunks/_deps/ultrahtml.mjs';
|
|
145
145
|
|
|
146
146
|
const defaultLoaders = {
|
|
147
147
|
".ts": "ts",
|
package/dist/_build/prepare.mjs
CHANGED
|
@@ -1508,4 +1508,4 @@ async function prepareDir(dir) {
|
|
|
1508
1508
|
await fsp.mkdir(dir, { recursive: true });
|
|
1509
1509
|
}
|
|
1510
1510
|
|
|
1511
|
-
export { snapshotStorage as a, scanUnprefixedPublicAssets as b, createNitro as c, compressPublicAssets as d,
|
|
1511
|
+
export { snapshotStorage as a, scanUnprefixedPublicAssets as b, createNitro as c, compressPublicAssets as d, copyPublicAssets as e, runTask as f, listTasks as g, prettyPath as h, isDirectory as i, loadOptions as l, prepare as p, resolveNitroPath as r, scanHandlers as s, writeFile as w };
|
package/dist/_build/snapshot.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import { g as glob } from '../_chunks/_deps/tinyglobby.mjs';
|
|
|
7
7
|
import { g as gzipSize } from '../_chunks/_deps/gzip-size.mjs';
|
|
8
8
|
import { p as prettyBytes } from '../_chunks/_deps/pretty-bytes.mjs';
|
|
9
9
|
import { a } from '../_chunks/_deps/std-env.mjs';
|
|
10
|
-
import { r as runParallel } from '../_chunks/
|
|
10
|
+
import { r as runParallel } from '../_chunks/builder.mjs';
|
|
11
11
|
import { mkdir, writeFile } from 'node:fs/promises';
|
|
12
12
|
import { a as snapshotStorage } from './prepare.mjs';
|
|
13
13
|
|
package/dist/_build/vite.mjs
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import '
|
|
3
|
-
import {
|
|
1
|
+
import { e as copyPublicAssets, s as scanHandlers, h as prettyPath, p as prepare, c as createNitro } from './prepare.mjs';
|
|
2
|
+
import consola from 'consola';
|
|
3
|
+
import { existsSync, watch as watch$1 } from 'node:fs';
|
|
4
4
|
import { defu } from 'defu';
|
|
5
|
-
import '../_chunks/_deps/mime.mjs';
|
|
6
5
|
import 'ufo';
|
|
7
|
-
import {
|
|
6
|
+
import { runtimeDir, runtimeDependencies } from 'nitro/runtime/meta';
|
|
7
|
+
import { r as resolveModulePath } from '../_chunks/_deps/exsolve.mjs';
|
|
8
8
|
import { readFile, rm, mkdir, writeFile, readlink } from 'node:fs/promises';
|
|
9
9
|
import 'node:zlib';
|
|
10
|
+
import '../_chunks/_deps/mime.mjs';
|
|
10
11
|
import 'node:worker_threads';
|
|
11
|
-
import consola from 'consola';
|
|
12
12
|
import 'h3';
|
|
13
13
|
import 'undici';
|
|
14
14
|
import 'nitro/meta';
|
|
15
15
|
import { NodeRequest, sendNodeResponse } from 'srvx/node';
|
|
16
16
|
import { a as NodeDevWorker, N as NitroDevApp } from '../_chunks/app.mjs';
|
|
17
|
-
import
|
|
18
|
-
import {
|
|
17
|
+
import 'node:url';
|
|
18
|
+
import { colors } from 'consola/utils';
|
|
19
19
|
import 'ofetch';
|
|
20
20
|
import { s as sanitizeFilePath } from '../_chunks/_deps/mlly.mjs';
|
|
21
21
|
import { a as alias } from '../_chunks/_deps/@rollup/plugin-alias.mjs';
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { pathToFileURL } from 'node:url';
|
|
3
|
-
import { colors } from 'consola/utils';
|
|
4
|
-
import { defu } from 'defu';
|
|
5
|
-
import { m as mime } from './_deps/mime.mjs';
|
|
6
|
-
import { a as addRoute, f as findAllRoutes, c as createRouter } from './_deps/rou3.mjs';
|
|
7
|
-
import { parseURL, withTrailingSlash, withBase, joinURL, withoutBase } from 'ufo';
|
|
8
|
-
import { z, P } from './_deps/ultrahtml.mjs';
|
|
9
|
-
import { a as relative, r as resolve, j as join, c as resolveAlias, i as isAbsolute, d as dirname } from './_deps/pathe.mjs';
|
|
10
|
-
import './server.mjs';
|
|
1
|
+
import { r as resolveNitroPath, i as isDirectory, w as writeFile, c as createNitro, b as scanUnprefixedPublicAssets, d as compressPublicAssets } from '../_build/prepare.mjs';
|
|
11
2
|
import { existsSync, promises } from 'node:fs';
|
|
3
|
+
import { defu } from 'defu';
|
|
12
4
|
import { i as parseNodeModulePath, l as lookupNodeModuleSubpath } from './_deps/mlly.mjs';
|
|
13
5
|
import { r as resolveModulePath } from './_deps/exsolve.mjs';
|
|
14
6
|
import { runtimeDir } from 'nitro/runtime/meta';
|
|
7
|
+
import { r as resolve, a as relative, c as resolveAlias, i as isAbsolute, j as join, d as dirname } from './_deps/pathe.mjs';
|
|
15
8
|
import { g as generateTypes, r as resolveSchema } from './_deps/untyped.mjs';
|
|
16
9
|
import { t as toExports } from './_deps/unimport.mjs';
|
|
10
|
+
import './server.mjs';
|
|
11
|
+
import { pathToFileURL } from 'node:url';
|
|
12
|
+
import { colors } from 'consola/utils';
|
|
13
|
+
import { m as mime } from './_deps/mime.mjs';
|
|
14
|
+
import { a as addRoute, f as findAllRoutes, c as createRouter } from './_deps/rou3.mjs';
|
|
15
|
+
import { parseURL, withTrailingSlash, withBase, joinURL, withoutBase } from 'ufo';
|
|
16
|
+
import { z, P } from './_deps/ultrahtml.mjs';
|
|
17
17
|
|
|
18
18
|
async function build(nitro) {
|
|
19
19
|
switch (nitro.options.builder) {
|
|
@@ -35,431 +35,78 @@ async function build(nitro) {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
async function
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const task = (opts.interval ? new Promise((resolve) => setTimeout(resolve, opts.interval)) : Promise.resolve()).then(() => cb(route)).catch((error) => {
|
|
47
|
-
console.error(error);
|
|
48
|
-
});
|
|
49
|
-
tasks.add(task);
|
|
50
|
-
return task.then(() => {
|
|
51
|
-
tasks.delete(task);
|
|
52
|
-
if (inputs.size > 0) {
|
|
53
|
-
return refillQueue();
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
function refillQueue() {
|
|
58
|
-
const workers = Math.min(opts.concurrency - tasks.size, inputs.size);
|
|
59
|
-
return Promise.all(Array.from({ length: workers }, () => queueNext()));
|
|
60
|
-
}
|
|
61
|
-
await refillQueue();
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const allowedExtensions = /* @__PURE__ */ new Set(["", ".json"]);
|
|
65
|
-
const linkParents$1 = /* @__PURE__ */ new Map();
|
|
66
|
-
const HTML_ENTITIES = {
|
|
67
|
-
"<": "<",
|
|
68
|
-
">": ">",
|
|
69
|
-
"&": "&",
|
|
70
|
-
"'": "'",
|
|
71
|
-
""": '"'
|
|
72
|
-
};
|
|
73
|
-
function escapeHtml(text) {
|
|
74
|
-
return text.replace(
|
|
75
|
-
/&(lt|gt|amp|apos|quot);/g,
|
|
76
|
-
(ch) => HTML_ENTITIES[ch] || ch
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
async function extractLinks(html, from, res, crawlLinks) {
|
|
80
|
-
const links = [];
|
|
81
|
-
const _links = [];
|
|
82
|
-
if (crawlLinks) {
|
|
83
|
-
await z(P(html), (node) => {
|
|
84
|
-
if (!node.attributes?.href) {
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
const link = escapeHtml(node.attributes.href);
|
|
88
|
-
if (!decodeURIComponent(link).startsWith("#") && allowedExtensions.has(getExtension(link))) {
|
|
89
|
-
_links.push(link);
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
const header = res.headers.get("x-nitro-prerender") || "";
|
|
94
|
-
_links.push(...header.split(",").map((i) => decodeURIComponent(i.trim())));
|
|
95
|
-
for (const link of _links.filter(Boolean)) {
|
|
96
|
-
const _link = parseURL(link);
|
|
97
|
-
if (_link.protocol || _link.host) {
|
|
38
|
+
async function writeTypes(nitro) {
|
|
39
|
+
const types = {
|
|
40
|
+
routes: {}
|
|
41
|
+
};
|
|
42
|
+
const typesDir = resolve(nitro.options.buildDir, "types");
|
|
43
|
+
const middleware = [...nitro.scannedHandlers, ...nitro.options.handlers];
|
|
44
|
+
for (const mw of middleware) {
|
|
45
|
+
if (typeof mw.handler !== "string" || !mw.route) {
|
|
98
46
|
continue;
|
|
99
47
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
_parents.add(from);
|
|
110
|
-
} else {
|
|
111
|
-
linkParents$1.set(link, /* @__PURE__ */ new Set([from]));
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
return links;
|
|
115
|
-
}
|
|
116
|
-
const EXT_REGEX = /\.[\da-z]+$/;
|
|
117
|
-
function getExtension(link) {
|
|
118
|
-
const pathname = parseURL(link).pathname;
|
|
119
|
-
return (pathname.match(EXT_REGEX) || [])[0] || "";
|
|
120
|
-
}
|
|
121
|
-
function formatPrerenderRoute(route) {
|
|
122
|
-
let str = ` \u251C\u2500 ${route.route} (${route.generateTimeMS}ms)`;
|
|
123
|
-
if (route.error) {
|
|
124
|
-
const parents = linkParents$1.get(route.route);
|
|
125
|
-
const errorColor = colors[route.error.status === 404 ? "yellow" : "red"];
|
|
126
|
-
const errorLead = parents?.size ? "\u251C\u2500\u2500" : "\u2514\u2500\u2500";
|
|
127
|
-
str += `
|
|
128
|
-
\u2502 ${errorLead} ${errorColor(route.error.message)}`;
|
|
129
|
-
if (parents?.size) {
|
|
130
|
-
str += `
|
|
131
|
-
${[...parents.values()].map((link) => ` \u2502 \u2514\u2500\u2500 Linked from ${link}`).join("\n")}`;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
if (route.skip) {
|
|
135
|
-
str += colors.gray(" (skipped)");
|
|
136
|
-
}
|
|
137
|
-
return colors.gray(str);
|
|
138
|
-
}
|
|
139
|
-
function matchesIgnorePattern(path, pattern) {
|
|
140
|
-
if (typeof pattern === "string") {
|
|
141
|
-
return path.startsWith(pattern);
|
|
142
|
-
}
|
|
143
|
-
if (typeof pattern === "function") {
|
|
144
|
-
return pattern(path) === true;
|
|
145
|
-
}
|
|
146
|
-
if (pattern instanceof RegExp) {
|
|
147
|
-
return pattern.test(path);
|
|
148
|
-
}
|
|
149
|
-
return false;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
const JsonSigRx = /^\s*["[{]|^\s*-?\d{1,16}(\.\d{1,17})?([Ee][+-]?\d+)?\s*$/;
|
|
153
|
-
const linkParents = /* @__PURE__ */ new Map();
|
|
154
|
-
async function prerender(nitro) {
|
|
155
|
-
if (nitro.options.noPublicDir) {
|
|
156
|
-
nitro.logger.warn(
|
|
157
|
-
"Skipping prerender since `noPublicDir` option is enabled."
|
|
48
|
+
const relativePath = relative(
|
|
49
|
+
typesDir,
|
|
50
|
+
resolveNitroPath(mw.handler, nitro.options)
|
|
51
|
+
).replace(/\.(js|mjs|cjs|ts|mts|cts|tsx|jsx)$/, "");
|
|
52
|
+
const method = mw.method || "default";
|
|
53
|
+
types.routes[mw.route] ??= {};
|
|
54
|
+
types.routes[mw.route][method] ??= [];
|
|
55
|
+
types.routes[mw.route][method].push(
|
|
56
|
+
`Simplify<Serialize<Awaited<ReturnType<typeof import('${relativePath}').default>>>>`
|
|
158
57
|
);
|
|
159
|
-
return;
|
|
160
58
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
59
|
+
let autoImportedTypes = [];
|
|
60
|
+
let autoImportExports = "";
|
|
61
|
+
if (nitro.unimport) {
|
|
62
|
+
await nitro.unimport.init();
|
|
63
|
+
const allImports = await nitro.unimport.getImports();
|
|
64
|
+
autoImportExports = toExports(allImports).replace(
|
|
65
|
+
/#internal\/nitro/g,
|
|
66
|
+
relative(typesDir, runtimeDir)
|
|
164
67
|
);
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
68
|
+
const resolvedImportPathMap = /* @__PURE__ */ new Map();
|
|
69
|
+
for (const i of allImports) {
|
|
70
|
+
const from = i.typeFrom || i.from;
|
|
71
|
+
if (resolvedImportPathMap.has(from)) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
let path = resolveAlias(from, nitro.options.alias);
|
|
75
|
+
if (!isAbsolute(path)) {
|
|
76
|
+
const resolvedPath = resolveModulePath(from, {
|
|
77
|
+
try: true,
|
|
78
|
+
from: nitro.options.nodeModulesDirs,
|
|
79
|
+
conditions: ["type", "node", "import"],
|
|
80
|
+
suffixes: ["", "/index"],
|
|
81
|
+
extensions: [".mjs", ".cjs", ".js", ".mts", ".cts", ".ts"]
|
|
82
|
+
});
|
|
83
|
+
if (resolvedPath) {
|
|
84
|
+
const { dir, name } = parseNodeModulePath(resolvedPath);
|
|
85
|
+
if (!dir || !name) {
|
|
86
|
+
path = resolvedPath;
|
|
87
|
+
} else {
|
|
88
|
+
const subpath = await lookupNodeModuleSubpath(resolvedPath);
|
|
89
|
+
path = join(dir, name, subpath || "");
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (existsSync(path) && !await isDirectory(path)) {
|
|
94
|
+
path = path.replace(/\.[a-z]+$/, "");
|
|
95
|
+
}
|
|
96
|
+
if (isAbsolute(path)) {
|
|
97
|
+
path = relative(typesDir, path);
|
|
98
|
+
}
|
|
99
|
+
resolvedImportPathMap.set(from, path);
|
|
178
100
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
preset: "nitro-prerender"
|
|
189
|
-
};
|
|
190
|
-
await nitro.hooks.callHook("prerender:config", prerendererConfig);
|
|
191
|
-
const nitroRenderer = await createNitro(prerendererConfig);
|
|
192
|
-
const prerenderStartTime = Date.now();
|
|
193
|
-
await nitro.hooks.callHook("prerender:init", nitroRenderer);
|
|
194
|
-
let path = relative(nitro.options.output.dir, nitro.options.output.publicDir);
|
|
195
|
-
if (!path.startsWith(".")) {
|
|
196
|
-
path = `./${path}`;
|
|
197
|
-
}
|
|
198
|
-
nitroRenderer.options.commands.preview = `npx serve ${path}`;
|
|
199
|
-
nitroRenderer.options.output.dir = nitro.options.output.dir;
|
|
200
|
-
await build(nitroRenderer);
|
|
201
|
-
const serverFilename = typeof nitroRenderer.options.rollupConfig?.output?.entryFileNames === "string" ? nitroRenderer.options.rollupConfig.output.entryFileNames : "index.mjs";
|
|
202
|
-
const serverEntrypoint = resolve(
|
|
203
|
-
nitroRenderer.options.output.serverDir,
|
|
204
|
-
serverFilename
|
|
205
|
-
);
|
|
206
|
-
const { closePrerenderer, appFetch } = await import(pathToFileURL(serverEntrypoint).href);
|
|
207
|
-
const routeRules = createRouter();
|
|
208
|
-
for (const [route, rules] of Object.entries(nitro.options.routeRules)) {
|
|
209
|
-
addRoute(routeRules, void 0, route, rules);
|
|
210
|
-
}
|
|
211
|
-
const _getRouteRules = (path2) => defu(
|
|
212
|
-
{},
|
|
213
|
-
...findAllRoutes(routeRules, void 0, path2).map((r) => r.data).reverse()
|
|
214
|
-
);
|
|
215
|
-
const generatedRoutes = /* @__PURE__ */ new Set();
|
|
216
|
-
const failedRoutes = /* @__PURE__ */ new Set();
|
|
217
|
-
const skippedRoutes = /* @__PURE__ */ new Set();
|
|
218
|
-
const displayedLengthWarns = /* @__PURE__ */ new Set();
|
|
219
|
-
const publicAssetBases = nitro.options.publicAssets.filter(
|
|
220
|
-
(a) => !!a.baseURL && a.baseURL !== "/" && !a.fallthrough
|
|
221
|
-
).map((a) => withTrailingSlash(a.baseURL));
|
|
222
|
-
const scannedPublicAssets = nitro.options.prerender.ignoreUnprefixedPublicAssets ? new Set(await scanUnprefixedPublicAssets(nitro)) : /* @__PURE__ */ new Set();
|
|
223
|
-
const canPrerender = (route = "/") => {
|
|
224
|
-
if (generatedRoutes.has(route) || skippedRoutes.has(route)) {
|
|
225
|
-
return false;
|
|
226
|
-
}
|
|
227
|
-
for (const pattern of nitro.options.prerender.ignore) {
|
|
228
|
-
if (matchesIgnorePattern(route, pattern)) {
|
|
229
|
-
return false;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
if (publicAssetBases.some((base) => route.startsWith(base))) {
|
|
233
|
-
return false;
|
|
234
|
-
}
|
|
235
|
-
if (scannedPublicAssets.has(route)) {
|
|
236
|
-
return false;
|
|
237
|
-
}
|
|
238
|
-
if (_getRouteRules(route).prerender === false) {
|
|
239
|
-
return false;
|
|
240
|
-
}
|
|
241
|
-
return true;
|
|
242
|
-
};
|
|
243
|
-
const canWriteToDisk = (route) => {
|
|
244
|
-
if (route.route.includes("?")) {
|
|
245
|
-
return false;
|
|
246
|
-
}
|
|
247
|
-
const FS_MAX_SEGMENT = 255;
|
|
248
|
-
const FS_MAX_PATH = 1024;
|
|
249
|
-
const FS_MAX_PATH_PUBLIC_HTML = FS_MAX_PATH - (nitro.options.output.publicDir.length + 10);
|
|
250
|
-
if ((route.route.length >= FS_MAX_PATH_PUBLIC_HTML || route.route.split("/").some((s) => s.length > FS_MAX_SEGMENT)) && !displayedLengthWarns.has(route)) {
|
|
251
|
-
displayedLengthWarns.add(route);
|
|
252
|
-
const _route = route.route.slice(0, 60) + "...";
|
|
253
|
-
if (route.route.length >= FS_MAX_PATH_PUBLIC_HTML) {
|
|
254
|
-
nitro.logger.warn(
|
|
255
|
-
`Prerendering long route "${_route}" (${route.route.length}) can cause filesystem issues since it exceeds ${FS_MAX_PATH_PUBLIC_HTML}-character limit when writing to \`${nitro.options.output.publicDir}\`.`
|
|
256
|
-
);
|
|
257
|
-
} else {
|
|
258
|
-
nitro.logger.warn(
|
|
259
|
-
`Skipping prerender of the route "${_route}" since it exceeds the ${FS_MAX_SEGMENT}-character limit in one of the path segments and can cause filesystem issues.`
|
|
260
|
-
);
|
|
261
|
-
return false;
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
return true;
|
|
265
|
-
};
|
|
266
|
-
const generateRoute = async (route) => {
|
|
267
|
-
const start = Date.now();
|
|
268
|
-
route = decodeURI(route);
|
|
269
|
-
if (!canPrerender(route)) {
|
|
270
|
-
skippedRoutes.add(route);
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
generatedRoutes.add(route);
|
|
274
|
-
const _route = { route };
|
|
275
|
-
const encodedRoute = encodeURI(route);
|
|
276
|
-
const res = await appFetch(withBase(encodedRoute, nitro.options.baseURL), {
|
|
277
|
-
headers: [["x-nitro-prerender", encodedRoute]]
|
|
278
|
-
// TODO
|
|
279
|
-
// retry: nitro.options.prerender.retry,
|
|
280
|
-
// retryDelay: nitro.options.prerender.retryDelay,
|
|
281
|
-
});
|
|
282
|
-
let dataBuff = Buffer.from(await res.arrayBuffer());
|
|
283
|
-
Object.defineProperty(_route, "contents", {
|
|
284
|
-
get: () => {
|
|
285
|
-
return dataBuff ? dataBuff.toString("utf8") : void 0;
|
|
286
|
-
},
|
|
287
|
-
set(value) {
|
|
288
|
-
if (dataBuff) {
|
|
289
|
-
dataBuff = Buffer.from(value);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
});
|
|
293
|
-
Object.defineProperty(_route, "data", {
|
|
294
|
-
get: () => {
|
|
295
|
-
return dataBuff ? dataBuff.buffer : void 0;
|
|
296
|
-
},
|
|
297
|
-
set(value) {
|
|
298
|
-
if (dataBuff) {
|
|
299
|
-
dataBuff = Buffer.from(value);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
});
|
|
303
|
-
const redirectCodes = [301, 302, 303, 304, 307, 308];
|
|
304
|
-
if (![200, ...redirectCodes].includes(res.status)) {
|
|
305
|
-
_route.error = new Error(`[${res.status}] ${res.statusText}`);
|
|
306
|
-
_route.error.status = res.status;
|
|
307
|
-
_route.error.statusText = res.statusText;
|
|
308
|
-
}
|
|
309
|
-
_route.generateTimeMS = Date.now() - start;
|
|
310
|
-
const contentType = res.headers.get("content-type") || "";
|
|
311
|
-
const isImplicitHTML = !route.endsWith(".html") && contentType.includes("html") && !JsonSigRx.test(dataBuff.subarray(0, 32).toString("utf8"));
|
|
312
|
-
const routeWithIndex = route.endsWith("/") ? route + "index" : route;
|
|
313
|
-
const htmlPath = route.endsWith("/") || nitro.options.prerender.autoSubfolderIndex ? joinURL(route, "index.html") : route + ".html";
|
|
314
|
-
_route.fileName = withoutBase(
|
|
315
|
-
isImplicitHTML ? htmlPath : routeWithIndex,
|
|
316
|
-
nitro.options.baseURL
|
|
317
|
-
);
|
|
318
|
-
const inferredContentType = mime.getType(_route.fileName) || "text/plain";
|
|
319
|
-
_route.contentType = contentType || inferredContentType;
|
|
320
|
-
await nitro.hooks.callHook("prerender:generate", _route, nitro);
|
|
321
|
-
if (_route.contentType !== inferredContentType) {
|
|
322
|
-
nitro._prerenderMeta[_route.fileName] ||= {};
|
|
323
|
-
nitro._prerenderMeta[_route.fileName].contentType = _route.contentType;
|
|
324
|
-
}
|
|
325
|
-
if (_route.error) {
|
|
326
|
-
failedRoutes.add(_route);
|
|
327
|
-
}
|
|
328
|
-
if (_route.skip || _route.error) {
|
|
329
|
-
await nitro.hooks.callHook("prerender:route", _route);
|
|
330
|
-
nitro.logger.log(formatPrerenderRoute(_route));
|
|
331
|
-
dataBuff = void 0;
|
|
332
|
-
return _route;
|
|
333
|
-
}
|
|
334
|
-
if (canWriteToDisk(_route)) {
|
|
335
|
-
const filePath = join(nitro.options.output.publicDir, _route.fileName);
|
|
336
|
-
await writeFile(filePath, dataBuff);
|
|
337
|
-
nitro._prerenderedRoutes.push(_route);
|
|
338
|
-
} else {
|
|
339
|
-
_route.skip = true;
|
|
340
|
-
}
|
|
341
|
-
if (!_route.error && (isImplicitHTML || route.endsWith(".html"))) {
|
|
342
|
-
const extractedLinks = await extractLinks(
|
|
343
|
-
dataBuff.toString("utf8"),
|
|
344
|
-
route,
|
|
345
|
-
res,
|
|
346
|
-
nitro.options.prerender.crawlLinks
|
|
347
|
-
);
|
|
348
|
-
for (const _link of extractedLinks) {
|
|
349
|
-
if (canPrerender(_link)) {
|
|
350
|
-
routes.add(_link);
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
await nitro.hooks.callHook("prerender:route", _route);
|
|
355
|
-
nitro.logger.log(formatPrerenderRoute(_route));
|
|
356
|
-
dataBuff = void 0;
|
|
357
|
-
return _route;
|
|
358
|
-
};
|
|
359
|
-
nitro.logger.info(
|
|
360
|
-
nitro.options.prerender.crawlLinks ? `Prerendering ${routes.size} initial routes with crawler` : `Prerendering ${routes.size} routes`
|
|
361
|
-
);
|
|
362
|
-
await runParallel(routes, generateRoute, {
|
|
363
|
-
concurrency: nitro.options.prerender.concurrency,
|
|
364
|
-
interval: nitro.options.prerender.interval
|
|
365
|
-
});
|
|
366
|
-
await closePrerenderer();
|
|
367
|
-
await nitro.hooks.callHook("prerender:done", {
|
|
368
|
-
prerenderedRoutes: nitro._prerenderedRoutes,
|
|
369
|
-
failedRoutes: [...failedRoutes]
|
|
370
|
-
});
|
|
371
|
-
if (nitro.options.prerender.failOnError && failedRoutes.size > 0) {
|
|
372
|
-
nitro.logger.log("\nErrors prerendering:");
|
|
373
|
-
for (const route of failedRoutes) {
|
|
374
|
-
const parents = linkParents.get(route.route);
|
|
375
|
-
parents?.size ? `
|
|
376
|
-
${[...parents.values()].map((link) => colors.gray(` \u2502 \u2514\u2500\u2500 Linked from ${link}`)).join("\n")}` : "";
|
|
377
|
-
nitro.logger.log(formatPrerenderRoute(route));
|
|
378
|
-
}
|
|
379
|
-
nitro.logger.log("");
|
|
380
|
-
throw new Error("Exiting due to prerender errors.");
|
|
381
|
-
}
|
|
382
|
-
const prerenderTimeInMs = Date.now() - prerenderStartTime;
|
|
383
|
-
nitro.logger.info(
|
|
384
|
-
`Prerendered ${nitro._prerenderedRoutes.length} routes in ${prerenderTimeInMs / 1e3} seconds`
|
|
385
|
-
);
|
|
386
|
-
if (nitro.options.compressPublicAssets) {
|
|
387
|
-
await compressPublicAssets(nitro);
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
async function writeTypes(nitro) {
|
|
392
|
-
const types = {
|
|
393
|
-
routes: {}
|
|
394
|
-
};
|
|
395
|
-
const typesDir = resolve(nitro.options.buildDir, "types");
|
|
396
|
-
const middleware = [...nitro.scannedHandlers, ...nitro.options.handlers];
|
|
397
|
-
for (const mw of middleware) {
|
|
398
|
-
if (typeof mw.handler !== "string" || !mw.route) {
|
|
399
|
-
continue;
|
|
400
|
-
}
|
|
401
|
-
const relativePath = relative(
|
|
402
|
-
typesDir,
|
|
403
|
-
resolveNitroPath(mw.handler, nitro.options)
|
|
404
|
-
).replace(/\.(js|mjs|cjs|ts|mts|cts|tsx|jsx)$/, "");
|
|
405
|
-
const method = mw.method || "default";
|
|
406
|
-
types.routes[mw.route] ??= {};
|
|
407
|
-
types.routes[mw.route][method] ??= [];
|
|
408
|
-
types.routes[mw.route][method].push(
|
|
409
|
-
`Simplify<Serialize<Awaited<ReturnType<typeof import('${relativePath}').default>>>>`
|
|
410
|
-
);
|
|
411
|
-
}
|
|
412
|
-
let autoImportedTypes = [];
|
|
413
|
-
let autoImportExports = "";
|
|
414
|
-
if (nitro.unimport) {
|
|
415
|
-
await nitro.unimport.init();
|
|
416
|
-
const allImports = await nitro.unimport.getImports();
|
|
417
|
-
autoImportExports = toExports(allImports).replace(
|
|
418
|
-
/#internal\/nitro/g,
|
|
419
|
-
relative(typesDir, runtimeDir)
|
|
420
|
-
);
|
|
421
|
-
const resolvedImportPathMap = /* @__PURE__ */ new Map();
|
|
422
|
-
for (const i of allImports) {
|
|
423
|
-
const from = i.typeFrom || i.from;
|
|
424
|
-
if (resolvedImportPathMap.has(from)) {
|
|
425
|
-
continue;
|
|
426
|
-
}
|
|
427
|
-
let path = resolveAlias(from, nitro.options.alias);
|
|
428
|
-
if (!isAbsolute(path)) {
|
|
429
|
-
const resolvedPath = resolveModulePath(from, {
|
|
430
|
-
try: true,
|
|
431
|
-
from: nitro.options.nodeModulesDirs,
|
|
432
|
-
conditions: ["type", "node", "import"],
|
|
433
|
-
suffixes: ["", "/index"],
|
|
434
|
-
extensions: [".mjs", ".cjs", ".js", ".mts", ".cts", ".ts"]
|
|
435
|
-
});
|
|
436
|
-
if (resolvedPath) {
|
|
437
|
-
const { dir, name } = parseNodeModulePath(resolvedPath);
|
|
438
|
-
if (!dir || !name) {
|
|
439
|
-
path = resolvedPath;
|
|
440
|
-
} else {
|
|
441
|
-
const subpath = await lookupNodeModuleSubpath(resolvedPath);
|
|
442
|
-
path = join(dir, name, subpath || "");
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
if (existsSync(path) && !await isDirectory(path)) {
|
|
447
|
-
path = path.replace(/\.[a-z]+$/, "");
|
|
448
|
-
}
|
|
449
|
-
if (isAbsolute(path)) {
|
|
450
|
-
path = relative(typesDir, path);
|
|
451
|
-
}
|
|
452
|
-
resolvedImportPathMap.set(from, path);
|
|
453
|
-
}
|
|
454
|
-
autoImportedTypes = [
|
|
455
|
-
nitro.options.imports && nitro.options.imports.autoImport !== false ? (await nitro.unimport.generateTypeDeclarations({
|
|
456
|
-
exportHelper: false,
|
|
457
|
-
resolvePath: (i) => {
|
|
458
|
-
const from = i.typeFrom || i.from;
|
|
459
|
-
return resolvedImportPathMap.get(from) ?? from;
|
|
460
|
-
}
|
|
461
|
-
})).trim() : ""
|
|
462
|
-
];
|
|
101
|
+
autoImportedTypes = [
|
|
102
|
+
nitro.options.imports && nitro.options.imports.autoImport !== false ? (await nitro.unimport.generateTypeDeclarations({
|
|
103
|
+
exportHelper: false,
|
|
104
|
+
resolvePath: (i) => {
|
|
105
|
+
const from = i.typeFrom || i.from;
|
|
106
|
+
return resolvedImportPathMap.get(from) ?? from;
|
|
107
|
+
}
|
|
108
|
+
})).trim() : ""
|
|
109
|
+
];
|
|
463
110
|
}
|
|
464
111
|
const generateRoutes = () => [
|
|
465
112
|
"// Generated by nitro",
|
|
@@ -645,4 +292,357 @@ function relativeWithDot(from, to) {
|
|
|
645
292
|
return RELATIVE_RE.test(rel) ? rel : "./" + rel;
|
|
646
293
|
}
|
|
647
294
|
|
|
295
|
+
async function runParallel(inputs, cb, opts) {
|
|
296
|
+
const tasks = /* @__PURE__ */ new Set();
|
|
297
|
+
function queueNext() {
|
|
298
|
+
const route = inputs.values().next().value;
|
|
299
|
+
if (!route) {
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
inputs.delete(route);
|
|
303
|
+
const task = (opts.interval ? new Promise((resolve) => setTimeout(resolve, opts.interval)) : Promise.resolve()).then(() => cb(route)).catch((error) => {
|
|
304
|
+
console.error(error);
|
|
305
|
+
});
|
|
306
|
+
tasks.add(task);
|
|
307
|
+
return task.then(() => {
|
|
308
|
+
tasks.delete(task);
|
|
309
|
+
if (inputs.size > 0) {
|
|
310
|
+
return refillQueue();
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
function refillQueue() {
|
|
315
|
+
const workers = Math.min(opts.concurrency - tasks.size, inputs.size);
|
|
316
|
+
return Promise.all(Array.from({ length: workers }, () => queueNext()));
|
|
317
|
+
}
|
|
318
|
+
await refillQueue();
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const allowedExtensions = /* @__PURE__ */ new Set(["", ".json"]);
|
|
322
|
+
const linkParents$1 = /* @__PURE__ */ new Map();
|
|
323
|
+
const HTML_ENTITIES = {
|
|
324
|
+
"<": "<",
|
|
325
|
+
">": ">",
|
|
326
|
+
"&": "&",
|
|
327
|
+
"'": "'",
|
|
328
|
+
""": '"'
|
|
329
|
+
};
|
|
330
|
+
function escapeHtml(text) {
|
|
331
|
+
return text.replace(
|
|
332
|
+
/&(lt|gt|amp|apos|quot);/g,
|
|
333
|
+
(ch) => HTML_ENTITIES[ch] || ch
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
async function extractLinks(html, from, res, crawlLinks) {
|
|
337
|
+
const links = [];
|
|
338
|
+
const _links = [];
|
|
339
|
+
if (crawlLinks) {
|
|
340
|
+
await z(P(html), (node) => {
|
|
341
|
+
if (!node.attributes?.href) {
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
const link = escapeHtml(node.attributes.href);
|
|
345
|
+
if (!decodeURIComponent(link).startsWith("#") && allowedExtensions.has(getExtension(link))) {
|
|
346
|
+
_links.push(link);
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
const header = res.headers.get("x-nitro-prerender") || "";
|
|
351
|
+
_links.push(...header.split(",").map((i) => decodeURIComponent(i.trim())));
|
|
352
|
+
for (const link of _links.filter(Boolean)) {
|
|
353
|
+
const _link = parseURL(link);
|
|
354
|
+
if (_link.protocol || _link.host) {
|
|
355
|
+
continue;
|
|
356
|
+
}
|
|
357
|
+
if (!_link.pathname.startsWith("/")) {
|
|
358
|
+
const fromURL = new URL(from, "http://localhost");
|
|
359
|
+
_link.pathname = new URL(_link.pathname, fromURL).pathname;
|
|
360
|
+
}
|
|
361
|
+
links.push(_link.pathname + _link.search);
|
|
362
|
+
}
|
|
363
|
+
for (const link of links) {
|
|
364
|
+
const _parents = linkParents$1.get(link);
|
|
365
|
+
if (_parents) {
|
|
366
|
+
_parents.add(from);
|
|
367
|
+
} else {
|
|
368
|
+
linkParents$1.set(link, /* @__PURE__ */ new Set([from]));
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
return links;
|
|
372
|
+
}
|
|
373
|
+
const EXT_REGEX = /\.[\da-z]+$/;
|
|
374
|
+
function getExtension(link) {
|
|
375
|
+
const pathname = parseURL(link).pathname;
|
|
376
|
+
return (pathname.match(EXT_REGEX) || [])[0] || "";
|
|
377
|
+
}
|
|
378
|
+
function formatPrerenderRoute(route) {
|
|
379
|
+
let str = ` \u251C\u2500 ${route.route} (${route.generateTimeMS}ms)`;
|
|
380
|
+
if (route.error) {
|
|
381
|
+
const parents = linkParents$1.get(route.route);
|
|
382
|
+
const errorColor = colors[route.error.status === 404 ? "yellow" : "red"];
|
|
383
|
+
const errorLead = parents?.size ? "\u251C\u2500\u2500" : "\u2514\u2500\u2500";
|
|
384
|
+
str += `
|
|
385
|
+
\u2502 ${errorLead} ${errorColor(route.error.message)}`;
|
|
386
|
+
if (parents?.size) {
|
|
387
|
+
str += `
|
|
388
|
+
${[...parents.values()].map((link) => ` \u2502 \u2514\u2500\u2500 Linked from ${link}`).join("\n")}`;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
if (route.skip) {
|
|
392
|
+
str += colors.gray(" (skipped)");
|
|
393
|
+
}
|
|
394
|
+
return colors.gray(str);
|
|
395
|
+
}
|
|
396
|
+
function matchesIgnorePattern(path, pattern) {
|
|
397
|
+
if (typeof pattern === "string") {
|
|
398
|
+
return path.startsWith(pattern);
|
|
399
|
+
}
|
|
400
|
+
if (typeof pattern === "function") {
|
|
401
|
+
return pattern(path) === true;
|
|
402
|
+
}
|
|
403
|
+
if (pattern instanceof RegExp) {
|
|
404
|
+
return pattern.test(path);
|
|
405
|
+
}
|
|
406
|
+
return false;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
const JsonSigRx = /^\s*["[{]|^\s*-?\d{1,16}(\.\d{1,17})?([Ee][+-]?\d+)?\s*$/;
|
|
410
|
+
const linkParents = /* @__PURE__ */ new Map();
|
|
411
|
+
async function prerender(nitro) {
|
|
412
|
+
if (nitro.options.noPublicDir) {
|
|
413
|
+
nitro.logger.warn(
|
|
414
|
+
"Skipping prerender since `noPublicDir` option is enabled."
|
|
415
|
+
);
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
if (nitro.options.builder === "vite") {
|
|
419
|
+
nitro.logger.warn(
|
|
420
|
+
"Skipping prerender since not supported with vite builder yet..."
|
|
421
|
+
);
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
const routes = new Set(nitro.options.prerender.routes);
|
|
425
|
+
const prerenderRulePaths = Object.entries(nitro.options.routeRules).filter(([path2, options]) => options.prerender && !path2.includes("*")).map((e) => e[0]);
|
|
426
|
+
for (const route of prerenderRulePaths) {
|
|
427
|
+
routes.add(route);
|
|
428
|
+
}
|
|
429
|
+
await nitro.hooks.callHook("prerender:routes", routes);
|
|
430
|
+
if (routes.size === 0) {
|
|
431
|
+
if (nitro.options.prerender.crawlLinks) {
|
|
432
|
+
routes.add("/");
|
|
433
|
+
} else {
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
nitro.logger.info("Initializing prerenderer");
|
|
438
|
+
nitro._prerenderedRoutes = [];
|
|
439
|
+
nitro._prerenderMeta = nitro._prerenderMeta || {};
|
|
440
|
+
const prerendererConfig = {
|
|
441
|
+
...nitro.options._config,
|
|
442
|
+
static: false,
|
|
443
|
+
rootDir: nitro.options.rootDir,
|
|
444
|
+
logLevel: 0,
|
|
445
|
+
preset: "nitro-prerender"
|
|
446
|
+
};
|
|
447
|
+
await nitro.hooks.callHook("prerender:config", prerendererConfig);
|
|
448
|
+
const nitroRenderer = await createNitro(prerendererConfig);
|
|
449
|
+
const prerenderStartTime = Date.now();
|
|
450
|
+
await nitro.hooks.callHook("prerender:init", nitroRenderer);
|
|
451
|
+
let path = relative(nitro.options.output.dir, nitro.options.output.publicDir);
|
|
452
|
+
if (!path.startsWith(".")) {
|
|
453
|
+
path = `./${path}`;
|
|
454
|
+
}
|
|
455
|
+
nitroRenderer.options.commands.preview = `npx serve ${path}`;
|
|
456
|
+
nitroRenderer.options.output.dir = nitro.options.output.dir;
|
|
457
|
+
await build(nitroRenderer);
|
|
458
|
+
const serverFilename = typeof nitroRenderer.options.rollupConfig?.output?.entryFileNames === "string" ? nitroRenderer.options.rollupConfig.output.entryFileNames : "index.mjs";
|
|
459
|
+
const serverEntrypoint = resolve(
|
|
460
|
+
nitroRenderer.options.output.serverDir,
|
|
461
|
+
serverFilename
|
|
462
|
+
);
|
|
463
|
+
const { closePrerenderer, appFetch } = await import(pathToFileURL(serverEntrypoint).href);
|
|
464
|
+
const routeRules = createRouter();
|
|
465
|
+
for (const [route, rules] of Object.entries(nitro.options.routeRules)) {
|
|
466
|
+
addRoute(routeRules, void 0, route, rules);
|
|
467
|
+
}
|
|
468
|
+
const _getRouteRules = (path2) => defu(
|
|
469
|
+
{},
|
|
470
|
+
...findAllRoutes(routeRules, void 0, path2).map((r) => r.data).reverse()
|
|
471
|
+
);
|
|
472
|
+
const generatedRoutes = /* @__PURE__ */ new Set();
|
|
473
|
+
const failedRoutes = /* @__PURE__ */ new Set();
|
|
474
|
+
const skippedRoutes = /* @__PURE__ */ new Set();
|
|
475
|
+
const displayedLengthWarns = /* @__PURE__ */ new Set();
|
|
476
|
+
const publicAssetBases = nitro.options.publicAssets.filter(
|
|
477
|
+
(a) => !!a.baseURL && a.baseURL !== "/" && !a.fallthrough
|
|
478
|
+
).map((a) => withTrailingSlash(a.baseURL));
|
|
479
|
+
const scannedPublicAssets = nitro.options.prerender.ignoreUnprefixedPublicAssets ? new Set(await scanUnprefixedPublicAssets(nitro)) : /* @__PURE__ */ new Set();
|
|
480
|
+
const canPrerender = (route = "/") => {
|
|
481
|
+
if (generatedRoutes.has(route) || skippedRoutes.has(route)) {
|
|
482
|
+
return false;
|
|
483
|
+
}
|
|
484
|
+
for (const pattern of nitro.options.prerender.ignore) {
|
|
485
|
+
if (matchesIgnorePattern(route, pattern)) {
|
|
486
|
+
return false;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
if (publicAssetBases.some((base) => route.startsWith(base))) {
|
|
490
|
+
return false;
|
|
491
|
+
}
|
|
492
|
+
if (scannedPublicAssets.has(route)) {
|
|
493
|
+
return false;
|
|
494
|
+
}
|
|
495
|
+
if (_getRouteRules(route).prerender === false) {
|
|
496
|
+
return false;
|
|
497
|
+
}
|
|
498
|
+
return true;
|
|
499
|
+
};
|
|
500
|
+
const canWriteToDisk = (route) => {
|
|
501
|
+
if (route.route.includes("?")) {
|
|
502
|
+
return false;
|
|
503
|
+
}
|
|
504
|
+
const FS_MAX_SEGMENT = 255;
|
|
505
|
+
const FS_MAX_PATH = 1024;
|
|
506
|
+
const FS_MAX_PATH_PUBLIC_HTML = FS_MAX_PATH - (nitro.options.output.publicDir.length + 10);
|
|
507
|
+
if ((route.route.length >= FS_MAX_PATH_PUBLIC_HTML || route.route.split("/").some((s) => s.length > FS_MAX_SEGMENT)) && !displayedLengthWarns.has(route)) {
|
|
508
|
+
displayedLengthWarns.add(route);
|
|
509
|
+
const _route = route.route.slice(0, 60) + "...";
|
|
510
|
+
if (route.route.length >= FS_MAX_PATH_PUBLIC_HTML) {
|
|
511
|
+
nitro.logger.warn(
|
|
512
|
+
`Prerendering long route "${_route}" (${route.route.length}) can cause filesystem issues since it exceeds ${FS_MAX_PATH_PUBLIC_HTML}-character limit when writing to \`${nitro.options.output.publicDir}\`.`
|
|
513
|
+
);
|
|
514
|
+
} else {
|
|
515
|
+
nitro.logger.warn(
|
|
516
|
+
`Skipping prerender of the route "${_route}" since it exceeds the ${FS_MAX_SEGMENT}-character limit in one of the path segments and can cause filesystem issues.`
|
|
517
|
+
);
|
|
518
|
+
return false;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
return true;
|
|
522
|
+
};
|
|
523
|
+
const generateRoute = async (route) => {
|
|
524
|
+
const start = Date.now();
|
|
525
|
+
route = decodeURI(route);
|
|
526
|
+
if (!canPrerender(route)) {
|
|
527
|
+
skippedRoutes.add(route);
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
530
|
+
generatedRoutes.add(route);
|
|
531
|
+
const _route = { route };
|
|
532
|
+
const encodedRoute = encodeURI(route);
|
|
533
|
+
const res = await appFetch(withBase(encodedRoute, nitro.options.baseURL), {
|
|
534
|
+
headers: [["x-nitro-prerender", encodedRoute]]
|
|
535
|
+
// TODO
|
|
536
|
+
// retry: nitro.options.prerender.retry,
|
|
537
|
+
// retryDelay: nitro.options.prerender.retryDelay,
|
|
538
|
+
});
|
|
539
|
+
let dataBuff = Buffer.from(await res.arrayBuffer());
|
|
540
|
+
Object.defineProperty(_route, "contents", {
|
|
541
|
+
get: () => {
|
|
542
|
+
return dataBuff ? dataBuff.toString("utf8") : void 0;
|
|
543
|
+
},
|
|
544
|
+
set(value) {
|
|
545
|
+
if (dataBuff) {
|
|
546
|
+
dataBuff = Buffer.from(value);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
});
|
|
550
|
+
Object.defineProperty(_route, "data", {
|
|
551
|
+
get: () => {
|
|
552
|
+
return dataBuff ? dataBuff.buffer : void 0;
|
|
553
|
+
},
|
|
554
|
+
set(value) {
|
|
555
|
+
if (dataBuff) {
|
|
556
|
+
dataBuff = Buffer.from(value);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
});
|
|
560
|
+
const redirectCodes = [301, 302, 303, 304, 307, 308];
|
|
561
|
+
if (![200, ...redirectCodes].includes(res.status)) {
|
|
562
|
+
_route.error = new Error(`[${res.status}] ${res.statusText}`);
|
|
563
|
+
_route.error.status = res.status;
|
|
564
|
+
_route.error.statusText = res.statusText;
|
|
565
|
+
}
|
|
566
|
+
_route.generateTimeMS = Date.now() - start;
|
|
567
|
+
const contentType = res.headers.get("content-type") || "";
|
|
568
|
+
const isImplicitHTML = !route.endsWith(".html") && contentType.includes("html") && !JsonSigRx.test(dataBuff.subarray(0, 32).toString("utf8"));
|
|
569
|
+
const routeWithIndex = route.endsWith("/") ? route + "index" : route;
|
|
570
|
+
const htmlPath = route.endsWith("/") || nitro.options.prerender.autoSubfolderIndex ? joinURL(route, "index.html") : route + ".html";
|
|
571
|
+
_route.fileName = withoutBase(
|
|
572
|
+
isImplicitHTML ? htmlPath : routeWithIndex,
|
|
573
|
+
nitro.options.baseURL
|
|
574
|
+
);
|
|
575
|
+
const inferredContentType = mime.getType(_route.fileName) || "text/plain";
|
|
576
|
+
_route.contentType = contentType || inferredContentType;
|
|
577
|
+
await nitro.hooks.callHook("prerender:generate", _route, nitro);
|
|
578
|
+
if (_route.contentType !== inferredContentType) {
|
|
579
|
+
nitro._prerenderMeta[_route.fileName] ||= {};
|
|
580
|
+
nitro._prerenderMeta[_route.fileName].contentType = _route.contentType;
|
|
581
|
+
}
|
|
582
|
+
if (_route.error) {
|
|
583
|
+
failedRoutes.add(_route);
|
|
584
|
+
}
|
|
585
|
+
if (_route.skip || _route.error) {
|
|
586
|
+
await nitro.hooks.callHook("prerender:route", _route);
|
|
587
|
+
nitro.logger.log(formatPrerenderRoute(_route));
|
|
588
|
+
dataBuff = void 0;
|
|
589
|
+
return _route;
|
|
590
|
+
}
|
|
591
|
+
if (canWriteToDisk(_route)) {
|
|
592
|
+
const filePath = join(nitro.options.output.publicDir, _route.fileName);
|
|
593
|
+
await writeFile(filePath, dataBuff);
|
|
594
|
+
nitro._prerenderedRoutes.push(_route);
|
|
595
|
+
} else {
|
|
596
|
+
_route.skip = true;
|
|
597
|
+
}
|
|
598
|
+
if (!_route.error && (isImplicitHTML || route.endsWith(".html"))) {
|
|
599
|
+
const extractedLinks = await extractLinks(
|
|
600
|
+
dataBuff.toString("utf8"),
|
|
601
|
+
route,
|
|
602
|
+
res,
|
|
603
|
+
nitro.options.prerender.crawlLinks
|
|
604
|
+
);
|
|
605
|
+
for (const _link of extractedLinks) {
|
|
606
|
+
if (canPrerender(_link)) {
|
|
607
|
+
routes.add(_link);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
await nitro.hooks.callHook("prerender:route", _route);
|
|
612
|
+
nitro.logger.log(formatPrerenderRoute(_route));
|
|
613
|
+
dataBuff = void 0;
|
|
614
|
+
return _route;
|
|
615
|
+
};
|
|
616
|
+
nitro.logger.info(
|
|
617
|
+
nitro.options.prerender.crawlLinks ? `Prerendering ${routes.size} initial routes with crawler` : `Prerendering ${routes.size} routes`
|
|
618
|
+
);
|
|
619
|
+
await runParallel(routes, generateRoute, {
|
|
620
|
+
concurrency: nitro.options.prerender.concurrency,
|
|
621
|
+
interval: nitro.options.prerender.interval
|
|
622
|
+
});
|
|
623
|
+
await closePrerenderer();
|
|
624
|
+
await nitro.hooks.callHook("prerender:done", {
|
|
625
|
+
prerenderedRoutes: nitro._prerenderedRoutes,
|
|
626
|
+
failedRoutes: [...failedRoutes]
|
|
627
|
+
});
|
|
628
|
+
if (nitro.options.prerender.failOnError && failedRoutes.size > 0) {
|
|
629
|
+
nitro.logger.log("\nErrors prerendering:");
|
|
630
|
+
for (const route of failedRoutes) {
|
|
631
|
+
const parents = linkParents.get(route.route);
|
|
632
|
+
parents?.size ? `
|
|
633
|
+
${[...parents.values()].map((link) => colors.gray(` \u2502 \u2514\u2500\u2500 Linked from ${link}`)).join("\n")}` : "";
|
|
634
|
+
nitro.logger.log(formatPrerenderRoute(route));
|
|
635
|
+
}
|
|
636
|
+
nitro.logger.log("");
|
|
637
|
+
throw new Error("Exiting due to prerender errors.");
|
|
638
|
+
}
|
|
639
|
+
const prerenderTimeInMs = Date.now() - prerenderStartTime;
|
|
640
|
+
nitro.logger.info(
|
|
641
|
+
`Prerendered ${nitro._prerenderedRoutes.length} routes in ${prerenderTimeInMs / 1e3} seconds`
|
|
642
|
+
);
|
|
643
|
+
if (nitro.options.compressPublicAssets) {
|
|
644
|
+
await compressPublicAssets(nitro);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
|
|
648
648
|
export { build as b, prerender as p, runParallel as r, writeTypes as w };
|
package/dist/_cli/build.mjs
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
import nodeCrypto from 'node:crypto';
|
|
2
1
|
import { d as defineCommand } from '../_chunks/_deps/citty.mjs';
|
|
3
|
-
import { createNitro, prepare, copyPublicAssets, prerender, build as build$1 } from 'nitro';
|
|
2
|
+
import { createNitro, prepare, copyPublicAssets, prerender, build as build$1 } from 'nitro/builder';
|
|
4
3
|
import { c as commonArgs } from './common.mjs';
|
|
5
4
|
import { r as resolve } from '../_chunks/_deps/pathe.mjs';
|
|
6
5
|
import 'consola';
|
|
7
6
|
import 'consola/utils';
|
|
8
7
|
|
|
9
|
-
if (!globalThis.crypto) {
|
|
10
|
-
globalThis.crypto = nodeCrypto;
|
|
11
|
-
}
|
|
12
8
|
const build = defineCommand({
|
|
13
9
|
meta: {
|
|
14
10
|
name: "build",
|
package/dist/_cli/dev.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { d as defineCommand } from '../_chunks/_deps/citty.mjs';
|
|
2
2
|
import { consola } from 'consola';
|
|
3
|
-
import { createNitro, prepare, build } from 'nitro';
|
|
3
|
+
import { createNitro, prepare, build } from 'nitro/builder';
|
|
4
4
|
import { c as commonArgs } from './common.mjs';
|
|
5
5
|
import { N as NitroDevServer } from '../_chunks/server.mjs';
|
|
6
6
|
import { r as resolve } from '../_chunks/_deps/pathe.mjs';
|
package/dist/_cli/list.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { d as defineCommand } from '../_chunks/_deps/citty.mjs';
|
|
2
2
|
import { consola } from 'consola';
|
|
3
|
-
import { loadOptions, listTasks } from 'nitro';
|
|
3
|
+
import { loadOptions, listTasks } from 'nitro/builder';
|
|
4
4
|
import { r as resolve } from '../_chunks/_deps/pathe.mjs';
|
|
5
5
|
import 'consola/utils';
|
|
6
6
|
|
package/dist/_cli/prepare.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { d as defineCommand } from '../_chunks/_deps/citty.mjs';
|
|
2
|
-
import { createNitro, writeTypes } from 'nitro';
|
|
2
|
+
import { createNitro, writeTypes } from 'nitro/builder';
|
|
3
3
|
import { c as commonArgs } from './common.mjs';
|
|
4
4
|
import { r as resolve } from '../_chunks/_deps/pathe.mjs';
|
|
5
5
|
import 'consola';
|
package/dist/_cli/run.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { d as defineCommand } from '../_chunks/_deps/citty.mjs';
|
|
2
2
|
import { consola } from 'consola';
|
|
3
3
|
import destr from 'destr';
|
|
4
|
-
import { loadOptions, runTask } from 'nitro';
|
|
4
|
+
import { loadOptions, runTask } from 'nitro/builder';
|
|
5
5
|
import { r as resolve } from '../_chunks/_deps/pathe.mjs';
|
|
6
6
|
import 'consola/utils';
|
|
7
7
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NitroConfig, LoadConfigOptions, Nitro, DevRPCHooks, DevMessageListener,
|
|
1
|
+
import { NitroConfig, LoadConfigOptions, Nitro, NitroOptions, DevRPCHooks, DevMessageListener, TaskEvent, TaskRunnerOptions } from 'nitro/types';
|
|
2
2
|
import { IncomingMessage, OutgoingMessage } from 'node:http';
|
|
3
3
|
import { Duplex } from 'node:stream';
|
|
4
4
|
import { ServerOptions, Server } from 'srvx';
|
|
@@ -6,7 +6,15 @@ import { HTTPHandler } from 'h3';
|
|
|
6
6
|
|
|
7
7
|
declare function createNitro(config?: NitroConfig, opts?: LoadConfigOptions): Promise<Nitro>;
|
|
8
8
|
|
|
9
|
-
declare function
|
|
9
|
+
declare function loadOptions(configOverrides?: NitroConfig, opts?: LoadConfigOptions): Promise<NitroOptions>;
|
|
10
|
+
|
|
11
|
+
declare function build(nitro: Nitro): Promise<void>;
|
|
12
|
+
|
|
13
|
+
declare function copyPublicAssets(nitro: Nitro): Promise<void>;
|
|
14
|
+
|
|
15
|
+
declare function prepare(nitro: Nitro): Promise<void>;
|
|
16
|
+
|
|
17
|
+
declare function writeTypes(nitro: Nitro): Promise<void>;
|
|
10
18
|
|
|
11
19
|
declare class NitroDevApp {
|
|
12
20
|
#private;
|
|
@@ -28,7 +36,7 @@ declare class NitroDevServer extends NitroDevApp implements DevRPCHooks {
|
|
|
28
36
|
offMessage(listener: DevMessageListener): void;
|
|
29
37
|
}
|
|
30
38
|
|
|
31
|
-
declare function
|
|
39
|
+
declare function prerender(nitro: Nitro): Promise<void>;
|
|
32
40
|
|
|
33
41
|
/** @experimental */
|
|
34
42
|
declare function runTask(taskEvent: TaskEvent, opts?: TaskRunnerOptions): Promise<{
|
|
@@ -41,12 +49,4 @@ declare function listTasks(opts?: TaskRunnerOptions): Promise<Record<string, {
|
|
|
41
49
|
};
|
|
42
50
|
}>>;
|
|
43
51
|
|
|
44
|
-
declare function build(nitro: Nitro): Promise<void>;
|
|
45
|
-
|
|
46
|
-
declare function copyPublicAssets(nitro: Nitro): Promise<void>;
|
|
47
|
-
|
|
48
|
-
declare function prepare(nitro: Nitro): Promise<void>;
|
|
49
|
-
|
|
50
|
-
declare function writeTypes(nitro: Nitro): Promise<void>;
|
|
51
|
-
|
|
52
52
|
export { build, copyPublicAssets, createDevServer, createNitro, listTasks, loadOptions, prepare, prerender, runTask, writeTypes };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export { b as build, p as prerender, w as writeTypes } from './_chunks/
|
|
1
|
+
export { e as copyPublicAssets, c as createNitro, g as listTasks, l as loadOptions, p as prepare, f as runTask } from './_build/prepare.mjs';
|
|
2
|
+
export { b as build, p as prerender, w as writeTypes } from './_chunks/builder.mjs';
|
|
3
3
|
export { c as createDevServer } from './_chunks/server.mjs';
|
|
4
4
|
import 'consola';
|
|
5
5
|
import 'hookable';
|
|
@@ -69,9 +69,9 @@ import 'consola/utils';
|
|
|
69
69
|
import './_chunks/_deps/dot-prop.mjs';
|
|
70
70
|
import 'node:zlib';
|
|
71
71
|
import './_chunks/_deps/mime.mjs';
|
|
72
|
-
import './_chunks/_deps/ultrahtml.mjs';
|
|
73
72
|
import './_chunks/_deps/untyped.mjs';
|
|
74
73
|
import './_chunks/_deps/knitwork.mjs';
|
|
74
|
+
import './_chunks/_deps/ultrahtml.mjs';
|
|
75
75
|
import './_chunks/app.mjs';
|
|
76
76
|
import 'node:worker_threads';
|
|
77
77
|
import 'h3';
|
|
@@ -3,14 +3,10 @@ import { useNitroApp, useNitroHooks } from "nitro/runtime";
|
|
|
3
3
|
import { trapUnhandledNodeErrors } from "nitro/runtime/internal";
|
|
4
4
|
import { startScheduleRunner } from "nitro/runtime/internal";
|
|
5
5
|
import { Server } from "node:http";
|
|
6
|
-
import nodeCrypto from "node:crypto";
|
|
7
6
|
import { parentPort, threadId } from "node:worker_threads";
|
|
8
7
|
import wsAdapter from "crossws/adapters/node";
|
|
9
8
|
import { toNodeHandler } from "srvx/node";
|
|
10
9
|
import { getSocketAddress, isSocketSupported } from "get-port-please";
|
|
11
|
-
if (!globalThis.crypto) {
|
|
12
|
-
globalThis.crypto = nodeCrypto;
|
|
13
|
-
}
|
|
14
10
|
trapUnhandledNodeErrors();
|
|
15
11
|
parentPort?.on("message", (msg) => {
|
|
16
12
|
if (msg && msg.event === "shutdown") {
|
package/lib/index.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// reserved for "nitro" import
|
package/lib/indexd.mts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// reserved for "nitro" import
|
package/package.json
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nitro-nightly",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0-20251030-091344-d4418b98",
|
|
4
4
|
"description": "Build and Deploy Universal JavaScript Servers",
|
|
5
5
|
"homepage": "https://nitro.build",
|
|
6
6
|
"repository": "nitrojs/nitro",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"exports": {
|
|
10
|
+
".": "./lib/index.mjs",
|
|
10
11
|
"./package.json": "./package.json",
|
|
11
|
-
"
|
|
12
|
+
"./builder": "./dist/builder.mjs",
|
|
12
13
|
"./config": "./lib/config.mjs",
|
|
13
14
|
"./types": "./dist/types/index.d.mts",
|
|
14
15
|
"./meta": "./lib/meta.mjs",
|