@kumologica/sdk 3.5.4 → 3.6.0-alpha7

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.
Files changed (36) hide show
  1. package/cli/cli.js +31 -8
  2. package/cli/commands/open.js +88 -15
  3. package/cli/commands/run.js +167 -0
  4. package/cli/commands/serve.js +139 -0
  5. package/package.json +5 -5
  6. package/src/app/main-process/main-window.js +1 -0
  7. package/src/app/main-process/modal-home.js +1 -0
  8. package/src/app/main-process/modal-newproject.js +1 -0
  9. package/src/app/main-process/modal-newtab.js +1 -0
  10. package/src/app/main-process/modal-nodelibrary.js +1 -0
  11. package/src/app/main-process/modal-renameTab.js +1 -0
  12. package/src/app/main-process/modal-welcome.js +1 -0
  13. package/src/app/main.js +179 -141
  14. package/src/app/preload.js +225 -139
  15. package/src/app/ui/editor-client/public/red/red.js +1943 -783
  16. package/src/app/ui/editor-client/public/red/red.min.js +2 -2
  17. package/src/app/ui/editor-client/public/red/style.min.css +1 -1
  18. package/src/app/ui/editor-client/public/vendor/ace-linters/javascript-service.js +10 -2
  19. package/src/app/ui/editor-client/src/js/red.js +183 -179
  20. package/src/app/ui/editor-client/src/js/ui/common/commandBox.js +107 -0
  21. package/src/app/ui/editor-client/src/js/ui/common/searchBox.js +91 -90
  22. package/src/app/ui/editor-client/src/js/ui/modules.js +164 -0
  23. package/src/app/ui/editor-client/src/js/ui/search.js +171 -123
  24. package/src/app/ui/editor-client/src/js/ui/sidebar.js +1 -1
  25. package/src/app/ui/editor-client/src/js/ui/ui-settings.js +419 -410
  26. package/src/app/ui/editor-client/src/sass/editor.scss +745 -746
  27. package/src/app/ui/editor-client/src/sass/forms.scss +1 -1
  28. package/src/app/ui/editor-client/src/sass/search.scss +16 -2
  29. package/src/app/ui/editor-client/src/sass/sidebar.scss +1 -1
  30. package/src/app/ui/editor-client/src/sass/style.scss +72 -69
  31. package/src/app/ui/editor-client/src/sass/ui/common/commandBox.scss +100 -0
  32. package/src/app/ui/editor-client/src/sass/ui/common/searchBox.scss +3 -2
  33. package/src/app/ui/editor-client/src/sass/ui-settings.scss +14 -14
  34. package/src/app/ui/editor-client/src/vendor/ace-linters/build/javascript-service.js +10 -2
  35. package/src/app/ui/editor-client/templates/index.mst +2 -2
  36. package/src/server/DesignerServer.js +152 -153
package/cli/cli.js CHANGED
@@ -1,9 +1,32 @@
1
- const chalk = require('chalk');
1
+ const { logError } = require("./utils/logger"); //("../utils/logger");
2
2
 
3
- require('yargs/yargs')(process.argv.slice(2))
4
- .commandDir('commands')
5
- .demandCommand()
6
- .help('help', 'Show usage information & exit')
7
- .alias('help', 'h')
8
- // .epilog("copyright 2021")
9
- .argv
3
+ const validCommands = [
4
+ "build",
5
+ "create-node",
6
+ "create",
7
+ "doc",
8
+ "export",
9
+ "list-templates",
10
+ "login",
11
+ "open",
12
+ "serve",
13
+ "run",
14
+ "test",
15
+ ];
16
+
17
+ require("yargs/yargs")(process.argv.slice(2))
18
+ .commandDir("commands")
19
+ .demandCommand(1, "Error: Command missing.")
20
+ .check((argv) => {
21
+ if (!validCommands.includes(argv._[0].toLowerCase())) {
22
+ throw new Error(`Unknown command: ${argv._[0]}. `);
23
+ }
24
+ return true;
25
+ })
26
+ .help("help", "Show usage information & exit")
27
+ .alias("help", "h")
28
+ .fail((msg, err, yargs) => {
29
+ logError(msg);
30
+ yargs.showHelp();
31
+ process.exit(1);
32
+ }).argv;
@@ -1,9 +1,38 @@
1
1
  const path = require('path');
