1 | "use strict";
|
2 |
|
3 | Object.defineProperty(exports, "__esModule", { value: true });
|
4 | exports.federationToStitchingSDL = void 0;
|
5 | const graphql_1 = require("graphql");
|
6 | const stitchingDirectives_js_1 = require("./stitchingDirectives.js");
|
7 | const extensionKind = /Extension$/;
|
8 | const entityKinds = [
|
9 | graphql_1.Kind.OBJECT_TYPE_DEFINITION,
|
10 | graphql_1.Kind.OBJECT_TYPE_EXTENSION,
|
11 | graphql_1.Kind.INTERFACE_TYPE_DEFINITION,
|
12 | graphql_1.Kind.INTERFACE_TYPE_EXTENSION,
|
13 | ];
|
14 | function isEntityKind(def) {
|
15 | return entityKinds.includes(def.kind);
|
16 | }
|
17 | function getQueryTypeDef(definitions) {
|
18 | var _a;
|
19 | const schemaDef = definitions.find(def => def.kind === graphql_1.Kind.SCHEMA_DEFINITION);
|
20 | const typeName = schemaDef
|
21 | ? (_a = schemaDef.operationTypes.find(({ operation }) => operation === 'query')) === null || _a === void 0 ? void 0 : _a.type.name.value
|
22 | : 'Query';
|
23 | return definitions.find(def => def.kind === graphql_1.Kind.OBJECT_TYPE_DEFINITION && def.name.value === typeName);
|
24 | }
|
25 |
|
26 |
|
27 |
|
28 |
|
29 | function federationToStitchingSDL(federationSDL, stitchingConfig = (0, stitchingDirectives_js_1.stitchingDirectives)()) {
|
30 | const doc = (0, graphql_1.parse)(federationSDL);
|
31 | const entityTypes = [];
|
32 | const baseTypeNames = doc.definitions.reduce((memo, typeDef) => {
|
33 | if (!extensionKind.test(typeDef.kind) && 'name' in typeDef && typeDef.name) {
|
34 | memo[typeDef.name.value] = true;
|
35 | }
|
36 | return memo;
|
37 | }, {});
|
38 | doc.definitions.forEach(typeDef => {
|
39 | var _a, _b, _c;
|
40 |
|
41 |
|
42 |
|
43 | if (extensionKind.test(typeDef.kind) && 'name' in typeDef && typeDef.name && !baseTypeNames[typeDef.name.value]) {
|
44 | typeDef.kind = typeDef.kind.replace(extensionKind, 'Definition');
|
45 | }
|
46 | if (!isEntityKind(typeDef))
|
47 | return;
|
48 |
|
49 |
|
50 | const keyDirs = [];
|
51 | const otherDirs = [];
|
52 | (_a = typeDef.directives) === null || _a === void 0 ? void 0 : _a.forEach(dir => {
|
53 | if (dir.name.value === 'key') {
|
54 | keyDirs.push(dir);
|
55 | }
|
56 | else {
|
57 | otherDirs.push(dir);
|
58 | }
|
59 | });
|
60 | if (!keyDirs.length)
|
61 | return;
|
62 |
|
63 | const selectionSet = `{ ${keyDirs.map((dir) => dir.arguments[0].value.value).join(' ')} }`;
|
64 | const keyFields = (0, graphql_1.parse)(selectionSet).definitions[0].selectionSet.selections.map((sel) => sel.name.value);
|
65 | const keyDir = keyDirs[0];
|
66 | keyDir.name.value = stitchingConfig.keyDirective.name;
|
67 | keyDir.arguments[0].name.value = 'selectionSet';
|
68 | keyDir.arguments[0].value.value = selectionSet;
|
69 | typeDef.directives = [keyDir, ...otherDirs];
|
70 |
|
71 |
|
72 |
|
73 | typeDef.fields = (_b = typeDef.fields) === null || _b === void 0 ? void 0 : _b.filter(fieldDef => {
|
74 | var _a;
|
75 | return (keyFields.includes(fieldDef.name.value) || !((_a = fieldDef.directives) === null || _a === void 0 ? void 0 : _a.find(dir => dir.name.value === 'external')));
|
76 | });
|
77 |
|
78 | (_c = typeDef.fields) === null || _c === void 0 ? void 0 : _c.forEach((fieldDef) => {
|
79 | fieldDef.directives = fieldDef.directives.filter((dir) => !/^(external|provides)$/.test(dir.name.value));
|
80 | fieldDef.directives.forEach((dir) => {
|
81 | if (dir.name.value === 'requires') {
|
82 | dir.name.value = stitchingConfig.computedDirective.name;
|
83 | dir.arguments[0].name.value = 'selectionSet';
|
84 | dir.arguments[0].value.value = `{ ${dir.arguments[0].value.value} }`;
|
85 | }
|
86 | });
|
87 | });
|
88 | if (typeDef.kind === graphql_1.Kind.OBJECT_TYPE_DEFINITION || typeDef.kind === graphql_1.Kind.OBJECT_TYPE_EXTENSION) {
|
89 | entityTypes.push(typeDef.name.value);
|
90 | }
|
91 | });
|
92 |
|
93 |
|
94 |
|
95 |
|
96 | if (entityTypes.length) {
|
97 | const queryDef = getQueryTypeDef(doc.definitions);
|
98 | const entitiesSchema = (0, graphql_1.parse)( `
|
99 | scalar _Any
|
100 | union _Entity = ${entityTypes.filter((v, i, a) => a.indexOf(v) === i).join(' | ')}
|
101 | type Query { _entities(representations: [_Any!]!): [_Entity]! @${stitchingConfig.mergeDirective.name} }
|
102 | `).definitions;
|
103 | doc.definitions.push(entitiesSchema[0]);
|
104 | doc.definitions.push(entitiesSchema[1]);
|
105 | if (queryDef) {
|
106 | queryDef.fields.push(entitiesSchema[2].fields[0]);
|
107 | }
|
108 | else {
|
109 | doc.definitions.push(entitiesSchema[2]);
|
110 | }
|
111 | }
|
112 | return [stitchingConfig.stitchingDirectivesTypeDefs, (0, graphql_1.print)(doc)].join('\n');
|
113 | }
|
114 | exports.federationToStitchingSDL = federationToStitchingSDL;
|