Skip to content

fix(server): reflect middleware initial context in procedure when use#234

Merged
dinwwwh merged 5 commits intomainfrom
fix/middleware-context-problems
Mar 14, 2025
Merged

fix(server): reflect middleware initial context in procedure when use#234
dinwwwh merged 5 commits intomainfrom
fix/middleware-context-problems

Conversation

@dinwwwh
Copy link
Copy Markdown
Member

@dinwwwh dinwwwh commented Mar 13, 2025

Bug Description:

The procedure ignores the middleware's initial context type. It only checks that the current context meets the expected type when calling .use. As a result, you can accidentally pass extra or invalid context values that the middleware doesn't expect, potentially causing it to break.

Example:

const mid = os.$context<{ retryable?: boolean }>().middleware(({ context, next }) => {
  // Use context.retryable here
  return next();
});

const procedure = os.use(mid).handler(() => 'Hello world');

In this example, procedure does not reflect the initial context type { retryable?: boolean }. It only verifies that the current context satisfies the { retryable?: boolean }.

const handler = new RPCHandler(procedure);

handler.handle(request, {
  context: {
    retryable: 'any-value-can-provide' // Invalid value that may break the middleware
  }
});

Now, the middleware mid can break when it encounters unexpected context values.


This PR also removes the unnecessary current context check after .use, as we had already removed the dedupe-middleware logic earlier. Therefore, it is safe to remove this check.

Summary by CodeRabbit

  • Refactor

    • Enhanced middleware and context management for more flexible and robust API behavior.
    • Updated builder, procedure, and router interfaces to offer clearer configuration and improved type safety.
    • Simplified type definitions for middleware functions, focusing on output types and removing unnecessary constraints.
  • Tests

    • Expanded test coverage to rigorously validate context merging and middleware configurations, ensuring accurate error handling and robust type checking.
    • Added new tests for invalid context types and refined existing tests for better clarity and type safety.
    • Restructured tests for better organization and readability, focusing on specific context handling scenarios.

@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 13, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
orpc ✅ Ready (Inspect) Visit Preview 💬 Add feedback Mar 13, 2025 3:00pm

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 13, 2025

Walkthrough

This pull request introduces comprehensive updates to middleware context handling across several server modules. Changes include the addition of a new Middleware type, updated generic parameters in the use methods of builders, implementers, routers, and decorated procedures, and revised context merging strategies. Old context types have been replaced with MergedInitialContext, MergedCurrentContext, and ContextExtendsGuard. Corresponding tests and import statements were updated consistently to validate stricter type checking and ensure that middleware input/output contexts are managed correctly.

Changes

File(s) Change Summary
packages/server/src/builder-variants.test-d.ts, packages/server/src/builder-variants.ts, packages/server/src/builder.test-d.ts, packages/server/src/builder.ts Added Middleware to imports; updated use, router, and lazy method signatures with new generic parameters (UInContext) and adjusted context types using Omit/Record.
packages/server/src/context.test-d.ts, packages/server/src/context.test.ts, packages/server/src/context.ts Replaced MergedContext and ConflictContextGuard with MergedInitialContext, MergedCurrentContext, and ContextExtendsGuard; renamed mergeContext to mergeCurrentContext.
packages/server/src/implementer-procedure.test-d.ts, packages/server/src/implementer-procedure.ts, packages/server/src/implementer-variants.test-d.ts, packages/server/src/implementer-variants.ts, packages/server/src/implementer.test-d.ts, packages/server/src/implementer.ts Revised use method signatures to include UOutContext and UInContext, updating return types for enhanced context merging; updated tests to reflect new middleware context behavior.
packages/server/src/middleware-decorated.test-d.ts, packages/server/src/middleware-decorated.ts, packages/server/src/procedure-decorated.test-d.ts, packages/server/src/procedure-decorated.ts, packages/server/src/middleware.test-d.ts, packages/server/src/middleware.ts Enhanced middleware and decorated procedure definitions with updated concatenation and use methods; simplified MiddlewareNextFn and refined context expectations using Omit and explicit merging.
packages/server/src/router-utils.test-d.ts, packages/server/src/router-utils.ts Updated EnhancedRouter type and enhanceRouter function signatures to include an additional current context parameter, merging initial context types into router definitions.

Possibly related PRs

  • unnoq/orpc#226: Modifies the .use methods in builder and router classes to improve middleware type safety and context handling.
  • unnoq/orpc#223: Adjusts DecoratedProcedure chaining methods, aligning type definitions and context management with the updated specifications.
  • unnoq/orpc#201: Introduces new context inference utilities that align with the enhanced context management in middleware.

Poem

Oh, I hop through lines of code,
A bunny in a type-safe mode.
Middleware fresh, contexts neat,
In every builder, route, and suite.
With Omit and Record, I dance with glee 🐇,
Celebrating changes as joyous as can be!

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

 ERR_PNPM_OPTIONAL_DEPS_REQUIRE_PROD_DEPS  Optional dependencies cannot be installed without production dependencies

