@kumologica/sdk 3.6.0-beta6 → 3.6.0-beta8

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.
@@ -5,50 +5,53 @@
5
5
  * main process (electron), kumologica runtime and itself (node part)
6
6
  */
7
7
 
8
-
9
8
  // const { AppServer, lambdify } = require('./lib/runtime-loader');
10
- const { lambdify } = require('@kumologica/runtime');
11
- const { codegen } = require('@kumologica/builder');
12
- const { DesignerServer } = require('../server/DesignerServer')
13
- const { Terminal } = require('xterm');
14
- const { FitAddon } = require('xterm-addon-fit');
15
- const electron = require('electron');
16
- const remote = require('@electron/remote');
9
+ const { lambdify } = require("@kumologica/runtime");
10
+ const { codegen } = require("@kumologica/builder");
11
+ const { DesignerServer } = require("../server/DesignerServer");
12
+ const { Terminal } = require("xterm");
13
+ const { FitAddon } = require("xterm-addon-fit");
14
+ const electron = require("electron");
15
+ const remote = require("@electron/remote");
16
+ const { exec, spawn } = require("child_process");
17
+ const chalk = require("chalk");
17
18
 
18
19
  // Parse arguments from: webPreferences.additionalArguments
19
- const argv = require('yargs/yargs')(process.argv.slice(2)).parse();
20
+ const argv = require("yargs/yargs")(process.argv.slice(2)).parse();
20
21
  const port = argv.port || 1880;
21
22
 
22
- const events = require('events');
23
- const debounce = require('debounce');
24
- const { promisify } = require('util');
23
+ const events = require("events");
24
+ const debounce = require("debounce");
25
+ const { promisify } = require("util");
25
26
 
26
- const dagre = require('dagre');
27
- const simpleGit = require('simple-git');
28
- const request = require('request');
27
+ const dagre = require("dagre");
28
+ const simpleGit = require("simple-git");
29
+ const request = require("request");
29
30
  const requestAsync = promisify(request);
30
31
 
31
- const CloudConfig = require('./lib/stores/aws-cloud-config-store');
32
- const TestConfig = require('./lib/stores/test-config-store');
33
- const KumohubConfig = require('./lib/stores/kumohub-config-store');
34
- const AzureConfig = require('./lib/stores/azure-config-store');
35
- const ProjectInfoConfig = require('./lib/stores/project-info-config-store');
36
- const { CloudConfigStore } = require('./lib/stores/settings-cloud-store');
37
- const { NetworkConfigStore } = require('./lib/stores/settings-network-store');
38
- const { OpenAIClient } = require('./lib/ai/openai');
32
+ const CloudConfig = require("./lib/stores/aws-cloud-config-store");
33
+ const TestConfig = require("./lib/stores/test-config-store");
34
+ const KumohubConfig = require("./lib/stores/kumohub-config-store");
35
+ const AzureConfig = require("./lib/stores/azure-config-store");
36
+ const ProjectInfoConfig = require("./lib/stores/project-info-config-store");
37
+ const { CloudConfigStore } = require("./lib/stores/settings-cloud-store");
38
+ const { NetworkConfigStore } = require("./lib/stores/settings-network-store");
39
+ const { OpenAIClient } = require("./lib/ai/openai");
39
40
 
40
- const AWSProfile = require('./lib/aws/aws-profile');
41
- const AWSDeployer = require('./lib/aws');
42
- const ServerlessDeployer = require('./lib/serverless');
43
- const GithubDeployer = require('./lib/github');
41
+ const AWSProfile = require("./lib/aws/aws-profile");
42
+ const AWSDeployer = require("./lib/aws");
43
+ const ServerlessDeployer = require("./lib/serverless");
44
+ const GithubDeployer = require("./lib/github");
44
45
 
45
- const { WorkspacePreferenceStore } = require('./lib/stores/workspace-preference-store');
46
+ const {
47
+ WorkspacePreferenceStore,
48
+ } = require("./lib/stores/workspace-preference-store");
46
49
 
