@beseif-solutions/prow-core 1.1.0 → 1.2.1
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/core.d.ts +3 -3
- package/dist/index.d.ts +1 -1
- package/dist/minified-utils/fields.d.ts +7 -2
- package/dist/minified-utils/locales.d.ts +2 -0
- package/dist/minified-utils/locales.js +4 -0
- package/dist/minified-utils/validation.d.ts +0 -2
- package/dist/minified-utils/validation.js +11 -33
- package/package.json +1 -1
- package/src/core.ts +3 -3
- package/src/index.ts +1 -1
- package/src/minified-utils/fields.ts +9 -2
- package/src/minified-utils/locales.ts +6 -0
- package/src/minified-utils/validation.ts +15 -71
package/dist/core.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import lodash from "lodash";
|
|
|
4
4
|
import moment from "moment-timezone";
|
|
5
5
|
import { FromCatalog, FromDirectory, T } from "./minified-utils/locales";
|
|
6
6
|
import { SourceConfig } from "./entities/source";
|
|
7
|
-
import { File } from "./minified-utils/fields";
|
|
7
|
+
import { File, RawFile } from "./minified-utils/fields";
|
|
8
8
|
export type SourceFunctions = {
|
|
9
9
|
register: <SC extends SourceConfig = SourceConfig>(source: SC[`id`], sandbox: boolean, data: SC[`fields`]) => Promise<{
|
|
10
10
|
id: string;
|
|
@@ -16,8 +16,8 @@ export type SourceFunctions = {
|
|
|
16
16
|
unregister: <SC extends SourceConfig = SourceConfig>(source: SC[`id`], sandbox: boolean, id: string) => Promise<void>;
|
|
17
17
|
};
|
|
18
18
|
export type StorageFunctions = {
|
|
19
|
-
read: (
|
|
20
|
-
store: (file:
|
|
19
|
+
read: (file: File) => Promise<RawFile>;
|
|
20
|
+
store: (file: RawFile) => Promise<File>;
|
|
21
21
|
};
|
|
22
22
|
export type Core = {
|
|
23
23
|
axios: AxiosInstance;
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export { Action, actionOutputSchema, actionSchema, AsyncAction, Event, eventSche
|
|
|
5
5
|
export { Provider, providerSchema } from './entities/provider';
|
|
6
6
|
export { Source } from './entities/source';
|
|
7
7
|
export { getPath, hasExpression, isDynamic, isExpression, split } from './minified-utils/context';
|
|
8
|
-
export { Condition, Field, File, SelectFieldChoice } from './minified-utils/fields';
|
|
8
|
+
export { Condition, Field, File, RawFile, SelectFieldChoice } from './minified-utils/fields';
|
|
9
9
|
export { DEFAULT_LOCALE, i18n, LocalizedField, LocalizedProperties, localizeFields, localizeGroup, localizeInputs, localizeOutputs, localizeProperties } from './minified-utils/locales';
|
|
10
10
|
export { Properties } from './minified-utils/properties';
|
|
11
11
|
export { alter, extract, fieldSchema, fieldsSchema, validate, ValidationOptions, ValidationResult } from './minified-utils/validation';
|
|
@@ -82,14 +82,19 @@ export type DictInputField<Extend = Record<never, never>> = {
|
|
|
82
82
|
items?: Field<Extend>[];
|
|
83
83
|
unknown?: boolean;
|
|
84
84
|
};
|
|
85
|
-
export type
|
|
85
|
+
export type RawFile = {
|
|
86
86
|
name: string;
|
|
87
87
|
type: string;
|
|
88
88
|
content: string;
|
|
89
89
|
};
|
|
90
|
+
export type File = {
|
|
91
|
+
name: string;
|
|
92
|
+
type: string;
|
|
93
|
+
id: string;
|
|
94
|
+
};
|
|
90
95
|
export type FileInputField<Extend = Record<never, never>> = {
|
|
91
96
|
type: `file`;
|
|
92
|
-
default?:
|
|
97
|
+
default?: never;
|
|
93
98
|
accept?: string | string[];
|
|
94
99
|
} & (SelectField<File, Extend> | {});
|
|
95
100
|
export type SelectField<Values = string | number | boolean | File, Extend = Record<never, never>> = {
|
|
@@ -7,12 +7,14 @@ import { Source } from '../entities/source';
|
|
|
7
7
|
export type LocalizedField = {
|
|
8
8
|
label: string;
|
|
9
9
|
help: string;
|
|
10
|
+
instructions?: string;
|
|
10
11
|
ui?: Record<string, any>;
|
|
11
12
|
};
|
|
12
13
|
export type LocalizedProperties = {
|
|
13
14
|
name: string;
|
|
14
15
|
description: string;
|
|
15
16
|
help?: Record<string, string>;
|
|
17
|
+
instructions?: string;
|
|
16
18
|
};
|
|
17
19
|
type TOptions = {
|
|
18
20
|
fallback?: boolean;
|
|
@@ -98,6 +98,7 @@ const localizeField = (t, element, field, recursive = {}) => {
|
|
|
98
98
|
const root = field.t || recursive.t || `${element}.fields`;
|
|
99
99
|
field.label = t(`${root}.${key}.label`, { fallback: true });
|
|
100
100
|
field.help = t(`${root}.${key}.help`);
|
|
101
|
+
field.instructions = t(`${root}.${key}.instructions`, { fallback: true, optional: true });
|
|
101
102
|
field.ui = t(`${root}.${key}.ui`, { fallback: true, optional: true }) || {};
|
|
102
103
|
if (field.type === `dict` && field.items) {
|
|
103
104
|
field.items = field.items.map((f) => localizeField(t, element, f, { parent: `${key}.items`, t: field.t }));
|
|
@@ -107,6 +108,7 @@ const localizeField = (t, element, field, recursive = {}) => {
|
|
|
107
108
|
...fc,
|
|
108
109
|
label: t(`${root}.${key}.choices.${fc.key}.label`, { fallback: true }),
|
|
109
110
|
help: t(`${root}.${key}.choices.${fc.key}.help`),
|
|
111
|
+
instructions: t(`${root}.${key}.choices.${fc.key}.instructions`, { fallback: true, optional: true }),
|
|
110
112
|
ui: {
|
|
111
113
|
...t(`${root}.${key}.choices.${fc.key}.ui`, { fallback: true, optional: true }) || {},
|
|
112
114
|
...fc.group && {
|
|
@@ -131,10 +133,12 @@ const localizeFields = (t, element) => {
|
|
|
131
133
|
exports.localizeFields = localizeFields;
|
|
132
134
|
const localizeProperties = (t, element) => {
|
|
133
135
|
const help = t(`${element.id}.help`, { fallback: true, optional: true });
|
|
136
|
+
const instructions = t(`${element.id}.instructions`, { fallback: true, optional: true });
|
|
134
137
|
return {
|
|
135
138
|
name: t(`${element.id}.name`, { fallback: true }),
|
|
136
139
|
description: t(`${element.id}.description`),
|
|
137
140
|
...help && { help: help },
|
|
141
|
+
...instructions && { instructions: instructions },
|
|
138
142
|
};
|
|
139
143
|
};
|
|
140
144
|
exports.localizeProperties = localizeProperties;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import Joi from "joi";
|
|
2
2
|
import { Field } from "./fields";
|
|
3
|
-
import { StorageFunctions } from "../core";
|
|
4
3
|
type ValidationExtended = {
|
|
5
4
|
original: any;
|
|
6
5
|
value: any;
|
|
@@ -17,7 +16,6 @@ type ValidationExtended = {
|
|
|
17
16
|
export declare const fieldSchema: () => Joi.ObjectSchema<any>;
|
|
18
17
|
export declare const fieldsSchema: () => Joi.ArraySchema<any[]>;
|
|
19
18
|
export type ValidationOptions = {
|
|
20
|
-
files: StorageFunctions;
|
|
21
19
|
secure?: boolean;
|
|
22
20
|
break?: boolean;
|
|
23
21
|
context?: Record<string, any>;
|
|
@@ -4,7 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.extract = exports.validate = exports.alter = exports.fieldsSchema = exports.fieldSchema = void 0;
|
|
7
|
-
const axios_1 = __importDefault(require("axios"));
|
|
8
7
|
const joi_1 = __importDefault(require("joi"));
|
|
9
8
|
const lodash_1 = __importDefault(require("lodash"));
|
|
10
9
|
const moment_timezone_1 = __importDefault(require("moment-timezone"));
|
|
@@ -164,10 +163,9 @@ const dictInputFieldSchema = () => joi_1.default.object({
|
|
|
164
163
|
const fileSchema = () => joi_1.default.object({
|
|
165
164
|
name: joi_1.default.string().required(),
|
|
166
165
|
type: joi_1.default.string().required(),
|
|
167
|
-
|
|
166
|
+
id: joi_1.default.string().required(),
|
|
168
167
|
});
|
|
169
168
|
const fileInputFieldSchema = () => joi_1.default.object({
|
|
170
|
-
default: defaultSchema(fileSchema()),
|
|
171
169
|
accept: joi_1.default.alternatives(joi_1.default.string(), joi_1.default.array().items(joi_1.default.string())).optional(),
|
|
172
170
|
})
|
|
173
171
|
.concat(joi_1.default.object({
|
|
@@ -218,7 +216,7 @@ const fieldSchema = () => inputFieldBaseSchema()
|
|
|
218
216
|
exports.fieldSchema = fieldSchema;
|
|
219
217
|
const fieldsSchema = () => joi_1.default.array().items((0, exports.fieldSchema)());
|
|
220
218
|
exports.fieldsSchema = fieldsSchema;
|
|
221
|
-
const getSimpleFieldSchema = (field
|
|
219
|
+
const getSimpleFieldSchema = (field) => {
|
|
222
220
|
if (field.as_array) {
|
|
223
221
|
throw new Error(`Cannot use as_array with simple field schema generator`);
|
|
224
222
|
}
|
|
@@ -310,26 +308,7 @@ const getSimpleFieldSchema = (field, configuration) => {
|
|
|
310
308
|
typeSchema = joi_1.default.object().unknown(true);
|
|
311
309
|
break;
|
|
312
310
|
case `file`:
|
|
313
|
-
typeSchema = fileSchema()
|
|
314
|
-
.external(async (value) => {
|
|
315
|
-
if (value.content.startsWith(`http://`) || value.content.startsWith(`https://`)) {
|
|
316
|
-
try {
|
|
317
|
-
const { data: content } = await axios_1.default.get(value.content, { responseType: `arraybuffer` });
|
|
318
|
-
value.content = Buffer.from(content).toString(`base64`);
|
|
319
|
-
}
|
|
320
|
-
catch (e) {
|
|
321
|
-
console.log(e);
|
|
322
|
-
throw new Error(`Could not fetch file from URL`);
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
else if (value.content.startsWith(`id:`)) {
|
|
326
|
-
const id = value.content.replace(`id:`, ``);
|
|
327
|
-
value.content = await configuration.files.read(id);
|
|
328
|
-
}
|
|
329
|
-
else {
|
|
330
|
-
}
|
|
331
|
-
return value;
|
|
332
|
-
});
|
|
311
|
+
typeSchema = fileSchema();
|
|
333
312
|
break;
|
|
334
313
|
}
|
|
335
314
|
if (`format` in field && field.format === `select`) {
|
|
@@ -441,7 +420,6 @@ const recursive_schema = async (field, data, options) => {
|
|
|
441
420
|
return;
|
|
442
421
|
}
|
|
443
422
|
}
|
|
444
|
-
const alteredField = lodash_1.default.cloneDeep(newField);
|
|
445
423
|
const relativeKey = options.relative ?
|
|
446
424
|
options.relative.endsWith(`]`) ?
|
|
447
425
|
options.array ? options.relative : `${options.relative}.${newField.key}`
|
|
@@ -467,7 +445,7 @@ const recursive_schema = async (field, data, options) => {
|
|
|
467
445
|
const itemSchemas = [];
|
|
468
446
|
if (lodash_1.default.isArray(resolved)) {
|
|
469
447
|
for (let i = 0; i < (resolved || []).length; i++) {
|
|
470
|
-
const { schema: itemSchema } = await recursive_schema(noArrayField, data, {
|
|
448
|
+
const { schema: itemSchema } = await recursive_schema(noArrayField, data, { alter: false, relative: `${relativeKey}[${i}]`, array: true, context: options.context });
|
|
471
449
|
if (itemSchema) {
|
|
472
450
|
itemSchemas.push(itemSchema);
|
|
473
451
|
}
|
|
@@ -482,7 +460,7 @@ const recursive_schema = async (field, data, options) => {
|
|
|
482
460
|
if (noArrayField.type === `dict` && noArrayField.items) {
|
|
483
461
|
const items = [];
|
|
484
462
|
for (const item of noArrayField.items) {
|
|
485
|
-
const recursive = await recursive_schema(item, data, {
|
|
463
|
+
const recursive = await recursive_schema(item, data, { alter: options.alter && true, relative: `${relativeKey}[0]`, context: options.context, no_undefined: true });
|
|
486
464
|
if (recursive) {
|
|
487
465
|
items.push({ key: item.key, schema: recursive.schema, field: recursive.field });
|
|
488
466
|
}
|
|
@@ -491,7 +469,7 @@ const recursive_schema = async (field, data, options) => {
|
|
|
491
469
|
noArrayField.items = items.map((i) => i.field);
|
|
492
470
|
}
|
|
493
471
|
else {
|
|
494
|
-
genericItemSchema = getSimpleFieldSchema(noArrayField
|
|
472
|
+
genericItemSchema = getSimpleFieldSchema(noArrayField);
|
|
495
473
|
}
|
|
496
474
|
calculatedSchema = getItemsArrayFieldSchema(newField, [genericItemSchema]);
|
|
497
475
|
}
|
|
@@ -500,7 +478,7 @@ const recursive_schema = async (field, data, options) => {
|
|
|
500
478
|
if (resolved || newField.required) {
|
|
501
479
|
const items = [];
|
|
502
480
|
for (const item of newField.items) {
|
|
503
|
-
const recursive = await recursive_schema(item, data, {
|
|
481
|
+
const recursive = await recursive_schema(item, data, { alter: options.alter && true, relative: relativeKey, context: options.context });
|
|
504
482
|
if (recursive) {
|
|
505
483
|
items.push({ key: item.key, schema: recursive.schema, field: recursive.field });
|
|
506
484
|
}
|
|
@@ -510,11 +488,11 @@ const recursive_schema = async (field, data, options) => {
|
|
|
510
488
|
}
|
|
511
489
|
else {
|
|
512
490
|
delete newField.items;
|
|
513
|
-
calculatedSchema = getSimpleFieldSchema(newField
|
|
491
|
+
calculatedSchema = getSimpleFieldSchema(newField);
|
|
514
492
|
}
|
|
515
493
|
}
|
|
516
494
|
else {
|
|
517
|
-
calculatedSchema = getSimpleFieldSchema(newField
|
|
495
|
+
calculatedSchema = getSimpleFieldSchema(newField);
|
|
518
496
|
}
|
|
519
497
|
if (!calculatedSchema) {
|
|
520
498
|
throw new Error(`Could not resolve schema for field ${newField.key}`);
|
|
@@ -522,7 +500,7 @@ const recursive_schema = async (field, data, options) => {
|
|
|
522
500
|
if (newField.disabled) {
|
|
523
501
|
lodash_1.default.unset(data, relativeKey);
|
|
524
502
|
}
|
|
525
|
-
return { schema: calculatedSchema, field:
|
|
503
|
+
return { schema: calculatedSchema, field: newField };
|
|
526
504
|
}
|
|
527
505
|
catch (e) {
|
|
528
506
|
throw e;
|
|
@@ -534,7 +512,7 @@ const validate_internal = async (fields, data, options) => {
|
|
|
534
512
|
for (const field of fields) {
|
|
535
513
|
const value = lodash_1.default.get(data, field.key, field.default);
|
|
536
514
|
const cloned = lodash_1.default.cloneDeep(data);
|
|
537
|
-
const recursive = await recursive_schema(field, cloned, {
|
|
515
|
+
const recursive = await recursive_schema(field, cloned, { alter: true, context: options.context });
|
|
538
516
|
if (!recursive) {
|
|
539
517
|
continue;
|
|
540
518
|
}
|
package/package.json
CHANGED
package/src/core.ts
CHANGED
|
@@ -4,7 +4,7 @@ import lodash from "lodash";
|
|
|
4
4
|
import moment from "moment-timezone";
|
|
5
5
|
import { FromCatalog, FromDirectory, i18n, T } from "./minified-utils/locales";
|
|
6
6
|
import { SourceConfig } from "./entities/source";
|
|
7
|
-
import { File } from "./minified-utils/fields";
|
|
7
|
+
import { File, RawFile } from "./minified-utils/fields";
|
|
8
8
|
|
|
9
9
|
export type SourceFunctions = {
|
|
10
10
|
register: <SC extends SourceConfig = SourceConfig>(source: SC[`id`], sandbox: boolean, data: SC[`fields`]) => Promise<{ id: string }>,
|
|
@@ -13,8 +13,8 @@ export type SourceFunctions = {
|
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
export type StorageFunctions = {
|
|
16
|
-
read: (
|
|
17
|
-
store: (file:
|
|
16
|
+
read: (file: File) => Promise<RawFile>,
|
|
17
|
+
store: (file: RawFile) => Promise<File>,
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
const FALLBACK_SOURCES: SourceFunctions = {
|
package/src/index.ts
CHANGED
|
@@ -5,7 +5,7 @@ export { Action, actionOutputSchema, actionSchema, AsyncAction, Event, eventSche
|
|
|
5
5
|
export { Provider, providerSchema } from './entities/provider';
|
|
6
6
|
export { Source } from './entities/source';
|
|
7
7
|
export { getPath, hasExpression, isDynamic, isExpression, split } from './minified-utils/context';
|
|
8
|
-
export { Condition, Field, File, SelectFieldChoice } from './minified-utils/fields';
|
|
8
|
+
export { Condition, Field, File, RawFile, SelectFieldChoice } from './minified-utils/fields';
|
|
9
9
|
export { DEFAULT_LOCALE, i18n, LocalizedField, LocalizedProperties, localizeFields, localizeGroup, localizeInputs, localizeOutputs, localizeProperties } from './minified-utils/locales';
|
|
10
10
|
export { Properties } from './minified-utils/properties';
|
|
11
11
|
export { alter, extract, fieldSchema, fieldsSchema, validate, ValidationOptions, ValidationResult } from './minified-utils/validation';
|
|
@@ -126,15 +126,22 @@ export type DictInputField<Extend = Record<never, never>> = {
|
|
|
126
126
|
unknown?: boolean,
|
|
127
127
|
};
|
|
128
128
|
|
|
129
|
+
export type RawFile = {
|
|
130
|
+
name: string,
|
|
131
|
+
type: string,
|
|
132
|
+
content: string,
|
|
133
|
+
};
|
|
134
|
+
|
|
129
135
|
export type File = {
|
|
130
136
|
name: string,
|
|
131
137
|
type: string,
|
|
132
|
-
|
|
138
|
+
id: string,
|
|
133
139
|
};
|
|
134
140
|
|
|
141
|
+
|
|
135
142
|
export type FileInputField<Extend = Record<never, never>> = {
|
|
136
143
|
type: `file`,
|
|
137
|
-
default?:
|
|
144
|
+
default?: never,
|
|
138
145
|
accept?: string | string[], // mime type
|
|
139
146
|
} & (
|
|
140
147
|
| SelectField<File, Extend>
|
|
@@ -11,6 +11,7 @@ import { Source } from '../entities/source';
|
|
|
11
11
|
export type LocalizedField = {
|
|
12
12
|
label: string,
|
|
13
13
|
help: string,
|
|
14
|
+
instructions?: string,
|
|
14
15
|
ui?: Record<string, any>,
|
|
15
16
|
};
|
|
16
17
|
|
|
@@ -18,6 +19,7 @@ export type LocalizedProperties = {
|
|
|
18
19
|
name: string,
|
|
19
20
|
description: string,
|
|
20
21
|
help?: Record<string, string>,
|
|
22
|
+
instructions?: string,
|
|
21
23
|
};
|
|
22
24
|
|
|
23
25
|
type TOptions = { fallback?: boolean, optional?: boolean };
|
|
@@ -143,6 +145,7 @@ const localizeField = (
|
|
|
143
145
|
|
|
144
146
|
field.label = t(`${root}.${key}.label`, { fallback: true });
|
|
145
147
|
field.help = t(`${root}.${key}.help`);
|
|
148
|
+
field.instructions = t(`${root}.${key}.instructions`, { fallback: true, optional: true });
|
|
146
149
|
field.ui = t(`${root}.${key}.ui`, { fallback: true, optional: true }) || {};
|
|
147
150
|
|
|
148
151
|
if (field.type === `dict` && field.items) {
|
|
@@ -152,6 +155,7 @@ const localizeField = (
|
|
|
152
155
|
...fc,
|
|
153
156
|
label: t(`${root}.${key}.choices.${fc.key}.label`, { fallback: true }),
|
|
154
157
|
help: t(`${root}.${key}.choices.${fc.key}.help`),
|
|
158
|
+
instructions: t(`${root}.${key}.choices.${fc.key}.instructions`, { fallback: true, optional: true }),
|
|
155
159
|
ui: {
|
|
156
160
|
...t(`${root}.${key}.choices.${fc.key}.ui`, { fallback: true, optional: true }) || {},
|
|
157
161
|
...fc.group && {
|
|
@@ -184,10 +188,12 @@ export const localizeProperties = (
|
|
|
184
188
|
element: Action | Trigger | Credentials | Provider | Source,
|
|
185
189
|
): LocalizedProperties => {
|
|
186
190
|
const help = t<Record<string, any>>(`${element.id}.help`, { fallback: true, optional: true });
|
|
191
|
+
const instructions = t<string>(`${element.id}.instructions`, { fallback: true, optional: true });
|
|
187
192
|
return {
|
|
188
193
|
name: t(`${element.id}.name`, { fallback: true }),
|
|
189
194
|
description: t(`${element.id}.description`),
|
|
190
195
|
...help && { help: help },
|
|
196
|
+
...instructions && { instructions: instructions },
|
|
191
197
|
};
|
|
192
198
|
};
|
|
193
199
|
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import axios from "axios";
|
|
2
1
|
import Joi, { DateSchema, NumberSchema, StringSchema } from "joi";
|
|
3
2
|
import _ from "lodash";
|
|
4
3
|
import moment from "moment-timezone";
|
|
5
4
|
import context from "./context";
|
|
6
|
-
import { Field,
|
|
5
|
+
import { Field, SelectFieldChoice } from "./fields";
|
|
7
6
|
import { where, Where } from "./where";
|
|
8
|
-
import { StorageFunctions } from "../core";
|
|
9
7
|
|
|
10
8
|
type ValidationExtended = {
|
|
11
9
|
original: any,
|
|
@@ -217,39 +215,12 @@ const dictInputFieldSchema = () =>
|
|
|
217
215
|
const fileSchema = () => Joi.object({
|
|
218
216
|
name: Joi.string().required(),
|
|
219
217
|
type: Joi.string().required(), // mime type
|
|
220
|
-
|
|
218
|
+
id: Joi.string().required(), // file id - not validated
|
|
221
219
|
});
|
|
222
220
|
|
|
223
|
-
// // ÑAPA: translate file to structured dict
|
|
224
|
-
// const fileReplacer = (field: CommonField & FileInputField): Field => ({
|
|
225
|
-
// key: field.key,
|
|
226
|
-
// type: `dict`,
|
|
227
|
-
// unknown: true,
|
|
228
|
-
// items: [
|
|
229
|
-
// {
|
|
230
|
-
// key: `name`,
|
|
231
|
-
// type: `string`,
|
|
232
|
-
// required: true,
|
|
233
|
-
// },
|
|
234
|
-
// {
|
|
235
|
-
// key: `type`,
|
|
236
|
-
// type: `string`,
|
|
237
|
-
// required: true,
|
|
238
|
-
// },
|
|
239
|
-
// {
|
|
240
|
-
// key: `content`,
|
|
241
|
-
// type: `string`,
|
|
242
|
-
// required: true,
|
|
243
|
-
// },
|
|
244
|
-
// ],
|
|
245
|
-
// default: field.default,
|
|
246
|
-
// ..._.pick(field, [`altered_by`, `disabled`, `required`, `as_password`, `show`, `as_array`, `array_min`, `array_max`, `array_length`]),
|
|
247
|
-
// ...Object.assign({}, ...Object.entries(field).map(([k, v]) => k.startsWith(`experimental_`) ? { [k]: v } : {})),
|
|
248
|
-
// }) as Field;
|
|
249
|
-
|
|
250
221
|
const fileInputFieldSchema = () =>
|
|
251
222
|
Joi.object({
|
|
252
|
-
default: defaultSchema(fileSchema()),
|
|
223
|
+
// default: defaultSchema(fileSchema()),
|
|
253
224
|
accept: Joi.alternatives(
|
|
254
225
|
Joi.string(),
|
|
255
226
|
Joi.array().items(Joi.string())
|
|
@@ -309,7 +280,7 @@ export const fieldSchema = () =>
|
|
|
309
280
|
export const fieldsSchema = () =>
|
|
310
281
|
Joi.array().items(fieldSchema());
|
|
311
282
|
|
|
312
|
-
const getSimpleFieldSchema = (field: Field
|
|
283
|
+
const getSimpleFieldSchema = (field: Field) => {
|
|
313
284
|
if (field.as_array) { throw new Error(`Cannot use as_array with simple field schema generator`); }
|
|
314
285
|
|
|
315
286
|
let typeSchema: Joi.Schema;
|
|
@@ -380,28 +351,7 @@ const getSimpleFieldSchema = (field: Field, configuration: { files: StorageFunct
|
|
|
380
351
|
typeSchema = Joi.object().unknown(true);
|
|
381
352
|
break;
|
|
382
353
|
case `file`:
|
|
383
|
-
typeSchema = fileSchema()
|
|
384
|
-
.external(async (value: File) => {
|
|
385
|
-
if (value.content.startsWith(`http://`) || value.content.startsWith(`https://`)) {
|
|
386
|
-
try {
|
|
387
|
-
// get content from public URL
|
|
388
|
-
const { data: content } = await axios.get(value.content, { responseType: `arraybuffer` });
|
|
389
|
-
// content to base64
|
|
390
|
-
value.content = Buffer.from(content).toString(`base64`);
|
|
391
|
-
} catch (e) {
|
|
392
|
-
console.log(e);
|
|
393
|
-
throw new Error(`Could not fetch file from URL`);
|
|
394
|
-
}
|
|
395
|
-
} else if (value.content.startsWith(`id:`)) {
|
|
396
|
-
const id = value.content.replace(`id:`, ``);
|
|
397
|
-
// get content from internal storage
|
|
398
|
-
value.content = await configuration.files.read(id);
|
|
399
|
-
} else {
|
|
400
|
-
// content as base64
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
return value;
|
|
404
|
-
});
|
|
354
|
+
typeSchema = fileSchema();
|
|
405
355
|
break;
|
|
406
356
|
}
|
|
407
357
|
|
|
@@ -471,7 +421,6 @@ const secure = async (field: Field, validation: ValidationExtended): Promise<Val
|
|
|
471
421
|
field.as_password ? _.omit(validation, [`value`, `original`]) as any : validation;
|
|
472
422
|
|
|
473
423
|
export type ValidationOptions = {
|
|
474
|
-
files: StorageFunctions,
|
|
475
424
|
secure?: boolean,
|
|
476
425
|
break?: boolean,
|
|
477
426
|
context?: Record<string, any>,
|
|
@@ -508,7 +457,7 @@ export const alter = (field: Field, relative: string, data: Record<string, any>)
|
|
|
508
457
|
return cloned;
|
|
509
458
|
};
|
|
510
459
|
|
|
511
|
-
const recursive_schema = async (field: Field, data: Record<string, any>, options: {
|
|
460
|
+
const recursive_schema = async (field: Field, data: Record<string, any>, options: { alter: boolean, context: Record<string, any>, relative?: string, array?: boolean, no_undefined?: boolean }): Promise<{ schema: Joi.Schema, field: Field }> => {
|
|
512
461
|
try {
|
|
513
462
|
let newField: Field = _.cloneDeep(field);
|
|
514
463
|
|
|
@@ -522,11 +471,6 @@ const recursive_schema = async (field: Field, data: Record<string, any>, options
|
|
|
522
471
|
if (typeof newField.show === `boolean` && !newField.show) { return; }
|
|
523
472
|
}
|
|
524
473
|
|
|
525
|
-
const alteredField: Field = _.cloneDeep(newField);
|
|
526
|
-
|
|
527
|
-
// ÑAPA: if the field is a file, replace it
|
|
528
|
-
// if (newField.type === `file`) { newField = fileReplacer(newField); }
|
|
529
|
-
|
|
530
474
|
const relativeKey = options.relative ?
|
|
531
475
|
options.relative.endsWith(`]`) ?
|
|
532
476
|
options.array ? options.relative : `${options.relative}.${newField.key}`
|
|
@@ -558,7 +502,7 @@ const recursive_schema = async (field: Field, data: Record<string, any>, options
|
|
|
558
502
|
const itemSchemas: Joi.Schema[] = [];
|
|
559
503
|
if (_.isArray(resolved)) {
|
|
560
504
|
for (let i = 0; i < (resolved || []).length; i++) {
|
|
561
|
-
const { schema: itemSchema } = await recursive_schema(noArrayField, data, {
|
|
505
|
+
const { schema: itemSchema } = await recursive_schema(noArrayField, data, { alter: false, relative: `${relativeKey}[${i}]`, array: true, context: options.context });
|
|
562
506
|
if (itemSchema) { itemSchemas.push(itemSchema); }
|
|
563
507
|
}
|
|
564
508
|
|
|
@@ -574,14 +518,14 @@ const recursive_schema = async (field: Field, data: Record<string, any>, options
|
|
|
574
518
|
const items: { key: string, schema: Joi.Schema, field: Field }[] = [];
|
|
575
519
|
|
|
576
520
|
for (const item of noArrayField.items) {
|
|
577
|
-
const recursive = await recursive_schema(item, data, {
|
|
521
|
+
const recursive = await recursive_schema(item, data, { alter: options.alter && true, relative: `${relativeKey}[0]`, context: options.context, no_undefined: true });
|
|
578
522
|
if (recursive) { items.push({ key: item.key, schema: recursive.schema, field: recursive.field }); }
|
|
579
523
|
}
|
|
580
524
|
|
|
581
525
|
genericItemSchema = getObjectFieldSchema(noArrayField, items);
|
|
582
526
|
noArrayField.items = items.map((i) => i.field);
|
|
583
527
|
} else {
|
|
584
|
-
genericItemSchema = getSimpleFieldSchema(noArrayField
|
|
528
|
+
genericItemSchema = getSimpleFieldSchema(noArrayField);
|
|
585
529
|
}
|
|
586
530
|
|
|
587
531
|
calculatedSchema = getItemsArrayFieldSchema(newField, [genericItemSchema]);
|
|
@@ -591,7 +535,7 @@ const recursive_schema = async (field: Field, data: Record<string, any>, options
|
|
|
591
535
|
const items: { key: string, schema: Joi.Schema, field: Field }[] = [];
|
|
592
536
|
|
|
593
537
|
for (const item of newField.items) {
|
|
594
|
-
const recursive = await recursive_schema(item, data, {
|
|
538
|
+
const recursive = await recursive_schema(item, data, { alter: options.alter && true, relative: relativeKey, context: options.context });
|
|
595
539
|
if (recursive) { items.push({ key: item.key, schema: recursive.schema, field: recursive.field }); }
|
|
596
540
|
}
|
|
597
541
|
|
|
@@ -599,10 +543,10 @@ const recursive_schema = async (field: Field, data: Record<string, any>, options
|
|
|
599
543
|
newField.items = items.map((i) => i.field);
|
|
600
544
|
} else {
|
|
601
545
|
delete newField.items;
|
|
602
|
-
calculatedSchema = getSimpleFieldSchema(newField
|
|
546
|
+
calculatedSchema = getSimpleFieldSchema(newField);
|
|
603
547
|
}
|
|
604
548
|
} else {
|
|
605
|
-
calculatedSchema = getSimpleFieldSchema(newField
|
|
549
|
+
calculatedSchema = getSimpleFieldSchema(newField);
|
|
606
550
|
}
|
|
607
551
|
|
|
608
552
|
if (!calculatedSchema) { throw new Error(`Could not resolve schema for field ${newField.key}`); }
|
|
@@ -610,11 +554,11 @@ const recursive_schema = async (field: Field, data: Record<string, any>, options
|
|
|
610
554
|
// if disabled schema validation is done but the value is not set
|
|
611
555
|
if (newField.disabled) { _.unset(data, relativeKey); }
|
|
612
556
|
|
|
613
|
-
return { schema: calculatedSchema, field:
|
|
557
|
+
return { schema: calculatedSchema, field: newField };
|
|
614
558
|
} catch (e) { throw e; }
|
|
615
559
|
};
|
|
616
560
|
|
|
617
|
-
const validate_internal = async (fields: Field[], data: Record<string, any>, options: {
|
|
561
|
+
const validate_internal = async (fields: Field[], data: Record<string, any>, options: { secure: boolean, break: boolean, context: Record<string, any> }): Promise<ValidationResult> => {
|
|
618
562
|
try {
|
|
619
563
|
const response: ValidationResult<{}> = { valid: true, fields: [] };
|
|
620
564
|
|
|
@@ -624,7 +568,7 @@ const validate_internal = async (fields: Field[], data: Record<string, any>, opt
|
|
|
624
568
|
|
|
625
569
|
const cloned = _.cloneDeep(data);
|
|
626
570
|
|
|
627
|
-
const recursive = await recursive_schema(field, cloned, {
|
|
571
|
+
const recursive = await recursive_schema(field, cloned, { alter: true, context: options.context });
|
|
628
572
|
if (!recursive) { continue; }
|
|
629
573
|
|
|
630
574
|
const resolved = _.get(cloned, field.key, field.default);
|