Skip to content

[SILO-454] chore: refactor decorator, logger packages#7618

Merged
sriramveeraghanta merged 8 commits intopreviewfrom
chore/refactor-decorators-pkg
Aug 29, 2025
Merged

[SILO-454] chore: refactor decorator, logger packages#7618
sriramveeraghanta merged 8 commits intopreviewfrom
chore/refactor-decorators-pkg

Conversation

@Prashant-Surya
Copy link
Member

@Prashant-Surya Prashant-Surya commented Aug 21, 2025

Description

  • add registerControllers function abstracting both rest, ws controllers
  • update logger to a simple json based logger

Type of Change

  • Improvement (change that would cause existing functionality to not work as expected)
  • Code refactoring

Test Scenarios

References

SILO-454

Summary by CodeRabbit

  • New Features

    • Register multiple controllers at once and unified REST/WebSocket route registration.
    • Expose Rest and WebSocket decorator namespaces.
  • Bug Fixes

    • Improved WebSocket error handling: exceptions are logged and sockets closed with proper code/message.
  • Refactor

    • Removed legacy WebSocket module; consolidated controller registration.
    • Request logging replaced with express-winston middleware.
  • Chores

    • Simplified logger to console-only config.
    • Updated build scripts and pinned several dev type versions.

- add registerControllers function abstracting both rest, ws controllers
- update logger to a simple json based logger
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 21, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Controller registration now accepts multiple controllers and delegates REST vs WebSocket registration to new helpers; the dedicated websocket-controller module was removed. Decorator exports were reshaped. Logger config and middleware moved to an express-winston Console-only setup. Several package.json scripts and devDependency pins were updated.

Changes

Cohort / File(s) Summary
Controller registration refactor
packages/decorators/src/controller.ts
registerControllers signature changed to accept controllers: ControllerConstructor[] and dependencies: any[]; iterates controllers, instantiates with deps, detects ws methods, and delegates to registerRestController or registerWebSocketController. WebSocket handlers are wrapped in try/catch to log and close sockets with code 1011.
WebSocket controller removal
packages/decorators/src/websocket-controller.ts
Module removed; deleted registerWebSocketControllers, BaseWebSocketController, and related metadata-driven WebSocket registration logic.
Public exports reshaping
packages/decorators/src/index.ts
Removed registerWebSocketControllers re-export; added namespace aliases Rest (from ./rest) and WebSocketNS (from ./websocket); other decorator exports retained.
REST decorator minor formatting
packages/decorators/src/rest.ts
Minor formatting/flow changes only; API unchanged.
Decorators package metadata & formatting
packages/decorators/package.json, packages/decorators/tsconfig.json, packages/decorators/.prettierrc, packages/decorators/README.md
Build/dev scripts updated (tsc --noEmit && tsup --minify, tsup --watch); moved/removed express, ws, reflect-metadata deps/peers; added .prettierrc; trivial tsconfig/README edits.
Logger config simplification
packages/logger/src/config.ts
Replaced multi-transport/custom formatting with exported loggerConfig: LoggerOptions (level from LOG_LEVEL, timestamp + JSON, single Console transport); removed file rotation and custom printf.
Middleware switched to express-winston
packages/logger/src/middleware.ts
Replaced custom requestLogger function with loggerMiddleware: RequestHandler using express-winston.logger(...) and loggerConfig.
Logger package manifest updates
packages/logger/package.json
Removed express and winston-daily-rotate-file; added express-winston; adjusted @types/node devDependency.
Pinned @types/lodash across manifests
apps/admin/package.json, apps/space/package.json, apps/web/package.json, packages/i18n/package.json, packages/ui/package.json, packages/utils/package.json
DevDependency @types/lodash changed from ^4.17.64.17.20 (pinned exact version) in multiple manifests.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant App as App
  participant Reg as registerControllers
  participant Router as Router
  participant RestReg as registerRestController
  participant WsReg as registerWebSocketController

  App->>Reg: registerControllers(router, controllers[], deps[])
  loop each Controller
    Reg->>Reg: instantiate Controller(...deps)
    Reg->>Reg: scan metadata for methods
    alt REST methods present
      Reg->>RestReg: register REST routes
      RestReg->>Router: router[verb](path, handler)
    end
    alt WS methods present
      Reg->>WsReg: register WS routes
      WsReg->>Router: router.ws(path, async handler)
      note right of WsReg #f0f4c3: WS handler wrapped in try/catch\non error: log & ws.close(1011,msg)
    end
  end
