UNPKG

egg

Version:

A web framework's framework for Node.js

795 lines (692 loc) 18.6 kB
import * as accepts from 'accepts'; import * as KoaApplication from 'koa'; import * as KoaRouter from 'koa-router'; import { Readable } from 'stream'; /** * BaseContextClass is a base class that can be extended, * it's instantiated in context level, * {@link Helper}, {@link Service} is extending it. */ declare class BaseContextClass { // tslint:disable-line /** * request context */ ctx: Context; /** * Application */ app: Application; /** * Application config object */ config: EggAppConfig; /** * service */ service: IService; constructor(ctx: Context); } export interface Logger { info(info: string, ...args: string[]): void; warn(info: string, ...args: string[]): void; debug(info: string, ...args: string[]): void; error(info: string, ...args: string[]): void; } interface Request extends KoaApplication.Request { // tslint:disable-line /** * detect if response should be json * 1. url path ends with `.json` * 2. response type is set to json * 3. detect by request accept header * * @member {Boolean} Request#acceptJSON * @since 1.0.0 */ acceptJSON: boolean; /** * Request remote IPv4 address * @member {String} Request#ip * @example * ```js * this.request.ip * => '127.0.0.1' * => '111.10.2.1' * ``` */ ip: string; /** * Get all pass through ip addresses from the request. * Enable only on `app.config.proxy = true` * * @member {Array} Request#ips * @example * ```js * this.request.ips * => ['100.23.1.2', '201.10.10.2'] * ``` */ ips: string[]; protocol: string; /** * get params pass by querystring, all value are Array type. {@link Request#query} * @member {Array} Request#queries * @example * ```js * GET http://127.0.0.1:7001?a=b&a=c&o[foo]=bar&b[]=1&b[]=2&e=val * this.queries * => * { * "a": ["b", "c"], * "o[foo]": ["bar"], * "b[]": ["1", "2"], * "e": ["val"] * } * ``` */ queries: { [key: string]: string[] }; /** * get params pass by querystring, all value are String type. * @member {Object} Request#query * @example * ```js * GET http://127.0.0.1:7001?name=Foo&age=20&age=21 * this.query * => { 'name': 'Foo', 'age': 20 } * * GET http://127.0.0.1:7001?a=b&a=c&o[foo]=bar&b[]=1&b[]=2&e=val * this.query * => * { * "a": "b", * "o[foo]": "bar", * "b[]": "1", * "e": "val" * } * ``` */ query: { [key: string]: string }; } interface Response extends KoaApplication.Response { // tslint:disable-line /** * read response real status code. * * e.g.: Using 302 status redirect to the global error page * instead of show current 500 status page. * And access log should save 500 not 302, * then the `realStatus` can help us find out the real status code. * @member {Number} Context#realStatus */ realStatus: number; } interface ContextView { // tslint:disable-line /** * Render a file by view engine * @param {String} name - the file path based on root * @param {Object} [locals] - data used by template * @param {Object} [options] - view options, you can use `options.viewEngine` to specify view engine * @return {Promise<String>} result - return a promise with a render result */ render(name: string, locals: any, options?: any): Promise<string>; /** * Render a template string by view engine * @param {String} tpl - template string * @param {Object} [locals] - data used by template * @param {Object} [options] - view options, you can use `options.viewEngine` to specify view engine * @return {Promise<String>} result - return a promise with a render result */ renderString(name: string, locals: any, options?: any): Promise<string>; } export type LoggerLevel = 'DEBUG' | 'INFO' | 'WARN' | 'ERROR' | 'NONE'; export interface EggAppConfig { workerStartTimeout: number; baseDir: string; /** * The option of `bodyParser` middleware * * @member Config#bodyParser * @property {Boolean} enable - enable bodyParser or not, default to true * @property {String | RegExp | Function | Array} ignore - won't parse request body when url path hit ignore pattern, can not set `ignore` when `match` presented * @property {String | RegExp | Function | Array} match - will parse request body only when url path hit match pattern * @property {String} encoding - body encoding config, default utf8 * @property {String} formLimit - form body size limit, default 100kb * @property {String} jsonLimit - json body size limit, default 100kb * @property {Boolean} strict - json body strict mode, if set strict value true, then only receive object and array json body * @property {Number} queryString.arrayLimit - from item array length limit, default 100 * @property {Number} queryString.depth - json value deep lenght, default 5 * @property {Number} queryString.parameterLimit - paramter number limit ,default 1000 */ bodyParser: { enable: boolean; encoding: string; formLimit: string; jsonLimit: string; strict: true; queryString: { arrayLimit: number; depth: number; parameterLimit: number; }; }; /** * logger options * @member Config#logger * @property {String} dir - directory of log files * @property {String} encoding - log file encloding, defaults to utf8 * @property {String} level - default log level, could be: DEBUG, INFO, WARN, ERROR or NONE, defaults to INFO in production * @property {String} consoleLevel - log level of stdout, defaults to INFO in local serverEnv, defaults to WARN in unittest, defaults to NONE elsewise * @property {Boolean} outputJSON - log as JSON or not, defaults to false * @property {Boolean} buffer - if enabled, flush logs to disk at a certain frequency to improve performance, defaults to true * @property {String} errorLogName - file name of errorLogger * @property {String} coreLogName - file name of coreLogger * @property {String} agentLogName - file name of agent worker log * @property {Object} coreLogger - custom config of coreLogger */ logger: { dir: string; encoding: string; env: string; level: LoggerLevel; consoleLevel: LoggerLevel; outputJSON: boolean; buffer: boolean; appLogName: string; coreLogName: string; agentLogName: string; errorLogName: string; coreLogger: any; }; httpclient: { keepAlive: boolean; freeSocketKeepAliveTimeout: number; timeout: number; maxSockets: number; maxFreeSockets: number; enableDNSCache: boolean; }; development: { /** * dirs needed watch, when files under these change, application will reload, use relative path */ watchDirs: string[]; /** * dirs don't need watch, including subdirectories, use relative path */ ignoreDirs: string[]; /** * don't wait all plugins ready, default is true. */ fastReady: boolean; }; /** * It will ignore special keys when dumpConfig */ dump: { ignore: Set<string>; }; /** * The environment of egg */ env: string; /** * The current HOME directory */ HOME: string; hostHeaders: string; /** * I18n options */ i18n: { /** * default value EN_US */ defaultLocale: string; /** * i18n resource file dir, not recommend to change default value */ dir: string; /** * custom the locale value field, default `query.locale`, you can modify this config, such as `query.lang` */ queryField: string; /** * The locale value key in the cookie, default is locale. */ cookieField: string; /** * Locale cookie expire time, default `1y`, If pass number value, the unit will be ms */ cookieMaxAge: string | number; }; /** * Detect request' ip from specified headers, not case-sensitive. Only worked when config.proxy set to true. */ ipHeaders: string; /** * jsonp options * @member Config#jsonp * @property {String} callback - jsonp callback method key, default to `_callback` * @property {Number} limit - callback method name's max length, default to `50` * @property {Boolean} csrf - enable csrf check or not. default to false * @property {String|RegExp|Array} whiteList - referrer white list */ jsonp: { limit: number; callback: string; csrf: boolean; whiteList: string | RegExp | Array<string | RegExp>; }; /** * The key that signing cookies. It can contain multiple keys seperated by . */ keys: string; /** * The name of the application */ name: string; /** * package.json */ pkg: any; rundir: string; security: { domainWhiteList: string[]; protocolWhiteList: string[]; defaultMiddleware: string; csrf: any; xframe: { enable: boolean; value: 'SAMEORIGIN' | 'DENY' | 'ALLOW-FROM'; }; hsts: any; methodnoallow: { enable: boolean }; noopen: { enable: boolean; } xssProtection: any; csp: any; }; siteFile: any; static: any; view: any; watcher: any; } export interface Router extends KoaRouter { /** * restful router api */ resources(name: string, prefix: string, middleware: any): Router; /** * @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: string, params: any): any; } declare interface EggApplication extends KoaApplication { // tslint:disable-line /** * The current directory of application */ baseDir: string; /** * The configuration of application */ config: EggAppConfig; /** * app.env delegate app.config.env */ env: string; /** * core logger for framework and plugins, log file is $HOME/logs/{appname}/egg-web */ coreLogger: Logger; /** * Alias to https://npmjs.com/package/depd */ deprecate: any; /** * HttpClient instance */ httpclient: any; /** * The loader instance, the default class is EggLoader. If you want define */ loader: any; /** * Logger for Application, wrapping app.coreLogger with context infomation * * @member {ContextLogger} Context#logger * @since 1.0.0 * @example * ```js * this.logger.info('some request data: %j', this.request.body); * this.logger.warn('WARNING!!!!'); * ``` */ logger: Logger; /** * All loggers contain logger, coreLogger and customLogger */ loggers: { [loggerName: string]: Logger }; /** * messenger instance */ messenger: any; plugins: any; /** * get router */ router: Router; Service: Service; /** * Whether `application` or `agent` */ type: string; /** * create a singleton instance */ addSingleton(name: string, create: any): void; /** * Excute scope after loaded and before app start */ beforeStart(scrope: () => void): void; /** * Close all, it wil close * - callbacks registered by beforeClose * - emit `close` event * - remove add listeners * * If error is thrown when it's closing, the promise will reject. * It will also reject after following call. * @return {Promise} promise * @since 1.0.0 */ close(): Promise<any>; /** * http request helper base on httpclient, it will auto save httpclient log. * Keep the same api with httpclient.request(url, args). * See https://github.com/node-modules/urllib#api-doc for more details. */ curl(url: string, opt: any): Promise<any>; /** * Get logger by name, it's equal to app.loggers['name'], but you can extend it with your own logical */ getLogger(name: string): Logger; /** * print the infomation when console.log(app) */ inspect(): any; /** * Alias to Router#url */ url(name: string, params: any): any; } export interface Application extends EggApplication { /** * global locals for view * @see Context#locals */ locals: any; /** * HTTP get method */ get(path: string, fn: string): void; get(path: string, ...middleware: any[]): void; /** * HTTP post method */ post(path: string, fn: string): void; post(path: string, ...middleware: any[]): void; /** * HTTP put method */ put(path: string, fn: string): void; put(path: string, ...middleware: any[]): void; /** * HTTP delete method */ delete(path: string, fn: string): void; delete(path: string, ...middleware: any[]): void; /** * restful router api */ resources(name: string, prefix: string, fn: string): Router; redirect(path: string, redirectPath: string): void; controller: IController; Controller: Controller; } interface FileStream extends Readable { // tslint:disable-line fields: any; filename: string; fieldname: string; mime: string; mimeType: string; transferEncoding: string; encoding: string; truncated: boolean; } export interface Context extends KoaApplication.Context { app: Application; service: IService; request: Request; response: Response; /** * Resource Parameters * @example * ##### ctx.params.id {string} * * `GET /api/users/1` => `'1'` * * ##### ctx.params.ids {Array<String>} * * `GET /api/users/1,2,3` => `['1', '2', '3']` * * ##### ctx.params.fields {Array<String>} * * Expect request return data fields, for example * `GET /api/users/1?fields=name,title` => `['name', 'title']`. * * ##### ctx.params.data {Object} * * Tht request data object * * ##### ctx.params.page {Number} * * Page number, `GET /api/users?page=10` => `10` * * ##### ctx.params.per_page {Number} * * The number of every page, `GET /api/users?per_page=20` => `20` */ params: any; /** * @see Request#accept */ queries: { [key: string]: string[] }; /** * @see Request#accept */ accept: accepts.Accepts; /** * @see Request#acceptJSON */ acceptJSON: boolean; /** * @see Request#ip */ ip: string; /** * @see Response#realStatus */ realStatus: number; /** * 设置返回资源对象 * set the ctx.body.data value * * @member {Object} Context#data= * @example * ```js * ctx.data = { * id: 1, * name: 'fengmk2' * }; * ``` * * will get responce * * ```js * HTTP/1.1 200 OK * * { * "data": { * "id": 1, * "name": "fengmk2" * } * } * ``` */ data: any; /** * set ctx.body.meta value * * @example * ```js * ctx.meta = { * count: 100 * }; * ``` * will get responce * * ```js * HTTP/1.1 200 OK * * { * "meta": { * "count": 100 * } * } * ``` */ meta: any; /** * 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 */ locals: any; /** * alias to {@link locals}, compatible with koa that use this variable */ state: any; /** * Logger for Application, wrapping app.coreLogger with context infomation * * @member {ContextLogger} Context#logger * @since 1.0.0 * @example * ```js * this.logger.info('some request data: %j', this.request.body); * this.logger.warn('WARNING!!!!'); * ``` */ logger: Logger; /** * Request start time */ starttime: number; /** * View instance that is created every request */ view: ContextView; /** * http request helper base on httpclient, it will auto save httpclient log. * Keep the same api with httpclient.request(url, args). * See https://github.com/node-modules/urllib#api-doc for more details. */ curl(url: string, opt: any): Promise<any>; /** * Render a file by view engine * @param {String} name - the file path based on root * @param {Object} [locals] - data used by template * @param {Object} [options] - view options, you can use `options.viewEngine` to specify view engine * @return {Promise<String>} result - return a promise with a render result */ render(name: string, locals: any, options?: any): Promise<string>; /** * Render a template string by view engine * @param {String} tpl - template string * @param {Object} [locals] - data used by template * @param {Object} [options] - view options, you can use `options.viewEngine` to specify view engine * @return {Promise<String>} result - return a promise with a render result */ renderString(name: string, locals: any, options?: any): Promise<string>; __(key: string, ...values: string[]): string; gettext(key: string, ...values: string[]): string; /** * get upload file stream * @example * ```js * const stream = yield this.getFileStream(); * // get other fields * console.log(stream.fields); * ``` * @method Context#getFileStream * @return {ReadStream} stream * @since 1.0.0 */ getFileStream(): Promise<FileStream>; /** * @see Responce.redirect */ redirect(url: string, alt?: string): void; } export class Controller extends BaseContextClass { } export class Service extends BaseContextClass { } /** * The empty interface `IService` is an placehoder, for egg * to auto injection service to ctx.service * * @example * * import { Service } from 'egg'; * class FooService extends Service { * async bar() {} * } * * declare module 'egg' { * export interface IService { * foo: FooService; * } * } * * Now I can get ctx.service.foo at controller and other service file. */ export interface IService { }// tslint:disable-line export interface IController { } // tslint:disable-line