backend-plus 2.7.6 → 2.7.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
Binary file
@@ -10,6 +10,7 @@ html(lang=lang)
10
10
  display: none
11
11
  }
12
12
  meta(name='viewport' content="width=device-width, user-scalable=no")
13
+ link(rel='icon', href='img/login-logo-icon.png')
13
14
  body
14
15
  form(id="loginForm", action="login", method="post")
15
16
  table.logintable
@@ -2347,12 +2347,16 @@ myOwn.TableGrid.prototype.prepareGrid = function prepareGrid(){
2347
2347
  grid.actualName = (grid.def.gridAlias || grid.def.name) + (grid.connector.fixedFields.length ? '-' + JSON4all.toUrl(grid.connector.fixedFields.map(function(pair){ return pair.value; })) : '')
2348
2348
  var captionTitle = grid.def.title;
2349
2349
  grid.connector.fixedFields.forEach(function(pair){
2350
- var toCaption = grid.def.field[pair.fieldName].toCaption ?? my.config.config['grid-smart-caption']
2350
+ var fixedFieldDef = grid.def.field[pair.fieldName] ?? (grid.def.functionDef?.parameters ?? []).find(function(parameter){ return parameter.name == pair.fieldName; });
2351
+ if(fixedFieldDef == null){
2352
+ throw new Error('the grid '+grid.def.name+' is filtered by '+pair.fieldName+' that is not a field nor a parameter of the table');
2353
+ }
2354
+ var toCaption = fixedFieldDef.toCaption ?? my.config.config['grid-smart-caption']
2351
2355
  if(toCaption && pair.value != null){
2352
- var typeName = grid.def.field[pair.fieldName].typeName;
2356
+ var typeName = fixedFieldDef.typeName;
2353
2357
  captionTitle += ' '
2354
2358
  if(toCaption == 'labeled' || toCaption != 'alone' && (typeName == 'boolean' || typeName == 'integer' || typeName == 'bigint' || typeName == 'decimal')){
2355
- captionTitle += grid.def.field[pair.fieldName].title + ':'
2359
+ captionTitle += (fixedFieldDef.title ?? fixedFieldDef.name) + ':'
2356
2360
  }
2357
2361
  if(typeName == 'date'){
2358
2362
  var date = bestGlobals.date(new Date(pair.value))
@@ -2613,8 +2617,8 @@ myOwn.TableGrid.prototype.displayGrid = function displayGrid(){
2613
2617
  if(!Object.keys(depot.rowPendingForUpdate).length){
2614
2618
  return Promise.resolve();
2615
2619
  }
2620
+ var specialMandatories=grid.def.specialValidator?myOwn.validators[grid.def.specialValidator].getMandatoryMap(depot.row):{};
2616
2621
  if(depot.status==='new'){
2617
- var specialMandatories=grid.def.specialValidator?myOwn.validators[grid.def.specialValidator].getMandatoryMap(depot.row):{};
2618
2622
  var mandatoryOmitted=function(fieldDef){
2619
2623
  return (specialMandatories[fieldDef.name] || fieldDef.nullable!==true && fieldDef.isPk || fieldDef.nullable===false)
2620
2624
  && depot.row[fieldDef.name]==null
@@ -2630,6 +2634,17 @@ myOwn.TableGrid.prototype.displayGrid = function displayGrid(){
2630
2634
  }
2631
2635
  return Promise.resolve(); // no grabo todavía
2632
2636
  };
2637
+ }else{
2638
+ // en una modificación solo se controlan los obligatorios especiales (campos que son obligatorios según lo cargado en otros)
2639
+ var specialOmitted=grid.def.fields.filter(function(fieldDef){
2640
+ return specialMandatories[fieldDef.name] && depot.row[fieldDef.name]==null;
2641
+ });
2642
+ if(specialOmitted.length){
2643
+ if(depot.tr){
2644
+ depot.tr.title = myOwn.messages.mandatoryFieldOmited + specialOmitted.map(f=>f.name).join(', ');
2645
+ }
2646
+ return Promise.resolve(); // no grabo todavía
2647
+ }
2633
2648
  }
2634
2649
  var timeStamp = my.setTimeStamp(depot.row);
2635
2650
  return grid.connector.saveRecord(depot, opts).then(function(result){
@@ -424,6 +424,7 @@ export interface AppConfigServer
424
424
  useCors: boolean //habilita Cross-Origin Resource Sharing
425
425
  allowedHosts:string[] //determina API allowed hosts (necesita habilitar useCors)
426
426
  policy?:string
427
+ environment?:string // 'production' or other (to choose defaults, for example the background)
427
428
  }
428
429
  export interface AppConfigDb
429
430
  {
@@ -503,6 +504,7 @@ export interface AppConfigClientSetup // front-end config
503
504
  version?:string
504
505
  menu?:boolean
505
506
  "background-img"?:string
507
+ environment?:string // copied from server.environment
506
508
  devel?:boolean
507
509
  deviceWidthForMobile?:string
508
510
  "initial-scale"?:string
@@ -823,6 +823,11 @@ AppBackend.prototype.start = function start(opts){
823
823
  be.config = config;
824
824
  be.clientSetup = {config: be.config["client-setup"]};
825
825
  be.clientSetup.config.prefix = be.clientSetup.config.prefix || be.config.server["base-url"].substr(1)+':';
826
+ if(be.config.server.environment == 'production' && be.config.devel){
827
+ console.warn('WARNING: devel config in a production environment (server.environment: production). For the background, production prevails');
828
+ }
829
+ // the client uses the environment to choose the default background (see my-ajax.js)
830
+ be.clientSetup.config.environment = be.config.server.environment;
826
831
  var downloadsConfig = be.config["client-setup"].downloads;
827
832
  if(downloadsConfig != null){
828
833
  if(downloadsConfig.method != null && !['legacy','SaveFilePicker'].includes(downloadsConfig.method)){
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.7.6",
4
+ "version": "2.7.8",
5
5
  "author": "Codenautas <codenautas@googlegroups.com>",
6
6
  "license": "MIT",
7
7
  "repository": "codenautas/backend-plus",
@@ -47,36 +47,36 @@
47
47
  "cors": "^2.8.6",
48
48
  "dialog-promise": "^0.10.7",
49
49
  "ensure-login": "^0.1.6",
50
- "express": "^5.2.1",
51
- "express-useragent": "^2.2.1",
50
+ "express": "^5.3.0",
51
+ "express-useragent": "^2.2.3",
52
52
  "fflate": "^0.8.3",
53
- "fs-extra": "^11.4.0",
53
+ "fs-extra": "^11.4.1",
54
54
  "js-to-html": "^1.4.0",
55
- "js-yaml": "^5.2.3",
56
- "json4all": "^1.4.4",
55
+ "js-yaml": "^5.4.3",
56
+ "json4all": "^1.4.5",
57
57
  "lazy-some": "^0.1.0",
58
- "like-ar": "^0.5.3",
58
+ "like-ar": "^0.5.4",
59
59
  "login-plus": "^1.9.0",
60
60
  "memorystore": "^1.6.8",
61
61
  "mini-tools": "^1.13.10",
62
- "moment": "^2.30.1",
63
- "multiparty": "^4.3.0",
64
- "nodemailer": "^9.0.3",
62
+ "moment": "^2.31.0",
63
+ "multiparty": "^4.3.1",
64
+ "nodemailer": "^10.0.16",
65
65
  "numeral": "^2.0.6",
66
66
  "pg-promise-strict": "^1.5.0",
67
67
  "pg-triggers": "0.4.6",
68
68
  "pikaday": "^1.8.2",
69
- "require-bro": "^0.4.0",
69
+ "require-bro": "^0.4.1",
70
70
  "serve-content": "^1.0.6",
71
71
  "session-file-store": "^1.5.0",
72
- "simple-git": "^3.36.0",
72
+ "simple-git": "^4.0.2",
73
73
  "sql-tools": "^0.1.7",
74
74
  "stack-trace": "^1.0.0",
75
75
  "tab-plus": "^0.2.0",
76
76
  "type-store": "^0.6.1",
77
77
  "typed-controls": "^0.12.7",
78
78
  "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz",
79
- "xlsx-now": "^0.4.2"
79
+ "xlsx-now": "^0.5.0"
80
80
  },
81
81
  "devDependencies": {
82
82
  "@types/big.js": "^7.0.0",
@@ -87,8 +87,8 @@
87
87
  "@types/js-yaml": "^4.0.9",
88
88
  "@types/mocha": "^10.0.10",
89
89
  "@types/multiparty": "^4.2.1",
90
- "@types/node": "^26.1.2",
91
- "@types/nodemailer": "^8.0.1",
90
+ "@types/node": "^26.6.5",
91
+ "@types/nodemailer": "^8.0.2",
92
92
  "@types/numeral": "~2.0.5",
93
93
  "@types/session-file-store": "^1.2.6",
94
94
  "@types/stack-trace": "^0.0.33",
@@ -97,24 +97,16 @@
97
97
  "discrepances": "^0.2.14",
98
98
  "esprima": "^4.0.1",
99
99
  "expect.js": "^0.3.1",
100
- "karma": "6.4.4",
101
- "karma-chrome-launcher": "^3.2.0",
102
- "karma-expect": "^1.1.3",
103
- "karma-firefox-launcher": "^2.1.3",
104
- "karma-ie-launcher": "^1.0.0",
105
- "karma-mocha": "^2.0.1",
106
100
  "kill-9": "^0.4.3",
107
- "mocha": "^12.0.0-rc.5",
108
- "nyc": "^18.0.0",
109
- "puppeteer": "^25.4.0",
110
- "qa-control": "0.9.2",
101
+ "mocha": "^12.0.3",
102
+ "qa-control": "0.12.1",
111
103
  "regexplicit": "^0.1.3",
112
104
  "self-explain": "^0.11.0",
113
105
  "sinon": "^22.1.0",
114
- "supertest": "^7.2.2",
115
- "types.d.ts": "^0.6.22",
106
+ "supertest": "^7.3.1",
107
+ "types.d.ts": "^0.7.1",
116
108
  "typescript": "^5.9.3",
117
- "why-is-node-running": "^3.2.2"
109
+ "why-is-node-running": "^3.2.3"
118
110
  },
119
111
  "engines": {
120
112
  "node": ">= 22"
@@ -122,13 +114,10 @@
122
114
  "scripts": {
123
115
  "test": "echo testear SiPer que usa la mayoría de la funcionalidad de Backend-Plus",
124
116
  "test-ui": "(npm run prepublish || echo \"continue w/error\") && mocha --reporter spec --single-run --bail test/test-*.js",
125
- "test-karma": "(npm run prepublish || echo \"continue w/error\") && mocha --reporter spec --bail test/test-k*.js",
126
117
  "test-why": "node --expose-internals ./node_modules/mocha/bin/_mocha --reporter spec --bail test/test*.js",
127
118
  "test-ci": "npm test",
128
119
  "test-cov": "(npm run prepublish || echo \"continue w/error\") && mocha --reporter spec --bail test/test*.js",
129
120
  "test-good": "mocha --reporter spec --bail --check-leaks test/test*.js",
130
- "example-pu": "node test/puppeteer/first-step.js",
131
- "test-pu": "node ./test/download_puppeteer && mocha --reporter spec --bail --check-leaks --globals cptable --globals QUOTE --globals __core-js_shared__ test/test-pu.js",
132
121
  "test-server": "mocha --reporter spec --single-run --bail test/test.js",
133
122
  "server-test": "node test/run-simple-backend.js",
134
123
  "example-tables": "node examples/tables/server/server-tables.js --dir-x examples/tables",
@@ -0,0 +1,6 @@
1
+ // No es un test. Existe para que tsconfig-client.json compile archivos de dos
2
+ // carpetas (src/for-client y src/test): tsc toma como raíz la carpeta común a
3
+ // todo lo que compila, y si solo quedara src/for-client la salida iría a la
4
+ // raíz del proyecto en vez de a ./for-client.
5
+ // TODO: Cambiar la configuración para uqe este archivo no sea necesario.
6
+ export {};
@@ -111,6 +111,8 @@ myAjax.readProcedureDefinitions=function readProcedureDefinitions(){
111
111
  var backgroundUrl
112
112
  if(my.config.config && my.config.config['background-img']){
113
113
  backgroundUrl = 'url("'+my.path.img+my.config.config['background-img']+'")'
114
+ }else if(my.config.config && my.config.config.environment == 'production'){
115
+ backgroundUrl = '';
114
116
  }else{
115
117
  if(/(^|[-_0-9/])(test|pru|prueba)($|[-_0-9/])/.test(location.pathname)){
116
118
  backgroundUrl = 'url("img/background-test.png")';
@@ -119,10 +121,13 @@ myAjax.readProcedureDefinitions=function readProcedureDefinitions(){
119
121
  }else if(/(^|[-_0-9/])(desa|devel)($|[-_0-9/])/.test(location.pathname) || my.config.config && my.config.config['devel']){
120
122
  backgroundUrl = 'url("img/background-devel.png")';
121
123
  }else{
122
- backgroundUrl = '';
124
+ // unknown environment: better to see a missing image than no background (declare server.environment)
125
+ backgroundUrl = 'url("img/background-unknown.png")';
123
126
  }
124
127
  }
125
128
  document.body.style.backgroundImage=backgroundUrl;
129
+ // for the apps that need the background in other elements
130
+ my.backgroundUrl=backgroundUrl;
126
131
  }
127
132
  }).then(function(){
128
133
  my.config.procedure=my.config.procedure||{};
@@ -1,381 +0,0 @@
1
- "use strict";
2
-
3
- /// <reference path="../node_modules/types.d.ts/modules/myOwn/in-myOwn.d.ts" />
4
- /// <reference path="../../lib/in-backend-plus.d.ts" />
5
- /// <reference path="../../src/for-client/my-localdb.ts" />
6
- /// <reference path="../../src/for-client/my-websqldb.ts" />
7
-
8
- import {LocalDb, LocalDbTransaction, TableDefinition} from "../for-client/my-localdb";
9
- import {changing} from "best-globals";
10
- import "mocha";
11
- import { WebsqlDb } from "../for-client/my-websqldb";
12
-
13
- function compare<T>(obtained:T, expected:T):boolean{
14
- expect(obtained).to.eql(expected);
15
- return true;
16
- }
17
-
18
- before(function(){
19
- // @ts-ignore
20
- window.myOwn=window.myOwn||{};
21
- // @ts-ignore
22
- window.myOwn.config=window.myOwn.config||{};
23
- // @ts-ignore
24
- window.myOwn.config.useragent=new UserAgent().parse(window.navigator.userAgent);
25
- })
26
-
27
- describe("websql-db", function(){
28
- var ldb:WebsqlDb;
29
- before(function(){
30
- this.timeout(10000);
31
- ldb = new WebsqlDb("the-test-name"+Math.random());
32
- });
33
- after(function(){
34
- //ldb.close();
35
- });
36
- describe("structures", function(){
37
- it("put and get structure", async function(){
38
- this.timeout(10000);
39
- var tableDef:TableDefinition={
40
- name:'this_name',
41
- fields:[
42
- {name: 'pk1', typeName:'text'}
43
- ],
44
- primaryKey:['pk1']
45
- };
46
- await ldb.registerStructure(tableDef);
47
- var newTableDef = await ldb.getStructure(tableDef.name);
48
- compare(tableDef, newTableDef);
49
- });
50
- it("check if exists and exists", async function(){
51
- this.timeout(10000);
52
- var tableDef={
53
- name:'this_name',
54
- fields:[
55
- {name: 'pk1', typeName:'text'}
56
- ],
57
- primaryKey:['pk1']
58
- };
59
- var exists:boolean = await ldb.existsStructure(tableDef.name);
60
- compare(true, exists);
61
- });
62
- it("check if exists and not exists", async function(){
63
- this.timeout(10000);
64
- var tableDef={
65
- name:'inexistent_this_name',
66
- fields:[
67
- {name: 'pk1', typeName:'text'}
68
- ],
69
- primaryKey:['pk1']
70
- };
71
- var exists:boolean = await ldb.existsStructure(tableDef.name);
72
- compare(false, exists);
73
- });
74
- it("check empty structure", async function(){
75
- this.timeout(10000);
76
- var tableDef={
77
- name:'this_name',
78
- fields:[
79
- {name: 'pk1', typeName:'text'}
80
- ],
81
- primaryKey:['pk1']
82
- };
83
- var isEmpty:boolean = await ldb.isEmpty(tableDef.name);
84
- compare(true, isEmpty);
85
- });
86
- it("reput and get structure", async function(){
87
- this.timeout(10000);
88
- var tableDef={
89
- name:'this_name',
90
- fields:[
91
- {name: 'pk1', typeName:'text'},
92
- {name: 'field1', typeName:'text'}
93
- ],
94
- primaryKey:['pk1']
95
- };
96
- await ldb.registerStructure(tableDef);
97
- var newTableDef = await ldb.getStructure(tableDef.name);
98
- compare(tableDef, newTableDef);
99
- });
100
- it("put another structure", async function(){
101
- this.timeout(10000);
102
- var tableDef={
103
- name:'other_name',
104
- fields:[
105
- {name: 'pk2', typeName:'text'}
106
- ],
107
- primaryKey:['pk2']
108
- };
109
- await ldb.registerStructure(tableDef);
110
- var newTableDef = await ldb.getStructure(tableDef.name);
111
- compare(tableDef, newTableDef);
112
- });
113
- it("get all structures", async function(){
114
- this.timeout(10000);
115
- var tableDef1 = await ldb.getStructure('this_name');
116
- var tableDef2 = await ldb.getStructure('other_name');
117
- var tableDefs = await ldb.getAllStructures();
118
- compare([tableDef1, tableDef2], tableDefs);
119
- });
120
- });
121
- describe("data", function(){
122
- type Quantity = {
123
- quantity:string,
124
- preferedUnit:string
125
- }
126
- var tableDef:TableDefinition={
127
- name:'phisical_quantities',
128
- fields:[
129
- {name: 'quantity', typeName:'text'},
130
- {name: 'preferedUnit', typeName:'text'}
131
- ],
132
- primaryKey:['quantity']
133
- }
134
- var mass:Quantity = {quantity: 'mass', preferedUnit:'g'};
135
- var quantities:Quantity[]=[
136
- mass,
137
- {quantity:'time', preferedUnit:'s'},
138
- {quantity:'volume', preferedUnit:'l'},
139
- ];
140
- before(async function(){
141
- await ldb.registerStructure(tableDef);
142
- });
143
- it("put a value", async function(){
144
- var obtainedMass = await ldb.putOne("phisical_quantities", mass);
145
- compare(mass, obtainedMass);
146
- })
147
- it("put many", async function(){
148
- await ldb.putMany("phisical_quantities", quantities.slice(1));
149
- })
150
- it("check empty structure", async function(){
151
- var count:boolean = await ldb.isEmpty("phisical_quantities");
152
- compare(false, count);
153
- });
154
- it("get one", async function(){
155
- var volume = await ldb.getOne<Quantity>("phisical_quantities", ["volume"]);
156
- compare(volume, quantities[2]);
157
- })
158
- it("get one if exists and exists", async function(){
159
- var time = await ldb.getOneIfExists<Quantity>("phisical_quantities", ["time"]);
160
- compare(time, quantities[1]);
161
- })
162
- it("get one if exists and do not exists", async function(){
163
- var undef = await ldb.getOneIfExists<Quantity>("phisical_quantities", ["fourth dimension"]);
164
- compare(undef, undefined);
165
- })
166
- it("get all",async function(){
167
- var all = await ldb.getAll<Quantity>("phisical_quantities");
168
- compare(all, quantities);
169
- })
170
- it("clear all",async function(){
171
- await ldb.clear("phisical_quantities");
172
- var all = await ldb.getAll<Quantity>("phisical_quantities");
173
- compare(all, []);
174
- })
175
- });
176
- describe("childs",function(){
177
- type Units = {
178
- quantity:string,
179
- unit:string
180
- }
181
- var tableDef:TableDefinition={
182
- fields:[
183
- {name: 'quantity', typeName:'text'},
184
- {name: 'unit' , typeName:'text'}
185
- ],
186
- name:'units',
187
- primaryKey:['quantity', 'unit']
188
- }
189
- var volumeUnits=[
190
- {quantity:'volume', unit:'ml'},
191
- {quantity:'volume', unit:'l'},
192
- {quantity:'volume', unit:'cm3'},
193
- {quantity:'volume', unit:'m3'},
194
- ]
195
- var volumeUnitsSorted=[
196
- {quantity:'volume', unit:'cm3'},
197
- {quantity:'volume', unit:'l'},
198
- {quantity:'volume', unit:'m3'},
199
- {quantity:'volume', unit:'ml'},
200
- ]
201
- var massUnits=[
202
- {quantity:'mass', unit:'g'},
203
- {quantity:'mass', unit:'kg'},
204
- {quantity:'mass', unit:'mg'},
205
- ]
206
- var timeUnits=[
207
- {quantity:'time', unit:'s'},
208
- {quantity:'time', unit:'h'},
209
- ]
210
- var units=volumeUnits.concat(massUnits).concat(timeUnits);
211
- before("",async function(){
212
- await ldb.registerStructure(tableDef);
213
- await ldb.putMany("units", units);
214
- })
215
- it("get cm3", async function(){
216
- var obtainedVolumes=await ldb.getOne<Units>("units", ["volume","cm3"]);
217
- compare(obtainedVolumes, volumeUnits[2]);
218
- })
219
- it("get volume childs", async function(){
220
- var obtainedVolumes=await ldb.getChild<Units>("units", ["volume"]);
221
- compare(obtainedVolumes, volumeUnitsSorted);
222
- })
223
- it("get mass childs", async function(){
224
- var obtainedMass=await ldb.getChild("units", ["mass"]);
225
- compare(obtainedMass, massUnits);
226
- })
227
- })
228
- describe("foreignKeys",function(){
229
- this.timeout(10000);
230
- type Product = {
231
- product:string,
232
- name:string,
233
- price:number,
234
- quantity_number: number,
235
- quantity: string,
236
- unit: string,
237
- units__description: string
238
- }
239
- type Units = {
240
- quantity:string,
241
- unit:string,
242
- description: string,
243
- }
244
- var unitsTableDef:TableDefinition={
245
- name:'units',
246
- fields:[
247
- {name: 'quantity' , typeName:'text'},
248
- {name: 'unit' , typeName:'text'},
249
- {name: 'description' , typeName:'text'}
250
- ],
251
- primaryKey:['quantity', 'unit']
252
- }
253
- var productsTableDef:TableDefinition={
254
- name:'products',
255
- fields:[
256
- {name: 'product' , typeName:'text'},
257
- {name: 'name' , typeName:'text'},
258
- {name: 'price' , typeName:'decimal'},
259
- {name: 'quantity_number' , typeName:'integer'},
260
- {name: 'quantity' , typeName:'text'},
261
- {name: 'unit' , typeName:'text'},
262
- {name: 'units__description' , typeName:'text'}
263
- ],
264
- primaryKey:['product'],
265
- foreignKeys: [{references:'units', fields:[{source:'quantity', target:'quantity'}, {source:'unit', target:'unit'}], displayFields:['description'], alias:'units'}]
266
- }
267
- var volumeUnits:Units[]=[
268
- {quantity:'volume', unit:'ml', description:'millilitre'},
269
- {quantity:'volume', unit:'l', description:'litre'},
270
- {quantity:'volume', unit:'cm3', description:'cubic centimetre'},
271
- {quantity:'volume', unit:'m3', description:'cubic metre'},
272
- ]
273
- var massUnits:Units[]=[
274
- {quantity:'mass', unit:'g', description:'gram'},
275
- {quantity:'mass', unit:'kg', description:'kilogram'},
276
- {quantity:'mass', unit:'mg', description:'milligram'},
277
- ]
278
- var timeUnits:Units[]=[
279
- {quantity:'time', unit:'s', description:'second'},
280
- {quantity:'time', unit:'m', description:'minute'},
281
- {quantity:'time', unit:'h', description:'hour'},
282
- ]
283
-
284
- var products:Product[]=[
285
- {product:'P11111', name: 'Gaseosa', price:35.50, quantity_number: 750, quantity: 'volume', unit: 'cm3', units__description: 'cubic centimetre'},
286
- {product:'P22222', name: 'Naranjas', price:25, quantity_number: 1, quantity: 'mass', unit: 'kg', units__description: 'kilogram'},
287
- {product:'P33333', name: 'Pelicula', price:150, quantity_number: 1.5, quantity: 'time', unit: 'h', units__description: 'hour'},
288
- ]
289
- var units=volumeUnits.concat(massUnits).concat(timeUnits);
290
- before("",async function(){
291
- await ldb.registerStructure(unitsTableDef);
292
- await ldb.registerStructure(productsTableDef);
293
- await ldb.putMany("units", units);
294
- await ldb.putMany("products", products);
295
- })
296
- it("get product and change unit", async function(){
297
- var myProduct=await ldb.getOne<Product>("products", ["P11111"]);
298
- myProduct.unit = 'ml';
299
- var myChangedProduct = await ldb.putOne("products", myProduct);
300
- compare(myChangedProduct, changing(products[0],{unit:'ml', units__description:'millilitre'}));
301
- })
302
- })
303
- });
304
-
305
-
306
- //
307
- //describe("local-db-transaction", function(){
308
- // /** @type {(callback:(ldb:any)=>Promise<T>)=>Promise<T>} */
309
- // var inLdb;
310
- // var tableDef;
311
- // var tableDef2;
312
- // var tableDef3;
313
- // var databaseName: string;
314
- // before(function(){
315
- // databaseName = "the-test-name"+Math.random();
316
- // inLdb = new LocalDbTransaction(databaseName).getBindedInTransaction();
317
- // tableDef={
318
- // name:'this_name',
319
- // fields:[
320
- // {name: 'pk1', typeName:'text'}
321
- // ],
322
- // primaryKey:['pk1']
323
- // };
324
- // tableDef2={
325
- // name:'other_name',
326
- // fields:[
327
- // {name: 'pk2', typeName:'text'}
328
- // ],
329
- // primaryKey:['pk2']
330
- // };
331
- // tableDef3={
332
- // name:'another_name',
333
- // fields:[
334
- // {name: 'pk3', typeName:'text'}
335
- // ],
336
- // primaryKey:['pk3']
337
- // };
338
- // });
339
- // describe("structures", function(){
340
- // it("put and get structure", async function(){
341
- // this.timeout(10000);
342
- // var structure = await inLdb(async function(ldb){
343
- // await ldb.registerStructure(tableDef);
344
- // return ldb.getStructure(tableDef.name)
345
- // });
346
- // compare(tableDef,structure);
347
- // });
348
- // it("drop database and put structure", async function(){
349
- // this.timeout(10000);
350
- // await LocalDb.deleteDatabase(databaseName);
351
- // var structure = await inLdb(async function(ldb){
352
- // await ldb.registerStructure(tableDef);
353
- // return ldb.getStructure(tableDef.name)
354
- // });
355
- // compare(tableDef,structure);
356
- // });
357
- // it("drop database and put a collection of structures", async function(){
358
- // this.timeout(10000);
359
- // var structures = [tableDef, tableDef2, tableDef3]
360
- // await LocalDb.deleteDatabase(databaseName);
361
- // var registeredStructs = await inLdb(async function(ldb){
362
- // var promiseChain=Promise.resolve();
363
- // structures.forEach(async function(structureToRegister){
364
- // promiseChain = promiseChain.then(function(){
365
- // return ldb.registerStructure(structureToRegister);
366
- // });
367
- // });
368
- // promiseChain = promiseChain.then(async function(){
369
- // var struct = await ldb.getStructure(tableDef.name);
370
- // var struct2 = await ldb.getStructure(tableDef2.name);
371
- // var struct3 = await ldb.getStructure(tableDef3.name);
372
- // return [struct,struct2,struct3]
373
- // });
374
- // return promiseChain;
375
- // });
376
- // compare(tableDef,registeredStructs[0]);
377
- // compare(tableDef2,registeredStructs[1]);
378
- // compare(tableDef3,registeredStructs[2]);
379
- // });
380
- // });
381
- //});