Skip to content

Commit

Permalink
feat!: add graphql class decorators (#58)
Browse files Browse the repository at this point in the history
* feat: add graphql class decorators

* fix: linting, prettier

* feat: add enum support

* fix: linting, prettier

* feat: new ts types

* fix: lint for naming convention
  • Loading branch information
AnguIar authored Apr 27, 2021
1 parent 6b659d5 commit 24429af
Show file tree
Hide file tree
Showing 13 changed files with 252 additions and 20 deletions.
50 changes: 50 additions & 0 deletions src/models/common/decorators/property/classGraphql.decorator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import 'reflect-metadata';
import { getTsTypesMapping } from '../../../layerMetadata/decorators/property/tsTypes.decorator';
import { IPropGraphQLMapping } from '../../interfaces/propGraphQLMapping.interface';
import { getGraphQLMapping } from './graphql.decorator';

const graphQLMetadataKey = Symbol('graphqlclassmapping');
type KeyValueDict = Record<string, unknown>;
const target = {};

export interface IGraphQLClassMapping {
name: string;
fields: IPropGraphQLMapping[];
}

export function graphqlClass(): ClassDecorator {
// eslint-disable-next-line @typescript-eslint/ban-types
return <TFunction extends Function>(graphqlmapping: TFunction) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
const classInstance = new (graphqlmapping as any)();
const classData: IGraphQLClassMapping = {
fields: getGraphQLMappings(classInstance),
name: graphqlmapping.name,
};

const classDataList = getGraphQLClassMapping() ?? [];
classDataList.push(classData);
Reflect.defineMetadata(graphQLMetadataKey, classDataList, target);
return graphqlmapping;
};
}

export function getGraphQLClassMapping(): IGraphQLClassMapping[] | undefined {
return Reflect.getMetadata(graphQLMetadataKey, target) as IGraphQLClassMapping[];
}

export function getGraphQLMappings(object: KeyValueDict): IPropGraphQLMapping[] {
const ret = [];
for (const prop in object) {
const graphQLMap = getGraphQLMapping(object, prop);
const tsTypesMap = getTsTypesMapping(object, prop);
if (graphQLMap && tsTypesMap) {
ret.push({
prop: prop,
...graphQLMap,
...tsTypesMap,
});
}
}
return ret;
}
16 changes: 16 additions & 0 deletions src/models/common/decorators/property/graphql.decorator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import 'reflect-metadata';

const graphQLMetadataKey = Symbol('graphqlmapping');

export interface IGraphQLMapping {
nullable?: boolean;
}

export function graphql(graphqlmapping?: IGraphQLMapping): PropertyDecorator {
const defaultMapping: IGraphQLMapping = { nullable: false };
return Reflect.metadata(graphQLMetadataKey, graphqlmapping ?? defaultMapping);
}

export function getGraphQLMapping<T>(target: T, propertyKey: string): IGraphQLMapping | undefined {
return Reflect.getMetadata(graphQLMetadataKey, target, propertyKey) as IGraphQLMapping;
}
6 changes: 6 additions & 0 deletions src/models/common/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export * from './decorators/property/graphql.decorator';
export * from './decorators/property/classGraphql.decorator';
export * from './interfaces/ormCatalog.interface';
export * from './interfaces/propCatalogDBMapping.interface';
export * from './interfaces/propGraphQLMapping.interface';
export * from '../layerMetadata/link';
6 changes: 0 additions & 6 deletions src/models/common/interfaces/link.interface.ts

This file was deleted.

6 changes: 6 additions & 0 deletions src/models/common/interfaces/propGraphQLMapping.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { IGraphQLMapping } from '../decorators/property/graphql.decorator';
import { ITsTypesMapping } from '../../layerMetadata/decorators/property/tsTypes.decorator';

