prostgles-server 2.0.29 → 2.0.33
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/dist/DboBuilder.js +8 -6
- package/dist/DboBuilder.js.map +1 -1
- package/dist/FileManager.d.ts +3 -1
- package/dist/FileManager.d.ts.map +1 -1
- package/dist/FileManager.js +45 -30
- package/dist/FileManager.js.map +1 -1
- package/dist/Prostgles.d.ts.map +1 -1
- package/dist/Prostgles.js +23 -2
- package/dist/Prostgles.js.map +1 -1
- package/dist/TableConfig.d.ts +35 -22
- package/dist/TableConfig.d.ts.map +1 -1
- package/dist/TableConfig.js +46 -19
- package/dist/TableConfig.js.map +1 -1
- package/lib/DboBuilder.ts +6 -6
- package/lib/FileManager.ts +52 -34
- package/lib/Prostgles.ts +25 -2
- package/lib/TableConfig.ts +96 -48
- package/package.json +1 -1
- package/tests/client_only_queries.js +2 -0
- package/tests/client_only_queries.ts +2 -0
- package/tests/config_test/DBoGenerated.d.ts +55 -82
- package/tests/config_test/index.html +6 -6
- package/tests/config_test/index.js +8 -5
- package/tests/config_test/index.js.map +1 -1
- package/tests/config_test/index.ts +8 -5
- package/tests/server/DBoGenerated.d.ts +0 -48
- package/tests/server/index.js +1 -1
- package/tests/server/index.ts +1 -1
- package/tests/server/media/{2a918e4d-828a-432c-a957-73725e3f79b8.txt → 1695f83b-1cee-4521-80f6-a1c7493c4a9a.txt} +0 -0
- package/tests/server/media/{783b7949-da93-4295-a463-c70731255e8a.txt → 299a1da2-bf86-4762-8702-4d669a81aa50.txt} +0 -0
- package/tests/server/media/{94d77b01-dbf0-4626-aa7f-b1959f43932d.txt → be751807-88e9-433a-bddb-db9917f46807.txt} +0 -0
- package/tests/server/media/{a5e41c3f-3098-4934-a394-82ddc1e4de04.txt → dfbe8a90-9146-468c-a0cc-c3e7d49bc25d.txt} +0 -0
- package/tests/server/package-lock.json +1 -1
package/dist/TableConfig.js
CHANGED
|
@@ -32,23 +32,29 @@ class TableConfigurator {
|
|
|
32
32
|
}
|
|
33
33
|
};
|
|
34
34
|
this.config = prostgles.opts.tableConfig;
|
|
35
|
-
this.dbo = prostgles.dbo;
|
|
36
|
-
this.db = prostgles.db;
|
|
37
35
|
this.prostgles = prostgles;
|
|
38
36
|
}
|
|
37
|
+
get dbo() { return this.prostgles.dbo; }
|
|
38
|
+
;
|
|
39
|
+
get db() { return this.prostgles.db; }
|
|
40
|
+
;
|
|
39
41
|
init() {
|
|
40
42
|
return __awaiter(this, void 0, void 0, function* () {
|
|
41
43
|
let queries = [];
|
|
42
44
|
/* Create lookup tables */
|
|
43
45
|
Object.keys(this.config).map(tableName => {
|
|
44
|
-
var _a, _b, _c
|
|
46
|
+
var _a, _b, _c;
|
|
45
47
|
const tableConf = this.config[tableName];
|
|
48
|
+
const { dropIfExists = false, dropIfExistsCascade = false } = tableConf;
|
|
49
|
+
if (dropIfExistsCascade) {
|
|
50
|
+
queries.push(`DROP TABLE IF EXISTS ${tableName} CASCADE;`);
|
|
51
|
+
}
|
|
52
|
+
else if (dropIfExists) {
|
|
53
|
+
queries.push(`DROP TABLE IF EXISTS ${tableName} ;`);
|
|
54
|
+
}
|
|
46
55
|
if ("isLookupTable" in tableConf && Object.keys((_a = tableConf.isLookupTable) === null || _a === void 0 ? void 0 : _a.values).length) {
|
|
47
56
|
const rows = Object.keys((_b = tableConf.isLookupTable) === null || _b === void 0 ? void 0 : _b.values).map(id => { var _a; return (Object.assign({ id }, ((_a = tableConf.isLookupTable) === null || _a === void 0 ? void 0 : _a.values[id]))); });
|
|
48
|
-
if ((_c =
|
|
49
|
-
queries.push(`DROP TABLE IF EXISTS ${tableName} CASCADE;`);
|
|
50
|
-
}
|
|
51
|
-
if (((_d = tableConf.isLookupTable) === null || _d === void 0 ? void 0 : _d.dropIfExists) || !((_e = this.dbo) === null || _e === void 0 ? void 0 : _e[tableName])) {
|
|
57
|
+
if (dropIfExists || !((_c = this.dbo) === null || _c === void 0 ? void 0 : _c[tableName])) {
|
|
52
58
|
const keys = Object.keys(rows[0]).filter(k => k !== "id");
|
|
53
59
|
queries.push(`CREATE TABLE IF NOT EXISTS ${tableName} (
|
|
54
60
|
id TEXT PRIMARY KEY
|
|
@@ -70,23 +76,44 @@ class TableConfigurator {
|
|
|
70
76
|
yield Promise.all(Object.keys(this.config).map((tableName) => __awaiter(this, void 0, void 0, function* () {
|
|
71
77
|
const tableConf = this.config[tableName];
|
|
72
78
|
if ("columns" in tableConf) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
const getColDef = (name, colConf) => {
|
|
80
|
+
if ("references" in colConf && colConf.references) {
|
|
81
|
+
const { nullable, tableName: lookupTable, columnName: lookupCol = "id", defaultValue } = colConf.references;
|
|
82
|
+
return ` ${prostgles_types_1.asName(name)} TEXT ${!nullable ? " NOT NULL " : ""} ${defaultValue ? ` DEFAULT ${PubSubManager_1.asValue(defaultValue)} ` : ""} REFERENCES ${lookupTable} (${lookupCol}) `;
|
|
83
|
+
}
|
|
84
|
+
else if ("sqlDefinition" in colConf && colConf.sqlDefinition) {
|
|
85
|
+
return ` ${prostgles_types_1.asName(name)} ${colConf.sqlDefinition} `;
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
const colDefs = [];
|
|
89
|
+
Object.keys(tableConf.columns).map(colName => {
|
|
90
|
+
const colConf = tableConf.columns[colName];
|
|
91
|
+
if (!this.dbo[tableName]) {
|
|
92
|
+
colDefs.push(getColDef(colName, colConf));
|
|
93
|
+
}
|
|
94
|
+
else if (!this.dbo[tableName].columns.find(c => colName === c.name)) {
|
|
95
|
+
if ("references" in colConf && colConf.references) {
|
|
96
|
+
const { tableName: lookupTable, } = colConf.references;
|
|
81
97
|
queries.push(`
|
|
82
98
|
ALTER TABLE ${prostgles_types_1.asName(tableName)}
|
|
83
|
-
ADD COLUMN ${
|
|
84
|
-
${defaultValue ? ` DEFAULT ${PubSubManager_1.asValue(defaultValue)} ` : ""}
|
|
85
|
-
REFERENCES ${lookupTable} (${lookupCol}) ;
|
|
99
|
+
ADD COLUMN ${getColDef(colName, colConf)};
|
|
86
100
|
`);
|
|
87
101
|
console.log(`TableConfigurator: ${tableName}(${colName})` + " referenced lookup table " + lookupTable);
|
|
88
102
|
}
|
|
89
|
-
|
|
103
|
+
else if ("sqlDefinition" in colConf && colConf.sqlDefinition) {
|
|
104
|
+
queries.push(`
|
|
105
|
+
ALTER TABLE ${prostgles_types_1.asName(tableName)}
|
|
106
|
+
ADD COLUMN ${getColDef(colName, colConf)};
|
|
107
|
+
`);
|
|
108
|
+
console.log(`TableConfigurator: created/added column ${tableName}(${colName}) ` + colConf.sqlDefinition);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
if (colDefs.length) {
|
|
113
|
+
queries.push(`CREATE TABLE ${prostgles_types_1.asName(tableName)} (
|
|
114
|
+
${colDefs.join(", \n")}
|
|
115
|
+
);`);
|
|
116
|
+
console.error("TableConfigurator: Created table: \n" + queries[0]);
|
|
90
117
|
}
|
|
91
118
|
}
|
|
92
119
|
})));
|
package/dist/TableConfig.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableConfig.js","sourceRoot":"","sources":["../lib/TableConfig.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,qDAAoD;AAIpD,mDAA0C;
|
|
1
|
+
{"version":3,"file":"TableConfig.js","sourceRoot":"","sources":["../lib/TableConfig.ts"],"names":[],"mappings":"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"}
|
package/lib/DboBuilder.ts
CHANGED
|
@@ -628,11 +628,11 @@ export class ViewHandler {
|
|
|
628
628
|
let _lang = lang;
|
|
629
629
|
let columns = this.columns
|
|
630
630
|
.filter(c => {
|
|
631
|
-
const { insert, select, update } = p;
|
|
631
|
+
const { insert, select, update } = p || {};
|
|
632
632
|
return [
|
|
633
|
-
...insert
|
|
634
|
-
...select
|
|
635
|
-
...update
|
|
633
|
+
...(insert?.fields || []),
|
|
634
|
+
...(select?.fields || []),
|
|
635
|
+
...(update?.fields || []),
|
|
636
636
|
].includes(c.name)
|
|
637
637
|
})
|
|
638
638
|
.map(c => {
|
|
@@ -779,8 +779,8 @@ export class ViewHandler {
|
|
|
779
779
|
}
|
|
780
780
|
|
|
781
781
|
if(!tableRules.select && !tableRules.update && !tableRules.delete && !tableRules.insert){
|
|
782
|
-
res.getInfo = false;
|
|
783
|
-
res.getColumns = false;
|
|
782
|
+
if([null, false].includes(tableRules.getInfo)) res.getInfo = false;
|
|
783
|
+
if([null, false].includes(tableRules.getColumns)) res.getColumns = false;
|
|
784
784
|
}
|
|
785
785
|
|
|
786
786
|
return res;
|
package/lib/FileManager.ts
CHANGED
|
@@ -6,7 +6,7 @@ import * as fs from 'fs';
|
|
|
6
6
|
import * as FileType from "file-type";
|
|
7
7
|
import * as sharp from "sharp";
|
|
8
8
|
|
|
9
|
-
import { DB, Prostgles } from './Prostgles';
|
|
9
|
+
import { DB, DbHandler, Prostgles } from './Prostgles';
|
|
10
10
|
import { asName, AnyObject } from 'prostgles-types';
|
|
11
11
|
import { TableHandler } from './DboBuilder';
|
|
12
12
|
|
|
@@ -71,6 +71,9 @@ export default class FileManager {
|
|
|
71
71
|
imageOptions: ImageOptions;
|
|
72
72
|
|
|
73
73
|
prostgles: Prostgles;
|
|
74
|
+
get dbo(): DbHandler { return this.prostgles.dbo };
|
|
75
|
+
get db(): DB { return this.prostgles.db };
|
|
76
|
+
|
|
74
77
|
tableName: string;
|
|
75
78
|
|
|
76
79
|
private fileRoute: string;
|
|
@@ -308,8 +311,10 @@ export default class FileManager {
|
|
|
308
311
|
|
|
309
312
|
init = async (prg: Prostgles) => {
|
|
310
313
|
this.prostgles = prg;
|
|
311
|
-
|
|
312
|
-
const {
|
|
314
|
+
|
|
315
|
+
// const { dbo, db, opts } = prg;
|
|
316
|
+
|
|
317
|
+
const { fileTable } = prg.opts;
|
|
313
318
|
const { tableName = "media", referencedTables = {} } = fileTable;
|
|
314
319
|
this.tableName = tableName;
|
|
315
320
|
|
|
@@ -320,43 +325,44 @@ export default class FileManager {
|
|
|
320
325
|
/**
|
|
321
326
|
* 1. Create media table
|
|
322
327
|
*/
|
|
323
|
-
if(!dbo[tableName]){
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
328
|
+
if(!this.dbo[tableName]){
|
|
329
|
+
console.log(`Creating fileTable ${asName(tableName)} ...`);
|
|
330
|
+
await this.db.any(`CREATE EXTENSION IF NOT EXISTS pgcrypto `);
|
|
331
|
+
await this.db.any(`CREATE TABLE IF NOT EXISTS ${asName(tableName)} (
|
|
332
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
333
|
+
name TEXT NOT NULL,
|
|
334
|
+
extension TEXT NOT NULL,
|
|
335
|
+
content_type TEXT NOT NULL,
|
|
336
|
+
url TEXT NOT NULL,
|
|
337
|
+
original_name TEXT NOT NULL,
|
|
338
|
+
|
|
339
|
+
description TEXT,
|
|
340
|
+
s3_url TEXT,
|
|
341
|
+
signed_url TEXT,
|
|
342
|
+
signed_url_expires BIGINT,
|
|
343
|
+
etag TEXT,
|
|
344
|
+
UNIQUE(name)
|
|
345
|
+
)`);
|
|
346
|
+
console.log(`Created fileTable ${asName(tableName)}`);
|
|
347
|
+
await prg.refreshDBO();
|
|
342
348
|
}
|
|
343
349
|
|
|
344
350
|
/**
|
|
345
351
|
* 2. Create media lookup tables
|
|
346
352
|
*/
|
|
347
353
|
await Promise.all(Object.keys(referencedTables).map(async refTable => {
|
|
348
|
-
if(!dbo[refTable]) throw `Referenced table (${refTable}) from fileTable.referencedTables record is missing`;
|
|
354
|
+
if(!this.dbo[refTable]) throw `Referenced table (${refTable}) from fileTable.referencedTables record is missing`;
|
|
349
355
|
// const lookupTableName = asName(`lookup_${tableName}_${refTable}`);
|
|
350
356
|
|
|
351
357
|
const lookupTableName = await this.parseSQLIdentifier(`prostgles_lookup_${tableName}_${refTable}`);
|
|
352
|
-
const pKeyFields = (await (dbo[refTable] as unknown as TableHandler).getColumns()).filter(f => f.is_pkey);
|
|
358
|
+
const pKeyFields = (await (this.dbo[refTable] as unknown as TableHandler).getColumns()).filter(f => f.is_pkey);
|
|
353
359
|
|
|
354
360
|
if(pKeyFields.length !== 1) throw `Could not make link table for ${refTable}. ${pKeyFields} must have exactly one primary key column. Current pkeys: ${pKeyFields.map(f => f.name)}`;
|
|
355
361
|
|
|
356
362
|
const pkField = pKeyFields[0];
|
|
357
363
|
const refType = referencedTables[refTable];
|
|
358
364
|
|
|
359
|
-
if(!dbo[lookupTableName]){
|
|
365
|
+
if(!this.dbo[lookupTableName]){
|
|
360
366
|
// if(!(await dbo[lookupTableName].count())) await db.any(`DROP TABLE IF EXISTS ${lookupTableName};`);
|
|
361
367
|
const action = ` (${tableName} <-> ${refTable}) join table ${lookupTableName}`; // PRIMARY KEY
|
|
362
368
|
const query = `
|
|
@@ -366,11 +372,11 @@ export default class FileManager {
|
|
|
366
372
|
)
|
|
367
373
|
`
|
|
368
374
|
// console.log(`Creating ${action} ...`, lookupTableName);
|
|
369
|
-
await db.any(query);
|
|
375
|
+
await this.db.any(query);
|
|
370
376
|
console.log(`Created ${action}`);
|
|
371
377
|
|
|
372
378
|
} else {
|
|
373
|
-
const cols = await dbo[lookupTableName].getColumns();
|
|
379
|
+
const cols = await this.dbo[lookupTableName].getColumns();
|
|
374
380
|
const badCols = cols.filter(c => !c.references);
|
|
375
381
|
await Promise.all(badCols.map(async badCol => {
|
|
376
382
|
console.error(
|
|
@@ -391,7 +397,7 @@ export default class FileManager {
|
|
|
391
397
|
if(q){
|
|
392
398
|
|
|
393
399
|
try {
|
|
394
|
-
await db.any(q)
|
|
400
|
+
await this.db.any(q)
|
|
395
401
|
console.log("Added missing constraint back");
|
|
396
402
|
|
|
397
403
|
} catch(e){
|
|
@@ -402,6 +408,7 @@ export default class FileManager {
|
|
|
402
408
|
}));
|
|
403
409
|
}
|
|
404
410
|
|
|
411
|
+
await prg.refreshDBO();
|
|
405
412
|
return true;
|
|
406
413
|
}));
|
|
407
414
|
|
|
@@ -417,21 +424,32 @@ export default class FileManager {
|
|
|
417
424
|
|
|
418
425
|
if(app){
|
|
419
426
|
app.get(this.fileRoute + "/:name", async (req, res) => {
|
|
420
|
-
if(!dbo[tableName]){
|
|
421
|
-
res.status(500).json({ err:
|
|
427
|
+
if(!this.dbo[tableName]){
|
|
428
|
+
res.status(500).json({ err: `Internal error: media table (${tableName}) not valid` });
|
|
422
429
|
return false;
|
|
423
430
|
}
|
|
424
431
|
|
|
425
|
-
const mediaTable = dbo[tableName] as unknown as TableHandler;
|
|
432
|
+
const mediaTable = this.dbo[tableName] as unknown as TableHandler;
|
|
426
433
|
|
|
427
434
|
try {
|
|
428
435
|
|
|
429
436
|
const { name } = req.params;
|
|
430
|
-
if(typeof name !== "string") throw "Invalid media name";
|
|
437
|
+
if(typeof name !== "string" || !name) throw "Invalid media name";
|
|
431
438
|
|
|
432
439
|
const media = await mediaTable.findOne({ name }, { select: { id: 1, name: 1, signed_url: 1, signed_url_expires: 1, content_type: 1 } }, { httpReq: req });
|
|
433
440
|
|
|
434
|
-
if(!media)
|
|
441
|
+
if(!media) {
|
|
442
|
+
/**
|
|
443
|
+
* Redirect to login !??
|
|
444
|
+
*/
|
|
445
|
+
// const mediaExists = await mediaTable.count({ name });
|
|
446
|
+
// if(mediaExists && this.prostgles.authHandler){
|
|
447
|
+
|
|
448
|
+
// } else {
|
|
449
|
+
// throw "Invalid media";
|
|
450
|
+
// }
|
|
451
|
+
throw "Invalid media";
|
|
452
|
+
}
|
|
435
453
|
|
|
436
454
|
if(this.s3Client){
|
|
437
455
|
let url = media.signed_url;
|
|
@@ -454,7 +472,7 @@ export default class FileManager {
|
|
|
454
472
|
|
|
455
473
|
} catch(e){
|
|
456
474
|
console.log(e)
|
|
457
|
-
res.status(404).json({ err: "Invalid media" });
|
|
475
|
+
res.status(404).json({ err: "Invalid/missing media" });
|
|
458
476
|
}
|
|
459
477
|
});
|
|
460
478
|
}
|
package/lib/Prostgles.ts
CHANGED
|
@@ -1062,6 +1062,20 @@ type DboTableCommand = Request & DboTable & {
|
|
|
1062
1062
|
// const insertParams: Array<keyof InsertRule> = ["fields", "forcedData", "returningFields", "validate"];
|
|
1063
1063
|
|
|
1064
1064
|
const RULE_TO_METHODS = [
|
|
1065
|
+
{
|
|
1066
|
+
rule: "getColumns",
|
|
1067
|
+
methods: ["getColumns"],
|
|
1068
|
+
no_limits: true,
|
|
1069
|
+
allowed_params: [],
|
|
1070
|
+
hint: ` expecting false | true | undefined`
|
|
1071
|
+
},
|
|
1072
|
+
{
|
|
1073
|
+
rule: "getInfo",
|
|
1074
|
+
methods: ["getInfo"],
|
|
1075
|
+
no_limits: true,
|
|
1076
|
+
allowed_params: [],
|
|
1077
|
+
hint: ` expecting false | true | undefined`
|
|
1078
|
+
},
|
|
1065
1079
|
{
|
|
1066
1080
|
rule: "insert",
|
|
1067
1081
|
methods: ["insert", "upsert"],
|
|
@@ -1080,7 +1094,7 @@ const RULE_TO_METHODS = [
|
|
|
1080
1094
|
},
|
|
1081
1095
|
{
|
|
1082
1096
|
rule: "select",
|
|
1083
|
-
methods: ["findOne", "find", "count"
|
|
1097
|
+
methods: ["findOne", "find", "count"],
|
|
1084
1098
|
no_limits: <SelectRule>{ fields: "*", filterFields: "*" },
|
|
1085
1099
|
allowed_params: <Array<keyof SelectRule>>["fields", "filterFields", "forcedFilter", "validate", "maxLimit"] ,
|
|
1086
1100
|
hint: ` expecting "*" | true | { fields: ( string | string[] | {} ) }`
|
|
@@ -1256,13 +1270,21 @@ export class PublishParser {
|
|
|
1256
1270
|
// if(tableName === "various") console.warn(1042, table_rules)
|
|
1257
1271
|
}
|
|
1258
1272
|
|
|
1259
|
-
/* Add implied
|
|
1273
|
+
/* Add missing implied rules */
|
|
1260
1274
|
MY_RULES.map(r => {
|
|
1261
1275
|
|
|
1276
|
+
if(["getInfo", "getColumns"].includes(r.rule) && ![null, false, 0].includes(table_rules[r.rule])){
|
|
1277
|
+
table_rules[r.rule] = r.no_limits;
|
|
1278
|
+
return ;
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
/* Add nested properties for fully allowed rules */
|
|
1262
1282
|
if ([true, "*"].includes(table_rules[r.rule]) && r.no_limits) {
|
|
1263
1283
|
table_rules[r.rule] = Object.assign({}, r.no_limits);
|
|
1264
1284
|
}
|
|
1285
|
+
|
|
1265
1286
|
if(table_rules[r.rule]){
|
|
1287
|
+
/* Add implied methods if not falsy */
|
|
1266
1288
|
r.methods.map(method => {
|
|
1267
1289
|
if(table_rules[method] === undefined){
|
|
1268
1290
|
const publishedTable = (table_rules as PublishTable);
|
|
@@ -1365,6 +1387,7 @@ export class PublishParser {
|
|
|
1365
1387
|
|
|
1366
1388
|
const table_rules = await this.getTableRules({ localParams: {socket}, tableName }, clientInfo);
|
|
1367
1389
|
|
|
1390
|
+
// if(tableName === "insert_rule") throw {table_rules}
|
|
1368
1391
|
if(table_rules && Object.keys(table_rules).length){
|
|
1369
1392
|
schema[tableName] = {};
|
|
1370
1393
|
let methods = [];
|
package/lib/TableConfig.ts
CHANGED
|
@@ -10,9 +10,13 @@ type ColExtraInfo = {
|
|
|
10
10
|
hint?: string;
|
|
11
11
|
};
|
|
12
12
|
|
|
13
|
+
type BaseTableDefinition = {
|
|
14
|
+
dropIfExistsCascade?: boolean;
|
|
15
|
+
dropIfExists?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
13
18
|
type LookupTableDefinition<LANG_IDS> = {
|
|
14
19
|
isLookupTable: {
|
|
15
|
-
dropIfExists?: boolean;
|
|
16
20
|
values: {
|
|
17
21
|
[id_value: string]: {} | {
|
|
18
22
|
[lang_id in keyof LANG_IDS]: string
|
|
@@ -21,31 +25,46 @@ type LookupTableDefinition<LANG_IDS> = {
|
|
|
21
25
|
}
|
|
22
26
|
}
|
|
23
27
|
|
|
28
|
+
type BaseColumn = {
|
|
29
|
+
/**
|
|
30
|
+
* Will add these values to .getColumns() result
|
|
31
|
+
*/
|
|
32
|
+
info?: ColExtraInfo;
|
|
33
|
+
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
type SQLDefColumn = {
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Raw sql statement used in creating/adding column
|
|
40
|
+
*/
|
|
41
|
+
sqlDefinition?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
type ReferencedColumn = {
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Will create a lookup table that this column will reference
|
|
48
|
+
*/
|
|
49
|
+
references?: {
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
tableName: string;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Defaults to id
|
|
56
|
+
*/
|
|
57
|
+
columnName?: string;
|
|
58
|
+
defaultValue?: string;
|
|
59
|
+
nullable?: boolean;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
type ColumnConfig = BaseColumn & (SQLDefColumn | ReferencedColumn)
|
|
64
|
+
|
|
24
65
|
type TableDefinition = {
|
|
25
66
|
columns: {
|
|
26
|
-
[column_name: string]:
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Will add these values to .getColumns() result
|
|
30
|
-
*/
|
|
31
|
-
info?: ColExtraInfo;
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Will create a lookup table that this column will reference
|
|
35
|
-
*/
|
|
36
|
-
references?: {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
tableName: string;
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Defaults to id
|
|
43
|
-
*/
|
|
44
|
-
columnName?: string;
|
|
45
|
-
defaultValue?: string;
|
|
46
|
-
nullable?: boolean;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
67
|
+
[column_name: string]: ColumnConfig
|
|
49
68
|
}
|
|
50
69
|
}
|
|
51
70
|
|
|
@@ -53,7 +72,7 @@ type TableDefinition = {
|
|
|
53
72
|
* Helper utility to create lookup tables for TEXT columns
|
|
54
73
|
*/
|
|
55
74
|
export type TableConfig<LANG_IDS = { en: 1, ro: 1 }> = {
|
|
56
|
-
[table_name: string]: TableDefinition | LookupTableDefinition<LANG_IDS
|
|
75
|
+
[table_name: string]: BaseTableDefinition & (TableDefinition | LookupTableDefinition<LANG_IDS>);
|
|
57
76
|
}
|
|
58
77
|
|
|
59
78
|
/**
|
|
@@ -62,15 +81,13 @@ export type TableConfig<LANG_IDS = { en: 1, ro: 1 }> = {
|
|
|
62
81
|
export default class TableConfigurator {
|
|
63
82
|
|
|
64
83
|
config?: TableConfig;
|
|
65
|
-
dbo: DbHandler;
|
|
66
|
-
db: DB;
|
|
84
|
+
get dbo(): DbHandler { return this.prostgles.dbo };
|
|
85
|
+
get db(): DB { return this.prostgles.db };
|
|
67
86
|
sidKeyName: string;
|
|
68
87
|
prostgles: Prostgles
|
|
69
88
|
|
|
70
89
|
constructor(prostgles: Prostgles){
|
|
71
90
|
this.config = prostgles.opts.tableConfig;
|
|
72
|
-
this.dbo = prostgles.dbo;
|
|
73
|
-
this.db = prostgles.db;
|
|
74
91
|
this.prostgles = prostgles;
|
|
75
92
|
}
|
|
76
93
|
|
|
@@ -94,12 +111,15 @@ export default class TableConfigurator {
|
|
|
94
111
|
/* Create lookup tables */
|
|
95
112
|
Object.keys(this.config).map(tableName => {
|
|
96
113
|
const tableConf = this.config[tableName];
|
|
114
|
+
const { dropIfExists = false, dropIfExistsCascade = false } = tableConf;
|
|
115
|
+
if(dropIfExistsCascade){
|
|
116
|
+
queries.push(`DROP TABLE IF EXISTS ${tableName} CASCADE;`);
|
|
117
|
+
} else if(dropIfExists){
|
|
118
|
+
queries.push(`DROP TABLE IF EXISTS ${tableName} ;`);
|
|
119
|
+
}
|
|
97
120
|
if("isLookupTable" in tableConf && Object.keys(tableConf.isLookupTable?.values).length){
|
|
98
|
-
const rows = Object.keys(tableConf.isLookupTable?.values).map(id => ({ id, ...(tableConf.isLookupTable?.values[id]) }))
|
|
99
|
-
if(
|
|
100
|
-
queries.push(`DROP TABLE IF EXISTS ${tableName} CASCADE;`);
|
|
101
|
-
}
|
|
102
|
-
if(tableConf.isLookupTable?.dropIfExists || !this.dbo?.[tableName]){
|
|
121
|
+
const rows = Object.keys(tableConf.isLookupTable?.values).map(id => ({ id, ...(tableConf.isLookupTable?.values[id]) }));
|
|
122
|
+
if(dropIfExists || !this.dbo?.[tableName]){
|
|
103
123
|
const keys = Object.keys(rows[0]).filter(k => k !== "id");
|
|
104
124
|
queries.push(`CREATE TABLE IF NOT EXISTS ${tableName} (
|
|
105
125
|
id TEXT PRIMARY KEY
|
|
@@ -124,25 +144,53 @@ export default class TableConfigurator {
|
|
|
124
144
|
await Promise.all(Object.keys(this.config).map(async tableName => {
|
|
125
145
|
const tableConf = this.config[tableName];
|
|
126
146
|
if("columns" in tableConf){
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
147
|
+
const getColDef = (name: string, colConf: ColumnConfig): string => {
|
|
148
|
+
|
|
149
|
+
if("references" in colConf && colConf.references){
|
|
150
|
+
|
|
151
|
+
const { nullable, tableName: lookupTable, columnName: lookupCol = "id", defaultValue } = colConf.references;
|
|
152
|
+
return ` ${asName(name)} TEXT ${!nullable? " NOT NULL " : ""} ${defaultValue? ` DEFAULT ${asValue(defaultValue)} ` : "" } REFERENCES ${lookupTable} (${lookupCol}) `;
|
|
153
|
+
|
|
154
|
+
} else if("sqlDefinition" in colConf && colConf.sqlDefinition){
|
|
133
155
|
|
|
134
|
-
|
|
135
|
-
|
|
156
|
+
return ` ${asName(name)} ${colConf.sqlDefinition} `;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const colDefs = [];
|
|
161
|
+
Object.keys(tableConf.columns).map(colName => {
|
|
162
|
+
const colConf = tableConf.columns[colName];
|
|
163
|
+
|
|
164
|
+
if(!this.dbo[tableName]){
|
|
165
|
+
colDefs.push(getColDef(colName, colConf))
|
|
166
|
+
} else if(!this.dbo[tableName].columns.find(c => colName === c.name)) {
|
|
167
|
+
|
|
168
|
+
if("references" in colConf && colConf.references){
|
|
169
|
+
|
|
170
|
+
const { tableName: lookupTable, } = colConf.references;
|
|
171
|
+
queries.push(`
|
|
172
|
+
ALTER TABLE ${asName(tableName)}
|
|
173
|
+
ADD COLUMN ${getColDef(colName, colConf)};
|
|
174
|
+
`)
|
|
175
|
+
console.log(`TableConfigurator: ${tableName}(${colName})` + " referenced lookup table " + lookupTable);
|
|
176
|
+
|
|
177
|
+
} else if("sqlDefinition" in colConf && colConf.sqlDefinition){
|
|
178
|
+
|
|
136
179
|
queries.push(`
|
|
137
180
|
ALTER TABLE ${asName(tableName)}
|
|
138
|
-
ADD COLUMN ${
|
|
139
|
-
${defaultValue? ` DEFAULT ${asValue(defaultValue)} ` : "" }
|
|
140
|
-
REFERENCES ${lookupTable} (${lookupCol}) ;
|
|
181
|
+
ADD COLUMN ${getColDef(colName, colConf)};
|
|
141
182
|
`)
|
|
142
|
-
console.log(`TableConfigurator: ${tableName}(${colName})` +
|
|
183
|
+
console.log(`TableConfigurator: created/added column ${tableName}(${colName}) ` + colConf.sqlDefinition)
|
|
143
184
|
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
if(colDefs.length){
|
|
189
|
+
queries.push(`CREATE TABLE ${asName(tableName)} (
|
|
190
|
+
${colDefs.join(", \n")}
|
|
191
|
+
);`)
|
|
192
|
+
console.error("TableConfigurator: Created table: \n" + queries[0])
|
|
193
|
+
}
|
|
146
194
|
}
|
|
147
195
|
}));
|
|
148
196
|
|
package/package.json
CHANGED
|
@@ -112,6 +112,8 @@ async function client_only(db, auth, log, methods) {
|
|
|
112
112
|
{ id: 2, public: 'public data' }
|
|
113
113
|
]);
|
|
114
114
|
});
|
|
115
|
+
const cols = await db.insert_rules.getColumns();
|
|
116
|
+
assert_1.strict.equal(cols.filter(({ insert, update: u, select: s, delete: d }) => insert && !u && !s && !d).length, 3, "Validated getColumns failed");
|
|
115
117
|
/* Validated insert */
|
|
116
118
|
const expectB = await db.insert_rules.insert({ name: "a" }, { returning: "*" });
|
|
117
119
|
assert_1.strict.deepStrictEqual(expectB, { name: "b" }, "Validated insert failed");
|
|
@@ -134,6 +134,8 @@ export default async function client_only(db: DBHandlerClient, auth: Auth, log:
|
|
|
134
134
|
]);
|
|
135
135
|
});
|
|
136
136
|
|
|
137
|
+
const cols = await db.insert_rules.getColumns();
|
|
138
|
+
assert.equal(cols.filter(({ insert, update: u, select: s, delete: d }) => insert && !u && !s && !d).length, 3, "Validated getColumns failed")
|
|
137
139
|
|
|
138
140
|
/* Validated insert */
|
|
139
141
|
const expectB = await db.insert_rules.insert({ name: "a" }, { returning: "*" });
|