Tip

⚡🧪 Multi-step agentic review comment chat (experimental)
  • We're introducing multi-step agentic chat in review comments. This experimental feature enhances review discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments.
    - To enable this feature, set early_access to true under in the settings.
✨ Finishing Touches
  • 📝 Generate Docstrings

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

@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 13, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown

@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 (1)
packages/server/src/context.test-d.ts (1)

14-16: Consider using a type alias instead of an empty interface.

The Empty interface doesn't have any properties, which is equivalent to {}. Consider using a type alias for better clarity.

-interface Empty {
-
-}
+type Empty = {}
🧰 Tools
🪛 Biome (1.9.4)

[error] 13-16: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between a5c2886 and 5457950.

📒 Files selected for processing (21)
  • packages/server/src/builder-variants.test-d.ts (15 hunks)
  • packages/server/src/builder-variants.ts (8 hunks)
  • packages/server/src/builder.test-d.ts (6 hunks)
  • packages/server/src/builder.ts (3 hunks)
  • packages/server/src/context.test-d.ts (1 hunks)
  • packages/server/src/context.test.ts (1 hunks)
  • packages/server/src/context.ts (1 hunks)
  • packages/server/src/implementer-procedure.test-d.ts (6 hunks)
  • packages/server/src/implementer-procedure.ts (3 hunks)
  • packages/server/src/implementer-variants.test-d.ts (2 hunks)
  • packages/server/src/implementer-variants.ts (2 hunks)
  • packages/server/src/implementer.test-d.ts (2 hunks)
  • packages/server/src/implementer.ts (2 hunks)
  • packages/server/src/middleware-decorated.test-d.ts (5 hunks)
  • packages/server/src/middleware-decorated.ts (2 hunks)
  • packages/server/src/middleware.test-d.ts (1 hunks)
  • packages/server/src/middleware.ts (2 hunks)
  • packages/server/src/procedure-decorated.test-d.ts (3 hunks)
  • packages/server/src/procedure-decorated.ts (2 hunks)
  • packages/server/src/router-utils.test-d.ts (2 hunks)
  • packages/server/src/router-utils.ts (2 hunks)
🧰 Additional context used
🪛 GitHub Actions: CI
packages/server/src/implementer.ts

[error] 52-52: Generic type 'EnhancedRouter' requires 4 type argument(s).


[error] 56-56: Generic type 'EnhancedRouter' requires 4 type argument(s).


[error] 52-52: Generic type 'EnhancedRouter' requires 4 type argument(s).


[error] 56-56: Generic type 'EnhancedRouter' requires 4 type argument(s).

packages/server/src/implementer-variants.ts

[error] 32-32: Generic type 'EnhancedRouter' requires 4 type argument(s).


[error] 36-36: Generic type 'EnhancedRouter' requires 4 type argument(s).


[error] 32-32: Generic type 'EnhancedRouter' requires 4 type argument(s).


[error] 36-36: Generic type 'EnhancedRouter' requires 4 type argument(s).

🪛 Biome (1.9.4)
packages/server/src/context.test-d.ts

[error] 13-16: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)

🔇 Additional comments (107)
packages/server/src/middleware-decorated.test-d.ts (5)

4-4: Appropriate replacement for removed MergedContext import.

The import of Context type is added correctly to replace the removed MergedContext import, aligning with the changes to context handling approach in this PR.


55-55: Improved type safety with more precise context types.

Changing from CurrentContext & { extra: boolean } to Omit<CurrentContext, 'extra'> & { extra: boolean } improves type safety by explicitly handling property conflicts. This ensures the middleware's extra property takes precedence over any potential extra property in CurrentContext.

Also applies to: 91-91


73-74: Enhanced context type definitions for better type safety.

The updated type definitions for the returned middleware provide more precise type handling by:

  1. Using CurrentContext & Record<never, never> for initial context
  2. Using Omit<{ extra: boolean }, never> & { extra2: boolean } for current context

This approach correctly reflects how middleware contexts are merged, addressing the initial problem of middleware context types being ignored.

Also applies to: 113-114


82-83: Improved error messaging for context type mismatches.

The error message update from context conflicts to "invalid TInContext" better describes the actual issue: incompatible initial context types between middlewares. This change helps developers understand type errors more easily.

Also applies to: 128-129


134-158: Thorough testing of initial context handling with middlewares.

This new test case properly validates the middleware's behavior with specific initial context types. It confirms that the DecoratedMiddleware correctly merges the initial contexts from different middlewares while respecting type constraints.

The specific test with { cacheable?: boolean } as initial context ensures that optional properties are handled correctly during the merging process.

packages/server/src/context.test.ts (1)

1-1: Function renaming reflects improved context handling approach.

Renaming from mergeContext to mergeCurrentContext makes the function's purpose more explicit, indicating that it specifically merges the current context rather than any context. This aligns with the PR's goal of distinguishing between initial and current context types in middleware.

Also applies to: 3-5

packages/server/src/middleware.test-d.ts (1)

