@torpor/build 1.0.0 → 1.0.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 (174) hide show
  1. package/dist/{flattenHeaders-C_YYLdOq.mjs → Server-BnjLJleZ.mjs} +2 -12
  2. package/dist/Server-BnjLJleZ.mjs.map +1 -0
  3. package/dist/{Server-C_IKav_e.d.mts → Server-Cler2w5O.d.mts} +3 -48
  4. package/dist/Server-Cler2w5O.d.mts.map +1 -0
  5. package/dist/ServerEvent-CTx3Q-hk.d.mts +48 -0
  6. package/dist/ServerEvent-CTx3Q-hk.d.mts.map +1 -0
  7. package/dist/{Site-CMa153FA.d.mts → Site-CE0_o5Ci.d.mts} +3 -2
  8. package/dist/Site-CE0_o5Ci.d.mts.map +1 -0
  9. package/dist/bin/index.js +1 -1
  10. package/dist/clientEntry.d.mts +1 -0
  11. package/dist/clientEntry.mjs +59 -0
  12. package/dist/clientEntry.mjs.map +1 -0
  13. package/dist/clientEntryDev.d.mts +1 -0
  14. package/dist/clientEntryDev.mjs +7 -0
  15. package/dist/clientEntryDev.mjs.map +1 -0
  16. package/dist/dev.d.mts +3 -0
  17. package/dist/dev.mjs +3 -0
  18. package/dist/endpoint-EULRGCKA.mjs +108 -0
  19. package/dist/endpoint-EULRGCKA.mjs.map +1 -0
  20. package/dist/flattenHeaders-DM5qsSqO.mjs +13 -0
  21. package/dist/flattenHeaders-DM5qsSqO.mjs.map +1 -0
  22. package/dist/index.d.mts +1 -1
  23. package/dist/load-BntzvmwL.mjs +228 -0
  24. package/dist/load-BntzvmwL.mjs.map +1 -0
  25. package/dist/nav.mjs +1 -225
  26. package/dist/nav.mjs.map +1 -1
  27. package/dist/openapi.d.mts +1 -1
  28. package/dist/run.d.mts +1 -1
  29. package/dist/run.d.mts.map +1 -1
  30. package/dist/run.mjs +1 -1
  31. package/dist/{runOpenApi-BUi1RH1l.mjs → runOpenApi-DlOgF2Il.mjs} +54 -16
  32. package/dist/runOpenApi-DlOgF2Il.mjs.map +1 -0
  33. package/dist/server/Server.d.mts +2 -0
  34. package/dist/server/Server.mjs +2 -0
  35. package/dist/server.d.mts +2 -1
  36. package/dist/server.d.mts.map +1 -1
  37. package/dist/server.mjs +2 -1
  38. package/dist/server.mjs.map +1 -1
  39. package/dist/serverEntry-1qY3wZig.mjs +351 -0
  40. package/dist/serverEntry-1qY3wZig.mjs.map +1 -0
  41. package/dist/serverEntry-BAO8m03V.d.mts +6 -0
  42. package/dist/serverEntry-BAO8m03V.d.mts.map +1 -0
  43. package/dist/serverEntry.d.mts +2 -0
  44. package/dist/serverEntry.mjs +2 -0
  45. package/dist/test.d.mts +2 -2
  46. package/dist/test.mjs +2 -104
  47. package/dist/test.mjs.map +1 -1
  48. package/package.json +9 -8
  49. package/dist/Server-C_IKav_e.d.mts.map +0 -1
  50. package/dist/Site-CMa153FA.d.mts.map +0 -1
  51. package/dist/flattenHeaders-C_YYLdOq.mjs.map +0 -1
  52. package/dist/runOpenApi-BUi1RH1l.mjs.map +0 -1
  53. package/src/bin/index.ts +0 -22
  54. package/src/dev.ts +0 -10
  55. package/src/form/formDataToRecord.ts +0 -23
  56. package/src/form/readForm.ts +0 -71
  57. package/src/form.ts +0 -4
  58. package/src/index.ts +0 -82
  59. package/src/nav/api.test-d.ts +0 -79
  60. package/src/nav/api.ts +0 -104
  61. package/src/nav/formSubmit.ts +0 -70
  62. package/src/nav/load.ts +0 -9
  63. package/src/nav/loadData.ts +0 -134
  64. package/src/nav/navigate.ts +0 -189
  65. package/src/nav/reload.ts +0 -9
  66. package/src/nav/route.ts +0 -38
  67. package/src/nav.ts +0 -6
  68. package/src/openapi/docsHtml.ts +0 -25
  69. package/src/openapi/document.ts +0 -154
  70. package/src/openapi/plugin.ts +0 -78
  71. package/src/openapi/types.ts +0 -82
  72. package/src/openapi.ts +0 -14
  73. package/src/response/TypedResponse.ts +0 -17
  74. package/src/response/badRequest.ts +0 -31
  75. package/src/response/created.ts +0 -31
  76. package/src/response/forbidden.ts +0 -21
  77. package/src/response/found.ts +0 -30
  78. package/src/response/methodNotAllowed.ts +0 -18
  79. package/src/response/movedPermanently.ts +0 -25
  80. package/src/response/notFound.ts +0 -24
  81. package/src/response/notModified.ts +0 -34
  82. package/src/response/ok.ts +0 -38
  83. package/src/response/permanentRedirect.ts +0 -30
  84. package/src/response/response.ts +0 -22
  85. package/src/response/seeOther.ts +0 -19
  86. package/src/response/serverError.ts +0 -24
  87. package/src/response/temporaryRedirect.ts +0 -31
  88. package/src/response/transfer.ts +0 -14
  89. package/src/response/unauthorized.ts +0 -21
  90. package/src/response/unprocessable.ts +0 -30
  91. package/src/response.ts +0 -37
  92. package/src/run/depCache.ts +0 -175
  93. package/src/run/devPlugin.ts +0 -128
  94. package/src/run/prepareTemplate.ts +0 -42
  95. package/src/run/run.ts +0 -86
  96. package/src/run/runBuild.ts +0 -128
  97. package/src/run/runDev.ts +0 -177
  98. package/src/run/runOpenApi.ts +0 -52
  99. package/src/run/runPreview.ts +0 -84
  100. package/src/run/staleTorpCopies.ts +0 -100
  101. package/src/run.ts +0 -7
  102. package/src/schema.ts +0 -7
  103. package/src/server/CookieHelper.ts +0 -46
  104. package/src/server/HeaderHelper.ts +0 -25
  105. package/src/server/Server.ts +0 -168
  106. package/src/server/ServerEvent.ts +0 -62
  107. package/src/server/connect/connectMiddleware.ts +0 -85
  108. package/src/server/connect/flattenHeaders.ts +0 -22
  109. package/src/server/connect/nodeMessageToNodeResponse.ts +0 -89
  110. package/src/server/connect/requestToNodeMessage.ts +0 -29
  111. package/src/server/contentType.ts +0 -85
  112. package/src/server/types/HttpMethod.ts +0 -12
  113. package/src/server/types/MiddlewareFunction.ts +0 -22
  114. package/src/server/types/ServerFunction.ts +0 -7
  115. package/src/server.ts +0 -7
  116. package/src/site/Router.ts +0 -175
  117. package/src/site/Site.ts +0 -388
  118. package/src/site/checkLayoutSlots.ts +0 -114
  119. package/src/site/checkRoutes.ts +0 -435
  120. package/src/site/clientEntry.ts +0 -121
  121. package/src/site/clientEntryDev.ts +0 -3
  122. package/src/site/defaultAdapter.ts +0 -11
  123. package/src/site/layoutSlots.ts +0 -53
  124. package/src/site/manifest.ts +0 -173
  125. package/src/site/serverEntry.ts +0 -648
  126. package/src/state/$page.ts +0 -25
  127. package/src/state/$serverPage.ts +0 -22
  128. package/src/state/client.ts +0 -15
  129. package/src/state.ts +0 -3
  130. package/src/test/runTest.ts +0 -538
  131. package/src/test.ts +0 -3
  132. package/src/types/Adapter.ts +0 -20
  133. package/src/types/ClientState.ts +0 -8
  134. package/src/types/InternalState.ts +0 -7
  135. package/src/types/Jsonify.ts +0 -20
  136. package/src/types/LayoutHandler.ts +0 -5
  137. package/src/types/LayoutPath.ts +0 -10
  138. package/src/types/ManifestRoute.ts +0 -6
  139. package/src/types/PageData.test-d.ts +0 -136
  140. package/src/types/PageData.ts +0 -35
  141. package/src/types/PageEndPoint.ts +0 -55
  142. package/src/types/PageForm.test-d.ts +0 -78
  143. package/src/types/PageForm.ts +0 -29
  144. package/src/types/PageLoadEvent.ts +0 -26
  145. package/src/types/PageLoadReturn.ts +0 -13
  146. package/src/types/PageProps.ts +0 -14
  147. package/src/types/PageServerAction.ts +0 -13
  148. package/src/types/PageServerEndPoint.test-d.ts +0 -105
  149. package/src/types/PageServerEndPoint.ts +0 -110
  150. package/src/types/PageServerLoad.ts +0 -15
  151. package/src/types/PageState.ts +0 -8
  152. package/src/types/ParseRouteParams.test-d.ts +0 -84
  153. package/src/types/ParseRouteParams.ts +0 -64
  154. package/src/types/Route.ts +0 -30
  155. package/src/types/RouteHandler.ts +0 -23
  156. package/src/types/RouteLayoutHandler.ts +0 -5
  157. package/src/types/RouteMatchResult.ts +0 -7
  158. package/src/types/RouteType.ts +0 -19
  159. package/src/types/ServerEndPoint.test-d.ts +0 -77
  160. package/src/types/ServerEndPoint.ts +0 -169
  161. package/src/types/ServerHook.ts +0 -18
  162. package/src/types/ServerLoadEvent.ts +0 -82
  163. package/src/types/ServerRequest.ts +0 -15
  164. package/src/types/SitePlugin.ts +0 -24
  165. package/src/types/StandardSchema.ts +0 -109
  166. package/src/utils/pathToRegex.ts +0 -17
  167. package/src/utils/pathTrie.ts +0 -182
  168. package/src/utils/searchParamsToRecord.ts +0 -18
  169. package/src/utils/torporPackages.ts +0 -150
  170. package/src/utils/tsconfigAliases.ts +0 -90
  171. package/src/validation/ValidationError.ts +0 -18
  172. package/src/validation/endpoint.ts +0 -83
  173. package/src/validation/validate.ts +0 -26
  174. package/src/vite-env.d.ts +0 -2
