UNPKG

@graphql-tools/federation

Version:

Useful tools to create and manipulate GraphQL schemas.

127 lines (121 loc) 4.54 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.buildSubgraphSchema = exports.SubgraphBaseSDL = void 0; const graphql_1 = require("graphql"); const value_or_promise_1 = require("value-or-promise"); const merge_1 = require("@graphql-tools/merge"); const schema_1 = require("@graphql-tools/schema"); const utils_1 = require("@graphql-tools/utils"); exports.SubgraphBaseSDL = ` scalar _Any scalar _FieldSet scalar link__Import enum link__Purpose { SECURITY EXECUTION } type _Service { sdl: String! } type Query { _service: _Service! } directive @external on FIELD_DEFINITION | OBJECT directive @requires(fields: _FieldSet!) on FIELD_DEFINITION directive @provides(fields: _FieldSet!) on FIELD_DEFINITION directive @key(fields: _FieldSet!, resolvable: Boolean = true) repeatable on OBJECT | INTERFACE directive @link( url: String! as: String for: link__Purpose import: [link__Import] ) repeatable on SCHEMA directive @shareable repeatable on OBJECT | FIELD_DEFINITION directive @inaccessible on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION directive @tag( name: String! ) repeatable on FIELD_DEFINITION | INTERFACE | OBJECT | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION directive @override(from: String!) on FIELD_DEFINITION directive @composeDirective(name: String!) repeatable on SCHEMA directive @extends on OBJECT | INTERFACE `; function buildSubgraphSchema(optsOrModules) { const opts = Array.isArray(optsOrModules) ? { typeDefs: optsOrModules.map(opt => opt.typeDefs), resolvers: optsOrModules.map(opt => opt.resolvers).flat(), } : optsOrModules; const entityTypeNames = []; function handleEntity(node) { if (node.directives?.some(directive => directive.name.value === 'key')) { entityTypeNames.push(node.name.value); } } const typeDefs = (0, graphql_1.visit)((0, merge_1.mergeTypeDefs)([exports.SubgraphBaseSDL, opts.typeDefs]), { ObjectTypeDefinition: node => { handleEntity(node); }, ObjectTypeExtension: node => { handleEntity(node); return { ...node, kind: graphql_1.Kind.OBJECT_TYPE_DEFINITION, directives: [ ...(node.directives || []), { kind: 'Directive', name: { kind: 'Name', value: 'extends', }, }, ], }; }, }); const givenResolvers = (0, merge_1.mergeResolvers)(opts.resolvers); const allTypeDefs = [typeDefs]; const allResolvers = [sdlResolvers, givenResolvers]; if (entityTypeNames.length > 0) { allTypeDefs.push(`union _Entity = ${entityTypeNames.join(' | ')}`); allTypeDefs.push(`extend type Query { _entities(representations: [_Any!]!): [_Entity]! }`); allResolvers.push({ _Entity: { __resolveType: entityTypeResolver, }, Query: { _entities: (_root, args, context, info) => value_or_promise_1.ValueOrPromise.all(args.representations.map(representation => new value_or_promise_1.ValueOrPromise(() => givenResolvers[representation.__typename]?.__resolveReference?.(representation, context, info)).then(resolvedEntity => { if (!resolvedEntity) { return representation; } if (!resolvedEntity.__typename) { resolvedEntity.__typename = representation.__typename; } return resolvedEntity; }))).resolve(), }, }); } return (0, schema_1.makeExecutableSchema)({ assumeValid: true, assumeValidSDL: true, ...opts, typeDefs: allTypeDefs, resolvers: allResolvers, }); } exports.buildSubgraphSchema = buildSubgraphSchema; function entityTypeResolver(obj) { return obj.__typename; } const sdlResolvers = { Query: { _service: () => ({}), }, _Service: { sdl: (_root, _args, _context, info) => (0, utils_1.printSchemaWithDirectives)(info.schema), }, };