galbe 0.1.7 → 0.1.13
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/.github/workflows/deploy_website.yml +1 -1
- package/.github/workflows/release.yml +1 -1
- package/README.md +3 -1
- package/docs/context.md +114 -0
- package/docs/error-handler.md +54 -0
- package/docs/getting-started.md +25 -25
- package/docs/handler.md +105 -0
- package/docs/hooks.md +90 -0
- package/docs/plugins.md +1 -0
- package/docs/router.md +10 -0
- package/docs/routes.md +12 -12
- package/docs/schemas.md +24 -28
- package/package.json +1 -1
- package/src/index.ts +4 -2
- package/src/parser.ts +63 -41
- package/src/router.ts +15 -11
- package/src/server.ts +32 -16
- package/src/types.ts +15 -9
- package/test/hooks.test.ts +23 -0
- package/test/router.test.ts +2 -6
|
@@ -16,5 +16,5 @@ jobs:
|
|
|
16
16
|
-H "Accept: application/vnd.github+json" \
|
|
17
17
|
-H "Authorization: Bearer ${{ secrets.GH_WEBSITE_TOKEN }}" \
|
|
18
18
|
-H "X-GitHub-Api-Version: 2022-11-28" \
|
|
19
|
-
https://api.github.com/repos/pierre-cm/galbe-website/actions/workflows/
|
|
19
|
+
https://api.github.com/repos/pierre-cm/galbe-website/actions/workflows/deploy.yml/dispatches \
|
|
20
20
|
-d '{"ref":"main"}'
|
package/README.md
CHANGED
package/docs/context.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Context
|
|
2
|
+
|
|
3
|
+
An instance of the context object is created when a new request is initiated and carrieds out along durring all the request lifecycle.
|
|
4
|
+
See the [Lifecycle](lifecycle) section to get more details.
|
|
5
|
+
|
|
6
|
+
Its purpose is to carrie all the relevent information about the request and to allow sharing informations between each step of the request lifecycle.
|
|
7
|
+
|
|
8
|
+
## Definition
|
|
9
|
+
|
|
10
|
+
A context has the following properties:
|
|
11
|
+
|
|
12
|
+
**request**
|
|
13
|
+
|
|
14
|
+
An instance of the [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object created by th server.
|
|
15
|
+
|
|
16
|
+
**headers**
|
|
17
|
+
|
|
18
|
+
A javascript object representing the `headers` of the current request.
|
|
19
|
+
|
|
20
|
+
- key (string): header name
|
|
21
|
+
- value: (string | [schema defined](schemas.md#headers)): header value
|
|
22
|
+
|
|
23
|
+
```js
|
|
24
|
+
{
|
|
25
|
+
"accept": "*/*",
|
|
26
|
+
"accept-encoding": "gzip, deflate, br",
|
|
27
|
+
"cookie": "Cookie_1=value; Cookie_2=value",
|
|
28
|
+
"host": "localhost:3000",
|
|
29
|
+
"user-agent": "galbe/1.0.0"
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**params**
|
|
34
|
+
|
|
35
|
+
A javascript object representing the request `parameters` of the current request.
|
|
36
|
+
|
|
37
|
+
- key (string): parameter name
|
|
38
|
+
- value: (string | [schema defined](schemas.md#params)): parameter value
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
galbe.get('/default/:p1/foo/:p2', ctx => console.log(ctx.params))
|
|
42
|
+
// GET /default/four/foo/2
|
|
43
|
+
{ p1: "four", p2: "2" }
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**query**
|
|
47
|
+
|
|
48
|
+
A javascript object representing the request `query parameters` of the current request.
|
|
49
|
+
|
|
50
|
+
- key (string): query parameter name
|
|
51
|
+
- value: (string | [schema defined](schemas.md#query)): query parameter value
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
galbe.get('/test', ctx => console.log(ctx.params))
|
|
55
|
+
// GET /test?one=1&two=2
|
|
56
|
+
{ one: "1", two: "2" }
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**body**
|
|
60
|
+
|
|
61
|
+
The body payload of the incoming request. The body type is computed according to the following rules.
|
|
62
|
+
|
|
63
|
+
If no [Schema](schemas.md) is defined, Galbe will parse the body type according to `content-type` Header value:
|
|
64
|
+
|
|
65
|
+
- `text/.*`: string
|
|
66
|
+
- `application/json`: object
|
|
67
|
+
- `application/x-www-form-urlencoded`: { [key: string]: any }
|
|
68
|
+
- `multipart/form-data`: { [key: string]:
|
|
69
|
+
{ headers: { name: string; type?: string; filename?: string };
|
|
70
|
+
content: any
|
|
71
|
+
} }
|
|
72
|
+
- `other`: AsyncGenerator\<Uint8Array\>
|
|
73
|
+
|
|
74
|
+
If a [Schema](schemas.md) is defined, Galbe will parse the body type according to the [Schema.body](schemas.md#body) defined for the current route.
|
|
75
|
+
|
|
76
|
+
**set**
|
|
77
|
+
|
|
78
|
+
The set property contains modifiable properties which purpose are to give informations to the Response parser.
|
|
79
|
+
|
|
80
|
+
- `status`: Set the response status
|
|
81
|
+
- `headers`: Set the response headers
|
|
82
|
+
|
|
83
|
+
```js
|
|
84
|
+
galbe.get('/example', ctx => {
|
|
85
|
+
ctx.set.status = 418
|
|
86
|
+
return "I don't do coffee"
|
|
87
|
+
})
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**state**
|
|
91
|
+
|
|
92
|
+
The state property purpose is to carry custom user object accross request lifecycle. In general it is used to share informations between the [hooks](hooks.md) and the [handler](handler.md).
|
|
93
|
+
|
|
94
|
+
- key (string): user defined key
|
|
95
|
+
- value (any): user defined object
|
|
96
|
+
|
|
97
|
+
```js
|
|
98
|
+
galbe.get(
|
|
99
|
+
'/example',
|
|
100
|
+
[
|
|
101
|
+
ctx => {
|
|
102
|
+
ctx.state['foo'] = 'bar'
|
|
103
|
+
}
|
|
104
|
+
],
|
|
105
|
+
ctx => {
|
|
106
|
+
return ctx.state.foo
|
|
107
|
+
}
|
|
108
|
+
)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
$ curl http://localhost:3000/example
|
|
113
|
+
bar
|
|
114
|
+
```
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Error handler
|
|
2
|
+
|
|
3
|
+
Any error happening during a request lifecycle will be intercepted by the error handler.
|
|
4
|
+
|
|
5
|
+
You can customize the default error handling behavior by defining a custom error handler using Galbe's intance `onError` method.
|
|
6
|
+
|
|
7
|
+
```js
|
|
8
|
+
const galbe = new Galbe()
|
|
9
|
+
galbe.onError(customErrorHandler)
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Definition
|
|
13
|
+
|
|
14
|
+
The error handler should be a function that takes two aguments: an [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) and a [Context](context.md). This function may potentially return a [Response type](handler.md#response-types).
|
|
15
|
+
|
|
16
|
+
```js
|
|
17
|
+
galbe.onErrorHandler((error, ctx) => {
|
|
18
|
+
if (error.status === 500) {
|
|
19
|
+
return new Response(`Server error ❌`, { status: 500 })
|
|
20
|
+
}
|
|
21
|
+
if (error.status === 404) {
|
|
22
|
+
return new Response(`Not found 🔎`, { status: 404 })
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The `error` argument could be any type of error thrown by your application. If the error originates from Galbe framework, it will be an instance of [RequestError](#request-error).
|
|
28
|
+
|
|
29
|
+
For instance, the [Router](router.md) will throw a `RequestError` with a `404` status if no route matches the incoming request path. Similarly, the Parser will throw a `RequestError` with a `400` status.
|
|
30
|
+
|
|
31
|
+
## Request Error
|
|
32
|
+
|
|
33
|
+
The `RequestError` class is utilized to instanciate a runtime request error in Galbe. It has two optional attributes: a `status` and a `payload`.
|
|
34
|
+
|
|
35
|
+
If your application throws a `RequestError` instance, Galbe will, by default, construct a Response from your `RequestError` and send it back to the client.
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
import { Galbe, RequestError } from 'galbe'
|
|
39
|
+
|
|
40
|
+
const galbe = new Galbe()
|
|
41
|
+
|
|
42
|
+
galbe.get('/coffee', () => throw new RequestError({ status: 418, payload: '🫖' }))
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
When called, above endpoint should respond:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
$ curl -i http://localhost:3000/coffee
|
|
49
|
+
HTTP/1.1 418 I'm a Teapot
|
|
50
|
+
Content-Type: application/json
|
|
51
|
+
Content-Length: 6
|
|
52
|
+
|
|
53
|
+
"🫖"
|
|
54
|
+
```
|
package/docs/getting-started.md
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
# Getting started
|
|
2
2
|
|
|
3
|
-
Galbe is a Javascript web framework
|
|
3
|
+
Galbe is a Javascript web framework for building fast and versatile backend servers with Bun.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Designed with simplicity in mind, Galbe allows you to quickly create and set up a project. In addition to its ease of use, Galbe also offers a range of useful features that help you focus on the core logic of your application.
|
|
6
6
|
|
|
7
7
|
## Requirements
|
|
8
8
|
|
|
9
9
|
To start developing your Galbe project, you first need to install [Bun](https://bun.sh).
|
|
10
10
|
|
|
11
|
-
## Automatic
|
|
11
|
+
## Automatic installation
|
|
12
12
|
|
|
13
13
|
This is the recommended way of setting up a Galbe project.
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
bun create galbe app
|
|
17
|
-
cd app
|
|
18
|
-
bun install
|
|
16
|
+
$ bun create galbe app
|
|
17
|
+
$ cd app
|
|
18
|
+
$ bun install
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
This will create a new project under `app` directory and install it.
|
|
@@ -23,12 +23,12 @@ This will create a new project under `app` directory and install it.
|
|
|
23
23
|
Now you can start the dev server by running:
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
|
-
bun dev
|
|
26
|
+
$ bun dev
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
This will start a web server on `
|
|
29
|
+
This will start a web server on `localhost:3000`.
|
|
30
30
|
|
|
31
|
-
To verify that the project was setup correctly and is running, try to reach `
|
|
31
|
+
To verify that the project was setup correctly and is running, try to reach `localhost:3000/hello` endpoint, this should return following greeting message:
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
34
|
$ curl localhost:3000/hello
|
|
@@ -38,13 +38,13 @@ Hello from Galbe!
|
|
|
38
38
|
> [!TIP]
|
|
39
39
|
> By default, the dev server automatically reloads on every file change.
|
|
40
40
|
|
|
41
|
-
## Manual
|
|
41
|
+
## Manual installation
|
|
42
42
|
|
|
43
43
|
Init a new Bun project and add Galbe as dependency:
|
|
44
44
|
|
|
45
45
|
```bash
|
|
46
|
-
bun init
|
|
47
|
-
bun add galbe
|
|
46
|
+
$ bun init
|
|
47
|
+
$ bun add galbe
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
Open `package.json` file and add the following scripts:
|
|
@@ -74,18 +74,18 @@ export default galbe
|
|
|
74
74
|
|
|
75
75
|
This is the recommended way to proceed but it is not mandatory. Galbe instances also provide a `listen` method that will allow you to manually start your server instance from the code.
|
|
76
76
|
|
|
77
|
-
> [!WARNING]
|
|
77
|
+
> [!WARNING]
|
|
78
78
|
> In the case you decide to not rely on Galbe CLI to run/build your app, you will not have access to [Automatic Route Analyzer](routes.md#automatic-route-analyzer) feature.
|
|
79
79
|
|
|
80
80
|
### Galbe CLI
|
|
81
81
|
|
|
82
82
|
```bash
|
|
83
|
-
galbe <command> <argument> [options]
|
|
83
|
+
$ galbe <command> <argument> [options]
|
|
84
84
|
```
|
|
85
85
|
|
|
86
86
|
Here are the available commands:
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
**dev**
|
|
89
89
|
|
|
90
90
|
Start a dev server running your Galbe application.
|
|
91
91
|
|
|
@@ -98,7 +98,7 @@ _options_
|
|
|
98
98
|
- `--port` or `-p`: port number (default: 3000)
|
|
99
99
|
- `--watch` or `-w`: watch file changes (default: true)
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
**build**
|
|
102
102
|
|
|
103
103
|
Bundle your Galbe application.
|
|
104
104
|
|
|
@@ -121,25 +121,25 @@ const galbe = new Galbe(configuration)
|
|
|
121
121
|
|
|
122
122
|
### Properties
|
|
123
123
|
|
|
124
|
-
|
|
124
|
+
**port**
|
|
125
125
|
|
|
126
126
|
The port number that the server will be listening on. Default is `3000`.
|
|
127
127
|
|
|
128
|
-
|
|
128
|
+
**basePath**
|
|
129
129
|
|
|
130
130
|
The base path is added as a prefix to all the routes created.
|
|
131
131
|
|
|
132
|
-
|
|
132
|
+
**routes**
|
|
133
133
|
|
|
134
134
|
A Glob Pattern or a list of Glob patterns defining the route files to be analyzed by the [Automatic Route Analyzer](routes.md#automatic-route-analyzer). Default is `src/**/*.route.{js,ts}`.
|
|
135
135
|
|
|
136
|
-
|
|
136
|
+
**plugin**
|
|
137
137
|
|
|
138
138
|
A property that can be used by plugins to add plugin's specific configuration. Every key should correspond to a [Unique Plugin Identifier](plugins.md).
|
|
139
139
|
|
|
140
140
|
### Examples
|
|
141
141
|
|
|
142
|
-
|
|
142
|
+
A common way to handle server configuration is to create new file `galbe.config.(js|ts|json)` at the root of your project directory and import it in your code. Here is an example:
|
|
143
143
|
|
|
144
144
|
galbe.config.js
|
|
145
145
|
|
|
@@ -171,7 +171,7 @@ export default new Galbe(config)
|
|
|
171
171
|
> export default config
|
|
172
172
|
> ```
|
|
173
173
|
|
|
174
|
-
## Project
|
|
174
|
+
## Project structure
|
|
175
175
|
|
|
176
176
|
One key aspect of Galbe, is its versatility in terms of project structure. This is partly allowed by the [Automatic Route Analyzer](routes.md#automatic-route-analyzer) and the `routes` config property which defaults to `src/**/*.route.{js,ts}`.
|
|
177
177
|
|
|
@@ -217,7 +217,7 @@ Here are two examples of valid project structures by default:
|
|
|
217
217
|
|
|
218
218
|
In both cases, the [Automatic Route Analyzer](routes.md#automatic-route-analyzer) will analyze `foo.route.ts` and `bar.route.ts` Route Files to find route definitions.
|
|
219
219
|
|
|
220
|
-
You can find more info about Route Files definition
|
|
220
|
+
You can find more info about Route Files definition in the [Routes Files](routes.md#route-files) section.
|
|
221
221
|
|
|
222
|
-
> [!NOTE]
|
|
223
|
-
>
|
|
222
|
+
> [!NOTE]
|
|
223
|
+
> The examples provided above will work with the default configuration, but you can easily customize the routes property to fit your own project structure. Simply redefine the `routes` property with your own pattern(s) to to fit your own project structure.
|
package/docs/handler.md
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Handler
|
|
2
|
+
|
|
3
|
+
A handler is a function that gets executed when a request matches the route definition. It is responsible for processing the request and sending a response.
|
|
4
|
+
|
|
5
|
+
## Handler declaration
|
|
6
|
+
|
|
7
|
+
The handler should be declared as last argument of the [Route Definition](routes.md#route-defintion) method.
|
|
8
|
+
|
|
9
|
+
```js
|
|
10
|
+
galbe.get('foo', schema, [hook1, hook2], ctx => {})
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Handler are called after the last hook call, or right after the request parsing if no hook is declared. To get a better understanding of the request lifecycle, you can refer to the [Lifecycle](lifecycle.md) section.
|
|
14
|
+
|
|
15
|
+
## Handler definition
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
const handler = ctx => {
|
|
19
|
+
const { name } = ctx.query
|
|
20
|
+
return `Hello ${name}!`
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The handler function takes a `context` object as single argument and might return a `response`.
|
|
25
|
+
|
|
26
|
+
**context**
|
|
27
|
+
|
|
28
|
+
The `context` object contains the request information as well as a `set` object that serves as a response modifier. You can find more detailed informations about the `context` object in the [Context](context.md) section.
|
|
29
|
+
|
|
30
|
+
**response**
|
|
31
|
+
|
|
32
|
+
To send a response, your handler can return an object. The response sent will depend on the type of the object returned. There are four types of responses that can be returned by a handler method. More about that in the next section.
|
|
33
|
+
|
|
34
|
+
## Response types
|
|
35
|
+
|
|
36
|
+
> [!NOTE]
|
|
37
|
+
> This section only cover response body payloads, to return specific response headers and/or status, you should define them with the `context.set` object before the return statement. More about it in the [Context](context.md) section.
|
|
38
|
+
|
|
39
|
+
### String
|
|
40
|
+
|
|
41
|
+
Case where `string` is returned by the handler.
|
|
42
|
+
|
|
43
|
+
- status: 200
|
|
44
|
+
- content-type: `text-plain`
|
|
45
|
+
|
|
46
|
+
**Example**
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
galbe.get('/example', ctx => {
|
|
50
|
+
return 'Hello Mom!'
|
|
51
|
+
})
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Object
|
|
55
|
+
|
|
56
|
+
Case where an `object` is returned by the handler.
|
|
57
|
+
|
|
58
|
+
- status: 200
|
|
59
|
+
- content-type: `application/json`
|
|
60
|
+
|
|
61
|
+
**Example**
|
|
62
|
+
|
|
63
|
+
```js
|
|
64
|
+
galbe.get('/example', ctx => {
|
|
65
|
+
return 'Hello Mom!'
|
|
66
|
+
})
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Response instance
|
|
70
|
+
|
|
71
|
+
Case where a [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) instance is returned by the handler.
|
|
72
|
+
|
|
73
|
+
In that case, `context.set` properties are not taken into account to contruct the response.
|
|
74
|
+
|
|
75
|
+
**Example**
|
|
76
|
+
|
|
77
|
+
<!-- prettier-ignore -->
|
|
78
|
+
```js
|
|
79
|
+
galbe.get('/example', ctx => {
|
|
80
|
+
return new Response(
|
|
81
|
+
'Hello Mom',
|
|
82
|
+
{ status: 200, headers: { 'content-type': 'text/plain' }
|
|
83
|
+
})
|
|
84
|
+
})
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Generator
|
|
88
|
+
|
|
89
|
+
Case where a [Generator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator) instance is returned by the handler.
|
|
90
|
+
|
|
91
|
+
- status: 200
|
|
92
|
+
- content-type: `text/event-stream`
|
|
93
|
+
|
|
94
|
+
**Example**
|
|
95
|
+
|
|
96
|
+
```js
|
|
97
|
+
async function* generator(array) {
|
|
98
|
+
for (const item of array) {
|
|
99
|
+
await Bun.sleep(500)
|
|
100
|
+
yield item
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
galbe.get('/example', ctx => generator(['one', 'two', 'three']))
|
|
105
|
+
```
|
package/docs/hooks.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Hooks
|
|
2
|
+
|
|
3
|
+
Hooks provide a simple way to perform specific actions before and/or after reaching a specific route endpoint.
|
|
4
|
+
|
|
5
|
+
## Hook definition
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
const hook = (context, next) => {
|
|
9
|
+
context.state['foo'] = 'bar'
|
|
10
|
+
await next()
|
|
11
|
+
console.log('Hook end')
|
|
12
|
+
}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The hook takes only two arguments, a `context` object and a `next` function.
|
|
16
|
+
|
|
17
|
+
**context**
|
|
18
|
+
|
|
19
|
+
The `context` object contains the request information along with a state property that is modifiable and preserved across all hooks and the handler. It is useful for sharing information or objects across hooks and handler. You can find more information about it in the [Context](context.md) section.
|
|
20
|
+
|
|
21
|
+
**next**
|
|
22
|
+
|
|
23
|
+
The `next` function calls the next hook in the hook list or the handler if the current hook is the last one declared. The `next` function should be called at most once. If it is omitted, Galbe will call it automatically at the end of the execution of the current hook.
|
|
24
|
+
|
|
25
|
+
> [!TIP]
|
|
26
|
+
> Hooks are interruptible objects, meaning they can return a response at any moment. This provides a powerful mechanism for implementing custom logic, such as authentication, authorization, caching, and more.
|
|
27
|
+
>
|
|
28
|
+
> To learn more about response types, ou can take a look at the [Response types](handler.md#response-types) section.
|
|
29
|
+
|
|
30
|
+
## Hooks declaration
|
|
31
|
+
|
|
32
|
+
Hooks should be declared just before the handler method in the [Route Definition](routes.md#route-defintion) method as a list of Hooks.
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
galbe.get('foo', [ hook1, hook2, ... ], ctx => {})
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Hooks are called just before the [Handler](handler.md) in the order that they have been declared in the hook list of the [Route Definition](routes.md#route-defintion). To get a better understanding of hooks execution during the request lifecycle, you can refer to the [Lifecycle](lifecycle.md) section.
|
|
39
|
+
|
|
40
|
+
### Examples
|
|
41
|
+
|
|
42
|
+
Linear hooks declaration:
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
const hook1 = context => {
|
|
46
|
+
console.log('hook1 called')
|
|
47
|
+
}
|
|
48
|
+
const hook2 = context => {
|
|
49
|
+
console.log('hook2 called')
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
galbe.get('example', [hook1, hook2], ctx => {
|
|
53
|
+
console.log('handler')
|
|
54
|
+
})
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
$ curl http://localhost:3000/example
|
|
59
|
+
hook1
|
|
60
|
+
hook2
|
|
61
|
+
handler
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Nested hooks declaration:
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
const hook1 = (context, next) => {
|
|
68
|
+
console.log('hook1 start')
|
|
69
|
+
await next()
|
|
70
|
+
console.log('hook1 end')
|
|
71
|
+
}
|
|
72
|
+
const hook2 = context => {
|
|
73
|
+
console.log('hook2 start')
|
|
74
|
+
await next()
|
|
75
|
+
console.log('hook2 end')
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
galbe.get('example', [hook1, hook2], ctx => {
|
|
79
|
+
console.log('handler')
|
|
80
|
+
})
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
$ curl http://localhost:3000/example
|
|
85
|
+
hook1 start
|
|
86
|
+
hook2 start
|
|
87
|
+
handler
|
|
88
|
+
hook2 end
|
|
89
|
+
hook1 end
|
|
90
|
+
```
|
package/docs/plugins.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Plugins
|
package/docs/router.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Router
|
|
2
|
+
|
|
3
|
+
Galbe router employs a hybrid approach to store and locating routes.
|
|
4
|
+
|
|
5
|
+
The static routes are maintained in a Map structure. This ensure that any incoming request path matching a static route is resolved in a constant time `O(1)`.
|
|
6
|
+
|
|
7
|
+
> [!NOTE]
|
|
8
|
+
> A static route is a route that doesn't contain any parameter (e.g.,`:param`) or wildcards `*`.
|
|
9
|
+
|
|
10
|
+
All other routes are stored in a [Trie](https://en.wikipedia.org/wiki/Trie)-like data structure. The time complexity of the search operation in this case is `O(n)`, where `n` represents the number of segments in the incoming request path.
|
package/docs/routes.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Routes
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Routes are the entry points for handling client requests in a Galbe application. In this section, we'll cover how to define routes, the various options available for route definitions, and how to use the Automatic Route Analyzer to simplify route setup.
|
|
4
|
+
|
|
5
|
+
## Route definition
|
|
4
6
|
|
|
5
7
|
Here is how to define routes in Galbe.
|
|
6
8
|
|
|
@@ -23,15 +25,15 @@ There are two special segments:
|
|
|
23
25
|
|
|
24
26
|
**schema** (Schema) _Optional_
|
|
25
27
|
|
|
26
|
-
See [Schemas](schemas) section.
|
|
28
|
+
See [Schemas](schemas.md) section.
|
|
27
29
|
|
|
28
30
|
**hooks** (Hook[]) _Optional_
|
|
29
31
|
|
|
30
|
-
See [Hooks](hooks) section.
|
|
32
|
+
See [Hooks](hooks.md) section.
|
|
31
33
|
|
|
32
34
|
**handler** (Handler)
|
|
33
35
|
|
|
34
|
-
See [Handler](handler) section.
|
|
36
|
+
See [Handler](handler.md) section.
|
|
35
37
|
|
|
36
38
|
### Examples
|
|
37
39
|
|
|
@@ -78,15 +80,13 @@ galbe.get(
|
|
|
78
80
|
## Automatic Route Analyzer
|
|
79
81
|
|
|
80
82
|
> [!NOTE]
|
|
81
|
-
> This feature is only available if you run/build the app via the [Galbe CLI](), which is the case by default if you created your app following the [Automatic Installation]() step or
|
|
82
|
-
|
|
83
|
-
The Automatic Route Analyzer is in charge of analyzing all the Route Files of your project and set up the routes defintions to your Glabe server automatically.
|
|
83
|
+
> This feature is only available if you run/build the app via the [Galbe CLI](getting-started.md#galbe-cli), which is the case by default if you created your app following the [Automatic Installation](getting-started.md#automatic-installation) step or if you configured your package.json to do so.
|
|
84
84
|
|
|
85
|
-
By default, the analyzer will search for
|
|
85
|
+
The Automatic Route Analyzer is responsible for analyzing all the Route Files of your project and setting up the route definitions for your Galbe server automatically. By default, the analyzer will search for Route Files matching paths like `src/**/*.route.{js,ts}`. This can be configured by modifying the value of `routes` property of your Galbe configuration. A value of `false` will disable the analyzer.
|
|
86
86
|
|
|
87
87
|
### Route Files
|
|
88
88
|
|
|
89
|
-
In order to be properly analyzed, Route Files must export a default function that takes a Galbe instance as unique argument. Your routes should be defined using that Galbe instance. Here a basic
|
|
89
|
+
In order to be properly analyzed, Route Files must export a default function that takes a Galbe instance as unique argument. Your routes should be defined using that Galbe instance. Here's a basic example in JavaScript:
|
|
90
90
|
|
|
91
91
|
```ts
|
|
92
92
|
export default g => {
|
|
@@ -94,7 +94,7 @@ export default g => {
|
|
|
94
94
|
}
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
-
The same example
|
|
97
|
+
The same example in Typescript:
|
|
98
98
|
|
|
99
99
|
```ts
|
|
100
100
|
import type { Galbe } from 'galbe'
|
|
@@ -103,7 +103,7 @@ export default (g: Galbe) => {
|
|
|
103
103
|
}
|
|
104
104
|
```
|
|
105
105
|
|
|
106
|
-
The Automatic Route Analyzer
|
|
106
|
+
The Automatic Route Analyzer can also collect metadata about your Route File and your routes by analyzing multiline comments. This can be used by some plugins to perform specific tasks. Here's an example of a Route File with multiline comment metadata:
|
|
107
107
|
|
|
108
108
|
```js
|
|
109
109
|
/**
|
|
@@ -121,4 +121,4 @@ export default g => {
|
|
|
121
121
|
}
|
|
122
122
|
```
|
|
123
123
|
|
|
124
|
-
You will find more information about comment
|
|
124
|
+
You will find more information about comment metadata and how to use them along with examples in the [Plugin](plugins.md) section.
|