mirror of
https://github.com/cerc-io/watcher-ts
synced 2025-01-23 11:39:05 +00:00
Handle subgraph entities field name conflicts and enum types in codegen (#86)
* Handle entity field conflicts * Handle enum type fields in subgraph entities
This commit is contained in:
parent
3ed4ab95af
commit
4b1b0e0ed6
@ -241,7 +241,7 @@ export class Entity {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Add subgraph entity specific columns.
|
// Add subgraph entity specific columns.
|
||||||
entityObject = this._addSubgraphColumns(entityObject, def);
|
entityObject = this._addSubgraphColumns(subgraphTypeDefs, entityObject, def);
|
||||||
|
|
||||||
// Add bigintTransformer column option if required.
|
// Add bigintTransformer column option if required.
|
||||||
this._addBigIntTransformerOption(entityObject);
|
this._addBigIntTransformerOption(entityObject);
|
||||||
@ -308,18 +308,24 @@ export class Entity {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_addSubgraphColumns (entityObject: any, def: any): any {
|
_addSubgraphColumns (subgraphTypeDefs: any, entityObject: any, def: any): any {
|
||||||
def.fields.forEach((field: any) => {
|
def.fields.forEach((field: any) => {
|
||||||
const name = field.name.value;
|
let name = field.name.value;
|
||||||
|
|
||||||
// Filter out already added columns.
|
// Column id is already added.
|
||||||
if (['id', 'blockHash', 'blockNumber'].includes(name)) {
|
if (name === 'id') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle column with existing name.
|
||||||
|
if (['blockHash', 'blockNumber'].includes(name)) {
|
||||||
|
name = `_${name}`;
|
||||||
|
}
|
||||||
|
|
||||||
const columnObject: any = {
|
const columnObject: any = {
|
||||||
name,
|
name,
|
||||||
columnOptions: []
|
columnOptions: [],
|
||||||
|
columnType: 'Column'
|
||||||
};
|
};
|
||||||
|
|
||||||
const { typeName, array, nullable } = this._getFieldType(field.type);
|
const { typeName, array, nullable } = this._getFieldType(field.type);
|
||||||
@ -345,29 +351,58 @@ export class Entity {
|
|||||||
|
|
||||||
const pgType = getPgForTs(tsType);
|
const pgType = getPgForTs(tsType);
|
||||||
|
|
||||||
// If basic type: create a column. If unknown: create a relation.
|
// If basic type: create a column.
|
||||||
if (pgType) {
|
if (pgType) {
|
||||||
columnObject.columnType = 'Column';
|
|
||||||
columnObject.pgType = pgType;
|
columnObject.pgType = pgType;
|
||||||
} else {
|
} else {
|
||||||
columnObject.columnType = 'ManyToOne';
|
if (subgraphTypeDefs.some((typeDef: any) => typeDef.kind === 'EnumTypeDefinition' && typeDef.name.value === typeName)) {
|
||||||
columnObject.lhs = '()';
|
// Create enum type column.
|
||||||
columnObject.rhs = tsType;
|
|
||||||
|
|
||||||
entityObject.imports[0].toImport.add('ManyToOne');
|
const entityImport = entityObject.imports.find(({ from }: any) => from === '../types');
|
||||||
|
|
||||||
// Check if type import already added.
|
if (!entityImport) {
|
||||||
const importObject = entityObject.imports.find((element: any) => {
|
entityObject.imports.push(
|
||||||
return element.from === `./${tsType}`;
|
{
|
||||||
});
|
toImport: new Set([typeName]),
|
||||||
|
from: '../types'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
entityImport.toImport.add(typeName);
|
||||||
|
}
|
||||||
|
|
||||||
if (!importObject) {
|
columnObject.columnOptions.push(
|
||||||
entityObject.imports.push(
|
|
||||||
{
|
{
|
||||||
toImport: new Set([tsType]),
|
option: 'type',
|
||||||
from: `./${tsType}`
|
value: "'enum'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
option: 'enum',
|
||||||
|
value: typeName
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
// Create a relation.
|
||||||
|
|
||||||
|
columnObject.columnType = 'ManyToOne';
|
||||||
|
columnObject.lhs = '()';
|
||||||
|
columnObject.rhs = tsType;
|
||||||
|
|
||||||
|
entityObject.imports[0].toImport.add('ManyToOne');
|
||||||
|
|
||||||
|
// Check if type import already added.
|
||||||
|
const importObject = entityObject.imports.find((element: any) => {
|
||||||
|
return element.from === `./${tsType}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!importObject) {
|
||||||
|
entityObject.imports.push(
|
||||||
|
{
|
||||||
|
toImport: new Set([tsType]),
|
||||||
|
from: `./${tsType}`
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,6 +263,11 @@ function generateWatcher (contractStrings: string[], visitor: Visitor, argv: any
|
|||||||
: process.stdout;
|
: process.stdout;
|
||||||
exportFill(outStream);
|
exportFill(outStream);
|
||||||
|
|
||||||
|
outStream = outputDir
|
||||||
|
? fs.createWriteStream(path.join(outputDir, 'src/types.ts'))
|
||||||
|
: process.stdout;
|
||||||
|
visitor.exportTypes(outStream);
|
||||||
|
|
||||||
let rcOutStream, ignoreOutStream;
|
let rcOutStream, ignoreOutStream;
|
||||||
|
|
||||||
if (outputDir) {
|
if (outputDir) {
|
||||||
|
11
packages/codegen/src/templates/types-template.handlebars
Normal file
11
packages/codegen/src/templates/types-template.handlebars
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2021 Vulcanize, Inc.
|
||||||
|
//
|
||||||
|
|
||||||
|
{{#each types as | type |}}
|
||||||
|
export enum {{type.name}} {
|
||||||
|
{{#each type.values as | value |}}
|
||||||
|
{{value}} = '{{value}}',
|
||||||
|
{{/each}}
|
||||||
|
}
|
||||||
|
{{/each}}
|
50
packages/codegen/src/types.ts
Normal file
50
packages/codegen/src/types.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2021 Vulcanize, Inc.
|
||||||
|
//
|
||||||
|
|
||||||
|
import fs from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
import Handlebars from 'handlebars';
|
||||||
|
import { Writable } from 'stream';
|
||||||
|
|
||||||
|
const TEMPLATE_FILE = './templates/types-template.handlebars';
|
||||||
|
|
||||||
|
export class Types {
|
||||||
|
_types: Array<any>;
|
||||||
|
_templateString: string;
|
||||||
|
|
||||||
|
constructor () {
|
||||||
|
this._types = [];
|
||||||
|
this._templateString = fs.readFileSync(path.resolve(__dirname, TEMPLATE_FILE)).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the generated types files from a template to a stream.
|
||||||
|
* @param outStream A writable output stream to write the types file to.
|
||||||
|
*/
|
||||||
|
exportTypes (outStream: Writable): void {
|
||||||
|
const template = Handlebars.compile(this._templateString);
|
||||||
|
const obj = {
|
||||||
|
types: this._types
|
||||||
|
};
|
||||||
|
const database = template(obj);
|
||||||
|
outStream.write(database);
|
||||||
|
}
|
||||||
|
|
||||||
|
addSubgraphTypes (subgraphSchemaDocument: any): void {
|
||||||
|
const subgraphTypeDefs = subgraphSchemaDocument.definitions;
|
||||||
|
|
||||||
|
subgraphTypeDefs.forEach((def: any) => {
|
||||||
|
if (def.kind !== 'EnumTypeDefinition') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const typeObject: any = {
|
||||||
|
name: def.name.value,
|
||||||
|
values: def.values.map((value: any) => value.name.value)
|
||||||
|
};
|
||||||
|
|
||||||
|
this._types.push(typeObject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -14,6 +14,7 @@ import { Reset } from './reset';
|
|||||||
import { Param } from './utils/types';
|
import { Param } from './utils/types';
|
||||||
import { MODE_ETH_CALL, MODE_STORAGE } from './utils/constants';
|
import { MODE_ETH_CALL, MODE_STORAGE } from './utils/constants';
|
||||||
import { parseSubgraphSchema } from './utils/subgraph';
|
import { parseSubgraphSchema } from './utils/subgraph';
|
||||||
|
import { Types } from './types';
|
||||||
|
|
||||||
export class Visitor {
|
export class Visitor {
|
||||||
_schema: Schema;
|
_schema: Schema;
|
||||||
@ -23,6 +24,7 @@ export class Visitor {
|
|||||||
_database: Database;
|
_database: Database;
|
||||||
_client: Client;
|
_client: Client;
|
||||||
_reset: Reset;
|
_reset: Reset;
|
||||||
|
_types: Types;
|
||||||
|
|
||||||
constructor () {
|
constructor () {
|
||||||
this._schema = new Schema();
|
this._schema = new Schema();
|
||||||
@ -32,6 +34,7 @@ export class Visitor {
|
|||||||
this._database = new Database();
|
this._database = new Database();
|
||||||
this._client = new Client();
|
this._client = new Client();
|
||||||
this._reset = new Reset();
|
this._reset = new Reset();
|
||||||
|
this._types = new Types();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -131,6 +134,7 @@ export class Visitor {
|
|||||||
const subgraphSchemaDocument = parseSubgraphSchema(subgraphPath);
|
const subgraphSchemaDocument = parseSubgraphSchema(subgraphPath);
|
||||||
|
|
||||||
this._schema.addSubgraphSchema(subgraphSchemaDocument);
|
this._schema.addSubgraphSchema(subgraphSchemaDocument);
|
||||||
|
this._types.addSubgraphTypes(subgraphSchemaDocument);
|
||||||
this._entity.addSubgraphEntities(subgraphSchemaDocument);
|
this._entity.addSubgraphEntities(subgraphSchemaDocument);
|
||||||
this._resolvers.addSubgraphResolvers(subgraphSchemaDocument);
|
this._resolvers.addSubgraphResolvers(subgraphSchemaDocument);
|
||||||
this._reset.addSubgraphEntities(subgraphSchemaDocument);
|
this._reset.addSubgraphEntities(subgraphSchemaDocument);
|
||||||
@ -197,4 +201,12 @@ export class Visitor {
|
|||||||
exportReset (resetOutStream: Writable, resetJQOutStream: Writable, resetStateOutStream: Writable): void {
|
exportReset (resetOutStream: Writable, resetJQOutStream: Writable, resetStateOutStream: Writable): void {
|
||||||
this._reset.exportReset(resetOutStream, resetJQOutStream, resetStateOutStream);
|
this._reset.exportReset(resetOutStream, resetJQOutStream, resetStateOutStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the types file generated from a template to a stream.
|
||||||
|
* @param outStream A writable output stream to write the database file to.
|
||||||
|
*/
|
||||||
|
exportTypes (outStream: Writable): void {
|
||||||
|
this._types.exportTypes(outStream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user