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.
Files changed (117) hide show
  1. package/README.md +1 -0
  2. package/README.zh-CN.md +1 -0
  3. package/dist/commonjs/app/extend/context.d.ts +154 -0
  4. package/dist/commonjs/app/extend/context.js +261 -0
  5. package/dist/commonjs/app/extend/context.types.d.ts +16 -0
  6. package/dist/commonjs/app/extend/context.types.js +3 -0
  7. package/dist/commonjs/app/extend/helper.d.ts +37 -0
  8. package/dist/commonjs/app/extend/helper.js +49 -0
  9. package/dist/commonjs/app/extend/request.d.ts +128 -0
  10. package/dist/commonjs/app/extend/request.js +270 -0
  11. package/dist/commonjs/app/extend/response.d.ts +25 -0
  12. package/dist/commonjs/app/extend/response.js +37 -0
  13. package/dist/commonjs/app/middleware/meta.d.ts +2 -3
  14. package/dist/commonjs/app/middleware/meta.js +1 -1
  15. package/dist/commonjs/app/middleware/notfound.d.ts +2 -3
  16. package/dist/commonjs/app/middleware/notfound.js +1 -1
  17. package/dist/commonjs/app/middleware/site_file.d.ts +5 -3
  18. package/dist/commonjs/app/middleware/site_file.js +21 -3
  19. package/dist/commonjs/config/config.default.js +5 -4
  20. package/dist/commonjs/config/plugin.js +3 -3
  21. package/dist/commonjs/index.d.ts +3 -1
  22. package/dist/commonjs/index.js +8 -6
  23. package/dist/commonjs/lib/application.d.ts +5 -12
  24. package/dist/commonjs/lib/application.js +9 -20
  25. package/dist/commonjs/lib/core/base_context_class.d.ts +2 -2
  26. package/dist/commonjs/lib/core/base_hook_class.d.ts +1 -1
  27. package/dist/commonjs/lib/core/context_httpclient.d.ts +3 -3
  28. package/dist/commonjs/lib/core/context_httpclient.js +1 -1
  29. package/dist/commonjs/lib/core/httpclient.d.ts +2 -3
  30. package/dist/commonjs/lib/core/httpclient.js +3 -6
  31. package/dist/commonjs/lib/core/messenger/IMessenger.d.ts +3 -3
  32. package/dist/commonjs/lib/core/messenger/index.js +2 -2
  33. package/dist/commonjs/lib/core/messenger/ipc.d.ts +6 -4
  34. package/dist/commonjs/lib/core/messenger/ipc.js +31 -20
  35. package/dist/commonjs/lib/core/messenger/local.d.ts +3 -3
  36. package/dist/commonjs/lib/core/messenger/local.js +14 -11
  37. package/dist/commonjs/lib/egg.d.ts +25 -16
  38. package/dist/commonjs/lib/egg.js +44 -22
  39. package/dist/commonjs/lib/egg.types.d.ts +6 -0
  40. package/dist/commonjs/lib/egg.types.js +3 -0
  41. package/dist/commonjs/lib/type.d.ts +3 -5
  42. package/dist/commonjs/lib/utils.d.ts +2 -0
  43. package/dist/commonjs/lib/utils.js +21 -0
  44. package/dist/commonjs/urllib.d.ts +1 -0
  45. package/dist/commonjs/urllib.js +18 -0
  46. package/dist/esm/app/extend/context.d.ts +154 -0
  47. package/dist/esm/app/extend/context.js +255 -0
  48. package/dist/esm/app/extend/context.types.d.ts +16 -0
  49. package/dist/esm/app/extend/context.types.js +2 -0
  50. package/dist/esm/app/extend/helper.d.ts +37 -0
  51. package/dist/esm/app/extend/helper.js +43 -0
  52. package/dist/esm/app/extend/request.d.ts +128 -0
  53. package/dist/esm/app/extend/request.js +264 -0
  54. package/dist/esm/app/extend/response.d.ts +25 -0
  55. package/dist/esm/app/extend/response.js +34 -0
  56. package/dist/esm/app/middleware/meta.d.ts +2 -3
  57. package/dist/esm/app/middleware/meta.js +1 -1
  58. package/dist/esm/app/middleware/notfound.d.ts +2 -3
  59. package/dist/esm/app/middleware/notfound.js +1 -1
  60. package/dist/esm/app/middleware/site_file.d.ts +5 -3
  61. package/dist/esm/app/middleware/site_file.js +21 -3
  62. package/dist/esm/config/config.default.js +5 -4
  63. package/dist/esm/config/plugin.js +3 -3
  64. package/dist/esm/index.d.ts +3 -1
  65. package/dist/esm/index.js +5 -4
  66. package/dist/esm/lib/application.d.ts +5 -12
  67. package/dist/esm/lib/application.js +9 -20
  68. package/dist/esm/lib/core/base_context_class.d.ts +2 -2
  69. package/dist/esm/lib/core/base_hook_class.d.ts +1 -1
  70. package/dist/esm/lib/core/context_httpclient.d.ts +3 -3
  71. package/dist/esm/lib/core/context_httpclient.js +1 -1
  72. package/dist/esm/lib/core/httpclient.d.ts +2 -3
  73. package/dist/esm/lib/core/httpclient.js +2 -2
  74. package/dist/esm/lib/core/messenger/IMessenger.d.ts +3 -3
  75. package/dist/esm/lib/core/messenger/index.js +2 -2
  76. package/dist/esm/lib/core/messenger/ipc.d.ts +6 -4
  77. package/dist/esm/lib/core/messenger/ipc.js +29 -18
  78. package/dist/esm/lib/core/messenger/local.d.ts +3 -3
  79. package/dist/esm/lib/core/messenger/local.js +14 -11
  80. package/dist/esm/lib/egg.d.ts +25 -16
  81. package/dist/esm/lib/egg.js +24 -15
  82. package/dist/esm/lib/egg.types.d.ts +6 -0
  83. package/dist/esm/lib/egg.types.js +2 -0
  84. package/dist/esm/lib/type.d.ts +3 -5
  85. package/dist/esm/lib/utils.d.ts +2 -0
  86. package/dist/esm/lib/utils.js +14 -0
  87. package/dist/esm/urllib.d.ts +1 -0
  88. package/dist/esm/urllib.js +2 -0
  89. package/dist/package.json +1 -1
  90. package/package.json +44 -29
  91. package/src/app/extend/context.ts +303 -0
  92. package/src/app/extend/context.types.ts +24 -0
  93. package/src/app/extend/{helper.js → helper.ts} +14 -13
  94. package/src/app/extend/{request.js → request.ts} +81 -79
  95. package/src/app/extend/response.ts +36 -0
  96. package/src/app/middleware/meta.ts +2 -3
  97. package/src/app/middleware/notfound.ts +2 -3
  98. package/src/app/middleware/site_file.ts +26 -7
  99. package/src/config/config.default.ts +4 -3
  100. package/src/config/plugin.ts +2 -2
  101. package/src/index.ts +5 -3
  102. package/src/lib/application.ts +14 -21
  103. package/src/lib/core/base_context_class.ts +2 -2
  104. package/src/lib/core/base_hook_class.ts +1 -1
  105. package/src/lib/core/context_httpclient.ts +3 -3
  106. package/src/lib/core/httpclient.ts +4 -5
  107. package/src/lib/core/messenger/IMessenger.ts +3 -3
  108. package/src/lib/core/messenger/index.ts +1 -1
  109. package/src/lib/core/messenger/ipc.ts +31 -20
  110. package/src/lib/core/messenger/local.ts +13 -11
  111. package/src/lib/egg.ts +60 -28
  112. package/src/lib/egg.types.ts +6 -0
  113. package/src/lib/type.ts +6 -6
  114. package/src/lib/utils.ts +16 -0
  115. package/src/urllib.ts +1 -0
  116. package/src/app/extend/context.js +0 -285
  117. 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 { fileURLToPath } from 'node:url';
