@quillsql/react 2.10.39 → 2.11.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.
Files changed (123) hide show
  1. package/dist/cjs/Chart.d.ts +4 -0
  2. package/dist/cjs/Chart.d.ts.map +1 -1
  3. package/dist/cjs/Chart.js +5 -5
  4. package/dist/cjs/ChartBuilder.js +2 -2
  5. package/dist/cjs/Context.d.ts +1 -1
  6. package/dist/cjs/Context.d.ts.map +1 -1
  7. package/dist/cjs/Context.js +3 -1
  8. package/dist/cjs/Dashboard.d.ts +3 -1
  9. package/dist/cjs/Dashboard.d.ts.map +1 -1
  10. package/dist/cjs/Dashboard.js +4 -4
  11. package/dist/cjs/QuillProvider.d.ts +3 -1
  12. package/dist/cjs/QuillProvider.d.ts.map +1 -1
  13. package/dist/cjs/QuillProvider.js +2 -2
  14. package/dist/cjs/ReportBuilder.d.ts +40 -40
  15. package/dist/cjs/ReportBuilder.d.ts.map +1 -1
  16. package/dist/cjs/ReportBuilder.js +2026 -917
  17. package/dist/cjs/components/Chart/LineChart.d.ts +5 -1
  18. package/dist/cjs/components/Chart/LineChart.d.ts.map +1 -1
  19. package/dist/cjs/components/Chart/LineChart.js +18 -6
  20. package/dist/cjs/components/QuillTable.d.ts +1 -1
  21. package/dist/cjs/components/QuillTable.d.ts.map +1 -1
  22. package/dist/cjs/components/QuillTable.js +157 -157
  23. package/dist/cjs/components/ReportBuilder/AddColumnPopover.d.ts +2 -0
  24. package/dist/cjs/components/ReportBuilder/AddColumnPopover.d.ts.map +1 -0
  25. package/dist/cjs/components/ReportBuilder/AddColumnPopover.js +128 -0
  26. package/dist/cjs/components/ReportBuilder/ast.d.ts +512 -0
  27. package/dist/cjs/components/ReportBuilder/ast.d.ts.map +1 -0
  28. package/dist/cjs/components/ReportBuilder/ast.js +210 -0
  29. package/dist/cjs/components/ReportBuilder/bigDateMap.d.ts +7 -0
  30. package/dist/cjs/components/ReportBuilder/bigDateMap.d.ts.map +1 -0
  31. package/dist/cjs/components/ReportBuilder/bigDateMap.js +689 -0
  32. package/dist/cjs/components/ReportBuilder/constants.d.ts +89 -0
  33. package/dist/cjs/components/ReportBuilder/constants.d.ts.map +1 -0
  34. package/dist/cjs/components/ReportBuilder/constants.js +130 -0
  35. package/dist/cjs/components/ReportBuilder/convert.d.ts +41 -0
  36. package/dist/cjs/components/ReportBuilder/convert.d.ts.map +1 -0
  37. package/dist/cjs/components/ReportBuilder/convert.js +730 -0
  38. package/dist/cjs/components/ReportBuilder/operators.d.ts +445 -0
  39. package/dist/cjs/components/ReportBuilder/operators.d.ts.map +1 -0
  40. package/dist/cjs/components/ReportBuilder/operators.js +552 -0
  41. package/dist/cjs/components/ReportBuilder/pivot.d.ts +10 -0
  42. package/dist/cjs/components/ReportBuilder/pivot.d.ts.map +1 -0
  43. package/dist/cjs/components/ReportBuilder/pivot.js +2 -0
  44. package/dist/cjs/components/ReportBuilder/postgres.d.ts +150 -0
  45. package/dist/cjs/components/ReportBuilder/postgres.d.ts.map +1 -0
  46. package/dist/cjs/components/ReportBuilder/postgres.js +365 -0
  47. package/dist/cjs/components/ReportBuilder/schema.d.ts +23 -0
  48. package/dist/cjs/components/ReportBuilder/schema.d.ts.map +1 -0
  49. package/dist/cjs/components/ReportBuilder/schema.js +2 -0
  50. package/dist/cjs/components/ReportBuilder/ui.d.ts +34 -0
  51. package/dist/cjs/components/ReportBuilder/ui.d.ts.map +1 -0
  52. package/dist/cjs/components/ReportBuilder/ui.js +389 -0
  53. package/dist/cjs/components/ReportBuilder/util.d.ts +76 -0
  54. package/dist/cjs/components/ReportBuilder/util.d.ts.map +1 -0
  55. package/dist/cjs/components/ReportBuilder/util.js +648 -0
  56. package/dist/cjs/components/UiComponents.d.ts +15 -2
  57. package/dist/cjs/components/UiComponents.d.ts.map +1 -1
  58. package/dist/cjs/components/UiComponents.js +50 -3
  59. package/dist/cjs/utils/crypto.d.ts +1 -1
  60. package/dist/cjs/utils/crypto.d.ts.map +1 -1
  61. package/dist/cjs/utils/crypto.js +9 -5
  62. package/dist/esm/Chart.d.ts +4 -0
  63. package/dist/esm/Chart.d.ts.map +1 -1
  64. package/dist/esm/Chart.js +5 -5
  65. package/dist/esm/ChartBuilder.js +1 -1
  66. package/dist/esm/Context.d.ts +1 -1
  67. package/dist/esm/Context.d.ts.map +1 -1
  68. package/dist/esm/Context.js +3 -1
  69. package/dist/esm/Dashboard.d.ts +3 -1
  70. package/dist/esm/Dashboard.d.ts.map +1 -1
  71. package/dist/esm/Dashboard.js +4 -4
  72. package/dist/esm/QuillProvider.d.ts +3 -1
  73. package/dist/esm/QuillProvider.d.ts.map +1 -1
  74. package/dist/esm/QuillProvider.js +2 -2
  75. package/dist/esm/ReportBuilder.d.ts +40 -40
  76. package/dist/esm/ReportBuilder.d.ts.map +1 -1
  77. package/dist/esm/ReportBuilder.js +2028 -917
  78. package/dist/esm/components/Chart/LineChart.d.ts +5 -1
  79. package/dist/esm/components/Chart/LineChart.d.ts.map +1 -1
  80. package/dist/esm/components/Chart/LineChart.js +18 -6
  81. package/dist/esm/components/QuillTable.d.ts +1 -1
  82. package/dist/esm/components/QuillTable.d.ts.map +1 -1
  83. package/dist/esm/components/QuillTable.js +157 -157
  84. package/dist/esm/components/ReportBuilder/AddColumnPopover.d.ts +2 -0
  85. package/dist/esm/components/ReportBuilder/AddColumnPopover.d.ts.map +1 -0
  86. package/dist/esm/components/ReportBuilder/AddColumnPopover.js +125 -0
  87. package/dist/esm/components/ReportBuilder/ast.d.ts +512 -0
  88. package/dist/esm/components/ReportBuilder/ast.d.ts.map +1 -0
  89. package/dist/esm/components/ReportBuilder/ast.js +186 -0
  90. package/dist/esm/components/ReportBuilder/bigDateMap.d.ts +7 -0
  91. package/dist/esm/components/ReportBuilder/bigDateMap.d.ts.map +1 -0
  92. package/dist/esm/components/ReportBuilder/bigDateMap.js +686 -0
  93. package/dist/esm/components/ReportBuilder/constants.d.ts +89 -0
  94. package/dist/esm/components/ReportBuilder/constants.d.ts.map +1 -0
  95. package/dist/esm/components/ReportBuilder/constants.js +127 -0
  96. package/dist/esm/components/ReportBuilder/convert.d.ts +41 -0
  97. package/dist/esm/components/ReportBuilder/convert.d.ts.map +1 -0
  98. package/dist/esm/components/ReportBuilder/convert.js +719 -0
  99. package/dist/esm/components/ReportBuilder/operators.d.ts +445 -0
  100. package/dist/esm/components/ReportBuilder/operators.d.ts.map +1 -0
  101. package/dist/esm/components/ReportBuilder/operators.js +548 -0
  102. package/dist/esm/components/ReportBuilder/pivot.d.ts +10 -0
  103. package/dist/esm/components/ReportBuilder/pivot.d.ts.map +1 -0
  104. package/dist/esm/components/ReportBuilder/pivot.js +1 -0
  105. package/dist/esm/components/ReportBuilder/postgres.d.ts +150 -0
  106. package/dist/esm/components/ReportBuilder/postgres.d.ts.map +1 -0
  107. package/dist/esm/components/ReportBuilder/postgres.js +355 -0
  108. package/dist/esm/components/ReportBuilder/schema.d.ts +23 -0
  109. package/dist/esm/components/ReportBuilder/schema.d.ts.map +1 -0
  110. package/dist/esm/components/ReportBuilder/schema.js +1 -0
  111. package/dist/esm/components/ReportBuilder/ui.d.ts +34 -0
  112. package/dist/esm/components/ReportBuilder/ui.d.ts.map +1 -0
  113. package/dist/esm/components/ReportBuilder/ui.js +366 -0
  114. package/dist/esm/components/ReportBuilder/util.d.ts +76 -0
  115. package/dist/esm/components/ReportBuilder/util.d.ts.map +1 -0
  116. package/dist/esm/components/ReportBuilder/util.js +616 -0
  117. package/dist/esm/components/UiComponents.d.ts +15 -2
  118. package/dist/esm/components/UiComponents.d.ts.map +1 -1
  119. package/dist/esm/components/UiComponents.js +47 -2
  120. package/dist/esm/utils/crypto.d.ts +1 -1
  121. package/dist/esm/utils/crypto.d.ts.map +1 -1
  122. package/dist/esm/utils/crypto.js +9 -5
  123. package/package.json +1 -1
