mirror of
https://github.com/cerc-io/watcher-ts
synced 2025-01-04 18:46:47 +00:00
Add CLI tool to compare watcher GQL responses (#494)
* Integrate gql response compare tool * Add README for compare-gql tool * Update readme * Update CLI output logs --------- Co-authored-by: neeraj <neeraj.rtly@gmail.com>
This commit is contained in:
parent
dab2d6d3e7
commit
ceb0a3de23
@ -54,3 +54,43 @@ A basic CLI to pass messages between peers using `stdin`/`stdout`
|
||||
* `enable-debug-info`: Whether to broadcast node's info over pubsub on request
|
||||
|
||||
* The process starts reading from `stdin` and outputs messages from others peers over the `/chat/1.0.0` protocol to `stdout`.
|
||||
|
||||
## compare-gql
|
||||
|
||||
A basic CLI to to fetch and compare watcher GQL response.
|
||||
|
||||
* Create a `config.yaml` file in the following format in `packages/cli`:
|
||||
|
||||
```yaml
|
||||
# Watcher URL
|
||||
url: ""
|
||||
|
||||
# Boolean to specify if it is a subgraph watcher
|
||||
isSubgraph: false
|
||||
|
||||
# File path for saving GQL result
|
||||
gqlResultFilepath: "./result.json"
|
||||
|
||||
# Optional parameter to override default GQL query
|
||||
graphqlQuery: ""
|
||||
```
|
||||
|
||||
* Run the following command to fetch and save first GQL response:
|
||||
|
||||
```
|
||||
yarn compare-gql --config config.yaml
|
||||
```
|
||||
|
||||
* On running CLI for the first time
|
||||
|
||||
```
|
||||
vulcanize:compare-gql Fetching response for the first time, re run CLI to compare with latest GQL response
|
||||
```
|
||||
|
||||
* Re run CLI after some time (average time taken for new block in Ethereum: `~12 seconds`)
|
||||
|
||||
```
|
||||
yarn compare-gql --config config.yaml
|
||||
```
|
||||
|
||||
* The diff for latest and previous GQL responses is shown
|
||||
|
12
packages/cli/config.yaml
Normal file
12
packages/cli/config.yaml
Normal file
@ -0,0 +1,12 @@
|
||||
# Watcher URL
|
||||
url: ""
|
||||
|
||||
# Boolean to specify if it is a subgraph watcher
|
||||
isSubgraph: false
|
||||
|
||||
# File path for saving GQL result
|
||||
gqlResultFilepath: "./result.json"
|
||||
|
||||
# Optional parameter to override default GQL query
|
||||
# Set GQL filepath containing query
|
||||
graphqlQuery: ""
|
34
packages/cli/graphql/azimuth-query.graphql
Normal file
34
packages/cli/graphql/azimuth-query.graphql
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
azimuthGetSyncStatus {
|
||||
latestProcessedBlockNumber
|
||||
latestIndexedBlockNumber
|
||||
}
|
||||
claimsGetSyncStatus {
|
||||
latestProcessedBlockNumber
|
||||
latestIndexedBlockNumber
|
||||
}
|
||||
censuresGetSyncStatus {
|
||||
latestProcessedBlockNumber
|
||||
latestIndexedBlockNumber
|
||||
}
|
||||
conditionalStarReleaseGetSyncStatus {
|
||||
latestProcessedBlockNumber
|
||||
latestIndexedBlockNumber
|
||||
}
|
||||
delegatedSendingGetSyncStatus {
|
||||
latestProcessedBlockNumber
|
||||
latestIndexedBlockNumber
|
||||
}
|
||||
eclipticGetSyncStatus {
|
||||
latestProcessedBlockNumber
|
||||
latestIndexedBlockNumber
|
||||
}
|
||||
linearStarReleaseGetSyncStatus {
|
||||
latestProcessedBlockNumber
|
||||
latestIndexedBlockNumber
|
||||
}
|
||||
pollsGetSyncStatus {
|
||||
latestProcessedBlockNumber
|
||||
latestIndexedBlockNumber
|
||||
}
|
||||
}
|
12
packages/cli/graphql/non-subgraph-query.graphql
Normal file
12
packages/cli/graphql/non-subgraph-query.graphql
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
getSyncStatus {
|
||||
initialIndexedBlockHash
|
||||
initialIndexedBlockNumber
|
||||
latestCanonicalBlockHash
|
||||
latestIndexedBlockHash
|
||||
latestCanonicalBlockNumber
|
||||
latestIndexedBlockNumber
|
||||
latestProcessedBlockHash
|
||||
latestProcessedBlockNumber
|
||||
}
|
||||
}
|
19
packages/cli/graphql/subgraph-query.graphql
Normal file
19
packages/cli/graphql/subgraph-query.graphql
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
getSyncStatus {
|
||||
initialIndexedBlockHash
|
||||
initialIndexedBlockNumber
|
||||
latestCanonicalBlockHash
|
||||
latestIndexedBlockHash
|
||||
latestCanonicalBlockNumber
|
||||
latestIndexedBlockNumber
|
||||
latestProcessedBlockHash
|
||||
latestProcessedBlockNumber
|
||||
}
|
||||
_meta {
|
||||
block {
|
||||
hash
|
||||
number
|
||||
timestamp
|
||||
}
|
||||
}
|
||||
}
|
@ -8,7 +8,8 @@
|
||||
"build": "yarn clean && tsc && yarn copy-assets",
|
||||
"clean": "rm -rf ./dist",
|
||||
"copy-assets": "copyfiles -u 1 src/**/*.gql dist/",
|
||||
"chat": "DEBUG='vulcanize:*, laconic:*' node dist/chat.js"
|
||||
"chat": "DEBUG='vulcanize:*, laconic:*' node dist/chat.js",
|
||||
"compare-gql": "DEBUG='vulcanize:*' node dist/compare-gql.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@apollo/client": "^3.7.1",
|
||||
@ -27,7 +28,11 @@
|
||||
"debug": "^4.3.1",
|
||||
"ethers": "^5.4.4",
|
||||
"express": "^4.18.2",
|
||||
"graphql": "^15.5.0",
|
||||
"graphql-request": "^6.1.0",
|
||||
"graphql-subscriptions": "^2.0.0",
|
||||
"js-yaml": "^4.0.0",
|
||||
"json-diff": "^0.5.4",
|
||||
"lodash": "^4.17.21",
|
||||
"pluralize": "^8.0.0",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
@ -36,6 +41,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "^4.17.14",
|
||||
"@types/js-yaml": "^4.0.3",
|
||||
"@types/json-diff": "^0.5.2",
|
||||
"@types/node": "16.11.7",
|
||||
"@types/pluralize": "^0.0.29",
|
||||
"@types/yargs": "^17.0.0",
|
||||
|
90
packages/cli/src/compare-gql.ts
Normal file
90
packages/cli/src/compare-gql.ts
Normal file
@ -0,0 +1,90 @@
|
||||
import { request } from 'graphql-request';
|
||||
import * as fs from 'fs';
|
||||
import jsonDiff from 'json-diff';
|
||||
import yargs from 'yargs';
|
||||
import { hideBin } from 'yargs/helpers';
|
||||
import path from 'path';
|
||||
import yaml from 'js-yaml';
|
||||
import debug from 'debug';
|
||||
|
||||
const SUBGRAPH_QUERY_FILEPATH = 'graphql/subgraph-query.graphql';
|
||||
const NON_SUBGRAPH_QUERY_FILEPATH = 'graphql/non-subgraph-query.graphql';
|
||||
|
||||
const log = debug('vulcanize:compare-gql');
|
||||
|
||||
function readFromJSONFile (filename: string): {[key: string]: any} | null {
|
||||
const fileContents = fs.readFileSync(filename, 'utf-8');
|
||||
|
||||
if (fileContents !== '') {
|
||||
return JSON.parse(fileContents);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function getQuery (isSubgraph: boolean, queryFilepath?: string): any {
|
||||
if (queryFilepath) {
|
||||
return fs.readFileSync(queryFilepath, 'utf-8');
|
||||
}
|
||||
|
||||
if (isSubgraph) {
|
||||
return fs.readFileSync(SUBGRAPH_QUERY_FILEPATH, 'utf-8');
|
||||
}
|
||||
|
||||
return fs.readFileSync(NON_SUBGRAPH_QUERY_FILEPATH, 'utf-8');
|
||||
}
|
||||
|
||||
async function main (): Promise<void> {
|
||||
const argv = await yargs(hideBin(process.argv))
|
||||
.option('config', {
|
||||
alias: 'c',
|
||||
demandOption: true,
|
||||
describe: 'Watcher config file path (yaml)',
|
||||
type: 'string'
|
||||
}).argv;
|
||||
|
||||
const configFilePath = path.resolve(argv.config);
|
||||
const inputConfig = yaml.load(fs.readFileSync(configFilePath, 'utf8')) as any;
|
||||
|
||||
log('Config:', inputConfig);
|
||||
|
||||
const isSubgraph = inputConfig.isSubgraph;
|
||||
const watcherUrl = inputConfig.url;
|
||||
const configFileDirectory = path.dirname(configFilePath);
|
||||
const gqlResultFilepath = path.resolve(configFileDirectory, inputConfig.gqlResultFilepath);
|
||||
const graphqlQueryFilepath = inputConfig.graphqlQuery ? path.resolve(configFileDirectory, inputConfig.graphqlQuery) : undefined;
|
||||
|
||||
if (!fs.existsSync(gqlResultFilepath)) {
|
||||
fs.writeFileSync(gqlResultFilepath, '', 'utf-8');
|
||||
}
|
||||
|
||||
const query = getQuery(isSubgraph, graphqlQueryFilepath);
|
||||
|
||||
let gqlResponse;
|
||||
|
||||
try {
|
||||
gqlResponse = await request(watcherUrl, query);
|
||||
} catch (err) {
|
||||
throw new Error('Error in GQL request: ' + (err as Error).message);
|
||||
}
|
||||
|
||||
const readOutputData = readFromJSONFile(gqlResultFilepath);
|
||||
|
||||
if (readOutputData !== null) {
|
||||
const diff = jsonDiff.diffString(readOutputData, gqlResponse);
|
||||
|
||||
if (diff !== '') {
|
||||
log('Diff detected', diff);
|
||||
} else {
|
||||
log('No diff detected, GQL response', gqlResponse);
|
||||
}
|
||||
} else {
|
||||
log('Fetching response for the first time, re run CLI to compare with latest GQL response');
|
||||
}
|
||||
|
||||
fs.writeFileSync(gqlResultFilepath, JSON.stringify(gqlResponse, null, 2));
|
||||
}
|
||||
|
||||
main().catch(err => {
|
||||
log(err);
|
||||
});
|
24
yarn.lock
24
yarn.lock
@ -1226,7 +1226,7 @@
|
||||
"@graphql-typed-document-node/core" "^3.1.1"
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@graphql-typed-document-node/core@^3.1.1":
|
||||
"@graphql-typed-document-node/core@^3.1.1", "@graphql-typed-document-node/core@^3.2.0":
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861"
|
||||
integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==
|
||||
@ -6512,6 +6512,13 @@ cross-fetch@^3.1.4:
|
||||
dependencies:
|
||||
node-fetch "2.6.7"
|
||||
|
||||
cross-fetch@^3.1.5:
|
||||
version "3.1.8"
|
||||
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82"
|
||||
integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==
|
||||
dependencies:
|
||||
node-fetch "^2.6.12"
|
||||
|
||||
cross-spawn@^6.0.5:
|
||||
version "6.0.5"
|
||||
resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz"
|
||||
@ -9021,6 +9028,14 @@ graphql-compose@^9.0.3:
|
||||
dependencies:
|
||||
graphql-type-json "0.3.2"
|
||||
|
||||
graphql-request@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-6.1.0.tgz#f4eb2107967af3c7a5907eb3131c671eac89be4f"
|
||||
integrity sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==
|
||||
dependencies:
|
||||
"@graphql-typed-document-node/core" "^3.2.0"
|
||||
cross-fetch "^3.1.5"
|
||||
|
||||
graphql-subscriptions@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/graphql-subscriptions/-/graphql-subscriptions-2.0.0.tgz"
|
||||
@ -12223,6 +12238,13 @@ node-fetch@^2.6.1:
|
||||
resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz"
|
||||
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
|
||||
|
||||
node-fetch@^2.6.12:
|
||||
version "2.7.0"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
|
||||
integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
|
||||
dependencies:
|
||||
whatwg-url "^5.0.0"
|
||||
|
||||
node-fetch@~1.7.1:
|
||||
version "1.7.3"
|
||||
resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz"
|
||||
|
Loading…
Reference in New Issue
Block a user