search-input-query-parser 0.1.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 (58) hide show
  1. package/dist/cjs/first-pass-parser.js +77 -0
  2. package/dist/cjs/lexer.js +322 -0
  3. package/dist/cjs/parse-in-values.js +65 -0
  4. package/dist/cjs/parse-primary.js +154 -0
  5. package/dist/cjs/parse-range-expression.js +174 -0
  6. package/dist/cjs/parser.js +85 -0
  7. package/dist/cjs/search-query-to-sql.js +346 -0
  8. package/dist/cjs/transform-to-expression.js +130 -0
  9. package/dist/cjs/validate-expression-fields.js +244 -0
  10. package/dist/cjs/validate-in-expression.js +33 -0
  11. package/dist/cjs/validate-string.js +65 -0
  12. package/dist/cjs/validate-wildcard.js +40 -0
  13. package/dist/cjs/validator.js +34 -0
  14. package/dist/esm/first-pass-parser.js +73 -0
  15. package/dist/esm/lexer.js +315 -0
  16. package/dist/esm/parse-in-values.js +61 -0
  17. package/dist/esm/parse-primary.js +147 -0
  18. package/dist/esm/parse-range-expression.js +170 -0
  19. package/dist/esm/parser.js +81 -0
  20. package/dist/esm/search-query-to-sql.js +341 -0
  21. package/dist/esm/transform-to-expression.js +126 -0
  22. package/dist/esm/validate-expression-fields.js +240 -0
  23. package/dist/esm/validate-in-expression.js +29 -0
  24. package/dist/esm/validate-string.js +61 -0
  25. package/dist/esm/validate-wildcard.js +36 -0
  26. package/dist/esm/validator.js +30 -0
  27. package/dist/types/first-pass-parser.d.ts +40 -0
  28. package/dist/types/lexer.d.ts +27 -0
  29. package/dist/types/parse-in-values.d.ts +3 -0
  30. package/dist/types/parse-primary.d.ts +6 -0
  31. package/dist/types/parse-range-expression.d.ts +2 -0
  32. package/dist/types/parser.d.ts +68 -0
  33. package/dist/types/search-query-to-sql.d.ts +18 -0
  34. package/dist/types/transform-to-expression.d.ts +3 -0
  35. package/dist/types/validate-expression-fields.d.ts +4 -0
  36. package/dist/types/validate-in-expression.d.ts +3 -0
  37. package/dist/types/validate-string.d.ts +3 -0
  38. package/dist/types/validate-wildcard.d.ts +3 -0
  39. package/dist/types/validator.d.ts +8 -0
  40. package/package.json +52 -0
  41. package/src/first-pass-parser.test.ts +441 -0
  42. package/src/first-pass-parser.ts +144 -0
  43. package/src/lexer.test.ts +439 -0
  44. package/src/lexer.ts +387 -0
  45. package/src/parse-in-values.ts +74 -0
  46. package/src/parse-primary.ts +179 -0
  47. package/src/parse-range-expression.ts +187 -0
  48. package/src/parser.test.ts +982 -0
  49. package/src/parser.ts +219 -0
  50. package/src/search-query-to-sql.test.ts +503 -0
  51. package/src/search-query-to-sql.ts +506 -0
  52. package/src/transform-to-expression.ts +153 -0
  53. package/src/validate-expression-fields.ts +296 -0
  54. package/src/validate-in-expression.ts +36 -0
  55. package/src/validate-string.ts +73 -0
  56. package/src/validate-wildcard.ts +45 -0
  57. package/src/validator.test.ts +192 -0
  58. package/src/validator.ts +53 -0
