backend-plus 1.19.5 → 2.0.0-beta.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/README.md CHANGED
@@ -2,15 +2,15 @@
2
2
 
3
3
  # backend-plus
4
4
 
5
- Backend for typed-controls
5
+ Backend for the anti Pareto rule.
6
6
 
7
7
 
8
8
  ![stable](https://img.shields.io/badge/stability-stable-blue.svg)
9
- [![npm-version](https://img.shields.io/npm/v/backend-plus.svg)](https://npmjs.org/package/backend-plus)
10
- [![downloads](https://img.shields.io/npm/dm/backend-plus.svg)](https://npmjs.org/package/backend-plus)
11
- [![build](https://img.shields.io/travis/codenautas/backend-plus/master.svg)](https://travis-ci.org/codenautas/backend-plus)
12
- [![coverage](https://img.shields.io/coveralls/codenautas/backend-plus/master.svg)](https://coveralls.io/r/codenautas/backend-plus)
13
- [![dependencies](https://img.shields.io/david/codenautas/backend-plus.svg)](https://david-dm.org/codenautas/backend-plus)
9
+ [![npm-version](https://img.shields.io/npm/v/backend-star.svg)](https://npmjs.org/package/backend-star)
10
+ [![downloads](https://img.shields.io/npm/dm/backend-star.svg)](https://npmjs.org/package/backend-star)
11
+ [![build](https://img.shields.io/travis/codenautas/backend-star/master.svg)](https://travis-ci.org/codenautas/backend-star)
12
+ [![coverage](https://img.shields.io/coveralls/codenautas/backend-star/master.svg)](https://coveralls.io/r/codenautas/backend-star)
13
+ [![dependencies](https://img.shields.io/david/codenautas/backend-star.svg)](https://david-dm.org/codenautas/backend-star)
14
14
 
15
15
 
16
16
  language: ![English](https://raw.githubusercontent.com/codenautas/multilang/master/img/lang-en.png)
@@ -60,6 +60,7 @@ menuContent | A | | menu | menu content
60
60
  table | T | `name` | table | table name
61
61
  label | T | `name` | | if you don't want to use default value to display in menu
62
62
  selectedByDefault | B | | | is the selected by default option
63
+ autoproced | B | `false` | proc | if yo want to execute the procedure without clicking the proced button
63
64
 
64
65
  Integrating example:
65
66
 
@@ -338,4 +338,8 @@ th.th-agg
338
338
  outline 1px solid #997
339
339
  left 0
340
340
 
341
- /* background-clip: padding-box; outline:2px solid black; */
341
+ /* background-clip: padding-box; outline:2px solid black; */
342
+
343
+ .my-grid > tbody > [not-here=yes] > td
344
+ background-color #ccc
345
+ color #888
@@ -647,14 +647,17 @@ myOwn.tableGrid = function tableGrid(tableName, mainElement, opts){
647
647
  })
648
648
  if(!thereIsANewRecord){
649
649
  var i = 0;
650
- while (i < grid.depots.length) {
651
- var depot = grid.depots[i];
652
- if (depot.tick != tick) {
653
- depot.manager.displayAsDeleted(depot);
654
- } else {
655
- i++;
650
+ var depotsToDelete = grid.depots.filter(depot => depot.tick != tick);
651
+ var depot;
652
+ if (myOwn.config.config['grid-row-retain-moved-or-deleted']) {
653
+ var depotsToRetain = grid.depots.filter(depot => depot.tick == tick);
654
+ for (depot of depotsToRetain) {
655
+ if (depot.tr.getAttribute('not-here')) depot.tr.removeAttribute('not-here')
656
656
  }
657
657
  }
658
+ while (depot = depotsToDelete.pop()) {
659
+ depot.manager.displayAsDeleted(depot, 'unknown');
660
+ }
658
661
  }
659
662
  })
660
663
  }
@@ -1014,7 +1017,7 @@ myOwn.DataColumnGrid.prototype.td = function td(depot, iColumn, tr, saveRow){
1014
1017
  var grid = this.grid;
1015
1018
  var fieldDef = this.fieldDef;
1016
1019
  var forInsert = false; // TODO: Verificar que esto está en desuso
1017
- var enabledInput=depot.allow.update !== false && grid.def.allow.update && !grid.connector.fixedField[fieldDef.name] && (forInsert?fieldDef.allow.insert:fieldDef.allow.update);
1020
+ var enabledInput=depot.allow.update !== false && grid.def.allow.update /* && !grid.connector.fixedField[fieldDef.name] */ && (forInsert?fieldDef.allow.insert:fieldDef.allow.update);
1018
1021
  var directInput=true;
1019
1022
  var control;
1020
1023
  var td;
@@ -2261,7 +2264,7 @@ myOwn.TableGrid.prototype.displayGrid = function displayGrid(){
2261
2264
  return fieldDef.visible;
2262
2265
  }).forEach(function(fieldDef){
2263
2266
  var td = depot.rowControls[fieldDef.name];
2264
- var editable=depot.allow.update !== false && grid.connector.def.allow.update && !grid.connector.fixedField[fieldDef.name] && (forInsert?fieldDef.allow.insert:fieldDef.allow.update && grid.connector.def.field[fieldDef.name].allow.update);
2267
+ var editable=depot.allow.update !== false && grid.connector.def.allow.update /* && !grid.connector.fixedField[fieldDef.name]*/ && (forInsert?fieldDef.allow.insert:fieldDef.allow.update && grid.connector.def.field[fieldDef.name].allow.update);
2265
2268
  td.disable(!editable);
2266
2269
  if(fieldDef.clientSide){
2267
2270
  if(!td.clientSidePrepared){
@@ -2696,39 +2699,43 @@ myOwn.TableGrid.prototype.displayGrid = function displayGrid(){
2696
2699
  grid.displayBody();
2697
2700
  };
2698
2701
 
2699
- myOwn.TableGrid.prototype.displayAsDeleted = function displayAsDeleted(depot){
2702
+ myOwn.TableGrid.prototype.displayAsDeleted = function displayAsDeleted(depot, mode){
2700
2703
  var grid = this;
2701
- var position = Math.min(grid.depots.length,Math.max(0,depot.tr.sectionRowIndex));
2702
- if(grid.depots[position] !== depot){
2703
- position = grid.depots.indexOf(depot);
2704
- }
2705
- if(position>=0){
2706
- grid.depots.splice(position,1);
2707
- }
2708
- if(grid.vertical){
2709
- var compareColNumberFun = function compareColNumberFun(a, b) {
2710
- var colNumberA = a.colNumber;
2711
- var colNumberB = b.colNumber;
2712
- return(colNumberA > colNumberB)?1:((colNumberA < colNumberB)?-1:0)
2713
- }
2714
- var i = 0;
2715
- Array.prototype.forEach.call(grid.dom.table.rows,function(tr){
2716
- if(i < grid.dom.table.rows.length-1 && tr.childNodes[depot.colNumber]){
2717
- depot.my.fade(tr.childNodes[depot.colNumber]);
2718
- }
2719
- i++;
2720
- });
2721
- var depots = grid.depots.sort(compareColNumberFun);
2722
- for(var j = depot.colNumber; j <= depots.length; j++){
2723
- depots[j-1].colNumber = j;
2704
+ if (mode == 'unknown' && myOwn.config.config['grid-row-retain-moved-or-deleted']) {
2705
+ depot.tr.setAttribute('not-here', 'yes');
2706
+ } else {
2707
+ var position = Math.min(grid.depots.length,Math.max(0,depot.tr.sectionRowIndex));
2708
+ if(grid.depots[position] !== depot){
2709
+ position = grid.depots.indexOf(depot);
2724
2710
  }
2725
- }else{
2726
- depot.my.fade(depot.tr);
2727
- for(var detailControl in depot.detailControls){
2728
- if(depot.detailControls[detailControl].tr){
2729
- depot.my.fade(depot.detailControls[detailControl].tr);
2711
+ if(position>=0){
2712
+ grid.depots.splice(position,1);
2713
+ }
2714
+ if(grid.vertical){
2715
+ var compareColNumberFun = function compareColNumberFun(a, b) {
2716
+ var colNumberA = a.colNumber;
2717
+ var colNumberB = b.colNumber;
2718
+ return(colNumberA > colNumberB)?1:((colNumberA < colNumberB)?-1:0)
2730
2719
  }
2731
- };
2720
+ var i = 0;
2721
+ Array.prototype.forEach.call(grid.dom.table.rows,function(tr){
2722
+ if(i < grid.dom.table.rows.length-1 && tr.childNodes[depot.colNumber]){
2723
+ depot.my.fade(tr.childNodes[depot.colNumber]);
2724
+ }
2725
+ i++;
2726
+ });
2727
+ var depots = grid.depots.sort(compareColNumberFun);
2728
+ for(var j = depot.colNumber; j <= depots.length; j++){
2729
+ depots[j-1].colNumber = j;
2730
+ }
2731
+ }else{
2732
+ depot.my.fade(depot.tr);
2733
+ for(var detailControl in depot.detailControls){
2734
+ if(depot.detailControls[detailControl].tr){
2735
+ depot.my.fade(depot.detailControls[detailControl].tr);
2736
+ }
2737
+ };
2738
+ }
2732
2739
  }
2733
2740
  grid.updateTotals(grid.depots.length?1:0, grid.depots.length);
2734
2741
  };
@@ -2757,7 +2764,7 @@ myOwn.tableAction={
2757
2764
  return depot.my.confirmDelete(depot, opts).then(function(result){
2758
2765
  if(result){
2759
2766
  return depot.connector.deleteRecord(depot, changing({reject:false},opts)).then(function(){
2760
- depot.manager.displayAsDeleted(depot);
2767
+ depot.manager.displayAsDeleted(depot, 'deleted');
2761
2768
  depot.manager.refreshAggregates();
2762
2769
  }).catch(depot.my.alertError);
2763
2770
  }
@@ -318,7 +318,7 @@ export type TableDefinition = EditableDbDefinition & {
318
318
  specialValidator?:string
319
319
  saveAfter?:boolean
320
320
  selfRefresh?:boolean
321
- filterColumns?:{column:string, operatior:string, value:any}[]
321
+ filterColumns?:{column:string, operator:string, value:any}[]
322
322
  }
323
323
  export type OtherTableDefs = TableDefinition['sql']['otherTableDefs']
324
324
  export interface DetailTable { table?: string, fields: FieldsForConnectDetailTable, abr: string, label?: string, refreshParent?:boolean, refreshFromParent?:boolean, wScreen?:string, condition?:string }
@@ -158,6 +158,8 @@ AppBackend.prototype.configStaticConfig = function configStaticConfig(){
158
158
  on-demand: false
159
159
  server:
160
160
  base-url: ''
161
+ bitacoraSchema: his
162
+ bitacoraTableName: bitacora
161
163
  skins:
162
164
  "":
163
165
  local-path: for-client
@@ -953,7 +955,7 @@ AppBackend.prototype.start = function start(opts){
953
955
  function(req, username, password, done) {
954
956
  var client;
955
957
  if(!be.config.login["preserve-case"]){
956
- username = username.toLowerCase();
958
+ username = username.toLowerCase().trim();
957
959
  }
958
960
  be.getDbClient(req).then(function(cli){
959
961
  client = cli;
@@ -981,11 +983,27 @@ AppBackend.prototype.start = function start(opts){
981
983
  if(be.config.login["double-dragon"]){
982
984
  be.DoubleDragon.dbParams[username] = changing(be.config.db, {user:username, password});
983
985
  }
984
- done(null, data.row);
986
+ return data.row;
985
987
  }
986
988
  }else{
987
989
  done(null,false,{message:be.messages.unlogged.login.userOrPassFail});
988
990
  }
991
+ }).then(async function(userInfo){
992
+ if (!be.config.login.skipBitacora) {
993
+ var context = be.getContext(req);
994
+ var sessionInfo = client.query(be.generateInsertSQL(be.config.server.bitacoraSchema, be.config.server.bitacoraTableName,{
995
+ procedure_name: '@login',
996
+ parameters: {
997
+ user:username,
998
+ machine_id: context.machineId,
999
+ navigator: context.navigator,
1000
+ init_date: bestGlobals.datetime.now(),
1001
+ }
1002
+ })).fetchUniqueValue();
1003
+ userInfo.bitacoraId = sessionInfo.value;
1004
+ }
1005
+ done(null, userInfo);
1006
+ return userInfo;
989
1007
  }).then(function(){
990
1008
  client.done();
991
1009
  }).catch(function(err){
@@ -1095,7 +1113,7 @@ AppBackend.prototype.start = function start(opts){
1095
1113
  console.log("Resolved modules from: " + process.cwd())
1096
1114
  likeAr(resolved_modules_log).forEach((c,l)=>console.log(` ${c} ${l}`));
1097
1115
  }
1098
- return be.sendMail({
1116
+ return be.sendMail({
1099
1117
  to: be.config.mailer?.supervise?.to,
1100
1118
  subject: `npm start ${be.config["client-setup"].title || packagejson.name} ok ✔️`,
1101
1119
  text:`Inicio del servicio: ${new Date().toJSON()}
@@ -1193,7 +1211,7 @@ AppBackend.prototype.checkDatabaseStructure = async function checkDatabaseStruct
1193
1211
  from ${be.config.login.schema?be.db.quoteIdent(be.config.login.schema)+'.':''}${be.config.login.table} limit 1`).fetchOneRowIfExists();
1194
1212
  }catch(err){
1195
1213
  var mensaje = `
1196
- --------quizas falten los campos en la tabla usuarios:
1214
+ -------- quizas falten los campos en la tabla usuarios:
1197
1215
  ${be.config.login.forget.mailFields.map(name=>`
1198
1216
  alter table ${be.config.login.schema?be.db.quoteIdent(be.config.login.schema)+'.':''}${be.config.login.table} add column ${name} text;`).join('')}
1199
1217
  `;
@@ -1203,6 +1221,21 @@ AppBackend.prototype.checkDatabaseStructure = async function checkDatabaseStruct
1203
1221
  }
1204
1222
  }
1205
1223
  }
1224
+ var bitacoraId = await client.query(`SELECT data_type
1225
+ FROM information_schema.columns
1226
+ WHERE /*table_schema = 'his' AND*/ table_name = 'bitacora' AND column_name = 'id'
1227
+ `).fetchOneRowIfExists();
1228
+ if (bitacoraId.row?.data_type != 'bigint') {
1229
+ var message = `
1230
+ ------- hay que cambiar la bitacora de lugar (a his) y agrandar el id (a bigint)
1231
+ alter table ${be.config.db.schema}.bitacora set schema his;
1232
+ alter table ${be.config.db.schema}.tokens set schema his;
1233
+ alter table his.bitacora alter column id type bigint;
1234
+ grant usage on schema his to ${be.config.db.user};
1235
+ grant select, insert, update on his.bitacora to ${be.config.db.user};
1236
+ `;
1237
+ throw new Error(message);
1238
+ }
1206
1239
  };
1207
1240
 
1208
1241
  AppBackend.prototype.postConfig = function postConfig(){
@@ -1238,6 +1271,36 @@ AppBackend.prototype.inTransactionProcedureContext = function inTransactionProce
1238
1271
  });
1239
1272
  }
1240
1273
 
1274
+ AppBackend.prototype.generateInsertSQL = function generateInsertSQL(schemaName, tableName, insertElement){
1275
+ var {db} = this;
1276
+ var cleanKeys = [];
1277
+ var cleanValues = [];
1278
+ for (var key in insertElement) {
1279
+ cleanKeys.push(db.quoteIdent(key));
1280
+ cleanValues.push(db.quoteNullable(insertElement[key]));
1281
+ }
1282
+ var sql = `INSERT INTO ${db.quoteIdent(schemaName)}.${db.quoteIdent(tableName)}
1283
+ (${cleanKeys.join(',')}) VALUES (${cleanValues.join(',')}) returning id`;
1284
+ return sql;
1285
+ }
1286
+
1287
+ AppBackend.prototype.updateUpdateSQL = function updateUpdateSQL(schemaName, tableName, updateElement, updateConditions){
1288
+ var {db} = this;
1289
+ var setPairs = [];
1290
+ for (var key in updateElement) {
1291
+ setPairs.push(db.quoteIdent(key) + " = " + db.quoteNullable(updateElement[key]));
1292
+ }
1293
+ var filterPairs = [];
1294
+ for (var key in updateConditions) {
1295
+ filterPairs.push(be.db.quoteIdent(key) + " = " + be.db.quoteLiteral(updateConditions[key]));
1296
+ };
1297
+ var sql = `UPDATE ${db.quoteIdent(schemaName)}.${db.quoteIdent(tableName)}
1298
+ SET ${setPairs.join(',')}
1299
+ WHERE ${filterPairs.join(' AND ')}`;
1300
+ return sql;
1301
+ }
1302
+
1303
+
1241
1304
  /** @param {boolean} forUnlogged */
1242
1305
  AppBackend.prototype.addProcedureServices = function addProcedureServices(forUnlogged){
1243
1306
  var be = this;
@@ -1295,7 +1358,8 @@ AppBackend.prototype.addProcedureServices = function addProcedureServices(forUnl
1295
1358
  * @param {import('express').NextFunction} next
1296
1359
  */
1297
1360
  async function(req, res, next){
1298
- const BITACORA_TABLENAME = be.config.server.bitacoraTableName || 'bitacora';
1361
+ const BITACORA_SCHEMA = be.config.server.bitacoraSchema;
1362
+ const BITACORA_TABLENAME = be.config.server.bitacoraTableName;
1299
1363
  var getDatetimeString = function getDatetimeString(){
1300
1364
  return datetime.now().toPlainString()
1301
1365
  }
@@ -1332,43 +1396,10 @@ AppBackend.prototype.addProcedureServices = function addProcedureServices(forUnl
1332
1396
  });
1333
1397
  return params;
1334
1398
  }
1335
- var generateInsertSQL = function(insertElement){
1336
- var cleanKeys = [];
1337
- var cleanValues = [];
1338
- for (var key in insertElement) {
1339
- cleanKeys.push(be.db.quoteIdent(key));
1340
- // if(typeof(insertElement[key]) !== 'string'){ //TODO: revisar si hace falta ahora que ponesmo quoteLiteral
1341
- // insertElement[key] = insertElement[key].toString();
1342
- // }
1343
- cleanValues.push(be.db.quoteLiteral(insertElement[key] || "null"));
1344
- }
1345
- var sql = "INSERT INTO " + be.db.quoteIdent(BITACORA_TABLENAME) + " ("+cleanKeys.join(',')+") VALUES ("+ cleanValues.join(',')+") returning id";
1346
- return sql;
1347
- }
1348
- var updateUpdateSQL = function(updateElement, tableName, updateConditions){
1349
- var keyValues = [];
1350
- for (var key in updateElement) {
1351
- // if(typeof(updateElement[key]) !== 'string'){ //TODO: revisar si hace falta ahora que ponesmo quoteLiteral
1352
- // updateElement[key] = updateElement[key].toString();
1353
- // }
1354
- keyValues.push(be.db.quoteIdent(key) + " = " + be.db.quoteLiteral(updateElement[key]));
1355
- }
1356
- var sql = "UPDATE " + be.db.quoteIdent(tableName) + " SET " + keyValues.join(',') + " WHERE ";
1357
- var keyValues = [];
1358
- for (var key in updateConditions) {
1359
- // if(typeof(updateConditions[key]) !== 'string'){ //TODO: revisar si hace falta ahora que ponesmo quoteLiteral
1360
- // updateConditions[key] = updateConditions[key].toString();
1361
- // }
1362
- keyValues.push(be.db.quoteIdent(key) + " = " + be.db.quoteLiteral(updateConditions[key]));
1363
- };
1364
- sql = sql + keyValues.join(' AND ');
1365
- return sql;
1366
- }
1367
1399
  var processBitacora = async function(hasError, status){
1368
1400
  var params = getParams();
1369
1401
  var defInsertBitacoraElement = {
1370
1402
  procedure_name : procedureDef.action,
1371
- parameters_definition: JSON.stringify(procedureDef.parameters),
1372
1403
  parameters: JSON.stringify(params),
1373
1404
  username: context.username,
1374
1405
  machine_id: context.machineId,
@@ -1386,18 +1417,18 @@ AppBackend.prototype.addProcedureServices = function addProcedureServices(forUnl
1386
1417
  if(lastBitacoraInsertedId){
1387
1418
  await be.inTransaction(req, async function(client){
1388
1419
  var updateConditions = { id: lastBitacoraInsertedId };
1389
- await client.query(updateUpdateSQL(getFinalStatusBitacoraElement(), BITACORA_TABLENAME, updateConditions)).execute();
1420
+ await client.query(be.updateUpdateSQL(BITACORA_SCHEMA, BITACORA_TABLENAME, getFinalStatusBitacoraElement(), updateConditions)).execute();
1390
1421
  });
1391
1422
  }else{
1392
1423
  await be.inTransaction(req, async function(client){
1393
- var result = await client.query(generateInsertSQL(defInsertBitacoraElement)).fetchUniqueRow();
1424
+ var result = await client.query(be.generateInsertSQL(BITACORA_SCHEMA, BITACORA_TABLENAME, defInsertBitacoraElement)).fetchUniqueRow();
1394
1425
  lastBitacoraInsertedId = result.row.id;
1395
1426
  });
1396
1427
  }
1397
1428
  }else if(hasError && procedureDef.bitacora.error){
1398
1429
  await be.inTransaction(req,async function(client){
1399
1430
  var insertElement = changing(defInsertBitacoraElement, getFinalStatusBitacoraElement());
1400
- await client.query(generateInsertSQL(insertElement)).execute();
1431
+ await client.query(be.generateInsertSQL(BITACORA_SCHEMA, BITACORA_TABLENAME, insertElement)).execute();
1401
1432
  });
1402
1433
  }
1403
1434
  //tengo configurada otra tabla para guardar el resultado de la bitacora y tengo la pk de esa tabla
@@ -1419,7 +1450,7 @@ AppBackend.prototype.addProcedureServices = function addProcedureServices(forUnl
1419
1450
  targetTableUpdateFieldsCondition.forEach(function(field){
1420
1451
  updateConditions[field] = params[field];
1421
1452
  });
1422
- await client.query(updateUpdateSQL(updateElement, procedureDef.bitacora.targetTable, updateConditions)).execute();
1453
+ await client.query(be.updateUpdateSQL(BITACORA_SCHEMA, procedureDef.bitacora.targetTable, updateElement, updateConditions)).execute();
1423
1454
  })
1424
1455
  }
1425
1456
  }
@@ -1,14 +1,14 @@
1
1
  "use strict";
2
2
 
3
3
  module.exports = function(context){
4
- const BITACORA_TABLENAME = context.be.config.server.bitacoraTableName || 'bitacora';
4
+ const BITACORA_TABLENAME = context.be.config.server.bitacoraTableName;
5
5
  return context.be.tableDefAdapt({
6
6
  name:'bitacora',
7
7
  title:'Bitacora',
8
8
  tableName: BITACORA_TABLENAME,
9
9
  editable:context.forDump,
10
10
  fields:[
11
- {name:'id' , typeName:'integer' , nullable:false, sequence:{name: 'secuencia_bitacora', firstValue: 1}},
11
+ {name:'id' , typeName:'bigint' , nullable:false, sequence:{name: 'secuencia_bitacora', firstValue: 1}},
12
12
  {name:'procedure_name' , typeName:'text' , nullable:false },
13
13
  {name:'parameters_definition' , typeName:'text' , nullable:false },
14
14
  {name:'parameters' , typeName:'text' , nullable:false },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "backend-plus",
3
- "description": "Backend for typed controls",
4
- "version": "1.19.5",
3
+ "description": "Backend for the anti Pareto rule",
4
+ "version": "2.0.0-beta.1",
5
5
  "author": "Codenautas <codenautas@googlegroups.com>",
6
6
  "license": "MIT",
7
7
  "repository": "codenautas/backend-plus",
@@ -46,7 +46,7 @@
46
46
  "fs-extra": "^11.1.1",
47
47
  "js-to-html": "^1.3.2",
48
48
  "js-yaml": "^4.1.0",
49
- "json4all": "^1.2.1",
49
+ "json4all": "^1.3.0-beta.1",
50
50
  "lazy-some": "^0.1.0",
51
51
  "like-ar": "^0.3.9",
52
52
  "login-plus": "^1.7.1",
@@ -81,7 +81,7 @@
81
81
  "@types/js-yaml": "^4.0.5",
82
82
  "@types/mocha": "^10.0.1",
83
83
  "@types/multiparty": "~0.0.33",
84
- "@types/node": "^20.3.0",
84
+ "@types/node": "^20.3.3",
85
85
  "@types/nodemailer": "^6.4.8",
86
86
  "@types/numeral": "~2.0.2",
87
87
  "@types/session-file-store": "^1.2.2",
@@ -98,11 +98,11 @@
98
98
  "kill-9": "~0.4.3",
99
99
  "mocha": "^10.2.0",
100
100
  "nyc": "^15.1.0",
101
- "puppeteer": "^20.5.0",
102
- "sinon": "^15.1.0",
101
+ "puppeteer": "^20.7.4",
102
+ "sinon": "^15.2.0",
103
103
  "supertest": "^6.3.3",
104
104
  "types.d.ts": "~0.6.15",
105
- "typescript": "^5.1.3",
105
+ "typescript": "^5.1.6",
106
106
  "why-is-node-running": "^2.2.2"
107
107
  },
108
108
  "engines": {