47
- const Kumohub = require('./lib/kumohub');
48
- const deployCli = require('@kumologica/builder');
49
- const Azure = require('./lib/azure');
50
+ const Kumohub = require("./lib/kumohub");
51
+ const deployCli = require("@kumologica/builder");
52
+ const Azure = require("./lib/azure");
50
53
 
51
- const { openFileOnEditor, openFolder } = require('./lib/utils/editor');
54
+ const { openFileOnEditor, openFolder } = require("./lib/utils/editor");
52
55
 
53
56
  const terminalEmitter = new events.EventEmitter();
54
57
  const awsDeployer = new AWSDeployer(terminalEmitter);
@@ -62,14 +65,13 @@ const azure = new Azure(terminalEmitter);
62
65
 
63
66
  const DESIGNER_DEBUGGER_URL = `http://127.0.0.1:${port}/__debugger__`;
64
67
 
65
- const KUMOLOGICA_NODE_LIB_BASEURL =
66
- 'https://library.kumohub.io';
68
+ const KUMOLOGICA_NODE_LIB_BASEURL = "https://library.kumohub.io";
67
69
  const KUMOLOGICA_NODE_LIB_URL = `${KUMOLOGICA_NODE_LIB_BASEURL}/library.json`;
68
70
 
69
71
  const cloudConfigStore = new CloudConfigStore();
70
72
  const networkConfigStore = new NetworkConfigStore();
71
73
 
72
- const openAIClient = new OpenAIClient({ version: 'gpt-3.5-turbo' }); //'gpt-4'
74
+ const openAIClient = new OpenAIClient({ version: "gpt-3.5-turbo" }); //'gpt-4'
73
75
 
74
76
  // function to be called each time
75
77
  // project changes - either new project created or old project opened.
@@ -81,9 +83,10 @@ function loadConfigs() {
81
83
  dataPath: window.__kumologica.settings.projectDir,
82
84
  });
83
85
 
84
- window.__kumologica.settings.kumohubConfig = new KumohubConfig.KumohubConfigStore({
85
- dataPath: window.__kumologica.settings.projectDir,
86
- });
86
+ window.__kumologica.settings.kumohubConfig =
87
+ new KumohubConfig.KumohubConfigStore({
88
+ dataPath: window.__kumologica.settings.projectDir,
89
+ });
87
90
 
88
91
  window.__kumologica.settings.azureConfig = new AzureConfig.AzureConfigStore({
89
92
  dataPath: window.__kumologica.settings.projectDir,
@@ -93,30 +96,31 @@ function loadConfigs() {
93
96
  dataPath: window.__kumologica.settings.projectDir,
94
97
  });
95
98
 
96
- window.__kumologica.settings.projectInfoConfig = new ProjectInfoConfig.ProjectInfoConfigStore({
97
- dataPath: window.__kumologica.settings.projectDir,
98
- });
99
+ window.__kumologica.settings.projectInfoConfig =
100
+ new ProjectInfoConfig.ProjectInfoConfigStore({
101
+ dataPath: window.__kumologica.settings.projectDir,
102
+ });
99
103
  }
100
104
 
101
105
  function deploy(projectInfo, params) {
102
- const alias = cloudConfigStore.getAWSAliasInfo(window.__kumologica.cloud.profile);
106
+ const alias = cloudConfigStore.getAWSAliasInfo(
107
+ window.__kumologica.cloud.profile
108
+ );
103
109
 
104
110
  return awsDeployer.deploy(projectInfo, params, alias.profile);
105
111
  }
106
112
 
107
113
  async function kumohubBuild(projectInfo) {
108
- const { build } = require('@kumologica/builder');
114
+ const { build } = require("@kumologica/builder");
109
115
  const params = {
110
116
  "project-directory": projectInfo.projectDir,
111
117
  "flow-file-name": projectInfo.projectFlowName,
112
- "zip-file-name": "lambda.zip"
113
- }
114
-
115
- build('kumohub', params, terminalEmitter); // default options
118
+ "zip-file-name": "lambda.zip",
119
+ };
116
120
 
