search-input-query-parser 0.2.1 → 0.4.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.
package/README.md CHANGED
@@ -20,7 +20,8 @@ import {
20
20
  const schemas: FieldSchema[] = [
21
21
  { name: 'title', type: 'string' },
22
22
  { name: 'price', type: 'number' },
23
- { name: 'date', type: 'date' }
23
+ { name: 'date', type: 'date' },
24
+ { name: 'in_stock', type: 'boolean' }
24
25
  ];
25
26
 
26
27
  // Parse a search query
@@ -58,7 +59,8 @@ const searchableColumns = ['title', 'description'];
58
59
  const schemas: FieldSchema[] = [
59
60
  { name: 'title', type: 'string' },
60
61
  { name: 'price', type: 'number' },
61
- { name: 'date', type: 'date' }
62
+ { name: 'date', type: 'date' },
63
+ { name: 'in_stock', type: 'boolean' }
62
64
  ];
63
65
 
64
66
  // Convert a search query to SQL
@@ -34,7 +34,7 @@ const parseExpression = (stream, minPrecedence = 0) => {
34
34
  if (nextToken.type === lexer_1.TokenType.EOF) {
35
35
  throw {
36
36
  message: `Unexpected token: ${token.value}`,
37
- code: validator_1.SearchQueryErrorCode.UNEXPECTED_TOKEN,
37
+ code: validator_1.SearchQueryErrorCode.SYNTAX_TOKEN_UNEXPECTED,
38
38
  value: token.value,
39
39
  position: token.position,
40
40
  length: token.length,
package/dist/cjs/lexer.js CHANGED
@@ -99,7 +99,7 @@ const tokenizeQuotedString = (input, position) => {
99
99
  }
100
100
  throw {
101
101
  message: "Unterminated quoted string",
102
- code: validator_1.SearchQueryErrorCode.UNTERMINATED_QUOTED_STRING,
102
+ code: validator_1.SearchQueryErrorCode.SYNTAX_QUOTE_UNTERMINATED,
103
103
  position,
104
104
  length,
105
105
  };
@@ -266,7 +266,7 @@ const tokenize = (input) => {
266
266
  prevToken.type === TokenType.STRING)) {
267
267
  throw {
268
268
  message: "Invalid syntax: Missing operator or whitespace between terms",
269
- code: validator_1.SearchQueryErrorCode.MISSING_OPERATOR_OR_WHITESPACE,
269
+ code: validator_1.SearchQueryErrorCode.SYNTAX_OPERATOR_OR_SPACE_MISSING,
270
270
  position: position,
271
271
  length: 1,
272
272
  };
@@ -279,7 +279,7 @@ const tokenize = (input) => {
279
279
  !isSpecialChar(input[newPos])) {
280
280
  throw {
281
281
  message: "Invalid syntax: Missing operator or whitespace between terms",
282
- code: validator_1.SearchQueryErrorCode.MISSING_OPERATOR_OR_WHITESPACE,
282
+ code: validator_1.SearchQueryErrorCode.SYNTAX_OPERATOR_OR_SPACE_MISSING,
283
283
  position: newPos,
284
284
  length: 1,
285
285
  };
@@ -10,7 +10,7 @@ const parseInValues = (stream, inValuePosition) => {
10
10
  if ((0, lexer_1.currentToken)(currentStream).type !== lexer_1.TokenType.LPAREN) {
11
11
  throw {
12
12
  message: "Expected '(' after IN",
13
- code: validator_1.SearchQueryErrorCode.EXPECTED_LPAREN_AFTER_IN,
13
+ code: validator_1.SearchQueryErrorCode.IN_LPAREN_MISSING,
14
14
  position: inValuePosition, // Use the position passed from the caller
15
15
  length: 1,
16
16
  };
@@ -22,7 +22,7 @@ const parseInValues = (stream, inValuePosition) => {
22
22
  if (values.length === 0) {
23
23
  throw {
24
24
  message: "IN operator requires at least one value",
25
- code: validator_1.SearchQueryErrorCode.EMPTY_IN_LIST,
25
+ code: validator_1.SearchQueryErrorCode.IN_LIST_EMPTY,
26
26
  position: token.position,
27
27
  length: 1,
28
28
  };
@@ -39,7 +39,7 @@ const parseInValues = (stream, inValuePosition) => {
39
39
  token.type !== lexer_1.TokenType.COMMA)) {
40
40
  throw {
41
41
  message: "Expected ',' or ')' after IN value",
42
- code: validator_1.SearchQueryErrorCode.EXPECTED_IN_SEPARATOR,
42
+ code: validator_1.SearchQueryErrorCode.IN_SEPARATOR_MISSING,
43
43
  position: token.position,
44
44
  length: 1,
45
45
  };
@@ -59,7 +59,7 @@ const parseInValues = (stream, inValuePosition) => {
59
59
  }
60
60
  throw {
61
61
  message: "Expected ',' or ')' after IN value",
62
- code: validator_1.SearchQueryErrorCode.EXPECTED_IN_SEPARATOR,
62
+ code: validator_1.SearchQueryErrorCode.IN_SEPARATOR_MISSING,
63
63
  position: nextToken.position,
64
64
  length: 1,
65
65
  };
@@ -10,7 +10,7 @@ const expectToken = (stream, type, message) => {
10
10
  if (token.type !== type) {
11
11
  throw {
12
12
  message: message ? message : `Expected ${type}`,
13
- code: validator_1.SearchQueryErrorCode.EXPECTED_TOKEN,
13
+ code: validator_1.SearchQueryErrorCode.SYNTAX_TOKEN_MISSING,
14
14
  value: type,
15
15
  position: token.position,
16
16
  length: token.length,
@@ -137,7 +137,7 @@ const parsePrimary = (stream) => {
137
137
  case lexer_1.TokenType.OR:
138
138
  throw {
139
139
  message: `${token.value} is a reserved word`,
140
- code: validator_1.SearchQueryErrorCode.RESERVED_WORD,
140
+ code: validator_1.SearchQueryErrorCode.SYNTAX_KEYWORD_RESERVED,
141
141
  value: token.value,
142
142
  position: token.position,
143
143
  length: token.length,
@@ -145,14 +145,14 @@ const parsePrimary = (stream) => {
145
145
  case lexer_1.TokenType.RPAREN:
146
146
  throw {
147
147
  message: 'Unexpected ")"',
148
- code: validator_1.SearchQueryErrorCode.UNEXPECTED_RIGHT_PAREN,
148
+ code: validator_1.SearchQueryErrorCode.SYNTAX_PARENTHESIS_UNEXPECTED,
149
149
  position: token.position,
150
150
  length: token.length,
151
151
  };
152
152
  default:
153
153
  throw {
154
154
  message: "Unexpected token",
155
- code: validator_1.SearchQueryErrorCode.UNEXPECTED_TOKEN,
155
+ code: validator_1.SearchQueryErrorCode.SYNTAX_TOKEN_UNEXPECTED,
156
156
  position: token.position,
157
157
  length: token.length,
158
158
  };
@@ -48,7 +48,7 @@ const parseSearchInputQuery = (input, fieldSchemas = []) => {
48
48
  if (finalToken.type !== lexer_1.TokenType.EOF) {
49
49
  throw {
50
50
  message: 'Unexpected ")"',
51
- code: validator_1.SearchQueryErrorCode.UNEXPECTED_RIGHT_PAREN,
51
+ code: validator_1.SearchQueryErrorCode.SYNTAX_PARENTHESIS_UNEXPECTED,
52
52
  position: finalToken.position,
53
53
  length: finalToken.length,
54
54
  };
@@ -9,7 +9,7 @@ const validateNumber = (value, position, errors) => {
9
9
  if (isNaN(Number(value))) {
10
10
  errors.push({
11
11
  message: "Invalid numeric value",
12
- code: validator_1.SearchQueryErrorCode.INVALID_NUMERIC_VALUE,
12
+ code: validator_1.SearchQueryErrorCode.VALUE_NUMERIC_INVALID,
13
13
  position,
14
14
  length: value.length,
15
15
  });
@@ -34,7 +34,7 @@ const validateNumericRange = (start, end, basePosition, errors) => {
34
34
  if (startNum > endNum) {
35
35
  errors.push({
36
36
  message: "Range start must be less than or equal to range end",
37
- code: validator_1.SearchQueryErrorCode.RANGE_START_GREATER_THAN_END,
37
+ code: validator_1.SearchQueryErrorCode.VALUE_RANGE_START_EXCEEDS_END,
38
38
  position: basePosition,
39
39
  length: start.length + 2 + end.length,
40
40
  });
@@ -55,7 +55,7 @@ const validateFieldValue = (expr, allowedFields, errors, schemas) => {
55
55
  if (!allowedFields.has(expr.field.toLowerCase())) {
56
56
  errors.push({
57
57
  message: `Invalid field: "${expr.field}"`,
58
- code: validator_1.SearchQueryErrorCode.INVALID_FIELD_NAME,
58
+ code: validator_1.SearchQueryErrorCode.FIELD_NAME_INVALID,
59
59
  value: expr.field,
60
60
  position: expr.position,
61
61
  length: expr.field.length,
@@ -70,7 +70,7 @@ const validateFieldValue = (expr, allowedFields, errors, schemas) => {
70
70
  if (isNaN(Number(value))) {
71
71
  errors.push({
72
72
  message: "Invalid numeric value",
73
- code: validator_1.SearchQueryErrorCode.INVALID_NUMERIC_VALUE,
73
+ code: validator_1.SearchQueryErrorCode.VALUE_NUMERIC_INVALID,
74
74
  position: expr.position +
75
75
  expr.field.length +
76
76
  4 +
@@ -83,7 +83,20 @@ const validateFieldValue = (expr, allowedFields, errors, schemas) => {
83
83
  if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) {
84
84
  errors.push({
85
85
  message: "Invalid date format",
86
- code: validator_1.SearchQueryErrorCode.INVALID_DATE_FORMAT,
86
+ code: validator_1.SearchQueryErrorCode.VALUE_DATE_FORMAT_INVALID,
87
+ position: expr.position +
88
+ expr.field.length +
89
+ 3 +
90
+ index * (value.length + 1),
91
+ length: value.length,
92
+ });
93
+ }
94
+ break;
95
+ case "boolean":
96
+ if (!["true", "false"].includes(value.toLowerCase())) {
97
+ errors.push({
98
+ message: "Invalid boolean value",
99
+ code: validator_1.SearchQueryErrorCode.VALUE_BOOLEAN_INVALID,
87
100
  position: expr.position +
88
101
  expr.field.length +
89
102
  3 +
@@ -100,9 +113,9 @@ const validateFieldValue = (expr, allowedFields, errors, schemas) => {
100
113
  case "WILDCARD": {
101
114
  // For wildcard patterns, validate against field type constraints
102
115
  const schema = schemas.get(expr.prefix.toLowerCase());
103
- if ((schema === null || schema === void 0 ? void 0 : schema.type) === "number" || (schema === null || schema === void 0 ? void 0 : schema.type) === "date") {
116
+ if ((schema === null || schema === void 0 ? void 0 : schema.type) === "number" || (schema === null || schema === void 0 ? void 0 : schema.type) === "date" || (schema === null || schema === void 0 ? void 0 : schema.type) === "boolean") {
104
117
  errors.push({
105
- code: validator_1.SearchQueryErrorCode.WILDCARD_NOT_ALLOWED,
118
+ code: validator_1.SearchQueryErrorCode.VALUE_WILDCARD_NOT_PERMITTED,
106
119
  value: schema.type,
107
120
  message: `Wildcards are not allowed for ${schema.type} fields`,
108
121
  position: expr.position,
@@ -120,7 +133,7 @@ const validateFieldValue = (expr, allowedFields, errors, schemas) => {
120
133
  if (!allowedFields.has(fieldName.toLowerCase()) && colonIndex > 0) {
121
134
  errors.push({
122
135
  message: `Invalid field: "${fieldName}"`,
123
- code: validator_1.SearchQueryErrorCode.INVALID_FIELD_NAME,
136
+ code: validator_1.SearchQueryErrorCode.FIELD_NAME_INVALID,
124
137
  value: fieldName,
125
138
  position: expr.position,
126
139
  length: colonIndex,
@@ -129,7 +142,7 @@ const validateFieldValue = (expr, allowedFields, errors, schemas) => {
129
142
  if (!value) {
130
143
  errors.push({
131
144
  message: "Expected field value",
132
- code: validator_1.SearchQueryErrorCode.EXPECTED_FIELD_VALUE,
145
+ code: validator_1.SearchQueryErrorCode.SYNTAX_VALUE_MISSING,
133
146
  position: expr.position,
134
147
  length: colonIndex + 1,
135
148
  });
@@ -138,7 +151,7 @@ const validateFieldValue = (expr, allowedFields, errors, schemas) => {
138
151
  if (value.startsWith(":")) {
139
152
  errors.push({
140
153
  message: "Missing field name",
141
- code: validator_1.SearchQueryErrorCode.MISSING_FIELD_NAME,
154
+ code: validator_1.SearchQueryErrorCode.SYNTAX_FIELD_NAME_MISSING,
142
155
  position: expr.position,
143
156
  length: value.length + colonIndex + 1,
144
157
  });
@@ -153,7 +166,7 @@ const validateFieldValue = (expr, allowedFields, errors, schemas) => {
153
166
  if (value === ".." || value.includes("...")) {
154
167
  errors.push({
155
168
  message: "Invalid range format",
156
- code: validator_1.SearchQueryErrorCode.INVALID_RANGE_FORMAT,
169
+ code: validator_1.SearchQueryErrorCode.VALUE_RANGE_FORMAT_INVALID,
157
170
  position: valueStartPosition,
158
171
  length: value.length,
159
172
  });
@@ -170,7 +183,7 @@ const validateFieldValue = (expr, allowedFields, errors, schemas) => {
170
183
  if (invalidOp.test(value)) {
171
184
  errors.push({
172
185
  message: "Invalid range operator",
173
- code: validator_1.SearchQueryErrorCode.INVALID_RANGE_OPERATOR,
186
+ code: validator_1.SearchQueryErrorCode.VALUE_RANGE_OPERATOR_INVALID,
174
187
  position: valueStartPosition,
175
188
  length: 3,
176
189
  });
@@ -179,7 +192,7 @@ const validateFieldValue = (expr, allowedFields, errors, schemas) => {
179
192
  if (!compValue) {
180
193
  errors.push({
181
194
  message: "Expected range value",
182
- code: validator_1.SearchQueryErrorCode.EXPECTED_RANGE_VALUE,
195
+ code: validator_1.SearchQueryErrorCode.VALUE_RANGE_MISSING,
183
196
  position: valueStartPosition + operator.length,
184
197
  length: 0,
185
198
  });
@@ -207,7 +220,7 @@ const validateFieldValue = (expr, allowedFields, errors, schemas) => {
207
220
  if (!dateValidator(start) || !dateValidator(end)) {
208
221
  errors.push({
209
222
  message: "Invalid date format",
210
- code: validator_1.SearchQueryErrorCode.INVALID_DATE_FORMAT,
223
+ code: validator_1.SearchQueryErrorCode.VALUE_DATE_FORMAT_INVALID,
211
224
  position: valueStartPosition,
212
225
  length: value.length,
213
226
  });
@@ -221,7 +234,7 @@ const validateFieldValue = (expr, allowedFields, errors, schemas) => {
221
234
  if (!dateValidator(dateStr)) {
222
235
  errors.push({
223
236
  message: "Invalid date format",
224
- code: validator_1.SearchQueryErrorCode.INVALID_DATE_FORMAT,
237
+ code: validator_1.SearchQueryErrorCode.VALUE_DATE_FORMAT_INVALID,
225
238
  position: valueStartPosition,
226
239
  length: value.length,
227
240
  });
@@ -231,7 +244,7 @@ const validateFieldValue = (expr, allowedFields, errors, schemas) => {
231
244
  else if (!dateValidator(value)) {
232
245
  errors.push({
233
246
  message: "Invalid date format",
234
- code: validator_1.SearchQueryErrorCode.INVALID_DATE_FORMAT,
247
+ code: validator_1.SearchQueryErrorCode.VALUE_DATE_FORMAT_INVALID,
235
248
  position: valueStartPosition,
236
249
  length: value.length,
237
250
  });
@@ -239,6 +252,16 @@ const validateFieldValue = (expr, allowedFields, errors, schemas) => {
239
252
  }
240
253
  }
241
254
  }
255
+ if (schema.type === "boolean") {
256
+ if (!["true", "false"].includes(value.toLowerCase())) {
257
+ errors.push({
258
+ message: "Invalid boolean value",
259
+ code: validator_1.SearchQueryErrorCode.VALUE_BOOLEAN_INVALID,
260
+ position: valueStartPosition,
261
+ length: value.length,
262
+ });
263
+ }
264
+ }
242
265
  break;
243
266
  }
244
267
  }
@@ -7,7 +7,7 @@ const validateInExpression = (expr, errors) => {
7
7
  if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(expr.field)) {
8
8
  errors.push({
9
9
  message: "Invalid characters in field name",
10
- code: validator_1.SearchQueryErrorCode.INVALID_FIELD_CHARS,
10
+ code: validator_1.SearchQueryErrorCode.FIELD_CHARS_INVALID,
11
11
  position: expr.position,
12
12
  length: expr.field.length,
13
13
  });
@@ -16,7 +16,7 @@ const validateInExpression = (expr, errors) => {
16
16
  if (validator_1.reservedWords.has(expr.field.toUpperCase())) {
17
17
  errors.push({
18
18
  message: `${expr.field} is a reserved word`,
19
- code: validator_1.SearchQueryErrorCode.RESERVED_WORD_AS_FIELD,
19
+ code: validator_1.SearchQueryErrorCode.FIELD_NAME_RESERVED,
20
20
  value: expr.field,
21
21
  position: expr.position,
22
22
  length: expr.field.length,
@@ -27,7 +27,7 @@ const validateInExpression = (expr, errors) => {
27
27
  if (value.includes(",")) {
28
28
  errors.push({
29
29
  message: "Invalid character in IN value",
30
- code: validator_1.SearchQueryErrorCode.INVALID_IN_VALUE,
30
+ code: validator_1.SearchQueryErrorCode.IN_VALUE_INVALID,
31
31
  position: expr.position + expr.field.length + 3 + index * (value.length + 1),
32
32
  length: value.length,
33
33
  });
@@ -16,7 +16,7 @@ const validateString = (expr, errors) => {
16
16
  if (expr.value.endsWith(":")) {
17
17
  errors.push({
18
18
  message: "Expected field value",
19
- code: validator_1.SearchQueryErrorCode.EXPECTED_FIELD_VALUE,
19
+ code: validator_1.SearchQueryErrorCode.SYNTAX_FIELD_VALUE_MISSING,
20
20
  position: expr.position,
21
21
  length: expr.length,
22
22
  });
@@ -26,7 +26,7 @@ const validateString = (expr, errors) => {
26
26
  if (expr.value.startsWith(":")) {
27
27
  errors.push({
28
28
  message: "Missing field name",
29
- code: validator_1.SearchQueryErrorCode.MISSING_FIELD_NAME,
29
+ code: validator_1.SearchQueryErrorCode.SYNTAX_FIELD_NAME_MISSING,
30
30
  position: expr.position,
31
31
  length: expr.length,
32
32
  });
@@ -39,7 +39,7 @@ const validateString = (expr, errors) => {
39
39
  if (validator_1.reservedWords.has(fieldName.toUpperCase())) {
40
40
  errors.push({
41
41
  message: `${fieldName} is a reserved word`,
42
- code: validator_1.SearchQueryErrorCode.RESERVED_WORD_AS_FIELD,
42
+ code: validator_1.SearchQueryErrorCode.FIELD_NAME_RESERVED,
43
43
  value: fieldName,
44
44
  position: expr.position,
45
45
  length: fieldName.length,
@@ -50,7 +50,7 @@ const validateString = (expr, errors) => {
50
50
  if (!/^[a-zA-Z0-9_-]+$/.test(fieldName)) {
51
51
  errors.push({
52
52
  message: "Invalid characters in field name",
53
- code: validator_1.SearchQueryErrorCode.INVALID_FIELD_CHARS,
53
+ code: validator_1.SearchQueryErrorCode.FIELD_CHARS_INVALID,
54
54
  position: expr.position,
55
55
  length: fieldName.length,
56
56
  });
@@ -62,7 +62,7 @@ const validateString = (expr, errors) => {
62
62
  validator_1.reservedWords.has(expr.value.toUpperCase())) {
63
63
  errors.push({
64
64
  message: `${expr.value} is a reserved word`,
65
- code: validator_1.SearchQueryErrorCode.RESERVED_WORD_AS_FIELD,
65
+ code: validator_1.SearchQueryErrorCode.FIELD_NAME_RESERVED,
66
66
  value: expr.value,
67
67
  position: expr.position,
68
68
  length: expr.length,
@@ -14,7 +14,7 @@ const validateWildcard = (expr, errors) => {
14
14
  const secondStar = value.indexOf("*", firstStar + 1);
15
15
  errors.push({
16
16
  message: "Only one trailing wildcard (*) is allowed",
17
- code: validator_1.SearchQueryErrorCode.MULTIPLE_WILDCARDS,
17
+ code: validator_1.SearchQueryErrorCode.WILDCARD_MULTIPLE_NOT_PERMITTED,
18
18
  position: expr.position + secondStar,
19
19
  length: 1,
20
20
  });
@@ -22,7 +22,7 @@ const validateWildcard = (expr, errors) => {
22
22
  if ((firstStar !== -1 && firstStar !== value.length - 1) && !value.endsWith("**")) {
23
23
  errors.push({
24
24
  message: "Wildcard (*) can only appear at the end of a term",
25
- code: validator_1.SearchQueryErrorCode.INVALID_WILDCARD_POSITION,
25
+ code: validator_1.SearchQueryErrorCode.WILDCARD_POSITION_INVALID,
26
26
  position: expr.position + firstStar,
27
27
  length: 1,
28
28
  });
@@ -34,7 +34,7 @@ const validateWildcard = (expr, errors) => {
34
34
  if (value.endsWith("**")) {
35
35
  errors.push({
36
36
  message: "Only one trailing wildcard (*) is allowed",
37
- code: validator_1.SearchQueryErrorCode.MULTIPLE_WILDCARDS,
37
+ code: validator_1.SearchQueryErrorCode.WILDCARD_MULTIPLE_NOT_PERMITTED,
38
38
  position: expr.position + value.length - 1,
39
39
  length: 1,
40
40
  });
@@ -5,38 +5,39 @@ const validate_in_expression_1 = require("./validate-in-expression");
5
5
  const validate_string_1 = require("./validate-string");
6
6
  var SearchQueryErrorCode;
7
7
  (function (SearchQueryErrorCode) {
8
- SearchQueryErrorCode[SearchQueryErrorCode["UNKNOWN_ERROR"] = 0] = "UNKNOWN_ERROR";
8
+ SearchQueryErrorCode[SearchQueryErrorCode["UNKNOWN"] = 0] = "UNKNOWN";
9
9
  // Syntax Errors (1000-1999)
10
- SearchQueryErrorCode[SearchQueryErrorCode["UNTERMINATED_QUOTED_STRING"] = 1001] = "UNTERMINATED_QUOTED_STRING";
11
- SearchQueryErrorCode[SearchQueryErrorCode["EXPECTED_FIELD_VALUE"] = 1002] = "EXPECTED_FIELD_VALUE";
12
- SearchQueryErrorCode[SearchQueryErrorCode["MISSING_FIELD_NAME"] = 1003] = "MISSING_FIELD_NAME";
13
- SearchQueryErrorCode[SearchQueryErrorCode["MISSING_FIELD_VALUE"] = 1004] = "MISSING_FIELD_VALUE";
14
- SearchQueryErrorCode[SearchQueryErrorCode["UNEXPECTED_RIGHT_PAREN"] = 1005] = "UNEXPECTED_RIGHT_PAREN";
15
- SearchQueryErrorCode[SearchQueryErrorCode["EXPECTED_RIGHT_PAREN"] = 1006] = "EXPECTED_RIGHT_PAREN";
16
- SearchQueryErrorCode[SearchQueryErrorCode["UNEXPECTED_TOKEN"] = 1007] = "UNEXPECTED_TOKEN";
17
- SearchQueryErrorCode[SearchQueryErrorCode["EXPECTED_TOKEN"] = 1008] = "EXPECTED_TOKEN";
18
- SearchQueryErrorCode[SearchQueryErrorCode["MISSING_OPERATOR_OR_WHITESPACE"] = 1009] = "MISSING_OPERATOR_OR_WHITESPACE";
19
- SearchQueryErrorCode[SearchQueryErrorCode["RESERVED_WORD"] = 1010] = "RESERVED_WORD";
10
+ SearchQueryErrorCode[SearchQueryErrorCode["SYNTAX_QUOTE_UNTERMINATED"] = 1001] = "SYNTAX_QUOTE_UNTERMINATED";
11
+ SearchQueryErrorCode[SearchQueryErrorCode["SYNTAX_VALUE_MISSING"] = 1002] = "SYNTAX_VALUE_MISSING";
12
+ SearchQueryErrorCode[SearchQueryErrorCode["SYNTAX_FIELD_NAME_MISSING"] = 1003] = "SYNTAX_FIELD_NAME_MISSING";
13
+ SearchQueryErrorCode[SearchQueryErrorCode["SYNTAX_FIELD_VALUE_MISSING"] = 1004] = "SYNTAX_FIELD_VALUE_MISSING";
14
+ SearchQueryErrorCode[SearchQueryErrorCode["SYNTAX_PARENTHESIS_UNEXPECTED"] = 1005] = "SYNTAX_PARENTHESIS_UNEXPECTED";
15
+ SearchQueryErrorCode[SearchQueryErrorCode["SYNTAX_PARENTHESIS_MISSING"] = 1006] = "SYNTAX_PARENTHESIS_MISSING";
16
+ SearchQueryErrorCode[SearchQueryErrorCode["SYNTAX_TOKEN_UNEXPECTED"] = 1007] = "SYNTAX_TOKEN_UNEXPECTED";
17
+ SearchQueryErrorCode[SearchQueryErrorCode["SYNTAX_TOKEN_MISSING"] = 1008] = "SYNTAX_TOKEN_MISSING";
18
+ SearchQueryErrorCode[SearchQueryErrorCode["SYNTAX_OPERATOR_OR_SPACE_MISSING"] = 1009] = "SYNTAX_OPERATOR_OR_SPACE_MISSING";
19
+ SearchQueryErrorCode[SearchQueryErrorCode["SYNTAX_KEYWORD_RESERVED"] = 1010] = "SYNTAX_KEYWORD_RESERVED";
20
20
  // Field Validation Errors (2000-2999)
21
- SearchQueryErrorCode[SearchQueryErrorCode["INVALID_FIELD_NAME"] = 2001] = "INVALID_FIELD_NAME";
22
- SearchQueryErrorCode[SearchQueryErrorCode["INVALID_FIELD_CHARS"] = 2002] = "INVALID_FIELD_CHARS";
23
- SearchQueryErrorCode[SearchQueryErrorCode["RESERVED_WORD_AS_FIELD"] = 2003] = "RESERVED_WORD_AS_FIELD";
21
+ SearchQueryErrorCode[SearchQueryErrorCode["FIELD_NAME_INVALID"] = 2001] = "FIELD_NAME_INVALID";
22
+ SearchQueryErrorCode[SearchQueryErrorCode["FIELD_CHARS_INVALID"] = 2002] = "FIELD_CHARS_INVALID";
23
+ SearchQueryErrorCode[SearchQueryErrorCode["FIELD_NAME_RESERVED"] = 2003] = "FIELD_NAME_RESERVED";
24
24
  // Value Validation Errors (3000-3999)
25
- SearchQueryErrorCode[SearchQueryErrorCode["INVALID_NUMERIC_VALUE"] = 3001] = "INVALID_NUMERIC_VALUE";
26
- SearchQueryErrorCode[SearchQueryErrorCode["INVALID_DATE_FORMAT"] = 3002] = "INVALID_DATE_FORMAT";
27
- SearchQueryErrorCode[SearchQueryErrorCode["INVALID_RANGE_FORMAT"] = 3003] = "INVALID_RANGE_FORMAT";
28
- SearchQueryErrorCode[SearchQueryErrorCode["INVALID_RANGE_OPERATOR"] = 3004] = "INVALID_RANGE_OPERATOR";
29
- SearchQueryErrorCode[SearchQueryErrorCode["EXPECTED_RANGE_VALUE"] = 3005] = "EXPECTED_RANGE_VALUE";
30
- SearchQueryErrorCode[SearchQueryErrorCode["RANGE_START_GREATER_THAN_END"] = 3006] = "RANGE_START_GREATER_THAN_END";
31
- SearchQueryErrorCode[SearchQueryErrorCode["WILDCARD_NOT_ALLOWED"] = 3007] = "WILDCARD_NOT_ALLOWED";
25
+ SearchQueryErrorCode[SearchQueryErrorCode["VALUE_NUMERIC_INVALID"] = 3001] = "VALUE_NUMERIC_INVALID";
26
+ SearchQueryErrorCode[SearchQueryErrorCode["VALUE_DATE_FORMAT_INVALID"] = 3002] = "VALUE_DATE_FORMAT_INVALID";
27
+ SearchQueryErrorCode[SearchQueryErrorCode["VALUE_RANGE_FORMAT_INVALID"] = 3003] = "VALUE_RANGE_FORMAT_INVALID";
28
+ SearchQueryErrorCode[SearchQueryErrorCode["VALUE_RANGE_OPERATOR_INVALID"] = 3004] = "VALUE_RANGE_OPERATOR_INVALID";
29
+ SearchQueryErrorCode[SearchQueryErrorCode["VALUE_RANGE_MISSING"] = 3005] = "VALUE_RANGE_MISSING";
30
+ SearchQueryErrorCode[SearchQueryErrorCode["VALUE_RANGE_START_EXCEEDS_END"] = 3006] = "VALUE_RANGE_START_EXCEEDS_END";
31
+ SearchQueryErrorCode[SearchQueryErrorCode["VALUE_WILDCARD_NOT_PERMITTED"] = 3007] = "VALUE_WILDCARD_NOT_PERMITTED";
32
+ SearchQueryErrorCode[SearchQueryErrorCode["VALUE_BOOLEAN_INVALID"] = 3008] = "VALUE_BOOLEAN_INVALID";
32
33
  // Wildcard Errors (4000-4999)
33
- SearchQueryErrorCode[SearchQueryErrorCode["INVALID_WILDCARD_POSITION"] = 4001] = "INVALID_WILDCARD_POSITION";
34
- SearchQueryErrorCode[SearchQueryErrorCode["MULTIPLE_WILDCARDS"] = 4002] = "MULTIPLE_WILDCARDS";
34
+ SearchQueryErrorCode[SearchQueryErrorCode["WILDCARD_POSITION_INVALID"] = 4001] = "WILDCARD_POSITION_INVALID";
35
+ SearchQueryErrorCode[SearchQueryErrorCode["WILDCARD_MULTIPLE_NOT_PERMITTED"] = 4002] = "WILDCARD_MULTIPLE_NOT_PERMITTED";
35
36
  // IN Expression Errors (5000-5999)
36
- SearchQueryErrorCode[SearchQueryErrorCode["EMPTY_IN_LIST"] = 5001] = "EMPTY_IN_LIST";
37
- SearchQueryErrorCode[SearchQueryErrorCode["INVALID_IN_VALUE"] = 5002] = "INVALID_IN_VALUE";
38
- SearchQueryErrorCode[SearchQueryErrorCode["EXPECTED_IN_SEPARATOR"] = 5003] = "EXPECTED_IN_SEPARATOR";
39
- SearchQueryErrorCode[SearchQueryErrorCode["EXPECTED_LPAREN_AFTER_IN"] = 5004] = "EXPECTED_LPAREN_AFTER_IN";
37
+ SearchQueryErrorCode[SearchQueryErrorCode["IN_LIST_EMPTY"] = 5001] = "IN_LIST_EMPTY";
38
+ SearchQueryErrorCode[SearchQueryErrorCode["IN_VALUE_INVALID"] = 5002] = "IN_VALUE_INVALID";
39
+ SearchQueryErrorCode[SearchQueryErrorCode["IN_SEPARATOR_MISSING"] = 5003] = "IN_SEPARATOR_MISSING";
40
+ SearchQueryErrorCode[SearchQueryErrorCode["IN_LPAREN_MISSING"] = 5004] = "IN_LPAREN_MISSING";
40
41
  })(SearchQueryErrorCode || (exports.SearchQueryErrorCode = SearchQueryErrorCode = {}));
41
42
  exports.reservedWords = new Set(["AND", "OR"]);
42
43
  const walkExpression = (expr, errors) => {
@@ -31,7 +31,7 @@ export const parseExpression = (stream, minPrecedence = 0) => {
31
31
  if (nextToken.type === TokenType.EOF) {
32
32
  throw {
33
33
  message: `Unexpected token: ${token.value}`,
34
- code: SearchQueryErrorCode.UNEXPECTED_TOKEN,
34
+ code: SearchQueryErrorCode.SYNTAX_TOKEN_UNEXPECTED,
35
35
  value: token.value,
36
36
  position: token.position,
37
37
  length: token.length,
package/dist/esm/lexer.js CHANGED
@@ -93,7 +93,7 @@ const tokenizeQuotedString = (input, position) => {
93
93
  }
94
94
  throw {
95
95
  message: "Unterminated quoted string",
96
- code: SearchQueryErrorCode.UNTERMINATED_QUOTED_STRING,
96
+ code: SearchQueryErrorCode.SYNTAX_QUOTE_UNTERMINATED,
97
97
  position,
98
98
  length,
99
99
  };
@@ -260,7 +260,7 @@ export const tokenize = (input) => {
260
260
  prevToken.type === TokenType.STRING)) {
261
261
  throw {
262
262
  message: "Invalid syntax: Missing operator or whitespace between terms",
263
- code: SearchQueryErrorCode.MISSING_OPERATOR_OR_WHITESPACE,
263
+ code: SearchQueryErrorCode.SYNTAX_OPERATOR_OR_SPACE_MISSING,
264
264
  position: position,
265
265
  length: 1,
266
266
  };
@@ -273,7 +273,7 @@ export const tokenize = (input) => {
273
273
  !isSpecialChar(input[newPos])) {
274
274
  throw {
275
275
  message: "Invalid syntax: Missing operator or whitespace between terms",
276
- code: SearchQueryErrorCode.MISSING_OPERATOR_OR_WHITESPACE,
276
+ code: SearchQueryErrorCode.SYNTAX_OPERATOR_OR_SPACE_MISSING,
277
277
  position: newPos,
278
278
  length: 1,
279
279
  };
@@ -7,7 +7,7 @@ export const parseInValues = (stream, inValuePosition) => {
7
7
  if (currentToken(currentStream).type !== TokenType.LPAREN) {
8
8
  throw {
9
9
  message: "Expected '(' after IN",
10
- code: SearchQueryErrorCode.EXPECTED_LPAREN_AFTER_IN,
10
+ code: SearchQueryErrorCode.IN_LPAREN_MISSING,
11
11
  position: inValuePosition, // Use the position passed from the caller
12
12
  length: 1,
13
13
  };
@@ -19,7 +19,7 @@ export const parseInValues = (stream, inValuePosition) => {
19
19
  if (values.length === 0) {
20
20
  throw {
21
21
  message: "IN operator requires at least one value",
22
- code: SearchQueryErrorCode.EMPTY_IN_LIST,
22
+ code: SearchQueryErrorCode.IN_LIST_EMPTY,
23
23
  position: token.position,
24
24
  length: 1,
25
25
  };
@@ -36,7 +36,7 @@ export const parseInValues = (stream, inValuePosition) => {
36
36
  token.type !== TokenType.COMMA)) {
37
37
  throw {
38
38
  message: "Expected ',' or ')' after IN value",
39
- code: SearchQueryErrorCode.EXPECTED_IN_SEPARATOR,
39
+ code: SearchQueryErrorCode.IN_SEPARATOR_MISSING,
40
40
  position: token.position,
41
41
  length: 1,
42
42
  };
@@ -56,7 +56,7 @@ export const parseInValues = (stream, inValuePosition) => {
56
56
  }
57
57
  throw {
58
58
  message: "Expected ',' or ')' after IN value",
59
- code: SearchQueryErrorCode.EXPECTED_IN_SEPARATOR,
59
+ code: SearchQueryErrorCode.IN_SEPARATOR_MISSING,
60
60
  position: nextToken.position,
61
61
  length: 1,
62
62
  };
@@ -7,7 +7,7 @@ export const expectToken = (stream, type, message) => {
7
7
  if (token.type !== type) {
8
8
  throw {
9
9
  message: message ? message : `Expected ${type}`,
10
- code: SearchQueryErrorCode.EXPECTED_TOKEN,
10
+ code: SearchQueryErrorCode.SYNTAX_TOKEN_MISSING,
11
11
  value: type,
12
12
  position: token.position,
13
13
  length: token.length,
@@ -131,7 +131,7 @@ export const parsePrimary = (stream) => {
131
131
  case TokenType.OR:
132
132
  throw {
133
133
  message: `${token.value} is a reserved word`,
134
- code: SearchQueryErrorCode.RESERVED_WORD,
134
+ code: SearchQueryErrorCode.SYNTAX_KEYWORD_RESERVED,
135
135
  value: token.value,
136
136
  position: token.position,
137
137
  length: token.length,
@@ -139,14 +139,14 @@ export const parsePrimary = (stream) => {
139
139
  case TokenType.RPAREN:
140
140
  throw {
141
141
  message: 'Unexpected ")"',
142
- code: SearchQueryErrorCode.UNEXPECTED_RIGHT_PAREN,
142
+ code: SearchQueryErrorCode.SYNTAX_PARENTHESIS_UNEXPECTED,
143
143
  position: token.position,
144
144
  length: token.length,
145
145
  };
146
146
  default:
147
147
  throw {
148
148
  message: "Unexpected token",
149
- code: SearchQueryErrorCode.UNEXPECTED_TOKEN,
149
+ code: SearchQueryErrorCode.SYNTAX_TOKEN_UNEXPECTED,
150
150
  position: token.position,
151
151
  length: token.length,
152
152
  };
@@ -43,7 +43,7 @@ export const parseSearchInputQuery = (input, fieldSchemas = []) => {
43
43
  if (finalToken.type !== TokenType.EOF) {
44
44
  throw {
45
45
  message: 'Unexpected ")"',
46
- code: SearchQueryErrorCode.UNEXPECTED_RIGHT_PAREN,
46
+ code: SearchQueryErrorCode.SYNTAX_PARENTHESIS_UNEXPECTED,
47
47
  position: finalToken.position,
48
48
  length: finalToken.length,
49
49
  };