@kumologica/sdk 3.0.0-alpha4

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 (76) hide show
  1. package/README.md +52 -0
  2. package/bin/kl.js +2 -0
  3. package/cli/KumologicaError.js +17 -0
  4. package/cli/cli.js +7 -0
  5. package/cli/commands/build-commands/aws.js +49 -0
  6. package/cli/commands/build-commands/azure.js +43 -0
  7. package/cli/commands/build-commands/kumohub.js +49 -0
  8. package/cli/commands/build.js +6 -0
  9. package/cli/commands/create-commands/create-project-iteratively.js +49 -0
  10. package/cli/commands/create-commands/index.js +5 -0
  11. package/cli/commands/create.js +66 -0
  12. package/cli/commands/deploy-commands/kumohub.js +114 -0
  13. package/cli/commands/deploy.js +6 -0
  14. package/cli/commands/doc-commands/html.js +60 -0
  15. package/cli/commands/doc.js +6 -0
  16. package/cli/commands/export-commands/cloudformation.js +371 -0
  17. package/cli/commands/export-commands/serverless.js +164 -0
  18. package/cli/commands/export-commands/terraform-commands/aws.js +193 -0
  19. package/cli/commands/export-commands/terraform-commands/azure.js +148 -0
  20. package/cli/commands/export-commands/terraform.js +6 -0
  21. package/cli/commands/export-commands/utils/validator.js +195 -0
  22. package/cli/commands/export.js +6 -0
  23. package/cli/commands/list-templates.js +24 -0
  24. package/cli/commands/open.js +53 -0
  25. package/cli/commands/start.js +165 -0
  26. package/cli/commands/test/TestSuiteRunner.js +76 -0
  27. package/cli/commands/test.js +123 -0
  28. package/cli/utils/download-template-from-repo.js +346 -0
  29. package/cli/utils/download-test.js +12 -0
  30. package/cli/utils/download.js +119 -0
  31. package/cli/utils/fs/copy-dir-contents-sync.js +15 -0
  32. package/cli/utils/fs/create-zip-file.js +39 -0
  33. package/cli/utils/fs/dir-exists-sync.js +14 -0
  34. package/cli/utils/fs/dir-exists.js +17 -0
  35. package/cli/utils/fs/file-exists-sync.js +14 -0
  36. package/cli/utils/fs/file-exists.js +12 -0
  37. package/cli/utils/fs/get-tmp-dir-path.js +22 -0
  38. package/cli/utils/fs/parse.js +40 -0
  39. package/cli/utils/fs/read-file-sync.js +11 -0
  40. package/cli/utils/fs/read-file.js +10 -0
  41. package/cli/utils/fs/safe-move-file.js +58 -0
  42. package/cli/utils/fs/walk-dir-sync.js +34 -0
  43. package/cli/utils/fs/write-file-sync.js +31 -0
  44. package/cli/utils/fs/write-file.js +32 -0
  45. package/cli/utils/logger.js +26 -0
  46. package/cli/utils/rename-service.js +49 -0
  47. package/package.json +72 -0
  48. package/src/api/core/comms.js +141 -0
  49. package/src/api/core/context.js +296 -0
  50. package/src/api/core/flows.js +286 -0
  51. package/src/api/core/index.js +29 -0
  52. package/src/api/core/library.js +106 -0
  53. package/src/api/core/nodes.js +476 -0
  54. package/src/api/core/projects.js +426 -0
  55. package/src/api/core/rest/context.js +42 -0
  56. package/src/api/core/rest/flow.js +53 -0
  57. package/src/api/core/rest/flows.js +53 -0
  58. package/src/api/core/rest/index.js +171 -0
  59. package/src/api/core/rest/nodes.js +164 -0
  60. package/src/api/core/rest/util.js +53 -0
  61. package/src/api/core/settings.js +287 -0
  62. package/src/api/tools/base/DesignerTool.js +108 -0
  63. package/src/api/tools/core/flow.js +58 -0
  64. package/src/api/tools/core/index.js +18 -0
  65. package/src/api/tools/core/node.js +77 -0
  66. package/src/api/tools/debugger/index.js +193 -0
  67. package/src/api/tools/filemanager/index.js +127 -0
  68. package/src/api/tools/git/index.js +103 -0
  69. package/src/api/tools/index.js +13 -0
  70. package/src/api/tools/test/index.js +56 -0
  71. package/src/api/tools/test/lib/TestCaseRunner.js +105 -0
  72. package/src/api/tools/test/lib/fixtures/example3-flow.json +148 -0
  73. package/src/api/tools/test/lib/fixtures/package.json +6 -0
  74. package/src/api/tools/test/lib/fixtures/s3-event.js +43 -0
  75. package/src/api/tools/test/lib/reporters/index.js +120 -0
  76. package/src/server/DesignerServer.js +141 -0
