diff --git a/.eslintrc.js b/.eslintrc.js index d720e6f..1775cb1 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -2,7 +2,6 @@ module.exports = { parser: '@typescript-eslint/parser', // Specifies the ESLint parser extends: [ 'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin - 'prettier/@typescript-eslint', // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier 'plugin:prettier/recommended', // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array. ], parserOptions: { diff --git a/package.json b/package.json index 6cc7e57..b29e0e7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "graphql-js-tree", - "version": "1.0.6", + "version": "1.0.7", "private": false, "license": "MIT", "description": "GraphQL Parser providing simplier structure", @@ -21,37 +21,24 @@ "url": "https://github.com/graphql-editor/graphql-js-tree.git" }, "devDependencies": { - "@commitlint/cli": "^8.3.5", - "@commitlint/config-conventional": "^8.3.4", "@types/graphql": "^14.5.0", - "@types/jest": "^25.1.4", - "@types/node": "^13.9.0", - "@typescript-eslint/eslint-plugin": "^4.15.0", - "@typescript-eslint/parser": "^4.15.0", - "cz-conventional-changelog": "^3.1.0", - "eslint": "^7.19.0", - "eslint-config-prettier": "^7.2.0", - "eslint-plugin-prettier": "^3.3.1", - "husky": "^4.2.3", - "jest": "^29.5.0", - "prettier": "^2.0.2", - "ts-jest": "^29.1.0", - "ts-node": "^9.0.0", - "ts-patch": "^3.0.0", - "typescript": "^5.1.3", + "@types/jest": "^29.5.11", + "@types/node": "^20.10.5", + "@typescript-eslint/eslint-plugin": "^6.16.0", + "@typescript-eslint/parser": "^6.16.0", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.1.2", + "husky": "^8.0.3", + "jest": "^29.7.0", + "prettier": "^3.1.1", + "ts-jest": "^29.1.1", + "ts-node": "^10.9.2", + "ts-patch": "^3.1.1", + "typescript": "^5.3.3", "typescript-transform-paths": "^3.4.6" }, "dependencies": { "graphql": "15.4.0" - }, - "config": { - "commitizen": { - "path": "./node_modules/cz-conventional-changelog" - } - }, - "husky": { - "hooks": { - "pre-commit": "npm run lint" - } } -} \ No newline at end of file +} diff --git a/src/TreeOperations/merge.ts b/src/TreeOperations/merge.ts index 8a83c38..82eb3cf 100644 --- a/src/TreeOperations/merge.ts +++ b/src/TreeOperations/merge.ts @@ -7,9 +7,11 @@ import { generateNodeId } from '@/shared'; const addFromLibrary = (n: ParserField): ParserField => ({ ...n, fromLibrary: true }); const mergeNode = (n1: ParserField, n2: ParserField) => { + const args = [...n1.args, ...n2.args.map(addFromLibrary)]; const mergedNode = { ...n1, - args: [...n1.args, ...n2.args.map(addFromLibrary)], + id: generateNodeId(n1.name, n1.data.type, args), + args, directives: [...n1.directives, ...n2.directives.map(addFromLibrary)], interfaces: [...n1.interfaces, ...n2.interfaces], } as ParserField; diff --git a/src/TreeOperations/orphans.ts b/src/TreeOperations/orphans.ts new file mode 100644 index 0000000..5812c10 --- /dev/null +++ b/src/TreeOperations/orphans.ts @@ -0,0 +1,16 @@ +import { ParserField, TypeSystemDefinition } from '@/Models'; + +export const removeOrphans = (possibleOrphans: string[], nodes: ParserField[]) => { + const usedNodes = nodes.flatMap((n) => { + return [...n.interfaces, ...n.args.flatMap((a) => [...a.name, ...a.args.map((ia) => ia.name)])]; + }); + return nodes.filter((n) => { + if (!possibleOrphans.includes(n.name)) { + return true; + } + if (n.data.type === TypeSystemDefinition.DirectiveDefinition) { + return true; + } + return usedNodes.includes(n.name); + }); +}; diff --git a/src/__tests__/GqlParser/GqlParserTreeToGql.spec.ts b/src/__tests__/GqlParser/GqlParserTreeToGql.spec.ts index 863c106..34141de 100644 --- a/src/__tests__/GqlParser/GqlParserTreeToGql.spec.ts +++ b/src/__tests__/GqlParser/GqlParserTreeToGql.spec.ts @@ -20,6 +20,7 @@ type Query { type User implements Nameable{ name: String age: Int + lastName: String friend: User } type Person implements Nameable{ @@ -80,6 +81,11 @@ const userNode = createRootField({ createPlainField({ name: 'friend', type: 'User' }), ], }); +const nameableNode = createRootField({ + name: 'Nameable', + type: TypeDefinition.InterfaceTypeDefinition, + args: [createPlainField({ name: 'name', type: 'String' })], +}); describe('Test generation of gql strings from the GqlParserTree', () => { it('Creates gql node from gql and schema', () => { @@ -327,11 +333,13 @@ describe('Test generation of gql strings from the GqlParserTree', () => { it('works with inline fragments', () => { const mockQueryInline = `query MyQuery { namings{ + name ... on Person { index } ... on User{ age + lastName } } }`; @@ -344,6 +352,10 @@ describe('Test generation of gql strings from the GqlParserTree', () => { name: 'namings', node: queryNode.args[2], children: [ + { + node: nameableNode.args[0], + name: 'name', + }, { inlineFragment: true, node: personNode, @@ -364,6 +376,10 @@ describe('Test generation of gql strings from the GqlParserTree', () => { name: 'age', node: userNode.args[1], }, + { + name: 'lastName', + node: userNode.args[2], + }, ], }, ], diff --git a/src/__tests__/TreeOperations/merge.spec.ts b/src/__tests__/TreeOperations/merge.spec.ts index bcff462..4348fbf 100644 --- a/src/__tests__/TreeOperations/merge.spec.ts +++ b/src/__tests__/TreeOperations/merge.spec.ts @@ -9,6 +9,26 @@ import { expectTrimmedEqual } from '@/__tests__/TestUtils'; // `; describe('Merging GraphQL Schemas', () => { + it('Should merge scalars', () => { + const baseSchema = ` + scalar URL + scalar JSON + `; + + const mergingSchema = ` + scalar URL + scalar DATE + `; + const t1 = mergeSDLs(baseSchema, mergingSchema); + if (t1.__typename === 'error') throw new Error('Invalid parse'); + expectTrimmedEqual( + t1.sdl, + ` + scalar JSON + scalar URL + scalar DATE`, + ); + }); it('Should merge fields of both nodes', () => { const baseSchema = ` type Person{ @@ -136,6 +156,11 @@ describe('Merging GraphQL Schemas', () => { `; const t1 = mergeSDLs(baseSchema, mergingSchema); if (t1.__typename === 'error') throw new Error('Invalid parse'); + expect( + t1.nodes.every((n, i) => { + return i === t1.nodes.findIndex((t1n) => t1n.id === n.id); + }), + ).toBeTruthy(); expectTrimmedEqual( t1.sdl, `