Skip to content

Conversation

@Harish-Naruto
Copy link
Member

@Harish-Naruto Harish-Naruto commented Aug 11, 2025

Summary by CodeRabbit

  • New Features

    • Added /health endpoint returning JSON { message: "OK" }.
    • Added /docs endpoint to serve static API documentation.
  • Documentation

    • Clarified delete interview endpoint request body (memberId) in API docs.
  • Refactor

    • Streamlined interviews routing initialization with no behavior changes.
  • Style

    • Minor comment and whitespace cleanups.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 11, 2025

Walkthrough

Adds /health and /docs endpoints to the app, refactors interviews router to no longer require injected Multer/Supabase, updates its registration, and tweaks JSDoc for the delete interview endpoint. Also includes whitespace and comment cleanups with no functional changes elsewhere.

Changes

Cohort / File(s) Summary
App endpoints and static docs
src/app.ts
Adds GET /health returning {message:"OK"}. Serves static docs at /docs from docs/apidoc. No other app middleware/route changes. Removes a header comment.
Interviews router refactor
src/routes/index.ts, src/routes/interviews.ts
Refactors interviewRouter to no-arg factory: interviewRouter() replaces interviewRouter(upload, supabase). Removes related imports/DI. Adds JSDoc @apiBody for memberId on DELETE /interviews/:id. Route handlers otherwise unchanged.
Achievements file formatting
src/routes/achievements.ts
Whitespace-only change after router init; no behavior changes.
API error comments cleanup
src/utils/apiError.ts
Removes top header and an interface JSDoc. No code or signature changes.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant ExpressApp as Express App
  participant InterviewsRouter as Interviews Router
  participant Controller as interviewCtrl
  participant Supabase as Supabase Client

  Client->>ExpressApp: DELETE /api/v1/interviews/:id (memberId in body)
  ExpressApp->>InterviewsRouter: Route dispatch
  InterviewsRouter->>Controller: deleteInterviewById(req, res)
  Controller->>Supabase: Delete interview by id (validate memberId)
  Supabase-->>Controller: Result / Error
  Controller-->>Client: HTTP response
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related PRs

Suggested reviewers

  • i-am-that-guy

Poem

Hop-hop! I nudge the routes in place,
A health ping chirps—OK, good grace.
Docs now bloom where /docs resides,
Interviews glide without DI guides.
Whiskers twitch at tidy lore—
Comments trimmed, we code some more.
Carrot commits! Deploy, explore. 🥕✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch health-endpoint

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.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai 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:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai 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 comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @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

Documentation and Community

  • 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.

@Sherin-2711 Sherin-2711 merged commit 5dde58d into main Aug 11, 2025
1 of 2 checks passed
@Harish-Naruto Harish-Naruto deleted the health-endpoint branch August 11, 2025 06:47
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: 2

🧹 Nitpick comments (5)
src/routes/achievements.ts (2)

2-2: Standardize the “Achievements” naming (fix typos)

Multiple identifiers are misspelled as “acheivements”. Consider renaming to “achievements” for consistency and maintainability.

-import * as acheivementsCtrl from '../controllers/achievement.controller';
+import * as achievementsCtrl from '../controllers/achievement.controller';

