Skip to content

Conversation

@csikb
Copy link
Contributor

@csikb csikb commented Dec 7, 2025

Summary by CodeRabbit

  • Chores

    • Updated security middleware dependency to version 8.1.0.
    • Removed legacy dependency.
  • Refactor

    • Restructured middleware configuration for improved framework compatibility.
  • Tests

    • Updated test suite to reflect middleware changes.

✏️ Tip: You can customize this high-level summary in your review settings.

@csikb csikb self-assigned this Dec 7, 2025
@coderabbitai
Copy link

coderabbitai bot commented Dec 7, 2025

Walkthrough

Migrated from koa-helmet to native helmet package with a custom Koa adapter wrapper. Created koaHelmet factory function to adapt Express-style helmet middleware for Koa integration, updated module exports, and adjusted tests throughout. Removed explicit return statement in health router.

Changes

Cohort / File(s) Summary
Dependency & Middleware Migration
package.json, src/middleware/helmet.ts, src/middleware/index.ts
Removed koa-helmet dependency (v8.0.1); added helmet (v8.1.0). Replaced helmet default export with koaHelmet named export—a Koa-compatible wrapper that adapts Express middleware. Updated barrel export to wildcard re-export from helmet.js.
Application Integration
src/index.ts
Updated helmet import to koaHelmet; changed middleware application from .use(helmet) to .use(koaHelmet()).
Test Suite Updates
src/index.test.ts, src/middleware/helmet.test.ts, src/middleware/index.test.ts
Updated mocking and assertions to reflect koaHelmet named export. Added tests for middleware invocation, error handling, and wrapper behavior. Adjusted assertion counts to match new call patterns.
Minor Refactoring
src/router/health.ts
Removed explicit return statement in /health endpoint error path.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Key areas requiring attention:
    • koaHelmet adapter implementation: verify correct Promise-based adaptation of Express middleware to Koa's async/await model
    • Error handling logic in helmet middleware wrapper: ensure errors are properly propagated
    • Test coverage for edge cases in the new adapter (especially request/response/next binding)
    • Verify barrel export change (export * from) doesn't inadvertently expose internal symbols

Possibly related PRs

  • fix: merge src and tests #283: Related through helmet middleware changes—touches the same middleware tests and export patterns from the previous koa-helmet approach.

Poem

🐰 Swapped the helmet guard today, from koa's embrace to native way,
Built an adapter, wrapped with care, so Express middleware fits right there,
Tests all updated, green and bright, our security flows just right! 🛡️

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: replace koa-helmet' is concise and clearly indicates the main change: removing the deprecated koa-helmet package and replacing it with the direct helmet package.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch replace/helmet

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8975d84 and 7d2fe89.

📒 Files selected for processing (1)
  • src/router/health.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • src/router/health.ts

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@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 (1)
src/middleware/helmet.ts (1)

1-19: Helmet Express→Koa adapter looks correct; suggest naming + clearer control flow

The adapter correctly:

  • Instantiates helmet(options) once.
  • Invokes it with ctx.req/ctx.res.
  • Propagates errors via Promise rejection and only calls next after helmet completes (via Promise adoption).

Two small improvements would make this more explicit and fix the Sonar warning about an unnamed function:

  1. Name the default-exported function (e.g. koaHelmet) for clearer stack traces and to satisfy static analysis.
  2. Separate the Express call from Koa’s next() instead of relying on resolve(next()), which works but hides the sequencing in Promise internals.

Suggested refactor:

-import helmet, { type HelmetOptions } from 'helmet'
-import type { Middleware } from 'koa'
+import helmet, { type HelmetOptions } from 'helmet'
+import type { Middleware } from 'koa'
@@
-export default function (options?: HelmetOptions): Middleware {
-  const expressHelmet = helmet(options)
-  return async (ctx, next) => {
-    return new Promise<void>((resolve, reject) => {
-      expressHelmet(ctx.req, ctx.res, (err) => {
-        if (err) return reject(err)
-        resolve(next())
-      })
-    })
-  }
-}
+export default function koaHelmet(options?: HelmetOptions): Middleware {
+  const expressHelmet = helmet(options)
+  return async (ctx, next) => {
+    await new Promise<void>((resolve, reject) => {
+      expressHelmet(ctx.req, ctx.res, (err) => {
+        if (err) return reject(err)
+        resolve()
+      })
+    })
+    await next()
+  }
+}

This keeps behavior the same, makes the flow easier to read, and addresses the SonarCloud “function should be named” warning. As per static analysis hints.

Please re-run the SonarCloud check and your tests after this change to confirm the warning disappears and headers/error handling remain unchanged.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5b0a459 and f5e366c.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (3)
  • package.json (1 hunks)
  • src/index.ts (1 hunks)
  • src/middleware/helmet.ts (1 hunks)
🧰 Additional context used
🪛 GitHub Check: SonarCloud Code Analysis
src/middleware/helmet.ts

[warning] 9-9: The function should be named.

