primate 0.15.5 → 0.15.7

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.15.5",
3
+ "version": "0.15.7",
4
4
  "description": "Expressive, minimal and extensible framework for JavaScript",
5
5
  "homepage": "https://primatejs.com",
6
6
  "bugs": "https://github.com/primatejs/primate/issues",
@@ -18,7 +18,7 @@
18
18
  "lint": "npx eslint ."
19
19
  },
20
20
  "dependencies": {
21
- "runtime-compat": "^0.15.0"
21
+ "runtime-compat": "^0.15.1"
22
22
  },
23
23
  "devDependencies": {
24
24
  "maximin": "^0.1.2"
package/src/config.js CHANGED
@@ -1,110 +1,5 @@
1
- import crypto from "runtime-compat/crypto";
2
- import {is} from "runtime-compat/dyndef";
3
- import {File, Path} from "runtime-compat/fs";
4
- import cache from "./cache.js";
5
- import extend from "./extend.js";
6
- import defaults from "./primate.config.js";
7
- import {colors, print, default as Logger} from "./Logger.js";
8
- import * as handlers from "./handlers/exports.js";
1
+ const filter = (key, array) => array?.flatMap(m => m[key] ?? []) ?? [];
9
2
 
10
- const qualify = (root, paths) =>
11
- Object.keys(paths).reduce((sofar, key) => {
12
- const value = paths[key];
13
- sofar[key] = typeof value === "string"
14
- ? new Path(root, value)
15
- : qualify(`${root}/${key}`, value);
16
- return sofar;
17
- }, {});
18
-
19
- const getConfig = async (root, filename) => {
20
- try {
21
- return extend(defaults, (await import(root.join(filename))).default);
22
- } catch (error) {
23
- return defaults;
24
- }
25
- };
26
-
27
- const getRoot = async () => {
28
- try {
29
- // use module root if possible
30
- return await Path.root();
31
- } catch (error) {
32
- // fall back to current directory
33
- return Path.resolve();
34
- }
35
- };
36
-
37
- const index = async env => {
38
- const name = "index.html";
39
- try {
40
- // user-provided file
41
- return await File.read(`${env.paths.static.join(name)}`);
42
- } catch (error) {
43
- // fallback
44
- return new Path(import.meta.url).directory.join(name).file.read();
45
- }
46
- };
47
-
48
- const hash = async (string, algorithm = "sha-384") => {
49
- const encoder = new TextEncoder();
50
- const bytes = await crypto.subtle.digest(algorithm, encoder.encode(string));
51
- const algo = algorithm.replace("-", () => "");
52
- return `${algo}-${btoa(String.fromCharCode(...new Uint8Array(bytes)))}`;
53
- };
54
-
55
- export default async (filename = "primate.config.js") => {
56
- is(filename).string();
57
- const root = await getRoot();
58
- const config = await getConfig(root, filename);
59
-
60
- const {name, version} = JSON.parse(await new Path(import.meta.url)
61
- .directory.directory.join("package.json").file.read());
62
-
63
- const env = {
64
- ...config,
65
- name, version,
66
- resources: [],
67
- entrypoints: [],
68
- paths: qualify(root, config.paths),
69
- root,
70
- log: new Logger(config.logger),
71
- register: (name, handler) => {
72
- env.handlers[name] = handler;
73
- },
74
- handlers: {...handlers},
75
- render: async ({body = "", head = ""} = {}) => {
76
- const html = await index(env);
77
- const heads = env.resources.map(({src, code, type, inline, integrity}) => {
78
- const tag = type === "style" ? "link" : "script";
79
- const pre = type === "style"
80
- ? `<${tag} rel="stylesheet" integrity="${integrity}"`
81
- : `<${tag} type="${type}" integrity="${integrity}"`;
82
- const middle = type === "style"
83
- ? ` href="${src}">`
84
- : ` src="${src}">`;
85
- const post = type === "style" ? "" : `</${tag}>`;
86
- return inline ? `${pre}>${code}${post}` : `${pre}${middle}${post}`;
87
- }).join("\n");
88
- return html
89
- .replace("%body%", () => body)
90
- .replace("%head%", () => `${head}${heads}`);
91
- },
92
- publish: async ({src, code, type = "", inline = false}) => {
93
- const integrity = await hash(code);
94
- env.resources.push({src, code, type, inline, integrity});
95
- return integrity;
96
- },
97
- bootstrap: ({type, code}) => {
98
- env.entrypoints.push({type, code});
99
- },
100
- };
101
- print(colors.blue(colors.bold(name)), colors.blue(version), "");
102
- const {modules} = config;
103
- // modules may load other modules
104
- const loads = await Promise.all(modules
105
- .filter(module => module.load !== undefined)
106
- .map(module => module.load()));
107
-
108
- return cache("config", filename, () => ({...env,
109
- modules: modules.concat(loads.flat())}));
110
- };
3
+ export default async env =>
4
+ [...filter("config", env.modules), _ => _].reduceRight((acc, handler) =>
5
+ input => handler(input, acc))(env);
package/src/env.js ADDED
@@ -0,0 +1,120 @@
1
+ import crypto from "runtime-compat/crypto";
2
+ import {is} from "runtime-compat/dyndef";
3
+ import {File, Path} from "runtime-compat/fs";
4
+ import cache from "./cache.js";
5
+ import extend from "./extend.js";
6
+ import defaults from "./primate.config.js";
7
+ import {colors, print, default as Logger} from "./Logger.js";
8
+ import * as handlers from "./handlers/exports.js";
9
+
10
+ const qualify = (root, paths) =>
11
+ Object.keys(paths).reduce((sofar, key) => {
12
+ const value = paths[key];
13
+ sofar[key] = typeof value === "string"
14
+ ? new Path(root, value)
15
+ : qualify(`${root}/${key}`, value);
16
+ return sofar;
17
+ }, {});
18
+
19
+ const getConfig = async (root, filename) => {
20
+ try {
21
+ return extend(defaults, (await import(root.join(filename))).default);
22
+ } catch (error) {
23
+ return defaults;
24
+ }
25
+ };
26
+
27
+ const getRoot = async () => {
28
+ try {
29
+ // use module root if possible
30
+ return await Path.root();
31
+ } catch (error) {
32
+ // fall back to current directory
33
+ return Path.resolve();
34
+ }
35
+ };
36
+
37
+ const index = async env => {
38
+ const name = "index.html";
39
+ try {
40
+ // user-provided file
41
+ return await File.read(`${env.paths.static.join(name)}`);
42
+ } catch (error) {
43
+ // fallback
44
+ return new Path(import.meta.url).directory.join(name).file.read();
45
+ }
46
+ };
47
+
48
+ const hash = async (string, algorithm = "sha-384") => {
49
+ const encoder = new TextEncoder();
50
+ const bytes = await crypto.subtle.digest(algorithm, encoder.encode(string));
51
+ const algo = algorithm.replace("-", () => "");
52
+ return `${algo}-${btoa(String.fromCharCode(...new Uint8Array(bytes)))}`;
53
+ };
54
+
55
+ export default async (filename = "primate.config.js") => {
56
+ is(filename).string();
57
+ const root = await getRoot();
58
+ const config = await getConfig(root, filename);
59
+
60
+ const {name, version} = JSON.parse(await new Path(import.meta.url)
61
+ .directory.directory.join("package.json").file.read());
62
+
63
+ // if ssl activated, resolve key and cert early
64
+ if (config.http.ssl) {
65
+ config.http.ssl.key = root.join(config.http.ssl.key);
66
+ config.http.ssl.cert = root.join(config.http.ssl.cert);
67
+ config.secure = true;
68
+ }
69
+
70
+ const env = {
71
+ ...config,
72
+ name, version,
73
+ resources: [],
74
+ entrypoints: [],
75
+ paths: qualify(root, config.paths),
76
+ root,
77
+ log: new Logger(config.logger),
78
+ register: (name, handler) => {
79
+ env.handlers[name] = handler;
80
+ },
81
+ handlers: {...handlers},
82
+ render: async ({body = "", head = ""} = {}) => {
83
+ const html = await index(env);
84
+ const heads = env.resources.map(({src, code, type, inline, integrity}) => {
85
+ const tag = type === "style" ? "link" : "script";
86
+ const pre = type === "style"
87
+ ? `<${tag} rel="stylesheet" integrity="${integrity}"`
88
+ : `<${tag} type="${type}" integrity="${integrity}"`;
89
+ const middle = type === "style"
90
+ ? ` href="${src}">`
91
+ : ` src="${src}">`;
92
+ const post = type === "style" ? "" : `</${tag}>`;
93
+ return inline ? `${pre}>${code}${post}` : `${pre}${middle}${post}`;
94
+ }).join("\n");
95
+ return html
96
+ .replace("%body%", () => body)
97
+ .replace("%head%", () => `${head}${heads}`);
98
+ },
99
+ publish: async ({src, code, type = "", inline = false}) => {
100
+ const integrity = await hash(code);
101
+ env.resources.push({src, code, type, inline, integrity});
102
+ return integrity;
103
+ },
104
+ bootstrap: ({type, code}) => {
105
+ env.entrypoints.push({type, code});
106
+ },
107
+ };
108
+ print(colors.blue(colors.bold(name)), colors.blue(version), "");
109
+ const type = env.secure ? "https" : "http";
110
+ const address = `${type}://${config.http.host}:${config.http.port}`;
111
+ print(colors.gray(`at ${address}`), "\n");
112
+ const {modules} = config;
113
+ // modules may load other modules
114
+ const loads = await Promise.all(modules
115
+ .filter(module => module.load !== undefined)
116
+ .map(module => module.load()));
117
+
118
+ return cache("config", filename, () => ({...env,
119
+ modules: modules.concat(loads.flat())}));
120
+ };
package/src/run.js CHANGED
@@ -1,4 +1,4 @@
1
- import config from "./config.js";
1
+ import env from "./env.js";
2
2
  import command from "./commands/exports.js";
3
3
 
4
- export default async name => command(name)(await config());
4
+ export default async name => command(name)(await env());
package/src/serve.js CHANGED
@@ -5,7 +5,6 @@ import mimes from "./mimes.js";
5
5
  import {http404} from "./handlers/http.js";
6
6
  import {isResponse} from "./duck.js";
7
7
  import respond from "./respond.js";
8
- import {colors, print} from "./Logger.js";
9
8
 
10
9
  const regex = /\.([a-z1-9]*)$/u;
11
10
  const mime = filename => mimes[filename.match(regex)[1]] ?? mimes.binary;
@@ -136,6 +135,4 @@ export default env => {
136
135
 
137
136
  return handlers({original: request, pathname: pathname + search, body});
138
137
  }, http);
139
-
140
- print(colors.gray(`at http://${http.host}:${http.port}`), "\n");
141
138
  };
package/src/start.js CHANGED
@@ -4,8 +4,11 @@ import publish from "./publish.js";
4
4
  import bundle from "./bundle.js";
5
5
  import route from "./route.js";
6
6
  import serve from "./serve.js";
7
+ import config from "./config.js";
7
8
 
8
9
  export default async (env, operations = {}) => {
10
+ // read/write configuration
11
+ await config(env);
9
12
  // register handlers
10
13
  await register(env);
11
14
  // compile server-side code