@theguild/federation-composition 0.1.2 → 0.1.3
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.
|
@@ -7,14 +7,18 @@ const state_js_1 = require("../../../subgraph/state.js");
|
|
|
7
7
|
const dependency_graph_js_1 = require("../../../utils/dependency-graph.js");
|
|
8
8
|
const helpers_js_2 = require("../../../utils/helpers.js");
|
|
9
9
|
const state_js_2 = require("../../../utils/state.js");
|
|
10
|
-
function
|
|
11
|
-
const
|
|
12
|
-
|
|
10
|
+
function canGraphMoveToGraphByEntity(supergraphState, entityName, sourceGraphId, targetGraphId) {
|
|
11
|
+
const objectTypeState = supergraphState.objectTypes.get(entityName);
|
|
12
|
+
if (!objectTypeState) {
|
|
13
|
+
throw new Error(`Type "${entityName}" not found in supergraph state`);
|
|
14
|
+
}
|
|
15
|
+
const objectTypeStateInSourceGraph = objectTypeState.byGraph.get(sourceGraphId);
|
|
16
|
+
const objectTypeStateInTargetGraph = objectTypeState.byGraph.get(targetGraphId);
|
|
17
|
+
const sourceGraphKeys = objectTypeStateInSourceGraph?.keys || [];
|
|
18
|
+
const targetGraphKeys = objectTypeStateInTargetGraph?.keys || [];
|
|
13
19
|
if (sourceGraphKeys.length === 0 && targetGraphKeys.length === 0) {
|
|
14
20
|
return false;
|
|
15
21
|
}
|
|
16
|
-
const fieldsOfSourceGraph = Array.from(objectTypeState.fields.values()).filter(f => f.byGraph.get(sourceGraphId));
|
|
17
|
-
const nonExternalFieldsOfSourceGraph = fieldsOfSourceGraph.filter(f => f.byGraph.get(sourceGraphId).external === false);
|
|
18
22
|
if (sourceGraphKeys.length === 0) {
|
|
19
23
|
return targetGraphKeys
|
|
20
24
|
.filter(k => k.resolvable === true)
|
|
@@ -201,31 +205,36 @@ function findLeafs(movabilityGraph, sourceId, destinationId, leafs, visited = ne
|
|
|
201
205
|
}
|
|
202
206
|
function SatisfiabilityRule(context, supergraphState) {
|
|
203
207
|
const typeDependencies = buildOutputTypesDependencies(supergraphState);
|
|
204
|
-
let
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
208
|
+
let movabilityGraph = new Map();
|
|
209
|
+
function getMovabilityGraphForType(typeName) {
|
|
210
|
+
const existingMovabilityGraph = movabilityGraph.get(typeName);
|
|
211
|
+
if (existingMovabilityGraph) {
|
|
212
|
+
return existingMovabilityGraph;
|
|
213
|
+
}
|
|
214
|
+
const objectState = supergraphState.objectTypes.get(typeName);
|
|
215
|
+
if (!objectState) {
|
|
216
|
+
throw new Error(`State of object type "${typeName}" not found in Supergraph state`);
|
|
217
|
+
}
|
|
218
|
+
const graph = new dependency_graph_js_1.DepGraph({
|
|
219
|
+
circular: true,
|
|
220
|
+
});
|
|
221
|
+
const graphIds = Array.from(objectState.byGraph.keys());
|
|
222
|
+
for (const sourceGraphId of objectState.byGraph.keys()) {
|
|
223
|
+
graph.addNode(sourceGraphId);
|
|
224
|
+
}
|
|
225
|
+
for (const sourceGraphId of objectState.byGraph.keys()) {
|
|
226
|
+
const otherGraphIds = graphIds.filter(g => g !== sourceGraphId);
|
|
227
|
+
for (const destGraphId of otherGraphIds) {
|
|
228
|
+
if (canGraphMoveToGraphByEntity(supergraphState, objectState.name, sourceGraphId, destGraphId)) {
|
|
229
|
+
graph.addDependency(sourceGraphId, destGraphId);
|
|
222
230
|
}
|
|
223
231
|
}
|
|
224
|
-
}
|
|
232
|
+
}
|
|
233
|
+
movabilityGraph.set(typeName, graph);
|
|
234
|
+
return graph;
|
|
235
|
+
}
|
|
236
|
+
return {
|
|
225
237
|
ObjectTypeField(objectState, fieldState) {
|
|
226
|
-
if (currentMovabilityGraphType !== objectState.name) {
|
|
227
|
-
throw new Error('ObjectTypeField runs before ObjectType! This should not happen.');
|
|
228
|
-
}
|
|
229
238
|
if (objectState.name === 'Query' ||
|
|
230
239
|
objectState.name === 'Mutation' ||
|
|
231
240
|
objectState.name === 'Subscription') {
|
|
@@ -286,10 +295,14 @@ function SatisfiabilityRule(context, supergraphState) {
|
|
|
286
295
|
reasons: [],
|
|
287
296
|
},
|
|
288
297
|
};
|
|
298
|
+
const currentObjectTypeMovabilityGraph = getMovabilityGraphForType(objectState.name);
|
|
299
|
+
if (!currentObjectTypeMovabilityGraph) {
|
|
300
|
+
throw new Error(`Movability graph for object type "${objectState.name}" not found in Supergraph state`);
|
|
301
|
+
}
|
|
289
302
|
if (uniqueKeyFieldsSet.size > 0) {
|
|
290
303
|
for (const graphId of objectState.byGraph.keys()) {
|
|
291
304
|
const fieldStateInGraph = fieldState.byGraph.get(graphId);
|
|
292
|
-
if (canGraphResolveField(objectState, fieldState, graphId, supergraphState,
|
|
305
|
+
if (canGraphResolveField(objectState, fieldState, graphId, supergraphState, currentObjectTypeMovabilityGraph)) {
|
|
293
306
|
continue;
|
|
294
307
|
}
|
|
295
308
|
if (fieldStateInGraph?.external === true) {
|
|
@@ -335,8 +348,11 @@ function SatisfiabilityRule(context, supergraphState) {
|
|
|
335
348
|
const graphsWithField = fieldStateGraphPairs
|
|
336
349
|
.filter(([g, _]) => canGraphResolveFieldDirectly(objectState, fieldState, g, supergraphState))
|
|
337
350
|
.map(([g, _]) => g);
|
|
338
|
-
const leafs = graphsWithField
|
|
339
|
-
|
|
351
|
+
const leafs = graphsWithField
|
|
352
|
+
.map(g => findLeafs(currentObjectTypeMovabilityGraph, graphId, g))
|
|
353
|
+
.flat(1);
|
|
354
|
+
if (leafs.length === 0 &&
|
|
355
|
+
currentObjectTypeMovabilityGraph.directDependenciesOf(graphId).length > 0) {
|
|
340
356
|
continue;
|
|
341
357
|
}
|
|
342
358
|
for (const [normalizedName, rootType] of rootTypes) {
|
|
@@ -357,7 +373,7 @@ function SatisfiabilityRule(context, supergraphState) {
|
|
|
357
373
|
})
|
|
358
374
|
.flat(1)
|
|
359
375
|
: otherGraphIds
|
|
360
|
-
.filter(g => !
|
|
376
|
+
.filter(g => !currentObjectTypeMovabilityGraph.directDependenciesOf(graphId).includes(g))
|
|
361
377
|
.map(gid => {
|
|
362
378
|
const keys = objectState.byGraph.get(gid).keys.map(k => k.fields);
|
|
363
379
|
if (keys.length > 0) {
|
|
@@ -449,6 +465,20 @@ function SatisfiabilityRule(context, supergraphState) {
|
|
|
449
465
|
if (!graphHasAtLeastOneResolvableField) {
|
|
450
466
|
continue;
|
|
451
467
|
}
|
|
468
|
+
const entityTypesReferencingLookingObject = dependenciesOfObjectType
|
|
469
|
+
.map(typeName => supergraphState.objectTypes.get(typeName))
|
|
470
|
+
.filter((t) => !!t && Array.from(t.byGraph.values()).some(tg => tg.keys.length > 0));
|
|
471
|
+
const graphIdsUnableToResolveFieldViaEntityType = [];
|
|
472
|
+
for (const [graphId] of graphsWithoutField) {
|
|
473
|
+
const localEntityTypes = entityTypesReferencingLookingObject.filter(et => et.byGraph.has(graphId));
|
|
474
|
+
const isFieldResolvableThroughEntity = localEntityTypes.some(et => graphsWithField.some(targetGraphId => canGraphMoveToGraphByEntity(supergraphState, et.name, graphId, targetGraphId)));
|
|
475
|
+
if (!isFieldResolvableThroughEntity) {
|
|
476
|
+
graphIdsUnableToResolveFieldViaEntityType.push(graphId);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
if (graphIdsUnableToResolveFieldViaEntityType.length === 0) {
|
|
480
|
+
continue;
|
|
481
|
+
}
|
|
452
482
|
const schemaDefinitionOfGraph = subgraphState.schema;
|
|
453
483
|
const rootTypes = [
|
|
454
484
|
schemaDefinitionOfGraph.queryType
|
|
@@ -4,14 +4,18 @@ import { TypeKind } from '../../../subgraph/state.js';
|
|
|
4
4
|
import { DepGraph } from '../../../utils/dependency-graph.js';
|
|
5
5
|
import { isDefined } from '../../../utils/helpers.js';
|
|
6
6
|
import { isList, isNonNull, stripNonNull, stripTypeModifiers } from '../../../utils/state.js';
|
|
7
|
-
function
|
|
8
|
-
const
|
|
9
|
-
|
|
7
|
+
function canGraphMoveToGraphByEntity(supergraphState, entityName, sourceGraphId, targetGraphId) {
|
|
8
|
+
const objectTypeState = supergraphState.objectTypes.get(entityName);
|
|
9
|
+
if (!objectTypeState) {
|
|
10
|
+
throw new Error(`Type "${entityName}" not found in supergraph state`);
|
|
11
|
+
}
|
|
12
|
+
const objectTypeStateInSourceGraph = objectTypeState.byGraph.get(sourceGraphId);
|
|
13
|
+
const objectTypeStateInTargetGraph = objectTypeState.byGraph.get(targetGraphId);
|
|
14
|
+
const sourceGraphKeys = objectTypeStateInSourceGraph?.keys || [];
|
|
15
|
+
const targetGraphKeys = objectTypeStateInTargetGraph?.keys || [];
|
|
10
16
|
if (sourceGraphKeys.length === 0 && targetGraphKeys.length === 0) {
|
|
11
17
|
return false;
|
|
12
18
|
}
|
|
13
|
-
const fieldsOfSourceGraph = Array.from(objectTypeState.fields.values()).filter(f => f.byGraph.get(sourceGraphId));
|
|
14
|
-
const nonExternalFieldsOfSourceGraph = fieldsOfSourceGraph.filter(f => f.byGraph.get(sourceGraphId).external === false);
|
|
15
19
|
if (sourceGraphKeys.length === 0) {
|
|
16
20
|
return targetGraphKeys
|
|
17
21
|
.filter(k => k.resolvable === true)
|
|
@@ -198,31 +202,36 @@ function findLeafs(movabilityGraph, sourceId, destinationId, leafs, visited = ne
|
|
|
198
202
|
}
|
|
199
203
|
export function SatisfiabilityRule(context, supergraphState) {
|
|
200
204
|
const typeDependencies = buildOutputTypesDependencies(supergraphState);
|
|
201
|
-
let
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
205
|
+
let movabilityGraph = new Map();
|
|
206
|
+
function getMovabilityGraphForType(typeName) {
|
|
207
|
+
const existingMovabilityGraph = movabilityGraph.get(typeName);
|
|
208
|
+
if (existingMovabilityGraph) {
|
|
209
|
+
return existingMovabilityGraph;
|
|
210
|
+
}
|
|
211
|
+
const objectState = supergraphState.objectTypes.get(typeName);
|
|
212
|
+
if (!objectState) {
|
|
213
|
+
throw new Error(`State of object type "${typeName}" not found in Supergraph state`);
|
|
214
|
+
}
|
|
215
|
+
const graph = new DepGraph({
|
|
216
|
+
circular: true,
|
|
217
|
+
});
|
|
218
|
+
const graphIds = Array.from(objectState.byGraph.keys());
|
|
219
|
+
for (const sourceGraphId of objectState.byGraph.keys()) {
|
|
220
|
+
graph.addNode(sourceGraphId);
|
|
221
|
+
}
|
|
222
|
+
for (const sourceGraphId of objectState.byGraph.keys()) {
|
|
223
|
+
const otherGraphIds = graphIds.filter(g => g !== sourceGraphId);
|
|
224
|
+
for (const destGraphId of otherGraphIds) {
|
|
225
|
+
if (canGraphMoveToGraphByEntity(supergraphState, objectState.name, sourceGraphId, destGraphId)) {
|
|
226
|
+
graph.addDependency(sourceGraphId, destGraphId);
|
|
219
227
|
}
|
|
220
228
|
}
|
|
221
|
-
}
|
|
229
|
+
}
|
|
230
|
+
movabilityGraph.set(typeName, graph);
|
|
231
|
+
return graph;
|
|
232
|
+
}
|
|
233
|
+
return {
|
|
222
234
|
ObjectTypeField(objectState, fieldState) {
|
|
223
|
-
if (currentMovabilityGraphType !== objectState.name) {
|
|
224
|
-
throw new Error('ObjectTypeField runs before ObjectType! This should not happen.');
|
|
225
|
-
}
|
|
226
235
|
if (objectState.name === 'Query' ||
|
|
227
236
|
objectState.name === 'Mutation' ||
|
|
228
237
|
objectState.name === 'Subscription') {
|
|
@@ -283,10 +292,14 @@ export function SatisfiabilityRule(context, supergraphState) {
|
|
|
283
292
|
reasons: [],
|
|
284
293
|
},
|
|
285
294
|
};
|
|
295
|
+
const currentObjectTypeMovabilityGraph = getMovabilityGraphForType(objectState.name);
|
|
296
|
+
if (!currentObjectTypeMovabilityGraph) {
|
|
297
|
+
throw new Error(`Movability graph for object type "${objectState.name}" not found in Supergraph state`);
|
|
298
|
+
}
|
|
286
299
|
if (uniqueKeyFieldsSet.size > 0) {
|
|
287
300
|
for (const graphId of objectState.byGraph.keys()) {
|
|
288
301
|
const fieldStateInGraph = fieldState.byGraph.get(graphId);
|
|
289
|
-
if (canGraphResolveField(objectState, fieldState, graphId, supergraphState,
|
|
302
|
+
if (canGraphResolveField(objectState, fieldState, graphId, supergraphState, currentObjectTypeMovabilityGraph)) {
|
|
290
303
|
continue;
|
|
291
304
|
}
|
|
292
305
|
if (fieldStateInGraph?.external === true) {
|
|
@@ -332,8 +345,11 @@ export function SatisfiabilityRule(context, supergraphState) {
|
|
|
332
345
|
const graphsWithField = fieldStateGraphPairs
|
|
333
346
|
.filter(([g, _]) => canGraphResolveFieldDirectly(objectState, fieldState, g, supergraphState))
|
|
334
347
|
.map(([g, _]) => g);
|
|
335
|
-
const leafs = graphsWithField
|
|
336
|
-
|
|
348
|
+
const leafs = graphsWithField
|
|
349
|
+
.map(g => findLeafs(currentObjectTypeMovabilityGraph, graphId, g))
|
|
350
|
+
.flat(1);
|
|
351
|
+
if (leafs.length === 0 &&
|
|
352
|
+
currentObjectTypeMovabilityGraph.directDependenciesOf(graphId).length > 0) {
|
|
337
353
|
continue;
|
|
338
354
|
}
|
|
339
355
|
for (const [normalizedName, rootType] of rootTypes) {
|
|
@@ -354,7 +370,7 @@ export function SatisfiabilityRule(context, supergraphState) {
|
|
|
354
370
|
})
|
|
355
371
|
.flat(1)
|
|
356
372
|
: otherGraphIds
|
|
357
|
-
.filter(g => !
|
|
373
|
+
.filter(g => !currentObjectTypeMovabilityGraph.directDependenciesOf(graphId).includes(g))
|
|
358
374
|
.map(gid => {
|
|
359
375
|
const keys = objectState.byGraph.get(gid).keys.map(k => k.fields);
|
|
360
376
|
if (keys.length > 0) {
|
|
@@ -446,6 +462,20 @@ export function SatisfiabilityRule(context, supergraphState) {
|
|
|
446
462
|
if (!graphHasAtLeastOneResolvableField) {
|
|
447
463
|
continue;
|
|
448
464
|
}
|
|
465
|
+
const entityTypesReferencingLookingObject = dependenciesOfObjectType
|
|
466
|
+
.map(typeName => supergraphState.objectTypes.get(typeName))
|
|
467
|
+
.filter((t) => !!t && Array.from(t.byGraph.values()).some(tg => tg.keys.length > 0));
|
|
468
|
+
const graphIdsUnableToResolveFieldViaEntityType = [];
|
|
469
|
+
for (const [graphId] of graphsWithoutField) {
|
|
470
|
+
const localEntityTypes = entityTypesReferencingLookingObject.filter(et => et.byGraph.has(graphId));
|
|
471
|
+
const isFieldResolvableThroughEntity = localEntityTypes.some(et => graphsWithField.some(targetGraphId => canGraphMoveToGraphByEntity(supergraphState, et.name, graphId, targetGraphId)));
|
|
472
|
+
if (!isFieldResolvableThroughEntity) {
|
|
473
|
+
graphIdsUnableToResolveFieldViaEntityType.push(graphId);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
if (graphIdsUnableToResolveFieldViaEntityType.length === 0) {
|
|
477
|
+
continue;
|
|
478
|
+
}
|
|
449
479
|
const schemaDefinitionOfGraph = subgraphState.schema;
|
|
450
480
|
const rootTypes = [
|
|
451
481
|
schemaDefinitionOfGraph.queryType
|