UNPKG

@graphql-tools/stitch

Version:

A set of utils for faster development of GraphQL tools

160 lines (159 loc) • 8.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isolateComputedFieldsTransformer = void 0; const graphql_1 = require("graphql"); const utils_1 = require("@graphql-tools/utils"); const wrap_1 = require("@graphql-tools/wrap"); function isolateComputedFieldsTransformer(subschemaConfig) { if (subschemaConfig.merge == null) { return [subschemaConfig]; } const baseSchemaTypes = Object.create(null); const isolatedSchemaTypes = Object.create(null); for (const typeName in subschemaConfig.merge) { const mergedTypeConfig = subschemaConfig.merge[typeName]; baseSchemaTypes[typeName] = mergedTypeConfig; if (mergedTypeConfig.fields) { const baseFields = Object.create(null); const isolatedFields = Object.create(null); for (const fieldName in mergedTypeConfig.fields) { const mergedFieldConfig = mergedTypeConfig.fields[fieldName]; if (mergedFieldConfig.computed && mergedFieldConfig.selectionSet) { isolatedFields[fieldName] = mergedFieldConfig; } else if (mergedFieldConfig.computed) { throw new Error(`A selectionSet is required for computed field "${typeName}.${fieldName}"`); } else { baseFields[fieldName] = mergedFieldConfig; } } const isolatedFieldCount = Object.keys(isolatedFields).length; const objectType = subschemaConfig.schema.getType(typeName); if (isolatedFieldCount && isolatedFieldCount !== Object.keys(objectType.getFields()).length) { baseSchemaTypes[typeName] = { ...mergedTypeConfig, fields: baseFields, }; isolatedSchemaTypes[typeName] = { ...mergedTypeConfig, fields: isolatedFields, canonical: undefined, }; } } } if (Object.keys(isolatedSchemaTypes).length) { return [ filterBaseSubschema({ ...subschemaConfig, merge: baseSchemaTypes }, isolatedSchemaTypes), filterIsolatedSubschema({ ...subschemaConfig, merge: isolatedSchemaTypes }), ]; } return [subschemaConfig]; } exports.isolateComputedFieldsTransformer = isolateComputedFieldsTransformer; function filterBaseSubschema(subschemaConfig, isolatedSchemaTypes) { var _a; const schema = subschemaConfig.schema; const typesForInterface = {}; const filteredSchema = (0, utils_1.pruneSchema)((0, utils_1.filterSchema)({ schema, objectFieldFilter: (typeName, fieldName) => { var _a, _b; return !((_b = (_a = isolatedSchemaTypes[typeName]) === null || _a === void 0 ? void 0 : _a.fields) === null || _b === void 0 ? void 0 : _b[fieldName]); }, interfaceFieldFilter: (typeName, fieldName) => { if (!typesForInterface[typeName]) { typesForInterface[typeName] = (0, utils_1.getImplementingTypes)(typeName, schema); } return !typesForInterface[typeName].some(implementingTypeName => { var _a, _b; return (_b = (_a = isolatedSchemaTypes[implementingTypeName]) === null || _a === void 0 ? void 0 : _a.fields) === null || _b === void 0 ? void 0 : _b[fieldName]; }); }, })); const filteredFields = {}; for (const typeName in filteredSchema.getTypeMap()) { const type = filteredSchema.getType(typeName); if ((0, graphql_1.isObjectType)(type) || (0, graphql_1.isInterfaceType)(type)) { filteredFields[typeName] = { __typename: true }; const fieldMap = type.getFields(); for (const fieldName in fieldMap) { filteredFields[typeName][fieldName] = true; } } } const filteredSubschema = { ...subschemaConfig, merge: subschemaConfig.merge ? { ...subschemaConfig.merge, } : undefined, transforms: ((_a = subschemaConfig.transforms) !== null && _a !== void 0 ? _a : []).concat([ new wrap_1.TransformCompositeFields((typeName, fieldName) => { var _a; return (((_a = filteredFields[typeName]) === null || _a === void 0 ? void 0 : _a[fieldName]) ? undefined : null); }, (typeName, fieldName) => { var _a; return (((_a = filteredFields[typeName]) === null || _a === void 0 ? void 0 : _a[fieldName]) ? undefined : null); }), ]), }; const remainingTypes = filteredSchema.getTypeMap(); const mergeConfig = filteredSubschema.merge; if (mergeConfig) { for (const mergeType in mergeConfig) { if (!remainingTypes[mergeType]) { delete mergeConfig[mergeType]; } } if (!Object.keys(mergeConfig).length) { delete filteredSubschema.merge; } } return filteredSubschema; } function filterIsolatedSubschema(subschemaConfig) { var _a, _b, _c; const rootFields = {}; for (const typeName in subschemaConfig.merge) { const mergedTypeConfig = subschemaConfig.merge[typeName]; const entryPoints = (_a = mergedTypeConfig.entryPoints) !== null && _a !== void 0 ? _a : [mergedTypeConfig]; for (const entryPoint of entryPoints) { if (entryPoint.fieldName != null) { rootFields[entryPoint.fieldName] = true; } } } const interfaceFields = {}; for (const typeName in subschemaConfig.merge) { const type = subschemaConfig.schema.getType(typeName); if (!type || !('getInterfaces' in type)) { throw new Error(`${typeName} expected to have 'getInterfaces' method`); } for (const int of type.getInterfaces()) { const intType = subschemaConfig.schema.getType(int.name); if (!intType || !('getFields' in intType)) { throw new Error(`${int.name} expected to have 'getFields' method`); } for (const intFieldName in intType.getFields()) { if ((_b = subschemaConfig.merge[typeName].fields) === null || _b === void 0 ? void 0 : _b[intFieldName]) { interfaceFields[int.name] = interfaceFields[int.name] || {}; interfaceFields[int.name][intFieldName] = true; } } } } const filteredSchema = (0, utils_1.pruneSchema)((0, utils_1.filterSchema)({ schema: subschemaConfig.schema, rootFieldFilter: (operation, fieldName) => operation === 'Query' && rootFields[fieldName] != null, objectFieldFilter: (typeName, fieldName) => { var _a, _b; return ((_b = (_a = subschemaConfig.merge[typeName]) === null || _a === void 0 ? void 0 : _a.fields) === null || _b === void 0 ? void 0 : _b[fieldName]) != null; }, interfaceFieldFilter: (typeName, fieldName) => { var _a; return ((_a = interfaceFields[typeName]) === null || _a === void 0 ? void 0 : _a[fieldName]) != null; }, })); const filteredFields = {}; for (const typeName in filteredSchema.getTypeMap()) { const type = filteredSchema.getType(typeName); if ((0, graphql_1.isObjectType)(type) || (0, graphql_1.isInterfaceType)(type)) { filteredFields[typeName] = { __typename: true }; const fieldMap = type.getFields(); for (const fieldName in fieldMap) { filteredFields[typeName][fieldName] = true; } } } return { ...subschemaConfig, transforms: ((_c = subschemaConfig.transforms) !== null && _c !== void 0 ? _c : []).concat([ new wrap_1.TransformCompositeFields((typeName, fieldName) => { var _a; return (((_a = filteredFields[typeName]) === null || _a === void 0 ? void 0 : _a[fieldName]) ? undefined : null); }, (typeName, fieldName) => { var _a; return (((_a = filteredFields[typeName]) === null || _a === void 0 ? void 0 : _a[fieldName]) ? undefined : null); }), ]), }; }