@primate/core 0.2.3 → 0.3.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 +7 -0
- package/lib/private/App.js +18 -12
- package/lib/private/Binder.d.ts +1 -1
- package/lib/private/BindingContext.d.ts +1 -1
- package/lib/private/BuildApp.d.ts +7 -1
- package/lib/private/BuildApp.js +35 -31
- package/lib/private/Loader.d.ts +1 -1
- package/lib/private/Loader.js +4 -3
- package/lib/private/ServeApp.d.ts +3 -2
- package/lib/private/ServeApp.js +27 -15
- package/lib/private/ServeInit.d.ts +1 -1
- package/lib/private/backend/TAG.d.ts +3 -0
- package/lib/private/backend/TAG.js +2 -0
- package/lib/private/builtin/DevModule.js +1 -3
- package/lib/private/client/Data.d.ts +1 -1
- package/lib/private/client/app.d.ts +2 -0
- package/lib/private/client/{App.js → app.js} +4 -2
- package/lib/private/client/spa/index.js +4 -0
- package/lib/private/database/Query.d.ts +3 -3
- package/lib/private/database/QueryBuilder.d.ts +2 -2
- package/lib/private/database/{DataRecord.d.ts → Schema.d.ts} +3 -3
- package/lib/private/database/Schema.js +3 -0
- package/lib/private/database/Store.d.ts +11 -11
- package/lib/private/frontend/Module.d.ts +2 -2
- package/lib/private/frontend/Module.js +47 -39
- package/lib/private/frontend/Render.d.ts +1 -1
- package/lib/private/frontend/ServerData.d.ts +2 -2
- package/lib/private/frontend/ServerView.d.ts +5 -0
- package/lib/private/frontend/ServerView.js +2 -0
- package/lib/private/frontend/View.d.ts +8 -0
- package/lib/private/frontend/View.js +2 -0
- package/lib/private/frontend/bundle-server.js +3 -3
- package/lib/private/hook/build.js +83 -69
- package/lib/private/i18n/Module.js +16 -3
- package/lib/private/location.d.ts +3 -0
- package/lib/private/location.js +6 -0
- package/lib/private/request/RequestBody.d.ts +8 -7
- package/lib/private/request/RequestBody.js +30 -14
- package/lib/private/response/ResponseFunction.d.ts +2 -2
- package/lib/private/response/redirect.js +5 -1
- package/lib/private/response/view.d.ts +3 -3
- package/lib/private/response/view.js +14 -12
- package/lib/private/route/wrap.d.ts +1 -5
- package/lib/private/route/wrap.js +4 -9
- package/lib/private/target/Manager.js +1 -1
- package/lib/private/target/web.js +0 -10
- package/lib/private/wasm/encode-request.js +25 -28
- package/lib/public/backend/TAG.d.ts +2 -0
- package/lib/public/backend/TAG.js +2 -0
- package/lib/public/client/app.d.ts +2 -0
- package/lib/public/client/app.js +2 -0
- package/lib/public/fail.d.ts +2 -0
- package/lib/public/fail.js +2 -0
- package/package.json +4 -4
- package/lib/private/client/App.d.ts +0 -4
- package/lib/private/database/DataRecord.js +0 -3
- package/lib/private/frontend/Component.d.ts +0 -8
- package/lib/private/frontend/Component.js +0 -2
- package/lib/private/frontend/ServerComponent.d.ts +0 -5
- package/lib/private/frontend/ServerComponent.js +0 -2
- package/lib/public/client/App.d.ts +0 -2
- package/lib/public/client/App.js +0 -2
- package/lib/public/route/wrap.d.ts +0 -2
- package/lib/public/route/wrap.js +0 -2
package/lib/private/App.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export default class App {
|
|
|
13
13
|
app_html: "app.html";
|
|
14
14
|
build: "build";
|
|
15
15
|
client: "client";
|
|
16
|
+
lib: "lib";
|
|
16
17
|
components: "components";
|
|
17
18
|
config: "config";
|
|
18
19
|
error_html: "error.html";
|
|
@@ -23,6 +24,8 @@ export default class App {
|
|
|
23
24
|
static: "static";
|
|
24
25
|
stores: "stores";
|
|
25
26
|
locales: "locales";
|
|
27
|
+
views: "views";
|
|
28
|
+
hooks: "hooks";
|
|
26
29
|
};
|
|
27
30
|
get target(): TargetManager;
|
|
28
31
|
get root(): FileRef;
|
|
@@ -30,6 +33,7 @@ export default class App {
|
|
|
30
33
|
readonly app_html: FileRef;
|
|
31
34
|
readonly build: FileRef;
|
|
32
35
|
readonly client: FileRef;
|
|
36
|
+
readonly lib: FileRef;
|
|
33
37
|
readonly components: FileRef;
|
|
34
38
|
readonly config: FileRef;
|
|
35
39
|
readonly error_html: FileRef;
|
|
@@ -40,11 +44,14 @@ export default class App {
|
|
|
40
44
|
readonly static: FileRef;
|
|
41
45
|
readonly stores: FileRef;
|
|
42
46
|
readonly locales: FileRef;
|
|
47
|
+
readonly views: FileRef;
|
|
48
|
+
readonly hooks: FileRef;
|
|
43
49
|
};
|
|
44
50
|
get mode(): Mode;
|
|
45
51
|
get modules(): Module[];
|
|
46
52
|
get extensions(): string[];
|
|
47
53
|
binder(file: FileRef): Binder | undefined;
|
|
54
|
+
basename(file: FileRef, directory: FileRef): string;
|
|
48
55
|
get<T>(key: symbol): T;
|
|
49
56
|
set(key: symbol, value: unknown): void;
|
|
50
57
|
config<P extends string>(path: P): ReturnType<typeof get<Config, P>>;
|
package/lib/private/App.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import fail from "#fail";
|
|
2
2
|
import location from "#location";
|
|
3
3
|
import reducer from "#reducer";
|
|
4
|
-
import wrap from "#route/wrap";
|
|
5
4
|
import TargetManager from "#target/Manager";
|
|
6
5
|
import assert from "@rcompat/assert";
|
|
7
6
|
import transform from "@rcompat/build/sync/transform";
|
|
@@ -23,30 +22,26 @@ const BIND_CONTEXTS = [
|
|
|
23
22
|
"config",
|
|
24
23
|
"routes",
|
|
25
24
|
"components",
|
|
25
|
+
"views",
|
|
26
26
|
"stores",
|
|
27
27
|
"locales",
|
|
28
28
|
"modules",
|
|
29
29
|
];
|
|
30
30
|
function generate_bindings(_app) {
|
|
31
31
|
return {
|
|
32
|
-
".js":
|
|
32
|
+
".js": (file, { context }) => {
|
|
33
33
|
const error = `js: only ${toContextString(BIND_CONTEXTS)} are supported`;
|
|
34
34
|
assert(BIND_CONTEXTS.includes(context), error);
|
|
35
|
-
|
|
36
|
-
? wrap(await file.text(), file, build)
|
|
37
|
-
: await file.text();
|
|
38
|
-
await file.append(".js").write(code);
|
|
35
|
+
return file.text();
|
|
39
36
|
},
|
|
40
|
-
".json": () => {
|
|
37
|
+
".json": (file) => {
|
|
41
38
|
// just copy the JSON for now
|
|
39
|
+
return file.text();
|
|
42
40
|
},
|
|
43
|
-
".ts": async (file, {
|
|
41
|
+
".ts": async (file, { context }) => {
|
|
44
42
|
const error = `ts: only ${toContextString(BIND_CONTEXTS)} are supported`;
|
|
45
43
|
assert(BIND_CONTEXTS.includes(context), error);
|
|
46
|
-
|
|
47
|
-
? wrap(compile(await file.text()), file, build)
|
|
48
|
-
: compile(await file.text());
|
|
49
|
-
await file.append(".js").write(code);
|
|
44
|
+
return compile(await file.text());
|
|
50
45
|
},
|
|
51
46
|
};
|
|
52
47
|
}
|
|
@@ -104,6 +99,17 @@ export default class App {
|
|
|
104
99
|
.toSorted(([a], [b]) => a.length > b.length ? -1 : 1)
|
|
105
100
|
.find(([extension]) => file.path.endsWith(extension))?.[1];
|
|
106
101
|
}
|
|
102
|
+
basename(file, directory) {
|
|
103
|
+
const relative = file.debase(directory);
|
|
104
|
+
const extensions = this.extensions
|
|
105
|
+
.toSorted((a, b) => a.length > b.length ? -1 : 1);
|
|
106
|
+
for (const extension of extensions) {
|
|
107
|
+
if (relative.path.endsWith(extension)) {
|
|
108
|
+
return relative.path.slice(1, -extension.length);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return relative.bare().path.slice(1);
|
|
112
|
+
}
|
|
107
113
|
get(key) {
|
|
108
114
|
return this.#kv.get(key);
|
|
109
115
|
}
|
package/lib/private/Binder.d.ts
CHANGED
|
@@ -8,6 +8,6 @@ type Options = {
|
|
|
8
8
|
};
|
|
9
9
|
context: BindingContext;
|
|
10
10
|
};
|
|
11
|
-
type Binder = (file: FileRef, options: Options) => MaybePromise<
|
|
11
|
+
type Binder = (file: FileRef, options: Options) => MaybePromise<string>;
|
|
12
12
|
export type { Binder as default };
|
|
13
13
|
//# sourceMappingURL=Binder.d.ts.map
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
type BindingContext = "components" | "config" | "locales" | "modules" | "routes" | "stores";
|
|
1
|
+
type BindingContext = "components" | "views" | "config" | "locales" | "modules" | "routes" | "stores" | "hooks";
|
|
2
2
|
export type { BindingContext as default };
|
|
3
3
|
//# sourceMappingURL=BindingContext.d.ts.map
|
|
@@ -3,6 +3,8 @@ import type BindingContext from "#BindingContext";
|
|
|
3
3
|
import Build from "@rcompat/build";
|
|
4
4
|
import type FileRef from "@rcompat/fs/FileRef";
|
|
5
5
|
import type MaybePromise from "@rcompat/type/MaybePromise";
|
|
6
|
+
type Loader = (source: string, file: FileRef) => MaybePromise<string>;
|
|
7
|
+
type Resolver = (basename: string, file: FileRef) => string;
|
|
6
8
|
export default class BuildApp extends App {
|
|
7
9
|
#private;
|
|
8
10
|
frontends: Map<string, string>;
|
|
@@ -15,9 +17,13 @@ export default class BuildApp extends App {
|
|
|
15
17
|
done(fn: () => void): void;
|
|
16
18
|
cleanup(): void;
|
|
17
19
|
export(code: string): void;
|
|
18
|
-
|
|
20
|
+
compile(directory: FileRef, context: BindingContext, options?: {
|
|
21
|
+
loader?: Loader;
|
|
22
|
+
resolver?: Resolver;
|
|
23
|
+
}): Promise<void>;
|
|
19
24
|
depth(): number;
|
|
20
25
|
get i18n_active(): boolean;
|
|
21
26
|
set i18n_active(active: boolean);
|
|
22
27
|
}
|
|
28
|
+
export {};
|
|
23
29
|
//# sourceMappingURL=BuildApp.d.ts.map
|
package/lib/private/BuildApp.js
CHANGED
|
@@ -29,11 +29,15 @@ export default class BuildApp extends App {
|
|
|
29
29
|
contents: "",
|
|
30
30
|
resolveDir: this.root.path,
|
|
31
31
|
},
|
|
32
|
+
conditions: ["style", "browser", "default", "module"],
|
|
32
33
|
resolveExtensions: [".ts", ".js", ...extensions],
|
|
33
34
|
tsconfigRaw: {
|
|
34
35
|
compilerOptions: {
|
|
35
36
|
baseUrl: "${configDir}",
|
|
36
37
|
paths: {
|
|
38
|
+
"#view/*": [
|
|
39
|
+
"views/*", ...extensions.map(e => `views/*${e}`),
|
|
40
|
+
],
|
|
37
41
|
"#component/*": [
|
|
38
42
|
"components/*", ...extensions.map(e => `components/*${e}`),
|
|
39
43
|
],
|
|
@@ -72,41 +76,41 @@ export default class BuildApp extends App {
|
|
|
72
76
|
export(code) {
|
|
73
77
|
this.build.export(code);
|
|
74
78
|
}
|
|
75
|
-
async
|
|
76
|
-
if (!await directory.exists())
|
|
79
|
+
async compile(directory, context, options = {}) {
|
|
80
|
+
if (!await directory.exists())
|
|
77
81
|
return;
|
|
82
|
+
const files = await directory.collect(({ path }) => this.extensions.some(e => path.endsWith(e)) && !path.endsWith(".d.ts"));
|
|
83
|
+
for (const file of files) {
|
|
84
|
+
await this.#compileFile(file, context, directory, options);
|
|
78
85
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
86
|
+
}
|
|
87
|
+
async #compileFile(file, context, directory, options) {
|
|
88
|
+
const binder = this.binder(file);
|
|
89
|
+
if (binder === undefined) {
|
|
90
|
+
log.info("no binder found for {0}", file.path);
|
|
91
|
+
return;
|
|
85
92
|
}
|
|
86
|
-
|
|
87
|
-
await
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const binder = this.binder(file);
|
|
95
|
-
if (binder === undefined) {
|
|
96
|
-
log.info("no binder found for {0}", file.path);
|
|
97
|
-
continue;
|
|
98
|
-
}
|
|
99
|
-
// copy to build/stage/${directory}
|
|
100
|
-
await file.copy(target);
|
|
101
|
-
await binder(target, {
|
|
102
|
-
build: { id: this.id, stage: this.runpath("stage") },
|
|
103
|
-
context,
|
|
104
|
-
});
|
|
105
|
-
// actual
|
|
106
|
-
const runtime_file = build_directory.join(debased.bare(".js"));
|
|
107
|
-
await runtime_file.directory.create();
|
|
108
|
-
runtime_file.write(await importer(debased));
|
|
93
|
+
// call the binder to compile
|
|
94
|
+
const compiled = await binder(file, {
|
|
95
|
+
build: { id: this.id, stage: this.runpath("stage") },
|
|
96
|
+
context,
|
|
97
|
+
});
|
|
98
|
+
if (!compiled) {
|
|
99
|
+
log.info("binder returned empty output for {0}", file.path);
|
|
100
|
+
return;
|
|
109
101
|
}
|
|
102
|
+
// apply loader if provided
|
|
103
|
+
const transformed = options.loader
|
|
104
|
+
? await options.loader(compiled, file)
|
|
105
|
+
: compiled;
|
|
106
|
+
const basename = this.basename(file, directory);
|
|
107
|
+
const resolved = options.resolver
|
|
108
|
+
? options.resolver(basename, file)
|
|
109
|
+
: basename;
|
|
110
|
+
const target = this.runpath(context, `${resolved}.js`);
|
|
111
|
+
// write to final location
|
|
112
|
+
await target.directory.create({ recursive: true });
|
|
113
|
+
await target.write(transformed);
|
|
110
114
|
}
|
|
111
115
|
depth() {
|
|
112
116
|
return this.get(s_layout_depth);
|
package/lib/private/Loader.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export default class Loader {
|
|
|
10
10
|
constructor(init: Init);
|
|
11
11
|
get static_root(): string;
|
|
12
12
|
page(name?: string): string;
|
|
13
|
-
asset(file: FileRef): Response
|
|
13
|
+
asset(file: FileRef): Promise<Response>;
|
|
14
14
|
serve(pathname: string): Promise<Response | undefined>;
|
|
15
15
|
}
|
|
16
16
|
export {};
|
package/lib/private/Loader.js
CHANGED
|
@@ -21,10 +21,11 @@ export default class Loader {
|
|
|
21
21
|
}
|
|
22
22
|
return this.#pages[name];
|
|
23
23
|
}
|
|
24
|
-
asset(file) {
|
|
24
|
+
async asset(file) {
|
|
25
25
|
return new Response(file.stream(), {
|
|
26
26
|
headers: {
|
|
27
27
|
"Content-Type": resolve(file.name),
|
|
28
|
+
"Content-Length": String(await file.byteLength()),
|
|
28
29
|
},
|
|
29
30
|
status: Status.OK,
|
|
30
31
|
});
|
|
@@ -32,13 +33,13 @@ export default class Loader {
|
|
|
32
33
|
async serve(pathname) {
|
|
33
34
|
const client_file = this.#root.join(`client/${pathname}`);
|
|
34
35
|
if (await client_file.isFile()) {
|
|
35
|
-
return this.asset(client_file);
|
|
36
|
+
return await this.asset(client_file);
|
|
36
37
|
}
|
|
37
38
|
if (pathname.startsWith(this.static_root)) {
|
|
38
39
|
const assetname = pathname.slice(this.static_root.length);
|
|
39
40
|
const static_file = this.#root.join(`static/${assetname}`);
|
|
40
41
|
if (await static_file.isFile()) {
|
|
41
|
-
return this.asset(static_file);
|
|
42
|
+
return await this.asset(static_file);
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import App from "#App";
|
|
2
2
|
import type Asset from "#asset/Asset";
|
|
3
|
-
import type
|
|
3
|
+
import type ServerView from "#frontend/ServerView";
|
|
4
4
|
import type ViewOptions from "#frontend/ViewOptions";
|
|
5
5
|
import type ViewResponse from "#frontend/ViewResponse";
|
|
6
6
|
import type I18NConfig from "#i18n/Config";
|
|
@@ -41,12 +41,13 @@ export default class ServeApp extends App {
|
|
|
41
41
|
};
|
|
42
42
|
get stores(): Dict;
|
|
43
43
|
get i18n(): I18NConfig | undefined;
|
|
44
|
-
|
|
44
|
+
loadView<T = ServerView>(name: string): T;
|
|
45
45
|
headers(csp?: {}): {
|
|
46
46
|
"Content-Security-Policy"?: string | undefined;
|
|
47
47
|
};
|
|
48
48
|
render(content: Omit<FullViewOptions, keyof ResponseInit>): string;
|
|
49
49
|
page(page?: string): string;
|
|
50
|
+
body_length(body: BodyInit | null): number;
|
|
50
51
|
respond(body: BodyInit | null, init?: ResponseInit): Response;
|
|
51
52
|
view(options: FullViewOptions): Response;
|
|
52
53
|
media(content_type: string, response?: ResponseInit): ResponseInit;
|
package/lib/private/ServeApp.js
CHANGED
|
@@ -20,6 +20,7 @@ import TEXT_HTML from "@rcompat/http/mime/text/html";
|
|
|
20
20
|
import serve from "@rcompat/http/serve";
|
|
21
21
|
import Status from "@rcompat/http/Status";
|
|
22
22
|
import entries from "@rcompat/record/entries";
|
|
23
|
+
import utf8ByteLength from "@rcompat/string/utf8-bytelength";
|
|
23
24
|
import pema from "pema";
|
|
24
25
|
import record from "pema/record";
|
|
25
26
|
import string from "pema/string";
|
|
@@ -44,17 +45,17 @@ const render_head = (assets, head) => {
|
|
|
44
45
|
const fonts = assets.filter(asset => asset.src?.endsWith(".woff2"));
|
|
45
46
|
const rest = assets.filter(asset => !asset.src?.endsWith(".woff2")
|
|
46
47
|
&& asset.type !== "js");
|
|
47
|
-
return
|
|
48
|
+
return fonts.map(font => tags.font({ href: font.src, type: "font/woff2" })).join("\n").concat("\n", rest
|
|
48
49
|
.map(({ code, inline, integrity, src, type }) => type === "style"
|
|
49
50
|
? tags.style({ code, href: src, inline })
|
|
50
|
-
: tags.script({ code, inline, integrity, src, type })).join("\n").concat("\n", head ?? "")
|
|
51
|
+
: tags.script({ code, inline, integrity, src, type })).join("\n")).concat("\n", head ?? "");
|
|
51
52
|
};
|
|
52
53
|
const s_http = Symbol("s_http");
|
|
53
54
|
;
|
|
54
55
|
export default class ServeApp extends App {
|
|
55
56
|
#init;
|
|
56
57
|
#server;
|
|
57
|
-
#
|
|
58
|
+
#views;
|
|
58
59
|
#csp = {};
|
|
59
60
|
#assets = [];
|
|
60
61
|
#stores;
|
|
@@ -65,7 +66,7 @@ export default class ServeApp extends App {
|
|
|
65
66
|
constructor(rootfile, init) {
|
|
66
67
|
super(new FileRef(rootfile).directory, init.config, init.mode);
|
|
67
68
|
this.#init = init;
|
|
68
|
-
this.#
|
|
69
|
+
this.#views = Object.fromEntries(init.views ?? []);
|
|
69
70
|
this.#stores = Object.fromEntries((init.stores?.map(([k, s]) => [k, s.default])) ?? []);
|
|
70
71
|
const http = this.#init.config.http;
|
|
71
72
|
this.#i18n_config = init.i18n_config;
|
|
@@ -130,13 +131,14 @@ export default class ServeApp extends App {
|
|
|
130
131
|
get i18n() {
|
|
131
132
|
return this.#i18n_config;
|
|
132
133
|
}
|
|
133
|
-
|
|
134
|
-
const
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
134
|
+
loadView(name) {
|
|
135
|
+
const f = new FileRef(name);
|
|
136
|
+
const base = f.path.slice(0, -f.fullExtension.length);
|
|
137
|
+
const view = this.#views[base];
|
|
138
|
+
if (view === undefined) {
|
|
139
|
+
throw fail("missing view component {0}", `${location.views}/${name}`);
|
|
138
140
|
}
|
|
139
|
-
return (
|
|
141
|
+
return (view.default ?? view);
|
|
140
142
|
}
|
|
141
143
|
;
|
|
142
144
|
headers(csp = {}) {
|
|
@@ -165,14 +167,20 @@ export default class ServeApp extends App {
|
|
|
165
167
|
page(page) {
|
|
166
168
|
return this.loader().page(page);
|
|
167
169
|
}
|
|
170
|
+
body_length(body) {
|
|
171
|
+
return typeof body === "string" ? utf8ByteLength(body) : 0;
|
|
172
|
+
}
|
|
168
173
|
respond(body, init) {
|
|
169
174
|
const { headers, status } = pema({
|
|
170
175
|
headers: record(string, string),
|
|
171
176
|
status: uint.values(Status).default(Status.OK),
|
|
172
177
|
}).parse(init);
|
|
178
|
+
const body_length = this.body_length(body);
|
|
173
179
|
return new Response(body, {
|
|
174
180
|
headers: {
|
|
175
|
-
"Content-Type": TEXT_HTML,
|
|
181
|
+
"Content-Type": TEXT_HTML,
|
|
182
|
+
...this.headers(),
|
|
183
|
+
...body_length ? { ...headers, "Content-Length": String(body_length) } : headers,
|
|
176
184
|
}, status: status,
|
|
177
185
|
});
|
|
178
186
|
}
|
|
@@ -218,9 +226,7 @@ export default class ServeApp extends App {
|
|
|
218
226
|
;
|
|
219
227
|
async start() {
|
|
220
228
|
this.#assets = await Promise.all(this.#init.assets.map(async (asset) => {
|
|
221
|
-
const code = asset.
|
|
222
|
-
? JSON.stringify(asset.code, null, 2)
|
|
223
|
-
: asset.code;
|
|
229
|
+
const code = asset.code;
|
|
224
230
|
return {
|
|
225
231
|
...asset,
|
|
226
232
|
code,
|
|
@@ -239,7 +245,13 @@ export default class ServeApp extends App {
|
|
|
239
245
|
}
|
|
240
246
|
catch (error) {
|
|
241
247
|
log.error(error);
|
|
242
|
-
return new Response(null, {
|
|
248
|
+
return new Response(null, {
|
|
249
|
+
headers: {
|
|
250
|
+
"Content-Length": String(0),
|
|
251
|
+
"Cache-Control": "no-cache",
|
|
252
|
+
},
|
|
253
|
+
status: Status.INTERNAL_SERVER_ERROR,
|
|
254
|
+
});
|
|
243
255
|
}
|
|
244
256
|
}, this.get(s_http));
|
|
245
257
|
log.system("started {0}", this.url);
|
|
@@ -15,9 +15,7 @@ export default class DevModule extends Module {
|
|
|
15
15
|
#reload_url;
|
|
16
16
|
constructor(app) {
|
|
17
17
|
super();
|
|
18
|
-
const assets = app.assets
|
|
19
|
-
.filter(asset => asset.type !== "importmap")
|
|
20
|
-
.map(asset => asset.src);
|
|
18
|
+
const assets = app.assets.map(asset => asset.src);
|
|
21
19
|
const http = app.config("http");
|
|
22
20
|
this.#paths = ([reload_path]).concat(assets);
|
|
23
21
|
this.#reload_url = `http://${http.host}:${reload_defaults.port}`;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @ts-expect-error esbuild vfs
|
|
2
2
|
import * as frontends from "#frontends";
|
|
3
|
-
|
|
3
|
+
class ClientApp {
|
|
4
4
|
start() {
|
|
5
5
|
const hydration = document.getElementById("hydration")?.textContent;
|
|
6
6
|
if (hydration !== undefined) {
|
|
@@ -9,4 +9,6 @@ export default class ClientApp {
|
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
|
-
|
|
12
|
+
const app = new ClientApp();
|
|
13
|
+
app.start();
|
|
14
|
+
//# sourceMappingURL=app.js.map
|
|
@@ -138,6 +138,10 @@ const go = async (href, updater, event) => {
|
|
|
138
138
|
// external redirect
|
|
139
139
|
};
|
|
140
140
|
export default (updater) => {
|
|
141
|
+
if (document.contentType === "application/json") {
|
|
142
|
+
location.reload();
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
141
145
|
globalThis.addEventListener("pageshow", event => {
|
|
142
146
|
if (event.persisted) {
|
|
143
147
|
globalThis.location.reload();
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
+
import type Schema from "#database/Schema";
|
|
1
2
|
import type StoreSchema from "pema/StoreSchema";
|
|
2
|
-
import type DataRecord from "#database/DataRecord";
|
|
3
3
|
type X<T> = {
|
|
4
4
|
[K in keyof T]: T[K];
|
|
5
5
|
} & {};
|
|
6
6
|
type Filter<T, P extends keyof T> = X<Pick<T, Extract<P, keyof T>>>;
|
|
7
|
-
export default class Query<T extends StoreSchema, P extends keyof
|
|
7
|
+
export default class Query<T extends StoreSchema, P extends keyof Schema<T> = keyof Schema<T>> {
|
|
8
8
|
#private;
|
|
9
9
|
constructor(schema: T);
|
|
10
10
|
select<K extends P>(...projection: K[]): Query<T, K>;
|
|
11
|
-
run(): Promise<Filter<
|
|
11
|
+
run(): Promise<Filter<Schema<T>, P>>;
|
|
12
12
|
}
|
|
13
13
|
export {};
|
|
14
14
|
//# sourceMappingURL=Query.d.ts.map
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import type Schema from "#database/Schema";
|
|
2
2
|
import type InferStoreOut from "pema/InferStoreOut";
|
|
3
3
|
import type StoreSchema from "pema/StoreSchema";
|
|
4
4
|
type X<T> = {
|
|
5
5
|
[K in keyof T]: T[K];
|
|
6
6
|
} & {};
|
|
7
7
|
type Filter<T, P extends keyof T> = X<Pick<T, Extract<P, keyof T>>>;
|
|
8
|
-
export default abstract class QueryBuilder<T extends StoreSchema, P extends keyof
|
|
8
|
+
export default abstract class QueryBuilder<T extends StoreSchema, P extends keyof Schema<T> = keyof Schema<T>> {
|
|
9
9
|
abstract where(criteria: any): QueryBuilder<T>;
|
|
10
10
|
abstract select<K extends P>(...fields: K[]): QueryBuilder<T, K>;
|
|
11
11
|
abstract run(): Promise<Filter<InferStoreOut<T>, P>>;
|
|
@@ -3,6 +3,6 @@ import type StoreSchema from "pema/StoreSchema";
|
|
|
3
3
|
type X<T> = {
|
|
4
4
|
[K in keyof T]: T[K];
|
|
5
5
|
} & {};
|
|
6
|
-
type
|
|
7
|
-
export type {
|
|
8
|
-
//# sourceMappingURL=
|
|
6
|
+
type Schema<T extends StoreSchema> = X<InferStoreOut<T>>;
|
|
7
|
+
export type { Schema as default };
|
|
8
|
+
//# sourceMappingURL=Schema.d.ts.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type Changes from "#database/Changes";
|
|
2
2
|
import type Database from "#database/Database";
|
|
3
|
-
import type
|
|
3
|
+
import type Schema from "#database/Schema";
|
|
4
4
|
import wrap from "#database/symbol/wrap";
|
|
5
5
|
import type Types from "#database/Types";
|
|
6
6
|
import type Dict from "@rcompat/type/Dict";
|
|
@@ -48,7 +48,7 @@ type Config = {
|
|
|
48
48
|
export default class DatabaseStore<S extends StoreSchema> implements Serializable {
|
|
49
49
|
#private;
|
|
50
50
|
[wrap]: (name: string, database: Database) => this;
|
|
51
|
-
readonly
|
|
51
|
+
readonly Schema: Schema<S>;
|
|
52
52
|
constructor(schema: S, config?: Config);
|
|
53
53
|
static new<S extends StoreSchema>(schema: S, config?: Config): DatabaseStore<S>;
|
|
54
54
|
get schema(): {
|
|
@@ -82,14 +82,14 @@ export default class DatabaseStore<S extends StoreSchema> implements Serializabl
|
|
|
82
82
|
* @throws If no record with the given id exists.
|
|
83
83
|
* @returns The record for the given id.
|
|
84
84
|
*/
|
|
85
|
-
get(id: Id): Promise<
|
|
85
|
+
get(id: Id): Promise<Schema<S>>;
|
|
86
86
|
/**
|
|
87
87
|
* Try to get a record by id.
|
|
88
88
|
*
|
|
89
89
|
* @param id Record id.
|
|
90
90
|
* @returns The record if found, otherwise `undefined`.
|
|
91
91
|
*/
|
|
92
|
-
try(id: Id): Promise<
|
|
92
|
+
try(id: Id): Promise<Schema<S> | undefined>;
|
|
93
93
|
/**
|
|
94
94
|
* Insert a single record.
|
|
95
95
|
*
|
|
@@ -100,7 +100,7 @@ export default class DatabaseStore<S extends StoreSchema> implements Serializabl
|
|
|
100
100
|
* @throws If a record with the same id already exists or validation fails.
|
|
101
101
|
* @returns The inserted record with id.
|
|
102
102
|
*/
|
|
103
|
-
insert(record: Insertable<S>): Promise<
|
|
103
|
+
insert(record: Insertable<S>): Promise<Schema<S>>;
|
|
104
104
|
/**
|
|
105
105
|
* Update a single record.
|
|
106
106
|
*
|
|
@@ -148,17 +148,17 @@ export default class DatabaseStore<S extends StoreSchema> implements Serializabl
|
|
|
148
148
|
* @param options Query options.
|
|
149
149
|
* @returns Matching records, possibly projected/limited/sorted.
|
|
150
150
|
*/
|
|
151
|
-
find(criteria: Criteria<S>): Promise<Filter<
|
|
151
|
+
find(criteria: Criteria<S>): Promise<Filter<Schema<S>>[]>;
|
|
152
152
|
find(criteria: Criteria<S>, options: {
|
|
153
153
|
limit?: number;
|
|
154
154
|
select?: undefined;
|
|
155
|
-
sort?: Sort<
|
|
156
|
-
}): Promise<Filter<
|
|
157
|
-
find<F extends Select<
|
|
155
|
+
sort?: Sort<Schema<S>>;
|
|
156
|
+
}): Promise<Filter<Schema<S>>[]>;
|
|
157
|
+
find<F extends Select<Schema<S>>>(criteria: Criteria<S>, options?: {
|
|
158
158
|
limit?: number;
|
|
159
159
|
select?: F;
|
|
160
|
-
sort?: Sort<
|
|
161
|
-
}): Promise<Filter<
|
|
160
|
+
sort?: Sort<Schema<S>>;
|
|
161
|
+
}): Promise<Filter<Schema<S>, F>[]>;
|
|
162
162
|
toJSON(): {
|
|
163
163
|
type: "object";
|
|
164
164
|
properties: Dict<import("pema/StoreType").Serialized>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type App from "#App";
|
|
2
2
|
import type BuildApp from "#BuildApp";
|
|
3
3
|
import type Render from "#frontend/Render";
|
|
4
|
-
import type
|
|
4
|
+
import type ServerView from "#frontend/ServerView";
|
|
5
5
|
import type ViewResponse from "#frontend/ViewResponse";
|
|
6
6
|
import Module from "#Module";
|
|
7
7
|
import type Next from "#module/Next";
|
|
@@ -10,7 +10,7 @@ import type NextServe from "#module/NextServe";
|
|
|
10
10
|
import type ServeApp from "#ServeApp";
|
|
11
11
|
import FileRef from "@rcompat/fs/FileRef";
|
|
12
12
|
import type MaybePromise from "@rcompat/type/MaybePromise";
|
|
13
|
-
export default abstract class FrontendModule<S =
|
|
13
|
+
export default abstract class FrontendModule<S = ServerView> extends Module {
|
|
14
14
|
#private;
|
|
15
15
|
abstract client: boolean;
|
|
16
16
|
abstract layouts: boolean;
|