@@ -0,0 +1,187 @@
1
+ import { FieldSchema, RangeExpression, FieldValue, RangeOperator } from "./parser";
2
+
3
+ const isRangeOperator = (str: string): str is RangeOperator => {
4
+ return [">=", ">", "<=", "<"].includes(str);
5
+ };
6
+
7
+ export const parseRangeExpression = (
8
+ fieldName: string,
9
+ value: string,
10
+ schema: FieldSchema | undefined,
11
+ position: number,
12
+ colonIndex: number
13
+ ): RangeExpression | FieldValue => {
14
+ // Handle ..20 (less than or equal)
15
+ if (value.startsWith("..")) {
16
+ const numValue = value.slice(2);
17
+ return {
18
+ type: "RANGE",
19
+ field: {
20
+ type: "FIELD",
21
+ value: fieldName,
22
+ position,
23
+ length: colonIndex,
24
+ },
25
+ operator: "<=",
26
+ value: {
27
+ type: "VALUE",
28
+ value: numValue,
29
+ position: position + colonIndex + 3, // after colon and ..
30
+ length: numValue.length,
31
+ },
32
+ position,
33
+ length: colonIndex + 1 + value.length,
34
+ };
35
+ }
36
+
37
+ // Handle 10.. (greater than or equal)
38
+ if (value.endsWith("..")) {
39
+ const numValue = value.slice(0, -2);
40
+ return {
41
+ type: "RANGE",
42
+ field: {
43
+ type: "FIELD",
44
+ value: fieldName,
45
+ position,
46
+ length: colonIndex,
47
+ },
48
+ operator: ">=",
49
+ value: {
50
+ type: "VALUE",
51
+ value: numValue,
52
+ position: position + colonIndex + 1,
53
+ length: numValue.length,
54
+ },
55
+ position,
56
+ length: colonIndex + 1 + value.length,
57
+ };
58
+ }
59
+
60
+ // Handle date ranges with YYYY-MM-DD format
61
+ if (schema?.type === "date") {
62
+ const betweenMatch = value.match(
63
+ /^(\d{4}-\d{2}-\d{2})\.\.(\d{4}-\d{2}-\d{2})$/
64
+ );
65
+ if (betweenMatch) {
66
+ const [_, start, end] = betweenMatch;
67
+ return {
68
+ type: "RANGE",
69
+ field: {
70
+ type: "FIELD",
71
+ value: fieldName,
72
+ position,
73
+ length: colonIndex,
74
+ },
75
+ operator: "BETWEEN",
76
+ value: {
77
+ type: "VALUE",
78
+ value: start,
79
+ position: position + colonIndex + 1,
80
+ length: start.length,
81
+ },
82
+ value2: {
83
+ type: "VALUE",
84
+ value: end,
85
+ position: position + colonIndex + start.length + 3,
86
+ length: end.length,
87
+ },
88
+ position,
89
+ length: colonIndex + 1 + value.length,
90
+ };
91
+ }
92
+ }
93
+
94
+ // Handle 10..20 (between), handling floats and negative numbers
95
+ const betweenMatch = value.match(/^(-?\d*\.?\d+)\.\.(-?\d*\.?\d+)$/);
96
+ if (betweenMatch) {
97
+ const [_, start, end] = betweenMatch;
98
+ return {
99
+ type: "RANGE",
100
+ field: {
101
+ type: "FIELD",
102
+ value: fieldName,
103
+ position,
104
+ length: colonIndex,
105
+ },
106
+ operator: "BETWEEN",
107
+ value: {
108
+ type: "VALUE",
109
+ value: start,
110
+ position: position + colonIndex + 1,
111
+ length: start.length,
112
+ },
113
+ value2: {
114
+ type: "VALUE",
115
+ value: end,
116
+ position: position + colonIndex + start.length + 3,
117
+ length: end.length,
118
+ },
119
+ position,
120
+ length: colonIndex + 1 + value.length,
121
+ };
122
+ }
123
+
124
+ // Handle >100, >=100, <100, <=100
125
+ if (value.length > 1 && isRangeOperator(value.slice(0, 2))) {
126
+ const operator = value.slice(0, 2) as RangeOperator;
127
+ const numValue = value.slice(2);
128
+ return {
129
+ type: "RANGE",
130
+ field: {
131
+ type: "FIELD",
132
+ value: fieldName,
133
+ position,
134
+ length: colonIndex,
135
+ },
136
+ operator,
137
+ value: {
138
+ type: "VALUE",
139
+ value: numValue,
140
+ position: position + colonIndex + 3,
141
+ length: numValue.length,
142
+ },
143
+ position,
144
+ length: colonIndex + 1 + value.length,
145
+ };
146
+ }
147
+
148
+ if (value.length > 0 && isRangeOperator(value.slice(0, 1))) {
149
+ const operator = value.slice(0, 1) as RangeOperator;
150
+ const numValue = value.slice(1);
151
+ return {
152
+ type: "RANGE",
153
+ field: {
154
+ type: "FIELD",
155
+ value: fieldName,
156
+ position,
157
+ length: colonIndex,
158
+ },
159
+ operator,
160
+ value: {
161
+ type: "VALUE",
162
+ value: numValue,
163
+ position: position + colonIndex + 2,
164
+ length: numValue.length,
165
+ },
166
+ position,
167
+ length: colonIndex + 1 + value.length,
168
+ };
169
+ }
170
+
171
+ // If no range pattern is matched, return a regular field value
172
+ return {
173
+ type: "FIELD_VALUE",
174
+ field: {
175
+ type: "FIELD",
176
+ value: fieldName,
177
+ position,
178
+ length: colonIndex,
179
+ },
180
+ value: {
181
+ type: "VALUE",
182
+ value,
183
+ position: position + colonIndex + 1,
184
+ length: value.length,
185
+ },
186
+ };
187
+ };