mirror of
https://github.com/cerc-io/watcher-ts
synced 2025-08-05 13:38:40 +00:00
Changes in codegen to remove lint warnings in generated watcher (#368)
* Codegen declare resultDataTypes before queries in gql schema * Update codegen templates to remove lint warnings * Add flag to overwrite existing watcher in target directory * Codegen set up pre-commit lint * Codegen generate .npmrc * Codegen refactor code for pre-commit lint * Update codegen templates with eslint rule exceptions * Fix missing comma in codegen template * Set husky preCommit file permission to executable --------- Co-authored-by: Dhruv Srivastava <dhruvdhs.ds@gmail.com>
This commit is contained in:
parent
49d67899be
commit
096a0081e6
1
packages/codegen/src/assets/.npmrc
Normal file
1
packages/codegen/src/assets/.npmrc
Normal file
@ -0,0 +1 @@
|
|||||||
|
@cerc-io:registry=https://git.vdb.to/api/packages/cerc-io/npm/
|
4
packages/codegen/src/assets/pre-commit
Normal file
4
packages/codegen/src/assets/pre-commit
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
. "$(dirname "$0")/_/husky.sh"
|
||||||
|
|
||||||
|
yarn lint
|
@ -57,6 +57,13 @@ const main = async (): Promise<void> => {
|
|||||||
describe: 'Continue generating watcher if unhandled types encountered',
|
describe: 'Continue generating watcher if unhandled types encountered',
|
||||||
type: 'boolean'
|
type: 'boolean'
|
||||||
})
|
})
|
||||||
|
.option('overwrite', {
|
||||||
|
alias: 'o',
|
||||||
|
demandOption: false,
|
||||||
|
default: false,
|
||||||
|
describe: 'Overwrite previously generated watcher',
|
||||||
|
type: 'boolean'
|
||||||
|
})
|
||||||
.argv;
|
.argv;
|
||||||
|
|
||||||
const config = getConfig(path.resolve(argv['config-file']));
|
const config = getConfig(path.resolve(argv['config-file']));
|
||||||
@ -108,11 +115,13 @@ const main = async (): Promise<void> => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const continueOnError = argv['continue-on-error'];
|
const continueOnError = argv['continue-on-error'];
|
||||||
|
const overwriteExisting = argv.overwrite;
|
||||||
|
|
||||||
const visitor = new Visitor(continueOnError);
|
const visitor = new Visitor(continueOnError);
|
||||||
|
|
||||||
parseAndVisit(visitor, contracts, config.mode);
|
parseAndVisit(visitor, contracts, config.mode);
|
||||||
|
|
||||||
generateWatcher(visitor, contracts, config);
|
generateWatcher(visitor, contracts, config, overwriteExisting);
|
||||||
};
|
};
|
||||||
|
|
||||||
function parseAndVisit (visitor: Visitor, contracts: any[], mode: string) {
|
function parseAndVisit (visitor: Visitor, contracts: any[], mode: string) {
|
||||||
@ -148,12 +157,23 @@ function parseAndVisit (visitor: Visitor, contracts: any[], mode: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateWatcher (visitor: Visitor, contracts: any[], config: any) {
|
function generateWatcher (visitor: Visitor, contracts: any[], config: any, overWriteExisting = false) {
|
||||||
// Prepare directory structure for the watcher.
|
// Prepare directory structure for the watcher.
|
||||||
let outputDir = '';
|
let outputDir = '';
|
||||||
|
|
||||||
if (config.outputFolder) {
|
if (config.outputFolder) {
|
||||||
outputDir = path.resolve(config.outputFolder);
|
outputDir = path.resolve(config.outputFolder);
|
||||||
if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir, { recursive: true });
|
|
||||||
|
if (fs.existsSync(outputDir)) {
|
||||||
|
if (!overWriteExisting) {
|
||||||
|
throw new Error('Watcher already exists in output folder. Run with --overwrite flag to overwrite');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fs.mkdirSync(outputDir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
const huskyDir = path.join(outputDir, '.husky');
|
||||||
|
if (!fs.existsSync(huskyDir)) fs.mkdirSync(huskyDir);
|
||||||
|
|
||||||
const environmentsFolder = path.join(outputDir, 'environments');
|
const environmentsFolder = path.join(outputDir, 'environments');
|
||||||
if (!fs.existsSync(environmentsFolder)) fs.mkdirSync(environmentsFolder);
|
if (!fs.existsSync(environmentsFolder)) fs.mkdirSync(environmentsFolder);
|
||||||
@ -247,6 +267,23 @@ function generateWatcher (visitor: Visitor, contracts: any[], config: any) {
|
|||||||
: process.stdout;
|
: process.stdout;
|
||||||
writeFileToStream(path.join(ASSET_DIR, '.gitignore'), outStream);
|
writeFileToStream(path.join(ASSET_DIR, '.gitignore'), outStream);
|
||||||
|
|
||||||
|
outStream = outputDir
|
||||||
|
? fs.createWriteStream(path.join(outputDir, '.npmrc'))
|
||||||
|
: process.stdout;
|
||||||
|
writeFileToStream(path.join(ASSET_DIR, '.npmrc'), outStream);
|
||||||
|
|
||||||
|
const huskyPreCommitFilePath = path.join(outputDir, '.husky/pre-commit');
|
||||||
|
|
||||||
|
outStream = outputDir
|
||||||
|
? fs.createWriteStream(huskyPreCommitFilePath)
|
||||||
|
: process.stdout;
|
||||||
|
writeFileToStream(path.join(ASSET_DIR, 'pre-commit'), outStream);
|
||||||
|
|
||||||
|
if (fs.existsSync(huskyPreCommitFilePath)) {
|
||||||
|
// Set file permission to executable
|
||||||
|
fs.chmodSync(huskyPreCommitFilePath, '775');
|
||||||
|
}
|
||||||
|
|
||||||
outStream = outputDir
|
outStream = outputDir
|
||||||
? fs.createWriteStream(path.join(outputDir, 'src/job-runner.ts'))
|
? fs.createWriteStream(path.join(outputDir, 'src/job-runner.ts'))
|
||||||
: process.stdout;
|
: process.stdout;
|
||||||
|
@ -22,11 +22,15 @@ export class Indexer {
|
|||||||
_events: Array<any>;
|
_events: Array<any>;
|
||||||
_subgraphEntities: Array<any>;
|
_subgraphEntities: Array<any>;
|
||||||
_templateString: string;
|
_templateString: string;
|
||||||
|
_hasStateVariableElementaryType: boolean;
|
||||||
|
_hasStateVariableMappingType: boolean;
|
||||||
|
|
||||||
constructor () {
|
constructor () {
|
||||||
this._queries = [];
|
this._queries = [];
|
||||||
this._events = [];
|
this._events = [];
|
||||||
this._subgraphEntities = [];
|
this._subgraphEntities = [];
|
||||||
|
this._hasStateVariableElementaryType = false;
|
||||||
|
this._hasStateVariableMappingType = false;
|
||||||
this._templateString = fs.readFileSync(path.resolve(__dirname, TEMPLATE_FILE)).toString();
|
this._templateString = fs.readFileSync(path.resolve(__dirname, TEMPLATE_FILE)).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,6 +96,15 @@ export class Indexer {
|
|||||||
|
|
||||||
if (stateVariableType) {
|
if (stateVariableType) {
|
||||||
queryObject.stateVariableType = stateVariableType;
|
queryObject.stateVariableType = stateVariableType;
|
||||||
|
|
||||||
|
switch (stateVariableType) {
|
||||||
|
case 'ElementaryTypeName':
|
||||||
|
this._hasStateVariableElementaryType = true;
|
||||||
|
break;
|
||||||
|
case 'Mapping':
|
||||||
|
this._hasStateVariableMappingType = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this._queries.push(queryObject);
|
this._queries.push(queryObject);
|
||||||
@ -173,6 +186,8 @@ export class Indexer {
|
|||||||
contracts,
|
contracts,
|
||||||
queries: this._queries,
|
queries: this._queries,
|
||||||
subgraphEntities: this._subgraphEntities,
|
subgraphEntities: this._subgraphEntities,
|
||||||
|
hasStateVariableElementaryType: this._hasStateVariableElementaryType,
|
||||||
|
hasStateVariableMappingType: this._hasStateVariableMappingType,
|
||||||
constants: {
|
constants: {
|
||||||
MODE_ETH_CALL,
|
MODE_ETH_CALL,
|
||||||
MODE_STORAGE
|
MODE_STORAGE
|
||||||
|
@ -257,7 +257,12 @@ export class Schema {
|
|||||||
value: (isArray) ? `[${value}]!` : value,
|
value: (isArray) ? `[${value}]!` : value,
|
||||||
proof: () => this._composer.getOTC('Proof')
|
proof: () => this._composer.getOTC('Proof')
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Using this to declare result types before queries
|
||||||
|
this._composer.addSchemaMustHaveType(typeComposer);
|
||||||
|
|
||||||
return typeComposer;
|
return typeComposer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ export const SUBGRAPH_ENTITIES = new Set([
|
|||||||
{{~/each}}]);
|
{{~/each}}]);
|
||||||
{{/if}}
|
{{/if}}
|
||||||
export const ENTITIES = [
|
export const ENTITIES = [
|
||||||
{{~#each queries as | query |}}{{~#if @index }}, {{/if}}{{query.entityName}}{{/each}}
|
{{~#each queries as | query |}}{{query.entityName}}{{#unless @last}}, {{/unless}}{{/each}}{{#if (subgraphPath)}}, {{/if}}
|
||||||
{{~#if (subgraphPath)}}...SUBGRAPH_ENTITIES{{/if}}];
|
{{~#if (subgraphPath)}}...SUBGRAPH_ENTITIES{{/if}}];
|
||||||
{{#if (subgraphPath)}}
|
{{#if (subgraphPath)}}
|
||||||
// Map: Entity to suitable query type.
|
// Map: Entity to suitable query type.
|
||||||
|
@ -4,7 +4,13 @@
|
|||||||
|
|
||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
|
|
||||||
import { updateStateForMappingType, updateStateForElementaryType, ResultEvent } from '@cerc-io/util';
|
import {
|
||||||
|
ResultEvent,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
updateStateForMappingType,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
updateStateForElementaryType
|
||||||
|
} from '@cerc-io/util';
|
||||||
|
|
||||||
import { Indexer } from './indexer';
|
import { Indexer } from './indexer';
|
||||||
|
|
||||||
|
@ -3,9 +3,11 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
|
import { DeepPartial, FindConditions, FindManyOptions{{#if (subgraphPath)}}, ObjectLiteral{{/if}} } from 'typeorm';
|
||||||
import debug from 'debug';
|
import debug from 'debug';
|
||||||
import { DeepPartial, FindConditions, FindManyOptions, ObjectLiteral } from 'typeorm';
|
{{#if queries}}
|
||||||
import JSONbig from 'json-bigint';
|
import JSONbig from 'json-bigint';
|
||||||
|
{{/if}}
|
||||||
import { ethers } from 'ethers';
|
import { ethers } from 'ethers';
|
||||||
{{#if (subgraphPath)}}
|
{{#if (subgraphPath)}}
|
||||||
import { SelectionNode } from 'graphql';
|
import { SelectionNode } from 'graphql';
|
||||||
@ -23,8 +25,12 @@ import {
|
|||||||
JobQueue,
|
JobQueue,
|
||||||
Where,
|
Where,
|
||||||
QueryOptions,
|
QueryOptions,
|
||||||
|
{{#if hasStateVariableElementaryType}}
|
||||||
updateStateForElementaryType,
|
updateStateForElementaryType,
|
||||||
|
{{/if}}
|
||||||
|
{{#if hasStateVariableMappingType}}
|
||||||
updateStateForMappingType,
|
updateStateForMappingType,
|
||||||
|
{{/if}}
|
||||||
{{#if (subgraphPath)}}
|
{{#if (subgraphPath)}}
|
||||||
BlockHeight,
|
BlockHeight,
|
||||||
updateSubgraphState,
|
updateSubgraphState,
|
||||||
@ -53,15 +59,21 @@ import { SyncStatus } from './entity/SyncStatus';
|
|||||||
import { StateSyncStatus } from './entity/StateSyncStatus';
|
import { StateSyncStatus } from './entity/StateSyncStatus';
|
||||||
import { BlockProgress } from './entity/BlockProgress';
|
import { BlockProgress } from './entity/BlockProgress';
|
||||||
import { State } from './entity/State';
|
import { State } from './entity/State';
|
||||||
|
{{#if (subgraphPath)}}
|
||||||
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
{{#each subgraphEntities as | subgraphEntity |}}
|
{{#each subgraphEntities as | subgraphEntity |}}
|
||||||
import { {{subgraphEntity.className}} } from './entity/{{subgraphEntity.className}}';
|
import { {{subgraphEntity.className}} } from './entity/{{subgraphEntity.className}}';
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{#if (subgraphPath)}}
|
/* eslint-enable @typescript-eslint/no-unused-vars */
|
||||||
|
|
||||||
import { FrothyEntity } from './entity/FrothyEntity';
|
import { FrothyEntity } from './entity/FrothyEntity';
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
const log = debug('vulcanize:indexer');
|
const log = debug('vulcanize:indexer');
|
||||||
|
{{#if queries}}
|
||||||
const JSONbigNative = JSONbig({ useNativeBigInt: true });
|
const JSONbigNative = JSONbig({ useNativeBigInt: true });
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
{{#each contracts as | contract |}}
|
{{#each contracts as | contract |}}
|
||||||
const KIND_{{capitalize contract.contractName}} = '{{contract.contractKind}}';
|
const KIND_{{capitalize contract.contractName}} = '{{contract.contractKind}}';
|
||||||
@ -178,12 +190,12 @@ export class Indexer implements IndexerInterface {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
{{/unless}}
|
|
||||||
log('{{query.name}}: db miss, fetching from upstream server');
|
|
||||||
|
|
||||||
const { block: { number } } = await this._ethClient.getBlockByHash(blockHash);
|
const { block: { number } } = await this._ethClient.getBlockByHash(blockHash);
|
||||||
const blockNumber = ethers.BigNumber.from(number).toNumber();
|
const blockNumber = ethers.BigNumber.from(number).toNumber();
|
||||||
|
|
||||||
|
{{/unless}}
|
||||||
|
log('{{query.name}}: db miss, fetching from upstream server');
|
||||||
|
|
||||||
{{#if (compare query.mode @root.constants.MODE_ETH_CALL)}}
|
{{#if (compare query.mode @root.constants.MODE_ETH_CALL)}}
|
||||||
const abi = this._abiMap.get(KIND_{{capitalize query.contract}});
|
const abi = this._abiMap.get(KIND_{{capitalize query.contract}});
|
||||||
assert(abi);
|
assert(abi);
|
||||||
@ -279,7 +291,7 @@ export class Indexer implements IndexerInterface {
|
|||||||
return createStateCheckpoint(this, contractAddress, blockHash);
|
return createStateCheckpoint(this, contractAddress, blockHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
async processCanonicalBlock (blockHash: string, blockNumber: number): Promise<void> {
|
async processCanonicalBlock (blockHash: string{{~#if (subgraphPath)}}, blockNumber: number{{/if}}): Promise<void> {
|
||||||
console.time('time:indexer#processCanonicalBlock-finalize_auto_diffs');
|
console.time('time:indexer#processCanonicalBlock-finalize_auto_diffs');
|
||||||
// Finalize staged diff blocks if any.
|
// Finalize staged diff blocks if any.
|
||||||
await this._baseIndexer.finalizeDiffStaged(blockHash);
|
await this._baseIndexer.finalizeDiffStaged(blockHash);
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
"lint": "eslint --max-warnings=0 .",
|
"lint": "eslint --max-warnings=0 .",
|
||||||
"build": "yarn clean && tsc && yarn copy-assets",
|
"build": "yarn clean && tsc && yarn copy-assets",
|
||||||
"clean": "rm -rf ./dist",
|
"clean": "rm -rf ./dist",
|
||||||
|
"prepare": "husky install",
|
||||||
"copy-assets": "copyfiles -u 1 src/**/*.gql dist/",
|
"copy-assets": "copyfiles -u 1 src/**/*.gql dist/",
|
||||||
"server": "DEBUG=vulcanize:* YARN_CHILD_PROCESS=true node --enable-source-maps dist/server.js",
|
"server": "DEBUG=vulcanize:* YARN_CHILD_PROCESS=true node --enable-source-maps dist/server.js",
|
||||||
"server:dev": "DEBUG=vulcanize:* YARN_CHILD_PROCESS=true ts-node src/server.ts",
|
"server:dev": "DEBUG=vulcanize:* YARN_CHILD_PROCESS=true ts-node src/server.ts",
|
||||||
@ -72,6 +73,7 @@
|
|||||||
"eslint-plugin-node": "^11.1.0",
|
"eslint-plugin-node": "^11.1.0",
|
||||||
"eslint-plugin-promise": "^5.1.0",
|
"eslint-plugin-promise": "^5.1.0",
|
||||||
"eslint-plugin-standard": "^5.0.0",
|
"eslint-plugin-standard": "^5.0.0",
|
||||||
|
"husky": "^7.0.2",
|
||||||
"ts-node": "^10.2.1",
|
"ts-node": "^10.2.1",
|
||||||
"typescript": "^5.0.2",
|
"typescript": "^5.0.2",
|
||||||
"copyfiles": "^2.4.1"
|
"copyfiles": "^2.4.1"
|
||||||
|
@ -6,18 +6,26 @@ import assert from 'assert';
|
|||||||
import BigInt from 'apollo-type-bigint';
|
import BigInt from 'apollo-type-bigint';
|
||||||
import debug from 'debug';
|
import debug from 'debug';
|
||||||
import Decimal from 'decimal.js';
|
import Decimal from 'decimal.js';
|
||||||
import { GraphQLResolveInfo, GraphQLScalarType } from 'graphql';
|
import {
|
||||||
|
GraphQLScalarType,
|
||||||
|
GraphQLResolveInfo
|
||||||
|
} from 'graphql';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
{{#if queries}}
|
||||||
ValueResult,
|
ValueResult,
|
||||||
BlockHeight,
|
{{/if}}
|
||||||
gqlTotalQueryCount,
|
gqlTotalQueryCount,
|
||||||
gqlQueryCount,
|
gqlQueryCount,
|
||||||
jsonBigIntStringReplacer,
|
|
||||||
getResultState,
|
getResultState,
|
||||||
setGQLCacheHints,
|
|
||||||
IndexerInterface,
|
IndexerInterface,
|
||||||
EventWatcher
|
{{#if (subgraphPath)}}
|
||||||
|
BlockHeight,
|
||||||
|
jsonBigIntStringReplacer,
|
||||||
|
{{/if}}
|
||||||
|
EventWatcher,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
setGQLCacheHints
|
||||||
} from '@cerc-io/util';
|
} from '@cerc-io/util';
|
||||||
|
|
||||||
import { Indexer } from './indexer';
|
import { Indexer } from './indexer';
|
||||||
@ -33,6 +41,7 @@ const log = debug('vulcanize:resolver');
|
|||||||
export const createResolvers = async (indexerArg: IndexerInterface, eventWatcher: EventWatcher): Promise<any> => {
|
export const createResolvers = async (indexerArg: IndexerInterface, eventWatcher: EventWatcher): Promise<any> => {
|
||||||
const indexer = indexerArg as Indexer;
|
const indexer = indexerArg as Indexer;
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
const gqlCacheConfig = indexer.serverConfig.gqlCache;
|
const gqlCacheConfig = indexer.serverConfig.gqlCache;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -81,7 +90,9 @@ export const createResolvers = async (indexerArg: IndexerInterface, eventWatcher
|
|||||||
{ blockHash, contractAddress
|
{ blockHash, contractAddress
|
||||||
{{~#each this.params}}, {{this.name~}} {{/each}} }: { blockHash: string, contractAddress: string
|
{{~#each this.params}}, {{this.name~}} {{/each}} }: { blockHash: string, contractAddress: string
|
||||||
{{~#each this.params}}, {{this.name}}: {{this.type~}} {{/each}} },
|
{{~#each this.params}}, {{this.name}}: {{this.type~}} {{/each}} },
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
__: any,
|
__: any,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
info: GraphQLResolveInfo
|
info: GraphQLResolveInfo
|
||||||
): Promise<ValueResult> => {
|
): Promise<ValueResult> => {
|
||||||
log('{{this.name}}', blockHash, contractAddress
|
log('{{this.name}}', blockHash, contractAddress
|
||||||
|
Loading…
Reference in New Issue
Block a user