UNPKG

4.39 kBJavaScriptView Raw
1/*eslint max-len: 0, no-var:0 */
2
3const charsRegex = /[\0\b\t\n\r\x1a"'\\]/g; // eslint-disable-line no-control-regex
4const charsMap = {
5 '\0': '\\0',
6 '\b': '\\b',
7 '\t': '\\t',
8 '\n': '\\n',
9 '\r': '\\r',
10 '\x1a': '\\Z',
11 '"': '\\"',
12 "'": "\\'",
13 '\\': '\\\\',
14};
15
16function wrapEscape(escapeFn) {
17 return function finalEscape(val, ctx = {}) {
18 return escapeFn(val, finalEscape, ctx);
19 };
20}
21
22function makeEscape(config = {}) {
23 const finalEscapeDate = config.escapeDate || dateToString;
24 const finalEscapeArray = config.escapeArray || arrayToList;
25 const finalEscapeBuffer = config.escapeBuffer || bufferToString;
26 const finalEscapeString = config.escapeString || escapeString;
27 const finalEscapeObject = config.escapeObject || escapeObject;
28 const finalWrap = config.wrap || wrapEscape;
29
30 function escapeFn(val, finalEscape, ctx) {
31 if (val === undefined || val === null) {
32 return 'NULL';
33 }
34 switch (typeof val) {
35 case 'boolean':
36 return val ? 'true' : 'false';
37 case 'number':
38 return val + '';
39 case 'object':
40 if (val instanceof Date) {
41 val = finalEscapeDate(val, finalEscape, ctx);
42 } else if (Array.isArray(val)) {
43 return finalEscapeArray(val, finalEscape, ctx);
44 } else if (Buffer.isBuffer(val)) {
45 return finalEscapeBuffer(val, finalEscape, ctx);
46 } else {
47 return finalEscapeObject(val, finalEscape, ctx);
48 }
49 }
50 return finalEscapeString(val, finalEscape, ctx);
51 }
52
53 return finalWrap ? finalWrap(escapeFn) : escapeFn;
54}
55
56function escapeObject(val, finalEscape, ctx) {
57 if (typeof val.toSQL === 'function') {
58 return val.toSQL(ctx);
59 } else {
60 return JSON.stringify(val);
61 }
62}
63
64function arrayToList(array, finalEscape, ctx) {
65 let sql = '';
66 for (let i = 0; i < array.length; i++) {
67 const val = array[i];
68 if (Array.isArray(val)) {
69 sql +=
70 (i === 0 ? '' : ', ') + '(' + arrayToList(val, finalEscape, ctx) + ')';
71 } else {
72 sql += (i === 0 ? '' : ', ') + finalEscape(val, ctx);
73 }
74 }
75 return sql;
76}
77
78function bufferToString(buffer) {
79 return 'X' + escapeString(buffer.toString('hex'));
80}
81
82function escapeString(val, finalEscape, ctx) {
83 let chunkIndex = (charsRegex.lastIndex = 0);
84 let escapedVal = '';
85 let match;
86
87 while ((match = charsRegex.exec(val))) {
88 escapedVal += val.slice(chunkIndex, match.index) + charsMap[match[0]];
89 chunkIndex = charsRegex.lastIndex;
90 }
91
92 if (chunkIndex === 0) {
93 // Nothing was escaped
94 return "'" + val + "'";
95 }
96
97 if (chunkIndex < val.length) {
98 return "'" + escapedVal + val.slice(chunkIndex) + "'";
99 }
100
101 return "'" + escapedVal + "'";
102}
103
104function dateToString(date, finalEscape, ctx) {
105 const timeZone = ctx.timeZone || 'local';
106
107 const dt = new Date(date);
108 let year;
109 let month;
110 let day;
111 let hour;
112 let minute;
113 let second;
114 let millisecond;
115
116 if (timeZone === 'local') {
117 year = dt.getFullYear();
118 month = dt.getMonth() + 1;
119 day = dt.getDate();
120 hour = dt.getHours();
121 minute = dt.getMinutes();
122 second = dt.getSeconds();
123 millisecond = dt.getMilliseconds();
124 } else {
125 const tz = convertTimezone(timeZone);
126
127 if (tz !== false && tz !== 0) {
128 dt.setTime(dt.getTime() + tz * 60000);
129 }
130
131 year = dt.getUTCFullYear();
132 month = dt.getUTCMonth() + 1;
133 day = dt.getUTCDate();
134 hour = dt.getUTCHours();
135 minute = dt.getUTCMinutes();
136 second = dt.getUTCSeconds();
137 millisecond = dt.getUTCMilliseconds();
138 }
139
140 // YYYY-MM-DD HH:mm:ss.mmm
141 return (
142 zeroPad(year, 4) +
143 '-' +
144 zeroPad(month, 2) +
145 '-' +
146 zeroPad(day, 2) +
147 ' ' +
148 zeroPad(hour, 2) +
149 ':' +
150 zeroPad(minute, 2) +
151 ':' +
152 zeroPad(second, 2) +
153 '.' +
154 zeroPad(millisecond, 3)
155 );
156}
157
158function zeroPad(number, length) {
159 number = number.toString();
160 while (number.length < length) {
161 number = '0' + number;
162 }
163 return number;
164}
165
166function convertTimezone(tz) {
167 if (tz === 'Z') {
168 return 0;
169 }
170 const m = tz.match(/([+\-\s])(\d\d):?(\d\d)?/);
171 if (m) {
172 return (
173 (m[1] == '-' ? -1 : 1) *
174 (parseInt(m[2], 10) + (m[3] ? parseInt(m[3], 10) : 0) / 60) *
175 60
176 );
177 }
178 return false;
179}
180
181module.exports = {
182 arrayToList,
183 bufferToString,
184 dateToString,
185 escapeString,
186 charsRegex,
187 charsMap,
188 escapeObject,
189 makeEscape,
190};