Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions packages/contract/src/schema.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,22 @@ import type { AnySchema, InferSchemaInput, InferSchemaOutput, MergedSchema, Sche
// Schemas should have distinct TInput and TOutput types to ensure correct inference.
const inputSchema = z.object({ input: z.number().transform((n) => `${n}`) })
const outputSchema = z.object({ output: z.string().transform((s) => Number(s)) })
const valibotSchema = v.object({
value: v.pipe(
v.string(),
v.transform((s) => Number(s)),
),
})
const arktypeSchema = arktypeType({ value: 'string' })
const untypedSchema = {
'~standard': {
version: 1 as const,
vendor: 'custom',
validate: (value: unknown) => ({ value: value as string }),
},
}

type UnionSchema = Schema<{ a: number }, { a: string }> | Schema<{ b: number }, { b: string }>

describe('Schema', () => {
it('supports any standard schema', () => {
Expand All @@ -28,11 +44,23 @@ describe('Schema', () => {
it('InferSchemaInput', () => {
expectTypeOf<InferSchemaInput<typeof inputSchema>>().toEqualTypeOf<{ input: number }>()
expectTypeOf<InferSchemaInput<typeof outputSchema>>().toEqualTypeOf<{ output: string }>()
expectTypeOf<InferSchemaInput<typeof valibotSchema>>().toEqualTypeOf<{ value: string }>()
expectTypeOf<InferSchemaInput<typeof arktypeSchema>>().toEqualTypeOf<{ value: string }>()
expectTypeOf<InferSchemaInput<UnionSchema>>().toEqualTypeOf<{ a: number } | { b: number }>()
expectTypeOf<InferSchemaInput<AnySchema>>().toBeAny()
expectTypeOf<InferSchemaInput<any>>().toEqualTypeOf<unknown>()
expectTypeOf<InferSchemaInput<typeof untypedSchema>>().toEqualTypeOf<unknown>()
})

it('InferSchemaOutput', () => {
expectTypeOf<InferSchemaOutput<typeof inputSchema>>().toEqualTypeOf<{ input: string }>()
expectTypeOf<InferSchemaOutput<typeof outputSchema>>().toEqualTypeOf<{ output: number }>()
expectTypeOf<InferSchemaOutput<typeof valibotSchema>>().toEqualTypeOf<{ value: number }>()
expectTypeOf<InferSchemaOutput<typeof arktypeSchema>>().toEqualTypeOf<{ value: string }>()
expectTypeOf<InferSchemaOutput<UnionSchema>>().toEqualTypeOf<{ a: string } | { b: string }>()
expectTypeOf<InferSchemaOutput<AnySchema>>().toBeAny()
expectTypeOf<InferSchemaOutput<any>>().toEqualTypeOf<unknown>()
expectTypeOf<InferSchemaOutput<typeof untypedSchema>>().toEqualTypeOf<unknown>()
})

describe('MergedSchema', () => {
Expand Down
10 changes: 6 additions & 4 deletions packages/contract/src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,18 @@ export type SchemaIssue = StandardSchemaV1.Issue
*
* @see {@link https://orpc.dev/docs/metadata | Metadata}
*/
export type InferSchemaInput<T extends AnySchema> =
T extends StandardSchemaV1<infer UInput, any> ? UInput : never
export type InferSchemaInput<T extends AnySchema> = 0 extends 1 & T
Comment thread
dinwwwh marked this conversation as resolved.
Resolved
? unknown
: NonNullable<T['~standard']['types']>['input']

/**
* Infers the output type of a schema.
*
* @see {@link https://orpc.dev/docs/metadata | Metadata}
*/
export type InferSchemaOutput<T extends AnySchema> =
T extends StandardSchemaV1<any, infer UOutput> ? UOutput : never
export type InferSchemaOutput<T extends AnySchema> = 0 extends 1 & T
? unknown
: NonNullable<T['~standard']['types']>['output']

export type MergedSchema<T extends AnySchema, U extends AnySchema> =
T extends Schema<infer TInput, infer TOutput>
Expand Down
9 changes: 4 additions & 5 deletions packages/server/src/procedure-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,16 +154,15 @@ export function createProcedureClient<
: output,
{ mapError: reconcileError },
),
) as typeof output
) as any
} else if (getTracer() && (output as unknown) instanceof ReadableStream) {
/**
* @warning
* Remember use `override` for ReadableStream to remain other special properties
*/
return override(
output,
traceReadableStream('consume_octet_stream_output', output),
) as typeof output
const stream = output as unknown as ReadableStream<unknown>

return override(stream, traceReadableStream('consume_octet_stream_output', stream)) as any
}

return output
Expand Down
Loading