UNPKG

@backland/schema

Version:

TypeScript schema declaration and validation library with static type inference

65 lines (64 loc) 3.35 kB
import { Compute, Merge, OnlyKnown } from '@backland/utils'; import { ParseStringDefinition } from '../../parseStringDefinition'; import { CommonDefSafe, FieldTypeName } from '../_fieldDefinitions'; import { FinalFieldDefinition } from '../_parseFields'; import { _FieldKV, _GetKey, GraphTypeKID, ObjectTypeKID } from './InferField'; import { GraphTypeLikeFieldDefinition } from './InferGraphType'; import { ObjectTypeLikeFieldDefinition } from './InferObjectType'; export declare const $sealedKey = "___sealed"; export type $sealedKey = typeof $sealedKey; export declare const $sealed: unique symbol; export type $sealed = typeof $sealed; export declare const $inferableKey = "___inferable"; export type $inferableKey = typeof $inferableKey; export type DescribeField<Input> = [$sealedKey] extends [keyof Input] ? Input : SealedField<_DescribeField<Input>> extends infer R ? { [K in keyof R]: R[K]; } & {} : never; export type _DescribeField<Input> = OnlyKnown<Input> extends infer Known ? Known extends string ? ParseStringDefinition<Known> : Known extends object ? _DescribeObject<Known> : never : never; export type SealedField<D extends object> = 'type' extends keyof D ? Seal<Merge<CommonDefSafe, D>> : D; export type $sealedDef = Compute<{ literal: $sealed; optional: false; list: false; } & CommonDefSafe>; export type Seal<T extends object> = Merge<T, { $sealed: $sealedDef; }> extends infer R ? { [K in keyof R]: R[K]; } & {} : never; export type DescribeWithoutSeal<T> = Omit<DescribeField<T>, $inferableKey | $sealedKey> extends infer R ? { [K in keyof R]: R[K]; } & {} : never; export type DescribeAndOverrideField<T, Override> = DescribeWithoutSeal<T> extends infer R ? R extends FinalFieldDefinition ? SealedField<Merge<{ [K in keyof R as K extends keyof Override ? never : K]: R[K]; }, Override>> : never : never; export type DescribeObjectDefinition<Input> = $sealedKey extends keyof Input ? Input : [Input] extends [object] ? Seal<{ -readonly [K in keyof Input]: DescribeField<Input[K]>; }> : Seal<{}>; export type _DescribeObject<Input extends object> = _FieldKV<Input> extends [infer K, infer V] ? K extends keyof Input ? K extends GraphTypeKID ? 'definition' extends keyof Input ? DescribeField<Input['definition']> : never : K extends ObjectTypeKID ? 'definition' extends keyof Input ? { type: 'object'; def: DescribeObjectDefinition<Input['definition']>; list: _GetKey<Input, 'list'>; optional: _GetKey<Input, 'optional'>; } : never : K extends FieldTypeName ? { type: K; def: V; list: _GetKey<Input, 'list'>; optional: _GetKey<Input, 'optional'>; } : K extends 'type' ? V extends FieldTypeName ? { type: V; def: _GetKey<Input, 'def'>; list: _GetKey<Input, 'list'>; optional: _GetKey<Input, 'optional'>; } : Input[K] extends GraphTypeLikeFieldDefinition ? Merge<DescribeField<Input[K]['definition']>, _OmitUndefined<{ list: _GetKey<Input, 'list'>; optional: _GetKey<Input, 'optional'>; }>> : Input[K] extends ObjectTypeLikeFieldDefinition ? { type: 'object'; def: DescribeObjectDefinition<Input[K]['definition']>; list: _GetKey<Input, 'list'>; optional: _GetKey<Input, 'optional'>; } : never : never : never : never; export type _OmitUndefined<T> = { [K in keyof T as T[K] extends undefined ? never : K]: T[K]; } & {};