@stacksjs/router 0.66.0 → 0.67.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 +68 -62
- package/package.json +12 -14
- package/dist/index.js.map +0 -762
- package/src/index.ts +0 -5
- package/src/middleware.ts +0 -35
- package/src/request.ts +0 -112
- package/src/router.ts +0 -358
- package/src/server.ts +0 -468
- package/src/utils.ts +0 -88
package/src/server.ts
DELETED
|
@@ -1,468 +0,0 @@
|
|
|
1
|
-
import type { Model, Route, RouteParam, StatusCode } from '@stacksjs/types'
|
|
2
|
-
import process from 'node:process'
|
|
3
|
-
import { handleError } from '@stacksjs/error-handling'
|
|
4
|
-
import { log } from '@stacksjs/logging'
|
|
5
|
-
import { getModelName } from '@stacksjs/orm'
|
|
6
|
-
import { extname, path } from '@stacksjs/path'
|
|
7
|
-
import { globSync } from '@stacksjs/storage'
|
|
8
|
-
import { route } from '.'
|
|
9
|
-
import { middlewares } from './middleware'
|
|
10
|
-
import { request as RequestParam } from './request'
|
|
11
|
-
|
|
12
|
-
interface ServeOptions {
|
|
13
|
-
host?: string
|
|
14
|
-
port?: number
|
|
15
|
-
debug?: boolean
|
|
16
|
-
timezone?: string
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
interface Options {
|
|
20
|
-
statusCode?: StatusCode
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export async function serve(options: ServeOptions = {}): Promise<void> {
|
|
24
|
-
const hostname = options.host || 'localhost'
|
|
25
|
-
const port = options.port || 3000
|
|
26
|
-
const development = options.debug ? true : process.env.APP_ENV !== 'production' && process.env.APP_ENV !== 'prod'
|
|
27
|
-
|
|
28
|
-
if (options.timezone)
|
|
29
|
-
process.env.TZ = options.timezone
|
|
30
|
-
|
|
31
|
-
Bun.serve({
|
|
32
|
-
hostname,
|
|
33
|
-
port,
|
|
34
|
-
development,
|
|
35
|
-
|
|
36
|
-
async fetch(req: Request) {
|
|
37
|
-
const reqBody = await req.text()
|
|
38
|
-
|
|
39
|
-
return await serverResponse(req, reqBody)
|
|
40
|
-
},
|
|
41
|
-
})
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export async function serverResponse(req: Request, body: string): Promise<Response> {
|
|
45
|
-
log.debug(`Incoming Request: ${req.method} ${req.url}`)
|
|
46
|
-
log.debug(`Headers: ${JSON.stringify(req.headers)}`)
|
|
47
|
-
log.debug(`Body: ${JSON.stringify(req.body)}`)
|
|
48
|
-
// log.debug(`Query: ${JSON.stringify(req.query)}`)
|
|
49
|
-
// log.debug(`Params: ${JSON.stringify(req.params)}`)
|
|
50
|
-
// log.debug(`Cookies: ${JSON.stringify(req.cookies)}`)
|
|
51
|
-
|
|
52
|
-
// Trim trailing slash from the URL if it's not the root '/'
|
|
53
|
-
// This automatically allows for route definitions, like
|
|
54
|
-
// '/about' and '/about/' to be treated as the same
|
|
55
|
-
const trimmedUrl = req.url.endsWith('/') && req.url.length > 1 ? req.url.slice(0, -1) : req.url
|
|
56
|
-
const url = new URL(trimmedUrl)
|
|
57
|
-
const routesList: Route[] = await route.getRoutes()
|
|
58
|
-
|
|
59
|
-
log.info(`Routes List: ${JSON.stringify(routesList)}`)
|
|
60
|
-
log.info(`URL: ${JSON.stringify(url)}`)
|
|
61
|
-
|
|
62
|
-
if (req.method === 'OPTIONS') {
|
|
63
|
-
return handleOptions(req)
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const foundRoute: Route | undefined = routesList
|
|
67
|
-
.filter((route: Route) => {
|
|
68
|
-
const pattern = new RegExp(`^${route.uri.replace(/\{(\w+)\}/g, '(\\w+)')}$`)
|
|
69
|
-
|
|
70
|
-
return pattern.test(url.pathname)
|
|
71
|
-
})
|
|
72
|
-
.find((route: Route) => route.method === req.method)
|
|
73
|
-
|
|
74
|
-
log.info(`Found Route: ${JSON.stringify(foundRoute)}`)
|
|
75
|
-
|
|
76
|
-
if (!foundRoute) {
|
|
77
|
-
// TODO: create a pretty 404 page
|
|
78
|
-
return new Response('<html><body><h1>Page not found!</h1<pre></pre></body></html>', {
|
|
79
|
-
status: 404,
|
|
80
|
-
headers: {
|
|
81
|
-
'Access-Control-Allow-Origin': '*',
|
|
82
|
-
'Access-Control-Allow-Headers': '*',
|
|
83
|
-
'Content-Type': 'application/json',
|
|
84
|
-
},
|
|
85
|
-
})
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const routeParams = extractDynamicSegments(foundRoute.uri, url.pathname)
|
|
89
|
-
|
|
90
|
-
if (!body) {
|
|
91
|
-
await addRouteQuery(url)
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
await addBody(body)
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
await addRouteParam(routeParams)
|
|
98
|
-
await addHeaders(req.headers)
|
|
99
|
-
|
|
100
|
-
return await execute(foundRoute, req, { statusCode: foundRoute?.statusCode })
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function handleOptions() {
|
|
104
|
-
return new Response(null, {
|
|
105
|
-
status: 204,
|
|
106
|
-
headers: {
|
|
107
|
-
'Access-Control-Allow-Origin': '*',
|
|
108
|
-
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
|
|
109
|
-
'Access-Control-Allow-Headers':
|
|
110
|
-
'Content-Type, Authorization, Access-Control-Allow-Headers, Access-Control-Allow-Origin, Accept',
|
|
111
|
-
'Access-Control-Max-Age': '86400', // Cache the preflight response for a day
|
|
112
|
-
},
|
|
113
|
-
})
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function extractDynamicSegments(routePattern: string, path: string): RouteParam {
|
|
117
|
-
const regexPattern = new RegExp(`^${routePattern.replace(/\{(\w+)\}/g, '(\\w+)')}$`)
|
|
118
|
-
const match = path.match(regexPattern)
|
|
119
|
-
|
|
120
|
-
if (!match) {
|
|
121
|
-
return null
|
|
122
|
-
}
|
|
123
|
-
const dynamicSegmentNames = [...routePattern.matchAll(/\{(\w+)\}/g)].map(m => m[1])
|
|
124
|
-
const dynamicSegmentValues = match.slice(1) // First match is the whole string, so we slice it off
|
|
125
|
-
|
|
126
|
-
const dynamicSegments: { [key: string]: string } = {}
|
|
127
|
-
dynamicSegmentNames.forEach((name, index) => {
|
|
128
|
-
if (name && dynamicSegmentValues[index] !== undefined) {
|
|
129
|
-
dynamicSegments[name] = dynamicSegmentValues[index] // Ensure value is defined
|
|
130
|
-
}
|
|
131
|
-
})
|
|
132
|
-
return dynamicSegments
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
type CallbackWithStatus = Route['callback'] & { status: number }
|
|
136
|
-
|
|
137
|
-
async function execute(foundRoute: Route, req: Request, { statusCode }: Options) {
|
|
138
|
-
const foundCallback: CallbackWithStatus = await route.resolveCallback(foundRoute.callback)
|
|
139
|
-
|
|
140
|
-
const middlewarePayload = await executeMiddleware(foundRoute)
|
|
141
|
-
|
|
142
|
-
if (
|
|
143
|
-
middlewarePayload !== null
|
|
144
|
-
&& typeof middlewarePayload === 'object'
|
|
145
|
-
&& Object.keys(middlewarePayload).length > 0
|
|
146
|
-
) {
|
|
147
|
-
const middlewareStatus = middlewarePayload.status
|
|
148
|
-
|
|
149
|
-
const { status, ...payloadWithoutStatus } = middlewarePayload
|
|
150
|
-
|
|
151
|
-
return new Response(JSON.stringify(payloadWithoutStatus), {
|
|
152
|
-
headers: {
|
|
153
|
-
'Content-Type': 'application/json',
|
|
154
|
-
'Access-Control-Allow-Origin': '*',
|
|
155
|
-
'Access-Control-Allow-Headers': '*',
|
|
156
|
-
},
|
|
157
|
-
status: middlewareStatus || 401,
|
|
158
|
-
})
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
if (!statusCode)
|
|
162
|
-
statusCode = 200
|
|
163
|
-
|
|
164
|
-
if (foundRoute?.method === 'GET' && (statusCode === 301 || statusCode === 302)) {
|
|
165
|
-
const callback = String(foundCallback)
|
|
166
|
-
const response = Response.redirect(callback, statusCode)
|
|
167
|
-
|
|
168
|
-
return noCache(response)
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
if (foundRoute?.method !== req.method) {
|
|
172
|
-
return new Response('Method not allowed', {
|
|
173
|
-
status: 405,
|
|
174
|
-
headers: {
|
|
175
|
-
'Access-Control-Allow-Origin': '*',
|
|
176
|
-
'Access-Control-Allow-Headers': '*',
|
|
177
|
-
},
|
|
178
|
-
})
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
// Check if it's a path to an HTML file
|
|
182
|
-
if (isString(foundCallback) && extname(foundCallback) === '.html') {
|
|
183
|
-
try {
|
|
184
|
-
const fileContent = Bun.file(foundCallback)
|
|
185
|
-
|
|
186
|
-
return new Response(fileContent, {
|
|
187
|
-
headers: {
|
|
188
|
-
'Content-Type': 'text/html',
|
|
189
|
-
'Access-Control-Allow-Origin': '*',
|
|
190
|
-
'Access-Control-Allow-Headers': '*',
|
|
191
|
-
},
|
|
192
|
-
})
|
|
193
|
-
}
|
|
194
|
-
catch (error) {
|
|
195
|
-
handleError('Error reading the HTML file', error)
|
|
196
|
-
return new Response('Error reading the HTML file', {
|
|
197
|
-
status: 500,
|
|
198
|
-
headers: {
|
|
199
|
-
'Access-Control-Allow-Origin': '*',
|
|
200
|
-
'Access-Control-Allow-Headers': '*',
|
|
201
|
-
},
|
|
202
|
-
})
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
if (isString(foundCallback)) {
|
|
207
|
-
return new Response(foundCallback, {
|
|
208
|
-
headers: {
|
|
209
|
-
'Content-Type': 'application/json',
|
|
210
|
-
'Access-Control-Allow-Origin': '*',
|
|
211
|
-
'Access-Control-Allow-Headers': '*',
|
|
212
|
-
},
|
|
213
|
-
status: 200,
|
|
214
|
-
})
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
if (foundCallback === undefined || foundCallback === null) {
|
|
218
|
-
return new Response('', {
|
|
219
|
-
headers: {
|
|
220
|
-
'Content-Type': 'application/json',
|
|
221
|
-
'Access-Control-Allow-Origin': '*',
|
|
222
|
-
'Access-Control-Allow-Headers': '*',
|
|
223
|
-
},
|
|
224
|
-
status: 204,
|
|
225
|
-
})
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
if (isFunction(foundCallback)) {
|
|
229
|
-
const result = foundCallback()
|
|
230
|
-
|
|
231
|
-
return new Response(JSON.stringify(result), {
|
|
232
|
-
status: 200,
|
|
233
|
-
headers: {
|
|
234
|
-
'Access-Control-Allow-Origin': '*',
|
|
235
|
-
'Access-Control-Allow-Headers': '*',
|
|
236
|
-
},
|
|
237
|
-
})
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
if (isObject(foundCallback) && foundCallback.status) {
|
|
241
|
-
if (foundCallback.status === 401) {
|
|
242
|
-
const { status, ...rest } = await foundCallback
|
|
243
|
-
|
|
244
|
-
return new Response(JSON.stringify(rest), {
|
|
245
|
-
headers: {
|
|
246
|
-
'Content-Type': 'application/json',
|
|
247
|
-
'Access-Control-Allow-Origin': '*',
|
|
248
|
-
'Access-Control-Allow-Headers': '*',
|
|
249
|
-
},
|
|
250
|
-
status: 401,
|
|
251
|
-
})
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
if (foundCallback.status === 404) {
|
|
255
|
-
const { status, ...rest } = await foundCallback
|
|
256
|
-
|
|
257
|
-
const { errors } = rest
|
|
258
|
-
|
|
259
|
-
return new Response(JSON.stringify(errors), {
|
|
260
|
-
headers: {
|
|
261
|
-
'Content-Type': 'application/json',
|
|
262
|
-
'Access-Control-Allow-Origin': '*',
|
|
263
|
-
'Access-Control-Allow-Headers': '*',
|
|
264
|
-
},
|
|
265
|
-
status: 404,
|
|
266
|
-
})
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
if (foundCallback.status === 403) {
|
|
270
|
-
const { status, ...rest } = await foundCallback
|
|
271
|
-
const { errors } = rest
|
|
272
|
-
return new Response(JSON.stringify(errors), {
|
|
273
|
-
headers: {
|
|
274
|
-
'Content-Type': 'application/json',
|
|
275
|
-
'Access-Control-Allow-Origin': '*',
|
|
276
|
-
'Access-Control-Allow-Headers': '*',
|
|
277
|
-
},
|
|
278
|
-
status: 403,
|
|
279
|
-
})
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
if (foundCallback.status === 422) {
|
|
283
|
-
const { status, ...rest } = await foundCallback
|
|
284
|
-
|
|
285
|
-
const { errors } = rest
|
|
286
|
-
return new Response(JSON.stringify(errors), {
|
|
287
|
-
headers: {
|
|
288
|
-
'Content-Type': 'application/json',
|
|
289
|
-
'Access-Control-Allow-Origin': '*',
|
|
290
|
-
'Access-Control-Allow-Headers': '*',
|
|
291
|
-
},
|
|
292
|
-
status: 422,
|
|
293
|
-
})
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
if (foundCallback.status === 500) {
|
|
297
|
-
const { status, ...rest } = await foundCallback
|
|
298
|
-
|
|
299
|
-
const { errors } = rest
|
|
300
|
-
|
|
301
|
-
const file = Bun.file(path.corePath('error-handling/src/views/500.html'))
|
|
302
|
-
|
|
303
|
-
return file.text().then((htmlContent) => {
|
|
304
|
-
// Replace the placeholder with the actual error message
|
|
305
|
-
const modifiedHtml = htmlContent.replace('{{ERROR_MESSAGE}}', errors)
|
|
306
|
-
|
|
307
|
-
return new Response(modifiedHtml, {
|
|
308
|
-
headers: {
|
|
309
|
-
'Content-Type': 'text/html',
|
|
310
|
-
'Access-Control-Allow-Origin': '*',
|
|
311
|
-
'Access-Control-Allow-Headers': '*',
|
|
312
|
-
},
|
|
313
|
-
status: 500,
|
|
314
|
-
})
|
|
315
|
-
})
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
if (isObject(foundCallback)) {
|
|
320
|
-
return new Response(JSON.stringify(foundCallback), {
|
|
321
|
-
headers: {
|
|
322
|
-
'Content-Type': 'application/json',
|
|
323
|
-
'Access-Control-Allow-Origin': '*',
|
|
324
|
-
'Access-Control-Allow-Headers': '*',
|
|
325
|
-
},
|
|
326
|
-
status: 200,
|
|
327
|
-
})
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
// If no known type matched, return a generic error.
|
|
331
|
-
return new Response('Unknown callback type.', {
|
|
332
|
-
headers: {
|
|
333
|
-
'Content-Type': 'application/json',
|
|
334
|
-
'Access-Control-Allow-Origin': '*',
|
|
335
|
-
'Access-Control-Allow-Headers': '*',
|
|
336
|
-
},
|
|
337
|
-
status: 500,
|
|
338
|
-
})
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
function noCache(response: Response): Response {
|
|
342
|
-
response.headers.set('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate')
|
|
343
|
-
response.headers.set('Pragma', 'no-cache')
|
|
344
|
-
response.headers.set('Expires', '0')
|
|
345
|
-
|
|
346
|
-
return response
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
async function addRouteQuery(url: URL): Promise<void> {
|
|
350
|
-
const modelFiles = globSync([path.userModelsPath('*.ts')], { absolute: true })
|
|
351
|
-
for (const modelFile of modelFiles) {
|
|
352
|
-
const model = (await import(modelFile)).default
|
|
353
|
-
const modelName = getModelName(model, modelFile)
|
|
354
|
-
const requestPath = path.frameworkPath(`requests/${modelName}Request.ts`)
|
|
355
|
-
const requestImport = await import(requestPath)
|
|
356
|
-
const requestInstance = requestImport.request
|
|
357
|
-
|
|
358
|
-
if (requestInstance) {
|
|
359
|
-
requestInstance.addQuery(url)
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
RequestParam.addQuery(url)
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
async function addBody(params: any): Promise<void> {
|
|
367
|
-
const modelFiles = globSync([path.userModelsPath('*.ts')], { absolute: true })
|
|
368
|
-
|
|
369
|
-
for (const modelFile of modelFiles) {
|
|
370
|
-
const model = (await import(modelFile)).default
|
|
371
|
-
const modelName = getModelName(model, modelFile)
|
|
372
|
-
const requestPath = path.frameworkPath(`requests/${modelName}Request.ts`)
|
|
373
|
-
const requestImport = await import(requestPath)
|
|
374
|
-
const requestInstance = requestImport.request
|
|
375
|
-
|
|
376
|
-
if (requestInstance) {
|
|
377
|
-
requestInstance.addBodies(JSON.parse(params))
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
RequestParam.addBodies(JSON.parse(params))
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
async function addRouteParam(param: RouteParam): Promise<void> {
|
|
385
|
-
const modelFiles = globSync([path.userModelsPath('*.ts')], { absolute: true })
|
|
386
|
-
|
|
387
|
-
for (const modelFile of modelFiles) {
|
|
388
|
-
const model = (await import(modelFile)).default as Model
|
|
389
|
-
const modelName = getModelName(model, modelFile)
|
|
390
|
-
const requestPath = path.frameworkPath(`requests/${modelName}Request.ts`)
|
|
391
|
-
const requestImport = await import(requestPath)
|
|
392
|
-
const requestInstance = requestImport.request
|
|
393
|
-
|
|
394
|
-
if (requestInstance) {
|
|
395
|
-
requestInstance.addParam(param)
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
RequestParam.addParam(param)
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
async function addHeaders(headers: Headers): Promise<void> {
|
|
403
|
-
const modelFiles = globSync([path.userModelsPath('*.ts')], { absolute: true })
|
|
404
|
-
|
|
405
|
-
for (const modelFile of modelFiles) {
|
|
406
|
-
const model = (await import(modelFile)).default as Model
|
|
407
|
-
const modelName = getModelName(model, modelFile)
|
|
408
|
-
const requestPath = path.frameworkPath(`requests/${modelName}Request.ts`)
|
|
409
|
-
const requestImport = await import(requestPath)
|
|
410
|
-
const requestInstance = requestImport.request
|
|
411
|
-
|
|
412
|
-
if (requestInstance) {
|
|
413
|
-
requestInstance.addHeaders(headers)
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
RequestParam.addHeaders(headers)
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
async function executeMiddleware(route: Route): Promise<any> {
|
|
421
|
-
const { middleware = null } = route
|
|
422
|
-
|
|
423
|
-
if (middleware && middlewares && isObjectNotEmpty(middlewares)) {
|
|
424
|
-
// let middlewareItem: MiddlewareOptions
|
|
425
|
-
if (isString(middleware)) {
|
|
426
|
-
const middlewarePath = path.userMiddlewarePath(`${middleware}.ts`)
|
|
427
|
-
|
|
428
|
-
const middlewareInstance = (await import(middlewarePath)).default
|
|
429
|
-
|
|
430
|
-
try {
|
|
431
|
-
await middlewareInstance.handle()
|
|
432
|
-
}
|
|
433
|
-
catch (error: any) {
|
|
434
|
-
return error
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
else {
|
|
438
|
-
for (const middlewareElement of middleware) {
|
|
439
|
-
const middlewarePath = path.userMiddlewarePath(`${middlewareElement}.ts`)
|
|
440
|
-
|
|
441
|
-
const middlewareInstance = (await import(middlewarePath)).default
|
|
442
|
-
|
|
443
|
-
try {
|
|
444
|
-
await middlewareInstance.handle()
|
|
445
|
-
}
|
|
446
|
-
catch (error: any) {
|
|
447
|
-
return error
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
function isString(val: unknown): val is string {
|
|
454
|
-
return typeof val === 'string'
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
function isObjectNotEmpty(obj: object): boolean {
|
|
458
|
-
return Object.keys(obj).length > 0
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
// eslint-disable-next-line ts/no-unsafe-function-type
|
|
462
|
-
function isFunction(val: unknown): val is Function {
|
|
463
|
-
return typeof val === 'function'
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
function isObject(val: unknown): val is object {
|
|
467
|
-
return typeof val === 'object'
|
|
468
|
-
}
|
package/src/utils.ts
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import type { ModelRequest, RequestInstance } from '@stacksjs/types'
|
|
2
|
-
import { type Ok, ok } from '@stacksjs/error-handling'
|
|
3
|
-
import { path } from '@stacksjs/path'
|
|
4
|
-
import { camelCase } from '@stacksjs/strings'
|
|
5
|
-
import { route } from './router'
|
|
6
|
-
|
|
7
|
-
export async function listRoutes(): Promise<Ok<string, any>> {
|
|
8
|
-
const routeLists = await route.getRoutes()
|
|
9
|
-
|
|
10
|
-
// eslint-disable-next-line no-console
|
|
11
|
-
console.table(routeLists)
|
|
12
|
-
|
|
13
|
-
return ok('Successfully listed routes!')
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function extractModelFromAction(action: string): string {
|
|
17
|
-
let model = ''
|
|
18
|
-
|
|
19
|
-
if (action.includes('IndexOrmAction')) {
|
|
20
|
-
const match = action.match(/\/([A-Z][a-z]+)IndexOrmAction/)
|
|
21
|
-
const modelString = match ? match[1] : ''
|
|
22
|
-
|
|
23
|
-
model = modelString as string
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (action.includes('StoreOrmAction')) {
|
|
27
|
-
const match = action.match(/\/([A-Z][a-z]+)StoreOrmAction/)
|
|
28
|
-
const modelString = match ? match[1] : ''
|
|
29
|
-
|
|
30
|
-
model = modelString as string
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (action.includes('ShowOrmAction')) {
|
|
34
|
-
const match = action.match(/\/([A-Z][a-z]+)ShowOrmAction/)
|
|
35
|
-
const modelString = match ? match[1] : ''
|
|
36
|
-
|
|
37
|
-
model = modelString as string
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (action.includes('UpdateOrmAction')) {
|
|
41
|
-
const match = action.match(/\/([A-Z][a-z]+)UpdateOrmAction/)
|
|
42
|
-
const modelString = match ? match[1] : ''
|
|
43
|
-
|
|
44
|
-
model = modelString as string
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (action.includes('DestroyOrmAction')) {
|
|
48
|
-
const match = action.match(/\/([A-Z][a-z]+)DestroyOrmAction/)
|
|
49
|
-
const modelString = match ? match[1] : ''
|
|
50
|
-
|
|
51
|
-
model = modelString as string
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return model
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export function extractDynamicAction(action: string): string | undefined {
|
|
58
|
-
const regex = /Actions\/(.*?)Action/
|
|
59
|
-
const match = action.match(regex)
|
|
60
|
-
|
|
61
|
-
return match ? match[1] : ''
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export async function extractModelRequest(action: string): Promise<RequestInstance | null> {
|
|
65
|
-
const extractedModel = extractModelFromAction(action)
|
|
66
|
-
const lowerCaseModel = camelCase(extractedModel)
|
|
67
|
-
const requestPath = path.frameworkPath(`requests/${extractedModel}Request.ts`)
|
|
68
|
-
const requestInstance = await import(requestPath)
|
|
69
|
-
const requestIndex = `${lowerCaseModel}Request`
|
|
70
|
-
|
|
71
|
-
return requestInstance[requestIndex]
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export async function findRequestInstance(requestInstance: string): Promise<ModelRequest> {
|
|
75
|
-
const frameworkDirectory = path.storagePath('framework/requests')
|
|
76
|
-
const filePath = path.join(frameworkDirectory, `${requestInstance}.ts`)
|
|
77
|
-
|
|
78
|
-
const reqInstance = await import(filePath)
|
|
79
|
-
|
|
80
|
-
return reqInstance.request
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export async function extractDefaultRequest(): Promise<RequestInstance> {
|
|
84
|
-
const requestPath = path.frameworkPath(`core/router/src/request.ts`)
|
|
85
|
-
const requestInstance = await import(requestPath)
|
|
86
|
-
|
|
87
|
-
return requestInstance.request
|
|
88
|
-
}
|