Skip to content
Draft
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
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export {
IfDefined,
memoize,
memoizeWithKey,
Selector,
UnknownIfNever,
unsupportedAdapter,
} from './utils';
Expand Down
12 changes: 12 additions & 0 deletions packages/core/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,15 @@ export function unsupportedAdapter<TResolver extends Resolver>(
throw new Error(`This feature is unsupported for ${adapterName}`);
};
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export interface Selector<T extends Record<string, any>> {
value: T[keyof T];
kind: keyof T;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
fn: <TMap extends {[K in keyof T]: (value: T[K]) => any}>(
map: TMap,
) => <U extends T[keyof T]>(
value: U,
) => ReturnType<TMap[(this & {value: U})['kind']]>;
}
12 changes: 9 additions & 3 deletions packages/main/src/resolver.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type {AdapterResolvers} from './adapters';
import type {Select} from './selector';
import type {SchemaKind} from './selector';
import type {
InputFrom,
OutputFrom,
Expand All @@ -11,6 +11,12 @@ export interface AdapterResolver extends Resolver {
base: {
[TModule in keyof AdapterResolvers]: SchemaFrom<AdapterResolvers[TModule]>;
}[keyof AdapterResolvers];
input: InputFrom<AdapterResolvers[Select<this['schema']>], this['schema']>;
output: OutputFrom<AdapterResolvers[Select<this['schema']>], this['schema']>;
input: InputFrom<
AdapterResolvers[SchemaKind<this['schema']>],
this['schema']
>;
output: OutputFrom<
AdapterResolvers[SchemaKind<this['schema']>],
this['schema']
>;
}
79 changes: 31 additions & 48 deletions packages/main/src/selector.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type {AdapterResolvers} from './adapters';
import type {AdapterResolver} from './resolver';
import type {Kind} from '@sinclair/typebox';
import type {IfDefined, SchemaFrom} from '@typeschema/core';
import type {IfDefined, SchemaFrom, Selector} from '@typeschema/core';
import type {CoreValidator} from 'suretype';

type IsTypeboxSchema<TSchema> = [IfDefined<typeof Kind>] extends [never]
Expand Down Expand Up @@ -48,54 +48,37 @@ function notJSON<TSchema>(
return schema as any;
}

export type Select<TSchema> =
// eslint-disable-next-line @typescript-eslint/ban-types
TSchema extends Function
? TSchema extends {assert: unknown}
? 'arktype'
: IsClassValidatorSchema<TSchema> extends true
? 'classValidator'
: 'function'
: IsTypeboxSchema<TSchema> extends true
? 'typebox'
: IsSuretypeSchema<TSchema> extends true
? 'suretype'
: TSchema extends {__isYupSchema__: unknown}
? 'yup'
: TSchema extends {_def: unknown}
? 'zod'
: TSchema extends {async: unknown}
? 'valibot'
: TSchema extends {refiner: unknown}
? 'superstruct'
: TSchema extends {_flags: unknown}
? 'joi'
: TSchema extends {encode: unknown}
? 'ioTs'
: TSchema extends {reflect: unknown}
? 'runtypes'
: TSchema extends {ast: unknown}
? 'effect'
: TSchema extends {kind: unknown}
? 'deepkit'
: TSchema extends {addValidator: unknown}
? 'ow'
: TSchema extends {toTerminals: unknown}
? 'valita'
: 'json';
interface SchemaSelector
extends Selector<{
[TModule in keyof AdapterResolvers]: SchemaFrom<AdapterResolvers[TModule]>;
}> {
// prettier-ignore
kind:
// eslint-disable-next-line @typescript-eslint/ban-types
this['value'] extends Function
? this['value'] extends {assert: unknown} ? 'arktype'
: IsClassValidatorSchema<this['value']> extends true ? 'classValidator'
: 'function'
: this['value'] extends object
? IsTypeboxSchema<this['value']> extends true ? 'typebox'
: IsSuretypeSchema<this['value']> extends true ? 'suretype'
: this['value'] extends {__isYupSchema__: unknown} ? 'yup'
: this['value'] extends {_def: unknown} ? 'zod'
: this['value'] extends {async: unknown} ? 'valibot'
: this['value'] extends {refiner: unknown} ? 'superstruct'
: this['value'] extends {_flags: unknown} ? 'joi'
: this['value'] extends {encode: unknown} ? 'ioTs'
: this['value'] extends {reflect: unknown} ? 'runtypes'
: this['value'] extends {ast: unknown} ? 'effect'
: this['value'] extends {kind: unknown} ? 'deepkit'
: this['value'] extends {addValidator: unknown} ? 'ow'
: this['value'] extends {toTerminals: unknown} ? 'valita'
: 'json'
: never;
}
export type SchemaKind<T> = (SchemaSelector & {value: T})['kind'];

export const select: <
TMap extends {
[TModule in keyof AdapterResolvers]: (
schema: SchemaFrom<AdapterResolvers[TModule]>,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
) => any;
},
>(
is: TMap,
) => <TSchema extends SchemaFrom<AdapterResolver>>(
schema: TSchema,
) => ReturnType<TMap[Select<TSchema>]> =
export const select: SchemaSelector['fn'] =
/* @__NO_SIDE_EFFECTS__ */
is => schema => {
switch (typeof schema) {
Expand Down