26-26: Simplified middleware next function type signature.

Removing the context type parameter from MiddlewareNextFn simplifies the type signature while improving the separation between initial and current context handling. This change is part of the broader effort to fix how middleware context types are managed.

packages/server/src/context.test-d.ts (4)

1-1: Updated imports reflect the new context handling approach.

The import changes from ConflictContextGuard, MergedContext to ContextExtendsGuard, MergedCurrentContext, MergedInitialContext properly reflect the new type system that distinguishes between initial and current contexts.


3-7: Comprehensive testing of initial context merging.

The tests for MergedInitialContext thoroughly verify that:

  1. Properties from both input types are included in the merged result
  2. Conflicting properties are correctly identified (resulting in never type)
  3. Properties in the exclusion set are properly handled

This ensures the type system correctly enforces the desired behavior for initial context merging.


9-12: Thorough validation of current context merging.

The tests for MergedCurrentContext properly verify that:

  1. Properties from both input types are included in the merged result
  2. When properties overlap, the second type's property takes precedence

This aligns with the expected behavior where middleware can override context properties.


18-28: Comprehensive testing of context extension guard.

The tests for ContextExtendsGuard thoroughly verify various extension scenarios:

  1. When the first type is assignable to the second type (returns unknown)
  2. When empty types or optional properties are involved
  3. When type extension fails (returns never) due to incompatible types

This ensures that middleware context type compatibility is properly enforced, addressing the core issue in the PR.

packages/server/src/implementer.ts (2)

3-3: Updated context type imports for enhanced middleware context handling.

The imports now include the new ContextExtendsGuard, MergedCurrentContext, and MergedInitialContext types which support the improved middleware context type validation introduced in this PR.


35-49: Improved middleware context type handling.

This update to the use method significantly enhances type safety by:

  1. Separating input and output context types with two generic parameters (UOutContext and UInContext)
  2. Using ContextExtendsGuard to validate that the middleware's input context is compatible with the current context
  3. Properly merging both initial and current contexts to preserve context type information throughout the middleware chain

This change directly addresses the PR's objective of reflecting middleware initial context in procedure types.

packages/server/src/implementer-variants.ts (2)

2-2: Updated context type imports for enhanced middleware context handling.

The imports now include the new ContextExtendsGuard, MergedCurrentContext, and MergedInitialContext types which are essential for the improved middleware context type system.


15-29: Improved middleware context type handling.

This change to the use method signature enhances type safety by:

  1. Using separate input and output context type parameters
  2. Adding ContextExtendsGuard to validate that input context extends the current context
  3. Properly merging initial and current contexts using the new utility types

These changes ensure that middleware context requirements are properly enforced throughout the middleware chain.

packages/server/src/implementer.test-d.ts (3)

4-4: Updated type imports to support new context handling system.

The test now imports MergedCurrentContext instead of the older context merging type, and adds the Middleware type to the imports. These changes align the tests with the new context handling system implemented in this PR.

Also applies to: 10-10


91-125: Enhanced tests for middleware without input mapping.

The updated test case for .use without map input thoroughly validates the new context handling system. It includes:

  1. Detailed type checking for middleware parameters
  2. Verification that the resulting types use MergedCurrentContext correctly
  3. Additional tests for invalid input contexts and type mismatches

This ensures the middleware properly reflects the initial context types as intended by the PR.


127-137: Added test for middleware with custom input context.

This new test case specifically validates the scenario where middleware specifies a custom input context (with cacheable? property). It verifies that:

  1. The middleware's input context requirements are preserved in the resulting type
  2. The initial context is correctly merged with the input context requirements

This test directly addresses the core issue this PR aims to fix.

packages/server/src/middleware.ts (2)

16-18: Simplified middleware next function interface.

The MiddlewareNextFn interface has been simplified by:

  1. Removing the TInContext generic parameter
  2. Changing the constraint on the U type parameter from Context & Partial<TInContext> to just Context

This change allows for more flexible context handling by decoupling the next function's context requirements from the input context, addressing the issue described in the PR.


37-37: Updated next function type in middleware options.

The next property type has been updated to use the simplified MiddlewareNextFn interface, removing the TInContext parameter. This change is consistent with the interface update and completes the middleware context handling improvements.

packages/server/src/router-utils.test-d.ts (6)

4-4: Added import for context merging types.

The newly imported Context and MergedInitialContext are essential for properly handling middleware context types in router utilities.


21-24: Added type definitions for enhanced context testing.

These new type definitions (TErrorMap, InitialContext2, CurrentContext2) correctly model the extended context types needed to test the middleware context inheritance behavior.


26-37: Updated type assertions to use MergedInitialContext.

This change fixes the core issue by ensuring that the procedure type correctly reflects the middleware's initial context. Now the Enhanced['ping'] type properly merges InitialContext2 with the original InitialContext.


39-50: Applied MergedInitialContext to nested router procedures.

Consistently applying the same context type changes to nested router procedures ensures type safety across the entire router hierarchy.


52-61: Applied context merging to pong procedure.