@@ -0,0 +1,648 @@
1
+ "use strict";
2
+ // A collection of reusable, pure, utility functions for the Report Builder.
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.getDateFilterInfo = exports.trimEndS = exports.deepCopy = exports.getPostgresBasicType = exports.showNodeAsRow = exports.isExtractEquals = exports.isDateTruncEquals = exports.tryConvertDateEquality = exports.extractSuffixToString = exports.dateTruncSuffixToString = exports.newUTCDate = exports.isColumnComparison = exports.isTheCurrentIntervalBigQuery = exports.isThePreviousInterval = exports.isTheCurrentInterval = exports.isInTheLastIntervalBigQuery = exports.isInTheLastInterval = exports.getInThePreviousIntervalSentence = exports.getInTheLastIntervalSentence = exports.getInTheCurrentIntervalSentence = exports.formatDateComparisonNode = exports.areObjectsEqualish = exports.isColumnDateish = exports.generateColumnExpr = exports.isColumnReferenceish = exports.isDateTrunc = exports.hasTopLevelOrBoolean = exports.isTopLevelBoolean = exports.isNodeEmptyCollection = void 0;
5
+ const date_fns_1 = require("date-fns");
6
+ const bigDateMap_1 = require("./bigDateMap");
7
+ /**
8
+ * A node that is "in" or "not in" where none of the variants are selected.
9
+ */
10
+ const isNodeEmptyCollection = (node) => {
11
+ return (['IN', 'NOT IN'].includes(node.operator) &&
12
+ node.right.type === 'expr_list' &&
13
+ node.right.value.length === 1 &&
14
+ node.right.value[0].type === 'function' &&
15
+ ['lower', 'upper'].includes(node.right.value[0].name.toLowerCase()) &&
16
+ node.right.value[0].args.type === 'expr_list' &&
17
+ node.right.value[0].args.value.length === 1 &&
18
+ node.right.value[0].args.value[0].value === '');
19
+ };
20
+ exports.isNodeEmptyCollection = isNodeEmptyCollection;
21
+ function isTopLevelBoolean(node) {
22
+ // override normal logic for conditions added by users
23
+ if (node.isCondition !== undefined) {
24
+ return true;
25
+ }
26
+ if (!node.parentheses &&
27
+ node.type === 'binary_expr' &&
28
+ (node.operator === 'AND' || node.operator === 'OR')) {
29
+ return true;
30
+ }
31
+ return false;
32
+ }
33
+ exports.isTopLevelBoolean = isTopLevelBoolean;
34
+ function hasTopLevelOrBoolean(ast) {
35
+ if (ast.where && ast.where.operator === 'OR') {
36
+ return true;
37
+ }
38
+ return false;
39
+ }
40
+ exports.hasTopLevelOrBoolean = hasTopLevelOrBoolean;
41
+ // Returns whether the node is a date_trunc function.
42
+ const isDateTrunc = (node) => {
43
+ try {
44
+ return node &&
45
+ node.type === 'function' &&
46
+ node.name === 'date_trunc' &&
47
+ node.args &&
48
+ node.args.type === 'expr_list' &&
49
+ node.args?.value.length === 2 &&
50
+ node.args?.value[0].type === 'single_quote_string' &&
51
+ // The right-side value can either be a double-quoted string literal or
52
+ // a cast to some sort of date-ish type. We handle these variants:
53
+ // -> date_trunc('month', '2024-01-01'::DATE)
54
+ // -> date_trunc('month', "2024-01-01")
55
+ // -> date_trunc('month', TIMESTAMP '2024-01-01')
56
+ // -> date_trunc('month', DATE '2024-01-01')
57
+ node.args?.value[1].type === 'cast'
58
+ ? node.args?.value[1].expr.type === 'single_quote_string'
59
+ : ['timestamp', 'date', 'column_ref', 'double_quote_string'].includes(node.args?.value[1].type);
60
+ }
61
+ catch (e) {
62
+ return false;
63
+ }
64
+ };
65
+ exports.isDateTrunc = isDateTrunc;
66
+ // Returns whether the given node is a raw column reference.
67
+ // TODO: This is a helpful function, let's use it!
68
+ // eslint-disable-next-line no-unused-vars
69
+ const isColumnReferenceish = (node) => {
70
+ return node && ['column_ref', 'double_quote_string'].includes(node.type);
71
+ };
72
+ exports.isColumnReferenceish = isColumnReferenceish;
73
+ function generateColumnExpr(name) {
74
+ return {
75
+ type: 'expr',
76
+ expr: {
77
+ type: 'column_ref',
78
+ table: null,
79
+ column: name,
80
+ },
81
+ as: null,
82
+ };
83
+ }
84
+ exports.generateColumnExpr = generateColumnExpr;
85
+ // Returns whether this column node is either a date_trunc or extract
86
+ // function which implies that it is some sort of date/timestamp type.
87
+ // TODO: replace me with actual code that checks against dbtype.
88
+ const isColumnDateish = (col) => {
89
+ return (col &&
90
+ col?.expr?.type === 'function' &&
91
+ ['date_trunc', 'extract'].includes(col?.expr?.name?.toLowerCase()));
92
+ };
93
+ exports.isColumnDateish = isColumnDateish;
94
+ function areObjectsEqualish(left, right) {
95
+ if (left === null || right === null)
96
+ return false;
97
+ if (left === undefined || right === undefined)
98
+ return false;
99
+ if (typeof left !== 'object' || typeof right !== 'object')
100
+ return false;
101
+ for (const [key, value] of Object.entries(left)) {
102
+ if (typeof value === 'string') {
103
+ if (!right[key])
104
+ return false;
105
+ if (right[key].toLowerCase() !== value.toLowerCase())
106
+ return false;
107
+ }
108
+ else if (typeof value === 'object') {
109
+ if (!areObjectsEqualish(value, right[key]))
110
+ return false;
111
+ }
112
+ else if (!value) {
113
+ if (!right[key])
114
+ return false;
115
+ }
116
+ else {
117
+ console.error('unknown type: ', typeof value);
118
+ }
119
+ }
120
+ return true;
121
+ }
122
+ exports.areObjectsEqualish = areObjectsEqualish;
123
+ function formatDateComparisonNode(node) {
124
+ for (const [key, callback] of Object.entries(bigDateMap_1.DATE_DESCRIPTION_MAP)) {
125
+ const partialObject = JSON.parse(key);
126
+ if (areObjectsEqualish(partialObject, node)) {
127
+ return callback(node);
128
+ }
129
+ }
130
+ return null;
131
+ }
132
+ exports.formatDateComparisonNode = formatDateComparisonNode;
133
+ function getInTheCurrentIntervalSentence(node, databaseType) {
134
+ if (databaseType === 'BigQuery') {
135
+ const dateColumn = node.left.args.value[0].column;
136
+ const periodValue = node.left.args.value[1].column.toLowerCase();
137
+ return `${dateColumn} in the current ${periodValue}`;
138
+ }
139
+ return null;
140
+ }
141
+ exports.getInTheCurrentIntervalSentence = getInTheCurrentIntervalSentence;
142
+ const BIG_QUERY_DAY_TO_INTERVAL_MAP = {
143
+ '* 365 day': 'year',
144
+ '* 30 day': 'month',
145
+ '* 7 day': 'week',
146
+ };
147
+ function getInTheLastIntervalSentence(node, databaseType) {
148
+ if (databaseType === 'BigQuery') {
149
+ const dateColumn = node.left.column;
150
+ const amount = node.right.args.value[1].expr.value;
151
+ let unit = node.right.args.value[1].unit.toLowerCase();
152
+ if (unit.includes('*')) {
153
+ unit = BIG_QUERY_DAY_TO_INTERVAL_MAP[unit];
154
+ }
155
+ return `${dateColumn} in the last ${amount} ${unit}${amount > 1 ? 's' : ''}`;
156
+ }
157
+ return null;
158
+ }
159
+ exports.getInTheLastIntervalSentence = getInTheLastIntervalSentence;
160
+ function getInThePreviousIntervalSentence(node, databaseType) {
161
+ if (databaseType === 'BigQuery') {
162
+ const dateColumn = node.left.args.value[0].column;
163
+ const periodValue = node.left.args.value[1].column.toLowerCase();
164
+ return `${dateColumn} in the previous ${periodValue}`;
165
+ }
166
+ return null;
167
+ }
168
+ exports.getInThePreviousIntervalSentence = getInThePreviousIntervalSentence;
169
+ // "created_at" >= date_trunc ('year', CURRENT_DATE) - INTERVAL '1 year'
170
+ // or
171
+ // "created_at" >= CURRENT_DATE - INTERVAL '1 year'
172
+ // in the last year aka one interval from today
173
+ const isInTheLastInterval = (node, databaseType) => {
174
+ if (databaseType.toLowerCase() === 'bigquery') {
175
+ return (0, exports.isInTheLastIntervalBigQuery)(node);
176
+ }
177
+ const isOutsideOfDateTrunc = ['>=', '>'].includes(node.operator) &&
178
+ node.left.type === 'column_ref' &&
179
+ node.right.type === 'binary_expr' &&
180
+ node.right.operator === '-' &&
181
+ node.right.left.type === 'function' &&
182
+ node.right.left.name.toLowerCase() === 'date_trunc' &&
183
+ node.right.left.args.value[0].type === 'single_quote_string' &&
184
+ node.right.left.args.value[1].type === 'function' &&
185
+ ['current_date', 'now'].includes(node.right.left.args.value[1].name.toLowerCase()) &&
186
+ node.right.right.type.toLowerCase() === 'interval' &&
187
+ node.right.right.expr.type === 'single_quote_string';
188
+ const noDateTrunc = ['>=', '>'].includes(node.operator) &&
189
+ node.left.type === 'column_ref' &&
190
+ node.right.type === 'binary_expr' &&
191
+ node.right.operator === '-' &&
192
+ node.right.left.type === 'function' &&
193
+ ['current_date', 'now'].includes(node.right.left.name.toLowerCase()) &&
194
+ node.right.right.type.toLowerCase() === 'interval' &&
195
+ node.right.right.expr.type === 'single_quote_string';
196
+ return isOutsideOfDateTrunc || noDateTrunc;
197
+ };
198
+ exports.isInTheLastInterval = isInTheLastInterval;
199
+ // created_at >= DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH)
200
+ // in the last month aka one interval from today
201
+ const isInTheLastIntervalBigQuery = (node) => {
202
+ const isOutsideOfDateTrunc = ['>=', '>'].includes(node.operator) &&
203
+ node.left.type === 'column_ref' &&
204
+ node.right.type === 'function' &&
205
+ node.right.name.toLowerCase() === 'timestamp_sub' &&
206
+ node.right.args.value[0].type === 'function' &&
207
+ node.right.args.value[1].type === 'interval' &&
208
+ ['current_timestamp'].includes(node.right.args.value[0].name.toLowerCase());
209
+ return isOutsideOfDateTrunc;
210
+ };
211
+ exports.isInTheLastIntervalBigQuery = isInTheLastIntervalBigQuery;
212
+ // "created_at" >= date_trunc ('year', CURRENT_DATE - INTERVAL '1 year')
213
+ // this year
214
+ const isTheCurrentInterval = (node, databaseType) => {
215
+ if (databaseType.toLowerCase() === 'bigquery') {
216
+ return (0, exports.isTheCurrentIntervalBigQuery)(node);
217
+ }
218
+ const isInsideOfDateTrunc = ['AND'].includes(node.operator) &&
219
+ (node.left.operator === '=' || node.left.type === 'double_quote_string') &&
220
+ node.right.operator === '=' &&
221
+ node.right.name.toLowerCase() === 'date_trunc' &&
222
+ node.args.value[0].type === 'single_quote_string' &&
223
+ node.args.value[1].type === 'binary_expr' &&
224
+ node.args.value[1].operator === '-' &&
225
+ node.args.value[1].left.type === 'function' &&
226
+ ['now', 'current_date'].includes(node.args.value[1].left.name.toLowerCase()) &&
227
+ node.args.value[1].right.type === 'interval' &&
228
+ node.args.value[1].right.expr.type === 'single_quote_string';
229
+ return isInsideOfDateTrunc;
230
+ };
231
+ exports.isTheCurrentInterval = isTheCurrentInterval;
232
+ const isThePreviousInterval = (node, databaseType) => {
233
+ const isInsideOfDateTrunc = ['='].includes(node.operator) &&
234
+ node.left.name &&
235
+ node.left.name.toLowerCase() === 'timestamp_trunc' &&
236
+ node.left.type === 'function' &&
237
+ node.right.name &&
238
+ node.right.name.toLowerCase() === 'timestamp_trunc' &&
239
+ node.right.args.value[0].name.toLowerCase() === 'timestamp_sub' &&
240
+ node.right.args.value[0].args.value[0].name.toLowerCase() ===
241
+ 'current_timestamp';
242
+ return isInsideOfDateTrunc;
243
+ };
244
+ exports.isThePreviousInterval = isThePreviousInterval;
245
+ const isTheCurrentIntervalBigQuery = (node) => {
246
+ const isInsideOfDateTrunc = ['='].includes(node.operator) &&
247
+ node.left.type === 'function' &&
248
+ node.left.name &&
249
+ node.left.name.toLowerCase() === 'timestamp_trunc' &&
250
+ node.right.type === 'function' &&
251
+ node.right.name.toLowerCase() === 'timestamp_trunc' &&
252
+ node.right.args.value[0].name.toLowerCase() === 'current_timestamp';
253
+ return isInsideOfDateTrunc;
254
+ };
255
+ exports.isTheCurrentIntervalBigQuery = isTheCurrentIntervalBigQuery;
256
+ /**
257
+ * Returns whether this node is the root of a binary expression
258
+ * where the left child is a string but really should be
259
+ * interpreted as a column name.
260
+ */
261
+ const isColumnComparison = (node) => {
262
+ const ops = [
263
+ '>=',
264
+ '>',
265
+ '<=',
266
+ '<',
267
+ 'AND',
268
+ 'OR',
269
+ '!=',
270
+ '=',
271
+ 'LIKE',
272
+ 'NOT LIKE',
273
+ 'IN',
274
+ 'NOT IN',
275
+ 'BETWEEN',
276
+ '-',
277
+ '+',
278
+ 'IS NOT',
279
+ 'IS',
280
+ ];
281
+ return (ops.includes(node.operator) &&
282
+ node.left &&
283
+ (node.left.type === 'column_ref' ||
284
+ node.left.type === 'double_quote_string' ||
285
+ (node.left.type === 'function' &&
286
+ ['lower', 'upper'].includes(node.left.name.toLowerCase()))));
287
+ };
288
+ exports.isColumnComparison = isColumnComparison;
289
+ // Returns a new date object with timezone adjusted
290
+ const newUTCDate = (dateString) => {
291
+ let date = new Date(dateString);
292
+ // If the date is invalid, try appending a 1 (eg. "April" => "April 1")
293
+ if (Number.isNaN(date.getDate())) {
294
+ date = new Date(`${dateString} 1`);
295
+ }
296
+ date.setMinutes(date.getMinutes() + date.getTimezoneOffset()); // TZ adjust
297
+ // Default to using the current year, unless explicitly overridden
298
+ const dateYear = date.getFullYear();
299
+ if (!dateString.includes(dateYear.toString())) {
300
+ date.setFullYear(new Date().getFullYear());
301
+ }
302
+ return date;
303
+ };
304
+ exports.newUTCDate = newUTCDate;
305
+ const getPeriod = (node, databaseType) => {
306
+ if (databaseType === 'BigQuery') {
307
+ return node.left.args.value[1]?.column.toLowerCase();
308
+ }
309
+ else {
310
+ return node.left.args.value[0]?.value.toLowerCase();
311
+ }
312
+ };
313
+ const getRawDateStr = (node, databaseType) => {
314
+ if (databaseType === 'BigQuery') {
315
+ return node.right.value;
316
+ }
317
+ else {
318
+ const dateNode = node.right.value ? node.right : node.right.args.value[1];
319
+ return dateNode.type === 'cast' ? dateNode.expr.value : dateNode.value;
320
+ }
321
+ };
322
+ /**
323
+ * Takes the right side of a dateTruncEquals expression (ie. the suffix)
324
+ * and returns a pretty string representation of what that value means.
325
+ *
326
+ * eg. date_trunc('year', TIMESTAMP '2023-01-01') would be "in 2023"
327
+ * eg. date_trunc('month', TIMESTAMP '2023-01-01') would be "in Jan 2023"
328
+ * eg. date_trunc('quarter', TIMESTAMP '2023-01-01') would be "in Q1 2023"
329
+ */
330
+ function dateTruncSuffixToString(node, databaseType) {
331
+ const period = getPeriod(node, databaseType);
332
+ const dateNode = node.right.value ? node.right : node.right.args.value[1];
333
+ const rawDateStr = dateNode.type === 'cast' ? dateNode.expr.value : dateNode.value;
334
+ const date = (0, exports.newUTCDate)(rawDateStr);
335
+ switch (period) {
336
+ case 'year':
337
+ return `in ${date.getFullYear()}`;
338
+ case 'quarter':
339
+ return `in Q${(0, date_fns_1.getQuarter)(date)} ${date.getFullYear()}`;
340
+ case 'month':
341
+ return `in ${date.toLocaleString('default', { month: 'short', year: 'numeric' })}`;
342
+ case 'week':
343
+ return `week of ${date.toDateString()}`;
344
+ case 'day':
345
+ return `on ${date.toDateString()}`;
346
+ case 'hour':
347
+ return `hour of ${date.toLocaleString()}`;
348
+ default:
349
+ return `${period} of ${date}`;
350
+ }
351
+ }
352
+ exports.dateTruncSuffixToString = dateTruncSuffixToString;
353
+ /**
354
+ * Takes an extract binary expression and returns a string version
355
+ * of what the AST means.
356
+ *
357
+ * eg. extract(YEAR FROM "created_at") = 2023 would be "in 2023"
358
+ * eg. extract(MONTH FROM "created_at") = 1 would be "in January"
359
+ * eg. TODO: add more variants as they come up
360
+ */
361
+ function extractSuffixToString(node) {
362
+ const period = node.left.args.field.toLowerCase();
363
+ const value = node.right.value;
364
+ switch (period) {
365
+ case 'year': {
366
+ return `is ${value}`;
367
+ }
368
+ case 'month': {
369
+ const date = new Date(2000, value - 1, 1);
370
+ date.setMinutes(date.getMinutes() + date.getTimezoneOffset()); // TZ adjust
371
+ return `in ${date.toLocaleString('default', { month: 'long' })}`;
372
+ }
373
+ default: {
374
+ return `${period} is ${value}`;
375
+ }
376
+ }
377
+ }
378
+ exports.extractSuffixToString = extractSuffixToString;
379
+ function tryConvertDateEquality(node, databaseType) {
380
+ if ((0, exports.isDateTruncEquals)(node)) {
381
+ const columnNode = node.left.args.value[1];
382
+ const columnName = columnNode.column ?? columnNode.value;
383
+ const cleanColumnName = columnName.replaceAll('_at', '');
384
+ const prettyDateSuffix = dateTruncSuffixToString(node, databaseType);
385
+ return `${cleanColumnName} ${prettyDateSuffix}`;
386
+ }
387
+ else if ((0, exports.isExtractEquals)(node)) {
388
+ const columnNode = node.left.args.source;
389
+ const columnName = columnNode.column ?? columnNode.value;
390
+ const cleanColumnName = columnName.replaceAll('_at', '');
391
+ const prettyDateSuffix = extractSuffixToString(node);
392
+ return `${cleanColumnName} ${prettyDateSuffix}`;
393
+ }
394
+ return undefined;
395
+ }
396
+ exports.tryConvertDateEquality = tryConvertDateEquality;
397
+ /**
398
+ * Returns whether this node is an equality of a date column with a
399
+ * date trunc.
400
+ */
401
+ const isDateTruncEquals = (node) => {
402
+ return (node.type === 'binary_expr' &&
403
+ node.operator === '=' &&
404
+ (0, exports.isDateTrunc)(node.left) &&
405
+ (node.right.type === 'single_quote_string' || // is a string literal
406
+ (node.right.type === 'cast' &&
407
+ node.right.expr.type === 'single_quote_string') || // or is string casted to non-string
408
+ (0, exports.isDateTrunc)(node.right)) // or is a date_trunc
409
+ );
410
+ };
411
+ exports.isDateTruncEquals = isDateTruncEquals;
412
+ /**
413
+ * Returns whether this node is an equality of a date column with extract.
414
+ */
415
+ const isExtractEquals = (node) => {
416
+ return (node.type === 'binary_expr' &&
417
+ node.operator === '=' &&
418
+ node.left.type === 'extract' &&
419
+ node.right.type === 'number');
420
+ };
421
+ exports.isExtractEquals = isExtractEquals;
422
+ function showNodeAsRow(node, ast) {
423
+ // if the expression is something like status = "completed"
424
+ if (node.left.type === 'column_ref') {
425
+ return true;
426
+ }
427
+ if (!['AND', 'OR'].includes(node.operator)) {
428
+ return true;
429
+ }
430
+ if ((ast.left?.left?.left?.left || ast.right?.left?.left?.left) &&
431
+ node.left.left?.type === 'column_ref') {
432
+ return true;
433
+ }
434
+ return false;
435
+ }
436
+ exports.showNodeAsRow = showNodeAsRow;
437
+ function getPostgresBasicType(column) {
438
+ if (!column)
439
+ return undefined;
440
+ let format;
441
+ if (column.dataTypeID) {
442
+ switch (column.dataTypeID) {
443
+ case 20: // int8
444
+ case 21: // int2
445
+ case 23: // int4
446
+ case 700: // float4
447
+ case 701: // float8
448
+ case 1700: // numeric
449
+ format = 'number';
450
+ break;
451
+ case 1082: // date
452
+ case 1083: // time
453
+ case 1184: // timestamptz
454
+ case 1114: // timestamp
455
+ format = 'date';
456
+ break;
457
+ case 1043: // varchar
458
+ default:
459
+ format = 'string';
460
+ }
461
+ }
462
+ return format;
463
+ }
464
+ exports.getPostgresBasicType = getPostgresBasicType;
465
+ const deepCopy = (obj) => JSON.parse(JSON.stringify(obj));
466
+ exports.deepCopy = deepCopy;
467
+ const trimEndS = (s) => (s.endsWith('s') ? s.slice(0, -1) : s);
468
+ exports.trimEndS = trimEndS;
469
+ const getDateColumnAndPath = (node) => {
470
+ // "created_at" <= ...
471
+ if (node.left && node.left.type === 'column_ref') {
472
+ return { dateColumn: node.left.column, dateColumnPath: 'left.column' };
473
+ }
474
+ // LOWER("created_at") <= ...
475
+ if (node.left &&
476
+ node.left.type === 'function' &&
477
+ ['lower', 'upper'].includes(node.left.name.toLowerCase()) &&
478
+ node.left.args.type == 'expr_list' &&
479
+ node.left.args.value.length === 1 &&
480
+ node.left.args.value[0].type === 'double_quote_string') {
481
+ return {
482
+ dateColumn: node.left.args.value[0].value,
483
+ dateColumnPath: 'left.args.value.0.value',
484
+ };
485
+ }
486
+ // LOWER("created_at") <= ...
487
+ if (node.left &&
488
+ node.left.type === 'function' &&
489
+ ['lower', 'upper'].includes(node.left.name.toLowerCase()) &&
490
+ node.left.args.type == 'expr_list' &&
491
+ node.left.args.value.length === 1 &&
492
+ node.left.args.value[0].type === 'column_ref') {
493
+ return {
494
+ dateColumn: node.left.args.value[0].column,
495
+ dateColumnPath: 'left.args.value.0.column',
496
+ };
497
+ }
498
+ // date_trunc('...', "...") = ...
499
+ if (node.left &&
500
+ node.left.type === 'function' &&
501
+ node.left.name.toLowerCase() === 'date_trunc' &&
502
+ node.left.args.type == 'expr_list' &&
503
+ node.left.args.value.length === 2 &&
504
+ node.left.args.value[1].type === 'column_ref') {
505
+ return {
506
+ dateColumn: node.left.args.value[1].column,
507
+ dateColumnPath: 'left.args.value.1.column',
508
+ };
509
+ }
510
+ // date_trunc('...', "...") = ...
511
+ if (node.left &&
512
+ node.left.type === 'function' &&
513
+ node.left.name.toLowerCase() === 'date_trunc' &&
514
+ node.left.args.type == 'expr_list' &&
515
+ node.left.args.value.length === 2 &&
516
+ node.left.args.value[1].type === 'double_quote_string') {
517
+ return {
518
+ dateColumn: node.left.args.value[1].value,
519
+ dateColumnPath: 'left.args.value.1.value',
520
+ };
521
+ }
522
+ // unknown
523
+ return { dateColumn: null, dateColumnPath: '' };
524
+ };
525
+ const parseIntervalNode = (node) => {
526
+ if (node.type !== 'interval')
527
+ return null;
528
+ if (node.unit && node.unit.length > 0) {
529
+ return {
530
+ intervalCount: parseInt(node.expr.value),
531
+ intervalType: node.unit,
532
+ };
533
+ }
534
+ const parts = node.expr.value.split(' ');
535
+ return {
536
+ intervalCount: parts.length > 1 ? parseInt(parts[0]) : 1,
537
+ intervalType: (0, exports.trimEndS)(parts.length > 1 ? parts[1] : 'year'),
538
+ };
539
+ };
540
+ // Parses the interval and path to the interval (used to change the interval)
541
+ // from a node using one of many pre-defined patterns. Otherwise null.
542
+ const getIntervalAndPath = (node) => {
543
+ if (node.right && node.right.right && node.right.right.type === 'interval') {
544
+ const interval = parseIntervalNode(node.right.right);
545
+ const { intervalCount, intervalType } = interval ?? {};
546
+ return {
547
+ intervalCount,
548
+ intervalType,
549
+ intervalPaths: ['right.right.expr.value'],
550
+ };
551
+ }
552
+ // date_trunc('...', "...") = date_trunc('...', ...)
553
+ if (node.left &&
554
+ node.left.type === 'function' &&
555
+ node.left.name.toLowerCase() === 'date_trunc' &&
556
+ node.left.args.type == 'expr_list' &&
557
+ node.left.args.value.length === 2 &&
558
+ node.right &&
559
+ node.right.type === 'function' &&
560
+ node.right.name.toLowerCase() === 'date_trunc' &&
561
+ node.right.args.type == 'expr_list' &&
562
+ node.right.args.value.length === 2) {
563
+ // date_trunc('day', "created_at") >= date_trunc('day', CURRENT_DATE - INTERVAL '90 days')
564
+ if (node.right &&
565
+ node.right.type === 'function' &&
566
+ node.right.name.toLowerCase() === 'date_trunc' &&
567
+ node.right.args.type == 'expr_list' &&
568
+ node.right.args.value.length === 2 &&
569
+ node.right.args.value[1].type === 'binary_expr' &&
570
+ node.right.args.value[1].right.type === 'interval') {
571
+ return parseIntervalNode(node.right.args.value[1].right);
572
+ }
573
+ const intervalType = node.right.args.value[0].value;
574
+ return {
575
+ intervalCount: null,
576
+ intervalType: (0, exports.trimEndS)(intervalType ?? 'year'),
577
+ intervalPaths: ['right.args.value.0.value', 'left.args.value.0.value'],
578
+ };
579
+ }
580
+ // "created_at" >= DATE_TRUNC('day', CURRENT_DATE - INTERVAL '90 days')
581
+ if (node.left &&
582
+ node.left.type === 'column_ref' &&
583
+ node.right &&
584
+ node.right.type === 'function' &&
585
+ node.right.name.toLowerCase() === 'date_trunc' &&
586
+ node.right.args.type == 'expr_list' &&
587
+ node.right.args.value.length === 2 &&
588
+ node.right.args.value[1].type === 'binary_expr' &&
589
+ node.right.args.value[1].right &&
590
+ node.right.args.value[1].right.type === 'interval') {
591
+ const interval = parseIntervalNode(node.right.node.right.args.value[1].right);
592
+ const { intervalCount, intervalType } = interval ?? {};
593
+ return {
594
+ intervalCount,
595
+ intervalType,
596
+ intervalPaths: ['right.args.value.0.value'],
597
+ };
598
+ }
599
+ // unknown
600
+ return { intervalCount: 1, intervalType: '', intervalPaths: [] };
601
+ };
602
+ const getDateFilterType = (node) => {
603
+ if ((0, exports.isDateTruncEquals)(node))
604
+ return 'equals';
605
+ if (node.operator === '>=' &&
606
+ node.left &&
607
+ node.left.type === 'column_ref' &&
608
+ node.right &&
609
+ node.right.type === 'binary_expr' &&
610
+ node.right.operator == '-' &&
611
+ node.right.right &&
612
+ node.right.right.type == 'interval') {
613
+ // ... >= ... - INTERVAL '...'
614
+ return 'in the last';
615
+ }
616
+ else if (node.operator === '=' &&
617
+ node.left?.type === 'function' &&
618
+ node.left?.name === 'date_trunc' &&
619
+ node.right?.type === 'function' &&
620
+ node.right?.name === 'date_trunc' &&
621
+ node.right.args.type === 'expr_list' &&
622
+ node.right.args.value.length === 2 &&
623
+ node.right.args.value[1].type === 'function' &&
624
+ ['current_date', 'now'].includes(node.right.args.value[1].name.toLowerCase())) {
625
+ // DATE_TRUNC('...', ...) = DATE_TRUNC('...', ...)
626
+ return 'in the current';
627
+ }
628
+ else {
629
+ // ... = DATE_TRUNC('...', ... - INTERVAL '...');
630
+ return 'in the previous';
631
+ }
632
+ };
633
+ const getDateFilterInfo = (node) => {
634
+ const { dateColumn, dateColumnPath } = getDateColumnAndPath(node);
635
+ const interval = getIntervalAndPath(node);
636
+ const { intervalCount, intervalType } = interval ?? {};
637
+ const intervalPaths = interval?.intervalPaths;
638
+ const dateFilterType = getDateFilterType(node);
639
+ return {
640
+ dateColumn,
641
+ dateColumnPath,
642
+ dateFilterType,
643
+ intervalCount,
644
+ intervalType,
645
+ intervalPaths,
646
+ };
647
+ };
648
+ exports.getDateFilterInfo = getDateFilterInfo;
@@ -27,6 +27,8 @@ export interface TableComponentProps {
27
27
  downloadCSV?: () => void;
28
28
  LoadingComponent?: () => JSX.Element;
29
29
  DownloadCSVButtonComponent?: (props: ButtonComponentProps) => JSX.Element;
30
+ rowsPerPage?: number;
31
+ emptyStateLabel?: string;
30
32
  }
