proto.io 0.0.215 → 0.0.216

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/adapters/file/aliyun-oss.d.ts +3 -3
  2. package/dist/adapters/file/database.d.ts +2 -2
  3. package/dist/adapters/file/database.js +1 -1
  4. package/dist/adapters/file/database.mjs +2 -2
  5. package/dist/adapters/file/filesystem.d.ts +3 -3
  6. package/dist/adapters/file/google-cloud-storage.d.ts +3 -3
  7. package/dist/adapters/storage/progres.d.ts +4 -8
  8. package/dist/adapters/storage/progres.js +444 -425
  9. package/dist/adapters/storage/progres.js.map +1 -1
  10. package/dist/adapters/storage/progres.mjs +445 -426
  11. package/dist/adapters/storage/progres.mjs.map +1 -1
  12. package/dist/client.d.ts +3 -3
  13. package/dist/client.mjs +3 -3
  14. package/dist/index.d.ts +3 -3
  15. package/dist/index.js +7 -8
  16. package/dist/index.js.map +1 -1
  17. package/dist/index.mjs +10 -11
  18. package/dist/index.mjs.map +1 -1
  19. package/dist/internals/{base-Cp5le5dC.d.ts → base-BO3ZP6EF.d.ts} +2 -2
  20. package/dist/internals/base-BO3ZP6EF.d.ts.map +1 -0
  21. package/dist/internals/{chunk--Vo2-p-z.d.ts → chunk-DDkLpKXp.d.ts} +3 -3
  22. package/dist/internals/chunk-DDkLpKXp.d.ts.map +1 -0
  23. package/dist/internals/{index-al1N-qi7.mjs → index-BzDsTt4R.mjs} +2 -2
  24. package/dist/internals/{index-al1N-qi7.mjs.map → index-BzDsTt4R.mjs.map} +1 -1
  25. package/dist/internals/{index-CZUGnb-y.d.ts → index-CYhA8SU8.d.ts} +2 -2
  26. package/dist/internals/index-CYhA8SU8.d.ts.map +1 -0
  27. package/dist/internals/{index-ZPbBr9Db.mjs → index-DF2AfSGK.mjs} +2 -2
  28. package/dist/internals/index-DF2AfSGK.mjs.map +1 -0
  29. package/dist/internals/index-DfnPpl1I.js.map +1 -1
  30. package/dist/internals/{index-YLrO0f2D.d.ts → index-HdMgLYtD.d.ts} +8 -5
  31. package/dist/internals/index-HdMgLYtD.d.ts.map +1 -0
  32. package/dist/internals/{validator-m6wY35c6.js → validator-BBjOdLiT.js} +4 -1
  33. package/dist/internals/validator-BBjOdLiT.js.map +1 -0
  34. package/dist/internals/{validator-ChrCrz_C.mjs → validator-LNgZGT_l.mjs} +5 -3
  35. package/dist/internals/validator-LNgZGT_l.mjs.map +1 -0
  36. package/package.json +1 -1
  37. package/dist/internals/base-Cp5le5dC.d.ts.map +0 -1
  38. package/dist/internals/chunk--Vo2-p-z.d.ts.map +0 -1
  39. package/dist/internals/index-CZUGnb-y.d.ts.map +0 -1
  40. package/dist/internals/index-YLrO0f2D.d.ts.map +0 -1
  41. package/dist/internals/index-ZPbBr9Db.mjs.map +0 -1
  42. package/dist/internals/validator-ChrCrz_C.mjs.map +0 -1
  43. package/dist/internals/validator-m6wY35c6.js.map +0 -1
@@ -9,7 +9,7 @@ var QueryStream = require('pg-query-stream');
9
9
  var utilsJs = require('@o2ter/utils-js');
10
10
  var Decimal = require('decimal.js');
11
11
  var utils = require('pg/lib/utils');
12
- var validator = require('../../internals/validator-m6wY35c6.js');
12
+ var validator = require('../../internals/validator-BBjOdLiT.js');
13
13
  require('@o2ter/crypto-js');
14
14
  var _const = require('../../internals/const-C3I6cfav.js');
15
15
  var random$1 = require('../../internals/random-nkOQ9U6S.js');
@@ -540,6 +540,399 @@ class QueryCompiler {
540
540
  }
541
541
  }
542
542
 
