vike-lite 1.0.0

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/README.md ADDED
@@ -0,0 +1,60 @@
1
+ # vike-lite
2
+
3
+ ### ⬇️ Clone
4
+ ```sh
5
+ git clone https://github.com/node-ecosystem/vike-lite.git
6
+ ```
7
+
8
+ ### ⚙️ Install
9
+ | Package Manager | Command
10
+ | - | -
11
+ | **npm** | `npm install -D vike-lite`
12
+ | **yarn** | `yarn add -D vike-lite`
13
+ | **pnpm** | `pnpm add -D vike-lite`
14
+
15
+ ### 📖 Usage
16
+ Add Vite plugin
17
+
18
+ ```ts
19
+ // vite.config.ts
20
+ import vikeLite from 'vike-lite/vite'
21
+
22
+ export default {
23
+ plugins: [
24
+ vikeLite()
25
+ ]
26
+ }
27
+ ```
28
+
29
+ #### Hooks
30
+
31
+ ### renderPage
32
+ ```ts
33
+ // /server/index.ts
34
+ import { cors } from 'hono/cors'
35
+ import { Hono } from 'hono'
36
+ import { renderPage } from 'vike-lite/server'
37
+
38
+ import apiRoutes from './apiRoutes'
39
+
40
+ const app = new Hono()
41
+
42
+ if (process.env.NODE_ENV === 'production') {
43
+ app.use(cors())
44
+ }
45
+
46
+ app.route('/api', apiRoutes)
47
+
48
+ // Catch-all remaining requests using custom rendering
49
+ app.get('*', async (c, next) => {
50
+ const response = await renderPage(c.req.raw)
51
+ return response ?? next()
52
+ })
53
+
54
+ app.onError((error, c) => {
55
+ console.error(error)
56
+ return c.json({ error: 'Internal Server Error' }, 500)
57
+ })
58
+
59
+ export default app
60
+ ```
@@ -0,0 +1,24 @@
1
+ //#region src/shared/matchRoute.ts
2
+ function matchRoute(urlPathname, routes) {
3
+ for (const route of routes) {
4
+ const paramNames = [];
5
+ const regexPath = route.path.replaceAll(/:([^/]+)/g, (_, paramName) => {
6
+ paramNames.push(paramName);
7
+ return "([^/]+)";
8
+ });
9
+ const regex = new RegExp(`^${regexPath}/?$`);
10
+ const match = urlPathname.match(regex);
11
+ if (match) {
12
+ let index = 0;
13
+ const routeParams = {};
14
+ for (const name of paramNames) routeParams[name] = match[++index];
15
+ return {
16
+ route,
17
+ routeParams
18
+ };
19
+ }
20
+ }
21
+ return null;
22
+ }
23
+ //#endregion
24
+ export { matchRoute as t };
@@ -0,0 +1,16 @@
1
+ //#region src/server/store.d.ts
2
+ interface VikeState {
3
+ routes: any[];
4
+ errorRoute: any | null;
5
+ config: {
6
+ onRenderHtml: () => Promise<any>;
7
+ } | null;
8
+ manifest: Record<string, any> | undefined;
9
+ }
10
+ declare const store: VikeState;
11
+ declare function setVikeState(newState: Partial<VikeState>): void;
12
+ //#endregion
13
+ //#region src/server/renderPage.d.ts
14
+ declare function renderPage(req: Request): Promise<Response>;
15
+ //#endregion
16
+ export { VikeState, renderPage, setVikeState, store };
@@ -0,0 +1,172 @@
1
+ import { n as virtualEntryClientId } from "./virtuals-CR__ZAgP.mjs";
2
+ import { t as matchRoute } from "./matchRoute-BONrLRYy.mjs";
3
+ //#region src/server/store.ts
4
+ const store = {
5
+ routes: [],
6
+ errorRoute: null,
7
+ config: null,
8
+ manifest: void 0
9
+ };
10
+ function setVikeState(newState) {
11
+ Object.assign(store, newState);
12
+ }
13
+ //#endregion
14
+ //#region src/server/abort.ts
15
+ var AbortRender = class extends Error {
16
+ statusCode;
17
+ reason;
18
+ constructor(statusCode, reason) {
19
+ super(`Render aborted with status ${statusCode}: ${reason || ""}`);
20
+ this.statusCode = statusCode;
21
+ this.reason = reason;
22
+ }
23
+ };
24
+ //#endregion
25
+ //#region src/server/renderPage.tsx
26
+ const isProd = process.env.NODE_ENV === "production";
27
+ const ESCAPE_LOOKUP = {
28
+ "&": String.raw`\u0026`,
29
+ ">": String.raw`\u003e`,
30
+ "<": String.raw`\u003c`,
31
+ "\u2028": String.raw`\u2028`,
32
+ "\u2029": String.raw`\u2029`
33
+ };
34
+ const ESCAPE_REGEX = /[&><\u{2028}\u{2029}]/gu;
35
+ function serializeContext(data) {
36
+ return JSON.stringify(data).replaceAll(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]);
37
+ }
38
+ function getAssets(pageModuleId) {
39
+ if (!isProd) return {
40
+ cssLinks: "",
41
+ jsPreloads: "",
42
+ entryClient: "/@id/virtual:entry-client"
43
+ };
44
+ const cssFiles = /* @__PURE__ */ new Set();
45
+ const jsFiles = /* @__PURE__ */ new Set();
46
+ const manifest = store.manifest;
47
+ function collectAssets(key) {
48
+ const chunk = manifest[key];
49
+ if (!chunk) throw new Error(`Asset not found in manifest for key: ${key}`);
50
+ jsFiles.add(chunk.file);
51
+ if (chunk.css) for (const css of chunk.css) cssFiles.add(css);
52
+ if (chunk.imports) for (const imp of chunk.imports) collectAssets(imp);
53
+ }
54
+ collectAssets(virtualEntryClientId);
55
+ collectAssets(pageModuleId.replace("@/", ""));
56
+ return {
57
+ cssLinks: [...cssFiles].map((href) => `<link rel="stylesheet" href="/${href}">`).join(""),
58
+ jsPreloads: [...jsFiles].map((href) => `<link rel="modulepreload" href="/${href}">`).join(""),
59
+ entryClient: "/" + manifest[virtualEntryClientId].file
60
+ };
61
+ }
62
+ async function buildPageContext(pathname, fullUrl, isJsonRequest) {
63
+ const matched = matchRoute(pathname, store.routes);
64
+ if (!matched) return null;
65
+ const { route, routeParams } = matched;
66
+ const pageContext = {
67
+ routeParams,
68
+ urlOriginal: fullUrl,
69
+ urlPathname: pathname
70
+ };
71
+ const [dataMod, titleMod, PageModule, HeadModule, LayoutModule] = await Promise.all([
72
+ route.data?.() ?? null,
73
+ route.title?.() ?? null,
74
+ isJsonRequest ? null : route.Page(),
75
+ isJsonRequest ? null : route.Head?.() ?? null,
76
+ isJsonRequest ? null : route.Layout?.() ?? null
77
+ ]);
78
+ if (dataMod) try {
79
+ pageContext.data = await (dataMod.data ?? dataMod.default)(pageContext);
80
+ } catch (error) {
81
+ console.error("+data hook failed at:", pathname);
82
+ throw error;
83
+ }
84
+ if (titleMod) try {
85
+ const titleFn = titleMod.title ?? titleMod.default;
86
+ pageContext.title = typeof titleFn === "function" ? titleFn(pageContext) : titleFn;
87
+ } catch (error) {
88
+ console.error("+title hook failed at:", pathname);
89
+ throw error;
90
+ }
91
+ return {
92
+ pageContext,
93
+ route,
94
+ PageModule,
95
+ HeadModule,
96
+ LayoutModule
97
+ };
98
+ }
99
+ async function renderErrorPage(req, status, originalPathname, error) {
100
+ if (!store.errorRoute) return new Response(status === 404 ? "Not Found" : "Internal Server Error", { status });
101
+ try {
102
+ const { onRenderHtml } = await store.config.onRenderHtml();
103
+ const [PageModule, HeadModule, LayoutModule] = await Promise.all([
104
+ store.errorRoute.Page(),
105
+ store.errorRoute.Head?.() ?? null,
106
+ store.errorRoute.Layout?.() ?? null
107
+ ]);
108
+ const pageContext = {
109
+ urlOriginal: req.url,
110
+ urlPathname: originalPathname,
111
+ routeParams: {},
112
+ is404: status === 404,
113
+ is500: status === 500,
114
+ errorMessage: status === 500 && error instanceof Error ? error.message : void 0
115
+ };
116
+ const html = await onRenderHtml({
117
+ pageContext,
118
+ Page: PageModule.Page ?? PageModule.default,
119
+ Layout: LayoutModule ? LayoutModule.Layout ?? LayoutModule.default : void 0,
120
+ Head: HeadModule ? HeadModule.Head ?? HeadModule.default : void 0,
121
+ pageTitleTag: `<title>${status === 404 ? "Page Not Found" : "Server Error"}</title>`,
122
+ serializedContext: serializeContext(pageContext),
123
+ assets: getAssets(store.errorRoute.page)
124
+ });
125
+ return new Response(html, {
126
+ status,
127
+ headers: { "Content-Type": "text/html" }
128
+ });
129
+ } catch (renderError) {
130
+ console.error("Error page render failed:", renderError);
131
+ return new Response(status === 404 ? "Not Found" : "Internal Server Error", { status });
132
+ }
133
+ }
134
+ async function renderPage(req) {
135
+ const { pathname } = new URL(req.url);
136
+ const isJsonRequest = pathname.endsWith(".pageContext.json");
137
+ let targetPathname = pathname;
138
+ if (isJsonRequest) {
139
+ targetPathname = targetPathname.replace(/\.pageContext\.json$/, "");
140
+ if (targetPathname === "/index") targetPathname = "/";
141
+ }
142
+ try {
143
+ const resolved = await buildPageContext(targetPathname, req.url, isJsonRequest);
144
+ if (!resolved) {
145
+ if (isJsonRequest) return Response.json({ is404: true }, { status: 404 });
146
+ return renderErrorPage(req, 404, targetPathname);
147
+ }
148
+ const { pageContext, route, PageModule, HeadModule, LayoutModule } = resolved;
149
+ if (isJsonRequest) return Response.json(pageContext);
150
+ const { onRenderHtml } = await store.config.onRenderHtml();
151
+ const html = await onRenderHtml({
152
+ pageContext,
153
+ Page: PageModule.Page ?? PageModule.default,
154
+ Head: HeadModule ? HeadModule.Head ?? HeadModule.default : void 0,
155
+ Layout: LayoutModule ? LayoutModule.Layout ?? LayoutModule.default : void 0,
156
+ pageTitleTag: pageContext.title ? `<title>${pageContext.title}</title>` : "",
157
+ serializedContext: serializeContext(pageContext),
158
+ assets: getAssets(route.page)
159
+ });
160
+ return new Response(html, {
161
+ status: 200,
162
+ headers: { "Content-Type": "text/html" }
163
+ });
164
+ } catch (error) {
165
+ if (error instanceof AbortRender) return new Response(error.reason || "Not Found", { status: error.statusCode });
166
+ console.error("Render Error:", error);
167
+ if (isJsonRequest) return Response.json({ is500: true }, { status: 500 });
168
+ return renderErrorPage(req, 500, targetPathname, error);
169
+ }
170
+ }
171
+ //#endregion
172
+ export { renderPage, setVikeState, store };
@@ -0,0 +1,7 @@
1
+ //#region src/shared/matchRoute.d.ts
2
+ declare function matchRoute(urlPathname: string, routes: Route[]): {
3
+ route: Route;
4
+ routeParams: Record<string, string>;
5
+ } | null;
6
+ //#endregion
7
+ export { matchRoute };
@@ -0,0 +1,2 @@
1
+ import { t as matchRoute } from "./matchRoute-BONrLRYy.mjs";
2
+ export { matchRoute };
@@ -0,0 +1,8 @@
1
+ //#region src/virtuals.ts
2
+ const virtualModuleId = "virtual:routes";
3
+ const virtualManifestId = "virtual:client-manifest";
4
+ const virtualAdapterId = "virtual:vike-lite-adapter";
5
+ const virtualEntryClientId = "virtual:entry-client";
6
+ const virtualSetupId = "virtual:vike-lite/setup";
7
+ //#endregion
8
+ export { virtualSetupId as a, virtualModuleId as i, virtualEntryClientId as n, virtualManifestId as r, virtualAdapterId as t };
@@ -0,0 +1,14 @@
1
+ import { Plugin } from "vite";
2
+
3
+ //#region src/vite-plugin.d.ts
4
+ declare function routerPlugin({
5
+ pagesDir,
6
+ serverEntry,
7
+ apiPrefix
8
+ }?: {
9
+ pagesDir?: string | undefined;
10
+ serverEntry?: string | undefined;
11
+ apiPrefix?: string | undefined;
12
+ }): Plugin;
13
+ //#endregion
14
+ export { routerPlugin as default };
package/dist/vite.mjs ADDED
@@ -0,0 +1,245 @@
1
+ import { a as virtualSetupId, i as virtualModuleId, n as virtualEntryClientId, r as virtualManifestId, t as virtualAdapterId } from "./virtuals-CR__ZAgP.mjs";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { Readable } from "node:stream";
5
+ import { pipeline } from "node:stream/promises";
6
+ //#region src/vite-plugin.ts
7
+ function generateRoutes(pagesAbsPath) {
8
+ if (!fs.existsSync(pagesAbsPath)) return { routes: [] };
9
+ const routes = [];
10
+ let errorRoute;
11
+ function walk(dir, routePath, parentLayout, parentHead) {
12
+ const files = fs.readdirSync(dir);
13
+ const importPath = "@/pages" + (dir === pagesAbsPath ? "" : "/" + path.relative(pagesAbsPath, dir).replaceAll("\\", "/"));
14
+ const currentLayout = files.includes("+Layout.tsx") ? `${importPath}/+Layout.tsx` : parentLayout;
15
+ const currentHead = files.includes("+Head.tsx") ? `${importPath}/+Head.tsx` : parentHead;
16
+ if (files.includes("+Page.tsx")) {
17
+ const route = {
18
+ path: routePath || "/",
19
+ page: `${importPath}/+Page.tsx`,
20
+ hasData: files.includes("+data.ts"),
21
+ hasTitle: files.includes("+title.ts")
22
+ };
23
+ if (currentLayout) route.layout = currentLayout;
24
+ if (currentHead) route.head = currentHead;
25
+ routes.push(route);
26
+ }
27
+ for (const file of files) {
28
+ const fullPath = path.join(dir, file);
29
+ if (!fs.statSync(fullPath).isDirectory()) continue;
30
+ if (file === "_error") {
31
+ if (fs.readdirSync(fullPath).includes("+Page.tsx")) errorRoute = {
32
+ path: "_error",
33
+ page: `${importPath}/_error/+Page.tsx`,
34
+ layout: currentLayout,
35
+ head: currentHead
36
+ };
37
+ continue;
38
+ }
39
+ if (file.startsWith("_")) continue;
40
+ walk(fullPath, routePath + (routePath.endsWith("/") ? "" : "/") + file.replace(/^@/, ":"), currentLayout, currentHead);
41
+ }
42
+ }
43
+ walk(pagesAbsPath, "");
44
+ routes.sort((a, b) => {
45
+ const aDynamic = a.path.includes(":");
46
+ const bDynamic = b.path.includes(":");
47
+ if (aDynamic && !bDynamic) return 1;
48
+ if (!aDynamic && bDynamic) return -1;
49
+ return b.path.length - a.path.length;
50
+ });
51
+ const homeIndex = routes.findIndex((r) => r.path === "/index");
52
+ if (homeIndex !== -1) routes[homeIndex].path = "/";
53
+ return {
54
+ routes,
55
+ errorRoute
56
+ };
57
+ }
58
+ /**
59
+ * Anti-FOUC: Inspect all known SSR modules, ask the client environment
60
+ * to translate them into plain text (thanks to ?direct) and return them.
61
+ */
62
+ async function injectFOUCStyles(server, html) {
63
+ const styles = /* @__PURE__ */ new Set();
64
+ const ssrEnv = server.environments.ssr;
65
+ const clientEnv = server.environments.client;
66
+ for (const mod of ssrEnv.moduleGraph.idToModuleMap.values()) {
67
+ if (!(mod.file && /\.(css|scss|sass|less|styl|stylus)($|\?)/.test(mod.file))) continue;
68
+ const url = mod.url.split("?", 1)[0];
69
+ try {
70
+ const result = await clientEnv.transformRequest(url + "?direct");
71
+ if (result?.code) styles.add(result.code);
72
+ } catch {}
73
+ }
74
+ if (styles.size === 0) return html;
75
+ const headEndIndex = html.lastIndexOf("</head>");
76
+ const bodyEndIndex = html.lastIndexOf("</body>");
77
+ let cssContent = "";
78
+ for (const s of styles) cssContent += s;
79
+ const inlineCss = `<style type="text/css" data-vite-dev-fouc>${cssContent}</style>`;
80
+ return html.slice(0, headEndIndex) + inlineCss + html.slice(headEndIndex, bodyEndIndex) + `<script type="module" data-vite-dev-fouc-cleanup>requestAnimationFrame(()=>{document.querySelectorAll('[data-vite-dev-fouc]').forEach(el=>el.remove());document.currentScript?.remove();})<\/script>` + html.slice(bodyEndIndex);
81
+ }
82
+ function routerPlugin({ pagesDir = "pages", serverEntry = "server/index.ts", apiPrefix = "/api" } = {}) {
83
+ const isProd = process.env.NODE_ENV === "production";
84
+ let viteConfigRoot;
85
+ const resolvedVirtualModuleId = "\0" + virtualModuleId;
86
+ const resolvedVirtualManifestId = "\0" + virtualManifestId;
87
+ const resolvedVirtualEntryClientId = "\0" + virtualEntryClientId;
88
+ const resolvedVirtualSetupId = "\0" + virtualSetupId;
89
+ return {
90
+ name: "vike-lite",
91
+ config() {
92
+ return {
93
+ appType: "custom",
94
+ environments: {
95
+ client: { build: {
96
+ outDir: "../dist/client",
97
+ emptyOutDir: true,
98
+ cssMinify: true,
99
+ manifest: true,
100
+ rolldownOptions: {
101
+ input: virtualEntryClientId,
102
+ output: {
103
+ format: "esm",
104
+ entryFileNames: "assets/[name].[hash].js",
105
+ chunkFileNames: (chunkInfo) => {
106
+ if (chunkInfo.facadeModuleId?.includes(`/${pagesDir}/`)) return "assets/pages/[name].[hash].js";
107
+ return "assets/chunks/[name].[hash].js";
108
+ },
109
+ assetFileNames: "assets/static/[name].[hash][extname]"
110
+ }
111
+ }
112
+ } },
113
+ ssr: { build: {
114
+ target: "esnext",
115
+ outDir: "../dist/server",
116
+ emptyOutDir: true,
117
+ rolldownOptions: {
118
+ input: serverEntry,
119
+ output: {
120
+ format: "esm",
121
+ entryFileNames: "index.mjs",
122
+ chunkFileNames: (chunkInfo) => {
123
+ if (chunkInfo.facadeModuleId?.includes(`/${pagesDir}/`)) return "assets/pages/[name].[hash].mjs";
124
+ return "assets/chunks/[name].[hash].mjs";
125
+ }
126
+ }
127
+ }
128
+ } }
129
+ }
130
+ };
131
+ },
132
+ configResolved(config) {
133
+ viteConfigRoot = config.root;
134
+ },
135
+ resolveId(id) {
136
+ if (id === "virtual:routes") return resolvedVirtualModuleId;
137
+ if (id === "virtual:client-manifest") return resolvedVirtualManifestId;
138
+ if (id === "virtual:entry-client") return resolvedVirtualEntryClientId;
139
+ if (id === "virtual:vike-lite/setup") return resolvedVirtualSetupId;
140
+ },
141
+ async load(id, options) {
142
+ if (id === resolvedVirtualModuleId) {
143
+ const { routes, errorRoute } = generateRoutes(path.resolve(viteConfigRoot, pagesDir));
144
+ const isSSR = options.ssr;
145
+ let code = `import {onRenderClient,onRenderHtml} from '${virtualAdapterId}';export const config={onRenderClient,onRenderHtml};export const routes=[`;
146
+ for (const r of routes) {
147
+ code += `{path:'${r.path}',page:'${r.page}',hasData:${r.hasData},hasTitle:${r.hasTitle},Page:()=>import('${r.page}'),`;
148
+ if (r.head) code += `Head:()=>import('${r.head}'),`;
149
+ if (r.layout) code += `Layout:()=>import('${r.layout}'),`;
150
+ if (isSSR) {
151
+ if (r.hasData) code += `data:()=>import('${r.page.replace("+Page.tsx", "+data.ts")}'),`;
152
+ if (r.hasTitle) code += `title:()=>import('${r.page.replace("+Page.tsx", "+title.ts")}'),`;
153
+ }
154
+ code += "},";
155
+ }
156
+ code += "];";
157
+ if (errorRoute) {
158
+ const e = errorRoute;
159
+ code += `export const errorRoute={path:'${e.path}',page:'${e.page}',Page:()=>import('${e.page}'),`;
160
+ if (e.layout) code += `Layout:()=>import('${e.layout}'),`;
161
+ if (e.head) code += `Head:()=>import('${e.head}'),`;
162
+ code += "};";
163
+ } else code += "export const errorRoute=null;";
164
+ return code;
165
+ }
166
+ if (id === resolvedVirtualManifestId) {
167
+ if (!isProd || !options?.ssr) return "";
168
+ const manifestPath = path.join(viteConfigRoot, "../dist/client/.vite/manifest.json");
169
+ return `export default ${fs.readFileSync(manifestPath, "utf8")}`;
170
+ }
171
+ if (id === resolvedVirtualEntryClientId) return `import{onRenderClient}from'${virtualAdapterId}';onRenderClient();`;
172
+ if (id === resolvedVirtualManifestId) {
173
+ if (!isProd || !options?.ssr) return "export default {}";
174
+ const manifestPath = path.join(viteConfigRoot, "../dist/client/.vite/manifest.json");
175
+ return `export default ${fs.readFileSync(manifestPath, "utf8")}`;
176
+ }
177
+ if (id === resolvedVirtualSetupId) return `
178
+ // 1. Importa i dati virtuali generati da Vite
179
+ import { routes, errorRoute, config } from '${virtualModuleId}';
180
+
181
+ // 2. Importa il setter dal TUO pacchetto compilato (assicurati di esportarlo nel package.json)
182
+ import { setVikeState } from 'vike-lite/store';
183
+
184
+ // 3. Risolve il manifest per la build di produzione
185
+ let manifest;
186
+ if (process.env.NODE_ENV === 'production') {
187
+ manifest = (await import('${virtualManifestId}')).default;
188
+ }
189
+
190
+ // 4. INIETTA lo stato in memoria!
191
+ setVikeState({ routes, errorRoute, config, manifest });
192
+ `;
193
+ },
194
+ configureServer(server) {
195
+ return () => {
196
+ server.middlewares.use(async (req, res, next) => {
197
+ try {
198
+ const ssrEnv = server.environments.ssr;
199
+ const absoluteServerEntry = path.join(viteConfigRoot, serverEntry);
200
+ const { default: app } = await ssrEnv.runner.import(absoluteServerEntry);
201
+ const headers = new Headers();
202
+ for (const [key, value] of Object.entries(req.headers)) {
203
+ if (key.startsWith(":")) continue;
204
+ if (Array.isArray(value)) for (const v of value) headers.append(key, v);
205
+ else if (value !== void 0) headers.set(key, value);
206
+ }
207
+ const requestInit = {
208
+ method: req.method,
209
+ headers
210
+ };
211
+ if (req.url.startsWith(apiPrefix)) {
212
+ server.config.logger.info(`API request: ${req.method} ${req.url}`, { timestamp: true });
213
+ requestInit.body = Readable.toWeb(req);
214
+ requestInit.duplex = "half";
215
+ } else if (req.url.endsWith(".pageContext.json")) server.config.logger.info(`SPA Navigation request: ${req.url}`, { timestamp: true });
216
+ const response = await app.fetch(new Request(`http://${req.headers.host}${req.url}`, requestInit));
217
+ res.statusCode = response.status;
218
+ if (response.headers.get("content-type")?.includes("text/html")) {
219
+ server.config.logger.info(`Page request: ${req.url}`, { timestamp: true });
220
+ let html = await response.text();
221
+ html = await injectFOUCStyles(server, html);
222
+ html = await server.transformIndexHtml(req.url, html);
223
+ res.setHeader("Content-Type", "text/html");
224
+ res.end(html);
225
+ return;
226
+ }
227
+ for (const [key, value] of response.headers) res.setHeader(key, value);
228
+ if (!response.body) {
229
+ res.end();
230
+ return;
231
+ }
232
+ if (res.destroyed || res.closed) return;
233
+ try {
234
+ await pipeline(Readable.fromWeb(response.body), res);
235
+ } catch {}
236
+ } catch (error) {
237
+ next(error);
238
+ }
239
+ });
240
+ };
241
+ }
242
+ };
243
+ }
244
+ //#endregion
245
+ export { routerPlugin as default };
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "vike-lite",
3
+ "version": "1.0.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.mts",
8
+ "exports": {
9
+ "./vite": {
10
+ "import": "./dist/vite.mjs",
11
+ "types": "./dist/vite.d.mts"
12
+ },
13
+ "./server": {
14
+ "import": "./dist/server.mjs",
15
+ "types": "./dist/server.d.mts"
16
+ },
17
+ "./shared": {
18
+ "import": "./dist/shared.mjs",
19
+ "types": "./dist/shared.d.mts"
20
+ }
21
+ },
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://github.com/node-ecosystem/vike-lite.git"
25
+ },
26
+ "homepage": "https://github.com/node-ecosystem/vike-lite#readme",
27
+ "bugs": {
28
+ "url": "https://github.com/node-ecosystem/vike-lite/issues"
29
+ },
30
+ "files": [
31
+ "dist"
32
+ ],
33
+ "scripts": {
34
+ "lint": "eslint src/**/*.{ts,tsx} *.ts",
35
+ "build": "tsdown",
36
+ "od": "yarn outdated"
37
+ },
38
+ "devDependencies": {
39
+ "@types/node": "^26.0.0",
40
+ "@yarnpkg/sdks": "^3.3.0",
41
+ "eslint": "^10.5.0",
42
+ "eslint-plugin-unicorn": "^68.0.0",
43
+ "tsdown": "^0.22.3",
44
+ "typescript": "^6.0.3",
45
+ "typescript-eslint": "^8.62.0",
46
+ "vite": "^8.1.0"
47
+ },
48
+ "peerDependencies": {
49
+ "vite": ">=8"
50
+ },
51
+ "engines": {
52
+ "node": ">=22"
53
+ },
54
+ "packageManager": "yarn@4.17.0"
55
+ }