@malloydata/malloy-filter 0.0.237-dev250222025222 → 0.0.237-dev250222205057

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 (69) hide show
  1. package/dist/a_simple_parser.js +12 -9
  2. package/dist/a_simple_parser.js.map +1 -1
  3. package/dist/base_parser.d.ts +0 -2
  4. package/dist/base_parser.js.map +1 -1
  5. package/dist/boolean_parser.d.ts +2 -2
  6. package/dist/boolean_parser.js +3 -1
  7. package/dist/boolean_parser.js.map +1 -1
  8. package/dist/boolean_serializer.d.ts +4 -4
  9. package/dist/boolean_serializer.js +12 -4
  10. package/dist/boolean_serializer.js.map +1 -1
  11. package/dist/clause_types.d.ts +40 -47
  12. package/dist/date_parser.d.ts +13 -11
  13. package/dist/date_parser.js +192 -131
  14. package/dist/date_parser.js.map +1 -1
  15. package/dist/date_serializer.d.ts +6 -5
  16. package/dist/date_serializer.js +65 -77
  17. package/dist/date_serializer.js.map +1 -1
  18. package/dist/date_types.d.ts +75 -0
  19. package/dist/{filter_types.js → date_types.js} +1 -1
  20. package/dist/date_types.js.map +1 -0
  21. package/dist/generate_samples.js +162 -87
  22. package/dist/generate_samples.js.map +1 -1
  23. package/dist/number_parser.d.ts +2 -5
  24. package/dist/number_parser.js +10 -51
  25. package/dist/number_parser.js.map +1 -1
  26. package/dist/number_serializer.d.ts +4 -4
  27. package/dist/number_serializer.js +17 -14
  28. package/dist/number_serializer.js.map +1 -1
  29. package/dist/string_parser.d.ts +2 -2
  30. package/dist/string_parser.js +21 -21
  31. package/dist/string_parser.js.map +1 -1
  32. package/dist/string_serializer.d.ts +6 -5
  33. package/dist/string_serializer.js +38 -24
  34. package/dist/string_serializer.js.map +1 -1
  35. package/package.json +1 -2
  36. package/src/DEVELOPING.md +2 -5
  37. package/src/a_simple_parser.ts +12 -9
  38. package/src/base_parser.ts +0 -3
  39. package/src/boolean_parser.ts +10 -5
  40. package/src/boolean_serializer.ts +14 -7
  41. package/src/clause_types.ts +65 -108
  42. package/src/date_parser.ts +229 -192
  43. package/src/date_serializer.ts +59 -87
  44. package/src/date_types.ts +159 -0
  45. package/src/generate_samples.ts +178 -109
  46. package/src/number_parser.ts +14 -63
  47. package/src/number_serializer.ts +19 -20
  48. package/src/string_parser.ts +40 -27
  49. package/src/string_serializer.ts +58 -32
  50. package/tsconfig.json +1 -6
  51. package/dist/a_simple_serializer.d.ts +0 -1
  52. package/dist/a_simple_serializer.js +0 -31
  53. package/dist/a_simple_serializer.js.map +0 -1
  54. package/dist/base_serializer.d.ts +0 -6
  55. package/dist/base_serializer.js +0 -11
  56. package/dist/base_serializer.js.map +0 -1
  57. package/dist/filter_parser.d.ts +0 -12
  58. package/dist/filter_parser.js +0 -66
  59. package/dist/filter_parser.js.map +0 -1
  60. package/dist/filter_serializer.d.ts +0 -13
  61. package/dist/filter_serializer.js +0 -43
  62. package/dist/filter_serializer.js.map +0 -1
  63. package/dist/filter_types.d.ts +0 -10
  64. package/dist/filter_types.js.map +0 -1
  65. package/src/a_simple_serializer.ts +0 -40
  66. package/src/base_serializer.ts +0 -9
  67. package/src/filter_parser.ts +0 -68
  68. package/src/filter_serializer.ts +0 -49
  69. package/src/filter_types.ts +0 -12
@@ -1,17 +1,13 @@
1
1
  import {
2
- DateRange,
3
2
  DateMoment,
4
- DateMomentInterval,
5
- DateMomentNumberInterval,
6
- DateMomentNumberUnit,
7
- DateMomentNumber,
8
- Clause,
9
- } from './clause_types';
10
- import {BaseSerializer} from './base_serializer';
3
+ DateBetweenClause,
4
+ DateForClause,
5
+ DateClause,
6
+ } from './date_types';
11
7
 