543
+ //
544
+ // encode.ts
545
+ //
546
+ // The MIT License
547
+ // Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.
548
+ //
549
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
550
+ // of this software and associated documentation files (the "Software"), to deal
551
+ // in the Software without restriction, including without limitation the rights
552
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
553
+ // copies of the Software, and to permit persons to whom the Software is
554
+ // furnished to do so, subject to the following conditions:
555
+ //
556
+ // The above copyright notice and this permission notice shall be included in
557
+ // all copies or substantial portions of the Software.
558
+ //
559
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
560
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
561
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
562
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
563
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
564
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
565
+ // THE SOFTWARE.
566
+ //
567
+ const _encodeJsonValue = (value) => {
568
+ if (_.isArray(value))
569
+ return sql `jsonb_build_array(${_.map(value, x => _encodeJsonValue(x))})`;
570
+ if (_.isPlainObject(value))
571
+ return sql `jsonb_build_object(${_.map(value, (v, k) => sql `${{ value: k }}, ${_encodeJsonValue(v)}`)})`;
572
+ return sql `to_jsonb(${{ value }})`;
573
+ };
574
+ const _jsonPopulateInclude = (className, colname, dataType) => {
575
+ switch (index._typeof(dataType)) {
576
+ case 'decimal':
577
+ return sql `jsonb_build_object(
578
+ '$decimal', CAST(${{ identifier: className }}.${{ identifier: colname }} AS TEXT)
579
+ ) AS ${{ identifier: colname }}`;
580
+ case 'date':
581
+ return sql `jsonb_build_object(
582
+ '$date', to_char(${{ identifier: className }}.${{ identifier: colname }} AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"')
583
+ ) AS ${{ identifier: colname }}`;
584
+ default:
585
+ return sql `${{ identifier: className }}.${{ identifier: colname }}`;
586
+ }
587
+ };
588
+ const encodeType = (colname, dataType, value) => {
589
+ if (_.isNil(value))
590
+ return sql `NULL`;
591
+ switch (_.isString(dataType) ? dataType : dataType.type) {
592
+ case 'boolean':
593
+ if (_.isBoolean(value))
594
+ return sql `${{ value }}`;
595
+ break;
596
+ case 'number':
597
+ if (_.isNumber(value) && _.isFinite(value))
598
+ return sql `${{ value }}`;
599
+ if (value instanceof Decimal)
600
+ return sql `${{ value: value.toNumber() }}`;
601
+ break;
602
+ case 'decimal':
603
+ if (_.isNumber(value) && _.isFinite(value))
604
+ return sql `CAST(${{ quote: (new Decimal(value)).toString() }} AS DECIMAL)`;
605
+ if (value instanceof Decimal)
606
+ return sql `CAST(${{ quote: value.toString() }} AS DECIMAL)`;
607
+ break;
608
+ case 'string':
609
+ if (_.isString(value))
610
+ return sql `${{ value }}`;
611
+ break;
612
+ case 'string[]':
613
+ if (_.isArray(value) && _.every(value, x => _.isString(x)))
614
+ return sql `ARRAY[${_.map(value, x => sql `${{ value: x }}`)}]::TEXT[]`;
615
+ break;
616
+ case 'date':
617
+ if (_.isDate(value))
618
+ return sql `${{ value }}`;
619
+ break;
620
+ case 'object':
621
+ if (_.isPlainObject(value))
622
+ return sql `${{ value: index._encodeValue(value) }}`;
623
+ break;
624
+ case 'vector':
625
+ if (!_.isArray(value) || value.length !== index.dimensionOf(dataType))
626
+ break;
627
+ if (!_.every(value, x => _.isFinite(x)))
628
+ break;
629
+ return sql `${{ value }}::DOUBLE PRECISION[]`;
630
+ case 'array':
631
+ if (!_.isArray(value))
632
+ break;
633
+ return sql `ARRAY[${_.map(value, x => _encodeJsonValue(index._encodeValue(x)))}]::JSONB[]`;
634
+ case 'pointer':
635
+ if (value instanceof index.TObject && value.objectId)
636
+ return sql `${{ value: `${value.className}$${value.objectId}` }}`;
637
+ break;
638
+ case 'relation':
639
+ if (_.isArray(value) && _.every(value, x => x instanceof index.TObject && x.objectId)) {
640
+ return sql `${{ value: _.uniq(_.map(value, (x) => `${x.className}$${x.objectId}`)) }}`;
641
+ }
642
+ break;
643
+ }
644
+ throw Error('Invalid data type');
645
+ };
646
+ const decodeType = (type, value) => {
647
+ switch (type) {
648
+ case 'boolean':
649
+ if (_.isBoolean(value))
650
+ return value;
651
+ if (value === 'true')
652
+ return true;
653
+ if (value === 'false')
654
+ return false;
655
+ break;
656
+ case 'number':
657
+ if (_.isNumber(value))
658
+ return value;
659
+ if (_.isString(value)) {
660
+ const float = parseFloat(value);
661
+ return _.isNaN(float) ? null : float;
662
+ }
663
+ break;
664
+ case 'decimal':
665
+ if (_.isString(value) || _.isNumber(value))
666
+ return new Decimal(value);
667
+ if (value instanceof Decimal)
668
+ return value;
669
+ if (_.isPlainObject(value) && _.isString(value.$decimal))
670
+ return new Decimal(value.$decimal);
671
+ break;
672
+ case 'string':
673
+ if (_.isString(value))
674
+ return value;
675
+ break;
676
+ case 'string[]':
677
+ if (_.isArray(value) && _.every(value, x => _.isString(x)))
678
+ return value;
679
+ break;
680
+ case 'date':
681
+ if (_.isDate(value))
682
+ return value;
683
+ if (_.isString(value)) {
684
+ const date = new Date(value);
685
+ if (isFinite(date.valueOf()))
686
+ return date;
687
+ }
688
+ if (_.isPlainObject(value) && _.isString(value.$date))
689
+ return new Date(value.$date);
690
+ break;
691
+ case 'object':
692
+ if (_.isPlainObject(value))
693
+ return index._decodeValue(value);
694
+ break;
695
+ case 'array':
696
+ if (_.isArray(value))
697
+ return index._decodeValue(value);
698
+ break;
699
+ case 'vector':
700
+ if (!_.isArray(value))
701
+ break;
702
+ if (_.every(value, x => _.isNumber(x))) {
703
+ return value;
704
+ }
705
+ break;
706
+ }
707
+ return null;
708
+ };
709
+
710
+ //
711
+ // expressions.ts
712
+ //
713
+ // The MIT License
714
+ // Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.
715
+ //
716
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
717
+ // of this software and associated documentation files (the "Software"), to deal
718
+ // in the Software without restriction, including without limitation the rights
719
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
720
+ // copies of the Software, and to permit persons to whom the Software is
721
+ // furnished to do so, subject to the following conditions:
722
+ //
723
+ // The above copyright notice and this permission notice shall be included in
724
+ // all copies or substantial portions of the Software.
725
+ //
726
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
727
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
728
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
729
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
730
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
731
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
732
+ // THE SOFTWARE.
733
+ //
734
+ const isArrayExpression = (expr) => {
735
+ if (expr instanceof validator.QueryArrayExpression)
736
+ return true;
737
+ if (expr instanceof validator.QueryValueExpression)
738
+ return _.isArray(expr.value);
739
+ return false;
740
+ };
741
+ const arrayLength = (expr) => {
742
+ if (expr instanceof validator.QueryArrayExpression)
743
+ return expr.exprs.length;
744
+ if (expr instanceof validator.QueryValueExpression)
745
+ return _.isArray(expr.value) ? expr.value.length : 0;
746
+ return 0;
747
+ };
748
+ const mapExpression = (expr, callback) => {
749
+ if (expr instanceof validator.QueryArrayExpression)
750
+ return _.map(expr.exprs, x => callback(x));
751
+ if (expr instanceof validator.QueryValueExpression)
752
+ return _.isArray(expr.value) ? _.map(expr.value, x => callback(new validator.QueryValueExpression(x))) : [];
753
+ return [];
754
+ };
755
+ const _PrimitiveValue = ['boolean', 'number', 'decimal', 'string', 'date'];
756
+ const encodeTypedQueryExpression = (compiler, parent, expr) => {
757
+ if (expr instanceof validator.QueryKeyExpression) {
758
+ const { element, dataType } = fetchElement(compiler, parent, expr.key);
759
+ const _dataType = dataType ? index._typeof(dataType) : null;
760
+ if (_dataType === 'number') {
761
+ return [
762
+ { type: 'number', sql: element },
763
+ { type: 'decimal', sql: sql `CAST((${element}) AS DECIMAL)` },
764
+ ];
765
+ }
766
+ else if (_dataType === 'decimal') {
767
+ return [
768
+ { type: 'decimal', sql: element },
769
+ { type: 'number', sql: element },
770
+ ];
771
+ }
772
+ else if (_dataType && _PrimitiveValue.includes(_dataType)) {
773
+ return [{ type: _dataType, sql: element }];
774
+ }
775
+ }
776
+ if (expr instanceof validator.QueryValueExpression) {
777
+ if (_.isBoolean(expr.value))
778
+ return [{ type: 'boolean', sql: sql `${{ value: expr.value }}` }];
779
+ if (_.isNumber(expr.value))
780
+ return [
781
+ { type: 'number', sql: sql `${{ value: expr.value }}` },
782
+ { type: 'decimal', sql: sql `CAST(${{ quote: (new Decimal(expr.value)).toString() }} AS DECIMAL)` },
783
+ ];
784
+ if (expr.value instanceof Decimal)
785
+ return [
786
+ { type: 'decimal', sql: sql `CAST(${{ quote: expr.value.toString() }} AS DECIMAL)` },
787
+ { type: 'number', sql: sql `${{ value: expr.value.toNumber() }}` },
788
+ ];
789
+ if (_.isString(expr.value))
790
+ return [{ type: 'string', sql: sql `${{ value: expr.value }}` }];
791
+ if (_.isDate(expr.value))
792
+ return [{ type: 'date', sql: sql `${{ value: expr.value }}` }];
793
+ }
794
+ if (expr instanceof validator.QueryCoditionalExpression ||
795
+ expr instanceof validator.QueryComparisonExpression ||
796
+ expr instanceof validator.QueryNotExpression) {
797
+ const value = encodeBooleanExpression(compiler, parent, expr);
798
+ if (value)
799
+ return [{ type: 'boolean', sql: value }];
800
+ }
801
+ if (expr instanceof validator.QueryDistanceExpression) {
802
+ const value = encodeDistanceQueryExpression(compiler, parent, expr);
803
+ return [{ type: 'number', sql: value }];
804
+ }
805
+ };
806
+ const encodeJsonQueryExpression = (compiler, parent, expr) => {
807
+ if (expr instanceof validator.QueryKeyExpression) {
808
+ const { element, dataType } = fetchElement(compiler, parent, expr.key);
809
+ if (dataType && index.isPrimitive(dataType)) {
810
+ switch (index._typeof(dataType)) {
811
+ case 'boolean': return sql `to_jsonb(${element})`;
812
+ case 'number': return sql `to_jsonb(${element})`;
813
+ case 'decimal': return sql `jsonb_build_object('$decimal', CAST(${element} AS TEXT))`;
814
+ case 'string': return sql `to_jsonb(${element})`;
815
+ case 'string[]': return sql `to_jsonb(${element})`;
816
+ case 'date': return sql `jsonb_build_object(
817
+ '$date', to_char(${element} AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"')
818
+ )`;
819
+ }
820
+ }
821
+ return sql `${element}`;
822
+ }
823
+ if (expr instanceof validator.QueryValueExpression) {
824
+ return _encodeJsonValue(index._encodeValue(expr.value));
825
+ }
826
+ if (expr instanceof validator.QueryArrayExpression) {
827
+ return sql `jsonb_build_array(${_.map(expr.exprs, x => encodeJsonQueryExpression(compiler, parent, x))})`;
828
+ }
829
+ const value = encodeQueryExpression(compiler, parent, expr);
830
+ if (!value)
831
+ throw Error('Invalid expression');
832
+ return sql `to_jsonb(${value})`;
833
+ };
834
+ const encodeVectorExpression = (compiler, parent, exprs) => {
835
+ if (exprs.length === 1) {
836
+ const [expr] = exprs;
837
+ if (expr instanceof validator.QueryKeyExpression) {
838
+ const { element, dataType } = fetchElement(compiler, parent, expr.key);
839
+ if (!dataType || !index.isVector(dataType))
840
+ throw Error('Invalid expression');
841
+ return { sql: element, dimension: dataType.dimension };
842
+ }
843
+ if (expr instanceof validator.QueryValueExpression) {
844
+ if (!_.isArray(expr.value) || !_.every(expr.value, x => _.isFinite(x)))
845
+ throw Error('Invalid expression');
846
+ return { sql: sql `${{ value: expr.value }}::DOUBLE PRECISION[]`, dimension: expr.value.length };
847
+ }
848
+ }
849
+ const result = _.map(exprs, x => _.find(encodeTypedQueryExpression(compiler, parent, x), e => e.type === 'number')?.sql);
850
+ if (_.some(result, x => _.isNil(x)))
851
+ throw Error('Invalid expression');
852
+ return { sql: sql `ARRAY[${_.map(result, x => sql `COALESCE(${x}, 0)`)}]`, dimension: result.length };
853
+ };
854
+ const encodeDistanceQueryExpression = (compiler, parent, expr) => {
855
+ const { sql: left, dimension: d1 } = encodeVectorExpression(compiler, parent, expr.left);
856
+ const { sql: right, dimension: d2 } = encodeVectorExpression(compiler, parent, expr.right);
857
+ if (d1 !== d2)
858
+ throw Error('Invalid expression');
859
+ const operatorMap = {
860
+ '$distance': sql `<->`,
861
+ '$innerProduct': sql `<#>`,
862
+ '$negInnerProduct': sql `<#>`,
863
+ '$cosineDistance': sql `<=>`,
864
+ '$rectilinearDistance': sql `<+>`,
865
+ };
866
+ const _expr = sql `
867
+ CAST(
868
+ ${left} AS VECTOR(${{ literal: `${d1}` }})
869
+ )
870
+ ${operatorMap[expr.type]}
871
+ CAST(
872
+ ${right} AS VECTOR(${{ literal: `${d2}` }})
873
+ )
874
+ `;
875
+ return expr.type === '$innerProduct' ? sql `-1 * (${_expr})` : _expr;
876
+ };
877
+ const matchType = (first, second) => {
878
+ const found = _.find(first, l => _.some(second, r => l.type === r.type));
879
+ return found ? [found, _.find(second, r => r.type === found.type)] : undefined;
880
+ };
881
+ const encodeBooleanExpression = (compiler, parent, expr) => {
882
+ if (expr instanceof validator.QueryCoditionalExpression) {
883
+ const queries = _.compact(_.map(expr.exprs, x => encodeBooleanExpression(compiler, parent, x)));
884
+ if (_.isEmpty(queries))
885
+ return;
886
+ switch (expr.type) {
887
+ case '$and': return sql `(${{ literal: _.map(queries, x => sql `(${x})`), separator: ' AND ' }})`;
888
+ case '$nor': return sql `(${{ literal: _.map(queries, x => sql `NOT (${x})`), separator: ' AND ' }})`;
889
+ case '$or': return sql `(${{ literal: _.map(queries, x => sql `(${x})`), separator: ' OR ' }})`;
890
+ }
891
+ }
892
+ if (expr instanceof validator.QueryComparisonExpression) {
893
+ const operatorMap = {
894
+ '$eq': nullSafeEqual(),
895
+ '$ne': nullSafeNotEqual(),
896
+ '$gt': sql `>`,
897
+ '$gte': sql `>=`,
898
+ '$lt': sql `<`,
899
+ '$lte': sql `<=`,
900
+ };
901
+ if (isArrayExpression(expr.left) &&
902
+ isArrayExpression(expr.right) &&
903
+ arrayLength(expr.left) === arrayLength(expr.right)) {
904
+ const _left = mapExpression(expr.left, x => encodeTypedQueryExpression(compiler, parent, x));
905
+ const _right = mapExpression(expr.right, x => encodeTypedQueryExpression(compiler, parent, x));
906
+ const mapped = _.compact(_.map(_.zip(_left, _right), ([l, r]) => matchType(l, r)));
907
+ if (mapped.length === _left.length) {
908
+ const [l, r] = _.unzip(mapped);
909
+ return sql `(${_.map(l, x => x.sql)}) ${operatorMap[expr.type]} (${_.map(r, x => x.sql)})`;
910
+ }
911
+ }
912
+ const _left = encodeTypedQueryExpression(compiler, parent, expr.left);
913
+ const _right = encodeTypedQueryExpression(compiler, parent, expr.right);
914
+ if (_left && _right) {
915
+ const matched = matchType(_left, _right);
916
+ if (matched)
917
+ return sql `${matched[0].sql} ${operatorMap[expr.type]} ${matched[1].sql}`;
918
+ }
919
+ const _left2 = encodeJsonQueryExpression(compiler, parent, expr.left);
920
+ const _right2 = encodeJsonQueryExpression(compiler, parent, expr.right);
921
+ return sql `${_left2} ${operatorMap[expr.type]} ${_right2}`;
922
+ }
923
+ if (expr instanceof validator.QueryNotExpression) {
924
+ const _expr = encodeBooleanExpression(compiler, parent, expr.expr);
925
+ return _expr ? sql `NOT (${_expr})` : undefined;
926
+ }
927
+ throw Error('Invalid expression');
928
+ };
929
+ const encodeQueryExpression = (compiler, parent, expr) => {
930
+ if (expr instanceof validator.QueryDistanceExpression) {
931
+ return encodeDistanceQueryExpression(compiler, parent, expr);
932
+ }
933
+ return encodeBooleanExpression(compiler, parent, expr);
934
+ };
935
+
543
936
  //
