@restura/core 1.7.0 → 1.8.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/dist/index.d.ts CHANGED
@@ -40,6 +40,10 @@ declare const loggerConfigSchema: z.ZodObject<{
40
40
  }, z.core.$strip>;
41
41
  type LoggerConfigSchema = z.infer<typeof loggerConfigSchema>;
42
42
 
43
+ /**
44
+ * @deprecated This is used for passing around until we finally get to the sending externally
45
+ * // TODO: Remove once backwards compatibility is no longer needed
46
+ */
43
47
  interface RsErrorInternalData<T extends Record<string, unknown> = Record<string, unknown>> {
44
48
  err: ErrorCode;
45
49
  msg: string;
@@ -70,13 +74,13 @@ declare enum HtmlStatusCodes {
70
74
  NETWORK_CONNECT_TIMEOUT = 599
71
75
  }
72
76
  type ErrorCode = 'BAD_REQUEST' | 'UNAUTHORIZED' | 'PAYMENT_REQUIRED' | 'FORBIDDEN' | 'NOT_FOUND' | 'METHOD_NOT_ALLOWED' | 'REQUEST_TIMEOUT' | 'CONFLICT' | 'GONE' | 'PAYLOAD_TOO_LARGE' | 'UNSUPPORTED_MEDIA_TYPE' | 'UPGRADE_REQUIRED' | 'UNPROCESSABLE_ENTITY' | 'TOO_MANY_REQUESTS' | 'SERVER_ERROR' | 'NOT_IMPLEMENTED' | 'BAD_GATEWAY' | 'SERVICE_UNAVAILABLE' | 'GATEWAY_TIMEOUT' | 'NETWORK_CONNECT_TIMEOUT' | 'UNKNOWN_ERROR' | 'RATE_LIMIT_EXCEEDED' | 'INVALID_TOKEN' | 'INCORRECT_EMAIL_OR_PASSWORD' | 'DUPLICATE' | 'CONNECTION_ERROR' | 'SCHEMA_ERROR' | 'DATABASE_ERROR';
73
- declare class RsError<T extends Record<string, unknown> = Record<string, unknown>> {
77
+ declare class RsError<T extends Record<string, unknown> = Record<string, unknown>> extends Error {
74
78
  err: ErrorCode;
75
79
  msg: string;
76
80
  options?: T;
77
81
  status?: number;
78
- stack: string;
79
82
  constructor(errCode: ErrorCode, message?: string, options?: T);
83
+ toJSON(): Record<string, unknown>;
80
84
  static htmlStatus(code: ErrorCode): number;
81
85
  static isRsError(error: unknown): error is RsError;
82
86
  }
@@ -1193,10 +1197,16 @@ declare function questionMarksToOrderedParams(query: string): string;
1193
1197
  /**
1194
1198
  * Creates a query to insert an object into a table.
1195
1199
  * @param table Table name to insert the object into
1196
- * @param obj Data to insert into the table
1197
- * @returns the query to insert the object into the table
1200
+ * @param obj Data to insert into the table
1201
+ * @param options.customSelect Optional custom SELECT clause that wraps the INSERT in a CTE.
1202
+ * When provided, the INSERT is wrapped in `WITH inserted AS (INSERT ... RETURNING *)`,
1203
+ * and your customSelect should reference the `inserted` alias.
1204
+ * Example: `{ customSelect: 'SELECT i.*, u.email FROM inserted i JOIN "user" u ON i."userId" = u.id' }`
1205
+ * @returns The query to insert the object into the table
1198
1206
  */
1199
- declare function insertObjectQuery(table: string, obj: DynamicObject): string;
1207
+ declare function insertObjectQuery(table: string, obj: DynamicObject, options?: {
1208
+ customSelect?: string;
1209
+ }): string;
1200
1210
  /**
1201
1211
  * Creates a query to update an object in a table.
1202
1212
  * @param table Table name to update the object in
package/dist/index.js CHANGED
@@ -14,6 +14,94 @@ import { config } from "@restura/internal";
14
14
  import pino from "pino";
15
15
  import pinoPretty from "pino-pretty";
16
16
 
17
+ // src/restura/RsError.ts
18
+ var HtmlStatusCodes = /* @__PURE__ */ ((HtmlStatusCodes2) => {
19
+ HtmlStatusCodes2[HtmlStatusCodes2["BAD_REQUEST"] = 400] = "BAD_REQUEST";
20
+ HtmlStatusCodes2[HtmlStatusCodes2["UNAUTHORIZED"] = 401] = "UNAUTHORIZED";
21
+ HtmlStatusCodes2[HtmlStatusCodes2["PAYMENT_REQUIRED"] = 402] = "PAYMENT_REQUIRED";
22
+ HtmlStatusCodes2[HtmlStatusCodes2["FORBIDDEN"] = 403] = "FORBIDDEN";
23
+ HtmlStatusCodes2[HtmlStatusCodes2["NOT_FOUND"] = 404] = "NOT_FOUND";
24
+ HtmlStatusCodes2[HtmlStatusCodes2["METHOD_NOT_ALLOWED"] = 405] = "METHOD_NOT_ALLOWED";
25
+ HtmlStatusCodes2[HtmlStatusCodes2["REQUEST_TIMEOUT"] = 408] = "REQUEST_TIMEOUT";
26
+ HtmlStatusCodes2[HtmlStatusCodes2["CONFLICT"] = 409] = "CONFLICT";
27
+ HtmlStatusCodes2[HtmlStatusCodes2["GONE"] = 410] = "GONE";
28
+ HtmlStatusCodes2[HtmlStatusCodes2["PAYLOAD_TOO_LARGE"] = 413] = "PAYLOAD_TOO_LARGE";
29
+ HtmlStatusCodes2[HtmlStatusCodes2["UNSUPPORTED_MEDIA_TYPE"] = 415] = "UNSUPPORTED_MEDIA_TYPE";
30
+ HtmlStatusCodes2[HtmlStatusCodes2["UPGRADE_REQUIRED"] = 426] = "UPGRADE_REQUIRED";
31
+ HtmlStatusCodes2[HtmlStatusCodes2["UNPROCESSABLE_ENTITY"] = 422] = "UNPROCESSABLE_ENTITY";
32
+ HtmlStatusCodes2[HtmlStatusCodes2["TOO_MANY_REQUESTS"] = 429] = "TOO_MANY_REQUESTS";
33
+ HtmlStatusCodes2[HtmlStatusCodes2["SERVER_ERROR"] = 500] = "SERVER_ERROR";
34
+ HtmlStatusCodes2[HtmlStatusCodes2["NOT_IMPLEMENTED"] = 501] = "NOT_IMPLEMENTED";
35
+ HtmlStatusCodes2[HtmlStatusCodes2["BAD_GATEWAY"] = 502] = "BAD_GATEWAY";
36
+ HtmlStatusCodes2[HtmlStatusCodes2["SERVICE_UNAVAILABLE"] = 503] = "SERVICE_UNAVAILABLE";
37
+ HtmlStatusCodes2[HtmlStatusCodes2["GATEWAY_TIMEOUT"] = 504] = "GATEWAY_TIMEOUT";
38
+ HtmlStatusCodes2[HtmlStatusCodes2["NETWORK_CONNECT_TIMEOUT"] = 599] = "NETWORK_CONNECT_TIMEOUT";
39
+ return HtmlStatusCodes2;
40
+ })(HtmlStatusCodes || {});
41
+ var RsError = class _RsError extends Error {
42
+ err;
43
+ msg;
44
+ options;
45
+ status;
46
+ constructor(errCode, message, options) {
47
+ super(message);
48
+ this.name = "RsError";
49
+ this.err = errCode;
50
+ this.msg = message || "";
51
+ this.status = _RsError.htmlStatus(errCode);
52
+ this.options = options;
53
+ }
54
+ toJSON() {
55
+ return {
56
+ type: this.name,
57
+ err: this.err,
58
+ message: this.message,
59
+ msg: this.msg,
60
+ status: this.status ?? 500,
61
+ stack: this.stack ?? "",
62
+ options: this.options
63
+ };
64
+ }
65
+ static htmlStatus(code) {
66
+ return htmlStatusMap[code];
67
+ }
68
+ static isRsError(error) {
69
+ return error instanceof _RsError;
70
+ }
71
+ };
72
+ var htmlStatusMap = {
73
+ // 1:1 mappings to HTTP status codes
74
+ BAD_REQUEST: 400 /* BAD_REQUEST */,
75
+ UNAUTHORIZED: 401 /* UNAUTHORIZED */,
76
+ PAYMENT_REQUIRED: 402 /* PAYMENT_REQUIRED */,
77
+ FORBIDDEN: 403 /* FORBIDDEN */,
78
+ NOT_FOUND: 404 /* NOT_FOUND */,
79
+ METHOD_NOT_ALLOWED: 405 /* METHOD_NOT_ALLOWED */,
80
+ REQUEST_TIMEOUT: 408 /* REQUEST_TIMEOUT */,
81
+ CONFLICT: 409 /* CONFLICT */,
82
+ GONE: 410 /* GONE */,
83
+ PAYLOAD_TOO_LARGE: 413 /* PAYLOAD_TOO_LARGE */,
84
+ UNSUPPORTED_MEDIA_TYPE: 415 /* UNSUPPORTED_MEDIA_TYPE */,
85
+ UPGRADE_REQUIRED: 426 /* UPGRADE_REQUIRED */,
86
+ UNPROCESSABLE_ENTITY: 422 /* UNPROCESSABLE_ENTITY */,
87
+ TOO_MANY_REQUESTS: 429 /* TOO_MANY_REQUESTS */,
88
+ SERVER_ERROR: 500 /* SERVER_ERROR */,
89
+ NOT_IMPLEMENTED: 501 /* NOT_IMPLEMENTED */,
90
+ BAD_GATEWAY: 502 /* BAD_GATEWAY */,
91
+ SERVICE_UNAVAILABLE: 503 /* SERVICE_UNAVAILABLE */,
92
+ GATEWAY_TIMEOUT: 504 /* GATEWAY_TIMEOUT */,
93
+ NETWORK_CONNECT_TIMEOUT: 599 /* NETWORK_CONNECT_TIMEOUT */,
94
+ // Specific business errors mapped to appropriate HTTP codes
95
+ UNKNOWN_ERROR: 500 /* SERVER_ERROR */,
96
+ RATE_LIMIT_EXCEEDED: 429 /* TOO_MANY_REQUESTS */,
97
+ INVALID_TOKEN: 401 /* UNAUTHORIZED */,
98
+ INCORRECT_EMAIL_OR_PASSWORD: 401 /* UNAUTHORIZED */,
99
+ DUPLICATE: 409 /* CONFLICT */,
100
+ CONNECTION_ERROR: 504 /* GATEWAY_TIMEOUT */,
101
+ SCHEMA_ERROR: 500 /* SERVER_ERROR */,
102
+ DATABASE_ERROR: 500 /* SERVER_ERROR */
103
+ };
104
+
17
105
  // src/logger/loggerConfigSchema.ts
18
106
  import { z } from "zod";
19
107
  var loggerConfigSchema = z.object({
@@ -68,6 +156,9 @@ var defaultSerializer = (error) => {
68
156
  responseData: err.response?.data
69
157
  };
70
158
  }
159
+ if (RsError.isRsError(error)) {
160
+ return error.toJSON();
161
+ }
71
162
  return baseSerializer(error);
72
163
  };
73
164
  var errorSerializer = (() => {
@@ -332,83 +423,6 @@ var SqlUtils = class _SqlUtils {
332
423
  }
333
424
  };
334
425
 
335
- // src/restura/RsError.ts
336
- var HtmlStatusCodes = /* @__PURE__ */ ((HtmlStatusCodes2) => {
337
- HtmlStatusCodes2[HtmlStatusCodes2["BAD_REQUEST"] = 400] = "BAD_REQUEST";
338
- HtmlStatusCodes2[HtmlStatusCodes2["UNAUTHORIZED"] = 401] = "UNAUTHORIZED";
339
- HtmlStatusCodes2[HtmlStatusCodes2["PAYMENT_REQUIRED"] = 402] = "PAYMENT_REQUIRED";
340
- HtmlStatusCodes2[HtmlStatusCodes2["FORBIDDEN"] = 403] = "FORBIDDEN";
341
- HtmlStatusCodes2[HtmlStatusCodes2["NOT_FOUND"] = 404] = "NOT_FOUND";
342
- HtmlStatusCodes2[HtmlStatusCodes2["METHOD_NOT_ALLOWED"] = 405] = "METHOD_NOT_ALLOWED";
343
- HtmlStatusCodes2[HtmlStatusCodes2["REQUEST_TIMEOUT"] = 408] = "REQUEST_TIMEOUT";
344
- HtmlStatusCodes2[HtmlStatusCodes2["CONFLICT"] = 409] = "CONFLICT";
345
- HtmlStatusCodes2[HtmlStatusCodes2["GONE"] = 410] = "GONE";
346
- HtmlStatusCodes2[HtmlStatusCodes2["PAYLOAD_TOO_LARGE"] = 413] = "PAYLOAD_TOO_LARGE";
347
- HtmlStatusCodes2[HtmlStatusCodes2["UNSUPPORTED_MEDIA_TYPE"] = 415] = "UNSUPPORTED_MEDIA_TYPE";
348
- HtmlStatusCodes2[HtmlStatusCodes2["UPGRADE_REQUIRED"] = 426] = "UPGRADE_REQUIRED";
349
- HtmlStatusCodes2[HtmlStatusCodes2["UNPROCESSABLE_ENTITY"] = 422] = "UNPROCESSABLE_ENTITY";
350
- HtmlStatusCodes2[HtmlStatusCodes2["TOO_MANY_REQUESTS"] = 429] = "TOO_MANY_REQUESTS";
351
- HtmlStatusCodes2[HtmlStatusCodes2["SERVER_ERROR"] = 500] = "SERVER_ERROR";
352
- HtmlStatusCodes2[HtmlStatusCodes2["NOT_IMPLEMENTED"] = 501] = "NOT_IMPLEMENTED";
353
- HtmlStatusCodes2[HtmlStatusCodes2["BAD_GATEWAY"] = 502] = "BAD_GATEWAY";
354
- HtmlStatusCodes2[HtmlStatusCodes2["SERVICE_UNAVAILABLE"] = 503] = "SERVICE_UNAVAILABLE";
355
- HtmlStatusCodes2[HtmlStatusCodes2["GATEWAY_TIMEOUT"] = 504] = "GATEWAY_TIMEOUT";
356
- HtmlStatusCodes2[HtmlStatusCodes2["NETWORK_CONNECT_TIMEOUT"] = 599] = "NETWORK_CONNECT_TIMEOUT";
357
- return HtmlStatusCodes2;
358
- })(HtmlStatusCodes || {});
359
- var RsError = class _RsError {
360
- err;
361
- msg;
362
- options;
363
- status;
364
- stack;
365
- constructor(errCode, message, options) {
366
- this.err = errCode;
367
- this.msg = message || "";
368
- this.status = _RsError.htmlStatus(errCode);
369
- this.stack = new Error().stack || "";
370
- this.options = options;
371
- }
372
- static htmlStatus(code) {
373
- return htmlStatusMap[code];
374
- }
375
- static isRsError(error) {
376
- return error instanceof _RsError;
377
- }
378
- };
379
- var htmlStatusMap = {
380
- // 1:1 mappings to HTTP status codes
381
- BAD_REQUEST: 400 /* BAD_REQUEST */,
382
- UNAUTHORIZED: 401 /* UNAUTHORIZED */,
383
- PAYMENT_REQUIRED: 402 /* PAYMENT_REQUIRED */,
384
- FORBIDDEN: 403 /* FORBIDDEN */,
385
- NOT_FOUND: 404 /* NOT_FOUND */,
386
- METHOD_NOT_ALLOWED: 405 /* METHOD_NOT_ALLOWED */,
387
- REQUEST_TIMEOUT: 408 /* REQUEST_TIMEOUT */,
388
- CONFLICT: 409 /* CONFLICT */,
389
- GONE: 410 /* GONE */,
390
- PAYLOAD_TOO_LARGE: 413 /* PAYLOAD_TOO_LARGE */,
391
- UNSUPPORTED_MEDIA_TYPE: 415 /* UNSUPPORTED_MEDIA_TYPE */,
392
- UPGRADE_REQUIRED: 426 /* UPGRADE_REQUIRED */,
393
- UNPROCESSABLE_ENTITY: 422 /* UNPROCESSABLE_ENTITY */,
394
- TOO_MANY_REQUESTS: 429 /* TOO_MANY_REQUESTS */,
395
- SERVER_ERROR: 500 /* SERVER_ERROR */,
396
- NOT_IMPLEMENTED: 501 /* NOT_IMPLEMENTED */,
397
- BAD_GATEWAY: 502 /* BAD_GATEWAY */,
398
- SERVICE_UNAVAILABLE: 503 /* SERVICE_UNAVAILABLE */,
399
- GATEWAY_TIMEOUT: 504 /* GATEWAY_TIMEOUT */,
400
- NETWORK_CONNECT_TIMEOUT: 599 /* NETWORK_CONNECT_TIMEOUT */,
401
- // Specific business errors mapped to appropriate HTTP codes
402
- UNKNOWN_ERROR: 500 /* SERVER_ERROR */,
403
- RATE_LIMIT_EXCEEDED: 429 /* TOO_MANY_REQUESTS */,
404
- INVALID_TOKEN: 401 /* UNAUTHORIZED */,
405
- INCORRECT_EMAIL_OR_PASSWORD: 401 /* UNAUTHORIZED */,
406
- DUPLICATE: 409 /* CONFLICT */,
407
- CONNECTION_ERROR: 504 /* GATEWAY_TIMEOUT */,
408
- SCHEMA_ERROR: 500 /* SERVER_ERROR */,
409
- DATABASE_ERROR: 500 /* SERVER_ERROR */
410
- };
411
-
412
426
  // src/restura/validators/ResponseValidator.ts
413
427
  var ResponseValidator = class _ResponseValidator {
414
428
  rootMap;
@@ -1910,15 +1924,25 @@ function questionMarksToOrderedParams(query) {
1910
1924
  return char;
1911
1925
  });
1912
1926
  }
1913
- function insertObjectQuery(table, obj) {
1927
+ function insertObjectQuery(table, obj, options) {
1928
+ const { customSelect } = options ?? {};
1914
1929
  const keys = Object.keys(obj);
1915
1930
  const params = Object.values(obj);
1916
1931
  const columns = keys.map((column) => escapeColumnName(column)).join(", ");
1917
1932
  const values = params.map((value) => SQL`${value}`).join(", ");
1918
1933
  let query = `
1919
- INSERT INTO "${table}" (${columns})
1920
- VALUES (${values})
1921
- RETURNING *`;
1934
+ INSERT INTO "${table}" (${columns})
1935
+ VALUES (${values})
1936
+ RETURNING *`;
1937
+ if (customSelect) {
1938
+ query = `
1939
+ WITH inserted AS (
1940
+ INSERT INTO "${table}" (${columns})
1941
+ VALUES (${values})
1942
+ RETURNING *
1943
+ )
1944
+ ${customSelect}`;
1945
+ }
1922
1946
  query = query.replace(/'(\?)'/g, "?");
1923
1947
  return query;
1924
1948
  }
@@ -2285,6 +2309,22 @@ var initializers = `
2285
2309
  }
2286
2310
  return format.literal(value);
2287
2311
  }
2312
+
2313
+ // Format a value with optional type cast
2314
+ function formatValueWithCast(rawValue, cast) {
2315
+ var formatted = formatValue(unescapeValue(rawValue));
2316
+ return cast ? formatted + '::' + cast : formatted;
2317
+ }
2318
+
2319
+ // Build SQL IN clause from pipe-separated values with optional cast
2320
+ function buildInClauseWithCast(column, rawValue, cast) {
2321
+ var values = splitPipeValues(rawValue);
2322
+ var literals = values.map(function(v) {
2323
+ var formatted = formatValue(v);
2324
+ return cast ? formatted + '::' + cast : formatted;
2325
+ });
2326
+ return column + ' IN (' + literals.join(', ') + ')';
2327
+ }
2288
2328
  `;
2289
2329
  var entryGrammar = `
2290
2330
  {
@@ -2319,7 +2359,7 @@ OldOperator
2319
2359
  = "and"i / "or"i
2320
2360
 
2321
2361
  OldColumn
2322
- = first:OldText rest:("." OldText)* {
2362
+ = first:OldColumnPart rest:("." OldColumnPart)* {
2323
2363
  const partsArray = [first];
2324
2364
  if (rest && rest.length > 0) {
2325
2365
  partsArray.push(...rest.map(item => item[1]));
@@ -2347,20 +2387,25 @@ OldColumn
2347
2387
  return result;
2348
2388
  }
2349
2389
 
2350
- OldText
2390
+ OldColumnPart
2351
2391
  = text:[a-z0-9 \\t\\r\\n\\-_:@']i+ {
2352
2392
  return text.join("");
2353
2393
  }
2354
2394
 
2395
+ OldText
2396
+ = text:[a-z0-9 \\t\\r\\n\\-_:@'.]i+ {
2397
+ return text.join("");
2398
+ }
2399
+
2355
2400
  OldType
2356
2401
  = "type" _ ":" _ type:OldTypeString {
2357
2402
  return type;
2358
2403
  }
2359
2404
 
2360
2405
  OldTypeString
2361
- = text:"startsWith" { return function(column, value) { return \`\${column}::text ILIKE '\${format.literal(value).slice(1,-1)}%'\`; } }
2362
- / text:"endsWith" { return function(column, value) { return \`\${column}::text ILIKE '%\${format.literal(value).slice(1,-1)}'\`; } }
2363
- / text:"contains" { return function(column, value) { return \`\${column}::text ILIKE '%\${format.literal(value).slice(1,-1)}%'\`; } }
2406
+ = text:"startsWith" { return function(column, value) { return \`\${column} ILIKE '\${format.literal(value).slice(1,-1)}%'\`; } }
2407
+ / text:"endsWith" { return function(column, value) { return \`\${column} ILIKE '%\${format.literal(value).slice(1,-1)}'\`; } }
2408
+ / text:"contains" { return function(column, value) { return \`\${column} ILIKE '%\${format.literal(value).slice(1,-1)}%'\`; } }
2364
2409
  / text:"exact" { return function(column, value) { return \`\${column} = \${formatValue(value)}\`; } }
2365
2410
  / text:"greaterThanEqual" { return function(column, value) { return \`\${column} >= \${formatValue(value)}\`; } }
2366
2411
  / text:"greaterThan" { return function(column, value) { return \`\${column} > \${formatValue(value)}\`; } }
@@ -2397,8 +2442,8 @@ SimpleExpr
2397
2442
  { return (negate ? 'NOT ' : '') + '(' + op(col) + ')'; }
2398
2443
  / negate:"!"? _ "(" _ col:Column _ "," _ op:NullOperator _ ")" _
2399
2444
  { return (negate ? 'NOT ' : '') + '(' + op(col) + ')'; }
2400
- / negate:"!"? _ "(" _ col:Column _ "," _ val:Value _ ")" _
2401
- { return (negate ? 'NOT ' : '') + '(' + col + ' = ' + formatValue(unescapeValue(val)) + ')'; }
2445
+ / negate:"!"? _ "(" _ col:Column _ "," _ val:CastedValue _ ")" _
2446
+ { return (negate ? 'NOT ' : '') + '(' + col + ' = ' + formatValueWithCast(val.value, val.cast) + ')'; }
2402
2447
 
2403
2448
  Column
2404
2449
  = first:ColPart rest:("." ColPart)* {
@@ -2434,15 +2479,25 @@ NullOperator
2434
2479
  / "null"i { return function(col) { return col + ' IS NULL'; }; }
2435
2480
 
2436
2481
  OperatorWithValue
2437
- = "in"i _ "," _ val:ValueWithPipes { return function(col) { return buildInClause(col, val); }; }
2438
- / "ne"i _ "," _ val:Value { return function(col) { return col + ' <> ' + formatValue(unescapeValue(val)); }; }
2439
- / "gte"i _ "," _ val:Value { return function(col) { return col + ' >= ' + formatValue(unescapeValue(val)); }; }
2440
- / "gt"i _ "," _ val:Value { return function(col) { return col + ' > ' + formatValue(unescapeValue(val)); }; }
2441
- / "lte"i _ "," _ val:Value { return function(col) { return col + ' <= ' + formatValue(unescapeValue(val)); }; }
2442
- / "lt"i _ "," _ val:Value { return function(col) { return col + ' < ' + formatValue(unescapeValue(val)); }; }
2443
- / "has"i _ "," _ val:Value { return function(col) { return col + '::text ILIKE ' + format.literal('%' + unescapeValue(val) + '%'); }; }
2444
- / "sw"i _ "," _ val:Value { return function(col) { return col + '::text ILIKE ' + format.literal(unescapeValue(val) + '%'); }; }
2445
- / "ew"i _ "," _ val:Value { return function(col) { return col + '::text ILIKE ' + format.literal('%' + unescapeValue(val)); }; }
2482
+ = "in"i _ "," _ val:CastedValueWithPipes { return function(col) { return buildInClauseWithCast(col, val.value, val.cast); }; }
2483
+ / "ne"i _ "," _ val:CastedValue { return function(col) { return col + ' <> ' + formatValueWithCast(val.value, val.cast); }; }
2484
+ / "gte"i _ "," _ val:CastedValue { return function(col) { return col + ' >= ' + formatValueWithCast(val.value, val.cast); }; }
2485
+ / "gt"i _ "," _ val:CastedValue { return function(col) { return col + ' > ' + formatValueWithCast(val.value, val.cast); }; }
2486
+ / "lte"i _ "," _ val:CastedValue { return function(col) { return col + ' <= ' + formatValueWithCast(val.value, val.cast); }; }
2487
+ / "lt"i _ "," _ val:CastedValue { return function(col) { return col + ' < ' + formatValueWithCast(val.value, val.cast); }; }
2488
+ / "has"i _ "," _ val:CastedValue { return function(col) { var formatted = format.literal('%' + unescapeValue(val.value) + '%'); return col + ' ILIKE ' + (val.cast ? formatted + '::' + val.cast : formatted); }; }
2489
+ / "sw"i _ "," _ val:CastedValue { return function(col) { var formatted = format.literal(unescapeValue(val.value) + '%'); return col + ' ILIKE ' + (val.cast ? formatted + '::' + val.cast : formatted); }; }
2490
+ / "ew"i _ "," _ val:CastedValue { return function(col) { var formatted = format.literal('%' + unescapeValue(val.value)); return col + ' ILIKE ' + (val.cast ? formatted + '::' + val.cast : formatted); }; }
2491
+
2492
+ CastedValue
2493
+ = val:Value cast:TypeCast? { return { value: val, cast: cast }; }
2494
+
2495
+ CastedValueWithPipes
2496
+ = val:ValueWithPipes cast:TypeCast? { return { value: val, cast: cast }; }
2497
+
2498
+ TypeCast
2499
+ = "::" type:("timestamptz"i / "timestamp"i / "boolean"i / "numeric"i / "bigint"i / "text"i / "date"i / "int"i)
2500
+ { return type.toLowerCase(); }
2446
2501
 
2447
2502
  Value
2448
2503
  = chars:ValueChar+ { return chars.join(''); }
@@ -2451,7 +2506,8 @@ ValueChar
2451
2506
  = "\\\\\\\\" { return '\\\\\\\\'; }
2452
2507
  / "\\\\," { return '\\\\,'; }
2453
2508
  / "\\\\|" { return '\\\\|'; }
2454
- / [^,()\\\\|]
2509
+ / [^,()\\\\|:]
2510
+ / c:":" !":" { return c; }
2455
2511
 
2456
2512
  ValueWithPipes
2457
2513
  = chars:ValueWithPipesChar+ { return chars.join(''); }
@@ -2460,7 +2516,8 @@ ValueWithPipesChar
2460
2516
  = "\\\\\\\\" { return '\\\\\\\\'; }
2461
2517
  / "\\\\," { return '\\\\,'; }
2462
2518
  / "\\\\|" { return '\\\\|'; }
2463
- / [^,()\\\\]
2519
+ / [^,()\\\\:]
2520
+ / c:":" !":" { return c; }
2464
2521
  `;
2465
2522
  var fullGrammar = entryGrammar + oldGrammar + newGrammar;
2466
2523
  var filterPsqlParser = peg.generate(fullGrammar, {