import { getNullableType, GraphQLFieldConfigArgumentMap, GraphQLFieldConfigMap, GraphQLSchema, GraphQLObjectType, GraphQLSchemaConfig, GraphQLObjectTypeConfig, } from "graphql"; import {ModelCtor, ModelType} from "sequelize"; import {SequelizeAdapter, SequelizeAdapterConfig} from "./SequelizeAdapter"; import _ from "lodash"; import CONS from "./constant"; /** * 覆盖一些常量 * @param map */ export function mergeConstant(map: Partial) { _.merge(CONS, map); } function getName(model: ModelType) { return model.name; } function map2NullableType(fields: GraphQLFieldConfigArgumentMap): GraphQLFieldConfigArgumentMap { const args: GraphQLFieldConfigArgumentMap = {}; Object.keys(fields).forEach(t => { args[t] = {...fields[t]}; args[t].type = getNullableType(args[t].type); }); return args; } export type GenerateAdapterConfig = SequelizeAdapterConfig & Partial & { customQuery?: ((adapters: AdapterMaps, options: GenerateAdapterConfig) => GraphQLFieldConfigMap) | GraphQLFieldConfigMap; customMutation?: ((adapters: AdapterMaps, options: GenerateAdapterConfig) => GraphQLFieldConfigMap) | GraphQLFieldConfigMap; customSubscription?: ((adapters: AdapterMaps, options: GenerateAdapterConfig) => GraphQLFieldConfigMap) | GraphQLFieldConfigMap; configMap?: { [key in keyof T]?: SequelizeAdapterConfig }; /** * 是否添加Mutation */ includeMutation?: boolean; /** * 是否添加Subscription */ includeSubscription?: boolean; /** * 移除Query字段 */ omitQueryFields?: string[]; /** * 移除Mutation字段 */ omitMutationFields?: string[]; /** * 移除Subscription字段 */ omitSubscriptionFields?: string[]; } export type AdapterMaps = { [key in keyof T]?: SequelizeAdapter } function thunkGet(value: ((adapters: AdapterMaps, options: GenerateAdapterConfig) => GraphQLFieldConfigMap) | GraphQLFieldConfigMap, adapters: AdapterMaps, options: GenerateAdapterConfig): GraphQLFieldConfigMap { if (_.isFunction(value)) return value(adapters, options); return value; } function generateType(include: boolean, omitFields: string[], value: ((adapters: AdapterMaps, options: GenerateAdapterConfig) => GraphQLFieldConfigMap) | GraphQLFieldConfigMap, adapters: AdapterMaps, fields: GraphQLFieldConfigMap, config: GraphQLObjectTypeConfig, options: GenerateAdapterConfig): GraphQLObjectType | null { if (!include && (!_.isFunction(value) && _.isEmpty(value)) || (_.isFunction(value) && _.isEmpty(thunkGet(value, adapters, options)))) return null; return new GraphQLObjectType({ ...config, fields: () => _.omit({ ...(include ? fields : {}), ...thunkGet(value, adapters, options) }, omitFields) }); } const defaultOptions: GenerateAdapterConfig = { customQuery: {}, customMutation: {}, customSubscription: {}, omitQueryFields: [], omitMutationFields: [], omitSubscriptionFields: [], includeMutation: true, includeSubscription: true, primaryKeyToIdType: true, configMap: {}, }; /** * 生成schema * @param models * @param options * @returns {GraphQLSchema} */ function generateSchema }>(models: T, options: GenerateAdapterConfig = {}): GraphQLSchema { options = { ...defaultOptions, ...options }; const { customQuery, customMutation, customSubscription, omitQueryFields, omitMutationFields, omitSubscriptionFields, includeMutation, includeSubscription, configMap, ...commonModelConfig } = options; // @ts-ignore const {query, mutation, subscription, adapters} = Object.keys(models).reduce<{ query: GraphQLFieldConfigMap; mutation: GraphQLFieldConfigMap; subscription: GraphQLFieldConfigMap; adapters: AdapterMaps; }>((obj, key) => { const model = models[key]; // @ts-ignore const modelSchema = new SequelizeAdapter(model, {...commonModelConfig, ...(configMap[key] || {})}); Object.assign(obj.query, modelSchema.queryFields); Object.assign(obj.mutation, modelSchema.mutationFields); Object.assign(obj.subscription, modelSchema.subscriptionFields); // @ts-ignore obj.adapters[key] = modelSchema; return obj; }, {query: {}, mutation: {}, subscription: {}, adapters: {}}); return new GraphQLSchema({ query: new GraphQLObjectType({ name: "Query", description: "Base Query", fields: () => { const fields = { ...query, ...thunkGet(customQuery, adapters, options) }; return _.omit(fields, omitQueryFields); } }), mutation: generateType(includeMutation, omitMutationFields, customMutation, adapters, mutation, { name: "Mutation", description: "Base Mutation", fields: {} }, options), subscription: generateType(includeSubscription, omitSubscriptionFields, customSubscription, adapters, subscription, { name: "Subscription", description: "Base Subscription", fields: {} }, options), ...(_.pick(commonModelConfig, ["description", "query", "mutation", "subscription", "types", "directives", "extensions", "astNode", "extensionASTNodes", "assumeValid"])) }); } export { getName, map2NullableType, generateSchema, };