Mirror: The spec-compliant minimum of client-side GraphQL.
0
fork

Configure Feed

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

Add initial utilities

+1202 -61
+109 -61
pnpm-lock.yaml
··· 1 1 lockfileVersion: 5.4 2 2 3 - specifiers: 4 - '@changesets/cli': ^2.26.0 5 - '@changesets/get-github-info': ^0.5.2 6 - '@rollup/plugin-buble': ^1.0.2 7 - '@rollup/plugin-commonjs': ^24.0.1 8 - '@rollup/plugin-node-resolve': ^15.0.1 9 - '@rollup/plugin-sucrase': ^5.0.1 10 - '@rollup/plugin-terser': ^0.4.0 11 - '@typescript-eslint/eslint-plugin': ^5.55.0 12 - '@typescript-eslint/parser': ^5.55.0 13 - eslint: ^8.36.0 14 - eslint-config-prettier: ^8.7.0 15 - eslint-plugin-prettier: ^4.2.1 16 - eslint-plugin-tsdoc: ^0.2.17 17 - husky-v4: ^4.3.8 18 - lint-staged: ^13.2.0 19 - npm-run-all: ^4.1.5 20 - prettier: ^2.8.4 21 - rimraf: ^4.4.0 22 - rollup: ^3.19.1 23 - rollup-plugin-cjs-check: ^1.0.2 24 - rollup-plugin-dts: ^5.3.0 25 - terser: ^5.16.6 26 - typescript: ^5.0.2 27 - vitest: ^0.29.3 3 + importers: 28 4 29 - devDependencies: 30 - '@changesets/cli': 2.26.0 31 - '@changesets/get-github-info': 0.5.2 32 - '@rollup/plugin-buble': 1.0.2_rollup@3.19.1 33 - '@rollup/plugin-commonjs': 24.0.1_rollup@3.19.1 34 - '@rollup/plugin-node-resolve': 15.0.1_rollup@3.19.1 35 - '@rollup/plugin-sucrase': 5.0.1_rollup@3.19.1 36 - '@rollup/plugin-terser': 0.4.0_rollup@3.19.1 37 - '@typescript-eslint/eslint-plugin': 5.55.0_qsnvknysi52qtaxqdyqyohkcku 38 - '@typescript-eslint/parser': 5.55.0_j4766f7ecgqbon3u7zlxn5zszu 39 - eslint: 8.36.0 40 - eslint-config-prettier: 8.7.0_eslint@8.36.0 41 - eslint-plugin-prettier: 4.2.1_eqzx3hpkgx5nnvxls3azrcc7dm 42 - eslint-plugin-tsdoc: 0.2.17 43 - husky-v4: 4.3.8 44 - lint-staged: 13.2.0 45 - npm-run-all: 4.1.5 46 - prettier: 2.8.4 47 - rimraf: 4.4.0 48 - rollup: 3.19.1 49 - rollup-plugin-cjs-check: 1.0.2_rollup@3.19.1 50 - rollup-plugin-dts: 5.3.0_7iejawhbqmte5pthjozf4tfuqy 51 - terser: 5.16.6 52 - typescript: 5.0.2 53 - vitest: 0.29.3_terser@5.16.6 5 + .: 6 + specifiers: 7 + '@changesets/cli': ^2.26.0 8 + '@changesets/get-github-info': ^0.5.2 9 + '@rollup/plugin-buble': ^1.0.2 10 + '@rollup/plugin-commonjs': ^24.0.1 11 + '@rollup/plugin-node-resolve': ^15.0.1 12 + '@rollup/plugin-sucrase': ^5.0.1 13 + '@rollup/plugin-terser': ^0.4.0 14 + '@typescript-eslint/eslint-plugin': ^5.55.0 15 + '@typescript-eslint/parser': ^5.55.0 16 + eslint: ^8.36.0 17 + eslint-config-prettier: ^8.7.0 18 + eslint-plugin-prettier: ^4.2.1 19 + eslint-plugin-tsdoc: ^0.2.17 20 + husky-v4: ^4.3.8 21 + lint-staged: ^13.2.0 22 + npm-run-all: ^4.1.5 23 + prettier: ^2.8.4 24 + rimraf: ^4.4.0 25 + rollup: ^3.19.1 26 + rollup-plugin-cjs-check: ^1.0.2 27 + rollup-plugin-dts: ^5.3.0 28 + terser: ^5.16.6 29 + typescript: ^5.0.2 30 + vitest: ^0.29.3 31 + devDependencies: 32 + '@changesets/cli': 2.26.0 33 + '@changesets/get-github-info': 0.5.2 34 + '@rollup/plugin-buble': 1.0.2_rollup@3.19.1 35 + '@rollup/plugin-commonjs': 24.0.1_rollup@3.19.1 36 + '@rollup/plugin-node-resolve': 15.0.1_rollup@3.19.1 37 + '@rollup/plugin-sucrase': 5.0.1_rollup@3.19.1 38 + '@rollup/plugin-terser': 0.4.0_rollup@3.19.1 39 + '@typescript-eslint/eslint-plugin': 5.55.0_qsnvknysi52qtaxqdyqyohkcku 40 + '@typescript-eslint/parser': 5.55.0_j4766f7ecgqbon3u7zlxn5zszu 41 + eslint: 8.36.0 42 + eslint-config-prettier: 8.7.0_eslint@8.36.0 43 + eslint-plugin-prettier: 4.2.1_eqzx3hpkgx5nnvxls3azrcc7dm 44 + eslint-plugin-tsdoc: 0.2.17 45 + husky-v4: 4.3.8 46 + lint-staged: 13.2.0 47 + npm-run-all: 4.1.5 48 + prettier: 2.8.4 49 + rimraf: 4.4.0 50 + rollup: 3.19.1 51 + rollup-plugin-cjs-check: 1.0.2_rollup@3.19.1 52 + rollup-plugin-dts: 5.3.0_7iejawhbqmte5pthjozf4tfuqy 53 + terser: 5.16.6 54 + typescript: 5.0.2 55 + vitest: 0.29.3_terser@5.16.6 56 + 57 + benchmark: 58 + specifiers: 59 + benchr: 4.3.0 60 + graphql: ^16.6.0 61 + dependencies: 62 + benchr: 4.3.0 63 + graphql: 16.6.0 54 64 55 65 packages: 56 66 ··· 1013 1023 /ansi-regex/5.0.1: 1014 1024 resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 1015 1025 engines: {node: '>=8'} 1016 - dev: true 1017 1026 1018 1027 /ansi-regex/6.0.1: 1019 1028 resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} ··· 1025 1034 engines: {node: '>=4'} 1026 1035 dependencies: 1027 1036 color-convert: 1.9.3 1028 - dev: true 1029 1037 1030 1038 /ansi-styles/4.3.0: 1031 1039 resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} ··· 1103 1111 resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 1104 1112 dev: true 1105 1113 1114 + /benchmark/2.1.4: 1115 + resolution: {integrity: sha512-l9MlfN4M1K/H2fbhfMy3B7vJd6AGKJVQn2h6Sg/Yx+KckoUA7ewS5Vv6TjSq18ooE1kS9hhAlQRH3AkXIh/aOQ==} 1116 + dependencies: 1117 + lodash: 4.17.21 1118 + platform: 1.3.6 1119 + dev: false 1120 + 1121 + /benchr/4.3.0: 1122 + resolution: {integrity: sha512-ZOJkEOLOI4vyf34fnUSmh+xvg8P86cmVfyORBgIJHLfXMuvrfkMsUEThMaJND406KGCigtBO6sMjExGbp+WeLw==} 1123 + engines: {node: '>=6.0.0'} 1124 + hasBin: true 1125 + dependencies: 1126 + benchmark: 2.1.4 1127 + chalk: 2.4.2 1128 + docopt: 0.6.2 1129 + easy-table: 1.2.0 1130 + require-all: 2.2.0 1131 + dev: false 1132 + 1106 1133 /better-path-resolve/1.0.0: 1107 1134 resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} 1108 1135 engines: {node: '>=4'} ··· 1209 1236 ansi-styles: 3.2.1 1210 1237 escape-string-regexp: 1.0.5 1211 1238 supports-color: 5.5.0 1212 - dev: true 1213 1239 1214 1240 /chalk/4.1.2: 1215 1241 resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} ··· 1293 1319 /clone/1.0.4: 1294 1320 resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} 1295 1321 engines: {node: '>=0.8'} 1296 - dev: true 1297 1322 1298 1323 /color-convert/1.9.3: 1299 1324 resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} 1300 1325 dependencies: 1301 1326 color-name: 1.1.3 1302 - dev: true 1303 1327 1304 1328 /color-convert/2.0.1: 1305 1329 resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} ··· 1310 1334 1311 1335 /color-name/1.1.3: 1312 1336 resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} 1313 - dev: true 1314 1337 1315 1338 /color-name/1.1.4: 1316 1339 resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} ··· 1456 1479 resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} 1457 1480 dependencies: 1458 1481 clone: 1.0.4 1459 - dev: true 1460 1482 1461 1483 /define-properties/1.2.0: 1462 1484 resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==} ··· 1483 1505 path-type: 4.0.0 1484 1506 dev: true 1485 1507 1508 + /docopt/0.6.2: 1509 + resolution: {integrity: sha512-NqTbaYeE4gA/wU1hdKFdU+AFahpDOpgGLzHP42k6H6DKExJd0A55KEVWYhL9FEmHmgeLvEU2vuKXDuU+4yToOw==} 1510 + engines: {node: '>=0.10.0'} 1511 + dev: false 1512 + 1486 1513 /doctrine/3.0.0: 1487 1514 resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} 1488 1515 engines: {node: '>=6.0.0'} ··· 1493 1520 /eastasianwidth/0.2.0: 1494 1521 resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} 1495 1522 dev: true 1523 + 1524 + /easy-table/1.2.0: 1525 + resolution: {integrity: sha512-OFzVOv03YpvtcWGe5AayU5G2hgybsg3iqA6drU8UaoZyB9jLGMTrz9+asnLp/E+6qPh88yEI1gvyZFZ41dmgww==} 1526 + dependencies: 1527 + ansi-regex: 5.0.1 1528 + optionalDependencies: 1529 + wcwidth: 1.0.1 1530 + dev: false 1496 1531 1497 1532 /emoji-regex/8.0.0: 1498 1533 resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} ··· 1617 1652 /escape-string-regexp/1.0.5: 1618 1653 resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} 1619 1654 engines: {node: '>=0.8.0'} 1620 - dev: true 1621 1655 1622 1656 /escape-string-regexp/4.0.0: 1623 1657 resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} ··· 2072 2106 /grapheme-splitter/1.0.4: 2073 2107 resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} 2074 2108 dev: true 2109 + 2110 + /graphql/16.6.0: 2111 + resolution: {integrity: sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw==} 2112 + engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} 2113 + dev: false 2075 2114 2076 2115 /hard-rejection/2.1.0: 2077 2116 resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} ··· 2085 2124 /has-flag/3.0.0: 2086 2125 resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} 2087 2126 engines: {node: '>=4'} 2088 - dev: true 2089 2127 2090 2128 /has-flag/4.0.0: 2091 2129 resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} ··· 2559 2597 /lodash.startcase/4.4.0: 2560 2598 resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} 2561 2599 dev: true 2600 + 2601 + /lodash/4.17.21: 2602 + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} 2603 + dev: false 2562 2604 2563 2605 /log-update/4.0.0: 2564 2606 resolution: {integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==} ··· 3079 3121 pathe: 1.1.0 3080 3122 dev: true 3081 3123 3124 + /platform/1.3.6: 3125 + resolution: {integrity: sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==} 3126 + dev: false 3127 + 3082 3128 /please-upgrade-node/3.2.0: 3083 3129 resolution: {integrity: sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==} 3084 3130 dependencies: ··· 3252 3298 jsesc: 0.5.0 3253 3299 dev: true 3254 3300 3301 + /require-all/2.2.0: 3302 + resolution: {integrity: sha512-YWj/WNCxs+KxppuN3j11Ztqzl8MI/oWj4ERwEwgJ5gsHzWi8OAK7FepPu8MLv/Rn8Pov6aPdpRkaoO2Tb6m+zQ==} 3303 + dev: false 3304 + 3255 3305 /require-directory/2.1.1: 3256 3306 resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} 3257 3307 engines: {node: '>=0.10.0'} ··· 3690 3740 engines: {node: '>=4'} 3691 3741 dependencies: 3692 3742 has-flag: 3.0.0 3693 - dev: true 3694 3743 3695 3744 /supports-color/7.2.0: 3696 3745 resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} ··· 4034 4083 resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} 4035 4084 dependencies: 4036 4085 defaults: 1.0.4 4037 - dev: true 4038 4086 4039 4087 /webidl-conversions/3.0.1: 4040 4088 resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
+251
src/ast.ts
··· 1 + import type { Kind } from './kind'; 2 + 3 + export interface Location { 4 + readonly start: number; 5 + readonly end: number; 6 + readonly source: Source; 7 + } 8 + 9 + export interface Source { 10 + body: string; 11 + name: string; 12 + locationOffset: { 13 + line: number; 14 + column: number; 15 + }; 16 + } 17 + 18 + export declare type ASTNode = 19 + | NameNode 20 + | DocumentNode 21 + | OperationDefinitionNode 22 + | VariableDefinitionNode 23 + | VariableNode 24 + | SelectionSetNode 25 + | FieldNode 26 + | ArgumentNode 27 + | FragmentSpreadNode 28 + | InlineFragmentNode 29 + | FragmentDefinitionNode 30 + | IntValueNode 31 + | FloatValueNode 32 + | StringValueNode 33 + | BooleanValueNode 34 + | NullValueNode 35 + | EnumValueNode 36 + | ListValueNode 37 + | ObjectValueNode 38 + | ObjectFieldNode 39 + | DirectiveNode 40 + | NamedTypeNode 41 + | ListTypeNode 42 + | NonNullTypeNode; 43 + 44 + export interface NameNode { 45 + readonly kind: Kind.NAME; 46 + readonly value: string; 47 + } 48 + 49 + export interface DocumentNode { 50 + readonly kind: Kind.DOCUMENT; 51 + readonly definitions: ReadonlyArray<ExecutableDefinitionNode>; 52 + readonly loc?: Location; 53 + } 54 + 55 + export type DefinitionNode = 56 + | OperationDefinitionNode 57 + | FragmentDefinitionNode; 58 + export type ExecutableDefinitionNode = 59 + | OperationDefinitionNode 60 + | FragmentDefinitionNode; 61 + 62 + export interface OperationDefinitionNode { 63 + readonly kind: Kind.OPERATION_DEFINITION; 64 + readonly operation: OperationTypeNode; 65 + readonly name?: NameNode; 66 + readonly variableDefinitions?: ReadonlyArray<VariableDefinitionNode>; 67 + readonly directives?: ReadonlyArray<DirectiveNode>; 68 + readonly selectionSet: SelectionSetNode; 69 + } 70 + 71 + export const enum OperationTypeNode { 72 + QUERY = 'query', 73 + MUTATION = 'mutation', 74 + SUBSCRIPTION = 'subscription', 75 + } 76 + 77 + export interface VariableDefinitionNode { 78 + readonly kind: Kind.VARIABLE_DEFINITION; 79 + readonly variable: VariableNode; 80 + readonly type: TypeNode; 81 + readonly defaultValue?: ConstValueNode; 82 + readonly directives?: ReadonlyArray<ConstDirectiveNode>; 83 + } 84 + 85 + export interface VariableNode { 86 + readonly kind: Kind.VARIABLE; 87 + readonly name: NameNode; 88 + } 89 + 90 + export interface SelectionSetNode { 91 + kind: Kind.SELECTION_SET; 92 + selections: ReadonlyArray<SelectionNode>; 93 + } 94 + 95 + export declare type SelectionNode = 96 + | FieldNode 97 + | FragmentSpreadNode 98 + | InlineFragmentNode; 99 + 100 + export interface FieldNode { 101 + readonly kind: Kind.FIELD; 102 + readonly alias?: NameNode; 103 + readonly name: NameNode; 104 + readonly arguments?: ReadonlyArray<ArgumentNode>; 105 + readonly directives?: ReadonlyArray<DirectiveNode>; 106 + readonly selectionSet?: SelectionSetNode; 107 + } 108 + 109 + export interface ArgumentNode { 110 + readonly kind: Kind.ARGUMENT; 111 + readonly name: NameNode; 112 + readonly value: ValueNode; 113 + } 114 + 115 + export interface ConstArgumentNode { 116 + readonly kind: Kind.ARGUMENT; 117 + readonly name: NameNode; 118 + readonly value: ConstValueNode; 119 + } 120 + 121 + export interface FragmentSpreadNode { 122 + readonly kind: Kind.FRAGMENT_SPREAD; 123 + readonly name: NameNode; 124 + readonly directives?: ReadonlyArray<DirectiveNode>; 125 + } 126 + 127 + export interface InlineFragmentNode { 128 + readonly kind: Kind.INLINE_FRAGMENT; 129 + readonly typeCondition?: NamedTypeNode; 130 + readonly directives?: ReadonlyArray<DirectiveNode>; 131 + readonly selectionSet: SelectionSetNode; 132 + } 133 + 134 + export interface FragmentDefinitionNode { 135 + readonly kind: Kind.FRAGMENT_DEFINITION; 136 + readonly name: NameNode; 137 + readonly typeCondition: NamedTypeNode; 138 + readonly directives?: ReadonlyArray<DirectiveNode>; 139 + readonly selectionSet: SelectionSetNode; 140 + } 141 + 142 + export type ValueNode = 143 + | VariableNode 144 + | IntValueNode 145 + | FloatValueNode 146 + | StringValueNode 147 + | BooleanValueNode 148 + | NullValueNode 149 + | EnumValueNode 150 + | ListValueNode 151 + | ObjectValueNode; 152 + 153 + export type ConstValueNode = 154 + | IntValueNode 155 + | FloatValueNode 156 + | StringValueNode 157 + | BooleanValueNode 158 + | NullValueNode 159 + | EnumValueNode 160 + | ConstListValueNode 161 + | ConstObjectValueNode; 162 + 163 + export interface IntValueNode { 164 + readonly kind: Kind.INT; 165 + readonly value: string; 166 + } 167 + 168 + export interface FloatValueNode { 169 + readonly kind: Kind.FLOAT; 170 + readonly value: string; 171 + } 172 + export interface StringValueNode { 173 + readonly kind: Kind.STRING; 174 + readonly value: string; 175 + readonly block?: boolean; 176 + } 177 + 178 + export interface BooleanValueNode { 179 + readonly kind: Kind.BOOLEAN; 180 + readonly value: boolean; 181 + } 182 + 183 + export interface NullValueNode { 184 + readonly kind: Kind.NULL; 185 + } 186 + 187 + export interface EnumValueNode { 188 + readonly kind: Kind.ENUM; 189 + readonly value: string; 190 + } 191 + 192 + export interface ListValueNode { 193 + readonly kind: Kind.LIST; 194 + readonly values: ReadonlyArray<ValueNode>; 195 + } 196 + 197 + export interface ConstListValueNode { 198 + readonly kind: Kind.LIST; 199 + readonly values: ReadonlyArray<ConstValueNode>; 200 + } 201 + 202 + export interface ObjectValueNode { 203 + readonly kind: Kind.OBJECT; 204 + readonly fields: ReadonlyArray<ObjectFieldNode>; 205 + } 206 + 207 + export interface ConstObjectValueNode { 208 + readonly kind: Kind.OBJECT; 209 + readonly fields: ReadonlyArray<ConstObjectFieldNode>; 210 + } 211 + 212 + export interface ObjectFieldNode { 213 + readonly kind: Kind.OBJECT_FIELD; 214 + readonly name: NameNode; 215 + readonly value: ValueNode; 216 + } 217 + 218 + export interface ConstObjectFieldNode { 219 + readonly kind: Kind.OBJECT_FIELD; 220 + readonly name: NameNode; 221 + readonly value: ConstValueNode; 222 + } 223 + 224 + export interface DirectiveNode { 225 + readonly kind: Kind.DIRECTIVE; 226 + readonly name: NameNode; 227 + readonly arguments?: ReadonlyArray<ArgumentNode>; 228 + } 229 + 230 + export interface ConstDirectiveNode { 231 + readonly kind: Kind.DIRECTIVE; 232 + readonly name: NameNode; 233 + readonly arguments?: ReadonlyArray<ConstArgumentNode>; 234 + } 235 + 236 + export declare type TypeNode = NamedTypeNode | ListTypeNode | NonNullTypeNode; 237 + 238 + export interface NamedTypeNode { 239 + readonly kind: Kind.NAMED_TYPE; 240 + readonly name: NameNode; 241 + } 242 + 243 + export interface ListTypeNode { 244 + readonly kind: Kind.LIST_TYPE; 245 + readonly type: TypeNode; 246 + } 247 + 248 + export interface NonNullTypeNode { 249 + readonly kind: Kind.NON_NULL_TYPE; 250 + readonly type: NamedTypeNode | ListTypeNode; 251 + }
+51
src/error.ts
··· 1 + import { Maybe, Extensions } from './types'; 2 + import { ASTNode, Source } from './ast'; 3 + 4 + export class GraphQLError extends Error { 5 + readonly locations: undefined; 6 + readonly path: ReadonlyArray<string | number> | undefined; 7 + readonly nodes: ReadonlyArray<ASTNode> | undefined; 8 + readonly source: Source | undefined; 9 + readonly positions: ReadonlyArray<number> | undefined; 10 + readonly originalError: Error | undefined; 11 + readonly extensions: Extensions; 12 + 13 + constructor( 14 + message: string, 15 + nodes?: ReadonlyArray<ASTNode> | ASTNode | null, 16 + source?: Maybe<Source>, 17 + positions?: Maybe<ReadonlyArray<number>>, 18 + path?: Maybe<ReadonlyArray<string | number>>, 19 + originalError?: Maybe<Error>, 20 + extensions?: Maybe<Extensions>, 21 + ) { 22 + super(message); 23 + 24 + this.name = 'GraphQLError'; 25 + this.message = message; 26 + 27 + if (path) this.path = path; 28 + if (nodes) this.nodes = (Array.isArray(nodes) ? nodes : [nodes]) as ASTNode[]; 29 + if (source) this.source = source; 30 + if (positions) this.positions = positions; 31 + if (originalError) this.originalError = originalError; 32 + 33 + let _extensions = extensions; 34 + if (!_extensions && originalError) { 35 + const originalExtensions = (originalError as any).extensions; 36 + if (originalExtensions && typeof originalExtensions === 'object') { 37 + _extensions = originalExtensions; 38 + } 39 + } 40 + 41 + this.extensions = extensions || {}; 42 + } 43 + 44 + toJSON() { 45 + return { ...this }; 46 + } 47 + 48 + toString() { 49 + return this.message; 50 + } 51 + }
+6
src/index.ts
··· 1 + export * from './ast'; 2 + export * from './kind'; 3 + export * from './error'; 4 + export * from './parser'; 5 + export * from './visitor'; 6 + export * from './printer';
+32
src/kind.ts
··· 1 + export enum Kind { 2 + /** Name */ 3 + NAME = 'Name', 4 + /** Document */ 5 + DOCUMENT = 'Document', 6 + OPERATION_DEFINITION = 'OperationDefinition', 7 + VARIABLE_DEFINITION = 'VariableDefinition', 8 + SELECTION_SET = 'SelectionSet', 9 + FIELD = 'Field', 10 + ARGUMENT = 'Argument', 11 + /** Fragments */ 12 + FRAGMENT_SPREAD = 'FragmentSpread', 13 + INLINE_FRAGMENT = 'InlineFragment', 14 + FRAGMENT_DEFINITION = 'FragmentDefinition', 15 + /** Values */ 16 + VARIABLE = 'Variable', 17 + INT = 'IntValue', 18 + FLOAT = 'FloatValue', 19 + STRING = 'StringValue', 20 + BOOLEAN = 'BooleanValue', 21 + NULL = 'NullValue', 22 + ENUM = 'EnumValue', 23 + LIST = 'ListValue', 24 + OBJECT = 'ObjectValue', 25 + OBJECT_FIELD = 'ObjectField', 26 + /** Directives */ 27 + DIRECTIVE = 'Directive', 28 + /** Types */ 29 + NAMED_TYPE = 'NamedType', 30 + LIST_TYPE = 'ListType', 31 + NON_NULL_TYPE = 'NonNullType', 32 + }
+480
src/parser.ts
··· 1 + /** 2 + * This is a spec-compliant implementation of a GraphQL query language parser, 3 + * up-to-date with the October 2021 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 './kind'; 8 + import { GraphQLError } from './error'; 9 + import type * as ast from './ast'; 10 + 11 + let input: string; 12 + let idx: number; 13 + 14 + function error(kind: Kind) { 15 + return new GraphQLError(`Syntax Error: Unexpected token at ${idx} in ${kind}`); 16 + } 17 + 18 + function advance(pattern: RegExp) { 19 + pattern.lastIndex = idx; 20 + if (pattern.test(input)) { 21 + const match = input.slice(idx, idx = pattern.lastIndex); 22 + return match; 23 + } 24 + } 25 + 26 + const leadingRe = / +(?=[^\s])/y; 27 + export function blockString(string: string) { 28 + let out = ''; 29 + let commonIndent = 0; 30 + let firstNonEmptyLine = 0; 31 + let lastNonEmptyLine = -1; 32 + const lines = string.split('\n'); 33 + for (let i = 0; i < lines.length; i++) { 34 + leadingRe.lastIndex = 0; 35 + if (leadingRe.test(lines[i])) { 36 + if (i && (!commonIndent || leadingRe.lastIndex < commonIndent)) 37 + commonIndent = leadingRe.lastIndex; 38 + firstNonEmptyLine = firstNonEmptyLine || i; 39 + lastNonEmptyLine = i; 40 + } 41 + } 42 + for (let i = firstNonEmptyLine; i <= lastNonEmptyLine; i++) { 43 + if (i !== firstNonEmptyLine) out += '\n'; 44 + out += lines[i].slice(commonIndent); 45 + } 46 + return out; 47 + } 48 + 49 + const ignoredRe = /(?:[\s,]*|#[^\n\r]*)*/y; 50 + function ignored() { 51 + ignoredRe.lastIndex = idx; 52 + ignoredRe.test(input); 53 + idx = ignoredRe.lastIndex; 54 + } 55 + 56 + const nameRe = /[_\w][_\d\w]*/y; 57 + function name(): ast.NameNode | undefined { 58 + let match: string | undefined; 59 + if (match = advance(nameRe)) { 60 + return { 61 + kind: Kind.NAME, 62 + value: match, 63 + }; 64 + } 65 + } 66 + 67 + const nullRe = /null/y; 68 + const boolRe = /true|false/y; 69 + const variableRe = /\$[_\w][_\d\w]*/y; 70 + const intRe = /[-]?\d+/y; 71 + const floatRe = /[-]?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/y; 72 + const complexStringRe = /\\/g; 73 + const blockStringRe = /"""(?:[\s\S]+(?="""))?"""/y; 74 + const stringRe = /"(?:[^"\r\n]+)?"/y; 75 + 76 + function value(constant: true): ast.ConstValueNode; 77 + function value(constant: boolean): ast.ValueNode; 78 + 79 + function value(constant: boolean): ast.ValueNode | undefined { 80 + let out: ast.ValueNode | undefined; 81 + let match: string | undefined; 82 + if (advance(nullRe)) { 83 + out = { kind: Kind.NULL }; 84 + } else if (match = advance(boolRe)) { 85 + out = { 86 + kind: Kind.BOOLEAN, 87 + value: match === 'true', 88 + }; 89 + } else if (!constant && (match = advance(variableRe))) { 90 + out = { 91 + kind: Kind.VARIABLE, 92 + name: { 93 + kind: Kind.NAME, 94 + value: match.slice(1), 95 + }, 96 + }; 97 + } else if (match = advance(floatRe)) { 98 + out = { 99 + kind: Kind.FLOAT, 100 + value: match, 101 + }; 102 + } else if (match = advance(intRe)) { 103 + out = { 104 + kind: Kind.INT, 105 + value: match, 106 + }; 107 + } else if (match = advance(nameRe)) { 108 + out = { 109 + kind: Kind.ENUM, 110 + value: match, 111 + }; 112 + } else if (match = advance(blockStringRe)) { 113 + out = { 114 + kind: Kind.STRING, 115 + value: blockString(match.slice(3, -3)), 116 + block: true, 117 + }; 118 + } else if (match = advance(stringRe)) { 119 + out = { 120 + kind: Kind.STRING, 121 + value: complexStringRe.test(match) 122 + ? JSON.parse(match) as string 123 + : match.slice(1, -1), 124 + block: false, 125 + }; 126 + } else if (out = list(constant) || object(constant)) { 127 + return out; 128 + } 129 + 130 + ignored(); 131 + return out; 132 + } 133 + 134 + function list(constant: boolean): ast.ListValueNode | undefined { 135 + let match: ast.ValueNode | undefined; 136 + if (input.charCodeAt(idx) === 91 /*'['*/) { 137 + idx++; 138 + ignored(); 139 + const values: ast.ValueNode[] = []; 140 + while (match = value(constant)) 141 + values.push(match); 142 + if (input.charCodeAt(idx++) !== 93 /*']'*/) 143 + throw error(Kind.LIST); 144 + ignored(); 145 + return { 146 + kind: Kind.LIST, 147 + values, 148 + }; 149 + } 150 + } 151 + 152 + function object(constant: boolean): ast.ObjectValueNode | undefined { 153 + if (input.charCodeAt(idx) === 123 /*'{'*/) { 154 + idx++; 155 + ignored(); 156 + const fields: ast.ObjectFieldNode[] = []; 157 + let _name: ast.NameNode | undefined; 158 + while (_name = name()) { 159 + ignored(); 160 + if (input.charCodeAt(idx++) !== 58 /*':'*/) 161 + throw error(Kind.OBJECT_FIELD); 162 + ignored(); 163 + const _value = value(constant); 164 + if (!_value) 165 + throw error(Kind.OBJECT_FIELD); 166 + fields.push({ 167 + kind: Kind.OBJECT_FIELD, 168 + name: _name, 169 + value: _value, 170 + }); 171 + } 172 + if (input.charCodeAt(idx++) !== 125 /*'}'*/) 173 + throw error(Kind.OBJECT); 174 + ignored(); 175 + return { 176 + kind: Kind.OBJECT, 177 + fields, 178 + }; 179 + } 180 + } 181 + 182 + function arguments_(constant: boolean): ast.ArgumentNode[] { 183 + const args: ast.ArgumentNode[] = []; 184 + ignored(); 185 + if (input.charCodeAt(idx) === 40 /*'('*/) { 186 + idx++; 187 + ignored(); 188 + let _name: ast.NameNode | undefined; 189 + while (_name = name()) { 190 + ignored(); 191 + if (input.charCodeAt(idx++) !== 58 /*':'*/) 192 + throw error(Kind.ARGUMENT); 193 + ignored(); 194 + const _value = value(constant); 195 + if (!_value) 196 + throw error(Kind.ARGUMENT); 197 + args.push({ 198 + kind: Kind.ARGUMENT, 199 + name: _name, 200 + value: _value, 201 + }); 202 + } 203 + if (!args.length || input.charCodeAt(idx++) !== 41 /*')'*/) 204 + throw error(Kind.ARGUMENT); 205 + ignored(); 206 + } 207 + return args; 208 + } 209 + 210 + function directives(constant: true): ast.ConstDirectiveNode[]; 211 + function directives(constant: boolean): ast.DirectiveNode[]; 212 + 213 + function directives(constant: boolean): ast.DirectiveNode[] { 214 + const directives: ast.DirectiveNode[] = []; 215 + ignored(); 216 + while (input.charCodeAt(idx) === 64 /*'@'*/) { 217 + idx++; 218 + const _name = name(); 219 + if (!_name) 220 + throw error(Kind.DIRECTIVE); 221 + ignored(); 222 + directives.push({ 223 + kind: Kind.DIRECTIVE, 224 + name: _name, 225 + arguments: arguments_(constant), 226 + }); 227 + } 228 + return directives; 229 + } 230 + 231 + function field(): ast.FieldNode | undefined { 232 + ignored(); 233 + let _name = name(); 234 + if (_name) { 235 + ignored(); 236 + let _alias: ast.NameNode | undefined; 237 + if (input.charCodeAt(idx) === 58 /*':'*/) { 238 + idx++; 239 + ignored(); 240 + _alias = _name; 241 + _name = name(); 242 + if (!_name) 243 + throw error(Kind.FIELD); 244 + ignored(); 245 + } 246 + return { 247 + kind: Kind.FIELD, 248 + alias: _alias, 249 + name: _name, 250 + arguments: arguments_(false), 251 + directives: directives(false), 252 + selectionSet: selectionSet(), 253 + }; 254 + } 255 + } 256 + 257 + function type(): ast.TypeNode | undefined { 258 + let match: ast.NameNode | ast.TypeNode | undefined; 259 + ignored(); 260 + if (input.charCodeAt(idx) === 91 /*'['*/) { 261 + idx++; 262 + ignored(); 263 + const _type = type(); 264 + if (!_type || input.charCodeAt(idx++) !== 93 /*']'*/) 265 + throw error(Kind.LIST_TYPE); 266 + match = { 267 + kind: Kind.LIST_TYPE, 268 + type: _type, 269 + }; 270 + } else if (match = name()) { 271 + match = { 272 + kind: Kind.NAMED_TYPE, 273 + name: match, 274 + }; 275 + } else { 276 + throw error(Kind.NAMED_TYPE); 277 + } 278 + 279 + ignored(); 280 + if (input.charCodeAt(idx) === 33 /*'!'*/) { 281 + idx++; 282 + ignored(); 283 + return { 284 + kind: Kind.NON_NULL_TYPE, 285 + type: match, 286 + }; 287 + } else { 288 + return match; 289 + } 290 + } 291 + 292 + const typeConditionRe = /on/y; 293 + function typeCondition(): ast.NamedTypeNode | undefined { 294 + if (advance(typeConditionRe)) { 295 + ignored(); 296 + const _name = name(); 297 + if (!_name) 298 + throw error(Kind.NAMED_TYPE); 299 + ignored(); 300 + return { 301 + kind: Kind.NAMED_TYPE, 302 + name: _name, 303 + }; 304 + } 305 + } 306 + 307 + const fragmentSpreadRe = /\.\.\./y; 308 + 309 + function fragmentSpread(): ast.FragmentSpreadNode | ast.InlineFragmentNode | undefined { 310 + ignored(); 311 + if (advance(fragmentSpreadRe)) { 312 + ignored(); 313 + let _name: ast.NameNode | undefined; 314 + if (_name = name()) { 315 + return { 316 + kind: Kind.FRAGMENT_SPREAD, 317 + name: _name, 318 + directives: directives(false), 319 + }; 320 + } else { 321 + const _typeCondition = typeCondition(); 322 + const _directives = directives(false); 323 + const _selectionSet = selectionSet(); 324 + if (!_selectionSet) 325 + throw error(Kind.INLINE_FRAGMENT); 326 + return { 327 + kind: Kind.INLINE_FRAGMENT, 328 + typeCondition: _typeCondition, 329 + directives: _directives, 330 + selectionSet: _selectionSet, 331 + }; 332 + } 333 + } 334 + } 335 + 336 + function selectionSet(): ast.SelectionSetNode | undefined { 337 + let match: ast.SelectionNode | undefined; 338 + ignored(); 339 + if (input.charCodeAt(idx) === 123 /*'{'*/) { 340 + idx++; 341 + ignored(); 342 + const selections: ast.SelectionNode[] = []; 343 + while (match = fragmentSpread() || field()) 344 + selections.push(match); 345 + if (!selections.length || input.charCodeAt(idx++) !== 125 /*'}'*/) 346 + throw error(Kind.SELECTION_SET); 347 + ignored(); 348 + return { 349 + kind: Kind.SELECTION_SET, 350 + selections, 351 + }; 352 + } 353 + } 354 + 355 + function variableDefinitions(): ast.VariableDefinitionNode[] { 356 + let match: string | undefined; 357 + const vars: ast.VariableDefinitionNode[] = []; 358 + ignored(); 359 + if (input.charCodeAt(idx) === 40 /*'('*/) { 360 + idx++; 361 + ignored(); 362 + while (match = advance(variableRe)) { 363 + ignored(); 364 + if (input.charCodeAt(idx++) !== 58 /*':'*/) 365 + throw error(Kind.VARIABLE_DEFINITION); 366 + const _type = type(); 367 + if (!_type) 368 + throw error(Kind.VARIABLE_DEFINITION); 369 + let _defaultValue: ast.ValueNode | undefined; 370 + if (input.charCodeAt(idx) === 61 /*'='*/) { 371 + idx++; 372 + ignored(); 373 + _defaultValue = value(true); 374 + if (!_defaultValue) 375 + throw error(Kind.VARIABLE_DEFINITION); 376 + } 377 + ignored(); 378 + vars.push({ 379 + kind: Kind.VARIABLE_DEFINITION, 380 + variable: { 381 + kind: Kind.VARIABLE, 382 + name: { 383 + kind: Kind.NAME, 384 + value: match.slice(1), 385 + }, 386 + }, 387 + type: _type, 388 + defaultValue: _defaultValue as ast.ConstValueNode, 389 + directives: directives(true), 390 + }); 391 + } 392 + if (input.charCodeAt(idx++) !== 41 /*')'*/) 393 + throw error(Kind.VARIABLE_DEFINITION); 394 + ignored(); 395 + } 396 + return vars; 397 + } 398 + 399 + const fragmentDefinitionRe = /fragment/y; 400 + function fragmentDefinition(): ast.FragmentDefinitionNode | undefined { 401 + if (advance(fragmentDefinitionRe)) { 402 + ignored(); 403 + const _name = name(); 404 + if (!_name) 405 + throw error(Kind.FRAGMENT_DEFINITION); 406 + ignored(); 407 + const _typeCondition = typeCondition(); 408 + if (!_typeCondition) 409 + throw error(Kind.FRAGMENT_DEFINITION); 410 + const _directives = directives(false); 411 + const _selectionSet = selectionSet(); 412 + if (!_selectionSet) 413 + throw error(Kind.FRAGMENT_DEFINITION); 414 + return { 415 + kind: Kind.FRAGMENT_DEFINITION, 416 + name: _name, 417 + typeCondition: _typeCondition, 418 + directives: _directives, 419 + selectionSet: _selectionSet, 420 + }; 421 + } 422 + } 423 + 424 + const operationDefinitionRe = /query|mutation|subscription/y; 425 + function operationDefinition(): ast.OperationDefinitionNode | undefined { 426 + let _operation: string | undefined; 427 + let _name: ast.NameNode | undefined; 428 + let _variableDefinitions: ast.VariableDefinitionNode[] = []; 429 + let _directives: ast.DirectiveNode[] = []; 430 + if (_operation = advance(operationDefinitionRe)) { 431 + ignored(); 432 + _name = name(); 433 + _variableDefinitions = variableDefinitions(); 434 + _directives = directives(false); 435 + } 436 + const _selectionSet = selectionSet(); 437 + if (_selectionSet) { 438 + return { 439 + kind: Kind.OPERATION_DEFINITION, 440 + operation: (_operation || 'query') as ast.OperationTypeNode, 441 + name: _name, 442 + variableDefinitions: _variableDefinitions, 443 + directives: _directives, 444 + selectionSet: _selectionSet, 445 + }; 446 + } 447 + } 448 + 449 + function document(): ast.DocumentNode { 450 + let match: ast.DefinitionNode | void; 451 + ignored(); 452 + const definitions: ast.DefinitionNode[] = []; 453 + while (match = fragmentDefinition() || operationDefinition()) 454 + definitions.push(match); 455 + if (idx !== input.length) 456 + throw error(Kind.DOCUMENT); 457 + return { 458 + kind: Kind.DOCUMENT, 459 + definitions, 460 + }; 461 + } 462 + 463 + export function parse(string: string): ast.DocumentNode { 464 + input = string; 465 + idx = 0; 466 + return document(); 467 + } 468 + 469 + export function parseValue(string: string): ast.ValueNode | undefined { 470 + input = string; 471 + idx = 0; 472 + ignored(); 473 + return value(false); 474 + } 475 + 476 + export function parseType(string: string): ast.TypeNode | undefined { 477 + input = string; 478 + idx = 0; 479 + return type(); 480 + }
+132
src/printer.ts
··· 1 + import { Kind } from './kind'; 2 + import { ASTNode } from './ast'; 3 + 4 + export function printString(string: string) { 5 + return JSON.stringify(string); 6 + } 7 + 8 + export function printBlockString(string: string) { 9 + return '"""\n' + string.replace(/"""/g, '\\"""') + '\n"""'; 10 + } 11 + 12 + const hasItems = <T>( 13 + array: ReadonlyArray<T> | undefined | null 14 + ): array is ReadonlyArray<T> => !!(array && array.length); 15 + 16 + export function print(node: ASTNode): string { 17 + let out: string; 18 + switch (node.kind) { 19 + case Kind.OPERATION_DEFINITION: 20 + if (node.operation === 'query' && !node.name && !hasItems(node.variableDefinitions) && !hasItems(node.directives)) { 21 + return print(node.selectionSet); 22 + } 23 + out = node.operation; 24 + if (node.name) 25 + out += ' ' + node.name.value; 26 + if (hasItems(node.variableDefinitions)) { 27 + if (!node.name) out += ' '; 28 + out += '(' + node.variableDefinitions.map(print).join(', ') + ')'; 29 + } 30 + if (hasItems(node.directives)) 31 + out += ' ' + node.directives.map(print).join(' '); 32 + return out + ' ' + print(node.selectionSet); 33 + 34 + case Kind.VARIABLE_DEFINITION: 35 + out = print(node.variable) + 36 + ': ' + 37 + print(node.type); 38 + if (node.defaultValue) 39 + out += ' = ' + print(node.defaultValue); 40 + if (hasItems(node.directives)) 41 + out += ' ' + node.directives.map(print).join(' '); 42 + return out; 43 + 44 + case Kind.FIELD: 45 + out = (node.alias ? print(node.alias) + ': ' : '') + node.name.value 46 + if (hasItems(node.arguments)) 47 + out += '(' + node.arguments.map(print).join(', ') + ')'; 48 + if (hasItems(node.directives)) 49 + out += ' ' + node.directives.map(print).join(' '); 50 + return node.selectionSet 51 + ? out + ' ' + print(node.selectionSet) 52 + : out; 53 + 54 + case Kind.STRING: 55 + return node.block 56 + ? printBlockString(node.value) 57 + : printString(node.value); 58 + 59 + case Kind.BOOLEAN: 60 + return '' + node.value; 61 + 62 + case Kind.NULL: 63 + return 'null'; 64 + 65 + case Kind.INT: 66 + case Kind.FLOAT: 67 + case Kind.ENUM: 68 + case Kind.NAME: 69 + return node.value; 70 + 71 + case Kind.LIST: 72 + return '[' + node.values.map(print).join(', ') + ']'; 73 + 74 + case Kind.OBJECT: 75 + return '{' + node.fields.map(print).join(', ') + '}'; 76 + 77 + case Kind.OBJECT_FIELD: 78 + return node.name.value + ': ' + print(node.value); 79 + 80 + case Kind.VARIABLE: 81 + return '$' + node.name.value; 82 + 83 + case Kind.DOCUMENT: 84 + return hasItems(node.definitions) 85 + ? node.definitions.map(print).join('\n\n') 86 + : ''; 87 + 88 + case Kind.SELECTION_SET: 89 + return '{\n ' + 90 + node.selections.map(print).join('\n').replace(/\n/g, '\n ') + 91 + '\n}'; 92 + 93 + case Kind.ARGUMENT: 94 + return node.name.value + ': ' + print(node.value); 95 + 96 + case Kind.FRAGMENT_SPREAD: 97 + out = '...' + node.name.value; 98 + if (hasItems(node.directives)) 99 + out += ' ' + node.directives.map(print).join(' '); 100 + return out; 101 + 102 + case Kind.INLINE_FRAGMENT: 103 + out = '...'; 104 + if (node.typeCondition) 105 + out += ' on ' + node.typeCondition.name.value; 106 + if (hasItems(node.directives)) 107 + out += ' ' + node.directives.map(print).join(' '); 108 + return out + ' ' + print(node.selectionSet); 109 + 110 + case Kind.FRAGMENT_DEFINITION: 111 + out = 'fragment ' + node.name.value; 112 + out += ' on ' + node.typeCondition.name.value; 113 + if (hasItems(node.directives)) 114 + out += ' ' + node.directives.map(print).join(' '); 115 + return out + ' ' + print(node.selectionSet); 116 + 117 + case Kind.DIRECTIVE: 118 + out = '@' + node.name.value; 119 + if (hasItems(node.arguments)) 120 + out += '(' + node.arguments.map(print).join(', ') + ')'; 121 + return out; 122 + 123 + case Kind.NAMED_TYPE: 124 + return node.name.value; 125 + 126 + case Kind.LIST_TYPE: 127 + return '[' + print(node.type) + ']'; 128 + 129 + case Kind.NON_NULL_TYPE: 130 + return print(node.type) + '!'; 131 + } 132 + }
+5
src/types.ts
··· 1 + export type Maybe<T> = T | undefined | null; 2 + 3 + export interface Extensions { 4 + [extension: string]: unknown; 5 + }
+136
src/visitor.ts
··· 1 + import { ASTNode } from './ast'; 2 + 3 + export const BREAK = {}; 4 + 5 + export function visit<N extends ASTNode>(root: N, visitor: ASTVisitor): N; 6 + export function visit<R>(root: ASTNode, visitor: ASTReducer<R>): R; 7 + 8 + export function visit(node: ASTNode, visitor: ASTVisitor | ASTReducer<any>) { 9 + const ancestors: Array<ASTNode | ReadonlyArray<ASTNode>>= []; 10 + const path: Array<string | number> = []; 11 + 12 + function traverse( 13 + node: ASTNode, 14 + key?: string | number | undefined, 15 + parent?: ASTNode | ReadonlyArray<ASTNode> | undefined, 16 + ) { 17 + let hasEdited = false; 18 + 19 + const enter = visitor[node.kind] && visitor[node.kind].enter || visitor[node.kind]; 20 + const resultEnter = 21 + enter && enter.call(visitor, node, key, parent, path, ancestors); 22 + if (resultEnter === false) { 23 + return node; 24 + } else if (resultEnter === null) { 25 + return null; 26 + } else if (resultEnter === BREAK) { 27 + throw BREAK; 28 + } else if (resultEnter && typeof resultEnter.kind === 'string') { 29 + hasEdited = resultEnter !== node; 30 + node = resultEnter; 31 + } 32 + 33 + if (parent) ancestors.push(parent); 34 + 35 + let result: any; 36 + const copy = { ...node }; 37 + for (const nodeKey in node) { 38 + path.push(nodeKey); 39 + let value = node[nodeKey]; 40 + if (Array.isArray(value)) { 41 + const newValue: any[] = []; 42 + for (let index = 0; index < value.length; index++) { 43 + if (value[index] != null && typeof value[index].kind === 'string') { 44 + ancestors.push(node); 45 + path.push(index); 46 + result = traverse(value[index], index, value); 47 + path.pop(); 48 + ancestors.pop(); 49 + if (result === undefined) { 50 + newValue.push(value[index]); 51 + } else if (result === null) { 52 + hasEdited = true; 53 + } else { 54 + hasEdited = hasEdited || result !== value[index]; 55 + newValue.push(result); 56 + } 57 + } 58 + } 59 + value = newValue; 60 + } else if (value != null && typeof value.kind === 'string') { 61 + result = traverse(value, nodeKey, node); 62 + if (result !== undefined) { 63 + hasEdited = hasEdited || value !== result; 64 + value = result; 65 + } 66 + } 67 + 68 + path.pop(); 69 + if (hasEdited) copy[nodeKey] = value; 70 + } 71 + 72 + if (parent) ancestors.pop(); 73 + const leave = visitor[node.kind] && visitor[node.kind].leave; 74 + const resultLeave = 75 + leave && leave.call(visitor, node, key, parent, path, ancestors); 76 + if (resultLeave === BREAK) { 77 + throw BREAK; 78 + } else if (resultLeave !== undefined) { 79 + return resultLeave; 80 + } else if (resultEnter !== undefined) { 81 + return hasEdited ? copy : resultEnter; 82 + } else { 83 + return hasEdited ? copy : node; 84 + } 85 + } 86 + 87 + try { 88 + const result = traverse(node); 89 + return result !== undefined && result !== false ? result : node; 90 + } catch (error) { 91 + if (error !== BREAK) throw error; 92 + return node; 93 + } 94 + } 95 + 96 + export type ASTVisitor = EnterLeaveVisitor<ASTNode> | KindVisitor; 97 + 98 + type KindVisitor = { 99 + readonly [NodeT in ASTNode as NodeT['kind']]?: 100 + | ASTVisitFn<NodeT> 101 + | EnterLeaveVisitor<NodeT>; 102 + }; 103 + 104 + interface EnterLeaveVisitor<TVisitedNode extends ASTNode> { 105 + readonly enter?: ASTVisitFn<TVisitedNode> | undefined; 106 + readonly leave?: ASTVisitFn<TVisitedNode> | undefined; 107 + } 108 + 109 + export type ASTVisitFn<Node extends ASTNode> = ( 110 + node: Node, 111 + key: string | number | undefined, 112 + parent: ASTNode | ReadonlyArray<ASTNode> | undefined, 113 + path: ReadonlyArray<string | number>, 114 + ancestors: ReadonlyArray<ASTNode | ReadonlyArray<ASTNode>>, 115 + ) => any; 116 + 117 + export type ASTReducer<R> = { 118 + readonly [NodeT in ASTNode as NodeT['kind']]?: { 119 + readonly enter?: ASTVisitFn<NodeT>; 120 + readonly leave: ASTReducerFn<NodeT, R>; 121 + }; 122 + }; 123 + 124 + type ASTReducerFn<TReducedNode extends ASTNode, R> = ( 125 + node: { [K in keyof TReducedNode]: ReducedField<TReducedNode[K], R> }, 126 + key: string | number | undefined, 127 + parent: ASTNode | ReadonlyArray<ASTNode> | undefined, 128 + path: ReadonlyArray<string | number>, 129 + ancestors: ReadonlyArray<ASTNode | ReadonlyArray<ASTNode>>, 130 + ) => R; 131 + 132 + type ReducedField<T, R> = T extends null | undefined 133 + ? T 134 + : T extends ReadonlyArray<any> 135 + ? ReadonlyArray<R> 136 + : R;