-
Notifications
You must be signed in to change notification settings - Fork 1
/
query-segment.js
86 lines (79 loc) · 2.99 KB
/
query-segment.js
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
export default class QuerySegment {
/**
* Creates a new `QuerySegment` that contains a partial or full SQL query and the parameters within them.
* @param {String} segment - The query string segment.
* @param {Map.<String, *>} params - The parameters that map to the segment.
*/
constructor(segment, params) {
//validate
if (segment && typeof segment !== 'string') {
throw new Error('The "segment" argument must be null, undefined, or a string.');
}
/**
* @type {String}
*/
this.segment = segment || '';
/**
* @type {Map.<String, *>}
*/
this.params = null;
if (params instanceof Map || Array.isArray(params)) {
this.params = new Map(params);
} else {
this.params = new Map();
}
}
/**
* Concatenates segments and params from the specified `segments` into a new line in the query segment.
* @param {Number} indent - The number of indent levels (x4 spaces) to indent the line by.
* @param {...QuerySegment|String} segments - The `QuerySegments` or strings to combine into this one.
* @returns {QuerySegment}
*/
line(indent, ...segments) {
return this.concat('\n', ' '.repeat(indent), ...segments);
}
/**
* Prepends segments and params from the specified `segments` into this one and returns this instance.
* @param {...QuerySegment|String} segments - The `QuerySegments` or strings to prepend into this one.
* @returns {QuerySegment}
*/
prepend(...segments) {
let temp = this.segment;
this.segment = '';
this.concat(...segments);
this.segment += temp;
return this;
}
/**
* Concatenates segments and params from the specified `segments` into this one and returns this instance.
* @param {...QuerySegment|String} segments - The `QuerySegments` or strings to combine into this one.
* @returns {QuerySegment}
*/
concat(...segments) {
if (!this.params) {
this.params = new Map();
}
for (let s of segments) {
if (s) {
if (typeof s === 'string') {
//concat a string segment
this.segment += s;
} else {
//combine QuerySegment
if (s.segment) {
this.segment += s.segment;
}
if (s.params.size) {
for (let [p, v] of s.params) {
if (this.params.has(p)) {
throw new Error(`The query segment failed to combine other segments due to a parameter name collision. The parameter named "${p}" was added previously or already exists.`);
}
this.params.set(p, v);
}
}
}
}
}
return this;
}
}