export interface IPropGraphQLMapping extends IGraphQLMapping, ITsTypesMapping {
prop: string;
}
1 change: 1 addition & 0 deletions src/models/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './common/index';
export * from './layerMetadata/index';
export * from './discreteIngestion/index';
export * from './layerMetadata/pycswLayerCatalogRecord';
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'reflect-metadata';
import { TsTypes } from './tsTypes.decorator';
import { IDescribeTsType } from './tsTypes.decorator';

const catalogDbMetadataKey = Symbol('catalogdbmapping');

Expand All @@ -15,7 +15,7 @@ export interface IColumnProps {
}

export interface IFieldProps {
overrideType?: TsTypes;
overrideType?: IDescribeTsType;
}

export interface ICatalogDBMapping {
Expand Down
56 changes: 48 additions & 8 deletions src/models/layerMetadata/decorators/property/tsTypes.decorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,58 @@ import 'reflect-metadata';

const tsTypesMetadataKey = Symbol('catalogdbmapping');

export enum TsTypes {
STRING = 'string',
BOOLEAN = 'boolean',
DATE = 'Date',
NUMBER = 'number',
export enum PropertiesTypes {
PRIMITIVE = 'primitive',
ENUM = 'enum',
CLASS = 'class',
ARRAY = 'array',
OBJECT = 'object',
LINK = 'Link',
LINKS = 'Link[]',
}
export interface IDescribeTsType {
value: string;
type: PropertiesTypes;
importFromPackage?: string;
}

/* eslint-disable @typescript-eslint/naming-convention */
export const TsTypes: Record<string, IDescribeTsType> = {
STRING: {
value: 'string',
type: PropertiesTypes.PRIMITIVE,
},
BOOLEAN: {
value: 'boolean',
type: PropertiesTypes.PRIMITIVE,
},
DATE: {
value: 'Date',
type: PropertiesTypes.PRIMITIVE,
},
NUMBER: {
value: 'number',
type: PropertiesTypes.PRIMITIVE,
},
OBJECT: {
value: 'object',
type: PropertiesTypes.OBJECT,
},
LINK: {
value: 'Link',
type: PropertiesTypes.CLASS,
},
LINKS: {
value: 'Link',
type: PropertiesTypes.ARRAY,
},
SENSORTYPE: {
value: 'SensorType',
type: PropertiesTypes.ENUM,
importFromPackage: '@map-colonies/mc-model-types',
},
};
/* eslint-enable @typescript-eslint/naming-convention */
export interface ITsTypesMapping {
mappingType: TsTypes;
mappingType: IDescribeTsType;
}

export function tsTypes(tsTypesMapping: ITsTypesMapping): PropertyDecorator {
Expand Down
2 changes: 1 addition & 1 deletion src/models/layerMetadata/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export * from './layerMetadata';
export * from './layerMetadata-StatusFields';

export { IShpMapping, ShapeFileType } from './decorators/property/shp.decorator';
export { TsTypes } from './decorators/property/tsTypes.decorator';
export { TsTypes, IDescribeTsType, PropertiesTypes } from './decorators/property/tsTypes.decorator';
export { IPYCSWMapping } from './decorators/property/csw.decorator';
export { IColumnProps } from './decorators/property/catalogDB.decorator';
export { IOrmCatalog } from '../common/interfaces/ormCatalog.interface';
39 changes: 38 additions & 1 deletion src/models/layerMetadata/layerMetadata.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { GeoJSON } from 'geojson';
import { IPropCatalogDBMapping } from '../common/interfaces/propCatalogDBMapping.interface';
import { graphql } from '../common/decorators/property/graphql.decorator';
import { getPyCSWMapping, IPYCSWMapping, pycsw } from './decorators/property/csw.decorator';
import { getShpMapping, IShpMapping, ShapeFileType, shpMapping } from './decorators/property/shp.decorator';
import { getCatalogDBMapping, ICatalogDBMapping, catalogDB } from './decorators/property/catalogDB.decorator';
Expand Down Expand Up @@ -58,6 +59,9 @@ export class LayerMetadata implements ILayerMetadata {
@tsTypes({
mappingType: TsTypes.STRING,
})
@graphql({
nullable: true,
})
public source?: string = undefined;

/**
Expand All @@ -82,6 +86,9 @@ export class LayerMetadata implements ILayerMetadata {
@tsTypes({
mappingType: TsTypes.STRING,
})
@graphql({
nullable: true,
})
public sourceName?: string = undefined;

/**
Expand All @@ -106,6 +113,9 @@ export class LayerMetadata implements ILayerMetadata {
@tsTypes({
mappingType: TsTypes.DATE,
})
@graphql({
nullable: true,
})
public updateDate?: Date = undefined;

/**
Expand All @@ -130,6 +140,9 @@ export class LayerMetadata implements ILayerMetadata {
@tsTypes({
mappingType: TsTypes.NUMBER,
})
@graphql({
nullable: true,
})
public resolution?: number = undefined;

/**
Expand All @@ -155,6 +168,9 @@ export class LayerMetadata implements ILayerMetadata {
@tsTypes({
mappingType: TsTypes.NUMBER,
})
@graphql({
nullable: true,
})
public ep90?: number = undefined;

/**
Expand All @@ -177,7 +193,10 @@ export class LayerMetadata implements ILayerMetadata {
valuePath: 'features[0].properties.SensorType',
})
@tsTypes({
mappingType: TsTypes.STRING,
mappingType: TsTypes.SENSORTYPE,
})
@graphql({
nullable: true,
})
public sensorType?: SensorType = undefined;

Expand All @@ -204,6 +223,9 @@ export class LayerMetadata implements ILayerMetadata {
@tsTypes({
mappingType: TsTypes.NUMBER,
})
@graphql({
nullable: true,
})
public rms?: number = undefined;

/**
Expand All @@ -229,6 +251,9 @@ export class LayerMetadata implements ILayerMetadata {
@tsTypes({
mappingType: TsTypes.STRING,
})
@graphql({
nullable: true,
})
public scale?: string = undefined;

/**
Expand All @@ -254,6 +279,9 @@ export class LayerMetadata implements ILayerMetadata {
@tsTypes({
mappingType: TsTypes.STRING,
})
@graphql({
nullable: true,
})
public dsc?: string = undefined;

/**
Expand All @@ -279,6 +307,9 @@ export class LayerMetadata implements ILayerMetadata {
@tsTypes({
mappingType: TsTypes.OBJECT,
})
@graphql({
nullable: true,
})
public geometry?: GeoJSON = undefined;

/**
Expand All @@ -300,6 +331,9 @@ export class LayerMetadata implements ILayerMetadata {
@tsTypes({
mappingType: TsTypes.STRING,
})
@graphql({
nullable: true,
})
public id?: string = undefined;

/**
Expand All @@ -321,6 +355,9 @@ export class LayerMetadata implements ILayerMetadata {
@tsTypes({
mappingType: TsTypes.STRING,
})
@graphql({
nullable: true,
})
public version?: string = undefined;

public static getPyCSWMapping(prop: string): IPYCSWMapping | undefined {
Expand Down
34 changes: 34 additions & 0 deletions src/models/layerMetadata/link.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { graphqlClass } from '../common/decorators/property/classGraphql.decorator';
import { graphql } from '../common/decorators/property/graphql.decorator';
import { TsTypes, tsTypes } from './decorators/property/tsTypes.decorator';

@graphqlClass()
export class Link {
@tsTypes({
mappingType: TsTypes.STRING,
})
@graphql({
nullable: true,
})
public name?: string = undefined;

@tsTypes({
mappingType: TsTypes.STRING,
})
@graphql({
nullable: true,
})
public description?: string = undefined;

@tsTypes({
mappingType: TsTypes.STRING,
})
@graphql()
public protocol?: string = undefined;

@tsTypes({
mappingType: TsTypes.STRING,
})
@graphql()
public url?: string = undefined;
}
Loading

0 comments on commit 24429af

Please sign in to comment.