proto.io 0.0.213 → 0.0.215
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/file/aliyun-oss.d.ts +3 -3
- package/dist/adapters/file/database.d.ts +2 -2
- package/dist/adapters/file/database.js +2 -2
- package/dist/adapters/file/database.js.map +1 -1
- package/dist/adapters/file/database.mjs +1 -1
- package/dist/adapters/file/filesystem.d.ts +3 -3
- package/dist/adapters/file/google-cloud-storage.d.ts +3 -3
- package/dist/adapters/storage/progres.d.ts +1 -1
- package/dist/adapters/storage/progres.js +133 -82
- package/dist/adapters/storage/progres.js.map +1 -1
- package/dist/adapters/storage/progres.mjs +95 -44
- package/dist/adapters/storage/progres.mjs.map +1 -1
- package/dist/client.d.ts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +42 -42
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/internals/{base-CZGalGrd.d.ts → base-Cp5le5dC.d.ts} +2 -2
- package/dist/internals/base-Cp5le5dC.d.ts.map +1 -0
- package/dist/internals/{chunk-BsT9SYny.d.ts → chunk--Vo2-p-z.d.ts} +3 -3
- package/dist/internals/chunk--Vo2-p-z.d.ts.map +1 -0
- package/dist/internals/{index-NF-U_3zG.d.ts → index-CZUGnb-y.d.ts} +2 -2
- package/dist/internals/index-CZUGnb-y.d.ts.map +1 -0
- package/dist/internals/{index-Boxwkqe0.d.ts → index-YLrO0f2D.d.ts} +12 -8
- package/dist/internals/index-YLrO0f2D.d.ts.map +1 -0
- package/dist/internals/random-CYjWDvex.mjs +37 -0
- package/dist/internals/random-CYjWDvex.mjs.map +1 -0
- package/dist/internals/random-nkOQ9U6S.js +39 -0
- package/dist/internals/random-nkOQ9U6S.js.map +1 -0
- package/dist/internals/{index-DG9HHO_U.mjs → validator-ChrCrz_C.mjs} +618 -3
- package/dist/internals/validator-ChrCrz_C.mjs.map +1 -0
- package/dist/internals/{index-D8O7SinR.js → validator-m6wY35c6.js} +622 -2
- package/dist/internals/validator-m6wY35c6.js.map +1 -0
- package/package.json +1 -1
- package/dist/internals/base-CZGalGrd.d.ts.map +0 -1
- package/dist/internals/chunk-BsT9SYny.d.ts.map +0 -1
- package/dist/internals/index-Boxwkqe0.d.ts.map +0 -1
- package/dist/internals/index-D8O7SinR.js.map +0 -1
- package/dist/internals/index-DG9HHO_U.mjs.map +0 -1
- package/dist/internals/index-NF-U_3zG.d.ts.map +0 -1
- package/dist/internals/random-CufRbivU.mjs +0 -526
- package/dist/internals/random-CufRbivU.mjs.map +0 -1
- package/dist/internals/random-DzvxbWAc.js +0 -532
- 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,582 @@ class QueryExpressionSelector extends QuerySelector {
|
|
|
772
810
|
}
|
|
773
811
|
}
|
|
774
812
|
|
|
775
|
-
|
|
776
|
-
|
|
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 if (key === '$percentile') {
|
|
885
|
+
const { input, p, mode = 'discrete' } = expr ?? {};
|
|
886
|
+
if (!_.isFinite(p) || p < 0 || p > 1)
|
|
887
|
+
throw Error('Invalid expression');
|
|
888
|
+
if (!_.includes(['discrete', 'continuous'], mode))
|
|
889
|
+
throw Error('Invalid expression');
|
|
890
|
+
return new QueryPercentileAccumulator(QueryExpression.decode(input ?? [], false), p, mode);
|
|
891
|
+
}
|
|
892
|
+
else {
|
|
893
|
+
throw Error('Invalid expression');
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
throw Error('Invalid expression');
|
|
897
|
+
}
|
|
898
|
+
simplify() {
|
|
899
|
+
return this;
|
|
900
|
+
}
|
|
901
|
+
keyPaths() {
|
|
902
|
+
return [];
|
|
903
|
+
}
|
|
904
|
+
mapKey(callback) {
|
|
905
|
+
return this;
|
|
906
|
+
}
|
|
907
|
+
evalType(schema, className) {
|
|
908
|
+
return;
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
class QueryNoParamAccumulator extends QueryAccumulator {
|
|
912
|
+
type;
|
|
913
|
+
constructor(type) {
|
|
914
|
+
super();
|
|
915
|
+
this.type = type;
|
|
916
|
+
}
|
|
917
|
+
simplify() {
|
|
918
|
+
return this;
|
|
919
|
+
}
|
|
920
|
+
keyPaths() {
|
|
921
|
+
return [];
|
|
922
|
+
}
|
|
923
|
+
mapKey(callback) {
|
|
924
|
+
return this;
|
|
925
|
+
}
|
|
926
|
+
evalType(schema, className) {
|
|
927
|
+
switch (this.type) {
|
|
928
|
+
case '$count': return 'number';
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
class QueryExprAccumulator extends QueryAccumulator {
|
|
933
|
+
type;
|
|
934
|
+
expr;
|
|
935
|
+
constructor(type, expr) {
|
|
936
|
+
super();
|
|
937
|
+
this.type = type;
|
|
938
|
+
this.expr = expr;
|
|
939
|
+
}
|
|
940
|
+
simplify() {
|
|
941
|
+
return new QueryExprAccumulator(this.type, this.expr.simplify());
|
|
942
|
+
}
|
|
943
|
+
keyPaths() {
|
|
944
|
+
return this.expr.keyPaths();
|
|
945
|
+
}
|
|
946
|
+
mapKey(callback) {
|
|
947
|
+
return new QueryExprAccumulator(this.type, this.expr.mapKey(callback));
|
|
948
|
+
}
|
|
949
|
+
evalType(schema, className) {
|
|
950
|
+
const [dataType] = this.expr.evalType(schema, className);
|
|
951
|
+
if (_.isNil(dataType))
|
|
952
|
+
return;
|
|
953
|
+
switch (this.type) {
|
|
954
|
+
case '$max': return _isTypeof(dataType, ['number', 'decimal', 'string', 'date']) ? dataType : undefined;
|
|
955
|
+
case '$min': return _isTypeof(dataType, ['number', 'decimal', 'string', 'date']) ? dataType : undefined;
|
|
956
|
+
case '$avg': return _isTypeof(dataType, ['number', 'decimal']) ? dataType : undefined;
|
|
957
|
+
case '$sum': return _isTypeof(dataType, ['number', 'decimal']) ? dataType : undefined;
|
|
958
|
+
case '$stdDevPop': return _isTypeof(dataType, ['number', 'decimal']) ? dataType : undefined;
|
|
959
|
+
case '$stdDevSamp': return _isTypeof(dataType, ['number', 'decimal']) ? dataType : undefined;
|
|
960
|
+
case '$varPop': return _isTypeof(dataType, ['number', 'decimal']) ? dataType : undefined;
|
|
961
|
+
case '$varSamp': return _isTypeof(dataType, ['number', 'decimal']) ? dataType : undefined;
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
class QueryPercentileAccumulator extends QueryAccumulator {
|
|
966
|
+
input;
|
|
967
|
+
p;
|
|
968
|
+
mode;
|
|
969
|
+
constructor(input, p, mode) {
|
|
970
|
+
super();
|
|
971
|
+
this.input = input;
|
|
972
|
+
this.p = p;
|
|
973
|
+
this.mode = mode;
|
|
974
|
+
}
|
|
975
|
+
simplify() {
|
|
976
|
+
return new QueryPercentileAccumulator(this.input.simplify(), this.p, this.mode);
|
|
977
|
+
}
|
|
978
|
+
keyPaths() {
|
|
979
|
+
return this.input.keyPaths();
|
|
980
|
+
}
|
|
981
|
+
mapKey(callback) {
|
|
982
|
+
return new QueryPercentileAccumulator(this.input.mapKey(callback), this.p, this.mode);
|
|
983
|
+
}
|
|
984
|
+
evalType(schema, className) {
|
|
985
|
+
const [dataType] = this.input.evalType(schema, className);
|
|
986
|
+
if (this.mode === 'continuous') {
|
|
987
|
+
return _isTypeof(dataType, ['number', 'decimal']) ? dataType : undefined;
|
|
988
|
+
}
|
|
989
|
+
return dataType;
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
//
|
|
994
|
+
// validator.ts
|
|
995
|
+
//
|
|
996
|
+
// The MIT License
|
|
997
|
+
// Copyright (c) 2021 - 2025 O2ter Limited. All rights reserved.
|
|
998
|
+
//
|
|
999
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
1000
|
+
// of this software and associated documentation files (the "Software"), to deal
|
|
1001
|
+
// in the Software without restriction, including without limitation the rights
|
|
1002
|
+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
1003
|
+
// copies of the Software, and to permit persons to whom the Software is
|
|
1004
|
+
// furnished to do so, subject to the following conditions:
|
|
1005
|
+
//
|
|
1006
|
+
// The above copyright notice and this permission notice shall be included in
|
|
1007
|
+
// all copies or substantial portions of the Software.
|
|
1008
|
+
//
|
|
1009
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
1010
|
+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
1011
|
+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
1012
|
+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
1013
|
+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
1014
|
+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
1015
|
+
// THE SOFTWARE.
|
|
1016
|
+
//
|
|
1017
|
+
const recursiveCheck = (x, stack) => {
|
|
1018
|
+
if (_.indexOf(stack, x) !== -1)
|
|
1019
|
+
throw Error('Recursive data detected');
|
|
1020
|
+
if (_.isRegExp(x) || isPrimitiveValue(x) || x instanceof TObject)
|
|
1021
|
+
return;
|
|
1022
|
+
const children = _.isArray(x) ? x : _.values(x);
|
|
1023
|
+
children.forEach(v => recursiveCheck(v, [...stack, x]));
|
|
1024
|
+
};
|
|
1025
|
+
const resolveDataType = (schema, classname, path) => {
|
|
1026
|
+
let fields = schema[classname].fields;
|
|
1027
|
+
let last;
|
|
1028
|
+
for (const key of _.toPath(path)) {
|
|
1029
|
+
const dataType = fields[key];
|
|
1030
|
+
if (_.isNil(dataType))
|
|
1031
|
+
throw Error(`Invalid path: ${path}`);
|
|
1032
|
+
if (isPrimitive(dataType) || isVector(dataType))
|
|
1033
|
+
return dataType;
|
|
1034
|
+
if (isShape(dataType)) {
|
|
1035
|
+
fields = dataType.shape;
|
|
1036
|
+
continue;
|
|
1037
|
+
}
|
|
1038
|
+
if (_.isNil(schema[dataType.target]))
|
|
1039
|
+
throw Error(`Invalid path: ${path}`);
|
|
1040
|
+
fields = schema[dataType.target].fields;
|
|
1041
|
+
last = dataType;
|
|
1042
|
+
}
|
|
1043
|
+
return last;
|
|
1044
|
+
};
|
|
1045
|
+
const resolveColumn = (schema, className, path) => {
|
|
1046
|
+
const _schema = schema[className] ?? {};
|
|
1047
|
+
let [colname, ...subpath] = path.split('.');
|
|
1048
|
+
let dataType = _schema.fields[colname];
|
|
1049
|
+
while (dataType && !_.isEmpty(subpath) && isShape(dataType)) {
|
|
1050
|
+
const [key, ...remain] = subpath;
|
|
1051
|
+
if (!dataType.shape[key])
|
|
1052
|
+
break;
|
|
1053
|
+
dataType = dataType.shape[key];
|
|
1054
|
+
colname = `${colname}.${key}`;
|
|
1055
|
+
subpath = remain;
|
|
1056
|
+
}
|
|
1057
|
+
return {
|
|
1058
|
+
paths: [colname, ...subpath],
|
|
1059
|
+
dataType,
|
|
1060
|
+
};
|
|
1061
|
+
};
|
|
1062
|
+
class QueryValidator {
|
|
1063
|
+
proto;
|
|
1064
|
+
acls;
|
|
1065
|
+
options;
|
|
1066
|
+
static patterns = {
|
|
1067
|
+
path: /^[a-z_][\w-]*(\[\d+\]|\.\d*|\.[a-z_][\w-]*)*$/gi,
|
|
1068
|
+
className: /^[a-z_][\w]*$/gi,
|
|
1069
|
+
fieldName: /^[a-z_][\w-]*$/gi,
|
|
1070
|
+
digits: /^\d+$/g,
|
|
1071
|
+
};
|
|
1072
|
+
_rperm(className) {
|
|
1073
|
+
if (this.options.master)
|
|
1074
|
+
return [];
|
|
1075
|
+
const check = _.intersection(this.schema[className]?.additionalObjectPermissions?.read, this.acls);
|
|
1076
|
+
if (!_.isEmpty(check))
|
|
1077
|
+
return [];
|
|
1078
|
+
return [{ _rperm: { $intersect: this.acls } }];
|
|
1079
|
+
}
|
|
1080
|
+
_wperm(className) {
|
|
1081
|
+
if (this.options.master)
|
|
1082
|
+
return [];
|
|
1083
|
+
const check = _.intersection(this.schema[className]?.additionalObjectPermissions?.update, this.acls);
|
|
1084
|
+
if (!_.isEmpty(check))
|
|
1085
|
+
return [];
|
|
1086
|
+
return [{ _wperm: { $intersect: this.acls } }];
|
|
1087
|
+
}
|
|
1088
|
+
_expiredAt = { $or: [{ _expired_at: { $eq: null } }, { _expired_at: { $gt: new Date() } }] };
|
|
1089
|
+
constructor(proto, acls, options) {
|
|
1090
|
+
this.proto = proto;
|
|
1091
|
+
this.acls = _.uniq(['*', ...acls]);
|
|
1092
|
+
this.options = options;
|
|
1093
|
+
}
|
|
1094
|
+
get schema() {
|
|
1095
|
+
return this.proto.schema;
|
|
1096
|
+
}
|
|
1097
|
+
get objectIdSize() {
|
|
1098
|
+
return this.proto[PVK].options.objectIdSize;
|
|
1099
|
+
}
|
|
1100
|
+
static recursiveCheck(...x) {
|
|
1101
|
+
recursiveCheck(x, []);
|
|
1102
|
+
}
|
|
1103
|
+
validateKeyPerm(key, type, schema) {
|
|
1104
|
+
key = _.first(key?.split('.')) ?? key;
|
|
1105
|
+
if (_.isEmpty(key) || (!_.has(schema.fields, key) && !TObject.defaultKeys.includes(key)))
|
|
1106
|
+
throw Error(`Invalid key: ${key}`);
|
|
1107
|
+
if (type === 'read' && TObject.defaultKeys.includes(key))
|
|
1108
|
+
return true;
|
|
1109
|
+
if (type !== 'read' && TObject.defaultReadonlyKeys.includes(key))
|
|
1110
|
+
return false;
|
|
1111
|
+
if (!this.options.disableSecurity && _.includes(schema.secureFields, key))
|
|
1112
|
+
return false;
|
|
1113
|
+
return this.options.master || !_.every(schema.fieldLevelPermissions?.[key]?.[type] ?? ['*'], x => !_.includes(this.acls, x));
|
|
1114
|
+
}
|
|
1115
|
+
validateCLPs(className, ...keys) {
|
|
1116
|
+
if (!_.has(this.schema, className))
|
|
1117
|
+
throw Error('No permission');
|
|
1118
|
+
return this.options.master || this.proto[PVK].validateCLPs(className, this.acls, keys);
|
|
1119
|
+
}
|
|
1120
|
+
validateForeignField(dataType, type, errorMeg) {
|
|
1121
|
+
if (_.isNil(dataType.foreignField))
|
|
1122
|
+
return;
|
|
1123
|
+
const foreignField = resolveDataType(this.schema, dataType.target, dataType.foreignField);
|
|
1124
|
+
if (_.isNil(foreignField) || _.isString(foreignField))
|
|
1125
|
+
throw Error(errorMeg);
|
|
1126
|
+
if (isPrimitive(foreignField))
|
|
1127
|
+
throw Error(errorMeg);
|
|
1128
|
+
if (foreignField.type === 'relation' && !_.isNil(foreignField.foreignField))
|
|
1129
|
+
throw Error(errorMeg);
|
|
1130
|
+
if (!this.validateKeyPerm(dataType.foreignField, type, this.schema[dataType.target]))
|
|
1131
|
+
throw Error('No permission');
|
|
1132
|
+
}
|
|
1133
|
+
validateKey(className, key, type, validator) {
|
|
1134
|
+
const schema = this.schema[className] ?? {};
|
|
1135
|
+
const _key = _.isArray(key) ? key.join('.') : key;
|
|
1136
|
+
if (!_key.match(validator))
|
|
1137
|
+
throw Error(`Invalid key: ${_key}`);
|
|
1138
|
+
const [colname, ..._subpath] = _.toPath(_key);
|
|
1139
|
+
if (!this.validateKeyPerm(colname, type, schema))
|
|
1140
|
+
return false;
|
|
1141
|
+
if (_.isEmpty(_subpath) && TObject.defaultKeys.includes(colname))
|
|
1142
|
+
return true;
|
|
1143
|
+
if (_.isEmpty(_subpath))
|
|
1144
|
+
return true;
|
|
1145
|
+
const { paths: [_colname, ...subpath], dataType } = resolveColumn(this.schema, className, _key);
|
|
1146
|
+
const isElem = _.first(subpath)?.match(QueryValidator.patterns.digits);
|
|
1147
|
+
if (isElem) {
|
|
1148
|
+
if (dataType === 'array' || dataType === 'string[]')
|
|
1149
|
+
return true;
|
|
1150
|
+
if (!_.isString(dataType) && dataType.type !== 'relation')
|
|
1151
|
+
return false;
|
|
1152
|
+
}
|
|
1153
|
+
if (isPrimitive(dataType))
|
|
1154
|
+
return true;
|
|
1155
|
+
if (isVector(dataType))
|
|
1156
|
+
return true;
|
|
1157
|
+
const relations = [];
|
|
1158
|
+
if (isShape(dataType)) {
|
|
1159
|
+
for (const { type } of shapePaths(dataType)) {
|
|
1160
|
+
if (!isPrimitive(type) && !isVector(type))
|
|
1161
|
+
relations.push(type);
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
else {
|
|
1165
|
+
relations.push(dataType);
|
|
1166
|
+
}
|
|
1167
|
+
for (const relation of relations) {
|
|
1168
|
+
if (_.isNil(this.schema[relation.target]))
|
|
1169
|
+
return false;
|
|
1170
|
+
if (type === 'read' && !this.validateCLPs(relation.target, 'get'))
|
|
1171
|
+
return false;
|
|
1172
|
+
if (relation.type === 'relation')
|
|
1173
|
+
this.validateForeignField(relation, type, `Invalid key: ${_key}`);
|
|
1174
|
+
}
|
|
1175
|
+
if (isShape(dataType)) {
|
|
1176
|
+
if (!_.isEmpty(subpath))
|
|
1177
|
+
throw Error(`Invalid key: ${_key}`);
|
|
1178
|
+
return true;
|
|
1179
|
+
}
|
|
1180
|
+
const _sub = isElem ? subpath.slice(1) : subpath;
|
|
1181
|
+
return _.isEmpty(_sub) || this.validateKey(dataType.target, _sub, type, validator);
|
|
1182
|
+
}
|
|
1183
|
+
validateFields(className, values, type, validator) {
|
|
1184
|
+
const _values = { ...values };
|
|
1185
|
+
for (const key of _.keys(_values)) {
|
|
1186
|
+
if (!this.validateKey(className, key, type, validator))
|
|
1187
|
+
throw Error('No permission');
|
|
1188
|
+
}
|
|
1189
|
+
return _values;
|
|
1190
|
+
}
|
|
1191
|
+
decodeGroupMatches(className, groupMatches) {
|
|
1192
|
+
const result = _.mapValues(groupMatches, m => _.mapValues(m, x => QueryAccumulator.decode(x).simplify()));
|
|
1193
|
+
for (const [colname, group] of _.entries(result)) {
|
|
1194
|
+
const dataType = resolveDataType(this.schema, className, colname);
|
|
1195
|
+
if (!dataType || !isRelation(dataType))
|
|
1196
|
+
throw Error(`Invalid relation key: ${colname}`);
|
|
1197
|
+
for (const key of _.keys(group)) {
|
|
1198
|
+
if (!key.match(QueryValidator.patterns.fieldName))
|
|
1199
|
+
throw Error(`Invalid field name: ${key}`);
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
return result;
|
|
1203
|
+
}
|
|
1204
|
+
decodeIncludes(className, includes, groupMatches) {
|
|
1205
|
+
const schema = this.schema[className] ?? {};
|
|
1206
|
+
const _includes = [];
|
|
1207
|
+
const populates = {};
|
|
1208
|
+
for (const include of includes) {
|
|
1209
|
+
if (include === '*') {
|
|
1210
|
+
const primitive = _.pickBy(schema.fields, (v, k) => isPrimitive(v) && this.validateKeyPerm(k, 'read', schema));
|
|
1211
|
+
const shapedObject = _.pickBy(schema.fields, (v, k) => isShape(v) && this.validateKeyPerm(k, 'read', schema));
|
|
1212
|
+
_includes.push(..._.keys(primitive), ..._.flatMap(shapedObject, (v, k) => _.flatMap(shapePaths(v), x => isPrimitive(x.type) ? [`${k}.${x.path}`] : [])));
|
|
1213
|
+
}
|
|
1214
|
+
else {
|
|
1215
|
+
const { paths: [colname, ...subpath], dataType } = resolveColumn(this.schema, className, include);
|
|
1216
|
+
if (!this.validateKeyPerm(colname, 'read', schema))
|
|
1217
|
+
throw Error('No permission');
|
|
1218
|
+
if (isPointer(dataType) || isRelation(dataType)) {
|
|
1219
|
+
if (!this.validateCLPs(dataType.target, 'get'))
|
|
1220
|
+
throw Error('No permission');
|
|
1221
|
+
if (dataType.type === 'relation')
|
|
1222
|
+
this.validateForeignField(dataType, 'read', `Invalid include: ${include}`);
|
|
1223
|
+
const isDigit = _.first(subpath)?.match(QueryValidator.patterns.digits);
|
|
1224
|
+
const _subpath = isRelation(dataType) && isDigit ? _.slice(subpath, 1) : subpath;
|
|
1225
|
+
populates[colname] = populates[colname] ?? { className: dataType.target, subpaths: [], groupMatches: {} };
|
|
1226
|
+
const s = _.first(_subpath);
|
|
1227
|
+
if (!s || !groupMatches[colname]?.[s]) {
|
|
1228
|
+
populates[colname].subpaths.push(_.isEmpty(_subpath) ? '*' : _subpath.join('.'));
|
|
1229
|
+
populates[colname].groupMatches = _.mapKeys(_.pickBy(groupMatches, (x, k) => _.startsWith(k, `${colname}.`)), (x, k) => k.slice(colname.length + 1));
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
else if (_.isEmpty(subpath) && isShape(dataType)) {
|
|
1233
|
+
for (const { path, type } of shapePaths(dataType)) {
|
|
1234
|
+
if (isPrimitive(type) || isVector(type)) {
|
|
1235
|
+
_includes.push(`${colname}.${path}`);
|
|
1236
|
+
}
|
|
1237
|
+
else {
|
|
1238
|
+
if (!this.validateCLPs(type.target, 'get'))
|
|
1239
|
+
throw Error('No permission');
|
|
1240
|
+
if (type.type === 'relation')
|
|
1241
|
+
this.validateForeignField(type, 'read', `Invalid include: ${include}`);
|
|
1242
|
+
populates[`${colname}.${path}`] = populates[`${colname}.${path}`] ?? { className: type.target, subpaths: [], groupMatches: {} };
|
|
1243
|
+
populates[`${colname}.${path}`].subpaths.push('*');
|
|
1244
|
+
populates[`${colname}.${path}`].groupMatches = _.mapKeys(_.pickBy(groupMatches, (x, k) => _.startsWith(k, `${colname}.${path}.`)), (x, k) => k.slice(`${colname}.${path}`.length + 1));
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
else if (_.isEmpty(subpath) || _.includes(['object', 'array'], _typeof(dataType))) {
|
|
1249
|
+
_includes.push(colname);
|
|
1250
|
+
}
|
|
1251
|
+
else {
|
|
1252
|
+
throw Error(`Invalid include: ${include}`);
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
for (const [key, populate] of _.toPairs(populates)) {
|
|
1257
|
+
const subpaths = this.decodeIncludes(populate.className, populate.subpaths, populate.groupMatches);
|
|
1258
|
+
_includes.push(..._.map(subpaths, x => `${key}.${x}`));
|
|
1259
|
+
}
|
|
1260
|
+
_includes.push(...TObject.defaultKeys);
|
|
1261
|
+
return _.uniq(_includes);
|
|
1262
|
+
}
|
|
1263
|
+
decodeSort(sort) {
|
|
1264
|
+
if (_.isArray(sort)) {
|
|
1265
|
+
return _.map(sort, s => ({
|
|
1266
|
+
order: s.order,
|
|
1267
|
+
expr: QueryExpression.decode(s.expr, false).simplify(),
|
|
1268
|
+
}));
|
|
1269
|
+
}
|
|
1270
|
+
return sort;
|
|
1271
|
+
}
|
|
1272
|
+
decodeMatches(className, matches, includes) {
|
|
1273
|
+
const schema = this.schema[className] ?? {};
|
|
1274
|
+
const _matches = {};
|
|
1275
|
+
const _includes = _.groupBy(_.map(includes, x => resolveColumn(this.schema, className, x)), ({ paths: [colname] }) => colname);
|
|
1276
|
+
for (const [colname, [{ dataType }]] of _.entries(_includes)) {
|
|
1277
|
+
if (!this.validateKeyPerm(colname, 'read', schema))
|
|
1278
|
+
continue;
|
|
1279
|
+
if (isPrimitive(dataType) || isVector(dataType) || isShape(dataType))
|
|
1280
|
+
continue;
|
|
1281
|
+
_matches[colname] = {
|
|
1282
|
+
matches: this.decodeMatches(dataType.target, {}, includes.filter(x => x.startsWith(`${colname}.`)).map(x => x.slice(colname.length + 1))),
|
|
1283
|
+
};
|
|
1284
|
+
}
|
|
1285
|
+
for (const [colname, match] of _.toPairs(matches)) {
|
|
1286
|
+
if (!this.validateKeyPerm(colname, 'read', schema))
|
|
1287
|
+
throw Error('No permission');
|
|
1288
|
+
const { paths: [_colname, ...subpath], dataType } = resolveColumn(this.schema, className, colname);
|
|
1289
|
+
if (isPointer(dataType) && !_.isEmpty(subpath)) {
|
|
1290
|
+
_matches[_colname] = {
|
|
1291
|
+
matches: this.decodeMatches(dataType.target, { [subpath.join('.')]: match }, includes.filter(x => x.startsWith(`${_colname}.`)).map(x => x.slice(_colname.length + 1))),
|
|
1292
|
+
};
|
|
1293
|
+
}
|
|
1294
|
+
else if (isRelation(dataType)) {
|
|
1295
|
+
if (!this.validateCLPs(dataType.target, 'get'))
|
|
1296
|
+
throw Error('No permission');
|
|
1297
|
+
this.validateForeignField(dataType, 'read', `Invalid match: ${colname}`);
|
|
1298
|
+
const groupMatches = this.decodeGroupMatches(dataType.target, match.groupMatches ?? {});
|
|
1299
|
+
_matches[_colname] = {
|
|
1300
|
+
...match,
|
|
1301
|
+
groupMatches,
|
|
1302
|
+
filter: QuerySelector.decode(_.castArray(match.filter)).simplify(),
|
|
1303
|
+
matches: this.decodeMatches(dataType.target, match.matches ?? {}, includes.filter(x => x.startsWith(`${_colname}.`)).map(x => x.slice(_colname.length + 1))),
|
|
1304
|
+
sort: match.sort && this.decodeSort(match.sort),
|
|
1305
|
+
};
|
|
1306
|
+
}
|
|
1307
|
+
else {
|
|
1308
|
+
throw Error(`Invalid match: ${colname}`);
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
return _matches;
|
|
1312
|
+
}
|
|
1313
|
+
validateRelatedBy(className, relation) {
|
|
1314
|
+
if (!this.validateCLPs(relation.className, 'get'))
|
|
1315
|
+
throw Error('No permission');
|
|
1316
|
+
if (!this.validateKey(relation.className, relation.key, 'read', QueryValidator.patterns.path))
|
|
1317
|
+
throw Error('No permission');
|
|
1318
|
+
const { dataType } = resolveColumn(this.schema, relation.className, relation.key);
|
|
1319
|
+
if (!isPointer(dataType) && !isRelation(dataType))
|
|
1320
|
+
throw Error(`Invalid relation key: ${relation.key}`);
|
|
1321
|
+
if (className && dataType.target !== className)
|
|
1322
|
+
throw Error(`Invalid relation key: ${relation.key}`);
|
|
1323
|
+
if (isRelation(dataType) && dataType.foreignField) {
|
|
1324
|
+
this.validateForeignField(dataType, 'read', `Invalid relation key: ${relation.key}`);
|
|
1325
|
+
this.validateRelatedBy(null, { className: dataType.target, key: dataType.foreignField });
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
decodeQuery(query, action) {
|
|
1329
|
+
if ('relatedBy' in query && query.relatedBy)
|
|
1330
|
+
this.validateRelatedBy(query.className, query.relatedBy);
|
|
1331
|
+
const filter = QuerySelector.decode([
|
|
1332
|
+
...action === 'read' ? this._rperm(query.className) : this._wperm(query.className),
|
|
1333
|
+
..._.castArray(query.filter),
|
|
1334
|
+
this._expiredAt,
|
|
1335
|
+
]).simplify();
|
|
1336
|
+
const groupMatches = this.decodeGroupMatches(query.className, query.groupMatches ?? {});
|
|
1337
|
+
const matchKeyPaths = (matches) => _.flatMap(matches, (match, key) => [
|
|
1338
|
+
..._.keys(match.sort),
|
|
1339
|
+
...QuerySelector.decode(match.filter ?? []).keyPaths(),
|
|
1340
|
+
...matchKeyPaths(match.matches ?? {}),
|
|
1341
|
+
..._.keys(match.groupMatches),
|
|
1342
|
+
..._.flatMap(_.values(match.groupMatches), x => QueryAccumulator.decode(x).keyPaths()),
|
|
1343
|
+
].map(x => `${key}.${x}`));
|
|
1344
|
+
const sort = query.sort && this.decodeSort(query.sort);
|
|
1345
|
+
const keyPaths = _.uniq([
|
|
1346
|
+
...query.includes ?? ['*'],
|
|
1347
|
+
..._.isArray(sort) ? _.flatMap(sort, s => s.expr.keyPaths()) : _.keys(sort),
|
|
1348
|
+
...filter.keyPaths(),
|
|
1349
|
+
...matchKeyPaths(query.matches ?? {}),
|
|
1350
|
+
..._.keys(groupMatches),
|
|
1351
|
+
..._.flatMap(_.values(groupMatches), m => _.flatMap(_.values(m), x => x.keyPaths())),
|
|
1352
|
+
]);
|
|
1353
|
+
const includes = this.decodeIncludes(query.className, keyPaths, groupMatches);
|
|
1354
|
+
const matches = this.decodeMatches(query.className, query.matches ?? {}, includes);
|
|
1355
|
+
return {
|
|
1356
|
+
...query,
|
|
1357
|
+
groupMatches,
|
|
1358
|
+
filter,
|
|
1359
|
+
matches,
|
|
1360
|
+
includes,
|
|
1361
|
+
sort,
|
|
1362
|
+
objectIdSize: this.objectIdSize,
|
|
1363
|
+
extraFilter: (className) => QuerySelector.decode([...this._rperm(className), this._expiredAt]).simplify(),
|
|
1364
|
+
};
|
|
1365
|
+
}
|
|
1366
|
+
isGetMethod(query) {
|
|
1367
|
+
const objectIds = [];
|
|
1368
|
+
if (query instanceof QueryCoditionalSelector && query.type === '$and') {
|
|
1369
|
+
for (const expr of query.exprs) {
|
|
1370
|
+
if (expr instanceof QueryFieldSelector &&
|
|
1371
|
+
expr.field === '_id' &&
|
|
1372
|
+
expr.expr.type === '$eq') {
|
|
1373
|
+
if (!_.isString(expr.expr.value))
|
|
1374
|
+
return false;
|
|
1375
|
+
objectIds.push(expr.expr.value);
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
else if (query instanceof QueryFieldSelector &&
|
|
1380
|
+
query.field === '_id' &&
|
|
1381
|
+
query.expr.type === '$eq') {
|
|
1382
|
+
if (!_.isString(query.expr.value))
|
|
1383
|
+
return false;
|
|
1384
|
+
objectIds.push(query.expr.value);
|
|
1385
|
+
}
|
|
1386
|
+
return _.uniq(objectIds).length === 1;
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1390
|
+
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, QueryPercentileAccumulator as o, resolveColumn as r };
|
|
1391
|
+
//# sourceMappingURL=validator-ChrCrz_C.mjs.map
|