| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- import { DynamicModule } from '@nestjs/common';
- import { GqlModuleOptions, GraphQLModule, GraphQLTypesLoader } from '@nestjs/graphql';
- import { GraphQLUpload } from 'apollo-server-core';
- import { extendSchema, printSchema } from 'graphql';
- import { GraphQLDateTime } from 'graphql-iso-date';
- import GraphQLJSON from 'graphql-type-json';
- import { ConfigModule } from '../../config/config.module';
- import { ConfigService } from '../../config/config.service';
- import { I18nModule } from '../../i18n/i18n.module';
- import { I18nService } from '../../i18n/i18n.service';
- import { getPluginAPIExtensions } from '../../plugin/plugin-utils';
- import { ApiSharedModule } from '../api-internal-modules';
- import { IdCodecService } from '../common/id-codec.service';
- import { IdEncoderExtension } from '../middleware/id-encoder-extension';
- import { TranslateErrorExtension } from '../middleware/translate-errors-extension';
- import { generateListOptions } from './generate-list-options';
- import { addGraphQLCustomFields } from './graphql-custom-fields';
- export interface GraphQLApiOptions {
- apiType: 'shop' | 'admin';
- typePaths: string[];
- apiPath: string;
- // tslint:disable-next-line:ban-types
- resolverModule: Function;
- }
- /**
- * Dynamically generates a GraphQLModule according to the given config options.
- */
- export function configureGraphQLModule(
- getOptions: (configService: ConfigService) => GraphQLApiOptions,
- ): DynamicModule {
- return GraphQLModule.forRootAsync({
- useFactory: (
- configService: ConfigService,
- i18nService: I18nService,
- idCodecService: IdCodecService,
- typesLoader: GraphQLTypesLoader,
- ) => {
- return createGraphQLOptions(
- i18nService,
- configService,
- idCodecService,
- typesLoader,
- getOptions(configService),
- );
- },
- inject: [ConfigService, I18nService, IdCodecService, GraphQLTypesLoader],
- imports: [ConfigModule, I18nModule, ApiSharedModule],
- });
- }
- async function createGraphQLOptions(
- i18nService: I18nService,
- configService: ConfigService,
- idCodecService: IdCodecService,
- typesLoader: GraphQLTypesLoader,
- options: GraphQLApiOptions,
- ): Promise<GqlModuleOptions> {
- // Prevent `Type "Node" is missing a "resolveType" resolver.` warnings.
- // See https://github.com/apollographql/apollo-server/issues/1075
- const dummyResolveType = {
- __resolveType() {
- return null;
- },
- };
- return {
- path: '/' + options.apiPath,
- typeDefs: await createTypeDefs(options.apiType),
- include: [options.resolverModule],
- resolvers: {
- JSON: GraphQLJSON,
- DateTime: GraphQLDateTime,
- Node: dummyResolveType,
- PaginatedList: dummyResolveType,
- Upload: GraphQLUpload || dummyResolveType,
- SearchResultPrice: {
- __resolveType(value: any) {
- return value.hasOwnProperty('value') ? 'SinglePrice' : 'PriceRange';
- },
- },
- },
- uploads: {
- maxFileSize: configService.assetOptions.uploadMaxFileSize,
- },
- playground: true,
- debug: true,
- context: (req: any) => req,
- extensions: [
- () => new TranslateErrorExtension(i18nService),
- () => new IdEncoderExtension(idCodecService),
- ],
- // This is handled by the Express cors plugin
- cors: false,
- };
- /**
- * Generates the server's GraphQL schema by combining:
- * 1. the default schema as defined in the source .graphql files specified by `typePaths`
- * 2. any custom fields defined in the config
- * 3. any schema extensions defined by plugins
- */
- async function createTypeDefs(apiType: 'shop' | 'admin'): Promise<string> {
- const customFields = configService.customFields;
- const typeDefs = await typesLoader.mergeTypesByPaths(options.typePaths);
- let schema = generateListOptions(typeDefs);
- schema = addGraphQLCustomFields(schema, customFields);
- const pluginSchemaExtensions = getPluginAPIExtensions(configService.plugins, apiType).map(
- e => e.schema,
- );
- for (const documentNode of pluginSchemaExtensions) {
- schema = extendSchema(schema, documentNode);
- }
- return printSchema(schema);
- }
- }
|