-export default function acheivementsRouter(upload: Multer, supabase: SupabaseClient) {
+export default function achievementsRouter(upload: Multer, supabase: SupabaseClient) {

-    router.get('/',  acheivementsCtrl.getAchievements);
+    router.get('/',  achievementsCtrl.getAchievements);

-    router.get("/:achievementId", acheivementsCtrl.getAchievementById);
+    router.get("/:achievementId", achievementsCtrl.getAchievementById);

-    router.post("/",  upload.single('image') , parseCreateAchievementData ,acheivementsCtrl.createAchievement);
+    router.post("/",  upload.single('image') , parseCreateAchievementData ,achievementsCtrl.createAchievement);

-    router.patch("/:achievementId",upload.single('image') , parseCreateAchievementData , acheivementsCtrl.updateAchievementById);
+    router.patch("/:achievementId",upload.single('image') , parseCreateAchievementData , achievementsCtrl.updateAchievementById);

-    router.delete("/:achievementId", acheivementsCtrl.deleteAchievementById);
+    router.delete("/:achievementId", achievementsCtrl.deleteAchievementById);

-    router.delete("/:achievementId/members/:memberId", acheivementsCtrl.removeMemberFromAchievement);
+    router.delete("/:achievementId/members/:memberId", achievementsCtrl.removeMemberFromAchievement);

Note: Update the import and usage in src/routes/index.ts accordingly.

Also applies to: 21-21, 33-33, 47-47, 67-67, 90-90, 105-105, 119-119


6-6: Nit: spacing after comma in import

Insert a space after the comma for readability.

-import { Request, Response,NextFunction } from 'express';
+import { Request, Response, NextFunction } from 'express';
src/utils/apiError.ts (1)

29-50: Optional: add structured logging in the error handler

Consider logging operational and programmer errors (without leaking PII), especially outside tests, to aid debugging and incident response.

Example minimal change:

 export function errorHandler(
   err: unknown,
   req: Request,
   res: Response,
   next: NextFunction,
 ): void {
+  // TODO: replace console with your logger (e.g., pino/winston)
+  if (process.env.NODE_ENV !== "test") {
+    // Safe log: avoid dumping full req/res; include route and method
+    // Only attach stack for non-production or explicitly operational errors
+    const safe = {
+      path: req.path,
+      method: req.method,
+      statusCode: err instanceof ApiError ? err.statusCode : 500,
+      message: err instanceof Error ? err.message : String(err),
+    };
+    // eslint-disable-next-line no-console
+    console.error("Unhandled error", safe, process.env.NODE_ENV !== "production" && err);
+  }
src/routes/interviews.ts (1)

96-105: DELETE with request body: confirm client compatibility

The JSDoc now requires memberId in the DELETE body. While Express supports this, some clients/proxies may strip or ignore DELETE bodies. Consider accepting memberId via a header or query param as a fallback, or document the constraint clearly.

Would you like a patch to accept memberId via header (e.g., X-Member-Id) if body is absent?

src/app.ts (1)

38-41: Nit: use app.get for the health check

Health is typically a GET/HEAD endpoint. Using app.get is clearer and avoids handling unintended methods.

-app.use("/health",(req,res)=>{
+app.get("/health",(req,res)=>{
   res.status(200).json({ message: "OK" });
-})
+});
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f77737a and 9bf6f5e.

📒 Files selected for processing (5)
  • src/app.ts (1 hunks)
  • src/routes/achievements.ts (1 hunks)
  • src/routes/index.ts (1 hunks)
  • src/routes/interviews.ts (2 hunks)
  • src/utils/apiError.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (4)
src/routes/achievements.ts (3)
src/routes/progress.ts (1)
  • progressRouter (7-55)
src/routes/projects.ts (1)
  • projectsRouter (28-196)
src/routes/topics.ts (1)
  • topicRouter (13-151)
src/routes/interviews.ts (2)
src/controllers/interview.controller.ts (2)
  • req (104-133)
  • req (34-59)
tests/Interview.test.ts (2)
  • it (180-308)
  • req (384-405)
src/app.ts (3)
src/routes/index.ts (1)
  • routes (12-29)
src/utils/apiError.ts (1)
  • errorHandler (29-50)
src/routes/progress.ts (1)
  • progressRouter (7-55)
src/routes/index.ts (1)
src/routes/interviews.ts (1)
  • interviewRouter (5-112)
🔇 Additional comments (4)
src/routes/achievements.ts (1)

23-23: Whitespace-only change is fine

Blank line after router initialization matches the pattern used in other route modules. No functional impact.

src/utils/apiError.ts (1)

19-24: Comment cleanup is fine

Removing the redundant JSDoc above ErrorResponse doesn’t affect behavior.

src/routes/interviews.ts (1)

5-7: Router factory signature simplification LGTM

Removing DI here is consistent with its usage. The route registrations remain intact.

src/routes/index.ts (1)

20-21: Interview router factory usage verified
All references to interviewRouter() have been updated to the new signature, and no residual dependencies remain.

• Call site confirmed in src/routes/index.ts (line 20)
• Router factory defined once in src/routes/interviews.ts (line 5)
• No Multer or SupabaseClient imports found in the interviews router
• Only one import from './interviews' (in src/routes/index.ts)

Comment on lines 20 to 26
app.use(
cors({
origin: config.ALLOWED_ORIGINS || "*", // e.g. 'https://club.example.com'
origin: config.ALLOWED_ORIGINS || "*",
methods: ["GET", "POST", "PATCH", "DELETE", "OPTIONS"],
credentials: true,
}),
);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

CORS misconfiguration: wildcard origin with credentials

Using origin: "" together with credentials: true will fail CORS in browsers (Access-Control-Allow-Origin cannot be "" when credentials are sent).

Use a dynamic origin or whitelist and align credentials accordingly:

-app.use(
-  cors({
-    origin: config.ALLOWED_ORIGINS || "*",
-    methods: ["GET", "POST", "PATCH", "DELETE", "OPTIONS"],
-    credentials: true,
-  }),
-);
+const allowedOrigins = (config.ALLOWED_ORIGINS || "")
+  .split(",")
+  .map(o => o.trim())
+  .filter(Boolean);
+
+app.use(cors({
+  // If list provided, reflect only allowed origins; otherwise reflect request origin
+  origin: allowedOrigins.length ? allowedOrigins : true,
+  methods: ["GET", "POST", "PATCH", "DELETE", "OPTIONS"],
+  // Credentials only when not using wildcard
+  credentials: allowedOrigins.length ? true : true, // origin:true reflects request origin, safe for credentials
+}));

If you prefer a stricter policy, set credentials: false when no whitelist is configured.

🤖 Prompt for AI Agents
In src/app.ts around lines 20 to 26 you are passing origin: "*" together with
credentials: true which breaks browser CORS (Access-Control-Allow-Origin cannot
be "*" when credentials are allowed); update the cors config to use a dynamic
origin checker or whitelist: parse config.ALLOWED_ORIGINS into an array and
provide origin as a function that validates the request origin and calls
callback(null, true) only for allowed origins (and sets
Access-Control-Allow-Credentials true), otherwise call callback(null, false) (or
reject); alternatively, if you do not have a whitelist, set credentials: false
to avoid the conflict; ensure the chosen approach returns the correct boolean to
the cors middleware so the Access-Control-Allow-Origin header is the specific
origin when credentials are enabled.

Comment on lines +44 to 47
// 404 handler
app.use((req, res) => {
res.status(404).json({ message: "Not Found" });
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

/docs route is unreachable and error handler ordering is incorrect

The catch-all 404 (Lines 45-47) responds before /docs (Lines 54-55), so /docs will 404. Additionally, the global error handler (Line 51) should be the last middleware; placing routes after it bypasses centralized error handling.

Move /docs above the 404 and keep the error handler last:

 app.use("/api/v1", routes(upload, supabase));

+// Serve API documentation
+app.use("/docs", express.static(path.join(__dirname, "..", "docs/apidoc")));
+
-// 404 handler
+// 404 handler
 app.use((req, res) => {
   res.status(404).json({ message: "Not Found" });
 });
 
-// Global error handler
-app.use(errorHandler);
+// Global error handler (must be last)
+app.use(errorHandler);
 
-// Serve API documentation
-app.use("/docs", express.static(path.join(__dirname, "..", "docs/apidoc")));

Also applies to: 53-55, 50-51

🤖 Prompt for AI Agents
In src/app.ts around lines 44-55, the 404 catch-all middleware is registered
before the /docs route and the global error handler is not the last middleware;
move the /docs route (currently at ~54-55) to be registered before the 404
handler (lines 44-47) so /docs is reachable, and ensure the global
error-handling middleware (around lines 50-51) is placed after the 404 handler
so it is the very last middleware in the stack; adjust order accordingly so: all
routes (including /docs) -> 404 catch-all -> global error handler.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants