@stacksjs/router 0.61.20 → 0.61.21

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.61.20",
4
+ "version": "0.61.21",
5
5
  "description": "The Stacks framework router.",
6
6
  "author": "Chris Breuer",
7
7
  "license": "MIT",
@@ -49,13 +49,13 @@
49
49
  },
50
50
  "peerDependencies": {
51
51
  "@stacksjs/config": "latest",
52
- "unplugin-vue-router": "^0.8.8",
52
+ "unplugin-vue-router": "^0.9.0",
53
53
  "vue-router": "^4.3.2"
54
54
  },
55
55
  "dependencies": {
56
56
  "@stacksjs/config": "latest",
57
57
  "@stacksjs/logging": "latest",
58
- "unplugin-vue-router": "^0.8.8",
58
+ "unplugin-vue-router": "^0.9.0",
59
59
  "vue-router": "^4.3.2"
60
60
  },
61
61
  "devDependencies": {
package/src/request.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { RouteParam } from '@stacksjs/types'
1
+ import type { RequestInstance, RouteParam } from "@stacksjs/types"
2
2
 
3
3
  interface RequestData {
4
4
  [key: string]: string
@@ -6,7 +6,7 @@ interface RequestData {
6
6
 
7
7
  type RouteParams = { [key: string]: string } | null
8
8
 
9
- export class Request {
9
+ export class Request implements RequestInstance{
10
10
  private static instance: Request
11
11
  private query: RequestData = {}
12
12
  private params: RouteParams = null
@@ -62,6 +62,6 @@ export class Request {
62
62
  const value = this.params ? this.params[key] || null : null
63
63
  return value ? Number.parseInt(value) : null
64
64
  }
65
- }
65
+ }
66
66
 
67
67
  export const request = new Request()
package/src/router.ts CHANGED
@@ -3,8 +3,11 @@ 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'
6
7
  import type { RedirectCode, Route, RouteGroupOptions, RouterInterface, StatusCode } from '@stacksjs/types'
7
8
 
9
+ import { extractModelRequest } from './utils'
10
+
8
11
  type ActionPath = string // TODO: narrow this by automating its generation
9
12
 
10
13
  export class Router implements RouterInterface {
@@ -93,6 +96,8 @@ export class Router implements RouterInterface {
93
96
  }
94
97
 
95
98
  public async action(path: ActionPath | Route['path']): Promise<this> {
99
+ if (!path) return this
100
+
96
101
  // check if action is a file anywhere in ./app/Actions/**/*.ts
97
102
  if (path?.endsWith('.ts')) {
98
103
  // given it ends with .ts, we treat it as an Actions path
@@ -102,22 +107,15 @@ export class Router implements RouterInterface {
102
107
  }
103
108
 
104
109
  path = pascalCase(path) // actions are PascalCase
105
- const userActionsPath = p.userActionsPath(`${path}.ts`)
106
110
 
107
111
  try {
108
- const action = (await import(userActionsPath)).default as Action
112
+ const action = (await import(p.userActionsPath(`${path}.ts`))).default as Action
109
113
 
110
114
  return this.addRoute(action.method ?? 'GET', this.prepareUri(path), action.handle, 200)
111
115
  } catch (error) {
112
- try {
113
- const action = (await import(p.userActionsPath(`${path}.ts`))).default as Action
114
-
115
- return this.addRoute(action.method ?? 'GET', this.prepareUri(path), action.handle, 200)
116
- } catch (error) {
117
- log.error(`Could not find Action for path: ${path}`)
116
+ log.error(`Could not find Action for path: ${path}`)
118
117
 
119
- return this
120
- }
118
+ return this
121
119
  }
122
120
  }
123
121
 
@@ -304,9 +302,9 @@ export class Router implements RouterInterface {
304
302
  // if succeeds, run the handle
305
303
  // if fails, return validation error
306
304
 
307
- if (condition) return await actionModule.default.handle()
308
-
309
- return await actionModule.default.handle(request)
305
+ const requestInstance = await extractModelRequest(modulePath)
306
+
307
+ return await actionModule.default.handle(requestInstance)
310
308
  }
311
309
 
312
310
  private normalizePath(path: string): string {
package/src/server.ts CHANGED
@@ -1,10 +1,13 @@
1
1
  import process from 'node:process'
2
2
  import { log } from '@stacksjs/logging'
3
- import { extname } from '@stacksjs/path'
4
- import type { Route, RouteParam, StatusCode } from '@stacksjs/types'
3
+ import { extname, path } from '@stacksjs/path'
4
+ import { glob } from '@stacksjs/storage'
5
+ import type { Model, Route, RouteParam, StatusCode } from '@stacksjs/types'
5
6
  import { route } from '.'
6
7
  import { middlewares } from './middleware'
7
8
  import { request as RequestParam } from './request'
9
+ import { getModelName } from '@stacksjs/orm'
10
+ import { lowercase } from '@stacksjs/strings'
8
11
 
9
12
  interface ServeOptions {
10
13
  host?: string
@@ -71,8 +74,8 @@ export async function serverResponse(req: Request) {
71
74
 
72
75
  const routeParams = extractDynamicSegments(foundRoute.uri, url.pathname)
73
76
 
74
- addRouteQuery(url)
75
- addRouteParam(routeParams)
77
+ await addRouteQuery(url)
78
+ await addRouteParam(routeParams)
76
79
 
77
80
  await executeMiddleware(foundRoute)
78
81
 
@@ -146,13 +149,43 @@ function noCache(response: Response) {
146
149
  return response
147
150
  }
148
151
 
149
- function addRouteQuery(url: URL): void {
150
- if (!isObjectNotEmpty(url.searchParams)) RequestParam.addQuery(url)
152
+ async function addRouteQuery(url: URL) {
153
+ const modelFiles = glob.sync(path.userModelsPath('*.ts'));
151
154
 
152
- // requestInstance.extractParamsFromRoute(route.uri, url.pathname)
155
+ for (const modelFile of modelFiles) {
156
+ const model = (await import(modelFile)).default;
157
+ const modelName = getModelName(model, modelFile);
158
+ const modelNameLower = `${lowercase(modelName)}Request`;
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 && !isObjectNotEmpty(url.searchParams)) {
164
+ requestInstance.addQuery(url);
165
+ }
166
+ }
167
+
168
+ if (!isObjectNotEmpty(url.searchParams)) {
169
+ RequestParam.addQuery(url);
170
+ }
153
171
  }
154
172
 
155
- function addRouteParam(param: RouteParam): void {
173
+ async function addRouteParam(param: RouteParam): Promise<void> {
174
+ const modelFiles = glob.sync(path.userModelsPath('*.ts'));
175
+
176
+ 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];
183
+
184
+ if (requestInstance) {
185
+ requestInstance.addParam(param);
186
+ }
187
+ }
188
+
156
189
  RequestParam.addParam(param)
157
190
  }
158
191
 
package/src/utils.ts CHANGED
@@ -1,4 +1,8 @@
1
+ import { ok } from '@stacksjs/error-handling'
1
2
  import { route } from './router'
3
+ import { path } from '@stacksjs/path'
4
+
5
+ import { lowercase } from '@stacksjs/strings'
2
6
 
3
7
  export async function listRoutes() {
4
8
  const routeLists = await route.getRoutes()
@@ -7,3 +11,52 @@ export async function listRoutes() {
7
11
 
8
12
  return ok('Successfully listed routes!')
9
13
  }
14
+
15
+ export function extractModelFromAction(action: string): string {
16
+ let model = ''
17
+
18
+ if (action.includes("StoreOrmAction")) {
19
+ const match = action.match(/\/([A-Z][a-z]+)StoreOrmAction/);
20
+
21
+ const modelString = match ? match[1] : '';
22
+
23
+ model = modelString as string
24
+ }
25
+
26
+ if (action.includes("ShowOrmAction")) {
27
+ const match = action.match(/\/([A-Z][a-z]+)ShowOrmAction/);
28
+ const modelString = match ? match[1] : '';
29
+
30
+ model = modelString as string
31
+ }
32
+
33
+ if (action.includes("UpdateOrmAction")) {
34
+ const match = action.match(/\/([A-Z][a-z]+)UpdateOrmAction/);
35
+ const modelString = match ? match[1] : '';
36
+
37
+ model = modelString as string
38
+ }
39
+
40
+ if (action.includes("DestroyOrmAction")) {
41
+ const match = action.match(/\/([A-Z][a-z]+)DestroyOrmAction/);
42
+ const modelString = match ? match[1] : '';
43
+
44
+ model = modelString as string
45
+ }
46
+
47
+ return model
48
+ }
49
+
50
+ export async function extractModelRequest(action: string) {
51
+ const extractedModel = extractModelFromAction(action)
52
+
53
+ const lowerCaseModel = lowercase(extractedModel)
54
+
55
+ const requestPath = path.projectStoragePath(`framework/requests/${extractedModel}Request.ts`)
56
+
57
+ const requestInstance = await import(requestPath)
58
+
59
+ const requestIndex = `${lowerCaseModel}Request`
60
+
61
+ return requestInstance[requestIndex]
62
+ }