@adonisjs/http-server 6.8.2-3 → 6.8.2-5

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.
Files changed (159) hide show
  1. package/LICENSE.md +1 -1
  2. package/build/factories/http_context.d.ts +1 -0
  3. package/build/factories/http_context.d.ts.map +1 -0
  4. package/build/factories/main.d.ts +1 -0
  5. package/build/factories/main.d.ts.map +1 -0
  6. package/build/factories/qs_parser_factory.d.ts +1 -0
  7. package/build/factories/qs_parser_factory.d.ts.map +1 -0
  8. package/build/factories/request.d.ts +1 -0
  9. package/build/factories/request.d.ts.map +1 -0
  10. package/build/factories/response.d.ts +1 -0
  11. package/build/factories/response.d.ts.map +1 -0
  12. package/build/factories/router.d.ts +1 -0
  13. package/build/factories/router.d.ts.map +1 -0
  14. package/build/factories/server_factory.d.ts +1 -0
  15. package/build/factories/server_factory.d.ts.map +1 -0
  16. package/build/index.d.ts +1 -0
  17. package/build/index.d.ts.map +1 -0
  18. package/build/src/cookies/client.d.ts +1 -0
  19. package/build/src/cookies/client.d.ts.map +1 -0
  20. package/build/src/cookies/drivers/encrypted.d.ts +1 -0
  21. package/build/src/cookies/drivers/encrypted.d.ts.map +1 -0
  22. package/build/src/cookies/drivers/plain.d.ts +1 -0
  23. package/build/src/cookies/drivers/plain.d.ts.map +1 -0
  24. package/build/src/cookies/drivers/signed.d.ts +1 -0
  25. package/build/src/cookies/drivers/signed.d.ts.map +1 -0
  26. package/build/src/cookies/parser.d.ts +1 -0
  27. package/build/src/cookies/parser.d.ts.map +1 -0
  28. package/build/src/cookies/serializer.d.ts +1 -0
  29. package/build/src/cookies/serializer.d.ts.map +1 -0
  30. package/build/src/debug.d.ts +1 -0
  31. package/build/src/debug.d.ts.map +1 -0
  32. package/build/src/define_config.d.ts +1 -0
  33. package/build/src/define_config.d.ts.map +1 -0
  34. package/build/src/define_middleware.d.ts +1 -0
  35. package/build/src/define_middleware.d.ts.map +1 -0
  36. package/build/src/exception_handler.d.ts +1 -0
  37. package/build/src/exception_handler.d.ts.map +1 -0
  38. package/build/src/exceptions.d.ts +1 -0
  39. package/build/src/exceptions.d.ts.map +1 -0
  40. package/build/src/helpers.d.ts +1 -0
  41. package/build/src/helpers.d.ts.map +1 -0
  42. package/build/src/http_context/local_storage.d.ts +1 -0
  43. package/build/src/http_context/local_storage.d.ts.map +1 -0
  44. package/build/src/http_context/main.d.ts +1 -0
  45. package/build/src/http_context/main.d.ts.map +1 -0
  46. package/build/src/qs.d.ts +1 -0
  47. package/build/src/qs.d.ts.map +1 -0
  48. package/build/src/redirect.d.ts +1 -0
  49. package/build/src/redirect.d.ts.map +1 -0
  50. package/build/src/request.d.ts +1 -0
  51. package/build/src/request.d.ts.map +1 -0
  52. package/build/src/response.d.ts +1 -0
  53. package/build/src/response.d.ts.map +1 -0
  54. package/build/src/router/brisk.d.ts +1 -0
  55. package/build/src/router/brisk.d.ts.map +1 -0
  56. package/build/src/router/executor.d.ts +1 -0
  57. package/build/src/router/executor.d.ts.map +1 -0
  58. package/build/src/router/factories/use_return_value.d.ts +1 -0
  59. package/build/src/router/factories/use_return_value.d.ts.map +1 -0
  60. package/build/src/router/group.d.ts +1 -0
  61. package/build/src/router/group.d.ts.map +1 -0
  62. package/build/src/router/lookup_store/main.d.ts +1 -0
  63. package/build/src/router/lookup_store/main.d.ts.map +1 -0
  64. package/build/src/router/lookup_store/route_finder.d.ts +1 -0
  65. package/build/src/router/lookup_store/route_finder.d.ts.map +1 -0
  66. package/build/src/router/lookup_store/url_builder.d.ts +1 -0
  67. package/build/src/router/lookup_store/url_builder.d.ts.map +1 -0
  68. package/build/src/router/lookup_store/url_builder.js +2 -2
  69. package/build/src/router/main.d.ts +4 -2
  70. package/build/src/router/main.d.ts.map +1 -0
  71. package/build/src/router/main.js +4 -0
  72. package/build/src/router/matchers.d.ts +1 -0
  73. package/build/src/router/matchers.d.ts.map +1 -0
  74. package/build/src/router/parser.d.ts +3 -0
  75. package/build/src/router/parser.d.ts.map +1 -0
  76. package/build/src/router/parser.js +5 -0
  77. package/build/src/router/resource.d.ts +1 -0
  78. package/build/src/router/resource.d.ts.map +1 -0
  79. package/build/src/router/route.d.ts +1 -0
  80. package/build/src/router/route.d.ts.map +1 -0
  81. package/build/src/router/store.d.ts +1 -0
  82. package/build/src/router/store.d.ts.map +1 -0
  83. package/build/src/router/store.js +3 -2
  84. package/build/src/server/factories/final_handler.d.ts +1 -0
  85. package/build/src/server/factories/final_handler.d.ts.map +1 -0
  86. package/build/src/server/factories/middleware_handler.d.ts +1 -0
  87. package/build/src/server/factories/middleware_handler.d.ts.map +1 -0
  88. package/build/src/server/factories/write_response.d.ts +1 -0
  89. package/build/src/server/factories/write_response.d.ts.map +1 -0
  90. package/build/src/server/main.d.ts +1 -0
  91. package/build/src/server/main.d.ts.map +1 -0
  92. package/build/src/types/base.d.ts +1 -0
  93. package/build/src/types/base.d.ts.map +1 -0
  94. package/build/src/types/main.d.ts +1 -0
  95. package/build/src/types/main.d.ts.map +1 -0
  96. package/build/src/types/middleware.d.ts +1 -0
  97. package/build/src/types/middleware.d.ts.map +1 -0
  98. package/build/src/types/qs.d.ts +1 -0
  99. package/build/src/types/qs.d.ts.map +1 -0
  100. package/build/src/types/request.d.ts +1 -0
  101. package/build/src/types/request.d.ts.map +1 -0
  102. package/build/src/types/response.d.ts +1 -0
  103. package/build/src/types/response.d.ts.map +1 -0
  104. package/build/src/types/route.d.ts +1 -0
  105. package/build/src/types/route.d.ts.map +1 -0
  106. package/build/src/types/server.d.ts +1 -0
  107. package/build/src/types/server.d.ts.map +1 -0
  108. package/factories/http_context.ts +73 -0
  109. package/factories/main.ts +15 -0
  110. package/factories/qs_parser_factory.ts +54 -0
  111. package/factories/request.ts +101 -0
  112. package/factories/response.ts +106 -0
  113. package/factories/router.ts +61 -0
  114. package/factories/server_factory.ts +94 -0
  115. package/index.ts +23 -0
  116. package/package.json +27 -23
  117. package/src/cookies/client.ts +98 -0
  118. package/src/cookies/drivers/encrypted.ts +42 -0
  119. package/src/cookies/drivers/plain.ts +37 -0
  120. package/src/cookies/drivers/signed.ts +42 -0
  121. package/src/cookies/parser.ts +196 -0
  122. package/src/cookies/serializer.ts +98 -0
  123. package/src/debug.ts +11 -0
  124. package/src/define_config.ts +56 -0
  125. package/src/define_middleware.ts +61 -0
  126. package/src/exception_handler.ts +290 -0
  127. package/src/exceptions.ts +55 -0
  128. package/src/helpers.ts +108 -0
  129. package/src/http_context/local_storage.ts +50 -0
  130. package/src/http_context/main.ts +126 -0
  131. package/src/qs.ts +31 -0
  132. package/src/redirect.ts +181 -0
  133. package/src/request.ts +982 -0
  134. package/src/response.ts +1421 -0
  135. package/src/router/brisk.ts +113 -0
  136. package/src/router/executor.ts +36 -0
  137. package/src/router/factories/use_return_value.ts +26 -0
  138. package/src/router/group.ts +243 -0
  139. package/src/router/lookup_store/main.ts +102 -0
  140. package/src/router/lookup_store/route_finder.ts +60 -0
  141. package/src/router/lookup_store/url_builder.ts +250 -0
  142. package/src/router/main.ts +431 -0
  143. package/src/router/matchers.ts +40 -0
  144. package/src/router/parser.ts +20 -0
  145. package/src/router/resource.ts +277 -0
  146. package/src/router/route.ts +363 -0
  147. package/src/router/store.ts +239 -0
  148. package/src/server/factories/final_handler.ts +38 -0
  149. package/src/server/factories/middleware_handler.ts +23 -0
  150. package/src/server/factories/write_response.ts +26 -0
  151. package/src/server/main.ts +356 -0
  152. package/src/types/base.ts +30 -0
  153. package/src/types/main.ts +16 -0
  154. package/src/types/middleware.ts +59 -0
  155. package/src/types/qs.ts +85 -0
  156. package/src/types/request.ts +52 -0
  157. package/src/types/response.ts +57 -0
  158. package/src/types/route.ts +217 -0
  159. package/src/types/server.ts +92 -0
