proto.io 0.0.212 → 0.0.214

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 (44) 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 +2 -2
  4. package/dist/adapters/file/database.js.map +1 -1
  5. package/dist/adapters/file/database.mjs +1 -1
  6. package/dist/adapters/file/filesystem.d.ts +3 -3
  7. package/dist/adapters/file/google-cloud-storage.d.ts +3 -3
  8. package/dist/adapters/storage/progres.d.ts +1 -1
  9. package/dist/adapters/storage/progres.js +117 -84
  10. package/dist/adapters/storage/progres.js.map +1 -1
  11. package/dist/adapters/storage/progres.mjs +79 -46
  12. package/dist/adapters/storage/progres.mjs.map +1 -1
  13. package/dist/client.d.ts +3 -3
  14. package/dist/index.d.ts +3 -3
  15. package/dist/index.js +42 -42
  16. package/dist/index.js.map +1 -1
  17. package/dist/index.mjs +2 -2
  18. package/dist/internals/{base-CZGalGrd.d.ts → base-E1b8J-Fs.d.ts} +2 -2
  19. package/dist/internals/base-E1b8J-Fs.d.ts.map +1 -0
  20. package/dist/internals/{chunk-BsT9SYny.d.ts → chunk-D1bD7otk.d.ts} +3 -3
  21. package/dist/internals/chunk-D1bD7otk.d.ts.map +1 -0
  22. package/dist/internals/{index-Boxwkqe0.d.ts → index-CbjY-gJ7.d.ts} +6 -8
  23. package/dist/internals/index-CbjY-gJ7.d.ts.map +1 -0
  24. package/dist/internals/{index-NF-U_3zG.d.ts → index-SSEdPyhp.d.ts} +2 -2
  25. package/dist/internals/index-SSEdPyhp.d.ts.map +1 -0
  26. package/dist/internals/random-CYjWDvex.mjs +37 -0
  27. package/dist/internals/random-CYjWDvex.mjs.map +1 -0
  28. package/dist/internals/random-nkOQ9U6S.js +39 -0
  29. package/dist/internals/random-nkOQ9U6S.js.map +1 -0
  30. package/dist/internals/{index-D8O7SinR.js → validator-DoRPoIs2.js} +586 -2
  31. package/dist/internals/validator-DoRPoIs2.js.map +1 -0
  32. package/dist/internals/{index-DG9HHO_U.mjs → validator-Dxmbwa3P.mjs} +583 -3
  33. package/dist/internals/validator-Dxmbwa3P.mjs.map +1 -0
  34. package/package.json +1 -1
  35. package/dist/internals/base-CZGalGrd.d.ts.map +0 -1
  36. package/dist/internals/chunk-BsT9SYny.d.ts.map +0 -1
  37. package/dist/internals/index-Boxwkqe0.d.ts.map +0 -1
  38. package/dist/internals/index-D8O7SinR.js.map +0 -1
  39. package/dist/internals/index-DG9HHO_U.mjs.map +0 -1
  40. package/dist/internals/index-NF-U_3zG.d.ts.map +0 -1
  41. package/dist/internals/random-CufRbivU.mjs +0 -526
  42. package/dist/internals/random-CufRbivU.mjs.map +0 -1
  43. package/dist/internals/random-DzvxbWAc.js +0 -532
  44. package/dist/internals/random-DzvxbWAc.js.map +0 -1
@@ -1,6 +1,7 @@
1
1
  import _ from 'lodash';
2
- import { T as TObject, l as isPrimitiveValue, m as isValue } from './index-al1N-qi7.mjs';
2
+ import { T as TObject, l as isPrimitiveValue, m as isValue, _ as _isTypeof, c as isPrimitive, f as isVector, b as isShape, s as shapePaths, a as isRelation, i as isPointer, k as _typeof } from './index-al1N-qi7.mjs';
3
3
  import Decimal from 'decimal.js';
4
+ import { P as PVK } from './private-CNw40LZ7.mjs';
4
5
 
5
6
  //
6
7
  // keys.ts
@@ -307,6 +308,9 @@ class QueryExpression {
307
308
  eval(value) {
308
309
  return true;
309
310
  }
311
+ evalType(schema, className) {
312
+ return [];
313
+ }
310
314
  }
