@primate/core 0.6.3 → 0.7.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.
- 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 +74 -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 +110 -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/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
|
@@ -4,7 +4,8 @@ import PERSIST_HEADER from "#i18n/constant/PERSIST_HEADER";
|
|
|
4
4
|
import E from "#i18n/errors";
|
|
5
5
|
import storage from "#i18n/storage";
|
|
6
6
|
import create from "#module/create";
|
|
7
|
-
import
|
|
7
|
+
import http from "@rcompat/http";
|
|
8
|
+
import is from "@rcompat/is";
|
|
8
9
|
function toLowerCase(string) {
|
|
9
10
|
return string.toLowerCase();
|
|
10
11
|
}
|
|
@@ -12,7 +13,7 @@ function pick(client, server) {
|
|
|
12
13
|
const lower = server.map(toLowerCase);
|
|
13
14
|
for (const raw of client.map(toLowerCase)) {
|
|
14
15
|
const locale = raw.trim();
|
|
15
|
-
if (!locale)
|
|
16
|
+
if (!is.text(locale))
|
|
16
17
|
continue;
|
|
17
18
|
const exact = lower.indexOf(locale);
|
|
18
19
|
if (exact !== -1)
|
|
@@ -67,7 +68,7 @@ export default function i18n_module(config) {
|
|
|
67
68
|
headers: {
|
|
68
69
|
"Content-Length": String(0),
|
|
69
70
|
},
|
|
70
|
-
status: Status.NO_CONTENT,
|
|
71
|
+
status: http.Status.NO_CONTENT,
|
|
71
72
|
});
|
|
72
73
|
// only accept existing locales
|
|
73
74
|
if (!locales.includes(requested))
|
|
@@ -75,7 +76,7 @@ export default function i18n_module(config) {
|
|
|
75
76
|
headers: {
|
|
76
77
|
"Content-Length": String(0),
|
|
77
78
|
},
|
|
78
|
-
status: Status.NO_CONTENT,
|
|
79
|
+
status: http.Status.NO_CONTENT,
|
|
79
80
|
});
|
|
80
81
|
const header = cookie(COOKIE_NAME, requested, {
|
|
81
82
|
secure,
|
|
@@ -87,7 +88,7 @@ export default function i18n_module(config) {
|
|
|
87
88
|
"Set-Cookie": header,
|
|
88
89
|
"Content-Length": String(0),
|
|
89
90
|
},
|
|
90
|
-
status: Status.NO_CONTENT,
|
|
91
|
+
status: http.Status.NO_CONTENT,
|
|
91
92
|
});
|
|
92
93
|
});
|
|
93
94
|
onRoute((request, next) => {
|
package/lib/private/index.d.ts
CHANGED
|
@@ -2,13 +2,21 @@ export type { default as App } from "#App";
|
|
|
2
2
|
export type { default as BuildApp } from "#build/App";
|
|
3
3
|
export type { default as Mode } from "#Mode";
|
|
4
4
|
export type { default as Module } from "#Module";
|
|
5
|
-
export type { BuildHook, HandleHook, InitHook, RouteHook, ServeHook, default as Setup } from "#module/Setup";
|
|
5
|
+
export type { BuildHook, HandleHook, InitHook, RouteHook, ServeHook, default as Setup, } from "#module/Setup";
|
|
6
|
+
export type { default as RequestContentType } from "#request/ContentType";
|
|
6
7
|
export type { default as RequestBag } from "#request/RequestBag";
|
|
7
8
|
export type { default as RequestBody } from "#request/RequestBody";
|
|
8
9
|
export type { default as RequestFacade } from "#request/RequestFacade";
|
|
9
10
|
export type { default as RequestPublic } from "#request/RequestPublic";
|
|
10
11
|
export type { default as RequestView } from "#request/RequestView";
|
|
11
|
-
export type { default as
|
|
12
|
+
export type { default as ResponseFunction } from "#response/ResponseFunction";
|
|
13
|
+
export type { default as ResponseLike } from "#response/ResponseLike";
|
|
12
14
|
export type { default as ServeApp } from "#serve/App";
|
|
13
15
|
export type { default as Target } from "#target/Target";
|
|
16
|
+
import logger from "#logger";
|
|
17
|
+
declare const core: {
|
|
18
|
+
logger: typeof logger;
|
|
19
|
+
try(fn: () => Promise<unknown>): Promise<void>;
|
|
20
|
+
};
|
|
21
|
+
export default core;
|
|
14
22
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/private/index.js
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { LogHook } from "#module/Setup";
|
|
2
|
+
declare const Schema: import("pema").DefaultType<import("pema").UnionType<[import("pema").LiteralType<"error">, import("pema").LiteralType<"warn">, import("pema").LiteralType<"info">, import("pema").LiteralType<"trace">]>, "trace" | "info" | "error" | "warn">;
|
|
3
|
+
export { Schema };
|
|
4
|
+
declare const levels: {
|
|
5
|
+
readonly error: 0;
|
|
6
|
+
readonly warn: 1;
|
|
7
|
+
readonly info: 2;
|
|
8
|
+
readonly trace: 3;
|
|
9
|
+
};
|
|
10
|
+
type Level = keyof typeof levels;
|
|
11
|
+
export type LogEntry = {
|
|
12
|
+
level: Level;
|
|
13
|
+
message: string;
|
|
14
|
+
};
|
|
15
|
+
export default function logger(level?: string, hooks?: LogHook[]): {
|
|
16
|
+
readonly level: string;
|
|
17
|
+
print(strings: TemplateStringsArray, ...params: unknown[]): void;
|
|
18
|
+
system(strings: TemplateStringsArray, ...params: unknown[]): void;
|
|
19
|
+
trace(strings: TemplateStringsArray, ...params: unknown[]): void;
|
|
20
|
+
info(strings: TemplateStringsArray, ...params: unknown[]): void;
|
|
21
|
+
warn(strings: TemplateStringsArray, ...params: unknown[]): void;
|
|
22
|
+
error(error: unknown): void;
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import cli from "@rcompat/cli";
|
|
2
|
+
import { CodeError } from "@rcompat/error";
|
|
3
|
+
import p from "pema";
|
|
4
|
+
const Schema = p.union("error", "warn", "info", "trace").default("warn");
|
|
5
|
+
export { Schema };
|
|
6
|
+
const levels = {
|
|
7
|
+
error: 0,
|
|
8
|
+
warn: 1,
|
|
9
|
+
info: 2,
|
|
10
|
+
trace: 3,
|
|
11
|
+
};
|
|
12
|
+
function mark(strings, params) {
|
|
13
|
+
return strings.reduce((acc, str, i) => acc + (i > 0 ? cli.fg.bold(String(params[i - 1])) : "") + str, "");
|
|
14
|
+
}
|
|
15
|
+
function format(strings, params) {
|
|
16
|
+
return strings.reduce((acc, str, i) => acc + (i > 0 ? String(params[i - 1]) : "") + str, "");
|
|
17
|
+
}
|
|
18
|
+
function run_hooks(level, message, hooks) {
|
|
19
|
+
for (const hook of hooks) {
|
|
20
|
+
hook({ level, message });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
// param is intentionally relaxed and not Schema.input
|
|
24
|
+
export default function logger(level = "warn", hooks = []) {
|
|
25
|
+
const n = levels[Schema.parse(level)];
|
|
26
|
+
return {
|
|
27
|
+
get level() {
|
|
28
|
+
return level;
|
|
29
|
+
},
|
|
30
|
+
print(strings, ...params) {
|
|
31
|
+
cli.print(format(strings, params));
|
|
32
|
+
},
|
|
33
|
+
system(strings, ...params) {
|
|
34
|
+
cli.print(` ${format(strings, params)}\n`);
|
|
35
|
+
},
|
|
36
|
+
trace(strings, ...params) {
|
|
37
|
+
if (n === levels.trace) {
|
|
38
|
+
cli.print(cli.fg.blue("[TRACE]"), mark(strings, params), "\n");
|
|
39
|
+
}
|
|
40
|
+
run_hooks("trace", format(strings, params), hooks);
|
|
41
|
+
},
|
|
42
|
+
info(strings, ...params) {
|
|
43
|
+
if (n >= levels.info) {
|
|
44
|
+
cli.print(cli.fg.green("[INFO]"), mark(strings, params), "\n");
|
|
45
|
+
}
|
|
46
|
+
run_hooks("info", format(strings, params), hooks);
|
|
47
|
+
},
|
|
48
|
+
warn(strings, ...params) {
|
|
49
|
+
if (n >= levels.warn) {
|
|
50
|
+
cli.print(cli.fg.yellow("[WARN]"), mark(strings, params), "\n");
|
|
51
|
+
}
|
|
52
|
+
run_hooks("warn", format(strings, params), hooks);
|
|
53
|
+
},
|
|
54
|
+
error(error) {
|
|
55
|
+
if (CodeError.is(error)) {
|
|
56
|
+
cli.print(cli.fg.red("[ERROR]"), mark(error.strings, error.params), "\n");
|
|
57
|
+
run_hooks("error", format(error.strings, error.params), hooks);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
console.error(error);
|
|
61
|
+
run_hooks("error", error.message, hooks);
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type App from "#App";
|
|
2
2
|
import type BuildApp from "#build/App";
|
|
3
|
+
import type { LogEntry } from "#logger";
|
|
3
4
|
import type NextHandle from "#module/NextHandle";
|
|
4
5
|
import type NextRoute from "#module/NextRoute";
|
|
5
6
|
import type RequestFacade from "#request/RequestFacade";
|
|
@@ -9,6 +10,7 @@ import type { MaybePromise } from "@rcompat/type";
|
|
|
9
10
|
export type InitHook = (app: App) => MaybePromise<void>;
|
|
10
11
|
export type BuildHook = (app: BuildApp) => MaybePromise<void>;
|
|
11
12
|
export type ServeHook = (app: ServeApp) => MaybePromise<void>;
|
|
13
|
+
export type LogHook = (entry: LogEntry) => void;
|
|
12
14
|
export type HandleHook = (request: RequestFacade, next: NextHandle) => MaybePromise<Response>;
|
|
13
15
|
export type RouteHook = (request: RequestFacade, next: NextRoute) => MaybePromise<ResponseLike>;
|
|
14
16
|
export default interface Setup {
|
|
@@ -17,5 +19,6 @@ export default interface Setup {
|
|
|
17
19
|
onServe(hook: ServeHook): void;
|
|
18
20
|
onHandle(hook: HandleHook): void;
|
|
19
21
|
onRoute(hook: RouteHook): void;
|
|
22
|
+
onLog(hook: LogHook): void;
|
|
20
23
|
}
|
|
21
24
|
//# sourceMappingURL=Setup.d.ts.map
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type Module from "#Module";
|
|
2
|
-
import type { BuildHook, HandleHook, InitHook, RouteHook, ServeHook } from "#module/Setup";
|
|
2
|
+
import type { BuildHook, HandleHook, InitHook, LogHook, RouteHook, ServeHook } from "#module/Setup";
|
|
3
3
|
type Hooks = {
|
|
4
4
|
init: InitHook[];
|
|
5
5
|
build: BuildHook[];
|
|
6
6
|
serve: ServeHook[];
|
|
7
7
|
handle: HandleHook[];
|
|
8
8
|
route: RouteHook[];
|
|
9
|
+
log: LogHook[];
|
|
9
10
|
};
|
|
10
11
|
type Created = {
|
|
11
12
|
name: string;
|
|
@@ -5,6 +5,7 @@ export default function create({ name, setup }) {
|
|
|
5
5
|
serve: [],
|
|
6
6
|
handle: [],
|
|
7
7
|
route: [],
|
|
8
|
+
log: [],
|
|
8
9
|
};
|
|
9
10
|
setup({
|
|
10
11
|
onInit(hook) {
|
|
@@ -22,6 +23,9 @@ export default function create({ name, setup }) {
|
|
|
22
23
|
onRoute(hook) {
|
|
23
24
|
hooks.route.push(hook);
|
|
24
25
|
},
|
|
26
|
+
onLog(hook) {
|
|
27
|
+
hooks.log.push(hook);
|
|
28
|
+
},
|
|
25
29
|
});
|
|
26
30
|
return { name, hooks };
|
|
27
31
|
}
|
package/lib/private/paths.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type
|
|
2
|
-
|
|
3
|
-
declare function resolve(root: FileRef, config_paths?: Dict<string[]>): Promise<any>;
|
|
1
|
+
import type BuildApp from "#build/App";
|
|
2
|
+
declare function resolve(app: BuildApp): Promise<any>;
|
|
4
3
|
export default resolve;
|
|
5
4
|
//# sourceMappingURL=paths.d.ts.map
|
package/lib/private/paths.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import E from "#errors";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const tsconfig_path = root.join("tsconfig.json");
|
|
2
|
+
async function resolve(app) {
|
|
3
|
+
const tsconfig_path = app.root.join("tsconfig.json");
|
|
5
4
|
if (await tsconfig_path.exists()) {
|
|
6
5
|
try {
|
|
7
6
|
let text = await tsconfig_path.text();
|
|
@@ -11,19 +10,14 @@ async function resolve(root, config_paths) {
|
|
|
11
10
|
.replace(/\/\/.*/g, "")
|
|
12
11
|
.replace(/,(\s*[}\]])/g, "$1");
|
|
13
12
|
const config = JSON.parse(text);
|
|
14
|
-
const
|
|
15
|
-
if (config_paths !== undefined && Object.keys(ts_paths).length > 0) {
|
|
16
|
-
return E.config_tsconfig_has_paths();
|
|
17
|
-
}
|
|
13
|
+
const paths = config.compilerOptions?.paths ?? {};
|
|
18
14
|
// merge with defaults (user paths override)
|
|
19
|
-
return { ...
|
|
15
|
+
return { ...paths };
|
|
20
16
|
}
|
|
21
|
-
catch {
|
|
22
|
-
|
|
17
|
+
catch (cause) {
|
|
18
|
+
throw E.config_failed_to_parse_tsconfig(tsconfig_path, cause);
|
|
23
19
|
}
|
|
24
20
|
}
|
|
25
|
-
if (config_paths !== undefined)
|
|
26
|
-
return config_paths;
|
|
27
21
|
return {};
|
|
28
22
|
}
|
|
29
23
|
export default resolve;
|
|
@@ -1,18 +1,14 @@
|
|
|
1
|
+
import symbol from "@rcompat/symbol";
|
|
1
2
|
import type { PartialDict } from "@rcompat/type";
|
|
2
3
|
type Contents = PartialDict<string>;
|
|
3
4
|
type Normalize = (key: string) => string;
|
|
4
|
-
interface Schema<T> {
|
|
5
|
-
parse(input: unknown): T;
|
|
6
|
-
}
|
|
7
|
-
interface CoercibleSchema<T> extends Schema<T> {
|
|
8
|
-
coerce(input: unknown): T;
|
|
9
|
-
}
|
|
10
5
|
type Options = {
|
|
11
6
|
normalize?: Normalize;
|
|
12
7
|
raw?: string;
|
|
13
8
|
};
|
|
14
9
|
export default class RequestBag {
|
|
15
10
|
#private;
|
|
11
|
+
[symbol.parse](): any;
|
|
16
12
|
/**
|
|
17
13
|
* Create a new RequestBag.
|
|
18
14
|
*
|
|
@@ -59,18 +55,6 @@ export default class RequestBag {
|
|
|
59
55
|
* @returns `true` if present with a defined value; otherwise `false`.
|
|
60
56
|
*/
|
|
61
57
|
has(key: string): boolean;
|
|
62
|
-
/**
|
|
63
|
-
* Parse the entire bag with a schema.
|
|
64
|
-
*
|
|
65
|
-
* The schema receives the bag's normalized contents.
|
|
66
|
-
*
|
|
67
|
-
* @typeParam T - Parsed/validated result type.
|
|
68
|
-
* @param schema - Object exposing `parse(input)`.
|
|
69
|
-
* @returns The parsed value.
|
|
70
|
-
* @throws Whatever the schema throws.
|
|
71
|
-
*/
|
|
72
|
-
parse<T>(schema: Schema<T>): T;
|
|
73
|
-
coerce<T>(schema: CoercibleSchema<T>): T;
|
|
74
58
|
/** Returns {@link raw}. Useful in template strings. */
|
|
75
59
|
toString(): string;
|
|
76
60
|
/**
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import E from "#errors";
|
|
2
2
|
import assert from "@rcompat/assert";
|
|
3
3
|
import fn from "@rcompat/fn";
|
|
4
|
+
import symbol from "@rcompat/symbol";
|
|
4
5
|
export default class RequestBag {
|
|
5
6
|
#contents;
|
|
6
7
|
#name;
|
|
7
8
|
#normalize;
|
|
8
9
|
#raw;
|
|
10
|
+
[symbol.parse]() {
|
|
11
|
+
return this.toJSON();
|
|
12
|
+
}
|
|
9
13
|
/**
|
|
10
14
|
* Create a new RequestBag.
|
|
11
15
|
*
|
|
@@ -94,22 +98,6 @@ export default class RequestBag {
|
|
|
94
98
|
const k = this.#normalize(key);
|
|
95
99
|
return this.#hasOwn(k) && this.#contents[k] !== undefined;
|
|
96
100
|
}
|
|
97
|
-
/**
|
|
98
|
-
* Parse the entire bag with a schema.
|
|
99
|
-
*
|
|
100
|
-
* The schema receives the bag's normalized contents.
|
|
101
|
-
*
|
|
102
|
-
* @typeParam T - Parsed/validated result type.
|
|
103
|
-
* @param schema - Object exposing `parse(input)`.
|
|
104
|
-
* @returns The parsed value.
|
|
105
|
-
* @throws Whatever the schema throws.
|
|
106
|
-
*/
|
|
107
|
-
parse(schema) {
|
|
108
|
-
return schema.parse(this.#contents);
|
|
109
|
-
}
|
|
110
|
-
coerce(schema) {
|
|
111
|
-
return schema.coerce(this.#contents);
|
|
112
|
-
}
|
|
113
101
|
/** Returns {@link raw}. Useful in template strings. */
|
|
114
102
|
toString() {
|
|
115
103
|
return this.raw;
|
|
@@ -1,35 +1,27 @@
|
|
|
1
|
+
import http from "@rcompat/http";
|
|
1
2
|
import type { Dict, JSONValue } from "@rcompat/type";
|
|
3
|
+
import type { Parsed } from "pema";
|
|
2
4
|
type Form = Dict<string>;
|
|
3
|
-
type
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} | {
|
|
10
|
-
type: "json";
|
|
11
|
-
value: JSONValue;
|
|
12
|
-
} | {
|
|
13
|
-
type: "none";
|
|
14
|
-
value: null;
|
|
15
|
-
} | {
|
|
16
|
-
type: "text";
|
|
17
|
-
value: string;
|
|
5
|
+
type Files = Dict<File>;
|
|
6
|
+
type MIMES = typeof http.MIME;
|
|
7
|
+
type MIME = MIMES[keyof MIMES];
|
|
8
|
+
type BodyOptions = {
|
|
9
|
+
contentType: MIME;
|
|
10
|
+
schema: Parsed<unknown>;
|
|
18
11
|
};
|
|
19
|
-
declare
|
|
20
|
-
declare function none(): RequestBody;
|
|
12
|
+
declare const patched: unique symbol;
|
|
21
13
|
export default class RequestBody {
|
|
22
14
|
#private;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
15
|
+
constructor(request: Request, options?: BodyOptions);
|
|
16
|
+
[patched](options: BodyOptions): RequestBody;
|
|
17
|
+
json(): Promise<JSONValue>;
|
|
18
|
+
form(): Promise<Form>;
|
|
19
|
+
multipart(): Promise<{
|
|
20
|
+
form: Form;
|
|
21
|
+
files: Files;
|
|
22
|
+
}>;
|
|
23
|
+
text(): Promise<string>;
|
|
24
|
+
blob(): Promise<Blob>;
|
|
33
25
|
}
|
|
34
|
-
export {};
|
|
26
|
+
export { patched as BodyPatch };
|
|
35
27
|
//# sourceMappingURL=RequestBody.d.ts.map
|
|
@@ -1,99 +1,76 @@
|
|
|
1
1
|
import E from "#errors";
|
|
2
|
-
import
|
|
2
|
+
import assert from "@rcompat/assert";
|
|
3
|
+
import http from "@rcompat/http";
|
|
3
4
|
import is from "@rcompat/is";
|
|
4
|
-
|
|
5
|
-
const form = Object.create(null);
|
|
6
|
-
const files = Object.create(null);
|
|
7
|
-
for (const [key, value] of (await request.formData()).entries()) {
|
|
8
|
-
if (is.string(value)) {
|
|
9
|
-
form[key] = value;
|
|
10
|
-
}
|
|
11
|
-
else {
|
|
12
|
-
files[key] = value;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
return { form, files };
|
|
16
|
-
}
|
|
17
|
-
;
|
|
18
|
-
async function parse(request, url) {
|
|
19
|
-
const raw = request.headers.get("content-type") ?? "none";
|
|
20
|
-
const type = raw.split(";")[0].trim().toLowerCase();
|
|
21
|
-
const path = url.pathname;
|
|
22
|
-
try {
|
|
23
|
-
switch (type) {
|
|
24
|
-
case MIME.APPLICATION_OCTET_STREAM:
|
|
25
|
-
return new RequestBody({ type: "binary", value: await request.blob() });
|
|
26
|
-
case MIME.APPLICATION_X_WWW_FORM_URLENCODED:
|
|
27
|
-
case MIME.MULTIPART_FORM_DATA: {
|
|
28
|
-
const { form, files } = await anyform(request);
|
|
29
|
-
return new RequestBody({ type: "form", value: form }, files);
|
|
30
|
-
}
|
|
31
|
-
case MIME.APPLICATION_JSON:
|
|
32
|
-
return new RequestBody({ type: "json", value: await request.json() });
|
|
33
|
-
case MIME.TEXT_PLAIN:
|
|
34
|
-
return new RequestBody({ type: "text", value: await request.text() });
|
|
35
|
-
case "none":
|
|
36
|
-
return RequestBody.none();
|
|
37
|
-
default:
|
|
38
|
-
throw E.request_unsupported_mime(path, type);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
catch (cause) {
|
|
42
|
-
throw E.request_unparsable_mime(path, type, cause);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
function none() {
|
|
46
|
-
return new RequestBody({ type: "none", value: null });
|
|
47
|
-
}
|
|
5
|
+
const patched = Symbol("RequestBody.patch");
|
|
48
6
|
export default class RequestBody {
|
|
49
|
-
#
|
|
50
|
-
#
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
this.#
|
|
55
|
-
this.#files = files;
|
|
56
|
-
}
|
|
57
|
-
get type() {
|
|
58
|
-
return this.#parsed.type;
|
|
59
|
-
}
|
|
60
|
-
#value() {
|
|
61
|
-
return this.#parsed.value;
|
|
62
|
-
}
|
|
63
|
-
#unexpected_body(expected) {
|
|
64
|
-
throw E.request_unexpected_body(expected, this.type);
|
|
65
|
-
}
|
|
66
|
-
json() {
|
|
67
|
-
if (this.type !== "json")
|
|
68
|
-
this.#unexpected_body("JSON");
|
|
69
|
-
return this.#value();
|
|
7
|
+
#request;
|
|
8
|
+
#parsed = false;
|
|
9
|
+
#options;
|
|
10
|
+
constructor(request, options) {
|
|
11
|
+
this.#request = request;
|
|
12
|
+
this.#options = options;
|
|
70
13
|
}
|
|
71
|
-
|
|
72
|
-
if (this
|
|
73
|
-
|
|
74
|
-
|
|
14
|
+
#parse(mime) {
|
|
15
|
+
if (this.#parsed)
|
|
16
|
+
throw E.request_body_already_parsed();
|
|
17
|
+
const raw = this.#request.headers.get("content-type") ?? "none";
|
|
18
|
+
const content_type = raw.split(";")[0].trim().toLowerCase();
|
|
19
|
+
assert.true(mime === content_type);
|
|
20
|
+
this.#parsed = true;
|
|
75
21
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
this.#unexpected_body("form");
|
|
79
|
-
return this.#files;
|
|
22
|
+
[patched](options) {
|
|
23
|
+
return new RequestBody(this.#request, options);
|
|
80
24
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
return this.#
|
|
25
|
+
async json() {
|
|
26
|
+
this.#parse(http.MIME.APPLICATION_JSON);
|
|
27
|
+
const raw = await this.#request.json();
|
|
28
|
+
return this.#options?.contentType === http.MIME.APPLICATION_JSON
|
|
29
|
+
? this.#options.schema.parse(raw)
|
|
30
|
+
: raw;
|
|
85
31
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
32
|
+
async form() {
|
|
33
|
+
this.#parse(http.MIME.APPLICATION_X_WWW_FORM_URLENCODED);
|
|
34
|
+
const form = Object.create(null);
|
|
35
|
+
for (const [key, value] of (await this.#request.formData()).entries()) {
|
|
36
|
+
form[key] = assert.string(value);
|
|
89
37
|
}
|
|
90
|
-
|
|
38
|
+
const raw = form;
|
|
39
|
+
return this.#options?.contentType === http.MIME.APPLICATION_X_WWW_FORM_URLENCODED
|
|
40
|
+
? this.#options.schema.parse(raw)
|
|
41
|
+
: raw;
|
|
91
42
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
43
|
+
async multipart() {
|
|
44
|
+
this.#parse(http.MIME.MULTIPART_FORM_DATA);
|
|
45
|
+
const form = Object.create(null);
|
|
46
|
+
const files = Object.create(null);
|
|
47
|
+
for (const [key, value] of (await this.#request.formData()).entries()) {
|
|
48
|
+
if (is.string(value)) {
|
|
49
|
+
form[key] = value;
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
files[key] = value;
|
|
53
|
+
}
|
|
95
54
|
}
|
|
96
|
-
|
|
55
|
+
const raw = { form, files };
|
|
56
|
+
return this.#options?.contentType === http.MIME.MULTIPART_FORM_DATA
|
|
57
|
+
? this.#options.schema.parse(raw)
|
|
58
|
+
: raw;
|
|
59
|
+
}
|
|
60
|
+
async text() {
|
|
61
|
+
this.#parse(http.MIME.TEXT_PLAIN);
|
|
62
|
+
const raw = await this.#request.text();
|
|
63
|
+
return this.#options?.contentType === http.MIME.TEXT_PLAIN
|
|
64
|
+
? this.#options.schema.parse(raw)
|
|
65
|
+
: raw;
|
|
66
|
+
}
|
|
67
|
+
async blob() {
|
|
68
|
+
this.#parse(http.MIME.APPLICATION_OCTET_STREAM);
|
|
69
|
+
const raw = await this.#request.blob();
|
|
70
|
+
return this.#options?.contentType === http.MIME.APPLICATION_OCTET_STREAM
|
|
71
|
+
? this.#options.schema.parse(raw)
|
|
72
|
+
: raw;
|
|
97
73
|
}
|
|
98
74
|
}
|
|
75
|
+
export { patched as BodyPatch };
|
|
99
76
|
//# sourceMappingURL=RequestBody.js.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type RequestBag from "#request/RequestBag";
|
|
2
2
|
import type RequestBody from "#request/RequestBody";
|
|
3
3
|
import type RequestView from "#request/RequestView";
|
|
4
|
-
import type
|
|
4
|
+
import type { Method } from "@rcompat/http";
|
|
5
5
|
import type { Dict } from "@rcompat/type";
|
|
6
6
|
type RequestFacade = {
|
|
7
|
-
method:
|
|
7
|
+
method: Method;
|
|
8
8
|
body: RequestBody;
|
|
9
9
|
cookies: RequestBag;
|
|
10
10
|
forward(to: string, headers?: Dict<string>): Promise<Response>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import http from "@rcompat/http";
|
|
2
2
|
async function run(hooks, request) {
|
|
3
3
|
const [first, ...rest] = hooks;
|
|
4
4
|
if (first === undefined) {
|
|
@@ -7,7 +7,7 @@ async function run(hooks, request) {
|
|
|
7
7
|
"Content-Length": String(0),
|
|
8
8
|
"Cache-Control": "no-cache",
|
|
9
9
|
},
|
|
10
|
-
status: Status.INTERNAL_SERVER_ERROR,
|
|
10
|
+
status: http.Status.INTERNAL_SERVER_ERROR,
|
|
11
11
|
});
|
|
12
12
|
}
|
|
13
13
|
return await first(request, next => run(rest, next));
|
|
@@ -17,9 +17,7 @@ function normalize(k) {
|
|
|
17
17
|
}
|
|
18
18
|
function header_bag(request) {
|
|
19
19
|
const headers = Object.fromEntries([...request.headers].map(([k, v]) => [k.toLowerCase(), v]));
|
|
20
|
-
return new RequestBag(headers, "headers", {
|
|
21
|
-
normalize,
|
|
22
|
-
});
|
|
20
|
+
return new RequestBag(headers, "headers", { normalize });
|
|
23
21
|
}
|
|
24
22
|
function cookie_bag(request) {
|
|
25
23
|
const header = request.headers.get("cookie");
|
|
@@ -47,7 +45,7 @@ function path_bag(url) {
|
|
|
47
45
|
function parse(request) {
|
|
48
46
|
const url = new URL(request.url);
|
|
49
47
|
const facade = {
|
|
50
|
-
body: RequestBody
|
|
48
|
+
body: new RequestBody(request),
|
|
51
49
|
method: request.method.toLowerCase(),
|
|
52
50
|
cookies: cookie_bag(request),
|
|
53
51
|
forward(to, headers) {
|