New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@graphql-codegen/plugin-helpers

Package Overview
Dependencies
Maintainers
4
Versions
5524
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@graphql-codegen/plugin-helpers - npm Package Compare versions

Comparing version

to
6.0.0-alpha-20250305095421-b22d7edea4edf2476d193eccc74d5ff69373a898

144

cjs/federation.js

@@ -6,6 +6,4 @@ "use strict";

exports.removeFederation = removeFederation;
const tslib_1 = require("tslib");
const utils_1 = require("@graphql-tools/utils");
const graphql_1 = require("graphql");
const merge_js_1 = tslib_1.__importDefault(require("lodash/merge.js"));
const index_js_1 = require("./index.js");

@@ -33,4 +31,28 @@ const utils_js_1 = require("./utils.js");

const setFederationMeta = ({ meta, typeName, update, }) => {
meta[typeName] = { ...(meta[typeName] || { hasResolveReference: false, resolvableKeyDirectives: [] }), ...update };
meta[typeName] = {
...(meta[typeName] ||
{
hasResolveReference: false,
resolvableKeyDirectives: [],
referenceSelectionSets: [],
}),
...update,
};
};
const getReferenceSelectionSets = ({ resolvableKeyDirectives, fields, }) => {
const referenceSelectionSets = [];
// @key() @key() - "primary keys" in Federation
// A reference may receive one primary key combination at a time, so they will be combined with `|`
const primaryKeys = resolvableKeyDirectives.map(extractReferenceSelectionSet);
referenceSelectionSets.push([...primaryKeys]);
for (const fieldNode of Object.values(fields)) {
// Look for @requires and see what the service needs and gets
const directives = getDirectivesByName('requires', fieldNode.astNode);
for (const directive of directives) {
const requires = extractReferenceSelectionSet(directive);
referenceSelectionSets.push([requires]);
}
}
return referenceSelectionSets;
};
const federationMeta = {};

@@ -48,2 +70,6 @@ const transformedSchema = (0, utils_1.mapSchema)(schema, {

};
const referenceSelectionSets = getReferenceSelectionSets({
resolvableKeyDirectives: federationDetails.resolvableKeyDirectives,
fields: typeConfig.fields,
});
setFederationMeta({

@@ -55,2 +81,3 @@ meta: federationMeta,

resolvableKeyDirectives: federationDetails.resolvableKeyDirectives,
referenceSelectionSets,
},

@@ -66,2 +93,6 @@ });

const typeConfig = type.toConfig();
const referenceSelectionSets = getReferenceSelectionSets({
resolvableKeyDirectives: federationDetails.resolvableKeyDirectives,
fields: typeConfig.fields,
});
typeConfig.fields = {

@@ -79,2 +110,3 @@ [resolveReferenceFieldName]: {

resolvableKeyDirectives: federationDetails.resolvableKeyDirectives,
referenceSelectionSets,
},

@@ -176,3 +208,2 @@ });

* Transforms a field's ParentType signature in ObjectTypes or InterfaceTypes involved in Federation
* @param data
*/

