prostgles-server 2.0.178 → 2.0.179
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/AuthHandler.d.ts +4 -4
- package/dist/AuthHandler.d.ts.map +1 -1
- package/dist/DBSchemaBuilder.d.ts +6 -6
- package/dist/DBSchemaBuilder.d.ts.map +1 -1
- package/dist/DBSchemaBuilder.js +25 -8
- package/dist/DBSchemaBuilder.js.map +1 -1
- package/dist/DboBuilder.d.ts +20 -21
- package/dist/DboBuilder.d.ts.map +1 -1
- package/dist/DboBuilder.js +1 -1
- package/dist/DboBuilder.js.map +1 -1
- package/dist/Prostgles.d.ts +8 -10
- package/dist/Prostgles.d.ts.map +1 -1
- package/dist/Prostgles.js.map +1 -1
- package/dist/PublishParser.d.ts +37 -37
- package/dist/PublishParser.d.ts.map +1 -1
- package/dist/PublishParser.js.map +1 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/lib/AuthHandler.d.ts +148 -0
- package/lib/AuthHandler.d.ts.map +1 -0
- package/lib/AuthHandler.js +411 -0
- package/lib/AuthHandler.ts +3 -3
- package/lib/DBEventsManager.d.ts +38 -0
- package/lib/DBEventsManager.d.ts.map +1 -0
- package/lib/DBEventsManager.js +136 -0
- package/lib/DBSchemaBuilder.d.ts +11 -0
- package/lib/DBSchemaBuilder.d.ts.map +1 -0
- package/lib/DBSchemaBuilder.js +102 -0
- package/lib/DBSchemaBuilder.ts +62 -27
- package/lib/DboBuilder.d.ts +428 -0
- package/lib/DboBuilder.d.ts.map +1 -0
- package/lib/DboBuilder.js +3078 -0
- package/lib/DboBuilder.ts +25 -25
- package/lib/FileManager.d.ts +168 -0
- package/lib/FileManager.d.ts.map +1 -0
- package/lib/FileManager.js +474 -0
- package/lib/Filtering.d.ts +15 -0
- package/lib/Filtering.d.ts.map +1 -0
- package/lib/Filtering.js +299 -0
- package/lib/PostgresNotifListenManager.d.ts +27 -0
- package/lib/PostgresNotifListenManager.d.ts.map +1 -0
- package/lib/PostgresNotifListenManager.js +122 -0
- package/lib/Prostgles.d.ts +193 -0
- package/lib/Prostgles.d.ts.map +1 -0
- package/lib/Prostgles.js +579 -0
- package/lib/Prostgles.ts +6 -6
- package/lib/PubSubManager.d.ts +157 -0
- package/lib/PubSubManager.d.ts.map +1 -0
- package/lib/PubSubManager.js +1400 -0
- package/lib/PublishParser.d.ts +262 -0
- package/lib/PublishParser.d.ts.map +1 -0
- package/lib/PublishParser.js +390 -0
- package/lib/PublishParser.ts +39 -38
- package/lib/QueryBuilder.d.ts +124 -0
- package/lib/QueryBuilder.d.ts.map +1 -0
- package/lib/QueryBuilder.js +1349 -0
- package/lib/SyncReplication.d.ts +34 -0
- package/lib/SyncReplication.d.ts.map +1 -0
- package/lib/SyncReplication.js +411 -0
- package/lib/TableConfig.d.ts +175 -0
- package/lib/TableConfig.d.ts.map +1 -0
- package/lib/TableConfig.js +231 -0
- package/lib/index.d.ts +10 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +45 -0
- package/lib/index.ts +3 -4
- package/lib/shortestPath.d.ts +10 -0
- package/lib/shortestPath.d.ts.map +1 -0
- package/lib/shortestPath.js +111 -0
- package/lib/utils.d.ts +2 -0
- package/lib/utils.d.ts.map +1 -0
- package/lib/utils.js +5 -0
- package/package.json +3 -3
- package/tests/client/PID.txt +1 -1
- package/tests/client/index.d.ts +1 -1
- package/tests/client/index.d.ts.map +1 -1
- package/tests/client_only_queries.d.ts +4 -0
- package/tests/client_only_queries.d.ts.map +1 -0
- package/tests/isomorphic_queries.d.ts +6 -0
- package/tests/isomorphic_queries.d.ts.map +1 -0
- package/tests/server/DBoGenerated.d.ts +97 -193
- package/tests/server/dboTypeCheck.d.ts +2 -0
- package/tests/server/dboTypeCheck.d.ts.map +1 -0
- package/tests/server/dboTypeCheck.js +14 -0
- package/tests/server/dboTypeCheck.ts +17 -0
- package/tests/server/index.d.ts +2 -0
- package/tests/server/index.d.ts.map +1 -0
- package/tests/server/index.js +11 -11
- package/tests/server/index.ts +23 -16
- package/tests/server/package-lock.json +5 -5
- package/tests/server/publishTypeCheck.d.ts +2 -0
- package/tests/server/publishTypeCheck.d.ts.map +1 -0
- package/tests/server/publishTypeCheck.js +120 -0
- package/tests/server/publishTypeCheck.ts +129 -0
- package/tests/server/tsconfig.json +4 -5
- package/tests/server_only_queries.d.ts +2 -0
- package/tests/server_only_queries.d.ts.map +1 -0
package/lib/Filtering.js
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseFilterItem = void 0;
|
|
4
|
+
const prostgles_types_1 = require("prostgles-types");
|
|
5
|
+
const DboBuilder_1 = require("./DboBuilder");
|
|
6
|
+
const parseFilterItem = (args) => {
|
|
7
|
+
const { filter: _f, select, tableAlias, pgp } = args;
|
|
8
|
+
if (!_f || (0, prostgles_types_1.isEmpty)(_f))
|
|
9
|
+
return "";
|
|
10
|
+
const mErr = (msg) => {
|
|
11
|
+
throw `${msg}: ${JSON.stringify(_f, null, 2)}`;
|
|
12
|
+
}, asValue = (v) => pgp.as.format("$1", [v]);
|
|
13
|
+
const fKeys = (0, prostgles_types_1.getKeys)(_f);
|
|
14
|
+
if (fKeys.length === 0) {
|
|
15
|
+
return "";
|
|
16
|
+
}
|
|
17
|
+
else if (fKeys.length > 1) {
|
|
18
|
+
return fKeys.map(fk => (0, exports.parseFilterItem)({
|
|
19
|
+
filter: { [fk]: _f[fk] },
|
|
20
|
+
select,
|
|
21
|
+
tableAlias,
|
|
22
|
+
pgp,
|
|
23
|
+
}))
|
|
24
|
+
.sort() /* sorted to ensure duplicate subscription channels are not created due to different condition order */
|
|
25
|
+
.join(" AND ");
|
|
26
|
+
}
|
|
27
|
+
const fKey = fKeys[0];
|
|
28
|
+
/* Exists filter */
|
|
29
|
+
if (prostgles_types_1.EXISTS_KEYS.find(k => k in _f)) {
|
|
30
|
+
// parseExistsFilter()
|
|
31
|
+
}
|
|
32
|
+
let selItem;
|
|
33
|
+
if (select)
|
|
34
|
+
selItem = select.find(s => fKey === s.alias);
|
|
35
|
+
let rightF = _f[fKey];
|
|
36
|
+
const getLeftQ = (selItm) => {
|
|
37
|
+
if (selItm.type === "function")
|
|
38
|
+
return selItm.getQuery();
|
|
39
|
+
return selItm.getQuery(tableAlias);
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Parsed left side of the query
|
|
43
|
+
*/
|
|
44
|
+
let leftQ; // = asName(selItem.alias);
|
|
45
|
+
/* Check if string notation. Build obj if necessary */
|
|
46
|
+
const dot_notation_delims = ["->", "."];
|
|
47
|
+
if (!selItem) {
|
|
48
|
+
/* See if dot notation. Pick the best matching starting string */
|
|
49
|
+
if (select) {
|
|
50
|
+
selItem = select.find(s => fKey.startsWith(s.alias) &&
|
|
51
|
+
dot_notation_delims.find(dn => fKey.slice(s.alias.length).startsWith(dn)));
|
|
52
|
+
}
|
|
53
|
+
if (!selItem) {
|
|
54
|
+
mErr("Bad filter. Could not match to a column or alias: ");
|
|
55
|
+
throw " ";
|
|
56
|
+
}
|
|
57
|
+
const remainingStr = fKey.slice(selItem.alias.length);
|
|
58
|
+
/* Is json path spec */
|
|
59
|
+
if (remainingStr.startsWith("->")) {
|
|
60
|
+
leftQ = getLeftQ(selItem);
|
|
61
|
+
const getSep = (fromIdx = 0) => {
|
|
62
|
+
const strPart = remainingStr.slice(fromIdx);
|
|
63
|
+
let idx = strPart.indexOf("->");
|
|
64
|
+
let idxx = strPart.indexOf("->>");
|
|
65
|
+
if (idx > -1) {
|
|
66
|
+
/* if -> matches then check if it's the last separator */
|
|
67
|
+
if (idx === idxx)
|
|
68
|
+
return { idx: idx + fromIdx, sep: "->>" };
|
|
69
|
+
return { idx: idx + fromIdx, sep: "->" };
|
|
70
|
+
}
|
|
71
|
+
idx = strPart.indexOf("->>");
|
|
72
|
+
if (idx > -1) {
|
|
73
|
+
return { idx: idx + fromIdx, sep: "->>" };
|
|
74
|
+
}
|
|
75
|
+
return undefined;
|
|
76
|
+
};
|
|
77
|
+
let currSep = getSep();
|
|
78
|
+
while (currSep) {
|
|
79
|
+
let nextSep = getSep(currSep.idx + currSep.sep.length);
|
|
80
|
+
let nextIdx = nextSep ? nextSep.idx : remainingStr.length;
|
|
81
|
+
/* If ending in set then add set as well into key */
|
|
82
|
+
if (nextSep && nextIdx + nextSep.sep.length === remainingStr.length) {
|
|
83
|
+
nextIdx = remainingStr.length;
|
|
84
|
+
nextSep = undefined;
|
|
85
|
+
}
|
|
86
|
+
// console.log({ currSep, nextSep })
|
|
87
|
+
leftQ += currSep.sep + asValue(remainingStr.slice(currSep.idx + currSep.sep.length, nextIdx));
|
|
88
|
+
currSep = nextSep;
|
|
89
|
+
}
|
|
90
|
+
/* Is collapsed filter spec e.g. { "col.$ilike": 'text' } */
|
|
91
|
+
}
|
|
92
|
+
else if (remainingStr.startsWith(".")) {
|
|
93
|
+
leftQ = getLeftQ(selItem);
|
|
94
|
+
let getSep = (fromIdx = 0) => {
|
|
95
|
+
const idx = remainingStr.slice(fromIdx).indexOf(".");
|
|
96
|
+
if (idx > -1)
|
|
97
|
+
return fromIdx + idx;
|
|
98
|
+
return idx;
|
|
99
|
+
};
|
|
100
|
+
let currIdx = getSep();
|
|
101
|
+
let res = {};
|
|
102
|
+
let curObj = res;
|
|
103
|
+
while (currIdx > -1) {
|
|
104
|
+
let nextIdx = getSep(currIdx + 1);
|
|
105
|
+
let nIdx = nextIdx > -1 ? nextIdx : remainingStr.length;
|
|
106
|
+
/* If ending in dot then add dot as well into key */
|
|
107
|
+
if (nextIdx + 1 === remainingStr.length) {
|
|
108
|
+
nIdx = remainingStr.length;
|
|
109
|
+
nextIdx = -1;
|
|
110
|
+
}
|
|
111
|
+
const key = remainingStr.slice(currIdx + 1, nIdx);
|
|
112
|
+
curObj[key] = nextIdx > -1 ? {} : _f[fKey];
|
|
113
|
+
curObj = curObj[key];
|
|
114
|
+
currIdx = nextIdx;
|
|
115
|
+
}
|
|
116
|
+
rightF = res;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
console.trace(141, select, selItem, remainingStr);
|
|
120
|
+
mErr("Bad filter. Could not find the valid col name or alias or col json path");
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
leftQ = getLeftQ(selItem);
|
|
125
|
+
}
|
|
126
|
+
if (!leftQ)
|
|
127
|
+
mErr("Internal error: leftQ missing?!");
|
|
128
|
+
/* Matching sel item */
|
|
129
|
+
if ((0, DboBuilder_1.isPlainObject)(rightF)) {
|
|
130
|
+
const parseRightVal = (val, expect = null) => {
|
|
131
|
+
const checkIfArr = () => {
|
|
132
|
+
if (!Array.isArray(val))
|
|
133
|
+
return mErr("This type of filter/column expects an Array of items");
|
|
134
|
+
};
|
|
135
|
+
if (expect === "csv") {
|
|
136
|
+
checkIfArr();
|
|
137
|
+
return pgp.as.format("($1:csv)", [val]);
|
|
138
|
+
}
|
|
139
|
+
else if (expect === "array" || selItem && selItem.columnPGDataType && selItem.columnPGDataType === "ARRAY") {
|
|
140
|
+
checkIfArr();
|
|
141
|
+
return pgp.as.format(" ARRAY[$1:csv]", [val]);
|
|
142
|
+
}
|
|
143
|
+
return asValue(val);
|
|
144
|
+
};
|
|
145
|
+
const filterKeys = Object.keys(rightF);
|
|
146
|
+
if (filterKeys.length !== 1)
|
|
147
|
+
mErr("Bad filter. Expecting one key only");
|
|
148
|
+
const fOpType = filterKeys[0];
|
|
149
|
+
const fVal = rightF[fOpType];
|
|
150
|
+
let sOpType;
|
|
151
|
+
let sVal;
|
|
152
|
+
if (fVal && (0, DboBuilder_1.isPlainObject)(fVal)) {
|
|
153
|
+
const keys = Object.keys(fVal);
|
|
154
|
+
if (!keys.length || keys.length !== 1) {
|
|
155
|
+
return mErr("Bad filter. Expecting a nested object with one key only ");
|
|
156
|
+
}
|
|
157
|
+
sOpType = keys[0];
|
|
158
|
+
sVal = fVal[sOpType];
|
|
159
|
+
}
|
|
160
|
+
// console.log({ fOpType, fVal, sOpType })
|
|
161
|
+
/** JSON cannot be compared so we'll cast it to TEXT */
|
|
162
|
+
if (selItem?.column_udt_type === "json" || ["$ilike", "$like", "$nilike", "$nlike"].includes(fOpType)) {
|
|
163
|
+
leftQ += "::TEXT ";
|
|
164
|
+
}
|
|
165
|
+
/** st_makeenvelope */
|
|
166
|
+
if (prostgles_types_1.GeomFilterKeys.includes(fOpType) && sOpType && prostgles_types_1.GeomFilter_Funcs.includes(sOpType)) {
|
|
167
|
+
/** If leftQ is geography then this err can happen: 'Antipodal (180 degrees long) edge detected!' */
|
|
168
|
+
if (sOpType.toLowerCase() === "st_makeenvelope")
|
|
169
|
+
leftQ += "::geometry";
|
|
170
|
+
return leftQ + ` ${fOpType} ` + `${sOpType}${parseRightVal(sVal, "csv")}`;
|
|
171
|
+
}
|
|
172
|
+
else if (["=", "$eq"].includes(fOpType) && !sOpType) {
|
|
173
|
+
if (fVal === null)
|
|
174
|
+
return leftQ + " IS NULL ";
|
|
175
|
+
return leftQ + " = " + parseRightVal(fVal);
|
|
176
|
+
}
|
|
177
|
+
else if (["<>", "$ne"].includes(fOpType)) {
|
|
178
|
+
if (fVal === null)
|
|
179
|
+
return leftQ + " IS NOT NULL ";
|
|
180
|
+
return leftQ + " <> " + parseRightVal(fVal);
|
|
181
|
+
}
|
|
182
|
+
else if ([">", "$gt"].includes(fOpType)) {
|
|
183
|
+
return leftQ + " > " + parseRightVal(fVal);
|
|
184
|
+
}
|
|
185
|
+
else if (["<", "$lt"].includes(fOpType)) {
|
|
186
|
+
return leftQ + " < " + parseRightVal(fVal);
|
|
187
|
+
}
|
|
188
|
+
else if ([">=", "$gte"].includes(fOpType)) {
|
|
189
|
+
return leftQ + " >= " + parseRightVal(fVal);
|
|
190
|
+
}
|
|
191
|
+
else if (["<=", "$lte"].includes(fOpType)) {
|
|
192
|
+
return leftQ + " <= " + parseRightVal(fVal);
|
|
193
|
+
}
|
|
194
|
+
else if (["$in"].includes(fOpType)) {
|
|
195
|
+
if (!fVal?.length) {
|
|
196
|
+
return " FALSE ";
|
|
197
|
+
}
|
|
198
|
+
let _fVal = fVal.filter((v) => v !== null);
|
|
199
|
+
let c1 = "", c2 = "";
|
|
200
|
+
if (_fVal.length)
|
|
201
|
+
c1 = leftQ + " IN " + parseRightVal(_fVal, "csv");
|
|
202
|
+
if (fVal.includes(null))
|
|
203
|
+
c2 = ` ${leftQ} IS NULL `;
|
|
204
|
+
return [c1, c2].filter(c => c).join(" OR ");
|
|
205
|
+
}
|
|
206
|
+
else if (["$nin"].includes(fOpType)) {
|
|
207
|
+
if (!fVal?.length) {
|
|
208
|
+
return " TRUE ";
|
|
209
|
+
}
|
|
210
|
+
let _fVal = fVal.filter((v) => v !== null);
|
|
211
|
+
let c1 = "", c2 = "";
|
|
212
|
+
if (_fVal.length)
|
|
213
|
+
c1 = leftQ + " NOT IN " + parseRightVal(_fVal, "csv");
|
|
214
|
+
if (fVal.includes(null))
|
|
215
|
+
c2 = ` ${leftQ} IS NOT NULL `;
|
|
216
|
+
return [c1, c2].filter(c => c).join(" AND ");
|
|
217
|
+
}
|
|
218
|
+
else if (["$between"].includes(fOpType)) {
|
|
219
|
+
if (!Array.isArray(fVal) || fVal.length !== 2) {
|
|
220
|
+
return mErr("Between filter expects an array of two values");
|
|
221
|
+
}
|
|
222
|
+
return leftQ + " BETWEEN " + asValue(fVal[0]) + " AND " + asValue(fVal[1]);
|
|
223
|
+
}
|
|
224
|
+
else if (["$ilike"].includes(fOpType)) {
|
|
225
|
+
return leftQ + " ILIKE " + asValue(fVal);
|
|
226
|
+
}
|
|
227
|
+
else if (["$like"].includes(fOpType)) {
|
|
228
|
+
return leftQ + " LIKE " + asValue(fVal);
|
|
229
|
+
}
|
|
230
|
+
else if (["$nilike"].includes(fOpType)) {
|
|
231
|
+
return leftQ + " NOT ILIKE " + asValue(fVal);
|
|
232
|
+
}
|
|
233
|
+
else if (["$nlike"].includes(fOpType)) {
|
|
234
|
+
return leftQ + " NOT LIKE " + asValue(fVal);
|
|
235
|
+
/* MAYBE TEXT OR MAYBE ARRAY */
|
|
236
|
+
}
|
|
237
|
+
else if (["@>", "<@", "$contains", "$containedBy", "&&", "@@"].includes(fOpType)) {
|
|
238
|
+
let operand = fOpType === "@@" ? "@@" :
|
|
239
|
+
["@>", "$contains"].includes(fOpType) ? "@>" :
|
|
240
|
+
["&&"].includes(fOpType) ? "&&" :
|
|
241
|
+
"<@";
|
|
242
|
+
/* Array for sure */
|
|
243
|
+
if (Array.isArray(fVal)) {
|
|
244
|
+
return leftQ + operand + parseRightVal(fVal, "array");
|
|
245
|
+
/* FTSQuery */
|
|
246
|
+
}
|
|
247
|
+
else if (["@@"].includes(fOpType) && prostgles_types_1.TextFilter_FullTextSearchFilterKeys.includes(sOpType)) {
|
|
248
|
+
let lq = `to_tsvector(${leftQ}::text)`;
|
|
249
|
+
if (selItem && selItem.columnPGDataType === "tsvector")
|
|
250
|
+
lq = leftQ;
|
|
251
|
+
let res = `${lq} ${operand} ` + `${sOpType}${parseRightVal(sVal, "csv")}`;
|
|
252
|
+
return res;
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
return mErr("Unrecognised filter operand: " + fOpType + " ");
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
/** Maybe it's an object key which means it's an equality comparison against a json object */
|
|
260
|
+
if (selItem?.column_udt_type?.startsWith("json")) {
|
|
261
|
+
return leftQ + " = " + parseRightVal(rightF);
|
|
262
|
+
}
|
|
263
|
+
return mErr("Unrecognised filter operand: " + fOpType + " ");
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
/* Is an equal filter */
|
|
268
|
+
if (rightF === null) {
|
|
269
|
+
return leftQ + " IS NULL ";
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
return leftQ + " = " + asValue(rightF);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
exports.parseFilterItem = parseFilterItem;
|
|
277
|
+
// ensure pgp is not NULL!!!
|
|
278
|
+
// const asValue = v => v;// pgp.as.value;
|
|
279
|
+
// const filters: FilterSpec[] = [
|
|
280
|
+
// ...(["ilike", "like"].map(op => ({
|
|
281
|
+
// operands: ["$" + op],
|
|
282
|
+
// tsDataTypes: ["any"] as TSDataType[],
|
|
283
|
+
// tsDefinition: ` { $${op}: string } `,
|
|
284
|
+
// // data_types:
|
|
285
|
+
// getQuery: (leftQuery: string, rightVal: any) => {
|
|
286
|
+
// return `${leftQuery}::text ${op.toUpperCase()} ${asValue(rightVal)}::text`
|
|
287
|
+
// }
|
|
288
|
+
// }))),
|
|
289
|
+
// {
|
|
290
|
+
// operands: ["", "="],
|
|
291
|
+
// tsDataTypes: ["any"],
|
|
292
|
+
// tsDefinition: ` { "=": any } | any `,
|
|
293
|
+
// // data_types:
|
|
294
|
+
// getQuery: (leftQuery: string, rightVal: any) => {
|
|
295
|
+
// if(rightVal === null) return`${leftQuery} IS NULL `;
|
|
296
|
+
// return `${leftQuery} = ${asValue(rightVal)}`;
|
|
297
|
+
// }
|
|
298
|
+
// }
|
|
299
|
+
// ];
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { DB } from "./Prostgles";
|
|
2
|
+
import pg from "pg-promise/typescript/pg-subset";
|
|
3
|
+
import pgPromise from "pg-promise";
|
|
4
|
+
export declare type PrglNotifListener = (args: {
|
|
5
|
+
length: number;
|
|
6
|
+
processId: number;
|
|
7
|
+
channel: string;
|
|
8
|
+
payload: string;
|
|
9
|
+
name: string;
|
|
10
|
+
}) => void;
|
|
11
|
+
export declare class PostgresNotifListenManager {
|
|
12
|
+
connection?: pgPromise.IConnected<{}, pg.IClient>;
|
|
13
|
+
db_pg: DB;
|
|
14
|
+
notifListener: PrglNotifListener;
|
|
15
|
+
db_channel_name: string;
|
|
16
|
+
isListening: any;
|
|
17
|
+
client: any;
|
|
18
|
+
static create: (db_pg: DB, notifListener: PrglNotifListener, db_channel_name: string) => Promise<PostgresNotifListenManager>;
|
|
19
|
+
constructor(db_pg: DB, notifListener: PrglNotifListener, db_channel_name: string, noInit?: boolean);
|
|
20
|
+
init(): Promise<PostgresNotifListenManager>;
|
|
21
|
+
isReady(): any;
|
|
22
|
+
startListening(): Promise<unknown>;
|
|
23
|
+
destroy: () => void;
|
|
24
|
+
stopListening: () => void;
|
|
25
|
+
reconnect(delay?: number | undefined, maxAttempts?: number | undefined): Promise<unknown>;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=PostgresNotifListenManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PostgresNotifListenManager.d.ts","sourceRoot":"","sources":["PostgresNotifListenManager.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,MAAM,iCAAiC,CAAC;AACjD,OAAO,SAAS,MAAM,YAAY,CAAC;AAEnC,oBAAY,iBAAiB,GAAG,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;CAAE,KAAK,IAAI,CAAC;AACvI,qBAAa,0BAA0B;IACnC,UAAU,CAAC,EAAE,SAAS,CAAC,UAAU,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC;IAClD,KAAK,EAAE,EAAE,CAAC;IACV,aAAa,EAAE,iBAAiB,CAAC;IACjC,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,GAAG,CAAC;IACjB,MAAM,EAAE,GAAG,CAAC;IAEZ,MAAM,CAAC,MAAM,6BAA8B,iBAAiB,mBAAmB,MAAM,KAAG,QAAQ,0BAA0B,CAAC,CAG1H;gBAEW,KAAK,EAAE,EAAE,EAAE,aAAa,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,UAAQ;IAS1F,IAAI,IAAI,OAAO,CAAC,0BAA0B,CAAC;IAQjD,OAAO;IAIP,cAAc;IA+Bd,OAAO,aAEN;IAED,aAAa,aAKZ;IAED,SAAS,CAAC,KAAK,GAAE,MAAM,GAAG,SAAa,EAAE,WAAW,GAAE,MAAM,GAAG,SAAa;CAsD/E"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.PostgresNotifListenManager = void 0;
|
|
8
|
+
class PostgresNotifListenManager {
|
|
9
|
+
constructor(db_pg, notifListener, db_channel_name, noInit = false) {
|
|
10
|
+
this.destroy = () => {
|
|
11
|
+
if (this.connection)
|
|
12
|
+
this.connection.done();
|
|
13
|
+
};
|
|
14
|
+
this.stopListening = () => {
|
|
15
|
+
if (this.db_channel_name) {
|
|
16
|
+
if (this.connection)
|
|
17
|
+
this.connection.none('UNLISTEN $1~', this.db_channel_name);
|
|
18
|
+
if (this.client)
|
|
19
|
+
this.client.query('UNLISTEN $1~', this.db_channel_name);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
if (!db_pg || !notifListener || !db_channel_name)
|
|
23
|
+
throw "PostgresNotifListenManager: db_pg OR notifListener OR db_channel_name MISSING";
|
|
24
|
+
this.db_pg = db_pg;
|
|
25
|
+
this.notifListener = notifListener;
|
|
26
|
+
this.db_channel_name = db_channel_name;
|
|
27
|
+
if (!noInit)
|
|
28
|
+
this.init();
|
|
29
|
+
}
|
|
30
|
+
async init() {
|
|
31
|
+
this.connection = undefined;
|
|
32
|
+
this.isListening = await this.startListening();
|
|
33
|
+
return this;
|
|
34
|
+
}
|
|
35
|
+
isReady() {
|
|
36
|
+
return this.isListening;
|
|
37
|
+
}
|
|
38
|
+
startListening() {
|
|
39
|
+
if (!this.db_pg || !this.notifListener)
|
|
40
|
+
throw "PostgresNotifListenManager: db_pg OR notifListener missing";
|
|
41
|
+
return this.reconnect() // = same as reconnect(0, 1)
|
|
42
|
+
.then(obj => {
|
|
43
|
+
return obj;
|
|
44
|
+
/* TODO: expose this within onReady */
|
|
45
|
+
// console.log('psqlWS - Successful Initial Connection');
|
|
46
|
+
// obj.done(); - releases the connection
|
|
47
|
+
/* HOW TO SEND NOTIF
|
|
48
|
+
Used for testing in conjunction with
|
|
49
|
+
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname='db-name';
|
|
50
|
+
|
|
51
|
+
function sendNotifications() {
|
|
52
|
+
if (this.connection) {
|
|
53
|
+
this.connection.none('NOTIFY $1~, $2', [this.db_channel_name, 'my payload string'])
|
|
54
|
+
.catch(error => {
|
|
55
|
+
console.log('psqlWS - Failed to Notify:', error); // unlikely to ever happen
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
*/
|
|
60
|
+
})
|
|
61
|
+
.catch(error => {
|
|
62
|
+
console.log('PostgresNotifListenManager: Failed Initial Connection:', error);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
reconnect(delay = 0, maxAttempts = 0) {
|
|
66
|
+
if (!this.db_pg || !this.notifListener)
|
|
67
|
+
throw "db_pg OR notifListener missing";
|
|
68
|
+
delay = delay > 0 ? parseInt(delay + "") : 0;
|
|
69
|
+
maxAttempts = maxAttempts > 0 ? parseInt(maxAttempts + "") : 1;
|
|
70
|
+
const setListeners = (client, notifListener, db_channel_name) => {
|
|
71
|
+
client.on('notification', notifListener);
|
|
72
|
+
this.client = client;
|
|
73
|
+
if (!this.connection)
|
|
74
|
+
throw "Connection missing";
|
|
75
|
+
return this.connection.none('LISTEN $1~', db_channel_name)
|
|
76
|
+
.catch(error => {
|
|
77
|
+
console.log("PostgresNotifListenManager: unexpected error: ", error); // unlikely to ever happen
|
|
78
|
+
});
|
|
79
|
+
}, removeListeners = (client) => {
|
|
80
|
+
client.removeListener('notification', this.notifListener);
|
|
81
|
+
}, onConnectionLost = (err, e) => {
|
|
82
|
+
console.log('PostgresNotifListenManager: Connectivity Problem:', err);
|
|
83
|
+
this.connection = undefined; // prevent use of the broken connection
|
|
84
|
+
removeListeners(e.client);
|
|
85
|
+
this.reconnect(5000, 10) // retry 10 times, with 5-second intervals
|
|
86
|
+
.then(() => {
|
|
87
|
+
console.log('PostgresNotifListenManager: Successfully Reconnected');
|
|
88
|
+
})
|
|
89
|
+
.catch(() => {
|
|
90
|
+
// failed after 10 attempts
|
|
91
|
+
console.log('PostgresNotifListenManager: Connection Lost Permanently. TERMINATING NODE PROCESS');
|
|
92
|
+
process.exit(); // exiting the process
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
return new Promise((resolve, reject) => {
|
|
96
|
+
setTimeout(() => {
|
|
97
|
+
this.db_pg.connect({ direct: true, onLost: onConnectionLost })
|
|
98
|
+
.then(obj => {
|
|
99
|
+
this.connection = obj; // global connection is now available
|
|
100
|
+
resolve(obj);
|
|
101
|
+
return setListeners(obj.client, this.notifListener, this.db_channel_name);
|
|
102
|
+
})
|
|
103
|
+
.catch(error => {
|
|
104
|
+
console.log('PostgresNotifListenManager: Error Connecting:', error);
|
|
105
|
+
if (--maxAttempts) {
|
|
106
|
+
this.reconnect(delay, maxAttempts)
|
|
107
|
+
.then(resolve)
|
|
108
|
+
.catch(reject);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
reject(error);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}, delay);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
exports.PostgresNotifListenManager = PostgresNotifListenManager;
|
|
119
|
+
PostgresNotifListenManager.create = (db_pg, notifListener, db_channel_name) => {
|
|
120
|
+
let res = new PostgresNotifListenManager(db_pg, notifListener, db_channel_name, true);
|
|
121
|
+
return res.init();
|
|
122
|
+
};
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import * as pgPromise from 'pg-promise';
|
|
2
|
+
import pg = require('pg-promise/typescript/pg-subset');
|
|
3
|
+
import FileManager, { ImageOptions, LocalConfig, S3Config } from "./FileManager";
|
|
4
|
+
import AuthHandler, { Auth } from "./AuthHandler";
|
|
5
|
+
import TableConfigurator, { TableConfig } from "./TableConfig";
|
|
6
|
+
import { DboBuilder, DBHandlerServer, PRGLIOSocket } from "./DboBuilder";
|
|
7
|
+
export { DBHandlerServer };
|
|
8
|
+
export declare type PGP = pgPromise.IMain<{}, pg.IClient>;
|
|
9
|
+
import { AnyObject } from "prostgles-types";
|
|
10
|
+
import { Publish, PublishMethods, PublishParams, PublishParser } from "./PublishParser";
|
|
11
|
+
import { DBEventsManager } from "./DBEventsManager";
|
|
12
|
+
export declare type DB = pgPromise.IDatabase<{}, pg.IClient>;
|
|
13
|
+
declare type DbConnection = string | pg.IConnectionParameters<pg.IClient>;
|
|
14
|
+
declare type DbConnectionOpts = pg.IDefaults;
|
|
15
|
+
export declare const TABLE_METHODS: readonly ["update", "find", "findOne", "insert", "delete", "upsert"];
|
|
16
|
+
export declare const JOIN_TYPES: readonly ["one-many", "many-one", "one-one", "many-many"];
|
|
17
|
+
export declare type Join = {
|
|
18
|
+
tables: [string, string];
|
|
19
|
+
on: {
|
|
20
|
+
[key: string]: string;
|
|
21
|
+
};
|
|
22
|
+
type: typeof JOIN_TYPES[number];
|
|
23
|
+
};
|
|
24
|
+
export declare type Joins = Join[] | "inferred";
|
|
25
|
+
declare type Keywords = {
|
|
26
|
+
$and: string;
|
|
27
|
+
$or: string;
|
|
28
|
+
$not: string;
|
|
29
|
+
};
|
|
30
|
+
export declare type DeepPartial<T> = {
|
|
31
|
+
[P in keyof T]?: DeepPartial<T[P]>;
|
|
32
|
+
};
|
|
33
|
+
declare type ExpressApp = {
|
|
34
|
+
get: (routePath: string, cb: (req: {
|
|
35
|
+
params: {
|
|
36
|
+
name: string;
|
|
37
|
+
};
|
|
38
|
+
cookies: {
|
|
39
|
+
sid: string;
|
|
40
|
+
};
|
|
41
|
+
}, res: {
|
|
42
|
+
redirect: (redirectUrl: string) => any;
|
|
43
|
+
contentType: (type: string) => void;
|
|
44
|
+
sendFile: (fileName: string, opts?: {
|
|
45
|
+
root: string;
|
|
46
|
+
}) => any;
|
|
47
|
+
status: (code: number) => {
|
|
48
|
+
json: (response: AnyObject) => any;
|
|
49
|
+
};
|
|
50
|
+
}) => any) => any;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Allows uploading and downloading files.
|
|
54
|
+
* Currently supports only S3.
|
|
55
|
+
*
|
|
56
|
+
* @description
|
|
57
|
+
* Will create a media table that contains file metadata and urls
|
|
58
|
+
* Inserting a file into this table through prostgles will upload it to S3 and insert the relevant metadata into the media table
|
|
59
|
+
* Requesting a file from HTTP GET {fileUrlPath}/{fileId} will:
|
|
60
|
+
* 1. check auth (if provided)
|
|
61
|
+
* 2. check the permissions in publish (if provided)
|
|
62
|
+
* 3. redirect the request to the signed url (if allowed)
|
|
63
|
+
*
|
|
64
|
+
* Specifying referencedTables will:
|
|
65
|
+
* 1. create a column in that table called media
|
|
66
|
+
* 2. create a lookup table lookup_media_{referencedTable} that joins referencedTable to the media table
|
|
67
|
+
*/
|
|
68
|
+
export declare type FileTableConfig = {
|
|
69
|
+
tableName?: string;
|
|
70
|
+
/**
|
|
71
|
+
* GET path used in serving media. defaults to /${tableName}
|
|
72
|
+
*/
|
|
73
|
+
fileServeRoute?: string;
|
|
74
|
+
awsS3Config?: S3Config;
|
|
75
|
+
localConfig?: LocalConfig;
|
|
76
|
+
expressApp: ExpressApp;
|
|
77
|
+
referencedTables?: {
|
|
78
|
+
[tableName: string]: "one" | "many";
|
|
79
|
+
};
|
|
80
|
+
imageOptions?: ImageOptions;
|
|
81
|
+
};
|
|
82
|
+
export declare type ProstglesInitOptions<S = void> = {
|
|
83
|
+
dbConnection: DbConnection;
|
|
84
|
+
dbOptions?: DbConnectionOpts;
|
|
85
|
+
tsGeneratedTypesDir?: string;
|
|
86
|
+
io?: any;
|
|
87
|
+
publish?: Publish<S>;
|
|
88
|
+
publishMethods?: PublishMethods<S>;
|
|
89
|
+
publishRawSQL?(params: PublishParams<S>): ((boolean | "*") | Promise<(boolean | "*")>);
|
|
90
|
+
joins?: Joins;
|
|
91
|
+
schema?: string;
|
|
92
|
+
sqlFilePath?: string;
|
|
93
|
+
onReady(dbo: DBOFullyTyped<S>, db: DB): void;
|
|
94
|
+
transactions?: string | boolean;
|
|
95
|
+
wsChannelNamePrefix?: string;
|
|
96
|
+
onSocketConnect?(socket: PRGLIOSocket, dbo: DBOFullyTyped<S>, db?: DB): any;
|
|
97
|
+
onSocketDisconnect?(socket: PRGLIOSocket, dbo: DBOFullyTyped<S>, db?: DB): any;
|
|
98
|
+
auth?: Auth<S>;
|
|
99
|
+
DEBUG_MODE?: boolean;
|
|
100
|
+
watchSchemaType?:
|
|
101
|
+
/**
|
|
102
|
+
* Will check client queries for schema changes
|
|
103
|
+
* Default
|
|
104
|
+
*/
|
|
105
|
+
"events"
|
|
106
|
+
/**
|
|
107
|
+
* Will set database event trigger for schema changes. Requires superuser
|
|
108
|
+
*/
|
|
109
|
+
| "queries";
|
|
110
|
+
watchSchema?:
|
|
111
|
+
/**
|
|
112
|
+
* If true then DBoGenerated.d.ts will be updated and "onReady" will be called with new schema on both client and server
|
|
113
|
+
*/
|
|
114
|
+
boolean
|
|
115
|
+
/**
|
|
116
|
+
* "hotReloadMode" will only rewrite the DBoGenerated.d.ts found in tsGeneratedTypesDir
|
|
117
|
+
* This is meant to be used in development when server restarts on file change
|
|
118
|
+
*/
|
|
119
|
+
| "hotReloadMode"
|
|
120
|
+
/**
|
|
121
|
+
* Function called when schema changes. Nothing else triggered
|
|
122
|
+
*/
|
|
123
|
+
| ((event: {
|
|
124
|
+
command: string;
|
|
125
|
+
query: string;
|
|
126
|
+
}) => void)
|
|
127
|
+
/**
|
|
128
|
+
* Schema checked for changes every 'checkIntervalMillis" milliseconds
|
|
129
|
+
*/
|
|
130
|
+
| {
|
|
131
|
+
checkIntervalMillis: number;
|
|
132
|
+
};
|
|
133
|
+
keywords?: Keywords;
|
|
134
|
+
onNotice?: (notice: AnyObject, message?: string) => void;
|
|
135
|
+
fileTable?: FileTableConfig;
|
|
136
|
+
tableConfig?: TableConfig;
|
|
137
|
+
};
|
|
138
|
+
export declare type OnReady = {
|
|
139
|
+
dbo: DBHandlerServer;
|
|
140
|
+
db: DB;
|
|
141
|
+
};
|
|
142
|
+
import { DBOFullyTyped } from "./DBSchemaBuilder";
|
|
143
|
+
export declare class Prostgles {
|
|
144
|
+
opts: ProstglesInitOptions;
|
|
145
|
+
db?: DB;
|
|
146
|
+
pgp?: PGP;
|
|
147
|
+
dbo?: DBHandlerServer;
|
|
148
|
+
_dboBuilder?: DboBuilder;
|
|
149
|
+
get dboBuilder(): DboBuilder;
|
|
150
|
+
set dboBuilder(d: DboBuilder);
|
|
151
|
+
publishParser?: PublishParser;
|
|
152
|
+
authHandler?: AuthHandler;
|
|
153
|
+
keywords: {
|
|
154
|
+
$filter: string;
|
|
155
|
+
$and: string;
|
|
156
|
+
$or: string;
|
|
157
|
+
$not: string;
|
|
158
|
+
};
|
|
159
|
+
private loaded;
|
|
160
|
+
dbEventsManager?: DBEventsManager;
|
|
161
|
+
fileManager?: FileManager;
|
|
162
|
+
tableConfigurator?: TableConfigurator;
|
|
163
|
+
isMedia(tableName: string): boolean;
|
|
164
|
+
constructor(params: ProstglesInitOptions);
|
|
165
|
+
destroyed: boolean;
|
|
166
|
+
onSchemaChange(event: {
|
|
167
|
+
command: string;
|
|
168
|
+
query: string;
|
|
169
|
+
}): Promise<void>;
|
|
170
|
+
checkDb(): void;
|
|
171
|
+
getTSFileName(): {
|
|
172
|
+
fileName: string;
|
|
173
|
+
fullPath: string;
|
|
174
|
+
};
|
|
175
|
+
private getFileText;
|
|
176
|
+
writeDBSchema(force?: boolean): void;
|
|
177
|
+
refreshDBO: () => Promise<DBHandlerServer>;
|
|
178
|
+
isSuperUser: boolean;
|
|
179
|
+
schema_checkIntervalMillis: any;
|
|
180
|
+
init(onReady: (dbo: DBOFullyTyped, db: DB) => any): Promise<{
|
|
181
|
+
db: DBOFullyTyped;
|
|
182
|
+
_db: DB;
|
|
183
|
+
pgp: PGP;
|
|
184
|
+
io?: any;
|
|
185
|
+
destroy: () => Promise<boolean>;
|
|
186
|
+
}>;
|
|
187
|
+
runSQLFile(filePath: string): Promise<any[][]>;
|
|
188
|
+
connectedSockets: any[];
|
|
189
|
+
setSocketEvents(): Promise<void>;
|
|
190
|
+
pushSocketSchema: (socket: any) => Promise<void>;
|
|
191
|
+
}
|
|
192
|
+
export declare function isSuperUser(db: DB): Promise<boolean>;
|
|
193
|
+
//# sourceMappingURL=Prostgles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Prostgles.d.ts","sourceRoot":"","sources":["Prostgles.ts"],"names":[],"mappings":"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"}
|