@fluixi/start 0.1.0-alpha.72 → 0.1.0-alpha.74
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.cjs +748 -0
- package/dist/adapter.mjs +717 -0
- package/dist/adapters/entry.cjs +122 -0
- package/dist/adapters/entry.mjs +95 -0
- package/dist/adapters/platforms.cjs +311 -0
- package/dist/adapters/platforms.mjs +284 -0
- package/dist/api-RH6E5UTH.mjs +114 -0
- package/dist/api.cjs +145 -0
- package/dist/api.mjs +116 -0
- package/dist/commands/api-23MJFSYL.mjs +17 -0
- package/dist/commands/api-4IYNQRKG.mjs +16 -0
- package/dist/commands/api-RH6E5UTH.mjs +114 -0
- package/dist/commands/build.cjs +870 -0
- package/dist/commands/build.mjs +710 -0
- package/dist/commands/chunk-NS5GR2GX.mjs +115 -0
- package/dist/commands/chunk-OCPCK4ZJ.mjs +117 -0
- package/dist/commands/dev.cjs +663 -0
- package/dist/commands/dev.mjs +505 -0
- package/dist/commands/index.cjs +1138 -0
- package/dist/commands/index.mjs +975 -0
- package/dist/commands/prerender.cjs +402 -0
- package/dist/commands/prerender.mjs +375 -0
- package/dist/commands/start.cjs +461 -0
- package/dist/commands/start.mjs +426 -0
- package/dist/config.cjs +144 -0
- package/dist/config.mjs +108 -0
- package/dist/di.cjs +200 -0
- package/dist/di.mjs +169 -0
- package/dist/document.cjs +115 -0
- package/dist/document.mjs +86 -0
- package/dist/generated-api.cjs +43 -0
- package/dist/generated-api.mjs +18 -0
- package/dist/generated-server-fns.cjs +43 -0
- package/dist/generated-server-fns.mjs +18 -0
- package/dist/handler-core.cjs +211 -0
- package/dist/handler-core.mjs +185 -0
- package/dist/handler.cjs +181 -0
- package/dist/handler.mjs +150 -0
- package/dist/head.cjs +25 -0
- package/dist/head.mjs +4 -0
- package/dist/image.cjs +146 -0
- package/dist/image.mjs +120 -0
- package/dist/index.cjs +1036 -0
- package/dist/index.mjs +968 -0
- package/dist/interceptors.cjs +71 -0
- package/dist/interceptors.mjs +42 -0
- package/dist/internal.cjs +388 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +6 -2
- package/dist/internal.mjs +218 -0
- package/dist/middleware.cjs +58 -0
- package/dist/middleware.mjs +31 -0
- package/dist/preload.cjs +42 -0
- package/dist/preload.mjs +18 -0
- package/dist/router.cjs +25 -0
- package/dist/router.mjs +4 -0
- package/dist/server-fn-setup.cjs +46 -0
- package/dist/server-fn-setup.mjs +22 -0
- package/dist/server-fn.cjs +109 -0
- package/dist/server-fn.mjs +79 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/dist/ui.cjs +123 -0
- package/dist/ui.mjs +93 -0
- package/package.json +45 -25
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/*! @fluixi/start v0.1.0-alpha.74 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
|
|
2
|
+
"use strict";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/handler-core.ts
|
|
22
|
+
var handler_core_exports = {};
|
|
23
|
+
__export(handler_core_exports, {
|
|
24
|
+
createHandlerFrom: () => createHandlerFrom
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(handler_core_exports);
|
|
27
|
+
|
|
28
|
+
// src/document.ts
|
|
29
|
+
var import_head = require("@fluixi/head");
|
|
30
|
+
function injectApp(template, appHtml, mountId = "root") {
|
|
31
|
+
const mount = new RegExp(`<div id=["']${mountId}["']\\s*>\\s*</div>`);
|
|
32
|
+
if (mount.test(template)) {
|
|
33
|
+
return template.replace(mount, `<div id="${mountId}">${appHtml}</div>`);
|
|
34
|
+
}
|
|
35
|
+
if (template.includes("<!--ssr-outlet-->")) {
|
|
36
|
+
return template.replace("<!--ssr-outlet-->", appHtml);
|
|
37
|
+
}
|
|
38
|
+
return template.replace("</body>", `<div id="${mountId}">${appHtml}</div></body>`);
|
|
39
|
+
}
|
|
40
|
+
function splitTemplate(template, mountId = "root") {
|
|
41
|
+
const mount = new RegExp(`<div id=["']${mountId}["']\\s*>\\s*</div>`);
|
|
42
|
+
const m = template.match(mount);
|
|
43
|
+
if (m && m.index !== void 0) {
|
|
44
|
+
return {
|
|
45
|
+
head: template.slice(0, m.index) + `<div id="${mountId}">`,
|
|
46
|
+
tail: `</div>` + template.slice(m.index + m[0].length)
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
const outlet = template.indexOf("<!--ssr-outlet-->");
|
|
50
|
+
if (outlet !== -1) {
|
|
51
|
+
return {
|
|
52
|
+
head: template.slice(0, outlet),
|
|
53
|
+
tail: template.slice(outlet + "<!--ssr-outlet-->".length)
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const body = template.indexOf("</body>");
|
|
57
|
+
if (body !== -1) {
|
|
58
|
+
return {
|
|
59
|
+
head: template.slice(0, body) + `<div id="${mountId}">`,
|
|
60
|
+
tail: `</div>` + template.slice(body)
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
return { head: template, tail: "" };
|
|
64
|
+
}
|
|
65
|
+
function injectPreload(template, files) {
|
|
66
|
+
const tags = files.filter((file) => !template.includes(file)).map(
|
|
67
|
+
(file) => file.endsWith(".css") ? `<link rel="stylesheet" href="${file}">` : (
|
|
68
|
+
// `modulepreload` also fetches the chunk's own static imports.
|
|
69
|
+
`<link rel="modulepreload" href="${file}">`
|
|
70
|
+
)
|
|
71
|
+
);
|
|
72
|
+
if (tags.length === 0) return template;
|
|
73
|
+
const head = template.indexOf("</head>");
|
|
74
|
+
if (head === -1) return template;
|
|
75
|
+
return template.slice(0, head) + tags.join("") + template.slice(head);
|
|
76
|
+
}
|
|
77
|
+
function setHtmlAttr(html, name, value) {
|
|
78
|
+
const existing = new RegExp(`(<html\\b[^>]*?)\\s${name}="[^"]*"`, "i");
|
|
79
|
+
if (existing.test(html)) return html.replace(existing, `$1 ${name}="${value}"`);
|
|
80
|
+
return html.replace(/<html\b/i, `<html ${name}="${value}"`);
|
|
81
|
+
}
|
|
82
|
+
function injectAppAndHead(template, rendered, mountId = "root") {
|
|
83
|
+
const { head, body } = (0, import_head.extractHeadMarker)(rendered);
|
|
84
|
+
let html = injectApp(template, body, mountId);
|
|
85
|
+
if (head) {
|
|
86
|
+
if (head.headHtml) {
|
|
87
|
+
if (/<title[\s>]/i.test(head.headHtml)) html = html.replace(/<title>[\s\S]*?<\/title>/i, "");
|
|
88
|
+
html = html.replace("</head>", `${head.headHtml}</head>`);
|
|
89
|
+
}
|
|
90
|
+
for (const [k, v] of Object.entries(head.htmlAttrs)) html = setHtmlAttr(html, k, v);
|
|
91
|
+
}
|
|
92
|
+
return html;
|
|
93
|
+
}
|
|
94
|
+
function guardHandler(handler, onError) {
|
|
95
|
+
return async (request) => {
|
|
96
|
+
try {
|
|
97
|
+
return await handler(request);
|
|
98
|
+
} catch (e) {
|
|
99
|
+
onError?.(e);
|
|
100
|
+
return new Response(String(e?.stack || e), {
|
|
101
|
+
status: 500,
|
|
102
|
+
headers: { "content-type": "text/plain; charset=utf-8" }
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// src/handler.ts
|
|
109
|
+
function streamDocument(head, body, tail) {
|
|
110
|
+
const enc = new TextEncoder();
|
|
111
|
+
const stream = new ReadableStream({
|
|
112
|
+
async start(controller) {
|
|
113
|
+
try {
|
|
114
|
+
controller.enqueue(enc.encode(head));
|
|
115
|
+
const reader = body.getReader();
|
|
116
|
+
for (; ; ) {
|
|
117
|
+
const { done, value } = await reader.read();
|
|
118
|
+
if (done) break;
|
|
119
|
+
controller.enqueue(value);
|
|
120
|
+
}
|
|
121
|
+
controller.enqueue(enc.encode(tail));
|
|
122
|
+
controller.close();
|
|
123
|
+
} catch (err) {
|
|
124
|
+
controller.error(err);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
return new Response(stream, {
|
|
129
|
+
status: 200,
|
|
130
|
+
headers: { "content-type": "text/html; charset=utf-8" }
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
function createRequestHandler(render) {
|
|
134
|
+
return async (request) => {
|
|
135
|
+
const url = new URL(request.url);
|
|
136
|
+
try {
|
|
137
|
+
const html = await render(url.pathname + url.search, request);
|
|
138
|
+
return new Response(html, {
|
|
139
|
+
status: 200,
|
|
140
|
+
headers: { "content-type": "text/html; charset=utf-8" }
|
|
141
|
+
});
|
|
142
|
+
} catch (e) {
|
|
143
|
+
return new Response(String(e?.stack || e), {
|
|
144
|
+
status: 500,
|
|
145
|
+
headers: { "content-type": "text/plain; charset=utf-8" }
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// src/middleware.ts
|
|
152
|
+
function normalizeMiddleware(mod) {
|
|
153
|
+
const def = mod?.default ?? mod;
|
|
154
|
+
if (def == null) return [];
|
|
155
|
+
if (Array.isArray(def)) return def.filter((m) => typeof m === "function");
|
|
156
|
+
return typeof def === "function" ? [def] : [];
|
|
157
|
+
}
|
|
158
|
+
function composeMiddleware(middlewares, core) {
|
|
159
|
+
if (middlewares.length === 0) return core;
|
|
160
|
+
return (request) => {
|
|
161
|
+
let lastCalled = -1;
|
|
162
|
+
const dispatch = (i) => {
|
|
163
|
+
if (i <= lastCalled) {
|
|
164
|
+
return Promise.reject(new Error("middleware called next() more than once"));
|
|
165
|
+
}
|
|
166
|
+
lastCalled = i;
|
|
167
|
+
const mw = middlewares[i];
|
|
168
|
+
if (!mw) return Promise.resolve(core(request));
|
|
169
|
+
return Promise.resolve(mw(request, () => dispatch(i + 1)));
|
|
170
|
+
};
|
|
171
|
+
return dispatch(0);
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// src/handler-core.ts
|
|
176
|
+
function createHandlerFrom({ template, mod, cfg, middleware, preload }) {
|
|
177
|
+
const withPreload = (html, pathname) => preload ? injectPreload(html, preload(pathname)) : html;
|
|
178
|
+
let core;
|
|
179
|
+
if (!cfg.ssr) {
|
|
180
|
+
core = createRequestHandler(async (url) => withPreload(template, url.split("?")[0]));
|
|
181
|
+
} else if (typeof mod.renderStream === "function") {
|
|
182
|
+
core = async (request) => {
|
|
183
|
+
const url = new URL(request.url);
|
|
184
|
+
const { head, tail } = splitTemplate(withPreload(template, url.pathname), cfg.mountId);
|
|
185
|
+
const body = await mod.renderStream(url.pathname + url.search, request);
|
|
186
|
+
return streamDocument(head, body, tail);
|
|
187
|
+
};
|
|
188
|
+
} else {
|
|
189
|
+
const render = mod.render ?? mod.default;
|
|
190
|
+
core = createRequestHandler(
|
|
191
|
+
async (url, request) => (
|
|
192
|
+
// `url` here is `pathname + search`; matching only ever wants the path.
|
|
193
|
+
injectAppAndHead(withPreload(template, url.split("?")[0]), await render(url, request), cfg.mountId)
|
|
194
|
+
)
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
if (typeof mod.handleServerFn === "function" && typeof mod.isServerFnRequest === "function") {
|
|
198
|
+
const render = core;
|
|
199
|
+
core = async (request) => mod.isServerFnRequest(request) ? mod.handleServerFn(request) : render(request);
|
|
200
|
+
}
|
|
201
|
+
if (typeof mod.handleApiRequest === "function" && typeof mod.isApiRequest === "function") {
|
|
202
|
+
const next = core;
|
|
203
|
+
core = async (request) => mod.isApiRequest(request) ? mod.handleApiRequest(request) : next(request);
|
|
204
|
+
}
|
|
205
|
+
if (!middleware) return guardHandler(core);
|
|
206
|
+
return guardHandler(composeMiddleware(normalizeMiddleware(middleware), core));
|
|
207
|
+
}
|
|
208
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
209
|
+
0 && (module.exports = {
|
|
210
|
+
createHandlerFrom
|
|
211
|
+
});
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/*! @fluixi/start v0.1.0-alpha.74 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
|
|
2
|
+
|
|
3
|
+
// src/document.ts
|
|
4
|
+
import { extractHeadMarker } from "@fluixi/head";
|
|
5
|
+
function injectApp(template, appHtml, mountId = "root") {
|
|
6
|
+
const mount = new RegExp(`<div id=["']${mountId}["']\\s*>\\s*</div>`);
|
|
7
|
+
if (mount.test(template)) {
|
|
8
|
+
return template.replace(mount, `<div id="${mountId}">${appHtml}</div>`);
|
|
9
|
+
}
|
|
10
|
+
if (template.includes("<!--ssr-outlet-->")) {
|
|
11
|
+
return template.replace("<!--ssr-outlet-->", appHtml);
|
|
12
|
+
}
|
|
13
|
+
return template.replace("</body>", `<div id="${mountId}">${appHtml}</div></body>`);
|
|
14
|
+
}
|
|
15
|
+
function splitTemplate(template, mountId = "root") {
|
|
16
|
+
const mount = new RegExp(`<div id=["']${mountId}["']\\s*>\\s*</div>`);
|
|
17
|
+
const m = template.match(mount);
|
|
18
|
+
if (m && m.index !== void 0) {
|
|
19
|
+
return {
|
|
20
|
+
head: template.slice(0, m.index) + `<div id="${mountId}">`,
|
|
21
|
+
tail: `</div>` + template.slice(m.index + m[0].length)
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
const outlet = template.indexOf("<!--ssr-outlet-->");
|
|
25
|
+
if (outlet !== -1) {
|
|
26
|
+
return {
|
|
27
|
+
head: template.slice(0, outlet),
|
|
28
|
+
tail: template.slice(outlet + "<!--ssr-outlet-->".length)
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
const body = template.indexOf("</body>");
|
|
32
|
+
if (body !== -1) {
|
|
33
|
+
return {
|
|
34
|
+
head: template.slice(0, body) + `<div id="${mountId}">`,
|
|
35
|
+
tail: `</div>` + template.slice(body)
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
return { head: template, tail: "" };
|
|
39
|
+
}
|
|
40
|
+
function injectPreload(template, files) {
|
|
41
|
+
const tags = files.filter((file) => !template.includes(file)).map(
|
|
42
|
+
(file) => file.endsWith(".css") ? `<link rel="stylesheet" href="${file}">` : (
|
|
43
|
+
// `modulepreload` also fetches the chunk's own static imports.
|
|
44
|
+
`<link rel="modulepreload" href="${file}">`
|
|
45
|
+
)
|
|
46
|
+
);
|
|
47
|
+
if (tags.length === 0) return template;
|
|
48
|
+
const head = template.indexOf("</head>");
|
|
49
|
+
if (head === -1) return template;
|
|
50
|
+
return template.slice(0, head) + tags.join("") + template.slice(head);
|
|
51
|
+
}
|
|
52
|
+
function setHtmlAttr(html, name, value) {
|
|
53
|
+
const existing = new RegExp(`(<html\\b[^>]*?)\\s${name}="[^"]*"`, "i");
|
|
54
|
+
if (existing.test(html)) return html.replace(existing, `$1 ${name}="${value}"`);
|
|
55
|
+
return html.replace(/<html\b/i, `<html ${name}="${value}"`);
|
|
56
|
+
}
|
|
57
|
+
function injectAppAndHead(template, rendered, mountId = "root") {
|
|
58
|
+
const { head, body } = extractHeadMarker(rendered);
|
|
59
|
+
let html = injectApp(template, body, mountId);
|
|
60
|
+
if (head) {
|
|
61
|
+
if (head.headHtml) {
|
|
62
|
+
if (/<title[\s>]/i.test(head.headHtml)) html = html.replace(/<title>[\s\S]*?<\/title>/i, "");
|
|
63
|
+
html = html.replace("</head>", `${head.headHtml}</head>`);
|
|
64
|
+
}
|
|
65
|
+
for (const [k, v] of Object.entries(head.htmlAttrs)) html = setHtmlAttr(html, k, v);
|
|
66
|
+
}
|
|
67
|
+
return html;
|
|
68
|
+
}
|
|
69
|
+
function guardHandler(handler, onError) {
|
|
70
|
+
return async (request) => {
|
|
71
|
+
try {
|
|
72
|
+
return await handler(request);
|
|
73
|
+
} catch (e) {
|
|
74
|
+
onError?.(e);
|
|
75
|
+
return new Response(String(e?.stack || e), {
|
|
76
|
+
status: 500,
|
|
77
|
+
headers: { "content-type": "text/plain; charset=utf-8" }
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// src/handler.ts
|
|
84
|
+
function streamDocument(head, body, tail) {
|
|
85
|
+
const enc = new TextEncoder();
|
|
86
|
+
const stream = new ReadableStream({
|
|
87
|
+
async start(controller) {
|
|
88
|
+
try {
|
|
89
|
+
controller.enqueue(enc.encode(head));
|
|
90
|
+
const reader = body.getReader();
|
|
91
|
+
for (; ; ) {
|
|
92
|
+
const { done, value } = await reader.read();
|
|
93
|
+
if (done) break;
|
|
94
|
+
controller.enqueue(value);
|
|
95
|
+
}
|
|
96
|
+
controller.enqueue(enc.encode(tail));
|
|
97
|
+
controller.close();
|
|
98
|
+
} catch (err) {
|
|
99
|
+
controller.error(err);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
return new Response(stream, {
|
|
104
|
+
status: 200,
|
|
105
|
+
headers: { "content-type": "text/html; charset=utf-8" }
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
function createRequestHandler(render) {
|
|
109
|
+
return async (request) => {
|
|
110
|
+
const url = new URL(request.url);
|
|
111
|
+
try {
|
|
112
|
+
const html = await render(url.pathname + url.search, request);
|
|
113
|
+
return new Response(html, {
|
|
114
|
+
status: 200,
|
|
115
|
+
headers: { "content-type": "text/html; charset=utf-8" }
|
|
116
|
+
});
|
|
117
|
+
} catch (e) {
|
|
118
|
+
return new Response(String(e?.stack || e), {
|
|
119
|
+
status: 500,
|
|
120
|
+
headers: { "content-type": "text/plain; charset=utf-8" }
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// src/middleware.ts
|
|
127
|
+
function normalizeMiddleware(mod) {
|
|
128
|
+
const def = mod?.default ?? mod;
|
|
129
|
+
if (def == null) return [];
|
|
130
|
+
if (Array.isArray(def)) return def.filter((m) => typeof m === "function");
|
|
131
|
+
return typeof def === "function" ? [def] : [];
|
|
132
|
+
}
|
|
133
|
+
function composeMiddleware(middlewares, core) {
|
|
134
|
+
if (middlewares.length === 0) return core;
|
|
135
|
+
return (request) => {
|
|
136
|
+
let lastCalled = -1;
|
|
137
|
+
const dispatch = (i) => {
|
|
138
|
+
if (i <= lastCalled) {
|
|
139
|
+
return Promise.reject(new Error("middleware called next() more than once"));
|
|
140
|
+
}
|
|
141
|
+
lastCalled = i;
|
|
142
|
+
const mw = middlewares[i];
|
|
143
|
+
if (!mw) return Promise.resolve(core(request));
|
|
144
|
+
return Promise.resolve(mw(request, () => dispatch(i + 1)));
|
|
145
|
+
};
|
|
146
|
+
return dispatch(0);
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// src/handler-core.ts
|
|
151
|
+
function createHandlerFrom({ template, mod, cfg, middleware, preload }) {
|
|
152
|
+
const withPreload = (html, pathname) => preload ? injectPreload(html, preload(pathname)) : html;
|
|
153
|
+
let core;
|
|
154
|
+
if (!cfg.ssr) {
|
|
155
|
+
core = createRequestHandler(async (url) => withPreload(template, url.split("?")[0]));
|
|
156
|
+
} else if (typeof mod.renderStream === "function") {
|
|
157
|
+
core = async (request) => {
|
|
158
|
+
const url = new URL(request.url);
|
|
159
|
+
const { head, tail } = splitTemplate(withPreload(template, url.pathname), cfg.mountId);
|
|
160
|
+
const body = await mod.renderStream(url.pathname + url.search, request);
|
|
161
|
+
return streamDocument(head, body, tail);
|
|
162
|
+
};
|
|
163
|
+
} else {
|
|
164
|
+
const render = mod.render ?? mod.default;
|
|
165
|
+
core = createRequestHandler(
|
|
166
|
+
async (url, request) => (
|
|
167
|
+
// `url` here is `pathname + search`; matching only ever wants the path.
|
|
168
|
+
injectAppAndHead(withPreload(template, url.split("?")[0]), await render(url, request), cfg.mountId)
|
|
169
|
+
)
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
if (typeof mod.handleServerFn === "function" && typeof mod.isServerFnRequest === "function") {
|
|
173
|
+
const render = core;
|
|
174
|
+
core = async (request) => mod.isServerFnRequest(request) ? mod.handleServerFn(request) : render(request);
|
|
175
|
+
}
|
|
176
|
+
if (typeof mod.handleApiRequest === "function" && typeof mod.isApiRequest === "function") {
|
|
177
|
+
const next = core;
|
|
178
|
+
core = async (request) => mod.isApiRequest(request) ? mod.handleApiRequest(request) : next(request);
|
|
179
|
+
}
|
|
180
|
+
if (!middleware) return guardHandler(core);
|
|
181
|
+
return guardHandler(composeMiddleware(normalizeMiddleware(middleware), core));
|
|
182
|
+
}
|
|
183
|
+
export {
|
|
184
|
+
createHandlerFrom
|
|
185
|
+
};
|
package/dist/handler.cjs
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/handler.ts
|
|
21
|
+
var handler_exports = {};
|
|
22
|
+
__export(handler_exports, {
|
|
23
|
+
createRequestHandler: () => createRequestHandler,
|
|
24
|
+
nodeToRequest: () => nodeToRequest,
|
|
25
|
+
sendResponse: () => sendResponse,
|
|
26
|
+
serveNode: () => serveNode,
|
|
27
|
+
streamDocument: () => streamDocument,
|
|
28
|
+
toNodeHandler: () => toNodeHandler,
|
|
29
|
+
withStaticFiles: () => withStaticFiles
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(handler_exports);
|
|
32
|
+
var import_node_http = require("node:http");
|
|
33
|
+
var import_promises = require("node:fs/promises");
|
|
34
|
+
var import_node_fs = require("node:fs");
|
|
35
|
+
var import_node_stream = require("node:stream");
|
|
36
|
+
var import_node_path = require("node:path");
|
|
37
|
+
function streamDocument(head, body, tail) {
|
|
38
|
+
const enc = new TextEncoder();
|
|
39
|
+
const stream = new ReadableStream({
|
|
40
|
+
async start(controller) {
|
|
41
|
+
try {
|
|
42
|
+
controller.enqueue(enc.encode(head));
|
|
43
|
+
const reader = body.getReader();
|
|
44
|
+
for (; ; ) {
|
|
45
|
+
const { done, value } = await reader.read();
|
|
46
|
+
if (done) break;
|
|
47
|
+
controller.enqueue(value);
|
|
48
|
+
}
|
|
49
|
+
controller.enqueue(enc.encode(tail));
|
|
50
|
+
controller.close();
|
|
51
|
+
} catch (err) {
|
|
52
|
+
controller.error(err);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
return new Response(stream, {
|
|
57
|
+
status: 200,
|
|
58
|
+
headers: { "content-type": "text/html; charset=utf-8" }
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
function createRequestHandler(render) {
|
|
62
|
+
return async (request) => {
|
|
63
|
+
const url = new URL(request.url);
|
|
64
|
+
try {
|
|
65
|
+
const html = await render(url.pathname + url.search, request);
|
|
66
|
+
return new Response(html, {
|
|
67
|
+
status: 200,
|
|
68
|
+
headers: { "content-type": "text/html; charset=utf-8" }
|
|
69
|
+
});
|
|
70
|
+
} catch (e) {
|
|
71
|
+
return new Response(String(e?.stack || e), {
|
|
72
|
+
status: 500,
|
|
73
|
+
headers: { "content-type": "text/plain; charset=utf-8" }
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function nodeToRequest(req) {
|
|
79
|
+
const host = req.headers.host ?? "localhost";
|
|
80
|
+
const url = `http://${host}${req.url ?? "/"}`;
|
|
81
|
+
const headers = new Headers();
|
|
82
|
+
for (const [k, v] of Object.entries(req.headers)) {
|
|
83
|
+
if (Array.isArray(v)) v.forEach((x) => headers.append(k, x));
|
|
84
|
+
else if (v != null) headers.set(k, v);
|
|
85
|
+
}
|
|
86
|
+
const method = req.method ?? "GET";
|
|
87
|
+
const init = { method, headers };
|
|
88
|
+
if (method !== "GET" && method !== "HEAD") {
|
|
89
|
+
init.body = req;
|
|
90
|
+
init.duplex = "half";
|
|
91
|
+
}
|
|
92
|
+
return new Request(url, init);
|
|
93
|
+
}
|
|
94
|
+
async function sendResponse(res, response) {
|
|
95
|
+
res.statusCode = response.status;
|
|
96
|
+
response.headers.forEach((value, key) => res.setHeader(key, value));
|
|
97
|
+
const body = response.body;
|
|
98
|
+
if (!body) {
|
|
99
|
+
res.end(await response.text().catch(() => ""));
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const reader = body.getReader();
|
|
103
|
+
try {
|
|
104
|
+
for (; ; ) {
|
|
105
|
+
const { done, value } = await reader.read();
|
|
106
|
+
if (done) break;
|
|
107
|
+
res.write(value);
|
|
108
|
+
}
|
|
109
|
+
} finally {
|
|
110
|
+
res.end();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function toNodeHandler(handler) {
|
|
114
|
+
return async (req, res) => {
|
|
115
|
+
const response = await handler(nodeToRequest(req));
|
|
116
|
+
await sendResponse(res, response);
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function serveNode(handler, opts = {}) {
|
|
120
|
+
const port = opts.port ?? 3e3;
|
|
121
|
+
const node = toNodeHandler(handler);
|
|
122
|
+
const server = (0, import_node_http.createServer)((req, res) => {
|
|
123
|
+
node(req, res).catch((e) => {
|
|
124
|
+
res.statusCode = 500;
|
|
125
|
+
res.end(String(e?.stack || e));
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
server.listen(
|
|
129
|
+
port,
|
|
130
|
+
() => opts.onListen ? opts.onListen(port) : console.log(` fluixi → http://localhost:${port}`)
|
|
131
|
+
);
|
|
132
|
+
return server;
|
|
133
|
+
}
|
|
134
|
+
var MIME = {
|
|
135
|
+
".js": "text/javascript",
|
|
136
|
+
".mjs": "text/javascript",
|
|
137
|
+
".css": "text/css",
|
|
138
|
+
".html": "text/html",
|
|
139
|
+
".json": "application/json",
|
|
140
|
+
".svg": "image/svg+xml",
|
|
141
|
+
".png": "image/png",
|
|
142
|
+
".jpg": "image/jpeg",
|
|
143
|
+
".jpeg": "image/jpeg",
|
|
144
|
+
".webp": "image/webp",
|
|
145
|
+
".ico": "image/x-icon",
|
|
146
|
+
".woff": "font/woff",
|
|
147
|
+
".woff2": "font/woff2",
|
|
148
|
+
".map": "application/json"
|
|
149
|
+
};
|
|
150
|
+
function withStaticFiles(handler, dir) {
|
|
151
|
+
return async (request) => {
|
|
152
|
+
const { pathname } = new URL(request.url);
|
|
153
|
+
if (pathname !== "/" && (0, import_node_path.extname)(pathname)) {
|
|
154
|
+
const file = (0, import_node_path.join)(dir, decodeURIComponent(pathname));
|
|
155
|
+
try {
|
|
156
|
+
const s = await (0, import_promises.stat)(file);
|
|
157
|
+
if (s.isFile()) {
|
|
158
|
+
const body = import_node_stream.Readable.toWeb((0, import_node_fs.createReadStream)(file));
|
|
159
|
+
return new Response(body, {
|
|
160
|
+
headers: {
|
|
161
|
+
"content-type": MIME[(0, import_node_path.extname)(file).toLowerCase()] ?? "application/octet-stream",
|
|
162
|
+
"content-length": String(s.size)
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
} catch {
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return handler(request);
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
173
|
+
0 && (module.exports = {
|
|
174
|
+
createRequestHandler,
|
|
175
|
+
nodeToRequest,
|
|
176
|
+
sendResponse,
|
|
177
|
+
serveNode,
|
|
178
|
+
streamDocument,
|
|
179
|
+
toNodeHandler,
|
|
180
|
+
withStaticFiles
|
|
181
|
+
});
|