@marko/run 0.0.1-beta1 → 0.0.1-beta2
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/adapter/default-entry.mjs +1 -1
- package/dist/adapter/index.cjs +1 -1
- package/dist/adapter/index.js +1 -1
- package/dist/vite/utils/route.d.ts +1 -1
- package/package.json +1 -1
- package/dist/adapter/server-old.d.ts +0 -3
- package/dist/adapter/server.d.ts +0 -6
- package/dist/adapters/node/index.d.ts +0 -5
- package/dist/adapters/node/server.d.ts +0 -3
- package/dist/adapters/static/crawler.d.ts +0 -9
- package/dist/adapters/static/default-entry.mjs +0 -1
- package/dist/adapters/static/index.cjs +0 -371
- package/dist/adapters/static/index.d.ts +0 -5
- package/dist/adapters/static/index.js +0 -341
- package/dist/adapters/static/server.d.ts +0 -3
- package/dist/runtime/request.d.ts +0 -4
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import createStaticServe from "serve-static";
|
|
2
2
|
import { createServer } from "http";
|
|
3
3
|
import { createMiddleware } from "@hattip/adapter-node";
|
|
4
|
-
import { handler } from "@marko/run";
|
|
4
|
+
import { handler } from "@marko/run/router";
|
|
5
5
|
|
|
6
6
|
const { PORT = 3456 } = process.env;
|
|
7
7
|
|
package/dist/adapter/index.cjs
CHANGED
|
@@ -64,7 +64,7 @@ async function createDevServer(configFile) {
|
|
|
64
64
|
});
|
|
65
65
|
const middleware = createViteDevMiddleware(
|
|
66
66
|
devServer,
|
|
67
|
-
async () => (await devServer.ssrLoadModule("@marko/run")).handler,
|
|
67
|
+
async () => (await devServer.ssrLoadModule("@marko/run/router")).handler,
|
|
68
68
|
import_adapter_node.createMiddleware
|
|
69
69
|
);
|
|
70
70
|
return devServer.middlewares.use(middleware);
|
package/dist/adapter/index.js
CHANGED
|
@@ -32,7 +32,7 @@ async function createDevServer(configFile) {
|
|
|
32
32
|
});
|
|
33
33
|
const middleware = createViteDevMiddleware(
|
|
34
34
|
devServer,
|
|
35
|
-
async () => (await devServer.ssrLoadModule("@marko/run")).handler,
|
|
35
|
+
async () => (await devServer.ssrLoadModule("@marko/run/router")).handler,
|
|
36
36
|
createMiddleware
|
|
37
37
|
);
|
|
38
38
|
return devServer.middlewares.use(middleware);
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { HttpVerb, Route } from "../types";
|
|
2
|
-
export declare function getVerbs(route: Route): ("get" | "
|
|
2
|
+
export declare function getVerbs(route: Route): ("get" | "delete" | "post" | "put")[];
|
|
3
3
|
export declare function hasVerb(route: Route, verb: HttpVerb): boolean | import("../types").RoutableFile | undefined;
|
package/package.json
CHANGED
package/dist/adapter/server.d.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
import { ViteDevServer } from "vite";
|
|
3
|
-
import { type NodeMiddleware } from "@hattip/adapter-node";
|
|
4
|
-
import type { Server } from "http";
|
|
5
|
-
export declare function createViteDevMiddleware<T>(devServer: ViteDevServer, load: (prev: T | undefined) => Promise<T>, factory: (value: T) => NodeMiddleware): NodeMiddleware;
|
|
6
|
-
export default function (entryFile?: string): Promise<Server>;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export interface Options {
|
|
2
|
-
out?: string;
|
|
3
|
-
origin?: string;
|
|
4
|
-
notFoundPath?: string;
|
|
5
|
-
}
|
|
6
|
-
export interface Crawler {
|
|
7
|
-
crawl(paths: string[]): Promise<void>;
|
|
8
|
-
}
|
|
9
|
-
export default function createCrawler(makeRequest: (request: Request) => Promise<Response>, opts?: Options): Crawler;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { router } from '@marko/run';
|
|
@@ -1,371 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
-
for (let key of __getOwnPropNames(from))
|
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
-
}
|
|
18
|
-
return to;
|
|
19
|
-
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
-
mod
|
|
23
|
-
));
|
|
24
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
25
|
-
|
|
26
|
-
// src/adapters/static/index.ts
|
|
27
|
-
var static_exports = {};
|
|
28
|
-
__export(static_exports, {
|
|
29
|
-
default: () => staticAdapter
|
|
30
|
-
});
|
|
31
|
-
module.exports = __toCommonJS(static_exports);
|
|
32
|
-
var import_path2 = __toESM(require("path"), 1);
|
|
33
|
-
var import_url = require("url");
|
|
34
|
-
var import_undici = require("undici");
|
|
35
|
-
|
|
36
|
-
// src/adapters/static/crawler.ts
|
|
37
|
-
var import_fs = __toESM(require("fs"), 1);
|
|
38
|
-
var import_path = __toESM(require("path"), 1);
|
|
39
|
-
var import_WritableStream = require("htmlparser2/lib/WritableStream");
|
|
40
|
-
var noop = () => {
|
|
41
|
-
};
|
|
42
|
-
var ignoredRels = /* @__PURE__ */ new Set(["nofollow", "enclosure", "external"]);
|
|
43
|
-
var contentType = "text/html";
|
|
44
|
-
function createCrawler(makeRequest, opts = {}) {
|
|
45
|
-
const origin = opts.origin || `http://localhost`;
|
|
46
|
-
const out = import_path.default.resolve(opts.out || "dist");
|
|
47
|
-
const notFoundPath = resolvePath(opts.notFoundPath || "/404/", origin);
|
|
48
|
-
let seen;
|
|
49
|
-
let queue;
|
|
50
|
-
let pending;
|
|
51
|
-
async function visit(path2) {
|
|
52
|
-
var _a, _b;
|
|
53
|
-
const parser = new import_WritableStream.WritableStream({
|
|
54
|
-
onopentag(name, attrs) {
|
|
55
|
-
const href = resolveHref(name, attrs);
|
|
56
|
-
const path3 = href && resolvePath(href, origin);
|
|
57
|
-
if (path3 !== void 0 && !seen.has(path3)) {
|
|
58
|
-
seen.add(path3);
|
|
59
|
-
queue.push(visit(path3));
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
const dirname = import_path.default.join(out, path2);
|
|
64
|
-
const abortController = new AbortController();
|
|
65
|
-
let fsWriter;
|
|
66
|
-
try {
|
|
67
|
-
const url = new URL(path2, origin);
|
|
68
|
-
const req = new Request(url, {
|
|
69
|
-
method: "GET",
|
|
70
|
-
signal: abortController.signal,
|
|
71
|
-
headers: { accept: contentType }
|
|
72
|
-
});
|
|
73
|
-
const res = await makeRequest(req);
|
|
74
|
-
if (!((_a = res.headers.get("content-type")) == null ? void 0 : _a.includes(contentType))) {
|
|
75
|
-
abortController.abort();
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
let redirect;
|
|
79
|
-
switch (res.status) {
|
|
80
|
-
case 200:
|
|
81
|
-
break;
|
|
82
|
-
case 404:
|
|
83
|
-
if (path2 !== notFoundPath) {
|
|
84
|
-
redirect = origin + notFoundPath;
|
|
85
|
-
}
|
|
86
|
-
break;
|
|
87
|
-
case 301: {
|
|
88
|
-
redirect = res.headers.get("location");
|
|
89
|
-
const redirectPath = resolvePath(redirect, origin);
|
|
90
|
-
if (redirectPath && !seen.has(redirectPath)) {
|
|
91
|
-
seen.add(redirectPath);
|
|
92
|
-
queue.push(visit(redirectPath));
|
|
93
|
-
}
|
|
94
|
-
break;
|
|
95
|
-
}
|
|
96
|
-
default: {
|
|
97
|
-
abortController.abort();
|
|
98
|
-
console.warn(`Status code ${res.status} was while crawling: '${path2}'`);
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
await import_fs.default.promises.mkdir(dirname, { recursive: true }).catch(noop);
|
|
103
|
-
fsWriter = import_fs.default.createWriteStream(import_path.default.join(dirname, "index.html"));
|
|
104
|
-
if (redirect) {
|
|
105
|
-
abortController.abort();
|
|
106
|
-
fsWriter.write(
|
|
107
|
-
`<!DOCTYPE html><meta http-equiv=Refresh content="0;url=${redirect.replace(
|
|
108
|
-
/"/g,
|
|
109
|
-
"("
|
|
110
|
-
)}">`
|
|
111
|
-
);
|
|
112
|
-
} else {
|
|
113
|
-
const writable = new WritableStream({
|
|
114
|
-
write(data) {
|
|
115
|
-
fsWriter.write(data);
|
|
116
|
-
parser.write(data);
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
await ((_b = res.body) == null ? void 0 : _b.pipeTo(writable));
|
|
120
|
-
}
|
|
121
|
-
} finally {
|
|
122
|
-
fsWriter == null ? void 0 : fsWriter.end();
|
|
123
|
-
parser.end();
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
return {
|
|
127
|
-
async crawl(paths = ["/"]) {
|
|
128
|
-
if (pending) {
|
|
129
|
-
await pending;
|
|
130
|
-
}
|
|
131
|
-
const startPaths = paths.map((path2) => resolvePath(path2, origin)).concat(notFoundPath);
|
|
132
|
-
seen = new Set(startPaths);
|
|
133
|
-
try {
|
|
134
|
-
queue = startPaths.map(visit);
|
|
135
|
-
while (queue.length) {
|
|
136
|
-
pending = Promise.all(queue);
|
|
137
|
-
queue = [];
|
|
138
|
-
await pending;
|
|
139
|
-
}
|
|
140
|
-
} finally {
|
|
141
|
-
pending = void 0;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
function resolveHref(tagName, attrs) {
|
|
147
|
-
switch (tagName) {
|
|
148
|
-
case "a":
|
|
149
|
-
if (attrs.href && !(attrs.download || ignoredRels.has(attrs.rel))) {
|
|
150
|
-
return attrs.href;
|
|
151
|
-
}
|
|
152
|
-
break;
|
|
153
|
-
case "link":
|
|
154
|
-
if (attrs.href) {
|
|
155
|
-
switch (attrs.rel) {
|
|
156
|
-
case "alternate":
|
|
157
|
-
case "author":
|
|
158
|
-
case "canonical":
|
|
159
|
-
case "help":
|
|
160
|
-
case "license":
|
|
161
|
-
case "next":
|
|
162
|
-
case "prefetch":
|
|
163
|
-
case "prerender":
|
|
164
|
-
case "prev":
|
|
165
|
-
case "search":
|
|
166
|
-
case "tag":
|
|
167
|
-
return attrs.href;
|
|
168
|
-
case "preload":
|
|
169
|
-
if (attrs.as === "document") {
|
|
170
|
-
return attrs.href;
|
|
171
|
-
}
|
|
172
|
-
break;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
break;
|
|
176
|
-
case "iframe":
|
|
177
|
-
return attrs.src;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
function resolvePath(href, origin) {
|
|
181
|
-
const url = new URL(href, origin);
|
|
182
|
-
if (url.origin === origin) {
|
|
183
|
-
let { pathname } = url;
|
|
184
|
-
const lastChar = pathname.length - 1;
|
|
185
|
-
if (pathname[lastChar] !== "/") {
|
|
186
|
-
pathname += "/";
|
|
187
|
-
}
|
|
188
|
-
return pathname + url.search;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// src/adapters/static/index.ts
|
|
193
|
-
var import_promises = __toESM(require("fs/promises"), 1);
|
|
194
|
-
|
|
195
|
-
// src/vite/utils/server.ts
|
|
196
|
-
var import_net = __toESM(require("net"), 1);
|
|
197
|
-
var import_child_process = __toESM(require("child_process"), 1);
|
|
198
|
-
async function spawnServer(cmd, port = 0, wait = 3e4) {
|
|
199
|
-
if (port <= 0) {
|
|
200
|
-
port = await getAvailablePort();
|
|
201
|
-
}
|
|
202
|
-
const proc = import_child_process.default.spawn(cmd, {
|
|
203
|
-
shell: true,
|
|
204
|
-
stdio: "inherit",
|
|
205
|
-
windowsHide: true,
|
|
206
|
-
env: { ...process.env, PORT: `${port}` }
|
|
207
|
-
});
|
|
208
|
-
const close = () => {
|
|
209
|
-
proc.unref();
|
|
210
|
-
proc.kill();
|
|
211
|
-
};
|
|
212
|
-
let remaining = wait > 0 ? wait : Infinity;
|
|
213
|
-
while (!await isPortInUse(port)) {
|
|
214
|
-
if (remaining >= 100) {
|
|
215
|
-
remaining -= 100;
|
|
216
|
-
await sleep(100);
|
|
217
|
-
} else {
|
|
218
|
-
close();
|
|
219
|
-
throw new Error(
|
|
220
|
-
`site-write: timeout while wating for server to start on port "${port}".`
|
|
221
|
-
);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
return close;
|
|
225
|
-
}
|
|
226
|
-
async function isPortInUse(port) {
|
|
227
|
-
return new Promise((resolve) => {
|
|
228
|
-
const connection = import_net.default.connect(port).setNoDelay(true).setKeepAlive(false).on("error", () => done(false)).on("connect", () => done(true));
|
|
229
|
-
function done(connected) {
|
|
230
|
-
connection.end();
|
|
231
|
-
resolve(connected);
|
|
232
|
-
}
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
async function getAvailablePort() {
|
|
236
|
-
return new Promise((resolve) => {
|
|
237
|
-
const server = import_net.default.createServer().listen(0, () => {
|
|
238
|
-
const { port } = server.address();
|
|
239
|
-
server.close(() => resolve(port));
|
|
240
|
-
});
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
function sleep(ms) {
|
|
244
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// src/adapters/static/server.ts
|
|
248
|
-
var import_serve_static = __toESM(require("serve-static"), 1);
|
|
249
|
-
var import_http = require("http");
|
|
250
|
-
var import_vite = require("vite");
|
|
251
|
-
var import_adapter_node = require("@hattip/adapter-node");
|
|
252
|
-
function noop2() {
|
|
253
|
-
}
|
|
254
|
-
async function server_default(dir) {
|
|
255
|
-
if (dir) {
|
|
256
|
-
const staticServe = (0, import_serve_static.default)(dir, {
|
|
257
|
-
index: "index.html",
|
|
258
|
-
immutable: true,
|
|
259
|
-
maxAge: "365 days"
|
|
260
|
-
});
|
|
261
|
-
return await (0, import_http.createServer)((req, res) => staticServe(req, res, noop2));
|
|
262
|
-
}
|
|
263
|
-
const devServer = await (0, import_vite.createServer)({
|
|
264
|
-
appType: "custom",
|
|
265
|
-
server: { middlewareMode: true }
|
|
266
|
-
});
|
|
267
|
-
let handler;
|
|
268
|
-
let middleware;
|
|
269
|
-
return devServer.middlewares.use(async (req, res, next) => {
|
|
270
|
-
try {
|
|
271
|
-
const module2 = await devServer.ssrLoadModule("@marko/run");
|
|
272
|
-
if (module2.handler !== handler) {
|
|
273
|
-
handler = module2.handler;
|
|
274
|
-
middleware = (0, import_adapter_node.createMiddleware)(handler);
|
|
275
|
-
}
|
|
276
|
-
await middleware(req, res, next);
|
|
277
|
-
} catch (err) {
|
|
278
|
-
if (err instanceof Error) {
|
|
279
|
-
devServer.ssrFixStacktrace(err);
|
|
280
|
-
}
|
|
281
|
-
return next(err);
|
|
282
|
-
}
|
|
283
|
-
});
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
// src/adapters/static/index.ts
|
|
287
|
-
var import_meta = {};
|
|
288
|
-
var __dirname = (0, import_url.fileURLToPath)(new URL(".", import_meta.url));
|
|
289
|
-
function staticAdapter(_options = {}) {
|
|
290
|
-
return {
|
|
291
|
-
name: "static-adapter",
|
|
292
|
-
async config(_options2) {
|
|
293
|
-
return {
|
|
294
|
-
codegen: {
|
|
295
|
-
trailingSlashes: "RedirectWith"
|
|
296
|
-
}
|
|
297
|
-
};
|
|
298
|
-
},
|
|
299
|
-
async getEntryFile() {
|
|
300
|
-
return import_path2.default.join(__dirname, "default-entry");
|
|
301
|
-
},
|
|
302
|
-
async startServer(port, dir) {
|
|
303
|
-
const server = await server_default(dir);
|
|
304
|
-
server.on("error", (err) => {
|
|
305
|
-
console.error(err);
|
|
306
|
-
process.exit(1);
|
|
307
|
-
});
|
|
308
|
-
return new Promise((resolve) => {
|
|
309
|
-
const listener = server.listen(port, () => {
|
|
310
|
-
const address = listener.address();
|
|
311
|
-
console.log(`Server started: http://localhost:${address.port}`);
|
|
312
|
-
resolve();
|
|
313
|
-
});
|
|
314
|
-
});
|
|
315
|
-
},
|
|
316
|
-
async buildEnd(routes, builtEntries, sourceEntries) {
|
|
317
|
-
var _a;
|
|
318
|
-
const pathsToVisit = [];
|
|
319
|
-
for (const route of routes) {
|
|
320
|
-
if (!((_a = route.params) == null ? void 0 : _a.length)) {
|
|
321
|
-
pathsToVisit.push(route.path);
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
const defaultEntry = await this.getEntryFile();
|
|
325
|
-
if (sourceEntries[0] === defaultEntry) {
|
|
326
|
-
const { router } = await import(builtEntries[0]);
|
|
327
|
-
const crawler = createCrawler(router, {});
|
|
328
|
-
await crawler.crawl(pathsToVisit);
|
|
329
|
-
} else {
|
|
330
|
-
const port = await getAvailablePort();
|
|
331
|
-
const origin = `http://localhost:${port}`;
|
|
332
|
-
const client = new import_undici.Pool(origin);
|
|
333
|
-
const closeServer = await spawnServer(`node ${builtEntries[0]}`, port);
|
|
334
|
-
const crawler = createCrawler(
|
|
335
|
-
async (request) => {
|
|
336
|
-
const url = new URL(request.url);
|
|
337
|
-
const headers = {};
|
|
338
|
-
request.headers.forEach((value, key) => {
|
|
339
|
-
headers[key] = value;
|
|
340
|
-
});
|
|
341
|
-
const responseData = await client.request({
|
|
342
|
-
path: url.pathname + url.search,
|
|
343
|
-
method: request.method,
|
|
344
|
-
signal: request.signal,
|
|
345
|
-
headers
|
|
346
|
-
});
|
|
347
|
-
return new Response(responseData.body, {
|
|
348
|
-
status: responseData.statusCode,
|
|
349
|
-
headers: responseData.headers
|
|
350
|
-
});
|
|
351
|
-
},
|
|
352
|
-
{
|
|
353
|
-
origin
|
|
354
|
-
}
|
|
355
|
-
);
|
|
356
|
-
try {
|
|
357
|
-
await crawler.crawl(pathsToVisit);
|
|
358
|
-
} finally {
|
|
359
|
-
await client.close();
|
|
360
|
-
closeServer();
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
for (const file of builtEntries) {
|
|
364
|
-
await import_promises.default.rm(file, { maxRetries: 5 }).catch(() => {
|
|
365
|
-
});
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
};
|
|
369
|
-
}
|
|
370
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
371
|
-
0 && (module.exports = {});
|
|
@@ -1,341 +0,0 @@
|
|
|
1
|
-
// src/adapters/static/index.ts
|
|
2
|
-
import path from "path";
|
|
3
|
-
import { fileURLToPath } from "url";
|
|
4
|
-
import { Pool } from "undici";
|
|
5
|
-
|
|
6
|
-
// src/adapters/static/crawler.ts
|
|
7
|
-
import fs from "fs";
|
|
8
|
-
import nodePath from "path";
|
|
9
|
-
import { WritableStream as Parser } from "htmlparser2/lib/WritableStream";
|
|
10
|
-
var noop = () => {
|
|
11
|
-
};
|
|
12
|
-
var ignoredRels = /* @__PURE__ */ new Set(["nofollow", "enclosure", "external"]);
|
|
13
|
-
var contentType = "text/html";
|
|
14
|
-
function createCrawler(makeRequest, opts = {}) {
|
|
15
|
-
const origin = opts.origin || `http://localhost`;
|
|
16
|
-
const out = nodePath.resolve(opts.out || "dist");
|
|
17
|
-
const notFoundPath = resolvePath(opts.notFoundPath || "/404/", origin);
|
|
18
|
-
let seen;
|
|
19
|
-
let queue;
|
|
20
|
-
let pending;
|
|
21
|
-
async function visit(path2) {
|
|
22
|
-
var _a, _b;
|
|
23
|
-
const parser = new Parser({
|
|
24
|
-
onopentag(name, attrs) {
|
|
25
|
-
const href = resolveHref(name, attrs);
|
|
26
|
-
const path3 = href && resolvePath(href, origin);
|
|
27
|
-
if (path3 !== void 0 && !seen.has(path3)) {
|
|
28
|
-
seen.add(path3);
|
|
29
|
-
queue.push(visit(path3));
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
const dirname = nodePath.join(out, path2);
|
|
34
|
-
const abortController = new AbortController();
|
|
35
|
-
let fsWriter;
|
|
36
|
-
try {
|
|
37
|
-
const url = new URL(path2, origin);
|
|
38
|
-
const req = new Request(url, {
|
|
39
|
-
method: "GET",
|
|
40
|
-
signal: abortController.signal,
|
|
41
|
-
headers: { accept: contentType }
|
|
42
|
-
});
|
|
43
|
-
const res = await makeRequest(req);
|
|
44
|
-
if (!((_a = res.headers.get("content-type")) == null ? void 0 : _a.includes(contentType))) {
|
|
45
|
-
abortController.abort();
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
let redirect;
|
|
49
|
-
switch (res.status) {
|
|
50
|
-
case 200:
|
|
51
|
-
break;
|
|
52
|
-
case 404:
|
|
53
|
-
if (path2 !== notFoundPath) {
|
|
54
|
-
redirect = origin + notFoundPath;
|
|
55
|
-
}
|
|
56
|
-
break;
|
|
57
|
-
case 301: {
|
|
58
|
-
redirect = res.headers.get("location");
|
|
59
|
-
const redirectPath = resolvePath(redirect, origin);
|
|
60
|
-
if (redirectPath && !seen.has(redirectPath)) {
|
|
61
|
-
seen.add(redirectPath);
|
|
62
|
-
queue.push(visit(redirectPath));
|
|
63
|
-
}
|
|
64
|
-
break;
|
|
65
|
-
}
|
|
66
|
-
default: {
|
|
67
|
-
abortController.abort();
|
|
68
|
-
console.warn(`Status code ${res.status} was while crawling: '${path2}'`);
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
await fs.promises.mkdir(dirname, { recursive: true }).catch(noop);
|
|
73
|
-
fsWriter = fs.createWriteStream(nodePath.join(dirname, "index.html"));
|
|
74
|
-
if (redirect) {
|
|
75
|
-
abortController.abort();
|
|
76
|
-
fsWriter.write(
|
|
77
|
-
`<!DOCTYPE html><meta http-equiv=Refresh content="0;url=${redirect.replace(
|
|
78
|
-
/"/g,
|
|
79
|
-
"("
|
|
80
|
-
)}">`
|
|
81
|
-
);
|
|
82
|
-
} else {
|
|
83
|
-
const writable = new WritableStream({
|
|
84
|
-
write(data) {
|
|
85
|
-
fsWriter.write(data);
|
|
86
|
-
parser.write(data);
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
await ((_b = res.body) == null ? void 0 : _b.pipeTo(writable));
|
|
90
|
-
}
|
|
91
|
-
} finally {
|
|
92
|
-
fsWriter == null ? void 0 : fsWriter.end();
|
|
93
|
-
parser.end();
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
return {
|
|
97
|
-
async crawl(paths = ["/"]) {
|
|
98
|
-
if (pending) {
|
|
99
|
-
await pending;
|
|
100
|
-
}
|
|
101
|
-
const startPaths = paths.map((path2) => resolvePath(path2, origin)).concat(notFoundPath);
|
|
102
|
-
seen = new Set(startPaths);
|
|
103
|
-
try {
|
|
104
|
-
queue = startPaths.map(visit);
|
|
105
|
-
while (queue.length) {
|
|
106
|
-
pending = Promise.all(queue);
|
|
107
|
-
queue = [];
|
|
108
|
-
await pending;
|
|
109
|
-
}
|
|
110
|
-
} finally {
|
|
111
|
-
pending = void 0;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
function resolveHref(tagName, attrs) {
|
|
117
|
-
switch (tagName) {
|
|
118
|
-
case "a":
|
|
119
|
-
if (attrs.href && !(attrs.download || ignoredRels.has(attrs.rel))) {
|
|
120
|
-
return attrs.href;
|
|
121
|
-
}
|
|
122
|
-
break;
|
|
123
|
-
case "link":
|
|
124
|
-
if (attrs.href) {
|
|
125
|
-
switch (attrs.rel) {
|
|
126
|
-
case "alternate":
|
|
127
|
-
case "author":
|
|
128
|
-
case "canonical":
|
|
129
|
-
case "help":
|
|
130
|
-
case "license":
|
|
131
|
-
case "next":
|
|
132
|
-
case "prefetch":
|
|
133
|
-
case "prerender":
|
|
134
|
-
case "prev":
|
|
135
|
-
case "search":
|
|
136
|
-
case "tag":
|
|
137
|
-
return attrs.href;
|
|
138
|
-
case "preload":
|
|
139
|
-
if (attrs.as === "document") {
|
|
140
|
-
return attrs.href;
|
|
141
|
-
}
|
|
142
|
-
break;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
break;
|
|
146
|
-
case "iframe":
|
|
147
|
-
return attrs.src;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
function resolvePath(href, origin) {
|
|
151
|
-
const url = new URL(href, origin);
|
|
152
|
-
if (url.origin === origin) {
|
|
153
|
-
let { pathname } = url;
|
|
154
|
-
const lastChar = pathname.length - 1;
|
|
155
|
-
if (pathname[lastChar] !== "/") {
|
|
156
|
-
pathname += "/";
|
|
157
|
-
}
|
|
158
|
-
return pathname + url.search;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// src/adapters/static/index.ts
|
|
163
|
-
import fs2 from "fs/promises";
|
|
164
|
-
|
|
165
|
-
// src/vite/utils/server.ts
|
|
166
|
-
import net from "net";
|
|
167
|
-
import cp from "child_process";
|
|
168
|
-
async function spawnServer(cmd, port = 0, wait = 3e4) {
|
|
169
|
-
if (port <= 0) {
|
|
170
|
-
port = await getAvailablePort();
|
|
171
|
-
}
|
|
172
|
-
const proc = cp.spawn(cmd, {
|
|
173
|
-
shell: true,
|
|
174
|
-
stdio: "inherit",
|
|
175
|
-
windowsHide: true,
|
|
176
|
-
env: { ...process.env, PORT: `${port}` }
|
|
177
|
-
});
|
|
178
|
-
const close = () => {
|
|
179
|
-
proc.unref();
|
|
180
|
-
proc.kill();
|
|
181
|
-
};
|
|
182
|
-
let remaining = wait > 0 ? wait : Infinity;
|
|
183
|
-
while (!await isPortInUse(port)) {
|
|
184
|
-
if (remaining >= 100) {
|
|
185
|
-
remaining -= 100;
|
|
186
|
-
await sleep(100);
|
|
187
|
-
} else {
|
|
188
|
-
close();
|
|
189
|
-
throw new Error(
|
|
190
|
-
`site-write: timeout while wating for server to start on port "${port}".`
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
return close;
|
|
195
|
-
}
|
|
196
|
-
async function isPortInUse(port) {
|
|
197
|
-
return new Promise((resolve) => {
|
|
198
|
-
const connection = net.connect(port).setNoDelay(true).setKeepAlive(false).on("error", () => done(false)).on("connect", () => done(true));
|
|
199
|
-
function done(connected) {
|
|
200
|
-
connection.end();
|
|
201
|
-
resolve(connected);
|
|
202
|
-
}
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
async function getAvailablePort() {
|
|
206
|
-
return new Promise((resolve) => {
|
|
207
|
-
const server = net.createServer().listen(0, () => {
|
|
208
|
-
const { port } = server.address();
|
|
209
|
-
server.close(() => resolve(port));
|
|
210
|
-
});
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
function sleep(ms) {
|
|
214
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// src/adapters/static/server.ts
|
|
218
|
-
import createStaticServe from "serve-static";
|
|
219
|
-
import { createServer as createHttpServer } from "http";
|
|
220
|
-
import { createServer as createDevServer } from "vite";
|
|
221
|
-
import { createMiddleware } from "@hattip/adapter-node";
|
|
222
|
-
function noop2() {
|
|
223
|
-
}
|
|
224
|
-
async function server_default(dir) {
|
|
225
|
-
if (dir) {
|
|
226
|
-
const staticServe = createStaticServe(dir, {
|
|
227
|
-
index: "index.html",
|
|
228
|
-
immutable: true,
|
|
229
|
-
maxAge: "365 days"
|
|
230
|
-
});
|
|
231
|
-
return await createHttpServer((req, res) => staticServe(req, res, noop2));
|
|
232
|
-
}
|
|
233
|
-
const devServer = await createDevServer({
|
|
234
|
-
appType: "custom",
|
|
235
|
-
server: { middlewareMode: true }
|
|
236
|
-
});
|
|
237
|
-
let handler;
|
|
238
|
-
let middleware;
|
|
239
|
-
return devServer.middlewares.use(async (req, res, next) => {
|
|
240
|
-
try {
|
|
241
|
-
const module = await devServer.ssrLoadModule("@marko/run");
|
|
242
|
-
if (module.handler !== handler) {
|
|
243
|
-
handler = module.handler;
|
|
244
|
-
middleware = createMiddleware(handler);
|
|
245
|
-
}
|
|
246
|
-
await middleware(req, res, next);
|
|
247
|
-
} catch (err) {
|
|
248
|
-
if (err instanceof Error) {
|
|
249
|
-
devServer.ssrFixStacktrace(err);
|
|
250
|
-
}
|
|
251
|
-
return next(err);
|
|
252
|
-
}
|
|
253
|
-
});
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
// src/adapters/static/index.ts
|
|
257
|
-
var __dirname = fileURLToPath(new URL(".", import.meta.url));
|
|
258
|
-
function staticAdapter(_options = {}) {
|
|
259
|
-
return {
|
|
260
|
-
name: "static-adapter",
|
|
261
|
-
async config(_options2) {
|
|
262
|
-
return {
|
|
263
|
-
codegen: {
|
|
264
|
-
trailingSlashes: "RedirectWith"
|
|
265
|
-
}
|
|
266
|
-
};
|
|
267
|
-
},
|
|
268
|
-
async getEntryFile() {
|
|
269
|
-
return path.join(__dirname, "default-entry");
|
|
270
|
-
},
|
|
271
|
-
async startServer(port, dir) {
|
|
272
|
-
const server = await server_default(dir);
|
|
273
|
-
server.on("error", (err) => {
|
|
274
|
-
console.error(err);
|
|
275
|
-
process.exit(1);
|
|
276
|
-
});
|
|
277
|
-
return new Promise((resolve) => {
|
|
278
|
-
const listener = server.listen(port, () => {
|
|
279
|
-
const address = listener.address();
|
|
280
|
-
console.log(`Server started: http://localhost:${address.port}`);
|
|
281
|
-
resolve();
|
|
282
|
-
});
|
|
283
|
-
});
|
|
284
|
-
},
|
|
285
|
-
async buildEnd(routes, builtEntries, sourceEntries) {
|
|
286
|
-
var _a;
|
|
287
|
-
const pathsToVisit = [];
|
|
288
|
-
for (const route of routes) {
|
|
289
|
-
if (!((_a = route.params) == null ? void 0 : _a.length)) {
|
|
290
|
-
pathsToVisit.push(route.path);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
const defaultEntry = await this.getEntryFile();
|
|
294
|
-
if (sourceEntries[0] === defaultEntry) {
|
|
295
|
-
const { router } = await import(builtEntries[0]);
|
|
296
|
-
const crawler = createCrawler(router, {});
|
|
297
|
-
await crawler.crawl(pathsToVisit);
|
|
298
|
-
} else {
|
|
299
|
-
const port = await getAvailablePort();
|
|
300
|
-
const origin = `http://localhost:${port}`;
|
|
301
|
-
const client = new Pool(origin);
|
|
302
|
-
const closeServer = await spawnServer(`node ${builtEntries[0]}`, port);
|
|
303
|
-
const crawler = createCrawler(
|
|
304
|
-
async (request) => {
|
|
305
|
-
const url = new URL(request.url);
|
|
306
|
-
const headers = {};
|
|
307
|
-
request.headers.forEach((value, key) => {
|
|
308
|
-
headers[key] = value;
|
|
309
|
-
});
|
|
310
|
-
const responseData = await client.request({
|
|
311
|
-
path: url.pathname + url.search,
|
|
312
|
-
method: request.method,
|
|
313
|
-
signal: request.signal,
|
|
314
|
-
headers
|
|
315
|
-
});
|
|
316
|
-
return new Response(responseData.body, {
|
|
317
|
-
status: responseData.statusCode,
|
|
318
|
-
headers: responseData.headers
|
|
319
|
-
});
|
|
320
|
-
},
|
|
321
|
-
{
|
|
322
|
-
origin
|
|
323
|
-
}
|
|
324
|
-
);
|
|
325
|
-
try {
|
|
326
|
-
await crawler.crawl(pathsToVisit);
|
|
327
|
-
} finally {
|
|
328
|
-
await client.close();
|
|
329
|
-
closeServer();
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
for (const file of builtEntries) {
|
|
333
|
-
await fs2.rm(file, { maxRetries: 5 }).catch(() => {
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
};
|
|
338
|
-
}
|
|
339
|
-
export {
|
|
340
|
-
staticAdapter as default
|
|
341
|
-
};
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
import type { ServerResponse, IncomingMessage } from "http";
|
|
3
|
-
export declare function createWebRequest<NodeRequest extends IncomingMessage = IncomingMessage>(nodeRequest: NodeRequest, url: URL): Request;
|
|
4
|
-
export declare function applyWebResponse<NodeRequest extends IncomingMessage = IncomingMessage>(nodeResponse: ServerResponse<NodeRequest>, webResponse: Response): Promise<void>;
|