graphql-config.service.ts 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. import { Injectable } from '@nestjs/common';
  2. import { GqlModuleOptions, GqlOptionsFactory } from '@nestjs/graphql';
  3. import * as fs from 'fs';
  4. import * as glob from 'glob';
  5. import { GraphQLDateTime } from 'graphql-iso-date';
  6. import * as GraphQLJSON from 'graphql-type-json';
  7. import { flatten } from 'lodash';
  8. import { mergeTypes } from 'merge-graphql-schemas';
  9. import * as path from 'path';
  10. import { ConfigService } from '../config/config.service';
  11. import { I18nService } from '../i18n/i18n.service';
  12. import { addGraphQLCustomFields } from './graphql-custom-fields';
  13. @Injectable()
  14. export class GraphqlConfigService implements GqlOptionsFactory {
  15. readonly typePaths = path.join(__dirname, '/../**/*.graphql');
  16. constructor(private i18nService: I18nService, private configService: ConfigService) {}
  17. createGqlOptions(): GqlModuleOptions {
  18. // Prevent `Type "Node" is missing a "resolveType" resolver.` warnings.
  19. // See https://github.com/apollographql/apollo-server/issues/1075
  20. const dummyResolveType = {
  21. __resolveType() {
  22. return null;
  23. },
  24. };
  25. return {
  26. path: '/' + this.configService.apiPath,
  27. typeDefs: this.createTypeDefs(),
  28. resolvers: {
  29. JSON: GraphQLJSON,
  30. DateTime: GraphQLDateTime,
  31. Node: dummyResolveType,
  32. PaginatedList: dummyResolveType,
  33. },
  34. playground: true,
  35. debug: true,
  36. context: req => req,
  37. // TODO: Need to also pass the Express context object for correct translations.
  38. // See https://github.com/apollographql/apollo-server/issues/1343
  39. formatError: err => {
  40. return this.i18nService.translateError(err);
  41. },
  42. };
  43. }
  44. private createTypeDefs(): string {
  45. const customFields = this.configService.customFields;
  46. const typeDefs = mergeTypesByPaths(this.typePaths);
  47. return addGraphQLCustomFields(typeDefs, customFields);
  48. }
  49. }
  50. /**
  51. * Copied directly from Nest's GraphQLFactory source, since there is currently an issue
  52. * with injecting the service itself. See https://github.com/nestjs/graphql/issues/52
  53. * TODO: These 2 functions rely on transitive dep (of @nestjs/graphql) and are just a
  54. * temp fix until the issue linked above is resolved.
  55. */
  56. function mergeTypesByPaths(...pathsToTypes: string[]): string {
  57. return mergeTypes(flatten(pathsToTypes.map(pattern => loadFiles(pattern))));
  58. }
  59. function loadFiles(pattern: string): any[] {
  60. const paths = glob.sync(pattern);
  61. return paths.map(p => fs.readFileSync(p, 'utf8'));
  62. }