backend-plus 2.0.0-rc.3 → 2.0.0-rc.31

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)
@@ -161,5 +161,9 @@ a.disabled
161
161
  font-size 80%
162
162
  text-align right
163
163
  color #777
164
+ > .json-container
165
+ position sticky
166
+ top 5%
167
+ bottom 5%
164
168
 
165
169
 
@@ -8,8 +8,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  var __generator = (this && this.__generator) || function (thisArg, body) {
11
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
12
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
11
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
12
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13
13
  function verb(n) { return function (v) { return step([n, v]); }; }
14
14
  function step(op) {
15
15
  if (f) throw new TypeError("Generator is already executing.");
@@ -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;
@@ -291,9 +291,11 @@ myOwn.showPage = function showPage(pageDef){
291
291
  rightMenu.style.zIndex=300;
292
292
  totalLayout.appendChild(rightMenu);
293
293
  }
294
- rightMenu.onclick=function(){
295
- if(!my.offline.mode){
296
- my.rightMenu();
294
+ if (rightMenu != null) {
295
+ rightMenu.onclick=function(){
296
+ if(!my.offline.mode){
297
+ my.rightMenu();
298
+ }
297
299
  }
298
300
  }
299
301
  };
@@ -539,9 +541,9 @@ myOwn.informDetectedStatus = function informDetectedStatus(statusCode, logged) {
539
541
  }
540
542
  if(statusCode==='notLogged'){
541
543
  var notLogged = document.getElementById('not-logged');
542
- notLogged.style.display='inherit';
544
+ if (notLogged) notLogged.style.display='inherit';
543
545
  var activeUser = document.getElementById('active-user');
544
- activeUser.style.display='none';
546
+ if (activeUser) activeUser.style.display='none';
545
547
  }
546
548
  }
547
549
 
@@ -558,11 +560,13 @@ myOwn.offlineModeRefresh = function offlineModeRefresh(){
558
560
  /** @type {HTMLImageElement} */
559
561
  // @ts-ignore
560
562
  var imgLight = document.getElementById('light-airplane');
561
- var skin=((my.config||{}).config||{}).skin;
562
- if(my.offline.mode){
563
- imgLight.src=my.path.img+'airplane-on.png';
564
- }else{
565
- imgLight.src=my.path.img+'airplane-off.png';
563
+ if (imgLight != null) {
564
+ var skin=((my.config||{}).config||{}).skin;
565
+ if(my.offline.mode){
566
+ imgLight.src=my.path.img+'airplane-on.png';
567
+ }else{
568
+ imgLight.src=my.path.img+'airplane-off.png';
569
+ }
566
570
  }
567
571
  }
568
572
 
@@ -183,20 +183,15 @@ myOwn.i18n.messages.es=changing(myOwn.i18n.messages.es, {
183
183
  /** @param {string} text */
184
184
  function regex4search(text){
185
185
  return new RegExp(
186
- text.trim().replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
186
+ text.toString().trim().replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
187
187
  // .replace(/"/g,"\\b")
188
188
  .replace(/[ñÑ]/g,'(?:gn|nn?i?|[ñÑ])')
189
- .replace(/[cCçÇ]/g,'[cçÇ]')
190
- .replace(/[áÁàÀäÄãÃ]/gi,'[AáÁàÀäÄãÃ]')
191
- .replace(/[éÉèÈëË]/gi,'[EéÉèÈëË]')
192
- .replace(/[íÍìÌïÏ]/gi,'[IíÍìÌïÏ]')
193
- .replace(/[óÓòÒöÖõÕ]/gi,'[OóÓòÒöÖõÕ]')
194
- .replace(/[úÚùÙüÜ]/gi,'[UúÚùÙüÜ]')
195
- .replace(/a/gi,'[AáÁàÀäÄãÃ]')
196
- .replace(/e/gi,'[EéÉèÈëË]')
197
- .replace(/i/gi,'[IíÍìÌïÏ]')
198
- .replace(/o/gi,'[OóÓòÒöÖõÕ]')
199
- .replace(/u/gi,'[UúÚùÙüÜ]')
189
+ .replace(/[cCçÇ]/g,'[cCçÇ]')
190
+ .replace(/[AáÁàÀäÄãÃ]/gi,'[AáÁàÀäÄãÃ]')
191
+ .replace(/[EéÉèÈëË]/gi,'[EéÉèÈëË]')
192
+ .replace(/[IíÍìÌïÏ]/gi,'[IíÍìÌïÏ]')
193
+ .replace(/[OóÓòÒöÖõÕ]/gi,'[OóÓòÒöÖõÕ]')
194
+ .replace(/[UúÚùÙüÜ]/gi,'[UúÚùÙüÜ]')
200
195
  // .replace(/\s+/g,'.*\\s+.*') mas estricto, exige el espacio
201
196
  .replace(/\s+/g,'.*')
202
197
  , 'i');
@@ -212,9 +207,9 @@ myOwn.comparatorParameterNull={
212
207
  '!=\u2205':true,
213
208
  }
214
209
  myOwn.comparator={
215
- '=':function(valueToCheck,condition){return valueToCheck == condition;},
216
- '~':function(valueToCheck,condition){return condition==null || regex4search(condition.toString()).test(valueToCheck);},
217
- '!~':function(valueToCheck,condition){return condition==null || !regex4search(condition.toString()).test(valueToCheck);},
210
+ '=':function(valueToCheck,condition){return sameValue(valueToCheck,condition);},
211
+ '~': function(valueToCheck,condition){return condition==null || condition instanceof Date ? Math.abs(condition-valueToCheck) <= 1000*60*60*24 : regex4search(condition).test(valueToCheck);},
212
+ '!~':function(valueToCheck,condition){return condition==null || condition instanceof Date ? Math.abs(condition-valueToCheck) > 1000*60*60*24 :!regex4search(condition).test(valueToCheck);},
218
213
  '/R/i':function(valueToCheck,condition){return condition==null || RegExp(condition,'i').test(valueToCheck);},
219
214
  '\u2205':function(valueToCheck,condition){return valueToCheck == null;},//\u2205 = conjunto vacío
220
215
  '!=\u2205':function(valueToCheck,condition){return valueToCheck != null;},//\u2205 = conjunto vacío
@@ -690,11 +685,18 @@ myOwn.tableGrid = function tableGrid(tableName, mainElement, opts){
690
685
  if (myOwn.config.config['grid-row-retain-moved-or-deleted'] && !force) {
691
686
  var depotsToRetain = grid.depots.filter(depot => depot.tick == tick);
692
687
  for (depot of depotsToRetain) {
688
+ depot['$refreshed'] = false
693
689
  if (depot.tr && depot.tr.getAttribute('not-here')) depot.tr.removeAttribute('not-here')
694
690
  }
695
691
  }
696
692
  while (depot = depotsToDelete.pop()) {
697
693
  depot.manager.displayAsDeleted(depot, force ? 'change-ff' : 'unknown');
694
+ if (myOwn.config.config['grid-row-retain-moved-or-deleted']) {
695
+ if(!depot['$refreshed']){
696
+ grid.retrieveRowAndRefresh(depot,{retrieveIgnoringWhere:true})
697
+ depot['$refreshed'] = true
698
+ }
699
+ }
698
700
  }
699
701
  }
700
702
  })
@@ -998,7 +1000,7 @@ myOwn.DataColumnGrid.prototype.thFilter = function thFilter(depot, iColumn){
998
1000
  var grid = this.grid;
999
1001
  var fieldDef = this.fieldDef;
1000
1002
  var fieldName=fieldDef.name;
1001
- depot.rowSymbols[fieldDef.name]=depot.rowSymbols[fieldDef.name]||'~';
1003
+ depot.rowSymbols[fieldDef.name]=depot.rowSymbols[fieldDef.name]||(fieldDef.typeName == 'text' ? '~' : '=');
1002
1004
  var filterImage=my.path.img+my.comparator.traductor[depot.rowSymbols[fieldDef.name]]+'.png';
1003
1005
  var th=html.td(this.cellAttributes({class:"autoFilter", "typed-controls-direct-input":true},{skipMandatory:true})).create();
1004
1006
  var symbolFilter=th;
@@ -1615,7 +1617,7 @@ myOwn.dialogDownload = function dialogDownload(grid){
1615
1617
  }else{
1616
1618
  separator='|';
1617
1619
  var trans={
1618
- '|':'\\|',
1620
+ '|':'\\x7C',
1619
1621
  '\\':'\\\\',
1620
1622
  '\r':'\\r',
1621
1623
  '\n':'\\n',
@@ -2246,7 +2248,8 @@ myOwn.TableGrid.prototype.createRowInsertElements = function createRowInsertElem
2246
2248
  }
2247
2249
  var depotForInsert = grid.createDepotFromRow({$allow:{delete:true, update:true}}, 'new');
2248
2250
  grid.connector.fixedFields.forEach(function(pair){
2249
- if(!pair.range && grid.def.field[pair.fieldName].inTable !== false){
2251
+ var fieldDef = grid.def.field[pair.fieldName];
2252
+ if(!pair.range && (fieldDef.inTable !== false || fieldDef.isPk && pair.value !=null)){
2250
2253
  depotForInsert.row[pair.fieldName] = pair.value;
2251
2254
  depotForInsert.rowPendingForUpdate[pair.fieldName] = pair.value;
2252
2255
  }
@@ -2385,7 +2388,8 @@ myOwn.TableGrid.prototype.displayGrid = function displayGrid(){
2385
2388
  fixedFields:grid.def.primaryKey.map(function(fieldName, i){
2386
2389
  return {fieldName:fieldName, value:depot.primaryKeyValues[i]};
2387
2390
  }),
2388
- pick:grid.def.pick
2391
+ pick:grid.def.pick,
2392
+ retrieveIgnoringWhere: opts?opts.retrieveIgnoringWhere:false
2389
2393
  }).then(function(result){
2390
2394
  grid.depotRefresh(depot,{updatedRow:result[0], sendedForUpdate:{}}, opts);
2391
2395
  })
@@ -1,4 +1,3 @@
1
- /// <reference types="websql" />
2
1
  import { TableDefinition } from "backend-plus";
3
2
  export type Key = string[];
4
3
  type DetectFeatures = {
@@ -8,8 +8,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  var __generator = (this && this.__generator) || function (thisArg, body) {
11
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
12
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
11
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
12
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13
13
  function verb(n) { return function (v) { return step([n, v]); }; }
14
14
  function step(op) {
15
15
  if (f) throw new TypeError("Generator is already executing.");
@@ -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$;
@@ -12,9 +12,7 @@ export type LangId = 'en'|'es'|'etc...';
12
12
 
13
13
  export type Server=net.Server;
14
14
 
15
- export interface CoreFunctionParameters{
16
- [key:string]: any
17
- }
15
+ export type CoreFunctionParameters<T extends Record<string, any>> = T;
18
16
 
19
17
  export type MarkdownDoc = 'markdown documentation with `` can content newlines. The identation of the first line is deleted in all others'|'etc...';
20
18
 
@@ -34,14 +32,14 @@ export type UploadedFileInfo={
34
32
  path: string
35
33
 
36
34
  }
37
- export type CoreFunction = ((context: ProcedureContext, parameters: CoreFunctionParameters) => Promise<any>)
38
- | ((context: ProcedureContext, parameters: CoreFunctionParameters, files?:UploadedFileInfo[]) => Promise<any>);
35
+ export type CoreFunction<T> = ((context: ProcedureContext, parameters: CoreFunctionParameters<T>) => Promise<any>)
36
+ | ((context: ProcedureContext, parameters: CoreFunctionParameters<T>, files?:UploadedFileInfo[]) => Promise<any>);
39
37
 
40
- export interface ProcedureDef {
38
+ export interface ProcedureDef<T = any> {
41
39
  action: string
42
40
  parameters: ProcedureParameter[]
43
41
  method?: 'get'|'post'
44
- coreFunction: CoreFunction
42
+ coreFunction: CoreFunction<T>
45
43
  encoding?:'JSON4all'|'JSON'|'download'
46
44
  multipart?:true
47
45
  progress?:true
@@ -78,7 +76,7 @@ export interface ContextForDump extends Context {
78
76
  forDump?:boolean
79
77
  }
80
78
 
81
- export type InformProgressFunction=(opts:Error|{data:any}|{start:any}|{message:string}|{message?:string, lengthComputable:boolean, loaded:number, total:number, force?:boolean})=>void
79
+ export type InformProgressFunction=(opts:Error|{data:any}|{start:any}|{message:string}|{idGroup?:string, message?:string, lengthComputable:boolean, loaded:number, total:number, force?:boolean})=>void
82
80
 
83
81
  export interface ProcedureContext extends Context{
84
82
  client:Client
@@ -93,6 +91,11 @@ export interface Request extends express.Request {
93
91
  user?:User
94
92
  session:express.Request["session"]
95
93
  }
94
+ export interface RequestDb {
95
+ user?:User
96
+ machineId?:string
97
+ userAgent?:{shortDescription?:string}
98
+ }
96
99
  export {Response, Express} from "express";
97
100
  export interface ResponsePlus extends express.Response{}
98
101
  export interface ExpressPlus extends express.Express{}
@@ -136,7 +139,7 @@ export type MenuInfoPath={
136
139
  path:string
137
140
  } & MenuInfoMinimo;
138
141
  export interface ClientModuleDefinition{
139
- type:'js'|'css'|'ttf'
142
+ type:'js'|'css'|'ttf'|'mjs'
140
143
  module?:string // module where to search in node_modules (node_modules/module/modPath/file) to serve
141
144
  modPath?:string // path inside module where to find file to serve
142
145
  src?:string // full path where browser search file (path/file)
@@ -171,6 +174,7 @@ export type SequenceDefinition = {
171
174
  prefix?:string /* Prefix for the generated value */
172
175
  }
173
176
  export type ExportMetadataDefinition={ /* TODO: define */ }
177
+ export type PostInputOptions='upperSpanish' | 'upperWithoutDiacritics' | 'parseDecimal'
174
178
  export type FieldDefinition = EditableDbDefinition & {
175
179
  name:string
176
180
  typeName:PgKnownTypes|'ARRAY:text'
@@ -186,7 +190,7 @@ export type FieldDefinition = EditableDbDefinition & {
186
190
  serverSide?:boolean /* default:!clientSide if the value is retrived from the database */
187
191
  inTable?:boolean /* default:!clientSide && !sql.fields[...].expr. Is a real fisical field in the table */
188
192
  /* sizeByte?:number deprecated size in bytes for numbers */
189
- allowEmtpyText?:boolean /* if a text field accepts '' as a valid value */
193
+ allowEmptyText?:boolean /* if a text field accepts '' as a valid value */
190
194
  mobileInputType?:string
191
195
  extraRow?:number
192
196
  inexactNumber?:number /* default:depends on typeName if = means abs(x-v)<espilon
@@ -212,6 +216,8 @@ export type FieldDefinition = EditableDbDefinition & {
212
216
  inherited?:boolean
213
217
  nameForUpsert?:string
214
218
  alwaysShow?:boolean /* show when appears in fixed fields */
219
+ suggestingKeys?:string[]
220
+ postInput?:PostInputOptions
215
221
  } & ({} | {
216
222
  sequence:SequenceDefinition
217
223
  nullable:true
@@ -252,22 +258,24 @@ export type Constraint = {constraintType:string, consName?:string} & (
252
258
  {constraintType:'unique', fields:string[], where?:string} |
253
259
  {constraintType:'check', expr?:string}
254
260
  )
261
+ export type OtherTableDefs = Record<string,Partial<TableDefinition & {prefilledField:Record<string,any>}>>
255
262
  export type TableDefinition = EditableDbDefinition & {
256
263
  name:string
257
264
  elementName?:string
258
265
  tableName?:string
259
266
  schema?:string
260
267
  title?:string
261
- fields:FieldDefinition[],
262
- primaryKey:string[],
263
- refrescable?: boolean;
268
+ fields:FieldDefinition[]
269
+ primaryKey:string[]
270
+ refrescable?: boolean
264
271
  sql?:{
272
+ primaryKey4Delete?:string[]
265
273
  isTable?:boolean
266
274
  from?:string
267
275
  where?:string
268
276
  postCreateSqls?:string
269
- skipEnance?: boolean,
270
- isReferable?: boolean,
277
+ skipEnance?: boolean
278
+ isReferable?: boolean
271
279
  logicalDeletes?:{
272
280
  fieldName:string
273
281
  valueToDelete:string
@@ -276,24 +284,26 @@ export type TableDefinition = EditableDbDefinition & {
276
284
  fieldName:string
277
285
  }
278
286
  tableName?:string
287
+ tableName4Delete?:string
279
288
  fields?:{
280
289
  [k:string]:{
281
290
  expr:string
282
291
  }
283
- },
292
+ }
284
293
  orderBy?:string[]
285
294
  viewBody?:string
286
295
  insertIfNotUpdate?:boolean
287
296
  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}
297
+ all ?:{name?:string, using?:string, check?:string}
298
+ select?:{name?:string, using?:string}
299
+ insert?:{name?:string, check?:string}
300
+ update?:{name?:string, using?:string, check?:string}
301
+ delete?:{name?:string, using?:string}
293
302
  }
294
303
  join?:string
295
304
  constraintsDeferred?:boolean
296
- otherTableDefs?:Record<string,Partial<TableDefinition & {prefilledField:Record<string,any>}>>
305
+ otherTableDefs?:OtherTableDefs
306
+ setExpectedPkValues?:boolean
297
307
  }
298
308
  foreignKeys?:ForeignKey[]
299
309
  softForeignKeys?:ForeignKey[]
@@ -319,10 +329,9 @@ export type TableDefinition = EditableDbDefinition & {
319
329
  specialValidator?:string
320
330
  saveAfter?:boolean
321
331
  selfRefresh?:boolean
322
- filterColumns?:{column:string, operator:string, value:any}[],
332
+ filterColumns?:{column:string, operator:string, value:any}[]
323
333
  gridAlias?:string /* front-end css my-table = gridAlias */
324
334
  }
325
- export type OtherTableDefs = TableDefinition['sql']['otherTableDefs']
326
335
  export interface DetailTable { table?: string, fields: FieldsForConnectDetailTable, abr: string, label?: string, refreshParent?:boolean, refreshFromParent?:boolean, wScreen?:string, condition?:string }
327
336
  export type TableDefinitionFunction = (context: ContextForDump, opts?:any) => TableDefinition;
328
337
  export type TableItemDef=string|{name:string, path?:string, tableGenerator?:(context:TableContext)=>TableDefinition}
@@ -365,6 +374,129 @@ export interface Caches {
365
374
  procedures:Record<string, {timestamp:number, result:any}>
366
375
  }
367
376
 
377
+ export interface AppConfigBin { // executables in SO
378
+ "zip-password-parameter-flag": string // parameter to pass the password to the zipper
379
+ "zip-password-prefix": string // password prefix
380
+ "zip-fixed-parameters":string // fixed parameters to pass to zipper
381
+ }
382
+
383
+ export interface AppConfig {
384
+ package: {
385
+ version: string
386
+ }
387
+ server: {
388
+ "base-url": string // rool path in the url
389
+ port: number // port of the API services
390
+ "session-store": string // strategies to store session info
391
+ "ip-replacer": string // ip that can be not showed or deduced in logs
392
+ "silent-startup": boolean // less logs when startup
393
+ "kill-9": string // a way to kill from URL with a token
394
+ bitacoraSchema: string
395
+ bitacoraTableName: string
396
+ }
397
+ db: {
398
+ motor: 'postgresql'
399
+ database: string
400
+ user: string
401
+ password: string
402
+ schema: string
403
+ search_path: string
404
+ tablespace: string // for creation scripts
405
+ "min-version": string // min version of the motor needed
406
+ nodb: boolean // if there is no database needed in the app
407
+ no_login: boolean // if no login is needed. Used only for all public sites
408
+ "downloadable-backup-path": string // OS path of the encrypted downloadable backup
409
+ }
410
+ login: {
411
+ schema: string // schema of the user table
412
+ table: string // user table
413
+ userFieldname: string // fieldname in user table that stores the user name
414
+ passFieldname: string // fieldname in user table that stores the password hash
415
+ rolFieldname: string // fieldname in user table that stores the rol
416
+ unloggedLandPage: string // land page when there is no user logged when the backend has public services
417
+ noLoggedUrlPath: string // path of non logged users when the backend has no public services
418
+ "preserve-case": boolean // preserve the case of the user name
419
+ activeClausule: string // SQL expression over the user table to check if a user is active
420
+ lockedClausule: string // SQL expression over the user table to check if a user is locked
421
+ disableChangePassword: boolean // disallow password change
422
+ skipBitacora: boolean // don't register logins
423
+ keepAlive: number // secs to keep alive a session if only keep alive request where received
424
+ plus: {
425
+ userFieldName:string
426
+ store:{
427
+ module: string
428
+ }
429
+ }
430
+ forget: { // forget password configurations:
431
+ urlPath: string // url sent by mail. default: `/new-pass`
432
+ urlPathOk: string // confirmation page
433
+ mailFields: string[] // fields for the forget pass mail
434
+
435
+ }
436
+ "double-dragon": boolean // app user must match db user
437
+ }
438
+ install: {
439
+ "table-data-dir": string // SO path to the .tab files in the db creation script
440
+ dump: { // configuration of --dump-db, the db creation script
441
+ "drop-his": boolean // include drop schema his in the db creation script
442
+ db: {
443
+ owner: string
444
+ extensions: string[] // extensions to be installed (gist, pg_trgm, pgcrypto)
445
+ enances: 'file' // if the enances must be dumped in a separate file
446
+ // from here info to set the owner and replace owner and user used in devel when script creation
447
+ "owner4special-scripts": string
448
+ "user4special-scripts": string
449
+ "apply-generic-user-replaces": string
450
+ }
451
+ "admin-can-create-tables": boolean // for apps that allows the user to create tables
452
+ "skip-content": boolean // don't create data from "table-data-dir"
453
+ folders: string //
454
+ scripts: {
455
+ prepare: string // SO path to the prepare scripts that will be run before the functions creations and inserts
456
+ "post-adapt": string // SO path to the post-adapt scripts that will be run after data inserts (of .tab tables)
457
+ }
458
+ }
459
+ }
460
+ "client-setup": { // front-end config
461
+ title:string // title of the app (common sufix of the title bar)
462
+ }
463
+ log: {
464
+ "serve-content": never
465
+ req: {
466
+ "keep-alive": boolean
467
+ }
468
+ db: {
469
+ "last-error": boolean // store last db error in a log file
470
+ devel: boolean //
471
+ "on-demand": string // if log db level can be changed on the fly
472
+ until: string | Date // full log until...
473
+ results: boolean // if query results must be included in full db logs
474
+ }
475
+ session: boolean // if all session activity must be logged
476
+ }
477
+ devel: {
478
+ delay: number // msec avg random delay in API responses (to emulate slow nets)
479
+ "cache-content": boolean // if the cache header must be sent to the client (when no devel config the default is true)
480
+ forceShowAsEditable: boolean // force "editable" behavior in grids
481
+ }
482
+ mailer: { // config to send mails
483
+ conn: string // connection string
484
+ "mail-info": {} // static mail config
485
+ supervise: {
486
+ to: string // email addres of the supervisor
487
+ event: {
488
+ }
489
+ }
490
+ }
491
+ bin: AppConfigBin
492
+ data: {
493
+ transformers: {
494
+ text: string // define the inputTransformers for text comming from the fron-end via the API
495
+ }
496
+ }
497
+ skipUnknownFieldsAtImport: boolean // if unknown fields must be skipped by default in import
498
+ }
499
+
368
500
  export class AppBackend{
369
501
  procedures:ProcedureDef[]
370
502
  procedure:{ [key:string]:ProcedureDef }
@@ -372,7 +504,7 @@ export class AppBackend{
372
504
  getTableDefinition: TableDefinitionsGetters
373
505
  tableStructures: TableDefinitions
374
506
  db: MotorDb
375
- config: any
507
+ config: AppConfig
376
508
  rootPath: string
377
509
  caches:Caches
378
510
  fieldDomain:{[k:string]:Partial<FieldDefinition>}
@@ -398,10 +530,10 @@ export class AppBackend{
398
530
  isAdmin():boolean
399
531
  canChangePass():Promise<boolean>
400
532
  getMenu(context?:Context):MenuDefinition
401
- inDbClient<T>(req:Request|null, doThisWithDbClient:(client:Client)=>Promise<T>):Promise<T>
402
- inTransaction<T>(req:Request|null, doThisWithDbTransaction:(client:Client)=>Promise<T>):Promise<T>
533
+ inDbClient<T>(req:RequestDb|null, doThisWithDbClient:(client:Client)=>Promise<T>):Promise<T>
534
+ inTransaction<T>(req:RequestDb|null, doThisWithDbTransaction:(client:Client)=>Promise<T>):Promise<T>
403
535
  inTransactionProcedureContext<T>(req:Request|null, coreFunction:(context:ProcedureContext)=>Promise<T>):Promise<T>
404
- procedureDefCompleter(procedureDef:ProcedureDef):ProcedureDef
536
+ procedureDefCompleter<T>(procedureDef:ProcedureDef):ProcedureDef<T>
405
537
  tableDefAdapt(tableDef:TableDefinition, context:Context):TableDefinition
406
538
  pushApp(dirname:string):void
407
539
  dumpDbTableFields(tableDefinition:TableDefinition):string[]
@@ -420,7 +552,8 @@ export class AppBackend{
420
552
  i18n:{
421
553
  messages:Record<LangId,Record<string, string>>
422
554
  }
423
- shootDownBackend():Promise<void>
555
+ shutdownCallbackListAdd(param:{message:string, fun:()=>Promise<void>}):void
556
+ shutdownBackend():Promise<void>
424
557
  setLog(opts:{until:string, results?:boolean}):void
425
558
  getDataDumpTransformations(rawData:string):Promise<{rawData:string, prepareTransformationSql:string[], endTransformationSql:string[]}>
426
559
  }