@beseif-solutions/prow-core 1.0.6 → 1.1.0
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 +8 -1
- package/dist/core.js +1 -0
- package/dist/index.d.ts +2 -3
- package/dist/index.js +7 -9
- package/dist/minified-utils/context.js +4 -2
- package/dist/minified-utils/validation.d.ts +8 -5
- package/dist/minified-utils/validation.js +30 -38
- package/package.json +1 -1
- package/src/core.ts +10 -1
- package/src/index.ts +2 -3
- package/src/minified-utils/context.ts +4 -2
- package/src/minified-utils/validation.ts +70 -40
- package/dist/minified-utils/protocol.d.ts +0 -52
- package/dist/minified-utils/protocol.js +0 -187
- package/src/minified-utils/protocol.ts +0 -244
package/dist/core.d.ts
CHANGED
|
@@ -4,6 +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
8
|
export type SourceFunctions = {
|
|
8
9
|
register: <SC extends SourceConfig = SourceConfig>(source: SC[`id`], sandbox: boolean, data: SC[`fields`]) => Promise<{
|
|
9
10
|
id: string;
|
|
@@ -14,6 +15,10 @@ export type SourceFunctions = {
|
|
|
14
15
|
}[]>;
|
|
15
16
|
unregister: <SC extends SourceConfig = SourceConfig>(source: SC[`id`], sandbox: boolean, id: string) => Promise<void>;
|
|
16
17
|
};
|
|
18
|
+
export type StorageFunctions = {
|
|
19
|
+
read: (id: string) => Promise<string>;
|
|
20
|
+
store: (file: File) => Promise<File>;
|
|
21
|
+
};
|
|
17
22
|
export type Core = {
|
|
18
23
|
axios: AxiosInstance;
|
|
19
24
|
moment: typeof moment;
|
|
@@ -22,11 +27,13 @@ export type Core = {
|
|
|
22
27
|
joi: Joi.Root;
|
|
23
28
|
sources?: SourceFunctions;
|
|
24
29
|
t: T;
|
|
30
|
+
files: StorageFunctions;
|
|
25
31
|
};
|
|
26
32
|
type CoreOptions = {
|
|
33
|
+
localization: FromDirectory | FromCatalog;
|
|
34
|
+
files: StorageFunctions;
|
|
27
35
|
env?: Record<string, any>;
|
|
28
36
|
sources?: SourceFunctions;
|
|
29
|
-
localization: FromDirectory | FromCatalog;
|
|
30
37
|
};
|
|
31
38
|
export declare const core: (options: CoreOptions) => Promise<Core>;
|
|
32
39
|
export {};
|
package/dist/core.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
export { Core, core } from './core';
|
|
1
|
+
export { Core, core, SourceFunctions, StorageFunctions } from './core';
|
|
2
2
|
export { CoreFunction, idSchema } from './entities/commons';
|
|
3
3
|
export { Credentials, credentialsSchema, OAuthCredentials, oauthCredentialsSchema, SessionCredentials, sessionCredentialsSchema, StaticCredentials, staticCredentialsSchema } from './entities/credentials';
|
|
4
4
|
export { Action, actionOutputSchema, actionSchema, AsyncAction, Event, eventSchema, ImmediateTrigger, immediateTriggerSchema, Request, ScheduledTrigger, scheduledTriggerSchema, SyncAction, syncActionSchema, Trigger, triggerOutputSchema, triggerSchema } from './entities/events';
|
|
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 { alter, extract, fieldSchema, fieldsSchema, validate, ValidationResult } from './minified-utils/validation';
|
|
9
8
|
export { Condition, Field, File, SelectFieldChoice } from './minified-utils/fields';
|
|
10
9
|
export { DEFAULT_LOCALE, i18n, LocalizedField, LocalizedProperties, localizeFields, localizeGroup, localizeInputs, localizeOutputs, localizeProperties } from './minified-utils/locales';
|
|
11
10
|
export { Properties } from './minified-utils/properties';
|
|
12
|
-
export {
|
|
11
|
+
export { alter, extract, fieldSchema, fieldsSchema, validate, ValidationOptions, ValidationResult } from './minified-utils/validation';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.validate = exports.fieldsSchema = exports.fieldSchema = exports.extract = exports.alter = exports.Properties = exports.localizeProperties = exports.localizeOutputs = exports.localizeInputs = exports.localizeGroup = exports.localizeFields = exports.i18n = exports.DEFAULT_LOCALE = exports.split = exports.isExpression = exports.isDynamic = exports.hasExpression = exports.getPath = exports.providerSchema = exports.triggerSchema = exports.triggerOutputSchema = exports.syncActionSchema = exports.scheduledTriggerSchema = exports.immediateTriggerSchema = exports.eventSchema = exports.actionSchema = exports.actionOutputSchema = exports.staticCredentialsSchema = exports.sessionCredentialsSchema = exports.oauthCredentialsSchema = exports.credentialsSchema = exports.idSchema = exports.core = void 0;
|
|
4
4
|
var core_1 = require("./core");
|
|
5
5
|
Object.defineProperty(exports, "core", { enumerable: true, get: function () { return core_1.core; } });
|
|
6
6
|
var commons_1 = require("./entities/commons");
|
|
@@ -27,12 +27,6 @@ Object.defineProperty(exports, "hasExpression", { enumerable: true, get: functio
|
|
|
27
27
|
Object.defineProperty(exports, "isDynamic", { enumerable: true, get: function () { return context_1.isDynamic; } });
|
|
28
28
|
Object.defineProperty(exports, "isExpression", { enumerable: true, get: function () { return context_1.isExpression; } });
|
|
29
29
|
Object.defineProperty(exports, "split", { enumerable: true, get: function () { return context_1.split; } });
|
|
30
|
-
var validation_1 = require("./minified-utils/validation");
|
|
31
|
-
Object.defineProperty(exports, "alter", { enumerable: true, get: function () { return validation_1.alter; } });
|
|
32
|
-
Object.defineProperty(exports, "extract", { enumerable: true, get: function () { return validation_1.extract; } });
|
|
33
|
-
Object.defineProperty(exports, "fieldSchema", { enumerable: true, get: function () { return validation_1.fieldSchema; } });
|
|
34
|
-
Object.defineProperty(exports, "fieldsSchema", { enumerable: true, get: function () { return validation_1.fieldsSchema; } });
|
|
35
|
-
Object.defineProperty(exports, "validate", { enumerable: true, get: function () { return validation_1.validate; } });
|
|
36
30
|
var locales_1 = require("./minified-utils/locales");
|
|
37
31
|
Object.defineProperty(exports, "DEFAULT_LOCALE", { enumerable: true, get: function () { return locales_1.DEFAULT_LOCALE; } });
|
|
38
32
|
Object.defineProperty(exports, "i18n", { enumerable: true, get: function () { return locales_1.i18n; } });
|
|
@@ -43,5 +37,9 @@ Object.defineProperty(exports, "localizeOutputs", { enumerable: true, get: funct
|
|
|
43
37
|
Object.defineProperty(exports, "localizeProperties", { enumerable: true, get: function () { return locales_1.localizeProperties; } });
|
|
44
38
|
var properties_1 = require("./minified-utils/properties");
|
|
45
39
|
Object.defineProperty(exports, "Properties", { enumerable: true, get: function () { return properties_1.Properties; } });
|
|
46
|
-
var
|
|
47
|
-
Object.defineProperty(exports, "
|
|
40
|
+
var validation_1 = require("./minified-utils/validation");
|
|
41
|
+
Object.defineProperty(exports, "alter", { enumerable: true, get: function () { return validation_1.alter; } });
|
|
42
|
+
Object.defineProperty(exports, "extract", { enumerable: true, get: function () { return validation_1.extract; } });
|
|
43
|
+
Object.defineProperty(exports, "fieldSchema", { enumerable: true, get: function () { return validation_1.fieldSchema; } });
|
|
44
|
+
Object.defineProperty(exports, "fieldsSchema", { enumerable: true, get: function () { return validation_1.fieldsSchema; } });
|
|
45
|
+
Object.defineProperty(exports, "validate", { enumerable: true, get: function () { return validation_1.validate; } });
|
|
@@ -47,7 +47,7 @@ class Context {
|
|
|
47
47
|
let serialized = false;
|
|
48
48
|
let unresolved;
|
|
49
49
|
const dynamicSource = field.type === `dict` && field.items && (0, exports.isDynamic)(source, false);
|
|
50
|
-
if (((lodash_1.default.isObject(source) || lodash_1.default.isArray(source)) && field.type === `dict` && !field.items) || dynamicSource) {
|
|
50
|
+
if (((lodash_1.default.isObject(source) || lodash_1.default.isArray(source)) && ((field.type === `dict` && !field.items) || (field.type === `file`))) || dynamicSource) {
|
|
51
51
|
serialized = true;
|
|
52
52
|
unresolved = JSON.stringify(source);
|
|
53
53
|
}
|
|
@@ -112,7 +112,9 @@ class Context {
|
|
|
112
112
|
}
|
|
113
113
|
const prop = lodash_1.default.get(i, map.value);
|
|
114
114
|
if (typeof prop !== `undefined`) {
|
|
115
|
-
if (
|
|
115
|
+
if (prop === null) {
|
|
116
|
+
}
|
|
117
|
+
else if (shouldInfer(child, prop)) {
|
|
116
118
|
item[key] = prop;
|
|
117
119
|
}
|
|
118
120
|
else {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import Joi from "joi";
|
|
2
2
|
import { Field } from "./fields";
|
|
3
|
+
import { StorageFunctions } from "../core";
|
|
3
4
|
type ValidationExtended = {
|
|
4
5
|
original: any;
|
|
5
6
|
value: any;
|
|
@@ -15,16 +16,18 @@ type ValidationExtended = {
|
|
|
15
16
|
});
|
|
16
17
|
export declare const fieldSchema: () => Joi.ObjectSchema<any>;
|
|
17
18
|
export declare const fieldsSchema: () => Joi.ArraySchema<any[]>;
|
|
19
|
+
export type ValidationOptions = {
|
|
20
|
+
files: StorageFunctions;
|
|
21
|
+
secure?: boolean;
|
|
22
|
+
break?: boolean;
|
|
23
|
+
context?: Record<string, any>;
|
|
24
|
+
};
|
|
18
25
|
export type ValidationResult<Extended = Record<string, never>> = {
|
|
19
26
|
valid: boolean;
|
|
20
27
|
fields: Field<Extended & ValidationExtended>[];
|
|
21
28
|
};
|
|
22
29
|
export declare const alter: (field: Field, relative: string, data: Record<string, any>) => Field;
|
|
23
|
-
export declare const validate: <I>(fields: Field<I>[], data: Record<string, any>, options
|
|
24
|
-
secure?: boolean;
|
|
25
|
-
break?: boolean;
|
|
26
|
-
context?: Record<string, any>;
|
|
27
|
-
}) => Promise<ValidationResult<I>>;
|
|
30
|
+
export declare const validate: <I>(fields: Field<I>[], data: Record<string, any>, options: ValidationOptions) => Promise<ValidationResult<I>>;
|
|
28
31
|
export declare const extract: (validation: Field<ValidationExtended>[], options?: {
|
|
29
32
|
original?: boolean;
|
|
30
33
|
}) => Promise<Record<string, any>>;
|
|
@@ -4,6 +4,7 @@ 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"));
|
|
7
8
|
const joi_1 = __importDefault(require("joi"));
|
|
8
9
|
const lodash_1 = __importDefault(require("lodash"));
|
|
9
10
|
const moment_timezone_1 = __importDefault(require("moment-timezone"));
|
|
@@ -165,31 +166,6 @@ const fileSchema = () => joi_1.default.object({
|
|
|
165
166
|
type: joi_1.default.string().required(),
|
|
166
167
|
content: joi_1.default.string().required(),
|
|
167
168
|
});
|
|
168
|
-
const fileReplacer = (field) => ({
|
|
169
|
-
key: field.key,
|
|
170
|
-
type: `dict`,
|
|
171
|
-
unknown: true,
|
|
172
|
-
items: [
|
|
173
|
-
{
|
|
174
|
-
key: `name`,
|
|
175
|
-
type: `string`,
|
|
176
|
-
required: true,
|
|
177
|
-
},
|
|
178
|
-
{
|
|
179
|
-
key: `type`,
|
|
180
|
-
type: `string`,
|
|
181
|
-
required: true,
|
|
182
|
-
},
|
|
183
|
-
{
|
|
184
|
-
key: `content`,
|
|
185
|
-
type: `string`,
|
|
186
|
-
required: true,
|
|
187
|
-
},
|
|
188
|
-
],
|
|
189
|
-
default: field.default,
|
|
190
|
-
...lodash_1.default.pick(field, [`altered_by`, `disabled`, `required`, `as_password`, `show`, `as_array`, `array_min`, `array_max`, `array_length`]),
|
|
191
|
-
...Object.assign({}, ...Object.entries(field).map(([k, v]) => k.startsWith(`experimental_`) ? { [k]: v } : {})),
|
|
192
|
-
});
|
|
193
169
|
const fileInputFieldSchema = () => joi_1.default.object({
|
|
194
170
|
default: defaultSchema(fileSchema()),
|
|
195
171
|
accept: joi_1.default.alternatives(joi_1.default.string(), joi_1.default.array().items(joi_1.default.string())).optional(),
|
|
@@ -242,7 +218,7 @@ const fieldSchema = () => inputFieldBaseSchema()
|
|
|
242
218
|
exports.fieldSchema = fieldSchema;
|
|
243
219
|
const fieldsSchema = () => joi_1.default.array().items((0, exports.fieldSchema)());
|
|
244
220
|
exports.fieldsSchema = fieldsSchema;
|
|
245
|
-
const getSimpleFieldSchema = (field) => {
|
|
221
|
+
const getSimpleFieldSchema = (field, configuration) => {
|
|
246
222
|
if (field.as_array) {
|
|
247
223
|
throw new Error(`Cannot use as_array with simple field schema generator`);
|
|
248
224
|
}
|
|
@@ -334,7 +310,26 @@ const getSimpleFieldSchema = (field) => {
|
|
|
334
310
|
typeSchema = joi_1.default.object().unknown(true);
|
|
335
311
|
break;
|
|
336
312
|
case `file`:
|
|
337
|
-
typeSchema = fileSchema()
|
|
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
|
+
});
|
|
338
333
|
break;
|
|
339
334
|
}
|
|
340
335
|
if (`format` in field && field.format === `select`) {
|
|
@@ -447,9 +442,6 @@ const recursive_schema = async (field, data, options) => {
|
|
|
447
442
|
}
|
|
448
443
|
}
|
|
449
444
|
const alteredField = lodash_1.default.cloneDeep(newField);
|
|
450
|
-
if (newField.type === `file`) {
|
|
451
|
-
newField = fileReplacer(newField);
|
|
452
|
-
}
|
|
453
445
|
const relativeKey = options.relative ?
|
|
454
446
|
options.relative.endsWith(`]`) ?
|
|
455
447
|
options.array ? options.relative : `${options.relative}.${newField.key}`
|
|
@@ -475,7 +467,7 @@ const recursive_schema = async (field, data, options) => {
|
|
|
475
467
|
const itemSchemas = [];
|
|
476
468
|
if (lodash_1.default.isArray(resolved)) {
|
|
477
469
|
for (let i = 0; i < (resolved || []).length; i++) {
|
|
478
|
-
const { schema: itemSchema } = await recursive_schema(noArrayField, data, { alter: false, relative: `${relativeKey}[${i}]`, array: true, context: options.context });
|
|
470
|
+
const { schema: itemSchema } = await recursive_schema(noArrayField, data, { files: options.files, alter: false, relative: `${relativeKey}[${i}]`, array: true, context: options.context });
|
|
479
471
|
if (itemSchema) {
|
|
480
472
|
itemSchemas.push(itemSchema);
|
|
481
473
|
}
|
|
@@ -490,7 +482,7 @@ const recursive_schema = async (field, data, options) => {
|
|
|
490
482
|
if (noArrayField.type === `dict` && noArrayField.items) {
|
|
491
483
|
const items = [];
|
|
492
484
|
for (const item of noArrayField.items) {
|
|
493
|
-
const recursive = await recursive_schema(item, data, { alter: options.alter && true, relative: `${relativeKey}[0]`, context: options.context, no_undefined: true });
|
|
485
|
+
const recursive = await recursive_schema(item, data, { files: options.files, alter: options.alter && true, relative: `${relativeKey}[0]`, context: options.context, no_undefined: true });
|
|
494
486
|
if (recursive) {
|
|
495
487
|
items.push({ key: item.key, schema: recursive.schema, field: recursive.field });
|
|
496
488
|
}
|
|
@@ -499,7 +491,7 @@ const recursive_schema = async (field, data, options) => {
|
|
|
499
491
|
noArrayField.items = items.map((i) => i.field);
|
|
500
492
|
}
|
|
501
493
|
else {
|
|
502
|
-
genericItemSchema = getSimpleFieldSchema(noArrayField);
|
|
494
|
+
genericItemSchema = getSimpleFieldSchema(noArrayField, { files: options.files });
|
|
503
495
|
}
|
|
504
496
|
calculatedSchema = getItemsArrayFieldSchema(newField, [genericItemSchema]);
|
|
505
497
|
}
|
|
@@ -508,7 +500,7 @@ const recursive_schema = async (field, data, options) => {
|
|
|
508
500
|
if (resolved || newField.required) {
|
|
509
501
|
const items = [];
|
|
510
502
|
for (const item of newField.items) {
|
|
511
|
-
const recursive = await recursive_schema(item, data, { alter: options.alter && true, relative: relativeKey, context: options.context });
|
|
503
|
+
const recursive = await recursive_schema(item, data, { files: options.files, alter: options.alter && true, relative: relativeKey, context: options.context });
|
|
512
504
|
if (recursive) {
|
|
513
505
|
items.push({ key: item.key, schema: recursive.schema, field: recursive.field });
|
|
514
506
|
}
|
|
@@ -518,11 +510,11 @@ const recursive_schema = async (field, data, options) => {
|
|
|
518
510
|
}
|
|
519
511
|
else {
|
|
520
512
|
delete newField.items;
|
|
521
|
-
calculatedSchema = getSimpleFieldSchema(newField);
|
|
513
|
+
calculatedSchema = getSimpleFieldSchema(newField, { files: options.files });
|
|
522
514
|
}
|
|
523
515
|
}
|
|
524
516
|
else {
|
|
525
|
-
calculatedSchema = getSimpleFieldSchema(newField);
|
|
517
|
+
calculatedSchema = getSimpleFieldSchema(newField, { files: options.files });
|
|
526
518
|
}
|
|
527
519
|
if (!calculatedSchema) {
|
|
528
520
|
throw new Error(`Could not resolve schema for field ${newField.key}`);
|
|
@@ -542,7 +534,7 @@ const validate_internal = async (fields, data, options) => {
|
|
|
542
534
|
for (const field of fields) {
|
|
543
535
|
const value = lodash_1.default.get(data, field.key, field.default);
|
|
544
536
|
const cloned = lodash_1.default.cloneDeep(data);
|
|
545
|
-
const recursive = await recursive_schema(field, cloned, { alter: true, context: options.context });
|
|
537
|
+
const recursive = await recursive_schema(field, cloned, { files: options.files, alter: true, context: options.context });
|
|
546
538
|
if (!recursive) {
|
|
547
539
|
continue;
|
|
548
540
|
}
|
|
@@ -594,7 +586,7 @@ const validate_internal = async (fields, data, options) => {
|
|
|
594
586
|
throw e;
|
|
595
587
|
}
|
|
596
588
|
};
|
|
597
|
-
const validate = async (fields, data, options
|
|
589
|
+
const validate = async (fields, data, options) => {
|
|
598
590
|
try {
|
|
599
591
|
const { error } = (0, exports.fieldsSchema)().validate(fields);
|
|
600
592
|
if (error) {
|
package/package.json
CHANGED
package/src/core.ts
CHANGED
|
@@ -4,6 +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
8
|
|
|
8
9
|
export type SourceFunctions = {
|
|
9
10
|
register: <SC extends SourceConfig = SourceConfig>(source: SC[`id`], sandbox: boolean, data: SC[`fields`]) => Promise<{ id: string }>,
|
|
@@ -11,6 +12,11 @@ export type SourceFunctions = {
|
|
|
11
12
|
unregister: <SC extends SourceConfig = SourceConfig>(source: SC[`id`], sandbox: boolean, id: string) => Promise<void>,
|
|
12
13
|
};
|
|
13
14
|
|
|
15
|
+
export type StorageFunctions = {
|
|
16
|
+
read: (id: string) => Promise<string>,
|
|
17
|
+
store: (file: File) => Promise<File>,
|
|
18
|
+
};
|
|
19
|
+
|
|
14
20
|
const FALLBACK_SOURCES: SourceFunctions = {
|
|
15
21
|
register: async () => {
|
|
16
22
|
throw new Error(`Sources not available: valid implementation not provided`);
|
|
@@ -31,12 +37,14 @@ export type Core = {
|
|
|
31
37
|
joi: Joi.Root,
|
|
32
38
|
sources?: SourceFunctions,
|
|
33
39
|
t: T,
|
|
40
|
+
files: StorageFunctions,
|
|
34
41
|
};
|
|
35
42
|
|
|
36
43
|
type CoreOptions = {
|
|
44
|
+
localization: FromDirectory | FromCatalog,
|
|
45
|
+
files: StorageFunctions,
|
|
37
46
|
env?: Record<string, any>,
|
|
38
47
|
sources?: SourceFunctions,
|
|
39
|
-
localization: FromDirectory | FromCatalog,
|
|
40
48
|
};
|
|
41
49
|
|
|
42
50
|
/* eslint-disable @typescript-eslint/unbound-method */
|
|
@@ -51,4 +59,5 @@ export const core = async (options: CoreOptions): Promise<Core> => ({
|
|
|
51
59
|
joi: Joi,
|
|
52
60
|
sources: options.sources || FALLBACK_SOURCES,
|
|
53
61
|
t: i18n(options.localization).t,
|
|
62
|
+
files: options.files,
|
|
54
63
|
});
|
package/src/index.ts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
export { Core, core } from './core';
|
|
1
|
+
export { Core, core, SourceFunctions, StorageFunctions } from './core';
|
|
2
2
|
export { CoreFunction, idSchema } from './entities/commons';
|
|
3
3
|
export { Credentials, credentialsSchema, OAuthCredentials, oauthCredentialsSchema, SessionCredentials, sessionCredentialsSchema, StaticCredentials, staticCredentialsSchema } from './entities/credentials';
|
|
4
4
|
export { Action, actionOutputSchema, actionSchema, AsyncAction, Event, eventSchema, ImmediateTrigger, immediateTriggerSchema, Request, ScheduledTrigger, scheduledTriggerSchema, SyncAction, syncActionSchema, Trigger, triggerOutputSchema, triggerSchema } from './entities/events';
|
|
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 { alter, extract, fieldSchema, fieldsSchema, validate, ValidationResult } from './minified-utils/validation';
|
|
9
8
|
export { Condition, Field, File, SelectFieldChoice } from './minified-utils/fields';
|
|
10
9
|
export { DEFAULT_LOCALE, i18n, LocalizedField, LocalizedProperties, localizeFields, localizeGroup, localizeInputs, localizeOutputs, localizeProperties } from './minified-utils/locales';
|
|
11
10
|
export { Properties } from './minified-utils/properties';
|
|
12
|
-
export {
|
|
11
|
+
export { alter, extract, fieldSchema, fieldsSchema, validate, ValidationOptions, ValidationResult } from './minified-utils/validation';
|
|
@@ -60,7 +60,7 @@ class Context {
|
|
|
60
60
|
|
|
61
61
|
const dynamicSource = field.type === `dict` && field.items && isDynamic(source, false);
|
|
62
62
|
|
|
63
|
-
if (((_.isObject(source) || _.isArray(source)) && field.type === `dict` && !field.items) || dynamicSource) {
|
|
63
|
+
if (((_.isObject(source) || _.isArray(source)) && ((field.type === `dict` && !field.items) || (field.type === `file`))) || dynamicSource) {
|
|
64
64
|
serialized = true;
|
|
65
65
|
unresolved = JSON.stringify(source);
|
|
66
66
|
} else if (typeof source === `string`) {
|
|
@@ -125,7 +125,9 @@ class Context {
|
|
|
125
125
|
|
|
126
126
|
const prop = _.get(i, map.value);
|
|
127
127
|
if (typeof prop !== `undefined`) {
|
|
128
|
-
if (
|
|
128
|
+
if (prop === null) {
|
|
129
|
+
// treat as empty value
|
|
130
|
+
} else if (shouldInfer(child, prop)) {
|
|
129
131
|
item[key] = prop;
|
|
130
132
|
} else {
|
|
131
133
|
item[key] = _.toString(prop);
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import axios from "axios";
|
|
1
2
|
import Joi, { DateSchema, NumberSchema, StringSchema } from "joi";
|
|
2
3
|
import _ from "lodash";
|
|
3
4
|
import moment from "moment-timezone";
|
|
4
5
|
import context from "./context";
|
|
6
|
+
import { Field, File, SelectFieldChoice } from "./fields";
|
|
5
7
|
import { where, Where } from "./where";
|
|
6
|
-
import {
|
|
8
|
+
import { StorageFunctions } from "../core";
|
|
7
9
|
|
|
8
10
|
type ValidationExtended = {
|
|
9
11
|
original: any,
|
|
@@ -218,32 +220,32 @@ const fileSchema = () => Joi.object({
|
|
|
218
220
|
content: Joi.string().required(), // base64 encoded content
|
|
219
221
|
});
|
|
220
222
|
|
|
221
|
-
// ÑAPA: translate file to structured dict
|
|
222
|
-
const fileReplacer = (field: CommonField & FileInputField): Field => ({
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}) as Field;
|
|
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;
|
|
247
249
|
|
|
248
250
|
const fileInputFieldSchema = () =>
|
|
249
251
|
Joi.object({
|
|
@@ -307,7 +309,7 @@ export const fieldSchema = () =>
|
|
|
307
309
|
export const fieldsSchema = () =>
|
|
308
310
|
Joi.array().items(fieldSchema());
|
|
309
311
|
|
|
310
|
-
const getSimpleFieldSchema = (field: Field) => {
|
|
312
|
+
const getSimpleFieldSchema = (field: Field, configuration: { files: StorageFunctions }) => {
|
|
311
313
|
if (field.as_array) { throw new Error(`Cannot use as_array with simple field schema generator`); }
|
|
312
314
|
|
|
313
315
|
let typeSchema: Joi.Schema;
|
|
@@ -378,7 +380,28 @@ const getSimpleFieldSchema = (field: Field) => {
|
|
|
378
380
|
typeSchema = Joi.object().unknown(true);
|
|
379
381
|
break;
|
|
380
382
|
case `file`:
|
|
381
|
-
typeSchema = fileSchema()
|
|
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
|
+
});
|
|
382
405
|
break;
|
|
383
406
|
}
|
|
384
407
|
|
|
@@ -447,6 +470,13 @@ const convertPath = (parts: (string | number)[]): string =>
|
|
|
447
470
|
const secure = async (field: Field, validation: ValidationExtended): Promise<ValidationExtended> =>
|
|
448
471
|
field.as_password ? _.omit(validation, [`value`, `original`]) as any : validation;
|
|
449
472
|
|
|
473
|
+
export type ValidationOptions = {
|
|
474
|
+
files: StorageFunctions,
|
|
475
|
+
secure?: boolean,
|
|
476
|
+
break?: boolean,
|
|
477
|
+
context?: Record<string, any>,
|
|
478
|
+
};
|
|
479
|
+
|
|
450
480
|
export type ValidationResult<Extended = Record<string, never>> = {
|
|
451
481
|
valid: boolean,
|
|
452
482
|
fields: Field<Extended & ValidationExtended>[],
|
|
@@ -478,7 +508,7 @@ export const alter = (field: Field, relative: string, data: Record<string, any>)
|
|
|
478
508
|
return cloned;
|
|
479
509
|
};
|
|
480
510
|
|
|
481
|
-
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 }> => {
|
|
511
|
+
const recursive_schema = async (field: Field, data: Record<string, any>, options: { files: StorageFunctions, alter: boolean, context: Record<string, any>, relative?: string, array?: boolean, no_undefined?: boolean }): Promise<{ schema: Joi.Schema, field: Field }> => {
|
|
482
512
|
try {
|
|
483
513
|
let newField: Field = _.cloneDeep(field);
|
|
484
514
|
|
|
@@ -495,7 +525,7 @@ const recursive_schema = async (field: Field, data: Record<string, any>, options
|
|
|
495
525
|
const alteredField: Field = _.cloneDeep(newField);
|
|
496
526
|
|
|
497
527
|
// ÑAPA: if the field is a file, replace it
|
|
498
|
-
if (newField.type === `file`) { newField = fileReplacer(newField); }
|
|
528
|
+
// if (newField.type === `file`) { newField = fileReplacer(newField); }
|
|
499
529
|
|
|
500
530
|
const relativeKey = options.relative ?
|
|
501
531
|
options.relative.endsWith(`]`) ?
|
|
@@ -528,7 +558,7 @@ const recursive_schema = async (field: Field, data: Record<string, any>, options
|
|
|
528
558
|
const itemSchemas: Joi.Schema[] = [];
|
|
529
559
|
if (_.isArray(resolved)) {
|
|
530
560
|
for (let i = 0; i < (resolved || []).length; i++) {
|
|
531
|
-
const { schema: itemSchema } = await recursive_schema(noArrayField, data, { alter: false, relative: `${relativeKey}[${i}]`, array: true, context: options.context });
|
|
561
|
+
const { schema: itemSchema } = await recursive_schema(noArrayField, data, { files: options.files, alter: false, relative: `${relativeKey}[${i}]`, array: true, context: options.context });
|
|
532
562
|
if (itemSchema) { itemSchemas.push(itemSchema); }
|
|
533
563
|
}
|
|
534
564
|
|
|
@@ -544,14 +574,14 @@ const recursive_schema = async (field: Field, data: Record<string, any>, options
|
|
|
544
574
|
const items: { key: string, schema: Joi.Schema, field: Field }[] = [];
|
|
545
575
|
|
|
546
576
|
for (const item of noArrayField.items) {
|
|
547
|
-
const recursive = await recursive_schema(item, data, { alter: options.alter && true, relative: `${relativeKey}[0]`, context: options.context, no_undefined: true });
|
|
577
|
+
const recursive = await recursive_schema(item, data, { files: options.files, alter: options.alter && true, relative: `${relativeKey}[0]`, context: options.context, no_undefined: true });
|
|
548
578
|
if (recursive) { items.push({ key: item.key, schema: recursive.schema, field: recursive.field }); }
|
|
549
579
|
}
|
|
550
580
|
|
|
551
581
|
genericItemSchema = getObjectFieldSchema(noArrayField, items);
|
|
552
582
|
noArrayField.items = items.map((i) => i.field);
|
|
553
583
|
} else {
|
|
554
|
-
genericItemSchema = getSimpleFieldSchema(noArrayField);
|
|
584
|
+
genericItemSchema = getSimpleFieldSchema(noArrayField, { files: options.files });
|
|
555
585
|
}
|
|
556
586
|
|
|
557
587
|
calculatedSchema = getItemsArrayFieldSchema(newField, [genericItemSchema]);
|
|
@@ -561,7 +591,7 @@ const recursive_schema = async (field: Field, data: Record<string, any>, options
|
|
|
561
591
|
const items: { key: string, schema: Joi.Schema, field: Field }[] = [];
|
|
562
592
|
|
|
563
593
|
for (const item of newField.items) {
|
|
564
|
-
const recursive = await recursive_schema(item, data, { alter: options.alter && true, relative: relativeKey, context: options.context });
|
|
594
|
+
const recursive = await recursive_schema(item, data, { files: options.files, alter: options.alter && true, relative: relativeKey, context: options.context });
|
|
565
595
|
if (recursive) { items.push({ key: item.key, schema: recursive.schema, field: recursive.field }); }
|
|
566
596
|
}
|
|
567
597
|
|
|
@@ -569,10 +599,10 @@ const recursive_schema = async (field: Field, data: Record<string, any>, options
|
|
|
569
599
|
newField.items = items.map((i) => i.field);
|
|
570
600
|
} else {
|
|
571
601
|
delete newField.items;
|
|
572
|
-
calculatedSchema = getSimpleFieldSchema(newField);
|
|
602
|
+
calculatedSchema = getSimpleFieldSchema(newField, { files: options.files });
|
|
573
603
|
}
|
|
574
604
|
} else {
|
|
575
|
-
calculatedSchema = getSimpleFieldSchema(newField);
|
|
605
|
+
calculatedSchema = getSimpleFieldSchema(newField, { files: options.files });
|
|
576
606
|
}
|
|
577
607
|
|
|
578
608
|
if (!calculatedSchema) { throw new Error(`Could not resolve schema for field ${newField.key}`); }
|
|
@@ -584,7 +614,7 @@ const recursive_schema = async (field: Field, data: Record<string, any>, options
|
|
|
584
614
|
} catch (e) { throw e; }
|
|
585
615
|
};
|
|
586
616
|
|
|
587
|
-
const validate_internal = async (fields: Field[], data: Record<string, any>, options: { secure: boolean, break: boolean, context: Record<string, any> }): Promise<ValidationResult> => {
|
|
617
|
+
const validate_internal = async (fields: Field[], data: Record<string, any>, options: { files: StorageFunctions, secure: boolean, break: boolean, context: Record<string, any> }): Promise<ValidationResult> => {
|
|
588
618
|
try {
|
|
589
619
|
const response: ValidationResult<{}> = { valid: true, fields: [] };
|
|
590
620
|
|
|
@@ -594,7 +624,7 @@ const validate_internal = async (fields: Field[], data: Record<string, any>, opt
|
|
|
594
624
|
|
|
595
625
|
const cloned = _.cloneDeep(data);
|
|
596
626
|
|
|
597
|
-
const recursive = await recursive_schema(field, cloned, { alter: true, context: options.context });
|
|
627
|
+
const recursive = await recursive_schema(field, cloned, { files: options.files, alter: true, context: options.context });
|
|
598
628
|
if (!recursive) { continue; }
|
|
599
629
|
|
|
600
630
|
const resolved = _.get(cloned, field.key, field.default);
|
|
@@ -644,7 +674,7 @@ const validate_internal = async (fields: Field[], data: Record<string, any>, opt
|
|
|
644
674
|
} catch (e) { throw e; }
|
|
645
675
|
};
|
|
646
676
|
|
|
647
|
-
export const validate = async <I>(fields: Field<I>[], data: Record<string, any>, options:
|
|
677
|
+
export const validate = async <I>(fields: Field<I>[], data: Record<string, any>, options: ValidationOptions): Promise<ValidationResult<I>> => {
|
|
648
678
|
try {
|
|
649
679
|
const { error } = fieldsSchema().validate(fields);
|
|
650
680
|
if (error) { throw new Error(`Invalid fields definition: ${error.message}`); }
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { Provider } from "../entities/provider";
|
|
2
|
-
export declare class Protocol {
|
|
3
|
-
private readonly provider;
|
|
4
|
-
private readonly configuration;
|
|
5
|
-
constructor(provider: Provider, configuration: Protocol.Configuration);
|
|
6
|
-
evaluate: (req: Protocol.Command) => Promise<any>;
|
|
7
|
-
}
|
|
8
|
-
export declare namespace Protocol {
|
|
9
|
-
type Model = `action` | `trigger` | `credential`;
|
|
10
|
-
type Invoke = {
|
|
11
|
-
command: `invoke`;
|
|
12
|
-
model: Protocol.Model;
|
|
13
|
-
id: string;
|
|
14
|
-
params: {
|
|
15
|
-
function: string;
|
|
16
|
-
configuration: Record<string, any>;
|
|
17
|
-
};
|
|
18
|
-
context: {
|
|
19
|
-
organization: string;
|
|
20
|
-
workspace: number;
|
|
21
|
-
environment: Record<string, any>;
|
|
22
|
-
localization: {
|
|
23
|
-
locale: string;
|
|
24
|
-
catalog: Record<string, any>;
|
|
25
|
-
};
|
|
26
|
-
};
|
|
27
|
-
};
|
|
28
|
-
type CredentialList = {
|
|
29
|
-
command: `list:credentials`;
|
|
30
|
-
};
|
|
31
|
-
type ActionList = {
|
|
32
|
-
command: `list:actions`;
|
|
33
|
-
};
|
|
34
|
-
type TriggerList = {
|
|
35
|
-
command: `list:triggers`;
|
|
36
|
-
};
|
|
37
|
-
type SourceList = {
|
|
38
|
-
command: `list:sources`;
|
|
39
|
-
};
|
|
40
|
-
type LocaleList = {
|
|
41
|
-
command: `list:locales`;
|
|
42
|
-
};
|
|
43
|
-
type Command = Invoke | CredentialList | ActionList | TriggerList | SourceList | LocaleList;
|
|
44
|
-
type SourcesConfiguration = {
|
|
45
|
-
host: string;
|
|
46
|
-
token: string;
|
|
47
|
-
};
|
|
48
|
-
type Configuration = {
|
|
49
|
-
path: string;
|
|
50
|
-
sources: SourcesConfiguration;
|
|
51
|
-
};
|
|
52
|
-
}
|
|
@@ -1,187 +0,0 @@
|
|
|
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.Protocol = void 0;
|
|
7
|
-
const axios_1 = __importDefault(require("axios"));
|
|
8
|
-
const joi_1 = __importDefault(require("joi"));
|
|
9
|
-
const lodash_1 = __importDefault(require("lodash"));
|
|
10
|
-
const core_1 = require("../core");
|
|
11
|
-
const provider_1 = require("../entities/provider");
|
|
12
|
-
const locales_1 = require("./locales");
|
|
13
|
-
const invokeSchema = joi_1.default.object({
|
|
14
|
-
command: joi_1.default.string().valid(`invoke`).required(),
|
|
15
|
-
model: joi_1.default.string().valid(`action`, `trigger`, `credential`).required(),
|
|
16
|
-
id: joi_1.default.string().required(),
|
|
17
|
-
params: joi_1.default.object({
|
|
18
|
-
function: joi_1.default.string().required(),
|
|
19
|
-
configuration: joi_1.default.object().required(),
|
|
20
|
-
}).required(),
|
|
21
|
-
context: joi_1.default.object({
|
|
22
|
-
organization: joi_1.default.string().required(),
|
|
23
|
-
workspace: joi_1.default.number().required(),
|
|
24
|
-
environment: joi_1.default.object().required(),
|
|
25
|
-
localization: joi_1.default.object({
|
|
26
|
-
locale: joi_1.default.string().required(),
|
|
27
|
-
catalog: joi_1.default.object().required(),
|
|
28
|
-
}).required(),
|
|
29
|
-
}).required(),
|
|
30
|
-
}).required();
|
|
31
|
-
const credentialListSchema = joi_1.default.object({
|
|
32
|
-
command: joi_1.default.string().valid(`list:credentials`).required(),
|
|
33
|
-
}).required();
|
|
34
|
-
const actionListSchema = joi_1.default.object({
|
|
35
|
-
command: joi_1.default.string().valid(`list:actions`).required(),
|
|
36
|
-
}).required();
|
|
37
|
-
const triggerListSchema = joi_1.default.object({
|
|
38
|
-
command: joi_1.default.string().valid(`list:triggers`).required(),
|
|
39
|
-
}).required();
|
|
40
|
-
const sourceListSchema = joi_1.default.object({
|
|
41
|
-
command: joi_1.default.string().valid(`list:sources`).required(),
|
|
42
|
-
}).required();
|
|
43
|
-
const localeListSchema = joi_1.default.object({
|
|
44
|
-
command: joi_1.default.string().valid(`list:locales`).required(),
|
|
45
|
-
}).required();
|
|
46
|
-
const commandSchema = joi_1.default.alternatives(invokeSchema, credentialListSchema, actionListSchema, triggerListSchema, sourceListSchema, localeListSchema);
|
|
47
|
-
const API_SOURCES = (provider, configuration, context) => {
|
|
48
|
-
const REQ_CONFIG = {
|
|
49
|
-
baseURL: configuration.host,
|
|
50
|
-
headers: {
|
|
51
|
-
"x-prow-provider": provider.id,
|
|
52
|
-
"x-prow-version": provider.version,
|
|
53
|
-
"x-prow-token": configuration.token,
|
|
54
|
-
"x-prow-organization": context.organization,
|
|
55
|
-
"x-active-workspace": `${context.workspace}`,
|
|
56
|
-
},
|
|
57
|
-
};
|
|
58
|
-
return {
|
|
59
|
-
register: async (source, sandbox, data) => {
|
|
60
|
-
try {
|
|
61
|
-
const { data: [created] } = await axios_1.default.post(`/feu/v1/sources`, {
|
|
62
|
-
provider: provider.id,
|
|
63
|
-
version: provider.version,
|
|
64
|
-
source: source,
|
|
65
|
-
sandbox: sandbox,
|
|
66
|
-
data: data,
|
|
67
|
-
}, REQ_CONFIG);
|
|
68
|
-
if (!created || !created.uuid) {
|
|
69
|
-
throw new Error(`Source registration failed`);
|
|
70
|
-
}
|
|
71
|
-
return { id: created.uuid };
|
|
72
|
-
}
|
|
73
|
-
catch (e) {
|
|
74
|
-
throw e;
|
|
75
|
-
}
|
|
76
|
-
},
|
|
77
|
-
unregister: async (source, sandbox, id) => {
|
|
78
|
-
try {
|
|
79
|
-
const { data: [get] } = await axios_1.default.post(`/feu/v1/sources/list`, {
|
|
80
|
-
provider: provider.id,
|
|
81
|
-
version: provider.version,
|
|
82
|
-
source: source,
|
|
83
|
-
sandbox: sandbox,
|
|
84
|
-
uuid: id,
|
|
85
|
-
}, REQ_CONFIG);
|
|
86
|
-
if (!get) {
|
|
87
|
-
throw new Error(`Source with ID ${id} not found`);
|
|
88
|
-
}
|
|
89
|
-
await axios_1.default.delete(`/feu/v1/sources/${get.id}`, REQ_CONFIG);
|
|
90
|
-
}
|
|
91
|
-
catch (e) {
|
|
92
|
-
throw e;
|
|
93
|
-
}
|
|
94
|
-
},
|
|
95
|
-
consume: async (source, sandbox) => {
|
|
96
|
-
try {
|
|
97
|
-
const { data: sources } = await axios_1.default.post(`/feu/v1/sources/list`, {
|
|
98
|
-
provider: provider.id,
|
|
99
|
-
version: provider.version,
|
|
100
|
-
source: source,
|
|
101
|
-
sandbox: sandbox,
|
|
102
|
-
}, REQ_CONFIG);
|
|
103
|
-
return sources.map((s) => ({
|
|
104
|
-
id: s.uuid,
|
|
105
|
-
data: s.data,
|
|
106
|
-
}));
|
|
107
|
-
}
|
|
108
|
-
catch (e) {
|
|
109
|
-
throw e;
|
|
110
|
-
}
|
|
111
|
-
},
|
|
112
|
-
};
|
|
113
|
-
};
|
|
114
|
-
class Protocol {
|
|
115
|
-
constructor(provider, configuration) {
|
|
116
|
-
this.evaluate = async (req) => {
|
|
117
|
-
try {
|
|
118
|
-
const validation = commandSchema.validate(req);
|
|
119
|
-
if (validation.error) {
|
|
120
|
-
throw new Error(`Invalid request: ${validation.error.message}`);
|
|
121
|
-
}
|
|
122
|
-
const serialize = (elem) => ({
|
|
123
|
-
...lodash_1.default.omit(elem, [`functions`, `helpers`]),
|
|
124
|
-
functions: Object.keys(elem.functions),
|
|
125
|
-
helpers: Object.keys(elem.helpers),
|
|
126
|
-
});
|
|
127
|
-
let response;
|
|
128
|
-
switch (req.command) {
|
|
129
|
-
case `list:actions`:
|
|
130
|
-
response = Object.values(this.provider.actions || {}).map(serialize);
|
|
131
|
-
break;
|
|
132
|
-
case `list:triggers`:
|
|
133
|
-
response = Object.values(this.provider.triggers || {}).map(serialize);
|
|
134
|
-
break;
|
|
135
|
-
case `list:credentials`:
|
|
136
|
-
response = Object.values(this.provider.credentials || {}).map(serialize);
|
|
137
|
-
break;
|
|
138
|
-
case `list:sources`:
|
|
139
|
-
response = Object.values(this.provider.sources || {});
|
|
140
|
-
break;
|
|
141
|
-
case `list:locales`:
|
|
142
|
-
const i18nInstance = (0, locales_1.i18n)({ directory: `${this.configuration.path}/locales` });
|
|
143
|
-
response = i18nInstance.i18n.getLocales().map((l) => {
|
|
144
|
-
i18nInstance.i18n.setLocale(l);
|
|
145
|
-
return {
|
|
146
|
-
code: l,
|
|
147
|
-
catalog: i18nInstance.i18n.getCatalog(),
|
|
148
|
-
};
|
|
149
|
-
});
|
|
150
|
-
break;
|
|
151
|
-
case `invoke`:
|
|
152
|
-
const elem = lodash_1.default.get(this.provider, `${req.model}s.${req.id}`);
|
|
153
|
-
if (!elem) {
|
|
154
|
-
throw new Error(`Could not find ${req.model} with ID ${req.id}`);
|
|
155
|
-
}
|
|
156
|
-
const func = lodash_1.default.get(elem, req.params.function);
|
|
157
|
-
if (!func || typeof func !== `function`) {
|
|
158
|
-
throw new Error(`Invalid function ${req.params.function}`);
|
|
159
|
-
}
|
|
160
|
-
const invokeInstance = await (0, core_1.core)({
|
|
161
|
-
env: req.context.environment,
|
|
162
|
-
localization: req.context.localization,
|
|
163
|
-
sources: API_SOURCES(this.provider, this.configuration.sources, {
|
|
164
|
-
organization: req.context.organization,
|
|
165
|
-
workspace: req.context.workspace,
|
|
166
|
-
}),
|
|
167
|
-
});
|
|
168
|
-
response = await func(invokeInstance, req.params.configuration);
|
|
169
|
-
break;
|
|
170
|
-
default:
|
|
171
|
-
throw new Error(`Invalid command`);
|
|
172
|
-
}
|
|
173
|
-
return response;
|
|
174
|
-
}
|
|
175
|
-
catch (e) {
|
|
176
|
-
throw e;
|
|
177
|
-
}
|
|
178
|
-
};
|
|
179
|
-
const providerValidation = (0, provider_1.providerSchema)().validate(provider);
|
|
180
|
-
if (providerValidation.error) {
|
|
181
|
-
throw new Error(`Invalid provider for protocol`);
|
|
182
|
-
}
|
|
183
|
-
this.provider = provider;
|
|
184
|
-
this.configuration = configuration;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
exports.Protocol = Protocol;
|
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
import axios from "axios";
|
|
2
|
-
import Joi from "joi";
|
|
3
|
-
import _ from "lodash";
|
|
4
|
-
import { core, SourceFunctions } from "../core";
|
|
5
|
-
import { Credentials } from "../entities/credentials";
|
|
6
|
-
import { Action, Trigger } from "../entities/events";
|
|
7
|
-
import { Provider, providerSchema } from "../entities/provider";
|
|
8
|
-
import { i18n } from "./locales";
|
|
9
|
-
|
|
10
|
-
const invokeSchema = Joi.object({
|
|
11
|
-
command: Joi.string().valid(`invoke`).required(),
|
|
12
|
-
model: Joi.string().valid(`action`, `trigger`, `credential`).required(),
|
|
13
|
-
id: Joi.string().required(),
|
|
14
|
-
params: Joi.object({
|
|
15
|
-
function: Joi.string().required(),
|
|
16
|
-
configuration: Joi.object().required(),
|
|
17
|
-
}).required(),
|
|
18
|
-
context: Joi.object({
|
|
19
|
-
organization: Joi.string().required(),
|
|
20
|
-
workspace: Joi.number().required(),
|
|
21
|
-
environment: Joi.object().required(),
|
|
22
|
-
localization: Joi.object({
|
|
23
|
-
locale: Joi.string().required(),
|
|
24
|
-
catalog: Joi.object().required(),
|
|
25
|
-
}).required(),
|
|
26
|
-
}).required(),
|
|
27
|
-
}).required();
|
|
28
|
-
|
|
29
|
-
const credentialListSchema = Joi.object({
|
|
30
|
-
command: Joi.string().valid(`list:credentials`).required(),
|
|
31
|
-
}).required();
|
|
32
|
-
|
|
33
|
-
const actionListSchema = Joi.object({
|
|
34
|
-
command: Joi.string().valid(`list:actions`).required(),
|
|
35
|
-
}).required();
|
|
36
|
-
|
|
37
|
-
const triggerListSchema = Joi.object({
|
|
38
|
-
command: Joi.string().valid(`list:triggers`).required(),
|
|
39
|
-
}).required();
|
|
40
|
-
|
|
41
|
-
const sourceListSchema = Joi.object({
|
|
42
|
-
command: Joi.string().valid(`list:sources`).required(),
|
|
43
|
-
}).required();
|
|
44
|
-
|
|
45
|
-
const localeListSchema = Joi.object({
|
|
46
|
-
command: Joi.string().valid(`list:locales`).required(),
|
|
47
|
-
}).required();
|
|
48
|
-
|
|
49
|
-
const commandSchema = Joi.alternatives(
|
|
50
|
-
invokeSchema,
|
|
51
|
-
credentialListSchema,
|
|
52
|
-
actionListSchema,
|
|
53
|
-
triggerListSchema,
|
|
54
|
-
sourceListSchema,
|
|
55
|
-
localeListSchema,
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
const API_SOURCES = (provider: Provider, configuration: Protocol.SourcesConfiguration, context: { organization: string, workspace: number }): SourceFunctions => {
|
|
59
|
-
|
|
60
|
-
const REQ_CONFIG = {
|
|
61
|
-
baseURL: configuration.host,
|
|
62
|
-
headers: {
|
|
63
|
-
"x-prow-provider": provider.id,
|
|
64
|
-
"x-prow-version": provider.version,
|
|
65
|
-
"x-prow-token": configuration.token,
|
|
66
|
-
"x-prow-organization": context.organization,
|
|
67
|
-
"x-active-workspace": `${context.workspace}`,
|
|
68
|
-
},
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
return {
|
|
72
|
-
register: async (source, sandbox, data) => {
|
|
73
|
-
try {
|
|
74
|
-
const { data: [created] } = await axios.post(`/feu/v1/sources`, {
|
|
75
|
-
provider: provider.id,
|
|
76
|
-
version: provider.version,
|
|
77
|
-
source: source,
|
|
78
|
-
sandbox: sandbox,
|
|
79
|
-
data: data,
|
|
80
|
-
}, REQ_CONFIG);
|
|
81
|
-
if (!created || !created.uuid) { throw new Error(`Source registration failed`); }
|
|
82
|
-
return { id: created.uuid };
|
|
83
|
-
} catch (e) { throw e; }
|
|
84
|
-
},
|
|
85
|
-
unregister: async (source, sandbox, id) => {
|
|
86
|
-
try {
|
|
87
|
-
const { data: [get] } = await axios.post(`/feu/v1/sources/list`, {
|
|
88
|
-
provider: provider.id,
|
|
89
|
-
version: provider.version,
|
|
90
|
-
source: source,
|
|
91
|
-
sandbox: sandbox,
|
|
92
|
-
uuid: id,
|
|
93
|
-
}, REQ_CONFIG);
|
|
94
|
-
if (!get) { throw new Error(`Source with ID ${id} not found`); }
|
|
95
|
-
|
|
96
|
-
await axios.delete(`/feu/v1/sources/${get.id}`, REQ_CONFIG);
|
|
97
|
-
} catch (e) { throw e; }
|
|
98
|
-
},
|
|
99
|
-
consume: async (source, sandbox) => {
|
|
100
|
-
try {
|
|
101
|
-
const { data: sources } = await axios.post(`/feu/v1/sources/list`, {
|
|
102
|
-
provider: provider.id,
|
|
103
|
-
version: provider.version,
|
|
104
|
-
source: source,
|
|
105
|
-
sandbox: sandbox,
|
|
106
|
-
}, REQ_CONFIG);
|
|
107
|
-
return sources.map((s) => ({
|
|
108
|
-
id: s.uuid,
|
|
109
|
-
data: s.data,
|
|
110
|
-
}));
|
|
111
|
-
} catch (e) { throw e; }
|
|
112
|
-
},
|
|
113
|
-
};
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
export class Protocol {
|
|
117
|
-
|
|
118
|
-
private readonly provider: Provider;
|
|
119
|
-
private readonly configuration: Protocol.Configuration;
|
|
120
|
-
|
|
121
|
-
constructor(provider: Provider, configuration: Protocol.Configuration) {
|
|
122
|
-
const providerValidation = providerSchema().validate(provider);
|
|
123
|
-
if (providerValidation.error) { throw new Error(`Invalid provider for protocol`); }
|
|
124
|
-
this.provider = provider;
|
|
125
|
-
this.configuration = configuration;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
public evaluate = async (req: Protocol.Command): Promise<any> => {
|
|
129
|
-
try {
|
|
130
|
-
const validation = commandSchema.validate(req);
|
|
131
|
-
if (validation.error) { throw new Error(`Invalid request: ${validation.error.message}`); }
|
|
132
|
-
|
|
133
|
-
const serialize = (elem: Action | Trigger | Credentials) => ({
|
|
134
|
-
..._.omit(elem, [`functions`, `helpers`]),
|
|
135
|
-
functions: Object.keys(elem.functions),
|
|
136
|
-
helpers: Object.keys(elem.helpers),
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
let response: any;
|
|
140
|
-
switch (req.command) {
|
|
141
|
-
case `list:actions`:
|
|
142
|
-
response = Object.values(this.provider.actions || {}).map(serialize);
|
|
143
|
-
break;
|
|
144
|
-
case `list:triggers`:
|
|
145
|
-
response = Object.values(this.provider.triggers || {}).map(serialize);
|
|
146
|
-
break;
|
|
147
|
-
case `list:credentials`:
|
|
148
|
-
response = Object.values(this.provider.credentials || {}).map(serialize);
|
|
149
|
-
break;
|
|
150
|
-
case `list:sources`:
|
|
151
|
-
response = Object.values(this.provider.sources || {});
|
|
152
|
-
break;
|
|
153
|
-
case `list:locales`:
|
|
154
|
-
const i18nInstance = i18n({ directory: `${this.configuration.path}/locales` });
|
|
155
|
-
response = i18nInstance.i18n.getLocales().map((l) => {
|
|
156
|
-
i18nInstance.i18n.setLocale(l);
|
|
157
|
-
return {
|
|
158
|
-
code: l,
|
|
159
|
-
catalog: i18nInstance.i18n.getCatalog(),
|
|
160
|
-
};
|
|
161
|
-
});
|
|
162
|
-
break;
|
|
163
|
-
case `invoke`:
|
|
164
|
-
const elem = _.get(this.provider, `${req.model}s.${req.id}`);
|
|
165
|
-
if (!elem) { throw new Error(`Could not find ${req.model} with ID ${req.id}`); }
|
|
166
|
-
|
|
167
|
-
const func = _.get(elem, req.params.function);
|
|
168
|
-
if (!func || typeof func !== `function`) { throw new Error(`Invalid function ${req.params.function}`); }
|
|
169
|
-
|
|
170
|
-
const invokeInstance = await core({
|
|
171
|
-
env: req.context.environment,
|
|
172
|
-
localization: req.context.localization,
|
|
173
|
-
sources: API_SOURCES(this.provider, this.configuration.sources, {
|
|
174
|
-
organization: req.context.organization,
|
|
175
|
-
workspace: req.context.workspace,
|
|
176
|
-
}),
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
response = await func(invokeInstance, req.params.configuration);
|
|
180
|
-
break;
|
|
181
|
-
default:
|
|
182
|
-
throw new Error(`Invalid command`);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
return response;
|
|
186
|
-
} catch (e) { throw e; }
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
export namespace Protocol {
|
|
191
|
-
|
|
192
|
-
export type Model = `action` | `trigger` | `credential`;
|
|
193
|
-
|
|
194
|
-
export type Invoke = {
|
|
195
|
-
command: `invoke`,
|
|
196
|
-
model: Protocol.Model,
|
|
197
|
-
id: string,
|
|
198
|
-
params: {
|
|
199
|
-
function: string,
|
|
200
|
-
configuration: Record<string, any>,
|
|
201
|
-
},
|
|
202
|
-
context: {
|
|
203
|
-
organization: string,
|
|
204
|
-
workspace: number,
|
|
205
|
-
environment: Record<string, any>,
|
|
206
|
-
localization: {
|
|
207
|
-
locale: string,
|
|
208
|
-
catalog: Record<string, any>,
|
|
209
|
-
},
|
|
210
|
-
},
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
export type CredentialList = {
|
|
214
|
-
command: `list:credentials`,
|
|
215
|
-
};
|
|
216
|
-
|
|
217
|
-
export type ActionList = {
|
|
218
|
-
command: `list:actions`,
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
export type TriggerList = {
|
|
222
|
-
command: `list:triggers`,
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
export type SourceList = {
|
|
226
|
-
command: `list:sources`,
|
|
227
|
-
};
|
|
228
|
-
|
|
229
|
-
export type LocaleList = {
|
|
230
|
-
command: `list:locales`,
|
|
231
|
-
};
|
|
232
|
-
|
|
233
|
-
export type Command = Invoke | CredentialList | ActionList | TriggerList | SourceList | LocaleList;
|
|
234
|
-
|
|
235
|
-
export type SourcesConfiguration = {
|
|
236
|
-
host: string,
|
|
237
|
-
token: string,
|
|
238
|
-
};
|
|
239
|
-
|
|
240
|
-
export type Configuration = {
|
|
241
|
-
path: string,
|
|
242
|
-
sources: SourcesConfiguration,
|
|
243
|
-
};
|
|
244
|
-
}
|