@primate/core 0.2.4 → 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.
Files changed (64) hide show
  1. package/lib/private/App.d.ts +5 -0
  2. package/lib/private/App.js +18 -13
  3. package/lib/private/Binder.d.ts +1 -1
  4. package/lib/private/BindingContext.d.ts +1 -1
  5. package/lib/private/BuildApp.d.ts +7 -1
  6. package/lib/private/BuildApp.js +33 -33
  7. package/lib/private/Loader.d.ts +1 -1
  8. package/lib/private/Loader.js +4 -3
  9. package/lib/private/ServeApp.d.ts +8 -6
  10. package/lib/private/ServeApp.js +29 -20
  11. package/lib/private/ServeInit.d.ts +1 -1
  12. package/lib/private/backend/TAG.d.ts +3 -0
  13. package/lib/private/backend/TAG.js +2 -0
  14. package/lib/private/builtin/DevModule.js +1 -3
  15. package/lib/private/client/Data.d.ts +1 -1
  16. package/lib/private/client/app.d.ts +2 -0
  17. package/lib/private/client/{App.js → app.js} +4 -2
  18. package/lib/private/client/spa/index.js +4 -0
  19. package/lib/private/database/Query.d.ts +3 -3
  20. package/lib/private/database/QueryBuilder.d.ts +2 -2
  21. package/lib/private/database/{DataRecord.d.ts → Schema.d.ts} +3 -3
  22. package/lib/private/database/Schema.js +3 -0
  23. package/lib/private/database/Store.d.ts +11 -11
  24. package/lib/private/frontend/Module.d.ts +2 -2
  25. package/lib/private/frontend/Module.js +47 -40
  26. package/lib/private/frontend/Render.d.ts +1 -1
  27. package/lib/private/frontend/ServerData.d.ts +2 -2
  28. package/lib/private/frontend/ServerView.d.ts +5 -0
  29. package/lib/private/frontend/ServerView.js +2 -0
  30. package/lib/private/frontend/View.d.ts +8 -0
  31. package/lib/private/frontend/View.js +2 -0
  32. package/lib/private/frontend/bundle-server.js +3 -3
  33. package/lib/private/hook/build.js +83 -75
  34. package/lib/private/i18n/Module.js +16 -3
  35. package/lib/private/location.d.ts +2 -0
  36. package/lib/private/location.js +4 -0
  37. package/lib/private/request/RequestBody.d.ts +8 -7
  38. package/lib/private/request/RequestBody.js +30 -14
  39. package/lib/private/response/ResponseFunction.d.ts +2 -2
  40. package/lib/private/response/redirect.js +5 -1
  41. package/lib/private/response/view.d.ts +3 -3
  42. package/lib/private/response/view.js +14 -12
  43. package/lib/private/route/wrap.d.ts +1 -5
  44. package/lib/private/route/wrap.js +4 -9
  45. package/lib/private/target/Manager.js +1 -1
  46. package/lib/private/target/web.js +0 -10
  47. package/lib/private/wasm/encode-request.js +25 -28
  48. package/lib/public/backend/TAG.d.ts +2 -0
  49. package/lib/public/backend/TAG.js +2 -0
  50. package/lib/public/client/app.d.ts +2 -0
  51. package/lib/public/client/app.js +2 -0
  52. package/lib/public/fail.d.ts +2 -0
  53. package/lib/public/fail.js +2 -0
  54. package/package.json +4 -4
  55. package/lib/private/client/App.d.ts +0 -4
  56. package/lib/private/database/DataRecord.js +0 -3
  57. package/lib/private/frontend/Component.d.ts +0 -8
  58. package/lib/private/frontend/Component.js +0 -2
  59. package/lib/private/frontend/ServerComponent.d.ts +0 -5
  60. package/lib/private/frontend/ServerComponent.js +0 -2
  61. package/lib/public/client/App.d.ts +0 -2
  62. package/lib/public/client/App.js +0 -2
  63. package/lib/public/route/wrap.d.ts +0 -2
  64. package/lib/public/route/wrap.js +0 -2
@@ -1,4 +1,4 @@
1
- import AppError from "#AppError";
1
+ import fail from "#fail";
2
2
  import bundle from "#frontend/bundle-server";
3
3
  import inline from "#inline";
4
4
  import location from "#location";
