@contrail/cli 1.0.29 → 1.0.31

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.
@@ -1,6 +1,7 @@
1
1
  import { App, AppDeclaration, AppActionDeclaration } from '../../interfaces';
2
2
  export declare function getActionsForApp(app: App): Promise<any>;
3
3
  export declare function getActionDeclarationIdentifier(actionKey: any, app: App): string;
4
+ export declare function deleteAction(actionId: any): Promise<any>;
4
5
  export declare class ActionsDeployer {
5
6
  deployActions(appDeclaration: AppDeclaration, app: App): Promise<void>;
6
7
  deployAction(actionKey: string, actionDeclaration: AppActionDeclaration, app: App, existingActions: Array<any>): Promise<void>;
@@ -12,6 +12,9 @@ export async function getActionsForApp(app) {
12
12
  export function getActionDeclarationIdentifier(actionKey, app) {
13
13
  return app.identifier + ':' + actionKey;
14
14
  }
15
+ export async function deleteAction(actionId) {
16
+ return await new Entities().delete({ entityName: 'event-workflow-action-definition', id: actionId });
17
+ }
15
18
  export class ActionsDeployer {
16
19
  async deployActions(appDeclaration, app) {
17
20
  // FETCH ALL ACTIONS FROM THE API.
@@ -1,7 +1,7 @@
1
1
  import { Entities } from '@contrail/sdk';
2
2
  import chalk from 'chalk';
3
3
  import { Auth } from '../../auth/auth';
4
- import { ActionsDeployer } from './actions-deployer';
4
+ import { ActionsDeployer, getActionsForApp, deleteAction } from './actions-deployer';
5
5
  import { TriggerKeyDefinitionParser, ConfigPropertiesParser } from './app-template-parsers';
6
6
  import { WorkflowDefinitionDeployer } from './workflow-definition-deployer';
7
7
  export class AppDeployer {
@@ -83,7 +83,7 @@ export class AppDeployer {
83
83
  keywords: appDeclaration.keywords,
84
84
  configProperties,
85
85
  triggerKeyDefinitions,
86
- isDockerBased: appDeclaration.isDockerBased,
86
+ dockerImageRef: appDeclaration.dockerImageRef,
87
87
  };
88
88
  const app = await new Entities().update({ entityName: 'app', id: existingApp.id, object: updates });
89
89
  console.log(`%s Updated app: ${app.name}`, chalk.yellow.bold('APP'));
@@ -92,6 +92,11 @@ export class AppDeployer {
92
92
  async remove(appDeclaration) {
93
93
  let app = await this.getExistingApp(appDeclaration);
94
94
  if (app) {
95
+ const actions = await getActionsForApp(app);
96
+ for (const action of actions) {
97
+ console.log(`%s Deleting action: ${action.identifier}`, chalk.yellow.bold('APP'));
98
+ await deleteAction(action.id);
99
+ }
95
100
  app = await new Entities().delete({ entityName: 'app', id: app.id });
96
101
  console.log(`%s Deleted app: ${app.name}`, chalk.yellow.bold('APP'));
97
102
  }
package/lib/cli.js CHANGED
@@ -6,7 +6,7 @@ import { UploadOptionSets } from './types/option-set-uploader';
6
6
  import { ParseOptionSetsLocalFiles } from './types/option-set-parser';
7
7
  import { MergeOptionSets } from './types/option-set-merger';
8
8
  import { MergeTypeProperties } from './types/types-properties-merger';
9
- import { ParseTypesFromFiles, ParseTypesFromLocalFiles } from './types/parse-types';
9
+ import { ParseTypesFromFiles, ParseTypesFromLocalFiles, ParseTypesFromTemplateFromLocalFiles } from './types/parse-types';
10
10
  import { loadColors, deleteColors } from './colors/color-loader';
11
11
  import { listConfig, removeConfig } from './config/configCommands';
12
12
  import { deleteWorkflowTemplate, deployWorkflowTemplate, listWorkflowTemplate } from './workflows/workflowCommands';
@@ -77,6 +77,10 @@ export async function cli(args) {
77
77
  ParseTypesFromLocalFiles(args);
78
78
  break;
79
79
  }
80
+ case 'parseTypesFromTemplateFromLocalFiles': {
81
+ ParseTypesFromTemplateFromLocalFiles(args);
82
+ break;
83
+ }
80
84
  case 'parseTypesFromFiles': {
81
85
  ParseTypesFromFiles(args);
82
86
  break;
@@ -221,6 +225,8 @@ const helpSections = [
221
225
  'parseOptionSetsLocalFiles <File Paths> Parse CSV files into OptionSets',
222
226
  'parseTypesFromLocalFiles <File Paths> Parse CSV files into Types and ',
223
227
  '. OptionSets from local files.\n',
228
+ 'parseTypesFromTemplateFromLocalFiles <File Paths> Parse CSV files into ',
229
+ '. Types and OptionSets from local files.\n',
224
230
  'parseTypesFromFiles <fileIds> Parse CSV files into Types and ',
225
231
  '. OptionSets from VibeIQ Files.\n',
226
232
  'mergeOptionSets <File Path> Merge the OptionSets from an existing',
@@ -1,2 +1,3 @@
1
1
  export declare function ParseTypesFromLocalFiles(args: any): Promise<void>;
2
2
  export declare function ParseTypesFromFiles(args: any): Promise<void>;
3
+ export declare function ParseTypesFromTemplateFromLocalFiles(args: any): Promise<void>;
@@ -1,4 +1,4 @@
1
- import { GetSuggestedTypes } from '@contrail/types';
1
+ import { GetSuggestedTypes, GetTypesFromTemplate } from '@contrail/types';
2
2
  import chalk from 'chalk';
3
3
  import fs from 'fs';
4
4
  import { getSeparatorByPlatform } from '../common';
@@ -6,6 +6,7 @@ import * as csvToJson from 'csvtojson';
6
6
  import { authUser } from '../auth/login';
7
7
  import { getCSVFromFile } from './csv-parser';
8
8
  const yaml = require('js-yaml');
9
+ // This uses local files to get the data to parse into types
9
10
  export async function ParseTypesFromLocalFiles(args) {
10
11
  try {
11
12
  if ((args === null || args === void 0 ? void 0 : args.length) < 4) {
@@ -23,6 +24,7 @@ export async function ParseTypesFromLocalFiles(args) {
23
24
  }
24
25
  console.log('%s Parsing Complete.', chalk.green.bold('COMPLETE'));
25
26
  }
27
+ // This uses VibeIq file ids to get the data to parse into types
26
28
  export async function ParseTypesFromFiles(args) {
27
29
  try {
28
30
  if ((args === null || args === void 0 ? void 0 : args.length) < 4) {
@@ -40,13 +42,33 @@ export async function ParseTypesFromFiles(args) {
40
42
  }
41
43
  console.log('%s Parsing Complete.', chalk.green.bold('COMPLETE'));
42
44
  }
45
+ // This uses local files to get type template file and the data file to parse into types
46
+ export async function ParseTypesFromTemplateFromLocalFiles(args) {
47
+ try {
48
+ if ((args === null || args === void 0 ? void 0 : args.length) < 5) {
49
+ throw new Error('File names must be included.');
50
+ }
51
+ console.log(`%s Parsing`, chalk.yellow.bold('TYPES AND OPTION SETS'));
52
+ const templateFileLocation = args[3];
53
+ const dataFileLocation = args[4];
54
+ console.log('Using Template File Location: ', templateFileLocation);
55
+ console.log('Using Data File Location: ', dataFileLocation);
56
+ await parseTypesFromTemplateFromLocalFiles(templateFileLocation, dataFileLocation);
57
+ console.log(`%s Parsed`, chalk.yellow.bold('TYPES AND OPTION SETS'));
58
+ }
59
+ catch (e) {
60
+ console.log(`%s Parsing Failed. ${e}`, chalk.red.bold('FAIL'));
61
+ return;
62
+ }
63
+ console.log('%s Parsing Complete.', chalk.green.bold('COMPLETE'));
64
+ }
43
65
  async function loadDataFromLocalCSV(fileName) {
44
66
  const CURRENT_DIR = process.cwd();
45
67
  try {
46
68
  const separator = getSeparatorByPlatform();
47
69
  const fullPath = CURRENT_DIR + separator + fileName;
48
70
  console.log('Getting file from path: ', fullPath);
49
- const csvData = await csvToJson.default().fromFile(fullPath);
71
+ const csvData = await csvToJson.default({ flatKeys: true }).fromFile(fullPath);
50
72
  return csvData;
51
73
  }
52
74
  catch (e) {
@@ -72,6 +94,25 @@ async function parseTypesFromLocalFiles(fileLocations) {
72
94
  saveData({ optionSets: suggestions.OptionSets }, 'parsed_optionSets.yml');
73
95
  saveData({ typeProperties: suggestions.TypeProperties }, 'parsed_typeProperties.yml');
74
96
  }
97
+ async function parseTypesFromTemplateFromLocalFiles(templateFileLocation, dataFileLocation) {
98
+ let templateCSVData = [];
99
+ let dataCSVData = [];
100
+ try {
101
+ console.log('Getting template from fileLocation: ', templateFileLocation);
102
+ templateCSVData = await loadDataFromLocalCSV(templateFileLocation);
103
+ console.log(`CSV import was successful. ${templateCSVData === null || templateCSVData === void 0 ? void 0 : templateCSVData.length} rows found.`);
104
+ console.log('Getting data from fileLocation: ', dataFileLocation);
105
+ dataCSVData = await loadDataFromLocalCSV(dataFileLocation);
106
+ console.log(`CSV import was successful. ${dataCSVData === null || dataCSVData === void 0 ? void 0 : dataCSVData.length} rows found.`);
107
+ }
108
+ catch (e) {
109
+ console.log('Error importing csv data.', e);
110
+ throw e;
111
+ }
112
+ const types = GetTypesFromTemplate(templateCSVData, dataCSVData);
113
+ saveData({ optionSets: types.OptionSets }, 'parsed_optionSets.yml');
114
+ saveData({ TypePropertiesByEntity: types.TypePropertiesByEntity }, 'parsed_TypePropertiesByEntity.yml');
115
+ }
75
116
  async function parseTypesFromFiles(fileIds) {
76
117
  await authUser();
77
118
  // get csv data
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrail/cli",
3
- "version": "1.0.29",
3
+ "version": "1.0.31",
4
4
  "description": "VibeIQ's Contrail Platform CLI.",
5
5
  "main": "lib/index.js",
6
6
  "bin": {
@@ -24,7 +24,7 @@
24
24
  "license": "ISC",
25
25
  "dependencies": {
26
26
  "@contrail/sdk": "^1.0.154",
27
- "@contrail/types": "^2.0.61",
27
+ "@contrail/types": "^2.0.69",
28
28
  "@contrail/util": "^1.0.17",
29
29
  "amazon-cognito-identity-js": "^5.2.3",
30
30
  "arg": "^4.0.1",
@@ -19,6 +19,10 @@ export function getActionDeclarationIdentifier(actionKey, app: App) {
19
19
  return app.identifier + ':' + actionKey;
20
20
  }
21
21
 
22
+ export async function deleteAction(actionId): Promise<any>{
23
+ return await new Entities().delete({ entityName: 'event-workflow-action-definition', id: actionId });
24
+ }
25
+
22
26
  export class ActionsDeployer {
23
27
  async deployActions(appDeclaration: AppDeclaration, app: App) {
24
28
 
@@ -1,7 +1,7 @@
1
1
  import { Entities } from '@contrail/sdk';
2
2
  import chalk from 'chalk';
3
3
  import { Auth } from '../../auth/auth';
4
- import { ActionsDeployer } from './actions-deployer';
4
+ import { ActionsDeployer, getActionsForApp, deleteAction } from './actions-deployer';
5
5
  import { App, AppDeclaration } from '../../interfaces';
6
6
  import { TriggerKeyDefinitionParser, ConfigPropertiesParser } from './app-template-parsers';
7
7
  import { WorkflowDefinitionDeployer } from './workflow-definition-deployer';
@@ -95,7 +95,7 @@ export class AppDeployer {
95
95
  keywords: appDeclaration.keywords,
96
96
  configProperties,
97
97
  triggerKeyDefinitions,
98
- isDockerBased: appDeclaration.isDockerBased,
98
+ dockerImageRef: appDeclaration.dockerImageRef,
99
99
  };
100
100
  const app = await new Entities().update({ entityName: 'app', id: existingApp.id, object: updates });
101
101
  console.log(`%s Updated app: ${app.name}`, chalk.yellow.bold('APP'));
@@ -105,6 +105,12 @@ export class AppDeployer {
105
105
  public async remove(appDeclaration: AppDeclaration) {
106
106
  let app = await this.getExistingApp(appDeclaration);
107
107
  if (app) {
108
+ const actions = await getActionsForApp(app)
109
+ for(const action of actions)
110
+ {
111
+ console.log(`%s Deleting action: ${action.identifier}`, chalk.yellow.bold('APP'));
112
+ await deleteAction(action.id);
113
+ }
108
114
  app = await new Entities().delete({ entityName: 'app', id: app.id });
109
115
  console.log(`%s Deleted app: ${app.name}`, chalk.yellow.bold('APP'));
110
116
  } else {
package/src/auth/login.ts CHANGED
@@ -152,4 +152,4 @@ async function refreshCurrentUserOrg() {
152
152
  // cache config in the fs
153
153
  storeConfig(Object.assign({}, Auth.config))
154
154
  return Object.assign({}, Auth.config);
155
- }
155
+ }
package/src/cli.ts CHANGED
@@ -7,7 +7,7 @@ import { UploadOptionSets } from './types/option-set-uploader';
7
7
  import { ParseOptionSetsLocalFiles } from './types/option-set-parser';
8
8
  import { MergeOptionSets } from './types/option-set-merger';
9
9
  import { MergeTypeProperties } from './types/types-properties-merger';
10
- import { ParseTypesFromFiles, ParseTypesFromLocalFiles } from './types/parse-types';
10
+ import { ParseTypesFromFiles, ParseTypesFromLocalFiles, ParseTypesFromTemplateFromLocalFiles } from './types/parse-types';
11
11
  import { loadColors, deleteColors } from './colors/color-loader';
12
12
  import {listConfig, removeConfig} from './config/configCommands'
13
13
  import {deleteWorkflowTemplate, deployWorkflowTemplate, listWorkflowTemplate} from './workflows/workflowCommands';
@@ -84,6 +84,10 @@ export async function cli(args) {
84
84
  ParseTypesFromLocalFiles(args);
85
85
  break;
86
86
  }
87
+ case 'parseTypesFromTemplateFromLocalFiles': {
88
+ ParseTypesFromTemplateFromLocalFiles(args);
89
+ break;
90
+ }
87
91
  case 'parseTypesFromFiles': {
88
92
  ParseTypesFromFiles(args);
89
93
  break;
@@ -235,6 +239,8 @@ const helpSections = [
235
239
  'parseOptionSetsLocalFiles <File Paths> Parse CSV files into OptionSets',
236
240
  'parseTypesFromLocalFiles <File Paths> Parse CSV files into Types and ',
237
241
  '. OptionSets from local files.\n',
242
+ 'parseTypesFromTemplateFromLocalFiles <File Paths> Parse CSV files into ',
243
+ '. Types and OptionSets from local files.\n',
238
244
  'parseTypesFromFiles <fileIds> Parse CSV files into Types and ',
239
245
  '. OptionSets from VibeIQ Files.\n',
240
246
  'mergeOptionSets <File Path> Merge the OptionSets from an existing',
@@ -1,4 +1,4 @@
1
- import { GetSuggestedTypes } from '@contrail/types';
1
+ import { GetSuggestedTypes, GetTypesFromTemplate } from '@contrail/types';
2
2
  import chalk from 'chalk';
3
3
  import fs from 'fs';
4
4
  import { getSeparatorByPlatform } from '../common';
@@ -8,6 +8,7 @@ import { getCSVFromFile } from './csv-parser';
8
8
 
9
9
  const yaml = require('js-yaml');
10
10
 
11
+ // This uses local files to get the data to parse into types
11
12
  export async function ParseTypesFromLocalFiles(args) {
12
13
  try {
13
14
  if (args?.length < 4) {
@@ -29,6 +30,7 @@ export async function ParseTypesFromLocalFiles(args) {
29
30
  console.log('%s Parsing Complete.', chalk.green.bold('COMPLETE'));
30
31
  }
31
32
 
33
+ // This uses VibeIq file ids to get the data to parse into types
32
34
  export async function ParseTypesFromFiles(args) {
33
35
  try {
34
36
  if (args?.length < 4) {
@@ -50,6 +52,30 @@ export async function ParseTypesFromFiles(args) {
50
52
  console.log('%s Parsing Complete.', chalk.green.bold('COMPLETE'));
51
53
  }
52
54
 
55
+ // This uses local files to get type template file and the data file to parse into types
56
+ export async function ParseTypesFromTemplateFromLocalFiles(args) {
57
+ try {
58
+ if (args?.length < 5) {
59
+ throw new Error('File names must be included.');
60
+ }
61
+ console.log(`%s Parsing`, chalk.yellow.bold('TYPES AND OPTION SETS'));
62
+ const templateFileLocation = args[3];
63
+ const dataFileLocation = args[4];
64
+ console.log('Using Template File Location: ', templateFileLocation);
65
+ console.log('Using Data File Location: ', dataFileLocation);
66
+
67
+ await parseTypesFromTemplateFromLocalFiles(templateFileLocation, dataFileLocation);
68
+ console.log(`%s Parsed`, chalk.yellow.bold('TYPES AND OPTION SETS'));
69
+
70
+ }
71
+ catch (e) {
72
+ console.log(`%s Parsing Failed. ${e}`, chalk.red.bold('FAIL'));
73
+ return;
74
+ }
75
+
76
+ console.log('%s Parsing Complete.', chalk.green.bold('COMPLETE'));
77
+ }
78
+
53
79
  async function loadDataFromLocalCSV(fileName) {
54
80
  const CURRENT_DIR = process.cwd();
55
81
  try {
@@ -57,7 +83,7 @@ async function loadDataFromLocalCSV(fileName) {
57
83
  const fullPath = CURRENT_DIR + separator + fileName;
58
84
 
59
85
  console.log('Getting file from path: ', fullPath);
60
- const csvData = await csvToJson.default().fromFile(fullPath);
86
+ const csvData = await csvToJson.default({flatKeys: true}).fromFile(fullPath);
61
87
 
62
88
  return csvData;
63
89
  } catch (e) {
@@ -84,8 +110,31 @@ async function parseTypesFromLocalFiles(fileLocations: string[]) {
84
110
 
85
111
  console.log(`CSV imports were successful. ${csvJSONData?.length} total rows found.`);
86
112
  const suggestions = GetSuggestedTypes(csvJSONData)
87
- saveData({optionSets: suggestions.OptionSets}, 'parsed_optionSets.yml');
88
- saveData({typeProperties: suggestions.TypeProperties}, 'parsed_typeProperties.yml');
113
+ saveData({ optionSets: suggestions.OptionSets }, 'parsed_optionSets.yml');
114
+ saveData({ typeProperties: suggestions.TypeProperties }, 'parsed_typeProperties.yml');
115
+ }
116
+
117
+ async function parseTypesFromTemplateFromLocalFiles(templateFileLocation: string, dataFileLocation: string) {
118
+
119
+ let templateCSVData: any[] = [];
120
+ let dataCSVData: any[] = [];
121
+ try {
122
+ console.log('Getting template from fileLocation: ', templateFileLocation);
123
+ templateCSVData = await loadDataFromLocalCSV(templateFileLocation);
124
+ console.log(`CSV import was successful. ${templateCSVData?.length} rows found.`);
125
+
126
+ console.log('Getting data from fileLocation: ', dataFileLocation);
127
+ dataCSVData = await loadDataFromLocalCSV(dataFileLocation);
128
+ console.log(`CSV import was successful. ${dataCSVData?.length} rows found.`);
129
+ }
130
+ catch (e) {
131
+ console.log('Error importing csv data.', e);
132
+ throw e;
133
+ }
134
+
135
+ const types = GetTypesFromTemplate(templateCSVData, dataCSVData)
136
+ saveData({ optionSets: types.OptionSets }, 'parsed_optionSets.yml');
137
+ saveData({ TypePropertiesByEntity: types.TypePropertiesByEntity }, 'parsed_TypePropertiesByEntity.yml');
89
138
  }
90
139
 
91
140
  async function parseTypesFromFiles(fileIds: string[]) {
@@ -109,8 +158,8 @@ async function parseTypesFromFiles(fileIds: string[]) {
109
158
  console.log(`CSV downloads were successful. ${csvJSONData?.length} total rows found.`);
110
159
  const suggestions = GetSuggestedTypes(csvJSONData)
111
160
 
112
- saveData({optionSets: suggestions.OptionSets}, 'parsed_optionSets.yml');
113
- saveData({typeProperties: suggestions.TypeProperties}, 'parsed_typeProperties.yml');
161
+ saveData({ optionSets: suggestions.OptionSets }, 'parsed_optionSets.yml');
162
+ saveData({ typeProperties: suggestions.TypeProperties }, 'parsed_typeProperties.yml');
114
163
  }
115
164
 
116
165
  function saveData(data, name) {
@@ -1,10 +0,0 @@
1
- import { App, AppDeclaration, AppActionDeclaration } from '../../interfaces';
2
- export declare class ActionsDeployer {
3
- deployActions(appDeclaration: AppDeclaration, app: App): Promise<void>;
4
- getActionsForApp(app: App): Promise<any>;
5
- deployAction(actionKey: string, actionDeclaration: AppActionDeclaration, app: App, existingActions: Array<any>): Promise<void>;
6
- private createNewActionDefinition;
7
- private updateActionDefinition;
8
- getActionDeclarationIdentifier(actionKey: any, app: App): string;
9
- getFunction(actionDeclaration: AppActionDeclaration): Promise<string>;
10
- }
@@ -1,97 +0,0 @@
1
- import { Entities } from '@contrail/sdk';
2
- import chalk from 'chalk';
3
- import { ConfigPropertiesParser } from './app-template-parsers';
4
- import { getSeparatorByPlatform } from '../../common';
5
- import fs from 'fs';
6
- export class ActionsDeployer {
7
- async deployActions(appDeclaration, app) {
8
- // FETCH ALL ACTIONS FROM THE API.
9
- const existingActions = await this.getActionsForApp(app);
10
- // UPSERT / DELETE BASED ON ACTION IDENTIFIER
11
- console.log('%s \tDeploying actions.', chalk.yellow.bold('ACTION'));
12
- for (const actionKey of Object.keys(appDeclaration.actions)) {
13
- await this.deployAction(actionKey, appDeclaration.actions[actionKey], app, existingActions);
14
- }
15
- }
16
- async getActionsForApp(app) {
17
- return await new Entities().get({
18
- entityName: 'event-workflow-action-definition',
19
- criteria: { ownerKey: `app:${app.id}` },
20
- });
21
- }
22
- async deployAction(actionKey, actionDeclaration, app, existingActions) {
23
- console.log(`%s \tDeploying action: ${actionKey}`, chalk.yellow.bold('ACTION'));
24
- const identifier = this.getActionDeclarationIdentifier(actionKey, app);
25
- const existingDefinition = existingActions.find(ad => ad.identifier === identifier);
26
- if (!existingDefinition) {
27
- await this.createNewActionDefinition(actionKey, actionDeclaration, app);
28
- }
29
- else {
30
- await this.updateActionDefinition(existingDefinition, actionDeclaration);
31
- }
32
- }
33
- async createNewActionDefinition(actionKey, actionDeclaration, app) {
34
- let configProperties;
35
- if (actionDeclaration === null || actionDeclaration === void 0 ? void 0 : actionDeclaration.actionConfiguration) {
36
- configProperties = ConfigPropertiesParser.getConfigProperties(actionDeclaration.actionConfiguration);
37
- }
38
- const newObject = {
39
- identifier: this.getActionDeclarationIdentifier(actionKey, app),
40
- name: actionDeclaration.name,
41
- ownerKey: `app:${app.id}`,
42
- public: app.public,
43
- configProperties,
44
- };
45
- const functionString = await this.getFunction(actionDeclaration);
46
- if (functionString) {
47
- newObject.executeFunctionString = functionString;
48
- }
49
- const actionDefinition = await new Entities().create({
50
- entityName: 'event-workflow-action-definition',
51
- object: newObject,
52
- });
53
- console.log(`%s Created new action definition: ${actionKey}`, chalk.yellow.bold('APP'));
54
- return actionDefinition;
55
- }
56
- async updateActionDefinition(existingActionDefinition, actionDeclaration) {
57
- let configProperties;
58
- if (actionDeclaration === null || actionDeclaration === void 0 ? void 0 : actionDeclaration.actionConfiguration) {
59
- configProperties = ConfigPropertiesParser.getConfigProperties(actionDeclaration.actionConfiguration);
60
- }
61
- else if (!(actionDeclaration === null || actionDeclaration === void 0 ? void 0 : actionDeclaration.actionConfiguration) && existingActionDefinition.configProperties) {
62
- configProperties = null;
63
- }
64
- const updates = {
65
- name: actionDeclaration.name,
66
- // public: actionDeclaration.public, // TODO - an actions visibility is allowed to change
67
- configProperties,
68
- };
69
- const functionString = await this.getFunction(actionDeclaration);
70
- if (functionString) {
71
- updates.executeFunctionString = functionString;
72
- }
73
- const actionDefinition = await new Entities().update({
74
- entityName: 'event-workflow-action-definition',
75
- id: existingActionDefinition.id,
76
- object: updates,
77
- });
78
- console.log(`%s Updated existing action definition: ${actionDefinition.identifier}`, chalk.yellow.bold('APP'));
79
- return actionDefinition;
80
- }
81
- getActionDeclarationIdentifier(actionKey, app) {
82
- return app.identifier + ':' + actionKey;
83
- }
84
- async getFunction(actionDeclaration) {
85
- if (!actionDeclaration.handler) {
86
- return;
87
- }
88
- if (!actionDeclaration.handler.endsWith('.js')) {
89
- throw new Error('Action handler must be a .js file.');
90
- }
91
- const CURRENT_DIR = process.cwd();
92
- const separator = getSeparatorByPlatform();
93
- const functionLocation = CURRENT_DIR + separator + actionDeclaration.handler;
94
- const content = fs.readFileSync(functionLocation);
95
- return content.toString();
96
- }
97
- }
@@ -1,76 +0,0 @@
1
- /** Describes the derivative JSON / object represented
2
- * in app.yml file.
3
- */
4
- export interface AppDeclaration {
5
- appIdentifier: string;
6
- appName: string;
7
- appDescription?: string;
8
- visibility: 'private' | 'public';
9
- publisher: string;
10
- version: string;
11
- eventWorkflowTriggerKeyMapping: string;
12
- thumbnail?: string;
13
- keywords?: Array<string>;
14
- actions?: {
15
- [key: string]: AppActionDeclaration;
16
- };
17
- appConfiguration: ConfigPropertyElements;
18
- triggers: {
19
- [key: string]: AppTriggerDeclaration;
20
- };
21
- isDockerBased?: boolean;
22
- }
23
- export interface ConfigPropertyElements {
24
- [key: string]: ConfigPropertyElement;
25
- }
26
- export interface ConfigPropertyElement {
27
- propertyType: string;
28
- options?: any[];
29
- label: string;
30
- }
31
- export interface AppActionDeclaration {
32
- handler: string;
33
- name: string;
34
- description?: string;
35
- actionConfiguration?: ConfigPropertyElements;
36
- }
37
- export interface AppTriggerDeclaration {
38
- key: string;
39
- name: string;
40
- external?: boolean;
41
- description?: string;
42
- }
43
- export interface App {
44
- id: string;
45
- identifier: string;
46
- name: string;
47
- public: boolean;
48
- description?: string;
49
- publisher: string;
50
- thumbnail: string;
51
- eventWorkflowTriggerKeyMapping: string;
52
- configProperties?: ConfigProperty[];
53
- triggerKeyDefinitions?: TriggerKeyDefinition[];
54
- }
55
- export declare class ConfigProperty {
56
- slug: string;
57
- propertyType: string;
58
- options?: any[];
59
- label: string;
60
- }
61
- export interface EventWorkflowActionDefinition {
62
- id?: string;
63
- identifier?: string;
64
- name?: string;
65
- executeFunctionString?: string;
66
- ownerKey?: string;
67
- public?: boolean;
68
- configProperties?: ConfigProperty[];
69
- isDockerBased?: boolean;
70
- }
71
- export declare class TriggerKeyDefinition {
72
- name: string;
73
- description?: string;
74
- triggerKey: string;
75
- external?: boolean;
76
- }
@@ -1,4 +0,0 @@
1
- export class ConfigProperty {
2
- }
3
- export class TriggerKeyDefinition {
4
- }
@@ -1,10 +0,0 @@
1
- import { App, AppDeclaration, WorkflowTemplateDeclaration } from './interfaces';
2
- export declare class WorkflowDeployer {
3
- deployWorkflows(appDeclaration: AppDeclaration, app: App): Promise<void>;
4
- getWorkflowsForApp(app: App): Promise<any>;
5
- deployWorkflow(workflowKey: string, workflow: WorkflowTemplateDeclaration, app: App, existingWorkflows: Array<any>, appDeclaration: AppDeclaration): Promise<any>;
6
- private createNewWorkflowDefinition;
7
- private populateActionIds;
8
- private updateWorkflowDefinition;
9
- getWorkflowDeclarationIdentifier(actionKey: any, app: App): string;
10
- }
@@ -1,87 +0,0 @@
1
- import { Entities } from '@contrail/sdk';
2
- import chalk from 'chalk';
3
- import { getActionDeclarationIdentifier, getActionsForApp } from './actions-deployer';
4
- export class WorkflowDeployer {
5
- async deployWorkflows(appDeclaration, app) {
6
- // FETCH ALL WORKFLOWS FROM THE API.
7
- const existingWorkflows = await this.getWorkflowsForApp(app);
8
- // UPSERT / DELETE BASED ON WORKFLOW IDENTIFIER
9
- console.log('%s \tDeploying workflows.', chalk.yellow.bold('WORKFLOW'));
10
- for (const workflowKey of Object.keys(appDeclaration.workflows)) {
11
- await this.deployWorkflow(workflowKey, appDeclaration.workflows[workflowKey], app, existingWorkflows, appDeclaration);
12
- }
13
- }
14
- async getWorkflowsForApp(app) {
15
- return await new Entities().get({
16
- entityName: 'event-workflow-template',
17
- criteria: { ownerKey: `app:${app.id}` },
18
- });
19
- }
20
- async deployWorkflow(workflowKey, workflow, app, existingWorkflows, appDeclaration) {
21
- console.log(`%s \tDeploying workflow: ${workflowKey}`, chalk.yellow.bold('WORKFLOW'));
22
- const identifier = this.getWorkflowDeclarationIdentifier(workflowKey, app);
23
- const existingDefinition = existingWorkflows.find(ad => ad.identifier === identifier);
24
- if (existingDefinition) {
25
- return await this.updateWorkflowDefinition(existingDefinition, workflow, app, appDeclaration);
26
- }
27
- return await this.createNewWorkflowDefinition(workflowKey, workflow, app, appDeclaration);
28
- }
29
- async createNewWorkflowDefinition(workflowKey, workflowDeclaration, app, appDeclaration) {
30
- await this.populateActionIds(workflowDeclaration, appDeclaration, app);
31
- const newObject = {
32
- identifier: this.getWorkflowDeclarationIdentifier(workflowKey, app),
33
- name: workflowDeclaration.name,
34
- ownerKey: `app:${app.id}`,
35
- triggerKey: workflowDeclaration.triggerKey,
36
- workflowDefinition: workflowDeclaration.workflowDefinition,
37
- isActive: workflowDeclaration.isActive,
38
- supportingAppId: workflowDeclaration.supportingAppId,
39
- messageGroupId: workflowDeclaration.messageGroupId,
40
- parallelWorkerCount: workflowDeclaration.parallelWorkerCount,
41
- };
42
- const workflowTemplate = await new Entities().create({
43
- entityName: 'event-workflow-template',
44
- object: newObject,
45
- });
46
- console.log(`%s Created new workflow definition: ${workflowKey}`, chalk.yellow.bold('WORKFLOW'));
47
- return workflowTemplate;
48
- }
49
- async populateActionIds(workflowDeclaration, appDeclaration, app) {
50
- var _a;
51
- let availableAppActions = await getActionsForApp(app);
52
- if (!((_a = workflowDeclaration.workflowDefinition) === null || _a === void 0 ? void 0 : _a.paths)) {
53
- return;
54
- }
55
- for (const path of workflowDeclaration.workflowDefinition.paths) {
56
- if (!(path === null || path === void 0 ? void 0 : path.actionDefinitionConfigs)) {
57
- continue;
58
- }
59
- for (const actionConfiguration of path.actionDefinitionConfigs) {
60
- const actionKey = actionConfiguration.action;
61
- const action = availableAppActions.find(action => action.identifier === getActionDeclarationIdentifier(actionKey, app));
62
- if (!action) {
63
- throw new Error(`Could not find action ${actionKey} declared in ${workflowDeclaration.name}`);
64
- }
65
- actionConfiguration.id = action.id;
66
- }
67
- }
68
- }
69
- async updateWorkflowDefinition(existingWorkflowDefinition, workflowDeclaration, app, appDeclaration) {
70
- await this.populateActionIds(workflowDeclaration, appDeclaration, app);
71
- const updates = Object.assign(new Object(), {
72
- name: workflowDeclaration.name,
73
- triggerKey: workflowDeclaration.triggerKey,
74
- workflowDefinition: workflowDeclaration.workflowDefinition
75
- });
76
- const updatedWorkflowDefinition = await new Entities().update({
77
- entityName: 'event-workflow-template',
78
- id: existingWorkflowDefinition.id,
79
- object: updates,
80
- });
81
- console.log(`%s Updated existing workflow definition: ${updatedWorkflowDefinition.identifier}`, chalk.yellow.bold('WORKFLOW'));
82
- return updatedWorkflowDefinition;
83
- }
84
- getWorkflowDeclarationIdentifier(actionKey, app) {
85
- return app.identifier + ':' + actionKey;
86
- }
87
- }