From 20e8a6dbf5a11c3731c068654ccb5650db52f1d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Poullain?= Date: Thu, 22 Aug 2024 16:25:01 +0200 Subject: [PATCH] Make Context.state type to "{}" by default --- docs/blog/version-5.0-release-notes.md | 37 ++++++++++++++++++- docs/docs/architecture/controllers.md | 2 +- docs/docs/architecture/hooks.md | 4 +- .../forwarding-data-between-hooks.feature.ts | 4 +- packages/core/src/core/http/context.ts | 2 +- .../src/architecture/websocket-context.ts | 2 +- 6 files changed, 42 insertions(+), 9 deletions(-) diff --git a/docs/blog/version-5.0-release-notes.md b/docs/blog/version-5.0-release-notes.md index b90ed058de..5fcc7c2dec 100644 --- a/docs/blog/version-5.0-release-notes.md +++ b/docs/blog/version-5.0-release-notes.md @@ -18,7 +18,40 @@ Version 5.0 of [Foal](https://foalts.org/) is out! - Support for Node 18 has been dropped and support for Node 22 has been added. -## Removal of depreacted components +## Better typing -- The deprecated hook `@Log` has been removed. To replace it, you can use the `Logger` service in a custom `@Hook`. +- The default type of `Context.state` is now `{}`. This way, you'll get a compilation error if you forget to specify a type for the state. + + ```typescript + // Version 4 + class MyController { + @Get('/foobar') + foobar(ctx: Context) { + // Does not throw. + console.log(ctx.state.shoppingCart); + } + } + + // Version 5 + class MyController { + @Get('/foobar') + foobar(ctx: Context) { + // Throws a compilation error: Property 'shoppingCart' does not exist on type '{}'.ts(2339) + console.log(ctx.state.shoppingCart); + } + } + + // Version 5 (without error) + class MyController { + @Get('/foobar') + foobar(ctx: Context) { + console.log(ctx.state.shoppingCart); + } + } + + ``` + +## Removal of deprecated components + +- The deprecated hook `@Log` has been removed. Use the `Logger` service in a custom `@Hook` instead. - The command alias `npx foal run-script` has been removed. Use `npx foal run` instead. \ No newline at end of file diff --git a/docs/docs/architecture/controllers.md b/docs/docs/architecture/controllers.md index 2607e8f8e4..6e279ec098 100644 --- a/docs/docs/architecture/controllers.md +++ b/docs/docs/architecture/controllers.md @@ -100,7 +100,7 @@ It has seven properties: | Name | Type | Description | | --- | --- | --- | | `request` | `Request` | Gives information about the HTTP request. | -| `state` | `{ [key: string]: any }` | Object which can be used to forward data accross several hooks (see [Hooks](./hooks.md)). | +| `state` | `{ [key: string]: any } = {}` | Object which can be used to forward data accross several hooks (see [Hooks](./hooks.md)). | | `user` | `{ [key: string]: any }`\|`null` | The current user (see [Authentication](../authentication/quick-start.md)). | | `session`| `Session`\|`null` | The session object if you use sessions. | | `files` | `FileList` | A list of file paths or buffers if you uploaded files (see [Upload and download files](../common/file-storage/upload-and-download-files.md)). | diff --git a/docs/docs/architecture/hooks.md b/docs/docs/architecture/hooks.md index 5bea7760a8..1927e5f5e6 100644 --- a/docs/docs/architecture/hooks.md +++ b/docs/docs/architecture/hooks.md @@ -465,7 +465,7 @@ import { Context, Get, Hook, HttpResponseOK, UserRequired } from '@foal/core'; import { Org } from '../entities'; function AddOrgToContext() { - return Hook(async ctx => { + return Hook(async (ctx: Context) => { if (ctx.user) { ctx.state.org = await Org.findOneByOrFail({ id: ctx.user.orgId }); } @@ -477,7 +477,7 @@ export class ApiController { @Get('/org-name') @UserRequired() @AddOrgToContext() - readOrgName(ctx: Context) { + readOrgName(ctx: Context) { return new HttpResponseOK(ctx.state.org.name); } diff --git a/packages/acceptance-tests/src/docs/architecture/hooks/forwarding-data-between-hooks.feature.ts b/packages/acceptance-tests/src/docs/architecture/hooks/forwarding-data-between-hooks.feature.ts index e862098042..bd92bf967d 100644 --- a/packages/acceptance-tests/src/docs/architecture/hooks/forwarding-data-between-hooks.feature.ts +++ b/packages/acceptance-tests/src/docs/architecture/hooks/forwarding-data-between-hooks.feature.ts @@ -21,7 +21,7 @@ describe('Feature: Forwarding data betweens hooks', () => { /* ======================= DOCUMENTATION BEGIN ======================= */ function AddOrgToContext() { - return Hook(async ctx => { + return Hook(async (ctx: Context) => { if (ctx.user) { ctx.state.org = await Org.findOneByOrFail({ id: ctx.user.orgId }); } @@ -33,7 +33,7 @@ describe('Feature: Forwarding data betweens hooks', () => { @Get('/org-name') @UserRequired() @AddOrgToContext() - readOrgName(ctx: Context) { + readOrgName(ctx: Context) { return new HttpResponseOK(ctx.state.org.name); } diff --git a/packages/core/src/core/http/context.ts b/packages/core/src/core/http/context.ts index f0db4e3c1f..18522ad192 100644 --- a/packages/core/src/core/http/context.ts +++ b/packages/core/src/core/http/context.ts @@ -114,7 +114,7 @@ interface Request extends IncomingMessage { * @class Context * @template User */ -export class Context { +export class Context { readonly request: Request; session: Session | null; diff --git a/packages/socket.io/src/architecture/websocket-context.ts b/packages/socket.io/src/architecture/websocket-context.ts index d6114ed549..ba8156802e 100644 --- a/packages/socket.io/src/architecture/websocket-context.ts +++ b/packages/socket.io/src/architecture/websocket-context.ts @@ -17,7 +17,7 @@ import { Session } from '@foal/core'; * @template ContextSession * @template ContextState */ -export class WebsocketContext { +export class WebsocketContext { readonly socket: Socket; session: Session | null;