primate 0.27.5 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "primate",
3
- "version": "0.27.5",
3
+ "version": "0.28.0",
4
4
  "description": "Polymorphic development platform",
5
5
  "homepage": "https://primatejs.com",
6
6
  "bugs": "https://github.com/primatejs/primate/issues",
@@ -9,7 +9,8 @@
9
9
  "src/**/*.js",
10
10
  "src/errors.json",
11
11
  "src/defaults/*.html",
12
- "!src/**/*.spec.js"
12
+ "!src/**/*.spec.js",
13
+ "types/*.ts"
13
14
  ],
14
15
  "bin": "src/bin.js",
15
16
  "repository": {
@@ -18,11 +19,12 @@
18
19
  "directory": "packages/primate"
19
20
  },
20
21
  "dependencies": {
21
- "rcompat": "^0.5.1"
22
+ "rcompat": "^0.7.2"
22
23
  },
23
24
  "engines": {
24
25
  "node": ">=18"
25
26
  },
26
27
  "type": "module",
28
+ "types": "./types/index.d.ts",
27
29
  "exports": "./src/exports.js"
28
30
  }
package/src/app.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import crypto from "rcompat/crypto";
2
2
  import { tryreturn } from "rcompat/async";
3
- import { Path } from "rcompat/fs";
3
+ import { File } from "rcompat/fs";
4
4
  import { is } from "rcompat/invariant";
5
5
  import { transform, valmap, to } from "rcompat/object";
6
6
  import { globify } from "rcompat/string";
@@ -15,8 +15,8 @@ const { DoubleFileExtension } = errors;
15
15
 
16
16
  // use user-provided file or fall back to default
17
17
  const index = (base, page, fallback) =>
18
- tryreturn(_ => Path.read(`${base.join(page)}`))
19
- .orelse(_ => Path.read(`${base.join(fallback)}`));
18
+ tryreturn(_ => File.text(`${base.join(page)}`))
19
+ .orelse(_ => File.text(`${base.join(fallback)}`));
20
20
 
21
21
  const encoder = new TextEncoder();
22
22
 
@@ -51,7 +51,7 @@ const render_head = (assets, head) =>
51
51
  : tags.script({ inline, code, type, integrity, src }),
52
52
  ).join("\n").concat("\n", head ?? "");
53
53
 
54
- const { name, version } = await new Path(import.meta.url).up(2)
54
+ const { name, version } = await new File(import.meta.url).up(2)
55
55
  .join(runtime.manifest).json();
56
56
 
