@graphql-tools/utils 8.6.7 → 8.6.10
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/index.js +107 -139
- package/index.mjs +107 -139
- package/package.json +2 -2
package/index.js
CHANGED
|
@@ -3220,155 +3220,123 @@ function addTypes(schema, newTypesOrDirectives) {
|
|
|
3220
3220
|
* @param options Additional options for removing unused types from the schema
|
|
3221
3221
|
*/
|
|
3222
3222
|
function pruneSchema(schema, options = {}) {
|
|
3223
|
-
const
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
(
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
}
|
|
3241
|
-
else if (graphql.isUnionType(type)) {
|
|
3242
|
-
if ((!type.getTypes().length && !options.skipEmptyUnionPruning) ||
|
|
3243
|
-
(pruningContext.unusedTypes[type.name] && !options.skipUnusedTypesPruning)) {
|
|
3244
|
-
typesToPrune.add(type.name);
|
|
3245
|
-
}
|
|
3246
|
-
}
|
|
3247
|
-
else if (graphql.isInterfaceType(type)) {
|
|
3248
|
-
const implementations = getImplementations(pruningContext, type);
|
|
3249
|
-
if ((!Object.keys(type.getFields()).length && !options.skipEmptyCompositeTypePruning) ||
|
|
3250
|
-
(implementations && !Object.keys(implementations).length && !options.skipUnimplementedInterfacesPruning) ||
|
|
3251
|
-
(pruningContext.unusedTypes[type.name] && !options.skipUnusedTypesPruning)) {
|
|
3252
|
-
typesToPrune.add(type.name);
|
|
3223
|
+
const { skipEmptyCompositeTypePruning, skipEmptyUnionPruning, skipPruning, skipUnimplementedInterfacesPruning, skipUnusedTypesPruning, } = options;
|
|
3224
|
+
let prunedTypes = []; // Pruned types during mapping
|
|
3225
|
+
let prunedSchema = schema;
|
|
3226
|
+
do {
|
|
3227
|
+
let visited = visitSchema(prunedSchema);
|
|
3228
|
+
// Custom pruning was defined, so we need to pre-emptively revisit the schema accounting for this
|
|
3229
|
+
if (skipPruning) {
|
|
3230
|
+
const revisit = [];
|
|
3231
|
+
for (const typeName in prunedSchema.getTypeMap()) {
|
|
3232
|
+
if (typeName.startsWith('__')) {
|
|
3233
|
+
continue;
|
|
3234
|
+
}
|
|
3235
|
+
const type = prunedSchema.getType(typeName);
|
|
3236
|
+
// if we want to skip pruning for this type, add it to the list of types to revisit
|
|
3237
|
+
if (type && skipPruning(type)) {
|
|
3238
|
+
revisit.push(typeName);
|
|
3239
|
+
}
|
|
3253
3240
|
}
|
|
3241
|
+
visited = visitQueue(revisit, prunedSchema, visited); // visit again
|
|
3242
|
+
}
|
|
3243
|
+
prunedTypes = [];
|
|
3244
|
+
prunedSchema = mapSchema(prunedSchema, {
|
|
3245
|
+
[exports.MapperKind.TYPE]: type => {
|
|
3246
|
+
if (!visited.has(type.name) && !graphql.isSpecifiedScalarType(type)) {
|
|
3247
|
+
if (graphql.isUnionType(type) ||
|
|
3248
|
+
graphql.isInputObjectType(type) ||
|
|
3249
|
+
graphql.isInterfaceType(type) ||
|
|
3250
|
+
graphql.isObjectType(type) ||
|
|
3251
|
+
graphql.isScalarType(type)) {
|
|
3252
|
+
// skipUnusedTypesPruning: skip pruning unused types
|
|
3253
|
+
if (skipUnusedTypesPruning) {
|
|
3254
|
+
return type;
|
|
3255
|
+
}
|
|
3256
|
+
// skipEmptyUnionPruning: skip pruning empty unions
|
|
3257
|
+
if (graphql.isUnionType(type) && skipEmptyUnionPruning && !Object.keys(type.getTypes()).length) {
|
|
3258
|
+
return type;
|
|
3259
|
+
}
|
|
3260
|
+
if (graphql.isInputObjectType(type) || graphql.isInterfaceType(type) || graphql.isObjectType(type)) {
|
|
3261
|
+
// skipEmptyCompositeTypePruning: skip pruning object types or interfaces with no fields
|
|
3262
|
+
if (skipEmptyCompositeTypePruning && !Object.keys(type.getFields()).length) {
|
|
3263
|
+
return type;
|
|
3264
|
+
}
|
|
3265
|
+
}
|
|
3266
|
+
// skipUnimplementedInterfacesPruning: skip pruning interfaces that are not implemented by any other types
|
|
3267
|
+
if (graphql.isInterfaceType(type) && skipUnimplementedInterfacesPruning) {
|
|
3268
|
+
return type;
|
|
3269
|
+
}
|
|
3270
|
+
}
|
|
3271
|
+
prunedTypes.push(type.name);
|
|
3272
|
+
visited.delete(type.name);
|
|
3273
|
+
return null;
|
|
3274
|
+
}
|
|
3275
|
+
return type;
|
|
3276
|
+
},
|
|
3277
|
+
});
|
|
3278
|
+
} while (prunedTypes.length); // Might have empty types and need to prune again
|
|
3279
|
+
return prunedSchema;
|
|
3280
|
+
}
|
|
3281
|
+
function visitSchema(schema) {
|
|
3282
|
+
const queue = []; // queue of nodes to visit
|
|
3283
|
+
// Grab the root types and start there
|
|
3284
|
+
for (const type of getRootTypes(schema)) {
|
|
3285
|
+
queue.push(type.name);
|
|
3286
|
+
}
|
|
3287
|
+
return visitQueue(queue, schema);
|
|
3288
|
+
}
|
|
3289
|
+
function visitQueue(queue, schema, visited = new Set()) {
|
|
3290
|
+
// Interfaces encountered that are field return types need to be revisited to add their implementations
|
|
3291
|
+
const revisit = new Map();
|
|
3292
|
+
// Navigate all types starting with pre-queued types (root types)
|
|
3293
|
+
while (queue.length) {
|
|
3294
|
+
const typeName = queue.pop();
|
|
3295
|
+
// Skip types we already visited unless it is an interface type that needs revisiting
|
|
3296
|
+
if (visited.has(typeName) && revisit[typeName] !== true) {
|
|
3297
|
+
continue;
|
|
3254
3298
|
}
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3299
|
+
const type = schema.getType(typeName);
|
|
3300
|
+
if (type) {
|
|
3301
|
+
// Get types for union
|
|
3302
|
+
if (graphql.isUnionType(type)) {
|
|
3303
|
+
queue.push(...type.getTypes().map(type => type.name));
|
|
3258
3304
|
}
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
if (typesToPrune.has(type.name)) {
|
|
3265
|
-
return null;
|
|
3305
|
+
// If it is an interface and it is a returned type, grab all implementations so we can use proper __typename in fragments
|
|
3306
|
+
if (graphql.isInterfaceType(type) && revisit[typeName] === true) {
|
|
3307
|
+
queue.push(...getImplementingTypes(type.name, schema));
|
|
3308
|
+
// No need to revisit this interface again
|
|
3309
|
+
revisit[typeName] = false;
|
|
3266
3310
|
}
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
}
|
|
3272
|
-
function visitOutputType(visitedTypes, pruningContext, type) {
|
|
3273
|
-
if (visitedTypes[type.name]) {
|
|
3274
|
-
return;
|
|
3275
|
-
}
|
|
3276
|
-
visitedTypes[type.name] = true;
|
|
3277
|
-
pruningContext.unusedTypes[type.name] = false;
|
|
3278
|
-
if (graphql.isObjectType(type) || graphql.isInterfaceType(type)) {
|
|
3279
|
-
const fields = type.getFields();
|
|
3280
|
-
for (const fieldName in fields) {
|
|
3281
|
-
const field = fields[fieldName];
|
|
3282
|
-
const namedType = graphql.getNamedType(field.type);
|
|
3283
|
-
visitOutputType(visitedTypes, pruningContext, namedType);
|
|
3284
|
-
for (const arg of field.args) {
|
|
3285
|
-
const type = graphql.getNamedType(arg.type);
|
|
3286
|
-
visitInputType(visitedTypes, pruningContext, type);
|
|
3311
|
+
// Visit interfaces this type is implementing if they haven't been visited yet
|
|
3312
|
+
if ('getInterfaces' in type) {
|
|
3313
|
+
// Only pushes to queue to visit but not return types
|
|
3314
|
+
queue.push(...type.getInterfaces().map(iface => iface.name));
|
|
3287
3315
|
}
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3316
|
+
// If the type has files visit those field types
|
|
3317
|
+
if ('getFields' in type) {
|
|
3318
|
+
const fields = type.getFields();
|
|
3319
|
+
const entries = Object.entries(fields);
|
|
3320
|
+
if (!entries.length) {
|
|
3321
|
+
continue;
|
|
3294
3322
|
}
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
visitOutputType(visitedTypes, pruningContext, type);
|
|
3307
|
-
}
|
|
3308
|
-
}
|
|
3309
|
-
}
|
|
3310
|
-
/**
|
|
3311
|
-
* Initialize a pruneContext given a schema.
|
|
3312
|
-
*/
|
|
3313
|
-
function createPruningContext(schema) {
|
|
3314
|
-
const pruningContext = {
|
|
3315
|
-
schema,
|
|
3316
|
-
unusedTypes: Object.create(null),
|
|
3317
|
-
implementations: Object.create(null),
|
|
3318
|
-
};
|
|
3319
|
-
for (const typeName in schema.getTypeMap()) {
|
|
3320
|
-
const type = schema.getType(typeName);
|
|
3321
|
-
if (type && 'getInterfaces' in type) {
|
|
3322
|
-
for (const iface of type.getInterfaces()) {
|
|
3323
|
-
const implementations = getImplementations(pruningContext, iface);
|
|
3324
|
-
if (implementations == null) {
|
|
3325
|
-
pruningContext.implementations[iface.name] = Object.create(null);
|
|
3323
|
+
for (const [, field] of entries) {
|
|
3324
|
+
if (graphql.isObjectType(type)) {
|
|
3325
|
+
// Visit arg types
|
|
3326
|
+
queue.push(...field.args.map(arg => graphql.getNamedType(arg.type).name));
|
|
3327
|
+
}
|
|
3328
|
+
const namedType = graphql.getNamedType(field.type);
|
|
3329
|
+
queue.push(namedType.name);
|
|
3330
|
+
// Interfaces returned on fields need to be revisited to add their implementations
|
|
3331
|
+
if (graphql.isInterfaceType(namedType) && !(namedType.name in revisit)) {
|
|
3332
|
+
revisit[namedType.name] = true;
|
|
3333
|
+
}
|
|
3326
3334
|
}
|
|
3327
|
-
pruningContext.implementations[iface.name][type.name] = true;
|
|
3328
3335
|
}
|
|
3336
|
+
visited.add(typeName); // Mark as visited (and therefore it is used and should be kept)
|
|
3329
3337
|
}
|
|
3330
3338
|
}
|
|
3331
|
-
return
|
|
3332
|
-
}
|
|
3333
|
-
/**
|
|
3334
|
-
* Get the implementations of an interface. May return undefined.
|
|
3335
|
-
*/
|
|
3336
|
-
function getImplementations(pruningContext, type) {
|
|
3337
|
-
return pruningContext.implementations[type.name];
|
|
3338
|
-
}
|
|
3339
|
-
function visitInputType(visitedTypes, pruningContext, type) {
|
|
3340
|
-
if (visitedTypes[type.name]) {
|
|
3341
|
-
return;
|
|
3342
|
-
}
|
|
3343
|
-
pruningContext.unusedTypes[type.name] = false;
|
|
3344
|
-
visitedTypes[type.name] = true;
|
|
3345
|
-
if (graphql.isInputObjectType(type)) {
|
|
3346
|
-
const fields = type.getFields();
|
|
3347
|
-
for (const fieldName in fields) {
|
|
3348
|
-
const field = fields[fieldName];
|
|
3349
|
-
const namedType = graphql.getNamedType(field.type);
|
|
3350
|
-
visitInputType(visitedTypes, pruningContext, namedType);
|
|
3351
|
-
}
|
|
3352
|
-
}
|
|
3353
|
-
}
|
|
3354
|
-
function visitTypes(pruningContext) {
|
|
3355
|
-
const schema = pruningContext.schema;
|
|
3356
|
-
for (const typeName in schema.getTypeMap()) {
|
|
3357
|
-
if (!typeName.startsWith('__')) {
|
|
3358
|
-
pruningContext.unusedTypes[typeName] = true;
|
|
3359
|
-
}
|
|
3360
|
-
}
|
|
3361
|
-
const visitedTypes = Object.create(null);
|
|
3362
|
-
const rootTypes = getRootTypes(schema);
|
|
3363
|
-
for (const rootType of rootTypes) {
|
|
3364
|
-
visitOutputType(visitedTypes, pruningContext, rootType);
|
|
3365
|
-
}
|
|
3366
|
-
for (const directive of schema.getDirectives()) {
|
|
3367
|
-
for (const arg of directive.args) {
|
|
3368
|
-
const type = graphql.getNamedType(arg.type);
|
|
3369
|
-
visitInputType(visitedTypes, pruningContext, type);
|
|
3370
|
-
}
|
|
3371
|
-
}
|
|
3339
|
+
return visited;
|
|
3372
3340
|
}
|
|
3373
3341
|
|
|
3374
3342
|
function mergeDeep(sources, respectPrototype = false) {
|
package/index.mjs
CHANGED
|
@@ -3218,155 +3218,123 @@ function addTypes(schema, newTypesOrDirectives) {
|
|
|
3218
3218
|
* @param options Additional options for removing unused types from the schema
|
|
3219
3219
|
*/
|
|
3220
3220
|
function pruneSchema(schema, options = {}) {
|
|
3221
|
-
const
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
(
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
}
|
|
3239
|
-
else if (isUnionType(type)) {
|
|
3240
|
-
if ((!type.getTypes().length && !options.skipEmptyUnionPruning) ||
|
|
3241
|
-
(pruningContext.unusedTypes[type.name] && !options.skipUnusedTypesPruning)) {
|
|
3242
|
-
typesToPrune.add(type.name);
|
|
3243
|
-
}
|
|
3244
|
-
}
|
|
3245
|
-
else if (isInterfaceType(type)) {
|
|
3246
|
-
const implementations = getImplementations(pruningContext, type);
|
|
3247
|
-
if ((!Object.keys(type.getFields()).length && !options.skipEmptyCompositeTypePruning) ||
|
|
3248
|
-
(implementations && !Object.keys(implementations).length && !options.skipUnimplementedInterfacesPruning) ||
|
|
3249
|
-
(pruningContext.unusedTypes[type.name] && !options.skipUnusedTypesPruning)) {
|
|
3250
|
-
typesToPrune.add(type.name);
|
|
3221
|
+
const { skipEmptyCompositeTypePruning, skipEmptyUnionPruning, skipPruning, skipUnimplementedInterfacesPruning, skipUnusedTypesPruning, } = options;
|
|
3222
|
+
let prunedTypes = []; // Pruned types during mapping
|
|
3223
|
+
let prunedSchema = schema;
|
|
3224
|
+
do {
|
|
3225
|
+
let visited = visitSchema(prunedSchema);
|
|
3226
|
+
// Custom pruning was defined, so we need to pre-emptively revisit the schema accounting for this
|
|
3227
|
+
if (skipPruning) {
|
|
3228
|
+
const revisit = [];
|
|
3229
|
+
for (const typeName in prunedSchema.getTypeMap()) {
|
|
3230
|
+
if (typeName.startsWith('__')) {
|
|
3231
|
+
continue;
|
|
3232
|
+
}
|
|
3233
|
+
const type = prunedSchema.getType(typeName);
|
|
3234
|
+
// if we want to skip pruning for this type, add it to the list of types to revisit
|
|
3235
|
+
if (type && skipPruning(type)) {
|
|
3236
|
+
revisit.push(typeName);
|
|
3237
|
+
}
|
|
3251
3238
|
}
|
|
3239
|
+
visited = visitQueue(revisit, prunedSchema, visited); // visit again
|
|
3240
|
+
}
|
|
3241
|
+
prunedTypes = [];
|
|
3242
|
+
prunedSchema = mapSchema(prunedSchema, {
|
|
3243
|
+
[MapperKind.TYPE]: type => {
|
|
3244
|
+
if (!visited.has(type.name) && !isSpecifiedScalarType(type)) {
|
|
3245
|
+
if (isUnionType(type) ||
|
|
3246
|
+
isInputObjectType(type) ||
|
|
3247
|
+
isInterfaceType(type) ||
|
|
3248
|
+
isObjectType(type) ||
|
|
3249
|
+
isScalarType(type)) {
|
|
3250
|
+
// skipUnusedTypesPruning: skip pruning unused types
|
|
3251
|
+
if (skipUnusedTypesPruning) {
|
|
3252
|
+
return type;
|
|
3253
|
+
}
|
|
3254
|
+
// skipEmptyUnionPruning: skip pruning empty unions
|
|
3255
|
+
if (isUnionType(type) && skipEmptyUnionPruning && !Object.keys(type.getTypes()).length) {
|
|
3256
|
+
return type;
|
|
3257
|
+
}
|
|
3258
|
+
if (isInputObjectType(type) || isInterfaceType(type) || isObjectType(type)) {
|
|
3259
|
+
// skipEmptyCompositeTypePruning: skip pruning object types or interfaces with no fields
|
|
3260
|
+
if (skipEmptyCompositeTypePruning && !Object.keys(type.getFields()).length) {
|
|
3261
|
+
return type;
|
|
3262
|
+
}
|
|
3263
|
+
}
|
|
3264
|
+
// skipUnimplementedInterfacesPruning: skip pruning interfaces that are not implemented by any other types
|
|
3265
|
+
if (isInterfaceType(type) && skipUnimplementedInterfacesPruning) {
|
|
3266
|
+
return type;
|
|
3267
|
+
}
|
|
3268
|
+
}
|
|
3269
|
+
prunedTypes.push(type.name);
|
|
3270
|
+
visited.delete(type.name);
|
|
3271
|
+
return null;
|
|
3272
|
+
}
|
|
3273
|
+
return type;
|
|
3274
|
+
},
|
|
3275
|
+
});
|
|
3276
|
+
} while (prunedTypes.length); // Might have empty types and need to prune again
|
|
3277
|
+
return prunedSchema;
|
|
3278
|
+
}
|
|
3279
|
+
function visitSchema(schema) {
|
|
3280
|
+
const queue = []; // queue of nodes to visit
|
|
3281
|
+
// Grab the root types and start there
|
|
3282
|
+
for (const type of getRootTypes(schema)) {
|
|
3283
|
+
queue.push(type.name);
|
|
3284
|
+
}
|
|
3285
|
+
return visitQueue(queue, schema);
|
|
3286
|
+
}
|
|
3287
|
+
function visitQueue(queue, schema, visited = new Set()) {
|
|
3288
|
+
// Interfaces encountered that are field return types need to be revisited to add their implementations
|
|
3289
|
+
const revisit = new Map();
|
|
3290
|
+
// Navigate all types starting with pre-queued types (root types)
|
|
3291
|
+
while (queue.length) {
|
|
3292
|
+
const typeName = queue.pop();
|
|
3293
|
+
// Skip types we already visited unless it is an interface type that needs revisiting
|
|
3294
|
+
if (visited.has(typeName) && revisit[typeName] !== true) {
|
|
3295
|
+
continue;
|
|
3252
3296
|
}
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3297
|
+
const type = schema.getType(typeName);
|
|
3298
|
+
if (type) {
|
|
3299
|
+
// Get types for union
|
|
3300
|
+
if (isUnionType(type)) {
|
|
3301
|
+
queue.push(...type.getTypes().map(type => type.name));
|
|
3256
3302
|
}
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
if (typesToPrune.has(type.name)) {
|
|
3263
|
-
return null;
|
|
3303
|
+
// If it is an interface and it is a returned type, grab all implementations so we can use proper __typename in fragments
|
|
3304
|
+
if (isInterfaceType(type) && revisit[typeName] === true) {
|
|
3305
|
+
queue.push(...getImplementingTypes(type.name, schema));
|
|
3306
|
+
// No need to revisit this interface again
|
|
3307
|
+
revisit[typeName] = false;
|
|
3264
3308
|
}
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
}
|
|
3270
|
-
function visitOutputType(visitedTypes, pruningContext, type) {
|
|
3271
|
-
if (visitedTypes[type.name]) {
|
|
3272
|
-
return;
|
|
3273
|
-
}
|
|
3274
|
-
visitedTypes[type.name] = true;
|
|
3275
|
-
pruningContext.unusedTypes[type.name] = false;
|
|
3276
|
-
if (isObjectType(type) || isInterfaceType(type)) {
|
|
3277
|
-
const fields = type.getFields();
|
|
3278
|
-
for (const fieldName in fields) {
|
|
3279
|
-
const field = fields[fieldName];
|
|
3280
|
-
const namedType = getNamedType(field.type);
|
|
3281
|
-
visitOutputType(visitedTypes, pruningContext, namedType);
|
|
3282
|
-
for (const arg of field.args) {
|
|
3283
|
-
const type = getNamedType(arg.type);
|
|
3284
|
-
visitInputType(visitedTypes, pruningContext, type);
|
|
3309
|
+
// Visit interfaces this type is implementing if they haven't been visited yet
|
|
3310
|
+
if ('getInterfaces' in type) {
|
|
3311
|
+
// Only pushes to queue to visit but not return types
|
|
3312
|
+
queue.push(...type.getInterfaces().map(iface => iface.name));
|
|
3285
3313
|
}
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3314
|
+
// If the type has files visit those field types
|
|
3315
|
+
if ('getFields' in type) {
|
|
3316
|
+
const fields = type.getFields();
|
|
3317
|
+
const entries = Object.entries(fields);
|
|
3318
|
+
if (!entries.length) {
|
|
3319
|
+
continue;
|
|
3292
3320
|
}
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
visitOutputType(visitedTypes, pruningContext, type);
|
|
3305
|
-
}
|
|
3306
|
-
}
|
|
3307
|
-
}
|
|
3308
|
-
/**
|
|
3309
|
-
* Initialize a pruneContext given a schema.
|
|
3310
|
-
*/
|
|
3311
|
-
function createPruningContext(schema) {
|
|
3312
|
-
const pruningContext = {
|
|
3313
|
-
schema,
|
|
3314
|
-
unusedTypes: Object.create(null),
|
|
3315
|
-
implementations: Object.create(null),
|
|
3316
|
-
};
|
|
3317
|
-
for (const typeName in schema.getTypeMap()) {
|
|
3318
|
-
const type = schema.getType(typeName);
|
|
3319
|
-
if (type && 'getInterfaces' in type) {
|
|
3320
|
-
for (const iface of type.getInterfaces()) {
|
|
3321
|
-
const implementations = getImplementations(pruningContext, iface);
|
|
3322
|
-
if (implementations == null) {
|
|
3323
|
-
pruningContext.implementations[iface.name] = Object.create(null);
|
|
3321
|
+
for (const [, field] of entries) {
|
|
3322
|
+
if (isObjectType(type)) {
|
|
3323
|
+
// Visit arg types
|
|
3324
|
+
queue.push(...field.args.map(arg => getNamedType(arg.type).name));
|
|
3325
|
+
}
|
|
3326
|
+
const namedType = getNamedType(field.type);
|
|
3327
|
+
queue.push(namedType.name);
|
|
3328
|
+
// Interfaces returned on fields need to be revisited to add their implementations
|
|
3329
|
+
if (isInterfaceType(namedType) && !(namedType.name in revisit)) {
|
|
3330
|
+
revisit[namedType.name] = true;
|
|
3331
|
+
}
|
|
3324
3332
|
}
|
|
3325
|
-
pruningContext.implementations[iface.name][type.name] = true;
|
|
3326
3333
|
}
|
|
3334
|
+
visited.add(typeName); // Mark as visited (and therefore it is used and should be kept)
|
|
3327
3335
|
}
|
|
3328
3336
|
}
|
|
3329
|
-
return
|
|
3330
|
-
}
|
|
3331
|
-
/**
|
|
3332
|
-
* Get the implementations of an interface. May return undefined.
|
|
3333
|
-
*/
|
|
3334
|
-
function getImplementations(pruningContext, type) {
|
|
3335
|
-
return pruningContext.implementations[type.name];
|
|
3336
|
-
}
|
|
3337
|
-
function visitInputType(visitedTypes, pruningContext, type) {
|
|
3338
|
-
if (visitedTypes[type.name]) {
|
|
3339
|
-
return;
|
|
3340
|
-
}
|
|
3341
|
-
pruningContext.unusedTypes[type.name] = false;
|
|
3342
|
-
visitedTypes[type.name] = true;
|
|
3343
|
-
if (isInputObjectType(type)) {
|
|
3344
|
-
const fields = type.getFields();
|
|
3345
|
-
for (const fieldName in fields) {
|
|
3346
|
-
const field = fields[fieldName];
|
|
3347
|
-
const namedType = getNamedType(field.type);
|
|
3348
|
-
visitInputType(visitedTypes, pruningContext, namedType);
|
|
3349
|
-
}
|
|
3350
|
-
}
|
|
3351
|
-
}
|
|
3352
|
-
function visitTypes(pruningContext) {
|
|
3353
|
-
const schema = pruningContext.schema;
|
|
3354
|
-
for (const typeName in schema.getTypeMap()) {
|
|
3355
|
-
if (!typeName.startsWith('__')) {
|
|
3356
|
-
pruningContext.unusedTypes[typeName] = true;
|
|
3357
|
-
}
|
|
3358
|
-
}
|
|
3359
|
-
const visitedTypes = Object.create(null);
|
|
3360
|
-
const rootTypes = getRootTypes(schema);
|
|
3361
|
-
for (const rootType of rootTypes) {
|
|
3362
|
-
visitOutputType(visitedTypes, pruningContext, rootType);
|
|
3363
|
-
}
|
|
3364
|
-
for (const directive of schema.getDirectives()) {
|
|
3365
|
-
for (const arg of directive.args) {
|
|
3366
|
-
const type = getNamedType(arg.type);
|
|
3367
|
-
visitInputType(visitedTypes, pruningContext, type);
|
|
3368
|
-
}
|
|
3369
|
-
}
|
|
3337
|
+
return visited;
|
|
3370
3338
|
}
|
|
3371
3339
|
|
|
3372
3340
|
function mergeDeep(sources, respectPrototype = false) {
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graphql-tools/utils",
|
|
3
|
-
"version": "8.6.
|
|
3
|
+
"version": "8.6.10",
|
|
4
4
|
"description": "Common package containing utils and types for GraphQL tools",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"peerDependencies": {
|
|
7
7
|
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"tslib": "~2.
|
|
10
|
+
"tslib": "~2.4.0"
|
|
11
11
|
},
|
|
12
12
|
"repository": {
|
|
13
13
|
"type": "git",
|