@@ -0,0 +1,250 @@
1
+ /*
2
+ * @adonisjs/http-server
3
+ *
4
+ * (c) AdonisJS
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+
10
+ import { RuntimeException } from '@poppinss/utils'
11
+ import type { Encryption } from '@adonisjs/encryption'
12
+
13
+ import type { Qs } from '../../qs.js'
14
+ import { parseRoutePattern } from '../parser.js'
15
+ import type { RouteFinder } from './route_finder.js'
16
+
17
+ /**
18
+ * URL builder class is used to create URIs for pre-registered
19
+ * routes.
20
+ *
21
+ * ```ts
22
+ * const builder = new UrlBuilder(encryption, routeFinder)
23
+ *
24
+ * builder
25
+ * .qs({ sort: 'id' })
26
+ * .params([category.id])
27
+ * .make('categories.posts.index')
28
+ * ```
29
+ */
30
+ export class UrlBuilder {
31
+ /**
32
+ * Query string parser
33
+ */
34
+ #qsParser: Qs
35
+
36
+ /**
37
+ * The parameters to apply on the route
38
+ */
39
+ #params: any[] | Record<string, any> = {}
40
+
41
+ /**
42
+ * Query string to append to the route
43
+ */
44
+ #qs: Record<string, any> = {}
45
+
46
+ /**
47
+ * Should we perform the route lookup or just build the
48
+ * given pattern as it is.
49
+ */
50
+ #shouldPerformLookup = true
51
+
52
+ /**
53
+ * BaseURL to append to the constructored URL
54
+ */
55
+ #baseUrl?: string
56
+
57
+ /**
58
+ * Encryption class for making signed URLs
59
+ */
60
+ #encryption: Encryption
61
+
62
+ /**
63
+ * Route finder for finding route pattern
64
+ */
65
+ #routeFinder: RouteFinder
66
+
67
+ constructor(encryption: Encryption, routeFinder: RouteFinder, qsParser: Qs) {
68
+ this.#qsParser = qsParser
69
+ this.#encryption = encryption
70
+ this.#routeFinder = routeFinder
71
+ }
72
+
73
+ /**
74
+ * Raises exception when wildcard values array is missing or
75
+ * has length of zero.
76
+ */
77
+ #ensureHasWildCardValues(pattern: string, values?: string[]) {
78
+ if (!values || !Array.isArray(values) || !values.length) {
79
+ throw new RuntimeException(
80
+ `Cannot make URL for "${pattern}" route. Invalid value provided for wildcard param`
81
+ )
82
+ }
83
+ }
84
+
85
+ /*
86
+ * Raises exception when value is not defined
87
+ */
88
+ #ensureHasParamValue(pattern: string, param: string, value: string) {
89
+ if (value === undefined || value === null) {
90
+ throw new RuntimeException(
91
+ `Cannot make URL for "${pattern}" route. Missing value for "${param}" param`
92
+ )
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Processes the pattern against the params
98
+ */
99
+ #processPattern(pattern: string): string {
100
+ const uriSegments: string[] = []
101
+ const paramsArray = Array.isArray(this.#params) ? this.#params : null
102
+ const paramsObject = !Array.isArray(this.#params) ? this.#params : {}
103
+
104
+ let paramsIndex = 0
105
+ const tokens = parseRoutePattern(pattern)
106
+
107
+ for (const token of tokens) {
108
+ /**
109
+ * Expected wildcard param to be at the end always and hence
110
+ * we must break out from the loop
111
+ */
112
+ if (token.type === 0) {
113
+ uriSegments.push(`${token.val}${token.end}`)
114
+ } else if (token.type === 2) {
115
+ const values: string[] = paramsArray ? paramsArray.slice(paramsIndex) : paramsObject['*']
116
+ this.#ensureHasWildCardValues(pattern, values)
117
+ uriSegments.push(`${values.join('/')}${token.end}`)
118
+ break
119
+ } else {
120
+ const paramName = token.val
121
+ const value = paramsArray ? paramsArray[paramsIndex] : paramsObject[paramName]
122
+
123
+ /**
124
+ * Type = 1 means param is required
125
+ */
126
+ if (token.type === 1) {
127
+ this.#ensureHasParamValue(pattern, paramName, value)
128
+ }
129
+
130
+ paramsIndex++
131
+ if (value !== undefined && value !== null) {
132
+ uriSegments.push(`${value}${token.end}`)
133
+ }
134
+ }
135
+ }
136
+
137
+ return `/${uriSegments.join('/')}`
138
+ }
139
+
140
+ /**
141
+ * Suffix the query string to the URL
142
+ */
143
+ #suffixQueryString(url: string, qs?: Record<string, any>): string {
144
+ if (qs) {
145
+ const queryString = this.#qsParser.stringify(qs)
146
+ url = queryString ? `${url}?${queryString}` : url
147
+ }
148
+
149
+ return url
150
+ }
151
+
152
+ /**
153
+ * Prefixes base URL to the uri string
154
+ */
155
+ #prefixBaseUrl(uri: string) {
156
+ return this.#baseUrl ? `${this.#baseUrl}${uri}` : uri
157
+ }
158
+
159
+ /**
160
+ * Prefix a custom base URL to the final URI
161
+ */
162
+ prefixUrl(url: string): this {
163
+ this.#baseUrl = url
164
+ return this
165
+ }
166
+
167
+ /**
168
+ * Disable route lookup. Calling this method considers
169
+ * the "identifier" as the route pattern
170
+ */
171
+ disableRouteLookup(): this {
172
+ this.#shouldPerformLookup = false
173
+ return this
174
+ }
175
+
176
+ /**
177
+ * Append query string to the final URI
178
+ */
179
+ qs(queryString?: Record<string, any>): this {
180
+ if (!queryString) {
181
+ return this
182
+ }
183
+
184
+ this.#qs = queryString
185
+ return this
186
+ }
187
+
188
+ /**
189
+ * Specify params to apply to the route pattern
190
+ */
191
+ params(params?: any[] | Record<string, any>): this {
192
+ if (!params) {
193
+ return this
194
+ }
195
+
196
+ this.#params = params
197
+ return this
198
+ }
199
+
200
+ /**
201
+ * Generate URL for the given route identifier. The identifier can be the
202
+ * route name, controller.method name or the route pattern
203
+ * itself.
204
+ */
205
+ make(identifier: string) {
206
+ let url: string
207
+
208
+ if (this.#shouldPerformLookup) {
209
+ const route = this.#routeFinder.findOrFail(identifier)
210
+ url = this.#processPattern(route.pattern)
211
+ } else {
212
+ url = this.#processPattern(identifier)
213
+ }
214
+
215
+ return this.#suffixQueryString(this.#prefixBaseUrl(url), this.#qs)
216
+ }
217
+
218
+ /**
219
+ * Generate a signed URL for the given route identifier. The identifier can be the
220
+ * route name, controller.method name or the route pattern
221
+ * itself.
222
+ */
223
+ makeSigned(identifier: string, options?: { expiresIn?: string | number; purpose?: string }) {
224
+ let url: string
225
+
226
+ if (this.#shouldPerformLookup) {
227
+ const route = this.#routeFinder.findOrFail(identifier)
228
+ url = this.#processPattern(route.pattern)
229
+ } else {
230
+ url = this.#processPattern(identifier)
231
+ }
232
+
233
+ /*
234
+ * Making the signature from the qualified url. We do not prefix the domain when
235
+ * making signature, since it just makes the signature big.
236
+ *
237
+ * There might be a case, when someone wants to generate signature for the same route
238
+ * on their 2 different domains, but we ignore that case for now and can consider
239
+ * it later (when someone asks for it)
240
+ */
241
+ const signature = this.#encryption.verifier.sign(
242
+ this.#suffixQueryString(url, this.#qs),
243
+ options?.expiresIn,
244
+ options?.purpose
245
+ )
246
+
247
+ const qs = Object.assign({}, this.#qs, { signature })
248
+ return this.#suffixQueryString(this.#prefixBaseUrl(url), qs)
249
+ }
250
+ }
@@ -0,0 +1,431 @@
1
+ /*
2
+ * @adonisjs/http-server
3
+ *
4
+ * (c) AdonisJS
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+
10
+ import is from '@sindresorhus/is'
11
+ import { moduleImporter } from '@adonisjs/fold'
12
+ import { RuntimeException } from '@poppinss/utils'
13
+ import type { Encryption } from '@adonisjs/encryption'
14
+ import type { Application } from '@adonisjs/application'
15
+
16
+ import type { Qs } from '../qs.js'
17
+ import { Route } from './route.js'
18
+ import { RouteGroup } from './group.js'
19
+ import { BriskRoute } from './brisk.js'
20
+ import { RoutesStore } from './store.js'
21
+ import { toRoutesJSON } from '../helpers.js'
22
+ import { RouteResource } from './resource.js'
23
+ import { LookupStore } from './lookup_store/main.js'
24
+ import { RouteMatchers as Matchers } from './matchers.js'
25
+ import type { Constructor, LazyImport } from '../types/base.js'
26
+ import { defineNamedMiddleware } from '../define_middleware.js'
27
+ import type { MiddlewareAsClass, ParsedGlobalMiddleware } from '../types/middleware.js'
28
+
29
+ import type {
30
+ RouteFn,
31
+ MatchedRoute,
32
+ RouteMatcher,
33
+ RouteMatchers,
34
+ MakeUrlOptions,
35
+ MakeSignedUrlOptions,
36
+ GetControllerHandlers,
37
+ } from '../types/route.js'
38
+ import { parseRoutePattern } from './parser.js'
39
+
40
+ /**
41
+ * Router class exposes a unified API to register new routes, group them or
42
+ * create route resources.
43
+ *
44
+ * ```ts
45
+ * const router = new Router()
46
+ *
47
+ * router.get('/', async function () {
48
+ * // handle request
49
+ * })
50
+ * ```
51
+ */
52
+ export class Router extends LookupStore {
53
+ /**
54
+ * Application is needed to resolve string based controller expressions
55
+ */
56
+ #app: Application<any>
57
+
58
+ /**
59
+ * Store with tokenized routes
60
+ */
61
+ #store: RoutesStore = new RoutesStore()
62
+
63
+ /**
64
+ * Global matchers to test route params against regular expressions.
65
+ */
66
+ #globalMatchers: RouteMatchers = {}
67
+
68
+ /**
69
+ * Middleware store to be shared with the routes
70
+ */
71
+ #middleware: ParsedGlobalMiddleware[] = []
72
+
73
+ /**
74
+ * A boolean to tell the router that a group is in
75
+ * open state right now
76
+ */
77
+ #openedGroups: RouteGroup[] = []
78
+
79
+ /**
80
+ * Collection of routes, including route resource and route
81
+ * group. To get a flat list of routes, call `router.toJSON()`
82
+ */
83
+ routes: (Route | RouteResource | RouteGroup | BriskRoute)[] = []
84
+
85
+ /**
86
+ * A flag to know if routes for explicit domains have been registered.
87
+ * The boolean is computed after calling the "commit" method.
88
+ */
89
+ usingDomains: boolean = false
90
+
91
+ /**
92
+ * Shortcut methods for commonly used route matchers
93
+ */
94
+ matchers = new Matchers()
95
+
96
+ constructor(app: Application<any>, encryption: Encryption, qsParser: Qs) {
97
+ super(encryption, qsParser)
98
+ this.#app = app
99
+ }
100
+
101
+ /**
102
+ * Push a give router entity to the list of routes or the
103
+ * recently opened group.
104
+ */
105
+ #pushToRoutes(entity: Route | RouteResource | RouteGroup | BriskRoute) {
106
+ const openedGroup = this.#openedGroups[this.#openedGroups.length - 1]
107
+ if (openedGroup) {
108
+ openedGroup.routes.push(entity)
109
+ return
110
+ }
111
+
112
+ this.routes.push(entity)
113
+ }
114
+
115
+ /**
116
+ * Parses the route pattern
117
+ */
118
+ parsePattern(pattern: string, matchers?: RouteMatchers) {
119
+ return parseRoutePattern(pattern, matchers)
120
+ }
121
+
122
+ /**
123
+ * Define an array of middleware to use on all the routes.
124
+ * Calling this method multiple times pushes to the
125
+ * existing list of middleware
126
+ */
127
+ use(middleware: LazyImport<MiddlewareAsClass>[]): this {
128
+ middleware.forEach((one) =>
129
+ this.#middleware.push(moduleImporter(one, 'handle').toHandleMethod())
130
+ )
131
+
132
+ return this
133
+ }
134
+
135
+ /**
136
+ * Define a collection of named middleware. The defined collection is
137
+ * not registered anywhere, but instead converted in a new collection
138
+ * of functions you can apply on the routes, or router groups.
139
+ */
140
+ named<NamedMiddleware extends Record<string, LazyImport<MiddlewareAsClass>>>(
141
+ collection: NamedMiddleware
142
+ ) {
143
+ return defineNamedMiddleware<NamedMiddleware>(collection)
144
+ }
145
+
146
+ /**
147
+ * Add route for a given pattern and methods
148
+ */
149
+ route<T extends Constructor<any>>(
150
+ pattern: string,
151
+ methods: string[],
152
+ handler: string | RouteFn | [LazyImport<T> | T, GetControllerHandlers<T>?]
153
+ ) {
154
+ const route = new Route(this.#app, this.#middleware, {
155
+ pattern,
156
+ methods,
157
+ handler,
158
+ globalMatchers: this.#globalMatchers,
159
+ })
160
+
161
+ this.#pushToRoutes(route)
162
+ return route
163
+ }
164
+
165
+ /**
166
+ * Define a route that handles all common HTTP methods
167
+ */
168
+ any<T extends Constructor<any>>(
169
+ pattern: string,
170
+ handler: string | RouteFn | [LazyImport<T> | T, GetControllerHandlers<T>?]
171
+ ) {
172
+ return this.route(
173
+ pattern,
174
+ ['HEAD', 'OPTIONS', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
175
+ handler
176
+ )
177
+ }
178
+
179
+ /**
180
+ * Define `GET` route
181
+ */
182
+ get<T extends Constructor<any>>(
183
+ pattern: string,
184
+ handler: string | RouteFn | [LazyImport<T> | T, GetControllerHandlers<T>?]
185
+ ) {
186
+ return this.route(pattern, ['GET', 'HEAD'], handler)
187
+ }
188
+
189
+ /**
190
+ * Define `POST` route
191
+ */
192
+ post<T extends Constructor<any>>(
193
+ pattern: string,
194
+ handler: string | RouteFn | [LazyImport<T> | T, GetControllerHandlers<T>?]
195
+ ) {
196
+ return this.route(pattern, ['POST'], handler)
197
+ }
198
+
199
+ /**
200
+ * Define `PUT` route
201
+ */
202
+ put<T extends Constructor<any>>(
203
+ pattern: string,
204
+ handler: string | RouteFn | [LazyImport<T> | T, GetControllerHandlers<T>?]
205
+ ) {
206
+ return this.route(pattern, ['PUT'], handler)
207
+ }
208
+
209
+ /**
210
+ * Define `PATCH` route
211
+ */
212
+ patch<T extends Constructor<any>>(
213
+ pattern: string,
214
+ handler: string | RouteFn | [LazyImport<T> | T, GetControllerHandlers<T>?]
215
+ ) {
216
+ return this.route(pattern, ['PATCH'], handler)
217
+ }
218
+
219
+ /**
220
+ * Define `DELETE` route
221
+ */
222
+ delete<T extends Constructor<any>>(
223
+ pattern: string,
224
+ handler: string | RouteFn | [LazyImport<T> | T, GetControllerHandlers<T>?]
225
+ ) {
226
+ return this.route(pattern, ['DELETE'], handler)
227
+ }
228
+
229
+ /**
230
+ * Creates a group of routes. A route group can apply transforms
231
+ * to routes in bulk
232
+ */
233
+ group(callback: () => void) {
234
+ /*
235
+ * Create a new group with empty set of routes
236
+ */
237
+ const group = new RouteGroup([])
238
+
239
+ /**
240
+ * Track group
241
+ */
242
+ this.#pushToRoutes(group)
243
+
244
+ /*
245
+ * Track the group, so that the upcoming calls inside the callback
246
+ * can use this group
247
+ */
248
+ this.#openedGroups.push(group)
249
+
250
+ /*
251
+ * Execute the callback. Now all registered routes will be
252
+ * collected seperately from the `routes` array
253
+ */
254
+ callback()
255
+
256
+ /*
257
+ * Now the callback is over, get rid of the opened group
258
+ */
259
+ this.#openedGroups.pop()
260
+
261
+ return group
262
+ }
263
+
264
+ /**
265
+ * Registers a route resource with conventional set of routes
266
+ */
267
+ resource(resource: string, controller: string | LazyImport<Constructor<any>> | Constructor<any>) {
268
+ const resourceInstance = new RouteResource(this.#app, this.#middleware, {
269
+ resource,
270
+ controller,
271
+ shallow: false,
272
+ globalMatchers: this.#globalMatchers,
273
+ })
274
+
275
+ this.#pushToRoutes(resourceInstance)
276
+ return resourceInstance
277
+ }
278
+
279
+ /**
280
+ * Register a route resource with shallow nested routes.
281
+ */
282
+ shallowResource(
283
+ resource: string,
284
+ controller: string | LazyImport<Constructor<any>> | Constructor<any>
285
+ ) {
286
+ const resourceInstance = new RouteResource(this.#app, this.#middleware, {
287
+ resource,
288
+ controller,
289
+ shallow: true,
290
+ globalMatchers: this.#globalMatchers,
291
+ })
292
+
293
+ this.#pushToRoutes(resourceInstance)
294
+ return resourceInstance
295
+ }
296
+
297
+ /**
298
+ * Returns a brisk route instance for a given URL pattern
299
+ */
300
+ on(pattern: string) {
301
+ const briskRoute = new BriskRoute(this.#app, this.#middleware, {
302
+ pattern,
303
+ globalMatchers: this.#globalMatchers,
304
+ })
305
+
306
+ this.#pushToRoutes(briskRoute)
307
+ return briskRoute
308
+ }
309
+
310
+ /**
311
+ * Define matcher for a given param. The global params are applied
312
+ * on all the routes (unless overridden at the route level).
313
+ */
314
+ where(param: string, matcher: RouteMatcher | string | RegExp): this {
315
+ if (typeof matcher === 'string') {
316
+ this.#globalMatchers[param] = { match: new RegExp(matcher) }
317
+ } else if (is.regExp(matcher)) {
318
+ this.#globalMatchers[param] = { match: matcher }
319
+ } else {
320
+ this.#globalMatchers[param] = matcher
321
+ }
322
+
323
+ return this
324
+ }
325
+
326
+ /**
327
+ * Commit routes to the store. The router is freezed after the
328
+ * commit method is called.
329
+ */
330
+ commit() {
331
+ const routeNamesByDomain: Map<string, Set<string>> = new Map()
332
+
333
+ toRoutesJSON(this.routes).forEach((route) => {
334
+ if (!routeNamesByDomain.has(route.domain)) {
335
+ routeNamesByDomain.set(route.domain, new Set())
336
+ }
337
+
338
+ const routeNames = routeNamesByDomain.get(route.domain)!
339
+
340
+ /*
341
+ * Raise error when route name is already in use. Route names have to be unique
342
+ * to ensure that only one route is returned during lookup.
343
+ */
344
+ if (route.name && routeNames.has(route.name)) {
345
+ throw new RuntimeException(
346
+ `Route with duplicate name found. A route with name "${route.name}" already exists`
347
+ )
348
+ }
349
+
350
+ /*
351
+ * If route has a unique, then track the name for checking duplicates
352
+ */
353
+ if (route.name) {
354
+ routeNames.add(route.name)
355
+ }
356
+
357
+ /**
358
+ * Register the route with the lookup store
359
+ */
360
+ this.register(route)
361
+ this.#store.add(route)
362
+ })
363
+
364
+ routeNamesByDomain.clear()
365
+
366
+ this.usingDomains = this.#store.usingDomains
367
+ this.routes = []
368
+ this.#globalMatchers = {}
369
+ this.#middleware = []
370
+ }
371
+
372
+ /**
373
+ * Find route for a given URL, method and optionally domain
374
+ */
375
+ match(url: string, method: string, hostname?: string | null): null | MatchedRoute {
376
+ const matchingDomain = this.#store.matchDomain(hostname)
377
+
378
+ return matchingDomain.length
379
+ ? this.#store.match(url, method, {
380
+ tokens: matchingDomain,
381
+ hostname: hostname!,
382
+ })
383
+ : this.#store.match(url, method)
384
+ }
385
+
386
+ /**
387
+ * Make URL to a pre-registered route
388
+ */
389
+ makeUrl(
390
+ routeIdentifier: string,
391
+ params?: any[] | Record<string, any>,
392
+ options?: MakeUrlOptions
393
+ ): string {
394
+ const normalizedOptions = Object.assign({}, options)
395
+
396
+ const builder = normalizedOptions.domain
397
+ ? this.builderForDomain(normalizedOptions.domain)
398
+ : this.builder()
399
+
400
+ builder.params(params)
401
+ builder.qs(normalizedOptions.qs)
402
+
403
+ normalizedOptions.prefixUrl && builder.prefixUrl(normalizedOptions.prefixUrl)
404
+ normalizedOptions.disableRouteLookup && builder.disableRouteLookup()
405
+
406
+ return builder.make(routeIdentifier)
407
+ }
408
+
409
+ /**
410
+ * Makes a signed URL to a pre-registered route.
411
+ */
412
+ makeSignedUrl(
413
+ routeIdentifier: string,
414
+ params?: any[] | Record<string, any>,
415
+ options?: MakeSignedUrlOptions
416
+ ): string {
417
+ const normalizedOptions = Object.assign({}, options)
418
+
419
+ const builder = normalizedOptions.domain
420
+ ? this.builderForDomain(normalizedOptions.domain)
421
+ : this.builder()
422
+
423
+ builder.params(params)
424
+ builder.qs(normalizedOptions.qs)
425
+
426
+ normalizedOptions.prefixUrl && builder.prefixUrl(normalizedOptions.prefixUrl)
427
+ normalizedOptions.disableRouteLookup && builder.disableRouteLookup()
428
+
429
+ return builder.makeSigned(routeIdentifier, normalizedOptions)
430
+ }
431
+ }
@@ -0,0 +1,40 @@
1
+ /*
2
+ * @adonisjs/http-server
3
+ *
4
+ * (c) AdonisJS
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+
10
+ import Macroable from '@poppinss/macroable'
11
+
12
+ /**
13
+ * Shortcut methods for commonly used route matchers
14
+ */
15
+ export class RouteMatchers extends Macroable {
16
+ /**
17
+ * Enforce value to be a number and also casts it to number data
18
+ * type
19
+ */
20
+ number() {
21
+ return { match: /^[0-9]+$/, cast: (value: string) => Number(value) }
22
+ }
23
+
24
+ /**
25
+ * Enforce value to be formatted as uuid
26
+ */
27
+ uuid() {
28
+ return {
29
+ match: /^[0-9a-zA-F]{8}-[0-9a-zA-F]{4}-[0-9a-zA-F]{4}-[0-9a-zA-F]{4}-[0-9a-zA-F]{12}$/,
30
+ cast: (value: string) => value.toLowerCase(),
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Enforce value to be formatted as slug
36
+ */
37
+ slug() {
38
+ return { match: /^[^\s-_](?!.*?[-_]{2,})([a-z0-9-\\]{1,})[^\s]*[^-_\s]$/ }
39
+ }
40
+ }