From c8d3b51e705b67b2064de9ab44a93635993b23eb Mon Sep 17 00:00:00 2001 From: Zak Henry Date: Sun, 19 Feb 2017 12:53:29 +0000 Subject: [PATCH] refactor(async/await): Refactored most runtime promises to async/await pattern --- src/common/stores/mock.store.ts | 9 +-- src/common/stores/store.ts | 16 +++-- src/server/controllers/request.ts | 2 +- src/server/controllers/resource.controller.ts | 59 ++++++++---------- src/server/middleware/debugLog.middleware.ts | 3 +- src/server/services/jwtAuthStrategy.ts | 34 +++++------ src/server/stores/db.store.ts | 60 ++++++++++--------- 7 files changed, 87 insertions(+), 96 deletions(-) diff --git a/src/common/stores/mock.store.ts b/src/common/stores/mock.store.ts index fdd635d..c6c08b2 100644 --- a/src/common/stores/mock.store.ts +++ b/src/common/stores/mock.store.ts @@ -59,11 +59,12 @@ export abstract class MockStore extends AbstractStore { + public async findOne(id?: identifier): Promise { + try { - return Promise.resolve(this.modelCollection.findById(id)); - } catch (e){ - return this.saveOne(this.getMock(id)) + return await this.modelCollection.findById(id); + } catch (e) { + return await this.saveOne(this.getMock(id)); } } diff --git a/src/common/stores/store.ts b/src/common/stores/store.ts index 1d4e6b7..210e17e 100644 --- a/src/common/stores/store.ts +++ b/src/common/stores/store.ts @@ -81,15 +81,13 @@ export abstract class AbstractStore { * @param validatorOptions * @returns {Promise} */ - public validate(model: T, validatorOptions?: ValidatorOptions): Promise | never { - - return this.validator.validate(model, validatorOptions) - .then((errors: ValidationError[]) => { - if (errors.length) { - throw new ValidationException(null, errors) - } - return model; - }); + public async validate(model: T, validatorOptions?: ValidatorOptions): Promise | never { + + const errors: ValidationError[] = await this.validator.validate(model, validatorOptions); + if (errors.length) { + throw new ValidationException(null, errors) + } + return model; } /** diff --git a/src/server/controllers/request.ts b/src/server/controllers/request.ts index bbc41e4..1c88ea1 100644 --- a/src/server/controllers/request.ts +++ b/src/server/controllers/request.ts @@ -70,7 +70,7 @@ export class Request { * Extract the passed body object from the raw request * @returns {Promise} */ - public getPayload(): Promise { + public getPayload(): Promise { return new Promise((resolve, reject) => { this.raw.setEncoding('utf8'); diff --git a/src/server/controllers/resource.controller.ts b/src/server/controllers/resource.controller.ts index e71cf1c..743688c 100644 --- a/src/server/controllers/resource.controller.ts +++ b/src/server/controllers/resource.controller.ts @@ -32,12 +32,9 @@ export abstract class ResourceController extends Abstra * @returns {any} */ @Route('GET', '/:id') - public getOne(request: Request, response: Response): Promise { - - return this.modelStore - .findOne(request.params() - .get('id')) - .then((model: M) => response.data(model)); + public async getOne(request: Request, response: Response): Promise { + const model: M = await this.modelStore.findOne(request.params().get('id')); + return response.data(model); } /** @@ -47,11 +44,9 @@ export abstract class ResourceController extends Abstra * @returns {any} */ @Route('GET', '/') - public getMany(request: Request, response: Response): Promise { - - return this.modelStore - .findMany() - .then((collection: Collection) => response.data(collection)); + public async getMany(request: Request, response: Response): Promise { + const collection: Collection = await this.modelStore.findMany(); + return response.data(collection); } /** @@ -85,12 +80,11 @@ export abstract class ResourceController extends Abstra * @returns {Promise} */ @Route('DELETE', '/:id') - public deleteOne(request: Request, response: Response): Promise { + public async deleteOne(request: Request, response: Response): Promise { - return request.getPayload() - .then((data: any) => this.modelStore.hydrate(data)) - .then((model: M) => this.modelStore.deleteOne(model)) - .then((model: M) => response.data(model)); + const model: M = await this.modelStore.hydrate(await request.getPayload()); + await this.modelStore.deleteOne(model); + return response.data(model); } /** @@ -101,28 +95,25 @@ export abstract class ResourceController extends Abstra * @param checkExists * @returns {Promise} */ - protected savePayload(request: Request, response: Response, checkExists: boolean = false, validatorOptions: ValidatorOptions = {}): Promise { - let modelPayload = request.getPayload() - .then((data: any) => this.modelStore.hydrate(data)); + protected async savePayload( + request: Request, + response: Response, + checkExists: boolean = false, + validatorOptions: ValidatorOptions = {}, + ): Promise | never { - if (checkExists) { - - modelPayload = modelPayload.then((payload: M) => { - return this.modelStore.hasOne(payload) - .then((exists: boolean) => { - if (!exists) { - throw new NotFoundException(`Model with id [${payload.getIdentifier()}] does not exist`); - } - return payload; - }); - }) + const model = await this.modelStore.hydrate(await request.getPayload()); + if (checkExists) { + const exists = await this.modelStore.hasOne(model); + if (!exists) { + throw new NotFoundException(`Model with id [${model.getIdentifier()}] does not exist`); + } } - return modelPayload - .then((model: M) => this.modelStore.validate(model, validatorOptions)) - .then((model: M) => this.modelStore.saveOne(model)) - .then((model: M) => response.data(model)); + await this.modelStore.validate(model, validatorOptions); + await this.modelStore.saveOne(model); + return response.data(model); } } diff --git a/src/server/middleware/debugLog.middleware.ts b/src/server/middleware/debugLog.middleware.ts index 3f579ba..1565e86 100644 --- a/src/server/middleware/debugLog.middleware.ts +++ b/src/server/middleware/debugLog.middleware.ts @@ -64,8 +64,7 @@ export class DebugLogMiddleware implements InjectableMiddleware { export function debugLog(...messages: string[]): InjectableMiddlewareFactory { return (injector: ReflectiveInjector): Middleware => { - return injector.get(DebugLogMiddleware) - .middlewareFactory(messages); + return injector.get(DebugLogMiddleware).middlewareFactory(messages); } } diff --git a/src/server/services/jwtAuthStrategy.ts b/src/server/services/jwtAuthStrategy.ts index 7cc4245..56cb70b 100644 --- a/src/server/services/jwtAuthStrategy.ts +++ b/src/server/services/jwtAuthStrategy.ts @@ -14,7 +14,7 @@ import { export const jwtAuthStrategyFactory:AuthenticationStrategyFactory = (remoteCliContext: RemoteCliContext): AuthenticationStrategy => { return function (vantage: any, options: any) { - return function (args: {client: {jwt: string, publicKeyPath: string, columns: number}}, cb: AuthenticationCallback) { + return async function (args: {client: {jwt: string, publicKeyPath: string, columns: number}}, cb: AuthenticationCallback) { try { remoteCliContext.logger.silly.debug('Passed client arguments: ', args); @@ -32,23 +32,21 @@ export const jwtAuthStrategyFactory:AuthenticationStrategyFactory = (remoteCliCo remoteCliContext.logger.info(`Authenticating JSON web token against public key [${keyPath}]`); - remoteCliContext.authService.verify(token, keyPath) - .then((payload: any) => { - remoteCliContext.logger.info(`${payload.username} has been authenticated with token`) - .debug('Token:', token); - let displayBanner = `Hi ${payload.username}, Welcome to Zeroth runtime cli.`; - if (args.client.columns >= 80) { - displayBanner = bannerBg(undefined, token); - } - this.log(chalk.grey(`You were authenticated with a JSON Web token verified against the public key at ${keyPath}`)); - this.log(displayBanner); - this.log(` Type 'help' for a list of available commands`); - - return cb(null, true); - }) - .catch((e: Error) => { - return cb(e.message, false); - }); + const payload = await remoteCliContext.authService.verify(token, keyPath); + + remoteCliContext.logger.info(`${payload.username} has been authenticated with token`) + .debug('Token:', token); + + let displayBanner = `Hi ${payload.username}, Welcome to Zeroth runtime cli.`; + if (args.client.columns >= 80) { + displayBanner = bannerBg(undefined, token); + } + + this.log(chalk.grey(`You were authenticated with a JSON Web token verified against the public key at ${keyPath}`)); + this.log(displayBanner); + this.log(` Type 'help' for a list of available commands`); + + return cb(null, true); } catch (e) { remoteCliContext.logger.error('Authentication error', e.message).debug(e.stack); diff --git a/src/server/stores/db.store.ts b/src/server/stores/db.store.ts index 2c9b3bb..09c9d8f 100644 --- a/src/server/stores/db.store.ts +++ b/src/server/stores/db.store.ts @@ -73,50 +73,54 @@ export abstract class DatabaseStore extends AbstractSto /** * @inheritdoc */ - public findMany(query?: Query): Promise> { - return this.getRepository() - .then((repo) => repo.find({ - //@todo define query and restrict count with pagination - })) - .then((entityArray: T[]): Collection => { - - if (!entityArray.length) { - throw new NotFoundException(`No ${this.modelStatic.name} found with query params [${JSON.stringify(query)}]`); - } - - return new Collection(entityArray); - }) - .catch((e) => { - this.logger.error(e); - throw e; + public async findMany(query?: Query): Promise> { + + try { + const repo = await this.getRepository(); + + const entityArray: T[] = await repo.find({ + //@todo define query interface and restrict count with pagination }); + + if (!entityArray.length) { + throw new NotFoundException(`No ${this.modelStatic.name} found with query params [${JSON.stringify(query)}]`); + } + + return new Collection(entityArray); + + } catch (e) { + this.logger.error(e); + throw e; + } } /** * @inheritdoc */ - public saveOne(model: T): Promise { - return this.getRepository() - .then((repo) => repo.persist(model)); + public async saveOne(model: T): Promise { + const repo = await this.getRepository(); + return repo.persist(model); } /** * @inheritdoc */ - public deleteOne(model: T): Promise { - return this.getRepository() - .then((repo) => repo.remove(model)); + public async deleteOne(model: T): Promise { + const repo = await this.getRepository(); + return repo.remove(model); } /** * @inheritdoc */ - public hasOne(model: T): Promise { - return this.getRepository() - .then((repo) => repo.findOneById(model)) - .then(() => true) - .catch(() => false) - ; + public async hasOne(model: T): Promise { + const repo = await this.getRepository(); + try { + await repo.findOneById(model.getIdentifier()); + return true; + } catch (e) { + return false; + } } }