Mirror: The small sibling of the graphql package, slimmed down for client-side libraries.

feat: Extract implementation to @0no-co/graphql.web (#11)

* Add @0no-co/graphql.web
* Use exports from @0no-co/graphql.web

authored by kitten.sh and committed by GitHub 9d9d3bf9 6963f679

+1 -66
alias/error/GraphQLError.mjs
··· 1 - import { getLocation } from 'graphql/language/location'; 2 - 3 - import { printLocation, printSourceLocation } from '../language/printLocation'; 4 - 5 - export class GraphQLError extends Error { 6 - constructor( 7 - message, 8 - nodes, 9 - source, 10 - positions, 11 - path, 12 - originalError, 13 - extensions 14 - ) { 15 - super(message); 16 - 17 - this.name = 'GraphQLError'; 18 - this.message = message; 19 - 20 - if (path) this.path = path; 21 - if (nodes) this.nodes = nodes; 22 - if (source) this.source = source; 23 - if (positions) this.positions = positions; 24 - if (originalError) this.originalError = originalError; 25 - 26 - let _extensions = extensions; 27 - if (_extensions == null && originalError != null) { 28 - const originalExtensions = originalError.extensions; 29 - if (isObjectLike(originalExtensions)) { 30 - _extensions = originalExtensions; 31 - } 32 - } 33 - 34 - if (_extensions) { 35 - this.extensions = _extensions; 36 - } 37 - } 38 - 39 - toJSON() { 40 - const formattedError = { message: this.message }; 41 - 42 - if (this.locations != null) formattedError.locations = this.locations; 43 - if (this.path != null) formattedError.path = this.path; 44 - if (this.extensions != null && Object.keys(this.extensions).length > 0) 45 - formattedError.extensions = this.extensions; 46 - return formattedError; 47 - } 48 - 49 - toString() { 50 - let output = error.message; 51 - 52 - if (error.nodes) { 53 - for (const node of error.nodes) { 54 - if (node.loc) { 55 - output += '\n\n' + printLocation(node.loc); 56 - } 57 - } 58 - } else if (error.source && error.locations) { 59 - for (const location of error.locations) { 60 - output += '\n\n' + printSourceLocation(error.source, location); 61 - } 62 - } 63 - 64 - return output; 65 - } 66 - } 1 + export { GraphQLError } from '@0no-co/graphql.web'; 67 2 68 3 /** 69 4 * Prints a GraphQLError to a string, representing useful location information
+1 -3
alias/language/blockString.mjs
··· 1 - export function printBlockString(str) { 2 - return '"""\n' + JSON.stringify(str).slice(1, -1) + '\n"""'; 3 - } 1 + export { printBlockString } from '@0no-co/graphql.web'; 4 2 5 3 export function isPrintableAsBlockString(value) { 6 4 return true;
+1
alias/language/kinds.mjs
··· 1 + export { Kind } from '@0no-co/graphql.web';
+1 -339
alias/language/parser.mjs
··· 1 - /** 2 - * This is a spec-compliant implementation of a GraphQL query language parser, 3 - * up-to-date with the June 2018 Edition. Unlike the reference implementation 4 - * in graphql.js it will only parse the query language, but not the schema 5 - * language. 6 - */ 7 - import { Kind } from 'graphql'; 8 - import { GraphQLError } from '../error/GraphQLError'; 9 - import { match, parse as makeParser } from 'reghex'; 10 - 11 - // 2.1.7: Includes commas, and line comments 12 - const ignored = /([\s,]|#[^\n\r]+)+/; 13 - 14 - // 2.1.9: Limited to ASCII character set, so regex shortcodes are fine 15 - const name = match(Kind.NAME, (x) => ({ 16 - kind: x.tag, 17 - value: x[0], 18 - }))` 19 - ${/[_\w][_\d\w]*/} 20 - `; 21 - 22 - const null_ = match(Kind.NULL, (x) => ({ 23 - kind: x.tag, 24 - }))` 25 - ${'null'} 26 - `; 27 - 28 - const bool = match(Kind.BOOLEAN, (x) => ({ 29 - kind: x.tag, 30 - value: x[0] === 'true', 31 - }))` 32 - ${/true|false/} 33 - `; 34 - 35 - const variable = match(Kind.VARIABLE, (x) => ({ 36 - kind: x.tag, 37 - name: x[0], 38 - }))` 39 - :${'$'} ${name} 40 - `; 41 - 42 - // 2.9.6: Technically, this parser doesn't need to check that true, false, and null 43 - // aren't used as enums, but this prevents mistakes and follows the spec closely 44 - const enum_ = match(Kind.ENUM, (x) => ({ 45 - kind: x.tag, 46 - value: x[0].value, 47 - }))` 48 - ${name} 49 - `; 50 - 51 - // 2.9.1-2: These combine both number values for the sake of simplicity. 52 - // It allows for leading zeroes, unlike graphql.js, which shouldn't matter; 53 - const number = match(null, (x) => ({ 54 - kind: x.length === 1 ? Kind.INT : Kind.FLOAT, 55 - value: x.join(''), 56 - }))` 57 - ${/[-]?\d+/} 58 - ${/[.]\d+/}? 59 - ${/[eE][+-]?\d+/}? 60 - `; 61 - 62 - // 2.9.4: Notably, this skips checks for unicode escape sequences and escaped quotes. 63 - const string = match(Kind.STRING, (x) => ({ 64 - kind: x.tag, 65 - value: x[0], 66 - }))` 67 - (:${'"""'} ${/[\s\S]+?(?=""")/} :${'"""'}) 68 - | (:${'"'} ${/[^"\r\n]*/} :${'"'}) 69 - `; 70 - 71 - const list = match(Kind.LIST, (x) => ({ 72 - kind: x.tag, 73 - values: x.slice(), 74 - }))` 75 - :${'['} 76 - ${() => value}* 77 - (?: ${ignored}? ${']'} ${ignored}?) 78 - `; 79 - 80 - const objectField = match(Kind.OBJECT_FIELD, (x) => ({ 81 - kind: x.tag, 82 - name: x[0], 83 - value: x[1], 84 - }))` 85 - :${ignored}? 86 - ${name} 87 - (?: ${ignored}? ${':'}) 88 - ${() => value} 89 - `; 90 - 91 - const object = match(Kind.OBJECT, (x) => ({ 92 - kind: x.tag, 93 - fields: x.slice(), 94 - }))` 95 - :${'{'} 96 - ${objectField}* 97 - (?: ${'}'} ${ignored}?) 98 - `; 99 - 100 - // 2.9: This matches the spec closely and is complete 101 - const value = match(null, (x) => x[0])` 102 - :${ignored}? 103 - ( 104 - ${null_} 105 - | ${bool} 106 - | ${variable} 107 - | ${string} 108 - | ${number} 109 - | ${enum_} 110 - | ${list} 111 - | ${object} 112 - ) 113 - :${ignored}? 114 - `; 115 - 116 - const arg = match(Kind.ARGUMENT, (x) => ({ 117 - kind: x.tag, 118 - name: x[0], 119 - value: x[1], 120 - }))` 121 - ${name} 122 - (?: ${ignored}? ${':'} ${ignored}?) 123 - ${value} 124 - `; 125 - 126 - const args = match()` 127 - :${ignored}? 128 - ( 129 - (?: ${'('} ${ignored}?) 130 - ${arg}+ 131 - (?: ${')'} ${ignored}?) 132 - )? 133 - `; 134 - 135 - const directive = match(Kind.DIRECTIVE, (x) => ({ 136 - kind: x.tag, 137 - name: x[0], 138 - arguments: x[1], 139 - }))` 140 - :${'@'} ${name} :${ignored}? 141 - ${args}? 142 - :${ignored}? 143 - `; 144 - 145 - const directives = match()` 146 - :${ignored}? 147 - ${directive}* 148 - `; 149 - 150 - const field = match(Kind.FIELD, (x) => { 151 - let i = 0; 152 - return { 153 - kind: x.tag, 154 - alias: x[1].kind === Kind.NAME ? x[i++] : undefined, 155 - name: x[i++], 156 - arguments: x[i++], 157 - directives: x[i++], 158 - selectionSet: x[i++], 159 - }; 160 - })` 161 - :${ignored}? 162 - ${name} 163 - ( 164 - (?: ${ignored}? ${':'} ${ignored}?) 165 - ${name} 166 - )? 167 - ${args} 168 - ${directives} 169 - ${() => selectionSet}? 170 - `; 171 - 172 - // 2.11: The type declarations may be simplified since there's little room 173 - // for error in this limited type system. 174 - const type = match(null, (x) => { 175 - const node = 176 - x[0].kind === 'Name' 177 - ? { kind: Kind.NAMED_TYPE, name: x[0] } 178 - : { kind: Kind.LIST_TYPE, type: x[0] }; 179 - return x[1] === '!' ? { kind: Kind.NON_NULL_TYPE, type: node } : node; 180 - })` 181 - ( 182 - ( 183 - (?: ${'['} ${ignored}?) 184 - ${() => type} 185 - (?: ${ignored}? ${']'} ${ignored}?) 186 - ) | ${name} 187 - ) 188 - ${'!'}? 189 - :${ignored}? 190 - `; 191 - 192 - const typeCondition = match(null, (x) => ({ 193 - kind: Kind.NAMED_TYPE, 194 - name: x[0], 195 - }))` 196 - (?: ${ignored}? ${'on'} ${ignored}) 197 - ${name} 198 - :${ignored}? 199 - `; 200 - 201 - const inlineFragment = match(Kind.INLINE_FRAGMENT, (x) => { 202 - let i = 0; 203 - return { 204 - kind: x.tag, 205 - typeCondition: x[i].kind === Kind.NAMED_TYPE ? x[i++] : undefined, 206 - directives: x[i++], 207 - selectionSet: x[i], 208 - }; 209 - })` 210 - :${'...'} 211 - ${typeCondition}? 212 - ${directives} 213 - ${() => selectionSet} 214 - `; 215 - 216 - const fragmentSpread = match(Kind.FRAGMENT_SPREAD, (x) => ({ 217 - kind: x.tag, 218 - name: x[0], 219 - directives: x[1], 220 - }))` 221 - (?: ${'...'} ${ignored}?) 222 - !${'on'} 223 - ${name} 224 - :${ignored}? 225 - ${directives} 226 - `; 227 - 228 - const selectionSet = match(Kind.SELECTION_SET, (x) => ({ 229 - kind: x.tag, 230 - selections: x.slice(), 231 - }))` 232 - :${ignored}? 233 - (?: ${'{'} ${ignored}?) 234 - ( 235 - ${inlineFragment} | 236 - ${fragmentSpread} | 237 - ${field} 238 - )+ 239 - (?: ${'}'} ${ignored}?) 240 - `; 241 - 242 - const varDefinitionDefault = match(null, (x) => x[0])` 243 - (?: ${'='} ${ignored}?) 244 - ${value} 245 - `; 246 - 247 - const varDefinition = match(Kind.VARIABLE_DEFINITION, (x) => ({ 248 - kind: x.tag, 249 - variable: x[0], 250 - type: x[1], 251 - defaultValue: x[2].kind ? x[2] : undefined, 252 - directives: !x[2].kind ? x[2] : x[3], 253 - }))` 254 - ${variable} 255 - (?: ${ignored}? ${':'} ${ignored}?) 256 - ${type} 257 - ${varDefinitionDefault}? 258 - ${directives} 259 - :${ignored}? 260 - `; 261 - 262 - const varDefinitions = match('vars')` 263 - :${ignored}? 264 - (?: ${'('} ${ignored}?) 265 - ${varDefinition}+ 266 - (?: ${')'} ${ignored}?) 267 - `; 268 - 269 - const fragmentDefinition = match(Kind.FRAGMENT_DEFINITION, (x) => ({ 270 - kind: x.tag, 271 - name: x[0], 272 - typeCondition: x[1], 273 - directives: x[2], 274 - selectionSet: x[3], 275 - }))` 276 - (?: ${ignored}? ${'fragment'} ${ignored}) 277 - ${name} 278 - ${typeCondition} 279 - ${directives} 280 - ${selectionSet} 281 - `; 282 - 283 - const operationDefinition = match(Kind.OPERATION_DEFINITION, (x) => { 284 - let i = 1; 285 - return { 286 - kind: x.tag, 287 - operation: x[0], 288 - name: x[i].kind === Kind.NAME ? x[i++] : undefined, 289 - variableDefinitions: x[i].tag === 'vars' ? x[i++].slice() : [], 290 - directives: x[i++], 291 - selectionSet: x[i], 292 - }; 293 - })` 294 - :${ignored}? 295 - ${/query|mutation|subscription/} 296 - (:${ignored} ${name})? 297 - ${varDefinitions}? 298 - ${directives} 299 - ${selectionSet} 300 - `; 301 - 302 - const queryShorthand = match(Kind.OPERATION_DEFINITION, (x) => ({ 303 - kind: x.tag, 304 - operation: 'query', 305 - name: undefined, 306 - variableDefinitions: [], 307 - directives: [], 308 - selectionSet: x[0], 309 - }))` 310 - ${selectionSet} 311 - `; 312 - 313 - const root = match(Kind.DOCUMENT, (x) => 314 - x.length ? { kind: x.tag, definitions: x.slice() } : undefined 315 - )` 316 - (${queryShorthand} | ${operationDefinition} | ${fragmentDefinition})* 317 - `; 318 - 319 - const _parse = makeParser(root); 320 - const _parseValue = makeParser(value); 321 - const _parseType = makeParser(type); 322 - 323 - export function parse(input) { 324 - const result = _parse(input); 325 - if (result == null) throw new GraphQLError('Syntax Error'); 326 - return result; 327 - } 328 - 329 - export function parseValue(input) { 330 - const result = _parseValue(input); 331 - if (result == null) throw new GraphQLError('Syntax Error'); 332 - return result; 333 - } 334 - 335 - export function parseType(input) { 336 - const result = _parseType(input); 337 - if (result == null) throw new GraphQLError('Syntax Error'); 338 - return result; 339 - } 1 + export { parse, parseType, parseValue } from '@0no-co/graphql.web';
+1 -1
alias/language/printString.mjs
··· 1 - export const printString = JSON.stringify; 1 + export { printString } from '@0no-co/graphql.web';
+1 -141
alias/language/printer.mjs
··· 1 - import { Kind } from 'graphql'; 2 - import { printBlockString } from './blockString'; 3 - import { printString } from './printString'; 4 - 5 - export function print(node) { 6 - if (Array.isArray(node)) { 7 - return node.map(print); 8 - } else if (node == null || typeof node !== 'object') { 9 - return node ? '' + node : ''; 10 - } 11 - 12 - switch (node.kind) { 13 - case 'OperationDefinition': { 14 - const prefix = join( 15 - [ 16 - node.operation, 17 - print(node.name) + 18 - wrap('(', join(print(node.variableDefinitions), ', '), ')'), 19 - join(print(node.directives), ' '), 20 - ], 21 - ' ' 22 - ); 23 - 24 - return ( 25 - (prefix === 'query' ? '' : prefix + ' ') + print(node.selectionSet) 26 - ); 27 - } 28 - 29 - case 'VariableDefinition': 30 - return ( 31 - print(node.variable) + 32 - ': ' + 33 - print(node.type) + 34 - wrap(' = ', print(node.defaultValue)) + 35 - wrap(' ', join(print(node.directives), ' ')) 36 - ); 37 - 38 - case 'Field': 39 - return join( 40 - [ 41 - wrap('', print(node.alias), ': ') + 42 - print(node.name) + 43 - wrap('(', join(print(node.arguments), ', '), ')'), 44 - join(print(node.directives), ' '), 45 - print(node.selectionSet), 46 - ], 47 - ' ' 48 - ); 49 - 50 - case 'StringValue': 51 - return node.isBlockString 52 - ? printBlockString(node.value) 53 - : printString(node.value); 54 - 55 - case 'BooleanValue': 56 - return node.value ? 'true' : 'false'; 57 - 58 - case 'NullValue': 59 - return 'null'; 60 - 61 - case 'IntValue': 62 - case 'FloatValue': 63 - case 'EnumValue': 64 - case 'Name': 65 - return node.value; 66 - 67 - case 'ListValue': 68 - return '[' + join(print(node.values), ', ') + ']'; 69 - 70 - case 'ObjectValue': 71 - return '{' + join(print(node.fields), ', ') + '}'; 72 - 73 - case 'ObjectField': 74 - return node.name.value + ': ' + print(node.value); 75 - 76 - case 'Variable': 77 - return '$' + node.name.value; 78 - case 'Document': 79 - return join(print(node.definitions), '\n\n') + '\n'; 80 - case 'SelectionSet': 81 - return block(print(node.selections)); 82 - case 'Argument': 83 - return node.name.value + ': ' + print(node.value); 84 - 85 - case 'FragmentSpread': 86 - return ( 87 - '...' + print(node.name) + wrap(' ', join(print(node.directives), ' ')) 88 - ); 89 - 90 - case 'InlineFragment': 91 - return join( 92 - [ 93 - '...', 94 - wrap('on ', print(node.typeCondition)), 95 - join(print(node.directives), ' '), 96 - print(node.selectionSet), 97 - ], 98 - ' ' 99 - ); 100 - 101 - case 'FragmentDefinition': 102 - return ( 103 - 'fragment ' + 104 - node.name.value + 105 - wrap('(', join(print(node.variableDefinitions), ', '), ')') + 106 - ' ' + 107 - 'on ' + 108 - print(node.typeCondition) + 109 - ' ' + 110 - wrap('', join(print(node.directives), ' '), ' ') + 111 - print(node.selectionSet) 112 - ); 113 - 114 - case 'Directive': 115 - return ( 116 - '@' + 117 - node.name.value + 118 - wrap('(', join(print(node.arguments), ', '), ')') 119 - ); 120 - 121 - case 'NamedType': 122 - return node.name.value; 123 - 124 - case 'ListType': 125 - return '[' + print(node.type) + ']'; 126 - 127 - case 'NonNullType': 128 - return print(node.type) + '!'; 129 - 130 - default: 131 - return ''; 132 - } 133 - } 134 - 135 - const join = (array, separator) => 136 - (array && array.filter((x) => x).join(separator || '')) || ''; 137 - 138 - const block = (array) => 139 - wrap('{\n ', join(array, '\n').replace(/\n/g, '\n '), '\n}'); 140 - 141 - const wrap = (start, value, end) => (value ? start + value + (end || '') : ''); 1 + export { print } from '@0no-co/graphql.web';
+2 -87
alias/language/visitor.mjs
··· 1 - import { 1 + export { 2 2 getEnterLeaveForKind, 3 3 getVisitFn, 4 4 visitInParallel, 5 - BREAK, 6 5 } from 'graphql/language/visitor'; 7 6 8 - export { getEnterLeaveForKind, getVisitFn, visitInParallel, BREAK }; 9 - 10 - export function visit(node, visitor) { 11 - const path = []; 12 - const ancestors = []; 13 - 14 - function traverse(node, key, parent) { 15 - let hasEdited = false; 16 - 17 - const enter = getVisitFn(visitor, node.kind, false); 18 - const resultEnter = 19 - enter && enter.call(visitor, node, key, parent, path, ancestors); 20 - if (resultEnter === false) { 21 - return node; 22 - } else if (resultEnter === null) { 23 - return null; 24 - } else if (resultEnter === BREAK) { 25 - throw BREAK; 26 - } else if (resultEnter && typeof resultEnter.kind === 'string') { 27 - hasEdited = resultEnter !== node; 28 - node = resultEnter; 29 - } 30 - 31 - if (parent) ancestors.push(parent); 32 - 33 - let result; 34 - const copy = { ...node }; 35 - for (const nodeKey in node) { 36 - path.push(nodeKey); 37 - let value = node[nodeKey]; 38 - if (Array.isArray(value)) { 39 - const newValue = []; 40 - for (let index = 0; index < value.length; index++) { 41 - if (value[index] != null && typeof value[index].kind === 'string') { 42 - ancestors.push(node); 43 - path.push(index); 44 - result = traverse(value[index], index, value); 45 - path.pop(); 46 - ancestors.pop(); 47 - if (result === undefined) { 48 - newValue.push(value[index]); 49 - } else if (result === null) { 50 - hasEdited = true; 51 - } else { 52 - hasEdited = hasEdited || result !== value[index]; 53 - newValue.push(result); 54 - } 55 - } 56 - } 57 - value = newValue; 58 - } else if (value != null && typeof value.kind === 'string') { 59 - result = traverse(value, nodeKey, node); 60 - if (result !== undefined) { 61 - hasEdited = hasEdited || value !== result; 62 - value = result; 63 - } 64 - } 65 - 66 - path.pop(); 67 - if (hasEdited) copy[nodeKey] = value; 68 - } 69 - 70 - if (parent) ancestors.pop(); 71 - const leave = getVisitFn(visitor, node.kind, true); 72 - const resultLeave = 73 - leave && leave.call(visitor, node, key, parent, path, ancestors); 74 - if (resultLeave === BREAK) { 75 - throw BREAK; 76 - } else if (resultLeave !== undefined) { 77 - return resultLeave; 78 - } else if (resultEnter !== undefined) { 79 - return hasEdited ? copy : resultEnter; 80 - } else { 81 - return hasEdited ? copy : node; 82 - } 83 - } 84 - 85 - try { 86 - const result = traverse(node); 87 - return result !== undefined && result !== false ? result : node; 88 - } catch (error) { 89 - if (error !== BREAK) throw error; 90 - return node; 91 - } 92 - } 7 + export { BREAK, visit } from '@0no-co/graphql.web';
+1
package.json
··· 28 28 "url": "https://github.com/kitten/graphql-web-lite.git" 29 29 }, 30 30 "devDependencies": { 31 + "@0no-co/graphql.web": "^0.1.2", 31 32 "@babel/core": "^7.15.0", 32 33 "@rollup/plugin-babel": "^5.3.0", 33 34 "@rollup/plugin-buble": "^0.21.3",
+11
tsconfig.json
··· 1 + { 2 + "compilerOptions": { 3 + "target": "ESNext", 4 + "module": "ESNext", 5 + "allowJs": true, 6 + "moduleResolution": "node", 7 + "strict": true, 8 + "skipLibCheck": true, 9 + "noEmit": true 10 + } 11 + }
+5
yarn.lock
··· 2 2 # yarn lockfile v1 3 3 4 4 5 + "@0no-co/graphql.web@^0.1.2": 6 + version "0.1.2" 7 + resolved "https://registry.yarnpkg.com/@0no-co/graphql.web/-/graphql.web-0.1.2.tgz#6a8f71bad35e1db0f1c464bc5aaf7a8d02c03b23" 8 + integrity sha512-Jgn4aaiXit6yDL4tBZvv1wV2x9rCEsElqpeNxO80NHUNOPP+QY9VxA1dq9RTSaeaeN6/i994gNV+UvRIX3gQLQ== 9 + 5 10 "@babel/code-frame@7.12.11": 6 11 version "7.12.11" 7 12 resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f"