backend-plus 2.5.2-betha.7 → 2.5.2-betha.9

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.
@@ -172,6 +172,10 @@ export type SequenceDefinition = {
172
172
  name:string
173
173
  firstValue:number
174
174
  prefix?:string /* Prefix for the generated value */
175
+ }
176
+ export type SequenceMadMaxDefinition = {
177
+ madMax: string[] // grouping of mad max sequences
178
+ firstValue: number
175
179
  }
176
180
  export type ExportMetadataDefinition={ /* TODO: define */ }
177
181
  export type PostInputOptions='upperSpanish' | 'upperWithoutDiacritics' | 'parseDecimal'
@@ -218,15 +222,21 @@ export type FieldDefinition = EditableDbDefinition & {
218
222
  alwaysShow?:boolean /* show when appears in fixed fields */
219
223
  suggestingKeys?:string[]
220
224
  postInput?:PostInputOptions
221
- } & ({
222
- sequence?: undefined
223
- nullable?: boolean
224
- editable?: boolean
225
- } | {
226
- sequence: SequenceDefinition
227
- nullable: true
228
- editable: false
229
- });
225
+ } & (
226
+ {
227
+ sequence?: undefined
228
+ nullable?: boolean
229
+ editable?: boolean
230
+ } | {
231
+ sequence: SequenceDefinition
232
+ nullable: true
233
+ editable: false
234
+ } | {
235
+ sequence: SequenceMadMaxDefinition
236
+ nullable: true
237
+ editable: boolean
238
+ }
239
+ );
230
240
  export type EditableDbDefinition = {
231
241
  editable?:boolean
232
242
  allow?:{
@@ -20,6 +20,7 @@ MiniTools.globalOpts.serveErr.propertiesWhiteList=['message','detail','code','ta
20
20
  var crypto = require('crypto');
21
21
  var serveContent = require('serve-content');
22
22
  var pg = require('pg-promise-strict');
23
+ var pgTriggers = require('pg-triggers');
23
24
  var SessionFileStore = require('session-file-store');
24
25
  var memorystore = require('memorystore');
25
26
  var jsToHtml=require('js-to-html');
@@ -2653,7 +2654,16 @@ AppBackend.prototype.dumpFkConstraint = function dumpFkConstraint(fk, tableDef,
2653
2654
  return {consName, clause, sourceFieldList};
2654
2655
  }
2655
2656
 
2657
+ AppBackend.prototype.isGeneratedSequence = function isGeneratedSequence(sequence, not){
2658
+ return sequence && ((!sequence.name && !sequence.madMax) == !not)
2659
+ }
2660
+
2661
+ AppBackend.prototype.isSequenceNonGenerated = function isSequenceNonGenerated(sequence){
2662
+ return this.isGeneratedSequence(sequence, true);
2663
+ }
2664
+
2656
2665
  AppBackend.prototype.dumpDbTableFields = function dumpDbTableFields(tableDef, opts = {}, complements = null){
2666
+ var be = this;
2657
2667
  var db = this.db;
2658
2668
  var fields=[];
2659
2669
  tableDef.fields.forEach(function(fieldDef){
@@ -2667,7 +2677,7 @@ AppBackend.prototype.dumpDbTableFields = function dumpDbTableFields(tableDef, op
2667
2677
  ' '+(fieldDef.dataLength?(fieldType=='text'?'varchar':fieldType)+'('+fieldDef.dataLength+')':fieldType)+
2668
2678
  (fieldDef.defaultValue!=null?' default '+db.quoteLiteral(fieldDef.defaultValue):'')+
2669
2679
  (fieldDef.defaultDbValue!=null?' default '+fieldDef.defaultDbValue:'')+
2670
- (fieldDef.sequence && !fieldDef.sequence.name?' generated always as identity':'')+
2680
+ (be.isGeneratedSequence(fieldDef.sequence)?' generated always as identity':'')+
2671
2681
  (fieldDef.generatedAs!=null?` generated always as (${fieldDef.generatedAs}) stored`:'')
2672
2682
  );
2673
2683
  if(complements){
@@ -2774,7 +2784,7 @@ AppBackend.prototype.dumpDbSchemaPartial = async function dumpDbSchemaPartial(pa
2774
2784
  lines.push('create table '+cualQuoteTableName+' (');
2775
2785
  var fields = be.dumpDbTableFields(tableDef, opts,
2776
2786
  function complements(fieldDef){
2777
- if(fieldDef.sequence && !fieldDef.sequence.name){
2787
+ if(be.isGeneratedSequence(fieldDef.sequence)){
2778
2788
  tablesWithStrictSequence[tableName]={}
2779
2789
  }
2780
2790
  if(fieldDef.typeName==='text' && !fieldDef.allowEmptyText){
@@ -2798,7 +2808,7 @@ AppBackend.prototype.dumpDbSchemaPartial = async function dumpDbSchemaPartial(pa
2798
2808
  ' alter column '+db.quoteIdent(fieldDef.name)+' set not null;'
2799
2809
  );
2800
2810
  }
2801
- if(fieldDef.sequence && fieldDef.sequence.name){
2811
+ if(be.isSequenceNonGenerated(fieldDef.sequence)){
2802
2812
  fieldsForSequences.push(fieldDef);
2803
2813
  }
2804
2814
  }
@@ -2901,19 +2911,26 @@ AppBackend.prototype.dumpDbSchemaPartial = async function dumpDbSchemaPartial(pa
2901
2911
  });
2902
2912
  lines.push(tableDef.sql.postCreateSqls);
2903
2913
  lines.push('');
2904
- fieldsForSequences.forEach(function(fieldDef) {
2914
+ await Promise.all(fieldsForSequences.map(async function(fieldDef) {
2905
2915
  var sequence = fieldDef.sequence;
2906
- lines.push("CREATE SEQUENCE "+db.quoteIdent(sequence.name)+" START "+db.quoteInteger(sequence.firstValue||1)+";");
2907
- lines.push(
2908
- "ALTER TABLE "+cualQuoteTableName+
2909
- " ALTER COLUMN "+db.quoteIdent(fieldDef.name)+
2910
- (sequence.prefix==null
2911
- ?" SET DEFAULT nextval("+db.quoteLiteral(sequence.name)+"::regclass);"
2912
- :" SET DEFAULT ("+db.quoteLiteral(sequence.prefix)+" || nextval("+db.quoteLiteral(sequence.name)+"::regclass)::text);"
2913
- )
2914
- );
2915
- lines.push('GRANT USAGE, SELECT ON SEQUENCE '+db.quoteIdent(sequence.name)+' TO '+user+';');
2916
- });
2916
+ if (sequence.name) {
2917
+ if (sequence.madMax) throw new Error('a sequence with madMax cannot have name');
2918
+ lines.push("CREATE SEQUENCE "+db.quoteIdent(sequence.name)+" START "+db.quoteInteger(sequence.firstValue||1)+";");
2919
+ lines.push(
2920
+ "ALTER TABLE "+cualQuoteTableName+
2921
+ " ALTER COLUMN "+db.quoteIdent(fieldDef.name)+
2922
+ (sequence.prefix==null
2923
+ ?" SET DEFAULT nextval("+db.quoteLiteral(sequence.name)+"::regclass);"
2924
+ :" SET DEFAULT ("+db.quoteLiteral(sequence.prefix)+" || nextval("+db.quoteLiteral(sequence.name)+"::regclass)::text);"
2925
+ )
2926
+ );
2927
+ lines.push('GRANT USAGE, SELECT ON SEQUENCE '+db.quoteIdent(sequence.name)+' TO '+user+';');
2928
+ } else if (sequence.madMax) {
2929
+ lines.push(await pgTriggers.dumpMaxIdTrigger(tableDef.sql.tableName, fieldDef.name, {grouping: sequence.madMax.grouping, firstValue: sequence.firstValue}));
2930
+ } else {
2931
+ throw new Error('a sequence without madMax nor name');
2932
+ }
2933
+ }));
2917
2934
  lines.push('');
2918
2935
  if(tableDef.sql.policies.enabled){
2919
2936
  policyLines.push(`ALTER TABLE ${cualQuoteTableName} ENABLE ROW LEVEL SECURITY;`);
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.5.2-betha.7",
4
+ "version": "2.5.2-betha.9",
5
5
  "author": "Codenautas <codenautas@googlegroups.com>",
6
6
  "license": "MIT",
7
7
  "repository": "codenautas/backend-plus",
@@ -35,13 +35,13 @@
35
35
  "best-globals": "^2.0.1",
36
36
  "big.js": "^7.0.1",
37
37
  "body-parser": "^2.2.0",
38
- "cast-error": "^0.1.1",
38
+ "cast-error": "^0.1.2",
39
39
  "castellano": "^0.1.4",
40
40
  "connect-pg-simple": "^10.0.0",
41
41
  "cookie-parser": "^1.4.7",
42
42
  "cors": "^2.8.5",
43
- "dialog-promise": "^0.10.1",
44
- "discrepances": "^0.2.8",
43
+ "dialog-promise": "^0.10.2",
44
+ "discrepances": "^0.2.9",
45
45
  "express": "^5.1.0",
46
46
  "express-session": "^1.18.1",
47
47
  "express-useragent": "^1.0.15",
@@ -51,14 +51,15 @@
51
51
  "json4all": "^1.4.0",
52
52
  "lazy-some": "^0.1.0",
53
53
  "like-ar": "^0.5.1",
54
- "login-plus": "^1.7.2",
54
+ "login-plus": "^1.7.3",
55
55
  "memorystore": "^1.6.7",
56
- "mini-tools": "^1.13.2",
56
+ "mini-tools": "^1.13.3",
57
57
  "moment": "^2.30.1",
58
58
  "multiparty": "^4.2.3",
59
59
  "nodemailer": "^7.0.3",
60
60
  "numeral": "^2.0.6",
61
- "pg-promise-strict": "^1.4.2",
61
+ "pg-promise-strict": "^1.4.3",
62
+ "pg-triggers": "0.4.3",
62
63
  "pikaday": "^1.8.2",
63
64
  "pug": "^3.0.3",
64
65
  "read-yaml-promise": "^1.0.2",
@@ -77,13 +78,13 @@
77
78
  "devDependencies": {
78
79
  "@types/big.js": "^6.2.2",
79
80
  "@types/expect.js": "~0.3.32",
80
- "@types/express": "^5.0.2",
81
+ "@types/express": "^5.0.3",
81
82
  "@types/express-useragent": "^1.0.5",
82
83
  "@types/fs-extra": "^11.0.4",
83
84
  "@types/js-yaml": "^4.0.9",
84
85
  "@types/mocha": "^10.0.10",
85
86
  "@types/multiparty": "~4.2.1",
86
- "@types/node": "^22.15.29",
87
+ "@types/node": "^24.0.3",
87
88
  "@types/nodemailer": "^6.4.17",
88
89
  "@types/numeral": "~2.0.5",
89
90
  "@types/session-file-store": "^1.2.5",
@@ -98,10 +99,10 @@
98
99
  "karma-ie-launcher": "^1.0.0",
99
100
  "karma-mocha": "^2.0.1",
100
101
  "kill-9": "~0.4.3",
101
- "mocha": "^11.5.0",
102
+ "mocha": "^11.7.0",
102
103
  "nyc": "^17.1.0",
103
- "puppeteer": "^24.9.0",
104
- "sinon": "^20.0.0",
104
+ "puppeteer": "^24.10.2",
105
+ "sinon": "^21.0.0",
105
106
  "supertest": "^7.1.1",
106
107
  "types.d.ts": "~0.6.22",
107
108
  "typescript": "^5.8.3",