-
Notifications
You must be signed in to change notification settings - Fork 15
/
request_validation.ts
106 lines (93 loc) · 3.02 KB
/
request_validation.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
export type SupportedMessage =
| TestMessage
| EvidenceCreatedMessage
export type TestMessage = {
type: "test"
}
export type EvidenceCreatedMessage = {
type: "evidence_created",
evidenceUuid: string,
operationSlug: string,
contentType: typeof SupportedContentTypes[number]
globalVariables: Record<string, unknown>[]
operationVariables: Record<string, unknown>[]
}
/**
* isValidProcessRequest is a type guard that reviews the given body to make sure it matches
* a supported request type.
*
* @param body Any json-parsed content. This is not guaranteed to be correct for random bodies --
* especially esoteric javascript objects.
* @returns true if the value given has a supported request type. Otherwise, this returns false
*/
export const isSupportedMessage = (body: unknown): body is SupportedMessage => {
if (
isRecordWithTypeField(body)
&& isString(body.type)
&& SupportedRequestTypes.includes((body.type as typeof SupportedRequestTypes[number]))
) {
const basicRequest = body as BasicRequest
return (
isTestRequest(basicRequest)
|| isProcessRequest(basicRequest)
)
}
return false
}
/**
* isJsonWithType is a type guard that verifies that the given value is an object with a "type"
* field.
* @param body Anything.
* @returns true if the value given is an object with a type field. Otherwise, this returns false.
*/
const isRecordWithTypeField = (body: unknown): body is { type: unknown } => {
return (
typeof body === 'object' &&
body !== null &&
"type" in body
)
}
const isTestRequest = (body: BasicRequest): body is TestMessage => {
return body.type == 'test'
}
/**
* isProcessRequest is a typeguard that verifies that the given body matches the expected type for
* a process-type request. This does not verify that the content "makes sense", bui
* @param body
* @returns
*/
const isProcessRequest = (body: BasicRequest): body is EvidenceCreatedMessage => {
return (
body.type === 'evidence_created' &&
hasField(body, "evidenceUuid", isString) &&
hasField(body, "operationSlug", isString) &&
hasField(body, "contentType", (v) => (
isString(v) &&
// typescript can't compare the string literal of SupportedContentTypes with a random string
// so we tell it that the random string _is_ one of the types, but `includes` will actually
// verify that the random string is one of the supported literals.
SupportedContentTypes.includes(v as typeof SupportedContentTypes[number]))
)
)
}
const isString = (v: unknown): v is string => (
typeof v === 'string'
)
const hasField = (o: Record<string, unknown>, field: string, ofType: (b: unknown) => boolean) => {
return field in o && ofType(o[field])
}
export const SupportedContentTypes = [
"http-request-cycle",
"terminal-recording",
"codeblock",
"event",
"image",
"none",
] as const
export const SupportedRequestTypes = [
"evidence_created",
"test",
] as const
type BasicRequest = Record<string, unknown> & {
type: typeof SupportedRequestTypes[number]
}