See more on https://sonarcloud.io/project/issues?id=BSStudio_bss-web-graphql-backend&issues=AZr5Cgz-mYQ2rrKlCw-w&open=AZr5Cgz-mYQ2rrKlCw-w&pullRequest=379

⏰ 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). (8)
  • GitHub Check: Release
  • GitHub Check: Lint
  • GitHub Check: Build
  • GitHub Check: Unit test
  • GitHub Check: Scorecard analysis
  • GitHub Check: Lint Dockerfile
  • GitHub Check: Build and publish
  • GitHub Check: Integration test
🔇 Additional comments (2)
src/index.ts (1)

17-17: Using helmet() as a Koa middleware factory looks correct

Given the new wrapper in src/middleware/helmet.ts returns a Koa Middleware when invoked, switching from .use(helmet) to .use(helmet()) is the right call pattern and keeps the middleware chain intact.

Please run your existing integration/e2e tests (especially any that assert response headers) to confirm the new helmet setup produces the expected security headers across routes.

package.json (1)

24-31: The dependency in question does not exist in the current package.json. The dependencies section contains only legitimate runtime packages (@koa/router, dotenv, helmet, koa, koa-compress, pg, postgraphile, and others), with no "test" entry present. The codebase correctly uses Vitest for testing (found in optionalDependencies), and no usage of a generic test package was found.

Likely an incorrect or invalid review comment.

Copy link

@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

🧹 Nitpick comments (1)
src/index.test.ts (1)

30-33: Mocking and expectations for helmet align with the new factory contract, but can be tightened

The updated mock and assertions correctly reflect helmet as a factory whose result is passed to koa.use, so behavior-wise this looks good.

One minor improvement: in

expect.soft(helmet).toHaveBeenCalledWith()
expect.soft(mockKoaInstance.use).toHaveBeenCalledWith(helmet())

the second line calls helmet() again inside the assertion. This:

  • Increments the mock’s call count (which you don’t currently assert on), and
  • Relies on mockReturnValue returning the same instance every time.

You can make the test more explicit and stable by capturing the first returned middleware and asserting against that, without additional calls:

   await import('./index.js')
@@
-    expect.soft(helmet).toHaveBeenCalledWith()
-    expect.soft(mockKoaInstance.use).toHaveBeenCalledWith(helmet())
+    expect.soft(helmet).toHaveBeenCalledTimes(1)
+    expect.soft(helmet).toHaveBeenCalledWith()
+
+    const helmetMiddleware = vi.mocked(helmet).mock.results[0]?.value
+    expect.soft(mockKoaInstance.use).toHaveBeenCalledWith(helmetMiddleware)

This keeps the intent clear (“koa.use gets exactly what helmet() returned”) without side effects in the assertion itself.

Also applies to: 49-49, 59-60

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5366159 and cdc7208.

📒 Files selected for processing (2)
  • src/index.test.ts (3 hunks)
  • src/middleware/helmet.test.ts (1 hunks)
🧰 Additional context used
🪛 GitHub Actions: Build
src/middleware/helmet.test.ts

[error] 12-12: AssertionError: expected "vi.fn()" to be called once, but got 0 times

- Updated test descriptions for clarity.
- Added tests to verify middleware creation and option handling.
- Included error handling test for express helmet middleware.
@codecov
Copy link

codecov bot commented Dec 7, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (5b0a459) to head (7d2fe89).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #379   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            4         5    +1     
  Lines           23        29    +6     
  Branches         4         5    +1     
=========================================
+ Hits            23        29    +6     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

csikb added 4 commits December 7, 2025 14:25
- Added beforeEach hook to clear mocks before each test.
- Updated test descriptions for clarity.
- Enhanced tests to verify middleware creation and option handling.
- Updated the import statement to rename `helmetMiddleware` to `helmetFactory`.
- Adjusted the middleware instantiation accordingly for clarity and consistency.
- Updated the middleware import and instantiation from `helmet` to `koaHelmet` across the application.
- Adjusted related tests to reflect the new naming convention for consistency and clarity.
Copy link

@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

📥 Commits

Reviewing files that changed from the base of the PR and between cdc7208 and 1f60e6e.

📒 Files selected for processing (6)
  • src/index.test.ts (4 hunks)
  • src/index.ts (2 hunks)
  • src/middleware/helmet.test.ts (1 hunks)
  • src/middleware/helmet.ts (1 hunks)
  • src/middleware/index.test.ts (3 hunks)
  • src/middleware/index.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/index.ts
  • src/middleware/helmet.ts
🧰 Additional context used
🧬 Code graph analysis (2)
src/middleware/helmet.test.ts (1)
src/middleware/helmet.ts (1)
  • koaHelmet (9-20)
src/index.test.ts (1)
src/middleware/helmet.ts (1)
  • koaHelmet (9-20)
🪛 GitHub Actions: Build
src/middleware/index.test.ts

[error] 31-37: Formatter would have printed the following content; formatting mismatch detected during linting. Command: 'pnpm run lint'. The Biome/formatter reported a diff and exit code 1.

🔇 Additional comments (3)
src/middleware/index.ts (1)