Now the pong procedure also correctly uses MergedInitialContext to combine InitialContext2 with the base Context.


63-74: Applied context merging to nested pong procedure.

Ensuring consistent application of the MergedInitialContext approach to all nested procedures.

packages/server/src/implementer-variants.test-d.ts (5)

4-4: Updated import to use MergedCurrentContext.

Replaced MergedContext with MergedCurrentContext, which better reflects the purpose of this type in handling the current context state during middleware execution.


10-10: Added Middleware type import.

This allows for stronger typing when working with middleware in tests, enabling better type checking between middleware and procedures.


22-49: Enhanced use method test with explicit context handling.

The test has been improved to:

  1. Clarify that it's testing the .use method without mapping input
  2. Verify type safety for all middleware parameters
  3. Test that extra context properties are properly merged with MergedCurrentContext
  4. Add type safety checks for the resulting implementer

This ensures the implementer correctly reflects middleware context.


51-56: Added tests for invalid context types.

These tests validate that the type system correctly rejects invalid context types when using middleware, preventing potential runtime errors from mismatched contexts.


58-68: Added test for middleware with explicit input context.

This test case validates the key fix in this PR - ensuring that when a middleware specifies an input context type (like { cacheable?: boolean }), the implementer correctly merges this with the existing context.

packages/server/src/implementer-procedure.test-d.ts (7)

10-10: Added Middleware type import.

Including the Middleware type enables stronger typing for middleware components in the implementer procedure tests.


83-91: Refined context type handling in ImplementedProcedure.

Updated to use Omit<CurrentContext, 'extra'> instead of directly extending the context. This approach prevents property conflicts and provides more precise control over which properties are included in the merged context.


93-100: Added tests for invalid context inputs.

These tests ensure that the type system properly rejects invalid input context types in middleware, preventing potential runtime errors from mismatched contexts.


142-166: Added support for middleware with explicit input context.

This test case validates the core fix in this PR - when a middleware specifies an input context type (like { cacheable?: boolean }), the procedure correctly merges this with the existing context types.


259-266: Updated ProcedureImplementer context handling.

Improved the type definition for applied to properly reflect how context types are merged in procedure implementers.


268-274: Added type validation for middleware context types.

These tests ensure that invalid context types are properly rejected by the type system when using middleware with procedure implementers.


324-348: Added support for middleware with explicit input context in ProcedureImplementer.

This test case confirms that the procedure implementer correctly merges the middleware's input context ({ cacheable?: boolean }) with the existing context, both with and without input mapping.

packages/server/src/procedure-decorated.test-d.ts (6)

7-7: Added Middleware type import.

Including the Middleware type enables stronger typing for middleware components in decorated procedure tests.


112-118: Refined context type handling in DecoratedProcedure.

Updated to use Omit<CurrentContext, 'extra'> for more precise control over merged context properties, ensuring that property conflicts are correctly handled.


121-129: Added tests for invalid context inputs.

These tests verify that the type system correctly rejects invalid middleware context types, preventing potential runtime errors.


151-158: Updated context type handling for mapped inputs.

Maintained consistent context type handling when using middleware with input mapping, ensuring proper type safety.


160-168: Added type validation for middleware with mapped inputs.

These tests ensure that invalid context types are properly rejected even when using middleware with input mapping.


170-194: Added tests for middleware with explicit input context.

These tests validate the key improvement in this PR - ensuring that decorated procedures correctly reflect and merge the initial context type specified by middleware (such as { cacheable?: boolean }).

packages/server/src/context.ts (4)

3-7: Ensure clarity on key collisions in MergedInitialContext.
MergedInitialContext cleverly merges TInitial and partial TAdditional while excluding the overlapping keys from TCurrent. This approach is valid, but be mindful of scenarios where TInitial and TAdditional share keys not appearing in TCurrent; it may produce unexpected name collisions or overshadowing if the code evolves. Overall, the logic is sound.


9-9: MergedCurrentContext structure looks solid.
Omit<T, keyof U> & U is a standard pattern for layering context types. This ensures that U overrides any corresponding keys in T.


11-14: Straightforward function for merging contexts.
mergeCurrentContext correctly applies the new MergedCurrentContext type and merges the two objects. The implementation is straightforward and aligns with your updated type definitions.


18-19:

Details

✅ Verification successful

Verify usage of ContextExtendsGuard in complex intersections.
ContextExtendsGuard conditionally yields unknown or never, ensuring type compatibility. In more advanced intersection or extension scenarios, false negatives or positives can occur if upstream contexts are especially intricate.

To confirm correct usage, consider scanning for all references to ContextExtendsGuard to ensure sound context constraints:


🏁 Script executed:

#!/bin/bash
# Searching through the entire codebase for "ContextExtendsGuard" references:
rg -A 5 "ContextExtendsGuard"

Length of output: 17261


ContextExtendsGuard Usage Verified
The scan confirms that ContextExtendsGuard is consistently used across the codebase (in builder, implementer, middleware, etc.) and the tests in context.test-d.ts validate its behavior in both straightforward and complex intersection scenarios. No issues were found; the conditional type correctly yields unknown or never as expected.

