@beseif-solutions/prow-core 0.4.5 → 1.0.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.
@@ -7,6 +7,7 @@ export type CoreConfig = {
7
7
  };
8
8
  type Configuration<Config extends CoreConfig> = ({
9
9
  sandbox: boolean;
10
+ context?: string;
10
11
  organization?: string;
11
12
  } & (Config[`inputs`] extends undefined ? {} : {
12
13
  inputs: Config[`inputs`];
@@ -19,7 +20,7 @@ type CommonConfig = Pick<CoreConfig, `credentials`> & {
19
20
  };
20
21
  export type Common<Config extends CommonConfig = {}> = {
21
22
  id: Config[`id`] extends string ? Config[`id`] : string;
22
- helpers?: Record<string, CoreFunction<{
23
+ helpers: Record<string, CoreFunction<{
23
24
  credentials: Config[`credentials`];
24
25
  inputs: any;
25
26
  outputs: any;
@@ -11,6 +11,7 @@ exports.idSchema = idSchema;
11
11
  const commonSchema = () => joi_1.default.object({
12
12
  id: (0, exports.idSchema)(),
13
13
  helpers: joi_1.default.object()
14
- .pattern(joi_1.default.string(), joi_1.default.function()),
14
+ .pattern(joi_1.default.string(), joi_1.default.function())
15
+ .required(),
15
16
  });
16
17
  exports.commonSchema = commonSchema;
package/dist/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  export { Core, core } from './core';
2
2
  export { CoreFunction, idSchema } from './entities/commons';
3
- export { Credentials, OAuthCredentials, SessionCredentials, StaticCredentials, credentialsSchema, oauthCredentialsSchema, sessionCredentialsSchema, staticCredentialsSchema } from './entities/credentials';
4
- export { Action, AsyncAction, Event, ImmediateTrigger, Request, ScheduledTrigger, SyncAction, Trigger, actionOutputSchema, actionSchema, eventSchema, immediateTriggerSchema, scheduledTriggerSchema, syncActionSchema, triggerOutputSchema, triggerSchema } from './entities/events';
3
+ export { Credentials, credentialsSchema, OAuthCredentials, oauthCredentialsSchema, SessionCredentials, sessionCredentialsSchema, StaticCredentials, staticCredentialsSchema } from './entities/credentials';
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
- export { hasExpression, isExpression, split } from './minified-utils/context';
8
- export { Condition, Field, File, SelectFieldChoice, ValidationResult, alter, extract, fieldSchema, fieldsSchema, validate } from './minified-utils/fields';
9
- export { DEFAULT_LOCALE, LocalizedField, LocalizedProperties, i18n, localizeFields, localizeGroup, localizeInputs, localizeOutputs, localizeProperties } from './minified-utils/locales';
7
+ export { getPath, hasExpression, isDynamic, isExpression, split } from './minified-utils/context';
8
+ export { alter, Condition, extract, Field, fieldSchema, fieldsSchema, File, SelectFieldChoice, validate, ValidationResult } from './minified-utils/fields';
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 { Protocol } from './minified-utils/protocol';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Protocol = exports.Properties = exports.localizeProperties = exports.localizeOutputs = exports.localizeInputs = exports.localizeGroup = exports.localizeFields = exports.i18n = exports.DEFAULT_LOCALE = exports.validate = exports.fieldsSchema = exports.fieldSchema = exports.extract = exports.alter = exports.split = exports.isExpression = exports.hasExpression = 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;
3
+ exports.Protocol = exports.Properties = exports.localizeProperties = exports.localizeOutputs = exports.localizeInputs = exports.localizeGroup = exports.localizeFields = exports.i18n = exports.DEFAULT_LOCALE = exports.validate = exports.fieldsSchema = exports.fieldSchema = exports.extract = exports.alter = 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");
@@ -22,7 +22,9 @@ Object.defineProperty(exports, "triggerSchema", { enumerable: true, get: functio
22
22
  var provider_1 = require("./entities/provider");
23
23
  Object.defineProperty(exports, "providerSchema", { enumerable: true, get: function () { return provider_1.providerSchema; } });
24
24
  var context_1 = require("./minified-utils/context");
25
+ Object.defineProperty(exports, "getPath", { enumerable: true, get: function () { return context_1.getPath; } });
25
26
  Object.defineProperty(exports, "hasExpression", { enumerable: true, get: function () { return context_1.hasExpression; } });
27
+ Object.defineProperty(exports, "isDynamic", { enumerable: true, get: function () { return context_1.isDynamic; } });
26
28
  Object.defineProperty(exports, "isExpression", { enumerable: true, get: function () { return context_1.isExpression; } });
27
29
  Object.defineProperty(exports, "split", { enumerable: true, get: function () { return context_1.split; } });
28
30
  var fields_1 = require("./minified-utils/fields");
@@ -2,8 +2,17 @@ import { Field } from "./fields";
2
2
  export declare const isExpression: (value: any) => boolean;
3
3
  export declare const hasExpression: (value: any) => boolean;
4
4
  export declare const split: (value: string) => string[];
5
+ export declare const getPath: (expression: string) => string;
6
+ type Dynamic = {
7
+ array: any[];
8
+ mapping: Record<string, {
9
+ type: `property` | `literal`;
10
+ value: any;
11
+ }>;
12
+ };
13
+ export declare const isDynamic: (data: any, processed: boolean) => data is Dynamic;
5
14
  declare class Context {
6
- readonly resolve: (field: Field, source: any, data: Record<string, any>) => any;
15
+ readonly resolve: (field: Field, source: any, data: Record<string, any>, depth?: number) => any;
7
16
  }
8
17
  declare const context: Context;
9
18
  export default context;
@@ -3,8 +3,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.split = exports.hasExpression = exports.isExpression = void 0;
6
+ exports.isDynamic = exports.getPath = exports.split = exports.hasExpression = exports.isExpression = void 0;
7
7
  const lodash_1 = __importDefault(require("lodash"));
8
+ const joi_1 = __importDefault(require("joi"));
8
9
  const IS_EXPRESSION_REGEX = /^{{2,3}[^}]+}{2,3}$/;
9
10
  const isExpression = (value) => typeof value === `string` ? IS_EXPRESSION_REGEX.test(value) : false;
10
11
  exports.isExpression = isExpression;
@@ -14,35 +15,45 @@ exports.hasExpression = hasExpression;
14
15
  const SPLIT_REGEX = /{{2,3}[^}]+}{2,3}|[^{}]+/g;
15
16
  const split = (value) => typeof value === `string` ? Array.from(value.match(SPLIT_REGEX) || []) : [];
16
17
  exports.split = split;
18
+ const getPath = (expression) => expression.replace(/^{+/g, ``).replace(/}+$/g, ``);
19
+ exports.getPath = getPath;
20
+ const isDynamic = (data, processed) => {
21
+ const schema = joi_1.default.object({
22
+ array: (processed ? joi_1.default.array() : joi_1.default.string()).required(),
23
+ mapping: joi_1.default.object()
24
+ .pattern(joi_1.default.string(), joi_1.default.object({
25
+ type: joi_1.default.string().valid(`property`, `literal`).required(),
26
+ value: joi_1.default.any().allow(null, ``).required(),
27
+ })).required(),
28
+ });
29
+ const { error } = schema.validate(data);
30
+ return !error;
31
+ };
32
+ exports.isDynamic = isDynamic;
33
+ const MAX_RESOLVE_DEPTH = 10;
17
34
  class Context {
18
35
  constructor() {
19
- this.resolve = (field, source, data) => {
20
- if (lodash_1.default.isNull(source) || lodash_1.default.isUndefined(source)) {
36
+ this.resolve = (field, source, data, depth = 0) => {
37
+ if (lodash_1.default.isNull(source) || lodash_1.default.isUndefined(source) || depth >= MAX_RESOLVE_DEPTH) {
21
38
  return source;
22
39
  }
23
40
  let serialized = false;
24
41
  let unresolved;
25
- if ((lodash_1.default.isObject(source) || lodash_1.default.isArray(source)) && field.type === `dict` && !field.items) {
42
+ const dynamicSource = (0, exports.isDynamic)(source, false);
43
+ if ((lodash_1.default.isObject(source) || lodash_1.default.isArray(source)) && field.type === `dict` && (!field.items || dynamicSource)) {
26
44
  serialized = true;
27
45
  unresolved = JSON.stringify(source);
28
46
  }
29
47
  else if (typeof source === `string`) {
30
48
  unresolved = source;
31
49
  }
32
- else {
33
- return source;
34
- }
35
50
  if (!unresolved || !(0, exports.hasExpression)(unresolved)) {
36
51
  return source;
37
52
  }
38
53
  const clonedData = lodash_1.default.cloneDeep(data);
39
- const parts = (0, exports.split)(unresolved);
40
54
  let resolved = unresolved;
41
- for (const expression of parts) {
42
- if (!(0, exports.isExpression)(expression)) {
43
- continue;
44
- }
45
- const path = expression.replace(/^{+/g, ``).replace(/}+$/g, ``);
55
+ if ((0, exports.isExpression)(unresolved)) {
56
+ const path = (0, exports.getPath)(unresolved);
46
57
  if (lodash_1.default.has(clonedData, path)) {
47
58
  const get = lodash_1.default.get(clonedData, path);
48
59
  const shouldInfer = field.as_array && lodash_1.default.isArray(get)
@@ -52,25 +63,60 @@ class Context {
52
63
  || field.type === `string` && typeof get === `string`
53
64
  || field.type === `boolean` && typeof get === `boolean`
54
65
  || field.type === `any`;
55
- if (unresolved === expression && shouldInfer) {
66
+ if (shouldInfer) {
56
67
  resolved = get;
57
- break;
58
68
  }
59
69
  else {
60
- if (serialized) {
61
- resolved = resolved.replace(`"${expression}"`, lodash_1.default.isObject(get) ? JSON.stringify(get) : `"${get}"`);
62
- }
63
- resolved = resolved.replace(expression, get);
70
+ resolved = lodash_1.default.toString(get);
64
71
  }
65
72
  }
66
73
  else {
67
- resolved = resolved.replace(expression, ``);
74
+ resolved = ``;
75
+ }
76
+ }
77
+ else {
78
+ const parts = (0, exports.split)(unresolved);
79
+ for (const expression of parts) {
80
+ if (!(0, exports.isExpression)(expression)) {
81
+ continue;
82
+ }
83
+ const path = (0, exports.getPath)(expression);
84
+ if (lodash_1.default.has(clonedData, path)) {
85
+ const get = lodash_1.default.get(clonedData, path);
86
+ if (serialized) {
87
+ resolved = resolved.replace(`"${expression}"`, (lodash_1.default.isObject(get) || lodash_1.default.isString(get)) ? JSON.stringify(get) : get);
88
+ }
89
+ resolved = resolved.replace(expression, lodash_1.default.toString(get));
90
+ }
91
+ else {
92
+ resolved = resolved.replace(expression, ``);
93
+ }
68
94
  }
69
95
  }
70
96
  const parsed = serialized ? JSON.parse(resolved) : resolved;
71
- return (typeof resolved === `string` ? resolved : JSON.stringify(resolved)).includes(`{{`) ?
72
- this.resolve(field, parsed, clonedData)
97
+ const response = (typeof resolved === `string` ? resolved : JSON.stringify(resolved)).includes(`{{`) ?
98
+ this.resolve(field, parsed, clonedData, depth + 1)
73
99
  : parsed;
100
+ if (dynamicSource && (0, exports.isDynamic)(response, true)) {
101
+ const dynamic = [];
102
+ for (const i of response.array) {
103
+ const item = {};
104
+ for (const [key, map] of Object.entries(response.mapping)) {
105
+ if (map.type === `property`) {
106
+ const prop = lodash_1.default.get(i, map.value);
107
+ if (typeof prop !== `undefined`) {
108
+ item[key] = prop;
109
+ }
110
+ }
111
+ else if (map.type === `literal`) {
112
+ item[key] = map.value;
113
+ }
114
+ }
115
+ dynamic.push(item);
116
+ }
117
+ return dynamic;
118
+ }
119
+ return response;
74
120
  };
75
121
  }
76
122
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beseif-solutions/prow-core",
3
- "version": "0.4.5",
3
+ "version": "1.0.0",
4
4
  "description": "Prow core functionalities and classes",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -9,6 +9,7 @@ export type CoreConfig = {
9
9
 
10
10
  type Configuration<Config extends CoreConfig> = ({
11
11
  sandbox: boolean,
12
+ context?: string,
12
13
  organization?: string,
13
14
  } & (
14
15
  Config[`inputs`] extends undefined ?
@@ -30,7 +31,7 @@ type CommonConfig = Pick<CoreConfig, `credentials`> & { id?: string };
30
31
 
31
32
  export type Common<Config extends CommonConfig = {}> = {
32
33
  id: Config[`id`] extends string ? Config[`id`] : string,
33
- helpers?: Record<string, CoreFunction<{ credentials: Config[`credentials`], inputs: any, outputs: any }>>,
34
+ helpers: Record<string, CoreFunction<{ credentials: Config[`credentials`], inputs: any, outputs: any }>>,
34
35
  };
35
36
 
36
37
  export const idSchema = () =>
@@ -41,5 +42,6 @@ export const commonSchema = () =>
41
42
  Joi.object({
42
43
  id: idSchema(),
43
44
  helpers: Joi.object()
44
- .pattern(Joi.string(), Joi.function()),
45
+ .pattern(Joi.string(), Joi.function())
46
+ .required(),
45
47
  });
package/src/index.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  export { Core, core } from './core';
2
2
  export { CoreFunction, idSchema } from './entities/commons';
3
- export { Credentials, OAuthCredentials, SessionCredentials, StaticCredentials, credentialsSchema, oauthCredentialsSchema, sessionCredentialsSchema, staticCredentialsSchema } from './entities/credentials';
4
- export { Action, AsyncAction, Event, ImmediateTrigger, Request, ScheduledTrigger, SyncAction, Trigger, actionOutputSchema, actionSchema, eventSchema, immediateTriggerSchema, scheduledTriggerSchema, syncActionSchema, triggerOutputSchema, triggerSchema } from './entities/events';
3
+ export { Credentials, credentialsSchema, OAuthCredentials, oauthCredentialsSchema, SessionCredentials, sessionCredentialsSchema, StaticCredentials, staticCredentialsSchema } from './entities/credentials';
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
- export { hasExpression, isExpression, split } from './minified-utils/context';
8
- export { Condition, Field, File, SelectFieldChoice, ValidationResult, alter, extract, fieldSchema, fieldsSchema, validate } from './minified-utils/fields';
9
- export { DEFAULT_LOCALE, LocalizedField, LocalizedProperties, i18n, localizeFields, localizeGroup, localizeInputs, localizeOutputs, localizeProperties } from './minified-utils/locales';
7
+ export { getPath, hasExpression, isDynamic, isExpression, split } from './minified-utils/context';
8
+ export { alter, Condition, extract, Field, fieldSchema, fieldsSchema, File, SelectFieldChoice, validate, ValidationResult } from './minified-utils/fields';
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
- export { Protocol } from './minified-utils/protocol';
11
+ export { Protocol } from './minified-utils/protocol';
@@ -1,5 +1,6 @@
1
1
  import _ from "lodash";
2
2
  import { Field } from "./fields";
3
+ import Joi from "joi";
3
4
 
4
5
  const IS_EXPRESSION_REGEX = /^{{2,3}[^}]+}{2,3}$/;
5
6
  export const isExpression = (value: any) =>
@@ -13,35 +14,60 @@ const SPLIT_REGEX = /{{2,3}[^}]+}{2,3}|[^{}]+/g;
13
14
  export const split = (value: string) =>
14
15
  typeof value === `string` ? Array.from(value.match(SPLIT_REGEX) || []) : [];
15
16
 
17
+ export const getPath = (expression: string) =>
18
+ expression.replace(/^{+/g, ``).replace(/}+$/g, ``);
19
+
20
+ type Dynamic = {
21
+ array: any[],
22
+ mapping: Record<string, {
23
+ type: `property` | `literal`,
24
+ value: any,
25
+ }>,
26
+ };
27
+
28
+ export const isDynamic = (data: any, processed: boolean): data is Dynamic => {
29
+ const schema = Joi.object({
30
+ array: (processed ? Joi.array() : Joi.string()).required(),
31
+ mapping: Joi.object()
32
+ .pattern(Joi.string(), Joi.object({
33
+ type: Joi.string().valid(`property`, `literal`).required(),
34
+ value: Joi.any().allow(null, ``).required(),
35
+ })).required(),
36
+ });
37
+
38
+ const { error } = schema.validate(data);
39
+ return !error;
40
+ };
41
+
42
+ const MAX_RESOLVE_DEPTH = 10;
43
+
16
44
  class Context {
17
45
 
18
- public readonly resolve = (field: Field, source: any, data: Record<string, any>) => {
19
- if (_.isNull(source) || _.isUndefined(source)) { return source; }
46
+ public readonly resolve = (field: Field, source: any, data: Record<string, any>, depth = 0) => {
47
+ if (_.isNull(source) || _.isUndefined(source) || depth >= MAX_RESOLVE_DEPTH) { return source; }
20
48
 
21
49
  let serialized = false;
22
50
  let unresolved: string;
23
- if ((_.isObject(source) || _.isArray(source)) && field.type === `dict` && !field.items) {
51
+
52
+ const dynamicSource = isDynamic(source, false);
53
+
54
+ if ((_.isObject(source) || _.isArray(source)) && field.type === `dict` && (!field.items || dynamicSource)) {
24
55
  serialized = true;
25
56
  unresolved = JSON.stringify(source);
26
57
  } else if (typeof source === `string`) {
27
58
  unresolved = source;
28
- } else { return source; }
59
+ }
29
60
 
30
61
  if (!unresolved || !hasExpression(unresolved)) { return source; }
31
62
 
32
63
  const clonedData = _.cloneDeep(data);
33
64
 
34
- const parts = split(unresolved);
35
-
36
65
  let resolved: any = unresolved;
37
- for (const expression of parts) {
38
- if (!isExpression(expression)) { continue; }
39
-
40
- const path = expression.replace(/^{+/g, ``).replace(/}+$/g, ``);
41
-
66
+ if (isExpression(unresolved)) {
67
+ // full expression
68
+ const path = getPath(unresolved);
42
69
  if (_.has(clonedData, path)) {
43
70
  const get = _.get(clonedData, path);
44
-
45
71
  const shouldInfer =
46
72
  field.as_array && _.isArray(get)
47
73
  || field.type === `dict` && _.isObject(get)
@@ -51,23 +77,55 @@ class Context {
51
77
  || field.type === `boolean` && typeof get === `boolean`
52
78
  || field.type === `any`;
53
79
 
54
- if (unresolved === expression && shouldInfer) {
80
+ if (shouldInfer) {
55
81
  resolved = get;
56
- break;
57
82
  } else {
58
- if (serialized) { resolved = resolved.replace(`"${expression}"`, _.isObject(get) ? JSON.stringify(get) : `"${get}"`); }
59
- resolved = resolved.replace(expression, get);
60
-
83
+ resolved = _.toString(get);
61
84
  }
62
- } else { resolved = resolved.replace(expression, ``); }
85
+ } else { resolved = ``; }
86
+ } else {
87
+ // partial expression
88
+ const parts = split(unresolved);
89
+ for (const expression of parts) {
90
+ if (!isExpression(expression)) { continue; }
91
+
92
+ const path = getPath(expression);
93
+ if (_.has(clonedData, path)) {
94
+ const get = _.get(clonedData, path);
95
+ if (serialized) { resolved = resolved.replace(`"${expression}"`, (_.isObject(get) || _.isString(get)) ? JSON.stringify(get) : get); }
96
+ resolved = resolved.replace(expression, _.toString(get));
97
+ } else { resolved = resolved.replace(expression, ``); }
98
+ }
63
99
  }
64
100
 
65
101
  const parsed = serialized ? JSON.parse(resolved) : resolved;
66
102
 
67
- // recursive resolution
68
- return (typeof resolved === `string` ? resolved : JSON.stringify(resolved)).includes(`{{`) ?
69
- this.resolve(field, parsed, clonedData)
103
+ const response = (typeof resolved === `string` ? resolved : JSON.stringify(resolved)).includes(`{{`) ?
104
+ this.resolve(field, parsed, clonedData, depth + 1)
70
105
  : parsed;
106
+
107
+ // check dynamic arrays
108
+ if (dynamicSource && isDynamic(response, true)) {
109
+ const dynamic = [];
110
+ for (const i of response.array) {
111
+ const item: Record<string, any> = {};
112
+ for (const [key, map] of Object.entries(response.mapping)) {
113
+ if (map.type === `property`) {
114
+ const prop = _.get(i, map.value);
115
+ if (typeof prop !== `undefined`) { item[key] = prop; }
116
+ } else if (map.type === `literal`) {
117
+ item[key] = map.value;
118
+ }
119
+ }
120
+ dynamic.push(item);
121
+ }
122
+
123
+ return dynamic;
124
+ }
125
+
126
+
127
+ // recursive resolution
128
+ return response;
71
129
  };
72
130
 
73
131
  }