Loading
sequenceDiagram
  autonumber
  participant Client as HTTP Client
  participant Express as Express App
  participant MW as loggerMiddleware (express-winston)
  participant Console as Console Transport

  Client->>Express: HTTP Request
  Express->>MW: Invoke loggerMiddleware
  MW->>Console: Log {method, url, status, responseTime}
  Express-->>Client: Response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • prateekshourya29

Poem

A rabbit taps routes with gentle paws,
REST and WS hop, arranged by laws.
Winston whispers to console bright,
Exports shuffled, builds take flight.
Hop — new code stitched, a merry sight! 🐇✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/refactor-decorators-pkg

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbit in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbit in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbit gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbit read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbit help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbit ignore or @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbit summary or @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbit or @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@makeplane
Copy link

makeplane bot commented Aug 21, 2025

Pull Request Linked with Plane Work Items

Comment Automatically Generated by Plane

@sriramveeraghanta sriramveeraghanta marked this pull request as ready for review August 26, 2025 13:32
Copilot AI review requested due to automatic review settings August 26, 2025 13:32
@sriramveeraghanta
Copy link
Member

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 26, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR refactors the decorator and logger packages to improve maintainability and consolidate functionality. It simplifies the logger configuration to use JSON formatting and consolidates controller registration into a single unified function.

  • Simplified logger package from a complex winston configuration to a minimal JSON-based logger using express-winston
  • Consolidated REST and WebSocket controller registration into a single registerControllers function
  • Removed redundant websocket-controller.ts file by moving functionality into controller.ts

Reviewed Changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
packages/logger/src/middleware.ts Replaced custom request logger middleware with express-winston
packages/logger/src/config.ts Simplified logger configuration to JSON format with minimal transports
packages/logger/package.json Updated dependencies to use express-winston instead of winston-daily-rotate-file
packages/decorators/src/websocket-controller.ts Removed file - functionality moved to controller.ts
packages/decorators/src/rest.ts Minor formatting change removing trailing comma
packages/decorators/src/index.ts Removed export of registerWebSocketControllers function
packages/decorators/src/controller.ts Added unified registerControllers function handling both REST and WebSocket controllers
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (1)

packages/logger/package.json:37

  • The @types/node dependency was removed but may still be needed for Node.js type definitions in the logger package. Verify that this removal doesn't break type checking.
    "tsup": "8.4.0",

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/decorators/src/controller.ts (1)

1-138: Fix missing imports and tighten controller typings in controller.ts

The recent changes introduce WebSocket handling and generic DI arrays but overlook some key type imports and leave broad any[] signatures. Please address the following:

• Add the missing Request import for the WebSocket handler callback
• Replace the loose any[] parameter types with safer alternatives (e.g. unknown[] or a specific constructor array)
• Augment or cast the Router type so that router.ws(...) is correctly typed, since Express’s Router interface doesn’t include .ws by default

Affected locations:

packages/decorators/src/controller.ts
• Line 1–2: import list
• Line 25–29: registerControllers signature
• Line 116–120: router.ws usage

Suggested diff:

--- a/packages/decorators/src/controller.ts
+++ b/packages/decorators/src/controller.ts
-import { RequestHandler, Router } from "express";
+import { RequestHandler, Router, Request } from "express";

