galbe 0.3.0 → 0.5.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/.github/workflows/build_test.yml +2 -4
- package/.github/workflows/release.yml +2 -2
- package/bin/cli.ts +8 -104
- package/bin/commands/build.ts +95 -0
- package/bin/commands/dev.ts +53 -0
- package/bin/commands/generate/client.ts +192 -0
- package/bin/commands/generate/code/openapi.parser.ts +479 -0
- package/bin/commands/generate/code.ts +75 -0
- package/bin/commands/generate/index.ts +12 -0
- package/bin/commands/generate/spec.ts +94 -0
- package/bin/res/cli.template.js +120 -0
- package/bin/res/client.template.ts +161 -0
- package/bin/util.ts +164 -0
- package/bun.lockb +0 -0
- package/docs/plugins.md +36 -36
- package/docs/routes.md +3 -3
- package/package.json +10 -8
- package/scripts/postinstall.ts +1 -3
- package/src/extras/spec/openapi.serializer.ts +264 -0
- package/src/extras.ts +1 -0
- package/src/index.ts +103 -73
- package/src/parser.ts +27 -5
- package/src/router.ts +27 -29
- package/src/routes.ts +138 -39
- package/src/schema.ts +69 -8
- package/src/server.ts +9 -10
- package/src/types.ts +73 -41
- package/src/util.ts +95 -10
- package/src/validator.ts +2 -0
- package/test/parser.test.ts +34 -0
- package/test/requests.test.ts +5 -12
- package/test/resources/test.route.comment.ts +20 -0
- package/test/responses.test.ts +109 -11
- package/test/routeFiles.test.ts +44 -27
- package/test/router.test.ts +67 -42
- package/scripts/build.ts +0 -14
package/test/routeFiles.test.ts
CHANGED
|
@@ -49,6 +49,18 @@ describe('routeFiles', () => {
|
|
|
49
49
|
put: {
|
|
50
50
|
tags: 'tag1, tag2',
|
|
51
51
|
other: 'Hello Mom!'
|
|
52
|
+
},
|
|
53
|
+
patch: {
|
|
54
|
+
head: 'patch method'
|
|
55
|
+
},
|
|
56
|
+
options: {
|
|
57
|
+
head: 'options method'
|
|
58
|
+
},
|
|
59
|
+
delete: {
|
|
60
|
+
head: 'delete method'
|
|
61
|
+
},
|
|
62
|
+
head: {
|
|
63
|
+
head: 'head method'
|
|
52
64
|
}
|
|
53
65
|
}
|
|
54
66
|
}
|
|
@@ -59,12 +71,7 @@ describe('routeFiles', () => {
|
|
|
59
71
|
const k = new Galbe()
|
|
60
72
|
await defineRoutes({}, k)
|
|
61
73
|
expect(k.router.routes).toEqual({
|
|
62
|
-
|
|
63
|
-
POST: {},
|
|
64
|
-
PUT: {},
|
|
65
|
-
PATCH: {},
|
|
66
|
-
DELETE: {},
|
|
67
|
-
OPTIONS: {}
|
|
74
|
+
routes: {}
|
|
68
75
|
})
|
|
69
76
|
})
|
|
70
77
|
|
|
@@ -72,12 +79,7 @@ describe('routeFiles', () => {
|
|
|
72
79
|
const k = new Galbe({ routes: false })
|
|
73
80
|
await defineRoutes({}, k)
|
|
74
81
|
expect(k.router.routes).toEqual({
|
|
75
|
-
|
|
76
|
-
POST: {},
|
|
77
|
-
PUT: {},
|
|
78
|
-
PATCH: {},
|
|
79
|
-
DELETE: {},
|
|
80
|
-
OPTIONS: {}
|
|
82
|
+
routes: {}
|
|
81
83
|
})
|
|
82
84
|
})
|
|
83
85
|
|
|
@@ -85,12 +87,7 @@ describe('routeFiles', () => {
|
|
|
85
87
|
const k = new Galbe()
|
|
86
88
|
await defineRoutes({ routes: 'unexisting_route' }, k)
|
|
87
89
|
expect(k.router.routes).toEqual({
|
|
88
|
-
|
|
89
|
-
POST: {},
|
|
90
|
-
PUT: {},
|
|
91
|
-
PATCH: {},
|
|
92
|
-
DELETE: {},
|
|
93
|
-
OPTIONS: {}
|
|
90
|
+
routes: {}
|
|
94
91
|
})
|
|
95
92
|
})
|
|
96
93
|
|
|
@@ -100,17 +97,17 @@ describe('routeFiles', () => {
|
|
|
100
97
|
await defineRoutes({ routes: 'test/resources/test.route.empty.ts' }, k)
|
|
101
98
|
|
|
102
99
|
const r = k.router.routes
|
|
103
|
-
expect(r
|
|
100
|
+
expect(r?.children?.one?.routes.get).toMatchObject({
|
|
104
101
|
method: 'get',
|
|
105
102
|
path: '/one',
|
|
106
103
|
handler: () => {}
|
|
107
104
|
})
|
|
108
|
-
expect(r
|
|
105
|
+
expect(r?.children?.two?.routes.post).toMatchObject({
|
|
109
106
|
method: 'post',
|
|
110
107
|
path: '/two',
|
|
111
108
|
handler: () => {}
|
|
112
109
|
})
|
|
113
|
-
expect(r
|
|
110
|
+
expect(r?.children?.three?.routes.put).toMatchObject({
|
|
114
111
|
method: 'put',
|
|
115
112
|
path: '/three',
|
|
116
113
|
handler: () => {}
|
|
@@ -140,36 +137,56 @@ describe('routeFiles', () => {
|
|
|
140
137
|
await defineRoutes({ routes: ['test/resources/test.route.*.ts'] }, k)
|
|
141
138
|
|
|
142
139
|
const r = k.router.routes
|
|
143
|
-
expect(r
|
|
140
|
+
expect(r?.children?.one?.routes.get).toMatchObject({
|
|
144
141
|
method: 'get',
|
|
145
142
|
path: '/one',
|
|
146
143
|
handler: () => {}
|
|
147
144
|
})
|
|
148
|
-
expect(r
|
|
145
|
+
expect(r?.children?.two?.routes.post).toMatchObject({
|
|
149
146
|
method: 'post',
|
|
150
147
|
path: '/two',
|
|
151
148
|
handler: () => {}
|
|
152
149
|
})
|
|
153
|
-
expect(r
|
|
150
|
+
expect(r?.children?.three?.routes.put).toMatchObject({
|
|
154
151
|
method: 'put',
|
|
155
152
|
path: '/three',
|
|
156
153
|
handler: () => {}
|
|
157
154
|
})
|
|
158
|
-
expect(r
|
|
155
|
+
expect(r?.children?.test?.param?.routes.get).toMatchObject({
|
|
159
156
|
method: 'get',
|
|
160
157
|
path: '/test/:param1',
|
|
161
158
|
handler: () => {}
|
|
162
159
|
})
|
|
163
|
-
expect(r
|
|
160
|
+
expect(r?.children?.test?.routes.post).toMatchObject({
|
|
164
161
|
method: 'post',
|
|
165
162
|
path: '/test',
|
|
166
163
|
handler: () => {}
|
|
167
164
|
})
|
|
168
|
-
expect(r
|
|
165
|
+
expect(r?.children?.test?.routes.put).toMatchObject({
|
|
169
166
|
method: 'put',
|
|
170
167
|
path: '/test',
|
|
171
168
|
handler: () => {}
|
|
172
169
|
})
|
|
170
|
+
expect(r?.children?.test?.routes.patch).toMatchObject({
|
|
171
|
+
method: 'patch',
|
|
172
|
+
path: '/test',
|
|
173
|
+
handler: () => {}
|
|
174
|
+
})
|
|
175
|
+
expect(r?.children?.test?.routes.options).toMatchObject({
|
|
176
|
+
method: 'options',
|
|
177
|
+
path: '/test',
|
|
178
|
+
handler: () => {}
|
|
179
|
+
})
|
|
180
|
+
expect(r?.children?.test?.routes.delete).toMatchObject({
|
|
181
|
+
method: 'delete',
|
|
182
|
+
path: '/test',
|
|
183
|
+
handler: () => {}
|
|
184
|
+
})
|
|
185
|
+
expect(r?.children?.test?.routes.head).toMatchObject({
|
|
186
|
+
method: 'head',
|
|
187
|
+
path: '/test',
|
|
188
|
+
handler: () => {}
|
|
189
|
+
})
|
|
173
190
|
expect(k.meta?.sort((a, b) => (a.file < b.file ? 1 : -1))).toMatchObject([
|
|
174
191
|
{
|
|
175
192
|
header: {},
|
package/test/router.test.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { expect, test, describe } from 'bun:test'
|
|
2
|
-
import { Galbe, NotFoundError, type RouteNode } from '../src'
|
|
2
|
+
import { Galbe, MethodNotAllowedError, NotFoundError, type RouteNode } from '../src'
|
|
3
3
|
|
|
4
4
|
describe('router', () => {
|
|
5
5
|
test('empty', async () => {
|
|
@@ -7,12 +7,7 @@ describe('router', () => {
|
|
|
7
7
|
const router = galbe.router
|
|
8
8
|
|
|
9
9
|
expect(router.prefix).toBe('')
|
|
10
|
-
expect(router.routes
|
|
11
|
-
expect(router.routes.POST).toEqual({})
|
|
12
|
-
expect(router.routes.PUT).toEqual({})
|
|
13
|
-
expect(router.routes.PATCH).toEqual({})
|
|
14
|
-
expect(router.routes.DELETE).toEqual({})
|
|
15
|
-
expect(router.routes.OPTIONS).toEqual({})
|
|
10
|
+
expect(router.routes).toEqual({ routes: {} })
|
|
16
11
|
})
|
|
17
12
|
|
|
18
13
|
test('routes, bad syntax', async () => {
|
|
@@ -45,13 +40,13 @@ describe('router', () => {
|
|
|
45
40
|
const galbe = new Galbe()
|
|
46
41
|
const router = galbe.router
|
|
47
42
|
|
|
48
|
-
expect(router.routes
|
|
43
|
+
expect(router.routes).toEqual({ routes: {} })
|
|
49
44
|
|
|
50
45
|
galbe.get('/', () => {})
|
|
51
|
-
let r: RouteNode | undefined = router.routes
|
|
46
|
+
let r: RouteNode | undefined = router.routes
|
|
52
47
|
|
|
53
|
-
expect(r?.
|
|
54
|
-
expect(r?.
|
|
48
|
+
expect(r?.routes.get?.method).toBe('get')
|
|
49
|
+
expect(r?.routes.get?.path).toBe('/')
|
|
55
50
|
expect(r?.param).toBeUndefined()
|
|
56
51
|
expect(r?.children).toBeUndefined()
|
|
57
52
|
|
|
@@ -59,28 +54,28 @@ describe('router', () => {
|
|
|
59
54
|
galbe.get('/test', mockHandler)
|
|
60
55
|
r = r?.children?.test
|
|
61
56
|
|
|
62
|
-
expect(r?.
|
|
63
|
-
expect(r?.
|
|
57
|
+
expect(r?.routes.get?.method).toBe('get')
|
|
58
|
+
expect(r?.routes.get?.path).toBe('/test')
|
|
64
59
|
expect(r?.param).toBeUndefined()
|
|
65
60
|
expect(r?.children).toBeUndefined()
|
|
66
|
-
expect(r?.
|
|
61
|
+
expect(r?.routes.get?.handler).toBe(mockHandler)
|
|
67
62
|
|
|
68
63
|
const mockHandler2 = () => {}
|
|
69
64
|
galbe.get('/test/:foo', mockHandler2)
|
|
70
65
|
r = r?.param
|
|
71
66
|
|
|
72
|
-
expect(r?.
|
|
73
|
-
expect(r?.
|
|
67
|
+
expect(r?.routes.get?.method).toBe('get')
|
|
68
|
+
expect(r?.routes.get?.path).toBe('/test/:foo')
|
|
74
69
|
expect(r?.param).toBeUndefined()
|
|
75
70
|
expect(r?.children).toBeUndefined()
|
|
76
|
-
expect(r?.
|
|
71
|
+
expect(r?.routes.get?.handler).toBe(mockHandler2)
|
|
77
72
|
|
|
78
73
|
const mockHandler3 = () => {}
|
|
79
74
|
galbe.get('/test/:foo/bar', mockHandler3)
|
|
80
75
|
|
|
81
76
|
expect(r?.children).toHaveProperty('bar')
|
|
82
77
|
expect(r?.param).toBeUndefined()
|
|
83
|
-
expect(r?.children?.bar?.
|
|
78
|
+
expect(r?.children?.bar?.routes.get?.handler).toBe(mockHandler3)
|
|
84
79
|
})
|
|
85
80
|
|
|
86
81
|
test('redefining root', async () => {
|
|
@@ -93,26 +88,26 @@ describe('router', () => {
|
|
|
93
88
|
galbe.get('/test', h2)
|
|
94
89
|
galbe.get('/', h3)
|
|
95
90
|
|
|
96
|
-
let r: RouteNode | undefined = router.routes
|
|
91
|
+
let r: RouteNode | undefined = router.routes
|
|
97
92
|
expect(router.prefix).toBe('')
|
|
98
|
-
expect(r?.
|
|
99
|
-
expect(r?.
|
|
100
|
-
expect(r?.
|
|
101
|
-
expect(r?.children?.test?.
|
|
102
|
-
expect(r?.children?.test?.
|
|
93
|
+
expect(r?.routes.get?.method).toBe('get')
|
|
94
|
+
expect(r?.routes.get?.path).toBe('/')
|
|
95
|
+
expect(r?.routes.get?.handler).toBe(h3)
|
|
96
|
+
expect(r?.children?.test?.routes.get?.method).toBe('get')
|
|
97
|
+
expect(r?.children?.test?.routes.get?.handler).toBe(h2)
|
|
103
98
|
|
|
104
99
|
const [h4, h5] = [() => {}, () => {}]
|
|
105
100
|
|
|
106
101
|
galbe.get('/foo/bar', h4)
|
|
107
102
|
galbe.get('/foo', h5)
|
|
108
103
|
|
|
109
|
-
r = router?.routes?.
|
|
110
|
-
expect(r?.
|
|
111
|
-
expect(r?.
|
|
112
|
-
expect(r?.
|
|
113
|
-
expect(r?.children?.bar?.
|
|
114
|
-
expect(r?.children?.bar?.
|
|
115
|
-
expect(r?.children?.bar?.
|
|
104
|
+
r = router?.routes?.children?.foo
|
|
105
|
+
expect(r?.routes.get?.method).toBe('get')
|
|
106
|
+
expect(r?.routes.get?.path).toBe('/foo')
|
|
107
|
+
expect(r?.routes.get?.handler).toBe(h5)
|
|
108
|
+
expect(r?.children?.bar?.routes.get?.method).toBe('get')
|
|
109
|
+
expect(r?.children?.bar?.routes.get?.path).toBe('/foo/bar')
|
|
110
|
+
expect(r?.children?.bar?.routes.get?.handler).toBe(h4)
|
|
116
111
|
})
|
|
117
112
|
|
|
118
113
|
test('find route', async () => {
|
|
@@ -125,18 +120,18 @@ describe('router', () => {
|
|
|
125
120
|
galbe.get('/test/foo', h3)
|
|
126
121
|
galbe.get('/test/foo/bar', h4)
|
|
127
122
|
|
|
128
|
-
let r1 = router.find('
|
|
123
|
+
let r1 = router.find('get', '/')
|
|
129
124
|
expect(r1.path).toBe('/')
|
|
130
125
|
expect(r1.handler).toBe(h1)
|
|
131
|
-
let r2 = router.find('
|
|
126
|
+
let r2 = router.find('get', '/test/foo')
|
|
132
127
|
expect(r2.path).toBe('/test/foo')
|
|
133
128
|
expect(r2.handler).toBe(h3)
|
|
134
|
-
let r3 = router.find('
|
|
129
|
+
let r3 = router.find('get', '/test/foo/bar')
|
|
135
130
|
expect(r3.path).toBe('/test/foo/bar')
|
|
136
131
|
expect(r3.handler).toBe(h4)
|
|
137
132
|
|
|
138
133
|
try {
|
|
139
|
-
router.find('
|
|
134
|
+
router.find('get', '/test')
|
|
140
135
|
expect.unreachable()
|
|
141
136
|
} catch (err: any) {
|
|
142
137
|
expect(err).toBeInstanceOf(NotFoundError)
|
|
@@ -145,7 +140,7 @@ describe('router', () => {
|
|
|
145
140
|
}
|
|
146
141
|
|
|
147
142
|
try {
|
|
148
|
-
router.find('
|
|
143
|
+
router.find('get', '/test/bar/bar')
|
|
149
144
|
expect.unreachable()
|
|
150
145
|
} catch (err: any) {
|
|
151
146
|
expect(err).toBeInstanceOf(NotFoundError)
|
|
@@ -163,11 +158,11 @@ describe('router', () => {
|
|
|
163
158
|
galbe.get('/test/:foo', h1)
|
|
164
159
|
galbe.get('/test/test', h2)
|
|
165
160
|
|
|
166
|
-
let r1 = router.find('
|
|
161
|
+
let r1 = router.find('get', '/test/42')
|
|
167
162
|
expect(r1.path).toBe('/test/:foo')
|
|
168
163
|
expect(r1.handler).toBe(h1)
|
|
169
164
|
|
|
170
|
-
let r2 = router.find('
|
|
165
|
+
let r2 = router.find('get', '/test/test')
|
|
171
166
|
expect(r2.path).toBe('/test/test')
|
|
172
167
|
expect(r2.handler).toBe(h2)
|
|
173
168
|
})
|
|
@@ -184,20 +179,50 @@ describe('router', () => {
|
|
|
184
179
|
|
|
185
180
|
galbe.get('/test/foo/*/lol', h4)
|
|
186
181
|
|
|
187
|
-
let r1 = router.find('
|
|
182
|
+
let r1 = router.find('get', '/test/foo/bar/42')
|
|
188
183
|
expect(r1.path).toBe('/test/foo/*')
|
|
189
184
|
expect(r1.handler).toBe(h1)
|
|
190
185
|
|
|
191
|
-
let r3 = router.find('
|
|
186
|
+
let r3 = router.find('get', '/test/foo/bar/bar')
|
|
192
187
|
expect(r3.path).toBe('/test/foo/:p/bar')
|
|
193
188
|
expect(r3.handler).toBe(h3)
|
|
194
189
|
|
|
195
|
-
let r4 = router.find('
|
|
190
|
+
let r4 = router.find('get', '/test/foo/foo')
|
|
196
191
|
expect(r4.path).toBe('/test/foo/*')
|
|
197
192
|
expect(r4.handler).toBe(h1)
|
|
198
193
|
|
|
199
|
-
let r5 = router.find('
|
|
194
|
+
let r5 = router.find('get', '/test/foo/toto/lol')
|
|
200
195
|
expect(r5.path).toBe('/test/foo/*/lol')
|
|
201
196
|
expect(r5.handler).toBe(h4)
|
|
202
197
|
})
|
|
198
|
+
|
|
199
|
+
test('method not allowed', async () => {
|
|
200
|
+
const galbe = new Galbe()
|
|
201
|
+
const router = galbe.router
|
|
202
|
+
|
|
203
|
+
const [h1, h2] = [() => {}, () => {}]
|
|
204
|
+
|
|
205
|
+
galbe.put('/test/foo', h1)
|
|
206
|
+
galbe.post('/test/bar/*', h2)
|
|
207
|
+
|
|
208
|
+
let r1 = router.find('put', '/test/foo')
|
|
209
|
+
expect(r1.path).toBe('/test/foo')
|
|
210
|
+
expect(r1.handler).toBe(h1)
|
|
211
|
+
try {
|
|
212
|
+
router.find('get', '/test/foo')
|
|
213
|
+
expect.unreachable()
|
|
214
|
+
} catch (err) {
|
|
215
|
+
expect(err).toBeInstanceOf(MethodNotAllowedError)
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
let r2 = router.find('post', '/test/bar/tender')
|
|
219
|
+
expect(r2.path).toBe('/test/bar/*')
|
|
220
|
+
expect(r2.handler).toBe(h2)
|
|
221
|
+
try {
|
|
222
|
+
router.find('delete', '/test/bar/toto/titi')
|
|
223
|
+
expect.unreachable()
|
|
224
|
+
} catch (err) {
|
|
225
|
+
expect(err).toBeInstanceOf(MethodNotAllowedError)
|
|
226
|
+
}
|
|
227
|
+
})
|
|
203
228
|
})
|
package/scripts/build.ts
DELETED