galbe 0.10.0 → 0.11.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/docs/plugins.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Plugins
2
2
 
3
- Galbe provides a powerful plugin system that allows developers to extend and customize the behavior of the framework. The plugin capabilities are centered around the [Request Lifecycle](https://galbe.dev/documentation/lifecycle).
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
4
 
5
5
  ## Definition
6
6
 
7
- ### Signature
7
+ ### Plugin Signature
8
8
 
9
9
  ```ts
10
10
  type GalbePlugin = {
@@ -17,52 +17,49 @@ type GalbePlugin = {
17
17
  }
18
18
  ```
19
19
 
20
- **name**
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`.
21
22
 
22
- The name should be a Unique Plugin Identifier. It should be chosen to be unique to avoid conflicts with other potential plugins. Ideally, it will have the form of `com.example.myplugin`.
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`.
23
27
 
24
- **init**
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).
25
30
 
26
- This method is called right after the server starts. It takes two arguments: a `config` and a `galbe` instance. The `config` holds the configuration for the specific scope of the current plugin (See [Configuration](getting-started.md#properties) `plugin` property for more details). The `galbe` argument is the instance of the current server; you can for instance retrieve the current routes definitions with `galbe.router.routes`.
31
+ It is **preemptable**, meaning that if a response is returned, it will be sent to the client immediately, bypassing further processing.
27
32
 
28
- **onFetch**
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.
29
35
 
30
- This method is called at the beginning of an incoming request. It takes a single `context` argument representing the current request [Context](context.md).
36
+ ### beforeHandle
37
+ Runs after request validation but before route hooks and the handler are called. Like the previous lifecycle methods, it is **preemptable**.
31
38
 
32
- It is preemptable, meaning that any returned value will be interpreted as a response to send back to the client. Therefore, the method should only return [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) instances or nothing.
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).
33
43
 
34
- **onRoute**
44
+ It is also **preemptable**, meaning any returned response will override the original handler response.
35
45
 
36
- This method is called after the router has found a matching route for the current request. Its takes a single `context` argument representing the current request [Context](context.md).
46
+ ## Plugin Registration
37
47
 
38
- It is preemptable, meaning that any returned value will be interpreted as a response to send back to the client. Therefore, the method should only return [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) instances or nothing.
39
-
40
- **beforeHandle**
41
-
42
- This method is called after the request has been validated and before the route hooks and the handler are called. It takes a single `context` argument representing the current request [Context](context.md).
43
-
44
- It is preemptable, meaning that any returned value will be interpreted as a response to send back to the client. Therefore, the method should only return [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) instances or nothing.
45
-
46
- **afterHandle**
47
-
48
- This method is called after the route handler has been called and before the response is sent. Its takes two arguments: a `response` object containing the [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) returned by the handler, and a `context` argument representing the current request [Context](context.md).
49
-
50
- It is preemptable, meaning that any returned value will be interpreted as a response to send back to the client. Therefore, the method should only return [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) instances or nothing.
51
-
52
- ### Usage
53
-
54
- To register a plugin with your Galbe server, you must use the `use` method from you galbe instance.
48
+ To register a plugin with your Galbe server, use the `use` method on your Galbe instance.
55
49
 
56
50
  ```js
57
51
  const galbe = new Galbe()
58
52
  galbe.use(plugin)
59
53
  ```
60
54
 
61
- ## Create a plugin
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).
62
59
 
63
60
  ### 1. Scaffolding
64
61
 
65
- The Galbe starter CLI provides a template that can be used to setup a Galbe plugin project.
62
+ The Galbe starter CLI provides a template for setting up a plugin project:
66
63
 
67
64
  ```bash
68
65
  $ bun create galbe my-plugin --template plugin
@@ -70,45 +67,40 @@ $ cd my-plugin
70
67
  $ bun install
71
68
  ```
72
69
 
73
- Now you should be ready to start developing your plugin. Following section will present an example of a plugin implementation.
74
-
75
70
  ### 2. Implementation
76
71
 