packages/server/src/procedure-decorated.ts (7)

4-4: Imports updated for new context merging types.
No issues here—importing Context, ContextExtendsGuard, MergedCurrentContext, and MergedInitialContext aligns with the implemented changes in context.ts.


56-59: use(...) overload with defaulted UInContext is well-defined.
Allowing UInContext to default to TCurrentContext provides flexibility. This ensures that middleware contexts can remain consistent if no specialized input context is needed.


65-66: Intersection return type for context validation.
Combining ContextExtendsGuard<UInContext, TCurrentContext> and ContextExtendsGuard<TCurrentContext, MergedCurrentContext<TCurrentContext, UOutContext>> properly enforces correct context evolution across middleware.


68-69: MergedInitialContext in returned DecoratedProcedure.
Providing an updated TInitialContext with merged in-context types ensures that the final decorated procedure consistently reflects the newly added middleware’s context.


76-78: Overload with an additional UInput parameter.
This second overload adds an extra level of flexibility by letting a custom input type differ from the original schema output. The signature is coherent with the typed approach.


86-87: Intersection return type for the second overload.
The repeated pattern of context intersection remains consistent and helps maintain type safety across different input variants.


89-90: Refined TInitialContext and TCurrentContext type merges.
Integrating MergedInitialContext and MergedCurrentContext here matches the design in context.ts, ensuring the final, decorated procedure’s context is properly updated.

packages/server/src/implementer-procedure.ts (5)

5-5: Newly imported merged context utilities.
Including MergedCurrentContext, MergedInitialContext, and ContextExtendsGuard reflects the unified approach introduced in context.ts.


22-25: Revamped use(...) method for ImplementedProcedure (first overload).
Adopting UOutContext and UInContext clarifies the distinction between incoming and outgoing middleware contexts. Returning both ContextExtendsGuard checks and the updated ImplementedProcedure ensures safe type evolution.

Also applies to: 31-35


42-45: Second overload with custom input type.
Similar to the first overload, but includes an additional UInput parameter and a mapInput function. These changes maintain consistency with the overhauled context system while enabling tailored input transformations.

Also applies to: 52-56


111-114: use(...) method in ProcedureImplementer (first overload).
Mirroring the ImplementedProcedure patterns, this ensures the builder interface also enforces correct context layering. The intersection types remain consistent with the broader design.

Also applies to: 120-124


130-133: Extended overload in ProcedureImplementer with custom input.
Providing UInput and mapping logic is identical to the approach above. The type constraints effectively create a seamless middleware chain, preserving correctness from builder to final procedure.

Also applies to: 140-144

packages/server/src/router-utils.ts (7)

2-2: Imports look good.
No concerns regarding importing these types; they are used consistently throughout the file.


74-79: Robust type definition for EnhancedRouter.
Introducing TInitialContext, TCurrentContext, and TErrorMap as constraints strengthens context validation throughout the router. This approach improves maintainability and type safety.


81-83: Appropriate recursive type usage.
These lines properly extend EnhancedRouter for nested lazy routers and procedures, preserving type safety in recursive structures.


91-91: Merging initial context.
Using MergedInitialContext<TInitialContext, UInitialContext, TCurrentContext> ensures that all context layers are properly combined with minimal duplication.


99-99: Mapped type extension for child routers.
This mapped type approach effectively applies the enhanced router type logic to each entry in the router object, promoting scalability.


107-112: Enhanced generic parameters on enhanceRouter.
Requiring TInitialContext, TCurrentContext, and TErrorMap adds clarity and consistency, aligning with other updated router definitions.


115-115: Return type alignment for enhanceRouter.
Returning EnhancedRouter<T, TInitialContext, TCurrentContext, TErrorMap> enforces consistency and ensures consumers get the fully typed router object.

packages/server/src/middleware-decorated.ts (6)

2-2: Expanded imports for advanced context handling.
Adding ContextExtendsGuard, MergedCurrentContext, and MergedInitialContext supports more thorough type checks in middleware composition.


18-20: New generic parameters in concat signature.
Allowing UOutContext extends Context and UInContext extends Context = MergedCurrentContext<...> ensures higher flexibility when chaining middlewares.


27-35: Strengthened type checks with ContextExtendsGuard.
This pattern ensures any concatenated middleware extends the existing in-context contract, preventing incompatible context merges.


40-41: Refined overload with default generic arguments.
Defaulting UInContext to MergedCurrentContext<TInContext, TOutContext> helps avoid unwieldy type placeholders in common middleware compositions.


43-44: Consistent context enforcement in second overload.
Requiring UInContext aligns the typed input flow across multiple middleware usage scenarios.


51-59: Extended DecoratedMiddleware return signature.
By merging initial/current contexts and confirming them via ContextExtendsGuard, these lines guarantee that the final decorated middleware remains type safe.

packages/server/src/builder.test-d.ts (7)

