1 | ;
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.parseWhere = exports.parseMeasurement = exports.Measurement = exports.Expression = void 0;
|
4 | const grammar_1 = require("./grammar");
|
5 | function regexHasFlags(re) {
|
6 | if (typeof re.flags !== "undefined") {
|
7 | return re.flags.length > 0;
|
8 | }
|
9 | return !re.toString().endsWith("/");
|
10 | }
|
11 | /**
|
12 | * Expression is used to build filtering expressions, like those used in WHERE
|
13 | * clauses. It can be used for fluent and safe building of queries using
|
14 | * untrusted input.
|
15 | *
|
16 | * @example
|
17 | * e => e
|
18 | * .field('host').equals.value('ares.peet.io')
|
19 | * .or
|
20 | * .field('host').matches(/example\.com$/)
|
21 | * .or
|
22 | * .expr(e => e
|
23 | * .field('country').equals.value('US')
|
24 | * .and
|
25 | * .field('state').equals.value('WA'));
|
26 | *
|
27 | * // Generates:
|
28 | * // "host" = 'ares.peet.io' OR "host" ~= /example\.com$/ OR \
|
29 | * // ("county" = 'US' AND "state" = 'WA')
|
30 | */
|
31 | class Expression {
|
32 | constructor() {
|
33 | this._query = [];
|
34 | }
|
35 | /**
|
36 | * Inserts a tag reference into the expression; the name will be
|
37 | * automatically escaped.
|
38 | * @param name
|
39 | * @return
|
40 | */
|
41 | tag(name) {
|
42 | this.field(name);
|
43 | return this;
|
44 | }
|
45 | /**
|
46 | * Inserts a field reference into the expression; the name will be
|
47 | * automatically escaped.
|
48 | * @param name
|
49 | * @return
|
50 | */
|
51 | field(name) {
|
52 | this._query.push(grammar_1.escape.quoted(name));
|
53 | return this;
|
54 | }
|
55 | /**
|
56 | * Inserts a subexpression; invokes the function with a new expression
|
57 | * that can be chained on.
|
58 | * @param fn
|
59 | * @return
|
60 | * @example
|
61 | * e.field('a').equals.value('b')
|
62 | * .or.expr(e =>
|
63 | * e.field('b').equals.value('b')
|
64 | * .and.field('a').equals.value('c'))
|
65 | * .toString()
|
66 | * // "a" = 'b' OR ("b" = 'b' AND "a" = 'c')
|
67 | */
|
68 | exp(fn) {
|
69 | this._query.push("(" + fn(new Expression()).toString() + ")");
|
70 | return this;
|
71 | }
|
72 | /**
|
73 | * Value chains on a value to the expression.
|
74 | *
|
75 | * - Numbers will be inserted verbatim
|
76 | * - Strings will be escaped and inserted
|
77 | * - Booleans will be inserted correctly
|
78 | * - Dates will be formatted and inserted correctly, including INanoDates.
|
79 | * - Regular expressions will be inserted correctly, however an error will
|
80 | * be thrown if they contain flags, as regex flags do not work in Influx
|
81 | * - Otherwise we'll try to call `.toString()` on the value, throwing
|
82 | * if we cannot do so.
|
83 | *
|
84 | * @param value
|
85 | * @return
|
86 | */
|
87 | value(value) {
|
88 | switch (typeof value) {
|
89 | case "number":
|
90 | this._query.push(value.toString());
|
91 | return this;
|
92 | case "string":
|
93 | this._query.push(grammar_1.escape.stringLit(value));
|
94 | return this;
|
95 | case "boolean":
|
96 | this._query.push(value ? "TRUE" : "FALSE");
|
97 | return this;
|
98 | default:
|
99 | if (value instanceof Date) {
|
100 | this._query.push(grammar_1.formatDate(value));
|
101 | return this;
|
102 | }
|
103 | if (value instanceof RegExp) {
|
104 | if (regexHasFlags(value)) {
|
105 | throw new Error("Attempted to query using a regex with flags, " +
|
106 | "but Influx doesn't support flags in queries.");
|
107 | }
|
108 | this._query.push("/" + value.source + "/");
|
109 | return this;
|
110 | }
|
111 | if (value && typeof value.toString === "function") {
|
112 | this._query.push(value.toString());
|
113 | return this;
|
114 | }
|
115 | throw new Error("node-influx doesn't know how to encode the provided value into a " +
|
116 | "query. If you think this is a bug, open an issue here: https://git.io/influx-err");
|
117 | }
|
118 | }
|
119 | /**
|
120 | * Chains on an AND clause to the expression.
|
121 | */
|
122 | get and() {
|
123 | this._query.push("AND");
|
124 | return this;
|
125 | }
|
126 | /**
|
127 | * Chains on an OR clause to the expression.
|
128 | */
|
129 | get or() {
|
130 | this._query.push("OR");
|
131 | return this;
|
132 | }
|
133 | /**
|
134 | * Chains on a `+` operator to the expression.
|
135 | */
|
136 | get plus() {
|
137 | this._query.push("+");
|
138 | return this;
|
139 | }
|
140 | /**
|
141 | * Chains on a `*` operator to the expression.
|
142 | */
|
143 | get times() {
|
144 | this._query.push("*");
|
145 | return this;
|
146 | }
|
147 | /**
|
148 | * Chains on a `-` operator to the expression.
|
149 | */
|
150 | get minus() {
|
151 | this._query.push("-");
|
152 | return this;
|
153 | }
|
154 | /**
|
155 | * Chains on a `/` operator to the expression.
|
156 | */
|
157 | get div() {
|
158 | this._query.push("/");
|
159 | return this;
|
160 | }
|
161 | /**
|
162 | * Chains on a `=` conditional to the expression.
|
163 | */
|
164 | get equals() {
|
165 | this._query.push("=");
|
166 | return this;
|
167 | }
|
168 | /**
|
169 | * Chains on a `=~` conditional to the expression to match regexes.
|
170 | */
|
171 | get matches() {
|
172 | this._query.push("=~");
|
173 | return this;
|
174 | }
|
175 | /**
|
176 | * Chains on a `!`` conditional to the expression to match regexes.
|
177 | */
|
178 | get doesntMatch() {
|
179 | this._query.push("!~");
|
180 | return this;
|
181 | }
|
182 | /**
|
183 | * Chains on a `!=` conditional to the expression.
|
184 | */
|
185 | get notEqual() {
|
186 | this._query.push("!=");
|
187 | return this;
|
188 | }
|
189 | /**
|
190 | * Chains on a `>` conditional to the expression.
|
191 | */
|
192 | get gt() {
|
193 | this._query.push(">");
|
194 | return this;
|
195 | }
|
196 | /**
|
197 | * Chains on a `>=` conditional to the expression.
|
198 | */
|
199 | get gte() {
|
200 | this._query.push(">=");
|
201 | return this;
|
202 | }
|
203 | /**
|
204 | * Chains on a `<` conditional to the expression.
|
205 | */
|
206 | get lt() {
|
207 | this._query.push("<");
|
208 | return this;
|
209 | }
|
210 | /**
|
211 | * Chains on a `<=` conditional to the expression.
|
212 | */
|
213 | get lte() {
|
214 | this._query.push("<=");
|
215 | return this;
|
216 | }
|
217 | /**
|
218 | * Converts the expression into its InfluxQL representation.
|
219 | * @return
|
220 | */
|
221 | toString() {
|
222 | return this._query.join(" ");
|
223 | }
|
224 | }
|
225 | exports.Expression = Expression;
|
226 | /**
|
227 | * Measurement creates a reference to a particular measurement. You can
|
228 | * reference it solely by its name, but you can also specify the retention
|
229 | * policy and database it lives under.
|
230 | *
|
231 | * @example
|
232 | * m.name('my_measurement') // "my_measurement"
|
233 | * m.name('my_measurement').policy('one_day') // "one_day"."my_measurement"
|
234 | * m.name('my_measurement').policy('one_day').db('mydb') // "mydb"."one_day"."my_measurement"
|
235 | */
|
236 | class Measurement {
|
237 | constructor() {
|
238 | this._parts = [null, null, null];
|
239 | }
|
240 | /**
|
241 | * Sets the measurement name.
|
242 | * @param name
|
243 | * @return
|
244 | */
|
245 | name(name) {
|
246 | this._parts[2] = name;
|
247 | return this;
|
248 | }
|
249 | /**
|
250 | * Sets the retention policy name.
|
251 | * @param retentionPolicy
|
252 | * @return
|
253 | */
|
254 | policy(retentionPolicy) {
|
255 | this._parts[1] = retentionPolicy;
|
256 | return this;
|
257 | }
|
258 | /**
|
259 | * Sets the database name.
|
260 | * @param db
|
261 | * @return
|
262 | */
|
263 | db(db) {
|
264 | this._parts[0] = db;
|
265 | return this;
|
266 | }
|
267 | /**
|
268 | * Converts the measurement into its InfluxQL representation.
|
269 | * @return
|
270 | * @throws {Error} if a measurement name is not provided
|
271 | */
|
272 | toString() {
|
273 | if (!this._parts[2]) {
|
274 | throw new Error(`You must specify a measurement name to query! Got \`${this._parts[2]}\``);
|
275 | }
|
276 | return this._parts
|
277 | .filter((p) => Boolean(p))
|
278 | .map((p) => grammar_1.escape.quoted(p))
|
279 | .join(".");
|
280 | }
|
281 | }
|
282 | exports.Measurement = Measurement;
|
283 | function parseMeasurement(q) {
|
284 | if (typeof q.measurement === "function") {
|
285 | return q.measurement(new Measurement()).toString();
|
286 | }
|
287 | return q.measurement;
|
288 | }
|
289 | exports.parseMeasurement = parseMeasurement;
|
290 | function parseWhere(q) {
|
291 | if (typeof q.where === "function") {
|
292 | return q.where(new Expression()).toString();
|
293 | }
|
294 | return q.where;
|
295 | }
|
296 | exports.parseWhere = parseWhere;
|