@stacksjs/router 0.61.22 → 0.62.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/dist/index.js +184915 -76269
- package/package.json +5 -5
- package/src/request.ts +59 -3
- package/src/router.ts +12 -9
- package/src/server.ts +245 -54
- package/src/utils.ts +57 -22
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacksjs/router",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.62.0",
|
|
5
5
|
"description": "The Stacks framework router.",
|
|
6
6
|
"author": "Chris Breuer",
|
|
7
7
|
"license": "MIT",
|
|
@@ -49,14 +49,14 @@
|
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
51
|
"@stacksjs/config": "latest",
|
|
52
|
-
"unplugin-vue-router": "^0.
|
|
53
|
-
"vue-router": "^4.
|
|
52
|
+
"unplugin-vue-router": "^0.10.0",
|
|
53
|
+
"vue-router": "^4.4.0"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
56
|
"@stacksjs/config": "latest",
|
|
57
57
|
"@stacksjs/logging": "latest",
|
|
58
|
-
"unplugin-vue-router": "^0.
|
|
59
|
-
"vue-router": "^4.
|
|
58
|
+
"unplugin-vue-router": "^0.10.0",
|
|
59
|
+
"vue-router": "^4.4.0"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@stacksjs/development": "latest"
|
package/src/request.ts
CHANGED
|
@@ -1,15 +1,33 @@
|
|
|
1
|
-
import type { RequestInstance, RouteParam } from
|
|
1
|
+
import type { RequestInstance, RouteParam } from '@stacksjs/types'
|
|
2
|
+
|
|
3
|
+
import type { VineType } from '@stacksjs/types'
|
|
4
|
+
import { customValidate, validateField } from '@stacksjs/validation'
|
|
2
5
|
|
|
3
6
|
interface RequestData {
|
|
4
7
|
[key: string]: string
|
|
5
8
|
}
|
|
6
9
|
|
|
10
|
+
interface ValidationType {
|
|
11
|
+
rule: VineType
|
|
12
|
+
message: { [key: string]: string }
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface ValidationField {
|
|
16
|
+
[key: string]: string | ValidationType
|
|
17
|
+
validation: ValidationType
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface CustomAttributes {
|
|
21
|
+
[key: string]: ValidationField
|
|
22
|
+
}
|
|
23
|
+
|
|
7
24
|
type RouteParams = { [key: string]: string } | null
|
|
8
25
|
|
|
9
|
-
export class Request implements RequestInstance{
|
|
26
|
+
export class Request implements RequestInstance {
|
|
10
27
|
private static instance: Request
|
|
11
28
|
private query: RequestData = {}
|
|
12
29
|
private params: RouteParams = null
|
|
30
|
+
private headers: any = {}
|
|
13
31
|
|
|
14
32
|
// An attempt to singleston instance, might be needed at some point
|
|
15
33
|
public static getInstance(): Request {
|
|
@@ -23,10 +41,18 @@ export class Request implements RequestInstance{
|
|
|
23
41
|
this.query = Object.fromEntries(url.searchParams)
|
|
24
42
|
}
|
|
25
43
|
|
|
44
|
+
public addBodies(params: any): void {
|
|
45
|
+
this.query = params
|
|
46
|
+
}
|
|
47
|
+
|
|
26
48
|
public addParam(param: RouteParam): void {
|
|
27
49
|
this.params = param
|
|
28
50
|
}
|
|
29
51
|
|
|
52
|
+
public addHeaders(headerParams: Headers): void {
|
|
53
|
+
this.headers = headerParams
|
|
54
|
+
}
|
|
55
|
+
|
|
30
56
|
public get(element: string): string | number | undefined {
|
|
31
57
|
return this.query[element]
|
|
32
58
|
}
|
|
@@ -35,6 +61,14 @@ export class Request implements RequestInstance{
|
|
|
35
61
|
return this.query
|
|
36
62
|
}
|
|
37
63
|
|
|
64
|
+
public async validate(attributes?: CustomAttributes): Promise<void> {
|
|
65
|
+
if (attributes === undefined || attributes === null) {
|
|
66
|
+
await validateField('Release', this.all())
|
|
67
|
+
} else {
|
|
68
|
+
await customValidate(attributes, this.all())
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
38
72
|
public has(element: string): boolean {
|
|
39
73
|
return element in this.query
|
|
40
74
|
}
|
|
@@ -50,10 +84,32 @@ export class Request implements RequestInstance{
|
|
|
50
84
|
if (match?.groups) this.params = match.groups
|
|
51
85
|
}
|
|
52
86
|
|
|
87
|
+
public header(headerParam: string): string | number | boolean | null {
|
|
88
|
+
return this.headers.get(headerParam)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
public getHeaders() {
|
|
92
|
+
return this.headers
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
public Header(headerParam: string): string | number | boolean | null {
|
|
96
|
+
return this.headers.get(headerParam)
|
|
97
|
+
}
|
|
98
|
+
|
|
53
99
|
public getParam(key: string): number | string | null {
|
|
54
100
|
return this.params ? this.params[key] || null : null
|
|
55
101
|
}
|
|
56
102
|
|
|
103
|
+
public bearerToken(): string | null {
|
|
104
|
+
const authorizationHeader = this.headers.get('authorization')
|
|
105
|
+
|
|
106
|
+
if (authorizationHeader && authorizationHeader.startsWith('Bearer ')) {
|
|
107
|
+
return authorizationHeader.substring(7)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return null
|
|
111
|
+
}
|
|
112
|
+
|
|
57
113
|
public getParams(): RouteParams {
|
|
58
114
|
return this.params
|
|
59
115
|
}
|
|
@@ -62,6 +118,6 @@ export class Request implements RequestInstance{
|
|
|
62
118
|
const value = this.params ? this.params[key] || null : null
|
|
63
119
|
return value ? Number.parseInt(value) : null
|
|
64
120
|
}
|
|
65
|
-
}
|
|
121
|
+
}
|
|
66
122
|
|
|
67
123
|
export const request = new Request()
|
package/src/router.ts
CHANGED
|
@@ -3,10 +3,9 @@ import { log } from '@stacksjs/logging'
|
|
|
3
3
|
import { path as p, projectStoragePath, routesPath } from '@stacksjs/path'
|
|
4
4
|
import { kebabCase, pascalCase } from '@stacksjs/strings'
|
|
5
5
|
import type { Job } from '@stacksjs/types'
|
|
6
|
-
import { request } from '@stacksjs/router'
|
|
7
6
|
import type { RedirectCode, Route, RouteGroupOptions, RouterInterface, StatusCode } from '@stacksjs/types'
|
|
8
7
|
|
|
9
|
-
import { extractModelRequest } from './utils'
|
|
8
|
+
import { extractDynamicRequest, extractModelRequest } from './utils'
|
|
10
9
|
|
|
11
10
|
type ActionPath = string // TODO: narrow this by automating its generation
|
|
12
11
|
|
|
@@ -284,11 +283,9 @@ export class Router implements RouterInterface {
|
|
|
284
283
|
|
|
285
284
|
let actionModule = null
|
|
286
285
|
|
|
287
|
-
if (modulePath.includes('OrmAction'))
|
|
286
|
+
if (modulePath.includes('OrmAction'))
|
|
288
287
|
actionModule = await import(importPathFunction(`/framework/orm/${modulePath}.ts`))
|
|
289
|
-
|
|
290
|
-
actionModule = await import(importPathFunction(`${modulePath}.ts`))
|
|
291
|
-
}
|
|
288
|
+
else actionModule = await import(importPathFunction(`${modulePath}.ts`))
|
|
292
289
|
|
|
293
290
|
// Use custom path from action module if available
|
|
294
291
|
const newPath = actionModule.default.path ?? originalPath
|
|
@@ -301,10 +298,16 @@ export class Router implements RouterInterface {
|
|
|
301
298
|
// then validate
|
|
302
299
|
// if succeeds, run the handle
|
|
303
300
|
// if fails, return validation error
|
|
301
|
+
let requestInstance
|
|
302
|
+
|
|
303
|
+
if (modulePath.includes('OrmAction')) requestInstance = await extractModelRequest(modulePath)
|
|
304
|
+
else requestInstance = await extractDynamicRequest(modulePath)
|
|
304
305
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
306
|
+
try {
|
|
307
|
+
return await actionModule.default.handle(requestInstance)
|
|
308
|
+
} catch (error: any) {
|
|
309
|
+
return { status: error.status, errors: error.errors }
|
|
310
|
+
}
|
|
308
311
|
}
|
|
309
312
|
|
|
310
313
|
private normalizePath(path: string): string {
|
package/src/server.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import process from 'node:process'
|
|
2
2
|
import { log } from '@stacksjs/logging'
|
|
3
|
-
import {
|
|
3
|
+
import { getModelName } from '@stacksjs/orm'
|
|
4
|
+
import { path, extname } from '@stacksjs/path'
|
|
4
5
|
import { glob } from '@stacksjs/storage'
|
|
6
|
+
import { camelCase, lowercase } from '@stacksjs/strings'
|
|
5
7
|
import type { Model, Route, RouteParam, StatusCode } from '@stacksjs/types'
|
|
6
8
|
import { route } from '.'
|
|
7
9
|
import { middlewares } from './middleware'
|
|
8
10
|
import { request as RequestParam } from './request'
|
|
9
|
-
import { getModelName } from '@stacksjs/orm'
|
|
10
|
-
import { lowercase } from '@stacksjs/strings'
|
|
11
11
|
|
|
12
12
|
interface ServeOptions {
|
|
13
13
|
host?: string
|
|
@@ -33,12 +33,14 @@ export async function serve(options: ServeOptions = {}) {
|
|
|
33
33
|
development,
|
|
34
34
|
|
|
35
35
|
async fetch(req: Request) {
|
|
36
|
-
|
|
36
|
+
const reqBody = await req.text()
|
|
37
|
+
|
|
38
|
+
return await serverResponse(req, reqBody)
|
|
37
39
|
},
|
|
38
40
|
})
|
|
39
41
|
}
|
|
40
42
|
|
|
41
|
-
export async function serverResponse(req: Request) {
|
|
43
|
+
export async function serverResponse(req: Request, body: string) {
|
|
42
44
|
log.info(`Incoming Request: ${req.method} ${req.url}`)
|
|
43
45
|
log.info(`Headers: ${JSON.stringify(req.headers)}`)
|
|
44
46
|
log.info(`Body: ${JSON.stringify(req.body)}`)
|
|
@@ -58,6 +60,10 @@ export async function serverResponse(req: Request) {
|
|
|
58
60
|
|
|
59
61
|
log.info(`URL: ${JSON.stringify(url)}`)
|
|
60
62
|
|
|
63
|
+
if (req.method === 'OPTIONS') {
|
|
64
|
+
return handleOptions(req)
|
|
65
|
+
}
|
|
66
|
+
|
|
61
67
|
const foundRoute: Route | undefined = routesList
|
|
62
68
|
.filter((route: Route) => {
|
|
63
69
|
const pattern = new RegExp(`^${route.uri.replace(/\{(\w+)\}/g, '(\\w+)')}$`)
|
|
@@ -67,21 +73,45 @@ export async function serverResponse(req: Request) {
|
|
|
67
73
|
.find((route: Route) => route.method === req.method)
|
|
68
74
|
|
|
69
75
|
log.info(`Found Route: ${JSON.stringify(foundRoute)}`)
|
|
70
|
-
// if (url.pathname === '/favicon.ico')
|
|
71
|
-
// return new Response('')
|
|
72
76
|
|
|
73
|
-
if (!foundRoute)
|
|
77
|
+
if (!foundRoute) {
|
|
78
|
+
return new Response('Pretty 404 page coming soon', {
|
|
79
|
+
status: 404,
|
|
80
|
+
headers: {
|
|
81
|
+
'Access-Control-Allow-Origin': '*',
|
|
82
|
+
'Access-Control-Allow-Headers': '*',
|
|
83
|
+
'Content-Type': 'json',
|
|
84
|
+
},
|
|
85
|
+
}) // TODO: create a pretty 404 page
|
|
86
|
+
}
|
|
74
87
|
|
|
75
88
|
const routeParams = extractDynamicSegments(foundRoute.uri, url.pathname)
|
|
76
89
|
|
|
77
|
-
|
|
78
|
-
|
|
90
|
+
if (!body) {
|
|
91
|
+
await addRouteQuery(url)
|
|
92
|
+
} else {
|
|
93
|
+
await addBody(body)
|
|
94
|
+
}
|
|
79
95
|
|
|
80
|
-
await
|
|
96
|
+
await addRouteParam(routeParams)
|
|
97
|
+
await addHeaders(req.headers)
|
|
81
98
|
|
|
82
99
|
return await execute(foundRoute, req, { statusCode: foundRoute?.statusCode })
|
|
83
100
|
}
|
|
84
101
|
|
|
102
|
+
function handleOptions(req: Request) {
|
|
103
|
+
return new Response(null, {
|
|
104
|
+
status: 204,
|
|
105
|
+
headers: {
|
|
106
|
+
'Access-Control-Allow-Origin': '*',
|
|
107
|
+
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
|
|
108
|
+
'Access-Control-Allow-Headers':
|
|
109
|
+
'Content-Type, Authorization, Access-Control-Allow-Headers, Access-Control-Allow-Origin, Accept',
|
|
110
|
+
'Access-Control-Max-Age': '86400', // Cache the preflight response for a day
|
|
111
|
+
},
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
|
|
85
115
|
function extractDynamicSegments(routePattern: string, path: string): RouteParam {
|
|
86
116
|
const regexPattern = new RegExp(`^${routePattern.replace(/\{(\w+)\}/g, '(\\w+)')}$`)
|
|
87
117
|
const match = path.match(regexPattern)
|
|
@@ -103,6 +133,27 @@ function extractDynamicSegments(routePattern: string, path: string): RouteParam
|
|
|
103
133
|
async function execute(foundRoute: Route, req: Request, { statusCode }: Options) {
|
|
104
134
|
const foundCallback = await route.resolveCallback(foundRoute.callback)
|
|
105
135
|
|
|
136
|
+
const middlewarePayload = await executeMiddleware(foundRoute)
|
|
137
|
+
|
|
138
|
+
if (
|
|
139
|
+
middlewarePayload !== null &&
|
|
140
|
+
typeof middlewarePayload === 'object' &&
|
|
141
|
+
Object.keys(middlewarePayload).length > 0
|
|
142
|
+
) {
|
|
143
|
+
const middlewareStatus = middlewarePayload.status
|
|
144
|
+
|
|
145
|
+
delete middlewarePayload.status
|
|
146
|
+
|
|
147
|
+
return await new Response(JSON.stringify(middlewarePayload), {
|
|
148
|
+
headers: {
|
|
149
|
+
'Content-Type': 'json',
|
|
150
|
+
'Access-Control-Allow-Origin': '*',
|
|
151
|
+
'Access-Control-Allow-Headers': '*',
|
|
152
|
+
},
|
|
153
|
+
status: middlewareStatus || 401,
|
|
154
|
+
})
|
|
155
|
+
}
|
|
156
|
+
|
|
106
157
|
if (!statusCode) statusCode = 200
|
|
107
158
|
|
|
108
159
|
if (foundRoute?.method === 'GET' && (statusCode === 301 || statusCode === 302)) {
|
|
@@ -112,7 +163,14 @@ async function execute(foundRoute: Route, req: Request, { statusCode }: Options)
|
|
|
112
163
|
return await noCache(response)
|
|
113
164
|
}
|
|
114
165
|
|
|
115
|
-
if (foundRoute?.method !== req.method)
|
|
166
|
+
if (foundRoute?.method !== req.method)
|
|
167
|
+
return new Response('Method not allowed', {
|
|
168
|
+
status: 405,
|
|
169
|
+
headers: {
|
|
170
|
+
'Access-Control-Allow-Origin': '*',
|
|
171
|
+
'Access-Control-Allow-Headers': '*',
|
|
172
|
+
},
|
|
173
|
+
})
|
|
116
174
|
|
|
117
175
|
// Check if it's a path to an HTML file
|
|
118
176
|
if (isString(foundCallback) && extname(foundCallback) === '.html') {
|
|
@@ -120,25 +178,117 @@ async function execute(foundRoute: Route, req: Request, { statusCode }: Options)
|
|
|
120
178
|
const fileContent = Bun.file(foundCallback)
|
|
121
179
|
|
|
122
180
|
return await new Response(fileContent, {
|
|
123
|
-
headers: {
|
|
181
|
+
headers: {
|
|
182
|
+
'Content-Type': 'text/html',
|
|
183
|
+
'Access-Control-Allow-Origin': '*',
|
|
184
|
+
'Access-Control-Allow-Headers': '*',
|
|
185
|
+
},
|
|
124
186
|
})
|
|
125
187
|
} catch (error) {
|
|
126
|
-
return await new Response('Error reading the HTML file', {
|
|
188
|
+
return await new Response('Error reading the HTML file', {
|
|
189
|
+
status: 500,
|
|
190
|
+
headers: {
|
|
191
|
+
'Access-Control-Allow-Origin': '*',
|
|
192
|
+
'Access-Control-Allow-Headers': '*',
|
|
193
|
+
},
|
|
194
|
+
})
|
|
127
195
|
}
|
|
128
196
|
}
|
|
129
197
|
|
|
130
|
-
if (isString(foundCallback))
|
|
198
|
+
if (isString(foundCallback))
|
|
199
|
+
return await new Response(foundCallback, {
|
|
200
|
+
headers: {
|
|
201
|
+
'Content-Type': 'json',
|
|
202
|
+
'Access-Control-Allow-Origin': '*',
|
|
203
|
+
'Access-Control-Allow-Headers': '*',
|
|
204
|
+
},
|
|
205
|
+
status: 200,
|
|
206
|
+
})
|
|
131
207
|
|
|
132
208
|
if (isFunction(foundCallback)) {
|
|
133
209
|
const result = foundCallback()
|
|
134
210
|
|
|
135
|
-
return await new Response(JSON.stringify(result)
|
|
211
|
+
return await new Response(JSON.stringify(result), {
|
|
212
|
+
status: 200,
|
|
213
|
+
headers: {
|
|
214
|
+
'Access-Control-Allow-Origin': '*',
|
|
215
|
+
'Access-Control-Allow-Headers': '*',
|
|
216
|
+
},
|
|
217
|
+
})
|
|
136
218
|
}
|
|
137
219
|
|
|
138
|
-
if (isObject(foundCallback)
|
|
220
|
+
if (isObject(foundCallback) && foundCallback.status) {
|
|
221
|
+
if (foundCallback.status === 401) {
|
|
222
|
+
delete foundCallback.status
|
|
223
|
+
|
|
224
|
+
return await new Response(JSON.stringify(foundCallback), {
|
|
225
|
+
headers: {
|
|
226
|
+
'Content-Type': 'json',
|
|
227
|
+
'Access-Control-Allow-Origin': '*',
|
|
228
|
+
'Access-Control-Allow-Headers': '*',
|
|
229
|
+
},
|
|
230
|
+
status: 401,
|
|
231
|
+
})
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (foundCallback.status === 403) {
|
|
235
|
+
delete foundCallback.status
|
|
236
|
+
return await new Response(JSON.stringify(foundCallback), {
|
|
237
|
+
headers: {
|
|
238
|
+
'Content-Type': 'json',
|
|
239
|
+
'Access-Control-Allow-Origin': '*',
|
|
240
|
+
'Access-Control-Allow-Headers': '*',
|
|
241
|
+
},
|
|
242
|
+
status: 403,
|
|
243
|
+
})
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (foundCallback.status === 422) {
|
|
247
|
+
// biome-ignore lint/performance/noDelete: <explanation>
|
|
248
|
+
delete foundCallback.status
|
|
249
|
+
|
|
250
|
+
return await new Response(JSON.stringify(foundCallback), {
|
|
251
|
+
headers: {
|
|
252
|
+
'Content-Type': 'json',
|
|
253
|
+
'Access-Control-Allow-Origin': '*',
|
|
254
|
+
'Access-Control-Allow-Headers': '*',
|
|
255
|
+
},
|
|
256
|
+
status: 422,
|
|
257
|
+
})
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (foundCallback.status === 500) {
|
|
261
|
+
delete foundCallback.status
|
|
262
|
+
return await new Response(JSON.stringify(foundCallback), {
|
|
263
|
+
headers: {
|
|
264
|
+
'Content-Type': 'json',
|
|
265
|
+
'Access-Control-Allow-Origin': '*',
|
|
266
|
+
'Access-Control-Allow-Headers': '*',
|
|
267
|
+
},
|
|
268
|
+
status: 500,
|
|
269
|
+
})
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (isObject(foundCallback))
|
|
274
|
+
return await new Response(JSON.stringify(foundCallback), {
|
|
275
|
+
headers: {
|
|
276
|
+
'Content-Type': 'json',
|
|
277
|
+
'Access-Control-Allow-Origin': '*',
|
|
278
|
+
'Access-Control-Allow-Headers': '*',
|
|
279
|
+
},
|
|
280
|
+
status: 200,
|
|
281
|
+
})
|
|
139
282
|
|
|
140
283
|
// If no known type matched, return a generic error.
|
|
141
|
-
return await new Response('Unknown callback type.', {
|
|
284
|
+
return await new Response('Unknown callback type.', {
|
|
285
|
+
headers: {
|
|
286
|
+
'Content-Type': 'json',
|
|
287
|
+
'Access-Control-Allow-Origin': '*',
|
|
288
|
+
'Access-Control-Allow-Headers': '*',
|
|
289
|
+
},
|
|
290
|
+
status: 500,
|
|
291
|
+
})
|
|
142
292
|
}
|
|
143
293
|
|
|
144
294
|
function noCache(response: Response) {
|
|
@@ -150,67 +300,108 @@ function noCache(response: Response) {
|
|
|
150
300
|
}
|
|
151
301
|
|
|
152
302
|
async function addRouteQuery(url: URL) {
|
|
153
|
-
const modelFiles = glob.sync(path.userModelsPath('*.ts'))
|
|
303
|
+
const modelFiles = glob.sync(path.userModelsPath('*.ts'))
|
|
154
304
|
|
|
155
305
|
for (const modelFile of modelFiles) {
|
|
156
|
-
const model = (await import(modelFile)).default
|
|
157
|
-
const modelName = getModelName(model, modelFile)
|
|
158
|
-
const modelNameLower = `${
|
|
159
|
-
const requestPath = path.projectStoragePath(`framework/requests/${modelName}Request.ts`)
|
|
160
|
-
const requestImport = await import(requestPath)
|
|
161
|
-
const requestInstance = requestImport[modelNameLower]
|
|
162
|
-
|
|
163
|
-
if (requestInstance
|
|
164
|
-
requestInstance.addQuery(url)
|
|
306
|
+
const model = (await import(modelFile)).default
|
|
307
|
+
const modelName = getModelName(model, modelFile)
|
|
308
|
+
const modelNameLower = `${camelCase(modelName)}Request`
|
|
309
|
+
const requestPath = path.projectStoragePath(`framework/requests/${modelName}Request.ts`)
|
|
310
|
+
const requestImport = await import(requestPath)
|
|
311
|
+
const requestInstance = requestImport[modelNameLower]
|
|
312
|
+
|
|
313
|
+
if (requestInstance) {
|
|
314
|
+
requestInstance.addQuery(url)
|
|
165
315
|
}
|
|
166
316
|
}
|
|
167
317
|
|
|
168
|
-
|
|
169
|
-
|
|
318
|
+
RequestParam.addQuery(url)
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
async function addBody(params: any) {
|
|
322
|
+
const modelFiles = glob.sync(path.userModelsPath('*.ts'))
|
|
323
|
+
|
|
324
|
+
for (const modelFile of modelFiles) {
|
|
325
|
+
const model = (await import(modelFile)).default
|
|
326
|
+
const modelName = getModelName(model, modelFile)
|
|
327
|
+
const modelNameLower = `${camelCase(modelName)}Request`
|
|
328
|
+
const requestPath = path.projectStoragePath(`framework/requests/${modelName}Request.ts`)
|
|
329
|
+
const requestImport = await import(requestPath)
|
|
330
|
+
const requestInstance = requestImport[modelNameLower]
|
|
331
|
+
|
|
332
|
+
if (requestInstance) {
|
|
333
|
+
requestInstance.addBodies(JSON.parse(params))
|
|
334
|
+
}
|
|
170
335
|
}
|
|
336
|
+
|
|
337
|
+
RequestParam.addBodies(JSON.parse(params))
|
|
171
338
|
}
|
|
172
339
|
|
|
173
340
|
async function addRouteParam(param: RouteParam): Promise<void> {
|
|
174
|
-
const modelFiles = glob.sync(path.userModelsPath('*.ts'))
|
|
341
|
+
const modelFiles = glob.sync(path.userModelsPath('*.ts'))
|
|
175
342
|
|
|
176
343
|
for (const modelFile of modelFiles) {
|
|
177
|
-
const model = (await import(modelFile)).default as Model
|
|
178
|
-
const modelName = getModelName(model, modelFile)
|
|
179
|
-
const modelNameLower = `${lowercase(modelName)}Request
|
|
180
|
-
const requestPath = path.projectStoragePath(`framework/requests/${modelName}Request.ts`)
|
|
181
|
-
const requestImport = await import(requestPath)
|
|
182
|
-
const requestInstance = requestImport[modelNameLower]
|
|
344
|
+
const model = (await import(modelFile)).default as Model
|
|
345
|
+
const modelName = getModelName(model, modelFile)
|
|
346
|
+
const modelNameLower = `${lowercase(modelName)}Request`
|
|
347
|
+
const requestPath = path.projectStoragePath(`framework/requests/${modelName}Request.ts`)
|
|
348
|
+
const requestImport = await import(requestPath)
|
|
349
|
+
const requestInstance = requestImport[modelNameLower]
|
|
183
350
|
|
|
184
351
|
if (requestInstance) {
|
|
185
|
-
requestInstance.addParam(param)
|
|
352
|
+
requestInstance.addParam(param)
|
|
186
353
|
}
|
|
187
354
|
}
|
|
188
355
|
|
|
189
356
|
RequestParam.addParam(param)
|
|
190
357
|
}
|
|
191
358
|
|
|
192
|
-
function
|
|
359
|
+
async function addHeaders(headers: Headers): Promise<void> {
|
|
360
|
+
const modelFiles = glob.sync(path.userModelsPath('*.ts'))
|
|
361
|
+
|
|
362
|
+
for (const modelFile of modelFiles) {
|
|
363
|
+
const model = (await import(modelFile)).default as Model
|
|
364
|
+
const modelName = getModelName(model, modelFile)
|
|
365
|
+
const modelNameLower = `${lowercase(modelName)}Request`
|
|
366
|
+
const requestPath = path.projectStoragePath(`framework/requests/${modelName}Request.ts`)
|
|
367
|
+
const requestImport = await import(requestPath)
|
|
368
|
+
const requestInstance = requestImport[modelNameLower]
|
|
369
|
+
|
|
370
|
+
if (requestInstance) {
|
|
371
|
+
requestInstance.addHeaders(headers)
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
RequestParam.addHeaders(headers)
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
async function executeMiddleware(route: Route): Promise<any> {
|
|
193
379
|
const { middleware = null } = route
|
|
194
380
|
|
|
195
381
|
if (middleware && middlewares && isObjectNotEmpty(middlewares)) {
|
|
196
382
|
// let middlewareItem: MiddlewareOptions
|
|
197
383
|
if (isString(middleware)) {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
384
|
+
const middlewarePath = path.userMiddlewarePath(`${middleware}.ts`)
|
|
385
|
+
|
|
386
|
+
const middlewareInstance = (await import(middlewarePath)).default
|
|
387
|
+
|
|
388
|
+
try {
|
|
389
|
+
await middlewareInstance.handle()
|
|
390
|
+
} catch (error: any) {
|
|
391
|
+
return error
|
|
392
|
+
}
|
|
204
393
|
} else {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
394
|
+
for (const middlewareElement of middleware) {
|
|
395
|
+
const middlewarePath = path.userMiddlewarePath(`${middlewareElement}.ts`)
|
|
396
|
+
|
|
397
|
+
const middlewareInstance = (await import(middlewarePath)).default
|
|
398
|
+
|
|
399
|
+
try {
|
|
400
|
+
await middlewareInstance.handle()
|
|
401
|
+
} catch (error: any) {
|
|
402
|
+
return error
|
|
403
|
+
}
|
|
404
|
+
}
|
|
214
405
|
}
|
|
215
406
|
}
|
|
216
407
|
}
|