@apollo/subgraph
Version:
Apollo Subgraph Utilities
152 lines • 7.26 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.isFederationType = exports.federationTypes = exports.serviceField = exports.entitiesField = exports.entitiesResolver = exports.LinkImportType = exports.AnyType = exports.ServiceType = exports.EntityType = void 0;
const graphql_1 = require("graphql");
const cache_control_types_1 = require("@apollo/cache-control-types");
const util_1 = require("util");
exports.EntityType = new graphql_1.GraphQLUnionType({
name: '_Entity',
types: [],
});
exports.ServiceType = new graphql_1.GraphQLObjectType({
name: '_Service',
fields: {
sdl: {
type: graphql_1.GraphQLString,
description: 'The sdl representing the federated service capabilities. Includes federation directives, removes federation types, and includes rest of full schema after schema directives have been applied',
},
},
});
exports.AnyType = new graphql_1.GraphQLScalarType({
name: '_Any',
serialize(value) {
return value;
},
});
exports.LinkImportType = new graphql_1.GraphQLScalarType({
name: 'link__Import',
specifiedByURL: null
});
function isPromise(value) {
return typeof (value === null || value === void 0 ? void 0 : value.then) === 'function';
}
async function maybeAddTypeNameToPossibleReturn(maybeObject, typename) {
const objectOrNull = await maybeObject;
if (objectOrNull !== null
&& typeof objectOrNull === 'object') {
if ('__typename' in objectOrNull && objectOrNull.__typename !== typename) {
return {
...objectOrNull,
__typename: typename,
};
}
Object.defineProperty(objectOrNull, '__typename', {
value: typename,
});
}
return objectOrNull;
}
function ensureValidRuntimeType(runtimeTypeName, schema, returnType, result) {
if (runtimeTypeName == null) {
throw new graphql_1.GraphQLError(`Abstract type "${returnType.name}" \`__resolveReference\` method must resolve to an Object type at runtime. Either the object returned by "${returnType}.__resolveReference" must include a valid \`__typename\` field, or the "${returnType.name}" type should provide a "resolveType" function or each possible type should provide an "isTypeOf" function.`);
}
if (typeof runtimeTypeName !== 'string') {
throw new graphql_1.GraphQLError(`Abstract type "${returnType.name}" \`__resolveReference\` method must resolve to an Object type at runtime with ` +
`value ${(0, util_1.inspect)(result)}, received "${(0, util_1.inspect)(runtimeTypeName)}".`);
}
const runtimeType = schema.getType(runtimeTypeName);
if (runtimeType == null) {
throw new graphql_1.GraphQLError(`Abstract type "${returnType.name}" \`__resolveReference\` method resolved to a type "${runtimeTypeName}" that does not exist inside the schema.`);
}
if (!(0, graphql_1.isObjectType)(runtimeType)) {
throw new graphql_1.GraphQLError(`Abstract type "${returnType.name}" \`__resolveReference\` method resolved to a non-object type "${runtimeTypeName}".`);
}
if (!schema.isSubType(returnType, runtimeType)) {
throw new graphql_1.GraphQLError(`Runtime Object type "${runtimeType.name}" \`__resolveReference\` method is not a possible type for "${returnType.name}".`);
}
return runtimeType;
}
async function withResolvedType({ type, value, context, info, callback, }) {
var _a;
const resolvedValue = await value;
if (resolvedValue === null) {
return resolvedValue;
}
const resolveTypeFn = (_a = type.resolveType) !== null && _a !== void 0 ? _a : graphql_1.defaultTypeResolver;
const runtimeType = resolveTypeFn(resolvedValue, context, info, type);
if (isPromise(runtimeType)) {
return runtimeType.then((name) => (callback(ensureValidRuntimeType(name, info.schema, type, resolvedValue))));
}
return callback(ensureValidRuntimeType(runtimeType, info.schema, type, resolvedValue));
}
function definedResolveReference(type) {
var _a, _b;
const extensions = type.extensions;
return (_b = (_a = extensions.apollo) === null || _a === void 0 ? void 0 : _a.subgraph) === null || _b === void 0 ? void 0 : _b.resolveReference;
}
function entitiesResolver({ representations, context, info }) {
return representations.map((reference) => {
const { __typename } = reference;
const type = info.schema.getType(__typename);
if (!type || !((0, graphql_1.isObjectType)(type) || (0, graphql_1.isInterfaceType)(type))) {
throw new Error(`The _entities resolver tried to load an entity for type "${__typename}", but no object or interface type of that name was found in the schema`);
}
const cacheControl = (0, cache_control_types_1.maybeCacheControlFromInfo)(info);
if (cacheControl) {
const cacheHint = cacheControl.cacheHintFromType(type);
if (cacheHint) {
cacheControl.cacheHint.restrict(cacheHint);
}
}
const resolveReference = definedResolveReference(type);
const result = resolveReference ? resolveReference(reference, context, info) : reference;
if ((0, graphql_1.isInterfaceType)(type)) {
return withResolvedType({
type,
value: result,
context,
info,
callback: (runtimeType) => {
let finalResult = maybeAddTypeNameToPossibleReturn(result, runtimeType.name);
if (!resolveReference) {
const runtimeResolveReference = definedResolveReference(runtimeType);
if (runtimeResolveReference) {
finalResult = isPromise(finalResult)
? finalResult.then((r) => runtimeResolveReference(r, context, info))
: runtimeResolveReference(finalResult, context, info);
finalResult = maybeAddTypeNameToPossibleReturn(finalResult, runtimeType.name);
}
}
return finalResult;
},
});
}
return maybeAddTypeNameToPossibleReturn(result, __typename);
});
}
exports.entitiesResolver = entitiesResolver;
exports.entitiesField = {
type: new graphql_1.GraphQLNonNull(new graphql_1.GraphQLList(exports.EntityType)),
args: {
representations: {
type: new graphql_1.GraphQLNonNull(new graphql_1.GraphQLList(new graphql_1.GraphQLNonNull(exports.AnyType))),
},
},
resolve(_source, { representations }, context, info) {
return entitiesResolver({ representations, context, info });
},
};
exports.serviceField = {
type: new graphql_1.GraphQLNonNull(exports.ServiceType),
};
exports.federationTypes = [
exports.ServiceType,
exports.AnyType,
exports.EntityType,
exports.LinkImportType,
];
function isFederationType(type) {
return ((0, graphql_1.isNamedType)(type) && exports.federationTypes.some(({ name }) => name === type.name));
}
exports.isFederationType = isFederationType;
//# sourceMappingURL=types.js.map