Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: remove delegates from Context #15

Merged
merged 1 commit into from
Jan 2, 2025
Merged

fix: remove delegates from Context #15

merged 1 commit into from
Jan 2, 2025

Conversation

fengmk2
Copy link
Member

@fengmk2 fengmk2 commented Jan 2, 2025

Summary by CodeRabbit

Release Notes

  • Documentation

    • Updated documentation for Koa Response object, adding method to append headers
  • Dependencies

    • Removed delegates dependency
    • Added @eggjs/bin
    • Updated @types/node and mm dependency versions
  • Type Improvements

    • Enhanced type safety across Application, Context, Request, and Response classes
    • Introduced more flexible generic type handling
  • Code Refactoring

    • Removed delegation mechanism in Context class
    • Added direct method and property definitions for request and response handling
  • Testing

    • Added new test cases for context subclassing and application behavior

Copy link

coderabbitai bot commented Jan 2, 2025

Walkthrough

This pull request introduces significant architectural changes to the Koa framework, focusing on enhancing type safety and removing the previous delegation mechanism. The modifications span multiple files, with key changes including the introduction of generic type parameters, direct method and property definitions in the Context class, and removal of the ContextDelegation type. The changes aim to provide more flexible and explicit handling of request and response functionalities while maintaining the core framework's behavior.

Changes

File Change Summary
docs/api/response.md Added documentation for response.append(field, value) method
example/extend/middleware.ts Updated type signature from ICustomContext to CustomContext
package.json Removed delegates dependency, added @eggjs/bin, updated dependency versions
src/application.ts Introduced generic type T for Application, updated method signatures
src/context.ts Removed delegation, added explicit request/response methods and properties
src/request.ts Added generic type parameter, updated query handling
src/response.ts Enhanced type handling, explicit return types for getters
test/application.test-d.ts Updated type imports and assertions
test/application/context.test.ts Added context subclass testing
test/test-helpers/context.ts Updated import and context creation method

Sequence Diagram

sequenceDiagram
    participant App as Application<T>
    participant Ctx as Context
    participant Req as Request
    participant Res as Response

    App->>Ctx: Create Context
    Ctx->>Req: Initialize Request
    Ctx->>Res: Initialize Response
    Ctx-->>App: Return Typed Context
    App->>Ctx: Apply Middleware
    Ctx->>Res: Manipulate Response
Loading

Possibly Related PRs

Poem

🐰 A Rabbit's Ode to Type Safety 🐰

Delegation's gone, generics arise,
Context now dances with type-driven guise
No more shadows, methods shine bright
Koa's framework leaps with type-safe might!

Hop, hop, hooray! 🎉


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • 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 generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

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. (Beta)
  • @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.

Copy link

New and removed dependencies detected. Learn more about Socket for GitHub ↗︎

Package New capabilities Transitives Size Publisher
npm/@eggjs/bin@7.0.1 environment Transitive: eval, filesystem, shell, unsafe +226 21.1 MB fengmk2
npm/@types/node@22.10.3 None +1 2.37 MB types
npm/mm@4.0.1 None +3 168 kB fengmk2

🚮 Removed packages: npm/@types/node@20.17.11, npm/delegates@1.0.0, npm/mm@3.4.0

View full report↗︎

Copy link

pkg-pr-new bot commented Jan 2, 2025

Open in Stackblitz

npm i https://pkg.pr.new/eggjs/koa/@eggjs/koa@15

commit: dac5571

Copy link

codecov bot commented Jan 2, 2025

Codecov Report

Attention: Patch coverage is 89.89899% with 30 lines in your changes missing coverage. Please review.

Project coverage is 98.44%. Comparing base (49abe7f) to head (dac5571).
Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
src/context.ts 88.41% 30 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##            master      #15      +/-   ##
===========================================
- Coverage   100.00%   98.44%   -1.56%     
===========================================
  Files            6        6              
  Lines         1725     1924     +199     
  Branches       321      366      +45     
===========================================
+ Hits          1725     1894     +169     
- Misses           0       30      +30     

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

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 (6)
src/application.ts (3)

154-154: Typed middleware application
Ensuring fn is a function and rejecting generator logic is consistent with modern async/await usage. Consider adding a test case to confirm that passing a non-function throws the correct error.


