primate 0.10.0 → 0.12.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/LICENSE +0 -2
- package/README.md +178 -68
- package/exports.js +1 -3
- package/module.json +4 -4
- package/package.json +9 -9
- package/readme/extensions/handlers/htmx/user-index.html +4 -0
- package/readme/extensions/handlers/htmx/user.js +23 -0
- package/readme/extensions/handlers/redirect/user.js +6 -0
- package/readme/extensions/modules/configure.js +3 -0
- package/readme/extensions/modules/domains/configure.js +5 -0
- package/readme/{domains → extensions/modules/domains}/fields.js +3 -4
- package/readme/{domains → extensions/modules/domains}/predicates.js +3 -3
- package/readme/{domains → extensions/modules/domains}/short-field-notation.js +3 -3
- package/readme/routing/accessing-the-request-body.js +3 -0
- package/readme/routing/basic.js +2 -5
- package/readme/serving-content/response.js +6 -0
- package/readme/serving-content/streams.js +1 -1
- package/readme/template.md +226 -0
- package/scripts/docs.sh +7 -0
- package/src/bin.js +2 -0
- package/src/bundle.js +3 -4
- package/src/config.js +48 -0
- package/src/duck.js +4 -0
- package/src/extend.spec.js +19 -27
- package/src/handlers/http404.js +2 -5
- package/src/handlers/json.js +2 -5
- package/src/handlers/stream.js +2 -5
- package/src/handlers/text.js +2 -5
- package/src/http-statuses.js +5 -0
- package/src/log.js +8 -1
- package/src/mimes.js +12 -0
- package/src/{preset/primate.js → primate.config.js} +1 -0
- package/src/respond.js +24 -0
- package/src/route.js +6 -20
- package/src/run.js +7 -16
- package/src/serve.js +35 -25
- package/README.template.md +0 -149
- package/bin/primate.js +0 -5
- package/src/conf.js +0 -27
- package/src/http-statuses.json +0 -5
- package/src/mimes.json +0 -12
- package/src/preset/stores/default.js +0 -2
- /package/readme/{serving-content → extensions/handlers/html}/user-index.html +0 -0
- /package/readme/{serving-content/html.js → extensions/handlers/html/user.js} +0 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# Primate
|
|
2
|
+
|
|
3
|
+
Expressive, minimal and extensible framework for JavaScript.
|
|
4
|
+
|
|
5
|
+
## Getting started
|
|
6
|
+
|
|
7
|
+
Create a route in `routes/hello.js`
|
|
8
|
+
|
|
9
|
+
```js
|
|
10
|
+
// getting-started/hello.js
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Add `{"type": "module"}` to your `package.json` and run `npx -y primate@latest`.
|
|
14
|
+
|
|
15
|
+
## Table of Contents
|
|
16
|
+
|
|
17
|
+
- [Serving content](#serving-content)
|
|
18
|
+
- [Plain text](#plain-text)
|
|
19
|
+
- [JSON](#json)
|
|
20
|
+
- [Streams](#streams)
|
|
21
|
+
- [Response](#response)
|
|
22
|
+
- [Routing](#routing)
|
|
23
|
+
- [Basic](#basic)
|
|
24
|
+
- [The request object](#the-request-object)
|
|
25
|
+
- [Accessing the request body](#accessing-the-request-body)
|
|
26
|
+
- [Regular expressions](#regular-expressions)
|
|
27
|
+
- [Named groups](#named-groups)
|
|
28
|
+
- [Aliasing](#aliasing)
|
|
29
|
+
- [Sharing logic across requests](#sharing-logic-across-requests)
|
|
30
|
+
- [Extensions](#extensions)
|
|
31
|
+
- [Handlers](#handlers)
|
|
32
|
+
- [HTML](#html)
|
|
33
|
+
- [Redirect](#redirect)
|
|
34
|
+
- [HTMX](#htmx)
|
|
35
|
+
- [Modules](#modules)
|
|
36
|
+
- [Data persistance](#data-persistance)
|
|
37
|
+
|
|
38
|
+
## Serving content
|
|
39
|
+
|
|
40
|
+
Create a file in `routes` that exports a default function.
|
|
41
|
+
|
|
42
|
+
### Plain text
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
// serving-content/plain-text.js
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### JSON
|
|
49
|
+
|
|
50
|
+
```js
|
|
51
|
+
// serving-content/json.js
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Streams
|
|
55
|
+
|
|
56
|
+
```js
|
|
57
|
+
// serving-content/streams.js
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Response
|
|
61
|
+
|
|
62
|
+
```js
|
|
63
|
+
// serving-content/response.js
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Routing
|
|
67
|
+
|
|
68
|
+
Routes map requests to responses. They are loaded from `routes`.
|
|
69
|
+
|
|
70
|
+
### Basic
|
|
71
|
+
|
|
72
|
+
```js
|
|
73
|
+
// routing/basic.js
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### The request object
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
// routing/the-request-object.js
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Accessing the request body
|
|
83
|
+
|
|
84
|
+
For requests containing a body, Primate will attempt to parse the body according
|
|
85
|
+
to the content type sent along the request. Currently supported are
|
|
86
|
+
`application/x-www-form-urlencoded` (typically for form submission) and
|
|
87
|
+
`application/json`.
|
|
88
|
+
|
|
89
|
+
```js
|
|
90
|
+
// routing/accessing-the-request-body.js
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Regular expressions
|
|
94
|
+
|
|
95
|
+
```js
|
|
96
|
+
// routing/regular-expressions.js
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Named groups
|
|
100
|
+
|
|
101
|
+
```js
|
|
102
|
+
// routing/named-groups.js
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Aliasing
|
|
106
|
+
|
|
107
|
+
```js
|
|
108
|
+
// routing/aliasing.js
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Sharing logic across requests
|
|
112
|
+
|
|
113
|
+
```js
|
|
114
|
+
// routing/sharing-logic-across-requests.js
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Extensions
|
|
118
|
+
|
|
119
|
+
There are two ways to extend Primate's core functionality. Handlers are used
|
|
120
|
+
per route to serve new types of content not supported by core. Modules extend
|
|
121
|
+
an app's entire scope.
|
|
122
|
+
|
|
123
|
+
Handlers and modules listed here are officially developed and supported by
|
|
124
|
+
Primate.
|
|
125
|
+
|
|
126
|
+
### Handlers
|
|
127
|
+
|
|
128
|
+
#### HTML
|
|
129
|
+
|
|
130
|
+
*[`@primate/html`][primate-html]*
|
|
131
|
+
|
|
132
|
+
Serve HTML tagged templates. This handler reads HTML component files from
|
|
133
|
+
`components`.
|
|
134
|
+
|
|
135
|
+
Create an HTML component in `components/user-index.html`
|
|
136
|
+
|
|
137
|
+
```html
|
|
138
|
+
<!-- extensions/handlers/html/user-index.html -->
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Create a route in `route/user.js` and serve the component in your route
|
|
142
|
+
|
|
143
|
+
```js
|
|
144
|
+
// extensions/handlers/html/user.js
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
#### Redirect
|
|
148
|
+
|
|
149
|
+
*[`@primate/redirect`][primate-redirect]*
|
|
150
|
+
|
|
151
|
+
Redirect the request.
|
|
152
|
+
|
|
153
|
+
Create a route in `route/user.js`
|
|
154
|
+
|
|
155
|
+
```js
|
|
156
|
+
// extensions/handlers/redirect/user.js
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
#### HTMX
|
|
160
|
+
|
|
161
|
+
*[`@primate/htmx`][primate-htmx]*
|
|
162
|
+
|
|
163
|
+
Serve HTML tagged templates with HTMX support. This handler reads HTML component
|
|
164
|
+
files from `components`.
|
|
165
|
+
|
|
166
|
+
Create an HTML component in `components/user-index.html`
|
|
167
|
+
|
|
168
|
+
```html
|
|
169
|
+
<!-- extensions/handlers/htmx/user-index.html -->
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Create a route in `route/user.js` and serve the component in your route
|
|
173
|
+
|
|
174
|
+
```js
|
|
175
|
+
// extensions/handlers/htmx/user.js
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Modules
|
|
179
|
+
|
|
180
|
+
To add modules, create a `primate.config.js` configuration file in your
|
|
181
|
+
project's root. This file should export a default object with the property
|
|
182
|
+
`modules` used for extending your app.
|
|
183
|
+
|
|
184
|
+
```js
|
|
185
|
+
// extensions/modules/configure.js
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
#### Data persistance
|
|
189
|
+
|
|
190
|
+
*[`@primate/domains`][primate-domains]*
|
|
191
|
+
|
|
192
|
+
Add data persistance in the form of ORM backed up by various drivers.
|
|
193
|
+
|
|
194
|
+
Import and initialize this module in your configuration file
|
|
195
|
+
|
|
196
|
+
```js
|
|
197
|
+
// extensions/modules/domains/configure.js
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
A domain represents a collection in a store using the static `fields` property
|
|
201
|
+
|
|
202
|
+
```js
|
|
203
|
+
// extensions/modules/domains/fields.js
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Field types may also be specified as an array with additional predicates
|
|
207
|
+
aside from the type
|
|
208
|
+
|
|
209
|
+
```js
|
|
210
|
+
// extensions/modules/domains/predicates.js
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Resources
|
|
214
|
+
|
|
215
|
+
* Website: https://primatejs.com
|
|
216
|
+
* IRC: Join the `#primate` channel on `irc.libera.chat`.
|
|
217
|
+
|
|
218
|
+
## License
|
|
219
|
+
|
|
220
|
+
MIT
|
|
221
|
+
|
|
222
|
+
[primate-html]: https://github.com/primatejs/primate-html
|
|
223
|
+
[primate-redirect]: https://github.com/primatejs/primate-redirect
|
|
224
|
+
[primate-htmx]: https://github.com/primatejs/primate-htmx
|
|
225
|
+
[primate-domains]: https://github.com/primatejs/primate-domains
|
|
226
|
+
[primate-sessions]: https://github.com/primatejs/primate-sessions
|
package/scripts/docs.sh
ADDED
package/src/bin.js
ADDED
package/src/bundle.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import {File} from "runtime-compat/
|
|
2
|
-
|
|
3
|
-
export default async conf => {
|
|
4
|
-
const {paths} = conf;
|
|
1
|
+
import {File} from "runtime-compat/fs";
|
|
5
2
|
|
|
3
|
+
export default async env => {
|
|
4
|
+
const {paths} = env;
|
|
6
5
|
if (await paths.static.exists) {
|
|
7
6
|
// remove public directory in case exists
|
|
8
7
|
if (await paths.public.exists) {
|
package/src/config.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {Path} from "runtime-compat/fs";
|
|
2
|
+
import {is} from "runtime-compat/dyndef";
|
|
3
|
+
import cache from "./cache.js";
|
|
4
|
+
import extend from "./extend.js";
|
|
5
|
+
import defaults from "./primate.config.js";
|
|
6
|
+
import * as log from "./log.js";
|
|
7
|
+
import package_json from "../package.json" assert {type: "json"};
|
|
8
|
+
|
|
9
|
+
const qualify = (root, paths) =>
|
|
10
|
+
Object.keys(paths).reduce((sofar, key) => {
|
|
11
|
+
const value = paths[key];
|
|
12
|
+
sofar[key] = typeof value === "string"
|
|
13
|
+
? new Path(root, value)
|
|
14
|
+
: qualify(`${root}/${key}`, value);
|
|
15
|
+
return sofar;
|
|
16
|
+
}, {});
|
|
17
|
+
|
|
18
|
+
const getConfig = async (root, filename) => {
|
|
19
|
+
try {
|
|
20
|
+
return extend(defaults, (await import(root.join(filename))).default);
|
|
21
|
+
} catch (error) {
|
|
22
|
+
return defaults;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export default async (filename = "primate.config.js") => {
|
|
27
|
+
is(filename).string();
|
|
28
|
+
let root;
|
|
29
|
+
try {
|
|
30
|
+
// use module root if possible
|
|
31
|
+
root = await Path.root();
|
|
32
|
+
} catch (error) {
|
|
33
|
+
// fall back to current directory
|
|
34
|
+
root = Path.resolve();
|
|
35
|
+
}
|
|
36
|
+
const config = await getConfig(root, filename);
|
|
37
|
+
|
|
38
|
+
const env = {
|
|
39
|
+
...config,
|
|
40
|
+
paths: qualify(root, config.paths),
|
|
41
|
+
root,
|
|
42
|
+
log: {...log, error: error => log.error(error, config),
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
env.log.info(`${package_json.name} \x1b[34m${package_json.version}\x1b[0m`);
|
|
46
|
+
const modules = await Promise.all(config.modules.map(module => module(env)));
|
|
47
|
+
return cache("config", filename, () => ({...env, modules}));
|
|
48
|
+
};
|
package/src/duck.js
ADDED
package/src/extend.spec.js
CHANGED
|
@@ -40,20 +40,20 @@ export default test => {
|
|
|
40
40
|
});
|
|
41
41
|
|
|
42
42
|
test.case("one property of a subobject", assert => {
|
|
43
|
-
const base = {key: {
|
|
44
|
-
const extension = {key: {
|
|
43
|
+
const base = {key: {subkey: "subvalue"}};
|
|
44
|
+
const extension = {key: {subkey: "subvalue 2"}};
|
|
45
45
|
assert(extend(base, extension)).equals(extension);
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
test.case("two properties of a subobject, one replaced", assert => {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
const base = {key: {subkey: "subvalue", subkey2: "subvalue2"}};
|
|
50
|
+
const extension = {key: {subkey: "subvalue 2"}};
|
|
51
|
+
const extended = {key: {subkey: "subvalue 2", subkey2: "subvalue2"}};
|
|
52
|
+
assert(extend(base, extension)).equals(extended);
|
|
53
|
+
});
|
|
54
54
|
|
|
55
|
-
test.case("
|
|
56
|
-
const
|
|
55
|
+
test.case("config enhancement", assert => {
|
|
56
|
+
const base = {
|
|
57
57
|
base: "/",
|
|
58
58
|
debug: false,
|
|
59
59
|
defaults: {
|
|
@@ -61,16 +61,14 @@ export default test => {
|
|
|
61
61
|
context: "guest",
|
|
62
62
|
},
|
|
63
63
|
paths: {
|
|
64
|
-
client: "client",
|
|
65
|
-
data: {
|
|
66
|
-
domains: "domains",
|
|
67
|
-
stores: "stores",
|
|
68
|
-
},
|
|
69
64
|
public: "public",
|
|
65
|
+
static: "static",
|
|
66
|
+
routes: "routes",
|
|
67
|
+
components: "components",
|
|
70
68
|
},
|
|
71
69
|
};
|
|
72
70
|
|
|
73
|
-
const
|
|
71
|
+
const additional = {
|
|
74
72
|
debug: true,
|
|
75
73
|
environment: "testing",
|
|
76
74
|
defaults: {
|
|
@@ -78,11 +76,7 @@ export default test => {
|
|
|
78
76
|
mode: "operational",
|
|
79
77
|
},
|
|
80
78
|
paths: {
|
|
81
|
-
client: "
|
|
82
|
-
data: {
|
|
83
|
-
stores: "storage",
|
|
84
|
-
drivers: "drivers",
|
|
85
|
-
},
|
|
79
|
+
client: "client",
|
|
86
80
|
},
|
|
87
81
|
};
|
|
88
82
|
|
|
@@ -96,16 +90,14 @@ export default test => {
|
|
|
96
90
|
mode: "operational",
|
|
97
91
|
},
|
|
98
92
|
paths: {
|
|
99
|
-
client: "
|
|
100
|
-
data: {
|
|
101
|
-
domains: "domains",
|
|
102
|
-
drivers: "drivers",
|
|
103
|
-
stores: "storage",
|
|
104
|
-
},
|
|
93
|
+
client: "client",
|
|
105
94
|
public: "public",
|
|
95
|
+
static: "static",
|
|
96
|
+
routes: "routes",
|
|
97
|
+
components: "components",
|
|
106
98
|
},
|
|
107
99
|
};
|
|
108
100
|
|
|
109
|
-
assert(extend(
|
|
101
|
+
assert(extend(base, additional)).equals(extended);
|
|
110
102
|
});
|
|
111
103
|
};
|
package/src/handlers/http404.js
CHANGED
package/src/handlers/json.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
export default (_, ...keys) => async () => [JSON.stringify(await keys[0]), {
|
|
2
2
|
status: 200,
|
|
3
3
|
headers: {"Content-Type": "application/json"},
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
export default (strings, ...keys) => async () =>
|
|
7
|
-
({...response, body: JSON.stringify(await keys[0])});
|
|
4
|
+
}];
|
package/src/handlers/stream.js
CHANGED
package/src/handlers/text.js
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
const last = -1;
|
|
2
|
-
const response = {
|
|
3
|
-
status: 200,
|
|
4
|
-
headers: {"Content-Type": "text/plain"},
|
|
5
|
-
};
|
|
6
2
|
|
|
7
3
|
export default (strings, ...keys) => async () => {
|
|
8
4
|
const awaitedKeys = await Promise.all(keys);
|
|
@@ -10,5 +6,6 @@ export default (strings, ...keys) => async () => {
|
|
|
10
6
|
.slice(0, last)
|
|
11
7
|
.map((string, i) => string + awaitedKeys[i])
|
|
12
8
|
.join("") + strings[strings.length + last];
|
|
13
|
-
|
|
9
|
+
|
|
10
|
+
return [body, {status: 200, headers: {"Content-Type": "text/plain"}}];
|
|
14
11
|
};
|
package/src/log.js
CHANGED
|
@@ -19,4 +19,11 @@ const log = new Proxy(Log, {
|
|
|
19
19
|
log.paint(colors[property] ?? reset, message).paint(reset, " ")),
|
|
20
20
|
});
|
|
21
21
|
|
|
22
|
-
export
|
|
22
|
+
export const info = (...args) => log.green("[info]").reset(...args).nl();
|
|
23
|
+
|
|
24
|
+
export const warn = (...args) => log.yellow("[warn]").reset(...args).nl();
|
|
25
|
+
|
|
26
|
+
export const error = (error, env) => {
|
|
27
|
+
log.red("[error]").reset(error.message).nl();
|
|
28
|
+
env.debug && console.log(error);
|
|
29
|
+
};
|
package/src/mimes.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
binary: "application/octet-stream",
|
|
3
|
+
css: "text/css",
|
|
4
|
+
html: "text/html",
|
|
5
|
+
jpg: "image/jpeg",
|
|
6
|
+
js: "text/javascript",
|
|
7
|
+
json: "application/json",
|
|
8
|
+
png: "image/png",
|
|
9
|
+
svg: "image/svg+xml",
|
|
10
|
+
woff2: "font/woff2",
|
|
11
|
+
webp: "image/webp",
|
|
12
|
+
};
|
package/src/respond.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {Blob} from "runtime-compat/fs";
|
|
2
|
+
import text from "./handlers/text.js";
|
|
3
|
+
import json from "./handlers/json.js";
|
|
4
|
+
import stream from "./handlers/stream.js";
|
|
5
|
+
import {isResponse as isResponseDuck} from "./duck.js";
|
|
6
|
+
import RouteError from "./errors/Route.js";
|
|
7
|
+
|
|
8
|
+
const isText = value => {
|
|
9
|
+
if (typeof value === "string") {
|
|
10
|
+
return text`${value}`;
|
|
11
|
+
}
|
|
12
|
+
throw new RouteError(`no handler found for ${value}`);
|
|
13
|
+
};
|
|
14
|
+
const isObject = value => typeof value === "object" && value !== null
|
|
15
|
+
? json`${value}` : isText(value);
|
|
16
|
+
const isResponse = value => isResponseDuck(value)
|
|
17
|
+
? () => value : isObject(value);
|
|
18
|
+
const isStream = value => value instanceof ReadableStream
|
|
19
|
+
? stream`${value}` : isResponse(value);
|
|
20
|
+
const isBlob = value => value instanceof Blob
|
|
21
|
+
? stream`${value}` : isStream(value);
|
|
22
|
+
const guess = value => isBlob(value);
|
|
23
|
+
|
|
24
|
+
export default result => typeof result === "function" ? result : guess(result);
|
package/src/route.js
CHANGED
|
@@ -1,21 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {Path, File} from "runtime-compat/filesystem";
|
|
1
|
+
import {Path} from "runtime-compat/fs";
|
|
3
2
|
import {is} from "runtime-compat/dyndef";
|
|
4
|
-
import {http404} from "./handlers/http.js";
|
|
5
|
-
import text from "./handlers/text.js";
|
|
6
|
-
import json from "./handlers/json.js";
|
|
7
|
-
import stream from "./handlers/stream.js";
|
|
8
3
|
import RouteError from "./errors/Route.js";
|
|
9
4
|
|
|
10
|
-
const isText = value => typeof value === "string" ? text`${value}` : http404``;
|
|
11
|
-
const isObject = value => typeof value === "object" && value !== null
|
|
12
|
-
? json`${value}` : isText(value);
|
|
13
|
-
const isStream = value => value instanceof ReadableStream
|
|
14
|
-
? stream`${value}` : isObject(value);
|
|
15
|
-
const isFile = value => value instanceof File
|
|
16
|
-
? stream`${value}` : isStream(value);
|
|
17
|
-
const guess = value => isFile(value);
|
|
18
|
-
|
|
19
5
|
// insensitive-case equal
|
|
20
6
|
const ieq = (left, right) => left.toLowerCase() === right.toLowerCase();
|
|
21
7
|
|
|
@@ -43,19 +29,19 @@ export default async definitions => {
|
|
|
43
29
|
get: (path, callback) => add("get", path, callback),
|
|
44
30
|
post: (path, callback) => add("post", path, callback),
|
|
45
31
|
alias: (key, value) => aliases.push({key, value}),
|
|
46
|
-
|
|
32
|
+
route: async request => {
|
|
47
33
|
const {method} = request.original;
|
|
48
34
|
const url = new URL(`https://primatejs.com${request.pathname}`);
|
|
49
35
|
const {pathname, searchParams} = url;
|
|
50
36
|
const params = Object.fromEntries(searchParams);
|
|
51
|
-
const verb = find(method, pathname, {handler: () =>
|
|
37
|
+
const verb = find(method, pathname, {handler: () => {
|
|
38
|
+
throw new RouteError(`no ${method.toUpperCase()} route to ${pathname}`);
|
|
39
|
+
}});
|
|
52
40
|
const path = pathname.split("/").filter(part => part !== "");
|
|
53
41
|
const named = verb.path?.exec(pathname)?.groups ?? {};
|
|
54
42
|
|
|
55
|
-
|
|
43
|
+
return verb.handler(await find("map", pathname)
|
|
56
44
|
.handler({...request, pathname, params, path, named}));
|
|
57
|
-
|
|
58
|
-
return typeof result === "function" ? result : guess(result);
|
|
59
45
|
},
|
|
60
46
|
};
|
|
61
47
|
if (await definitions.exists) {
|
package/src/run.js
CHANGED
|
@@ -1,22 +1,13 @@
|
|
|
1
|
+
import bundle from "./bundle.js";
|
|
2
|
+
import config from "./config.js";
|
|
1
3
|
import serve from "./serve.js";
|
|
2
4
|
import route from "./route.js";
|
|
3
|
-
import bundle from "./bundle.js";
|
|
4
|
-
import package_json from "../package.json" assert {type: "json"};
|
|
5
|
-
import log from "./log.js";
|
|
6
|
-
|
|
7
|
-
const extract = (modules, key) => modules.flatMap(module => module[key] ?? []);
|
|
8
|
-
|
|
9
|
-
export default async conf => {
|
|
10
|
-
log.reset("Primate").yellow(package_json.version);
|
|
11
5
|
|
|
12
|
-
|
|
6
|
+
export default async () => {
|
|
7
|
+
const env = await config();
|
|
8
|
+
const {paths} = env;
|
|
13
9
|
const router = await route(paths.routes);
|
|
14
|
-
await bundle(
|
|
10
|
+
await bundle(env);
|
|
15
11
|
|
|
16
|
-
|
|
17
|
-
paths: conf.paths,
|
|
18
|
-
from: conf.paths.public,
|
|
19
|
-
http: conf.http,
|
|
20
|
-
modules: extract(conf.modules ?? [], "serve"),
|
|
21
|
-
});
|
|
12
|
+
serve({router, ...env});
|
|
22
13
|
};
|