@expo/entity-database-adapter-knex 0.61.0 → 0.62.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.
@@ -311,63 +311,411 @@ declare const ALLOWED_CAST_TYPES: readonly ["int", "integer", "int2", "int4", "i
311
311
  * Only these types can be used to prevent SQL injection through type name interpolation.
312
312
  */
313
313
  export type PostgresCastType = (typeof ALLOWED_CAST_TYPES)[number];
314
- type ExtractFields<T> = T extends SQLFragment<infer F> ? F : never;
315
- type ExprValueNullable<TExpr> = TExpr extends SQLChainableFragment<any, infer TValue> ? TValue | null | undefined : SupportedSQLValue;
316
- type ExprValue<TExpr> = TExpr extends SQLChainableFragment<any, infer TValue> ? TValue : SupportedSQLValue;
317
- type ExprValueArray<TExpr> = TExpr extends SQLChainableFragment<any, infer TValue> ? readonly TValue[] : readonly SupportedSQLValue[];
318
- declare function inArrayHelper<TExpr extends SQLFragment<any>>(expression: TExpr, values: ExprValueArray<TExpr>): SQLFragment<ExtractFields<TExpr>>;
314
+ type ExtractFragmentFields<T> = T extends SQLFragment<infer F> ? F : never;
315
+ type FragmentValueNullable<TFragment> = TFragment extends SQLChainableFragment<any, infer TValue> ? TValue | null | undefined : SupportedSQLValue;
316
+ type FragmentValue<TFragment> = TFragment extends SQLChainableFragment<any, infer TValue> ? TValue : SupportedSQLValue;
317
+ type FragmentValueArray<TFragment> = TFragment extends SQLChainableFragment<any, infer TValue> ? readonly TValue[] : readonly SupportedSQLValue[];
318
+ /**
319
+ * Generates an `IN (...)` condition from a fragment and array of values.
320
+ * Each array element becomes a separate bound parameter. Returns `FALSE` for empty arrays.
321
+ *
322
+ * @param fragment - A SQLFragment or SQLChainableFragment to check
323
+ * @param values - The values to check membership against
324
+ */
325
+ declare function inArrayHelper<TFragment extends SQLFragment<any>>(fragment: TFragment, values: FragmentValueArray<TFragment>): SQLFragment<ExtractFragmentFields<TFragment>>;
326
+ /**
327
+ * Generates an `IN (...)` condition from a field name and array of values.
328
+ * Each array element becomes a separate bound parameter. Returns `FALSE` for empty arrays.
329
+ *
330
+ * @param fieldName - The entity field name to check
331
+ * @param values - The values to check membership against
332
+ */
319
333
  declare function inArrayHelper<TFields extends Record<string, any>, N extends PickSupportedSQLValueKeys<TFields>>(fieldName: N, values: readonly TFields[N][]): SQLFragment<TFields>;
320
- declare function anyArrayHelper<TExpr extends SQLFragment<any>>(expression: TExpr, values: ExprValueArray<TExpr>): SQLFragment<ExtractFields<TExpr>>;
334
+ /**
335
+ * Generates an `= ANY(?)` condition from a fragment and array of values.
336
+ * The array is bound as a single parameter for consistent query shape. Returns `FALSE` for empty arrays.
337
+ *
338
+ * @param fragment - A SQLFragment or SQLChainableFragment to check
339
+ * @param values - The values to check membership against
340
+ */
341
+ declare function anyArrayHelper<TFragment extends SQLFragment<any>>(fragment: TFragment, values: FragmentValueArray<TFragment>): SQLFragment<ExtractFragmentFields<TFragment>>;
342
+ /**
343
+ * Generates an `= ANY(?)` condition from a field name and array of values.
344
+ * The array is bound as a single parameter for consistent query shape. Returns `FALSE` for empty arrays.
345
+ *
346
+ * @param fieldName - The entity field name to check
347
+ * @param values - The values to check membership against
348
+ */
321
349
  declare function anyArrayHelper<TFields extends Record<string, any>, N extends PickSupportedSQLValueKeys<TFields>>(fieldName: N, values: readonly TFields[N][]): SQLFragment<TFields>;
322
- declare function notInArrayHelper<TExpr extends SQLFragment<any>>(expression: TExpr, values: ExprValueArray<TExpr>): SQLFragment<ExtractFields<TExpr>>;
350
+ /**
351
+ * Generates a `NOT IN (...)` condition from a fragment and array of values.
352
+ * Each array element becomes a separate bound parameter. Returns `TRUE` for empty arrays.
353
+ *
354
+ * @param fragment - A SQLFragment or SQLChainableFragment to check
355
+ * @param values - The values to check non-membership against
356
+ */
357
+ declare function notInArrayHelper<TFragment extends SQLFragment<any>>(fragment: TFragment, values: FragmentValueArray<TFragment>): SQLFragment<ExtractFragmentFields<TFragment>>;
358
+ /**
359
+ * Generates a `NOT IN (...)` condition from a field name and array of values.
360
+ * Each array element becomes a separate bound parameter. Returns `TRUE` for empty arrays.
361
+ *
362
+ * @param fieldName - The entity field name to check
363
+ * @param values - The values to check non-membership against
364
+ */
323
365
  declare function notInArrayHelper<TFields extends Record<string, any>, N extends PickSupportedSQLValueKeys<TFields>>(fieldName: N, values: readonly TFields[N][]): SQLFragment<TFields>;
324
- declare function betweenHelper<TExpr extends SQLFragment<any>>(expression: TExpr, min: ExprValue<TExpr>, max: ExprValue<TExpr>): SQLFragment<ExtractFields<TExpr>>;
366
+ /**
367
+ * Generates a `BETWEEN min AND max` condition (inclusive) from a fragment.
368
+ *
369
+ * @param fragment - A SQLFragment or SQLChainableFragment to check
370
+ * @param min - The lower bound
371
+ * @param max - The upper bound
372
+ */
373
+ declare function betweenHelper<TFragment extends SQLFragment<any>>(fragment: TFragment, min: FragmentValue<TFragment>, max: FragmentValue<TFragment>): SQLFragment<ExtractFragmentFields<TFragment>>;
374
+ /**
375
+ * Generates a `BETWEEN min AND max` condition (inclusive) from a field name.
376
+ *
377
+ * @param fieldName - The entity field name to check
378
+ * @param min - The lower bound
379
+ * @param max - The upper bound
380
+ */
325
381
  declare function betweenHelper<TFields extends Record<string, any>, N extends PickSupportedSQLValueKeys<TFields>>(fieldName: N, min: TFields[N], max: TFields[N]): SQLFragment<TFields>;
326
- declare function notBetweenHelper<TExpr extends SQLFragment<any>>(expression: TExpr, min: ExprValue<TExpr>, max: ExprValue<TExpr>): SQLFragment<ExtractFields<TExpr>>;
382
+ /**
383
+ * Generates a `NOT BETWEEN min AND max` condition from a fragment.
384
+ *
385
+ * @param fragment - A SQLFragment or SQLChainableFragment to check
386
+ * @param min - The lower bound
387
+ * @param max - The upper bound
388
+ */
389
+ declare function notBetweenHelper<TFragment extends SQLFragment<any>>(fragment: TFragment, min: FragmentValue<TFragment>, max: FragmentValue<TFragment>): SQLFragment<ExtractFragmentFields<TFragment>>;
390
+ /**
391
+ * Generates a `NOT BETWEEN min AND max` condition from a field name.
392
+ *
393
+ * @param fieldName - The entity field name to check
394
+ * @param min - The lower bound
395
+ * @param max - The upper bound
396
+ */
327
397
  declare function notBetweenHelper<TFields extends Record<string, any>, N extends PickSupportedSQLValueKeys<TFields>>(fieldName: N, min: TFields[N], max: TFields[N]): SQLFragment<TFields>;
328
- declare function likeHelper<TExpr extends SQLFragment<any>>(expression: TExpr, pattern: string): SQLFragment<ExtractFields<TExpr>>;
398
+ /**
399
+ * Generates a case-sensitive `LIKE` condition from a fragment.
400
+ *
401
+ * @param fragment - A SQLFragment or SQLChainableFragment to match
402
+ * @param pattern - The LIKE pattern (use `%` for wildcards, `_` for single character)
403
+ */
404
+ declare function likeHelper<TFragment extends SQLFragment<any>>(fragment: TFragment, pattern: string): SQLFragment<ExtractFragmentFields<TFragment>>;
405
+ /**
406
+ * Generates a case-sensitive `LIKE` condition from a field name.
407
+ *
408
+ * @param fieldName - The entity field name to match
409
+ * @param pattern - The LIKE pattern (use `%` for wildcards, `_` for single character)
410
+ */
329
411
  declare function likeHelper<TFields extends Record<string, any>, N extends PickStringValueKeys<TFields>>(fieldName: N, pattern: string): SQLFragment<TFields>;
330
- declare function notLikeHelper<TExpr extends SQLFragment<any>>(expression: TExpr, pattern: string): SQLFragment<ExtractFields<TExpr>>;
412
+ /**
413
+ * Generates a case-sensitive `NOT LIKE` condition from a fragment.
414
+ *
415
+ * @param fragment - A SQLFragment or SQLChainableFragment to match
416
+ * @param pattern - The LIKE pattern (use `%` for wildcards, `_` for single character)
417
+ */
418
+ declare function notLikeHelper<TFragment extends SQLFragment<any>>(fragment: TFragment, pattern: string): SQLFragment<ExtractFragmentFields<TFragment>>;
419
+ /**
420
+ * Generates a case-sensitive `NOT LIKE` condition from a field name.
421
+ *
422
+ * @param fieldName - The entity field name to match
423
+ * @param pattern - The LIKE pattern (use `%` for wildcards, `_` for single character)
424
+ */
331
425
  declare function notLikeHelper<TFields extends Record<string, any>, N extends PickStringValueKeys<TFields>>(fieldName: N, pattern: string): SQLFragment<TFields>;
332
- declare function ilikeHelper<TExpr extends SQLFragment<any>>(expression: TExpr, pattern: string): SQLFragment<ExtractFields<TExpr>>;
426
+ /**
427
+ * Generates a case-insensitive `ILIKE` condition from a fragment (PostgreSQL-specific).
428
+ *
429
+ * @param fragment - A SQLFragment or SQLChainableFragment to match
430
+ * @param pattern - The LIKE pattern (use `%` for wildcards, `_` for single character)
431
+ */
432
+ declare function ilikeHelper<TFragment extends SQLFragment<any>>(fragment: TFragment, pattern: string): SQLFragment<ExtractFragmentFields<TFragment>>;
433
+ /**
434
+ * Generates a case-insensitive `ILIKE` condition from a field name (PostgreSQL-specific).
435
+ *
436
+ * @param fieldName - The entity field name to match
437
+ * @param pattern - The LIKE pattern (use `%` for wildcards, `_` for single character)
438
+ */
333
439
  declare function ilikeHelper<TFields extends Record<string, any>, N extends PickStringValueKeys<TFields>>(fieldName: N, pattern: string): SQLFragment<TFields>;
334
- declare function notIlikeHelper<TExpr extends SQLFragment<any>>(expression: TExpr, pattern: string): SQLFragment<ExtractFields<TExpr>>;
440
+ /**
441
+ * Generates a case-insensitive `NOT ILIKE` condition from a fragment (PostgreSQL-specific).
442
+ *
443
+ * @param fragment - A SQLFragment or SQLChainableFragment to match
444
+ * @param pattern - The LIKE pattern (use `%` for wildcards, `_` for single character)
445
+ */
446
+ declare function notIlikeHelper<TFragment extends SQLFragment<any>>(fragment: TFragment, pattern: string): SQLFragment<ExtractFragmentFields<TFragment>>;
447
+ /**
448
+ * Generates a case-insensitive `NOT ILIKE` condition from a field name (PostgreSQL-specific).
449
+ *
450
+ * @param fieldName - The entity field name to match
451
+ * @param pattern - The LIKE pattern (use `%` for wildcards, `_` for single character)
452
+ */
335
453
  declare function notIlikeHelper<TFields extends Record<string, any>, N extends PickStringValueKeys<TFields>>(fieldName: N, pattern: string): SQLFragment<TFields>;
336
- declare function isNullHelper<TExpr extends SQLFragment<any>>(expression: TExpr): SQLFragment<ExtractFields<TExpr>>;
454
+ /**
455
+ * Generates an `IS NULL` condition from a fragment.
456
+ *
457
+ * @param fragment - A SQLFragment or SQLChainableFragment to check
458
+ */
459
+ declare function isNullHelper<TFragment extends SQLFragment<any>>(fragment: TFragment): SQLFragment<ExtractFragmentFields<TFragment>>;
460
+ /**
461
+ * Generates an `IS NULL` condition from a field name.
462
+ *
463
+ * @param fieldName - The entity field name to check
464
+ */
337
465
  declare function isNullHelper<TFields extends Record<string, any>, N extends keyof TFields>(fieldName: N): SQLFragment<TFields>;
338
- declare function isNotNullHelper<TExpr extends SQLFragment<any>>(expression: TExpr): SQLFragment<ExtractFields<TExpr>>;
466
+ /**
467
+ * Generates an `IS NOT NULL` condition from a fragment.
468
+ *
469
+ * @param fragment - A SQLFragment or SQLChainableFragment to check
470
+ */
471
+ declare function isNotNullHelper<TFragment extends SQLFragment<any>>(fragment: TFragment): SQLFragment<ExtractFragmentFields<TFragment>>;
472
+ /**
473
+ * Generates an `IS NOT NULL` condition from a field name.
474
+ *
475
+ * @param fieldName - The entity field name to check
476
+ */
339
477
  declare function isNotNullHelper<TFields extends Record<string, any>, N extends keyof TFields>(fieldName: N): SQLFragment<TFields>;
340
- declare function eqHelper<TExpr extends SQLFragment<any>>(expression: TExpr, value: ExprValueNullable<TExpr>): SQLFragment<ExtractFields<TExpr>>;
478
+ /**
479
+ * Generates an equality condition (`= value`) from a fragment.
480
+ * Automatically converts `null`/`undefined` to `IS NULL`.
481
+ *
482
+ * @param fragment - A SQLFragment or SQLChainableFragment to compare
483
+ * @param value - The value to compare against
484
+ */
485
+ declare function eqHelper<TFragment extends SQLFragment<any>>(fragment: TFragment, value: FragmentValueNullable<TFragment>): SQLFragment<ExtractFragmentFields<TFragment>>;
486
+ /**
487
+ * Generates an equality condition (`= value`) from a field name.
488
+ * Automatically converts `null`/`undefined` to `IS NULL`.
489
+ *
490
+ * @param fieldName - The entity field name to compare
491
+ * @param value - The value to compare against
492
+ */
341
493
  declare function eqHelper<TFields extends Record<string, any>, N extends PickSupportedSQLValueKeys<TFields>>(fieldName: N, value: TFields[N]): SQLFragment<TFields>;
342
- declare function neqHelper<TExpr extends SQLFragment<any>>(expression: TExpr, value: ExprValueNullable<TExpr>): SQLFragment<ExtractFields<TExpr>>;
494
+ /**
495
+ * Generates an inequality condition (`!= value`) from a fragment.
496
+ * Automatically converts `null`/`undefined` to `IS NOT NULL`.
497
+ *
498
+ * @param fragment - A SQLFragment or SQLChainableFragment to compare
499
+ * @param value - The value to compare against
500
+ */
501
+ declare function neqHelper<TFragment extends SQLFragment<any>>(fragment: TFragment, value: FragmentValueNullable<TFragment>): SQLFragment<ExtractFragmentFields<TFragment>>;
502
+ /**
503
+ * Generates an inequality condition (`!= value`) from a field name.
504
+ * Automatically converts `null`/`undefined` to `IS NOT NULL`.
505
+ *
506
+ * @param fieldName - The entity field name to compare
507
+ * @param value - The value to compare against
508
+ */
343
509
  declare function neqHelper<TFields extends Record<string, any>, N extends PickSupportedSQLValueKeys<TFields>>(fieldName: N, value: TFields[N]): SQLFragment<TFields>;
344
- declare function gtHelper<TExpr extends SQLFragment<any>>(expression: TExpr, value: ExprValue<TExpr>): SQLFragment<ExtractFields<TExpr>>;
510
+ /**
511
+ * Generates a greater-than condition (`> value`) from a fragment.
512
+ *
513
+ * @param fragment - A SQLFragment or SQLChainableFragment to compare
514
+ * @param value - The value to compare against
515
+ */
516
+ declare function gtHelper<TFragment extends SQLFragment<any>>(fragment: TFragment, value: FragmentValue<TFragment>): SQLFragment<ExtractFragmentFields<TFragment>>;
517
+ /**
518
+ * Generates a greater-than condition (`> value`) from a field name.
519
+ *
520
+ * @param fieldName - The entity field name to compare
521
+ * @param value - The value to compare against
522
+ */
345
523
  declare function gtHelper<TFields extends Record<string, any>, N extends PickSupportedSQLValueKeys<TFields>>(fieldName: N, value: TFields[N]): SQLFragment<TFields>;
346
- declare function gteHelper<TExpr extends SQLFragment<any>>(expression: TExpr, value: ExprValue<TExpr>): SQLFragment<ExtractFields<TExpr>>;
524
+ /**
525
+ * Generates a greater-than-or-equal-to condition (`>= value`) from a fragment.
526
+ *
527
+ * @param fragment - A SQLFragment or SQLChainableFragment to compare
528
+ * @param value - The value to compare against
529
+ */
530
+ declare function gteHelper<TFragment extends SQLFragment<any>>(fragment: TFragment, value: FragmentValue<TFragment>): SQLFragment<ExtractFragmentFields<TFragment>>;
531
+ /**
532
+ * Generates a greater-than-or-equal-to condition (`>= value`) from a field name.
533
+ *
534
+ * @param fieldName - The entity field name to compare
535
+ * @param value - The value to compare against
536
+ */
347
537
  declare function gteHelper<TFields extends Record<string, any>, N extends PickSupportedSQLValueKeys<TFields>>(fieldName: N, value: TFields[N]): SQLFragment<TFields>;
348
- declare function ltHelper<TExpr extends SQLFragment<any>>(expression: TExpr, value: ExprValue<TExpr>): SQLFragment<ExtractFields<TExpr>>;
538
+ /**
539
+ * Generates a less-than condition (`< value`) from a fragment.
540
+ *
541
+ * @param fragment - A SQLFragment or SQLChainableFragment to compare
542
+ * @param value - The value to compare against
543
+ */
544
+ declare function ltHelper<TFragment extends SQLFragment<any>>(fragment: TFragment, value: FragmentValue<TFragment>): SQLFragment<ExtractFragmentFields<TFragment>>;
545
+ /**
546
+ * Generates a less-than condition (`< value`) from a field name.
547
+ *
548
+ * @param fieldName - The entity field name to compare
549
+ * @param value - The value to compare against
550
+ */
349
551
  declare function ltHelper<TFields extends Record<string, any>, N extends PickSupportedSQLValueKeys<TFields>>(fieldName: N, value: TFields[N]): SQLFragment<TFields>;
350
- declare function lteHelper<TExpr extends SQLFragment<any>>(expression: TExpr, value: ExprValue<TExpr>): SQLFragment<ExtractFields<TExpr>>;
552
+ /**
553
+ * Generates a less-than-or-equal-to condition (`<= value`) from a fragment.
554
+ *
555
+ * @param fragment - A SQLFragment or SQLChainableFragment to compare
556
+ * @param value - The value to compare against
557
+ */
558
+ declare function lteHelper<TFragment extends SQLFragment<any>>(fragment: TFragment, value: FragmentValue<TFragment>): SQLFragment<ExtractFragmentFields<TFragment>>;
559
+ /**
560
+ * Generates a less-than-or-equal-to condition (`<= value`) from a field name.
561
+ *
562
+ * @param fieldName - The entity field name to compare
563
+ * @param value - The value to compare against
564
+ */
351
565
  declare function lteHelper<TFields extends Record<string, any>, N extends PickSupportedSQLValueKeys<TFields>>(fieldName: N, value: TFields[N]): SQLFragment<TFields>;
352
- declare function jsonContainsHelper<TExpr extends SQLFragment<any>>(expression: TExpr, value: JsonSerializable): SQLFragment<ExtractFields<TExpr>>;
566
+ /**
567
+ * Generates a JSON contains condition (`@>`) from a fragment.
568
+ * Tests whether the JSON value contains the given value.
569
+ *
570
+ * @param fragment - A SQLFragment or SQLChainableFragment to check
571
+ * @param value - The JSON value to check containment of
572
+ */
573
+ declare function jsonContainsHelper<TFragment extends SQLFragment<any>>(fragment: TFragment, value: JsonSerializable): SQLFragment<ExtractFragmentFields<TFragment>>;
574
+ /**
575
+ * Generates a JSON contains condition (`@>`) from a field name.
576
+ * Tests whether the JSON value contains the given value.
577
+ *
578
+ * @param fieldName - The entity field name to check
579
+ * @param value - The JSON value to check containment of
580
+ */
353
581
  declare function jsonContainsHelper<TFields extends Record<string, any>, N extends keyof TFields>(fieldName: N, value: JsonSerializable): SQLFragment<TFields>;
354
- declare function jsonContainedByHelper<TExpr extends SQLFragment<any>>(expression: TExpr, value: JsonSerializable): SQLFragment<ExtractFields<TExpr>>;
582
+ /**
583
+ * Generates a JSON contained-by condition (`<@`) from a fragment.
584
+ * Tests whether the JSON value is contained by the given value.
585
+ *
586
+ * @param fragment - A SQLFragment or SQLChainableFragment to check
587
+ * @param value - The JSON value to check containment against
588
+ */
589
+ declare function jsonContainedByHelper<TFragment extends SQLFragment<any>>(fragment: TFragment, value: JsonSerializable): SQLFragment<ExtractFragmentFields<TFragment>>;
590
+ /**
591
+ * Generates a JSON contained-by condition (`<@`) from a field name.
592
+ * Tests whether the JSON value is contained by the given value.
593
+ *
594
+ * @param fieldName - The entity field name to check
595
+ * @param value - The JSON value to check containment against
596
+ */
355
597
  declare function jsonContainedByHelper<TFields extends Record<string, any>, N extends keyof TFields>(fieldName: N, value: JsonSerializable): SQLFragment<TFields>;
356
- declare function jsonPathHelper<TExpr extends SQLFragment<any>>(expression: TExpr, path: string): SQLChainableFragment<ExtractFields<TExpr>, SupportedSQLValue>;
598
+ /**
599
+ * JSON path extraction (`->`) from a fragment. Returns JSON.
600
+ * Returns an SQLChainableFragment for fluent chaining.
601
+ *
602
+ * @param fragment - A SQLFragment or SQLChainableFragment to extract from
603
+ * @param path - The JSON key to extract
604
+ */
605
+ declare function jsonPathHelper<TFragment extends SQLFragment<any>>(fragment: TFragment, path: string): SQLChainableFragment<ExtractFragmentFields<TFragment>, SupportedSQLValue>;
606
+ /**
607
+ * JSON path extraction (`->`) from a field name. Returns JSON.
608
+ * Returns an SQLChainableFragment for fluent chaining.
609
+ *
610
+ * @param fieldName - The entity field name to extract from
611
+ * @param path - The JSON key to extract
612
+ */
357
613
  declare function jsonPathHelper<TFields extends Record<string, any>, N extends keyof TFields>(fieldName: N, path: string): SQLChainableFragment<TFields, SupportedSQLValue>;
358
- declare function jsonPathTextHelper<TExpr extends SQLFragment<any>>(expression: TExpr, path: string): SQLChainableFragment<ExtractFields<TExpr>, SupportedSQLValue>;
614
+ /**
615
+ * JSON path text extraction (`->>`) from a fragment. Returns text.
616
+ * Returns an SQLChainableFragment for fluent chaining.
617
+ *
618
+ * @param fragment - A SQLFragment or SQLChainableFragment to extract from
619
+ * @param path - The JSON key to extract as text
620
+ */
621
+ declare function jsonPathTextHelper<TFragment extends SQLFragment<any>>(fragment: TFragment, path: string): SQLChainableFragment<ExtractFragmentFields<TFragment>, SupportedSQLValue>;
622
+ /**
623
+ * JSON path text extraction (`->>`) from a field name. Returns text.
624
+ * Returns an SQLChainableFragment for fluent chaining.
625
+ *
626
+ * @param fieldName - The entity field name to extract from
627
+ * @param path - The JSON key to extract as text
628
+ */
359
629
  declare function jsonPathTextHelper<TFields extends Record<string, any>, N extends keyof TFields>(fieldName: N, path: string): SQLChainableFragment<TFields, SupportedSQLValue>;
360
- declare function jsonDeepPathHelper<TExpr extends SQLFragment<any>>(expression: TExpr, path: readonly string[]): SQLChainableFragment<ExtractFields<TExpr>, SupportedSQLValue>;
630
+ /**
631
+ * JSON deep path extraction (`#>`) from a fragment. Returns JSON at the specified key path.
632
+ * Returns an SQLChainableFragment for fluent chaining.
633
+ *
634
+ * @param fragment - A SQLFragment or SQLChainableFragment to extract from
635
+ * @param path - Array of keys forming the path (e.g., ['user', 'address', 'city'])
636
+ */
637
+ declare function jsonDeepPathHelper<TFragment extends SQLFragment<any>>(fragment: TFragment, path: readonly string[]): SQLChainableFragment<ExtractFragmentFields<TFragment>, SupportedSQLValue>;
638
+ /**
639
+ * JSON deep path extraction (`#>`) from a field name. Returns JSON at the specified key path.
640
+ * Returns an SQLChainableFragment for fluent chaining.
641
+ *
642
+ * @param fieldName - The entity field name to extract from
643
+ * @param path - Array of keys forming the path (e.g., ['user', 'address', 'city'])
644
+ */
361
645
  declare function jsonDeepPathHelper<TFields extends Record<string, any>, N extends keyof TFields>(fieldName: N, path: readonly string[]): SQLChainableFragment<TFields, SupportedSQLValue>;
362
- declare function jsonDeepPathTextHelper<TExpr extends SQLFragment<any>>(expression: TExpr, path: readonly string[]): SQLChainableFragment<ExtractFields<TExpr>, SupportedSQLValue>;
646
+ /**
647
+ * JSON deep path text extraction (`#>>`) from a fragment. Returns text at the specified key path.
648
+ * Returns an SQLChainableFragment for fluent chaining.
649
+ *
650
+ * @param fragment - A SQLFragment or SQLChainableFragment to extract from
651
+ * @param path - Array of keys forming the path (e.g., ['user', 'address', 'city'])
652
+ */
653
+ declare function jsonDeepPathTextHelper<TFragment extends SQLFragment<any>>(fragment: TFragment, path: readonly string[]): SQLChainableFragment<ExtractFragmentFields<TFragment>, SupportedSQLValue>;
654
+ /**
655
+ * JSON deep path text extraction (`#>>`) from a field name. Returns text at the specified key path.
656
+ * Returns an SQLChainableFragment for fluent chaining.
657
+ *
658
+ * @param fieldName - The entity field name to extract from
659
+ * @param path - Array of keys forming the path (e.g., ['user', 'address', 'city'])
660
+ */
363
661
  declare function jsonDeepPathTextHelper<TFields extends Record<string, any>, N extends keyof TFields>(fieldName: N, path: readonly string[]): SQLChainableFragment<TFields, SupportedSQLValue>;
364
- declare function castHelper<TExpr extends SQLFragment<any>>(expression: TExpr, typeName: PostgresCastType): SQLChainableFragment<ExtractFields<TExpr>, SupportedSQLValue>;
662
+ /**
663
+ * SQL type cast (`::type`) from a fragment.
664
+ * Returns an SQLChainableFragment for fluent chaining.
665
+ *
666
+ * @param fragment - A SQLFragment or SQLChainableFragment to cast
667
+ * @param typeName - The PostgreSQL type name (e.g., 'int', 'text', 'timestamptz')
668
+ */
669
+ declare function castHelper<TFragment extends SQLFragment<any>>(fragment: TFragment, typeName: PostgresCastType): SQLChainableFragment<ExtractFragmentFields<TFragment>, SupportedSQLValue>;
670
+ /**
671
+ * SQL type cast (`::type`) from a field name.
672
+ * Returns an SQLChainableFragment for fluent chaining.
673
+ *
674
+ * @param fieldName - The entity field name to cast
675
+ * @param typeName - The PostgreSQL type name (e.g., 'int', 'text', 'timestamptz')
676
+ */
365
677
  declare function castHelper<TFields extends Record<string, any>, N extends keyof TFields>(fieldName: N, typeName: PostgresCastType): SQLChainableFragment<TFields, SupportedSQLValue>;
366
- declare function lowerHelper<TExpr extends SQLFragment<any>>(expression: TExpr): SQLChainableFragment<ExtractFields<TExpr>, SupportedSQLValue>;
678
+ /**
679
+ * Wraps a fragment in `LOWER()` to convert to lowercase.
680
+ * Returns an SQLChainableFragment for fluent chaining.
681
+ *
682
+ * @param fragment - A SQLFragment or SQLChainableFragment to convert
683
+ */
684
+ declare function lowerHelper<TFragment extends SQLFragment<any>>(fragment: TFragment): SQLChainableFragment<ExtractFragmentFields<TFragment>, SupportedSQLValue>;
685
+ /**
686
+ * Wraps a field in `LOWER()` to convert to lowercase.
687
+ * Returns an SQLChainableFragment for fluent chaining.
688
+ *
689
+ * @param fieldName - The entity field name to convert
690
+ */
367
691
  declare function lowerHelper<TFields extends Record<string, any>, N extends PickStringValueKeys<TFields>>(fieldName: N): SQLChainableFragment<TFields, TFields[N]>;
368
- declare function upperHelper<TExpr extends SQLFragment<any>>(expression: TExpr): SQLChainableFragment<ExtractFields<TExpr>, SupportedSQLValue>;
692
+ /**
693
+ * Wraps a fragment in `UPPER()` to convert to uppercase.
694
+ * Returns an SQLChainableFragment for fluent chaining.
695
+ *
696
+ * @param fragment - A SQLFragment or SQLChainableFragment to convert
697
+ */
698
+ declare function upperHelper<TFragment extends SQLFragment<any>>(fragment: TFragment): SQLChainableFragment<ExtractFragmentFields<TFragment>, SupportedSQLValue>;
699
+ /**
700
+ * Wraps a field in `UPPER()` to convert to uppercase.
701
+ * Returns an SQLChainableFragment for fluent chaining.
702
+ *
703
+ * @param fieldName - The entity field name to convert
704
+ */
369
705
  declare function upperHelper<TFields extends Record<string, any>, N extends PickStringValueKeys<TFields>>(fieldName: N): SQLChainableFragment<TFields, TFields[N]>;
370
- declare function trimHelper<TExpr extends SQLFragment<any>>(expression: TExpr): SQLChainableFragment<ExtractFields<TExpr>, SupportedSQLValue>;
706
+ /**
707
+ * Wraps a fragment in `TRIM()` to remove leading and trailing whitespace.
708
+ * Returns an SQLChainableFragment for fluent chaining.
709
+ *
710
+ * @param fragment - A SQLFragment or SQLChainableFragment to trim
711
+ */
712
+ declare function trimHelper<TFragment extends SQLFragment<any>>(fragment: TFragment): SQLChainableFragment<ExtractFragmentFields<TFragment>, SupportedSQLValue>;
713
+ /**
714
+ * Wraps a field in `TRIM()` to remove leading and trailing whitespace.
715
+ * Returns an SQLChainableFragment for fluent chaining.
716
+ *
717
+ * @param fieldName - The entity field name to trim
718
+ */
371
719
  declare function trimHelper<TFields extends Record<string, any>, N extends PickStringValueKeys<TFields>>(fieldName: N): SQLChainableFragment<TFields, TFields[N]>;
372
720
  /**
373
721
  * Common SQL helper functions for building queries.
@@ -284,10 +284,10 @@ export class EntityKnexDataManager {
284
284
  catch (e) {
285
285
  throw new EntityDatabaseAdapterPaginationCursorInvalidError(`Failed to decode cursor`, e instanceof Error ? e : undefined);
286
286
  }
287
- if (!('id' in parsedCursor)) {
288
- throw new EntityDatabaseAdapterPaginationCursorInvalidError(`Cursor is missing required 'id' field. Parsed cursor: ${JSON.stringify(parsedCursor)}`);
287
+ if (typeof parsedCursor === 'object' && 'id' in parsedCursor) {
288
+ return parsedCursor.id;
289
289
  }
290
- return parsedCursor.id;
290
+ throw new EntityDatabaseAdapterPaginationCursorInvalidError(`Cursor is missing required 'id' field. Parsed cursor: ${JSON.stringify(parsedCursor)}`);
291
291
  }
292
292
  resolveSearchFieldToSQLFragment(field, tableAlias) {
293
293
  if (field instanceof SQLFragment) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expo/entity-database-adapter-knex",
3
- "version": "0.61.0",
3
+ "version": "0.62.0",
4
4
  "description": "Knex database adapter for @expo/entity",
5
5
  "files": [
6
6
  "build",
@@ -29,15 +29,15 @@
29
29
  "license": "MIT",
30
30
  "type": "module",
31
31
  "dependencies": {
32
- "@expo/entity": "^0.61.0",
32
+ "@expo/entity": "^0.62.0",
33
33
  "knex": "^3.1.0"
34
34
  },
35
35
  "devDependencies": {
36
- "@expo/entity-testing-utils": "^0.61.0",
37
- "@jest/globals": "30.2.0",
36
+ "@expo/entity-testing-utils": "^0.62.0",
37
+ "@jest/globals": "30.3.0",
38
38
  "pg": "8.20.0",
39
39
  "ts-mockito": "2.6.1",
40
40
  "typescript": "5.9.3"
41
41
  },
42
- "gitHead": "a6f1dd723262cb1c3e8022d3a8799c17602cd15b"
42
+ "gitHead": "4965cc238882982e6315beca48a68679ed45456b"
43
43
  }
@@ -630,27 +630,41 @@ function resolveInnerExpr<TFields extends Record<string, any>>(
630
630
  // SupportedSQLValue for plain SQLFragment inputs.
631
631
 
632
632
  // Extract TFields from a SQLFragment type
633
- type ExtractFields<T> = T extends SQLFragment<infer F> ? F : never;
633
+ type ExtractFragmentFields<T> = T extends SQLFragment<infer F> ? F : never;
634
634
 
635
635
  // Conditional value types for expression overloads.
636
636
  // Uses SQLChainableFragment<any, ...> so that TExpr alone drives inference (single type param).
637
- type ExprValueNullable<TExpr> =
638
- TExpr extends SQLChainableFragment<any, infer TValue>
637
+ type FragmentValueNullable<TFragment> =
638
+ TFragment extends SQLChainableFragment<any, infer TValue>
639
639
  ? TValue | null | undefined
640
640
  : SupportedSQLValue;
641
641
 
642
- type ExprValue<TExpr> =
643
- TExpr extends SQLChainableFragment<any, infer TValue> ? TValue : SupportedSQLValue;
642
+ type FragmentValue<TFragment> =
643
+ TFragment extends SQLChainableFragment<any, infer TValue> ? TValue : SupportedSQLValue;
644
644
 
645
- type ExprValueArray<TExpr> =
646
- TExpr extends SQLChainableFragment<any, infer TValue>
645
+ type FragmentValueArray<TFragment> =
646
+ TFragment extends SQLChainableFragment<any, infer TValue>
647
647
  ? readonly TValue[]
648
648
  : readonly SupportedSQLValue[];
649
649
 
650
- function inArrayHelper<TExpr extends SQLFragment<any>>(
651
- expression: TExpr,
652
- values: ExprValueArray<TExpr>,
653
- ): SQLFragment<ExtractFields<TExpr>>;
650
+ /**
651
+ * Generates an `IN (...)` condition from a fragment and array of values.
652
+ * Each array element becomes a separate bound parameter. Returns `FALSE` for empty arrays.
653
+ *
654
+ * @param fragment - A SQLFragment or SQLChainableFragment to check
655
+ * @param values - The values to check membership against
656
+ */
657
+ function inArrayHelper<TFragment extends SQLFragment<any>>(
658
+ fragment: TFragment,
659
+ values: FragmentValueArray<TFragment>,
660
+ ): SQLFragment<ExtractFragmentFields<TFragment>>;
661
+ /**
662
+ * Generates an `IN (...)` condition from a field name and array of values.
663
+ * Each array element becomes a separate bound parameter. Returns `FALSE` for empty arrays.
664
+ *
665
+ * @param fieldName - The entity field name to check
666
+ * @param values - The values to check membership against
667
+ */
654
668
  function inArrayHelper<
655
669
  TFields extends Record<string, any>,
656
670
  N extends PickSupportedSQLValueKeys<TFields>,
@@ -662,10 +676,24 @@ function inArrayHelper<TFields extends Record<string, any>>(
662
676
  return resolveInnerExpr(expressionOrFieldName).inArray(values);
663
677
  }
664
678
 
665
- function anyArrayHelper<TExpr extends SQLFragment<any>>(
666
- expression: TExpr,
667
- values: ExprValueArray<TExpr>,
668
- ): SQLFragment<ExtractFields<TExpr>>;
679
+ /**
680
+ * Generates an `= ANY(?)` condition from a fragment and array of values.
681
+ * The array is bound as a single parameter for consistent query shape. Returns `FALSE` for empty arrays.
682
+ *
683
+ * @param fragment - A SQLFragment or SQLChainableFragment to check
684
+ * @param values - The values to check membership against
685
+ */
686
+ function anyArrayHelper<TFragment extends SQLFragment<any>>(
687
+ fragment: TFragment,
688
+ values: FragmentValueArray<TFragment>,
689
+ ): SQLFragment<ExtractFragmentFields<TFragment>>;
690
+ /**
691
+ * Generates an `= ANY(?)` condition from a field name and array of values.
692
+ * The array is bound as a single parameter for consistent query shape. Returns `FALSE` for empty arrays.
693
+ *
694
+ * @param fieldName - The entity field name to check
695
+ * @param values - The values to check membership against
696
+ */
669
697
  function anyArrayHelper<
670
698
  TFields extends Record<string, any>,
671
699
  N extends PickSupportedSQLValueKeys<TFields>,
@@ -677,10 +705,24 @@ function anyArrayHelper<TFields extends Record<string, any>>(
677
705
  return resolveInnerExpr(expressionOrFieldName).anyArray(values);
678
706
  }
679
707
 
680
- function notInArrayHelper<TExpr extends SQLFragment<any>>(
681
- expression: TExpr,
682
- values: ExprValueArray<TExpr>,
683
- ): SQLFragment<ExtractFields<TExpr>>;
708
+ /**
709
+ * Generates a `NOT IN (...)` condition from a fragment and array of values.
710
+ * Each array element becomes a separate bound parameter. Returns `TRUE` for empty arrays.
711
+ *
712
+ * @param fragment - A SQLFragment or SQLChainableFragment to check
713
+ * @param values - The values to check non-membership against
714
+ */
715
+ function notInArrayHelper<TFragment extends SQLFragment<any>>(
716
+ fragment: TFragment,
717
+ values: FragmentValueArray<TFragment>,
718
+ ): SQLFragment<ExtractFragmentFields<TFragment>>;
719
+ /**
720
+ * Generates a `NOT IN (...)` condition from a field name and array of values.
721
+ * Each array element becomes a separate bound parameter. Returns `TRUE` for empty arrays.
722
+ *
723
+ * @param fieldName - The entity field name to check
724
+ * @param values - The values to check non-membership against
725
+ */
684
726
  function notInArrayHelper<
685
727
  TFields extends Record<string, any>,
686
728
  N extends PickSupportedSQLValueKeys<TFields>,
@@ -692,11 +734,25 @@ function notInArrayHelper<TFields extends Record<string, any>>(
692
734
  return resolveInnerExpr(expressionOrFieldName).notInArray(values);
693
735
  }
694
736
 
695
- function betweenHelper<TExpr extends SQLFragment<any>>(
696
- expression: TExpr,
697
- min: ExprValue<TExpr>,
698
- max: ExprValue<TExpr>,
699
- ): SQLFragment<ExtractFields<TExpr>>;
737
+ /**
738
+ * Generates a `BETWEEN min AND max` condition (inclusive) from a fragment.
739
+ *
740
+ * @param fragment - A SQLFragment or SQLChainableFragment to check
741
+ * @param min - The lower bound
742
+ * @param max - The upper bound
743
+ */
744
+ function betweenHelper<TFragment extends SQLFragment<any>>(
745
+ fragment: TFragment,
746
+ min: FragmentValue<TFragment>,
747
+ max: FragmentValue<TFragment>,
748
+ ): SQLFragment<ExtractFragmentFields<TFragment>>;
749
+ /**
750
+ * Generates a `BETWEEN min AND max` condition (inclusive) from a field name.
751
+ *
752
+ * @param fieldName - The entity field name to check
753
+ * @param min - The lower bound
754
+ * @param max - The upper bound
755
+ */
700
756
  function betweenHelper<
701
757
  TFields extends Record<string, any>,
702
758
  N extends PickSupportedSQLValueKeys<TFields>,
@@ -709,11 +765,25 @@ function betweenHelper<TFields extends Record<string, any>>(
709
765
  return resolveInnerExpr(expressionOrFieldName).between(min, max);
710
766
  }
711
767
 
712
- function notBetweenHelper<TExpr extends SQLFragment<any>>(
713
- expression: TExpr,
714
- min: ExprValue<TExpr>,
715
- max: ExprValue<TExpr>,
716
- ): SQLFragment<ExtractFields<TExpr>>;
768
+ /**
769
+ * Generates a `NOT BETWEEN min AND max` condition from a fragment.
770
+ *
771
+ * @param fragment - A SQLFragment or SQLChainableFragment to check
772
+ * @param min - The lower bound
773
+ * @param max - The upper bound
774
+ */
775
+ function notBetweenHelper<TFragment extends SQLFragment<any>>(
776
+ fragment: TFragment,
777
+ min: FragmentValue<TFragment>,
778
+ max: FragmentValue<TFragment>,
779
+ ): SQLFragment<ExtractFragmentFields<TFragment>>;
780
+ /**
781
+ * Generates a `NOT BETWEEN min AND max` condition from a field name.
782
+ *
783
+ * @param fieldName - The entity field name to check
784
+ * @param min - The lower bound
785
+ * @param max - The upper bound
786
+ */
717
787
  function notBetweenHelper<
718
788
  TFields extends Record<string, any>,
719
789
  N extends PickSupportedSQLValueKeys<TFields>,
@@ -726,10 +796,22 @@ function notBetweenHelper<TFields extends Record<string, any>>(
726
796
  return resolveInnerExpr(expressionOrFieldName).notBetween(min, max);
727
797
  }
728
798
 
729
- function likeHelper<TExpr extends SQLFragment<any>>(
730
- expression: TExpr,
799
+ /**
800
+ * Generates a case-sensitive `LIKE` condition from a fragment.
801
+ *
802
+ * @param fragment - A SQLFragment or SQLChainableFragment to match
803
+ * @param pattern - The LIKE pattern (use `%` for wildcards, `_` for single character)
804
+ */
805
+ function likeHelper<TFragment extends SQLFragment<any>>(
806
+ fragment: TFragment,
731
807
  pattern: string,
732
- ): SQLFragment<ExtractFields<TExpr>>;
808
+ ): SQLFragment<ExtractFragmentFields<TFragment>>;
809
+ /**
810
+ * Generates a case-sensitive `LIKE` condition from a field name.
811
+ *
812
+ * @param fieldName - The entity field name to match
813
+ * @param pattern - The LIKE pattern (use `%` for wildcards, `_` for single character)
814
+ */
733
815
  function likeHelper<TFields extends Record<string, any>, N extends PickStringValueKeys<TFields>>(
734
816
  fieldName: N,
735
817
  pattern: string,
@@ -741,10 +823,22 @@ function likeHelper<TFields extends Record<string, any>>(
741
823
  return resolveInnerExpr(expressionOrFieldName).like(pattern);
742
824
  }
743
825
 
744
- function notLikeHelper<TExpr extends SQLFragment<any>>(
745
- expression: TExpr,
826
+ /**
827
+ * Generates a case-sensitive `NOT LIKE` condition from a fragment.
828
+ *
829
+ * @param fragment - A SQLFragment or SQLChainableFragment to match
830
+ * @param pattern - The LIKE pattern (use `%` for wildcards, `_` for single character)
831
+ */
832
+ function notLikeHelper<TFragment extends SQLFragment<any>>(
833
+ fragment: TFragment,
746
834
  pattern: string,
747
- ): SQLFragment<ExtractFields<TExpr>>;
835
+ ): SQLFragment<ExtractFragmentFields<TFragment>>;
836
+ /**
837
+ * Generates a case-sensitive `NOT LIKE` condition from a field name.
838
+ *
839
+ * @param fieldName - The entity field name to match
840
+ * @param pattern - The LIKE pattern (use `%` for wildcards, `_` for single character)
841
+ */
748
842
  function notLikeHelper<TFields extends Record<string, any>, N extends PickStringValueKeys<TFields>>(
749
843
  fieldName: N,
750
844
  pattern: string,
@@ -756,10 +850,22 @@ function notLikeHelper<TFields extends Record<string, any>>(
756
850
  return resolveInnerExpr(expressionOrFieldName).notLike(pattern);
757
851
  }
758
852
 
759
- function ilikeHelper<TExpr extends SQLFragment<any>>(
760
- expression: TExpr,
853
+ /**
854
+ * Generates a case-insensitive `ILIKE` condition from a fragment (PostgreSQL-specific).
855
+ *
856
+ * @param fragment - A SQLFragment or SQLChainableFragment to match
857
+ * @param pattern - The LIKE pattern (use `%` for wildcards, `_` for single character)
858
+ */
859
+ function ilikeHelper<TFragment extends SQLFragment<any>>(
860
+ fragment: TFragment,
761
861
  pattern: string,
762
- ): SQLFragment<ExtractFields<TExpr>>;
862
+ ): SQLFragment<ExtractFragmentFields<TFragment>>;
863
+ /**
864
+ * Generates a case-insensitive `ILIKE` condition from a field name (PostgreSQL-specific).
865
+ *
866
+ * @param fieldName - The entity field name to match
867
+ * @param pattern - The LIKE pattern (use `%` for wildcards, `_` for single character)
868
+ */
763
869
  function ilikeHelper<TFields extends Record<string, any>, N extends PickStringValueKeys<TFields>>(
764
870
  fieldName: N,
765
871
  pattern: string,
@@ -771,10 +877,22 @@ function ilikeHelper<TFields extends Record<string, any>>(
771
877
  return resolveInnerExpr(expressionOrFieldName).ilike(pattern);
772
878
  }
773
879
 
774
- function notIlikeHelper<TExpr extends SQLFragment<any>>(
775
- expression: TExpr,
880
+ /**
881
+ * Generates a case-insensitive `NOT ILIKE` condition from a fragment (PostgreSQL-specific).
882
+ *
883
+ * @param fragment - A SQLFragment or SQLChainableFragment to match
884
+ * @param pattern - The LIKE pattern (use `%` for wildcards, `_` for single character)
885
+ */
886
+ function notIlikeHelper<TFragment extends SQLFragment<any>>(
887
+ fragment: TFragment,
776
888
  pattern: string,
777
- ): SQLFragment<ExtractFields<TExpr>>;
889
+ ): SQLFragment<ExtractFragmentFields<TFragment>>;
890
+ /**
891
+ * Generates a case-insensitive `NOT ILIKE` condition from a field name (PostgreSQL-specific).
892
+ *
893
+ * @param fieldName - The entity field name to match
894
+ * @param pattern - The LIKE pattern (use `%` for wildcards, `_` for single character)
895
+ */
778
896
  function notIlikeHelper<
779
897
  TFields extends Record<string, any>,
780
898
  N extends PickStringValueKeys<TFields>,
@@ -786,9 +904,19 @@ function notIlikeHelper<TFields extends Record<string, any>>(
786
904
  return resolveInnerExpr(expressionOrFieldName).notIlike(pattern);
787
905
  }
788
906
 
789
- function isNullHelper<TExpr extends SQLFragment<any>>(
790
- expression: TExpr,
791
- ): SQLFragment<ExtractFields<TExpr>>;
907
+ /**
908
+ * Generates an `IS NULL` condition from a fragment.
909
+ *
910
+ * @param fragment - A SQLFragment or SQLChainableFragment to check
911
+ */
912
+ function isNullHelper<TFragment extends SQLFragment<any>>(
913
+ fragment: TFragment,
914
+ ): SQLFragment<ExtractFragmentFields<TFragment>>;
915
+ /**
916
+ * Generates an `IS NULL` condition from a field name.
917
+ *
918
+ * @param fieldName - The entity field name to check
919
+ */
792
920
  function isNullHelper<TFields extends Record<string, any>, N extends keyof TFields>(
793
921
  fieldName: N,
794
922
  ): SQLFragment<TFields>;
@@ -798,9 +926,19 @@ function isNullHelper<TFields extends Record<string, any>>(
798
926
  return resolveInnerExpr(expressionOrFieldName).isNull();
799
927
  }
800
928
 
801
- function isNotNullHelper<TExpr extends SQLFragment<any>>(
802
- expression: TExpr,
803
- ): SQLFragment<ExtractFields<TExpr>>;
929
+ /**
930
+ * Generates an `IS NOT NULL` condition from a fragment.
931
+ *
932
+ * @param fragment - A SQLFragment or SQLChainableFragment to check
933
+ */
934
+ function isNotNullHelper<TFragment extends SQLFragment<any>>(
935
+ fragment: TFragment,
936
+ ): SQLFragment<ExtractFragmentFields<TFragment>>;
937
+ /**
938
+ * Generates an `IS NOT NULL` condition from a field name.
939
+ *
940
+ * @param fieldName - The entity field name to check
941
+ */
804
942
  function isNotNullHelper<TFields extends Record<string, any>, N extends keyof TFields>(
805
943
  fieldName: N,
806
944
  ): SQLFragment<TFields>;
@@ -810,10 +948,24 @@ function isNotNullHelper<TFields extends Record<string, any>>(
810
948
  return resolveInnerExpr(expressionOrFieldName).isNotNull();
811
949
  }
812
950
 
813
- function eqHelper<TExpr extends SQLFragment<any>>(
814
- expression: TExpr,
815
- value: ExprValueNullable<TExpr>,
816
- ): SQLFragment<ExtractFields<TExpr>>;
951
+ /**
952
+ * Generates an equality condition (`= value`) from a fragment.
953
+ * Automatically converts `null`/`undefined` to `IS NULL`.
954
+ *
955
+ * @param fragment - A SQLFragment or SQLChainableFragment to compare
956
+ * @param value - The value to compare against
957
+ */
958
+ function eqHelper<TFragment extends SQLFragment<any>>(
959
+ fragment: TFragment,
960
+ value: FragmentValueNullable<TFragment>,
961
+ ): SQLFragment<ExtractFragmentFields<TFragment>>;
962
+ /**
963
+ * Generates an equality condition (`= value`) from a field name.
964
+ * Automatically converts `null`/`undefined` to `IS NULL`.
965
+ *
966
+ * @param fieldName - The entity field name to compare
967
+ * @param value - The value to compare against
968
+ */
817
969
  function eqHelper<
818
970
  TFields extends Record<string, any>,
819
971
  N extends PickSupportedSQLValueKeys<TFields>,
@@ -825,10 +977,24 @@ function eqHelper<TFields extends Record<string, any>>(
825
977
  return resolveInnerExpr(expressionOrFieldName).eq(value);
826
978
  }
827
979
 
828
- function neqHelper<TExpr extends SQLFragment<any>>(
829
- expression: TExpr,
830
- value: ExprValueNullable<TExpr>,
831
- ): SQLFragment<ExtractFields<TExpr>>;
980
+ /**
981
+ * Generates an inequality condition (`!= value`) from a fragment.
982
+ * Automatically converts `null`/`undefined` to `IS NOT NULL`.
983
+ *
984
+ * @param fragment - A SQLFragment or SQLChainableFragment to compare
985
+ * @param value - The value to compare against
986
+ */
987
+ function neqHelper<TFragment extends SQLFragment<any>>(
988
+ fragment: TFragment,
989
+ value: FragmentValueNullable<TFragment>,
990
+ ): SQLFragment<ExtractFragmentFields<TFragment>>;
991
+ /**
992
+ * Generates an inequality condition (`!= value`) from a field name.
993
+ * Automatically converts `null`/`undefined` to `IS NOT NULL`.
994
+ *
995
+ * @param fieldName - The entity field name to compare
996
+ * @param value - The value to compare against
997
+ */
832
998
  function neqHelper<
833
999
  TFields extends Record<string, any>,
834
1000
  N extends PickSupportedSQLValueKeys<TFields>,
@@ -840,10 +1006,22 @@ function neqHelper<TFields extends Record<string, any>>(
840
1006
  return resolveInnerExpr(expressionOrFieldName).neq(value);
841
1007
  }
842
1008
 
843
- function gtHelper<TExpr extends SQLFragment<any>>(
844
- expression: TExpr,
845
- value: ExprValue<TExpr>,
846
- ): SQLFragment<ExtractFields<TExpr>>;
1009
+ /**
1010
+ * Generates a greater-than condition (`> value`) from a fragment.
1011
+ *
1012
+ * @param fragment - A SQLFragment or SQLChainableFragment to compare
1013
+ * @param value - The value to compare against
1014
+ */
1015
+ function gtHelper<TFragment extends SQLFragment<any>>(
1016
+ fragment: TFragment,
1017
+ value: FragmentValue<TFragment>,
1018
+ ): SQLFragment<ExtractFragmentFields<TFragment>>;
1019
+ /**
1020
+ * Generates a greater-than condition (`> value`) from a field name.
1021
+ *
1022
+ * @param fieldName - The entity field name to compare
1023
+ * @param value - The value to compare against
1024
+ */
847
1025
  function gtHelper<
848
1026
  TFields extends Record<string, any>,
849
1027
  N extends PickSupportedSQLValueKeys<TFields>,
@@ -855,10 +1033,22 @@ function gtHelper<TFields extends Record<string, any>>(
855
1033
  return resolveInnerExpr(expressionOrFieldName).gt(value);
856
1034
  }
857
1035
 
858
- function gteHelper<TExpr extends SQLFragment<any>>(
859
- expression: TExpr,
860
- value: ExprValue<TExpr>,
861
- ): SQLFragment<ExtractFields<TExpr>>;
1036
+ /**
1037
+ * Generates a greater-than-or-equal-to condition (`>= value`) from a fragment.
1038
+ *
1039
+ * @param fragment - A SQLFragment or SQLChainableFragment to compare
1040
+ * @param value - The value to compare against
1041
+ */
1042
+ function gteHelper<TFragment extends SQLFragment<any>>(
1043
+ fragment: TFragment,
1044
+ value: FragmentValue<TFragment>,
1045
+ ): SQLFragment<ExtractFragmentFields<TFragment>>;
1046
+ /**
1047
+ * Generates a greater-than-or-equal-to condition (`>= value`) from a field name.
1048
+ *
1049
+ * @param fieldName - The entity field name to compare
1050
+ * @param value - The value to compare against
1051
+ */
862
1052
  function gteHelper<
863
1053
  TFields extends Record<string, any>,
864
1054
  N extends PickSupportedSQLValueKeys<TFields>,
@@ -870,10 +1060,22 @@ function gteHelper<TFields extends Record<string, any>>(
870
1060
  return resolveInnerExpr(expressionOrFieldName).gte(value);
871
1061
  }
872
1062
 
873
- function ltHelper<TExpr extends SQLFragment<any>>(
874
- expression: TExpr,
875
- value: ExprValue<TExpr>,
876
- ): SQLFragment<ExtractFields<TExpr>>;
1063
+ /**
1064
+ * Generates a less-than condition (`< value`) from a fragment.
1065
+ *
1066
+ * @param fragment - A SQLFragment or SQLChainableFragment to compare
1067
+ * @param value - The value to compare against
1068
+ */
1069
+ function ltHelper<TFragment extends SQLFragment<any>>(
1070
+ fragment: TFragment,
1071
+ value: FragmentValue<TFragment>,
1072
+ ): SQLFragment<ExtractFragmentFields<TFragment>>;
1073
+ /**
1074
+ * Generates a less-than condition (`< value`) from a field name.
1075
+ *
1076
+ * @param fieldName - The entity field name to compare
1077
+ * @param value - The value to compare against
1078
+ */
877
1079
  function ltHelper<
878
1080
  TFields extends Record<string, any>,
879
1081
  N extends PickSupportedSQLValueKeys<TFields>,
@@ -885,10 +1087,22 @@ function ltHelper<TFields extends Record<string, any>>(
885
1087
  return resolveInnerExpr(expressionOrFieldName).lt(value);
886
1088
  }
887
1089
 
888
- function lteHelper<TExpr extends SQLFragment<any>>(
889
- expression: TExpr,
890
- value: ExprValue<TExpr>,
891
- ): SQLFragment<ExtractFields<TExpr>>;
1090
+ /**
1091
+ * Generates a less-than-or-equal-to condition (`<= value`) from a fragment.
1092
+ *
1093
+ * @param fragment - A SQLFragment or SQLChainableFragment to compare
1094
+ * @param value - The value to compare against
1095
+ */
1096
+ function lteHelper<TFragment extends SQLFragment<any>>(
1097
+ fragment: TFragment,
1098
+ value: FragmentValue<TFragment>,
1099
+ ): SQLFragment<ExtractFragmentFields<TFragment>>;
1100
+ /**
1101
+ * Generates a less-than-or-equal-to condition (`<= value`) from a field name.
1102
+ *
1103
+ * @param fieldName - The entity field name to compare
1104
+ * @param value - The value to compare against
1105
+ */
892
1106
  function lteHelper<
893
1107
  TFields extends Record<string, any>,
894
1108
  N extends PickSupportedSQLValueKeys<TFields>,
@@ -900,10 +1114,24 @@ function lteHelper<TFields extends Record<string, any>>(
900
1114
  return resolveInnerExpr(expressionOrFieldName).lte(value);
901
1115
  }
902
1116
 
903
- function jsonContainsHelper<TExpr extends SQLFragment<any>>(
904
- expression: TExpr,
1117
+ /**
1118
+ * Generates a JSON contains condition (`@>`) from a fragment.
1119
+ * Tests whether the JSON value contains the given value.
1120
+ *
1121
+ * @param fragment - A SQLFragment or SQLChainableFragment to check
1122
+ * @param value - The JSON value to check containment of
1123
+ */
1124
+ function jsonContainsHelper<TFragment extends SQLFragment<any>>(
1125
+ fragment: TFragment,
905
1126
  value: JsonSerializable,
906
- ): SQLFragment<ExtractFields<TExpr>>;
1127
+ ): SQLFragment<ExtractFragmentFields<TFragment>>;
1128
+ /**
1129
+ * Generates a JSON contains condition (`@>`) from a field name.
1130
+ * Tests whether the JSON value contains the given value.
1131
+ *
1132
+ * @param fieldName - The entity field name to check
1133
+ * @param value - The JSON value to check containment of
1134
+ */
907
1135
  function jsonContainsHelper<TFields extends Record<string, any>, N extends keyof TFields>(
908
1136
  fieldName: N,
909
1137
  value: JsonSerializable,
@@ -921,10 +1149,24 @@ function jsonContainsHelper<TFields extends Record<string, any>>(
921
1149
  return sql`${inner} @> ${serialized}::jsonb`;
922
1150
  }
923
1151
 
924
- function jsonContainedByHelper<TExpr extends SQLFragment<any>>(
925
- expression: TExpr,
1152
+ /**
1153
+ * Generates a JSON contained-by condition (`<@`) from a fragment.
1154
+ * Tests whether the JSON value is contained by the given value.
1155
+ *
1156
+ * @param fragment - A SQLFragment or SQLChainableFragment to check
1157
+ * @param value - The JSON value to check containment against
1158
+ */
1159
+ function jsonContainedByHelper<TFragment extends SQLFragment<any>>(
1160
+ fragment: TFragment,
926
1161
  value: JsonSerializable,
927
- ): SQLFragment<ExtractFields<TExpr>>;
1162
+ ): SQLFragment<ExtractFragmentFields<TFragment>>;
1163
+ /**
1164
+ * Generates a JSON contained-by condition (`<@`) from a field name.
1165
+ * Tests whether the JSON value is contained by the given value.
1166
+ *
1167
+ * @param fieldName - The entity field name to check
1168
+ * @param value - The JSON value to check containment against
1169
+ */
928
1170
  function jsonContainedByHelper<TFields extends Record<string, any>, N extends keyof TFields>(
929
1171
  fieldName: N,
930
1172
  value: JsonSerializable,
@@ -942,10 +1184,24 @@ function jsonContainedByHelper<TFields extends Record<string, any>>(
942
1184
  return sql`${inner} <@ ${serialized}::jsonb`;
943
1185
  }
944
1186
 
945
- function jsonPathHelper<TExpr extends SQLFragment<any>>(
946
- expression: TExpr,
1187
+ /**
1188
+ * JSON path extraction (`->`) from a fragment. Returns JSON.
1189
+ * Returns an SQLChainableFragment for fluent chaining.
1190
+ *
1191
+ * @param fragment - A SQLFragment or SQLChainableFragment to extract from
1192
+ * @param path - The JSON key to extract
1193
+ */
1194
+ function jsonPathHelper<TFragment extends SQLFragment<any>>(
1195
+ fragment: TFragment,
947
1196
  path: string,
948
- ): SQLChainableFragment<ExtractFields<TExpr>, SupportedSQLValue>;
1197
+ ): SQLChainableFragment<ExtractFragmentFields<TFragment>, SupportedSQLValue>;
1198
+ /**
1199
+ * JSON path extraction (`->`) from a field name. Returns JSON.
1200
+ * Returns an SQLChainableFragment for fluent chaining.
1201
+ *
1202
+ * @param fieldName - The entity field name to extract from
1203
+ * @param path - The JSON key to extract
1204
+ */
949
1205
  function jsonPathHelper<TFields extends Record<string, any>, N extends keyof TFields>(
950
1206
  fieldName: N,
951
1207
  path: string,
@@ -959,10 +1215,24 @@ function jsonPathHelper<TFields extends Record<string, any>>(
959
1215
  return new SQLChainableFragment(wrapped.sql, wrapped.bindings);
960
1216
  }
961
1217
 
962
- function jsonPathTextHelper<TExpr extends SQLFragment<any>>(
963
- expression: TExpr,
1218
+ /**
1219
+ * JSON path text extraction (`->>`) from a fragment. Returns text.
1220
+ * Returns an SQLChainableFragment for fluent chaining.
1221
+ *
1222
+ * @param fragment - A SQLFragment or SQLChainableFragment to extract from
1223
+ * @param path - The JSON key to extract as text
1224
+ */
1225
+ function jsonPathTextHelper<TFragment extends SQLFragment<any>>(
1226
+ fragment: TFragment,
964
1227
  path: string,
965
- ): SQLChainableFragment<ExtractFields<TExpr>, SupportedSQLValue>;
1228
+ ): SQLChainableFragment<ExtractFragmentFields<TFragment>, SupportedSQLValue>;
1229
+ /**
1230
+ * JSON path text extraction (`->>`) from a field name. Returns text.
1231
+ * Returns an SQLChainableFragment for fluent chaining.
1232
+ *
1233
+ * @param fieldName - The entity field name to extract from
1234
+ * @param path - The JSON key to extract as text
1235
+ */
966
1236
  function jsonPathTextHelper<TFields extends Record<string, any>, N extends keyof TFields>(
967
1237
  fieldName: N,
968
1238
  path: string,
@@ -976,10 +1246,24 @@ function jsonPathTextHelper<TFields extends Record<string, any>>(
976
1246
  return new SQLChainableFragment(wrapped.sql, wrapped.bindings);
977
1247
  }
978
1248
 
979
- function jsonDeepPathHelper<TExpr extends SQLFragment<any>>(
980
- expression: TExpr,
1249
+ /**
1250
+ * JSON deep path extraction (`#>`) from a fragment. Returns JSON at the specified key path.
1251
+ * Returns an SQLChainableFragment for fluent chaining.
1252
+ *
1253
+ * @param fragment - A SQLFragment or SQLChainableFragment to extract from
1254
+ * @param path - Array of keys forming the path (e.g., ['user', 'address', 'city'])
1255
+ */
1256
+ function jsonDeepPathHelper<TFragment extends SQLFragment<any>>(
1257
+ fragment: TFragment,
981
1258
  path: readonly string[],
982
- ): SQLChainableFragment<ExtractFields<TExpr>, SupportedSQLValue>;
1259
+ ): SQLChainableFragment<ExtractFragmentFields<TFragment>, SupportedSQLValue>;
1260
+ /**
1261
+ * JSON deep path extraction (`#>`) from a field name. Returns JSON at the specified key path.
1262
+ * Returns an SQLChainableFragment for fluent chaining.
1263
+ *
1264
+ * @param fieldName - The entity field name to extract from
1265
+ * @param path - Array of keys forming the path (e.g., ['user', 'address', 'city'])
1266
+ */
983
1267
  function jsonDeepPathHelper<TFields extends Record<string, any>, N extends keyof TFields>(
984
1268
  fieldName: N,
985
1269
  path: readonly string[],
@@ -994,10 +1278,24 @@ function jsonDeepPathHelper<TFields extends Record<string, any>>(
994
1278
  return new SQLChainableFragment(wrapped.sql, wrapped.bindings);
995
1279
  }
996
1280
 
997
- function jsonDeepPathTextHelper<TExpr extends SQLFragment<any>>(
998
- expression: TExpr,
1281
+ /**
1282
+ * JSON deep path text extraction (`#>>`) from a fragment. Returns text at the specified key path.
1283
+ * Returns an SQLChainableFragment for fluent chaining.
1284
+ *
1285
+ * @param fragment - A SQLFragment or SQLChainableFragment to extract from
1286
+ * @param path - Array of keys forming the path (e.g., ['user', 'address', 'city'])
1287
+ */
1288
+ function jsonDeepPathTextHelper<TFragment extends SQLFragment<any>>(
1289
+ fragment: TFragment,
999
1290
  path: readonly string[],
1000
- ): SQLChainableFragment<ExtractFields<TExpr>, SupportedSQLValue>;
1291
+ ): SQLChainableFragment<ExtractFragmentFields<TFragment>, SupportedSQLValue>;
1292
+ /**
1293
+ * JSON deep path text extraction (`#>>`) from a field name. Returns text at the specified key path.
1294
+ * Returns an SQLChainableFragment for fluent chaining.
1295
+ *
1296
+ * @param fieldName - The entity field name to extract from
1297
+ * @param path - Array of keys forming the path (e.g., ['user', 'address', 'city'])
1298
+ */
1001
1299
  function jsonDeepPathTextHelper<TFields extends Record<string, any>, N extends keyof TFields>(
1002
1300
  fieldName: N,
1003
1301
  path: readonly string[],
@@ -1012,10 +1310,24 @@ function jsonDeepPathTextHelper<TFields extends Record<string, any>>(
1012
1310
  return new SQLChainableFragment(wrapped.sql, wrapped.bindings);
1013
1311
  }
1014
1312
 
1015
- function castHelper<TExpr extends SQLFragment<any>>(
1016
- expression: TExpr,
1313
+ /**
1314
+ * SQL type cast (`::type`) from a fragment.
1315
+ * Returns an SQLChainableFragment for fluent chaining.
1316
+ *
1317
+ * @param fragment - A SQLFragment or SQLChainableFragment to cast
1318
+ * @param typeName - The PostgreSQL type name (e.g., 'int', 'text', 'timestamptz')
1319
+ */
1320
+ function castHelper<TFragment extends SQLFragment<any>>(
1321
+ fragment: TFragment,
1017
1322
  typeName: PostgresCastType,
1018
- ): SQLChainableFragment<ExtractFields<TExpr>, SupportedSQLValue>;
1323
+ ): SQLChainableFragment<ExtractFragmentFields<TFragment>, SupportedSQLValue>;
1324
+ /**
1325
+ * SQL type cast (`::type`) from a field name.
1326
+ * Returns an SQLChainableFragment for fluent chaining.
1327
+ *
1328
+ * @param fieldName - The entity field name to cast
1329
+ * @param typeName - The PostgreSQL type name (e.g., 'int', 'text', 'timestamptz')
1330
+ */
1019
1331
  function castHelper<TFields extends Record<string, any>, N extends keyof TFields>(
1020
1332
  fieldName: N,
1021
1333
  typeName: PostgresCastType,
@@ -1033,9 +1345,21 @@ function castHelper<TFields extends Record<string, any>>(
1033
1345
  return new SQLChainableFragment(wrapped.sql, wrapped.bindings);
1034
1346
  }
1035
1347
 
1036
- function lowerHelper<TExpr extends SQLFragment<any>>(
1037
- expression: TExpr,
1038
- ): SQLChainableFragment<ExtractFields<TExpr>, SupportedSQLValue>;
1348
+ /**
1349
+ * Wraps a fragment in `LOWER()` to convert to lowercase.
1350
+ * Returns an SQLChainableFragment for fluent chaining.
1351
+ *
1352
+ * @param fragment - A SQLFragment or SQLChainableFragment to convert
1353
+ */
1354
+ function lowerHelper<TFragment extends SQLFragment<any>>(
1355
+ fragment: TFragment,
1356
+ ): SQLChainableFragment<ExtractFragmentFields<TFragment>, SupportedSQLValue>;
1357
+ /**
1358
+ * Wraps a field in `LOWER()` to convert to lowercase.
1359
+ * Returns an SQLChainableFragment for fluent chaining.
1360
+ *
1361
+ * @param fieldName - The entity field name to convert
1362
+ */
1039
1363
  function lowerHelper<TFields extends Record<string, any>, N extends PickStringValueKeys<TFields>>(
1040
1364
  fieldName: N,
1041
1365
  ): SQLChainableFragment<TFields, TFields[N]>;
@@ -1047,9 +1371,21 @@ function lowerHelper<TFields extends Record<string, any>>(
1047
1371
  return new SQLChainableFragment(wrapped.sql, wrapped.bindings);
1048
1372
  }
1049
1373
 
1050
- function upperHelper<TExpr extends SQLFragment<any>>(
1051
- expression: TExpr,
1052
- ): SQLChainableFragment<ExtractFields<TExpr>, SupportedSQLValue>;
1374
+ /**
1375
+ * Wraps a fragment in `UPPER()` to convert to uppercase.
1376
+ * Returns an SQLChainableFragment for fluent chaining.
1377
+ *
1378
+ * @param fragment - A SQLFragment or SQLChainableFragment to convert
1379
+ */
1380
+ function upperHelper<TFragment extends SQLFragment<any>>(
1381
+ fragment: TFragment,
1382
+ ): SQLChainableFragment<ExtractFragmentFields<TFragment>, SupportedSQLValue>;
1383
+ /**
1384
+ * Wraps a field in `UPPER()` to convert to uppercase.
1385
+ * Returns an SQLChainableFragment for fluent chaining.
1386
+ *
1387
+ * @param fieldName - The entity field name to convert
1388
+ */
1053
1389
  function upperHelper<TFields extends Record<string, any>, N extends PickStringValueKeys<TFields>>(
1054
1390
  fieldName: N,
1055
1391
  ): SQLChainableFragment<TFields, TFields[N]>;
@@ -1061,9 +1397,21 @@ function upperHelper<TFields extends Record<string, any>>(
1061
1397
  return new SQLChainableFragment(wrapped.sql, wrapped.bindings);
1062
1398
  }
1063
1399
 
1064
- function trimHelper<TExpr extends SQLFragment<any>>(
1065
- expression: TExpr,
1066
- ): SQLChainableFragment<ExtractFields<TExpr>, SupportedSQLValue>;
1400
+ /**
1401
+ * Wraps a fragment in `TRIM()` to remove leading and trailing whitespace.
1402
+ * Returns an SQLChainableFragment for fluent chaining.
1403
+ *
1404
+ * @param fragment - A SQLFragment or SQLChainableFragment to trim
1405
+ */
1406
+ function trimHelper<TFragment extends SQLFragment<any>>(
1407
+ fragment: TFragment,
1408
+ ): SQLChainableFragment<ExtractFragmentFields<TFragment>, SupportedSQLValue>;
1409
+ /**
1410
+ * Wraps a field in `TRIM()` to remove leading and trailing whitespace.
1411
+ * Returns an SQLChainableFragment for fluent chaining.
1412
+ *
1413
+ * @param fieldName - The entity field name to trim
1414
+ */
1067
1415
  function trimHelper<TFields extends Record<string, any>, N extends PickStringValueKeys<TFields>>(
1068
1416
  fieldName: N,
1069
1417
  ): SQLChainableFragment<TFields, TFields[N]>;
@@ -2196,6 +2196,32 @@ describe('postgres entity integration', () => {
2196
2196
  },
2197
2197
  }),
2198
2198
  ).rejects.toThrow("Cursor is missing required 'id' field.");
2199
+
2200
+ // Try with valid base64-encoded JSON that decodes to a non-object primitive
2201
+ const primitiveCursor = Buffer.from(JSON.stringify(12345)).toString('base64url');
2202
+ await expect(
2203
+ PostgresTestEntity.knexLoader(vc).loadPageAsync({
2204
+ first: 10,
2205
+ after: primitiveCursor,
2206
+ pagination: {
2207
+ strategy: PaginationStrategy.STANDARD,
2208
+ orderBy: [],
2209
+ },
2210
+ }),
2211
+ ).rejects.toThrow("Cursor is missing required 'id' field.");
2212
+
2213
+ // Try with valid base64-encoded JSON string primitive
2214
+ const stringPrimitiveCursor = Buffer.from(JSON.stringify('hello')).toString('base64url');
2215
+ await expect(
2216
+ PostgresTestEntity.knexLoader(vc).loadPageAsync({
2217
+ first: 10,
2218
+ after: stringPrimitiveCursor,
2219
+ pagination: {
2220
+ strategy: PaginationStrategy.STANDARD,
2221
+ orderBy: [],
2222
+ },
2223
+ }),
2224
+ ).rejects.toThrow("Cursor is missing required 'id' field.");
2199
2225
  });
2200
2226
 
2201
2227
  it('performs pagination with both loader types', async () => {
@@ -559,6 +559,7 @@ export class EntityKnexDataManager<
559
559
 
560
560
  private decodeOpaqueCursor(cursor: string): TFields[TIDField] {
561
561
  let parsedCursor: any;
562
+
562
563
  try {
563
564
  const decoded = Buffer.from(cursor, 'base64url').toString();
564
565
  parsedCursor = JSON.parse(decoded);
@@ -569,13 +570,13 @@ export class EntityKnexDataManager<
569
570
  );
570
571
  }
571
572
 
572
- if (!('id' in parsedCursor)) {
573
- throw new EntityDatabaseAdapterPaginationCursorInvalidError(
574
- `Cursor is missing required 'id' field. Parsed cursor: ${JSON.stringify(parsedCursor)}`,
575
- );
573
+ if (typeof parsedCursor === 'object' && 'id' in parsedCursor) {
574
+ return parsedCursor.id;
576
575
  }
577
576
 
578
- return parsedCursor.id;
577
+ throw new EntityDatabaseAdapterPaginationCursorInvalidError(
578
+ `Cursor is missing required 'id' field. Parsed cursor: ${JSON.stringify(parsedCursor)}`,
579
+ );
579
580
  }
580
581
 
581
582
  private resolveSearchFieldToSQLFragment(