├── renovate.json ├── .eslintignore ├── .eslintrc.js ├── .travis.yml ├── types ├── tsconfig.json └── index.d.ts ├── .babelrc.js ├── LICENSE ├── .gitignore ├── README.md ├── package.json ├── src └── index.js └── test └── index.test.js /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["github>4Catalyzer/renovate-config:library", ":automergeMinor"] 3 | } 4 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | !.babelrc.js 2 | !.eslintrc.js 3 | 4 | **/coverage/ 5 | **/lib/ 6 | **/es/ 7 | **/node_modules/ 8 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['4catalyzer', '4catalyzer-jest', 'prettier'], 3 | plugins: ['prettier'], 4 | rules: { 5 | 'prettier/prettier': 'error', 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - node 4 | - lts/* 5 | 6 | cache: 7 | yarn: true 8 | npm: true 9 | 10 | after_script: 11 | - node_modules/.bin/codecov 12 | 13 | branches: 14 | only: 15 | - master 16 | -------------------------------------------------------------------------------- /types/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "forceConsistentCasingInFileNames": true, 4 | "lib": ["es2015", "esnext.asynciterable"], 5 | "strict": true, 6 | "types": [], 7 | "noEmit": true, 8 | "baseUrl": "." 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.babelrc.js: -------------------------------------------------------------------------------- 1 | module.exports = (api) => ({ 2 | presets: [ 3 | [ 4 | '@babel/env', 5 | { 6 | bugfixes: true, 7 | loose: true, 8 | modules: api.env() === 'esm' ? false : 'commonjs', 9 | }, 10 | ], 11 | ], 12 | }); 13 | -------------------------------------------------------------------------------- /types/index.d.ts: -------------------------------------------------------------------------------- 1 | // TypeScript Version: 3.0 2 | 3 | import { GraphQLScalarType } from 'graphql'; 4 | 5 | // This named export is intended for users of CommonJS. Users of ES modules 6 | // should instead use the default export. 7 | export const GraphQLJSON: GraphQLScalarType; 8 | 9 | export default GraphQLJSON; 10 | 11 | export const GraphQLJSONObject: GraphQLScalarType; 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Jimmy Jia 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # Snowpack dependency directory (https://snowpack.dev/) 45 | web_modules/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | .parcel-cache 78 | 79 | # Next.js build output 80 | .next 81 | 82 | # Nuxt.js build / generate output 83 | .nuxt 84 | dist 85 | 86 | # Gatsby files 87 | .cache/ 88 | # Comment in the public line in if your project uses Gatsby and not Next.js 89 | # https://nextjs.org/blog/next-9-1#public-directory-support 90 | # public 91 | 92 | # vuepress build output 93 | .vuepress/dist 94 | 95 | # Serverless directories 96 | .serverless/ 97 | 98 | # FuseBox cache 99 | .fusebox/ 100 | 101 | # DynamoDB Local files 102 | .dynamodb/ 103 | 104 | # TernJS port file 105 | .tern-port 106 | 107 | # Stores VSCode versions used for testing VSCode extensions 108 | .vscode-test 109 | 110 | # yarn v2 111 | 112 | .yarn/cache 113 | .yarn/unplugged 114 | .yarn/build-state.yml 115 | .pnp.* 116 | 117 | # Transpiled code. 118 | /lib 119 | /es 120 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # graphql-type-json [![Travis][build-badge]][build] [![npm][npm-badge]][npm] 2 | 3 | JSON scalar types for [GraphQL.js](https://github.com/graphql/graphql-js). 4 | 5 | [![Codecov][codecov-badge]][codecov] 6 | 7 | ## Usage 8 | 9 | This package exports a JSON value scalar GraphQL.js type: 10 | 11 | ```js 12 | import GraphQLJSON from 'graphql-type-json'; 13 | ``` 14 | 15 | It also exports a JSON object scalar type: 16 | 17 | ```js 18 | import { GraphQLJSONObject } from 'graphql-type-json'; 19 | ``` 20 | 21 | These types can also be imported as follows using CommonJS: 22 | 23 | ```js 24 | const { GraphQLJSON, GraphQLJSONObject } = require('graphql-type-json'); 25 | ``` 26 | 27 | `GraphQLJSON` can represent any JSON-serializable value, including scalars, arrays, and objects. `GraphQLJSONObject` represents specifically JSON objects, which covers many practical use cases for JSON scalars. 28 | 29 | ### Programmatically-constructed schemas 30 | 31 | You can use this in a programmatically-constructed schema as with any other scalar type: 32 | 33 | ```js 34 | import GraphQLJSON, { GraphQLJSONObject } from 'graphql-type-json'; 35 | 36 | export default new GraphQLObjectType({ 37 | name: 'MyType', 38 | 39 | fields: { 40 | myValue: { type: GraphQLJSON }, 41 | myObject: { type: GraphQLJSONObject }, 42 | }, 43 | }); 44 | ``` 45 | 46 | ### SDL with [GraphQL-tools](https://github.com/apollographql/graphql-tools) 47 | 48 | When using the SDL with GraphQL-tools, define `GraphQLJSON` as the resolver for the appropriate scalar type in your schema: 49 | 50 | ```js 51 | import { makeExecutableSchema } from 'graphql-tools'; 52 | import GraphQLJSON, { GraphQLJSONObject } from 'graphql-type-json'; 53 | 54 | const typeDefs = ` 55 | scalar JSON 56 | scalar JSONObject 57 | 58 | type MyType { 59 | myValue: JSON 60 | myObject: JSONObject 61 | } 62 | 63 | # ... 64 | `; 65 | 66 | const resolvers = { 67 | JSON: GraphQLJSON, 68 | JSONObject: GraphQLJSONObject, 69 | }; 70 | 71 | export default makeExecutableSchema({ typeDefs, resolvers }); 72 | ``` 73 | 74 | [build-badge]: https://img.shields.io/travis/taion/graphql-type-json/master.svg 75 | [build]: https://travis-ci.org/taion/graphql-type-json 76 | [npm-badge]: https://img.shields.io/npm/v/graphql-type-json.svg 77 | [npm]: https://www.npmjs.com/package/graphql-type-json 78 | [codecov-badge]: https://img.shields.io/codecov/c/github/taion/graphql-type-json/master.svg 79 | [codecov]: https://codecov.io/gh/taion/graphql-type-json 80 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "graphql-type-json", 3 | "version": "0.3.2", 4 | "description": "JSON scalar types for GraphQL.js", 5 | "files": [ 6 | "lib", 7 | "es" 8 | ], 9 | "main": "lib/index.js", 10 | "module": "es/index.js", 11 | "types": "lib/index.d.ts", 12 | "scripts": { 13 | "build": "npm run build:cjs && npm run build:esm && npm run build:types", 14 | "build:cjs": "babel -d lib --delete-dir-on-start src", 15 | "build:esm": "babel --env-name esm -d es --delete-dir-on-start src", 16 | "build:types": "cpy types/*.d.ts lib", 17 | "format": "eslint --fix . && npm run prettier -- --write", 18 | "lint": "eslint . && npm run prettier -- -l", 19 | "prepublish": "npm run build", 20 | "prettier": "prettier --ignore-path .eslintignore '**/*.{md,ts,tsx}'", 21 | "tdd": "jest --watch", 22 | "test": "npm run lint && npm run test:ts && npm run testonly -- --coverage", 23 | "test:ts": "dtslint types", 24 | "testonly": "jest --runInBand --verbose" 25 | }, 26 | "husky": { 27 | "hooks": { 28 | "pre-commit": "lint-staged" 29 | } 30 | }, 31 | "lint-staged": { 32 | "*.js": "eslint --fix", 33 | "*.{md,ts}": "prettier --write" 34 | }, 35 | "prettier": { 36 | "printWidth": 79, 37 | "singleQuote": true, 38 | "trailingComma": "all" 39 | }, 40 | "jest": { 41 | "collectCoverageFrom": [ 42 | "src/**" 43 | ], 44 | "testEnvironment": "node" 45 | }, 46 | "repository": { 47 | "type": "git", 48 | "url": "git+https://github.com/taion/graphql-type-json.git" 49 | }, 50 | "keywords": [ 51 | "graphql" 52 | ], 53 | "author": "Jimmy Jia", 54 | "license": "MIT", 55 | "bugs": { 56 | "url": "https://github.com/taion/graphql-type-json/issues" 57 | }, 58 | "homepage": "https://github.com/taion/graphql-type-json#readme", 59 | "devDependencies": { 60 | "@babel/cli": "^7.12.13", 61 | "@babel/core": "^7.12.13", 62 | "@babel/preset-env": "^7.12.13", 63 | "babel-jest": "^26.6.3", 64 | "codecov": "^3.8.1", 65 | "cpy-cli": "^3.1.1", 66 | "dtslint": "^3.7.0", 67 | "eslint": "^7.19.0", 68 | "eslint-config-4catalyzer": "^1.1.5", 69 | "eslint-config-4catalyzer-jest": "^2.0.10", 70 | "eslint-config-prettier": "^6.15.0", 71 | "eslint-plugin-import": "^2.22.1", 72 | "eslint-plugin-jest": "^23.20.0", 73 | "eslint-plugin-prettier": "^3.3.1", 74 | "graphql": "^15.5.0", 75 | "husky": "^4.3.8", 76 | "jest": "^26.6.3", 77 | "lint-staged": "^10.5.4", 78 | "prettier": "^2.2.1", 79 | "typescript": "^4.1.3" 80 | }, 81 | "peerDependencies": { 82 | "graphql": ">=0.8.0" 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import { GraphQLScalarType } from 'graphql'; 2 | import { Kind, print } from 'graphql/language'; 3 | 4 | function identity(value) { 5 | return value; 6 | } 7 | 8 | function ensureObject(value) { 9 | if (typeof value !== 'object' || value === null || Array.isArray(value)) { 10 | throw new TypeError( 11 | `JSONObject cannot represent non-object value: ${value}`, 12 | ); 13 | } 14 | 15 | return value; 16 | } 17 | 18 | function parseObject(typeName, ast, variables) { 19 | const value = Object.create(null); 20 | ast.fields.forEach((field) => { 21 | // eslint-disable-next-line no-use-before-define 22 | value[field.name.value] = parseLiteral(typeName, field.value, variables); 23 | }); 24 | 25 | return value; 26 | } 27 | 28 | function parseLiteral(typeName, ast, variables) { 29 | switch (ast.kind) { 30 | case Kind.STRING: 31 | case Kind.BOOLEAN: 32 | return ast.value; 33 | case Kind.INT: 34 | case Kind.FLOAT: 35 | return parseFloat(ast.value); 36 | case Kind.OBJECT: 37 | return parseObject(typeName, ast, variables); 38 | case Kind.LIST: 39 | return ast.values.map((n) => parseLiteral(typeName, n, variables)); 40 | case Kind.NULL: 41 | return null; 42 | case Kind.VARIABLE: 43 | return variables ? variables[ast.name.value] : undefined; 44 | default: 45 | throw new TypeError(`${typeName} cannot represent value: ${print(ast)}`); 46 | } 47 | } 48 | 49 | // This named export is intended for users of CommonJS. Users of ES modules 50 | // should instead use the default export. 51 | export const GraphQLJSON = new GraphQLScalarType({ 52 | name: 'JSON', 53 | description: 54 | 'The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf).', 55 | specifiedByUrl: 56 | 'http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf', 57 | serialize: identity, 58 | parseValue: identity, 59 | parseLiteral: (ast, variables) => parseLiteral('JSON', ast, variables), 60 | }); 61 | 62 | export default GraphQLJSON; 63 | 64 | export const GraphQLJSONObject = new GraphQLScalarType({ 65 | name: 'JSONObject', 66 | description: 67 | 'The `JSONObject` scalar type represents JSON objects as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf).', 68 | specifiedByUrl: 69 | 'http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf', 70 | serialize: ensureObject, 71 | parseValue: ensureObject, 72 | parseLiteral: (ast, variables) => { 73 | if (ast.kind !== Kind.OBJECT) { 74 | throw new TypeError( 75 | `JSONObject cannot represent non-object value: ${print(ast)}`, 76 | ); 77 | } 78 | 79 | return parseObject('JSONObject', ast, variables); 80 | }, 81 | }); 82 | -------------------------------------------------------------------------------- /test/index.test.js: -------------------------------------------------------------------------------- 1 | import { 2 | GraphQLInt, 3 | GraphQLObjectType, 4 | GraphQLSchema, 5 | graphql, 6 | } from 'graphql'; 7 | 8 | // eslint-disable-next-line import/no-named-as-default 9 | import GraphQLJSON, { GraphQLJSONObject } from '../src'; 10 | 11 | const FIXTURE = { 12 | string: 'string', 13 | int: 3, 14 | float: 3.14, 15 | true: true, 16 | false: false, 17 | null: null, 18 | object: { 19 | string: 'string', 20 | int: 3, 21 | float: 3.14, 22 | true: true, 23 | false: false, 24 | null: null, 25 | }, 26 | array: ['string', 3, 3.14, true, false, null], 27 | }; 28 | 29 | function createSchema(type) { 30 | return new GraphQLSchema({ 31 | query: new GraphQLObjectType({ 32 | name: 'Query', 33 | fields: { 34 | value: { 35 | type, 36 | args: { 37 | arg: { type }, 38 | }, 39 | resolve: (obj, { arg }) => arg, 40 | }, 41 | rootValue: { 42 | type, 43 | resolve: (obj) => obj, 44 | }, 45 | }, 46 | }), 47 | types: [GraphQLInt], 48 | }); 49 | } 50 | 51 | describe('GraphQLJSON', () => { 52 | let schema; 53 | 54 | beforeEach(() => { 55 | schema = createSchema(GraphQLJSON); 56 | }); 57 | 58 | describe('serialize', () => { 59 | it('should support serialization', () => 60 | graphql( 61 | schema, 62 | /* GraphQL */ ` 63 | query { 64 | rootValue 65 | } 66 | `, 67 | FIXTURE, 68 | ).then(({ data, errors }) => { 69 | expect(data.rootValue).toEqual(FIXTURE); 70 | expect(errors).toBeUndefined(); 71 | })); 72 | }); 73 | 74 | describe('parseValue', () => { 75 | it('should support parsing values', () => 76 | graphql( 77 | schema, 78 | /* GraphQL */ ` 79 | query($arg: JSON!) { 80 | value(arg: $arg) 81 | } 82 | `, 83 | null, 84 | null, 85 | { 86 | arg: FIXTURE, 87 | }, 88 | ).then(({ data, errors }) => { 89 | expect(data.value).toEqual(FIXTURE); 90 | expect(errors).toBeUndefined(); 91 | })); 92 | }); 93 | 94 | describe('parseLiteral', () => { 95 | it('should support parsing literals', () => 96 | graphql( 97 | schema, 98 | /* GraphQL */ ` 99 | query($intValue: Int = 3) { 100 | value( 101 | arg: { 102 | string: "string" 103 | int: $intValue 104 | float: 3.14 105 | true: true 106 | false: false 107 | null: null 108 | object: { 109 | string: "string" 110 | int: $intValue 111 | float: 3.14 112 | true: true 113 | false: false 114 | null: null 115 | } 116 | array: ["string", $intValue, 3.14, true, false, null] 117 | } 118 | ) 119 | } 120 | `, 121 | ).then(({ data, errors }) => { 122 | expect(data.value).toEqual(FIXTURE); 123 | expect(errors).toBeUndefined(); 124 | })); 125 | 126 | it('should handle null literal', () => 127 | graphql( 128 | schema, 129 | /* GraphQL */ ` 130 | { 131 | value(arg: null) 132 | } 133 | `, 134 | ).then(({ data, errors }) => { 135 | expect(data).toEqual({ 136 | value: null, 137 | }); 138 | expect(errors).toBeUndefined(); 139 | })); 140 | 141 | it('should handle list literal', () => 142 | graphql( 143 | schema, 144 | /* GraphQL */ ` 145 | { 146 | value(arg: []) 147 | } 148 | `, 149 | ).then(({ data, errors }) => { 150 | expect(data).toEqual({ 151 | value: [], 152 | }); 153 | expect(errors).toBeUndefined(); 154 | })); 155 | 156 | it('should reject invalid literal', () => 157 | graphql( 158 | schema, 159 | /* GraphQL */ ` 160 | { 161 | value(arg: INVALID) 162 | } 163 | `, 164 | ).then(({ data, errors }) => { 165 | expect(data).toBeUndefined(); 166 | expect(errors).toMatchInlineSnapshot(` 167 | Array [ 168 | [GraphQLError: Expected value of type "JSON", found INVALID; JSON cannot represent value: INVALID], 169 | ] 170 | `); 171 | })); 172 | }); 173 | }); 174 | 175 | describe('GraphQLJSONObject', () => { 176 | let schema; 177 | 178 | beforeEach(() => { 179 | schema = createSchema(GraphQLJSONObject); 180 | }); 181 | 182 | describe('serialize', () => { 183 | it('should support serialization', () => 184 | graphql( 185 | schema, 186 | /* GraphQL */ ` 187 | query { 188 | rootValue 189 | } 190 | `, 191 | FIXTURE, 192 | ).then(({ data, errors }) => { 193 | expect(data.rootValue).toEqual(FIXTURE); 194 | expect(errors).toBeUndefined(); 195 | })); 196 | 197 | it('should reject string value', () => 198 | graphql( 199 | schema, 200 | /* GraphQL */ ` 201 | query { 202 | rootValue 203 | } 204 | `, 205 | 'foo', 206 | ).then(({ data, errors }) => { 207 | expect(data.rootValue).toBeNull(); 208 | expect(errors).toMatchInlineSnapshot(` 209 | Array [ 210 | [GraphQLError: JSONObject cannot represent non-object value: foo], 211 | ] 212 | `); 213 | })); 214 | 215 | it('should reject array value', () => 216 | graphql( 217 | schema, 218 | /* GraphQL */ ` 219 | query { 220 | rootValue 221 | } 222 | `, 223 | [], 224 | ).then(({ data, errors }) => { 225 | expect(data.rootValue).toBeNull(); 226 | expect(errors).toMatchInlineSnapshot(` 227 | Array [ 228 | [GraphQLError: JSONObject cannot represent non-object value: ], 229 | ] 230 | `); 231 | })); 232 | }); 233 | 234 | describe('parseValue', () => { 235 | it('should support parsing values', () => 236 | graphql( 237 | schema, 238 | /* GraphQL */ ` 239 | query($arg: JSONObject!) { 240 | value(arg: $arg) 241 | } 242 | `, 243 | null, 244 | null, 245 | { 246 | arg: FIXTURE, 247 | }, 248 | ).then(({ data, errors }) => { 249 | expect(data.value).toEqual(FIXTURE); 250 | expect(errors).toBeUndefined(); 251 | })); 252 | 253 | it('should reject string value', () => 254 | graphql( 255 | schema, 256 | /* GraphQL */ ` 257 | query($arg: JSONObject!) { 258 | value(arg: $arg) 259 | } 260 | `, 261 | null, 262 | null, 263 | { 264 | arg: 'foo', 265 | }, 266 | ).then(({ data, errors }) => { 267 | expect(data).toBeUndefined(); 268 | expect(errors).toMatchInlineSnapshot(` 269 | Array [ 270 | [GraphQLError: Variable "$arg" got invalid value "foo"; Expected type "JSONObject". JSONObject cannot represent non-object value: foo], 271 | ] 272 | `); 273 | })); 274 | 275 | it('should reject array value', () => 276 | graphql( 277 | schema, 278 | /* GraphQL */ ` 279 | query($arg: JSONObject!) { 280 | value(arg: $arg) 281 | } 282 | `, 283 | null, 284 | null, 285 | { 286 | arg: [], 287 | }, 288 | ).then(({ data, errors }) => { 289 | expect(data).toBeUndefined(); 290 | expect(errors).toMatchInlineSnapshot(` 291 | Array [ 292 | [GraphQLError: Variable "$arg" got invalid value []; Expected type "JSONObject". JSONObject cannot represent non-object value: ], 293 | ] 294 | `); 295 | })); 296 | }); 297 | 298 | describe('parseLiteral', () => { 299 | it('should support parsing literals', () => 300 | graphql( 301 | schema, 302 | /* GraphQL */ ` 303 | query($intValue: Int = 3) { 304 | value( 305 | arg: { 306 | string: "string" 307 | int: $intValue 308 | float: 3.14 309 | true: true 310 | false: false 311 | null: null 312 | object: { 313 | string: "string" 314 | int: $intValue 315 | float: 3.14 316 | true: true 317 | false: false 318 | null: null 319 | } 320 | array: ["string", $intValue, 3.14, true, false, null] 321 | } 322 | ) 323 | } 324 | `, 325 | ).then(({ data, errors }) => { 326 | expect(data.value).toEqual(FIXTURE); 327 | expect(errors).toBeUndefined(); 328 | })); 329 | 330 | it('should reject string literal', () => 331 | graphql( 332 | schema, 333 | /* GraphQL */ ` 334 | { 335 | value(arg: "foo") 336 | } 337 | `, 338 | ).then(({ data, errors }) => { 339 | expect(data).toBeUndefined(); 340 | expect(errors).toMatchInlineSnapshot(` 341 | Array [ 342 | [GraphQLError: Expected value of type "JSONObject", found "foo"; JSONObject cannot represent non-object value: "foo"], 343 | ] 344 | `); 345 | })); 346 | 347 | it('should reject array literal', () => 348 | graphql( 349 | schema, 350 | /* GraphQL */ ` 351 | { 352 | value(arg: []) 353 | } 354 | `, 355 | ).then(({ data, errors }) => { 356 | expect(data).toBeUndefined(); 357 | expect(errors).toMatchInlineSnapshot(` 358 | Array [ 359 | [GraphQLError: Expected value of type "JSONObject", found []; JSONObject cannot represent non-object value: []], 360 | ] 361 | `); 362 | })); 363 | }); 364 | }); 365 | --------------------------------------------------------------------------------