@kumologica/sdk 3.0.11 → 3.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/commands/build-commands/kumohub.js +46 -4
- package/package.json +6 -4
- package/src/app/lib/stores/settings-cloud-store.js +28 -25
- package/src/app/lib/stores/settings-network-store.js +0 -1
- package/src/app/lib/stores/test-config-store.js +152 -19
- package/src/app/lib/stores/util/iniParser.js +46 -0
- package/src/app/lib/stores/util/iniParser.spec.js +72 -0
- package/src/app/main-process/{runtime-manager.js → editor-manager.js} +44 -8
- package/src/app/main-process/main-window.js +6 -2
- package/src/app/main-process/modal-home.js +6 -2
- package/src/app/main-process/modal-newproject.js +6 -2
- package/src/app/main-process/modal-nodelibrary.js +6 -2
- package/src/app/main-process/modal-welcome.js +8 -3
- package/src/app/main.js +18 -14
- package/src/app/preload.js +33 -13
- package/src/app/ui/editor-client/public/red/red.js +395 -224
- package/src/app/ui/editor-client/public/red/red.min.js +1 -1
- package/src/app/ui/editor-client/public/red/style.min.css +1 -1
- package/src/app/ui/editor-client/public/vendor/kumologica/http-test-case.js +113 -0
- package/src/app/ui/editor-client/public/vendor/simplemde/simplemde.min.css +0 -7
- package/src/app/ui/editor-client/public/vendor/simplemde/simplemde.min.js +0 -15
- package/src/app/ui/editor-client/public/vendor/xterm/lib/xterm.js +0 -2
- package/src/app/ui/editor-client/src/js/ui/editor.js +2 -1
- package/src/app/ui/editor-client/src/js/ui/header.js +1 -1
- package/src/app/ui/editor-client/src/js/ui/logviewer.js +1 -1
- package/src/app/ui/editor-client/src/js/ui/project-info.js +3 -1
- package/src/app/ui/editor-client/src/js/ui/tab-azure.js +3 -3
- package/src/app/ui/editor-client/src/js/ui/tab-info.js +1 -1
- package/src/app/ui/editor-client/src/js/ui/tab-kumohub.js +26 -7
- package/src/app/ui/editor-client/src/js/ui/tab-test.js +134 -62
- package/src/app/ui/editor-client/src/js/ui/ui-settings.js +220 -143
- package/src/app/ui/editor-client/src/js/ui/view.js +5 -5
- package/src/app/ui/editor-client/src/sass/palette.scss +15 -0
- package/src/app/ui/editor-client/src/sass/tab-test.scss +9 -4
- package/src/app/ui/editor-client/src/sass/ui-settings.scss +7 -1
- package/src/app/ui/editor-client/src/vendor/kumologica/http-test-case.js +113 -0
|
@@ -1,7 +1,49 @@
|
|
|
1
|
-
exports.command = 'kumohub
|
|
2
|
-
exports.desc =
|
|
3
|
-
|
|
1
|
+
exports.command = 'kumohub';
|
|
2
|
+
exports.desc = `Builds kumohub binaries:
|
|
3
|
+
* generates kumohub artefacts
|
|
4
|
+
* runs npm install
|
|
5
|
+
* creates zip file
|
|
6
|
+
|
|
7
|
+
Documentation:
|
|
8
|
+
https://docs.kumologica.com/docs/references/cli/BuildKumohub.html`;
|
|
9
|
+
|
|
10
|
+
exports.builder = {
|
|
11
|
+
"flow-file-name": {
|
|
12
|
+
describe: "The name of kumologica flow file.\n Auto search if not provided.\n ",
|
|
13
|
+
type: 'string',
|
|
14
|
+
alias: 'f',
|
|
15
|
+
nargs: 1
|
|
16
|
+
},
|
|
17
|
+
"project-directory": {
|
|
18
|
+
describe: "The root directory of project.\n Current working directory if not provided.\n",
|
|
19
|
+
type: 'string',
|
|
20
|
+
alias: 'd',
|
|
21
|
+
nargs: 1
|
|
22
|
+
},
|
|
23
|
+
"zip-file-name": {
|
|
24
|
+
describe: "The name of zip file to be created",
|
|
25
|
+
type: 'string',
|
|
26
|
+
default: 'lambda.zip',
|
|
27
|
+
alias: 'z',
|
|
28
|
+
nargs: 1
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function display(argv) {
|
|
33
|
+
console.log(`\nBuilding kumohub artefacts with following parameters: \n`);
|
|
34
|
+
console.log('project-directory: %s', argv["project-directory"]||'');
|
|
35
|
+
console.log('flow-file-name: %s', argv["flow-file-name"]||'');
|
|
36
|
+
console.log('zip-file-name: %s', argv["zip-file-name"]||'');
|
|
37
|
+
}
|
|
4
38
|
|
|
5
39
|
exports.handler = function (argv) {
|
|
6
|
-
|
|
40
|
+
display(argv);
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
const { build } = require('@kumologica/builder');
|
|
44
|
+
build('kumohub', argv);
|
|
45
|
+
} catch (e) {
|
|
46
|
+
console.log(`${e.message}`);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
7
49
|
}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"productName": "Kumologica Designer",
|
|
4
4
|
"copyright": "Copyright 2020 Kumologica Pty Ltd, All Rights Reserved.",
|
|
5
5
|
"author": "Kumologica Pty Ltd <contact@kumologica.com>",
|
|
6
|
-
"version": "3.0.
|
|
6
|
+
"version": "3.0.12",
|
|
7
7
|
"description": "Kumologica Designer, harnessing Serverless for your cloud integration needs",
|
|
8
8
|
"main": "src/app/main.js",
|
|
9
9
|
"files": [
|
|
@@ -64,9 +64,10 @@
|
|
|
64
64
|
},
|
|
65
65
|
"license": "Proprietary",
|
|
66
66
|
"dependencies": {
|
|
67
|
-
"@
|
|
68
|
-
"@kumologica/
|
|
69
|
-
"@kumologica/devkit": "3.0.
|
|
67
|
+
"@electron/remote": "^2.0.8",
|
|
68
|
+
"@kumologica/builder": "3.0.12",
|
|
69
|
+
"@kumologica/devkit": "3.0.12",
|
|
70
|
+
"@kumologica/runtime": "3.0.12",
|
|
70
71
|
"adm-zip": "0.4.13",
|
|
71
72
|
"ajv": "8.10.0",
|
|
72
73
|
"aws-sdk": "2.513.0",
|
|
@@ -112,6 +113,7 @@
|
|
|
112
113
|
"simplemde": "1.11.2",
|
|
113
114
|
"smoketail": "0.2.2",
|
|
114
115
|
"socket.io": "2.3.0",
|
|
116
|
+
"tcp-port-used": "1.0.2",
|
|
115
117
|
"util": "0.12.1",
|
|
116
118
|
"when": "3.7.8",
|
|
117
119
|
"ws": "7.1.1",
|
|
@@ -1,30 +1,33 @@
|
|
|
1
1
|
// properties: ~/.kumologica/credentials
|
|
2
2
|
|
|
3
|
-
const defaultContent =
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
3
|
+
const defaultContent = `; This file contains all your sensitive credential information
|
|
4
|
+
; about your cloud connections used by Kumologica Designer.
|
|
5
|
+
; For more information visit https://docs.kumologica.com/settings
|
|
6
|
+
;
|
|
7
|
+
; Examples:
|
|
8
|
+
|
|
9
|
+
; =============== Kumohub Details =======================
|
|
10
|
+
; Follow the format for this section as: "kumohub.<alias>"
|
|
11
|
+
; =======================================================
|
|
12
|
+
; [kumohub.default]
|
|
13
|
+
; username = your-username
|
|
14
|
+
; password = your-password
|
|
15
|
+
; subscription = kumohub-subscription-id
|
|
16
|
+
|
|
17
|
+
; ============= AWS Cloud Details =======================
|
|
18
|
+
; Follow the format for this section as: "aws.<alias>"
|
|
19
|
+
; =======================================================
|
|
20
|
+
; [aws.development]
|
|
21
|
+
; profile = your-defined-aws-profile
|
|
22
|
+
|
|
23
|
+
; ============= Azure Cloud Details =====================
|
|
24
|
+
; Follow the format for this section as: "azure.<alias>"
|
|
25
|
+
; =======================================================
|
|
26
|
+
; [azure.default]
|
|
27
|
+
; subscription_id = 00000000-0000-0000-0000-000000000000
|
|
28
|
+
; client_id = 00000000-0000-0000-0000-000000000000
|
|
29
|
+
; client_secret = 0000000000000000000000000000000
|
|
30
|
+
; tenant_id = 00000000-0000-0000-0000-000000000000
|
|
28
31
|
`
|
|
29
32
|
|
|
30
33
|
const os = require('os');
|
|
@@ -1,26 +1,159 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
const {
|
|
2
|
+
getVariablesByConfigAndSection,
|
|
3
|
+
getSectionsByText
|
|
4
|
+
} = require('./util/iniParser');
|
|
5
|
+
|
|
6
|
+
const NO_ENVIRONMENT = "__no_environment__";
|
|
7
|
+
|
|
8
|
+
const KEYS = {
|
|
9
|
+
ROOT_KEY: "test",
|
|
10
|
+
ENVIRONMENTS: "environments",
|
|
11
|
+
TESTCASE_OLD: "test",
|
|
12
|
+
PROPERTIES_OLD: "properties",
|
|
13
|
+
TESTCASE: "testcase",
|
|
14
|
+
ENVIRONMENT: "environment"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const DEFAULT_ENVIRONMENTS = [
|
|
18
|
+
"; ===========================================================",
|
|
19
|
+
"; Environment variables must be defined under one section",
|
|
20
|
+
"; You can define as many sections as you need.",
|
|
21
|
+
"; (Remove the semicolons to uncomment the lines)",
|
|
22
|
+
"; ===========================================================",
|
|
23
|
+
"",
|
|
24
|
+
"; Example:",
|
|
25
|
+
"",
|
|
26
|
+
"; [development] ",
|
|
27
|
+
"; KUMOLOGICA_LOGLEVEL=DEBUG",
|
|
28
|
+
"; VAR_1=VALUE_1",
|
|
29
|
+
"",
|
|
30
|
+
"; [test]",
|
|
31
|
+
"; KUMOLOGICA_LOGLEVEL=ERROR",
|
|
32
|
+
"; VAR_1=VALUE_1",
|
|
33
|
+
]
|
|
5
34
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
35
|
+
const Store = require('./store');
|
|
36
|
+
|
|
37
|
+
class TestConfigStore extends Store {
|
|
38
|
+
|
|
39
|
+
constructor(defaults) {
|
|
40
|
+
super({ ...defaults, configName: '.kumologica/test-config', defaults: {}});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
getConfigFileFullPath() {
|
|
44
|
+
return this.path;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
getTestConfig() {
|
|
48
|
+
let config = super.get(KEYS.ROOT_KEY);
|
|
49
|
+
|
|
50
|
+
// Decorate with default environments if not persisted
|
|
51
|
+
config = this.convertToLatestVersion(config);
|
|
52
|
+
|
|
53
|
+
// check whether is first time, i.e. config is empty
|
|
54
|
+
if (!config) {
|
|
55
|
+
config = {};
|
|
56
|
+
config[KEYS.TESTCASE] = "__runAll";
|
|
57
|
+
config[KEYS.ENVIRONMENT] = NO_ENVIRONMENT;
|
|
58
|
+
config[KEYS.ENVIRONMENTS] = DEFAULT_ENVIRONMENTS;
|
|
59
|
+
super.set(KEYS.ROOT_KEY, config);
|
|
12
60
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
61
|
+
|
|
62
|
+
return config;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
convertToLatestVersion(config) {
|
|
66
|
+
let newConfig = config;
|
|
67
|
+
if (newConfig){
|
|
68
|
+
if (newConfig.hasOwnProperty(KEYS.TESTCASE_OLD)){
|
|
69
|
+
// replace: "config.test" -> "config.testcase"
|
|
70
|
+
newConfig[KEYS.TESTCASE] = newConfig[KEYS.TESTCASE_OLD];
|
|
71
|
+
delete newConfig[KEYS.TESTCASE_OLD];
|
|
72
|
+
// select "config.environment" = no_environment
|
|
73
|
+
newConfig[KEYS.ENVIRONMENT] = NO_ENVIRONMENT;
|
|
74
|
+
// append the old properties to the new environment
|
|
75
|
+
newConfig[KEYS.ENVIRONMENTS] = DEFAULT_ENVIRONMENTS;
|
|
76
|
+
if (newConfig.hasOwnProperty(KEYS.PROPERTIES_OLD)){
|
|
77
|
+
let props = newConfig[KEYS.PROPERTIES_OLD];
|
|
78
|
+
newConfig[KEYS.ENVIRONMENTS].push('[old-properties]');
|
|
79
|
+
for (const [key, value] of Object.entries(props)) {
|
|
80
|
+
newConfig[KEYS.ENVIRONMENTS].push(`${key}=${value}`);
|
|
81
|
+
}
|
|
82
|
+
delete newConfig[KEYS.PROPERTIES_OLD];
|
|
83
|
+
// persist the new model
|
|
84
|
+
super.set(KEYS.ROOT_KEY, newConfig);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
16
87
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
88
|
+
return newConfig;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
saveTestValuesIntoConfig(value) {
|
|
92
|
+
let config = this.getTestConfig();
|
|
93
|
+
config[KEYS.ENVIRONMENT] = this.listEnvironments().includes(value[KEYS.ENVIRONMENT])?value[KEYS.ENVIRONMENT]: NO_ENVIRONMENT;
|
|
94
|
+
config[KEYS.TESTCASE] = value[KEYS.TESTCASE];
|
|
95
|
+
super.set(KEYS.ROOT_KEY, config);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
saveEnvironmentSectionIntoConfig(text) {
|
|
99
|
+
let config = this.getTestConfig();
|
|
100
|
+
config[KEYS.ENVIRONMENTS] = this.convertTextIntoArray(text);
|
|
101
|
+
super.set(KEYS.ROOT_KEY, config);
|
|
102
|
+
// If selected environment is not longer available, lets default it to no_environment
|
|
103
|
+
if (!this.listEnvironments().includes(config[KEYS.ENVIRONMENT])) {
|
|
104
|
+
config[KEYS.ENVIRONMENTS] = this.convertTextIntoArray(text);
|
|
105
|
+
config[KEYS.ENVIRONMENT] = NO_ENVIRONMENT;
|
|
106
|
+
super.set(KEYS.ROOT_KEY, config);
|
|
20
107
|
}
|
|
21
108
|
}
|
|
22
109
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
110
|
+
getEnvironmentSectionFromConfig() {
|
|
111
|
+
return this.convertArrayIntoText(this.getTestConfig()[KEYS.ENVIRONMENTS]);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
getLatestSelectedEnvironment() {
|
|
115
|
+
let config = this.getTestConfig();
|
|
116
|
+
return (config.hasOwnProperty(KEYS.ENVIRONMENT))? config[KEYS.ENVIRONMENT]: NO_ENVIRONMENT;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
getLatestSelectedTestCase() {
|
|
120
|
+
let config = this.getTestConfig();
|
|
121
|
+
if (config){
|
|
122
|
+
if (config.hasOwnProperty(KEYS.TESTCASE)) {
|
|
123
|
+
return config[KEYS.TESTCASE];
|
|
124
|
+
} else if (config.hasOwnProperty(KEYS.TESTCASE_OLD)) {
|
|
125
|
+
return config[KEYS.TESTCASE_OLD];
|
|
126
|
+
} else {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
listEnvironments() {
|
|
134
|
+
let enviromentAsText = this.convertArrayIntoText(this.getTestConfig()[KEYS.ENVIRONMENTS])
|
|
135
|
+
return getSectionsByText(enviromentAsText);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
listVariablesByEnvironment(section) {
|
|
139
|
+
let environmentSelected = section;
|
|
140
|
+
if (!environmentSelected) {
|
|
141
|
+
environmentSelected = this.getLatestSelectedEnvironment();
|
|
142
|
+
}
|
|
143
|
+
let aEnvironments = this.getTestConfig()[KEYS.ENVIRONMENTS];
|
|
144
|
+
return getVariablesByConfigAndSection(this.convertArrayIntoText(aEnvironments), environmentSelected);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
convertTextIntoArray(text){
|
|
148
|
+
let lines = text.split(/\r\n|\n/);
|
|
149
|
+
return lines.map(l => l.trim());
|
|
150
|
+
}
|
|
151
|
+
convertArrayIntoText(lines) {
|
|
152
|
+
return lines.join('\r\n');
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
module.exports = {
|
|
157
|
+
TestConfigStore
|
|
158
|
+
};
|
|
26
159
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const ini = require('ini');
|
|
2
|
+
|
|
3
|
+
function parseStringToConfig(text) {
|
|
4
|
+
let config = ini.parse(text);
|
|
5
|
+
return config;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function getSectionsByText(text) {
|
|
9
|
+
let config = parseStringToConfig(text);
|
|
10
|
+
let keys = [];
|
|
11
|
+
if (config) {
|
|
12
|
+
keys = Object.keys(config);
|
|
13
|
+
keys= keys.filter(section => isValidSection(section, config))
|
|
14
|
+
}
|
|
15
|
+
return keys;
|
|
16
|
+
}
|
|
17
|
+
function getVariablesByConfigAndSection(environmentsAsText, section){
|
|
18
|
+
let oEnvironments = parseStringToConfig(environmentsAsText);
|
|
19
|
+
let variables = [];
|
|
20
|
+
|
|
21
|
+
if (oEnvironments){
|
|
22
|
+
if (oEnvironments[section]){
|
|
23
|
+
for (const [key, value] of Object.entries(oEnvironments[section])) {
|
|
24
|
+
variables.push({ key, value })
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
return variables;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function isValidSection(section, config) {
|
|
34
|
+
return (
|
|
35
|
+
section !== '__no_environment__' &&
|
|
36
|
+
!section.trim().startsWith('//') &&
|
|
37
|
+
!section.trim().startsWith('#') &&
|
|
38
|
+
typeof config[section] == 'object' && Object.entries(config[section]).length > 0
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
module.exports = {
|
|
43
|
+
parseStringToConfig,
|
|
44
|
+
getSectionsByText,
|
|
45
|
+
getVariablesByConfigAndSection
|
|
46
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
|
|
2
|
+
const chai = require('chai');
|
|
3
|
+
const {
|
|
4
|
+
parseStringToConfig,
|
|
5
|
+
getSectionsByText,
|
|
6
|
+
getVariablesByConfigAndSection } = require('./iniParser');
|
|
7
|
+
|
|
8
|
+
let assert = chai.assert;
|
|
9
|
+
|
|
10
|
+
const ENVIRONMENTS_WITH_COMMENTS = `
|
|
11
|
+
// comment
|
|
12
|
+
; hola amigos
|
|
13
|
+
; this is comments
|
|
14
|
+
[dev]
|
|
15
|
+
url=http://dev.good.url.com
|
|
16
|
+
private=false
|
|
17
|
+
[test]
|
|
18
|
+
url=http://test.good.url.com
|
|
19
|
+
private=true
|
|
20
|
+
`;
|
|
21
|
+
const ENVIRONMENTS_WITHOUT_SECTIONS = ``;
|
|
22
|
+
|
|
23
|
+
const ENVIRONMENTS_WRONG_FORMAT = `
|
|
24
|
+
// comment
|
|
25
|
+
; hola amigos
|
|
26
|
+
; this is comments
|
|
27
|
+
[dev]
|
|
28
|
+
url
|
|
29
|
+
private = false
|
|
30
|
+
USER == test123
|
|
31
|
+
password=asdfa salutation=hello
|
|
32
|
+
`;
|
|
33
|
+
|
|
34
|
+
const ENVIRONMENTS_MISSING_SECTION = `
|
|
35
|
+
// comment
|
|
36
|
+
; hola amigos
|
|
37
|
+
; this is comments
|
|
38
|
+
;;[dev]
|
|
39
|
+
url = true
|
|
40
|
+
|
|
41
|
+
[test]
|
|
42
|
+
url = hola
|
|
43
|
+
|
|
44
|
+
`;
|
|
45
|
+
|
|
46
|
+
describe('parse correctly a environment section', () => {
|
|
47
|
+
it('happy path', () => {
|
|
48
|
+
let config = parseStringToConfig(ENVIRONMENTS_WITH_COMMENTS)
|
|
49
|
+
let sections = getSectionsByText(ENVIRONMENTS_WITH_COMMENTS);
|
|
50
|
+
assert.equal(sections.length, 2);
|
|
51
|
+
|
|
52
|
+
let vars = getVariablesByConfigAndSection(config, sections[0]);
|
|
53
|
+
assert.equal(vars.length, 2);
|
|
54
|
+
});
|
|
55
|
+
it('No sections available', () => {
|
|
56
|
+
let sections = getSectionsByText(ENVIRONMENTS_WITHOUT_SECTIONS);
|
|
57
|
+
assert.equal(sections.length, 0);
|
|
58
|
+
});
|
|
59
|
+
it('Variables not correct', () => {
|
|
60
|
+
let config = parseStringToConfig(ENVIRONMENTS_WRONG_FORMAT)
|
|
61
|
+
let sections = getSectionsByText(ENVIRONMENTS_WRONG_FORMAT);
|
|
62
|
+
let vars = getVariablesByConfigAndSection(config, sections[0]);
|
|
63
|
+
assert.equal(vars.length, 4);
|
|
64
|
+
})
|
|
65
|
+
it('Detecting missing sections', () => {
|
|
66
|
+
let sections = getSectionsByText(ENVIRONMENTS_MISSING_SECTION);
|
|
67
|
+
console.log(sections);
|
|
68
|
+
//let vars = getVariablesByConfigAndSection(config, sections[0]);
|
|
69
|
+
//assert.equal(vars.length, 4);
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
});
|
|
@@ -1,17 +1,39 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
const fs = require('fs-extra');
|
|
3
|
-
const { dialog } = require('electron')
|
|
3
|
+
const { dialog } = require('electron');
|
|
4
|
+
const tcpPortUsed = require('tcp-port-used');
|
|
4
5
|
const { findAllFlowFiles } = require('../lib/utils/editor');
|
|
5
6
|
|
|
6
7
|
const editorApi = require('../ui/editor-api/lib');
|
|
7
8
|
const { AppServer } = require('../lib/runtime-loader');
|
|
8
9
|
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
async function allocatePort(port) {
|
|
12
|
+
let inUse = await tcpPortUsed.check(port);
|
|
13
|
+
if (inUse){
|
|
14
|
+
let newPort = ++port;
|
|
15
|
+
console.log(`> Port: ${port} in use. Trying with port: ${newPort}...`);
|
|
16
|
+
return await allocatePort(newPort);
|
|
17
|
+
} else{
|
|
18
|
+
return port;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
class EditorManagerClass {
|
|
11
24
|
currentUserProjectDir = null;
|
|
12
25
|
previousUserProjectDir = null;
|
|
13
26
|
appServer = null;
|
|
27
|
+
port = 1880;
|
|
28
|
+
|
|
29
|
+
constructor() {
|
|
30
|
+
this.start = this.start.bind(this);
|
|
31
|
+
this.readEnv = this.readEnv.bind(this);
|
|
32
|
+
this.getPort = this.getPort.bind(this);
|
|
33
|
+
this.setPort = this.setPort.bind(this);
|
|
34
|
+
this.stop = this.stop.bind(this);
|
|
14
35
|
|
|
36
|
+
}
|
|
15
37
|
async start(userProjectDir, startupEmitter) {
|
|
16
38
|
// *** Hack:
|
|
17
39
|
// Do not start a new appServer if the project is the current one already running
|
|
@@ -34,6 +56,10 @@ class RuntimeManager {
|
|
|
34
56
|
if (this.appServer !== null) {
|
|
35
57
|
await this.appServer.stop();
|
|
36
58
|
}
|
|
59
|
+
// Check ports availability
|
|
60
|
+
let portAllocated = await allocatePort(this.getPort());
|
|
61
|
+
this.setPort(portAllocated);
|
|
62
|
+
console.log(`> Starting editor on port: ${this.getPort()}...`);
|
|
37
63
|
|
|
38
64
|
// Backwards compatibility check
|
|
39
65
|
const constParams = AppServer.length;
|
|
@@ -41,7 +67,7 @@ class RuntimeManager {
|
|
|
41
67
|
// Runtime <= 2.0.11
|
|
42
68
|
this.appServer = new AppServer(
|
|
43
69
|
flowFilePath, // full path of the flow.json file
|
|
44
|
-
|
|
70
|
+
this.getPort(), // port
|
|
45
71
|
AppServer.mode.HEADFUL_DEFAULT_EXPRESS,
|
|
46
72
|
undefined, //loglevel
|
|
47
73
|
editorApi,
|
|
@@ -50,7 +76,7 @@ class RuntimeManager {
|
|
|
50
76
|
this.appServer = new AppServer({
|
|
51
77
|
projectDir: this.currentUserProjectDir,
|
|
52
78
|
flowFilePath: flowFilePath,
|
|
53
|
-
port:
|
|
79
|
+
port: this.getPort(),
|
|
54
80
|
serverMode: AppServer.mode.HEADFUL_DEFAULT_EXPRESS,
|
|
55
81
|
logLevel: undefined,
|
|
56
82
|
editorApi: editorApi,
|
|
@@ -59,11 +85,13 @@ class RuntimeManager {
|
|
|
59
85
|
} else {
|
|
60
86
|
throw new Error('Runtime version is incompatible with this designer');
|
|
61
87
|
}
|
|
62
|
-
|
|
88
|
+
|
|
89
|
+
// Persist the server settings in the window global scope for the ui to access.
|
|
63
90
|
await this.appServer.start();
|
|
64
91
|
return flowFilePath;
|
|
65
92
|
} catch (err) {
|
|
66
|
-
|
|
93
|
+
console.log('Editor Manager cannot be started. Reason:', err.code);
|
|
94
|
+
throw err;
|
|
67
95
|
}
|
|
68
96
|
}
|
|
69
97
|
|
|
@@ -82,6 +110,14 @@ class RuntimeManager {
|
|
|
82
110
|
return undefined;
|
|
83
111
|
}
|
|
84
112
|
|
|
113
|
+
getPort() {
|
|
114
|
+
return this.port;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
setPort(newPort) {
|
|
118
|
+
this.port = newPort;
|
|
119
|
+
}
|
|
120
|
+
|
|
85
121
|
/**
|
|
86
122
|
* Originally after promise is resolved it invoked `process.exit()`
|
|
87
123
|
* @returns a promise
|
|
@@ -119,7 +155,6 @@ class RuntimeManager {
|
|
|
119
155
|
properties: ['openFile']
|
|
120
156
|
});
|
|
121
157
|
if (flowFile){
|
|
122
|
-
console.log('[runtime-manager] flowFile = ', flowFile);
|
|
123
158
|
return flowFile[0];
|
|
124
159
|
} else {
|
|
125
160
|
throw new Error('A valid flow file must be selected')
|
|
@@ -137,5 +172,6 @@ class RuntimeManager {
|
|
|
137
172
|
}
|
|
138
173
|
// onClose(fn) {
|
|
139
174
|
}
|
|
175
|
+
const editorManager = new EditorManagerClass();
|
|
140
176
|
|
|
141
|
-
module.exports =
|
|
177
|
+
module.exports = editorManager;
|
|
@@ -5,6 +5,7 @@ const url = require('url');
|
|
|
5
5
|
const { defaultKeys } = require('../lib/stores/user-preference-store');
|
|
6
6
|
const { BrowserWindow } = electron;
|
|
7
7
|
const EventEmitter = require('events');
|
|
8
|
+
|
|
8
9
|
let { ipcMain } = electron;
|
|
9
10
|
|
|
10
11
|
// using electron-updater instead of builtin autoUpdater
|
|
@@ -12,6 +13,7 @@ let { ipcMain } = electron;
|
|
|
12
13
|
const { autoUpdater } = require('electron-updater');
|
|
13
14
|
|
|
14
15
|
const preloadJsPath = path.join(__dirname, '..', 'preload.js');
|
|
16
|
+
const editorManager = require('./editor-manager');
|
|
15
17
|
|
|
16
18
|
class MainWindow {
|
|
17
19
|
window = null;
|
|
@@ -42,7 +44,9 @@ class MainWindow {
|
|
|
42
44
|
webPreferences: {
|
|
43
45
|
nodeIntegration: false,
|
|
44
46
|
preload: preloadJsPath,
|
|
45
|
-
contextIsolation: false
|
|
47
|
+
contextIsolation: false,
|
|
48
|
+
enableRemoteModule: true,
|
|
49
|
+
additionalArguments: [`--port=${editorManager.getPort()}`]
|
|
46
50
|
},
|
|
47
51
|
show: false,
|
|
48
52
|
icon: path.join(__dirname, '../ui/editor-client/src/kumologica-app.png'),
|
|
@@ -120,7 +124,7 @@ class MainWindow {
|
|
|
120
124
|
load() {
|
|
121
125
|
this.window.loadURL(
|
|
122
126
|
url.format({
|
|
123
|
-
pathname:
|
|
127
|
+
pathname: `127.0.0.1:${editorManager.getPort()}`,
|
|
124
128
|
protocol: 'http:',
|
|
125
129
|
slashes: true,
|
|
126
130
|
}),
|
|
@@ -3,6 +3,8 @@ const path = require('path');
|
|
|
3
3
|
const url = require('url');
|
|
4
4
|
const EventEmitter = require('events');
|
|
5
5
|
const dependencies = require('../lib/dependencies.js');
|
|
6
|
+
const editorManager = require('./editor-manager');
|
|
7
|
+
const PORT = editorManager.getPort();
|
|
6
8
|
|
|
7
9
|
const { BrowserWindow } = electron;
|
|
8
10
|
const preloadJsPath = path.join(__dirname, '..', 'preload.js');
|
|
@@ -30,7 +32,9 @@ class ModalHome {
|
|
|
30
32
|
webPreferences: {
|
|
31
33
|
nodeIntegration: false,
|
|
32
34
|
preload: preloadJsPath,
|
|
33
|
-
contextIsolation: false
|
|
35
|
+
contextIsolation: false,
|
|
36
|
+
enableRemoteModule: true,
|
|
37
|
+
additionalArguments: [`--port=${PORT}`]
|
|
34
38
|
},
|
|
35
39
|
show: false
|
|
36
40
|
};
|
|
@@ -79,7 +83,7 @@ class ModalHome {
|
|
|
79
83
|
load() {
|
|
80
84
|
this.window.loadURL(
|
|
81
85
|
url.format({
|
|
82
|
-
pathname:
|
|
86
|
+
pathname: `127.0.0.1:${PORT}/__home`,
|
|
83
87
|
protocol: 'http:',
|
|
84
88
|
slashes: true
|
|
85
89
|
}),
|
|
@@ -3,6 +3,8 @@ const path = require('path');
|
|
|
3
3
|
const url = require('url');
|
|
4
4
|
const { BrowserWindow } = electron;
|
|
5
5
|
const preloadJsPath = path.join(__dirname, '..', 'preload.js');
|
|
6
|
+
const editorManager = require('./editor-manager');
|
|
7
|
+
const PORT = editorManager.getPort();
|
|
6
8
|
|
|
7
9
|
class ModalNewProject {
|
|
8
10
|
// Properties
|
|
@@ -26,12 +28,14 @@ class ModalNewProject {
|
|
|
26
28
|
nodeIntegration: false,
|
|
27
29
|
preload: preloadJsPath,
|
|
28
30
|
enableRemoteModule: true,
|
|
29
|
-
contextIsolation: false
|
|
31
|
+
contextIsolation: false,
|
|
32
|
+
additionalArguments: [`--port=${PORT}`]
|
|
30
33
|
},
|
|
31
34
|
show: false,
|
|
32
35
|
};
|
|
33
36
|
|
|
34
37
|
this.window = new BrowserWindow(windowOptions);
|
|
38
|
+
require("@electron/remote/main").enable(this.window.webContents);
|
|
35
39
|
// this.window.webContents.openDevTools();
|
|
36
40
|
|
|
37
41
|
this.window.on('focus', () => this.window.webContents.send('focus'));
|
|
@@ -56,7 +60,7 @@ class ModalNewProject {
|
|
|
56
60
|
load() {
|
|
57
61
|
this.window.loadURL(
|
|
58
62
|
url.format({
|
|
59
|
-
pathname:
|
|
63
|
+
pathname: `127.0.0.1:${PORT}/__newProject`,
|
|
60
64
|
protocol: 'http:',
|
|
61
65
|
slashes: true,
|
|
62
66
|
}),
|