mixpanel-browser 2.43.0 → 2.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,508 +0,0 @@
1
- /* eslint camelcase: "off" */
2
-
3
- import {_} from './utils';
4
-
5
- /*
6
- * This file is a js implementation for a subset in eval_node.c
7
- */
8
-
9
- /*
10
- * Constants
11
- */
12
- // Metadata keys
13
- /** @const */ var OPERATOR_KEY = 'operator';
14
- /** @const */ var PROPERTY_KEY = 'property';
15
- /** @const */ var WINDOW_KEY = 'window';
16
- /** @const */ var UNIT_KEY = 'unit';
17
- /** @const */ var VALUE_KEY = 'value';
18
- /** @const */ var HOUR_KEY = 'hour';
19
- /** @const */ var DAY_KEY = 'day';
20
- /** @const */ var WEEK_KEY = 'week';
21
- /** @const */ var MONTH_KEY = 'month';
22
-
23
- // Operands
24
- /** @const */ export var EVENT_PROPERTY = 'event';
25
- /** @const */ export var LITERAL_PROPERTY = 'literal';
26
-
27
- // Binary Operators
28
- /** @const */ export var AND_OPERATOR = 'and';
29
- /** @const */ export var OR_OPERATOR = 'or';
30
- /** @const */ export var IN_OPERATOR = 'in';
31
- /** @const */ export var NOT_IN_OPERATOR = 'not in';
32
- /** @const */ export var PLUS_OPERATOR = '+';
33
- /** @const */ export var MINUS_OPERATOR = '-';
34
- /** @const */ export var MUL_OPERATOR = '*';
35
- /** @const */ export var DIV_OPERATOR = '/';
36
- /** @const */ export var MOD_OPERATOR = '%';
37
- /** @const */ export var EQUALS_OPERATOR = '==';
38
- /** @const */ export var NOT_EQUALS_OPERATOR = '!=';
39
- /** @const */ export var GREATER_OPERATOR = '>';
40
- /** @const */ export var LESS_OPERATOR = '<';
41
- /** @const */ export var GREATER_EQUAL_OPERATOR = '>=';
42
- /** @const */ export var LESS_EQUAL_OPERATOR = '<=';
43
-
44
- // Typecast Operators
45
- /** @const */ export var BOOLEAN_OPERATOR = 'boolean';
46
- /** @const */ export var DATETIME_OPERATOR = 'datetime';
47
- /** @const */ export var LIST_OPERATOR = 'list';
48
- /** @const */ export var NUMBER_OPERATOR = 'number';
49
- /** @const */ export var STRING_OPERATOR = 'string';
50
-
51
- // Unary Operators
52
- /** @const */ export var NOT_OPERATOR = 'not';
53
- /** @const */ export var DEFINED_OPERATOR = 'defined';
54
- /** @const */ export var NOT_DEFINED_OPERATOR = 'not defined';
55
-
56
- // Special literals
57
- /** @const */ export var NOW_LITERAL = 'now';
58
-
59
- // Type cast functions
60
- function toNumber(value) {
61
- if (value === null) {
62
- return null;
63
- }
64
-
65
- switch (typeof(value)) {
66
- case 'object':
67
- if (_.isDate(value) && value.getTime() >= 0) {
68
- return value.getTime();
69
- }
70
- return null;
71
- case 'boolean':
72
- return Number(value);
73
- case 'number':
74
- return value;
75
- case 'string':
76
- value = Number(value);
77
- if (!isNaN(value)) {
78
- return value;
79
- }
80
- return 0;
81
- }
82
- return null;
83
- }
84
-
85
- export function evaluateNumber(op, properties) {
86
- if (!op['operator'] || op['operator'] !== NUMBER_OPERATOR || !op['children'] || op['children'].length !== 1) {
87
- throw ('Invalid cast operator: number ' + op);
88
- }
89
-
90
- return toNumber(evaluateSelector(op['children'][0], properties));
91
- }
92
-
93
- function toBoolean(value) {
94
- if (value === null) {
95
- return false;
96
- }
97
-
98
- switch (typeof value) {
99
- case 'boolean':
100
- return value;
101
- case 'number':
102
- return value !== 0.0;
103
- case 'string':
104
- return value.length > 0;
105
- case 'object':
106
- if (_.isArray(value) && value.length > 0) {
107
- return true;
108
- }
109
- if (_.isDate(value) && value.getTime() > 0) {
110
- return true;
111
- }
112
- if (_.isObject(value) && !_.isEmptyObject(value)) {
113
- return true;
114
- }
115
- return false;
116
- }
117
- return false;
118
- }
119
-
120
- export function evaluateBoolean(op, properties) {
121
- if (!op['operator'] || op['operator'] !== BOOLEAN_OPERATOR || !op['children'] || op['children'].length !== 1) {
122
- throw ('Invalid cast operator: boolean ' + op);
123
- }
124
-
125
- return toBoolean(evaluateSelector(op['children'][0], properties));
126
- }
127
-
128
- export function evaluateDateTime(op, properties) {
129
- if (!op['operator'] || op['operator'] !== DATETIME_OPERATOR || !op['children'] || op['children'].length !== 1) {
130
- throw ('Invalid cast operator: datetime ' + op);
131
- }
132
-
133
- var v = evaluateSelector(op['children'][0], properties);
134
- if (v === null) {
135
- return null;
136
- }
137
-
138
- switch (typeof(v)) {
139
- case 'number':
140
- case 'string':
141
- var d = new Date(v);
142
- if (isNaN(d.getTime())) {
143
- return null;
144
- }
145
- return d;
146
- case 'object':
147
- if (_.isDate(v)) {
148
- return v;
149
- }
150
- }
151
-
152
- return null;
153
- }
154
-
155
- export function evaluateList(op, properties) {
156
- if (!op['operator'] || op['operator'] !== LIST_OPERATOR || !op['children'] || op['children'].length !== 1) {
157
- throw ('Invalid cast operator: list ' + op);
158
- }
159
-
160
- var v = evaluateSelector(op['children'][0], properties);
161
- if (v === null) {
162
- return null;
163
- }
164
-
165
- if (_.isArray(v)) {
166
- return v;
167
- }
168
-
169
- return null;
170
- }
171
-
172
- export function evaluateString(op, properties) {
173
- if (!op['operator'] || op['operator'] !== STRING_OPERATOR || !op['children'] || op['children'].length !== 1) {
174
- throw ('Invalid cast operator: string ' + op);
175
- }
176
-
177
- var v = evaluateSelector(op['children'][0], properties);
178
- switch (typeof(v)) {
179
- case 'object':
180
- if (_.isDate(v)) {
181
- return v.toJSON();
182
- }
183
- return JSON.stringify(v);
184
- }
185
- return String(v);
186
- }
187
-
188
- // Operators
189
- export function evaluateAnd(op, properties) {
190
- if (!op['operator'] || op['operator'] !== AND_OPERATOR || !op['children'] || op['children'].length !== 2) {
191
- throw ('Invalid operator: AND ' + op);
192
- }
193
-
194
- return toBoolean(evaluateSelector(op['children'][0], properties)) && toBoolean(evaluateSelector(op['children'][1], properties));
195
- }
196
-
197
- export function evaluateOr(op, properties) {
198
- if (!op['operator'] || op['operator'] !== OR_OPERATOR || !op['children'] || op['children'].length !== 2) {
199
- throw ('Invalid operator: OR ' + op);
200
- }
201
-
202
- return toBoolean(evaluateSelector(op['children'][0], properties)) || toBoolean(evaluateSelector(op['children'][1], properties));
203
- }
204
-
205
- export function evaluateIn(op, properties) {
206
- if (!op['operator'] || [IN_OPERATOR, NOT_IN_OPERATOR].indexOf(op['operator']) === -1 || !op['children'] || op['children'].length !== 2) {
207
- throw ('Invalid operator: IN/NOT IN ' + op);
208
- }
209
- var leftValue = evaluateSelector(op['children'][0], properties);
210
- var rightValue = evaluateSelector(op['children'][1], properties);
211
-
212
- if (!_.isArray(rightValue) && !_.isString(rightValue)) {
213
- throw ('Invalid operand for operator IN: invalid type' + rightValue);
214
- }
215
-
216
- var v = rightValue.indexOf(leftValue) > -1;
217
- if (op['operator'] === NOT_IN_OPERATOR) {
218
- return !v;
219
- }
220
- return v;
221
- }
222
-
223
- export function evaluatePlus(op, properties) {
224
- if (!op['operator'] || op['operator'] !== PLUS_OPERATOR || !op['children'] || op['children'].length < 2) {
225
- throw ('Invalid operator: PLUS ' + op);
226
- }
227
- var l = evaluateSelector(op['children'][0], properties);
228
- var r = evaluateSelector(op['children'][1], properties);
229
-
230
- if (typeof l === 'number' && typeof r === 'number') {
231
- return l + r;
232
- }
233
- if (typeof l === 'string' && typeof r === 'string') {
234
- return l + r;
235
- }
236
- return null;
237
- }
238
-
239
- export function evaluateArithmetic(op, properties) {
240
- if (!op['operator'] || [MINUS_OPERATOR, MUL_OPERATOR, DIV_OPERATOR, MOD_OPERATOR].indexOf(op['operator']) === -1 ||
241
- !op['children'] || op['children'].length < 2) {
242
- throw ('Invalid arithmetic operator ' + op);
243
- }
244
-
245
- var l = evaluateSelector(op['children'][0], properties);
246
- var r = evaluateSelector(op['children'][1], properties);
247
-
248
- if (typeof l === 'number' && typeof r === 'number') {
249
- switch (op['operator']) {
250
- case MINUS_OPERATOR:
251
- return l - r;
252
- case MUL_OPERATOR:
253
- return l * r;
254
- case DIV_OPERATOR:
255
- if (r !== 0) {
256
- return l / r;
257
- }
258
- return null;
259
- case MOD_OPERATOR:
260
- if (r === 0) {
261
- return null;
262
- }
263
- if (l === 0) {
264
- return 0;
265
- }
266
- if ((l < 0 && r > 0) || (l > 0 && r < 0)) {
267
- /* Mimic python modulo - result takes sign of the divisor
268
- * if one operand is negative. */
269
- return -(Math.floor(l / r) * r - l);
270
- }
271
- return l % r;
272
- default:
273
- throw('Unknown operator: ' + op['operator']);
274
- }
275
- }
276
-
277
- return null;
278
- }
279
-
280
- function _isArrayEqual(l, r) {
281
- if (l === r) return true;
282
- if (l === null || r === null) return false;
283
- if (l.length !== r.length) return false;
284
-
285
- for (var i = 0; i < l.length; i++) {
286
- if (l[i] !== r[i]) {
287
- return false;
288
- }
289
- }
290
-
291
- return true;
292
- }
293
-
294
- function _isEqual(l, r) {
295
- if ( l === null && l === r ) {
296
- return true;
297
- }
298
- if (typeof l === typeof r) {
299
- switch (typeof l) {
300
- case 'number':
301
- case 'string':
302
- case 'boolean':
303
- return l === r;
304
- case 'object':
305
- if (_.isArray(l) && _.isArray(r)) {
306
- return _isArrayEqual(l, r);
307
- }
308
- if (_.isDate(l) && _.isDate(r)) {
309
- return l.getTime() === r.getTime();
310
- }
311
- if (_.isObject(l) && _.isObject(r)) {
312
- return JSON.stringify(l) === JSON.stringify(r);
313
- }
314
- }
315
- }
316
- return false;
317
- }
318
-
319
- export function evaluateEquality(op, properties) {
320
- if (!op['operator'] || [EQUALS_OPERATOR, NOT_EQUALS_OPERATOR].indexOf(op['operator']) === -1 || !op['children'] || op['children'].length !== 2) {
321
- throw ('Invalid equality operator ' + op);
322
- }
323
-
324
- var v = _isEqual(evaluateSelector(op['children'][0], properties), evaluateSelector(op['children'][1], properties));
325
-
326
- switch (op['operator']) {
327
- case EQUALS_OPERATOR:
328
- return v;
329
- case NOT_EQUALS_OPERATOR:
330
- return !v;
331
- }
332
- }
333
-
334
- export function evaluateComparison(op, properties) {
335
- if (!op['operator'] ||
336
- [GREATER_OPERATOR, GREATER_EQUAL_OPERATOR, LESS_OPERATOR, LESS_EQUAL_OPERATOR].indexOf(op['operator']) === -1 ||
337
- !op['children'] || op['children'].length !== 2) {
338
- throw ('Invalid comparison operator ' + op);
339
- }
340
- var l = evaluateSelector(op['children'][0], properties);
341
- var r = evaluateSelector(op['children'][1], properties);
342
-
343
- if (typeof(l) === typeof(r)) {
344
- if (typeof(r) === 'number' || _.isDate(r)) {
345
- l = toNumber(l);
346
- r = toNumber(r);
347
- switch (op['operator']) {
348
- case GREATER_OPERATOR:
349
- return l > r;
350
- case GREATER_EQUAL_OPERATOR:
351
- return l >= r;
352
- case LESS_OPERATOR:
353
- return l < r;
354
- case LESS_EQUAL_OPERATOR:
355
- return l <= r;
356
- }
357
- } else if (typeof(r) === 'string') {
358
- var compare = l.localeCompare(r);
359
- switch (op['operator']) {
360
- case GREATER_OPERATOR:
361
- return compare > 0;
362
- case GREATER_EQUAL_OPERATOR:
363
- return compare >= 0;
364
- case LESS_OPERATOR:
365
- return compare < 0;
366
- case LESS_EQUAL_OPERATOR:
367
- return compare <= 0;
368
- }
369
- }
370
- }
371
-
372
- return null;
373
- }
374
-
375
- export function evaluateDefined(op, properties) {
376
- if (!op['operator'] || [DEFINED_OPERATOR, NOT_DEFINED_OPERATOR].indexOf(op['operator']) === -1 ||
377
- !op['children'] || op['children'].length !== 1) {
378
- throw ('Invalid defined/not defined operator: ' + op);
379
- }
380
-
381
- var b = evaluateSelector(op['children'][0], properties) !== null;
382
- if (op['operator'] === NOT_DEFINED_OPERATOR) {
383
- return !b;
384
- }
385
-
386
- return b;
387
- }
388
-
389
- export function evaluateNot(op, properties) {
390
- if (!op['operator'] || op['operator'] !== NOT_OPERATOR || !op['children'] || op['children'].length !== 1) {
391
- throw ('Invalid not operator: ' + op);
392
- }
393
-
394
- var v = evaluateSelector(op['children'][0], properties);
395
- if (v === null) {
396
- return true;
397
- }
398
-
399
- if (typeof(v) === 'boolean') {
400
- return !v;
401
- }
402
-
403
- return null;
404
- }
405
-
406
- export function evaluateOperator(op, properties) {
407
- if (!op['operator']) {
408
- throw ('Invalid operator: operator key missing ' + op);
409
- }
410
-
411
- switch (op['operator']) {
412
- case AND_OPERATOR:
413
- return evaluateAnd(op, properties);
414
- case OR_OPERATOR:
415
- return evaluateOr(op, properties);
416
- case IN_OPERATOR:
417
- case NOT_IN_OPERATOR:
418
- return evaluateIn(op, properties);
419
- case PLUS_OPERATOR:
420
- return evaluatePlus(op, properties);
421
- case MINUS_OPERATOR:
422
- case MUL_OPERATOR:
423
- case DIV_OPERATOR:
424
- case MOD_OPERATOR:
425
- return evaluateArithmetic(op, properties);
426
- case EQUALS_OPERATOR:
427
- case NOT_EQUALS_OPERATOR:
428
- return evaluateEquality(op, properties);
429
- case GREATER_OPERATOR:
430
- case LESS_OPERATOR:
431
- case GREATER_EQUAL_OPERATOR:
432
- case LESS_EQUAL_OPERATOR:
433
- return evaluateComparison(op, properties);
434
- case BOOLEAN_OPERATOR:
435
- return evaluateBoolean(op, properties);
436
- case DATETIME_OPERATOR:
437
- return evaluateDateTime(op, properties);
438
- case LIST_OPERATOR:
439
- return evaluateList(op, properties);
440
- case NUMBER_OPERATOR:
441
- return evaluateNumber(op, properties);
442
- case STRING_OPERATOR:
443
- return evaluateString(op, properties);
444
- case DEFINED_OPERATOR:
445
- case NOT_DEFINED_OPERATOR:
446
- return evaluateDefined(op, properties);
447
- case NOT_OPERATOR:
448
- return evaluateNot(op, properties);
449
- }
450
- }
451
-
452
- export function evaluateWindow(value) {
453
- var win = value[WINDOW_KEY];
454
- if (!win || !win[UNIT_KEY] || !win[VALUE_KEY]) {
455
- throw('Invalid window: missing required keys ' + JSON.stringify(value));
456
- }
457
- var out = new Date();
458
- switch (win[UNIT_KEY]) {
459
- case HOUR_KEY:
460
- out.setTime(out.getTime() + (win[VALUE_KEY]*-1*60*60*1000));
461
- break;
462
- case DAY_KEY:
463
- out.setTime(out.getTime() + (win[VALUE_KEY]*-1*24*60*60*1000));
464
- break;
465
- case WEEK_KEY:
466
- out.setTime(out.getTime() + (win[VALUE_KEY]*-1*7*24*60*60*1000));
467
- break;
468
- case MONTH_KEY:
469
- out.setTime(out.getTime() + (win[VALUE_KEY]*-1*30*24*60*60*1000));
470
- break;
471
- default:
472
- throw('Invalid unit: ' + win[UNIT_KEY]);
473
- }
474
-
475
- return out;
476
- }
477
-
478
- export function evaluateOperand(op, properties) {
479
- if (!op['property'] || !op['value']) {
480
- throw('Invalid operand: missing required keys ' + op);
481
- }
482
- switch (op['property']) {
483
- case EVENT_PROPERTY:
484
- if (properties[op['value']] !== undefined) {
485
- return properties[op['value']];
486
- }
487
- return null;
488
- case LITERAL_PROPERTY:
489
- if (op['value'] === NOW_LITERAL) {
490
- return new Date();
491
- }
492
- if (typeof(op['value']) === 'object') {
493
- return evaluateWindow(op['value']);
494
- }
495
- return op['value'];
496
- default:
497
- throw('Invalid operand: Invalid property type ' + op['property']);
498
- }
499
- }
500
-
501
- export function evaluateSelector(filters, properties) {
502
- if (filters[PROPERTY_KEY]) {
503
- return evaluateOperand(filters, properties);
504
- }
505
- if (filters[OPERATOR_KEY]) {
506
- return evaluateOperator(filters, properties);
507
- }
508
- }