@primate/core 0.7.4 → 0.8.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 (120) hide show
  1. package/lib/private/App.d.ts +128 -65
  2. package/lib/private/Bag.d.ts +11 -0
  3. package/lib/private/Bag.js +31 -0
  4. package/lib/private/Flags.d.ts +5 -5
  5. package/lib/private/Flags.js +2 -1
  6. package/lib/private/app/Facade.client.d.ts +20 -0
  7. package/lib/private/app/Facade.client.js +30 -0
  8. package/lib/private/app/{Facade.d.ts → Facade.server.d.ts} +141 -72
  9. package/lib/private/app/{Facade.js → Facade.server.js} +12 -4
  10. package/lib/private/build/App.d.ts +0 -2
  11. package/lib/private/build/App.js +0 -7
  12. package/lib/private/build/client/index.js +29 -27
  13. package/lib/private/build/client/plugin/frontend.js +1 -1
  14. package/lib/private/build/hook.js +0 -3
  15. package/lib/private/build/server/index.js +5 -18
  16. package/lib/private/build/server/plugin/native-addons.d.ts +1 -1
  17. package/lib/private/build/server/plugin/native-addons.js +1 -1
  18. package/lib/private/client/create-form.d.ts +13 -9
  19. package/lib/private/client/create-form.js +21 -4
  20. package/lib/private/client/transport.js +0 -2
  21. package/lib/private/config/index.d.ts +6 -2
  22. package/lib/private/config/schema.d.ts +28 -21
  23. package/lib/private/config/schema.js +5 -3
  24. package/lib/private/cookie.d.ts +5 -5
  25. package/lib/private/db/errors.d.ts +82 -82
  26. package/lib/private/db/migrate/store.d.ts +2 -2
  27. package/lib/private/db/primary.d.ts +1 -1
  28. package/lib/private/db/sql.d.ts +1 -1
  29. package/lib/private/errors.d.ts +80 -68
  30. package/lib/private/errors.js +22 -0
  31. package/lib/private/frontend.d.ts +7 -7
  32. package/lib/private/frontend.js +7 -10
  33. package/lib/private/i18n/API.d.ts +14 -18
  34. package/lib/private/i18n/config.client.d.ts +7 -0
  35. package/lib/private/i18n/config.client.js +130 -0
  36. package/lib/private/i18n/config.server.d.ts +7 -0
  37. package/lib/private/i18n/{index/server.js → config.server.js} +31 -23
  38. package/lib/private/i18n/constant/COOKIE_NAME.d.ts +1 -1
  39. package/lib/private/i18n/constant/DEFAULT_LOCALE.d.ts +1 -1
  40. package/lib/private/i18n/constant/DEFAULT_PERSIST_MODE.d.ts +1 -1
  41. package/lib/private/i18n/constant/PERSIST_HEADER.d.ts +1 -1
  42. package/lib/private/i18n/constant/PERSIST_METHOD.d.ts +1 -1
  43. package/lib/private/i18n/constant/PERSIST_STORAGE_KEY.d.ts +1 -1
  44. package/lib/private/i18n/index.d.ts +42 -0
  45. package/lib/private/i18n/index.js +6 -0
  46. package/lib/private/i18n/missing.d.ts +5 -0
  47. package/lib/private/i18n/missing.js +38 -0
  48. package/lib/private/i18n/module.js +36 -52
  49. package/lib/private/i18n/schema.d.ts +4 -4
  50. package/lib/private/loader.d.ts +5 -0
  51. package/lib/private/loader.js +28 -0
  52. package/lib/private/logger.d.ts +1 -1
  53. package/lib/private/request/RequestBag.d.ts +12 -13
  54. package/lib/private/request/RequestBag.js +5 -4
  55. package/lib/private/request/RequestView.d.ts +5 -5
  56. package/lib/private/request/RequestView.js +0 -1
  57. package/lib/private/response/view.d.ts +1 -0
  58. package/lib/private/response/view.js +0 -7
  59. package/lib/private/route/Handler.d.ts +1 -1
  60. package/lib/private/route/NarrowedRequest.d.ts +6 -1
  61. package/lib/private/route/Options.d.ts +2 -1
  62. package/lib/private/route/hook.d.ts +1 -2
  63. package/lib/private/route/router.d.ts +9 -9
  64. package/lib/private/route/router.js +9 -0
  65. package/lib/private/route.client.d.ts +21 -12
  66. package/lib/private/route.client.js +9 -4
  67. package/lib/private/route.d.ts +3 -0
  68. package/lib/private/route.js +2 -0
  69. package/lib/private/serve/App.d.ts +2 -13
  70. package/lib/private/serve/App.js +63 -46
  71. package/lib/private/serve/Init.d.ts +0 -3
  72. package/lib/private/server/TAG.d.ts +1 -1
  73. package/lib/private/session/config.client.d.ts +4 -0
  74. package/lib/private/session/config.client.js +24 -0
  75. package/lib/private/session/config.server.d.ts +15 -0
  76. package/lib/private/session/config.server.js +44 -0
  77. package/lib/private/session/index.d.ts +2 -14
  78. package/lib/private/session/index.js +2 -43
  79. package/lib/private/session/schema.d.ts +5 -5
  80. package/lib/private/store/PrimaryKey.d.ts +1 -1
  81. package/lib/private/store.client.d.ts +13 -0
  82. package/lib/private/store.client.js +9 -0
  83. package/lib/private/store.d.ts +2 -0
  84. package/lib/private/target/Manager.d.ts +2 -0
  85. package/lib/private/target/Manager.js +29 -5
  86. package/lib/private/target/Target.d.ts +2 -0
  87. package/lib/public/i18n.d.ts +3 -0
  88. package/lib/public/{i18n/config.js → i18n.js} +1 -1
  89. package/lib/public/loader.d.ts +2 -0
  90. package/lib/public/loader.js +2 -0
  91. package/lib/public/response.d.ts +1 -1
  92. package/lib/public/{session/config.d.ts → session.d.ts} +1 -1
  93. package/lib/public/{session/config.js → session.js} +1 -1
  94. package/package.json +27 -13
  95. package/lib/private/app/Facade.browser.d.ts +0 -11
  96. package/lib/private/app/Facade.browser.js +0 -19
  97. package/lib/private/build/server/plugin/store.d.ts +0 -4
  98. package/lib/private/build/server/plugin/store.js +0 -25
  99. package/lib/private/build/server/plugin/stores.d.ts +0 -4
  100. package/lib/private/build/server/plugin/stores.js +0 -28
  101. package/lib/private/i18n/index/client.d.ts +0 -9
  102. package/lib/private/i18n/index/client.js +0 -152
  103. package/lib/private/i18n/index/server.d.ts +0 -9
  104. package/lib/private/i18n/symbol/internal.d.ts +0 -3
  105. package/lib/private/i18n/symbol/internal.js +0 -3
  106. package/lib/public/i18n/API.d.ts +0 -2
  107. package/lib/public/i18n/API.js +0 -2
  108. package/lib/public/i18n/Catalogs.d.ts +0 -2
  109. package/lib/public/i18n/Catalogs.js +0 -2
  110. package/lib/public/i18n/ContextData.d.ts +0 -2
  111. package/lib/public/i18n/ContextData.js +0 -2
  112. package/lib/public/i18n/config.d.ts +0 -2
  113. package/lib/public/i18n/locale.d.ts +0 -2
  114. package/lib/public/i18n/locale.js +0 -2
  115. package/lib/public/i18n/sInternal.d.ts +0 -2
  116. package/lib/public/i18n/sInternal.js +0 -2
  117. package/lib/public/route/hook.d.ts +0 -2
  118. package/lib/public/route/hook.js +0 -2
  119. /package/lib/private/i18n/{index/types.d.ts → types.d.ts} +0 -0
  120. /package/lib/private/i18n/{index/types.js → types.js} +0 -0
