prostgles-server 4.2.160 → 4.2.161
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/lib/Auth/AuthHandler.ts +436 -0
- package/lib/Auth/AuthTypes.ts +280 -0
- package/lib/Auth/getSafeReturnURL.ts +35 -0
- package/lib/Auth/sendEmail.ts +83 -0
- package/lib/Auth/setAuthProviders.ts +128 -0
- package/lib/Auth/setEmailProvider.ts +85 -0
- package/lib/Auth/setupAuthRoutes.ts +161 -0
- package/lib/DBEventsManager.ts +178 -0
- package/lib/DBSchemaBuilder.ts +225 -0
- package/lib/DboBuilder/DboBuilder.ts +319 -0
- package/lib/DboBuilder/DboBuilderTypes.ts +361 -0
- package/lib/DboBuilder/QueryBuilder/Functions.ts +1153 -0
- package/lib/DboBuilder/QueryBuilder/QueryBuilder.ts +288 -0
- package/lib/DboBuilder/QueryBuilder/getJoinQuery.ts +263 -0
- package/lib/DboBuilder/QueryBuilder/getNewQuery.ts +271 -0
- package/lib/DboBuilder/QueryBuilder/getSelectQuery.ts +136 -0
- package/lib/DboBuilder/QueryBuilder/prepareHaving.ts +22 -0
- package/lib/DboBuilder/QueryStreamer.ts +250 -0
- package/lib/DboBuilder/TableHandler/DataValidator.ts +428 -0
- package/lib/DboBuilder/TableHandler/TableHandler.ts +205 -0
- package/lib/DboBuilder/TableHandler/delete.ts +115 -0
- package/lib/DboBuilder/TableHandler/insert.ts +183 -0
- package/lib/DboBuilder/TableHandler/insertTest.ts +78 -0
- package/lib/DboBuilder/TableHandler/onDeleteFromFileTable.ts +62 -0
- package/lib/DboBuilder/TableHandler/runInsertUpdateQuery.ts +134 -0
- package/lib/DboBuilder/TableHandler/update.ts +126 -0
- package/lib/DboBuilder/TableHandler/updateBatch.ts +49 -0
- package/lib/DboBuilder/TableHandler/updateFile.ts +48 -0
- package/lib/DboBuilder/TableHandler/upsert.ts +34 -0
- package/lib/DboBuilder/ViewHandler/ViewHandler.ts +393 -0
- package/lib/DboBuilder/ViewHandler/count.ts +38 -0
- package/lib/DboBuilder/ViewHandler/find.ts +153 -0
- package/lib/DboBuilder/ViewHandler/getExistsCondition.ts +73 -0
- package/lib/DboBuilder/ViewHandler/getExistsFilters.ts +74 -0
- package/lib/DboBuilder/ViewHandler/getInfo.ts +32 -0
- package/lib/DboBuilder/ViewHandler/getTableJoinQuery.ts +84 -0
- package/lib/DboBuilder/ViewHandler/parseComplexFilter.ts +96 -0
- package/lib/DboBuilder/ViewHandler/parseFieldFilter.ts +105 -0
- package/lib/DboBuilder/ViewHandler/parseJoinPath.ts +208 -0
- package/lib/DboBuilder/ViewHandler/prepareSortItems.ts +163 -0
- package/lib/DboBuilder/ViewHandler/prepareWhere.ts +90 -0
- package/lib/DboBuilder/ViewHandler/size.ts +37 -0
- package/lib/DboBuilder/ViewHandler/subscribe.ts +118 -0
- package/lib/DboBuilder/ViewHandler/validateViewRules.ts +70 -0
- package/lib/DboBuilder/dboBuilderUtils.ts +222 -0
- package/lib/DboBuilder/getColumns.ts +114 -0
- package/lib/DboBuilder/getCondition.ts +201 -0
- package/lib/DboBuilder/getSubscribeRelatedTables.ts +190 -0
- package/lib/DboBuilder/getTablesForSchemaPostgresSQL.ts +426 -0
- package/lib/DboBuilder/insertNestedRecords.ts +355 -0
- package/lib/DboBuilder/parseUpdateRules.ts +187 -0
- package/lib/DboBuilder/prepareShortestJoinPaths.ts +186 -0
- package/lib/DboBuilder/runSQL.ts +182 -0
- package/lib/DboBuilder/runTransaction.ts +50 -0
- package/lib/DboBuilder/sqlErrCodeToMsg.ts +254 -0
- package/lib/DboBuilder/uploadFile.ts +69 -0
- package/lib/Event_Trigger_Tags.ts +118 -0
- package/lib/FileManager/FileManager.ts +358 -0
- package/lib/FileManager/getValidatedFileType.ts +69 -0
- package/lib/FileManager/initFileManager.ts +187 -0
- package/lib/FileManager/upload.ts +62 -0
- package/lib/FileManager/uploadStream.ts +79 -0
- package/lib/Filtering.ts +463 -0
- package/lib/JSONBValidation/validate_jsonb_schema_sql.ts +502 -0
- package/lib/JSONBValidation/validation.ts +143 -0
- package/lib/Logging.ts +127 -0
- package/lib/PostgresNotifListenManager.ts +143 -0
- package/lib/Prostgles.ts +485 -0
- package/lib/ProstglesTypes.ts +196 -0
- package/lib/PubSubManager/PubSubManager.ts +609 -0
- package/lib/PubSubManager/addSub.ts +138 -0
- package/lib/PubSubManager/addSync.ts +141 -0
- package/lib/PubSubManager/getCreatePubSubManagerError.ts +72 -0
- package/lib/PubSubManager/getPubSubManagerInitQuery.ts +662 -0
- package/lib/PubSubManager/initPubSubManager.ts +79 -0
- package/lib/PubSubManager/notifListener.ts +173 -0
- package/lib/PubSubManager/orphanTriggerCheck.ts +70 -0
- package/lib/PubSubManager/pushSubData.ts +55 -0
- package/lib/PublishParser/PublishParser.ts +162 -0
- package/lib/PublishParser/getFileTableRules.ts +124 -0
- package/lib/PublishParser/getSchemaFromPublish.ts +141 -0
- package/lib/PublishParser/getTableRulesWithoutFileTable.ts +177 -0
- package/lib/PublishParser/publishTypesAndUtils.ts +399 -0
- package/lib/RestApi.ts +127 -0
- package/lib/SchemaWatch/SchemaWatch.ts +90 -0
- package/lib/SchemaWatch/createSchemaWatchEventTrigger.ts +3 -0
- package/lib/SchemaWatch/getValidatedWatchSchemaType.ts +45 -0
- package/lib/SchemaWatch/getWatchSchemaTagList.ts +27 -0
- package/lib/SyncReplication.ts +557 -0
- package/lib/TableConfig/TableConfig.ts +468 -0
- package/lib/TableConfig/getColumnDefinitionQuery.ts +111 -0
- package/lib/TableConfig/getConstraintDefinitionQueries.ts +95 -0
- package/lib/TableConfig/getFutureTableSchema.ts +64 -0
- package/lib/TableConfig/getPGIndexes.ts +53 -0
- package/lib/TableConfig/getTableColumnQueries.ts +129 -0
- package/lib/TableConfig/initTableConfig.ts +326 -0
- package/lib/index.ts +13 -0
- package/lib/initProstgles.ts +319 -0
- package/lib/onSocketConnected.ts +102 -0
- package/lib/runClientRequest.ts +129 -0
- package/lib/shortestPath.ts +122 -0
- package/lib/typeTests/DBoGenerated.d.ts +320 -0
- package/lib/typeTests/dboTypeCheck.ts +81 -0
- package/lib/utils.ts +15 -0
- package/package.json +1 -1
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { AnyObject, DbJoinMaker, DBSchema, isObject, JSONB, SQLHandler, TableHandler, ViewHandler } from "prostgles-types";
|
|
2
|
+
import prostgles from ".";
|
|
3
|
+
import { Auth } from "./Auth/AuthTypes";
|
|
4
|
+
import { DboBuilder, escapeTSNames, postgresToTsType } from "./DboBuilder/DboBuilder";
|
|
5
|
+
import { PublishAllOrNothing, PublishParams, PublishTableRule, PublishViewRule, } from "./PublishParser/PublishParser";
|
|
6
|
+
import { getJSONBSchemaTSTypes } from "./JSONBValidation/validation";
|
|
7
|
+
import { DBHandlerServer, TableSchemaColumn, TX } from "./DboBuilder/DboBuilderTypes";
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
export const getDBSchema = (dboBuilder: DboBuilder): string => {
|
|
11
|
+
const tables: string[] = [];
|
|
12
|
+
|
|
13
|
+
const getColTypeForDBSchema = (udt_name: TableSchemaColumn["udt_name"]): string => {
|
|
14
|
+
if(udt_name === "interval"){
|
|
15
|
+
const units = [ "years", "months", "days", "hours", "minutes", "seconds", "milliseconds"];
|
|
16
|
+
|
|
17
|
+
return `{ ${units.map(u => `${u}?: number;`).join(" ")} }`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return postgresToTsType(udt_name);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Tables and columns are sorted to avoid infinite loops due to changing order */
|
|
24
|
+
dboBuilder.tablesOrViews?.slice(0).sort((a, b) => a.name.localeCompare(b.name)).forEach(tov => {
|
|
25
|
+
const cols = tov.columns.slice(0).sort((a, b) => a.name.localeCompare(b.name));
|
|
26
|
+
const getColType = (c: typeof cols[number]) => {
|
|
27
|
+
|
|
28
|
+
let type: string = (c.is_nullable? "null | " : "") + getColTypeForDBSchema(c.udt_name) + ";"
|
|
29
|
+
const colConf = dboBuilder.prostgles.tableConfigurator?.getColumnConfig(tov.name, c.name);
|
|
30
|
+
if(colConf){
|
|
31
|
+
if(isObject(colConf) && (colConf.jsonbSchema || colConf.jsonbSchemaType)){
|
|
32
|
+
const schema: JSONB.JSONBSchema = colConf.jsonbSchema || { ...colConf, type: colConf.jsonbSchemaType };
|
|
33
|
+
|
|
34
|
+
type = getJSONBSchemaTSTypes(schema, { nullable: colConf.nullable }, " ", dboBuilder.tablesOrViews ?? []);
|
|
35
|
+
} else if(isObject(colConf) && "enum" in colConf){
|
|
36
|
+
if(!colConf.enum) throw "colConf.enum missing"
|
|
37
|
+
const types = colConf.enum.map(t => typeof t === "number"? t : JSON.stringify(t));
|
|
38
|
+
if(colConf.nullable){
|
|
39
|
+
types.unshift("null")
|
|
40
|
+
}
|
|
41
|
+
type = types.join(" | ");
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Columns that are nullable or have default values can be ommitted from an insert
|
|
46
|
+
* Non nullable columns with default values cannot containt null values in an insert so they must contain a valid value or be omitted
|
|
47
|
+
*/
|
|
48
|
+
return `${escapeTSNames(c.name)}${c.is_nullable || c.has_default? "?" : ""}: ${type}`
|
|
49
|
+
}
|
|
50
|
+
tables.push(`${escapeTSNames(tov.name)}: {
|
|
51
|
+
is_view: ${tov.is_view};
|
|
52
|
+
select: ${tov.privileges.select};
|
|
53
|
+
insert: ${tov.privileges.insert};
|
|
54
|
+
update: ${tov.privileges.update};
|
|
55
|
+
delete: ${tov.privileges.delete};
|
|
56
|
+
columns: {${cols.map(c => `
|
|
57
|
+
${getColType(c)}`).join("")}
|
|
58
|
+
};
|
|
59
|
+
};\n `)
|
|
60
|
+
})
|
|
61
|
+
return `
|
|
62
|
+
export type DBSchemaGenerated = {
|
|
63
|
+
${tables.join("")}
|
|
64
|
+
}
|
|
65
|
+
`;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
type ServerViewHandler<T extends AnyObject = AnyObject, Schema extends DBSchema | void = void> = ViewHandler<T, Schema> & { is_view: boolean; }
|
|
69
|
+
type ServerTableHandler<T extends AnyObject = AnyObject, Schema extends DBSchema | void = void> = TableHandler<T, Schema> & { is_view: boolean; }
|
|
70
|
+
|
|
71
|
+
export type DBTableHandlersFromSchema<Schema = void> = Schema extends DBSchema? {
|
|
72
|
+
[tov_name in keyof Schema]: Schema[tov_name]["is_view"] extends true?
|
|
73
|
+
ServerViewHandler<Schema[tov_name]["columns"], Schema> :
|
|
74
|
+
ServerTableHandler<Schema[tov_name]["columns"], Schema>
|
|
75
|
+
} : Record<string, Partial<ServerTableHandler>>;
|
|
76
|
+
|
|
77
|
+
export type DBHandlerServerExtra<TH = Record<string, Partial<ServerTableHandler>>, WithTransactions = true> = {
|
|
78
|
+
sql: SQLHandler;
|
|
79
|
+
} & Partial<DbJoinMaker> & (
|
|
80
|
+
WithTransactions extends true? { tx: TX<TH> } :
|
|
81
|
+
Record<string, never>
|
|
82
|
+
);
|
|
83
|
+
// export type DBOFullyTyped<Schema = void> = Schema extends DBSchema? (
|
|
84
|
+
// DBTableHandlersFromSchema<Schema> & DBHandlerServerExtra<DBTableHandlersFromSchema<Schema>>
|
|
85
|
+
// ) :
|
|
86
|
+
// DBHandlerServer;
|
|
87
|
+
export type DBOFullyTyped<Schema = void> = DBTableHandlersFromSchema<Schema> & DBHandlerServerExtra<DBTableHandlersFromSchema<Schema>>
|
|
88
|
+
|
|
89
|
+
export type PublishFullyTyped<Schema = void> = Schema extends DBSchema? (
|
|
90
|
+
| PublishAllOrNothing
|
|
91
|
+
| {
|
|
92
|
+
[tov_name in keyof Partial<Schema>]:
|
|
93
|
+
| PublishAllOrNothing
|
|
94
|
+
| (
|
|
95
|
+
Schema[tov_name]["is_view"] extends true?
|
|
96
|
+
PublishViewRule<Schema[tov_name]["columns"], Schema> :
|
|
97
|
+
PublishTableRule<Schema[tov_name]["columns"], Schema>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
) : (
|
|
101
|
+
| PublishAllOrNothing
|
|
102
|
+
| Record<string, PublishViewRule | PublishTableRule | PublishAllOrNothing>
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
/** Type checks */
|
|
108
|
+
(() => {
|
|
109
|
+
|
|
110
|
+
const ddb: DBOFullyTyped = 1 as any;
|
|
111
|
+
ddb.dwad?.insert;
|
|
112
|
+
ddb.dwad?.delete;
|
|
113
|
+
|
|
114
|
+
const d: DBOFullyTyped<undefined> = 1 as any;
|
|
115
|
+
d.dwad?.insert;
|
|
116
|
+
d.dwad?.delete;
|
|
117
|
+
|
|
118
|
+
const p: PublishParams = 1 as any;
|
|
119
|
+
p.dbo.dwad?.insert;
|
|
120
|
+
ddb.dwad?.delete;
|
|
121
|
+
|
|
122
|
+
//@ts-ignore
|
|
123
|
+
prostgles({
|
|
124
|
+
dbConnection: 1 as any,
|
|
125
|
+
publish: async (params) => {
|
|
126
|
+
const _rows = await params.dbo.dwadwa?.find?.({});
|
|
127
|
+
|
|
128
|
+
return "*" as const
|
|
129
|
+
},
|
|
130
|
+
transactions: true,
|
|
131
|
+
onReady: ({ dbo }) => {
|
|
132
|
+
dbo.tdwa?.find!();
|
|
133
|
+
dbo.tx?.(t => {
|
|
134
|
+
t.dwa?.find!();
|
|
135
|
+
})
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
const _auth: Auth = {
|
|
141
|
+
sidKeyName: "sid_token",
|
|
142
|
+
getUser: async (sid, db, _db) => {
|
|
143
|
+
db.dwadaw?.find;
|
|
144
|
+
return 1 as any;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
type S = {
|
|
150
|
+
tbl1: {
|
|
151
|
+
columns: {
|
|
152
|
+
col1: number | null;
|
|
153
|
+
col2: string;
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
tbl2: {
|
|
157
|
+
columns: {
|
|
158
|
+
col1: number | null;
|
|
159
|
+
col2: string;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** Test the created schema */
|
|
165
|
+
const c: S = 1 as any;
|
|
166
|
+
const _test: DBSchema = c;
|
|
167
|
+
const dbt: DBOFullyTyped<S> = 1 as any;
|
|
168
|
+
|
|
169
|
+
dbt.tx!(t => {
|
|
170
|
+
t.tbl1.delete();
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
const db: DBHandlerServer = 1 as any;
|
|
174
|
+
db.tx!(t => {
|
|
175
|
+
t.wadwa?.find!()
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
const _publish = (): PublishFullyTyped<S> => {
|
|
179
|
+
const r = {
|
|
180
|
+
tbl1: {
|
|
181
|
+
select: {
|
|
182
|
+
fields: "*" as const,
|
|
183
|
+
forcedFilter: { col1: 32, col2: "" }
|
|
184
|
+
},
|
|
185
|
+
getColumns: true,
|
|
186
|
+
getInfo: true,
|
|
187
|
+
delete: {
|
|
188
|
+
filterFields: {col1: 1}
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
tbl2: {
|
|
192
|
+
delete: {
|
|
193
|
+
filterFields: "*" as const,
|
|
194
|
+
forcedFilter: {col1: 2}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
const res: PublishFullyTyped<S> = {
|
|
199
|
+
tbl1: {
|
|
200
|
+
select: {
|
|
201
|
+
fields: "*",
|
|
202
|
+
forcedFilter: { col1: 32, col2: "" }
|
|
203
|
+
},
|
|
204
|
+
getColumns: true,
|
|
205
|
+
getInfo: true,
|
|
206
|
+
delete: {
|
|
207
|
+
filterFields: { col1: 1 }
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
tbl2: {
|
|
211
|
+
delete: {
|
|
212
|
+
filterFields: "*" as const,
|
|
213
|
+
forcedFilter: { col1: 2 }
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
const _res1: PublishFullyTyped = r
|
|
218
|
+
|
|
219
|
+
const p: PublishParams<undefined> = 1 as any;
|
|
220
|
+
|
|
221
|
+
p.dbo.dwadaw?.find?.();
|
|
222
|
+
|
|
223
|
+
return res;
|
|
224
|
+
}
|
|
225
|
+
})
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
|
|
2
|
+
/*---------------------------------------------------------------------------------------------
|
|
3
|
+
* Copyright (c) Stefan L. All rights reserved.
|
|
4
|
+
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
|
5
|
+
*--------------------------------------------------------------------------------------------*/
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
PG_COLUMN_UDT_DATA_TYPE,
|
|
9
|
+
SQLOptions,
|
|
10
|
+
getJoinHandlers,
|
|
11
|
+
isDefined,
|
|
12
|
+
tryCatch
|
|
13
|
+
} from "prostgles-types";
|
|
14
|
+
import { getDBSchema } from "../DBSchemaBuilder";
|
|
15
|
+
import {
|
|
16
|
+
DB, Prostgles
|
|
17
|
+
} from "../Prostgles";
|
|
18
|
+
import { Join } from "../ProstglesTypes";
|
|
19
|
+
import { PubSubManager } from "../PubSubManager/PubSubManager";
|
|
20
|
+
import { getCreatePubSubManagerError } from "../PubSubManager/getCreatePubSubManagerError";
|
|
21
|
+
import {
|
|
22
|
+
DbTableInfo,
|
|
23
|
+
PublishParser
|
|
24
|
+
} from "../PublishParser/PublishParser";
|
|
25
|
+
import { Graph } from "../shortestPath";
|
|
26
|
+
import { clone } from "../utils";
|
|
27
|
+
import { DBHandlerServer, DbTxTableHandlers, LocalParams, TX, TableSchema, TxCB } from "./DboBuilderTypes";
|
|
28
|
+
import { QueryStreamer } from "./QueryStreamer";
|
|
29
|
+
import { TableHandler } from "./TableHandler/TableHandler";
|
|
30
|
+
import { JoinPaths, ViewHandler } from "./ViewHandler/ViewHandler";
|
|
31
|
+
import { parseJoinPath } from "./ViewHandler/parseJoinPath";
|
|
32
|
+
import { PGConstraint, getCanExecute, getConstraints, getErrorAsObject, getSerializedClientErrorFromPGError } from "./dboBuilderUtils";
|
|
33
|
+
import { getTablesForSchemaPostgresSQL } from "./getTablesForSchemaPostgresSQL";
|
|
34
|
+
import { prepareShortestJoinPaths } from "./prepareShortestJoinPaths";
|
|
35
|
+
import { cacheDBTypes, runSQL } from "./runSQL";
|
|
36
|
+
import { runClientTransactionStatement } from "./runTransaction";
|
|
37
|
+
|
|
38
|
+
export * from "./DboBuilderTypes";
|
|
39
|
+
export * from "./dboBuilderUtils";
|
|
40
|
+
|
|
41
|
+
type OidInfo = {
|
|
42
|
+
/**
|
|
43
|
+
* Oid
|
|
44
|
+
*/
|
|
45
|
+
relid: number;
|
|
46
|
+
relname: string;
|
|
47
|
+
schemaname: string;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
type TableOidInfo = OidInfo & {
|
|
51
|
+
pkey_columns: string[] | null;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
type TableOidColumnInfo = OidInfo & {
|
|
55
|
+
column_name: string;
|
|
56
|
+
udt_name: string;
|
|
57
|
+
ordinal_position: number;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
export class DboBuilder {
|
|
62
|
+
tablesOrViews?: TableSchema[];
|
|
63
|
+
/**
|
|
64
|
+
* Used in obtaining column names for error messages
|
|
65
|
+
*/
|
|
66
|
+
constraints?: PGConstraint[];
|
|
67
|
+
|
|
68
|
+
db: DB;
|
|
69
|
+
|
|
70
|
+
dbo: DBHandlerServer;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Undefined if cannot create table triggers
|
|
74
|
+
*/
|
|
75
|
+
private _pubSubManager?: PubSubManager;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Used for db.sql field type details
|
|
79
|
+
*/
|
|
80
|
+
DATA_TYPES: { oid: string, typname: PG_COLUMN_UDT_DATA_TYPE }[] | undefined;
|
|
81
|
+
DATA_TYPES_DBKEY = "";
|
|
82
|
+
USER_TABLES: TableOidInfo[] | undefined;
|
|
83
|
+
USER_TABLE_COLUMNS: TableOidColumnInfo[] | undefined;
|
|
84
|
+
|
|
85
|
+
queryStreamer: QueryStreamer;
|
|
86
|
+
|
|
87
|
+
get tables(): DbTableInfo[] {
|
|
88
|
+
return (this.tablesOrViews ?? [])
|
|
89
|
+
.map(({ name, columns }) => {
|
|
90
|
+
const info = this.dbo[name]?.tableOrViewInfo;
|
|
91
|
+
if(!info) return undefined;
|
|
92
|
+
return {
|
|
93
|
+
name,
|
|
94
|
+
columns,
|
|
95
|
+
info
|
|
96
|
+
}})
|
|
97
|
+
.filter(isDefined);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
getPubSubManager = async (): Promise<PubSubManager> => {
|
|
101
|
+
if (!this._pubSubManager) {
|
|
102
|
+
|
|
103
|
+
const canExecute = await getCanExecute(this.db)
|
|
104
|
+
if (!canExecute) throw "PubSubManager based subscriptions not possible: Cannot run EXECUTE statements on this connection";
|
|
105
|
+
|
|
106
|
+
const { pubSubManager, error, hasError } = await tryCatch(async () => {
|
|
107
|
+
const pubSubManager = await PubSubManager.create({
|
|
108
|
+
dboBuilder: this,
|
|
109
|
+
});
|
|
110
|
+
return { pubSubManager };
|
|
111
|
+
});
|
|
112
|
+
this._pubSubManager = pubSubManager;
|
|
113
|
+
if (hasError || !this._pubSubManager ) {
|
|
114
|
+
await this.prostgles.opts.onLog?.({
|
|
115
|
+
type: "debug",
|
|
116
|
+
command: "PubSubManager.create",
|
|
117
|
+
duration: 0,
|
|
118
|
+
error: getErrorAsObject(error)
|
|
119
|
+
});
|
|
120
|
+
throw "Could not create this._pubSubManager check logs";
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return this._pubSubManager;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
tsTypesDefinition?: string;
|
|
128
|
+
joinGraph?: Graph;
|
|
129
|
+
private shortestJoinPaths: JoinPaths = [];
|
|
130
|
+
|
|
131
|
+
prostgles: Prostgles;
|
|
132
|
+
publishParser?: PublishParser;
|
|
133
|
+
|
|
134
|
+
onSchemaChange?: (event: { command: string; query: string }) => void;
|
|
135
|
+
|
|
136
|
+
private constructor(prostgles: Prostgles) {
|
|
137
|
+
this.prostgles = prostgles;
|
|
138
|
+
if (!this.prostgles.db) throw "db missing"
|
|
139
|
+
this.db = this.prostgles.db;
|
|
140
|
+
this.dbo = {} as unknown as DBHandlerServer;
|
|
141
|
+
this.queryStreamer = new QueryStreamer(this);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
private init = async () => {
|
|
145
|
+
|
|
146
|
+
await this.build();
|
|
147
|
+
/* If watchSchema is enabled then PubSubManager must be created (if possible) because it creates the event trigger */
|
|
148
|
+
if (
|
|
149
|
+
this.prostgles.schemaWatch?.type.watchType === "DDL_trigger"
|
|
150
|
+
) {
|
|
151
|
+
await this.getPubSubManager()
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return this;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
public static create = async (prostgles: Prostgles): Promise<DboBuilder> => {
|
|
158
|
+
const res = new DboBuilder(prostgles)
|
|
159
|
+
return await res.init();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
destroy() {
|
|
164
|
+
this._pubSubManager?.destroy();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
_joins?: Join[];
|
|
168
|
+
get joins(): Join[] {
|
|
169
|
+
return clone(this._joins ?? []).filter(j => j.tables[0] !== j.tables[1]) as Join[];
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
set joins(j: Join[]) {
|
|
173
|
+
this._joins = clone(j);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
getAllJoinPaths() {
|
|
177
|
+
return this.shortestJoinPaths;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
prepareShortestJoinPaths = async () => {
|
|
181
|
+
const { joins, shortestJoinPaths, joinGraph } = await prepareShortestJoinPaths(this);
|
|
182
|
+
this.joinGraph = joinGraph;
|
|
183
|
+
this.joins = joins;
|
|
184
|
+
this.shortestJoinPaths = shortestJoinPaths;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
runSQL = async (query: string, params: any, options: SQLOptions | undefined, localParams?: LocalParams) => {
|
|
188
|
+
return runSQL.bind(this)(query, params, options, localParams).catch(error => Promise.reject(getSerializedClientErrorFromPGError(error, { type: "sql" })));
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
canSubscribe = false;
|
|
192
|
+
checkingCanSubscribe = false;
|
|
193
|
+
async build(): Promise<DBHandlerServer> {
|
|
194
|
+
if(!this.canSubscribe && !this.checkingCanSubscribe){
|
|
195
|
+
this.checkingCanSubscribe = true;
|
|
196
|
+
const subscribeError = await getCreatePubSubManagerError(this);
|
|
197
|
+
if(subscribeError){
|
|
198
|
+
console.error(
|
|
199
|
+
"Could not initiate PubSubManager. Realtime data/Subscriptions will not work. Error: ",
|
|
200
|
+
subscribeError
|
|
201
|
+
);
|
|
202
|
+
this.canSubscribe = false;
|
|
203
|
+
} else {
|
|
204
|
+
this.canSubscribe = true;
|
|
205
|
+
}
|
|
206
|
+
this.checkingCanSubscribe = false;
|
|
207
|
+
}
|
|
208
|
+
const start = Date.now();
|
|
209
|
+
const tablesOrViewsReq = await getTablesForSchemaPostgresSQL(this, this.prostgles.opts.schema);
|
|
210
|
+
await this.prostgles.opts.onLog?.({
|
|
211
|
+
type: "debug",
|
|
212
|
+
command: "DboBuilder.getTablesForSchemaPostgresSQL",
|
|
213
|
+
data: tablesOrViewsReq.durations,
|
|
214
|
+
duration: Date.now() - start,
|
|
215
|
+
})
|
|
216
|
+
this.tablesOrViews = tablesOrViewsReq.result;
|
|
217
|
+
|
|
218
|
+
this.constraints = await getConstraints(this.db, this.prostgles.opts.schema);
|
|
219
|
+
await this.prepareShortestJoinPaths();
|
|
220
|
+
|
|
221
|
+
this.dbo = {};
|
|
222
|
+
this.tablesOrViews.map(tov => {
|
|
223
|
+
const columnsForTypes = tov.columns.slice(0).sort((a, b) => a.name.localeCompare(b.name));
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
const filterKeywords = Object.values(this.prostgles.keywords);
|
|
227
|
+
const $filterCol = columnsForTypes.find(c => filterKeywords.includes(c.name));
|
|
228
|
+
if ($filterCol) {
|
|
229
|
+
throw `DboBuilder init error: \n\nTable ${JSON.stringify(tov.name)} column ${JSON.stringify($filterCol.name)} is colliding with Prostgles filtering functionality ($filter keyword)
|
|
230
|
+
Please provide a replacement keyword name using the $filter_keyName init option.
|
|
231
|
+
Alternatively you can rename the table column\n`;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
this.dbo[tov.escaped_identifier] = new (tov.is_view ? ViewHandler : TableHandler)(this.db, tov, this, undefined, this.shortestJoinPaths);
|
|
235
|
+
|
|
236
|
+
if (this.shortestJoinPaths && this.shortestJoinPaths.find(jp => [jp.t1, jp.t2].includes(tov.name))) {
|
|
237
|
+
|
|
238
|
+
const table = tov.name;
|
|
239
|
+
|
|
240
|
+
this.dbo.innerJoin ??= {};
|
|
241
|
+
this.dbo.leftJoin ??= {};
|
|
242
|
+
this.dbo.innerJoinOne ??= {};
|
|
243
|
+
this.dbo.leftJoinOne ??= {};
|
|
244
|
+
|
|
245
|
+
const joinHandlers = getJoinHandlers(table);
|
|
246
|
+
//@ts-ignore
|
|
247
|
+
this.dbo.leftJoin[table] = joinHandlers.leftJoin;
|
|
248
|
+
this.dbo.innerJoin[table] = joinHandlers.innerJoin;
|
|
249
|
+
this.dbo.leftJoinOne[table] = joinHandlers.leftJoinOne;
|
|
250
|
+
this.dbo.innerJoinOne[table] = joinHandlers.innerJoinOne;
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
if (this.prostgles.opts.transactions) {
|
|
255
|
+
let txKey = "tx";
|
|
256
|
+
if (typeof this.prostgles.opts.transactions === "string") txKey = this.prostgles.opts.transactions;
|
|
257
|
+
|
|
258
|
+
(this.dbo[txKey] as unknown as TX) = (cb: TxCB) => this.getTX(cb);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (!this.dbo.sql) {
|
|
262
|
+
|
|
263
|
+
this.dbo.sql = this.runSQL;
|
|
264
|
+
} else {
|
|
265
|
+
console.warn(`Could not create dbo.sql handler because there is already a table named "sql"`)
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
this.tsTypesDefinition = [
|
|
269
|
+
`/* SCHEMA DEFINITON. Table names have been altered to work with Typescript */`,
|
|
270
|
+
`/* DBO Definition */`,
|
|
271
|
+
getDBSchema(this)
|
|
272
|
+
].join("\n");
|
|
273
|
+
|
|
274
|
+
return this.dbo;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
getShortestJoinPath = (viewHandler: ViewHandler, target: string): JoinPaths[number] | undefined => {
|
|
278
|
+
const source = viewHandler.name;
|
|
279
|
+
if(source === target){
|
|
280
|
+
const joinPath = parseJoinPath({
|
|
281
|
+
rawPath: target,
|
|
282
|
+
rootTable: source,
|
|
283
|
+
viewHandler
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
if(!joinPath) return undefined;
|
|
287
|
+
|
|
288
|
+
return {
|
|
289
|
+
t1: source,
|
|
290
|
+
t2: target,
|
|
291
|
+
path: [source]
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const jp = this.shortestJoinPaths.find(jp => jp.t1 === source && jp.t2 === target);
|
|
296
|
+
return jp;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
getTX = async (cb: TxCB) => {
|
|
300
|
+
const transaction = await this.db.tx(t => {
|
|
301
|
+
const dbTX: DbTxTableHandlers & Pick<DBHandlerServer, "sql"> = {};
|
|
302
|
+
this.tablesOrViews?.map(tov => {
|
|
303
|
+
const handlerClass = tov.is_view ? ViewHandler : TableHandler;
|
|
304
|
+
dbTX[tov.name] = new handlerClass(this.db, tov, this, { t, dbTX }, this.shortestJoinPaths);
|
|
305
|
+
});
|
|
306
|
+
dbTX.sql = (q, args, opts, localP) => this.runSQL(q, args, opts, { tx: { dbTX, t }, ...(localP ?? {}) })
|
|
307
|
+
|
|
308
|
+
return cb(dbTX, t);
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
return transaction;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
cacheDBTypes = cacheDBTypes.bind(this);
|
|
315
|
+
|
|
316
|
+
runClientTransactionStatement = (statement: string) => {
|
|
317
|
+
return runClientTransactionStatement(statement, this.prostgles.opts.dbConnection as any);
|
|
318
|
+
}
|
|
319
|
+
}
|