@graphql-mesh/fusion-composition 0.9.1 → 0.9.2

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.
@@ -12,12 +12,12 @@ function addInaccessibleDirective(directableObj) {
12
12
  extensions.directives = directives;
13
13
  directableObj.astNode = undefined;
14
14
  }
15
- function compareAndAddInaccessibleDirective(originalSchema, filteredSchema) {
15
+ function compareAndAddInaccessibleDirective(originalSchema, filteredSchema, typesMadeUnreachable) {
16
16
  const rootTypeNames = (0, utils_1.getRootTypeNames)(originalSchema);
17
17
  return (0, utils_1.mapSchema)(originalSchema, {
18
18
  [utils_1.MapperKind.TYPE]: type => {
19
19
  const typeInFiltered = filteredSchema.getType(type.name);
20
- if (!typeInFiltered) {
20
+ if (!typeInFiltered || typesMadeUnreachable.has(type.name)) {
21
21
  addInaccessibleDirective(type);
22
22
  }
23
23
  else if ('getFields' in type) {
@@ -198,6 +198,22 @@ filters, filterDeprecatedTypes, filterDeprecatedFields,
198
198
  };
199
199
  }
200
200
  return function filterTransform(schema) {
201
- return compareAndAddInaccessibleDirective(schema, (0, utils_1.mapSchema)(schema, schemaMapper));
201
+ const rootTypeNames = (0, utils_1.getRootTypeNames)(schema);
202
+ // keep empty root types around since composition handles their inaccessible fields
203
+ const pruneOptions = {
204
+ skipPruning: type => rootTypeNames.has(type.name),
205
+ };
206
+ // apply the requested filters structurally in a temporary schema
207
+ const filteredSchema = (0, utils_1.mapSchema)(schema, schemaMapper);
208
+ // prune both versions to find types disconnected specifically by those filters
209
+ const reachableOriginalSchema = (0, utils_1.pruneSchema)(schema, pruneOptions);
210
+ const reachableFilteredSchema = (0, utils_1.pruneSchema)(filteredSchema, pruneOptions);
211
+ const typesMadeUnreachable = new Set(Object.values(reachableOriginalSchema.getTypeMap())
212
+ .filter(type => !rootTypeNames.has(type.name) && // do not filter out root types ever
213
+ !(0, graphql_1.isEnumType)(type) && // federation validates enum defaults before removing inaccessible fields, so keep enums public
214
+ !reachableFilteredSchema.getType(type.name))
215
+ .map(type => type.name));
216
+ // preserve the executable schema and hide filtered fields and newly orphaned types from clients
217
+ return compareAndAddInaccessibleDirective(schema, filteredSchema, typesMadeUnreachable);
202
218
  };
203
219
  }
@@ -1,6 +1,6 @@
1
- import { isNonNullType, } from 'graphql';
1
+ import { isEnumType, isNonNullType, } from 'graphql';
2
2
  import { Minimatch } from 'minimatch';
3
- import { getDirectiveExtensions, getRootTypeNames, MapperKind, mapSchema, } from '@graphql-tools/utils';
3
+ import { getDirectiveExtensions, getRootTypeNames, MapperKind, mapSchema, pruneSchema, } from '@graphql-tools/utils';
4
4
  export function addInaccessibleDirective(directableObj) {
5
5
  const directives = getDirectiveExtensions(directableObj);
6
6
  directives.inaccessible = [{}];
@@ -8,12 +8,12 @@ export function addInaccessibleDirective(directableObj) {
8
8
  extensions.directives = directives;
9
9
  directableObj.astNode = undefined;
10
10
  }
11
- function compareAndAddInaccessibleDirective(originalSchema, filteredSchema) {
11
+ function compareAndAddInaccessibleDirective(originalSchema, filteredSchema, typesMadeUnreachable) {
12
12
  const rootTypeNames = getRootTypeNames(originalSchema);
13
13
  return mapSchema(originalSchema, {
14
14
  [MapperKind.TYPE]: type => {
15
15
  const typeInFiltered = filteredSchema.getType(type.name);
16
- if (!typeInFiltered) {
16
+ if (!typeInFiltered || typesMadeUnreachable.has(type.name)) {
17
17
  addInaccessibleDirective(type);
18
18
  }
19
19
  else if ('getFields' in type) {
@@ -194,6 +194,22 @@ filters, filterDeprecatedTypes, filterDeprecatedFields,
194
194
  };
195
195
  }
196
196
  return function filterTransform(schema) {
197
- return compareAndAddInaccessibleDirective(schema, mapSchema(schema, schemaMapper));
197
+ const rootTypeNames = getRootTypeNames(schema);
198
+ // keep empty root types around since composition handles their inaccessible fields
199
+ const pruneOptions = {
200
+ skipPruning: type => rootTypeNames.has(type.name),
201
+ };
202
+ // apply the requested filters structurally in a temporary schema
203
+ const filteredSchema = mapSchema(schema, schemaMapper);
204
+ // prune both versions to find types disconnected specifically by those filters
205
+ const reachableOriginalSchema = pruneSchema(schema, pruneOptions);
206
+ const reachableFilteredSchema = pruneSchema(filteredSchema, pruneOptions);
207
+ const typesMadeUnreachable = new Set(Object.values(reachableOriginalSchema.getTypeMap())
208
+ .filter(type => !rootTypeNames.has(type.name) && // do not filter out root types ever
209
+ !isEnumType(type) && // federation validates enum defaults before removing inaccessible fields, so keep enums public
210
+ !reachableFilteredSchema.getType(type.name))
211
+ .map(type => type.name));
212
+ // preserve the executable schema and hide filtered fields and newly orphaned types from clients
213
+ return compareAndAddInaccessibleDirective(schema, filteredSchema, typesMadeUnreachable);
198
214
  };
199
215
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graphql-mesh/fusion-composition",
3
- "version": "0.9.1",
3
+ "version": "0.9.2",
4
4
  "description": "Basic composition utility for Fusion spec",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {