@torpor/build 0.4.8 → 0.4.10

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.
Files changed (105) hide show
  1. package/dist/nav.mjs +3 -1
  2. package/dist/nav.mjs.map +1 -1
  3. package/package.json +7 -3
  4. package/CHANGELOG.md +0 -467
  5. package/scripts/postbuild.ts +0 -12
  6. package/src/bin/index.ts +0 -11
  7. package/src/index.ts +0 -30
  8. package/src/nav/formSubmit.ts +0 -49
  9. package/src/nav/load.ts +0 -9
  10. package/src/nav/loadData.ts +0 -134
  11. package/src/nav/navigate.ts +0 -164
  12. package/src/nav/reload.ts +0 -9
  13. package/src/nav.ts +0 -4
  14. package/src/response/badRequest.ts +0 -19
  15. package/src/response/created.ts +0 -20
  16. package/src/response/forbidden.ts +0 -21
  17. package/src/response/found.ts +0 -30
  18. package/src/response/methodNotAllowed.ts +0 -18
  19. package/src/response/movedPermanently.ts +0 -25
  20. package/src/response/notFound.ts +0 -24
  21. package/src/response/notModified.ts +0 -34
  22. package/src/response/ok.ts +0 -29
  23. package/src/response/permanentRedirect.ts +0 -30
  24. package/src/response/response.ts +0 -22
  25. package/src/response/seeOther.ts +0 -19
  26. package/src/response/serverError.ts +0 -24
  27. package/src/response/temporaryRedirect.ts +0 -31
  28. package/src/response/transfer.ts +0 -14
  29. package/src/response/unauthorized.ts +0 -21
  30. package/src/response/unprocessable.ts +0 -18
  31. package/src/response.ts +0 -37
  32. package/src/run/prepareTemplate.ts +0 -39
  33. package/src/run/run.ts +0 -62
  34. package/src/run/runBuild.ts +0 -77
  35. package/src/run/runDev.ts +0 -89
  36. package/src/run/runPreview.ts +0 -93
  37. package/src/run.ts +0 -6
  38. package/src/server/CookieHelper.ts +0 -36
  39. package/src/server/HeaderHelper.ts +0 -25
  40. package/src/server/Routerx.ts +0 -72
  41. package/src/server/Server.ts +0 -144
  42. package/src/server/ServerEvent.ts +0 -39
  43. package/src/server/connect/bufferToArrayBuffer.ts +0 -8
  44. package/src/server/connect/connectMiddleware.ts +0 -81
  45. package/src/server/connect/flattenHeaders.ts +0 -44
  46. package/src/server/connect/nodeMessageToNodeResponse.ts +0 -89
  47. package/src/server/connect/readableToBuffer.ts +0 -16
  48. package/src/server/connect/requestToNodeMessage.ts +0 -26
  49. package/src/server/contentType.ts +0 -85
  50. package/src/server/types/HttpMethod.ts +0 -12
  51. package/src/server/types/MiddlewareFunction.ts +0 -8
  52. package/src/server/types/ServerFunction.ts +0 -7
  53. package/src/server.ts +0 -7
  54. package/src/site/Router.ts +0 -164
  55. package/src/site/Site.ts +0 -214
  56. package/src/site/clientEntry.ts +0 -108
  57. package/src/site/clientEntryDev.ts +0 -3
  58. package/src/site/defaultAdapter.ts +0 -11
  59. package/src/site/manifest.ts +0 -54
  60. package/src/site/serverEntry.ts +0 -417
  61. package/src/state/$page.ts +0 -24
  62. package/src/state/client.ts +0 -15
  63. package/src/state.ts +0 -3
  64. package/src/test/runTest.ts +0 -350
  65. package/src/test.ts +0 -3
  66. package/src/types/Adapter.ts +0 -8
  67. package/src/types/ClientState.ts +0 -8
  68. package/src/types/InternalState.ts +0 -7
  69. package/src/types/LayoutHandler.ts +0 -5
  70. package/src/types/LayoutPath.ts +0 -10
  71. package/src/types/ManifestRoute.ts +0 -6
  72. package/src/types/PageEndPoint.ts +0 -39
  73. package/src/types/PageLoadEvent.ts +0 -14
  74. package/src/types/PageServerAction.ts +0 -7
  75. package/src/types/PageServerEndPoint.ts +0 -16
  76. package/src/types/PageServerLoad.ts +0 -7
  77. package/src/types/PageState.ts +0 -8
  78. package/src/types/Route.ts +0 -11
  79. package/src/types/RouteHandler.ts +0 -16
  80. package/src/types/RouteLayoutHandler.ts +0 -5
  81. package/src/types/RouteMatchResult.ts +0 -7
  82. package/src/types/RouteType.ts +0 -19
  83. package/src/types/ServerEndPoint.ts +0 -37
  84. package/src/types/ServerHook.ts +0 -11
  85. package/src/types/ServerLoadEvent.ts +0 -37
  86. package/src/types/ServerRequest.ts +0 -7
  87. package/src/utils/pathToRegex.ts +0 -15
  88. package/src/vite-env.d.ts +0 -2
  89. package/test/api/_hook.server.ts +0 -3
  90. package/test/api/posts/+page.server.ts +0 -3
  91. package/test/api/posts/[id]/+page.server.ts +0 -3
  92. package/test/app.test.ts +0 -47
  93. package/test/router.test.ts +0 -78
  94. package/test/routes/+page.server.ts +0 -3
  95. package/test/routes/+page.ts +0 -3
  96. package/test/routes/_error.ts +0 -3
  97. package/test/routes/_hook.server.ts +0 -3
  98. package/test/routes/_layout.server.ts +0 -3
  99. package/test/routes/_layout.ts +0 -3
  100. package/test/routes/posts/+page.ts +0 -3
  101. package/test/routes/posts/[id]/+page.ts +0 -3
  102. package/test/site.test.ts +0 -40
  103. package/tsconfig.json +0 -9
  104. package/tsdown.config.ts +0 -18
  105. package/vitest.config.ts +0 -3
