@fjell/core 4.4.50 → 4.4.52

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.
Files changed (56) hide show
  1. package/package.json +3 -3
  2. package/src/AItemService.ts +0 -38
  3. package/src/Coordinate.ts +0 -35
  4. package/src/dictionary.ts +0 -84
  5. package/src/errors/ActionError.ts +0 -69
  6. package/src/errors/BusinessLogicError.ts +0 -24
  7. package/src/errors/DuplicateError.ts +0 -57
  8. package/src/errors/NotFoundError.ts +0 -24
  9. package/src/errors/PermissionError.ts +0 -31
  10. package/src/errors/ValidationError.ts +0 -27
  11. package/src/errors/index.ts +0 -7
  12. package/src/event/emitter.ts +0 -247
  13. package/src/event/events.ts +0 -178
  14. package/src/event/index.ts +0 -130
  15. package/src/event/matching.ts +0 -264
  16. package/src/event/subscription.ts +0 -181
  17. package/src/event/types.ts +0 -282
  18. package/src/index.ts +0 -70
  19. package/src/item/IFactory.ts +0 -122
  20. package/src/item/IQFactory.ts +0 -163
  21. package/src/item/IQUtils.ts +0 -392
  22. package/src/item/IUtils.ts +0 -40
  23. package/src/item/ItemQuery.ts +0 -88
  24. package/src/items.ts +0 -120
  25. package/src/key/KUtils.ts +0 -484
  26. package/src/keys.ts +0 -95
  27. package/src/logger.ts +0 -5
  28. package/src/operations/OperationContext.ts +0 -12
  29. package/src/operations/Operations.ts +0 -357
  30. package/src/operations/contained.ts +0 -134
  31. package/src/operations/errorEnhancer.ts +0 -204
  32. package/src/operations/index.ts +0 -2
  33. package/src/operations/methods.ts +0 -363
  34. package/src/operations/primary.ts +0 -101
  35. package/src/operations/specialized.ts +0 -71
  36. package/src/operations/wrappers/createActionWrapper.ts +0 -108
  37. package/src/operations/wrappers/createAllActionWrapper.ts +0 -109
  38. package/src/operations/wrappers/createAllFacetWrapper.ts +0 -98
  39. package/src/operations/wrappers/createAllWrapper.ts +0 -103
  40. package/src/operations/wrappers/createCreateWrapper.ts +0 -117
  41. package/src/operations/wrappers/createFacetWrapper.ts +0 -97
  42. package/src/operations/wrappers/createFindOneWrapper.ts +0 -105
  43. package/src/operations/wrappers/createFindWrapper.ts +0 -105
  44. package/src/operations/wrappers/createGetWrapper.ts +0 -96
  45. package/src/operations/wrappers/createOneWrapper.ts +0 -128
  46. package/src/operations/wrappers/createRemoveWrapper.ts +0 -91
  47. package/src/operations/wrappers/createUpdateWrapper.ts +0 -106
  48. package/src/operations/wrappers/createUpsertWrapper.ts +0 -108
  49. package/src/operations/wrappers/index.ts +0 -39
  50. package/src/operations/wrappers/types.ts +0 -63
  51. package/src/validation/ItemValidator.ts +0 -131
  52. package/src/validation/KeyValidator.ts +0 -365
  53. package/src/validation/LocationValidator.ts +0 -136
  54. package/src/validation/QueryValidator.ts +0 -250
  55. package/src/validation/index.ts +0 -32
  56. package/src/validation/types.ts +0 -45
