@onebun/core 0.2.2 → 0.2.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onebun/core",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Core package for OneBun framework - decorators, DI, modules, controllers",
5
5
  "license": "LGPL-3.0",
6
6
  "author": "RemRyahirev",
@@ -3234,8 +3234,7 @@ describe('WebSocket Gateway API Documentation (docs/api/websocket.md)', () => {
3234
3234
  class TestGateway extends BaseWebSocketGateway {
3235
3235
  @OnConnect()
3236
3236
  handleConnect(@Client() client: WsClientData) {
3237
- // eslint-disable-next-line no-console
3238
- console.log(`Client ${client.id} connected`);
3237
+ this.logger.info(`Client ${client.id} connected`);
3239
3238
 
3240
3239
  return { event: 'welcome', data: { message: 'Welcome!' } };
3241
3240
  }
@@ -3252,8 +3251,7 @@ describe('WebSocket Gateway API Documentation (docs/api/websocket.md)', () => {
3252
3251
  class TestGateway extends BaseWebSocketGateway {
3253
3252
  @OnDisconnect()
3254
3253
  handleDisconnect(@Client() client: WsClientData) {
3255
- // eslint-disable-next-line no-console
3256
- console.log(`Client ${client.id} disconnected`);
3254
+ this.logger.info(`Client ${client.id} disconnected`);
3257
3255
  }
3258
3256
  }
3259
3257
 
@@ -3682,8 +3680,7 @@ describe('WebSocket Chat Example (docs/examples/websocket-chat.md)', () => {
3682
3680
 
3683
3681
  @OnConnect()
3684
3682
  async handleConnect(@Client() client: WsClientData) {
3685
- // eslint-disable-next-line no-console
3686
- console.log(`Client ${client.id} connected`);
3683
+ this.logger.info(`Client ${client.id} connected`);
3687
3684
 
3688
3685
  return {
3689
3686
  event: 'welcome',
@@ -3697,8 +3694,7 @@ describe('WebSocket Chat Example (docs/examples/websocket-chat.md)', () => {
3697
3694
 
3698
3695
  @OnDisconnect()
3699
3696
  async handleDisconnect(@Client() client: WsClientData) {
3700
- // eslint-disable-next-line no-console
3701
- console.log(`Client ${client.id} disconnected`);
3697
+ this.logger.info(`Client ${client.id} disconnected`);
3702
3698
 
3703
3699
  for (const room of client.rooms) {
3704
3700
  this.emitToRoom(room, 'user:left', {
@@ -3714,8 +3710,7 @@ describe('WebSocket Chat Example (docs/examples/websocket-chat.md)', () => {
3714
3710
  @RoomName() room: string,
3715
3711
  @PatternParams() params: { roomId: string },
3716
3712
  ) {
3717
- // eslint-disable-next-line no-console
3718
- console.log(`Client ${client.id} joining room ${params.roomId}`);
3713
+ this.logger.info(`Client ${client.id} joining room ${params.roomId}`);
3719
3714
 
3720
3715
  await this.joinRoom(client.id, room);
3721
3716
 
@@ -3981,6 +3976,52 @@ describe('WebSocket Chat Example (docs/examples/websocket-chat.md)', () => {
3981
3976
  });
3982
3977
  });
3983
3978
 
3979
+ describe('WebSocket Gateway DI (docs/api/websocket.md#basewebsocketgateway)', () => {
3980
+ /**
3981
+ * @source docs/api/websocket.md#basewebsocketgateway
3982
+ * Gateways receive this.logger and this.config just like controllers.
3983
+ */
3984
+ it('should inject logger and config into WebSocket gateway via module DI', async () => {
3985
+ const effectLib = await import('effect');
3986
+ const moduleMod = await import('./module/module');
3987
+ const testUtils = await import('./testing/test-utils');
3988
+
3989
+ @WebSocketGateway({ path: '/ws' })
3990
+ class TestGateway extends BaseWebSocketGateway {
3991
+ @OnConnect()
3992
+ handleConnect(@Client() client: WsClientData) {
3993
+ this.logger.info(`Client ${client.id} connected`);
3994
+
3995
+ return { event: 'welcome', data: { id: client.id } };
3996
+ }
3997
+
3998
+ getLoggerForTest() {
3999
+ return this.logger;
4000
+ }
4001
+
4002
+ getConfigForTest() {
4003
+ return this.config;
4004
+ }
4005
+ }
4006
+
4007
+ @Module({ controllers: [TestGateway] })
4008
+ class TestModule {}
4009
+
4010
+ const mod = new moduleMod.OneBunModule(TestModule, testUtils.makeMockLoggerLayer());
4011
+ mod.getLayer();
4012
+ await effectLib.Effect.runPromise(mod.setup() as import('effect').Effect.Effect<unknown, never, never>);
4013
+
4014
+ const gateway = mod.getControllerInstance(TestGateway) as unknown as TestGateway;
4015
+ expect(gateway).toBeDefined();
4016
+ expect(gateway.getLoggerForTest()).toBeDefined();
4017
+ expect(typeof gateway.getLoggerForTest().info).toBe('function');
4018
+ expect(typeof gateway.getLoggerForTest().warn).toBe('function');
4019
+ expect(typeof gateway.getLoggerForTest().error).toBe('function');
4020
+ expect(gateway.getConfigForTest()).toBeDefined();
4021
+ expect(typeof gateway.getConfigForTest().get).toBe('function');
4022
+ });
4023
+ });
4024
+
3984
4025
  // ============================================================================
3985
4026
  // SSE (Server-Sent Events) Documentation Tests
3986
4027
  // ============================================================================
@@ -6,6 +6,7 @@ import {
6
6
 
7
7
  import type { Controller } from './controller';
8
8
  import type { ModuleInstance } from '../types';
9
+ import type { BaseWebSocketGateway } from '../websocket/ws-base-gateway';
9
10
 
10
11
  import {
11
12
  createSyncLogger,
@@ -540,8 +541,14 @@ export class OneBunModule implements ModuleInstance {
540
541
  const controllerConstructor = controllerClass as new (...args: unknown[]) => Controller;
541
542
  const controller = new controllerConstructor(...dependencies);
542
543
 
543
- // Initialize controller with logger and config (skip for WebSocket gateways)
544
- if (!isWebSocketGateway(controllerClass) && typeof controller.initializeController === 'function') {
544
+ // Initialize controller with logger and config
545
+ if (isWebSocketGateway(controllerClass)) {
546
+ // Initialize WebSocket gateway with logger and config
547
+ const gateway = controller as unknown as BaseWebSocketGateway;
548
+ if (typeof gateway._initializeBase === 'function') {
549
+ gateway._initializeBase(this.logger, this.config);
550
+ }
551
+ } else if (typeof controller.initializeController === 'function') {
545
552
  controller.initializeController(this.logger, this.config);
546
553
  }
547
554
 
@@ -11,8 +11,11 @@ import type {
11
11
  WsRoom,
12
12
  WsServer,
13
13
  } from './ws.types';
14
+ import type { IConfig, OneBunAppConfig } from '../module/config.interface';
14
15
  import type { Server, ServerWebSocket } from 'bun';
15
16
 
17
+ import type { SyncLogger } from '@onebun/logger';
18
+
16
19
  import { createFullEventMessage, createNativeMessage } from './ws-socketio-protocol';
17
20
  import { WsStorageEvent, isPubSubAdapter } from './ws-storage';
18
21
 
@@ -45,6 +48,12 @@ export function _resetClientSocketsForTesting(): void {
45
48
  * ```
46
49
  */
47
50
  export abstract class BaseWebSocketGateway {
51
+ /** Logger instance with gateway class name as context */
52
+ protected logger!: SyncLogger;
53
+
54
+ /** Configuration instance for accessing environment variables */
55
+ protected config!: IConfig<OneBunAppConfig>;
56
+
48
57
  /** Storage adapter for persisting client/room data */
49
58
  protected storage: WsStorageAdapter | null = null;
50
59
 
@@ -58,6 +67,17 @@ export abstract class BaseWebSocketGateway {
58
67
  // Initialization
59
68
  // ============================================================================
60
69
 
70
+ /**
71
+ * Initialize the gateway with logger and config
72
+ * Called internally by the framework during DI
73
+ * @internal
74
+ */
75
+ _initializeBase(logger: SyncLogger, config: IConfig<OneBunAppConfig>): void {
76
+ const className = this.constructor.name;
77
+ this.logger = logger.child({ className });
78
+ this.config = config;
79
+ }
80
+
61
81
  /**
62
82
  * Initialize the gateway with storage and server
63
83
  * Called internally by the framework