57
57
  export default async (log, root, config) => {
@@ -100,7 +100,7 @@ export default async (log, root, config) => {
100
100
 
101
101
  await Promise.all((await source.collect(filter)).map(async path => {
102
102
  const debased = path.debase(this.root).path.slice(1);
103
- const filename = new Path(directory).join(path.debase(source));
103
+ const filename = File.join(directory, path.debase(source));
104
104
  const target = await target_base.join(filename.debase(directory));
105
105
  await target.directory.create();
106
106
  await (regexs.some(regex => regex.test(debased))
@@ -177,7 +177,7 @@ export default async (log, root, config) => {
177
177
  }
178
178
  if (inline || type === "style") {
179
179
  this.assets.push({
180
- src: new Path(http.static.root).join(src ?? "").path,
180
+ src: File.join(http.static.root, src ?? "").path,
181
181
  code: inline ? code : "",
182
182
  type,
183
183
  inline,
@@ -203,7 +203,7 @@ export default async (log, root, config) => {
203
203
 
204
204
  const parts = module.split("/");
205
205
  const path = [this.library, ...parts];
206
- const pkg = await Path.resolve().join(...path, this.manifest).json();
206
+ const pkg = await File.resolve().join(...path, this.manifest).json();
207
207
  const exports = pkg.exports === undefined
208
208
  ? { [module]: `/${module}/${pkg.main}` }
209
209
  : transform(pkg.exports, entry => entry
@@ -220,11 +220,11 @@ export default async (log, root, config) => {
220
220
  ?? value.default?.replace(".", `./${module}`)
221
221
  ?? value.import?.replace(".", `./${module}`),
222
222
  ]));
223
- const dependency = Path.resolve().join(...path);
224
- const target = new Path(this.runpath(client), this.library, ...parts);
223
+ const dependency = File.resolve().join(...path);
224
+ const target = File.join(this.runpath(client), this.library, ...parts);
225
225
  await dependency.copy(target);
226
226
  this.importmaps = {
227
- ...valmap(exports, value => new Path(root, this.library, value).path),
227
+ ...valmap(exports, value => File.join(root, this.library, value).path),
228
228
  ...this.importmaps };
229
229
  },
230
230
  };
package/src/cwd.js CHANGED
@@ -1,3 +1,3 @@
1
- import { Path } from "rcompat/fs";
1
+ import { File } from "rcompat/fs";
2
2
 
3
- export default (meta, up = 1) => new Path(meta.url).up(up);
3
+ export default (meta, up = 1) => new File(meta.url).up(up);
package/src/errors.js CHANGED
@@ -1,7 +1,7 @@
1
- import { Path } from "rcompat/fs";
1
+ import { File } from "rcompat/fs";
2
2
  import Logger from "./Logger.js";
3
3
 
4
- const json = await new Path(import.meta.url).up(1).join("errors.json").json();
4
+ const json = await new File(import.meta.url).up(1).join("errors.json").json();
5
5
 
6
6
  const errors = Logger.err(json.errors, json.module);
7
7
 
@@ -1,4 +1,4 @@
1
- import { Path } from "rcompat/fs";
1
+ import { File } from "rcompat/fs";
2
2
 
3
3
  export default async (app, type, post = () => undefined) => {
4
4
  const { config } = app;
@@ -14,7 +14,7 @@ export default async (app, type, post = () => undefined) => {
14
14
  .map(async include => {
15
15
  const path = app.root.join(include);
16
16
  if (await path.exists()) {
17
- const target = Path.join(type, include);
17
+ const target = File.join(type, include);
18
18
  await app.stage(path, target);
19
19
  await post(target);
20
20
  }
@@ -5,21 +5,17 @@ import errors from "../errors.js";
5
5
 
6
6
  const deslash = url => url.replaceAll(/(?<!http:)\/{2,}/gu, _ => "/");
7
7
 
8
- const parse_body = (body, headers, url) =>
9
- tryreturn(async _ => {
10
- console.log("HHHH");
11
- return Body.parse(body, headers.get("content-type")) ?? {};
12
- }).orelse(error => errors.MismatchedBody.throw(url.pathname, error.message));
8
+ const parse_body = (request, url) =>
9
+ tryreturn(async _ => await Body.parse(request) ?? {})
10
+ .orelse(error => errors.MismatchedBody.throw(url.pathname, error.message));
13
11
 
14
12
  export default dispatch => async original => {
15
13
  const { headers } = original;
16
14
  const url = new URL(deslash(globalThis.decodeURIComponent(original.url)));
17
15
  const cookies = headers.get("cookie");
18
- const body = await parse_body(original.body, headers, url);
16
+ const body = await parse_body(original, url);
19
17
 
20
- return { original, url, body,
21
- async_function: async () => "1",
22
- ...valmap({
18
+ return { original, url, body, ...valmap({
23
19
  query: [from(url.searchParams), url.search],
24
20
  headers: [from(headers), headers, false],
25
21
  cookies: [from(cookies?.split(";").map(cookie =>
@@ -1,4 +1,4 @@
1
- import { Path } from "rcompat/fs";
1
+ import { File } from "rcompat/fs";
2
2
  import { cascade } from "rcompat/async";
3
3
  import { stringify } from "rcompat/object";
4
4
 
@@ -7,7 +7,7 @@ const post = async app => {
7
7
 
8
8
  {
9
9
  // after hook, publish a zero assumptions app.js (no css imports)
10
- const src = new Path(root, app.config.build.index);
10
+ const src = File.join(root, app.config.build.index);
11
11
 
12
12
  await app.publish({
13
13
  code: app.exports.filter(({ type }) => type === "script")
@@ -1,4 +1,4 @@
1
- import { Path } from "rcompat/fs";
1
+ import { File } from "rcompat/fs";
2
2
  import { cascade } from "rcompat/async";
3
3
  import cwd from "../cwd.js";
4
4
  import copy_includes from "./copy_includes.js";
@@ -17,7 +17,7 @@ const pre = async app => {
17
17
  if (await path.components.exists()) {
18
18
  // copy .js files from components to build/client/components, since
19
19
  // frontend frameworks handle non-js files
20
- const target = Path.join(client, components);
20
+ const target = File.join(client, components);
21
21
  await app.stage(path.components, target, /^.*.js$/u);
22
22
  }
23
23
 
@@ -29,13 +29,13 @@ const post = async app => {
29
29
 
30
30
  if (await path.static.exists()) {
31
31
  // copy static files to build/server/static
32
- await app.stage(path.static, new Path(location.server, location.static));
32
+ await app.stage(path.static, File.join(location.server, location.static));
33
33
 
34
34
  // copy static files to build/client/static
35
- await app.stage(path.static, new Path(location.client, location.static));
35
+ await app.stage(path.static, File.join(location.client, location.static));
36
36
 
37
37
  // publish JavaScript and CSS files
38
- const imports = await Path.collect(path.static, /\.(?:js|css)$/u);
38
+ const imports = await File.collect(path.static, /\.(?:js|css)$/u);
39
39
  await Promise.all(imports.map(async file => {
40
40
  const code = await file.text();
41
41
  const src = file.debase(path.static);
@@ -54,7 +54,7 @@ const post = async app => {
54
54
  const client = app.runpath(location.client);
55
55
  await copy_includes(app, location.client, async to =>
56
56
  Promise.all((await to.collect(/\.js$/u)).map(async script => {
57
- const src = new Path(root, script.path.replace(client, _ => ""));
57
+ const src = File.join(root, script.path.replace(client, _ => ""));
58
58
  await app.publish({ src, code: await script.text(), type: "module" });
59
59
  })),
60
60
  );
@@ -15,10 +15,10 @@ const is_object = value => is_non_null_object(value)
15
15
  ? json(value) : is_text(value);
16
16
  const is_response = value => is_response_duck(value)
17
17
  ? _ => value : is_object(value);
18
- const isStream = value => value instanceof ReadableStream
18
+ const is_stream = value => value instanceof ReadableStream
19
19
  ? stream(value) : is_response(value);
20
20
  const is_blob = value => value instanceof Blob
21
- ? stream(value) : isStream(value);
21
+ ? stream(value.stream()) : is_stream(value);
22
22
  const is_URL = value => value instanceof URL
23
23
  ? redirect(value.href) : is_blob(value);
24
24
  const guess = value => is_URL(value);
@@ -1,4 +1,4 @@
1
- import { Path } from "rcompat/fs";
1
+ import { File } from "rcompat/fs";
2
2
  import { identity } from "rcompat/function";
3
3
  import errors from "../errors.js";
4
4
 
@@ -17,13 +17,13 @@ export default async ({
17
17
  warn = true,
18
18
  } = {}) => {
19
19
  const objects = directory === undefined ? [] : await Promise.all(
20
- (await Path.collect(directory, /^.*.js$/u, { recursive }))
20
+ (await File.collect(directory, /^.*.js$/u, { recursive }))
21
21
  .filter(filter)
22
22
  .map(async path => [
23
23
  `${path}`.replace(directory, _ => "").slice(1, -ending.length),
24
- (await import(path)),
24
+ await import(path),
25
25
  ]));
26
- warn && await Path.exists(directory) && empty(log)(objects, name, directory);
26
+ warn && await directory.exists() && empty(log)(objects, name, directory);
27
27
 
28
28
  return objects;
29
29
  };
@@ -1,4 +1,4 @@
1
- import { Path } from "rcompat/fs";
1
+ import { File } from "rcompat/fs";
2
2
  import errors from "../../errors.js";
3
3
  import to_sorted from "../../to_sorted.js";
4
4
 
@@ -10,7 +10,7 @@ export default type => async (log, directory, load) => {
10
10
  .map(([name, object]) => [name.replace(replace, () => ""), object]),
11
11
  ([a], [b]) => a.length - b.length);
12
12
 
13
- const resolve = name => new Path(directory, name, `+${type}.js`);
13
+ const resolve = name => File.join(directory, name, `+${type}.js`);
14
14
  objects.some(([name, value]) => typeof value.default !== "function"
15
15
  && errors.InvalidDefaultExport.throw(resolve(name)));
16
16
 
@@ -1,4 +1,4 @@
1
- import { Path } from "rcompat/fs";
1
+ import { File } from "rcompat/fs";
2
2
  import { is } from "rcompat/invariant";
3
3
  import { tryreturn } from "rcompat/sync";
4
4
  import errors from "../errors.js";
@@ -10,7 +10,7 @@ export default async (log, directory, load = fs) => {
10
10
  const types = (await load({ log, directory, name: "types", filter }))
11
11
  .map(([name, type]) => [name, type.default]);
12
12
 
13
- const resolve = name => new Path(directory, name);
13
+ const resolve = name => File.join(directory, name);
14
14
  types.every(([name, type]) => tryreturn(_ => {
15
15
  is(type).object();
16
16
  is(type.base).string();
package/src/run.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { tryreturn } from "rcompat/async";
2
- import { Path } from "rcompat/fs";
2
+ import { File } from "rcompat/fs";
3
3
  import { extend } from "rcompat/object";
4
4
  import app from "./app.js";
5
5
  import { default as Logger, bye } from "./Logger.js";
@@ -28,7 +28,7 @@ const get_config = async root => {
28
28
 
29
29
  export default async name => tryreturn(async _ => {
30
30
  // use module root if possible, fall back to current directory
31
- const root = await tryreturn(_ => Path.root()).orelse(_ => Path.resolve());
31
+ const root = await tryreturn(_ => File.root()).orelse(_ => File.resolve());
32
32
  const config = await get_config(root);
33
33
  logger = new Logger(config.logger);
34
34
  await command(name)(await app(logger, root, config));
@@ -0,0 +1,64 @@
1
+ declare module "primate" {
2
+ type App = any;
3
+
4
+ interface MinOptions {
5
+ status: number,
6
+ }
7
+
8
+ interface ErrorOptions extends MinOptions {
9
+ page: string,
10
+ }
11
+
12
+ interface Options extends ErrorOptions {
13
+ placeholders: {},
14
+ headers: Headers | {},
15
+ }
16
+
17
+ type Dispatcher = {
18
+ get(property: string): string,
19
+ };
20
+
21
+ type RequestFacade = {
22
+ body: {}
23
+ path: Dispatcher,
24
+ query: Dispatcher,
25
+ cookies: Dispatcher,
26
+ headers: Dispatcher,
27
+ original: Request,
28
+ };
29
+
30
+ type ResponseFn = (app: App, ...rest: any) => Response;
31
+ type ResponseFacade =
32
+ string
33
+ | object
34
+ | URL
35
+ | Blob
36
+ | ReadableStream
37
+ | Response
38
+ | ResponseFn;
39
+
40
+ type RouteFunction = (request?: RequestFacade) => ResponseFacade;
41
+
42
+ type Streamable = ReadableStream | Blob;
43
+
44
+ export type Route = {
45
+ get?: RouteFunction,
46
+ post?: RouteFunction,
47
+ put?: RouteFunction,
48
+ delete?: RouteFunction,
49
+ };
50
+
51
+ export function text(body: string, options?: MinOptions): ResponseFn;
52
+
53
+ export function json(body: {}, options?: MinOptions): ResponseFn;
54
+
55
+ export function stream(body: Streamable, options?: MinOptions): ResponseFn;
56
+
57
+ export function redirect(location: string, options?: MinOptions): ResponseFn;
58
+
59
+ export function html(name: string, options?: MinOptions): ResponseFn;
60
+
61
+ export function view(name: string, props: {}, options?: Options): ResponseFn;
62
+
63
+ export function error(body: string, options?: ErrorOptions): ResponseFn;
64
+ }