@@ -13,13 +13,13 @@ import pema from "pema";
13
13
  import array from "pema/array";
14
14
  import boolean from "pema/boolean";
15
15
  import string from "pema/string";
16
- const contexts = ["lib", "components"];
16
+ const contexts = ["views", "components"];
17
17
  async function normalize(path) {
18
18
  return `p_${await hash(path)}`;
19
19
  }
20
20
  export default class FrontendModule extends Module {
21
21
  #options;
22
- render = async (component, props) => ({ body: await component(props) });
22
+ render = async (view, props) => ({ body: await view(props) });
23
23
  root;
24
24
  compile = {};
25
25
  css;
@@ -50,39 +50,41 @@ export default class FrontendModule extends Module {
50
50
  return this.#options.spa;
51
51
  }
52
52
  #load(name, props, app) {
53
- const component = app.component(name);
54
- return { component, name, props };
53
+ const view = app.loadView(name);
54
+ return { view, name, props };
55
55
  }
56
56
  ;
57
57
  async #render(server, client, app) {
58
58
  const { body, head = "", headers = {} } = this.ssr
59
- ? await this.render(server.component, server.props)
59
+ ? await this.render(server.view, server.props)
60
60
  : { body: "", head: "" };
61
61
  if (!this.client) {
62
62
  return { body, head, headers };
63
63
  }
64
- const code = "import app from \"app\"; app.start();";
65
- const inlined = await inline(code, "module");
64
+ const app_asset = app.assets.find(asset => asset.src?.includes("app") && asset.src.endsWith(".js"));
65
+ if (!app_asset)
66
+ throw fail("Could not find app.js in assets");
67
+ const app_script = `<script type="module" src="${app_asset.src}" integrity="${app_asset.integrity}"></script>`;
66
68
  const json_props = JSON.stringify({ frontend: this.name, ...client });
67
69
  const hydrated = await inline(json_props, APPLICATION_JSON, "hydration");
68
- const script_src = [inlined.integrity, hydrated.integrity];
70
+ const script_src = [hydrated.integrity, `'${app_asset.integrity}'`];
69
71
  return {
70
72
  body,
71
- head: head.concat(inlined.head, hydrated.head),
73
+ head: head.concat(app_script, hydrated.head),
72
74
  headers: app.headers({ "script-src": script_src }),
73
75
  };
74
76
  }
75
77
  normalize(name) {
76
78
  return normalize(name);
77
79
  }
