Skip to content

Commit

Permalink
convert to typescript every file in /engine ; doument input / output …
Browse files Browse the repository at this point in the history
…types for classes and some functions ; add linter for built files
  • Loading branch information
getlarge committed Mar 20, 2020
1 parent c1f5bd8 commit 07d719b
Show file tree
Hide file tree
Showing 44 changed files with 755 additions and 416 deletions.
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -10,6 +10,7 @@
"test-watch": "jest --watch",
"lint": "eslint src/*",
"lint-fix": "eslint src/* --fix",
"lint:fix": "tsc --noEmit && eslint '*/**/*.{js,ts,tsx}' --quiet --fix",
"lint-staged": "lint-staged",
"coverage": "cross-env NODE_ENV=test jest --coverage",
"coverage-ci": "npm run coverage && cat ./coverage/lcov.info | codecov",
Expand Down
10 changes: 0 additions & 10 deletions src/engine/CustomError.js

This file was deleted.

26 changes: 26 additions & 0 deletions src/engine/CustomError.ts
@@ -0,0 +1,26 @@
/* eslint-disable @typescript-eslint/no-explicit-any */

declare type ErrorInterface = Error;

declare class Error implements ErrorInterface {
name: string;
message: string;
static captureStackTrace(object: any, objectConstructor?: any): any;
}

export class CustomError extends Error {
code: any;
status?: any;
meta?: any;

constructor(message?: string, code?: any, status?: any, meta?: any) {
// super(message);
super();
Error.captureStackTrace(this, this.constructor);
this.message = message;
this.name = this.constructor.name;
this.code = code;
this.status = status;
this.meta = meta;
}
}
@@ -1,4 +1,5 @@
/* eslint-disable @typescript-eslint/no-empty-function */
/* eslint-disable @typescript-eslint/explicit-function-return-type */

import { Action, isAction } from './Action';
import { Permission, isPermission } from '../permission/Permission';
Expand Down Expand Up @@ -327,7 +328,7 @@ describe('Action', () => {
input: {},
output: {},
resolve() {},
permissions: [ new Permission().authenticated(), new Permission() ],
permissions: [new Permission().authenticated(), new Permission()],
});

function fn() {
Expand All @@ -338,3 +339,6 @@ describe('Action', () => {
});
});
});

/* eslint-enable @typescript-eslint/no-empty-function */
/* eslint-enable @typescript-eslint/explicit-function-return-type */
97 changes: 70 additions & 27 deletions src/engine/action/Action.js → src/engine/action/Action.ts
@@ -1,16 +1,51 @@
import { passOrThrow, isMap, isFunction } from '../util';
/* eslint-disable @typescript-eslint/no-explicit-any */

import { passOrThrow, isMap, isFunction } from '../util';
import { AttributeBase } from '../attribute/Attribute';
import { DataTypeFunction } from '../datatype/DataType';
import {
generatePermissionDescription,
processActionPermissions,
Permission,
} from '../permission/Permission';

export const ACTION_TYPE_MUTATION = 'mutation';
export const ACTION_TYPE_QUERY = 'query';
export const actionTypes = [ ACTION_TYPE_MUTATION, ACTION_TYPE_QUERY ];
export const actionTypes = [ACTION_TYPE_MUTATION, ACTION_TYPE_QUERY];

export type ActionSetup = {
name?: string;
description?: string;
// input?: AttributeBase | Function | { [type: string]: Function };
input?: any;
// output?: AttributeBase | Function | { [type: string]: Function };
output?: any;
resolve?: Function;
type?: string;
permissions?: Function | Permission | Permission[];
postProcessor?: Function;
};

