@torpor/build 0.2.0 → 0.3.1

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 (158) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/dist/RouteType-g8Ce5gOd.js +107 -0
  3. package/dist/RouteType-g8Ce5gOd.js.map +1 -0
  4. package/dist/Server-CSpY_-Ba.d.ts +78 -0
  5. package/dist/Server-CSpY_-Ba.d.ts.map +1 -0
  6. package/dist/ServerEvent-2-CnAy1W.js +74 -0
  7. package/dist/ServerEvent-2-CnAy1W.js.map +1 -0
  8. package/dist/Site-D4x1l0p5.d.ts +67 -0
  9. package/dist/Site-D4x1l0p5.d.ts.map +1 -0
  10. package/dist/_page-Cv6YWocY.js +33 -0
  11. package/dist/_page-Cv6YWocY.js.map +1 -0
  12. package/dist/bin/index.d.ts +1 -1
  13. package/dist/bin/index.js +14 -19
  14. package/dist/bin/index.js.map +1 -1
  15. package/dist/connectMiddleware-DbLj0St1.js +252 -0
  16. package/dist/connectMiddleware-DbLj0St1.js.map +1 -0
  17. package/dist/index.d.ts +188 -179
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +109 -145
  20. package/dist/index.js.map +1 -1
  21. package/dist/nav.d.ts +14 -0
  22. package/dist/nav.d.ts.map +1 -0
  23. package/dist/nav.js +206 -0
  24. package/dist/nav.js.map +1 -0
  25. package/dist/pathToRegex-CTgx7hQP.js +11 -0
  26. package/dist/pathToRegex-CTgx7hQP.js.map +1 -0
  27. package/dist/response-D-XpIuMH.js +307 -0
  28. package/dist/response-D-XpIuMH.js.map +1 -0
  29. package/dist/response.d.ts +336 -151
  30. package/dist/response.d.ts.map +1 -0
  31. package/dist/response.js +4 -37
  32. package/dist/run-CVKpO0HO.js +331 -0
  33. package/dist/run-CVKpO0HO.js.map +1 -0
  34. package/dist/run.d.ts +11 -8
  35. package/dist/run.d.ts.map +1 -0
  36. package/dist/run.js +8 -18
  37. package/dist/seeOther-BmehiI4C.js +110 -0
  38. package/dist/seeOther-BmehiI4C.js.map +1 -0
  39. package/dist/server.d.ts +12 -11
  40. package/dist/server.d.ts.map +1 -0
  41. package/dist/server.js +5 -18
  42. package/dist/state.d.ts +14 -10
  43. package/dist/state.d.ts.map +1 -0
  44. package/dist/state.js +3 -7
  45. package/dist/test.d.ts +12 -11
  46. package/dist/test.d.ts.map +1 -0
  47. package/dist/test.js +152 -225
  48. package/dist/test.js.map +1 -1
  49. package/package.json +25 -29
  50. package/src/bin/index.ts +9 -11
  51. package/src/index.ts +3 -0
  52. package/src/nav/formSubmit.ts +48 -0
  53. package/src/nav/load.ts +9 -0
  54. package/src/nav/loadData.ts +121 -0
  55. package/src/nav/navigate.ts +163 -0
  56. package/src/nav/reload.ts +9 -0
  57. package/src/nav.ts +4 -0
  58. package/src/response/badRequest.ts +9 -4
  59. package/src/response/created.ts +10 -3
  60. package/src/response/forbidden.ts +11 -4
  61. package/src/response/found.ts +30 -0
  62. package/src/response/methodNotAllowed.ts +8 -4
  63. package/src/response/movedPermanently.ts +25 -0
  64. package/src/response/notFound.ts +14 -7
  65. package/src/response/notModified.ts +24 -4
  66. package/src/response/ok.ts +19 -10
  67. package/src/response/permanentRedirect.ts +30 -0
  68. package/src/response/seeOther.ts +9 -3
  69. package/src/response/serverError.ts +14 -2
  70. package/src/response/temporaryRedirect.ts +31 -0
  71. package/src/response/unauthorized.ts +11 -4
  72. package/src/response/unprocessable.ts +8 -2
  73. package/src/response.ts +8 -4
  74. package/src/{site → run}/prepareTemplate.ts +1 -1
  75. package/src/{site → run}/run.ts +1 -1
  76. package/src/{site → run}/runBuild.ts +2 -2
  77. package/src/{site → run}/runDev.ts +2 -2
  78. package/src/{site → run}/runPreview.ts +1 -1
  79. package/src/run.ts +4 -4
  80. package/src/server/Routerx.ts +3 -3
  81. package/src/server/Server.ts +3 -3
  82. package/src/server/connect/connectMiddleware.ts +2 -1
  83. package/src/server/connect/nodeMessageToNodeResponse.ts +2 -2
  84. package/src/site/Router.ts +3 -3
  85. package/src/site/clientEntry.ts +16 -269
  86. package/src/site/defaultAdapter.ts +1 -1
  87. package/src/site/serverEntry.ts +86 -45
  88. package/src/state/$page.ts +3 -12
  89. package/src/state/client.ts +6 -0
  90. package/src/state/internal.ts +45 -0
  91. package/src/test/runTest.ts +1 -1
  92. package/src/types/Adapter.ts +2 -4
  93. package/src/types/ClientState.ts +8 -0
  94. package/src/types/InternalState.ts +7 -0
  95. package/src/types/LayoutHandler.ts +2 -4
  96. package/src/types/LayoutPath.ts +10 -0
  97. package/src/types/ManifestRoute.ts +2 -4
  98. package/src/types/PageEndPoint.ts +2 -4
  99. package/src/types/PageLoadEvent.ts +2 -4
  100. package/src/types/PageServerEndPoint.ts +2 -4
  101. package/src/types/PageState.ts +8 -0
  102. package/src/types/RouteHandler.ts +2 -4
  103. package/src/types/RouteLayoutHandler.ts +2 -4
  104. package/src/types/RouteMatchResult.ts +2 -4
  105. package/src/types/ServerHook.ts +3 -7
  106. package/src/types/ServerLoadEvent.ts +2 -4
  107. package/src/{site → utils}/pathToRegex.ts +1 -1
  108. package/{tsup.config.ts → tsdown.config.ts} +3 -4
  109. package/dist/Server-CNZWh5ca.d.cts +0 -71
  110. package/dist/Server-CNZWh5ca.d.ts +0 -71
  111. package/dist/Site-C2020GV_.d.ts +0 -63
  112. package/dist/Site-DQojGpE-.d.cts +0 -63
  113. package/dist/bin/index.cjs +0 -778
  114. package/dist/bin/index.cjs.map +0 -1
  115. package/dist/bin/index.d.cts +0 -1
  116. package/dist/chunk-565UOT3F.js +0 -18
  117. package/dist/chunk-565UOT3F.js.map +0 -1
  118. package/dist/chunk-B2UNTYN5.js +0 -68
  119. package/dist/chunk-B2UNTYN5.js.map +0 -1
  120. package/dist/chunk-CZHJQCPI.js +0 -286
  121. package/dist/chunk-CZHJQCPI.js.map +0 -1
  122. package/dist/chunk-PTVHEJZ5.js +0 -152
  123. package/dist/chunk-PTVHEJZ5.js.map +0 -1
  124. package/dist/chunk-SJVHHGVW.js +0 -13
  125. package/dist/chunk-SJVHHGVW.js.map +0 -1
  126. package/dist/chunk-TDOXEXG6.js +0 -85
  127. package/dist/chunk-TDOXEXG6.js.map +0 -1
  128. package/dist/chunk-WVXAN4IV.js +0 -50
  129. package/dist/chunk-WVXAN4IV.js.map +0 -1
  130. package/dist/chunk-YRBEYKQM.js +0 -372
  131. package/dist/chunk-YRBEYKQM.js.map +0 -1
  132. package/dist/index.cjs +0 -322
  133. package/dist/index.cjs.map +0 -1
  134. package/dist/index.d.cts +0 -199
  135. package/dist/metafile-cjs.json +0 -1
  136. package/dist/metafile-esm.json +0 -1
  137. package/dist/response.cjs +0 -150
  138. package/dist/response.cjs.map +0 -1
  139. package/dist/response.d.cts +0 -166
  140. package/dist/response.js.map +0 -1
  141. package/dist/run.cjs +0 -787
  142. package/dist/run.cjs.map +0 -1
  143. package/dist/run.d.cts +0 -14
  144. package/dist/run.js.map +0 -1
  145. package/dist/server.cjs +0 -398
  146. package/dist/server.cjs.map +0 -1
  147. package/dist/server.d.cts +0 -17
  148. package/dist/server.js.map +0 -1
  149. package/dist/state.cjs +0 -44
  150. package/dist/state.cjs.map +0 -1
  151. package/dist/state.d.cts +0 -11
  152. package/dist/state.js.map +0 -1
  153. package/dist/test.cjs +0 -538
  154. package/dist/test.cjs.map +0 -1
  155. package/dist/test.d.cts +0 -15
  156. package/src/response/moved.ts +0 -16
  157. package/src/response/redirect.ts +0 -17
  158. package/src/state/Page.ts +0 -8