78
- respond = (component, props = {}, options = {}) => async (app, { as_layout, layouts = [] } = {}, request) => {
80
+ respond = (view, props = {}, options = {}) => async (app, { as_layout, layouts = [] } = {}, request) => {
79
81
  if (as_layout) {
80
- return this.#load(component, props, app);
82
+ return this.#load(view, props, app);
81
83
  }
82
- const components = (await Promise.all(layouts
84
+ const views = (await Promise.all(layouts
83
85
  .map(layout => layout(app, { as_layout: true }, request))))
84
- /* set the actual page as the last component */
85
- .concat(this.#load(component, props, app));
86
+ /* set the actual page as the last view */
87
+ .concat(this.#load(view, props, app));
86
88
  const $request = {
87
89
  context: request.context,
88
90
  cookies: request.cookies.toJSON(),
@@ -93,35 +95,41 @@ export default class FrontendModule extends Module {
93
95
  };
94
96
  const $props = this.layouts
95
97
  ? {
96
- components: await map(components, ({ name }) => normalize(name)),
97
- props: components.map(c => c.props),
98
+ views: await map(views, ({ name }) => normalize(name)),
99
+ props: views.map(c => c.props),
98
100
  request: $request,
99
101
  }
100
102
  : { props, request: $request };
101
103
  const client = {
102
- component: this.layouts ? "root" : await normalize(component),
104
+ view: this.layouts ? "root" : await normalize(view),
103
105
  spa: this.spa,
104
106
  ssr: this.ssr,
105
107
  ...$props,
106
108
  };
107
109
  if (this.spa && request.headers.get("Accept") === APPLICATION_JSON) {
108
- return new Response(JSON.stringify(client), {
109
- headers: { ...app.headers(), "Content-Type": APPLICATION_JSON },
110
+ const json_body = JSON.stringify(client);
111
+ return new Response(json_body, {
112
+ headers: {
113
+ ...app.headers(),
114
+ "Content-Type": APPLICATION_JSON,
115
+ "Content-Length": String(app.body_length(json_body)),
116
+ "Cache-Control": "no-store",
117
+ },
110
118
  status: options.status ?? Status.OK,
111
119
  });
112
120
  }
113
121
  try {
114
122
  const server = this.layouts
115
123
  ? {
116
- component: app.component(`${this.rootname}.js`),
124
+ view: app.loadView(`${this.rootname}.js`),
117
125
  props: {
118
- components: components.map(c => c.component),
119
- props: components.map(c => c.props),
126
+ views: views.map(c => c.view),
127
+ props: views.map(c => c.props),
120
128
  request: $request,
121
129
  },
122
130
  }
123
131
  : {
124
- component: app.component(component),
132
+ view: app.loadView(view),
125
133
  props,
126
134
  request: $request,
127
135
  };
@@ -129,8 +137,8 @@ export default class FrontendModule extends Module {
129
137
  return app.view({ body, head, headers, ...options });
130
138
  }
131
139
  catch (error) {
132
- const path = `${location.components}/${component}`;
133
- throw new AppError("error in component {0}\n{1}", path, error);
140
+ const path = `${location.views}/${view}`;
141
+ throw fail("error in view{0}\n{1}", path, error);
134
142
  }
135
143
  };
136
144
  serve(app, next) {
@@ -168,19 +176,19 @@ export default class FrontendModule extends Module {
168
176
  : null;
169
177
  });
170
178
  }
171
- const components_filter = new RegExp(`^${name}:components`);
172
- const components_base = app.root.join(location.components);
173
- build.onResolve({ filter: components_filter }, ({ path }) => {
179
+ const views_filter = new RegExp(`^${name}:views`);
180
+ const views_base = app.root.join(location.views);
181
+ build.onResolve({ filter: views_filter }, ({ path }) => {
174
182
  return { namespace: `${name}`, path };
175
183
  });
176
- build.onLoad({ filter: components_filter }, async () => {
177
- const components = await components_base
184
+ build.onLoad({ filter: views_filter }, async () => {
185
+ const views = await views_base
178
186
  .collect(c => fileExtensions.includes(c.fullExtension));
179
187
  let contents = "";
180
- for (const component of components) {
181
- const { path } = component.debase(components_base, "/");
188
+ for (const view of views) {
189
+ const { path } = view.debase(views_base, "/");
182
190
  contents += `export { default as ${await normalize(path)} }
183
- from "#component/${path}";\n`;
191
+ from "#view/${path}";\n`;
184
192
  }
185
193
  return { contents, resolveDir: app.root.path };
186
194
  });
@@ -207,20 +215,19 @@ export default class FrontendModule extends Module {
207
215
  init(app, next) {
208
216
  this.fileExtensions.forEach(e => {
209
217
  app.bind(e, async (file, { context }) => {
210
- assert(contexts.includes(context), `${this.name}: only components or lib supported`);
218
+ assert(contexts.includes(context), `${this.name}: only components supported`);
211
219
  if (this.compile.server) {
212
- const original = file.debase(app.runpath("stage", context));
213
- const source = app.path[context].join(original);
214
- const code = await this.compile.server(await source.text());
220
+ const code = await this.compile.server(await file.text());
215
221
  const bundled = await bundle({
216
222
  code,
217
- source,
223
+ source: file,
218
224
  root: app.root,
219
225
  extensions: this.fileExtensions,
220
226
  compile: async (s) => this.compile.server(s),
221
227
  });
222
- await file.append(".js").write(bundled);
228
+ return bundled;
223
229
  }
230
+ return await file.text();
224
231
  });
225
232
  });
226
233
  return next(app);
@@ -1,6 +1,6 @@
1
1
  import type Dict from "@rcompat/type/Dict";
2
2
  import type MaybePromise from "@rcompat/type/MaybePromise";
3
- type Render<S = unknown> = (component: S, props: Dict) => MaybePromise<{
3
+ type Render<V = unknown> = (view: V, props: Dict) => MaybePromise<{
4
4
  body: string;
5
5
  head?: string;
6
6
  headers?: Record<string, string>;
@@ -1,6 +1,6 @@
1
1
  import type Dict from "@rcompat/type/Dict";
2
- type ServerData<T> = {
3
- component: T;
2
+ type ServerData<V> = {
3
+ view: V;
4
4
  props: Dict;
5
5
  };
6
6
  export type { ServerData as default };
@@ -0,0 +1,5 @@
1
+ import type Dict from "@rcompat/type/Dict";
2
+ import type MaybePromise from "@rcompat/type/MaybePromise";
3
+ type ServerView = (props: Dict) => MaybePromise<string>;
4
+ export { ServerView as default };
5
+ //# sourceMappingURL=ServerView.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ServerView.js.map
@@ -0,0 +1,8 @@
1
+ import type Dict from "@rcompat/type/Dict";
2
+ type View = {
3
+ view: unknown;
4
+ name: string;
5
+ props: Dict;
6
+ };
7
+ export type { View as default };
8
+ //# sourceMappingURL=View.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=View.js.map
@@ -13,12 +13,12 @@ export default async function bundleServer(init) {
13
13
  const contents = await compile(src, file);
14
14
  return { contents, loader: "js", resolveDir: file.directory.path };
15
15
  });
16
- // externalise anything not relative nor "#component/"
16
+ // externalise anything not relative nor "#view/"
17
17
  build.onResolve({ filter: /.*/ }, args => {
18
18
  const p = args.path;
19
19
  const relative = p.startsWith("./") || p.startsWith("../");
20
- const components = p.startsWith("#component/");
21
- if (!relative && !components)
20
+ const views = p.startsWith("#view/");
21
+ if (!relative && !views)
22
22
  return { path: p, external: true };
23
23
  return null;
24
24
  });
@@ -1,8 +1,9 @@
1
- import AppError from "#AppError";
1
+ import fail from "#fail";
2
2
  import location from "#location";
3
3
  import log from "#log";
4
4
  import reducer from "#reducer";
5
5
  import $router from "#request/router";
6
+ import wrap from "#route/wrap";
6
7
  import s_layout_depth from "#symbol/layout-depth";
7
8
  import FileRef from "@rcompat/fs/FileRef";
8
9
  import json from "@rcompat/package/json";
@@ -12,10 +13,10 @@ const pre = async (app) => {
12
13
  // remove build directory in case exists
13
14
  await app.path.build.remove();
14
15
  await app.path.build.create();
15
- await Promise.all(["server", "client", "components"]
16
+ await Promise.all(["server", "client", "views"]
16
17
  .map(directory => app.runpath(directory).create()));
17
18
  // this has to occur before post, so that layout depth is available for
18
- // compiling root components
19
+ // compiling root views
19
20
  // bindings should have been registered during `init`
20
21
  const router = await $router(app.path.routes, app.extensions);
21
22
  app.set(s_layout_depth, router.depth("layout"));
@@ -27,33 +28,36 @@ const pre = async (app) => {
27
28
  app.i18n_active = has_i18n_config;
28
29
  return app;
29
30
  };
30
- async function indexDatabase(base) {
31
- const export_from = "export { default } from";
32
- const default_database = `${export_from} "#stage/config/database/index.js";`;
33
- // app/config/database does not exist
31
+ async function index_database(base) {
32
+ // app/config/database does not exist -> use prelayered default
34
33
  if (!await base.exists())
35
- return default_database;
34
+ return "";
36
35
  const databases = await base.list();
37
36
  const n = databases.length;
38
- // none in app/config/database -> fallback
37
+ // none in app/config/database -> use prelayered default
39
38
  if (n === 0)
40
- return default_database;
41
- // index database file found, will be overwritten in next step
42
- if (databases.some(d => d.base === "index"))
43
39
  return "";
44
40
  const names = databases.map(d => d.name);
45
- // app/config/database/default.ts -> use
46
- const ts = names.includes("default.ts");
47
- if (ts)
48
- return `${export_from} "#stage/config/database/default.ts";`;
49
- // app/config/database/default.js -> use
50
- const js = names.includes("default.js");
51
- if (js)
52
- return `${export_from} "#stage/config/database/default.js";`;
53
- // one in app/config/database -> default
54
- if (n === 1)
55
- return `${export_from} "#stage/config/database/${names[0]}";`;
56
- throw new AppError("Multiple database drivers; add index or default.(ts|js). Found: {0}", names.join(", "));
41
+ // index database file found, will be overwritten in next step -> do nothing
42
+ if (names.includes("index.ts") || names.includes("index.js")) {
43
+ return ""; // empty string means: don't generate, user provided own
44
+ }
45
+ // app/config/default.ts -> reexport
46
+ if (names.includes("default.ts")) {
47
+ return "export { default } from \"./default.js\";";
48
+ }
49
+ // app/config/default.js -> reexport
50
+ if (names.includes("default.js")) {
51
+ return "export { default } from \"./default.js\";";
52
+ }
53
+ // exactly one in app/config/database -> reexport that
54
+ if (n === 1) {
55
+ const onlyFile = names[0];
56
+ const withoutExt = onlyFile.replace(/\.(ts|js)$/, ".js");
57
+ return `export { default } from "./${withoutExt}";`;
58
+ }
59
+ // multiple files, none is index or default -> error
60
+ throw fail("multiple database drivers, add index or default.(ts|js); found {0}", names.join(", "));
57
61
  }
58
62
  const js_re = /^.*.js$/;
59
63
  const write_directories = async (build_directory, app) => {
@@ -81,22 +85,22 @@ store.push(["${FileRef.webpath(bare)}", store${i}]);`).join("\n")}
81
85
  export default store;`;
82
86
  await build_directory.join("stores.js").write(stores_js);
83
87
  };
84
- const write_components = async (build_directory, app) => {
85
- const d2 = app.runpath(location.components);
88
+ const write_views = async (build_directory, app) => {
89
+ const d2 = app.runpath(location.views);
86
90
  const e = await Promise.all((await FileRef.collect(d2, file => js_re.test(file.path)))
87
91
  .map(async (path) => `${path}`.replace(d2.toString(), _ => "")));
88
- const components_js = `
89
- const component = [];
90
- ${e.map(path => path.slice(1, -".js".length)).map((bare, i) => `import * as component${i} from "${FileRef.webpath(`#component/${bare}`)}";
91
- component.push(["${FileRef.webpath(bare)}", component${i}]);`).join("\n")}
92
+ const views_js = `
93
+ const view = [];
94
+ ${e.map(path => path.slice(1, -".js".length)).map((bare, i) => `import * as view${i} from "${FileRef.webpath(`#view/${bare}`)}";
95
+ view.push(["${FileRef.webpath(bare)}", view${i}]);`).join("\n")}
92
96
 
93
97
  ${app.roots.map((root, i) => `
94
98
  import * as root${i} from "${FileRef.webpath(`../server/${root.name}`)}";
95
- component.push(["${root.name.slice(0, -".js".length)}", root${i}]);
99
+ view.push(["${root.name.slice(0, -".js".length)}", root${i}]);
96
100
  `).join("\n")}
97
101
 
98
- export default component;`;
99
- await build_directory.join("components.js").write(components_js);
102
+ export default view;`;
103
+ await build_directory.join("views.js").write(views_js);
100
104
  };
101
105
  const write_bootstrap = async (app, mode, i18n_active) => {
102
106
  const build_start_script = `
@@ -104,7 +108,7 @@ import serve from "primate/serve";
104
108
  const files = {};
105
109
  ${app.server_build.map(name => `${name}s`).map(name => `import ${name} from "./${app.id}/${name}.js";
106
110
  files.${name} = ${name};`).join("\n")}
107
- import components from "./${app.id}/components.js";
111
+ import views from "./${app.id}/views.js";
108
112
  import stores from "./${app.id}/stores.js";
109
113
  import target from "./target.js";
110
114
  import session from "#session";
@@ -122,7 +126,7 @@ const app = await serve(import.meta.url, {
122
126
  ...target,
123
127
  config,
124
128
  files,
125
- components,
129
+ views,
126
130
  stores,
127
131
  mode: "${mode}",
128
132
  session_config: session[s_config],
@@ -135,39 +139,50 @@ export default app;
135
139
  };
136
140
  const post = async (app) => {
137
141
  const defaults = FileRef.join(import.meta.url, "../../defaults");
138
- await app.stage(app.path.routes, "routes", file => dedent `
139
- export * from "#stage/route${file}";
140
- `);
141
- await app.stage(app.path.stores, "stores", file => dedent `
142
- import database from "#database";
143
- import store from "#stage/store${file}";
144
- import wrap from "primate/database/wrap";
145
-
146
- export default await wrap("${file.base}", store, database);
147
- `);
142
+ await app.compile(app.path.routes, "routes", {
143
+ loader: (source, file) => {
144
+ const path = app.basename(file, app.path.routes);
145
+ return wrap(source, path, app.id);
146
+ },
147
+ });
148
+ await app.compile(app.path.stores, "stores", {
149
+ resolver: basename => `${basename}.original`, // First pass: save original
150
+ });
151
+ if (await app.path.stores.exists()) {
152
+ const stores = await app.path.stores.collect(({ path }) => app.extensions.some(e => path.endsWith(e)));
153
+ for (const file of stores) {
154
+ const basename = app.basename(file, app.path.stores);
155
+ const wrapper = dedent `
156
+ import database from "#database";
157
+ import store from "./${basename}.original.js";
158
+ import wrap from "primate/database/wrap";
159
+ export default wrap("${basename}", store, database);
160
+ `;
161
+ const target = app.runpath("stores", `${basename}.js`);
162
+ await target.write(wrapper);
163
+ }
164
+ }
148
165
  const configs = FileRef.join(dirname, "../../private/config/config");
149
166
  const database_base = app.path.config.join("database");
150
- await app.stage(configs, "config", async (file) => {
151
- if (file.path === "/database/index.js")
152
- return indexDatabase(database_base);
153
- return `export { default } from "#stage/config${file}";`;
167
+ // prelayer config default
168
+ await app.compile(configs, "config", {
169
+ loader: async (source, file) => {
170
+ const relative = file.debase(configs);
171
+ if (relative.path === "/database/index.js") {
172
+ const indexContent = await index_database(database_base);
173
+ // if empty, user provided own index -> use the compiled source
174
+ return indexContent || source;
175
+ }
176
+ return source;
177
+ },
154
178
  });
155
- await app.stage(app.path.modules, "modules", file => `export { default } from "#stage/module${file}";`);
156
- // stage locales
157
- await app.stage(app.path.locales, "locales", file => `export { default } from "#stage/locale${file}";`);
158
- // stage app config after locales so #locale imports can be resolved
159
- await app.stage(app.path.config, "config", file => `export { default } from "#stage/config${file}";`);
160
- // component library
161
- await app.stage(app.path.lib, "lib", file => `
162
- export * from "#stage/lib${file}";
163
- `);
164
- // stage components
165
- await app.stage(app.path.components, "components", file => `
166
- import * as component from "#stage/component${file}";
167
-
168
- export * from "#stage/component${file}";
169
- export default component?.default;
170
- `);
179
+ await app.compile(app.path.modules, "modules");
180
+ await app.compile(app.path.locales, "locales");
181
+ await app.compile(app.path.config, "config");
182
+ // reusable components
183
+ await app.compile(app.path.components, "components");
184
+ // view components
185
+ await app.compile(app.path.views, "views");
171
186
  // copy framework pages
172
187
  await defaults.copy(app.runpath(location.server, location.pages));
173
188
  // copy pages to build
@@ -184,7 +199,7 @@ const post = async (app) => {
184
199
  const src = file.debase(app.path.static);
185
200
  app.build.export(`import "./${location.static}${src}";`);
186
201
  }));
187
- app.build.export("export { default } from \"primate/client/app\";");
202
+ app.build.export("import \"primate/client/app\";");
188
203
  app.build.plugin({
189
204
  name: "@primate/core/frontend",
190
205
  setup(build) {
@@ -213,7 +228,7 @@ const post = async (app) => {
213
228
  const build_directory = app.path.build.join(app.id);
214
229
  // TODO: remove after rcompat automatically creates directories
215
230
  await build_directory.create();
216
- await write_components(build_directory, app);
231
+ await write_views(build_directory, app);
217
232
  await write_stores(build_directory, app);
218
233
  await write_directories(build_directory, app);
219
234
  await write_bootstrap(app, app.mode, app.i18n_active);
@@ -227,18 +242,11 @@ const post = async (app) => {
227
242
  "#database/*": "./config/database/*.js",
228
243
  "#session": "./config/session.js",
229
244
  "#i18n": "./config/i18n.js",
230
- "#lib/*": "./lib/*.js",
245
+ "#view/*": "./views/*.js",
231
246
  "#component/*": "./components/*.js",
232
247
  "#locale/*": "./locales/*.js",
233
248
  "#module/*": "./modules/*.js",
234
249
  "#route/*": "./routes/*.js",
235
- "#stage/lib/*": "./stage/lib/*.js",
236
- "#stage/component/*": "./stage/components/*.js",
237
- "#stage/locale/*": "./stage/locales/*.js",
238
- "#stage/config/*": "./stage/config/*.js",
239
- "#stage/module/*": "./stage/modules/*.js",
240
- "#stage/route/*": "./stage/routes/*.js",
241
- "#stage/store/*": "./stage/stores/*.js",
242
250
  "#store/*": "./stores/*.js",
243
251
  },
244
252
  };
@@ -66,17 +66,30 @@ export default class I18NModule extends Module {
66
66
  return next(request);
67
67
  // only cookie-persistance is server-supported
68
68
  if (this.#persist !== "cookie")
69
- return new Response(null, { status: Status.NO_CONTENT });
69
+ return new Response(null, {
70
+ headers: {
71
+ "Content-Length": String(0),
72
+ },
73
+ status: Status.NO_CONTENT
74
+ });
70
75
  // only accept configured locales
71
76
  if (!this.#configured(requested))
72
- return new Response(null, { status: Status.NO_CONTENT });
77
+ return new Response(null, {
78
+ headers: {
79
+ "Content-Length": String(0),
80
+ },
81
+ status: Status.NO_CONTENT
82
+ });
73
83
  const header = cookie(COOKIE_NAME, requested, {
74
84
  secure: this.#secure,
75
85
  path: "/",
76
86
  sameSite: "Strict",
77
87
  });
78
88
  return new Response(null, {
79
- headers: { "set-cookie": header },
89
+ headers: {
90
+ "Set-Cookie": header,
91
+ "Content-Length": String(0),
92
+ },
80
93
  status: Status.NO_CONTENT,
81
94
  });
82
95
  }
@@ -13,6 +13,8 @@ declare const _default: {
13
13
  readonly static: "static";
14
14
  readonly stores: "stores";
15
15
  readonly locales: "locales";
16
+ readonly views: "views";
17
+ readonly hooks: "hooks";
16
18
  };
17
19
  export default _default;
18
20
  //# sourceMappingURL=location.d.ts.map
@@ -27,5 +27,9 @@ export default {
27
27
  stores: "stores",
28
28
  // locales
29
29
  locales: "locales",
30
+ // views
31
+ views: "views",
32
+ // hooks
33
+ hooks: "hooks",
30
34
  };
31
35
  //# sourceMappingURL=location.js.map
@@ -1,13 +1,13 @@
1
1
  import type Dict from "@rcompat/type/Dict";
2
2
  import type JSONValue from "@rcompat/type/JSONValue";
3
3
  import type Schema from "@rcompat/type/Schema";
4
- type Fields = Dict<FormDataEntryValue>;
4
+ type Form = Dict<string>;
5
5
  type Parsed = {
6
6
  type: "binary";
7
7
  value: Blob;
8
8
  } | {
9
- type: "fields";
10
- value: Fields;
9
+ type: "form";
10
+ value: Dict<string>;
11
11
  } | {
12
12
  type: "json";
13
13
  value: JSONValue;
@@ -25,12 +25,13 @@ export default class RequestBody {
25
25
  #private;
26
26
  static parse(request: Request, url: URL): Promise<RequestBody>;
27
27
  static none(): RequestBody;
28
- constructor(p: Parsed);
29
- get type(): "binary" | "fields" | "json" | "none" | "text";
28
+ constructor(parsed: Parsed, files?: Dict<File>);
29
+ get type(): "binary" | "form" | "json" | "none" | "text";
30
30
  json(): JSONValue;
31
31
  json<S extends Schema<unknown>>(schema: S): ParseReturn<S>;
32
- fields(): Fields;
33
- fields<S extends Schema<unknown>>(schema: S): ParseReturn<S>;
32
+ form(): Form;
33
+ form<S extends Schema<unknown>>(schema: S): ParseReturn<S>;
34
+ files(): Dict<File>;
34
35
  text(): string;
35
36
  binary(): Blob;
36
37
  none(): null;