typescript-type
Version:
Typescript type
79 lines (68 loc) • 2.6 kB
text/typescript
import { randomBytes } from 'crypto';
import { isLeft } from 'fp-ts/lib/Either';
import * as t from 'io-ts';
import reporter from 'io-ts-reporters';
import { PartialRecord } from '../types/operand';
import { BadConfigException } from './driver.exceptions';
import { Statuses } from './driver.statuses';
import { LinkStrategy, LinksObject } from './driver.types';
export abstract class Driver<Config = any> {
public name = 'driver';
protected config: Config;
protected linkStrategy: LinkStrategy = 'default';
protected abstract links: LinksObject;
constructor(config: Config, protected configCodec: any) {
this.config = this.getParsedData(config, configCodec);
}
public setName(name: string) {
this.name = name;
}
public setConfig(config: Config) {
this.config = this.getParsedData(config, this.configCodec);
}
public setLinkStrategy(strategy: LinkStrategy) {
this.linkStrategy = strategy;
}
public generateId(max = 12, length = 8) {
const random = randomBytes(3 * 4).toString('base64').replace(/\/|\+/g, '');
return this.now(max) + random.substring(0, length).toUpperCase();
}
public status(statuses: PartialRecord<Statuses, string[]>, code: string) {
for (const s in statuses) {
const c = statuses[<Statuses>s];
if (c && code && c.indexOf(code) > -1) { return s; }
}
return Statuses.pending;
}
public now(max = 12): string {
return (new Date()).toISOString().replace(/[^0-9]/g, '').substring(0, max);
}
protected getLinks() {
return this.links[this.linkStrategy];
}
/**
* Parses using the codec and throws an exception if not matching
*
* @throws BadConfigException
*/
protected getParsedData = <TData = any, O = TData, I = unknown>(rawData: I, codec: t.Type<TData, O, I>): TData => {
const result = codec.decode(rawData);
if (isLeft(result)) {
// Use a reporter to throw an error if validation fails
throw new BadConfigException(reporter.report(result));
}
// Get the validated value and use it in your application
return result.right;
};
}
export const getDriver = <T extends Driver, U extends string>(
driverName: U, config: Parameters<Driver['setConfig']>[0], drivers: { [x: string]: any; }
): T => {
if (!drivers[driverName]) {
throw Error(`This driver is not supported, supported drivers: ${Object.keys(drivers).join(', ')}`);
}
const driver = drivers[driverName], instance = new driver(config) as unknown as T;
instance.name = driverName;
if (config.sandbox) { instance.setLinkStrategy('sandbox'); }
return instance;
};