-
-
Notifications
You must be signed in to change notification settings - Fork 141
feat(trpc): support event iterator for toORPCRouter #716
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,14 +1,21 @@ | ||||||||||||||||||||||
| import type { AsyncIteratorClass } from '@orpc/shared' | ||||||||||||||||||||||
| import type { AnyProcedure, AnyRouter, inferRouterContext } from '@trpc/server' | ||||||||||||||||||||||
| import type { inferRouterMeta, Parser } from '@trpc/server/unstable-core-do-not-import' | ||||||||||||||||||||||
| import type { inferRouterMeta, Parser, TrackedData } from '@trpc/server/unstable-core-do-not-import' | ||||||||||||||||||||||
| import { mapEventIterator } from '@orpc/client' | ||||||||||||||||||||||
| import * as ORPC from '@orpc/server' | ||||||||||||||||||||||
| import { isTypescriptObject } from '@orpc/shared' | ||||||||||||||||||||||
| import { TRPCError } from '@trpc/server' | ||||||||||||||||||||||
| import { getHTTPStatusCodeFromError } from '@trpc/server/unstable-core-do-not-import' | ||||||||||||||||||||||
| import { isObject, isTypescriptObject } from '@orpc/shared' | ||||||||||||||||||||||
| import { isTrackedEnvelope, TRPCError } from '@trpc/server' | ||||||||||||||||||||||
| import { getHTTPStatusCodeFromError, isAsyncIterable } from '@trpc/server/unstable-core-do-not-import' | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| export interface experimental_ORPCMeta extends ORPC.Route { | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| export type experimental_ToORPCOutput<T> | ||||||||||||||||||||||
| = T extends AsyncIterable<infer TData, infer TReturn, infer TNext> | ||||||||||||||||||||||
| ? AsyncIteratorClass<TData, TReturn, TNext> | ||||||||||||||||||||||
| : T | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| export type experimental_ToORPCRouterResult<TContext extends ORPC.Context, TMeta extends ORPC.Meta, TRecord extends Record<string, any>> | ||||||||||||||||||||||
| = { | ||||||||||||||||||||||
| [K in keyof TRecord]: | ||||||||||||||||||||||
|
|
@@ -17,7 +24,7 @@ export type experimental_ToORPCRouterResult<TContext extends ORPC.Context, TMeta | |||||||||||||||||||||
| TContext, | ||||||||||||||||||||||
| object, | ||||||||||||||||||||||
| ORPC.Schema<TRecord[K]['_def']['$types']['input'], unknown>, | ||||||||||||||||||||||
| ORPC.Schema<unknown, TRecord[K]['_def']['$types']['output']>, | ||||||||||||||||||||||
| ORPC.Schema<unknown, experimental_ToORPCOutput<TRecord[K]['_def']['$types']['output']>>, | ||||||||||||||||||||||
| object, | ||||||||||||||||||||||
| TMeta | ||||||||||||||||||||||
| > | ||||||||||||||||||||||
|
|
@@ -88,16 +95,42 @@ function toORPCProcedure(procedure: AnyProcedure) { | |||||||||||||||||||||
| middlewares: [], | ||||||||||||||||||||||
| inputSchema: toDisabledStandardSchema(procedure._def.inputs.at(-1)), | ||||||||||||||||||||||
| outputSchema: toDisabledStandardSchema((procedure as any)._def.output), | ||||||||||||||||||||||
| handler: async ({ context, signal, path, input }) => { | ||||||||||||||||||||||
| handler: async ({ context, signal, path, input, lastEventId }) => { | ||||||||||||||||||||||
| try { | ||||||||||||||||||||||
| return await procedure({ | ||||||||||||||||||||||
| const trpcInput = lastEventId !== undefined && (input === undefined || isObject(input)) | ||||||||||||||||||||||
| ? { ...input, lastEventId } | ||||||||||||||||||||||
| : input | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
Comment on lines
+98
to
+103
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainVerify input spreading behavior with complex objects. The input merging logic looks correct, but spreading could have unexpected behavior with objects containing getters, symbols, or non-enumerable properties. 🏁 Script executed: #!/bin/bash
# Description: Search for test cases that verify input merging behavior with complex objects
# Expected: Tests covering edge cases like objects with getters, symbols, or prototype pollution
rg -A 10 -B 5 "lastEventId.*input|input.*lastEventId" --type tsLength of output: 17376 Add tests for input merging edge cases with complex objects The current tests only cover primitive and plain‐object inputs. Since object spread only copies own, enumerable, string-keyed properties, please add unit tests in
This will ensure the merge 🤖 Prompt for AI Agents |
||||||||||||||||||||||
| const output = await procedure({ | ||||||||||||||||||||||
| ctx: context, | ||||||||||||||||||||||
| signal, | ||||||||||||||||||||||
| path: path.join('.'), | ||||||||||||||||||||||
| type: procedure._def.type, | ||||||||||||||||||||||
| input, | ||||||||||||||||||||||
| getRawInput: () => input, | ||||||||||||||||||||||
| input: trpcInput, | ||||||||||||||||||||||
| getRawInput: () => trpcInput, | ||||||||||||||||||||||
| }) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| if (isAsyncIterable(output)) { | ||||||||||||||||||||||
| return mapEventIterator(output[Symbol.asyncIterator](), { | ||||||||||||||||||||||
| error: async error => error, | ||||||||||||||||||||||
| value: (value) => { | ||||||||||||||||||||||
| if (isTrackedEnvelope(value)) { | ||||||||||||||||||||||
| const [id, data] = value | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| return ORPC.withEventMeta({ | ||||||||||||||||||||||
| id, | ||||||||||||||||||||||
| data, | ||||||||||||||||||||||
|
Comment on lines
+119
to
+122
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The cast
Suggested change
|
||||||||||||||||||||||
| } satisfies TrackedData<unknown>, { | ||||||||||||||||||||||
| id, | ||||||||||||||||||||||
| }) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| return value | ||||||||||||||||||||||
| }, | ||||||||||||||||||||||
| }) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| return output | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| catch (cause) { | ||||||||||||||||||||||
| if (cause instanceof TRPCError) { | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Uh oh!
There was an error while loading. Please reload this page.