12
- export class DateSerializer extends BaseSerializer {
13
- constructor(clauses: Clause[]) {
14
- super(clauses);
8
+ export class DateSerializer {
9
+ constructor(private clauses: DateClause[]) {
10
+ this.clauses = clauses;
15
11
  }
16
12
 
17
13
  public serialize(): string {
@@ -19,95 +15,71 @@ export class DateSerializer extends BaseSerializer {
19
15
  return result.trim().replace(/,$/, '');
20
16
  }
21
17
 
22
- private static dateMomentToString(operator: string, clause: Clause): string {
23
- if (
24
- operator === 'NOW' ||
25
- operator === 'TODAY' ||
26
- operator === 'YESTERDAY' ||
27
- operator === 'TOMORROW'
28
- ) {
29
- const custom: DateMoment = clause as DateMoment;
30
- return custom.prefix ? custom.prefix + ' ' + operator : operator;
31
- } else if (
32
- operator === 'LAST' ||
33
- operator === 'THIS' ||
34
- operator === 'NEXT'
35
- ) {
36
- const custom: DateMomentInterval = clause as DateMomentInterval;
37
- let value = custom.operator + ' ' + custom.unit;
38
- if (custom.prefix) {
39
- value = custom.prefix + ' ' + value;
40
- }
41
- return value;
42
- } else if (operator === 'LASTN' || operator === 'NEXTN') {
43
- const custom: DateMomentNumberInterval =
44
- clause as DateMomentNumberInterval;
45
- operator = operator.substring(0, 4); // Strip "N"
46
- let value = operator + ' ' + custom.value + ' ' + custom.unit;
47
- if (custom.prefix) {
48
- value = custom.prefix + ' ' + value;
49
- }
50
- return value;
51
- } else if (operator === 'AGO' || operator === 'FROMNOW') {
52
- const custom: DateMomentNumberInterval =
53
- clause as DateMomentNumberInterval;
54
- if (operator === 'FROMNOW') operator = 'FROM NOW';
55
- let value = custom.value + ' ' + custom.unit + ' ' + operator;
56
- if (custom.prefix) {
57
- value = custom.prefix + ' ' + value;
58
- }
59
- return value;
60
- } else if (operator === 'TIMEBLOCK') {
61
- const custom: DateMomentNumberUnit = clause as DateMomentNumberUnit;
62
- let value = custom.value + ' ' + custom.unit;
63
- if (custom.prefix) {
64
- value = custom.prefix + ' ' + value;
65
- }
66
- return value;
67
- } else if (operator === 'DATE' || operator === 'DATETIME') {
68
- const custom: DateMomentNumber = clause as DateMomentNumber;
69
- let value = custom.date;
70
- if (custom.time) {
71
- value = value + ' ' + custom.time;
72
- }
73
- if (custom.prefix) {
74
- value = custom.prefix + ' ' + value;
75
- }
76
- return value;
18
+ private static dateMomentToString(moment: DateMoment): string {
19
+ if (moment.type === 'ABSOLUTE') {
20
+ return moment.date;
21
+ } else if (moment.type === 'INTERVAL') {
22
+ return moment.kind + ' ' + moment.unit;
23
+ } else if (moment.type === 'NAMED') {
24
+ return moment.name;
25
+ } else if (moment.type === 'OFFSET_FROM_NOW') {
26
+ const direction = moment.direction === 'FROMNOW' ? 'FROM NOW' : 'AGO';
27
+ return moment.amount + ' ' + moment.unit + ' ' + direction;
28
+ } else if (moment.type === 'SPAN_FROM_NOW') {
29
+ return moment.direction + ' ' + moment.amount + ' ' + moment.unit;
30
+ } else {
31
+ throw new Error('moment type not recognized ' + JSON.stringify(moment));
77
32
  }
78
- return '';
79
33
  }
80
34
 
81
- private static dateRangeToString(
82
- operator: 'TO' | 'FOR',
83
- clause: DateRange
84
- ): string {
35
+ private static goDateBetweenClause(clause: DateBetweenClause): string {
85
36
  return (
86
- DateSerializer.dateMomentToString(clause.start.operator, clause.start) +
87
- ' ' +
88
- clause.operator +
37
+ DateSerializer.dateMomentToString(clause.from) +
38
+ ' TO ' +
39
+ DateSerializer.dateMomentToString(clause.to)
40
+ );
41
+ }
42
+
43
+ private static goDateForClause(clause: DateForClause): string {
44
+ return (
45
+ DateSerializer.dateMomentToString(clause.from) +
46
+ ' FOR ' +
47
+ clause.duration.amount +
89
48
  ' ' +
90
- DateSerializer.dateMomentToString(clause.end.operator, clause.end)
49
+ clause.duration.unit
91
50
  );
92
51
  }
93
52
 
94
- private static clauseToString(operator: string, clause: Clause): string {
95
- if (operator === 'TO' || operator === 'FOR') {
96
- const custom = clause as DateRange;
97
- return DateSerializer.dateRangeToString(operator, custom);
53
+ private static clauseToString(clause: DateClause): string {
54
+ if (!('operator' in clause)) {
55
+ throw new Error('Invalid date clause ' + JSON.stringify(clause));
56
+ }
57
+ if (clause.operator === 'TO_RANGE') {
58
+ return DateSerializer.goDateBetweenClause(clause);
59
+ } else if (clause.operator === 'FOR_RANGE') {
60
+ return DateSerializer.goDateForClause(clause);
61
+ } else if (clause.operator === 'BEFORE') {
62
+ return 'BEFORE ' + DateSerializer.dateMomentToString(clause.moment);
63
+ } else if (clause.operator === 'AFTER') {
64
+ return 'AFTER ' + DateSerializer.dateMomentToString(clause.moment);
65
+ } else if (clause.operator === 'ON') {
66
+ return DateSerializer.dateMomentToString(clause.moment);
67
+ } else if (clause.operator === 'NULL') {
68
+ return 'NULL';
69
+ } else if (clause.operator === 'NOTNULL') {
70
+ return '-NULL';
71
+ } else if (clause.operator === 'DURATION') {
72
+ return clause.duration.amount + ' ' + clause.duration.unit;
73
+ } else {
74
+ throw new Error('Clause type not recognized ' + JSON.stringify(clause));
98
75
  }
99
- return DateSerializer.dateMomentToString(operator, clause);
100
76
  }
101
77
 
102
- private static clausesToString(clauses: Clause[]): string {
78
+ private static clausesToString(clauses: DateClause[]): string {
103
79
  let result = '';
104
80
  for (const clause of clauses) {
105
- if ('operator' in clause) {
106
- result += DateSerializer.clauseToString(clause.operator, clause);
107
- result += ', ';
108
- } else {
109
- throw new Error('Invalid date clause ' + JSON.stringify(clause));
110
- }
81
+ result += DateSerializer.clauseToString(clause);
82
+ result += ', ';
111
83
  }
112
84
  return result;
113
85
  }
@@ -0,0 +1,159 @@
1
+ import {FilterError} from './clause_types';
2
+
3
+ export type DateTimeUnit =
4
+ | 'YEAR'
5
+ | 'QUARTER'
6
+ | 'MONTH'
7
+ | 'WEEK'
8
+ | 'DAY'
9
+ | 'HOUR'
10
+ | 'MINUTE'
11
+ | 'SECOND';
12
+
13
+ export type DateWeekday =
14
+ | 'MONDAY'
15
+ | 'TUESDAY'
16
+ | 'WEDNESDAY'
17
+ | 'THURSDAY'
18
+ | 'FRIDAY'
19
+ | 'SATURDAY'
20
+ | 'SUNDAY';
21
+
22
+ // 7 weeks, 32 hours
23
+ export interface Duration {
24
+ amount: number;
25
+ unit: DateTimeUnit;
26
+ }
27
+
28
+ export type DateMomentName = 'NOW' | 'TODAY' | 'YESTERDAY' | 'TOMORROW';
29
+
30
+ // now, today, yesterday, tomorrow
31
+ export interface NamedMoment {
32
+ type: 'NAMED';
33
+ name: DateMomentName;
34
+ }
35
+
36
+ export type DateMomentIntervalOperator = 'LAST' | 'THIS' | 'NEXT';
37
+
38
+ // LAST|UNITOFTIME, LAST|DAYOFWEEK
39
+ // THIS|UNITOFTIME
40
+ // NEXT|UNITOFTIME, NEXT|DAYOFWEEK
41
+ // last month, next tuesday, this month
42
+ export interface IntervalMoment {
43
+ type: 'INTERVAL';
44
+ kind: DateMomentIntervalOperator;
45
+ unit: DateTimeUnit | DateWeekday;
46
+ }
47
+
48
+ export type DateMomentOffsetFromNowDirection = 'AGO' | 'FROMNOW';
49
+
50
+ // NUMBER|UNITOFTIME|AGO
51
+ // NUMBER|UNITOFTIME|FROM|NOW
52
+ // 3 hours ago, 6 weeks from now
53
+ export interface OffsetMoment {
54
+ type: 'OFFSET_FROM_NOW';
55
+ direction: DateMomentOffsetFromNowDirection;
56
+ unit: DateTimeUnit;
57
+ amount: number;
58
+ }
59
+
60
+ export type DateMomentSpanFromNowDirection = 'LAST' | 'NEXT';
61
+
62
+ // LAST|NUMBER|UNITOFTIME
63
+ // NEXT|NUMBER|UNITOFTIME
64
+ // last 3 hours, next 2025 seconds, last 6 weeks
65
+ export interface SpanMoment {
66
+ type: 'SPAN_FROM_NOW';
67
+ direction: DateMomentSpanFromNowDirection;
68
+ unit: DateTimeUnit;
69
+ amount: number;
70
+ }
71
+
72
+ // 2005, 2005-01, 2005-01-01, 2005-01-01 00:00, 2005-01-01 00:00:01
73
+ export interface AbsoluteMoment {
74
+ type: 'ABSOLUTE';
75
+ date: string;
76
+ unit: DateTimeUnit;
77
+ }
78
+
79
+ // 2025-01
80
+ // {
81
+ // operator: 'ON';
82
+ // moment: { date: '2025-01';
83
+ // unit: 'MONTH' }
84
+ // }
85
+
86
+ // after 2025-01
87
+ // {
88
+ // operator: 'AFTER';
89
+ // moment: { date: '2025-01';
90
+ // unit: 'MONTH' }
91
+ // }
92
+
93
+ export type DateMoment =
94
+ | AbsoluteMoment // 2005-01
95
+ | NamedMoment // "today"
96
+ | IntervalMoment // "this month"
97
+ | SpanMoment // "last 3 weeks, next 3 weeks
98
+ | OffsetMoment; // "3 days ago"
99
+
100
+ // after 2005-01, after 3 hours ago
101
+ export interface DateAfterClause {
102
+ operator: 'AFTER';
103
+ moment: DateMoment;
104
+ }
105
+
106
+ // before 2005-01, before 3 hours ago
107
+ export interface DateBeforeClause {
108
+ operator: 'BEFORE';
109
+ moment: DateMoment;
110
+ }
111
+
112
+ // next week, last 3 weeks, 3 days ago
113
+ export interface DateOnClause {
114
+ operator: 'ON';
115
+ moment: DateMoment;
116
+ }
117
+
118
+ // 2015 to next month
119
+ export interface DateBetweenClause {
120
+ operator: 'TO_RANGE';
121
+ from: DateMoment;
122
+ to: DateMoment;
123
+ }
124
+
125
+ // 2025-01-01 12:00:00 for 3 days
126
+ export interface DateForClause {
127
+ operator: 'FOR_RANGE';
128
+ from: DateMoment;
129
+ duration: Duration;
130
+ }
131
+
132
+ export interface DateNullClause {
133
+ operator: 'NULL';
134
+ }
135
+
136
+ export interface DateNotNullClause {
137
+ operator: 'NOTNULL';
138
+ }
139
+
140
+ // 3 days
141
+ export interface DateDurationClause {
142
+ operator: 'DURATION';
143
+ duration: Duration;
144
+ }
145
+
146
+ export type DateClause =
147
+ | DateAfterClause
148
+ | DateBeforeClause
149
+ | DateOnClause
150
+ | DateBetweenClause
151
+ | DateForClause
152
+ | DateNullClause
153
+ | DateNotNullClause
154
+ | DateDurationClause;
155
+
156
+ export interface DateParserResponse {
157
+ clauses: DateClause[];
158
+ errors: FilterError[];
159
+ }