3-3: LGTM! Wildcard export aligns with the new named export pattern.

The change from exporting a default alias to a wildcard re-export correctly exposes the new koaHelmet named export. This is a breaking API change (consumers must now import koaHelmet instead of helmet), but it aligns with the PR's objective to replace koa-helmet with the standard helmet library via a Koa-compatible wrapper.

src/middleware/index.test.ts (1)

4-4: LGTM! Test correctly updated for the new named export.

The import and mock have been properly updated from helmet to koaHelmet, and the test expectations now correctly reference the new API surface.

Also applies to: 14-14, 29-29

src/middleware/helmet.test.ts (1)

1-96: Excellent test coverage for the Koa adapter!

The test suite comprehensively validates the koaHelmet factory pattern:

  • Factory invocation and middleware return type
  • Options forwarding to the underlying helmet library
  • Middleware execution flow (Express callback → Koa next)
  • Error propagation (reject promise, skip next)

The dynamic import pattern after mocking and the beforeEach cleanup ensure proper test isolation.

csikb added 2 commits December 8, 2025 08:00
- Refactored test assertions in `index.test.ts` for better readability.
- Adjusted the way keys are compared in the test to enhance clarity.
Copy link

@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 (1)
src/middleware/index.test.ts (1)

4-4: koaHelmet migration in test looks consistent; consider aligning mock specifier

The switch from default helmet to named koaHelmet is wired through correctly here: the import, mock shape, and expected export map all reference koaHelmet consistently, which matches the new middleware API.

One small readability/robustness nit: the import uses './helmet.js' while the mock targets './helmet'. Depending on your Vitest/TS module resolution, this might or might not refer to the same module. For clarity (and to avoid subtle mismatches later), consider updating the mock to also use './helmet.js' so the specifiers are identical.

Also applies to: 14-15, 29-29

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1f60e6e and 8975d84.

📒 Files selected for processing (2)
  • src/middleware/index.test.ts (3 hunks)
  • src/middleware/postgraphile.ts (1 hunks)
🧰 Additional context used
🪛 GitHub Actions: Build
src/middleware/postgraphile.ts

[error] 15-15: Type 'typeof import("/home/runner/work/bss-web-graphql-backend/bss-web-graphql-backend/node_modules/.pnpm/@graphile-contrib+pg-simplify-inflector@6.1.0/node_modules/@graphile-contrib/pg-simplify-inflector/index")' is not assignable to type 'Plugin'. TS2322. Build failed during 'pnpm run build' (tsc).

🪛 GitHub Check: Build
src/middleware/postgraphile.ts

[failure] 15-15:
Type 'typeof import("/home/runner/work/bss-web-graphql-backend/bss-web-graphql-backend/node_modules/.pnpm/@graphile-contrib+pg-simplify-inflector@6.1.0/node_modules/@graphile-contrib/pg-simplify-inflector/index")' is not assignable to type 'Plugin'.

🔇 Additional comments (2)
src/middleware/index.test.ts (1)

33-35: Additional key-order-agnostic assertion is sound

The second expect.soft that compares sorted Object.keys(actual) and Object.keys(expected) is a good complement to toMatchObject, and the total of two expectations matches expect.assertions(2). No further changes needed here.

src/middleware/postgraphile.ts (1)

15-15: Correct the import to remove .default — the plugin is already unwrapped by the default import.

When using ESM import ... from syntax with a default export, the exported value is automatically unwrapped. Accessing .default again returns the module namespace rather than the plugin itself, causing the TypeScript error.

The current code is incorrect:

import PgSimplifyInflectorPlugin from '@graphile-contrib/pg-simplify-inflector'
appendPlugins: [PgSimplifyInflectorPlugin.default]  // Wrong: accesses .default on unwrapped import

The correct usage is:

import PgSimplifyInflectorPlugin from '@graphile-contrib/pg-simplify-inflector'
appendPlugins: [PgSimplifyInflectorPlugin]  // Correct: plugin is already the default export

Remove .default from line 15.

@csikb csikb added this pull request to the merge queue Dec 8, 2025
github-merge-queue bot pushed a commit that referenced this pull request Dec 8, 2025
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Chores**
* Replaced the Koa-specific helmet package in the project manifest with
the standard helmet dependency.

* **Refactor**
* Helmet middleware now must be instantiated (called) with optional
configuration and is re-exposed via the middleware barrel.

* **Tests**
* Updated tests and mocks to reflect the middleware factory pattern and
adjusted assertions/counts accordingly.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
@csikb csikb removed this pull request from the merge queue due to a manual request Dec 8, 2025
@sonarqubecloud
Copy link

sonarqubecloud bot commented Dec 8, 2025

@csikb csikb enabled auto-merge December 8, 2025 08:10
@csikb csikb added this pull request to the merge queue Dec 8, 2025
Merged via the queue into main with commit e6fe28e Dec 8, 2025
17 checks passed
@csikb csikb deleted the replace/helmet branch December 8, 2025 08:12
@bsstudio-pr-release
Copy link

🎉 This PR is included in version 2.0.17 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants