@adonisjs/http-server 7.0.0-1 → 7.0.0-3
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/build/chunk-NC6OWANS.js +4437 -0
- package/build/chunk-NC6OWANS.js.map +1 -0
- package/build/factories/http_server.d.ts +1 -0
- package/build/factories/main.js +332 -14
- package/build/factories/main.js.map +1 -0
- package/build/index.js +309 -22
- package/build/index.js.map +1 -0
- package/build/src/define_middleware.d.ts +2 -1
- package/build/src/router/lookup_store/main.d.ts +1 -3
- package/build/src/router/lookup_store/route_finder.d.ts +5 -1
- package/build/src/router/main.d.ts +5 -4
- package/build/src/router/resource.d.ts +19 -7
- package/build/src/types/main.js +1 -15
- package/build/src/types/main.js.map +1 -0
- package/build/src/types/middleware.d.ts +3 -1
- package/package.json +60 -59
- package/build/factories/http_context.js +0 -51
- package/build/factories/http_server.js +0 -26
- package/build/factories/qs_parser_factory.js +0 -44
- package/build/factories/request.js +0 -73
- package/build/factories/response.js +0 -77
- package/build/factories/router.js +0 -45
- package/build/factories/server_factory.js +0 -65
- package/build/src/cookies/client.js +0 -84
- package/build/src/cookies/drivers/encrypted.js +0 -36
- package/build/src/cookies/drivers/plain.js +0 -33
- package/build/src/cookies/drivers/signed.js +0 -36
- package/build/src/cookies/parser.js +0 -167
- package/build/src/cookies/serializer.js +0 -79
- package/build/src/debug.js +0 -10
- package/build/src/define_config.js +0 -68
- package/build/src/define_middleware.js +0 -35
- package/build/src/exception_handler.js +0 -306
- package/build/src/exceptions.js +0 -38
- package/build/src/helpers.js +0 -105
- package/build/src/http_context/local_storage.js +0 -39
- package/build/src/http_context/main.js +0 -105
- package/build/src/qs.js +0 -25
- package/build/src/redirect.js +0 -140
- package/build/src/request.js +0 -865
- package/build/src/response.js +0 -1208
- package/build/src/router/brisk.js +0 -85
- package/build/src/router/executor.js +0 -30
- package/build/src/router/factories/use_return_value.js +0 -22
- package/build/src/router/group.js +0 -207
- package/build/src/router/lookup_store/main.js +0 -86
- package/build/src/router/lookup_store/route_finder.js +0 -49
- package/build/src/router/lookup_store/url_builder.js +0 -209
- package/build/src/router/main.js +0 -316
- package/build/src/router/matchers.js +0 -36
- package/build/src/router/parser.js +0 -17
- package/build/src/router/resource.js +0 -216
- package/build/src/router/route.js +0 -293
- package/build/src/router/store.js +0 -195
- package/build/src/server/factories/final_handler.js +0 -30
- package/build/src/server/factories/middleware_handler.js +0 -16
- package/build/src/server/factories/write_response.js +0 -24
- package/build/src/server/main.js +0 -292
- package/build/src/types/base.js +0 -9
- package/build/src/types/middleware.js +0 -9
- package/build/src/types/qs.js +0 -9
- package/build/src/types/request.js +0 -9
- package/build/src/types/response.js +0 -9
- package/build/src/types/route.js +0 -9
- package/build/src/types/server.js +0 -9
package/build/src/router/main.js
DELETED
|
@@ -1,316 +0,0 @@
|
|
|
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
|
-
import is from '@sindresorhus/is';
|
|
10
|
-
import { moduleImporter } from '@adonisjs/fold';
|
|
11
|
-
import { RuntimeException } from '@poppinss/utils';
|
|
12
|
-
import { Route } from './route.js';
|
|
13
|
-
import { RouteGroup } from './group.js';
|
|
14
|
-
import { BriskRoute } from './brisk.js';
|
|
15
|
-
import { RoutesStore } from './store.js';
|
|
16
|
-
import { toRoutesJSON } from '../helpers.js';
|
|
17
|
-
import { RouteResource } from './resource.js';
|
|
18
|
-
import { LookupStore } from './lookup_store/main.js';
|
|
19
|
-
import { RouteMatchers as Matchers } from './matchers.js';
|
|
20
|
-
import { defineNamedMiddleware } from '../define_middleware.js';
|
|
21
|
-
import { parseRoutePattern } from './parser.js';
|
|
22
|
-
/**
|
|
23
|
-
* Router class exposes a unified API to register new routes, group them or
|
|
24
|
-
* create route resources.
|
|
25
|
-
*
|
|
26
|
-
* ```ts
|
|
27
|
-
* const router = new Router()
|
|
28
|
-
*
|
|
29
|
-
* router.get('/', async function () {
|
|
30
|
-
* // handle request
|
|
31
|
-
* })
|
|
32
|
-
* ```
|
|
33
|
-
*/
|
|
34
|
-
export class Router extends LookupStore {
|
|
35
|
-
/**
|
|
36
|
-
* Application is needed to resolve string based controller expressions
|
|
37
|
-
*/
|
|
38
|
-
#app;
|
|
39
|
-
/**
|
|
40
|
-
* Store with tokenized routes
|
|
41
|
-
*/
|
|
42
|
-
#store = new RoutesStore();
|
|
43
|
-
/**
|
|
44
|
-
* Global matchers to test route params against regular expressions.
|
|
45
|
-
*/
|
|
46
|
-
#globalMatchers = {};
|
|
47
|
-
/**
|
|
48
|
-
* Middleware store to be shared with the routes
|
|
49
|
-
*/
|
|
50
|
-
#middleware = [];
|
|
51
|
-
/**
|
|
52
|
-
* A boolean to tell the router that a group is in
|
|
53
|
-
* open state right now
|
|
54
|
-
*/
|
|
55
|
-
#openedGroups = [];
|
|
56
|
-
/**
|
|
57
|
-
* Collection of routes, including route resource and route
|
|
58
|
-
* group. To get a flat list of routes, call `router.toJSON()`
|
|
59
|
-
*/
|
|
60
|
-
routes = [];
|
|
61
|
-
/**
|
|
62
|
-
* A flag to know if routes for explicit domains have been registered.
|
|
63
|
-
* The boolean is computed after calling the "commit" method.
|
|
64
|
-
*/
|
|
65
|
-
usingDomains = false;
|
|
66
|
-
/**
|
|
67
|
-
* Shortcut methods for commonly used route matchers
|
|
68
|
-
*/
|
|
69
|
-
matchers = new Matchers();
|
|
70
|
-
constructor(app, encryption, qsParser) {
|
|
71
|
-
super(encryption, qsParser);
|
|
72
|
-
this.#app = app;
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Push a give router entity to the list of routes or the
|
|
76
|
-
* recently opened group.
|
|
77
|
-
*/
|
|
78
|
-
#pushToRoutes(entity) {
|
|
79
|
-
const openedGroup = this.#openedGroups[this.#openedGroups.length - 1];
|
|
80
|
-
if (openedGroup) {
|
|
81
|
-
openedGroup.routes.push(entity);
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
this.routes.push(entity);
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Parses the route pattern
|
|
88
|
-
*/
|
|
89
|
-
parsePattern(pattern, matchers) {
|
|
90
|
-
return parseRoutePattern(pattern, matchers);
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Define an array of middleware to use on all the routes.
|
|
94
|
-
* Calling this method multiple times pushes to the
|
|
95
|
-
* existing list of middleware
|
|
96
|
-
*/
|
|
97
|
-
use(middleware) {
|
|
98
|
-
middleware.forEach((one) => this.#middleware.push(moduleImporter(one, 'handle').toHandleMethod()));
|
|
99
|
-
return this;
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Define a collection of named middleware. The defined collection is
|
|
103
|
-
* not registered anywhere, but instead converted in a new collection
|
|
104
|
-
* of functions you can apply on the routes, or router groups.
|
|
105
|
-
*/
|
|
106
|
-
named(collection) {
|
|
107
|
-
return defineNamedMiddleware(collection);
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Add route for a given pattern and methods
|
|
111
|
-
*/
|
|
112
|
-
route(pattern, methods, handler) {
|
|
113
|
-
const route = new Route(this.#app, this.#middleware, {
|
|
114
|
-
pattern,
|
|
115
|
-
methods,
|
|
116
|
-
handler,
|
|
117
|
-
globalMatchers: this.#globalMatchers,
|
|
118
|
-
});
|
|
119
|
-
this.#pushToRoutes(route);
|
|
120
|
-
return route;
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Define a route that handles all common HTTP methods
|
|
124
|
-
*/
|
|
125
|
-
any(pattern, handler) {
|
|
126
|
-
return this.route(pattern, ['HEAD', 'OPTIONS', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE'], handler);
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Define `GET` route
|
|
130
|
-
*/
|
|
131
|
-
get(pattern, handler) {
|
|
132
|
-
return this.route(pattern, ['GET', 'HEAD'], handler);
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* Define `POST` route
|
|
136
|
-
*/
|
|
137
|
-
post(pattern, handler) {
|
|
138
|
-
return this.route(pattern, ['POST'], handler);
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Define `PUT` route
|
|
142
|
-
*/
|
|
143
|
-
put(pattern, handler) {
|
|
144
|
-
return this.route(pattern, ['PUT'], handler);
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Define `PATCH` route
|
|
148
|
-
*/
|
|
149
|
-
patch(pattern, handler) {
|
|
150
|
-
return this.route(pattern, ['PATCH'], handler);
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* Define `DELETE` route
|
|
154
|
-
*/
|
|
155
|
-
delete(pattern, handler) {
|
|
156
|
-
return this.route(pattern, ['DELETE'], handler);
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Creates a group of routes. A route group can apply transforms
|
|
160
|
-
* to routes in bulk
|
|
161
|
-
*/
|
|
162
|
-
group(callback) {
|
|
163
|
-
/*
|
|
164
|
-
* Create a new group with empty set of routes
|
|
165
|
-
*/
|
|
166
|
-
const group = new RouteGroup([]);
|
|
167
|
-
/**
|
|
168
|
-
* Track group
|
|
169
|
-
*/
|
|
170
|
-
this.#pushToRoutes(group);
|
|
171
|
-
/*
|
|
172
|
-
* Track the group, so that the upcoming calls inside the callback
|
|
173
|
-
* can use this group
|
|
174
|
-
*/
|
|
175
|
-
this.#openedGroups.push(group);
|
|
176
|
-
/*
|
|
177
|
-
* Execute the callback. Now all registered routes will be
|
|
178
|
-
* collected seperately from the `routes` array
|
|
179
|
-
*/
|
|
180
|
-
callback();
|
|
181
|
-
/*
|
|
182
|
-
* Now the callback is over, get rid of the opened group
|
|
183
|
-
*/
|
|
184
|
-
this.#openedGroups.pop();
|
|
185
|
-
return group;
|
|
186
|
-
}
|
|
187
|
-
/**
|
|
188
|
-
* Registers a route resource with conventional set of routes
|
|
189
|
-
*/
|
|
190
|
-
resource(resource, controller) {
|
|
191
|
-
const resourceInstance = new RouteResource(this.#app, this.#middleware, {
|
|
192
|
-
resource,
|
|
193
|
-
controller,
|
|
194
|
-
shallow: false,
|
|
195
|
-
globalMatchers: this.#globalMatchers,
|
|
196
|
-
});
|
|
197
|
-
this.#pushToRoutes(resourceInstance);
|
|
198
|
-
return resourceInstance;
|
|
199
|
-
}
|
|
200
|
-
/**
|
|
201
|
-
* Register a route resource with shallow nested routes.
|
|
202
|
-
*/
|
|
203
|
-
shallowResource(resource, controller) {
|
|
204
|
-
const resourceInstance = new RouteResource(this.#app, this.#middleware, {
|
|
205
|
-
resource,
|
|
206
|
-
controller,
|
|
207
|
-
shallow: true,
|
|
208
|
-
globalMatchers: this.#globalMatchers,
|
|
209
|
-
});
|
|
210
|
-
this.#pushToRoutes(resourceInstance);
|
|
211
|
-
return resourceInstance;
|
|
212
|
-
}
|
|
213
|
-
/**
|
|
214
|
-
* Returns a brisk route instance for a given URL pattern
|
|
215
|
-
*/
|
|
216
|
-
on(pattern) {
|
|
217
|
-
const briskRoute = new BriskRoute(this.#app, this.#middleware, {
|
|
218
|
-
pattern,
|
|
219
|
-
globalMatchers: this.#globalMatchers,
|
|
220
|
-
});
|
|
221
|
-
this.#pushToRoutes(briskRoute);
|
|
222
|
-
return briskRoute;
|
|
223
|
-
}
|
|
224
|
-
/**
|
|
225
|
-
* Define matcher for a given param. The global params are applied
|
|
226
|
-
* on all the routes (unless overridden at the route level).
|
|
227
|
-
*/
|
|
228
|
-
where(param, matcher) {
|
|
229
|
-
if (typeof matcher === 'string') {
|
|
230
|
-
this.#globalMatchers[param] = { match: new RegExp(matcher) };
|
|
231
|
-
}
|
|
232
|
-
else if (is.regExp(matcher)) {
|
|
233
|
-
this.#globalMatchers[param] = { match: matcher };
|
|
234
|
-
}
|
|
235
|
-
else {
|
|
236
|
-
this.#globalMatchers[param] = matcher;
|
|
237
|
-
}
|
|
238
|
-
return this;
|
|
239
|
-
}
|
|
240
|
-
/**
|
|
241
|
-
* Commit routes to the store. The router is freezed after the
|
|
242
|
-
* commit method is called.
|
|
243
|
-
*/
|
|
244
|
-
commit() {
|
|
245
|
-
const routeNamesByDomain = new Map();
|
|
246
|
-
toRoutesJSON(this.routes).forEach((route) => {
|
|
247
|
-
if (!routeNamesByDomain.has(route.domain)) {
|
|
248
|
-
routeNamesByDomain.set(route.domain, new Set());
|
|
249
|
-
}
|
|
250
|
-
const routeNames = routeNamesByDomain.get(route.domain);
|
|
251
|
-
/*
|
|
252
|
-
* Raise error when route name is already in use. Route names have to be unique
|
|
253
|
-
* to ensure that only one route is returned during lookup.
|
|
254
|
-
*/
|
|
255
|
-
if (route.name && routeNames.has(route.name)) {
|
|
256
|
-
throw new RuntimeException(`Route with duplicate name found. A route with name "${route.name}" already exists`);
|
|
257
|
-
}
|
|
258
|
-
/*
|
|
259
|
-
* If route has a unique, then track the name for checking duplicates
|
|
260
|
-
*/
|
|
261
|
-
if (route.name) {
|
|
262
|
-
routeNames.add(route.name);
|
|
263
|
-
}
|
|
264
|
-
/**
|
|
265
|
-
* Register the route with the lookup store
|
|
266
|
-
*/
|
|
267
|
-
this.register(route);
|
|
268
|
-
this.#store.add(route);
|
|
269
|
-
});
|
|
270
|
-
routeNamesByDomain.clear();
|
|
271
|
-
this.usingDomains = this.#store.usingDomains;
|
|
272
|
-
this.routes = [];
|
|
273
|
-
this.#globalMatchers = {};
|
|
274
|
-
this.#middleware = [];
|
|
275
|
-
}
|
|
276
|
-
/**
|
|
277
|
-
* Find route for a given URL, method and optionally domain
|
|
278
|
-
*/
|
|
279
|
-
match(url, method, hostname) {
|
|
280
|
-
const matchingDomain = this.#store.matchDomain(hostname);
|
|
281
|
-
return matchingDomain.length
|
|
282
|
-
? this.#store.match(url, method, {
|
|
283
|
-
tokens: matchingDomain,
|
|
284
|
-
hostname: hostname,
|
|
285
|
-
})
|
|
286
|
-
: this.#store.match(url, method);
|
|
287
|
-
}
|
|
288
|
-
/**
|
|
289
|
-
* Make URL to a pre-registered route
|
|
290
|
-
*/
|
|
291
|
-
makeUrl(routeIdentifier, params, options) {
|
|
292
|
-
const normalizedOptions = Object.assign({}, options);
|
|
293
|
-
const builder = normalizedOptions.domain
|
|
294
|
-
? this.builderForDomain(normalizedOptions.domain)
|
|
295
|
-
: this.builder();
|
|
296
|
-
builder.params(params);
|
|
297
|
-
builder.qs(normalizedOptions.qs);
|
|
298
|
-
normalizedOptions.prefixUrl && builder.prefixUrl(normalizedOptions.prefixUrl);
|
|
299
|
-
normalizedOptions.disableRouteLookup && builder.disableRouteLookup();
|
|
300
|
-
return builder.make(routeIdentifier);
|
|
301
|
-
}
|
|
302
|
-
/**
|
|
303
|
-
* Makes a signed URL to a pre-registered route.
|
|
304
|
-
*/
|
|
305
|
-
makeSignedUrl(routeIdentifier, params, options) {
|
|
306
|
-
const normalizedOptions = Object.assign({}, options);
|
|
307
|
-
const builder = normalizedOptions.domain
|
|
308
|
-
? this.builderForDomain(normalizedOptions.domain)
|
|
309
|
-
: this.builder();
|
|
310
|
-
builder.params(params);
|
|
311
|
-
builder.qs(normalizedOptions.qs);
|
|
312
|
-
normalizedOptions.prefixUrl && builder.prefixUrl(normalizedOptions.prefixUrl);
|
|
313
|
-
normalizedOptions.disableRouteLookup && builder.disableRouteLookup();
|
|
314
|
-
return builder.makeSigned(routeIdentifier, normalizedOptions);
|
|
315
|
-
}
|
|
316
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
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
|
-
import Macroable from '@poppinss/macroable';
|
|
10
|
-
/**
|
|
11
|
-
* Shortcut methods for commonly used route matchers
|
|
12
|
-
*/
|
|
13
|
-
export class RouteMatchers extends Macroable {
|
|
14
|
-
/**
|
|
15
|
-
* Enforce value to be a number and also casts it to number data
|
|
16
|
-
* type
|
|
17
|
-
*/
|
|
18
|
-
number() {
|
|
19
|
-
return { match: /^[0-9]+$/, cast: (value) => Number(value) };
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Enforce value to be formatted as uuid
|
|
23
|
-
*/
|
|
24
|
-
uuid() {
|
|
25
|
-
return {
|
|
26
|
-
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}$/,
|
|
27
|
-
cast: (value) => value.toLowerCase(),
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Enforce value to be formatted as slug
|
|
32
|
-
*/
|
|
33
|
-
slug() {
|
|
34
|
-
return { match: /^[^\s-_](?!.*?[-_]{2,})([a-z0-9-\\]{1,})[^\s]*[^-_\s]$/ };
|
|
35
|
-
}
|
|
36
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
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
|
-
// @ts-expect-error
|
|
10
|
-
import matchit from '@poppinss/matchit';
|
|
11
|
-
/**
|
|
12
|
-
* Parses the route pattern
|
|
13
|
-
*/
|
|
14
|
-
export function parseRoutePattern(pattern, matchers) {
|
|
15
|
-
const tokens = matchit.parse(pattern, matchers);
|
|
16
|
-
return tokens;
|
|
17
|
-
}
|
|
@@ -1,216 +0,0 @@
|
|
|
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
|
-
import string from '@poppinss/utils/string';
|
|
10
|
-
import Macroable from '@poppinss/macroable';
|
|
11
|
-
import { RuntimeException } from '@poppinss/utils';
|
|
12
|
-
import { Route } from './route.js';
|
|
13
|
-
/**
|
|
14
|
-
* Route resource exposes the API to register multiple routes for a resource.
|
|
15
|
-
*/
|
|
16
|
-
export class RouteResource extends Macroable {
|
|
17
|
-
/**
|
|
18
|
-
* Resource identifier. Nested resources are separated
|
|
19
|
-
* with a dot notation
|
|
20
|
-
*/
|
|
21
|
-
#resource;
|
|
22
|
-
/**
|
|
23
|
-
* The controller to handle resource routing requests
|
|
24
|
-
*/
|
|
25
|
-
#controller;
|
|
26
|
-
/**
|
|
27
|
-
* Is it a shallow resource? Shallow resources URLs do not have parent
|
|
28
|
-
* resource name and id once they can be identified with the id.
|
|
29
|
-
*/
|
|
30
|
-
#shallow = false;
|
|
31
|
-
/**
|
|
32
|
-
* Matchers inherited from the router
|
|
33
|
-
*/
|
|
34
|
-
#globalMatchers;
|
|
35
|
-
/**
|
|
36
|
-
* Reference to the AdonisJS application
|
|
37
|
-
*/
|
|
38
|
-
#app;
|
|
39
|
-
/**
|
|
40
|
-
* Middleware registered on the router
|
|
41
|
-
*/
|
|
42
|
-
#routerMiddleware;
|
|
43
|
-
/**
|
|
44
|
-
* Parameter names for the resources. Defaults to `id` for
|
|
45
|
-
* a singular resource and `resource_id` for nested
|
|
46
|
-
* resources.
|
|
47
|
-
*/
|
|
48
|
-
#params = {};
|
|
49
|
-
/**
|
|
50
|
-
* Base name for the routes. We suffix action names
|
|
51
|
-
* on top of the base name
|
|
52
|
-
*/
|
|
53
|
-
#routesBaseName;
|
|
54
|
-
/**
|
|
55
|
-
* A collection of routes instances that belongs to this resource
|
|
56
|
-
*/
|
|
57
|
-
routes = [];
|
|
58
|
-
constructor(app, routerMiddleware, options) {
|
|
59
|
-
super();
|
|
60
|
-
this.#validateResourceName(options.resource);
|
|
61
|
-
this.#app = app;
|
|
62
|
-
this.#shallow = options.shallow;
|
|
63
|
-
this.#routerMiddleware = routerMiddleware;
|
|
64
|
-
this.#controller = options.controller;
|
|
65
|
-
this.#globalMatchers = options.globalMatchers;
|
|
66
|
-
this.#resource = this.#normalizeResourceName(options.resource);
|
|
67
|
-
this.#routesBaseName = this.#getRoutesBaseName();
|
|
68
|
-
this.#buildRoutes();
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Normalizes the resource name to dropping leading and trailing
|
|
72
|
-
* slashes.
|
|
73
|
-
*/
|
|
74
|
-
#normalizeResourceName(resource) {
|
|
75
|
-
return resource.replace(/^\//, '').replace(/\/$/, '');
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Ensure resource name is not an empty string
|
|
79
|
-
*/
|
|
80
|
-
#validateResourceName(resource) {
|
|
81
|
-
if (!resource || resource === '/') {
|
|
82
|
-
throw new RuntimeException(`Invalid resource name "${resource}"`);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Converting segments of a resource to snake case to
|
|
87
|
-
* make the route name.
|
|
88
|
-
*/
|
|
89
|
-
#getRoutesBaseName() {
|
|
90
|
-
return this.#resource
|
|
91
|
-
.split('.')
|
|
92
|
-
.map((token) => string.snakeCase(token))
|
|
93
|
-
.join('.');
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Create a new route for the given pattern, methods and controller action
|
|
97
|
-
*/
|
|
98
|
-
#createRoute(pattern, methods, action) {
|
|
99
|
-
const route = new Route(this.#app, this.#routerMiddleware, {
|
|
100
|
-
pattern,
|
|
101
|
-
methods,
|
|
102
|
-
handler: typeof this.#controller === 'string'
|
|
103
|
-
? `${this.#controller}.${action}`
|
|
104
|
-
: [this.#controller, action],
|
|
105
|
-
globalMatchers: this.#globalMatchers,
|
|
106
|
-
});
|
|
107
|
-
route.as(`${this.#routesBaseName}.${action}`);
|
|
108
|
-
this.routes.push(route);
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Returns the `resource_id` name for a given resource. The
|
|
112
|
-
* resource name is converted to singular form and
|
|
113
|
-
* transformed to snake case.
|
|
114
|
-
*
|
|
115
|
-
* photos becomes photo_id
|
|
116
|
-
* users becomes user_id
|
|
117
|
-
*/
|
|
118
|
-
#getResourceId(resource) {
|
|
119
|
-
return `${string.snakeCase(string.singular(resource))}_id`;
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Build routes for the given resource
|
|
123
|
-
*/
|
|
124
|
-
#buildRoutes() {
|
|
125
|
-
const resources = this.#resource.split('.');
|
|
126
|
-
const mainResource = resources.pop();
|
|
127
|
-
this.#params[mainResource] = ':id';
|
|
128
|
-
const baseURI = `${resources
|
|
129
|
-
.map((resource) => {
|
|
130
|
-
const paramName = `:${this.#getResourceId(resource)}`;
|
|
131
|
-
this.#params[resource] = paramName;
|
|
132
|
-
return `${resource}/${paramName}`;
|
|
133
|
-
})
|
|
134
|
-
.join('/')}/${mainResource}`;
|
|
135
|
-
this.#createRoute(baseURI, ['GET', 'HEAD'], 'index');
|
|
136
|
-
this.#createRoute(`${baseURI}/create`, ['GET', 'HEAD'], 'create');
|
|
137
|
-
this.#createRoute(baseURI, ['POST'], 'store');
|
|
138
|
-
this.#createRoute(`${this.#shallow ? mainResource : baseURI}/:id`, ['GET', 'HEAD'], 'show');
|
|
139
|
-
this.#createRoute(`${this.#shallow ? mainResource : baseURI}/:id/edit`, ['GET', 'HEAD'], 'edit');
|
|
140
|
-
this.#createRoute(`${this.#shallow ? mainResource : baseURI}/:id`, ['PUT', 'PATCH'], 'update');
|
|
141
|
-
this.#createRoute(`${this.#shallow ? mainResource : baseURI}/:id`, ['DELETE'], 'destroy');
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Filter the routes based on their partial names
|
|
145
|
-
*/
|
|
146
|
-
#filter(names, inverse) {
|
|
147
|
-
const actions = Array.isArray(names) ? names : [names];
|
|
148
|
-
return this.routes.filter((route) => {
|
|
149
|
-
const match = actions.find((name) => route.getName().endsWith(name));
|
|
150
|
-
return inverse ? !match : match;
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* Register only given routes and remove others
|
|
155
|
-
*/
|
|
156
|
-
only(names) {
|
|
157
|
-
this.#filter(names, true).forEach((route) => route.markAsDeleted());
|
|
158
|
-
return this;
|
|
159
|
-
}
|
|
160
|
-
/**
|
|
161
|
-
* Register all routes, except the one's defined
|
|
162
|
-
*/
|
|
163
|
-
except(names) {
|
|
164
|
-
this.#filter(names, false).forEach((route) => route.markAsDeleted());
|
|
165
|
-
return this;
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* Register api only routes. The `create` and `edit` routes, which
|
|
169
|
-
* are meant to show forms will not be registered
|
|
170
|
-
*/
|
|
171
|
-
apiOnly() {
|
|
172
|
-
return this.except(['create', 'edit']);
|
|
173
|
-
}
|
|
174
|
-
/**
|
|
175
|
-
* Define matcher for params inside the resource
|
|
176
|
-
*/
|
|
177
|
-
where(key, matcher) {
|
|
178
|
-
this.routes.forEach((route) => {
|
|
179
|
-
route.where(key, matcher);
|
|
180
|
-
});
|
|
181
|
-
return this;
|
|
182
|
-
}
|
|
183
|
-
tap(actions, callback) {
|
|
184
|
-
if (typeof actions === 'function') {
|
|
185
|
-
this.routes.forEach((route) => actions(route));
|
|
186
|
-
return this;
|
|
187
|
-
}
|
|
188
|
-
this.#filter(actions, false).forEach((route) => callback(route));
|
|
189
|
-
return this;
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Set the param name for a given resource
|
|
193
|
-
*/
|
|
194
|
-
params(resources) {
|
|
195
|
-
Object.keys(resources).forEach((resource) => {
|
|
196
|
-
const param = resources[resource];
|
|
197
|
-
const existingParam = this.#params[resource];
|
|
198
|
-
this.#params[resource] = `:${param}`;
|
|
199
|
-
this.routes.forEach((route) => {
|
|
200
|
-
route.setPattern(route.getPattern().replace(`${resource}/${existingParam}`, `${resource}/:${param}`));
|
|
201
|
-
});
|
|
202
|
-
});
|
|
203
|
-
return this;
|
|
204
|
-
}
|
|
205
|
-
/**
|
|
206
|
-
* Prepend name to all the routes
|
|
207
|
-
*/
|
|
208
|
-
as(name, normalizeName = true) {
|
|
209
|
-
name = normalizeName ? string.snakeCase(name) : name;
|
|
210
|
-
this.routes.forEach((route) => {
|
|
211
|
-
route.as(route.getName().replace(this.#routesBaseName, name), false);
|
|
212
|
-
});
|
|
213
|
-
this.#routesBaseName = name;
|
|
214
|
-
return this;
|
|
215
|
-
}
|
|
216
|
-
}
|