drapcode-utility 1.7.6 → 1.7.8
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/build/encryption/index.d.ts +2 -2
- package/build/encryption/index.js +26 -66
- package/build/encryption/utility.d.ts +1 -0
- package/build/encryption/utility.js +17 -16
- package/build/format-fields/index.js +10 -7
- package/build/utils/query-parser.js +1 -1
- package/build/utils/query-paser-new.js +1 -1
- package/build/utils/util.js +8 -14
- package/package.json +4 -4
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AwsConfig, Encryption } from "./model";
|
|
2
|
-
export declare const crypt: (data: any, fields: Array<object>, encryption: Encryption, decrypt: boolean,
|
|
3
|
-
export declare const processItemEncryptDecrypt: (item: any, fields: Array<object>, encryption: Encryption, decrypt: boolean,
|
|
2
|
+
export declare const crypt: (data: any, fields: Array<object>, encryption: Encryption, decrypt: boolean, encryptedRefCollections?: Array<object>) => Promise<any>;
|
|
3
|
+
export declare const processItemEncryptDecrypt: (item: any, fields: Array<object>, encryption: Encryption, decrypt: boolean, encryptedRefCollections?: Array<object>) => Promise<any>;
|
|
4
4
|
export declare const processDataEncryptionDecryption: (data: string, encryption: Encryption, decrypt: boolean) => Promise<string>;
|
|
5
5
|
/**
|
|
6
6
|
* This method is used to generate private KEY for KMS ARN
|
|
@@ -35,15 +35,6 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
35
35
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
36
|
}
|
|
37
37
|
};
|
|
38
|
-
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
39
|
-
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
40
|
-
if (ar || !(i in from)) {
|
|
41
|
-
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
42
|
-
ar[i] = from[i];
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return to.concat(ar || Array.prototype.slice.call(from));
|
|
46
|
-
};
|
|
47
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
39
|
exports.processKMSDecryption = exports.cryptFile = exports.drapcodeEncryptDecrypt = exports.decryptDataWithKMS = exports.encryptDataWithKMS = exports.createKMSDataKey = exports.processDataEncryptionDecryption = exports.processItemEncryptDecrypt = exports.crypt = void 0;
|
|
49
40
|
var client_kms_1 = require("@aws-sdk/client-kms");
|
|
@@ -51,8 +42,8 @@ var crypt_1 = require("./crypt");
|
|
|
51
42
|
var file_1 = require("./file");
|
|
52
43
|
var KMS_1 = require("./KMS");
|
|
53
44
|
var drapcode_constant_1 = require("drapcode-constant");
|
|
54
|
-
var crypt = function (data, fields, encryption, decrypt,
|
|
55
|
-
if (
|
|
45
|
+
var crypt = function (data, fields, encryption, decrypt, encryptedRefCollections) {
|
|
46
|
+
if (encryptedRefCollections === void 0) { encryptedRefCollections = []; }
|
|
56
47
|
return __awaiter(void 0, void 0, void 0, function () {
|
|
57
48
|
var _a, accessKeyId, secretAccessKey, region, config, plainTextData, promises;
|
|
58
49
|
return __generator(this, function (_b) {
|
|
@@ -76,13 +67,13 @@ var crypt = function (data, fields, encryption, decrypt, encrypedRefCollections)
|
|
|
76
67
|
case 2:
|
|
77
68
|
if (!Array.isArray(data)) return [3 /*break*/, 4];
|
|
78
69
|
promises = data.map(function (item) {
|
|
79
|
-
return (0, exports.processItemEncryptDecrypt)(item, fields, encryption, decrypt,
|
|
70
|
+
return (0, exports.processItemEncryptDecrypt)(item, fields, encryption, decrypt, encryptedRefCollections);
|
|
80
71
|
});
|
|
81
72
|
return [4 /*yield*/, Promise.all(promises)];
|
|
82
73
|
case 3:
|
|
83
74
|
data = _b.sent();
|
|
84
75
|
return [3 /*break*/, 6];
|
|
85
|
-
case 4: return [4 /*yield*/, (0, exports.processItemEncryptDecrypt)(data, fields, encryption, decrypt,
|
|
76
|
+
case 4: return [4 /*yield*/, (0, exports.processItemEncryptDecrypt)(data, fields, encryption, decrypt, encryptedRefCollections)];
|
|
86
77
|
case 5:
|
|
87
78
|
data = _b.sent();
|
|
88
79
|
_b.label = 6;
|
|
@@ -92,8 +83,8 @@ var crypt = function (data, fields, encryption, decrypt, encrypedRefCollections)
|
|
|
92
83
|
});
|
|
93
84
|
};
|
|
94
85
|
exports.crypt = crypt;
|
|
95
|
-
var processItemEncryptDecrypt = function (item, fields, encryption, decrypt,
|
|
96
|
-
if (
|
|
86
|
+
var processItemEncryptDecrypt = function (item, fields, encryption, decrypt, encryptedRefCollections) {
|
|
87
|
+
if (encryptedRefCollections === void 0) { encryptedRefCollections = []; }
|
|
97
88
|
return __awaiter(void 0, void 0, void 0, function () {
|
|
98
89
|
var _loop_1, _i, _a, fieldName;
|
|
99
90
|
return __generator(this, function (_b) {
|
|
@@ -101,35 +92,33 @@ var processItemEncryptDecrypt = function (item, fields, encryption, decrypt, enc
|
|
|
101
92
|
case 0:
|
|
102
93
|
if (!(item && typeof item === "object")) return [3 /*break*/, 4];
|
|
103
94
|
_loop_1 = function (fieldName) {
|
|
104
|
-
var field, promises, _c, _d, _e, _f, refField, _g, _h
|
|
105
|
-
return __generator(this, function (
|
|
106
|
-
switch (
|
|
95
|
+
var field, promises, _c, _d, _e, _f, refField, _g, _h;
|
|
96
|
+
return __generator(this, function (_j) {
|
|
97
|
+
switch (_j.label) {
|
|
107
98
|
case 0:
|
|
108
99
|
field = fields.find(function (field) { return field.fieldName === fieldName; });
|
|
109
100
|
if (!(field && field.encrypted)) return [3 /*break*/, 4];
|
|
110
|
-
if (!(Array.isArray(item[fieldName]) &&
|
|
101
|
+
if (!(Array.isArray(item[fieldName]) &&
|
|
102
|
+
drapcode_constant_1.OptionTypeFields.includes(field.type))) return [3 /*break*/, 2];
|
|
111
103
|
promises = item[fieldName].map(function (value) {
|
|
112
|
-
return item[fieldName] = (0, exports.processDataEncryptionDecryption)(value, encryption, decrypt);
|
|
104
|
+
return (item[fieldName] = (0, exports.processDataEncryptionDecryption)(value, encryption, decrypt));
|
|
113
105
|
});
|
|
114
106
|
_c = item;
|
|
115
107
|
_d = fieldName;
|
|
116
108
|
return [4 /*yield*/, Promise.all(promises)];
|
|
117
109
|
case 1:
|
|
118
|
-
_c[_d] =
|
|
110
|
+
_c[_d] = _j.sent();
|
|
119
111
|
return [3 /*break*/, 4];
|
|
120
112
|
case 2:
|
|
121
113
|
_e = item;
|
|
122
114
|
_f = fieldName;
|
|
123
115
|
return [4 /*yield*/, (0, exports.processDataEncryptionDecryption)(item[fieldName], encryption, decrypt)];
|
|
124
116
|
case 3:
|
|
125
|
-
_e[_f] =
|
|
126
|
-
|
|
117
|
+
_e[_f] = _j.sent();
|
|
118
|
+
_j.label = 4;
|
|
127
119
|
case 4:
|
|
128
|
-
if (!decrypt) return [3 /*break*/,
|
|
129
|
-
if (!
|
|
130
|
-
drapcode_constant_1.FieldTypes.createdBy.id,
|
|
131
|
-
drapcode_constant_1.FieldTypes.belongsTo.id,
|
|
132
|
-
], false).includes(field === null || field === void 0 ? void 0 : field.type)) return [3 /*break*/, 6];
|
|
120
|
+
if (!decrypt) return [3 /*break*/, 6];
|
|
121
|
+
if (!drapcode_constant_1.BelongsCreatedByRefField.includes(field === null || field === void 0 ? void 0 : field.type)) return [3 /*break*/, 6];
|
|
133
122
|
refField = field;
|
|
134
123
|
if (!refField.refCollection &&
|
|
135
124
|
field.type === drapcode_constant_1.FieldTypes.createdBy.id) {
|
|
@@ -140,19 +129,11 @@ var processItemEncryptDecrypt = function (item, fields, encryption, decrypt, enc
|
|
|
140
129
|
}
|
|
141
130
|
_g = item;
|
|
142
131
|
_h = fieldName;
|
|
143
|
-
return [4 /*yield*/, processReferenceItemDecrypt(item[fieldName], encryption, decrypt, refField,
|
|
132
|
+
return [4 /*yield*/, processReferenceItemDecrypt(item[fieldName], encryption, decrypt, refField, encryptedRefCollections)];
|
|
144
133
|
case 5:
|
|
145
|
-
_g[_h] =
|
|
146
|
-
|
|
147
|
-
case 6:
|
|
148
|
-
if (!((field === null || field === void 0 ? void 0 : field.type) === drapcode_constant_1.FieldTypes.dynamic_option.id)) return [3 /*break*/, 8];
|
|
149
|
-
_j = item;
|
|
150
|
-
_k = fieldName;
|
|
151
|
-
return [4 /*yield*/, processDynamicFieldDecrypt(item[fieldName], encryption, decrypt, field, encrypedRefCollections)];
|
|
152
|
-
case 7:
|
|
153
|
-
_j[_k] = _l.sent();
|
|
154
|
-
_l.label = 8;
|
|
155
|
-
case 8: return [2 /*return*/];
|
|
134
|
+
_g[_h] = _j.sent();
|
|
135
|
+
_j.label = 6;
|
|
136
|
+
case 6: return [2 /*return*/];
|
|
156
137
|
}
|
|
157
138
|
});
|
|
158
139
|
};
|
|
@@ -205,12 +186,12 @@ var processDataEncryptionDecryption = function (data, encryption, decrypt) { ret
|
|
|
205
186
|
});
|
|
206
187
|
}); };
|
|
207
188
|
exports.processDataEncryptionDecryption = processDataEncryptionDecryption;
|
|
208
|
-
var processReferenceItemDecrypt = function (data, encryption, decrypt, refField,
|
|
189
|
+
var processReferenceItemDecrypt = function (data, encryption, decrypt, refField, encryptedRefCollections) { return __awaiter(void 0, void 0, void 0, function () {
|
|
209
190
|
var refCollection, promises;
|
|
210
191
|
return __generator(this, function (_a) {
|
|
211
192
|
switch (_a.label) {
|
|
212
193
|
case 0:
|
|
213
|
-
refCollection = getEncryptedReferenceCollection(
|
|
194
|
+
refCollection = getEncryptedReferenceCollection(encryptedRefCollections, refField).refCollection;
|
|
214
195
|
if (!refCollection) return [3 /*break*/, 2];
|
|
215
196
|
if (!Array.isArray(data)) return [3 /*break*/, 2];
|
|
216
197
|
promises = data.map(function (item) {
|
|
@@ -224,33 +205,12 @@ var processReferenceItemDecrypt = function (data, encryption, decrypt, refField,
|
|
|
224
205
|
}
|
|
225
206
|
});
|
|
226
207
|
}); };
|
|
227
|
-
var
|
|
228
|
-
var _a, refCollectionFieldName, refCollection, refCollectionField, promises;
|
|
229
|
-
return __generator(this, function (_b) {
|
|
230
|
-
switch (_b.label) {
|
|
231
|
-
case 0:
|
|
232
|
-
_a = getEncryptedReferenceCollection(encrypedRefCollections, refField), refCollectionFieldName = _a.refCollectionFieldName, refCollection = _a.refCollection;
|
|
233
|
-
if (!refCollection) return [3 /*break*/, 2];
|
|
234
|
-
refCollectionField = refCollection.fields.find(function (field) { return field.fieldName === refCollectionFieldName; });
|
|
235
|
-
if (!(refCollectionField && refCollectionField.encrypted)) return [3 /*break*/, 2];
|
|
236
|
-
if (!Array.isArray(data)) return [3 /*break*/, 2];
|
|
237
|
-
promises = data.map(function (item) {
|
|
238
|
-
return (0, exports.processDataEncryptionDecryption)(item, encryption, decrypt);
|
|
239
|
-
});
|
|
240
|
-
return [4 /*yield*/, Promise.all(promises)];
|
|
241
|
-
case 1:
|
|
242
|
-
data = _b.sent();
|
|
243
|
-
_b.label = 2;
|
|
244
|
-
case 2: return [2 /*return*/, data];
|
|
245
|
-
}
|
|
246
|
-
});
|
|
247
|
-
}); };
|
|
248
|
-
var getEncryptedReferenceCollection = function (encrypedRefCollections, refField) {
|
|
208
|
+
var getEncryptedReferenceCollection = function (encryptedRefCollections, refField) {
|
|
249
209
|
var _a = refField === null || refField === void 0 ? void 0 : refField.refCollection, refCollectionName = _a.collectionName, refCollectionFieldName = _a.collectionField;
|
|
250
210
|
var refCollection;
|
|
251
|
-
if (
|
|
211
|
+
if (encryptedRefCollections.length) {
|
|
252
212
|
if (refCollectionName) {
|
|
253
|
-
refCollection =
|
|
213
|
+
refCollection = encryptedRefCollections.find(function (encColl) { return encColl.collectionName === refCollectionName; });
|
|
254
214
|
}
|
|
255
215
|
}
|
|
256
216
|
return { refCollectionName: refCollectionName, refCollectionFieldName: refCollectionFieldName, refCollection: refCollection };
|
|
@@ -9,30 +9,31 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
|
9
9
|
return to.concat(ar || Array.prototype.slice.call(from));
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.getEncryptedReferenceFieldsQuery = void 0;
|
|
12
|
+
exports.prepareDBQuery = exports.getEncryptedReferenceFieldsQuery = void 0;
|
|
13
13
|
var drapcode_constant_1 = require("drapcode-constant");
|
|
14
14
|
var getEncryptedReferenceFieldsQuery = function (collectionFields, projectId) {
|
|
15
15
|
var collectionsNamesArr = [];
|
|
16
|
-
collectionFields.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
var collectionName = field.refCollection.collectionName;
|
|
27
|
-
collectionsNamesArr.push(collectionName);
|
|
28
|
-
}
|
|
16
|
+
collectionFields = collectionFields.filter(function (field) {
|
|
17
|
+
return drapcode_constant_1.BelongsCreatedByRefField.includes(field.type);
|
|
18
|
+
});
|
|
19
|
+
collectionFields.forEach(function (field) {
|
|
20
|
+
if (!field.refCollection && field.type === drapcode_constant_1.FieldTypes.createdBy.id) {
|
|
21
|
+
collectionsNamesArr.push("user");
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
var collectionName = field.refCollection.collectionName;
|
|
25
|
+
collectionsNamesArr.push(collectionName);
|
|
29
26
|
}
|
|
30
27
|
});
|
|
28
|
+
return (0, exports.prepareDBQuery)(projectId, collectionsNamesArr);
|
|
29
|
+
};
|
|
30
|
+
exports.getEncryptedReferenceFieldsQuery = getEncryptedReferenceFieldsQuery;
|
|
31
|
+
var prepareDBQuery = function (projectId, collections) {
|
|
31
32
|
var query = [
|
|
32
33
|
{
|
|
33
34
|
$match: {
|
|
34
35
|
projectId: projectId,
|
|
35
|
-
collectionName: { $in: __spreadArray([],
|
|
36
|
+
collectionName: { $in: __spreadArray([], collections, true) },
|
|
36
37
|
fields: { $elemMatch: { encrypted: true } },
|
|
37
38
|
},
|
|
38
39
|
},
|
|
@@ -52,4 +53,4 @@ var getEncryptedReferenceFieldsQuery = function (collectionFields, projectId) {
|
|
|
52
53
|
];
|
|
53
54
|
return query;
|
|
54
55
|
};
|
|
55
|
-
exports.
|
|
56
|
+
exports.prepareDBQuery = prepareDBQuery;
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
3
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
4
|
+
if (ar || !(i in from)) {
|
|
5
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
6
|
+
ar[i] = from[i];
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
10
|
+
};
|
|
2
11
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
13
|
};
|
|
@@ -55,13 +64,7 @@ var getFormatFieldData = function (fieldData, fieldType) {
|
|
|
55
64
|
markdown.id,
|
|
56
65
|
];
|
|
57
66
|
var numberType = [number.id, unix_timestamp.id];
|
|
58
|
-
var arrayType = [
|
|
59
|
-
reference.id,
|
|
60
|
-
belongsTo.id,
|
|
61
|
-
multi_reference.id,
|
|
62
|
-
dynamic_option.id,
|
|
63
|
-
static_option.id,
|
|
64
|
-
];
|
|
67
|
+
var arrayType = __spreadArray(__spreadArray([], drapcode_constant_1.NonBelongsSelectOptionFields, true), [belongsTo.id], false);
|
|
65
68
|
if (stringType.includes(fieldType)) {
|
|
66
69
|
if (typeof fieldData !== "string")
|
|
67
70
|
fieldData = String(fieldData);
|
|
@@ -167,7 +167,7 @@ var queryParser = function (collectionName, query, constants, externalParams, cu
|
|
|
167
167
|
}
|
|
168
168
|
console.log("==> aggregateQuery", aggregateQuery);
|
|
169
169
|
console.log("==> aggregateQuery", JSON.stringify(aggregateQuery));
|
|
170
|
-
queryStr = ".aggregate(".concat(JSON.stringify(aggregateQuery), ", { collation: { locale: \"en\" } })");
|
|
170
|
+
queryStr = ".aggregate(".concat(JSON.stringify(aggregateQuery), ", { collation: { locale: \"en\" }, allowDiskUse: true })");
|
|
171
171
|
str = "req.db.collection('".concat(collectionName, "')").concat(queryStr);
|
|
172
172
|
str += ".toArray()";
|
|
173
173
|
return [2 /*return*/, str];
|
|
@@ -256,7 +256,7 @@ var queryParserNew = function (collectionName, query, constants, externalParams,
|
|
|
256
256
|
if (finder != "COUNT" && limit) {
|
|
257
257
|
aggregateQuery.push({ $skip: +offset }, { $limit: +limit });
|
|
258
258
|
}
|
|
259
|
-
queryStr = ".aggregate(".concat(JSON.stringify(aggregateQuery), ", { collation: { locale: \"en\" } })");
|
|
259
|
+
queryStr = ".aggregate(".concat(JSON.stringify(aggregateQuery), ", { collation: { locale: \"en\" }, allowDiskUse: true })");
|
|
260
260
|
str = "req.db.collection('".concat(collectionName, "')").concat(queryStr);
|
|
261
261
|
str += ".toArray()";
|
|
262
262
|
return [2 /*return*/, str];
|
package/build/utils/util.js
CHANGED
|
@@ -586,14 +586,8 @@ var replaceValueFromTenant = function (variableName, tenant) {
|
|
|
586
586
|
return lodash_1.default.get(tenant, variableName);
|
|
587
587
|
};
|
|
588
588
|
var fillDefaultValues = function (collection, itemdata) {
|
|
589
|
-
var
|
|
590
|
-
var fieldsToSkip =
|
|
591
|
-
drapcode_constant_1.FieldTypes.isDeleted.id,
|
|
592
|
-
drapcode_constant_1.FieldTypes.uuid.id,
|
|
593
|
-
drapcode_constant_1.FieldTypes.createdBy.id,
|
|
594
|
-
drapcode_constant_1.FieldTypes.updatedAt.id,
|
|
595
|
-
drapcode_constant_1.FieldTypes.createdAt.id,
|
|
596
|
-
];
|
|
589
|
+
var filledItemData = __assign({}, itemdata);
|
|
590
|
+
var fieldsToSkip = drapcode_constant_1.hiddenFormField;
|
|
597
591
|
var fieldTypesToSkip = [drapcode_constant_1.FieldTypes.boolean.id];
|
|
598
592
|
var allFields = collection.fields.filter(function (field) {
|
|
599
593
|
return !fieldsToSkip.includes(field.fieldName) &&
|
|
@@ -601,18 +595,18 @@ var fillDefaultValues = function (collection, itemdata) {
|
|
|
601
595
|
});
|
|
602
596
|
allFields.forEach(function (field) {
|
|
603
597
|
var fieldName = field.fieldName;
|
|
604
|
-
if (!(fieldName in
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
598
|
+
if (!(fieldName in filledItemData) ||
|
|
599
|
+
filledItemData[fieldName] === "" ||
|
|
600
|
+
filledItemData[fieldName] === 0 ||
|
|
601
|
+
filledItemData[fieldName] === false) {
|
|
608
602
|
var formattedField = JSON.parse(JSON.stringify(field));
|
|
609
603
|
if (field.extraFieldSetting &&
|
|
610
604
|
"defaultValue" in formattedField.extraFieldSetting) {
|
|
611
|
-
|
|
605
|
+
filledItemData[fieldName] = assignFieldValue(formattedField, field, fieldName, filledItemData);
|
|
612
606
|
}
|
|
613
607
|
}
|
|
614
608
|
});
|
|
615
|
-
return
|
|
609
|
+
return filledItemData;
|
|
616
610
|
};
|
|
617
611
|
exports.fillDefaultValues = fillDefaultValues;
|
|
618
612
|
var assignFieldValue = function (formattedField, field, fieldName, filledItemdata) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "drapcode-utility",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.8",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -37,9 +37,9 @@
|
|
|
37
37
|
"@types/voca": "^1.4.2",
|
|
38
38
|
"axios": "^1.1.2",
|
|
39
39
|
"dompurify": "^3.1.7",
|
|
40
|
-
"drapcode-constant": "^1.6.
|
|
41
|
-
"drapcode-logger": "^1.2.
|
|
42
|
-
"drapcode-redis": "^1.1.
|
|
40
|
+
"drapcode-constant": "^1.6.1",
|
|
41
|
+
"drapcode-logger": "^1.2.8",
|
|
42
|
+
"drapcode-redis": "^1.1.7",
|
|
43
43
|
"exiftool-vendored": "^28.2.1",
|
|
44
44
|
"express": "^4.17.1",
|
|
45
45
|
"gm": "^1.25.0",
|