@apollo/federation-internals
Version:
Apollo Federation internal utilities
156 lines • 7.97 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.Supergraph = exports.isFed1Supergraph = exports.validateSupergraph = exports.ROUTER_SUPPORTED_SUPERGRAPH_FEATURES = exports.DEFAULT_SUPPORTED_SUPERGRAPH_FEATURES = void 0;
const definitions_1 = require("./definitions");
const coreSpec_1 = require("./specs/coreSpec");
const joinSpec_1 = require("./specs/joinSpec");
const contextSpec_1 = require("./specs/contextSpec");
const costSpec_1 = require("./specs/costSpec");
const buildSchema_1 = require("./buildSchema");
const extractSubgraphsFromSupergraph_1 = require("./extractSubgraphsFromSupergraph");
const error_1 = require("./error");
exports.DEFAULT_SUPPORTED_SUPERGRAPH_FEATURES = new Set([
'https://specs.apollo.dev/core/v0.1',
'https://specs.apollo.dev/core/v0.2',
'https://specs.apollo.dev/join/v0.1',
'https://specs.apollo.dev/join/v0.2',
'https://specs.apollo.dev/join/v0.3',
'https://specs.apollo.dev/join/v0.4',
'https://specs.apollo.dev/join/v0.5',
'https://specs.apollo.dev/tag/v0.1',
'https://specs.apollo.dev/tag/v0.2',
'https://specs.apollo.dev/tag/v0.3',
'https://specs.apollo.dev/inaccessible/v0.1',
'https://specs.apollo.dev/inaccessible/v0.2',
]);
exports.ROUTER_SUPPORTED_SUPERGRAPH_FEATURES = new Set([
'https://specs.apollo.dev/core/v0.1',
'https://specs.apollo.dev/core/v0.2',
'https://specs.apollo.dev/join/v0.1',
'https://specs.apollo.dev/join/v0.2',
'https://specs.apollo.dev/join/v0.3',
'https://specs.apollo.dev/join/v0.4',
'https://specs.apollo.dev/join/v0.5',
'https://specs.apollo.dev/tag/v0.1',
'https://specs.apollo.dev/tag/v0.2',
'https://specs.apollo.dev/tag/v0.3',
'https://specs.apollo.dev/inaccessible/v0.1',
'https://specs.apollo.dev/inaccessible/v0.2',
'https://specs.apollo.dev/authenticated/v0.1',
'https://specs.apollo.dev/requiresScopes/v0.1',
'https://specs.apollo.dev/policy/v0.1',
'https://specs.apollo.dev/source/v0.1',
'https://specs.apollo.dev/context/v0.1',
'https://specs.apollo.dev/cost/v0.1',
'https://specs.apollo.dev/connect/v0.1',
]);
const coreVersionZeroDotOneUrl = coreSpec_1.FeatureUrl.parse('https://specs.apollo.dev/core/v0.1');
function checkFeatureSupport(coreFeatures, supportedFeatures) {
const errors = [];
const coreItself = coreFeatures.coreItself;
if (coreItself.url.equals(coreVersionZeroDotOneUrl)) {
const purposefulFeatures = [...coreFeatures.allFeatures()].filter(f => f.purpose);
if (purposefulFeatures.length > 0) {
errors.push(error_1.ERRORS.UNSUPPORTED_LINKED_FEATURE.err(`the \`for:\` argument is unsupported by version ${coreItself.url.version} ` +
`of the core spec. Please upgrade to at least @core v0.2 (https://specs.apollo.dev/core/v0.2).`, {
nodes: (0, definitions_1.sourceASTs)(coreItself.directive, ...purposefulFeatures.map(f => f.directive))
}));
}
}
for (const feature of coreFeatures.allFeatures()) {
if (feature.url.equals(coreVersionZeroDotOneUrl) || feature.purpose === 'EXECUTION' || feature.purpose === 'SECURITY') {
if (!supportedFeatures.has(feature.url.base.toString())) {
errors.push(error_1.ERRORS.UNSUPPORTED_LINKED_FEATURE.err(`feature ${feature.url} is for: ${feature.purpose} but is unsupported`, { nodes: feature.directive.sourceAST }));
}
}
}
if (errors.length > 0) {
throw (0, coreSpec_1.ErrCoreCheckFailed)(errors);
}
}
function validateSupergraph(supergraph) {
const coreFeatures = supergraph.coreFeatures;
if (!coreFeatures) {
throw error_1.ERRORS.INVALID_FEDERATION_SUPERGRAPH.err("Invalid supergraph: must be a core schema");
}
const joinFeature = coreFeatures.getByIdentity(joinSpec_1.joinIdentity);
if (!joinFeature) {
throw error_1.ERRORS.INVALID_FEDERATION_SUPERGRAPH.err("Invalid supergraph: must use the join spec");
}
const joinSpec = joinSpec_1.JOIN_VERSIONS.find(joinFeature.url.version);
if (!joinSpec) {
throw error_1.ERRORS.INVALID_FEDERATION_SUPERGRAPH.err(`Invalid supergraph: uses unsupported join spec version ${joinFeature.url.version} (supported versions: ${joinSpec_1.JOIN_VERSIONS.versions().join(', ')})`);
}
const contextFeature = coreFeatures.getByIdentity(contextSpec_1.ContextSpecDefinition.identity);
let contextSpec = undefined;
if (contextFeature) {
contextSpec = contextSpec_1.CONTEXT_VERSIONS.find(contextFeature.url.version);
if (!contextSpec) {
throw error_1.ERRORS.INVALID_FEDERATION_SUPERGRAPH.err(`Invalid supergraph: uses unsupported context spec version ${contextFeature.url.version} (supported versions: ${contextSpec_1.CONTEXT_VERSIONS.versions().join(', ')})`);
}
}
const costFeature = coreFeatures.getByIdentity(costSpec_1.costIdentity);
let costSpec = undefined;
if (costFeature) {
costSpec = costSpec_1.COST_VERSIONS.find(costFeature.url.version);
if (!costSpec) {
throw error_1.ERRORS.INVALID_FEDERATION_SUPERGRAPH.err(`Invalid supergraph: uses unsupported cost spec version ${costFeature.url.version} (supported versions: ${costSpec_1.COST_VERSIONS.versions().join(', ')})`);
}
}
return [coreFeatures, joinSpec, contextSpec, costSpec];
}
exports.validateSupergraph = validateSupergraph;
function isFed1Supergraph(supergraph) {
return validateSupergraph(supergraph)[1].version.equals(new coreSpec_1.FeatureVersion(0, 1));
}
exports.isFed1Supergraph = isFed1Supergraph;
class Supergraph {
constructor(schema, supportedFeatures = exports.DEFAULT_SUPPORTED_SUPERGRAPH_FEATURES, shouldValidate = true) {
this.schema = schema;
this.shouldValidate = shouldValidate;
const [coreFeatures] = validateSupergraph(schema);
if (supportedFeatures !== null) {
checkFeatureSupport(coreFeatures, supportedFeatures);
}
if (shouldValidate) {
schema.validate();
}
else {
schema.assumeValid();
}
this.containedSubgraphs = (0, extractSubgraphsFromSupergraph_1.extractSubgraphsNamesAndUrlsFromSupergraph)(schema);
}
static build(supergraphSdl, options) {
const schema = typeof supergraphSdl === 'string'
? (0, buildSchema_1.buildSchema)(supergraphSdl, { validate: false })
: (0, buildSchema_1.buildSchemaFromAST)(supergraphSdl, { validate: false });
return new Supergraph(schema, options === null || options === void 0 ? void 0 : options.supportedFeatures, options === null || options === void 0 ? void 0 : options.validateSupergraph);
}
static buildForTests(supergraphSdl, validateSupergraph) {
return Supergraph.build(supergraphSdl, { supportedFeatures: exports.ROUTER_SUPPORTED_SUPERGRAPH_FEATURES, validateSupergraph });
}
subgraphsMetadata() {
return this.containedSubgraphs;
}
subgraphs() {
if (!this._subgraphs) {
const extractionResults = (0, extractSubgraphsFromSupergraph_1.extractSubgraphsFromSupergraph)(this.schema, this.shouldValidate);
this._subgraphs = extractionResults[0];
this._subgraphNameToGraphEnumValue = extractionResults[1];
}
return this._subgraphs;
}
subgraphNameToGraphEnumValue() {
if (!this._subgraphNameToGraphEnumValue) {
const extractionResults = (0, extractSubgraphsFromSupergraph_1.extractSubgraphsFromSupergraph)(this.schema, this.shouldValidate);
this._subgraphs = extractionResults[0];
this._subgraphNameToGraphEnumValue = extractionResults[1];
}
return new Map([...this._subgraphNameToGraphEnumValue]);
}
apiSchema() {
return this.schema.toAPISchema();
}
}
exports.Supergraph = Supergraph;
//# sourceMappingURL=supergraphs.js.map
;