7
- import { EggCore, type EggCoreContext, type EggCoreOptions } from '@eggjs/core';
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 interface EggContext extends EggCoreContext {
43
- app: EggApplicationCore;
44
- /**
45
- * Request start time
46
- * @member {Number} Context#starttime
47
- */
48
- starttime: number;
49
- /**
50
- * Request start timer using `performance.now()`
51
- * @member {Number} Context#performanceStarttime
52
- */
53
- performanceStarttime: number;
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.load();
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: object) {
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
- if (typeof __dirname !== 'undefined') {
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): EggCoreContext {
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;
@@ -0,0 +1,6 @@
1
+ declare module '@eggjs/core' {
2
+ // add EggApplicationCore overrides types
3
+ interface EggCore {
4
+ inspect(): any;
5
+ }
6
+ }
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
- type IgnoreItem = string | RegExp | ((ctx: EggCoreContext) => boolean);
20
- type IgnoreOrMatch = IgnoreItem | IgnoreItem[];
18
+ // import @eggjs/watcher types
19
+ // import '@eggjs/watcher';
21
20
 
22
- export type Next = () => Promise<void>;
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: EggCoreContext): void;
106
+ onerror(err: any, ctx: ContextDelegation): void;
107
107
  };
108
108
 
109
109
  /**
@@ -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
- };