@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.
- package/CHANGELOG.md +42 -0
- package/dist/RouteType-g8Ce5gOd.js +107 -0
- package/dist/RouteType-g8Ce5gOd.js.map +1 -0
- package/dist/Server-CSpY_-Ba.d.ts +78 -0
- package/dist/Server-CSpY_-Ba.d.ts.map +1 -0
- package/dist/ServerEvent-2-CnAy1W.js +74 -0
- package/dist/ServerEvent-2-CnAy1W.js.map +1 -0
- package/dist/Site-D4x1l0p5.d.ts +67 -0
- package/dist/Site-D4x1l0p5.d.ts.map +1 -0
- package/dist/_page-Cv6YWocY.js +33 -0
- package/dist/_page-Cv6YWocY.js.map +1 -0
- package/dist/bin/index.d.ts +1 -1
- package/dist/bin/index.js +14 -19
- package/dist/bin/index.js.map +1 -1
- package/dist/connectMiddleware-DbLj0St1.js +252 -0
- package/dist/connectMiddleware-DbLj0St1.js.map +1 -0
- package/dist/index.d.ts +188 -179
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +109 -145
- package/dist/index.js.map +1 -1
- package/dist/nav.d.ts +14 -0
- package/dist/nav.d.ts.map +1 -0
- package/dist/nav.js +206 -0
- package/dist/nav.js.map +1 -0
- package/dist/pathToRegex-CTgx7hQP.js +11 -0
- package/dist/pathToRegex-CTgx7hQP.js.map +1 -0
- package/dist/response-D-XpIuMH.js +307 -0
- package/dist/response-D-XpIuMH.js.map +1 -0
- package/dist/response.d.ts +336 -151
- package/dist/response.d.ts.map +1 -0
- package/dist/response.js +4 -37
- package/dist/run-CVKpO0HO.js +331 -0
- package/dist/run-CVKpO0HO.js.map +1 -0
- package/dist/run.d.ts +11 -8
- package/dist/run.d.ts.map +1 -0
- package/dist/run.js +8 -18
- package/dist/seeOther-BmehiI4C.js +110 -0
- package/dist/seeOther-BmehiI4C.js.map +1 -0
- package/dist/server.d.ts +12 -11
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +5 -18
- package/dist/state.d.ts +14 -10
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +3 -7
- package/dist/test.d.ts +12 -11
- package/dist/test.d.ts.map +1 -0
- package/dist/test.js +152 -225
- package/dist/test.js.map +1 -1
- package/package.json +25 -29
- package/src/bin/index.ts +9 -11
- package/src/index.ts +3 -0
- package/src/nav/formSubmit.ts +48 -0
- package/src/nav/load.ts +9 -0
- package/src/nav/loadData.ts +121 -0
- package/src/nav/navigate.ts +163 -0
- package/src/nav/reload.ts +9 -0
- package/src/nav.ts +4 -0
- package/src/response/badRequest.ts +9 -4
- package/src/response/created.ts +10 -3
- package/src/response/forbidden.ts +11 -4
- package/src/response/found.ts +30 -0
- package/src/response/methodNotAllowed.ts +8 -4
- package/src/response/movedPermanently.ts +25 -0
- package/src/response/notFound.ts +14 -7
- package/src/response/notModified.ts +24 -4
- package/src/response/ok.ts +19 -10
- package/src/response/permanentRedirect.ts +30 -0
- package/src/response/seeOther.ts +9 -3
- package/src/response/serverError.ts +14 -2
- package/src/response/temporaryRedirect.ts +31 -0
- package/src/response/unauthorized.ts +11 -4
- package/src/response/unprocessable.ts +8 -2
- package/src/response.ts +8 -4
- package/src/{site → run}/prepareTemplate.ts +1 -1
- package/src/{site → run}/run.ts +1 -1
- package/src/{site → run}/runBuild.ts +2 -2
- package/src/{site → run}/runDev.ts +2 -2
- package/src/{site → run}/runPreview.ts +1 -1
- package/src/run.ts +4 -4
- package/src/server/Routerx.ts +3 -3
- package/src/server/Server.ts +3 -3
- package/src/server/connect/connectMiddleware.ts +2 -1
- package/src/server/connect/nodeMessageToNodeResponse.ts +2 -2
- package/src/site/Router.ts +3 -3
- package/src/site/clientEntry.ts +16 -269
- package/src/site/defaultAdapter.ts +1 -1
- package/src/site/serverEntry.ts +86 -45
- package/src/state/$page.ts +3 -12
- package/src/state/client.ts +6 -0
- package/src/state/internal.ts +45 -0
- package/src/test/runTest.ts +1 -1
- package/src/types/Adapter.ts +2 -4
- package/src/types/ClientState.ts +8 -0
- package/src/types/InternalState.ts +7 -0
- package/src/types/LayoutHandler.ts +2 -4
- package/src/types/LayoutPath.ts +10 -0
- package/src/types/ManifestRoute.ts +2 -4
- package/src/types/PageEndPoint.ts +2 -4
- package/src/types/PageLoadEvent.ts +2 -4
- package/src/types/PageServerEndPoint.ts +2 -4
- package/src/types/PageState.ts +8 -0
- package/src/types/RouteHandler.ts +2 -4
- package/src/types/RouteLayoutHandler.ts +2 -4
- package/src/types/RouteMatchResult.ts +2 -4
- package/src/types/ServerHook.ts +3 -7
- package/src/types/ServerLoadEvent.ts +2 -4
- package/src/{site → utils}/pathToRegex.ts +1 -1
- package/{tsup.config.ts → tsdown.config.ts} +3 -4
- package/dist/Server-CNZWh5ca.d.cts +0 -71
- package/dist/Server-CNZWh5ca.d.ts +0 -71
- package/dist/Site-C2020GV_.d.ts +0 -63
- package/dist/Site-DQojGpE-.d.cts +0 -63
- package/dist/bin/index.cjs +0 -778
- package/dist/bin/index.cjs.map +0 -1
- package/dist/bin/index.d.cts +0 -1
- package/dist/chunk-565UOT3F.js +0 -18
- package/dist/chunk-565UOT3F.js.map +0 -1
- package/dist/chunk-B2UNTYN5.js +0 -68
- package/dist/chunk-B2UNTYN5.js.map +0 -1
- package/dist/chunk-CZHJQCPI.js +0 -286
- package/dist/chunk-CZHJQCPI.js.map +0 -1
- package/dist/chunk-PTVHEJZ5.js +0 -152
- package/dist/chunk-PTVHEJZ5.js.map +0 -1
- package/dist/chunk-SJVHHGVW.js +0 -13
- package/dist/chunk-SJVHHGVW.js.map +0 -1
- package/dist/chunk-TDOXEXG6.js +0 -85
- package/dist/chunk-TDOXEXG6.js.map +0 -1
- package/dist/chunk-WVXAN4IV.js +0 -50
- package/dist/chunk-WVXAN4IV.js.map +0 -1
- package/dist/chunk-YRBEYKQM.js +0 -372
- package/dist/chunk-YRBEYKQM.js.map +0 -1
- package/dist/index.cjs +0 -322
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -199
- package/dist/metafile-cjs.json +0 -1
- package/dist/metafile-esm.json +0 -1
- package/dist/response.cjs +0 -150
- package/dist/response.cjs.map +0 -1
- package/dist/response.d.cts +0 -166
- package/dist/response.js.map +0 -1
- package/dist/run.cjs +0 -787
- package/dist/run.cjs.map +0 -1
- package/dist/run.d.cts +0 -14
- package/dist/run.js.map +0 -1
- package/dist/server.cjs +0 -398
- package/dist/server.cjs.map +0 -1
- package/dist/server.d.cts +0 -17
- package/dist/server.js.map +0 -1
- package/dist/state.cjs +0 -44
- package/dist/state.cjs.map +0 -1
- package/dist/state.d.cts +0 -11
- package/dist/state.js.map +0 -1
- package/dist/test.cjs +0 -538
- package/dist/test.cjs.map +0 -1
- package/dist/test.d.cts +0 -15
- package/src/response/moved.ts +0 -16
- package/src/response/redirect.ts +0 -17
- package/src/state/Page.ts +0 -8
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import transfer from "./transfer";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 308 Permanent Redirect
|
|
5
|
+
*
|
|
6
|
+
* The HTTP 308 Permanent Redirect redirection response status code indicates
|
|
7
|
+
* that the requested resource has been permanently moved to the URL given by
|
|
8
|
+
* the Location header.
|
|
9
|
+
*
|
|
10
|
+
* A browser receiving this status will automatically request the resource at
|
|
11
|
+
* the URL in the Location header, redirecting the user to the new page. Search
|
|
12
|
+
* engines receiving this response will attribute links to the original URL to
|
|
13
|
+
* the redirected resource, passing the SEO ranking to the new URL.
|
|
14
|
+
*
|
|
15
|
+
* The request method and the body will not be modified by the client in the
|
|
16
|
+
* redirected request. A 301 Moved Permanently requires the request method and
|
|
17
|
+
* the body to remain unchanged when redirection is performed, but this is
|
|
18
|
+
* incorrectly handled by older clients to use the GET method instead.
|
|
19
|
+
*
|
|
20
|
+
* > Note: Some Web applications may use the 308 Permanent Redirect in a
|
|
21
|
+
* > non-standard way and for different purposes. For example, Google Drive uses
|
|
22
|
+
* > a 308 Resume Incomplete response to indicate to the client when an
|
|
23
|
+
* > unfinished upload has stalled. See Perform a resumable download on the
|
|
24
|
+
* > Google Drive documentation for more information.
|
|
25
|
+
*
|
|
26
|
+
* See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/308
|
|
27
|
+
*/
|
|
28
|
+
export default function permanentRedirect(location: string): Response {
|
|
29
|
+
return transfer(308, location);
|
|
30
|
+
}
|
package/src/response/seeOther.ts
CHANGED
|
@@ -3,10 +3,16 @@ import transfer from "./transfer";
|
|
|
3
3
|
/**
|
|
4
4
|
* 303 See Other
|
|
5
5
|
*
|
|
6
|
-
* The
|
|
7
|
-
*
|
|
6
|
+
* The HTTP 303 See Other redirection response status code indicates that the
|
|
7
|
+
* browser should redirect to the URL in the Location header instead of
|
|
8
|
+
* rendering the requested resource.
|
|
8
9
|
*
|
|
9
|
-
*
|
|
10
|
+
* This response code is often sent back as a result of PUT or POST methods so
|
|
11
|
+
* the client may retrieve a confirmation, or view a representation of a
|
|
12
|
+
* real-world object (see HTTP range-14). The method to retrieve the redirected
|
|
13
|
+
* resource is always GET.
|
|
14
|
+
*
|
|
15
|
+
* See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/303
|
|
10
16
|
*/
|
|
11
17
|
export default function seeOther(location: string): Response {
|
|
12
18
|
return transfer(303, location);
|
|
@@ -3,9 +3,21 @@ import response from "./response";
|
|
|
3
3
|
/**
|
|
4
4
|
* 500 Server Error
|
|
5
5
|
*
|
|
6
|
-
* The
|
|
6
|
+
* The HTTP 500 Internal Server Error server error response status code
|
|
7
|
+
* indicates that the server encountered an unexpected condition that prevented
|
|
8
|
+
* it from fulfilling the request. This error is a generic "catch-all" response
|
|
9
|
+
* to server issues, indicating that the server cannot find a more appropriate
|
|
10
|
+
* 5XX error to respond with.
|
|
7
11
|
*
|
|
8
|
-
*
|
|
12
|
+
* If you're a visitor seeing 500 errors on a web page, these issues require
|
|
13
|
+
* investigation by server owners or administrators. There are many possible
|
|
14
|
+
* causes of 500 errors, including: improper server configuration, out-of-memory
|
|
15
|
+
* (OOM) issues, unhandled exceptions, improper file permissions, or other
|
|
16
|
+
* complex factors. Server administrators may proactively log occurrences of
|
|
17
|
+
* server error responses, like the 500 status code, with details about the
|
|
18
|
+
* initiating requests to improve the stability of a service in the future.
|
|
19
|
+
*
|
|
20
|
+
* See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/500
|
|
9
21
|
*/
|
|
10
22
|
export default function serverError(body?: object | string): Response {
|
|
11
23
|
return response(500, body ?? "Server error");
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import transfer from "./transfer";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 307 Temporary Redirect
|
|
5
|
+
*
|
|
6
|
+
* The HTTP 307 Temporary Redirect redirection response status code indicates
|
|
7
|
+
* that the resource requested has been temporarily moved to the URL in the
|
|
8
|
+
* Location header.
|
|
9
|
+
*
|
|
10
|
+
* A browser receiving this status will automatically request the resource at
|
|
11
|
+
* the URL in the Location header, redirecting the user to the new page. Search
|
|
12
|
+
* engines receiving this response will not attribute links to the original URL
|
|
13
|
+
* to the new resource, meaning no SEO value is transferred to the new URL.
|
|
14
|
+
*
|
|
15
|
+
* The method and the body of the original request are reused to perform the
|
|
16
|
+
* redirected request. In the cases where you want the request method to be
|
|
17
|
+
* changed to GET, use 303 See Other instead. This is useful when you want to
|
|
18
|
+
* give an answer to a successful PUT request that is not the uploaded resource,
|
|
19
|
+
* but a status monitor or confirmation message like "You have successfully
|
|
20
|
+
* uploaded XYZ".
|
|
21
|
+
*
|
|
22
|
+
* The difference between 307 and 302 is that 307 guarantees that the client
|
|
23
|
+
* will not change the request method and body when the redirected request is
|
|
24
|
+
* made. With 302, older clients incorrectly changed the method to GET. 307 and
|
|
25
|
+
* 302 responses are identical when the request method is GET.
|
|
26
|
+
*
|
|
27
|
+
* See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/307
|
|
28
|
+
*/
|
|
29
|
+
export default function temporaryRedirect(location: string): Response {
|
|
30
|
+
return transfer(307, location);
|
|
31
|
+
}
|
|
@@ -3,11 +3,18 @@ import response from "./response";
|
|
|
3
3
|
/**
|
|
4
4
|
* 401 Unauthorized
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* The HTTP 401 Unauthorized client error response status code indicates that a
|
|
7
|
+
* request was not successful because it lacks valid authentication credentials
|
|
8
|
+
* for the requested resource. This status code is sent with an HTTP
|
|
9
|
+
* WWW-Authenticate response header that contains information on the
|
|
10
|
+
* authentication scheme the server expects the client to include to make the
|
|
11
|
+
* request successfully.
|
|
9
12
|
*
|
|
10
|
-
*
|
|
13
|
+
* A 401 Unauthorized is similar to the 403 Forbidden response, except that a
|
|
14
|
+
* 403 is returned when a request contains valid credentials, but the client
|
|
15
|
+
* does not have permissions to perform a certain action.
|
|
16
|
+
*
|
|
17
|
+
* See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/401
|
|
11
18
|
*/
|
|
12
19
|
export default function unauthorized(body?: object | string): Response {
|
|
13
20
|
return response(401, body ?? "Unauthorized");
|
|
@@ -3,9 +3,15 @@ import response from "./response";
|
|
|
3
3
|
/**
|
|
4
4
|
* 422 Unprocessable Content
|
|
5
5
|
*
|
|
6
|
-
* The
|
|
6
|
+
* The HTTP 422 Unprocessable Content client error response status code
|
|
7
|
+
* indicates that the server understood the content type of the request content,
|
|
8
|
+
* and the syntax of the request content was correct, but it was unable to
|
|
9
|
+
* process the contained instructions.
|
|
7
10
|
*
|
|
8
|
-
*
|
|
11
|
+
* Clients that receive a 422 response should expect that repeating the request
|
|
12
|
+
* without modification will fail with the same error.
|
|
13
|
+
*
|
|
14
|
+
* See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/422
|
|
9
15
|
*/
|
|
10
16
|
export default function unprocessable(body?: object | string): Response {
|
|
11
17
|
return response(422, body ?? "Unprocessable");
|
package/src/response.ts
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import badRequest from "./response/badRequest";
|
|
2
2
|
import created from "./response/created";
|
|
3
3
|
import forbidden from "./response/forbidden";
|
|
4
|
+
import found from "./response/found";
|
|
4
5
|
import methodNotAllowed from "./response/methodNotAllowed";
|
|
5
|
-
import
|
|
6
|
+
import movedPermanently from "./response/movedPermanently";
|
|
6
7
|
import notFound from "./response/notFound";
|
|
7
8
|
import notModified from "./response/notModified";
|
|
8
9
|
import ok from "./response/ok";
|
|
9
|
-
import
|
|
10
|
+
import permanentRedirect from "./response/permanentRedirect";
|
|
10
11
|
import response from "./response/response";
|
|
11
12
|
import seeOther from "./response/seeOther";
|
|
12
13
|
import serverError from "./response/serverError";
|
|
14
|
+
import temporaryRedirect from "./response/temporaryRedirect";
|
|
13
15
|
import transfer from "./response/transfer";
|
|
14
16
|
import unauthorized from "./response/unauthorized";
|
|
15
17
|
import unprocessable from "./response/unprocessable";
|
|
@@ -19,10 +21,12 @@ export {
|
|
|
19
21
|
ok,
|
|
20
22
|
created,
|
|
21
23
|
transfer,
|
|
24
|
+
movedPermanently,
|
|
25
|
+
found,
|
|
22
26
|
seeOther,
|
|
23
27
|
notModified,
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
temporaryRedirect,
|
|
29
|
+
permanentRedirect,
|
|
26
30
|
badRequest,
|
|
27
31
|
unauthorized,
|
|
28
32
|
forbidden,
|
|
@@ -11,7 +11,7 @@ export default function prepareTemplate(template: string, clientScript: string):
|
|
|
11
11
|
|
|
12
12
|
// Put %COMPONENT_BODY% inside <div id="app"></div>
|
|
13
13
|
// This is where the component's HTML will go
|
|
14
|
-
let bodyStart = regexIndexOf(result,
|
|
14
|
+
let bodyStart = regexIndexOf(result, /<div\s+id=("app"|'app'|app)\s+/);
|
|
15
15
|
bodyStart = result.indexOf(">", bodyStart) + 1;
|
|
16
16
|
let bodyEnd = result.indexOf("</div>", bodyStart);
|
|
17
17
|
if (bodyStart === -1 || bodyEnd === -1) {
|
package/src/{site → run}/run.ts
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { transformWithEsbuild } from "vite";
|
|
4
|
-
import Site from "
|
|
4
|
+
import Site from "../site/Site";
|
|
5
5
|
import runBuild from "./runBuild";
|
|
6
6
|
import runDev from "./runDev";
|
|
7
7
|
import runPreview from "./runPreview";
|
|
@@ -2,8 +2,8 @@ import torpor from "@torpor/unplugin/vite";
|
|
|
2
2
|
import { existsSync, promises as fs } from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { build, defineConfig } from "vite";
|
|
5
|
-
import Site from "
|
|
6
|
-
import manifest from "
|
|
5
|
+
import Site from "../site/Site";
|
|
6
|
+
import manifest from "../site/manifest.ts";
|
|
7
7
|
|
|
8
8
|
// TODO: Don't cache index.html in dev?
|
|
9
9
|
// TODO: Multiple hook.server locations
|
|
@@ -7,8 +7,8 @@ import { createServer as createViteServer } from "vite";
|
|
|
7
7
|
import { serverError } from "../response.ts";
|
|
8
8
|
import Server from "../server/Server.ts";
|
|
9
9
|
import connectMiddleware from "../server/connect/connectMiddleware.ts";
|
|
10
|
-
import Site from "
|
|
11
|
-
import manifest from "
|
|
10
|
+
import Site from "../site/Site.ts";
|
|
11
|
+
import manifest from "../site/manifest.ts";
|
|
12
12
|
import prepareTemplate from "./prepareTemplate.ts";
|
|
13
13
|
|
|
14
14
|
export default async function runDev(site: Site): Promise<void> {
|
|
@@ -4,7 +4,7 @@ import path from "node:path";
|
|
|
4
4
|
import { serverError } from "../response.ts";
|
|
5
5
|
import Server from "../server/Server.ts";
|
|
6
6
|
import contentType from "../server/contentType.ts";
|
|
7
|
-
import Site from "
|
|
7
|
+
import Site from "../site/Site";
|
|
8
8
|
import prepareTemplate from "./prepareTemplate.ts";
|
|
9
9
|
import runBuild from "./runBuild";
|
|
10
10
|
|
package/src/run.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import run from "./
|
|
2
|
-
import runBuild from "./
|
|
3
|
-
import runDev from "./
|
|
4
|
-
import runPreview from "./
|
|
1
|
+
import run from "./run/run";
|
|
2
|
+
import runBuild from "./run/runBuild";
|
|
3
|
+
import runDev from "./run/runDev";
|
|
4
|
+
import runPreview from "./run/runPreview";
|
|
5
5
|
|
|
6
6
|
export { run, runDev, runBuild, runPreview };
|
package/src/server/Routerx.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import pathToRegex from "../
|
|
1
|
+
import pathToRegex from "../utils/pathToRegex";
|
|
2
2
|
import type HttpMethod from "./types/HttpMethod";
|
|
3
3
|
import type MiddlewareFunction from "./types/MiddlewareFunction";
|
|
4
4
|
import type ServerFunction from "./types/ServerFunction";
|
|
@@ -66,7 +66,7 @@ class MiddlewareHandler {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
interface Match {
|
|
70
70
|
fn: ServerFunction;
|
|
71
71
|
params?: Record<string, string>;
|
|
72
|
-
}
|
|
72
|
+
}
|
package/src/server/Server.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import pathToRegex from "../
|
|
1
|
+
import pathToRegex from "../utils/pathToRegex";
|
|
2
2
|
import ServerEvent from "./ServerEvent";
|
|
3
3
|
import type MiddlewareFunction from "./types/MiddlewareFunction";
|
|
4
4
|
import type ServerFunction from "./types/ServerFunction";
|
|
@@ -138,7 +138,7 @@ class RouteHandler {
|
|
|
138
138
|
// }
|
|
139
139
|
//}
|
|
140
140
|
|
|
141
|
-
|
|
141
|
+
interface Match {
|
|
142
142
|
fn: ServerFunction;
|
|
143
143
|
params?: Record<string, string>;
|
|
144
|
-
}
|
|
144
|
+
}
|
|
@@ -38,6 +38,7 @@ export default function connectMiddleware(
|
|
|
38
38
|
|
|
39
39
|
const cnext = async (error?: unknown) => {
|
|
40
40
|
if (error) {
|
|
41
|
+
// eslint-disable-next-line no-base-to-string
|
|
41
42
|
reject(error instanceof Error ? error : new Error(String(error)));
|
|
42
43
|
} else {
|
|
43
44
|
// TODO: Can we nest the next functions less? This is a bit weird
|
|
@@ -53,7 +54,7 @@ export default function connectMiddleware(
|
|
|
53
54
|
resolve();
|
|
54
55
|
}
|
|
55
56
|
} catch (e) {
|
|
56
|
-
cnext(e);
|
|
57
|
+
await cnext(e);
|
|
57
58
|
}
|
|
58
59
|
});
|
|
59
60
|
};
|
|
@@ -81,9 +81,9 @@ export default function nodeMessageToNodeResponse(
|
|
|
81
81
|
};
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
interface ServerResponseResponse {
|
|
85
85
|
res: ServerResponse;
|
|
86
86
|
onReadable: (
|
|
87
87
|
cb: (result: { readable: Readable; headers: OutgoingHttpHeaders; status: number }) => void,
|
|
88
88
|
) => void;
|
|
89
|
-
}
|
|
89
|
+
}
|
package/src/site/Router.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type LayoutHandler from "../types/LayoutHandler";
|
|
2
2
|
import type ManifestRoute from "../types/ManifestRoute";
|
|
3
3
|
import type RouteHandler from "../types/RouteHandler";
|
|
4
|
-
import pathToRegex from "
|
|
4
|
+
import pathToRegex from "../utils/pathToRegex";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* A router that handles file routes with layouts, hooks, etc.
|
|
@@ -158,8 +158,8 @@ class Route {
|
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
|
|
161
|
+
interface Match {
|
|
162
162
|
handler: RouteHandler;
|
|
163
163
|
params?: Record<string, string>;
|
|
164
164
|
query: URLSearchParams;
|
|
165
|
-
}
|
|
165
|
+
}
|
package/src/site/clientEntry.ts
CHANGED
|
@@ -1,32 +1,21 @@
|
|
|
1
1
|
import manifest from "@torpor/build/manifest";
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import type PageEndPoint from "../types/PageEndPoint
|
|
8
|
-
import type PageServerEndPoint from "../types/PageServerEndPoint
|
|
9
|
-
import type RouteHandler from "../types/RouteHandler.ts";
|
|
2
|
+
import loadData from "../nav/loadData.ts";
|
|
3
|
+
import navigate from "../nav/navigate.ts";
|
|
4
|
+
import $page from "../state/$page.ts";
|
|
5
|
+
import client from "../state/client";
|
|
6
|
+
import type LayoutPath from "../types/LayoutPath";
|
|
7
|
+
import type PageEndPoint from "../types/PageEndPoint";
|
|
8
|
+
import type PageServerEndPoint from "../types/PageServerEndPoint";
|
|
10
9
|
import Router from "./Router.ts";
|
|
11
10
|
|
|
12
11
|
// Build the router from the Site object created by the user
|
|
13
12
|
const router = new Router();
|
|
14
13
|
router.addPages(manifest.routes);
|
|
15
14
|
|
|
16
|
-
//
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
reuse: boolean;
|
|
21
|
-
/** Data loaded from endpoints that should be re-used */
|
|
22
|
-
data: any;
|
|
23
|
-
/** The range of the UI in this layout's slot */
|
|
24
|
-
slotRange: any;
|
|
25
|
-
}
|
|
26
|
-
let layoutStack: LayoutPath[] = [];
|
|
27
|
-
|
|
28
|
-
// TODO: Probably expire after 30 seconds or something?
|
|
29
|
-
let prefetchedData: Record<string, any> = {};
|
|
15
|
+
// Put it in client state so that it can be accessed from navigate. We can't
|
|
16
|
+
// just import it to navigate because that gets built by tsdown, without Vite
|
|
17
|
+
// and the manifest
|
|
18
|
+
client.router = router;
|
|
30
19
|
|
|
31
20
|
// Intercept clicks on links
|
|
32
21
|
window.addEventListener("click", async (e) => {
|
|
@@ -108,254 +97,12 @@ window.addEventListener("popstate", async () => {
|
|
|
108
97
|
});
|
|
109
98
|
|
|
110
99
|
// Do the initial navigation and hydration
|
|
111
|
-
navigateToLocation(document.location, true);
|
|
100
|
+
await navigateToLocation(document.location, true);
|
|
112
101
|
|
|
113
102
|
async function navigateToLocation(location: Location, firstTime = false) {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
async function navigate(url: URL, firstTime = false): Promise<boolean> {
|
|
118
|
-
let parent = document.getElementById("app");
|
|
119
|
-
if (!parent) {
|
|
120
|
-
// TODO: 500
|
|
121
|
-
console.log("500");
|
|
122
|
-
return false;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const path = url.pathname;
|
|
126
|
-
const query = url.searchParams;
|
|
127
|
-
|
|
128
|
-
console.log(`navigating to '${path}'${query.size ? ` with ${query}` : ""}`);
|
|
129
|
-
|
|
130
|
-
const route = router.match(path, query);
|
|
131
|
-
if (!route) {
|
|
132
|
-
// TODO: 404
|
|
133
|
-
console.log("404");
|
|
134
|
-
return false;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Update $page before building the components
|
|
138
|
-
$page.url = url;
|
|
139
|
-
if (path.endsWith("/_error")) {
|
|
140
|
-
$page.status = parseInt(query.get("status") ?? "404");
|
|
141
|
-
$page.error.message = query.get("message") ?? "";
|
|
142
|
-
// Make it look a bit classier by removing the query
|
|
143
|
-
window.history.replaceState({}, "", url.toString().split("?")[0]);
|
|
144
|
-
} else {
|
|
145
|
-
$page.status = 200;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
const handler = route.handler;
|
|
149
|
-
const params = route.params || {};
|
|
150
|
-
|
|
151
|
-
// There must be a client endpoint with a component
|
|
152
|
-
const clientEndPoint: PageEndPoint | undefined = (await handler.endPoint()).default;
|
|
153
|
-
if (!clientEndPoint?.component) {
|
|
154
|
-
// TODO: 404
|
|
155
|
-
console.log("404");
|
|
156
|
-
return false;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// There may be a server endpoint
|
|
160
|
-
const serverEndPoint: PageServerEndPoint | undefined =
|
|
161
|
-
handler.serverEndPoint && (await handler.serverEndPoint())?.default;
|
|
162
|
-
|
|
163
|
-
let newLayoutStack: LayoutPath[] = [];
|
|
164
|
-
|
|
165
|
-
// Pass the data into $props
|
|
166
|
-
// TODO: Don't load if this is the first time -- it should have been passed to us, somehow...
|
|
167
|
-
const data = await loadData(
|
|
168
|
-
handler,
|
|
169
|
-
params,
|
|
170
|
-
path,
|
|
171
|
-
newLayoutStack,
|
|
172
|
-
clientEndPoint,
|
|
173
|
-
serverEndPoint,
|
|
174
|
-
);
|
|
175
|
-
const $props: Record<string, any> = { data };
|
|
176
|
-
|
|
177
|
-
layoutStack.push({ path: route.handler.path, data: {}, reuse: false, slotRange: null });
|
|
178
|
-
layoutStack = newLayoutStack;
|
|
179
|
-
|
|
180
|
-
// If there are layouts, work our way upwards, pushing each component into
|
|
181
|
-
// the default slot of its parent
|
|
182
|
-
// TODO: There's probably a nicer way to do this with reducers or something
|
|
183
|
-
let component = clientEndPoint.component as Component;
|
|
184
|
-
let slots: Record<string, SlotRender> | undefined = undefined;
|
|
185
|
-
if (handler.layouts) {
|
|
186
|
-
let slotFunctions: SlotRender[] = [];
|
|
187
|
-
// The last slot function will render the client component
|
|
188
|
-
slotFunctions[handler.layouts.length] = function clientComponent(parent, anchor, _, $context) {
|
|
189
|
-
let i = layoutStack.length - 1;
|
|
190
|
-
layoutStack[i].slotRange = fillLayoutSlot(
|
|
191
|
-
clientEndPoint.component!,
|
|
192
|
-
slotFunctions[i + 1],
|
|
193
|
-
parent,
|
|
194
|
-
anchor,
|
|
195
|
-
$props,
|
|
196
|
-
$context,
|
|
197
|
-
);
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
// Each earlier slot function will render a layout
|
|
201
|
-
for (let i = handler.layouts.length - 1; i >= 0; i--) {
|
|
202
|
-
const layoutEndPoint: PageEndPoint | undefined = (await handler.layouts[i].endPoint())
|
|
203
|
-
?.default;
|
|
204
|
-
if (layoutEndPoint?.component) {
|
|
205
|
-
if (layoutStack[i].reuse) {
|
|
206
|
-
// Set the parent to add the new content to (from the old
|
|
207
|
-
// content), clear the range under this point, and set the
|
|
208
|
-
// component to the slot function within this layout
|
|
209
|
-
parent = layoutStack[i].slotRange.startNode.parentNode as HTMLElement;
|
|
210
|
-
clearLayoutSlot(layoutStack[i].slotRange);
|
|
211
|
-
component = slotFunctions[i + 1];
|
|
212
|
-
break;
|
|
213
|
-
} else if (i === 0) {
|
|
214
|
-
component = layoutEndPoint.component as Component;
|
|
215
|
-
slots = { _: slotFunctions[i + 1] };
|
|
216
|
-
} else {
|
|
217
|
-
slotFunctions[i] = function layoutComponent(parent, anchor, _, $context) {
|
|
218
|
-
layoutStack[i - 1].slotRange = fillLayoutSlot(
|
|
219
|
-
layoutEndPoint.component!,
|
|
220
|
-
slotFunctions[i + 1],
|
|
221
|
-
parent,
|
|
222
|
-
anchor,
|
|
223
|
-
$props,
|
|
224
|
-
$context,
|
|
225
|
-
);
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
if (firstTime) {
|
|
233
|
-
hydrate(parent, component, $props, slots);
|
|
234
|
-
} else {
|
|
235
|
-
try {
|
|
236
|
-
mount(parent, component, $props, slots);
|
|
237
|
-
} catch (error) {
|
|
238
|
-
// TODO: Show a proper Error component
|
|
239
|
-
parent.innerHTML = '<span style="color: red">Script syntax error</span><p>' + error + "</p>";
|
|
240
|
-
console.log(error);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// Reset prefetched data on each navigation
|
|
245
|
-
prefetchedData = {};
|
|
246
|
-
|
|
247
|
-
return true;
|
|
248
|
-
}
|
|
103
|
+
// Reset $page on submit and link navigation
|
|
104
|
+
// TODO: Should we put data in $page.data??
|
|
105
|
+
$page.form = undefined;
|
|
249
106
|
|
|
250
|
-
|
|
251
|
-
handler: RouteHandler,
|
|
252
|
-
params: Record<string, string>,
|
|
253
|
-
path: string,
|
|
254
|
-
newLayoutStack: LayoutPath[],
|
|
255
|
-
clientEndPoint: PageEndPoint | undefined,
|
|
256
|
-
serverEndPoint: PageServerEndPoint | undefined,
|
|
257
|
-
prefetch = false,
|
|
258
|
-
) {
|
|
259
|
-
let data = {};
|
|
260
|
-
if (handler.layouts) {
|
|
261
|
-
for (let [i, layout] of handler.layouts.entries()) {
|
|
262
|
-
let layoutPath = layout.path;
|
|
263
|
-
for (let key in params) {
|
|
264
|
-
layoutPath = layoutPath.replace(`[${key}]`, params[key]);
|
|
265
|
-
}
|
|
266
|
-
if (layoutStack.at(i)?.path === layoutPath) {
|
|
267
|
-
// We've already loaded this layout, we can just re-use its data and UI
|
|
268
|
-
if (!prefetch) {
|
|
269
|
-
layoutStack[i].reuse = true;
|
|
270
|
-
}
|
|
271
|
-
newLayoutStack[i] = layoutStack[i];
|
|
272
|
-
Object.assign(data, layoutStack[i].data);
|
|
273
|
-
} else {
|
|
274
|
-
const stackLayout = { path: layoutPath, data: {}, reuse: false, slotRange: null };
|
|
275
|
-
const layoutEndPoint: PageEndPoint | undefined = (await layout.endPoint())?.default;
|
|
276
|
-
const layoutServerEndPoint: PageServerEndPoint | undefined =
|
|
277
|
-
layout.serverEndPoint && (await layout.serverEndPoint())?.default;
|
|
278
|
-
const layoutResponse = await loadClientAndServerData(
|
|
279
|
-
stackLayout.data,
|
|
280
|
-
document.location.origin + layoutPath,
|
|
281
|
-
params,
|
|
282
|
-
layoutEndPoint,
|
|
283
|
-
layoutServerEndPoint,
|
|
284
|
-
);
|
|
285
|
-
if (layoutResponse?.ok === false) {
|
|
286
|
-
return false;
|
|
287
|
-
}
|
|
288
|
-
Object.assign(data, stackLayout.data);
|
|
289
|
-
newLayoutStack.push(stackLayout);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
let endPointResponse = await loadClientAndServerData(
|
|
294
|
-
data,
|
|
295
|
-
document.location.origin + path,
|
|
296
|
-
params,
|
|
297
|
-
clientEndPoint,
|
|
298
|
-
serverEndPoint,
|
|
299
|
-
);
|
|
300
|
-
if (endPointResponse?.ok === false) {
|
|
301
|
-
return false;
|
|
302
|
-
}
|
|
303
|
-
return data;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
async function loadClientAndServerData(
|
|
307
|
-
data: Record<string, any>,
|
|
308
|
-
location: string,
|
|
309
|
-
params: Record<string, string>,
|
|
310
|
-
clientEndPoint?: PageEndPoint,
|
|
311
|
-
serverEndPoint?: PageServerEndPoint,
|
|
312
|
-
): Promise<Response | undefined | void> {
|
|
313
|
-
if (clientEndPoint?.load) {
|
|
314
|
-
if (prefetchedData[location]) {
|
|
315
|
-
Object.assign(data, prefetchedData[location]);
|
|
316
|
-
} else {
|
|
317
|
-
const clientUrl = new URL(document.location.href);
|
|
318
|
-
const clientParams = buildClientParams(clientUrl, params, data);
|
|
319
|
-
const clientResponse = await clientEndPoint.load(clientParams);
|
|
320
|
-
if (clientResponse) {
|
|
321
|
-
if (clientResponse.ok) {
|
|
322
|
-
if (clientResponse.headers.get("Content-Type")?.includes("application/json")) {
|
|
323
|
-
const clientData = await clientResponse.json();
|
|
324
|
-
Object.assign(data, clientData);
|
|
325
|
-
prefetchedData[location] = clientData;
|
|
326
|
-
}
|
|
327
|
-
} else {
|
|
328
|
-
return clientResponse;
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
if (serverEndPoint?.load) {
|
|
334
|
-
const serverUrl = location.replace(/\/$/, "") + "/~server";
|
|
335
|
-
|
|
336
|
-
if (prefetchedData[serverUrl]) {
|
|
337
|
-
Object.assign(data, prefetchedData[serverUrl]);
|
|
338
|
-
} else {
|
|
339
|
-
const serverResponse = await fetch(serverUrl);
|
|
340
|
-
if (serverResponse) {
|
|
341
|
-
if (serverResponse.ok) {
|
|
342
|
-
if (serverResponse.headers.get("Content-Type")?.includes("application/json")) {
|
|
343
|
-
const serverData = await serverResponse.json();
|
|
344
|
-
Object.assign(data, serverData);
|
|
345
|
-
prefetchedData[serverUrl] = serverData;
|
|
346
|
-
}
|
|
347
|
-
} else {
|
|
348
|
-
return serverResponse;
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
function buildClientParams(url: URL, params: Record<string, string>, data: Record<string, any>) {
|
|
356
|
-
return {
|
|
357
|
-
url,
|
|
358
|
-
params,
|
|
359
|
-
data,
|
|
360
|
-
};
|
|
107
|
+
return await navigate(new URL(location.toString()), firstTime);
|
|
361
108
|
}
|