Skip to content

Commit

Permalink
feat: make entity fields unique on database with @unique directive
Browse files Browse the repository at this point in the history
  • Loading branch information
metmirr committed Jun 30, 2020
1 parent 299c64c commit d740010
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 7 deletions.
7 changes: 7 additions & 0 deletions substrate-query-framework/cli/src/generate/field-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export function buildFieldContext(f: Field, entity: ObjectType): GeneratorContex
return {
...withFieldTypeGuardProps(f),
...withRequired(f),
...withUnique(f),
...withArrayCustomFieldConfig(f),
...withTsTypeAndDecorator(f),
...withDerivedNames(f, entity),
Expand Down Expand Up @@ -102,6 +103,12 @@ export function withDescription(f: Field): GeneratorContext {
};
}

export function withUnique(f: Field): GeneratorContext {
return {
unique: f.unique,
};
}

export function withTsTypeAndDecorator(f: Field): GeneratorContext {
const fieldType = f.columnType();
if (TYPE_FIELDS[fieldType]) {
Expand Down
2 changes: 2 additions & 0 deletions substrate-query-framework/cli/src/model/Field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export class Field {
isList: boolean;
// Description of the field will be shown in GrapqQL API
description?: string;
// Make field as a unique column on database
unique?: boolean;

constructor(name: string, type: string, nullable = true, isBuildinType = true, isList = false) {
this.name = name;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
import { GraphQLSchemaParser, Visitors, SchemaNode } from './SchemaParser';
import { WarthogModel, Field, ObjectType } from '../model';
import Debug from 'debug';
import { ENTITY_DIRECTIVE } from './constant';
import { ENTITY_DIRECTIVE, UNIQUE_DIRECTIVE } from './constant';
import { FTSDirective, FULL_TEXT_SEARCHABLE_DIRECTIVE } from './FTSDirective';

const debug = Debug('qnode-cli:model-generator');
Expand Down Expand Up @@ -78,6 +78,11 @@ export class WarthogModelBuilder {
return entityDirective ? true : false;
}

private isUnique(field: FieldDefinitionNode): boolean {
const entityDirective = field.directives?.find(d => d.name.value === UNIQUE_DIRECTIVE);
return entityDirective ? true : false;
}

/**
* Generate a new ObjectType from ObjectTypeDefinitionNode
* @param o ObjectTypeDefinitionNode
Expand Down Expand Up @@ -134,6 +139,7 @@ export class WarthogModelBuilder {
throw new Error(`Unrecognized type. ${JSON.stringify(typeNode, null, 2)}`);
}
field.description = fieldNode.description?.value;
field.unique = this.isUnique(fieldNode);
return field;
});
debug(`Read and parsed fields: ${JSON.stringify(fields, null, 2)}`);
Expand Down
6 changes: 4 additions & 2 deletions substrate-query-framework/cli/src/parse/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
*/
export const SCHEMA_DEFINITIONS_PREAMBLE = `
directive @entity on OBJECT | INTERFACE # Mark both object types and interfaces
directive @unique on FIELD_DEFINITION
scalar BigInt # Arbitrarily large integers
scalar BigDecimal # is used to represent arbitrary precision decimals
scalar Bytes # Byte array, represented as a hexadecimal string
type Query {
_dummy: String # empty queries are not allowed
}
`
`;

export const ENTITY_DIRECTIVE = 'entity'
export const ENTITY_DIRECTIVE = 'entity';
export const UNIQUE_DIRECTIVE = 'unique';
14 changes: 10 additions & 4 deletions substrate-query-framework/cli/src/templates/entities/model.ts.mst
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,21 @@ export {{#isInterface}}abstract{{/isInterface}} class {{className}}
{{/is.oto}}

{{#is.array}}
@CustomField({ db: { type: '{{dbType}}', array: true{{^required}}, nullable: true{{/required}} },
api: { type: '{{apiType}}',{{^required}}nullable: true,{{/required}}
{{#description}}description: `{{{description}}}`{{/description}} }})
@CustomField({
db: { type: '{{dbType}}', array: true,{{^required}}nullable: true,{{/required}} {{#unique}}unique: true,{{/unique}}},
api: { type: '{{apiType}}', {{^required}}nullable: true,{{/required}}
{{#description}}description: `{{{description}}}`{{/description}} }
})
{{camelName}}{{^required}}?{{/required}}{{#required}}!{{/required}}: {{tsType}}[];
{{/is.array}}

{{! TODO: add enums here }}
{{#is.scalar}}
@{{decorator}}({ {{^required}}nullable: true,{{/required}} {{#description}}description: `{{{description}}}`{{/description}} })
@{{decorator}}({
{{^required}}nullable: true,{{/required}}
{{#description}}description: `{{{description}}}`,{{/description}}
{{#unique}}unique: true,{{/unique}}
})
{{camelName}}{{^required}}?{{/required}}{{#required}}!{{/required}}: {{tsType}};
{{/is.scalar}}

Expand Down

0 comments on commit d740010

Please sign in to comment.