Skip to content
Merged
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
4 changes: 2 additions & 2 deletions apps/content/docs/openapi/input-output-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,9 @@ export type DetailedOutput = {

Make sure your handler’s return value matches this structure when using detailed mode.

## Default Configuration
## Initial Configuration

Customize the default oRPC input/output structure settings using `.$route`:
Customize the initial oRPC input/output structure settings using `.$route`:

```ts
const base = os.$route({ inputStructure: 'detailed' })
Expand Down
4 changes: 2 additions & 2 deletions apps/content/docs/openapi/routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ const router = {
}
```

## Default Configuration
## Initial Configuration

Customize the default oRPC routing settings using `.$route`:
Customize the initial oRPC routing settings using `.$route`:

```ts
const base = os.$route({ method: 'GET' })
Expand Down
11 changes: 11 additions & 0 deletions apps/content/docs/procedure.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,17 @@ const example = os

To learn more, see the [Middleware](/docs/middleware) documentation.

## Initial Configuration

Customize the initial input schema using `.$input`:

```ts
const base = os.$input(z.void())
const base = os.$input<Schema<void, unknown>>()
```

Unlike `.input`, the `.$input` method lets you redefine the input schema after its initial configuration. This is useful when you need to enforce a `void` input when no `.input` is specified.

## Reusability

Each modification to a builder creates a completely new instance, avoiding reference issues. This makes it easy to reuse and extend procedures efficiently.
Expand Down
12 changes: 6 additions & 6 deletions packages/server/src/builder-variants.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe('BuilderWithMiddlewares', () => {
it('backward compatibility', () => {
const expected = {} as OmitChainMethodDeep<
typeof generalBuilder,
'$config' | '$context' | '$meta' | '$route' | 'middleware'
'$config' | '$context' | '$meta' | '$route' | '$input' | 'middleware'
>

// expectTypeOf(builder).toMatchTypeOf(expected)
Expand Down Expand Up @@ -279,7 +279,7 @@ describe('ProcedureBuilder', () => {
it('backward compatibility', () => {
const expected = {} as OmitChainMethodDeep<
typeof generalBuilder,
'$config' | '$context' | '$meta' | '$route' | 'middleware' | 'prefix' | 'tag' | 'router' | 'lazy'
'$config' | '$context' | '$meta' | '$route' | '$input' | 'middleware' | 'prefix' | 'tag' | 'router' | 'lazy'
>

expectTypeOf(builder).toMatchTypeOf(expected)
Expand Down Expand Up @@ -458,7 +458,7 @@ describe('ProcedureBuilderWithInput', () => {
it('backward compatibility', () => {
const expected = {} as OmitChainMethodDeep<
typeof generalBuilder,
'$config' | '$context' | '$meta' | '$route' | 'middleware' | 'prefix' | 'tag' | 'router' | 'lazy' | 'input'
'$config' | '$context' | '$meta' | '$route' | '$input' | 'middleware' | 'prefix' | 'tag' | 'router' | 'lazy' | 'input'
>

expectTypeOf(builder).toMatchTypeOf(expected)
Expand Down Expand Up @@ -673,7 +673,7 @@ describe('ProcedureBuilderWithOutput', () => {
it('backward compatibility', () => {
const expected = {} as OmitChainMethodDeep<
typeof generalBuilder,
'$config' | '$context' | '$meta' | '$route' | 'middleware' | 'prefix' | 'tag' | 'router' | 'lazy' | 'output'
'$config' | '$context' | '$meta' | '$route' | '$input' | 'middleware' | 'prefix' | 'tag' | 'router' | 'lazy' | 'output'
>

// expectTypeOf(builder).toMatchTypeOf(expected)
Expand Down Expand Up @@ -839,7 +839,7 @@ describe('ProcedureBuilderWithInputOutput', () => {
it('backward compatibility', () => {
const expected = {} as OmitChainMethodDeep<
typeof generalBuilder,
'$config' | '$context' | '$meta' | '$route' | 'middleware' | 'prefix' | 'tag' | 'router' | 'lazy' | 'input' | 'output'
'$config' | '$context' | '$meta' | '$route' | '$input' | 'middleware' | 'prefix' | 'tag' | 'router' | 'lazy' | 'input' | 'output'
>

// expectTypeOf(builder).toMatchTypeOf(expected)
Expand Down Expand Up @@ -1039,7 +1039,7 @@ describe('RouterBuilder', () => {
it('backward compatibility', () => {
const expected = {} as OmitChainMethodDeep<
typeof generalBuilder,
'$config' | '$context' | '$meta' | '$route' | 'middleware' | 'meta' | 'route' | 'input' | 'output' | 'handler'
'$config' | '$context' | '$meta' | '$route' | '$input' | 'middleware' | 'meta' | 'route' | 'input' | 'output' | 'handler'
>

// expectTypeOf(builder).toMatchTypeOf(expected)
Expand Down
37 changes: 37 additions & 0 deletions packages/server/src/builder.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type { DecoratedMiddleware } from './middleware-decorated'
import type { Procedure } from './procedure'
import type { DecoratedProcedure } from './procedure-decorated'
import type { EnhancedRouter } from './router-utils'
import { z } from 'zod'
import { generalSchema } from '../../contract/tests/shared'
import { router } from '../tests/shared'

Expand Down Expand Up @@ -115,6 +116,42 @@ describe('Builder', () => {
builder.$route({ method: 'INVALID' })
})

describe('.$input', () => {
it('with actual schema', () => {
const schema = z.void()

expectTypeOf(builder.$input(schema)).toEqualTypeOf<
Builder<
InitialContext,
CurrentContext,
typeof schema,
typeof outputSchema,
typeof baseErrorMap,
BaseMeta
>
>()

// @ts-expect-error --- invalid schema
builder.$input({})
})

it('with types only', () => {
expectTypeOf(builder.$input<Schema<void, unknown>>()).toEqualTypeOf<
Builder<
InitialContext,
CurrentContext,
Schema<void, unknown>,
typeof outputSchema,
typeof baseErrorMap,
BaseMeta
>
>()

// @ts-expect-error --- invalid schema
builder.$input<'invalid'>()
})
})

describe('.middleware', () => {
it('works', () => {
expectTypeOf(
Expand Down
27 changes: 27 additions & 0 deletions packages/server/src/builder.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import type { Schema } from '@orpc/contract'
import { isContractProcedure } from '@orpc/contract'
import { z } from 'zod'
import { baseErrorMap, baseMeta, baseRoute, generalSchema, inputSchema, outputSchema } from '../../contract/tests/shared'
import { router } from '../tests/shared'
import { Builder } from './builder'
Expand Down Expand Up @@ -94,6 +96,31 @@ describe('builder', () => {
})
})

describe('.$input', () => {
it('with actual schema', () => {
const schema = z.void()
const applied = builder.$input(schema)

expect(applied).instanceOf(Builder)
expect(applied).not.toBe(builder)
expect(applied['~orpc']).toEqual({
...def,
inputSchema: schema,
})
})

it('with type only', () => {
const applied = builder.$input<Schema<void, unknown>>()

expect(applied).instanceOf(Builder)
expect(applied).not.toBe(builder)
expect(applied['~orpc']).toEqual({
...def,
inputSchema: undefined,
})
})
})

it('.middleware', () => {
const mid = vi.fn()
const applied = builder.middleware(mid)
Expand Down
9 changes: 9 additions & 0 deletions packages/server/src/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,15 @@ export class Builder<
})
}

$input<U extends AnySchema>(
initialInputSchema?: U,
): Builder<TInitialContext, TCurrentContext, U, TOutputSchema, TErrorMap, TMeta> {
return new Builder({
...this['~orpc'],
inputSchema: initialInputSchema,
})
}

middleware<UOutContext extends Context, TInput, TOutput = any>( // = any here is important to make middleware can be used in any output by default
middleware: Middleware<TCurrentContext, UOutContext, TInput, TOutput, ORPCErrorConstructorMap<TErrorMap>, TMeta>,
): DecoratedMiddleware<TCurrentContext, UOutContext, TInput, TOutput, ORPCErrorConstructorMap<any>, TMeta> { // ORPCErrorConstructorMap<any> ensures middleware can used in any procedure
Expand Down
2 changes: 1 addition & 1 deletion packages/server/src/implementer-procedure.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ describe('ProcedureImplementer', () => {
it('backward compatibility', () => {
const expected = {} as OmitChainMethodDeep<
typeof generalBuilder,
'$config' | '$context' | '$meta' | '$route' | 'middleware' | 'prefix' | 'tag' | 'router' | 'lazy' | 'input' | 'output' | 'meta' | 'route' | 'errors'
'$config' | '$context' | '$meta' | '$route' | '$input' | 'middleware' | 'prefix' | 'tag' | 'router' | 'lazy' | 'input' | 'output' | 'meta' | 'route' | 'errors'
>

// expectTypeOf(builder).toMatchTypeOf(expected)
Expand Down