@eggjs/router
Version:
Router middleware for egg/koa. Provides RESTful resource routing.
244 lines • 18.3 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.EggRouter = void 0;
const node_assert_1 = __importDefault(require("node:assert"));
const utility_1 = require("utility");
const inflection_1 = __importDefault(require("inflection"));
const methods_1 = __importDefault(require("methods"));
const is_type_of_1 = require("is-type-of");
const Router_js_1 = require("./Router.js");
const REST_MAP = {
index: {
suffix: '',
method: 'GET',
},
new: {
namePrefix: 'new_',
member: true,
suffix: 'new',
method: 'GET',
},
create: {
suffix: '',
method: 'POST',
},
show: {
member: true,
suffix: ':id',
method: 'GET',
},
edit: {
member: true,
namePrefix: 'edit_',
suffix: ':id/edit',
method: 'GET',
},
update: {
member: true,
namePrefix: '',
suffix: ':id',
method: ['PATCH', 'PUT'],
},
destroy: {
member: true,
namePrefix: 'destroy_',
suffix: ':id',
method: 'DELETE',
},
};
/**
* FIXME: move these patch into @eggjs/router
*/
class EggRouter extends Router_js_1.Router {
app;
/**
* @class
* @param {Object} opts - Router options.
* @param {Application} app - Application object.
*/
constructor(opts, app) {
super(opts);
this.app = app;
}
verb(method, nameOrPath, pathOrMiddleware, ...middleware) {
const { path, middlewares, options } = this._formatRouteParams(nameOrPath, pathOrMiddleware, middleware);
if (typeof method === 'string') {
method = [method];
}
this.register(path, method, middlewares, options);
return this;
}
head(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('head', nameOrPath, pathOrMiddleware, ...middlewares);
}
options(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('options', nameOrPath, pathOrMiddleware, ...middlewares);
}
get(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('get', nameOrPath, pathOrMiddleware, ...middlewares);
}
put(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('put', 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);
}
delete(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb('delete', nameOrPath, pathOrMiddleware, ...middlewares);
}
all(nameOrPath, pathOrMiddleware, ...middlewares) {
return this.verb(methods_1.default, nameOrPath, pathOrMiddleware, ...middlewares);
}
register(path, methods, middleware, opts) {
// patch register to support bind ctx function middleware and string controller
middleware = Array.isArray(middleware) ? middleware : [middleware];
for (const mw of middleware) {
if ((0, is_type_of_1.isGeneratorFunction)(mw)) {
throw new TypeError(methods.toString() + ' `' + path + '`: Please use async function instead of generator function');
}
}
const middlewares = convertMiddlewares(middleware, this.app);
return super.register(path, methods, middlewares, opts);
}
resources(nameOrPath, pathOrMiddleware, ...middleware) {
const { path, middlewares, options } = this._formatRouteParams(nameOrPath, pathOrMiddleware, middleware);
// last argument is Controller object
const controller = resolveController(middlewares.pop(), this.app);
for (const key in REST_MAP) {
const action = controller[key];
if (!action)
continue;
const opts = REST_MAP[key];
let routeName;
if (opts.member) {
routeName = inflection_1.default.singularize(options.name ?? '');
}
else {
routeName = inflection_1.default.pluralize(options.name ?? '');
}
if (opts.namePrefix) {
routeName = opts.namePrefix + routeName;
}
const prefix = path.replace(/\/$/, '');
const urlPath = opts.suffix ? `${prefix}/${opts.suffix}` : prefix;
const method = Array.isArray(opts.method) ? opts.method : [opts.method];
this.register(urlPath, method, middlewares.concat(action), { name: routeName });
}
return this;
}
/**
* @param {String} name - Router name
* @param {Object} params - more parameters
* @example
* ```js
* router.url('edit_post', { id: 1, name: 'foo', page: 2 })
* => /posts/1/edit?name=foo&page=2
* router.url('posts', { name: 'foo&1', page: 2 })
* => /posts?name=foo%261&page=2
* ```
* @return {String} url by path name and query params.
* @since 1.0.0
*/
url(name, params) {
const route = this.route(name);
if (!route)
return '';
const args = params;
let url = route.path;
(0, node_assert_1.default)(!(url instanceof RegExp), `Can't get the url for regExp ${url} for by name '${name}'`);
const queries = [];
if (typeof args === 'object' && args !== null) {
const replacedParams = [];
url = url.replace(/:([a-zA-Z_]\w*)/g, ($0, key) => {
if (key in args) {
const values = args[key];
replacedParams.push(key);
return (0, utility_1.encodeURIComponent)(Array.isArray(values) ? String(values[0]) : String(values));
}
return $0;
});
for (const key in args) {
if (replacedParams.includes(key)) {
continue;
}
const values = args[key];
const encodedKey = (0, utility_1.encodeURIComponent)(key);
if (Array.isArray(values)) {
for (const val of values) {
queries.push(`${encodedKey}=${(0, utility_1.encodeURIComponent)(String(val))}`);
}
}
else {
queries.push(`${encodedKey}=${(0, utility_1.encodeURIComponent)(String(values))}`);
}
}
}
if (queries.length > 0) {
const queryStr = queries.join('&');
if (!url.includes('?')) {
url = `${url}?${queryStr}`;
}
else {
url = `${url}&${queryStr}`;
}
}
return url;
}
/**
* @alias to url()
*/
pathFor(name, params) {
return this.url(name, params);
}
}
exports.EggRouter = EggRouter;
/**
* resolve controller from string to function
* @param {String|Function} controller input controller
* @param {Application} app egg application instance
*/
function resolveController(controller, app) {
if (typeof controller === 'string') {
// resolveController('foo.bar.Home', app)
const actions = controller.split('.');
let obj = app.controller;
actions.forEach(key => {
obj = obj[key];
if (!obj)
throw new Error(`app.controller.${controller} not exists`);
});
controller = obj;
}
// ensure controller is exists
if (!controller)
throw new Error('controller not exists');
return controller;
}
/**
* 1. ensure controller(last argument) support string
* - [url, controller]: app.get('/home', 'home');
* - [name, url, controller(string)]: app.get('posts', '/posts', 'posts.list');
* - [name, url, controller]: app.get('posts', '/posts', app.controller.posts.list);
* - [name, url(regexp), controller]: app.get('regRouter', /\/home\/index/, 'home.index');
* - [name, url, middleware, [...], controller]: `app.get(/user/:id', hasLogin, canGetUser, 'user.show');`
*
* 2. bind ctx to controller `this`
*
* @param {Array} middlewares middlewares and controller(last middleware)
* @param {Application} app egg application instance
*/
function convertMiddlewares(middlewares, app) {
// ensure controller is resolved
const controller = resolveController(middlewares.pop(), app);
function wrappedController(ctx, next) {
return controller.apply(ctx, [ctx, next]);
}
return [...middlewares, wrappedController];
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRWdnUm91dGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL0VnZ1JvdXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSw4REFBaUM7QUFDakMscUNBQXVFO0FBQ3ZFLDREQUFvQztBQUNwQyxzREFBOEI7QUFDOUIsMkNBQWlEO0FBQ2pELDJDQUFtRjtBQVVuRixNQUFNLFFBQVEsR0FBbUM7SUFDL0MsS0FBSyxFQUFFO1FBQ0wsTUFBTSxFQUFFLEVBQUU7UUFDVixNQUFNLEVBQUUsS0FBSztLQUNkO0lBQ0QsR0FBRyxFQUFFO1FBQ0gsVUFBVSxFQUFFLE1BQU07UUFDbEIsTUFBTSxFQUFFLElBQUk7UUFDWixNQUFNLEVBQUUsS0FBSztRQUNiLE1BQU0sRUFBRSxLQUFLO0tBQ2Q7SUFDRCxNQUFNLEVBQUU7UUFDTixNQUFNLEVBQUUsRUFBRTtRQUNWLE1BQU0sRUFBRSxNQUFNO0tBQ2Y7SUFDRCxJQUFJLEVBQUU7UUFDSixNQUFNLEVBQUUsSUFBSTtRQUNaLE1BQU0sRUFBRSxLQUFLO1FBQ2IsTUFBTSxFQUFFLEtBQUs7S0FDZDtJQUNELElBQUksRUFBRTtRQUNKLE1BQU0sRUFBRSxJQUFJO1FBQ1osVUFBVSxFQUFFLE9BQU87UUFDbkIsTUFBTSxFQUFFLFVBQVU7UUFDbEIsTUFBTSxFQUFFLEtBQUs7S0FDZDtJQUNELE1BQU0sRUFBRTtRQUNOLE1BQU0sRUFBRSxJQUFJO1FBQ1osVUFBVSxFQUFFLEVBQUU7UUFDZCxNQUFNLEVBQUUsS0FBSztRQUNiLE1BQU0sRUFBRSxDQUFFLE9BQU8sRUFBRSxLQUFLLENBQUU7S0FDM0I7SUFDRCxPQUFPLEVBQUU7UUFDUCxNQUFNLEVBQUUsSUFBSTtRQUNaLFVBQVUsRUFBRSxVQUFVO1FBQ3RCLE1BQU0sRUFBRSxLQUFLO1FBQ2IsTUFBTSxFQUFFLFFBQVE7S0FDakI7Q0FDRixDQUFDO0FBTUY7O0dBRUc7QUFDSCxNQUFhLFNBQVUsU0FBUSxrQkFBTTtJQUMxQixHQUFH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