222-222: Context creation method
Currently annotated as @private but exposed as a public method. Consider aligning the visibility modifier with the intended usage, or clarify in docs if it’s deliberately public for advanced use cases.


249-249: Protected _respond
The method systematically handles various response types (buffer, string, stream, JSON). It's lengthy, but logically sound. For future maintainability, consider factoring out specialized blocks (e.g., HEAD handling) into smaller helper methods.

test/test-helpers/context.ts (1)

2-2: Switched to named import
Renaming Application as Koa clarifies the usage but keep an eye on consistency with the rest of the project to avoid confused references.

test/application/context.test.ts (1)

42-67: Comprehensive test coverage for MyContext and MyApp.
These tests nicely demonstrate how subclassing Context and providing a custom Application subclass can add extra functionality. Consider adding negative or edge-case tests (e.g., verifying error handling) to further validate behavior.

docs/api/response.md (1)

Line range hint 216-222: Enhance documentation with more detailed examples and behavior description.

While the documentation follows the consistent style, it could be more comprehensive. Consider adding:

  • Example of appending multiple values
  • Behavior when the header already exists
  • Relationship with the set method

Here's a suggested expansion:

### response.append(field, value)

  Append additional header `field` with value `val`.
+
+ If the header already exists, the new value will be appended to the existing one.
+ For multiple values, you can call append multiple times:
+
+```js
+// Appending multiple values
+ctx.append('Link', '<http://127.0.0.1/>');
+ctx.append('Link', '<http://example.com/>');
+// Results in: Link: <http://127.0.0.1/>, <http://example.com/>
+
+// Appending array of values
+ctx.append('Vary', ['Accept', 'User-Agent']);
+```
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 54e8826 and dac5571.

📒 Files selected for processing (10)
  • docs/api/response.md (1 hunks)
  • example/extend/middleware.ts (2 hunks)
  • package.json (3 hunks)
  • src/application.ts (8 hunks)
  • src/context.ts (2 hunks)
  • src/request.ts (3 hunks)
  • src/response.ts (3 hunks)
  • test/application.test-d.ts (1 hunks)
  • test/application/context.test.ts (2 hunks)
  • test/test-helpers/context.ts (2 hunks)
🧰 Additional context used
🪛 GitHub Check: codecov/patch
src/context.ts

[warning] 273-274: src/context.ts#L273-L274
Added lines #L273 - L274 were not covered by tests


[warning] 337-338: src/context.ts#L337-L338
Added lines #L337 - L338 were not covered by tests


[warning] 341-342: src/context.ts#L341-L342
Added lines #L341 - L342 were not covered by tests


[warning] 345-346: src/context.ts#L345-L346
Added lines #L345 - L346 were not covered by tests


[warning] 349-350: src/context.ts#L349-L350
Added lines #L349 - L350 were not covered by tests


[warning] 353-354: src/context.ts#L353-L354
Added lines #L353 - L354 were not covered by tests


[warning] 365-366: src/context.ts#L365-L366
Added lines #L365 - L366 were not covered by tests


[warning] 377-378: src/context.ts#L377-L378
Added lines #L377 - L378 were not covered by tests


[warning] 381-382: src/context.ts#L381-L382
Added lines #L381 - L382 were not covered by tests


[warning] 445-446: src/context.ts#L445-L446
Added lines #L445 - L446 were not covered by tests


[warning] 461-462: src/context.ts#L461-L462
Added lines #L461 - L462 were not covered by tests


[warning] 465-466: src/context.ts#L465-L466
Added lines #L465 - L466 were not covered by tests


[warning] 469-470: src/context.ts#L469-L470
Added lines #L469 - L470 were not covered by tests


[warning] 473-474: src/context.ts#L473-L474
Added lines #L473 - L474 were not covered by tests


[warning] 477-478: src/context.ts#L477-L478
Added lines #L477 - L478 were not covered by tests

🔇 Additional comments (33)
src/application.ts (7)

14-14: Adoption of new Context import
The explicit import of Context suggests a shift to more direct references instead of delegations. No issues found, but ensure that all dependent modules are consistently updated to avoid circular dependencies.


24-24: Refined MiddlewareFunc template
Defining MiddlewareFunc with a default generic bound to Context increases flexibility for custom contexts. This is a safe and clean approach to typed middleware.


