@beseif-solutions/prow-core 0.0.16

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 (47) hide show
  1. package/dist/core.d.ts +21 -0
  2. package/dist/core.js +46 -0
  3. package/dist/entities/category.d.ts +1 -0
  4. package/dist/entities/category.js +20 -0
  5. package/dist/entities/commons.d.ts +26 -0
  6. package/dist/entities/commons.js +15 -0
  7. package/dist/entities/credentials.d.ts +85 -0
  8. package/dist/entities/credentials.js +48 -0
  9. package/dist/entities/events.d.ts +131 -0
  10. package/dist/entities/events.js +82 -0
  11. package/dist/entities/provider.d.ts +12 -0
  12. package/dist/entities/provider.js +25 -0
  13. package/dist/index.d.ts +8 -0
  14. package/dist/index.js +33 -0
  15. package/dist/minified-utils/context.d.ts +6 -0
  16. package/dist/minified-utils/context.js +55 -0
  17. package/dist/minified-utils/env.d.ts +13 -0
  18. package/dist/minified-utils/env.js +96 -0
  19. package/dist/minified-utils/fields.d.ts +128 -0
  20. package/dist/minified-utils/fields.js +458 -0
  21. package/dist/minified-utils/locales.d.ts +27 -0
  22. package/dist/minified-utils/locales.js +88 -0
  23. package/dist/minified-utils/proxy.d.ts +9 -0
  24. package/dist/minified-utils/proxy.js +55 -0
  25. package/dist/minified-utils/types.d.ts +11 -0
  26. package/dist/minified-utils/types.js +2 -0
  27. package/dist/minified-utils/utils.d.ts +1 -0
  28. package/dist/minified-utils/utils.js +26 -0
  29. package/dist/minified-utils/where.d.ts +40 -0
  30. package/dist/minified-utils/where.js +265 -0
  31. package/package.json +44 -0
  32. package/src/core.ts +56 -0
  33. package/src/entities/category.ts +9 -0
  34. package/src/entities/commons.ts +40 -0
  35. package/src/entities/credentials.ts +131 -0
  36. package/src/entities/events.ts +198 -0
  37. package/src/entities/provider.ts +29 -0
  38. package/src/index.ts +8 -0
  39. package/src/minified-utils/context.ts +56 -0
  40. package/src/minified-utils/env.ts +90 -0
  41. package/src/minified-utils/fields.ts +628 -0
  42. package/src/minified-utils/locales.ts +124 -0
  43. package/src/minified-utils/proxy.ts +44 -0
  44. package/src/minified-utils/types.ts +18 -0
  45. package/src/minified-utils/utils.ts +18 -0
  46. package/src/minified-utils/where.ts +330 -0
  47. package/tsconfig.json +21 -0