@@ -0,0 +1,108 @@
1
+
2
+ class DesignerTool {
3
+ constructor(designServer) {
4
+ this.designServer = designServer;
5
+ this.adminApp = designServer.getAdminServer(); // TODO: remove
6
+ this.flowServer = designServer.getFlowServer();
7
+
8
+ this.runtimeEventEmitter = this.flowServer.events;
9
+ }
10
+
11
+ getRuntimePlugin(pluginName) {
12
+ return this.flowServer.runtime.pluginRegistry.getPlugin(pluginName);
13
+ }
14
+
15
+ isRuntimePluginInstalled(pluginName) {
16
+ return this.getRuntimePlugin(pluginName) ? true : false;
17
+ }
18
+
19
+ // ================================
20
+ // WebSocket communication with SDK
21
+ // ================================
22
+
23
+ /**
24
+ * This method will be used by all the tools within the `install` method in order to register a websocket tool
25
+ * that will respond to each `eventType` request.
26
+ * @param {string} eventType
27
+ * @param {function(string): {type: string, payload?: object}} action
28
+ */
29
+ addEventHandler(eventType, action) {
30
+ this.designServer.registerEvent(eventType, action);
31
+ }
32
+
33
+ /**
34
+ * Sends an event over WebSocket back to the client.
35
+ * If you use this method instead of sendResponse, ensure to follow the naming convention used for responses: `{eventType}:response`
36
+ * @param {WebSocket} ws - The WebSocket connection.
37
+ * @param {string} eventType - The type of event to send.
38
+ * @param {object} payload - The payload data to send with the event.
39
+ */
40
+ sendEvent(ws, eventType, payload) {
41
+ let response = {
42
+ type: eventType,
43
+ payload
44
+ };
45
+ ws.send(JSON.stringify(response));
46
+ }
47
+
48
+ /**
49
+ * Sends a response event over WebSocket back to the client
50
+ * @param {WebSocket} ws - The WebSocket connection.
51
+ * @param {string} eventType - The type of event to send as a response.
52
+ * @param {object} payload - The payload data to send with the response.
53
+ */
54
+ sendResponse(ws, eventType, payload) {
55
+ this.sendEvent(ws, `${eventType}:response`, payload);
56
+ }
57
+
58
+ /**
59
+ * Sends an error event over WebSocket back to the client
60
+ * @param {WebSocket} ws - The WebSocket connection.
61
+ * @param {string} eventType - The type of event to send as an error.
62
+ * @param {Error} err - The error object to send with the error event.
63
+ */
64
+ sendError(ws, eventType, err) {
65
+ this.sendEvent(ws, `${eventType}:error`, { reason: err });
66
+ }
67
+
68
+ // ================================
69
+ // Communication with Runtime
70
+ // ================================
71
+
72
+ /**
73
+ * Use these two methods to subscribe to events emitted by a runtime plugin
74
+ * Remember that whenever you subscribe you will have to unsubscribe it when you are done
75
+ * otherwise, events will come duplicated.
76
+ *
77
+ * @param {*} listener
78
+ */
79
+ subscribeRuntimeListener(listener) {
80
+ this.runtimeEventEmitter.on('runtime-event', listener);
81
+ }
82
+ clearRuntimeListener(listener) {
83
+ this.runtimeEventEmitter.off('runtime-event', listener);
84
+ }
85
+
86
+ /**
87
+ * Use this method to invoke a command to a runtime plugin.
88
+ * - Plugin must extends the class `Plugin`
89
+ * - Communication will be done direct call to the object
90
+ *
91
+ * @param {string} pluginName
92
+ * @param {string} command
93
+ * @param {*} params - optional
94
+ */
95
+ sendCommandToPlugin(pluginName, command, params) {
96
+ let plugin = this.getRuntimePlugin(pluginName);
97
+ if (plugin) {
98
+ plugin.handleCommand(command, params);
99
+ } else {
100
+ throw new Error(`Plugin not found: ${pluginName}`);
101
+ }
102
+ }
103
+
104
+ }
105
+
106
+ module.exports = {
107
+ DesignerTool
108
+ }
@@ -0,0 +1,58 @@
1
+ const { DesignerTool } = require("../base/DesignerTool");
2
+
3
+ class CoreFlowTool extends DesignerTool {
4
+ constructor(designServer) {
5
+ super(designServer);
6
+ }
7
+ install() {
8
+ /**
9
+ * { type: 'test:run',
10
+ * payload: { testcaseid: '123432.34343'} }
11
+ */
12
+ this.addEventHandler('flow:getFlow', this.getFlowAction('flow:getFlow'));
13
+ this.addEventHandler('flow:deployFlow', this.deployFlowAction('flow:deployFlow'));
14
+ this.addEventHandler('flow:reloadFlow', this.reloadFlowAction('flow:reloadFlow'));
15
+
16
+ }
17
+ getFlowAction(eventType) {
18
+ return async (ws, payload) => {
19
+ try {
20
+ let response = this.flowServer.runtime._.nodes.getFlows()
21
+ this.sendResponse(ws, eventType, response);
22
+ } catch (err) {
23
+ this.sendError(ws, eventType, err.message);
24
+ }
25
+
26
+ }
27
+ }
28
+ deployFlowAction(eventType) {
29
+ return async (ws, payload) => {
30
+ try {
31
+ let response = this.flowServer.runtime._.nodes.setFlows(payload, 'full');
32
+ this.sendResponse(ws, eventType, {});
33
+
34
+ } catch (err) {
35
+ this.sendError(ws, eventType, err.message);
36
+ }
37
+
38
+ }
39
+ }
40
+ reloadFlowAction(eventType) {
41
+ return async (ws, payload) => {
42
+ try {
43
+ let response = this.flowServer.runtime._.nodes.loadFlows(true);
44
+ this.sendResponse(ws, eventType, {});
45
+
46
+ } catch (err) {
47
+ this.sendError(ws, eventType, err.message);
48
+ }
49
+
50
+ }
51
+ }
52
+
53
+ }
54
+
55
+
56
+ module.exports = {
57
+ CoreFlowTool
58
+ }
@@ -0,0 +1,18 @@
1
+ const { DesignerTool } = require("../base/DesignerTool");
2
+
3
+ const { CoreFlowTool } = require('./flow');
4
+ const { CoreNodeTool } = require('./node');
5
+
6
+ class CoreTools extends DesignerTool {
7
+ constructor(designServer) {
8
+ super(designServer);
9
+ }
10
+ install() {
11
+ new CoreFlowTool(this.designServer).install();
12
+ new CoreNodeTool(this.designServer).install();
13
+ }
14
+ }
15
+
16
+ module.exports = {
17
+ CoreTools
18
+ }
@@ -0,0 +1,77 @@
1
+ const { DesignerTool } = require("../base/DesignerTool");
2
+
3
+ class CoreNodeTool extends DesignerTool {
4
+ constructor(designServer) {
5
+ super(designServer);
6
+ }
7
+ install() {
8
+ /**
9
+ * { type: 'test:run',
10
+ * payload: { testcaseid: '123432.34343'} }
11
+ */
12
+ this.addEventHandler('node:getAllNodes', this.getAllNodes('node:getAllNodes'));
13
+ this.addEventHandler('node:getAllInstalledTypes', this.getAllInstalledTypes('node:getAllInstalledTypes'));
14
+
15
+ }
16
+ /**
17
+ *
18
+ * @param {*} eventType
19
+ * @returns
20
+ * {
21
+ "type": "node:getAllNodes:response",
22
+ "payload": [
23
+ {
24
+ "id": "kumologica-core/sftp",
25
+ "name": "sftp",
26
+ "types": [
27
+ "SFTP"
28
+ ],
29
+ "enabled": true,
30
+ "local": false,
31
+ "module": "kumologica-core",
32
+ "version": "3.2.0-beta6"
33
+ },
34
+ {
35
+ "id": "kumologica-core/Rekognition",
36
+ "name": "Rekognition",
37
+ "types": [
38
+ "Rekognition"
39
+ ],
40
+ "enabled": true,
41
+ "local": false,
42
+ "module": "kumologica-core",
43
+ "version": "3.2.0-beta6"
44
+ }, ... ]
45
+ */
46
+ getAllNodes(eventType) {
47
+ return async (ws, payload) => {
48
+ try {
49
+ let response = this.flowServer.runtime._.nodes.getNodeList();
50
+ // console.log(this.flowServer.runtime._.nodes.getNodeConfigs());
51
+ // console.log(this.flowServer.runtime._.nodes.getNodeConfig('kumologica-core/sftp'));
52
+ this.sendResponse(ws, eventType, response);
53
+ } catch (err) {
54
+ this.sendError(ws, eventType, err.message);
55
+ }
56
+
57
+ }
58
+ }
59
+
60
+ getAllInstalledTypes(eventType) {
61
+ return async (ws, payload) => {
62
+ try {
63
+ let response = this.flowServer.runtime._.nodes.getNodeConfigs();
64
+ this.sendResponse(ws, eventType, response);
65
+ } catch (err) {
66
+ this.sendError(ws, eventType, err.message);
67
+ }
68
+ }
69
+ }
70
+
71
+ }
72
+
73
+
74
+ module.exports = {
75
+ CoreNodeTool
76
+ }
77
+ 1
@@ -0,0 +1,193 @@
1
+ const { DesignerTool } = require('../base/DesignerTool');
2
+ const { TestCaseRunner, InMemoryReporter } = require('../test/lib/TestCaseRunner');
3
+
4
+ const DEBUGGER_PLUGIN = 'DebuggerPlugin';
5
+
6
+ /**
7
+ *
8
+ * Commands:
9
+ * { type: 'debugger:start', payload: { testcaseid: '2343.3434', breakpoints: {'123.1231', '1231.123'}}
10
+ * { type: 'debugger:continue' }
11
+ * { type: 'debugger:next' }
12
+ * { type: 'debugger:terminate' }
13
+ *
14
+ * Events:
15
+ * { type: 'debugger:on:trace', payload: { step: 1, type: 'input|output|error', message: {...}, vars: {} }}
16
+ * { type: 'debugger:on:change-state', payload: { step: 2, from: 'running', to: 'paused'}}
17
+ * { type: 'debugger:on:event', { status: "startFlow" });
18
+ *
19
+ * Responses:
20
+ * { type: 'debugger:start:response', "payload": { "testCaseExecutionTimeInMs": 1.7501250505447388, "testCaseID": "e8fb91dc.46c24", "testCaseDescription": "TestCase HelloWorld", "assertions": [... ] } }
21
+ */
22
+ class DebuggerTool extends DesignerTool {
23
+ constructor(designerServer) {
24
+ super(designerServer);
25
+ }
26
+
27
+ install() {
28
+ this.addEventHandler('debugger:start', this.start('debugger:start'));
29
+ this.addEventHandler('debugger:next', this.next('debugger:next'));
30
+ this.addEventHandler('debugger:continue', this.continue('debugger:continue'));
31
+ this.addEventHandler('debugger:terminate', this.terminate('debugger:terminate'));
32
+ }
33
+
34
+
35
+ start(eventType) {
36
+ return async (ws, payload) => {
37
+ const { testcaseid, breakpoints } = payload;
38
+ // runtime -> tool -> sdk
39
+ let debuggerListener = this.debuggerEventListener(ws);
40
+
41
+ try {
42
+ if (!this.isRuntimePluginInstalled(DEBUGGER_PLUGIN)) {
43
+ throw new Error("DebuggerPlugin not installed");
44
+ }
45
+ let pluginCommands = this.getRuntimePlugin(DEBUGGER_PLUGIN).listCommands();
46
+
47
+ // Subscribe to debugger plugin events
48
+ this.subscribeRuntimeListener(debuggerListener);
49
+
50
+ // Send command to get ready the debugger plugin
51
+ this.sendCommandToPlugin(DEBUGGER_PLUGIN, pluginCommands.ENABLE, breakpoints);
52
+
53
+ // Execute the flow as a test
54
+ const reporter = new InMemoryReporter();
55
+ const runner = new TestCaseRunner(this.flowServer, testcaseid, [reporter]);
56
+ await runner.runAsync();
57
+ let response = {
58
+ testCaseExecutionTimeInMs: reporter.executionTimeInMs,
59
+ testCaseID: reporter.testCaseID,
60
+ testCaseDescription: reporter.testCaseDescription,
61
+ assertions: reporter.assertionResults
62
+ }
63
+ this.sendResponse(ws, eventType, response);
64
+
65
+ } catch (err) {
66
+ console.log(err);
67
+ this.sendError(ws, eventType, err.message);
68
+ } finally {
69
+ this.clearRuntimeListener(debuggerListener);
70
+ }
71
+
72
+ }
73
+ }
74
+
75
+ next(eventType) {
76
+ return async (ws, payload) => {
77
+ try {
78
+ if (!this.isRuntimePluginInstalled(DEBUGGER_PLUGIN)) {
79
+ throw new Error("DebuggerPlugin not installed");
80
+ }
81
+ let pluginCommands = this.getRuntimePlugin(DEBUGGER_PLUGIN).listCommands();
82
+ // Send command to get ready the debugger plugin
83
+ this.sendCommandToPlugin(DEBUGGER_PLUGIN, pluginCommands.NEXT);
84
+ } catch (err) {
85
+ console.log(err);
86
+ this.sendError(ws, eventType, err.message);
87
+ }
88
+ };
89
+ }
90
+
91
+ continue(eventType) {
92
+ return async (ws, payload) => {
93
+ try {
94
+ if (!this.isRuntimePluginInstalled(DEBUGGER_PLUGIN)) {
95
+ throw new Error("DebuggerPlugin not installed");
96
+ }
97
+ let pluginCommands = this.getRuntimePlugin(DEBUGGER_PLUGIN).listCommands();
98
+ // Send command to get ready the debugger plugin
99
+ this.sendCommandToPlugin(DEBUGGER_PLUGIN, pluginCommands.CONTINUE);
100
+ } catch (err) {
101
+ console.log(err);
102
+ this.sendError(ws, eventType, err.message);
103
+ }
104
+ };
105
+ }
106
+
107
+ terminate(eventType) {
108
+ return async (ws, payload) => {
109
+ try {
110
+ if (!this.isRuntimePluginInstalled(DEBUGGER_PLUGIN)) {
111
+ throw new Error("DebuggerPlugin not installed");
112
+ }
113
+ let pluginCommands = this.getRuntimePlugin(DEBUGGER_PLUGIN).listCommands();
114
+ // Send command to get ready the debugger plugin
115
+ this.sendCommandToPlugin(DEBUGGER_PLUGIN, pluginCommands.TERMINATE);
116
+ } catch (err) {
117
+ console.log(err);
118
+ this.sendError(ws, eventType, err.message);
119
+ }
120
+ };
121
+ }
122
+
123
+ debuggerEventListener(ws) {
124
+ return (event) => {
125
+ let payload = event.payload;
126
+
127
+ switch (event.id) {
128
+ case 'runtime-event://debuggerPlugin/startFlow':
129
+ this.sendEvent(ws, 'debugger:on:event', { status: "startFlow" });
130
+ break;
131
+ case 'runtime-event://debuggerPlugin/endFlow':
132
+ this.sendEvent(ws, 'debugger:on:event', { status: "endFlow" });
133
+ break;
134
+ case 'runtime-event://debuggerPlugin/errorFlow':
135
+ this.sendEvent(ws, 'debugger:on:event', { status: "errorFlow" });
136
+ break;
137
+
138
+ case 'runtime-event://debuggerPlugin/startNode':
139
+ case 'runtime-event://debuggerPlugin/endNode':
140
+ case 'runtime-event://debuggerPlugin/errorNode':
141
+ this.sendEvent(ws, 'debugger:on:trace', payload);
142
+ break;
143
+
144
+ case 'runtime-event://debuggerPlugin/changeState':
145
+ this.sendEvent(ws, 'debugger:on:change-state', payload);
146
+ break;
147
+ default:
148
+ // do nothing
149
+ }
150
+ }
151
+
152
+ };
153
+
154
+ // NOT NEEDED YET
155
+ // genNextUniqueId(node, testcaseid) {
156
+ // let uniqueExecutionNodeId;
157
+ // let id = node.id;
158
+ // // check if node.id has not yet injected with unique runtime id
159
+ // if (!id.includes('::')){
160
+ // uniqueExecutionNodeId = `${testcaseid}::${node.id}::0`;
161
+ // } else{
162
+ // // Replace the testcase id for current one, if still carries the old one
163
+ // let idTokenized = id.split('::');
164
+ // let prevTestCaseId = idTokenized[0];
165
+ // let prevNodeId = idTokenized[1];
166
+ // let prevExecutionId = idTokenized[2];
167
+
168
+ // if (prevTestCaseId !== testcaseid) {
169
+ // id = `${testcaseid}::${prevNodeId}::${prevExecutionId}`
170
+ // }
171
+
172
+ // // if it has iterate over the executionId (last part of the unique runtime id)
173
+
174
+ // let posExecId = id.lastIndexOf('::');
175
+ // let prefixId = id.substr(0, posExecId);
176
+ // let executionId = parseInt(id.substr(posExecId + 2));
177
+
178
+ // uniqueExecutionNodeId = `${prefixId}::${executionId}`;
179
+ // while (uniqueExecutionNodeId in this._cache) {
180
+ // executionId = executionId + 1;
181
+ // uniqueExecutionNodeId = `${prefixId}::${executionId}`;
182
+ // }
183
+ // }
184
+
185
+
186
+ // return uniqueExecutionNodeId;
187
+ // }
188
+ }
189
+
190
+
191
+ module.exports = {
192
+ DebuggerTool
193
+ }
@@ -0,0 +1,127 @@
1
+ const { DesignerTool } = require("../base/DesignerTool");
2
+
3
+ /**
4
+ * FileManagerTool
5
+ * A cloud designer tool responsible to facilitate the sync of files between the frontend and the local filesystem.
6
+ * This tool will support the following operations: rename, update, add and delete files.
7
+ *
8
+ */
9
+ class FileManagerTool extends DesignerTool {
10
+ constructor(designerServer) {
11
+ super(designerServer);
12
+ }
13
+
14
+ install() {
15
+ /**
16
+ * { "type": "filemanager:pull" }
17
+ */
18
+ this.addEventHandler('filemanager:pull', this.executePull('filemanager:pull'));
19
+ /**
20
+ * { "type": "filemanager:push",
21
+ * "payload": { ... }}
22
+ */
23
+ this.addEventHandler('filemanager:push', this.executePush('filemanager:push'));
24
+ }
25
+
26
+ /**
27
+ * Invoked by the client to get the project structure on the server (localfilesystem).
28
+ * @param {string} - eventType: "filemanager:pull"
29
+ */
30
+ executePull(eventType) {
31
+ /**
32
+ * @param {ws} - client websocket
33
+ * @returns {Object} - response
34
+ * :: Example
35
+ * {
36
+ * 'flow': '/project-directory/simple-flow.json',
37
+ * 'files': {
38
+ * '/project-directory': {
39
+ * '.kumologica': {
40
+ * 'editor.json': <content>
41
+ * '.kumologica-ignore: "build \n",
42
+ * }
43
+ *
44
+ * 'simple-flow.json': <content>,
45
+ * 'config.json': <content>,
46
+ * 'package.json': <content>
47
+ * }
48
+ * }
49
+ *
50
+ * }
51
+ */
52
+ return async (ws, payload) => {
53
+ try {
54
+ const response = this.flowServer.runtime.storage.getProjectStructure();
55
+ this.sendResponse(ws, eventType, response);
56
+ } catch (err) {
57
+ console.log(err);
58
+ this.sendError(ws, eventType, "An error ocurred while pulling project directory from the server");
59
+ }
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Invoked by the client to send the project structure updates into the server.
65
+ * @param {string} - eventType: "filemanager:push"
66
+ */
67
+ executePush(eventType) {
68
+ /**
69
+ * @param {ws} - client websocket
70
+ * @param {Object} payload - request's payload
71
+ * @param {}
72
+ * :: Example
73
+ * {[
74
+ * {
75
+ * operation: "add_file",
76
+ * path: "/project-directory",
77
+ * filename: "secret.pem",
78
+ * content: <content>
79
+ * },
80
+ * {
81
+ * operation: "delete_file",
82
+ * path: "/project-directory",
83
+ * filename: "secret.pem"
84
+ * },
85
+ * {
86
+ * operation: "update_file",
87
+ * path: "/project-directory",
88
+ * filename: "secret.pem",
89
+ * content: <content>
90
+ * },
91
+ * {
92
+ * operation: "rename_file",
93
+ * path: "/project-directory",
94
+ * filename: "secret.pem",
95
+ * newFileName: "keys.pem"
96
+ * },
97
+ * {
98
+ * operation: "add_folder",
99
+ * path: "/project-directory/new-folder",
100
+ * },
101
+ * {
102
+ * operation: "remove_folder",
103
+ * path: "/project-directory/old-folder",
104
+ * },
105
+ * {
106
+ * operation: "rename_folder",
107
+ * path: "/project-directory/old-folder",
108
+ * newPath: "/project-directory/new-folder",
109
+ * },
110
+
111
+ * ]}
112
+ */
113
+ return async (ws, payload) => {
114
+ try {
115
+ const response = await this.flowServer.runtime.storage.fileOperation(payload);
116
+ this.sendResponse(ws, eventType, response);
117
+ } catch (err) {
118
+ console.log(err);
119
+ this.sendError(ws, eventType, err.message);
120
+ }
121
+ }
122
+ }
123
+ }
124
+
125
+ module.exports = {
126
+ FileManagerTool
127
+ }
@@ -0,0 +1,103 @@
1
+ const { DesignerTool } = require("../base/DesignerTool");
2
+ const simpleGit = require('simple-git');
3
+
4
+ class GitTool extends DesignerTool {
5
+ constructor(designerServer) {
6
+ super(designerServer);
7
+ }
8
+
9
+ install() {
10
+ /**
11
+ * { "type": "git:status"}
12
+ */
13
+ this.addEventHandler('git:status', this.executeGitStatus('git:status'));
14
+ /**
15
+ * { "type": "git:add-and-commit",
16
+ * "payload": { "commit": "commit message..." }}
17
+ */
18
+ this.addEventHandler('git:add-and-commit', this.executeAddAndCommit('git:add-and-commit'));
19
+ /**
20
+ * { "type": "git:push-origin"
21
+ * "payload": {
22
+ * proxy: "http://my-annoying-proxy" // optional
23
+ * }
24
+ * }
25
+ */
26
+ this.addEventHandler('git:push-origin', this.executePushOrigin('git:push-origin'));
27
+
28
+ }
29
+
30
+ gitCommand(options) {
31
+ const { proxy } = options || {};
32
+
33
+ // base options
34
+ let gitOptions = {
35
+ baseDir: this.flowServer.serverSettings.projectDir,
36
+ binary: 'git',
37
+ maxConcurrentProcesses: 6,
38
+ trimmed: false
39
+ }
40
+ // proxy included?
41
+ if (proxy) {
42
+ gitOptions = { ...gitOptions, config: [`http.proxy=${proxy}`] }
43
+ }
44
+ return simpleGit(gitOptions);
45
+ }
46
+
47
+ executeGitStatus(eventType) {
48
+ return async (ws, payload) => {
49
+ try {
50
+ const git = this.gitCommand();
51
+ let status = await git.status(); //['-', 'sb'] // newStatus = {ahead, behind, current, tracking};
52
+ this.sendResponse(ws, eventType, { status });
53
+ } catch (err) {
54
+ this.sendError(ws, eventType, "The current project directory is not a Git repository. Please initialize Git in this directory.");
55
+ }
56
+ }
57
+ }
58
+
59
+ executeAddAndCommit(eventType) {
60
+ return async (ws, payload) => {
61
+ try {
62
+ const { commit } = payload;
63
+ if (!commit) {
64
+ throw new Error('Commit message cannot be empty')
65
+ }
66
+ const git = this.gitCommand();
67
+ const resp = await git.add('./*').commit(commit);
68
+ this.sendResponse(ws, eventType, { resp });
69
+ } catch (err) {
70
+ this.sendError(ws, eventType, err.message);
71
+ }
72
+ }
73
+ }
74
+
75
+ executePushOrigin(eventType) {
76
+ return async (ws, payload) => {
77
+ try {
78
+ const { proxy } = payload;
79
+ const git = this.gitCommand({ proxy });
80
+ let currentBranch = await this.readCurrentBranch();
81
+ const resp = await git.push('origin', currentBranch);
82
+ this.sendResponse(ws, eventType, { resp });
83
+ } catch (e) {
84
+ this.sendError(ws, eventType, err.message);
85
+ }
86
+ }
87
+ }
88
+
89
+ async readCurrentBranch() {
90
+ try {
91
+ const git = this.gitCommand();
92
+ const localBranches = await git.branchLocal();
93
+ return localBranches.current;
94
+ } catch (err) {
95
+ throw err;
96
+ }
97
+
98
+ }
99
+ }
100
+
101
+ module.exports = {
102
+ GitTool
103
+ }