prostgles-server 3.0.124 → 3.0.126
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.d.ts.map +1 -1
- package/dist/DboBuilder.js +10 -9
- package/dist/DboBuilder.js.map +1 -1
- package/dist/JSONBValidation/validate_jsonb_schema_sql.js +2 -2
- package/dist/JSONBValidation/validate_jsonb_schema_sql.js.map +1 -1
- package/dist/PubSubManager/PubSubManager.d.ts.map +1 -1
- package/dist/PubSubManager/PubSubManager.js +17 -16
- package/dist/PubSubManager/PubSubManager.js.map +1 -1
- package/dist/PubSubManager/getInitQuery.d.ts.map +1 -1
- package/dist/PubSubManager/getInitQuery.js +5 -4
- package/dist/PubSubManager/getInitQuery.js.map +1 -1
- package/dist/PubSubManager/initPubSubManager.d.ts.map +1 -1
- package/dist/PubSubManager/initPubSubManager.js +4 -1
- package/dist/PubSubManager/initPubSubManager.js.map +1 -1
- package/dist/TableConfig.d.ts.map +1 -1
- package/dist/TableConfig.js +42 -12
- package/dist/TableConfig.js.map +1 -1
- package/lib/DboBuilder.d.ts.map +1 -1
- package/lib/DboBuilder.js +10 -9
- package/lib/DboBuilder.ts +10 -9
- package/lib/JSONBValidation/validate_jsonb_schema_sql.js +2 -2
- package/lib/JSONBValidation/validate_jsonb_schema_sql.ts +2 -2
- package/lib/PubSubManager/PubSubManager.d.ts.map +1 -1
- package/lib/PubSubManager/PubSubManager.js +17 -16
- package/lib/PubSubManager/PubSubManager.ts +17 -16
- package/lib/PubSubManager/getInitQuery.d.ts.map +1 -1
- package/lib/PubSubManager/getInitQuery.js +5 -4
- package/lib/PubSubManager/getInitQuery.ts +5 -4
- package/lib/PubSubManager/initPubSubManager.d.ts.map +1 -1
- package/lib/PubSubManager/initPubSubManager.js +4 -1
- package/lib/PubSubManager/initPubSubManager.ts +4 -1
- package/lib/TableConfig.d.ts.map +1 -1
- package/lib/TableConfig.js +42 -12
- package/lib/TableConfig.ts +49 -13
- package/package.json +1 -1
- package/tests/client/PID.txt +1 -1
- package/tests/server/DBoGenerated.d.ts +1 -1
- package/tests/server/index.js +1 -1
- package/tests/server/index.ts +1 -1
- package/tests/server/package-lock.json +1 -1
package/lib/TableConfig.js
CHANGED
|
@@ -178,7 +178,7 @@ class TableConfigurator {
|
|
|
178
178
|
await Promise.all((0, prostgles_types_1.getKeys)(this.config).map(async (tableName) => {
|
|
179
179
|
const tableConf = this.config[tableName];
|
|
180
180
|
if ("columns" in tableConf) {
|
|
181
|
-
const getColDef = (name, colConf) => {
|
|
181
|
+
const getColDef = async (name, colConf) => {
|
|
182
182
|
const colNameEsc = asName(name);
|
|
183
183
|
const getColTypeDef = (colConf, pgType) => {
|
|
184
184
|
const { nullable, defaultValue } = colConf;
|
|
@@ -217,17 +217,46 @@ class TableConfigurator {
|
|
|
217
217
|
/** Validate default value against jsonbSchema */
|
|
218
218
|
const q = `SELECT ${validate_jsonb_schema_sql_1.VALIDATE_SCHEMA_FUNCNAME}(${jsonbSchemaStr}, ${(0, PubSubManager_1.asValue)(colConf.defaultValue) + "::JSONB"}, ARRAY[${(0, PubSubManager_1.asValue)(name)}]) as v`;
|
|
219
219
|
if (colConf.defaultValue) {
|
|
220
|
-
this.log(q);
|
|
221
220
|
const failedDefault = (err) => {
|
|
222
|
-
|
|
221
|
+
return { msg: `Default value (${colConf.defaultValue}) for ${tableName}.${name} does not satisfy the jsonb constraint check: ${q}`, err };
|
|
223
222
|
};
|
|
224
|
-
|
|
223
|
+
try {
|
|
224
|
+
const row = await this.dbo.sql(q, {}, { returnType: "row" });
|
|
225
225
|
if (!row?.v) {
|
|
226
|
-
|
|
226
|
+
throw "Error";
|
|
227
227
|
}
|
|
228
|
-
}
|
|
228
|
+
}
|
|
229
|
+
catch (e) {
|
|
230
|
+
throw failedDefault(e);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
const namePreffix = 'prostgles_jsonb_';
|
|
234
|
+
const { val: nameEnding } = await this.db.one("SELECT MD5( ${table} || ${column} || ${schema}) as val", { table: tableName, column: name, schema: jsonbSchemaStr });
|
|
235
|
+
const constraintName = namePreffix + nameEnding;
|
|
236
|
+
const colConstraints = await this.db.manyOrNone(`
|
|
237
|
+
SELECT *
|
|
238
|
+
FROM (
|
|
239
|
+
SELECT distinct c.conname as name,
|
|
240
|
+
(SELECT r.relname from pg_class r where r.oid = c.conrelid) as "table",
|
|
241
|
+
(SELECT array_agg(attname::text) from pg_attribute
|
|
242
|
+
where attrelid = c.conrelid and ARRAY[attnum] <@ c.conkey) as cols
|
|
243
|
+
-- (SELECT array_agg(attname::text) from pg_attribute
|
|
244
|
+
-- where attrelid = c.confrelid and ARRAY[attnum] <@ c.confkey) as fcols,
|
|
245
|
+
-- (SELECT r.relname from pg_class r where r.oid = c.confrelid) as ftable
|
|
246
|
+
FROM pg_catalog.pg_constraint c
|
|
247
|
+
INNER JOIN pg_catalog.pg_class rel
|
|
248
|
+
ON rel.oid = c.conrelid
|
|
249
|
+
INNER JOIN pg_catalog.pg_namespace nsp
|
|
250
|
+
ON nsp.oid = connamespace
|
|
251
|
+
) t
|
|
252
|
+
WHERE TRUE
|
|
253
|
+
AND "table" = ${(0, PubSubManager_1.asValue)(tableName)} AND cols @> ARRAY[${(0, PubSubManager_1.asValue)(name)}]
|
|
254
|
+
`);
|
|
255
|
+
const existingNonMatchingConstraints = colConstraints.filter(c => c.name.startsWith(namePreffix) && c.name !== constraintName);
|
|
256
|
+
for await (const oldCons of existingNonMatchingConstraints) {
|
|
257
|
+
await this.db.any(`ALTER TABLE ${asName(tableName)} DROP CONSTRAINT ${asName(oldCons.name)}`);
|
|
229
258
|
}
|
|
230
|
-
return ` ${colNameEsc} ${getColTypeDef(colConf, "JSONB")} CHECK(${validate_jsonb_schema_sql_1.VALIDATE_SCHEMA_FUNCNAME}(${jsonbSchemaStr}, ${colNameEsc}, ARRAY[${(0, PubSubManager_1.asValue)(name)}]))`;
|
|
259
|
+
return ` ${colNameEsc} ${getColTypeDef(colConf, "JSONB")}, CONSTRAINT ${asName(constraintName)} CHECK(${validate_jsonb_schema_sql_1.VALIDATE_SCHEMA_FUNCNAME}(${jsonbSchemaStr}, ${colNameEsc}, ARRAY[${(0, PubSubManager_1.asValue)(name)}]))`;
|
|
231
260
|
}
|
|
232
261
|
else if ("enum" in colConf) {
|
|
233
262
|
if (!colConf.enum?.length)
|
|
@@ -262,19 +291,20 @@ class TableConfigurator {
|
|
|
262
291
|
throw err;
|
|
263
292
|
}
|
|
264
293
|
}
|
|
265
|
-
(0, prostgles_types_1.getKeys)(tableConf.columns).filter(c => {
|
|
294
|
+
const columns = (0, prostgles_types_1.getKeys)(tableConf.columns).filter(c => {
|
|
266
295
|
const colDef = tableConf.columns[c];
|
|
267
296
|
return typeof colDef === "string" || !("joinDef" in colDef);
|
|
268
|
-
})
|
|
297
|
+
});
|
|
298
|
+
for await (const colName of columns) {
|
|
269
299
|
const colConf = tableConf.columns[colName];
|
|
270
300
|
/* Add columns to create statement */
|
|
271
301
|
if (!tableHandler) {
|
|
272
|
-
colCreateLines.push(getColDef(colName, colConf));
|
|
302
|
+
colCreateLines.push(await getColDef(colName, colConf));
|
|
273
303
|
}
|
|
274
304
|
else if (tableHandler && !tableHandler.columns?.find(c => colName === c.name)) {
|
|
275
305
|
queries.push(`
|
|
276
306
|
ALTER TABLE ${asName(tableName)}
|
|
277
|
-
ADD COLUMN ${getColDef(colName, colConf)};
|
|
307
|
+
ADD COLUMN ${await getColDef(colName, colConf)};
|
|
278
308
|
`);
|
|
279
309
|
if ((0, prostgles_types_1.isObject)(colConf) && "references" in colConf && colConf.references) {
|
|
280
310
|
const { tableName: lookupTable, } = colConf.references;
|
|
@@ -284,7 +314,7 @@ class TableConfigurator {
|
|
|
284
314
|
this.log(`TableConfigurator: created/added column ${tableName}(${colName}) `);
|
|
285
315
|
}
|
|
286
316
|
}
|
|
287
|
-
}
|
|
317
|
+
}
|
|
288
318
|
}
|
|
289
319
|
if (colCreateLines.length) {
|
|
290
320
|
queries.push([
|
package/lib/TableConfig.ts
CHANGED
|
@@ -472,7 +472,7 @@ export default class TableConfigurator<LANG_IDS = { en: 1 }> {
|
|
|
472
472
|
await Promise.all(getKeys(this.config).map(async tableName => {
|
|
473
473
|
const tableConf = this.config![tableName];
|
|
474
474
|
if ("columns" in tableConf) {
|
|
475
|
-
const getColDef = (name: string, colConf: ColumnConfig): string => {
|
|
475
|
+
const getColDef = async (name: string, colConf: ColumnConfig): Promise<string> => {
|
|
476
476
|
const colNameEsc = asName(name);
|
|
477
477
|
const getColTypeDef = (colConf: BaseColumnTypes, pgType: "TEXT" | "JSONB") => {
|
|
478
478
|
const { nullable, defaultValue } = colConf;
|
|
@@ -518,19 +518,53 @@ export default class TableConfigurator<LANG_IDS = { en: 1 }> {
|
|
|
518
518
|
}) + "::TEXT";
|
|
519
519
|
|
|
520
520
|
/** Validate default value against jsonbSchema */
|
|
521
|
-
const q = `SELECT ${VALIDATE_SCHEMA_FUNCNAME}(${jsonbSchemaStr}, ${asValue(colConf.defaultValue)+"::JSONB"}, ARRAY[${asValue(name)}]) as v
|
|
521
|
+
const q = `SELECT ${VALIDATE_SCHEMA_FUNCNAME}(${jsonbSchemaStr}, ${asValue(colConf.defaultValue)+"::JSONB"}, ARRAY[${asValue(name)}]) as v`;
|
|
522
522
|
if(colConf.defaultValue){
|
|
523
|
-
|
|
523
|
+
|
|
524
524
|
const failedDefault = (err?: any) => {
|
|
525
|
-
|
|
525
|
+
return { msg: `Default value (${colConf.defaultValue}) for ${tableName}.${name} does not satisfy the jsonb constraint check: ${q}`, err };
|
|
526
526
|
}
|
|
527
|
-
|
|
527
|
+
try {
|
|
528
|
+
const row = await this.dbo.sql!(q, {}, { returnType: "row" });
|
|
528
529
|
if(!row?.v) {
|
|
529
|
-
|
|
530
|
+
throw "Error";
|
|
530
531
|
}
|
|
531
|
-
}
|
|
532
|
+
} catch(e){
|
|
533
|
+
throw failedDefault(e);
|
|
534
|
+
}
|
|
532
535
|
}
|
|
533
|
-
|
|
536
|
+
const namePreffix = 'prostgles_jsonb_' as const;
|
|
537
|
+
const { val: nameEnding } = await this.db.one("SELECT MD5( ${table} || ${column} || ${schema}) as val", { table: tableName, column: name, schema: jsonbSchemaStr });
|
|
538
|
+
const constraintName = namePreffix + nameEnding;
|
|
539
|
+
const colConstraints: {
|
|
540
|
+
name: string;
|
|
541
|
+
table: string;
|
|
542
|
+
cols: Array<string>;
|
|
543
|
+
}[] = await this.db.manyOrNone(`
|
|
544
|
+
SELECT *
|
|
545
|
+
FROM (
|
|
546
|
+
SELECT distinct c.conname as name,
|
|
547
|
+
(SELECT r.relname from pg_class r where r.oid = c.conrelid) as "table",
|
|
548
|
+
(SELECT array_agg(attname::text) from pg_attribute
|
|
549
|
+
where attrelid = c.conrelid and ARRAY[attnum] <@ c.conkey) as cols
|
|
550
|
+
-- (SELECT array_agg(attname::text) from pg_attribute
|
|
551
|
+
-- where attrelid = c.confrelid and ARRAY[attnum] <@ c.confkey) as fcols,
|
|
552
|
+
-- (SELECT r.relname from pg_class r where r.oid = c.confrelid) as ftable
|
|
553
|
+
FROM pg_catalog.pg_constraint c
|
|
554
|
+
INNER JOIN pg_catalog.pg_class rel
|
|
555
|
+
ON rel.oid = c.conrelid
|
|
556
|
+
INNER JOIN pg_catalog.pg_namespace nsp
|
|
557
|
+
ON nsp.oid = connamespace
|
|
558
|
+
) t
|
|
559
|
+
WHERE TRUE
|
|
560
|
+
AND "table" = ${asValue(tableName)} AND cols @> ARRAY[${asValue(name)}]
|
|
561
|
+
`);
|
|
562
|
+
const existingNonMatchingConstraints = colConstraints.filter(c => c.name.startsWith(namePreffix) && c.name !== constraintName);
|
|
563
|
+
for await (const oldCons of existingNonMatchingConstraints){
|
|
564
|
+
await this.db.any(`ALTER TABLE ${asName(tableName)} DROP CONSTRAINT ${asName(oldCons.name)}`);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
return ` ${colNameEsc} ${getColTypeDef(colConf, "JSONB")}, CONSTRAINT ${asName(constraintName)} CHECK(${VALIDATE_SCHEMA_FUNCNAME}(${jsonbSchemaStr}, ${colNameEsc}, ARRAY[${asValue(name)}]))`;
|
|
534
568
|
|
|
535
569
|
} else if("enum" in colConf) {
|
|
536
570
|
if(!colConf.enum?.length) throw new Error("colConf.enum Must not be empty");
|
|
@@ -567,21 +601,23 @@ export default class TableConfigurator<LANG_IDS = { en: 1 }> {
|
|
|
567
601
|
}
|
|
568
602
|
}
|
|
569
603
|
|
|
570
|
-
getKeys(tableConf.columns).filter(c => {
|
|
604
|
+
const columns = getKeys(tableConf.columns).filter(c => {
|
|
571
605
|
const colDef = tableConf.columns![c];
|
|
572
606
|
return typeof colDef === "string" || !("joinDef" in colDef)
|
|
573
|
-
})
|
|
607
|
+
});
|
|
608
|
+
|
|
609
|
+
for await(const colName of columns) {
|
|
574
610
|
const colConf = tableConf.columns![colName];
|
|
575
611
|
|
|
576
612
|
/* Add columns to create statement */
|
|
577
613
|
if (!tableHandler) {
|
|
578
|
-
colCreateLines.push(getColDef(colName, colConf));
|
|
614
|
+
colCreateLines.push(await getColDef(colName, colConf));
|
|
579
615
|
|
|
580
616
|
} else if (tableHandler && !tableHandler.columns?.find(c => colName === c.name)) {
|
|
581
617
|
|
|
582
618
|
queries.push(`
|
|
583
619
|
ALTER TABLE ${asName(tableName)}
|
|
584
|
-
ADD COLUMN ${getColDef(colName, colConf)};
|
|
620
|
+
ADD COLUMN ${await getColDef(colName, colConf)};
|
|
585
621
|
`)
|
|
586
622
|
if (isObject(colConf) && "references" in colConf && colConf.references) {
|
|
587
623
|
|
|
@@ -591,7 +627,7 @@ export default class TableConfigurator<LANG_IDS = { en: 1 }> {
|
|
|
591
627
|
this.log(`TableConfigurator: created/added column ${tableName}(${colName}) `)
|
|
592
628
|
}
|
|
593
629
|
}
|
|
594
|
-
}
|
|
630
|
+
}
|
|
595
631
|
}
|
|
596
632
|
|
|
597
633
|
if (colCreateLines.length) {
|
package/package.json
CHANGED
package/tests/client/PID.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
178436
|
|
@@ -437,7 +437,7 @@ export type DBSchemaGenerated = {
|
|
|
437
437
|
columns: {
|
|
438
438
|
email: string;
|
|
439
439
|
id?: number;
|
|
440
|
-
preferences
|
|
440
|
+
preferences: { showIntro?: boolean; theme?: 'light' | 'dark' | 'auto'; others: any[]; };
|
|
441
441
|
status: "active" | "disabled" | "pending"
|
|
442
442
|
};
|
|
443
443
|
};
|
package/tests/server/index.js
CHANGED
|
@@ -90,7 +90,7 @@ function dd() {
|
|
|
90
90
|
id: { sqlDefinition: `SERIAL PRIMARY KEY ` },
|
|
91
91
|
email: { sqlDefinition: `TEXT NOT NULL` },
|
|
92
92
|
status: { enum: ["active", "disabled", "pending"] },
|
|
93
|
-
preferences: {
|
|
93
|
+
preferences: {
|
|
94
94
|
jsonbSchemaType: {
|
|
95
95
|
showIntro: { type: "boolean", optional: true },
|
|
96
96
|
theme: { enum: ["light", "dark", "auto"], optional: true },
|
package/tests/server/index.ts
CHANGED
|
@@ -111,7 +111,7 @@ function dd(){
|
|
|
111
111
|
id: { sqlDefinition: `SERIAL PRIMARY KEY ` },
|
|
112
112
|
email: { sqlDefinition: `TEXT NOT NULL` },
|
|
113
113
|
status: { enum: ["active", "disabled", "pending"] },
|
|
114
|
-
preferences: {
|
|
114
|
+
preferences: {
|
|
115
115
|
jsonbSchemaType: {
|
|
116
116
|
showIntro: { type: "boolean", optional: true },
|
|
117
117
|
theme: { enum: ["light", "dark", "auto"], optional: true },
|