@torpor/build 0.1.12 → 0.1.14
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/CHANGELOG.md +14 -0
- package/dist/{Server-DhJ1nRFR.d.cts → Server-BC_dixZQ.d.cts} +5 -6
- package/dist/{Server-DhJ1nRFR.d.ts → Server-BC_dixZQ.d.ts} +5 -6
- package/dist/{Site-CM2pZtq6.d.cts → Site-BeRKXeJ4.d.cts} +7 -1
- package/dist/{Site-BB6kV7wC.d.ts → Site-D70KrWlY.d.ts} +7 -1
- package/dist/bin/index.cjs +14 -23
- package/dist/bin/index.cjs.map +1 -1
- package/dist/bin/index.js +5 -3
- package/dist/bin/index.js.map +1 -1
- package/dist/chunk-2QQN3D3K.js +50 -0
- package/dist/chunk-2QQN3D3K.js.map +1 -0
- package/dist/chunk-65K3R3CP.js +150 -0
- package/dist/chunk-65K3R3CP.js.map +1 -0
- package/dist/{chunk-VAGHGWM5.js → chunk-D6LHMH2C.js} +5 -47
- package/dist/chunk-D6LHMH2C.js.map +1 -0
- package/dist/chunk-EVBUHZGK.js +85 -0
- package/dist/chunk-EVBUHZGK.js.map +1 -0
- package/dist/{chunk-YU2SSD7E.js → chunk-FMRCLIWE.js} +4 -83
- package/dist/chunk-FMRCLIWE.js.map +1 -0
- package/dist/chunk-WMHM5RGZ.js +15 -0
- package/dist/chunk-WMHM5RGZ.js.map +1 -0
- package/dist/{chunk-GHXCJ52Z.js → chunk-XLNPB3GH.js} +17 -26
- package/dist/chunk-XLNPB3GH.js.map +1 -0
- package/dist/index.cjs +6 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -9
- package/dist/index.d.ts +8 -9
- package/dist/index.js +16 -137
- package/dist/index.js.map +1 -1
- package/dist/metafile-cjs.json +1 -1
- package/dist/metafile-esm.json +1 -1
- package/dist/response.cjs.map +1 -1
- package/dist/response.js +8 -6
- package/dist/run.cjs +14 -23
- package/dist/run.cjs.map +1 -1
- package/dist/run.d.cts +2 -2
- package/dist/run.d.ts +2 -2
- package/dist/run.js +5 -3
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +2 -2
- package/dist/server.d.ts +2 -2
- package/dist/server.js +6 -4
- package/dist/state.cjs.map +1 -1
- package/dist/state.d.cts +2 -1
- package/dist/state.d.ts +2 -1
- package/dist/state.js +3 -10
- package/dist/state.js.map +1 -1
- package/dist/test.cjs +519 -0
- package/dist/test.cjs.map +1 -0
- package/dist/test.d.cts +8 -0
- package/dist/test.d.ts +8 -0
- package/dist/test.js +227 -0
- package/dist/test.js.map +1 -0
- package/package.json +11 -6
- package/src/response/response.ts +1 -1
- package/src/server/CookieHelper.ts +2 -2
- package/src/server/HeaderHelper.ts +2 -2
- package/src/server/Routerx.ts +7 -2
- package/src/server/Server.ts +6 -1
- package/src/server/ServerEvent.ts +1 -1
- package/src/server/contentType.ts +1 -1
- package/src/site/Router.ts +9 -3
- package/src/site/Site.ts +8 -2
- package/src/site/prepareTemplate.ts +1 -1
- package/src/site/run.ts +9 -7
- package/src/site/runBuild.ts +9 -14
- package/src/site/runDev.ts +3 -8
- package/src/site/runPreview.ts +1 -1
- package/src/site/serverEntry.ts +1 -1
- package/src/state/$page.ts +6 -1
- package/src/test/runTest.ts +314 -0
- package/src/test.ts +3 -0
- package/tsup.config.ts +8 -2
- package/vitest.config.ts +2 -2
- package/dist/chunk-GHXCJ52Z.js.map +0 -1
- package/dist/chunk-VAGHGWM5.js.map +0 -1
- package/dist/chunk-YU2SSD7E.js.map +0 -1
package/dist/test.js
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import {
|
|
2
|
+
HOOK_ROUTE,
|
|
3
|
+
HOOK_SERVER_ROUTE,
|
|
4
|
+
LAYOUT_ROUTE,
|
|
5
|
+
LAYOUT_SERVER_ROUTE,
|
|
6
|
+
PAGE_ROUTE,
|
|
7
|
+
PAGE_SERVER_ROUTE,
|
|
8
|
+
Router,
|
|
9
|
+
SERVER_ROUTE
|
|
10
|
+
} from "./chunk-65K3R3CP.js";
|
|
11
|
+
import {
|
|
12
|
+
page_default
|
|
13
|
+
} from "./chunk-WMHM5RGZ.js";
|
|
14
|
+
import {
|
|
15
|
+
notFound,
|
|
16
|
+
ok,
|
|
17
|
+
seeOther
|
|
18
|
+
} from "./chunk-2QQN3D3K.js";
|
|
19
|
+
import {
|
|
20
|
+
ServerEvent
|
|
21
|
+
} from "./chunk-EVBUHZGK.js";
|
|
22
|
+
import "./chunk-SJVHHGVW.js";
|
|
23
|
+
|
|
24
|
+
// src/test/runTest.ts
|
|
25
|
+
import path from "node:path";
|
|
26
|
+
async function runTest(site, route) {
|
|
27
|
+
if (!route.startsWith("/")) route += "/";
|
|
28
|
+
const req = new Request(`http://localhost${route}`);
|
|
29
|
+
const ev = new ServerEvent(req);
|
|
30
|
+
const router = new Router();
|
|
31
|
+
router.addPages(
|
|
32
|
+
site.routes.map((r) => ({
|
|
33
|
+
path: r.path,
|
|
34
|
+
type: r.type,
|
|
35
|
+
endPoint: () => import(
|
|
36
|
+
/* @vite-ignore */
|
|
37
|
+
path.join(site.root, r.file)
|
|
38
|
+
)
|
|
39
|
+
}))
|
|
40
|
+
);
|
|
41
|
+
return await load(router, ev, "%COMPONENT_HTML%");
|
|
42
|
+
}
|
|
43
|
+
async function load(router, ev, template) {
|
|
44
|
+
const url = new URL(ev.request.url);
|
|
45
|
+
const path2 = url.pathname;
|
|
46
|
+
const query = url.searchParams;
|
|
47
|
+
const route = router.match(path2, query);
|
|
48
|
+
if (!route) {
|
|
49
|
+
return notFound();
|
|
50
|
+
}
|
|
51
|
+
page_default.url = url;
|
|
52
|
+
const handler = route.handler;
|
|
53
|
+
const params = route.params || {};
|
|
54
|
+
switch (handler.type) {
|
|
55
|
+
case PAGE_ROUTE:
|
|
56
|
+
case LAYOUT_ROUTE: {
|
|
57
|
+
if (ev.request.method === "GET") {
|
|
58
|
+
return await loadView(ev, url, handler, params, template);
|
|
59
|
+
} else if (ev.request.method === "POST") {
|
|
60
|
+
return await runAction(ev, url, handler, params, query);
|
|
61
|
+
}
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
case PAGE_SERVER_ROUTE:
|
|
65
|
+
case LAYOUT_SERVER_ROUTE: {
|
|
66
|
+
if (ev.request.method === "GET") {
|
|
67
|
+
return await loadData(ev, url, handler, "load", params);
|
|
68
|
+
}
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
case SERVER_ROUTE: {
|
|
72
|
+
const functionName = ev.request.method.toLowerCase().replace("delete", "del");
|
|
73
|
+
return await loadData(ev, url, handler, functionName, params);
|
|
74
|
+
}
|
|
75
|
+
case HOOK_ROUTE:
|
|
76
|
+
case HOOK_SERVER_ROUTE: {
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return notFound();
|
|
81
|
+
}
|
|
82
|
+
async function loadData(ev, url, handler, functionName, params) {
|
|
83
|
+
const serverEndPoint = (await handler.endPoint()).default;
|
|
84
|
+
if (serverEndPoint && serverEndPoint[functionName]) {
|
|
85
|
+
const serverParams = buildServerParams(ev, url, params);
|
|
86
|
+
if (handler.serverHook) {
|
|
87
|
+
const serverHook = (await handler.serverHook()).default;
|
|
88
|
+
if (serverHook?.handle) {
|
|
89
|
+
await serverHook.handle(serverParams);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
const result = await serverEndPoint[functionName](serverParams);
|
|
93
|
+
return result || ok();
|
|
94
|
+
}
|
|
95
|
+
return notFound();
|
|
96
|
+
}
|
|
97
|
+
async function loadView(ev, url, handler, params, template) {
|
|
98
|
+
const clientEndPoint = (await handler.endPoint()).default;
|
|
99
|
+
if (!clientEndPoint?.component) {
|
|
100
|
+
return notFound();
|
|
101
|
+
}
|
|
102
|
+
const serverEndPoint = handler.serverEndPoint && (await handler.serverEndPoint())?.default;
|
|
103
|
+
const serverParams = buildServerParams(ev, url, params);
|
|
104
|
+
if (handler.serverHook) {
|
|
105
|
+
const serverHook = (await handler.serverHook()).default;
|
|
106
|
+
if (serverHook?.handle) {
|
|
107
|
+
await serverHook.handle(serverParams);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
let data = {};
|
|
111
|
+
if (handler.layouts) {
|
|
112
|
+
for (let layout of handler.layouts) {
|
|
113
|
+
const layoutEndPoint = (await layout.endPoint())?.default;
|
|
114
|
+
const layoutServerEndPoint = layout.serverEndPoint && (await layout.serverEndPoint())?.default;
|
|
115
|
+
const layoutData = await loadClientAndServerData(
|
|
116
|
+
url,
|
|
117
|
+
params,
|
|
118
|
+
serverParams,
|
|
119
|
+
data,
|
|
120
|
+
layoutEndPoint,
|
|
121
|
+
layoutServerEndPoint
|
|
122
|
+
);
|
|
123
|
+
Object.assign(data, layoutData);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
let endPointData = await loadClientAndServerData(
|
|
127
|
+
url,
|
|
128
|
+
params,
|
|
129
|
+
serverParams,
|
|
130
|
+
data,
|
|
131
|
+
clientEndPoint,
|
|
132
|
+
serverEndPoint
|
|
133
|
+
);
|
|
134
|
+
Object.assign(data, endPointData);
|
|
135
|
+
let $props = { data };
|
|
136
|
+
let component = clientEndPoint.component;
|
|
137
|
+
let slots = void 0;
|
|
138
|
+
if (handler.layouts) {
|
|
139
|
+
let slotFunctions = [];
|
|
140
|
+
slotFunctions[handler.layouts.length] = (_, context) => clientEndPoint.component($props, context);
|
|
141
|
+
for (let i = handler.layouts.length - 1; i >= 0; i--) {
|
|
142
|
+
const layoutEndPoint = (await handler.layouts[i].endPoint())?.default;
|
|
143
|
+
if (layoutEndPoint?.component) {
|
|
144
|
+
if (i === 0) {
|
|
145
|
+
component = layoutEndPoint.component;
|
|
146
|
+
slots = { _: slotFunctions[i + 1] };
|
|
147
|
+
} else {
|
|
148
|
+
slotFunctions[i] = (_, context) => layoutEndPoint.component($props, context, {
|
|
149
|
+
_: slotFunctions[i + 1]
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
let html;
|
|
156
|
+
try {
|
|
157
|
+
html = component($props, void 0, slots);
|
|
158
|
+
html = template.replace("%COMPONENT_HTML%", html);
|
|
159
|
+
} catch (error) {
|
|
160
|
+
html = '<span style="color: red">Script syntax error</span><p>' + error + "</p>";
|
|
161
|
+
console.log(error);
|
|
162
|
+
}
|
|
163
|
+
return new Response(html, {
|
|
164
|
+
status: 200,
|
|
165
|
+
headers: {
|
|
166
|
+
"Content-Type": "text/html"
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
async function runAction(ev, url, handler, params, query) {
|
|
171
|
+
const actionName = (Array.from(query.keys())[0] || "default").replace(/^\//, "");
|
|
172
|
+
const serverEndPoint = handler.serverEndPoint && (await handler.serverEndPoint()).default;
|
|
173
|
+
if (serverEndPoint?.actions) {
|
|
174
|
+
const action = serverEndPoint.actions[actionName];
|
|
175
|
+
if (action) {
|
|
176
|
+
const serverParams = buildServerParams(ev, url, params);
|
|
177
|
+
if (handler.serverHook) {
|
|
178
|
+
const serverHook = (await handler.serverHook()).default;
|
|
179
|
+
if (serverHook?.handle) {
|
|
180
|
+
await serverHook.handle(serverParams);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
const result = await action(serverParams);
|
|
184
|
+
return result || seeOther(url.pathname);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return notFound();
|
|
188
|
+
}
|
|
189
|
+
async function loadClientAndServerData(url, params, serverParams, data, clientEndPoint, serverEndPoint) {
|
|
190
|
+
let newData = {};
|
|
191
|
+
if (clientEndPoint?.load) {
|
|
192
|
+
const clientParams = buildClientParams(url, data, params);
|
|
193
|
+
const clientData = await clientEndPoint.load(clientParams);
|
|
194
|
+
if (clientData) {
|
|
195
|
+
Object.assign(newData, clientData);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (serverEndPoint?.load) {
|
|
199
|
+
const serverData = await serverEndPoint.load(serverParams);
|
|
200
|
+
if (serverData?.ok) {
|
|
201
|
+
Object.assign(newData, await serverData.json());
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return newData;
|
|
205
|
+
}
|
|
206
|
+
function buildClientParams(url, params, data) {
|
|
207
|
+
return {
|
|
208
|
+
url,
|
|
209
|
+
params,
|
|
210
|
+
data
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
function buildServerParams(ev, url, params) {
|
|
214
|
+
return {
|
|
215
|
+
url,
|
|
216
|
+
params,
|
|
217
|
+
appData: {},
|
|
218
|
+
request: ev.request,
|
|
219
|
+
cookies: ev.cookies,
|
|
220
|
+
headers: ev.headers,
|
|
221
|
+
adapter: ev.adapter
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
export {
|
|
225
|
+
runTest
|
|
226
|
+
};
|
|
227
|
+
//# sourceMappingURL=test.js.map
|
package/dist/test.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/test/runTest.ts"],"sourcesContent":["import { type ServerComponent, type ServerSlotRender } from \"@torpor/view\";\nimport path from \"node:path\";\nimport notFound from \"../response/notFound.ts\";\nimport ok from \"../response/ok.ts\";\nimport seeOther from \"../response/seeOther.ts\";\nimport ServerEvent from \"../server/ServerEvent.ts\";\nimport Router from \"../site/Router.ts\";\nimport Site from \"../site/Site\";\nimport $page from \"../state/$page.ts\";\nimport type PageEndPoint from \"../types/PageEndPoint.ts\";\nimport type PageServerEndPoint from \"../types/PageServerEndPoint.ts\";\nimport RouteHandler from \"../types/RouteHandler.ts\";\nimport {\n\tHOOK_ROUTE,\n\tHOOK_SERVER_ROUTE,\n\tLAYOUT_ROUTE,\n\tLAYOUT_SERVER_ROUTE,\n\tPAGE_ROUTE,\n\tPAGE_SERVER_ROUTE,\n\tSERVER_ROUTE,\n} from \"../types/RouteType\";\nimport type ServerEndPoint from \"../types/ServerEndPoint.ts\";\nimport type ServerHook from \"../types/ServerHook.ts\";\nimport type ServerLoadEvent from \"../types/ServerLoadEvent.ts\";\n\nexport default async function runTest(site: Site, route: string): Promise<Response> {\n\tif (!route.startsWith(\"/\")) route += \"/\";\n\tconst req = new Request(`http://localhost${route}`);\n\tconst ev = new ServerEvent(req);\n\n\t// Build the router from the Site object created by the user\n\tconst router = new Router();\n\trouter.addPages(\n\t\tsite.routes.map((r) => ({\n\t\t\tpath: r.path,\n\t\t\ttype: r.type,\n\t\t\tendPoint: () => import(/* @vite-ignore */ path.join(site.root, r.file)),\n\t\t})),\n\t);\n\n\treturn await load(router, ev, \"%COMPONENT_HTML%\");\n}\n\n// HACK: This is a copy of serverEntry\n// TODO: Make it shared instead!\nasync function load(router: Router, ev: ServerEvent, template: string): Promise<Response> {\n\t//const url = new URL(`http://${process.env.HOST ?? \"localhost\"}${ev.request.url}`);\n\tconst url = new URL(ev.request.url);\n\tconst path = url.pathname;\n\tconst query = url.searchParams;\n\n\t//console.log(`handling ${ev.request.method} for '${path}'${query.size ? ` with ${query}` : \"\"}`);\n\n\tconst route = router.match(path, query);\n\tif (!route) {\n\t\treturn notFound();\n\t}\n\n\t// Update $page before building the components\n\t// TODO: Find somewhere better to put this\n\t$page.url = url;\n\n\tconst handler = route.handler;\n\tconst params = route.params || {};\n\n\t// TODO: Hit the server hook out here\n\t// We could maybe set data loading up as middleware on a route??????\n\n\tswitch (handler.type) {\n\t\tcase PAGE_ROUTE:\n\t\tcase LAYOUT_ROUTE: {\n\t\t\t// It's a /+page.ts or /_layout.ts endpoint\n\t\t\tif (ev.request.method === \"GET\") {\n\t\t\t\treturn await loadView(ev, url, handler, params, template);\n\t\t\t} else if (ev.request.method === \"POST\") {\n\t\t\t\treturn await runAction(ev, url, handler, params, query);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase PAGE_SERVER_ROUTE:\n\t\tcase LAYOUT_SERVER_ROUTE: {\n\t\t\t// It's a /+page.server.ts or /_layout.server.ts endpoint\n\t\t\tif (ev.request.method === \"GET\") {\n\t\t\t\treturn await loadData(ev, url, handler, \"load\", params);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase SERVER_ROUTE: {\n\t\t\t// It's a /+server.ts endpoint\n\t\t\tconst functionName = ev.request.method.toLowerCase().replace(\"delete\", \"del\");\n\t\t\treturn await loadData(ev, url, handler, functionName, params);\n\t\t}\n\t\tcase HOOK_ROUTE:\n\t\tcase HOOK_SERVER_ROUTE: {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn notFound();\n}\n\nasync function loadData(\n\tev: ServerEvent,\n\turl: URL,\n\thandler: RouteHandler,\n\tfunctionName: string,\n\tparams: Record<string, string>,\n) {\n\tconst serverEndPoint: ServerEndPoint | undefined = (await handler.endPoint()).default;\n\tif (serverEndPoint && serverEndPoint[functionName]) {\n\t\tconst serverParams = buildServerParams(ev, url, params);\n\n\t\tif (handler.serverHook) {\n\t\t\tconst serverHook: ServerHook | undefined = (await handler.serverHook()).default;\n\t\t\tif (serverHook?.handle) {\n\t\t\t\tawait serverHook.handle(serverParams);\n\t\t\t}\n\t\t}\n\n\t\tconst result = await serverEndPoint[functionName](serverParams);\n\n\t\t// If there was no response returned from load (such as errors or a\n\t\t// redirect), send an ok response\n\t\treturn result || ok();\n\t}\n\n\treturn notFound();\n}\n\nasync function loadView(\n\tev: ServerEvent,\n\turl: URL,\n\thandler: RouteHandler,\n\tparams: Record<string, string>,\n\ttemplate: string,\n) {\n\t// There must be a client endpoint with a component\n\tconst clientEndPoint: PageEndPoint | undefined = (await handler.endPoint()).default;\n\tif (!clientEndPoint?.component) {\n\t\treturn notFound();\n\t}\n\n\t// There may be a server endpoint\n\tconst serverEndPoint: PageServerEndPoint | undefined =\n\t\thandler.serverEndPoint && (await handler.serverEndPoint())?.default;\n\n\t// Maybe hit the server hook\n\tconst serverParams = buildServerParams(ev, url, params);\n\tif (handler.serverHook) {\n\t\tconst serverHook: ServerHook | undefined = (await handler.serverHook()).default;\n\t\tif (serverHook?.handle) {\n\t\t\tawait serverHook.handle(serverParams);\n\t\t}\n\t}\n\n\t// Pass the data into $props\n\t// TODO: Promise.all\n\t// NOTE: We're loading data from top to bottom, overriding as we go, and I'm not sure if this is the best way to go\n\tlet data = {};\n\tif (handler.layouts) {\n\t\tfor (let layout of handler.layouts) {\n\t\t\tconst layoutEndPoint: PageEndPoint | undefined = (await layout.endPoint())?.default;\n\t\t\tconst layoutServerEndPoint: PageServerEndPoint | undefined =\n\t\t\t\tlayout.serverEndPoint && (await layout.serverEndPoint())?.default;\n\t\t\tconst layoutData = await loadClientAndServerData(\n\t\t\t\turl,\n\t\t\t\tparams,\n\t\t\t\tserverParams,\n\t\t\t\tdata,\n\t\t\t\tlayoutEndPoint,\n\t\t\t\tlayoutServerEndPoint,\n\t\t\t);\n\t\t\tObject.assign(data, layoutData);\n\t\t}\n\t}\n\tlet endPointData = await loadClientAndServerData(\n\t\turl,\n\t\tparams,\n\t\tserverParams,\n\t\tdata,\n\t\tclientEndPoint,\n\t\tserverEndPoint,\n\t);\n\tObject.assign(data, endPointData);\n\tlet $props: Record<string, any> = { data };\n\n\t// If there are layouts, work our way upwards, pushing each component into\n\t// the default slot of its parent\n\t// TODO: Also handle layout server data\n\t// TODO: There's probably a nicer way to do this with reducers or something\n\t// TODO: Re-use parent layouts\n\tlet component = clientEndPoint.component as ServerComponent;\n\tlet slots: Record<string, ServerSlotRender> | undefined = undefined;\n\tif (handler.layouts) {\n\t\tlet slotFunctions: ServerSlotRender[] = [];\n\t\tslotFunctions[handler.layouts.length] = (_, context) =>\n\t\t\t(clientEndPoint.component as ServerComponent)($props, context);\n\t\tfor (let i = handler.layouts.length - 1; i >= 0; i--) {\n\t\t\tconst layoutEndPoint: PageEndPoint | undefined = (await handler.layouts[i].endPoint())\n\t\t\t\t?.default;\n\t\t\tif (layoutEndPoint?.component) {\n\t\t\t\tif (i === 0) {\n\t\t\t\t\tcomponent = layoutEndPoint.component as ServerComponent;\n\t\t\t\t\tslots = { _: slotFunctions[i + 1] };\n\t\t\t\t} else {\n\t\t\t\t\tslotFunctions[i] = (_, context) =>\n\t\t\t\t\t\t(layoutEndPoint.component as ServerComponent)($props, context, {\n\t\t\t\t\t\t\t_: slotFunctions[i + 1],\n\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tlet html;\n\ttry {\n\t\thtml = component($props, undefined, slots);\n\t\thtml = template.replace(\"%COMPONENT_HTML%\", html);\n\t} catch (error) {\n\t\t// TODO: Show a proper Error component\n\t\thtml = '<span style=\"color: red\">Script syntax error</span><p>' + error + \"</p>\";\n\t\tconsole.log(error);\n\t}\n\n\treturn new Response(html, {\n\t\tstatus: 200,\n\t\theaders: {\n\t\t\t\"Content-Type\": \"text/html\",\n\t\t},\n\t});\n}\n\nasync function runAction(\n\tev: ServerEvent,\n\turl: URL,\n\thandler: RouteHandler,\n\tparams: Record<string, string>,\n\tquery: URLSearchParams,\n) {\n\tconst actionName = (Array.from(query.keys())[0] || \"default\").replace(/^\\//, \"\");\n\tconst serverEndPoint: PageServerEndPoint | undefined =\n\t\thandler.serverEndPoint && (await handler.serverEndPoint()).default;\n\tif (serverEndPoint?.actions) {\n\t\tconst action = serverEndPoint.actions[actionName];\n\t\tif (action) {\n\t\t\t// TODO: form.errors etc\n\t\t\tconst serverParams = buildServerParams(ev, url, params);\n\n\t\t\tif (handler.serverHook) {\n\t\t\t\tconst serverHook: ServerHook | undefined = (await handler.serverHook()).default;\n\t\t\t\tif (serverHook?.handle) {\n\t\t\t\t\tawait serverHook.handle(serverParams);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst result = await action(serverParams); // <--\n\n\t\t\t// If there was no response returned from the action (such as errors\n\t\t\t// or a redirect), reload the page by redirecting\n\t\t\treturn result || seeOther(url.pathname);\n\t\t}\n\t}\n\n\treturn notFound();\n}\n\nasync function loadClientAndServerData(\n\turl: URL,\n\tparams: Record<string, string>,\n\tserverParams: ServerLoadEvent,\n\tdata: Record<string, any>,\n\tclientEndPoint?: PageEndPoint,\n\tserverEndPoint?: PageServerEndPoint,\n) {\n\tlet newData = {};\n\tif (clientEndPoint?.load) {\n\t\tconst clientParams = buildClientParams(url, data, params);\n\t\tconst clientData = await clientEndPoint.load(clientParams);\n\t\tif (clientData) {\n\t\t\tObject.assign(newData, clientData);\n\t\t}\n\t}\n\tif (serverEndPoint?.load) {\n\t\tconst serverData = await serverEndPoint.load(serverParams);\n\t\tif (serverData?.ok) {\n\t\t\tObject.assign(newData, await serverData.json());\n\t\t}\n\t}\n\treturn newData;\n}\n\nfunction buildClientParams(url: URL, params: Record<string, string>, data: Record<string, any>) {\n\treturn {\n\t\turl,\n\t\tparams,\n\t\tdata,\n\t};\n}\n\nfunction buildServerParams(\n\tev: ServerEvent,\n\turl: URL,\n\tparams: Record<string, string>,\n): ServerLoadEvent {\n\treturn {\n\t\turl,\n\t\tparams,\n\t\tappData: {},\n\t\trequest: ev.request,\n\t\tcookies: ev.cookies,\n\t\theaders: ev.headers,\n\t\tadapter: ev.adapter,\n\t};\n}\n"],"mappings":"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","names":["path"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@torpor/build",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.14",
|
|
4
4
|
"description": "A framework for building sites and apps with Torpor",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -32,6 +32,11 @@
|
|
|
32
32
|
"import": "./dist/server.js",
|
|
33
33
|
"require": "./dist/server.cjs"
|
|
34
34
|
},
|
|
35
|
+
"./test": {
|
|
36
|
+
"types": "./dist/test.d.ts",
|
|
37
|
+
"import": "./dist/test.js",
|
|
38
|
+
"require": "./dist/test.cjs"
|
|
39
|
+
},
|
|
35
40
|
"./manifest": {
|
|
36
41
|
"types": "./src/types/manifest.d.ts"
|
|
37
42
|
}
|
|
@@ -48,20 +53,20 @@
|
|
|
48
53
|
"dependencies": {
|
|
49
54
|
"cookie": "^1.0.2",
|
|
50
55
|
"dotenv": "^16.5.0",
|
|
51
|
-
"vite": "^6.
|
|
56
|
+
"vite": "^6.3.5",
|
|
52
57
|
"vite-tsconfig-paths": "^5.1.4",
|
|
53
58
|
"@torpor/view": "^0.0.11",
|
|
54
|
-
"@torpor/unplugin": "^0.1.
|
|
59
|
+
"@torpor/unplugin": "^0.1.6"
|
|
55
60
|
},
|
|
56
61
|
"devDependencies": {
|
|
57
62
|
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
|
58
63
|
"tsup": "^8.4.0",
|
|
59
|
-
"tsx": "^4.19.
|
|
64
|
+
"tsx": "^4.19.4",
|
|
60
65
|
"typescript": "^5.8.3",
|
|
61
|
-
"vitest": "^3.1.
|
|
66
|
+
"vitest": "^3.1.3"
|
|
62
67
|
},
|
|
63
68
|
"scripts": {
|
|
64
|
-
"build": "tsup",
|
|
69
|
+
"build": "tsc --noEmit && tsup",
|
|
65
70
|
"build:watch": "tsup --watch",
|
|
66
71
|
"check": "tsc --noEmit",
|
|
67
72
|
"test": "vitest"
|
package/src/response/response.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* header set to "application/json". Otherwise, if the body is a string, the
|
|
6
6
|
* content-type header will be set to "text/plain".
|
|
7
7
|
*/
|
|
8
|
-
export default function response(status: number, body?: object | string) {
|
|
8
|
+
export default function response(status: number, body?: object | string): Response {
|
|
9
9
|
let headers: Record<string, string> | undefined = undefined;
|
|
10
10
|
if (body) {
|
|
11
11
|
if (typeof body === "object") {
|
|
@@ -18,7 +18,7 @@ export default class CookieHelper {
|
|
|
18
18
|
return parse(header ?? "")[name];
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
set(name: string, value: string, options?: SerializeOptions) {
|
|
21
|
+
set(name: string, value: string, options?: SerializeOptions): void {
|
|
22
22
|
// Set a cookie header with some default values for security
|
|
23
23
|
options ??= {};
|
|
24
24
|
options.httpOnly ??= true;
|
|
@@ -27,7 +27,7 @@ export default class CookieHelper {
|
|
|
27
27
|
this.cookies.set(name, serialize(name, value, options));
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
delete(name: string, options?: SerializeOptions) {
|
|
30
|
+
delete(name: string, options?: SerializeOptions): void {
|
|
31
31
|
// Set a cookie header with an immediate expiry date
|
|
32
32
|
options ??= {};
|
|
33
33
|
options.expires = new Date(0);
|
|
@@ -15,11 +15,11 @@ export default class HeaderHelper {
|
|
|
15
15
|
return this.request.headers.get(name) ?? undefined;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
set(name: string, value: string) {
|
|
18
|
+
set(name: string, value: string): void {
|
|
19
19
|
this.headers.set(name, value);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
delete(name: string) {
|
|
22
|
+
delete(name: string): void {
|
|
23
23
|
this.headers.delete(name);
|
|
24
24
|
}
|
|
25
25
|
}
|
package/src/server/Routerx.ts
CHANGED
|
@@ -6,7 +6,7 @@ import type ServerFunction from "./types/ServerFunction";
|
|
|
6
6
|
// This is not actually used anywhere, for now at least
|
|
7
7
|
|
|
8
8
|
export default class Router {
|
|
9
|
-
methods = new Map<HttpMethod, RouteHandler[]>();
|
|
9
|
+
methods: Map<HttpMethod, RouteHandler[]> = new Map<HttpMethod, RouteHandler[]>();
|
|
10
10
|
middleware: MiddlewareHandler[] = [];
|
|
11
11
|
|
|
12
12
|
constructor() {
|
|
@@ -28,7 +28,7 @@ export default class Router {
|
|
|
28
28
|
return this;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
match(method: HttpMethod, path: string) {
|
|
31
|
+
match(method: HttpMethod, path: string): Match | undefined {
|
|
32
32
|
for (let handler of this.methods.get(method)!) {
|
|
33
33
|
let match = path.match(handler.regex);
|
|
34
34
|
if (match) {
|
|
@@ -65,3 +65,8 @@ class MiddlewareHandler {
|
|
|
65
65
|
this.fn = fn;
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
|
+
|
|
69
|
+
type Match = {
|
|
70
|
+
fn: ServerFunction;
|
|
71
|
+
params?: Record<string, string>;
|
|
72
|
+
};
|
package/src/server/Server.ts
CHANGED
|
@@ -74,7 +74,7 @@ export default class Server {
|
|
|
74
74
|
return this;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
match(path: string) {
|
|
77
|
+
match(path: string): Match | undefined {
|
|
78
78
|
for (let handler of this.routes) {
|
|
79
79
|
let match = path.match(handler.regex);
|
|
80
80
|
if (match) {
|
|
@@ -137,3 +137,8 @@ class RouteHandler {
|
|
|
137
137
|
// this.fn = fn;
|
|
138
138
|
// }
|
|
139
139
|
//}
|
|
140
|
+
|
|
141
|
+
type Match = {
|
|
142
|
+
fn: ServerFunction;
|
|
143
|
+
params?: Record<string, string>;
|
|
144
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// From https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/MIME_types/Common_types
|
|
2
2
|
|
|
3
|
-
export default function contentType(extension: string) {
|
|
3
|
+
export default function contentType(extension: string): string {
|
|
4
4
|
return types[extension] || "application/octet-stream";
|
|
5
5
|
}
|
|
6
6
|
|
package/src/site/Router.ts
CHANGED
|
@@ -16,7 +16,7 @@ export default class Router {
|
|
|
16
16
|
// this.addPage(route, file);
|
|
17
17
|
//}
|
|
18
18
|
|
|
19
|
-
addPages(routes: ManifestRoute[]) {
|
|
19
|
+
addPages(routes: ManifestRoute[]): this {
|
|
20
20
|
for (let r of routes) {
|
|
21
21
|
this.routes.push(
|
|
22
22
|
new Route(r.path, {
|
|
@@ -31,7 +31,7 @@ export default class Router {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
// TODO: Allow calling with the endpoint itself, so that you can setup an app with no scaffold
|
|
34
|
-
addPage(path: string, type: number, endPoint: () => Promise<any>) {
|
|
34
|
+
addPage(path: string, type: number, endPoint: () => Promise<any>): this {
|
|
35
35
|
this.routes.push(
|
|
36
36
|
new Route(path, {
|
|
37
37
|
path,
|
|
@@ -53,7 +53,7 @@ export default class Router {
|
|
|
53
53
|
}
|
|
54
54
|
*/
|
|
55
55
|
|
|
56
|
-
match(path: string, query: URLSearchParams) {
|
|
56
|
+
match(path: string, query: URLSearchParams): Match | undefined {
|
|
57
57
|
for (let route of this.routes) {
|
|
58
58
|
let match = path.match(route.regex);
|
|
59
59
|
if (match) {
|
|
@@ -157,3 +157,9 @@ class Route {
|
|
|
157
157
|
this.handler = handler;
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
|
+
|
|
161
|
+
type Match = {
|
|
162
|
+
handler: RouteHandler;
|
|
163
|
+
params?: Record<string, string>;
|
|
164
|
+
query: URLSearchParams;
|
|
165
|
+
};
|
package/src/site/Site.ts
CHANGED
|
@@ -33,12 +33,18 @@ export default class Site {
|
|
|
33
33
|
plugins: Plugin[] = [tsconfigPaths({ loose: true })];
|
|
34
34
|
// Is default adapter a bad idea?
|
|
35
35
|
adapter: Adapter = defaultAdapter;
|
|
36
|
+
/**
|
|
37
|
+
* Extra inputs, as absolute file paths, that will be compiled with the
|
|
38
|
+
* output. What you do with them after that is up to you. File paths ending
|
|
39
|
+
* with server.ts/js will only be compiled with the server output
|
|
40
|
+
*/
|
|
41
|
+
inputs: string[] = [];
|
|
36
42
|
|
|
37
43
|
constructor() {
|
|
38
44
|
this.root = process.cwd();
|
|
39
45
|
}
|
|
40
46
|
|
|
41
|
-
async addRouteFolder(folder: string) {
|
|
47
|
+
async addRouteFolder(folder: string): Promise<void> {
|
|
42
48
|
const routeFolder = path.join(this.root, folder);
|
|
43
49
|
const routeFiles = await fs.readdir(routeFolder, { recursive: true });
|
|
44
50
|
|
|
@@ -63,7 +69,7 @@ export default class Site {
|
|
|
63
69
|
this.#sortRoutes();
|
|
64
70
|
}
|
|
65
71
|
|
|
66
|
-
addRouteFile(path: string, file: string) {
|
|
72
|
+
addRouteFile(path: string, file: string): void {
|
|
67
73
|
let type = this.#routeType(file);
|
|
68
74
|
this.routes.push({ path, file, type });
|
|
69
75
|
this.#sortRoutes();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export default function prepareTemplate(template: string, clientScript: string) {
|
|
1
|
+
export default function prepareTemplate(template: string, clientScript: string): string {
|
|
2
2
|
let contentStart = regexIndexOf(template, /\<div\s+id=("app"|'app'|app)\s+/);
|
|
3
3
|
contentStart = template.indexOf(">", contentStart) + 1;
|
|
4
4
|
let contentEnd = template.indexOf("</div>", contentStart);
|
package/src/site/run.ts
CHANGED
|
@@ -6,7 +6,10 @@ import runBuild from "./runBuild";
|
|
|
6
6
|
import runDev from "./runDev";
|
|
7
7
|
import runPreview from "./runPreview";
|
|
8
8
|
|
|
9
|
-
export default async function run(
|
|
9
|
+
export default async function run(
|
|
10
|
+
folder: string,
|
|
11
|
+
mode: "dev" | "build" | "preview",
|
|
12
|
+
): Promise<void> {
|
|
10
13
|
// Look for and load a site.config.js/ts file in the working directory
|
|
11
14
|
let configFile = "";
|
|
12
15
|
let deleteConfigFile = false;
|
|
@@ -19,12 +22,11 @@ export default async function run(folder: string, mode: "dev" | "build" | "previ
|
|
|
19
22
|
// If it's TS, we need to convert it to JS
|
|
20
23
|
// TODO: Put the generated file somewhere better (dist?)
|
|
21
24
|
configFile = path.join(folder, "site.config.temp.js");
|
|
22
|
-
let source = (
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
fs.writeFileSync(configFile, source);
|
|
25
|
+
let source = fs.readFileSync(tsConfigFile, "utf-8");
|
|
26
|
+
let transformed = await transformWithEsbuild(source, tsConfigFile, {
|
|
27
|
+
loader: "ts",
|
|
28
|
+
});
|
|
29
|
+
fs.writeFileSync(configFile, transformed.code);
|
|
28
30
|
deleteConfigFile = true;
|
|
29
31
|
} else {
|
|
30
32
|
throw new Error("site.config file not found");
|
package/src/site/runBuild.ts
CHANGED
|
@@ -10,7 +10,7 @@ import manifest from "./manifest.ts";
|
|
|
10
10
|
// TODO: Don't reload layouts during client routing
|
|
11
11
|
// TODO: Call the correct +page and +server routes when in the same folder
|
|
12
12
|
|
|
13
|
-
export default async function runBuild(site: Site) {
|
|
13
|
+
export default async function runBuild(site: Site): Promise<void> {
|
|
14
14
|
// Delete the dist folder if it exists
|
|
15
15
|
const distFolder = path.resolve(site.root, "dist");
|
|
16
16
|
if (existsSync(distFolder)) {
|
|
@@ -36,12 +36,7 @@ export default async function runBuild(site: Site) {
|
|
|
36
36
|
// EXCLUDING anything with `server.js` in the name
|
|
37
37
|
await build(
|
|
38
38
|
defineConfig({
|
|
39
|
-
plugins: [
|
|
40
|
-
manifest(site),
|
|
41
|
-
// @ts-ignore
|
|
42
|
-
torpor(),
|
|
43
|
-
...site.plugins,
|
|
44
|
-
],
|
|
39
|
+
plugins: [manifest(site), torpor(), ...site.plugins],
|
|
45
40
|
build: {
|
|
46
41
|
outDir: clientFolder,
|
|
47
42
|
rollupOptions: {
|
|
@@ -51,6 +46,7 @@ export default async function runBuild(site: Site) {
|
|
|
51
46
|
...site.routes
|
|
52
47
|
.filter((r) => !/server\.(ts|js)$/.test(r.file))
|
|
53
48
|
.map((r) => path.resolve(site.root, r.file)),
|
|
49
|
+
...site.inputs.filter((f) => !/server\.(ts|js)$/.test(f)),
|
|
54
50
|
],
|
|
55
51
|
},
|
|
56
52
|
ssrManifest: true,
|
|
@@ -62,16 +58,15 @@ export default async function runBuild(site: Site) {
|
|
|
62
58
|
// files
|
|
63
59
|
await build(
|
|
64
60
|
defineConfig({
|
|
65
|
-
plugins: [
|
|
66
|
-
manifest(site, true),
|
|
67
|
-
// @ts-ignore
|
|
68
|
-
torpor(),
|
|
69
|
-
...site.plugins,
|
|
70
|
-
],
|
|
61
|
+
plugins: [manifest(site, true), torpor(), ...site.plugins],
|
|
71
62
|
build: {
|
|
72
63
|
outDir: serverFolder,
|
|
73
64
|
rollupOptions: {
|
|
74
|
-
input: [
|
|
65
|
+
input: [
|
|
66
|
+
serverScript,
|
|
67
|
+
...site.routes.map((r) => path.resolve(site.root, r.file)),
|
|
68
|
+
...site.inputs,
|
|
69
|
+
],
|
|
75
70
|
},
|
|
76
71
|
ssr: serverScript,
|
|
77
72
|
},
|
package/src/site/runDev.ts
CHANGED
|
@@ -10,7 +10,7 @@ import Site from "./Site.ts";
|
|
|
10
10
|
import manifest from "./manifest.ts";
|
|
11
11
|
import prepareTemplate from "./prepareTemplate.ts";
|
|
12
12
|
|
|
13
|
-
export default async function runDev(site: Site) {
|
|
13
|
+
export default async function runDev(site: Site): Promise<void> {
|
|
14
14
|
const server = new Server();
|
|
15
15
|
|
|
16
16
|
// Create the Vite server in middleware mode and configure the app type as
|
|
@@ -19,12 +19,7 @@ export default async function runDev(site: Site) {
|
|
|
19
19
|
const vite = await createViteServer({
|
|
20
20
|
server: { middlewareMode: true },
|
|
21
21
|
appType: "custom",
|
|
22
|
-
plugins: [
|
|
23
|
-
manifest(site, true),
|
|
24
|
-
// @ts-ignore not sure...
|
|
25
|
-
torpor(),
|
|
26
|
-
...site.plugins,
|
|
27
|
-
],
|
|
22
|
+
plugins: [manifest(site, true), torpor(), ...site.plugins],
|
|
28
23
|
});
|
|
29
24
|
|
|
30
25
|
// Read site.html
|
|
@@ -46,7 +41,7 @@ export default async function runDev(site: Site) {
|
|
|
46
41
|
// Prepare site.html so that we can just splice components into it
|
|
47
42
|
template = prepareTemplate(template, clientScript);
|
|
48
43
|
|
|
49
|
-
// Use
|
|
44
|
+
// Use Vite's Connect instance as middleware. We need to wrap it with
|
|
50
45
|
// createMiddlewareHandler that converts Connect middleware to
|
|
51
46
|
// Request/Response web handlers
|
|
52
47
|
server.use(connectMiddleware(vite.middlewares));
|
package/src/site/runPreview.ts
CHANGED
|
@@ -8,7 +8,7 @@ import Site from "./Site";
|
|
|
8
8
|
import prepareTemplate from "./prepareTemplate.ts";
|
|
9
9
|
import runBuild from "./runBuild";
|
|
10
10
|
|
|
11
|
-
export default async function runPreview(site: Site) {
|
|
11
|
+
export default async function runPreview(site: Site): Promise<void> {
|
|
12
12
|
// Build the site
|
|
13
13
|
await runBuild(site);
|
|
14
14
|
|
package/src/site/serverEntry.ts
CHANGED
|
@@ -28,7 +28,7 @@ router.addPages(manifest.routes);
|
|
|
28
28
|
|
|
29
29
|
//console.log(`routes:\n ${router.routes.map((r) => r.path).join("\n ")}`);
|
|
30
30
|
|
|
31
|
-
export async function load(ev: ServerEvent, template: string) {
|
|
31
|
+
export async function load(ev: ServerEvent, template: string): Promise<Response> {
|
|
32
32
|
//const url = new URL(`http://${process.env.HOST ?? "localhost"}${ev.request.url}`);
|
|
33
33
|
const url = new URL(ev.request.url);
|
|
34
34
|
const path = url.pathname;
|