@theguild/federation-composition
Version:
Open Source Composition library for Apollo Federation
107 lines (104 loc) • 4.06 kB
JavaScript
import { Kind } from 'graphql';
import { print } from './graphql/printer.js';
import { transformSupergraphToPublicSchema } from './graphql/transform-supergraph-to-public-schema.js';
import { sdl as authenticatedSDL } from './specifications/authenticated.js';
import { sdl as inaccessibleSDL } from './specifications/inaccessible.js';
import { sdl as joinSDL } from './specifications/join.js';
import { sdl as linkSDL, printLink } from './specifications/link.js';
import { sdl as policySDL } from './specifications/policy.js';
import { sdl as requiresScopesSDL } from './specifications/requires-scopes.js';
import { sdl as tagSDL } from './specifications/tag.js';
import { validate } from './validate.js';
export function composeServices(services, __internal) {
const validationResult = validate(services, __internal);
if (!validationResult.success) {
return {
errors: validationResult.errors,
};
}
const rootTypes = {
query: false,
mutation: false,
subscription: false,
};
for (const def of validationResult.supergraph) {
if (def.name.value === 'Query') {
rootTypes.query = true;
}
else if (def.name.value === 'Mutation') {
rootTypes.mutation = true;
}
else if (def.name.value === 'Subscription') {
rootTypes.subscription = true;
}
if (rootTypes.query === true &&
rootTypes.mutation === true &&
rootTypes.subscription === true) {
break;
}
}
const usedTagSpec = validationResult.specs.tag;
const usedInaccessibleSpec = validationResult.specs.inaccessible;
const usedPolicySpec = validationResult.specs.policy;
const usedRequiresScopesSpec = validationResult.specs.requiresScopes;
const usedAuthenticatedSpec = validationResult.specs.authenticated;
let _publicSdl;
return {
supergraphSdl: `
schema
@link(url: "https://specs.apollo.dev/link/v1.0")
@link(url: "https://specs.apollo.dev/join/v0.3", for: EXECUTION)
${usedTagSpec ? '@link(url: "https://specs.apollo.dev/tag/v0.3")' : ''}
${usedInaccessibleSpec
? '@link(url: "https://specs.apollo.dev/inaccessible/v0.2", for: SECURITY)'
: ''}
${usedPolicySpec ? '@link(url: "https://specs.apollo.dev/policy/v0.1", for: SECURITY)' : ''}
${usedRequiresScopesSpec
? '@link(url: "https://specs.apollo.dev/requiresScopes/v0.1", for: SECURITY)'
: ''}
${usedAuthenticatedSpec
? '@link(url: "https://specs.apollo.dev/authenticated/v0.1", for: SECURITY)'
: ''}
${validationResult.links.map(printLink).join('\n ')}
{
${rootTypes.query ? 'query: Query' : ''}
${rootTypes.mutation ? 'mutation: Mutation' : ''}
${rootTypes.subscription ? 'subscription: Subscription' : ''}
}
${joinSDL}
${linkSDL}
${usedTagSpec ? tagSDL : ''}
${usedInaccessibleSpec ? inaccessibleSDL : ''}
${usedPolicySpec ? policySDL : ''}
${usedRequiresScopesSpec ? requiresScopesSDL : ''}
${usedAuthenticatedSpec ? authenticatedSDL : ''}
${print({
kind: Kind.DOCUMENT,
definitions: validationResult.supergraph,
})}
`,
get publicSdl() {
if (_publicSdl) {
return _publicSdl;
}
_publicSdl = print(transformSupergraphToPublicSchema({
kind: Kind.DOCUMENT,
definitions: validationResult.supergraph,
}));
return _publicSdl;
},
};
}
export function assertCompositionSuccess(compositionResult, message) {
if (compositionHasErrors(compositionResult)) {
throw new Error(message || 'Unexpected test failure');
}
}
export function assertCompositionFailure(compositionResult, message) {
if (!compositionHasErrors(compositionResult)) {
throw new Error(message || 'Unexpected test failure');
}
}
export function compositionHasErrors(compositionResult) {
return 'errors' in compositionResult && !!compositionResult.errors;
}