2
2
  const { spawn } = require("child_process");
3
3
  const { Updater } = require('@kumologica/builder');
4
+ const { confirm } = require('enquirer');
4
5
 
5
6
  const { logError } = require('../utils/logger');
6
- const rootPath = path.join(__dirname, '..', '..',);
7
+ const rootPath = path.join(__dirname, '..', '..', '..', '..');
8
+
9
+ function displayTable(data) {
10
+ if (!data.length) {
11
+ return;
12
+ }
13
+
14
+ // Get the keys (property names) from the first row
15
+ const keys = Object.keys(data[0]);
16
+
17
+ // Get the maximum width for each column
18
+ const colWidths = keys.map(key =>
19
+ Math.max(...data.map(row => row[key].length), key.length) // Include header (key) length
20
+ );
21
+
22
+ // Display the headers (property names)
23
+ const headerRow = keys
24
+ .map((key, i) => key.padEnd(colWidths[i])) // Align headers
25
+ .join(' '); // Add spaces between columns
26
+ console.log(headerRow);
27
+
28
+ // Display rows with left-aligned columns
29
+ data.forEach(row => {
30
+ const formattedRow = keys
31
+ .map((key, i) => row[key].padEnd(colWidths[i])) // Align row data
32
+ .join(' '); // Add spaces between columns
33
+ console.log(formattedRow);
34
+ });
35
+ }
7
36
 
8
37
  function startElectron(projectDir) {
9
38
  console.debug(`Project directory: ${projectDir}`);
@@ -31,17 +60,8 @@ function startElectron(projectDir) {
31
60
  });
32
61
  }
33
62
 
34
- async function updater(projectDir) {
35
- if (!projectDir) {
36
- console.debug("Project directory not provided, skipping upgrade check");
37
- return;
38
- }
39
-
40
- const { confirm } = require('enquirer');
41
-
42
- const updater = new Updater(projectDir);
43
- const updates = updater.updatesAvailable();
44
-
63
+ // Prompt to upgrade to aws sdk v3
64
+ async function promptV3(updates) {
45
65
  if (updates.v3) {
46
66
  console.log("");
47
67
  console.log("This project uses the deprecated aws-sdk v2. Migration to aws-sdk v3 is available.");
@@ -64,10 +84,63 @@ async function updater(projectDir) {
64
84
  }
65
85
  }
66
86
 
67
- await updater.update();
87
+ return "v3";
68
88
  }
69
89
  }
70
90
 
91
+ // prompt to upgrade to latest versions and run install
92
+ async function promptUpdates(updates) {
93
+ let displayPrompt = false;
94
+ if (updates.installs && updates.installs.length > 0) {
95
+ console.log("");
96
+ console.log("The following dependency versions are not installed and may affect your service logic:");
97
+ console.log("");
98
+ displayTable(updates.installs);
99
+ displayPrompt = true;
100
+ }
101
+
102
+ if (updates.updates && updates.updates.length > 0) {
103
+ console.log("");
104
+ console.log("The following dependencies have new versions available:");
105
+ console.log("");
106
+ displayTable(updates.updates);
107
+ console.log("");
108
+ displayPrompt = true;
109
+ }
110
+
111
+ if (displayPrompt) {
112
+ return await confirm({ initial: true, message: 'Do you wish to upgrade and install latest versions in your project?' });
113
+ }
114
+ return false;
115
+ }
116
+
117
+ /*
118
+ check if upgrade in npmjs to the existing ones in package.json
119
+ check if upgrade or missing node_modules vs package.json
120
+ check if missing node_modules
121
+ */
122
+ async function updater(projectDir) {
123
+ if (!projectDir) {
124
+ console.debug("Project directory not provided, skipping upgrade check");
125
+ return;
126
+ }
127
+ const updater = new Updater(projectDir);
128
+ const updates = await updater.checkForUpdates();
129
+
130
+ const upd = await promptUpdates(updates);
131
+ if (!upd) {
132
+ delete updates.updates;
133
+ delete updates.installs;
134
+ }
135
+
136
+ const v3 = await promptV3(updates);
137
+ if (!v3) {
138
+ delete updates.v3;
139
+ }
140
+
141
+ await updater.update(updates);
142
+ }
143
+
71
144
  exports.command = "open [project_directory]"
