@depup/graphql-codegen__plugin-helpers 6.2.0-depup.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -0
- package/changes.json +18 -0
- package/cjs/federation.js +436 -0
- package/cjs/getCachedDocumentNodeFromSchema.js +5 -0
- package/cjs/helpers.js +178 -0
- package/cjs/index.js +13 -0
- package/cjs/oldVisit.js +19 -0
- package/cjs/package.json +1 -0
- package/cjs/profiler.js +49 -0
- package/cjs/resolve-external-module-and-fn.js +31 -0
- package/cjs/types.js +6 -0
- package/cjs/utils.js +35 -0
- package/esm/federation.js +430 -0
- package/esm/getCachedDocumentNodeFromSchema.js +2 -0
- package/esm/helpers.js +168 -0
- package/esm/index.js +8 -0
- package/esm/oldVisit.js +16 -0
- package/esm/profiler.js +45 -0
- package/esm/resolve-external-module-and-fn.js +27 -0
- package/esm/types.js +3 -0
- package/esm/utils.js +29 -0
- package/package.json +76 -0
- package/typings/federation.d.cts +102 -0
- package/typings/federation.d.ts +102 -0
- package/typings/getCachedDocumentNodeFromSchema.d.cts +2 -0
- package/typings/getCachedDocumentNodeFromSchema.d.ts +2 -0
- package/typings/helpers.d.cts +13 -0
- package/typings/helpers.d.ts +13 -0
- package/typings/index.d.cts +9 -0
- package/typings/index.d.ts +9 -0
- package/typings/oldVisit.d.cts +9 -0
- package/typings/oldVisit.d.ts +9 -0
- package/typings/profiler.d.cts +28 -0
- package/typings/profiler.d.ts +28 -0
- package/typings/resolve-external-module-and-fn.d.cts +1 -0
- package/typings/resolve-external-module-and-fn.d.ts +1 -0
- package/typings/types.d.cts +635 -0
- package/typings/types.d.ts +635 -0
- package/typings/utils.d.cts +6 -0
- package/typings/utils.d.ts +6 -0
package/README.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# @depup/graphql-codegen__plugin-helpers
|
|
2
|
+
|
|
3
|
+
> Dependency-bumped version of [@graphql-codegen/plugin-helpers](https://www.npmjs.com/package/@graphql-codegen/plugin-helpers)
|
|
4
|
+
|
|
5
|
+
Generated by [DepUp](https://github.com/depup/npm) -- all production
|
|
6
|
+
dependencies bumped to latest versions.
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install @depup/graphql-codegen__plugin-helpers
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
| Field | Value |
|
|
15
|
+
|-------|-------|
|
|
16
|
+
| Original | [@graphql-codegen/plugin-helpers](https://www.npmjs.com/package/@graphql-codegen/plugin-helpers) @ 6.2.0 |
|
|
17
|
+
| Processed | 2026-03-17 |
|
|
18
|
+
| Smoke test | passed |
|
|
19
|
+
| Deps updated | 3 |
|
|
20
|
+
|
|
21
|
+
## Dependency Changes
|
|
22
|
+
|
|
23
|
+
| Dependency | From | To |
|
|
24
|
+
|------------|------|-----|
|
|
25
|
+
| change-case-all | 1.0.15 | ^2.1.0 |
|
|
26
|
+
| lodash | ~4.17.0 | ^4.17.23 |
|
|
27
|
+
| tslib | ~2.6.0 | ^2.8.1 |
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
Source: https://github.com/depup/npm | Original: https://www.npmjs.com/package/@graphql-codegen/plugin-helpers
|
|
32
|
+
|
|
33
|
+
License inherited from the original package.
|
package/changes.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"bumped": {
|
|
3
|
+
"change-case-all": {
|
|
4
|
+
"from": "1.0.15",
|
|
5
|
+
"to": "^2.1.0"
|
|
6
|
+
},
|
|
7
|
+
"lodash": {
|
|
8
|
+
"from": "~4.17.0",
|
|
9
|
+
"to": "^4.17.23"
|
|
10
|
+
},
|
|
11
|
+
"tslib": {
|
|
12
|
+
"from": "~2.6.0",
|
|
13
|
+
"to": "^2.8.1"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"timestamp": "2026-03-17T16:31:48.947Z",
|
|
17
|
+
"totalUpdated": 3
|
|
18
|
+
}
|
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ApolloFederation = exports.federationSpec = void 0;
|
|
4
|
+
exports.addFederationReferencesToSchema = addFederationReferencesToSchema;
|
|
5
|
+
exports.removeFederation = removeFederation;
|
|
6
|
+
const utils_1 = require("@graphql-tools/utils");
|
|
7
|
+
const graphql_1 = require("graphql");
|
|
8
|
+
const index_js_1 = require("./index.js");
|
|
9
|
+
const utils_js_1 = require("./utils.js");
|
|
10
|
+
/**
|
|
11
|
+
* Federation Spec
|
|
12
|
+
*/
|
|
13
|
+
exports.federationSpec = (0, graphql_1.parse)(/* GraphQL */ `
|
|
14
|
+
scalar _FieldSet
|
|
15
|
+
|
|
16
|
+
directive @external on FIELD_DEFINITION
|
|
17
|
+
directive @requires(fields: _FieldSet!) on FIELD_DEFINITION
|
|
18
|
+
directive @provides(fields: _FieldSet!) on FIELD_DEFINITION
|
|
19
|
+
directive @key(fields: _FieldSet!) on OBJECT | INTERFACE
|
|
20
|
+
`);
|
|
21
|
+
/**
|
|
22
|
+
* Adds `__resolveReference` in each ObjectType and InterfaceType involved in Federation.
|
|
23
|
+
* We do this to utilise the existing FieldDefinition logic of the plugin, which includes many logic:
|
|
24
|
+
* - mapper
|
|
25
|
+
* - return type
|
|
26
|
+
* @param schema
|
|
27
|
+
*/
|
|
28
|
+
function addFederationReferencesToSchema(schema) {
|
|
29
|
+
const setFederationMeta = ({ meta, typeName, update, }) => {
|
|
30
|
+
meta[typeName] = {
|
|
31
|
+
...(meta[typeName] ||
|
|
32
|
+
{
|
|
33
|
+
hasResolveReference: false,
|
|
34
|
+
resolvableKeyDirectives: [],
|
|
35
|
+
referenceSelectionSets: [],
|
|
36
|
+
referenceSelectionSetsString: '',
|
|
37
|
+
}),
|
|
38
|
+
...update,
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
const getReferenceSelectionSets = ({ resolvableKeyDirectives, fields, }) => {
|
|
42
|
+
const referenceSelectionSets = [];
|
|
43
|
+
// @key() @key() - "primary keys" in Federation
|
|
44
|
+
// A reference may receive one primary key combination at a time, so they will be combined with `|`
|
|
45
|
+
const primaryKeys = resolvableKeyDirectives.map(extractReferenceSelectionSet);
|
|
46
|
+
referenceSelectionSets.push({ directive: '@key', selectionSets: [...primaryKeys] });
|
|
47
|
+
const requiresPossibleTypes = [];
|
|
48
|
+
for (const fieldNode of Object.values(fields)) {
|
|
49
|
+
// Look for @requires and see what the service needs and gets
|
|
50
|
+
const directives = getDirectivesByName('requires', fieldNode.astNode);
|
|
51
|
+
for (const directive of directives) {
|
|
52
|
+
const requires = extractReferenceSelectionSet(directive);
|
|
53
|
+
requiresPossibleTypes.push(requires);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
referenceSelectionSets.push({ directive: '@requires', selectionSets: requiresPossibleTypes });
|
|
57
|
+
return referenceSelectionSets;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Function to find all combinations of selection sets and push them into the `result`
|
|
61
|
+
* This is used for `@requires` directive because depending on the operation selection set, different
|
|
62
|
+
* combination of fields are sent from the router.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* Input: [
|
|
66
|
+
* { a: true },
|
|
67
|
+
* { b: true },
|
|
68
|
+
* { c: true },
|
|
69
|
+
* { d: true},
|
|
70
|
+
* ]
|
|
71
|
+
* Output: [
|
|
72
|
+
* { a: true },
|
|
73
|
+
* { a: true, b: true },
|
|
74
|
+
* { a: true, c: true },
|
|
75
|
+
* { a: true, d: true },
|
|
76
|
+
* { a: true, b: true, c: true },
|
|
77
|
+
* { a: true, b: true, d: true },
|
|
78
|
+
* { a: true, c: true, d: true },
|
|
79
|
+
* { a: true, b: true, c: true, d: true }
|
|
80
|
+
*
|
|
81
|
+
* { b: true },
|
|
82
|
+
* { b: true, c: true },
|
|
83
|
+
* { b: true, d: true },
|
|
84
|
+
* { b: true, c: true, d: true }
|
|
85
|
+
*
|
|
86
|
+
* { c: true },
|
|
87
|
+
* { c: true, d: true },
|
|
88
|
+
*
|
|
89
|
+
* { d: true },
|
|
90
|
+
* ]
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
function findAllSelectionSetCombinations(selectionSets, result) {
|
|
94
|
+
if (selectionSets.length === 0) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
for (let baseIndex = 0; baseIndex < selectionSets.length; baseIndex++) {
|
|
98
|
+
const base = selectionSets.slice(0, baseIndex + 1);
|
|
99
|
+
const rest = selectionSets.slice(baseIndex + 1, selectionSets.length);
|
|
100
|
+
const currentSelectionSet = base.reduce((acc, selectionSet) => {
|
|
101
|
+
acc = { ...acc, ...selectionSet };
|
|
102
|
+
return acc;
|
|
103
|
+
}, {});
|
|
104
|
+
if (baseIndex === 0) {
|
|
105
|
+
result.push(currentSelectionSet);
|
|
106
|
+
}
|
|
107
|
+
for (const selectionSet of rest) {
|
|
108
|
+
result.push({ ...currentSelectionSet, ...selectionSet });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const next = selectionSets.slice(1, selectionSets.length);
|
|
112
|
+
if (next.length > 0) {
|
|
113
|
+
findAllSelectionSetCombinations(next, result);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const printReferenceSelectionSets = ({ typeName, baseFederationType, referenceSelectionSets, }) => {
|
|
117
|
+
const referenceSelectionSetStrings = referenceSelectionSets.reduce((acc, { directive, selectionSets: originalSelectionSets }) => {
|
|
118
|
+
const result = [];
|
|
119
|
+
let selectionSets = originalSelectionSets;
|
|
120
|
+
if (directive === '@requires') {
|
|
121
|
+
selectionSets = [];
|
|
122
|
+
findAllSelectionSetCombinations(originalSelectionSets, selectionSets);
|
|
123
|
+
if (selectionSets.length > 0) {
|
|
124
|
+
result.push('Record<PropertyKey, never>');
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
for (const referenceSelectionSet of selectionSets) {
|
|
128
|
+
result.push(`GraphQLRecursivePick<${baseFederationType}, ${JSON.stringify(referenceSelectionSet)}>`);
|
|
129
|
+
}
|
|
130
|
+
if (result.length === 0) {
|
|
131
|
+
return acc;
|
|
132
|
+
}
|
|
133
|
+
if (result.length === 1) {
|
|
134
|
+
acc.push(result.join(' | '));
|
|
135
|
+
return acc;
|
|
136
|
+
}
|
|
137
|
+
acc.push(`( ${result.join('\n | ')} )`);
|
|
138
|
+
return acc;
|
|
139
|
+
}, []);
|
|
140
|
+
return `\n ( { __typename: '${typeName}' }\n & ${referenceSelectionSetStrings.join('\n & ')} )`;
|
|
141
|
+
};
|
|
142
|
+
const federationMeta = {};
|
|
143
|
+
const transformedSchema = (0, utils_1.mapSchema)(schema, {
|
|
144
|
+
[utils_1.MapperKind.INTERFACE_TYPE]: type => {
|
|
145
|
+
const node = (0, utils_1.astFromInterfaceType)(type, schema);
|
|
146
|
+
const federationDetails = checkTypeFederationDetails(node, schema);
|
|
147
|
+
if (federationDetails && federationDetails.resolvableKeyDirectives.length > 0) {
|
|
148
|
+
const typeConfig = type.toConfig();
|
|
149
|
+
typeConfig.fields = {
|
|
150
|
+
[resolveReferenceFieldName]: {
|
|
151
|
+
type,
|
|
152
|
+
},
|
|
153
|
+
...typeConfig.fields,
|
|
154
|
+
};
|
|
155
|
+
const referenceSelectionSets = getReferenceSelectionSets({
|
|
156
|
+
resolvableKeyDirectives: federationDetails.resolvableKeyDirectives,
|
|
157
|
+
fields: typeConfig.fields,
|
|
158
|
+
});
|
|
159
|
+
const referenceSelectionSetsString = printReferenceSelectionSets({
|
|
160
|
+
typeName: type.name,
|
|
161
|
+
baseFederationType: `FederationTypes['${type.name}']`, // FIXME: run convertName on FederationTypes
|
|
162
|
+
referenceSelectionSets,
|
|
163
|
+
});
|
|
164
|
+
setFederationMeta({
|
|
165
|
+
meta: federationMeta,
|
|
166
|
+
typeName: type.name,
|
|
167
|
+
update: {
|
|
168
|
+
hasResolveReference: true,
|
|
169
|
+
resolvableKeyDirectives: federationDetails.resolvableKeyDirectives,
|
|
170
|
+
referenceSelectionSets,
|
|
171
|
+
referenceSelectionSetsString,
|
|
172
|
+
},
|
|
173
|
+
});
|
|
174
|
+
return new graphql_1.GraphQLInterfaceType(typeConfig);
|
|
175
|
+
}
|
|
176
|
+
return type;
|
|
177
|
+
},
|
|
178
|
+
[utils_1.MapperKind.OBJECT_TYPE]: type => {
|
|
179
|
+
const node = (0, utils_1.astFromObjectType)(type, schema);
|
|
180
|
+
const federationDetails = checkTypeFederationDetails(node, schema);
|
|
181
|
+
if (federationDetails && federationDetails.resolvableKeyDirectives.length > 0) {
|
|
182
|
+
const typeConfig = type.toConfig();
|
|
183
|
+
const referenceSelectionSets = getReferenceSelectionSets({
|
|
184
|
+
resolvableKeyDirectives: federationDetails.resolvableKeyDirectives,
|
|
185
|
+
fields: typeConfig.fields,
|
|
186
|
+
});
|
|
187
|
+
typeConfig.fields = {
|
|
188
|
+
[resolveReferenceFieldName]: {
|
|
189
|
+
type,
|
|
190
|
+
},
|
|
191
|
+
...typeConfig.fields,
|
|
192
|
+
};
|
|
193
|
+
const referenceSelectionSetsString = printReferenceSelectionSets({
|
|
194
|
+
typeName: type.name,
|
|
195
|
+
baseFederationType: `FederationTypes['${type.name}']`, // FIXME: run convertName on FederationTypes
|
|
196
|
+
referenceSelectionSets,
|
|
197
|
+
});
|
|
198
|
+
setFederationMeta({
|
|
199
|
+
meta: federationMeta,
|
|
200
|
+
typeName: type.name,
|
|
201
|
+
update: {
|
|
202
|
+
hasResolveReference: true,
|
|
203
|
+
resolvableKeyDirectives: federationDetails.resolvableKeyDirectives,
|
|
204
|
+
referenceSelectionSets,
|
|
205
|
+
referenceSelectionSetsString,
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
return new graphql_1.GraphQLObjectType(typeConfig);
|
|
209
|
+
}
|
|
210
|
+
return type;
|
|
211
|
+
},
|
|
212
|
+
});
|
|
213
|
+
return {
|
|
214
|
+
transformedSchema,
|
|
215
|
+
federationMeta,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Removes Federation Spec from GraphQL Schema
|
|
220
|
+
* @param schema
|
|
221
|
+
* @param config
|
|
222
|
+
*/
|
|
223
|
+
function removeFederation(schema) {
|
|
224
|
+
return (0, utils_1.mapSchema)(schema, {
|
|
225
|
+
[utils_1.MapperKind.QUERY]: queryType => {
|
|
226
|
+
const queryTypeConfig = queryType.toConfig();
|
|
227
|
+
delete queryTypeConfig.fields._entities;
|
|
228
|
+
delete queryTypeConfig.fields._service;
|
|
229
|
+
return new graphql_1.GraphQLObjectType(queryTypeConfig);
|
|
230
|
+
},
|
|
231
|
+
[utils_1.MapperKind.UNION_TYPE]: unionType => {
|
|
232
|
+
const unionTypeName = unionType.name;
|
|
233
|
+
if (unionTypeName === '_Entity' || unionTypeName === '_Any') {
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
return unionType;
|
|
237
|
+
},
|
|
238
|
+
[utils_1.MapperKind.OBJECT_TYPE]: objectType => {
|
|
239
|
+
if (objectType.name === '_Service') {
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
return objectType;
|
|
243
|
+
},
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
const resolveReferenceFieldName = '__resolveReference';
|
|
247
|
+
class ApolloFederation {
|
|
248
|
+
enabled = false;
|
|
249
|
+
schema;
|
|
250
|
+
providesMap;
|
|
251
|
+
/**
|
|
252
|
+
* `fieldsToGenerate` is a meta object where the keys are object type names
|
|
253
|
+
* and the values are fields that must be generated for that object.
|
|
254
|
+
*/
|
|
255
|
+
fieldsToGenerate;
|
|
256
|
+
meta = {};
|
|
257
|
+
constructor({ enabled, schema, meta }) {
|
|
258
|
+
this.enabled = enabled;
|
|
259
|
+
this.schema = schema;
|
|
260
|
+
this.providesMap = this.createMapOfProvides();
|
|
261
|
+
this.fieldsToGenerate = {};
|
|
262
|
+
this.meta = meta;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Excludes types definde by Federation
|
|
266
|
+
* @param typeNames List of type names
|
|
267
|
+
*/
|
|
268
|
+
filterTypeNames(typeNames) {
|
|
269
|
+
return this.enabled ? typeNames.filter(t => t !== '_FieldSet') : typeNames;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Excludes `__resolveReference` fields
|
|
273
|
+
* @param fieldNames List of field names
|
|
274
|
+
*/
|
|
275
|
+
filterFieldNames(fieldNames) {
|
|
276
|
+
return this.enabled ? fieldNames.filter(t => t !== resolveReferenceFieldName) : fieldNames;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Decides if directive should not be generated
|
|
280
|
+
* @param name directive's name
|
|
281
|
+
*/
|
|
282
|
+
skipDirective(name) {
|
|
283
|
+
return this.enabled && ['external', 'requires', 'provides', 'key'].includes(name);
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Decides if scalar should not be generated
|
|
287
|
+
* @param name directive's name
|
|
288
|
+
*/
|
|
289
|
+
skipScalar(name) {
|
|
290
|
+
return this.enabled && name === '_FieldSet';
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* findFieldNodesToGenerate
|
|
294
|
+
* @description Function to find field nodes to generate.
|
|
295
|
+
* In a normal setup, all fields must be generated.
|
|
296
|
+
* However, in a Federatin setup, a field should not be generated if:
|
|
297
|
+
* - The field is marked as `@external` and there is no `@provides` path to the field
|
|
298
|
+
* - The parent object is marked as `@external` and there is no `@provides` path to the field
|
|
299
|
+
*/
|
|
300
|
+
findFieldNodesToGenerate({ node, }) {
|
|
301
|
+
const nodeName = node.name.value;
|
|
302
|
+
if (this.fieldsToGenerate[nodeName]) {
|
|
303
|
+
return this.fieldsToGenerate[nodeName];
|
|
304
|
+
}
|
|
305
|
+
const fieldNodes = (node.fields || []).map(field => field.node);
|
|
306
|
+
if (!this.enabled) {
|
|
307
|
+
return fieldNodes;
|
|
308
|
+
}
|
|
309
|
+
// If the object is marked with `@external`, fields to generate are those with `@provides`
|
|
310
|
+
if (this.isExternal(node)) {
|
|
311
|
+
const fieldNodesWithProvides = fieldNodes.reduce((acc, fieldNode) => {
|
|
312
|
+
if (this.hasProvides(node, fieldNode.name.value)) {
|
|
313
|
+
acc.push(fieldNode);
|
|
314
|
+
return acc;
|
|
315
|
+
}
|
|
316
|
+
return acc;
|
|
317
|
+
}, []);
|
|
318
|
+
this.fieldsToGenerate[nodeName] = fieldNodesWithProvides;
|
|
319
|
+
return fieldNodesWithProvides;
|
|
320
|
+
}
|
|
321
|
+
// If the object is not marked with `@external`, fields to generate are:
|
|
322
|
+
// - the fields without `@external`
|
|
323
|
+
// - the `@external` fields with `@provides`
|
|
324
|
+
const fieldNodesWithoutExternalOrHasProvides = fieldNodes.reduce((acc, fieldNode) => {
|
|
325
|
+
if (!this.isExternal(fieldNode)) {
|
|
326
|
+
acc.push(fieldNode);
|
|
327
|
+
return acc;
|
|
328
|
+
}
|
|
329
|
+
if (this.isExternal(fieldNode) && this.hasProvides(node, fieldNode.name.value)) {
|
|
330
|
+
acc.push(fieldNode);
|
|
331
|
+
return acc;
|
|
332
|
+
}
|
|
333
|
+
return acc;
|
|
334
|
+
}, []);
|
|
335
|
+
this.fieldsToGenerate[nodeName] = fieldNodesWithoutExternalOrHasProvides;
|
|
336
|
+
return fieldNodesWithoutExternalOrHasProvides;
|
|
337
|
+
}
|
|
338
|
+
isResolveReferenceField(fieldNode) {
|
|
339
|
+
const name = typeof fieldNode.name === 'string' ? fieldNode.name : fieldNode.name.value;
|
|
340
|
+
return this.enabled && name === resolveReferenceFieldName;
|
|
341
|
+
}
|
|
342
|
+
addFederationTypeGenericIfApplicable({ genericTypes, typeName, federationTypesType, }) {
|
|
343
|
+
if (!this.getMeta()[typeName]) {
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
const typeRef = `${federationTypesType}['${typeName}']`;
|
|
347
|
+
genericTypes.push(`FederationReferenceType extends ${typeRef} = ${typeRef}`);
|
|
348
|
+
}
|
|
349
|
+
getMeta() {
|
|
350
|
+
return this.meta;
|
|
351
|
+
}
|
|
352
|
+
isExternal(node) {
|
|
353
|
+
return getDirectivesByName('external', node).length > 0;
|
|
354
|
+
}
|
|
355
|
+
hasProvides(node, fieldName) {
|
|
356
|
+
const fields = this.providesMap[node.name.value];
|
|
357
|
+
if (fields?.length) {
|
|
358
|
+
return fields.includes(fieldName);
|
|
359
|
+
}
|
|
360
|
+
return false;
|
|
361
|
+
}
|
|
362
|
+
createMapOfProvides() {
|
|
363
|
+
const providesMap = {};
|
|
364
|
+
for (const typename of Object.keys(this.schema.getTypeMap())) {
|
|
365
|
+
const objectType = this.schema.getType(typename);
|
|
366
|
+
if ((0, graphql_1.isObjectType)(objectType)) {
|
|
367
|
+
for (const field of Object.values(objectType.getFields())) {
|
|
368
|
+
const provides = getDirectivesByName('provides', field.astNode)
|
|
369
|
+
.map(extractReferenceSelectionSet)
|
|
370
|
+
.reduce((prev, curr) => [...prev, ...Object.keys(curr)], []); // FIXME: this is not taking into account nested selection sets e.g. `company { taxCode }`
|
|
371
|
+
const ofType = (0, utils_js_1.getBaseType)(field.type);
|
|
372
|
+
providesMap[ofType.name] ||= [];
|
|
373
|
+
providesMap[ofType.name].push(...provides);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
return providesMap;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
exports.ApolloFederation = ApolloFederation;
|
|
381
|
+
/**
|
|
382
|
+
* Checks if Object Type is involved in Federation. Based on `@key` directive
|
|
383
|
+
* @param node Type
|
|
384
|
+
*/
|
|
385
|
+
function checkTypeFederationDetails(node, schema) {
|
|
386
|
+
const name = node.name.value;
|
|
387
|
+
const directives = node.directives;
|
|
388
|
+
const rootTypeNames = (0, utils_1.getRootTypeNames)(schema);
|
|
389
|
+
const isNotRoot = !rootTypeNames.has(name);
|
|
390
|
+
const isNotIntrospection = !name.startsWith('__');
|
|
391
|
+
const keyDirectives = directives.filter(d => d.name.value === 'key');
|
|
392
|
+
const check = isNotRoot && isNotIntrospection && keyDirectives.length > 0;
|
|
393
|
+
if (!check) {
|
|
394
|
+
return false;
|
|
395
|
+
}
|
|
396
|
+
const resolvableKeyDirectives = keyDirectives.filter(d => {
|
|
397
|
+
for (const arg of d.arguments) {
|
|
398
|
+
if (arg.name.value === 'resolvable' && arg.value.kind === 'BooleanValue' && arg.value.value === false) {
|
|
399
|
+
return false;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
return true;
|
|
403
|
+
});
|
|
404
|
+
return { resolvableKeyDirectives };
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Extracts directives from a node based on directive's name
|
|
408
|
+
* @param name directive name
|
|
409
|
+
* @param node ObjectType or Field
|
|
410
|
+
*/
|
|
411
|
+
function getDirectivesByName(name, node) {
|
|
412
|
+
return node?.directives?.filter(d => d.name.value === name) || [];
|
|
413
|
+
}
|
|
414
|
+
function extractReferenceSelectionSet(directive) {
|
|
415
|
+
const arg = directive.arguments.find(arg => arg.name.value === 'fields');
|
|
416
|
+
const { value } = arg.value;
|
|
417
|
+
return (0, index_js_1.oldVisit)((0, graphql_1.parse)(`{${value}}`), {
|
|
418
|
+
leave: {
|
|
419
|
+
SelectionSet(node) {
|
|
420
|
+
return node.selections.reduce((accum, field) => {
|
|
421
|
+
accum[field.name] = field.selection;
|
|
422
|
+
return accum;
|
|
423
|
+
}, {});
|
|
424
|
+
},
|
|
425
|
+
Field(node) {
|
|
426
|
+
return {
|
|
427
|
+
name: node.name.value,
|
|
428
|
+
selection: node.selectionSet || true,
|
|
429
|
+
};
|
|
430
|
+
},
|
|
431
|
+
Document(node) {
|
|
432
|
+
return node.definitions.find((def) => def.kind === 'OperationDefinition' && def.operation === 'query').selectionSet;
|
|
433
|
+
},
|
|
434
|
+
},
|
|
435
|
+
});
|
|
436
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getCachedDocumentNodeFromSchema = void 0;
|
|
4
|
+
const utils_1 = require("@graphql-tools/utils");
|
|
5
|
+
exports.getCachedDocumentNodeFromSchema = (0, utils_1.memoize1)(utils_1.getDocumentNodeFromSchema);
|
package/cjs/helpers.js
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isOutputConfigArray = isOutputConfigArray;
|
|
4
|
+
exports.isConfiguredOutput = isConfiguredOutput;
|
|
5
|
+
exports.normalizeOutputParam = normalizeOutputParam;
|
|
6
|
+
exports.normalizeInstanceOrArray = normalizeInstanceOrArray;
|
|
7
|
+
exports.normalizeConfig = normalizeConfig;
|
|
8
|
+
exports.hasNullableTypeRecursively = hasNullableTypeRecursively;
|
|
9
|
+
exports.isUsingTypes = isUsingTypes;
|
|
10
|
+
exports.normalizeImportExtension = normalizeImportExtension;
|
|
11
|
+
const graphql_1 = require("graphql");
|
|
12
|
+
const utils_js_1 = require("./utils.js");
|
|
13
|
+
function isOutputConfigArray(type) {
|
|
14
|
+
return Array.isArray(type);
|
|
15
|
+
}
|
|
16
|
+
function isConfiguredOutput(type) {
|
|
17
|
+
return typeof type === 'object';
|
|
18
|
+
}
|
|
19
|
+
function normalizeOutputParam(config) {
|
|
20
|
+
// In case of direct array with a list of plugins
|
|
21
|
+
if (isOutputConfigArray(config)) {
|
|
22
|
+
return {
|
|
23
|
+
documents: [],
|
|
24
|
+
schema: [],
|
|
25
|
+
plugins: isConfiguredOutput(config) ? config.plugins : config,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
if (isConfiguredOutput(config)) {
|
|
29
|
+
return config;
|
|
30
|
+
}
|
|
31
|
+
throw new Error(`Invalid "generates" config!`);
|
|
32
|
+
}
|
|
33
|
+
function normalizeInstanceOrArray(type) {
|
|
34
|
+
if (Array.isArray(type)) {
|
|
35
|
+
return type;
|
|
36
|
+
}
|
|
37
|
+
if (!type) {
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
return [type];
|
|
41
|
+
}
|
|
42
|
+
function normalizeConfig(config) {
|
|
43
|
+
if (typeof config === 'string') {
|
|
44
|
+
return [{ [config]: {} }];
|
|
45
|
+
}
|
|
46
|
+
if (Array.isArray(config)) {
|
|
47
|
+
return config.map(plugin => (typeof plugin === 'string' ? { [plugin]: {} } : plugin));
|
|
48
|
+
}
|
|
49
|
+
if (typeof config === 'object') {
|
|
50
|
+
return Object.keys(config).reduce((prev, pluginName) => [...prev, { [pluginName]: config[pluginName] }], []);
|
|
51
|
+
}
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
function hasNullableTypeRecursively(type) {
|
|
55
|
+
if (!(0, graphql_1.isNonNullType)(type)) {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
if ((0, graphql_1.isListType)(type) || (0, graphql_1.isNonNullType)(type)) {
|
|
59
|
+
return hasNullableTypeRecursively(type.ofType);
|
|
60
|
+
}
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
function isUsingTypes(document, externalFragments, schema) {
|
|
64
|
+
let foundFields = 0;
|
|
65
|
+
const typesStack = [];
|
|
66
|
+
(0, graphql_1.visit)(document, {
|
|
67
|
+
SelectionSet: {
|
|
68
|
+
enter(node, key, parent, anscestors) {
|
|
69
|
+
const insideIgnoredFragment = anscestors.find((f) => f.kind && f.kind === 'FragmentDefinition' && externalFragments.includes(f.name.value));
|
|
70
|
+
if (insideIgnoredFragment) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const selections = node.selections || [];
|
|
74
|
+
if (schema && selections.length > 0) {
|
|
75
|
+
const nextTypeName = (() => {
|
|
76
|
+
if (parent.kind === graphql_1.Kind.FRAGMENT_DEFINITION) {
|
|
77
|
+
return parent.typeCondition.name.value;
|
|
78
|
+
}
|
|
79
|
+
if (parent.kind === graphql_1.Kind.FIELD) {
|
|
80
|
+
const lastType = typesStack[typesStack.length - 1];
|
|
81
|
+
if (!lastType) {
|
|
82
|
+
throw new Error(`Unable to find parent type! Please make sure you operation passes validation`);
|
|
83
|
+
}
|
|
84
|
+
const field = lastType.getFields()[parent.name.value];
|
|
85
|
+
if (!field) {
|
|
86
|
+
throw new Error(`Unable to find field "${parent.name.value}" on type "${lastType}"!`);
|
|
87
|
+
}
|
|
88
|
+
return (0, utils_js_1.getBaseType)(field.type).name;
|
|
89
|
+
}
|
|
90
|
+
if (parent.kind === graphql_1.Kind.OPERATION_DEFINITION) {
|
|
91
|
+
if (parent.operation === 'query') {
|
|
92
|
+
return schema.getQueryType().name;
|
|
93
|
+
}
|
|
94
|
+
if (parent.operation === 'mutation') {
|
|
95
|
+
return schema.getMutationType().name;
|
|
96
|
+
}
|
|
97
|
+
if (parent.operation === 'subscription') {
|
|
98
|
+
return schema.getSubscriptionType().name;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else if (parent.kind === graphql_1.Kind.INLINE_FRAGMENT) {
|
|
102
|
+
if (parent.typeCondition) {
|
|
103
|
+
return parent.typeCondition.name.value;
|
|
104
|
+
}
|
|
105
|
+
return typesStack[typesStack.length - 1].name;
|
|
106
|
+
}
|
|
107
|
+
return null;
|
|
108
|
+
})();
|
|
109
|
+
typesStack.push(schema.getType(nextTypeName));
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
leave(node) {
|
|
113
|
+
const selections = node.selections || [];
|
|
114
|
+
if (schema && selections.length > 0) {
|
|
115
|
+
typesStack.pop();
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
Field: {
|
|
120
|
+
enter: (node, key, parent, path, anscestors) => {
|
|
121
|
+
if (node.name.value.startsWith('__')) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const insideIgnoredFragment = anscestors.find((f) => f.kind && f.kind === 'FragmentDefinition' && externalFragments.includes(f.name.value));
|
|
125
|
+
if (insideIgnoredFragment) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const selections = node.selectionSet ? node.selectionSet.selections || [] : [];
|
|
129
|
+
const relevantFragmentSpreads = selections.filter(s => s.kind === graphql_1.Kind.FRAGMENT_SPREAD && !externalFragments.includes(s.name.value));
|
|
130
|
+
if (selections.length === 0 || relevantFragmentSpreads.length > 0) {
|
|
131
|
+
foundFields++;
|
|
132
|
+
}
|
|
133
|
+
if (schema) {
|
|
134
|
+
const lastType = typesStack[typesStack.length - 1];
|
|
135
|
+
if (lastType && (0, graphql_1.isObjectType)(lastType)) {
|
|
136
|
+
const field = lastType.getFields()[node.name.value];
|
|
137
|
+
if (!field) {
|
|
138
|
+
throw new Error(`Unable to find field "${node.name.value}" on type "${lastType}"!`);
|
|
139
|
+
}
|
|
140
|
+
const currentType = field.type;
|
|
141
|
+
// To handle `Maybe` usage
|
|
142
|
+
if (hasNullableTypeRecursively(currentType)) {
|
|
143
|
+
foundFields++;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
VariableDefinition: {
|
|
150
|
+
enter: (node, key, parent, path, anscestors) => {
|
|
151
|
+
const insideIgnoredFragment = anscestors.find((f) => f.kind && f.kind === 'FragmentDefinition' && externalFragments.includes(f.name.value));
|
|
152
|
+
if (insideIgnoredFragment) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
foundFields++;
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
InputValueDefinition: {
|
|
159
|
+
enter: (node, key, parent, path, anscestors) => {
|
|
160
|
+
const insideIgnoredFragment = anscestors.find((f) => f.kind && f.kind === 'FragmentDefinition' && externalFragments.includes(f.name.value));
|
|
161
|
+
if (insideIgnoredFragment) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
foundFields++;
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
return foundFields > 0;
|
|
169
|
+
}
|
|
170
|
+
function normalizeImportExtension({ emitLegacyCommonJSImports, importExtension, }) {
|
|
171
|
+
if (importExtension !== undefined) {
|
|
172
|
+
return importExtension;
|
|
173
|
+
}
|
|
174
|
+
if (emitLegacyCommonJSImports === undefined || emitLegacyCommonJSImports === true) {
|
|
175
|
+
return '';
|
|
176
|
+
}
|
|
177
|
+
return '.js';
|
|
178
|
+
}
|
package/cjs/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveExternalModuleAndFn = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
tslib_1.__exportStar(require("./federation.js"), exports);
|
|
6
|
+
tslib_1.__exportStar(require("./getCachedDocumentNodeFromSchema.js"), exports);
|
|
7
|
+
tslib_1.__exportStar(require("./helpers.js"), exports);
|
|
8
|
+
tslib_1.__exportStar(require("./oldVisit.js"), exports);
|
|
9
|
+
tslib_1.__exportStar(require("./profiler.js"), exports);
|
|
10
|
+
var resolve_external_module_and_fn_js_1 = require("./resolve-external-module-and-fn.js");
|
|
11
|
+
Object.defineProperty(exports, "resolveExternalModuleAndFn", { enumerable: true, get: function () { return resolve_external_module_and_fn_js_1.resolveExternalModuleAndFn; } });
|
|
12
|
+
tslib_1.__exportStar(require("./types.js"), exports);
|
|
13
|
+
tslib_1.__exportStar(require("./utils.js"), exports);
|