UNPKG

30.9 kBTypeScriptView Raw
1/// <reference types="node" />
2import accepts = require('accepts');
3import KoaApplication = require('koa');
4import KoaRouter = require('koa-router');
5import { EventEmitter } from 'events'
6import { Readable } from 'stream';
7import { Socket } from 'net';
8import { IncomingMessage, ServerResponse } from 'http';
9import { EggLogger, EggLoggers, LoggerLevel as EggLoggerLevel, EggContextLogger } from 'egg-logger';
10import { HttpClient, RequestOptions2 as RequestOptions } from 'urllib';
11import {
12 EggCoreBase,
13 FileLoaderOption,
14 EggLoader as CoreLoader,
15 EggCoreOptions as CoreOptions,
16 EggLoaderOptions as CoreLoaderOptions,
17 BaseContextClass as CoreBaseContextClass,
18} from 'egg-core';
19import EggCookies = require('egg-cookies');
20import 'egg-onerror';
21import 'egg-session';
22import 'egg-i18n';
23import 'egg-watcher';
24import 'egg-multipart';
25import 'egg-security';
26import 'egg-development';
27import 'egg-logrotator';
28import 'egg-schedule';
29import 'egg-static';
30import 'egg-jsonp';
31import 'egg-view';
32
33declare module 'egg' {
34 // plain object
35 type PlainObject<T = any> = { [key: string]: T };
36
37 // Remove specific property from the specific class
38 type RemoveSpecProp<T, P> = Pick<T, Exclude<keyof T, P>>;
39
40 interface EggHttpClient extends HttpClient<RequestOptions> {}
41 interface EggHttpConstructor {
42 new (app: Application): EggHttpClient;
43 }
44
45 interface EggContextHttpClient extends HttpClient<RequestOptions> {}
46 interface EggContextHttpClientConstructor {
47 new (ctx: Context): EggContextHttpClient;
48 }
49
50 /**
51 * BaseContextClass is a base class that can be extended,
52 * it's instantiated in context level,
53 * {@link Helper}, {@link Service} is extending it.
54 */
55 export class BaseContextClass extends CoreBaseContextClass<Context, Application, EggAppConfig, IService> { // tslint:disable-line
56 /**
57 * logger
58 */
59 protected logger: EggLogger;
60 }
61
62 export class Boot {
63 /**
64 * logger
65 * @member {EggLogger}
66 */
67 protected logger: EggLogger;
68
69 /**
70 * The configuration of application
71 * @member {EggAppConfig}
72 */
73 protected config: EggAppConfig;
74
75 /**
76 * The instance of agent
77 * @member {Agent}
78 */
79 protected agent: Agent;
80
81 /**
82 * The instance of app
83 * @member {Application}
84 */
85 protected app: Application;
86 }
87
88 export type RequestArrayBody = any[];
89 export type RequestObjectBody = PlainObject;
90 export interface Request extends KoaApplication.Request { // tslint:disable-line
91 /**
92 * detect if response should be json
93 * 1. url path ends with `.json`
94 * 2. response type is set to json
95 * 3. detect by request accept header
96 *
97 * @member {Boolean} Request#acceptJSON
98 * @since 1.0.0
99 */
100 acceptJSON: boolean;
101
102 /**
103 * Request remote IPv4 address
104 * @member {String} Request#ip
105 * @example
106 * ```js
107 * this.request.ip
108 * => '127.0.0.1'
109 * => '111.10.2.1'
110 * ```
111 */
112 ip: string;
113
114 /**
115 * Get all pass through ip addresses from the request.
116 * Enable only on `app.config.proxy = true`
117 *
118 * @member {Array} Request#ips
119 * @example
120 * ```js
121 * this.request.ips
122 * => ['100.23.1.2', '201.10.10.2']
123 * ```
124 */
125 ips: string[];
126
127 protocol: string;
128
129 /**
130 * get params pass by querystring, all value are Array type. {@link Request#query}
131 * @member {Array} Request#queries
132 * @example
133 * ```js
134 * GET http://127.0.0.1:7001?a=b&a=c&o[foo]=bar&b[]=1&b[]=2&e=val
135 * this.queries
136 * =>
137 * {
138 * "a": ["b", "c"],
139 * "o[foo]": ["bar"],
140 * "b[]": ["1", "2"],
141 * "e": ["val"]
142 * }
143 * ```
144 */
145 queries: PlainObject<string[]>;
146
147 /**
148 * get params pass by querystring, all value are String type.
149 * @member {Object} Request#query
150 * @example
151 * ```js
152 * GET http://127.0.0.1:7001?name=Foo&age=20&age=21
153 * this.query
154 * => { 'name': 'Foo', 'age': 20 }
155 *
156 * GET http://127.0.0.1:7001?a=b&a=c&o[foo]=bar&b[]=1&b[]=2&e=val
157 * this.query
158 * =>
159 * {
160 * "a": "b",
161 * "o[foo]": "bar",
162 * "b[]": "1",
163 * "e": "val"
164 * }
165 * ```
166 */
167 query: PlainObject<string>;
168
169 body: any;
170 }
171
172 export interface Response extends KoaApplication.Response { // tslint:disable-line
173 /**
174 * read response real status code.
175 *
176 * e.g.: Using 302 status redirect to the global error page
177 * instead of show current 500 status page.
178 * And access log should save 500 not 302,
179 * then the `realStatus` can help us find out the real status code.
180 * @member {Number} Context#realStatus
181 */
182 realStatus: number;
183 }
184
185 export type LoggerLevel = EggLoggerLevel;
186
187 /**
188 * egg app info
189 * @example
190 * ```js
191 * // config/config.default.ts
192 * import { EggAppInfo } from 'egg';
193 *
194 * export default (appInfo: EggAppInfo) => {
195 * return {
196 * keys: appInfo.name + '123456',
197 * };
198 * }
199 * ```
200 */
201 export interface EggAppInfo {
202 pkg: any; // package.json
203 name: string; // the application name from package.json
204 baseDir: string; // current directory of application
205 env: EggEnvType; // equals to serverEnv
206 HOME: string; // home directory of the OS
207 root: string; // baseDir when local and unittest, HOME when other environment
208 }
209
210 type IgnoreItem = string | RegExp | ((ctx: Context) => boolean);
211 type IgnoreOrMatch = IgnoreItem | IgnoreItem[];
212
213 /** Custom Loader Configuration */
214 export interface CustomLoaderConfig extends RemoveSpecProp<FileLoaderOption, 'inject' | 'target'> {
215 /**
216 * an object you wanner load to, value can only be 'ctx' or 'app'. default to app
217 */
218 inject?: 'ctx' | 'app';
219 /**
220 * whether need to load files in plugins or framework, default to false
221 */
222 loadunit?: boolean;
223 }
224
225 export interface EggAppConfig {
226 workerStartTimeout: number;
227 baseDir: string;
228 middleware: string[];
229
230 /**
231 * The option of `bodyParser` middleware
232 *
233 * @member Config#bodyParser
234 * @property {Boolean} enable - enable bodyParser or not, default to true
235 * @property {String | RegExp | Function | Array} ignore - won't parse request body when url path hit ignore pattern, can not set `ignore` when `match` presented
236 * @property {String | RegExp | Function | Array} match - will parse request body only when url path hit match pattern
237 * @property {String} encoding - body encoding config, default utf8
238 * @property {String} formLimit - form body size limit, default 100kb
239 * @property {String} jsonLimit - json body size limit, default 100kb
240 * @property {Boolean} strict - json body strict mode, if set strict value true, then only receive object and array json body
241 * @property {Number} queryString.arrayLimit - from item array length limit, default 100
242 * @property {Number} queryString.depth - json value deep lenght, default 5
243 * @property {Number} queryString.parameterLimit - paramter number limit ,default 1000
244 * @property {string[]} enableTypes - parser will only parse when request type hits enableTypes, default is ['json', 'form']
245 * @property {any} extendTypes - support extend types
246 */
247 bodyParser: {
248 enable: boolean;
249 encoding: string;
250 formLimit: string;
251 jsonLimit: string;
252 strict: boolean;
253 queryString: {
254 arrayLimit: number;
255 depth: number;
256 parameterLimit: number;
257 };
258 ignore: IgnoreOrMatch;
259 match: IgnoreOrMatch;
260 enableTypes: string[];
261 extendTypes: {
262 json: string[];
263 form: string[];
264 text: string[];
265 };
266 };
267
268 /**
269 * logger options
270 * @member Config#logger
271 * @property {String} dir - directory of log files
272 * @property {String} encoding - log file encloding, defaults to utf8
273 * @property {String} level - default log level, could be: DEBUG, INFO, WARN, ERROR or NONE, defaults to INFO in production
274 * @property {String} consoleLevel - log level of stdout, defaults to INFO in local serverEnv, defaults to WARN in unittest, defaults to NONE elsewise
275 * @property {Boolean} disableConsoleAfterReady - disable logger console after app ready. defaults to `false` on local and unittest env, others is `true`.
276 * @property {Boolean} outputJSON - log as JSON or not, defaults to false
277 * @property {Boolean} buffer - if enabled, flush logs to disk at a certain frequency to improve performance, defaults to true
278 * @property {String} errorLogName - file name of errorLogger
279 * @property {String} coreLogName - file name of coreLogger
280 * @property {String} agentLogName - file name of agent worker log
281 * @property {Object} coreLogger - custom config of coreLogger
282 * @property {Boolean} allowDebugAtProd - allow debug log at prod, defaults to true
283 */
284 logger: {
285 dir: string;
286 encoding: string;
287 env: EggEnvType;
288 level: LoggerLevel;
289 consoleLevel: LoggerLevel;
290 disableConsoleAfterReady: boolean;
291 outputJSON: boolean;
292 buffer: boolean;
293 appLogName: string;
294 coreLogName: string;
295 agentLogName: string;
296 errorLogName: string;
297 coreLogger: any;
298 allowDebugAtProd: boolean;
299 };
300
301 httpclient: {
302 keepAlive: boolean;
303 freeSocketKeepAliveTimeout?: number;
304 freeSocketTimeout: number;
305 timeout: number;
306 maxSockets: number;
307 maxFreeSockets: number;
308 enableDNSCache: boolean;
309 };
310
311 development: {
312 /**
313 * dirs needed watch, when files under these change, application will reload, use relative path
314 */
315 watchDirs: string[];
316 /**
317 * dirs don't need watch, including subdirectories, use relative path
318 */
319 ignoreDirs: string[];
320 /**
321 * don't wait all plugins ready, default is true.
322 */
323 fastReady: boolean;
324 /**
325 * whether reload on debug, default is true.
326 */
327 reloadOnDebug: boolean;
328 /**
329 * whether override default watchDirs, default is false.
330 */
331 overrideDefault: boolean;
332 /**
333 * whether to reload, use https://github.com/sindresorhus/multimatch
334 */
335 reloadPattern: string[] | string;
336 };
337
338 /**
339 * customLoader config
340 */
341 customLoader: {
342 [key: string]: CustomLoaderConfig;
343 };
344
345 /**
346 * It will ignore special keys when dumpConfig
347 */
348 dump: {
349 ignore: Set<string>;
350 };
351
352 /**
353 * The environment of egg
354 */
355 env: EggEnvType;
356
357 /**
358 * The current HOME directory
359 */
360 HOME: string;
361
362 hostHeaders: string;
363
364 /**
365 * I18n options
366 */
367 i18n: {
368 /**
369 * default value EN_US
370 */
371 defaultLocale: string;
372 /**
373 * i18n resource file dir, not recommend to change default value
374 */
375 dir: string;
376 /**
377 * custom the locale value field, default `query.locale`, you can modify this config, such as `query.lang`
378 */
379 queryField: string;
380 /**
381 * The locale value key in the cookie, default is locale.
382 */
383 cookieField: string;
384 /**
385 * Locale cookie expire time, default `1y`, If pass number value, the unit will be ms
386 */
387 cookieMaxAge: string | number;
388 };
389
390 /**
391 * Detect request' ip from specified headers, not case-sensitive. Only worked when config.proxy set to true.
392 */
393 ipHeaders: string;
394
395 /**
396 * jsonp options
397 * @member Config#jsonp
398 * @property {String} callback - jsonp callback method key, default to `_callback`
399 * @property {Number} limit - callback method name's max length, default to `50`
400 * @property {Boolean} csrf - enable csrf check or not. default to false
401 * @property {String|RegExp|Array} whiteList - referrer white list
402 */
403 jsonp: {
404 limit: number;
405 callback: string;
406 csrf: boolean;
407 whiteList: string | RegExp | Array<string | RegExp>;
408 };
409
410 /**
411 * The key that signing cookies. It can contain multiple keys seperated by .
412 */
413 keys: string;
414
415 /**
416 * The name of the application
417 */
418 name: string;
419
420 /**
421 * package.json
422 */
423 pkg: any;
424
425 rundir: string;
426
427 security: {
428 domainWhiteList: string[];
429 protocolWhiteList: string[];
430 defaultMiddleware: string;
431 csrf: any;
432 xframe: {
433 enable: boolean;
434 value: 'SAMEORIGIN' | 'DENY' | 'ALLOW-FROM';
435 };
436 hsts: any;
437 methodnoallow: { enable: boolean };
438 noopen: { enable: boolean; }
439 xssProtection: any;
440 csp: any;
441 };
442
443 siteFile: PlainObject<string | Buffer>;
444
445 static: {
446 prefix: string;
447 dir: string | string[];
448 // support lazy load
449 dynamic: boolean;
450 preload: boolean;
451 buffer: boolean;
452 maxFiles: number;
453 } & PlainObject;
454
455 watcher: PlainObject;
456
457 onClientError(err: Error, socket: Socket, app: EggApplication): ClientErrorResponse | Promise<ClientErrorResponse>;
458
459 /**
460 * server timeout in milliseconds, default to 2 minutes.
461 *
462 * for special request, just use `ctx.req.setTimeout(ms)`
463 *
464 * @see https://nodejs.org/api/http.html#http_server_timeout
465 */
466 serverTimeout: number | null;
467
468 [prop: string]: any;
469 }
470
471 export interface ClientErrorResponse {
472 body: string | Buffer;
473 status: number;
474 headers: { [key: string]: string };
475 }
476
477 export interface Router extends KoaRouter<any, Context> {
478 /**
479 * restful router api
480 */
481 resources(name: string, prefix: string, ...middleware: any[]): Router;
482
483 /**
484 * @param {String} name - Router name
485 * @param {Object} params - more parameters
486 * @example
487 * ```js
488 * router.url('edit_post', { id: 1, name: 'foo', page: 2 })
489 * => /posts/1/edit?name=foo&page=2
490 * router.url('posts', { name: 'foo&1', page: 2 })
491 * => /posts?name=foo%261&page=2
492 * ```
493 * @return {String} url by path name and query params.
494 * @since 1.0.0
495 */
496 url(name: string, params: any): any;
497 }
498
499 export interface EggApplication extends EggCoreBase<EggAppConfig> { // tslint:disable-line
500 /**
501 * HttpClient instance
502 */
503 httpclient: EggHttpClient;
504
505 /**
506 * Logger for Application, wrapping app.coreLogger with context infomation
507 *
508 * @member {ContextLogger} Context#logger
509 * @since 1.0.0
510 * @example
511 * ```js
512 * this.logger.info('some request data: %j', this.request.body);
513 * this.logger.warn('WARNING!!!!');
514 * ```
515 */
516 logger: EggLogger;
517
518 /**
519 * core logger for framework and plugins, log file is $HOME/logs/{appname}/egg-web
520 */
521 coreLogger: EggLogger;
522
523 /**
524 * All loggers contain logger, coreLogger and customLogger
525 */
526 loggers: EggLoggers;
527
528 /**
529 * messenger instance
530 */
531 messenger: Messenger;
532
533 /**
534 * get router
535 */
536 router: Router;
537
538 /**
539 * create a singleton instance
540 */
541 addSingleton(name: string, create: any): void;
542
543 runSchedule(schedulePath: string): Promise<any>;
544
545 /**
546 * http request helper base on httpclient, it will auto save httpclient log.
547 * Keep the same api with httpclient.request(url, args).
548 * See https://github.com/node-modules/urllib#api-doc for more details.
549 */
550 curl<T = any>(url: string, opt?: RequestOptions): Promise<T>;
551
552 /**
553 * Get logger by name, it's equal to app.loggers['name'], but you can extend it with your own logical
554 */
555 getLogger(name: string): EggLogger;
556
557 /**
558 * print the infomation when console.log(app)
559 */
560 inspect(): any;
561
562 /**
563 * Alias to Router#url
564 */
565 url(name: string, params: any): any;
566
567 /**
568 * Create an anonymous context, the context isn't request level, so the request is mocked.
569 * then you can use context level API like `ctx.service`
570 * @member {String} EggApplication#createAnonymousContext
571 * @param {Request} req - if you want to mock request like querystring, you can pass an object to this function.
572 * @return {Context} context
573 */
574 createAnonymousContext(req?: Request): Context;
575
576 /**
577 * export context base classes, let framework can impl sub class and over context extend easily.
578 */
579 ContextCookies: typeof EggCookies;
580 ContextLogger: typeof EggContextLogger;
581 ContextHttpClient: EggContextHttpClientConstructor;
582 HttpClient: EggHttpConstructor;
583 Subscription: typeof Subscription;
584 Controller: typeof Controller;
585 Service: typeof Service;
586 }
587
588 // compatible
589 export class EggApplication {
590 constructor(options?: CoreOptions);
591 }
592
593 export type RouterPath = string | RegExp;
594
595 export class Application extends EggApplication {
596 /**
597 * global locals for view
598 * @see Context#locals
599 */
600 locals: IApplicationLocals;
601
602 /**
603 * HTTP get method
604 */
605 get(path: RouterPath, fn: string): void;
606 get(path: RouterPath, ...middleware: any[]): void;
607
608 /**
609 * HTTP post method
610 */
611 post(path: RouterPath, fn: string): void;
612 post(path: RouterPath, ...middleware: any[]): void;
613
614 /**
615 * HTTP put method
616 */
617 put(path: RouterPath, fn: string): void;
618 put(path: RouterPath, ...middleware: any[]): void;
619
620 /**
621 * HTTP delete method
622 */
623 delete(path: RouterPath, fn: string): void;
624 delete(path: RouterPath, ...middleware: any[]): void;
625
626 /**
627 * restful router api
628 */
629 resources(name: string, prefix: string, fn: string): Router;
630 resources(path: string, prefix: string, ...middleware: any[]): Router;
631
632 redirect(path: string, redirectPath: string): void;
633
634 controller: IController;
635
636 middleware: KoaApplication.Middleware[] & IMiddleware;
637
638 /**
639 * Run async function in the background
640 * @see Context#runInBackground
641 * @param {Function} scope - the first args is an anonymous ctx
642 */
643 runInBackground(scope: (ctx: Context) => void): void;
644 }
645
646 export interface IApplicationLocals extends PlainObject { }
647
648 export interface FileStream extends Readable { // tslint:disable-line
649 fields: any;
650
651 filename: string;
652
653 fieldname: string;
654
655 mime: string;
656
657 mimeType: string;
658
659 transferEncoding: string;
660
661 encoding: string;
662
663 truncated: boolean;
664 }
665
666 interface GetFileStreamOptions {
667 requireFile?: boolean; // required file submit, default is true
668 defCharset?: string;
669 limits?: {
670 fieldNameSize?: number;
671 fieldSize?: number;
672 fields?: number;
673 fileSize?: number;
674 files?: number;
675 parts?: number;
676 headerPairs?: number;
677 };
678 checkFile?(
679 fieldname: string,
680 file: any,
681 filename: string,
682 encoding: string,
683 mimetype: string
684 ): void | Error;
685 }
686
687 /**
688 * KoaApplication's Context will carry the default 'cookie' property in
689 * the egg's Context interface, which is wrong here because we have our own
690 * special properties (e.g: encrypted). So we must remove this property and
691 * create our own with the same name.
692 * @see https://github.com/eggjs/egg/pull/2958
693 *
694 * However, the latest version of Koa has "[key: string]: any" on the
695 * context, and there'll be a type error for "keyof koa.Context".
696 * So we have to directly inherit from "KoaApplication.BaseContext" and
697 * rewrite all the properties to be compatible with types in Koa.
698 * @see https://github.com/eggjs/egg/pull/3329
699 */
700 export interface Context extends KoaApplication.BaseContext {
701 [key: string]: any;
702
703 app: Application;
704
705 // properties of koa.Context
706 req: IncomingMessage;
707 res: ServerResponse;
708 originalUrl: string;
709 respond?: boolean;
710
711 service: IService;
712
713 request: Request;
714
715 response: Response;
716
717 // The new 'cookies' instead of Koa's.
718 cookies: EggCookies;
719
720 helper: IHelper;
721
722 /**
723 * Resource Parameters
724 * @example
725 * ##### ctx.params.id {string}
726 *
727 * `GET /api/users/1` => `'1'`
728 *
729 * ##### ctx.params.ids {Array<String>}
730 *
731 * `GET /api/users/1,2,3` => `['1', '2', '3']`
732 *
733 * ##### ctx.params.fields {Array<String>}
734 *
735 * Expect request return data fields, for example
736 * `GET /api/users/1?fields=name,title` => `['name', 'title']`.
737 *
738 * ##### ctx.params.data {Object}
739 *
740 * Tht request data object
741 *
742 * ##### ctx.params.page {Number}
743 *
744 * Page number, `GET /api/users?page=10` => `10`
745 *
746 * ##### ctx.params.per_page {Number}
747 *
748 * The number of every page, `GET /api/users?per_page=20` => `20`
749 */
750 params: any;
751
752 /**
753 * @see Request#accept
754 */
755 queries: PlainObject<string[]>;
756
757 /**
758 * @see Request#accept
759 */
760 accept: accepts.Accepts;
761
762 /**
763 * @see Request#acceptJSON
764 */
765 acceptJSON: boolean;
766
767 /**
768 * @see Request#ip
769 */
770 ip: string;
771
772 /**
773 * @see Response#realStatus
774 */
775 realStatus: number;
776
777 /**
778 * Set the ctx.body.data value
779 *
780 * @member {Object} Context#data=
781 * @example
782 * ```js
783 * ctx.data = {
784 * id: 1,
785 * name: 'fengmk2'
786 * };
787 * ```
788 *
789 * will get responce
790 *
791 * ```js
792 * HTTP/1.1 200 OK
793 *
794 * {
795 * "data": {
796 * "id": 1,
797 * "name": "fengmk2"
798 * }
799 * }
800 * ```
801 */
802 data: any;
803
804 /**
805 * set ctx.body.meta value
806 *
807 * @example
808 * ```js
809 * ctx.meta = {
810 * count: 100
811 * };
812 * ```
813 * will get responce
814 *
815 * ```js
816 * HTTP/1.1 200 OK
817 *
818 * {
819 * "meta": {
820 * "count": 100
821 * }
822 * }
823 * ```
824 */
825 meta: any;
826
827 /**
828 * locals is an object for view, you can use `app.locals` and `ctx.locals` to set variables,
829 * which will be used as data when view is rendering.
830 * 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`.
831 *
832 * when you set locals, only object is available
833 *
834 * ```js
835 * this.locals = {
836 * a: 1
837 * };
838 * this.locals = {
839 * b: 1
840 * };
841 * this.locals.c = 1;
842 * console.log(this.locals);
843 * {
844 * a: 1,
845 * b: 1,
846 * c: 1,
847 * };
848 * ```
849 *
850 * `ctx.locals` has cache, it only merges `app.locals` once in one request.
851 *
852 * @member {Object} Context#locals
853 */
854 locals: IApplicationLocals & IContextLocals;
855
856 /**
857 * alias to {@link locals}, compatible with koa that use this variable
858 */
859 state: any;
860
861 /**
862 * Logger for Application, wrapping app.coreLogger with context infomation
863 *
864 * @member {ContextLogger} Context#logger
865 * @since 1.0.0
866 * @example
867 * ```js
868 * this.logger.info('some request data: %j', this.request.body);
869 * this.logger.warn('WARNING!!!!');
870 * ```
871 */
872 logger: EggLogger;
873
874 /**
875 * Get logger by name, it's equal to app.loggers['name'], but you can extend it with your own logical
876 */
877 getLogger(name: string): EggLogger;
878
879 /**
880 * Request start time
881 */
882 starttime: number;
883
884 /**
885 * http request helper base on httpclient, it will auto save httpclient log.
886 * Keep the same api with httpclient.request(url, args).
887 * See https://github.com/node-modules/urllib#api-doc for more details.
888 */
889 curl<T = any>(url: string, opt?: RequestOptions): Promise<T>;
890
891 __(key: string, ...values: string[]): string;
892 gettext(key: string, ...values: string[]): string;
893
894 /**
895 * get upload file stream
896 * @example
897 * ```js
898 * const stream = await this.getFileStream();
899 * // get other fields
900 * console.log(stream.fields);
901 * ```
902 * @method Context#getFileStream
903 * @param {Object} options
904 * @return {ReadStream} stream
905 * @since 1.0.0
906 */
907 getFileStream(options?: GetFileStreamOptions): Promise<FileStream>;
908
909 /**
910 * @see Responce.redirect
911 */
912 redirect(url: string, alt?: string): void;
913 }
914
915 export interface IContextLocals extends PlainObject { }
916
917 export class Controller extends BaseContextClass { }
918
919 export class Service extends BaseContextClass { }
920
921 export class Subscription extends BaseContextClass { }
922
923 /**
924 * The empty interface `IService` is a placeholder, for egg
925 * to auto injection service to ctx.service
926 *
927 * @example
928 *
929 * import { Service } from 'egg';
930 * class FooService extends Service {
931 * async bar() {}
932 * }
933 *
934 * declare module 'egg' {
935 * export interface IService {
936 * foo: FooService;
937 * }
938 * }
939 *
940 * Now I can get ctx.service.foo at controller and other service file.
941 */
942 export interface IService extends PlainObject { } // tslint:disable-line
943
944 export interface IController extends PlainObject { } // tslint:disable-line
945
946 export interface IMiddleware extends PlainObject { } // tslint:disable-line
947
948 export interface IHelper extends PlainObject, BaseContextClass {
949 /**
950 * Generate URL path(without host) for route. Takes the route name and a map of named params.
951 * @method Helper#pathFor
952 * @param {String} name - Router Name
953 * @param {Object} params - Other params
954 *
955 * @example
956 * ```js
957 * app.get('home', '/index.htm', 'home.index');
958 * ctx.helper.pathFor('home', { by: 'recent', limit: 20 })
959 * => /index.htm?by=recent&limit=20
960 * ```
961 * @return {String} url path(without host)
962 */
963 pathFor(name: string, params?: PlainObject): string;
964
965 /**
966 * Generate full URL(with host) for route. Takes the route name and a map of named params.
967 * @method Helper#urlFor
968 * @param {String} name - Router name
969 * @param {Object} params - Other params
970 * @example
971 * ```js
972 * app.get('home', '/index.htm', 'home.index');
973 * ctx.helper.urlFor('home', { by: 'recent', limit: 20 })
974 * => http://127.0.0.1:7001/index.htm?by=recent&limit=20
975 * ```
976 * @return {String} full url(with host)
977 */
978 urlFor(name: string, params?: PlainObject): string;
979 }
980
981 // egg env type
982 export type EggEnvType = 'local' | 'unittest' | 'prod' | string;
983
984 /**
985 * plugin config item interface
986 */
987 export interface IEggPluginItem {
988 env?: EggEnvType[];
989 path?: string;
990 package?: string;
991 enable?: boolean;
992 }
993
994 export type EggPluginItem = IEggPluginItem | boolean;
995
996 /**
997 * build-in plugin list
998 */
999 export interface EggPlugin {
1000 [key: string]: EggPluginItem | undefined;
1001 onerror?: EggPluginItem;
1002 session?: EggPluginItem;
1003 i18n?: EggPluginItem;
1004 watcher?: EggPluginItem;
1005 multipart?: EggPluginItem;
1006 security?: EggPluginItem;
1007 development?: EggPluginItem;
1008 logrotator?: EggPluginItem;
1009 schedule?: EggPluginItem;
1010 static?: EggPluginItem;
1011 jsonp?: EggPluginItem;
1012 view?: EggPluginItem;
1013 }
1014
1015 /**
1016 * Singleton instance in Agent Worker, extend {@link EggApplication}
1017 */
1018 export class Agent extends EggApplication {
1019 }
1020
1021 export interface ClusterOptions {
1022 /** specify framework that can be absolute path or npm package */
1023 framework?: string;
1024 /** directory of application, default to `process.cwd()` */
1025 baseDir?: string;
1026 /** customized plugins, for unittest */
1027 plugins?: object | null;
1028 /** numbers of app workers, default to `os.cpus().length` */
1029 workers?: number;
1030 /** listening port, default to 7001(http) or 8443(https) */
1031 port?: number;
1032 /** https or not */
1033 https?: boolean;
1034 /** ssl key */
1035 key?: string;
1036 /** ssl cert */
1037 cert?: string;
1038 [prop: string]: any;
1039 }
1040
1041 export function startCluster(options: ClusterOptions, callback: (...args: any[]) => any): void;
1042
1043 export interface StartOptions{
1044 /** specify framework that can be absolute path or npm package */
1045 framework?: string;
1046 /** directory of application, default to `process.cwd()` */
1047 baseDir?: string;
1048 /** ignore single process mode warning */
1049 ignoreWarning? :boolean
1050 }
1051
1052 export function start(options?:StartOptions):Promise<Application>
1053
1054 /**
1055 * Powerful Partial, Support adding ? modifier to a mapped property in deep level
1056 * @example
1057 * import { PowerPartial, EggAppConfig } from 'egg';
1058 *
1059 * // { view: { defaultEngines: string } } => { view?: { defaultEngines?: string } }
1060 * type EggConfig = PowerPartial<EggAppConfig>
1061 */
1062 export type PowerPartial<T> = {
1063 [U in keyof T]?: T[U] extends object
1064 ? PowerPartial<T[U]>
1065 : T[U]
1066 };
1067
1068 // send data can be number|string|boolean|object but not Set|Map
1069 export interface Messenger extends EventEmitter {
1070 /**
1071 * broadcast to all agent/app processes including itself
1072 */
1073 broadcast(action: string, data: any): void;
1074
1075 /**
1076 * send to agent from the app,
1077 * send to an random app from the agent
1078 */
1079 sendRandom(action: string, data: any): void;
1080
1081 /**
1082 * send to specified process
1083 */
1084 sendTo(pid: number, action: string, data: any): void;
1085
1086 /**
1087 * send to agent from the app,
1088 * send to itself from the agent
1089 */
1090 sendToAgent(action: string, data: any): void;
1091
1092 /**
1093 * send to all app including itself from the app,
1094 * send to all app from the agent
1095 */
1096 sendToApp(action: string, data: any): void;
1097 }
1098
1099 // compatible
1100 export interface EggLoaderOptions extends CoreLoaderOptions {}
1101 export interface EggLoader extends CoreLoader {}
1102
1103 /**
1104 * App worker process Loader, will load plugins
1105 * @see https://github.com/eggjs/egg-core
1106 */
1107 export class AppWorkerLoader extends CoreLoader {
1108 loadConfig(): void;
1109 load(): void;
1110 }
1111
1112 /**
1113 * Agent worker process loader
1114 * @see https://github.com/eggjs/egg-loader
1115 */
1116 export class AgentWorkerLoader extends CoreLoader {
1117 loadConfig(): void;
1118 load(): void;
1119 }
1120
1121 export interface IBoot {
1122 /**
1123 * Ready to call configDidLoad,
1124 * Config, plugin files are referred,
1125 * this is the last chance to modify the config.
1126 */
1127 configWillLoad?(): void;
1128
1129 /**
1130 * Config, plugin files have loaded
1131 */
1132 configDidLoad?(): void;
1133
1134 /**
1135 * All files have loaded, start plugin here
1136 */
1137 didLoad?(): Promise<void>;
1138
1139 /**
1140 * All plugins have started, can do some thing before app ready
1141 */
1142 willReady?(): Promise<void>;
1143
1144 /**
1145 * Worker is ready, can do some things,
1146 * don't need to block the app boot
1147 */
1148 didReady?(): Promise<void>;
1149
1150 /**
1151 * Server is listening
1152 */
1153 serverDidReady?(): Promise<void>;
1154
1155 /**
1156 * Do some thing before app close
1157 */
1158 beforeClose?(): Promise<void>;
1159 }
1160
1161 export interface Singleton<T> {
1162 get(id: string): T;
1163 }
1164}
1165
\No newline at end of file