dbgate-datalib 6.1.6 → 6.2.1
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/ChangeSet.d.ts +3 -3
- package/lib/ChangeSet.js +56 -27
- package/lib/GridDisplay.d.ts +1 -0
- package/lib/GridDisplay.js +12 -10
- package/lib/PerspectiveTreeNode.d.ts +1 -0
- package/lib/PerspectiveTreeNode.js +5 -0
- package/lib/TableGridDisplay.js +5 -2
- package/package.json +5 -5
package/lib/ChangeSet.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Command, Condition } from 'dbgate-sqltree';
|
|
2
|
-
import type { NamedObjectInfo, DatabaseInfo, TableInfo } from 'dbgate-types';
|
|
2
|
+
import type { NamedObjectInfo, DatabaseInfo, TableInfo, SqlDialect } from 'dbgate-types';
|
|
3
3
|
import { JsonDataObjectUpdateCommand } from 'dbgate-tools';
|
|
4
4
|
export interface ChangeSetItem {
|
|
5
5
|
pureName: string;
|
|
@@ -45,8 +45,8 @@ export declare function findExistingChangeSetItem(changeSet: ChangeSet, definiti
|
|
|
45
45
|
export declare function setChangeSetValue(changeSet: ChangeSet, definition: ChangeSetFieldDefinition, value: string): ChangeSet;
|
|
46
46
|
export declare function setChangeSetRowData(changeSet: ChangeSet, definition: ChangeSetRowDefinition, document: any): ChangeSet;
|
|
47
47
|
export declare function batchUpdateChangeSet(changeSet: ChangeSet, rowDefinitions: ChangeSetRowDefinition[], dataRows: []): ChangeSet;
|
|
48
|
-
export declare function extractChangeSetCondition(item: ChangeSetItem, alias?: string): Condition;
|
|
49
|
-
export declare function changeSetToSql(changeSet: ChangeSet, dbinfo: DatabaseInfo): Command[];
|
|
48
|
+
export declare function extractChangeSetCondition(item: ChangeSetItem, alias?: string, table?: TableInfo, dialect?: SqlDialect): Condition;
|
|
49
|
+
export declare function changeSetToSql(changeSet: ChangeSet, dbinfo: DatabaseInfo, dialect: SqlDialect): Command[];
|
|
50
50
|
export declare function revertChangeSetRowChanges(changeSet: ChangeSet, definition: ChangeSetRowDefinition): ChangeSet;
|
|
51
51
|
export declare function deleteChangeSetRows(changeSet: ChangeSet, definition: ChangeSetRowDefinition): ChangeSet;
|
|
52
52
|
export declare function getChangeSetInsertedRows(changeSet: ChangeSet, name?: NamedObjectInfo): any[];
|
package/lib/ChangeSet.js
CHANGED
|
@@ -136,31 +136,53 @@ function batchUpdateChangeSet(changeSet, rowDefinitions, dataRows) {
|
|
|
136
136
|
return changeSet;
|
|
137
137
|
}
|
|
138
138
|
exports.batchUpdateChangeSet = batchUpdateChangeSet;
|
|
139
|
-
function extractFields(item, allowNulls = true, allowedDocumentColumns = []) {
|
|
139
|
+
function extractFields(item, allowNulls = true, allowedDocumentColumns = [], table, dialect) {
|
|
140
140
|
const allFields = Object.assign({}, item.fields);
|
|
141
|
+
function isUuidColumn(columnName) {
|
|
142
|
+
var _a;
|
|
143
|
+
return ((_a = table === null || table === void 0 ? void 0 : table.columns.find(x => x.columnName == columnName)) === null || _a === void 0 ? void 0 : _a.dataType.toLowerCase()) == 'uuid';
|
|
144
|
+
}
|
|
145
|
+
function createUpdateField(targetColumn) {
|
|
146
|
+
var _a, _b;
|
|
147
|
+
const shouldGenerateDefaultValue = isUuidColumn(targetColumn) && allFields[targetColumn] == null && (dialect === null || dialect === void 0 ? void 0 : dialect.generateDefaultValueForUuid);
|
|
148
|
+
if (shouldGenerateDefaultValue) {
|
|
149
|
+
return {
|
|
150
|
+
targetColumn,
|
|
151
|
+
sql: dialect === null || dialect === void 0 ? void 0 : dialect.generateDefaultValueForUuid,
|
|
152
|
+
exprType: 'raw',
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
targetColumn,
|
|
157
|
+
exprType: 'value',
|
|
158
|
+
value: allFields[targetColumn],
|
|
159
|
+
dataType: (_b = (_a = table === null || table === void 0 ? void 0 : table.columns) === null || _a === void 0 ? void 0 : _a.find(x => x.columnName == targetColumn)) === null || _b === void 0 ? void 0 : _b.dataType,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
141
162
|
for (const docField in item.document || {}) {
|
|
142
163
|
if (allowedDocumentColumns.includes(docField)) {
|
|
143
164
|
allFields[docField] = item.document[docField];
|
|
144
165
|
}
|
|
145
166
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
.map(
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
167
|
+
const columnNames = Object.keys(allFields);
|
|
168
|
+
if ((dialect === null || dialect === void 0 ? void 0 : dialect.generateDefaultValueForUuid) && table) {
|
|
169
|
+
columnNames.push(...table.columns.map(i => i.columnName));
|
|
170
|
+
}
|
|
171
|
+
return lodash_1.default.uniq(columnNames)
|
|
172
|
+
.filter(targetColumn => allowNulls ||
|
|
173
|
+
allFields[targetColumn] != null ||
|
|
174
|
+
(isUuidColumn(targetColumn) && (dialect === null || dialect === void 0 ? void 0 : dialect.generateDefaultValueForUuid)))
|
|
175
|
+
.map(targetColumn => createUpdateField(targetColumn));
|
|
153
176
|
}
|
|
154
|
-
function changeSetInsertToSql(item, dbinfo = null) {
|
|
177
|
+
function changeSetInsertToSql(item, dbinfo = null, dialect = null) {
|
|
155
178
|
var _a, _b;
|
|
156
179
|
const table = (_a = dbinfo === null || dbinfo === void 0 ? void 0 : dbinfo.tables) === null || _a === void 0 ? void 0 : _a.find(x => x.schemaName == item.schemaName && x.pureName == item.pureName);
|
|
157
|
-
const fields = extractFields(item, false, (_b = table === null || table === void 0 ? void 0 : table.columns) === null || _b === void 0 ? void 0 : _b.map(x => x.columnName));
|
|
180
|
+
const fields = extractFields(item, false, (_b = table === null || table === void 0 ? void 0 : table.columns) === null || _b === void 0 ? void 0 : _b.map(x => x.columnName), table, dialect);
|
|
158
181
|
if (fields.length == 0)
|
|
159
182
|
return null;
|
|
160
183
|
let autoInc = false;
|
|
161
184
|
if (table) {
|
|
162
185
|
const autoIncCol = table.columns.find(x => x.autoIncrement);
|
|
163
|
-
// console.log('autoIncCol', autoIncCol);
|
|
164
186
|
if (autoIncCol && fields.find(x => x.targetColumn == autoIncCol.columnName)) {
|
|
165
187
|
autoInc = true;
|
|
166
188
|
}
|
|
@@ -194,19 +216,23 @@ function changeSetInsertToSql(item, dbinfo = null) {
|
|
|
194
216
|
: null,
|
|
195
217
|
];
|
|
196
218
|
}
|
|
197
|
-
function extractChangeSetCondition(item, alias) {
|
|
219
|
+
function extractChangeSetCondition(item, alias, table, dialect) {
|
|
198
220
|
function getColumnCondition(columnName) {
|
|
221
|
+
var _a, _b;
|
|
222
|
+
const dataType = (_b = (_a = table === null || table === void 0 ? void 0 : table.columns) === null || _a === void 0 ? void 0 : _a.find(x => x.columnName == columnName)) === null || _b === void 0 ? void 0 : _b.dataType;
|
|
199
223
|
const value = item.condition[columnName];
|
|
200
224
|
const expr = {
|
|
201
225
|
exprType: 'column',
|
|
202
226
|
columnName,
|
|
203
|
-
source:
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
227
|
+
source: (dialect === null || dialect === void 0 ? void 0 : dialect.omitTableBeforeColumn)
|
|
228
|
+
? undefined
|
|
229
|
+
: {
|
|
230
|
+
name: {
|
|
231
|
+
pureName: item.pureName,
|
|
232
|
+
schemaName: item.schemaName,
|
|
233
|
+
},
|
|
234
|
+
alias,
|
|
207
235
|
},
|
|
208
|
-
alias,
|
|
209
|
-
},
|
|
210
236
|
};
|
|
211
237
|
if (value == null) {
|
|
212
238
|
return {
|
|
@@ -221,6 +247,7 @@ function extractChangeSetCondition(item, alias) {
|
|
|
221
247
|
left: expr,
|
|
222
248
|
right: {
|
|
223
249
|
exprType: 'value',
|
|
250
|
+
dataType,
|
|
224
251
|
value,
|
|
225
252
|
},
|
|
226
253
|
};
|
|
@@ -262,7 +289,7 @@ function compileSimpleChangeSetCondition(fields) {
|
|
|
262
289
|
conditions: lodash_1.default.keys(fields).map(columnName => getColumnCondition(columnName)),
|
|
263
290
|
};
|
|
264
291
|
}
|
|
265
|
-
function changeSetUpdateToSql(item, dbinfo = null) {
|
|
292
|
+
function changeSetUpdateToSql(item, dbinfo = null, dialect = null) {
|
|
266
293
|
var _a, _b, _c;
|
|
267
294
|
const table = (_a = dbinfo === null || dbinfo === void 0 ? void 0 : dbinfo.tables) === null || _a === void 0 ? void 0 : _a.find(x => x.schemaName == item.schemaName && x.pureName == item.pureName);
|
|
268
295
|
const autoIncCol = (_b = table === null || table === void 0 ? void 0 : table.columns) === null || _b === void 0 ? void 0 : _b.find(x => x.autoIncrement);
|
|
@@ -274,11 +301,13 @@ function changeSetUpdateToSql(item, dbinfo = null) {
|
|
|
274
301
|
},
|
|
275
302
|
},
|
|
276
303
|
commandType: 'update',
|
|
277
|
-
fields: extractFields(item, true, (_c = table === null || table === void 0 ? void 0 : table.columns) === null || _c === void 0 ? void 0 : _c.map(x => x.columnName).filter(x => x != (autoIncCol === null || autoIncCol === void 0 ? void 0 : autoIncCol.columnName))),
|
|
278
|
-
where: extractChangeSetCondition(item),
|
|
304
|
+
fields: extractFields(item, true, (_c = table === null || table === void 0 ? void 0 : table.columns) === null || _c === void 0 ? void 0 : _c.map(x => x.columnName).filter(x => x != (autoIncCol === null || autoIncCol === void 0 ? void 0 : autoIncCol.columnName)), table),
|
|
305
|
+
where: extractChangeSetCondition(item, undefined, table, dialect),
|
|
279
306
|
};
|
|
280
307
|
}
|
|
281
|
-
function changeSetDeleteToSql(item) {
|
|
308
|
+
function changeSetDeleteToSql(item, dbinfo = null, dialect = null) {
|
|
309
|
+
var _a;
|
|
310
|
+
const table = (_a = dbinfo === null || dbinfo === void 0 ? void 0 : dbinfo.tables) === null || _a === void 0 ? void 0 : _a.find(x => x.schemaName == item.schemaName && x.pureName == item.pureName);
|
|
282
311
|
return {
|
|
283
312
|
from: {
|
|
284
313
|
name: {
|
|
@@ -287,14 +316,14 @@ function changeSetDeleteToSql(item) {
|
|
|
287
316
|
},
|
|
288
317
|
},
|
|
289
318
|
commandType: 'delete',
|
|
290
|
-
where: extractChangeSetCondition(item),
|
|
319
|
+
where: extractChangeSetCondition(item, undefined, table, dialect),
|
|
291
320
|
};
|
|
292
321
|
}
|
|
293
|
-
function changeSetToSql(changeSet, dbinfo) {
|
|
322
|
+
function changeSetToSql(changeSet, dbinfo, dialect) {
|
|
294
323
|
return lodash_1.default.compact(lodash_1.default.flatten([
|
|
295
|
-
...changeSet.inserts.map(item => changeSetInsertToSql(item, dbinfo)),
|
|
296
|
-
...changeSet.updates.map(item => changeSetUpdateToSql(item, dbinfo)),
|
|
297
|
-
...changeSet.deletes.map(changeSetDeleteToSql),
|
|
324
|
+
...changeSet.inserts.map(item => changeSetInsertToSql(item, dbinfo, dialect)),
|
|
325
|
+
...changeSet.updates.map(item => changeSetUpdateToSql(item, dbinfo, dialect)),
|
|
326
|
+
...changeSet.deletes.map(item => changeSetDeleteToSql(item, dbinfo, dialect)),
|
|
298
327
|
]));
|
|
299
328
|
}
|
|
300
329
|
exports.changeSetToSql = changeSetToSql;
|
package/lib/GridDisplay.d.ts
CHANGED
|
@@ -115,6 +115,7 @@ export declare abstract class GridDisplay {
|
|
|
115
115
|
createSelectBase(name: NamedObjectInfo, columns: ColumnInfo[], options: any, defaultOrderColumnName?: string): Select;
|
|
116
116
|
getRowNumberOverSelect(select: Select, offset: number, count: number): Select;
|
|
117
117
|
getPageQuery(offset: number, count: number): Select;
|
|
118
|
+
getPageQueryText(offset: number, count: number): string;
|
|
118
119
|
getExportQuery(postprocessSelect?: any): string;
|
|
119
120
|
getExportQueryJson(postprocessSelect?: any): Select;
|
|
120
121
|
getExportColumnMap(): {
|
package/lib/GridDisplay.js
CHANGED
|
@@ -161,7 +161,7 @@ class GridDisplay {
|
|
|
161
161
|
if (condition) {
|
|
162
162
|
orCondition.conditions.push(lodash_1.default.cloneDeepWith(condition, (expr) => {
|
|
163
163
|
if (expr.exprType == 'placeholder') {
|
|
164
|
-
return this.createColumnExpression(column, { alias: 'basetbl' }, undefined, 'filter');
|
|
164
|
+
return this.createColumnExpression(column, !this.dialect.omitTableAliases ? { alias: 'basetbl' } : undefined, undefined, 'filter');
|
|
165
165
|
}
|
|
166
166
|
}));
|
|
167
167
|
}
|
|
@@ -268,7 +268,7 @@ class GridDisplay {
|
|
|
268
268
|
}
|
|
269
269
|
}
|
|
270
270
|
getColumns(columnFilter) {
|
|
271
|
-
return this.columns.filter(col => (0, dbgate_tools_1.filterName)(columnFilter, col.columnName));
|
|
271
|
+
return this.columns.filter(col => { var _a; return (0, dbgate_tools_1.filterName)(columnFilter, (_a = col.columnName) === null || _a === void 0 ? void 0 : _a.toString()); });
|
|
272
272
|
}
|
|
273
273
|
getGridColumns() {
|
|
274
274
|
return this.getColumns(null).filter(x => this.isColumnChecked(x));
|
|
@@ -408,7 +408,7 @@ class GridDisplay {
|
|
|
408
408
|
return expr;
|
|
409
409
|
}
|
|
410
410
|
}
|
|
411
|
-
return Object.assign({ exprType: 'column', alias: alias || col.columnName, source }, col);
|
|
411
|
+
return Object.assign(Object.assign(Object.assign({ exprType: 'column' }, (!this.dialect.omitTableAliases && { alias: alias || col.columnName })), { source }), col);
|
|
412
412
|
}
|
|
413
413
|
createSelectBase(name, columns, options, defaultOrderColumnName) {
|
|
414
414
|
var _a, _b;
|
|
@@ -417,11 +417,8 @@ class GridDisplay {
|
|
|
417
417
|
const orderColumnName = defaultOrderColumnName !== null && defaultOrderColumnName !== void 0 ? defaultOrderColumnName : (_a = columns[0]) === null || _a === void 0 ? void 0 : _a.columnName;
|
|
418
418
|
const select = {
|
|
419
419
|
commandType: 'select',
|
|
420
|
-
from: {
|
|
421
|
-
|
|
422
|
-
alias: 'basetbl',
|
|
423
|
-
},
|
|
424
|
-
columns: columns.map(col => this.createColumnExpression(col, { alias: 'basetbl' }, undefined, 'view')),
|
|
420
|
+
from: Object.assign({ name: lodash_1.default.pick(name, ['schemaName', 'pureName']) }, (!this.dialect.omitTableAliases && { alias: 'basetbl' })),
|
|
421
|
+
columns: columns.map(col => this.createColumnExpression(col, !this.dialect.omitTableAliases ? { alias: 'basetbl' } : undefined, undefined, 'view')),
|
|
425
422
|
orderBy: ((_b = this.driver) === null || _b === void 0 ? void 0 : _b.requiresDefaultSortCriteria)
|
|
426
423
|
? [
|
|
427
424
|
{
|
|
@@ -432,7 +429,7 @@ class GridDisplay {
|
|
|
432
429
|
]
|
|
433
430
|
: null,
|
|
434
431
|
};
|
|
435
|
-
const displayedColumnInfo = lodash_1.default.keyBy(this.columns.map(col => (Object.assign(Object.assign({}, col), { sourceAlias: 'basetbl' }))), 'uniqueName');
|
|
432
|
+
const displayedColumnInfo = lodash_1.default.keyBy(this.columns.map(col => (Object.assign(Object.assign({}, col), (!this.dialect.omitTableAliases && { sourceAlias: 'basetbl' })))), 'uniqueName');
|
|
436
433
|
this.processReferences(select, displayedColumnInfo, options);
|
|
437
434
|
this.applyFilterOnSelect(select, displayedColumnInfo);
|
|
438
435
|
this.applyGroupOnSelect(select, displayedColumnInfo);
|
|
@@ -454,7 +451,7 @@ class GridDisplay {
|
|
|
454
451
|
? x
|
|
455
452
|
: x.source
|
|
456
453
|
? x
|
|
457
|
-
: Object.assign(Object.assign({}, x), { source: { alias: 'basetbl' } }))
|
|
454
|
+
: Object.assign(Object.assign({}, x), (!this.dialect.omitTableAliases && { source: { alias: 'basetbl' } })))
|
|
458
455
|
: [
|
|
459
456
|
Object.assign(Object.assign({}, select.columns[0]), { direction: 'ASC' }),
|
|
460
457
|
],
|
|
@@ -505,6 +502,11 @@ class GridDisplay {
|
|
|
505
502
|
// const sql = treeToSql(this.driver, select, dumpSqlSelect);
|
|
506
503
|
// return sql;
|
|
507
504
|
}
|
|
505
|
+
getPageQueryText(offset, count) {
|
|
506
|
+
const select = this.getPageQuery(offset, count);
|
|
507
|
+
const sql = (0, dbgate_sqltree_1.treeToSql)(this.driver, select, dbgate_sqltree_1.dumpSqlSelect);
|
|
508
|
+
return sql;
|
|
509
|
+
}
|
|
508
510
|
getExportQuery(postprocessSelect = null) {
|
|
509
511
|
const select = this.createSelect({ isExport: true });
|
|
510
512
|
if (!select)
|
|
@@ -57,6 +57,7 @@ export declare abstract class PerspectiveTreeNode {
|
|
|
57
57
|
get customJoinConfig(): PerspectiveCustomJoinConfig;
|
|
58
58
|
get db(): DatabaseInfo;
|
|
59
59
|
get isCircular(): boolean;
|
|
60
|
+
get pathIdentifier(): any;
|
|
60
61
|
hasDesignerIdInIncestors(designerId: string): boolean;
|
|
61
62
|
getChildMatchColumns(): any[];
|
|
62
63
|
getParentMatchColumns(): any[];
|
|
@@ -182,6 +182,11 @@ class PerspectiveTreeNode {
|
|
|
182
182
|
get isCircular() {
|
|
183
183
|
return false;
|
|
184
184
|
}
|
|
185
|
+
get pathIdentifier() {
|
|
186
|
+
if (this.parentNode)
|
|
187
|
+
return `${this.parentNode.pathIdentifier}_${this.codeName}`;
|
|
188
|
+
return this.codeName;
|
|
189
|
+
}
|
|
185
190
|
hasDesignerIdInIncestors(designerId) {
|
|
186
191
|
var _a;
|
|
187
192
|
if (designerId == this.designerId)
|
package/lib/TableGridDisplay.js
CHANGED
|
@@ -77,6 +77,7 @@ class TableGridDisplay extends GridDisplay_1.GridDisplay {
|
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
addReferenceToSelect(select, parentAlias, column) {
|
|
80
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
80
81
|
const childAlias = `${column.uniqueName}_ref`;
|
|
81
82
|
if ((select.from.relations || []).find(x => x.alias == childAlias))
|
|
82
83
|
return;
|
|
@@ -99,7 +100,7 @@ class TableGridDisplay extends GridDisplay_1.GridDisplay {
|
|
|
99
100
|
},
|
|
100
101
|
right: {
|
|
101
102
|
exprType: 'column',
|
|
102
|
-
columnName: table.primaryKey.columns[0].columnName,
|
|
103
|
+
columnName: (_d = (_c = (_b = (_a = column.foreignKey) === null || _a === void 0 ? void 0 : _a.columns) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.refColumnName) !== null && _d !== void 0 ? _d : (_g = (_f = (_e = table.primaryKey) === null || _e === void 0 ? void 0 : _e.columns) === null || _f === void 0 ? void 0 : _f[0]) === null || _g === void 0 ? void 0 : _g.columnName,
|
|
103
104
|
source: { name: table, alias: childAlias },
|
|
104
105
|
},
|
|
105
106
|
},
|
|
@@ -200,7 +201,9 @@ class TableGridDisplay extends GridDisplay_1.GridDisplay {
|
|
|
200
201
|
table.foreignKeys.find(fk => fk.columns.length == 1 && fk.columns[0].columnName == col.columnName), isForeignKeyUnique: false });
|
|
201
202
|
if (res.foreignKey) {
|
|
202
203
|
const refTableInfo = this.dbinfo.tables.find(x => x.schemaName == res.foreignKey.refSchemaName && x.pureName == res.foreignKey.refTableName);
|
|
203
|
-
if (refTableInfo &&
|
|
204
|
+
if (refTableInfo &&
|
|
205
|
+
res.foreignKey.columns.length == 1 &&
|
|
206
|
+
(0, dbgate_tools_1.isTableColumnUnique)(refTableInfo, res.foreignKey.columns[0].refColumnName)) {
|
|
204
207
|
res.isForeignKeyUnique = true;
|
|
205
208
|
}
|
|
206
209
|
}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "6.1
|
|
2
|
+
"version": "6.2.1",
|
|
3
3
|
"name": "dbgate-datalib",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"typings": "lib/index.d.ts",
|
|
@@ -13,13 +13,13 @@
|
|
|
13
13
|
"lib"
|
|
14
14
|
],
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"dbgate-sqltree": "^6.1
|
|
17
|
-
"dbgate-tools": "^6.1
|
|
18
|
-
"dbgate-filterparser": "^6.1
|
|
16
|
+
"dbgate-sqltree": "^6.2.1",
|
|
17
|
+
"dbgate-tools": "^6.2.1",
|
|
18
|
+
"dbgate-filterparser": "^6.2.1",
|
|
19
19
|
"uuid": "^3.4.0"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
|
-
"dbgate-types": "^6.1
|
|
22
|
+
"dbgate-types": "^6.2.1",
|
|
23
23
|
"@types/node": "^13.7.0",
|
|
24
24
|
"jest": "^28.1.3",
|
|
25
25
|
"ts-jest": "^28.0.7",
|