@@ -14,6 +14,15 @@ class Router {
14
14
  assert.maybe.dict(options);
15
15
  if (is_hook_file(path))
16
16
  throw E.hook_route_functions_not_allowed(path);
17
+ if (options?.path !== undefined) {
18
+ const declared = Object.keys(options.path.properties);
19
+ const expected = [...path.matchAll(/\[([^\]]+)\]/g)].map(m => m[1]);
20
+ const missing = expected.filter(k => !declared.includes(k));
21
+ const extra = declared.filter(k => !expected.includes(k));
22
+ if (missing.length > 0 || extra.length > 0) {
23
+ throw E.build_path_schema_mismatch(path, method, expected, declared);
24
+ }
25
+ }
17
26
  if (!(path in this.#routes))
18
27
  this.#routes[path] = {};
19
28
  this.#routes[path][method] = { handler, options: options ?? {} };
@@ -1,3 +1,4 @@
1
+ import type ResponseLike from "#response/ResponseLike";
1
2
  import type ContentTypeMap from "#route/ContentTypeMap";
2
3
  import type RouteHandler from "#route/Handler";
3
4
  import type RouteOptions from "#route/Options";
@@ -9,35 +10,43 @@ type Body<O extends RouteOptions> = O extends {
9
10
  } ? Unpack<S["infer"]> : O extends {
10
11
  contentType: infer CT extends keyof ContentTypeMap;
11
12
  } ? ContentTypeMap[CT] : never;
13
+ type Path<O extends RouteOptions> = O extends {
14
+ path: infer S extends Parsed<unknown>;
15
+ } ? Unpack<S["infer"]> : never;
12
16
  type MethodMeta = {
13
17
  contentType?: string;
14
18
  };
15
- type ClientMethod<O extends RouteOptions> = MethodMeta & (Body<O> extends never ? () => Promise<Response> : (args: {
19
+ type ClientMethod<O extends RouteOptions, R = unknown> = MethodMeta & {
20
+ _result?: R;
21
+ } & (Body<O> extends never ? Path<O> extends never ? () => Promise<Response> : (args: {
22
+ path: Path<O>;
23
+ }) => Promise<Response> : Path<O> extends never ? (args: {
16
24
  body: Body<O>;
25
+ }) => Promise<Response> : (args: {
26
+ body: Body<O>;
27
+ path: Path<O>;
17
28
  }) => Promise<Response>);
18
29
  type ClientRoute<R> = {
19
30
  [K in keyof R]: R[K] extends {
20
31
  options: infer O extends RouteOptions;
21
- } ? ClientMethod<O> : () => Promise<Response>;
32
+ result?: infer Result;
33
+ } ? ClientMethod<O, Result> : () => Promise<Response>;
22
34
  };
23
- type WithResult<O extends RouteOptions> = {
35
+ type WithResult<O extends RouteOptions, R = unknown> = {
24
36
  handler: RouteHandler<O>;
25
37
  options: O;
38
+ result?: R;
26
39
  };
27
40
  type RouteHandlers = {
28
41
  [key: string]: RouteHandler | WithResult<RouteOptions>;
29
42
  };
30
- declare function route<R extends RouteHandlers>(handlers: R): {
31
- _handlers: {
32
- [k: string]: {
33
- contentType: ("application/x-7z-compressed" | "application/octet-stream" | "application/x-bzip2" | "application/gzip" | "application/json" | "application/ld+json" | "application/pdf" | "application/x-rar-compressed" | "application/rss+xml" | "application/x-tar" | "application/wasm" | "application/manifest+json" | "application/xml" | "application/yaml" | "application/zip" | "audio/mpeg" | "audio/ogg" | "audio/wav" | "audio/webm" | "font/otf" | "font/ttf" | "font/woff" | "font/woff2" | "image/apng" | "image/avif" | "image/bmp" | "image/gif" | "image/x-icon" | "image/jpeg" | "image/png" | "image/svg+xml" | "image/tiff" | "image/webp" | "text/css" | "text/csv" | "text/html" | "text/javascript" | "text/markdown" | "text/rtf" | "text/plain" | "text/tab-separated-values" | "text/vtt" | "video/quicktime" | "video/mp4" | "video/ogg" | "video/mp2t" | "video/webm" | "application/x-www-form-urlencoded" | "multipart/form-data" | "text/event-stream") | undefined;
34
- };
35
- };
36
- connect(path: string): ClientRoute<R>;
37
- };
43
+ declare function route<R extends RouteHandlers>(handlers: R): ClientRoute<R>;
38
44
  declare namespace route {
39
- var _a: <O extends RouteOptions>(options: O, handler: RouteHandler<O>) => WithResult<O>;
45
+ var _a: <O extends RouteOptions, R extends ResponseLike>(options: O, handler: RouteHandler<O, R>) => WithResult<O, R>;
40
46
  export { _a as with };
41
47
  }
48
+ declare namespace route {
49
+ var hook: typeof import("#route/hook").default;
50
+ }
42
51
  export default route;
43
52
  //# sourceMappingURL=route.client.d.ts.map
@@ -1,3 +1,4 @@
1
+ import hook from "#route/hook";
1
2
  function is_with(value) {
2
3
  return typeof value === "object" &&
3
4
  value !== null &&
@@ -7,9 +8,8 @@ function is_with(value) {
7
8
  function serialize_body(contentType, body) {
8
9
  if (body === undefined)
9
10
  return undefined;
10
- if (contentType === "application/json") {
11
+ if (contentType === "application/json")
11
12
  return JSON.stringify(body);
12
- }
13
13
  if (contentType === "application/x-www-form-urlencoded") {
14
14
  return body instanceof URLSearchParams
15
15
  ? body
@@ -25,7 +25,7 @@ function headers(contentType) {
25
25
  return { "Content-Type": contentType };
26
26
  }
27
27
  function route(handlers) {
28
- return {
28
+ const r = {
29
29
  _handlers: Object.fromEntries(Object.entries(handlers).map(([method, value]) => {
30
30
  const options = is_with(value) ? value.options : {};
31
31
  return [method, { contentType: options.contentType }];
@@ -33,7 +33,10 @@ function route(handlers) {
33
33
  connect(path) {
34
34
  return Object.fromEntries(Object.entries(this._handlers).map(([method, { contentType }]) => {
35
35
  const fn = async (args = {}) => {
36
- return fetch(path, {
36
+ const resolved = args.path !== undefined
37
+ ? path.replace(/\[([^\]]+)\]/g, (_, key) => encodeURIComponent(args.path[key] ?? `[${key}]`))
38
+ : path;
39
+ return fetch(resolved, {
37
40
  method: method.toUpperCase(),
38
41
  headers: headers(contentType),
39
42
  body: serialize_body(contentType, args.body),
@@ -43,9 +46,11 @@ function route(handlers) {
43
46
  }));
44
47
  },
45
48
  };
49
+ return r;
46
50
  }
47
51
  route.with = function (options, handler) {
48
52
  return { handler, options };
49
53
  };
54
+ route.hook = hook;
50
55
  export default route;
51
56
  //# sourceMappingURL=route.client.js.map
@@ -21,5 +21,8 @@ declare namespace route {
21
21
  var _a: <O extends RouteOptions>(options: O, handler: RouteHandler<O>) => WithResult<O>;
22
22
  export { _a as with };
23
23
  }
24
+ declare namespace route {
25
+ var hook: typeof import("#route/hook").default;
26
+ }
24
27
  export default route;
25
28
  //# sourceMappingURL=route.d.ts.map
@@ -1,4 +1,5 @@
1
1
  import E from "#errors";
2
+ import hook from "#route/hook";
2
3
  import is from "@rcompat/is";
3
4
  const BRAND = Symbol("route.with");
4
5
  function is_with(value) {
@@ -18,5 +19,6 @@ route.with = function (options, handler) {
18
19
  }
19
20
  return { [BRAND]: true, handler, options };
20
21
  };
22
+ route.hook = hook;
21
23
  export default route;
22
24
  //# sourceMappingURL=route.js.map
@@ -1,24 +1,16 @@
1
1
  import App from "#App";
2
2
  import type Asset from "#asset/Asset";
3
- import type ServerView from "#client/ServerView";
3
+ import Bag from "#Bag";
4
4
  import type ViewOptions from "#client/ViewOptions";
5
5
  import type ViewResponse from "#client/ViewResponse";
6
- import type I18NConfig from "#i18n/Config";
7
6
  import type RequestFacade from "#request/RequestFacade";
8
7
  import type RouteHandler from "#route/Handler";
9
8
  import type ServeInit from "#serve/Init";
10
9
  import FileRouter from "@rcompat/fs/FileRouter";
11
10
  import type { Actions } from "@rcompat/http";
12
- import type { Dict } from "@rcompat/type";
13
11
  interface FullViewOptions extends ViewOptions {
14
12
  body: string;
15
13
  }
16
- interface PublishOptions {
17
- code: string;
18
- inline: boolean;
19
- src?: string;
20
- type: string;
21
- }
22
14
  export default class ServeApp extends App {
23
15
  #private;
24
16
  constructor(rootfile: string, init: ServeInit);
@@ -27,9 +19,7 @@ export default class ServeApp extends App {
27
19
  get frontends(): {
28
20
  [k: string]: ViewResponse;
29
21
  };
30
- get stores(): Dict;
31
- get i18n(): I18NConfig | undefined;
32
- loadView<T = ServerView>(name: string): T;
22
+ get views(): Bag;
33
23
  headers(csp?: {}): {
34
24
  "Content-Security-Policy"?: string | undefined;
35
25
  };
@@ -38,7 +28,6 @@ export default class ServeApp extends App {
38
28
  respond(body: BodyInit | null, init?: ResponseInit): Response;
39
29
  view(options: FullViewOptions): Response;
40
30
  media(content_type: string, response?: ResponseInit): ResponseInit;
41
- publish({ code, inline, src, type }: PublishOptions): Promise<void>;
42
31
  create_csp(): void;
43
32
  frontend(extension: string, view_response: ViewResponse): void;
44
33
  page(name?: string): string;
@@ -1,5 +1,6 @@
1
1
  import App from "#App";
2
2
  import { s_config } from "#app/Facade";
3
+ import Bag from "#Bag";
3
4
  import E from "#errors";
4
5
  import hash from "#hash";
5
6
  import i18n_module from "#i18n/module";
@@ -48,6 +49,36 @@ const render_head = (assets, head) => {
48
49
  ? tags.style({ code, href: src, inline })
49
50
  : tags.script({ code, inline, integrity, src, type })).join("\n")).concat("\n", head ?? "");
50
51
  };
52
+ function entrypoint_name(src) {
53
+ const file = src.split("/").at(-1) ?? src;
54
+ return file.replace(/-[A-Z0-9]+(?=\.(?:js|css)$)/i, "")
55
+ .replace(/\.(?:js|css)$/i, "");
56
+ }
57
+ function render_entrypoint(asset) {
58
+ if (asset.type === "style") {
59
+ return tags.style({
60
+ code: asset.code,
61
+ href: asset.src,
62
+ inline: asset.inline,
63
+ });
64
+ }
65
+ return tags.script({
66
+ code: asset.code,
67
+ inline: asset.inline,
68
+ integrity: asset.integrity,
69
+ src: asset.src,
70
+ type: "module",
71
+ });
72
+ }
73
+ function render_entrypoints(assets, names) {
74
+ return Object.fromEntries(names.map(name => {
75
+ const asset = assets.find(asset => asset.src !== undefined && entrypoint_name(asset.src) === name);
76
+ if (asset === undefined) {
77
+ throw new Error(`entrypoint ${name} not emitted`);
78
+ }
79
+ return [name, render_entrypoint(asset)];
80
+ }));
81
+ }
51
82
  const s_http = Symbol("s_http");
52
83
  const content_type_method = {
53
84
  "application/json": "json",
@@ -56,7 +87,7 @@ const content_type_method = {
56
87
  "multipart/form-data": "multipart",
57
88
  "application/octet-stream": "blob",
58
89
  };
59
- ;
90
+ const asset_extensions = [".js", ".css", ".woff2"];
60
91
  export default class ServeApp extends App {
61
92
  #init;
62
93
  #server;
@@ -65,10 +96,9 @@ export default class ServeApp extends App {
65
96
  #assets = [];
66
97
  #serve_assets;
67
98
  #pages;
68
- #stores;
69
99
  #frontends = new Map();
70
100
  #router;
71
- #i18n_config;
101
+ #entrypoints = {};
72
102
  constructor(rootfile, init) {
73
103
  const dir = fs.ref(rootfile).directory;
74
104
  super(dir, init.facade[s_config], {
@@ -78,12 +108,18 @@ export default class ServeApp extends App {
78
108
  log: init.log,
79
109
  });
80
110
  this.#init = init;
81
- this.#views = Object.fromEntries(init.views ?? []);
82
- this.#stores = Object.fromEntries((init.stores?.map(([k, s]) => [k, s.default])) ?? []);
111
+ this.#views = new Bag((init.views ?? []).map(([k, v]) => {
112
+ if (is.undefined(v.default))
113
+ throw E.view_missing_default_export(k);
114
+ return [k, v.default];
115
+ }), name => {
116
+ const f = fs.ref(name).path;
117
+ const extension = Object.keys(this.frontends).find(e => f.endsWith(e));
118
+ return is.undefined(extension) ? name : f.slice(0, -extension.length);
119
+ });
83
120
  this.#serve_assets = init.assets;
84
121
  this.#pages = init.pages;
85
122
  const http_config = this.#init.facade[s_config].http;
86
- this.#i18n_config = init.i18n;
87
123
  this.set(s_http, {
88
124
  host: http_config.host,
89
125
  port: http_config.port,
@@ -107,8 +143,9 @@ export default class ServeApp extends App {
107
143
  if (init.session !== undefined) {
108
144
  this.register(session_module(init.session));
109
145
  }
110
- if (init.i18n !== undefined)
111
- this.register(i18n_module(init.i18n));
146
+ const i18n_config = init.facade[s_config].i18n;
147
+ if (i18n_config !== undefined)
148
+ this.register(i18n_module(i18n_config));
112
149
  this.register(create({
113
150
  name: "builtin/handle",
114
151
  setup({ onHandle }) {
@@ -139,25 +176,9 @@ export default class ServeApp extends App {
139
176
  get frontends() {
140
177
  return Object.fromEntries(this.#frontends);
141
178
  }
142
- get stores() {
143
- return this.#stores;
144
- }
145
- get i18n() {
146
- return this.#i18n_config;
147
- }
148
- loadView(name) {
149
- const f = fs.ref(name).path;
150
- const frontends = Object.keys(this.frontends);
151
- const extension = frontends.find(client => f.endsWith(client));
152
- const base = is.undefined(extension) ? name : f.slice(0, -extension.length);
153
- const view = this.#views[base];
154
- if (is.undefined(view))
155
- throw E.view_missing(name);
156
- if (is.undefined(view.default))
157
- throw E.view_missing_default_export(name);
158
- return view.default;
179
+ get views() {
180
+ return this.#views;
159
181
  }
160
- ;
161
182
  headers(csp = {}) {
162
183
  const base = Object.entries(this.config("http.csp") ?? {});
163
184
  return {
@@ -171,7 +192,12 @@ export default class ServeApp extends App {
171
192
  render(content) {
172
193
  const { body, head, page, partial, placeholders = {} } = content;
173
194
  ["body", "head"].forEach(key => assert.undefined(placeholders[key]));
174
- return partial === true ? body : Object.entries(placeholders)
195
+ const all_placeholders = {
196
+ ...this.#entrypoints,
197
+ ...placeholders,
198
+ };
199
+ const entrypoint_names = Object.keys(this.config("entrypoints") ?? {});
200
+ return partial === true ? body : Object.entries(all_placeholders)
175
201
  // replace given placeholders, defaulting to ""
176
202
  .reduce((rendered, [key, value]) => rendered
177
203
  .replaceAll(`%${key}%`, value?.toString() ?? ""), this.page(page))
@@ -179,7 +205,8 @@ export default class ServeApp extends App {
179
205
  .replaceAll(/(?<keep>%(?:head|body)%)|%.*?%/gus, "$1")
180
206
  // replace body and head
181
207
  .replace("%body%", body)
182
- .replace("%head%", render_head(this.#assets, head));
208
+ .replace("%head%", render_head(this.#assets.filter(asset => asset.src === undefined
209
+ || !entrypoint_names.includes(entrypoint_name(asset.src))), head));
183
210
  }
184
211
  body_length(body) {
185
212
  return is.string(body) ? utf8.size(body) : 0;
@@ -214,20 +241,6 @@ export default class ServeApp extends App {
214
241
  };
215
242
  }
216
243
  ;
217
- async publish({ code, inline = false, src, type = "" }) {
218
- if (inline || type === "style") {
219
- this.#assets.push({
220
- code: inline ? code : "",
221
- inline,
222
- integrity: await hash(code),
223
- src: fs.join(this.config("http.static.root"), src ?? "").path,
224
- type,
225
- });
226
- }
227
- // rehash assets_csp
228
- this.create_csp();
229
- }
230
- ;
231
244
  create_csp() {
232
245
  this.#csp = this.#assets.map(({ integrity, type: directive }) => [`${directive === "style" ? "style" : "script"}-src`, integrity])
233
246
  .reduce((csp, [directive, _hash]) => ({
@@ -293,7 +306,7 @@ export default class ServeApp extends App {
293
306
  async start() {
294
307
  if (this.mode === "production") {
295
308
  this.#assets = await Promise.all(Object.entries(this.#serve_assets.client)
296
- .filter(([src]) => src.endsWith(".css") || src.endsWith(".js"))
309
+ .filter(([src]) => asset_extensions.some(ext => src.endsWith(ext)))
297
310
  .map(async ([src, asset]) => {
298
311
  const type = src.endsWith(".css") ? "style" : "js";
299
312
  const code = atob(asset.data);
@@ -311,7 +324,7 @@ export default class ServeApp extends App {
311
324
  const files = await client_dir.exists()
312
325
  ? await client_dir.files({
313
326
  recursive: true,
314
- filter: info => info.extension === ".js" || info.extension === ".css",
327
+ filter: info => asset_extensions.includes(info.extension),
315
328
  })
316
329
  : [];
317
330
  this.#assets = await Promise.all(files.map(async (file) => {
@@ -326,6 +339,8 @@ export default class ServeApp extends App {
326
339
  };
327
340
  }));
328
341
  }
342
+ this.#entrypoints = render_entrypoints(this.#assets, Object.keys(this.config("entrypoints") ?? {}));
343
+ this.create_csp();
329
344
  this.#server = await serve(async (request) => {
330
345
  try {
331
346
  return await handle(this, parse(request));
@@ -387,7 +402,7 @@ export default class ServeApp extends App {
387
402
  return undefined;
388
403
  }
389
404
  const handler = route_path.handler;
390
- const { contentType, body } = route_path.options;
405
+ const { contentType, body, path } = route_path.options;
391
406
  if (contentType !== undefined) {
392
407
  const raw = request.headers.try("content-type") ?? "";
393
408
  const actual = raw.split(";")[0].trim().toLowerCase();
@@ -396,7 +411,9 @@ export default class ServeApp extends App {
396
411
  }
397
412
  }
398
413
  const refined = Object.assign(Object.create(request), {
399
- path: new RequestBag(matched.params, "path", {
414
+ path: new RequestBag(is.defined(path)
415
+ ? path.parse(matched.params)
416
+ : matched.params, "path", {
400
417
  normalize: k => k.toLowerCase(),
401
418
  raw: request.url.pathname,
402
419
  }),
@@ -1,5 +1,4 @@
1
1
  import type AppFacade from "#app/Facade";
2
- import type I18NConfig from "#i18n/Config";
3
2
  import type { Schema as LogSchema } from "#logger";
4
3
  import type Mode from "#Mode";
5
4
  import type SessionConfig from "#session/Config";
@@ -19,7 +18,6 @@ type ServeInit = {
19
18
  }>;
20
19
  };
21
20
  views?: [string, Import][];
22
- stores?: [string, Import][];
23
21
  facade: AppFacade;
24
22
  routes: [string, {
25
23
  default: any;
@@ -29,7 +27,6 @@ type ServeInit = {
29
27
  log: typeof LogSchema.infer;
30
28
  pages: Dict<string>;
31
29
  session?: SessionConfig;
32
- i18n?: I18NConfig;
33
30
  };
34
31
  export type { ServeInit as default };
35
32
  //# sourceMappingURL=Init.d.ts.map
@@ -1,3 +1,3 @@
1
- declare const _default: "0.6";
1
+ declare const _default = "0.6";
2
2
  export default _default;
3
3
  //# sourceMappingURL=TAG.d.ts.map
@@ -0,0 +1,4 @@
1
+ import type SessionFacade from "#session/SessionFacade";
2
+ import type { StoreSchema } from "pema";
3
+ export default function session<S extends StoreSchema>(): SessionFacade<any>;
4
+ //# sourceMappingURL=config.client.d.ts.map
@@ -0,0 +1,24 @@
1
+ export default function session() {
2
+ const facade = {
3
+ get id() {
4
+ return "";
5
+ },
6
+ get exists() {
7
+ return false;
8
+ },
9
+ create() {
10
+ },
11
+ get() {
12
+ return {};
13
+ },
14
+ try() {
15
+ return {};
16
+ },
17
+ set() {
18
+ },
19
+ destroy() {
20
+ },
21
+ };
22
+ return facade;
23
+ }
24
+ //# sourceMappingURL=config.client.js.map
@@ -0,0 +1,15 @@
1
+ import configSchema from "#session/schema";
2
+ import type SessionFacade from "#session/SessionFacade";
3
+ import type Store from "#store/Store";
4
+ import type { InferStore, StoreSchema } from "pema";
5
+ type ConfigInput = typeof configSchema.input;
6
+ type X<T> = {
7
+ [K in keyof T]: T[K];
8
+ } & {};
9
+ type Infer<S extends StoreSchema> = X<Omit<InferStore<S>, "id" | "session_id">>;
10
+ export default function session<S extends StoreSchema>(config: {
11
+ store: Store<S>;
12
+ } & Partial<ConfigInput>): SessionFacade<Infer<S>>;
13
+ export default function session(Infer?: Omit<Partial<ConfigInput>, "store">): SessionFacade<unknown>;
14
+ export {};
15
+ //# sourceMappingURL=config.server.d.ts.map
@@ -0,0 +1,44 @@
1
+ import E from "#errors";
2
+ import configSchema from "#session/schema";
3
+ import local_storage from "#session/storage";
4
+ import s_config from "#symbol/config";
5
+ export default function session(config) {
6
+ const parsed = configSchema.parse(config ?? {});
7
+ const store = parsed.store;
8
+ // bind the ALS store to this T
9
+ const storage = local_storage();
10
+ const current = () => {
11
+ const s = storage.getStore();
12
+ if (s === undefined)
13
+ throw E.session_handle_unavailable();
14
+ return s;
15
+ };
16
+ const facade = {
17
+ get id() {
18
+ return current().id;
19
+ },
20
+ get exists() {
21
+ return current().exists;
22
+ },
23
+ create(initial) {
24
+ current().create(initial);
25
+ },
26
+ get() {
27
+ return current().get();
28
+ },
29
+ try() {
30
+ return current().try();
31
+ },
32
+ set(next) {
33
+ current().set(next);
34
+ },
35
+ destroy() {
36
+ current().destroy();
37
+ },
38
+ get [s_config]() {
39
+ return { ...parsed, store };
40
+ },
41
+ };
42
+ return facade;
43
+ }
44
+ //# sourceMappingURL=config.server.js.map
@@ -1,15 +1,3 @@
1
- import configSchema from "#session/schema";
2
- import type SessionFacade from "#session/SessionFacade";
3
- import type Store from "#store/Store";
4
- import type { InferStore, StoreSchema } from "pema";
5
- type ConfigInput = typeof configSchema.input;
6
- type X<T> = {
7
- [K in keyof T]: T[K];
8
- } & {};
9
- type Infer<S extends StoreSchema> = X<Omit<InferStore<S>, "id" | "session_id">>;
10
- export default function session<S extends StoreSchema>(config: {
11
- store: Store<S>;
12
- } & Partial<ConfigInput>): SessionFacade<Infer<S>>;
13
- export default function session(Infer?: Omit<Partial<ConfigInput>, "store">): SessionFacade<unknown>;
14
- export {};
1
+ import config from "#session/config";
2
+ export default config;
15
3
  //# sourceMappingURL=index.d.ts.map
@@ -1,44 +1,3 @@
1
- import E from "#errors";
2
- import configSchema from "#session/schema";
3
- import local_storage from "#session/storage";
4
- import s_config from "#symbol/config";
5
- export default function session(config) {
6
- const parsed = configSchema.parse(config ?? {});
7
- const store = parsed.store;
8
- // bind the ALS store to this T
9
- const storage = local_storage();
10
- const current = () => {
11
- const s = storage.getStore();
12
- if (s === undefined)
13
- throw E.session_handle_unavailable();
14
- return s;
15
- };
16
- const facade = {
17
- get id() {
18
- return current().id;
19
- },
20
- get exists() {
21
- return current().exists;
22
- },
23
- create(initial) {
24
- current().create(initial);
25
- },
26
- get() {
27
- return current().get();
28
- },
29
- try() {
30
- return current().try();
31
- },
32
- set(next) {
33
- current().set(next);
34
- },
35
- destroy() {
36
- current().destroy();
37
- },
38
- get [s_config]() {
39
- return { ...parsed, store };
40
- },
41
- };
42
- return facade;
43
- }
1
+ import config from "#session/config";
2
+ export default config;
44
3
  //# sourceMappingURL=index.js.map
@@ -1,13 +1,13 @@
1
1
  import Store from "#store/Store";
2
2
  declare const _default: import("pema").ObjectType<import("pema").NormalizeSchemaObject<{
3
3
  readonly cookie: {
4
- readonly httpOnly: import("pema").DefaultType<import("pema").BooleanType, true>;
5
- readonly name: import("pema").DefaultType<import("pema").StringType, "session_id">;
6
- readonly path: import("pema").DefaultType<import("pema").StringType, "/">;
7
- readonly sameSite: import("pema").DefaultType<import("pema").UnionType<[import("pema").LiteralType<"Strict">, import("pema").LiteralType<"Lax">, import("pema").LiteralType<"None">]>, "Lax" | "None" | "Strict">;
4
+ httpOnly: import("pema").DefaultType<import("pema").BooleanType<undefined>, true>;
5
+ name: import("pema").DefaultType<import("pema").StringType, "session_id">;
6
+ path: import("pema").DefaultType<import("pema").StringType, "/">;
7
+ sameSite: import("pema").DefaultType<import("pema").UnionType<[import("pema").LiteralType<"Strict", undefined>, import("pema").LiteralType<"Lax", undefined>, import("pema").LiteralType<"None", undefined>], undefined>, "Lax" | "None" | "Strict">;
8
8
  };
9
9
  readonly store: import("pema").DefaultType<import("pema").ConstructorType<typeof Store>, Store<import("../store/StoreInput.js").default, string>>;
10
- }>, {
10
+ }>, undefined, {
11
11
  cookie: {
12
12
  httpOnly: boolean;
13
13
  name: string;
@@ -8,7 +8,7 @@ export default class PrimaryKey<T extends AllowedPKType> {
8
8
  constructor(type: T, options?: Options);
9
9
  static new<T extends AllowedPKType>(type: T, options?: Options): PrimaryKey<T>;
10
10
  get type(): T;
11
- get datatype(): "uuid" | "uuid_v4" | "uuid_v7" | "u128" | "u16" | "u32" | "u64" | "u8";
11
+ get datatype(): "u128" | "u16" | "u32" | "u64" | "u8" | "uuid" | "uuid_v4" | "uuid_v7";
12
12
  get name(): string;
13
13
  get nullable(): boolean;
14
14
  get generate(): boolean;
@@ -7,5 +7,18 @@ declare function store(): {
7
7
  update: () => Promise<number>;
8
8
  delete: () => Promise<number>;
9
9
  };
10
+ declare namespace store {
11
+ var key: {
12
+ primary(): void;
13
+ foreign(): void;
14
+ };
15
+ }
16
+ declare namespace store {
17
+ var relation: {
18
+ one(): void;
19
+ many(): void;
20
+ is(): void;
21
+ };
22
+ }
10
23
  export default store;
11
24
  //# sourceMappingURL=store.client.d.ts.map
@@ -14,5 +14,14 @@ function store() {
14
14
  delete: async () => 0,
15
15
  };
16
16
  }
17
+ store.key = {
18
+ primary() { },
19
+ foreign() { },
20
+ };
21
+ store.relation = {
22
+ one() { },
23
+ many() { },
24
+ is() { },
25
+ };
17
26
  export default store;
18
27
  //# sourceMappingURL=store.client.js.map