@@ -1,14 +1,13 @@
1
1
  import manifest from "@torpor/build/manifest";
2
- // @ts-ignore This errors in the Cloudflare build?
3
- import { $page } from "@torpor/build/state";
4
2
  import { type ServerComponent, type ServerSlotRender } from "@torpor/view";
5
3
  import notFound from "../response/notFound.ts";
6
4
  import ok from "../response/ok.ts";
7
5
  import seeOther from "../response/seeOther.ts";
8
6
  import ServerEvent from "../server/ServerEvent.ts";
7
+ import $page from "../state/$page";
9
8
  import type PageEndPoint from "../types/PageEndPoint.ts";
10
9
  import type PageServerEndPoint from "../types/PageServerEndPoint.ts";
11
- import RouteHandler from "../types/RouteHandler.ts";
10
+ import type RouteHandler from "../types/RouteHandler.ts";
12
11
  import {
13
12
  ERROR_ROUTE,
14
13
  HOOK_ROUTE,
@@ -30,35 +29,7 @@ router.addPages(manifest.routes);
30
29
 
31
30
  //console.log(`routes:\n ${router.routes.map((r) => r.path).join("\n ")}`);
32
31
 
33
- async function handleResponse(response: Response): Promise<Response> {
34
- $page.status = response.status;
35
-
36
- // Success codes and redirect codes are acceptable
37
- if (response.status >= 200 && response.status <= 399) {
38
- return response;
39
- }
40
-
41
- // It's an error, so redirect to the error page
42
- // We're just pushing the status and message in the URL, but maybe there's a
43
- // more sophisticated way to do this?
44
- // TODO: Should be returning loadView rather than redirecting
45
- // TODO: Should be returning the NEAREST error page to this path, including layouts
46
- let params = new URLSearchParams();
47
- params.append("status", $page.status.toString());
48
- let message = await response.text();
49
- if (response.headers.get("Content-Type")?.includes("application/json")) {
50
- const data = JSON.parse(message);
51
- message = data.message ?? message;
52
- }
53
- if (message) {
54
- $page.error.message = message;
55
- params.append("message", message);
56
- }
57
- return seeOther(`/_error?${params.toString()}`);
58
- }
59
-
60
32
  export async function load(ev: ServerEvent, template: string): Promise<Response> {
61
- //const url = new URL(`http://${process.env.HOST ?? "localhost"}${ev.request.url}`);
62
33
  const url = new URL(ev.request.url);
63
34
  const path = url.pathname;
64
35
  const query = url.searchParams;
@@ -69,19 +40,18 @@ export async function load(ev: ServerEvent, template: string): Promise<Response>
69
40
  if (!route) {
70
41
  return handleResponse(notFound());
71
42
  }
43
+ const handler = route.handler;
44
+ const params = route.params || {};
72
45
 
73
46
  // Update $page before building the components
74
47
  $page.url = url;
75
48
  if (path.endsWith("/_error")) {
76
49
  $page.status = parseInt(query.get("status") ?? "404");
77
- $page.error.message = query.get("message") ?? "";
50
+ $page.error = { message: query.get("message") ?? "" };
78
51
  } else {
79
52
  $page.status = 200;
80
53
  }
81
54
 
82
- const handler = route.handler;
83
- const params = route.params || {};
84
-
85
55
  // TODO: Hit the server hook out here
86
56
  // We could maybe set data loading up as middleware on a route??????
87
57
 
@@ -92,7 +62,7 @@ export async function load(ev: ServerEvent, template: string): Promise<Response>
92
62
  if (ev.request.method === "GET") {
93
63
  return handleResponse(await loadView(ev, url, handler, params, template));
94
64
  } else if (ev.request.method === "POST") {
95
- return handleResponse(await runAction(ev, url, handler, params, query));
65
+ return handleResponse(await runAction(ev, url, handler, params, query, template), true);
96
66
  }
97
67
  break;
98
68
  }
@@ -121,6 +91,42 @@ export async function load(ev: ServerEvent, template: string): Promise<Response>
121
91
  return notFound();
122
92
  }
