@analogjs/vite-plugin-nitro 3.0.0-alpha.7 → 3.0.0-alpha.9
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/package.json +3 -6
- package/src/index.d.ts +1 -1
- package/src/index.js +6 -2
- package/src/index.js.map +1 -1
- package/src/lib/build-server.js +97 -140
- package/src/lib/build-server.js.map +1 -1
- package/src/lib/build-sitemap.js +48 -60
- package/src/lib/build-sitemap.js.map +1 -1
- package/src/lib/build-ssr.js +16 -18
- package/src/lib/build-ssr.js.map +1 -1
- package/src/lib/hooks/post-rendering-hook.js +10 -6
- package/src/lib/hooks/post-rendering-hook.js.map +1 -1
- package/src/lib/options.d.ts +8 -0
- package/src/lib/plugins/dev-server-plugin.js +91 -101
- package/src/lib/plugins/dev-server-plugin.js.map +1 -1
- package/src/lib/plugins/page-endpoints.js +26 -46
- package/src/lib/plugins/page-endpoints.js.map +1 -1
- package/src/lib/utils/get-content-files.js +88 -97
- package/src/lib/utils/get-content-files.js.map +1 -1
- package/src/lib/utils/get-page-handlers.js +70 -84
- package/src/lib/utils/get-page-handlers.js.map +1 -1
- package/src/lib/utils/node-web-bridge.js +34 -45
- package/src/lib/utils/node-web-bridge.js.map +1 -1
- package/src/lib/utils/register-dev-middleware.js +41 -47
- package/src/lib/utils/register-dev-middleware.js.map +1 -1
- package/src/lib/utils/renderers.js +55 -51
- package/src/lib/utils/renderers.js.map +1 -1
- package/src/lib/utils/rolldown.d.ts +2 -0
- package/src/lib/utils/rolldown.js +12 -0
- package/src/lib/utils/rolldown.js.map +1 -0
- package/src/lib/vite-plugin-nitro.js +442 -676
- package/src/lib/vite-plugin-nitro.js.map +1 -1
- package/README.md +0 -125
- package/src/lib/options.js +0 -2
- package/src/lib/options.js.map +0 -1
- package/src/lib/utils/load-esm.js +0 -23
- package/src/lib/utils/load-esm.js.map +0 -1
|
@@ -1,70 +1,59 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { normalizePath
|
|
4
|
-
import { resolve } from
|
|
5
|
-
import { readFileSync } from
|
|
6
|
-
import { createRouter
|
|
7
|
-
import { defu } from
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if (result instanceof Response) {
|
|
58
|
-
await writeWebResponseToNode(res, result);
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
res.setHeader('Content-Type', 'text/html');
|
|
62
|
-
res.end(result);
|
|
63
|
-
}
|
|
64
|
-
catch (e) {
|
|
65
|
-
viteServer.ssrFixStacktrace(e);
|
|
66
|
-
res.statusCode = 500;
|
|
67
|
-
res.end(`
|
|
1
|
+
import { writeWebResponseToNode } from "../utils/node-web-bridge.js";
|
|
2
|
+
import { registerDevServerMiddleware } from "../utils/register-dev-middleware.js";
|
|
3
|
+
import { normalizePath } from "vite";
|
|
4
|
+
import { resolve } from "node:path";
|
|
5
|
+
import { readFileSync } from "node:fs";
|
|
6
|
+
import { createRouter, toRouteMatcher } from "radix3";
|
|
7
|
+
import { defu } from "defu";
|
|
8
|
+
//#region packages/vite-plugin-nitro/src/lib/plugins/dev-server-plugin.ts
|
|
9
|
+
function devServerPlugin(options) {
|
|
10
|
+
const workspaceRoot = options?.workspaceRoot || process.cwd();
|
|
11
|
+
const sourceRoot = options?.sourceRoot ?? "src";
|
|
12
|
+
const index = options.index || "index.html";
|
|
13
|
+
let config;
|
|
14
|
+
let root;
|
|
15
|
+
let isTest = false;
|
|
16
|
+
return {
|
|
17
|
+
name: "analogjs-dev-ssr-plugin",
|
|
18
|
+
config(userConfig, { mode }) {
|
|
19
|
+
config = userConfig;
|
|
20
|
+
root = normalizePath(resolve(workspaceRoot, config.root || ".") || ".");
|
|
21
|
+
isTest = isTest ? isTest : mode === "test";
|
|
22
|
+
return {
|
|
23
|
+
appType: "custom",
|
|
24
|
+
resolve: { alias: { "~analog/entry-server": options.entryServer || `${root}/${sourceRoot}/main.server.ts` } }
|
|
25
|
+
};
|
|
26
|
+
},
|
|
27
|
+
configureServer(viteServer) {
|
|
28
|
+
if (isTest) return;
|
|
29
|
+
return async () => {
|
|
30
|
+
remove_html_middlewares(viteServer.middlewares);
|
|
31
|
+
registerDevServerMiddleware(root, sourceRoot, viteServer);
|
|
32
|
+
viteServer.middlewares.use(async (req, res) => {
|
|
33
|
+
let template = readFileSync(resolve(viteServer.config.root, index), "utf-8");
|
|
34
|
+
template = await viteServer.transformIndexHtml(req.originalUrl, template);
|
|
35
|
+
const _routeRulesMatcher = toRouteMatcher(createRouter({ routes: options.routeRules }));
|
|
36
|
+
const _getRouteRules = (path) => defu({}, ..._routeRulesMatcher.matchAll(path).reverse());
|
|
37
|
+
try {
|
|
38
|
+
let result;
|
|
39
|
+
if (_getRouteRules(req.originalUrl).ssr === false) result = template;
|
|
40
|
+
else {
|
|
41
|
+
const entryServer = (await viteServer.ssrLoadModule("~analog/entry-server"))["default"];
|
|
42
|
+
result = await entryServer(req.originalUrl, template, {
|
|
43
|
+
req,
|
|
44
|
+
res
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
if (result instanceof Response) {
|
|
48
|
+
await writeWebResponseToNode(res, result);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
res.setHeader("Content-Type", "text/html");
|
|
52
|
+
res.end(result);
|
|
53
|
+
} catch (e) {
|
|
54
|
+
viteServer.ssrFixStacktrace(e);
|
|
55
|
+
res.statusCode = 500;
|
|
56
|
+
res.end(`
|
|
68
57
|
<!DOCTYPE html>
|
|
69
58
|
<html lang="en">
|
|
70
59
|
<head>
|
|
@@ -72,50 +61,51 @@ export function devServerPlugin(options) {
|
|
|
72
61
|
<title>Error</title>
|
|
73
62
|
<script type="module">
|
|
74
63
|
import { ErrorOverlay } from '/@vite/client'
|
|
75
|
-
document.body.appendChild(new ErrorOverlay(${JSON.stringify(prepareError(req, e)).replace(/</g,
|
|
76
|
-
|
|
64
|
+
document.body.appendChild(new ErrorOverlay(${JSON.stringify(prepareError(req, e)).replace(/</g, "\\u003c")}))
|
|
65
|
+
<\/script>
|
|
77
66
|
</head>
|
|
78
67
|
<body>
|
|
79
68
|
</body>
|
|
80
69
|
</html>
|
|
81
70
|
`);
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
};
|
|
87
76
|
}
|
|
88
77
|
/**
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
78
|
+
* Removes Vite internal middleware
|
|
79
|
+
*
|
|
80
|
+
* @param server
|
|
81
|
+
*/
|
|
93
82
|
function remove_html_middlewares(server) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
}
|
|
83
|
+
const html_middlewares = [
|
|
84
|
+
"viteIndexHtmlMiddleware",
|
|
85
|
+
"vite404Middleware",
|
|
86
|
+
"viteSpaFallbackMiddleware",
|
|
87
|
+
"viteHtmlFallbackMiddleware"
|
|
88
|
+
];
|
|
89
|
+
for (let i = server.stack.length - 1; i > 0; i--) {
|
|
90
|
+
const handler = server.stack[i]?.handle;
|
|
91
|
+
const handlerName = typeof handler === "function" ? handler.name : void 0;
|
|
92
|
+
if (handlerName && html_middlewares.includes(handlerName)) server.stack.splice(i, 1);
|
|
93
|
+
}
|
|
107
94
|
}
|
|
108
95
|
/**
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
96
|
+
* Formats error for SSR message in error overlay
|
|
97
|
+
* @param req
|
|
98
|
+
* @param error
|
|
99
|
+
* @returns
|
|
100
|
+
*/
|
|
114
101
|
function prepareError(req, error) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
102
|
+
const e = error;
|
|
103
|
+
return {
|
|
104
|
+
message: `An error occured while server rendering ${req.url}:\n\n\t${typeof e === "string" ? e : e.message} `,
|
|
105
|
+
stack: typeof e === "string" ? "" : e.stack
|
|
106
|
+
};
|
|
120
107
|
}
|
|
108
|
+
//#endregion
|
|
109
|
+
export { devServerPlugin };
|
|
110
|
+
|
|
121
111
|
//# sourceMappingURL=dev-server-plugin.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev-server-plugin.js","
|
|
1
|
+
{"version":3,"file":"dev-server-plugin.js","names":[],"sources":["../../../../../../packages/vite-plugin-nitro/src/lib/plugins/dev-server-plugin.ts"],"sourcesContent":["// SSR dev server, middleware and error page source modified from\n// https://github.com/solidjs/solid-start/blob/main/packages/start/dev/server.js\n\nimport {\n Connect,\n Plugin,\n UserConfig,\n ViteDevServer,\n normalizePath,\n} from 'vite';\nimport { resolve } from 'node:path';\nimport { readFileSync } from 'node:fs';\nimport { createRouter as createRadixRouter, toRouteMatcher } from 'radix3';\nimport { defu } from 'defu';\nimport type { NitroRouteRules } from 'nitro/types';\n\nimport { registerDevServerMiddleware } from '../utils/register-dev-middleware.js';\nimport { writeWebResponseToNode } from '../utils/node-web-bridge.js';\nimport { Options } from '../options.js';\n\ntype ServerOptions = Options & { routeRules?: Record<string, any> | undefined };\n\nexport function devServerPlugin(options: ServerOptions): Plugin {\n const workspaceRoot = options?.workspaceRoot || process.cwd();\n const sourceRoot = options?.sourceRoot ?? 'src';\n const index = options.index || 'index.html';\n let config: UserConfig;\n let root: string;\n let isTest = false;\n\n return {\n name: 'analogjs-dev-ssr-plugin',\n config(userConfig, { mode }) {\n config = userConfig;\n root = normalizePath(resolve(workspaceRoot, config.root || '.') || '.');\n isTest = isTest ? isTest : mode === 'test';\n return {\n appType: 'custom',\n resolve: {\n alias: {\n '~analog/entry-server':\n options.entryServer || `${root}/${sourceRoot}/main.server.ts`,\n },\n },\n };\n },\n configureServer(viteServer) {\n if (isTest) {\n return;\n }\n\n return async () => {\n remove_html_middlewares(viteServer.middlewares);\n registerDevServerMiddleware(root, sourceRoot, viteServer);\n\n viteServer.middlewares.use(async (req, res) => {\n let template = readFileSync(\n resolve(viteServer.config.root, index),\n 'utf-8',\n );\n\n template = await viteServer.transformIndexHtml(\n req.originalUrl as string,\n template,\n );\n\n const _routeRulesMatcher = toRouteMatcher(\n createRadixRouter({ routes: options.routeRules }),\n );\n const _getRouteRules = (path: string) =>\n defu(\n {},\n ..._routeRulesMatcher.matchAll(path).reverse(),\n ) as NitroRouteRules;\n\n try {\n let result: string | Response;\n // Check for route rules explicitly disabling SSR\n if (_getRouteRules(req.originalUrl as string).ssr === false) {\n result = template;\n } else {\n const entryServer = (\n await viteServer.ssrLoadModule('~analog/entry-server')\n )['default'];\n result = await entryServer(req.originalUrl, template, {\n req,\n res,\n });\n }\n\n if (result instanceof Response) {\n await writeWebResponseToNode(res, result);\n return;\n }\n res.setHeader('Content-Type', 'text/html');\n res.end(result);\n } catch (e) {\n viteServer.ssrFixStacktrace(e as Error);\n res.statusCode = 500;\n res.end(`\n <!DOCTYPE html>\n <html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <title>Error</title>\n <script type=\"module\">\n import { ErrorOverlay } from '/@vite/client'\n document.body.appendChild(new ErrorOverlay(${JSON.stringify(\n prepareError(req, e),\n ).replace(/</g, '\\\\u003c')}))\n </script>\n </head>\n <body>\n </body>\n </html>\n `);\n }\n });\n };\n },\n };\n}\n\n/**\n * Removes Vite internal middleware\n *\n * @param server\n */\nfunction remove_html_middlewares(server: ViteDevServer['middlewares']) {\n const html_middlewares = [\n 'viteIndexHtmlMiddleware',\n 'vite404Middleware',\n 'viteSpaFallbackMiddleware',\n 'viteHtmlFallbackMiddleware',\n ];\n for (let i = server.stack.length - 1; i > 0; i--) {\n const handler = server.stack[i]?.handle;\n const handlerName =\n typeof handler === 'function' ? handler.name : undefined;\n if (handlerName && html_middlewares.includes(handlerName)) {\n server.stack.splice(i, 1);\n }\n }\n}\n\n/**\n * Formats error for SSR message in error overlay\n * @param req\n * @param error\n * @returns\n */\nfunction prepareError(req: Connect.IncomingMessage, error: unknown) {\n const e = error as Error;\n return {\n message: `An error occured while server rendering ${req.url}:\\n\\n\\t${\n typeof e === 'string' ? e : e.message\n } `,\n stack: typeof e === 'string' ? '' : e.stack,\n };\n}\n"],"mappings":";;;;;;;;AAsBA,SAAgB,gBAAgB,SAAgC;CAC9D,MAAM,gBAAgB,SAAS,iBAAiB,QAAQ,KAAK;CAC7D,MAAM,aAAa,SAAS,cAAc;CAC1C,MAAM,QAAQ,QAAQ,SAAS;CAC/B,IAAI;CACJ,IAAI;CACJ,IAAI,SAAS;AAEb,QAAO;EACL,MAAM;EACN,OAAO,YAAY,EAAE,QAAQ;AAC3B,YAAS;AACT,UAAO,cAAc,QAAQ,eAAe,OAAO,QAAQ,IAAI,IAAI,IAAI;AACvE,YAAS,SAAS,SAAS,SAAS;AACpC,UAAO;IACL,SAAS;IACT,SAAS,EACP,OAAO,EACL,wBACE,QAAQ,eAAe,GAAG,KAAK,GAAG,WAAW,kBAChD,EACF;IACF;;EAEH,gBAAgB,YAAY;AAC1B,OAAI,OACF;AAGF,UAAO,YAAY;AACjB,4BAAwB,WAAW,YAAY;AAC/C,gCAA4B,MAAM,YAAY,WAAW;AAEzD,eAAW,YAAY,IAAI,OAAO,KAAK,QAAQ;KAC7C,IAAI,WAAW,aACb,QAAQ,WAAW,OAAO,MAAM,MAAM,EACtC,QACD;AAED,gBAAW,MAAM,WAAW,mBAC1B,IAAI,aACJ,SACD;KAED,MAAM,qBAAqB,eACzB,aAAkB,EAAE,QAAQ,QAAQ,YAAY,CAAC,CAClD;KACD,MAAM,kBAAkB,SACtB,KACE,EAAE,EACF,GAAG,mBAAmB,SAAS,KAAK,CAAC,SAAS,CAC/C;AAEH,SAAI;MACF,IAAI;AAEJ,UAAI,eAAe,IAAI,YAAsB,CAAC,QAAQ,MACpD,UAAS;WACJ;OACL,MAAM,eACJ,MAAM,WAAW,cAAc,uBAAuB,EACtD;AACF,gBAAS,MAAM,YAAY,IAAI,aAAa,UAAU;QACpD;QACA;QACD,CAAC;;AAGJ,UAAI,kBAAkB,UAAU;AAC9B,aAAM,uBAAuB,KAAK,OAAO;AACzC;;AAEF,UAAI,UAAU,gBAAgB,YAAY;AAC1C,UAAI,IAAI,OAAO;cACR,GAAG;AACV,iBAAW,iBAAiB,EAAW;AACvC,UAAI,aAAa;AACjB,UAAI,IAAI;;;;;;;;iEAQ6C,KAAK,UAChD,aAAa,KAAK,EAAE,CACrB,CAAC,QAAQ,MAAM,UAAU,CAAC;;;;;;cAMjC;;MAEJ;;;EAGP;;;;;;;AAQH,SAAS,wBAAwB,QAAsC;CACrE,MAAM,mBAAmB;EACvB;EACA;EACA;EACA;EACD;AACD,MAAK,IAAI,IAAI,OAAO,MAAM,SAAS,GAAG,IAAI,GAAG,KAAK;EAChD,MAAM,UAAU,OAAO,MAAM,IAAI;EACjC,MAAM,cACJ,OAAO,YAAY,aAAa,QAAQ,OAAO,KAAA;AACjD,MAAI,eAAe,iBAAiB,SAAS,YAAY,CACvD,QAAO,MAAM,OAAO,GAAG,EAAE;;;;;;;;;AAW/B,SAAS,aAAa,KAA8B,OAAgB;CAClE,MAAM,IAAI;AACV,QAAO;EACL,SAAS,2CAA2C,IAAI,IAAI,SAC1D,OAAO,MAAM,WAAW,IAAI,EAAE,QAC/B;EACD,OAAO,OAAO,MAAM,WAAW,KAAK,EAAE;EACvC"}
|
|
@@ -1,48 +1,28 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { normalizePath } from
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
// In h3 v2 / Nitro v3, event.node is undefined during prerendering
|
|
17
|
-
// (which uses the fetch-based pipeline, not Node.js http). We use
|
|
18
|
-
// optional chaining so that page endpoints work in both Node.js
|
|
19
|
-
// server and fetch-based prerender contexts.
|
|
20
|
-
// Nitro v3 no longer guarantees the private `nitro/deps/ofetch`
|
|
21
|
-
// subpath that older codegen relied on.
|
|
22
|
-
//
|
|
23
|
-
// Page loaders expect Nitro-style `$fetch` semantics (parsed data plus
|
|
24
|
-
// internal relative-route support), so construct a request-local fetch
|
|
25
|
-
// using public APIs:
|
|
26
|
-
// - `createFetch` from `ofetch` for `$fetch` behavior
|
|
27
|
-
// - `fetchWithEvent` from `h3` for internal Nitro request routing
|
|
28
|
-
//
|
|
29
|
-
// This avoids both unstable private Nitro imports and assumptions about
|
|
30
|
-
// a global runtime `$fetch` being available during prerender.
|
|
31
|
-
const code = `
|
|
1
|
+
import { SERVER_FETCH_FACTORY_SNIPPET } from "../utils/renderers.js";
|
|
2
|
+
import { normalizePath } from "vite";
|
|
3
|
+
import { parseSync } from "oxc-parser";
|
|
4
|
+
//#region packages/vite-plugin-nitro/src/lib/plugins/page-endpoints.ts
|
|
5
|
+
function pageEndpointsPlugin() {
|
|
6
|
+
return {
|
|
7
|
+
name: "analogjs-vite-plugin-nitro-rollup-page-endpoint",
|
|
8
|
+
async transform(_code, id) {
|
|
9
|
+
if (normalizePath(id).includes("/pages/") && id.endsWith(".server.ts")) {
|
|
10
|
+
const fileExports = parseSync(id, _code, {
|
|
11
|
+
sourceType: "module",
|
|
12
|
+
lang: "ts"
|
|
13
|
+
}).module.staticExports.flatMap((e) => e.entries.filter((entry) => entry.exportName.name !== null).map((entry) => entry.exportName.name));
|
|
14
|
+
return {
|
|
15
|
+
code: `
|
|
32
16
|
import { defineHandler, fetchWithEvent } from 'nitro/h3';
|
|
33
17
|
import { createFetch } from 'ofetch';
|
|
34
18
|
|
|
35
|
-
${fileExports.includes(
|
|
36
|
-
? _code
|
|
37
|
-
: `
|
|
19
|
+
${fileExports.includes("load") ? _code : `
|
|
38
20
|
${_code}
|
|
39
21
|
export const load = () => {
|
|
40
22
|
return {};
|
|
41
23
|
}`}
|
|
42
24
|
|
|
43
|
-
${fileExports.includes(
|
|
44
|
-
? ''
|
|
45
|
-
: `
|
|
25
|
+
${fileExports.includes("action") ? "" : `
|
|
46
26
|
export const action = () => {
|
|
47
27
|
return {};
|
|
48
28
|
}
|
|
@@ -79,14 +59,14 @@ export function pageEndpointsPlugin() {
|
|
|
79
59
|
}
|
|
80
60
|
}
|
|
81
61
|
});
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
return;
|
|
89
|
-
},
|
|
90
|
-
};
|
|
62
|
+
`,
|
|
63
|
+
map: null
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
91
68
|
}
|
|
69
|
+
//#endregion
|
|
70
|
+
export { pageEndpointsPlugin };
|
|
71
|
+
|
|
92
72
|
//# sourceMappingURL=page-endpoints.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-endpoints.js","
|
|
1
|
+
{"version":3,"file":"page-endpoints.js","names":[],"sources":["../../../../../../packages/vite-plugin-nitro/src/lib/plugins/page-endpoints.ts"],"sourcesContent":["import { parseSync } from 'oxc-parser';\nimport { normalizePath } from 'vite';\nimport { SERVER_FETCH_FACTORY_SNIPPET } from '../utils/renderers.js';\n\nexport function pageEndpointsPlugin() {\n return {\n name: 'analogjs-vite-plugin-nitro-rollup-page-endpoint',\n async transform(\n _code: string,\n id: string,\n ): Promise<{ code: string; map: null } | undefined> {\n if (normalizePath(id).includes('/pages/') && id.endsWith('.server.ts')) {\n const result = parseSync(id, _code, {\n sourceType: 'module',\n lang: 'ts',\n });\n\n const fileExports: string[] = result.module.staticExports.flatMap((e) =>\n e.entries\n .filter((entry) => entry.exportName.name !== null)\n .map((entry) => entry.exportName.name as string),\n );\n\n // In h3 v2 / Nitro v3, event.node is undefined during prerendering\n // (which uses the fetch-based pipeline, not Node.js http). We use\n // optional chaining so that page endpoints work in both Node.js\n // server and fetch-based prerender contexts.\n // Nitro v3 no longer guarantees the private `nitro/deps/ofetch`\n // subpath that older codegen relied on.\n //\n // Page loaders expect Nitro-style `$fetch` semantics (parsed data plus\n // internal relative-route support), so construct a request-local fetch\n // using public APIs:\n // - `createFetch` from `ofetch` for `$fetch` behavior\n // - `fetchWithEvent` from `h3` for internal Nitro request routing\n //\n // This avoids both unstable private Nitro imports and assumptions about\n // a global runtime `$fetch` being available during prerender.\n const code = `\n import { defineHandler, fetchWithEvent } from 'nitro/h3';\n import { createFetch } from 'ofetch';\n\n ${\n fileExports.includes('load')\n ? _code\n : `\n ${_code}\n export const load = () => {\n return {};\n }`\n }\n\n ${\n fileExports.includes('action')\n ? ''\n : `\n export const action = () => {\n return {};\n }\n `\n }\n\n export default defineHandler(async(event) => {\n ${SERVER_FETCH_FACTORY_SNIPPET}\n\n if (event.method === 'GET') {\n try {\n return await load({\n params: event.context.params,\n req: event.node?.req,\n res: event.node?.res,\n fetch: serverFetch,\n event\n });\n } catch(e) {\n console.error(\\` An error occurred: \\${e}\\`)\n throw e;\n }\n } else {\n try {\n return await action({\n params: event.context.params,\n req: event.node?.req,\n res: event.node?.res,\n fetch: serverFetch,\n event\n });\n } catch(e) {\n console.error(\\` An error occurred: \\${e}\\`)\n throw e;\n }\n }\n });\n `;\n\n return {\n code,\n map: null,\n };\n }\n\n return;\n },\n };\n}\n"],"mappings":";;;;AAIA,SAAgB,sBAAsB;AACpC,QAAO;EACL,MAAM;EACN,MAAM,UACJ,OACA,IACkD;AAClD,OAAI,cAAc,GAAG,CAAC,SAAS,UAAU,IAAI,GAAG,SAAS,aAAa,EAAE;IAMtE,MAAM,cALS,UAAU,IAAI,OAAO;KAClC,YAAY;KACZ,MAAM;KACP,CAAC,CAEmC,OAAO,cAAc,SAAS,MACjE,EAAE,QACC,QAAQ,UAAU,MAAM,WAAW,SAAS,KAAK,CACjD,KAAK,UAAU,MAAM,WAAW,KAAe,CACnD;AA0ED,WAAO;KACL,MA1DW;;;;cAKP,YAAY,SAAS,OAAO,GACxB,QACA;kBACA,MAAM;;;mBAIX;;cAGC,YAAY,SAAS,SAAS,GAC1B,KACA;;;;gBAKL;;;gBAGG,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAkCnC,KAAK;KACN;;;EAKN"}
|
|
@@ -1,100 +1,91 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { join, relative, resolve } from
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
1
|
+
import { normalizePath } from "vite";
|
|
2
|
+
import { join, relative, resolve } from "node:path";
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import { globSync } from "tinyglobby";
|
|
5
|
+
import { createRequire } from "node:module";
|
|
6
|
+
//#region packages/vite-plugin-nitro/src/lib/utils/get-content-files.ts
|
|
7
|
+
var require = createRequire(import.meta.url);
|
|
7
8
|
/**
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
name = match[1]; // File name without extension
|
|
87
|
-
extension = match[3] || ''; // File extension or empty string if no extension
|
|
88
|
-
}
|
|
89
|
-
// Return structured content file data for prerendering
|
|
90
|
-
return {
|
|
91
|
-
name,
|
|
92
|
-
extension,
|
|
93
|
-
path: resolvedDir,
|
|
94
|
-
attributes: raw.attributes,
|
|
95
|
-
content: fileContents,
|
|
96
|
-
};
|
|
97
|
-
});
|
|
98
|
-
return mappedFilesWithFm;
|
|
9
|
+
* Discovers content files with front matter and extracts metadata for prerendering.
|
|
10
|
+
*
|
|
11
|
+
* This function:
|
|
12
|
+
* 1. Discovers all content files matching the specified glob pattern
|
|
13
|
+
* 2. Reads each file and parses front matter metadata
|
|
14
|
+
* 3. Extracts file name, extension, and path information
|
|
15
|
+
* 4. Returns structured data for prerendering content pages
|
|
16
|
+
*
|
|
17
|
+
* @param workspaceRoot The workspace root directory path
|
|
18
|
+
* @param rootDir The project root directory relative to workspace
|
|
19
|
+
* @param glob The glob pattern to match content files (e.g., 'content/blog')
|
|
20
|
+
* @returns Array of PrerenderContentFile objects with metadata and front matter
|
|
21
|
+
*
|
|
22
|
+
* Example usage:
|
|
23
|
+
* const contentFiles = getMatchingContentFilesWithFrontMatter(
|
|
24
|
+
* '/workspace',
|
|
25
|
+
* 'apps/my-app',
|
|
26
|
+
* 'content/blog'
|
|
27
|
+
* );
|
|
28
|
+
*
|
|
29
|
+
* Sample discovered file paths:
|
|
30
|
+
* - /workspace/apps/my-app/content/blog/first-post.md
|
|
31
|
+
* - /workspace/apps/my-app/content/blog/2024/01/hello-world.md
|
|
32
|
+
* - /workspace/apps/my-app/content/blog/tech/angular-v17.mdx
|
|
33
|
+
* - /workspace/apps/my-app/content/blog/about/index.md
|
|
34
|
+
*
|
|
35
|
+
* Sample output structure:
|
|
36
|
+
* {
|
|
37
|
+
* name: 'first-post',
|
|
38
|
+
* extension: 'md',
|
|
39
|
+
* path: 'content/blog',
|
|
40
|
+
* attributes: { title: 'My First Post', date: '2024-01-01', tags: ['intro'] }
|
|
41
|
+
* }
|
|
42
|
+
*
|
|
43
|
+
* tinyglobby vs fast-glob comparison:
|
|
44
|
+
* - Both support the same glob patterns for file discovery
|
|
45
|
+
* - Both are efficient for finding content files
|
|
46
|
+
* - tinyglobby is now used instead of fast-glob
|
|
47
|
+
* - tinyglobby provides similar functionality with smaller bundle size
|
|
48
|
+
* - tinyglobby's globSync returns absolute paths when absolute: true is set
|
|
49
|
+
*
|
|
50
|
+
* Front matter parsing:
|
|
51
|
+
* - Uses front-matter library to parse YAML/TOML front matter
|
|
52
|
+
* - Extracts metadata like title, date, tags, author, etc.
|
|
53
|
+
* - Supports both YAML (---) and TOML (+++) delimiters
|
|
54
|
+
* - Returns structured attributes for prerendering
|
|
55
|
+
*
|
|
56
|
+
* File path processing:
|
|
57
|
+
* - Normalizes paths for cross-platform compatibility
|
|
58
|
+
* - Extracts file name without extension
|
|
59
|
+
* - Determines file extension for content type handling
|
|
60
|
+
* - Maintains relative path structure for routing
|
|
61
|
+
*/
|
|
62
|
+
function getMatchingContentFilesWithFrontMatter(workspaceRoot, rootDir, glob) {
|
|
63
|
+
const fm = require("front-matter");
|
|
64
|
+
const root = normalizePath(resolve(workspaceRoot, rootDir));
|
|
65
|
+
const resolvedDir = normalizePath(relative(root, join(root, glob)));
|
|
66
|
+
return globSync([`${root}/${resolvedDir}/*`], {
|
|
67
|
+
dot: true,
|
|
68
|
+
absolute: true
|
|
69
|
+
}).map((f) => {
|
|
70
|
+
const fileContents = readFileSync(f, "utf8");
|
|
71
|
+
const raw = fm(fileContents);
|
|
72
|
+
const match = normalizePath(f).replace(root, "").match(/\/([^/.]+)(\.([^/.]+))?$/);
|
|
73
|
+
let name = "";
|
|
74
|
+
let extension = "";
|
|
75
|
+
if (match) {
|
|
76
|
+
name = match[1];
|
|
77
|
+
extension = match[3] || "";
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
name,
|
|
81
|
+
extension,
|
|
82
|
+
path: resolvedDir,
|
|
83
|
+
attributes: raw.attributes,
|
|
84
|
+
content: fileContents
|
|
85
|
+
};
|
|
86
|
+
});
|
|
99
87
|
}
|
|
88
|
+
//#endregion
|
|
89
|
+
export { getMatchingContentFilesWithFrontMatter };
|
|
90
|
+
|
|
100
91
|
//# sourceMappingURL=get-content-files.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-content-files.js","
|
|
1
|
+
{"version":3,"file":"get-content-files.js","names":[],"sources":["../../../../../../packages/vite-plugin-nitro/src/lib/utils/get-content-files.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { join, relative, resolve } from 'node:path';\nimport { normalizePath } from 'vite';\nimport { createRequire } from 'node:module';\nimport { globSync } from 'tinyglobby';\n\nimport { PrerenderContentFile } from '../options';\n\nconst require = createRequire(import.meta.url);\n\n/**\n * Discovers content files with front matter and extracts metadata for prerendering.\n *\n * This function:\n * 1. Discovers all content files matching the specified glob pattern\n * 2. Reads each file and parses front matter metadata\n * 3. Extracts file name, extension, and path information\n * 4. Returns structured data for prerendering content pages\n *\n * @param workspaceRoot The workspace root directory path\n * @param rootDir The project root directory relative to workspace\n * @param glob The glob pattern to match content files (e.g., 'content/blog')\n * @returns Array of PrerenderContentFile objects with metadata and front matter\n *\n * Example usage:\n * const contentFiles = getMatchingContentFilesWithFrontMatter(\n * '/workspace',\n * 'apps/my-app',\n * 'content/blog'\n * );\n *\n * Sample discovered file paths:\n * - /workspace/apps/my-app/content/blog/first-post.md\n * - /workspace/apps/my-app/content/blog/2024/01/hello-world.md\n * - /workspace/apps/my-app/content/blog/tech/angular-v17.mdx\n * - /workspace/apps/my-app/content/blog/about/index.md\n *\n * Sample output structure:\n * {\n * name: 'first-post',\n * extension: 'md',\n * path: 'content/blog',\n * attributes: { title: 'My First Post', date: '2024-01-01', tags: ['intro'] }\n * }\n *\n * tinyglobby vs fast-glob comparison:\n * - Both support the same glob patterns for file discovery\n * - Both are efficient for finding content files\n * - tinyglobby is now used instead of fast-glob\n * - tinyglobby provides similar functionality with smaller bundle size\n * - tinyglobby's globSync returns absolute paths when absolute: true is set\n *\n * Front matter parsing:\n * - Uses front-matter library to parse YAML/TOML front matter\n * - Extracts metadata like title, date, tags, author, etc.\n * - Supports both YAML (---) and TOML (+++) delimiters\n * - Returns structured attributes for prerendering\n *\n * File path processing:\n * - Normalizes paths for cross-platform compatibility\n * - Extracts file name without extension\n * - Determines file extension for content type handling\n * - Maintains relative path structure for routing\n */\nexport function getMatchingContentFilesWithFrontMatter(\n workspaceRoot: string,\n rootDir: string,\n glob: string,\n): PrerenderContentFile[] {\n // Dynamically require front-matter library\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const fm = require('front-matter');\n\n // Normalize the project root path for consistent path handling\n const root = normalizePath(resolve(workspaceRoot, rootDir));\n\n // Resolve the content directory path relative to the project root\n const resolvedDir = normalizePath(relative(root, join(root, glob)));\n\n // Discover all content files in the specified directory\n // Pattern: looks for any files in the resolved directory\n const contentFiles: string[] = globSync([`${root}/${resolvedDir}/*`], {\n dot: true,\n absolute: true,\n });\n\n // Process each discovered content file to extract metadata and front matter\n const mappedFilesWithFm: PrerenderContentFile[] = contentFiles.map((f) => {\n // Read the file contents as UTF-8 text\n const fileContents = readFileSync(f, 'utf8');\n\n // Parse front matter from the file content\n const raw = fm(fileContents);\n\n const filepath = normalizePath(f).replace(root, '');\n\n const match = filepath.match(/\\/([^/.]+)(\\.([^/.]+))?$/);\n let name = '';\n let extension = '';\n if (match) {\n name = match[1]; // File name without extension\n extension = match[3] || ''; // File extension or empty string if no extension\n }\n\n // Return structured content file data for prerendering\n return {\n name,\n extension,\n path: resolvedDir,\n attributes: raw.attributes as { attributes: Record<string, any> },\n content: fileContents,\n };\n });\n\n return mappedFilesWithFm;\n}\n"],"mappings":";;;;;;AAQA,IAAM,UAAU,cAAc,OAAO,KAAK,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwD9C,SAAgB,uCACd,eACA,SACA,MACwB;CAGxB,MAAM,KAAK,QAAQ,eAAe;CAGlC,MAAM,OAAO,cAAc,QAAQ,eAAe,QAAQ,CAAC;CAG3D,MAAM,cAAc,cAAc,SAAS,MAAM,KAAK,MAAM,KAAK,CAAC,CAAC;AAqCnE,QAjC+B,SAAS,CAAC,GAAG,KAAK,GAAG,YAAY,IAAI,EAAE;EACpE,KAAK;EACL,UAAU;EACX,CAAC,CAG6D,KAAK,MAAM;EAExE,MAAM,eAAe,aAAa,GAAG,OAAO;EAG5C,MAAM,MAAM,GAAG,aAAa;EAI5B,MAAM,QAFW,cAAc,EAAE,CAAC,QAAQ,MAAM,GAAG,CAE5B,MAAM,2BAA2B;EACxD,IAAI,OAAO;EACX,IAAI,YAAY;AAChB,MAAI,OAAO;AACT,UAAO,MAAM;AACb,eAAY,MAAM,MAAM;;AAI1B,SAAO;GACL;GACA;GACA,MAAM;GACN,YAAY,IAAI;GAChB,SAAS;GACV;GACD"}
|