Skip to content

Commit

Permalink
feat(hydra-cli): export all model files from a single module (#348)
Browse files Browse the repository at this point in the history
* feat(hydra-cli): export all model files from a single module

affects: @dzlzv/hydra-cli

all generated model classes are now exported from a separate 'model' module

* fix(hydra-cli): add model to the module to the compiled package

affects: @dzlzv/hydra-cli
  • Loading branch information
dzhelezov authored Apr 8, 2021
1 parent aae6745 commit 47b526a
Show file tree
Hide file tree
Showing 16 changed files with 219 additions and 44 deletions.
2 changes: 2 additions & 0 deletions packages/hydra-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,15 @@
"@oclif/plugin-help": "^2",
"@oclif/plugin-plugins": "^1.9.4",
"@types/chalk": "^2.2.0",
"@types/copyfiles": "^2.4.0",
"@types/fs-extra": "^8.1.0",
"@types/graphql": "^14.5.0",
"@types/listr": "^0.14.2",
"@types/mustache": "^4.0.1",
"@types/node": "^12.12.30",
"chalk": "^4.1.0",
"cli-ux": "^5.4.9",
"copyfiles": "^2.4.1",
"execa": "^4.0.3",
"fs-extra": "^9.0.0",
"glob": "^7.1.6",
Expand Down
21 changes: 12 additions & 9 deletions packages/hydra-cli/src/generate/AbstractRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,17 @@ export abstract class AbstractRenderer {
abstract transform(): GeneratorContext

render(mustacheTeplate: string): string {
const mustacheContext = this.transform()
debug(`Rendering with context: ${JSON.stringify(mustacheContext, null, 2)}`)

const rendered = Mustache.render(mustacheTeplate, mustacheContext)
return prettier.format(rendered, {
parser: 'typescript',
singleQuote: true,
printWidth: 120,
})
return render(mustacheTeplate, this.transform())
}
}

export function render(template: string, context: GeneratorContext): string {
debug(`Rendering with context: ${JSON.stringify(context, null, 2)}`)

const rendered = Mustache.render(template, context)
return prettier.format(rendered, {
parser: 'typescript',
singleQuote: true,
printWidth: 120,
})
}
6 changes: 3 additions & 3 deletions packages/hydra-cli/src/generate/ModelRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export class ModelRenderer extends AbstractRenderer {
this.objType.interfaces !== undefined
) {
return {
interfaces: [utils.withNames(this.objType.interfaces[0].name)],
interfaces: [utils.withNames(this.objType.interfaces[0])],
}
}
return {}
Expand All @@ -46,7 +46,7 @@ export class ModelRenderer extends AbstractRenderer {
const subclasses: GeneratorContext[] = []
this.model
.getSubclasses(this.objType.name)
.map((o) => subclasses.push(utils.withNames(o.name)))
.map((o) => subclasses.push(utils.withNames(o)))
return {
subclasses,
}
Expand Down Expand Up @@ -169,7 +169,7 @@ export class ModelRenderer extends AbstractRenderer {
...this.withDescription(),
...this.withImportProps(),
...this.withFieldResolvers(),
...utils.withNames(this.objType.name),
...utils.withNames(this.objType),
}
}
}
36 changes: 36 additions & 0 deletions packages/hydra-cli/src/generate/SourcesGenerator.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as fs from 'fs-extra'
import * as path from 'path'
import copyfiles from 'copyfiles'
import { getTemplatePath, createFile, createDir } from '../utils/utils'

import Debug from 'debug'
Expand All @@ -10,6 +11,8 @@ import { EnumRenderer } from './EnumRenderer'
import { kebabCase } from './utils'
import { ConfigProvider } from './ConfigProvider'
import { VariantsRenderer } from './VariantsRenderer'
import { render } from './AbstractRenderer'
import { indexContext } from './model-index-context'

const debug = Debug('qnode-cli:sources-generator')