export class Action {
constructor(setup = {}) {
name: string;
description: string;
// input: AttributeBase | Function | { [type: string]: Function };
// private _input: AttributeBase | Function | { [type: string]: Function };
input: any;
private _input: any;
// output: AttributeBase | Function | { [type: string]: Function };
// private _output: AttributeBase | Function | { [type: string]: Function };
output: any;
private _output: any;
resolve: Function;
type: string;
permissions: Function | Permission | Permission[];
private _permissions: Function | Permission | Permission[];
private _defaultPermissions: Function | Permission | Permission[];
descriptionPermissions: string | false;
postProcessor: Function;

constructor(setup: ActionSetup = {} as ActionSetup) {
const {
name,
description,
Expand Down Expand Up @@ -77,24 +112,26 @@ export class Action {
}

if (isFunction(this.input)) {
this.input = this.input();
const inputFn = this.input as Function;
this.input = inputFn();

passOrThrow(
isMap(this.input),
() =>
`Input definition function for action '${
this.name
}' does not return a map`,
`Input definition function for action '${this.name}' does not return a map`,
);
}

const inputAttr = this.input as AttributeBase;
passOrThrow(
this.input.type,
inputAttr.type,
() => `Missing input type for action '${this.name}'`,
);

if (isFunction(this.input.type)) {
this.input.type = this.input.type({
if (isFunction(inputAttr.type)) {
const inputAttrType = inputAttr.type as DataTypeFunction;
this.input = this.input as AttributeBase;
this.input.type = inputAttrType({
name: 'input',
description: this.input.description || this.description,
});
Expand All @@ -105,7 +142,7 @@ export class Action {
return this._input;
}

hasInput() {
hasInput(): boolean {
return !!this.input;
}

Expand All @@ -119,24 +156,26 @@ export class Action {
}

if (isFunction(this.output)) {
this.output = this.output();
const outputFn = this.output as Function;
this.output = outputFn();

passOrThrow(
isMap(this.output),
() =>
`Output definition function for action '${
this.name
}' does not return a map`,
`Output definition function for action '${this.name}' does not return a map`,
);
}

const outputAttr = this.output as AttributeBase;
passOrThrow(
this.output.type,
outputAttr.type,
() => `Missing output type for action '${this.name}'`,
);

if (isFunction(this.output.type)) {
this.output.type = this.output.type({
if (isFunction(outputAttr.type)) {
const outputAttrType = outputAttr.type as DataTypeFunction;
this.output = this.output as AttributeBase;
this.output.type = outputAttrType({
name: 'output',
description: this.output.description || this.description,
});
Expand All @@ -147,19 +186,23 @@ export class Action {
return this._output;
}

hasOutput() {
hasOutput(): boolean {
return !!this.output;
}

_processPermissions() {
if (this._permissions) {
const permissions = isFunction(this._permissions)
? this._permissions()
: this._permissions;

return processActionPermissions(this, permissions);
}
else if (this._defaultPermissions) {
if (isFunction(this._permissions)) {
const permissionsFn = this._permissions as Function;
return processActionPermissions(this, permissionsFn);
}
return processActionPermissions(this, this._permissions);

// const permissions = isFunction(this._permissions)
// ? this._permissions()
// : this._permissions;
// return processActionPermissions(this, permissions);
} else if (this._defaultPermissions) {
return processActionPermissions(this, this._defaultPermissions);
}

Expand Down Expand Up @@ -193,6 +236,6 @@ export class Action {
}
}

export const isAction = obj => {
export const isAction = (obj: any) => {
return obj instanceof Action;
};
32 changes: 28 additions & 4 deletions src/engine/attribute/Attribute.ts
@@ -1,6 +1,7 @@
import { ComplexDataType } from '../datatype/ComplexDataType';
import { DataType, DataTypeFunction } from '../datatype/DataType';
import { Entity } from '../entity/Entity';
import { Mutation } from '../mutation/Mutation';

/**
* base of a model attribute
Expand All @@ -14,7 +15,7 @@ export type AttributeBase = {
/**
* data type of the attribute
*/
type: DataType | ComplexDataType | Entity;
type: DataType | ComplexDataType | Entity | DataTypeFunction;

/**
* make attribute non-nullable on the storage level
Expand Down Expand Up @@ -46,17 +47,38 @@ export type AttributeBase = {
/**
* default value generator for create type mutations
*/
defaultValue?: () => any;

defaultValue?: (
payload?: any,
entityMutation?: Mutation,
entity?: Entity,
context?: Record<string, any>,
) => any;

/**
* custom data serializer function
*/
serialize?: () => any;

serialize?: (
field?: any,
payload?: any,
entityMutation?: Mutation,
entity?: Entity,
model?: any,
context?: Record<string, any>,
language?: any,
) => any;

/**
* custom validation function
*/
validate?: () => any;
validate?: (
value?: any,
attributeName?: string,
row?: any,
source?: any,
context?: Record<string, any>,
) => any;

/**
* hide the attribute in the protocol (graphql) layer
Expand All @@ -82,6 +104,8 @@ export type AttributeBase = {
* place to store custom (project-related) meta data
*/
meta?: any;

gqlFieldNameI18n?: any;
};

/**
Expand Down
@@ -1,24 +1,40 @@
import { passOrThrow, isArray } from '../util';

import { isSchema } from '../schema/Schema';

import { Schema, isSchema } from '../schema/Schema';
import { languageIsoCodeRegex, LANGUAGE_ISO_CODE_PATTERN } from '../constants';

import { isProtocolConfiguration } from '../protocol/ProtocolConfiguration';
import { isStorageConfiguration } from '../storage/StorageConfiguration';
import {
ProtocolConfiguration,
isProtocolConfiguration,
} from '../protocol/ProtocolConfiguration';
import {
StorageConfiguration,
isStorageConfiguration,
} from '../storage/StorageConfiguration';

import * as _ from 'lodash';

export type ConfigurationSetup = {
languages?: string[];
schema?: Schema;
protocolConfiguration?: ProtocolConfiguration;
storageConfiguration?: StorageConfiguration;
};

export class Configuration {
constructor(setup = {}) {
languages: string[];
schema: Schema;
protocolConfiguration: ProtocolConfiguration;
storageConfiguration: StorageConfiguration;

constructor(setup: ConfigurationSetup = {} as ConfigurationSetup) {
const {
languages,
schema,
protocolConfiguration,
storageConfiguration,
} = setup;

this.setLanguages(languages || [ 'en' ]);
this.setLanguages(languages || ['en']);

if (schema) {
this.setSchema(schema);
Expand Down
1 change: 1 addition & 0 deletions src/engine/entity/Entity.ts
Expand Up @@ -63,6 +63,7 @@ export type EntitySetup = {
includeTimeTracking?: boolean;
includeUserTracking?: boolean;
indexes?: any;
// improve typings ?
mutations?: any;
permissions?: any;
states?: any;
Expand Down
2 changes: 2 additions & 0 deletions src/engine/entity/ShadowEntity.spec.ts
@@ -1,3 +1,5 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */

import { Entity } from './Entity';
import { ShadowEntity, isShadowEntity } from './ShadowEntity';
import { passOrThrow } from '../util';
Expand Down

0 comments on commit 07d719b

Please sign in to comment.