@primate/core 0.3.4 → 0.4.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.
Files changed (157) hide show
  1. package/lib/private/App.d.ts +5 -19
  2. package/lib/private/App.js +13 -75
  3. package/lib/private/Binder.d.ts +1 -3
  4. package/lib/private/Flags.d.ts +7 -0
  5. package/lib/private/Flags.js +7 -0
  6. package/lib/private/Module.d.ts +2 -2
  7. package/lib/private/backend/TAG.d.ts +1 -1
  8. package/lib/private/backend/TAG.js +1 -1
  9. package/lib/private/build/App.d.ts +34 -0
  10. package/lib/private/build/App.js +103 -0
  11. package/lib/private/build/client/index.d.ts +3 -0
  12. package/lib/private/build/client/index.js +95 -0
  13. package/lib/private/build/client/plugin/alias.d.ts +4 -0
  14. package/lib/private/build/client/plugin/alias.js +12 -0
  15. package/lib/private/build/client/plugin/entrypoint.d.ts +4 -0
  16. package/lib/private/build/client/plugin/entrypoint.js +15 -0
  17. package/lib/private/build/client/plugin/frontend.d.ts +4 -0
  18. package/lib/private/build/client/plugin/frontend.js +15 -0
  19. package/lib/private/build/client/plugin/server-stamp.d.ts +4 -0
  20. package/lib/private/build/client/plugin/server-stamp.js +14 -0
  21. package/lib/private/build/client/reload.d.ts +7 -0
  22. package/lib/private/build/client/reload.js +6 -0
  23. package/lib/private/{hook/build.d.ts → build/hook.d.ts} +2 -2
  24. package/lib/private/build/hook.js +49 -0
  25. package/lib/private/build/index.d.ts +4 -0
  26. package/lib/private/{build.js → build/index.js} +7 -5
  27. package/lib/private/build/server/index.d.ts +3 -0
  28. package/lib/private/build/server/index.js +89 -0
  29. package/lib/private/build/server/plugin/assets.d.ts +4 -0
  30. package/lib/private/build/server/plugin/assets.js +67 -0
  31. package/lib/private/build/server/plugin/config.d.ts +4 -0
  32. package/lib/private/build/server/plugin/config.js +43 -0
  33. package/lib/private/build/server/plugin/database-default.d.ts +4 -0
  34. package/lib/private/build/server/plugin/database-default.js +48 -0
  35. package/lib/private/build/server/plugin/frontend.d.ts +4 -0
  36. package/lib/private/build/server/plugin/frontend.js +21 -0
  37. package/lib/private/build/server/plugin/hot-reload.d.ts +4 -0
  38. package/lib/private/build/server/plugin/hot-reload.js +36 -0
  39. package/lib/private/build/server/plugin/native-addons.d.ts +4 -0
  40. package/lib/private/build/server/plugin/native-addons.js +55 -0
  41. package/lib/private/build/server/plugin/node-imports.d.ts +4 -0
  42. package/lib/private/build/server/plugin/node-imports.js +32 -0
  43. package/lib/private/build/server/plugin/requires.d.ts +4 -0
  44. package/lib/private/build/server/plugin/requires.js +30 -0
  45. package/lib/private/build/server/plugin/roots.d.ts +4 -0
  46. package/lib/private/build/server/plugin/roots.js +18 -0
  47. package/lib/private/build/server/plugin/route.d.ts +4 -0
  48. package/lib/private/build/server/plugin/route.js +56 -0
  49. package/lib/private/build/server/plugin/store-wrap.d.ts +4 -0
  50. package/lib/private/build/server/plugin/store-wrap.js +33 -0
  51. package/lib/private/build/server/plugin/store.d.ts +4 -0
  52. package/lib/private/build/server/plugin/store.js +47 -0
  53. package/lib/private/build/server/plugin/stores.d.ts +4 -0
  54. package/lib/private/build/server/plugin/stores.js +25 -0
  55. package/lib/private/build/server/plugin/view.d.ts +4 -0
  56. package/lib/private/build/server/plugin/view.js +64 -0
  57. package/lib/private/build/server/plugin/views.d.ts +4 -0
  58. package/lib/private/build/server/plugin/views.js +36 -0
  59. package/lib/private/build/server/plugin/virtual-pages.d.ts +4 -0
  60. package/lib/private/build/server/plugin/virtual-pages.js +41 -0
  61. package/lib/private/build/server/plugin/virtual-routes.d.ts +4 -0
  62. package/lib/private/build/server/plugin/virtual-routes.js +46 -0
  63. package/lib/private/build/server/plugin/wasm.d.ts +4 -0
  64. package/lib/private/build/server/plugin/wasm.js +36 -0
  65. package/lib/private/client/Data.d.ts +2 -0
  66. package/lib/private/client/app.js +4 -1
  67. package/lib/private/config/index.d.ts +0 -2
  68. package/lib/private/config/schema.d.ts +4 -6
  69. package/lib/private/config/schema.js +9 -19
  70. package/lib/private/database/Store.d.ts +4 -1
  71. package/lib/private/database/Store.js +8 -2
  72. package/lib/private/database/test.js +8 -8
  73. package/lib/private/frontend/Module.d.ts +4 -3
  74. package/lib/private/frontend/Module.js +47 -50
  75. package/lib/private/frontend/Publish.d.ts +1 -1
  76. package/lib/private/i18n/Module.d.ts +1 -1
  77. package/lib/private/i18n/Module.js +2 -2
  78. package/lib/private/location.d.ts +0 -6
  79. package/lib/private/location.js +0 -12
  80. package/lib/private/module/BuildHook.d.ts +1 -1
  81. package/lib/private/module/NextBuild.d.ts +1 -1
  82. package/lib/private/module/NextServe.d.ts +1 -1
  83. package/lib/private/paths.d.ts +5 -0
  84. package/lib/private/paths.js +30 -0
  85. package/lib/private/reducer.d.ts +2 -2
  86. package/lib/private/request/route.d.ts +1 -1
  87. package/lib/private/request/route.js +6 -8
  88. package/lib/private/response/ResponseFunction.d.ts +1 -1
  89. package/lib/private/response/binary.d.ts +1 -1
  90. package/lib/private/response/json.d.ts +1 -1
  91. package/lib/private/response/sse.d.ts +1 -1
  92. package/lib/private/response/text.d.ts +1 -1
  93. package/lib/private/response/view.d.ts +6 -9
  94. package/lib/private/response/view.js +12 -8
  95. package/lib/private/response.d.ts +1 -1
  96. package/lib/private/route/router.d.ts +3 -2
  97. package/lib/private/route/router.js +5 -4
  98. package/lib/private/{ServeApp.d.ts → serve/App.d.ts} +5 -22
  99. package/lib/private/{ServeApp.js → serve/App.js} +106 -35
  100. package/lib/private/{ServeInit.d.ts → serve/Init.d.ts} +16 -12
  101. package/lib/private/serve/Init.js +2 -0
  102. package/lib/private/{hook/serve.d.ts → serve/hook.d.ts} +2 -2
  103. package/lib/private/{hook/serve.js → serve/hook.js} +1 -1
  104. package/lib/private/serve/index.d.ts +5 -0
  105. package/lib/private/serve/index.js +6 -0
  106. package/lib/private/{builtin/DevModule.d.ts → serve/module/Dev.d.ts} +2 -2
  107. package/lib/private/{builtin/DevModule.js → serve/module/Dev.js} +4 -6
  108. package/lib/private/{builtin/HandleModule.d.ts → serve/module/Handle.d.ts} +2 -2
  109. package/lib/private/{builtin/HandleModule.js → serve/module/Handle.js} +2 -2
  110. package/lib/private/session/SessionModule.d.ts +3 -2
  111. package/lib/private/session/SessionModule.js +47 -24
  112. package/lib/private/session/index.d.ts +11 -8
  113. package/lib/private/session/index.js +5 -3
  114. package/lib/private/session/schema.d.ts +2 -4
  115. package/lib/private/session/schema.js +14 -16
  116. package/lib/private/target/Manager.js +5 -1
  117. package/lib/private/wasm/instantiate.js +2 -2
  118. package/lib/public/BuildApp.d.ts +1 -1
  119. package/lib/public/BuildApp.js +1 -1
  120. package/lib/public/Flags.d.ts +2 -0
  121. package/lib/public/Flags.js +2 -0
  122. package/lib/public/ServeApp.d.ts +1 -1
  123. package/lib/public/ServeApp.js +1 -1
  124. package/lib/public/build.d.ts +1 -1
  125. package/lib/public/build.js +1 -1
  126. package/lib/public/serve.d.ts +1 -1
  127. package/lib/public/serve.js +1 -1
  128. package/package.json +6 -7
  129. package/lib/private/BindingContext.d.ts +0 -3
  130. package/lib/private/BindingContext.js +0 -2
  131. package/lib/private/BuildApp.d.ts +0 -31
  132. package/lib/private/BuildApp.js +0 -130
  133. package/lib/private/Loader.d.ts +0 -17
  134. package/lib/private/Loader.js +0 -47
  135. package/lib/private/ServeInit.js +0 -2
  136. package/lib/private/build.d.ts +0 -4
  137. package/lib/private/config/config/app.d.ts +0 -3
  138. package/lib/private/config/config/app.js +0 -3
  139. package/lib/private/config/config/database/index.d.ts +0 -3
  140. package/lib/private/config/config/database/index.js +0 -3
  141. package/lib/private/config/config/session.d.ts +0 -3
  142. package/lib/private/config/config/session.js +0 -3
  143. package/lib/private/frontend/bundle-server.d.ts +0 -13
  144. package/lib/private/frontend/bundle-server.js +0 -48
  145. package/lib/private/hook/build.js +0 -260
  146. package/lib/private/serve.d.ts +0 -5
  147. package/lib/private/serve.js +0 -8
  148. package/lib/private/session/InMemoryManager.d.ts +0 -9
  149. package/lib/private/session/InMemoryManager.js +0 -23
  150. package/lib/private/session/Manager.d.ts +0 -9
  151. package/lib/private/session/Manager.js +0 -4
  152. package/lib/private/target/web.d.ts +0 -4
  153. package/lib/private/target/web.js +0 -58
  154. package/lib/public/Loader.d.ts +0 -2
  155. package/lib/public/Loader.js +0 -2
  156. package/lib/public/session/Manager.d.ts +0 -2
  157. package/lib/public/session/Manager.js +0 -2
