From 74cc9079f75272b643f76a56ccceec8779be6b09 Mon Sep 17 00:00:00 2001 From: tilacog Date: Wed, 6 Sep 2023 00:43:10 -0300 Subject: [PATCH] common: prevent mergeSelectionsets from mutating its input --- packages/indexer-common/package.json | 2 + .../src/__tests__/subgraph.test.ts | 37 ++++++++++++++++++- packages/indexer-common/src/utils.ts | 7 +++- 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/packages/indexer-common/package.json b/packages/indexer-common/package.json index 5fc472382..17d19c4af 100644 --- a/packages/indexer-common/package.json +++ b/packages/indexer-common/package.json @@ -25,6 +25,7 @@ "@graphprotocol/common-ts": "2.0.3", "@graphprotocol/cost-model": "0.1.16", "@thi.ng/heaps": "1.2.38", + "@types/lodash.clonedeep": "^4.5.7", "@types/lodash.intersection": "^4.4.7", "@types/lodash.xor": "^4.5.7", "@urql/core": "2.4.4", @@ -39,6 +40,7 @@ "graphql": "16.3.0", "graphql-tag": "2.12.6", "jayson": "3.6.6", + "lodash.clonedeep": "^4.5.0", "lodash.groupby": "^4.6.0", "lodash.intersection": "^4.4.0", "lodash.isequal": "^4.5.0", diff --git a/packages/indexer-common/src/__tests__/subgraph.test.ts b/packages/indexer-common/src/__tests__/subgraph.test.ts index 5db477f19..dd39e7123 100644 --- a/packages/indexer-common/src/__tests__/subgraph.test.ts +++ b/packages/indexer-common/src/__tests__/subgraph.test.ts @@ -1,4 +1,4 @@ -import { DocumentNode } from 'graphql' +import { DocumentNode, print } from 'graphql' import { SubgraphFreshnessChecker, LoggerInterface, @@ -7,6 +7,8 @@ import { } from '../subgraphs' import { QueryResult } from '../network-subgraph' import gql from 'graphql-tag' +import { mergeSelectionSets } from '../utils' +import { merge } from 'evt/lib/Evt.merge' /* eslint-disable @typescript-eslint/no-explicit-any */ export const mockProvider: ProviderInterface & any = { @@ -48,6 +50,39 @@ function mockQueryResult(blockNumber: number): QueryResult & { } } /* eslint-enable @typescript-eslint/no-explicit-any */ +const blockNumberQuery = gql` + { + _meta { + block { + number + } + } + } +` + +const expectedMergedQuery = gql` + query TestQuery { + foo { + id + } + _meta { + block { + number + } + } + } +` + +describe('mergeSelectionSets function', () => { + it('can append the block number to an existing query', () => { + let result: DocumentNode + // Repetition required to test `mergeSelectionSets` doesn't mutate its inputq + for (let i = 0; i < 3; i++) { + result = mergeSelectionSets(testSubgraphQuery, blockNumberQuery) + } + expect(print(result!)).toEqual(print(expectedMergedQuery)) + }) +}) describe('SubgraphFreshnessChecker', () => { beforeEach(jest.resetAllMocks) diff --git a/packages/indexer-common/src/utils.ts b/packages/indexer-common/src/utils.ts index b83bb9d2c..a486424a0 100644 --- a/packages/indexer-common/src/utils.ts +++ b/packages/indexer-common/src/utils.ts @@ -7,6 +7,7 @@ import { import { Logger, Metrics, timer } from '@graphprotocol/common-ts' import { indexerError, IndexerErrorCode } from './errors' import { DocumentNode, SelectionSetNode, Kind } from 'graphql' +import cloneDeep from 'lodash.clonedeep' export const parseBoolean = ( val: string | boolean | number | undefined | null, @@ -68,13 +69,15 @@ export function mergeSelectionSets( first: DocumentNode, second: DocumentNode, ): DocumentNode { - const firstSelectionSet = extractSelectionSet(first) + // Work on a copy to avoid mutating inupt + const copy = cloneDeep(first) + const firstSelectionSet = extractSelectionSet(copy) const secondSelectionSet = extractSelectionSet(second) firstSelectionSet.selections = [ ...firstSelectionSet.selections, ...secondSelectionSet.selections, ] - return first + return copy } function extractSelectionSet(document: DocumentNode): SelectionSetNode {