9-9: Added Middleware import.
Pulling in Middleware clarifies the typed approach to builder usage and tests.


235-236: Refined BuilderWithMiddlewares type.
Wrapping InitialContext and adjusting CurrentContext with extra property is consistent with how contexts are extended in the codebase.


245-246: Ensuring incompatible TInContext yields never.
These test lines confirm that invalid middleware context types are disallowed, preventing silent type mismatches.


277-278: Additional context merging test.
Again verifying InitialContext & Record<never, never> merges with a specialized CurrentContext that includes extra.


292-293: Incompatible TInContext scenario repeated.
This negative test ensures the builder rejects middleware with incompatible context types, preserving correctness.


434-435: Correct usage of EnhancedRouter with router.
These lines confirm that .router(...) returns a strongly typed EnhancedRouter reflecting the updated context and error map.


459-460: Lazy router integration with EnhancedRouter.
The type check validates that a lazily imported router is properly wrapped with EnhancedRouter, maintaining the same context constraints.

packages/server/src/builder-variants.test-d.ts (14)

8-8: New imports look appropriate.
Pulling in Middleware and MiddlewareOutputFn better supports the updated .use method type checks and output function references.


71-108: Thorough type testing for .use without mapped input.
These changes correctly ensure that the middleware function sees the right input (“unknown” by default) and merges the context into CurrentContext as expected. The negative tests (@ts-expect-error) further confirm that invalid input contexts or output mappings are detected properly.


110-123: Consistent handling of TInContext.
Allowing TInContext to default to TCurrentContext when unspecified—and mapping explicitly when needed—provides crucial flexibility in typed middleware usage. This matches the broader approach and looks good.


331-367: Expanded .use coverage for ProcedureBuilder.
These lines mirror the same context-merging approach, ensuring consistent type-checking for procedures. The tests are well-structured, with negative checks confirming type safety.


370-383: TInContext usage with ProcedureBuilder is well-validated.
Explicitly testing optional cacheable?: boolean merges seamlessly with the existing CurrentContext. The negative test coverage looks robust.


547-548: Context merging logic in .use for ProcedureBuilderWithInput.
The lines reflect the same strategy of verifying the updated context types (e.g., extra: boolean). This helps ensure every new context key merges properly.

Also applies to: 556-557


613-636: Proper mapping for TInContext in ProcedureBuilderWithInput.
Splitting the middleware function from the mapping function is especially useful for advanced input transformations. The type-level checks here appear accurate.


764-792: ProcedureBuilderWithOutput .use without map input.
Testing the default input as unknown while applying an output shape is consistent with the design. The sync between InferSchemaInput<TOutputSchema> and MiddlewareOutputFn is verified.


800-814: Handling TInContext with output-specific builder.
Ensuring a separate context can be introduced (e.g., { cacheable?: boolean }) maintains consistent merges at compile time. Good coverage of potential error scenarios.


940-980: Type safety for .use in ProcedureBuilderWithInputOutput (no map input).
These lines confirm the context merges with both input and output schemas present. The negative tests keep everything safe.


1030-1054: TInContext in ProcedureBuilderWithInputOutput.
Excellent update—flexible input contexts with thorough negative tests. Mapping is handled carefully to avoid incorrect input usage.


1140-1173: RouterBuilder .use tests without map input.
Merging the new partial context fields into CurrentContext and confirming negative scenarios with 'invalid' keys ensures routers respect the same style as procedures.


1176-1186: RouterBuilder .use with custom TInContext.
The refined approach for dynamic context merges is consistent with the other builder variants. Great to see the thorough coverage.


1206-1230: Enhanced router usage within RouterBuilder.
These changes show the final step in merging contexts when loading external routers—both immediate (.router()) and deferred (.lazy()). Type checks align well with updated generics.

packages/server/src/builder.ts (5)

3-3: Refined import for context merging.
Switching to ContextExtendsGuard, MergedCurrentContext, and MergedInitialContext ensures more granular control when checking context compatibility.


125-163: Overhauled .use API for flexible input and output contexts.
The new <UInContext extends Context = TCurrentContext> paradigm is a clear improvement, letting developers specify narrower or broader incoming contexts without losing strong typing. Negative path checks are handled by ContextExtendsGuard.


145-163: Mapped .use method variant.
Providing the secondary mapInput parameter fosters advanced transformations while preserving the core context-based checks. This significantly enhances middleware extensibility.


243-243: Refined router integration return type.
Ensuring that enhanceRouter returns EnhancedRouter<U, TInitialContext, TCurrentContext, TErrorMap> cements correct routing context merges as soon as the router is attached.


249-250: Improved lazy-loading for routers.
The new type signature enforces concurrency in context definitions even for asynchronously loaded routers. Excellent guard against mismatched contexts at runtime.

packages/server/src/builder-variants.ts (8)

3-3: Importing refined context utilities.
This change aligns ContextExtendsGuard and MergedContext usage throughout builder variants, ensuring all derived interfaces can share the new context merging logic.


