Skip to content

Commit

Permalink
map input
Browse files Browse the repository at this point in the history
  • Loading branch information
unnoq committed Jan 16, 2025
1 parent e5a8492 commit dc8f399
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 16 deletions.
29 changes: 22 additions & 7 deletions packages/contract/src/schema-utils.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,28 @@
import type { SchemaInput, SchemaOutput } from './types'
import { type } from './schema-utils'

it('type', () => {
const schema = type<string>()
describe('type', () => {
it('without map', () => {
const schema = type<string>()

expectTypeOf<SchemaInput<typeof schema>>().toEqualTypeOf<string>()
expectTypeOf<SchemaOutput<typeof schema>>().toEqualTypeOf<string>()
expectTypeOf<SchemaInput<typeof schema>>().toEqualTypeOf<string>()
expectTypeOf<SchemaOutput<typeof schema>>().toEqualTypeOf<string>()
})

const schema2 = type<string, number>()
expectTypeOf<SchemaInput<typeof schema2>>().toEqualTypeOf<string>()
expectTypeOf<SchemaOutput<typeof schema2>>().toEqualTypeOf<number>()
it('with map', () => {
const schema2 = type<string, number>((val) => {
expectTypeOf(val).toEqualTypeOf<string>()

return Number(val)
})

expectTypeOf<SchemaInput<typeof schema2>>().toEqualTypeOf<string>()
expectTypeOf<SchemaOutput<typeof schema2>>().toEqualTypeOf<number>()

// @ts-expect-error - map is required when TInput !== TOutput
type<string, number>()

// @ts-expect-error - output not match number
type<string, number>(() => '123')
})
})
8 changes: 4 additions & 4 deletions packages/contract/src/schema-utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { type } from './schema-utils'

describe('type', async () => {
it('without check', async () => {
it('without map', async () => {
const schema = type()
const val = {}
expect((await schema['~standard'].validate(val) as any).value).toBe(val)
})

it('with check', async () => {
it('with map', async () => {
const val = {}
const check = vi.fn().mockReturnValueOnce({ value: val })
const check = vi.fn().mockReturnValueOnce('__mapped__')
const schema = type(check)
expect((await schema['~standard'].validate(val) as any).value).toBe(val)
expect((await schema['~standard'].validate(val) as any).value).toBe('__mapped__')
expect(check).toHaveBeenCalledWith(val)
})
})
17 changes: 12 additions & 5 deletions packages/contract/src/schema-utils.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import type { IsEqual, Promisable } from '@orpc/shared'
import type { StandardSchemaV1 } from '@standard-schema/spec'

export function type<TInput, TOutput = TInput>(
check?: (val: unknown) => StandardSchemaV1.Result<TOutput> | Promise<StandardSchemaV1.Result<TOutput>>,
): StandardSchemaV1<TInput, TOutput> {
export type TypeRest<TInput, TOutput> =
| [map: (input: TInput) => Promisable<TOutput>]
| (IsEqual<TInput, TOutput> extends true ? [] : never)

export function type<TInput, TOutput = TInput>(...[map]: TypeRest<TInput, TOutput>): StandardSchemaV1<TInput, TOutput> {
return {
'~standard': {
vendor: 'custom',
version: 1,
validate(value) {
return check ? check(value) : { value: value as any }
async validate(value) {
if (map) {
return { value: await map(value as TInput) as TOutput }
}

return { value: value as TOutput }
},
},
}
Expand Down

0 comments on commit dc8f399

Please sign in to comment.