@torpor/build 0.4.13 → 1.0.0

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 (176) hide show
  1. package/README.md +20 -2
  2. package/dist/Jsonify-Dg6gChd3.d.mts +10 -0
  3. package/dist/Jsonify-Dg6gChd3.d.mts.map +1 -0
  4. package/dist/ParseRouteParams-DBmqlmLh.d.mts +42 -0
  5. package/dist/ParseRouteParams-DBmqlmLh.d.mts.map +1 -0
  6. package/dist/{RouteType-B6BMOyYw.mjs → Router-C4ADUfhv.mjs} +30 -42
  7. package/dist/Router-C4ADUfhv.mjs.map +1 -0
  8. package/dist/{Server-CF5wDJp6.d.mts → Server-C_IKav_e.d.mts} +44 -16
  9. package/dist/Server-C_IKav_e.d.mts.map +1 -0
  10. package/dist/{ServerEvent-CxPwA4lH.mjs → ServerEvent-Dljn5i7A.mjs} +37 -11
  11. package/dist/ServerEvent-Dljn5i7A.mjs.map +1 -0
  12. package/dist/Site-CMa153FA.d.mts +565 -0
  13. package/dist/Site-CMa153FA.d.mts.map +1 -0
  14. package/dist/StandardSchema-D28L8_zZ.d.mts +100 -0
  15. package/dist/StandardSchema-D28L8_zZ.d.mts.map +1 -0
  16. package/dist/TypedResponse-6lznqN4U.d.mts +22 -0
  17. package/dist/TypedResponse-6lznqN4U.d.mts.map +1 -0
  18. package/dist/{_page-BQs4WvCO.mjs → _page-4cQKs_Dn.mjs} +3 -5
  19. package/dist/_page-4cQKs_Dn.mjs.map +1 -0
  20. package/dist/bin/index.d.mts +1 -1
  21. package/dist/bin/index.js +15 -11
  22. package/dist/bin/index.js.map +1 -1
  23. package/dist/flattenHeaders-C_YYLdOq.mjs +114 -0
  24. package/dist/flattenHeaders-C_YYLdOq.mjs.map +1 -0
  25. package/dist/form.d.mts +35 -0
  26. package/dist/form.d.mts.map +1 -0
  27. package/dist/form.mjs +48 -0
  28. package/dist/form.mjs.map +1 -0
  29. package/dist/index.d.mts +72 -156
  30. package/dist/index.d.mts.map +1 -1
  31. package/dist/index.mjs +164 -32
  32. package/dist/index.mjs.map +1 -1
  33. package/dist/nav.d.mts +58 -5
  34. package/dist/nav.d.mts.map +1 -1
  35. package/dist/nav.mjs +116 -38
  36. package/dist/nav.mjs.map +1 -1
  37. package/dist/openapi.d.mts +144 -0
  38. package/dist/openapi.d.mts.map +1 -0
  39. package/dist/openapi.mjs +2 -0
  40. package/dist/pathTrie-D4Ax2Mu9.mjs +160 -0
  41. package/dist/pathTrie-D4Ax2Mu9.mjs.map +1 -0
  42. package/dist/plugin-D8Www11B.mjs +202 -0
  43. package/dist/plugin-D8Www11B.mjs.map +1 -0
  44. package/dist/{response-C5TtAsh1.mjs → response-Bg4w2S1q.mjs} +16 -39
  45. package/dist/response-Bg4w2S1q.mjs.map +1 -0
  46. package/dist/response.d.mts +309 -289
  47. package/dist/response.d.mts.map +1 -1
  48. package/dist/response.mjs +3 -4
  49. package/dist/run.d.mts +11 -4
  50. package/dist/run.d.mts.map +1 -1
  51. package/dist/run.mjs +2 -8
  52. package/dist/runOpenApi-BUi1RH1l.mjs +1381 -0
  53. package/dist/runOpenApi-BUi1RH1l.mjs.map +1 -0
  54. package/dist/schema.d.mts +32 -0
  55. package/dist/schema.d.mts.map +1 -0
  56. package/dist/schema.mjs +2 -0
  57. package/dist/server.d.mts +10 -8
  58. package/dist/server.d.mts.map +1 -1
  59. package/dist/server.mjs +132 -4
  60. package/dist/server.mjs.map +1 -0
  61. package/dist/state.d.mts.map +1 -1
  62. package/dist/state.mjs +2 -3
  63. package/dist/test.d.mts +8 -10
  64. package/dist/test.d.mts.map +1 -1
  65. package/dist/test.mjs +286 -82
  66. package/dist/test.mjs.map +1 -1
  67. package/dist/{seeOther-B4Yhu9iq.mjs → unprocessable-DAZbrDeR.mjs} +34 -13
  68. package/dist/unprocessable-DAZbrDeR.mjs.map +1 -0
  69. package/dist/validate-Ok4krlkX.mjs +40 -0
  70. package/dist/validate-Ok4krlkX.mjs.map +1 -0
  71. package/package.json +28 -17
  72. package/src/bin/index.ts +13 -2
  73. package/src/dev.ts +10 -0
  74. package/src/form/formDataToRecord.ts +23 -0
  75. package/src/form/readForm.ts +71 -0
  76. package/src/form.ts +4 -0
  77. package/src/index.ts +53 -1
  78. package/src/nav/api.test-d.ts +79 -0
  79. package/src/nav/api.ts +104 -0
  80. package/src/nav/formSubmit.ts +18 -4
  81. package/src/nav/navigate.ts +40 -15
  82. package/src/nav/route.ts +38 -0
  83. package/src/nav.ts +3 -1
  84. package/src/openapi/docsHtml.ts +25 -0
  85. package/src/openapi/document.ts +154 -0
  86. package/src/openapi/plugin.ts +78 -0
  87. package/src/openapi/types.ts +82 -0
  88. package/src/openapi.ts +14 -0
  89. package/src/response/TypedResponse.ts +17 -0
  90. package/src/response/badRequest.ts +14 -2
  91. package/src/response/created.ts +13 -2
  92. package/src/response/found.ts +2 -2
  93. package/src/response/movedPermanently.ts +2 -2
  94. package/src/response/notModified.ts +2 -2
  95. package/src/response/ok.ts +13 -4
  96. package/src/response/response.ts +4 -4
  97. package/src/response/unprocessable.ts +14 -2
  98. package/src/run/depCache.ts +175 -0
  99. package/src/run/devPlugin.ts +128 -0
  100. package/src/run/prepareTemplate.ts +6 -3
  101. package/src/run/run.ts +63 -39
  102. package/src/run/runBuild.ts +63 -12
  103. package/src/run/runDev.ts +146 -58
  104. package/src/run/runOpenApi.ts +52 -0
  105. package/src/run/runPreview.ts +17 -26
  106. package/src/run/staleTorpCopies.ts +100 -0
  107. package/src/run.ts +2 -1
  108. package/src/schema.ts +7 -0
  109. package/src/server/CookieHelper.ts +17 -7
  110. package/src/server/Server.ts +54 -30
  111. package/src/server/ServerEvent.ts +24 -1
  112. package/src/server/connect/connectMiddleware.ts +44 -40
  113. package/src/server/connect/flattenHeaders.ts +1 -23
  114. package/src/server/connect/requestToNodeMessage.ts +6 -3
  115. package/src/server/types/MiddlewareFunction.ts +18 -4
  116. package/src/site/Router.ts +52 -41
  117. package/src/site/Site.ts +184 -10
  118. package/src/site/checkLayoutSlots.ts +114 -0
  119. package/src/site/checkRoutes.ts +435 -0
  120. package/src/site/clientEntry.ts +22 -9
  121. package/src/site/layoutSlots.ts +53 -0
  122. package/src/site/manifest.ts +125 -6
  123. package/src/site/serverEntry.ts +352 -133
  124. package/src/state/$page.ts +2 -1
  125. package/src/state/$serverPage.ts +22 -0
  126. package/src/test/runTest.ts +306 -118
  127. package/src/types/Adapter.ts +12 -0
  128. package/src/types/Jsonify.ts +20 -0
  129. package/src/types/PageData.test-d.ts +136 -0
  130. package/src/types/PageData.ts +35 -0
  131. package/src/types/PageEndPoint.ts +25 -9
  132. package/src/types/PageForm.test-d.ts +78 -0
  133. package/src/types/PageForm.ts +29 -0
  134. package/src/types/PageLoadEvent.ts +16 -4
  135. package/src/types/PageLoadReturn.ts +13 -0
  136. package/src/types/PageProps.ts +14 -0
  137. package/src/types/PageServerAction.ts +8 -2
  138. package/src/types/PageServerEndPoint.test-d.ts +105 -0
  139. package/src/types/PageServerEndPoint.ts +99 -5
  140. package/src/types/PageServerLoad.ts +11 -3
  141. package/src/types/ParseRouteParams.test-d.ts +84 -0
  142. package/src/types/ParseRouteParams.ts +64 -0
  143. package/src/types/Route.ts +20 -1
  144. package/src/types/RouteHandler.ts +8 -1
  145. package/src/types/ServerEndPoint.test-d.ts +77 -0
  146. package/src/types/ServerEndPoint.ts +148 -16
  147. package/src/types/ServerHook.ts +10 -3
  148. package/src/types/ServerLoadEvent.ts +48 -3
  149. package/src/types/ServerRequest.ts +10 -2
  150. package/src/types/SitePlugin.ts +24 -0
  151. package/src/types/StandardSchema.ts +109 -0
  152. package/src/utils/pathToRegex.ts +4 -2
  153. package/src/utils/pathTrie.ts +182 -0
  154. package/src/utils/searchParamsToRecord.ts +18 -0
  155. package/src/utils/torporPackages.ts +150 -0
  156. package/src/utils/tsconfigAliases.ts +90 -0
  157. package/src/validation/ValidationError.ts +18 -0
  158. package/src/validation/endpoint.ts +83 -0
  159. package/src/validation/validate.ts +26 -0
  160. package/dist/RouteType-B6BMOyYw.mjs.map +0 -1
  161. package/dist/Server-CF5wDJp6.d.mts.map +0 -1
  162. package/dist/ServerEvent-CxPwA4lH.mjs.map +0 -1
  163. package/dist/Site-DgC6WWn1.d.mts +0 -78
  164. package/dist/Site-DgC6WWn1.d.mts.map +0 -1
  165. package/dist/_page-BQs4WvCO.mjs.map +0 -1
  166. package/dist/connectMiddleware-D7nehjj3.mjs +0 -252
  167. package/dist/connectMiddleware-D7nehjj3.mjs.map +0 -1
  168. package/dist/pathToRegex-TUAMc3zS.mjs +0 -11
  169. package/dist/pathToRegex-TUAMc3zS.mjs.map +0 -1
  170. package/dist/response-C5TtAsh1.mjs.map +0 -1
  171. package/dist/run-DiZgkMnG.mjs +0 -332
  172. package/dist/run-DiZgkMnG.mjs.map +0 -1
  173. package/dist/seeOther-B4Yhu9iq.mjs.map +0 -1
  174. package/src/server/Routerx.ts +0 -72
  175. package/src/server/connect/bufferToArrayBuffer.ts +0 -8
  176. package/src/server/connect/readableToBuffer.ts +0 -16