33-51: BuilderWithMiddlewares::use now supports UInContext.
The additional generic clarifies where a middleware’s input context can differ from the builder’s current context, which improves type safety for advanced designs.


107-124: ProcedureBuilder::use with the updated generics.
This mirrors the approach in BuilderWithMiddlewares, ensuring procedure-level usage can also handle distinct input contexts. The negative tests likely catch incorrect merges.


160-178: ProcedureBuilderWithInput::use gains improved context merging flows.
Explicitly factoring out InferSchemaOutput<TInputSchema> for the middleware’s input type is a neat addition. The twin call style (with or without mapInput) is flexible yet safe.

Also applies to: 180-198


238-255: ProcedureBuilderWithOutput::use—output shapes validated.
By referencing InferSchemaInput<TOutputSchema>, these lines preserve the full chain of transformations. This ensures that a builder calls .use() with the correct output type.


288-305: ProcedureBuilderWithInputOutput::use maintains input-output correctness.
The generics for InferSchemaOutput<TInputSchema> and InferSchemaInput<TOutputSchema> confirm that both the request and response shapes remain strongly typed. Great consistency with the rest of the changes.

Also applies to: 307-325


351-367: RouterBuilder::use—refined for merged contexts.
Shifting from a single TCurrentContext to a parameterized UInContext fosters the same advanced behavior as in procedure builders, unifying the entire codebase’s approach to typed contexts.


378-379: Lazy router signature broadening.
These lines confirm that lazy-loading a router still respects the newly introduced TCurrentContext merges, matching the immediate .router() method.

Comment thread packages/server/src/implementer.ts Outdated
Comment thread packages/server/src/implementer-variants.ts Outdated
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Mar 13, 2025

Open in Stackblitz

More templates

@orpc/client

npm i https://pkg.pr.new/@orpc/client@234

@orpc/contract

npm i https://pkg.pr.new/@orpc/contract@234

@orpc/openapi

npm i https://pkg.pr.new/@orpc/openapi@234

@orpc/openapi-client

npm i https://pkg.pr.new/@orpc/openapi-client@234

@orpc/react-query

npm i https://pkg.pr.new/@orpc/react-query@234

@orpc/shared

npm i https://pkg.pr.new/@orpc/shared@234

@orpc/server

npm i https://pkg.pr.new/@orpc/server@234

@orpc/solid-query

npm i https://pkg.pr.new/@orpc/solid-query@234

@orpc/standard-server

npm i https://pkg.pr.new/@orpc/standard-server@234

@orpc/standard-server-fetch

npm i https://pkg.pr.new/@orpc/standard-server-fetch@234

@orpc/standard-server-node

npm i https://pkg.pr.new/@orpc/standard-server-node@234

@orpc/svelte-query

npm i https://pkg.pr.new/@orpc/svelte-query@234

@orpc/vue-colada

npm i https://pkg.pr.new/@orpc/vue-colada@234

@orpc/vue-query

npm i https://pkg.pr.new/@orpc/vue-query@234

@orpc/zod

npm i https://pkg.pr.new/@orpc/zod@234

commit: 6cfcfd7

Copy link
Copy Markdown

@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)
packages/server/src/context.test-d.ts (1)

14-16: Consider using a type alias instead of an empty interface

The Empty interface is equivalent to {}. Using a type alias would be more appropriate here.

-interface Empty {
-
-}
+type Empty = {};
🧰 Tools
🪛 Biome (1.9.4)

[error] 13-16: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between dab7d8f and 6cfcfd7.

📒 Files selected for processing (9)
  • packages/server/src/builder-variants.ts (8 hunks)
  • packages/server/src/builder.ts (3 hunks)
  • packages/server/src/context.test-d.ts (1 hunks)
  • packages/server/src/context.ts (1 hunks)
  • packages/server/src/implementer-procedure.ts (3 hunks)
  • packages/server/src/implementer-variants.ts (2 hunks)
  • packages/server/src/implementer.ts (2 hunks)
  • packages/server/src/middleware-decorated.ts (2 hunks)
  • packages/server/src/procedure-decorated.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/server/src/implementer-variants.ts
  • packages/server/src/builder-variants.ts
  • packages/server/src/middleware-decorated.ts
  • packages/server/src/builder.ts
🧰 Additional context used
🪛 Biome (1.9.4)
packages/server/src/context.test-d.ts

[error] 13-16: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)

🔇 Additional comments (20)
packages/server/src/context.test-d.ts (4)

1-1: Properly updated imports to match new context type system

The import statement has been correctly updated to import the new context-related types that replace the old ones: ContextExtendsGuard, MergedCurrentContext, and MergedInitialContext.


3-7: LGTM: Comprehensive test coverage for MergedInitialContext

This test correctly verifies the type merging behavior for the new MergedInitialContext type, including how it handles property merging and conflicts between the different context types.


9-12: LGTM: Proper validation of MergedCurrentContext

The test correctly validates both the successful merging of properties and the conflict resolution behavior where properties in the second context override those in the first context.