31
33
  export interface TextInputComponentProps {
32
34
  onChange: (e: any) => void;
@@ -73,12 +75,12 @@ export declare const MemoizedSecondaryButton: ({ label, onClick }: {
73
75
  label: any;
74
76
  onClick: any;
75
77
  }) => import("react/jsx-runtime").JSX.Element;
76
- export declare const MemoizedSelect: ({ value, onChange, options, disabled, label, }: {
78
+ export declare const MemoizedSelect: ({ value, onChange, options, disabled, style, }: {
77
79
  value: any;
78
80
  onChange: any;
79
81
  options: any;
80
82
  disabled?: boolean | undefined;
81
- label: any;
83
+ style?: {} | undefined;
82
84
  }) => import("react/jsx-runtime").JSX.Element;
83
85
  export declare const MemoizedHeader: ({ children }: {
84
86
  children: any;
@@ -86,6 +88,17 @@ export declare const MemoizedHeader: ({ children }: {
86
88
  export declare const MemoizedLabel: ({ children }: {
87
89
  children: any;
88
90
  }) => import("react/jsx-runtime").JSX.Element;
91
+ export declare const MemoizedCheckbox: ({ checked, onChange, style, ...props }: {
92
+ [x: string]: any;
93
+ checked: any;
94
+ onChange: any;
95
+ style?: {} | undefined;
96
+ }) => import("react/jsx-runtime").JSX.Element;
97
+ export declare const MemoizedTabs: ({ defaultValue, options, onValueChange }: {
98
+ defaultValue: any;
99
+ options: any;
100
+ onValueChange: any;
101
+ }) => import("react/jsx-runtime").JSX.Element;
89
102
  export declare const MemoizedText: ({ children }: {
90
103
  children: any;
91
104
  }) => import("react/jsx-runtime").JSX.Element;