@beseif-solutions/prow-core 0.0.39 → 0.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.
@@ -26,8 +26,11 @@ type EventConfig = Pick<CoreConfig, `credentials` | `outputs`> & {
26
26
  outputs: string[];
27
27
  };
28
28
  sources?: string[];
29
+ fields?: Record<string, any>;
29
30
  };
30
- type CommonEvents<Config extends EventConfig = {}> = Common<Config> & {
31
+ type CommonEvents<Config extends EventConfig = {
32
+ fields: Record<string, any>;
33
+ }> = Common<Config> & {
31
34
  model: `event`;
32
35
  categorization: {
33
36
  department: string;
@@ -49,7 +52,9 @@ export type Request = {
49
52
  query: Record<string, string>;
50
53
  body: any;
51
54
  };
52
- export type ImmediateTrigger<Config extends EventConfig = {}> = CommonEvents<Config> & {
55
+ export type ImmediateTrigger<Config extends EventConfig = {
56
+ fields: Record<string, any>;
57
+ }> = CommonEvents<Config> & {
53
58
  type: `trigger`;
54
59
  immediate: true;
55
60
  outputs: [DefaultConnectableEvent<Config[`flags`][`outputs`][number]>];
@@ -57,7 +62,7 @@ export type ImmediateTrigger<Config extends EventConfig = {}> = CommonEvents<Con
57
62
  mount?: CoreFunction<{
58
63
  credentials: Config[`credentials`];
59
64
  inputs: {
60
- fields: Record<string, any>;
65
+ fields: Config[`fields`];
61
66
  link: string;
62
67
  };
63
68
  outputs: {
@@ -68,7 +73,7 @@ export type ImmediateTrigger<Config extends EventConfig = {}> = CommonEvents<Con
68
73
  unmount?: CoreFunction<{
69
74
  credentials: Config[`credentials`];
70
75
  inputs: {
71
- fields: Record<string, any>;
76
+ fields: Config[`fields`];
72
77
  link: string;
73
78
  setup?: any;
74
79
  };
@@ -79,7 +84,7 @@ export type ImmediateTrigger<Config extends EventConfig = {}> = CommonEvents<Con
79
84
  challenge?: CoreFunction<{
80
85
  credentials: Config[`credentials`];
81
86
  inputs: {
82
- fields: Record<string, any>;
87
+ fields: Config[`fields`];
83
88
  link: string;
84
89
  request: Request;
85
90
  setup?: any;
@@ -92,7 +97,7 @@ export type ImmediateTrigger<Config extends EventConfig = {}> = CommonEvents<Con
92
97
  handle: CoreFunction<{
93
98
  credentials: Config[`credentials`];
94
99
  inputs: {
95
- fields: Record<string, any>;
100
+ fields: Config[`fields`];
96
101
  request: Request;
97
102
  setup?: any;
98
103
  };
@@ -104,7 +109,7 @@ export type ImmediateTrigger<Config extends EventConfig = {}> = CommonEvents<Con
104
109
  fire?: CoreFunction<{
105
110
  credentials: Config[`credentials`];
106
111
  inputs: {
107
- fields: Record<string, any>;
112
+ fields: Config[`fields`];
108
113
  link: string;
109
114
  setup?: any;
110
115
  };
@@ -115,7 +120,7 @@ export type ImmediateTrigger<Config extends EventConfig = {}> = CommonEvents<Con
115
120
  poll?: CoreFunction<{
116
121
  credentials: Config[`credentials`];
117
122
  inputs: {
118
- fields: Record<string, any>;
123
+ fields: Config[`fields`];
119
124
  last_schedule?: string;
120
125
  limit?: number;
121
126
  };
@@ -126,7 +131,9 @@ export type ImmediateTrigger<Config extends EventConfig = {}> = CommonEvents<Con
126
131
  }>;
127
132
  };
128
133
  };
129
- export type ScheduledTrigger<Config extends EventConfig = {}> = CommonEvents<Config> & {
134
+ export type ScheduledTrigger<Config extends EventConfig = {
135
+ fields: Record<string, any>;
136
+ }> = CommonEvents<Config> & {
130
137
  type: `trigger`;
131
138
  immediate: false;
132
139
  outputs: [DefaultConnectableEvent<Config[`flags`][`outputs`][number]>];
@@ -134,7 +141,7 @@ export type ScheduledTrigger<Config extends EventConfig = {}> = CommonEvents<Con
134
141
  poll: CoreFunction<{
135
142
  credentials: Config[`credentials`];
136
143
  inputs: {
137
- fields: Record<string, any>;
144
+ fields: Config[`fields`];
138
145
  last_schedule?: string;
139
146
  limit?: number;
140
147
  };
@@ -145,8 +152,12 @@ export type ScheduledTrigger<Config extends EventConfig = {}> = CommonEvents<Con
145
152
  }>;
146
153
  };
147
154
  };
148
- export type Trigger<Config extends EventConfig = {}> = ImmediateTrigger<Config> | ScheduledTrigger<Config>;
149
- export type Action<Config extends EventConfig = {}> = CommonEvents<Config> & {
155
+ export type Trigger<Config extends EventConfig = {
156
+ fields: Record<string, any>;
157
+ }> = ImmediateTrigger<Config> | ScheduledTrigger<Config>;
158
+ export type Action<Config extends EventConfig = {
159
+ fields: Record<string, any>;
160
+ }> = CommonEvents<Config> & {
150
161
  type: `action`;
151
162
  inputs: [DefaultConnectableEvent<Config[`flags`][`inputs`][number]>, ...AdditionalConnectableEvent<Config[`flags`][`inputs`][number]>[]];
152
163
  outputs: [DefaultConnectableEvent<Config[`flags`][`outputs`][number]>, ...(AdditionalConnectableEvent<Config[`flags`][`outputs`][number]> | ErrorConnectableEvent<Config[`flags`][`outputs`][number]>)[]];
@@ -154,7 +165,7 @@ export type Action<Config extends EventConfig = {}> = CommonEvents<Config> & {
154
165
  execute: CoreFunction<{
155
166
  credentials: Config[`credentials`];
156
167
  inputs: {
157
- fields: Record<string, any>;
168
+ fields: Config[`fields`];
158
169
  flags: Partial<Record<Config[`flags`][`inputs`][number], true>>;
159
170
  };
160
171
  outputs: {
@@ -164,7 +175,9 @@ export type Action<Config extends EventConfig = {}> = CommonEvents<Config> & {
164
175
  }>;
165
176
  };
166
177
  };
167
- export type Event<Config extends EventConfig = {}> = Action<Config> | Trigger<Config>;
178
+ export type Event<Config extends EventConfig = {
179
+ fields: Record<string, any>;
180
+ }> = Action<Config> | Trigger<Config>;
168
181
  export declare const scheduledTriggerSchema: () => Joi.ObjectSchema<any>;
169
182
  export declare const immediateTriggerSchema: () => Joi.ObjectSchema<any>;
170
183
  export declare const triggerSchema: () => Joi.AlternativesSchema<any>;
package/dist/index.d.ts CHANGED
@@ -4,7 +4,7 @@ export { Credentials, credentialsSchema, OAuthCredentials, oauthCredentialsSchem
4
4
  export { Action, actionOutputSchema, actionSchema, Event, eventSchema, ImmediateTrigger, immediateTriggerSchema, Request, ScheduledTrigger, scheduledTriggerSchema, Trigger, triggerOutputSchema, triggerSchema } from './entities/events';
5
5
  export { Provider, providerSchema } from './entities/provider';
6
6
  export { Source } from './entities/source';
7
- export { extract, Field, fieldSchema, fieldsSchema, File, SelectFieldChoice, validate, ValidationResult } from './minified-utils/fields';
7
+ export { alter, extract, Field, fieldSchema, fieldsSchema, File, SelectFieldChoice, validate, ValidationResult } from './minified-utils/fields';
8
8
  export { i18n, LocalizedField, LocalizedProperties, localizeFields, localizeGroup, localizeInputs, localizeOutputs, localizeProperties } from './minified-utils/locales';
9
9
  export { Properties } from './minified-utils/properties';
10
10
  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.validate = exports.fieldsSchema = exports.fieldSchema = exports.extract = exports.providerSchema = exports.triggerSchema = exports.triggerOutputSchema = 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.validate = exports.fieldsSchema = exports.fieldSchema = exports.extract = exports.alter = exports.providerSchema = exports.triggerSchema = exports.triggerOutputSchema = 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");
@@ -21,6 +21,7 @@ Object.defineProperty(exports, "triggerSchema", { enumerable: true, get: functio
21
21
  var provider_1 = require("./entities/provider");
22
22
  Object.defineProperty(exports, "providerSchema", { enumerable: true, get: function () { return provider_1.providerSchema; } });
23
23
  var fields_1 = require("./minified-utils/fields");
24
+ Object.defineProperty(exports, "alter", { enumerable: true, get: function () { return fields_1.alter; } });
24
25
  Object.defineProperty(exports, "extract", { enumerable: true, get: function () { return fields_1.extract; } });
25
26
  Object.defineProperty(exports, "fieldSchema", { enumerable: true, get: function () { return fields_1.fieldSchema; } });
26
27
  Object.defineProperty(exports, "fieldsSchema", { enumerable: true, get: function () { return fields_1.fieldsSchema; } });
@@ -1,18 +1,16 @@
1
1
  import Joi from "joi";
2
- import { OneOf } from "./types";
3
2
  import { Where } from "./where";
4
3
  export type Condition = {
5
4
  condition: Where;
6
- } & OneOf<{
7
5
  overrides: Partial<Field>;
8
- show: boolean;
9
- }>;
6
+ };
10
7
  type Common = {
11
8
  key: string;
12
9
  altered_by?: Condition[];
13
10
  disabled?: boolean;
14
11
  required?: boolean;
15
12
  as_password?: boolean;
13
+ show?: boolean;
16
14
  show_label?: boolean;
17
15
  } & ({
18
16
  as_array?: false;
@@ -30,6 +28,7 @@ type Any = string | number | boolean | Any[] | {
30
28
  type AnyInputField<Extend = Record<never, never>> = {
31
29
  type: `any`;
32
30
  default?: Any | Any[];
31
+ allow_nullish?: boolean;
33
32
  } & (SelectField<Any, Extend> | {});
34
33
  type StringInputField<Extend = Record<never, never>> = {
35
34
  type: `string`;
@@ -127,6 +126,7 @@ export type ValidationResult<Extended = Record<string, never>> = {
127
126
  valid: boolean;
128
127
  fields: Field<Extended & ValidationExtended>[];
129
128
  };
129
+ export declare const alter: (field: Field, relative: string, data: Record<string, any>) => Field<Record<never, never>>;
130
130
  export declare const validate: <I>(fields: Field<I>[], data: Record<string, any>, options?: {
131
131
  secure?: boolean;
132
132
  break?: boolean;
@@ -3,23 +3,23 @@ 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.extract = exports.validate = exports.fieldsSchema = exports.fieldSchema = void 0;
6
+ exports.extract = exports.validate = exports.alter = exports.fieldsSchema = exports.fieldSchema = void 0;
7
7
  const joi_1 = __importDefault(require("joi"));
8
8
  const lodash_1 = __importDefault(require("lodash"));
9
9
  const moment_timezone_1 = __importDefault(require("moment-timezone"));
10
10
  const context_1 = __importDefault(require("./context"));
11
11
  const where_1 = require("./where");
12
12
  const conditionSchema = () => joi_1.default.object({
13
- condition: joi_1.default.object(),
14
- overrides: joi_1.default.object(),
15
- show: joi_1.default.bool(),
16
- }).xor(`overrides`, `show`);
13
+ condition: joi_1.default.object().required(),
14
+ overrides: joi_1.default.object().required(),
15
+ });
17
16
  const commonFieldSchema = () => joi_1.default.object({
18
17
  key: joi_1.default.string().required(),
19
18
  altered_by: joi_1.default.array().items(conditionSchema()),
20
19
  disabled: joi_1.default.bool(),
21
20
  required: joi_1.default.bool(),
22
21
  as_password: joi_1.default.bool(),
22
+ show: joi_1.default.bool(),
23
23
  show_label: joi_1.default.bool().default(true),
24
24
  as_array: joi_1.default.bool(),
25
25
  array_min: joi_1.default.when(`as_array`, {
@@ -173,7 +173,7 @@ const fileReplacer = (field) => ({
173
173
  },
174
174
  ],
175
175
  default: field.default,
176
- ...lodash_1.default.pick(field, [`altered_by`, `disabled`, `required`, `as_password`, `show_label`, `as_array`, `array_min`, `array_max`, `array_length`]),
176
+ ...lodash_1.default.pick(field, [`altered_by`, `disabled`, `required`, `as_password`, `show`, `show_label`, `as_array`, `array_min`, `array_max`, `array_length`]),
177
177
  });
178
178
  const fileInputFieldSchema = () => joi_1.default.object({
179
179
  default: defaultSchema(fileSchema()),
@@ -235,6 +235,9 @@ const getSimpleFieldSchema = (field) => {
235
235
  switch (field.type) {
236
236
  case `any`:
237
237
  typeSchema = anySchema();
238
+ if (field.allow_nullish) {
239
+ typeSchema = typeSchema.allow(null, ``, 0, undefined);
240
+ }
238
241
  break;
239
242
  case `boolean`:
240
243
  typeSchema = joi_1.default.bool();
@@ -366,10 +369,13 @@ const getObjectFieldSchema = (field, items) => {
366
369
  return getGeneralSchema(field, schema);
367
370
  };
368
371
  const getGeneralSchema = (field, schema) => {
372
+ if (field.required) {
373
+ schema = schema.required();
374
+ }
369
375
  if (field.disabled) {
370
376
  schema = schema.forbidden();
371
377
  }
372
- return field.required ? schema.required() : schema;
378
+ return schema;
373
379
  };
374
380
  const convertPath = (parts) => parts.map((p, i) => typeof p === `string` ? (i === 0 ? p : `.${p}`) : `[${p}]`).join(``);
375
381
  const secure = async (field, validation) => field.as_password ? lodash_1.default.omit(validation, [`value`, `original`]) : validation;
@@ -389,9 +395,31 @@ const relative_condition = (condition, relative) => {
389
395
  throw e;
390
396
  }
391
397
  };
398
+ const alter = (field, relative, data) => {
399
+ const cloned = lodash_1.default.cloneDeep(field);
400
+ for (const alteration of cloned.altered_by) {
401
+ const condition = relative_condition(alteration.condition, relative);
402
+ const matches = (0, where_1.where)(data, [condition]);
403
+ if (matches) {
404
+ lodash_1.default.assign(cloned, alteration.overrides);
405
+ }
406
+ }
407
+ return cloned;
408
+ };
409
+ exports.alter = alter;
392
410
  const recursive_schema = async (field, data, options) => {
393
411
  try {
394
- const newField = field.type === `file` ? fileReplacer(field) : lodash_1.default.cloneDeep(field);
412
+ let newField = lodash_1.default.cloneDeep(field);
413
+ if (newField.altered_by?.length > 0) {
414
+ newField = (0, exports.alter)(newField, options.relative, data);
415
+ if (options.alter) {
416
+ delete newField.altered_by;
417
+ }
418
+ }
419
+ const alteredField = lodash_1.default.cloneDeep(newField);
420
+ if (newField.type === `file`) {
421
+ newField = fileReplacer(newField);
422
+ }
395
423
  const relativeKey = options.relative ?
396
424
  options.relative.endsWith(`]`) ?
397
425
  options.array ? options.relative : `${options.relative}.${newField.key}`
@@ -405,7 +433,7 @@ const recursive_schema = async (field, data, options) => {
405
433
  const itemSchemas = [];
406
434
  if (lodash_1.default.isArray(resolved)) {
407
435
  for (let i = 0; i < (resolved || []).length; i++) {
408
- const itemSchema = await recursive_schema(lodash_1.default.omit(newField, [`as_array`, `array_min`, `array_max`, `array_length`]), data, { relative: `${relativeKey}[${i}]`, array: true, context: options.context });
436
+ const { schema: itemSchema } = await recursive_schema(lodash_1.default.omit(newField, [`as_array`, `array_min`, `array_max`, `array_length`]), data, { alter: false, relative: `${relativeKey}[${i}]`, array: true, context: options.context });
409
437
  if (itemSchema) {
410
438
  itemSchemas.push(itemSchema);
411
439
  }
@@ -414,16 +442,17 @@ const recursive_schema = async (field, data, options) => {
414
442
  calculatedSchema = getArrayFieldSchema(newField, itemSchemas);
415
443
  }
416
444
  else if (newField.type === `dict` && newField.items) {
417
- const itemSchemas = [];
445
+ const items = [];
418
446
  if (lodash_1.default.isObject(resolved)) {
419
447
  for (const item of newField.items) {
420
- const itemSchema = await recursive_schema(item, data, { relative: relativeKey, context: options.context });
421
- if (itemSchema) {
422
- itemSchemas.push({ key: item.key, schema: itemSchema });
448
+ const recursive = await recursive_schema(item, data, { alter: options.alter && true, relative: relativeKey, context: options.context });
449
+ if (recursive) {
450
+ items.push({ key: item.key, schema: recursive.schema, field: recursive.field });
423
451
  }
424
452
  }
425
453
  }
426
- calculatedSchema = getObjectFieldSchema(newField, itemSchemas);
454
+ calculatedSchema = getObjectFieldSchema(newField, items);
455
+ newField.items = items.map((i) => i.field);
427
456
  }
428
457
  else {
429
458
  calculatedSchema = getSimpleFieldSchema(newField);
@@ -431,27 +460,14 @@ const recursive_schema = async (field, data, options) => {
431
460
  if (!calculatedSchema) {
432
461
  throw new Error(`Could not resolve schema for field ${newField.key}`);
433
462
  }
434
- if (newField.altered_by?.length > 0) {
435
- let hide = false;
436
- for (const alteration of newField.altered_by) {
437
- const condition = relative_condition(alteration.condition, options.relative);
438
- const matches = (0, where_1.where)(data, [condition]);
439
- if (matches) {
440
- if (`overrides` in alteration) {
441
- lodash_1.default.assign(newField, alteration.overrides);
442
- }
443
- else if (`show` in alteration) {
444
- hide = !alteration.show;
445
- }
446
- }
447
- }
448
- delete newField.altered_by;
449
- if (hide) {
450
- lodash_1.default.unset(data, relativeKey);
451
- return;
452
- }
463
+ if (typeof newField.show === `boolean` && !newField.show) {
464
+ lodash_1.default.unset(data, relativeKey);
465
+ return;
453
466
  }
454
- return calculatedSchema;
467
+ else if (newField.disabled) {
468
+ lodash_1.default.unset(data, relativeKey);
469
+ }
470
+ return { schema: calculatedSchema, field: field.type === `file` ? alteredField : newField };
455
471
  }
456
472
  catch (e) {
457
473
  throw e;
@@ -463,12 +479,15 @@ const validate_internal = async (fields, data, options) => {
463
479
  for (const field of fields) {
464
480
  const value = lodash_1.default.get(data, field.key, field.default);
465
481
  const cloned = lodash_1.default.cloneDeep(data);
466
- const schema = await recursive_schema(field, cloned, { context: options.context });
482
+ const recursive = await recursive_schema(field, cloned, { alter: true, context: options.context });
483
+ if (!recursive) {
484
+ continue;
485
+ }
467
486
  const resolved = lodash_1.default.get(cloned, field.key, field.default);
468
487
  let validation;
469
488
  let error;
470
489
  try {
471
- validation = await schema.validateAsync(resolved, { abortEarly: false });
490
+ validation = await recursive.schema.validateAsync(resolved, { abortEarly: false });
472
491
  }
473
492
  catch (e) {
474
493
  error = e;
@@ -495,7 +514,7 @@ const validate_internal = async (fields, data, options) => {
495
514
  }
496
515
  response.valid && (response.valid = error ? false : true);
497
516
  response.fields.push({
498
- ...field,
517
+ ...recursive.field,
499
518
  ...options.secure ? await secure(field, extended) : extended,
500
519
  });
501
520
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beseif-solutions/prow-core",
3
- "version": "0.0.39",
3
+ "version": "0.1.0",
4
4
  "description": "Prow core functionalities and classes",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -33,9 +33,10 @@ type EventConfig = Pick<CoreConfig, `credentials` | `outputs`> & {
33
33
  outputs: string[],
34
34
  },
35
35
  sources?: string[],
36
+ fields?: Record<string, any>,
36
37
  };
37
38
 
38
- type CommonEvents<Config extends EventConfig = {}> = Common<Config> & {
39
+ type CommonEvents<Config extends EventConfig = { fields: Record<string, any> }> = Common<Config> & {
39
40
  model: `event`,
40
41
  categorization: {
41
42
  department: string,
@@ -59,75 +60,75 @@ export type Request = {
59
60
  body: any,
60
61
  };
61
62
 
62
- export type ImmediateTrigger<Config extends EventConfig = {}> = CommonEvents<Config> & {
63
+ export type ImmediateTrigger<Config extends EventConfig = { fields: Record<string, any> }> = CommonEvents<Config> & {
63
64
  type: `trigger`,
64
65
  immediate: true,
65
66
  outputs: [DefaultConnectableEvent<Config[`flags`][`outputs`][number]>],
66
67
  functions: {
67
68
  mount?: CoreFunction<{
68
69
  credentials: Config[`credentials`],
69
- inputs: { fields: Record<string, any>, link: string },
70
+ inputs: { fields: Config[`fields`], link: string },
70
71
  outputs: { done: boolean, setup?: any },
71
72
  }>,
72
73
  unmount?: CoreFunction<{
73
74
  credentials: Config[`credentials`],
74
- inputs: { fields: Record<string, any>, link: string, setup?: any },
75
+ inputs: { fields: Config[`fields`], link: string, setup?: any },
75
76
  outputs: { done: boolean },
76
77
  }>,
77
78
  challenge?: CoreFunction<{
78
79
  credentials: Config[`credentials`],
79
- inputs: { fields: Record<string, any>, link: string, request: Request, setup?: any },
80
+ inputs: { fields: Config[`fields`], link: string, request: Request, setup?: any },
80
81
  outputs: { done: boolean, response?: any },
81
82
  }>,
82
83
  handle: CoreFunction<{
83
84
  credentials: Config[`credentials`],
84
- inputs: { fields: Record<string, any>, request: Request, setup?: any },
85
+ inputs: { fields: Config[`fields`], request: Request, setup?: any },
85
86
  outputs: { records: Config[`outputs`][], flags: Partial<Record<Config[`flags`][`outputs`][number], true>> },
86
87
  }>,
87
88
  fire?: CoreFunction<{
88
89
  credentials: Config[`credentials`],
89
- inputs: { fields: Record<string, any>, link: string, setup?: any },
90
+ inputs: { fields: Config[`fields`], link: string, setup?: any },
90
91
  outputs: { done: boolean },
91
92
  }>,
92
93
  poll?: CoreFunction<{
93
94
  credentials: Config[`credentials`],
94
- inputs: { fields: Record<string, any>, last_schedule?: string, limit?: number },
95
+ inputs: { fields: Config[`fields`], last_schedule?: string, limit?: number },
95
96
  outputs: { records: Config[`outputs`][], flags: Partial<Record<Config[`flags`][`outputs`][number], true>> },
96
97
  }>,
97
98
  },
98
99
  };
99
100
 
100
- export type ScheduledTrigger<Config extends EventConfig = {}> = CommonEvents<Config> & {
101
+ export type ScheduledTrigger<Config extends EventConfig = { fields: Record<string, any> }> = CommonEvents<Config> & {
101
102
  type: `trigger`,
102
103
  immediate: false,
103
104
  outputs: [DefaultConnectableEvent<Config[`flags`][`outputs`][number]>],
104
105
  functions: {
105
106
  poll: CoreFunction<{
106
107
  credentials: Config[`credentials`],
107
- inputs: { fields: Record<string, any>, last_schedule?: string, limit?: number },
108
+ inputs: { fields: Config[`fields`], last_schedule?: string, limit?: number },
108
109
  outputs: { records: Config[`outputs`][], flags: Partial<Record<Config[`flags`][`outputs`][number], true>> },
109
110
  }>,
110
111
  },
111
112
  };
112
113
 
113
- export type Trigger<Config extends EventConfig = {}> =
114
+ export type Trigger<Config extends EventConfig = { fields: Record<string, any> }> =
114
115
  | ImmediateTrigger<Config>
115
116
  | ScheduledTrigger<Config>;
116
117
 
117
- export type Action<Config extends EventConfig = {}> = CommonEvents<Config> & {
118
+ export type Action<Config extends EventConfig = { fields: Record<string, any> }> = CommonEvents<Config> & {
118
119
  type: `action`,
119
120
  inputs: [DefaultConnectableEvent<Config[`flags`][`inputs`][number]>, ...AdditionalConnectableEvent<Config[`flags`][`inputs`][number]>[]],
120
121
  outputs: [DefaultConnectableEvent<Config[`flags`][`outputs`][number]>, ...(AdditionalConnectableEvent<Config[`flags`][`outputs`][number]> | ErrorConnectableEvent<Config[`flags`][`outputs`][number]>)[]],
121
122
  functions: {
122
123
  execute: CoreFunction<{
123
124
  credentials: Config[`credentials`],
124
- inputs: { fields: Record<string, any>, flags: Partial<Record<Config[`flags`][`inputs`][number], true>> },
125
+ inputs: { fields: Config[`fields`], flags: Partial<Record<Config[`flags`][`inputs`][number], true>> },
125
126
  outputs: { output: Config[`outputs`], flags: Partial<Record<Config[`flags`][`outputs`][number], true>> },
126
127
  }>,
127
128
  },
128
129
  };
129
130
 
130
- export type Event<Config extends EventConfig = {}> =
131
+ export type Event<Config extends EventConfig = { fields: Record<string, any> }> =
131
132
  | Action<Config>
132
133
  | Trigger<Config>;
133
134
 
package/src/index.ts CHANGED
@@ -4,7 +4,7 @@ export { Credentials, credentialsSchema, OAuthCredentials, oauthCredentialsSchem
4
4
  export { Action, actionOutputSchema, actionSchema, Event, eventSchema, ImmediateTrigger, immediateTriggerSchema, Request, ScheduledTrigger, scheduledTriggerSchema, Trigger, triggerOutputSchema, triggerSchema } from './entities/events';
5
5
  export { Provider, providerSchema } from './entities/provider';
6
6
  export { Source } from './entities/source';
7
- export { extract, Field, fieldSchema, fieldsSchema, File, SelectFieldChoice, validate, ValidationResult } from './minified-utils/fields';
7
+ export { alter, extract, Field, fieldSchema, fieldsSchema, File, SelectFieldChoice, validate, ValidationResult } from './minified-utils/fields';
8
8
  export { i18n, LocalizedField, LocalizedProperties, localizeFields, localizeGroup, localizeInputs, localizeOutputs, localizeProperties } from './minified-utils/locales';
9
9
  export { Properties } from './minified-utils/properties';
10
10
  export { Protocol } from './minified-utils/protocol';
@@ -2,15 +2,12 @@ import Joi, { DateSchema, NumberSchema, StringSchema } from "joi";
2
2
  import _ from "lodash";
3
3
  import moment from "moment-timezone";
4
4
  import context from "./context";
5
- import { OneOf } from "./types";
6
5
  import { where, Where } from "./where";
7
6
 
8
7
  export type Condition = {
9
8
  condition: Where,
10
- } & OneOf<{
11
9
  overrides: Partial<Field>,
12
- show: boolean,
13
- }>;
10
+ };
14
11
 
15
12
  type Common = {
16
13
  key: string,
@@ -18,6 +15,7 @@ type Common = {
18
15
  disabled?: boolean,
19
16
  required?: boolean,
20
17
  as_password?: boolean,
18
+ show?: boolean,
21
19
  show_label?: boolean,
22
20
  } & ({
23
21
  as_array?: false,
@@ -47,6 +45,7 @@ type Any = string | number | boolean | Any[] | { [key: string]: Any };
47
45
  type AnyInputField<Extend = Record<never, never>> = {
48
46
  type: `any`,
49
47
  default?: Any | Any[],
48
+ allow_nullish?: boolean, // allow null values
50
49
  } & (
51
50
  | SelectField<Any, Extend>
52
51
  | {}
@@ -181,10 +180,9 @@ type ValidationExtended = {
181
180
 
182
181
  const conditionSchema = () =>
183
182
  Joi.object({
184
- condition: Joi.object(),
185
- overrides: Joi.object(),
186
- show: Joi.bool(),
187
- }).xor(`overrides`, `show`);
183
+ condition: Joi.object().required(),
184
+ overrides: Joi.object().required(),
185
+ });
188
186
 
189
187
  const commonFieldSchema = () =>
190
188
  Joi.object({
@@ -193,6 +191,7 @@ const commonFieldSchema = () =>
193
191
  disabled: Joi.bool(),
194
192
  required: Joi.bool(),
195
193
  as_password: Joi.bool(),
194
+ show: Joi.bool(),
196
195
  show_label: Joi.bool().default(true),
197
196
  as_array: Joi.bool(),
198
197
  array_min: Joi.when(`as_array`, {
@@ -385,7 +384,7 @@ const fileReplacer = (field: Common & FileInputField): Field => ({
385
384
  },
386
385
  ],
387
386
  default: field.default,
388
- ..._.pick(field, [`altered_by`, `disabled`, `required`, `as_password`, `show_label`, `as_array`, `array_min`, `array_max`, `array_length`]),
387
+ ..._.pick(field, [`altered_by`, `disabled`, `required`, `as_password`, `show`, `show_label`, `as_array`, `array_min`, `array_max`, `array_length`]),
389
388
  }) as Field;
390
389
 
391
390
  const fileInputFieldSchema = () =>
@@ -457,6 +456,8 @@ const getSimpleFieldSchema = (field: Field) => {
457
456
  switch (field.type) {
458
457
  case `any`:
459
458
  typeSchema = anySchema();
459
+ // allow null values for any type
460
+ if (field.allow_nullish) { typeSchema = typeSchema.allow(null, ``, 0, undefined); }
460
461
  break;
461
462
  case `boolean`:
462
463
  typeSchema = Joi.bool();
@@ -563,8 +564,9 @@ const getObjectFieldSchema = (field: Field, items: { key: string, schema: Joi.Sc
563
564
  };
564
565
 
565
566
  const getGeneralSchema = (field: Field, schema: Joi.Schema): Joi.Schema => {
567
+ if (field.required) { schema = schema.required(); }
566
568
  if (field.disabled) { schema = schema.forbidden(); }
567
- return field.required ? schema.required() : schema;
569
+ return schema;
568
570
  };
569
571
 
570
572
  const convertPath = (parts: (string | number)[]): string =>
@@ -593,10 +595,33 @@ const relative_condition = (condition: Where, relative: string): typeof conditio
593
595
  } catch (e) { throw e; }
594
596
  };
595
597
 
596
- const recursive_schema = async (field: Field, data: Record<string, any>, options: { relative?: string, array?: boolean, context: Record<string, any> }): Promise<Joi.Schema> => {
598
+ export const alter = (field: Field, relative: string, data: Record<string, any>) => {
599
+ const cloned = _.cloneDeep(field);
600
+ for (const alteration of cloned.altered_by) {
601
+ const condition = relative_condition(alteration.condition, relative);
602
+
603
+ const matches = where(data, [condition]);
604
+ if (matches) { _.assign(cloned, alteration.overrides); }
605
+ }
606
+ return cloned;
607
+ };
608
+
609
+ const recursive_schema = async (field: Field, data: Record<string, any>, options: { alter: boolean, relative?: string, array?: boolean, context: Record<string, any> }): Promise<{ schema: Joi.Schema, field: Field }> => {
597
610
  try {
611
+ let newField: Field = _.cloneDeep(field);
612
+
613
+ // alterations over already resolved data (previous fields)
614
+ if (newField.altered_by?.length > 0) {
615
+ newField = alter(newField, options.relative, data);
616
+
617
+ // remove altered_by only if it's not an array -> array alterations must be kept for front-end rendering
618
+ if (options.alter) { delete newField.altered_by; }
619
+ }
620
+
621
+ const alteredField: Field = _.cloneDeep(newField);
622
+
598
623
  // ÑAPA: if the field is a file, replace it
599
- const newField = field.type === `file` ? fileReplacer(field) : _.cloneDeep(field);
624
+ if (newField.type === `file`) { newField = fileReplacer(newField); }
600
625
 
601
626
  const relativeKey = options.relative ?
602
627
  options.relative.endsWith(`]`) ?
@@ -613,61 +638,45 @@ const recursive_schema = async (field: Field, data: Record<string, any>, options
613
638
  // get schema for field with data
614
639
  let calculatedSchema: Joi.Schema;
615
640
  if (newField.as_array && resolved) {
616
-
617
641
  const itemSchemas: Joi.Schema[] = [];
618
642
  if (_.isArray(resolved)) {
619
643
  for (let i = 0; i < (resolved || []).length; i++) {
620
- const itemSchema = await recursive_schema(
644
+ const { schema: itemSchema } = await recursive_schema(
621
645
  _.omit(newField, [`as_array`, `array_min`, `array_max`, `array_length`]) as Field,
622
- data, { relative: `${relativeKey}[${i}]`, array: true, context: options.context });
646
+ data, { alter: false, relative: `${relativeKey}[${i}]`, array: true, context: options.context });
623
647
  if (itemSchema) { itemSchemas.push(itemSchema); }
624
648
  }
625
649
  }
626
650
 
627
651
  calculatedSchema = getArrayFieldSchema(newField, itemSchemas);
628
652
  } else if (newField.type === `dict` && newField.items) {
629
- const itemSchemas: { key: string, schema: Joi.Schema }[] = [];
653
+ const items: { key: string, schema: Joi.Schema, field: Field }[] = [];
630
654
 
631
655
  if (_.isObject(resolved)) {
632
656
  for (const item of newField.items) {
633
- const itemSchema = await recursive_schema(item, data, { relative: relativeKey, context: options.context });
634
- if (itemSchema) { itemSchemas.push({ key: item.key, schema: itemSchema }); }
657
+ const recursive = await recursive_schema(item, data, { alter: options.alter && true, relative: relativeKey, context: options.context });
658
+ if (recursive) { items.push({ key: item.key, schema: recursive.schema, field: recursive.field }); }
635
659
  }
636
660
  }
637
661
 
638
- calculatedSchema = getObjectFieldSchema(newField, itemSchemas);
662
+ calculatedSchema = getObjectFieldSchema(newField, items);
663
+ newField.items = items.map((i) => i.field);
639
664
  } else {
640
665
  calculatedSchema = getSimpleFieldSchema(newField);
641
666
  }
642
667
 
643
668
  if (!calculatedSchema) { throw new Error(`Could not resolve schema for field ${newField.key}`); }
644
669
 
645
- // alterations over data
646
- if (newField.altered_by?.length > 0) {
647
- let hide = false;
648
- for (const alteration of newField.altered_by) {
649
- const condition = relative_condition(alteration.condition, options.relative);
650
-
651
- const matches = where(data, [condition]);
652
- if (matches) {
653
- if (`overrides` in alteration) {
654
- _.assign(newField, alteration.overrides);
655
- } else if (`show` in alteration) {
656
- hide = !alteration.show;
657
- }
658
- }
659
- }
660
-
661
- delete newField.altered_by;
662
-
663
- if (hide) {
664
- // if the field is hidden, we don't need to validate it
665
- _.unset(data, relativeKey);
666
- return;
667
- }
670
+ if (typeof newField.show === `boolean` && !newField.show) {
671
+ // if the field is hidden, we don't need to validate it
672
+ _.unset(data, relativeKey);
673
+ return;
674
+ } else if (newField.disabled) {
675
+ // TODO: check this
676
+ _.unset(data, relativeKey);
668
677
  }
669
678
 
670
- return calculatedSchema;
679
+ return { schema: calculatedSchema, field: field.type === `file` ? alteredField : newField };
671
680
  } catch (e) { throw e; }
672
681
  };
673
682
 
@@ -681,14 +690,15 @@ const validate_internal = async (fields: Field[], data: Record<string, any>, opt
681
690
 
682
691
  const cloned = _.cloneDeep(data);
683
692
 
684
- const schema = await recursive_schema(field, cloned, { context: options.context });
693
+ const recursive = await recursive_schema(field, cloned, { alter: true, context: options.context });
694
+ if (!recursive) { continue; }
685
695
 
686
696
  const resolved = _.get(cloned, field.key, field.default);
687
697
 
688
698
  let validation: any;
689
699
  let error: any;
690
700
  try {
691
- validation = await schema.validateAsync(resolved, { abortEarly: false });
701
+ validation = await recursive.schema.validateAsync(resolved, { abortEarly: false });
692
702
  } catch (e) { error = e; }
693
703
 
694
704
  let extended: ValidationExtended;
@@ -713,7 +723,7 @@ const validate_internal = async (fields: Field[], data: Record<string, any>, opt
713
723
 
714
724
  response.valid &&= error ? false : true;
715
725
  response.fields.push({
716
- ...field as any,
726
+ ...recursive.field as any,
717
727
  ...options.secure ? await secure(field, extended) : extended,
718
728
  });
719
729
 
package/tsconfig.json CHANGED
@@ -11,10 +11,9 @@
11
11
  "declaration": true
12
12
  },
13
13
  "include": [
14
- "src/**/*.ts",
14
+ "src/**/*.ts"
15
15
  ],
16
16
  "exclude": [
17
- "./test",
18
17
  "node_modules",
19
18
  "dist/**/*.js"
20
19
  ]