Skip to content

feat(server): allow .concat middlewares with narrowed input types#420

Merged
dinwwwh merged 1 commit intomainfrom
feat/server/middleware-concat-can-narrow-down-input-types
Apr 18, 2025
Merged

feat(server): allow .concat middlewares with narrowed input types#420
dinwwwh merged 1 commit intomainfrom
feat/server/middleware-concat-can-narrow-down-input-types

Conversation

@dinwwwh
Copy link
Copy Markdown
Member

@dinwwwh dinwwwh commented Apr 17, 2025

For example, if middleware A accepts unknown as input, B can now specify a more specific input type (e.g., number, { id: string }, etc.). Previously, both A and B were required to use unknown for the input type when concatenated.

Summary by CodeRabbit

  • Documentation

    • Improved middleware documentation with new notes and examples on using input mapping and aligning input types when composing middleware.
  • Bug Fixes

    • Enhanced type safety and flexibility for middleware input types, ensuring better compatibility when chaining or transforming middleware.
  • Tests

    • Updated and expanded tests to verify correct handling and rejection of new input shapes in middleware.

For example, if middleware A accepts unknown as input, B can now specify a more specific input type (e.g., number, { id: string }, etc.).
Previously, both A and B were required to use unknown for the input type when concatenated.
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 17, 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 Apr 17, 2025 3:41am

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 17, 2025

Walkthrough

The changes update the middleware documentation and enhance the type system for decorated middleware in the codebase. Documentation is expanded to clarify how to use .mapInput for adapting and composing middleware with different input shapes. In the implementation, the DecoratedMiddleware interface gains a new generic parameter for the concat method, allowing for more flexible and precise input type propagation. Corresponding test files are updated to use a new input shape with two string properties, and additional type error tests are added to ensure type safety.

Changes

File(s) Change Summary
apps/content/docs/middleware.md Enhanced documentation with notes and examples explaining .mapInput for adapting middleware input types and aligning input types when concatenating middleware.
packages/server/src/middleware-decorated.ts Updated DecoratedMiddleware interface: added a generic UInput extends TInput to concat method overloads, allowing more flexible input type specification and propagation. Adjusted mapInput argument type accordingly. No runtime logic changes.
packages/server/src/middleware-decorated.test-d.ts Changed test input types from { input: string } to { input1: string, input2: string } throughout. Updated all relevant type assertions and tests. Added type error tests for incorrect input shapes. Adjusted callback parameter types for .mapInput and .concat methods to match new input shape.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant MiddlewareA
    participant MiddlewareB

    User->>MiddlewareA: Call with input { input1, input2 }
    MiddlewareA->>MiddlewareB: (After .mapInput or .concat) Call with mapped input
    MiddlewareB-->>User: Return processed result
Loading

Poem

In the warren of types, we hop and we bound,
With input shapes shifting, new pathways are found.
Docs now explain how to map and compose,
While generics ensure our middleware flows.
Two strings in our basket, not just one to bring—
Type-safe and nimble, our code’s in full spring!
🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings

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

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • 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 Apr 17, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

📢 Thoughts on this report? Let us know!

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Apr 17, 2025

More templates

@orpc/arktype

npm i https://pkg.pr.new/@orpc/arktype@420

@orpc/client

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

@orpc/openapi

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

@orpc/openapi-client

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

@orpc/contract

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

@orpc/react

npm i https://pkg.pr.new/@orpc/react@420

@orpc/react-query

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

@orpc/server

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

@orpc/shared

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

@orpc/solid-query

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

@orpc/standard-server

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

@orpc/standard-server-fetch

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

@orpc/standard-server-node

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

@orpc/svelte-query

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

@orpc/valibot

npm i https://pkg.pr.new/@orpc/valibot@420

@orpc/vue-colada

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

@orpc/vue-query

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

@orpc/zod

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

commit: 7024088

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

🔭 Outside diff range comments (1)
packages/server/src/middleware-decorated.ts (1)

7-79: 💡 Verification agent

🧩 Analysis chain

Verify implementation supports the new type definitions

While the type signature changes look good, it's important to ensure the implementation in decorateMiddleware correctly handles the narrowed input types.


🏁 Script executed:

#!/bin/bash
# Check if the implementation in decorateMiddleware can properly handle the narrowed input types

# Examine the decorated.concat implementation
cat packages/server/src/middleware-decorated.ts | grep -A 20 "decorated.concat = "

# Look for tests that verify this behavior
fd -t f test -e ts | grep -l middleware | xargs grep -l concat | xargs cat

Length of output: 1022


Fix concat to preserve narrowed input types

The current decorated.concat implementation in packages/server/src/middleware-decorated.ts casts everything to any, which bypasses your new generic signatures and means mapped or narrowed inputs aren’t actually enforced. You’ll need to:

• In middleware-decorated.ts, remove the as any casts around input, options, and return values in decorated.concat.
• Update the callback signatures to use the proper generic parameters (e.g. UInput, UMappedInput, TInput) instead of any.
• Add unit tests verifying that mapInput and concat truly narrow the input type (for example, assert that passing an incorrect input shape fails at compile time).