@@ -4,12 +4,11 @@ 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";
7
- import type Loader from "#Loader";
8
7
  import RequestBag from "#request/RequestBag";
9
8
  import RequestBody from "#request/RequestBody";
10
9
  import type RequestFacade from "#request/RequestFacade";
11
10
  import type RouteHandler from "#route/Handler";
12
- import type ServeInit from "#ServeInit";
11
+ import type ServeInit from "#serve/Init";
13
12
  import FileRouter from "@rcompat/fs/FileRouter";
14
13
  import type Actions from "@rcompat/http/Actions";
15
14
  import type Dict from "@rcompat/type/Dict";
@@ -26,20 +25,13 @@ export default class ServeApp extends App {
26
25
  #private;
27
26
  constructor(rootfile: string, init: ServeInit);
28
27
  get secure(): boolean;
29
- loader<T extends Loader>(): T;
30
- serve(pathname: string): Promise<Response | undefined>;
31
28
  get assets(): Asset[];
32
- get modules(): import("./Module.js").default[];
29
+ get modules(): import("../Module.js").default[];
33
30
  get url(): string;
34
31
  get router(): FileRouter;
35
32
  get frontends(): {
36
33
  [x: string]: ViewResponse | undefined;
37
34
  };
38
- get files(): {
39
- routes: [string, {
40
- default: any;
41
- }][];
42
- };
43
35
  get stores(): Dict;
44
36
  get i18n(): I18NConfig | undefined;
45
37
  loadView<T = ServerView>(name: string): T;
@@ -47,7 +39,6 @@ export default class ServeApp extends App {
47
39
  "Content-Security-Policy"?: string | undefined;
48
40
  };
49
41
  render(content: Omit<FullViewOptions, keyof ResponseInit>): string;
50
- page(page?: string): string;
51
42
  body_length(body: BodyInit | null): number;
52
43
  respond(body: BodyInit | null, init?: ResponseInit): Response;
53
44
  view(options: FullViewOptions): Response;
@@ -55,6 +46,8 @@ export default class ServeApp extends App {
55
46
  publish({ code, inline, src, type }: PublishOptions): Promise<void>;
56
47
  create_csp(): void;
57
48
  register(extension: string, viewFunction: ViewResponse): void;
49
+ page(name?: string): string;
50
+ serveAsset(pathname: string): Promise<Response | undefined>;
58
51
  start(): Promise<void>;
59
52
  stop(): void;
60
53
  upgrade(request: Request, actions: Actions): null;
@@ -76,16 +69,6 @@ export default class ServeApp extends App {
76
69
  url: URL;
77
70
  };
78
71
  } | undefined>;
79
- get session(): {
80
- cookie: {
81
- httpOnly: boolean;
82
- name: string;
83
- path: string;
84
- sameSite: "Lax" | "None" | "Strict";
85
- };
86
- manager: import("./session/Manager.js").default<unknown>;
87
- schema: import("@rcompat/type/Schema").default<unknown> | undefined;
88
- };
89
72
  }
