@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,96 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Env = void 0;
7
+ const dotenv_1 = require("dotenv");
8
+ const fs_1 = require("fs");
9
+ const lodash_1 = __importDefault(require("lodash"));
10
+ const path_1 = __importDefault(require("path"));
11
+ const readline_1 = require("readline");
12
+ class Env {
13
+ constructor(root) {
14
+ this.getEnv = (flag) => {
15
+ try {
16
+ const fd = (0, fs_1.openSync)(this.filepath, flag);
17
+ const buffer = (0, fs_1.readFileSync)(fd);
18
+ const parsed = (0, dotenv_1.parse)(buffer);
19
+ return parsed;
20
+ }
21
+ catch (e) {
22
+ throw e;
23
+ }
24
+ };
25
+ this.read = async (name, options = {}) => {
26
+ try {
27
+ let value;
28
+ if (!lodash_1.default.has(this.env, name)) {
29
+ if (!options.create) {
30
+ throw new Error(`Environment variable not found: ${name}`);
31
+ }
32
+ value = await this.prompt(`${name}: `);
33
+ await this.write(name, value);
34
+ }
35
+ else {
36
+ value = lodash_1.default.get(this.env, name);
37
+ }
38
+ return value;
39
+ }
40
+ catch (e) {
41
+ throw e;
42
+ }
43
+ };
44
+ this.write = async (name, value) => {
45
+ try {
46
+ const fd = (0, fs_1.openSync)(this.filepath, `w`);
47
+ this.env[name] = value;
48
+ const arr = [];
49
+ for (const key of Object.keys(this.env)) {
50
+ arr.push(`${key}=${this.env[key]}`);
51
+ }
52
+ const buffer = Buffer.from(arr.join(`\n`));
53
+ (0, fs_1.writeSync)(fd, buffer, 0, buffer.length);
54
+ (0, fs_1.closeSync)(fd);
55
+ }
56
+ catch (e) {
57
+ throw e;
58
+ }
59
+ };
60
+ this.prompt = async (text) => new Promise(async (resolve, reject) => {
61
+ try {
62
+ const stdin = (0, readline_1.createInterface)({
63
+ input: process.stdin,
64
+ output: process.stdout,
65
+ });
66
+ stdin.on(`close`, () => { reject(`Aborted`); });
67
+ stdin.question(text, (answer) => {
68
+ resolve(answer);
69
+ stdin.close();
70
+ });
71
+ }
72
+ catch (e) {
73
+ reject(e.message || e);
74
+ }
75
+ });
76
+ if (path_1.default.isAbsolute(root)) {
77
+ this.filepath = path_1.default.resolve(root, `.env`);
78
+ }
79
+ else {
80
+ const absolute = process.cwd();
81
+ this.filepath = path_1.default.resolve(absolute, root, `.env`);
82
+ }
83
+ try {
84
+ this.env = this.getEnv(`r`);
85
+ }
86
+ catch (e) {
87
+ if (e?.code === `ENOENT`) {
88
+ this.env = this.getEnv(`w`);
89
+ }
90
+ else {
91
+ throw e;
92
+ }
93
+ }
94
+ }
95
+ }
96
+ exports.Env = Env;
@@ -0,0 +1,128 @@
1
+ import Joi from "joi";
2
+ import { OneOf } from "./types";
3
+ import { Where } from "./where";
4
+ export type Condition = {
5
+ condition: Where;
6
+ } & OneOf<{
7
+ overrides: Partial<Field>;
8
+ show: boolean;
9
+ }>;
10
+ type Common = {
11
+ key: string;
12
+ altered_by?: Condition[];
13
+ disabled?: boolean;
14
+ required?: boolean;
15
+ as_password?: boolean;
16
+ } & ({
17
+ as_array?: false;
18
+ } | {
19
+ as_array: true;
20
+ array_min?: number;
21
+ array_max?: number;
22
+ array_length?: number;
23
+ });
24
+ export type Field<Extend = Record<never, never>> = Common & InputField<Extend>;
25
+ type InputField<Extend = Record<never, never>> = (AnyInputField<Extend> | StringInputField<Extend> | NumberInputField<Extend> | BooleanInputField<Extend> | DateTimeInputField<Extend> | DateInputField<Extend> | TimeInputField<Extend> | DictInputField<Extend>) & Extend;
26
+ type Any = string | number | boolean;
27
+ type AnyInputField<Extend = Record<never, never>> = {
28
+ type: `any`;
29
+ default?: Any | Any[];
30
+ } & (SelectField<Any, Extend> | {});
31
+ type StringInputField<Extend = Record<never, never>> = {
32
+ type: `string`;
33
+ default?: string | string[];
34
+ length?: number;
35
+ min?: number;
36
+ max?: number;
37
+ regexp?: string;
38
+ pattern?: `email` | `uri`;
39
+ } & (SelectField<string, Extend> | FileField | TextareaField | RichTextField | {});
40
+ type NumberInputField<Extend = Record<never, never>> = {
41
+ type: `number`;
42
+ default?: number | number[];
43
+ min?: number;
44
+ max?: number;
45
+ } & ({
46
+ float: true;
47
+ decimals?: number;
48
+ } | {
49
+ float: false;
50
+ }) & (SelectField<number, Extend> | {});
51
+ type BooleanInputField<Extend = Record<never, never>> = {
52
+ type: `boolean`;
53
+ default?: boolean | boolean[];
54
+ } & (SelectField<boolean, Extend> | {
55
+ format: `checkbox`;
56
+ } | {
57
+ format: `switch`;
58
+ } | {});
59
+ type DateTimeInputField<Extend = Record<never, never>> = {
60
+ type: `datetime`;
61
+ timezone?: string;
62
+ default?: string | number | (string | number)[];
63
+ min?: number | string;
64
+ max?: number | string;
65
+ } & (SelectField<string | number, Extend> | {});
66
+ type DateInputField<Extend = Record<never, never>> = {
67
+ type: `date`;
68
+ default?: string | string[];
69
+ min?: string;
70
+ max?: string;
71
+ } & (SelectField<string, Extend> | {});
72
+ type TimeInputField<Extend = Record<never, never>> = {
73
+ type: `time`;
74
+ timezone?: string;
75
+ default?: string | string[];
76
+ } & (SelectField<string, Extend> | {});
77
+ type DictInputField<Extend = Record<never, never>> = {
78
+ type: `dict`;
79
+ default?: Record<string, any> | Record<string, any>[];
80
+ items?: Field<Extend>[];
81
+ unknown?: boolean;
82
+ };
83
+ type SelectField<Values = string | number | boolean, Extend = Record<never, never>> = {
84
+ format: `select`;
85
+ choices: SelectFieldChoice<Values, Extend>[] | string;
86
+ unknown?: boolean;
87
+ };
88
+ export type SelectFieldChoice<Values = string | number | boolean, Extend = Record<never, never>> = {
89
+ key: string;
90
+ value: Values;
91
+ } & Extend;
92
+ type FileField = {
93
+ format: `file`;
94
+ };
95
+ type TextareaField = {
96
+ format: `textarea`;
97
+ };
98
+ type RichTextField = {
99
+ format: `rich-text`;
100
+ };
101
+ type ValidationExtended = {
102
+ original: any;
103
+ value: any;
104
+ } & ({
105
+ valid: true;
106
+ } | {
107
+ valid: false;
108
+ errors: {
109
+ path: string;
110
+ message: string;
111
+ type: string;
112
+ }[];
113
+ });
114
+ export declare const fieldSchema: () => Joi.ObjectSchema<any>;
115
+ export declare const fieldsSchema: () => Joi.ArraySchema<any[]>;
116
+ export type ValidationResult<Extended = Record<string, never>> = {
117
+ valid: boolean;
118
+ fields: Field<Extended & ValidationExtended>[];
119
+ };
120
+ export declare const validate: <I>(fields: Field<I>[], data: Record<string, any>, options?: {
121
+ secure?: boolean;
122
+ break?: boolean;
123
+ context?: Record<string, any>;
124
+ }) => Promise<ValidationResult<I>>;
125
+ export declare const extract: (validation: Field<ValidationExtended>[], options?: {
126
+ original?: boolean;
127
+ }) => Promise<Record<string, any>>;
128
+ export {};
@@ -0,0 +1,458 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.extract = exports.validate = exports.fieldsSchema = exports.fieldSchema = void 0;
7
+ const joi_1 = __importDefault(require("joi"));
8
+ const lodash_1 = __importDefault(require("lodash"));
9
+ const where_1 = require("./where");
10
+ const moment_timezone_1 = __importDefault(require("moment-timezone"));
11
+ const axios_1 = __importDefault(require("axios"));
12
+ const context_1 = __importDefault(require("./context"));
13
+ const conditionSchema = () => joi_1.default.object({
14
+ condition: joi_1.default.object(),
15
+ overrides: joi_1.default.object(),
16
+ show: joi_1.default.bool(),
17
+ }).xor(`overrides`, `show`);
18
+ const commonFieldSchema = () => joi_1.default.object({
19
+ key: joi_1.default.string().required(),
20
+ altered_by: joi_1.default.array().items(conditionSchema()),
21
+ disabled: joi_1.default.bool(),
22
+ required: joi_1.default.bool(),
23
+ as_password: joi_1.default.bool(),
24
+ as_array: joi_1.default.bool(),
25
+ array_min: joi_1.default.when(`as_array`, {
26
+ is: true,
27
+ then: joi_1.default.number(),
28
+ otherwise: joi_1.default.forbidden(),
29
+ }),
30
+ array_max: joi_1.default.when(`as_array`, {
31
+ is: true,
32
+ then: joi_1.default.number(),
33
+ otherwise: joi_1.default.forbidden(),
34
+ }),
35
+ array_length: joi_1.default.when(`as_array`, {
36
+ is: true,
37
+ then: joi_1.default.number(),
38
+ otherwise: joi_1.default.forbidden(),
39
+ }),
40
+ });
41
+ const types = [`any`, `string`, `number`, `boolean`, `date`, `datetime`, `time`, `dict`];
42
+ const inputFieldBaseSchema = () => joi_1.default.object({
43
+ type: joi_1.default.string().required()
44
+ .valid(...types),
45
+ })
46
+ .concat(commonFieldSchema())
47
+ .unknown();
48
+ const choiceSchema = (type) => joi_1.default.object({
49
+ key: joi_1.default.string().required(),
50
+ value: type.required(),
51
+ }).unknown();
52
+ const choicesSchema = (type) => joi_1.default.alternatives(joi_1.default.string(), joi_1.default.array().min(1)
53
+ .items(choiceSchema(type)));
54
+ const defaultSchema = (type) => joi_1.default.when(`as_array`, {
55
+ is: true,
56
+ then: joi_1.default.array().items(type),
57
+ otherwise: type,
58
+ });
59
+ const anySchema = () => joi_1.default.alternatives(joi_1.default.string(), joi_1.default.bool(), joi_1.default.number());
60
+ const anyInputFieldSchema = () => joi_1.default.object({
61
+ default: defaultSchema(anySchema()),
62
+ })
63
+ .concat(joi_1.default.object({
64
+ format: joi_1.default.string().valid(`select`),
65
+ choices: joi_1.default.when(`format`, {
66
+ is: `select`,
67
+ then: choicesSchema(anySchema()).required(),
68
+ otherwise: joi_1.default.forbidden(),
69
+ }),
70
+ }));
71
+ const stringInputFieldSchema = () => joi_1.default.object({
72
+ default: defaultSchema(joi_1.default.string()),
73
+ length: joi_1.default.number(),
74
+ min: joi_1.default.number(),
75
+ max: joi_1.default.number(),
76
+ regexp: joi_1.default.string(),
77
+ pattern: joi_1.default.string().valid(`email`, `uri`),
78
+ })
79
+ .concat(joi_1.default.object({
80
+ format: joi_1.default.string().valid(`file`, `select`, `textarea`, `rich-text`),
81
+ choices: joi_1.default.when(`format`, {
82
+ is: `select`,
83
+ then: choicesSchema(joi_1.default.string()).required(),
84
+ otherwise: joi_1.default.forbidden(),
85
+ }),
86
+ }));
87
+ const numberInputFieldSchema = () => joi_1.default.object({
88
+ default: defaultSchema(joi_1.default.number()),
89
+ min: joi_1.default.number(),
90
+ max: joi_1.default.number(),
91
+ float: joi_1.default.bool(),
92
+ decimals: joi_1.default.when(`float`, {
93
+ is: true,
94
+ then: joi_1.default.number().required(),
95
+ otherwise: joi_1.default.forbidden(),
96
+ }),
97
+ })
98
+ .concat(joi_1.default.object({
99
+ format: joi_1.default.string().valid(`select`),
100
+ choices: joi_1.default.when(`format`, {
101
+ is: `select`,
102
+ then: choicesSchema(joi_1.default.number()).required(),
103
+ otherwise: joi_1.default.forbidden(),
104
+ }),
105
+ }));
106
+ const booleanInputFieldSchema = () => joi_1.default.object({
107
+ default: defaultSchema(joi_1.default.bool()),
108
+ })
109
+ .concat(joi_1.default.object({
110
+ format: joi_1.default.string().valid(`select`, `checkbox`, `switch`),
111
+ choices: joi_1.default.when(`format`, {
112
+ is: `select`,
113
+ then: choicesSchema(joi_1.default.bool()).required(),
114
+ otherwise: joi_1.default.forbidden(),
115
+ }),
116
+ }));
117
+ const dateInputFieldSchema = () => joi_1.default.object({
118
+ default: defaultSchema(joi_1.default.alternatives(joi_1.default.string(), joi_1.default.number())),
119
+ min: joi_1.default.alternatives(joi_1.default.string(), joi_1.default.number()),
120
+ max: joi_1.default.alternatives(joi_1.default.string(), joi_1.default.number()),
121
+ })
122
+ .concat(joi_1.default.object({
123
+ format: joi_1.default.string().valid(`select`),
124
+ choices: joi_1.default.when(`format`, {
125
+ is: `select`,
126
+ then: choicesSchema(joi_1.default.alternatives(joi_1.default.string(), joi_1.default.number())).required(),
127
+ otherwise: joi_1.default.forbidden(),
128
+ }),
129
+ }));
130
+ const timeInputFieldSchema = () => joi_1.default.object({
131
+ default: defaultSchema(joi_1.default.alternatives(joi_1.default.string(), joi_1.default.number())),
132
+ })
133
+ .concat(joi_1.default.object({
134
+ format: joi_1.default.string().valid(`select`),
135
+ choices: joi_1.default.when(`format`, {
136
+ is: `select`,
137
+ then: choicesSchema(joi_1.default.alternatives(joi_1.default.string(), joi_1.default.number())).required(),
138
+ otherwise: joi_1.default.forbidden(),
139
+ }),
140
+ }));
141
+ const dictInputFieldSchema = () => joi_1.default.object({
142
+ default: defaultSchema(joi_1.default.object()),
143
+ items: joi_1.default.array().items(joi_1.default.link(`#field`)).min(1),
144
+ unknown: joi_1.default.when(`items`, {
145
+ is: joi_1.default.exist(),
146
+ then: joi_1.default.bool(),
147
+ otherwise: joi_1.default.forbidden(),
148
+ }),
149
+ });
150
+ const fieldSchema = () => inputFieldBaseSchema()
151
+ .id(`field`)
152
+ .when(joi_1.default.object({ type: joi_1.default.valid(`any`) }).unknown(), {
153
+ then: inputFieldBaseSchema()
154
+ .concat(anyInputFieldSchema()),
155
+ })
156
+ .when(joi_1.default.object({ type: joi_1.default.valid(`string`) }).unknown(), {
157
+ then: inputFieldBaseSchema()
158
+ .concat(stringInputFieldSchema()),
159
+ })
160
+ .when(joi_1.default.object({ type: joi_1.default.valid(`number`) }).unknown(), {
161
+ then: inputFieldBaseSchema()
162
+ .concat(numberInputFieldSchema()),
163
+ })
164
+ .when(joi_1.default.object({ type: joi_1.default.valid(`boolean`) }).unknown(), {
165
+ then: inputFieldBaseSchema()
166
+ .concat(booleanInputFieldSchema()),
167
+ })
168
+ .when(joi_1.default.object({ type: joi_1.default.valid(`date`, `datetime`) }).unknown(), {
169
+ then: inputFieldBaseSchema()
170
+ .concat(dateInputFieldSchema()),
171
+ })
172
+ .when(joi_1.default.object({ type: joi_1.default.valid(`time`) }).unknown(), {
173
+ then: inputFieldBaseSchema()
174
+ .concat(timeInputFieldSchema()),
175
+ })
176
+ .when(joi_1.default.object({ type: joi_1.default.valid(`dict`) }).unknown(), {
177
+ then: inputFieldBaseSchema()
178
+ .concat(dictInputFieldSchema()),
179
+ })
180
+ .when(joi_1.default.object({ type: joi_1.default.invalid(...types) }).unknown(), {
181
+ then: joi_1.default.forbidden(),
182
+ });
183
+ exports.fieldSchema = fieldSchema;
184
+ const fieldsSchema = () => joi_1.default.array().items((0, exports.fieldSchema)());
185
+ exports.fieldsSchema = fieldsSchema;
186
+ const getFieldSchema = (field) => {
187
+ let typeSchema;
188
+ switch (field.type) {
189
+ case `any`:
190
+ typeSchema = anySchema();
191
+ break;
192
+ case `boolean`:
193
+ typeSchema = joi_1.default.bool();
194
+ break;
195
+ case `string`:
196
+ typeSchema = joi_1.default.string();
197
+ if (field.length) {
198
+ typeSchema = typeSchema.length(field.length);
199
+ }
200
+ if (field.min) {
201
+ typeSchema = typeSchema.min(field.min);
202
+ }
203
+ else {
204
+ typeSchema = typeSchema.allow(``);
205
+ }
206
+ if (field.max) {
207
+ typeSchema = typeSchema.max(field.max);
208
+ }
209
+ if (field.regexp) {
210
+ typeSchema = typeSchema.regex(new RegExp(field.regexp));
211
+ }
212
+ if (field.pattern === `email`) {
213
+ typeSchema = typeSchema.email();
214
+ }
215
+ if (field.pattern === `uri`) {
216
+ typeSchema = typeSchema.uri();
217
+ }
218
+ if (`format` in field && field.format === `file`) {
219
+ typeSchema = typeSchema.external(async (value, helpers) => {
220
+ if (!helpers.original && !field.required) {
221
+ return helpers.original;
222
+ }
223
+ const [asURL, asBase64] = await Promise.allSettled([
224
+ (async () => {
225
+ try {
226
+ const { value: url, error } = joi_1.default.string().uri().validate(helpers.original);
227
+ if (error) {
228
+ throw new Error(`Invalid URL schema`);
229
+ }
230
+ const { data: content } = await axios_1.default.get(url, { responseType: `arraybuffer` });
231
+ return Buffer.from(content).toString(`base64`);
232
+ }
233
+ catch (e) {
234
+ throw e;
235
+ }
236
+ })(),
237
+ (async () => {
238
+ try {
239
+ const base64regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/;
240
+ if (!base64regex.test(helpers.original)) {
241
+ throw new Error(`Invalid regexp`);
242
+ }
243
+ return Buffer.from(helpers.original, `base64`).toString(`base64`);
244
+ }
245
+ catch (e) {
246
+ throw e;
247
+ }
248
+ })(),
249
+ ]);
250
+ if (asURL.status === `fulfilled`) {
251
+ return asURL.value;
252
+ }
253
+ else if (asBase64.status === `fulfilled`) {
254
+ return asBase64.value;
255
+ }
256
+ return helpers.message({ external: `invalid value, expected URL or Base64 string` });
257
+ });
258
+ }
259
+ break;
260
+ case `date`:
261
+ case `datetime`:
262
+ case `time`:
263
+ if (field.type === `time`) {
264
+ typeSchema = joi_1.default.string();
265
+ }
266
+ else {
267
+ typeSchema = joi_1.default.date().strict(false);
268
+ if (field.min) {
269
+ typeSchema = typeSchema.min(field.min);
270
+ }
271
+ if (field.max) {
272
+ typeSchema = typeSchema.max(field.max);
273
+ }
274
+ }
275
+ typeSchema = typeSchema.external(async (value, helpers) => {
276
+ if (!helpers.original && !field.required) {
277
+ return helpers.original;
278
+ }
279
+ const format = field.type === `date` ? `YYYY-MM-DD` :
280
+ field.type === `time` ? `HH:mmZ` :
281
+ `YYYY-MM-DDTHH:mm:ssZ`;
282
+ const d = (field.type === `datetime` && typeof helpers.original === `number`) ?
283
+ moment_timezone_1.default.unix(helpers.original).tz(`UTC`)
284
+ : moment_timezone_1.default.tz(helpers.original, format, `UTC`);
285
+ if (!d.isValid()) {
286
+ return helpers.message({ external: `invalid format, expected ${format}` });
287
+ }
288
+ const timezone = (field.type === `date` ? `UTC` : field.timezone) || `UTC`;
289
+ return d.tz(timezone).format(format);
290
+ });
291
+ break;
292
+ case `number`:
293
+ typeSchema = joi_1.default.number();
294
+ if (field.min) {
295
+ typeSchema = typeSchema.min(field.min);
296
+ }
297
+ if (field.max) {
298
+ typeSchema = typeSchema.max(field.max);
299
+ }
300
+ if (field.float) {
301
+ typeSchema = typeSchema.precision(field.decimals || 2);
302
+ }
303
+ else {
304
+ typeSchema = typeSchema.precision(0);
305
+ }
306
+ break;
307
+ case `dict`:
308
+ if (field.items) {
309
+ typeSchema = getFieldsSchema(field.items).unknown(field.unknown || false);
310
+ }
311
+ else {
312
+ typeSchema = joi_1.default.object().unknown(true);
313
+ }
314
+ break;
315
+ }
316
+ if (`format` in field && field.format === `select`) {
317
+ if (!field.unknown) {
318
+ if (lodash_1.default.isArray(field.choices)) {
319
+ typeSchema = typeSchema.valid(...field.choices.map((c) => c.value));
320
+ }
321
+ else {
322
+ }
323
+ }
324
+ }
325
+ if (field.as_array) {
326
+ typeSchema = joi_1.default.array().items(typeSchema);
327
+ if (field.array_length) {
328
+ typeSchema = typeSchema.length(field.array_length);
329
+ }
330
+ if (field.array_min) {
331
+ typeSchema = typeSchema.min(field.array_min);
332
+ }
333
+ if (field.array_max) {
334
+ typeSchema = typeSchema.max(field.array_max);
335
+ }
336
+ }
337
+ if (field.disabled) {
338
+ typeSchema = typeSchema.forbidden();
339
+ }
340
+ return field.required ? typeSchema.required() : typeSchema;
341
+ };
342
+ const getFieldsSchema = (fields) => {
343
+ let schema = joi_1.default.object();
344
+ for (const field of fields) {
345
+ const fSchema = getFieldSchema(field);
346
+ schema = schema.concat(joi_1.default.object({ [field.key]: fSchema }));
347
+ }
348
+ return schema;
349
+ };
350
+ const convertPath = (parts) => parts.map((p, i) => typeof p === `string` ? (i === 0 ? p : `.${p}`) : `[${p}]`).join(``);
351
+ const secure = async (field, validation) => field.as_password ? lodash_1.default.omit(validation, [`value`, `original`]) : validation;
352
+ const validate_internal = async (fields, data, options) => {
353
+ try {
354
+ const response = { valid: true, fields: [] };
355
+ const clonedData = lodash_1.default.cloneDeep(data);
356
+ for (const field of lodash_1.default.compact(fields)) {
357
+ if (options.break && !response.valid) {
358
+ break;
359
+ }
360
+ if (field.altered_by?.length > 0) {
361
+ let hide = false;
362
+ for (const alteration of field.altered_by) {
363
+ const matches = (0, where_1.where)(clonedData, [alteration.condition]);
364
+ if (matches) {
365
+ if (`overrides` in alteration) {
366
+ lodash_1.default.assign(field, alteration.overrides);
367
+ }
368
+ else if (`show` in alteration) {
369
+ hide = !alteration.show;
370
+ }
371
+ }
372
+ }
373
+ delete field.altered_by;
374
+ if (hide) {
375
+ continue;
376
+ }
377
+ }
378
+ const value = lodash_1.default.get(clonedData, field.key, field.default);
379
+ const resolved = context_1.default.resolve(value, options.context);
380
+ const schema = getFieldSchema(field);
381
+ let validation;
382
+ let error;
383
+ try {
384
+ validation = await schema.validateAsync(resolved, { abortEarly: false });
385
+ }
386
+ catch (e) {
387
+ error = e;
388
+ }
389
+ let extended;
390
+ if (error) {
391
+ extended = {
392
+ valid: false,
393
+ errors: error.details.map((d) => ({
394
+ type: d.type,
395
+ path: convertPath([field.key, ...d.path]),
396
+ message: d.message,
397
+ })),
398
+ original: value,
399
+ value: null,
400
+ };
401
+ }
402
+ else {
403
+ extended = {
404
+ valid: true,
405
+ original: value,
406
+ value: validation,
407
+ };
408
+ }
409
+ lodash_1.default.set(clonedData, field.key, validation);
410
+ response.valid && (response.valid = error ? false : true);
411
+ response.fields.push({
412
+ ...field,
413
+ ...options.secure ? await secure(field, extended) : extended,
414
+ });
415
+ }
416
+ return response;
417
+ }
418
+ catch (e) {
419
+ throw e;
420
+ }
421
+ };
422
+ const validate = async (fields, data, options = {}) => {
423
+ try {
424
+ const { error } = (0, exports.fieldsSchema)().validate(fields);
425
+ if (error) {
426
+ throw new Error(`Invalid fields definition: ${error.message}`);
427
+ }
428
+ const defaultOptions = lodash_1.default.assign({ secure: true, break: false, context: {} }, options);
429
+ const response = await validate_internal(fields, data, defaultOptions);
430
+ return response;
431
+ }
432
+ catch (e) {
433
+ throw e;
434
+ }
435
+ };
436
+ exports.validate = validate;
437
+ const extract_recursive = async (validation, options, path = ``) => {
438
+ try {
439
+ const response = {};
440
+ for (const field of validation) {
441
+ const key = lodash_1.default.compact([path, field.key]).join(`.`);
442
+ lodash_1.default.set(response, key, options.original ? field.original : field.value);
443
+ }
444
+ return response;
445
+ }
446
+ catch (e) {
447
+ throw e;
448
+ }
449
+ };
450
+ const extract = async (validation, options = {}) => {
451
+ try {
452
+ return await extract_recursive(validation, options);
453
+ }
454
+ catch (e) {
455
+ throw e;
456
+ }
457
+ };
458
+ exports.extract = extract;