-export function registerControllers(
-  router: Router,
-  controllers: any[],
-  dependencies: any[] = []
-): void {
+export function registerControllers(
+  router: Router,
+  controllers: Array<ControllerConstructor>,
+  dependencies: unknown[] = []
+): void {

And around the WebSocket registration:

-        if (
-          typeof handler === "function" &&
-          "ws" in router &&
-          typeof router.ws === "function"
-        ) {
-          router.ws(`${baseRoute}${route}`, (ws: WebSocket, req: Request) => {
+        // Cast to any or extend Router so `.ws` is recognized
+        const wsRouter = router as unknown as {
+          ws(path: string, cb: (ws: WebSocket, req: Request) => void): void;
+        };
+        if (typeof handler === "function") {
+          wsRouter.ws(`${baseRoute}${route}`, (ws: WebSocket, req: Request) => {

These changes will restore proper typing for Request, eliminate unsafe any[], and ensure router.ws compiles without errors.

🧹 Nitpick comments (11)
packages/decorators/src/controller.ts (7)

27-29: Tighten types for controllers/dependencies (resolves “Unexpected any” warnings)

Use concrete constructor and unknown[] instead of any[]. Addresses static analysis warnings at these lines.

-export function registerControllers(
-  router: Router,
-  controllers: any[],
-  dependencies: any[] = []
-): void {
+export function registerControllers(
+  router: Router,
+  controllers: ControllerConstructor[],
+  dependencies: unknown[] = []
+): void {

Optional: make this generic to improve inference for shared DI tuples:

export function registerControllers<D extends unknown[]>(
  router: Router,
  controllers: Array<new (...args: D) => ControllerInstance>,
  dependencies: D = [] as unknown as D
): void { /* ... */ }

105-110: Unify metadata type: cast to HttpMethod, not string

Minor consistency tweak; keeps types aligned across REST/WS paths.

-    ) as string;
+    ) as HttpMethod;

58-60: Guard against missing @controller decorator (baseRoute may be undefined)

If a controller lacks the @Controller class decorator, baseRoute metadata is undefined, leading to paths like undefined/users. Provide a safe default.

-  const baseRoute = Reflect.getMetadata("baseRoute", Controller) as string;
+  const baseRoute =
+    (Reflect.getMetadata("baseRoute", Controller) as string | undefined) ?? "";

Apply in both REST and WS registration helpers.

Also applies to: 100-101


120-133: Optional: replace console.error with pluggable logger to align with “simple JSON-based logger”

To keep this package logger-agnostic yet align with the PR’s logging direction, accept an optional logger in dependencies or via a lightweight hook, and fall back to console.error. Keeps separation of concerns.


61-91: Minor: bind handler once and avoid unknown

Not critical, but you can narrow the handler type and bind once for clarity.

-      const handler = instance[methodName] as unknown;
+      const handler = instance[methodName] as unknown as RequestHandler;
       if (typeof handler === "function") {
         if (method !== "ws") {
           (
             router[method] as (
               path: string,
               ...handlers: RequestHandler[]
             ) => void
-          )(`${baseRoute}${route}`, ...middlewares, handler.bind(instance));
+          )(`${baseRoute}${route}`, ...middlewares, handler.bind(instance));
         }
       }

30-42: Note on WS detection heuristic

The isWebsocket flag is derived from any method tagged "ws". With the earlier change to always register both, this heuristic becomes optional. If you keep it, it can be repurposed for minor optimizations (skip WS registration when no WS methods exist).


25-33: Consider exposing a typed Controller type in public API

Right now ControllerConstructor and ControllerInstance are internal. Exposing them (or a subset) would let apps type their controller arrays without any escape hatches.

I can draft a minimal types.ts and re-export it for consumers if helpful.

packages/logger/src/config.ts (1)

3-11: Capture error stacks and harden the logger for exceptions/rejections

Adding errors({ stack: true }) preserves stack traces, and dedicated handlers prevent process crashes on unhandled errors while keeping output JSON-only.

Apply:

 export const loggerConfig: LoggerOptions = {
   level: process.env.LOG_LEVEL || "info",
   format: format.combine(
+    format.errors({ stack: true }),
     format.timestamp({
       format: "YYYY-MM-DD HH:mm:ss.SSS",
     }),
     format.json()
   ),
-  transports: [new transports.Console()],
+  transports: [new transports.Console()],
+  exceptionHandlers: [new transports.Console()],
+  rejectionHandlers: [new transports.Console()],
+  exitOnError: false,
 };
packages/logger/src/middleware.ts (3)

6-7: Drop redundant transports override

loggerConfig already specifies Console transport; overriding it here adds duplication and future drift.

Apply:

-  ...loggerConfig,
-  transports: [new transports.Console()],
+  ...loggerConfig,

9-9: Remove expressFormat when emitting JSON

expressFormat is for morgan-style human logs; with format.json() in loggerConfig you’ll get a JSON object with a “message” field set from msg. expressFormat adds no value and can confuse expectations.

Apply:

-  expressFormat: true,

5-5: Type the middleware without reintroducing express types

To avoid any, but also not depend on @types/express, you can expose the inferred type from express-winston without leaking express types in your API surface by exporting a function factory instead of a concrete instance. That defers typing to the app layer.

Example:

-import expressWinston from "express-winston";
+import expressWinston from "express-winston";
 
-export const loggerMiddleware: any = expressWinston.logger({
+export const createLoggerMiddleware = () =>
+  expressWinston.logger({
     ...loggerConfig,
     msg: "{{req.method}} {{req.url}} {{res.statusCode}} {{res.responseTime}}ms",
-    expressFormat: true,
-});
+    meta: false,
+    statusLevels: true,
+  });

Consumers call createLoggerMiddleware() in their Express app, getting proper types from their own express install.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3602ff6 and e2fa03d.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (7)
  • packages/decorators/src/controller.ts (4 hunks)
  • packages/decorators/src/index.ts (0 hunks)
  • packages/decorators/src/rest.ts (1 hunks)
  • packages/decorators/src/websocket-controller.ts (0 hunks)
  • packages/logger/package.json (1 hunks)
  • packages/logger/src/config.ts (1 hunks)
  • packages/logger/src/middleware.ts (1 hunks)
💤 Files with no reviewable changes (2)
  • packages/decorators/src/websocket-controller.ts
  • packages/decorators/src/index.ts
🧰 Additional context used
🧬 Code graph analysis (3)
packages/logger/src/middleware.ts (1)
packages/logger/src/config.ts (1)
  • loggerConfig (3-12)
packages/decorators/src/controller.ts (3)
packages/decorators/src/rest.ts (1)
  • Controller (12-17)
packages/decorators/src/index.ts (2)
  • Controller (2-2)
  • WebSocket (4-4)
packages/decorators/src/websocket.ts (1)
  • WebSocket (8-13)
packages/logger/src/config.ts (1)
apps/live/src/core/helpers/logger.ts (1)
  • logger (22-37)
🪛 GitHub Check: Build and lint web apps
packages/decorators/src/controller.ts

[warning] 28-28:
Unexpected any. Specify a different type


[warning] 27-27:
Unexpected any. Specify a different type

🔇 Additional comments (8)
packages/decorators/src/rest.ts (1)

24-26: LGTM: non-functional formatting change only

Removing the trailing comma in the factory arg list is a no-op; decorators’ behavior and metadata remain intact.

packages/decorators/src/controller.ts (4)

94-102: WS helper mirrors REST helper nicely

Separation of concerns and reuse of baseRoute logic look good; the try/catch around handler invocation is a good safety net for WS handlers.


121-133: WS error handling is pragmatic

Closing with 1011 and surfacing the error message is reasonable. Once a pluggable logger is available, route these logs through it.


61-76: Middleware metadata handling looks correct

Fetching, defaulting to [], and spreading into the route registration matches the REST decorator semantics.


77-89: Route registration binding is correct

handler.bind(instance) ensures this correctness for controller methods.

packages/logger/package.json (1)

31-32: Peer dependency compatibility verified; run security audit before merging

The peerDependency for express-winston@4.2.0 is winston >=3.x <4, and your logger’s package.json pins "winston": "^3.17.0", so the versions align correctly.

Please perform a fresh install and run a non-dev security audit on the packages/logger workspace to catch any potential vulnerabilities:

npm install
npm audit --workspace=packages/logger --omit=dev
packages/logger/src/config.ts (1)

14-14: LGTM: central logger export

Centralizing createLogger(loggerConfig) is clean and keeps consumers consistent.

packages/logger/src/middleware.ts (1)

8-8: No action needed: {{res.responseTime}} is supported in express-winston v4.x

According to the official express-winston README, the msg option examples include the {{res.responseTime}}ms token to interpolate the response time when logging HTTP requests. This placeholder is valid in v4.x out of the box, so you can safely leave your template as-is.

  • Example from the v4.x README: msg: "{{res.statusCode}} {{req.method}} {{res.responseTime}}ms {{req.url}}" (github.com)
  • The same usage is documented in the npm package description for v1.x (which the v4.x README mirrors): msg: "{{res.statusCode}} {{req.method}} {{res.responseTime}}ms {{req.url}}" (npmjs.com)

If you ever need to log responseTime at the root level instead of under res, you can alternatively use {{responseTime}} or configure dynamicMeta, but no change is required for the current setup.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (6)
packages/decorators/src/controller.ts (4)

25-29: Improve type safety for controller parameters.

The use of any[] for both controllers and dependencies parameters removes type safety, as noted in previous reviews.

Apply this diff to improve type safety:

 export function registerControllers(
   router: Router,
-  controllers: ControllerConstructor[],
-  dependencies: any[] = []
+  controllers: ControllerConstructor[],
+  dependencies: unknown[] = []
 ): void {

The controllers parameter is already properly typed, but dependencies should use unknown[] instead of any[] for better type safety.


30-52: Critical logic flaw: Mixed controllers and REST dependency injection.

The current implementation has two significant issues:

  1. Mixed controllers aren't fully supported: A controller with both REST and WebSocket methods will only be registered as WebSocket, skipping all REST endpoints.

  2. REST controllers lose dependency injection: REST registration creates a new instance without dependencies, breaking controllers that require constructor arguments.

Apply this diff to fix both issues:

-    if (isWebsocket) {
-      // Register as WebSocket controller
-      // Pass the existing instance with dependencies to avoid creating a new instance without them
-      registerWebSocketController(router, Controller, instance);
-    } else {
-      // Register as REST controller - doesn't accept an instance parameter
-      registerRestController(router, Controller);
-    }
+    // Register both REST and WebSocket handlers if present, using the same DI-backed instance
+    registerRestController(router, Controller, instance);
+    registerWebSocketController(router, Controller, instance);

This ensures the same dependency-injected instance is used for both registrations and supports controllers with mixed REST/WebSocket methods.


54-57: Update REST controller to accept existing instance.

The registerRestController function needs to accept an optional existing instance to support dependency injection properly.

Apply this diff to support dependency injection:

 function registerRestController(
   router: Router,
-  Controller: ControllerConstructor
+  Controller: ControllerConstructor,
+  existingInstance?: ControllerInstance
 ): void {
-  const instance = new Controller();
+  const instance = existingInstance ?? new Controller();

115-121: Fix TypeScript error with Router.ws access.

TypeScript will fail because router.ws is not part of the Express Router type definition. The current dot notation access will cause compilation errors.

Apply this diff to fix the type error:

       if (
         typeof handler === "function" &&
-        "ws" in router &&
-        typeof router.ws === "function"
+        "ws" in (router as any) &&
+        typeof (router as any).ws === "function"
       ) {
-        router.ws(`${baseRoute}${route}`, (ws: WebSocket, req: Request) => {
+        (router as any).ws(`${baseRoute}${route}`, (ws: WebSocket, req: Request) => {
packages/logger/src/middleware.ts (2)

1-1: Good: explicit RequestHandler typing resolves prior feedback.

Exporting a concrete Express RequestHandler type is clear and helps consumers.


6-11: Disable meta logging to avoid leaking PII/secrets; add sane levels and ignore health.

With express-winston, meta is true by default and can include headers (Authorization/Cookie), bodies, and other sensitive fields. For lean JSON lines, explicitly disable meta and map status codes to log levels; also consider ignoring health probes.

Apply this diff:

 export const loggerMiddleware: RequestHandler = expressWinston.logger({
   ...loggerConfig,
-  transports: [new transports.Console()],
-  msg: "{{req.method}} {{req.url}} {{res.statusCode}} {{res.responseTime}}ms",
-  expressFormat: true,
+  msg: "{{req.method}} {{req.url}} {{res.statusCode}} {{res.responseTime}}ms",
+  meta: false,
+  statusLevels: true, // 5xx=error, 4xx=warn, else=info
+  ignoreRoute: (req) => req.url === "/health" || req.url === "/ready",
 });

If you need selected metadata later, flip meta: true and add strict requestFilter/responseFilter to strip bodies and headers; I can draft that variant.

🧹 Nitpick comments (3)
packages/logger/package.json (1)

30-33: Declare Express as a peer dependency for clearer integration contracts.

This package ships Express middleware. Depending apps should provide their own Express version to avoid duplicate instances/mismatches. Add a peerDependency instead of bundling Express here.

Apply this diff:

   "dependencies": {
     "express-winston": "^4.2.0",
     "winston": "^3.17.0"
   },
+  "peerDependencies": {
+    "express": "^4.17.0"
+  },
packages/logger/src/middleware.ts (2)

9-10: Avoid mixing msg and expressFormat; pick one to prevent confusion.

Setting both is redundant; msg overrides the morgan-style message. Use only the custom msg (recommended for stable JSON).

Apply this minimal diff if you prefer morgan-style instead:

-  msg: "{{req.method}} {{req.url}} {{res.statusCode}} {{res.responseTime}}ms",
-  expressFormat: true,
+  expressFormat: true,

Or keep msg and drop expressFormat as shown in the earlier diff.


3-3: Remove unused import after dropping explicit transports override.

Once transports are sourced exclusively from loggerConfig, this import becomes unused.

-import { transports } from "winston";
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e2fa03d and b77da77.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (5)
  • packages/decorators/package.json (1 hunks)
  • packages/decorators/src/controller.ts (4 hunks)
  • packages/decorators/tsconfig.json (0 hunks)
  • packages/logger/package.json (1 hunks)
  • packages/logger/src/middleware.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • packages/decorators/tsconfig.json
🧰 Additional context used
🧬 Code graph analysis (2)
packages/logger/src/middleware.ts (1)
packages/logger/src/config.ts (1)
  • loggerConfig (3-12)
packages/decorators/src/controller.ts (3)
packages/decorators/src/rest.ts (1)
  • Controller (12-17)
packages/decorators/src/index.ts (2)
  • Controller (2-2)
  • WebSocket (4-4)
packages/decorators/src/websocket.ts (1)
  • WebSocket (8-13)
🪛 GitHub Check: Build and lint web apps
packages/decorators/src/controller.ts

[warning] 28-28:
Unexpected any. Specify a different type

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (4)
packages/decorators/package.json (2)

14-15: Simplified build configuration looks good.

The updated build and dev scripts are cleaner and leverage tsup's default configuration. The removal of explicit --external flags suggests dependencies are now handled differently (likely through the tsup config or peer dependencies).


29-29: Good move to devDependencies.

Moving reflect-metadata to devDependencies is appropriate since it's only needed at build time for metadata generation, not at runtime.

packages/decorators/src/controller.ts (2)

1-2: Good addition of missing type imports.

The Request and WebSocket type imports are now properly included, resolving the TypeScript compilation issues flagged in previous reviews.


121-133: Good WebSocket error handling implementation.

The error handling wrapper for WebSocket handlers is well-implemented with proper error logging and graceful connection closure using the appropriate WebSocket close codes.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
packages/utils/package.json (1)

39-39: Centralize @types/lodash pin and verify types locally

  • 🔍 Confirmed a single version (4.17.20) of @types/lodash is installed across the monorepo (pnpm-lock.yaml) [run-scripts output].

  • ⚠️ Automated type-check script (check:types) isn’t defined in several workspaces, so please run your local type checks after installing dependencies:

    pnpm install
    pnpm run check:types   # or your project’s equivalent type-check command
  • 💡 To avoid having to bump each package’s @types/lodash entry, add a root-level override/resolution in package.json:

    For npm:

    {
      "overrides": {
        "@types/lodash": "4.17.20"
      }
    }

    For pnpm:

    {
      "pnpm": {
        "overrides": {
          "@types/lodash": "4.17.20"
        }
      }
    }

    For Yarn (Berry):

    {
      "resolutions": {
        "@types/lodash": "4.17.20"
      }
    }
packages/i18n/package.json (1)

28-28: Good pin; matches lodash v4 and reduces unexpected DT drift.

No functional impact at runtime; only TS types. Keep this consistent across the repo or consider a root-level override as noted in utils.

apps/web/package.json (1)

75-75: Pin looks good; keep @types scoped to devDependencies (as done here).

This avoids shipping type packages to prod images. No additional changes needed.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between b77da77 and f56d39d.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (6)
  • apps/admin/package.json (1 hunks)
  • apps/space/package.json (1 hunks)
  • apps/web/package.json (1 hunks)
  • packages/i18n/package.json (1 hunks)
  • packages/ui/package.json (1 hunks)
  • packages/utils/package.json (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • apps/space/package.json
  • apps/admin/package.json
🔇 Additional comments (1)
packages/ui/package.json (1)

69-69: LGTM on pinning @types/lodash; aligns with other workspaces.

No concerns. Ensure Storybook type checks still pass with TS 5.8.3 (covered by the verification script suggested in utils).

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f56d39d and 63d9523.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (1)
  • packages/decorators/package.json (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build and lint web apps
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (2)
packages/decorators/package.json (2)

16-16: Lint budget raised to 1 warning — confirm intent

Allowing warnings can hide regressions. If unintentional, revert to 0.

-    "check:lint": "eslint . --max-warnings 1",
+    "check:lint": "eslint . --max-warnings 0",

14-16: Install dependencies and verify build artifacts
The build failed with “tsc: not found,” so ensure workspace dependencies are installed (e.g. run npm install or your monorepo install command at the repo root) before rerunning the build. Then in packages/decorators, run:

npm run build
ls dist
# confirm dist/index.js, dist/index.mjs, and dist/index.d.ts exist

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (4)
packages/decorators/src/controller.ts (4)

18-21: Tighten types for dependencies (avoid any[]); consider generics to bind DI args to constructors.

Current any[] loses type-safety. Minimal: switch to unknown[]. Better: generic D extends unknown[] across the API.

Minimal change:

-  controllers: ControllerConstructor[],
-  dependencies: any[] = []
+  controllers: ControllerConstructor[],
+  dependencies: unknown[] = []

Stronger generic alternative (optional):

-type ControllerConstructor {
-  new (...args: unknown[]): ControllerInstance;
-  prototype: ControllerInstance;
-}
+type ControllerConstructor<D extends unknown[] = unknown[]> =
+  (new (...args: D) => ControllerInstance) & { prototype: ControllerInstance };
@@
-export function registerControllers(
-  router: Router,
-  controllers: ControllerConstructor[],
-  dependencies: any[] = []
-): void {
+export function registerControllers<D extends unknown[]>(
+  router: Router,
+  controllers: ControllerConstructor<D>[],
+  dependencies: D = [] as unknown as D
+): void {

If you take the generic route, update helper signatures similarly (Controller: ControllerConstructor).


22-41: Don’t drop REST when WS is present; reuse the same DI-backed instance for both.

Mixed controllers (having both REST and WS methods) currently register only WS; REST is skipped. Also, REST re-instantiates without DI. Always register both using the same instance.

-    // Determine if it's a WebSocket controller or REST controller by checking
-    // if it has any methods with the "ws" method metadata
-    const isWebsocket = Object.getOwnPropertyNames(Controller.prototype).some((methodName) => {
-      if (methodName === "constructor") return false;
-      return Reflect.getMetadata("method", instance, methodName) === "ws";
-    });
-
-    if (isWebsocket) {
-      // Register as WebSocket controller
-      // Pass the existing instance with dependencies to avoid creating a new instance without them
-      registerWebSocketController(router, Controller, instance);
-    } else {
-      // Register as REST controller - doesn't accept an instance parameter
-      registerRestController(router, Controller);
-    }
+    // Register both REST and WS handlers (if present) using the same DI-backed instance.
+    registerRestController(router, Controller, instance);
+    registerWebSocketController(router, Controller, instance);

44-46: Propagate DI instance into REST; guard against missing baseRoute.

REST path ignores DI and can produce “undefined/…” routes if the class lacks @controller. Accept an existing instance and default baseRoute.

-function registerRestController(router: Router, Controller: ControllerConstructor): void {
-  const instance = new Controller();
-  const baseRoute = Reflect.getMetadata("baseRoute", Controller) as string;
+function registerRestController(
+  router: Router,
+  Controller: ControllerConstructor,
+  existingInstance?: ControllerInstance
+): void {
+  const instance = existingInstance ?? new Controller();
+  const baseRoute = (Reflect.getMetadata("baseRoute", Controller) as string) || "";

88-97: Fix TS type error: Router.ws isn’t on Express’ Router; also avoid leaking error details to clients.

Accessing router.ws fails type-checking; narrow/cast before use. Return a generic WS close reason and log details server-side only.

-      if (typeof handler === "function" && "ws" in router && typeof router.ws === "function") {
-        router.ws(`${baseRoute}${route}`, (ws: WebSocket, req: Request) => {
-          try {
-            handler.call(instance, ws, req);
-          } catch (error) {
-            console.error(`WebSocket error in ${Controller.name}.${methodName}`, error);
-            ws.close(1011, error instanceof Error ? error.message : "Internal server error");
-          }
-        });
-      }
+      if (typeof handler === "function") {
+        const wsRouter = router as Router & {
+          ws?: (path: string, handler: (ws: WebSocket, req: Request) => void) => void;
+        };
+        if (typeof wsRouter.ws === "function") {
+          wsRouter.ws(`${baseRoute}${route}`, (ws: WebSocket, req: Request) => {
+            try {
+              handler.call(instance, ws, req);
+            } catch (error) {
+              console.error(`WebSocket error in ${Controller.name}.${methodName}`, error);
+              ws.close(1011, "Internal server error");
+            }
+          });
+        }
+      }
🧹 Nitpick comments (1)
packages/decorators/src/controller.ts (1)

71-100: WebSocket wiring is solid with error handling; consider pluggable logger.

Runtime try/catch and 1011 close are good. Optionally inject a logger or use your new JSON logger to keep consistency across packages.

I can wire this to your JSON logger (or accept a logger param with a default) if you want a commit-ready patch.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 63d9523 and 5f6fc47.

📒 Files selected for processing (4)
  • packages/decorators/.prettierrc (1 hunks)
  • packages/decorators/README.md (1 hunks)
  • packages/decorators/src/controller.ts (2 hunks)
  • packages/decorators/src/rest.ts (2 hunks)
✅ Files skipped from review due to trivial changes (2)
  • packages/decorators/.prettierrc
  • packages/decorators/README.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/decorators/src/rest.ts
🧰 Additional context used
🧬 Code graph analysis (1)
packages/decorators/src/controller.ts (2)
packages/decorators/src/rest.ts (1)
  • Controller (12-17)
packages/decorators/src/websocket.ts (1)
  • WebSocket (8-13)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Analyze (javascript)
  • GitHub Check: Build and lint web apps
🔇 Additional comments (1)
packages/decorators/src/controller.ts (1)

51-64: REST wiring looks correct.

Metadata usage, middleware application, and handler binding are fine.

@sriramveeraghanta sriramveeraghanta merged commit 258d24b into preview Aug 29, 2025
6 of 7 checks passed
@sriramveeraghanta sriramveeraghanta deleted the chore/refactor-decorators-pkg branch August 29, 2025 08:59
@coderabbitai coderabbitai bot mentioned this pull request Sep 3, 2025
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants