diff --git a/package-lock.json b/package-lock.json index 7ae6828..ae2d190 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,26 +22,18 @@ "mocha": "9.2.2", "prettier": "3.3.3", "sinon": "13.0.1", - "ts-node": "10.4.0", - "typescript": "4.7.4" - } - }, - "node_modules/@cspotcode/source-map-consumer": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", - "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", - "dev": true, - "engines": { - "node": ">= 12" + "ts-node": "10.9.2", + "typescript": "5.3.3" } }, "node_modules/@cspotcode/source-map-support": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", - "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, + "license": "MIT", "dependencies": { - "@cspotcode/source-map-consumer": "0.8.0" + "@jridgewell/trace-mapping": "0.3.9" }, "engines": { "node": ">=12" @@ -193,6 +185,34 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2519,12 +2539,13 @@ } }, "node_modules/ts-node": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.4.0.tgz", - "integrity": "sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==", + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, + "license": "MIT", "dependencies": { - "@cspotcode/source-map-support": "0.7.0", + "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", @@ -2535,11 +2556,13 @@ "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "bin": { "ts-node": "dist/bin.js", "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", "ts-node-script": "dist/bin-script.js", "ts-node-transpile-only": "dist/bin-transpile.js", "ts-script": "dist/bin-script-deprecated.js" @@ -2582,9 +2605,9 @@ } }, "node_modules/typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -2592,7 +2615,7 @@ "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, "node_modules/uri-js": { @@ -2605,6 +2628,13 @@ "punycode": "^2.1.0" } }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -2762,19 +2792,13 @@ } }, "dependencies": { - "@cspotcode/source-map-consumer": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", - "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", - "dev": true - }, "@cspotcode/source-map-support": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", - "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, "requires": { - "@cspotcode/source-map-consumer": "0.8.0" + "@jridgewell/trace-mapping": "0.3.9" } }, "@eslint-community/eslint-utils": { @@ -2870,6 +2894,28 @@ "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", "dev": true }, + "@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -4455,12 +4501,12 @@ "requires": {} }, "ts-node": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.4.0.tgz", - "integrity": "sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==", + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "requires": { - "@cspotcode/source-map-support": "0.7.0", + "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", @@ -4471,6 +4517,7 @@ "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" } }, @@ -4490,9 +4537,9 @@ "dev": true }, "typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", "dev": true }, "uri-js": { @@ -4504,6 +4551,12 @@ "punycode": "^2.1.0" } }, + "v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index c8fb3a6..5465155 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "mocha": "9.2.2", "prettier": "3.3.3", "sinon": "13.0.1", - "ts-node": "10.4.0", - "typescript": "4.7.4" + "ts-node": "10.9.2", + "typescript": "5.3.3" } } diff --git a/src/__tests__/aliases.tests.ts b/src/__tests__/aliases.tests.ts index 1597cb4..7e81476 100644 --- a/src/__tests__/aliases.tests.ts +++ b/src/__tests__/aliases.tests.ts @@ -1,11 +1,11 @@ import { expect } from 'chai'; -import { jsonToGraphQLQuery } from '../'; +import { jsonToGraphQLQuery, type QueryJSON } from '../'; describe('jsonToGraphQLQuery() - aliases', () => { it('supports multiple aliases for one type', () => { - const query = { + const query: QueryJSON = { query: { lorem: { __aliasFor: 'Posts', diff --git a/src/__tests__/arguments.tests.ts b/src/__tests__/arguments.tests.ts index 2104d46..18866a0 100644 --- a/src/__tests__/arguments.tests.ts +++ b/src/__tests__/arguments.tests.ts @@ -1,11 +1,11 @@ import { expect } from 'chai'; -import { jsonToGraphQLQuery } from '../'; +import { jsonToGraphQLQuery, type QueryJSON } from '../'; describe('jsonToGraphQLQuery() - arguments', () => { it('converts a query with simple arguments', () => { - const query = { + const query: QueryJSON = { query: { Posts: { __args: { @@ -29,7 +29,7 @@ describe('jsonToGraphQLQuery() - arguments', () => { }); it('converts a query with JSON arguments', () => { - const query = { + const query: QueryJSON = { query: { Posts: { __args: { @@ -56,7 +56,7 @@ describe('jsonToGraphQLQuery() - arguments', () => { }); it('converts a query with JSON arguments containing arrays of objects', () => { - const query = { + const query: QueryJSON = { query: { Posts: { __args: { @@ -83,7 +83,7 @@ describe('jsonToGraphQLQuery() - arguments', () => { }); it('converts a query with null arguments and nested nulls', () => { - const query = { + const query: QueryJSON = { query: { Posts: { __args: { @@ -97,7 +97,7 @@ describe('jsonToGraphQLQuery() - arguments', () => { post_date: true } } - } as any; + }; expect(jsonToGraphQLQuery(query, { pretty: true })).to.equal( `query { Posts (where: {id: null}, orderBy: null) { @@ -109,7 +109,7 @@ describe('jsonToGraphQLQuery() - arguments', () => { }); it('converts a query with nested objects and arguments', () => { - const query = { + const query: QueryJSON = { query: { Posts: { __args: { @@ -144,7 +144,7 @@ describe('jsonToGraphQLQuery() - arguments', () => { }); it('works with pretty mode turned off', () => { - const query = { + const query: QueryJSON = { query: { Posts: { __args: { @@ -162,7 +162,7 @@ describe('jsonToGraphQLQuery() - arguments', () => { }); it('Empty args object should not generate parentheses', () => { - const query = { + const query: QueryJSON = { query: { Posts: { __args: {}, diff --git a/src/__tests__/directives.tests.ts b/src/__tests__/directives.tests.ts index 9891263..05de5c7 100644 --- a/src/__tests__/directives.tests.ts +++ b/src/__tests__/directives.tests.ts @@ -1,11 +1,11 @@ import { expect } from 'chai'; -import { jsonToGraphQLQuery } from '../'; +import { jsonToGraphQLQuery, type QueryJSON } from '../'; describe('jsonToGraphQLQuery() - directives', () => { it('converts a simple query with args and directives with no arguments', () => { - const query = { + const query: QueryJSON = { query: { Posts: { __args: { @@ -22,7 +22,7 @@ describe('jsonToGraphQLQuery() - directives', () => { post_date: true } } - } as any; + }; expect(jsonToGraphQLQuery(query, { pretty: true })).to.equal( `query { Posts (where: {id: 10}, orderBy: "flibble") @client { @@ -34,7 +34,7 @@ describe('jsonToGraphQLQuery() - directives', () => { }); it('converts a complex query with directives with no arguments', () => { - const query = { + const query: QueryJSON = { query: { diet: { __directives: { @@ -57,23 +57,23 @@ describe('jsonToGraphQLQuery() - directives', () => { }, title: 'Diet' }, - someOtherAbritraryKey: { + someOtherArbitraryKey: { __directives: { client: true }, arb1: 'arbitrary value', - arb2: 'some other arbitrary value' + arb2: 'some other arbitrary value', } } }; const expected = 'query { diet @client { id options { ' + 'mood { category id selected } weight { category icon id text } } ' + - 'title } someOtherAbritraryKey @client { arb1 arb2 } }'; + 'title } someOtherArbitraryKey @client { arb1 arb2 } }'; expect(jsonToGraphQLQuery(query)).to.equal(expected); }); it('converts a simple query with args and multiple directives', () => { - const query = { + const query: QueryJSON = { query: { Posts: { __args: { @@ -93,7 +93,7 @@ describe('jsonToGraphQLQuery() - directives', () => { post_date: true, }, }, - } as any; + }; expect(jsonToGraphQLQuery(query, { pretty: true })).to.equal( `query { Posts (where: {id: 10}, orderBy: "flibble") @client @withArgs(id: [1, 2, 3]) { @@ -106,7 +106,7 @@ describe('jsonToGraphQLQuery() - directives', () => { }); it('converts a simple query with args and multiple directives but a directive has an empty object', () => { - const query = { + const query: QueryJSON = { query: { Posts: { __args: { @@ -124,7 +124,7 @@ describe('jsonToGraphQLQuery() - directives', () => { post_date: true, }, }, - } as any; + }; expect(jsonToGraphQLQuery(query, { pretty: true })).to.equal( `query { Posts (where: {id: 10}, orderBy: "flibble") @client @withArgs { @@ -137,7 +137,7 @@ describe('jsonToGraphQLQuery() - directives', () => { }); it('converts a complex query with multiple directives', () => { - const query = { + const query: QueryJSON = { query: { diet: { __directives: { @@ -160,7 +160,7 @@ describe('jsonToGraphQLQuery() - directives', () => { }, title: 'Diet', }, - someOtherAbritraryKey: { + someOtherArbitraryKey: { __directives: { client: true, withArgs: { @@ -175,7 +175,7 @@ describe('jsonToGraphQLQuery() - directives', () => { const expected = 'query { diet @client { id options { ' + 'mood { category id selected } weight { category icon id text } } ' + - 'title } someOtherAbritraryKey @client @withArgs(id: [1, 2, 3]) { arb1 arb2 } }'; + 'title } someOtherArbitraryKey @client @withArgs(id: [1, 2, 3]) { arb1 arb2 } }'; expect(jsonToGraphQLQuery(query)).to.equal(expected); }); diff --git a/src/__tests__/falsykeys.tests.ts b/src/__tests__/falsykeys.tests.ts index 705b578..0a328ea 100644 --- a/src/__tests__/falsykeys.tests.ts +++ b/src/__tests__/falsykeys.tests.ts @@ -1,9 +1,9 @@ import { expect } from 'chai'; -import { jsonToGraphQLQuery } from '../'; +import { jsonToGraphQLQuery, type QueryJSON } from '../'; describe('jsonToGraphQLQuery() - falsy keys', () => { it('does not include fields which value is false', () => { - const query = { + const query: QueryJSON = { query: { Posts: { __args: { @@ -24,7 +24,7 @@ describe('jsonToGraphQLQuery() - falsy keys', () => { }); it('includes fields with falsy values if includeFalsyKeys is true', () => { - const query = { + const query: QueryJSON = { query: { Posts: { __args: { @@ -45,7 +45,7 @@ describe('jsonToGraphQLQuery() - falsy keys', () => { }); it('does not include object with only false keys', () => { - const query = { + const query: QueryJSON = { query: { Posts: { id: true, @@ -63,7 +63,7 @@ describe('jsonToGraphQLQuery() - falsy keys', () => { }); it('does include object with only false keys if includeFalsyKeys is true', () => { - const query = { + const query: QueryJSON = { query: { Posts: { id: true, @@ -81,7 +81,7 @@ describe('jsonToGraphQLQuery() - falsy keys', () => { }); it('Includes the nested object if includeFalsyKeys is true', () => { - const query = { + const query: QueryJSON = { query: { Posts: { id: true, @@ -100,7 +100,7 @@ describe('jsonToGraphQLQuery() - falsy keys', () => { }); it('does not include the object if nested object has falsy values', () => { - const query = { + const query: QueryJSON = { query: { Posts: { id: true, @@ -117,7 +117,7 @@ describe('jsonToGraphQLQuery() - falsy keys', () => { }); it('skip objects when deeply nested keys contain falsy values', () => { - const query = { + const query: QueryJSON = { query: { id: true, Posts: { @@ -145,7 +145,7 @@ describe('jsonToGraphQLQuery() - falsy keys', () => { }); it('Include values if nested object has falsy values and includeFalsyKeys is true', () => { - const query = { + const query: QueryJSON = { query: { Posts: { id: true, diff --git a/src/__tests__/fragments.tests.ts b/src/__tests__/fragments.tests.ts index 34214ed..aca8556 100644 --- a/src/__tests__/fragments.tests.ts +++ b/src/__tests__/fragments.tests.ts @@ -1,11 +1,11 @@ import { expect } from 'chai'; -import { jsonToGraphQLQuery } from '../'; +import { jsonToGraphQLQuery, type QueryJSON } from '../'; describe('jsonToGraphQLQuery() - fragments', () => { it('supports inline fragments', () => { - const query = { + const query: QueryJSON = { query: { Posts: { __on: { @@ -21,7 +21,7 @@ describe('jsonToGraphQLQuery() - fragments', () => { }); it('supports inline fragments with subfields on same level', () => { - const query = { + const query: QueryJSON = { query: { Posts: { title: true, @@ -38,7 +38,7 @@ describe('jsonToGraphQLQuery() - fragments', () => { }); it('supports multiple inline fragments', () => { - const query = { + const query: QueryJSON = { query: { Posts: { __on: [ @@ -49,7 +49,8 @@ describe('jsonToGraphQLQuery() - fragments', () => { { __typeName: 'UnconfigurablePost', name: true - }] + } + ] } } }; @@ -59,19 +60,19 @@ describe('jsonToGraphQLQuery() - fragments', () => { }); it('supports full inline fragments', () => { - const query = { - query: { - Posts: { - __all_on: [ - 'ConfigurablePost', - 'PageInfo' - ] - } - } - }; - expect(jsonToGraphQLQuery(query)).to.equal( - 'query { Posts { ...ConfigurablePost ...PageInfo } }' - ); - }); + const query: QueryJSON = { + query: { + Posts: { + __all_on: [ + 'ConfigurablePost', + 'PageInfo' + ] + } + } + }; + expect(jsonToGraphQLQuery(query)).to.equal( + 'query { Posts { ...ConfigurablePost ...PageInfo } }' + ); + }); }); diff --git a/src/__tests__/ignorefields.tests.ts b/src/__tests__/ignorefields.tests.ts index 7d90c02..cba8139 100644 --- a/src/__tests__/ignorefields.tests.ts +++ b/src/__tests__/ignorefields.tests.ts @@ -1,11 +1,11 @@ import { expect } from 'chai'; -import { jsonToGraphQLQuery } from '../'; +import { jsonToGraphQLQuery, type QueryJSON } from '../'; describe('jsonToGraphQLQuery() - ignoreFields option', () => { it('ignores a field that exists in the initial object', () => { - const query = { + const query: QueryJSON = { query: { Posts: { thisShouldBeIgnored: { @@ -19,7 +19,7 @@ describe('jsonToGraphQLQuery() - ignoreFields option', () => { }; expect(jsonToGraphQLQuery(query, { pretty: true, - ignoreFields: ['thisShouldBeIgnored'] + ignoreFields: ['thisShouldBeIgnored'], })).to.equal( `query { Posts { @@ -31,7 +31,7 @@ describe('jsonToGraphQLQuery() - ignoreFields option', () => { }); it('we can ignore apollo __typename keys', () => { - const query = { + const query: QueryJSON = { query: { Posts: { __typename: 'Posts', @@ -47,7 +47,7 @@ describe('jsonToGraphQLQuery() - ignoreFields option', () => { }; expect(jsonToGraphQLQuery(query, { pretty: true, - ignoreFields: ['__typename'] + ignoreFields: ['__typename'], })).to.equal( `query { Posts { diff --git a/src/__tests__/mutations.tests.ts b/src/__tests__/mutations.tests.ts index 940d94c..517d3e4 100644 --- a/src/__tests__/mutations.tests.ts +++ b/src/__tests__/mutations.tests.ts @@ -1,9 +1,9 @@ import { expect } from 'chai'; -import { jsonToGraphQLQuery } from '../'; +import { jsonToGraphQLQuery, type MutationJSON } from '../'; describe('jsonToGraphQLQuery() - mutations', () => { it('simple mutation', () => { - const mutation = { + const mutation: MutationJSON = { mutation: { delete_post: { __args: { id: 1234 }, @@ -21,7 +21,7 @@ describe('jsonToGraphQLQuery() - mutations', () => { }); it('correctly converts mutations with no specified return fields', () => { - const query = { + const query: MutationJSON = { mutation: { create_post: { __args: { diff --git a/src/__tests__/name.tests.ts b/src/__tests__/name.tests.ts index ed777e2..091e07a 100644 --- a/src/__tests__/name.tests.ts +++ b/src/__tests__/name.tests.ts @@ -1,9 +1,9 @@ import { expect } from 'chai'; -import { jsonToGraphQLQuery, EnumType, VariableType } from '../'; +import { jsonToGraphQLQuery, EnumType, VariableType, type QueryJSON, type MutationJSON } from '../'; describe('jsonToGraphQLQuery() - name', () => { it('supports Named Queries', () => { - const query = { + const query: QueryJSON = { query: { __name: 'NewName', lorem: { @@ -28,7 +28,7 @@ describe('jsonToGraphQLQuery() - name', () => { }); it('supports Named Mutations', () => { - const query = { + const query: MutationJSON = { mutation: { __name: 'NewName', one: { @@ -55,7 +55,7 @@ describe('jsonToGraphQLQuery() - name', () => { describe('jsonToGraphQLQuery() - combinations', () => { it('correctly converts query with name/ empty variables', () => { - const query = { + const query: QueryJSON = { query: { __name: 'NewName', __variables: {}, @@ -80,7 +80,7 @@ describe('jsonToGraphQLQuery() - combinations', () => { }); it('correctly converts query with name/variables', () => { - const query = { + const query: QueryJSON = { query: { __name: 'NewName', __variables: { @@ -108,7 +108,7 @@ describe('jsonToGraphQLQuery() - combinations', () => { }); it('correctly converts query with variables/name/alias/args/variable/fragments', () => { - const query = { + const query: QueryJSON = { query: { __name: 'NewName', __variables: { diff --git a/src/__tests__/nodes.tests.ts b/src/__tests__/nodes.tests.ts index f4380d6..12ee219 100644 --- a/src/__tests__/nodes.tests.ts +++ b/src/__tests__/nodes.tests.ts @@ -1,6 +1,6 @@ import { expect } from 'chai'; -import { jsonToGraphQLQuery } from '../'; +import { jsonToGraphQLQuery, type QueryJSON } from '../'; describe('jsonToGraphQLQuery() - node conversion', () => { @@ -12,18 +12,20 @@ describe('jsonToGraphQLQuery() - node conversion', () => { it('throws if query is not an object', () => { expect(() => { + // @ts-expect-error jsonToGraphQLQuery('not a query object'); }).to.throw('query object not specified'); }); it('throws if object has no keys', () => { expect(() => { + // @ts-expect-error jsonToGraphQLQuery({}); }).to.throw('query object has no data'); }); it('converts a simple query', () => { - const query = { + const query: QueryJSON = { query: { Posts: { id: true, @@ -43,7 +45,7 @@ describe('jsonToGraphQLQuery() - node conversion', () => { }); it('converts a query with nested objects', () => { - const query = { + const query: QueryJSON = { query: { Posts: { id: true, @@ -71,7 +73,7 @@ describe('jsonToGraphQLQuery() - node conversion', () => { }); it('gets keys from an array instead of adding the index as a key', () => { - const query = { + const query: QueryJSON = { query: { Posts: [{ id: true, @@ -89,7 +91,7 @@ describe('jsonToGraphQLQuery() - node conversion', () => { }); it('gets keys from an array instead of adding the index as a key and print pretty', () => { - const query = { + const query: QueryJSON = { query: { Posts: [{ id: true, @@ -114,10 +116,9 @@ describe('jsonToGraphQLQuery() - node conversion', () => { }); it('handles empty arrays by adding the key but no values to the query', () => { - const Posts: any[] = []; - const query = { + const query: QueryJSON = { query: { - Posts, + Posts: [], Lorem: { id: true }, @@ -130,7 +131,7 @@ describe('jsonToGraphQLQuery() - node conversion', () => { }); it('handles arrays of numbers by adding the key but no values to the query', () => { - const query = { + const query: QueryJSON = { query: { Posts: [1, 2, 3], Lorem: { @@ -145,7 +146,7 @@ describe('jsonToGraphQLQuery() - node conversion', () => { }); it('handles arrays of strings by adding the key but no values to the query', () => { - const query = { + const query: QueryJSON = { query: { Posts: ['test 1', 'test 2', 'test 3'], Lorem: { @@ -160,7 +161,7 @@ describe('jsonToGraphQLQuery() - node conversion', () => { }); it('handles arrays of mixed types by taking the first object of the array', () => { - const query = { + const query: QueryJSON = { query: { Posts: [1, null, { id: true, name: true }], Lorem: { @@ -175,10 +176,9 @@ describe('jsonToGraphQLQuery() - node conversion', () => { }); it('handles arrays of string by adding the key but no values to the query', () => { - const Posts: any[] = [null]; - const query = { + const query: QueryJSON = { query: { - Posts, + Posts: [null], Lorem: { id: true }, @@ -191,15 +191,14 @@ describe('jsonToGraphQLQuery() - node conversion', () => { }); it('handles arrays of string by adding the key but no values to the query and print pretty', () => { - const Posts: any[] = []; - const query = { + const query: QueryJSON = { query: { - Posts, + Posts: [], Lorem: { - id: true + id: true, }, Ipsum: false, - } + }, }; expect(jsonToGraphQLQuery(query, { pretty: true })).to.equal( `query { diff --git a/src/index.ts b/src/index.ts index 08d7420..b3ba9d3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,3 @@ - export * from './jsonToGraphQLQuery'; export {EnumType} from './types/EnumType'; export {VariableType} from './types/VariableType'; diff --git a/src/jsonToGraphQLQuery.ts b/src/jsonToGraphQLQuery.ts index 40dda23..f22dd7d 100644 --- a/src/jsonToGraphQLQuery.ts +++ b/src/jsonToGraphQLQuery.ts @@ -3,6 +3,7 @@ import { VariableType } from './types/VariableType'; export const configFields = [ '__args', + // still in here for compatibility with v1.* '__alias', '__aliasFor', '__variables', @@ -81,14 +82,89 @@ function getIndent(level: number): string { return Array(level * 4 + 1).join(' '); } -function filterNonConfigFields(fieldName: string, ignoreFields: string[]) { - // Returns true if fieldName is not a 'configField'. +/** + * Returns `true` if `fieldName` is not `ConfigField` and is not included to `ignoreFields` + */ +function filterNonConfigFields(fieldName: string, ignoreFields?: string[]) { return ( - configFields.indexOf(fieldName) == -1 && - ignoreFields.indexOf(fieldName) == -1 + !configFields.includes(fieldName) && + !ignoreFields?.includes(fieldName) ); } +type Primitive = string | number | boolean | EnumType | VariableType | null; +type ArgValue = Primitive | ArgObject | ArgValue[]; +type ArgObject = { + [key: string]: ArgValue; +}; + +type ArgumentsJSON = ArgObject; + +type DirectivesJSON = { + [directiveName: string]: | true | ArgObject | undefined; + skip?: { + if: VariableType | boolean; + }; + include?: { + if: VariableType | boolean; + }; +}; + +type OnFragment = SelectionSetJSON & { + __typeName: string; +}; + +type AllOnFragment = string[]; + +type Letter = 'a' | 'A' | 'b' | 'B' | 'c' | 'C' | 'd' | 'D' | 'e' | 'E' | 'f' | 'F' | 'g' | 'G' | 'h' | 'H' | 'i' | 'I' | 'j' | 'J' | 'k' | 'K' | 'l' | 'L' | 'm' | 'M' | 'n' | 'N' | 'o' | 'O' | 'p' | 'P' | 'q' | 'Q' | 'r' | 'R' | 's' | 'S' | 't' | 'T' | 'u' | 'U' | 'v' | 'V' | 'w' | 'W' | 'x' | 'X' | 'y' | 'Y' | 'z' | 'Z'; +type LetterOrDigit = Letter | '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'; +/** Start with letter or underscore (NameStart), do not start with two underscores (disallow reserved names) */ +type UnreservedName = `${Letter}${string}` | `_${LetterOrDigit}${string}`; + +type SelectionSetJSON = { + [k in UnreservedName]: FieldJSON; +} & { + __typename?: boolean | string; +}; +type FieldJSON = boolean | string | number | FieldJSONNode | (null | FieldJSON)[]; +type FieldJSONNode = SelectionSetJSON & { + __args?: ArgumentsJSON; + __aliasFor?: string; + __directives?: DirectivesJSON; + __on?: OnFragment | OnFragment[]; + __all_on?: AllOnFragment; +}; + +type FragmentJSON = { + fragment: SelectionSetJSON & { + __name?: string; + }; +}; + +type TypeName = string; +type TypeNameWithDefaultValue = + | `${'String' | 'ID'}${'' | '!'} = "${string}"` + | `${'Int' | 'Float'}${'' | '!'} = ${number}` + | `Boolean${'' | '!'} = ${boolean}` + | `${TypeName} = ${string}`; +type VariableDeclarations = Record; + +export type QueryJSON = { + query: { + __variables?: VariableDeclarations; + __name?: string; + } & SelectionSetJSON; +}; + +export type MutationJSON = { + mutation: { + __variables?: VariableDeclarations; + __name?: string; + } & SelectionSetJSON; +}; + +export type GraphQLJSON = FragmentJSON | QueryJSON | MutationJSON; + function convertQuery( node: any, level: number, @@ -96,7 +172,7 @@ function convertQuery( options: IJsonToGraphQLOptions ) { Object.keys(node) - .filter((key) => filterNonConfigFields(key, options.ignoreFields!)) + .filter((key) => filterNonConfigFields(key, options.ignoreFields)) .forEach((key) => { let value = node[key]; if (typeof value === 'object') { @@ -213,7 +289,7 @@ export interface IJsonToGraphQLOptions { } export function jsonToGraphQLQuery( - query: any, + query: GraphQLJSON, options: IJsonToGraphQLOptions = {} ) { if (!query || typeof query != 'object') { diff --git a/src/types/__tests__/EnumType.tests.ts b/src/types/__tests__/EnumType.tests.ts index e33e31a..641d8ba 100644 --- a/src/types/__tests__/EnumType.tests.ts +++ b/src/types/__tests__/EnumType.tests.ts @@ -1,23 +1,23 @@ import { expect } from 'chai'; -import { jsonToGraphQLQuery, EnumType } from '../../'; +import { jsonToGraphQLQuery, EnumType, type QueryJSON } from '../../'; describe('EnumType()', () => { it('converts a query with enum arguments', () => { - const query = { - query: { - Posts: { - __args: { - status: new EnumType('PUBLISHED') - }, - id: true, - title: true, - post_date: true - } - } - }; - expect(jsonToGraphQLQuery(query, { pretty: true })).to.equal( + const query: QueryJSON = { + query: { + Posts: { + __args: { + status: new EnumType('PUBLISHED') + }, + id: true, + title: true, + post_date: true + } + } + }; + expect(jsonToGraphQLQuery(query, { pretty: true })).to.equal( `query { Posts (status: PUBLISHED) { id @@ -25,6 +25,5 @@ describe('EnumType()', () => { post_date } }`); - }); - + }); }); \ No newline at end of file diff --git a/src/types/__tests__/VariableType.tests.ts b/src/types/__tests__/VariableType.tests.ts index 5f54977..fea494b 100644 --- a/src/types/__tests__/VariableType.tests.ts +++ b/src/types/__tests__/VariableType.tests.ts @@ -1,11 +1,11 @@ import { expect } from 'chai'; -import { jsonToGraphQLQuery, VariableType } from '../../'; +import { jsonToGraphQLQuery, type QueryJSON, VariableType } from '../../'; describe('VariableType()', () => { it('converts query variables', () => { - const query = { + const query: QueryJSON = { query: { __variables: { someString: 'String!',