├── .github ├── dependabot.yml └── workflows │ ├── main.yml │ ├── release.yml │ └── test.yml ├── .gitignore ├── CHANGELOG.md ├── README.md ├── ROADMAP.md ├── example ├── codegen.yml ├── package-lock.json ├── package.json ├── schema.graphql └── src │ ├── getComments.graphql │ ├── getUsers.graphql │ └── index.ts ├── jest.config.js ├── package-lock.json ├── package.json ├── renovate.json ├── src ├── cacheVisitor.ts ├── config.ts └── index.ts ├── test ├── index.spec.ts └── schema.json └── tsconfig.json /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # Basic dependabot.yml file with 2 | # minimum configuration for two package managers 3 | 4 | version: 2 5 | updates: 6 | # Enable version updates for npm 7 | - package-ecosystem: "npm" 8 | # Look for `package.json` and `lock` files in the `root` directory 9 | directory: "/" 10 | # Check the npm registry for updates every day (weekdays) 11 | schedule: 12 | interval: "monthly" 13 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | on: 3 | push: 4 | tags: 5 | - v*.*.* 6 | jobs: 7 | publish: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@master 11 | - uses: actions/setup-node@v2 12 | with: 13 | node-version: 12 14 | registry-url: https://registry.npmjs.org/ 15 | - run: npm install 16 | - run: npm publish 17 | env: 18 | NODE_AUTH_TOKEN: ${{ secrets.npm_token }} 19 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: release 2 | on: workflow_dispatch 3 | jobs: 4 | release: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: actions/setup-node@v2 8 | with: 9 | node-version: 12 10 | registry-url: https://registry.npmjs.org/ 11 | - name: checkout 12 | uses: actions/checkout@v2 13 | with: 14 | fetch-depth: 0 # gives standard-version access to all previous commits 15 | - name: generate tag and release body 16 | run: | 17 | git config user.name Fabio Benedetti 18 | git config user.email fabyo82@outlook.com 19 | npx standard-version 20 | - name: publish tag 21 | id: publish_tag 22 | run: | 23 | git push --follow-tags origin main && npm install && npm publish 24 | echo ::set-output name=tag_name::$(git describe HEAD --abbrev=0) 25 | env: 26 | NODE_AUTH_TOKEN: ${{ secrets.npm_token }} 27 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 28 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: push 3 | jobs: 4 | build: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: actions/checkout@v2 8 | - name: Install modules 9 | run: npm install 10 | - name: Run tests 11 | run: npm run test 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | .vscode 4 | example/src/generated 5 | .npmrc -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ### [0.1.10](https://github.com/correttojs/graphql-codegen-apollo-cache/compare/v0.1.9...v0.1.10) (2021-05-06) 6 | 7 | ### [0.1.9](https://github.com/correttojs/graphql-codegen-apollo-cache/compare/v0.1.8...v0.1.9) (2021-04-04) 8 | 9 | 10 | ### Features 11 | 12 | * renovate ([280d741](https://github.com/correttojs/graphql-codegen-apollo-cache/commit/280d7418472ae62c76de8371e43e769d6c28dc82)) 13 | 14 | ### [0.1.8](https://github.com/correttojs/graphql-codegen-apollo-cache/compare/v0.1.7...v0.1.8) (2021-02-02) 15 | 16 | 17 | ### Features 18 | 19 | * deprecate plugin ([8a09e9d](https://github.com/correttojs/graphql-codegen-apollo-cache/commit/8a09e9dbd901430c88e4f8f11706f5073579665e)) 20 | * review doc ([e2959f7](https://github.com/correttojs/graphql-codegen-apollo-cache/commit/e2959f75310e34a55aa09c71fa63d4849155cb19)) 21 | 22 | ### [0.1.7](https://github.com/correttojs/graphql-codegen-apollo-cache/compare/v0.1.6...v0.1.7) (2020-12-28) 23 | 24 | ### [0.1.6](https://github.com/correttojs/graphql-codegen-apollo-cache/compare/v0.1.5...v0.1.6) (2020-11-19) 25 | 26 | 27 | ### Features 28 | 29 | * add test job ([8424361](https://github.com/correttojs/graphql-codegen-apollo-cache/commit/842436176e3987cde93fd7150bddb46c329cf8eb)) 30 | * remove test ([759208d](https://github.com/correttojs/graphql-codegen-apollo-cache/commit/759208d0d765f7b097ae24dd99e5987ebeaf4b87)) 31 | 32 | ### [0.1.5](https://github.com/correttojs/graphql-codegen-apollo-cache/compare/v0.1.4...v0.1.5) (2020-07-18) 33 | 34 | 35 | ### Bug Fixes 36 | 37 | * example ([cc184d1](https://github.com/correttojs/graphql-codegen-apollo-cache/commit/cc184d1ae7ab9fe24f7e7fae9be1ceb1df3d4809)) 38 | 39 | ### [0.1.4](https://github.com/correttojs/graphql-codegen-apollo-cache/compare/v0.1.3...v0.1.4) (2020-07-17) 40 | 41 | 42 | ### Features 43 | 44 | * **apollo3:** bump dependencies, adapt for apollo ([031865d](https://github.com/correttojs/graphql-codegen-apollo-cache/commit/031865d13b445b67b099dc7a6ca2940fde79d0af)) 45 | 46 | ### [0.1.3](https://github.com/correttojs/graphql-codegen-apollo-cache/compare/v0.1.2...v0.1.3) (2020-07-17) 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NOTE: You can use [TypedDocumentNode](https://github.com/dotansimha/graphql-typed-document-node) instead 2 | 3 | see the [example](example/src/index.ts) 4 | 5 | # Graphql generator Apollo Cache Plugin 6 | 7 | GraphQL Code Generator plugin for generating a functions to read and write from the apollo cache 8 | 9 | 10 | 11 | ## Install 12 | `npm i graphql-codegen-apollo-cache` 13 | 14 | ## Configuration 15 | - `excludePatterns` (default: null): regexp to exclude operation names 16 | - `excludePatternsOptions` (default: ''): regexp flags to exclude operation names 17 | - `reactApolloVersion` (default: 2): apollo client version 18 | - `apolloCacheImportFrom` (default: apollo-cache-inmemory): apollo-cache-inmemory dependency 19 | - `apolloImportFrom` (default: apollo-client v2 or @apollo/client v3): apollo client dependency 20 | - `dataIdFromObjectImport` (default: apollo-cache-inmemory): custom dataIdFromObject dependency 21 | - `dataIdFromObjectName`: dataIdFromObject function name 22 | - `generateFragmentsRead`(default: true): generate fragments read functions 23 | - `generateFragmentsWrite`(default: true): generate fragments write functions 24 | - `generateQueriesWrite`(default: true): generate query read functions 25 | - `generateQueriesWrite`(default: true): generate query write functions 26 | - `customImports` (default: ''): full custom import declaration 27 | - `pre` (default: ''): custom code before each function 28 | - `post` (default: ''): custom code after each function 29 | 30 | ## Example config 31 | 32 | ``` 33 | overwrite: true 34 | schema: 35 | - 'https://myschema/graphql' 36 | documents: 37 | - 'src/**/*.graphql' 38 | generates: 39 | src/@types/codegen/graphql.tsx: 40 | plugins: 41 | - 'typescript' 42 | - 'typescript-operations' 43 | - 'typescript-react-apollo' 44 | src/@types/codegen/cache.tsx: 45 | config: 46 | documentMode: external 47 | importDocumentNodeExternallyFrom: ./graphql 48 | preset: import-types 49 | presetConfig: 50 | typesPath: ./graphql 51 | plugins: 52 | - ./build/src/index.js 53 | hooks: 54 | afterAllFileWrite: 55 | - prettier --write 56 | 57 | ``` -------------------------------------------------------------------------------- /ROADMAP.md: -------------------------------------------------------------------------------- 1 | # Version 1 2 | 3 | - ~~add different apollo configurations (path for v2, v3)~~ 4 | - ~~generate fragments read/write functions~~ 5 | - ~~add config to exclude operations~~ 6 | - ~~add example code~~ 7 | - generate hooks -------------------------------------------------------------------------------- /example/codegen.yml: -------------------------------------------------------------------------------- 1 | overwrite: true 2 | schema: "schema.graphql" 3 | documents: "src/**/*.graphql" 4 | generates: 5 | ./src/generated/graphql-operations.ts: 6 | plugins: 7 | - typescript 8 | - typescript-operations 9 | - typed-document-node 10 | src/generated/graphql.tsx: 11 | plugins: 12 | - "typescript" 13 | - "typescript-operations" 14 | - "typescript-react-apollo" 15 | config: 16 | reactApolloVersion: 3 17 | withHooks: false 18 | withHOC: false 19 | withComponent: false 20 | src/generated/cache.tsx: 21 | config: 22 | documentMode: external 23 | importDocumentNodeExternallyFrom: ./graphql 24 | reactApolloVersion: 3 25 | # excludePatterns: 'getComments' 26 | # excludePatternsOptions: 'i' 27 | # customDataIdFromObjectName: 'test' 28 | # customDataIdFromObjectImport: 'abc' 29 | generateQueriesWrite: false 30 | generateQueriesRead: true 31 | generateFragmentsRead: true 32 | generateFragmentsWrite: false 33 | pre: 'try{' 34 | post: '}catch(e){console.log(e); return null}' 35 | preset: import-types 36 | presetConfig: 37 | typesPath: ./graphql 38 | plugins: 39 | - "../build/src/index.js" 40 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "dependencies": {}, 7 | "devDependencies": { 8 | "@apollo/client": "3.4.7", 9 | "@graphql-codegen/cli": "1.21.8", 10 | "@graphql-codegen/import-types-preset": "1.18.6", 11 | "@graphql-codegen/typed-document-node": "1.18.10", 12 | "@graphql-codegen/typescript": "1.23.0", 13 | "@graphql-codegen/typescript-operations": "1.18.4", 14 | "@graphql-codegen/typescript-react-apollo": "2.3.1", 15 | "@graphql-typed-document-node/core": "3.1.0", 16 | "react": "17.0.2" 17 | }, 18 | "scripts": { 19 | "test": "echo \"Error: no test specified\" && exit 1", 20 | "codegen": "graphql-codegen --config codegen.yml" 21 | }, 22 | "author": "", 23 | "license": "ISC" 24 | } 25 | -------------------------------------------------------------------------------- /example/schema.graphql: -------------------------------------------------------------------------------- 1 | extend type Query { 2 | users: [User] 3 | comments: [Comment] 4 | } 5 | 6 | type User { 7 | name: String 8 | surname: String 9 | address: String 10 | age: Int 11 | } 12 | 13 | type Comment { 14 | user: User 15 | message: String 16 | } 17 | -------------------------------------------------------------------------------- /example/src/getComments.graphql: -------------------------------------------------------------------------------- 1 | query getComments { 2 | comments { 3 | message 4 | user { 5 | ...UserMessage 6 | } 7 | } 8 | } 9 | 10 | fragment UserMessage on User { 11 | name 12 | surname 13 | address 14 | } 15 | -------------------------------------------------------------------------------- /example/src/getUsers.graphql: -------------------------------------------------------------------------------- 1 | query getUser { 2 | users { 3 | name 4 | surname 5 | address 6 | age 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /example/src/index.ts: -------------------------------------------------------------------------------- 1 | import { InMemoryCache, ApolloClient } from "@apollo/client"; 2 | import { 3 | GetUserDocument, 4 | UserMessageFragmentDoc, 5 | } from "./generated/graphql-operations"; 6 | 7 | const cache = new InMemoryCache(); 8 | 9 | export const gqlClient = new ApolloClient({ 10 | cache, 11 | }); 12 | 13 | export const getAddress = () => { 14 | const users = gqlClient.readQuery({ query: GetUserDocument }); 15 | return users.users[0].address; 16 | }; 17 | 18 | export const getUserMessage = () => { 19 | const userMessage = gqlClient.readFragment({ 20 | fragment: UserMessageFragmentDoc, 21 | }); 22 | return userMessage.address; 23 | }; 24 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: "ts-jest", 3 | testEnvironment: "node", 4 | testPathIgnorePatterns: ["build", "/node_modules/"], 5 | }; 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "graphql-codegen-apollo-cache", 3 | "version": "0.1.10", 4 | "description": "GraphQL Code Generator plugin for generating a functions to read and write from the apollo cache", 5 | "license": "MIT", 6 | "scripts": { 7 | "test": "jest", 8 | "prepublish": "tsc", 9 | "codegen": "graphql-codegen --config codegen.yml", 10 | "release": "standard-version" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/correttojs/graphql-codegen-apollo-cache" 15 | }, 16 | "dependencies": { 17 | "@graphql-codegen/plugin-helpers": "^1.18.4", 18 | "@graphql-codegen/visitor-plugin-common": "^1.20.0", 19 | "auto-bind": "~4.0.0" 20 | }, 21 | "main": "build/src/index.js", 22 | "devDependencies": { 23 | "@graphql-codegen/cli": "1.21.8", 24 | "@graphql-codegen/fragment-matcher": "2.0.1", 25 | "@graphql-codegen/import-types-preset": "1.18.6", 26 | "@graphql-codegen/introspection": "1.18.2", 27 | "@graphql-codegen/testing": "1.17.7", 28 | "@graphql-codegen/typescript": "1.23.0", 29 | "@graphql-codegen/typescript-operations": "1.18.4", 30 | "@graphql-codegen/typescript-react-apollo": "2.3.1", 31 | "@types/jest": "26.0.24", 32 | "@types/node": "15.3.1", 33 | "apollo-cache-inmemory": "1.6.6", 34 | "apollo-client": "2.6.10", 35 | "graphql": "15.5.1", 36 | "graphql-codegen": "0.4.0", 37 | "jest": "26.6.3", 38 | "standard-version": "9.3.1", 39 | "ts-jest": "26.5.6", 40 | "typescript": "4.3.5" 41 | }, 42 | "author": "Fabio Benedetti" 43 | } 44 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["config:base"], 3 | "packageRules": [ 4 | { 5 | "matchUpdateTypes": ["minor", "patch", "pin", "digest"], 6 | "automerge": true 7 | } 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /src/cacheVisitor.ts: -------------------------------------------------------------------------------- 1 | import { Types } from "@graphql-codegen/plugin-helpers"; 2 | import { 3 | ClientSideBaseVisitor, 4 | ClientSideBasePluginConfig, 5 | getConfigValue, 6 | LoadedFragment, 7 | OMIT_TYPE, 8 | DocumentMode, 9 | } from "@graphql-codegen/visitor-plugin-common"; 10 | 11 | import autoBind from "auto-bind"; 12 | import { GraphQLSchema, OperationDefinitionNode } from "graphql"; 13 | import { ApolloCacheRawPluginConfig, Config } from "./config"; 14 | 15 | export type ApolloCachePluginConfig = ClientSideBasePluginConfig & Config; 16 | 17 | export class ApolloCacheVisitor extends ClientSideBaseVisitor< 18 | ApolloCacheRawPluginConfig, 19 | ApolloCachePluginConfig 20 | > { 21 | private _externalImportPrefix: string; 22 | private imports = new Set(); 23 | 24 | constructor( 25 | schema: GraphQLSchema, 26 | fragments: LoadedFragment[], 27 | rawConfig: ApolloCacheRawPluginConfig, 28 | documents: Types.DocumentFile[] 29 | ) { 30 | super(schema, fragments, rawConfig, { 31 | withHooks: getConfigValue(rawConfig.withHooks, false), 32 | apolloReactCommonImportFrom: getConfigValue( 33 | rawConfig.apolloReactCommonImportFrom, 34 | rawConfig.reactApolloVersion === 3 35 | ? "@apollo/client" 36 | : "@apollo/react-common" 37 | ), 38 | 39 | apolloReactHooksImportFrom: getConfigValue( 40 | rawConfig.apolloReactHooksImportFrom, 41 | rawConfig.reactApolloVersion === 3 42 | ? "@apollo/client" 43 | : "@apollo/react-hooks" 44 | ), 45 | apolloImportFrom: getConfigValue( 46 | rawConfig.apolloImportFrom, 47 | rawConfig.reactApolloVersion === 3 ? "@apollo/client" : "apollo-client" 48 | ), 49 | 50 | apolloCacheImportFrom: getConfigValue( 51 | rawConfig.apolloCacheImportFrom, 52 | rawConfig.reactApolloVersion === 3 53 | ? "@apollo/client" 54 | : "apollo-cache-inmemory" 55 | ), 56 | 57 | reactApolloVersion: getConfigValue(rawConfig.reactApolloVersion, 2), 58 | excludePatterns: getConfigValue(rawConfig.excludePatterns, null), 59 | excludePatternsOptions: getConfigValue( 60 | rawConfig.excludePatternsOptions, 61 | "" 62 | ), 63 | dataIdFromObjectImport: getConfigValue( 64 | rawConfig.dataIdFromObjectImport, 65 | null 66 | ), 67 | dataIdFromObjectName: getConfigValue( 68 | rawConfig.dataIdFromObjectName, 69 | "defaultDataIdFromObject" 70 | ), 71 | generateFragmentsRead: getConfigValue( 72 | rawConfig.generateFragmentsRead, 73 | true 74 | ), 75 | generateFragmentsWrite: getConfigValue( 76 | rawConfig.generateFragmentsWrite, 77 | true 78 | ), 79 | generateQueriesRead: getConfigValue(rawConfig.generateQueriesRead, true), 80 | generateQueriesWrite: getConfigValue( 81 | rawConfig.generateQueriesWrite, 82 | true 83 | ), 84 | pre: getConfigValue(rawConfig.pre, ""), 85 | post: getConfigValue(rawConfig.post, ""), 86 | customImports: getConfigValue(rawConfig.customImports, null), 87 | }); 88 | 89 | this._externalImportPrefix = this.config.importOperationTypesFrom 90 | ? `${this.config.importOperationTypesFrom}.` 91 | : ""; 92 | this._documents = documents; 93 | 94 | autoBind(this); 95 | } 96 | 97 | public getImports(): string[] { 98 | this.imports.add( 99 | `import { ApolloClient } from '${this.config.apolloImportFrom}';` 100 | ); 101 | this.imports.add( 102 | `import { defaultDataIdFromObject, NormalizedCacheObject } from '${this.config.apolloCacheImportFrom}';` 103 | ); 104 | if (this.config.dataIdFromObjectImport) { 105 | this.imports.add( 106 | `import { ${this.config.dataIdFromObjectName} } from '${this.config.dataIdFromObjectImport}';` 107 | ); 108 | } 109 | if (this.config.customImports) { 110 | this.imports.add(this.config.customImports); 111 | } 112 | 113 | const baseImports = super.getImports(); 114 | const hasOperations = this._collectedOperations.length > 0; 115 | 116 | if (!hasOperations) { 117 | return baseImports; 118 | } 119 | 120 | return [...baseImports, ...Array.from(this.imports)]; 121 | } 122 | 123 | private _buildOperationReadCache( 124 | node: OperationDefinitionNode, 125 | documentVariableName: string, 126 | operationResultType: string, 127 | operationVariablesTypes: string 128 | ): string { 129 | if (node.operation === "mutation") { 130 | return ""; 131 | } 132 | const operationName: string = this.convertName(node.name.value, { 133 | useTypesPrefix: false, 134 | }); 135 | 136 | if ( 137 | this.config.excludePatterns && 138 | new RegExp( 139 | this.config.excludePatterns, 140 | this.config.excludePatternsOptions 141 | ).test(operationName) 142 | ) { 143 | return ""; 144 | } 145 | 146 | const readString = this.config.generateQueriesRead 147 | ? `export function readQuery${operationName}(cache: ApolloClient, variables?: ${operationVariablesTypes}):${operationResultType} { 148 | ${this.config.pre} 149 | return cache.readQuery({ 150 | query: Operations.${documentVariableName}, 151 | variables, 152 | }); 153 | ${this.config.post} 154 | };` 155 | : ""; 156 | 157 | const writeString = this.config.generateQueriesWrite 158 | ? `export function writeQuery${operationName}(cache: ApolloClient, data: ${operationResultType}, variables?: ${operationVariablesTypes}) { 159 | ${this.config.pre} 160 | cache.writeQuery({ 161 | query: Operations.${documentVariableName}, 162 | variables, 163 | data, 164 | }); 165 | 166 | ${this.config.post} 167 | }` 168 | : ""; 169 | 170 | return [readString, writeString].filter((a) => a).join("\n"); 171 | } 172 | 173 | protected buildOperation( 174 | node: OperationDefinitionNode, 175 | documentVariableName: string, 176 | operationType: string, 177 | operationResultType: string, 178 | operationVariablesTypes: string 179 | ): string { 180 | operationResultType = this._externalImportPrefix + operationResultType; 181 | operationVariablesTypes = 182 | this._externalImportPrefix + operationVariablesTypes; 183 | 184 | const cache = this._buildOperationReadCache( 185 | node, 186 | documentVariableName, 187 | operationResultType, 188 | operationVariablesTypes 189 | ); 190 | return [cache].join("\n"); 191 | } 192 | 193 | public buildOperationReadFragmentCache(): string { 194 | const res = this._fragments.map((fragment) => { 195 | const read = this.config.generateFragmentsRead 196 | ? `export function readFragment${fragment.name}(cache: ApolloClient, fragmentIdProps?: Partial) { 197 | ${this.config.pre} 198 | const dataId = ${this.config.dataIdFromObjectName}({ 199 | __typename: '${fragment.onType}', 200 | ...(fragmentIdProps ? fragmentIdProps : {}) 201 | }) 202 | return cache.readFragment({ 203 | id: dataId, 204 | fragment: Operations.${fragment.name}FragmentDoc, 205 | fragmentName: '${fragment.name}', 206 | }); 207 | ${this.config.post} 208 | };` 209 | : ""; 210 | 211 | const write = this.config.generateFragmentsWrite 212 | ? `export function writeFragment${fragment.name}(cache: ApolloClient, fragmentIdProps?: Partial, data: Partial) { 213 | ${this.config.pre} 214 | const dataId = ${this.config.dataIdFromObjectName}({ 215 | __typename: '${fragment.onType}', 216 | ...(fragmentIdProps ? fragmentIdProps : {}) 217 | }) 218 | cache.writeFragment({ 219 | id: dataId, 220 | fragment: Operations.${fragment.name}FragmentDoc, 221 | data, 222 | }) 223 | ${this.config.post} 224 | }; 225 | ` 226 | : ""; 227 | return [read, write].filter((a) => a).join("\n"); 228 | }); 229 | return res.filter((a) => a).join("\n"); 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /src/config.ts: -------------------------------------------------------------------------------- 1 | import { RawClientSideBasePluginConfig } from "@graphql-codegen/visitor-plugin-common"; 2 | 3 | /** 4 | * @description This plugin generates React Apollo components and HOC with TypeScript typings. 5 | * 6 | * It extends the basic TypeScript plugins: `@graphql-codegen/typescript`, `@graphql-codegen/typescript-operations` - and thus shares a similar configuration. 7 | */ 8 | export type ApolloCacheRawPluginConfig = RawClientSideBasePluginConfig & Config; 9 | 10 | export type Config = { 11 | /** 12 | * @description Customized the output by enabling/disabling the generated React Hooks. 13 | * @default false 14 | * 15 | * @exampleMarkdown 16 | * ```yml 17 | * generates: 18 | * path/to/file.ts: 19 | * plugins: 20 | * - typescript 21 | * - typescript-operations 22 | * - typescript-react-apollo 23 | * config: 24 | * withHooks: false 25 | * ``` 26 | */ 27 | withHooks?: boolean; 28 | 29 | /** 30 | * @description Customize the package where apollo-react common lib is loaded from. 31 | * @default "@apollo/react-common" 32 | */ 33 | apolloReactCommonImportFrom?: string; 34 | 35 | /** 36 | * @description Customize the package where apollo-client lib is loaded from. 37 | * @default "apollo-client" 38 | */ 39 | apolloImportFrom?: string; 40 | 41 | /** 42 | * @description Customize the package where apollo-cache-inmemory lib is loaded from. 43 | * @default "apollo-cache-inmemory" 44 | */ 45 | apolloCacheImportFrom?: string; 46 | 47 | /** 48 | * @description Customize the package where apollo-react hooks lib is loaded from. 49 | * @default "@apollo/react-hooks" 50 | */ 51 | apolloReactHooksImportFrom?: string; 52 | 53 | /** 54 | * @description Sets the version of react-apollo. 55 | * @default 2 56 | * 57 | * @exampleMarkdown 58 | * ```yml 59 | * generates: 60 | * path/to/file.ts: 61 | * plugins: 62 | * - typescript 63 | * - typescript-operations 64 | * - typescript-react-apollo 65 | * config: 66 | * reactApolloVersion: 3 67 | * ``` 68 | */ 69 | reactApolloVersion?: 2 | 3; 70 | /** 71 | * @description Regexp to exclude a certain operation name 72 | */ 73 | excludePatterns?: string; 74 | /** 75 | * @description Regexp options to exclude a certain operation name 76 | */ 77 | excludePatternsOptions?: string; 78 | /** 79 | * @description Path to custom DataIdFromObject import 80 | */ 81 | dataIdFromObjectImport?: string; 82 | /** 83 | * @description Path to custom DataIdFromObject function 84 | */ 85 | dataIdFromObjectName?: string; 86 | generateFragmentsRead?: boolean; 87 | generateFragmentsWrite?: boolean; 88 | generateQueriesRead?: boolean; 89 | generateQueriesWrite?: boolean; 90 | pre?: string; 91 | post?: string; 92 | customImports?: string; 93 | }; 94 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { extname } from "path"; 2 | 3 | import { 4 | PluginFunction, 5 | PluginValidateFn, 6 | Types, 7 | } from "@graphql-codegen/plugin-helpers"; 8 | import { LoadedFragment } from "@graphql-codegen/visitor-plugin-common"; 9 | import { RawClientSideBasePluginConfig } from "@graphql-codegen/visitor-plugin-common"; 10 | import { 11 | FragmentDefinitionNode, 12 | GraphQLSchema, 13 | Kind, 14 | concatAST, 15 | visit, 16 | } from "graphql"; 17 | 18 | import { ApolloCacheVisitor } from "./cacheVisitor"; 19 | import { ApolloCacheRawPluginConfig } from "./config"; 20 | 21 | export const plugin: PluginFunction< 22 | ApolloCacheRawPluginConfig, 23 | Types.ComplexPluginOutput 24 | > = ( 25 | schema: GraphQLSchema, 26 | documents: Types.DocumentFile[], 27 | config: ApolloCacheRawPluginConfig 28 | ) => { 29 | const allAst = concatAST(documents.map((v) => v.document)); 30 | 31 | const allFragments: LoadedFragment[] = [ 32 | ...(allAst.definitions.filter( 33 | (d) => d.kind === Kind.FRAGMENT_DEFINITION 34 | ) as FragmentDefinitionNode[]).map((fragmentDef) => ({ 35 | node: fragmentDef, 36 | name: fragmentDef.name.value, 37 | onType: fragmentDef.typeCondition.name.value, 38 | isExternal: false, 39 | })), 40 | ...(config.externalFragments || []), 41 | ]; 42 | 43 | const visitor = new ApolloCacheVisitor( 44 | schema, 45 | allFragments, 46 | config, 47 | documents 48 | ); 49 | let visitorResult = visit(allAst, { leave: visitor }); 50 | 51 | const fragments = visitor.buildOperationReadFragmentCache(); 52 | return { 53 | prepend: visitor.getImports(), 54 | content: [ 55 | ...visitorResult.definitions.filter((t) => typeof t === "string"), 56 | fragments, 57 | ].join("\n"), 58 | }; 59 | }; 60 | 61 | export const validate: PluginValidateFn = async ( 62 | schema: GraphQLSchema, 63 | documents: Types.DocumentFile[], 64 | config: RawClientSideBasePluginConfig, 65 | outputFile: string 66 | ) => { 67 | if (extname(outputFile) !== ".tsx") { 68 | throw new Error(`Plugin "react-apollo" requires extension to be ".tsx"!`); 69 | } 70 | }; 71 | 72 | export { ApolloCacheVisitor }; 73 | -------------------------------------------------------------------------------- /test/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { validateTs } from "@graphql-codegen/testing"; 2 | import { plugin } from "../src/index"; 3 | import { parse, GraphQLSchema, buildClientSchema } from "graphql"; 4 | import { Types, mergeOutputs } from "@graphql-codegen/plugin-helpers"; 5 | import { plugin as tsPlugin } from "@graphql-codegen/typescript"; 6 | import { plugin as tsDocumentsPlugin } from "@graphql-codegen/typescript-operations"; 7 | 8 | describe("Apollo Cache", () => { 9 | let spyConsoleError: jest.SpyInstance; 10 | beforeEach(() => { 11 | spyConsoleError = jest.spyOn(console, "warn"); 12 | spyConsoleError.mockImplementation(); 13 | }); 14 | 15 | afterEach(() => { 16 | spyConsoleError.mockRestore(); 17 | }); 18 | 19 | const schema = buildClientSchema(require("./schema.json")); 20 | const basicDoc = parse(/* GraphQL */ ` 21 | query test { 22 | feed { 23 | id 24 | commentCount 25 | repository { 26 | full_name 27 | html_url 28 | owner { 29 | avatar_url 30 | } 31 | } 32 | } 33 | } 34 | `); 35 | 36 | const validateTypeScript = async ( 37 | output: Types.PluginOutput, 38 | testSchema: GraphQLSchema, 39 | documents: Types.DocumentFile[], 40 | config: any, 41 | playground = false 42 | ) => { 43 | const tsOutput = await tsPlugin(testSchema, documents, config, { 44 | outputFile: "", 45 | }); 46 | const tsDocumentsOutput = await tsDocumentsPlugin( 47 | testSchema, 48 | documents, 49 | config, 50 | { outputFile: "" } 51 | ); 52 | const merged = mergeOutputs([tsOutput, tsDocumentsOutput, output]); 53 | validateTs(merged, undefined, true, false, playground); 54 | 55 | return merged; 56 | }; 57 | 58 | describe("Imports", () => { 59 | it("should import apollo-cache-inmemory and apollo-client dependencies", async () => { 60 | const docs = [{ location: "", document: basicDoc }]; 61 | const content = (await plugin( 62 | schema, 63 | docs, 64 | {}, 65 | { 66 | outputFile: "graphql.tsx", 67 | } 68 | )) as Types.ComplexPluginOutput; 69 | 70 | expect(content.prepend).toContain("import gql from 'graphql-tag';"); 71 | expect(content.prepend).toContain( 72 | "import { defaultDataIdFromObject, NormalizedCacheObject } from 'apollo-cache-inmemory';" 73 | ); 74 | expect(content.prepend).toContain( 75 | "import { ApolloClient } from 'apollo-client';" 76 | ); 77 | await validateTypeScript(content, schema, docs, {}); 78 | }); 79 | 80 | it("should import custom apollo-cache-inmemory and apollo-client dependencies", async () => { 81 | const docs = [{ location: "", document: basicDoc }]; 82 | const content = (await plugin( 83 | schema, 84 | docs, 85 | { 86 | apolloCacheImportFrom: "cache", 87 | apolloImportFrom: "client", 88 | }, 89 | { 90 | outputFile: "graphql.tsx", 91 | } 92 | )) as Types.ComplexPluginOutput; 93 | 94 | expect(content.prepend).toContain("import gql from 'graphql-tag';"); 95 | expect(content.prepend).toContain( 96 | "import { defaultDataIdFromObject, NormalizedCacheObject } from 'cache';" 97 | ); 98 | expect(content.prepend).toContain( 99 | "import { ApolloClient } from 'client';" 100 | ); 101 | await validateTypeScript(content, schema, docs, {}); 102 | }); 103 | 104 | it("should import custom apollo-client v3 dependencies", async () => { 105 | const docs = [{ location: "", document: basicDoc }]; 106 | const content = (await plugin( 107 | schema, 108 | docs, 109 | { 110 | reactApolloVersion: 3, 111 | }, 112 | { 113 | outputFile: "graphql.tsx", 114 | } 115 | )) as Types.ComplexPluginOutput; 116 | 117 | expect(content.prepend).toContain( 118 | "import { ApolloClient } from '@apollo/client';" 119 | ); 120 | await validateTypeScript(content, schema, docs, {}); 121 | }); 122 | 123 | it("should import DocumentNode when using noGraphQLTag", async () => { 124 | const docs = [{ location: "", document: basicDoc }]; 125 | const content = (await plugin( 126 | schema, 127 | docs, 128 | { 129 | noGraphQLTag: true, 130 | }, 131 | { 132 | outputFile: "graphql.tsx", 133 | } 134 | )) as Types.ComplexPluginOutput; 135 | 136 | expect(content.prepend).toContain( 137 | `import { DocumentNode } from 'graphql';` 138 | ); 139 | expect(content.prepend).not.toContain(`import gql from 'graphql-tag';`); 140 | await validateTypeScript(content, schema, docs, {}); 141 | }); 142 | 143 | it(`should use gql import from gqlImport config option`, async () => { 144 | const docs = [{ location: "", document: basicDoc }]; 145 | const content = (await plugin( 146 | schema, 147 | docs, 148 | { gqlImport: "graphql.macro#gql" }, 149 | { 150 | outputFile: "graphql.tsx", 151 | } 152 | )) as Types.ComplexPluginOutput; 153 | 154 | expect(content.prepend).toContain(`import { gql } from 'graphql.macro';`); 155 | await validateTypeScript(content, schema, docs, {}); 156 | }); 157 | }); 158 | 159 | describe("ReadQuery", () => { 160 | it("Should generate ReadQuery and WriteQuery for query", async () => { 161 | const documents = parse(/* GraphQL */ ` 162 | query feed { 163 | feed { 164 | id 165 | commentCount 166 | repository { 167 | full_name 168 | html_url 169 | owner { 170 | avatar_url 171 | } 172 | } 173 | } 174 | } 175 | 176 | mutation submitRepository($name: String) { 177 | submitRepository(repoFullName: $name) { 178 | id 179 | } 180 | } 181 | `); 182 | const docs = [{ location: "", document: documents }]; 183 | 184 | const content = (await plugin( 185 | schema, 186 | docs, 187 | {}, 188 | { 189 | outputFile: "graphql.tsx", 190 | } 191 | )) as Types.ComplexPluginOutput; 192 | 193 | expect(content.content).toBeSimilarStringTo(` 194 | export function readQueryFeed(cache: ApolloClient, variables?: FeedQueryVariables):FeedQuery { 195 | return cache.readQuery({ 196 | query: Operations.FeedDocument, 197 | variables, 198 | }); 199 | };`); 200 | expect(content.content).toBeSimilarStringTo(` 201 | export function writeQueryFeed(cache: ApolloClient, data: FeedQuery, variables?: FeedQueryVariables) { 202 | cache.writeQuery({ 203 | query: Operations.FeedDocument, 204 | variables, 205 | data, 206 | }); 207 | }`); 208 | await validateTypeScript(content, schema, docs, {}); 209 | }); 210 | 211 | it("Should exclude query patterns", async () => { 212 | const documents = parse(/* GraphQL */ ` 213 | query feed { 214 | feed { 215 | id 216 | commentCount 217 | repository { 218 | full_name 219 | html_url 220 | owner { 221 | avatar_url 222 | } 223 | } 224 | } 225 | } 226 | 227 | mutation submitRepository($name: String) { 228 | submitRepository(repoFullName: $name) { 229 | id 230 | } 231 | } 232 | `); 233 | const docs = [{ location: "", document: documents }]; 234 | 235 | const content = (await plugin( 236 | schema, 237 | docs, 238 | { excludePatterns: "feed", excludePatternsOptions: "i" }, 239 | { 240 | outputFile: "graphql.tsx", 241 | } 242 | )) as Types.ComplexPluginOutput; 243 | 244 | expect(content.content).not.toBeSimilarStringTo(` 245 | export function readQueryFeed(cache: ApolloClient, variables?: FeedQueryVariables):FeedQuery { 246 | return cache.readQuery({ 247 | query: Operations.FeedDocument, 248 | variables, 249 | }); 250 | };`); 251 | expect(content.content).not.toBeSimilarStringTo(` 252 | export function writeQueryFeed(cache: ApolloClient, data: FeedQuery, variables?: FeedQueryVariables) { 253 | cache.writeQuery({ 254 | query: Operations.FeedDocument, 255 | variables, 256 | data, 257 | }); 258 | }`); 259 | await validateTypeScript(content, schema, docs, {}); 260 | }); 261 | 262 | it("Should not add typesPrefix to hooks", async () => { 263 | const docs = [{ location: "", document: basicDoc }]; 264 | const content = (await plugin( 265 | schema, 266 | docs, 267 | { typesPrefix: "I" }, 268 | { 269 | outputFile: "graphql.tsx", 270 | } 271 | )) as Types.ComplexPluginOutput; 272 | 273 | expect(content.content).toContain(`export function readQueryTest`); 274 | expect(content.content).toContain(`export function writeQueryTest`); 275 | }); 276 | }); 277 | }); 278 | -------------------------------------------------------------------------------- /test/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "__schema": { 3 | "queryType": { 4 | "name": "Query" 5 | }, 6 | "mutationType": { 7 | "name": "Mutation" 8 | }, 9 | "subscriptionType": { 10 | "name": "Subscription" 11 | }, 12 | "types": [ 13 | { 14 | "kind": "OBJECT", 15 | "name": "Query", 16 | "description": "", 17 | "fields": [ 18 | { 19 | "name": "feed", 20 | "description": "A feed of repository submissions", 21 | "args": [ 22 | { 23 | "name": "type", 24 | "description": "The sort order for the feed", 25 | "type": { 26 | "kind": "NON_NULL", 27 | "name": null, 28 | "ofType": { 29 | "kind": "ENUM", 30 | "name": "FeedType", 31 | "ofType": null 32 | } 33 | }, 34 | "defaultValue": null 35 | }, 36 | { 37 | "name": "offset", 38 | "description": "The number of items to skip, for pagination", 39 | "type": { 40 | "kind": "SCALAR", 41 | "name": "Int", 42 | "ofType": null 43 | }, 44 | "defaultValue": null 45 | }, 46 | { 47 | "name": "limit", 48 | "description": "The number of items to fetch starting from the offset, for pagination", 49 | "type": { 50 | "kind": "SCALAR", 51 | "name": "Int", 52 | "ofType": null 53 | }, 54 | "defaultValue": null 55 | } 56 | ], 57 | "type": { 58 | "kind": "LIST", 59 | "name": null, 60 | "ofType": { 61 | "kind": "OBJECT", 62 | "name": "Entry", 63 | "ofType": null 64 | } 65 | }, 66 | "isDeprecated": false, 67 | "deprecationReason": null 68 | }, 69 | { 70 | "name": "entry", 71 | "description": "A single entry", 72 | "args": [ 73 | { 74 | "name": "repoFullName", 75 | "description": "The full repository name from GitHub, e.g. \"apollostack/GitHunt-API\"", 76 | "type": { 77 | "kind": "NON_NULL", 78 | "name": null, 79 | "ofType": { 80 | "kind": "SCALAR", 81 | "name": "String", 82 | "ofType": null 83 | } 84 | }, 85 | "defaultValue": null 86 | } 87 | ], 88 | "type": { 89 | "kind": "OBJECT", 90 | "name": "Entry", 91 | "ofType": null 92 | }, 93 | "isDeprecated": false, 94 | "deprecationReason": null 95 | }, 96 | { 97 | "name": "currentUser", 98 | "description": "Return the currently logged in user, or null if nobody is logged in", 99 | "args": [], 100 | "type": { 101 | "kind": "OBJECT", 102 | "name": "User", 103 | "ofType": null 104 | }, 105 | "isDeprecated": false, 106 | "deprecationReason": null 107 | } 108 | ], 109 | "inputFields": null, 110 | "interfaces": [], 111 | "enumValues": null, 112 | "possibleTypes": null 113 | }, 114 | { 115 | "kind": "ENUM", 116 | "name": "FeedType", 117 | "description": "A list of options for the sort order of the feed", 118 | "fields": null, 119 | "inputFields": null, 120 | "interfaces": null, 121 | "enumValues": [ 122 | { 123 | "name": "HOT", 124 | "description": "Sort by a combination of freshness and score, using Reddit's algorithm", 125 | "isDeprecated": false, 126 | "deprecationReason": null 127 | }, 128 | { 129 | "name": "NEW", 130 | "description": "Newest entries first", 131 | "isDeprecated": false, 132 | "deprecationReason": null 133 | }, 134 | { 135 | "name": "TOP", 136 | "description": "Highest score entries first", 137 | "isDeprecated": false, 138 | "deprecationReason": null 139 | } 140 | ], 141 | "possibleTypes": null 142 | }, 143 | { 144 | "kind": "SCALAR", 145 | "name": "Int", 146 | "description": "The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. ", 147 | "fields": null, 148 | "inputFields": null, 149 | "interfaces": null, 150 | "enumValues": null, 151 | "possibleTypes": null 152 | }, 153 | { 154 | "kind": "OBJECT", 155 | "name": "Entry", 156 | "description": "Information about a GitHub repository submitted to GitHunt", 157 | "fields": [ 158 | { 159 | "name": "repository", 160 | "description": "Information about the repository from GitHub", 161 | "args": [], 162 | "type": { 163 | "kind": "NON_NULL", 164 | "name": null, 165 | "ofType": { 166 | "kind": "OBJECT", 167 | "name": "Repository", 168 | "ofType": null 169 | } 170 | }, 171 | "isDeprecated": false, 172 | "deprecationReason": null 173 | }, 174 | { 175 | "name": "postedBy", 176 | "description": "The GitHub user who submitted this entry", 177 | "args": [], 178 | "type": { 179 | "kind": "NON_NULL", 180 | "name": null, 181 | "ofType": { 182 | "kind": "OBJECT", 183 | "name": "User", 184 | "ofType": null 185 | } 186 | }, 187 | "isDeprecated": false, 188 | "deprecationReason": null 189 | }, 190 | { 191 | "name": "createdAt", 192 | "description": "A timestamp of when the entry was submitted", 193 | "args": [], 194 | "type": { 195 | "kind": "NON_NULL", 196 | "name": null, 197 | "ofType": { 198 | "kind": "SCALAR", 199 | "name": "Float", 200 | "ofType": null 201 | } 202 | }, 203 | "isDeprecated": false, 204 | "deprecationReason": null 205 | }, 206 | { 207 | "name": "score", 208 | "description": "The score of this repository, upvotes - downvotes", 209 | "args": [], 210 | "type": { 211 | "kind": "NON_NULL", 212 | "name": null, 213 | "ofType": { 214 | "kind": "SCALAR", 215 | "name": "Int", 216 | "ofType": null 217 | } 218 | }, 219 | "isDeprecated": false, 220 | "deprecationReason": null 221 | }, 222 | { 223 | "name": "hotScore", 224 | "description": "The hot score of this repository", 225 | "args": [], 226 | "type": { 227 | "kind": "NON_NULL", 228 | "name": null, 229 | "ofType": { 230 | "kind": "SCALAR", 231 | "name": "Float", 232 | "ofType": null 233 | } 234 | }, 235 | "isDeprecated": false, 236 | "deprecationReason": null 237 | }, 238 | { 239 | "name": "comments", 240 | "description": "Comments posted about this repository", 241 | "args": [ 242 | { 243 | "name": "limit", 244 | "description": "", 245 | "type": { 246 | "kind": "SCALAR", 247 | "name": "Int", 248 | "ofType": null 249 | }, 250 | "defaultValue": null 251 | }, 252 | { 253 | "name": "offset", 254 | "description": "", 255 | "type": { 256 | "kind": "SCALAR", 257 | "name": "Int", 258 | "ofType": null 259 | }, 260 | "defaultValue": null 261 | } 262 | ], 263 | "type": { 264 | "kind": "NON_NULL", 265 | "name": null, 266 | "ofType": { 267 | "kind": "LIST", 268 | "name": null, 269 | "ofType": { 270 | "kind": "OBJECT", 271 | "name": "Comment", 272 | "ofType": null 273 | } 274 | } 275 | }, 276 | "isDeprecated": false, 277 | "deprecationReason": null 278 | }, 279 | { 280 | "name": "commentCount", 281 | "description": "The number of comments posted about this repository", 282 | "args": [], 283 | "type": { 284 | "kind": "NON_NULL", 285 | "name": null, 286 | "ofType": { 287 | "kind": "SCALAR", 288 | "name": "Int", 289 | "ofType": null 290 | } 291 | }, 292 | "isDeprecated": false, 293 | "deprecationReason": null 294 | }, 295 | { 296 | "name": "id", 297 | "description": "The SQL ID of this entry", 298 | "args": [], 299 | "type": { 300 | "kind": "NON_NULL", 301 | "name": null, 302 | "ofType": { 303 | "kind": "SCALAR", 304 | "name": "Int", 305 | "ofType": null 306 | } 307 | }, 308 | "isDeprecated": false, 309 | "deprecationReason": null 310 | }, 311 | { 312 | "name": "vote", 313 | "description": "XXX to be changed", 314 | "args": [], 315 | "type": { 316 | "kind": "NON_NULL", 317 | "name": null, 318 | "ofType": { 319 | "kind": "OBJECT", 320 | "name": "Vote", 321 | "ofType": null 322 | } 323 | }, 324 | "isDeprecated": false, 325 | "deprecationReason": null 326 | } 327 | ], 328 | "inputFields": null, 329 | "interfaces": [], 330 | "enumValues": null, 331 | "possibleTypes": null 332 | }, 333 | { 334 | "kind": "OBJECT", 335 | "name": "Repository", 336 | "description": "A repository object from the GitHub API. This uses the exact field names returned by the\nGitHub API for simplicity, even though the convention for GraphQL is usually to camel case.", 337 | "fields": [ 338 | { 339 | "name": "name", 340 | "description": "Just the name of the repository, e.g. GitHunt-API", 341 | "args": [], 342 | "type": { 343 | "kind": "NON_NULL", 344 | "name": null, 345 | "ofType": { 346 | "kind": "SCALAR", 347 | "name": "String", 348 | "ofType": null 349 | } 350 | }, 351 | "isDeprecated": false, 352 | "deprecationReason": null 353 | }, 354 | { 355 | "name": "full_name", 356 | "description": "The full name of the repository with the username, e.g. apollostack/GitHunt-API", 357 | "args": [], 358 | "type": { 359 | "kind": "NON_NULL", 360 | "name": null, 361 | "ofType": { 362 | "kind": "SCALAR", 363 | "name": "String", 364 | "ofType": null 365 | } 366 | }, 367 | "isDeprecated": false, 368 | "deprecationReason": null 369 | }, 370 | { 371 | "name": "description", 372 | "description": "The description of the repository", 373 | "args": [], 374 | "type": { 375 | "kind": "SCALAR", 376 | "name": "String", 377 | "ofType": null 378 | }, 379 | "isDeprecated": false, 380 | "deprecationReason": null 381 | }, 382 | { 383 | "name": "html_url", 384 | "description": "The link to the repository on GitHub", 385 | "args": [], 386 | "type": { 387 | "kind": "NON_NULL", 388 | "name": null, 389 | "ofType": { 390 | "kind": "SCALAR", 391 | "name": "String", 392 | "ofType": null 393 | } 394 | }, 395 | "isDeprecated": false, 396 | "deprecationReason": null 397 | }, 398 | { 399 | "name": "stargazers_count", 400 | "description": "The number of people who have starred this repository on GitHub", 401 | "args": [], 402 | "type": { 403 | "kind": "NON_NULL", 404 | "name": null, 405 | "ofType": { 406 | "kind": "SCALAR", 407 | "name": "Int", 408 | "ofType": null 409 | } 410 | }, 411 | "isDeprecated": false, 412 | "deprecationReason": null 413 | }, 414 | { 415 | "name": "open_issues_count", 416 | "description": "The number of open issues on this repository on GitHub", 417 | "args": [], 418 | "type": { 419 | "kind": "SCALAR", 420 | "name": "Int", 421 | "ofType": null 422 | }, 423 | "isDeprecated": false, 424 | "deprecationReason": null 425 | }, 426 | { 427 | "name": "owner", 428 | "description": "The owner of this repository on GitHub, e.g. apollostack", 429 | "args": [], 430 | "type": { 431 | "kind": "OBJECT", 432 | "name": "User", 433 | "ofType": null 434 | }, 435 | "isDeprecated": false, 436 | "deprecationReason": null 437 | } 438 | ], 439 | "inputFields": null, 440 | "interfaces": [], 441 | "enumValues": null, 442 | "possibleTypes": null 443 | }, 444 | { 445 | "kind": "SCALAR", 446 | "name": "String", 447 | "description": "The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", 448 | "fields": null, 449 | "inputFields": null, 450 | "interfaces": null, 451 | "enumValues": null, 452 | "possibleTypes": null 453 | }, 454 | { 455 | "kind": "OBJECT", 456 | "name": "User", 457 | "description": "A user object from the GitHub API. This uses the exact field names returned from the GitHub API.", 458 | "fields": [ 459 | { 460 | "name": "login", 461 | "description": "The name of the user, e.g. apollostack", 462 | "args": [], 463 | "type": { 464 | "kind": "NON_NULL", 465 | "name": null, 466 | "ofType": { 467 | "kind": "SCALAR", 468 | "name": "String", 469 | "ofType": null 470 | } 471 | }, 472 | "isDeprecated": false, 473 | "deprecationReason": null 474 | }, 475 | { 476 | "name": "avatar_url", 477 | "description": "The URL to a directly embeddable image for this user's avatar", 478 | "args": [], 479 | "type": { 480 | "kind": "NON_NULL", 481 | "name": null, 482 | "ofType": { 483 | "kind": "SCALAR", 484 | "name": "String", 485 | "ofType": null 486 | } 487 | }, 488 | "isDeprecated": false, 489 | "deprecationReason": null 490 | }, 491 | { 492 | "name": "html_url", 493 | "description": "The URL of this user's GitHub page", 494 | "args": [], 495 | "type": { 496 | "kind": "NON_NULL", 497 | "name": null, 498 | "ofType": { 499 | "kind": "SCALAR", 500 | "name": "String", 501 | "ofType": null 502 | } 503 | }, 504 | "isDeprecated": false, 505 | "deprecationReason": null 506 | } 507 | ], 508 | "inputFields": null, 509 | "interfaces": [], 510 | "enumValues": null, 511 | "possibleTypes": null 512 | }, 513 | { 514 | "kind": "SCALAR", 515 | "name": "Float", 516 | "description": "The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point). ", 517 | "fields": null, 518 | "inputFields": null, 519 | "interfaces": null, 520 | "enumValues": null, 521 | "possibleTypes": null 522 | }, 523 | { 524 | "kind": "OBJECT", 525 | "name": "Comment", 526 | "description": "A comment about an entry, submitted by a user", 527 | "fields": [ 528 | { 529 | "name": "id", 530 | "description": "The SQL ID of this entry", 531 | "args": [], 532 | "type": { 533 | "kind": "NON_NULL", 534 | "name": null, 535 | "ofType": { 536 | "kind": "SCALAR", 537 | "name": "Int", 538 | "ofType": null 539 | } 540 | }, 541 | "isDeprecated": false, 542 | "deprecationReason": null 543 | }, 544 | { 545 | "name": "postedBy", 546 | "description": "The GitHub user who posted the comment", 547 | "args": [], 548 | "type": { 549 | "kind": "NON_NULL", 550 | "name": null, 551 | "ofType": { 552 | "kind": "OBJECT", 553 | "name": "User", 554 | "ofType": null 555 | } 556 | }, 557 | "isDeprecated": false, 558 | "deprecationReason": null 559 | }, 560 | { 561 | "name": "createdAt", 562 | "description": "A timestamp of when the comment was posted", 563 | "args": [], 564 | "type": { 565 | "kind": "NON_NULL", 566 | "name": null, 567 | "ofType": { 568 | "kind": "SCALAR", 569 | "name": "Float", 570 | "ofType": null 571 | } 572 | }, 573 | "isDeprecated": false, 574 | "deprecationReason": null 575 | }, 576 | { 577 | "name": "content", 578 | "description": "The text of the comment", 579 | "args": [], 580 | "type": { 581 | "kind": "NON_NULL", 582 | "name": null, 583 | "ofType": { 584 | "kind": "SCALAR", 585 | "name": "String", 586 | "ofType": null 587 | } 588 | }, 589 | "isDeprecated": false, 590 | "deprecationReason": null 591 | }, 592 | { 593 | "name": "repoName", 594 | "description": "The repository which this comment is about", 595 | "args": [], 596 | "type": { 597 | "kind": "NON_NULL", 598 | "name": null, 599 | "ofType": { 600 | "kind": "SCALAR", 601 | "name": "String", 602 | "ofType": null 603 | } 604 | }, 605 | "isDeprecated": false, 606 | "deprecationReason": null 607 | } 608 | ], 609 | "inputFields": null, 610 | "interfaces": [], 611 | "enumValues": null, 612 | "possibleTypes": null 613 | }, 614 | { 615 | "kind": "OBJECT", 616 | "name": "Vote", 617 | "description": "XXX to be removed", 618 | "fields": [ 619 | { 620 | "name": "vote_value", 621 | "description": "", 622 | "args": [], 623 | "type": { 624 | "kind": "NON_NULL", 625 | "name": null, 626 | "ofType": { 627 | "kind": "SCALAR", 628 | "name": "Int", 629 | "ofType": null 630 | } 631 | }, 632 | "isDeprecated": false, 633 | "deprecationReason": null 634 | } 635 | ], 636 | "inputFields": null, 637 | "interfaces": [], 638 | "enumValues": null, 639 | "possibleTypes": null 640 | }, 641 | { 642 | "kind": "OBJECT", 643 | "name": "Mutation", 644 | "description": "", 645 | "fields": [ 646 | { 647 | "name": "submitRepository", 648 | "description": "Submit a new repository, returns the new submission", 649 | "args": [ 650 | { 651 | "name": "repoFullName", 652 | "description": "The full repository name from GitHub, e.g. \"apollostack/GitHunt-API\"", 653 | "type": { 654 | "kind": "NON_NULL", 655 | "name": null, 656 | "ofType": { 657 | "kind": "SCALAR", 658 | "name": "String", 659 | "ofType": null 660 | } 661 | }, 662 | "defaultValue": null 663 | } 664 | ], 665 | "type": { 666 | "kind": "OBJECT", 667 | "name": "Entry", 668 | "ofType": null 669 | }, 670 | "isDeprecated": false, 671 | "deprecationReason": null 672 | }, 673 | { 674 | "name": "vote", 675 | "description": "Vote on a repository submission, returns the submission that was voted on", 676 | "args": [ 677 | { 678 | "name": "repoFullName", 679 | "description": "The full repository name from GitHub, e.g. \"apollostack/GitHunt-API\"", 680 | "type": { 681 | "kind": "NON_NULL", 682 | "name": null, 683 | "ofType": { 684 | "kind": "SCALAR", 685 | "name": "String", 686 | "ofType": null 687 | } 688 | }, 689 | "defaultValue": null 690 | }, 691 | { 692 | "name": "type", 693 | "description": "The type of vote - UP, DOWN, or CANCEL", 694 | "type": { 695 | "kind": "NON_NULL", 696 | "name": null, 697 | "ofType": { 698 | "kind": "ENUM", 699 | "name": "VoteType", 700 | "ofType": null 701 | } 702 | }, 703 | "defaultValue": null 704 | } 705 | ], 706 | "type": { 707 | "kind": "OBJECT", 708 | "name": "Entry", 709 | "ofType": null 710 | }, 711 | "isDeprecated": false, 712 | "deprecationReason": null 713 | }, 714 | { 715 | "name": "submitComment", 716 | "description": "Comment on a repository, returns the new comment", 717 | "args": [ 718 | { 719 | "name": "repoFullName", 720 | "description": "The full repository name from GitHub, e.g. \"apollostack/GitHunt-API\"", 721 | "type": { 722 | "kind": "NON_NULL", 723 | "name": null, 724 | "ofType": { 725 | "kind": "SCALAR", 726 | "name": "String", 727 | "ofType": null 728 | } 729 | }, 730 | "defaultValue": null 731 | }, 732 | { 733 | "name": "commentContent", 734 | "description": "The text content for the new comment", 735 | "type": { 736 | "kind": "NON_NULL", 737 | "name": null, 738 | "ofType": { 739 | "kind": "SCALAR", 740 | "name": "String", 741 | "ofType": null 742 | } 743 | }, 744 | "defaultValue": null 745 | } 746 | ], 747 | "type": { 748 | "kind": "OBJECT", 749 | "name": "Comment", 750 | "ofType": null 751 | }, 752 | "isDeprecated": false, 753 | "deprecationReason": null 754 | } 755 | ], 756 | "inputFields": null, 757 | "interfaces": [], 758 | "enumValues": null, 759 | "possibleTypes": null 760 | }, 761 | { 762 | "kind": "ENUM", 763 | "name": "VoteType", 764 | "description": "The type of vote to record, when submitting a vote", 765 | "fields": null, 766 | "inputFields": null, 767 | "interfaces": null, 768 | "enumValues": [ 769 | { 770 | "name": "UP", 771 | "description": "", 772 | "isDeprecated": false, 773 | "deprecationReason": null 774 | }, 775 | { 776 | "name": "DOWN", 777 | "description": "", 778 | "isDeprecated": false, 779 | "deprecationReason": null 780 | }, 781 | { 782 | "name": "CANCEL", 783 | "description": "", 784 | "isDeprecated": false, 785 | "deprecationReason": null 786 | } 787 | ], 788 | "possibleTypes": null 789 | }, 790 | { 791 | "kind": "OBJECT", 792 | "name": "Subscription", 793 | "description": "", 794 | "fields": [ 795 | { 796 | "name": "commentAdded", 797 | "description": "Subscription fires on every comment added", 798 | "args": [ 799 | { 800 | "name": "repoFullName", 801 | "description": "", 802 | "type": { 803 | "kind": "NON_NULL", 804 | "name": null, 805 | "ofType": { 806 | "kind": "SCALAR", 807 | "name": "String", 808 | "ofType": null 809 | } 810 | }, 811 | "defaultValue": null 812 | } 813 | ], 814 | "type": { 815 | "kind": "OBJECT", 816 | "name": "Comment", 817 | "ofType": null 818 | }, 819 | "isDeprecated": false, 820 | "deprecationReason": null 821 | } 822 | ], 823 | "inputFields": null, 824 | "interfaces": [], 825 | "enumValues": null, 826 | "possibleTypes": null 827 | }, 828 | { 829 | "kind": "OBJECT", 830 | "name": "__Schema", 831 | "description": "A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, as well as the entry points for query, mutation, and subscription operations.", 832 | "fields": [ 833 | { 834 | "name": "types", 835 | "description": "A list of all types supported by this server.", 836 | "args": [], 837 | "type": { 838 | "kind": "NON_NULL", 839 | "name": null, 840 | "ofType": { 841 | "kind": "LIST", 842 | "name": null, 843 | "ofType": { 844 | "kind": "NON_NULL", 845 | "name": null, 846 | "ofType": { 847 | "kind": "OBJECT", 848 | "name": "__Type", 849 | "ofType": null 850 | } 851 | } 852 | } 853 | }, 854 | "isDeprecated": false, 855 | "deprecationReason": null 856 | }, 857 | { 858 | "name": "queryType", 859 | "description": "The type that query operations will be rooted at.", 860 | "args": [], 861 | "type": { 862 | "kind": "NON_NULL", 863 | "name": null, 864 | "ofType": { 865 | "kind": "OBJECT", 866 | "name": "__Type", 867 | "ofType": null 868 | } 869 | }, 870 | "isDeprecated": false, 871 | "deprecationReason": null 872 | }, 873 | { 874 | "name": "mutationType", 875 | "description": "If this server supports mutation, the type that mutation operations will be rooted at.", 876 | "args": [], 877 | "type": { 878 | "kind": "OBJECT", 879 | "name": "__Type", 880 | "ofType": null 881 | }, 882 | "isDeprecated": false, 883 | "deprecationReason": null 884 | }, 885 | { 886 | "name": "subscriptionType", 887 | "description": "If this server support subscription, the type that subscription operations will be rooted at.", 888 | "args": [], 889 | "type": { 890 | "kind": "OBJECT", 891 | "name": "__Type", 892 | "ofType": null 893 | }, 894 | "isDeprecated": false, 895 | "deprecationReason": null 896 | }, 897 | { 898 | "name": "directives", 899 | "description": "A list of all directives supported by this server.", 900 | "args": [], 901 | "type": { 902 | "kind": "NON_NULL", 903 | "name": null, 904 | "ofType": { 905 | "kind": "LIST", 906 | "name": null, 907 | "ofType": { 908 | "kind": "NON_NULL", 909 | "name": null, 910 | "ofType": { 911 | "kind": "OBJECT", 912 | "name": "__Directive", 913 | "ofType": null 914 | } 915 | } 916 | } 917 | }, 918 | "isDeprecated": false, 919 | "deprecationReason": null 920 | } 921 | ], 922 | "inputFields": null, 923 | "interfaces": [], 924 | "enumValues": null, 925 | "possibleTypes": null 926 | }, 927 | { 928 | "kind": "OBJECT", 929 | "name": "__Type", 930 | "description": "The fundamental unit of any GraphQL Schema is the type. There are many kinds of types in GraphQL as represented by the `__TypeKind` enum.\n\nDepending on the kind of a type, certain fields describe information about that type. Scalar types provide no information beyond a name and description, while Enum types provide their values. Object and Interface types provide the fields they describe. Abstract types, Union and Interface, provide the Object types possible at runtime. List and NonNull types compose other types.", 931 | "fields": [ 932 | { 933 | "name": "kind", 934 | "description": null, 935 | "args": [], 936 | "type": { 937 | "kind": "NON_NULL", 938 | "name": null, 939 | "ofType": { 940 | "kind": "ENUM", 941 | "name": "__TypeKind", 942 | "ofType": null 943 | } 944 | }, 945 | "isDeprecated": false, 946 | "deprecationReason": null 947 | }, 948 | { 949 | "name": "name", 950 | "description": null, 951 | "args": [], 952 | "type": { 953 | "kind": "SCALAR", 954 | "name": "String", 955 | "ofType": null 956 | }, 957 | "isDeprecated": false, 958 | "deprecationReason": null 959 | }, 960 | { 961 | "name": "description", 962 | "description": null, 963 | "args": [], 964 | "type": { 965 | "kind": "SCALAR", 966 | "name": "String", 967 | "ofType": null 968 | }, 969 | "isDeprecated": false, 970 | "deprecationReason": null 971 | }, 972 | { 973 | "name": "fields", 974 | "description": null, 975 | "args": [ 976 | { 977 | "name": "includeDeprecated", 978 | "description": null, 979 | "type": { 980 | "kind": "SCALAR", 981 | "name": "Boolean", 982 | "ofType": null 983 | }, 984 | "defaultValue": "false" 985 | } 986 | ], 987 | "type": { 988 | "kind": "LIST", 989 | "name": null, 990 | "ofType": { 991 | "kind": "NON_NULL", 992 | "name": null, 993 | "ofType": { 994 | "kind": "OBJECT", 995 | "name": "__Field", 996 | "ofType": null 997 | } 998 | } 999 | }, 1000 | "isDeprecated": false, 1001 | "deprecationReason": null 1002 | }, 1003 | { 1004 | "name": "interfaces", 1005 | "description": null, 1006 | "args": [], 1007 | "type": { 1008 | "kind": "LIST", 1009 | "name": null, 1010 | "ofType": { 1011 | "kind": "NON_NULL", 1012 | "name": null, 1013 | "ofType": { 1014 | "kind": "OBJECT", 1015 | "name": "__Type", 1016 | "ofType": null 1017 | } 1018 | } 1019 | }, 1020 | "isDeprecated": false, 1021 | "deprecationReason": null 1022 | }, 1023 | { 1024 | "name": "possibleTypes", 1025 | "description": null, 1026 | "args": [], 1027 | "type": { 1028 | "kind": "LIST", 1029 | "name": null, 1030 | "ofType": { 1031 | "kind": "NON_NULL", 1032 | "name": null, 1033 | "ofType": { 1034 | "kind": "OBJECT", 1035 | "name": "__Type", 1036 | "ofType": null 1037 | } 1038 | } 1039 | }, 1040 | "isDeprecated": false, 1041 | "deprecationReason": null 1042 | }, 1043 | { 1044 | "name": "enumValues", 1045 | "description": null, 1046 | "args": [ 1047 | { 1048 | "name": "includeDeprecated", 1049 | "description": null, 1050 | "type": { 1051 | "kind": "SCALAR", 1052 | "name": "Boolean", 1053 | "ofType": null 1054 | }, 1055 | "defaultValue": "false" 1056 | } 1057 | ], 1058 | "type": { 1059 | "kind": "LIST", 1060 | "name": null, 1061 | "ofType": { 1062 | "kind": "NON_NULL", 1063 | "name": null, 1064 | "ofType": { 1065 | "kind": "OBJECT", 1066 | "name": "__EnumValue", 1067 | "ofType": null 1068 | } 1069 | } 1070 | }, 1071 | "isDeprecated": false, 1072 | "deprecationReason": null 1073 | }, 1074 | { 1075 | "name": "inputFields", 1076 | "description": null, 1077 | "args": [], 1078 | "type": { 1079 | "kind": "LIST", 1080 | "name": null, 1081 | "ofType": { 1082 | "kind": "NON_NULL", 1083 | "name": null, 1084 | "ofType": { 1085 | "kind": "OBJECT", 1086 | "name": "__InputValue", 1087 | "ofType": null 1088 | } 1089 | } 1090 | }, 1091 | "isDeprecated": false, 1092 | "deprecationReason": null 1093 | }, 1094 | { 1095 | "name": "ofType", 1096 | "description": null, 1097 | "args": [], 1098 | "type": { 1099 | "kind": "OBJECT", 1100 | "name": "__Type", 1101 | "ofType": null 1102 | }, 1103 | "isDeprecated": false, 1104 | "deprecationReason": null 1105 | } 1106 | ], 1107 | "inputFields": null, 1108 | "interfaces": [], 1109 | "enumValues": null, 1110 | "possibleTypes": null 1111 | }, 1112 | { 1113 | "kind": "ENUM", 1114 | "name": "__TypeKind", 1115 | "description": "An enum describing what kind of type a given `__Type` is.", 1116 | "fields": null, 1117 | "inputFields": null, 1118 | "interfaces": null, 1119 | "enumValues": [ 1120 | { 1121 | "name": "SCALAR", 1122 | "description": "Indicates this type is a scalar.", 1123 | "isDeprecated": false, 1124 | "deprecationReason": null 1125 | }, 1126 | { 1127 | "name": "OBJECT", 1128 | "description": "Indicates this type is an object. `fields` and `interfaces` are valid fields.", 1129 | "isDeprecated": false, 1130 | "deprecationReason": null 1131 | }, 1132 | { 1133 | "name": "INTERFACE", 1134 | "description": "Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.", 1135 | "isDeprecated": false, 1136 | "deprecationReason": null 1137 | }, 1138 | { 1139 | "name": "UNION", 1140 | "description": "Indicates this type is a union. `possibleTypes` is a valid field.", 1141 | "isDeprecated": false, 1142 | "deprecationReason": null 1143 | }, 1144 | { 1145 | "name": "ENUM", 1146 | "description": "Indicates this type is an enum. `enumValues` is a valid field.", 1147 | "isDeprecated": false, 1148 | "deprecationReason": null 1149 | }, 1150 | { 1151 | "name": "INPUT_OBJECT", 1152 | "description": "Indicates this type is an input object. `inputFields` is a valid field.", 1153 | "isDeprecated": false, 1154 | "deprecationReason": null 1155 | }, 1156 | { 1157 | "name": "LIST", 1158 | "description": "Indicates this type is a list. `ofType` is a valid field.", 1159 | "isDeprecated": false, 1160 | "deprecationReason": null 1161 | }, 1162 | { 1163 | "name": "NON_NULL", 1164 | "description": "Indicates this type is a non-null. `ofType` is a valid field.", 1165 | "isDeprecated": false, 1166 | "deprecationReason": null 1167 | } 1168 | ], 1169 | "possibleTypes": null 1170 | }, 1171 | { 1172 | "kind": "SCALAR", 1173 | "name": "Boolean", 1174 | "description": "The `Boolean` scalar type represents `true` or `false`.", 1175 | "fields": null, 1176 | "inputFields": null, 1177 | "interfaces": null, 1178 | "enumValues": null, 1179 | "possibleTypes": null 1180 | }, 1181 | { 1182 | "kind": "OBJECT", 1183 | "name": "__Field", 1184 | "description": "Object and Interface types are described by a list of Fields, each of which has a name, potentially a list of arguments, and a return type.", 1185 | "fields": [ 1186 | { 1187 | "name": "name", 1188 | "description": null, 1189 | "args": [], 1190 | "type": { 1191 | "kind": "NON_NULL", 1192 | "name": null, 1193 | "ofType": { 1194 | "kind": "SCALAR", 1195 | "name": "String", 1196 | "ofType": null 1197 | } 1198 | }, 1199 | "isDeprecated": false, 1200 | "deprecationReason": null 1201 | }, 1202 | { 1203 | "name": "description", 1204 | "description": null, 1205 | "args": [], 1206 | "type": { 1207 | "kind": "SCALAR", 1208 | "name": "String", 1209 | "ofType": null 1210 | }, 1211 | "isDeprecated": false, 1212 | "deprecationReason": null 1213 | }, 1214 | { 1215 | "name": "args", 1216 | "description": null, 1217 | "args": [], 1218 | "type": { 1219 | "kind": "NON_NULL", 1220 | "name": null, 1221 | "ofType": { 1222 | "kind": "LIST", 1223 | "name": null, 1224 | "ofType": { 1225 | "kind": "NON_NULL", 1226 | "name": null, 1227 | "ofType": { 1228 | "kind": "OBJECT", 1229 | "name": "__InputValue", 1230 | "ofType": null 1231 | } 1232 | } 1233 | } 1234 | }, 1235 | "isDeprecated": false, 1236 | "deprecationReason": null 1237 | }, 1238 | { 1239 | "name": "type", 1240 | "description": null, 1241 | "args": [], 1242 | "type": { 1243 | "kind": "NON_NULL", 1244 | "name": null, 1245 | "ofType": { 1246 | "kind": "OBJECT", 1247 | "name": "__Type", 1248 | "ofType": null 1249 | } 1250 | }, 1251 | "isDeprecated": false, 1252 | "deprecationReason": null 1253 | }, 1254 | { 1255 | "name": "isDeprecated", 1256 | "description": null, 1257 | "args": [], 1258 | "type": { 1259 | "kind": "NON_NULL", 1260 | "name": null, 1261 | "ofType": { 1262 | "kind": "SCALAR", 1263 | "name": "Boolean", 1264 | "ofType": null 1265 | } 1266 | }, 1267 | "isDeprecated": false, 1268 | "deprecationReason": null 1269 | }, 1270 | { 1271 | "name": "deprecationReason", 1272 | "description": null, 1273 | "args": [], 1274 | "type": { 1275 | "kind": "SCALAR", 1276 | "name": "String", 1277 | "ofType": null 1278 | }, 1279 | "isDeprecated": false, 1280 | "deprecationReason": null 1281 | } 1282 | ], 1283 | "inputFields": null, 1284 | "interfaces": [], 1285 | "enumValues": null, 1286 | "possibleTypes": null 1287 | }, 1288 | { 1289 | "kind": "OBJECT", 1290 | "name": "__InputValue", 1291 | "description": "Arguments provided to Fields or Directives and the input fields of an InputObject are represented as Input Values which describe their type and optionally a default value.", 1292 | "fields": [ 1293 | { 1294 | "name": "name", 1295 | "description": null, 1296 | "args": [], 1297 | "type": { 1298 | "kind": "NON_NULL", 1299 | "name": null, 1300 | "ofType": { 1301 | "kind": "SCALAR", 1302 | "name": "String", 1303 | "ofType": null 1304 | } 1305 | }, 1306 | "isDeprecated": false, 1307 | "deprecationReason": null 1308 | }, 1309 | { 1310 | "name": "description", 1311 | "description": null, 1312 | "args": [], 1313 | "type": { 1314 | "kind": "SCALAR", 1315 | "name": "String", 1316 | "ofType": null 1317 | }, 1318 | "isDeprecated": false, 1319 | "deprecationReason": null 1320 | }, 1321 | { 1322 | "name": "type", 1323 | "description": null, 1324 | "args": [], 1325 | "type": { 1326 | "kind": "NON_NULL", 1327 | "name": null, 1328 | "ofType": { 1329 | "kind": "OBJECT", 1330 | "name": "__Type", 1331 | "ofType": null 1332 | } 1333 | }, 1334 | "isDeprecated": false, 1335 | "deprecationReason": null 1336 | }, 1337 | { 1338 | "name": "defaultValue", 1339 | "description": "A GraphQL-formatted string representing the default value for this input value.", 1340 | "args": [], 1341 | "type": { 1342 | "kind": "SCALAR", 1343 | "name": "String", 1344 | "ofType": null 1345 | }, 1346 | "isDeprecated": false, 1347 | "deprecationReason": null 1348 | } 1349 | ], 1350 | "inputFields": null, 1351 | "interfaces": [], 1352 | "enumValues": null, 1353 | "possibleTypes": null 1354 | }, 1355 | { 1356 | "kind": "OBJECT", 1357 | "name": "__EnumValue", 1358 | "description": "One possible value for a given Enum. Enum values are unique values, not a placeholder for a string or numeric value. However an Enum value is returned in a JSON response as a string.", 1359 | "fields": [ 1360 | { 1361 | "name": "name", 1362 | "description": null, 1363 | "args": [], 1364 | "type": { 1365 | "kind": "NON_NULL", 1366 | "name": null, 1367 | "ofType": { 1368 | "kind": "SCALAR", 1369 | "name": "String", 1370 | "ofType": null 1371 | } 1372 | }, 1373 | "isDeprecated": false, 1374 | "deprecationReason": null 1375 | }, 1376 | { 1377 | "name": "description", 1378 | "description": null, 1379 | "args": [], 1380 | "type": { 1381 | "kind": "SCALAR", 1382 | "name": "String", 1383 | "ofType": null 1384 | }, 1385 | "isDeprecated": false, 1386 | "deprecationReason": null 1387 | }, 1388 | { 1389 | "name": "isDeprecated", 1390 | "description": null, 1391 | "args": [], 1392 | "type": { 1393 | "kind": "NON_NULL", 1394 | "name": null, 1395 | "ofType": { 1396 | "kind": "SCALAR", 1397 | "name": "Boolean", 1398 | "ofType": null 1399 | } 1400 | }, 1401 | "isDeprecated": false, 1402 | "deprecationReason": null 1403 | }, 1404 | { 1405 | "name": "deprecationReason", 1406 | "description": null, 1407 | "args": [], 1408 | "type": { 1409 | "kind": "SCALAR", 1410 | "name": "String", 1411 | "ofType": null 1412 | }, 1413 | "isDeprecated": false, 1414 | "deprecationReason": null 1415 | } 1416 | ], 1417 | "inputFields": null, 1418 | "interfaces": [], 1419 | "enumValues": null, 1420 | "possibleTypes": null 1421 | }, 1422 | { 1423 | "kind": "OBJECT", 1424 | "name": "__Directive", 1425 | "description": "A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.\n\nIn some cases, you need to provide options to alter GraphQL's execution behavior in ways field arguments will not suffice, such as conditionally including or skipping a field. Directives provide this by describing additional information to the executor.", 1426 | "fields": [ 1427 | { 1428 | "name": "name", 1429 | "description": null, 1430 | "args": [], 1431 | "type": { 1432 | "kind": "NON_NULL", 1433 | "name": null, 1434 | "ofType": { 1435 | "kind": "SCALAR", 1436 | "name": "String", 1437 | "ofType": null 1438 | } 1439 | }, 1440 | "isDeprecated": false, 1441 | "deprecationReason": null 1442 | }, 1443 | { 1444 | "name": "description", 1445 | "description": null, 1446 | "args": [], 1447 | "type": { 1448 | "kind": "SCALAR", 1449 | "name": "String", 1450 | "ofType": null 1451 | }, 1452 | "isDeprecated": false, 1453 | "deprecationReason": null 1454 | }, 1455 | { 1456 | "name": "locations", 1457 | "description": null, 1458 | "args": [], 1459 | "type": { 1460 | "kind": "NON_NULL", 1461 | "name": null, 1462 | "ofType": { 1463 | "kind": "LIST", 1464 | "name": null, 1465 | "ofType": { 1466 | "kind": "NON_NULL", 1467 | "name": null, 1468 | "ofType": { 1469 | "kind": "ENUM", 1470 | "name": "__DirectiveLocation", 1471 | "ofType": null 1472 | } 1473 | } 1474 | } 1475 | }, 1476 | "isDeprecated": false, 1477 | "deprecationReason": null 1478 | }, 1479 | { 1480 | "name": "args", 1481 | "description": null, 1482 | "args": [], 1483 | "type": { 1484 | "kind": "NON_NULL", 1485 | "name": null, 1486 | "ofType": { 1487 | "kind": "LIST", 1488 | "name": null, 1489 | "ofType": { 1490 | "kind": "NON_NULL", 1491 | "name": null, 1492 | "ofType": { 1493 | "kind": "OBJECT", 1494 | "name": "__InputValue", 1495 | "ofType": null 1496 | } 1497 | } 1498 | } 1499 | }, 1500 | "isDeprecated": false, 1501 | "deprecationReason": null 1502 | }, 1503 | { 1504 | "name": "onOperation", 1505 | "description": null, 1506 | "args": [], 1507 | "type": { 1508 | "kind": "NON_NULL", 1509 | "name": null, 1510 | "ofType": { 1511 | "kind": "SCALAR", 1512 | "name": "Boolean", 1513 | "ofType": null 1514 | } 1515 | }, 1516 | "isDeprecated": true, 1517 | "deprecationReason": "Use `locations`." 1518 | }, 1519 | { 1520 | "name": "onFragment", 1521 | "description": null, 1522 | "args": [], 1523 | "type": { 1524 | "kind": "NON_NULL", 1525 | "name": null, 1526 | "ofType": { 1527 | "kind": "SCALAR", 1528 | "name": "Boolean", 1529 | "ofType": null 1530 | } 1531 | }, 1532 | "isDeprecated": true, 1533 | "deprecationReason": "Use `locations`." 1534 | }, 1535 | { 1536 | "name": "onField", 1537 | "description": null, 1538 | "args": [], 1539 | "type": { 1540 | "kind": "NON_NULL", 1541 | "name": null, 1542 | "ofType": { 1543 | "kind": "SCALAR", 1544 | "name": "Boolean", 1545 | "ofType": null 1546 | } 1547 | }, 1548 | "isDeprecated": true, 1549 | "deprecationReason": "Use `locations`." 1550 | } 1551 | ], 1552 | "inputFields": null, 1553 | "interfaces": [], 1554 | "enumValues": null, 1555 | "possibleTypes": null 1556 | }, 1557 | { 1558 | "kind": "ENUM", 1559 | "name": "__DirectiveLocation", 1560 | "description": "A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies.", 1561 | "fields": null, 1562 | "inputFields": null, 1563 | "interfaces": null, 1564 | "enumValues": [ 1565 | { 1566 | "name": "QUERY", 1567 | "description": "Location adjacent to a query operation.", 1568 | "isDeprecated": false, 1569 | "deprecationReason": null 1570 | }, 1571 | { 1572 | "name": "MUTATION", 1573 | "description": "Location adjacent to a mutation operation.", 1574 | "isDeprecated": false, 1575 | "deprecationReason": null 1576 | }, 1577 | { 1578 | "name": "SUBSCRIPTION", 1579 | "description": "Location adjacent to a subscription operation.", 1580 | "isDeprecated": false, 1581 | "deprecationReason": null 1582 | }, 1583 | { 1584 | "name": "FIELD", 1585 | "description": "Location adjacent to a field.", 1586 | "isDeprecated": false, 1587 | "deprecationReason": null 1588 | }, 1589 | { 1590 | "name": "FRAGMENT_DEFINITION", 1591 | "description": "Location adjacent to a fragment definition.", 1592 | "isDeprecated": false, 1593 | "deprecationReason": null 1594 | }, 1595 | { 1596 | "name": "FRAGMENT_SPREAD", 1597 | "description": "Location adjacent to a fragment spread.", 1598 | "isDeprecated": false, 1599 | "deprecationReason": null 1600 | }, 1601 | { 1602 | "name": "INLINE_FRAGMENT", 1603 | "description": "Location adjacent to an inline fragment.", 1604 | "isDeprecated": false, 1605 | "deprecationReason": null 1606 | }, 1607 | { 1608 | "name": "SCHEMA", 1609 | "description": "Location adjacent to a schema definition.", 1610 | "isDeprecated": false, 1611 | "deprecationReason": null 1612 | }, 1613 | { 1614 | "name": "SCALAR", 1615 | "description": "Location adjacent to a scalar definition.", 1616 | "isDeprecated": false, 1617 | "deprecationReason": null 1618 | }, 1619 | { 1620 | "name": "OBJECT", 1621 | "description": "Location adjacent to an object type definition.", 1622 | "isDeprecated": false, 1623 | "deprecationReason": null 1624 | }, 1625 | { 1626 | "name": "FIELD_DEFINITION", 1627 | "description": "Location adjacent to a field definition.", 1628 | "isDeprecated": false, 1629 | "deprecationReason": null 1630 | }, 1631 | { 1632 | "name": "ARGUMENT_DEFINITION", 1633 | "description": "Location adjacent to an argument definition.", 1634 | "isDeprecated": false, 1635 | "deprecationReason": null 1636 | }, 1637 | { 1638 | "name": "INTERFACE", 1639 | "description": "Location adjacent to an interface definition.", 1640 | "isDeprecated": false, 1641 | "deprecationReason": null 1642 | }, 1643 | { 1644 | "name": "UNION", 1645 | "description": "Location adjacent to a union definition.", 1646 | "isDeprecated": false, 1647 | "deprecationReason": null 1648 | }, 1649 | { 1650 | "name": "ENUM", 1651 | "description": "Location adjacent to an enum definition.", 1652 | "isDeprecated": false, 1653 | "deprecationReason": null 1654 | }, 1655 | { 1656 | "name": "ENUM_VALUE", 1657 | "description": "Location adjacent to an enum value definition.", 1658 | "isDeprecated": false, 1659 | "deprecationReason": null 1660 | }, 1661 | { 1662 | "name": "INPUT_OBJECT", 1663 | "description": "Location adjacent to an input object type definition.", 1664 | "isDeprecated": false, 1665 | "deprecationReason": null 1666 | }, 1667 | { 1668 | "name": "INPUT_FIELD_DEFINITION", 1669 | "description": "Location adjacent to an input object field definition.", 1670 | "isDeprecated": false, 1671 | "deprecationReason": null 1672 | } 1673 | ], 1674 | "possibleTypes": null 1675 | } 1676 | ], 1677 | "directives": [ 1678 | { 1679 | "name": "skip", 1680 | "description": "Directs the executor to skip this field or fragment when the `if` argument is true.", 1681 | "locations": [ 1682 | "FIELD", 1683 | "FRAGMENT_SPREAD", 1684 | "INLINE_FRAGMENT" 1685 | ], 1686 | "args": [ 1687 | { 1688 | "name": "if", 1689 | "description": "Skipped when true.", 1690 | "type": { 1691 | "kind": "NON_NULL", 1692 | "name": null, 1693 | "ofType": { 1694 | "kind": "SCALAR", 1695 | "name": "Boolean", 1696 | "ofType": null 1697 | } 1698 | }, 1699 | "defaultValue": null 1700 | } 1701 | ] 1702 | }, 1703 | { 1704 | "name": "include", 1705 | "description": "Directs the executor to include this field or fragment only when the `if` argument is true.", 1706 | "locations": [ 1707 | "FIELD", 1708 | "FRAGMENT_SPREAD", 1709 | "INLINE_FRAGMENT" 1710 | ], 1711 | "args": [ 1712 | { 1713 | "name": "if", 1714 | "description": "Included when true.", 1715 | "type": { 1716 | "kind": "NON_NULL", 1717 | "name": null, 1718 | "ofType": { 1719 | "kind": "SCALAR", 1720 | "name": "Boolean", 1721 | "ofType": null 1722 | } 1723 | }, 1724 | "defaultValue": null 1725 | } 1726 | ] 1727 | }, 1728 | { 1729 | "name": "deprecated", 1730 | "description": "Marks an element of a GraphQL schema as no longer supported.", 1731 | "locations": [ 1732 | "FIELD_DEFINITION", 1733 | "ENUM_VALUE" 1734 | ], 1735 | "args": [ 1736 | { 1737 | "name": "reason", 1738 | "description": "Explains why this element was deprecated, usually also including a suggestion for how to access supported similar data. Formatted in [Markdown](https://daringfireball.net/projects/markdown/).", 1739 | "type": { 1740 | "kind": "SCALAR", 1741 | "name": "String", 1742 | "ofType": null 1743 | }, 1744 | "defaultValue": "\"No longer supported\"" 1745 | } 1746 | ] 1747 | } 1748 | ] 1749 | } 1750 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "lib": [ 5 | "es2015" 6 | ], 7 | "module": "commonjs", 8 | "moduleResolution": "node", 9 | "jsx": "preserve", 10 | "outDir": "build", 11 | "esModuleInterop": true 12 | }, 13 | "exclude": ["node_modules", "example"] 14 | } 15 | --------------------------------------------------------------------------------