90
73
  export {};
91
- //# sourceMappingURL=ServeApp.d.ts.map
74
+ //# sourceMappingURL=App.d.ts.map
@@ -1,6 +1,4 @@
1
1
  import App from "#App";
2
- import DevModule from "#builtin/DevModule";
3
- import HandleModule from "#builtin/HandleModule";
4
2
  import fail from "#fail";
5
3
  import hash from "#hash";
6
4
  import I18NModule from "#i18n/Module";
@@ -11,11 +9,14 @@ import parse from "#request/parse";
11
9
  import RequestBag from "#request/RequestBag";
12
10
  import RequestBody from "#request/RequestBody";
13
11
  import router from "#route/router";
12
+ import DevModule from "#serve/module/Dev";
13
+ import HandleModule from "#serve/module/Handle";
14
14
  import SessionModule from "#session/SessionModule";
15
15
  import tags from "#tags";
16
16
  import is from "@rcompat/assert/is";
17
17
  import FileRef from "@rcompat/fs/FileRef";
18
18
  import FileRouter from "@rcompat/fs/FileRouter";
19
+ import resolve from "@rcompat/http/mime/extension/resolve";
19
20
  import TEXT_HTML from "@rcompat/http/mime/text/html";
20
21
  import serve from "@rcompat/http/serve";
