@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 canGraphMoveToGraph(supergraphState, objectTypeState, sourceGraphId, targetGraphId) {
11
- const sourceGraphKeys = objectTypeState.byGraph.get(sourceGraphId).keys;
12
- const targetGraphKeys = objectTypeState.byGraph.get(targetGraphId).keys;
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 currentMovabilityGraphType;
205
- let movabilityGraph;
206
- return {
207
- ObjectType(objectState) {
208
- currentMovabilityGraphType = objectState.name;
209
- movabilityGraph = new dependency_graph_js_1.DepGraph({
210
- circular: true,
211
- });
212
- const graphIds = Array.from(objectState.byGraph.keys());
213
- for (const sourceGraphId of objectState.byGraph.keys()) {
214
- movabilityGraph.addNode(sourceGraphId);
215
- }
216
- for (const sourceGraphId of objectState.byGraph.keys()) {
217
- const otherGraphIds = graphIds.filter(g => g !== sourceGraphId);
218
- for (const destGraphId of otherGraphIds) {
219
- if (canGraphMoveToGraph(supergraphState, objectState, sourceGraphId, destGraphId)) {
220
- movabilityGraph.addDependency(sourceGraphId, destGraphId);
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, movabilityGraph)) {
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.map(g => findLeafs(movabilityGraph, graphId, g)).flat(1);
339
- if (leafs.length === 0 && movabilityGraph.directDependenciesOf(graphId).length > 0) {
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 => !movabilityGraph.directDependenciesOf(graphId).includes(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 canGraphMoveToGraph(supergraphState, objectTypeState, sourceGraphId, targetGraphId) {
8
- const sourceGraphKeys = objectTypeState.byGraph.get(sourceGraphId).keys;
9
- const targetGraphKeys = objectTypeState.byGraph.get(targetGraphId).keys;
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 currentMovabilityGraphType;
202
- let movabilityGraph;
203
- return {
204
- ObjectType(objectState) {
205
- currentMovabilityGraphType = objectState.name;
206
- movabilityGraph = new DepGraph({
207
- circular: true,
208
- });
209
- const graphIds = Array.from(objectState.byGraph.keys());
210
- for (const sourceGraphId of objectState.byGraph.keys()) {
211
- movabilityGraph.addNode(sourceGraphId);
212
- }
213
- for (const sourceGraphId of objectState.byGraph.keys()) {
214
- const otherGraphIds = graphIds.filter(g => g !== sourceGraphId);
215
- for (const destGraphId of otherGraphIds) {
216
- if (canGraphMoveToGraph(supergraphState, objectState, sourceGraphId, destGraphId)) {
217
- movabilityGraph.addDependency(sourceGraphId, destGraphId);
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, movabilityGraph)) {
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.map(g => findLeafs(movabilityGraph, graphId, g)).flat(1);
336
- if (leafs.length === 0 && movabilityGraph.directDependenciesOf(graphId).length > 0) {
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 => !movabilityGraph.directDependenciesOf(graphId).includes(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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theguild/federation-composition",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Open Source Composition library for Apollo Federation",
5
5
  "peerDependencies": {
6
6
  "graphql": "^16.0.0"