egg 4.0.0-beta.0 → 4.0.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/README.zh-CN.md +1 -0
- package/dist/commonjs/app/extend/context.d.ts +154 -0
- package/dist/commonjs/app/extend/context.js +261 -0
- package/dist/commonjs/app/extend/context.types.d.ts +16 -0
- package/dist/commonjs/app/extend/context.types.js +3 -0
- package/dist/commonjs/app/extend/helper.d.ts +37 -0
- package/dist/commonjs/app/extend/helper.js +49 -0
- package/dist/commonjs/app/extend/request.d.ts +128 -0
- package/dist/commonjs/app/extend/request.js +270 -0
- package/dist/commonjs/app/extend/response.d.ts +25 -0
- package/dist/commonjs/app/extend/response.js +37 -0
- package/dist/commonjs/app/middleware/meta.d.ts +2 -3
- package/dist/commonjs/app/middleware/meta.js +1 -1
- package/dist/commonjs/app/middleware/notfound.d.ts +2 -3
- package/dist/commonjs/app/middleware/notfound.js +1 -1
- package/dist/commonjs/app/middleware/site_file.d.ts +5 -3
- package/dist/commonjs/app/middleware/site_file.js +21 -3
- package/dist/commonjs/config/config.default.js +5 -4
- package/dist/commonjs/config/plugin.js +3 -3
- package/dist/commonjs/index.d.ts +3 -1
- package/dist/commonjs/index.js +8 -6
- package/dist/commonjs/lib/application.d.ts +5 -12
- package/dist/commonjs/lib/application.js +9 -20
- package/dist/commonjs/lib/core/base_context_class.d.ts +2 -2
- package/dist/commonjs/lib/core/base_hook_class.d.ts +1 -1
- package/dist/commonjs/lib/core/context_httpclient.d.ts +3 -3
- package/dist/commonjs/lib/core/context_httpclient.js +1 -1
- package/dist/commonjs/lib/core/httpclient.d.ts +2 -3
- package/dist/commonjs/lib/core/httpclient.js +3 -6
- package/dist/commonjs/lib/core/messenger/IMessenger.d.ts +3 -3
- package/dist/commonjs/lib/core/messenger/index.js +2 -2
- package/dist/commonjs/lib/core/messenger/ipc.d.ts +6 -4
- package/dist/commonjs/lib/core/messenger/ipc.js +31 -20
- package/dist/commonjs/lib/core/messenger/local.d.ts +3 -3
- package/dist/commonjs/lib/core/messenger/local.js +14 -11
- package/dist/commonjs/lib/egg.d.ts +25 -16
- package/dist/commonjs/lib/egg.js +44 -22
- package/dist/commonjs/lib/egg.types.d.ts +6 -0
- package/dist/commonjs/lib/egg.types.js +3 -0
- package/dist/commonjs/lib/type.d.ts +3 -5
- package/dist/commonjs/lib/utils.d.ts +2 -0
- package/dist/commonjs/lib/utils.js +21 -0
- package/dist/commonjs/urllib.d.ts +1 -0
- package/dist/commonjs/urllib.js +18 -0
- package/dist/esm/app/extend/context.d.ts +154 -0
- package/dist/esm/app/extend/context.js +255 -0
- package/dist/esm/app/extend/context.types.d.ts +16 -0
- package/dist/esm/app/extend/context.types.js +2 -0
- package/dist/esm/app/extend/helper.d.ts +37 -0
- package/dist/esm/app/extend/helper.js +43 -0
- package/dist/esm/app/extend/request.d.ts +128 -0
- package/dist/esm/app/extend/request.js +264 -0
- package/dist/esm/app/extend/response.d.ts +25 -0
- package/dist/esm/app/extend/response.js +34 -0
- package/dist/esm/app/middleware/meta.d.ts +2 -3
- package/dist/esm/app/middleware/meta.js +1 -1
- package/dist/esm/app/middleware/notfound.d.ts +2 -3
- package/dist/esm/app/middleware/notfound.js +1 -1
- package/dist/esm/app/middleware/site_file.d.ts +5 -3
- package/dist/esm/app/middleware/site_file.js +21 -3
- package/dist/esm/config/config.default.js +5 -4
- package/dist/esm/config/plugin.js +3 -3
- package/dist/esm/index.d.ts +3 -1
- package/dist/esm/index.js +5 -4
- package/dist/esm/lib/application.d.ts +5 -12
- package/dist/esm/lib/application.js +9 -20
- package/dist/esm/lib/core/base_context_class.d.ts +2 -2
- package/dist/esm/lib/core/base_hook_class.d.ts +1 -1
- package/dist/esm/lib/core/context_httpclient.d.ts +3 -3
- package/dist/esm/lib/core/context_httpclient.js +1 -1
- package/dist/esm/lib/core/httpclient.d.ts +2 -3
- package/dist/esm/lib/core/httpclient.js +2 -2
- package/dist/esm/lib/core/messenger/IMessenger.d.ts +3 -3
- package/dist/esm/lib/core/messenger/index.js +2 -2
- package/dist/esm/lib/core/messenger/ipc.d.ts +6 -4
- package/dist/esm/lib/core/messenger/ipc.js +29 -18
- package/dist/esm/lib/core/messenger/local.d.ts +3 -3
- package/dist/esm/lib/core/messenger/local.js +14 -11
- package/dist/esm/lib/egg.d.ts +25 -16
- package/dist/esm/lib/egg.js +24 -15
- package/dist/esm/lib/egg.types.d.ts +6 -0
- package/dist/esm/lib/egg.types.js +2 -0
- package/dist/esm/lib/type.d.ts +3 -5
- package/dist/esm/lib/utils.d.ts +2 -0
- package/dist/esm/lib/utils.js +14 -0
- package/dist/esm/urllib.d.ts +1 -0
- package/dist/esm/urllib.js +2 -0
- package/dist/package.json +1 -1
- package/package.json +44 -29
- package/src/app/extend/context.ts +303 -0
- package/src/app/extend/context.types.ts +24 -0
- package/src/app/extend/{helper.js → helper.ts} +14 -13
- package/src/app/extend/{request.js → request.ts} +81 -79
- package/src/app/extend/response.ts +36 -0
- package/src/app/middleware/meta.ts +2 -3
- package/src/app/middleware/notfound.ts +2 -3
- package/src/app/middleware/site_file.ts +26 -7
- package/src/config/config.default.ts +4 -3
- package/src/config/plugin.ts +2 -2
- package/src/index.ts +5 -3
- package/src/lib/application.ts +14 -21
- package/src/lib/core/base_context_class.ts +2 -2
- package/src/lib/core/base_hook_class.ts +1 -1
- package/src/lib/core/context_httpclient.ts +3 -3
- package/src/lib/core/httpclient.ts +4 -5
- package/src/lib/core/messenger/IMessenger.ts +3 -3
- package/src/lib/core/messenger/index.ts +1 -1
- package/src/lib/core/messenger/ipc.ts +31 -20
- package/src/lib/core/messenger/local.ts +13 -11
- package/src/lib/egg.ts +60 -28
- package/src/lib/egg.types.ts +6 -0
- package/src/lib/type.ts +6 -6
- package/src/lib/utils.ts +16 -0
- package/src/urllib.ts +1 -0
- package/src/app/extend/context.js +0 -285
- package/src/app/extend/response.js +0 -101
package/src/lib/egg.ts
CHANGED
|
@@ -3,12 +3,22 @@ import path from 'node:path';
|
|
|
3
3
|
import fs from 'node:fs';
|
|
4
4
|
import http, { type IncomingMessage, type ServerResponse } from 'node:http';
|
|
5
5
|
import inspector from 'node:inspector';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
7
|
+
import {
|
|
8
|
+
EggCore,
|
|
9
|
+
Request as EggCoreRequest,
|
|
10
|
+
Response as EggCoreResponse,
|
|
11
|
+
Router,
|
|
12
|
+
} from '@eggjs/core';
|
|
13
|
+
import type {
|
|
14
|
+
EggCoreOptions,
|
|
15
|
+
Next, MiddlewareFunc as EggCoreMiddlewareFunc,
|
|
16
|
+
ILifecycleBoot,
|
|
17
|
+
} from '@eggjs/core';
|
|
8
18
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
9
19
|
// @ts-ignore
|
|
10
20
|
import createClusterClient, { close as closeClusterClient } from 'cluster-client';
|
|
11
|
-
import extend from 'extend2';
|
|
21
|
+
import { extend } from 'extend2';
|
|
12
22
|
import { EggContextLogger as ContextLogger, EggLoggers, EggLogger } from 'egg-logger';
|
|
13
23
|
import { Cookies as ContextCookies } from '@eggjs/cookies';
|
|
14
24
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
@@ -16,6 +26,7 @@ import { Cookies as ContextCookies } from '@eggjs/cookies';
|
|
|
16
26
|
import CircularJSON from 'circular-json-for-egg';
|
|
17
27
|
import type { Agent } from './agent.js';
|
|
18
28
|
import type { Application } from './application.js';
|
|
29
|
+
import Context, { type ContextDelegation } from '../app/extend/context.js';
|
|
19
30
|
import type { EggAppConfig } from './type.js';
|
|
20
31
|
import { create as createMessenger, IMessenger } from './core/messenger/index.js';
|
|
21
32
|
import { ContextHttpClient } from './core/context_httpclient.js';
|
|
@@ -30,6 +41,9 @@ import { convertObject } from './core/utils.js';
|
|
|
30
41
|
import { BaseContextClass } from './core/base_context_class.js';
|
|
31
42
|
import { BaseHookClass } from './core/base_hook_class.js';
|
|
32
43
|
import type { EggApplicationLoader } from './loader/index.js';
|
|
44
|
+
import { getSourceDirname } from './utils.js';
|
|
45
|
+
|
|
46
|
+
import './egg.types.js';
|
|
33
47
|
|
|
34
48
|
const EGG_PATH = Symbol.for('egg#eggPath');
|
|
35
49
|
|
|
@@ -39,20 +53,35 @@ export interface EggApplicationCoreOptions extends Omit<EggCoreOptions, 'baseDir
|
|
|
39
53
|
baseDir?: string;
|
|
40
54
|
}
|
|
41
55
|
|
|
42
|
-
export
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
56
|
+
// export egg classes
|
|
57
|
+
export {
|
|
58
|
+
Context,
|
|
59
|
+
Router,
|
|
60
|
+
EggLogger,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export class Request extends EggCoreRequest {
|
|
64
|
+
declare app: EggCore;
|
|
65
|
+
declare response: Response;
|
|
66
|
+
declare ctx: ContextDelegation;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export class Response extends EggCoreResponse {
|
|
70
|
+
declare app: EggCore;
|
|
71
|
+
declare request: Request;
|
|
72
|
+
declare ctx: ContextDelegation;
|
|
54
73
|
}
|
|
55
74
|
|
|
75
|
+
// export egg types
|
|
76
|
+
export type {
|
|
77
|
+
ContextDelegation,
|
|
78
|
+
ILifecycleBoot,
|
|
79
|
+
Next,
|
|
80
|
+
};
|
|
81
|
+
// keep compatible with egg version 3.x
|
|
82
|
+
export type EggContext = ContextDelegation;
|
|
83
|
+
export type MiddlewareFunc<T extends ContextDelegation = ContextDelegation> = EggCoreMiddlewareFunc<T>;
|
|
84
|
+
|
|
56
85
|
/**
|
|
57
86
|
* Based on koa's Application
|
|
58
87
|
* @see https://github.com/eggjs/egg-core
|
|
@@ -60,6 +89,7 @@ export interface EggContext extends EggCoreContext {
|
|
|
60
89
|
* @augments EggCore
|
|
61
90
|
*/
|
|
62
91
|
export class EggApplicationCore extends EggCore {
|
|
92
|
+
declare ctxStorage: AsyncLocalStorage<ContextDelegation>;
|
|
63
93
|
// export context base classes, let framework can impl sub class and over context extend easily.
|
|
64
94
|
ContextCookies = ContextCookies;
|
|
65
95
|
ContextLogger = ContextLogger;
|
|
@@ -144,7 +174,16 @@ export class EggApplicationCore extends EggCore {
|
|
|
144
174
|
this.messenger.once('egg-ready', () => {
|
|
145
175
|
this.lifecycle.triggerServerDidReady();
|
|
146
176
|
});
|
|
147
|
-
this.
|
|
177
|
+
this.lifecycle.registerBeforeStart(async () => {
|
|
178
|
+
await this.load();
|
|
179
|
+
}, 'load files');
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* @deprecated please use `options` property instead
|
|
184
|
+
*/
|
|
185
|
+
get _options() {
|
|
186
|
+
return this.options;
|
|
148
187
|
}
|
|
149
188
|
|
|
150
189
|
protected async loadConfig() {
|
|
@@ -212,7 +251,7 @@ export class EggApplicationCore extends EggCore {
|
|
|
212
251
|
* - {Number} [maxWaitTime|30000] - leader startup max time, default is 30 seconds
|
|
213
252
|
* @return {ClientWrapper} wrapper
|
|
214
253
|
*/
|
|
215
|
-
cluster(clientClass: unknown, options
|
|
254
|
+
cluster(clientClass: unknown, options?: object) {
|
|
216
255
|
const clientClassOptions = {
|
|
217
256
|
...this.config.clusterClient,
|
|
218
257
|
...options,
|
|
@@ -403,7 +442,6 @@ export class EggApplicationCore extends EggCore {
|
|
|
403
442
|
if (!(err instanceof Error)) {
|
|
404
443
|
const newError = new Error(String(err));
|
|
405
444
|
// err maybe an object, try to copy the name, message and stack to the new error instance
|
|
406
|
-
/* istanbul ignore else */
|
|
407
445
|
if (err) {
|
|
408
446
|
if (err.name) newError.name = err.name;
|
|
409
447
|
if (err.message) newError.message = err.message;
|
|
@@ -411,7 +449,6 @@ export class EggApplicationCore extends EggCore {
|
|
|
411
449
|
}
|
|
412
450
|
err = newError;
|
|
413
451
|
}
|
|
414
|
-
/* istanbul ignore else */
|
|
415
452
|
if (err.name === 'Error') {
|
|
416
453
|
err.name = 'unhandledRejectionError';
|
|
417
454
|
}
|
|
@@ -491,12 +528,7 @@ export class EggApplicationCore extends EggCore {
|
|
|
491
528
|
}
|
|
492
529
|
|
|
493
530
|
get [EGG_PATH]() {
|
|
494
|
-
|
|
495
|
-
return path.dirname(__dirname);
|
|
496
|
-
}
|
|
497
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
498
|
-
// @ts-ignore
|
|
499
|
-
return path.dirname(path.dirname(fileURLToPath(import.meta.url)));
|
|
531
|
+
return getSourceDirname();
|
|
500
532
|
}
|
|
501
533
|
|
|
502
534
|
#setupTimeoutTimer() {
|
|
@@ -538,7 +570,7 @@ export class EggApplicationCore extends EggCore {
|
|
|
538
570
|
* @deprecated
|
|
539
571
|
*/
|
|
540
572
|
get proxy() {
|
|
541
|
-
this.deprecate('please use app.config.proxy instead');
|
|
573
|
+
// this.deprecate('please use app.config.proxy instead');
|
|
542
574
|
return this.config.proxy;
|
|
543
575
|
}
|
|
544
576
|
/* eslint no-empty-function: off */
|
|
@@ -580,7 +612,7 @@ export class EggApplicationCore extends EggCore {
|
|
|
580
612
|
* @param {Request} [req] - if you want to mock request like querystring, you can pass an object to this function.
|
|
581
613
|
* @return {Context} context
|
|
582
614
|
*/
|
|
583
|
-
createAnonymousContext(req?: any):
|
|
615
|
+
createAnonymousContext(req?: any): EggContext {
|
|
584
616
|
const request: any = {
|
|
585
617
|
headers: {
|
|
586
618
|
host: '127.0.0.1',
|
|
@@ -624,7 +656,7 @@ export class EggApplicationCore extends EggCore {
|
|
|
624
656
|
const context = Object.create(this.context) as EggContext;
|
|
625
657
|
const request = context.request = Object.create(this.request);
|
|
626
658
|
const response = context.response = Object.create(this.response);
|
|
627
|
-
context.app = request.app = response.app = this;
|
|
659
|
+
context.app = request.app = response.app = this as any;
|
|
628
660
|
context.req = request.req = response.req = req;
|
|
629
661
|
context.res = request.res = response.res = res;
|
|
630
662
|
request.ctx = response.ctx = context;
|
package/src/lib/type.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { Socket } from 'node:net';
|
|
2
|
-
import type { EggCoreContext } from '@eggjs/core';
|
|
3
2
|
import type {
|
|
4
3
|
RequestOptions as HttpClientRequestOptions,
|
|
5
4
|
} from 'urllib';
|
|
@@ -10,16 +9,17 @@ import type {
|
|
|
10
9
|
FileLoaderOptions,
|
|
11
10
|
} from '@eggjs/core';
|
|
12
11
|
import type {
|
|
13
|
-
EggApplicationCore,
|
|
12
|
+
EggApplicationCore, ContextDelegation,
|
|
14
13
|
} from './egg.js';
|
|
15
14
|
import type { MetaMiddlewareOptions } from '../app/middleware/meta.js';
|
|
16
15
|
import type { NotFoundMiddlewareOptions } from '../app/middleware/notfound.js';
|
|
17
16
|
import type { SiteFileMiddlewareOptions } from '../app/middleware/site_file.js';
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
// import @eggjs/watcher types
|
|
19
|
+
// import '@eggjs/watcher';
|
|
21
20
|
|
|
22
|
-
|
|
21
|
+
type IgnoreItem = string | RegExp | ((ctx: ContextDelegation) => boolean);
|
|
22
|
+
type IgnoreOrMatch = IgnoreItem | IgnoreItem[];
|
|
23
23
|
|
|
24
24
|
export interface ClientErrorResponse {
|
|
25
25
|
body: string | Buffer;
|
|
@@ -103,7 +103,7 @@ export interface EggAppConfig {
|
|
|
103
103
|
};
|
|
104
104
|
/** Default is `'error'`, it will return `400` response when `Prototype-Poisoning` happen. */
|
|
105
105
|
onProtoPoisoning: 'error' | 'remove' | 'ignore';
|
|
106
|
-
onerror(err: any, ctx:
|
|
106
|
+
onerror(err: any, ctx: ContextDelegation): void;
|
|
107
107
|
};
|
|
108
108
|
|
|
109
109
|
/**
|
package/src/lib/utils.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
|
|
5
|
+
export function getSourceDirname() {
|
|
6
|
+
if (typeof __dirname !== 'undefined') {
|
|
7
|
+
return path.dirname(__dirname);
|
|
8
|
+
}
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
10
|
+
// @ts-ignore
|
|
11
|
+
return path.dirname(path.dirname(fileURLToPath(import.meta.url)));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function getSourceFile(filename: string) {
|
|
15
|
+
return path.join(getSourceDirname(), filename);
|
|
16
|
+
}
|
package/src/urllib.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from 'urllib';
|
|
@@ -1,285 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const { performance } = require('perf_hooks');
|
|
4
|
-
const delegate = require('delegates');
|
|
5
|
-
const { assign } = require('utility');
|
|
6
|
-
const eggUtils = require('egg-core').utils;
|
|
7
|
-
|
|
8
|
-
const HELPER = Symbol('Context#helper');
|
|
9
|
-
const LOCALS = Symbol('Context#locals');
|
|
10
|
-
const LOCALS_LIST = Symbol('Context#localsList');
|
|
11
|
-
const COOKIES = Symbol('Context#cookies');
|
|
12
|
-
const CONTEXT_LOGGERS = Symbol('Context#logger');
|
|
13
|
-
const CONTEXT_HTTPCLIENT = Symbol('Context#httpclient');
|
|
14
|
-
const CONTEXT_ROUTER = Symbol('Context#router');
|
|
15
|
-
|
|
16
|
-
const proto = module.exports = {
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Get the current visitor's cookies.
|
|
20
|
-
*/
|
|
21
|
-
get cookies() {
|
|
22
|
-
if (!this[COOKIES]) {
|
|
23
|
-
this[COOKIES] = new this.app.ContextCookies(this, this.app.keys, this.app.config.cookies);
|
|
24
|
-
}
|
|
25
|
-
return this[COOKIES];
|
|
26
|
-
},
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Get a wrapper httpclient instance contain ctx in the hold request process
|
|
30
|
-
*
|
|
31
|
-
* @return {ContextHttpClient} the wrapper httpclient instance
|
|
32
|
-
*/
|
|
33
|
-
get httpclient() {
|
|
34
|
-
if (!this[CONTEXT_HTTPCLIENT]) {
|
|
35
|
-
this[CONTEXT_HTTPCLIENT] = new this.app.ContextHttpClient(this);
|
|
36
|
-
}
|
|
37
|
-
return this[CONTEXT_HTTPCLIENT];
|
|
38
|
-
},
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Shortcut for httpclient.curl
|
|
42
|
-
*
|
|
43
|
-
* @function Context#curl
|
|
44
|
-
* @param {String|Object} url - request url address.
|
|
45
|
-
* @param {Object} [options] - options for request.
|
|
46
|
-
* @return {Object} see {@link ContextHttpClient#curl}
|
|
47
|
-
*/
|
|
48
|
-
curl(url, options) {
|
|
49
|
-
return this.httpclient.curl(url, options);
|
|
50
|
-
},
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Alias to {@link Application#router}
|
|
54
|
-
*
|
|
55
|
-
* @member {Router} Context#router
|
|
56
|
-
* @since 1.0.0
|
|
57
|
-
* @example
|
|
58
|
-
* ```js
|
|
59
|
-
* this.router.pathFor('post', { id: 12 });
|
|
60
|
-
* ```
|
|
61
|
-
*/
|
|
62
|
-
get router() {
|
|
63
|
-
if (!this[CONTEXT_ROUTER]) {
|
|
64
|
-
this[CONTEXT_ROUTER] = this.app.router;
|
|
65
|
-
}
|
|
66
|
-
return this[CONTEXT_ROUTER];
|
|
67
|
-
},
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Set router to Context, only use on EggRouter
|
|
71
|
-
* @param {EggRouter} val router instance
|
|
72
|
-
*/
|
|
73
|
-
set router(val) {
|
|
74
|
-
this[CONTEXT_ROUTER] = val;
|
|
75
|
-
},
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Get helper instance from {@link Application#Helper}
|
|
79
|
-
*
|
|
80
|
-
* @member {Helper} Context#helper
|
|
81
|
-
* @since 1.0.0
|
|
82
|
-
*/
|
|
83
|
-
get helper() {
|
|
84
|
-
if (!this[HELPER]) {
|
|
85
|
-
this[HELPER] = new this.app.Helper(this);
|
|
86
|
-
}
|
|
87
|
-
return this[HELPER];
|
|
88
|
-
},
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Wrap app.loggers with context infomation,
|
|
92
|
-
* if a custom logger is defined by naming aLogger, then you can `ctx.getLogger('aLogger')`
|
|
93
|
-
*
|
|
94
|
-
* @param {String} name - logger name
|
|
95
|
-
* @return {Logger} logger
|
|
96
|
-
*/
|
|
97
|
-
getLogger(name) {
|
|
98
|
-
if (this.app.config.logger.enableFastContextLogger) {
|
|
99
|
-
return this.app.getLogger(name);
|
|
100
|
-
}
|
|
101
|
-
let cache = this[CONTEXT_LOGGERS];
|
|
102
|
-
if (!cache) {
|
|
103
|
-
cache = this[CONTEXT_LOGGERS] = {};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// read from cache
|
|
107
|
-
if (cache[name]) return cache[name];
|
|
108
|
-
|
|
109
|
-
// get no exist logger
|
|
110
|
-
const appLogger = this.app.getLogger(name);
|
|
111
|
-
if (!appLogger) return null;
|
|
112
|
-
|
|
113
|
-
// write to cache
|
|
114
|
-
cache[name] = new this.app.ContextLogger(this, appLogger);
|
|
115
|
-
return cache[name];
|
|
116
|
-
},
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Logger for Application, wrapping app.coreLogger with context infomation
|
|
120
|
-
*
|
|
121
|
-
* @member {ContextLogger} Context#logger
|
|
122
|
-
* @since 1.0.0
|
|
123
|
-
* @example
|
|
124
|
-
* ```js
|
|
125
|
-
* this.logger.info('some request data: %j', this.request.body);
|
|
126
|
-
* this.logger.warn('WARNING!!!!');
|
|
127
|
-
* ```
|
|
128
|
-
*/
|
|
129
|
-
get logger() {
|
|
130
|
-
return this.getLogger('logger');
|
|
131
|
-
},
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Logger for frameworks and plugins,
|
|
135
|
-
* wrapping app.coreLogger with context infomation
|
|
136
|
-
*
|
|
137
|
-
* @member {ContextLogger} Context#coreLogger
|
|
138
|
-
* @since 1.0.0
|
|
139
|
-
*/
|
|
140
|
-
get coreLogger() {
|
|
141
|
-
return this.getLogger('coreLogger');
|
|
142
|
-
},
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* locals is an object for view, you can use `app.locals` and `ctx.locals` to set variables,
|
|
146
|
-
* which will be used as data when view is rendering.
|
|
147
|
-
* 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`.
|
|
148
|
-
*
|
|
149
|
-
* when you set locals, only object is available
|
|
150
|
-
*
|
|
151
|
-
* ```js
|
|
152
|
-
* this.locals = {
|
|
153
|
-
* a: 1
|
|
154
|
-
* };
|
|
155
|
-
* this.locals = {
|
|
156
|
-
* b: 1
|
|
157
|
-
* };
|
|
158
|
-
* this.locals.c = 1;
|
|
159
|
-
* console.log(this.locals);
|
|
160
|
-
* {
|
|
161
|
-
* a: 1,
|
|
162
|
-
* b: 1,
|
|
163
|
-
* c: 1,
|
|
164
|
-
* };
|
|
165
|
-
* ```
|
|
166
|
-
*
|
|
167
|
-
* `ctx.locals` has cache, it only merges `app.locals` once in one request.
|
|
168
|
-
*
|
|
169
|
-
* @member {Object} Context#locals
|
|
170
|
-
*/
|
|
171
|
-
get locals() {
|
|
172
|
-
if (!this[LOCALS]) {
|
|
173
|
-
this[LOCALS] = assign({}, this.app.locals);
|
|
174
|
-
}
|
|
175
|
-
if (this[LOCALS_LIST] && this[LOCALS_LIST].length) {
|
|
176
|
-
assign(this[LOCALS], this[LOCALS_LIST]);
|
|
177
|
-
this[LOCALS_LIST] = null;
|
|
178
|
-
}
|
|
179
|
-
return this[LOCALS];
|
|
180
|
-
},
|
|
181
|
-
|
|
182
|
-
set locals(val) {
|
|
183
|
-
if (!this[LOCALS_LIST]) {
|
|
184
|
-
this[LOCALS_LIST] = [];
|
|
185
|
-
}
|
|
186
|
-
this[LOCALS_LIST].push(val);
|
|
187
|
-
},
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* alias to {@link Context#locals}, compatible with koa that use this variable
|
|
191
|
-
* @member {Object} state
|
|
192
|
-
* @see Context#locals
|
|
193
|
-
*/
|
|
194
|
-
get state() {
|
|
195
|
-
return this.locals;
|
|
196
|
-
},
|
|
197
|
-
|
|
198
|
-
set state(val) {
|
|
199
|
-
this.locals = val;
|
|
200
|
-
},
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* Run async function in the background
|
|
204
|
-
* @param {Function} scope - the first args is ctx
|
|
205
|
-
* ```js
|
|
206
|
-
* this.body = 'hi';
|
|
207
|
-
*
|
|
208
|
-
* this.runInBackground(async ctx => {
|
|
209
|
-
* await ctx.mysql.query(sql);
|
|
210
|
-
* await ctx.curl(url);
|
|
211
|
-
* });
|
|
212
|
-
* ```
|
|
213
|
-
*/
|
|
214
|
-
runInBackground(scope) {
|
|
215
|
-
// try to use custom function name first
|
|
216
|
-
/* istanbul ignore next */
|
|
217
|
-
const taskName = scope._name || scope.name || eggUtils.getCalleeFromStack(true);
|
|
218
|
-
scope._name = taskName;
|
|
219
|
-
this._runInBackground(scope);
|
|
220
|
-
},
|
|
221
|
-
|
|
222
|
-
// let plugins or frameworks to reuse _runInBackground in some cases.
|
|
223
|
-
// e.g.: https://github.com/eggjs/egg-mock/pull/78
|
|
224
|
-
_runInBackground(scope) {
|
|
225
|
-
const ctx = this;
|
|
226
|
-
const start = performance.now();
|
|
227
|
-
/* istanbul ignore next */
|
|
228
|
-
const taskName = scope._name || scope.name || eggUtils.getCalleeFromStack(true);
|
|
229
|
-
// use setImmediate to ensure all sync logic will run async
|
|
230
|
-
return new Promise(resolve => setImmediate(resolve))
|
|
231
|
-
// use app.toAsyncFunction to support both generator function and async function
|
|
232
|
-
.then(() => ctx.app.toAsyncFunction(scope)(ctx))
|
|
233
|
-
.then(() => {
|
|
234
|
-
ctx.coreLogger.info('[egg:background] task:%s success (%dms)',
|
|
235
|
-
taskName, Math.floor((performance.now() - start) * 1000) / 1000);
|
|
236
|
-
})
|
|
237
|
-
.catch(err => {
|
|
238
|
-
// background task process log
|
|
239
|
-
ctx.coreLogger.info('[egg:background] task:%s fail (%dms)',
|
|
240
|
-
taskName, Math.floor((performance.now() - start) * 1000) / 1000);
|
|
241
|
-
|
|
242
|
-
// emit error when promise catch, and set err.runInBackground flag
|
|
243
|
-
err.runInBackground = true;
|
|
244
|
-
ctx.app.emit('error', err, ctx);
|
|
245
|
-
});
|
|
246
|
-
},
|
|
247
|
-
};
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* Context delegation.
|
|
251
|
-
*/
|
|
252
|
-
|
|
253
|
-
delegate(proto, 'request')
|
|
254
|
-
/**
|
|
255
|
-
* @member {Boolean} Context#acceptJSON
|
|
256
|
-
* @see Request#acceptJSON
|
|
257
|
-
* @since 1.0.0
|
|
258
|
-
*/
|
|
259
|
-
.getter('acceptJSON')
|
|
260
|
-
/**
|
|
261
|
-
* @member {Array} Context#queries
|
|
262
|
-
* @see Request#queries
|
|
263
|
-
* @since 1.0.0
|
|
264
|
-
*/
|
|
265
|
-
.getter('queries')
|
|
266
|
-
/**
|
|
267
|
-
* @member {Boolean} Context#accept
|
|
268
|
-
* @see Request#accept
|
|
269
|
-
* @since 1.0.0
|
|
270
|
-
*/
|
|
271
|
-
.getter('accept')
|
|
272
|
-
/**
|
|
273
|
-
* @member {string} Context#ip
|
|
274
|
-
* @see Request#ip
|
|
275
|
-
* @since 1.0.0
|
|
276
|
-
*/
|
|
277
|
-
.access('ip');
|
|
278
|
-
|
|
279
|
-
delegate(proto, 'response')
|
|
280
|
-
/**
|
|
281
|
-
* @member {Number} Context#realStatus
|
|
282
|
-
* @see Response#realStatus
|
|
283
|
-
* @since 1.0.0
|
|
284
|
-
*/
|
|
285
|
-
.access('realStatus');
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const getType = require('cache-content-type');
|
|
4
|
-
const isJSON = require('koa-is-json');
|
|
5
|
-
|
|
6
|
-
const REAL_STATUS = Symbol('Context#realStatus');
|
|
7
|
-
|
|
8
|
-
module.exports = {
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Get or set the length of content.
|
|
12
|
-
*
|
|
13
|
-
* For Get: If the original content length is null or undefined, it will read out
|
|
14
|
-
* the body's content length as the return value.
|
|
15
|
-
*
|
|
16
|
-
* @member {Number} Response#type
|
|
17
|
-
* @param {Number} len The content-length to be set.
|
|
18
|
-
*/
|
|
19
|
-
set length(len) {
|
|
20
|
-
// copy from koa
|
|
21
|
-
// change header name to lower case
|
|
22
|
-
this.set('content-length', len);
|
|
23
|
-
},
|
|
24
|
-
|
|
25
|
-
get length() {
|
|
26
|
-
// copy from koa
|
|
27
|
-
const len = this.header['content-length'];
|
|
28
|
-
const body = this.body;
|
|
29
|
-
|
|
30
|
-
if (len == null) {
|
|
31
|
-
if (!body) return;
|
|
32
|
-
if (typeof body === 'string') return Buffer.byteLength(body);
|
|
33
|
-
if (Buffer.isBuffer(body)) return body.length;
|
|
34
|
-
if (isJSON(body)) return Buffer.byteLength(JSON.stringify(body));
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return parseInt(len, 10);
|
|
39
|
-
},
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Get or set the content-type.
|
|
43
|
-
*
|
|
44
|
-
* For Set: If type is null or undefined, this property will be removed.
|
|
45
|
-
*
|
|
46
|
-
* For Get: If the value is null or undefined, an empty string will be returned;
|
|
47
|
-
* if you have multiple values seperated by `;`, ONLY the first one will be returned.
|
|
48
|
-
*
|
|
49
|
-
* @member {String} Response#type
|
|
50
|
-
* @param {String} type The content-type to be set.
|
|
51
|
-
*/
|
|
52
|
-
set type(type) {
|
|
53
|
-
// copy from koa
|
|
54
|
-
// Different:
|
|
55
|
-
// - change header name to lower case
|
|
56
|
-
type = getType(type);
|
|
57
|
-
if (type) {
|
|
58
|
-
this.set('content-type', type);
|
|
59
|
-
} else {
|
|
60
|
-
this.remove('content-type');
|
|
61
|
-
}
|
|
62
|
-
},
|
|
63
|
-
|
|
64
|
-
get type() {
|
|
65
|
-
// copy from koa
|
|
66
|
-
const type = this.get('content-type');
|
|
67
|
-
if (!type) return '';
|
|
68
|
-
return type.split(';')[0];
|
|
69
|
-
},
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Get or set a real status code.
|
|
73
|
-
*
|
|
74
|
-
* e.g.: Using 302 status redirect to the global error page
|
|
75
|
-
* instead of show current 500 status page.
|
|
76
|
-
* And access log should save 500 not 302,
|
|
77
|
-
* then the `realStatus` can help us find out the real status code.
|
|
78
|
-
* @member {Number} Response#realStatus
|
|
79
|
-
* @return {Number} The status code to be set.
|
|
80
|
-
*/
|
|
81
|
-
get realStatus() {
|
|
82
|
-
if (this[REAL_STATUS]) {
|
|
83
|
-
return this[REAL_STATUS];
|
|
84
|
-
}
|
|
85
|
-
return this.status;
|
|
86
|
-
},
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Set a real status code.
|
|
90
|
-
*
|
|
91
|
-
* e.g.: Using 302 status redirect to the global error page
|
|
92
|
-
* instead of show current 500 status page.
|
|
93
|
-
* And access log should save 500 not 302,
|
|
94
|
-
* then the `realStatus` can help us find out the real status code.
|
|
95
|
-
* @member {Number} Response#realStatus
|
|
96
|
-
* @param {Number} status The status code to be set.
|
|
97
|
-
*/
|
|
98
|
-
set realStatus(status) {
|
|
99
|
-
this[REAL_STATUS] = status;
|
|
100
|
-
},
|
|
101
|
-
};
|