30-30: Generic Application class
Allowing Application to be parameterized by a Context subtype is a good design for extending or customizing the context. This change should maintain backward compatibility while enabling richer types going forward.


44-45: Typed middleware array and async local storage
By providing a dedicated type to the middleware array and using AsyncLocalStorage<T>, concurrency data is properly associated with each request. However, keep an eye on memory usage under high load to avoid potential leaks.


47-51: Configurable context, request, and response classes
These prototypical class references afford dynamic subclassing. If you plan to override behavior, verify that these do not inadvertently mask important upstream constructor parameters.


87-91: Dynamic subclass creation
The dynamically extended classes (ApplicationContext, ApplicationRequest, ApplicationResponse) can improve maintainability for complex features. Verify coverage for all introduced methods, especially where custom overrides could occur.


199-199: Improved type safety in request handling
The updated middleware signature with ctx: T ensures strong typing in your request pipeline. No immediate concerns found; just confirm that all error paths have test coverage.

src/context.ts (4)

3-3: Importing ParsedUrlQuery
Using ParsedUrlQuery fosters strong typing for request.query, which can mitigate runtime-typing mistakes.


8-8: Importing Accepts type
This addition helps ensure robust type checking when retrieving accepted encodings, charsets, etc. Keep usage consistent across the file to avoid confusion.


227-383: Request delegation removal in favor of explicit getters and methods
All the new request delegation methods (e.g., acceptsLanguages, acceptsEncodings, getters like querystring, method, etc.) are clear and explicit. This improves readability over the previous delegate approach.

However, static analysis shows lines (e.g., 273-274, 337-338, 341-342, etc.) lack test coverage. Consider adding tests to confirm baseline functionality of these new getters.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 273-274: src/context.ts#L273-L274
Added lines #L273 - L274 were not covered by tests


[warning] 337-338: src/context.ts#L337-L338
Added lines #L337 - L338 were not covered by tests


[warning] 341-342: src/context.ts#L341-L342
Added lines #L341 - L342 were not covered by tests


[warning] 345-346: src/context.ts#L345-L346
Added lines #L345 - L346 were not covered by tests


[warning] 349-350: src/context.ts#L349-L350
Added lines #L349 - L350 were not covered by tests


[warning] 353-354: src/context.ts#L353-L354
Added lines #L353 - L354 were not covered by tests


[warning] 365-366: src/context.ts#L365-L366
Added lines #L365 - L366 were not covered by tests


[warning] 377-378: src/context.ts#L377-L378
Added lines #L377 - L378 were not covered by tests


[warning] 381-382: src/context.ts#L381-L382
Added lines #L381 - L382 were not covered by tests


384-483: Response delegation removal in favor of explicit getters and methods
Direct calls such as redirect(), has(), set(), and property access for status, body, etc., enhance overall clarity by making the Context API more explicit.

Several lines (e.g., 445-446, 461-462, 465-466, etc.) lack coverage per the static analysis hints. Consider adding tests to validate basic operation (e.g., reading length, updating etag).

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 445-446: src/context.ts#L445-L446
Added lines #L445 - L446 were not covered by tests


[warning] 461-462: src/context.ts#L461-L462
Added lines #L461 - L462 were not covered by tests


[warning] 465-466: src/context.ts#L465-L466
Added lines #L465 - L466 were not covered by tests


[warning] 469-470: src/context.ts#L469-L470
Added lines #L469 - L470 were not covered by tests


[warning] 473-474: src/context.ts#L473-L474
Added lines #L473 - L474 were not covered by tests


[warning] 477-478: src/context.ts#L477-L478
Added lines #L477 - L478 were not covered by tests

test/application.test-d.ts (1)

2-2: Aligned type references with Context
Switching the type from ContextDelegation to Context keeps the tests consistent with the code changes. Confirm that no usage scenarios remain that still rely on delegation-based logic.

Also applies to: 5-5, 11-11

example/extend/middleware.ts (2)

1-1: Removed reference to ContextDelegation
By importing Context directly, we simplify the type references and remove the transitional delegation code. Maintain updated imports throughout any extended classes.


10-10: Middleware uses a custom context
These typed definitions make it clear which custom properties and methods are available (ctx.hello). Confirm test coverage for your extended context usage.

test/test-helpers/context.ts (1)

