backend-plus 2.0.0-rc.1 → 2.0.0-rc.10

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
@@ -6,11 +6,11 @@ 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-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)
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)
14
14
 
15
15
 
16
16
  language: ![English](https://raw.githubusercontent.com/codenautas/multilang/master/img/lang-en.png)
@@ -205,7 +205,7 @@ entry | usage
205
205
  -----------------------------|---------------
206
206
  server |
207
207
  .port | port where is listening
208
- .base-rul | base url added to domain name
208
+ .base-url | base url added to domain name
209
209
  .module-store |
210
210
  install | (see Spanish)
211
211
  .dump | (see Spanish)
@@ -152,7 +152,7 @@ myOwn.wScreens.procAux = {
152
152
  button.disabled=false;
153
153
  divProgressOutside.style.opacity=0.33;
154
154
  toggleProgress.disabled=false;
155
- labelProgress.textContent=resultOk?my.messages.completed:'error';
155
+ labelProgress.textContent=typeof resultOk == "string" ? resultOk : resultOk !== false ? my.messages.completed : 'error';
156
156
  }).catch(function(err){
157
157
  my.log(err);
158
158
  divProgress.textContent=err.message;
@@ -690,11 +690,18 @@ myOwn.tableGrid = function tableGrid(tableName, mainElement, opts){
690
690
  if (myOwn.config.config['grid-row-retain-moved-or-deleted'] && !force) {
691
691
  var depotsToRetain = grid.depots.filter(depot => depot.tick == tick);
692
692
  for (depot of depotsToRetain) {
693
+ depot['$refreshed'] = false
693
694
  if (depot.tr && depot.tr.getAttribute('not-here')) depot.tr.removeAttribute('not-here')
694
695
  }
695
696
  }
696
697
  while (depot = depotsToDelete.pop()) {
697
698
  depot.manager.displayAsDeleted(depot, force ? 'change-ff' : 'unknown');
699
+ if (myOwn.config.config['grid-row-retain-moved-or-deleted']) {
700
+ if(!depot['$refreshed']){
701
+ grid.retrieveRowAndRefresh(depot,{retrieveIgnoringWhere:true})
702
+ depot['$refreshed'] = true
703
+ }
704
+ }
698
705
  }
699
706
  }
700
707
  })
