forked from planetscale/database-js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsanitization.ts
86 lines (71 loc) · 1.89 KB
/
sanitization.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
type Stringable = { toString: () => string }
type Value = null | undefined | number | boolean | string | Array<Value> | Date | Stringable
export function format(query: string, values: Value[] | Record<string, Value>): string {
return Array.isArray(values) ? replacePosition(query, values) : replaceNamed(query, values)
}
function replacePosition(query: string, values: Value[]): string {
let index = 0
return query.replace(/\?/g, (match) => {
return index < values.length ? sanitize(values[index++]) : match
})
}
function replaceNamed(query: string, values: Record<string, Value>): string {
return query.replace(/:(\w+)/g, (match, name) => {
return hasOwn(values, name) ? sanitize(values[name]) : match
})
}
function hasOwn(obj: unknown, name: string): boolean {
return Object.prototype.hasOwnProperty.call(obj, name)
}
function sanitize(value: Value): string {
if (value == null) {
return 'null'
}
if (typeof value === 'number') {
return String(value)
}
if (typeof value === 'boolean') {
return value ? 'true' : 'false'
}
if (typeof value === 'string') {
return quote(value)
}
if (Array.isArray(value)) {
return value.map(sanitize).join(', ')
}
if (value instanceof Date) {
return quote(value.toISOString().replace('Z', ''))
}
return quote(value.toString())
}
function quote(text: string): string {
return `'${escape(text)}'`
}
const re = /[\0\b\n\r\t\x1a\\"']/g
function escape(text: string): string {
return text.replace(re, replacement)
}
function replacement(text: string): string {
switch (text) {
case '"':
return '\\"'
case "'":
return "\\'"
case '\n':
return '\\n'
case '\r':
return '\\r'
case '\t':
return '\\t'
case '\\':
return '\\\\'
case '\0':
return '\\0'
case '\b':
return '\\b'
case '\x1a':
return '\\Z'
default:
return ''
}
}