@grapes-agency/apollo-link-local-schema
Advanced tools
Comparing version 1.0.0-alpha.12 to 1.0.0-alpha.13
@@ -5,2 +5,9 @@ # Changelog | ||
## [1.0.0-alpha.13](https://github.com/grapes-agency/apollo-link-local-schema/compare/v1.0.0-alpha.12...v1.0.0-alpha.13) (2020-10-22) | ||
### Bug Fixes | ||
* general fixes ([5b50f7b](https://github.com/grapes-agency/apollo-link-local-schema/commit/5b50f7b5212a52c1e602a4191bb11f349dbb9300)) | ||
## [1.0.0-alpha.12](https://github.com/grapes-agency/apollo-link-local-schema/compare/v1.0.0-alpha.11...v1.0.0-alpha.12) (2020-10-20) | ||
@@ -7,0 +14,0 @@ |
512
index.cjs.js
@@ -5,8 +5,220 @@ 'use strict'; | ||
var client = require('@apollo/client'); | ||
var core = require('@apollo/client/core'); | ||
var LocalState = require('@apollo/client/core/LocalState'); | ||
var utilities = require('@apollo/client/utilities'); | ||
var graphql = require('graphql'); | ||
var tslib = require('tslib'); | ||
var graphql = require('graphql'); | ||
const isObjectTypeDefinition = (node) => node.kind === 'ObjectTypeDefinition'; | ||
const isInterfaceTypeDefinition = (node) => node.kind === 'InterfaceTypeDefinition'; | ||
const isUnionTypeDefinition = (node) => node.kind === 'UnionTypeDefinition'; | ||
const isInputObjectTypeDefinition = (node) => node.kind === 'InputObjectTypeDefinition'; | ||
const isEnumTypeDefinition = (node) => node.kind === 'EnumTypeDefinition'; | ||
const isObjectTypeExtension = (node) => node.kind === 'ObjectTypeExtension'; | ||
const isScalarTypeDefinition = (node) => node.kind === 'ScalarTypeDefinition'; | ||
const isOperationDefinition = (node) => node.kind === 'OperationDefinition'; | ||
const isDirectiveDefinition = (node) => node.kind === 'DirectiveDefinition'; | ||
const isFragmentDefinition = (node) => node.kind === 'FragmentDefinition'; | ||
const isSchemaDefinition = (node) => node.kind === 'SchemaDefinition'; | ||
const isTypeDefinition = (node) => [ | ||
'ScalarTypeDefinition', | ||
'ObjectTypeDefinition', | ||
'InterfaceTypeDefinition', | ||
'UnionTypeDefinition', | ||
'EnumTypeDefinition', | ||
'InputObjectTypeDefinition', | ||
].includes(node.kind); | ||
const isListType = (node) => node.kind === 'ListType'; | ||
const isNonNullType = (node) => node.kind === 'NonNullType'; | ||
const getTypeName = (type) => { | ||
if (type.kind === 'NonNullType' || type.kind === 'ListType') { | ||
return getTypeName(type.type); | ||
} | ||
return type.name.value; | ||
}; | ||
const isDeepListType = (type) => { | ||
if (type.kind === 'NonNullType') { | ||
return isDeepListType(type.type); | ||
} | ||
return type.kind === 'ListType'; | ||
}; | ||
// https://github.com/graphql/graphql-spec/blob/master/spec/Section%204%20--%20Introspection.md | ||
const specifiedDefinitions = graphql.specifiedScalarTypes.map(scalarType => (Object.assign({ kind: 'ScalarTypeDefinition', name: { | ||
kind: 'Name', | ||
value: scalarType.name, | ||
} }, (scalarType.description | ||
? { | ||
description: { | ||
kind: 'StringValue', | ||
value: scalarType.description, | ||
}, | ||
} | ||
: {})))); | ||
const getDeprecateDirective = (node) => { var _a; return (_a = node.directives) === null || _a === void 0 ? void 0 : _a.find(directive => directive.name.value === 'deprecated'); }; | ||
const isDeprecated = (node) => Boolean(getDeprecateDirective(node)); | ||
const getDeprecationReason = (node) => { | ||
var _a; | ||
const directive = getDeprecateDirective(node); | ||
if (!directive) { | ||
return null; | ||
} | ||
const reasonArg = (_a = directive.arguments) === null || _a === void 0 ? void 0 : _a.find(arg => arg.name.value === 'reason'); | ||
if (!reasonArg) { | ||
return null; | ||
} | ||
return reasonArg.value.value; | ||
}; | ||
const addIntrospectionResolvers = (resolvers, typeDefs, { includeObjectTypeExtensions: allowObjectExtensions = false } = {}) => { | ||
var _a; | ||
const allTypes = [...specifiedDefinitions, ...typeDefs.definitions].filter(type => isTypeDefinition(type) || (allowObjectExtensions && isObjectTypeExtension(type))); | ||
const findType = (name) => allTypes.find(definition => { var _a; return 'name' in definition && ((_a = definition.name) === null || _a === void 0 ? void 0 : _a.value) === name; }); | ||
const schemaDefinition = typeDefs.definitions.find(isSchemaDefinition); | ||
const queryName = ((_a = schemaDefinition === null || schemaDefinition === void 0 ? void 0 : schemaDefinition.operationTypes.find(operationType => operationType.operation === 'query')) === null || _a === void 0 ? void 0 : _a.type.name.value) || 'Query'; | ||
const findMainType = (name, fallbackName) => { | ||
const queryOperation = schemaDefinition === null || schemaDefinition === void 0 ? void 0 : schemaDefinition.operationTypes.find(operationType => operationType.operation === name); | ||
const typeName = (queryOperation === null || queryOperation === void 0 ? void 0 : queryOperation.type.name.value) || fallbackName; | ||
const type = findType(typeName); | ||
if (type) { | ||
return { | ||
__typename: '__Type', | ||
node: type, | ||
}; | ||
} | ||
return null; | ||
}; | ||
if (!resolvers[queryName]) { | ||
resolvers[queryName] = {}; | ||
} | ||
resolvers[queryName].__schema = () => ({ | ||
__typename: '__Schema', | ||
}); | ||
resolvers[queryName].__type = (_root, { name }) => { | ||
const type = findType(name); | ||
if (type) { | ||
return { __typename: '__Type', node: type }; | ||
} | ||
return null; | ||
}; | ||
resolvers.__Schema = { | ||
description: () => { var _a; return ((_a = schemaDefinition === null || schemaDefinition === void 0 ? void 0 : schemaDefinition.description) === null || _a === void 0 ? void 0 : _a.value) || null; }, | ||
queryType: () => findMainType('query', 'Query'), | ||
mutationType: () => findMainType('mutation', 'Mutation'), | ||
subscriptionType: () => findMainType('subscription', 'Subscription'), | ||
directives: () => typeDefs.definitions.filter(isDirectiveDefinition).map(node => ({ __typename: '__Directive', node })), | ||
types: () => allTypes.map(type => ({ __typename: '__Type', node: type })), | ||
}; | ||
resolvers.__Type = { | ||
kind: ({ node }) => { | ||
switch (node.kind) { | ||
case 'ScalarTypeDefinition': { | ||
return 'SCALAR'; | ||
} | ||
case 'ObjectTypeDefinition': | ||
case 'ObjectTypeExtension': { | ||
return 'OBJECT'; | ||
} | ||
case 'InterfaceTypeDefinition': { | ||
return 'INTERFACE'; | ||
} | ||
case 'UnionTypeDefinition': { | ||
return 'UNION'; | ||
} | ||
case 'EnumTypeDefinition': { | ||
return 'ENUM'; | ||
} | ||
case 'InputObjectTypeDefinition': { | ||
return 'INPUT_OBJECT'; | ||
} | ||
case 'ListType': { | ||
return 'LIST'; | ||
} | ||
case 'NonNullType': { | ||
return 'NON_NULL'; | ||
} | ||
default: { | ||
throw new Error(`Unknown kind ${node.kind}`); | ||
} | ||
} | ||
}, | ||
name: ({ node }) => { var _a; return ('name' in node ? ((_a = node.name) === null || _a === void 0 ? void 0 : _a.value) || null : null); }, | ||
description: ({ node }) => { var _a; return ('description' in node ? ((_a = node.description) === null || _a === void 0 ? void 0 : _a.value) || null : null); }, | ||
fields: ({ node }, args) => { | ||
var _a; | ||
if (!(isObjectTypeDefinition(node) || isInterfaceTypeDefinition(node) || isObjectTypeExtension(node))) { | ||
return null; | ||
} | ||
return (((_a = node.fields) === null || _a === void 0 ? void 0 : _a.filter(field => (args && args.includeDeprecated) || !isDeprecated(field)).map(field => ({ __typename: '__Field', node: field }))) || []); | ||
}, | ||
interfaces: ({ node }) => { | ||
var _a; | ||
if (!(isObjectTypeDefinition(node) || isInterfaceTypeDefinition(node) || isObjectTypeExtension(node))) { | ||
return null; | ||
} | ||
return ((_a = node.interfaces) === null || _a === void 0 ? void 0 : _a.map(iface => ({ __typename: '__Type', node: iface }))) || []; | ||
}, | ||
possibleTypes: ({ node }) => { | ||
var _a; | ||
if (!isUnionTypeDefinition(node)) { | ||
return null; | ||
} | ||
// @todo add interface type here | ||
return ((_a = node.types) === null || _a === void 0 ? void 0 : _a.map(type => ({ __typename: '__Type', node: findType(type.name.value) }))) || []; | ||
}, | ||
enumValues: ({ node }, args) => { | ||
var _a; | ||
if (!isEnumTypeDefinition(node)) { | ||
return null; | ||
} | ||
return (((_a = node.values) === null || _a === void 0 ? void 0 : _a.filter(value => (args && args.includeDeprecated) || !isDeprecated(value)).map(value => ({ __typename: '__EnumValue', node: value }))) || []); | ||
}, | ||
inputFields: ({ node }) => { | ||
var _a; | ||
if (!isInputObjectTypeDefinition(node)) { | ||
return null; | ||
} | ||
return ((_a = node.fields) === null || _a === void 0 ? void 0 : _a.map(field => ({ __typename: '__InputValue', node: field }))) || []; | ||
}, | ||
ofType: ({ node }) => { | ||
if (!(isListType(node) || isNonNullType(node))) { | ||
return null; | ||
} | ||
return { __typename: '__Type', node: node.type.kind === 'NamedType' ? findType(node.type.name.value) : node.type }; | ||
}, | ||
}; | ||
resolvers.__Field = { | ||
name: ({ node }) => node.name.value, | ||
description: ({ node }) => { var _a; return ((_a = node.description) === null || _a === void 0 ? void 0 : _a.value) || null; }, | ||
args: ({ node }) => { var _a; return ((_a = node.arguments) === null || _a === void 0 ? void 0 : _a.map(arg => ({ __typename: '__InputValue', node: arg }))) || []; }, | ||
type: ({ node }) => ({ | ||
__typename: '__Type', | ||
node: node.type.kind === 'NamedType' ? findType(node.type.name.value) : node.type, | ||
}), | ||
isDeprecated: ({ node }) => isDeprecated(node), | ||
deprecationReason: ({ node }) => getDeprecationReason(node), | ||
}; | ||
resolvers.__InputValue = { | ||
name: ({ node }) => node.name.value, | ||
description: ({ node }) => { var _a; return ((_a = node.description) === null || _a === void 0 ? void 0 : _a.value) || null; }, | ||
type: ({ node }) => ({ | ||
__typename: '__Type', | ||
node: node.type.kind === 'NamedType' ? findType(node.type.name.value) : node.type, | ||
}), | ||
defaultValue: ({ node }) => node.defaultValue && ('value' in node.defaultValue ? String(node.defaultValue.value) : null), | ||
}; | ||
resolvers.__EnumValue = { | ||
name: ({ node }) => node.name.value, | ||
description: ({ node }) => { var _a; return ((_a = node.description) === null || _a === void 0 ? void 0 : _a.value) || null; }, | ||
isDeprecated: ({ node }) => isDeprecated(node), | ||
deprecationReason: ({ node }) => getDeprecationReason(node), | ||
}; | ||
resolvers.__Directive = { | ||
name: ({ node }) => node.name.value, | ||
description: ({ node }) => { var _a; return ((_a = node.description) === null || _a === void 0 ? void 0 : _a.value) || null; }, | ||
locations: ({ node }) => node.locations.map(location => location.value), | ||
args: ({ node }) => { var _a; return ((_a = node.arguments) === null || _a === void 0 ? void 0 : _a.map(arg => ({ __typename: '__InputValue', node: arg }))) || []; }, | ||
isRepeatable: ({ node }) => node.repeatable, | ||
}; | ||
}; | ||
const fixTypeDefs = (serviceName, typeDefs) => { | ||
@@ -77,36 +289,2 @@ for (const definition of typeDefs.definitions) { | ||
const isObjectTypeDefinition = (node) => node.kind === 'ObjectTypeDefinition'; | ||
const isInterfaceTypeDefinition = (node) => node.kind === 'InterfaceTypeDefinition'; | ||
const isUnionTypeDefinition = (node) => node.kind === 'UnionTypeDefinition'; | ||
const isInputObjectTypeDefinition = (node) => node.kind === 'InputObjectTypeDefinition'; | ||
const isEnumTypeDefinition = (node) => node.kind === 'EnumTypeDefinition'; | ||
const isObjectTypeExtension = (node) => node.kind === 'ObjectTypeExtension'; | ||
const isScalarTypeDefinition = (node) => node.kind === 'ScalarTypeDefinition'; | ||
const isOperationDefinition = (node) => node.kind === 'OperationDefinition'; | ||
const isDirectiveDefinition = (node) => node.kind === 'DirectiveDefinition'; | ||
const isFragmentDefinition = (node) => node.kind === 'FragmentDefinition'; | ||
const isSchemaDefinition = (node) => node.kind === 'SchemaDefinition'; | ||
const isTypeDefinition = (node) => [ | ||
'ScalarTypeDefinition', | ||
'ObjectTypeDefinition', | ||
'InterfaceTypeDefinition', | ||
'UnionTypeDefinition', | ||
'EnumTypeDefinition', | ||
'InputObjectTypeDefinition', | ||
].includes(node.kind); | ||
const isListType = (node) => node.kind === 'ListType'; | ||
const isNonNullType = (node) => node.kind === 'NonNullType'; | ||
const getTypeName = (type) => { | ||
if (type.kind === 'NonNullType' || type.kind === 'ListType') { | ||
return getTypeName(type.type); | ||
} | ||
return type.name.value; | ||
}; | ||
const isDeepListType = (type) => { | ||
if (type.kind === 'NonNullType') { | ||
return isDeepListType(type.type); | ||
} | ||
return type.kind === 'ListType'; | ||
}; | ||
const mergeDocuments = (documents) => { | ||
@@ -153,2 +331,9 @@ const types = new Map(); | ||
class TypeMap extends Map { | ||
constructor(typeDefs) { | ||
const objectTypeDefinitions = typeDefs.definitions.filter(definition => isObjectTypeDefinition(definition) || isObjectTypeExtension(definition)); | ||
super(objectTypeDefinitions.map(definition => [definition.name.value, definition])); | ||
} | ||
} | ||
const extendSelection = (node, fragmentMap) => { | ||
@@ -234,3 +419,3 @@ var _a; | ||
} | ||
return new client.Observable(observer => { | ||
return new core.Observable(observer => { | ||
let stopped = false; | ||
@@ -273,4 +458,3 @@ let asyncIterator; | ||
var _a; | ||
const objectTypeDefinitions = typeDefs.definitions.filter(definition => isObjectTypeDefinition(definition) || isObjectTypeExtension(definition)); | ||
const typeMap = new Map(objectTypeDefinitions.map(definition => [definition.name.value, definition])); | ||
const typeMap = new TypeMap(typeDefs); | ||
const mappedResolvers = Object.fromEntries(Object.entries(resolvers).map(([key, fields]) => { | ||
@@ -345,3 +529,3 @@ const typeDefinition = typeMap.get(key); | ||
} | ||
for (const objectTypeDefinition of objectTypeDefinitions) { | ||
for (const objectTypeDefinition of typeMap.values()) { | ||
const objectName = objectTypeDefinition.name.value; | ||
@@ -474,3 +658,3 @@ for (const field of objectTypeDefinition.fields || []) { | ||
/* eslint-disable default-case */ | ||
const alwaysAllowFields = ['__schema', '__type', '__resolveType']; | ||
const alwaysAllowFields = ['__schema', '__type', '__resolveType', '__typename']; | ||
const splitDocument = (document, objectType) => { | ||
@@ -482,2 +666,4 @@ if (!objectType) { | ||
const usedFragments = new Set(); | ||
let inFragment = false; | ||
let hasOperationDefinition = false; | ||
const baseVisitor = { | ||
@@ -489,2 +675,3 @@ OperationDefinition: { | ||
} | ||
hasOperationDefinition = true; | ||
}, | ||
@@ -495,18 +682,29 @@ }, | ||
}, | ||
FragmentDefinition(fragmentDefinition) { | ||
if (!usedFragments.has(fragmentDefinition.name.value)) { | ||
return null; | ||
} | ||
FragmentDefinition: { | ||
enter() { | ||
inFragment = true; | ||
}, | ||
leave(fragmentDefinition) { | ||
inFragment = false; | ||
if (!usedFragments.has(fragmentDefinition.name.value)) { | ||
return null; | ||
} | ||
}, | ||
}, | ||
}; | ||
let fieldDepth = -1; | ||
hasOperationDefinition = false; | ||
const internalDocument = graphql.visit(document, Object.assign(Object.assign({}, baseVisitor), { Field: { | ||
enter(field) { | ||
if (inFragment) { | ||
return; | ||
} | ||
fieldDepth += 1; | ||
if (fieldDepth > 0) { | ||
return field; | ||
return; | ||
} | ||
if (hasField(field)) { | ||
return field; | ||
return; | ||
} | ||
fieldDepth -= 1; | ||
return null; | ||
@@ -518,12 +716,18 @@ }, | ||
} })); | ||
const hasInteralOperationDefinition = hasOperationDefinition; | ||
hasOperationDefinition = false; | ||
usedFragments.clear(); | ||
const externalDocument = graphql.visit(document, Object.assign(Object.assign({}, baseVisitor), { Field: { | ||
enter(field) { | ||
if (inFragment) { | ||
return; | ||
} | ||
fieldDepth += 1; | ||
if (fieldDepth > 0) { | ||
return field; | ||
return; | ||
} | ||
if (!hasField(field)) { | ||
return field; | ||
return; | ||
} | ||
fieldDepth -= 1; | ||
return null; | ||
@@ -535,185 +739,11 @@ }, | ||
} })); | ||
const hasExternalOperationDefinition = hasOperationDefinition; | ||
return [ | ||
internalDocument && internalDocument.definitions.length > 0 ? internalDocument : null, | ||
externalDocument && externalDocument.definitions.length > 0 ? externalDocument : null, | ||
internalDocument && hasInteralOperationDefinition && internalDocument.definitions.length > 0 ? internalDocument : null, | ||
externalDocument && hasExternalOperationDefinition && externalDocument.definitions.length > 0 ? externalDocument : null, | ||
]; | ||
}; | ||
// https://github.com/graphql/graphql-spec/blob/master/spec/Section%204%20--%20Introspection.md | ||
const specifiedDefinitions = graphql.specifiedScalarTypes.map(scalarType => (Object.assign({ kind: 'ScalarTypeDefinition', name: { | ||
kind: 'Name', | ||
value: scalarType.name, | ||
} }, (scalarType.description | ||
? { | ||
description: { | ||
kind: 'StringValue', | ||
value: scalarType.description, | ||
}, | ||
} | ||
: {})))); | ||
const getDeprecateDirective = (node) => { var _a; return (_a = node.directives) === null || _a === void 0 ? void 0 : _a.find(directive => directive.name.value === 'deprecated'); }; | ||
const isDeprecated = (node) => Boolean(getDeprecateDirective(node)); | ||
const getDeprecationReason = (node) => { | ||
var _a; | ||
const directive = getDeprecateDirective(node); | ||
if (!directive) { | ||
return null; | ||
} | ||
const reasonArg = (_a = directive.arguments) === null || _a === void 0 ? void 0 : _a.find(arg => arg.name.value === 'reason'); | ||
if (!reasonArg) { | ||
return null; | ||
} | ||
return reasonArg.value.value; | ||
}; | ||
const addIntrospectionResolvers = (resolvers, typeDefs) => { | ||
const allTypes = [...specifiedDefinitions, ...typeDefs.definitions].filter(isTypeDefinition); | ||
const findType = (name) => allTypes.find(definition => { var _a; return 'name' in definition && ((_a = definition.name) === null || _a === void 0 ? void 0 : _a.value) === name; }); | ||
if (!resolvers.Query) { | ||
resolvers.Query = {}; | ||
} | ||
const schemaDefinition = typeDefs.definitions.find(isSchemaDefinition); | ||
const findMainType = (name, fallbackName) => { | ||
const queryOperation = schemaDefinition === null || schemaDefinition === void 0 ? void 0 : schemaDefinition.operationTypes.find(operationType => operationType.operation === name); | ||
const typeName = (queryOperation === null || queryOperation === void 0 ? void 0 : queryOperation.type.name.value) || fallbackName; | ||
const type = findType(typeName); | ||
if (type) { | ||
return { | ||
__typename: '__Type', | ||
node: type, | ||
}; | ||
} | ||
return null; | ||
}; | ||
resolvers.Query.__schema = () => ({ | ||
__typename: '__Schema', | ||
}); | ||
resolvers.Query.__type = (_root, { name }) => { | ||
const type = findType(name); | ||
if (type) { | ||
return { __typename: '__Type', node: type }; | ||
} | ||
return null; | ||
}; | ||
resolvers.__Schema = { | ||
description: () => { var _a; return ((_a = schemaDefinition === null || schemaDefinition === void 0 ? void 0 : schemaDefinition.description) === null || _a === void 0 ? void 0 : _a.value) || null; }, | ||
queryType: () => findMainType('query', 'Query'), | ||
mutationType: () => findMainType('mutation', 'Mutation'), | ||
subscriptionType: () => findMainType('subscription', 'Subscription'), | ||
directives: () => typeDefs.definitions.filter(isDirectiveDefinition).map(node => ({ __typename: '__Directive', node })), | ||
types: () => allTypes.map(type => ({ __typename: '__Type', node: type })), | ||
}; | ||
resolvers.__Type = { | ||
kind: ({ node }) => { | ||
switch (node.kind) { | ||
case 'ScalarTypeDefinition': { | ||
return 'SCALAR'; | ||
} | ||
case 'ObjectTypeDefinition': { | ||
return 'OBJECT'; | ||
} | ||
case 'InterfaceTypeDefinition': { | ||
return 'INTERFACE'; | ||
} | ||
case 'UnionTypeDefinition': { | ||
return 'UNION'; | ||
} | ||
case 'EnumTypeDefinition': { | ||
return 'ENUM'; | ||
} | ||
case 'InputObjectTypeDefinition': { | ||
return 'INPUT_OBJECT'; | ||
} | ||
case 'ListType': { | ||
return 'LIST'; | ||
} | ||
case 'NonNullType': { | ||
return 'NON_NULL'; | ||
} | ||
default: { | ||
throw new Error(`Unknown kind ${node.kind}`); | ||
} | ||
} | ||
}, | ||
name: ({ node }) => { var _a; return ('name' in node ? ((_a = node.name) === null || _a === void 0 ? void 0 : _a.value) || null : null); }, | ||
description: ({ node }) => { var _a; return ('description' in node ? ((_a = node.description) === null || _a === void 0 ? void 0 : _a.value) || null : null); }, | ||
fields: ({ node }, args) => { | ||
var _a; | ||
if (!(isObjectTypeDefinition(node) || isInterfaceTypeDefinition(node))) { | ||
return null; | ||
} | ||
return (((_a = node.fields) === null || _a === void 0 ? void 0 : _a.filter(field => (args && args.includeDeprecated) || !isDeprecated(field)).map(field => ({ __typename: '__Field', node: field }))) || []); | ||
}, | ||
interfaces: ({ node }) => { | ||
var _a; | ||
if (!(isObjectTypeDefinition(node) || isInterfaceTypeDefinition(node))) { | ||
return null; | ||
} | ||
return ((_a = node.interfaces) === null || _a === void 0 ? void 0 : _a.map(iface => ({ __typename: '__Type', node: iface }))) || []; | ||
}, | ||
possibleTypes: ({ node }) => { | ||
var _a; | ||
if (!isUnionTypeDefinition(node)) { | ||
return null; | ||
} | ||
// @todo add interface type here | ||
return ((_a = node.types) === null || _a === void 0 ? void 0 : _a.map(type => ({ __typename: '__Type', node: findType(type.name.value) }))) || []; | ||
}, | ||
enumValues: ({ node }, args) => { | ||
var _a; | ||
if (!isEnumTypeDefinition(node)) { | ||
return null; | ||
} | ||
return (((_a = node.values) === null || _a === void 0 ? void 0 : _a.filter(value => (args && args.includeDeprecated) || !isDeprecated(value)).map(value => ({ __typename: '__EnumValue', node: value }))) || []); | ||
}, | ||
inputFields: ({ node }) => { | ||
var _a; | ||
if (!isInputObjectTypeDefinition(node)) { | ||
return null; | ||
} | ||
return ((_a = node.fields) === null || _a === void 0 ? void 0 : _a.map(field => ({ __typename: '__InputValue', node: field }))) || []; | ||
}, | ||
ofType: ({ node }) => { | ||
if (!(isListType(node) || isNonNullType(node))) { | ||
return null; | ||
} | ||
return { __typename: '__Type', node: node.type.kind === 'NamedType' ? findType(node.type.name.value) : node.type }; | ||
}, | ||
}; | ||
resolvers.__Field = { | ||
name: ({ node }) => node.name.value, | ||
description: ({ node }) => { var _a; return ((_a = node.description) === null || _a === void 0 ? void 0 : _a.value) || null; }, | ||
args: ({ node }) => { var _a; return ((_a = node.arguments) === null || _a === void 0 ? void 0 : _a.map(arg => ({ __typename: '__InputValue', node: arg }))) || []; }, | ||
type: ({ node }) => ({ | ||
__typename: '__Type', | ||
node: node.type.kind === 'NamedType' ? findType(node.type.name.value) : node.type, | ||
}), | ||
isDeprecated: ({ node }) => isDeprecated(node), | ||
deprecationReason: ({ node }) => getDeprecationReason(node), | ||
}; | ||
resolvers.__InputValue = { | ||
name: ({ node }) => node.name.value, | ||
description: ({ node }) => { var _a; return ((_a = node.description) === null || _a === void 0 ? void 0 : _a.value) || null; }, | ||
type: ({ node }) => ({ | ||
__typename: '__Type', | ||
node: node.type.kind === 'NamedType' ? findType(node.type.name.value) : node.type, | ||
}), | ||
defaultValue: ({ node }) => node.defaultValue && ('value' in node.defaultValue ? String(node.defaultValue.value) : null), | ||
}; | ||
resolvers.__EnumValue = { | ||
name: ({ node }) => node.name.value, | ||
description: ({ node }) => { var _a; return ((_a = node.description) === null || _a === void 0 ? void 0 : _a.value) || null; }, | ||
isDeprecated: ({ node }) => isDeprecated(node), | ||
deprecationReason: ({ node }) => getDeprecationReason(node), | ||
}; | ||
resolvers.__Directive = { | ||
name: ({ node }) => node.name.value, | ||
description: ({ node }) => { var _a; return ((_a = node.description) === null || _a === void 0 ? void 0 : _a.value) || null; }, | ||
locations: ({ node }) => node.locations.map(location => location.value), | ||
args: ({ node }) => { var _a; return ((_a = node.arguments) === null || _a === void 0 ? void 0 : _a.map(arg => ({ __typename: '__InputValue', node: arg }))) || []; }, | ||
isRepeatable: ({ node }) => node.repeatable, | ||
}; | ||
}; | ||
/* eslint-disable no-shadow */ | ||
class LocalSchemaLink extends client.ApolloLink { | ||
class LocalSchemaLink extends core.ApolloLink { | ||
constructor(options) { | ||
@@ -733,3 +763,4 @@ super(); | ||
this.context = context; | ||
const mergedTypeDefs = mergeDocuments(Array.isArray(typeDefs) ? typeDefs : [typeDefs]); | ||
const typeDefsArray = Array.isArray(typeDefs) ? typeDefs : [typeDefs]; | ||
const mergedTypeDefs = mergeDocuments(typeDefsArray); | ||
const schemaDefinition = mergedTypeDefs.definitions.find(isSchemaDefinition); | ||
@@ -749,3 +780,3 @@ this.operationNames = { | ||
if (introspection) { | ||
addIntrospectionResolvers(mappedResolvers, mergedTypeDefs); | ||
addIntrospectionResolvers(mappedResolvers, mergedTypeDefs, { includeObjectTypeExtensions: Boolean(this.federated) }); | ||
} | ||
@@ -785,6 +816,6 @@ this.typeDefs = mergedTypeDefs; | ||
const operationDefinition = operation === 'query' | ||
? this.objectTypes.find(objectType => objectType.name.value === 'Query') | ||
? this.objectTypes.find(objectType => objectType.name.value === this.operationNames.query) | ||
: operation === 'mutation' | ||
? this.objectTypes.find(objectType => objectType.name.value === 'Mutation') | ||
: this.objectTypes.find(objectType => objectType.name.value === 'Subscription'); | ||
? this.objectTypes.find(objectType => objectType.name.value === this.operationNames.mutation) | ||
: this.objectTypes.find(objectType => objectType.name.value === this.operationNames.subscription); | ||
const documentsPair = splitDocument(document, operationDefinition); | ||
@@ -797,9 +828,10 @@ this.processedDocuments.set(document, documentsPair); | ||
const { query, variables } = operation; | ||
const mainDefintion = utilities.getMainDefinition(query); | ||
const mainDefinition = utilities.getMainDefinition(query); | ||
const [internalQuery, externalQuery] = this.federated ? [query, null] : this.splitDocuments(query); | ||
const isSubscription = mainDefintion.kind === 'OperationDefinition' && mainDefintion.operation === 'subscription'; | ||
const isSubscription = mainDefinition.operation === 'subscription'; | ||
const __typename = this.operationNames[mainDefinition.operation]; | ||
if (isSubscription && internalQuery && externalQuery) { | ||
throw new Error('Subscriptions cannot be a mix of local and external subscriptions'); | ||
} | ||
let nonLocalObservable = client.Observable.of({ data: {} }); | ||
let nonLocalObservable = core.Observable.of({ data: {} }); | ||
if (forward) { | ||
@@ -817,3 +849,3 @@ if (!internalQuery) { | ||
if (!isSubscription) { | ||
return nonLocalObservable.flatMap(remoteResult => new client.Observable(observer => { | ||
return nonLocalObservable.flatMap(remoteResult => new core.Observable(observer => { | ||
if (this.validateQuery) { | ||
@@ -832,3 +864,3 @@ try { | ||
document: internalQuery, | ||
remoteResult, | ||
remoteResult: Object.assign(Object.assign({}, remoteResult), { data: Object.assign(Object.assign({}, remoteResult.data), { __typename }) }), | ||
context: this.getContext(), | ||
@@ -854,3 +886,3 @@ variables, | ||
} | ||
return new client.Observable(observer => { | ||
return new core.Observable(observer => { | ||
let subscription; | ||
@@ -872,7 +904,7 @@ localState | ||
observables.push(observable | ||
.flatMap(result => new client.Observable(o => { | ||
.flatMap(result => new core.Observable(o => { | ||
localState | ||
.runResolvers({ | ||
document: internalQuery, | ||
remoteResult: { data: result }, | ||
remoteResult: { data: Object.assign(Object.assign({}, result), { __typename }) }, | ||
context: Object.assign(Object.assign({}, this.getContext()), { __subscription: true }), | ||
@@ -879,0 +911,0 @@ variables, |
/// <reference types="zen-observable" /> | ||
import { ApolloLink, Operation, NextLink, FetchResult, Observable } from '@apollo/client'; | ||
import { ApolloLink, Operation, NextLink, FetchResult, Observable } from '@apollo/client/core'; | ||
import { DocumentNode } from 'graphql'; | ||
@@ -4,0 +4,0 @@ import { Resolvers } from './interfaces'; |
@@ -1,7 +0,9 @@ | ||
import { ApolloLink, Observable } from '@apollo/client'; | ||
import { ApolloLink, Observable } from '@apollo/client/core'; | ||
import { LocalState } from '@apollo/client/core/LocalState'; | ||
import { getMainDefinition } from '@apollo/client/utilities'; | ||
import { isSchemaDefinition, isObjectTypeDefinition, isObjectTypeExtension } from './utils/node.js'; | ||
import { addIntrospectionResolvers } from './introspection/addIntrospectionResolvers.js'; | ||
import './introspection/index.js'; | ||
import { LocalFederationSupport } from './localFederation/LocalFederationSupport.js'; | ||
import './localFederation/index.js'; | ||
import { isSchemaDefinition, isObjectTypeDefinition, isObjectTypeExtension } from './utils/node.js'; | ||
import { mergeDocuments } from './utils/mergeDocuments.js'; | ||
@@ -12,3 +14,2 @@ import { mapResolvers } from './utils/mapResolvers.js'; | ||
import { splitDocument } from './utils/splitDocument.js'; | ||
import { addIntrospectionResolvers } from './utils/addIntrospectionResolvers.js'; | ||
import './utils/index.js'; | ||
@@ -32,3 +33,4 @@ | ||
this.context = context; | ||
const mergedTypeDefs = mergeDocuments(Array.isArray(typeDefs) ? typeDefs : [typeDefs]); | ||
const typeDefsArray = Array.isArray(typeDefs) ? typeDefs : [typeDefs]; | ||
const mergedTypeDefs = mergeDocuments(typeDefsArray); | ||
const schemaDefinition = mergedTypeDefs.definitions.find(isSchemaDefinition); | ||
@@ -48,3 +50,3 @@ this.operationNames = { | ||
if (introspection) { | ||
addIntrospectionResolvers(mappedResolvers, mergedTypeDefs); | ||
addIntrospectionResolvers(mappedResolvers, mergedTypeDefs, { includeObjectTypeExtensions: Boolean(this.federated) }); | ||
} | ||
@@ -84,6 +86,6 @@ this.typeDefs = mergedTypeDefs; | ||
const operationDefinition = operation === 'query' | ||
? this.objectTypes.find(objectType => objectType.name.value === 'Query') | ||
? this.objectTypes.find(objectType => objectType.name.value === this.operationNames.query) | ||
: operation === 'mutation' | ||
? this.objectTypes.find(objectType => objectType.name.value === 'Mutation') | ||
: this.objectTypes.find(objectType => objectType.name.value === 'Subscription'); | ||
? this.objectTypes.find(objectType => objectType.name.value === this.operationNames.mutation) | ||
: this.objectTypes.find(objectType => objectType.name.value === this.operationNames.subscription); | ||
const documentsPair = splitDocument(document, operationDefinition); | ||
@@ -96,5 +98,6 @@ this.processedDocuments.set(document, documentsPair); | ||
const { query, variables } = operation; | ||
const mainDefintion = getMainDefinition(query); | ||
const mainDefinition = getMainDefinition(query); | ||
const [internalQuery, externalQuery] = this.federated ? [query, null] : this.splitDocuments(query); | ||
const isSubscription = mainDefintion.kind === 'OperationDefinition' && mainDefintion.operation === 'subscription'; | ||
const isSubscription = mainDefinition.operation === 'subscription'; | ||
const __typename = this.operationNames[mainDefinition.operation]; | ||
if (isSubscription && internalQuery && externalQuery) { | ||
@@ -130,3 +133,3 @@ throw new Error('Subscriptions cannot be a mix of local and external subscriptions'); | ||
document: internalQuery, | ||
remoteResult, | ||
remoteResult: Object.assign(Object.assign({}, remoteResult), { data: Object.assign(Object.assign({}, remoteResult.data), { __typename }) }), | ||
context: this.getContext(), | ||
@@ -173,3 +176,3 @@ variables, | ||
document: internalQuery, | ||
remoteResult: { data: result }, | ||
remoteResult: { data: Object.assign(Object.assign({}, result), { __typename }) }, | ||
context: Object.assign(Object.assign({}, this.getContext()), { __subscription: true }), | ||
@@ -176,0 +179,0 @@ variables, |
{ | ||
"name": "@grapes-agency/apollo-link-local-schema", | ||
"version": "1.0.0-alpha.12", | ||
"version": "1.0.0-alpha.13", | ||
"description": "Lightweight local schema resolver for @apollo/client", | ||
@@ -5,0 +5,0 @@ "main": "index.cjs.js", |
import type { FragmentMap } from '@apollo/client/utilities'; | ||
import type { ObjectTypeDefinitionNode, FieldNode, ObjectTypeExtensionNode } from 'graphql'; | ||
import type { TypeMap } from './TypeMap'; | ||
interface ProcessResultOptions { | ||
@@ -7,3 +8,3 @@ field: FieldNode; | ||
objectType: ObjectTypeDefinitionNode | ObjectTypeExtensionNode; | ||
typeMap: Map<string, ObjectTypeDefinitionNode | ObjectTypeExtensionNode>; | ||
typeMap: TypeMap; | ||
data: any; | ||
@@ -10,0 +11,0 @@ } |
@@ -7,2 +7,1 @@ export * from './mergeDocuments'; | ||
export * from './splitDocument'; | ||
export * from './addIntrospectionResolvers'; |
@@ -7,3 +7,2 @@ export { getTypeName, isDeepListType, isDirectiveDefinition, isEnumTypeDefinition, isFragmentDefinition, isInputObjectTypeDefinition, isInterfaceTypeDefinition, isListType, isNamedType, isNonNullType, isObjectTypeDefinition, isObjectTypeExtension, isOperationDefinition, isScalarTypeDefinition, isSchemaDefinition, isTypeDefinition, isUnionTypeDefinition } from './node.js'; | ||
export { splitDocument } from './splitDocument.js'; | ||
export { addIntrospectionResolvers } from './addIntrospectionResolvers.js'; | ||
//# sourceMappingURL=index.js.map |
@@ -1,2 +0,3 @@ | ||
import { isObjectTypeDefinition, isObjectTypeExtension, getTypeName, isScalarTypeDefinition } from './node.js'; | ||
import { getTypeName, isScalarTypeDefinition } from './node.js'; | ||
import { TypeMap } from './TypeMap.js'; | ||
import { addTypesnames } from './addTypenames.js'; | ||
@@ -7,4 +8,3 @@ import { isSubscriptionResolver, mapSubscription } from './mapSubscription.js'; | ||
var _a; | ||
const objectTypeDefinitions = typeDefs.definitions.filter(definition => isObjectTypeDefinition(definition) || isObjectTypeExtension(definition)); | ||
const typeMap = new Map(objectTypeDefinitions.map(definition => [definition.name.value, definition])); | ||
const typeMap = new TypeMap(typeDefs); | ||
const mappedResolvers = Object.fromEntries(Object.entries(resolvers).map(([key, fields]) => { | ||
@@ -79,3 +79,3 @@ const typeDefinition = typeMap.get(key); | ||
} | ||
for (const objectTypeDefinition of objectTypeDefinitions) { | ||
for (const objectTypeDefinition of typeMap.values()) { | ||
const objectName = objectTypeDefinition.name.value; | ||
@@ -82,0 +82,0 @@ for (const field of objectTypeDefinition.fields || []) { |
import { ObjectTypeDefinitionNode, ObjectTypeExtensionNode } from 'graphql'; | ||
import { Resolver, SubscriptionResolver } from '../interfaces'; | ||
import type { TypeMap } from './TypeMap'; | ||
export declare const isSubscriptionResolver: (resolver: any) => resolver is SubscriptionResolver<any, any>; | ||
@@ -8,3 +9,3 @@ interface MapSubscriptionOptions<T> { | ||
objectType?: ObjectTypeDefinitionNode | ObjectTypeExtensionNode; | ||
typeMap: Map<string, ObjectTypeDefinitionNode | ObjectTypeExtensionNode>; | ||
typeMap: TypeMap; | ||
} | ||
@@ -11,0 +12,0 @@ export declare const mapSubscription: <C, T>({ fieldName, resolver, objectType, typeMap, }: MapSubscriptionOptions<T>) => Resolver<C & { |
@@ -1,2 +0,2 @@ | ||
import { Observable } from '@apollo/client'; | ||
import { Observable } from '@apollo/client/core'; | ||
import { addTypesnames } from './addTypenames.js'; | ||
@@ -3,0 +3,0 @@ |
import { visit } from 'graphql'; | ||
/* eslint-disable default-case */ | ||
const alwaysAllowFields = ['__schema', '__type', '__resolveType']; | ||
const alwaysAllowFields = ['__schema', '__type', '__resolveType', '__typename']; | ||
const splitDocument = (document, objectType) => { | ||
@@ -11,2 +11,4 @@ if (!objectType) { | ||
const usedFragments = new Set(); | ||
let inFragment = false; | ||
let hasOperationDefinition = false; | ||
const baseVisitor = { | ||
@@ -18,2 +20,3 @@ OperationDefinition: { | ||
} | ||
hasOperationDefinition = true; | ||
}, | ||
@@ -24,18 +27,29 @@ }, | ||
}, | ||
FragmentDefinition(fragmentDefinition) { | ||
if (!usedFragments.has(fragmentDefinition.name.value)) { | ||
return null; | ||
} | ||
FragmentDefinition: { | ||
enter() { | ||
inFragment = true; | ||
}, | ||
leave(fragmentDefinition) { | ||
inFragment = false; | ||
if (!usedFragments.has(fragmentDefinition.name.value)) { | ||
return null; | ||
} | ||
}, | ||
}, | ||
}; | ||
let fieldDepth = -1; | ||
hasOperationDefinition = false; | ||
const internalDocument = visit(document, Object.assign(Object.assign({}, baseVisitor), { Field: { | ||
enter(field) { | ||
if (inFragment) { | ||
return; | ||
} | ||
fieldDepth += 1; | ||
if (fieldDepth > 0) { | ||
return field; | ||
return; | ||
} | ||
if (hasField(field)) { | ||
return field; | ||
return; | ||
} | ||
fieldDepth -= 1; | ||
return null; | ||
@@ -47,12 +61,18 @@ }, | ||
} })); | ||
const hasInteralOperationDefinition = hasOperationDefinition; | ||
hasOperationDefinition = false; | ||
usedFragments.clear(); | ||
const externalDocument = visit(document, Object.assign(Object.assign({}, baseVisitor), { Field: { | ||
enter(field) { | ||
if (inFragment) { | ||
return; | ||
} | ||
fieldDepth += 1; | ||
if (fieldDepth > 0) { | ||
return field; | ||
return; | ||
} | ||
if (!hasField(field)) { | ||
return field; | ||
return; | ||
} | ||
fieldDepth -= 1; | ||
return null; | ||
@@ -64,5 +84,6 @@ }, | ||
} })); | ||
const hasExternalOperationDefinition = hasOperationDefinition; | ||
return [ | ||
internalDocument && internalDocument.definitions.length > 0 ? internalDocument : null, | ||
externalDocument && externalDocument.definitions.length > 0 ? externalDocument : null, | ||
internalDocument && hasInteralOperationDefinition && internalDocument.definitions.length > 0 ? internalDocument : null, | ||
externalDocument && hasExternalOperationDefinition && externalDocument.definitions.length > 0 ? externalDocument : null, | ||
]; | ||
@@ -69,0 +90,0 @@ }; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
187161
64
2065