@@ -0,0 +1,22 @@
1
+ //#region src/response/TypedResponse.d.ts
2
+ /**
3
+ * A Response whose JSON body type is known, as returned by e.g. `ok({ ... })`.
4
+ * Purely a compile-time marker: `__body` is never set at runtime.
5
+ */
6
+ interface TypedResponse<T> extends Response {
7
+ /**
8
+ * Phantom property carrying the body type. Required so that plain
9
+ * `Response` values do not match `TypedResponse<infer T>`.
10
+ */
11
+ readonly __body: T;
12
+ }
13
+ /**
14
+ * A Response that does not carry typed JSON data (e.g. redirects, errors,
15
+ * plain-text bodies). Loads may return these alongside typed data responses.
16
+ */
17
+ type UntypedResponse = Response & {
18
+ readonly __body?: never;
19
+ };
20
+ //#endregion
21
+ export { UntypedResponse as n, TypedResponse as t };
22
+ //# sourceMappingURL=TypedResponse-6lznqN4U.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TypedResponse-6lznqN4U.d.mts","names":[],"sources":["../src/response/TypedResponse.ts"],"mappings":";;;;;UAIyB,cAAc,WAAW;;;;;WAKxC,QAAQ;;;;;;KAON,kBAAkB;WAAsB"}
@@ -1,5 +1,4 @@
1
1
  import { $watch } from "@torpor/view";
2
-
3
2
  //#region src/state/$page.ts
4
3
  const PAGE_SYMBOL = Symbol.for("torp.Page");