77
- Here is an example of a plugin implementation that handles routes tagged with `@deprecated` metadata (See [Route files](routes.md#route-files) section about metadata).
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).
78
73
 
79
74
  deprecated.plugin.ts
80
-
81
75
  ```ts
82
- import type { GalbePlugin } from 'galbe'
76
+ import type { GalbePlugin, Route } from 'galbe'
83
77
  import { walkMetaRoutes } from 'galbe/utils'
84
78
 
85
79
  const PLUGIN_ID = 'dev.galbe.deprecated'
86
80
 
87
- export default () => {
81
+ export default (): GalbePlugin => {
88
82
  let deprecateds = new Set<string>()
83
+ const isRouteDeprecated = (route?: Route) =>
84
+ deprecateds.has(JSON.stringify({ method: route?.method, path: route?.path }))
85
+
89
86
  return {
90
87
  name: PLUGIN_ID,
91
88
  // Init the plugin, check for deprecated metadata tags
92
89
  init(_config, galbe) {
93
- if (galbe.meta) {
94
- walkMetaRoutes(galbe.meta, (method, path, meta) => {
95
- if (meta.deprecated) deprecateds.add(JSON.stringify({ method, path }))
96
- })
97
- }
90
+ walkMetaRoutes(galbe.meta || [], (method, path, meta) => {
91
+ if (meta.deprecated) deprecateds.add(JSON.stringify({ method, path }))
92
+ })
98
93
  },
99
94
  // Check if the current route is deprecated; if so, flag it as such and log it
100
95
  onRoute(context) {
101
96
  let r = context.route
102
- if (!r) return
103
- if (deprecateds.has(JSON.stringify({ method: r.method, path: r.path }))) {
104
- console.warn(`Call to deprecated route "${r.method} ${r.path}"`)
97
+ if (isRouteDeprecated(r)) {
98
+ console.warn(`Call to deprecated route "${r?.method} ${r?.path}"`)
105
99
  }
106
100
  },
107
101
  // Add a header to the response if the route has been flagged as deprecated
108
102
  afterHandle(response, context) {
109
- let r = context.route
110
- if (!r) return
111
- if (deprecateds.has(JSON.stringify({ method: r.method, path: r.path }))) {
103
+ if (isRouteDeprecated(context.route)) {
112
104
  response.headers.set('x-deprecated', 'true')
113
105
  }
114
106
  }
@@ -116,6 +108,8 @@ export default () => {
116
108
  }
117
109
  ```
118
110
 
111
+ Register the plugin with your Galbe server:
112
+
119
113
  ```ts
120
114
  import { Galbe } from 'galbe'
121
115
  import deprecatedPlugin from './deprecated.plugin'
@@ -128,26 +122,25 @@ export default galbe
128
122
 
129
123
  ### 3. Publishing
130
124
 
131
- If you want to submit your plugin to the [official plugin list](https://galbe.dev/plugins), you should follow these steps:
132
-
133
- 1. Create a **public** Github repository for your plugin. Make sure to include the following information in the README at the root of your repository:
125
+ To submit your plugin to the [official plugin list](https://galbe.dev/plugins), follow these steps:
134
126
 
135
- - A description of your plugin and what it does.
136
- - How to install and configure it.
137
- - How to use it.
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.
138
131
 
139
- 2. (_Optional_) Publish your plugin to [NPM](https://npmjs.com).
132
+ 2. _(Optional)_ Publish your plugin to [NPM](https://npmjs.com).
140
133
 
141
- 3. Create a Pull Request adding your plugin config to [plugins.json](https://github.com/pierre-cm/galbe-website/blob/main/plugins.json) file. The config should be in the following format:
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:
142
135
 
143
136
  ```json
144
137
  "plugin-id": {
145
138
  "name": "Plugin Name",
146
139
  "description": "Plugin description",
147
140
  "repo": "https://github.com/<username>/<repo-name>",
148
- "npm": "https://www.npmjs.com/package/<package-name>",
141
+ "npm": "https://www.npmjs.com/package/<package-name>"
149
142
  }
150
143
  ```
151
144
 
152
145
  > [!IMPORTANT]
153
- > Please provide any relevent information about the plugin in the Pull Request description. It will be reviewed by the project maintainers as soon as possible. Be sure to check the [Glabe Contributing Guide](https://github.com/pierre-cm/galbe/blob/main/docs/CONTRIBUTING.md) before submitting any request. Same rules will apply here.
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 CHANGED
@@ -1,8 +1,8 @@
1
1
  # Router
2
2
 
3
- Galbe router employs a hybrid approach to store and locating routes.
3
+ Galbe router employs a hybrid approach to store and locate routes.
4
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)`.
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
6
 
7
7
  > [!NOTE]
8
8
  > A static route is a route that doesn't contain any parameter (e.g.,`:param`) or wildcards `*`.
package/docs/routes.md CHANGED
@@ -1,71 +1,64 @@
1
1
  # Routes
2
2
 
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.
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
4
 
5
- ## Route definition
5
+ ## Defining Routes
6
6
 
7
- Here is how to define routes in Galbe.
7
+ Here's how to define routes in Galbe:
8
8
 
9
9
  ```ts
10
10
  galbe.[method](path: string, schema?: Schema, hooks?: Hooks[], handler: Handler)
11
11
  ```
12
12
 
13
- **method** ( get | post | put | delete | patch | options | head )
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.
14
15
 
15
- The [HTTP Request Method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) for the defined route.
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.
16
21
 
17
- **path** (string)
22
+ - **schema** (Schema) _(Optional)_
23
+ - See the [Schemas](schemas.md) section.
18
24
 
19
- The path of the route. It should be composed of a sequence of segments separated by `/`. Each segment can be composed alphanumeric characters and dashes, but should not start or end with a dash.
25
+ - **hooks** (Hook[]) _(Optional)_
26
+ - See the [Hooks](hooks.md) section.
20
27
 
21
- There are two special segments:
22
-
23
- - `:param` Any segment starting with `:` indicates a parameter segment.
24
- - `*` To indicate a wildcard segment. This will match any segment or sequence of segments.
25
-
26
- **schema** (Schema) _Optional_
27
-
28
- See [Schemas](schemas.md) section.
29
-
30
- **hooks** (Hook[]) _Optional_
31
-
32
- See [Hooks](hooks.md) section.
33
-
34
- **handler** (Handler)
35
-
36
- See [Handler](handler.md) section.
28
+ - **handler** (Handler)
29
+ - See the [Handler](handler.md) section.
37
30
 
38
31
  ### Examples
39
32
 
40
- **Basic route**
33
+ #### Basic Route
41
34
 
42
35
  ```js
43
- galbe.get('/foo', ctx => 'Hello World!')
36
+ galbe.get('/foo', ctx => 'Hello, World!')
44
37
  ```
45
38
 
46
- **Route with Schema**
39
+ #### Route with a Schema
47
40
 
48
41
  <!-- prettier-ignore -->
49
42
  ```js
50
43
  galbe.get(
51
44
  '/foo/:bar',
52
45
  { params: { bar: $T.string() } },
53
- ctx => `Hello ${ctx.params.bar} !`
46
+ ctx => `Hello, ${ctx.params.bar}!`
54
47
  )
55
48
  ```
56
49
 
57
- **Route with Hooks**
50
+ #### Route with Hooks
58
51
 
59
52
  <!-- prettier-ignore -->
60
53
  ```js
61
54
  galbe.get(
62
55
  '/foo/:bar',
63
56
  [() => console.log('Hook1'), () => console.log('Hook2')],
64
- ctx => `Hello ${ctx.params.bar} !`
57
+ ctx => `Hello, ${ctx.params.bar}!`
65
58
  )
66
59
  ```
67
60
 
68
- **Route with Schemas and Hooks**
61
+ #### Route with Schemas and Hooks
69
62
 
70
63
  <!-- prettier-ignore -->
71
64
  ```js
@@ -73,20 +66,43 @@ galbe.get(
73
66
  '/foo/:bar',
74
67
  { params: { bar: $T.string() } },
75
68
  [() => console.log('Hook')],
76
- ctx => `Hello ${ctx.params.bar} !`
69
+ ctx => `Hello, ${ctx.params.bar}!`
77
70
  )
78
71
  ```
79
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
+
80
96
  ## Automatic Route Analyzer
81
97
 
82
98
  > [!NOTE]
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.
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.
84
100
 
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 route analyzer.
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.
86
102
 
87
103
  ### Route Files
88
104
 
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:
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:
90
106
 
91
107
  ```ts
92
108
  export default g => {
@@ -94,16 +110,16 @@ export default g => {
94
110
  }
95
111
  ```
96
112
 
97
- 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:
113
+ The Automatic Route Analyzer can also extract metadata from multiline comments. Some plugins utilize this metadata for specific tasks. Example:
98
114
 
99
115
  ```js
100
116
  /**
101
- * This is the header's head comment
102
- * @annotation example of header's annotation
117
+ * Header metadata description
118
+ * @annotation Example of a header annotation
103
119
  */
104
120
  export default g => {
105
121
  /**
106
- * This is a route head comment
122
+ * Route-specific metadata
107
123
  * @deprecated
108
124
  * @operationId fooBar
109
125
  * @tags tag1 tag2
@@ -113,4 +129,5 @@ export default g => {
113
129
  ```
114
130
 
115
131
  > [!TIP]
116
- > You can ignore a specific route from being analyzed by adding a `//@galbe-ignore` comment before the route definition. This is useful if you want to exclude certain routes from automatic analysis or documentation generation.
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
+