🧹 Nitpick comments (1)
apps/content/docs/middleware.md (1)

168-170: Added guidance for concatenating middlewares with different input types

Good informational note explaining that .mapInput can be used to align input types before concatenation, which is essential for users to understand when working with the new type narrowing feature.

Consider enhancing this section with a code example similar to the first info block, showing how to concatenate two middlewares with different input types. This would provide a more concrete illustration of the concept.

 ::: info
 If you want to concatenate two middlewares with different input types, you can use `.mapInput` to align their input types before concatenation.
+
+```ts
+const validateId = os.middleware(async ({ next }, input: number) => {
+  if (input <= 0) throw new Error('Invalid ID')
+  return next()
+})
+
+const validateUser = os.middleware(async ({ next }, input: { name: string }) => {
+  if (!input.name) throw new Error('Name required')
+  return next()
+})
+
+// Concatenate middlewares with different input types
+const validateUserWithId = validateId
+  .mapInput((input: { id: number, name: string }) => input.id)
+  .concat(validateUser.mapInput((input: { id: number, name: string }) => ({ name: input.name })))
+```
 :::
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 649a676 and 7024088.

📒 Files selected for processing (3)
  • apps/content/docs/middleware.md (2 hunks)
  • packages/server/src/middleware-decorated.test-d.ts (10 hunks)
  • packages/server/src/middleware-decorated.ts (3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
packages/server/src/middleware-decorated.test-d.ts (2)
packages/server/src/middleware-decorated.ts (1)
  • DecoratedMiddleware (7-79)
packages/server/tests/shared.ts (1)
  • CurrentContext (8-8)
packages/server/src/middleware-decorated.ts (3)
packages/server/src/context.ts (3)
  • Context (1-1)
  • MergedCurrentContext (9-9)
  • MergedInitialContext (3-7)
packages/server/src/builder.ts (1)
  • middleware (146-150)
packages/server/src/middleware.ts (2)
  • Middleware (46-61)
  • MapInputMiddleware (65-67)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: publish-commit
🔇 Additional comments (17)
packages/server/src/middleware-decorated.ts (6)

30-30: Type parameter enhancement for better input type narrowing

This change allows for more specific input types when concatenating middlewares. By introducing UInput extends TInput, a middleware can now accept a narrower input type than the middleware it's being concatenated with.


36-36: Updated middleware input type parameter to use narrowed type

The middleware input parameter now uses the new UInput generic type parameter, allowing for proper type narrowing in middleware chains.


44-44: Return type now preserves the narrowed input type

The returned DecoratedMiddleware now correctly propagates the narrowed input type through the middleware chain.


58-58: Added same type parameter enhancement to second concat overload

Consistent application of the UInput extends TInput type parameter to the second concat overload ensures both methods support input type narrowing.


70-70: Updated mapInput parameter to use narrowed input type

The mapInput parameter now maps from the narrowed UInput type rather than the original TInput, maintaining type safety throughout the middleware chain.


74-74: Return type consistency with narrowed input type

The returned DecoratedMiddleware from the second concat overload also correctly preserves the narrowed input type.

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

13-13: Updated test input type to a more complex shape

Changed from single property object { input: string } to a two-property object { input1: string, input2: string } to better test the new input type narrowing capabilities.


25-25: Consistent input type update in type assertions

Input type updated consistently in the middleware type assertions to match the type defined for the decorated object.


34-34: Updated mapInput test to work with new input type

The mapInput test now properly demonstrates transforming from a string literal to the new two-property object, testing the type narrowing capabilities.


53-53: Updated concat test to use the new input type

The concat test now expects input1 property from the input, properly testing the type propagation during middleware concatenation.


74-74: Updated expected type assertion for concat result

The type assertion for the concatenated middleware result now correctly expects the new input type with two properties.


83-84: Added type error test for incorrect input shape

New test ensures TypeScript correctly rejects inputs that don't match the expected shape, validating the type safety of the narrowed input types.


108-108: Updated mapInput parameter type in concat with map test

The input type in the mapInput callback now correctly reflects that only the input1 property is needed by the middleware after mapping.


116-116: Consistent input type in concat with map result type

The expected type for the concatenated middleware with mapInput correctly maintains the two-property input type.


131-132: Added type error test for input mismatch with mapInput

This test ensures TypeScript correctly rejects mapInput functions that use an invalid input type, further validating type safety.


146-146: Updated input types in TInContext tests

The input types in the TInContext tests are consistently updated to the new two-property format, ensuring comprehensive testing of the type system changes.

Also applies to: 157-157

apps/content/docs/middleware.md (1)

124-136: Added helpful documentation for mapInput usage

Excellent addition explaining how to adapt middleware to accept different input shapes using .mapInput. The example clearly demonstrates transforming from an object with an id property to a simple number input that the original middleware expects.

@dinwwwh dinwwwh merged commit 2d41af5 into main Apr 18, 2025
8 checks passed
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