From 78567aed2e672e9a1ae93029b94aee13cce8c6f2 Mon Sep 17 00:00:00 2001 From: Malte Wildt Date: Fri, 19 Mar 2021 14:56:53 +0100 Subject: [PATCH 1/2] Add Support for Interface types in SDL-Transformation and generade additional @extends directives in extending Interfaces and Type --- .gitignore | 4 ++++ src/transform-federation.ts | 4 ++++ src/transform-sdl.ts | 40 +++++++++++++++++++++++++++++++++++-- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 934db85..8251d56 100644 --- a/.gitignore +++ b/.gitignore @@ -90,3 +90,7 @@ typings/ .dynamodb/ dist/ + +# Intellij IDEA Configuration +.idea +*.iml diff --git a/src/transform-federation.ts b/src/transform-federation.ts index c0f7d95..7e63f56 100644 --- a/src/transform-federation.ts +++ b/src/transform-federation.ts @@ -58,6 +58,10 @@ export function transformSchemaFederation( const entityTypes = Object.fromEntries( Object.entries(federationConfig) .filter(([, { keyFields }]) => keyFields && keyFields.length) + .filter(([objectName]) => { + const type = schemaWithQueryType.getType(objectName); + return !isInterfaceType(type); + }) .map(([objectName]) => { const type = schemaWithQueryType.getType(objectName); if (!isObjectType(type)) { diff --git a/src/transform-sdl.ts b/src/transform-sdl.ts index 21f595e..8ee1125 100644 --- a/src/transform-sdl.ts +++ b/src/transform-sdl.ts @@ -1,5 +1,5 @@ import { - FieldDefinitionNode, + FieldDefinitionNode, InterfaceTypeDefinitionNode, ObjectTypeDefinitionNode, ObjectTypeExtensionNode, parse, @@ -13,6 +13,7 @@ import { FederationFieldsConfig, FederationObjectConfig, } from './transform-federation'; +import { InterfaceTypeExtensionNode } from 'graphql'; function createDirectiveWithFields(directiveName: string, fields: string) { return createDirectiveNode(directiveName, { @@ -86,10 +87,45 @@ export function addFederationAnnotations( ) : []; + if (extend) { + newDirectives.push(createDirectiveNode('extends')) + } + + return { + ...node, + directives: [...(node.directives || []), ...newDirectives], + kind: (extend ? 'ObjectTypeExtension' : node.kind) + }; + } + }, + leave() { + currentObjectName = undefined; + }, + }, + InterfaceTypeDefinition: { + enter( + node: InterfaceTypeDefinitionNode, + ): InterfaceTypeDefinitionNode | InterfaceTypeExtensionNode | undefined { + currentObjectName = node.name.value; + if (objectTypesTodo.has(currentObjectName)) { + objectTypesTodo.delete(currentObjectName); + + const { keyFields, extend } = federationConfig[currentObjectName]; + + const newDirectives = keyFields + ? keyFields.map((keyField) => + createDirectiveWithFields('key', keyField), + ) + : []; + + if (extend) { + newDirectives.push(createDirectiveNode('extends')) + } + return { ...node, directives: [...(node.directives || []), ...newDirectives], - kind: extend ? 'ObjectTypeExtension' : node.kind, + kind: (extend ? 'InterfaceTypeExtension' : node.kind) }; } }, From d648de41f42cd5a3ba25be49fd23d35a0dd05af1 Mon Sep 17 00:00:00 2001 From: Malte Wildt Date: Mon, 22 Mar 2021 10:11:01 +0100 Subject: [PATCH 2/2] push dist --- .gitignore | 2 - dist/ast-builders.d.ts | 6 ++ dist/ast-builders.js | 36 +++++++ dist/ast-builders.js.map | 1 + dist/transform-federation.d.ts | 20 ++++ dist/transform-federation.js | 74 +++++++++++++ dist/transform-federation.js.map | 1 + dist/transform-federation.spec.d.ts | 1 + dist/transform-federation.spec.js | 147 ++++++++++++++++++++++++++ dist/transform-federation.spec.js.map | 1 + dist/transform-sdl.d.ts | 2 + dist/transform-sdl.js | 146 +++++++++++++++++++++++++ dist/transform-sdl.js.map | 1 + dist/transform-sdl.spec.d.ts | 1 + dist/transform-sdl.spec.js | 73 +++++++++++++ dist/transform-sdl.spec.js.map | 1 + 16 files changed, 511 insertions(+), 2 deletions(-) create mode 100644 dist/ast-builders.d.ts create mode 100644 dist/ast-builders.js create mode 100644 dist/ast-builders.js.map create mode 100644 dist/transform-federation.d.ts create mode 100644 dist/transform-federation.js create mode 100644 dist/transform-federation.js.map create mode 100644 dist/transform-federation.spec.d.ts create mode 100644 dist/transform-federation.spec.js create mode 100644 dist/transform-federation.spec.js.map create mode 100644 dist/transform-sdl.d.ts create mode 100644 dist/transform-sdl.js create mode 100644 dist/transform-sdl.js.map create mode 100644 dist/transform-sdl.spec.d.ts create mode 100644 dist/transform-sdl.spec.js create mode 100644 dist/transform-sdl.spec.js.map diff --git a/.gitignore b/.gitignore index 8251d56..22fd847 100644 --- a/.gitignore +++ b/.gitignore @@ -89,8 +89,6 @@ typings/ # DynamoDB Local files .dynamodb/ -dist/ - # Intellij IDEA Configuration .idea *.iml diff --git a/dist/ast-builders.d.ts b/dist/ast-builders.d.ts new file mode 100644 index 0000000..031e767 --- /dev/null +++ b/dist/ast-builders.d.ts @@ -0,0 +1,6 @@ +import { NameNode, StringValueNode, DirectiveNode, ValueNode } from 'graphql/language'; +export declare function createNameNode(value: string): NameNode; +export declare function createStringValueNode(value: string, block?: boolean): StringValueNode; +export declare function createDirectiveNode(name: string, directiveArguments?: { + [argumentName: string]: ValueNode; +}): DirectiveNode; diff --git a/dist/ast-builders.js b/dist/ast-builders.js new file mode 100644 index 0000000..9f0f727 --- /dev/null +++ b/dist/ast-builders.js @@ -0,0 +1,36 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.createDirectiveNode = exports.createStringValueNode = exports.createNameNode = void 0; +function createNameNode(value) { + return { + kind: 'Name', + value: value, + }; +} +exports.createNameNode = createNameNode; +function createStringValueNode(value, block) { + if (block === void 0) { block = false; } + return { + kind: 'StringValue', + value: value, + block: block, + }; +} +exports.createStringValueNode = createStringValueNode; +function createDirectiveNode(name, directiveArguments) { + if (directiveArguments === void 0) { directiveArguments = {}; } + return { + kind: 'Directive', + name: createNameNode(name), + arguments: Object.entries(directiveArguments).map(function (_a) { + var argumentName = _a[0], value = _a[1]; + return ({ + kind: 'Argument', + name: createNameNode(argumentName), + value: value, + }); + }), + }; +} +exports.createDirectiveNode = createDirectiveNode; +//# sourceMappingURL=ast-builders.js.map \ No newline at end of file diff --git a/dist/ast-builders.js.map b/dist/ast-builders.js.map new file mode 100644 index 0000000..3e7b8a3 --- /dev/null +++ b/dist/ast-builders.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ast-builders.js","sourceRoot":"","sources":["../src/ast-builders.ts"],"names":[],"mappings":";;;AAOA,SAAgB,cAAc,CAAC,KAAa;IAC1C,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,KAAK,OAAA;KACN,CAAC;AACJ,CAAC;AALD,wCAKC;AAED,SAAgB,qBAAqB,CACnC,KAAa,EACb,KAAa;IAAb,sBAAA,EAAA,aAAa;IAEb,OAAO;QACL,IAAI,EAAE,aAAa;QACnB,KAAK,OAAA;QACL,KAAK,OAAA;KACN,CAAC;AACJ,CAAC;AATD,sDASC;AAED,SAAgB,mBAAmB,CACjC,IAAY,EACZ,kBAA8D;IAA9D,mCAAA,EAAA,uBAA8D;IAE9D,OAAO;QACL,IAAI,EAAE,WAAW;QACjB,IAAI,EAAE,cAAc,CAAC,IAAI,CAAC;QAC1B,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAC/C,UAAC,EAAqB;gBAApB,YAAY,QAAA,EAAE,KAAK,QAAA;YAAM,OAAA,CAAC;gBAC1B,IAAI,EAAE,UAAU;gBAChB,IAAI,EAAE,cAAc,CAAC,YAAY,CAAC;gBAClC,KAAK,OAAA;aACN,CAAC;QAJyB,CAIzB,CACH;KACF,CAAC;AACJ,CAAC;AAfD,kDAeC"} \ No newline at end of file diff --git a/dist/transform-federation.d.ts b/dist/transform-federation.d.ts new file mode 100644 index 0000000..f931e84 --- /dev/null +++ b/dist/transform-federation.d.ts @@ -0,0 +1,20 @@ +import { GraphQLSchema } from 'graphql'; +import { GraphQLReferenceResolver } from '@apollo/federation/dist/types'; +export interface FederationFieldConfig { + external?: boolean; + provides?: string; + requires?: string; +} +export interface FederationFieldsConfig { + [fieldName: string]: FederationFieldConfig; +} +export interface FederationObjectConfig { + keyFields?: string[]; + extend?: boolean; + resolveReference?: GraphQLReferenceResolver; + fields?: FederationFieldsConfig; +} +export interface FederationConfig { + [objectName: string]: FederationObjectConfig; +} +export declare function transformSchemaFederation(schema: GraphQLSchema, federationConfig: FederationConfig): GraphQLSchema; diff --git a/dist/transform-federation.js b/dist/transform-federation.js new file mode 100644 index 0000000..c75bd55 --- /dev/null +++ b/dist/transform-federation.js @@ -0,0 +1,74 @@ +"use strict"; +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.transformSchemaFederation = void 0; +var apollo_graphql_1 = require("apollo-graphql"); +var graphql_1 = require("graphql"); +var transform_sdl_1 = require("./transform-sdl"); +var types_1 = require("@apollo/federation/dist/types"); +function transformSchemaFederation(schema, federationConfig) { + var schemaWithFederationDirectives = transform_sdl_1.addFederationAnnotations(graphql_1.printSchema(schema), federationConfig); + var schemaWithQueryType = !schema.getQueryType() + ? new graphql_1.GraphQLSchema(__assign(__assign({}, schema.toConfig()), { query: new graphql_1.GraphQLObjectType({ + name: 'Query', + fields: {}, + }) })) + : schema; + var entityTypes = Object.fromEntries(Object.entries(federationConfig) + .filter(function (_a) { + var keyFields = _a[1].keyFields; + return keyFields && keyFields.length; + }) + .filter(function (_a) { + var objectName = _a[0]; + var type = schemaWithQueryType.getType(objectName); + return !graphql_1.isInterfaceType(type); + }) + .map(function (_a) { + var objectName = _a[0]; + var type = schemaWithQueryType.getType(objectName); + if (!graphql_1.isObjectType(type)) { + throw new Error("Type \"" + objectName + "\" is not an object type and can't have a key directive"); + } + return [objectName, type]; + })); + var hasEntities = !!Object.keys(entityTypes).length; + var schemaWithFederationQueryType = apollo_graphql_1.transformSchema(schemaWithQueryType, function (type) { + // Add `_entities` and `_service` fields to query root type + if (graphql_1.isObjectType(type) && type === schemaWithQueryType.getQueryType()) { + var config = type.toConfig(); + return new graphql_1.GraphQLObjectType(__assign(__assign({}, config), { fields: __assign(__assign(__assign({}, config.fields), (hasEntities && { _entities: types_1.entitiesField })), { _service: __assign(__assign({}, types_1.serviceField), { resolve: function () { return ({ sdl: schemaWithFederationDirectives }); } }) }) })); + } + return undefined; + }); + var schemaWithUnionType = apollo_graphql_1.transformSchema(schemaWithFederationQueryType, function (type) { + if (graphql_1.isUnionType(type) && type.name === types_1.EntityType.name) { + return new graphql_1.GraphQLUnionType(__assign(__assign({}, types_1.EntityType.toConfig()), { types: Object.values(entityTypes) })); + } + return undefined; + }); + // Not using transformSchema since it will remove resolveReference + Object.entries(federationConfig).forEach(function (_a) { + var objectName = _a[0], currentFederationConfig = _a[1]; + if (currentFederationConfig.resolveReference) { + var type = schemaWithUnionType.getType(objectName); + if (!graphql_1.isObjectType(type)) { + throw new Error("Type \"" + objectName + "\" is not an object type and can't have a resolveReference function"); + } + type.resolveReference = currentFederationConfig.resolveReference; + } + }); + return schemaWithUnionType; +} +exports.transformSchemaFederation = transformSchemaFederation; +//# sourceMappingURL=transform-federation.js.map \ No newline at end of file diff --git a/dist/transform-federation.js.map b/dist/transform-federation.js.map new file mode 100644 index 0000000..4ec9a64 --- /dev/null +++ b/dist/transform-federation.js.map @@ -0,0 +1 @@ +{"version":3,"file":"transform-federation.js","sourceRoot":"","sources":["../src/transform-federation.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/transform-federation.spec.d.ts b/dist/transform-federation.spec.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/dist/transform-federation.spec.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/transform-federation.spec.js b/dist/transform-federation.spec.js new file mode 100644 index 0000000..6b65b93 --- /dev/null +++ b/dist/transform-federation.spec.js @@ -0,0 +1,147 @@ +"use strict"; +var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) { + if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } + return cooked; +}; +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var graphql_tools_1 = require("graphql-tools"); +var transform_federation_1 = require("./transform-federation"); +var execute_1 = require("graphql/execution/execute"); +var language_1 = require("graphql/language"); +var dedent = require("dedent"); +describe('Transform Federation', function () { + it('should add a _service field', function () { return __awaiter(void 0, void 0, void 0, function () { + var executableSchema, federationSchema, _a; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + executableSchema = graphql_tools_1.makeExecutableSchema({ + typeDefs: "\n type Product {\n id: ID!\n }\n ", + resolvers: {}, + }); + federationSchema = transform_federation_1.transformSchemaFederation(executableSchema, { + Product: { + keyFields: ['id'], + }, + }); + _a = expect; + return [4 /*yield*/, execute_1.execute({ + schema: federationSchema, + document: language_1.parse("\n query {\n _service {\n sdl\n }\n }\n "), + })]; + case 1: + _a.apply(void 0, [_b.sent()]).toEqual({ + data: { + _service: { + sdl: dedent(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n type Product @key(fields: \"id\") {\n id: ID!\n }\n\n "], ["\n type Product @key(fields: \"id\") {\n id: ID!\n }\\n\n "]))), + }, + }, + }); + return [2 /*return*/]; + } + }); + }); }); + it('should resolve references', function () { return __awaiter(void 0, void 0, void 0, function () { + var executableSchema, federationSchema, _a; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + executableSchema = graphql_tools_1.makeExecutableSchema({ + typeDefs: "\n type Product {\n id: ID!\n name: String!\n }\n ", + resolvers: {}, + }); + federationSchema = transform_federation_1.transformSchemaFederation(executableSchema, { + Product: { + keyFields: ['id'], + extend: true, + resolveReference: function (reference) { + return __assign(__assign({}, reference), { name: 'mock name' }); + }, + }, + }); + _a = expect; + return [4 /*yield*/, execute_1.execute({ + schema: federationSchema, + document: language_1.parse("\n query{\n _entities (representations: {\n __typename:\"Product\"\n id: \"1\"\n }) {\n __typename\n ...on Product {\n id\n name\n }\n }\n } \n "), + })]; + case 1: + _a.apply(void 0, [_b.sent()]).toEqual({ + data: { + _entities: [ + { + __typename: 'Product', + id: '1', + name: 'mock name', + }, + ], + }, + }); + return [2 /*return*/]; + } + }); + }); }); + it('should throw and error when adding resolveReference on a scalar', function () { + var executableSchema = graphql_tools_1.makeExecutableSchema({ + typeDefs: 'scalar MockScalar', + resolvers: {}, + }); + expect(function () { + return transform_federation_1.transformSchemaFederation(executableSchema, { + MockScalar: { + resolveReference: function () { + return {}; + }, + }, + }); + }).toThrow('Type "MockScalar" is not an object type and can\'t have a resolveReference function'); + }); +}); +var templateObject_1; +//# sourceMappingURL=transform-federation.spec.js.map \ No newline at end of file diff --git a/dist/transform-federation.spec.js.map b/dist/transform-federation.spec.js.map new file mode 100644 index 0000000..9ed0486 --- /dev/null +++ b/dist/transform-federation.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"transform-federation.spec.js","sourceRoot":"","sources":["../src/transform-federation.spec.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAAqD;AACrD,+DAAmE;AACnE,qDAAoD;AACpD,6CAAyC;AACzC,+BAAkC;AAElC,QAAQ,CAAC,sBAAsB,EAAE;IAC/B,EAAE,CAAC,6BAA6B,EAAE;;;;;oBAC1B,gBAAgB,GAAG,oCAAoB,CAAC;wBAC5C,QAAQ,EAAE,gEAIT;wBACD,SAAS,EAAE,EAAE;qBACd,CAAC,CAAC;oBAEG,gBAAgB,GAAG,gDAAyB,CAAC,gBAAgB,EAAE;wBACnE,OAAO,EAAE;4BACP,SAAS,EAAE,CAAC,IAAI,CAAC;yBAClB;qBACF,CAAC,CAAC;oBAEH,KAAA,MAAM,CAAA;oBACJ,qBAAM,iBAAO,CAAC;4BACZ,MAAM,EAAE,gBAAgB;4BACxB,QAAQ,EAAE,gBAAK,CAAC,sGAMf,CAAC;yBACH,CAAC,EAAA;;oBAVJ,kBACE,SASE,EACH,CAAC,OAAO,CAAC;wBACR,IAAI,EAAE;4BACJ,QAAQ,EAAE;gCACR,GAAG,EAAE,MAAM,0KAAA,wGAIV,IAAA;6BACF;yBACF;qBACF,CAAC,CAAC;;;;SACJ,CAAC,CAAC;IACH,EAAE,CAAC,2BAA2B,EAAE;;;;;oBACxB,gBAAgB,GAAG,oCAAoB,CAAC;wBAC5C,QAAQ,EAAE,yEAKT;wBACD,SAAS,EAAE,EAAE;qBACd,CAAC,CAAC;oBAEG,gBAAgB,GAAG,gDAAyB,CAAC,gBAAgB,EAAE;wBACnE,OAAO,EAAE;4BACP,SAAS,EAAE,CAAC,IAAI,CAAC;4BACjB,MAAM,EAAE,IAAI;4BACZ,gBAAgB,YAAC,SAAS;gCACxB,6BACK,SAAS,KACZ,IAAI,EAAE,WAAW,IACjB;4BACJ,CAAC;yBACF;qBACF,CAAC,CAAC;oBAEH,KAAA,MAAM,CAAA;oBACJ,qBAAM,iBAAO,CAAC;4BACZ,MAAM,EAAE,gBAAgB;4BACxB,QAAQ,EAAE,gBAAK,CAAC,2SAaf,CAAC;yBACH,CAAC,EAAA;;oBAjBJ,kBACE,SAgBE,EACH,CAAC,OAAO,CAAC;wBACR,IAAI,EAAE;4BACJ,SAAS,EAAE;gCACT;oCACE,UAAU,EAAE,SAAS;oCACrB,EAAE,EAAE,GAAG;oCACP,IAAI,EAAE,WAAW;iCAClB;6BACF;yBACF;qBACF,CAAC,CAAC;;;;SACJ,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE;QACpE,IAAM,gBAAgB,GAAG,oCAAoB,CAAC;YAC5C,QAAQ,EAAE,mBAAmB;YAC7B,SAAS,EAAE,EAAE;SACd,CAAC,CAAC;QAEH,MAAM,CAAC;YACL,OAAA,gDAAyB,CAAC,gBAAgB,EAAE;gBAC1C,UAAU,EAAE;oBACV,gBAAgB;wBACd,OAAO,EAAE,CAAC;oBACZ,CAAC;iBACF;aACF,CAAC;QANF,CAME,CACH,CAAC,OAAO,CACP,qFAAqF,CACtF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/transform-sdl.d.ts b/dist/transform-sdl.d.ts new file mode 100644 index 0000000..c5f59ba --- /dev/null +++ b/dist/transform-sdl.d.ts @@ -0,0 +1,2 @@ +import { FederationConfig } from './transform-federation'; +export declare function addFederationAnnotations(schema: string, federationConfig: FederationConfig): string; diff --git a/dist/transform-sdl.js b/dist/transform-sdl.js new file mode 100644 index 0000000..93e7ad9 --- /dev/null +++ b/dist/transform-sdl.js @@ -0,0 +1,146 @@ +"use strict"; +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +var __spreadArrays = (this && this.__spreadArrays) || function () { + for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; + for (var r = Array(s), k = 0, i = 0; i < il; i++) + for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) + r[k] = a[j]; + return r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.addFederationAnnotations = void 0; +var language_1 = require("graphql/language"); +var ast_builders_1 = require("./ast-builders"); +function createDirectiveWithFields(directiveName, fields) { + return ast_builders_1.createDirectiveNode(directiveName, { + fields: ast_builders_1.createStringValueNode(fields), + }); +} +function isFieldConfigToDo(_a) { + var external = _a.external, provides = _a.provides, requires = _a.requires; + return Boolean(external || provides || requires); +} +function filterFieldsConfigToDo(fieldsConfig) { + return Object.fromEntries(Object.entries(fieldsConfig).filter(function (_a) { + var fieldConfig = _a[1]; + return isFieldConfigToDo(fieldConfig); + })); +} +function isObjectConfigToDo(_a) { + var extend = _a.extend, keyFields = _a.keyFields; + return Boolean((keyFields && keyFields.length) || extend); +} +function addFederationAnnotations(schema, federationConfig) { + var ast = language_1.parse(schema); + var objectTypesTodo = new Set(Object.entries(federationConfig) + .filter(function (_a) { + var config = _a[1]; + return isObjectConfigToDo(config); + }) + .map(function (_a) { + var objectName = _a[0]; + return objectName; + })); + var fieldTypesTodo = Object.fromEntries(Object.entries(federationConfig) + .flatMap(function (_a) { + var objectName = _a[0], fields = _a[1].fields; + return fields ? [[objectName, filterFieldsConfigToDo(fields)]] : []; + }) + .filter(function (_a) { + var fieldsConfig = _a[1]; + return Object.keys(fieldsConfig).length; + })); + var currentObjectName = undefined; + var withDirectives = language_1.visit(ast, { + ObjectTypeDefinition: { + enter: function (node) { + currentObjectName = node.name.value; + if (objectTypesTodo.has(currentObjectName)) { + objectTypesTodo.delete(currentObjectName); + var _a = federationConfig[currentObjectName], keyFields = _a.keyFields, extend = _a.extend; + var newDirectives = keyFields + ? keyFields.map(function (keyField) { + return createDirectiveWithFields('key', keyField); + }) + : []; + // if (extend) { + // newDirectives.push(createDirectiveNode('extends')) + // } + return __assign(__assign({}, node), { directives: __spreadArrays((node.directives || []), newDirectives), kind: (extend ? 'ObjectTypeExtension' : node.kind) }); + } + }, + leave: function () { + currentObjectName = undefined; + }, + }, + InterfaceTypeDefinition: { + enter: function (node) { + currentObjectName = node.name.value; + if (objectTypesTodo.has(currentObjectName)) { + objectTypesTodo.delete(currentObjectName); + var _a = federationConfig[currentObjectName], keyFields = _a.keyFields, extend = _a.extend; + var newDirectives = keyFields + ? keyFields.map(function (keyField) { + return createDirectiveWithFields('key', keyField); + }) + : []; + // if (extend) { + // newDirectives.push(createDirectiveNode('extends')) + // } + return __assign(__assign({}, node), { directives: __spreadArrays((node.directives || []), newDirectives), kind: (extend ? 'InterfaceTypeExtension' : node.kind) }); + } + }, + leave: function () { + currentObjectName = undefined; + }, + }, + FieldDefinition: function (node) { + var currentFieldsTodo = currentObjectName && fieldTypesTodo[currentObjectName]; + if (currentObjectName && + currentFieldsTodo && + currentFieldsTodo[node.name.value]) { + var currentFieldConfig = currentFieldsTodo[node.name.value]; + delete currentFieldsTodo[node.name.value]; + if (Object.keys(currentFieldsTodo).length === 0) { + delete fieldTypesTodo[currentObjectName]; + } + return __assign(__assign({}, node), { directives: __spreadArrays((node.directives || []), (currentFieldConfig.external + ? [ast_builders_1.createDirectiveNode('external')] + : []), (currentFieldConfig.provides + ? [ + createDirectiveWithFields('provides', currentFieldConfig.provides), + ] + : []), (currentFieldConfig.requires + ? [ + createDirectiveWithFields('requires', currentFieldConfig.requires), + ] + : [])) }); + } + return undefined; + }, + }); + if (objectTypesTodo.size !== 0) { + throw new Error("Could not add key directives or extend types: " + Array.from(objectTypesTodo).join(', ')); + } + if (Object.keys(fieldTypesTodo).length !== 0) { + throw new Error("Could not add directive to these fields: " + Object.entries(fieldTypesTodo) + .flatMap(function (_a) { + var objectName = _a[0], fieldsConfig = _a[1]; + return Object.keys(fieldsConfig).map(function (externalField) { return objectName + "." + externalField; }); + }) + .join(', ')); + } + return language_1.print(withDirectives); +} +exports.addFederationAnnotations = addFederationAnnotations; +//# sourceMappingURL=transform-sdl.js.map \ No newline at end of file diff --git a/dist/transform-sdl.js.map b/dist/transform-sdl.js.map new file mode 100644 index 0000000..67f72a7 --- /dev/null +++ b/dist/transform-sdl.js.map @@ -0,0 +1 @@ +{"version":3,"file":"transform-sdl.js","sourceRoot":"","sources":["../src/transform-sdl.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/transform-sdl.spec.d.ts b/dist/transform-sdl.spec.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/dist/transform-sdl.spec.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/transform-sdl.spec.js b/dist/transform-sdl.spec.js new file mode 100644 index 0000000..65b22a8 --- /dev/null +++ b/dist/transform-sdl.spec.js @@ -0,0 +1,73 @@ +"use strict"; +var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) { + if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } + return cooked; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var dedent_1 = __importDefault(require("dedent")); +var transform_sdl_1 = require("./transform-sdl"); +describe('transform-sdl', function () { + it('should add key directives to sdl', function () { + expect(transform_sdl_1.addFederationAnnotations("\n type Product @keep {\n id: Int\n }", { + Product: { + keyFields: ['id'], + }, + })).toEqual(dedent_1.default(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n type Product @keep @key(fields: \"id\") {\n id: Int\n }\n"], ["\n type Product @keep @key(fields: \"id\") {\n id: Int\n }\\n"])))); + }); + it('should throw an error if not all keys were added', function () { + expect(function () { + transform_sdl_1.addFederationAnnotations("\n type Product {\n id: Int\n }\n ", { + NotProduct: { + keyFields: ['mock keyFields'], + }, + NotProduct2: { + keyFields: ['mock keyFields'], + }, + }); + }).toThrow('Could not add key directives or extend types: NotProduct, NotProduct2'); + }); + it('should convert types to extend types', function () { + expect(transform_sdl_1.addFederationAnnotations("\n type Product {\n id: Int\n }", { + Product: { + extend: true, + }, + })).toEqual(dedent_1.default(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n extend type Product {\n id: Int\n }\n"], ["\n extend type Product {\n id: Int\n }\\n"])))); + }); + it('should add directive to fields', function () { + expect(transform_sdl_1.addFederationAnnotations("\n type Product {\n id: Int\n }", { + Product: { + fields: { + id: { + external: true, + provides: 'mock provides', + requires: 'a { query }', + }, + }, + }, + })).toEqual(dedent_1.default(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n type Product {\n id: Int @external @provides(fields: \"mock provides\") @requires(fields: \"a { query }\")\n }\n"], ["\n type Product {\n id: Int @external @provides(fields: \"mock provides\") @requires(fields: \"a { query }\")\n }\\n"])))); + }); + it('should throw an error if not all external fields could get a directive', function () { + expect(function () { + transform_sdl_1.addFederationAnnotations("\n type Product {\n id: Int\n }\n ", { + NotProduct: { + fields: { + field1: { + external: true, + }, + field2: { + provides: 'mock provides', + }, + field3: { + requires: 'mock requires', + }, + }, + }, + }); + }).toThrow('Could not add directive to these fields: NotProduct.field1, NotProduct.field2, NotProduct.field3'); + }); +}); +var templateObject_1, templateObject_2, templateObject_3; +//# sourceMappingURL=transform-sdl.spec.js.map \ No newline at end of file diff --git a/dist/transform-sdl.spec.js.map b/dist/transform-sdl.spec.js.map new file mode 100644 index 0000000..52a728e --- /dev/null +++ b/dist/transform-sdl.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"transform-sdl.spec.js","sourceRoot":"","sources":["../src/transform-sdl.spec.ts"],"names":[],"mappings":";;;;;;;;;AAAA,kDAA4B;AAC5B,iDAA2D;AAE3D,QAAQ,CAAC,eAAe,EAAE;IACxB,EAAE,CAAC,kCAAkC,EAAE;QACrC,MAAM,CACJ,wCAAwB,CACtB,wDAGA,EACA;YACE,OAAO,EAAE;gBACP,SAAS,EAAE,CAAC,IAAI,CAAC;aAClB;SACF,CACF,CACF,CAAC,OAAO,CAAC,gBAAM,kJAAA,gFAGV,KAAC,CAAC;IACV,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE;QACrD,MAAM,CAAC;YACL,wCAAwB,CACtB,gEAID,EACC;gBACE,UAAU,EAAE;oBACV,SAAS,EAAE,CAAC,gBAAgB,CAAC;iBAC9B;gBACD,WAAW,EAAE;oBACX,SAAS,EAAE,CAAC,gBAAgB,CAAC;iBAC9B;aACF,CACF,CAAC;QACJ,CAAC,CAAC,CAAC,OAAO,CACR,uEAAuE,CACxE,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE;QACzC,MAAM,CACJ,wCAAwB,CACtB,kDAGA,EACA;YACE,OAAO,EAAE;gBACP,MAAM,EAAE,IAAI;aACb;SACF,CACF,CACF,CAAC,OAAO,CAAC,gBAAM,8HAAA,4DAGV,KAAC,CAAC;IACV,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE;QACnC,MAAM,CACJ,wCAAwB,CACtB,kDAGA,EACA;YACE,OAAO,EAAE;gBACP,MAAM,EAAE;oBACN,EAAE,EAAE;wBACF,QAAQ,EAAE,IAAI;wBACd,QAAQ,EAAE,eAAe;wBACzB,QAAQ,EAAE,aAAa;qBACxB;iBACF;aACF;SACF,CACF,CACF,CAAC,OAAO,CAAC,gBAAM,yMAAA,uIAGV,KAAC,CAAC;IACV,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wEAAwE,EAAE;QAC3E,MAAM,CAAC;YACL,wCAAwB,CACtB,gEAID,EACC;gBACE,UAAU,EAAE;oBACV,MAAM,EAAE;wBACN,MAAM,EAAE;4BACN,QAAQ,EAAE,IAAI;yBACf;wBACD,MAAM,EAAE;4BACN,QAAQ,EAAE,eAAe;yBAC1B;wBACD,MAAM,EAAE;4BACN,QAAQ,EAAE,eAAe;yBAC1B;qBACF;iBACF;aACF,CACF,CAAC;QACJ,CAAC,CAAC,CAAC,OAAO,CACR,kGAAkG,CACnG,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"} \ No newline at end of file