UNPKG

egg

Version:

A web application framework for Node.js

243 lines (242 loc) • 5.85 kB
import { Context as Context$1, utils } from "@eggjs/core"; import { assign } from "utility"; import { diff, now } from "performance-ms"; //#region src/app/extend/context.ts const HELPER = Symbol("ctx helper"); const LOCALS = Symbol("ctx locals"); const LOCALS_LIST = Symbol("ctx localsList"); const COOKIES = Symbol("ctx cookies"); const CONTEXT_HTTPCLIENT = Symbol("ctx httpclient"); const CONTEXT_ROUTER = Symbol("ctx router"); var Context = class extends Context$1 { /** * Request start time * @member {Number} Context#starttime */ starttime; /** * Request start timer using `performance.now()` * @member {Number} Context#performanceStarttime */ performanceStarttime; /** * Get the current visitor's cookies. */ get cookies() { let cookies = this[COOKIES]; if (!cookies) this[COOKIES] = cookies = new this.app.ContextCookies(this, this.app.keys, this.app.config.cookies); return cookies; } /** * Get a wrapper httpclient instance contain ctx in the hold request process * * @return {HttpClient} the wrapper httpclient instance */ get httpclient() { if (!this[CONTEXT_HTTPCLIENT]) this[CONTEXT_HTTPCLIENT] = new this.app.ContextHttpClient(this); return this[CONTEXT_HTTPCLIENT]; } /** * Alias to {@link Context#httpclient} */ get httpClient() { return this.httpclient; } /** * Shortcut for httpclient.curl * * @function Context#curl * @param {String|Object} url - request url address. * @param {Object} [options] - options for request. * @return {Object} see {@link ContextHttpClient#curl} */ async curl(url, options) { return await this.httpclient.curl(url, options); } /** * Alias to {@link Application#router} * * @member {Router} Context#router * @since 1.0.0 * @example * ```js * this.router.pathFor('post', { id: 12 }); * ``` */ get router() { if (this[CONTEXT_ROUTER]) return this[CONTEXT_ROUTER]; return this.app.router; } /** * Set router to Context, only use on EggRouter * @param {Router} val router instance */ set router(val) { this[CONTEXT_ROUTER] = val; } /** * Get helper instance from {@link Application#Helper} * * @member {Helper} Context#helper * @since 1.0.0 */ get helper() { if (!this[HELPER]) this[HELPER] = new this.app.Helper(this); return this[HELPER]; } /** * Wrap app.loggers with context information, * if a custom logger is defined by naming aLogger, then you can `ctx.getLogger('aLogger')` * * @param {String} name - logger name */ getLogger(name) { return this.app.getLogger(name); } /** * Logger for Application * * @member {Logger} Context#logger * @since 1.0.0 * @example * ```js * this.logger.info('some request data: %j', this.request.body); * this.logger.warn('WARNING!!!!'); * ``` */ get logger() { return this.getLogger("logger"); } /** * Logger for frameworks and plugins * * @member {Logger} Context#coreLogger * @since 1.0.0 */ get coreLogger() { return this.getLogger("coreLogger"); } /** * locals is an object for view, you can use `app.locals` and `ctx.locals` to set variables, * which will be used as data when view is rendering. * The difference between `app.locals` and `ctx.locals` is the context level, `app.locals` is global level, and `ctx.locals` is request level. when you get `ctx.locals`, it will merge `app.locals`. * * when you set locals, only object is available * * ```js * this.locals = { * a: 1 * }; * this.locals = { * b: 1 * }; * this.locals.c = 1; * console.log(this.locals); * { * a: 1, * b: 1, * c: 1, * }; * ``` * * `ctx.locals` has cache, it only merges `app.locals` once in one request. * * @member {Object} Context#locals */ get locals() { if (!this[LOCALS]) this[LOCALS] = assign({}, this.app.locals); if (Array.isArray(this[LOCALS_LIST]) && this[LOCALS_LIST].length > 0) { assign(this[LOCALS], this[LOCALS_LIST]); this[LOCALS_LIST] = null; } return this[LOCALS]; } set locals(val) { const localsList = this[LOCALS_LIST] ?? []; localsList.push(val); this[LOCALS_LIST] = localsList; } /** * alias to {@link Context#locals}, compatible with koa that use this variable * @member {Object} state * @see Context#locals */ get state() { return this.locals; } set state(val) { this.locals = val; } /** * Run async function in the background * @param {Function} scope - the first args is ctx * ```js * this.body = 'hi'; * * this.runInBackground(async ctx => { * await ctx.mysql.query(sql); * await ctx.curl(url); * }); * ``` */ runInBackground(scope, taskName) { if (!taskName) taskName = Reflect.get(scope, "_name") || scope.name || utils.getCalleeFromStack(true); setImmediate(() => { this._runInBackground(scope, taskName); }); } async _runInBackground(scope, taskName) { const startTime = now(); try { await scope(this); this.coreLogger.info("[egg:background] task:%s success (%dms)", taskName, diff(startTime)); } catch (err) { this.coreLogger.info("[egg:background] task:%s fail (%dms)", taskName, diff(startTime)); err.runInBackground = true; this.app.emit("error", err, this); } } /** * @member {Boolean} Context#acceptJSON * @see Request#acceptJSON * @since 1.0.0 */ get acceptJSON() { return this.request.acceptJSON; } get query() { return this.request.query; } /** * @member {Array} Context#queries * @see Request#queries * @since 1.0.0 */ get queries() { return this.request.queries; } /** * @member {string} Context#ip * @see Request#ip * @since 1.0.0 */ get ip() { return this.request.ip; } set ip(val) { this.request.ip = val; } /** * @member {Number} Context#realStatus * @see Response#realStatus * @since 1.0.0 */ get realStatus() { return this.response.realStatus; } set realStatus(val) { this.response.realStatus = val; } }; //#endregion export { Context as default };