@@ -1,417 +0,0 @@
1
- import manifest from "@torpor/build/manifest";
2
- import { type ServerComponent, type ServerSlotRender } from "@torpor/view/ssr";
3
- import notFound from "../response/notFound.ts";
4
- import ok from "../response/ok.ts";
5
- import seeOther from "../response/seeOther.ts";
6
- import ServerEvent from "../server/ServerEvent.ts";
7
- import $page from "../state/$page";
8
- import type PageEndPoint from "../types/PageEndPoint.ts";
9
- import type PageServerEndPoint from "../types/PageServerEndPoint.ts";
10
- import type RouteHandler from "../types/RouteHandler.ts";
11
- import {
12
- ERROR_ROUTE,
13
- HOOK_ROUTE,
14
- HOOK_SERVER_ROUTE,
15
- LAYOUT_ROUTE,
16
- LAYOUT_SERVER_ROUTE,
17
- PAGE_ROUTE,
18
- PAGE_SERVER_ROUTE,
19
- SERVER_ROUTE,
20
- } from "../types/RouteType";
21
- import type ServerEndPoint from "../types/ServerEndPoint.ts";
22
- import type ServerHook from "../types/ServerHook.ts";
23
- import type ServerLoadEvent from "../types/ServerLoadEvent.ts";
24
- import Router from "./Router.ts";
25
-
26
- // Build the router from the Site object created by the user
27
- const router = new Router();
28
- router.addPages(manifest.routes);
29
-
30
- //console.log(`routes:\n ${router.routes.map((r) => r.path).join("\n ")}`);
31
-
32
- export async function load(ev: ServerEvent, template: string): Promise<Response> {
33
- const url = new URL(ev.request.url);
34
- const path = url.pathname;
35
- const query = url.searchParams;
36
-
37
- //console.log(`handling ${ev.request.method} for '${path}'${query.size ? ` with ${query}` : ""}`);
38
-
39
- const route = router.match(path, query);
40
- if (!route) {
41
- return handleResponse(notFound());
42
- }
43
- const handler = route.handler;
44
- const params = route.params || {};
45
-
46
- // Update $page before building the components
47
- $page.url = url;
48
- if (path.endsWith("/_error")) {
49
- $page.status = parseInt(query.get("status") ?? "404");
50
- $page.error = { message: query.get("message") ?? "" };
51
- } else {
52
- $page.status = 200;
53
- }
54
-
55
- // TODO: Hit the server hook out here
56
- // We could maybe set data loading up as middleware on a route??????
57
-
58
- switch (handler.type) {
59
- case PAGE_ROUTE:
60
- case LAYOUT_ROUTE: {
61
- // It's a /+page.ts or /_layout.ts endpoint
62
- if (ev.request.method === "GET") {
63
- return handleResponse(await loadView(ev, url, handler, params, template));
64
- } else if (ev.request.method === "POST") {
65
- return handleResponse(await runAction(ev, url, handler, params, query, template), true);
66
- }
67
- break;
68
- }
69
- case PAGE_SERVER_ROUTE:
70
- case LAYOUT_SERVER_ROUTE: {
71
- // It's a /+page.server.ts or /_layout.server.ts endpoint
72
- if (ev.request.method === "GET") {
73
- return await loadData(ev, url, handler, "load", params);
74
- }
75
- break;
76
- }
77
- case SERVER_ROUTE: {
78
- // It's a /+server.ts endpoint
79
- const functionName = ev.request.method.toLowerCase().replace("delete", "del");
80
- return await loadData(ev, url, handler, functionName, params);
81
- }
82
- case HOOK_ROUTE:
83
- case HOOK_SERVER_ROUTE: {
84
- break;
85
- }
86
- case ERROR_ROUTE: {
87
- return await loadView(ev, url, handler, params, template);
88
- }
89
- }
90
-
91
- return notFound();
92
- }
93
-
94
- async function handleResponse(response: Response, fromForm = false): Promise<Response> {
95
- $page.status = response.status;
96
-
97
- // Success codes and redirect codes are acceptable
98
- if (response.status >= 200 && response.status <= 399) {
99
- return response;
100
- }
101
-
102
- // 4xx error codes are acceptable from form actions
103
- if (fromForm && response.status >= 400 && response.status <= 499) {
104
- return response;
105
- }
106
-
107
- // It's an error, so redirect to the error page
108
- // We're just pushing the status and message in the URL, but maybe there's a
109
- // more sophisticated way to do this?
110
- // TODO: Should be returning loadView rather than redirecting
111
- // TODO: Should be returning the NEAREST error page to this path, including layouts
112
- let params = new URLSearchParams();
113
- params.append("status", $page.status.toString());
114
- let message = await response.text();
115
- if (response.headers.get("Content-Type")?.includes("application/json")) {
116
- const data = JSON.parse(message);
117
- message = data.message ?? message;
118
- }
119
- if (message) {
120
- if ($page.error) {
121
- $page.error.message = message;
122
- } else {
123
- $page.error = { message };
124
- }
125
- params.append("message", message);
126
- }
127
- return seeOther(`/_error?${params.toString()}`);
128
- }
129
-
130
- async function loadData(
131
- ev: ServerEvent,
132
- url: URL,
133
- handler: RouteHandler,
134
- functionName: string,
135
- params: Record<string, string>,
136
- ) {
137
- const serverEndPoint: ServerEndPoint | undefined = (await handler.endPoint()).default;
138
- if (serverEndPoint && serverEndPoint[functionName]) {
139
- const serverParams = buildServerParams(ev, url, params);
140
-
141
- if (handler.serverHook) {
142
- const serverHook: ServerHook | undefined = (await handler.serverHook()).default;
143
- if (serverHook?.handle) {
144
- await serverHook.handle(serverParams);
145
- }
146
- }
147
-
148
- const result = await serverEndPoint[functionName](serverParams);
149
-
150
- // If there was no response returned from load (such as errors or a
151
- // redirect), send an ok response
152
- return result || ok();
153
- }
154
-
155
- return notFound();
156
- }
157
-
158
- async function loadView(
159
- ev: ServerEvent,
160
- url: URL,
161
- handler: RouteHandler,
162
- params: Record<string, string>,
163
- template: string,
164
- formStatus?: number,
165
- form?: Record<string, string | number>,
166
- ) {
167
- // There must be a client endpoint with a component
168
- const clientEndPoint: PageEndPoint | undefined = (await handler.endPoint()).default;
169
- if (!clientEndPoint?.component) {
170
- return notFound();
171
- }
172
-
173
- // There may be a server endpoint
174
- const serverEndPoint: PageServerEndPoint | undefined =
175
- handler.serverEndPoint && (await handler.serverEndPoint())?.default;
176
-
177
- // Maybe hit the server hook
178
- const serverParams = buildServerParams(ev, url, params);
179
- if (handler.serverHook) {
180
- const serverHook: ServerHook | undefined = (await handler.serverHook()).default;
181
- if (serverHook?.handle) {
182
- await serverHook.handle(serverParams);
183
- }
184
- }
185
-
186
- // Pass the data into $props
187
- // TODO: Promise.all
188
- // NOTE: We're loading data from top to bottom, overriding as we go, and I'm
189
- // not sure if this is the best way to go
190
- let data = {};
191
- if (handler.layouts) {
192
- for (let layout of handler.layouts) {
193
- const layoutEndPoint: PageEndPoint | undefined = (await layout.endPoint())?.default;
194
- const layoutServerEndPoint: PageServerEndPoint | undefined =
195
- layout.serverEndPoint && (await layout.serverEndPoint())?.default;
196
- const layoutResponse = await loadClientAndServerData(
197
- url,
198
- params,
199
- serverParams,
200
- data,
201
- layoutEndPoint,
202
- layoutServerEndPoint,
203
- );
204
- if (layoutResponse?.ok === false) {
205
- return layoutResponse;
206
- }
207
- }
208
- }
209
- let endPointResponse = await loadClientAndServerData(
210
- url,
211
- params,
212
- serverParams,
213
- data,
214
- clientEndPoint,
215
- serverEndPoint,
216
- );
217
- if (endPointResponse?.ok === false) {
218
- return endPointResponse;
219
- }
220
- let $props: Record<string, any> = { data, form };
221
-
222
- let styles = "";
223
-
224
- // If there are layouts, work our way upwards, pushing each component into
225
- // the default slot of its parent
226
- // TODO: Also handle layout server data
227
- // TODO: There's probably a nicer way to do this with reducers or something
228
- let component = clientEndPoint.component as ServerComponent;
229
- let slots: Record<string, ServerSlotRender> | undefined = undefined;
230
- if (handler.layouts) {
231
- let slotFunctions: ServerSlotRender[] = [];
232
- slotFunctions[handler.layouts.length] = (_, $context) => {
233
- let { body, head } = (clientEndPoint.component as ServerComponent)($props, $context);
234
- styles += head;
235
- return body;
236
- };
237
- for (let i = handler.layouts.length - 1; i >= 0; i--) {
238
- const layoutEndPoint: PageEndPoint | undefined = (await handler.layouts[i].endPoint())
239
- ?.default;
240
- if (layoutEndPoint?.component) {
241
- if (i === 0) {
242
- component = layoutEndPoint.component as ServerComponent;
243
- slots = { _: slotFunctions[i + 1] };
244
- } else {
245
- slotFunctions[i] = (_, $context) => {
246
- let { body, head } = (layoutEndPoint.component as ServerComponent)($props, $context, {
247
- _: slotFunctions[i + 1],
248
- });
249
- styles += head;
250
- return body;
251
- };
252
- }
253
- }
254
- }
255
- }
256
-
257
- let html;
258
- try {
259
- let { body, head } = component($props, undefined, slots);
260
-
261
- // Put the form info in a hidden input so that it can be accessed on the client
262
- if (form) {
263
- body += `\n<input type="hidden" id="t-form-data" value='${JSON.stringify(form).replaceAll("'", "\\'")}' />`;
264
- }
265
-
266
- styles += head;
267
- html = template.replace("%COMPONENT_BODY%", body).replace("%COMPONENT_HEAD%", styles);
268
- } catch (error) {
269
- // TODO: Show a proper Error component
270
- html = '<span style="color: red">Script syntax error</span><p>' + error + "</p>";
271
- console.log(error);
272
- }
273
-
274
- return new Response(html, {
275
- status: formStatus ?? 200,
276
- headers: {
277
- "Content-Type": "text/html",
278
- },
279
- });
280
- }
281
-
282
- async function runAction(
283
- ev: ServerEvent,
284
- url: URL,
285
- handler: RouteHandler,
286
- params: Record<string, string>,
287
- query: URLSearchParams,
288
- template: string,
289
- ) {
290
- const actionName = (Array.from(query.keys())[0] || "default").replace(/^\//, "");
291
- const serverEndPoint: PageServerEndPoint | undefined =
292
- handler.serverEndPoint && (await handler.serverEndPoint()).default;
293
- if (serverEndPoint?.actions) {
294
- const action = serverEndPoint.actions[actionName];
295
- if (action) {
296
- const serverParams = buildServerParams(ev, url, params);
297
-
298
- if (handler.serverHook) {
299
- const serverHook: ServerHook | undefined = (await handler.serverHook()).default;
300
- if (serverHook?.handle) {
301
- await serverHook.handle(serverParams);
302
- }
303
- }
304
-
305
- let result = await action(serverParams);
306
-
307
- if (ev.request.headers.has("x-torpor-form-submit")) {
308
- // If the form was submitted from javascript, just return the
309
- // response and it will be handled on the client
310
- // TODO: Should we make the user return a response??
311
- result ??= ok();
312
-
313
- // If it's a redirect, we need to stop the browser handling it
314
- if (result.status >= 300 && result.status <= 399) {
315
- const location = result.headers.get("location") ?? "";
316
- result = ok();
317
- result.headers.set("x-torpor-form-redirect", "");
318
- result.headers.set("location", location);
319
- }
320
-
321
- return result;
322
- } else if (
323
- !result ||
324
- (result.status >= 200 && result.status <= 299) ||
325
- (result.status >= 400 && result.status <= 499)
326
- ) {
327
- // If the form was submitted without javascript, and there was
328
- // no result, an ok result, or a 4xx error, re-render the view
329
- // with the form result
330
- // TODO: do not re-run hooks?
331
- const newUrl = new URL(url.pathname, url);
332
- const formStatus = result?.status;
333
- let formMessage = await result?.text();
334
- if (formMessage && result?.headers.get("Content-Type")?.includes("application/json")) {
335
- $page.form = JSON.parse(formMessage);
336
- formMessage = undefined;
337
- } else {
338
- $page.form = {};
339
- }
340
- // Set status and message if they haven't already been set,
341
- // which means that you can just return e.g. forbidden() or
342
- // forbidden("no!") and there will be something you can work
343
- // with in your component, or you can set a completely custom
344
- // object with whatever info you need
345
- $page.form!.status ??= formStatus ?? 0;
346
- $page.form!.message ??= formMessage ?? "";
347
- return await loadView(ev, newUrl, handler, params, template, formStatus, $page.form);
348
- } else {
349
- // If the form was submitted without javascript and there was a
350
- // redirect or server error, just return the result to handle it
351
- // as normal
352
- return result;
353
- }
354
- }
355
- }
356
-
357
- return notFound();
358
- }
359
-
360
- async function loadClientAndServerData(
361
- url: URL,
362
- params: Record<string, string>,
363
- serverParams: ServerLoadEvent,
364
- data: Record<string, any>,
365
- clientEndPoint?: PageEndPoint,
366
- serverEndPoint?: PageServerEndPoint,
367
- ) {
368
- if (clientEndPoint?.load) {
369
- const clientParams = buildClientParams(url, params, data);
370
- const clientResponse = await clientEndPoint.load(clientParams);
371
- if (clientResponse) {
372
- if (clientResponse.ok) {
373
- if (clientResponse.headers.get("Content-Type")?.includes("application/json")) {
374
- Object.assign(data, await clientResponse.json());
375
- }
376
- } else {
377
- return clientResponse;
378
- }
379
- }
380
- }
381
- if (serverEndPoint?.load) {
382
- const serverResponse = await serverEndPoint.load(serverParams);
383
- if (serverResponse) {
384
- if (serverResponse.ok) {
385
- if (serverResponse.headers.get("Content-Type")?.includes("application/json")) {
386
- Object.assign(data, await serverResponse.json());
387
- }
388
- } else {
389
- return serverResponse;
390
- }
391
- }
392
- }
393
- }
394
-
395
- function buildClientParams(url: URL, params: Record<string, string>, data: Record<string, any>) {
396
- return {
397
- url,
398
- params,
399
- data,
400
- };
401
- }
402
-
403
- function buildServerParams(
404
- ev: ServerEvent,
405
- url: URL,
406
- params: Record<string, string>,
407
- ): ServerLoadEvent {
408
- return {
409
- url,
410
- params,
411
- appData: {},
412
- request: ev.request,
413
- cookies: ev.cookies,
414
- headers: ev.headers,
415
- adapter: ev.adapter,
416
- };
417
- }
@@ -1,24 +0,0 @@
1
- import { $watch } from "@torpor/view";
2
- import type PageState from "../types/PageState";
3
-
4
- const PAGE_SYMBOL: unique symbol = Symbol.for("t_page");
5
-
6
- const $page: PageState =
7
- // @ts-ignore
8
- (globalThis[PAGE_SYMBOL] ??=
9
- // TODO: Should use the SSR $watch if entering via serverEntry
10
- $watch(
11
- {
12
- status: 404,
13
- url: new URL("http://localhost"),
14
- form: undefined,
15
- error: {
16
- message: "",
17
- },
18
- },
19
- {
20
- shallow: true,
21
- },
22
- ));
23
-
24
- export default $page;
@@ -1,15 +0,0 @@
1
- import type ClientState from "../types/ClientState";
2
-
3
- const CLIENT_SYMBOL: unique symbol = Symbol.for("t_client_state");
4
-
5
- const client: ClientState =
6
- // @ts-ignore
7
- (globalThis[CLIENT_SYMBOL] ??= {
8
- // @ts-ignore This will definitely, 100% get set
9
- router: null,
10
- layoutStack: [],
11
- // TODO: Probably expire after 30 seconds or something?
12
- prefetchedData: {},
13
- });
14
-
15
- export default client;
package/src/state.ts DELETED
@@ -1,3 +0,0 @@
1
- import $page from "./state/$page";
2
-
3
- export { $page };