UNPKG

graphql-gene

Version:

Generates automatically an executable schema out of your ORM models

141 lines (140 loc) 12.4 kB
import { GraphQLFieldResolver } from 'graphql'; import { GeneContext } from 'graphql-gene/context'; import { FindOptionsHandler, FindOptionsHandlerByType, FindOptionsStateByModel, GraphQLFieldName, GraphqlReturnTypes, GraphqlToTypescript, GraphqlTypeName, GraphQLVarType, InferFields, Narrow, OperatorInputs, Prop, PrototypeOrNot, SomeRequired, TypeOrFunction, ValidGraphqlType } from './types'; import { GENE_RESOLVER_TEMPLATES, QUERY_ORDER_ENUM } from './constants'; type ArgsDefinition<V = string> = Record<string, V> | `${GENE_RESOLVER_TEMPLATES}` | undefined; export type StrictArgsDefinition = ArgsDefinition<GraphqlReturnTypes<ValidGraphqlType>>; export type GeneConfigTypes<TSource = Record<string, unknown> | undefined, TContext = GeneContext, TArgDefs extends ArgsDefinition = undefined, TReturnType extends string | unknown = unknown> = readonly string[] | (GeneObjectTypeConfig<TSource, TContext, TArgDefs, TReturnType> & { geneConfig?: GeneConfig; }); export type GeneObjectTypeConfig<TSource = Record<string, unknown> | undefined, TContext = GeneContext, TArgDefs extends ArgsDefinition = undefined, TReturnType extends string | unknown = unknown> = Record<GraphQLFieldName, GraphqlReturnTypes<ValidGraphqlType | ''> | GeneTypeConfig<TSource, TContext, TArgDefs, TReturnType>>; type FallbackIfInvalid<T, TFallback> = T extends never ? TFallback : T; type AccurateTypeSource<TTypeName, TFallbackSource = Record<string, unknown> | undefined> = TTypeName extends 'Query' | 'Mutation' ? undefined : TTypeName extends string ? FallbackIfInvalid<NonNullable<GraphqlToTypescript<TTypeName>>, TFallbackSource> : TFallbackSource; export type ExtendedTypes<TSource = Record<string, unknown> | undefined, TContext = GeneContext, TArgDefs extends ArgsDefinition = undefined, TReturnType extends string | unknown = unknown> = { [typeName in GraphqlTypeName]?: Record<GraphQLFieldName, FieldConfig<AccurateTypeSource<typeName, TSource>, TContext, undefined extends TArgDefs ? ArgsDefinition : TArgDefs, TReturnType extends unknown ? GraphqlReturnTypes<ValidGraphqlType> : TReturnType>>; }; export type NarrowExtendedTypes<TTypes extends Record<string, Record<string, object>>> = { [TypeName in keyof TTypes]?: { [FieldName in keyof TTypes[TypeName]]: ExtendedTypeField<TTypes[TypeName][FieldName], TypeName>; }; }; type ValidReturnTypeOption<T> = Narrow<T> extends GraphqlReturnTypes<ValidGraphqlType> ? Narrow<T> : never; export type ExtendedTypeField<T, TypeName> = { [K in keyof T]: K extends 'resolver' ? GeneResolverOption<AccurateTypeSource<TypeName>, GeneContext, Prop<T, 'args'> extends ArgsDefinition ? Prop<T, 'args'> : never, ValidReturnTypeOption<Prop<T, 'returnType'>>> : K extends 'returnType' ? ValidReturnTypeOption<T[K]> : K extends 'args' ? T[K] extends StrictArgsDefinition ? Narrow<T[K]> : never : K extends 'findOptions' ? FindOptionsHandlerByType<TypeName, T[K]> : Narrow<T[K]>; }; export type StrictExtendedTypes<TSource = Record<string, unknown> | undefined, TContext = GeneContext, TArgDefs extends ArgsDefinition = undefined> = ExtendedTypes<TSource, TContext, TArgDefs, GraphqlReturnTypes<ValidGraphqlType>>; export interface GeneConfig<M = unknown, TSource = M | Record<string, unknown> | undefined, TContext = GeneContext, TArgDefs extends ArgsDefinition = undefined, TReturnType extends string | unknown = unknown, TVarType extends GraphQLVarType = GraphQLVarType> { /** Array of fields to include in the GraphQL type (default: include all). */ include?: (InferFields<M> | RegExp)[]; /** Array of fields to exclude in the GraphQL type (default: ['createdAt', updatedAt']). */ exclude?: (InferFields<M> | RegExp)[]; /** To include the timestamp attributes or not (default: false). */ includeTimestamps?: boolean | ('createdAt' | 'updatedAt')[]; /** The GraphQL variable type to use (default: "type"). */ varType?: TVarType; /** Directives to apply at the type level (also possible at the field level). */ directives?: TypeOrFunction<GeneDirectiveConfig<Record<string, string | number | boolean | string[] | number[] | boolean[] | null> | undefined, TSource extends M ? PrototypeOrNot<M> : TSource>[]>; /** * The values of "aliases" would be nested GeneConfig properties that overwrites the ones se * at a higher level. This is useful for instances with a specific scope include more fields * that the parent model (i.e. `AuthenticatedUser` being an alias of `User`). Note that the * alias needs to be exported from _graphqlTypes.ts_ as well. * * @example * include: ['id', 'username'], * * aliases: { * AuthenticatedUser: { * include: ['id', 'email', 'username', 'role', 'address', 'orders'], * }, * }, * * @example * export { User as AuthenticatedUser } from '../models/User/User.model' */ aliases?: { [modelKey in GraphqlTypeName]?: GeneConfig<M, TSource, TContext, TArgDefs, TReturnType, TVarType>; }; /** * Extend the Query or Mutation types only. * @deprecated You should import and call `extendTypes` instead. */ types?: ExtendedTypes<TSource, TContext, TArgDefs, TReturnType>; findOptions?: FindOptionsHandler<FindOptionsStateByModel<M, any>>; } export type GeneTypeConfig<TSource = Record<string, unknown> | undefined, TContext = GeneContext, TArgDefs extends ArgsDefinition = undefined, TReturnType extends string | unknown = unknown> = { directives?: TypeOrFunction<GeneDirectiveConfig<Record<string, string | number | boolean | string[] | number[] | boolean[] | null> | undefined, TSource>[]>; args?: TArgDefs extends undefined ? undefined : TArgDefs; resolver?: GeneResolverOption<TSource, TContext, TArgDefs, TReturnType>; returnType: TReturnType extends unknown ? GraphqlReturnTypes<ValidGraphqlType> : TReturnType; findOptions?: FindOptionsHandler<object>; }; export type FieldConfig<TSource = Record<string, unknown> | undefined, TContext = GeneContext, TArgDefs extends ArgsDefinition = undefined, TReturnType extends string | unknown = unknown> = GraphqlReturnTypes<ValidGraphqlType> | SomeRequired<GeneTypeConfig<TSource, TContext, TArgDefs, TReturnType>, 'resolver'>; type GeneResolverOption<TSource = Record<string, unknown> | undefined, TContext = GeneContext, TArgDefs extends ArgsDefinition = undefined, TReturnType extends string | unknown = unknown> = GeneResolver<TSource, TContext, FieldConfigArgsOption<TArgDefs, TReturnType>, TReturnType extends string ? GraphqlToTypescript<TReturnType> : unknown> | `${GENE_RESOLVER_TEMPLATES}`; export type GeneResolver<TSource = Record<string, unknown> | undefined, TContext = GeneContext, TArgs = Record<string, unknown> | undefined, TResult = unknown> = (options: { source: Parameters<GraphQLFieldResolver<TSource, TContext, TArgs>>[0]; args: Parameters<GraphQLFieldResolver<TSource, TContext, TArgs>>[1]; context: Parameters<GraphQLFieldResolver<TSource, TContext, TArgs>>[2]; info: Parameters<GraphQLFieldResolver<TSource, TContext, TArgs>>[3]; }) => TResult | Promise<TResult>; export type FieldConfigArgsOption<TArgDefs extends ArgsDefinition, TReturnType extends string | unknown> = TArgDefs extends `${GENE_RESOLVER_TEMPLATES.default}` ? GeneDefaultResolverArgs<TReturnType extends string ? NonNullable<GraphqlToTypescript<TReturnType>> : unknown> : TArgDefs extends undefined ? Record<string, unknown> | undefined : { [k in keyof Narrow<TArgDefs>]: Narrow<TArgDefs>[k] extends string ? GraphqlToTypescript<Narrow<TArgDefs>[k]> : unknown; }; export type ArgsTypeToGraphQL<ArgsType> = { [k in keyof Required<ArgsType>]: Required<ArgsType>[k] extends number ? 'Int' : k extends 'where' | 'order' ? string : Required<ArgsType>[k] extends string ? 'String' : Required<ArgsType>[k] extends boolean ? 'Boolean' : never; }; export type GeneDefaultResolverArgs<M> = { page: number; perPage: number; locale?: string; id?: string; where: { [k in keyof M]: Exclude<M[k], null | undefined> extends string | number | bigint | boolean ? OperatorInputs<Exclude<M[k], null | undefined>> : never; }; order?: keyof M extends string ? `${keyof M}_${QUERY_ORDER_ENUM}`[] : never; }; export type GeneDirective<TDirectiveArgs, TSource = Record<string, unknown> | undefined, TContext = GeneContext, TArgs = Record<string, unknown> | undefined> = TDirectiveArgs extends undefined ? (args?: TDirectiveArgs) => GeneDirectiveConfig<TDirectiveArgs, TSource, TContext, TArgs> : (args: TDirectiveArgs) => GeneDirectiveConfig<TDirectiveArgs, TSource, TContext, TArgs>; export type GeneDirectiveConfig<TDirectiveArgs = Record<string, string | number | boolean | string[] | number[] | boolean[] | null> | undefined, TSource = Record<string, unknown> | undefined, TContext = GeneContext, TArgs = Record<string, unknown> | undefined> = TDirectiveArgs extends undefined ? { name: string; args?: TDirectiveArgs; handler: GeneDirectiveHandler<TSource, TContext, TArgs>; } : { name: string; args: TDirectiveArgs; handler: GeneDirectiveHandler<TSource, TContext, TArgs>; }; export type GeneDirectiveHandler<TSource = Record<string, unknown> | undefined, TContext = GeneContext, TArgs = Record<string, unknown> | undefined, TResult = unknown> = (options: { source: Parameters<GraphQLFieldResolver<TSource, TContext, TArgs, TResult>>[0]; args: Parameters<GraphQLFieldResolver<TSource, TContext, TArgs, TResult>>[1]; context: Parameters<GraphQLFieldResolver<TSource, TContext, TArgs, TResult>>[2]; info: Parameters<GraphQLFieldResolver<TSource, TContext, TArgs, TResult>>[3]; field: string; filter: <TValue>(callback: (value: TValue) => unknown) => void; resolve: () => Promise<TResult> | TResult; }) => Promise<void> | void; export declare class GeneModel { static geneConfig?: GeneConfig; } /** * Provide typing and default values to GeneConfig. You need to pass the model class as the first * argument to ensure accurate types for "include" and "exclude" options (they only accept regular * expressions or one of the model field name as string). * * @default geneConfig.exclude - ['createdAt', 'updatedAt'] */ export declare function defineGraphqlGeneConfig<M = unknown, TSource = M | Record<string, unknown> | undefined, TContext = GeneContext, TArgDefs extends ArgsDefinition = undefined, TReturnType extends string | unknown = unknown, TVarType extends GraphQLVarType = 'type'>(_model: M, options: GeneConfig<M, TSource, TContext, TArgDefs, TReturnType, TVarType>): GeneConfig<M, TSource, TContext, TArgDefs, TReturnType, TVarType>; export declare function defineDirective<TDirectiveArgs = undefined, TSource = Record<string, unknown> | undefined, TContext = GeneContext, TArgs = Record<string, unknown> | undefined>(directive: GeneDirective<TDirectiveArgs, TSource, TContext, TArgs>): GeneDirective<TDirectiveArgs, Record<string, unknown> | undefined, TContext, TArgs>; /** * @deprecated Field config passed to `extendTypes` don't need to be wrapped with `defineField` * anymore in order to be accurate (they are now even better typed without it). */ export declare function defineField<TSource extends Record<string, unknown> | undefined, TArgDefs extends StrictArgsDefinition, TReturnType extends GraphqlReturnTypes<ValidGraphqlType>, TContext = GeneContext>(config: Narrow<FieldConfig<TSource, TContext, TArgDefs, TReturnType>, 'args' | 'returnType'>): FieldConfig<any, TContext, any, TReturnType>; export declare function defineType<T extends GeneObjectTypeConfig<TSource, TContext, TArgDefs>, TSource, TContext, TArgDefs extends ArgsDefinition, TVarType extends GraphQLVarType>(config: T, geneConfig?: GeneConfig<T, TSource, TContext, TArgDefs, string, TVarType>): T; export declare function defineInput<T extends GeneObjectTypeConfig<TSource, TContext, TArgDefs>, TSource, TContext, TArgDefs extends ArgsDefinition>(config: T): T & { geneConfig: GeneConfig<{}, Record<string, unknown> | {} | undefined, GeneContext, undefined, unknown, "input">; }; export declare function defineEnum<TValue extends string>(values: TValue[]): TValue[]; export declare function defineUnion<TUnion extends string>(unions: TUnion[]): Required<Partial<Record<TUnion, "">>> & { geneConfig: GeneConfig<{}, Record<string, unknown> | {} | undefined, GeneContext, undefined, unknown, "union">; }; export {};