egg
Version:
A web application framework for Node.js
243 lines (242 loc) • 5.85 kB
JavaScript
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 };