forked from cloudevents/sdk-javascript
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparsers.ts
105 lines (89 loc) · 3.1 KB
/
parsers.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/*
Copyright 2021 The CloudEvents Authors
SPDX-License-Identifier: Apache-2.0
*/
import JSONbig from "json-bigint";
import CONSTANTS from "./constants";
import { isString, isDefinedOrThrow, isStringOrObjectOrThrow, ValidationError } from "./event/validation";
const __JSON = JSON;
export abstract class Parser {
abstract parse(payload: Record<string, unknown> | string | string[] | undefined): 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, unknown> | string): string {
if (typeof payload === "string") {
// This is kind of a hack, but the payload data could be JSON in the form of a single
// string, such as "some data". But without the quotes in the string, JSON.parse blows
// up. We can check for this scenario and add quotes. Not sure if this is ideal.
if (!/^[[|{|"]/.test(payload)) {
payload = `"${payload}"`;
}
}
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"));
if (process.env[CONSTANTS.USE_BIG_INT_ENV] === "true") {
JSON = JSONbig(({ useNativeBigInt: true })) as JSON;
} else {
JSON = __JSON;
}
const parseJSON = (v: Record<string, unknown> | 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, unknown> | 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): string {
let date = new Date(Date.parse(payload));
if (date.toString() === "Invalid Date") {
date = new Date();
}
return date.toISOString();
}
}
export const parserByEncoding: { [key: string]: { [key: string]: Parser } } = {
base64: {
[CONSTANTS.MIME_CE_JSON]: new JSONParser(new Base64Parser()),
[CONSTANTS.MIME_OCTET_STREAM]: new PassThroughParser(),
},
};