galbe 0.12.0 → 0.12.2
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 +2 -2
- package/package.json +6 -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/test/routeFiles.test.ts
DELETED
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
import { expect, test, describe } from 'bun:test'
|
|
2
|
-
import { defineRoutes, GalbeProxy, metaAnalysis } from '../src/routes'
|
|
3
|
-
import { Galbe } from '../src'
|
|
4
|
-
|
|
5
|
-
describe('routeFiles', () => {
|
|
6
|
-
test('meta analysis, empty', async () => {
|
|
7
|
-
let meta = await metaAnalysis('./test/resources/test.route.empty.ts')
|
|
8
|
-
expect(meta).toEqual({
|
|
9
|
-
header: {},
|
|
10
|
-
routes: {
|
|
11
|
-
'/one': {
|
|
12
|
-
get: {}
|
|
13
|
-
},
|
|
14
|
-
'/two': {
|
|
15
|
-
post: {}
|
|
16
|
-
},
|
|
17
|
-
'/three': {
|
|
18
|
-
put: {}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
})
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
test('meta analysis, comments', async () => {
|
|
25
|
-
let meta = await metaAnalysis('./test/resources/test.route.comment.ts')
|
|
26
|
-
expect(meta).toEqual({
|
|
27
|
-
header: {
|
|
28
|
-
head: 'description\nmultiline',
|
|
29
|
-
tag: 'test'
|
|
30
|
-
},
|
|
31
|
-
routes: {
|
|
32
|
-
'/test/:param1': {
|
|
33
|
-
get: {
|
|
34
|
-
head: 'This part\nhere',
|
|
35
|
-
tags: 'tag1, tag2, tag3',
|
|
36
|
-
summary: 'short summary',
|
|
37
|
-
description: 'longer description example',
|
|
38
|
-
deprecated: true,
|
|
39
|
-
param: ['{path} param1 description', '{query} param2 description']
|
|
40
|
-
}
|
|
41
|
-
},
|
|
42
|
-
'/test': {
|
|
43
|
-
post: {
|
|
44
|
-
tags: 'tag1, tag2, tag3',
|
|
45
|
-
summary: 'short summary',
|
|
46
|
-
description: 'longer description example',
|
|
47
|
-
body: 'body descripton'
|
|
48
|
-
},
|
|
49
|
-
put: {
|
|
50
|
-
tags: 'tag1, tag2',
|
|
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'
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
})
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
test('define routes, no route', async () => {
|
|
71
|
-
const k = new GalbeProxy(new Galbe())
|
|
72
|
-
await defineRoutes({}, k)
|
|
73
|
-
expect(k.router.routes).toEqual({
|
|
74
|
-
routes: {}
|
|
75
|
-
})
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
test('define routes, no route (false)', async () => {
|
|
79
|
-
const k = new GalbeProxy(new Galbe({ routes: false }))
|
|
80
|
-
await defineRoutes({}, k)
|
|
81
|
-
expect(k.router.routes).toEqual({
|
|
82
|
-
routes: {}
|
|
83
|
-
})
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
test('define routes, no route found', async () => {
|
|
87
|
-
const k = new GalbeProxy(new Galbe())
|
|
88
|
-
await defineRoutes({ routes: 'unexisting_route' }, k)
|
|
89
|
-
expect(k.router.routes).toEqual({
|
|
90
|
-
routes: {}
|
|
91
|
-
})
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
test('define routes, route.empty', async () => {
|
|
95
|
-
const k = new GalbeProxy(new Galbe())
|
|
96
|
-
|
|
97
|
-
await defineRoutes({ routes: 'test/resources/test.route.empty.ts' }, k)
|
|
98
|
-
|
|
99
|
-
const r = k.router.routes
|
|
100
|
-
expect(r?.children?.one?.routes.get).toMatchObject({
|
|
101
|
-
method: 'get',
|
|
102
|
-
path: '/one',
|
|
103
|
-
handler: () => {}
|
|
104
|
-
})
|
|
105
|
-
expect(r?.children?.two?.routes.post).toMatchObject({
|
|
106
|
-
method: 'post',
|
|
107
|
-
path: '/two',
|
|
108
|
-
handler: () => {}
|
|
109
|
-
})
|
|
110
|
-
expect(r?.children?.three?.routes.put).toMatchObject({
|
|
111
|
-
method: 'put',
|
|
112
|
-
path: '/three',
|
|
113
|
-
handler: () => {}
|
|
114
|
-
})
|
|
115
|
-
expect(k.meta).toMatchObject([
|
|
116
|
-
{
|
|
117
|
-
header: {},
|
|
118
|
-
routes: {
|
|
119
|
-
'/one': {
|
|
120
|
-
get: {}
|
|
121
|
-
},
|
|
122
|
-
'/two': {
|
|
123
|
-
post: {}
|
|
124
|
-
},
|
|
125
|
-
'/three': {
|
|
126
|
-
put: {}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
])
|
|
131
|
-
expect(k.meta?.[0].file).toMatch(/test\.route\.empty\.ts$/)
|
|
132
|
-
})
|
|
133
|
-
|
|
134
|
-
test('define routes, all', async () => {
|
|
135
|
-
const k = new GalbeProxy(new Galbe())
|
|
136
|
-
|
|
137
|
-
await defineRoutes({ routes: ['test/resources/test.route.*.ts'] }, k)
|
|
138
|
-
|
|
139
|
-
const r = k.router.routes
|
|
140
|
-
expect(r?.children?.one?.routes.get).toMatchObject({
|
|
141
|
-
method: 'get',
|
|
142
|
-
path: '/one',
|
|
143
|
-
handler: () => {}
|
|
144
|
-
})
|
|
145
|
-
expect(r?.children?.two?.routes.post).toMatchObject({
|
|
146
|
-
method: 'post',
|
|
147
|
-
path: '/two',
|
|
148
|
-
handler: () => {}
|
|
149
|
-
})
|
|
150
|
-
expect(r?.children?.three?.routes.put).toMatchObject({
|
|
151
|
-
method: 'put',
|
|
152
|
-
path: '/three',
|
|
153
|
-
handler: () => {}
|
|
154
|
-
})
|
|
155
|
-
expect(r?.children?.test?.param?.routes.get).toMatchObject({
|
|
156
|
-
method: 'get',
|
|
157
|
-
path: '/test/:param1',
|
|
158
|
-
handler: () => {}
|
|
159
|
-
})
|
|
160
|
-
expect(r?.children?.test?.routes.post).toMatchObject({
|
|
161
|
-
method: 'post',
|
|
162
|
-
path: '/test',
|
|
163
|
-
handler: () => {}
|
|
164
|
-
})
|
|
165
|
-
expect(r?.children?.test?.routes.put).toMatchObject({
|
|
166
|
-
method: 'put',
|
|
167
|
-
path: '/test',
|
|
168
|
-
handler: () => {}
|
|
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
|
-
})
|
|
190
|
-
expect(k.meta?.sort((a, b) => (a.file < b.file ? 1 : -1))).toMatchObject([
|
|
191
|
-
{
|
|
192
|
-
header: {},
|
|
193
|
-
routes: {
|
|
194
|
-
'/one': {
|
|
195
|
-
get: {}
|
|
196
|
-
},
|
|
197
|
-
'/two': {
|
|
198
|
-
post: {}
|
|
199
|
-
},
|
|
200
|
-
'/three': {
|
|
201
|
-
put: {}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
},
|
|
205
|
-
{
|
|
206
|
-
header: {
|
|
207
|
-
head: 'description\nmultiline',
|
|
208
|
-
tag: 'test'
|
|
209
|
-
},
|
|
210
|
-
routes: {
|
|
211
|
-
'/test/:param1': {
|
|
212
|
-
get: {
|
|
213
|
-
head: 'This part\nhere',
|
|
214
|
-
tags: 'tag1, tag2, tag3',
|
|
215
|
-
summary: 'short summary',
|
|
216
|
-
description: 'longer description example',
|
|
217
|
-
deprecated: true,
|
|
218
|
-
param: ['{path} param1 description', '{query} param2 description']
|
|
219
|
-
}
|
|
220
|
-
},
|
|
221
|
-
'/test': {
|
|
222
|
-
post: {
|
|
223
|
-
tags: 'tag1, tag2, tag3',
|
|
224
|
-
summary: 'short summary',
|
|
225
|
-
description: 'longer description example',
|
|
226
|
-
body: 'body descripton'
|
|
227
|
-
},
|
|
228
|
-
put: {
|
|
229
|
-
tags: 'tag1, tag2',
|
|
230
|
-
other: 'Hello Mom!'
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
])
|
|
236
|
-
expect(k.meta?.[0].file).toMatch(/test\.route\..*$/)
|
|
237
|
-
expect(k.meta?.[1].file).toMatch(/test\.route\..*$/)
|
|
238
|
-
})
|
|
239
|
-
})
|
package/test/router.test.ts
DELETED
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
import { expect, test, describe } from 'bun:test'
|
|
2
|
-
import { Galbe, MethodNotAllowedError, NotFoundError, type RouteNode } from '../src'
|
|
3
|
-
|
|
4
|
-
describe('router', () => {
|
|
5
|
-
test('empty', async () => {
|
|
6
|
-
const galbe = new Galbe()
|
|
7
|
-
const router = galbe.router
|
|
8
|
-
|
|
9
|
-
expect(router.prefix).toBe('')
|
|
10
|
-
expect(router.routes).toEqual({ routes: {} })
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
test('routes, bad syntax', async () => {
|
|
14
|
-
const galbe = new Galbe()
|
|
15
|
-
|
|
16
|
-
const invalidPaths = ['.', '/@', '/-ta', '/test/-ta', '/hell@/w0rld', '/last-', '../', './x', '/hello?']
|
|
17
|
-
|
|
18
|
-
for (const p of invalidPaths) {
|
|
19
|
-
try {
|
|
20
|
-
galbe.get(p, () => {})
|
|
21
|
-
expect.unreachable()
|
|
22
|
-
} catch (err) {
|
|
23
|
-
expect(err).toBeInstanceOf(SyntaxError)
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
test('chaining routes', async () => {
|
|
29
|
-
const galbe = new Galbe()
|
|
30
|
-
const router = galbe.router
|
|
31
|
-
|
|
32
|
-
expect(router.routes).toEqual({ routes: {} })
|
|
33
|
-
|
|
34
|
-
galbe.get('/', () => {})
|
|
35
|
-
let r: RouteNode | undefined = router.routes
|
|
36
|
-
|
|
37
|
-
expect(r?.routes.get?.method).toBe('get')
|
|
38
|
-
expect(r?.routes.get?.path).toBe('/')
|
|
39
|
-
expect(r?.param).toBeUndefined()
|
|
40
|
-
expect(r?.children).toBeUndefined()
|
|
41
|
-
|
|
42
|
-
const mockHandler = () => {}
|
|
43
|
-
galbe.get('/test', mockHandler)
|
|
44
|
-
r = r?.children?.test
|
|
45
|
-
|
|
46
|
-
expect(r?.routes.get?.method).toBe('get')
|
|
47
|
-
expect(r?.routes.get?.path).toBe('/test')
|
|
48
|
-
expect(r?.param).toBeUndefined()
|
|
49
|
-
expect(r?.children).toBeUndefined()
|
|
50
|
-
expect(r?.routes.get?.handler).toBe(mockHandler)
|
|
51
|
-
|
|
52
|
-
const mockHandler2 = () => {}
|
|
53
|
-
galbe.get('/test/:foo', mockHandler2)
|
|
54
|
-
r = r?.param
|
|
55
|
-
|
|
56
|
-
expect(r?.routes.get?.method).toBe('get')
|
|
57
|
-
expect(r?.routes.get?.path).toBe('/test/:foo')
|
|
58
|
-
expect(r?.param).toBeUndefined()
|
|
59
|
-
expect(r?.children).toBeUndefined()
|
|
60
|
-
expect(r?.routes.get?.handler).toBe(mockHandler2)
|
|
61
|
-
|
|
62
|
-
const mockHandler3 = () => {}
|
|
63
|
-
galbe.get('/test/:foo/bar', mockHandler3)
|
|
64
|
-
|
|
65
|
-
expect(r?.children).toHaveProperty('bar')
|
|
66
|
-
expect(r?.param).toBeUndefined()
|
|
67
|
-
expect(r?.children?.bar?.routes.get?.handler).toBe(mockHandler3)
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
test('redefining root', async () => {
|
|
71
|
-
const galbe = new Galbe()
|
|
72
|
-
const router = galbe.router
|
|
73
|
-
|
|
74
|
-
const [h1, h2, h3] = [() => {}, () => {}, () => {}]
|
|
75
|
-
|
|
76
|
-
galbe.get('/', h1)
|
|
77
|
-
galbe.get('/test', h2)
|
|
78
|
-
galbe.get('/', h3)
|
|
79
|
-
|
|
80
|
-
let r: RouteNode | undefined = router.routes
|
|
81
|
-
expect(router.prefix).toBe('')
|
|
82
|
-
expect(r?.routes.get?.method).toBe('get')
|
|
83
|
-
expect(r?.routes.get?.path).toBe('/')
|
|
84
|
-
expect(r?.routes.get?.handler).toBe(h3)
|
|
85
|
-
expect(r?.children?.test?.routes.get?.method).toBe('get')
|
|
86
|
-
expect(r?.children?.test?.routes.get?.handler).toBe(h2)
|
|
87
|
-
|
|
88
|
-
const [h4, h5] = [() => {}, () => {}]
|
|
89
|
-
|
|
90
|
-
galbe.get('/foo/bar', h4)
|
|
91
|
-
galbe.get('/foo', h5)
|
|
92
|
-
|
|
93
|
-
r = router?.routes?.children?.foo
|
|
94
|
-
expect(r?.routes.get?.method).toBe('get')
|
|
95
|
-
expect(r?.routes.get?.path).toBe('/foo')
|
|
96
|
-
expect(r?.routes.get?.handler).toBe(h5)
|
|
97
|
-
expect(r?.children?.bar?.routes.get?.method).toBe('get')
|
|
98
|
-
expect(r?.children?.bar?.routes.get?.path).toBe('/foo/bar')
|
|
99
|
-
expect(r?.children?.bar?.routes.get?.handler).toBe(h4)
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
test('find route', async () => {
|
|
103
|
-
const galbe = new Galbe()
|
|
104
|
-
const router = galbe.router
|
|
105
|
-
|
|
106
|
-
const [h1, h3, h4] = [() => {}, () => {}, () => {}, () => {}]
|
|
107
|
-
|
|
108
|
-
galbe.get('/', h1)
|
|
109
|
-
galbe.get('/test/foo', h3)
|
|
110
|
-
galbe.get('/test/foo/bar', h4)
|
|
111
|
-
|
|
112
|
-
let r1 = router.find('get', '/')
|
|
113
|
-
expect(r1.path).toBe('/')
|
|
114
|
-
expect(r1.handler).toBe(h1)
|
|
115
|
-
let r2 = router.find('get', '/test/foo')
|
|
116
|
-
expect(r2.path).toBe('/test/foo')
|
|
117
|
-
expect(r2.handler).toBe(h3)
|
|
118
|
-
let r3 = router.find('get', '/test/foo/bar')
|
|
119
|
-
expect(r3.path).toBe('/test/foo/bar')
|
|
120
|
-
expect(r3.handler).toBe(h4)
|
|
121
|
-
|
|
122
|
-
try {
|
|
123
|
-
router.find('get', '/test')
|
|
124
|
-
expect.unreachable()
|
|
125
|
-
} catch (err: any) {
|
|
126
|
-
expect(err).toBeInstanceOf(NotFoundError)
|
|
127
|
-
expect(err.status).toBe(404)
|
|
128
|
-
expect(err.payload).toBe('Not Found')
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
try {
|
|
132
|
-
router.find('get', '/test/bar/bar')
|
|
133
|
-
expect.unreachable()
|
|
134
|
-
} catch (err: any) {
|
|
135
|
-
expect(err).toBeInstanceOf(NotFoundError)
|
|
136
|
-
expect(err.status).toBe(404)
|
|
137
|
-
expect(err.payload).toBe('Not Found')
|
|
138
|
-
}
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
test('find route param', async () => {
|
|
142
|
-
const galbe = new Galbe()
|
|
143
|
-
const router = galbe.router
|
|
144
|
-
|
|
145
|
-
const [h1, h2] = [() => {}, () => {}]
|
|
146
|
-
|
|
147
|
-
galbe.get('/test/:foo', h1)
|
|
148
|
-
galbe.get('/test/test', h2)
|
|
149
|
-
|
|
150
|
-
let r1 = router.find('get', '/test/42')
|
|
151
|
-
expect(r1.path).toBe('/test/:foo')
|
|
152
|
-
expect(r1.handler).toBe(h1)
|
|
153
|
-
|
|
154
|
-
let r2 = router.find('get', '/test/test')
|
|
155
|
-
expect(r2.path).toBe('/test/test')
|
|
156
|
-
expect(r2.handler).toBe(h2)
|
|
157
|
-
})
|
|
158
|
-
|
|
159
|
-
test('wildcard routes', async () => {
|
|
160
|
-
const galbe = new Galbe()
|
|
161
|
-
const router = galbe.router
|
|
162
|
-
|
|
163
|
-
const [h1, h2, h3, h4] = [() => {}, () => {}, () => {}, () => {}]
|
|
164
|
-
|
|
165
|
-
galbe.get('/test/foo/*', h1)
|
|
166
|
-
galbe.get('/test/foo/bar', h2)
|
|
167
|
-
galbe.get('/test/foo/:p/bar', h3)
|
|
168
|
-
|
|
169
|
-
galbe.get('/test/foo/*/lol', h4)
|
|
170
|
-
|
|
171
|
-
let r1 = router.find('get', '/test/foo/bar/42')
|
|
172
|
-
expect(r1.path).toBe('/test/foo/*')
|
|
173
|
-
expect(r1.handler).toBe(h1)
|
|
174
|
-
|
|
175
|
-
let r3 = router.find('get', '/test/foo/bar/bar')
|
|
176
|
-
expect(r3.path).toBe('/test/foo/:p/bar')
|
|
177
|
-
expect(r3.handler).toBe(h3)
|
|
178
|
-
|
|
179
|
-
let r4 = router.find('get', '/test/foo/foo')
|
|
180
|
-
expect(r4.path).toBe('/test/foo/*')
|
|
181
|
-
expect(r4.handler).toBe(h1)
|
|
182
|
-
|
|
183
|
-
let r5 = router.find('get', '/test/foo/toto/lol')
|
|
184
|
-
expect(r5.path).toBe('/test/foo/*/lol')
|
|
185
|
-
expect(r5.handler).toBe(h4)
|
|
186
|
-
})
|
|
187
|
-
|
|
188
|
-
test('method not allowed', async () => {
|
|
189
|
-
const galbe = new Galbe()
|
|
190
|
-
const router = galbe.router
|
|
191
|
-
|
|
192
|
-
const [h1, h2] = [() => {}, () => {}]
|
|
193
|
-
|
|
194
|
-
galbe.put('/test/foo', h1)
|
|
195
|
-
galbe.post('/test/bar/*', h2)
|
|
196
|
-
|
|
197
|
-
let r1 = router.find('put', '/test/foo')
|
|
198
|
-
expect(r1.path).toBe('/test/foo')
|
|
199
|
-
expect(r1.handler).toBe(h1)
|
|
200
|
-
try {
|
|
201
|
-
router.find('get', '/test/foo')
|
|
202
|
-
expect.unreachable()
|
|
203
|
-
} catch (err) {
|
|
204
|
-
expect(err).toBeInstanceOf(MethodNotAllowedError)
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
let r2 = router.find('post', '/test/bar/tender')
|
|
208
|
-
expect(r2.path).toBe('/test/bar/*')
|
|
209
|
-
expect(r2.handler).toBe(h2)
|
|
210
|
-
try {
|
|
211
|
-
router.find('delete', '/test/bar/toto/titi')
|
|
212
|
-
expect.unreachable()
|
|
213
|
-
} catch (err) {
|
|
214
|
-
expect(err).toBeInstanceOf(MethodNotAllowedError)
|
|
215
|
-
}
|
|
216
|
-
})
|
|
217
|
-
|
|
218
|
-
test('trailing slash routes', async () => {
|
|
219
|
-
const galbe = new Galbe()
|
|
220
|
-
const router = galbe.router
|
|
221
|
-
|
|
222
|
-
const handler = () => {}
|
|
223
|
-
galbe.get('/test/', handler)
|
|
224
|
-
|
|
225
|
-
expect(router.routes.children?.test?.routes.get?.handler).toBe(handler)
|
|
226
|
-
|
|
227
|
-
const r = router.find('get', '/test')
|
|
228
|
-
expect(r.path).toBe('/test/')
|
|
229
|
-
expect(r.handler).toBe(handler)
|
|
230
|
-
})
|
|
231
|
-
})
|
package/test/test.utils.ts
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { $T, type Context } from '../src'
|
|
2
|
-
|
|
3
|
-
export type Case = {
|
|
4
|
-
body?: any
|
|
5
|
-
type?: string
|
|
6
|
-
schema: string
|
|
7
|
-
expected: { status: number; type?: string; resp?: any }
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export const formdata = (data: Record<string, string | string[] | Blob>): FormData => {
|
|
11
|
-
const form = new FormData()
|
|
12
|
-
for (const [k, v] of Object.entries(data)) {
|
|
13
|
-
if (Array.isArray(v)) for (const v2 of v) form.append(k, v2)
|
|
14
|
-
else form.append(k, v)
|
|
15
|
-
}
|
|
16
|
-
return form
|
|
17
|
-
}
|
|
18
|
-
export const fileHash = async (ba: any) =>
|
|
19
|
-
Array.from(new Uint8Array(await crypto.subtle.digest('SHA-256', ba)))
|
|
20
|
-
.map(byte => byte.toString(16).padStart(2, '0'))
|
|
21
|
-
.join('')
|
|
22
|
-
export const decoder = new TextDecoder()
|
|
23
|
-
|
|
24
|
-
export const schema_objectBase = {
|
|
25
|
-
ba: $T.byteArray(),
|
|
26
|
-
string: $T.string(),
|
|
27
|
-
number: $T.number(),
|
|
28
|
-
bool: $T.boolean(),
|
|
29
|
-
any: $T.any(),
|
|
30
|
-
optional: $T.optional($T.any()),
|
|
31
|
-
}
|
|
32
|
-
export const schema_object = {
|
|
33
|
-
...schema_objectBase,
|
|
34
|
-
object: $T.object($T.any()),
|
|
35
|
-
array: $T.array(),
|
|
36
|
-
null: $T.null(),
|
|
37
|
-
nullable: $T.nullable($T.string()),
|
|
38
|
-
nullish: $T.nullish($T.number()),
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export const isAsyncIterator = (obj: any) => {
|
|
42
|
-
if (Object(obj) !== obj) return false
|
|
43
|
-
const method = obj[Symbol.asyncIterator]
|
|
44
|
-
if (typeof method != 'function') return false
|
|
45
|
-
const aIter = method.call(obj)
|
|
46
|
-
return aIter === obj
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const parseAsyncIterator = async (body: any): Promise<any> => {
|
|
50
|
-
const chunks = []
|
|
51
|
-
let type
|
|
52
|
-
for await (const chunk of body) {
|
|
53
|
-
if (chunk instanceof Uint8Array) type = 'byteArray'
|
|
54
|
-
else if (typeof chunk === 'string') type = 'string'
|
|
55
|
-
// @ts-ignore
|
|
56
|
-
chunks.push(chunk)
|
|
57
|
-
}
|
|
58
|
-
// @ts-ignore
|
|
59
|
-
if (type === 'byteArray') return new Uint8Array(chunks.map(c => Array.from(c)).flat())
|
|
60
|
-
if (type === 'string') return chunks.join('')
|
|
61
|
-
return chunks
|
|
62
|
-
}
|
|
63
|
-
const parseBody = async (body: any): Promise<any> =>
|
|
64
|
-
typeof body === 'object' && body !== null && !Array.isArray(body)
|
|
65
|
-
? Object.fromEntries(
|
|
66
|
-
await Promise.all(
|
|
67
|
-
Object.entries(body).map(async ([k, v]) => {
|
|
68
|
-
if (v instanceof Uint8Array) return [k, await fileHash(v)]
|
|
69
|
-
else return [k, await parseBody(v)]
|
|
70
|
-
})
|
|
71
|
-
)
|
|
72
|
-
)
|
|
73
|
-
: body
|
|
74
|
-
export const handleBody = async (ctx: any) => {
|
|
75
|
-
if (ctx.body === undefined) {
|
|
76
|
-
return { type: 'undefined' }
|
|
77
|
-
}
|
|
78
|
-
if (ctx?.body instanceof ReadableStream) {
|
|
79
|
-
let content = ''
|
|
80
|
-
for await (const chunk of ctx.body) {
|
|
81
|
-
if (typeof chunk === 'string') content += chunk
|
|
82
|
-
else content += decoder.decode(chunk)
|
|
83
|
-
}
|
|
84
|
-
return { type: 'ReadableStream', content }
|
|
85
|
-
}
|
|
86
|
-
if (Array.isArray(ctx.body)) {
|
|
87
|
-
return { type: 'array', content: ctx.body }
|
|
88
|
-
}
|
|
89
|
-
if (ctx?.body instanceof Uint8Array) {
|
|
90
|
-
return { type: 'byteArray', content: decoder.decode(ctx.body) }
|
|
91
|
-
}
|
|
92
|
-
if (isAsyncIterator(ctx.body)) {
|
|
93
|
-
return { type: 'AsyncIterator', content: await parseAsyncIterator(ctx.body) }
|
|
94
|
-
} else {
|
|
95
|
-
return { type: typeof ctx.body, content: await parseBody(ctx.body) }
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
export const handleUrlFormStream = async (ctx: Context) => {
|
|
99
|
-
let resp: Record<string, any> = {}
|
|
100
|
-
// @ts-ignore
|
|
101
|
-
for await (const [k, v] of ctx.body) {
|
|
102
|
-
if (k in resp) {
|
|
103
|
-
resp[k] = Array.isArray(resp[k]) ? [...resp[k], v] : [resp[k], v]
|
|
104
|
-
} else resp[k] = v
|
|
105
|
-
}
|
|
106
|
-
return { type: 'object', content: resp }
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export const EMPTY_BA_STR = 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
|