@@ -0,0 +1,124 @@
1
+ import I18n from 'i18n';
2
+ import _ from 'lodash';
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import { Credentials, SessionCredentials, StaticCredentials } from '../entities/credentials';
6
+ import { Action, ConnectableEvent, Trigger } from '../entities/events';
7
+ import { Field, SelectFieldChoice } from './fields';
8
+ import { Provider } from '../entities/provider';
9
+ import { validateDirectory } from './utils';
10
+
11
+ type LocalizedField = {
12
+ label: string,
13
+ help: string,
14
+ };
15
+
16
+ type LocalizedProperties = {
17
+ name: string,
18
+ description: string,
19
+ };
20
+
21
+ type TOptions = { fallback?: boolean };
22
+
23
+ const DEFAULT_LOCALE = `en`;
24
+
25
+ export const i18n = (directory: string, options: { locale?: string } = {}) => {
26
+ try {
27
+ if (!validateDirectory(directory)) {
28
+ throw new Error(`Invalid directory: ${directory}`);
29
+ }
30
+
31
+ const availableLocales = fs.readdirSync(directory).map((file) => path.basename(file, path.extname(file)));
32
+ const requestedLocale = options.locale || DEFAULT_LOCALE;
33
+
34
+ const activeLocale = availableLocales.includes(requestedLocale) ? requestedLocale : DEFAULT_LOCALE;
35
+
36
+ const i18nInstance: I18n.I18n = new I18n.I18n({
37
+ locales: availableLocales,
38
+ directory: directory,
39
+ defaultLocale: DEFAULT_LOCALE,
40
+ objectNotation: true,
41
+ autoReload: true,
42
+ missingKeyFn: () => ``,
43
+ });
44
+ i18nInstance.setLocale(activeLocale);
45
+
46
+ return {
47
+ t: (code: string, opts: TOptions = {}) => {
48
+ let response = i18nInstance.__(code);
49
+ if (!response && opts.fallback) {
50
+ response = i18nInstance.__({ phrase: code, locale: DEFAULT_LOCALE });
51
+ }
52
+ return response;
53
+ }, i18n: i18nInstance,
54
+ };
55
+ } catch (e) { throw e; }
56
+ };
57
+
58
+ const localizeField = (
59
+ t: ReturnType<typeof i18n>[`t`],
60
+ element: string,
61
+ field: Field<LocalizedField>,
62
+ parent = ``,
63
+ ): Field<LocalizedField> => {
64
+ const key = _.compact([parent, field.key]).join(`.`);
65
+ field.label = t(`${element}.fields.${key}.label`, { fallback: true });
66
+ field.help = t(`${element}.fields.${key}.help`);
67
+
68
+ if (field.type === `dict` && field.items) {
69
+ field.items = field.items.map((f) => localizeField(t, element, f, `${key}.items`));
70
+ } else if (`format` in field && field.format === `select` && _.isArray(field.choices)) {
71
+ field.choices = field.choices.map((fc: SelectFieldChoice<any, LocalizedField>) => ({
72
+ ...fc,
73
+ label: t(`${element}.fields.${key}.choices.${fc.key}.label`, { fallback: true }),
74
+ help: t(`${element}.fields.${key}.choices.${fc.key}.help`),
75
+ }));
76
+ }
77
+
78
+ return field;
79
+ };
80
+
81
+ export const localizeFields = (
82
+ t: ReturnType<typeof i18n>[`t`],
83
+ element: Action | Trigger | StaticCredentials | SessionCredentials,
84
+ ): Field<LocalizedField>[] => {
85
+ const response: Field<LocalizedField>[] = [];
86
+ if (element[`fields`] && element[`fields`].length > 0) {
87
+ response.push(...element[`fields`].map((f) => localizeField(t, element.id, f as any)));
88
+ }
89
+ return response;
90
+ };
91
+
92
+ export const localizeProperties = (
93
+ t: ReturnType<typeof i18n>[`t`],
94
+ element: Action | Trigger | Credentials | Provider,
95
+ ): LocalizedProperties => ({
96
+ name: t(`${element.id}.name`, { fallback: true }),
97
+ description: t(`${element.id}.description`),
98
+ });
99
+
100
+ const localizeConnectable = (
101
+ t: ReturnType<typeof i18n>[`t`],
102
+ element: Action | Trigger,
103
+ type: `inputs` | `outputs`,
104
+ ): (ConnectableEvent & LocalizedProperties)[] => {
105
+ const response: (ConnectableEvent & LocalizedProperties)[] = [];
106
+ if (element[type] && element[type].length > 0) {
107
+ response.push(...(element[type] as ConnectableEvent[]).map((c) => ({
108
+ ...c,
109
+ name: t(`${element.id}.${type}.${c.key}.name`, { fallback: true }),
110
+ description: t(`${element.id}.${type}.${c.key}.description`),
111
+ })));
112
+ }
113
+ return response;
114
+ };
115
+
116
+ export const localizeInputs = (
117
+ t: ReturnType<typeof i18n>[`t`],
118
+ element: Action,
119
+ ) => localizeConnectable(t, element, `inputs`);
120
+
121
+ export const localizeOutputs = (
122
+ t: ReturnType<typeof i18n>[`t`],
123
+ element: Action | Trigger,
124
+ ) => localizeConnectable(t, element, `outputs`);
@@ -0,0 +1,44 @@
1
+ import { AsyncReturnType } from "./types";
2
+
3
+ export type ProxyLogs<F extends (...args: any[]) => any> = {
4
+ before?: (name: string, args: Parameters<F>) => (void | Promise<void>),
5
+ after?: (name: string, response: AsyncReturnType<F>) => (void | Promise<void>),
6
+ error?: (name: string, error: Error) => (void | Promise<void>),
7
+ };
8
+
9
+ export const logProxy = <F extends (...args: any[]) => any>(name: string, f: F, logs: ProxyLogs<F> = {}) => new Proxy(f, {
10
+ apply: async (target, self, args: Parameters<F>) => {
11
+ try {
12
+ if (logs.before) { await logs.before(name, args); }
13
+ const response = await target(...args);
14
+ if (logs.after) { await logs.after(name, response); }
15
+ return response;
16
+ } catch (e) {
17
+ if (logs.error) { await logs.error(name, e); }
18
+ throw e;
19
+ }
20
+ },
21
+ });
22
+
23
+ export const functionProxy = <F extends (...args: any[]) => (any | Promise<any>)>(f: F, name?: string) => new Proxy(f, {
24
+ apply: async (target, self, args) => {
25
+ try {
26
+ console.log(`Call to ${name || target}`);
27
+ const response = await target(...args);
28
+ return response;
29
+ } catch (e) { throw e; }
30
+ },
31
+ });
32
+
33
+ export const accessProxy = <T extends object>(obj: T, custom?: Partial<{ [K in keyof T]: T[K] }>) => new Proxy(obj, {
34
+ get: (target, prop) => {
35
+ const value = target[prop];
36
+ if (custom && custom[prop]) {
37
+ return custom[prop];
38
+ } else if (typeof value === `function`) {
39
+ return functionProxy(value, prop as string);
40
+ } else if (typeof value === `object`) {
41
+ return accessProxy(value);
42
+ } else { return value; }
43
+ },
44
+ });
@@ -0,0 +1,18 @@
1
+ export type RequireMinOne<T, Keys extends keyof T = keyof T> = Pick<T, Exclude<keyof T, Keys>> & {
2
+ [K in Keys]-?: Required<Pick<T, K>>;
3
+ }[Keys];
4
+
5
+ export type RequireOne<T extends Record<string, any>, Keys extends keyof T = keyof T> = Pick<T, Exclude<keyof T, Keys>> & {
6
+ [K in Keys]-?: Required<Pick<T, K>> & Partial<Record<Exclude<Keys, K>, undefined>>;
7
+ }[Keys];
8
+
9
+ export type OneOf<T extends Record<string, any>> = Partial<RequireOne<T>>;
10
+
11
+ export type DeepPartial<T extends Record<string, any>> = {
12
+ [P in keyof T]?: T[P] extends Record<string, any> ? DeepPartial<T[P]> : T[P];
13
+ };
14
+
15
+ export type AsyncReturnType<T extends (...args: any[]) => any> =
16
+ T extends (...args: any[]) => Promise<infer U> ? U :
17
+ T extends (...args: any[]) => infer U ? U :
18
+ any;
@@ -0,0 +1,18 @@
1
+ import fs from 'fs';
2
+ export const validateDirectory = (directory: string): boolean => {
3
+ try {
4
+ if (!fs.existsSync(directory)) {
5
+ console.error(`Directory does not exist: ${directory}`);
6
+ return false;
7
+ }
8
+ const files = fs.readdirSync(directory);
9
+ if (!files.some((file) => file.endsWith(`.json`))) {
10
+ console.error(`No valid localization files found in directory: ${directory}`);
11
+ return false;
12
+ }
13
+ return true;
14
+ } catch (error) {
15
+ console.error(`Error validating directory: ${error.message}`);
16
+ return false;
17
+ }
18
+ };
@@ -0,0 +1,330 @@
1
+ import moment from "moment-timezone";
2
+ import { DeepPartial, RequireMinOne } from "./types";
3
+ import _ from "lodash";
4
+ import Joi from "joi";
5
+
6
+ type Basic = string | number | boolean;
7
+ type Is<T extends Basic> = {
8
+ is: T,
9
+ };
10
+ type Like<T extends Basic> = T extends string ? {
11
+ like: T,
12
+ } : undefined;
13
+ type ILike<T extends Basic> = T extends string ? {
14
+ ilike: T,
15
+ } : undefined;
16
+ type In<T extends Basic> = {
17
+ in: T[],
18
+ };
19
+ type Range<T extends Basic> = RequireMinOne<{
20
+ lt: T,
21
+ eq: T,
22
+ gt: T,
23
+ gte: T,
24
+ lte: T,
25
+ }> & {
26
+ date?: boolean,
27
+ };
28
+ type Contains<T extends (Basic | Record<string, any>)[]> = {
29
+ contains: T[number] | T,
30
+ };
31
+ type Complex<T extends (Basic | (Basic | Record<string, any>)[])> = T extends Basic ? Is<T> | Like<T> | ILike<T> | In<T> | Range<T> : T extends (Basic | Record<string, any>)[] ? T extends Record<string, any>[] ? Contains<DeepPartial<T[number]>[]> : Contains<T> : never;
32
+ type Condition<T> = (T extends Basic ? T : T extends Complex<infer F> ? (Complex<F> & {
33
+ inverse?: boolean,
34
+ nullable?: boolean,
35
+ relational?: string,
36
+ }) : never);
37
+
38
+ export type Where<T extends Record<string, any> = Record<string, any>> = Partial<{
39
+ [K in keyof T]: T[K] extends Basic ? Condition<T[K] | Complex<T[K]>> | Condition<T[K] | Complex<T[K]>>[] : (T[K] extends Record<string, any> ? Where<T[K]> : (T[K] extends any[] ? Condition<Complex<T[K]>> : never));
40
+ }>;
41
+
42
+ const conditionSchema = () => Joi.object({
43
+ inverse: Joi.bool(),
44
+ nullable: Joi.bool(),
45
+ });
46
+
47
+ const relationalSchema = () => conditionSchema()
48
+ .concat(Joi.object({
49
+ relational: Joi.string().required(),
50
+ is: Joi.string().allow(null),
51
+ in: Joi.array().items(Joi.string().allow(null)),
52
+ lt: Joi.string().allow(null),
53
+ eq: Joi.string().allow(null),
54
+ gt: Joi.string().allow(null),
55
+ gte: Joi.string().allow(null),
56
+ lte: Joi.string().allow(null),
57
+ }));
58
+
59
+ const numberSchema = (params: { strict: boolean }) => conditionSchema()
60
+ .concat(Joi.object({
61
+ is: Joi.number().strict(params.strict).allow(null),
62
+ in: Joi.array().items(Joi.number().strict(params.strict).allow(null)),
63
+ lt: Joi.number().strict(params.strict).allow(null),
64
+ eq: Joi.number().strict(params.strict).allow(null),
65
+ gt: Joi.number().strict(params.strict).allow(null),
66
+ gte: Joi.number().strict(params.strict).allow(null),
67
+ lte: Joi.number().strict(params.strict).allow(null),
68
+ })).or(`is`, `in`, `lt`, `eq`, `gt`, `gte`, `lte`);
69
+
70
+ const stringSchema = (params: { strict: boolean }) => conditionSchema()
71
+ .concat(Joi.object({
72
+ is: Joi.string().strict(params.strict).allow(null),
73
+ like: Joi.string().strict(params.strict).allow(null),
74
+ ilike: Joi.string().strict(params.strict).allow(null),
75
+ in: Joi.array().items(Joi.string().strict(params.strict).allow(null)),
76
+ })).or(`is`, `ilike`, `like`, `in`);
77
+
78
+ const boolSchema = (params: { strict: boolean }) => conditionSchema()
79
+ .concat(Joi.object({
80
+ is: Joi.bool().strict(params.strict).allow(null),
81
+ })).or(`is`);
82
+
83
+ const dateSchema = (params: { strict: boolean }) => conditionSchema()
84
+ .concat(Joi.object({
85
+ lt: Joi.date().strict(params.strict).allow(null),
86
+ eq: Joi.date().strict(params.strict).allow(null),
87
+ gt: Joi.date().strict(params.strict).allow(null),
88
+ gte: Joi.date().strict(params.strict).allow(null),
89
+ lte: Joi.date().strict(params.strict).allow(null),
90
+ date: true,
91
+ })).or(`lt`, `eq`, `gt`, `gte`, `lte`);
92
+
93
+
94
+ const arraySchema = () => conditionSchema()
95
+ .concat(Joi.object({
96
+ contains: Joi.alternatives(
97
+ basicSchema(),
98
+ Joi.array().items(Joi.any()),
99
+ Joi.object()
100
+ .pattern(Joi.string(), Joi.alternatives(basicSchema(), Joi.array().items(Joi.any()), Joi.link(`#object`)))
101
+ .id(`object`),
102
+ ),
103
+ }));
104
+
105
+ const basicSchema = () => Joi.alternatives(Joi.string().strict(false), Joi.number().strict(false), Joi.bool().strict(false));
106
+
107
+ const complexSchema = () => Joi.alternatives(
108
+ numberSchema({ strict: false }),
109
+ stringSchema({ strict: false }),
110
+ boolSchema({ strict: false }),
111
+ dateSchema({ strict: false }),
112
+ arraySchema(),
113
+ relationalSchema());
114
+
115
+ const orSchema = () => Joi.array().items(Joi.alternatives(basicSchema(), complexSchema()));
116
+
117
+ const whereSchema = () => Joi.object()
118
+ .pattern(Joi.string(), Joi.alternatives(
119
+ // and queries
120
+ basicSchema(), complexSchema(),
121
+ // or queries
122
+ orSchema(),
123
+ // recursive schema
124
+ Joi.link(`#where`)))
125
+ .id(`where`);
126
+
127
+ const clearObject = (obj: Record<string, any>, path = ``): void => {
128
+ _.map(obj || {}, (v, k) => {
129
+ if (_.isUndefined(v)) { _.unset(obj, `${path}${k}`); }
130
+ if (_.isObject(v)) { clearObject(v, `${k}.`); }
131
+ });
132
+ };
133
+
134
+ const validate = <DataType>(schema: Joi.Schema, data: DataType, options?: any): DataType => {
135
+ try {
136
+ if (!_.isFunction(schema[`validate`])) { throw new Error(`Invalid schema`); }
137
+ if (_.isObject(data)) { clearObject(data); }
138
+ const result = schema.validate(data, options);
139
+ if (result.error) { throw result.error; }
140
+ return data;
141
+ } catch (err) {
142
+ throw new Error(_.get(err, `details.0.message`) || err.message || err);
143
+ }
144
+ };
145
+
146
+ const isBasic = (condition: any): condition is Basic => {
147
+ try {
148
+ basicSchema().validate(condition);
149
+ validate(basicSchema(), condition);
150
+ return true;
151
+ } catch (e) { return false; }
152
+ };
153
+
154
+ const isComplex = (condition: any): condition is Complex<any> => {
155
+ try {
156
+ validate(complexSchema(), condition);
157
+ return true;
158
+ } catch (e) { return false; }
159
+ };
160
+
161
+ const isOr = (condition: any): condition is (Basic | Complex<any>)[] => {
162
+ try {
163
+ validate(orSchema(), condition);
164
+ return true;
165
+ } catch (e) { return false; }
166
+ };
167
+
168
+ const isWhere = (condition: any): condition is Where => {
169
+ try {
170
+ validate(whereSchema(), condition);
171
+ return true;
172
+ } catch (e) { return false; }
173
+ };
174
+
175
+ const processRange = (condition: Basic, value: Basic, comparator: `<` | `=` | `>` | `>=` | `<=`, date: boolean): boolean => {
176
+ let v1: any;
177
+ let v2: any;
178
+ let compare: ((v1: any, v2: any) => boolean);
179
+
180
+ if (date) {
181
+ v1 = moment(value as any);
182
+ v2 = moment(condition as any);
183
+ switch (comparator) {
184
+ case `<`:
185
+ compare = (d1: moment.Moment, d2: moment.Moment) => d1.isBefore(d2);
186
+ break;
187
+ case `=`:
188
+ compare = (d1: moment.Moment, d2: moment.Moment) => !d1.isAfter(d2) && !d1.isBefore(d2);
189
+ break;
190
+ case `>`:
191
+ compare = (d1: moment.Moment, d2: moment.Moment) => d1.isAfter(d2);
192
+ break;
193
+ case `>=`:
194
+ compare = (d1: moment.Moment, d2: moment.Moment) => d1.isAfter(d2) || (!d1.isAfter(d2) && !d1.isBefore(d2));
195
+ break;
196
+ case `<=`:
197
+ compare = (d1: moment.Moment, d2: moment.Moment) => d1.isBefore(d2) || (!d1.isAfter(d2) && !d1.isBefore(d2));
198
+ break;
199
+ }
200
+ } else {
201
+ v1 = value;
202
+ v2 = condition;
203
+ switch (comparator) {
204
+ case `<`:
205
+ compare = (d1: any, d2: any) => d1 < d2;
206
+ break;
207
+ case `=`:
208
+ compare = (d1: any, d2: any) => d1 === d2;
209
+ break;
210
+ case `>`:
211
+ compare = (d1: any, d2: any) => d1 > d2;
212
+ break;
213
+ case `>=`:
214
+ compare = (d1: moment.Moment, d2: moment.Moment) => d1 >= d2;
215
+ break;
216
+ case `<=`:
217
+ compare = (d1: moment.Moment, d2: moment.Moment) => d1 <= d2;
218
+ break;
219
+ }
220
+ }
221
+ return compare(v1, v2);
222
+ };
223
+
224
+ type Flags = {
225
+ i?: boolean, // case insensitive
226
+ };
227
+
228
+ const processBasic = (value: Basic, condition: Condition<Basic>, flags?: Flags): boolean =>
229
+ (typeof value === `string` && typeof condition === `string` && flags?.i) ?
230
+ value.toLowerCase() === condition.toLowerCase()
231
+ : value === condition;
232
+
233
+ const processComplex = (value: Basic, condition: Condition<Complex<any>>, flags?: Flags): boolean => {
234
+
235
+ const results: boolean[] = [];
236
+
237
+ // helpers
238
+ const withNullable = (bool: boolean, val: Basic) => (bool || condition.nullable && _.isNull(val));
239
+ const withInverse = (bool: boolean) => bool !== condition.inverse;
240
+
241
+ // is
242
+ if (`is` in condition) {
243
+ const is = (typeof value === `string` && typeof condition.is === `string` && flags?.i) ?
244
+ value.toLowerCase() === condition.is.toLowerCase()
245
+ : value === condition.is;
246
+ results.push(withInverse(withNullable(is, value)));
247
+ }
248
+
249
+ // like
250
+ if (`like` in condition) {
251
+ const regexp = new RegExp(`^${condition.like.replace(/%/g, `.*`).replace(/_/g, `.`)}$`);
252
+ const like = regexp.test(value as string);
253
+ results.push(withInverse(withNullable(like, value)));
254
+ }
255
+
256
+ if (`ilike` in condition) {
257
+ const regexp = new RegExp(`^${condition.ilike.replace(/%/g, `.*`).replace(/_/g, `.`)}$`, `i`);
258
+ const ilike = regexp.test(value as string);
259
+ results.push(withInverse(withNullable(ilike, value)));
260
+ }
261
+
262
+ // in
263
+ if (`in` in condition) {
264
+ const isIn = (condition.in && condition.in.length > 0) ?
265
+ _.includes(condition.in, value) :
266
+ _.isNull(value);
267
+ results.push(withInverse(withNullable(isIn, value)));
268
+ }
269
+
270
+ // range
271
+ if (`lt` in condition) {
272
+ const lt = processRange(condition.lt, value, `<`, condition.date || false);
273
+ results.push(withInverse(withNullable(lt, value)));
274
+ }
275
+ if (`eq` in condition) {
276
+ const eq = processRange(condition.eq, value, `=`, condition.date || false);
277
+ results.push(withInverse(withNullable(eq, value)));
278
+ }
279
+ if (`gt` in condition) {
280
+ const gt = processRange(condition.gt, value, `>`, condition.date || false);
281
+
282
+ results.push(withInverse(withNullable(gt, value)));
283
+ }
284
+ if (`gte` in condition) {
285
+ const gte = processRange(condition.gte, value, `>=`, condition.date || false);
286
+ results.push(withInverse(withNullable(gte, value)));
287
+ }
288
+ if (`lte` in condition) {
289
+ const lte = processRange(condition.lte, value, `<=`, condition.date || false);
290
+ results.push(withInverse(withNullable(lte, value)));
291
+ }
292
+
293
+ return !results.some((r) => !r);
294
+ };
295
+
296
+ const processWhere = (json: Record<string, any>, conditions: Where[], flags?: Flags): boolean => {
297
+
298
+ let matches = false;
299
+ for (const w of conditions) {
300
+
301
+ let matchesWhere = true;
302
+ for (const key of _.keys(w)) {
303
+ const value = _.get(json, key, null);
304
+ // if (_.isUndefined(value)) { matchesWhere = false; break; }
305
+
306
+ const cond = w[key];
307
+ if (isOr(cond)) {
308
+ matchesWhere &&= _.some(cond, (c) => processWhere({ [key]: value }, [{ [key]: c }], flags));
309
+ } else if (isBasic(cond)) {
310
+ matchesWhere &&= processBasic(value, cond, flags);
311
+ } else if (isComplex(cond)) {
312
+ matchesWhere &&= processComplex(value, cond, flags);
313
+ } else if (isWhere(cond)) {
314
+ matchesWhere &&= processWhere(value, [cond], flags);
315
+ } else {
316
+ // TODO
317
+ continue;
318
+ }
319
+
320
+ if (!matchesWhere) { break; }
321
+ }
322
+ matches ||= matchesWhere;
323
+ if (matches) { break; }
324
+ }
325
+
326
+ return matches;
327
+ };
328
+
329
+ export const where = (json: Record<string, any>, conditions: Where[], flags?: Flags): boolean =>
330
+ processWhere(json, conditions, flags);
package/tsconfig.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "commonjs",
5
+ "experimentalDecorators": true,
6
+ "emitDecoratorMetadata": true,
7
+ "removeComments": true,
8
+ "esModuleInterop": true,
9
+ "outDir": "dist",
10
+ "resolveJsonModule": true,
11
+ "declaration": true
12
+ },
13
+ "include": [
14
+ "src/**/*.ts",
15
+ ],
16
+ "exclude": [
17
+ "./test",
18
+ "node_modules",
19
+ "dist/**/*.js"
20
+ ]
21
+ }