Expand All @@ -29,17 +32,20 @@ export interface GeneratorContext {
export class SourcesGenerator {
readonly config: ConfigProvider
readonly model: WarthogModel
dryRun = false

constructor(model: WarthogModel) {
this.config = new ConfigProvider()
this.model = model
this.dryRun = process.env.DRY_RUN === 'true'
}

generate(): void {
this.generateEnums()
this.generateVariants()
this.generateModels()
this.generateQueries()
this.generateModelIndex()
}

generateModels(): void {
Expand Down Expand Up @@ -141,6 +147,36 @@ export class SourcesGenerator {
this.writeFile(path.join(enumsDir, `enums.ts`), rendered)
}

generateModelIndex(): string {
const rendered = render(
this.readTemplate('entities/model-all.ts.mst'),
indexContext(this.model)
)
if (!this.dryRun) {
// create top-level /model folder
const modelDir = path.join(this.config.config.get('ROOT_FOLDER'), 'model')
createDir(modelDir, false, true)

// write to /modul/index.ts
this.writeFile(path.join(modelDir, 'index.ts'), rendered)
// copy all model files there
copyfiles(
[
'src/**/*.model.*',
'src/**/enums/enums.ts',
'src/**/variants/variants.ts',
modelDir,
],
2,
() => {
// do nothing
}
)
}
// return the result to simply testing
return rendered
}

/**
*
* @param template relative path to a template from the templates folder, e.g. 'db-helper.mst'
Expand Down
9 changes: 2 additions & 7 deletions packages/hydra-cli/src/generate/enum-context.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
import { GraphQLEnumType } from 'graphql'
import { GeneratorContext, ENUMS_FOLDER } from './SourcesGenerator'
import { withNames } from './utils'

export function withEnum(enumType: GraphQLEnumType): GeneratorContext {
return {
...withName(enumType),
...withNames(enumType),
...withValues(enumType),
}
}

export function withName(enumType: GraphQLEnumType): GeneratorContext {
return {
name: enumType.name,
}
}

export function withValues(enumType: GraphQLEnumType): GeneratorContext {
const values: GeneratorContext[] = []
enumType
Expand Down
44 changes: 44 additions & 0 deletions packages/hydra-cli/src/generate/model-index-context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import Debug from 'debug'
import { ObjectType, WarthogModel } from '../model'
import { GeneratorContext } from './SourcesGenerator'
import { withNames } from './utils'

const debug = Debug('qnode-cli:model-index-context')

export function withModelNames(
model: WarthogModel
): { modelClasses: GeneratorContext[] } {
const entities = [...model.interfaces, ...model.entities]
return {
modelClasses: entities.map((e) => withNames(e)),
}
}

export function withEnumNames(
model: WarthogModel
): { enums: GeneratorContext[] } {
return { enums: model.enums.map((en) => withNames(en)) }
}

export function withUnionNames(
model: WarthogModel
): { unions: GeneratorContext[] } {
return { unions: model.unions.map((u) => withNames(u)) }
}

export function withVariantNames(
model: WarthogModel
): { variants: GeneratorContext[] } {
return { variants: model.variants.map((v: ObjectType) => withNames(v)) }
}

export function indexContext(model: WarthogModel): GeneratorContext {
const out = {
...withModelNames(model),
...withEnumNames(model),
...withUnionNames(model),
...withVariantNames(model),
}
debug(`Index context: ${JSON.stringify(out, null, 2)}`)
return out
}
10 changes: 2 additions & 8 deletions packages/hydra-cli/src/generate/union-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,14 @@ import { withNames } from './utils'

export function withUnionType(unionType: UnionType): GeneratorContext {
return {
...withName(unionType),
...withNames(unionType),
...withTypes(unionType),
}
}

export function withName(unionType: UnionType): GeneratorContext {
return {
name: unionType.name,
}
}

export function withTypes(unionType: UnionType): GeneratorContext {
const types: GeneratorContext[] = []
unionType.types.map((t) => types.push(withNames(t.name)))
unionType.types.map((t) => types.push(withNames(t)))
return {
types,
}
Expand Down
12 changes: 11 additions & 1 deletion packages/hydra-cli/src/generate/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export function names(name: string): { [key: string]: string } {
}
}

export function withNames(name: string): GeneratorContext {
export function withNames({ name }: { name: string }): GeneratorContext {
return {
name,
...names(name),
Expand Down Expand Up @@ -84,3 +84,13 @@ export function generateResolverReturnType(
): string {
return `Promise<${type}${isList ? '[]' : ''} | null>`
}

/**
* replace all whitespaces and carriage returns
*
* @param s
* @returns the same string with all whitecharacters removed
*/
export function compact(s: string): string {
return s.replace(/\s/g, '')
}
10 changes: 0 additions & 10 deletions packages/hydra-cli/src/index.ts

This file was deleted.

20 changes: 20 additions & 0 deletions packages/hydra-cli/src/templates/entities/model-all.ts.mst
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{{#modelClasses}}
import { {{className}} } from './{{kebabName}}/{{kebabName}}.model';
export { {{className}} };
{{/modelClasses}}


{{#enums}}
import { {{name}} } from './enums/enums';
export { {{name}} }; {{! we need to re-export enums for type-GraphQL to resolve types correctly }}
{{/enums}}

{{#variants}}
import { {{name}} } from './variants/variants.model'
export { {{name}} };
{{/variants}}

{{#unions}}
import { {{name}} } from './variants/variants.model'
export { {{name}} };
{{/unions}}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@
"esModuleInterop": true,
"declaration": true
},
"include": ["src/**/*", "db/**/*"],
"include": ["src/**/*", "db/**/*", "model/**/*"],
"exclude": ["node_modules/**/*", "generated/**/*", "tools/**/*"]
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { DatabaseManager } from '@dzlzv/hydra-db-utils'
import { Transfer } from '../generated/graphql-server/src/modules/transfer/transfer.model'
import { BlockTimestamp } from '../generated/graphql-server/src/modules/block-timestamp/block-timestamp.model'
import { Transfer, BlockTimestamp } from '../generated/graphql-server/model'

// run 'NODE_URL=<RPC_ENDPOINT> EVENTS=<comma separated list of events> yarn codegen:mappings-types'
// to genenerate typescript classes for events, such as Balances.TransferEvent
Expand Down
77 changes: 77 additions & 0 deletions packages/hydra-cli/test/helpers/model-index-context.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { expect } from 'chai'
import { SourcesGenerator } from '../../src/generate/SourcesGenerator'
import { fromStringSchema } from './model'
import { compact as c } from '../../src/generate/utils'

describe('model index render', () => {
before(() => {
// bypass the annoying warthog checks...
process.env.WARTHOG_APP_HOST = 'test'
process.env.WARTHOG_APP_PORT = 'test'
process.env.WARTHOG_DB_HOST = 'test'
process.env.DRY_RUN = 'true'
})

it('should render index file', () => {
const model = fromStringSchema(`
enum Network {
BABYLON
ALEXANDRIA
ROME
}
union MyUnion = Var1 | Var2
type Var1 @variant {
f1: BigInt!
}
type Var2 @variant {
f2: String!
}
type MyEntity @entity {
f3: String!
}
interface MyInterface @entity {
f4: String!
}
`)

const rendered = new SourcesGenerator(model).generateModelIndex()

expect(c(rendered)).to.include(
c(`import { MyUnion } from './variants/variants.model`),
'should import union types'
)
expect(c(rendered)).to.include(
c(`import { Var1 } from './variants/variants.model`),
'should import variant'
)
expect(c(rendered)).to.include(
c(`import { Network } from './enums/enums`),
'should import enums'
)
expect(c(rendered)).to.include(
c(`export { Network }`),
'should export enums'
)
expect(c(rendered)).to.include(
c(`import { MyEntity } from './my-entity/my-entity.model`),
'should import entities'
)
expect(c(rendered)).to.include(
c(`export { MyEntity } `),
'should export entities'
)
expect(c(rendered)).to.include(
c(`import { MyInterface } from './my-interface/my-interface.model`),
'should import interfaces'
)
expect(c(rendered)).to.include(
c(`export { MyInterface } `),
'should export interfaces'
)
})
})
3 changes: 1 addition & 2 deletions packages/sample/mappings/mappings.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { DatabaseManager } from '@dzlzv/hydra-db-utils'
import { Transfer } from '../generated/graphql-server/src/modules/transfer/transfer.model'
import { BlockTimestamp } from '../generated/graphql-server/src/modules/block-timestamp/block-timestamp.model'
import { Transfer, BlockTimestamp } from '../generated/graphql-server/model'

// run 'NODE_URL=<RPC_ENDPOINT> EVENTS=<comma separated list of events> yarn codegen:mappings-types'
// to genenerate typescript classes for events, such as Balances.TransferEvent
Expand Down
Loading

0 comments on commit 47b526a

Please sign in to comment.