311
315
  class QueryCoditionalExpression extends QueryExpression {
312
316
  type;
@@ -342,6 +346,9 @@ class QueryCoditionalExpression extends QueryExpression {
342
346
  case '$or': return _.some(this.exprs, expr => expr.eval(value));
343
347
  }
344
348
  }
349
+ evalType(schema, className) {
350
+ return ['boolean'];
351
+ }
345
352
  }
346
353
  class QueryComparisonExpression extends QueryExpression {
347
354
  type;
@@ -375,6 +382,9 @@ class QueryComparisonExpression extends QueryExpression {
375
382
  case '$ne': return !equal(this.left.eval(value), this.right.eval(value));
376
383
  }
377
384
  }
385
+ evalType(schema, className) {
386
+ return ['boolean'];
387
+ }
378
388
  }
379
389
  class QueryNotExpression extends QueryExpression {
380
390
  expr;
@@ -394,6 +404,9 @@ class QueryNotExpression extends QueryExpression {
394
404
  eval(value) {
395
405
  return !this.expr.eval(value);
396
406
  }
407
+ evalType(schema, className) {
408
+ return ['boolean'];
409
+ }
397
410
  }
398
411
  class QueryArrayExpression extends QueryExpression {
399
412
  exprs;
@@ -413,6 +426,9 @@ class QueryArrayExpression extends QueryExpression {
413
426
  eval(value) {
414
427
  return _.map(this.exprs, x => x.eval(value));
415
428
  }
429
+ evalType(schema, className) {
430
+ return ['array'];
431
+ }
416
432
  }
417
433
  class QueryDistanceExpression extends QueryExpression {
418
434
  type;
@@ -451,6 +467,9 @@ class QueryDistanceExpression extends QueryExpression {
451
467
  case '$rectilinearDistance': return rectilinearDistance(left, right);
452
468
  }
453
469
  }
470
+ evalType(schema, className) {
471
+ return ['number'];
472
+ }
454
473
  }
455
474
  class QueryKeyExpression extends QueryExpression {
456
475
  key;
@@ -467,6 +486,10 @@ class QueryKeyExpression extends QueryExpression {
467
486
  eval(value) {
468
487
  return getValue(value, this.key);
469
488
  }
489
+ evalType(schema, className) {
490
+ const { paths: [, ...subpath], dataType } = resolveColumn(schema, className, this.key);
491
+ return _.isEmpty(subpath) ? [dataType] : [];
492
+ }
470
493
  }
471
494
  class QueryValueExpression extends QueryExpression {
472
495
  value;
@@ -477,6 +500,21 @@ class QueryValueExpression extends QueryExpression {
477
500
  eval(value) {
478
501
  return value;
479
502
  }
503
+ evalType(schema, className) {
504
+ if (_.isDate(this.value))
505
+ return ['date'];
506
+ if (_.isBoolean(this.value))
507
+ return ['boolean'];
508
+ if (_.isArray(this.value))
509
+ return ['array'];
510
+ if (_.isString(this.value))
511
+ return ['string'];
512
+ if (_.isNumber(this.value))
513
+ return ['number', 'decimal'];
514
+ if (this.value instanceof Decimal)
515
+ return ['decimal', 'number'];
516
+ return [];
517
+ }
480
518
  }
481
519
 
482
520
  //
@@ -772,5 +810,547 @@ class QueryExpressionSelector extends QuerySelector {
772
810
  }
773
811
  }
774
812
 
775
- export { FieldSelectorExpression as F, QuerySelector as Q, QueryCoditionalSelector as a, QueryFieldSelector as b, QueryExpressionSelector as c, QueryDistanceExpression as d, QueryKeyExpression as e, QueryValueExpression as f, QueryCoditionalExpression as g, QueryComparisonExpression as h, QueryNotExpression as i, QueryArrayExpression as j, QueryExpression as k };
776
- //# sourceMappingURL=index-DG9HHO_U.mjs.map
813
+ //
814
+ // accumulators.ts
815
+ //
816
+ // The MIT License
817
+ // Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.
818
+ //
819
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
820
+ // of this software and associated documentation files (the "Software"), to deal
821
+ // in the Software without restriction, including without limitation the rights
822
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
823
+ // copies of the Software, and to permit persons to whom the Software is
824
+ // furnished to do so, subject to the following conditions:
825
+ //
826
+ // The above copyright notice and this permission notice shall be included in
827
+ // all copies or substantial portions of the Software.
828
+ //
829
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
830
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
831
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
832
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
833
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
834
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
835
+ // THE SOFTWARE.
836
+ //
837
+ const accumulatorExprKeys = [
838
+ '$max',
839
+ '$min',
840
+ '$sum',
841
+ '$avg',
842
+ '$stdDevPop',
843
+ '$stdDevSamp',
844
+ '$varPop',
845
+ '$varSamp'
846
+ ];
847
+ const accumulatorNoParamKeys = [
848
+ '$count'
849
+ ];
850
+
851
+ //
852
+ // accumulators.ts
853
+ //
854
+ // The MIT License
855
+ // Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.
856
+ //
857
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
858
+ // of this software and associated documentation files (the "Software"), to deal
859
+ // in the Software without restriction, including without limitation the rights
860
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
861
+ // copies of the Software, and to permit persons to whom the Software is
862
+ // furnished to do so, subject to the following conditions:
863
+ //
864
+ // The above copyright notice and this permission notice shall be included in
865
+ // all copies or substantial portions of the Software.
866
+ //
867
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
868
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
869
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
870
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
871
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
872
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
873
+ // THE SOFTWARE.
874
+ //
875
+ class QueryAccumulator {
876
+ static decode(query) {
877
+ for (const [key, expr] of _.toPairs(query)) {
878
+ if (_.includes(accumulatorExprKeys, key)) {
879
+ return new QueryExprAccumulator(key, QueryExpression.decode(expr ?? [], false));
880
+ }
881
+ else if (_.includes(accumulatorNoParamKeys, key)) {
882
+ return new QueryNoParamAccumulator(key);
883
+ }
884
+ else {
885
+ throw Error('Invalid expression');
886
+ }
887
+ }
888
+ throw Error('Invalid expression');
889
+ }
890
+ simplify() {
891
+ return this;
892
+ }
893
+ keyPaths() {
894
+ return [];
895
+ }
896
+ mapKey(callback) {
897
+ return this;
898
+ }
899
+ evalType(schema, className) {
900
+ return;
901
+ }
902
+ }
903
+ class QueryNoParamAccumulator extends QueryAccumulator {
904
+ type;
905
+ constructor(type) {
906
+ super();
907
+ this.type = type;
908
+ }
909
+ simplify() {
910
+ return this;
911
+ }
912
+ keyPaths() {
913
+ return [];
914
+ }
915
+ mapKey(callback) {
916
+ return this;
917
+ }
918
+ evalType(schema, className) {
919
+ switch (this.type) {
920
+ case '$count': return 'number';
921
+ }
922
+ }
923
+ }
924
+ class QueryExprAccumulator extends QueryAccumulator {
925
+ type;
926
+ expr;
927
+ constructor(type, expr) {
928
+ super();
929
+ this.type = type;
930
+ this.expr = expr;
931
+ }
932
+ simplify() {
933
+ return new QueryExprAccumulator(this.type, this.expr.simplify());
934
+ }
935
+ keyPaths() {
936
+ return this.expr?.keyPaths() ?? [];
937
+ }
938
+ mapKey(callback) {
939
+ return new QueryExprAccumulator(this.type, this.expr.mapKey(callback));
940
+ }
941
+ evalType(schema, className) {
942
+ const [dataType] = this.expr?.evalType(schema, className) ?? [];
943
+ if (_.isNil(dataType))
944
+ return;
945
+ switch (this.type) {
946
+ case '$max': return _isTypeof(dataType, ['number', 'decimal', 'string', 'date']) ? dataType : undefined;
947
+ case '$min': return _isTypeof(dataType, ['number', 'decimal', 'string', 'date']) ? dataType : undefined;
948
+ case '$avg': return _isTypeof(dataType, ['number', 'decimal']) ? dataType : undefined;
949
+ case '$sum': return _isTypeof(dataType, ['number', 'decimal']) ? dataType : undefined;
950
+ case '$stdDevPop': return _isTypeof(dataType, ['number', 'decimal']) ? dataType : undefined;
951
+ case '$stdDevSamp': return _isTypeof(dataType, ['number', 'decimal']) ? dataType : undefined;
952
+ case '$varPop': return _isTypeof(dataType, ['number', 'decimal']) ? dataType : undefined;
953
+ case '$varSamp': return _isTypeof(dataType, ['number', 'decimal']) ? dataType : undefined;
954
+ }
955
+ }
956
+ }
957
+
958
+ //
959
+ // validator.ts
960
+ //
961
+ // The MIT License
962
+ // Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.
963
+ //
964
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
965
+ // of this software and associated documentation files (the "Software"), to deal
966
+ // in the Software without restriction, including without limitation the rights
967
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
968
+ // copies of the Software, and to permit persons to whom the Software is
969
+ // furnished to do so, subject to the following conditions:
970
+ //
971
+ // The above copyright notice and this permission notice shall be included in
972
+ // all copies or substantial portions of the Software.
973
+ //
974
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
975
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
976
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
977
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
978
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
979
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
980
+ // THE SOFTWARE.
981
+ //
982
+ const recursiveCheck = (x, stack) => {
983
+ if (_.indexOf(stack, x) !== -1)
984
+ throw Error('Recursive data detected');
985
+ if (_.isRegExp(x) || isPrimitiveValue(x) || x instanceof TObject)
986
+ return;
987
+ const children = _.isArray(x) ? x : _.values(x);
988
+ children.forEach(v => recursiveCheck(v, [...stack, x]));
989
+ };
990
+ const resolveDataType = (schema, classname, path) => {
991
+ let fields = schema[classname].fields;
992
+ let last;
993
+ for (const key of _.toPath(path)) {
994
+ const dataType = fields[key];
995
+ if (_.isNil(dataType))
996
+ throw Error(`Invalid path: ${path}`);
997
+ if (isPrimitive(dataType) || isVector(dataType))
998
+ return dataType;
999
+ if (isShape(dataType)) {
1000
+ fields = dataType.shape;
1001
+ continue;
1002
+ }
1003
+ if (_.isNil(schema[dataType.target]))
1004
+ throw Error(`Invalid path: ${path}`);
1005
+ fields = schema[dataType.target].fields;
1006
+ last = dataType;
1007
+ }
1008
+ return last;
1009
+ };
1010
+ const resolveColumn = (schema, className, path) => {
1011
+ const _schema = schema[className] ?? {};
1012
+ let [colname, ...subpath] = path.split('.');
1013
+ let dataType = _schema.fields[colname];
1014
+ while (dataType && !_.isEmpty(subpath) && isShape(dataType)) {
1015
+ const [key, ...remain] = subpath;
1016
+ if (!dataType.shape[key])
1017
+ break;
1018
+ dataType = dataType.shape[key];
1019
+ colname = `${colname}.${key}`;
1020
+ subpath = remain;
1021
+ }
1022
+ return {
1023
+ paths: [colname, ...subpath],
1024
+ dataType,
1025
+ };
1026
+ };
1027
+ class QueryValidator {
1028
+ proto;
1029
+ acls;
1030
+ options;
1031
+ static patterns = {
1032
+ path: /^[a-z_][\w-]*(\[\d+\]|\.\d*|\.[a-z_][\w-]*)*$/gi,
1033
+ className: /^[a-z_][\w]*$/gi,
1034
+ fieldName: /^[a-z_][\w-]*$/gi,
1035
+ digits: /^\d+$/g,
1036
+ };
1037
+ _rperm(className) {
1038
+ if (this.options.master)
1039
+ return [];
1040
+ const check = _.intersection(this.schema[className]?.additionalObjectPermissions?.read, this.acls);
1041
+ if (!_.isEmpty(check))
1042
+ return [];
1043
+ return [{ _rperm: { $intersect: this.acls } }];
1044
+ }
1045
+ _wperm(className) {
1046
+ if (this.options.master)
1047
+ return [];
1048
+ const check = _.intersection(this.schema[className]?.additionalObjectPermissions?.update, this.acls);
1049
+ if (!_.isEmpty(check))
1050
+ return [];
1051
+ return [{ _wperm: { $intersect: this.acls } }];
1052
+ }
1053
+ _expiredAt = { $or: [{ _expired_at: { $eq: null } }, { _expired_at: { $gt: new Date() } }] };
1054
+ constructor(proto, acls, options) {
1055
+ this.proto = proto;
1056
+ this.acls = _.uniq(['*', ...acls]);
1057
+ this.options = options;
1058
+ }
1059
+ get schema() {
1060
+ return this.proto.schema;
1061
+ }
1062
+ get objectIdSize() {
1063
+ return this.proto[PVK].options.objectIdSize;
1064
+ }
1065
+ static recursiveCheck(...x) {
1066
+ recursiveCheck(x, []);
1067
+ }
1068
+ validateKeyPerm(key, type, schema) {
1069
+ key = _.first(key?.split('.')) ?? key;
1070
+ if (_.isEmpty(key) || (!_.has(schema.fields, key) && !TObject.defaultKeys.includes(key)))
1071
+ throw Error(`Invalid key: ${key}`);
1072
+ if (type === 'read' && TObject.defaultKeys.includes(key))
1073
+ return true;
1074
+ if (type !== 'read' && TObject.defaultReadonlyKeys.includes(key))
1075
+ return false;
1076
+ if (!this.options.disableSecurity && _.includes(schema.secureFields, key))
1077
+ return false;
1078
+ return this.options.master || !_.every(schema.fieldLevelPermissions?.[key]?.[type] ?? ['*'], x => !_.includes(this.acls, x));
1079
+ }
1080
+ validateCLPs(className, ...keys) {
1081
+ if (!_.has(this.schema, className))
1082
+ throw Error('No permission');
1083
+ return this.options.master || this.proto[PVK].validateCLPs(className, this.acls, keys);
1084
+ }
1085
+ validateForeignField(dataType, type, errorMeg) {
1086
+ if (_.isNil(dataType.foreignField))
1087
+ return;
1088
+ const foreignField = resolveDataType(this.schema, dataType.target, dataType.foreignField);
1089
+ if (_.isNil(foreignField) || _.isString(foreignField))
1090
+ throw Error(errorMeg);
1091
+ if (isPrimitive(foreignField))
1092
+ throw Error(errorMeg);
1093
+ if (foreignField.type === 'relation' && !_.isNil(foreignField.foreignField))
1094
+ throw Error(errorMeg);
1095
+ if (!this.validateKeyPerm(dataType.foreignField, type, this.schema[dataType.target]))
1096
+ throw Error('No permission');
1097
+ }
1098
+ validateKey(className, key, type, validator) {
1099
+ const schema = this.schema[className] ?? {};
1100
+ const _key = _.isArray(key) ? key.join('.') : key;
1101
+ if (!_key.match(validator))
1102
+ throw Error(`Invalid key: ${_key}`);
1103
+ const [colname, ..._subpath] = _.toPath(_key);
1104
+ if (!this.validateKeyPerm(colname, type, schema))
1105
+ return false;
1106
+ if (_.isEmpty(_subpath) && TObject.defaultKeys.includes(colname))
1107
+ return true;
1108
+ if (_.isEmpty(_subpath))
1109
+ return true;
1110
+ const { paths: [_colname, ...subpath], dataType } = resolveColumn(this.schema, className, _key);
1111
+ const isElem = _.first(subpath)?.match(QueryValidator.patterns.digits);
1112
+ if (isElem) {
1113
+ if (dataType === 'array' || dataType === 'string[]')
1114
+ return true;
1115
+ if (!_.isString(dataType) && dataType.type !== 'relation')
1116
+ return false;
1117
+ }
1118
+ if (isPrimitive(dataType))
1119
+ return true;
1120
+ if (isVector(dataType))
1121
+ return true;
1122
+ const relations = [];
1123
+ if (isShape(dataType)) {
1124
+ for (const { type } of shapePaths(dataType)) {
1125
+ if (!isPrimitive(type) && !isVector(type))
1126
+ relations.push(type);
1127
+ }
1128
+ }
1129
+ else {
1130
+ relations.push(dataType);
1131
+ }
1132
+ for (const relation of relations) {
1133
+ if (_.isNil(this.schema[relation.target]))
1134
+ return false;
1135
+ if (type === 'read' && !this.validateCLPs(relation.target, 'get'))
1136
+ return false;
1137
+ if (relation.type === 'relation')
1138
+ this.validateForeignField(relation, type, `Invalid key: ${_key}`);
1139
+ }
1140
+ if (isShape(dataType)) {
1141
+ if (!_.isEmpty(subpath))
1142
+ throw Error(`Invalid key: ${_key}`);
1143
+ return true;
1144
+ }
1145
+ const _sub = isElem ? subpath.slice(1) : subpath;
1146
+ return _.isEmpty(_sub) || this.validateKey(dataType.target, _sub, type, validator);
1147
+ }
1148
+ validateFields(className, values, type, validator) {
1149
+ const _values = { ...values };
1150
+ for (const key of _.keys(_values)) {
1151
+ if (!this.validateKey(className, key, type, validator))
1152
+ throw Error('No permission');
1153
+ }
1154
+ return _values;
1155
+ }
1156
+ decodeGroupMatches(className, groupMatches) {
1157
+ const result = _.mapValues(groupMatches, m => _.mapValues(m, x => QueryAccumulator.decode(x).simplify()));
1158
+ for (const [colname, group] of _.entries(result)) {
1159
+ const dataType = resolveDataType(this.schema, className, colname);
1160
+ if (!dataType || !isRelation(dataType))
1161
+ throw Error(`Invalid relation key: ${colname}`);
1162
+ for (const key of _.keys(group)) {
1163
+ if (!key.match(QueryValidator.patterns.fieldName))
1164
+ throw Error(`Invalid field name: ${key}`);
1165
+ }
1166
+ }
1167
+ return result;
1168
+ }
1169
+ decodeIncludes(className, includes, groupMatches) {
1170
+ const schema = this.schema[className] ?? {};
1171
+ const _includes = [];
1172
+ const populates = {};
1173
+ for (const include of includes) {
1174
+ if (include === '*') {
1175
+ const primitive = _.pickBy(schema.fields, (v, k) => isPrimitive(v) && this.validateKeyPerm(k, 'read', schema));
1176
+ const shapedObject = _.pickBy(schema.fields, (v, k) => isShape(v) && this.validateKeyPerm(k, 'read', schema));
1177
+ _includes.push(..._.keys(primitive), ..._.flatMap(shapedObject, (v, k) => _.flatMap(shapePaths(v), x => isPrimitive(x.type) ? [`${k}.${x.path}`] : [])));
1178
+ }
1179
+ else {
1180
+ const { paths: [colname, ...subpath], dataType } = resolveColumn(this.schema, className, include);
1181
+ if (!this.validateKeyPerm(colname, 'read', schema))
1182
+ throw Error('No permission');
1183
+ if (isPointer(dataType) || isRelation(dataType)) {
1184
+ if (!this.validateCLPs(dataType.target, 'get'))
1185
+ throw Error('No permission');
1186
+ if (dataType.type === 'relation')
1187
+ this.validateForeignField(dataType, 'read', `Invalid include: ${include}`);
1188
+ const isDigit = _.first(subpath)?.match(QueryValidator.patterns.digits);
1189
+ const _subpath = isRelation(dataType) && isDigit ? _.slice(subpath, 1) : subpath;
1190
+ populates[colname] = populates[colname] ?? { className: dataType.target, subpaths: [], groupMatches: {} };
1191
+ const s = _.first(_subpath);
1192
+ if (!s || !groupMatches[colname]?.[s]) {
1193
+ populates[colname].subpaths.push(_.isEmpty(_subpath) ? '*' : _subpath.join('.'));
1194
+ populates[colname].groupMatches = _.mapKeys(_.pickBy(groupMatches, (x, k) => _.startsWith(k, `${colname}.`)), (x, k) => k.slice(colname.length + 1));
1195
+ }
1196
+ }
1197
+ else if (_.isEmpty(subpath) && isShape(dataType)) {
1198
+ for (const { path, type } of shapePaths(dataType)) {
1199
+ if (isPrimitive(type) || isVector(type)) {
1200
+ _includes.push(`${colname}.${path}`);
1201
+ }
1202
+ else {
1203
+ if (!this.validateCLPs(type.target, 'get'))
1204
+ throw Error('No permission');
1205
+ if (type.type === 'relation')
1206
+ this.validateForeignField(type, 'read', `Invalid include: ${include}`);
1207
+ populates[`${colname}.${path}`] = populates[`${colname}.${path}`] ?? { className: type.target, subpaths: [], groupMatches: {} };
1208
+ populates[`${colname}.${path}`].subpaths.push('*');
1209
+ populates[`${colname}.${path}`].groupMatches = _.mapKeys(_.pickBy(groupMatches, (x, k) => _.startsWith(k, `${colname}.${path}.`)), (x, k) => k.slice(`${colname}.${path}`.length + 1));
1210
+ }
1211
+ }
1212
+ }
1213
+ else if (_.isEmpty(subpath) || _.includes(['object', 'array'], _typeof(dataType))) {
1214
+ _includes.push(colname);
1215
+ }
1216
+ else {
1217
+ throw Error(`Invalid include: ${include}`);
1218
+ }
1219
+ }
1220
+ }
1221
+ for (const [key, populate] of _.toPairs(populates)) {
1222
+ const subpaths = this.decodeIncludes(populate.className, populate.subpaths, populate.groupMatches);
1223
+ _includes.push(..._.map(subpaths, x => `${key}.${x}`));
1224
+ }
1225
+ _includes.push(...TObject.defaultKeys);
1226
+ return _.uniq(_includes);
1227
+ }
1228
+ decodeSort(sort) {
1229
+ if (_.isArray(sort)) {
1230
+ return _.map(sort, s => ({
1231
+ order: s.order,
1232
+ expr: QueryExpression.decode(s.expr, false).simplify(),
1233
+ }));
1234
+ }
1235
+ return sort;
1236
+ }
1237
+ decodeMatches(className, matches, includes) {
1238
+ const schema = this.schema[className] ?? {};
1239
+ const _matches = {};
1240
+ const _includes = _.groupBy(_.map(includes, x => resolveColumn(this.schema, className, x)), ({ paths: [colname] }) => colname);
1241
+ for (const [colname, [{ dataType }]] of _.entries(_includes)) {
1242
+ if (!this.validateKeyPerm(colname, 'read', schema))
1243
+ continue;
1244
+ if (isPrimitive(dataType) || isVector(dataType) || isShape(dataType))
1245
+ continue;
1246
+ _matches[colname] = {
1247
+ matches: this.decodeMatches(dataType.target, {}, includes.filter(x => x.startsWith(`${colname}.`)).map(x => x.slice(colname.length + 1))),
1248
+ };
1249
+ }
1250
+ for (const [colname, match] of _.toPairs(matches)) {
1251
+ if (!this.validateKeyPerm(colname, 'read', schema))
1252
+ throw Error('No permission');
1253
+ const { paths: [_colname, ...subpath], dataType } = resolveColumn(this.schema, className, colname);
1254
+ if (isPointer(dataType) && !_.isEmpty(subpath)) {
1255
+ _matches[_colname] = {
1256
+ matches: this.decodeMatches(dataType.target, { [subpath.join('.')]: match }, includes.filter(x => x.startsWith(`${_colname}.`)).map(x => x.slice(_colname.length + 1))),
1257
+ };
1258
+ }
1259
+ else if (isRelation(dataType)) {
1260
+ if (!this.validateCLPs(dataType.target, 'get'))
1261
+ throw Error('No permission');
1262
+ this.validateForeignField(dataType, 'read', `Invalid match: ${colname}`);
1263
+ const groupMatches = this.decodeGroupMatches(dataType.target, match.groupMatches ?? {});
1264
+ _matches[_colname] = {
1265
+ ...match,
1266
+ groupMatches,
1267
+ filter: QuerySelector.decode(_.castArray(match.filter)).simplify(),
1268
+ matches: this.decodeMatches(dataType.target, match.matches ?? {}, includes.filter(x => x.startsWith(`${_colname}.`)).map(x => x.slice(_colname.length + 1))),
1269
+ sort: match.sort && this.decodeSort(match.sort),
1270
+ };
1271
+ }
1272
+ else {
1273
+ throw Error(`Invalid match: ${colname}`);
1274
+ }
1275
+ }
1276
+ return _matches;
1277
+ }
1278
+ validateRelatedBy(className, relation) {
1279
+ if (!this.validateCLPs(relation.className, 'get'))
1280
+ throw Error('No permission');
1281
+ if (!this.validateKey(relation.className, relation.key, 'read', QueryValidator.patterns.path))
1282
+ throw Error('No permission');
1283
+ const { dataType } = resolveColumn(this.schema, relation.className, relation.key);
1284
+ if (!isPointer(dataType) && !isRelation(dataType))
1285
+ throw Error(`Invalid relation key: ${relation.key}`);
1286
+ if (className && dataType.target !== className)
1287
+ throw Error(`Invalid relation key: ${relation.key}`);
1288
+ if (isRelation(dataType) && dataType.foreignField) {
1289
+ this.validateForeignField(dataType, 'read', `Invalid relation key: ${relation.key}`);
1290
+ this.validateRelatedBy(null, { className: dataType.target, key: dataType.foreignField });
1291
+ }
1292
+ }
1293
+ decodeQuery(query, action) {
1294
+ if ('relatedBy' in query && query.relatedBy)
1295
+ this.validateRelatedBy(query.className, query.relatedBy);
1296
+ const filter = QuerySelector.decode([
1297
+ ...action === 'read' ? this._rperm(query.className) : this._wperm(query.className),
1298
+ ..._.castArray(query.filter),
1299
+ this._expiredAt,
1300
+ ]).simplify();
1301
+ const groupMatches = this.decodeGroupMatches(query.className, query.groupMatches ?? {});
1302
+ const matchKeyPaths = (matches) => _.flatMap(matches, (match, key) => [
1303
+ ..._.keys(match.sort),
1304
+ ...QuerySelector.decode(match.filter ?? []).keyPaths(),
1305
+ ...matchKeyPaths(match.matches ?? {}),
1306
+ ..._.keys(match.groupMatches),
1307
+ ..._.flatMap(_.values(match.groupMatches), x => QueryAccumulator.decode(x).keyPaths()),
1308
+ ].map(x => `${key}.${x}`));
1309
+ const sort = query.sort && this.decodeSort(query.sort);
1310
+ const keyPaths = _.uniq([
1311
+ ...query.includes ?? ['*'],
1312
+ ..._.isArray(sort) ? _.flatMap(sort, s => s.expr.keyPaths()) : _.keys(sort),
1313
+ ...filter.keyPaths(),
1314
+ ...matchKeyPaths(query.matches ?? {}),
1315
+ ..._.keys(groupMatches),
1316
+ ..._.flatMap(_.values(groupMatches), m => _.flatMap(_.values(m), x => x.keyPaths())),
1317
+ ]);
1318
+ const includes = this.decodeIncludes(query.className, keyPaths, groupMatches);
1319
+ const matches = this.decodeMatches(query.className, query.matches ?? {}, includes);
1320
+ return {
1321
+ ...query,
1322
+ groupMatches,
1323
+ filter,
1324
+ matches,
1325
+ includes,
1326
+ sort,
1327
+ objectIdSize: this.objectIdSize,
1328
+ extraFilter: (className) => QuerySelector.decode([...this._rperm(className), this._expiredAt]).simplify(),
1329
+ };
1330
+ }
1331
+ isGetMethod(query) {
1332
+ const objectIds = [];
1333
+ if (query instanceof QueryCoditionalSelector && query.type === '$and') {
1334
+ for (const expr of query.exprs) {
1335
+ if (expr instanceof QueryFieldSelector &&
1336
+ expr.field === '_id' &&
1337
+ expr.expr.type === '$eq') {
1338
+ if (!_.isString(expr.expr.value))
1339
+ return false;
1340
+ objectIds.push(expr.expr.value);
1341
+ }
1342
+ }
1343
+ }
1344
+ else if (query instanceof QueryFieldSelector &&
1345
+ query.field === '_id' &&
1346
+ query.expr.type === '$eq') {
1347
+ if (!_.isString(query.expr.value))
1348
+ return false;
1349
+ objectIds.push(query.expr.value);
1350
+ }
1351
+ return _.uniq(objectIds).length === 1;
1352
+ }
1353
+ }
1354
+
1355
+ export { FieldSelectorExpression as F, QueryValidator as Q, resolveDataType as a, QuerySelector as b, QueryCoditionalSelector as c, QueryFieldSelector as d, QueryExpressionSelector as e, QueryDistanceExpression as f, QueryKeyExpression as g, QueryValueExpression as h, QueryCoditionalExpression as i, QueryComparisonExpression as j, QueryNotExpression as k, QueryArrayExpression as l, QueryNoParamAccumulator as m, QueryExprAccumulator as n, resolveColumn as r };
1356
+ //# sourceMappingURL=validator-Dxmbwa3P.mjs.map