galbe 0.1.4 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,39 @@
1
+ name: Release
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ scope:
7
+ description: 'Version bump scope (patch, minor, major)'
8
+ required: true
9
+
10
+ jobs:
11
+ release:
12
+ runs-on: ubuntu-latest
13
+ env:
14
+ GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
15
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
16
+ RELEASE_SCOPE: ${{ github.event.inputs.scope }}
17
+ steps:
18
+ - name: Checkout repository
19
+ uses: actions/checkout@v4
20
+ - name: Setup Bun
21
+ uses: oven-sh/setup-bun@v1
22
+ with:
23
+ bun-version: latest
24
+ registry-url: https://registry.npmjs.org
25
+ - name: Setup SSH
26
+ uses: webfactory/ssh-agent@v0.8.0
27
+ with:
28
+ ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
29
+ - name: Setup Git
30
+ run: |
31
+ git config user.email "${GITHUB_ACTOR}@users.noreply.github.com"
32
+ git config user.name "${GITHUB_ACTOR}"
33
+ - name: Install dependencies & build
34
+ run: |
35
+ bun install & bun run build
36
+ - name: Release
37
+ run: |
38
+ npm config set //registry.npmjs.org/:_authToken $NPM_TOKEN
39
+ bun run release --increment $RELEASE_SCOPE --ci --no-git.requireCleanWorkingDir
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Galbe
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1 +1,22 @@
1
1
  # Galbe
