galbe 0.1.13 → 0.3.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/bun.lockb +0 -0
- package/docs/context.md +1 -1
- package/docs/getting-started.md +8 -0
- package/docs/handler.md +1 -1
- package/docs/hooks.md +5 -5
- package/docs/plugins.md +117 -0
- package/docs/schemas.md +19 -2
- package/package.json +1 -1
- package/src/index.ts +61 -49
- package/src/parser.ts +2 -3
- package/src/router.ts +1 -0
- package/src/routes.ts +13 -10
- package/src/schema.ts +10 -0
- package/src/server.ts +69 -57
- package/src/types.ts +51 -26
- package/src/util.ts +18 -2
- package/src/validator.ts +25 -5
- package/test/plugins.test.ts +3 -3
- package/test/responses.test.ts +288 -13
package/src/server.ts
CHANGED
|
@@ -3,6 +3,9 @@ import type { Context, Route } from './types'
|
|
|
3
3
|
import { InternalError, RequestError } from './types'
|
|
4
4
|
import { parseEntry, requestBodyParser, requestPathParser, responseParser } from './parser'
|
|
5
5
|
import { Galbe } from './index'
|
|
6
|
+
import { validateResponse } from './validator'
|
|
7
|
+
|
|
8
|
+
const LOADABLE_METHODS = ['POST', 'PUT', 'PATCH']
|
|
6
9
|
|
|
7
10
|
const handleInternalError = (error: any) => {
|
|
8
11
|
console.error(error)
|
|
@@ -10,26 +13,11 @@ const handleInternalError = (error: any) => {
|
|
|
10
13
|
}
|
|
11
14
|
|
|
12
15
|
const setupPluginCallbacks = (galbe: Galbe) => ({
|
|
13
|
-
init: galbe.plugins.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if (p.onFetch) l.push(p.onFetch)
|
|
19
|
-
return l
|
|
20
|
-
}, []),
|
|
21
|
-
onRoute: galbe.plugins.reduce((l: Function[], p) => {
|
|
22
|
-
if (p.onRoute) l.push(p.onRoute)
|
|
23
|
-
return l
|
|
24
|
-
}, []),
|
|
25
|
-
beforeHandle: galbe.plugins.reduce((l: Function[], p) => {
|
|
26
|
-
if (p.beforeHandle) l.push(p.beforeHandle)
|
|
27
|
-
return l
|
|
28
|
-
}, []),
|
|
29
|
-
afterHandle: galbe.plugins.reduce((l: Function[], p) => {
|
|
30
|
-
if (p.afterHandle) l.push(p.afterHandle)
|
|
31
|
-
return l
|
|
32
|
-
}, [])
|
|
16
|
+
init: galbe.plugins.filter(p => p.init),
|
|
17
|
+
onFetch: galbe.plugins.filter(p => p.onFetch),
|
|
18
|
+
onRoute: galbe.plugins.filter(p => p.onRoute),
|
|
19
|
+
beforeHandle: galbe.plugins.filter(p => p.beforeHandle),
|
|
20
|
+
afterHandle: galbe.plugins.filter(p => p.afterHandle)
|
|
33
21
|
})
|
|
34
22
|
|
|
35
23
|
export default async (galbe: Galbe, port?: number) => {
|
|
@@ -37,7 +25,8 @@ export default async (galbe: Galbe, port?: number) => {
|
|
|
37
25
|
if (galbe?.config?.basePath && galbe?.config?.basePath[0] !== '/')
|
|
38
26
|
galbe.config.basePath = `/${galbe?.config?.basePath}`
|
|
39
27
|
let pluginsCb = setupPluginCallbacks(galbe)
|
|
40
|
-
|
|
28
|
+
//@ts-ignore
|
|
29
|
+
for (const p of pluginsCb.init) await p.init(galbe?.config?.plugin?.[p.name], galbe)
|
|
41
30
|
|
|
42
31
|
return Bun.serve({
|
|
43
32
|
port: port || galbe.config?.port || 3000,
|
|
@@ -51,8 +40,9 @@ export default async (galbe: Galbe, port?: number) => {
|
|
|
51
40
|
body: {},
|
|
52
41
|
state: {}
|
|
53
42
|
}
|
|
54
|
-
for (const
|
|
55
|
-
|
|
43
|
+
for (const p of pluginsCb.onFetch) {
|
|
44
|
+
//@ts-ignore
|
|
45
|
+
const r = await p.onFetch(context)
|
|
56
46
|
if (r) return r
|
|
57
47
|
}
|
|
58
48
|
const url = new URL(req.url)
|
|
@@ -66,9 +56,11 @@ export default async (galbe: Galbe, port?: number) => {
|
|
|
66
56
|
if (error instanceof RequestError) throw error
|
|
67
57
|
else throw handleInternalError(error)
|
|
68
58
|
}
|
|
59
|
+
context.route = route
|
|
69
60
|
|
|
70
|
-
for (const
|
|
71
|
-
|
|
61
|
+
for (const p of pluginsCb.onRoute) {
|
|
62
|
+
//@ts-ignore
|
|
63
|
+
const r = await p.onRoute(context)
|
|
72
64
|
if (r) return r
|
|
73
65
|
}
|
|
74
66
|
|
|
@@ -80,41 +72,46 @@ export default async (galbe: Galbe, port?: number) => {
|
|
|
80
72
|
for (let [k, v] of url.searchParams) inQuery[k] = v
|
|
81
73
|
let inParams = requestPathParser(url.pathname, route.path)
|
|
82
74
|
|
|
83
|
-
context.body =
|
|
75
|
+
context.body = LOADABLE_METHODS.includes(req.method)
|
|
76
|
+
? await requestBodyParser(req.body, inHeaders, schema.body)
|
|
77
|
+
: null
|
|
84
78
|
context.headers = inHeaders
|
|
85
79
|
context.query = inQuery
|
|
86
80
|
context.params = inParams
|
|
87
81
|
|
|
88
82
|
// request validation
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
83
|
+
if (galbe.config?.requestValidator?.enabled) {
|
|
84
|
+
let errors: RequestError[] = []
|
|
85
|
+
try {
|
|
86
|
+
if (schema?.headers)
|
|
87
|
+
context.headers = {
|
|
88
|
+
...context.headers,
|
|
89
|
+
...parseEntry(context.headers, schema.headers, { name: 'headers', i: true })
|
|
90
|
+
}
|
|
91
|
+
} catch (error) {
|
|
92
|
+
if (error instanceof RequestError) errors.push(error)
|
|
93
|
+
else throw handleInternalError(error)
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
if (schema?.query) context.query = parseEntry(context.query, schema.query, { name: 'query' })
|
|
97
|
+
} catch (error) {
|
|
98
|
+
if (error instanceof RequestError) errors.push(error)
|
|
99
|
+
else throw handleInternalError(error)
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
if (schema?.params) context.params = parseEntry(context.params, schema.params, { name: 'params' })
|
|
103
|
+
} catch (error) {
|
|
104
|
+
if (error instanceof RequestError) errors.push(error)
|
|
105
|
+
else throw handleInternalError(error)
|
|
106
|
+
}
|
|
107
|
+
if (errors.length) {
|
|
108
|
+
throw new RequestError({ status: 400, payload: errors.reduce((acc, c) => ({ ...acc, ...c.payload }), {}) })
|
|
109
|
+
}
|
|
114
110
|
}
|
|
115
111
|
|
|
116
|
-
for (const
|
|
117
|
-
|
|
112
|
+
for (const p of pluginsCb.beforeHandle) {
|
|
113
|
+
//@ts-ignore
|
|
114
|
+
const r = await p.beforeHandle(context)
|
|
118
115
|
if (r) return r
|
|
119
116
|
}
|
|
120
117
|
|
|
@@ -152,8 +149,12 @@ export default async (galbe: Galbe, port?: number) => {
|
|
|
152
149
|
|
|
153
150
|
const parsedResponse = responseParser(response, context)
|
|
154
151
|
|
|
155
|
-
|
|
156
|
-
|
|
152
|
+
if (galbe.config?.responseValidator?.enabled && schema.response)
|
|
153
|
+
validateResponse(response, schema.response, context.set.status || 200)
|
|
154
|
+
|
|
155
|
+
for (const p of pluginsCb.afterHandle) {
|
|
156
|
+
//@ts-ignore
|
|
157
|
+
const r = await p.afterHandle(parsedResponse, context)
|
|
157
158
|
if (r) return r
|
|
158
159
|
}
|
|
159
160
|
|
|
@@ -163,8 +164,19 @@ export default async (galbe: Galbe, port?: number) => {
|
|
|
163
164
|
let customError
|
|
164
165
|
if (galbe.errorHandler) customError = responseParser(galbe.errorHandler(error, context), context)
|
|
165
166
|
if (customError) return customError
|
|
166
|
-
if (error instanceof
|
|
167
|
-
|
|
167
|
+
if (error instanceof InternalError) {
|
|
168
|
+
console.log(`Internal Error`, error?.payload || '')
|
|
169
|
+
return new Response('Internal Server Error', {
|
|
170
|
+
status: error.status,
|
|
171
|
+
headers: { 'Content-Type': 'application/json' }
|
|
172
|
+
})
|
|
173
|
+
} else if (error instanceof RequestError) {
|
|
174
|
+
let payload = ''
|
|
175
|
+
if (typeof error.payload === 'string') payload = error.payload
|
|
176
|
+
try {
|
|
177
|
+
payload = JSON.stringify(error.payload)
|
|
178
|
+
} catch (err) {}
|
|
179
|
+
return new Response(payload, {
|
|
168
180
|
status: error.status,
|
|
169
181
|
headers: { 'Content-Type': 'application/json' }
|
|
170
182
|
})
|
package/src/types.ts
CHANGED
|
@@ -22,12 +22,27 @@ export type STBody =
|
|
|
22
22
|
| STBoolean
|
|
23
23
|
| STNumber
|
|
24
24
|
| STInteger
|
|
25
|
+
| STLiteral
|
|
25
26
|
| STObject
|
|
26
27
|
| STArray
|
|
27
28
|
| STUrlForm
|
|
28
29
|
| STMultipartForm
|
|
29
30
|
| STUnion
|
|
30
31
|
| STStream
|
|
32
|
+
|
|
33
|
+
export type STResponseValue =
|
|
34
|
+
| STByteArray
|
|
35
|
+
| STString
|
|
36
|
+
| STBoolean
|
|
37
|
+
| STNumber
|
|
38
|
+
| STInteger
|
|
39
|
+
| STLiteral
|
|
40
|
+
| STObject
|
|
41
|
+
| STArray
|
|
42
|
+
| STUnion
|
|
43
|
+
| STStream
|
|
44
|
+
export type STResponse = Record<number, STResponseValue>
|
|
45
|
+
|
|
31
46
|
export type MaybeArray<T> = T | T[]
|
|
32
47
|
|
|
33
48
|
export type Method = 'get' | 'post' | 'put' | 'delete' | 'patch' | 'options'
|
|
@@ -74,6 +89,8 @@ export type GalbeConfig = {
|
|
|
74
89
|
routes?: boolean | string | string[]
|
|
75
90
|
router?: { cacheEnabled: boolean }
|
|
76
91
|
plugin?: Record<string, any>
|
|
92
|
+
requestValidator?: { enabled: boolean }
|
|
93
|
+
responseValidator?: { enabled: boolean }
|
|
77
94
|
}
|
|
78
95
|
/**
|
|
79
96
|
* #### Schema
|
|
@@ -96,15 +113,17 @@ export type GalbeConfig = {
|
|
|
96
113
|
*/
|
|
97
114
|
export type RequestSchema<
|
|
98
115
|
Path extends string = string,
|
|
99
|
-
H extends STHeaders =
|
|
100
|
-
P extends Partial<STParams<Path>> =
|
|
101
|
-
Q extends STQuery =
|
|
102
|
-
B extends STBody = STBody
|
|
116
|
+
H extends STHeaders = STHeaders,
|
|
117
|
+
P extends Partial<STParams<Path>> = Partial<STParams<Path>>,
|
|
118
|
+
Q extends STQuery = STQuery,
|
|
119
|
+
B extends STBody = STBody,
|
|
120
|
+
R extends STResponse = STResponse
|
|
103
121
|
> = {
|
|
104
122
|
headers?: H
|
|
105
123
|
params?: P
|
|
106
124
|
query?: Q
|
|
107
125
|
body?: B
|
|
126
|
+
response?: R
|
|
108
127
|
}
|
|
109
128
|
|
|
110
129
|
type OmitNotDefined<S extends RequestSchema> = {
|
|
@@ -124,6 +143,7 @@ export type Context<Path extends string = string, S extends RequestSchema = Requ
|
|
|
124
143
|
query: Static<STObject<Exclude<S['query'], undefined>>>
|
|
125
144
|
body: Static<Exclude<S['body'], undefined>>
|
|
126
145
|
request: Request
|
|
146
|
+
route?: Route
|
|
127
147
|
state: Record<string, any>
|
|
128
148
|
set: {
|
|
129
149
|
headers: {
|
|
@@ -146,44 +166,48 @@ export type Endpoint = {
|
|
|
146
166
|
H extends STHeaders,
|
|
147
167
|
P extends Partial<STParams<Path>>,
|
|
148
168
|
Q extends STQuery,
|
|
149
|
-
B extends STBody = any
|
|
169
|
+
B extends STBody = any,
|
|
170
|
+
R extends STResponse = STResponse
|
|
150
171
|
>(
|
|
151
172
|
path: Path,
|
|
152
|
-
schema: RequestSchema<Path, H, P, Q, B>,
|
|
153
|
-
hooks: Hook<Path, RequestSchema<Path, H, P, Q, B>>[],
|
|
154
|
-
handler: Handler<Path, RequestSchema<Path, H, P, Q, B>>
|
|
173
|
+
schema: RequestSchema<Path, H, P, Q, B, R>,
|
|
174
|
+
hooks: Hook<Path, RequestSchema<Path, H, P, Q, B, R>>[],
|
|
175
|
+
handler: Handler<Path, RequestSchema<Path, H, P, Q, B, R>>
|
|
155
176
|
): void
|
|
156
177
|
<
|
|
157
178
|
Path extends string,
|
|
158
179
|
H extends STHeaders,
|
|
159
180
|
P extends Partial<STParams<Path>>,
|
|
160
181
|
Q extends STQuery,
|
|
161
|
-
B extends STBody = any
|
|
182
|
+
B extends STBody = any,
|
|
183
|
+
R extends STResponse = STResponse
|
|
162
184
|
>(
|
|
163
185
|
path: Path,
|
|
164
|
-
schema: RequestSchema<Path, H, P, Q, B>,
|
|
165
|
-
handler: Handler<Path, RequestSchema<Path, H, P, Q, B>>
|
|
186
|
+
schema: RequestSchema<Path, H, P, Q, B, R>,
|
|
187
|
+
handler: Handler<Path, RequestSchema<Path, H, P, Q, B, R>>
|
|
166
188
|
): void
|
|
167
189
|
<
|
|
168
190
|
Path extends string,
|
|
169
191
|
H extends STHeaders,
|
|
170
192
|
P extends Partial<STParams<Path>>,
|
|
171
193
|
Q extends STQuery,
|
|
172
|
-
B extends STBody = any
|
|
194
|
+
B extends STBody = any,
|
|
195
|
+
R extends STResponse = STResponse
|
|
173
196
|
>(
|
|
174
197
|
path: Path,
|
|
175
|
-
hooks: Hook<Path, RequestSchema<Path, H, P, Q, B>>[],
|
|
176
|
-
handler: Handler<Path, RequestSchema<Path, H, P, Q, B>>
|
|
198
|
+
hooks: Hook<Path, RequestSchema<Path, H, P, Q, B, R>>[],
|
|
199
|
+
handler: Handler<Path, RequestSchema<Path, H, P, Q, B, R>>
|
|
177
200
|
): void
|
|
178
201
|
<
|
|
179
202
|
Path extends string,
|
|
180
203
|
H extends STHeaders,
|
|
181
204
|
P extends Partial<STParams<Path>>,
|
|
182
205
|
Q extends STQuery,
|
|
183
|
-
B extends STBody = any
|
|
206
|
+
B extends STBody = any,
|
|
207
|
+
R extends STResponse = STResponse
|
|
184
208
|
>(
|
|
185
209
|
path: Path,
|
|
186
|
-
handler: Handler<Path, RequestSchema<Path, H, P, Q, B>>
|
|
210
|
+
handler: Handler<Path, RequestSchema<Path, H, P, Q, B, R>>
|
|
187
211
|
): void
|
|
188
212
|
}
|
|
189
213
|
|
|
@@ -192,7 +216,7 @@ export class RequestError {
|
|
|
192
216
|
payload: any
|
|
193
217
|
constructor(options: { status?: number; payload?: any }) {
|
|
194
218
|
this.status = options.status ?? 500
|
|
195
|
-
this.payload = options.payload
|
|
219
|
+
this.payload = options.payload
|
|
196
220
|
}
|
|
197
221
|
}
|
|
198
222
|
|
|
@@ -209,14 +233,15 @@ export type Route<
|
|
|
209
233
|
H extends STHeaders = {},
|
|
210
234
|
P extends Partial<STParams<Path>> = {},
|
|
211
235
|
Q extends STQuery = {},
|
|
212
|
-
B extends STBody = STBody
|
|
236
|
+
B extends STBody = STBody,
|
|
237
|
+
R extends STResponse = STResponse
|
|
213
238
|
> = {
|
|
214
239
|
method: Method
|
|
215
240
|
path: Path
|
|
216
|
-
schema: RequestSchema<Path, H, P, Q, B>
|
|
217
|
-
context: Context<Path, RequestSchema<Path, H, P, Q, B>>
|
|
241
|
+
schema: RequestSchema<Path, H, P, Q, B, R>
|
|
242
|
+
context: Context<Path, RequestSchema<Path, H, P, Q, B, R>>
|
|
218
243
|
hooks: Hook[]
|
|
219
|
-
handler: Handler<Path, RequestSchema<Path, H, P, Q, B>>
|
|
244
|
+
handler: Handler<Path, RequestSchema<Path, H, P, Q, B, R>>
|
|
220
245
|
}
|
|
221
246
|
|
|
222
247
|
export type RouteTree = {
|
|
@@ -224,13 +249,13 @@ export type RouteTree = {
|
|
|
224
249
|
}
|
|
225
250
|
|
|
226
251
|
export class NotFoundError extends RequestError {
|
|
227
|
-
constructor(message?:
|
|
252
|
+
constructor(message?: any) {
|
|
228
253
|
super({ status: 404, payload: message ?? 'Not found' })
|
|
229
254
|
}
|
|
230
255
|
}
|
|
231
256
|
|
|
232
257
|
export class InternalError extends RequestError {
|
|
233
|
-
constructor(message?:
|
|
258
|
+
constructor(message?: any) {
|
|
234
259
|
super({ status: 500, payload: message ?? 'Internal Server Error' })
|
|
235
260
|
}
|
|
236
261
|
}
|
|
@@ -259,8 +284,8 @@ export class InternalError extends RequestError {
|
|
|
259
284
|
export type GalbePlugin = {
|
|
260
285
|
name: string
|
|
261
286
|
init?: (config: any, galbe: Galbe) => MaybePromise<void>
|
|
262
|
-
onFetch?: (
|
|
263
|
-
onRoute?: (
|
|
287
|
+
onFetch?: (context: Context) => MaybePromise<Response | void>
|
|
288
|
+
onRoute?: (context: Context) => MaybePromise<Response | void>
|
|
264
289
|
beforeHandle?: (context: Context) => MaybePromise<Response | void>
|
|
265
|
-
afterHandle?: (response: Response) => MaybePromise<Response | void>
|
|
290
|
+
afterHandle?: (response: Response, context: Context) => MaybePromise<Response | void>
|
|
266
291
|
}
|
package/src/util.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { RouteFileMeta } from './routes'
|
|
2
|
+
|
|
1
3
|
const METHOD_COLOR: Record<string, string> = {
|
|
2
4
|
get: '\x1b[32m',
|
|
3
5
|
post: '\x1b[34m',
|
|
@@ -6,7 +8,21 @@ const METHOD_COLOR: Record<string, string> = {
|
|
|
6
8
|
delete: '\x1b[31m',
|
|
7
9
|
options: ''
|
|
8
10
|
}
|
|
9
|
-
|
|
11
|
+
|
|
12
|
+
export const extractMetaRoute = (route: { path: string; method: string }, meta?: Array<RouteFileMeta>) => {
|
|
13
|
+
return meta?.map(e => (route.path in e.routes ? e.routes[route.path]?.[route.method] : null)).filter(e => e)?.[0]
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const logRoute = (
|
|
17
|
+
r: { method: string; path: string },
|
|
18
|
+
meta?: Record<string, boolean | string | string[]> | null
|
|
19
|
+
) => {
|
|
10
20
|
let color = METHOD_COLOR?.[r.method] || ''
|
|
11
|
-
console.log(
|
|
21
|
+
console.log(
|
|
22
|
+
` [${color}${`${r.method.toUpperCase()}\x1b[0m]`.padEnd(12, ' ')} ${r.path}${
|
|
23
|
+
meta?.head ? ` - ${meta.head}` : ''
|
|
24
|
+
}`
|
|
25
|
+
)
|
|
12
26
|
}
|
|
27
|
+
|
|
28
|
+
export const isIterator = (obj: any) => typeof obj?.next === 'function'
|
package/src/validator.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { InternalError, type STResponse } from './index'
|
|
1
2
|
import type { STSchema, STProps, STUnion } from './schema'
|
|
2
|
-
import { Kind, Optional } from './schema'
|
|
3
|
+
import { Kind, Optional, Stream } from './schema'
|
|
4
|
+
import { isIterator } from './util'
|
|
3
5
|
|
|
4
6
|
export const validate = (elt: any, schema: STSchema, parse = false): any => {
|
|
5
7
|
type ValidationError = string | string[] | { [key: string]: ValidationError }
|
|
@@ -7,7 +9,10 @@ export const validate = (elt: any, schema: STSchema, parse = false): any => {
|
|
|
7
9
|
const iElt = elt
|
|
8
10
|
|
|
9
11
|
if (schema[Kind] === 'boolean') {
|
|
10
|
-
if (
|
|
12
|
+
if (typeof elt === 'string') {
|
|
13
|
+
if (parse) elt = elt === 'true' ? true : elt === 'false' ? false : null
|
|
14
|
+
else throw `Expected boolean, got string.`
|
|
15
|
+
}
|
|
11
16
|
if (elt !== true && elt !== false) throw `${iElt} is not a valid boolean. Should be 'true' or 'false'`
|
|
12
17
|
} else if (schema[Kind] === 'integer') {
|
|
13
18
|
if (parse && typeof elt === 'string') elt = Number(elt)
|
|
@@ -84,6 +89,22 @@ export const validate = (elt: any, schema: STSchema, parse = false): any => {
|
|
|
84
89
|
return elt
|
|
85
90
|
}
|
|
86
91
|
|
|
92
|
+
export const validateResponse = (response: any, schema: STResponse, status: number) => {
|
|
93
|
+
if (!(status in schema)) return
|
|
94
|
+
const s = schema[status]
|
|
95
|
+
if (response instanceof ReadableStream) {
|
|
96
|
+
if (!s[Stream]) throw new InternalError(`Expected ${s[Kind]} response, but got ReadableStream`)
|
|
97
|
+
} else if (isIterator(response)) {
|
|
98
|
+
if (!s[Stream]) throw new InternalError(`Expected ${s[Kind]} response, but got Iterator`)
|
|
99
|
+
} else {
|
|
100
|
+
try {
|
|
101
|
+
validate(response, s)
|
|
102
|
+
} catch (error) {
|
|
103
|
+
throw new InternalError({ ResponseValidationError: error })
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
87
108
|
const schemaValidation = (value: any, schema: STSchema) => {
|
|
88
109
|
const errors = []
|
|
89
110
|
if (schema[Kind] === 'integer' || schema[Kind] === 'number') {
|
|
@@ -92,9 +113,8 @@ const schemaValidation = (value: any, schema: STSchema) => {
|
|
|
92
113
|
if (schema.exclusiveMax !== undefined)
|
|
93
114
|
if ((value as number) >= schema.exclusiveMax)
|
|
94
115
|
errors.push(`${value} is greater or equal to ${schema.exclusiveMax}`)
|
|
95
|
-
if (schema.
|
|
96
|
-
|
|
97
|
-
if (schema.maximum !== undefined)
|
|
116
|
+
if (schema.min !== undefined) if ((value as number) < schema.min) errors.push(`${value} is less than ${schema.min}`)
|
|
117
|
+
if (schema.max !== undefined)
|
|
98
118
|
if ((value as number) > schema.max) errors.push(`${value} is greater than ${schema.max}`)
|
|
99
119
|
} else if (schema[Kind] === 'string') {
|
|
100
120
|
if (schema.minLength !== undefined && (value as string).length < schema.minLength)
|
package/test/plugins.test.ts
CHANGED
|
@@ -39,8 +39,8 @@ describe('plugins', async () => {
|
|
|
39
39
|
let request: any = null
|
|
40
40
|
const plugin: GalbePlugin = {
|
|
41
41
|
name: 'dev.galbe.test.init',
|
|
42
|
-
onFetch: mock(
|
|
43
|
-
request =
|
|
42
|
+
onFetch: mock(ctx => {
|
|
43
|
+
request = ctx.request
|
|
44
44
|
})
|
|
45
45
|
}
|
|
46
46
|
|
|
@@ -86,7 +86,7 @@ describe('plugins', async () => {
|
|
|
86
86
|
const plugin: GalbePlugin = {
|
|
87
87
|
name: 'dev.galbe.test.init',
|
|
88
88
|
onRoute: mock(r => {
|
|
89
|
-
route = r
|
|
89
|
+
route = r.route
|
|
90
90
|
})
|
|
91
91
|
}
|
|
92
92
|
|