diff --git a/example/extend/Context.ts b/example/extend/Context.ts new file mode 100644 index 000000000..254e47b05 --- /dev/null +++ b/example/extend/Context.ts @@ -0,0 +1,7 @@ +import { Context } from '../../src/index.js'; + +export class CustomContext extends Context { + get state() { + return { foo: 'bar' }; + } +} diff --git a/src/context.ts b/src/context.ts index 004970923..2d676f425 100644 --- a/src/context.ts +++ b/src/context.ts @@ -17,15 +17,14 @@ export class Context { res: ServerResponse; request: Request & AnyProto; response: Response & AnyProto; - state: Record; originalUrl: string; respond?: boolean; + #state: Record = {}; constructor(app: Application, req: IncomingMessage, res: ServerResponse) { this.app = app; this.req = req; this.res = res; - this.state = {}; this.request = new app.RequestClass(app, this, req, res); this.response = new app.ResponseClass(app, this as any, req, res); this.request.response = this.response; @@ -219,6 +218,10 @@ export class Context { set cookies(cookies: Cookies) { this._cookies = cookies; } + + get state() { + return this.#state; + } } /** diff --git a/src/request.ts b/src/request.ts index d8929fac5..0c16b49d0 100644 --- a/src/request.ts +++ b/src/request.ts @@ -12,6 +12,10 @@ import type { Application } from './application.js'; import type { ContextDelegation } from './context.js'; import type { Response } from './response.js'; +export interface RequestSocket extends Socket { + encrypted: boolean; +} + export class Request { [key: symbol]: unknown; app: Application; @@ -299,7 +303,7 @@ export class Request { * Return the request socket. */ get socket() { - return this.req.socket as (Socket & { encrypted: boolean; }); + return this.req.socket as RequestSocket; } /** diff --git a/test/application/index.test.ts b/test/application/index.test.ts index d02765f51..a9c5031c1 100644 --- a/test/application/index.test.ts +++ b/test/application/index.test.ts @@ -117,4 +117,15 @@ describe('app', () => { throw CreateError(500, 'test error'); }, Koa.HttpError); }); + + it('should print object work', () => { + const app = new Koa(); + const ctx = (app as any).createContext({} as any, { + getHeaders() {}, + } as any); + console.log(ctx.request); + console.log(ctx.response); + console.log(ctx.context); + console.log(app); + }); }); diff --git a/test/context/state.test.ts b/test/context/state.test.ts index 455dddfbf..5908f5304 100644 --- a/test/context/state.test.ts +++ b/test/context/state.test.ts @@ -8,6 +8,35 @@ describe('ctx.state', () => { app.use(ctx => { assert.deepStrictEqual(ctx.state, {}); + ctx.state.user = 'example'; + }); + + app.use(ctx => { + assert.deepStrictEqual(ctx.state, { user: 'example' }); + }); + + const server = app.listen(); + + return request(server) + .get('/') + .expect(404); + }); + + it('should override state getter', () => { + const app = new Koa(); + app.ContextClass = class extends app.ContextClass { + get state(): Record { + return { foo: 'bar' }; + } + }; + + app.use(ctx => { + assert.deepStrictEqual(ctx.state, { foo: 'bar' }); + (ctx.state as any).user = 'example'; + }); + + app.use(ctx => { + assert.deepStrictEqual(ctx.state, { foo: 'bar' }); }); const server = app.listen();