From 530422919273908c26551971beb182325b1f871c Mon Sep 17 00:00:00 2001 From: Dimitri POSTOLOV Date: Sat, 2 Dec 2023 00:38:09 +0100 Subject: [PATCH 1/3] yo --- .../__snapshots__/federation-subgraph.spec.md | 30 +++ .../__tests__/federation-subgraph.spec.ts | 22 ++ packages/plugin/package.json | 8 + .../plugin/src/rules/federation-subgraph.ts | 60 +++++ pnpm-lock.yaml | 208 +++++++++++++++++- scripts/create-rule.ts | 2 +- 6 files changed, 328 insertions(+), 2 deletions(-) create mode 100644 packages/plugin/__tests__/__snapshots__/federation-subgraph.spec.md create mode 100644 packages/plugin/__tests__/federation-subgraph.spec.ts create mode 100644 packages/plugin/src/rules/federation-subgraph.ts diff --git a/packages/plugin/__tests__/__snapshots__/federation-subgraph.spec.md b/packages/plugin/__tests__/__snapshots__/federation-subgraph.spec.md new file mode 100644 index 00000000000..a79bef85a7a --- /dev/null +++ b/packages/plugin/__tests__/__snapshots__/federation-subgraph.spec.md @@ -0,0 +1,30 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`federation-subgraph > invalid > should validate subgraph 1`] = ` +#### ⌨️ Code + + 1 | type Query { + 2 | t: T + 3 | } + 4 | + 5 | type T @key(fields: "f") { + 6 | f(x: Int): Int + 7 | } + +#### ❌ Error + + > 1 | type Query { + | ^^^^^^^^^^^^^^^^^^^^ + > 2 | t: T + | ^^^^^^^^^^^^^^ + > 3 | } + | ^^^^^^^^^^^^^^ + > 4 | + | ^^^^^^^^^^^^^^ + > 5 | type T @key(fields: "f") { + | ^^^^^^^^^^^^^^ + > 6 | f(x: Int): Int + | ^^^^^^^^^^^^^^ + > 7 | } + | ^^^^^^^^^^ On type "T", for @key(fields: "f"): field T.f cannot be included because it has arguments (fields with argument are not allowed in @key) +`; diff --git a/packages/plugin/__tests__/federation-subgraph.spec.ts b/packages/plugin/__tests__/federation-subgraph.spec.ts new file mode 100644 index 00000000000..59320cc0e4d --- /dev/null +++ b/packages/plugin/__tests__/federation-subgraph.spec.ts @@ -0,0 +1,22 @@ +import { rule } from '../src/rules/federation-subgraph'; +import { ruleTester } from './test-utils'; + +ruleTester.run('federation-subgraph', rule, { + valid: [], + invalid: [ + { + // https://github.com/apollographql/federation/blob/4ffe723395b4a054807b4f58181f166d76b57160/internals-js/src/__tests__/subgraphValidation.test.ts#L9 + name: 'should validate subgraph', + code: /* GraphQL */ ` + type Query { + t: T + } + + type T @key(fields: "f") { + f(x: Int): Int + } + `, + errors: 1, + }, + ], +}); diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 3dfb1fdfdd9..68b7c1e2440 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -39,9 +39,15 @@ "typecheck": "tsc --noEmit" }, "peerDependencies": { + "@apollo/federation-internals": "^2", "eslint": ">=8.44.0", "graphql": "^16" }, + "peerDependenciesMeta": { + "@apollo/federation-internals": { + "optional": true + } + }, "dependencies": { "@graphql-tools/code-file-loader": "^8.0.0", "@graphql-tools/graphql-tag-pluck": "^8.0.0", @@ -53,6 +59,7 @@ "lodash.lowercase": "^4.3.0" }, "devDependencies": { + "@apollo/federation-internals": "^2.6.1", "@theguild/eslint-rule-tester": "workspace:*", "@types/debug": "4.1.12", "@types/eslint": "8.44.8", @@ -61,6 +68,7 @@ "@types/json-schema": "7.0.15", "@types/lodash.lowercase": "4.3.9", "graphql": "16.8.1", + "graphql-tag": "^2.12.6", "json-schema-to-ts": "2.9.2" }, "publishConfig": { diff --git a/packages/plugin/src/rules/federation-subgraph.ts b/packages/plugin/src/rules/federation-subgraph.ts new file mode 100644 index 00000000000..96ffde19465 --- /dev/null +++ b/packages/plugin/src/rules/federation-subgraph.ts @@ -0,0 +1,60 @@ +import { + asFed2SubgraphDocument, + buildSchemaFromAST, + FederationBlueprint, + Subgraph, +} from '@apollo/federation-internals'; +import { GraphQLESLintRule } from '../types.js'; + +const RULE_ID = 'federation-subgraph'; + +export const rule: GraphQLESLintRule = { + meta: { + type: 'problem', + docs: { + category: 'Schema', + description: 'Enforce subgraph to be valid according Federation 2 spec.', + url: `https://the-guild.dev/graphql/eslint/rules/${RULE_ID}`, + // examples: [ + // { + // title: 'Incorrect', + // code: /* GraphQL */ ``, + // }, + // { + // title: 'Correct', + // code: /* GraphQL */ ``, + // }, + // ], + }, + schema: [], + }, + create(context) { + return { + Document(node) { + const withRootTypeRenaming = true; + + const buildOptions = { + blueprint: new FederationBlueprint(withRootTypeRenaming), + validate: false, + }; + const doc = asFed2SubgraphDocument(node.rawNode()); + + const subgraphSchema = buildSchemaFromAST(doc, buildOptions); + + const name = 'graphql-eslint-subgraph'; + + const subgraph = new Subgraph(name, `http://${name}`, subgraphSchema); + + try { + subgraph.validate(); + } catch (error) { + context.report({ + node, + // Remove `[graphql-eslint-subgraph] ` suffix in error message + message: (error as Error).message.slice(name.length + '[] '.length), + }); + } + }, + }; + }, +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e69162e8a8d..c0a926d9e4d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -268,6 +268,12 @@ importers: specifier: ^4.3.0 version: 4.3.0 devDependencies: + '@apollo/composition': + specifier: ^2.6.1 + version: 2.6.1(graphql@16.8.1) + '@apollo/federation-internals': + specifier: ^2.6.1 + version: 2.6.1(graphql@16.8.1) '@theguild/eslint-rule-tester': specifier: workspace:* version: link:../rule-tester @@ -292,6 +298,9 @@ importers: graphql: specifier: 16.8.1 version: 16.8.1 + graphql-tag: + specifier: ^2.12.6 + version: 2.12.6(graphql@16.8.1) json-schema-to-ts: specifier: 2.9.2 version: 2.9.2 @@ -561,6 +570,43 @@ packages: '@jridgewell/gen-mapping': 0.3.3 '@jridgewell/trace-mapping': 0.3.19 + /@apollo/composition@2.6.1(graphql@16.8.1): + resolution: {integrity: sha512-jj4Y/r15EX5N/e4VtU/ftxNQI8NyYDc2IS3Tq2/pUH57sM0HyCqJzwc0tVsptEAhwgYVzuFgiRXlchMjwer/Zg==} + engines: {node: '>=14.15.0'} + peerDependencies: + graphql: ^16.5.0 + dependencies: + '@apollo/federation-internals': 2.6.1(graphql@16.8.1) + '@apollo/query-graphs': 2.6.1(graphql@16.8.1) + graphql: 16.8.1 + dev: true + + /@apollo/federation-internals@2.6.1(graphql@16.8.1): + resolution: {integrity: sha512-6nsLtspVvJ3+41JDhhJkJIvLKHTZSZempPQjiaoehZJ9SU/8oPZQ9FomF8XGbgEZMKmnc+4/YweonQURusDW5w==} + engines: {node: '>=14.15.0'} + peerDependencies: + graphql: ^16.5.0 + dependencies: + '@types/uuid': 9.0.7 + chalk: 4.1.2 + graphql: 16.8.1 + js-levenshtein: 1.1.6 + uuid: 9.0.0 + dev: true + + /@apollo/query-graphs@2.6.1(graphql@16.8.1): + resolution: {integrity: sha512-7D7Rxcmy1/bQ7ZkTFocy+MbG1rhCEyrhCZj8WW5zgwMp0qfr/PCQxB1/fhU4pxdugXWZsgPlNi5o7O8iqeYKxQ==} + engines: {node: '>=14.15.0'} + peerDependencies: + graphql: ^16.5.0 + dependencies: + '@apollo/federation-internals': 2.6.1(graphql@16.8.1) + deep-equal: 2.2.3 + graphql: 16.8.1 + ts-graphviz: 1.8.1 + uuid: 9.0.0 + dev: true + /@ardatan/sync-fetch@0.0.1: resolution: {integrity: sha512-xhlTqH0m31mnsG0tIP4ETgfSB6gXDaYYsUWTrlUV93fFQPI9dd8hE0Ot6MHLCtqgB32hwJAC3YZMWlXZw7AleA==} engines: {node: '>=14'} @@ -3153,6 +3199,10 @@ packages: resolution: {integrity: sha512-MFETx3tbTjE7Uk6vvnWINA/1iJ7LuMdO4fcq8UfF0pRbj01aGLduVvQcRyswuACJdpnHgg8E3rQLhaRdNEJS0w==} dev: false + /@types/uuid@9.0.7: + resolution: {integrity: sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==} + dev: true + /@types/ws@8.5.5: resolution: {integrity: sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==} dependencies: @@ -3920,6 +3970,14 @@ packages: get-intrinsic: 1.2.1 dev: true + /call-bind@1.0.5: + resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==} + dependencies: + function-bind: 1.1.2 + get-intrinsic: 1.2.2 + set-function-length: 1.1.1 + dev: true + /callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -4751,6 +4809,30 @@ packages: type-detect: 4.0.8 dev: true + /deep-equal@2.2.3: + resolution: {integrity: sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + call-bind: 1.0.5 + es-get-iterator: 1.1.3 + get-intrinsic: 1.2.2 + is-arguments: 1.1.1 + is-array-buffer: 3.0.2 + is-date-object: 1.0.5 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.2 + isarray: 2.0.5 + object-is: 1.1.5 + object-keys: 1.1.1 + object.assign: 4.1.4 + regexp.prototype.flags: 1.5.1 + side-channel: 1.0.4 + which-boxed-primitive: 1.0.2 + which-collection: 1.0.1 + which-typed-array: 1.1.13 + dev: true + /deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -4783,6 +4865,15 @@ packages: clone: 1.0.4 dev: true + /define-data-property@1.1.1: + resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.2 + gopd: 1.0.1 + has-property-descriptors: 1.0.0 + dev: true + /define-lazy-prop@3.0.0: resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} engines: {node: '>=12'} @@ -4994,6 +5085,20 @@ packages: which-typed-array: 1.1.11 dev: true + /es-get-iterator@1.1.3: + resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + has-symbols: 1.0.3 + is-arguments: 1.1.1 + is-map: 2.0.2 + is-set: 2.0.2 + is-string: 1.0.7 + isarray: 2.0.5 + stop-iteration-iterator: 1.0.0 + dev: true + /es-iterator-helpers@1.0.14: resolution: {integrity: sha512-JgtVnwiuoRuzLvqelrvN3Xu7H9bu2ap/kQ2CrM62iidP8SKuD99rWU3CJy++s7IVL2qb/AjXPGR/E7i9ngd/Cw==} dependencies: @@ -5987,6 +6092,10 @@ packages: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} dev: true + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + dev: true + /function.prototype.name@1.1.6: resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} engines: {node: '>= 0.4'} @@ -6028,6 +6137,15 @@ packages: has-symbols: 1.0.3 dev: true + /get-intrinsic@1.2.2: + resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==} + dependencies: + function-bind: 1.1.2 + has-proto: 1.0.1 + has-symbols: 1.0.3 + hasown: 2.0.0 + dev: true + /get-nonce@1.0.1: resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} engines: {node: '>=6'} @@ -6220,6 +6338,16 @@ packages: graphql: 16.8.1 dev: false + /graphql-tag@2.12.6(graphql@16.8.1): + resolution: {integrity: sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==} + engines: {node: '>=10'} + peerDependencies: + graphql: ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + graphql: 16.8.1 + tslib: 2.6.2 + dev: true + /graphql-ws@5.14.0(graphql@16.8.1): resolution: {integrity: sha512-itrUTQZP/TgswR4GSSYuwWUzrE/w5GhbwM2GX3ic2U7aw33jgEsayfIlvaj7/GcIvZgNMzsPTrE5hqPuFUiE5g==} engines: {node: '>=10'} @@ -6317,6 +6445,13 @@ packages: type-fest: 1.4.0 dev: false + /hasown@2.0.0: + resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + dev: true + /hast-util-from-dom@5.0.0: resolution: {integrity: sha512-d6235voAp/XR3Hh5uy7aGLbM3S4KamdW0WEgOaU1YoewnuYw4HXb5eRtv9g65m/RFGEfUY1Mw4UqCc5Y8L4Stg==} dependencies: @@ -6631,6 +6766,14 @@ packages: is-alphabetical: 2.0.1 is-decimal: 2.0.1 + /is-arguments@1.1.1: + resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + has-tostringtag: 1.0.0 + dev: true + /is-array-buffer@3.0.2: resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} dependencies: @@ -6966,6 +7109,11 @@ packages: engines: {node: '>=10'} dev: true + /js-levenshtein@1.1.6: + resolution: {integrity: sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==} + engines: {node: '>=0.10.0'} + dev: true + /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -8643,6 +8791,14 @@ packages: resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} dev: true + /object-is@1.1.5: + resolution: {integrity: sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.0 + dev: true + /object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} @@ -9713,6 +9869,15 @@ packages: functions-have-names: 1.2.3 dev: true + /regexp.prototype.flags@1.5.1: + resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.0 + set-function-name: 2.0.1 + dev: true + /regjsparser@0.10.0: resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} hasBin: true @@ -10051,6 +10216,25 @@ packages: resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} dev: true + /set-function-length@1.1.1: + resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + get-intrinsic: 1.2.2 + gopd: 1.0.1 + has-property-descriptors: 1.0.0 + dev: true + + /set-function-name@2.0.1: + resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.0 + dev: true + /sh-syntax@0.4.1: resolution: {integrity: sha512-MW/ZsCYTu11EIYYTSZcfAgMFszAodCmQVB27XssHoIN6L4EG0KSA3h32x8whaSOKuYBX5wz9EybfnPBUFQMCKA==} engines: {node: '>=16.0.0'} @@ -10221,6 +10405,13 @@ packages: resolution: {integrity: sha512-f9aPhy8fYBuMN+sNfakZV18U39PbalgjXG3lLB9WkaYTxijru61wb57V9wxxNthXM5Sd88ETBWi29qLAsHO52Q==} dev: true + /stop-iteration-iterator@1.0.0: + resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} + engines: {node: '>= 0.4'} + dependencies: + internal-slot: 1.0.5 + dev: true + /stream-transform@2.1.3: resolution: {integrity: sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ==} dependencies: @@ -10720,6 +10911,11 @@ packages: engines: {node: '>=6.10'} dev: false + /ts-graphviz@1.8.1: + resolution: {integrity: sha512-54/fe5iu0Jb6X0pmDmzsA2UHLfyHjUEUwfHtZcEOR0fZ6Myf+dFoO6eNsyL8CBDMJ9u7WWEewduVaiaXlvjSVw==} + engines: {node: '>=14.16'} + dev: true + /ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} dev: true @@ -11233,7 +11429,6 @@ packages: /uuid@9.0.0: resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==} hasBin: true - dev: false /uvu@0.5.6: resolution: {integrity: sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==} @@ -11629,6 +11824,17 @@ packages: has-tostringtag: 1.0.0 dev: true + /which-typed-array@1.1.13: + resolution: {integrity: sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.5 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.0 + dev: true + /which@1.3.1: resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} hasBin: true diff --git a/scripts/create-rule.ts b/scripts/create-rule.ts index f99addf74bf..fb08b2d0187 100644 --- a/scripts/create-rule.ts +++ b/scripts/create-rule.ts @@ -115,7 +115,7 @@ function useSchema(code: string): { code: string; parserOptions: Omit Date: Sat, 2 Dec 2023 00:42:37 +0100 Subject: [PATCH 2/3] aa --- packages/plugin/src/rules/federation-subgraph.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/plugin/src/rules/federation-subgraph.ts b/packages/plugin/src/rules/federation-subgraph.ts index 96ffde19465..2857865f156 100644 --- a/packages/plugin/src/rules/federation-subgraph.ts +++ b/packages/plugin/src/rules/federation-subgraph.ts @@ -31,14 +31,16 @@ export const rule: GraphQLESLintRule = { create(context) { return { Document(node) { - const withRootTypeRenaming = true; + // https://github.com/apollographql/federation/blob/4ffe723395b4a054807b4f58181f166d76b57160/internals-js/src/__tests__/testUtils.ts#L16C45-L16C67 + const doc = asFed2SubgraphDocument(node.rawNode()); + const withRootTypeRenaming = true; const buildOptions = { blueprint: new FederationBlueprint(withRootTypeRenaming), validate: false, }; - const doc = asFed2SubgraphDocument(node.rawNode()); + // https://github.com/apollographql/federation/blob/4ffe723395b4a054807b4f58181f166d76b57160/internals-js/src/federation.ts#L1329 const subgraphSchema = buildSchemaFromAST(doc, buildOptions); const name = 'graphql-eslint-subgraph'; From fc49d5e4c38d7ed06e4ab39d8d082242e4afd9fe Mon Sep 17 00:00:00 2001 From: Dimitri POSTOLOV Date: Sat, 2 Dec 2023 00:43:35 +0100 Subject: [PATCH 3/3] aa --- packages/plugin/src/estree-converter/types.ts | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/packages/plugin/src/estree-converter/types.ts b/packages/plugin/src/estree-converter/types.ts index fe3f728ba75..d8512139006 100644 --- a/packages/plugin/src/estree-converter/types.ts +++ b/packages/plugin/src/estree-converter/types.ts @@ -79,34 +79,34 @@ type NodeWithType = type ParentNode = T extends DocumentNode ? AST.Program : T extends DefinitionNode - ? DocumentNode - : T extends EnumValueDefinitionNode - ? EnumTypeDefinitionNode | EnumTypeExtensionNode - : T extends InputValueDefinitionNode - ? - | DirectiveDefinitionNode - | FieldDefinitionNode - | InputObjectTypeDefinitionNode - | InputObjectTypeExtensionNode - : T extends FieldDefinitionNode - ? - | InterfaceTypeDefinitionNode - | InterfaceTypeExtensionNode - | ObjectTypeDefinitionNode - | ObjectTypeExtensionNode - : T extends SelectionSetNode - ? ExecutableDefinitionNode | FieldNode | InlineFragmentNode - : T extends SelectionNode - ? SelectionSetNode - : T extends TypeNode - ? NodeWithType - : T extends NameNode - ? NodeWithName - : T extends DirectiveNode - ? InputObjectTypeDefinitionNode | ObjectTypeDefinitionNode - : T extends VariableNode - ? VariableDefinitionNode - : unknown; // Explicitly show error to add new ternary with parent nodes + ? DocumentNode + : T extends EnumValueDefinitionNode + ? EnumTypeDefinitionNode | EnumTypeExtensionNode + : T extends InputValueDefinitionNode + ? + | DirectiveDefinitionNode + | FieldDefinitionNode + | InputObjectTypeDefinitionNode + | InputObjectTypeExtensionNode + : T extends FieldDefinitionNode + ? + | InterfaceTypeDefinitionNode + | InterfaceTypeExtensionNode + | ObjectTypeDefinitionNode + | ObjectTypeExtensionNode + : T extends SelectionSetNode + ? ExecutableDefinitionNode | FieldNode | InlineFragmentNode + : T extends SelectionNode + ? SelectionSetNode + : T extends TypeNode + ? NodeWithType + : T extends NameNode + ? NodeWithName + : T extends DirectiveNode + ? InputObjectTypeDefinitionNode | ObjectTypeDefinitionNode + : T extends VariableNode + ? VariableDefinitionNode + : unknown; // Explicitly show error to add new ternary with parent nodes type Node = // Remove readonly for friendly editor popup @@ -130,7 +130,7 @@ export type GraphQLESTreeNode = : GraphQLESTreeNode[K], W>; } : // If Program node => add `parent: null` field - T extends AST.Program - ? T & { parent: null } - : // Return value as is - T; + T extends AST.Program + ? T & { parent: null } + : // Return value as is + T;