@primate/core 0.6.3 → 0.7.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 (187) hide show
  1. package/lib/private/App.d.ts +76 -149
  2. package/lib/private/App.js +22 -6
  3. package/lib/private/Flags.d.ts +5 -3
  4. package/lib/private/Flags.js +4 -2
  5. package/lib/private/app/Facade.d.ts +77 -156
  6. package/lib/private/app/Facade.js +4 -1
  7. package/lib/private/build/App.d.ts +4 -2
  8. package/lib/private/build/App.js +13 -4
  9. package/lib/private/build/client/index.js +24 -10
  10. package/lib/private/build/client/plugin/routes.d.ts +4 -0
  11. package/lib/private/build/client/plugin/routes.js +77 -0
  12. package/lib/private/build/hook.js +14 -6
  13. package/lib/private/build/index.d.ts +3 -2
  14. package/lib/private/build/index.js +9 -15
  15. package/lib/private/build/preclient/index.d.ts +3 -0
  16. package/lib/private/build/preclient/index.js +69 -0
  17. package/lib/private/build/preclient/plugin/routes.d.ts +4 -0
  18. package/lib/private/build/preclient/plugin/routes.js +44 -0
  19. package/lib/private/build/server/index.js +8 -5
  20. package/lib/private/build/server/plugin/assets.js +3 -3
  21. package/lib/private/build/server/plugin/native-addons.js +6 -8
  22. package/lib/private/build/server/plugin/node-imports.js +5 -7
  23. package/lib/private/build/server/plugin/route-client.d.ts +4 -0
  24. package/lib/private/build/server/plugin/route-client.js +111 -0
  25. package/lib/private/build/server/plugin/route.js +3 -10
  26. package/lib/private/build/server/plugin/virtual-pages.js +3 -3
  27. package/lib/private/build/server/plugin/virtual-routes.d.ts +2 -1
  28. package/lib/private/build/server/plugin/virtual-routes.js +27 -8
  29. package/lib/private/build/server/plugin/wasm.js +3 -2
  30. package/lib/private/build/shared/intercept.d.ts +4 -0
  31. package/lib/private/build/shared/intercept.js +29 -0
  32. package/lib/private/client/Data.d.ts +1 -1
  33. package/lib/private/client/boot.js +2 -2
  34. package/lib/private/client/create-form.d.ts +11 -1
  35. package/lib/private/client/create-form.js +21 -3
  36. package/lib/private/client/index.d.ts +2 -2
  37. package/lib/private/client/navigate.d.ts +1 -0
  38. package/lib/private/client/navigate.js +7 -6
  39. package/lib/private/client/submit.d.ts +2 -1
  40. package/lib/private/client/submit.js +8 -7
  41. package/lib/private/client/{http.d.ts → transport.d.ts} +3 -3
  42. package/lib/private/client/{http.js → transport.js} +7 -9
  43. package/lib/private/config/schema.d.ts +5 -13
  44. package/lib/private/config/schema.js +1 -5
  45. package/lib/private/db/DB.d.ts +3 -1
  46. package/lib/private/db/MemoryDB.d.ts +5 -2
  47. package/lib/private/db/MemoryDB.js +33 -19
  48. package/lib/private/db/SQLDB.d.ts +23 -0
  49. package/lib/private/db/SQLDB.js +2 -0
  50. package/lib/private/db/errors.d.ts +74 -7
  51. package/lib/private/db/errors.js +31 -7
  52. package/lib/private/db/migrate/apply.js +8 -9
  53. package/lib/private/db/migrate/bundle.js +2 -2
  54. package/lib/private/db/migrate/create.js +18 -20
  55. package/lib/private/db/migrate/status.js +9 -10
  56. package/lib/private/db/migrate/store.d.ts +3 -3
  57. package/lib/private/db/migrate/store.js +5 -5
  58. package/lib/private/db/test.js +256 -115
  59. package/lib/private/db/testSQL.d.ts +50 -0
  60. package/lib/private/db/testSQL.js +196 -0
  61. package/lib/private/errors.d.ts +66 -9
  62. package/lib/private/errors.js +37 -16
  63. package/lib/private/frontend.d.ts +4 -4
  64. package/lib/private/frontend.js +11 -8
  65. package/lib/private/i18n/errors.d.ts +7 -1
  66. package/lib/private/i18n/errors.js +1 -1
  67. package/lib/private/i18n/index/types.d.ts +1 -1
  68. package/lib/private/i18n/locale.d.ts +1 -1
  69. package/lib/private/i18n/module.js +6 -5
  70. package/lib/private/index.d.ts +10 -2
  71. package/lib/private/index.js +13 -1
  72. package/lib/private/logger.d.ts +24 -0
  73. package/lib/private/logger.js +66 -0
  74. package/lib/private/module/Setup.d.ts +3 -0
  75. package/lib/private/module/create.d.ts +2 -1
  76. package/lib/private/module/create.js +4 -0
  77. package/lib/private/paths.d.ts +2 -3
  78. package/lib/private/paths.js +6 -12
  79. package/lib/private/request/ContentType.d.ts +3 -0
  80. package/lib/private/request/ContentType.js +2 -0
  81. package/lib/private/request/RequestBag.d.ts +2 -18
  82. package/lib/private/request/RequestBag.js +4 -16
  83. package/lib/private/request/RequestBody.d.ts +20 -28
  84. package/lib/private/request/RequestBody.js +63 -86
  85. package/lib/private/request/RequestFacade.d.ts +2 -2
  86. package/lib/private/request/handle.js +2 -2
  87. package/lib/private/request/parse.js +2 -4
  88. package/lib/private/request/route.js +15 -8
  89. package/lib/private/response/binary.d.ts +2 -2
  90. package/lib/private/response/binary.js +6 -6
  91. package/lib/private/response/error.js +6 -2
  92. package/lib/private/response/json.js +2 -2
  93. package/lib/private/response/null.d.ts +3 -0
  94. package/lib/private/response/null.js +6 -0
  95. package/lib/private/response/redirect.js +4 -3
  96. package/lib/private/response/respond.js +4 -4
  97. package/lib/private/response/sse.js +2 -2
  98. package/lib/private/response/text.js +2 -2
  99. package/lib/private/route/ContentTypeMap.d.ts +10 -0
  100. package/lib/private/route/ContentTypeMap.js +2 -0
  101. package/lib/private/route/Handler.d.ts +3 -2
  102. package/lib/private/route/NarrowedRequest.d.ts +23 -0
  103. package/lib/private/route/NarrowedRequest.js +2 -0
  104. package/lib/private/route/Options.d.ts +6 -1
  105. package/lib/private/route/Path.d.ts +2 -2
  106. package/lib/private/route/hook.d.ts +3 -1
  107. package/lib/private/route/hook.js +1 -2
  108. package/lib/private/route/router.d.ts +7 -11
  109. package/lib/private/route/router.js +13 -20
  110. package/lib/private/route.client.d.ts +36 -0
  111. package/lib/private/route.client.js +8 -0
  112. package/lib/private/route.d.ts +21 -5
  113. package/lib/private/route.js +21 -5
  114. package/lib/private/serve/App.d.ts +1 -2
  115. package/lib/private/serve/App.js +64 -58
  116. package/lib/private/serve/Init.d.ts +2 -0
  117. package/lib/private/serve/dev-module.js +2 -3
  118. package/lib/private/serve/index.js +5 -6
  119. package/lib/private/server/TAG.d.ts +1 -1
  120. package/lib/private/server/TAG.js +1 -1
  121. package/lib/private/session/index.d.ts +1 -1
  122. package/lib/private/session/index.js +3 -2
  123. package/lib/private/session/module.js +3 -3
  124. package/lib/private/session/schema.d.ts +3 -3
  125. package/lib/private/session/schema.js +4 -3
  126. package/lib/private/store/ExtractRelation.d.ts +7 -0
  127. package/lib/private/store/ExtractRelation.js +2 -0
  128. package/lib/private/store/ExtractSchema.d.ts +10 -0
  129. package/lib/private/{orm → store}/ForeignKey.d.ts +1 -1
  130. package/lib/private/store/Init.d.ts +13 -0
  131. package/lib/private/store/Init.js +2 -0
  132. package/lib/private/{orm/store.d.ts → store/Store.d.ts} +50 -50
  133. package/lib/private/{orm/store.js → store/Store.js} +163 -107
  134. package/lib/private/store/StoreInput.d.ts +11 -0
  135. package/lib/private/store/key.d.ts +8 -0
  136. package/lib/private/store/key.js +8 -0
  137. package/lib/private/{orm → store}/parse.d.ts +3 -3
  138. package/lib/private/{orm → store}/parse.js +7 -2
  139. package/lib/private/store/relation.d.ts +29 -0
  140. package/lib/private/store/relation.js +26 -0
  141. package/lib/private/store.d.ts +24 -0
  142. package/lib/private/store.js +10 -0
  143. package/lib/public/db/errors.d.ts +1 -1
  144. package/lib/public/db/errors.js +1 -1
  145. package/lib/public/db/testSQL.d.ts +2 -0
  146. package/lib/public/db/testSQL.js +2 -0
  147. package/lib/public/db.d.ts +1 -0
  148. package/lib/public/index.d.ts +1 -0
  149. package/lib/public/index.js +1 -1
  150. package/lib/public/response.d.ts +6 -6
  151. package/lib/public/response.js +4 -1
  152. package/lib/public/route.client.d.ts +2 -0
  153. package/lib/public/route.client.js +2 -0
  154. package/lib/public/store.d.ts +2 -0
  155. package/lib/public/store.js +2 -0
  156. package/package.json +24 -17
  157. package/lib/private/bye.d.ts +0 -3
  158. package/lib/private/bye.js +0 -4
  159. package/lib/private/log.d.ts +0 -20
  160. package/lib/private/log.js +0 -47
  161. package/lib/private/orm/ExtractSchema.d.ts +0 -9
  162. package/lib/private/orm/StoreInput.d.ts +0 -10
  163. package/lib/private/orm/key.d.ts +0 -8
  164. package/lib/private/orm/key.js +0 -8
  165. package/lib/private/orm/relation.d.ts +0 -43
  166. package/lib/private/orm/relation.js +0 -26
  167. package/lib/private/request/Verb.d.ts +0 -4
  168. package/lib/private/request/Verb.js +0 -2
  169. package/lib/private/request/verbs.d.ts +0 -3
  170. package/lib/private/request/verbs.js +0 -12
  171. package/lib/private/route/wrap.d.ts +0 -2
  172. package/lib/private/route/wrap.js +0 -12
  173. package/lib/public/log.d.ts +0 -2
  174. package/lib/public/log.js +0 -2
  175. package/lib/public/orm/key.d.ts +0 -2
  176. package/lib/public/orm/key.js +0 -2
  177. package/lib/public/orm/relation.d.ts +0 -2
  178. package/lib/public/orm/relation.js +0 -2
  179. package/lib/public/orm/store.d.ts +0 -2
  180. package/lib/public/orm/store.js +0 -2
  181. package/lib/public/request/verbs.d.ts +0 -2
  182. package/lib/public/request/verbs.js +0 -2
  183. /package/lib/private/{orm → store}/ExtractSchema.js +0 -0
  184. /package/lib/private/{orm → store}/ForeignKey.js +0 -0
  185. /package/lib/private/{orm → store}/PrimaryKey.d.ts +0 -0
  186. /package/lib/private/{orm → store}/PrimaryKey.js +0 -0
  187. /package/lib/private/{orm → store}/StoreInput.js +0 -0