123
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
+
124
130
  async function loadData(
125
131
  ev: ServerEvent,
126
132
  url: URL,
@@ -155,6 +161,8 @@ async function loadView(
155
161
  handler: RouteHandler,
156
162
  params: Record<string, string>,
157
163
  template: string,
164
+ formStatus?: number,
165
+ form?: Record<string, string>,
158
166
  ) {
159
167
  // There must be a client endpoint with a component
160
168
  const clientEndPoint: PageEndPoint | undefined = (await handler.endPoint()).default;
@@ -209,7 +217,7 @@ async function loadView(
209
217
  if (endPointResponse?.ok === false) {
210
218
  return endPointResponse;
211
219
  }
212
- let $props: Record<string, any> = { data };
220
+ let $props: Record<string, any> = { data, form };
213
221
 
214
222
  let styles = "";
215
223
 
@@ -217,7 +225,6 @@ async function loadView(
217
225
  // the default slot of its parent
218
226
  // TODO: Also handle layout server data
219
227
  // TODO: There's probably a nicer way to do this with reducers or something
220
- // TODO: Re-use parent layouts
221
228
  let component = clientEndPoint.component as ServerComponent;
222
229
  let slots: Record<string, ServerSlotRender> | undefined = undefined;
223
230
  if (handler.layouts) {
@@ -250,6 +257,12 @@ async function loadView(
250
257
  let html;
251
258
  try {
252
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
+
253
266
  styles += head;
254
267
  html = template.replace("%COMPONENT_BODY%", body).replace("%COMPONENT_HEAD%", styles);
255
268
  } catch (error) {
@@ -259,7 +272,7 @@ async function loadView(
259
272
  }
260
273
 
261
274
  return new Response(html, {
262
- status: 200,
275
+ status: formStatus ?? 200,
263
276
  headers: {
264
277
  "Content-Type": "text/html",
265
278
  },
@@ -272,6 +285,7 @@ async function runAction(
272
285
  handler: RouteHandler,
273
286
  params: Record<string, string>,
274
287
  query: URLSearchParams,
288
+ template: string,
275
289
  ) {
276
290
  const actionName = (Array.from(query.keys())[0] || "default").replace(/^\//, "");
277
291
  const serverEndPoint: PageServerEndPoint | undefined =
@@ -279,7 +293,6 @@ async function runAction(
279
293
  if (serverEndPoint?.actions) {
280
294
  const action = serverEndPoint.actions[actionName];
281
295
  if (action) {
282
- // TODO: form.errors etc
283
296
  const serverParams = buildServerParams(ev, url, params);
284
297
 
285
298
  if (handler.serverHook) {
@@ -289,14 +302,42 @@ async function runAction(
289
302
  }
290
303
  }
291
304
 
292
- const result = await action(serverParams);
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
+ }
293
320
 
294
- // Return the response if it was not ok (i.e. errors or a redirect)
295
- // Otherwise, reload the page by redirecting
296
- if (result && !result.ok) {
297
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
+ const form = await result?.json();
334
+ $page.form = form;
335
+ return await loadView(ev, newUrl, handler, params, template, formStatus, form);
298
336
  } else {
299
- return seeOther(url.pathname);
337
+ // If the form was submitted without javascript and there was a
338
+ // redirect or server error, just return the result to handle it
339
+ // as normal
340
+ return result;
300
341
  }
301
342
  }
302
343
  }
@@ -1,15 +1,6 @@
1
- import { $watch } from "@torpor/view";
2
- import Page from "./Page";
1
+ import type PageState from "../types/PageState";
2
+ import internal from "./internal";
3
3
 
4
- const $page: Page = $watch(
5
- {
6
- status: 404,
7
- url: new URL("http://localhost"),
8
- error: {
9
- message: "",
10
- },
11
- },
12
- { shallow: true },
13
- );
4
+ const $page: PageState = internal().$page;
14
5
 
15
6
  export default $page;
@@ -0,0 +1,6 @@
1
+ import type ClientState from "../types/ClientState";
2
+ import internal from "./internal";
3
+
4
+ const client: ClientState = internal().client;
5
+
6
+ export default client;
@@ -0,0 +1,45 @@
1
+ import { $watch } from "@torpor/view";
2
+ import type ClientState from "../types/ClientState";
3
+ import type InternalState from "../types/InternalState";
4
+ import type PageState from "../types/PageState";
5
+
6
+ // Do a weird little dance to ensure that everyone has the same $page and
7
+ // client, regardless of if they are entering via serverEntry/clientEntry or the
8
+ // built library. There may be an easier way to do this!
9
+
10
+ const INTERNAL_GLOBAL: unique symbol = Symbol.for("torpor-internal");
11
+
12
+ export default function internal(): InternalState {
13
+ // @ts-ignore
14
+ if (globalThis[INTERNAL_GLOBAL] === undefined) {
15
+ // TODO: Should use the SSR $watch if entering via serverEntry
16
+ const $page: PageState = $watch(
17
+ {
18
+ status: 404,
19
+ url: new URL("http://localhost"),
20
+ form: undefined,
21
+ error: {
22
+ message: "",
23
+ },
24
+ },
25
+ {
26
+ shallow: true,
27
+ },
28
+ );
29
+ const client: ClientState = {
30
+ // @ts-ignore This will definitely, 100% get set
31
+ router: null,
32
+ layoutStack: [],
33
+ // TODO: Probably expire after 30 seconds or something?
34
+ prefetchedData: {},
35
+ };
36
+
37
+ // @ts-ignore
38
+ globalThis[INTERNAL_GLOBAL] = {
39
+ $page,
40
+ client,
41
+ } satisfies InternalState;
42
+ }
43
+ // @ts-ignore
44
+ return globalThis[INTERNAL_GLOBAL] as InternalState;
45
+ }
@@ -9,7 +9,7 @@ import Site from "../site/Site";
9
9
  import $page from "../state/$page.ts";
10
10
  import type PageEndPoint from "../types/PageEndPoint.ts";
11
11
  import type PageServerEndPoint from "../types/PageServerEndPoint.ts";
12
- import RouteHandler from "../types/RouteHandler.ts";
12
+ import type RouteHandler from "../types/RouteHandler.ts";
13
13
  import {
14
14
  HOOK_ROUTE,
15
15
  HOOK_SERVER_ROUTE,
@@ -1,10 +1,8 @@
1
1
  import Server from "../server/Server";
2
2
  import Site from "../site/Site";
3
3
 
4
- type Adapter = {
4
+ export default interface Adapter {
5
5
  prebuild?: (site: Site) => Promise<void> | void;
6
6
  postbuild?: (site: Site) => Promise<void> | void;
7
7
  serve: (server: Server, site: Site) => void;
8
- };
9
-
10
- export default Adapter;
8
+ }
@@ -0,0 +1,8 @@
1
+ import Router from "../site/Router";
2
+ import type LayoutPath from "./LayoutPath";
3
+
4
+ export default interface ClientState {
5
+ router: Router;
6
+ layoutStack: LayoutPath[];
7
+ prefetchedData: Record<string, any>;
8
+ }
@@ -0,0 +1,7 @@
1
+ import type ClientState from "./ClientState";
2
+ import type PageState from "./PageState";
3
+
4
+ export default interface InternalState {
5
+ $page: PageState;
6
+ client: ClientState;
7
+ }
@@ -1,7 +1,5 @@
1
- type LayoutHandler = {
1
+ export default interface LayoutHandler {
2
2
  path: string;
3
3
  endPoint: () => Promise<any>;
4
4
  serverEndPoint?: () => Promise<any>;
5
- };
6
-
7
- export default LayoutHandler;
5
+ }
@@ -0,0 +1,10 @@
1
+ // Store the current layout stack, so that we can re-use parts of it as necessary
2
+ export default interface LayoutPath {
3
+ path: string;
4
+ /** Whether to re-use this layout */
5
+ reuse: boolean;
6
+ /** Data loaded from endpoints that should be re-used */
7
+ data: any;
8
+ /** The range of the UI in this layout's slot */
9
+ slotRange: any;
10
+ }
@@ -1,7 +1,5 @@
1
- type ManifestRoute = {
1
+ export default interface ManifestRoute {
2
2
  path: string;
3
3
  type: number;
4
4
  endPoint: () => Promise<any>;
5
- };
6
-
7
- export default ManifestRoute;
5
+ }
@@ -4,7 +4,7 @@ import type PageLoadEvent from "./PageLoadEvent";
4
4
  /**
5
5
  * For +page.
6
6
  */
7
- type PageEndPoint = {
7
+ export default interface PageEndPoint {
8
8
  /**
9
9
  * Builds the route path for the page in a type-safe manner.
10
10
  * TODO: Not sure this is actually the best way to do it...
@@ -25,9 +25,7 @@ type PageEndPoint = {
25
25
  * The head element data for the page, which may include a <title> and <meta> elements.
26
26
  */
27
27
  head?: HeadElement[] | ((event: PageLoadEvent) => HeadElement[]);
28
- };
29
-
30
- export default PageEndPoint;
28
+ }
31
29
 
32
30
  type HeadElement = TitleElement | MetaElement;
33
31
 
@@ -1,4 +1,4 @@
1
- type PageLoadEvent = {
1
+ export default interface PageLoadEvent {
2
2
  /**
3
3
  * The URL for the server function.
4
4
  */
@@ -11,6 +11,4 @@ type PageLoadEvent = {
11
11
  * Data that is (optionally) loaded from the load function and passed into the page as $props.data.
12
12
  */
13
13
  data: Record<string, any>;
14
- };
15
-
16
- export default PageLoadEvent;
14
+ }
@@ -4,7 +4,7 @@ import type PageServerLoad from "./PageServerLoad";
4
4
  /**
5
5
  * For +page.server.
6
6
  */
7
- type PageServerEndPoint = {
7
+ export default interface PageServerEndPoint {
8
8
  /**
9
9
  * Loads data from the server for a page.
10
10
  */
@@ -13,6 +13,4 @@ type PageServerEndPoint = {
13
13
  * A map of actions that can be performed on the server for a page, generally from a form submit.
14
14
  */
15
15
  actions?: Record<string, PageServerAction>;
16
- };
17
-
18
- export default PageServerEndPoint;
16
+ }
@@ -0,0 +1,8 @@
1
+ export default interface PageState {
2
+ status: number;
3
+ url: URL;
4
+ form?: Record<string, string>;
5
+ error?: {
6
+ message: string;
7
+ };
8
+ }
@@ -1,6 +1,6 @@
1
1
  import type RouteLayoutHandler from "./RouteLayoutHandler";
2
2
 
3
- type RouteHandler = {
3
+ export default interface RouteHandler {
4
4
  path: string;
5
5
  type: number;
6
6
  endPoint: () => Promise<any>;
@@ -9,6 +9,4 @@ type RouteHandler = {
9
9
  layouts?: RouteLayoutHandler[];
10
10
  serverEndPoint?: () => Promise<any>;
11
11
  serverHook?: () => Promise<any>;
12
- };
13
-
14
- export default RouteHandler;
12
+ }
@@ -1,7 +1,5 @@
1
- type RouteLayoutHandler = {
1
+ export default interface RouteLayoutHandler {
2
2
  path: string;
3
3
  endPoint: () => Promise<any>;
4
4
  serverEndPoint?: () => Promise<any>;
5
- };
6
-
7
- export default RouteLayoutHandler;
5
+ }
@@ -1,9 +1,7 @@
1
1
  import type RouteHandler from "./RouteHandler";
2
2
 
3
- type RouteMatchResult = {
3
+ export default interface RouteMatchResult {
4
4
  handler: RouteHandler;
5
5
  params?: Record<string, string>;
6
6
  query?: Record<string, string>;
7
- };
8
-
9
- export default RouteMatchResult;
7
+ }
@@ -3,13 +3,9 @@ import type ServerLoadEvent from "./ServerLoadEvent";
3
3
  /**
4
4
  * For _hook.server.
5
5
  */
6
- type ServerHook = {
6
+ export default interface ServerHook {
7
7
  /**
8
8
  * Called on each server request.
9
9
  */
10
- handle?: ServerLoad;
11
- };
12
-
13
- export default ServerHook;
14
-
15
- type ServerLoad = (event: ServerLoadEvent) => Promise<void> | void;
10
+ handle?: (event: ServerLoadEvent) => Promise<void> | void;
11
+ }
@@ -1,7 +1,7 @@
1
1
  import CookieHelper from "../server/CookieHelper";
2
2
  import HeaderHelper from "../server/HeaderHelper";
3
3
 
4
- type ServerLoadEvent = {
4
+ export default interface ServerLoadEvent {
5
5
  /**
6
6
  * The URL for the server function.
7
7
  */
@@ -34,6 +34,4 @@ type ServerLoadEvent = {
34
34
  * An optional adapter object, containing adapter-specific functionality.
35
35
  */
36
36
  adapter: Record<PropertyKey, any>;
37
- };
38
-
39
- export default ServerLoadEvent;
37
+ }
@@ -4,7 +4,7 @@ export default function pathToRegex(path: string): RegExp {
4
4
  .split("/")
5
5
  // Replace `[slug]` with a grouped match so we can pull out params
6
6
  .map((p) => {
7
- return p.replace(/\[([^\/]+?)\]/, "(?<$1>[^\\/]+?)");
7
+ return p.replace(/\[([^/]+?)\]/, "(?<$1>[^\\/]+?)");
8
8
  })
9
9
  .join("\\/")
10
10
  // Replace globs with regex syntax
@@ -1,4 +1,4 @@
1
- import { type Options, defineConfig } from "tsup";
1
+ import { type Options, defineConfig } from "tsdown";
2
2
 
3
3
  type Config =
4
4
  | Options
@@ -8,6 +8,7 @@ type Config =
8
8
  export default defineConfig({
9
9
  entry: [
10
10
  "src/index.ts",
11
+ "src/nav.ts",
11
12
  "src/response.ts",
12
13
  "src/run.ts",
13
14
  "src/server.ts",
@@ -15,10 +16,8 @@ export default defineConfig({
15
16
  "src/test.ts",
16
17
  "src/bin/index.ts",
17
18
  ],
18
- format: ["esm", "cjs"],
19
+ format: "esm",
19
20
  dts: true,
20
- clean: true,
21
- metafile: true,
22
21
  sourcemap: true,
23
22
  // Put this in here to stop issues with bundling Vite from bin/index.ts
24
23
  // I'm not sure if this will cause further issues down the line?
@@ -1,71 +0,0 @@
1
- import { SerializeOptions } from 'cookie';
2
-
3
- declare class CookieHelper {
4
- request: Request;
5
- cookies: Map<string, string>;
6
- constructor(request: Request);
7
- get(name: string): string | undefined;
8
- set(name: string, value: string, options?: SerializeOptions): void;
9
- delete(name: string, options?: SerializeOptions): void;
10
- }
11
-
12
- declare class HeaderHelper {
13
- request: Request;
14
- headers: Map<string, string>;
15
- constructor(request: Request);
16
- get(name: string): string | undefined;
17
- set(name: string, value: string): void;
18
- delete(name: string): void;
19
- }
20
-
21
- declare class ServerEvent {
22
- request: Request;
23
- response: Response | undefined | void;
24
- params?: Record<string, string>;
25
- adapter: any;
26
- cookies: CookieHelper;
27
- headers: HeaderHelper;
28
- constructor(request: Request, params?: Record<string, string>);
29
- addHeaders(): void;
30
- }
31
-
32
- type MiddlewareFunction = (ev: ServerEvent, next: () => void | Promise<void>) => void | Promise<void>;
33
-
34
- type ServerFunction = (e: ServerEvent) => Response | undefined | void | Promise<Response | undefined | void>;
35
-
36
- /**
37
- * A Fetch API Request/Response server.
38
- */
39
- declare class Server {
40
- #private;
41
- routes: RouteHandler[];
42
- middleware: MiddlewareFunction[];
43
- constructor();
44
- /**
45
- * The standard Fetch API method that should work in any runtime (including
46
- * Node with polyfills).
47
- * @returns
48
- */
49
- fetch: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
50
- /**
51
- * Adds a server function at a route path.
52
- * @param path The route path pattern.
53
- * @param fn The function to call when the pattern is matched.
54
- * @returns
55
- */
56
- add(path: string, fn: ServerFunction): Server;
57
- match(path: string): Match | undefined;
58
- use(...fn: MiddlewareFunction[]): Server;
59
- }
60
- declare class RouteHandler {
61
- path: string;
62
- regex: RegExp;
63
- fn: ServerFunction;
64
- constructor(path: string, fn: ServerFunction);
65
- }
66
- type Match = {
67
- fn: ServerFunction;
68
- params?: Record<string, string>;
69
- };
70
-
71
- export { CookieHelper as C, HeaderHelper as H, type MiddlewareFunction as M, Server as S, ServerEvent as a };