25-25: Directly returning app.createContext
Eliminating the cast to any or ContextDelegation is safer, especially when dealing with generics. Confirm all test usage is updated to expect the new Context type.

test/application/context.test.ts (1)

3-3: Good import statement for type safety.
This import ensures that your subclass extends the correct Context type.

src/response.ts (6)

16-16: Context import for better type clarity.
Replacing ContextDelegation with the direct Context import aligns with the removal of delegates.


19-19: Generic parameter ensures flexible context usage.
Declaring export class Response<T extends Context = Context> properly integrates the custom context types.


24-24: ctx: T property type strongly typed.
Using T allows the Response to access specialized context properties.


27-27: Constructor signature updated to accept generic ctx.
This change ensures Response is constructed with the correct context subtype.


171-188: Refined length getter logic and types.
The explicit number | undefined return type and checks covering string, buffer, and JSON content make its usage clearer and robust. This also prevents potential runtime errors from unaccounted content types.


281-281: Explicit return type for type getter.
Returning a string for the MIME type is consistent with the broader type-safety improvements in this PR.

src/request.ts (6)

12-12: Direct Context import ensures consistency.
Removing the ContextDelegation reference clarifies the class’s direct dependency on Context.


19-19: Generic Request class for advanced context customization.
This helps align the request-handling logic with custom context types.


24-24: Strong typing for ctx: T.
Allows referencing specialized properties on ctx within Request without losing type information.


28-28: Updated constructor to accept a generic context.
Ensures the Request instance associates with the correct type of context.


145-145: Type-safe getter for query.
Returning ParsedUrlQuery improves confidence when accessing query properties.


161-161: Setter for query ensures URL rewriting remains coherent.
Converting an object into a querystring is now strictly typed, mitigating potential runtime type errors.

package.json (4)

12-16: Enhanced scripts for CI and test processes.
Using pretest, preci, and postci clarifies the workflow around linting, coverage, and packaging.


58-58: @eggjs/bin dependency added.
This presumably aligns with your new build/CI approach.

Would you like to verify its usage across scripts or confirm backward compatibility?


72-72: Updated @types/node to version "22".
Ensure that the Node.js typing changes do not break compatibility with older Node.js versions.


81-81: Bumped mm to ^4.0.1.
Check any major version changes or breaking differences in mm usage, especially around mocking behaviors.

docs/api/response.md (1)

Line range hint 216-222: Verify implementation matches documentation.

Let's verify that the documented behavior matches the actual implementation.

✅ Verification successful

Documentation matches implementation and tests

The documentation accurately reflects the implementation and behavior of the append method:

  1. The implementation in src/response.ts shows that the method accepts a field (string) and value (string or string array) as parameters, which matches the documented signature.
  2. The tests in test/response/append.test.ts demonstrate the documented behavior:
    • Multiple values for the same header are properly handled (e.g., x-foo)
    • The example in the documentation using Link header is actually tested in the test file
    • Both single values and arrays are supported as shown in the tests
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the append method implementation matches the documentation

# Search for the append method implementation
echo "Searching for append method implementation..."
ast-grep --pattern 'append(field: string, val: string | string[]) {
  $$$
}'

# Search for tests related to append
echo "Searching for related tests..."
rg -A 5 'test.*append.*header'

Length of output: 283


Script:

#!/bin/bash
# Let's try a different approach to find the append implementation and its tests

# Search for files containing 'append' method
echo "Searching for files with append method..."
rg -l "append.*header|append.*field"

# Search for the implementation with more context
echo "Searching for append implementation..."
rg -A 5 "append.*header|append.*field"

# Search for test files containing 'append'
echo "Looking for test files..."
fd "test.*\.(js|ts|jsx|tsx)$" | xargs rg "append"

Length of output: 2154

@fengmk2 fengmk2 merged commit a3bdefe into master Jan 2, 2025
21 of 23 checks passed
@fengmk2 fengmk2 deleted the fix-Context branch January 2, 2025 04:03
fengmk2 pushed a commit that referenced this pull request Jan 2, 2025
[skip ci]

## [2.20.3](v2.20.2...v2.20.3) (2025-01-02)

### Bug Fixes

* remove delegates from Context ([#15](#15)) ([a3bdefe](a3bdefe))
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.

1 participant