5
4
  const $page = globalThis[PAGE_SYMBOL] ??= $watch({
@@ -8,8 +7,7 @@ const $page = globalThis[PAGE_SYMBOL] ??= $watch({
8
7
  form: void 0,
9
8
  error: { message: "" }
10
9
  }, { shallow: true });
11
- var $page_default = $page;
12
-
13
10
  //#endregion
14
- export { $page_default as t };
15
- //# sourceMappingURL=_page-BQs4WvCO.mjs.map
11
+ export { $page as t };
12
+
13
+ //# sourceMappingURL=_page-4cQKs_Dn.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_page-4cQKs_Dn.mjs","names":[],"sources":["../src/state/$page.ts"],"sourcesContent":["import { $watch } from \"@torpor/view\";\nimport type PageState from \"../types/PageState\";\n\nconst PAGE_SYMBOL: unique symbol = Symbol.for(\"torp.Page\");\n\nconst $page: PageState =\n\t// @ts-ignore\n\t(globalThis[PAGE_SYMBOL] ??=\n\t\t// The server request path uses `state/$serverPage`, which stores the\n\t\t// same state (same `globalThis` slot) without a reactive proxy\n\t\t$watch(\n\t\t\t{\n\t\t\t\tstatus: 404,\n\t\t\t\turl: new URL(\"http://localhost\"),\n\t\t\t\tform: undefined,\n\t\t\t\terror: {\n\t\t\t\t\tmessage: \"\",\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tshallow: true,\n\t\t\t},\n\t\t));\n\nexport default $page;\n"],"mappings":";;AAGA,MAAM,cAA6B,OAAO,IAAI,WAAW;AAEzD,MAAM,QAEJ,WAAW,iBAGX,OACC;CACC,QAAQ;CACR,KAAK,IAAI,IAAI,kBAAkB;CAC/B,MAAM,KAAA;CACN,OAAO,EACN,SAAS,GACV;AACD,GACA,EACC,SAAS,KACV,CACD"}
@@ -1 +1 @@
1
- export { };
1
+ export {}
package/dist/bin/index.js CHANGED
@@ -1,17 +1,21 @@
1
1
  #! /usr/bin/env node
2
- import "../pathToRegex-TUAMc3zS.mjs";
3
- import "../seeOther-B4Yhu9iq.mjs";
4
- import "../response-C5TtAsh1.mjs";
5
- import { t as run } from "../run-DiZgkMnG.mjs";
6
- import "../ServerEvent-CxPwA4lH.mjs";
7
- import "../connectMiddleware-D7nehjj3.mjs";
8
-
2
+ import { n as loadSite, r as run, t as runOpenApi } from "../runOpenApi-BUi1RH1l.mjs";
9
3
  //#region src/bin/index.ts
10
4
  const workingDir = process.cwd();
11
- if (process.argv.includes("--dev")) await run(workingDir, "dev");
5
+ if (process.argv.includes("--openapi")) {
6
+ const flagIndex = process.argv.indexOf("--openapi");
7
+ const next = process.argv[flagIndex + 1];
8
+ const outFile = next && !next.startsWith("-") ? next : "openapi.json";
9
+ const { site, vite } = await loadSite(workingDir);
10
+ try {
11
+ await runOpenApi(site, vite, outFile);
12
+ } finally {
13
+ await vite.close();
14
+ }
15
+ } else if (process.argv.includes("--dev")) await run(workingDir, "dev");
12
16
  else if (process.argv.includes("--build")) await run(workingDir, "build");
13
17
  else if (process.argv.includes("--preview")) await run(workingDir, "preview");
14
-
15
18
  //#endregion
16
- export { };
17
- //# sourceMappingURL=index.mjs.map
19
+ export {};
20
+
21
+ //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/bin/index.ts"],"sourcesContent":["#! /usr/bin/env node\nimport run from \"../run/run\";\n\nconst workingDir = process.cwd();\nif (process.argv.includes(\"--dev\")) {\n\tawait run(workingDir, \"dev\");\n} else if (process.argv.includes(\"--build\")) {\n\tawait run(workingDir, \"build\");\n} else if (process.argv.includes(\"--preview\")) {\n\tawait run(workingDir, \"preview\");\n}\n"],"mappings":";;;;;;;;;AAGA,MAAM,aAAa,QAAQ,KAAK;AAChC,IAAI,QAAQ,KAAK,SAAS,QAAQ,CACjC,OAAM,IAAI,YAAY,MAAM;SAClB,QAAQ,KAAK,SAAS,UAAU,CAC1C,OAAM,IAAI,YAAY,QAAQ;SACpB,QAAQ,KAAK,SAAS,YAAY,CAC5C,OAAM,IAAI,YAAY,UAAU"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/bin/index.ts"],"sourcesContent":["#! /usr/bin/env node\nimport run, { loadSite } from \"../run/run\";\nimport runOpenApi from \"../run/runOpenApi\";\n\nconst workingDir = process.cwd();\nif (process.argv.includes(\"--openapi\")) {\n\tconst flagIndex = process.argv.indexOf(\"--openapi\");\n\tconst next = process.argv[flagIndex + 1];\n\tconst outFile = next && !next.startsWith(\"-\") ? next : \"openapi.json\";\n\tconst { site, vite } = await loadSite(workingDir);\n\ttry {\n\t\tawait runOpenApi(site, vite, outFile);\n\t} finally {\n\t\tawait vite.close();\n\t}\n} else if (process.argv.includes(\"--dev\")) {\n\tawait run(workingDir, \"dev\");\n} else if (process.argv.includes(\"--build\")) {\n\tawait run(workingDir, \"build\");\n} else if (process.argv.includes(\"--preview\")) {\n\tawait run(workingDir, \"preview\");\n}\n"],"mappings":";;;AAIA,MAAM,aAAa,QAAQ,IAAI;AAC/B,IAAI,QAAQ,KAAK,SAAS,WAAW,GAAG;CACvC,MAAM,YAAY,QAAQ,KAAK,QAAQ,WAAW;CAClD,MAAM,OAAO,QAAQ,KAAK,YAAY;CACtC,MAAM,UAAU,QAAQ,CAAC,KAAK,WAAW,GAAG,IAAI,OAAO;CACvD,MAAM,EAAE,MAAM,SAAS,MAAM,SAAS,UAAU;CAChD,IAAI;EACH,MAAM,WAAW,MAAM,MAAM,OAAO;CACrC,UAAU;EACT,MAAM,KAAK,MAAM;CAClB;AACD,OAAO,IAAI,QAAQ,KAAK,SAAS,OAAO,GACvC,MAAM,IAAI,YAAY,KAAK;KACrB,IAAI,QAAQ,KAAK,SAAS,SAAS,GACzC,MAAM,IAAI,YAAY,OAAO;KACvB,IAAI,QAAQ,KAAK,SAAS,WAAW,GAC3C,MAAM,IAAI,YAAY,SAAS"}
@@ -0,0 +1,114 @@
1
+ import { t as PathTrie } from "./pathTrie-D4Ax2Mu9.mjs";
2
+ import { t as ServerEvent } from "./ServerEvent-Dljn5i7A.mjs";
3
+ //#region src/server/Server.ts
4
+ /**
5
+ * A Fetch API Request/Response server.
6
+ */
7
+ var Server = class {
8
+ routes = [];
9
+ #trie = new PathTrie();
10
+ middleware = [];
11
+ constructor() {
12
+ this.routes = [];
13
+ this.middleware = [];
14
+ }
15
+ /**
16
+ * The standard Fetch API method that should work in any runtime (including
17
+ * Node with polyfills).
18
+ * @returns
19
+ */
20
+ fetch = async (input, init) => {
21
+ const request = input instanceof Request && !init ? input : new Request(input, init);
22
+ const url = new URL(request.url);
23
+ const match = this.match(url.pathname);
24
+ let ev = new ServerEvent(request, match?.params, url);
25
+ if (this.middleware.length) {
26
+ let entered = 0;
27
+ let response = void 0;
28
+ let error = void 0;
29
+ try {
30
+ for (; entered < this.middleware.length && !response; entered++) {
31
+ const result = await this.middleware[entered].enter?.(ev);
32
+ if (result) response = result;
33
+ }
34
+ if (!response && match) {
35
+ const result = await match.fn(ev);
36
+ if (result) response = result;
37
+ }
38
+ } catch (e) {
39
+ error = e;
40
+ ev.error = e;
41
+ } finally {
42
+ if (response) ev.response = response;
43
+ while (entered > 0) {
44
+ entered--;
45
+ const result = await this.middleware[entered].exit?.(ev);
46
+ if (result) {
47
+ response = result;
48
+ ev.response = result;
49
+ }
50
+ }
51
+ }
52
+ if (error && !response) throw error;
53
+ } else if (match) ev.response = await match.fn(ev);
54
+ else return new Response(null, { status: 404 });
55
+ ev.response ??= new Response(null, { status: 200 });
56
+ ev.addHeaders();
57
+ return ev.response;
58
+ };
59
+ /**
60
+ * Adds a server function at a route path.
61
+ * @param path The route path pattern.
62
+ * @param fn The function to call when the pattern is matched.
63
+ * @returns
64
+ */
65
+ add(path, fn) {
66
+ let handler = new RouteHandler(path, fn);
67
+ this.routes.push(handler);
68
+ this.#trie.insert(path, handler);
69
+ this.#sortRoutes();
70
+ return this;
71
+ }
72
+ match(path) {
73
+ const found = this.#trie.match(path);
74
+ if (found) return {
75
+ fn: found.value.fn,
76
+ params: found.params
77
+ };
78
+ console.log(`Server path not found: ${path}`);
79
+ }
80
+ use(...fn) {
81
+ this.middleware = this.middleware.concat(fn);
82
+ return this;
83
+ }
84
+ #sortRoutes() {
85
+ this.routes = this.routes.sort((a, b) => {
86
+ for (let i = 0; i < Math.min(a.path.length, b.path.length); i++) if (a.path[i] === "[" && b.path[i] !== "[") return 1;
87
+ else if (b.path[i] === "[" && a.path[i] !== "[") return -1;
88
+ else if (a.path[i] === b.path[i]) {} else return a.path[i].localeCompare(b.path[i]);
89
+ return a.path.length - b.path.length;
90
+ });
91
+ }
92
+ };
93
+ var RouteHandler = class {
94
+ path;
95
+ fn;
96
+ constructor(path, fn) {
97
+ this.path = path;
98
+ this.fn = fn;
99
+ }
100
+ };
101
+ //#endregion
102
+ //#region src/server/connect/flattenHeaders.ts
103
+ function flattenHeaders(headers) {
104
+ const flatHeaders = new Headers();
105
+ for (const [key, value] of Object.entries(headers)) if (value === void 0 || value === null) continue;
106
+ else if (Array.isArray(value)) {
107
+ for (const v of value) if (v !== void 0 && v !== null) flatHeaders.append(key, String(v));
108
+ } else flatHeaders.set(key, String(value));
109
+ return flatHeaders;
110
+ }
111
+ //#endregion
112
+ export { Server as n, flattenHeaders as t };
113
+
114
+ //# sourceMappingURL=flattenHeaders-C_YYLdOq.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flattenHeaders-C_YYLdOq.mjs","names":["#trie","#sortRoutes"],"sources":["../src/server/Server.ts","../src/server/connect/flattenHeaders.ts"],"sourcesContent":["import PathTrie from \"../utils/pathTrie\";\nimport ServerEvent from \"./ServerEvent\";\nimport type MiddlewareFunction from \"./types/MiddlewareFunction\";\nimport type ServerFunction from \"./types/ServerFunction\";\n\n/**\n * A Fetch API Request/Response server.\n */\nexport default class Server {\n\t// TODO: We don't use any of the routes, just add(\"*\") in runDev/runBuild...\n\troutes: RouteHandler[] = [];\n\t// Match index for the routes above\n\t#trie = new PathTrie<RouteHandler>();\n\t// TODO: We only use the Vite middleware here\n\tmiddleware: MiddlewareFunction[] = [];\n\n\tconstructor() {\n\t\tthis.routes = [];\n\t\tthis.middleware = [];\n\t}\n\n\t/**\n\t * The standard Fetch API method that should work in any runtime (including\n\t * Node with polyfills).\n\t * @returns\n\t */\n\tfetch = async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n\t\t// Use the request as-is when we were given one, so that the adapter\n\t\t// doesn't pay for constructing it twice\n\t\tconst request = input instanceof Request && !init ? input : new Request(input, init);\n\t\tconst url = new URL(request.url);\n\t\tconst match = this.match(url.pathname);\n\t\tlet ev = new ServerEvent(request, match?.params, url);\n\n\t\tif (this.middleware.length) {\n\t\t\t// TODO: Get middleware that applies to this route only?\n\t\t\tlet entered = 0;\n\t\t\tlet response: Response | undefined = undefined;\n\t\t\tlet error: unknown = undefined;\n\t\t\ttry {\n\t\t\t\tfor (; entered < this.middleware.length && !response; entered++) {\n\t\t\t\t\t// A middleware returns a Response to short-circuit the request\n\t\t\t\t\tconst result = await this.middleware[entered].enter?.(ev);\n\t\t\t\t\tif (result) {\n\t\t\t\t\t\tresponse = result;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!response && match) {\n\t\t\t\t\tconst result = await match.fn(ev);\n\t\t\t\t\tif (result) {\n\t\t\t\t\t\tresponse = result;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\t// Exits can handle the error by returning a Response; if none\n\t\t\t\t// does, it is rethrown below\n\t\t\t\terror = e;\n\t\t\t\tev.error = e;\n\t\t\t} finally {\n\t\t\t\tif (response) {\n\t\t\t\t\tev.response = response;\n\t\t\t\t}\n\t\t\t\t// Run exit hooks in reverse order for the middleware that were\n\t\t\t\t// entered. An exit hook can return a Response to replace the\n\t\t\t\t// response, or to handle ev.error\n\t\t\t\twhile (entered > 0) {\n\t\t\t\t\tentered--;\n\t\t\t\t\tconst result = await this.middleware[entered].exit?.(ev);\n\t\t\t\t\tif (result) {\n\t\t\t\t\t\tresponse = result;\n\t\t\t\t\t\tev.response = result;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (error && !response) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t} else if (match) {\n\t\t\tev.response = await match.fn(ev);\n\t\t} else {\n\t\t\treturn new Response(null, { status: 404 });\n\t\t}\n\n\t\t// TODO: Should I be returning 200 if there's no response? Because it's not an error??\n\t\tev.response ??= new Response(null, { status: 200 });\n\t\tev.addHeaders();\n\n\t\treturn ev.response;\n\t};\n\n\t/**\n\t * Adds a server function at a route path.\n\t * @param path The route path pattern.\n\t * @param fn The function to call when the pattern is matched.\n\t * @returns\n\t */\n\tadd(path: string, fn: ServerFunction): Server {\n\t\tlet handler = new RouteHandler(path, fn);\n\t\tthis.routes.push(handler);\n\t\tthis.#trie.insert(path, handler);\n\t\tthis.#sortRoutes();\n\t\treturn this;\n\t}\n\n\tmatch(path: string): Match | undefined {\n\t\tconst found = this.#trie.match(path);\n\t\tif (found) {\n\t\t\treturn {\n\t\t\t\tfn: found.value.fn,\n\t\t\t\tparams: found.params,\n\t\t\t};\n\t\t}\n\t\tconsole.log(`Server path not found: ${path}`);\n\t}\n\n\t// TODO:\n\t//use(path: string, ...fn: MiddlewareFunction[])\n\tuse(...fn: MiddlewareFunction[]): Server {\n\t\tthis.middleware = this.middleware.concat(fn);\n\t\treturn this;\n\t}\n\n\t#sortRoutes() {\n\t\tthis.routes = this.routes.sort((a, b) => {\n\t\t\t// Sort [param]s after paths\n\t\t\t// There might be a quicker/easier way to do this\n\t\t\tfor (let i = 0; i < Math.min(a.path.length, b.path.length); i++) {\n\t\t\t\tif (a.path[i] === \"[\" && b.path[i] !== \"[\") {\n\t\t\t\t\treturn 1;\n\t\t\t\t} else if (b.path[i] === \"[\" && a.path[i] !== \"[\") {\n\t\t\t\t\treturn -1;\n\t\t\t\t} else if (a.path[i] === b.path[i]) {\n\t\t\t\t\t// Keep going...\n\t\t\t\t} else {\n\t\t\t\t\treturn a.path[i].localeCompare(b.path[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn a.path.length - b.path.length;\n\t\t});\n\t}\n}\n\nclass RouteHandler {\n\tpath: string;\n\tfn: ServerFunction;\n\n\tconstructor(path: string, fn: ServerFunction) {\n\t\tthis.path = path;\n\t\tthis.fn = fn;\n\t}\n}\n\n//class MiddlewareHandler {\n//\tpath: string;\n//\tregex: RegExp;\n//\tfn: MiddlewareFunction;\n//\n//\tconstructor(path: string, fn: MiddlewareFunction) {\n//\t\tthis.path = path;\n//\t\tthis.regex = pathToRegex(path);\n//\t\tthis.fn = fn;\n//\t}\n//}\n\ninterface Match {\n\tfn: ServerFunction;\n\tparams?: Record<string, string>;\n}\n","import { IncomingHttpHeaders } from \"node:http\";\nimport { OutgoingHttpHeaders } from \"node:http2\";\n\nexport default function flattenHeaders(\n\theaders: IncomingHttpHeaders | OutgoingHttpHeaders,\n): HeadersInit {\n\tconst flatHeaders = new Headers();\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tif (value === undefined || value === null) {\n\t\t\tcontinue;\n\t\t} else if (Array.isArray(value)) {\n\t\t\tfor (const v of value) {\n\t\t\t\tif (v !== undefined && v !== null) {\n\t\t\t\t\tflatHeaders.append(key, String(v));\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tflatHeaders.set(key, String(value));\n\t\t}\n\t}\n\treturn flatHeaders;\n}\n"],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ //#region src/form/readForm.d.ts
2
+ /**
3
+ * The values read from a form submission, coerced by the spec's default
4
+ * value types: string defaults produce strings, number defaults produce
5
+ * numbers, boolean defaults produce booleans, and array defaults produce
6
+ * arrays of the element type (an empty array default produces strings).
7
+ */
8
+ type FormValues<Spec extends Record<string, unknown>> = { [K in keyof Spec]: FormValue<Spec[K]>; };
9
+ type FormValue<T> = T extends boolean ? boolean : T extends number ? number : T extends readonly unknown[] ? [T[number]] extends [never] ? string[] : T[number][] : string;
10
+ /**
11
+ * Reads and coerces the submitted fields of a form action, e.g.
12
+ *
13
+ * ```ts
14
+ * const data = await readForm(request, {
15
+ * title: "",
16
+ * done: false,
17
+ * priority: 0,
18
+ * tags: [],
19
+ * });
20
+ * // data: { title: string; done: boolean; priority: number; tags: string[] }
21
+ * ```
22
+ *
23
+ * The spec object declares the expected fields; each key's default value
24
+ * determines the type and the fallback when the field is missing or can't be
25
+ * coerced. Booleans follow checkbox semantics (unchecked fields are absent,
26
+ * so they come back as `false`).
27
+ *
28
+ * @param request The action event's request, or its FormData directly
29
+ * @param spec An object mapping field names to default values
30
+ * @returns The coerced field values
31
+ */
32
+ declare function readForm<Spec extends Record<string, unknown>>(request: Request | FormData, spec: Spec): Promise<FormValues<Spec>>;
33
+ //#endregion
34
+ export { type FormValues, readForm };
35
+ //# sourceMappingURL=form.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form.d.mts","names":[],"sources":["../src/form/readForm.ts"],"mappings":";;;;;;;KAMY,WAAW,aAAa,8BAClC,WAAW,OAAO,UAAU,KAAK;KAG9B,UAAU,KAAK,8BAEjB,4BAEC,gCACE,wCAEA;;;;;;;;;;;;;;;;;;;;;;;iBAyBwB,SAAS,aAAa,yBACnD,SAAS,UAAU,UACnB,MAAM,OACJ,QAAQ,WAAW"}
package/dist/form.mjs ADDED
@@ -0,0 +1,48 @@
1
+ //#region src/form/readForm.ts
2
+ /**
3
+ * Reads and coerces the submitted fields of a form action, e.g.
4
+ *
5
+ * ```ts
6
+ * const data = await readForm(request, {
7
+ * title: "",
8
+ * done: false,
9
+ * priority: 0,
10
+ * tags: [],
11
+ * });
12
+ * // data: { title: string; done: boolean; priority: number; tags: string[] }
13
+ * ```
14
+ *
15
+ * The spec object declares the expected fields; each key's default value
16
+ * determines the type and the fallback when the field is missing or can't be
17
+ * coerced. Booleans follow checkbox semantics (unchecked fields are absent,
18
+ * so they come back as `false`).
19
+ *
20
+ * @param request The action event's request, or its FormData directly
21
+ * @param spec An object mapping field names to default values
22
+ * @returns The coerced field values
23
+ */
24
+ async function readForm(request, spec) {
25
+ const formData = request instanceof FormData ? request : await request.formData();
26
+ const result = {};
27
+ for (const key of Object.keys(spec)) {
28
+ const defaultValue = spec[key];
29
+ const values = formData.getAll(key).map((v) => v.toString());
30
+ result[key] = Array.isArray(defaultValue) ? values.map((value) => coerceValue(value, defaultValue[0])) : coerceValue(values[0], defaultValue);
31
+ }
32
+ return result;
33
+ }
34
+ function coerceValue(value, defaultValue) {
35
+ if (typeof defaultValue === "number") {
36
+ const n = value === void 0 || value === "" ? NaN : Number(value);
37
+ return Number.isNaN(n) ? defaultValue : n;
38
+ }
39
+ if (typeof defaultValue === "boolean") {
40
+ if (value === void 0) return false;
41
+ return !(value === "" || value === "false" || value === "off");
42
+ }
43
+ return value ?? defaultValue ?? "";
44
+ }
45
+ //#endregion
46
+ export { readForm };
47
+
48
+ //# sourceMappingURL=form.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form.mjs","names":[],"sources":["../src/form/readForm.ts"],"sourcesContent":["/**\n * The values read from a form submission, coerced by the spec's default\n * value types: string defaults produce strings, number defaults produce\n * numbers, boolean defaults produce booleans, and array defaults produce\n * arrays of the element type (an empty array default produces strings).\n */\nexport type FormValues<Spec extends Record<string, unknown>> = {\n\t[K in keyof Spec]: FormValue<Spec[K]>;\n};\n\ntype FormValue<T> = T extends boolean\n\t? boolean\n\t: T extends number\n\t\t? number\n\t\t: T extends readonly unknown[]\n\t\t\t? [T[number]] extends [never]\n\t\t\t\t? string[]\n\t\t\t\t: T[number][]\n\t\t\t: string;\n\n/**\n * Reads and coerces the submitted fields of a form action, e.g.\n *\n * ```ts\n * const data = await readForm(request, {\n * title: \"\",\n * done: false,\n * priority: 0,\n * tags: [],\n * });\n * // data: { title: string; done: boolean; priority: number; tags: string[] }\n * ```\n *\n * The spec object declares the expected fields; each key's default value\n * determines the type and the fallback when the field is missing or can't be\n * coerced. Booleans follow checkbox semantics (unchecked fields are absent,\n * so they come back as `false`).\n *\n * @param request The action event's request, or its FormData directly\n * @param spec An object mapping field names to default values\n * @returns The coerced field values\n */\nexport default async function readForm<Spec extends Record<string, unknown>>(\n\trequest: Request | FormData,\n\tspec: Spec,\n): Promise<FormValues<Spec>> {\n\tconst formData = request instanceof FormData ? request : await request.formData();\n\tconst result: Record<string, unknown> = {};\n\tfor (const key of Object.keys(spec)) {\n\t\tconst defaultValue = spec[key];\n\t\t// oxlint-disable-next-line typescript/no-base-to-string\n\t\tconst values = formData.getAll(key).map((v) => v.toString());\n\t\tresult[key] = Array.isArray(defaultValue)\n\t\t\t? values.map((value) => coerceValue(value, defaultValue[0]))\n\t\t\t: coerceValue(values[0], defaultValue);\n\t}\n\treturn result as FormValues<Spec>;\n}\n\nfunction coerceValue(value: string | undefined, defaultValue: unknown): unknown {\n\tif (typeof defaultValue === \"number\") {\n\t\tconst n = value === undefined || value === \"\" ? NaN : Number(value);\n\t\treturn Number.isNaN(n) ? defaultValue : n;\n\t}\n\tif (typeof defaultValue === \"boolean\") {\n\t\t// Unchecked checkboxes are not submitted at all\n\t\tif (value === undefined) return false;\n\t\treturn !(value === \"\" || value === \"false\" || value === \"off\");\n\t}\n\treturn value ?? defaultValue ?? \"\";\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA0CA,eAA8B,SAC7B,SACA,MAC4B;CAC5B,MAAM,WAAW,mBAAmB,WAAW,UAAU,MAAM,QAAQ,SAAS;CAChF,MAAM,SAAkC,CAAC;CACzC,KAAK,MAAM,OAAO,OAAO,KAAK,IAAI,GAAG;EACpC,MAAM,eAAe,KAAK;EAE1B,MAAM,SAAS,SAAS,OAAO,GAAG,CAAC,CAAC,KAAK,MAAM,EAAE,SAAS,CAAC;EAC3D,OAAO,OAAO,MAAM,QAAQ,YAAY,IACrC,OAAO,KAAK,UAAU,YAAY,OAAO,aAAa,EAAE,CAAC,IACzD,YAAY,OAAO,IAAI,YAAY;CACvC;CACA,OAAO;AACR;AAEA,SAAS,YAAY,OAA2B,cAAgC;CAC/E,IAAI,OAAO,iBAAiB,UAAU;EACrC,MAAM,IAAI,UAAU,KAAA,KAAa,UAAU,KAAK,MAAM,OAAO,KAAK;EAClE,OAAO,OAAO,MAAM,CAAC,IAAI,eAAe;CACzC;CACA,IAAI,OAAO,iBAAiB,WAAW;EAEtC,IAAI,UAAU,KAAA,GAAW,OAAO;EAChC,OAAO,EAAE,UAAU,MAAM,UAAU,WAAW,UAAU;CACzD;CACA,OAAO,SAAS,gBAAgB;AACjC"}
package/dist/index.d.mts CHANGED
@@ -1,7 +1,8 @@
1
- import { a as CookieHelper, i as HeaderHelper } from "./Server-CF5wDJp6.mjs";
2
- import { n as Adapter, t as Site } from "./Site-DgC6WWn1.mjs";
3
- import { Component } from "@torpor/view";
4
-
1
+ import { a as RouteParamsOf, i as RouteArgsOf, n as ParseRouteParams, r as RouteArgs } from "./ParseRouteParams-DBmqlmLh.mjs";
2
+ import { C as ServerLoadEvent, S as QueryRecord, _ as PageLoadEvent, a as ServerEndPoint, b as ServerHook, c as ActionBody, d as PageServerActionSchemas, f as PageServerEndPoint, g as PageLoadReturn, h as PageEndPoint, i as SchemaQuery, l as LoadParams, m as PageServerAction, n as ParamsOf, o as ServerEndPointSchemas, p as PageServerLoad, r as SchemaBody, s as ServerRequest, t as Site, u as LoadQuery, v as SitePlugin, x as FormDataRecord, y as Adapter } from "./Site-CMa153FA.mjs";
3
+ import { n as UntypedResponse, t as TypedResponse } from "./TypedResponse-6lznqN4U.mjs";
4
+ import { t as StandardSchemaV1 } from "./StandardSchema-D28L8_zZ.mjs";
5
+ import { t as Jsonify } from "./Jsonify-Dg6gChd3.mjs";
5
6
  //#region src/types/ManifestRoute.d.ts
6
7
  interface ManifestRoute {
7
8
  path: string;
@@ -19,8 +20,8 @@ interface RouteLayoutHandler {
19
20
  //#endregion
20
21
  //#region src/types/RouteHandler.d.ts
21
22
  /**
22
- * A handler for a route in the Router.
23
- */
23
+ * A handler for a route in the Router.
24
+ */
24
25
  interface RouteHandler {
25
26
  path: string;
26
27
  type: number;
@@ -29,13 +30,16 @@ interface RouteHandler {
29
30
  loaded?: boolean;
30
31
  layouts?: RouteLayoutHandler[];
31
32
  serverEndPoint?: () => Promise<any>;
32
- serverHook?: () => Promise<any>;
33
+ serverHooks?: (() => Promise<any>)[];
34
+ modulePromise?: Promise<any>;
35
+ resolvedModule?: any;
36
+ resolvedHooks?: Promise<ServerHook[]>;
33
37
  }
34
38
  //#endregion
35
39
  //#region src/site/Router.d.ts
36
40
  /**
37
- * A router that handles file routes with layouts, hooks, etc.
38
- */
41
+ * A router that handles file routes with layouts, hooks, etc.
42
+ */
39
43
  declare class Router {
40
44
  #private;
41
45
  routes: Route[];
@@ -46,7 +50,6 @@ declare class Router {
46
50
  }
47
51
  declare class Route {
48
52
  path: string;
49
- regex: RegExp;
50
53
  handler: RouteHandler;
51
54
  constructor(path: string, handler: RouteHandler);
52
55
  }
@@ -56,158 +59,71 @@ interface RouteMatch {
56
59
  query: URLSearchParams;
57
60
  }
58
61
  //#endregion
59
- //#region src/types/PageLoadEvent.d.ts
60
- interface PageLoadEvent {
61
- /**
62
- * The URL for the server function.
63
- */
64
- url: URL;
65
- /**
66
- * Route params from the URL and route path.
67
- */
68
- params: Record<string, string>;
69
- /**
70
- * Data that is (optionally) loaded from the load function and passed into the page as $props.data.
71
- */
72
- data: Record<string, any>;
73
- }
74
- //#endregion
75
- //#region src/types/PageEndPoint.d.ts
62
+ //#region src/types/PageData.d.ts
76
63
  /**
77
- * For +page.
78
- */
79
- interface PageEndPoint {
80
- /**
81
- * Builds the route path for the page in a type-safe manner.
82
- * TODO: Not sure this is actually the best way to do it...
83
- */
84
- route?: (...args: any[]) => string;
85
- /**
86
- * Loads data for the page.
87
- */
88
- load?: (event: PageLoadEvent) => Response | undefined | void | Promise<Response | undefined | void>;
89
- /**
90
- * The component that is displayed for the page.
91
- */
92
- component?: Component;
93
- /**
94
- * The head element data for the page, which may include a <title> and <meta> elements.
95
- */
96
- head?: HeadElement[] | ((event: PageLoadEvent) => HeadElement[]);
97
- }
98
- type HeadElement = TitleElement | MetaElement;
99
- interface TitleElement {
100
- title: string;
101
- }
102
- interface MetaElement {
103
- name: string;
104
- content: string;
105
- }
106
- //#endregion
107
- //#region src/types/ServerLoadEvent.d.ts
108
- interface ServerLoadEvent {
109
- /**
110
- * The URL for the server function.
111
- */
112
- url: URL;
113
- /**
114
- * Route params from the URL and route path.
115
- */
116
- params: Record<string, string>;
117
- /**
118
- * Data that is available to functions in +server hooks, layouts, endpoints
119
- * and pages. It flows down in that order.
120
- */
121
- appData: Record<string, any>;
122
- /**
123
- * The server request.
124
- */
125
- request: Request;
126
- /**
127
- * A helper for getting and setting cookie data.
128
- */
129
- cookies: CookieHelper;
130
- /**
131
- * A helper for getting and setting headers.
132
- */
133
- headers: HeaderHelper;
134
- /**
135
- * An optional adapter object, containing adapter-specific functionality.
136
- */
137
- adapter: Record<PropertyKey, any>;
138
- }
139
- //#endregion
140
- //#region src/types/PageServerAction.d.ts
141
- type PageServerAction = (event: ServerLoadEvent) => Response | undefined | void | Promise<Response | undefined | void>;
142
- //#endregion
143
- //#region src/types/PageServerLoad.d.ts
144
- type PageServerLoad = (event: ServerLoadEvent) => Response | undefined | void | Promise<Response | undefined | void>;
145
- //#endregion
146
- //#region src/types/PageServerEndPoint.d.ts
64
+ * The page data produced by an endpoint's `load` function, e.g.
65
+ *
66
+ * ```ts
67
+ * import type server from "./+page.server";
68
+ * type Data = PageData<typeof server>;
69
+ * ```
70
+ *
71
+ * Falls back to a loose record when the endpoint has no load or its load
72
+ * returns untyped responses.
73
+ */
74
+ type PageData<EndPoint> = EndPoint extends {
75
+ load?: (event: any) => infer Return;
76
+ } ? NonNullable<Awaited<Return>> extends TypedResponse<infer Body> ? Body : Record<string, any> : Record<string, any>;
147
77
  /**
148
- * For +page.server.
149
- */
150
- interface PageServerEndPoint {
151
- /**
152
- * Loads data from the server for a page.
153
- */
154
- load?: PageServerLoad;
155
- /**
156
- * A map of actions that can be performed on the server for a page, generally from a form submit.
157
- */
158
- actions?: Record<string, PageServerAction>;
159
- }
78
+ * The merged page data for a page that sits under one or more layouts: pass
79
+ * the layout endpoints first and the page endpoint last, e.g.
80
+ *
81
+ * ```ts
82
+ * import type layoutServer from "../_layout.server";
83
+ * import type server from "./+page.server";
84
+ * type Data = MergePageData<typeof layoutServer, typeof server>;
85
+ * ```
86
+ *
87
+ * Each endpoint's data is intersected in order; endpoints without a typed
88
+ * `load` contribute nothing but looseness.
89
+ */
90
+ type MergePageData<EndPoints extends any[]> = EndPoints extends [infer First, ...infer Rest] ? PageData<First> & MergePageData<Rest> : unknown;
160
91
  //#endregion
161
- //#region src/types/ServerRequest.d.ts
162
- type ServerRequest = (event: ServerLoadEvent) => Response | undefined | void | Promise<Response | undefined | void>;
163
- //#endregion
164
- //#region src/types/ServerEndPoint.d.ts
92
+ //#region src/types/PageForm.d.ts
93
+ /** The non-undefined return values of an endpoint's actions. */
94
+ type ActionReturns<Actions> = { [K in keyof Actions]: Actions[K] extends ((event: any) => infer Return) ? NonNullable<Awaited<Return>> : never; }[keyof Actions];
165
95
  /**
166
- * For +server.
167
- */
168
- type ServerEndPoint = {
169
- [key: string]: ServerRequest;
170
- } & {
171
- /**
172
- * Performs a GET.
173
- */
174
- get?: ServerRequest;
175
- /**
176
- * Performs a POST.
177
- */
178
- post?: ServerRequest;
179
- /**
180
- * Performs a PATCH.
181
- */
182
- patch?: ServerRequest;
183
- /**
184
- * Performs a PUT.
185
- */
186
- put?: ServerRequest;
187
- /**
188
- * Performs a DELETE.
189
- */
190
- del?: ServerRequest;
191
- /**
192
- * Performs an OPTIONS request.
193
- */
194
- options?: ServerRequest;
195
- /**
196
- * Performs a HEAD request.
197
- */
198
- head?: ServerRequest;
199
- };
96
+ * The form result an endpoint's actions produce, i.e. what becomes the page's
97
+ * `$props.form` after a submit, e.g.
98
+ *
99
+ * ```ts
100
+ * import type server from "./+page.server";
101
+ * type Form = PageForm<typeof server>;
102
+ * ```
103
+ *
104
+ * Actions returning typed responses (e.g. `ok({ ... })`, `badRequest({ ... })`)
105
+ * contribute their JSON bodies as a union. Falls back to a loose record when
106
+ * there are no actions or their responses are untyped.
107
+ */
108
+ type PageForm<EndPoint> = EndPoint extends {
109
+ actions?: infer Actions;
110
+ } ? [NonNullable<Actions>] extends [never] ? Record<string, any> : ActionReturns<NonNullable<Actions>> extends TypedResponse<infer Body> ? Body : Record<string, any> : Record<string, any>;
200
111
  //#endregion
201
- //#region src/types/ServerHook.d.ts
112
+ //#region src/types/PageProps.d.ts
202
113
  /**
203
- * For _hook.server.
204
- */
205
- interface ServerHook {
206
- /**
207
- * Called on each server request.
208
- */
209
- handle?: (event: ServerLoadEvent) => Promise<void> | void;
114
+ * The props passed to a page (or layout) component: the data accumulated from
115
+ * load functions, plus the result of the last form action if any.
116
+ */
117
+ interface PageProps<Data = Record<string, any>, Form = Record<string, any>> {
118
+ /**
119
+ * Data loaded by the page's (and its layouts') load functions.
120
+ */
121
+ data: Data;
122
+ /**
123
+ * The JSON result of the last form action, if a form was submitted.
124
+ */
125
+ form: Form | undefined;
210
126
  }
211
127
  //#endregion
212
- export { type Adapter, type PageEndPoint, type PageLoadEvent, type PageServerAction, type PageServerEndPoint, type PageServerLoad, Router, type ServerEndPoint, type ServerHook, type ServerLoadEvent, type ServerRequest, Site };
128
+ export { type ActionBody, type Adapter, type FormDataRecord, type Jsonify, type LoadParams, type LoadQuery, type MergePageData, type PageData, type PageEndPoint, type PageForm, type PageLoadEvent, type PageLoadReturn, type PageProps, type PageServerAction, type PageServerActionSchemas, type PageServerEndPoint, type PageServerLoad, type ParamsOf, type ParseRouteParams, type QueryRecord, type RouteArgs, type RouteArgsOf, type RouteParamsOf, Router, type SchemaBody, type SchemaQuery, type ServerEndPoint, type ServerEndPointSchemas, type ServerHook, type ServerLoadEvent, type ServerRequest, Site, type SitePlugin, type StandardSchemaV1, type TypedResponse, type UntypedResponse };
213
129
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types/ManifestRoute.ts","../src/types/RouteLayoutHandler.ts","../src/types/RouteHandler.ts","../src/site/Router.ts","../src/types/PageLoadEvent.ts","../src/types/PageEndPoint.ts","../src/types/ServerLoadEvent.ts","../src/types/PageServerAction.ts","../src/types/PageServerLoad.ts","../src/types/PageServerEndPoint.ts","../src/types/ServerRequest.ts","../src/types/ServerEndPoint.ts","../src/types/ServerHook.ts"],"sourcesContent":[],"mappings":";;;;;UAAyB,aAAA;;;kBAGR;;;;;UCHQ,kBAAA;;kBAER;yBACO;;;;;;;UCEC,YAAA;MFLA,EAAA,MAAA;;kBEQR;;QDRQ,CAAA,EAAA,OAAA;YCYd;yBACa;qBACJ;AAdgB;;;;;;AFAX,cGQJ,MAAA,CHRI;;UGShB;;UFTgB,CAAA,MAAA,EEkBP,aFlBO,EAAA,CAAA,EAAA,IAER;sDEgCoC;6BAuBzB,kBAAkB;;ADzDV,cCmJ9B,KAAA,CD9ImB;EAGR,IAAA,EAAA,MAAA;EAIN,KAAA,ECyIH,MDzIG;EACa,OAAA,ECyId,YDzIc;EACJ,WAAA,CAAA,IAAA,EAAA,MAAA,EAAA,OAAA,EC0IgB,YD1IhB;;UCiJV,UAAA;WACA;WACA;EA/JoB,KAMT,EA0Jb,eA1Ja;;;;UCRI,aAAA;;;;OAInB;;;;UAIG;;;;QAIF;AFZ6B;;;;;;AFAX,UKMA,YAAA,CLHR;;;;;;;;AEHmB;EAQnB,IAAA,CAAA,EAAA,CAAA,KAAA,EGQR,aHRQ,EAAA,GGSX,QHTW,GAAA,SAAA,GAAA,IAAA,GGSmB,OHTnB,CGS2B,QHT3B,GAAA,SAAA,GAAA,IAAA,CAAA;EAIN;;;EAES,SAAA,CAAA,EGOP,SHPO;;;;ECZU,IAMT,CAAA,EEkBb,WFlBa,EAAA,GAAA,CAAA,CAAA,KAAA,EEkBY,aFlBZ,EAAA,GEkB8B,WFlB9B,EAAA,CAAA;;AACZ,KEoBJ,WAAA,GAAc,YFpBV,GEoByB,WFpBzB;UEsBC,YAAA,CFbQ;EAgBmC,KAAA,EAAA,MAAA;;UEC3C,WAAA,CFsBoC;EAAA,IAAA,EAAA,MAAA;EAAA,OA0FxC,EAAA,MAAA;;;;UGhJmB,eAAA;;;;OAInB;;;;UAIG;;;AJX2B;;EAYzB,OAAA,EIMD,MJNC,CAAA,MAAA,EAAA,GAAA,CAAA;EACa;;;WISd;;;AHpBoB;EAOrB,OAAA,EGkBC,YHlBD;EASS;;;EAuC4B,OAAA,EG1BpC,YH0BoC;EAAA;AAAA;;EA6FpC,OAAA,EGnHA,MHmHA,CGnHO,WHmHP,EAAA,GAAA,CAAA;;;;KIpJL,gBAAA,WACG,oBACH,8BAA8B,QAAQ;;;KCFtC,cAAA,WACG,oBACH,8BAA8B,QAAQ;;;;;;ARJlB,USMA,kBAAA,CTHR;;;;MCHQ,CAAA,EQUjB,cRViB;;;;ECAW,OAKX,CAAA,EOSd,MPTc,CAAA,MAAA,EOSC,gBPTD,CAAA;;;;KQHpB,aAAA,WACG,oBACH,8BAA8B,QAAQ;;;;;;KCCtC,cAAA;MXLoB,EAAA,MAAA,CAAA,EWKc,aXLd;;;;;QWSlB;;;ATT6B;EAQnB,IAAA,CAAA,ESKT,aTLS;EAIN;;;EAES,KAAA,CAAA,ESGX,aTHW;;;;ECZU,GAMT,CAAA,EQad,aRbc;EACZ;;;EAgDmB,GAAA,CAAA,EQhCrB,aRgCqB;EAAkB;;AAAA;EA4FtC,OAAA,CAAA,EQxHG,aRwHH;EACE;;;EAE0B,IAO1B,CAAA,EQ9HF,aR8HE;CACA;;;;;;US3Je,UAAA;;;;mBAIP,oBAAoB"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types/ManifestRoute.ts","../src/types/RouteLayoutHandler.ts","../src/types/RouteHandler.ts","../src/site/Router.ts","../src/types/PageData.ts","../src/types/PageForm.ts","../src/types/PageProps.ts"],"mappings":";;;;;;UAAyB;EACxB;EACA;EACA,gBAAgB;EAChB;;;;UCJwB;EACxB;EACA,gBAAgB;EAChB,uBAAuB;;;;;;;UCGC;EACxB;EACA;EACA,gBAAgB;EAChB;EAEA;EACA,UAAU;EACV,uBAAuB;EACvB,qBAAqB;EAIrB,gBAAgB;EAChB;EACA,gBAAgB,QAAQ;;;;;;;cCbJ;;EACpB,QAAQ;EAMR;EAOA,SAAS,QAAQ;EAQjB,QAAQ,cAAc,cAAc,gBAAgB,cAAc;EAuBlE,MAAM,cAAc,OAAO,kBAAkB;;cA2GxC;EACL;EACA,SAAS;EAET,YAAY,cAAc,SAAS;;UAM1B;EACT,SAAS;EACT,SAAS;EACT,OAAO;;;;;;;;;;;;;;;KChKI,SAAS,YAAY;EAAmB,QAAQ,qBAAqB;IAC9E,YAAY,QAAQ,iBAAiB,oBAAoB,QACxD,OACA,sBACD;;;;;;;;;;;;;;KAeS,cAAc,2BAA2B,yBAAyB,gBAAgB,QAC3F,SAAS,SAAS,cAAc;;;;KC9B9B,cAAc,cACjB,WAAW,UAAU,QAAQ,aAAY,qBAAqB,UAC5D,YAAY,QAAQ,0BAEhB;;;;;;;;;;;;;;KAeI,SAAS,YAAY;EAAmB,gBAAgB;KAChE,YAAY,4BACZ,sBACA,cAAc,YAAY,kBAAkB,oBAAoB,QAC/D,OACA,sBACF;;;;;;;UCxBsB,UAAU,OAAO,qBAAqB,OAAO;;;;EAIrE,MAAM;;;;EAIN,MAAM"}