@@ -1,163 +0,0 @@
1
- import { cPK } from '../key/KUtils';
2
- import {
3
- CompoundType,
4
- Condition,
5
- ConditionOperator,
6
- EventQuery,
7
- isCondition,
8
- ItemQuery,
9
- OrderDirection
10
- } from "./ItemQuery";
11
-
12
- export class IQFactory {
13
-
14
- private query: ItemQuery = {};
15
-
16
- public constructor(query: ItemQuery = {}) {
17
- this.query = query;
18
- }
19
-
20
- public orderBy(field: string, direction: OrderDirection = 'asc') {
21
- if (!this.query.orderBy) {
22
- this.query.orderBy = [];
23
- }
24
- this.query.orderBy.push({ field, direction });
25
- return this;
26
- }
27
-
28
- public agg(name: string, query: ItemQuery) {
29
- if (!this.query.aggs) {
30
- this.query.aggs = {};
31
- }
32
- this.query.aggs[name] = query;
33
- return this;
34
- }
35
-
36
- public event(name: string, query: EventQuery) {
37
- if (!this.query.events) {
38
- this.query.events = {};
39
- }
40
- this.query.events[name] = query;
41
- return this;
42
- }
43
-
44
- public conditions(conditions: Condition[], compoundType: CompoundType = 'AND') {
45
- for (const condition of conditions) {
46
- if (!isCondition(condition)) {
47
- throw new Error(`Invalid condition: ${JSON.stringify(condition)}`);
48
- }
49
- }
50
- if (!this.query.compoundCondition) {
51
- // If there is no top-level compound condition, create one
52
- // with the given compound type. This will mostly likely be the most common case.
53
- this.query.compoundCondition = {
54
- compoundType,
55
- conditions: conditions,
56
- };
57
- } else {
58
- // If there is already a top-level compound condition, create a new compound condition
59
- // and add it to the conditions array of the top-level compound condition.
60
- const compoundCondition = {
61
- compoundType,
62
- conditions,
63
- };
64
- this.query.compoundCondition.conditions.push(compoundCondition);
65
- }
66
- return this;
67
- }
68
-
69
- public limit(limit: number) {
70
- this.query.limit = limit;
71
- return this;
72
- }
73
-
74
- public offset(offset: number) {
75
- this.query.offset = offset;
76
- return this;
77
- }
78
-
79
- // TODO: right now, we're only supporting PK refs for queries. Should add support for CKs
80
- public pk(kt: string, pk: string, name?: string) {
81
- if (!this.query.refs) {
82
- this.query.refs = {};
83
- }
84
- const refName = name || kt;
85
- this.query.refs[refName] = { key: cPK<string>(pk, kt) };
86
- return this;
87
- }
88
-
89
- public condition(
90
- column: string,
91
- value: string[] | string | number[] | number | boolean | Date | null,
92
- operator: ConditionOperator = '==',
93
- ) {
94
- const condition: Condition = { column, value, operator };
95
- if (isCondition(condition)) {
96
- if (!this.query.compoundCondition) {
97
- // If there is no top-level compound condition, create one
98
- // with the default compound type of 'AND'.
99
- this.query.compoundCondition = {
100
- compoundType: 'AND',
101
- conditions: [],
102
- };
103
- }
104
- this.query.compoundCondition.conditions.push(condition);
105
- return this;
106
- } else {
107
- throw new Error(`Invalid condition: ${JSON.stringify(condition)}`);
108
- }
109
- }
110
-
111
- public static all() {
112
- const iqFactory = new IQFactory();
113
- return iqFactory;
114
- }
115
-
116
- public static orderBy(field: string, direction: OrderDirection = 'asc') {
117
- const iqFactory = new IQFactory();
118
- return iqFactory.orderBy(field, direction);
119
- }
120
-
121
- public static agg(name: string, query: ItemQuery) {
122
- const iqFactory = new IQFactory();
123
- return iqFactory.agg(name, query);
124
- }
125
-
126
- public static event(name: string, query: EventQuery) {
127
- const iqFactory = new IQFactory();
128
- return iqFactory.event(name, query);
129
- }
130
-
131
- public static limit(limit: number) {
132
- const iqFactory = new IQFactory();
133
- return iqFactory.limit(limit);
134
- }
135
-
136
- public static offset(offset: number) {
137
- const iqFactory = new IQFactory();
138
- return iqFactory.offset(offset);
139
- }
140
-
141
- public static pk(kt: string, pk: string, name?: string) {
142
- const iqFactory = new IQFactory();
143
- return iqFactory.pk(kt, pk, name);
144
- }
145
-
146
- public static condition(
147
- column: string,
148
- value: string[] | string | number[] | number | boolean | Date | null,
149
- operator: ConditionOperator = '=='
150
- ) {
151
- const iqFactory = new IQFactory();
152
- return iqFactory.condition(column, value, operator);
153
- }
154
-
155
- public static conditions(conditions: Condition[], compoundType: CompoundType = 'AND') {
156
- const iqFactory = new IQFactory();
157
- return iqFactory.conditions(conditions, compoundType);
158
- }
159
-
160
- toQuery() {
161
- return this.query;
162
- }
163
- }
@@ -1,392 +0,0 @@
1
- import { Item, Reference, ReferenceItem, References } from "../items";
2
- import { isItemKeyEqual, isPriKey } from "../key/KUtils";
3
- import { ComKey, PriKey } from "../keys";
4
- import LibLogger from "../logger";
5
- import * as luxon from 'luxon';
6
- import { CompoundCondition, Condition, EventQuery, isCondition, ItemQuery, QueryParams } from "./ItemQuery";
7
-
8
- const logger = LibLogger.get('IQUtils');
9
-
10
- /**
11
- * When we query or search, we're sending a GET request. This converts everything in ItemQuery into a flat
12
- * object that can be sent over a GET request.
13
- *
14
- * Note that there is some discussion about this. Evidently Elastic supports search with POST, but that also
15
- * feels like a bit of a hack. It's not a RESTful way to do things. So we're sticking with GET for now.
16
- *
17
- * For reference, look at RFC 9110 "HTTP Semantics", June which clarified on top of and RFC 7231. It's possible
18
- * but there are so many caveats and conditions in the standard, it's not worth it.
19
- *
20
- * Anticipating the next question - "isn't there a limit to the length of a URL?" The specification does not
21
- * specify a limit, and there are limits in various browsers and servers - Apache is 4,000 chars, Chrome is 2M chars.
22
- * Short answer is that if this query is being used to craft something that complex, it is probably a better idea
23
- * to provide an action or a custom query endpoint on the server.
24
- *
25
- * @param query
26
- * @returns QueryParams ready to be get over a GET request.
27
- */
28
- export const queryToParams = (query: ItemQuery): QueryParams => {
29
- const params: QueryParams = {};
30
- if (query.compoundCondition) {
31
- params.compoundCondition = JSON.stringify(query.compoundCondition);
32
- }
33
- if (query.refs) {
34
- params.refs = JSON.stringify(query.refs);
35
- }
36
- if (query.limit) {
37
- params.limit = query.limit;
38
- }
39
- if (query.offset) {
40
- params.offset = query.offset;
41
- }
42
- if (query.aggs) {
43
- params.aggs = JSON.stringify(query.aggs);
44
- }
45
- if (query.events) {
46
- params.events = JSON.stringify(query.events);
47
- }
48
- return params;
49
- }
50
-
51
- // This is a dateTimeReviver used for JSON parse - when we convert a param back to a query, we need this.
52
- const dateTimeReviver = function (key: string, value: string) {
53
- if (typeof value === 'string') {
54
- const parsedDate = luxon.DateTime.fromISO(value);
55
- if (parsedDate.isValid) {
56
- return parsedDate.toJSDate();;
57
- }
58
- }
59
- return value;
60
- }
61
-
62
- /**
63
- * This method translates from a flat QueryParams object with stringify'd JSON back to a full ItemQuery.
64
- *
65
- * @param params Parameters sent over a GET request
66
- * @returns A fully hydrated ItemQuery object.
67
- */
68
- export const paramsToQuery = (params: QueryParams): ItemQuery => {
69
- const query: ItemQuery = {};
70
- if (params.compoundCondition) {
71
- query.compoundCondition = JSON.parse(params.compoundCondition as string) as CompoundCondition;
72
- }
73
- if (params.refs) {
74
- query.refs = JSON.parse(params.refs as string) as References;
75
- }
76
- if (params.limit) {
77
- query.limit = Number(params.limit);
78
- }
79
- if (params.offset) {
80
- query.offset = Number(params.offset);
81
- }
82
- if (params.aggs) {
83
- query.aggs = JSON.parse(params.aggs as string) as Record<string, ItemQuery>;
84
- }
85
- if (params.events) {
86
- query.events = JSON.parse(params.events as string, dateTimeReviver) as Record<string, { start?: Date, end?: Date }>;
87
- }
88
- return query;
89
- }
90
-
91
- const isRefQueryMatch =
92
- <
93
- S extends string,
94
- L1 extends string = never,
95
- L2 extends string = never,
96
- L3 extends string = never,
97
- L4 extends string = never,
98
- L5 extends string = never
99
- >(
100
- refKey: string,
101
- queryRef: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>,
102
- references: References,
103
- ): boolean => {
104
- logger.trace('doesRefMatch', { queryRef, references });
105
- logger.debug('Comparing Ref', { refKey, itemRef: references[refKey], queryRef });
106
- if (!references[refKey]) {
107
- return false;
108
- }
109
- return isItemKeyEqual(queryRef, references[refKey].key);
110
- }
111
-
112
- const isCompoundConditionQueryMatch = <
113
- S extends string,
114
- L1 extends string = never,
115
- L2 extends string = never,
116
- L3 extends string = never,
117
- L4 extends string = never,
118
- L5 extends string = never
119
- >(
120
- queryCondition: CompoundCondition,
121
- item: Item<S, L1, L2, L3, L4, L5>,
122
- ): boolean => {
123
- if (queryCondition.compoundType === 'AND') {
124
- // If this is an AND compound condition, we need to check if all of the conditions match
125
- return queryCondition.conditions.every(
126
- (condition: Condition | CompoundCondition) =>
127
- isCondition(condition) ?
128
- isConditionQueryMatch(condition, item) :
129
- isCompoundConditionQueryMatch(condition, item)
130
- );
131
- } else {
132
- // If this is an OR compound condition, we need to check if any of the conditions match
133
- return queryCondition.conditions.some(
134
- (condition: Condition | CompoundCondition) =>
135
- isCondition(condition) ?
136
- isConditionQueryMatch(condition, item) :
137
- isCompoundConditionQueryMatch(condition, item)
138
- );
139
- }
140
- }
141
-
142
- const isConditionQueryMatch = <
143
- S extends string,
144
- L1 extends string = never,
145
- L2 extends string = never,
146
- L3 extends string = never,
147
- L4 extends string = never,
148
- L5 extends string = never
149
- >(
150
- queryCondition: Condition,
151
- item: Item<S, L1, L2, L3, L4, L5>,
152
- ): boolean => {
153
- const propKey = queryCondition.column;
154
- logger.trace('doesConditionMatch', { propKey, queryCondition, item });
155
- // eslint-disable-next-line no-undefined
156
- if (item[propKey] === undefined) {
157
- logger.debug('Item does not contain prop under key', { propKey, item });
158
- return false;
159
- }
160
- logger.debug('Comparing Condition', { propKey, itemProp: item[propKey], queryCondition });
161
-
162
- // Handle null values - only == and != make sense with null
163
- if (queryCondition.value === null) {
164
- if (queryCondition.operator === '==') {
165
- return item[propKey] === null;
166
- } else if (queryCondition.operator === '!=') {
167
- return item[propKey] !== null;
168
- } else {
169
- throw new Error(
170
- `Operator ${queryCondition.operator} cannot be used with null value. Use '==' for null checks or '!=' for not-null checks.`
171
- );
172
- }
173
- }
174
-
175
- let result = false;
176
- switch (queryCondition.operator) {
177
- case '==':
178
- result = item[propKey] === queryCondition.value;
179
- break;
180
- case '!=':
181
- result = item[propKey] !== queryCondition.value;
182
- break;
183
- case '>':
184
- result = item[propKey] > queryCondition.value;
185
- break;
186
- case '>=':
187
- result = item[propKey] >= queryCondition.value;
188
- break;
189
- case '<':
190
- result = item[propKey] < queryCondition.value;
191
- break;
192
- case '<=':
193
- result = item[propKey] <= queryCondition.value;
194
- break;
195
- case 'in':
196
- result = (queryCondition.value as unknown as string[]).includes(item[propKey] as string);
197
- break;
198
- case 'not-in':
199
- result = !(queryCondition.value as unknown as string[]).includes(item[propKey] as string);
200
- break;
201
- case 'array-contains':
202
- result = (item[propKey] as unknown as string[]).includes(queryCondition.value as string);
203
- break;
204
- case 'array-contains-any':
205
- result = (queryCondition.value as unknown as string[])
206
- .some(value => (item[propKey] as unknown as string[]).includes(value));
207
- break;
208
- }
209
- return result;
210
- }
211
-
212
- const isAggQueryMatch = <
213
- S extends string,
214
- L1 extends string = never,
215
- L2 extends string = never,
216
- L3 extends string = never,
217
- L4 extends string = never,
218
- L5 extends string = never
219
- >(
220
- aggKey: string,
221
- aggQuery: ItemQuery,
222
- agg: ReferenceItem<S, L1, L2, L3, L4, L5>
223
- ): boolean => {
224
- const aggItem = agg.item;
225
- logger.debug('Comparing Agg', { aggKey, aggItem, aggQuery });
226
- // Fancy, right? This is a recursive call to isQueryMatch
227
- if (!aggItem) {
228
- return false;
229
- }
230
- return isQueryMatch(aggItem, aggQuery);
231
- }
232
-
233
- const isEventQueryMatch = <
234
- S extends string,
235
- L1 extends string = never,
236
- L2 extends string = never,
237
- L3 extends string = never,
238
- L4 extends string = never,
239
- L5 extends string = never
240
- >(
241
- eventKey: string,
242
- eventQuery: EventQuery,
243
- item: Item<S, L1, L2, L3, L4, L5>,
244
- ): boolean => {
245
- if (!item.events[eventKey]) {
246
- logger.debug('Item does not contain event under key', { eventKey, events: item.events });
247
- return false;
248
- } else {
249
- const itemEvent = item.events[eventKey];
250
- if (itemEvent.at !== null) {
251
- if (eventQuery.start && !(eventQuery.start.getTime() <= itemEvent.at.getTime())) {
252
- logger.debug('Item date before event start query', { eventQuery, itemEvent });
253
- return false;
254
- }
255
- if (eventQuery.end && !(eventQuery.end.getTime() > itemEvent.at.getTime())) {
256
- logger.debug('Item date after event end query', { eventQuery, itemEvent });
257
- return false;
258
- }
259
- } else {
260
- logger.debug('Item event does contains a null at', { itemEvent });
261
- return false;
262
- }
263
- return true;
264
- }
265
- }
266
-
267
- export const isQueryMatch = <
268
- S extends string,
269
- L1 extends string = never,
270
- L2 extends string = never,
271
- L3 extends string = never,
272
- L4 extends string = never,
273
- L5 extends string = never
274
- >(item: Item<S, L1, L2, L3, L4, L5>, query: ItemQuery): boolean => {
275
-
276
- logger.trace('isMatch', { item, query });
277
- if (query.refs && item.refs) {
278
- for (const key in query.refs) {
279
- const queryRef = query.refs[key];
280
- if (!isRefQueryMatch(key, queryRef.key, item.refs)) return false;
281
- }
282
- } else if (query.refs && !item.refs) {
283
- logger.debug('Query contains refs but item does not have refs', { query, item });
284
- return false;
285
- }
286
-
287
- if (query.compoundCondition && item) {
288
- if (!isCompoundConditionQueryMatch(query.compoundCondition, item)) return false;
289
- }
290
-
291
- if (query.events && item.events) {
292
- for (const key in query.events) {
293
- const queryEvent = query.events[key];
294
- if (!isEventQueryMatch(key, queryEvent, item)) return false
295
- }
296
- return true;
297
- }
298
-
299
- if (query.aggs && item.aggs) {
300
- for (const key in query.aggs) {
301
- const aggQuery = query.aggs[key];
302
- // aggs is a record where each key maps to an array of aggregations
303
- if (item.aggs[key]) {
304
- let hasMatch = false;
305
- for (const aggRecord of item.aggs[key]) {
306
- if (isAggQueryMatch(key, aggQuery, aggRecord as ReferenceItem<any, any, any, any, any, any>)) {
307
- hasMatch = true;
308
- break;
309
- }
310
- }
311
- if (!hasMatch) return false;
312
- } else {
313
- return false;
314
- }
315
- }
316
- } else if (query.aggs && !item.aggs) {
317
- logger.debug('Query contains aggs but item does not have aggs', { query, item });
318
- return false;
319
- }
320
-
321
- // If it hasn't returned false by now, it must be a match
322
- return true;
323
- }
324
-
325
- export const abbrevQuery = (query: ItemQuery | null | undefined): string => {
326
- const abbrev = ['IQ'];
327
- if( query ) {
328
- if (query.refs) {
329
- for (const key in query.refs) {
330
- const ref = abbrevRef(key, query.refs[key]);
331
- abbrev.push(ref);
332
- }
333
- }
334
- if (query.compoundCondition) {
335
- const props = abbrevCompoundCondition(query.compoundCondition);
336
- abbrev.push(props);
337
- }
338
- if (query.aggs) {
339
- for (const key in query.aggs) {
340
- const agg = abbrevAgg(key, query.aggs[key]);
341
- abbrev.push(agg);
342
- }
343
- }
344
- if (query.events) {
345
- const events = `(E${Object.keys(query.events).join(',')})`;
346
- abbrev.push(events);
347
- }
348
- if (query.limit) {
349
- abbrev.push(`L${query.limit}`);
350
- }
351
- if (query.offset) {
352
- abbrev.push(`O${query.offset}`);
353
- }
354
- } else {
355
- abbrev.push('(empty)');
356
- }
357
- return abbrev.join(' ');
358
- }
359
-
360
- export const abbrevRef = <
361
- S extends string,
362
- L1 extends string = never,
363
- L2 extends string = never,
364
- L3 extends string = never,
365
- L4 extends string = never,
366
- L5 extends string = never
367
- >(key: string, ref: Reference<S, L1, L2, L3, L4, L5>): string => {
368
- if (isPriKey(ref.key)) {
369
- const priKey = ref.key as PriKey<S>;
370
- return `R(${key},${priKey.kt},${priKey.pk})`;
371
- } else {
372
- const comKey = ref.key as ComKey<S, L1, L2, L3, L4, L5>;
373
- return `R(${key},${JSON.stringify(comKey)})`;
374
- }
375
- }
376
-
377
- export const abbrevAgg = (key: string, agg: ItemQuery): string => {
378
- return `A(${key},${abbrevQuery(agg)})`;
379
- }
380
-
381
- export const abbrevCompoundCondition = (compoundCondition: CompoundCondition): string => {
382
- return `CC(${compoundCondition.compoundType},` +
383
- `${compoundCondition.conditions ? compoundCondition.conditions.map(abbrevCondition).join(',') : 'No Conditions'})`;
384
- }
385
-
386
- export const abbrevCondition = (condition: Condition | CompoundCondition): string => {
387
- if (isCondition(condition)) {
388
- return `(${condition.column},${condition.value},${condition.operator})`;
389
- } else {
390
- return abbrevCompoundCondition(condition);
391
- }
392
- }
@@ -1,40 +0,0 @@
1
- /* eslint-disable indent */
2
-
3
- import { Item } from "../items";
4
- import { isComKey, isPriKey } from "../key/KUtils";
5
- import { ComKey, PriKey } from "../keys";
6
-
7
- /**
8
- * @deprecated Use validatePK from @fjell/core/validation instead
9
- * Re-exported for backward compatibility
10
- */
11
- export { validatePK, validateKeys } from '../validation/ItemValidator';
12
-
13
- // validatePK and validateKeys have been moved to ../validation/ItemValidator.ts
14
- // They are re-exported above for backward compatibility
15
-
16
- export const isPriItem = <
17
- S extends string,
18
- L1 extends string = never,
19
- L2 extends string = never,
20
- L3 extends string = never,
21
- L4 extends string = never,
22
- L5 extends string = never,
23
- >(
24
- item: Item<S, L1, L2, L3, L4, L5>,
25
- ): item is Item<S> & { key: PriKey<S> } => {
26
- return !!(item && item.key && isPriKey(item.key));
27
- };
28
-
29
- export const isComItem = <
30
- S extends string,
31
- L1 extends string = never,
32
- L2 extends string = never,
33
- L3 extends string = never,
34
- L4 extends string = never,
35
- L5 extends string = never,
36
- >(
37
- item: Item<S, L1, L2, L3, L4, L5>,
38
- ): item is Item<S, L1, L2, L3, L4, L5> & { key: ComKey<S, L1, L2, L3, L4, L5> } => {
39
- return !!(item && item.key && isComKey(item.key));
40
- };
@@ -1,88 +0,0 @@
1
- import { References } from '../items';
2
-
3
- export type QueryParams = Record<string, string | number | boolean | Date>;
4
-
5
- /**
6
- * The operator for a condition. This is the same as the operators used in the Firestore query language.
7
- */
8
- export type ConditionOperator =
9
- '==' | '!=' | '>' | '>=' | '<' | '<=' | 'in' | 'not-in' | 'array-contains' | 'array-contains-any';
10
-
11
- /**
12
- * A single property condition is defined with a column, value, and operator.
13
- * This is a condition that is used in a query.
14
- */
15
- export type Condition = {
16
- column: string,
17
- value: string[] | string | number[] | number | boolean | Date | null,
18
- operator: ConditionOperator,
19
- };
20
-
21
- /**
22
- * When applying a compound condition, the CompoundType defines the type of compound condition.
23
- */
24
- export type CompoundType = 'AND' | 'OR';
25
-
26
- /**
27
- * When configuring a CompoundCondition this can contain a collection of conditions
28
- * that will be applied to the query. By default, this is an AND conditiion that is associated
29
- * with an array of Condition objects OR an array of CompoundCondition objects.
30
- *
31
- * For example, I could have { compoundType: 'AND', conditions: [{column: 'name', value: 'test', operator: '=='},
32
- * {column: 'age', value: 21, operator: '>='}]} which would filter the query to only include items
33
- * where the name is 'test' and the age is greater than or equal to 21.
34
- *
35
- * Or, I could have a { compoundType: 'OR', conditions: [{column: 'name', value: 'test', operator: '=='},
36
- * {column: 'age', value: 21, operator: '>='}]} which would filter the query to only include items
37
- * where the name is 'test' OR the age is greater than or equal to 21.
38
- *
39
- * I could also nest an OR within an AND, like this:
40
- * ['AND', [{column: 'name', value: 'test', operator: '=='},
41
- * { compoundType: 'OR', conditions: [{column: 'age', value: 21, operator: '<='},
42
- * {column: 'age', value: 52, operator: '>='}]}]] which would filter the query to only include items where the
43
- * name is 'test' and the age is less than or equal to 21 or greater than or equal to 52.
44
- */
45
- export type CompoundCondition = {
46
- compoundType: CompoundType,
47
- conditions: Array<Condition | CompoundCondition>
48
- };
49
-
50
- export const isCondition = (condition: any): condition is Condition => {
51
- return (
52
- typeof condition.column === 'string' &&
53
- (Array.isArray(condition.value) && condition.value.every((item: any) => typeof item === 'string')) ||
54
- (Array.isArray(condition.value) && condition.value.every((item: any) => typeof item === 'number')) ||
55
- typeof condition.value === 'string' ||
56
- typeof condition.value === 'number' ||
57
- typeof condition.value === 'boolean' ||
58
- condition.value instanceof Date ||
59
- condition.value === null
60
- ) && (condition.operator ? typeof condition.operator === 'string' : true);
61
- }
62
-
63
- export type EventQuery = {
64
- start?: Date,
65
- end?: Date,
66
- by?: string,
67
- }
68
-
69
- export type OrderDirection = 'asc' | 'desc';
70
-
71
- export type OrderBy = {
72
- field: string;
73
- direction: OrderDirection;
74
- }
75
-
76
- export type ItemQuery = {
77
- refs?: References;
78
- compoundCondition?: CompoundCondition;
79
- limit?: number;
80
- offset?: number;
81
- aggs?: Record<
82
- string,
83
- ItemQuery
84
- >;
85
- events?: Record<string, EventQuery>;
86
- orderBy?: OrderBy[];
87
- };
88
-