@stacksjs/router 0.62.0 → 0.63.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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stacksjs/router",
3
3
  "type": "module",
4
- "version": "0.62.0",
4
+ "version": "0.63.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.10.0",
53
- "vue-router": "^4.4.0"
52
+ "unplugin-vue-router": "^0.10.6",
53
+ "vue-router": "^4.4.3"
54
54
  },
55
55
  "dependencies": {
56
56
  "@stacksjs/config": "latest",
57
57
  "@stacksjs/logging": "latest",
58
- "unplugin-vue-router": "^0.10.0",
59
- "vue-router": "^4.4.0"
58
+ "unplugin-vue-router": "^0.10.6",
59
+ "vue-router": "^4.4.3"
60
60
  },
61
61
  "devDependencies": {
62
62
  "@stacksjs/development": "latest"
package/src/request.ts CHANGED
@@ -103,7 +103,7 @@ export class Request implements RequestInstance {
103
103
  public bearerToken(): string | null {
104
104
  const authorizationHeader = this.headers.get('authorization')
105
105
 
106
- if (authorizationHeader && authorizationHeader.startsWith('Bearer ')) {
106
+ if (authorizationHeader?.startsWith('Bearer ')) {
107
107
  return authorizationHeader.substring(7)
108
108
  }
109
109
 
package/src/router.ts CHANGED
@@ -4,8 +4,7 @@ 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
6
  import type { RedirectCode, Route, RouteGroupOptions, RouterInterface, StatusCode } from '@stacksjs/types'
7
-
8
- import { extractDynamicRequest, extractModelRequest } from './utils'
7
+ import { extractDefaultRequest, extractModelRequest, findRequestInstance } from './utils'
9
8
 
10
9
  type ActionPath = string // TODO: narrow this by automating its generation
11
10
 
@@ -283,7 +282,9 @@ export class Router implements RouterInterface {
283
282
 
284
283
  let actionModule = null
285
284
 
286
- if (modulePath.includes('OrmAction'))
285
+ if (modulePath.includes('storage/framework/orm')) actionModule = await import(`${modulePath}.ts`)
286
+ else if (modulePath.includes('app/Actions')) actionModule = await import(`${modulePath}.ts`)
287
+ else if (modulePath.includes('OrmAction'))
287
288
  actionModule = await import(importPathFunction(`/framework/orm/${modulePath}.ts`))
288
289
  else actionModule = await import(importPathFunction(`${modulePath}.ts`))
289
290
 
@@ -300,8 +301,15 @@ export class Router implements RouterInterface {
300
301
  // if fails, return validation error
301
302
  let requestInstance
302
303
 
303
- if (modulePath.includes('OrmAction')) requestInstance = await extractModelRequest(modulePath)
304
- else requestInstance = await extractDynamicRequest(modulePath)
304
+ console.log('actionModule', actionModule)
305
+
306
+ if (actionModule.default.requestFile) {
307
+ requestInstance = await findRequestInstance(actionModule.default.requestFile)
308
+ } else {
309
+ requestInstance = await extractDefaultRequest(modulePath)
310
+ }
311
+
312
+ console.log(actionModule.default.requestFile)
305
313
 
306
314
  try {
307
315
  return await actionModule.default.handle(requestInstance)
package/src/server.ts CHANGED
@@ -3,7 +3,6 @@ import { log } from '@stacksjs/logging'
3
3
  import { getModelName } from '@stacksjs/orm'
4
4
  import { path, extname } from '@stacksjs/path'
5
5
  import { glob } from '@stacksjs/storage'
6
- import { camelCase, lowercase } from '@stacksjs/strings'
7
6
  import type { Model, Route, RouteParam, StatusCode } from '@stacksjs/types'
8
7
  import { route } from '.'
9
8
  import { middlewares } from './middleware'
@@ -130,8 +129,10 @@ function extractDynamicSegments(routePattern: string, path: string): RouteParam
130
129
  return dynamicSegments
131
130
  }
132
131
 
132
+ type CallbackWithStatus = Route['callback'] & { status: number }
133
+
133
134
  async function execute(foundRoute: Route, req: Request, { statusCode }: Options) {
134
- const foundCallback = await route.resolveCallback(foundRoute.callback)
135
+ const foundCallback: CallbackWithStatus = await route.resolveCallback(foundRoute.callback)
135
136
 
136
137
  const middlewarePayload = await executeMiddleware(foundRoute)
137
138
 
@@ -142,9 +143,9 @@ async function execute(foundRoute: Route, req: Request, { statusCode }: Options)
142
143
  ) {
143
144
  const middlewareStatus = middlewarePayload.status
144
145
 
145
- delete middlewarePayload.status
146
+ const { status, ...payloadWithoutStatus } = middlewarePayload
146
147
 
147
- return await new Response(JSON.stringify(middlewarePayload), {
148
+ return await new Response(JSON.stringify(payloadWithoutStatus), {
148
149
  headers: {
149
150
  'Content-Type': 'json',
150
151
  'Access-Control-Allow-Origin': '*',
@@ -163,7 +164,7 @@ async function execute(foundRoute: Route, req: Request, { statusCode }: Options)
163
164
  return await noCache(response)
164
165
  }
165
166
 
166
- if (foundRoute?.method !== req.method)
167
+ if (foundRoute?.method !== req.method) {
167
168
  return new Response('Method not allowed', {
168
169
  status: 405,
169
170
  headers: {
@@ -171,6 +172,7 @@ async function execute(foundRoute: Route, req: Request, { statusCode }: Options)
171
172
  'Access-Control-Allow-Headers': '*',
172
173
  },
173
174
  })
175
+ }
174
176
 
175
177
  // Check if it's a path to an HTML file
176
178
  if (isString(foundCallback) && extname(foundCallback) === '.html') {
@@ -219,9 +221,9 @@ async function execute(foundRoute: Route, req: Request, { statusCode }: Options)
219
221
 
220
222
  if (isObject(foundCallback) && foundCallback.status) {
221
223
  if (foundCallback.status === 401) {
222
- delete foundCallback.status
224
+ const { status, ...rest } = foundCallback
223
225
 
224
- return await new Response(JSON.stringify(foundCallback), {
226
+ return await new Response(JSON.stringify(rest), {
225
227
  headers: {
226
228
  'Content-Type': 'json',
227
229
  'Access-Control-Allow-Origin': '*',
@@ -232,8 +234,9 @@ async function execute(foundRoute: Route, req: Request, { statusCode }: Options)
232
234
  }
233
235
 
234
236
  if (foundCallback.status === 403) {
235
- delete foundCallback.status
236
- return await new Response(JSON.stringify(foundCallback), {
237
+ const { status, ...rest } = foundCallback
238
+
239
+ return await new Response(JSON.stringify(rest), {
237
240
  headers: {
238
241
  'Content-Type': 'json',
239
242
  'Access-Control-Allow-Origin': '*',
@@ -244,10 +247,9 @@ async function execute(foundRoute: Route, req: Request, { statusCode }: Options)
244
247
  }
245
248
 
246
249
  if (foundCallback.status === 422) {
247
- // biome-ignore lint/performance/noDelete: <explanation>
248
- delete foundCallback.status
250
+ const { status, ...rest } = foundCallback
249
251
 
250
- return await new Response(JSON.stringify(foundCallback), {
252
+ return await new Response(JSON.stringify(rest), {
251
253
  headers: {
252
254
  'Content-Type': 'json',
253
255
  'Access-Control-Allow-Origin': '*',
@@ -258,19 +260,16 @@ async function execute(foundRoute: Route, req: Request, { statusCode }: Options)
258
260
  }
259
261
 
260
262
  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
- },
263
+ const { status, ...rest } = foundCallback
264
+
265
+ return await new Response(JSON.stringify(rest), {
266
+ headers: { 'Content-Type': 'json', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': '*' },
268
267
  status: 500,
269
268
  })
270
269
  }
271
270
  }
272
271
 
273
- if (isObject(foundCallback))
272
+ if (isObject(foundCallback)) {
274
273
  return await new Response(JSON.stringify(foundCallback), {
275
274
  headers: {
276
275
  'Content-Type': 'json',
@@ -279,6 +278,7 @@ async function execute(foundRoute: Route, req: Request, { statusCode }: Options)
279
278
  },
280
279
  status: 200,
281
280
  })
281
+ }
282
282
 
283
283
  // If no known type matched, return a generic error.
284
284
  return await new Response('Unknown callback type.', {
@@ -305,10 +305,9 @@ async function addRouteQuery(url: URL) {
305
305
  for (const modelFile of modelFiles) {
306
306
  const model = (await import(modelFile)).default
307
307
  const modelName = getModelName(model, modelFile)
308
- const modelNameLower = `${camelCase(modelName)}Request`
309
- const requestPath = path.projectStoragePath(`framework/requests/${modelName}Request.ts`)
308
+ const requestPath = path.frameworkPath(`requests/${modelName}Request.ts`)
310
309
  const requestImport = await import(requestPath)
311
- const requestInstance = requestImport[modelNameLower]
310
+ const requestInstance = requestImport.request
312
311
 
313
312
  if (requestInstance) {
314
313
  requestInstance.addQuery(url)
@@ -324,10 +323,9 @@ async function addBody(params: any) {
324
323
  for (const modelFile of modelFiles) {
325
324
  const model = (await import(modelFile)).default
326
325
  const modelName = getModelName(model, modelFile)
327
- const modelNameLower = `${camelCase(modelName)}Request`
328
- const requestPath = path.projectStoragePath(`framework/requests/${modelName}Request.ts`)
326
+ const requestPath = path.frameworkPath(`requests/${modelName}Request.ts`)
329
327
  const requestImport = await import(requestPath)
330
- const requestInstance = requestImport[modelNameLower]
328
+ const requestInstance = requestImport.request
331
329
 
332
330
  if (requestInstance) {
333
331
  requestInstance.addBodies(JSON.parse(params))
@@ -343,10 +341,9 @@ async function addRouteParam(param: RouteParam): Promise<void> {
343
341
  for (const modelFile of modelFiles) {
344
342
  const model = (await import(modelFile)).default as Model
345
343
  const modelName = getModelName(model, modelFile)
346
- const modelNameLower = `${lowercase(modelName)}Request`
347
- const requestPath = path.projectStoragePath(`framework/requests/${modelName}Request.ts`)
344
+ const requestPath = path.frameworkPath(`requests/${modelName}Request.ts`)
348
345
  const requestImport = await import(requestPath)
349
- const requestInstance = requestImport[modelNameLower]
346
+ const requestInstance = requestImport.request
350
347
 
351
348
  if (requestInstance) {
352
349
  requestInstance.addParam(param)
@@ -362,10 +359,9 @@ async function addHeaders(headers: Headers): Promise<void> {
362
359
  for (const modelFile of modelFiles) {
363
360
  const model = (await import(modelFile)).default as Model
364
361
  const modelName = getModelName(model, modelFile)
365
- const modelNameLower = `${lowercase(modelName)}Request`
366
- const requestPath = path.projectStoragePath(`framework/requests/${modelName}Request.ts`)
362
+ const requestPath = path.frameworkPath(`requests/${modelName}Request.ts`)
367
363
  const requestImport = await import(requestPath)
368
- const requestInstance = requestImport[modelNameLower]
364
+ const requestInstance = requestImport.request
369
365
 
370
366
  if (requestInstance) {
371
367
  requestInstance.addHeaders(headers)
package/src/utils.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { ok } from '@stacksjs/error-handling'
2
2
  import { path } from '@stacksjs/path'
3
- import { glob } from '@stacksjs/storage'
3
+ import { existsSync } from '@stacksjs/storage'
4
4
  import { camelCase } from '@stacksjs/strings'
5
5
  import { route } from './router'
6
6
 
@@ -15,6 +15,14 @@ export async function listRoutes() {
15
15
  export function extractModelFromAction(action: string): string {
16
16
  let model = ''
17
17
 
18
+ if (action.includes('IndexOrmAction')) {
19
+ const match = action.match(/\/([A-Z][a-z]+)IndexOrmAction/)
20
+
21
+ const modelString = match ? match[1] : ''
22
+
23
+ model = modelString as string
24
+ }
25
+
18
26
  if (action.includes('StoreOrmAction')) {
19
27
  const match = action.match(/\/([A-Z][a-z]+)StoreOrmAction/)
20
28
 
@@ -60,7 +68,7 @@ export async function extractModelRequest(action: string) {
60
68
 
61
69
  const lowerCaseModel = camelCase(extractedModel)
62
70
 
63
- const requestPath = path.projectStoragePath(`framework/requests/${extractedModel}Request.ts`)
71
+ const requestPath = path.frameworkPath(`requests/${extractedModel}Request.ts`)
64
72
 
65
73
  const requestInstance = await import(requestPath)
66
74
 
@@ -69,29 +77,36 @@ export async function extractModelRequest(action: string) {
69
77
  return requestInstance[requestIndex]
70
78
  }
71
79
 
72
- export async function extractDynamicRequest(action: string) {
73
- const extractedModel = extractDynamicAction(action) || ''
80
+ export async function findRequestInstance(requestInstance: string) {
81
+ const frameworkDirectory = path.projectStoragePath('framework/requests')
74
82
 
75
- const lowerCaseModel = camelCase(extractedModel)
83
+ const filePath = path.join(frameworkDirectory, `${requestInstance}.ts`)
76
84
 
77
- const modelFiles = glob.sync(path.userModelsPath('*.ts'))
85
+ const pathExists = await existsSync(filePath)
78
86
 
79
- const fileToCheck = `${extractedModel}.ts`
87
+ // Check if the directory exists
88
+ if (pathExists) {
89
+ const requestInstance = await import(filePath)
80
90
 
81
- const fileExists = modelFiles.some((file) => file.split('/').pop() === fileToCheck)
91
+ return requestInstance.request
92
+ }
93
+
94
+ const defaultRequestPath = path.projectStoragePath('framework/core/router/src/request.ts')
82
95
 
83
- if (!fileExists) {
84
- const requestPath = path.projectStoragePath(`framework/core/router/src/request.ts`)
85
- const requestInstance = await import(requestPath)
96
+ const fileExists = await existsSync(defaultRequestPath)
97
+
98
+ if (fileExists) {
99
+ const requestInstance = await import(defaultRequestPath)
86
100
 
87
101
  return requestInstance.request
88
102
  }
89
103
 
90
- const requestPath = path.projectStoragePath(`framework/requests/${extractedModel}Request.ts`)
104
+ return null
105
+ }
91
106
 
107
+ export async function extractDefaultRequest(action: string) {
108
+ const requestPath = path.frameworkPath(`core/router/src/request.ts`)
92
109
  const requestInstance = await import(requestPath)
93
110
 
94
- const requestIndex = `${lowerCaseModel}Request`
95
-
96
- return requestInstance[requestIndex]
111
+ return requestInstance.request
97
112
  }