1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.pruneSchema = void 0;
|
4 | const graphql_1 = require("graphql");
|
5 | const mapSchema_js_1 = require("./mapSchema.js");
|
6 | const Interfaces_js_1 = require("./Interfaces.js");
|
7 | const rootTypes_js_1 = require("./rootTypes.js");
|
8 | const get_implementing_types_js_1 = require("./get-implementing-types.js");
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 | function pruneSchema(schema, options = {}) {
|
15 | const { skipEmptyCompositeTypePruning, skipEmptyUnionPruning, skipPruning, skipUnimplementedInterfacesPruning, skipUnusedTypesPruning, } = options;
|
16 | let prunedTypes = [];
|
17 | let prunedSchema = schema;
|
18 | do {
|
19 | let visited = visitSchema(prunedSchema);
|
20 |
|
21 | if (skipPruning) {
|
22 | const revisit = [];
|
23 | for (const typeName in prunedSchema.getTypeMap()) {
|
24 | if (typeName.startsWith('__')) {
|
25 | continue;
|
26 | }
|
27 | const type = prunedSchema.getType(typeName);
|
28 |
|
29 | if (type && skipPruning(type)) {
|
30 | revisit.push(typeName);
|
31 | }
|
32 | }
|
33 | visited = visitQueue(revisit, prunedSchema, visited);
|
34 | }
|
35 | prunedTypes = [];
|
36 | prunedSchema = (0, mapSchema_js_1.mapSchema)(prunedSchema, {
|
37 | [Interfaces_js_1.MapperKind.TYPE]: type => {
|
38 | if (!visited.has(type.name) && !(0, graphql_1.isSpecifiedScalarType)(type)) {
|
39 | if ((0, graphql_1.isUnionType)(type) ||
|
40 | (0, graphql_1.isInputObjectType)(type) ||
|
41 | (0, graphql_1.isInterfaceType)(type) ||
|
42 | (0, graphql_1.isObjectType)(type) ||
|
43 | (0, graphql_1.isScalarType)(type)) {
|
44 |
|
45 | if (skipUnusedTypesPruning) {
|
46 | return type;
|
47 | }
|
48 |
|
49 | if ((0, graphql_1.isUnionType)(type) && skipEmptyUnionPruning && !Object.keys(type.getTypes()).length) {
|
50 | return type;
|
51 | }
|
52 | if ((0, graphql_1.isInputObjectType)(type) || (0, graphql_1.isInterfaceType)(type) || (0, graphql_1.isObjectType)(type)) {
|
53 |
|
54 | if (skipEmptyCompositeTypePruning && !Object.keys(type.getFields()).length) {
|
55 | return type;
|
56 | }
|
57 | }
|
58 |
|
59 | if ((0, graphql_1.isInterfaceType)(type) && skipUnimplementedInterfacesPruning) {
|
60 | return type;
|
61 | }
|
62 | }
|
63 | prunedTypes.push(type.name);
|
64 | visited.delete(type.name);
|
65 | return null;
|
66 | }
|
67 | return type;
|
68 | },
|
69 | });
|
70 | } while (prunedTypes.length);
|
71 | return prunedSchema;
|
72 | }
|
73 | exports.pruneSchema = pruneSchema;
|
74 | function visitSchema(schema) {
|
75 | const queue = [];
|
76 |
|
77 | for (const type of (0, rootTypes_js_1.getRootTypes)(schema)) {
|
78 | queue.push(type.name);
|
79 | }
|
80 | return visitQueue(queue, schema);
|
81 | }
|
82 | function visitQueue(queue, schema, visited = new Set()) {
|
83 |
|
84 | const revisit = new Map();
|
85 |
|
86 | while (queue.length) {
|
87 | const typeName = queue.pop();
|
88 |
|
89 | if (visited.has(typeName) && revisit[typeName] !== true) {
|
90 | continue;
|
91 | }
|
92 | const type = schema.getType(typeName);
|
93 | if (type) {
|
94 |
|
95 | if ((0, graphql_1.isUnionType)(type)) {
|
96 | queue.push(...type.getTypes().map(type => type.name));
|
97 | }
|
98 |
|
99 | if ((0, graphql_1.isInterfaceType)(type) && revisit[typeName] === true) {
|
100 | queue.push(...(0, get_implementing_types_js_1.getImplementingTypes)(type.name, schema));
|
101 |
|
102 | revisit[typeName] = false;
|
103 | }
|
104 |
|
105 | if ('getInterfaces' in type) {
|
106 |
|
107 | queue.push(...type.getInterfaces().map(iface => iface.name));
|
108 | }
|
109 |
|
110 | if ('getFields' in type) {
|
111 | const fields = type.getFields();
|
112 | const entries = Object.entries(fields);
|
113 | if (!entries.length) {
|
114 | continue;
|
115 | }
|
116 | for (const [, field] of entries) {
|
117 | if ((0, graphql_1.isObjectType)(type)) {
|
118 |
|
119 | queue.push(...field.args.map(arg => (0, graphql_1.getNamedType)(arg.type).name));
|
120 | }
|
121 | const namedType = (0, graphql_1.getNamedType)(field.type);
|
122 | queue.push(namedType.name);
|
123 |
|
124 | if ((0, graphql_1.isInterfaceType)(namedType) && !(namedType.name in revisit)) {
|
125 | revisit[namedType.name] = true;
|
126 | }
|
127 | }
|
128 | }
|
129 | visited.add(typeName);
|
130 | }
|
131 | }
|
132 | return visited;
|
133 | }
|