@@ -1,71 +0,0 @@
1
- /**
2
- * The values read from a form submission, coerced by the spec's default
3
- * value types: string defaults produce strings, number defaults produce
4
- * numbers, boolean defaults produce booleans, and array defaults produce
5
- * arrays of the element type (an empty array default produces strings).
6
- */
7
- export type FormValues<Spec extends Record<string, unknown>> = {
8
- [K in keyof Spec]: FormValue<Spec[K]>;
9
- };
10
-
11
- type FormValue<T> = T extends boolean
12
- ? boolean
13
- : T extends number
14
- ? number
15
- : T extends readonly unknown[]
16
- ? [T[number]] extends [never]
17
- ? string[]
18
- : T[number][]
19
- : string;
20
-
21
- /**
22
- * Reads and coerces the submitted fields of a form action, e.g.
23
- *
24
- * ```ts
25
- * const data = await readForm(request, {
26
- * title: "",
27
- * done: false,
28
- * priority: 0,
29
- * tags: [],
30
- * });
31
- * // data: { title: string; done: boolean; priority: number; tags: string[] }
32
- * ```
33
- *
34
- * The spec object declares the expected fields; each key's default value
35
- * determines the type and the fallback when the field is missing or can't be
36
- * coerced. Booleans follow checkbox semantics (unchecked fields are absent,
37
- * so they come back as `false`).
38
- *
39
- * @param request The action event's request, or its FormData directly
40
- * @param spec An object mapping field names to default values
41
- * @returns The coerced field values
42
- */
43
- export default async function readForm<Spec extends Record<string, unknown>>(
44
- request: Request | FormData,
45
- spec: Spec,
46
- ): Promise<FormValues<Spec>> {
47
- const formData = request instanceof FormData ? request : await request.formData();
48
- const result: Record<string, unknown> = {};
49
- for (const key of Object.keys(spec)) {
50
- const defaultValue = spec[key];
51
- // oxlint-disable-next-line typescript/no-base-to-string
52
- const values = formData.getAll(key).map((v) => v.toString());
53
- result[key] = Array.isArray(defaultValue)
54
- ? values.map((value) => coerceValue(value, defaultValue[0]))
55
- : coerceValue(values[0], defaultValue);
56
- }
57
- return result as FormValues<Spec>;
58
- }
59
-
60
- function coerceValue(value: string | undefined, defaultValue: unknown): unknown {
61
- if (typeof defaultValue === "number") {
62
- const n = value === undefined || value === "" ? NaN : Number(value);
63
- return Number.isNaN(n) ? defaultValue : n;
64
- }
65
- if (typeof defaultValue === "boolean") {
66
- // Unchecked checkboxes are not submitted at all
67
- if (value === undefined) return false;
68
- return !(value === "" || value === "false" || value === "off");
69
- }
70
- return value ?? defaultValue ?? "";
71
- }
package/src/form.ts DELETED
@@ -1,4 +0,0 @@
1
- import readForm from "./form/readForm";
2
-
3
- export { readForm };
4
- export type { FormValues } from "./form/readForm";
package/src/index.ts DELETED
@@ -1,82 +0,0 @@
1
- import Router from "./site/Router";
2
- import Site from "./site/Site";
3
- import type Adapter from "./types/Adapter";
4
- import type { Jsonify } from "./types/Jsonify";
5
- import type { MergePageData, PageData } from "./types/PageData";
6
- import type { PageForm } from "./types/PageForm";
7
- import type PageEndPoint from "./types/PageEndPoint";
8
- import type PageLoadEvent from "./types/PageLoadEvent";
9
- import type { PageLoadReturn } from "./types/PageLoadReturn";
10
- import type PageProps from "./types/PageProps";
11
- import type {
12
- ParseRouteParams,
13
- RouteArgs,
14
- RouteArgsOf,
15
- RouteParamsOf,
16
- } from "./types/ParseRouteParams";
17
- import type PageServerAction from "./types/PageServerAction";
18
- import type PageServerEndPoint from "./types/PageServerEndPoint";
19
- import type {
20
- ActionBody,
21
- LoadParams,
22
- LoadQuery,
23
- PageServerActionSchemas,
24
- } from "./types/PageServerEndPoint";
25
- import type PageServerLoad from "./types/PageServerLoad";
26
- import type TypedResponse from "./response/TypedResponse";
27
- import type { UntypedResponse } from "./response/TypedResponse";
28
- import type ServerEndPoint from "./types/ServerEndPoint";
29
- import type {
30
- ParamsOf,
31
- SchemaBody,
32
- SchemaQuery,
33
- ServerEndPointSchemas,
34
- } from "./types/ServerEndPoint";
35
- import type ServerHook from "./types/ServerHook";
36
- import type ServerLoadEvent from "./types/ServerLoadEvent";
37
- import type { FormDataRecord, QueryRecord } from "./types/ServerLoadEvent";
38
- import type ServerRequest from "./types/ServerRequest";
39
- import type { StandardSchemaV1 } from "./types/StandardSchema";
40
- import type SitePlugin from "./types/SitePlugin";
41
-
42
- // NOTE: Don't export any general functionality from here -- it may result in
43
- // Vite errors like `Could not resolve '../pkg' in lightningcss` etc
44
-
45
- export { Site, Router };
46
-
47
- export type {
48
- Adapter,
49
- PageEndPoint,
50
- PageServerEndPoint,
51
- PageServerActionSchemas,
52
- ActionBody,
53
- LoadQuery,
54
- LoadParams,
55
- PageServerLoad,
56
- PageServerAction,
57
- ServerEndPoint,
58
- ServerEndPointSchemas,
59
- SchemaBody,
60
- SchemaQuery,
61
- ParamsOf,
62
- ServerRequest,
63
- ServerHook,
64
- ServerLoadEvent,
65
- SitePlugin,
66
- FormDataRecord,
67
- QueryRecord,
68
- StandardSchemaV1,
69
- PageLoadEvent,
70
- ParseRouteParams,
71
- RouteArgs,
72
- RouteArgsOf,
73
- RouteParamsOf,
74
- Jsonify,
75
- TypedResponse,
76
- UntypedResponse,
77
- PageData,
78
- MergePageData,
79
- PageForm,
80
- PageLoadReturn,
81
- PageProps,
82
- };
@@ -1,79 +0,0 @@
1
- import type { ApiMethods } from "./api";
2
- import makeApi from "./api";
3
- import ok from "../response/ok";
4
- import type TypedResponse from "../response/TypedResponse";
5
- import type ServerLoadEvent from "../types/ServerLoadEvent";
6
-
7
- // A sample endpoint shape, as inferred from a `+server` default export
8
- interface TimeEndPoint {
9
- get: (event: ServerLoadEvent<"/api/time">) => Promise<TypedResponse<{ time: number }>>;
10
- post: (event: ServerLoadEvent<"/api/time">) => Promise<Response>;
11
- }
12
-
13
- // An endpoint whose handler annotates an expected request body
14
- interface CreatePostEndPoint {
15
- post: (
16
- event: ServerLoadEvent<"/api/posts", { title: string }>,
17
- ) => Promise<TypedResponse<{ id: number }>>;
18
- }
19
-
20
- type Equals<A, B> =
21
- (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? true : false;
22
- type Expect<T extends true> = T;
23
-
24
- // The get caller resolves to the typed JSON body (or a raw Response)
25
- export type R01 = Expect<
26
- Equals<
27
- ApiMethods<TimeEndPoint>["get"],
28
- (body?: BodyInit | object, init?: RequestInit) => Promise<{ time: number } | Response>
29
- >
30
- >;
31
-
32
- // Handlers that return a plain Response fall back to unknown
33
- export type R02 = Expect<
34
- Equals<
35
- ApiMethods<TimeEndPoint>["post"],
36
- (body?: BodyInit | object, init?: RequestInit) => Promise<unknown>
37
- >
38
- >;
39
-
40
- // Only defined handlers are callable
41
- export type R03 = Expect<Equals<keyof ApiMethods<TimeEndPoint>, "get" | "post">>;
42
-
43
- // An annotated event body types the client call's body param
44
- export type R04 = Expect<
45
- Equals<
46
- ApiMethods<CreatePostEndPoint>["post"],
47
- (body?: { title: string }, init?: RequestInit) => Promise<{ id: number } | Response>
48
- >
49
- >;
50
-
51
- // Usage: params are enforced by the route path
52
- export const timeApi: ApiMethods<TimeEndPoint> = makeApi<"/api/time", TimeEndPoint>("/api/time");
53
- export const postApi: ApiMethods<TimeEndPoint> = makeApi<"/api/posts/[id]", TimeEndPoint>(
54
- "/api/posts/[id]",
55
- {
56
- id: "5",
57
- },
58
- );
59
- // @ts-expect-error missing params
60
- void makeApi<"/api/posts/[id]", TimeEndPoint>("/api/posts/[id]");
61
- // @ts-expect-error params are not accepted for static paths
62
- void makeApi<"/api/time", TimeEndPoint>("/api/time", {});
63
- // @ts-expect-error 'nope' is not a param of /api/posts/[id]
64
- void makeApi<"/api/posts/[id]", TimeEndPoint>("/api/posts/[id]", { nope: "1" });
65
-
66
- // Usage: an annotated body is checked at the call site
67
- export const createApi: ApiMethods<CreatePostEndPoint> = makeApi<"/api/posts", CreatePostEndPoint>(
68
- "/api/posts",
69
- );
70
- void createApi.post({ title: "Hello" });
71
- // @ts-expect-error 'name' is not part of the endpoint's expected body
72
- void createApi.post({ name: "Hello" });
73
- // @ts-expect-error 'title' is required
74
- void createApi.post({});
75
-
76
- // ok() typing: object bodies are typed, strings are not
77
- export const typed: TypedResponse<{ time: number }> = ok({ time: 5 });
78
- export const untypedResponse: Response = ok("plain");
79
- export const noBodyResponse: Response = ok();
package/src/nav/api.ts DELETED
@@ -1,104 +0,0 @@
1
- import type { ExactRouteParams, ParseRouteParams } from "../types/ParseRouteParams";
2
- import type TypedResponse from "../response/TypedResponse";
3
- import route from "./route";
4
-
5
- /**
6
- * The value a client call resolves to: the endpoint's typed JSON body when it
7
- * returns a typed response, or the raw Response when the body isn't JSON.
8
- * Untyped endpoints resolve to `unknown`.
9
- */
10
- type ApiResult<Handler> = Handler extends (event: any) => any
11
- ? Awaited<ReturnType<Handler>> extends TypedResponse<infer Body>
12
- ? Body | Response
13
- : unknown
14
- : never;
15
-
16
- /**
17
- * The body a client call accepts: the endpoint event's annotated JSON body
18
- * type (from `ServerLoadEvent<Route, Body>`), or a loose value when the
19
- * handler doesn't annotate one.
20
- */
21
- type ApiRequestBody<Handler> = Handler extends (event: infer Event) => any
22
- ? Event extends { json: () => Promise<infer Body> }
23
- ? unknown extends Body
24
- ? BodyInit | object
25
- : Body
26
- : BodyInit | object
27
- : BodyInit | object;
28
-
29
- /** The callable methods of an endpoint, one per handler it defines. */
30
- export type ApiMethods<Endpoint extends object> = {
31
- [Method in string & keyof Endpoint as NonNullable<Endpoint[Method]> extends (event: any) => any
32
- ? Method
33
- : never]: (
34
- body?: ApiRequestBody<NonNullable<Endpoint[Method]>>,
35
- init?: RequestInit,
36
- ) => Promise<ApiResult<NonNullable<Endpoint[Method]>>>;
37
- };
38
-
39
- const METHODS = ["get", "post", "patch", "put", "del", "options", "head"] as const;
40
-
41
- /**
42
- * Creates typed client callers for a `+server` endpoint, e.g.
43
- *
44
- * ```ts
45
- * import type endpoint from "@/routes/api/posts/[id]/+server";
46
- * const post = makeApi<"/api/posts/[id]", typeof endpoint>("/api/posts/[id]");
47
- * const data = await post.get(); // typed from the endpoint's responses
48
- * ```
49
- *
50
- * Method names match the endpoint's handlers (`del` for DELETE). Params are
51
- * filled in and URI-encoded from the route path, and JSON responses are
52
- * parsed; non-JSON responses resolve to the raw Response. Failed requests
53
- * (non-2xx) throw.
54
- *
55
- * @param path The endpoint's route path
56
- * @param params The route params, required if the path has dynamic segments
57
- * @returns An object with one caller per handler defined by the endpoint
58
- */
59
- export default function makeApi<
60
- Route extends string,
61
- Endpoint extends object,
62
- Params extends ParseRouteParams<Route> = ParseRouteParams<Route>,
63
- >(
64
- path: Route,
65
- // NOTE: The rest args conditional must stay INLINE — routing it through a
66
- // type alias defeats `Params` inference, and excess keys stop being checked
67
- ...args: string extends Route
68
- ? [params?: Record<string, string>]
69
- : keyof ParseRouteParams<Route> extends never
70
- ? []
71
- : [params: Params & ExactRouteParams<Params, ParseRouteParams<Route>>]
72
- ): ApiMethods<Endpoint> {
73
- const url = route(path as string, ...(args as [params?: Record<string, string>]));
74
- const api: Record<string, (body?: unknown, init?: RequestInit) => Promise<unknown>> = {};
75
- for (const method of METHODS) {
76
- api[method] = (body, init) => request(method, url, body, init);
77
- }
78
- return api as ApiMethods<Endpoint>;
79
- }
80
-
81
- async function request(
82
- method: string,
83
- url: string,
84
- body: unknown,
85
- init?: RequestInit,
86
- ): Promise<unknown> {
87
- // `del` is the endpoint handler name for DELETE requests
88
- const httpMethod = method === "del" ? "delete" : method;
89
- const options: RequestInit = { method: httpMethod.toUpperCase(), ...init };
90
- if (body !== undefined && options.body === undefined && method !== "get" && method !== "head") {
91
- if (typeof body === "object") {
92
- options.headers ??= { "Content-Type": "application/json" };
93
- options.body = JSON.stringify(body);
94
- } else {
95
- options.body = body as BodyInit;
96
- }
97
- }
98
- const response = await fetch(url, options);
99
- if (!response.ok) {
100
- throw new Error(`API ${method.toUpperCase()} ${url} failed: ${response.status}`);
101
- }
102
- const contentType = response.headers.get("Content-Type") ?? "";
103
- return contentType.includes("application/json") ? await response.json() : response;
104
- }
@@ -1,70 +0,0 @@
1
- import $page from "../state/$page";
2
- import load from "./load";
3
- import reload from "./reload";
4
-
5
- export default async function formSubmit(e: SubmitEvent): Promise<void> {
6
- // We'll take it from here
7
- e.preventDefault();
8
-
9
- // Reset $page on submit and link navigation
10
- // TODO: Should we put data in $page.data??
11
- $page.form = undefined;
12
-
13
- // Perform a POST fetch to the form's action location
14
- const form = e.target as HTMLFormElement;
15
- const button = e.submitter as HTMLButtonElement;
16
- // HACK: submit buttons have their formAction set to the current page if not
17
- // set, so we can't just check whether it's empty and fallback to form action
18
- //const action = button?.formAction ?? form.action;
19
- let action = form.action || document.URL;
20
- if (button && button.formAction && button.formAction !== document.URL) {
21
- action = button.formAction;
22
- }
23
- const options = {
24
- body: new FormData(form),
25
- method: "POST",
26
- mode: "cors",
27
- credentials: "same-origin",
28
- // Add a special header which tells the server that we want the raw
29
- // error response (if applicable) rather than the reloaded page that you
30
- // would get if submitting a page without javascript
31
- headers: {
32
- "X-Torpor-Form-Submit": "",
33
- },
34
- };
35
- const response = await fetch(
36
- action,
37
- // @ts-ignore -- don't know what it's complaining about here
38
- options,
39
- );
40
-
41
- if (
42
- response.status === 200 &&
43
- response.headers.has("Content-Disposition") &&
44
- /attachment;\s*filename="(.+?)"/.test(response.headers.get("Content-Disposition")!)
45
- ) {
46
- // TODO: Is this enough to check to see if we have a file that should download?
47
- // Download the file by creating a dummy <a> and clicking it
48
- const downloadFileName =
49
- response.headers.get("Content-Disposition")?.match(/attachment;\s*filename="(.+?)"/)![1] ??
50
- "file";
51
- const downloadLink = document.createElement("a");
52
- downloadLink.href = window.URL.createObjectURL(await response.blob());
53
- downloadLink.download = downloadFileName;
54
- downloadLink.click();
55
- } else if (response.status === 200 && response.headers.has("X-Torpor-Form-Redirect")) {
56
- // TODO: Should do the correct type of redirect e.g. seeOther etc
57
- const redirect = response.headers.get("Location")!;
58
- await load(redirect);
59
- window.location.href = redirect;
60
- } else if (
61
- (response.status >= 200 && response.status <= 299) ||
62
- (response.status >= 400 && response.status <= 499)
63
- ) {
64
- // Put the response into `$page.form`, and it will be put into `$props` in reload
65
- if (response.headers.get("Content-Type") === "application/json") {
66
- $page.form = await response.json();
67
- }
68
- await reload();
69
- }
70
- }
package/src/nav/load.ts DELETED
@@ -1,9 +0,0 @@
1
- import navigate from "./navigate";
2
-
3
- /**
4
- * Loads and renders the page at the supplied path.
5
- */
6
- export default async function load(path: string): Promise<boolean> {
7
- const url = new URL(path, document.location.href);
8
- return await navigate(url);
9
- }
@@ -1,134 +0,0 @@
1
- import client from "../state/client";
2
- import type LayoutPath from "../types/LayoutPath";
3
- import type PageEndPoint from "../types/PageEndPoint";
4
- import type PageServerEndPoint from "../types/PageServerEndPoint";
5
- import type RouteHandler from "../types/RouteHandler";
6
-
7
- export default async function loadData(
8
- handler: RouteHandler,
9
- params: Record<string, string>,
10
- path: string,
11
- query: URLSearchParams,
12
- newLayoutStack: LayoutPath[],
13
- clientEndPoint: PageEndPoint | undefined,
14
- serverEndPoint: PageServerEndPoint | undefined,
15
- prefetch = false,
16
- ): Promise<Record<string, string> | void> {
17
- let data = {};
18
- if (handler.layouts) {
19
- let layoutStack = client.layoutStack;
20
- for (let [i, layout] of handler.layouts.entries()) {
21
- let layoutPath = layout.path;
22
- for (let key in params) {
23
- layoutPath = layoutPath.replace(`[${key}]`, params[key]);
24
- }
25
- if (layoutStack.at(i)?.path === layoutPath) {
26
- // We've already loaded this layout, we can just re-use its data and UI
27
- if (!prefetch) {
28
- layoutStack[i].reuse = true;
29
- }
30
- newLayoutStack[i] = layoutStack[i];
31
- Object.assign(data, layoutStack[i].data);
32
- } else {
33
- const stackLayout = { path: layoutPath, data: {}, reuse: false, slotRegion: null };
34
- const layoutEndPoint: PageEndPoint | undefined = (await layout.endPoint())?.default;
35
- const layoutServerEndPoint: PageServerEndPoint | undefined =
36
- layout.serverEndPoint && (await layout.serverEndPoint())?.default;
37
- const layoutResponse = await loadClientAndServerData(
38
- stackLayout.data,
39
- document.location.origin + layoutPath,
40
- query,
41
- params,
42
- layoutEndPoint,
43
- layoutServerEndPoint,
44
- );
45
- if (layoutResponse?.ok === false) {
46
- return;
47
- }
48
- Object.assign(data, stackLayout.data);
49
- newLayoutStack.push(stackLayout);
50
- }
51
- }
52
- }
53
- let endPointResponse = await loadClientAndServerData(
54
- data,
55
- document.location.origin + path,
56
- query,
57
- params,
58
- clientEndPoint,
59
- serverEndPoint,
60
- );
61
- if (endPointResponse?.ok === false) {
62
- return;
63
- }
64
- return data;
65
- }
66
-
67
- async function loadClientAndServerData(
68
- data: Record<string, any>,
69
- location: string,
70
- query: URLSearchParams,
71
- params: Record<string, string>,
72
- clientEndPoint?: PageEndPoint,
73
- serverEndPoint?: PageServerEndPoint,
74
- ): Promise<Response | undefined | void> {
75
- let prefetchedData = client.prefetchedData;
76
-
77
- if (clientEndPoint?.load) {
78
- const clientKey = location + (query.size > 0 ? `?${query}` : "");
79
- if (prefetchedData[clientKey]) {
80
- Object.assign(data, prefetchedData[clientKey]);
81
- } else {
82
- const clientUrl = new URL(document.location.href);
83
- for (let [name, value] of query) {
84
- clientUrl.searchParams.append(name, value);
85
- }
86
- const clientParams = buildClientParams(clientUrl, params, data);
87
- const clientResponse = await clientEndPoint.load(clientParams);
88
- if (clientResponse) {
89
- if (clientResponse.ok) {
90
- if (clientResponse.headers.get("Content-Type")?.includes("application/json")) {
91
- const clientData = await clientResponse.json();
92
- Object.assign(data, clientData);
93
- prefetchedData[clientKey] = clientData;
94
- }
95
- } else {
96
- return clientResponse;
97
- }
98
- }
99
- }
100
- }
101
-
102
- if (serverEndPoint?.load) {
103
- const serverLocation = location.replace(/\/$/, "") + "/~server";
104
- const serverKey = serverLocation + (query.size > 0 ? `?${query}` : "");
105
- if (prefetchedData[serverKey]) {
106
- Object.assign(data, prefetchedData[serverKey]);
107
- } else {
108
- const serverUrl = new URL(serverLocation);
109
- for (let [name, value] of query) {
110
- serverUrl.searchParams.append(name, value);
111
- }
112
- const serverResponse = await fetch(serverUrl);
113
- if (serverResponse) {
114
- if (serverResponse.ok) {
115
- if (serverResponse.headers.get("Content-Type")?.includes("application/json")) {
116
- const serverData = await serverResponse.json();
117
- Object.assign(data, serverData);
118
- prefetchedData[serverKey] = serverData;
119
- }
120
- } else {
121
- return serverResponse;
122
- }
123
- }
124
- }
125
- }
126
- }
127
-
128
- function buildClientParams(url: URL, params: Record<string, string>, data: Record<string, any>) {
129
- return {
130
- url,
131
- params,
132
- data,
133
- };
134
- }