Mirror: The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

(introspection) - Add options to include more schema info to minifyIntrospectionQuery (#1578)

* Add includeScalars option to minifyIntrospectionQuery

* Remove Any scalar if it's not needed

* Add includeEnums / includeInputs / includeDirectives options

* Update changeset

* Fix linting issues in minifyIntrospectionQuery

* Fix directives mapping for undefined directives input

authored by

Phil Pluckthun and committed by
GitHub
398007e0 d90f7ded

+105 -24
+7
.changeset/lovely-hounds-tap.md
··· 1 + --- 2 + '@urql/introspection': minor 3 + --- 4 + 5 + Add options to `@urql/introspection`'s `minifyIntrospectionQuery` allowing the inclusion of more 6 + information into the minified schema as needed, namely `includeScalars`, `includeEnums`, 7 + `includeInputs`, and `includeDirectives`.
+98 -24
packages/introspection/src/minifyIntrospectionQuery.ts
··· 2 2 IntrospectionQuery, 3 3 IntrospectionType, 4 4 IntrospectionTypeRef, 5 + IntrospectionInputValue, 5 6 } from 'graphql'; 6 7 8 + let _includeScalars = false; 9 + let _includeEnums = false; 10 + let _includeInputs = false; 11 + let _hasAnyType = false; 12 + 7 13 const anyType: IntrospectionTypeRef = { 8 14 kind: 'SCALAR', 9 15 name: 'Any', 10 16 }; 11 17 12 - const mapType = ( 13 - fromType: any, 14 - toType: IntrospectionTypeRef 15 - ): IntrospectionTypeRef => { 18 + const mapType = (fromType: any): IntrospectionTypeRef => { 16 19 switch (fromType.kind) { 17 20 case 'NON_NULL': 18 21 case 'LIST': 19 22 return { 20 23 kind: fromType.kind, 21 - ofType: mapType(fromType.ofType, toType), 24 + ofType: mapType(fromType.ofType), 22 25 }; 23 26 24 27 case 'SCALAR': 28 + _hasAnyType = _hasAnyType || _includeScalars; 29 + return _includeScalars ? fromType : anyType; 30 + 25 31 case 'INPUT_OBJECT': 32 + _hasAnyType = _hasAnyType || _includeInputs; 33 + return _includeInputs ? fromType : anyType; 34 + 26 35 case 'ENUM': 27 - return toType; 36 + _hasAnyType = _hasAnyType || _includeEnums; 37 + return _includeEnums ? fromType : anyType; 28 38 29 39 case 'OBJECT': 30 40 case 'INTERFACE': 31 41 case 'UNION': 32 - return { 33 - kind: fromType.kind, 34 - name: fromType.name, 35 - }; 42 + return fromType; 36 43 37 44 default: 38 45 throw new TypeError( ··· 45 52 type: IntrospectionType 46 53 ): IntrospectionType => { 47 54 switch (type.kind) { 48 - case 'OBJECT': { 55 + case 'SCALAR': 56 + return { 57 + kind: 'SCALAR', 58 + name: type.name, 59 + }; 60 + 61 + case 'ENUM': 62 + return { 63 + kind: 'ENUM', 64 + name: type.name, 65 + enumValues: type.enumValues.map( 66 + value => 67 + ({ 68 + name: value.name, 69 + } as any) 70 + ), 71 + }; 72 + 73 + case 'INPUT_OBJECT': { 74 + return { 75 + kind: 'INPUT_OBJECT', 76 + name: type.name, 77 + inputFields: type.inputFields.map( 78 + field => 79 + ({ 80 + name: field.name, 81 + type: mapType(field.type), 82 + defaultValue: field.defaultValue || undefined, 83 + } as IntrospectionInputValue) 84 + ), 85 + }; 86 + } 87 + 88 + case 'OBJECT': 49 89 return { 50 90 kind: 'OBJECT', 51 91 name: type.name, ··· 53 93 field => 54 94 ({ 55 95 name: field.name, 56 - type: field.type && mapType(field.type, anyType), 96 + type: field.type && mapType(field.type), 57 97 args: 58 98 field.args && 59 99 field.args.map(arg => ({ 60 100 name: arg.name, 61 - type: mapType(arg.type, anyType), 101 + type: mapType(arg.type), 62 102 })), 63 103 } as any) 64 104 ), ··· 69 109 name: int.name, 70 110 })), 71 111 }; 72 - } 73 112 74 - case 'INTERFACE': { 113 + case 'INTERFACE': 75 114 return { 76 115 kind: 'INTERFACE', 77 116 name: type.name, ··· 79 118 field => 80 119 ({ 81 120 name: field.name, 82 - type: field.type && mapType(field.type, anyType), 121 + type: field.type && mapType(field.type), 83 122 args: 84 123 field.args && 85 124 field.args.map(arg => ({ 86 125 name: arg.name, 87 - type: mapType(arg.type, anyType), 126 + type: mapType(arg.type), 88 127 })), 89 128 } as any) 90 129 ), ··· 101 140 name: type.name, 102 141 })), 103 142 }; 104 - } 105 143 106 - case 'UNION': { 144 + case 'UNION': 107 145 return { 108 146 kind: 'UNION', 109 147 name: type.name, ··· 112 150 name: type.name, 113 151 })), 114 152 }; 115 - } 116 153 117 154 default: 118 155 return type; 119 156 } 120 157 }; 121 158 159 + export interface MinifySchemaOptions { 160 + /** Includes scalar names (instead of an `Any` replacement) in the output when enabled. */ 161 + includeScalars?: boolean; 162 + /** Includes enums (instead of an `Any` replacement) in the output when enabled. */ 163 + includeEnums?: boolean; 164 + /** Includes all input objects (instead of an `Any` replacement) in the output when enabled. */ 165 + includeInputs?: boolean; 166 + /** Includes all directives in the output when enabled. */ 167 + includeDirectives?: boolean; 168 + } 169 + 170 + /** Removes extraneous information from introspected schema data to minify it and prepare it for use on the client-side. */ 122 171 export const minifyIntrospectionQuery = ( 123 - schema: IntrospectionQuery 172 + schema: IntrospectionQuery, 173 + opts: MinifySchemaOptions = {} 124 174 ): IntrospectionQuery => { 125 175 if (!schema || !('__schema' in schema)) { 126 176 throw new TypeError('Expected to receive an IntrospectionQuery.'); 127 177 } 128 178 179 + _hasAnyType = false; 180 + _includeScalars = !!opts.includeScalars; 181 + _includeEnums = !!opts.includeEnums; 182 + _includeInputs = !!opts.includeInputs; 183 + 129 184 const { 130 - __schema: { queryType, mutationType, subscriptionType, types }, 185 + __schema: { queryType, mutationType, subscriptionType, types, directives }, 131 186 } = schema; 132 187 133 188 const minifiedTypes = types ··· 144 199 return false; 145 200 default: 146 201 return ( 202 + (_includeScalars && type.kind === 'SCALAR') || 203 + (_includeEnums && type.kind === 'ENUM') || 204 + (_includeInputs && type.kind === 'INPUT_OBJECT') || 147 205 type.kind === 'OBJECT' || 148 206 type.kind === 'INTERFACE' || 149 207 type.kind === 'UNION' ··· 152 210 }) 153 211 .map(minifyIntrospectionType); 154 212 155 - minifiedTypes.push({ kind: 'SCALAR', name: anyType.name }); 213 + const minifiedDirectives = (directives || []).map(directive => ({ 214 + name: directive.name, 215 + isRepeatable: directive.isRepeatable ? true : undefined, 216 + locations: directive.locations, 217 + args: directive.args.map( 218 + arg => 219 + ({ 220 + name: arg.name, 221 + type: mapType(arg.type), 222 + defaultValue: arg.defaultValue || undefined, 223 + } as IntrospectionInputValue) 224 + ), 225 + })); 226 + 227 + if (!_includeScalars || !_includeEnums || !_includeInputs || _hasAnyType) { 228 + minifiedTypes.push({ kind: 'SCALAR', name: anyType.name }); 229 + } 156 230 157 231 return { 158 232 __schema: { ··· 160 234 mutationType, 161 235 subscriptionType, 162 236 types: minifiedTypes, 163 - directives: [], 237 + directives: opts.includeDirectives ? minifiedDirectives : [], 164 238 }, 165 239 }; 166 240 };