@primate/core 0.6.3 → 0.7.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/lib/private/App.d.ts +76 -149
- package/lib/private/App.js +22 -6
- package/lib/private/Flags.d.ts +5 -3
- package/lib/private/Flags.js +4 -2
- package/lib/private/app/Facade.d.ts +77 -156
- package/lib/private/app/Facade.js +4 -1
- package/lib/private/build/App.d.ts +4 -2
- package/lib/private/build/App.js +13 -4
- package/lib/private/build/client/index.js +24 -10
- package/lib/private/build/client/plugin/routes.d.ts +4 -0
- package/lib/private/build/client/plugin/routes.js +77 -0
- package/lib/private/build/hook.js +14 -6
- package/lib/private/build/index.d.ts +3 -2
- package/lib/private/build/index.js +9 -15
- package/lib/private/build/preclient/index.d.ts +3 -0
- package/lib/private/build/preclient/index.js +69 -0
- package/lib/private/build/preclient/plugin/routes.d.ts +4 -0
- package/lib/private/build/preclient/plugin/routes.js +44 -0
- package/lib/private/build/server/index.js +8 -5
- package/lib/private/build/server/plugin/assets.js +3 -3
- package/lib/private/build/server/plugin/native-addons.js +6 -8
- package/lib/private/build/server/plugin/node-imports.js +5 -7
- package/lib/private/build/server/plugin/route-client.d.ts +4 -0
- package/lib/private/build/server/plugin/route-client.js +111 -0
- package/lib/private/build/server/plugin/route.js +3 -10
- package/lib/private/build/server/plugin/virtual-pages.js +3 -3
- package/lib/private/build/server/plugin/virtual-routes.d.ts +2 -1
- package/lib/private/build/server/plugin/virtual-routes.js +27 -8
- package/lib/private/build/server/plugin/wasm.js +3 -2
- package/lib/private/build/shared/intercept.d.ts +4 -0
- package/lib/private/build/shared/intercept.js +29 -0
- package/lib/private/client/Data.d.ts +1 -1
- package/lib/private/client/boot.js +2 -2
- package/lib/private/client/create-form.d.ts +11 -1
- package/lib/private/client/create-form.js +21 -3
- package/lib/private/client/index.d.ts +2 -2
- package/lib/private/client/navigate.d.ts +1 -0
- package/lib/private/client/navigate.js +7 -6
- package/lib/private/client/submit.d.ts +2 -1
- package/lib/private/client/submit.js +8 -7
- package/lib/private/client/{http.d.ts → transport.d.ts} +3 -3
- package/lib/private/client/{http.js → transport.js} +7 -9
- package/lib/private/config/schema.d.ts +5 -13
- package/lib/private/config/schema.js +1 -5
- package/lib/private/db/DB.d.ts +3 -1
- package/lib/private/db/MemoryDB.d.ts +5 -2
- package/lib/private/db/MemoryDB.js +33 -19
- package/lib/private/db/SQLDB.d.ts +23 -0
- package/lib/private/db/SQLDB.js +2 -0
- package/lib/private/db/errors.d.ts +74 -7
- package/lib/private/db/errors.js +31 -7
- package/lib/private/db/migrate/apply.js +8 -9
- package/lib/private/db/migrate/bundle.js +2 -2
- package/lib/private/db/migrate/create.js +18 -20
- package/lib/private/db/migrate/status.js +9 -10
- package/lib/private/db/migrate/store.d.ts +3 -3
- package/lib/private/db/migrate/store.js +5 -5
- package/lib/private/db/test.js +256 -115
- package/lib/private/db/testSQL.d.ts +50 -0
- package/lib/private/db/testSQL.js +196 -0
- package/lib/private/errors.d.ts +66 -9
- package/lib/private/errors.js +37 -16
- package/lib/private/frontend.d.ts +4 -4
- package/lib/private/frontend.js +11 -8
- package/lib/private/i18n/errors.d.ts +7 -1
- package/lib/private/i18n/errors.js +1 -1
- package/lib/private/i18n/index/types.d.ts +1 -1
- package/lib/private/i18n/locale.d.ts +1 -1
- package/lib/private/i18n/module.js +6 -5
- package/lib/private/index.d.ts +10 -2
- package/lib/private/index.js +13 -1
- package/lib/private/logger.d.ts +24 -0
- package/lib/private/logger.js +66 -0
- package/lib/private/module/Setup.d.ts +3 -0
- package/lib/private/module/create.d.ts +2 -1
- package/lib/private/module/create.js +4 -0
- package/lib/private/paths.d.ts +2 -3
- package/lib/private/paths.js +6 -12
- package/lib/private/request/ContentType.d.ts +3 -0
- package/lib/private/request/ContentType.js +2 -0
- package/lib/private/request/RequestBag.d.ts +2 -18
- package/lib/private/request/RequestBag.js +4 -16
- package/lib/private/request/RequestBody.d.ts +20 -28
- package/lib/private/request/RequestBody.js +63 -86
- package/lib/private/request/RequestFacade.d.ts +2 -2
- package/lib/private/request/handle.js +2 -2
- package/lib/private/request/parse.js +2 -4
- package/lib/private/request/route.js +15 -8
- package/lib/private/response/binary.d.ts +2 -2
- package/lib/private/response/binary.js +6 -6
- package/lib/private/response/error.js +6 -2
- package/lib/private/response/json.js +2 -2
- package/lib/private/response/null.d.ts +3 -0
- package/lib/private/response/null.js +6 -0
- package/lib/private/response/redirect.js +4 -3
- package/lib/private/response/respond.js +4 -4
- package/lib/private/response/sse.js +2 -2
- package/lib/private/response/text.js +2 -2
- package/lib/private/route/ContentTypeMap.d.ts +10 -0
- package/lib/private/route/ContentTypeMap.js +2 -0
- package/lib/private/route/Handler.d.ts +3 -2
- package/lib/private/route/NarrowedRequest.d.ts +23 -0
- package/lib/private/route/NarrowedRequest.js +2 -0
- package/lib/private/route/Options.d.ts +6 -1
- package/lib/private/route/Path.d.ts +2 -2
- package/lib/private/route/hook.d.ts +3 -1
- package/lib/private/route/hook.js +1 -2
- package/lib/private/route/router.d.ts +7 -11
- package/lib/private/route/router.js +13 -20
- package/lib/private/route.client.d.ts +36 -0
- package/lib/private/route.client.js +8 -0
- package/lib/private/route.d.ts +21 -5
- package/lib/private/route.js +21 -5
- package/lib/private/serve/App.d.ts +1 -2
- package/lib/private/serve/App.js +64 -58
- package/lib/private/serve/Init.d.ts +2 -0
- package/lib/private/serve/dev-module.js +2 -3
- package/lib/private/serve/index.js +5 -6
- package/lib/private/server/TAG.d.ts +1 -1
- package/lib/private/server/TAG.js +1 -1
- package/lib/private/session/index.d.ts +1 -1
- package/lib/private/session/index.js +3 -2
- package/lib/private/session/module.js +3 -3
- package/lib/private/session/schema.d.ts +3 -3
- package/lib/private/session/schema.js +4 -3
- package/lib/private/store/ExtractRelation.d.ts +7 -0
- package/lib/private/store/ExtractRelation.js +2 -0
- package/lib/private/store/ExtractSchema.d.ts +10 -0
- package/lib/private/{orm → store}/ForeignKey.d.ts +1 -1
- package/lib/private/store/Init.d.ts +13 -0
- package/lib/private/store/Init.js +2 -0
- package/lib/private/{orm/store.d.ts → store/Store.d.ts} +50 -50
- package/lib/private/{orm/store.js → store/Store.js} +163 -107
- package/lib/private/store/StoreInput.d.ts +11 -0
- package/lib/private/store/key.d.ts +8 -0
- package/lib/private/store/key.js +8 -0
- package/lib/private/{orm → store}/parse.d.ts +3 -3
- package/lib/private/{orm → store}/parse.js +7 -2
- package/lib/private/store/relation.d.ts +29 -0
- package/lib/private/store/relation.js +26 -0
- package/lib/private/store.d.ts +24 -0
- package/lib/private/store.js +10 -0
- package/lib/public/db/errors.d.ts +1 -1
- package/lib/public/db/errors.js +1 -1
- package/lib/public/db/testSQL.d.ts +2 -0
- package/lib/public/db/testSQL.js +2 -0
- package/lib/public/db.d.ts +1 -0
- package/lib/public/index.d.ts +1 -0
- package/lib/public/index.js +1 -1
- package/lib/public/response.d.ts +6 -6
- package/lib/public/response.js +4 -1
- package/lib/public/route.client.d.ts +2 -0
- package/lib/public/route.client.js +2 -0
- package/lib/public/store.d.ts +2 -0
- package/lib/public/store.js +2 -0
- package/package.json +24 -17
- package/lib/private/bye.d.ts +0 -3
- package/lib/private/bye.js +0 -4
- package/lib/private/log.d.ts +0 -20
- package/lib/private/log.js +0 -47
- package/lib/private/orm/ExtractSchema.d.ts +0 -9
- package/lib/private/orm/StoreInput.d.ts +0 -10
- package/lib/private/orm/key.d.ts +0 -8
- package/lib/private/orm/key.js +0 -8
- package/lib/private/orm/relation.d.ts +0 -43
- package/lib/private/orm/relation.js +0 -26
- package/lib/private/request/Verb.d.ts +0 -4
- package/lib/private/request/Verb.js +0 -2
- package/lib/private/request/verbs.d.ts +0 -3
- package/lib/private/request/verbs.js +0 -12
- package/lib/private/route/wrap.d.ts +0 -2
- package/lib/private/route/wrap.js +0 -12
- package/lib/public/log.d.ts +0 -2
- package/lib/public/log.js +0 -2
- package/lib/public/orm/key.d.ts +0 -2
- package/lib/public/orm/key.js +0 -2
- package/lib/public/orm/relation.d.ts +0 -2
- package/lib/public/orm/relation.js +0 -2
- package/lib/public/orm/store.d.ts +0 -2
- package/lib/public/orm/store.js +0 -2
- package/lib/public/request/verbs.d.ts +0 -2
- package/lib/public/request/verbs.js +0 -2
- /package/lib/private/{orm → store}/ExtractSchema.js +0 -0
- /package/lib/private/{orm → store}/ForeignKey.js +0 -0
- /package/lib/private/{orm → store}/PrimaryKey.d.ts +0 -0
- /package/lib/private/{orm → store}/PrimaryKey.js +0 -0
- /package/lib/private/{orm → store}/StoreInput.js +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import E from "#errors";
|
|
2
|
-
import log from "#log";
|
|
1
|
+
import E, { Code } from "#errors";
|
|
3
2
|
import response_error from "#response/error";
|
|
4
3
|
import response_json from "#response/json";
|
|
5
4
|
import respond from "#response/respond";
|
|
6
|
-
import {
|
|
5
|
+
import { CodeError } from "@rcompat/error";
|
|
6
|
+
import http from "@rcompat/http";
|
|
7
7
|
import ParseError from "pema/ParseError";
|
|
8
8
|
const result = (request, response) => ({ request, response });
|
|
9
9
|
function wrap_hook(h) {
|
|
@@ -43,24 +43,31 @@ export default async function (app, partial_request) {
|
|
|
43
43
|
try {
|
|
44
44
|
const route = await app.route(partial_request);
|
|
45
45
|
if (route === undefined) {
|
|
46
|
+
app.log.trace `no route for pathname ${partial_request.url.pathname}`;
|
|
46
47
|
return response_error()(app, {}, partial_request);
|
|
47
48
|
}
|
|
48
|
-
const { errors, hooks, layouts, handler } = route;
|
|
49
|
+
const { errors, hooks = [], layouts, handler, is_head } = route;
|
|
49
50
|
errorRoute = errors[0];
|
|
50
51
|
const internal_hooks = app.route_hooks.map(wrap_hook);
|
|
51
52
|
const route_hooks = hooks.map(wrap_hook);
|
|
52
53
|
const last = async (req, _next) => result(req, await handler(req));
|
|
53
54
|
const { request, response } = await run([...internal_hooks, ...route_hooks, last], route.request);
|
|
54
|
-
|
|
55
|
+
const full = await respond(response)(app, {
|
|
55
56
|
layouts: await Promise.all(layouts.map(layout => layout(request))),
|
|
56
57
|
}, request);
|
|
58
|
+
return is_head
|
|
59
|
+
? new Response(null, { headers: full.headers, status: full.status })
|
|
60
|
+
: full;
|
|
57
61
|
}
|
|
58
62
|
catch (error) {
|
|
59
63
|
const request = partial_request;
|
|
60
|
-
if (error
|
|
61
|
-
return response_json(error.toJSON(), { status: Status.BAD_REQUEST })(app);
|
|
64
|
+
if (ParseError.is(error)) {
|
|
65
|
+
return response_json(error.toJSON(), { status: http.Status.BAD_REQUEST })(app);
|
|
62
66
|
}
|
|
63
|
-
|
|
67
|
+
if (CodeError.matches(error, Code.request_content_type_mismatch)) {
|
|
68
|
+
return response_json({ error: error.message }, { status: http.Status.UNSUPPORTED_MEDIA_TYPE })(app);
|
|
69
|
+
}
|
|
70
|
+
app.log.error(error);
|
|
64
71
|
// the +error.js page itself could fail
|
|
65
72
|
try {
|
|
66
73
|
return respond(await errorRoute(request))(app, {}, request);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type ServeApp from "#serve/App";
|
|
2
|
-
import type {
|
|
2
|
+
import type { Streamable } from "@rcompat/fs";
|
|
3
3
|
/**
|
|
4
4
|
* Stream a binary response.
|
|
5
5
|
* @param source streamable source
|
|
6
6
|
* @param options response options
|
|
7
7
|
* @return Response rendering function
|
|
8
8
|
*/
|
|
9
|
-
export default function binary(source:
|
|
9
|
+
export default function binary(source: Streamable, init?: ResponseInit): (app: ServeApp) => Response;
|
|
10
10
|
//# sourceMappingURL=binary.d.ts.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import fs from "@rcompat/fs";
|
|
2
|
+
import http from "@rcompat/http";
|
|
3
3
|
import is from "@rcompat/is";
|
|
4
4
|
const encodeRFC5987 = (s) => encodeURIComponent(s).replace(/['()*]/g, c => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);
|
|
5
5
|
/**
|
|
@@ -31,15 +31,15 @@ function toContentDisposition(filename) {
|
|
|
31
31
|
*/
|
|
32
32
|
export default function binary(source, init) {
|
|
33
33
|
return (app) => {
|
|
34
|
-
const { headers, ...rest } = app.media(MIME.APPLICATION_OCTET_STREAM, init);
|
|
35
|
-
const name =
|
|
34
|
+
const { headers, ...rest } = app.media(http.MIME.APPLICATION_OCTET_STREAM, init);
|
|
35
|
+
const name = fs.isNamedStream(source) ? source.name : "default.bin";
|
|
36
36
|
const out = new Headers(headers);
|
|
37
37
|
out.set("Content-Disposition", toContentDisposition(name));
|
|
38
38
|
if (is.blob(source)) {
|
|
39
|
-
source.type && out.set("Content-Type", source.type);
|
|
39
|
+
is.text(source.type) && out.set("Content-Type", source.type);
|
|
40
40
|
out.set("Content-Length", String(source.size));
|
|
41
41
|
}
|
|
42
|
-
return app.respond(
|
|
42
|
+
return app.respond(fs.stream(source), {
|
|
43
43
|
...rest, headers: Object.fromEntries(out.entries()),
|
|
44
44
|
});
|
|
45
45
|
};
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import location from "#location";
|
|
2
|
-
import
|
|
2
|
+
import http from "@rcompat/http";
|
|
3
|
+
const sse_reload = `<script>
|
|
4
|
+
new EventSource("/esbuild").addEventListener("change", () => location.reload());
|
|
5
|
+
</script>`;
|
|
3
6
|
/**
|
|
4
7
|
* Render an error page.
|
|
5
8
|
*
|
|
@@ -11,8 +14,9 @@ import { Status } from "@rcompat/http";
|
|
|
11
14
|
export default function error(options) {
|
|
12
15
|
return app => app.view({
|
|
13
16
|
body: options?.body ?? "Not Found",
|
|
17
|
+
head: app.mode === "development" ? sse_reload : undefined,
|
|
14
18
|
page: options?.page ?? location.error_html,
|
|
15
|
-
status: options?.status ?? Status.NOT_FOUND,
|
|
19
|
+
status: options?.status ?? http.Status.NOT_FOUND,
|
|
16
20
|
});
|
|
17
21
|
}
|
|
18
22
|
//# sourceMappingURL=error.js.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import response from "#response";
|
|
2
|
-
import
|
|
2
|
+
import http from "@rcompat/http";
|
|
3
3
|
/**
|
|
4
4
|
* Issue a JSON response
|
|
5
5
|
* @param body body object
|
|
6
6
|
* @param options response options
|
|
7
7
|
* @return Response rendering function
|
|
8
8
|
*/
|
|
9
|
-
export default response(MIME.APPLICATION_JSON, JSON.stringify);
|
|
9
|
+
export default response(http.MIME.APPLICATION_JSON, JSON.stringify);
|
|
10
10
|
//# sourceMappingURL=json.js.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import http from "@rcompat/http";
|
|
2
|
+
import is from "@rcompat/is";
|
|
2
3
|
function hasCRLF(s) {
|
|
3
4
|
return /[\r\n]/.test(s);
|
|
4
5
|
}
|
|
@@ -31,7 +32,7 @@ function toSearch(query) {
|
|
|
31
32
|
return params;
|
|
32
33
|
}, new URLSearchParams())
|
|
33
34
|
.toString();
|
|
34
|
-
return search ? "?" + search : "";
|
|
35
|
+
return is.text(search) ? "?" + search : "";
|
|
35
36
|
}
|
|
36
37
|
function toNormalized(relative, base) {
|
|
37
38
|
// base -> URL resolution
|
|
@@ -60,6 +61,6 @@ app => app.respond(null, {
|
|
|
60
61
|
Location: location,
|
|
61
62
|
"Cache-Control": "no-cache",
|
|
62
63
|
},
|
|
63
|
-
status: status ?? Status.FOUND,
|
|
64
|
+
status: status ?? http.Status.FOUND,
|
|
64
65
|
});
|
|
65
66
|
//# sourceMappingURL=redirect.js.map
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import E from "#errors";
|
|
2
2
|
import binary from "#response/binary";
|
|
3
3
|
import json from "#response/json";
|
|
4
|
+
import $null from "#response/null";
|
|
4
5
|
import redirect from "#response/redirect";
|
|
5
6
|
import text from "#response/text";
|
|
6
|
-
import
|
|
7
|
-
import { Status } from "@rcompat/http";
|
|
7
|
+
import fs from "@rcompat/fs";
|
|
8
8
|
import is from "@rcompat/is";
|
|
9
9
|
function match(m) {
|
|
10
10
|
return m;
|
|
11
11
|
}
|
|
12
12
|
// [if, then]
|
|
13
13
|
const guesses = match([
|
|
14
|
-
[is.null,
|
|
14
|
+
[is.null, $null],
|
|
15
15
|
[is.url, value => redirect(value.toString())],
|
|
16
|
-
[
|
|
16
|
+
[fs.isStream, value => binary(value)],
|
|
17
17
|
[is.response, value => _ => value],
|
|
18
18
|
[is.dict, json],
|
|
19
19
|
[is.array, json],
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import response from "#response";
|
|
2
|
-
import
|
|
2
|
+
import http from "@rcompat/http";
|
|
3
3
|
const encode = (input) => new TextEncoder().encode(input);
|
|
4
4
|
const handle = (body) => new ReadableStream({
|
|
5
5
|
cancel() {
|
|
@@ -21,5 +21,5 @@ const handle = (body) => new ReadableStream({
|
|
|
21
21
|
* @param options response options
|
|
22
22
|
* @return Response rendering function
|
|
23
23
|
*/
|
|
24
|
-
export default response(MIME.TEXT_EVENT_STREAM, handle);
|
|
24
|
+
export default response(http.MIME.TEXT_EVENT_STREAM, handle);
|
|
25
25
|
//# sourceMappingURL=sse.js.map
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import response from "#response";
|
|
2
2
|
import fn from "@rcompat/fn";
|
|
3
|
-
import
|
|
3
|
+
import http from "@rcompat/http";
|
|
4
4
|
/**
|
|
5
5
|
* Return a plaintext response
|
|
6
6
|
* @param body plaintext body
|
|
7
7
|
* @param options response options
|
|
8
8
|
* @return Response rendering function
|
|
9
9
|
*/
|
|
10
|
-
export default response(MIME.TEXT_PLAIN, fn.identity);
|
|
10
|
+
export default response(http.MIME.TEXT_PLAIN, fn.identity);
|
|
11
11
|
//# sourceMappingURL=text.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Dict, JSONValue } from "@rcompat/type";
|
|
2
|
+
type ContentTypeMap = {
|
|
3
|
+
"application/json": JSONValue;
|
|
4
|
+
"text/plain": string;
|
|
5
|
+
"application/x-www-form-urlencoded": URLSearchParams | Dict<string>;
|
|
6
|
+
"multipart/form-data": FormData | Dict<FormDataEntryValue>;
|
|
7
|
+
"application/octet-stream": Blob;
|
|
8
|
+
};
|
|
9
|
+
export type { ContentTypeMap as default };
|
|
10
|
+
//# sourceMappingURL=ContentTypeMap.d.ts.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type RequestFacade from "#request/RequestFacade";
|
|
2
1
|
import type ResponseLike from "#response/ResponseLike";
|
|
2
|
+
import type NarrowedRequest from "#route/NarrowedRequest";
|
|
3
|
+
import type RouteOptions from "#route/Options";
|
|
3
4
|
import type { MaybePromise } from "@rcompat/type";
|
|
4
|
-
type RouteHandler = (request:
|
|
5
|
+
type RouteHandler<O extends RouteOptions = RouteOptions> = (request: NarrowedRequest<O>) => MaybePromise<ResponseLike>;
|
|
5
6
|
export { RouteHandler as default };
|
|
6
7
|
//# sourceMappingURL=Handler.d.ts.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type RequestBody from "#request/RequestBody";
|
|
2
|
+
import type RequestFacade from "#request/RequestFacade";
|
|
3
|
+
import type RouteOptions from "#route/Options";
|
|
4
|
+
import type { Unpack } from "@rcompat/type";
|
|
5
|
+
import type { Parsed } from "pema";
|
|
6
|
+
type ContentTypeMethod = {
|
|
7
|
+
"application/json": "json";
|
|
8
|
+
"text/plain": "text";
|
|
9
|
+
"application/x-www-form-urlencoded": "form";
|
|
10
|
+
"multipart/form-data": "multipart";
|
|
11
|
+
"application/octet-stream": "blob";
|
|
12
|
+
};
|
|
13
|
+
type NarrowedBody<O extends RouteOptions, B extends RequestBody> = O extends {
|
|
14
|
+
contentType: infer CT extends keyof ContentTypeMethod;
|
|
15
|
+
body: Parsed<infer T>;
|
|
16
|
+
} ? Omit<B, ContentTypeMethod[CT]> & {
|
|
17
|
+
[K in ContentTypeMethod[CT]]: () => Promise<Unpack<T>>;
|
|
18
|
+
} : B;
|
|
19
|
+
type NarrowedRequest<O extends RouteOptions> = Omit<RequestFacade, "body"> & {
|
|
20
|
+
body: NarrowedBody<O, RequestBody>;
|
|
21
|
+
};
|
|
22
|
+
export type { NarrowedRequest as default };
|
|
23
|
+
//# sourceMappingURL=NarrowedRequest.d.ts.map
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
import type http from "@rcompat/http";
|
|
2
|
+
import type { Parsed } from "pema";
|
|
3
|
+
type MIME = Omit<typeof http.MIME, "resolve" | "extension">;
|
|
4
|
+
type MIMEValue = MIME[keyof MIME];
|
|
1
5
|
type RouteOptions = {
|
|
2
|
-
|
|
6
|
+
contentType?: MIMEValue;
|
|
7
|
+
body?: Parsed<unknown>;
|
|
3
8
|
};
|
|
4
9
|
export type { RouteOptions as default };
|
|
5
10
|
//# sourceMappingURL=Options.d.ts.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import type { Method } from "@rcompat/http";
|
|
2
2
|
import type RouteHandler from "#route/Handler";
|
|
3
3
|
import type RouteOptions from "#route/Options";
|
|
4
4
|
type RoutePath = {
|
|
5
|
-
[key in
|
|
5
|
+
[key in Method]?: {
|
|
6
6
|
handler: RouteHandler;
|
|
7
7
|
options: RouteOptions;
|
|
8
8
|
};
|
|
@@ -2,5 +2,7 @@ import type NextRoute from "#module/NextRoute";
|
|
|
2
2
|
import type RequestFacade from "#request/RequestFacade";
|
|
3
3
|
import type ResponseLike from "#response/ResponseLike";
|
|
4
4
|
import type { MaybePromise } from "@rcompat/type";
|
|
5
|
-
|
|
5
|
+
type HookFn = (request: RequestFacade, next: NextRoute) => MaybePromise<ResponseLike>;
|
|
6
|
+
export default function hook(fn: HookFn): HookFn;
|
|
7
|
+
export {};
|
|
6
8
|
//# sourceMappingURL=hook.d.ts.map
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
import type RequestHook from "#module/RequestHook";
|
|
2
|
-
import type Verb from "#request/Verb";
|
|
3
2
|
import type RouteHandler from "#route/Handler";
|
|
4
3
|
import type RouteOptions from "#route/Options";
|
|
5
|
-
|
|
4
|
+
import type { Method } from "@rcompat/http";
|
|
6
5
|
declare class Router {
|
|
7
6
|
#private;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
get active(): string | undefined;
|
|
11
|
-
add(verb: Verb, handler: RouteHandler, options?: RouteOptions): void;
|
|
12
|
-
addHook(fn: RequestHook): void;
|
|
7
|
+
add(path: string, method: Method, handler: RouteHandler, options?: RouteOptions): void;
|
|
8
|
+
addHook(path: string, fn: RequestHook): void;
|
|
13
9
|
getHooks(path: string): RequestHook[];
|
|
14
10
|
verifyHook(path: string): void;
|
|
15
11
|
get(path: string): {
|
|
@@ -17,10 +13,6 @@ declare class Router {
|
|
|
17
13
|
handler: RouteHandler;
|
|
18
14
|
options: RouteOptions;
|
|
19
15
|
} | undefined;
|
|
20
|
-
head?: {
|
|
21
|
-
handler: RouteHandler;
|
|
22
|
-
options: RouteOptions;
|
|
23
|
-
} | undefined;
|
|
24
16
|
get?: {
|
|
25
17
|
handler: RouteHandler;
|
|
26
18
|
options: RouteOptions;
|
|
@@ -37,6 +29,10 @@ declare class Router {
|
|
|
37
29
|
handler: RouteHandler;
|
|
38
30
|
options: RouteOptions;
|
|
39
31
|
} | undefined;
|
|
32
|
+
head?: {
|
|
33
|
+
handler: RouteHandler;
|
|
34
|
+
options: RouteOptions;
|
|
35
|
+
} | undefined;
|
|
40
36
|
connect?: {
|
|
41
37
|
handler: RouteHandler;
|
|
42
38
|
options: RouteOptions;
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import E from "#errors";
|
|
2
2
|
import assert from "@rcompat/assert";
|
|
3
|
-
const stack = [];
|
|
4
|
-
export const routes = stack;
|
|
5
3
|
function is_hook_file(p) {
|
|
6
4
|
const basename = p.split("/").at(-1) ?? p;
|
|
7
5
|
return basename === "+hook" || basename.startsWith("+hook.");
|
|
@@ -9,28 +7,23 @@ function is_hook_file(p) {
|
|
|
9
7
|
class Router {
|
|
10
8
|
#routes = {};
|
|
11
9
|
#hooks = {};
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
add(verb, handler, options) {
|
|
16
|
-
assert.string(verb);
|
|
10
|
+
add(path, method, handler, options) {
|
|
11
|
+
assert.string(path);
|
|
12
|
+
assert.string(method);
|
|
17
13
|
assert.function(handler);
|
|
18
14
|
assert.maybe.dict(options);
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
if (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (!(active in _routes))
|
|
25
|
-
_routes[active] = {};
|
|
26
|
-
_routes[active][verb] = { handler, options: options ?? {} };
|
|
15
|
+
if (is_hook_file(path))
|
|
16
|
+
throw E.hook_route_functions_not_allowed(path);
|
|
17
|
+
if (!(path in this.#routes))
|
|
18
|
+
this.#routes[path] = {};
|
|
19
|
+
this.#routes[path][method] = { handler, options: options ?? {} };
|
|
27
20
|
}
|
|
28
|
-
addHook(fn) {
|
|
21
|
+
addHook(path, fn) {
|
|
22
|
+
assert.string(path);
|
|
29
23
|
assert.function(fn);
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
(this.#hooks[active] ??= []).push(fn);
|
|
24
|
+
if (!is_hook_file(path))
|
|
25
|
+
throw E.hook_not_allowed(path);
|
|
26
|
+
(this.#hooks[path] ??= []).push(fn);
|
|
34
27
|
}
|
|
35
28
|
getHooks(path) {
|
|
36
29
|
return [...(this.#hooks[path] ?? [])];
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type ContentTypeMap from "#route/ContentTypeMap";
|
|
2
|
+
import type RouteHandler from "#route/Handler";
|
|
3
|
+
import type RouteOptions from "#route/Options";
|
|
4
|
+
import type { Unpack } from "@rcompat/type";
|
|
5
|
+
import type { Parsed } from "pema";
|
|
6
|
+
type Body<O extends RouteOptions> = O extends {
|
|
7
|
+
contentType: infer _CT extends keyof ContentTypeMap;
|
|
8
|
+
body: infer S extends Parsed<unknown>;
|
|
9
|
+
} ? Unpack<S["infer"]> : O extends {
|
|
10
|
+
contentType: infer CT extends keyof ContentTypeMap;
|
|
11
|
+
} ? ContentTypeMap[CT] : never;
|
|
12
|
+
type MethodMeta = {
|
|
13
|
+
contentType?: string;
|
|
14
|
+
};
|
|
15
|
+
type ClientMethod<O extends RouteOptions> = MethodMeta & (Body<O> extends never ? () => Promise<Response> : (args: {
|
|
16
|
+
body: Body<O>;
|
|
17
|
+
}) => Promise<Response>);
|
|
18
|
+
type ClientRoute<R> = {
|
|
19
|
+
[K in keyof R]: R[K] extends {
|
|
20
|
+
options: infer O extends RouteOptions;
|
|
21
|
+
} ? ClientMethod<O> : () => Promise<Response>;
|
|
22
|
+
};
|
|
23
|
+
type WithResult<O extends RouteOptions> = {
|
|
24
|
+
handler: RouteHandler<O>;
|
|
25
|
+
options: O;
|
|
26
|
+
};
|
|
27
|
+
type RouteHandlers = {
|
|
28
|
+
[key: string]: RouteHandler | WithResult<RouteOptions>;
|
|
29
|
+
};
|
|
30
|
+
declare function route<R extends RouteHandlers>(handlers: R): ClientRoute<R>;
|
|
31
|
+
declare namespace route {
|
|
32
|
+
var _a: <O extends RouteOptions>(options: O, handler: RouteHandler<O>) => WithResult<O>;
|
|
33
|
+
export { _a as with };
|
|
34
|
+
}
|
|
35
|
+
export default route;
|
|
36
|
+
//# sourceMappingURL=route.client.d.ts.map
|
package/lib/private/route.d.ts
CHANGED
|
@@ -1,9 +1,25 @@
|
|
|
1
|
-
import type Verb from "#request/Verb";
|
|
2
1
|
import type RouteHandler from "#route/Handler";
|
|
3
2
|
import type RouteOptions from "#route/Options";
|
|
4
|
-
type
|
|
5
|
-
|
|
3
|
+
import type { Method } from "@rcompat/http";
|
|
4
|
+
declare const BRAND: unique symbol;
|
|
5
|
+
type WithResult<O extends RouteOptions> = {
|
|
6
|
+
[BRAND]: true;
|
|
7
|
+
handler: RouteHandler;
|
|
8
|
+
options: O;
|
|
6
9
|
};
|
|
7
|
-
|
|
8
|
-
|
|
10
|
+
type AnyHandler = RouteHandler | WithResult<RouteOptions>;
|
|
11
|
+
type RouteHandlers = {
|
|
12
|
+
[key in Method]?: AnyHandler;
|
|
13
|
+
};
|
|
14
|
+
declare function route(handlers: RouteHandlers): {
|
|
15
|
+
[k: string]: {
|
|
16
|
+
handler: RouteHandler;
|
|
17
|
+
options: RouteOptions;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
declare namespace route {
|
|
21
|
+
var _a: <O extends RouteOptions>(options: O, handler: RouteHandler<O>) => WithResult<O>;
|
|
22
|
+
export { _a as with };
|
|
23
|
+
}
|
|
24
|
+
export default route;
|
|
9
25
|
//# sourceMappingURL=route.d.ts.map
|
package/lib/private/route.js
CHANGED
|
@@ -1,6 +1,22 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import E from "#errors";
|
|
2
|
+
import is from "@rcompat/is";
|
|
3
|
+
const BRAND = Symbol("route.with");
|
|
4
|
+
function is_with(value) {
|
|
5
|
+
return is.branded(value, BRAND);
|
|
6
|
+
}
|
|
7
|
+
function route(handlers) {
|
|
8
|
+
return Object.fromEntries(Object.entries(handlers).map(([method, value]) => {
|
|
9
|
+
if (is_with(value)) {
|
|
10
|
+
return [method, { handler: value.handler, options: value.options }];
|
|
11
|
+
}
|
|
12
|
+
return [method, { handler: value, options: {} }];
|
|
13
|
+
}));
|
|
14
|
+
}
|
|
15
|
+
route.with = function (options, handler) {
|
|
16
|
+
if (options.body !== undefined && options.contentType === undefined) {
|
|
17
|
+
throw E.build_body_requires_content_type();
|
|
18
|
+
}
|
|
19
|
+
return { [BRAND]: true, handler, options };
|
|
20
|
+
};
|
|
21
|
+
export default route;
|
|
6
22
|
//# sourceMappingURL=route.js.map
|
|
@@ -22,9 +22,7 @@ interface PublishOptions {
|
|
|
22
22
|
export default class ServeApp extends App {
|
|
23
23
|
#private;
|
|
24
24
|
constructor(rootfile: string, init: ServeInit);
|
|
25
|
-
get secure(): boolean;
|
|
26
25
|
get assets(): Asset[];
|
|
27
|
-
get url(): string;
|
|
28
26
|
get router(): FileRouter;
|
|
29
27
|
get frontends(): {
|
|
30
28
|
[k: string]: ViewResponse;
|
|
@@ -54,6 +52,7 @@ export default class ServeApp extends App {
|
|
|
54
52
|
layouts: RouteHandler[];
|
|
55
53
|
handler: RouteHandler;
|
|
56
54
|
request: any;
|
|
55
|
+
is_head: boolean;
|
|
57
56
|
} | undefined>;
|
|
58
57
|
}
|
|
59
58
|
export {};
|