21
22
  import Status from "@rcompat/http/Status";
@@ -58,16 +59,25 @@ export default class ServeApp extends App {
58
59
  #views;
59
60
  #csp = {};
60
61
  #assets = [];
62
+ #serve_assets;
63
+ #pages;
61
64
  #stores;
62
65
  #frontends = {};
63
66
  #router;
64
67
  #builtins;
65
68
  #i18n_config;
66
69
  constructor(rootfile, init) {
67
- super(new FileRef(rootfile).directory, init.config, init.mode);
70
+ const dir = new FileRef(rootfile).directory;
71
+ super(dir, init.config, {
72
+ mode: init.mode,
73
+ target: init.target,
74
+ dir: dir.path,
75
+ });
68
76
  this.#init = init;
69
77
  this.#views = Object.fromEntries(init.views ?? []);
70
78
  this.#stores = Object.fromEntries((init.stores?.map(([k, s]) => [k, s.default])) ?? []);
79
+ this.#serve_assets = init.assets;
80
+ this.#pages = init.pages;
71
81
  const http = this.#init.config.http;
72
82
  this.#i18n_config = init.i18n_config;
73
83
  this.set(s_http, {
@@ -85,11 +95,11 @@ export default class ServeApp extends App {
85
95
  guard: { recursive: true },
86
96
  layout: { recursive: true },
87
97
  },
88
- }, init.files.routes.map(s => s[0]));
98
+ }, init.routes.map(s => s[0]));
89
99
  this.#builtins = {
90
100
  dev: init.mode === "development" ? new DevModule(this) : undefined,
91
101
  handle: new HandleModule(this),
92
- session: new SessionModule(this),
102
+ session: init.session_config ? new SessionModule(this.secure, init.session_config) : undefined,
93
103
  i18n: init.i18n_config ? new I18NModule(init.i18n_config) : undefined,
94
104
  };
95
105
  }
@@ -98,12 +108,6 @@ export default class ServeApp extends App {
98
108
  const ssl = this.config("http.ssl");
99
109
  return ssl.key !== undefined && ssl.cert !== undefined;
100
110
  }
101
- loader() {
102
- return this.#init.loader;
103
- }
104
- serve(pathname) {
105
- return this.loader().serve(pathname);
106
- }
107
111
  get assets() {
108
112
  return this.#assets;
109
113
  }
