prostgles-server 4.2.2 → 4.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/DboBuilder/TableHandler/insert.d.ts.map +1 -1
- package/dist/DboBuilder/TableHandler/insert.js +17 -7
- package/dist/DboBuilder/TableHandler/insert.js.map +1 -1
- package/dist/DboBuilder/TableHandler/update.d.ts.map +1 -1
- package/dist/DboBuilder/TableHandler/update.js +6 -3
- package/dist/DboBuilder/TableHandler/update.js.map +1 -1
- package/dist/Prostgles.d.ts.map +1 -1
- package/dist/Prostgles.js +0 -2
- package/dist/Prostgles.js.map +1 -1
- package/dist/initProstgles.d.ts +2 -2
- package/dist/initProstgles.d.ts.map +1 -1
- package/dist/my.d copy.ts +1020 -0
- package/dist/my.d.ts +1655 -0
- package/lib/DboBuilder/TableHandler/insert.ts +16 -10
- package/lib/DboBuilder/TableHandler/update.ts +6 -4
- package/lib/Prostgles.ts +0 -1
- package/lib/initProstgles.ts +2 -2
- package/package.json +2 -2
- package/tests/isomorphic_queries.ts +10 -0
- package/tests/server/package-lock.json +3 -3
|
@@ -0,0 +1,1020 @@
|
|
|
1
|
+
|
|
2
|
+
type AnyObject = Record<string, any>;
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export type Explode<T> = keyof T extends infer K
|
|
6
|
+
? K extends unknown
|
|
7
|
+
? { [I in keyof T]: I extends K ? T[I] : never }
|
|
8
|
+
: never
|
|
9
|
+
: never;
|
|
10
|
+
export type AtMostOne<T> = Explode<Partial<T>>;
|
|
11
|
+
export type AtLeastOne<T, U = {[K in keyof T]: Pick<T, K> }> = Partial<T> & U[keyof U]
|
|
12
|
+
export type ExactlyOne<T> = AtMostOne<T> & AtLeastOne<T>;
|
|
13
|
+
export type DBTableSchema = {
|
|
14
|
+
is_view?: boolean;
|
|
15
|
+
select?: boolean;
|
|
16
|
+
insert?: boolean;
|
|
17
|
+
update?: boolean;
|
|
18
|
+
delete?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Used in update, insertm select and filters
|
|
21
|
+
* fields that are nullable or with a default value are be optional
|
|
22
|
+
*/
|
|
23
|
+
columns: AnyObject;
|
|
24
|
+
}
|
|
25
|
+
export type DBSchema = {
|
|
26
|
+
[tov_name: string]: DBTableSchema
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type AllowedTSType = string | number | boolean | Date | any;
|
|
30
|
+
export type AllowedTSTypes = AllowedTSType[];
|
|
31
|
+
|
|
32
|
+
export const CompareFilterKeys = ["=", "$eq","<>",">","<",">=","<=","$eq","$ne","$gt","$gte","$lte"] as const;
|
|
33
|
+
export const CompareInFilterKeys = ["$in", "$nin"] as const;
|
|
34
|
+
|
|
35
|
+
export const JsonbOperands = {
|
|
36
|
+
"@>": {
|
|
37
|
+
"Operator": "@>",
|
|
38
|
+
"Right Operand Type": "jsonb",
|
|
39
|
+
"Description": "Does the left JSON value contain the right JSON path/value entries at the top level?",
|
|
40
|
+
"Example": "'{\"a\":1, \"b\":2}'::jsonb @> '{\"b\":2}'::jsonb"
|
|
41
|
+
},
|
|
42
|
+
"<@": {
|
|
43
|
+
"Operator": "<@",
|
|
44
|
+
"Right Operand Type": "jsonb",
|
|
45
|
+
"Description": "Are the left JSON path/value entries contained at the top level within the right JSON value?",
|
|
46
|
+
"Example": "'{\"b\":2}'::jsonb <@ '{\"a\":1, \"b\":2}'::jsonb"
|
|
47
|
+
},
|
|
48
|
+
"?": {
|
|
49
|
+
"Operator": "?",
|
|
50
|
+
"Right Operand Type": "text",
|
|
51
|
+
"Description": "Does the string exist as a top-level key within the JSON value?",
|
|
52
|
+
"Example": "'{\"a\":1, \"b\":2}'::jsonb ? 'b'"
|
|
53
|
+
},
|
|
54
|
+
"?|": {
|
|
55
|
+
"Operator": "?|",
|
|
56
|
+
"Right Operand Type": "text[]",
|
|
57
|
+
"Description": "Do any of these array strings exist as top-level keys?",
|
|
58
|
+
"Example": "'{\"a\":1, \"b\":2, \"c\":3}'::jsonb ?| array['b', 'c']"
|
|
59
|
+
},
|
|
60
|
+
"?&": {
|
|
61
|
+
"Operator": "?&",
|
|
62
|
+
"Right Operand Type": "text[]",
|
|
63
|
+
"Description": "Do all of these array strings exist as top-level keys?",
|
|
64
|
+
"Example": "'[\"a\", \"b\"]'::jsonb ?& array['a', 'b']"
|
|
65
|
+
},
|
|
66
|
+
"||": {
|
|
67
|
+
"Operator": "||",
|
|
68
|
+
"Right Operand Type": "jsonb",
|
|
69
|
+
"Description": "Concatenate two jsonb values into a new jsonb value",
|
|
70
|
+
"Example": "'[\"a\", \"b\"]'::jsonb || '[\"c\", \"d\"]'::jsonb"
|
|
71
|
+
},
|
|
72
|
+
"-": {
|
|
73
|
+
"Operator": "-",
|
|
74
|
+
"Right Operand Type": "integer",
|
|
75
|
+
"Description": "Delete the array element with specified index (Negative integers count from the end). Throws an error if top level container is not an array.",
|
|
76
|
+
"Example": "'[\"a\", \"b\"]'::jsonb - 1"
|
|
77
|
+
},
|
|
78
|
+
"#-": {
|
|
79
|
+
"Operator": "#-",
|
|
80
|
+
"Right Operand Type": "text[]",
|
|
81
|
+
"Description": "Delete the field or element with specified path (for JSON arrays, negative integers count from the end)",
|
|
82
|
+
"Example": "'[\"a\", {\"b\":1}]'::jsonb #- '{1,b}'"
|
|
83
|
+
},
|
|
84
|
+
"@?": {
|
|
85
|
+
"Operator": "@?",
|
|
86
|
+
"Right Operand Type": "jsonpath",
|
|
87
|
+
"Description": "Does JSON path return any item for the specified JSON value?",
|
|
88
|
+
"Example": "'{\"a\":[1,2,3,4,5]}'::jsonb @? '$.a[*] ? (@ > 2)'"
|
|
89
|
+
},
|
|
90
|
+
"@@": {
|
|
91
|
+
"Operator": "@@",
|
|
92
|
+
"Right Operand Type": "jsonpath",
|
|
93
|
+
"Description": "Returns the result of JSON path predicate check for the specified JSON value. Only the first item of the result is taken into account. If the result is not Boolean, then null is returned.",
|
|
94
|
+
"Example": "'{\"a\":[1,2,3,4,5]}'::jsonb @@ '$.a[*] > 2'"
|
|
95
|
+
}
|
|
96
|
+
} as const;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Example: col_name: { $gt: 2 }
|
|
100
|
+
*/
|
|
101
|
+
export type CompareFilter<T extends AllowedTSType = string> =
|
|
102
|
+
/**
|
|
103
|
+
* column value equals provided value
|
|
104
|
+
*/
|
|
105
|
+
| T
|
|
106
|
+
| ExactlyOne<Record<typeof CompareFilterKeys[number], T>>
|
|
107
|
+
|
|
108
|
+
| ExactlyOne<Record<typeof CompareInFilterKeys[number], T[]>>
|
|
109
|
+
| { "$between": [T, T] }
|
|
110
|
+
;
|
|
111
|
+
export const TextFilterKeys = ["$ilike", "$like", "$nilike", "$nlike"] as const;
|
|
112
|
+
|
|
113
|
+
export const TextFilterFTSKeys = ["@@", "@>", "<@", "$contains", "$containedBy"] as const;
|
|
114
|
+
|
|
115
|
+
export const TextFilter_FullTextSearchFilterKeys = ["to_tsquery","plainto_tsquery","phraseto_tsquery","websearch_to_tsquery"] as const;
|
|
116
|
+
export type FullTextSearchFilter =
|
|
117
|
+
| ExactlyOne<Record<typeof TextFilter_FullTextSearchFilterKeys[number], string[]>>
|
|
118
|
+
;
|
|
119
|
+
|
|
120
|
+
export type TextFilter =
|
|
121
|
+
| CompareFilter<string>
|
|
122
|
+
| ExactlyOne<Record<typeof TextFilterKeys[number], string>>
|
|
123
|
+
|
|
124
|
+
| ExactlyOne<Record<typeof TextFilterFTSKeys[number], FullTextSearchFilter>>
|
|
125
|
+
;
|
|
126
|
+
|
|
127
|
+
export const ArrayFilterOperands = ["@>", "<@", "=", "$eq", "$contains", "$containedBy", "&&", "$overlaps"] as const;
|
|
128
|
+
export type ArrayFilter<T extends AllowedTSType[]> =
|
|
129
|
+
| Record<typeof ArrayFilterOperands[number], T>
|
|
130
|
+
| ExactlyOne<Record<typeof ArrayFilterOperands[number], T>>
|
|
131
|
+
;
|
|
132
|
+
|
|
133
|
+
/* POSTGIS */
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Makes bounding box from NW and SE points
|
|
137
|
+
* float xmin, float ymin, float xmax, float ymax, integer srid=unknown
|
|
138
|
+
* https://postgis.net/docs/ST_MakeEnvelope.html
|
|
139
|
+
*/
|
|
140
|
+
export type GeoBBox = { ST_MakeEnvelope: number[] }
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Returns TRUE if A's 2D bounding box intersects B's 2D bounding box.
|
|
145
|
+
* https://postgis.net/docs/reference.html#Operators
|
|
146
|
+
*/
|
|
147
|
+
export type GeomFilter =
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* A's 2D bounding box intersects B's 2D bounding box.
|
|
151
|
+
*/
|
|
152
|
+
| { "&&": GeoBBox }
|
|
153
|
+
// | { "&&&": GeoBBox }
|
|
154
|
+
// | { "&<": GeoBBox }
|
|
155
|
+
// | { "&<|": GeoBBox }
|
|
156
|
+
// | { "&>": GeoBBox }
|
|
157
|
+
// | { "<<": GeoBBox }
|
|
158
|
+
// | { "<<|": GeoBBox }
|
|
159
|
+
// | { ">>": GeoBBox }
|
|
160
|
+
|
|
161
|
+
// | { "=": GeoBBox }
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* A's bounding box is contained by B's
|
|
165
|
+
*/
|
|
166
|
+
| { "@": GeoBBox }
|
|
167
|
+
// | { "|&>": GeoBBox }
|
|
168
|
+
// | { "|>>": GeoBBox }
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* A's bounding box contains B's.
|
|
172
|
+
*/
|
|
173
|
+
// | { "~": GeoBBox }
|
|
174
|
+
// | { "~=": GeoBBox }
|
|
175
|
+
;
|
|
176
|
+
export const GeomFilterKeys = ["~","~=","@","|&>","|>>", ">>", "=", "<<|", "<<", "&>", "&<|", "&<", "&&&", "&&"] as const;
|
|
177
|
+
export const GeomFilter_Funcs = [
|
|
178
|
+
"ST_MakeEnvelope",
|
|
179
|
+
"st_makeenvelope",
|
|
180
|
+
"ST_MakePolygon",
|
|
181
|
+
"st_makepolygon",
|
|
182
|
+
] as const;
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
// PG will try to cast strings to appropriate type
|
|
186
|
+
export type CastFromTSToPG<T extends AllowedTSType> =
|
|
187
|
+
T extends number ? (T | string)
|
|
188
|
+
: T extends string ? (T | Date)
|
|
189
|
+
: T extends boolean ? (T | string)
|
|
190
|
+
: T extends Date ? (T | string)
|
|
191
|
+
: T
|
|
192
|
+
|
|
193
|
+
export type FilterDataType<T extends AllowedTSType> =
|
|
194
|
+
T extends string ? TextFilter
|
|
195
|
+
: T extends number ? CompareFilter<CastFromTSToPG<T>>
|
|
196
|
+
: T extends boolean ? CompareFilter<CastFromTSToPG<T>>
|
|
197
|
+
: T extends Date ? CompareFilter<CastFromTSToPG<T>>
|
|
198
|
+
: T extends any[] ? ArrayFilter<T>
|
|
199
|
+
: (CompareFilter<T> | TextFilter | GeomFilter)
|
|
200
|
+
;
|
|
201
|
+
|
|
202
|
+
export const EXISTS_KEYS = ["$exists", "$notExists", "$existsJoined", "$notExistsJoined"] as const;
|
|
203
|
+
export type EXISTS_KEY = typeof EXISTS_KEYS[number];
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* {
|
|
207
|
+
* $filter: [
|
|
208
|
+
* { $funcName: [...args] },
|
|
209
|
+
* operand,
|
|
210
|
+
* value | funcFilter
|
|
211
|
+
* ]
|
|
212
|
+
* }
|
|
213
|
+
*/
|
|
214
|
+
export const COMPLEX_FILTER_KEY = "$filter" as const;
|
|
215
|
+
export type ComplexFilter = Record<typeof COMPLEX_FILTER_KEY, [
|
|
216
|
+
{ [funcName: string]: any[] },
|
|
217
|
+
typeof CompareFilterKeys[number]?,
|
|
218
|
+
any?
|
|
219
|
+
]>;
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Shortened filter operands
|
|
223
|
+
*/
|
|
224
|
+
type BasicFilter<Field extends string, DataType extends any> = Partial<{
|
|
225
|
+
[K in Extract<typeof CompareFilterKeys[number], string> as `${Field}.${K}`]: CastFromTSToPG<DataType>
|
|
226
|
+
}> | Partial<{
|
|
227
|
+
[K in Extract<typeof CompareInFilterKeys[number], string> as `${Field}.${K}`]: CastFromTSToPG<DataType>[]
|
|
228
|
+
}>;
|
|
229
|
+
type StringFilter<Field extends string, DataType extends any> = BasicFilter<Field, DataType> & (Partial<{
|
|
230
|
+
[K in Extract<typeof TextFilterKeys[number], string> as `${Field}.${K}`]: DataType
|
|
231
|
+
}> | Partial<{
|
|
232
|
+
[K in Extract<typeof TextFilterFTSKeys[number], string> as `${Field}.${K}`]: any
|
|
233
|
+
}>);
|
|
234
|
+
export type ValueOf<T> = T[keyof T];
|
|
235
|
+
|
|
236
|
+
type ShorthandFilter<Obj extends Record<string, any>> = ValueOf<{
|
|
237
|
+
[K in keyof Obj]: Obj[K] extends string? StringFilter<K, Required<Obj>[K]> : BasicFilter<K, Required<Obj>[K]>;
|
|
238
|
+
}>
|
|
239
|
+
|
|
240
|
+
/* Traverses object keys to make filter */
|
|
241
|
+
export type FilterForObject<T extends AnyObject = AnyObject> =
|
|
242
|
+
/* { col: { $func: ["value"] } } */
|
|
243
|
+
| {
|
|
244
|
+
[K in keyof Partial<T>]: FilterDataType<T[K]>
|
|
245
|
+
} & Partial<ComplexFilter>
|
|
246
|
+
/**
|
|
247
|
+
* Filters with shorthand notation
|
|
248
|
+
* @example: { "name.$ilike": 'abc' }
|
|
249
|
+
*/
|
|
250
|
+
| ShorthandFilter<T>
|
|
251
|
+
;
|
|
252
|
+
|
|
253
|
+
export type ExistsFilter<S = void> = Partial<{
|
|
254
|
+
[key in EXISTS_KEY]: S extends DBSchema?
|
|
255
|
+
ExactlyOne<{
|
|
256
|
+
[tname in keyof S]:
|
|
257
|
+
| FullFilter<S[tname]["columns"], S>
|
|
258
|
+
| {
|
|
259
|
+
path: RawJoinPath[];
|
|
260
|
+
filter: FullFilter<S[tname]["columns"], S>
|
|
261
|
+
}
|
|
262
|
+
}> : any
|
|
263
|
+
/** ExactlyOne does not for any type. This produces error */
|
|
264
|
+
// ExactlyOne<{
|
|
265
|
+
// [key: string]: FullFilter<AnyObject,S>
|
|
266
|
+
// }>
|
|
267
|
+
}>;
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Filter that relates to a single column { col: 2 } or
|
|
272
|
+
* an exists filter: { $exists: { } }
|
|
273
|
+
*/
|
|
274
|
+
export type FilterItem<T extends AnyObject = AnyObject> =
|
|
275
|
+
| FilterForObject<T>
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
export type AnyObjIfVoid<T extends AnyObject | void> = T extends AnyObject? T : AnyObject;
|
|
279
|
+
/**
|
|
280
|
+
* Full filter
|
|
281
|
+
* @example { $or: [ { id: 1 }, { status: 'live' } ] }
|
|
282
|
+
*/
|
|
283
|
+
export type FullFilter<T extends AnyObject | void, S extends DBSchema | void> =
|
|
284
|
+
| { $and: FullFilter<T, S>[] }
|
|
285
|
+
| { $or: FullFilter<T, S>[] }
|
|
286
|
+
| FilterItem<AnyObjIfVoid<T>>
|
|
287
|
+
| ExistsFilter<S>
|
|
288
|
+
| ComplexFilter
|
|
289
|
+
|
|
290
|
+
/** Not implemented yet */
|
|
291
|
+
// | { $not: FilterItem<T> }
|
|
292
|
+
;
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Simpler FullFilter to reduce load on compilation
|
|
296
|
+
*/
|
|
297
|
+
export type FullFilterBasic<T = { [key: string]: any }> = {
|
|
298
|
+
[key in keyof Partial<T & { [key: string]: any }>]: any
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
export const _PG_strings = [
|
|
303
|
+
'bpchar','char','varchar','text','citext','uuid','bytea', 'time','timetz','interval','name',
|
|
304
|
+
'cidr', 'inet', 'macaddr', 'macaddr8', "int4range", "int8range", "numrange",
|
|
305
|
+
'tsvector'
|
|
306
|
+
] as const;
|
|
307
|
+
export const _PG_numbers = ['int2','int4','int8','float4','float8','numeric','money','oid'] as const;
|
|
308
|
+
export const _PG_json = ['json', 'jsonb'] as const;
|
|
309
|
+
export const _PG_bool = ['bool'] as const;
|
|
310
|
+
export const _PG_date = ['date', 'timestamp', 'timestamptz'] as const;
|
|
311
|
+
export const _PG_interval = ['interval'] as const;
|
|
312
|
+
export const _PG_postgis = ['geometry', 'geography'] as const;
|
|
313
|
+
export const _PG_geometric = [
|
|
314
|
+
"point",
|
|
315
|
+
"line",
|
|
316
|
+
"lseg",
|
|
317
|
+
"box",
|
|
318
|
+
"path",
|
|
319
|
+
"polygon",
|
|
320
|
+
"circle",
|
|
321
|
+
] as const;
|
|
322
|
+
|
|
323
|
+
export type PG_COLUMN_UDT_DATA_TYPE =
|
|
324
|
+
| typeof _PG_strings[number]
|
|
325
|
+
| typeof _PG_numbers[number]
|
|
326
|
+
| typeof _PG_geometric[number]
|
|
327
|
+
| typeof _PG_json[number]
|
|
328
|
+
| typeof _PG_bool[number]
|
|
329
|
+
| typeof _PG_date[number]
|
|
330
|
+
| typeof _PG_interval[number]
|
|
331
|
+
| typeof _PG_postgis[number];
|
|
332
|
+
|
|
333
|
+
const TS_PG_PRIMITIVES = {
|
|
334
|
+
"string": [ ..._PG_strings, ..._PG_date, ..._PG_geometric, ..._PG_postgis, "lseg"],
|
|
335
|
+
"number": _PG_numbers,
|
|
336
|
+
"boolean": _PG_bool,
|
|
337
|
+
"any": [..._PG_json, ..._PG_interval], // consider as any
|
|
338
|
+
|
|
339
|
+
/** Timestamps are kept in original string format to avoid filters failing
|
|
340
|
+
* TODO: cast to dates if udt_name date/timestamp(0 - 3)
|
|
341
|
+
*/
|
|
342
|
+
// "Date": _PG_date,
|
|
343
|
+
} as const;
|
|
344
|
+
|
|
345
|
+
export const TS_PG_Types = {
|
|
346
|
+
...TS_PG_PRIMITIVES,
|
|
347
|
+
"number[]": TS_PG_PRIMITIVES.number.map(s => `_${s}` as const),
|
|
348
|
+
"boolean[]": TS_PG_PRIMITIVES.boolean.map(s => `_${s}` as const),
|
|
349
|
+
"string[]": TS_PG_PRIMITIVES.string.map(s => `_${s}` as const),
|
|
350
|
+
"any[]": TS_PG_PRIMITIVES.any.map(s => `_${s}` as const),
|
|
351
|
+
// "Date[]": _PG_date.map(s => `_${s}` as const),
|
|
352
|
+
// "any": [],
|
|
353
|
+
} as const;
|
|
354
|
+
export type TS_COLUMN_DATA_TYPES = keyof typeof TS_PG_Types;
|
|
355
|
+
|
|
356
|
+
export type ColumnInfo = {
|
|
357
|
+
name: string;
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Column display name. Will be first non empty value from i18n data, comment, name
|
|
361
|
+
*/
|
|
362
|
+
label: string;
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Column description (if provided)
|
|
366
|
+
*/
|
|
367
|
+
comment: string;
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Ordinal position of the column within the table (count starts at 1)
|
|
371
|
+
*/
|
|
372
|
+
ordinal_position: number;
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* True if column is nullable. A not-null constraint is one way a column can be known not nullable, but there may be others.
|
|
376
|
+
*/
|
|
377
|
+
is_nullable: boolean;
|
|
378
|
+
|
|
379
|
+
is_updatable: boolean;
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Simplified data type
|
|
383
|
+
*/
|
|
384
|
+
data_type: string;
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Postgres raw data types. values starting with underscore means it's an array of that data type
|
|
388
|
+
*/
|
|
389
|
+
udt_name: PG_COLUMN_UDT_DATA_TYPE;
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Element data type
|
|
393
|
+
*/
|
|
394
|
+
element_type: string;
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Element raw data type
|
|
398
|
+
*/
|
|
399
|
+
element_udt_name: string;
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* PRIMARY KEY constraint on column. A table can have more then one PK
|
|
403
|
+
*/
|
|
404
|
+
is_pkey: boolean;
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Foreign key constraint
|
|
408
|
+
* A column can reference multiple tables
|
|
409
|
+
*/
|
|
410
|
+
references?: {
|
|
411
|
+
ftable: string;
|
|
412
|
+
fcols: string[];
|
|
413
|
+
cols: string[];
|
|
414
|
+
}[];
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* true if column has a default value
|
|
418
|
+
* Used for excluding pkey from insert
|
|
419
|
+
*/
|
|
420
|
+
has_default: boolean;
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Column default value
|
|
424
|
+
*/
|
|
425
|
+
column_default?: any;
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Extracted from tableConfig
|
|
429
|
+
* Used in SmartForm
|
|
430
|
+
*/
|
|
431
|
+
min?: string | number;
|
|
432
|
+
max?: string | number;
|
|
433
|
+
hint?: string;
|
|
434
|
+
|
|
435
|
+
jsonbSchema?: any;
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* If degined then this column is referencing the file table
|
|
439
|
+
* Extracted from FileTable config
|
|
440
|
+
* Used in SmartForm
|
|
441
|
+
*/
|
|
442
|
+
file?: any;
|
|
443
|
+
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
export type ValidatedColumnInfo = ColumnInfo & {
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* TypeScript data type
|
|
451
|
+
*/
|
|
452
|
+
tsDataType: TS_COLUMN_DATA_TYPES;
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Can be viewed/selected
|
|
456
|
+
*/
|
|
457
|
+
select: boolean;
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Can be ordered by
|
|
461
|
+
*/
|
|
462
|
+
orderBy: boolean;
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* Can be filtered by
|
|
466
|
+
*/
|
|
467
|
+
filter: boolean;
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* Can be inserted
|
|
471
|
+
*/
|
|
472
|
+
insert: boolean;
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* Can be updated
|
|
476
|
+
*/
|
|
477
|
+
update: boolean;
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Can be used in the delete filter
|
|
481
|
+
*/
|
|
482
|
+
delete: boolean;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
export type DBSchemaTable = {
|
|
487
|
+
name: string;
|
|
488
|
+
info: TableInfo;
|
|
489
|
+
columns: ValidatedColumnInfo[];
|
|
490
|
+
};
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* List of fields to include or exclude
|
|
494
|
+
*/
|
|
495
|
+
export type FieldFilter<T extends AnyObject = AnyObject> = SelectTyped<T>
|
|
496
|
+
|
|
497
|
+
export type AscOrDesc = 1 | -1 | boolean;
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* @example
|
|
501
|
+
* { product_name: -1 } -> SORT BY product_name DESC
|
|
502
|
+
* [{ field_name: (1 | -1 | boolean) }]
|
|
503
|
+
* true | 1 -> ascending
|
|
504
|
+
* false | -1 -> descending
|
|
505
|
+
* Array order is maintained
|
|
506
|
+
* if nullEmpty is true then empty text will be replaced to null (so nulls sorting takes effect on it)
|
|
507
|
+
*/
|
|
508
|
+
export type _OrderBy<T extends AnyObject> =
|
|
509
|
+
| { [K in keyof Partial<T>]: AscOrDesc }
|
|
510
|
+
| { [K in keyof Partial<T>]: AscOrDesc }[]
|
|
511
|
+
| { key: keyof T, asc?: AscOrDesc, nulls?: "last" | "first", nullEmpty?: boolean }[]
|
|
512
|
+
| Array<keyof T>
|
|
513
|
+
| keyof T
|
|
514
|
+
;
|
|
515
|
+
|
|
516
|
+
export type OrderBy<T extends AnyObject | void = void> = T extends AnyObject? _OrderBy<T> : _OrderBy<AnyObject>;
|
|
517
|
+
|
|
518
|
+
type CommonSelect =
|
|
519
|
+
| "*"
|
|
520
|
+
| ""
|
|
521
|
+
| { "*" : 1 }
|
|
522
|
+
|
|
523
|
+
export type SelectTyped<T extends AnyObject> =
|
|
524
|
+
| { [K in keyof Partial<T>]: 1 | true }
|
|
525
|
+
| { [K in keyof Partial<T>]: 0 | false }
|
|
526
|
+
| (keyof T)[]
|
|
527
|
+
| CommonSelect
|
|
528
|
+
;
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
export const JOIN_KEYS = ["$innerJoin", "$leftJoin"] as const;
|
|
532
|
+
export const JOIN_PARAMS = ["select", "filter", "$path", "$condition", "offset", "limit", "orderBy"] as const;
|
|
533
|
+
|
|
534
|
+
export type JoinCondition = {
|
|
535
|
+
column: string;
|
|
536
|
+
rootColumn: string;
|
|
537
|
+
} | ComplexFilter;
|
|
538
|
+
|
|
539
|
+
export type JoinPath = {
|
|
540
|
+
table: string;
|
|
541
|
+
/**
|
|
542
|
+
* {
|
|
543
|
+
* leftColumn: "rightColumn"
|
|
544
|
+
* }
|
|
545
|
+
*/
|
|
546
|
+
on?: Record<string, string>[];
|
|
547
|
+
};
|
|
548
|
+
export type RawJoinPath = string | (JoinPath | string)[]
|
|
549
|
+
|
|
550
|
+
export type DetailedJoinSelect = Partial<Record<typeof JOIN_KEYS[number], RawJoinPath>> & {
|
|
551
|
+
select: Select;
|
|
552
|
+
filter?: FullFilter<void, void>;
|
|
553
|
+
offset?: number;
|
|
554
|
+
limit?: number;
|
|
555
|
+
orderBy?: OrderBy;
|
|
556
|
+
} & (
|
|
557
|
+
{
|
|
558
|
+
$condition?: undefined;
|
|
559
|
+
} | {
|
|
560
|
+
/**
|
|
561
|
+
* If present then will overwrite $path and any inferred joins
|
|
562
|
+
*/
|
|
563
|
+
$condition?: JoinCondition[];
|
|
564
|
+
|
|
565
|
+
}
|
|
566
|
+
);
|
|
567
|
+
|
|
568
|
+
export type SimpleJoinSelect =
|
|
569
|
+
| "*"
|
|
570
|
+
/** Aliased Shorthand join: table_name: { ...select } */
|
|
571
|
+
| Record<string, 1 | "*" | true | FunctionSelect>
|
|
572
|
+
| Record<string, 0 | false>
|
|
573
|
+
|
|
574
|
+
export type JoinSelect =
|
|
575
|
+
| SimpleJoinSelect
|
|
576
|
+
| DetailedJoinSelect;
|
|
577
|
+
|
|
578
|
+
type FunctionShorthand = string;
|
|
579
|
+
type FunctionFull = Record<string, any[] | readonly any[] | FunctionShorthand>;
|
|
580
|
+
type FunctionSelect = FunctionShorthand | FunctionFull;
|
|
581
|
+
/**
|
|
582
|
+
* { computed_field: { funcName: [args] } }
|
|
583
|
+
*/
|
|
584
|
+
type FunctionAliasedSelect = Record<string, FunctionFull>;
|
|
585
|
+
|
|
586
|
+
type InclusiveSelect = true | 1 | FunctionSelect | JoinSelect;
|
|
587
|
+
|
|
588
|
+
type SelectFuncs<T extends AnyObject = AnyObject, IsTyped = false> = (
|
|
589
|
+
| ({ [K in keyof Partial<T>]: InclusiveSelect } & Record<string, IsTyped extends true? FunctionFull : InclusiveSelect>)
|
|
590
|
+
| FunctionAliasedSelect
|
|
591
|
+
| { [K in keyof Partial<T>]: true | 1 | string }
|
|
592
|
+
| { [K in keyof Partial<T>]: 0 | false }
|
|
593
|
+
| CommonSelect
|
|
594
|
+
| (keyof Partial<T>)[]
|
|
595
|
+
);
|
|
596
|
+
|
|
597
|
+
/** S param is needed to ensure the non typed select works fine */
|
|
598
|
+
export type Select<T extends AnyObject | void = void, S extends DBSchema | void = void> = { t: T, s: S } extends { t: AnyObject, s: DBSchema } ? SelectFuncs<T & { $rowhash: string }, true> : SelectFuncs<AnyObject & { $rowhash: string }, false>;
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
export type SelectBasic =
|
|
602
|
+
| { [key: string]: any }
|
|
603
|
+
| {}
|
|
604
|
+
| undefined
|
|
605
|
+
| ""
|
|
606
|
+
| "*"
|
|
607
|
+
;
|
|
608
|
+
|
|
609
|
+
/* Simpler types */
|
|
610
|
+
type CommonSelectParams = {
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* If null then maxLimit if present will be applied
|
|
614
|
+
* If undefined then 1000 will be applied as the default
|
|
615
|
+
*/
|
|
616
|
+
limit?: number | null;
|
|
617
|
+
offset?: number;
|
|
618
|
+
|
|
619
|
+
/**
|
|
620
|
+
* Will group by all non aggregated fields specified in select (or all fields by default)
|
|
621
|
+
*/
|
|
622
|
+
groupBy?: boolean;
|
|
623
|
+
|
|
624
|
+
returnType?:
|
|
625
|
+
|
|
626
|
+
/**
|
|
627
|
+
* Will return the first row as an object. Will throw an error if more than a row is returned. Use limit: 1 to avoid error.
|
|
628
|
+
*/
|
|
629
|
+
| "row"
|
|
630
|
+
|
|
631
|
+
/**
|
|
632
|
+
* Will return the first value from the selected field
|
|
633
|
+
*/
|
|
634
|
+
| "value"
|
|
635
|
+
|
|
636
|
+
/**
|
|
637
|
+
* Will return an array of values from the selected field. Similar to array_agg(field).
|
|
638
|
+
*/
|
|
639
|
+
| "values"
|
|
640
|
+
|
|
641
|
+
/**
|
|
642
|
+
* Will return the sql statement. Requires publishRawSQL privileges if called by client
|
|
643
|
+
*/
|
|
644
|
+
| "statement"
|
|
645
|
+
|
|
646
|
+
/**
|
|
647
|
+
* Will return the sql statement excluding the user header. Requires publishRawSQL privileges if called by client
|
|
648
|
+
*/
|
|
649
|
+
| "statement-no-rls"
|
|
650
|
+
|
|
651
|
+
/**
|
|
652
|
+
* Will return the sql statement where condition. Requires publishRawSQL privileges if called by client
|
|
653
|
+
*/
|
|
654
|
+
| "statement-where"
|
|
655
|
+
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
export type SelectParams<T extends AnyObject | void = void, S extends DBSchema | void = void> = CommonSelectParams & {
|
|
659
|
+
select?: Select<T, S>;
|
|
660
|
+
orderBy?: OrderBy<S extends DBSchema? T : void>;
|
|
661
|
+
}
|
|
662
|
+
export type SubscribeParams<T extends AnyObject | void = void, S extends DBSchema | void = void> = SelectParams<T, S> & {
|
|
663
|
+
throttle?: number;
|
|
664
|
+
throttleOpts?: {
|
|
665
|
+
/**
|
|
666
|
+
* False by default.
|
|
667
|
+
* If true then the first value will be emitted at the end of the interval. Instant otherwise
|
|
668
|
+
* */
|
|
669
|
+
skipFirst?: boolean;
|
|
670
|
+
};
|
|
671
|
+
};
|
|
672
|
+
|
|
673
|
+
export type UpdateParams<T extends AnyObject | void = void, S extends DBSchema | void = void> = {
|
|
674
|
+
returning?: Select<T, S>;
|
|
675
|
+
onConflictDoNothing?: boolean;
|
|
676
|
+
fixIssues?: boolean;
|
|
677
|
+
|
|
678
|
+
/* true by default. If false the update will fail if affecting more than one row */
|
|
679
|
+
multi?: boolean;
|
|
680
|
+
} & Pick<CommonSelectParams, "returnType">;
|
|
681
|
+
|
|
682
|
+
export type InsertParams<T extends AnyObject | void = void, S extends DBSchema | void = void> = {
|
|
683
|
+
returning?: Select<T, S>;
|
|
684
|
+
onConflictDoNothing?: boolean;
|
|
685
|
+
fixIssues?: boolean;
|
|
686
|
+
} & Pick<CommonSelectParams, "returnType">;
|
|
687
|
+
|
|
688
|
+
export type DeleteParams<T extends AnyObject | void = void, S extends DBSchema | void = void> = {
|
|
689
|
+
returning?: Select<T, S>;
|
|
690
|
+
} & Pick<CommonSelectParams, "returnType">;
|
|
691
|
+
|
|
692
|
+
export type PartialLax<T = AnyObject> = Partial<T> & AnyObject;
|
|
693
|
+
|
|
694
|
+
export type TableInfo = {
|
|
695
|
+
/**
|
|
696
|
+
* OID from the postgres database
|
|
697
|
+
*/
|
|
698
|
+
oid: number;
|
|
699
|
+
/**
|
|
700
|
+
* Comment from the postgres database
|
|
701
|
+
*/
|
|
702
|
+
comment?: string;
|
|
703
|
+
/**
|
|
704
|
+
* Defined if this is the fileTable
|
|
705
|
+
*/
|
|
706
|
+
isFileTable?: {
|
|
707
|
+
/**
|
|
708
|
+
* Defined if direct inserts are disabled.
|
|
709
|
+
* Only nested inserts through the specified tables/columns are allowed
|
|
710
|
+
* */
|
|
711
|
+
allowedNestedInserts?: {
|
|
712
|
+
table: string;
|
|
713
|
+
column: string;
|
|
714
|
+
}[] | undefined;
|
|
715
|
+
};
|
|
716
|
+
|
|
717
|
+
/**
|
|
718
|
+
* True if fileTable is enabled and this table references the fileTable
|
|
719
|
+
*/
|
|
720
|
+
hasFiles?: boolean;
|
|
721
|
+
|
|
722
|
+
isView?: boolean;
|
|
723
|
+
|
|
724
|
+
/**
|
|
725
|
+
* Name of the fileTable (if enabled)
|
|
726
|
+
*/
|
|
727
|
+
fileTableName?: string;
|
|
728
|
+
|
|
729
|
+
/**
|
|
730
|
+
* Used for getColumns in cases where the columns are dynamic based on the request.
|
|
731
|
+
* See dynamicFields from Update rules
|
|
732
|
+
*/
|
|
733
|
+
dynamicRules?: {
|
|
734
|
+
update?: boolean;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
/**
|
|
738
|
+
* Additional table info provided through TableConfig
|
|
739
|
+
*/
|
|
740
|
+
info?: {
|
|
741
|
+
label?: string;
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
export type OnError = (err: any) => void;
|
|
746
|
+
|
|
747
|
+
type JoinedSelect = Record<string, Select>;
|
|
748
|
+
|
|
749
|
+
type ParseSelect<Select extends SelectParams<TD>["select"], TD extends AnyObject> =
|
|
750
|
+
(Select extends { "*": 1 }? Required<TD> : {})
|
|
751
|
+
& {
|
|
752
|
+
[Key in keyof Omit<Select, "*">]: Select[Key] extends 1? Required<TD>[Key] :
|
|
753
|
+
Select[Key] extends Record<string, any[]>? any : //Function select
|
|
754
|
+
Select[Key] extends JoinedSelect? any[] :
|
|
755
|
+
any;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
type GetSelectDataType<S extends DBSchema | void, O extends SelectParams<TD, S>, TD extends AnyObject> =
|
|
759
|
+
O extends { returnType: "value" }? any :
|
|
760
|
+
O extends { returnType: "values"; select: Record<string, 1> }? ValueOf<Pick<Required<TD>, keyof O["select"]>> :
|
|
761
|
+
O extends { returnType: "values" }? any :
|
|
762
|
+
O extends { select: "*" }? Required<TD> :
|
|
763
|
+
O extends { select: "" }? Record<string, never> :
|
|
764
|
+
O extends { select: Record<string, 0> }? Omit<Required<TD>, keyof O["select"]> :
|
|
765
|
+
O extends { select: Record<string, any> }? ParseSelect<O["select"], Required<TD>> :
|
|
766
|
+
Required<TD>;
|
|
767
|
+
|
|
768
|
+
export type GetSelectReturnType<S extends DBSchema | void, O extends SelectParams<TD, S>, TD extends AnyObject, isMulti extends boolean> =
|
|
769
|
+
O extends { returnType: "statement" }? string :
|
|
770
|
+
isMulti extends true? GetSelectDataType<S, O, TD>[] :
|
|
771
|
+
GetSelectDataType<S, O, TD>;
|
|
772
|
+
|
|
773
|
+
type GetReturningReturnType<O extends UpdateParams<TD, S>, TD extends AnyObject, S extends DBSchema | void = void> =
|
|
774
|
+
O extends { returning: "*" }? Required<TD> :
|
|
775
|
+
O extends { returning: "" }? Record<string, never> :
|
|
776
|
+
O extends { returning: Record<string, 1> }? Pick<Required<TD>, keyof O["returning"]> :
|
|
777
|
+
O extends { returning: Record<string, 0> }? Omit<Required<TD>, keyof O["returning"]> :
|
|
778
|
+
void;
|
|
779
|
+
|
|
780
|
+
type GetUpdateReturnType<O extends UpdateParams<TD, S>, TD extends AnyObject, S extends DBSchema | void = void> =
|
|
781
|
+
O extends { multi: false }?
|
|
782
|
+
GetReturningReturnType<O, TD, S> :
|
|
783
|
+
GetReturningReturnType<O, TD, S>[];
|
|
784
|
+
|
|
785
|
+
type GetInsertReturnType<Data extends AnyObject | AnyObject[], O extends UpdateParams<TD, S>, TD extends AnyObject, S extends DBSchema | void = void> =
|
|
786
|
+
Data extends any[]?
|
|
787
|
+
GetReturningReturnType<O, TD, S>[] :
|
|
788
|
+
GetReturningReturnType<O, TD, S>;
|
|
789
|
+
|
|
790
|
+
export type SubscriptionHandler = {
|
|
791
|
+
unsubscribe: () => Promise<any>;
|
|
792
|
+
filter: FullFilter<void, void> | {};
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
type GetColumns = (lang?: string, params?: { rule: "update", data: AnyObject, filter: AnyObject }) => Promise<ValidatedColumnInfo[]>;
|
|
796
|
+
|
|
797
|
+
export type ViewHandler<TD extends AnyObject = AnyObject, S extends DBSchema | void = void> = {
|
|
798
|
+
getInfo?: (lang?: string) => Promise<TableInfo>;
|
|
799
|
+
getColumns?: GetColumns
|
|
800
|
+
find: <P extends SelectParams<TD, S>>(filter?: FullFilter<TD, S>, selectParams?: P) => Promise<GetSelectReturnType<S, P, TD, true>>;
|
|
801
|
+
findOne: <P extends SelectParams<TD, S>>(filter?: FullFilter<TD, S>, selectParams?: P) => Promise<undefined | GetSelectReturnType<S, P, TD, false>>;
|
|
802
|
+
subscribe: <P extends SubscribeParams<TD, S>>(
|
|
803
|
+
filter: FullFilter<TD, S>,
|
|
804
|
+
params: P,
|
|
805
|
+
onData: (items: GetSelectReturnType<S, P, TD, true>) => any,
|
|
806
|
+
onError?: OnError
|
|
807
|
+
) => Promise<SubscriptionHandler>;
|
|
808
|
+
subscribeOne: <P extends SubscribeParams<TD, S>>(
|
|
809
|
+
filter: FullFilter<TD, S>,
|
|
810
|
+
params: P,
|
|
811
|
+
onData: (item: GetSelectReturnType<S, P, TD, false> | undefined) => any,
|
|
812
|
+
onError?: OnError
|
|
813
|
+
) => Promise<SubscriptionHandler>;
|
|
814
|
+
count: <P extends SelectParams<TD, S>>(filter?: FullFilter<TD, S>, selectParams?: P) => Promise<number>;
|
|
815
|
+
/**
|
|
816
|
+
* Returns result size in bits
|
|
817
|
+
*/
|
|
818
|
+
size: <P extends SelectParams<TD, S>>(filter?: FullFilter<TD, S>, selectParams?: P) => Promise<string>;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
export type UpsertDataToPGCast<TD extends AnyObject = AnyObject> = {
|
|
822
|
+
[K in keyof TD]: CastFromTSToPG<TD[K]>
|
|
823
|
+
};
|
|
824
|
+
|
|
825
|
+
type UpsertDataToPGCastLax<T extends AnyObject> = PartialLax<UpsertDataToPGCast<T>>;
|
|
826
|
+
type InsertData<T extends AnyObject> = UpsertDataToPGCast<T> | UpsertDataToPGCast<T>[]
|
|
827
|
+
|
|
828
|
+
export type TableHandler<TD extends AnyObject = AnyObject, S extends DBSchema | void = void> = ViewHandler<TD, S> & {
|
|
829
|
+
update: <P extends UpdateParams<TD, S>>(filter: FullFilter<TD, S>, newData: UpsertDataToPGCastLax<TD>, params?: P) => Promise<GetUpdateReturnType<P ,TD, S> | undefined>;
|
|
830
|
+
updateBatch: <P extends UpdateParams<TD, S>>(data: [FullFilter<TD, S>, UpsertDataToPGCastLax<TD>][], params?: P) => Promise<GetUpdateReturnType<P ,TD, S> | void>;
|
|
831
|
+
upsert: <P extends UpdateParams<TD, S>>(filter: FullFilter<TD, S>, newData: UpsertDataToPGCastLax<TD>, params?: P) => Promise<GetUpdateReturnType<P ,TD, S>>;
|
|
832
|
+
insert: <P extends InsertParams<TD, S>, D extends InsertData<TD>>(data: D, params?: P ) => Promise<GetInsertReturnType<D, P ,TD, S>>;
|
|
833
|
+
delete: <P extends DeleteParams<TD, S>>(filter?: FullFilter<TD, S>, params?: P) => Promise<GetUpdateReturnType<P ,TD, S> | undefined>;
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
export type JoinMakerOptions<TT extends AnyObject = AnyObject> = SelectParams<TT> & { path?: RawJoinPath };
|
|
837
|
+
export type JoinMaker<TT extends AnyObject = AnyObject, S extends DBSchema | void = void> = (filter?: FullFilter<TT, S>, select?: Select<TT>, options?: JoinMakerOptions<TT> ) => any;
|
|
838
|
+
export type JoinMakerBasic = (filter?: FullFilterBasic, select?: SelectBasic, options?: SelectParams & { path?: RawJoinPath }) => any;
|
|
839
|
+
|
|
840
|
+
export type TableJoin = {
|
|
841
|
+
[key: string]: JoinMaker;
|
|
842
|
+
}
|
|
843
|
+
export type TableJoinBasic = {
|
|
844
|
+
[key: string]: JoinMakerBasic;
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
export type DbJoinMaker = {
|
|
848
|
+
innerJoin: TableJoin;
|
|
849
|
+
leftJoin: TableJoin;
|
|
850
|
+
innerJoinOne: TableJoin;
|
|
851
|
+
leftJoinOne: TableJoin;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
export type TableHandlers = {
|
|
855
|
+
[key: string]: Partial<TableHandler> | TableHandler;
|
|
856
|
+
};
|
|
857
|
+
|
|
858
|
+
|
|
859
|
+
export type SocketSQLStreamPacket = {
|
|
860
|
+
type: "data";
|
|
861
|
+
fields?: any[];
|
|
862
|
+
rows: any[];
|
|
863
|
+
ended?: boolean;
|
|
864
|
+
info?: SQLResultInfo;
|
|
865
|
+
processId: number;
|
|
866
|
+
} | {
|
|
867
|
+
type: "error";
|
|
868
|
+
error: any;
|
|
869
|
+
};
|
|
870
|
+
export type SocketSQLStreamServer = {
|
|
871
|
+
channel: string;
|
|
872
|
+
unsubChannel: string;
|
|
873
|
+
};
|
|
874
|
+
export type SocketSQLStreamHandlers = {
|
|
875
|
+
run: (query: string, params?: any | any[]) => Promise<void>;
|
|
876
|
+
stop: (terminate?: boolean) => Promise<void>;
|
|
877
|
+
};
|
|
878
|
+
export type SocketSQLStreamClient = SocketSQLStreamServer & {
|
|
879
|
+
start: (listener: (packet: SocketSQLStreamPacket) => void) => Promise<SocketSQLStreamHandlers>
|
|
880
|
+
};
|
|
881
|
+
|
|
882
|
+
|
|
883
|
+
export type DBNoticeConfig = {
|
|
884
|
+
socketChannel: string;
|
|
885
|
+
socketUnsubChannel: string;
|
|
886
|
+
}
|
|
887
|
+
export type DBNotifConfig = DBNoticeConfig & {
|
|
888
|
+
notifChannel: string;
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
|
|
892
|
+
export type SQLOptions = {
|
|
893
|
+
/**
|
|
894
|
+
* Return type of the query
|
|
895
|
+
*/
|
|
896
|
+
returnType?: Required<SelectParams>["returnType"] | "statement" | "rows" | "noticeSubscription" | "arrayMode" | "stream";
|
|
897
|
+
|
|
898
|
+
/**
|
|
899
|
+
* If allowListen not specified and a LISTEN query is issued then expect error
|
|
900
|
+
*/
|
|
901
|
+
allowListen?: boolean;
|
|
902
|
+
|
|
903
|
+
/**
|
|
904
|
+
* Positive integer that works only with returnType="stream".
|
|
905
|
+
* If provided then the query will be cancelled when the specified number of rows have been streamed
|
|
906
|
+
*/
|
|
907
|
+
streamLimit?: number;
|
|
908
|
+
|
|
909
|
+
/**
|
|
910
|
+
* If true then the connection will be persisted and used for subsequent queries
|
|
911
|
+
*/
|
|
912
|
+
persistStreamConnection?: boolean;
|
|
913
|
+
|
|
914
|
+
/**
|
|
915
|
+
* connectionId of the stream connection to use
|
|
916
|
+
* Acquired from the first query with persistStreamConnection=true
|
|
917
|
+
*/
|
|
918
|
+
streamConnectionId?: string;
|
|
919
|
+
|
|
920
|
+
/**
|
|
921
|
+
* If false then the query will not be checked for params. Used to ignore queries with param like text (e.g.: ${someText} )
|
|
922
|
+
* Defaults to true
|
|
923
|
+
*/
|
|
924
|
+
hasParams?: boolean;
|
|
925
|
+
};
|
|
926
|
+
|
|
927
|
+
export type SQLRequest = {
|
|
928
|
+
query: string;
|
|
929
|
+
params?: any | any[];
|
|
930
|
+
options?: SQLOptions
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
export type NotifSubscription = {
|
|
934
|
+
socketChannel: string;
|
|
935
|
+
socketUnsubChannel: string;
|
|
936
|
+
notifChannel: string;
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
export type NoticeSubscription = {
|
|
940
|
+
socketChannel: string;
|
|
941
|
+
socketUnsubChannel: string;
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
export type DBEventHandles = {
|
|
945
|
+
socketChannel: string;
|
|
946
|
+
socketUnsubChannel: string;
|
|
947
|
+
addListener: (listener: (event: any) => void) => { removeListener: () => void; }
|
|
948
|
+
};
|
|
949
|
+
|
|
950
|
+
export type CheckForListen<T, O extends SQLOptions> = O["allowListen"] extends true? (DBEventHandles | T) : T;
|
|
951
|
+
|
|
952
|
+
export type SQLResultInfo = {
|
|
953
|
+
command: "SELECT" | "UPDATE" | "DELETE" | "CREATE" | "ALTER" | "LISTEN" | "UNLISTEN" | "INSERT" | string;
|
|
954
|
+
rowCount: number;
|
|
955
|
+
duration: number;
|
|
956
|
+
}
|
|
957
|
+
export type SQLResult<T extends SQLOptions["returnType"]> = SQLResultInfo & {
|
|
958
|
+
rows: (T extends "arrayMode"? any : AnyObject)[];
|
|
959
|
+
fields: {
|
|
960
|
+
name: string;
|
|
961
|
+
dataType: string;
|
|
962
|
+
udt_name: PG_COLUMN_UDT_DATA_TYPE;
|
|
963
|
+
tsDataType: TS_COLUMN_DATA_TYPES;
|
|
964
|
+
tableID?: number;
|
|
965
|
+
tableName?: string;
|
|
966
|
+
tableSchema?: string;
|
|
967
|
+
columnID?: number;
|
|
968
|
+
columnName?: string;
|
|
969
|
+
}[];
|
|
970
|
+
}
|
|
971
|
+
export type GetSQLReturnType<O extends SQLOptions> = CheckForListen<
|
|
972
|
+
(
|
|
973
|
+
O["returnType"] extends "row"? AnyObject | null :
|
|
974
|
+
O["returnType"] extends "rows"? AnyObject[] :
|
|
975
|
+
O["returnType"] extends "value"? any | null :
|
|
976
|
+
O["returnType"] extends "values"? any[] :
|
|
977
|
+
O["returnType"] extends "statement"? string :
|
|
978
|
+
O["returnType"] extends "noticeSubscription"? DBEventHandles :
|
|
979
|
+
O["returnType"] extends "stream"? SocketSQLStreamClient :
|
|
980
|
+
SQLResult<O["returnType"]>
|
|
981
|
+
)
|
|
982
|
+
, O>;
|
|
983
|
+
|
|
984
|
+
export type SQLHandler =
|
|
985
|
+
/**
|
|
986
|
+
*
|
|
987
|
+
* @param query <string> query. e.g.: SELECT * FROM users;
|
|
988
|
+
* @param params <any[] | object> query arguments to be escaped. e.g.: { name: 'dwadaw' }
|
|
989
|
+
* @param options <object> { returnType: "statement" | "rows" | "noticeSubscription" }
|
|
990
|
+
*/
|
|
991
|
+
<Opts extends SQLOptions>(
|
|
992
|
+
query: string,
|
|
993
|
+
args?: AnyObject | any[],
|
|
994
|
+
options?: Opts,
|
|
995
|
+
serverSideOptions?: {
|
|
996
|
+
socket: any
|
|
997
|
+
} | {
|
|
998
|
+
httpReq: any;
|
|
999
|
+
}
|
|
1000
|
+
) => Promise<GetSQLReturnType<Opts>>
|
|
1001
|
+
|
|
1002
|
+
|
|
1003
|
+
export type DbTxTableHandlers = {
|
|
1004
|
+
[key: string]: Omit<Partial<TableHandler>, "dbTx"> | Omit<TableHandler, "dbTx">;
|
|
1005
|
+
};
|
|
1006
|
+
export type TxCB<TH = DbTxTableHandlers> = {
|
|
1007
|
+
(t: TH & Pick<DBHandlerServer, "sql">, _t: any): (any | void);
|
|
1008
|
+
};
|
|
1009
|
+
export type TX<TH = TableHandlers> = {
|
|
1010
|
+
(t: TxCB<TH>): Promise<(any | void)>;
|
|
1011
|
+
};
|
|
1012
|
+
export type DBHandlerServer<TH = TableHandlers> = TH & Partial<DbJoinMaker> & {
|
|
1013
|
+
sql?: SQLHandler;
|
|
1014
|
+
} & {
|
|
1015
|
+
tx?: TX<TH>;
|
|
1016
|
+
};
|
|
1017
|
+
export type DBTableHandlersFromSchema<Schema = void> = Schema extends DBSchema ? {
|
|
1018
|
+
[tov_name in keyof Schema]: Schema[tov_name]["is_view"] extends true ? ViewHandler<Schema[tov_name]["columns"]> : TableHandler<Schema[tov_name]["columns"]>;
|
|
1019
|
+
} : Record<string, TableHandler>;
|
|
1020
|
+
export type DBOFullyTyped<Schema = void> = (DBTableHandlersFromSchema<Schema> & Pick<DBHandlerServer<DBTableHandlersFromSchema<Schema>>, "tx" | "sql">);
|