544
937
  // storage.ts
545
938
  //
@@ -705,9 +1098,13 @@ class SqlStorage {
705
1098
  const self = this;
706
1099
  const compiler = self._makeCompiler(false, query.extraFilter);
707
1100
  const _matchesType = self._matchesType(compiler, query);
708
- const _query = compiler._selectQuery({ ...query, sort: {} }, {
709
- sort: sql `ORDER BY ${self.dialect.random(opts ?? {})}`,
710
- });
1101
+ const _query = compiler._selectQuery({ ...query, sort: {} }, ({ fetchName }) => ({
1102
+ sort: sql `ORDER BY ${self.dialect.random(opts?.weight ? _.first(encodeTypedQueryExpression(compiler, {
1103
+ name: fetchName,
1104
+ className: query.className,
1105
+ groupMatches: query.groupMatches,
1106
+ }, opts.weight))?.sql : undefined)}`,
1107
+ }));
711
1108
  return (async function* () {
712
1109
  const objects = self.query(_query);
713
1110
  for await (const object of objects) {
@@ -951,8 +1348,8 @@ const encodeSortKey = (compiler, parent, key) => {
951
1348
  const { element } = fetchElement(compiler, parent, key);
952
1349
  return element;
953
1350
  };
954
- const random = (opts) => {
955
- return opts.weight ? sql `-ln(random()) / ${{ identifier: opts.weight }}` : sql `random()`;
1351
+ const random = (weight) => {
1352
+ return weight ? sql `-ln(random()) / ${weight}` : sql `random()`;
956
1353
  };
957
1354
 
958
1355
  //
@@ -1187,183 +1584,16 @@ class PostgresDriver extends PostgresClientDriver {
1187
1584
  if (!this.pubsub)
1188
1585
  return () => void 0;
1189
1586
  const release = this.pubsub.subscribe(({ channel: _channel, payload }) => {
1190
- if (_channel === channel)
1191
- callback(payload);
1192
- });
1193
- return () => {
1194
- release();
1195
- if (this.pubsub?.isEmpty())
1196
- this._release_pubsub();
1197
- };
1198
- }
1199
- }
1200
-
1201
- //
1202
- // encode.ts
1203
- //
1204
- // The MIT License
1205
- // Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.
1206
- //
1207
- // Permission is hereby granted, free of charge, to any person obtaining a copy
1208
- // of this software and associated documentation files (the "Software"), to deal
1209
- // in the Software without restriction, including without limitation the rights
1210
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1211
- // copies of the Software, and to permit persons to whom the Software is
1212
- // furnished to do so, subject to the following conditions:
1213
- //
1214
- // The above copyright notice and this permission notice shall be included in
1215
- // all copies or substantial portions of the Software.
1216
- //
1217
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1218
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1219
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1220
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1221
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1222
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1223
- // THE SOFTWARE.
1224
- //
1225
- const _encodeJsonValue = (value) => {
1226
- if (_.isArray(value))
1227
- return sql `jsonb_build_array(${_.map(value, x => _encodeJsonValue(x))})`;
1228
- if (_.isPlainObject(value))
1229
- return sql `jsonb_build_object(${_.map(value, (v, k) => sql `${{ value: k }}, ${_encodeJsonValue(v)}`)})`;
1230
- return sql `to_jsonb(${{ value }})`;
1231
- };
1232
- const _jsonPopulateInclude = (className, colname, dataType) => {
1233
- switch (index._typeof(dataType)) {
1234
- case 'decimal':
1235
- return sql `jsonb_build_object(
1236
- '$decimal', CAST(${{ identifier: className }}.${{ identifier: colname }} AS TEXT)
1237
- ) AS ${{ identifier: colname }}`;
1238
- case 'date':
1239
- return sql `jsonb_build_object(
1240
- '$date', to_char(${{ identifier: className }}.${{ identifier: colname }} AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"')
1241
- ) AS ${{ identifier: colname }}`;
1242
- default:
1243
- return sql `${{ identifier: className }}.${{ identifier: colname }}`;
1244
- }
1245
- };
1246
- const encodeType = (colname, dataType, value) => {
1247
- if (_.isNil(value))
1248
- return sql `NULL`;
1249
- switch (_.isString(dataType) ? dataType : dataType.type) {
1250
- case 'boolean':
1251
- if (_.isBoolean(value))
1252
- return sql `${{ value }}`;
1253
- break;
1254
- case 'number':
1255
- if (_.isNumber(value) && _.isFinite(value))
1256
- return sql `${{ value }}`;
1257
- if (value instanceof Decimal)
1258
- return sql `${{ value: value.toNumber() }}`;
1259
- break;
1260
- case 'decimal':
1261
- if (_.isNumber(value) && _.isFinite(value))
1262
- return sql `CAST(${{ quote: (new Decimal(value)).toString() }} AS DECIMAL)`;
1263
- if (value instanceof Decimal)
1264
- return sql `CAST(${{ quote: value.toString() }} AS DECIMAL)`;
1265
- break;
1266
- case 'string':
1267
- if (_.isString(value))
1268
- return sql `${{ value }}`;
1269
- break;
1270
- case 'string[]':
1271
- if (_.isArray(value) && _.every(value, x => _.isString(x)))
1272
- return sql `ARRAY[${_.map(value, x => sql `${{ value: x }}`)}]::TEXT[]`;
1273
- break;
1274
- case 'date':
1275
- if (_.isDate(value))
1276
- return sql `${{ value }}`;
1277
- break;
1278
- case 'object':
1279
- if (_.isPlainObject(value))
1280
- return sql `${{ value: index._encodeValue(value) }}`;
1281
- break;
1282
- case 'vector':
1283
- if (!_.isArray(value) || value.length !== index.dimensionOf(dataType))
1284
- break;
1285
- if (!_.every(value, x => _.isFinite(x)))
1286
- break;
1287
- return sql `${{ value }}::DOUBLE PRECISION[]`;
1288
- case 'array':
1289
- if (!_.isArray(value))
1290
- break;
1291
- return sql `ARRAY[${_.map(value, x => _encodeJsonValue(index._encodeValue(x)))}]::JSONB[]`;
1292
- case 'pointer':
1293
- if (value instanceof index.TObject && value.objectId)
1294
- return sql `${{ value: `${value.className}$${value.objectId}` }}`;
1295
- break;
1296
- case 'relation':
1297
- if (_.isArray(value) && _.every(value, x => x instanceof index.TObject && x.objectId)) {
1298
- return sql `${{ value: _.uniq(_.map(value, (x) => `${x.className}$${x.objectId}`)) }}`;
1299
- }
1300
- break;
1301
- }
1302
- throw Error('Invalid data type');
1303
- };
1304
- const decodeType = (type, value) => {
1305
- switch (type) {
1306
- case 'boolean':
1307
- if (_.isBoolean(value))
1308
- return value;
1309
- if (value === 'true')
1310
- return true;
1311
- if (value === 'false')
1312
- return false;
1313
- break;
1314
- case 'number':
1315
- if (_.isNumber(value))
1316
- return value;
1317
- if (_.isString(value)) {
1318
- const float = parseFloat(value);
1319
- return _.isNaN(float) ? null : float;
1320
- }
1321
- break;
1322
- case 'decimal':
1323
- if (_.isString(value) || _.isNumber(value))
1324
- return new Decimal(value);
1325
- if (value instanceof Decimal)
1326
- return value;
1327
- if (_.isPlainObject(value) && _.isString(value.$decimal))
1328
- return new Decimal(value.$decimal);
1329
- break;
1330
- case 'string':
1331
- if (_.isString(value))
1332
- return value;
1333
- break;
1334
- case 'string[]':
1335
- if (_.isArray(value) && _.every(value, x => _.isString(x)))
1336
- return value;
1337
- break;
1338
- case 'date':
1339
- if (_.isDate(value))
1340
- return value;
1341
- if (_.isString(value)) {
1342
- const date = new Date(value);
1343
- if (isFinite(date.valueOf()))
1344
- return date;
1345
- }
1346
- if (_.isPlainObject(value) && _.isString(value.$date))
1347
- return new Date(value.$date);
1348
- break;
1349
- case 'object':
1350
- if (_.isPlainObject(value))
1351
- return index._decodeValue(value);
1352
- break;
1353
- case 'array':
1354
- if (_.isArray(value))
1355
- return index._decodeValue(value);
1356
- break;
1357
- case 'vector':
1358
- if (!_.isArray(value))
1359
- break;
1360
- if (_.every(value, x => _.isNumber(x))) {
1361
- return value;
1362
- }
1363
- break;
1587
+ if (_channel === channel)
1588
+ callback(payload);
1589
+ });
1590
+ return () => {
1591
+ release();
1592
+ if (this.pubsub?.isEmpty())
1593
+ this._release_pubsub();
1594
+ };
1364
1595
  }
1365
- return null;
1366
- };
1596
+ }
1367
1597
 
1368
1598
  //
1369
1599
  // update.ts
@@ -1651,232 +1881,6 @@ const updateOperation = (paths, dataType, operation) => {
1651
1881
  throw Error('Invalid update operation');
1652
1882
  };
1653
1883
 
1654
- //
1655
- // expressions.ts
1656
- //
1657
- // The MIT License
1658
- // Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.
1659
- //
1660
- // Permission is hereby granted, free of charge, to any person obtaining a copy
1661
- // of this software and associated documentation files (the "Software"), to deal
1662
- // in the Software without restriction, including without limitation the rights
1663
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1664
- // copies of the Software, and to permit persons to whom the Software is
1665
- // furnished to do so, subject to the following conditions:
1666
- //
1667
- // The above copyright notice and this permission notice shall be included in
1668
- // all copies or substantial portions of the Software.
1669
- //
1670
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1671
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1672
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1673
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1674
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1675
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1676
- // THE SOFTWARE.
1677
- //
1678
- const isArrayExpression = (expr) => {
1679
- if (expr instanceof validator.QueryArrayExpression)
1680
- return true;
1681
- if (expr instanceof validator.QueryValueExpression)
1682
- return _.isArray(expr.value);
1683
- return false;
1684
- };
1685
- const arrayLength = (expr) => {
1686
- if (expr instanceof validator.QueryArrayExpression)
1687
- return expr.exprs.length;
1688
- if (expr instanceof validator.QueryValueExpression)
1689
- return _.isArray(expr.value) ? expr.value.length : 0;
1690
- return 0;
1691
- };
1692
- const mapExpression = (expr, callback) => {
1693
- if (expr instanceof validator.QueryArrayExpression)
1694
- return _.map(expr.exprs, x => callback(x));
1695
- if (expr instanceof validator.QueryValueExpression)
1696
- return _.isArray(expr.value) ? _.map(expr.value, x => callback(new validator.QueryValueExpression(x))) : [];
1697
- return [];
1698
- };
1699
- const _PrimitiveValue = ['boolean', 'number', 'decimal', 'string', 'date'];
1700
- const encodeTypedQueryExpression = (compiler, parent, expr) => {
1701
- if (expr instanceof validator.QueryKeyExpression) {
1702
- const { element, dataType } = fetchElement(compiler, parent, expr.key);
1703
- const _dataType = dataType ? index._typeof(dataType) : null;
1704
- if (_dataType === 'number') {
1705
- return [
1706
- { type: 'number', sql: element },
1707
- { type: 'decimal', sql: sql `CAST((${element}) AS DECIMAL)` },
1708
- ];
1709
- }
1710
- else if (_dataType === 'decimal') {
1711
- return [
1712
- { type: 'decimal', sql: element },
1713
- { type: 'number', sql: element },
1714
- ];
1715
- }
1716
- else if (_dataType && _PrimitiveValue.includes(_dataType)) {
1717
- return [{ type: _dataType, sql: element }];
1718
- }
1719
- }
1720
- if (expr instanceof validator.QueryValueExpression) {
1721
- if (_.isBoolean(expr.value))
1722
- return [{ type: 'boolean', sql: sql `${{ value: expr.value }}` }];
1723
- if (_.isNumber(expr.value))
1724
- return [
1725
- { type: 'number', sql: sql `${{ value: expr.value }}` },
1726
- { type: 'decimal', sql: sql `CAST(${{ quote: (new Decimal(expr.value)).toString() }} AS DECIMAL)` },
1727
- ];
1728
- if (expr.value instanceof Decimal)
1729
- return [
1730
- { type: 'decimal', sql: sql `CAST(${{ quote: expr.value.toString() }} AS DECIMAL)` },
1731
- { type: 'number', sql: sql `${{ value: expr.value.toNumber() }}` },
1732
- ];
1733
- if (_.isString(expr.value))
1734
- return [{ type: 'string', sql: sql `${{ value: expr.value }}` }];
1735
- if (_.isDate(expr.value))
1736
- return [{ type: 'date', sql: sql `${{ value: expr.value }}` }];
1737
- }
1738
- if (expr instanceof validator.QueryCoditionalExpression ||
1739
- expr instanceof validator.QueryComparisonExpression ||
1740
- expr instanceof validator.QueryNotExpression) {
1741
- const value = encodeBooleanExpression(compiler, parent, expr);
1742
- if (value)
1743
- return [{ type: 'boolean', sql: value }];
1744
- }
1745
- if (expr instanceof validator.QueryDistanceExpression) {
1746
- const value = encodeDistanceQueryExpression(compiler, parent, expr);
1747
- return [{ type: 'number', sql: value }];
1748
- }
1749
- };
1750
- const encodeJsonQueryExpression = (compiler, parent, expr) => {
1751
- if (expr instanceof validator.QueryKeyExpression) {
1752
- const { element, dataType } = fetchElement(compiler, parent, expr.key);
1753
- if (dataType && index.isPrimitive(dataType)) {
1754
- switch (index._typeof(dataType)) {
1755
- case 'boolean': return sql `to_jsonb(${element})`;
1756
- case 'number': return sql `to_jsonb(${element})`;
1757
- case 'decimal': return sql `jsonb_build_object('$decimal', CAST(${element} AS TEXT))`;
1758
- case 'string': return sql `to_jsonb(${element})`;
1759
- case 'string[]': return sql `to_jsonb(${element})`;
1760
- case 'date': return sql `jsonb_build_object(
1761
- '$date', to_char(${element} AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"')
1762
- )`;
1763
- }
1764
- }
1765
- return sql `${element}`;
1766
- }
1767
- if (expr instanceof validator.QueryValueExpression) {
1768
- return _encodeJsonValue(index._encodeValue(expr.value));
1769
- }
1770
- if (expr instanceof validator.QueryArrayExpression) {
1771
- return sql `jsonb_build_array(${_.map(expr.exprs, x => encodeJsonQueryExpression(compiler, parent, x))})`;
1772
- }
1773
- const value = encodeQueryExpression(compiler, parent, expr);
1774
- if (!value)
1775
- throw Error('Invalid expression');
1776
- return sql `to_jsonb(${value})`;
1777
- };
1778
- const encodeVectorExpression = (compiler, parent, exprs) => {
1779
- if (exprs.length === 1) {
1780
- const [expr] = exprs;
1781
- if (expr instanceof validator.QueryKeyExpression) {
1782
- const { element, dataType } = fetchElement(compiler, parent, expr.key);
1783
- if (!dataType || !index.isVector(dataType))
1784
- throw Error('Invalid expression');
1785
- return { sql: element, dimension: dataType.dimension };
1786
- }
1787
- if (expr instanceof validator.QueryValueExpression) {
1788
- if (!_.isArray(expr.value) || !_.every(expr.value, x => _.isFinite(x)))
1789
- throw Error('Invalid expression');
1790
- return { sql: sql `${{ value: expr.value }}::DOUBLE PRECISION[]`, dimension: expr.value.length };
1791
- }
1792
- }
1793
- const result = _.map(exprs, x => _.find(encodeTypedQueryExpression(compiler, parent, x), e => e.type === 'number')?.sql);
1794
- if (_.some(result, x => _.isNil(x)))
1795
- throw Error('Invalid expression');
1796
- return { sql: sql `ARRAY[${_.map(result, x => sql `COALESCE(${x}, 0)`)}]`, dimension: result.length };
1797
- };
1798
- const encodeDistanceQueryExpression = (compiler, parent, expr) => {
1799
- const { sql: left, dimension: d1 } = encodeVectorExpression(compiler, parent, expr.left);
1800
- const { sql: right, dimension: d2 } = encodeVectorExpression(compiler, parent, expr.right);
1801
- if (d1 !== d2)
1802
- throw Error('Invalid expression');
1803
- const operatorMap = {
1804
- '$distance': sql `<->`,
1805
- '$innerProduct': sql `<#>`,
1806
- '$negInnerProduct': sql `<#>`,
1807
- '$cosineDistance': sql `<=>`,
1808
- '$rectilinearDistance': sql `<+>`,
1809
- };
1810
- const _expr = sql `
1811
- CAST(
1812
- ${left} AS VECTOR(${{ literal: `${d1}` }})
1813
- )
1814
- ${operatorMap[expr.type]}
1815
- CAST(
1816
- ${right} AS VECTOR(${{ literal: `${d2}` }})
1817
- )
1818
- `;
1819
- return expr.type === '$innerProduct' ? sql `-1 * (${_expr})` : _expr;
1820
- };
1821
- const matchType = (first, second) => {
1822
- const found = _.find(first, l => _.some(second, r => l.type === r.type));
1823
- return found ? [found, _.find(second, r => r.type === found.type)] : undefined;
1824
- };
1825
- const encodeBooleanExpression = (compiler, parent, expr) => {
1826
- if (expr instanceof validator.QueryCoditionalExpression) {
1827
- const queries = _.compact(_.map(expr.exprs, x => encodeBooleanExpression(compiler, parent, x)));
1828
- if (_.isEmpty(queries))
1829
- return;
1830
- switch (expr.type) {
1831
- case '$and': return sql `(${{ literal: _.map(queries, x => sql `(${x})`), separator: ' AND ' }})`;
1832
- case '$nor': return sql `(${{ literal: _.map(queries, x => sql `NOT (${x})`), separator: ' AND ' }})`;
1833
- case '$or': return sql `(${{ literal: _.map(queries, x => sql `(${x})`), separator: ' OR ' }})`;
1834
- }
1835
- }
1836
- if (expr instanceof validator.QueryComparisonExpression) {
1837
- const operatorMap = {
1838
- '$eq': nullSafeEqual(),
1839
- '$ne': nullSafeNotEqual(),
1840
- '$gt': sql `>`,
1841
- '$gte': sql `>=`,
1842
- '$lt': sql `<`,
1843
- '$lte': sql `<=`,
1844
- };
1845
- if (isArrayExpression(expr.left) &&
1846
- isArrayExpression(expr.right) &&
1847
- arrayLength(expr.left) === arrayLength(expr.right)) {
1848
- const _left = mapExpression(expr.left, x => encodeTypedQueryExpression(compiler, parent, x));
1849
- const _right = mapExpression(expr.right, x => encodeTypedQueryExpression(compiler, parent, x));
1850
- const mapped = _.compact(_.map(_.zip(_left, _right), ([l, r]) => matchType(l, r)));
1851
- if (mapped.length === _left.length) {
1852
- const [l, r] = _.unzip(mapped);
1853
- return sql `(${_.map(l, x => x.sql)}) ${operatorMap[expr.type]} (${_.map(r, x => x.sql)})`;
1854
- }
1855
- }
1856
- const _left = encodeTypedQueryExpression(compiler, parent, expr.left);
1857
- const _right = encodeTypedQueryExpression(compiler, parent, expr.right);
1858
- if (_left && _right) {
1859
- const matched = matchType(_left, _right);
1860
- if (matched)
1861
- return sql `${matched[0].sql} ${operatorMap[expr.type]} ${matched[1].sql}`;
1862
- }
1863
- const _left2 = encodeJsonQueryExpression(compiler, parent, expr.left);
1864
- const _right2 = encodeJsonQueryExpression(compiler, parent, expr.right);
1865
- return sql `${_left2} ${operatorMap[expr.type]} ${_right2}`;
1866
- }
1867
- if (expr instanceof validator.QueryNotExpression) {
1868
- const _expr = encodeBooleanExpression(compiler, parent, expr.expr);
1869
- return _expr ? sql `NOT (${_expr})` : undefined;
1870
- }
1871
- throw Error('Invalid expression');
1872
- };
1873
- const encodeQueryExpression = (compiler, parent, expr) => {
1874
- if (expr instanceof validator.QueryDistanceExpression) {
1875
- return encodeDistanceQueryExpression(compiler, parent, expr);
1876
- }
1877
- return encodeBooleanExpression(compiler, parent, expr);
1878
- };
1879
-
1880
1884
  //
1881
1885
  // populate.ts
1882
1886
  //
@@ -1993,29 +1997,44 @@ const selectPopulate = (compiler, parent, populate, field) => {
1993
1997
  }
1994
1998
  }
