@edgeone/nuxt-pages 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 +275 -0
- package/dist/build/content/server.js +18 -0
- package/dist/build/content/static.js +17 -0
- package/dist/build/functions/server.js +19 -0
- package/dist/build/plugin-context.js +18 -0
- package/dist/build/routes.js +18 -0
- package/dist/build/templates/nuxt-handler-backup.js +305 -0
- package/dist/build/templates/nuxt-handler-monorepo.tmpl-ipx_backup.js +511 -0
- package/dist/build/templates/nuxt-handler-monorepo.tmpl.js +243 -0
- package/dist/build/templates/nuxt-handler.tmpl.js +212 -0
- package/dist/esm-chunks/chunk-5YBUNNZ4.js +81 -0
- package/dist/esm-chunks/chunk-6BT4RYQJ.js +43 -0
- package/dist/esm-chunks/chunk-6YERJDAJ.js +208 -0
- package/dist/esm-chunks/chunk-GX4Z7KQX.js +15065 -0
- package/dist/esm-chunks/chunk-HBXUWFGE.js +19 -0
- package/dist/esm-chunks/chunk-HY3HNABZ.js +87 -0
- package/dist/esm-chunks/chunk-KGYBHZC3.js +1467 -0
- package/dist/esm-chunks/chunk-MMMRMLH2.js +132 -0
- package/dist/esm-chunks/chunk-NJ4SUJNF.js +5635 -0
- package/dist/esm-chunks/chunk-QG7JLDXY.js +127 -0
- package/dist/esm-chunks/chunk-RPSYO4VM.js +562 -0
- package/dist/esm-chunks/chunk-UOPC2N5A.js +69 -0
- package/dist/esm-chunks/chunk-V2LFVP3C.js +838 -0
- package/dist/index.js +61 -0
- package/dist/run/config.js +17 -0
- package/dist/run/constants.js +17 -0
- package/dist/run/handlers/cache.cjs +1410 -0
- package/dist/run/handlers/nuxt-cache.cjs +200 -0
- package/dist/run/handlers/nuxt-server.js +156 -0
- package/dist/run/handlers/request-context.cjs +148 -0
- package/dist/run/handlers/server.js +77 -0
- package/dist/run/handlers/tags-handler.cjs +177 -0
- package/dist/run/handlers/tracer.cjs +1004 -0
- package/dist/run/handlers/use-cache-handler.js +220 -0
- package/dist/run/handlers/wait-until.cjs +123 -0
- package/dist/run/headers.js +17 -0
- package/dist/run/revalidate.js +34 -0
- package/dist/run/storage/regional-blob-store.cjs +64 -0
- package/dist/run/storage/request-scoped-in-memory-cache.cjs +1582 -0
- package/dist/run/storage/storage.cjs +191 -0
- package/dist/shared/blob-types.cjs +37 -0
- package/dist/shared/blobkey.js +25 -0
- package/dist/shared/cache-types.cjs +33 -0
- package/dist/shared/nuxt-cache-types.cjs +18 -0
- package/dist/types/options.js +6 -0
- package/dist/utils.js +25 -0
- package/package.json +58 -0
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { resolve, dirname } from 'path';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
import { readFileSync, existsSync, statSync } from 'fs';
|
|
4
|
+
import { extname } from 'path';
|
|
5
|
+
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = dirname(__filename);
|
|
8
|
+
|
|
9
|
+
// Static assets directory
|
|
10
|
+
const ASSET_DIR = resolve(__dirname, '../assets');
|
|
11
|
+
|
|
12
|
+
// MIME type mapping
|
|
13
|
+
const MIME_TYPES = {
|
|
14
|
+
'.html': 'text/html; charset=utf-8',
|
|
15
|
+
'.js': 'application/javascript',
|
|
16
|
+
'.css': 'text/css',
|
|
17
|
+
'.json': 'application/json',
|
|
18
|
+
'.png': 'image/png',
|
|
19
|
+
'.jpg': 'image/jpeg',
|
|
20
|
+
'.jpeg': 'image/jpeg',
|
|
21
|
+
'.gif': 'image/gif',
|
|
22
|
+
'.svg': 'image/svg+xml',
|
|
23
|
+
'.ico': 'image/x-icon',
|
|
24
|
+
'.txt': 'text/plain',
|
|
25
|
+
'.xml': 'application/xml'
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Get the MIME type of a file
|
|
30
|
+
*/
|
|
31
|
+
function getMimeType(filePath) {
|
|
32
|
+
const ext = extname(filePath).toLowerCase();
|
|
33
|
+
return MIME_TYPES[ext] || 'application/octet-stream';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Handle static file requests
|
|
38
|
+
*/
|
|
39
|
+
function handleStaticFile(url) {
|
|
40
|
+
try {
|
|
41
|
+
// Remove query parameters
|
|
42
|
+
let cleanUrl = url.split('?')[0];
|
|
43
|
+
|
|
44
|
+
// Handle IPX image processing paths from @nuxt/image
|
|
45
|
+
// Convert /_ipx/s_800x600/hero.png to /hero.png
|
|
46
|
+
// Also handles nested paths: /_ipx/s_800x600/images/hero.png -> /images/hero.png
|
|
47
|
+
if (cleanUrl.startsWith('/_ipx/')) {
|
|
48
|
+
let newUrl = '';
|
|
49
|
+
|
|
50
|
+
// Remove /_ipx/ prefix
|
|
51
|
+
const ipxPath = cleanUrl.slice(6); // Remove '/_ipx/'
|
|
52
|
+
|
|
53
|
+
// IPX format: /_ipx/[params]/[original_path]
|
|
54
|
+
// Parameters are typically the first segment(s) and contain underscores/commas
|
|
55
|
+
// The original file path starts after the params
|
|
56
|
+
const pathSegments = ipxPath.split('/').filter(s => s); // Remove empty segments
|
|
57
|
+
|
|
58
|
+
if (pathSegments.length === 0) {
|
|
59
|
+
// Empty path after /_ipx/, skip
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Check each segment for file extension
|
|
64
|
+
for (let i = 0; i < pathSegments.length; i++) {
|
|
65
|
+
const segment = pathSegments[i];
|
|
66
|
+
if(segment.startsWith('s_') || segment.startsWith('w_') || segment.startsWith('h_') || segment.startsWith('q_') || segment.startsWith('f_') || segment.startsWith('c_') || segment.startsWith('bg_') || segment.startsWith('blur_') || segment.startsWith('_')) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
// Check if segment ends with a known image extension
|
|
70
|
+
newUrl += '/' + segment;
|
|
71
|
+
}
|
|
72
|
+
if(cleanUrl.includes('http://') || cleanUrl.includes('https://')) {
|
|
73
|
+
newUrl = cleanUrl.includes('http://') ? cleanUrl.slice(cleanUrl.indexOf('http://')) : cleanUrl.slice(cleanUrl.indexOf('https://'));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
statusCode: 302,
|
|
78
|
+
headers: {
|
|
79
|
+
'from-server': 'true',
|
|
80
|
+
location: newUrl
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if(cleanUrl.includes('-ssr-functions/_ipx/')) {
|
|
86
|
+
let newUrl = '';
|
|
87
|
+
const pathSegments = cleanUrl.split('/') // Remove empty segments
|
|
88
|
+
if(pathSegments.length === 0) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
// Check each segment for file extension
|
|
92
|
+
newUrl = pathSegments.slice(4).join('/');
|
|
93
|
+
if(newUrl.includes('http:/') && !newUrl.includes('http://')) {
|
|
94
|
+
newUrl = newUrl.replace('http:/', 'http://');
|
|
95
|
+
} else if(newUrl.includes('https:/') && !newUrl.includes('https://')) {
|
|
96
|
+
newUrl = newUrl.replace('https:/', 'https://');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
statusCode: 302,
|
|
101
|
+
headers: {
|
|
102
|
+
'from-server': 'true',
|
|
103
|
+
location: newUrl
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// 本地调试寻找文件路径
|
|
109
|
+
const possiblePaths = [];
|
|
110
|
+
|
|
111
|
+
// Direct file path
|
|
112
|
+
const directPath = resolve(ASSET_DIR, cleanUrl.startsWith('/') ? cleanUrl.slice(1) : cleanUrl);
|
|
113
|
+
possiblePaths.push(directPath);
|
|
114
|
+
|
|
115
|
+
// Try each possible path
|
|
116
|
+
for (const filePath of possiblePaths) {
|
|
117
|
+
// Security check: ensure file is within asset directory
|
|
118
|
+
if (!filePath.startsWith(ASSET_DIR)) {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (existsSync(filePath) && statSync(filePath).isFile()) {
|
|
123
|
+
const content = readFileSync(filePath);
|
|
124
|
+
const mimeType = getMimeType(filePath);
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
statusCode: 200,
|
|
128
|
+
headers: {
|
|
129
|
+
'Content-Type': mimeType,
|
|
130
|
+
'Content-Length': content.length.toString(),
|
|
131
|
+
'Cache-Control': 'public, max-age=31536000' // 1 year cache
|
|
132
|
+
},
|
|
133
|
+
body: content
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
} catch (error) {
|
|
138
|
+
console.error('Static file error:', error);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Lazy load Nitro application
|
|
146
|
+
*/
|
|
147
|
+
let nitroApp = null;
|
|
148
|
+
async function getNitroApp() {
|
|
149
|
+
if (!nitroApp) {
|
|
150
|
+
// Set environment variables to prevent automatic server startup
|
|
151
|
+
process.env.NITRO_PORT = '';
|
|
152
|
+
process.env.PORT = '';
|
|
153
|
+
|
|
154
|
+
// Set correct static assets path
|
|
155
|
+
process.env.NITRO_PUBLIC_DIR = ASSET_DIR;
|
|
156
|
+
|
|
157
|
+
const { {{USE_NITRO_APP_SYMBOL}}: useNitroApp } = await import('./chunks/nitro/nitro.mjs');
|
|
158
|
+
nitroApp = useNitroApp();
|
|
159
|
+
}
|
|
160
|
+
return nitroApp;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
async function getBody(req) {
|
|
164
|
+
if (req.method !== 'GET' && req.method !== 'HEAD') {
|
|
165
|
+
const chunks = [];
|
|
166
|
+
for await (const chunk of req) {
|
|
167
|
+
chunks.push(chunk);
|
|
168
|
+
}
|
|
169
|
+
const body = Buffer.concat(chunks).toString();
|
|
170
|
+
return body;
|
|
171
|
+
}
|
|
172
|
+
return '';
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* EdgeOne function handler
|
|
177
|
+
*/
|
|
178
|
+
export default async function handler(req, res, context) {
|
|
179
|
+
try {
|
|
180
|
+
const url = req.url || '/';
|
|
181
|
+
const method = req.method || 'GET';
|
|
182
|
+
const headers = req.headers || new Headers();
|
|
183
|
+
const body = await getBody(req);
|
|
184
|
+
|
|
185
|
+
// First try to handle static assets
|
|
186
|
+
if (method === 'GET') {
|
|
187
|
+
const staticResponse = handleStaticFile(url);
|
|
188
|
+
if (staticResponse) {
|
|
189
|
+
return new Response(staticResponse.body, {
|
|
190
|
+
status: staticResponse.statusCode,
|
|
191
|
+
headers: staticResponse.headers
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Handle dynamic requests
|
|
197
|
+
const app = await getNitroApp();
|
|
198
|
+
|
|
199
|
+
try {
|
|
200
|
+
const response = await app.localCall({
|
|
201
|
+
url,
|
|
202
|
+
method,
|
|
203
|
+
headers,
|
|
204
|
+
body
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
return new Response(response.body, {
|
|
208
|
+
status: response.statusCode,
|
|
209
|
+
headers: response.headers
|
|
210
|
+
});
|
|
211
|
+
} catch (nitroError) {
|
|
212
|
+
// Handle Nitro static file read errors (prerender files not found)
|
|
213
|
+
// Check error and its cause property (H3Error may wrap actual error in cause)
|
|
214
|
+
const actualError = nitroError?.cause || nitroError;
|
|
215
|
+
const errorPath = actualError?.path || nitroError?.path;
|
|
216
|
+
const errorCode = actualError?.code || nitroError?.code;
|
|
217
|
+
|
|
218
|
+
// If error is due to prerender static file not found, try dynamic rendering
|
|
219
|
+
if (errorCode === 'ENOENT' &&
|
|
220
|
+
errorPath &&
|
|
221
|
+
(errorPath.includes('/assets/') || errorPath.includes('assets/')) &&
|
|
222
|
+
(errorPath.includes('/index.html') || errorPath.includes('index.html'))) {
|
|
223
|
+
console.warn(`Prerender file not found: ${errorPath}, falling back to dynamic rendering for ${url}`);
|
|
224
|
+
|
|
225
|
+
// If static file handling has been tried but file not found, should perform dynamic rendering
|
|
226
|
+
// Nitro should be able to handle dynamic routes, but if it still tries to read static files,
|
|
227
|
+
// it may be due to configuration issues. We throw an error directly to let user know to build or check configuration
|
|
228
|
+
throw new Error(`Prerender route ${url} not found. Make sure to run build first or configure routeRules correctly. Original error: ${actualError?.message || nitroError?.message}`);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Other errors are thrown directly
|
|
232
|
+
throw nitroError;
|
|
233
|
+
}
|
|
234
|
+
} catch (error) {
|
|
235
|
+
return new Response(`Server Error: ${error.message}`, {
|
|
236
|
+
status: 500,
|
|
237
|
+
headers: {
|
|
238
|
+
'Content-Type': 'text/plain'
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
// import { createServer } from 'http';
|
|
2
|
+
// import {
|
|
3
|
+
// createRequestContext,
|
|
4
|
+
// runWithRequestContext,
|
|
5
|
+
// } from './.edgeone/dist/run/handlers/request-context.cjs';
|
|
6
|
+
// import {
|
|
7
|
+
// createEdgeOneNuxtServerHandler,
|
|
8
|
+
// defaultEdgeOneNuxtConfig
|
|
9
|
+
// } from './.edgeone/dist/run/handlers/nuxt-server.cjs';
|
|
10
|
+
// import {
|
|
11
|
+
// createEdgeOneNuxtCacheHandler
|
|
12
|
+
// } from './.edgeone/dist/run/handlers/nuxt-cache.cjs';
|
|
13
|
+
|
|
14
|
+
// // Initialize Nuxt server handler
|
|
15
|
+
// const nuxtServerHandler = createEdgeOneNuxtServerHandler(defaultEdgeOneNuxtConfig);
|
|
16
|
+
|
|
17
|
+
// async function handleResponse(res, response, passHeaders = {}) {
|
|
18
|
+
// const startTime = Date.now();
|
|
19
|
+
|
|
20
|
+
// if (!response) {
|
|
21
|
+
// res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
22
|
+
// res.end(JSON.stringify({
|
|
23
|
+
// error: "Not Found",
|
|
24
|
+
// message: "The requested path does not exist"
|
|
25
|
+
// }));
|
|
26
|
+
// console.log(`HandleResponse: 404 Not Found - ${Date.now() - startTime}ms`);
|
|
27
|
+
// return;
|
|
28
|
+
// }
|
|
29
|
+
|
|
30
|
+
// try {
|
|
31
|
+
// if (response instanceof Response) {
|
|
32
|
+
// const headers = Object.fromEntries(response.headers);
|
|
33
|
+
// Object.assign(headers, passHeaders);
|
|
34
|
+
|
|
35
|
+
// // Handle set-cookie headers properly
|
|
36
|
+
// if (response.headers.has('set-cookie')) {
|
|
37
|
+
// const cookieArr = response.headers.getSetCookie();
|
|
38
|
+
// headers['set-cookie'] = cookieArr;
|
|
39
|
+
// }
|
|
40
|
+
|
|
41
|
+
// res.writeHead(response.status, headers);
|
|
42
|
+
|
|
43
|
+
// if (response.body) {
|
|
44
|
+
// const arrayBuffer = await response.arrayBuffer();
|
|
45
|
+
// res.end(Buffer.from(arrayBuffer));
|
|
46
|
+
// } else {
|
|
47
|
+
// res.end();
|
|
48
|
+
// }
|
|
49
|
+
// } else {
|
|
50
|
+
// // Handle non-Response objects
|
|
51
|
+
// res.writeHead(200, { 'Content-Type': 'application/json', ...passHeaders });
|
|
52
|
+
// res.end(JSON.stringify(response));
|
|
53
|
+
// }
|
|
54
|
+
// } catch (error) {
|
|
55
|
+
// console.error('Error in handleResponse:', error);
|
|
56
|
+
// res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
57
|
+
// res.end(JSON.stringify({
|
|
58
|
+
// error: "Internal Server Error",
|
|
59
|
+
// message: error.message
|
|
60
|
+
// }));
|
|
61
|
+
// } finally {
|
|
62
|
+
// console.log(`HandleResponse: ${response?.status || 'unknown'} - ${Date.now() - startTime}ms`);
|
|
63
|
+
// }
|
|
64
|
+
// }
|
|
65
|
+
|
|
66
|
+
// // Enable regional blobs for EdgeOne
|
|
67
|
+
// process.env.USE_REGIONAL_BLOBS = 'true';
|
|
68
|
+
|
|
69
|
+
// export default async function handler(req, context) {
|
|
70
|
+
// const requestContext = createRequestContext(req, context);
|
|
71
|
+
|
|
72
|
+
// // Initialize cache handler for this request
|
|
73
|
+
// const cacheHandler = createEdgeOneNuxtCacheHandler({
|
|
74
|
+
// maxMemoryCacheSize: 50 * 1024 * 1024, // 50MB
|
|
75
|
+
// revalidateOnStale: true
|
|
76
|
+
// });
|
|
77
|
+
|
|
78
|
+
// // Add cache handler to request context
|
|
79
|
+
// requestContext.cacheHandler = cacheHandler;
|
|
80
|
+
|
|
81
|
+
// const handlerResponse = await runWithRequestContext(requestContext, async () => {
|
|
82
|
+
// try {
|
|
83
|
+
// // Convert Node.js request to Web API Request
|
|
84
|
+
// const url = new URL(req.url, `http://${req.headers.host}`);
|
|
85
|
+
// const method = req.method || 'GET';
|
|
86
|
+
|
|
87
|
+
// let body = null;
|
|
88
|
+
// if (method !== 'GET' && method !== 'HEAD') {
|
|
89
|
+
// body = createReadableStreamFromRequest(req);
|
|
90
|
+
// }
|
|
91
|
+
|
|
92
|
+
// const webRequest = new Request(url.toString(), {
|
|
93
|
+
// method,
|
|
94
|
+
// headers: req.headers,
|
|
95
|
+
// body
|
|
96
|
+
// });
|
|
97
|
+
|
|
98
|
+
// // Handle request with Nuxt server handler
|
|
99
|
+
// return await nuxtServerHandler.handleRequest(webRequest, requestContext);
|
|
100
|
+
// } catch (error) {
|
|
101
|
+
// console.error('Error in Nuxt handler:', error);
|
|
102
|
+
|
|
103
|
+
// return new Response(JSON.stringify({
|
|
104
|
+
// error: 'Internal Server Error',
|
|
105
|
+
// message: error.message,
|
|
106
|
+
// timestamp: new Date().toISOString()
|
|
107
|
+
// }), {
|
|
108
|
+
// status: 500,
|
|
109
|
+
// headers: {
|
|
110
|
+
// 'Content-Type': 'application/json',
|
|
111
|
+
// 'X-Handled-By': 'EdgeOne-Nuxt-Error'
|
|
112
|
+
// }
|
|
113
|
+
// });
|
|
114
|
+
// }
|
|
115
|
+
// });
|
|
116
|
+
|
|
117
|
+
// return handlerResponse;
|
|
118
|
+
// }
|
|
119
|
+
|
|
120
|
+
// export const config = {
|
|
121
|
+
// path: '/*',
|
|
122
|
+
// preferStatic: true,
|
|
123
|
+
// };
|
|
124
|
+
|
|
125
|
+
// // Development server configuration
|
|
126
|
+
// const port = 9000;
|
|
127
|
+
|
|
128
|
+
// // Convert Node.js request stream to Web API ReadableStream
|
|
129
|
+
// function createReadableStreamFromRequest(req) {
|
|
130
|
+
// return new ReadableStream({
|
|
131
|
+
// start(controller) {
|
|
132
|
+
// req.on('data', chunk => {
|
|
133
|
+
// // Convert Buffer to Uint8Array
|
|
134
|
+
// const uint8Array = new Uint8Array(chunk);
|
|
135
|
+
// controller.enqueue(uint8Array);
|
|
136
|
+
// });
|
|
137
|
+
|
|
138
|
+
// req.on('end', () => {
|
|
139
|
+
// controller.close();
|
|
140
|
+
// });
|
|
141
|
+
|
|
142
|
+
// req.on('error', error => {
|
|
143
|
+
// controller.error(error);
|
|
144
|
+
// });
|
|
145
|
+
// },
|
|
146
|
+
|
|
147
|
+
// cancel() {
|
|
148
|
+
// // Clean up resources
|
|
149
|
+
// req.destroy();
|
|
150
|
+
// }
|
|
151
|
+
// });
|
|
152
|
+
// }
|
|
153
|
+
|
|
154
|
+
// // Development server for local testing
|
|
155
|
+
// // Start development server directly when running the script
|
|
156
|
+
// const server = createServer(async (req, res) => {
|
|
157
|
+
// try {
|
|
158
|
+
// const response = await handler(req, { waitUntil: () => {} });
|
|
159
|
+
// await handleResponse(res, response);
|
|
160
|
+
// } catch (error) {
|
|
161
|
+
// console.error('Development server error:', error);
|
|
162
|
+
// res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
163
|
+
// res.end(JSON.stringify({
|
|
164
|
+
// error: 'Development Server Error',
|
|
165
|
+
// message: error.message
|
|
166
|
+
// }));
|
|
167
|
+
// }
|
|
168
|
+
// });
|
|
169
|
+
|
|
170
|
+
// server.listen(port, () => {
|
|
171
|
+
// console.log(`Nuxt development server running on http://localhost:${port}`);
|
|
172
|
+
// });
|
|
173
|
+
|
|
174
|
+
// Ensure Nitro can read import.meta and env like in built index
|
|
175
|
+
globalThis._importMeta_ = { url: import.meta.url, env: process.env };
|
|
176
|
+
|
|
177
|
+
// Choose port
|
|
178
|
+
process.env.NITRO_PORT = process.env.NITRO_PORT || '9000';
|
|
179
|
+
process.env.PORT = process.env.PORT || process.env.NITRO_PORT;
|
|
180
|
+
|
|
181
|
+
// Import and execute Nitro server (top-level code starts the server)
|
|
182
|
+
const nitroModule = await import('./chunks/nitro/nitro.mjs');
|
|
183
|
+
|
|
184
|
+
// Get useNitroApp (your build exports it as `k`)
|
|
185
|
+
const useNitroApp = nitroModule.k || nitroModule.useNitroApp;
|
|
186
|
+
if (!useNitroApp) {
|
|
187
|
+
console.error('useNitroApp not found in nitro module exports');
|
|
188
|
+
process.exit(1);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const nitroApp = useNitroApp();
|
|
192
|
+
|
|
193
|
+
// Request interceptor
|
|
194
|
+
nitroApp.hooks.hook('request', async (event) => {
|
|
195
|
+
const { req } = event.node;
|
|
196
|
+
console.log(`📥 [${new Date().toISOString()}] ${req.method} ${req.url}`);
|
|
197
|
+
console.log('📋 Request Headers:', req.headers);
|
|
198
|
+
// Example: mark request source
|
|
199
|
+
req.headers['x-intercepted-by'] = 'custom-hooks';
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
// Response interceptor
|
|
203
|
+
nitroApp.hooks.hook('beforeResponse', async (event, response) => {
|
|
204
|
+
const { res } = event.node;
|
|
205
|
+
console.log(`📤 [${new Date().toISOString()}] Status: ${res.statusCode}`);
|
|
206
|
+
console.log('📋 Response Headers:', res.getHeaders());
|
|
207
|
+
// Example: add a custom header
|
|
208
|
+
res.setHeader('x-intercepted', 'true');
|
|
209
|
+
return response;
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
console.log('🔍 Request/Response interception enabled (run-with-hooks)');
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
|
|
2
|
+
var require = await (async () => {
|
|
3
|
+
var { createRequire } = await import("node:module");
|
|
4
|
+
return createRequire(import.meta.url);
|
|
5
|
+
})();
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
// src/run/headers.ts
|
|
9
|
+
var getHeaderValueArray = (header) => {
|
|
10
|
+
return header.split(",").map((value) => value.trim()).filter(Boolean);
|
|
11
|
+
};
|
|
12
|
+
var omitHeaderValues = (header, values) => {
|
|
13
|
+
const headerValues = getHeaderValueArray(header);
|
|
14
|
+
const filteredValues = headerValues.filter(
|
|
15
|
+
(value) => !values.some((val) => value.startsWith(val))
|
|
16
|
+
);
|
|
17
|
+
return filteredValues.join(", ");
|
|
18
|
+
};
|
|
19
|
+
function setCacheControlFromRequestContext(headers, revalidate) {
|
|
20
|
+
const cdnCacheControl = (
|
|
21
|
+
// if we are serving already stale response, instruct edge to not attempt to cache that response
|
|
22
|
+
headers.get("x-nextjs-cache") === "STALE" ? "public, max-age=0, must-revalidate, durable" : `s-maxage=${revalidate || 31536e3}, stale-while-revalidate=31536000, durable`
|
|
23
|
+
);
|
|
24
|
+
headers.set("eo-cdn-cache-control", cdnCacheControl);
|
|
25
|
+
}
|
|
26
|
+
var setCacheControlHeaders = ({ headers, status }, request, requestContext) => {
|
|
27
|
+
if (typeof requestContext.routeHandlerRevalidate !== "undefined" && ["GET", "HEAD"].includes(request.method) && !headers.has("cdn-cache-control") && !headers.has("eo-cdn-cache-control")) {
|
|
28
|
+
setCacheControlFromRequestContext(headers, requestContext.routeHandlerRevalidate);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (status === 404) {
|
|
32
|
+
if (request.url.endsWith(".php")) {
|
|
33
|
+
headers.set("cache-control", "public, max-age=0, must-revalidate");
|
|
34
|
+
headers.set("eo-cdn-cache-control", `max-age=31536000, durable`);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (process.env.CACHE_404_PAGE && request.url.endsWith("/404") && ["GET", "HEAD"].includes(request.method)) {
|
|
38
|
+
setCacheControlFromRequestContext(headers, requestContext.pageHandlerRevalidate);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const cacheControl = headers.get("cache-control");
|
|
43
|
+
if (cacheControl !== null && ["GET", "HEAD"].includes(request.method) && !headers.has("cdn-cache-control") && !headers.has("eo-cdn-cache-control")) {
|
|
44
|
+
const browserCacheControl = omitHeaderValues(cacheControl, [
|
|
45
|
+
"s-maxage",
|
|
46
|
+
"stale-while-revalidate"
|
|
47
|
+
]);
|
|
48
|
+
const cdnCacheControl = (
|
|
49
|
+
// if we are serving already stale response, instruct edge to not attempt to cache that response
|
|
50
|
+
headers.get("x-nextjs-cache") === "STALE" ? "public, max-age=0, must-revalidate, durable" : [
|
|
51
|
+
...getHeaderValueArray(cacheControl).map(
|
|
52
|
+
(value) => value === "stale-while-revalidate" ? "stale-while-revalidate=31536000" : value
|
|
53
|
+
),
|
|
54
|
+
"durable"
|
|
55
|
+
].join(", ")
|
|
56
|
+
);
|
|
57
|
+
headers.set("cache-control", browserCacheControl || "public, max-age=0, must-revalidate");
|
|
58
|
+
headers.set("eo-cdn-cache-control", cdnCacheControl);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (cacheControl === null && ["GET", "HEAD"].includes(request.method) && !headers.has("cdn-cache-control") && !headers.has("eo-cdn-cache-control") && requestContext.usedFsReadForNonFallback && !requestContext.didPagesRouterOnDemandRevalidate) {
|
|
62
|
+
headers.set("cache-control", "public, max-age=0, must-revalidate");
|
|
63
|
+
headers.set("eo-cdn-cache-control", `max-age=31536000, durable`);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
var setCacheTagsHeaders = (headers, requestContext) => {
|
|
67
|
+
if (!headers.has("cache-control")) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
var setCacheStatusHeader = (headers, nextCache) => {
|
|
72
|
+
if (headers.has("x-nextjs-cache")) {
|
|
73
|
+
headers.delete("x-nextjs-cache");
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export {
|
|
78
|
+
setCacheControlHeaders,
|
|
79
|
+
setCacheTagsHeaders,
|
|
80
|
+
setCacheStatusHeader
|
|
81
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
|
|
2
|
+
var require = await (async () => {
|
|
3
|
+
var { createRequire } = await import("node:module");
|
|
4
|
+
return createRequire(import.meta.url);
|
|
5
|
+
})();
|
|
6
|
+
|
|
7
|
+
var __create = Object.create;
|
|
8
|
+
var __defProp = Object.defineProperty;
|
|
9
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
10
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
11
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
12
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
13
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
14
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
15
|
+
}) : x)(function(x) {
|
|
16
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
17
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
18
|
+
});
|
|
19
|
+
var __commonJS = (cb, mod) => function __require2() {
|
|
20
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
21
|
+
};
|
|
22
|
+
var __copyProps = (to, from, except, desc) => {
|
|
23
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
24
|
+
for (let key of __getOwnPropNames(from))
|
|
25
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
26
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
27
|
+
}
|
|
28
|
+
return to;
|
|
29
|
+
};
|
|
30
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
31
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
32
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
33
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
34
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
35
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
36
|
+
mod
|
|
37
|
+
));
|
|
38
|
+
|
|
39
|
+
export {
|
|
40
|
+
__require,
|
|
41
|
+
__commonJS,
|
|
42
|
+
__toESM
|
|
43
|
+
};
|