121
+ build("kumohub", params, terminalEmitter); // default options
117
122
  }
118
123
  async function kumohubDeploy(projectInfo, params) {
119
-
120
124
  const alias = cloudConfigStore.getKumohubAliasInfo(params.profile);
121
125
 
122
126
  params.username = alias.username;
@@ -125,7 +129,7 @@ async function kumohubDeploy(projectInfo, params) {
125
129
  params["flow-file-name"] = projectInfo.projectFlowName;
126
130
  params["project-directory"] = projectInfo.projectDir;
127
131
 
128
- return await deployCli.deploy('kumohub', params, terminalEmitter);
132
+ return await deployCli.deploy("kumohub", params, terminalEmitter);
129
133
  }
130
134
 
131
135
  async function azureDeploy(projectInfo, params) {
@@ -136,42 +140,34 @@ async function azureDeploy(projectInfo, params) {
136
140
  }
137
141
 
138
142
  async function generateScript(provider, projectInfo, params) {
139
- const alias = cloudConfigStore.getAWSAliasInfo(window.__kumologica.cloud.profile);
143
+ const alias = cloudConfigStore.getAWSAliasInfo(
144
+ window.__kumologica.cloud.profile
145
+ );
140
146
 
141
147
  if (provider == window.__kumologica.cloud.provider.aws) {
142
- await awsDeployer.generateScript(
143
- projectInfo,
144
- params,
145
- alias.profile
146
- );
148
+ await awsDeployer.generateScript(projectInfo, params, alias.profile);
147
149
  } else if (provider == window.__kumologica.cloud.provider.serverless) {
148
- await serverlessDeployer.generateScript(
149
- projectInfo,
150
- params,
151
- alias.profile
152
- );
150
+ await serverlessDeployer.generateScript(projectInfo, params, alias.profile);
153
151
  } else if (provider == window.__kumologica.cloud.provider.github) {
154
- await githubDeployer.generateScript(
155
- projectInfo,
156
- params,
157
- alias.profile
158
- );
152
+ await githubDeployer.generateScript(projectInfo, params, alias.profile);
159
153
  }
160
154
  }
161
155
 
162
156
  async function listServices(type) {
163
- const alias = cloudConfigStore.getAWSAliasInfo(window.__kumologica.cloud.profile);
157
+ const alias = cloudConfigStore.getAWSAliasInfo(
158
+ window.__kumologica.cloud.profile
159
+ );
164
160
 
165
161
  let lServices = await awsDeployer.listServices(type, alias.profile);
166
162
  return lServices;
167
163
  }
168
164
 
169
165
  function hasJsonStructure(str) {
170
- if (typeof str !== 'string') return false;
166
+ if (typeof str !== "string") return false;
171
167
  try {
172
168
  const result = JSON.parse(str);
173
169
  const type = Object.prototype.toString.call(result);
174
- return type === '[object Object]' || type === '[object Array]';
170
+ return type === "[object Object]" || type === "[object Array]";
175
171
  } catch (err) {
176
172
  return false;
177
173
  }
@@ -187,10 +183,9 @@ async function getRegion(profile) {
187
183
  }
188
184
 
189
185
  async function testFlow(testEvent, targetNode, environmentVariables) {
190
-
191
186
  let event;
192
187
 
193
- targetNode = targetNode || '*';
188
+ targetNode = targetNode || "*";
194
189
  try {
195
190
  // TODO: we should check not only if data is json parsable, but also if it is well-formed JSON structure
196
191
  // Eg. 1234, "hello world"
@@ -201,13 +196,13 @@ async function testFlow(testEvent, targetNode, environmentVariables) {
201
196
  throw err;
202
197
  }
203
198
 
204
- headers = { ...headers, 'x-kumologica-testcasenode': targetNode };
199
+ headers = { ...headers, "x-kumologica-testcasenode": targetNode };
205
200
 
206
201
  if (environmentVariables) {
207
202
  if (Object.keys(environmentVariables).length > 0) {
208
203
  headers = {
209
204
  ...headers,
210
- 'x-kumologica-aws-env': JSON.stringify(environmentVariables),
205
+ "x-kumologica-aws-env": JSON.stringify(environmentVariables),
211
206
  };
212
207
  }
213
208
  }
@@ -215,53 +210,71 @@ async function testFlow(testEvent, targetNode, environmentVariables) {
215
210
  if (environmentVariables && environmentVariables["AWS_PROFILE"]) {
216
211
  headers = {
217
212
  ...headers,
218
- 'x-kumologica-aws-profile': environmentVariables["AWS_PROFILE"],
213
+ "x-kumologica-aws-profile": environmentVariables["AWS_PROFILE"],
219
214
  };
220
215
 
221
216
  const region = await new AWSProfile().getRegion(
222
217
  environmentVariables["AWS_PROFILE"]
223
218
  );
224
219
 
225
- headers = { ...headers, 'x-kumologica-aws-region': region };
220
+ headers = { ...headers, "x-kumologica-aws-region": region };
226
221
  } else {
227
- terminalEmitter.emit('terminal-output', " ");
228
- terminalEmitter.emit('terminal-output', "AWS_PROFILE property not defined on test tab, default aws cli precedence will be used.");
229
- terminalEmitter.emit('terminal-output', "For details see: https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html");
230
- terminalEmitter.emit('terminal-output', " ");
231
- terminalEmitter.emit('terminal-output', "Your environment variables:");
232
- terminalEmitter.emit('terminal-output', ` AWS_PROFILE: ${process.env.AWS_PROFILE}`);
233
- terminalEmitter.emit('terminal-output', ` AWS_REGION: ${process.env.AWS_REGION}`);
234
- terminalEmitter.emit('terminal-output', ` AWS_ACCESS_KEY_ID: ${process.env.AWS_ACCESS_KEY_ID}`);
235
- terminalEmitter.emit('terminal-output', ` AWS_SECRET_ACCESS_KEY: ${process.env.AWS_SECRET_ACCESS_KEY}`);
236
- terminalEmitter.emit('terminal-output', " ");
222
+ terminalEmitter.emit("terminal-output", " ");
223
+ terminalEmitter.emit(
224
+ "terminal-output",
225
+ "AWS_PROFILE property not defined on test tab, default aws cli precedence will be used."
226
+ );
227
+ terminalEmitter.emit(
228
+ "terminal-output",
229
+ "For details see: https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html"
230
+ );
231
+ terminalEmitter.emit("terminal-output", " ");
232
+ terminalEmitter.emit("terminal-output", "Your environment variables:");
233
+ terminalEmitter.emit(
234
+ "terminal-output",
235
+ ` AWS_PROFILE: ${process.env.AWS_PROFILE}`
236
+ );
237
+ terminalEmitter.emit(
238
+ "terminal-output",
239
+ ` AWS_REGION: ${process.env.AWS_REGION}`
240
+ );
241
+ terminalEmitter.emit(
242
+ "terminal-output",
243
+ ` AWS_ACCESS_KEY_ID: ${process.env.AWS_ACCESS_KEY_ID}`
244
+ );
245
+ terminalEmitter.emit(
246
+ "terminal-output",
247
+ ` AWS_SECRET_ACCESS_KEY: ${process.env.AWS_SECRET_ACCESS_KEY}`
248
+ );
249
+ terminalEmitter.emit("terminal-output", " ");
237
250
  }
238
- console.log('[preload] Invoking the testFlow...');
251
+ console.log("[preload] Invoking the testFlow...");
239
252
  try {
240
253
  let resp = await requestAsync({
241
254
  uri: `http://127.0.0.1:${port}/`,
242
- method: 'POST',
255
+ method: "POST",
243
256
  headers: headers,
244
257
  body: event,
245
258
  json: true,
246
259
  });
247
- console.log('[preload] Response:', resp.body);
260
+ console.log("[preload] Response:", resp.body);
248
261
  return resp;
249
262
  } catch (err) {
250
- console.log('[preload] Request end with errors...', e);
263
+ console.log("[preload] Request end with errors...", e);
251
264
  throw e;
252
265
  }
253
266
  }
254
267
 
255
- /**
268
+ /**
256
269
  * Debugger API Client endpoints
257
270
  */
258
271
 
259
272
  async function addBreakpoint(id) {
260
- const url = `${DESIGNER_DEBUGGER_URL}/add-breakpoint/${id}`
273
+ const url = `${DESIGNER_DEBUGGER_URL}/add-breakpoint/${id}`;
261
274
 
262
275
  let options = {
263
276
  uri: url,
264
- method: 'GET',
277
+ method: "GET",
265
278
  json: true,
266
279
  };
267
280
 
@@ -273,7 +286,7 @@ async function addBreakpoint(id) {
273
286
  console.log(
274
287
  `Received a "${statusCode}" from Kumologica Node Library host`
275
288
  );
276
- return '';
289
+ return "";
277
290
  }
278
291
  } catch (err) {
279
292
  throw err;
@@ -281,11 +294,11 @@ async function addBreakpoint(id) {
281
294
  }
282
295
 
283
296
  async function removeAllBreakpoints() {
284
- const url = `${DESIGNER_DEBUGGER_URL}/remove-all-breakpoints`
297
+ const url = `${DESIGNER_DEBUGGER_URL}/remove-all-breakpoints`;
285
298
 
286
299
  let options = {
287
300
  uri: url,
288
- method: 'GET',
301
+ method: "GET",
289
302
  json: true,
290
303
  };
291
304
 
@@ -294,15 +307,14 @@ async function removeAllBreakpoints() {
294
307
  } catch (err) {
295
308
  throw err;
296
309
  }
297
-
298
310
  }
299
311
 
300
312
  async function isBreakpointFound(id) {
301
- const url = `${DESIGNER_DEBUGGER_URL}/contains-breakpoint/${id}`
313
+ const url = `${DESIGNER_DEBUGGER_URL}/contains-breakpoint/${id}`;
302
314
 
303
315
  let options = {
304
316
  uri: url,
305
- method: 'GET',
317
+ method: "GET",
306
318
  json: true,
307
319
  };
308
320
 
@@ -311,15 +323,14 @@ async function isBreakpointFound(id) {
311
323
  } catch (err) {
312
324
  throw err;
313
325
  }
314
-
315
326
  }
316
327
 
317
328
  async function toggleBreakpoint(id) {
318
- const url = `${DESIGNER_DEBUGGER_URL}/toggle-breakpoint/${id}`
329
+ const url = `${DESIGNER_DEBUGGER_URL}/toggle-breakpoint/${id}`;
319
330
 
320
331
  let options = {
321
332
  uri: url,
322
- method: 'GET',
333
+ method: "GET",
323
334
  json: true,
324
335
  };
325
336
 
@@ -328,15 +339,14 @@ async function toggleBreakpoint(id) {
328
339
  } catch (err) {
329
340
  throw err;
330
341
  }
331
-
332
342
  }
333
343
 
334
344
  async function enableDebugger() {
335
- const url = `${DESIGNER_DEBUGGER_URL}/enable`
345
+ const url = `${DESIGNER_DEBUGGER_URL}/enable`;
336
346
 
337
347
  let options = {
338
348
  uri: url,
339
- method: 'GET',
349
+ method: "GET",
340
350
  json: true,
341
351
  };
342
352
 
@@ -347,13 +357,12 @@ async function enableDebugger() {
347
357
  }
348
358
  }
349
359
 
350
-
351
360
  async function listBreakpoints() {
352
- const url = `${DESIGNER_DEBUGGER_URL}/list-breakpoints`
361
+ const url = `${DESIGNER_DEBUGGER_URL}/list-breakpoints`;
353
362
 
354
363
  let options = {
355
364
  uri: url,
356
- method: 'GET',
365
+ method: "GET",
357
366
  json: true,
358
367
  };
359
368
 
@@ -365,11 +374,11 @@ async function listBreakpoints() {
365
374
  }
366
375
 
367
376
  async function redrawBreakpoints() {
368
- const url = `${DESIGNER_DEBUGGER_URL}/redraw-breakpoints`
377
+ const url = `${DESIGNER_DEBUGGER_URL}/redraw-breakpoints`;
369
378
 
370
379
  let options = {
371
380
  uri: url,
372
- method: 'GET',
381
+ method: "GET",
373
382
  json: true,
374
383
  };
375
384
 
@@ -381,11 +390,11 @@ async function redrawBreakpoints() {
381
390
  }
382
391
 
383
392
  async function disableDebugger() {
384
- const url = `${DESIGNER_DEBUGGER_URL}/disable`
393
+ const url = `${DESIGNER_DEBUGGER_URL}/disable`;
385
394
 
386
395
  let options = {
387
396
  uri: url,
388
- method: 'GET',
397
+ method: "GET",
389
398
  json: true,
390
399
  };
391
400
 
@@ -397,11 +406,11 @@ async function disableDebugger() {
397
406
  }
398
407
 
399
408
  async function continueDebugger() {
400
- const url = `${DESIGNER_DEBUGGER_URL}/continue`
409
+ const url = `${DESIGNER_DEBUGGER_URL}/continue`;
401
410
 
402
411
  let options = {
403
412
  uri: url,
404
- method: 'GET',
413
+ method: "GET",
405
414
  json: true,
406
415
  };
407
416
 
@@ -413,11 +422,11 @@ async function continueDebugger() {
413
422
  }
414
423
 
415
424
  async function stopDebugger() {
416
- const url = `${DESIGNER_DEBUGGER_URL}/stop`
425
+ const url = `${DESIGNER_DEBUGGER_URL}/stop`;
417
426
 
418
427
  let options = {
419
428
  uri: url,
420
- method: 'GET',
429
+ method: "GET",
421
430
  json: true,
422
431
  };
423
432
 
@@ -429,11 +438,11 @@ async function stopDebugger() {
429
438
  }
430
439
 
431
440
  async function nextDebugger() {
432
- const url = `${DESIGNER_DEBUGGER_URL}/next`
441
+ const url = `${DESIGNER_DEBUGGER_URL}/next`;
433
442
 
434
443
  let options = {
435
444
  uri: url,
436
- method: 'GET',
445
+ method: "GET",
437
446
  json: true,
438
447
  };
439
448
 
@@ -445,11 +454,11 @@ async function nextDebugger() {
445
454
  }
446
455
 
447
456
  async function terminateDebugger() {
448
- const url = `${DESIGNER_DEBUGGER_URL}/terminate`
457
+ const url = `${DESIGNER_DEBUGGER_URL}/terminate`;
449
458
 
450
459
  let options = {
451
460
  uri: url,
452
- method: 'GET',
461
+ method: "GET",
453
462
  json: true,
454
463
  };
455
464
 
@@ -468,14 +477,14 @@ async function fetchAvailableNodes() {
468
477
 
469
478
  let options = {
470
479
  uri: KUMOLOGICA_NODE_LIB_URL,
471
- method: 'GET',
480
+ method: "GET",
472
481
  json: true,
473
482
  };
474
483
 
475
484
  // Inject proxy header if required
476
485
  let proxyHeader = RED.uiSettings.getProxyHeader();
477
486
  if (proxyHeader) {
478
- options.proxy = proxyHeader
487
+ options.proxy = proxyHeader;
479
488
  }
480
489
 
481
490
  try {
@@ -526,11 +535,11 @@ function kumohubIsLoggedIn(profile) {
526
535
  function validateAlias(alias) {
527
536
  let msg = undefined;
528
537
  if (!alias.username) {
529
- msg = 'Invalid kumohub profile, missing username.';
538
+ msg = "Invalid kumohub profile, missing username.";
530
539
  } else if (!alias.password) {
531
- msg = 'Invalid kumohub profile, missing password.';
540
+ msg = "Invalid kumohub profile, missing password.";
532
541
  } else if (!alias.subscription) {
533
- msg = 'Invalid kumohub profile, missing subscription';
542
+ msg = "Invalid kumohub profile, missing subscription";
534
543
  }
535
544
 
536
545
  if (msg) {
@@ -561,25 +570,104 @@ function dispatch(type, payload) {
561
570
  ipcRenderer.send(type, payload);
562
571
  }
563
572
 
573
+ function includeNodePathIntoPath() {
574
+ // Include the node_path into the path, otherwise the npm wont be found if dynamically exported
575
+ if (process.env.NODE_PATH) {
576
+ const shellEnvSeparator = process.platform === "win32" ? ";" : ":";
577
+ return process.env.NODE_PATH + shellEnvSeparator + process.env.PATH;
578
+ } else {
579
+ return process.env.PATH;
580
+ }
581
+ }
582
+
583
+ async function npmInstall(dependency) {
584
+ return new Promise((resolve, reject) => {
585
+ window.__kumologica.editor.terminal.eventEmitter.emit(
586
+ "terminal-output",
587
+ `Running ${dependency} in directory: ${window.__kumologica.settings.projectDir}...`
588
+ );
589
+
590
+ // Break the dependency (string) into command + args
591
+ const parts = dependency.trim().split(" ");
592
+ let command = parts[0];
593
+ const args = parts.slice(1);
594
+
595
+ const child = spawn(command, args, {
596
+ cwd: window.__kumologica.settings.projectDir,
597
+ env: {
598
+ ...process.env,
599
+ PATH: includeNodePathIntoPath(),
600
+ },
601
+ shell: true,
602
+ });
603
+
604
+ // Stream stdout data
605
+ child.stdout.on("data", (data) => {
606
+ window.__kumologica.editor.terminal.eventEmitter.emit(
607
+ "terminal-output",
608
+ data.toString()
609
+ );
610
+ });
611
+
612
+ // Stream stderr data
613
+ child.stderr.on("data", (data) => {
614
+ window.__kumologica.editor.terminal.eventEmitter.emit(
615
+ "terminal-output",
616
+ data.toString()
617
+ );
618
+ });
619
+
620
+ // Handle process exit
621
+ child.on("close", (code) => {
622
+ console.log("preload: close with code:", code);
623
+
624
+ if (code !== 0) {
625
+ let message =
626
+ code === 127
627
+ ? `The task failed with exit code ${code}. Please ensure that the NODE_PATH environment variable is correctly set and exported in your system's environment.`
628
+ : `The task failed with exit code ${code}`;
629
+
630
+ window.__kumologica.editor.terminal.eventEmitter.emit(
631
+ "terminal-output",
632
+ `❌ Error: ${message}`
633
+ );
634
+ reject(new Error(message));
635
+ } else {
636
+ window.__kumologica.editor.terminal.eventEmitter.emit(
637
+ "terminal-output",
638
+ `✅ Done.`
639
+ );
640
+ resolve();
641
+ }
642
+ });
643
+
644
+ // Handle execution errors
645
+ child.on("error", (error) => {
646
+ window.__kumologica.editor.terminal.eventEmitter.emit(
647
+ "terminal-output",
648
+ `Error: ${error.message}`
649
+ );
650
+ });
651
+ });
652
+ }
564
653
 
565
654
  window.__kumologica = {};
566
655
  window.__kumologica.electron = electron;
567
656
  window.__kumologica.electron.remote = remote;
568
657
 
569
-
570
658
  // Present a contract to interact with main process
571
659
  window.__kumologica.main = {};
572
660
  window.__kumologica.main.dispatch = dispatch;
573
661
 
574
662
  // Present a contract to interact with editor project (itself)
575
663
  window.__kumologica.editor = {};
576
- window.__kumologica.editor.runner = require('./ui/editor-api/lib/runner');
664
+ window.__kumologica.editor.runner = require("./ui/editor-api/lib/runner");
577
665
 
578
666
  // terminal section
579
667
  window.__kumologica.editor.terminal = {};
580
668
  window.__kumologica.editor.terminal.opts = {
581
669
  fontSize: 13,
582
- fontFamily: 'Ubuntu Mono, courier-new, courier, monospace',
670
+ fontFamily: "Ubuntu Mono, courier-new, courier, monospace",
583
671
  };
584
672
  window.__kumologica.editor.terminal.Terminal = Terminal;
585
673
  window.__kumologica.editor.terminal.FitAddon = FitAddon;
@@ -592,13 +680,13 @@ window.__kumologica.settings.loadConfigs = loadConfigs;
592
680
 
593
681
  window.__kumologica.settings.cloudConfigStore = cloudConfigStore;
594
682
  window.__kumologica.settings.networkConfigStore = networkConfigStore;
595
- window.__kumologica.settings.workspacePreferenceStore = new WorkspacePreferenceStore();
683
+ window.__kumologica.settings.workspacePreferenceStore =
684
+ new WorkspacePreferenceStore();
596
685
 
597
686
  window.__kumologica.settings.platform = {};
598
- window.__kumologica.settings.platform.isMac = process.platform === 'darwin';
599
- window.__kumologica.settings.platform.isWindows = process.platform === 'win32';
600
- window.__kumologica.settings.platform.isLinux = process.platform === 'linux';
601
-
687
+ window.__kumologica.settings.platform.isMac = process.platform === "darwin";
688
+ window.__kumologica.settings.platform.isWindows = process.platform === "win32";
689
+ window.__kumologica.settings.platform.isLinux = process.platform === "linux";
602
690
 
603
691
  // Present a contract to interact with runtime project
604
692
  window.__kumologica.runtime = {};
@@ -641,7 +729,7 @@ window.__kumologica.azure.deploy = azureDeploy;
641
729
  // Expose utilities and extra libs
642
730
  window.__kumologica.libs = {};
643
731
  window.__kumologica.libs.debounce = debounce;
644
- window.__kumologica.libs.path = require('path');
732
+ window.__kumologica.libs.path = require("path");
645
733
  window.__kumologica.libs.testFlow = testFlow;
646
734
  window.__kumologica.libs.openFileOnEditor = openFileOnEditor;
647
735
  window.__kumologica.libs.openFolder = openFolder;
@@ -653,8 +741,8 @@ window.__kumologica.libs.openAIClient = openAIClient;
653
741
 
654
742
  /**
655
743
  * Return the name of the valid kumologica flow or undefined otherwise.
656
- * @param {} projectDir
657
- * @returns
744
+ * @param {} projectDir
745
+ * @returns
658
746
  */
659
747
  function findValidKumologicaFlowInDir(projectDir) {
660
748
  return codegen.findFlowFile(projectDir);
@@ -684,6 +772,6 @@ window.__kumologica.debugger.terminate = terminateDebugger;
684
772
  window.__kumologica.debugger.next = nextDebugger;
685
773
  window.__kumologica.debugger.stop = stopDebugger;
686
774
 
687
-
688
-
689
-
775
+ // Commands
776
+ window.__kumologica.command = {};
777
+ window.__kumologica.command.npmInstall = npmInstall;