1995
1999
  else if (expr instanceof validator.QueryExprAccumulator) {
1996
- const op = {
1997
- '$max': 'MAX',
1998
- '$min': 'MIN',
1999
- '$avg': 'AVG',
2000
- '$sum': 'SUM',
2001
- '$stdDevPop': 'STDDEV_POP',
2002
- '$stdDevSamp': 'STDDEV_SAMP',
2003
- '$varPop': 'VAR_POP',
2004
- '$varSamp': 'VAR_SAMP',
2005
- }[expr.type];
2006
2000
  if (!expr.expr)
2007
2001
  throw Error('Invalid expression');
2008
2002
  const exprs = encodeTypedQueryExpression(compiler, populate, expr.expr);
2009
2003
  const value = _.first(exprs)?.sql;
2010
2004
  if (!value)
2011
2005
  throw Error('Invalid expression');
2012
- columns.push(sql `
2013
- (
2014
- SELECT ${{ literal: op }}(${value}) FROM (
2015
- ${_selectRelationPopulate(compiler, parent, populate, field, false)}
2016
- ) ${{ identifier: populate.name }}
2017
- ) AS ${{ identifier: `${field}.${key}` }}
2018
- `);
2006
+ switch (expr.type) {
2007
+ case '$most':
2008
+ columns.push(sql `
2009
+ (
2010
+ SELECT MODE() WITHIN GROUP (ORDER BY (${value})) FROM (
2011
+ ${_selectRelationPopulate(compiler, parent, populate, field, false)}
2012
+ ) ${{ identifier: populate.name }}
2013
+ ) AS ${{ identifier: `${field}.${key}` }}
2014
+ `);
2015
+ break;
2016
+ default:
2017
+ {
2018
+ const op = {
2019
+ '$max': 'MAX',
2020
+ '$min': 'MIN',
2021
+ '$avg': 'AVG',
2022
+ '$sum': 'SUM',
2023
+ '$stdDevPop': 'STDDEV_POP',
2024
+ '$stdDevSamp': 'STDDEV_SAMP',
2025
+ '$varPop': 'VAR_POP',
2026
+ '$varSamp': 'VAR_SAMP',
2027
+ }[expr.type];
2028
+ columns.push(sql `
2029
+ (
2030
+ SELECT ${{ literal: op }}(${value}) FROM (
2031
+ ${_selectRelationPopulate(compiler, parent, populate, field, false)}
2032
+ ) ${{ identifier: populate.name }}
2033
+ ) AS ${{ identifier: `${field}.${key}` }}
2034
+ `);
2035
+ }
2036
+ break;
2037
+ }
2019
2038
  }
2020
2039
  else if (expr instanceof validator.QueryPercentileAccumulator) {
2021
2040
  const op = {