@@ -122,9 +126,6 @@ export default class ServeApp extends App {
122
126
  get frontends() {
123
127
  return { ...this.#frontends };
124
128
  }
125
- get files() {
126
- return this.#init.files;
127
- }
128
129
  get stores() {
129
130
  return this.#stores;
130
131
  }
@@ -132,13 +133,17 @@ export default class ServeApp extends App {
132
133
  return this.#i18n_config;
133
134
  }
134
135
  loadView(name) {
135
- const f = new FileRef(name);
136
- const base = f.path.slice(0, -f.fullExtension.length);
136
+ const f = new FileRef(name).path;
137
+ const frontends = Object.keys(this.frontends);
138
+ const extension = frontends.find(frontend => f.endsWith(frontend));
139
+ const base = extension === undefined ? name : f.slice(0, -extension.length);
137
140
  const view = this.#views[base];
138
- if (view === undefined) {
139
- throw fail("missing view component {0}", `${location.views}/${name}`);
141
+ if (view === undefined)
142
+ throw fail("no view {0}", name);
143
+ if (view.default === undefined) {
144
+ throw fail("view {0} must export a default component", name);
140
145
  }
141
- return (view.default ?? view);
146
+ return view.default;
142
147
  }
143
148
  ;
144
149
  headers(csp = {}) {
@@ -164,9 +169,6 @@ export default class ServeApp extends App {
164
169
  .replace("%body%", body)
165
170
  .replace("%head%", render_head(this.#assets, head));
166
171
  }
167
- page(page) {
168
- return this.loader().page(page);
169
- }
170
172
  body_length(body) {
171
173
  return typeof body === "string" ? utf8ByteLength(body) : 0;
172
174
  }
@@ -224,15 +226,88 @@ export default class ServeApp extends App {
224
226
  this.#frontends[extension] = viewFunction;
225
227
  }
226
228
  ;
229
+ page(name) {
230
+ const page_name = name ?? location.app_html;
231
+ return this.#pages[page_name];
232
+ }
233
+ async #try_serve(file) {
234
+ if (await file.exists() && await file.isFile()) {
235
+ return new Response(file.stream(), {
236
+ headers: {
237
+ "Content-Type": resolve(file.name),
238
+ "Content-Length": String(await file.byteLength()),
239
+ },
240
+ status: Status.OK,
241
+ });
242
+ }
243
+ }
244
+ async serveAsset(pathname) {
245
+ const static_root = this.config("http.static.root");
246
+ if (!pathname.startsWith(static_root))
247
+ return undefined;
248
+ if (this.mode === "development") {
249
+ const client_asset = this.root.join(location.client, pathname);
250
+ const client_response = await this.#try_serve(client_asset);
251
+ if (client_response !== undefined)
252
+ return client_response;
253
+ const static_asset = this.root.join("..", location.static, pathname);
254
+ const static_response = await this.#try_serve(static_asset);
255
+ if (static_response !== undefined)
256
+ return static_response;
257
+ return undefined;
258
+ }
259
+ const asset = this.#serve_assets.client[pathname] ??
260
+ this.#serve_assets.static[pathname];
261
+ if (asset) {
262
+ const binary = atob(asset.data);
263
+ const bytes = new Uint8Array(binary.length);
264
+ for (let i = 0; i < binary.length; i++) {
265
+ bytes[i] = binary.charCodeAt(i);
266
+ }
267
+ return new Response(bytes, {
268
+ headers: {
269
+ "Content-Type": asset.mime,
270
+ "Content-Length": String(bytes.length),
271
+ },
272
+ status: Status.OK,
273
+ });
274
+ }
275
+ return undefined;
276
+ }
227
277
  async start() {
228
- this.#assets = await Promise.all(this.#init.assets.map(async (asset) => {
229
- const code = asset.code;
230
- return {
231
- ...asset,
232
- code,
233
- integrity: await hash(code),
234
- };
235
- }));
278
+ if (this.mode === "production") {
279
+ this.#assets = await Promise.all(Object.entries(this.#serve_assets.client)
280
+ .filter(([src]) => src.endsWith(".css") || src.endsWith(".js"))
281
+ .map(async ([src, asset]) => {
282
+ const type = src.endsWith(".css") ? "style" : "js";
283
+ const code = atob(asset.data);
284
+ return {
285
+ code,
286
+ inline: false,
287
+ integrity: await hash(code),
288
+ src,
289
+ type,
290
+ };
291
+ }));
292
+ }
293
+ else {
294
+ const client_dir = this.root.join(location.client);
295
+ const files = await client_dir.exists()
296
+ ? await client_dir.collect(f => f.extension === ".js"
297
+ || f.extension === ".css")
298
+ : [];
299
+ this.#assets = await Promise.all(files.map(async (file) => {
300
+ const type = file.extension === ".css" ? "style" : "js";
301
+ const code = await file.text();
302
+ return {
303
+ code,
304
+ inline: false,
305
+ integrity: await hash(code),
306
+ src: `/${file.name}`,
307
+ type,
308
+ };
309
+ }));
310
+ }
236
311
  const modules = [
237
312
  this.#builtins.dev,
238
313
  ...this.modules,
@@ -306,9 +381,5 @@ export default class ServeApp extends App {
306
381
  },
307
382
  };
308
383
  }
309
- get session() {
310
- return this.#init.session_config;
311
- }
312
- ;
313
384
  }
314
- //# sourceMappingURL=ServeApp.js.map
385
+ //# sourceMappingURL=App.js.map
@@ -1,29 +1,33 @@
1
- import type Asset from "#asset/Asset";
2
1
  import type Config from "#config/Config";
3
2
  import type I18NConfig from "#i18n/Config";
4
- import type Loader from "#Loader";
5
3
  import type Mode from "#Mode";
6
4
  import type SessionConfig from "#session/Config";
7
5
  import type Dict from "@rcompat/type/Dict";
8
6
  type Import = {
9
7
  default: unknown;
10
8
  } & Dict;
11
- type BuildFiles = {
12
- routes: [string, {
13
- default: any;
14
- }][];
15
- };
16
9
  type ServeInit = {
17
- assets: Asset[];
10
+ assets: {
11
+ client: Dict<{
12
+ mime: string;
13
+ data: string;
14
+ }>;
15
+ static: Dict<{
16
+ mime: string;
17
+ data: string;
18
+ }>;
19
+ };
18
20
  views?: [string, Import][];
19
21
  stores?: [string, Import][];
20
22
  config: Config;
21
- files: BuildFiles;
22
- loader: Loader;
23
+ routes: [string, {
24
+ default: any;
25
+ }][];
23
26
  mode: Mode;
24
27
  target: string;
25
- session_config: SessionConfig;
28
+ pages: Dict<string>;
29
+ session_config?: SessionConfig;
26
30
  i18n_config?: I18NConfig;
27
31
  };