@@ -1,7 +1,6 @@
1
1
  import E from "#errors";
2
- import wrap from "#route/wrap";
3
2
  import fs from "@rcompat/fs";
4
- const contents = "export default {};";
3
+ const empty = "export default {};";
5
4
  export default function plugin_server_route(app) {
6
5
  const path_routes = app.path.routes;
7
6
  return {
@@ -28,23 +27,17 @@ export default function plugin_server_route(app) {
28
27
  if (!file || !extension) {
29
28
  throw E.build_missing_route(relative, path_routes);
30
29
  }
31
- // normalise "routes/foo.ext" -> "foo" for router
32
- const relative_from_routes = file.path.split("routes").pop();
33
- const no_extensions = relative_from_routes
34
- .replace(/^[\\/]/, "")
35
- .slice(0, -extension.length);
36
- const route_path = no_extensions.replace(/\\/g, "/");
37
30
  const resolveDir = file.directory.path;
38
31
  const watchFiles = [file.path];
39
32
  const binder = app.binder(file);
40
33
  if (!binder)
41
- return { contents, loader: "js", resolveDir, watchFiles };
34
+ return { contents: empty, loader: "js", resolveDir, watchFiles };
42
35
  const compiled = await binder(file, {
43
36
  build: { id: app.id },
44
37
  context: "routes",
45
38
  });
46
39
  return {
47
- contents: wrap(compiled, route_path, app.id),
40
+ contents: compiled,
48
41
  loader: extension === ".ts" ? "ts" : "js",
49
42
  resolveDir,
50
43
  watchFiles,
@@ -1,5 +1,5 @@
1
- import fs from "@rcompat/fs";
2
- const core_pkg = await fs.project.root(import.meta.dirname);
1
+ import runtime from "@rcompat/runtime";
2
+ const core = await runtime.projectRoot(import.meta.dirname);
3
3
  export default function plugin_server_virtual_pages(app) {
4
4
  return {
5
5
  name: "primate/server/virtual/pages",
@@ -9,7 +9,7 @@ export default function plugin_server_virtual_pages(app) {
9
9
  });
10
10
  build.onLoad({ filter: /.*/, namespace: "primate-pages" }, async () => {
11
11
  const filter = /^.*\.html$/ui;
12
- const defaults = core_pkg.join("lib", "private", "defaults");
12
+ const defaults = core.join("lib", "private", "defaults");
13
13
  const pages = {};
14
14
  for (const file of await defaults.files({ filter })) {
15
15
  pages[file.name] = file;
@@ -1,4 +1,5 @@
1
1
  import type BuildApp from "#build/App";
2
2
  import type { Plugin } from "esbuild";
3
- export default function plugin_server_virtual_routes(app: BuildApp): Plugin;
3
+ declare function plugin_server_virtual_routes(app: BuildApp): Plugin;
4
+ export default plugin_server_virtual_routes;
4
5
  //# sourceMappingURL=virtual-routes.d.ts.map
@@ -1,8 +1,15 @@
1
- export default function plugin_server_virtual_routes(app) {
1
+ function is_hook_file(p) {
2
+ const basename = p.split("/").at(-1) ?? p;
3
+ return basename === "+hook" || basename.startsWith("+hook.");
4
+ }
5
+ function plugin_server_virtual_routes(app) {
2
6
  const extension_pattern = new RegExp(`(${app.extensions.map(e => e.replace(".", "\\.")).join("|")})$`);
3
- const is_route_file = (f) => !f.name.endsWith("~") &&
4
- !f.name.startsWith(".") &&
5
- extension_pattern.test(f.path);
7
+ function is_route_file(f) {
8
+ return !f.name.endsWith("~") &&
9
+ !f.name.startsWith(".") &&
10
+ !f.name.startsWith("-") &&
11
+ extension_pattern.test(f.path);
12
+ }
6
13
  return {
7
14
  name: "primate/server/virtual/routes",
8
15
  setup(build) {
@@ -16,13 +23,24 @@ export default function plugin_server_virtual_routes(app) {
16
23
  recursive: true,
17
24
  });
18
25
  const contents = `
19
- const route = [];
26
+ import router from "primate/router";
27
+ ${route_files.map((file, i) => {
28
+ const path = app.basename(file, app.path.routes);
29
+ return `import route${i} from "app:route/${path}";`;
30
+ }).join("\n")}
31
+ const routes = [];
20
32
  ${route_files.map((file, i) => {
21
33
  const path = app.basename(file, app.path.routes);
22
- return `const route${i} = (await import("app:route/${path}")).default;
23
- route.push(["${path}", route${i}]);`;
34
+ return is_hook_file(path)
35
+ ? `router.addHook("${path}", route${i});
36
+ routes.push(["${path}", route${i}]);
37
+ `
38
+ : `for (const [method, { handler, options }] of Object.entries(route${i})) {
39
+ router.add("${path}", method, handler, options);
40
+ }
41
+ routes.push(["${path}", route${i}]);`;
24
42
  }).join("\n")}
25
- export default route;
43
+ export default routes;
26
44
  `;
27
45
  const watchDirs = (await app.path.routes.dirs({
28
46
  recursive: true,
@@ -38,4 +56,5 @@ export default function plugin_server_virtual_routes(app) {
38
56
  },
39
57
  };
40
58
  }
59
+ export default plugin_server_virtual_routes;
41
60
  //# sourceMappingURL=virtual-routes.js.map
@@ -20,13 +20,14 @@ export default function plugin_server_wasm(app) {
20
20
  });
21
21
  build.onLoad({ filter: /.*/, namespace: "wasm-dev" }, async (args) => {
22
22
  const wasm_file = app.runpath("wasm", args.path + ".wasm");
23
+ const fs_path = import.meta.resolve("@rcompat/fs");
23
24
  return {
24
25
  contents: `
25
- import fs from "@rcompat/fs";
26
+ const { default: fs } = await import("${fs_path}");
26
27
  export default await fs.ref("${wasm_file.path}").bytes();
27
28
  `,
28
29
  loader: "js",
29
- resolveDir: app.root.path,
30
+ resolveDir: new URL(".", import.meta.url).pathname,
30
31
  };
31
32
  });
32
33
  },
@@ -0,0 +1,4 @@
1
+ import type { FileRef } from "@rcompat/fs";
2
+ import type { OnResolveArgs } from "esbuild";
3
+ export default function intercept(args: OnResolveArgs, views: FileRef): boolean;
4
+ //# sourceMappingURL=intercept.d.ts.map
@@ -0,0 +1,29 @@
1
+ import runtime from "@rcompat/runtime";
2
+ function is_bare(path) {
3
+ return /^[a-z]/.test(path);
4
+ }
5
+ function is_npm_package(path, resolve_dir) {
6
+ if (!path.startsWith("@"))
7
+ return false;
8
+ const parts = path.split("/");
9
+ if (parts.length < 2)
10
+ return false;
11
+ const pkg = parts[0] + "/" + parts[1];
12
+ try {
13
+ runtime.resolve(pkg, resolve_dir);
14
+ return true;
15
+ }
16
+ catch {
17
+ return false;
18
+ }
19
+ }
20
+ export default function intercept(args, views) {
21
+ if (!args.resolveDir.startsWith(views.path))
22
+ return true;
23
+ if (is_bare(args.path))
24
+ return true;
25
+ if (is_npm_package(args.path, args.resolveDir))
26
+ return true;
27
+ return false;
28
+ }
29
+ //# sourceMappingURL=intercept.js.map
@@ -4,7 +4,7 @@ import type { Dict } from "@rcompat/type";
4
4
  type ClientData<T extends Dict = Dict> = {
5
5
  view: string;
6
6
  request: RequestView;
7
- spa: boolean;
7
+ csr: boolean;
8
8
  ssr: boolean;
9
9
  mode: Mode;
10
10
  } & T;
@@ -2,7 +2,7 @@ import navigate from "#client/navigate";
2
2
  import root from "#client/root";
3
3
  import storage from "#client/storage";
4
4
  import submit from "#client/submit";
5
- import { MIME } from "@rcompat/http";
5
+ import http from "@rcompat/http";
6
6
  export default (u) => {
7
7
  root.set(u);
8
8
  const { location, history } = globalThis;
@@ -50,7 +50,7 @@ export default (u) => {
50
50
  const action = target.action ?? location.pathname;
51
51
  const url = new URL(action);
52
52
  const data = new FormData(target);
53
- const form = enctype === MIME.MULTIPART_FORM_DATA
53
+ const form = enctype === http.MIME.MULTIPART_FORM_DATA
54
54
  ? data
55
55
  : new URLSearchParams(data);
56
56
  try {
@@ -1,6 +1,6 @@
1
1
  import type { Dict } from "@rcompat/type";
2
2
  type FormId = string;
3
- type FieldErrors = readonly string[];
3
+ type FieldErrors = string[];
4
4
  type FormErrors = {
5
5
  form: FieldErrors;
6
6
  fields: Dict<FieldErrors>;
@@ -15,11 +15,21 @@ export type FormView = FormSnapshot & {
15
15
  submit: (event?: Event) => Promise<void>;
16
16
  };
17
17
  type FormSubscriber = (snapshot: FormSnapshot) => void;
18
+ export type MethodMeta = {
19
+ contentType?: string;
20
+ };
21
+ export type ClientMethod<Values extends Dict = Dict> = MethodMeta & ((args: {
22
+ body: Values;
23
+ }) => Promise<Response>);
18
24
  export type FormInit = {
19
25
  id?: string;
20
26
  method?: "POST" | "PUT" | "PATCH" | "DELETE";
21
27
  url?: string;
22
28
  headers?: Dict<string>;
29
+ action?: (args: {
30
+ body: unknown;
31
+ }) => Promise<Response>;
32
+ contentType?: string;
23
33
  };
24
34
  type FormController = {
25
35
  subscribe(fn: FormSubscriber): () => void;
@@ -1,5 +1,6 @@
1
1
  import extract_issues from "#client/extract-issues";
2
2
  import submit from "#client/submit";
3
+ import is from "@rcompat/is";
3
4
  function decode_pointer_segment(segment) {
4
5
  // decode JSON Pointer: ~1 -> /, ~0 -> ~
5
6
  return segment.replace(/~1/g, "/").replace(/~0/g, "~");
@@ -21,6 +22,21 @@ function pointer_to_fieldname(path) {
21
22
  }
22
23
  return name;
23
24
  }
25
+ function content_type_body(contentType, form_data) {
26
+ if (contentType === "application/json")
27
+ return Object.fromEntries(form_data);
28
+ if (contentType === "multipart/form-data")
29
+ return form_data;
30
+ // default: application/x-www-form-urlencoded
31
+ return new URLSearchParams(form_data);
32
+ }
33
+ function form_data_body(form_data) {
34
+ for (const value of form_data.values()) {
35
+ if (value instanceof File && value.size > 0)
36
+ return form_data;
37
+ }
38
+ return new URLSearchParams(form_data);
39
+ }
24
40
  export default function createForm(init) {
25
41
  const id = init.id ?? `form-${crypto.randomUUID()}`;
26
42
  let snapshot = {
@@ -83,7 +99,9 @@ export default function createForm(init) {
83
99
  const form_data = new FormData(form_element);
84
100
  setSubmitting(true);
85
101
  try {
86
- const response = await submit(url, form_data, method);
102
+ const response = await (is.defined(init.action)
103
+ ? init.action({ body: content_type_body(init.contentType, form_data) })
104
+ : submit(url, form_data_body(form_data), method));
87
105
  if (response.ok) {
88
106
  // on success: clear errors, let the app decide what to do next
89
107
  // (redirect/reload)
@@ -91,8 +109,8 @@ export default function createForm(init) {
91
109
  publish();
92
110
  return;
93
111
  }
94
- const payload = await response.json();
95
- const issues = extract_issues(payload); // all issues, all paths
112
+ // all issues, all paths
113
+ const issues = extract_issues(await response.json());
96
114
  setErrors(issues);
97
115
  }
98
116
  catch (error) {
@@ -1,4 +1,4 @@
1
- import type { FormInit, FormView } from "#client/create-form";
1
+ import type { ClientMethod, FormInit, FormView, MethodMeta } from "#client/create-form";
2
2
  import createForm from "#client/create-form";
3
3
  import type Data from "#client/Data";
4
4
  import type Publish from "#client/Publish";
@@ -19,5 +19,5 @@ declare const client: {
19
19
  toValidated: typeof toValidated;
20
20
  };
21
21
  export default client;
22
- export type { Data, FormInit, FormView, Publish, Render, ValidateInit, ValidateUpdater, ValidationError, ViewResponse, };
22
+ export type { ClientMethod, Data, FormInit, FormView, MethodMeta, Publish, Render, ValidateInit, ValidateUpdater, ValidationError, ViewResponse };
23
23
  //# sourceMappingURL=index.d.ts.map
@@ -1,6 +1,7 @@
1
1
  type Location = {
2
2
  hash: string;
3
3
  pathname: string;
4
+ search: string;
4
5
  };
5
6
  declare function goto(target: Location, state?: boolean, after?: () => void): Promise<void>;
6
7
  declare function go(href: string, event?: Event): Promise<void>;
@@ -1,9 +1,9 @@
1
- import http from "#client/http";
2
1
  import root from "#client/root";
3
2
  import storage from "#client/storage";
4
- import { MIME } from "@rcompat/http";
3
+ import transport from "#client/transport";
4
+ import http from "@rcompat/http";
5
5
  const headers = {
6
- Accept: MIME.APPLICATION_JSON,
6
+ Accept: http.MIME.APPLICATION_JSON,
7
7
  };
8
8
  const get_by_id_or_name = (name) => document.getElementById(name) ?? document.getElementsByName(name)[0];
9
9
  const scroll_hash = (hash) => {
@@ -18,13 +18,14 @@ async function goto(target, state = false, after) {
18
18
  try {
19
19
  const { scrollTop } = globalThis.document.scrollingElement;
20
20
  const { location } = globalThis;
21
- const { requested, response } = await http.refetch(target.pathname, { headers });
22
- if (http.is_json(response)) {
21
+ const path = target.pathname + target.search;
22
+ const { requested, response } = await transport.refetch(path, { headers });
23
+ if (transport.is_json(response)) {
23
24
  if (response.ok)
24
25
  root.update(await response.json());
25
26
  if (state) {
26
27
  storage.new({ hash: location.hash, pathname: location.pathname, scrollTop });
27
- history.pushState({}, "", `${target.pathname}${target.hash}`);
28
+ history.pushState({}, "", `${path}${target.hash}`);
28
29
  }
29
30
  after?.();
30
31
  return;
@@ -1,2 +1,3 @@
1
- export default function submit(pathname: string, body: any, method: string): Promise<Response>;
1
+ declare function submit(pathname: string, body: any, method: string): Promise<Response>;
2
+ export default submit;
2
3
  //# sourceMappingURL=submit.d.ts.map
@@ -1,18 +1,18 @@
1
- import http from "#client/http";
2
1
  import root from "#client/root";
3
2
  import storage from "#client/storage";
4
- import { MIME } from "@rcompat/http";
3
+ import transport from "#client/transport";
4
+ import http from "@rcompat/http";
5
5
  const headers = {
6
- Accept: MIME.APPLICATION_JSON,
6
+ Accept: http.MIME.APPLICATION_JSON,
7
7
  };
8
- export default async function submit(pathname, body, method) {
9
- const { requested, response } = await http.refetch(pathname, {
8
+ async function submit(pathname, body, method) {
9
+ const { requested, response } = await transport.refetch(pathname, {
10
10
  body, headers, method,
11
11
  });
12
12
  if (response.redirected) {
13
13
  const { location, document, history } = globalThis;
14
14
  const scrollTop = document.scrollingElement?.scrollTop ?? 0;
15
- if (http.is_json(response))
15
+ if (transport.is_json(response))
16
16
  root.update(await response.json());
17
17
  storage.new({
18
18
  hash: location.hash,
@@ -23,7 +23,7 @@ export default async function submit(pathname, body, method) {
23
23
  history.pushState({}, "", url.pathname + url.search);
24
24
  return response;
25
25
  }
26
- if (http.is_json(response)) {
26
+ if (transport.is_json(response)) {
27
27
  if (response.ok) {
28
28
  root.update(await response.json());
29
29
  history.replaceState({}, "", requested.pathname + requested.search);
@@ -38,4 +38,5 @@ export default async function submit(pathname, body, method) {
38
38
  globalThis.location.assign(target);
39
39
  return response;
40
40
  }
41
+ export default submit;
41
42
  //# sourceMappingURL=submit.js.map
@@ -4,10 +4,10 @@ declare function refetch(input: string | URL, init?: RequestInit, max_hops?: num
4
4
  }>;
5
5
  declare function is_json(response: Response): boolean;
6
6
  declare function submit(pathname: string, body: any, method: string): Promise<Response>;
7
- declare const http: {
7
+ declare const transport: {
8
8
  refetch: typeof refetch;
9
9
  is_json: typeof is_json;
10
10
  submit: typeof submit;
11
11
  };
12
- export default http;
13
- //# sourceMappingURL=http.d.ts.map
12
+ export default transport;
13
+ //# sourceMappingURL=transport.d.ts.map
@@ -1,4 +1,4 @@
1
- import { MIME } from "@rcompat/http";
1
+ import http from "@rcompat/http";
2
2
  const sameorigin = (url) => url.origin === globalThis.location.origin;
3
3
  const get_location = (response, base) => {
4
4
  if (response.type === "opaqueredirect")
@@ -7,6 +7,8 @@ const get_location = (response, base) => {
7
7
  return location !== null ? new URL(location, base) : null;
8
8
  };
9
9
  async function refetch(input, init = {}, max_hops = 5) {
10
+ console.log("location.href", globalThis.location.href);
11
+ console.log("input", input.toString());
10
12
  let url = new URL(input.toString(), globalThis.location.href);
11
13
  const method = (init.method ?? "GET").toUpperCase();
12
14
  let hops = 0;
@@ -36,7 +38,7 @@ async function refetch(input, init = {}, max_hops = 5) {
36
38
  }
37
39
  function is_json(response) {
38
40
  const raw = response.headers.get("content-type") ?? "";
39
- return raw.split(";")[0].trim() === MIME.APPLICATION_JSON;
41
+ return raw.split(";")[0].trim() === http.MIME.APPLICATION_JSON;
40
42
  }
41
43
  async function submit(pathname, body, method) {
42
44
  const { requested, response } = await refetch(pathname, { body, method });
@@ -48,10 +50,6 @@ async function submit(pathname, body, method) {
48
50
  }
49
51
  return response;
50
52
  }
51
- const http = {
52
- refetch,
53
- is_json,
54
- submit,
55
- };
56
- export default http;
57
- //# sourceMappingURL=http.js.map
53
+ const transport = { refetch, is_json, submit };
54
+ export default transport;
55
+ //# sourceMappingURL=transport.js.map
@@ -3,6 +3,7 @@ import type Module from "#Module";
3
3
  import type { Dict } from "@rcompat/type";
4
4
  import type { ObjectType, Parsed } from "pema";
5
5
  declare const _default: ObjectType<import("pema").NormalizeSchemaObject<{
6
+ readonly conditions: import("pema").DefaultType<import("pema").ArrayType<import("pema").StringType>, string[]>;
6
7
  readonly http: {
7
8
  readonly csp: import("pema").OptionalType<import("pema").RecordType<import("pema").StringType, import("pema").ArrayType<import("pema").StringType>>>;
8
9
  readonly headers: import("pema").OptionalType<import("pema").RecordType<import("pema").StringType, import("pema").StringType>>;
@@ -24,10 +25,10 @@ declare const _default: ObjectType<import("pema").NormalizeSchemaObject<{
24
25
  readonly db: {
25
26
  readonly migrations: import("pema").OptionalType<ObjectType<{
26
27
  table: import("pema").StringType;
27
- db: import("pema").PureType<DB, "PureType">;
28
+ db: import("pema").PureType<DB<unknown>, "PureType">;
28
29
  }, {
29
30
  table: string;
30
- db: DB;
31
+ db: DB<unknown>;
31
32
  }>>;
32
33
  };
33
34
  readonly env: {
@@ -39,12 +40,8 @@ declare const _default: ObjectType<import("pema").NormalizeSchemaObject<{
39
40
  name: import("pema").StringType;
40
41
  setup: import("pema").FunctionType;
41
42
  }, Module>>, Module[]>;
42
- readonly request: {
43
- readonly body: {
44
- readonly parse: import("pema").DefaultType<import("pema").BooleanType, true>;
45
- };
46
- };
47
43
  }>, {
44
+ conditions: string[];
48
45
  http: {
49
46
  csp: Record<string, string[]> | undefined;
50
47
  headers: Record<string, string> | undefined;
@@ -66,7 +63,7 @@ declare const _default: ObjectType<import("pema").NormalizeSchemaObject<{
66
63
  db: {
67
64
  migrations: {
68
65
  table: string;
69
- db: DB;
66
+ db: DB<unknown>;
70
67
  } | undefined;
71
68
  };
72
69
  env: {
@@ -75,11 +72,6 @@ declare const _default: ObjectType<import("pema").NormalizeSchemaObject<{
75
72
  }> | undefined;
76
73
  };
77
74
  modules: Module[];
78
- request: {
79
- body: {
80
- parse: boolean;
81
- };
82
- };
83
75
  }>;
84
76
  export default _default;
85
77
  //# sourceMappingURL=schema.d.ts.map
@@ -1,6 +1,7 @@
1
1
  import fs from "@rcompat/fs";
2
2
  import p from "pema";
3
3
  export default p({
4
+ conditions: p.array(p.string).unique().default([]),
4
5
  http: {
5
6
  csp: p.dict(p.array(p.string)).optional(),
6
7
  headers: p.dict().optional(),
@@ -34,10 +35,5 @@ export default p({
34
35
  }).shape())
35
36
  .uniqueBy(member => member.name)
36
37
  .default([]),
37
- request: {
38
- body: {
39
- parse: p.boolean.default(true),
40
- },
41
- },
42
38
  });
43
39
  //# sourceMappingURL=schema.js.map
@@ -21,9 +21,10 @@ export type Schema = {
21
21
  introspect(name: string, pk?: PK): MaybePromise<MaybeTable>;
22
22
  alter(name: string, diff: SchemaDiff): MaybePromise<void>;
23
23
  };
24
- export default interface DB {
24
+ export default interface DB<Client = unknown> {
25
25
  schema: Schema;
26
26
  close(): MaybePromise<void>;
27
+ readonly client: Client;
27
28
  create<O extends Dict>(as: As, record: Dict): MaybePromise<O>;
28
29
  read(as: As, args: {
29
30
  count: true;
@@ -34,6 +35,7 @@ export default interface DB {
34
35
  where: Dict;
35
36
  fields?: string[];
36
37
  limit?: number;
38
+ offset?: number;
37
39
  sort?: Sort;
38
40
  with?: With;
39
41
  }): MaybePromise<Dict[]>;
@@ -4,9 +4,11 @@ import type { Schema } from "#db/DB";
4
4
  import type DataDict from "#db/DataDict";
5
5
  import type Sort from "#db/Sort";
6
6
  import type With from "#db/With";
7
- import type { Dict, MaybePromise } from "@rcompat/type";
8
- export default class MemoryDB implements DB {
7
+ import type { Dict, MaybePromise, PartialDict } from "@rcompat/type";
8
+ type Tables = PartialDict<Dict[]>;
9
+ export default class MemoryDB implements DB<Tables> {
9
10
  #private;
11
+ get client(): Tables;
10
12
  get schema(): Schema;
11
13
  close(): void;
12
14
  create<O extends Dict>(as: As, record: Dict): MaybePromise<O>;
@@ -30,4 +32,5 @@ export default class MemoryDB implements DB {
30
32
  where: DataDict;
31
33
  }): number;
32
34
  }
35
+ export {};
33
36
  //# sourceMappingURL=MemoryDB.d.ts.map