@stacksjs/router 0.66.0 → 0.68.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/fsevents-hj42pnne.node +0 -0
- package/dist/index.js +107 -76
- 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/index.ts
DELETED
package/src/middleware.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import type { MiddlewareOptions } from '@stacksjs/types'
|
|
2
|
-
import { userMiddlewarePath } from '@stacksjs/path'
|
|
3
|
-
|
|
4
|
-
export class Middleware implements MiddlewareOptions {
|
|
5
|
-
name: string
|
|
6
|
-
priority: number
|
|
7
|
-
handle: () => Promise<void>
|
|
8
|
-
|
|
9
|
-
constructor(data: MiddlewareOptions) {
|
|
10
|
-
this.name = data.name
|
|
11
|
-
this.priority = data.priority
|
|
12
|
-
this.handle = data.handle
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// const readdir = promisify(fs.readdir)
|
|
17
|
-
|
|
18
|
-
async function importMiddlewares(directory: string): Promise<string[]> {
|
|
19
|
-
// const middlewares = []
|
|
20
|
-
// TODO: somehow this breaks ./buddy dev
|
|
21
|
-
// const files = await readdir(directory)
|
|
22
|
-
|
|
23
|
-
// for (const file of files) {
|
|
24
|
-
// // Dynamically import the middleware
|
|
25
|
-
// const imported = await import(path.join(directory, file))
|
|
26
|
-
// middlewares.push(imported.default)
|
|
27
|
-
// }
|
|
28
|
-
|
|
29
|
-
// return middlewares
|
|
30
|
-
return [directory] // fix this: return array of middlewares
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export async function middlewares(): Promise<string[]> {
|
|
34
|
-
return await importMiddlewares(userMiddlewarePath())
|
|
35
|
-
}
|
package/src/request.ts
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import type { RequestInstance, RouteParam, VineType } from '@stacksjs/types'
|
|
2
|
-
|
|
3
|
-
import { customValidate, validateField } from '@stacksjs/validation'
|
|
4
|
-
|
|
5
|
-
interface RequestData {
|
|
6
|
-
[key: string]: any
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
interface ValidationField {
|
|
10
|
-
rule: VineType
|
|
11
|
-
message: Record<string, string>
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
type AuthToken = `${number}:${number}:${string}`
|
|
15
|
-
|
|
16
|
-
interface CustomAttributes {
|
|
17
|
-
[key: string]: ValidationField
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
type RouteParams = { [key: string]: string | number } | null
|
|
21
|
-
|
|
22
|
-
export class Request<T extends RequestData = RequestData> implements RequestInstance {
|
|
23
|
-
public query: T = {} as T
|
|
24
|
-
public params: RouteParams = null
|
|
25
|
-
public headers: any = {}
|
|
26
|
-
|
|
27
|
-
public addQuery(url: URL): void {
|
|
28
|
-
this.query = Object.fromEntries(url.searchParams) as unknown as T
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
public addBodies(params: any): void {
|
|
32
|
-
this.query = params
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
public addParam(param: RouteParam): void {
|
|
36
|
-
this.params = param
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
public addHeaders(headerParams: Headers): void {
|
|
40
|
-
this.headers = headerParams
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
public get(element: string): any {
|
|
44
|
-
return this.query[element]
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
public all(): T {
|
|
48
|
-
return this.query
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
public async validate(attributes?: CustomAttributes): Promise<void> {
|
|
52
|
-
if (attributes === undefined || attributes === null) {
|
|
53
|
-
await validateField('Release', this.all())
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
await customValidate(attributes, this.all())
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
public has(element: string): boolean {
|
|
61
|
-
return element in this.query
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
public isEmpty(): boolean {
|
|
65
|
-
return Object.keys(this.query).length === 0
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
public extractParamsFromRoute(routePattern: string, pathname: string): void {
|
|
69
|
-
const pattern = new RegExp(`^${routePattern.replace(/:(\w+)/g, (match, paramName) => `(?<${paramName}>\\w+)`)}$`)
|
|
70
|
-
const match = pattern.exec(pathname)
|
|
71
|
-
|
|
72
|
-
if (match?.groups)
|
|
73
|
-
this.params = match.groups
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
public header(headerParam: string): string | number | boolean | null {
|
|
77
|
-
return this.headers.get(headerParam)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
public getHeaders(): any {
|
|
81
|
-
return this.headers
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
public Header(headerParam: string): string | number | boolean | null {
|
|
85
|
-
return this.headers.get(headerParam)
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
public getParam(key: string): number | string | null {
|
|
89
|
-
return this.params ? this.params[key] || null : null
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
public bearerToken(): string | null | AuthToken {
|
|
93
|
-
const authorizationHeader = this.headers.get('authorization')
|
|
94
|
-
|
|
95
|
-
if (authorizationHeader?.startsWith('Bearer ')) {
|
|
96
|
-
return authorizationHeader.substring(7)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return null
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
public getParams(): RouteParams {
|
|
103
|
-
return this.params
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
public getParamAsInt(key: string): number | null {
|
|
107
|
-
const value = this.getParam(key)
|
|
108
|
-
return value ? Number.parseInt(value.toString()) : null
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
export const request: Request = new Request()
|
package/src/router.ts
DELETED
|
@@ -1,358 +0,0 @@
|
|
|
1
|
-
import type { Action } from '@stacksjs/actions'
|
|
2
|
-
import type { Job, RedirectCode, RequestInstance, Route, RouteGroupOptions, RouterInterface, StatusCode } from '@stacksjs/types'
|
|
3
|
-
import { handleError } from '@stacksjs/error-handling'
|
|
4
|
-
import { log } from '@stacksjs/logging'
|
|
5
|
-
import { path as p } from '@stacksjs/path'
|
|
6
|
-
import { kebabCase, pascalCase } from '@stacksjs/strings'
|
|
7
|
-
import { customValidate, isObjectNotEmpty } from '@stacksjs/validation'
|
|
8
|
-
import { extractDefaultRequest, findRequestInstance } from './utils'
|
|
9
|
-
|
|
10
|
-
type ActionPath = string // TODO: narrow this by automating its generation
|
|
11
|
-
|
|
12
|
-
export class Router implements RouterInterface {
|
|
13
|
-
private routes: Route[] = []
|
|
14
|
-
private groupPrefix = ''
|
|
15
|
-
private path = ''
|
|
16
|
-
|
|
17
|
-
private addRoute(
|
|
18
|
-
method: Route['method'],
|
|
19
|
-
uri: string,
|
|
20
|
-
callback: Route['callback'] | string | object,
|
|
21
|
-
statusCode: StatusCode,
|
|
22
|
-
): this {
|
|
23
|
-
const name = uri.replace(/\//g, '.').replace(/:/g, '') // we can improve this
|
|
24
|
-
const pattern = new RegExp(
|
|
25
|
-
`^${uri.replace(/:[a-z]+/gi, (_match) => {
|
|
26
|
-
return '([a-zA-Z0-9-]+)'
|
|
27
|
-
})}$`,
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
// let routeCallback: Route['callback']
|
|
31
|
-
|
|
32
|
-
// if (typeof callback === 'string' || typeof callback === 'object') {
|
|
33
|
-
// // Convert string or object to RouteCallback
|
|
34
|
-
// routeCallback = () => callback
|
|
35
|
-
// } else {
|
|
36
|
-
// routeCallback = callback
|
|
37
|
-
// }
|
|
38
|
-
|
|
39
|
-
log.debug(`Adding route: ${method} ${uri} with name ${name}`)
|
|
40
|
-
|
|
41
|
-
this.routes.push({
|
|
42
|
-
name,
|
|
43
|
-
method,
|
|
44
|
-
url: uri,
|
|
45
|
-
uri,
|
|
46
|
-
callback,
|
|
47
|
-
pattern,
|
|
48
|
-
statusCode,
|
|
49
|
-
paramNames: [],
|
|
50
|
-
// middleware: [],
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
return this
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
public get(path: Route['url'], callback: Route['callback']): this {
|
|
57
|
-
this.path = this.normalizePath(path)
|
|
58
|
-
log.debug(`Normalized Path: ${this.path}`)
|
|
59
|
-
|
|
60
|
-
const uri = this.prepareUri(this.path)
|
|
61
|
-
log.debug(`Prepared URI: ${uri}`)
|
|
62
|
-
|
|
63
|
-
return this.addRoute('GET', uri, callback, 200)
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
public async email(path: Route['url']): Promise<this> {
|
|
67
|
-
path = pascalCase(path)
|
|
68
|
-
|
|
69
|
-
const emailModule = (await import(p.userNotificationsPath(path))).default as Action
|
|
70
|
-
const callback = emailModule.handle
|
|
71
|
-
const uri = this.prepareUri(path)
|
|
72
|
-
this.addRoute('GET', uri, callback, 200)
|
|
73
|
-
|
|
74
|
-
return this
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
public async health(): Promise<this> {
|
|
78
|
-
const healthModule = (await import(p.userActionsPath('HealthAction'))).default as Action
|
|
79
|
-
const callback = healthModule.handle
|
|
80
|
-
const path = healthModule.path ?? `/health`
|
|
81
|
-
|
|
82
|
-
this.addRoute('GET', path, callback, 200)
|
|
83
|
-
|
|
84
|
-
return this
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
public async job(path: Route['url']): Promise<this> {
|
|
88
|
-
path = pascalCase(path)
|
|
89
|
-
|
|
90
|
-
// removes the potential `JobJob` suffix in case the user does not choose to use the Job suffix in their file name
|
|
91
|
-
const job = (await import(p.userJobsPath(`${path}.ts`))).default as Job
|
|
92
|
-
|
|
93
|
-
return this.addRoute('GET', this.prepareUri(path), job.handle, 200)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
public async action(path: ActionPath | Route['path']): Promise<this> {
|
|
97
|
-
if (!path)
|
|
98
|
-
return this
|
|
99
|
-
|
|
100
|
-
// check if action is a file anywhere in ./app/Actions/**/*.ts
|
|
101
|
-
if (path?.endsWith('.ts')) {
|
|
102
|
-
// given it ends with .ts, we treat it as an Actions path
|
|
103
|
-
const action = (await import(p.userActionsPath(path))).default as Action
|
|
104
|
-
path = action.path ?? kebabCase(path as string)
|
|
105
|
-
return this.addRoute(action.method ?? 'GET', path, action.handle, 200)
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
path = pascalCase(path) // actions are PascalCase
|
|
109
|
-
|
|
110
|
-
try {
|
|
111
|
-
const action = (await import(p.userActionsPath(path))).default as Action
|
|
112
|
-
|
|
113
|
-
return this.addRoute(action.method ?? 'GET', this.prepareUri(path), action.handle, 200)
|
|
114
|
-
}
|
|
115
|
-
catch (error) {
|
|
116
|
-
handleError(`Could not find Action for path: ${path}`, error)
|
|
117
|
-
|
|
118
|
-
return this
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
public post(path: Route['url'], callback: Route['callback']): this {
|
|
123
|
-
this.path = this.normalizePath(path)
|
|
124
|
-
|
|
125
|
-
const uri = this.prepareUri(this.path)
|
|
126
|
-
|
|
127
|
-
return this.addRoute('POST', uri, callback, 201)
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
public view(path: Route['url'], callback: Route['callback']): this {
|
|
131
|
-
this.path = this.normalizePath(path)
|
|
132
|
-
|
|
133
|
-
const uri = this.prepareUri(this.path)
|
|
134
|
-
|
|
135
|
-
return this.addRoute('GET', uri, callback, 200)
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
public redirect(path: Route['url'], callback: Route['callback'], _status?: RedirectCode): this {
|
|
139
|
-
return this.addRoute('GET', path, callback, 302)
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
public delete(path: Route['url'], callback: Route['callback']): this {
|
|
143
|
-
return this.addRoute('DELETE', this.prepareUri(path), callback, 204)
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
public patch(path: Route['url'], callback: Route['callback']): this {
|
|
147
|
-
this.path = this.normalizePath(path)
|
|
148
|
-
log.debug(`Normalized Path: ${this.path}`)
|
|
149
|
-
|
|
150
|
-
const uri = this.prepareUri(this.path)
|
|
151
|
-
log.debug(`Prepared URI: ${uri}`)
|
|
152
|
-
|
|
153
|
-
return this.addRoute('PATCH', uri, callback, 202)
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
public put(path: Route['url'], callback: Route['callback']): this {
|
|
157
|
-
this.path = this.normalizePath(path)
|
|
158
|
-
|
|
159
|
-
const uri = this.prepareUri(this.path)
|
|
160
|
-
|
|
161
|
-
return this.addRoute('PUT', uri, callback, 202)
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
public group(options: string | RouteGroupOptions, callback?: () => void): this {
|
|
165
|
-
if (typeof options === 'string')
|
|
166
|
-
options = options.startsWith('/') ? options.slice(1) : options
|
|
167
|
-
|
|
168
|
-
let cb: () => void
|
|
169
|
-
|
|
170
|
-
this.prepareGroupPrefix(options)
|
|
171
|
-
|
|
172
|
-
if (typeof options === 'function') {
|
|
173
|
-
cb = options
|
|
174
|
-
options = {}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
if (!callback)
|
|
178
|
-
throw new Error('Missing callback function for your route group.')
|
|
179
|
-
|
|
180
|
-
cb = callback
|
|
181
|
-
|
|
182
|
-
const { prefix, middleware = [] } = options as RouteGroupOptions
|
|
183
|
-
|
|
184
|
-
// Save a reference to the original routes array
|
|
185
|
-
const originalRoutes = this.routes
|
|
186
|
-
|
|
187
|
-
// Create a new routes array for the duration of the callback
|
|
188
|
-
this.routes = []
|
|
189
|
-
|
|
190
|
-
// Execute the callback. This will add routes to the new this.routes array
|
|
191
|
-
cb()
|
|
192
|
-
|
|
193
|
-
// For each route added by the callback, adjust the URI and add to the original routes array
|
|
194
|
-
this.routes.forEach((r) => {
|
|
195
|
-
r.uri = `${prefix}${r.uri}`
|
|
196
|
-
|
|
197
|
-
if (middleware.length)
|
|
198
|
-
r.middleware = middleware
|
|
199
|
-
|
|
200
|
-
originalRoutes.push(r)
|
|
201
|
-
return this
|
|
202
|
-
})
|
|
203
|
-
|
|
204
|
-
// Restore the original routes array.
|
|
205
|
-
this.routes = originalRoutes
|
|
206
|
-
|
|
207
|
-
return this
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
public name(name: string): this {
|
|
211
|
-
this.routes[this.routes.length - 1].name = name
|
|
212
|
-
|
|
213
|
-
return this
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
public middleware(middleware: Route['middleware']): this {
|
|
217
|
-
this.routes[this.routes.length - 1].middleware = middleware
|
|
218
|
-
|
|
219
|
-
return this
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
public prefix(prefix: string): this {
|
|
223
|
-
this.routes[this.routes.length - 1].prefix = prefix
|
|
224
|
-
|
|
225
|
-
return this
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
public async getRoutes(): Promise<Route[]> {
|
|
229
|
-
await import('../../../../../routes/api') // user routes
|
|
230
|
-
await import('../../../orm/routes') // auto-generated routes
|
|
231
|
-
|
|
232
|
-
return this.routes
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
private setGroupPrefix(prefix: string, options: RouteGroupOptions = {}) {
|
|
236
|
-
if (prefix !== '') {
|
|
237
|
-
prefix = `/${this.groupPrefix}/${prefix}`.replace(/\/\//g, '/') // remove double slashes in case there are any
|
|
238
|
-
this.groupPrefix = prefix
|
|
239
|
-
return
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// Ensure options is always treated as an object, even if it's undefined or a function
|
|
243
|
-
const effectiveOptions = typeof options === 'object' ? options : {}
|
|
244
|
-
|
|
245
|
-
this.groupPrefix = effectiveOptions.prefix ?? prefix ?? ''
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
private prepareGroupPrefix(options: string | RouteGroupOptions): void {
|
|
249
|
-
if (this.groupPrefix !== '' && typeof options !== 'string') {
|
|
250
|
-
this.setGroupPrefix(this.groupPrefix, options)
|
|
251
|
-
return
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
if (typeof options === 'string') {
|
|
255
|
-
this.setGroupPrefix(options)
|
|
256
|
-
return
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
this.setGroupPrefix('', options)
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
public async resolveCallback(callback: Route['callback']): Promise<Route['callback']> {
|
|
263
|
-
if (callback instanceof Promise) {
|
|
264
|
-
const actionModule = await callback
|
|
265
|
-
return actionModule.default
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
if (typeof callback === 'string')
|
|
269
|
-
return await this.importCallbackFromPath(callback, this.path)
|
|
270
|
-
|
|
271
|
-
// in this case, the callback ends up being a function
|
|
272
|
-
return callback
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
public async importCallbackFromPath(callbackPath: string, originalPath: string): Promise<Route['callback']> {
|
|
276
|
-
let modulePath = callbackPath
|
|
277
|
-
let importPathFunction = p.appPath // Default import path function
|
|
278
|
-
|
|
279
|
-
if (callbackPath.startsWith('../'))
|
|
280
|
-
importPathFunction = p.routesPath
|
|
281
|
-
if (modulePath.includes('OrmAction'))
|
|
282
|
-
importPathFunction = p.storagePath
|
|
283
|
-
|
|
284
|
-
// Remove trailing .ts if present
|
|
285
|
-
modulePath = modulePath.endsWith('.ts') ? modulePath.slice(0, -3) : modulePath
|
|
286
|
-
|
|
287
|
-
let actionModule = null
|
|
288
|
-
|
|
289
|
-
if (modulePath.includes('storage/framework/orm'))
|
|
290
|
-
actionModule = await import(modulePath)
|
|
291
|
-
else if (modulePath.includes('app/Actions'))
|
|
292
|
-
actionModule = await import(modulePath)
|
|
293
|
-
else if (modulePath.includes('OrmAction'))
|
|
294
|
-
actionModule = await import(p.storagePath(`/framework/actions/src/${modulePath}.ts`))
|
|
295
|
-
else actionModule = await import(importPathFunction(modulePath))
|
|
296
|
-
|
|
297
|
-
// Use custom path from action module if available
|
|
298
|
-
const newPath = actionModule.default.path ?? originalPath
|
|
299
|
-
this.updatePathIfNeeded(newPath, originalPath)
|
|
300
|
-
|
|
301
|
-
// we need to make sure the validation happens here
|
|
302
|
-
// to do so, we need to:
|
|
303
|
-
// find the ./app/Models/* file
|
|
304
|
-
// then check via a regex which model attributes validations to utilize by checking what's in between t
|
|
305
|
-
// then validate
|
|
306
|
-
// if succeeds, run the handle
|
|
307
|
-
// if fails, return validation error
|
|
308
|
-
let requestInstance: RequestInstance
|
|
309
|
-
|
|
310
|
-
if (actionModule.default.requestFile) {
|
|
311
|
-
requestInstance = await findRequestInstance(actionModule.default.requestFile)
|
|
312
|
-
}
|
|
313
|
-
else {
|
|
314
|
-
requestInstance = await extractDefaultRequest()
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
try {
|
|
318
|
-
if (isObjectNotEmpty(actionModule.default.validations) && requestInstance)
|
|
319
|
-
await customValidate(actionModule.default.validations, requestInstance.all())
|
|
320
|
-
|
|
321
|
-
return await actionModule.default.handle(requestInstance)
|
|
322
|
-
}
|
|
323
|
-
catch (error: any) {
|
|
324
|
-
if (error.status === 422)
|
|
325
|
-
return { status: 422, errors: JSON.parse(error.message) }
|
|
326
|
-
|
|
327
|
-
if (!error.status)
|
|
328
|
-
return { status: 500, errors: error.message }
|
|
329
|
-
|
|
330
|
-
return { status: error.status, errors: error.message }
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
private normalizePath(path: string): string {
|
|
335
|
-
return path.endsWith('/') ? path.slice(0, -1) : path
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
public prepareUri(path: string): string {
|
|
339
|
-
// if string starts with / then remove it because we are adding it back in the next line
|
|
340
|
-
if (path.startsWith('/'))
|
|
341
|
-
path = path.slice(1)
|
|
342
|
-
|
|
343
|
-
path = `${this.groupPrefix}/${path}`
|
|
344
|
-
|
|
345
|
-
// if path ends in "/", then remove it
|
|
346
|
-
// e.g. triggered when route is "/"
|
|
347
|
-
return path.endsWith('/') ? path.slice(0, -1) : path
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
private updatePathIfNeeded(newPath: string, originalPath: string): void {
|
|
351
|
-
if (newPath !== originalPath) {
|
|
352
|
-
// Logic to update the path if needed, based on the action module's custom path
|
|
353
|
-
this.path = newPath
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
export const route: Router = new Router()
|