28
32
  export type { ServeInit as default };
29
- //# sourceMappingURL=ServeInit.d.ts.map
33
+ //# sourceMappingURL=Init.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=Init.js.map
@@ -1,4 +1,4 @@
1
- import type ServeApp from "#ServeApp";
1
+ import type ServeApp from "#serve/App";
2
2
  declare const _default: (app: ServeApp) => Promise<ServeApp>;
3
3
  export default _default;
4
- //# sourceMappingURL=serve.d.ts.map
4
+ //# sourceMappingURL=hook.d.ts.map
@@ -10,4 +10,4 @@ async function post(app) {
10
10
  return app;
11
11
  }
12
12
  export default async (app) => post(await reducer(app.modules, pre(app), "serve"));
13
- //# sourceMappingURL=serve.js.map
13
+ //# sourceMappingURL=hook.js.map
@@ -0,0 +1,5 @@
1
+ import ServeApp from "#serve/App";
2
+ import type ServeInit from "#serve/Init";
3
+ declare const _default: (root: string, options: ServeInit) => Promise<ServeApp>;
4
+ export default _default;
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,6 @@
1
+ import ServeApp from "#serve/App";
2
+ import serve from "#serve/hook";
3
+ export default async (root, options) => {
4
+ return serve(await new ServeApp(root, options).init());
5
+ };
6
+ //# sourceMappingURL=index.js.map
@@ -1,11 +1,11 @@
1
1
  import Module from "#Module";
2
2
  import type NextHandle from "#module/NextHandle";
3
3
  import type RequestFacade from "#request/RequestFacade";
4
- import type ServeApp from "#ServeApp";
4
+ import type ServeApp from "#serve/App";
5
5
  export default class DevModule extends Module {
6
6
  #private;
7
7
  name: string;
8
8
  constructor(app: ServeApp);
9
9
  handle(request: RequestFacade, next: NextHandle): import("@rcompat/type/MaybePromise").default<Response>;
10
10
  }
11
- //# sourceMappingURL=DevModule.d.ts.map
11
+ //# sourceMappingURL=Dev.d.ts.map
@@ -1,6 +1,5 @@
1
+ import reload from "#build/client/reload";
1
2
  import Module from "#Module";
