@beseif-solutions/prow-core 0.4.4 → 0.4.6

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;
@@ -2,6 +2,7 @@ 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;
5
6
  declare class Context {
6
7
  readonly resolve: (field: Field, source: any, data: Record<string, any>) => any;
7
8
  }
@@ -3,7 +3,7 @@ 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.getPath = exports.split = exports.hasExpression = exports.isExpression = void 0;
7
7
  const lodash_1 = __importDefault(require("lodash"));
8
8
  const IS_EXPRESSION_REGEX = /^{{2,3}[^}]+}{2,3}$/;
9
9
  const isExpression = (value) => typeof value === `string` ? IS_EXPRESSION_REGEX.test(value) : false;
@@ -14,6 +14,8 @@ exports.hasExpression = hasExpression;
14
14
  const SPLIT_REGEX = /{{2,3}[^}]+}{2,3}|[^{}]+/g;
15
15
  const split = (value) => typeof value === `string` ? Array.from(value.match(SPLIT_REGEX) || []) : [];
16
16
  exports.split = split;
17
+ const getPath = (expression) => expression.replace(/^{+/g, ``).replace(/}+$/g, ``);
18
+ exports.getPath = getPath;
17
19
  class Context {
18
20
  constructor() {
19
21
  this.resolve = (field, source, data) => {
@@ -29,20 +31,13 @@ class Context {
29
31
  else if (typeof source === `string`) {
30
32
  unresolved = source;
31
33
  }
32
- else {
33
- return source;
34
- }
35
34
  if (!unresolved || !(0, exports.hasExpression)(unresolved)) {
36
35
  return source;
37
36
  }
38
37
  const clonedData = lodash_1.default.cloneDeep(data);
39
- const parts = (0, exports.split)(unresolved);
40
38
  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, ``);
39
+ if ((0, exports.isExpression)(unresolved)) {
40
+ const path = (0, exports.getPath)(unresolved);
46
41
  if (lodash_1.default.has(clonedData, path)) {
47
42
  const get = lodash_1.default.get(clonedData, path);
48
43
  const shouldInfer = field.as_array && lodash_1.default.isArray(get)
@@ -52,19 +47,34 @@ class Context {
52
47
  || field.type === `string` && typeof get === `string`
53
48
  || field.type === `boolean` && typeof get === `boolean`
54
49
  || field.type === `any`;
55
- if (unresolved === expression && shouldInfer) {
50
+ if (shouldInfer) {
56
51
  resolved = get;
57
- break;
58
52
  }
59
53
  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);
54
+ resolved = lodash_1.default.toString(get);
64
55
  }
65
56
  }
66
57
  else {
67
- resolved = resolved.replace(expression, ``);
58
+ resolved = ``;
59
+ }
60
+ }
61
+ else {
62
+ const parts = (0, exports.split)(unresolved);
63
+ for (const expression of parts) {
64
+ if (!(0, exports.isExpression)(expression)) {
65
+ continue;
66
+ }
67
+ const path = (0, exports.getPath)(expression);
68
+ if (lodash_1.default.has(clonedData, path)) {
69
+ const get = lodash_1.default.get(clonedData, path);
70
+ if (serialized) {
71
+ resolved = resolved.replace(`"${expression}"`, (lodash_1.default.isObject(get) || lodash_1.default.isString(get)) ? JSON.stringify(get) : get);
72
+ }
73
+ resolved = resolved.replace(expression, lodash_1.default.toString(get));
74
+ }
75
+ else {
76
+ resolved = resolved.replace(expression, ``);
77
+ }
68
78
  }
69
79
  }
70
80
  const parsed = serialized ? JSON.parse(resolved) : resolved;
@@ -58,13 +58,14 @@ const defaultSchema = (type) => joi_1.default.when(`as_array`, {
58
58
  then: joi_1.default.array().items(type),
59
59
  otherwise: type,
60
60
  });
61
- const anySchema = () => {
61
+ const anySchema = (nullish = true) => {
62
62
  const randId = Math.random().toString(36).substring(2, 15);
63
- return joi_1.default.alternatives(joi_1.default.string(), joi_1.default.bool(), joi_1.default.number(), joi_1.default.array().items(joi_1.default.link(`#${randId}`)), joi_1.default.object().pattern(joi_1.default.string(), joi_1.default.link(`#${randId}`)))
63
+ return joi_1.default.alternatives(joi_1.default.string(), joi_1.default.bool(), joi_1.default.number(), joi_1.default.array().items(joi_1.default.link(`#${randId}`)), joi_1.default.object().pattern(joi_1.default.string(), joi_1.default.link(`#${randId}`)), ...nullish ? [joi_1.default.valid(null, ``)] : [])
64
64
  .id(randId);
65
65
  };
66
66
  const anyInputFieldSchema = () => joi_1.default.object({
67
67
  default: defaultSchema(anySchema()),
68
+ allow_nullish: joi_1.default.bool().default(true),
68
69
  })
69
70
  .concat(joi_1.default.object({
70
71
  format: joi_1.default.string().valid(`select`),
@@ -248,10 +249,7 @@ const getSimpleFieldSchema = (field) => {
248
249
  let typeSchema;
249
250
  switch (field.type) {
250
251
  case `any`:
251
- typeSchema = anySchema();
252
- if (field.allow_nullish) {
253
- typeSchema = typeSchema.allow(null, ``, 0);
254
- }
252
+ typeSchema = anySchema(field.allow_nullish);
255
253
  break;
256
254
  case `boolean`:
257
255
  typeSchema = joi_1.default.bool();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beseif-solutions/prow-core",
3
- "version": "0.4.4",
3
+ "version": "0.4.6",
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
  });
@@ -13,6 +13,9 @@ const SPLIT_REGEX = /{{2,3}[^}]+}{2,3}|[^{}]+/g;
13
13
  export const split = (value: string) =>
14
14
  typeof value === `string` ? Array.from(value.match(SPLIT_REGEX) || []) : [];
15
15
 
16
+ export const getPath = (expression: string) =>
17
+ expression.replace(/^{+/g, ``).replace(/}+$/g, ``);
18
+
16
19
  class Context {
17
20
 
18
21
  public readonly resolve = (field: Field, source: any, data: Record<string, any>) => {
@@ -25,23 +28,18 @@ class Context {
25
28
  unresolved = JSON.stringify(source);
26
29
  } else if (typeof source === `string`) {
27
30
  unresolved = source;
28
- } else { return source; }
31
+ }
29
32
 
30
33
  if (!unresolved || !hasExpression(unresolved)) { return source; }
31
34
 
32
35
  const clonedData = _.cloneDeep(data);
33
36
 
34
- const parts = split(unresolved);
35
-
36
37
  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
-
38
+ if (isExpression(unresolved)) {
39
+ // full expression
40
+ const path = getPath(unresolved);
42
41
  if (_.has(clonedData, path)) {
43
42
  const get = _.get(clonedData, path);
44
-
45
43
  const shouldInfer =
46
44
  field.as_array && _.isArray(get)
47
45
  || field.type === `dict` && _.isObject(get)
@@ -51,15 +49,25 @@ class Context {
51
49
  || field.type === `boolean` && typeof get === `boolean`
52
50
  || field.type === `any`;
53
51
 
54
- if (unresolved === expression && shouldInfer) {
52
+ if (shouldInfer) {
55
53
  resolved = get;
56
- break;
57
54
  } else {
58
- if (serialized) { resolved = resolved.replace(`"${expression}"`, _.isObject(get) ? JSON.stringify(get) : `"${get}"`); }
59
- resolved = resolved.replace(expression, get);
60
-
55
+ resolved = _.toString(get);
61
56
  }
62
- } else { resolved = resolved.replace(expression, ``); }
57
+ } else { resolved = ``; }
58
+ } else {
59
+ // partial expression
60
+ const parts = split(unresolved);
61
+ for (const expression of parts) {
62
+ if (!isExpression(expression)) { continue; }
63
+
64
+ const path = getPath(expression);
65
+ if (_.has(clonedData, path)) {
66
+ const get = _.get(clonedData, path);
67
+ if (serialized) { resolved = resolved.replace(`"${expression}"`, (_.isObject(get) || _.isString(get)) ? JSON.stringify(get) : get); }
68
+ resolved = resolved.replace(expression, _.toString(get));
69
+ } else { resolved = resolved.replace(expression, ``); }
70
+ }
63
71
  }
64
72
 
65
73
  const parsed = serialized ? JSON.parse(resolved) : resolved;
@@ -249,7 +249,7 @@ const defaultSchema = (type: Joi.Schema) =>
249
249
  otherwise: type,
250
250
  });
251
251
 
252
- const anySchema = () => {
252
+ const anySchema = (nullish = true) => {
253
253
  // eslint-disable-next-line @typescript-eslint/no-magic-numbers
254
254
  const randId = Math.random().toString(36).substring(2, 15);
255
255
  return Joi.alternatives(
@@ -257,13 +257,16 @@ const anySchema = () => {
257
257
  Joi.bool(),
258
258
  Joi.number(),
259
259
  Joi.array().items(Joi.link(`#${randId}`)),
260
- Joi.object().pattern(Joi.string(), Joi.link(`#${randId}`)))
260
+ Joi.object().pattern(Joi.string(), Joi.link(`#${randId}`)),
261
+ ...nullish ? [Joi.valid(null, ``)] : [],
262
+ )
261
263
  .id(randId);
262
264
  };
263
265
 
264
266
  const anyInputFieldSchema = () =>
265
267
  Joi.object({
266
268
  default: defaultSchema(anySchema()),
269
+ allow_nullish: Joi.bool().default(true),
267
270
  })
268
271
  .concat(Joi.object({
269
272
  format: Joi.string().valid(`select`),
@@ -474,9 +477,7 @@ const getSimpleFieldSchema = (field: Field) => {
474
477
  let typeSchema: Joi.Schema;
475
478
  switch (field.type) {
476
479
  case `any`:
477
- typeSchema = anySchema();
478
- // allow null values for any type
479
- if (field.allow_nullish) { typeSchema = typeSchema.allow(null, ``, 0); }
480
+ typeSchema = anySchema(field.allow_nullish);
480
481
  break;
481
482
  case `boolean`:
482
483
  typeSchema = Joi.bool();