@graphql-tools/utils 8.6.5 → 8.6.8
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/executor.d.ts +3 -3
- package/index.js +97 -142
- package/index.mjs +97 -142
- package/package.json +1 -1
- package/print-schema-with-directives.d.ts +1 -1
package/executor.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ExecutionResult, ExecutionRequest } from './Interfaces';
|
|
2
2
|
declare type MaybePromise<T> = Promise<T> | T;
|
|
3
3
|
declare type MaybeAsyncIterable<T> = AsyncIterable<T> | T;
|
|
4
|
-
export declare type AsyncExecutor<TBaseContext = Record<string, any>, TBaseExtensions = Record<string, any>> = <TReturn = any, TArgs = Record<string, any>, TContext extends TBaseContext = TBaseContext, TRoot = any, TExtensions extends TBaseExtensions = TBaseExtensions>(request: ExecutionRequest<TArgs, TContext, TRoot, TExtensions>) => Promise<MaybeAsyncIterable<ExecutionResult<TReturn>>>;
|
|
5
|
-
export declare type SyncExecutor<TBaseContext = Record<string, any>, TBaseExtensions = Record<string, any>> = <TReturn = any, TArgs = Record<string, any>, TContext extends TBaseContext = TBaseContext, TRoot = any, TExtensions extends TBaseExtensions = TBaseExtensions>(request: ExecutionRequest<TArgs, TContext, TRoot, TExtensions>) => ExecutionResult<TReturn>;
|
|
6
|
-
export declare type Executor<TBaseContext = Record<string, any>, TBaseExtensions = Record<string, any>> = <TReturn = any, TArgs = Record<string, any>, TContext extends TBaseContext = TBaseContext, TRoot = any, TExtensions extends TBaseExtensions = TBaseExtensions>(request: ExecutionRequest<TArgs, TContext, TRoot, TExtensions>) => MaybePromise<MaybeAsyncIterable<ExecutionResult<TReturn>>>;
|
|
4
|
+
export declare type AsyncExecutor<TBaseContext = Record<string, any>, TBaseExtensions = Record<string, any>> = <TReturn = any, TArgs extends Record<string, any> = Record<string, any>, TContext extends TBaseContext = TBaseContext, TRoot = any, TExtensions extends TBaseExtensions = TBaseExtensions>(request: ExecutionRequest<TArgs, TContext, TRoot, TExtensions>) => Promise<MaybeAsyncIterable<ExecutionResult<TReturn>>>;
|
|
5
|
+
export declare type SyncExecutor<TBaseContext = Record<string, any>, TBaseExtensions = Record<string, any>> = <TReturn = any, TArgs extends Record<string, any> = Record<string, any>, TContext extends TBaseContext = TBaseContext, TRoot = any, TExtensions extends TBaseExtensions = TBaseExtensions>(request: ExecutionRequest<TArgs, TContext, TRoot, TExtensions>) => ExecutionResult<TReturn>;
|
|
6
|
+
export declare type Executor<TBaseContext = Record<string, any>, TBaseExtensions = Record<string, any>> = <TReturn = any, TArgs extends Record<string, any> = Record<string, any>, TContext extends TBaseContext = TBaseContext, TRoot = any, TExtensions extends TBaseExtensions = TBaseExtensions>(request: ExecutionRequest<TArgs, TContext, TRoot, TExtensions>) => MaybePromise<MaybeAsyncIterable<ExecutionResult<TReturn>>>;
|
|
7
7
|
export {};
|
package/index.js
CHANGED
|
@@ -1123,7 +1123,7 @@ function astFromEnumValue(value, schema, pathToDirectivesInExtensions) {
|
|
|
1123
1123
|
value: value.name,
|
|
1124
1124
|
},
|
|
1125
1125
|
// ConstXNode has been introduced in v16 but it is not compatible with XNode so we do `as any` for backwards compatibility
|
|
1126
|
-
directives:
|
|
1126
|
+
directives: getDeprecatableDirectiveNodes(value, schema, pathToDirectivesInExtensions),
|
|
1127
1127
|
};
|
|
1128
1128
|
}
|
|
1129
1129
|
function makeDeprecatedDirective(deprecationReason) {
|
|
@@ -3220,155 +3220,110 @@ 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);
|
|
3253
|
-
}
|
|
3254
|
-
}
|
|
3255
|
-
else {
|
|
3256
|
-
if (pruningContext.unusedTypes[type.name] && !options.skipUnusedTypesPruning) {
|
|
3257
|
-
typesToPrune.add(type.name);
|
|
3258
|
-
}
|
|
3259
|
-
}
|
|
3260
|
-
}
|
|
3261
|
-
// TODO: consider not returning a new schema if there was nothing to prune. This would be a breaking change.
|
|
3262
|
-
const prunedSchema = mapSchema(schema, {
|
|
3263
|
-
[exports.MapperKind.TYPE]: (type) => {
|
|
3264
|
-
if (typesToPrune.has(type.name)) {
|
|
3265
|
-
return null;
|
|
3266
|
-
}
|
|
3267
|
-
},
|
|
3268
|
-
});
|
|
3269
|
-
// if we pruned something, we need to prune again in case there are now objects without fields
|
|
3270
|
-
return typesToPrune.size ? pruneSchema(prunedSchema, options) : prunedSchema;
|
|
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);
|
|
3287
|
-
}
|
|
3288
|
-
}
|
|
3289
|
-
if (graphql.isInterfaceType(type)) {
|
|
3290
|
-
const implementations = getImplementations(pruningContext, type);
|
|
3291
|
-
if (implementations) {
|
|
3292
|
-
for (const typeName in implementations) {
|
|
3293
|
-
visitOutputType(visitedTypes, pruningContext, pruningContext.schema.getType(typeName));
|
|
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);
|
|
3294
3239
|
}
|
|
3295
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
|
+
// 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
|
|
3294
|
+
if (visited.has(typeName)) {
|
|
3295
|
+
continue;
|
|
3296
3296
|
}
|
|
3297
|
-
if ('getInterfaces' in type) {
|
|
3298
|
-
for (const iFace of type.getInterfaces()) {
|
|
3299
|
-
visitOutputType(visitedTypes, pruningContext, iFace);
|
|
3300
|
-
}
|
|
3301
|
-
}
|
|
3302
|
-
}
|
|
3303
|
-
else if (graphql.isUnionType(type)) {
|
|
3304
|
-
const types = type.getTypes();
|
|
3305
|
-
for (const type of types) {
|
|
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
3297
|
const type = schema.getType(typeName);
|
|
3321
|
-
if (type
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3298
|
+
if (type) {
|
|
3299
|
+
// Get types for union
|
|
3300
|
+
if (graphql.isUnionType(type)) {
|
|
3301
|
+
queue.push(...type.getTypes().map(type => type.name));
|
|
3302
|
+
}
|
|
3303
|
+
// If the type has files visit those field types
|
|
3304
|
+
if ('getFields' in type) {
|
|
3305
|
+
const fields = type.getFields();
|
|
3306
|
+
const entries = Object.entries(fields);
|
|
3307
|
+
if (!entries.length) {
|
|
3308
|
+
continue;
|
|
3309
|
+
}
|
|
3310
|
+
for (const [, field] of entries) {
|
|
3311
|
+
if (graphql.isInputObjectType(type)) {
|
|
3312
|
+
for (const arg of field.args) {
|
|
3313
|
+
queue.push(graphql.getNamedType(arg.type).name); // Visit arg types
|
|
3314
|
+
}
|
|
3315
|
+
}
|
|
3316
|
+
queue.push(graphql.getNamedType(field.type).name);
|
|
3326
3317
|
}
|
|
3327
|
-
pruningContext.implementations[iface.name][type.name] = true;
|
|
3328
3318
|
}
|
|
3319
|
+
// Visit interfaces this type is implementing if they haven't been visited yet
|
|
3320
|
+
if ('getInterfaces' in type) {
|
|
3321
|
+
queue.push(...type.getInterfaces().map(iface => iface.name));
|
|
3322
|
+
}
|
|
3323
|
+
visited.add(typeName); // Mark as visited (and therefore it is used and should be kept)
|
|
3329
3324
|
}
|
|
3330
3325
|
}
|
|
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
|
-
}
|
|
3326
|
+
return visited;
|
|
3372
3327
|
}
|
|
3373
3328
|
|
|
3374
3329
|
function mergeDeep(sources, respectPrototype = false) {
|
package/index.mjs
CHANGED
|
@@ -1120,7 +1120,7 @@ function astFromEnumValue(value, schema, pathToDirectivesInExtensions) {
|
|
|
1120
1120
|
value: value.name,
|
|
1121
1121
|
},
|
|
1122
1122
|
// ConstXNode has been introduced in v16 but it is not compatible with XNode so we do `as any` for backwards compatibility
|
|
1123
|
-
directives:
|
|
1123
|
+
directives: getDeprecatableDirectiveNodes(value, schema, pathToDirectivesInExtensions),
|
|
1124
1124
|
};
|
|
1125
1125
|
}
|
|
1126
1126
|
function makeDeprecatedDirective(deprecationReason) {
|
|
@@ -3218,155 +3218,110 @@ 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);
|
|
3251
|
-
}
|
|
3252
|
-
}
|
|
3253
|
-
else {
|
|
3254
|
-
if (pruningContext.unusedTypes[type.name] && !options.skipUnusedTypesPruning) {
|
|
3255
|
-
typesToPrune.add(type.name);
|
|
3256
|
-
}
|
|
3257
|
-
}
|
|
3258
|
-
}
|
|
3259
|
-
// TODO: consider not returning a new schema if there was nothing to prune. This would be a breaking change.
|
|
3260
|
-
const prunedSchema = mapSchema(schema, {
|
|
3261
|
-
[MapperKind.TYPE]: (type) => {
|
|
3262
|
-
if (typesToPrune.has(type.name)) {
|
|
3263
|
-
return null;
|
|
3264
|
-
}
|
|
3265
|
-
},
|
|
3266
|
-
});
|
|
3267
|
-
// if we pruned something, we need to prune again in case there are now objects without fields
|
|
3268
|
-
return typesToPrune.size ? pruneSchema(prunedSchema, options) : prunedSchema;
|
|
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);
|
|
3285
|
-
}
|
|
3286
|
-
}
|
|
3287
|
-
if (isInterfaceType(type)) {
|
|
3288
|
-
const implementations = getImplementations(pruningContext, type);
|
|
3289
|
-
if (implementations) {
|
|
3290
|
-
for (const typeName in implementations) {
|
|
3291
|
-
visitOutputType(visitedTypes, pruningContext, pruningContext.schema.getType(typeName));
|
|
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);
|
|
3292
3237
|
}
|
|
3293
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
|
+
// Navigate all types starting with pre-queued types (root types)
|
|
3289
|
+
while (queue.length) {
|
|
3290
|
+
const typeName = queue.pop();
|
|
3291
|
+
// Skip types we already visited
|
|
3292
|
+
if (visited.has(typeName)) {
|
|
3293
|
+
continue;
|
|
3294
3294
|
}
|
|
3295
|
-
if ('getInterfaces' in type) {
|
|
3296
|
-
for (const iFace of type.getInterfaces()) {
|
|
3297
|
-
visitOutputType(visitedTypes, pruningContext, iFace);
|
|
3298
|
-
}
|
|
3299
|
-
}
|
|
3300
|
-
}
|
|
3301
|
-
else if (isUnionType(type)) {
|
|
3302
|
-
const types = type.getTypes();
|
|
3303
|
-
for (const type of types) {
|
|
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
3295
|
const type = schema.getType(typeName);
|
|
3319
|
-
if (type
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3296
|
+
if (type) {
|
|
3297
|
+
// Get types for union
|
|
3298
|
+
if (isUnionType(type)) {
|
|
3299
|
+
queue.push(...type.getTypes().map(type => type.name));
|
|
3300
|
+
}
|
|
3301
|
+
// If the type has files visit those field types
|
|
3302
|
+
if ('getFields' in type) {
|
|
3303
|
+
const fields = type.getFields();
|
|
3304
|
+
const entries = Object.entries(fields);
|
|
3305
|
+
if (!entries.length) {
|
|
3306
|
+
continue;
|
|
3307
|
+
}
|
|
3308
|
+
for (const [, field] of entries) {
|
|
3309
|
+
if (isInputObjectType(type)) {
|
|
3310
|
+
for (const arg of field.args) {
|
|
3311
|
+
queue.push(getNamedType(arg.type).name); // Visit arg types
|
|
3312
|
+
}
|
|
3313
|
+
}
|
|
3314
|
+
queue.push(getNamedType(field.type).name);
|
|
3324
3315
|
}
|
|
3325
|
-
pruningContext.implementations[iface.name][type.name] = true;
|
|
3326
3316
|
}
|
|
3317
|
+
// Visit interfaces this type is implementing if they haven't been visited yet
|
|
3318
|
+
if ('getInterfaces' in type) {
|
|
3319
|
+
queue.push(...type.getInterfaces().map(iface => iface.name));
|
|
3320
|
+
}
|
|
3321
|
+
visited.add(typeName); // Mark as visited (and therefore it is used and should be kept)
|
|
3327
3322
|
}
|
|
3328
3323
|
}
|
|
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
|
-
}
|
|
3324
|
+
return visited;
|
|
3370
3325
|
}
|
|
3371
3326
|
|
|
3372
3327
|
function mergeDeep(sources, respectPrototype = false) {
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@ export declare function printSchemaWithDirectives(schema: GraphQLSchema, options
|
|
|
5
5
|
export declare function astFromSchema(schema: GraphQLSchema, pathToDirectivesInExtensions?: Array<string>): SchemaDefinitionNode | SchemaExtensionNode | null;
|
|
6
6
|
export declare function astFromDirective(directive: GraphQLDirective, schema?: GraphQLSchema, pathToDirectivesInExtensions?: Array<string>): DirectiveDefinitionNode;
|
|
7
7
|
export declare function getDirectiveNodes(entity: GraphQLSchema | GraphQLNamedType | GraphQLEnumValue, schema: GraphQLSchema, pathToDirectivesInExtensions?: Array<string>): Array<DirectiveNode>;
|
|
8
|
-
export declare function getDeprecatableDirectiveNodes(entity: GraphQLArgument | GraphQLField<any, any> | GraphQLInputField, schema?: GraphQLSchema, pathToDirectivesInExtensions?: Array<string>): Array<DirectiveNode>;
|
|
8
|
+
export declare function getDeprecatableDirectiveNodes(entity: GraphQLArgument | GraphQLField<any, any> | GraphQLInputField | GraphQLEnumValue, schema?: GraphQLSchema, pathToDirectivesInExtensions?: Array<string>): Array<DirectiveNode>;
|
|
9
9
|
export declare function astFromArg(arg: GraphQLArgument, schema?: GraphQLSchema, pathToDirectivesInExtensions?: Array<string>): InputValueDefinitionNode;
|
|
10
10
|
export declare function astFromObjectType(type: GraphQLObjectType, schema: GraphQLSchema, pathToDirectivesInExtensions?: Array<string>): ObjectTypeDefinitionNode;
|
|
11
11
|
export declare function astFromInterfaceType(type: GraphQLInterfaceType, schema: GraphQLSchema, pathToDirectivesInExtensions?: Array<string>): InterfaceTypeDefinitionNode;
|