@@ -183,28 +214,15 @@ transformFieldParentType({ fieldNode, parentType, parentTypeSignature, federationTypeSignature, }) {

}
const parentTypeMeta = this.getMeta()[parentType.name];
if (!parentTypeMeta?.hasResolveReference) {
const result = this.printReferenceSelectionSets({
typeName: parentType.name,
baseFederationType: federationTypeSignature,
});
// When `!result`, it means this is not a Federation entity, so we just return the parentTypeSignature
if (!result) {
return parentTypeSignature;
}
const isObjectFieldWithFederationRef = (0, graphql_1.isObjectType)(parentType) &&
(nodeHasTypeExtension(parentType, this.schema) || fieldNode.name.value === resolveReferenceFieldName);
const isInterfaceFieldWithFederationRef = (0, graphql_1.isInterfaceType)(parentType) && fieldNode.name.value === resolveReferenceFieldName;
if (!isObjectFieldWithFederationRef && !isInterfaceFieldWithFederationRef) {
const isEntityResolveReferenceField = ((0, graphql_1.isObjectType)(parentType) || (0, graphql_1.isInterfaceType)(parentType)) && fieldNode.name.value === resolveReferenceFieldName;
if (!isEntityResolveReferenceField) {
return parentTypeSignature;
}
const outputs = [`{ __typename: '${parentType.name}' } &`];
// Look for @requires and see what the service needs and gets
const requires = getDirectivesByName('requires', fieldNode).map(this.extractFieldSet);
const requiredFields = this.translateFieldSet((0, merge_js_1.default)({}, ...requires), federationTypeSignature);
// @key() @key() - "primary keys" in Federation
const primaryKeys = parentTypeMeta.resolvableKeyDirectives.map(def => {
const fields = this.extractFieldSet(def);
return this.translateFieldSet(fields, federationTypeSignature);
});
const [open, close] = primaryKeys.length > 1 ? ['(', ')'] : ['', ''];
outputs.push([open, primaryKeys.join(' | '), close].join(''));
// include required fields
if (requires.length) {
outputs.push(`& ${requiredFields}`);
}
return outputs.join(' ');
return result;
}

@@ -234,27 +252,21 @@ addFederationTypeGenericIfApplicable({ genericTypes, typeName, federationTypesType, }) {

}
translateFieldSet(fields, parentTypeRef) {
return `GraphQLRecursivePick<${parentTypeRef}, ${JSON.stringify(fields)}>`;
printReferenceSelectionSet({ typeName, referenceSelectionSet, }) {
return `GraphQLRecursivePick<${typeName}, ${JSON.stringify(referenceSelectionSet)}>`;
}
extractFieldSet(directive) {
const arg = directive.arguments.find(arg => arg.name.value === 'fields');
const { value } = arg.value;
return (0, index_js_1.oldVisit)((0, graphql_1.parse)(`{${value}}`), {
leave: {
SelectionSet(node) {
return node.selections.reduce((accum, field) => {
accum[field.name] = field.selection;
return accum;
}, {});
},
Field(node) {
return {
name: node.name.value,
selection: node.selectionSet || true,
};
},
Document(node) {
return node.definitions.find((def) => def.kind === 'OperationDefinition' && def.operation === 'query').selectionSet;
},
},
});
printReferenceSelectionSets({ typeName, baseFederationType, }) {
const federationMeta = this.getMeta()[typeName];
if (!federationMeta?.hasResolveReference) {
return false;
}
return `\n ( { __typename: '${typeName}' }\n & ${federationMeta.referenceSelectionSets
.map(referenceSelectionSetArray => {
const result = referenceSelectionSetArray.map(referenceSelectionSet => {
return this.printReferenceSelectionSet({
referenceSelectionSet,
typeName: baseFederationType,
});
});
return result.length > 1 ? `( ${result.join(' | ')} )` : result.join(' | ');
})
.join('\n & ')} )`;
}

@@ -268,3 +280,3 @@ createMapOfProvides() {

const provides = getDirectivesByName('provides', field.astNode)
.map(this.extractFieldSet)
.map(extractReferenceSelectionSet)
.reduce((prev, curr) => [...prev, ...Object.keys(curr)], []);

@@ -324,10 +336,24 @@ const ofType = (0, utils_js_1.getBaseType)(field.type);

}
/**
* Checks if the Object Type extends a federated type from a remote schema.
* Based on if any of its fields contain the `@external` directive
* @param node Type
*/
function nodeHasTypeExtension(node, schema) {
const definition = (0, graphql_1.isObjectType)(node) ? node.astNode || (0, utils_1.astFromObjectType)(node, schema) : node;
return definition.fields?.some(field => getDirectivesByName('external', field).length);
function extractReferenceSelectionSet(directive) {
const arg = directive.arguments.find(arg => arg.name.value === 'fields');
const { value } = arg.value;
return (0, index_js_1.oldVisit)((0, graphql_1.parse)(`{${value}}`), {
leave: {
SelectionSet(node) {
return node.selections.reduce((accum, field) => {
accum[field.name] = field.selection;
return accum;
}, {});
},
Field(node) {
return {
name: node.name.value,
selection: node.selectionSet || true,
};
},
Document(node) {
return node.definitions.find((def) => def.kind === 'OperationDefinition' && def.operation === 'query').selectionSet;
},
},
});
}
import { astFromInterfaceType, astFromObjectType, getRootTypeNames, MapperKind, mapSchema } from '@graphql-tools/utils';
import { GraphQLInterfaceType, GraphQLObjectType, isInterfaceType, isObjectType, parse, } from 'graphql';
import merge from 'lodash/merge.js';
import { oldVisit } from './index.js';

@@ -26,4 +25,28 @@ import { getBaseType } from './utils.js';

const setFederationMeta = ({ meta, typeName, update, }) => {
meta[typeName] = { ...(meta[typeName] || { hasResolveReference: false, resolvableKeyDirectives: [] }), ...update };
meta[typeName] = {
...(meta[typeName] ||
{
hasResolveReference: false,
resolvableKeyDirectives: [],
referenceSelectionSets: [],
}),
...update,
};
};
const getReferenceSelectionSets = ({ resolvableKeyDirectives, fields, }) => {
const referenceSelectionSets = [];
// @key() @key() - "primary keys" in Federation
// A reference may receive one primary key combination at a time, so they will be combined with `|`
const primaryKeys = resolvableKeyDirectives.map(extractReferenceSelectionSet);
referenceSelectionSets.push([...primaryKeys]);
for (const fieldNode of Object.values(fields)) {
// Look for @requires and see what the service needs and gets
const directives = getDirectivesByName('requires', fieldNode.astNode);
for (const directive of directives) {
const requires = extractReferenceSelectionSet(directive);
referenceSelectionSets.push([requires]);
}
}
return referenceSelectionSets;
};
const federationMeta = {};

@@ -41,2 +64,6 @@ const transformedSchema = mapSchema(schema, {

};
const referenceSelectionSets = getReferenceSelectionSets({
resolvableKeyDirectives: federationDetails.resolvableKeyDirectives,
fields: typeConfig.fields,
});
setFederationMeta({

@@ -48,2 +75,3 @@ meta: federationMeta,

resolvableKeyDirectives: federationDetails.resolvableKeyDirectives,
referenceSelectionSets,
},

@@ -59,2 +87,6 @@ });

const typeConfig = type.toConfig();
const referenceSelectionSets = getReferenceSelectionSets({
resolvableKeyDirectives: federationDetails.resolvableKeyDirectives,
fields: typeConfig.fields,
});
typeConfig.fields = {

@@ -72,2 +104,3 @@ [resolveReferenceFieldName]: {

resolvableKeyDirectives: federationDetails.resolvableKeyDirectives,
referenceSelectionSets,
},

@@ -169,3 +202,2 @@ });

* Transforms a field's ParentType signature in ObjectTypes or InterfaceTypes involved in Federation
* @param data
*/

@@ -176,28 +208,15 @@ transformFieldParentType({ fieldNode, parentType, parentTypeSignature, federationTypeSignature, }) {

}
const parentTypeMeta = this.getMeta()[parentType.name];
if (!parentTypeMeta?.hasResolveReference) {
const result = this.printReferenceSelectionSets({
typeName: parentType.name,
baseFederationType: federationTypeSignature,
});
// When `!result`, it means this is not a Federation entity, so we just return the parentTypeSignature
if (!result) {
return parentTypeSignature;
}
const isObjectFieldWithFederationRef = isObjectType(parentType) &&
(nodeHasTypeExtension(parentType, this.schema) || fieldNode.name.value === resolveReferenceFieldName);
const isInterfaceFieldWithFederationRef = isInterfaceType(parentType) && fieldNode.name.value === resolveReferenceFieldName;
if (!isObjectFieldWithFederationRef && !isInterfaceFieldWithFederationRef) {
const isEntityResolveReferenceField = (isObjectType(parentType) || isInterfaceType(parentType)) && fieldNode.name.value === resolveReferenceFieldName;
if (!isEntityResolveReferenceField) {
return parentTypeSignature;
}
const outputs = [`{ __typename: '${parentType.name}' } &`];
// Look for @requires and see what the service needs and gets
const requires = getDirectivesByName('requires', fieldNode).map(this.extractFieldSet);
const requiredFields = this.translateFieldSet(merge({}, ...requires), federationTypeSignature);
// @key() @key() - "primary keys" in Federation
const primaryKeys = parentTypeMeta.resolvableKeyDirectives.map(def => {
const fields = this.extractFieldSet(def);
return this.translateFieldSet(fields, federationTypeSignature);
});
const [open, close] = primaryKeys.length > 1 ? ['(', ')'] : ['', ''];
outputs.push([open, primaryKeys.join(' | '), close].join(''));
// include required fields
if (requires.length) {
outputs.push(`& ${requiredFields}`);
}
return outputs.join(' ');
return result;
}

@@ -227,27 +246,21 @@ addFederationTypeGenericIfApplicable({ genericTypes, typeName, federationTypesType, }) {

}
translateFieldSet(fields, parentTypeRef) {
return `GraphQLRecursivePick<${parentTypeRef}, ${JSON.stringify(fields)}>`;
printReferenceSelectionSet({ typeName, referenceSelectionSet, }) {
return `GraphQLRecursivePick<${typeName}, ${JSON.stringify(referenceSelectionSet)}>`;
}
extractFieldSet(directive) {
const arg = directive.arguments.find(arg => arg.name.value === 'fields');
const { value } = arg.value;
return oldVisit(parse(`{${value}}`), {
leave: {
SelectionSet(node) {
return node.selections.reduce((accum, field) => {
accum[field.name] = field.selection;
return accum;
}, {});
},
Field(node) {
return {
name: node.name.value,
selection: node.selectionSet || true,
};
},
Document(node) {
return node.definitions.find((def) => def.kind === 'OperationDefinition' && def.operation === 'query').selectionSet;
},
},
});
printReferenceSelectionSets({ typeName, baseFederationType, }) {
const federationMeta = this.getMeta()[typeName];
if (!federationMeta?.hasResolveReference) {
return false;
}
return `\n ( { __typename: '${typeName}' }\n & ${federationMeta.referenceSelectionSets
.map(referenceSelectionSetArray => {
const result = referenceSelectionSetArray.map(referenceSelectionSet => {
return this.printReferenceSelectionSet({
referenceSelectionSet,
typeName: baseFederationType,
});
});
return result.length > 1 ? `( ${result.join(' | ')} )` : result.join(' | ');
})
.join('\n & ')} )`;
}

@@ -261,3 +274,3 @@ createMapOfProvides() {

const provides = getDirectivesByName('provides', field.astNode)
.map(this.extractFieldSet)
.map(extractReferenceSelectionSet)
.reduce((prev, curr) => [...prev, ...Object.keys(curr)], []);

@@ -316,10 +329,24 @@ const ofType = getBaseType(field.type);

}
/**
* Checks if the Object Type extends a federated type from a remote schema.
* Based on if any of its fields contain the `@external` directive
* @param node Type
*/
function nodeHasTypeExtension(node, schema) {
const definition = isObjectType(node) ? node.astNode || astFromObjectType(node, schema) : node;
return definition.fields?.some(field => getDirectivesByName('external', field).length);
function extractReferenceSelectionSet(directive) {
const arg = directive.arguments.find(arg => arg.name.value === 'fields');
const { value } = arg.value;
return oldVisit(parse(`{${value}}`), {
leave: {
SelectionSet(node) {
return node.selections.reduce((accum, field) => {
accum[field.name] = field.selection;
return accum;
}, {});
},
Field(node) {
return {
name: node.name.value,
selection: node.selectionSet || true,
};
},
Document(node) {
return node.definitions.find((def) => def.kind === 'OperationDefinition' && def.operation === 'query').selectionSet;
},
},
});
}
{
"name": "@graphql-codegen/plugin-helpers",
"version": "6.0.0-alpha-20250219094450-c0f73ba2266dfdde71725fb9a05c6286b0515874",
"version": "6.0.0-alpha-20250305095421-b22d7edea4edf2476d193eccc74d5ff69373a898",
"description": "GraphQL Code Generator common utils and types",

@@ -5,0 +5,0 @@ "peerDependencies": {

@@ -6,5 +6,26 @@ import { DirectiveNode, FieldDefinitionNode, GraphQLNamedType, GraphQLSchema } from 'graphql';

export declare const federationSpec: import("graphql").DocumentNode;
/**
* ReferenceSelectionSet
* @description Each is a collection of fields that are available in a reference payload (originated from the Router)
* @example
* - resolvable fields marked with `@key`
* - fields declared in `@provides`
*/
interface ReferenceSelectionSet {
name: string;
selection: boolean | ReferenceSelectionSet[];
}
interface TypeMeta {
hasResolveReference: boolean;
resolvableKeyDirectives: readonly DirectiveNode[];
/**
* referenceSelectionSets
* @description Each element can be `ReferenceSelectionSet[]`.
* Elements at the root level are combined with `&` and nested elements are combined with `|`.
*
* @example:
* - [[A, B], [C], [D]] -> (A | B) & C & D
* - [[A, B], [C, D], [E]] -> (A | B) & (C | D) & E
*/
referenceSelectionSets: ReferenceSelectionSet[][];
}

@@ -72,3 +93,2 @@ export type FederationMeta = {

* Transforms a field's ParentType signature in ObjectTypes or InterfaceTypes involved in Federation
* @param data
*/

@@ -90,6 +110,12 @@ transformFieldParentType({ fieldNode, parentType, parentTypeSignature, federationTypeSignature, }: {

private hasProvides;
private translateFieldSet;
private extractFieldSet;
printReferenceSelectionSet({ typeName, referenceSelectionSet, }: {
typeName: string;
referenceSelectionSet: ReferenceSelectionSet;
}): string;
printReferenceSelectionSets({ typeName, baseFederationType, }: {
typeName: string;
baseFederationType: string;
}): string | false;
private createMapOfProvides;
}
export {};

Sorry, the diff of this file is not supported yet