@@ -1615,7 +1622,7 @@ myOwn.dialogDownload = function dialogDownload(grid){
1615
1622
  }else{
1616
1623
  separator='|';
1617
1624
  var trans={
1618
- '|':'\\|',
1625
+ '|':'\\x7C',
1619
1626
  '\\':'\\\\',
1620
1627
  '\r':'\\r',
1621
1628
  '\n':'\\n',
@@ -2385,7 +2392,8 @@ myOwn.TableGrid.prototype.displayGrid = function displayGrid(){
2385
2392
  fixedFields:grid.def.primaryKey.map(function(fieldName, i){
2386
2393
  return {fieldName:fieldName, value:depot.primaryKeyValues[i]};
2387
2394
  }),
2388
- pick:grid.def.pick
2395
+ pick:grid.def.pick,
2396
+ retrieveIgnoringWhere: opts?opts.retrieveIgnoringWhere:false
2389
2397
  }).then(function(result){
2390
2398
  grid.depotRefresh(depot,{updatedRow:result[0], sendedForUpdate:{}}, opts);
2391
2399
  })
@@ -0,0 +1,6 @@
1
+ create or replace function get_app_user() returns text
2
+ stable language sql
3
+ as
4
+ $sql$
5
+ select split_part(current_setting('application_name'),' ',1);
6
+ $sql$;
@@ -35,7 +35,7 @@ export type UploadedFileInfo={
35
35
 
36
36
  }
37
37
  export type CoreFunction = ((context: ProcedureContext, parameters: CoreFunctionParameters) => Promise<any>)
38
- | ((context: ProcedureContext, parameters: CoreFunctionParameters, files?:UploadedFileInfo[]) => Promise<any>);
38
+ | ((context: ProcedureContext, parameters: CoreFunctionParameters, files?:UploadedFileInfo[]) => Promise<any>);
39
39
 
40
40
  export interface ProcedureDef {
41
41
  action: string
@@ -252,6 +252,7 @@ export type Constraint = {constraintType:string, consName?:string} & (
252
252
  {constraintType:'unique', fields:string[], where?:string} |
253
253
  {constraintType:'check', expr?:string}
254
254
  )
255
+ export type OtherTableDefs = Record<string,Partial<TableDefinition & {prefilledField:Record<string,any>}>>
255
256
  export type TableDefinition = EditableDbDefinition & {
256
257
  name:string
257
258
  elementName?:string
@@ -285,15 +286,15 @@ export type TableDefinition = EditableDbDefinition & {
285
286
  viewBody?:string
286
287
  insertIfNotUpdate?:boolean
287
288
  policies?:{
288
- all ?:{using?:string, check?:string}
289
- select?:{using?:string}
290
- insert?:{ check?:string}
291
- update?:{using?:string, check?:string}
292
- delete?:{using?:string}
289
+ all ?:{name?:string, using?:string, check?:string}
290
+ select?:{name?:string, using?:string}
291
+ insert?:{name?:string, check?:string}
292
+ update?:{name?:string, using?:string, check?:string}
293
+ delete?:{name?:string, using?:string}
293
294
  }
294
295
  join?:string
295
296
  constraintsDeferred?:boolean
296
- otherTableDefs?:Record<string,Partial<TableDefinition & {prefilledField:Record<string,any>}>>
297
+ otherTableDefs?:OtherTableDefs
297
298
  }
298
299
  foreignKeys?:ForeignKey[]
299
300
  softForeignKeys?:ForeignKey[]
@@ -322,7 +323,6 @@ export type TableDefinition = EditableDbDefinition & {
322
323
  filterColumns?:{column:string, operator:string, value:any}[],
323
324
  gridAlias?:string /* front-end css my-table = gridAlias */
324
325
  }
325
- export type OtherTableDefs = TableDefinition['sql']['otherTableDefs']
326
326
  export interface DetailTable { table?: string, fields: FieldsForConnectDetailTable, abr: string, label?: string, refreshParent?:boolean, refreshFromParent?:boolean, wScreen?:string, condition?:string }
327
327
  export type TableDefinitionFunction = (context: ContextForDump, opts?:any) => TableDefinition;
328
328
  export type TableItemDef=string|{name:string, path?:string, tableGenerator?:(context:TableContext)=>TableDefinition}
@@ -54,6 +54,7 @@ var bestGlobals = require('best-globals');
54
54
  var coalesce = bestGlobals.coalesce;
55
55
  var changing = bestGlobals.changing;
56
56
  var datetime = bestGlobals.datetime;
57
+ var splitRawRowIntoRow = bestGlobals.splitRawRowIntoRow;
57
58
  const escapeRegExp = bestGlobals.escapeRegExp;
58
59
  var isLowerIdent = bestGlobals.isLowerIdent;
59
60
 
@@ -456,7 +457,7 @@ AppBackend.prototype.setStaticConfig = function setStaticConfig(defConfigYamlStr
456
457
 
457
458
  AppBackend.prototype.configList = function configList(){
458
459
  var list=[this.staticConfig];
459
- if(!this.staticConfig["client-setup"].title && fs.existsSync(this.rootPath+'/def-config.yaml')){
460
+ if(!this.staticConfig["client-setup"]?.title && fs.existsSync(this.rootPath+'/def-config.yaml')){
460
461
  console.log('DEPRECATED!!!!!!')
461
462
  console.error('ERROR el def-config hay que ponerlo dentro de staticConfig');
462
463
  console.log('DEPRECATED!!!!!!')
@@ -466,7 +467,7 @@ AppBackend.prototype.configList = function configList(){
466
467
  list.push(this.rootPath+'/def-config.yaml')
467
468
  };
468
469
  list.push(this.rootPath+'/local-config');
469
- list.push(process.env.BACKEND_PLUS_LOCAL_CONFIG||{});
470
+ list.push(process.env.BACKEND_PLUS_LOCAL_CONFIG?.trim()||{});
470
471
  return list;
471
472
  };
472
473
 
@@ -704,7 +705,7 @@ AppBackend.prototype.start = function start(opts){
704
705
  throw new Error("backend-plus: Motor not recongnized: "+be.config.db.motor);
705
706
  }
706
707
  be.db = pg;
707
- be.dbUserNameExpr="split_part(current_setting('application_name'),' ',1)";
708
+ be.dbUserNameExpr="get_app_user()";
708
709
  be.dbUserRolExpr=`(select ${be.db.quoteIdent(be.config.login.rolFieldName)}
709
710
  from ${be.config.login.schema?be.db.quoteIdent(be.config.login.schema)+'.':''}${be.db.quoteIdent(be.config.login.table)}
710
711
  where ${be.db.quoteIdent(be.config.login.userFieldName)} = ${be.dbUserNameExpr})`
@@ -760,6 +761,7 @@ AppBackend.prototype.start = function start(opts){
760
761
  pg.log.inFileName = 'last-pg-error-local.sql'
761
762
  pg.logLastError.inFileName = 'last-pg-error-local.sql'
762
763
  }
764
+ be.config.db.search_path = be.config.db.search_path ?? [be.config.db.schema, 'public'];
763
765
  be.getDbClient = function getDbClient(req){
764
766
  var paramsDb = be.DoubleDragon?.dbParams?.[req?.user?.[be.config.login.userFieldName]] ?? be.config.db;
765
767
  return pg.connect(paramsDb).then(function(client){
@@ -771,7 +773,7 @@ AppBackend.prototype.start = function start(opts){
771
773
  return client.query(
772
774
  "SET application_name = "+be.db.quoteLiteral(dbAppName)
773
775
  ).execute().then(function(){
774
- var search_path = be.config.db.search_path || [be.config.db.schema, 'public'];
776
+ var search_path = be.config.db.search_path;
775
777
  if(search_path.length>0){
776
778
  return client.query("set SEARCH_PATH TO "+be.db.quoteIdentList(search_path)).execute().then(function(){
777
779
  return client;
@@ -1130,7 +1132,7 @@ AppBackend.prototype.start = function start(opts){
1130
1132
  }
1131
1133
  return be.sendMail({
1132
1134
  to: be.config.mailer?.supervise?.to,
1133
- subject: `npm start ${be.config["client-setup"].title || packagejson.name} ok ✔️`,
1135
+ subject: `npm start ${be.config["client-setup"]?.title || packagejson.name} ok ✔️`,
1134
1136
  text:`Inicio del servicio: ${new Date().toJSON()}
1135
1137
 
1136
1138
  Contexto: ${os.userInfo().username} ${process.cwd()}
@@ -1152,7 +1154,7 @@ AppBackend.prototype.start = function start(opts){
1152
1154
  }
1153
1155
  var mailDeAvisoDeFalla = be.sendMail({
1154
1156
  to: be.config.mailer?.supervise?.to,
1155
- subject: `npm start ${be.config["client-setup"].title || packagejson.name} fallido 🛑`,
1157
+ subject: `npm start ${be.config["client-setup"]?.title || packagejson.name} fallido 🛑`,
1156
1158
  text:`Falla en el inicio del servicio: ${new Date().toJSON()}
1157
1159
 
1158
1160
  Contexto: ${os.userInfo().username} ${process.cwd()}
@@ -1209,13 +1211,14 @@ AppBackend.prototype.checkDatabaseStructure = async function checkDatabaseStruct
1209
1211
  }
1210
1212
  if(be.config.login?.forget){
1211
1213
  try{
1212
- await client.query(`select tokentype, info, due from tokens limit 1`).fetchOneRowIfExists();
1214
+ await client.query(`select tokentype, info, due from his.tokens limit 1`).fetchOneRowIfExists();
1213
1215
  }catch(err){
1214
1216
  var mensaje = `
1215
1217
  --------quizas falten los campos en la tabla tokens:
1216
1218
  alter table tokens add column tokentype text;
1217
1219
  alter table tokens add column info jsonb;
1218
1220
  alter table tokens add column due timestamp;
1221
+ --------quizas falte moverla al esquema his.
1219
1222
  `;
1220
1223
  err.message += mensaje;
1221
1224
  console.log(mensaje)
@@ -1253,6 +1256,21 @@ AppBackend.prototype.checkDatabaseStructure = async function checkDatabaseStruct
1253
1256
  `;
1254
1257
  throw new Error(message);
1255
1258
  }
1259
+ var {rows: sql_routines} = await client.query(`SELECT routine_name, routine_schema, routine_definition
1260
+ FROM information_schema.routines
1261
+ WHERE routine_schema in (${be.config.db.search_path.map(path => be.db.quoteLiteral(path)).join(', ')})
1262
+ `).fetchAll();
1263
+ var sqlRoutines = likeAr.toPlainObject(sql_routines, 'routine_name');
1264
+ var message = ''
1265
+ likeAr(AppBackend.prototype.sql_routines).forEach((routine_name, def) => {
1266
+ if (sqlRoutines[routine_name] && def.dump.includes(sqlRoutines[routine_name].routine_definition)) {
1267
+ message += `
1268
+ ----- hay que crear o actualizar la rutina ${routine_name}:
1269
+ ${dump}
1270
+ `;
1271
+ }
1272
+ })
1273
+ if (message) throw new Error(message);
1256
1274
  };
1257
1275
 
1258
1276
  AppBackend.prototype.postConfig = function postConfig(){
@@ -2181,7 +2199,7 @@ AppBackend.prototype.mainPage = function mainPage(req, offlineMode, opts){
2181
2199
  }
2182
2200
  return html.html(attr,[
2183
2201
  html.head([
2184
- html.title(be.config["client-setup"].title),
2202
+ html.title(be.config["client-setup"]?.title),
2185
2203
  html.meta({charset:"utf-8"}),
2186
2204
  viewportAttrs?html.meta(viewportAttrs):null,
2187
2205
  html.link({href: opts.icons.iconShortcut , rel: "shortcut icon", type: "image/png"}),
@@ -2804,10 +2822,11 @@ AppBackend.prototype.dumpDbSchemaPartial = async function dumpDbSchemaPartial(pa
2804
2822
  lines.push('');
2805
2823
  if(tableDef.sql.policies.enabled){
2806
2824
  policyLines.push(`ALTER TABLE ${cualQuoteTableName} ENABLE ROW LEVEL SECURITY;`);
2807
- ['all', 'select', 'insert', 'update', 'delete'].forEach((command)=>{
2808
- var polcom=tableDef.sql.policies[command];
2809
- if(polcom.using || polcom.check){
2810
- policyLines.push(`CREATE POLICY bp_pol_${command} ON ${cualQuoteTableName} AS PERMISSIVE FOR ${command}`+
2825
+ [null, 'all', 'select', 'insert', 'update', 'delete'].forEach((command)=>{
2826
+ var polcom=tableDef.sql.policies[command] ?? {using: `true`, permissive:true};
2827
+ if(polcom?.using || polcom?.check){
2828
+ policyLines.push(`CREATE POLICY ${be.db.quoteIdent(polcom.name ?? `bp ${command ?? `base`}`)} ON ${cualQuoteTableName} `+
2829
+ `AS ${polcom.permissive ? `PERMISSIVE` : `RESTRICTIVE`} FOR ${command ?? `all`} TO ${be.config.db.user}`+
2811
2830
  (polcom.using? ` USING ( ${polcom.using} )`:'')+
2812
2831
  (polcom.check?` WITH CHECK ( ${polcom.check} )`:'')+';'
2813
2832
  );
@@ -2847,6 +2866,7 @@ AppBackend.prototype.dumpDbSchemaPartial = async function dumpDbSchemaPartial(pa
2847
2866
  allTableData = allTableContent.slice(startIndex, lastIndex);
2848
2867
  } catch(err) {
2849
2868
  if (err.code != 'ENOENT') throw err;
2869
+ //throw err;
2850
2870
  }
2851
2871
  }
2852
2872
  if (allTableData) {
@@ -2919,7 +2939,7 @@ AppBackend.prototype.dumpDbSchemaPartial = async function dumpDbSchemaPartial(pa
2919
2939
  }else{
2920
2940
  var lines=content.split(/\r?\n/)
2921
2941
  .filter(line => !(/^[-| ]*$/.test(line)) )
2922
- .map(line => line.split(/(?<!(?:^|[^\\])(?:\\\\)*\\)\|/).map(item => item.trimRight().replace(/\\(.)/g,(_,l)=>(l=='t'?'\t':l=='r'?'\r':l=='n'?'\n':l=='s'?' ':l))) )
2942
+ .map(line => splitRawRowIntoRow(line))
2923
2943
  .filter(line => line.length>1 || line.length==1 && line[0].trim() );
2924
2944
  if(lines.length>1){
2925
2945
  if(lines[0][0].startsWith('\ufeff')){
@@ -2964,26 +2984,57 @@ AppBackend.prototype.dumpDbSchemaPartial = async function dumpDbSchemaPartial(pa
2964
2984
  console.log('silence "skipping content" messages in "local-config.yaml".install.dump.skip-content=true');
2965
2985
  }
2966
2986
  }
2987
+ let installFolders = be.config.install.dump.folders ?? ['install']
2967
2988
  let texts = await Promise.all(
2968
2989
  ['prepare.sql','pre-adapt.sql','adapt.sql']
2969
2990
  .concat(be.config.install.dump.scripts['prepare'])
2970
2991
  .concat(be.config.install.dump.scripts['post-adapt'])
2971
- .map(function(fileName){
2972
- return fs.readFile(be.rootPath+'/install/'+fileName, {encoding:'UTF8'}).catch(function(err){
2973
- if(err.code!='ENOENT'){
2974
- throw err;
2992
+ .map(async function(fileName){
2993
+ if (!fileName) return '';
2994
+ var i = 0;
2995
+ var content;
2996
+ do {
2997
+ var folder = installFolders[i];
2998
+ try{
2999
+ content = await fs.readFile(be.rootPath+'/'+folder+'/'+fileName, {encoding:'UTF8'});
3000
+ } catch (err) {
3001
+ if(err.code!='ENOENT') throw err;
2975
3002
  }
2976
- console.log("err:",err);
3003
+ i++;
3004
+ } while (i < installFolders.length && !content);
3005
+ if (!content) {
2977
3006
  return '-- no '+fileName+'\n';
2978
- }).then(function(content){
2979
- return '-- '+fileName+'\n'+content;
2980
- });
3007
+ } else {
3008
+ return '-- '+folder+'/'+fileName+'\n'+content;
3009
+ };
2981
3010
  })
2982
3011
  );
3012
+
3013
+ var common = (await Promise.all(be.appStack.map(async function(stackNode){
3014
+ var common = [];
3015
+ for (var prefix of ['../', '../../']) {
3016
+ try {
3017
+ var dirName = Path.join(stackNode.path,prefix+'install').replace(regexpDistReplacer,'$1$2')
3018
+ var list = await fs.readdir(dirName);
3019
+ } catch (err) {
3020
+ if (err.code != 'ENOENT') throw err;
3021
+ var list = [];
3022
+ }
3023
+ for(var fileName of list){
3024
+ if (fileName.endsWith('-fun.sql')) {
3025
+ common.push(await fs.readFile(Path.join(dirName,fileName), 'utf-8'));
3026
+ }
3027
+ }
3028
+ }
3029
+ return common.join('\n');
3030
+ }))).join('\n');
3031
+
2983
3032
  var prepareList=(be.config.install.dump.scripts['prepare']||[]);
2984
3033
  var mainSql=(
2985
3034
  (complete? linesCreate.join('\n'): '')+
2986
3035
  (complete||opts.forDump? searchPathline.join('\n'): '')+
3036
+ '\n-- common'+
3037
+ common+'\n'+
2987
3038
  (complete? '\n\n--prepare.sql\n'+ texts[0]+'\n\n' :'' )+
2988
3039
  (complete? texts.slice(3,3+prepareList.length).join('\n\n')+'\n\n' : '' )+
2989
3040
  '\n-- functions\n' + functionLines.join('\n')+
@@ -3116,6 +3167,8 @@ AppBackend.prototype.exportacionesGenerico = async function exportacionesGeneric
3116
3167
  if (typeof result[0].title !== "string" || typeof result[0].rows !== "object" && !(result[0].rows instanceof Array) ) {
3117
3168
  throw new Error ("exportacionesGenerico debe recibir {title:string, rows:Record<string, any>[]}")
3118
3169
  }
3170
+ csvFileName = result[0].csvFileName ?? csvFileName;
3171
+ fileName = result[0].fileName ?? fileName;
3119
3172
  await bestGlobals.sleep(100);
3120
3173
  context.informProgress({message:`buscando archivos recién generados`})
3121
3174
  /** @type {{url:string, label:string}[]} */
@@ -1,7 +1,7 @@
1
1
  // @ts-check
2
2
  "use strict";
3
3
 
4
- var {datetime, changing, coalesce} = require('best-globals');
4
+ var {datetime, changing, coalesce, splitRawRowIntoRow} = require('best-globals');
5
5
  var XLSX = require('xlsx');
6
6
  var fs = require('fs/promises')
7
7
  var fsSync = require('fs');
@@ -78,13 +78,14 @@ ProcedureTables = [
78
78
  {name: 'table', encoding:'plain'},
79
79
  {name: 'fixedFields', defaultValue:[]},
80
80
  {name: 'paramfun', defaultValue:[]},
81
- {name: 'pick', defaultValue:'', encoding:'plain'}
81
+ {name: 'pick', defaultValue:'', encoding:'plain'},
82
+ {name: 'retrieveIgnoringWhere', defaultValue:false}
82
83
  ],
83
84
  coreFunction:
84
85
  /**
85
86
  *
86
87
  * @param {*} context
87
- * @param {{table:string, fixedFields:{fieldName:string, value:any, range:string}[], paramfun:string[], pick:string}} parameters
88
+ * @param {{table:string, fixedFields:{fieldName:string, value:any, range:string}[], paramfun:string[], pick:string, retrieveIgnoringWhere:boolean}} parameters * @param {{table:string, fixedFields:{fieldName:string, value:any, range:string}[], paramfun:string[], pick:string}} parameters
88
89
  */
89
90
  async function tableDatum(context, parameters){
90
91
  var be=context.be;
@@ -148,7 +149,7 @@ ProcedureTables = [
148
149
  /** @type {string} */
149
150
  var sql="SELECT "+[...defTable.sql.select].join(', ')+
150
151
  "\n FROM "+defTable.sql.from+
151
- "\n WHERE "+(defTable.sql.where||(defTable.allow.select && !defTable.forInsertOnlyMode?'true':'false'))+fixedClausule.join("")+
152
+ "\n WHERE "+((parameters.retrieveIgnoringWhere?'true':defTable.sql.where)||(defTable.allow.select && !defTable.forInsertOnlyMode?'true':'false'))+fixedClausule.join("")+
152
153
  // " ORDER BY "+defTable.primaryKey.map(be.db.quoteIdent.bind(be.db)).join(',')
153
154
  "\n ORDER BY "+(defTable.sql.orderBy||defTable.primaryKey).map(function(fieldName){ return be.db.quoteIdent(fieldName); }).join(',')
154
155
  if(specialFixedClause.length){
@@ -804,7 +805,8 @@ ProcedureTables = [
804
805
  var rowsForUpsert=lines.slice(1).map(function(line){
805
806
  var othersArray = [];
806
807
  if(separator=='|'){
807
- var row = line.split(/(?<!(?:^|[^\\])(?:\\\\)*\\)\|/).map(item => item.trimRight().replace(/\\(.)/g,(_,l)=>(l=='t'?'\t':l=='r'?'\r':l=='n'?'\n':l=='s'?' ':l)));
808
+ var row = splitRawRowIntoRow(line);
809
+
808
810
  }else{
809
811
  var row=line.split(separator);
810
812
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "backend-plus",
3
3
  "description": "Backend for the anti Pareto rule",
4
- "version": "2.0.0-rc.1",
4
+ "version": "2.0.0-rc.10",
5
5
  "author": "Codenautas <codenautas@googlegroups.com>",
6
6
  "license": "MIT",
7
7
  "repository": "codenautas/backend-plus",
@@ -11,7 +11,8 @@
11
11
  "lib",
12
12
  "for-client",
13
13
  "unlogged",
14
- "src"
14
+ "src",
15
+ "install"
15
16
  ],
16
17
  "contributors": [
17
18
  {
@@ -31,32 +32,32 @@
31
32
  "@upgraded/locate-path": "^6.0.0-alfa.1",
32
33
  "ajax-best-promise": "^0.4.0",
33
34
  "backend-skins": "^0.1.15",
34
- "best-globals": "^1.1.2",
35
+ "best-globals": "^1.1.4",
35
36
  "big.js": "^6.2.1",
36
37
  "body-parser": "^1.20.2",
37
- "cast-error": "^0.1.0",
38
+ "cast-error": "^0.1.1",
38
39
  "castellano": "^0.1.3",
39
40
  "connect-pg-simple": "^9.0.1",
40
41
  "cookie-parser": "^1.4.6",
41
42
  "dialog-promise": "^0.9.15",
42
43
  "discrepances": "^0.2.8",
43
- "express": "^4.18.2",
44
- "express-session": "^1.17.3",
44
+ "express": "^4.19.2",
45
+ "express-session": "^1.18.0",
45
46
  "express-useragent": "^1.0.15",
46
47
  "fs-extra": "^11.2.0",
47
48
  "js-to-html": "^1.3.2",
48
49
  "js-yaml": "^4.1.0",
49
50
  "json4all": "^1.3.0-beta.1",
50
51
  "lazy-some": "^0.1.0",
51
- "like-ar": "^0.3.9",
52
+ "like-ar": "^0.4.0",
52
53
  "login-plus": "^1.7.1",
53
54
  "memorystore": "^1.6.7",
54
55
  "mini-tools": "^1.12.1",
55
56
  "moment": "^2.30.1",
56
57
  "multiparty": "^4.2.3",
57
- "nodemailer": "^6.9.8",
58
+ "nodemailer": "^6.9.13",
58
59
  "numeral": "^2.0.6",
59
- "pg-promise-strict": "^1.3.3",
60
+ "pg-promise-strict": "^1.4.0",
60
61
  "pikaday": "^1.8.2",
61
62
  "pug": "^3.0.2",
62
63
  "read-yaml-promise": "^1.0.2",
@@ -67,8 +68,8 @@
67
68
  "session-file-store": "^1.5.0",
68
69
  "sql-tools": "^0.1.2",
69
70
  "stack-trace": "^0.0.10",
70
- "stylus": "0.62.0",
71
- "type-store": "^0.4.0",
71
+ "stylus": "0.63.0",
72
+ "type-store": "^0.4.1",
72
73
  "typed-controls": "^0.12.0",
73
74
  "xlsx": "https://cdn.sheetjs.com/xlsx-0.19.3/xlsx-0.19.3.tgz"
74
75
  },
@@ -81,7 +82,7 @@
81
82
  "@types/js-yaml": "^4.0.9",
82
83
  "@types/mocha": "^10.0.6",
83
84
  "@types/multiparty": "~0.0.36",
84
- "@types/node": "^20.11.9",
85
+ "@types/node": "^20.12.2",
85
86
  "@types/nodemailer": "^6.4.14",
86
87
  "@types/numeral": "~2.0.5",
87
88
  "@types/session-file-store": "^1.2.5",
@@ -89,20 +90,20 @@
89
90
  "@types/websql": "~0.0.30",
90
91
  "esprima": "^4.0.1",
91
92
  "expect.js": "~0.3.1",
92
- "karma": "6.4.2",
93
+ "karma": "6.4.3",
93
94
  "karma-chrome-launcher": "^3.2.0",
94
95
  "karma-expect": "^1.1.3",
95
- "karma-firefox-launcher": "^2.1.2",
96
+ "karma-firefox-launcher": "^2.1.3",
96
97
  "karma-ie-launcher": "^1.0.0",
97
98
  "karma-mocha": "^2.0.1",
98
99
  "kill-9": "~0.4.3",
99
- "mocha": "^10.2.0",
100
+ "mocha": "^10.4.0",
100
101
  "nyc": "^15.1.0",
101
- "puppeteer": "^21.9.0",
102
+ "puppeteer": "^22.6.1",
102
103
  "sinon": "^17.0.1",
103
104
  "supertest": "^6.3.4",
104
105
  "types.d.ts": "~0.6.21",
105
- "typescript": "^5.3.3",
106
+ "typescript": "^5.4.3",
106
107
  "why-is-node-running": "^2.2.2"
107
108
  },
108
109
  "engines": {