1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.DirectiveMetadata = void 0;
|
4 | const graphql_1 = require("graphql");
|
5 | const utilities_1 = require("../utilities");
|
6 | const utils_1 = require("./utils");
|
7 | class DirectiveMetadata {
|
8 | constructor(subgraphs) {
|
9 | this.directiveUsagesPerSubgraph = new Map();
|
10 | for (const subgraph of subgraphs) {
|
11 | const visitor = this.getTypeVisitor(subgraph.name);
|
12 | (0, graphql_1.visit)(subgraph.typeDefs, {
|
13 | ObjectTypeDefinition: visitor,
|
14 | ObjectTypeExtension: visitor,
|
15 | InterfaceTypeDefinition: visitor,
|
16 | InterfaceTypeExtension: visitor,
|
17 | UnionTypeDefinition: visitor,
|
18 | UnionTypeExtension: visitor,
|
19 | });
|
20 | }
|
21 | }
|
22 | getTypeVisitor(subgraphName) {
|
23 | function collectDirectiveUsages(node, usagesOnNode) {
|
24 | var _a;
|
25 | for (const directive of (_a = node.directives) !== null && _a !== void 0 ? _a : []) {
|
26 | const usages = (0, utilities_1.mapGetOrSet)(usagesOnNode, directive.name.value, []);
|
27 | usages.push(directive);
|
28 | }
|
29 | }
|
30 | return (node) => {
|
31 | const directiveUsagesPerType = (0, utilities_1.mapGetOrSet)(this.directiveUsagesPerSubgraph, subgraphName, new Map());
|
32 | const { directives: usagesOnType, fields: usagesByFieldName } = (0, utilities_1.mapGetOrSet)(directiveUsagesPerType, node.name.value, {
|
33 | directives: new Map(),
|
34 | fields: new Map(),
|
35 | });
|
36 | collectDirectiveUsages(node, usagesOnType);
|
37 | if ('fields' in node && node.fields) {
|
38 | for (const field of node.fields) {
|
39 | const usagesOnField = (0, utilities_1.mapGetOrSet)(usagesByFieldName, field.name.value, new Map());
|
40 | collectDirectiveUsages(field, usagesOnField);
|
41 | }
|
42 | }
|
43 | };
|
44 | }
|
45 | hasUsages(directiveName) {
|
46 | for (const directiveUsagesPerType of this.directiveUsagesPerSubgraph.values()) {
|
47 | for (const { directives, fields } of directiveUsagesPerType.values()) {
|
48 | const usagesOnType = directives.get(directiveName);
|
49 | if (usagesOnType && usagesOnType.length > 0)
|
50 | return true;
|
51 | for (const directiveUsages of fields.values()) {
|
52 | const usagesOnField = directiveUsages.get(directiveName);
|
53 | if (usagesOnField && usagesOnField.length > 0)
|
54 | return true;
|
55 | }
|
56 | }
|
57 | }
|
58 | return false;
|
59 | }
|
60 | applyMetadataToSupergraphSchema(schema) {
|
61 | for (const directiveUsagesPerType of this.directiveUsagesPerSubgraph.values()) {
|
62 | for (const [typeName, { directives, fields },] of directiveUsagesPerType.entries()) {
|
63 | const namedType = schema.getType(typeName);
|
64 | if (!namedType)
|
65 | continue;
|
66 | const existingMetadata = (0, utils_1.getFederationMetadata)(namedType);
|
67 | const typeFederationMetadata = {
|
68 | ...existingMetadata,
|
69 | directiveUsages: mergeDirectiveUsages(existingMetadata === null || existingMetadata === void 0 ? void 0 : existingMetadata.directiveUsages, directives),
|
70 | };
|
71 | namedType.extensions = {
|
72 | ...namedType.extensions,
|
73 | federation: typeFederationMetadata,
|
74 | };
|
75 | for (const [fieldName, usagesPerDirective] of fields.entries()) {
|
76 | if (!('getFields' in namedType))
|
77 | continue;
|
78 | const field = namedType.getFields()[fieldName];
|
79 | if (!field)
|
80 | continue;
|
81 | const existingMetadata = (0, utils_1.getFederationMetadata)(field);
|
82 | const fieldFederationMetadata = {
|
83 | ...existingMetadata,
|
84 | directiveUsages: mergeDirectiveUsages(existingMetadata === null || existingMetadata === void 0 ? void 0 : existingMetadata.directiveUsages, usagesPerDirective),
|
85 | };
|
86 | field.extensions = {
|
87 | ...field.extensions,
|
88 | federation: fieldFederationMetadata,
|
89 | };
|
90 | }
|
91 | }
|
92 | }
|
93 | }
|
94 | }
|
95 | exports.DirectiveMetadata = DirectiveMetadata;
|
96 | function mergeDirectiveUsages(first, second) {
|
97 | const merged = new Map();
|
98 | if (first) {
|
99 | for (const [directiveName, usages] of first.entries()) {
|
100 | merged.set(directiveName, [...usages]);
|
101 | }
|
102 | }
|
103 | for (const [directiveName, newUsages] of second.entries()) {
|
104 | const usages = (0, utilities_1.mapGetOrSet)(merged, directiveName, []);
|
105 | usages.push(...newUsages);
|
106 | }
|
107 | return merged;
|
108 | }
|
109 |
|
\ | No newline at end of file |