@eggjs/router
Version:
Router middleware for egg/koa. Provides RESTful resource routing.
783 lines • 50.3 kB
JavaScript
/**
* RESTful resource routing middleware for eggjs.
*/
import { debuglog } from 'node:util';
import assert from 'node:assert';
import compose from 'koa-compose';
import HttpError from 'http-errors';
import methods from 'methods';
import { Layer } from './Layer.js';
const debug = debuglog('@eggjs/router:Router');
export class Router {
opts;
methods;
/** Layer stack */
stack = [];
params = {};
/**
* Create a new router.
*
* @example
*
* Basic usage:
*
* ```javascript
* var Koa = require('koa');
* var Router = require('koa-router');
*
* var app = new Koa();
* var router = new Router();
*
* router.get('/', (ctx, next) => {
* // ctx.router available
* });
*
* app
* .use(router.routes())
* .use(router.allowedMethods());
* ```
*
* @alias module:koa-router
* @param {Object=} opts optional
* @param {String=} opts.prefix prefix router paths
* @class
*/
constructor(opts) {
this.opts = opts ?? {};
this.methods = this.opts.methods ?? [
'HEAD',
'OPTIONS',
'GET',
'PUT',
'PATCH',
'POST',
'DELETE',
];
}
use(pathOrMiddleware, ...middlewares) {
// support array of paths
// use(paths, ...middlewares)
if (Array.isArray(pathOrMiddleware) && typeof pathOrMiddleware[0] === 'string') {
for (const path of pathOrMiddleware) {
this.use(path, ...middlewares);
}
return this;
}
let path = '';
let hasPath = false;
if (typeof pathOrMiddleware === 'string') {
// use(path, ...middlewares)
path = pathOrMiddleware;
hasPath = true;
}
else if (typeof pathOrMiddleware === 'function') {
// use(...middlewares)
middlewares = [pathOrMiddleware, ...middlewares];
}
for (const m of middlewares) {
if (m.router) {
for (const nestedLayer of m.router.stack) {
if (path) {
nestedLayer.setPrefix(path);
}
if (this.opts.prefix) {
nestedLayer.setPrefix(this.opts.prefix);
}
this.stack.push(nestedLayer);
}
if (this.params) {
for (const key in this.params) {
m.router.param(key, this.params[key]);
}
}
}
else {
this.register(path || '(.*)', [], m, { end: false, ignoreCaptures: !hasPath });
}
}
return this;
}
/**
* Set the path prefix for a Router instance that was already initialized.
*
* @example
*
* ```javascript
* router.prefix('/things/:thing_id')
* ```
*
* @param {String} prefix prefix string
* @return {Router} router instance
*/
prefix(prefix) {
prefix = prefix.replace(/\/$/, '');
this.opts.prefix = prefix;
for (const layer of this.stack) {
layer.setPrefix(prefix);
}
return this;
}
/**
* Returns router middleware which dispatches a route matching the request.
*
* @return {Function} middleware function
*/
routes() {
const dispatch = (ctx, next) => {
const routerPath = this.opts.routerPath || ctx.routerPath || ctx.path;
const matched = this.match(routerPath, ctx.method);
debug('dispatch: %s %s, routerPath: %s, matched: %s', ctx.method, ctx.path, routerPath, matched.route);
if (ctx.matched) {
ctx.matched.push(...matched.path);
}
else {
ctx.matched = matched.path;
}
ctx.router = this;
if (!matched.route) {
return next();
}
const matchedLayers = matched.pathAndMethod;
const layerChain = matchedLayers.reduce((memo, layer) => {
memo.push((ctx, next) => {
// ctx.captures = layer.captures(routerPath, ctx.captures);
ctx.captures = layer.captures(routerPath);
ctx.params = layer.params(routerPath, ctx.captures, ctx.params);
// ctx._matchedRouteName & ctx._matchedRoute for compatibility
ctx._matchedRouteName = ctx.routerName = layer.name;
if (!layer.name) {
ctx._matchedRouteName = undefined;
}
ctx._matchedRoute = ctx.routerPath = layer.path;
return next();
});
return memo.concat(layer.stack);
}, []);
return compose(layerChain)(ctx, next);
};
dispatch.router = this;
return dispatch;
}
/**
* @alias to routes()
*/
middleware() {
return this.routes();
}
/**
* Returns separate middleware for responding to `OPTIONS` requests with
* an `Allow` header containing the allowed methods, as well as responding
* with `405 Method Not Allowed` and `501 Not Implemented` as appropriate.
*
* @example
*
* ```javascript
* var Koa = require('koa');
* var Router = require('koa-router');
*
* var app = new Koa();
* var router = new Router();
*
* app.use(router.routes());
* app.use(router.allowedMethods());
* ```
*
* **Example with [Boom](https://github.com/hapijs/boom)**
*
* ```javascript
* var Koa = require('koa');
* var Router = require('koa-router');
* var Boom = require('boom');
*
* var app = new Koa();
* var router = new Router();
*
* app.use(router.routes());
* app.use(router.allowedMethods({
* throw: true,
* notImplemented: () => new Boom.notImplemented(),
* methodNotAllowed: () => new Boom.methodNotAllowed()
* }));
* ```
*
* @param {Object=} options optional params
* @param {Boolean=} options.throw throw error instead of setting status and header
* @param {Function=} options.notImplemented throw the returned value in place of the default NotImplemented error
* @param {Function=} options.methodNotAllowed throw the returned value in place of the default MethodNotAllowed error
* @return {Function} middleware function
*/
allowedMethods(options) {
const implemented = this.methods;
return async function allowedMethods(ctx, next) {
await next();
if (ctx.status && ctx.status !== 404)
return;
const allowed = {};
ctx.matched.forEach((route) => {
route.methods.forEach(method => {
allowed[method] = method;
});
});
const allowedMethods = Object.keys(allowed);
if (!implemented.includes(ctx.method)) {
if (options?.throw) {
let notImplementedThrowable;
if (typeof options?.notImplemented === 'function') {
notImplementedThrowable = options.notImplemented(); // set whatever the user returns from their function
}
else {
notImplementedThrowable = new HttpError.NotImplemented();
}
throw notImplementedThrowable;
}
else {
ctx.status = 501;
ctx.set('Allow', allowedMethods.join(', '));
}
}
else if (allowedMethods.length > 0) {
if (ctx.method === 'OPTIONS') {
ctx.status = 200;
ctx.body = '';
ctx.set('Allow', allowedMethods.join(', '));
}
else if (!allowed[ctx.method]) {
if (options?.throw) {
let notAllowedThrowable;
if (typeof options?.methodNotAllowed === 'function') {
notAllowedThrowable = options.methodNotAllowed(); // set whatever the user returns from their function
}
else {
notAllowedThrowable = new HttpError.MethodNotAllowed();
}
throw notAllowedThrowable;
}
else {
ctx.status = 405;
ctx.set('Allow', allowedMethods.join(', '));
}
}
}
};
}
/**
* Redirect `source` to `destination` URL with optional 30x status `code`.
*
* Both `source` and `destination` can be route names.
*
* ```javascript
* router.redirect('/login', 'sign-in');
* ```
*
* This is equivalent to:
*
* ```javascript
* router.all('/login', ctx => {
* ctx.redirect('/sign-in');
* ctx.status = 301;
* });
* ```
*
* @param {String} source URL or route name.
* @param {String} destination URL or route name.
* @param {Number=} status HTTP status code (default: 301).
* @return {Router} router instance
*/
redirect(source, destination, status = 301) {
// lookup source route by name
if (source[0] !== '/') {
const routeUrl = this.url(source);
if (routeUrl instanceof Error) {
throw routeUrl;
}
source = routeUrl;
}
// lookup destination route by name
if (destination[0] !== '/') {
const routeUrl = this.url(destination);
if (routeUrl instanceof Error) {
throw routeUrl;
}
destination = routeUrl;
}
return this.all(source, ctx => {
ctx.redirect(destination);
ctx.status = status;
});
}
/**
* Create and register a route.
*
* @param {String|RegExp|(String|RegExp)[]} path Path string.
* @param {String[]} methods Array of HTTP verbs.
* @param {Function|Function[]} middleware Multiple middleware also accepted.
* @param {Object} [opts] optional params
* @private
*/
register(path, methods, middleware, opts) {
// support array of paths
if (Array.isArray(path)) {
const routes = [];
for (const p of path) {
const route = this.#register(p, methods, middleware, opts);
routes.push(route);
}
return routes;
}
// create route
const route = this.#register(path, methods, middleware, opts);
return route;
}
#register(path, methods, middleware, opts) {
opts = opts ?? {};
// create route
const route = new Layer(path, methods, middleware, {
end: opts.end === false ? opts.end : true,
name: opts.name,
sensitive: opts.sensitive ?? this.opts.sensitive ?? false,
strict: opts.strict ?? this.opts.strict ?? false,
prefix: opts.prefix ?? this.opts.prefix ?? '',
ignoreCaptures: opts.ignoreCaptures,
});
// FIXME: why???
if (this.opts.prefix) {
route.setPrefix(this.opts.prefix);
}
// add parameter middleware to the new route layer
for (const param in this.params) {
route.param(param, this.params[param]);
}
this.stack.push(route);
return route;
}
/**
* Lookup route with given `name`.
*
* @param {String} name route name
* @return {Layer|false} layer instance of false
*/
route(name) {
for (const route of this.stack) {
if (route.name === name) {
return route;
}
}
return false;
}
/**
* Generate URL for route. Takes a route name and map of named `params`.
*
* @example
*
* ```javascript
* router.get('user', '/users/:id', (ctx, next) => {
* // ...
* });
*
* router.url('user', 3);
* // => "/users/3"
*
* router.url('user', { id: 3 });
* // => "/users/3"
*
* router.use((ctx, next) => {
* // redirect to named route
* ctx.redirect(ctx.router.url('sign-in'));
* })
*
* router.url('user', { id: 3 }, { query: { limit: 1 } });
* // => "/users/3?limit=1"
*
* router.url('user', { id: 3 }, { query: "limit=1" });
* // => "/users/3?limit=1"
* ```
*/
url(name, params, ...paramsOrOptions) {
const route = this.route(name);
if (route) {
return route.url(params, ...paramsOrOptions);
}
return new Error(`No route found for name: ${name}`);
}
/**
* Generate URL from url pattern and given `params`.
*
* @example
*
* ```javascript
* var url = Router.url('/users/:id', { id: 1 });
* // => "/users/1"
* ```
*
* @param {String} path url pattern
* @param {Object} params url parameters
* @return {String} url string
*/
static url(path, params, ...paramsOrOptions) {
return Layer.prototype.url.call({ path }, params, ...paramsOrOptions);
}
/**
* Match given `path` and return corresponding routes.
*
* @param {String} path path string
* @param {String} method method name
* @return {Object.<path, pathAndMethod>} returns layers that matched path and
* path and method.
* @private
*/
match(path, method) {
const matched = {
// matched path
path: [],
// matched path and method(including none method)
pathAndMethod: [],
// method matched or not
route: false,
};
for (const layer of this.stack) {
debug('test %s %s', layer.path, layer.regexp);
if (layer.match(path)) {
matched.path.push(layer);
if (layer.methods.length === 0 || layer.methods.includes(method)) {
matched.pathAndMethod.push(layer);
if (layer.methods.length > 0) {
matched.route = true;
}
}
// if (layer.methods.length === 0) {
// matched.pathAndMethod.push(layer);
// } else if (layer.methods.includes(method)) {
// matched.pathAndMethod.push(layer);
// matched.route = true;
// }
}
}
return matched;
}
/**
* Run middleware for named route parameters. Useful for auto-loading or
* validation.
*
* @example
*
* ```javascript
* router
* .param('user', (id, ctx, next) => {
* ctx.user = users[id];
* if (!ctx.user) return ctx.status = 404;
* return next();
* })
* .get('/users/:user', ctx => {
* ctx.body = ctx.user;
* })
* .get('/users/:user/friends', ctx => {
* return ctx.user.getFriends().then(function(friends) {
* ctx.body = friends;
* });
* })
* // /users/3 => {"id": 3, "name": "Alex"}
* // /users/3/friends => [{"id": 4, "name": "TJ"}]
* ```
*
* @param {String} param param
* @param {Function} middleware route middleware
* @return {Router} instance
*/
param(param, middleware) {
this.params[param] = middleware;
for (const route of this.stack) {
route.param(param, middleware);
}
return this;
}
_formatRouteParams(nameOrPath, pathOrMiddleware, middlewares) {
const options = {};
let path;
if (typeof nameOrPath === 'string' && nameOrPath.startsWith('/')) {
// verb(method, path, ...middlewares)
path = nameOrPath;
middlewares = [pathOrMiddleware, ...middlewares];
if (typeof pathOrMiddleware === 'string') {
// verb(method, path, controllerString)
// set controller name to router name
options.name = pathOrMiddleware;
}
}
else if (nameOrPath instanceof RegExp) {
// verb(method, pathRegex, ...middlewares)
path = nameOrPath;
middlewares = [pathOrMiddleware, ...middlewares];
if (typeof pathOrMiddleware === 'string') {
// verb(method, pathRegex, controllerString)
// set controller name to router name
options.name = pathOrMiddleware;
}
}
else if (Array.isArray(nameOrPath)) {
// verb(method, paths, ...middlewares)
path = nameOrPath;
middlewares = [pathOrMiddleware, ...middlewares];
if (typeof pathOrMiddleware === 'string') {
// verb(method, pathRegex, controllerString)
// set controller name to router name
options.name = pathOrMiddleware;
}
}
else if (typeof pathOrMiddleware === 'string' || pathOrMiddleware instanceof RegExp) {
// verb(method, name, path, ...middlewares)
path = pathOrMiddleware;
assert(typeof nameOrPath === 'string', 'route name should be string');
options.name = nameOrPath;
}
else if (Array.isArray(pathOrMiddleware)) {
// verb(method, name, paths, ...middlewares)
path = pathOrMiddleware;
assert(typeof nameOrPath === 'string', 'route name should be string');
options.name = nameOrPath;
}
else {
// verb(method, path, ...middlewares)
path = nameOrPath;
middlewares = [pathOrMiddleware, ...middlewares];
}
return {
path,
middlewares,
options,
};
}
/**
* Create `router.verb()` methods, where *verb* is one of the HTTP verbs such
* as `router.get()` or `router.post()`.
*
* Match URL patterns to callback functions or controller actions using `router.verb()`,
* where **verb** is one of the HTTP verbs such as `router.get()` or `router.post()`.
*
* Additionally, `router.all()` can be used to match against all methods.
*
* ```javascript
* router
* .get('/', (ctx, next) => {
* ctx.body = 'Hello World!';
* })
* .post('/users', (ctx, next) => {
* // ...
* })
* .put('/users/:id', (ctx, next) => {
* // ...
* })
* .del('/users/:id', (ctx, next) => {
* // ...
* })
* .all('/users/:id', (ctx, next) => {
* // ...
* });
* ```
*
* When a route is matched, its path is available at `ctx._matchedRoute` and if named,
* the name is available at `ctx._matchedRouteName`
*
* Route paths will be translated to regular expressions using
* [path-to-regexp](https://github.com/pillarjs/path-to-regexp).
*
* Query strings will not be considered when matching requests.
*
* #### Named routes
*
* Routes can optionally have names. This allows generation of URLs and easy
* renaming of URLs during development.
*
* ```javascript
* router.get('user', '/users/:id', (ctx, next) => {
* // ...
* });
*
* router.url('user', 3);
* // => "/users/3"
* ```
*
* #### Multiple middleware
*
* Multiple middleware may be given:
*
* ```javascript
* router.get(
* '/users/:id',
* (ctx, next) => {
* return User.findOne(ctx.params.id).then(function(user) {
* ctx.user = user;
* next();
* });
* },
* ctx => {
* console.log(ctx.user);
* // => { id: 17, name: "Alex" }
* }
* );
* ```
*
* ### Nested routers
*
* Nesting routers is supported:
*
* ```javascript
* var forums = new Router();
* var posts = new Router();
*
* posts.get('/', (ctx, next) => {...});
* posts.get('/:pid', (ctx, next) => {...});
* forums.use('/forums/:fid/posts', posts.routes(), posts.allowedMethods());
*
* // responds to "/forums/123/posts" and "/forums/123/posts/123"
* app.use(forums.routes());
* ```
*
* #### Router prefixes
*
* Route paths can be prefixed at the router level:
*
* ```javascript
* var router = new Router({
* prefix: '/users'
* });
*
* router.get('/', ...); // responds to "/users"
* router.get('/:id', ...); // responds to "/users/:id"
* ```
*
* #### URL parameters
*
* Named route parameters are captured and added to `ctx.params`.
*
* ```javascript
* router.get('/:category/:title', (ctx, next) => {
* console.log(ctx.params);
* // => { category: 'programming', title: 'how-to-node' }
* });
* ```
*
* The [path-to-regexp](https://github.com/pillarjs/path-to-regexp) module is
* used to convert paths to regular expressions.
*
*/
verb(method, nameOrPath, pathOrMiddleware, ...middleware) {
const { options, path, middlewares } = this._formatRouteParams(nameOrPath, pathOrMiddleware, middleware);
if (typeof method === 'string') {
method = [method];
}
this.register(path, method, middlewares, options);
return this;
}
all(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb(methods, nameOrPath, pathOrMiddleware, ...middlewares);
}
acl(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('acl', nameOrPath, pathOrMiddleware, ...middlewares);
}
bind(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('bind', nameOrPath, pathOrMiddleware, ...middlewares);
}
checkout(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('checkout', nameOrPath, pathOrMiddleware, ...middlewares);
}
connect(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('connect', nameOrPath, pathOrMiddleware, ...middlewares);
}
copy(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('copy', nameOrPath, pathOrMiddleware, ...middlewares);
}
delete(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('delete', nameOrPath, pathOrMiddleware, ...middlewares);
}
del(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('delete', nameOrPath, pathOrMiddleware, ...middlewares);
}
get(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('get', nameOrPath, pathOrMiddleware, ...middlewares);
}
query(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('query', nameOrPath, pathOrMiddleware, ...middlewares);
}
head(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('head', nameOrPath, pathOrMiddleware, ...middlewares);
}
link(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('link', nameOrPath, pathOrMiddleware, ...middlewares);
}
lock(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('lock', nameOrPath, pathOrMiddleware, ...middlewares);
}
['m-search'](nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('m-search', nameOrPath, pathOrMiddleware, ...middlewares);
}
merge(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('merge', nameOrPath, pathOrMiddleware, ...middlewares);
}
mkactivity(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('mkactivity', nameOrPath, pathOrMiddleware, ...middlewares);
}
mkcalendar(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('mkcalendar', nameOrPath, pathOrMiddleware, ...middlewares);
}
mkcol(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('mkcol', nameOrPath, pathOrMiddleware, ...middlewares);
}
move(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('move', nameOrPath, pathOrMiddleware, ...middlewares);
}
notify(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('notify', nameOrPath, pathOrMiddleware, ...middlewares);
}
options(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('options', nameOrPath, pathOrMiddleware, ...middlewares);
}
patch(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('patch', nameOrPath, pathOrMiddleware, ...middlewares);
}
post(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('post', nameOrPath, pathOrMiddleware, ...middlewares);
}
propfind(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('propfind', nameOrPath, pathOrMiddleware, ...middlewares);
}
proppatch(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('proppatch', nameOrPath, pathOrMiddleware, ...middlewares);
}
purge(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('purge', nameOrPath, pathOrMiddleware, ...middlewares);
}
put(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('put', nameOrPath, pathOrMiddleware, ...middlewares);
}
rebind(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('rebind', nameOrPath, pathOrMiddleware, ...middlewares);
}
report(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('report', nameOrPath, pathOrMiddleware, ...middlewares);
}
search(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('search', nameOrPath, pathOrMiddleware, ...middlewares);
}
source(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('source', nameOrPath, pathOrMiddleware, ...middlewares);
}
subscribe(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('subscribe', nameOrPath, pathOrMiddleware, ...middlewares);
}
trace(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('trace', nameOrPath, pathOrMiddleware, ...middlewares);
}
unbind(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('unbind', nameOrPath, pathOrMiddleware, ...middlewares);
}
unlink(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('unlink', nameOrPath, pathOrMiddleware, ...middlewares);
}
unlock(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('unlock', nameOrPath, pathOrMiddleware, ...middlewares);
}
unsubscribe(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('unsubscribe', nameOrPath, pathOrMiddleware, ...middlewares);
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUm91dGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL1JvdXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUVILE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDckMsT0FBTyxNQUFNLE1BQU0sYUFBYSxDQUFDO0FBQ2pDLE9BQU8sT0FBTyxNQUFNLGFBQWEsQ0FBQztBQUNsQyxPQUFPLFNBQVMsTUFBTSxhQUFhLENBQUM7QUFDcEMsT0FBTyxPQUFPLE1BQU0sU0FBUyxDQUFDO0FBQzlCLE9BQU8sRUFBRSxLQUFLLEVBQW1CLE1BQU0sWUFBWSxDQUFDO0FBR3BELE1BQU0sS0FBSyxHQUFHLFFBQVEsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO0FBb0MvQyxNQUFNLE9BQU8sTUFBTTtJQUNSLElBQUksQ0FBZ0I7SUFDcEIsT0FBTyxDQUFXO0lBQzNCLGtCQUFrQjtJQUNULEtBQUssR0FBWSxFQUFFLENBQUM7SUFDcEIsTUFBTSxHQUF3QyxFQUFFLENBQUM7SUFFMUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztPQTJCRztJQUNILFlBQVksSUFBb0I7UUFDOUIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLElBQUk7WUFDbEMsTUFBTTtZQUNOLFNBQVM7WUFDVCxLQUFLO1lBQ0wsS0FBSztZQUNMLE9BQU87WUFDUCxNQUFNO1lBQ04sUUFBUTtTQUNULENBQUM7SUFDSixDQUFDO0lBZ0NELEdBQUcsQ0FBQyxnQkFBb0QsRUFBRSxHQUFHLFdBQTZCO1FBQ3hGLHlCQUF5QjtRQUN6Qiw2QkFBNkI7UUFDN0IsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLElBQUksT0FBTyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUMv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