2
+
3
+ [![Build & Test](https://github.com/pierre-cm/galbe/actions/workflows/build_test.yml/badge.svg?branch=main)](https://github.com/pierre-cm/galbe/actions/workflows/build_test.yml)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/pierre-cm/galbe/blob/main/LICENSE)
5
+ [![npm](https://img.shields.io/npm/v/galbe)](https://www.npmjs.com/package/galbe)
6
+
7
+ Galbe is a fast, lightweight and highly customizable JavaScript web framework based on [Bun](https://bun.sh).
8
+
9
+ > [!IMPORTANT]
10
+ > Galbe is currently under active development and not guaranteed to be stable. Future releases may potentially introduce breaking changes.
11
+
12
+ ## Getting started
13
+
14
+ ```bash
15
+ bun create galbe
16
+ ```
17
+
18
+ ## Documentation
19
+
20
+ The detailed documentation is available at [galbe.dev](https://galbe.dev).
21
+
22
+ ## Contributing
package/bin/cli.ts CHANGED
@@ -5,7 +5,7 @@ import type { RouteMeta } from '../src/routes'
5
5
  import { program } from 'commander'
6
6
  import { relative, resolve } from 'path'
7
7
  import { mkdir, readdir, lstat, rm } from 'fs/promises'
8
- import { metaAnalysis } from '../src/routes'
8
+ import { DEFAULT_ROUTE_PATTERN, metaAnalysis } from '../src/routes'
9
9
  import { randomUUID } from 'crypto'
10
10
  import { Galbe } from '../src'
11
11
 
@@ -14,7 +14,8 @@ const BUILD_ID = randomUUID()
14
14
 
15
15
  Bun.env.FORCE_COLOR = '1'
16
16
 
17
- const parseRoutes = async (routes?: string | string[]): Promise<{ path: string; meta: RouteMeta }[]> => {
17
+ const parseRoutes = async (routes?: boolean | string | string[]): Promise<{ path: string; meta: RouteMeta }[]> => {
18
+ routes = routes === true ? DEFAULT_ROUTE_PATTERN : routes
18
19
  if (!routes) return []
19
20
  let files: { path: string; meta: RouteMeta }[] = []
20
21
  if (typeof routes === 'string') {
@@ -61,11 +62,12 @@ program.name('galbe').description('CLI to execute galbe utilities').version('0.1
61
62
 
62
63
  program
63
64
  .command('dev')
64
- .description('Run a dev server running your galbe API')
65
+ .description('Start a dev server running your Galbe application')
65
66
  .argument('<string>', 'filename')
66
67
  .option('-p, --port <number>', 'port number', '')
68
+ .option('-w, --watch', 'watch file changes', 'true')
67
69
  .action(async (fileName, props) => {
68
- const { port } = props
70
+ const { port, watch } = props
69
71
  const devRoot = resolve(ROOT, '.galbe', 'dev')
70
72
  await mkdir(devRoot, { recursive: true })
71
73
  await Bun.write(
@@ -76,15 +78,15 @@ program
76
78
  await rm(resolve(ROOT, '.galbe', 'dev'), { recursive: true })
77
79
  })
78
80
 
79
- await $`BUN_ENV=development bun run --watch ${resolve(devRoot, 'index.ts')}`.cwd(ROOT)
81
+ await $`BUN_ENV=development bun run ${watch ? '--watch' : ''} ${resolve(devRoot, 'index.ts')}`.cwd(ROOT)
80
82
  })
81
83
 
82
84
  program
83
85
  .command('build')
84
- .description('Build your galbe API')
86
+ .description('undle your Galbe application')
85
87
  .argument('<string>', 'filename')
86
- .option('-o, --out <string>', 'output file', '')
87
- .option('-c, --compile', 'standalone executable', false)
88
+ .option('-o, --out <string>', 'output file/directory', '')
89
+ .option('-c, --compile', 'create a standalone executable', false)
88
90
  .action(async (fileName, props) => {
89
91
  const { out, compile } = props
90
92
  const g: Galbe = (await import(resolve(ROOT, fileName))).default
@@ -97,7 +99,7 @@ program
97
99
  buildIndex,
98
100
  '--target',
99
101
  'bun',
100
- ...(compile ? ['--compile', '--outfile', out ? out : 'api'] : ['--outdir', out ? out : 'dist'])
102
+ ...(compile ? ['--compile', '--outfile', out ? out : 'app'] : ['--outdir', out ? out : 'dist'])
101
103
  ].filter(c => c)
102
104
  Bun.spawn(cmds, {
103
105
  cwd: ROOT,
package/bun.lockb CHANGED
Binary file
package/bunfig.toml ADDED
@@ -0,0 +1,2 @@
1
+ [install]
2
+ registry = "https://registry.npmjs.org/"
@@ -1,5 +1,223 @@
1
- ### Create a project
1
+ # Getting started
2
2
 
3
- ```shell
4
- bun create pierre-cm/create-galbe
3
+ Galbe is a Javascript web framework to build fast and versatile backend servers with Bun.
4
+
5
+ It was designed with simplicity in mind, allowing you to quickly create and setup a project. In addition, Galbe also offers usefull features, allowing you to focus on your application logic rather than the rest.
6
+
7
+ ## Requirements
8
+
9
+ To start developing your Galbe project, you first need to install [Bun](https://bun.sh).
10
+
11
+ ## Automatic Installation
12
+
13
+ This is the recommended way of setting up a Galbe project.
14
+
15
+ ```bash
16
+ bun create galbe app
17
+ cd app
18
+ bun install
5
19
  ```
20
+
21
+ This will create a new project under `app` directory and install it.
22
+
23
+ Now you can start the dev server by running:
24
+
25
+ ```bash
26
+ bun dev
27
+ ```
28
+
29
+ This will start a web server on `loclahost:3000`.
30
+
31
+ To verify that the project was setup correctly and is running, try to reach `loclahost:3000/hello` endpoint, this should return following greeting message:
32
+
33
+ ```bash
34
+ $ curl localhost:3000/hello
35
+ Hello from Galbe!
36
+ ```
37
+
38
+ > [!TIP]
39
+ > By default, the dev server automatically reloads on every file change.
40
+
41
+ ## Manual Installation
42
+
43
+ Init a new Bun project and add Galbe as dependency:
44
+
45
+ ```bash
46
+ bun init
47
+ bun add galbe
48
+ ```
49
+
50
+ Open `package.json` file and add the following scripts:
51
+
52
+ ```json
53
+ {
54
+ "scripts": {
55
+ "dev": "galbe dev index.ts",
56
+ "build": "galbe build index.ts",
57
+ "test": "bun test"
58
+ }
59
+ }
60
+ ```
61
+
62
+ As you can see, those scripts rely on Galbe CLI to run and build the application. You will find more info about Galbe CLI available options in the next section [Galbe CLI](#galbe-cli).
63
+
64
+ This require your `index.ts` to export a default Galbe instance in order to work. As in the following example:
65
+
66
+ ```ts
67
+ import { Galbe } from 'galbe'
68
+
69
+ const g = new Galbe({ port: 3000 })
70
+ g.get('/hello', () => 'Hello Mom!')
71
+
72
+ export default galbe
73
+ ```
74
+
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
+
77
+ > [!WARNING]
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
+
80
+ ### Galbe CLI
81
+
82
+ ```bash
83
+ galbe <command> <argument> [options]
84
+ ```
85
+
86
+ Here are the available commands:
87
+
88
+ #### dev
89
+
90
+ Start a dev server running your Galbe application.
91
+
92
+ _argument_
93
+
94
+ The path of the file exporting your Galbe instance
95
+
96
+ _options_
97
+
98
+ - `--port` or `-p`: port number (default: 3000)
99
+ - `--watch` or `-w`: watch file changes (default: true)
100
+
101
+ #### build
102
+
103
+ Bundle your Galbe application.
104
+
105
+ _argument_
106
+
107
+ The path of the file exporting your Galbe instance
108
+
109
+ _options_
110
+
111
+ - `--out` or `-o`: output file | directory (default: app | dist )
112
+ - `--compile` or `-c`: create a standalone executable (default: false)
113
+
114
+ ## Configuration
115
+
116
+ To configure your Galbe server, you should pass your configuration to the Galbe constructor when you instanciate it.
117
+
118
+ ```ts
119
+ const galbe = new Galbe(configuration)
120
+ ```
121
+
122
+ ### Properties
123
+
124
+ #### port
125
+
126
+ The port number that the server will be listening on. Default is `3000`.
127
+
128
+ #### basePath
129
+
130
+ The base path is added as a prefix to all the routes created.
131
+
132
+ #### routes
133
+
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
+
136
+ #### plugin
137
+
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
+
140
+ ### Examples
141
+
142
+ An common way to handle server configuration is to create new file a `galbe.config.(js|ts|json)` at the root of your project directory and import it in your code. Here is an example:
143
+
144
+ galbe.config.js
145
+
146
+ ```js
147
+ export default {
148
+ port: Bun.env.GALBE_PORT
149
+ routes: 'src/**/*.route.ts',
150
+ }
151
+ ```
152
+
153
+ index.js
154
+
155
+ ```js
156
+ import { Galbe } from 'galbe'
157
+ import config from './galbe.config'
158
+
159
+ export default new Galbe(config)
160
+ ```
161
+
162
+ > [!TIP]
163
+ > If you are using Typescript, you can import `GalbeConfig` type from galbe package to ensure type consistency for your configuration. Here is an example:
164
+ >
165
+ > ```ts
166
+ > import type { GalbeConfig } from 'galbe'
167
+ > const config: GalbeConfig = {
168
+ > port: Number(Bun.env.GALBE_PORT),
169
+ > routes: 'routes/*.route.ts'
170
+ > }
171
+ > export default config
172
+ > ```
173
+
174
+ ## Project Structure
175
+
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
+
178
+ Here are two examples of valid project structures by default:
179
+
180
+ **Example 1**
181
+
182
+ ```txt
183
+ ┌── src
184
+ │ ├── hooks
185
+ │ │   └── log.hook.ts
186
+ │ ├── routes
187
+ │ │   ├── foo.route.ts
188
+ │ │   └── foo.route.ts
189
+ │ └── schemas
190
+ │ ├── bar.schema.ts
191
+ │ └── bar.schema.ts
192
+ ├── galbe.config.ts
193
+ ├── index.ts
194
+ ├── package.json
195
+ ├── README.md
196
+ └── tsconfig.json
197
+ ```
198
+
199
+ **Example 2**
200
+
201
+ ```txt
202
+ ┌── src
203
+ │ ├── hooks
204
+ │ │   └── log.hook.ts
205
+ │ ├── foo
206
+ │ │   ├── foo.route.ts
207
+ │ │   └── foo.schema.ts
208
+ │ └── bar
209
+ │ ├── bar.route.ts
210
+ │ └── bar.schema.ts
211
+ ├── galbe.config.ts
212
+ ├── index.ts
213
+ ├── package.json
214
+ ├── README.md
215
+ └── tsconfig.json
216
+ ```
217
+
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
+
220
+ You can find more info about Route Files definition under the [Routes](routes.md) section.
221
+
222
+ > [!NOTE]
223
+ > Those are just examples that will work with the default configuration. You can of course redefine `routes` property with your own pattern(s) to fit your own project structure.
package/docs/routes.md ADDED
@@ -0,0 +1,124 @@
1
+ # Routes
2
+
3
+ ## Route Definition
4
+
5
+ Here is how to define routes in Galbe.
6
+
7
+ ```ts
8
+ galbe.[method](path: string, schema?: Schema, hooks?: Hooks[], handler: Handler)
9
+ ```
10
+
11
+ **method** ( get | post | put | delete | patch | options )
12
+
13
+ The [HTTP Request Method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) for the defined route.
14
+
15
+ **path** (string)
16
+
17
+ 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.
18
+
19
+ There are two special segments:
20
+
21
+ - `:param` Any segment starting with `:` indicates a parameter segment.
22
+ - `*` To indicate a wildcard segment. This will match any segment or sequence of segments.
23
+
24
+ **schema** (Schema) _Optional_
25
+
26
+ See [Schemas](schemas) section.
27
+
28
+ **hooks** (Hook[]) _Optional_
29
+
30
+ See [Hooks](hooks) section.
31
+
32
+ **handler** (Handler)
33
+
34
+ See [Handler](handler) section.
35
+
36
+ ### Examples
37
+
38
+ **Basic route**
39
+
40
+ ```js
41
+ galbe.get('/foo', ctx => 'Hello World!')
42
+ ```
43
+
44
+ **Route with Schema**
45
+
46
+ <!-- prettier-ignore -->
47
+ ```js
48
+ galbe.get(
49
+ '/foo/:bar',
50
+ { params: { bar: $T.string() } },
51
+ ctx => `Hello ${ctx.params.bar} !`
52
+ )
53
+ ```
54
+
55
+ **Route with Hooks**
56
+
57
+ <!-- prettier-ignore -->
58
+ ```js
59
+ galbe.get(
60
+ '/foo/:bar',
61
+ [() => console.log('Hook1'), () => console.log('Hook2')],
62
+ ctx => `Hello ${ctx.params.bar} !`
63
+ )
64
+ ```
65
+
66
+ **Route with Schemas and Hooks**
67
+
68
+ <!-- prettier-ignore -->
69
+ ```js
70
+ galbe.get(
71
+ '/foo/:bar',
72
+ { params: { bar: $T.string() } },
73
+ [() => console.log('Hook')],
74
+ ctx => `Hello ${ctx.params.bar} !`
75
+ )
76
+ ```
77
+
78
+ ## Automatic Route Analyzer
79
+
80
+ > [!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 properly configured your package.json to do so.
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.
84
+
85
+ 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
+
87
+ ### Route Files
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 js example:
90
+
91
+ ```ts
92
+ export default g => {
93
+ g.get('/foo/:bar', ctx => ctx.params.bar)
94
+ }
95
+ ```
96
+
97
+ The same example using Typescript:
98
+
99
+ ```ts
100
+ import type { Galbe } from 'galbe'
101
+ export default (g: Galbe) => {
102
+ g.get('/foo/:bar', ctx => ctx.params.bar)
103
+ }
104
+ ```
105
+
106
+ The Automatic Route Analyzer is also capable of collecting metadata about your Routefile and your routes by analyzing multiline comments. This can be used by some plugins to perform specific tasks. Here is an example of Routefile with multiline comments metadata.
107
+
108
+ ```js
109
+ /**
110
+ * This is the header's head comment
111
+ * @annotation example of header's annotation
112
+ */
113
+ export default g => {
114
+ /**
115
+ * This is a route head comment
116
+ * @deprecated
117
+ * @tag tag1
118
+ * @tag tag2
119
+ */
120
+ g.get('/foo/:bar', ctx => ctx.params.bar)
121
+ }
122
+ ```
123
+
124
+ You will find more information about comment's metadata and how to use them along with examples in a plugin in the [Plugin](plugins) section.