prostgles-server 2.0.278 → 2.0.281
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/PublishParser.d.ts.map +1 -1
- package/dist/PublishParser.js +3 -2
- package/dist/PublishParser.js.map +1 -1
- package/dist/TableConfig.d.ts +28 -0
- package/dist/TableConfig.d.ts.map +1 -1
- package/dist/TableConfig.js +47 -4
- package/dist/TableConfig.js.map +1 -1
- package/lib/PublishParser.d.ts.map +1 -1
- package/lib/PublishParser.js +3 -2
- package/lib/PublishParser.ts +425 -423
- package/lib/TableConfig.d.ts +28 -0
- package/lib/TableConfig.d.ts.map +1 -1
- package/lib/TableConfig.js +47 -4
- package/lib/TableConfig.ts +83 -4
- package/package.json +1 -1
- package/tests/client/PID.txt +1 -1
- package/tests/server/package-lock.json +1 -1
package/lib/PublishParser.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { getKeys, RULE_METHODS, AnyObject, get, TableSchemaForClient, DBSchemaTable, MethodKey, TableInfo, FullFilter } from "prostgles-types";
|
|
1
|
+
import { getKeys, RULE_METHODS, AnyObject, get, TableSchemaForClient, DBSchemaTable, MethodKey, TableInfo, FullFilter, isObject } from "prostgles-types";
|
|
2
2
|
import { ClientInfo } from "./AuthHandler";
|
|
3
3
|
import { CommonTableRules, Filter, isPlainObject, LocalParams, PRGLIOSocket, TableHandler, ViewHandler } from "./DboBuilder";
|
|
4
4
|
import type { TableHandler as TableHandlerFromTypes } from "prostgles-types";
|
|
5
5
|
import { Prostgles, DBHandlerServer, DB, TABLE_METHODS } from "./Prostgles";
|
|
6
6
|
import type { DBOFullyTyped, PublishFullyTyped } from "./DBSchemaBuilder";
|
|
7
|
-
export type Method = (...args: any) => (
|
|
8
|
-
export type PublishMethods<S = void> = (params: PublishParams<S>) => { [key:string]: Method } | Promise<{ [key:string]: Method } | null>;
|
|
7
|
+
export type Method = (...args: any) => (any | Promise<any>);
|
|
8
|
+
export type PublishMethods<S = void> = (params: PublishParams<S>) => { [key: string]: Method } | Promise<{ [key: string]: Method } | null>;
|
|
9
9
|
|
|
10
10
|
export type Awaitable<T> = T | Promise<T>;
|
|
11
11
|
|
|
@@ -24,77 +24,77 @@ type DboTableCommand = Request & DboTable & {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
const RULE_TO_METHODS = [
|
|
27
|
-
{
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
27
|
+
{
|
|
28
|
+
rule: "getColumns",
|
|
29
|
+
sqlRule: "select",
|
|
30
|
+
methods: RULE_METHODS.getColumns,
|
|
31
|
+
no_limits: true,
|
|
32
|
+
allowed_params: [],
|
|
33
|
+
table_only: false,
|
|
34
|
+
hint: ` expecting false | true | undefined`
|
|
35
35
|
},
|
|
36
|
-
{
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
36
|
+
{
|
|
37
|
+
rule: "getInfo",
|
|
38
|
+
sqlRule: "select",
|
|
39
|
+
methods: RULE_METHODS.getInfo,
|
|
40
|
+
no_limits: true,
|
|
41
|
+
allowed_params: [],
|
|
42
|
+
table_only: false,
|
|
43
|
+
hint: ` expecting false | true | undefined`
|
|
44
44
|
},
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
45
|
+
{
|
|
46
|
+
rule: "insert",
|
|
47
|
+
sqlRule: "insert",
|
|
48
|
+
methods: RULE_METHODS.insert,
|
|
49
|
+
no_limits: <SelectRule>{ fields: "*" },
|
|
50
|
+
table_only: true,
|
|
51
|
+
allowed_params: <Array<keyof InsertRule>>["fields", "forcedData", "returningFields", "validate", "preValidate", "postValidate"],
|
|
52
|
+
hint: ` expecting "*" | true | { fields: string | string[] | {} }`
|
|
53
53
|
},
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
54
|
+
{
|
|
55
|
+
rule: "update",
|
|
56
|
+
sqlRule: "update",
|
|
57
|
+
methods: RULE_METHODS.update,
|
|
58
|
+
no_limits: <UpdateRule>{ fields: "*", filterFields: "*", returningFields: "*" },
|
|
59
|
+
table_only: true,
|
|
60
|
+
allowed_params: <Array<keyof UpdateRule>>["fields", "filterFields", "forcedFilter", "forcedData", "returningFields", "validate", "dynamicFields"],
|
|
61
|
+
hint: ` expecting "*" | true | { fields: string | string[] | {} }`
|
|
62
62
|
},
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
63
|
+
{
|
|
64
|
+
rule: "select",
|
|
65
|
+
sqlRule: "select",
|
|
66
|
+
methods: RULE_METHODS.select,
|
|
67
|
+
no_limits: <SelectRule>{ fields: "*", filterFields: "*" },
|
|
68
|
+
table_only: false,
|
|
69
|
+
allowed_params: <Array<keyof SelectRule>>["fields", "filterFields", "forcedFilter", "validate", "maxLimit"],
|
|
70
|
+
hint: ` expecting "*" | true | { fields: ( string | string[] | {} ) }`
|
|
71
71
|
},
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
72
|
+
{
|
|
73
|
+
rule: "delete",
|
|
74
|
+
sqlRule: "delete",
|
|
75
|
+
methods: RULE_METHODS.delete,
|
|
76
|
+
no_limits: <DeleteRule>{ filterFields: "*" },
|
|
77
|
+
table_only: true,
|
|
78
|
+
allowed_params: <Array<keyof DeleteRule>>["filterFields", "forcedFilter", "returningFields", "validate"],
|
|
79
|
+
hint: ` expecting "*" | true | { filterFields: ( string | string[] | {} ) } \n Will use "select", "update", "delete" and "insert" rules`
|
|
80
80
|
},
|
|
81
|
-
{
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
81
|
+
{
|
|
82
|
+
rule: "sync",
|
|
83
|
+
sqlRule: "select",
|
|
84
|
+
methods: RULE_METHODS.sync,
|
|
85
|
+
no_limits: null,
|
|
86
|
+
table_only: true,
|
|
87
|
+
allowed_params: <Array<keyof SyncRule>>["id_fields", "synced_field", "sync_type", "allow_delete", "throttle", "batch_size"],
|
|
88
|
+
hint: ` expecting "*" | true | { id_fields: string[], synced_field: string }`
|
|
89
89
|
},
|
|
90
|
-
{
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
90
|
+
{
|
|
91
|
+
rule: "subscribe",
|
|
92
|
+
sqlRule: "select",
|
|
93
|
+
methods: RULE_METHODS.subscribe,
|
|
94
|
+
no_limits: <SubscribeRule>{ throttle: 0 },
|
|
95
|
+
table_only: true,
|
|
96
|
+
allowed_params: <Array<keyof SubscribeRule>>["throttle"],
|
|
97
|
+
hint: ` expecting "*" | true | { throttle: number } \n Will use "select" rules`
|
|
98
98
|
}
|
|
99
99
|
] as const;
|
|
100
100
|
|
|
@@ -102,16 +102,16 @@ import { FieldFilter, SelectParams } from "prostgles-types";
|
|
|
102
102
|
import { DEFAULT_SYNC_BATCH_SIZE } from "./PubSubManager";
|
|
103
103
|
|
|
104
104
|
export type InsertRequestData = {
|
|
105
|
-
|
|
106
|
-
|
|
105
|
+
data: object | object[]
|
|
106
|
+
returning: FieldFilter;
|
|
107
107
|
}
|
|
108
108
|
export type SelectRequestData = {
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
filter: object;
|
|
110
|
+
params: SelectParams;
|
|
111
111
|
}
|
|
112
112
|
export type DeleteRequestData = {
|
|
113
|
-
|
|
114
|
-
|
|
113
|
+
filter: object;
|
|
114
|
+
returning: FieldFilter;
|
|
115
115
|
}
|
|
116
116
|
export type UpdateRequestDataOne<R> = {
|
|
117
117
|
filter: FullFilter<R>
|
|
@@ -123,7 +123,7 @@ export type UpdateReq<R> = {
|
|
|
123
123
|
data: Partial<R>;
|
|
124
124
|
}
|
|
125
125
|
export type UpdateRequestDataBatch<R> = {
|
|
126
|
-
|
|
126
|
+
data: UpdateReq<R>[];
|
|
127
127
|
}
|
|
128
128
|
export type UpdateRequestData<R extends AnyObject = AnyObject> = UpdateRequestDataOne<R> | UpdateRequestDataBatch<R>;
|
|
129
129
|
|
|
@@ -133,165 +133,165 @@ export type ValidateUpdateRow<R extends AnyObject = AnyObject, S = void> = (args
|
|
|
133
133
|
|
|
134
134
|
export type SelectRule<Cols extends AnyObject = AnyObject, S = void> = {
|
|
135
135
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
136
|
+
/**
|
|
137
|
+
* Fields allowed to be selected. Tip: Use false to exclude field
|
|
138
|
+
*/
|
|
139
|
+
fields: FieldFilter<Cols>;
|
|
140
140
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
141
|
+
/**
|
|
142
|
+
* The maximum number of rows a user can get in a select query. null by default. Unless a null or higher limit is specified 100 rows will be returned by the default
|
|
143
|
+
*/
|
|
144
|
+
maxLimit?: number | null;
|
|
145
145
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
146
|
+
/**
|
|
147
|
+
* Filter added to every query (e.g. user_id) to restrict access
|
|
148
|
+
*/
|
|
149
|
+
forcedFilter?: FullFilter<Cols, S>;
|
|
150
150
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
151
|
+
/**
|
|
152
|
+
* Fields user can filter by
|
|
153
|
+
* */
|
|
154
|
+
filterFields?: FieldFilter<Cols>;
|
|
155
155
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
156
|
+
/**
|
|
157
|
+
* Validation logic to check/update data for each request
|
|
158
|
+
*/
|
|
159
|
+
validate?(args: SelectRequestData): SelectRequestData | Promise<SelectRequestData>;
|
|
160
160
|
|
|
161
161
|
}
|
|
162
162
|
export type InsertRule<Cols extends AnyObject = AnyObject, S = void> = {
|
|
163
163
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
164
|
+
/**
|
|
165
|
+
* Fields allowed to be inserted. Tip: Use false to exclude field
|
|
166
|
+
*/
|
|
167
|
+
fields: SelectRule<Cols>["fields"]
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Data to include/overwrite on each insert
|
|
171
|
+
*/
|
|
172
|
+
forcedData?: Partial<Cols>;
|
|
168
173
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Validation logic to check/update data after the insert.
|
|
191
|
-
* Happens in the same transaction so upon throwing an error the record will be deleted (not committed)
|
|
192
|
-
*/
|
|
193
|
-
postValidate?: ValidateRow<Required<Cols>, S>;
|
|
174
|
+
/**
|
|
175
|
+
* Fields user can view after inserting
|
|
176
|
+
*/
|
|
177
|
+
returningFields?: SelectRule<Cols>["fields"]
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Validation logic to check/update data for each request. Happens before publish rule checks (for fields, forcedData/forcedFilter)
|
|
181
|
+
*/
|
|
182
|
+
preValidate?: ValidateRow<Cols, S>;
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Validation logic to check/update data for each request. Happens after publish rule checks (for fields, forcedData/forcedFilter)
|
|
186
|
+
*/
|
|
187
|
+
validate?: ValidateRow<Cols, S>;
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Validation logic to check/update data after the insert.
|
|
191
|
+
* Happens in the same transaction so upon throwing an error the record will be deleted (not committed)
|
|
192
|
+
*/
|
|
193
|
+
postValidate?: ValidateRow<Required<Cols>, S>;
|
|
194
194
|
}
|
|
195
195
|
export type UpdateRule<Cols extends AnyObject = AnyObject, S = void> = {
|
|
196
196
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
197
|
+
/**
|
|
198
|
+
* Fields allowed to be updated. Tip: Use false/0 to exclude field
|
|
199
|
+
*/
|
|
200
|
+
fields: SelectRule<Cols>["fields"]
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Row level FGAC
|
|
204
|
+
* Used when the editable fields change based on the updated row
|
|
205
|
+
* If specified then the fields from the first matching filter table.count({ ...filter, ...updateFilter }) > 0 will be used
|
|
206
|
+
* If none matching then the "fields" will be used
|
|
207
|
+
* Specify in decreasing order of specificity otherwise a more general filter will match first
|
|
208
|
+
*/
|
|
209
|
+
dynamicFields?: {
|
|
210
|
+
filter: SelectRule<Cols, S>["forcedFilter"]
|
|
200
211
|
fields: SelectRule<Cols>["fields"]
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Validation logic to check/update data for each request
|
|
237
|
-
*/
|
|
238
|
-
validate?: ValidateUpdateRow<Cols, S>;
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
* Validation logic to check/update data after the insert.
|
|
242
|
-
* Happens in the same transaction so upon throwing an error the record will be deleted (not committed)
|
|
243
|
-
*/
|
|
244
|
-
postValidate?: ValidateRow<Required<Cols>, S>;
|
|
212
|
+
}[];
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Filter added to every query (e.g. user_id) to restrict access
|
|
216
|
+
* This filter cannot be updated
|
|
217
|
+
*/
|
|
218
|
+
forcedFilter?: SelectRule<Cols, S>["forcedFilter"]
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Data to include/overwrite on each updatDBe
|
|
222
|
+
*/
|
|
223
|
+
forcedData?: InsertRule<Cols, S>["forcedData"]
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Fields user can use to find the updates
|
|
227
|
+
*/
|
|
228
|
+
filterFields?: SelectRule<Cols>["fields"]
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Fields user can view after updating
|
|
232
|
+
*/
|
|
233
|
+
returningFields?: SelectRule<Cols>["fields"]
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Validation logic to check/update data for each request
|
|
237
|
+
*/
|
|
238
|
+
validate?: ValidateUpdateRow<Cols, S>;
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Validation logic to check/update data after the insert.
|
|
242
|
+
* Happens in the same transaction so upon throwing an error the record will be deleted (not committed)
|
|
243
|
+
*/
|
|
244
|
+
postValidate?: ValidateRow<Required<Cols>, S>;
|
|
245
245
|
};
|
|
246
246
|
|
|
247
247
|
export type DeleteRule<Cols extends AnyObject = AnyObject, S = void> = {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Filter added to every query (e.g. user_id) to restrict access
|
|
251
|
+
*/
|
|
252
|
+
forcedFilter?: SelectRule<Cols, S>["forcedFilter"]
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Fields user can filter by
|
|
256
|
+
*/
|
|
257
|
+
filterFields: FieldFilter<Cols>;
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Fields user can view after deleting
|
|
261
|
+
*/
|
|
262
|
+
returningFields?: SelectRule<Cols>["filterFields"]
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Validation logic to check/update data for each request
|
|
266
|
+
*/
|
|
267
|
+
validate?(...args: any[]): Awaitable<void>;// UpdateRequestData<Cols>;
|
|
268
268
|
}
|
|
269
269
|
export type SyncRule<Cols extends AnyObject = AnyObject> = {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Primary keys used in updating data
|
|
273
|
+
*/
|
|
274
|
+
id_fields: (keyof Cols)[];
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Numerical incrementing fieldname (last updated timestamp) used to sync items
|
|
278
|
+
*/
|
|
279
|
+
synced_field: keyof Cols;
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* EXPERIMENTAL. Disabled by default. If true then server will attempt to delete any records missing from client.
|
|
283
|
+
*/
|
|
284
|
+
allow_delete?: boolean;
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Throttle replication transmission in milliseconds. Defaults to 100
|
|
288
|
+
*/
|
|
289
|
+
throttle?: number;
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Number of rows to send per trip. Defaults to 50
|
|
293
|
+
*/
|
|
294
|
+
batch_size?: number;
|
|
295
295
|
}
|
|
296
296
|
export type SubscribeRule = {
|
|
297
297
|
throttle?: number;
|
|
@@ -349,13 +349,13 @@ export type PublishParams<S = void> = {
|
|
|
349
349
|
}
|
|
350
350
|
export type RequestParams = { dbo?: DBHandlerServer, socket?: any };
|
|
351
351
|
export type PublishAllOrNothing = true | "*" | false | null;
|
|
352
|
-
type PublishObject = {
|
|
353
|
-
[table_name: string]: (PublishTableRule | PublishViewRule | PublishAllOrNothing
|
|
352
|
+
type PublishObject = {
|
|
353
|
+
[table_name: string]: (PublishTableRule | PublishViewRule | PublishAllOrNothing)
|
|
354
354
|
};
|
|
355
|
-
export type ParsedPublishTables = {
|
|
355
|
+
export type ParsedPublishTables = {
|
|
356
356
|
[table_name: string]: ParsedPublishTable
|
|
357
357
|
};
|
|
358
|
-
export type PublishedResult<Schema = void> = PublishAllOrNothing | PublishFullyTyped<Schema
|
|
358
|
+
export type PublishedResult<Schema = void> = PublishAllOrNothing | PublishFullyTyped<Schema>;
|
|
359
359
|
export type Publish<Schema = void> = PublishedResult<Schema> | ((params: PublishParams<Schema>) => Awaitable<PublishedResult<Schema>>);
|
|
360
360
|
|
|
361
361
|
export class PublishParser {
|
|
@@ -366,45 +366,45 @@ export class PublishParser {
|
|
|
366
366
|
db: DB
|
|
367
367
|
prostgles: Prostgles;
|
|
368
368
|
|
|
369
|
-
constructor(publish: any, publishMethods: any, publishRawSQL: any, dbo: DBHandlerServer, db: DB, prostgles: Prostgles){
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
369
|
+
constructor(publish: any, publishMethods: any, publishRawSQL: any, dbo: DBHandlerServer, db: DB, prostgles: Prostgles) {
|
|
370
|
+
this.publish = publish;
|
|
371
|
+
this.publishMethods = publishMethods;
|
|
372
|
+
this.publishRawSQL = publishRawSQL;
|
|
373
|
+
this.dbo = dbo;
|
|
374
|
+
this.db = db;
|
|
375
|
+
this.prostgles = prostgles;
|
|
376
376
|
|
|
377
|
-
|
|
377
|
+
if (!this.dbo || !this.publish) throw "INTERNAL ERROR: dbo and/or publish missing";
|
|
378
378
|
}
|
|
379
379
|
|
|
380
380
|
async getPublishParams(localParams: LocalParams, clientInfo?: ClientInfo): Promise<PublishParams> {
|
|
381
|
-
if(!this.dbo) throw "dbo missing"
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
381
|
+
if (!this.dbo) throw "dbo missing"
|
|
382
|
+
return {
|
|
383
|
+
...(clientInfo || await this.prostgles.authHandler?.getClientInfo(localParams)),
|
|
384
|
+
dbo: this.dbo,
|
|
385
|
+
db: this.db,
|
|
386
|
+
socket: localParams.socket!
|
|
387
|
+
}
|
|
388
388
|
}
|
|
389
389
|
|
|
390
|
-
async getMethods(socket: any){
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
390
|
+
async getMethods(socket: any) {
|
|
391
|
+
let methods = {};
|
|
392
|
+
|
|
393
|
+
const publishParams = await this.getPublishParams({ socket });
|
|
394
|
+
const _methods = await applyParamsIfFunc(this.publishMethods, publishParams);
|
|
395
|
+
|
|
396
|
+
if (_methods && Object.keys(_methods).length) {
|
|
397
|
+
getKeys(_methods).map(key => {
|
|
398
|
+
if (_methods[key] && (typeof _methods[key] === "function" || typeof _methods[key].then === "function")) {
|
|
399
|
+
//@ts-ignore
|
|
400
|
+
methods[key] = _methods[key];
|
|
401
|
+
} else {
|
|
402
|
+
throw `invalid publishMethods item -> ${key} \n Expecting a function or promise`
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
return methods;
|
|
408
408
|
}
|
|
409
409
|
|
|
410
410
|
/**
|
|
@@ -413,36 +413,36 @@ export class PublishParser {
|
|
|
413
413
|
* @param user
|
|
414
414
|
*/
|
|
415
415
|
async getPublish(localParams: LocalParams, clientInfo?: ClientInfo): Promise<PublishObject> {
|
|
416
|
-
|
|
417
|
-
|
|
416
|
+
const publishParams = await this.getPublishParams(localParams, clientInfo)
|
|
417
|
+
let _publish = await applyParamsIfFunc(this.publish, publishParams);
|
|
418
418
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
419
|
+
if (_publish === "*") {
|
|
420
|
+
let publish = {} as any;
|
|
421
|
+
this.prostgles.dboBuilder.tablesOrViews?.map(tov => {
|
|
422
|
+
publish[tov.name] = "*";
|
|
423
|
+
});
|
|
424
|
+
return publish;
|
|
425
|
+
}
|
|
426
426
|
|
|
427
|
-
|
|
427
|
+
return _publish;
|
|
428
428
|
}
|
|
429
|
-
async getValidatedRequestRuleWusr({ tableName, command, localParams }: DboTableCommand): Promise<TableRule>{
|
|
430
|
-
|
|
431
|
-
|
|
429
|
+
async getValidatedRequestRuleWusr({ tableName, command, localParams }: DboTableCommand): Promise<TableRule> {
|
|
430
|
+
const clientInfo = await this.prostgles.authHandler!.getClientInfo(localParams);
|
|
431
|
+
return await this.getValidatedRequestRule({ tableName, command, localParams }, clientInfo);
|
|
432
432
|
}
|
|
433
|
-
|
|
434
|
-
async getValidatedRequestRule({ tableName, command, localParams }: DboTableCommand, clientInfo?: ClientInfo): Promise<TableRule>{
|
|
435
|
-
if(!this.dbo) throw "INTERNAL ERROR: dbo is missing";
|
|
436
433
|
|
|
437
|
-
|
|
434
|
+
async getValidatedRequestRule({ tableName, command, localParams }: DboTableCommand, clientInfo?: ClientInfo): Promise<TableRule> {
|
|
435
|
+
if (!this.dbo) throw "INTERNAL ERROR: dbo is missing";
|
|
436
|
+
|
|
437
|
+
if (!command || !tableName) throw "command OR tableName are missing";
|
|
438
438
|
|
|
439
439
|
let rtm = RULE_TO_METHODS.find(rtms => (rtms.methods as any).includes(command));
|
|
440
|
-
if(!rtm){
|
|
440
|
+
if (!rtm) {
|
|
441
441
|
throw "Invalid command: " + command;
|
|
442
442
|
}
|
|
443
443
|
|
|
444
444
|
/* Must be local request -> allow everything */
|
|
445
|
-
if(!localParams || (!localParams.socket && !localParams.httpReq)){
|
|
445
|
+
if (!localParams || (!localParams.socket && !localParams.httpReq)) {
|
|
446
446
|
return RULE_TO_METHODS.reduce((a, v) => ({
|
|
447
447
|
...a,
|
|
448
448
|
[v.rule]: v.no_limits
|
|
@@ -450,45 +450,47 @@ export class PublishParser {
|
|
|
450
450
|
}
|
|
451
451
|
|
|
452
452
|
/* Must be from socket. Must have a publish */
|
|
453
|
-
if(!this.publish) throw "publish is missing";
|
|
453
|
+
if (!this.publish) throw "publish is missing";
|
|
454
454
|
|
|
455
455
|
/* Get any publish errors for socket */
|
|
456
456
|
const schm = localParams?.socket?.prostgles?.schema?.[tableName]?.[command];
|
|
457
457
|
|
|
458
|
-
if(schm && schm.err) throw schm.err;
|
|
458
|
+
if (schm && schm.err) throw schm.err;
|
|
459
459
|
|
|
460
460
|
let table_rule = await this.getTableRules({ tableName, localParams }, clientInfo);
|
|
461
|
-
if(!table_rule) throw { stack: ["getValidatedRequestRule()"], message: "Invalid or disallowed table: " + tableName};
|
|
461
|
+
if (!table_rule) throw { stack: ["getValidatedRequestRule()"], message: "Invalid or disallowed table: " + tableName };
|
|
462
462
|
|
|
463
463
|
|
|
464
|
-
if(command === "upsert"){
|
|
465
|
-
if(!table_rule.update || !table_rule.insert){
|
|
464
|
+
if (command === "upsert") {
|
|
465
|
+
if (!table_rule.update || !table_rule.insert) {
|
|
466
466
|
throw { stack: ["getValidatedRequestRule()"], message: `Invalid or disallowed command: upsert` };
|
|
467
467
|
}
|
|
468
468
|
}
|
|
469
469
|
|
|
470
|
-
if(rtm && table_rule && table_rule[rtm.rule]){
|
|
470
|
+
if (rtm && table_rule && table_rule[rtm.rule]) {
|
|
471
471
|
return table_rule;
|
|
472
472
|
} else throw { stack: ["getValidatedRequestRule()"], message: `Invalid or disallowed command: ${tableName}.${command}` };
|
|
473
473
|
}
|
|
474
|
-
|
|
474
|
+
|
|
475
475
|
async getTableRules({ tableName, localParams }: DboTable, clientInfo?: ClientInfo): Promise<ParsedPublishTable | undefined> {
|
|
476
|
-
|
|
476
|
+
|
|
477
477
|
try {
|
|
478
|
-
if(!localParams || !tableName) throw { stack: ["getTableRules()"], message: "publish OR socket OR dbo OR tableName are missing" };
|
|
478
|
+
if (!localParams || !tableName) throw { stack: ["getTableRules()"], message: "publish OR socket OR dbo OR tableName are missing" };
|
|
479
479
|
|
|
480
480
|
let _publish = await this.getPublish(localParams, clientInfo);
|
|
481
481
|
|
|
482
|
-
const raw_table_rules = _publish[tableName]
|
|
483
|
-
if(!raw_table_rules)
|
|
482
|
+
const raw_table_rules = _publish[tableName];
|
|
483
|
+
if (!raw_table_rules || isObject(raw_table_rules) && Object.values(raw_table_rules).every(v => !v)) {
|
|
484
|
+
return undefined;
|
|
485
|
+
}
|
|
484
486
|
|
|
485
487
|
let parsed_table: ParsedPublishTable = {};
|
|
486
488
|
|
|
487
489
|
/* Get view or table specific rules */
|
|
488
490
|
const tHandler = (this.dbo[tableName] as TableHandler | ViewHandler);
|
|
489
491
|
|
|
490
|
-
if(!tHandler) throw { stack: ["getTableRules()"], message: `${tableName} could not be found in dbo` };
|
|
491
|
-
|
|
492
|
+
if (!tHandler) throw { stack: ["getTableRules()"], message: `${tableName} could not be found in dbo` };
|
|
493
|
+
|
|
492
494
|
const is_view = tHandler.is_view;
|
|
493
495
|
const MY_RULES = RULE_TO_METHODS.filter(r => {
|
|
494
496
|
|
|
@@ -496,13 +498,13 @@ export class PublishParser {
|
|
|
496
498
|
const pgUserIsAllowedThis = tHandler.tableOrViewInfo.privileges[r.sqlRule];
|
|
497
499
|
let result = (!is_view || !r.table_only) && pgUserIsAllowedThis;
|
|
498
500
|
|
|
499
|
-
if(!pgUserIsAllowedThis && isPlainObject(raw_table_rules) && (raw_table_rules as PublishTableRule)[r.sqlRule]){
|
|
501
|
+
if (!pgUserIsAllowedThis && isPlainObject(raw_table_rules) && (raw_table_rules as PublishTableRule)[r.sqlRule]) {
|
|
500
502
|
throw `Your postgres user is not allowed ${r.sqlRule} on table ${tableName}`;
|
|
501
503
|
}
|
|
502
504
|
|
|
503
|
-
if((r.rule === "subscribe" || r.rule === "sync") && !this.prostgles.isSuperUser){
|
|
505
|
+
if ((r.rule === "subscribe" || r.rule === "sync") && !this.prostgles.isSuperUser) {
|
|
504
506
|
result = false;
|
|
505
|
-
if(isPlainObject(raw_table_rules) && (raw_table_rules as PublishTableRule)[r.rule]){
|
|
507
|
+
if (isPlainObject(raw_table_rules) && (raw_table_rules as PublishTableRule)[r.rule]) {
|
|
506
508
|
throw `Cannot publish realtime rule ${tableName}.${r.rule}. Superuser is required for this`
|
|
507
509
|
}
|
|
508
510
|
}
|
|
@@ -510,43 +512,43 @@ export class PublishParser {
|
|
|
510
512
|
return result;
|
|
511
513
|
});
|
|
512
514
|
|
|
513
|
-
|
|
515
|
+
|
|
514
516
|
|
|
515
517
|
/* All methods allowed. Add no limits for table rules */
|
|
516
|
-
if([true, "*"].includes(raw_table_rules as any)){
|
|
518
|
+
if ([true, "*"].includes(raw_table_rules as any)) {
|
|
517
519
|
parsed_table = {};
|
|
518
520
|
MY_RULES.filter(r => r.no_limits).forEach(r => {
|
|
519
521
|
parsed_table[r.rule] = { ...r.no_limits as object } as any;
|
|
520
522
|
});
|
|
521
523
|
|
|
522
|
-
|
|
523
|
-
} else if(isPlainObject(raw_table_rules) && getKeys(raw_table_rules).length){
|
|
524
|
+
/** Specific rules allowed */
|
|
525
|
+
} else if (isPlainObject(raw_table_rules) && getKeys(raw_table_rules).length) {
|
|
524
526
|
const allRuleKeys: (keyof PublishViewRule | keyof PublishTableRule)[] = getKeys(raw_table_rules);
|
|
525
527
|
const dissallowedRuleKeys = allRuleKeys.filter(m => !(raw_table_rules as PublishTableRule)[m])
|
|
526
528
|
|
|
527
529
|
MY_RULES.map(r => {
|
|
528
530
|
/** Unless specifically disabled these are allowed */
|
|
529
|
-
if(["getInfo", "getColumns"].includes(r.rule) && !dissallowedRuleKeys.includes(r.rule as any)){
|
|
531
|
+
if (["getInfo", "getColumns"].includes(r.rule) && !dissallowedRuleKeys.includes(r.rule as any)) {
|
|
530
532
|
parsed_table[r.rule] = r.no_limits as any;
|
|
531
|
-
return
|
|
532
|
-
}
|
|
533
|
-
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
|
|
534
536
|
/** Add no_limit values for implied/ fully allowed methods */
|
|
535
537
|
if ([true, "*"].includes((raw_table_rules as PublishTableRule)[r.rule] as any) && r.no_limits) {
|
|
536
538
|
parsed_table[r.rule] = Object.assign({}, r.no_limits) as any;
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
} else if(isPlainObject((raw_table_rules as any)[r.rule])){
|
|
539
|
+
|
|
540
|
+
/** Carry over detailed config */
|
|
541
|
+
} else if (isPlainObject((raw_table_rules as any)[r.rule])) {
|
|
540
542
|
parsed_table[r.rule] = (raw_table_rules as any)[r.rule]
|
|
541
543
|
}
|
|
542
544
|
});
|
|
543
|
-
|
|
545
|
+
|
|
544
546
|
allRuleKeys.filter(m => parsed_table[m])
|
|
545
547
|
.find((method) => {
|
|
546
548
|
let rm = MY_RULES.find(r => r.rule === method || (r.methods as readonly string[]).includes(method));
|
|
547
|
-
if(!rm){
|
|
549
|
+
if (!rm) {
|
|
548
550
|
let extraInfo = "";
|
|
549
|
-
if(is_view && RULE_TO_METHODS.find(r => !is_view && r.rule === method || (r.methods as any).includes(method))){
|
|
551
|
+
if (is_view && RULE_TO_METHODS.find(r => !is_view && r.rule === method || (r.methods as any).includes(method))) {
|
|
550
552
|
extraInfo = "You've specified table rules to a view\n";
|
|
551
553
|
}
|
|
552
554
|
throw `Invalid rule in publish.${tableName} -> ${method} \n${extraInfo}Expecting any of: ${MY_RULES.flatMap(r => [r.rule, ...r.methods]).join(", ")}`;
|
|
@@ -554,40 +556,40 @@ export class PublishParser {
|
|
|
554
556
|
|
|
555
557
|
/* Check RULES for invalid params */
|
|
556
558
|
/* Methods do not have params -> They use them from rules */
|
|
557
|
-
if(method === rm.rule){
|
|
559
|
+
if (method === rm.rule) {
|
|
558
560
|
let method_params = getKeys(parsed_table[method]);
|
|
559
561
|
let iparam = method_params.find(p => !rm?.allowed_params.includes(<never>p));
|
|
560
|
-
if(iparam){
|
|
562
|
+
if (iparam) {
|
|
561
563
|
throw `Invalid setting in publish.${tableName}.${method} -> ${iparam}. \n Expecting any of: ${rm.allowed_params.join(", ")}`;
|
|
562
564
|
}
|
|
563
565
|
}
|
|
564
566
|
|
|
565
567
|
/* Add default params (if missing) */
|
|
566
|
-
if(method === "sync"){
|
|
567
|
-
|
|
568
|
-
if([true, "*"].includes(parsed_table[method] as any)){
|
|
568
|
+
if (method === "sync") {
|
|
569
|
+
|
|
570
|
+
if ([true, "*"].includes(parsed_table[method] as any)) {
|
|
569
571
|
throw "Invalid sync rule. Expecting { id_fields: string[], synced_field: string } ";
|
|
570
572
|
}
|
|
571
|
-
|
|
572
|
-
if(typeof parsed_table[method]?.throttle !== "number"){
|
|
573
|
+
|
|
574
|
+
if (typeof parsed_table[method]?.throttle !== "number") {
|
|
573
575
|
parsed_table[method]!.throttle = 100;
|
|
574
576
|
}
|
|
575
|
-
if(typeof parsed_table[method]?.batch_size !== "number"){
|
|
577
|
+
if (typeof parsed_table[method]?.batch_size !== "number") {
|
|
576
578
|
parsed_table[method]!.batch_size = DEFAULT_SYNC_BATCH_SIZE;
|
|
577
579
|
}
|
|
578
580
|
}
|
|
579
581
|
|
|
580
582
|
/* Enable subscribe if not explicitly disabled */
|
|
581
583
|
const subKey = "subscribe" as const;
|
|
582
|
-
|
|
583
|
-
if(method === "select" && !dissallowedRuleKeys.includes(subKey)){
|
|
584
|
+
|
|
585
|
+
if (method === "select" && !dissallowedRuleKeys.includes(subKey)) {
|
|
584
586
|
const sr = MY_RULES.find(r => r.rule === subKey);
|
|
585
|
-
if(sr){
|
|
587
|
+
if (sr) {
|
|
586
588
|
parsed_table[subKey] = { ...sr.no_limits as SubscribeRule };
|
|
587
589
|
parsed_table.subscribeOne = { ...sr.no_limits as SubscribeRule };
|
|
588
590
|
}
|
|
589
591
|
}
|
|
590
|
-
});
|
|
592
|
+
});
|
|
591
593
|
|
|
592
594
|
} else {
|
|
593
595
|
throw "Unexpected publish"
|
|
@@ -602,12 +604,12 @@ export class PublishParser {
|
|
|
602
604
|
/** THIS IS A MESS -> some methods cannot be dissallowed (unsync, unsubscribe...) */
|
|
603
605
|
r.methods.forEach(method => {
|
|
604
606
|
const isAllowed = tableRules[r.rule] && (tableRules as any)[method] === undefined;
|
|
605
|
-
if(isAllowed){
|
|
606
|
-
|
|
607
|
-
if(method === "updateBatch" && !tableRules.update){
|
|
608
|
-
|
|
609
|
-
} else if(method === "upsert" && (!tableRules.update || !tableRules.insert)){
|
|
610
|
-
|
|
607
|
+
if (isAllowed) {
|
|
608
|
+
|
|
609
|
+
if (method === "updateBatch" && !tableRules.update) {
|
|
610
|
+
|
|
611
|
+
} else if (method === "upsert" && (!tableRules.update || !tableRules.insert)) {
|
|
612
|
+
|
|
611
613
|
} else {
|
|
612
614
|
(res as any)[method] ??= true;
|
|
613
615
|
}
|
|
@@ -617,9 +619,9 @@ export class PublishParser {
|
|
|
617
619
|
|
|
618
620
|
return res;
|
|
619
621
|
}
|
|
620
|
-
|
|
622
|
+
|
|
621
623
|
parsed_table = getImpliedMethods(parsed_table);
|
|
622
|
-
|
|
624
|
+
|
|
623
625
|
return parsed_table;
|
|
624
626
|
} catch (e) {
|
|
625
627
|
throw e;
|
|
@@ -627,117 +629,117 @@ export class PublishParser {
|
|
|
627
629
|
}
|
|
628
630
|
|
|
629
631
|
|
|
630
|
-
|
|
632
|
+
|
|
631
633
|
/* Prepares schema for client. Only allowed views and commands will be present */
|
|
632
|
-
async getSchemaFromPublish(socket: any): Promise<{schema: TableSchemaForClient; tables: DBSchemaTable[] }> {
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
634
|
+
async getSchemaFromPublish(socket: any): Promise<{ schema: TableSchemaForClient; tables: DBSchemaTable[] }> {
|
|
635
|
+
let schema: TableSchemaForClient = {};
|
|
636
|
+
let tables: DBSchemaTable[] = []
|
|
637
|
+
|
|
638
|
+
try {
|
|
639
|
+
/* Publish tables and views based on socket */
|
|
640
|
+
const clientInfo = await this.prostgles.authHandler?.getClientInfo({ socket });
|
|
641
|
+
let _publish = await this.getPublish(socket, clientInfo);
|
|
642
|
+
|
|
643
|
+
|
|
644
|
+
if (_publish && Object.keys(_publish).length) {
|
|
645
|
+
let txKey = "tx";
|
|
646
|
+
if (!this.prostgles.opts.transactions) txKey = "";
|
|
647
|
+
if (typeof this.prostgles.opts.transactions === "string") txKey = this.prostgles.opts.transactions;
|
|
648
|
+
|
|
649
|
+
const tableNames = Object.keys(_publish).filter(k => !txKey || txKey !== k);
|
|
650
|
+
|
|
651
|
+
await Promise.all(tableNames
|
|
652
|
+
.map(async tableName => {
|
|
653
|
+
if (!this.dbo[tableName]) {
|
|
654
|
+
throw `Table ${tableName} does not exist
|
|
653
655
|
Expecting one of: ${this.prostgles.dboBuilder.tablesOrViews?.map(tov => tov.name).join(", ")}
|
|
654
656
|
DBO tables: ${Object.keys(this.dbo).filter(k => (this.dbo[k] as any).find).join(", ")}
|
|
655
657
|
`;
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
} catch (e) {
|
|
725
|
-
console.error("Prostgles \nERRORS IN PUBLISH: ", JSON.stringify(e));
|
|
726
|
-
throw e;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
const table_rules = await this.getTableRules({ localParams: { socket }, tableName }, clientInfo);
|
|
661
|
+
|
|
662
|
+
if (table_rules && Object.keys(table_rules).length) {
|
|
663
|
+
schema[tableName] = {};
|
|
664
|
+
let methods: MethodKey[] = [];
|
|
665
|
+
let tableInfo: TableInfo | undefined;
|
|
666
|
+
let tableColumns: DBSchemaTable["columns"] | undefined;
|
|
667
|
+
|
|
668
|
+
if (typeof table_rules === "object") {
|
|
669
|
+
methods = getKeys(table_rules) as any;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
await Promise.all(methods.filter(m => m !== "select" as any).map(async method => {
|
|
673
|
+
if (method === "sync" && table_rules[method]) {
|
|
674
|
+
|
|
675
|
+
/* Pass sync info */
|
|
676
|
+
schema[tableName][method] = table_rules[method];
|
|
677
|
+
} else if ((table_rules as any)[method]) {
|
|
678
|
+
|
|
679
|
+
schema[tableName][method] = {};
|
|
680
|
+
|
|
681
|
+
/* Test for issues with the common table CRUD methods () */
|
|
682
|
+
if (TABLE_METHODS.includes(method as any)) {
|
|
683
|
+
|
|
684
|
+
let err = null;
|
|
685
|
+
try {
|
|
686
|
+
let valid_table_command_rules = await this.getValidatedRequestRule({ tableName, command: method, localParams: { socket } }, clientInfo);
|
|
687
|
+
await (this.dbo[tableName] as any)[method]({}, {}, {}, valid_table_command_rules, { socket, isRemoteRequest: true, testRule: true });
|
|
688
|
+
|
|
689
|
+
} catch (e) {
|
|
690
|
+
err = "INTERNAL PUBLISH ERROR";
|
|
691
|
+
schema[tableName][method] = { err };
|
|
692
|
+
|
|
693
|
+
throw `publish.${tableName}.${method}: \n -> ${e}`;
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
|
|
698
|
+
if (method === "getInfo" || method === "getColumns") {
|
|
699
|
+
let tableRules = await this.getValidatedRequestRule({ tableName, command: method, localParams: { socket } }, clientInfo);
|
|
700
|
+
const res = await (this.dbo[tableName] as any)[method](undefined, undefined, undefined, tableRules, { socket, isRemoteRequest: true });
|
|
701
|
+
if (method === "getInfo") {
|
|
702
|
+
tableInfo = res;
|
|
703
|
+
} else if (method === "getColumns") {
|
|
704
|
+
tableColumns = res;
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
}));
|
|
709
|
+
|
|
710
|
+
if (tableInfo && tableColumns) {
|
|
711
|
+
|
|
712
|
+
tables.push({
|
|
713
|
+
name: tableName,
|
|
714
|
+
info: tableInfo,
|
|
715
|
+
columns: tableColumns
|
|
716
|
+
})
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
return true;
|
|
721
|
+
})
|
|
722
|
+
);
|
|
727
723
|
}
|
|
728
|
-
|
|
729
|
-
|
|
724
|
+
|
|
725
|
+
|
|
726
|
+
} catch (e) {
|
|
727
|
+
console.error("Prostgles \nERRORS IN PUBLISH: ", JSON.stringify(e));
|
|
728
|
+
throw e;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
return { schema, tables };
|
|
730
732
|
}
|
|
731
733
|
|
|
732
734
|
}
|
|
733
735
|
|
|
734
|
-
|
|
735
|
-
function applyParamsIfFunc(maybeFunc: any, ...params: any): any{
|
|
736
|
-
if(
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
){
|
|
740
|
-
|
|
736
|
+
|
|
737
|
+
function applyParamsIfFunc(maybeFunc: any, ...params: any): any {
|
|
738
|
+
if (
|
|
739
|
+
(maybeFunc !== null && maybeFunc !== undefined) &&
|
|
740
|
+
(typeof maybeFunc === "function" || typeof maybeFunc.then === "function")
|
|
741
|
+
) {
|
|
742
|
+
return maybeFunc(...params);
|
|
741
743
|
}
|
|
742
744
|
|
|
743
745
|
return maybeFunc;
|