18-31: LGTM: Thorough test coverage for ContextExtendsGuard

The test covers a comprehensive set of scenarios for the new ContextExtendsGuard type, including:

  • Successfully extending when the first type has all properties of the second type
  • Successfully extending when types are identical
  • Successfully extending with empty types and optional properties
  • Correctly failing when extending in the wrong direction or with incompatible types

This robust test coverage ensures the type guard behaves as expected in all cases.

packages/server/src/implementer.ts (4)

3-3: Properly updated imports to match new context type system

The import statement has been correctly updated to reflect the new context types: ContextExtendsGuard, MergedCurrentContext, and MergedInitialContext.


35-49: Added input/output context separation in middleware's use method

This change is crucial for the PR objective. The middleware use method has been updated to properly reflect the middleware's context types:

  1. Two generic type parameters are now used:

    • UOutContext for the output context
    • UInContext for the input context (defaulting to current context)
  2. The return type now properly enforces that:

    • The current context extends the middleware's input context
    • The middleware's output context is properly merged with initial context

This fixes the bug where a procedure wasn't validating that the context passed to the middleware matches the expected type.


52-52: Added missing type parameter to EnhancedRouter

The return type for the router method has been properly updated to include the required fourth type parameter (TCurrentContext) for EnhancedRouter, fixing the type error mentioned in the past review comments.


56-56: Added missing type parameter to EnhancedRouter

The return type for the lazy method has been properly updated to include the required fourth type parameter (TCurrentContext) for EnhancedRouter, fixing the type error mentioned in the past review comments.

packages/server/src/context.ts (4)

3-8: Improved context merging with MergedInitialContext

This new type properly addresses the PR objective by introducing a more sophisticated context merging strategy:

  • TInitial: The base initial context
  • TAdditional: The middleware's input context type
  • TCurrent: The current context type

The implementation correctly merges the initial context with the additional context, but excludes properties from the additional context that are already present in the current context. This ensures that middleware's initial context is properly reflected in the procedure context.


9-9: LGTM: Added MergedCurrentContext for output context handling

The new MergedCurrentContext type correctly implements the merging strategy for the current context and middleware's output context, where properties from the output context override matching properties in the current context.


11-16: Renamed and updated mergeContext to reflect new type system

The function has been properly renamed from mergeContext to mergeCurrentContext to match its specific purpose, and its return type has been updated to use the new MergedCurrentContext type.


18-18: Improved type safety with ContextExtendsGuard

The new ContextExtendsGuard type replaces the previous ConflictContextGuard with a more precise type check. It validates that the first context type extends the second context type, returning unknown if valid and never if invalid. This ensures type safety when combining contexts in middleware.

packages/server/src/procedure-decorated.ts (3)

4-4: Properly updated imports to match new context type system

The import statement has been correctly updated to import the new context types: ContextExtendsGuard, MergedCurrentContext, and MergedInitialContext.


56-74: Added input/output context separation in decorated procedure

This change is crucial for the PR objective. The decorated procedure's use method now:

  1. Takes separate generic type parameters for input and output contexts
  2. Uses ContextExtendsGuard to ensure type safety for both:
    • Validating that the current context extends the middleware's input context
    • Validating that the middleware's output context extends the current context
  3. Properly merges initial and current contexts using the new type system

This implementation ensures that middleware context types are correctly reflected in the procedure, addressing the core issue in the PR.


76-95: LGTM: Consistently updated the overloaded use method

The second overload of the use method (with input mapping) has been consistently updated to match the changes in the first overload, ensuring type safety and proper context merging for this variant as well.

packages/server/src/implementer-procedure.ts (5)

5-5: Import additions align with improved context type handling

The addition of ContextExtendsGuard, MergedCurrentContext, and MergedInitialContext types provides the necessary tools for the stricter context type validation being implemented in this PR.


22-40: Improved type safety for middleware context handling

This change properly reflects the middleware's initial context type in the procedure by:

  1. Separating input (UInContext) and output (UOutContext) context types
  2. Using ContextExtendsGuard to ensure context compatibility
  3. Using MergedInitialContext to propagate middleware context requirements to the procedure

This addresses the core issue where procedures previously ignored the middleware's initial context type requirements.


42-61: Consistent type safety improvements for input-mapping middleware

Similar to the previous overload, these changes correctly implement the middleware context type validation for the input-mapping version of the use method. The implementation maintains consistency with the other overload and properly handles context type validation.


111-128: Consistent implementation in ProcedureImplementer interface

The changes to the ProcedureImplementer interface mirror those in the ImplementedProcedure interface, ensuring consistent type safety across the builder pattern. The context type validation is properly implemented to reflect middleware's context requirements.


130-148: Input-mapping middleware consistently updated in ProcedureImplementer

The second overload of the use method in ProcedureImplementer has been correctly updated to match the pattern established in the other changes. This completes the implementation of stricter context type validation throughout the procedure builder system.

@dinwwwh dinwwwh merged commit d452413 into main Mar 14, 2025
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