@nocobase/database 0.7.0-alpha.6 → 0.7.0-alpha.60
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/lib/collection-importer.js +101 -67
- package/lib/collection.js +339 -210
- package/lib/database.d.ts +4 -1
- package/lib/database.js +489 -275
- package/lib/fields/array-field.js +45 -25
- package/lib/fields/belongs-to-field.js +101 -54
- package/lib/fields/belongs-to-many-field.js +98 -53
- package/lib/fields/boolean-field.js +24 -9
- package/lib/fields/context-field.js +77 -42
- package/lib/fields/date-field.js +24 -9
- package/lib/fields/field.js +114 -75
- package/lib/fields/has-inverse-field.js +4 -2
- package/lib/fields/has-many-field.js +105 -56
- package/lib/fields/has-one-field.js +105 -54
- package/lib/fields/index.d.ts +3 -1
- package/lib/fields/index.js +277 -32
- package/lib/fields/json-field.js +36 -16
- package/lib/fields/number-field.js +53 -26
- package/lib/fields/password-field.js +118 -73
- package/lib/fields/radio-field.js +75 -47
- package/lib/fields/relation-field.js +41 -28
- package/lib/fields/sort-field.js +165 -89
- package/lib/fields/string-field.js +24 -9
- package/lib/fields/text-field.js +24 -9
- package/lib/fields/time-field.js +24 -9
- package/lib/fields/uid-field.js +57 -28
- package/lib/fields/uuid-field.d.ts +9 -0
- package/lib/fields/uuid-field.js +39 -0
- package/lib/fields/virtual-field.js +24 -9
- package/lib/filter-parser.js +288 -179
- package/lib/index.js +210 -29
- package/lib/magic-attribute-model.js +123 -71
- package/lib/mock-database.js +68 -34
- package/lib/model-hook.js +101 -60
- package/lib/model.js +116 -81
- package/lib/operators/array.js +136 -96
- package/lib/operators/association.js +30 -14
- package/lib/operators/boolean.d.ts +13 -0
- package/lib/operators/boolean.js +35 -0
- package/lib/operators/date.js +78 -34
- package/lib/operators/empty.js +113 -75
- package/lib/operators/index.js +15 -3
- package/lib/operators/ne.js +27 -12
- package/{esm/operators/ne.d.ts → lib/operators/notIn.d.ts} +2 -2
- package/lib/operators/notIn.js +29 -0
- package/lib/operators/string.js +56 -35
- package/lib/operators/utils.js +18 -10
- package/lib/options-parser.js +323 -215
- package/lib/playground.js +66 -53
- package/lib/relation-repository/belongs-to-many-repository.js +281 -198
- package/lib/relation-repository/belongs-to-repository.js +10 -6
- package/lib/relation-repository/hasmany-repository.js +168 -121
- package/lib/relation-repository/hasone-repository.js +10 -6
- package/lib/relation-repository/multiple-relation-repository.d.ts +3 -3
- package/lib/relation-repository/multiple-relation-repository.js +263 -148
- package/lib/relation-repository/relation-repository.d.ts +1 -1
- package/lib/relation-repository/relation-repository.js +155 -95
- package/lib/relation-repository/single-relation-repository.d.ts +6 -6
- package/lib/relation-repository/single-relation-repository.js +138 -99
- package/lib/relation-repository/types.js +4 -2
- package/lib/repository.d.ts +4 -7
- package/lib/repository.js +465 -291
- package/lib/transaction-decorator.js +80 -67
- package/lib/update-associations.d.ts +1 -2
- package/lib/update-associations.js +525 -321
- package/lib/update-guard.js +160 -117
- package/package.json +3 -8
- package/src/__tests__/fields/uuid-field.test.ts +30 -0
- package/src/__tests__/operator/notIn.test.ts +33 -0
- package/src/__tests__/option-parser.test.ts +20 -0
- package/src/database.ts +51 -4
- package/src/fields/context-field.ts +1 -1
- package/src/fields/index.ts +3 -0
- package/src/fields/uuid-field.ts +21 -0
- package/src/mock-database.ts +1 -1
- package/src/model-hook.ts +1 -1
- package/src/operators/boolean.ts +18 -0
- package/src/operators/index.ts +2 -0
- package/src/operators/notIn.ts +12 -0
- package/src/options-parser.ts +1 -1
- package/src/relation-repository/multiple-relation-repository.ts +8 -6
- package/src/relation-repository/relation-repository.ts +11 -6
- package/src/relation-repository/single-relation-repository.ts +6 -6
- package/src/repository.ts +4 -6
- package/src/update-associations.ts +1 -2
- package/esm/collection-importer.d.ts +0 -7
- package/esm/collection-importer.js +0 -49
- package/esm/collection-importer.js.map +0 -1
- package/esm/collection.d.ts +0 -73
- package/esm/collection.js +0 -224
- package/esm/collection.js.map +0 -1
- package/esm/database.d.ts +0 -101
- package/esm/database.js +0 -275
- package/esm/database.js.map +0 -1
- package/esm/fields/array-field.d.ts +0 -11
- package/esm/fields/array-field.js +0 -26
- package/esm/fields/array-field.js.map +0 -1
- package/esm/fields/belongs-to-field.d.ts +0 -12
- package/esm/fields/belongs-to-field.js +0 -57
- package/esm/fields/belongs-to-field.js.map +0 -1
- package/esm/fields/belongs-to-many-field.d.ts +0 -11
- package/esm/fields/belongs-to-many-field.js +0 -55
- package/esm/fields/belongs-to-many-field.js.map +0 -1
- package/esm/fields/boolean-field.d.ts +0 -8
- package/esm/fields/boolean-field.js +0 -8
- package/esm/fields/boolean-field.js.map +0 -1
- package/esm/fields/context-field.d.ts +0 -13
- package/esm/fields/context-field.js +0 -43
- package/esm/fields/context-field.js.map +0 -1
- package/esm/fields/date-field.d.ts +0 -8
- package/esm/fields/date-field.js +0 -8
- package/esm/fields/date-field.js.map +0 -1
- package/esm/fields/field.d.ts +0 -37
- package/esm/fields/field.js +0 -74
- package/esm/fields/field.js.map +0 -1
- package/esm/fields/has-inverse-field.d.ts +0 -4
- package/esm/fields/has-inverse-field.js +0 -2
- package/esm/fields/has-inverse-field.js.map +0 -1
- package/esm/fields/has-many-field.d.ts +0 -64
- package/esm/fields/has-many-field.js +0 -58
- package/esm/fields/has-many-field.js.map +0 -1
- package/esm/fields/has-one-field.d.ts +0 -64
- package/esm/fields/has-one-field.js +0 -57
- package/esm/fields/has-one-field.js.map +0 -1
- package/esm/fields/index.d.ts +0 -40
- package/esm/fields/index.js +0 -21
- package/esm/fields/index.js.map +0 -1
- package/esm/fields/json-field.d.ts +0 -14
- package/esm/fields/json-field.js +0 -17
- package/esm/fields/json-field.js.map +0 -1
- package/esm/fields/number-field.d.ts +0 -32
- package/esm/fields/number-field.js +0 -28
- package/esm/fields/number-field.js.map +0 -1
- package/esm/fields/password-field.d.ts +0 -21
- package/esm/fields/password-field.js +0 -71
- package/esm/fields/password-field.js.map +0 -1
- package/esm/fields/radio-field.d.ts +0 -14
- package/esm/fields/radio-field.js +0 -49
- package/esm/fields/radio-field.js.map +0 -1
- package/esm/fields/relation-field.d.ts +0 -20
- package/esm/fields/relation-field.js +0 -27
- package/esm/fields/relation-field.js.map +0 -1
- package/esm/fields/sort-field.d.ts +0 -16
- package/esm/fields/sort-field.js +0 -90
- package/esm/fields/sort-field.js.map +0 -1
- package/esm/fields/string-field.d.ts +0 -8
- package/esm/fields/string-field.js +0 -8
- package/esm/fields/string-field.js.map +0 -1
- package/esm/fields/text-field.d.ts +0 -8
- package/esm/fields/text-field.js +0 -8
- package/esm/fields/text-field.js.map +0 -1
- package/esm/fields/time-field.d.ts +0 -8
- package/esm/fields/time-field.js +0 -8
- package/esm/fields/time-field.js.map +0 -1
- package/esm/fields/uid-field.d.ts +0 -10
- package/esm/fields/uid-field.js +0 -27
- package/esm/fields/uid-field.js.map +0 -1
- package/esm/fields/virtual-field.d.ts +0 -8
- package/esm/fields/virtual-field.js +0 -8
- package/esm/fields/virtual-field.js.map +0 -1
- package/esm/filter-parser.d.ts +0 -27
- package/esm/filter-parser.js +0 -185
- package/esm/filter-parser.js.map +0 -1
- package/esm/index.d.ts +0 -15
- package/esm/index.js +0 -16
- package/esm/index.js.map +0 -1
- package/esm/magic-attribute-model.d.ts +0 -7
- package/esm/magic-attribute-model.js +0 -70
- package/esm/magic-attribute-model.js.map +0 -1
- package/esm/mock-database.d.ts +0 -22
- package/esm/mock-database.js +0 -34
- package/esm/mock-database.js.map +0 -1
- package/esm/model-hook.d.ts +0 -12
- package/esm/model-hook.js +0 -61
- package/esm/model-hook.js.map +0 -1
- package/esm/model.d.ts +0 -15
- package/esm/model.js +0 -80
- package/esm/model.js.map +0 -1
- package/esm/operators/array.d.ts +0 -26
- package/esm/operators/array.js +0 -105
- package/esm/operators/array.js.map +0 -1
- package/esm/operators/association.d.ts +0 -10
- package/esm/operators/association.js +0 -14
- package/esm/operators/association.js.map +0 -1
- package/esm/operators/date.d.ts +0 -34
- package/esm/operators/date.js +0 -35
- package/esm/operators/date.js.map +0 -1
- package/esm/operators/empty.d.ts +0 -28
- package/esm/operators/empty.js +0 -58
- package/esm/operators/empty.js.map +0 -1
- package/esm/operators/index.d.ts +0 -2
- package/esm/operators/index.js +0 -2
- package/esm/operators/index.js.map +0 -1
- package/esm/operators/ne.js +0 -12
- package/esm/operators/ne.js.map +0 -1
- package/esm/operators/string.d.ts +0 -21
- package/esm/operators/string.js +0 -35
- package/esm/operators/string.js.map +0 -1
- package/esm/operators/utils.d.ts +0 -4
- package/esm/operators/utils.js +0 -11
- package/esm/operators/utils.js.map +0 -1
- package/esm/options-parser.d.ts +0 -31
- package/esm/options-parser.js +0 -225
- package/esm/options-parser.js.map +0 -1
- package/esm/playground.d.ts +0 -1
- package/esm/playground.js +0 -53
- package/esm/playground.js.map +0 -1
- package/esm/relation-repository/belongs-to-many-repository.d.ts +0 -36
- package/esm/relation-repository/belongs-to-many-repository.js +0 -199
- package/esm/relation-repository/belongs-to-many-repository.js.map +0 -1
- package/esm/relation-repository/belongs-to-repository.d.ts +0 -17
- package/esm/relation-repository/belongs-to-repository.js +0 -4
- package/esm/relation-repository/belongs-to-repository.js.map +0 -1
- package/esm/relation-repository/hasmany-repository.d.ts +0 -23
- package/esm/relation-repository/hasmany-repository.js +0 -125
- package/esm/relation-repository/hasmany-repository.js.map +0 -1
- package/esm/relation-repository/hasone-repository.d.ts +0 -17
- package/esm/relation-repository/hasone-repository.js +0 -4
- package/esm/relation-repository/hasone-repository.js.map +0 -1
- package/esm/relation-repository/multiple-relation-repository.d.ts +0 -23
- package/esm/relation-repository/multiple-relation-repository.js +0 -149
- package/esm/relation-repository/multiple-relation-repository.js.map +0 -1
- package/esm/relation-repository/relation-repository.d.ts +0 -32
- package/esm/relation-repository/relation-repository.js +0 -93
- package/esm/relation-repository/relation-repository.js.map +0 -1
- package/esm/relation-repository/single-relation-repository.d.ts +0 -23
- package/esm/relation-repository/single-relation-repository.js +0 -96
- package/esm/relation-repository/single-relation-repository.js.map +0 -1
- package/esm/relation-repository/types.d.ts +0 -7
- package/esm/relation-repository/types.js +0 -2
- package/esm/relation-repository/types.js.map +0 -1
- package/esm/repository.d.ts +0 -165
- package/esm/repository.js +0 -276
- package/esm/repository.js.map +0 -1
- package/esm/transaction-decorator.d.ts +0 -1
- package/esm/transaction-decorator.js +0 -63
- package/esm/transaction-decorator.js.map +0 -1
- package/esm/update-associations.d.ts +0 -60
- package/esm/update-associations.js +0 -362
- package/esm/update-associations.js.map +0 -1
- package/esm/update-guard.d.ts +0 -26
- package/esm/update-guard.js +0 -122
- package/esm/update-guard.js.map +0 -1
- package/lib/collection-importer.js.map +0 -1
- package/lib/collection.js.map +0 -1
- package/lib/database.js.map +0 -1
- package/lib/fields/array-field.js.map +0 -1
- package/lib/fields/belongs-to-field.js.map +0 -1
- package/lib/fields/belongs-to-many-field.js.map +0 -1
- package/lib/fields/boolean-field.js.map +0 -1
- package/lib/fields/context-field.js.map +0 -1
- package/lib/fields/date-field.js.map +0 -1
- package/lib/fields/field.js.map +0 -1
- package/lib/fields/has-inverse-field.js.map +0 -1
- package/lib/fields/has-many-field.js.map +0 -1
- package/lib/fields/has-one-field.js.map +0 -1
- package/lib/fields/index.js.map +0 -1
- package/lib/fields/json-field.js.map +0 -1
- package/lib/fields/number-field.js.map +0 -1
- package/lib/fields/password-field.js.map +0 -1
- package/lib/fields/radio-field.js.map +0 -1
- package/lib/fields/relation-field.js.map +0 -1
- package/lib/fields/sort-field.js.map +0 -1
- package/lib/fields/string-field.js.map +0 -1
- package/lib/fields/text-field.js.map +0 -1
- package/lib/fields/time-field.js.map +0 -1
- package/lib/fields/uid-field.js.map +0 -1
- package/lib/fields/virtual-field.js.map +0 -1
- package/lib/filter-parser.js.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/magic-attribute-model.js.map +0 -1
- package/lib/mock-database.js.map +0 -1
- package/lib/model-hook.js.map +0 -1
- package/lib/model.js.map +0 -1
- package/lib/operators/array.js.map +0 -1
- package/lib/operators/association.js.map +0 -1
- package/lib/operators/date.js.map +0 -1
- package/lib/operators/empty.js.map +0 -1
- package/lib/operators/index.js.map +0 -1
- package/lib/operators/ne.js.map +0 -1
- package/lib/operators/string.js.map +0 -1
- package/lib/operators/utils.js.map +0 -1
- package/lib/options-parser.js.map +0 -1
- package/lib/playground.js.map +0 -1
- package/lib/relation-repository/belongs-to-many-repository.js.map +0 -1
- package/lib/relation-repository/belongs-to-repository.js.map +0 -1
- package/lib/relation-repository/hasmany-repository.js.map +0 -1
- package/lib/relation-repository/hasone-repository.js.map +0 -1
- package/lib/relation-repository/multiple-relation-repository.js.map +0 -1
- package/lib/relation-repository/relation-repository.js.map +0 -1
- package/lib/relation-repository/single-relation-repository.js.map +0 -1
- package/lib/relation-repository/types.js.map +0 -1
- package/lib/repository.js.map +0 -1
- package/lib/transaction-decorator.js.map +0 -1
- package/lib/update-associations.js.map +0 -1
- package/lib/update-guard.js.map +0 -1
- package/tsconfig.build.json +0 -9
- package/tsconfig.json +0 -5
package/lib/update-guard.js
CHANGED
|
@@ -1,129 +1,172 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
6
|
exports.UpdateGuard = void 0;
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
|
|
8
|
+
function _lodash() {
|
|
9
|
+
const data = _interopRequireDefault(require("lodash"));
|
|
10
|
+
|
|
11
|
+
_lodash = function _lodash() {
|
|
12
|
+
return data;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
return data;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
var _model = require("./model");
|
|
19
|
+
|
|
20
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
21
|
+
|
|
9
22
|
class UpdateGuard {
|
|
10
|
-
|
|
11
|
-
|
|
23
|
+
constructor() {
|
|
24
|
+
this.model = void 0;
|
|
25
|
+
this.action = void 0;
|
|
26
|
+
this.associationKeysToBeUpdate = void 0;
|
|
27
|
+
this.blackList = void 0;
|
|
28
|
+
this.whiteList = void 0;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
setAction(action) {
|
|
32
|
+
this.action = action;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
setModel(model) {
|
|
36
|
+
this.model = model;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
setAssociationKeysToBeUpdate(associationKeysToBeUpdate) {
|
|
40
|
+
if (this.action == 'create') {
|
|
41
|
+
this.associationKeysToBeUpdate = Object.keys(this.model.associations);
|
|
42
|
+
} else {
|
|
43
|
+
this.associationKeysToBeUpdate = associationKeysToBeUpdate;
|
|
12
44
|
}
|
|
13
|
-
|
|
14
|
-
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
setWhiteList(whiteList) {
|
|
48
|
+
this.whiteList = whiteList;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
setBlackList(blackList) {
|
|
52
|
+
this.blackList = blackList;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Sanitize values by whitelist blacklist
|
|
56
|
+
* @param values
|
|
57
|
+
*/
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
sanitize(values) {
|
|
61
|
+
values = _lodash().default.clone(values);
|
|
62
|
+
|
|
63
|
+
if (!this.model) {
|
|
64
|
+
throw new Error('please set model first');
|
|
15
65
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
66
|
+
|
|
67
|
+
const associations = this.model.associations;
|
|
68
|
+
|
|
69
|
+
const associationsValues = _lodash().default.pick(values, Object.keys(associations)); // build params of association update guard
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
const listOfAssociation = (list, association) => {
|
|
73
|
+
if (list) {
|
|
74
|
+
list = list.filter(whiteListKey => whiteListKey.startsWith(`${association}.`)).map(whiteListKey => whiteListKey.replace(`${association}.`, ''));
|
|
75
|
+
|
|
76
|
+
if (list.length == 0) {
|
|
77
|
+
return undefined;
|
|
19
78
|
}
|
|
20
|
-
|
|
21
|
-
|
|
79
|
+
|
|
80
|
+
return list;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return undefined;
|
|
84
|
+
}; // sanitize association values
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
Object.keys(associationsValues).forEach(association => {
|
|
88
|
+
let associationValues = associationsValues[association];
|
|
89
|
+
|
|
90
|
+
const filterAssociationToBeUpdate = value => {
|
|
91
|
+
const associationKeysToBeUpdate = this.associationKeysToBeUpdate || [];
|
|
92
|
+
|
|
93
|
+
if (associationKeysToBeUpdate.includes(association)) {
|
|
94
|
+
return value;
|
|
22
95
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Sanitize values by whitelist blacklist
|
|
32
|
-
* @param values
|
|
33
|
-
*/
|
|
34
|
-
sanitize(values) {
|
|
35
|
-
values = lodash_1.default.clone(values);
|
|
36
|
-
if (!this.model) {
|
|
37
|
-
throw new Error('please set model first');
|
|
96
|
+
|
|
97
|
+
const associationObj = associations[association];
|
|
98
|
+
const associationKeyName = associationObj.associationType == 'BelongsTo' || associationObj.associationType == 'HasOne' ? associationObj.targetKey : associationObj.target.primaryKeyAttribute;
|
|
99
|
+
|
|
100
|
+
if (value[associationKeyName]) {
|
|
101
|
+
return _lodash().default.pick(value, [associationKeyName, ...Object.keys(associationObj.target.associations)]);
|
|
38
102
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return undefined;
|
|
49
|
-
}
|
|
50
|
-
return list;
|
|
51
|
-
}
|
|
52
|
-
return undefined;
|
|
53
|
-
};
|
|
54
|
-
// sanitize association values
|
|
55
|
-
Object.keys(associationsValues).forEach((association) => {
|
|
56
|
-
let associationValues = associationsValues[association];
|
|
57
|
-
const filterAssociationToBeUpdate = (value) => {
|
|
58
|
-
const associationKeysToBeUpdate = this.associationKeysToBeUpdate || [];
|
|
59
|
-
if (associationKeysToBeUpdate.includes(association)) {
|
|
60
|
-
return value;
|
|
61
|
-
}
|
|
62
|
-
const associationObj = associations[association];
|
|
63
|
-
const associationKeyName = associationObj.associationType == 'BelongsTo' || associationObj.associationType == 'HasOne'
|
|
64
|
-
? associationObj.targetKey
|
|
65
|
-
: associationObj.target.primaryKeyAttribute;
|
|
66
|
-
if (value[associationKeyName]) {
|
|
67
|
-
return lodash_1.default.pick(value, [associationKeyName, ...Object.keys(associationObj.target.associations)]);
|
|
68
|
-
}
|
|
69
|
-
return value;
|
|
70
|
-
};
|
|
71
|
-
const sanitizeValue = (value) => {
|
|
72
|
-
const associationUpdateGuard = new UpdateGuard();
|
|
73
|
-
associationUpdateGuard.setModel(associations[association].target);
|
|
74
|
-
['whiteList', 'blackList', 'associationKeysToBeUpdate'].forEach((optionKey) => {
|
|
75
|
-
associationUpdateGuard[`set${lodash_1.default.upperFirst(optionKey)}`](listOfAssociation(this[optionKey], association));
|
|
76
|
-
});
|
|
77
|
-
return associationUpdateGuard.sanitize(filterAssociationToBeUpdate(value));
|
|
78
|
-
};
|
|
79
|
-
if (Array.isArray(associationValues)) {
|
|
80
|
-
associationValues = associationValues.map((value) => {
|
|
81
|
-
if (typeof value == 'string' || typeof value == 'number') {
|
|
82
|
-
return value;
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
return sanitizeValue(value);
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
else if (typeof associationValues === 'object' && associationValues !== null) {
|
|
90
|
-
associationValues = sanitizeValue(associationValues);
|
|
91
|
-
}
|
|
92
|
-
// set association values to sanitized value
|
|
93
|
-
values[association] = associationValues;
|
|
103
|
+
|
|
104
|
+
return value;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const sanitizeValue = value => {
|
|
108
|
+
const associationUpdateGuard = new UpdateGuard();
|
|
109
|
+
associationUpdateGuard.setModel(associations[association].target);
|
|
110
|
+
['whiteList', 'blackList', 'associationKeysToBeUpdate'].forEach(optionKey => {
|
|
111
|
+
associationUpdateGuard[`set${_lodash().default.upperFirst(optionKey)}`](listOfAssociation(this[optionKey], association));
|
|
94
112
|
});
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
return result;
|
|
113
|
+
return associationUpdateGuard.sanitize(filterAssociationToBeUpdate(value));
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
if (Array.isArray(associationValues)) {
|
|
117
|
+
associationValues = associationValues.map(value => {
|
|
118
|
+
if (typeof value == 'string' || typeof value == 'number') {
|
|
119
|
+
return value;
|
|
120
|
+
} else {
|
|
121
|
+
return sanitizeValue(value);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
} else if (typeof associationValues === 'object' && associationValues !== null) {
|
|
125
|
+
associationValues = sanitizeValue(associationValues);
|
|
126
|
+
} // set association values to sanitized value
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
values[association] = associationValues;
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
if (values instanceof _model.Model) {
|
|
133
|
+
return values;
|
|
117
134
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
135
|
+
|
|
136
|
+
let valuesKeys = Object.keys(values || {}); // handle whitelist
|
|
137
|
+
|
|
138
|
+
if (this.whiteList) {
|
|
139
|
+
valuesKeys = valuesKeys.filter(valueKey => {
|
|
140
|
+
return this.whiteList.findIndex(whiteKey => {
|
|
141
|
+
const keyPaths = whiteKey.split('.');
|
|
142
|
+
return keyPaths[0] === valueKey;
|
|
143
|
+
}) !== -1;
|
|
144
|
+
});
|
|
145
|
+
} // handle blacklist
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
if (this.blackList) {
|
|
149
|
+
valuesKeys = valuesKeys.filter(valueKey => !this.blackList.includes(valueKey));
|
|
126
150
|
}
|
|
151
|
+
|
|
152
|
+
const result = valuesKeys.reduce((obj, key) => {
|
|
153
|
+
_lodash().default.set(obj, key, values[key]);
|
|
154
|
+
|
|
155
|
+
return obj;
|
|
156
|
+
}, {});
|
|
157
|
+
return result;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
static fromOptions(model, options) {
|
|
161
|
+
const guard = new UpdateGuard();
|
|
162
|
+
guard.setModel(model);
|
|
163
|
+
guard.setWhiteList(options.whitelist);
|
|
164
|
+
guard.setBlackList(options.blacklist);
|
|
165
|
+
guard.setAction(_lodash().default.get(options, 'action', 'update'));
|
|
166
|
+
guard.setAssociationKeysToBeUpdate(options.updateAssociationValues);
|
|
167
|
+
return guard;
|
|
168
|
+
}
|
|
169
|
+
|
|
127
170
|
}
|
|
128
|
-
|
|
129
|
-
|
|
171
|
+
|
|
172
|
+
exports.UpdateGuard = UpdateGuard;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/database",
|
|
3
|
-
"version": "0.7.0-alpha.
|
|
3
|
+
"version": "0.7.0-alpha.60",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"types": "./lib/index.d.ts",
|
|
@@ -11,13 +11,8 @@
|
|
|
11
11
|
"url": "http://www.apache.org/licenses/LICENSE-2.0"
|
|
12
12
|
}
|
|
13
13
|
],
|
|
14
|
-
"scripts": {
|
|
15
|
-
"build": "rimraf -rf lib esm dist && npm run build:cjs && npm run build:esm",
|
|
16
|
-
"build:cjs": "tsc --project tsconfig.build.json",
|
|
17
|
-
"build:esm": "tsc --project tsconfig.build.json --module es2015 --outDir esm"
|
|
18
|
-
},
|
|
19
14
|
"dependencies": {
|
|
20
|
-
"@nocobase/utils": "0.7.0-alpha.
|
|
15
|
+
"@nocobase/utils": "0.7.0-alpha.60",
|
|
21
16
|
"async-mutex": "^0.3.2",
|
|
22
17
|
"deepmerge": "^4.2.2",
|
|
23
18
|
"flat": "^5.0.2",
|
|
@@ -29,5 +24,5 @@
|
|
|
29
24
|
"url": "git+https://github.com/nocobase/nocobase.git",
|
|
30
25
|
"directory": "packages/database"
|
|
31
26
|
},
|
|
32
|
-
"gitHead": "
|
|
27
|
+
"gitHead": "f0d0afbb19dbd90ac3cf4155748fa084c67f54ee"
|
|
33
28
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { mockDatabase } from '../';
|
|
2
|
+
import { Database } from '../../database';
|
|
3
|
+
|
|
4
|
+
describe('string field', () => {
|
|
5
|
+
let db: Database;
|
|
6
|
+
|
|
7
|
+
beforeEach(async () => {
|
|
8
|
+
db = mockDatabase();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
afterEach(async () => {
|
|
12
|
+
await db.close();
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('define', async () => {
|
|
16
|
+
const Test = db.collection({
|
|
17
|
+
name: 'tests',
|
|
18
|
+
autoGenId: false,
|
|
19
|
+
fields: [
|
|
20
|
+
{
|
|
21
|
+
type: 'uuid',
|
|
22
|
+
name: 'id',
|
|
23
|
+
primaryKey: true,
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
});
|
|
27
|
+
await Test.sync();
|
|
28
|
+
await Test.model.create();
|
|
29
|
+
});
|
|
30
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { mockDatabase } from '../index';
|
|
2
|
+
import Database from '../../database';
|
|
3
|
+
|
|
4
|
+
describe('ne operator', () => {
|
|
5
|
+
let db: Database;
|
|
6
|
+
let Test;
|
|
7
|
+
beforeEach(async () => {
|
|
8
|
+
db = mockDatabase({});
|
|
9
|
+
|
|
10
|
+
Test = db.collection({
|
|
11
|
+
name: 'tests',
|
|
12
|
+
fields: [{ type: 'string', name: 'name' }],
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
await db.sync();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
afterEach(async () => {
|
|
19
|
+
await db.close();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('should notIn with null', async () => {
|
|
23
|
+
await db.getRepository('tests').create({});
|
|
24
|
+
|
|
25
|
+
const results = await db.getRepository('tests').count({
|
|
26
|
+
filter: {
|
|
27
|
+
'name.$notIn': ['123'],
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
expect(results).toEqual(1);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
@@ -81,6 +81,7 @@ describe('option parser', () => {
|
|
|
81
81
|
],
|
|
82
82
|
});
|
|
83
83
|
});
|
|
84
|
+
|
|
84
85
|
test('with sort option', () => {
|
|
85
86
|
let options: any = {
|
|
86
87
|
sort: ['id'],
|
|
@@ -182,4 +183,23 @@ describe('option parser', () => {
|
|
|
182
183
|
|
|
183
184
|
expect(params['include'][0]['attributes']['exclude']).toContain('id');
|
|
184
185
|
});
|
|
186
|
+
|
|
187
|
+
test('option parser with multiple association', () => {
|
|
188
|
+
// fields with association field
|
|
189
|
+
const options = {
|
|
190
|
+
appends: ['user', 'comments.id', 'tags.id'],
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const parser = new OptionsParser(options, {
|
|
194
|
+
collection: Post,
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
const params = parser.toSequelizeParams();
|
|
198
|
+
expect(params.include.length).toBe(3);
|
|
199
|
+
expect(params.include[0].association).toBe('user');
|
|
200
|
+
expect(params.include[1].association).toBe('comments');
|
|
201
|
+
expect(params.include[1].attributes).toEqual(['id']);
|
|
202
|
+
expect(params.include[2].association).toBe('tags');
|
|
203
|
+
expect(params.include[2].attributes).toEqual(['id']);
|
|
204
|
+
});
|
|
185
205
|
});
|
package/src/database.ts
CHANGED
|
@@ -2,7 +2,17 @@ import { applyMixins, AsyncEmitter } from '@nocobase/utils';
|
|
|
2
2
|
import merge from 'deepmerge';
|
|
3
3
|
import { EventEmitter } from 'events';
|
|
4
4
|
import lodash from 'lodash';
|
|
5
|
-
import {
|
|
5
|
+
import { isAbsolute, resolve } from 'path';
|
|
6
|
+
import {
|
|
7
|
+
ModelCtor,
|
|
8
|
+
Op,
|
|
9
|
+
Options,
|
|
10
|
+
QueryInterfaceDropAllTablesOptions,
|
|
11
|
+
QueryOptions,
|
|
12
|
+
Sequelize,
|
|
13
|
+
SyncOptions,
|
|
14
|
+
Utils
|
|
15
|
+
} from 'sequelize';
|
|
6
16
|
import { Collection, CollectionOptions, RepositoryType } from './collection';
|
|
7
17
|
import { ImporterReader, ImportFileExtension } from './collection-importer';
|
|
8
18
|
import * as FieldTypes from './fields';
|
|
@@ -64,8 +74,22 @@ export class Database extends EventEmitter implements AsyncEmitter {
|
|
|
64
74
|
if (options instanceof Sequelize) {
|
|
65
75
|
this.sequelize = options;
|
|
66
76
|
} else {
|
|
67
|
-
|
|
68
|
-
|
|
77
|
+
const opts = {
|
|
78
|
+
sync: {
|
|
79
|
+
alter: {
|
|
80
|
+
drop: false,
|
|
81
|
+
},
|
|
82
|
+
force: false,
|
|
83
|
+
},
|
|
84
|
+
...options,
|
|
85
|
+
};
|
|
86
|
+
if (options.storage && options.storage !== ':memory:') {
|
|
87
|
+
if (!isAbsolute(options.storage)) {
|
|
88
|
+
opts.storage = resolve(process.cwd(), options.storage);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
this.sequelize = new Sequelize(opts);
|
|
92
|
+
this.options = opts;
|
|
69
93
|
}
|
|
70
94
|
|
|
71
95
|
this.collections = new Map();
|
|
@@ -248,6 +272,29 @@ export class Database extends EventEmitter implements AsyncEmitter {
|
|
|
248
272
|
return this.sequelize.getDialect() === 'sqlite' && lodash.get(this.options, 'storage') == ':memory:';
|
|
249
273
|
}
|
|
250
274
|
|
|
275
|
+
async auth(options: QueryOptions & { repeat?: number } = {}) {
|
|
276
|
+
const { repeat = 10, ...others } = options;
|
|
277
|
+
const delay = (ms) => new Promise((yea) => setTimeout(yea, ms));
|
|
278
|
+
let count = 1;
|
|
279
|
+
const authenticate = async () => {
|
|
280
|
+
try {
|
|
281
|
+
await this.sequelize.authenticate(others);
|
|
282
|
+
console.log('Connection has been established successfully.');
|
|
283
|
+
return true;
|
|
284
|
+
} catch (error) {
|
|
285
|
+
if (count >= repeat) {
|
|
286
|
+
throw error;
|
|
287
|
+
}
|
|
288
|
+
console.log('reconnecting...', count);
|
|
289
|
+
++count;
|
|
290
|
+
await delay(500);
|
|
291
|
+
return await authenticate();
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
return await authenticate();
|
|
296
|
+
}
|
|
297
|
+
|
|
251
298
|
async reconnect() {
|
|
252
299
|
if (this.isSqliteMemory()) {
|
|
253
300
|
return;
|
|
@@ -312,7 +359,7 @@ export class Database extends EventEmitter implements AsyncEmitter {
|
|
|
312
359
|
return result;
|
|
313
360
|
}
|
|
314
361
|
|
|
315
|
-
emitAsync: (event: string | symbol, ...args: any[]) => Promise<boolean>;
|
|
362
|
+
declare emitAsync: (event: string | symbol, ...args: any[]) => Promise<boolean>;
|
|
316
363
|
}
|
|
317
364
|
|
|
318
365
|
export function extend(collectionOptions: CollectionOptions, mergeOptions?: MergeOptions) {
|
package/src/fields/index.ts
CHANGED
|
@@ -22,6 +22,7 @@ import { StringFieldOptions } from './string-field';
|
|
|
22
22
|
import { TextFieldOptions } from './text-field';
|
|
23
23
|
import { TimeFieldOptions } from './time-field';
|
|
24
24
|
import { UidFieldOptions } from './uid-field';
|
|
25
|
+
import { UUIDFieldOptions } from './uuid-field';
|
|
25
26
|
import { VirtualFieldOptions } from './virtual-field';
|
|
26
27
|
|
|
27
28
|
export * from './array-field';
|
|
@@ -43,6 +44,7 @@ export * from './string-field';
|
|
|
43
44
|
export * from './text-field';
|
|
44
45
|
export * from './time-field';
|
|
45
46
|
export * from './uid-field';
|
|
47
|
+
export * from './uuid-field';
|
|
46
48
|
export * from './virtual-field';
|
|
47
49
|
|
|
48
50
|
export type FieldOptions =
|
|
@@ -64,6 +66,7 @@ export type FieldOptions =
|
|
|
64
66
|
| TimeFieldOptions
|
|
65
67
|
| DateFieldOptions
|
|
66
68
|
| UidFieldOptions
|
|
69
|
+
| UUIDFieldOptions
|
|
67
70
|
| PasswordFieldOptions
|
|
68
71
|
| ContextFieldOptions
|
|
69
72
|
| BelongsToFieldOptions
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { DataTypes } from 'sequelize';
|
|
2
|
+
import { BaseColumnFieldOptions, Field, FieldContext } from './field';
|
|
3
|
+
|
|
4
|
+
export class UuidField extends Field {
|
|
5
|
+
constructor(options?: any, context?: FieldContext) {
|
|
6
|
+
super(
|
|
7
|
+
{
|
|
8
|
+
defaultValue: DataTypes.UUIDV4,
|
|
9
|
+
...options,
|
|
10
|
+
},
|
|
11
|
+
context,
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
get dataType() {
|
|
15
|
+
return DataTypes.UUID;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface UUIDFieldOptions extends BaseColumnFieldOptions {
|
|
20
|
+
type: 'uuid';
|
|
21
|
+
}
|
package/src/mock-database.ts
CHANGED
|
@@ -24,7 +24,7 @@ export function getConfigByEnv() {
|
|
|
24
24
|
host: process.env.DB_HOST,
|
|
25
25
|
port: process.env.DB_PORT,
|
|
26
26
|
dialect: process.env.DB_DIALECT,
|
|
27
|
-
logging: process.env.
|
|
27
|
+
logging: process.env.DB_LOGGING === 'on' ? console.log : false,
|
|
28
28
|
storage:
|
|
29
29
|
process.env.DB_STORAGE && process.env.DB_STORAGE !== ':memory:'
|
|
30
30
|
? resolve(process.cwd(), process.env.DB_STORAGE)
|
package/src/model-hook.ts
CHANGED
package/src/operators/index.ts
CHANGED
package/src/options-parser.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { omit } from 'lodash';
|
|
2
|
-
import { MultiAssociationAccessors, Op, Sequelize, Transaction } from 'sequelize';
|
|
2
|
+
import { MultiAssociationAccessors, Op, Sequelize, Transaction, Transactionable } from 'sequelize';
|
|
3
3
|
import {
|
|
4
4
|
CommonFindOptions,
|
|
5
5
|
CountOptions,
|
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
FindOptions,
|
|
10
10
|
TargetKey,
|
|
11
11
|
TK,
|
|
12
|
-
TransactionAble,
|
|
13
12
|
UpdateOptions
|
|
14
13
|
} from '../repository';
|
|
15
14
|
import { updateModelByValues } from '../update-associations';
|
|
@@ -20,7 +19,7 @@ export interface FindAndCountOptions extends CommonFindOptions {}
|
|
|
20
19
|
|
|
21
20
|
export interface FindOneOptions extends CommonFindOptions, FilterByTk {}
|
|
22
21
|
|
|
23
|
-
export interface AssociatedOptions extends
|
|
22
|
+
export interface AssociatedOptions extends Transactionable {
|
|
24
23
|
tk?: TK;
|
|
25
24
|
}
|
|
26
25
|
|
|
@@ -150,7 +149,10 @@ export abstract class MultipleRelationRepository extends RelationRepository {
|
|
|
150
149
|
|
|
151
150
|
const queryOptions = this.buildQueryOptions(options as any);
|
|
152
151
|
|
|
153
|
-
const instances = await this.find(
|
|
152
|
+
const instances = await this.find({
|
|
153
|
+
...queryOptions,
|
|
154
|
+
transaction,
|
|
155
|
+
});
|
|
154
156
|
|
|
155
157
|
for (const instance of instances) {
|
|
156
158
|
await updateModelByValues(instance, values, {
|
|
@@ -163,8 +165,8 @@ export abstract class MultipleRelationRepository extends RelationRepository {
|
|
|
163
165
|
|
|
164
166
|
for (const instance of instances) {
|
|
165
167
|
if (options.hooks !== false) {
|
|
166
|
-
await this.db.emitAsync(`${this.targetCollection.name}.afterUpdateWithAssociations`, instance, options);
|
|
167
|
-
await this.db.emitAsync(`${this.targetCollection.name}.afterSaveWithAssociations`, instance, options);
|
|
168
|
+
await this.db.emitAsync(`${this.targetCollection.name}.afterUpdateWithAssociations`, instance, {...options, transaction});
|
|
169
|
+
await this.db.emitAsync(`${this.targetCollection.name}.afterSaveWithAssociations`, instance, {...options, transaction});
|
|
168
170
|
}
|
|
169
171
|
}
|
|
170
172
|
|