2
- import reload_defaults from "@rcompat/build/reload/defaults";
3
- import reload_path from "@rcompat/build/reload/path";
4
3
  function pass(address, request) {
5
4
  return fetch(address, {
6
5
  body: request.body,
@@ -16,9 +15,8 @@ export default class DevModule extends Module {
16
15
  constructor(app) {
17
16
  super();
18
17
  const assets = app.assets.map(asset => asset.src);
19
- const http = app.config("http");
20
- this.#paths = ([reload_path]).concat(assets);
21
- this.#reload_url = `http://${http.host}:${reload_defaults.port}`;
18
+ this.#paths = ([reload.path]).concat(assets);
19
+ this.#reload_url = `http://${reload.host}:${reload.port}`;
22
20
  }
23
21
  handle(request, next) {
24
22
  const { pathname } = new URL(request.url);
@@ -27,4 +25,4 @@ export default class DevModule extends Module {
27
25
  : next(request);
28
26
  }
29
27
  }
30
- //# sourceMappingURL=DevModule.js.map
28
+ //# sourceMappingURL=Dev.js.map
@@ -1,10 +1,10 @@
1
1
  import Module from "#Module";
2
2
  import type RequestFacade from "#request/RequestFacade";
3
- import type ServeApp from "#ServeApp";
3
+ import type ServeApp from "#serve/App";
4
4
  export default class HandleModule extends Module {
5
5
  #private;
6
6
  name: string;
7
7
  constructor(app: ServeApp);
8
8
  handle(request: RequestFacade): Promise<Response>;
9
9
  }
10
- //# sourceMappingURL=HandleModule.d.ts.map
10
+ //# sourceMappingURL=Handle.d.ts.map
@@ -8,8 +8,8 @@ export default class HandleModule extends Module {
8
8
  this.#app = app;
9
9
  }
10
10
  async handle(request) {
11
- return await this.#app.serve(request.url.pathname)
11
+ return await this.#app.serveAsset(request.url.pathname)
12
12
  ?? route(this.#app, request);
13
13
  }
14
14
  }
15
- //# sourceMappingURL=HandleModule.js.map
15
+ //# sourceMappingURL=Handle.js.map
@@ -2,11 +2,12 @@ import Module from "#Module";
2
2
  import type NextHandle from "#module/NextHandle";
3
3
  import type NextServe from "#module/NextServe";
4
4
  import type RequestFacade from "#request/RequestFacade";
5
- import type ServeApp from "#ServeApp";
5
+ import type ServeApp from "#serve/App";
6
+ import type Config from "#session/Config";
6
7
  export default class SessionModule extends Module {
7
8
  #private;
8
9
  name: string;
9
- constructor(app: ServeApp);
10
+ constructor(secure: boolean, config: Config);
10
11
  serve(app: ServeApp, next: NextServe): Promise<ServeApp>;
11
12
  handle(request: RequestFacade, next: NextHandle): Promise<Response>;
12
13
  }
@@ -1,7 +1,9 @@
1
+ import fail from "#fail";
1
2
  import Module from "#Module";
2
3
  import kSerialize from "#session/k-serialize";
3
4
  import SessionHandle from "#session/SessionHandle";
4
5
  import storage from "#session/storage";
6
+ import p from "pema";
5
7
  const cookie = (name, value, options) => {
6
8
  const parts = [`${name}=${value}`];
7
9
  parts.push(`Path=${options.path}`);
@@ -16,26 +18,47 @@ const cookie = (name, value, options) => {
16
18
  };
17
19
  export default class SessionModule extends Module {
18
20
  name = "builtin/session";
19
- #app;
20
- #manager;
21
+ #store;
21
22
  #secure;
22
- constructor(app) {
23
+ #config;
24
+ constructor(secure, config) {
23
25
  super();
24
- this.#app = app;
25
- this.#secure = app.secure;
26
- this.#manager = app.session.manager;
26
+ this.#secure = secure;
27
+ this.#config = config;
28
+ this.#store = config.store;
29
+ const props = this.#store.type.properties;
30
+ if (!("session_id" in props)) {
31
+ throw fail("Session store must have a session_id field");
32
+ }
33
+ try {
34
+ props.session_id.parse(crypto.randomUUID());
35
+ }
36
+ catch {
37
+ throw fail("Session store session_id must be a string type");
38
+ }
27
39
  }
28
40
  async serve(app, next) {
29
- // initialize the session manager
30
- await this.#manager.init?.();
41
+ await this.#store.collection.create();
31
42
  return next(app);
32
43
  }
33
44
  async handle(request, next) {
34
- const { name, ...config } = this.#app.session.cookie;
45
+ const { name, ...config } = this.#config.cookie;
35
46
  const sid = request.cookies.try(name);
36
- const data = sid !== undefined ? await this.#manager.load(sid) : undefined;
37
- const id = data !== undefined ? sid : undefined;
38
- const session = new SessionHandle(id, data, this.#app.session.schema);
47
+ // Look up session by session_id
48
+ const existing = sid !== undefined
49
+ ? await this.#store.find({ session_id: sid }, { limit: 1 })
50
+ : [];
51
+ const exists = existing.length > 0;
52
+ let data = undefined;
53
+ let dbId = undefined;
54
+ if (exists) {
55
+ const record = existing[0];
56
+ const { id: _id, session_id: _sid, ...rest } = record;
57
+ data = rest;
58
+ dbId = _id;
59
+ }
60
+ const session_type = p.omit(this.#store.type, "id", "session_id");
61
+ const session = new SessionHandle(sid, data, session_type);
39
62
  const response = await new Promise((resolve, reject) => {
40
63
  storage().run(session, async () => {
41
64
  try {
@@ -56,10 +79,10 @@ export default class SessionModule extends Module {
56
79
  sameSite: config.sameSite,
57
80
  secure: this.#secure,
58
81
  };
59
- // no session existed -> either create or noop (noop already returned)
60
- if (id === undefined) {
82
+ // no session existed -> either create or noop
83
+ if (!exists) {
61
84
  if (!snap.exists) {
62
- // stale cookie -> clear; no cookie, noop
85
+ // stale cookie -> clear
63
86
  if (sid !== undefined) {
64
87
  response.headers.append("set-cookie", cookie(name, "", {
65
88
  ...options, maxAge: 0,
@@ -67,32 +90,32 @@ export default class SessionModule extends Module {
67
90
  }
68
91
  return response;
69
92
  }
70
- // safe due to fast-path
71
- await this.#manager.create(snap.id, snap.data);
93
+ // create new session
94
+ await this.#store.insert({ session_id: snap.id, ...snap.data });
72
95
  response.headers.append("set-cookie", cookie(name, snap.id, options));
73
96
  return response;
74
97
  }
75
- // from here: session existed (id is defined)
98
+ // from here: session existed (dbId is defined)
76
99
  // fast-path: session exists, same id and not dirty -> noop
77
- if (snap.exists && snap.id === id && !snap.dirty)
100
+ if (snap.exists && snap.id === sid && !snap.dirty)
78
101
  return response;
79
102
  // current absent -> destroy + clear cookie
80
103
  if (!snap.exists) {
81
- await this.#manager.destroy(id);
104
+ await this.#store.delete(dbId);
82
105
  response.headers.append("set-cookie", cookie(name, "", {
83
106
  ...options, maxAge: 0,
84
107
  }));
85
108
  return response;
86
109
  }
87
110
  // session recreated in route -> destroy old, create new, set cookie
88
- if (snap.id !== id) {
89
- await this.#manager.destroy(id);
90
- await this.#manager.create(snap.id, snap.data);
111
+ if (snap.id !== sid) {
112
+ await this.#store.delete(dbId);
113
+ await this.#store.insert({ session_id: snap.id, ...snap.data });
91
114
  response.headers.append("set-cookie", cookie(name, snap.id, options));
92
115
  return response;
93
116
  }
94
117
  // dirty -> replace session contents
95
- await this.#manager.save(id, snap.data);
118
+ await this.#store.update(dbId, snap.data);
96
119
  return response;
97
120
  }
98
121
  }
@@ -1,13 +1,16 @@
1
+ import type DatabaseStore from "#database/Store";
1
2
  import configSchema from "#session/schema";
2
3
  import type SessionFacade from "#session/SessionFacade";
3
- import type Schema from "@rcompat/type/Schema";
4
+ import type InferStore from "pema/InferStore";
5
+ import type StoreSchema from "pema/StoreSchema";
4
6
  type ConfigInput = typeof configSchema.input;
5
- type InferSchema<S> = S extends {
6
- parse(input: unknown): infer T;
7
- } ? T : unknown;
8
- export default function session<S extends Schema<any>>(config: {
9
- schema: S;
10
- } & Partial<ConfigInput>): SessionFacade<InferSchema<S>>;
11
- export default function session(config?: Omit<Partial<ConfigInput>, "schema">): SessionFacade<unknown>;
7
+ type X<T> = {
8
+ [K in keyof T]: T[K];
9
+ } & {};
10
+ type Infer<S extends StoreSchema> = X<Omit<InferStore<S>, "id" | "session_id">>;
11
+ export default function session<S extends StoreSchema>(config: {
12
+ store: DatabaseStore<S>;
13
+ } & Partial<ConfigInput>): SessionFacade<Infer<S>>;
14
+ export default function session(Infer?: Omit<Partial<ConfigInput>, "store">): SessionFacade<unknown>;
12
15
  export {};
13
16
  //# sourceMappingURL=index.d.ts.map
@@ -3,8 +3,8 @@ import local_storage from "#session/storage";
3
3
  import s_config from "#symbol/config";
4
4
  export default function session(config) {
5
5
  const parsed = configSchema.parse(config ?? {});
6
- const schema = config?.schema;
7
- // bind the ALS store to this T (unknown at runtime; fine)
6
+ const store = parsed.store;
7
+ // bind the ALS store to this T
8
8
  const storage = local_storage();
9
9
  const current = () => {
10
10
  const s = storage.getStore();
@@ -34,7 +34,9 @@ export default function session(config) {
34
34
  destroy() {
35
35
  current().destroy();
36
36
  },
37
- get [s_config]() { return { ...parsed, schema }; },
37
+ get [s_config]() {
38
+ return { ...parsed, store };
39
+ },
38
40
  };
39
41
  return facade;
40
42
  }
@@ -1,5 +1,4 @@
1
- import SessionManager from "#session/Manager";
2
- import type Schema from "@rcompat/type/Schema";
1
+ import Store from "#database/Store";
3
2
  declare const _default: import("pema").ObjectType<{
4
3
  cookie: import("pema").ObjectType<{
5
4
  httpOnly: import("pema").DefaultType<import("pema/boolean").BooleanType, true>;
@@ -7,8 +6,7 @@ declare const _default: import("pema").ObjectType<{
7
6
  path: import("pema").DefaultType<import("pema/string").StringType, "/">;
8
7
  sameSite: import("pema").DefaultType<import("pema/union").UnionType<[import("pema").LiteralType<"Strict">, import("pema").LiteralType<"Lax">, import("pema").LiteralType<"None">]>, "Lax" | "None" | "Strict">;
9
8
  }>;
10
- manager: import("pema").DefaultType<import("pema/constructor").ConstructorType<typeof SessionManager>, SessionManager<unknown>>;
11
- schema: import("pema").OptionalType<import("pema").PureType<Schema<unknown>, "PureType">>;
9
+ store: import("pema").DefaultType<import("pema").ConstructorType<typeof Store>, Store<import("pema/StoreSchema").default>>;
12
10
  }>;
13
11
  export default _default;
14
12
  //# sourceMappingURL=schema.d.ts.map