prostgles-server 2.0.249 → 2.0.250
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/delete.js +2 -2
- package/dist/DboBuilder/delete.js.map +1 -1
- package/dist/DboBuilder/insert.d.ts.map +1 -1
- package/dist/DboBuilder/insert.js +19 -4
- package/dist/DboBuilder/insert.js.map +1 -1
- package/dist/DboBuilder/insertDataParse.d.ts.map +1 -1
- package/dist/DboBuilder/insertDataParse.js +4 -3
- package/dist/DboBuilder/insertDataParse.js.map +1 -1
- package/dist/DboBuilder/update.js +1 -1
- package/dist/DboBuilder/update.js.map +1 -1
- package/dist/DboBuilder.d.ts +6 -3
- package/dist/DboBuilder.d.ts.map +1 -1
- package/dist/DboBuilder.js +177 -92
- package/dist/DboBuilder.js.map +1 -1
- package/lib/DboBuilder/delete.js +2 -2
- package/lib/DboBuilder/delete.ts +2 -2
- package/lib/DboBuilder/insert.d.ts.map +1 -1
- package/lib/DboBuilder/insert.js +19 -4
- package/lib/DboBuilder/insert.ts +24 -4
- package/lib/DboBuilder/insertDataParse.d.ts.map +1 -1
- package/lib/DboBuilder/insertDataParse.js +4 -3
- package/lib/DboBuilder/insertDataParse.ts +5 -4
- package/lib/DboBuilder/update.js +1 -1
- package/lib/DboBuilder/update.ts +1 -1
- package/lib/DboBuilder.d.ts +6 -3
- package/lib/DboBuilder.d.ts.map +1 -1
- package/lib/DboBuilder.js +177 -92
- package/lib/DboBuilder.ts +206 -97
- package/package.json +1 -1
- package/tests/client/PID.txt +1 -1
- package/tests/isomorphic_queries.ts +1 -1
- package/tests/server/index.js +9 -1
- package/tests/server/index.ts +9 -1
- package/tests/server/package-lock.json +1 -1
package/lib/DboBuilder.ts
CHANGED
|
@@ -156,10 +156,13 @@ export type LocalParams = {
|
|
|
156
156
|
testRule?: boolean;
|
|
157
157
|
tableAlias?: string;
|
|
158
158
|
// subOne?: boolean;
|
|
159
|
-
|
|
159
|
+
|
|
160
|
+
tx?: {
|
|
161
|
+
dbTX: TableHandlers;
|
|
162
|
+
t: pgPromise.ITask<{}>;
|
|
163
|
+
}
|
|
160
164
|
|
|
161
165
|
// localTX?: pgPromise.ITask<{}>;
|
|
162
|
-
localDBTX?: DBHandlerServer;
|
|
163
166
|
|
|
164
167
|
returnQuery?: boolean;
|
|
165
168
|
|
|
@@ -2431,6 +2434,8 @@ export class TableHandler extends ViewHandler {
|
|
|
2431
2434
|
|
|
2432
2435
|
}
|
|
2433
2436
|
|
|
2437
|
+
let DATA_TYPES: {oid: string, typname: PG_COLUMN_UDT_DATA_TYPE }[] | undefined;
|
|
2438
|
+
let USER_TABLES: { relid: string; relname: string; }[] | undefined;
|
|
2434
2439
|
|
|
2435
2440
|
import { JOIN_TYPES } from "./Prostgles";
|
|
2436
2441
|
import { BasicSession } from "./AuthHandler";
|
|
@@ -2640,6 +2645,107 @@ export class DboBuilder {
|
|
|
2640
2645
|
return this.joinPaths;
|
|
2641
2646
|
}
|
|
2642
2647
|
|
|
2648
|
+
runSQL = async (query: string, params: any, options: SQLOptions | undefined, localParams?: LocalParams) => {
|
|
2649
|
+
|
|
2650
|
+
/** Cache types */
|
|
2651
|
+
DATA_TYPES ??= await this.db.any("SELECT oid, typname FROM pg_type") ?? [];
|
|
2652
|
+
USER_TABLES ??= await this.db.any("SELECT relid, relname FROM pg_catalog.pg_statio_user_tables") ?? [];
|
|
2653
|
+
|
|
2654
|
+
const canRunSQL = async (localParams?: LocalParams) => {
|
|
2655
|
+
if(!localParams?.socket || !localParams?.httpReq) return true;
|
|
2656
|
+
|
|
2657
|
+
const { socket } = localParams;
|
|
2658
|
+
const publishParams = await this.prostgles.publishParser!.getPublishParams({ socket });
|
|
2659
|
+
let res = await this.prostgles.opts.publishRawSQL?.(publishParams);
|
|
2660
|
+
return Boolean(res && typeof res === "boolean" || res === "*");
|
|
2661
|
+
}
|
|
2662
|
+
|
|
2663
|
+
if(!(await canRunSQL(localParams))) throw "Not allowed to run SQL";
|
|
2664
|
+
|
|
2665
|
+
const { returnType, allowListen }: SQLOptions = options || ({} as any);
|
|
2666
|
+
const { socket } = localParams || {};
|
|
2667
|
+
|
|
2668
|
+
const db = localParams?.tx?.t || this.db;
|
|
2669
|
+
if(returnType === "noticeSubscription"){
|
|
2670
|
+
if(!socket) throw "Only allowed with client socket"
|
|
2671
|
+
return await this.prostgles.dbEventsManager?.addNotice(socket);
|
|
2672
|
+
} else if(returnType === "statement"){
|
|
2673
|
+
try {
|
|
2674
|
+
return pgp.as.format(query, params);
|
|
2675
|
+
} catch (err){
|
|
2676
|
+
throw (err as any).toString();
|
|
2677
|
+
}
|
|
2678
|
+
} else if(db) {
|
|
2679
|
+
|
|
2680
|
+
let finalQuery = query + "";
|
|
2681
|
+
if(returnType === "arrayMode" && !["listen ", "notify "].find(c => query.toLowerCase().trim().startsWith(c))){
|
|
2682
|
+
finalQuery = new PQ({ text: pgp.as.format(query, params), rowMode: "array" });
|
|
2683
|
+
}
|
|
2684
|
+
|
|
2685
|
+
let _qres = await db.result(finalQuery, params)
|
|
2686
|
+
const { fields, rows, command } = _qres;
|
|
2687
|
+
|
|
2688
|
+
/**
|
|
2689
|
+
* Fallback for watchSchema in case not superuser and cannot add db event listener
|
|
2690
|
+
*/
|
|
2691
|
+
const { watchSchema, watchSchemaType } = this.prostgles?.opts || {};
|
|
2692
|
+
|
|
2693
|
+
if(
|
|
2694
|
+
watchSchema &&
|
|
2695
|
+
(!this.prostgles.isSuperUser || watchSchemaType === "prostgles_queries")
|
|
2696
|
+
){
|
|
2697
|
+
if(["CREATE", "ALTER", "DROP"].includes(command)){
|
|
2698
|
+
this.prostgles.onSchemaChange({ command, query })
|
|
2699
|
+
} else if(query) {
|
|
2700
|
+
const cleanedQuery = query.toLowerCase().replace(/\s\s+/g, ' ');
|
|
2701
|
+
if(PubSubManager.SCHEMA_ALTERING_QUERIES.some(q => cleanedQuery.includes(q.toLowerCase()))){
|
|
2702
|
+
this.prostgles.onSchemaChange({ command, query })
|
|
2703
|
+
}
|
|
2704
|
+
}
|
|
2705
|
+
}
|
|
2706
|
+
|
|
2707
|
+
if(command === "LISTEN"){
|
|
2708
|
+
if(!allowListen) throw new Error(`Your query contains a LISTEN command. Set { allowListen: true } to get subscription hooks. Or ignore this message`)
|
|
2709
|
+
if(!socket) throw "Only allowed with client socket"
|
|
2710
|
+
return await this.prostgles.dbEventsManager?.addNotify(query, socket);
|
|
2711
|
+
|
|
2712
|
+
} else if(returnType === "rows") {
|
|
2713
|
+
return rows;
|
|
2714
|
+
|
|
2715
|
+
} else if(returnType === "row") {
|
|
2716
|
+
return rows[0];
|
|
2717
|
+
|
|
2718
|
+
} else if(returnType === "value") {
|
|
2719
|
+
return Object.values(rows?.[0] || {})?.[0];
|
|
2720
|
+
|
|
2721
|
+
} else if(returnType === "values") {
|
|
2722
|
+
return rows.map(r => Object.values(r[0]));
|
|
2723
|
+
|
|
2724
|
+
} else {
|
|
2725
|
+
|
|
2726
|
+
let qres: SQLResult<typeof returnType> = {
|
|
2727
|
+
duration: 0,
|
|
2728
|
+
..._qres,
|
|
2729
|
+
fields: fields?.map(f => {
|
|
2730
|
+
const dataType = DATA_TYPES!.find(dt => +dt.oid === +f.dataTypeID)?.typname ?? "text",
|
|
2731
|
+
tableName = USER_TABLES!.find(t => +t.relid === +f.tableID),
|
|
2732
|
+
tsDataType = postgresToTsType(dataType);
|
|
2733
|
+
|
|
2734
|
+
return {
|
|
2735
|
+
...f,
|
|
2736
|
+
tsDataType,
|
|
2737
|
+
dataType,
|
|
2738
|
+
udt_name: dataType,
|
|
2739
|
+
tableName: tableName?.relname
|
|
2740
|
+
}
|
|
2741
|
+
}) ?? []
|
|
2742
|
+
};
|
|
2743
|
+
return qres;
|
|
2744
|
+
}
|
|
2745
|
+
|
|
2746
|
+
} else console.error("db missing");
|
|
2747
|
+
}
|
|
2748
|
+
|
|
2643
2749
|
async build(): Promise<DBHandlerServer>{
|
|
2644
2750
|
|
|
2645
2751
|
this.tablesOrViews = await getTablesForSchemaPostgresSQL(this.db);
|
|
@@ -2707,105 +2813,102 @@ export class DboBuilder {
|
|
|
2707
2813
|
|
|
2708
2814
|
if(!this.dbo.sql){
|
|
2709
2815
|
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
let USER_TABLES: { relid: string; relname: string; }[] = !needType? [] : await this.db.any("SELECT relid, relname FROM pg_catalog.pg_statio_user_tables");
|
|
2713
|
-
|
|
2714
|
-
this.dbo.sql = async (query: string, params: any, options: SQLOptions | undefined, localParams?: LocalParams) => {
|
|
2816
|
+
this.dbo.sql = this.runSQL;
|
|
2817
|
+
// this.dbo.sql = async (query: string, params: any, options: SQLOptions | undefined, localParams?: LocalParams) => {
|
|
2715
2818
|
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2819
|
+
// const canRunSQL = async (localParams?: LocalParams) => {
|
|
2820
|
+
// if(!localParams?.socket || !localParams?.httpReq) return true;
|
|
2821
|
+
|
|
2822
|
+
// const { socket } = localParams;
|
|
2823
|
+
// const publishParams = await this.prostgles.publishParser!.getPublishParams({ socket });
|
|
2824
|
+
// let res = await this.prostgles.opts.publishRawSQL?.(publishParams);
|
|
2825
|
+
// return Boolean(res && typeof res === "boolean" || res === "*");
|
|
2826
|
+
// }
|
|
2827
|
+
|
|
2828
|
+
// if(!(await canRunSQL(localParams))) throw "Not allowed to run SQL";
|
|
2829
|
+
|
|
2830
|
+
// const { returnType, allowListen }: SQLOptions = options || ({} as any);
|
|
2831
|
+
// const { socket } = localParams || {};
|
|
2832
|
+
|
|
2833
|
+
// if(returnType === "noticeSubscription"){
|
|
2834
|
+
// if(!socket) throw "Only allowed with client socket"
|
|
2835
|
+
// return await this.prostgles.dbEventsManager?.addNotice(socket);
|
|
2836
|
+
// } else if(returnType === "statement"){
|
|
2837
|
+
// try {
|
|
2838
|
+
// return pgp.as.format(query, params);
|
|
2839
|
+
// } catch (err){
|
|
2840
|
+
// throw (err as any).toString();
|
|
2841
|
+
// }
|
|
2842
|
+
// } else if(this.db) {
|
|
2843
|
+
|
|
2844
|
+
// let finalQuery = query + "";
|
|
2845
|
+
// if(returnType === "arrayMode" && !["listen ", "notify "].find(c => query.toLowerCase().trim().startsWith(c))){
|
|
2846
|
+
// finalQuery = new PQ({ text: pgp.as.format(query, params), rowMode: "array" });
|
|
2847
|
+
// }
|
|
2848
|
+
|
|
2849
|
+
// let _qres = await this.db.result(finalQuery, params)
|
|
2850
|
+
// const { fields, rows, command } = _qres;
|
|
2851
|
+
|
|
2852
|
+
// /**
|
|
2853
|
+
// * Fallback for watchSchema in case not superuser and cannot add db event listener
|
|
2854
|
+
// */
|
|
2855
|
+
// const { watchSchema, watchSchemaType } = this.prostgles?.opts || {};
|
|
2856
|
+
|
|
2857
|
+
// if(
|
|
2858
|
+
// watchSchema &&
|
|
2859
|
+
// (!this.prostgles.isSuperUser || watchSchemaType === "prostgles_queries")
|
|
2860
|
+
// ){
|
|
2861
|
+
// if(["CREATE", "ALTER", "DROP"].includes(command)){
|
|
2862
|
+
// this.prostgles.onSchemaChange({ command, query })
|
|
2863
|
+
// } else if(query) {
|
|
2864
|
+
// const cleanedQuery = query.toLowerCase().replace(/\s\s+/g, ' ');
|
|
2865
|
+
// if(PubSubManager.SCHEMA_ALTERING_QUERIES.some(q => cleanedQuery.includes(q.toLowerCase()))){
|
|
2866
|
+
// this.prostgles.onSchemaChange({ command, query })
|
|
2867
|
+
// }
|
|
2868
|
+
// }
|
|
2869
|
+
// }
|
|
2870
|
+
|
|
2871
|
+
// if(command === "LISTEN"){
|
|
2872
|
+
// if(!allowListen) throw new Error(`Your query contains a LISTEN command. Set { allowListen: true } to get subscription hooks. Or ignore this message`)
|
|
2873
|
+
// if(!socket) throw "Only allowed with client socket"
|
|
2874
|
+
// return await this.prostgles.dbEventsManager?.addNotify(query, socket);
|
|
2875
|
+
|
|
2876
|
+
// } else if(returnType === "rows") {
|
|
2877
|
+
// return rows;
|
|
2775
2878
|
|
|
2776
|
-
|
|
2777
|
-
|
|
2879
|
+
// } else if(returnType === "row") {
|
|
2880
|
+
// return rows[0];
|
|
2778
2881
|
|
|
2779
|
-
|
|
2780
|
-
|
|
2882
|
+
// } else if(returnType === "value") {
|
|
2883
|
+
// return Object.values(rows?.[0] || {})?.[0];
|
|
2781
2884
|
|
|
2782
|
-
|
|
2783
|
-
|
|
2885
|
+
// } else if(returnType === "values") {
|
|
2886
|
+
// return rows.map(r => Object.values(r[0]));
|
|
2784
2887
|
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2888
|
+
// } else {
|
|
2889
|
+
|
|
2890
|
+
// let qres: SQLResult<typeof returnType> = {
|
|
2891
|
+
// duration: 0,
|
|
2892
|
+
// ..._qres,
|
|
2893
|
+
// fields: fields?.map(f => {
|
|
2894
|
+
// const dataType = DATA_TYPES.find(dt => +dt.oid === +f.dataTypeID)?.typname ?? "text",
|
|
2895
|
+
// tableName = USER_TABLES.find(t => +t.relid === +f.tableID),
|
|
2896
|
+
// tsDataType = postgresToTsType(dataType);
|
|
2897
|
+
|
|
2898
|
+
// return {
|
|
2899
|
+
// ...f,
|
|
2900
|
+
// tsDataType,
|
|
2901
|
+
// dataType,
|
|
2902
|
+
// udt_name: dataType,
|
|
2903
|
+
// tableName: tableName?.relname
|
|
2904
|
+
// }
|
|
2905
|
+
// }) ?? []
|
|
2906
|
+
// };
|
|
2907
|
+
// return qres;
|
|
2908
|
+
// }
|
|
2806
2909
|
|
|
2807
|
-
|
|
2808
|
-
}
|
|
2910
|
+
// } else console.error("db missing");
|
|
2911
|
+
// }
|
|
2809
2912
|
} else {
|
|
2810
2913
|
console.warn(`Could not create dbo.sql handler because there is already a table named "sql"`)
|
|
2811
2914
|
}
|
|
@@ -2821,13 +2924,19 @@ export class DboBuilder {
|
|
|
2821
2924
|
|
|
2822
2925
|
getTX = (cb: TxCB) => {
|
|
2823
2926
|
return this.db.tx((t) => {
|
|
2824
|
-
let dbTX: TableHandlers = {};
|
|
2927
|
+
let dbTX: TableHandlers & Pick<DBHandlerServer, "sql"> = {};
|
|
2825
2928
|
this.tablesOrViews?.map(tov => {
|
|
2826
2929
|
dbTX[tov.name] = new (tov.is_view? ViewHandler: TableHandler)(this.db, tov, this, t, dbTX, this.joinPaths);
|
|
2827
2930
|
});
|
|
2931
|
+
if(!dbTX.sql){
|
|
2932
|
+
dbTX.sql = this.runSQL;
|
|
2933
|
+
}
|
|
2828
2934
|
getKeys(dbTX).map(k => {
|
|
2829
2935
|
dbTX[k].dbTX = dbTX;
|
|
2830
|
-
})
|
|
2936
|
+
});
|
|
2937
|
+
|
|
2938
|
+
dbTX.sql = (q, args, opts, localP) => this.runSQL(q, args, opts, { tx: {dbTX, t }, ...(localP ?? {}) })
|
|
2939
|
+
|
|
2831
2940
|
return cb(dbTX, t);
|
|
2832
2941
|
});
|
|
2833
2942
|
}
|
package/package.json
CHANGED
package/tests/client/PID.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
29151
|
|
@@ -640,7 +640,7 @@ export default async function isomorphic(db: Partial<DBHandlerServer> | Partial<
|
|
|
640
640
|
}
|
|
641
641
|
},
|
|
642
642
|
*/
|
|
643
|
-
|
|
643
|
+
|
|
644
644
|
const json = { a: true, arr: "2", arr1: 3, arr2: [1], arrStr: ["1123.string"] }
|
|
645
645
|
const fo = await db.tjson.insert({ colOneOf: "a", json }, { returning: "*"});
|
|
646
646
|
// assert.deepStrictEqual(fo.json, json);
|
package/tests/server/index.js
CHANGED
|
@@ -313,7 +313,15 @@ function dd() {
|
|
|
313
313
|
row.name = "b";
|
|
314
314
|
return row;
|
|
315
315
|
},
|
|
316
|
-
postValidate: async (row,
|
|
316
|
+
postValidate: async (row, dboTx) => {
|
|
317
|
+
/** Records must exist in this transaction */
|
|
318
|
+
log(JSON.stringify(row));
|
|
319
|
+
const exists = await dboTx.sql("SELECT * FROM insert_rules WHERE id = ${id}", row, { returnType: "row" });
|
|
320
|
+
const existsd = await dboTx.insert_rules.findOne({ id: row.id });
|
|
321
|
+
if (row.id !== exists.id || row.id !== existsd.id) {
|
|
322
|
+
console.error("postValidate failed");
|
|
323
|
+
// process.exit(1)
|
|
324
|
+
}
|
|
317
325
|
if (row.name === "fail")
|
|
318
326
|
throw "Failed";
|
|
319
327
|
return undefined;
|
package/tests/server/index.ts
CHANGED
|
@@ -341,7 +341,15 @@ function dd(){
|
|
|
341
341
|
if(row.name === "a") row.name = "b"
|
|
342
342
|
return row
|
|
343
343
|
},
|
|
344
|
-
postValidate: async (row,
|
|
344
|
+
postValidate: async (row, dboTx) => {
|
|
345
|
+
/** Records must exist in this transaction */
|
|
346
|
+
log(JSON.stringify(row))
|
|
347
|
+
const exists = await dboTx.sql("SELECT * FROM insert_rules WHERE id = ${id}", row, { returnType: "row" });
|
|
348
|
+
const existsd = await dboTx.insert_rules.findOne({ id: row.id });
|
|
349
|
+
if(row.id !== exists.id || row.id !== existsd.id){
|
|
350
|
+
console.error("postValidate failed");
|
|
351
|
+
// process.exit(1)
|
|
352
|
+
}
|
|
345
353
|
if(row.name === "fail") throw "Failed";
|
|
346
354
|
return undefined
|
|
347
355
|
}
|