72
145
  exports.builder = (yargs) => {
73
146
  yargs.positional(`project_directory`, {
@@ -79,8 +152,8 @@ exports.builder = (yargs) => {
79
152
  exports.desc = 'Open Kumologica Designer'
80
153
 
81
154
  exports.handler = async ({ project_directory }) => {
82
- const projectDir = project_directory? path.resolve(project_directory): undefined ;
83
-
155
+ const projectDir = project_directory? path.resolve(project_directory): undefined;
84
156
  await updater(projectDir);
157
+
85
158
  startElectron(projectDir);
86
159
  }
@@ -0,0 +1,167 @@
1
+ /**
2
+ * This command should be used to start the kumologica runtime in local mode. And it will
3
+ * be assisting the UI on all aspects of the project development.
4
+ *
5
+ * Example:
6
+ * kl run ./myproject
7
+ * kl run ./myproject/flow.json
8
+ * kl run (this will look for a flow.json in the current directory)
9
+ *
10
+ * If not flow is found, the process will be exited (with code 1)
11
+ *
12
+ * The Runtime API can be found in: packages/runtime/src/runtime/lib/api/rest/index.js
13
+ * The actual runtime is in: packages/runtime/src/runtime/lib/index.js
14
+ *
15
+ * Naming convention used during the code:
16
+ * - AdminApp (express app) is the server that serves the Runtime API
17
+ * - NodeApp (express app) is the server that runs the flow
18
+ *
19
+ * DEVELOPER NOTE:
20
+ * Current implementation seems to be mounting the runtime api in the NodeApp (see runtime/lib/index.js:534)
21
+ * Ideally we would like to separate the two apps and have the AdminApp running on a different port.
22
+ *
23
+ */
24
+
25
+ const path = require("path");
26
+ const fs = require("fs");
27
+ const { codegen } = require("@kumologica/builder");
28
+ const { DesignerServer } = require("../../src/server/DesignerServer");
29
+ const { logError, logNotice, logInfo, logFatal } = require("../utils/logger");
30
+
31
+ exports.command = "run [project_directory]";
32
+ exports.desc = `Start a local HTTP server to execute task and then stops HTTP server and exit.`;
33
+
34
+ exports.builder = (yargs) => {
35
+ yargs.positional(`project_directory`, {
36
+ type: "string",
37
+ describe:
38
+ "Path to a valid kumologica project directory or flow file. (Optional)",
39
+ });
40
+ yargs.option(`loglevel`, {
41
+ describe: "Logging level: [error, warn, info, debug, trace]",
42
+ type: "string",
43
+ nargs: 1,
44
+ });
45
+ yargs.option(`port`, {
46
+ describe: "Specifies the listening port utilized by the application",
47
+ type: "number",
48
+ nargs: 1,
49
+ });
50
+ yargs.option(`taskName`, {
51
+ describe: "The name of the task.",
52
+ type: "string",
53
+ alias: "t",
54
+ nargs: 1,
55
+ });
56
+ yargs.option(`args`, {
57
+ describe: "The list of arguments, either '-a one two three' or '-a one -a two -a three' ",
58
+ type: "array",
59
+ alias: "a"
60
+ });
61
+ };
62
+
63
+ exports.handler = async ({ project_directory, loglevel, port, taskName, args }) => {
64
+ logNotice(`Starting HTTP Server...`);
65
+ let projectDirectory = project_directory || process.cwd();
66
+ // project_directory can point to a directory or a flow, so lets make sure that first the directory exists
67
+ let absProjectDirectory;
68
+ let exitCode = 1;
69
+ try {
70
+ absProjectDirectory = fs.realpathSync(projectDirectory);
71
+ } catch (err) {
72
+ logFatal(`Project not found: ${projectDirectory}`);
73
+ process.exit(exitCode);
74
+ }
75
+
76
+ try {
77
+ // Resolve the path to the flow path
78
+ const [projectFlowDirname, projectFlowFullPath] = resolveProjectFlowPath(absProjectDirectory);
79
+ logInfo(`> Flow file found: ${projectFlowFullPath}`);
80
+
81
+ // Gather all cli params
82
+ const cliParams = {
83
+ loglevel,
84
+ port,
85
+ noadmin: true,
86
+ };
87
+
88
+ // Start a server
89
+ let server = new DesignerServer({
90
+ flowPath: projectFlowFullPath,
91
+ cliParams,
92
+ });
93
+
94
+ await server.start();
95
+
96
+ const tName = taskName || process.env.taskName;
97
+ const req = {
98
+ method: 'POST',
99
+ headers: {
100
+ },
101
+ body: JSON.stringify({args: args})
102
+ };
103
+ const url = `http://127.0.0.1:${port||1880}/__task__/${tName}`;
104
+
105
+ const response = await fetch(url, req);
106
+ const data = await response.text();
107
+
108
+ logInfo("Status: " + response.status);
109
+ logInfo("Message: " + data);
110
+
111
+ await server.stop();
112
+
113
+ exitCode = response.status >= 200 && response.status < 300 ? 0 : 1;
114
+
115
+ } catch (e) {
116
+ logFatal(e.message);
117
+ }
118
+
119
+ process.exit(exitCode);
120
+ };
121
+
122
+ /**
123
+ * Resolve a given path to a new path that points to the project flow json file.
124
+ * Scenarios:
125
+ * - If path undefined will resolve using current directory
126
+ * - If path directory, it should look up for a valid flow.json file, if it does not exist create it
127
+ * - If path is pointing to an actual flowFile, just return it.
128
+ *
129
+ * @param {string} projectDir
130
+ */
131
+ function resolveProjectFlowPath(projectDir) {
132
+ // output
133
+ let projectFlowFullPath;
134
+ let projectFlowDirname;
135
+
136
+ let projectDirOrFile = projectDir || process.cwd();
137
+
138
+ let isDir = isDirectory(projectDirOrFile);
139
+ if (isDir) {
140
+ let flowFileName = codegen.findFlowFile(projectDirOrFile); // returns only the flowname
141
+
142
+ if (!flowFileName) {
143
+ logError(`No flow found in directory: ${projectDirOrFile}`);
144
+ process.exit(1);
145
+ } else {
146
+ projectFlowDirname = projectDirOrFile;
147
+ projectFlowFullPath = path.join(projectDirOrFile, flowFileName);
148
+ }
149
+ } else if (isDir === false) {
150
+ projectFlowDirname = path.dirname(projectDirOrFile);
151
+ projectFlowFullPath = projectDirOrFile;
152
+ } else {
153
+ logError(`Directory does not exist: ${projectDirOrFile}`);
154
+ process.exit(1);
155
+ }
156
+
157
+ return [projectFlowDirname, projectFlowFullPath];
158
+ }
159
+
160
+ function isDirectory(dir) {
161
+ try {
162
+ let stats = fs.statSync(dir);
163
+ return stats.isDirectory();
164
+ } catch (err) {
165
+ return undefined;
166
+ }
167
+ }
@@ -0,0 +1,139 @@
1
+ /**
2
+ * This command should be used to start the kumologica runtime in local mode. And it will
3
+ * be assisting the UI on all aspects of the project development.
4
+ *
5
+ * Example:
6
+ * kl start ./myproject
7
+ * kl start ./myproject/flow.json
8
+ * kl start (this will look for a flow.json in the current directory)
9
+ *
10
+ * If not flow is found, the process will be exited (with code 1)
11
+ *
12
+ * The Runtime API can be found in: packages/runtime/src/runtime/lib/api/rest/index.js
13
+ * The actual runtime is in: packages/runtime/src/runtime/lib/index.js
14
+ *
15
+ * Naming convention used during the code:
16
+ * - AdminApp (express app) is the server that serves the Runtime API
17
+ * - NodeApp (express app) is the server that runs the flow
18
+ *
19
+ * DEVELOPER NOTE:
20
+ * Current implementation seems to be mounting the runtime api in the NodeApp (see runtime/lib/index.js:534)
21
+ * Ideally we wouldl like to separate the two apps and have the AdminApp running on a different port.
22
+ *
23
+ */
24
+
25
+ const path = require("path");
26
+ const fs = require("fs");
27
+ const { codegen } = require("@kumologica/builder");
28
+ const { DesignerServer } = require("../../src/server/DesignerServer");
29
+ const { logError, logNotice, logInfo, logFatal } = require("../utils/logger");
30
+ // const opn = require('better-opn');
31
+
32
+ exports.command = "serve [project_directory]";
33
+ exports.desc = `Start a local HTTP server to serve a project`;
34
+
35
+ exports.builder = (yargs) => {
36
+ yargs.positional(`project_directory`, {
37
+ type: "string",
38
+ describe:
39
+ "Path to a valid kumologica project directory or flow file. (Optional)",
40
+ });
41
+ yargs.option(`loglevel`, {
42
+ describe: "Logging level: [error, warn, info, debug, trace]",
43
+ type: "string",
44
+ nargs: 1,
45
+ });
46
+ yargs.option(`port`, {
47
+ describe: "Specifies the listening port utilized by the application",
48
+ type: "number",
49
+ nargs: 1,
50
+ });
51
+ };
52
+
53
+ exports.handler = async ({ project_directory, loglevel, port, secured }) => {
54
+ logNotice(`Starting HTTP Server...`);
55
+ let projectDirectory = project_directory || process.cwd();
56
+ // project_directory can point to a directory or a flow, so lets make sure that first the directory exists
57
+ let absProjectDirectory;
58
+
59
+ try {
60
+ absProjectDirectory = fs.realpathSync(projectDirectory);
61
+ } catch (err) {
62
+ logFatal(`Project not found: ${projectDirectory}`);
63
+ process.exit(1);
64
+ }
65
+
66
+ try {
67
+ // Resolve the path to the flow path
68
+ const [projectFlowDirname, projectFlowFullPath] =
69
+ resolveProjectFlowPath(absProjectDirectory);
70
+ logInfo(`> Flow file found: ${projectFlowFullPath}`);
71
+
72
+ // Gather all cli params
73
+ const cliParams = {
74
+ loglevel,
75
+ port,
76
+ noadmin: true,
77
+ };
78
+
79
+ // Start a server
80
+ let server = new DesignerServer({
81
+ flowPath: projectFlowFullPath,
82
+ cliParams,
83
+ });
84
+
85
+ await server.start();
86
+
87
+ // open("http://localhost:1880/hello");
88
+ } catch (e) {
89
+ console.log(e);
90
+ logFatal(e.message);
91
+ }
92
+ };
93
+
94
+ /**
95
+ * Resolve a given path to a new path that points to the project flow json file.
96
+ * Scenarios:
97
+ * - If path undefined will resolve using current directory
98
+ * - If path directory, it should look up for a valid flow.json file, if it does not exist create it
99
+ * - If path is pointing to an actual flowFile, just return it.
100
+ *
101
+ * @param {string} projectDir
102
+ */
103
+ function resolveProjectFlowPath(projectDir) {
104
+ // output
105
+ let projectFlowFullPath;
106
+ let projectFlowDirname;
107
+
108
+ let projectDirOrFile = projectDir || process.cwd();
109
+
110
+ let isDir = isDirectory(projectDirOrFile);
111
+ if (isDir) {
112
+ let flowFileName = codegen.findFlowFile(projectDirOrFile); // returns only the flowname
113
+
114
+ if (!flowFileName) {
115
+ logError(`No flow found in directory: ${projectDirOrFile}`);
116
+ process.exit(1);
117
+ } else {
118
+ projectFlowDirname = projectDirOrFile;
119
+ projectFlowFullPath = path.join(projectDirOrFile, flowFileName);
120
+ }
121
+ } else if (isDir === false) {
122
+ projectFlowDirname = path.dirname(projectDirOrFile);
123
+ projectFlowFullPath = projectDirOrFile;
124
+ } else {
125
+ logError(`Directory does not exist: ${projectDirOrFile}`);
126
+ process.exit(1);
127
+ }
128
+
129
+ return [projectFlowDirname, projectFlowFullPath];
130
+ }
131
+
132
+ function isDirectory(dir) {
133
+ try {
134
+ let stats = fs.statSync(dir);
135
+ return stats.isDirectory();
136
+ } catch (err) {
137
+ return undefined;
138
+ }
139
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kumologica/sdk",
3
- "version": "3.5.4",
3
+ "version": "3.6.0-alpha7",
4
4
  "productName": "Kumologica Designer",
5
5
  "copyright": "Copyright 2020 Kumologica Pty Ltd, All Rights Reserved.",
6
6
  "author": "Kumologica Pty Ltd <contact@kumologica.com>",
@@ -82,9 +82,9 @@
82
82
  "@aws-sdk/credential-providers": "^3.556.0",
83
83
  "@aws-sdk/lib-dynamodb": "^3.549.0",
84
84
  "@electron/remote": "^2.0.8",
85
- "@kumologica/builder": "3.5.4",
86
- "@kumologica/devkit": "3.5.4",
87
- "@kumologica/runtime": "3.5.4",
85
+ "@kumologica/builder": "3.6.0-alpha7",
86
+ "@kumologica/devkit": "3.6.0-alpha7",
87
+ "@kumologica/runtime": "3.6.0-alpha7",
88
88
  "adm-zip": "0.4.13",
89
89
  "ajv": "8.10.0",
90
90
  "archive-type": "^4.0.0",
@@ -102,7 +102,7 @@
102
102
  "dagre": "^0.8.5",
103
103
  "debounce": "^1.2.0",
104
104
  "decompress": "^4.2.1",
105
- "electron": "19.0.0",
105
+ "electron": "30.0.0",
106
106
  "electron-tabs": "^1.0.1",
107
107
  "electron-updater": "4.3.9",
108
108
  "enquirer": "2.3.6",
@@ -42,6 +42,7 @@ class MainWindow {
42
42
  titleBarStyle: 'hiddenInset',
43
43
  icon: "./src/assets/kumologica-app.png",
44
44
  webPreferences: {
45
+ sandbox: false,
45
46
  webviewTag: true,
46
47
  nodeIntegration: false,
47
48
  preload: preloadJsPath,
@@ -28,6 +28,7 @@ class ModalHome {
28
28
  resizable: false,
29
29
  backgroundColor: '#fff',
30
30
  webPreferences: {
31
+ sandbox: false,
31
32
  nodeIntegration: false,
32
33
  preload: preloadJsPath,
33
34
  contextIsolation: false,
@@ -23,6 +23,7 @@ class ModalNewProject {
23
23
  titleBarStyle: 'hiddenInset',
24
24
  backgroundColor: '#fff',
25
25
  webPreferences: {
26
+ sandbox: false,
26
27
  nodeIntegration: false,
27
28
  preload: preloadJsPath,
28
29
  enableRemoteModule: true,
@@ -24,6 +24,7 @@ class ModalNewTab {
24
24
  titleBarStyle: 'hiddenInset',
25
25
  backgroundColor: '#fff',
26
26
  webPreferences: {
27
+ sandbox: false,
27
28
  nodeIntegration: false,
28
29
  preload: preloadJsPath,
29
30
  enableRemoteModule: true,
@@ -26,6 +26,7 @@ class ModalNodeLibrary {
26
26
  backgroundColor: '#fff',
27
27
  icon: iconPath,
28
28
  webPreferences: {
29
+ sandbox: false,
29
30
  nodeIntegration: false,
30
31
  preload: preloadJsPath,
31
32
  contextIsolation: false,
@@ -26,6 +26,7 @@ class ModalRenameTab {
26
26
  titleBarStyle: 'hiddenInset',
27
27
  backgroundColor: '#fff',
28
28
  webPreferences: {
29
+ sandbox: false,
29
30
  nodeIntegration: false,
30
31
  preload: preloadJsPath,
31
32
  enableRemoteModule: true,
@@ -26,6 +26,7 @@ class ModalWelcome {
26
26
  resizable: false,
27
27
  backgroundColor: '#fff',
28
28
  webPreferences: {
29
+ sandbox: false,
29
30
  nodeIntegration: false,
30
31
  preload: preloadJsPath,
31
32
  contextIsolation: false,