From 6a663379e840c8c7643ab7b3764ddb8f72d80adf Mon Sep 17 00:00:00 2001 From: Grant Timmerman Date: Thu, 23 Jul 2020 16:05:22 -0700 Subject: [PATCH] refactor: simplify parser logic and duplicated code Signed-off-by: Grant Timmerman --- src/parsers.ts | 79 +++++++++++++++++++++++++++++++++ src/parsers/base64.ts | 18 -------- src/parsers/date.ts | 7 --- src/parsers/index.ts | 30 ------------- src/parsers/json.ts | 30 ------------- src/parsers/mapped.ts | 6 --- src/parsers/parser.ts | 3 -- src/parsers/pass_through.ts | 7 --- test/integration/parser_test.ts | 2 +- 9 files changed, 80 insertions(+), 102 deletions(-) create mode 100644 src/parsers.ts delete mode 100644 src/parsers/base64.ts delete mode 100644 src/parsers/date.ts delete mode 100644 src/parsers/index.ts delete mode 100644 src/parsers/json.ts delete mode 100644 src/parsers/mapped.ts delete mode 100644 src/parsers/parser.ts delete mode 100644 src/parsers/pass_through.ts diff --git a/src/parsers.ts b/src/parsers.ts new file mode 100644 index 00000000..f97bfed9 --- /dev/null +++ b/src/parsers.ts @@ -0,0 +1,79 @@ +import CONSTANTS from "./constants"; +import { isString, isDefinedOrThrow, isStringOrObjectOrThrow, ValidationError } from "./event/validation"; + +export abstract class Parser { + abstract parse(payload: Record | string): unknown; +} + +export class JSONParser implements Parser { + decorator?: Base64Parser; + constructor(decorator?: Base64Parser) { + this.decorator = decorator; + } + + /** + * Parses the payload with an optional decorator + * @param {object|string} payload the JSON payload + * @return {object} the parsed JSON payload. + */ + parse(payload: Record | string): string { + if (this.decorator) { + payload = this.decorator.parse(payload); + } + + isDefinedOrThrow(payload, new ValidationError("null or undefined payload")); + isStringOrObjectOrThrow(payload, new ValidationError("invalid payload type, allowed are: string or object")); + const parseJSON = (v: Record | string): string => (isString(v) ? JSON.parse(v as string) : v); + return parseJSON(payload); + } +} + +export class PassThroughParser extends Parser { + parse(payload: unknown): unknown { + return payload; + } +} + +const jsonParser = new JSONParser(); +export const parserByContentType: { [key: string]: Parser } = { + [CONSTANTS.MIME_JSON]: jsonParser, + [CONSTANTS.MIME_CE_JSON]: jsonParser, + [CONSTANTS.DEFAULT_CONTENT_TYPE]: jsonParser, + [CONSTANTS.DEFAULT_CE_CONTENT_TYPE]: jsonParser, + [CONSTANTS.MIME_OCTET_STREAM]: new PassThroughParser(), +}; + +export class Base64Parser implements Parser { + decorator?: Parser; + + constructor(decorator?: Parser) { + this.decorator = decorator; + } + + parse(payload: Record | string): string { + let payloadToParse = payload; + if (this.decorator) { + payloadToParse = this.decorator.parse(payload) as string; + } + + return Buffer.from(payloadToParse as string, "base64").toString(); + } +} + +export interface MappedParser { + name: string; + parser: Parser; +} + +export class DateParser extends Parser { + parse(payload: string): Date { + return new Date(Date.parse(payload)); + } +} + +export const parserByEncoding: { [key: string]: { [key: string]: Parser } } = { + base64: { + [CONSTANTS.MIME_CE_JSON]: new JSONParser(new Base64Parser()), + [CONSTANTS.MIME_OCTET_STREAM]: new PassThroughParser(), + }, +}; diff --git a/src/parsers/base64.ts b/src/parsers/base64.ts deleted file mode 100644 index bb442ff6..00000000 --- a/src/parsers/base64.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Parser } from "./parser"; - -export class Base64Parser implements Parser { - decorator?: Parser; - - constructor(decorator?: Parser) { - this.decorator = decorator; - } - - parse(payload: Record | string): string { - let payloadToParse = payload; - if (this.decorator) { - payloadToParse = this.decorator.parse(payload) as string; - } - - return Buffer.from(payloadToParse as string, "base64").toString(); - } -} diff --git a/src/parsers/date.ts b/src/parsers/date.ts deleted file mode 100644 index 77d53d4a..00000000 --- a/src/parsers/date.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Parser } from "./parser"; - -export class DateParser extends Parser { - parse(payload: string): Date { - return new Date(Date.parse(payload)); - } -} diff --git a/src/parsers/index.ts b/src/parsers/index.ts deleted file mode 100644 index 56e3da88..00000000 --- a/src/parsers/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Parser } from "./parser"; -import { JSONParser } from "./json"; -import { PassThroughParser } from "./pass_through"; -import { Base64Parser } from "./base64"; -import CONSTANTS from "../constants"; - -export * from "./parser"; -export * from "./base64"; -export * from "./json"; -export * from "./date"; -export * from "./mapped"; -export * from "./pass_through"; - -const jsonParser = new JSONParser(); -const passThroughParser = new PassThroughParser(); - -export const parserByContentType: { [key: string]: Parser } = { - [CONSTANTS.MIME_JSON]: jsonParser, - [CONSTANTS.MIME_CE_JSON]: jsonParser, - [CONSTANTS.DEFAULT_CONTENT_TYPE]: jsonParser, - [CONSTANTS.DEFAULT_CE_CONTENT_TYPE]: jsonParser, - [CONSTANTS.MIME_OCTET_STREAM]: passThroughParser, -}; - -export const parserByEncoding: { [key: string]: { [key: string]: Parser } } = { - base64: { - [CONSTANTS.MIME_CE_JSON]: new JSONParser(new Base64Parser()), - [CONSTANTS.MIME_OCTET_STREAM]: new PassThroughParser(), - }, -}; diff --git a/src/parsers/json.ts b/src/parsers/json.ts deleted file mode 100644 index 062f9dad..00000000 --- a/src/parsers/json.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Base64Parser } from "./base64"; -import { isString, isDefinedOrThrow, isStringOrObjectOrThrow, ValidationError } from "../event/validation"; -import { Parser } from "./parser"; - -const invalidPayloadTypeError = new ValidationError("invalid payload type, allowed are: string or object"); -const nullOrUndefinedPayload = new ValidationError("null or undefined payload"); - -const parseJSON = (v: Record | string): string => (isString(v) ? JSON.parse(v as string) : v); - -export class JSONParser implements Parser { - decorator?: Base64Parser; - constructor(decorator?: Base64Parser) { - this.decorator = decorator; - } - - /** - * Parses the payload with an optional decorator - * @param {object|string} payload the JSON payload - * @return {object} the parsed JSON payload. - */ - parse(payload: Record | string): string { - if (this.decorator) { - payload = this.decorator.parse(payload); - } - - isDefinedOrThrow(payload, nullOrUndefinedPayload); - isStringOrObjectOrThrow(payload, invalidPayloadTypeError); - return parseJSON(payload); - } -} diff --git a/src/parsers/mapped.ts b/src/parsers/mapped.ts deleted file mode 100644 index 820e800e..00000000 --- a/src/parsers/mapped.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Parser } from "./parser"; - -export interface MappedParser { - name: string; - parser: Parser; -} diff --git a/src/parsers/parser.ts b/src/parsers/parser.ts deleted file mode 100644 index bf604f03..00000000 --- a/src/parsers/parser.ts +++ /dev/null @@ -1,3 +0,0 @@ -export abstract class Parser { - abstract parse(payload: Record | string): unknown; -} diff --git a/src/parsers/pass_through.ts b/src/parsers/pass_through.ts deleted file mode 100644 index 454fc758..00000000 --- a/src/parsers/pass_through.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Parser } from "./parser"; - -export class PassThroughParser extends Parser { - parse(payload: unknown): unknown { - return payload; - } -} diff --git a/test/integration/parser_test.ts b/test/integration/parser_test.ts index 2157e7db..b5d678a4 100644 --- a/test/integration/parser_test.ts +++ b/test/integration/parser_test.ts @@ -1,7 +1,7 @@ import "mocha"; import { expect } from "chai"; -import { JSONParser as Parser } from "../../src/parsers/"; +import { JSONParser as Parser } from "../../src/parsers"; import { ValidationError } from "../../src/"; describe("JSON Event Format Parser", () => {