galbe 0.12.1 → 0.13.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/bin/commands/generate/code/openapi.parser.ts +18 -11
- package/bin/commands/generate/index.ts +3 -1
- package/bin/commands/generate/model.ts +153 -0
- package/bin/commands/generate/spec.ts +7 -5
- package/bin/util.ts +9 -0
- package/package.json +8 -4
- package/src/types.ts +1 -1
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -35
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -23
- package/.github/workflows/build_test.yml +0 -17
- package/.github/workflows/deploy_website.yml +0 -20
- package/.github/workflows/release.yml +0 -39
- package/.prettierrc +0 -10
- package/bun.lock +0 -904
- package/bunfig.toml +0 -2
- package/docs/CONTRIBUTING.md +0 -105
- package/docs/cli.md +0 -343
- package/docs/configuration.md +0 -80
- package/docs/context.md +0 -104
- package/docs/error-handler.md +0 -54
- package/docs/getting-started.md +0 -164
- package/docs/handler.md +0 -119
- package/docs/hooks.md +0 -90
- package/docs/plugins.md +0 -146
- package/docs/router.md +0 -10
- package/docs/routes.md +0 -133
- package/docs/schemas.md +0 -327
- package/test/hooks.test.ts +0 -200
- package/test/parser.test.ts +0 -1358
- package/test/plugins.test.ts +0 -239
- package/test/requests.test.ts +0 -917
- package/test/resources/image.png +0 -0
- package/test/resources/object.badSyntax.json +0 -8
- package/test/resources/object.json +0 -8
- package/test/resources/object.missing.json +0 -6
- package/test/resources/static/chameleon.png +0 -0
- package/test/resources/static/index.html +0 -13
- package/test/resources/static/sub/index.html +0 -13
- package/test/resources/static/sub/other.html +0 -13
- package/test/resources/test.route.comment.ts +0 -58
- package/test/resources/test.route.empty.ts +0 -9
- package/test/responses.test.ts +0 -483
- package/test/routeFiles.test.ts +0 -239
- package/test/router.test.ts +0 -231
- package/test/test.utils.ts +0 -109
- package/test/types.test.ts +0 -909
- package/tsconfig.json +0 -23
package/docs/getting-started.md
DELETED
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
# Getting Started
|
|
2
|
-
|
|
3
|
-
Galbe is a JavaScript web framework for building fast and versatile backend servers with Bun.
|
|
4
|
-
|
|
5
|
-
Designed for simplicity, Galbe allows you to quickly create and configure a project. In addition to its ease of use, it offers various features that help you focus on your application's core logic.
|
|
6
|
-
|
|
7
|
-
## Requirements
|
|
8
|
-
|
|
9
|
-
To start developing with Galbe, you first need to install [Bun](https://bun.sh).
|
|
10
|
-
|
|
11
|
-
## Automatic Installation (Recommended)
|
|
12
|
-
|
|
13
|
-
This is the recommended way to set up a Galbe project.
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
$ bun create galbe app
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
The Galbe starter CLI will prompt you to choose a template and a target language. Select `hello` as the template and `typescript` as the language. This will create a new project in the `app` directory.
|
|
20
|
-
|
|
21
|
-
Now, navigate to your newly created project and install dependencies:
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
$ cd app
|
|
25
|
-
$ bun i
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
Start the development server by running:
|
|
29
|
-
|
|
30
|
-
```bash
|
|
31
|
-
$ bun dev
|
|
32
|
-
🏗️ Constructing routes
|
|
33
|
-
|
|
34
|
-
hello.route.ts
|
|
35
|
-
[GET] /hello/:name Greeting endpoint
|
|
36
|
-
|
|
37
|
-
done
|
|
38
|
-
|
|
39
|
-
🚀 Server running at http://localhost:3000
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
Try accessing the hello endpoint:
|
|
43
|
-
|
|
44
|
-
```bash
|
|
45
|
-
$ curl localhost:3000/hello/John?age=32
|
|
46
|
-
Hello John! You're 32 y.o.
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
> [!TIP]
|
|
50
|
-
> To explore more of Galbe's capabilities, check out the `demo` template in the Galbe starter CLI.
|
|
51
|
-
|
|
52
|
-
## Manual Installation
|
|
53
|
-
|
|
54
|
-
Initialize a new Bun project and add Galbe as a dependency:
|
|
55
|
-
|
|
56
|
-
```bash
|
|
57
|
-
$ bun init
|
|
58
|
-
$ bun add galbe
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
Open `package.json` and add the following scripts:
|
|
62
|
-
|
|
63
|
-
```json
|
|
64
|
-
{
|
|
65
|
-
"scripts": {
|
|
66
|
-
"dev": "galbe dev index.ts -w .",
|
|
67
|
-
"build": "galbe build index.ts",
|
|
68
|
-
"test": "bun test"
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
These scripts use the Galbe CLI to run and build the application. More details are available in the [CLI](cli.md) section.
|
|
74
|
-
|
|
75
|
-
Your `index.ts` file must export a default Galbe instance:
|
|
76
|
-
|
|
77
|
-
```ts
|
|
78
|
-
import { Galbe } from "galbe"
|
|
79
|
-
|
|
80
|
-
const galbe = new Galbe({ port: 3000 })
|
|
81
|
-
galbe.get("/hello", () => "Hello Mom!")
|
|
82
|
-
|
|
83
|
-
export default galbe
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
This approach is recommended but not mandatory. Galbe instances also provide a `listen` method, allowing you to manually start your server from within your code.
|
|
87
|
-
|
|
88
|
-
> [!WARNING]
|
|
89
|
-
> If you choose not to use the Galbe CLI for running or building your app, you will not have access to features such as the [Automatic Route Analyzer](routes.md#automatic-route-analyzer).
|
|
90
|
-
|
|
91
|
-
## Project Structure
|
|
92
|
-
|
|
93
|
-
Galbe is highly flexible in terms of project structure. The [Automatic Route Analyzer](routes.md#automatic-route-analyzer), triggered by the `routes` configuration option (default: `src/**/*.route.{js,ts}`), enables versatile project organization.
|
|
94
|
-
|
|
95
|
-
Here are two examples of valid project structures:
|
|
96
|
-
|
|
97
|
-
**Example 1**
|
|
98
|
-
|
|
99
|
-
```txt
|
|
100
|
-
┌── src
|
|
101
|
-
│ ├── hooks
|
|
102
|
-
│ │ └── log.hook.ts
|
|
103
|
-
│ ├── routes
|
|
104
|
-
│ │ ├── foo.route.ts
|
|
105
|
-
│ │ └── bar.route.ts
|
|
106
|
-
│ └── schemas
|
|
107
|
-
│ ├── foo.schema.ts
|
|
108
|
-
│ └── bar.schema.ts
|
|
109
|
-
├── galbe.config.ts
|
|
110
|
-
├── index.ts
|
|
111
|
-
├── package.json
|
|
112
|
-
├── README.md
|
|
113
|
-
└── tsconfig.json
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
**Example 2**
|
|
117
|
-
|
|
118
|
-
```txt
|
|
119
|
-
┌── src
|
|
120
|
-
│ ├── hooks
|
|
121
|
-
│ │ └── log.hook.ts
|
|
122
|
-
│ ├── foo
|
|
123
|
-
│ │ ├── foo.route.ts
|
|
124
|
-
│ │ └── foo.schema.ts
|
|
125
|
-
│ └── bar
|
|
126
|
-
│ ├── bar.route.ts
|
|
127
|
-
│ └── bar.schema.ts
|
|
128
|
-
├── galbe.config.ts
|
|
129
|
-
├── index.ts
|
|
130
|
-
├── package.json
|
|
131
|
-
├── README.md
|
|
132
|
-
└── tsconfig.json
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
In both cases, the [Automatic Route Analyzer](routes.md#automatic-route-analyzer) will detect `foo.route.ts` and `bar.route.ts` to set up route definitions.
|
|
136
|
-
|
|
137
|
-
For more details, see the [Route Files](routes.md#route-files) section.
|
|
138
|
-
|
|
139
|
-
> [!NOTE]
|
|
140
|
-
> These examples work with the default configuration, but you can customize the `routes` property to fit your project structure. Define `routes` with your preferred pattern(s) to match your file organization.
|
|
141
|
-
|
|
142
|
-
## Debugging
|
|
143
|
-
|
|
144
|
-
The easiest way to debug your application is by using the [VSCode Bun extension](https://marketplace.visualstudio.com/items?itemName=oven.bun-vscode).
|
|
145
|
-
|
|
146
|
-
Create a `.vscode/launch.json` configuration file in your project root with the following content:
|
|
147
|
-
|
|
148
|
-
```json
|
|
149
|
-
{
|
|
150
|
-
"version": "0.2.0",
|
|
151
|
-
"configurations": [
|
|
152
|
-
{
|
|
153
|
-
"type": "bun",
|
|
154
|
-
"request": "launch",
|
|
155
|
-
"name": "Debug Galbe",
|
|
156
|
-
"program": "node_modules/galbe/bin/cli.ts",
|
|
157
|
-
"env": { "TERM": "xterm" },
|
|
158
|
-
"cwd": "${workspaceFolder}",
|
|
159
|
-
"runtime": "bun",
|
|
160
|
-
"runtimeArgs": ["dev", "index.ts", "-w", "."]
|
|
161
|
-
}
|
|
162
|
-
]
|
|
163
|
-
}
|
|
164
|
-
```
|
package/docs/handler.md
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
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 the last argument of the [Route Definition](routes.md#route-definition) method.
|
|
8
|
-
|
|
9
|
-
```js
|
|
10
|
-
galbe.get('foo', schema, [hook1, hook2], ctx => {})
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
Handlers 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](https://galbe.dev/documentation/lifecycle) 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 its 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 information 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 covers 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 a `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 { message: '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 this case, `context.set` properties are not taken into account to construct 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
|
-
```
|
|
106
|
-
|
|
107
|
-
## Throwing Errors
|
|
108
|
-
|
|
109
|
-
Throwing a `RequestError` at any point in the handler execution will result in a response with the specified status and payload.
|
|
110
|
-
|
|
111
|
-
#### Example
|
|
112
|
-
|
|
113
|
-
```ts
|
|
114
|
-
g.get("/test", () => {
|
|
115
|
-
throw new RequestError({ status: 418, payload: '🫖' })
|
|
116
|
-
})
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
Any other kind of error will result in a `500` response with the error message `"Internal Server Error"` by default. You can always customize it by defining a custom [Error Handler](error-handler.md).
|
package/docs/hooks.md
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
# Hooks
|
|
2
|
-
|
|
3
|
-
Hooks provide a simple way to execute specific actions before and/or after reaching a route endpoint in Galbe.
|
|
4
|
-
|
|
5
|
-
## Defining Hooks
|
|
6
|
-
|
|
7
|
-
```ts
|
|
8
|
-
const hook = async (context, next) => {
|
|
9
|
-
context.state['foo'] = 'bar'
|
|
10
|
-
await next()
|
|
11
|
-
console.log('Hook end')
|
|
12
|
-
}
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
A hook takes two arguments: `context` and `next`.
|
|
16
|
-
|
|
17
|
-
### context
|
|
18
|
-
|
|
19
|
-
The `context` object contains request information and a modifiable `state` property that persists across all hooks and the handler. This is useful for sharing data across hooks and handlers. More details are available in the [Context](context.md) section.
|
|
20
|
-
|
|
21
|
-
### next
|
|
22
|
-
|
|
23
|
-
The `next` function calls the next hook in the list, or the handler if the current hook is the last one. The `next` function should be called at most once. If omitted, Galbe will automatically call it at the end of the current hook’s execution.
|
|
24
|
-
|
|
25
|
-
> [!TIP]
|
|
26
|
-
> Hooks are interruptible, meaning they can return a response at any time. This is useful for implementing custom logic such as authentication, authorization, and caching.
|
|
27
|
-
>
|
|
28
|
-
> For more details on response handling, see [Response Types](handler.md#response-types).
|
|
29
|
-
|
|
30
|
-
## Declaring Hooks
|
|
31
|
-
|
|
32
|
-
Hooks should be declared before the handler method in the [Route Definition](routes.md#route-definition) as a list of hook functions.
|
|
33
|
-
|
|
34
|
-
```ts
|
|
35
|
-
galbe.get('/foo', [hook1, hook2, ...], ctx => {})
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
Hooks execute in the order they are declared, just before the [Handler](handler.md). For a deeper understanding of their execution in the request lifecycle, see the [Lifecycle](https://galbe.dev/documentation/lifecycle) section.
|
|
39
|
-
|
|
40
|
-
### Examples
|
|
41
|
-
|
|
42
|
-
#### Linear Hook Execution
|
|
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 Hook Execution
|
|
65
|
-
|
|
66
|
-
```ts
|
|
67
|
-
const hook1 = async (context, next) => {
|
|
68
|
-
console.log('hook1 start')
|
|
69
|
-
await next()
|
|
70
|
-
console.log('hook1 end')
|
|
71
|
-
}
|
|
72
|
-
const hook2 = async (context, next) => {
|
|
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
DELETED
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
# Plugins
|
|
2
|
-
|
|
3
|
-
Galbe provides a powerful plugin system that allows developers to extend and customize the framework’s behavior. The plugin capabilities integrate with the [Request Lifecycle](https://galbe.dev/documentation/lifecycle).
|
|
4
|
-
|
|
5
|
-
## Definition
|
|
6
|
-
|
|
7
|
-
### Plugin Signature
|
|
8
|
-
|
|
9
|
-
```ts
|
|
10
|
-
type GalbePlugin = {
|
|
11
|
-
name: string
|
|
12
|
-
init?: (config: any, galbe: Galbe) => MaybePromise<void>
|
|
13
|
-
onFetch?: (context: Context) => MaybePromise<Response | void>
|
|
14
|
-
onRoute?: (context: Context) => MaybePromise<Response | void>
|
|
15
|
-
beforeHandle?: (context: Context) => MaybePromise<Response | void>
|
|
16
|
-
afterHandle?: (response: Response, context: Context) => MaybePromise<Response | void>
|
|
17
|
-
}
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
### name
|
|
21
|
-
The plugin name should be a Unique Plugin Identifier to prevent conflicts with other plugins. Ideally, it follows the format `com.example.myplugin`.
|
|
22
|
-
|
|
23
|
-
### init
|
|
24
|
-
This method is called immediately after the server starts. It receives two arguments:
|
|
25
|
-
- `config`: The plugin-specific configuration (See [Configuration](getting-started.md#properties) `plugin` property).
|
|
26
|
-
- `galbe`: The Galbe server instance, from which you can retrieve routes using `galbe.router.routes`.
|
|
27
|
-
|
|
28
|
-
### onFetch
|
|
29
|
-
This method is executed at the beginning of an incoming request. It receives a `context` object representing the [Request Context](context.md).
|
|
30
|
-
|
|
31
|
-
It is **preemptable**, meaning that if a response is returned, it will be sent to the client immediately, bypassing further processing.
|
|
32
|
-
|
|
33
|
-
### onRoute
|
|
34
|
-
Executed after the router identifies a matching route for the request. It takes a `context` argument and is **preemptable**, meaning it can return an early response.
|
|
35
|
-
|
|
36
|
-
### beforeHandle
|
|
37
|
-
Runs after request validation but before route hooks and the handler are called. Like the previous lifecycle methods, it is **preemptable**.
|
|
38
|
-
|
|
39
|
-
### afterHandle
|
|
40
|
-
Called after the route handler is executed but before sending the response. It receives two arguments:
|
|
41
|
-
- `response`: The [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) object from the handler.
|
|
42
|
-
- `context`: The request [Context](context.md).
|
|
43
|
-
|
|
44
|
-
It is also **preemptable**, meaning any returned response will override the original handler response.
|
|
45
|
-
|
|
46
|
-
## Plugin Registration
|
|
47
|
-
|
|
48
|
-
To register a plugin with your Galbe server, use the `use` method on your Galbe instance.
|
|
49
|
-
|
|
50
|
-
```js
|
|
51
|
-
const galbe = new Galbe()
|
|
52
|
-
galbe.use(plugin)
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
## How to Create a Plugin
|
|
56
|
-
|
|
57
|
-
This section will walk you through the process of creating a plugin.
|
|
58
|
-
Before creating a plugin, don't forget to check if there's an existing plugin that can be used. You can take a look at the official [Plugin List](https://galbe.dev/plugins).
|
|
59
|
-
|
|
60
|
-
### 1. Scaffolding
|
|
61
|
-
|
|
62
|
-
The Galbe starter CLI provides a template for setting up a plugin project:
|
|
63
|
-
|
|
64
|
-
```bash
|
|
65
|
-
$ bun create galbe my-plugin --template plugin
|
|
66
|
-
$ cd my-plugin
|
|
67
|
-
$ bun install
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
### 2. Implementation
|
|
71
|
-
|
|
72
|
-
Below is an example of a plugin that handles routes tagged with `@deprecated` metadata (See [Route Files](routes.md#route-files) for metadata usage).
|
|
73
|
-
|
|
74
|
-
deprecated.plugin.ts
|
|
75
|
-
```ts
|
|
76
|
-
import type { GalbePlugin, Route } from 'galbe'
|
|
77
|
-
import { walkMetaRoutes } from 'galbe/utils'
|
|
78
|
-
|
|
79
|
-
const PLUGIN_ID = 'dev.galbe.deprecated'
|
|
80
|
-
|
|
81
|
-
export default (): GalbePlugin => {
|
|
82
|
-
let deprecateds = new Set<string>()
|
|
83
|
-
const isRouteDeprecated = (route?: Route) =>
|
|
84
|
-
deprecateds.has(JSON.stringify({ method: route?.method, path: route?.path }))
|
|
85
|
-
|
|
86
|
-
return {
|
|
87
|
-
name: PLUGIN_ID,
|
|
88
|
-
// Init the plugin, check for deprecated metadata tags
|
|
89
|
-
init(_config, galbe) {
|
|
90
|
-
walkMetaRoutes(galbe.meta || [], (method, path, meta) => {
|
|
91
|
-
if (meta.deprecated) deprecateds.add(JSON.stringify({ method, path }))
|
|
92
|
-
})
|
|
93
|
-
},
|
|
94
|
-
// Check if the current route is deprecated; if so, flag it as such and log it
|
|
95
|
-
onRoute(context) {
|
|
96
|
-
let r = context.route
|
|
97
|
-
if (isRouteDeprecated(r)) {
|
|
98
|
-
console.warn(`Call to deprecated route "${r?.method} ${r?.path}"`)
|
|
99
|
-
}
|
|
100
|
-
},
|
|
101
|
-
// Add a header to the response if the route has been flagged as deprecated
|
|
102
|
-
afterHandle(response, context) {
|
|
103
|
-
if (isRouteDeprecated(context.route)) {
|
|
104
|
-
response.headers.set('x-deprecated', 'true')
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
} as GalbePlugin
|
|
108
|
-
}
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
Register the plugin with your Galbe server:
|
|
112
|
-
|
|
113
|
-
```ts
|
|
114
|
-
import { Galbe } from 'galbe'
|
|
115
|
-
import deprecatedPlugin from './deprecated.plugin'
|
|
116
|
-
|
|
117
|
-
const galbe = new Galbe()
|
|
118
|
-
galbe.use(deprecatedPlugin())
|
|
119
|
-
|
|
120
|
-
export default galbe
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
### 3. Publishing
|
|
124
|
-
|
|
125
|
-
To submit your plugin to the [official plugin list](https://galbe.dev/plugins), follow these steps:
|
|
126
|
-
|
|
127
|
-
1. **Create a public GitHub repository** for your plugin, ensuring that the `README.md` includes:
|
|
128
|
-
- A clear description of your plugin.
|
|
129
|
-
- Installation and configuration instructions.
|
|
130
|
-
- Usage examples.
|
|
131
|
-
|
|
132
|
-
2. _(Optional)_ Publish your plugin to [NPM](https://npmjs.com).
|
|
133
|
-
|
|
134
|
-
3. **Submit a Pull Request** to add your plugin configuration to [plugins.json](https://github.com/pierre-cm/galbe-website/blob/main/plugins.json) in the following format:
|
|
135
|
-
|
|
136
|
-
```json
|
|
137
|
-
"plugin-id": {
|
|
138
|
-
"name": "Plugin Name",
|
|
139
|
-
"description": "Plugin description",
|
|
140
|
-
"repo": "https://github.com/<username>/<repo-name>",
|
|
141
|
-
"npm": "https://www.npmjs.com/package/<package-name>"
|
|
142
|
-
}
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
> [!IMPORTANT]
|
|
146
|
-
> Provide all relevant details in the Pull Request description. It will be reviewed by project maintainers as soon as possible. Check the [Galbe Contributing Guide](https://github.com/pierre-cm/galbe/blob/main/docs/CONTRIBUTING.md) before submitting.
|
package/docs/router.md
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
# Router
|
|
2
|
-
|
|
3
|
-
Galbe router employs a hybrid approach to store and locate routes.
|
|
4
|
-
|
|
5
|
-
The static routes are maintained in a Map structure. This ensures 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
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
# Routes
|
|
2
|
-
|
|
3
|
-
Routes serve as the entry points for handling client requests in a Galbe application. This section covers route definition, available configuration options, and the Automatic Route Analyzer, which simplifies route setup.
|
|
4
|
-
|
|
5
|
-
## Defining Routes
|
|
6
|
-
|
|
7
|
-
Here's how to define routes in Galbe:
|
|
8
|
-
|
|
9
|
-
```ts
|
|
10
|
-
galbe.[method](path: string, schema?: Schema, hooks?: Hooks[], handler: Handler)
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
- **method** (`get` | `post` | `put` | `delete` | `patch` | `options` | `head`)
|
|
14
|
-
- The [HTTP request method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) for the route.
|
|
15
|
-
|
|
16
|
-
- **path** (string)
|
|
17
|
-
- The URL path of the route, composed of segments separated by `/`. Each segment may contain alphanumeric characters and dashes but should not start or end with a dash.
|
|
18
|
-
- Special segments:
|
|
19
|
-
- `:param` → A segment starting with `:` represents a parameter.
|
|
20
|
-
- `*` → A wildcard segment matching any sequence of segments.
|
|
21
|
-
|
|
22
|
-
- **schema** (Schema) _(Optional)_
|
|
23
|
-
- See the [Schemas](schemas.md) section.
|
|
24
|
-
|
|
25
|
-
- **hooks** (Hook[]) _(Optional)_
|
|
26
|
-
- See the [Hooks](hooks.md) section.
|
|
27
|
-
|
|
28
|
-
- **handler** (Handler)
|
|
29
|
-
- See the [Handler](handler.md) section.
|
|
30
|
-
|
|
31
|
-
### Examples
|
|
32
|
-
|
|
33
|
-
#### Basic Route
|
|
34
|
-
|
|
35
|
-
```js
|
|
36
|
-
galbe.get('/foo', ctx => 'Hello, World!')
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
#### Route with a Schema
|
|
40
|
-
|
|
41
|
-
<!-- prettier-ignore -->
|
|
42
|
-
```js
|
|
43
|
-
galbe.get(
|
|
44
|
-
'/foo/:bar',
|
|
45
|
-
{ params: { bar: $T.string() } },
|
|
46
|
-
ctx => `Hello, ${ctx.params.bar}!`
|
|
47
|
-
)
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
#### Route with Hooks
|
|
51
|
-
|
|
52
|
-
<!-- prettier-ignore -->
|
|
53
|
-
```js
|
|
54
|
-
galbe.get(
|
|
55
|
-
'/foo/:bar',
|
|
56
|
-
[() => console.log('Hook1'), () => console.log('Hook2')],
|
|
57
|
-
ctx => `Hello, ${ctx.params.bar}!`
|
|
58
|
-
)
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
#### Route with Schemas and Hooks
|
|
62
|
-
|
|
63
|
-
<!-- prettier-ignore -->
|
|
64
|
-
```js
|
|
65
|
-
galbe.get(
|
|
66
|
-
'/foo/:bar',
|
|
67
|
-
{ params: { bar: $T.string() } },
|
|
68
|
-
[() => console.log('Hook')],
|
|
69
|
-
ctx => `Hello, ${ctx.params.bar}!`
|
|
70
|
-
)
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
## Defining Static Routes
|
|
74
|
-
|
|
75
|
-
Static routes serve files from the filesystem.
|
|
76
|
-
|
|
77
|
-
```ts
|
|
78
|
-
galbe.static(path: string, target: string, options?: StaticEndpointOptions)
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
- **path** (string): The URL path of the route.
|
|
82
|
-
|
|
83
|
-
- **target** (string): The path to the directory or file to serve.
|
|
84
|
-
|
|
85
|
-
- **options** (StaticEndpointOptions) _(Optional)_:
|
|
86
|
-
- **resolve** ((path: string, target: string) => string | null | undefined | void) _(Optional)_
|
|
87
|
-
A function that resolves the path to the file to serve. The function may return a string corresponding to the new target.
|
|
88
|
-
|
|
89
|
-
### Examples
|
|
90
|
-
|
|
91
|
-
<!-- prettier-ignore -->
|
|
92
|
-
```js
|
|
93
|
-
galbe.static('/static', './public')
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
## Automatic Route Analyzer
|
|
97
|
-
|
|
98
|
-
> [!NOTE]
|
|
99
|
-
> This feature is only available if you run or build the app using the [Galbe CLI](getting-started.md#galbe-cli). The CLI is used by default if you followed the [Automatic Installation](getting-started.md#automatic-installation) or configured `package.json` accordingly.
|
|
100
|
-
|
|
101
|
-
The Automatic Route Analyzer scans all Route Files in your project and sets up route definitions automatically. By default, it looks for files matching `src/**/*.route.{js,ts}`. This behavior can be customized via the `routes` property in your Galbe configuration. Setting it to `false` disables the analyzer.
|
|
102
|
-
|
|
103
|
-
### Route Files
|
|
104
|
-
|
|
105
|
-
To be analyzed correctly, a Route File must export a default function that accepts a Galbe instance as its only argument. Define your routes within this function. Example in JavaScript:
|
|
106
|
-
|
|
107
|
-
```ts
|
|
108
|
-
export default g => {
|
|
109
|
-
g.get('/foo/:bar', ctx => ctx.params.bar)
|
|
110
|
-
}
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
The Automatic Route Analyzer can also extract metadata from multiline comments. Some plugins utilize this metadata for specific tasks. Example:
|
|
114
|
-
|
|
115
|
-
```js
|
|
116
|
-
/**
|
|
117
|
-
* Header metadata description
|
|
118
|
-
* @annotation Example of a header annotation
|
|
119
|
-
*/
|
|
120
|
-
export default g => {
|
|
121
|
-
/**
|
|
122
|
-
* Route-specific metadata
|
|
123
|
-
* @deprecated
|
|
124
|
-
* @operationId fooBar
|
|
125
|
-
* @tags tag1 tag2
|
|
126
|
-
*/
|
|
127
|
-
g.get('/foo/:bar', ctx => ctx.params.bar)
|
|
128
|
-
}
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
> [!TIP]
|
|
132
|
-
> To exclude a route from analysis, add `//@galbe-ignore` before its definition. This is useful for preventing certain routes from being included in automatic analysis or documentation generation.
|
|
133
|
-
|