@optimizely/ocp-local-env 1.0.0-beta.5 → 1.0.0-beta.7

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 (119) hide show
  1. package/dist/package.json +3 -2
  2. package/dist/public/bundle.7a5338c67e783e9b42f7.js +3 -0
  3. package/dist/public/{bundle.932ab47a0dbf0319bc8b.js.LICENSE.txt → bundle.7a5338c67e783e9b42f7.js.LICENSE.txt} +33 -0
  4. package/dist/public/bundle.7a5338c67e783e9b42f7.js.map +1 -0
  5. package/dist/public/index.html +1 -1
  6. package/dist/src/executor/DestinationExecutor.js +10 -7
  7. package/dist/src/executor/DestinationExecutor.js.map +1 -1
  8. package/dist/src/executor/FunctionExecutor.js +1 -1
  9. package/dist/src/executor/FunctionExecutor.js.map +1 -1
  10. package/dist/src/executor/JobExecutor.js +1 -1
  11. package/dist/src/executor/JobExecutor.js.map +1 -1
  12. package/dist/src/executor/LifecycleExecutor.js +1 -1
  13. package/dist/src/executor/LifecycleExecutor.js.map +1 -1
  14. package/dist/src/executor/SourceExecutor.d.ts +32 -0
  15. package/dist/src/executor/SourceExecutor.js +161 -0
  16. package/dist/src/executor/SourceExecutor.js.map +1 -0
  17. package/dist/src/local_engine/LocalJobApi.d.ts +38 -0
  18. package/dist/src/local_engine/LocalJobApi.js +180 -0
  19. package/dist/src/local_engine/LocalJobApi.js.map +1 -0
  20. package/dist/src/local_engine/local-engine-child-base.d.ts +16 -0
  21. package/dist/src/local_engine/local-engine-child-base.js +201 -14
  22. package/dist/src/local_engine/local-engine-child-base.js.map +1 -1
  23. package/dist/src/local_engine/local-engine-client.d.ts +70 -1
  24. package/dist/src/local_engine/local-engine-client.js +545 -26
  25. package/dist/src/local_engine/local-engine-client.js.map +1 -1
  26. package/dist/src/local_engine/local-engine-types.d.ts +98 -2
  27. package/dist/src/local_engine/local-engine-unified.d.ts +18 -0
  28. package/dist/src/local_engine/local-engine-unified.js +227 -1
  29. package/dist/src/local_engine/local-engine-unified.js.map +1 -1
  30. package/dist/src/local_engine/local-engine-utils.js +34 -7
  31. package/dist/src/local_engine/local-engine-utils.js.map +1 -1
  32. package/dist/src/local_engine/localSDKConfig.js +237 -39
  33. package/dist/src/local_engine/localSDKConfig.js.map +1 -1
  34. package/dist/src/local_engine/storage/LocalConfigStore.d.ts +18 -0
  35. package/dist/src/local_engine/storage/LocalConfigStore.js +52 -3
  36. package/dist/src/local_engine/storage/LocalConfigStore.js.map +1 -1
  37. package/dist/src/local_engine/storage/LocalJobStore.d.ts +1 -0
  38. package/dist/src/local_engine/storage/LocalJobStore.js +12 -2
  39. package/dist/src/local_engine/storage/LocalJobStore.js.map +1 -1
  40. package/dist/src/local_engine/storage/LocalKVStore.d.ts +1 -0
  41. package/dist/src/local_engine/storage/LocalKVStore.js +134 -75
  42. package/dist/src/local_engine/storage/LocalKVStore.js.map +1 -1
  43. package/dist/src/local_engine/storage/LocalNotificationStore.d.ts +1 -0
  44. package/dist/src/local_engine/storage/LocalNotificationStore.js +17 -3
  45. package/dist/src/local_engine/storage/LocalNotificationStore.js.map +1 -1
  46. package/dist/src/local_engine/storage/LocalSecretsStore.d.ts +1 -0
  47. package/dist/src/local_engine/storage/LocalSecretsStore.js +37 -6
  48. package/dist/src/local_engine/storage/LocalSecretsStore.js.map +1 -1
  49. package/dist/src/local_engine/storage/LocalSettingsStore.d.ts +1 -0
  50. package/dist/src/local_engine/storage/LocalSettingsStore.js +61 -11
  51. package/dist/src/local_engine/storage/LocalSettingsStore.js.map +1 -1
  52. package/dist/src/local_engine/storage/SourceDataStore.d.ts +23 -0
  53. package/dist/src/local_engine/storage/SourceDataStore.js +83 -0
  54. package/dist/src/local_engine/storage/SourceDataStore.js.map +1 -0
  55. package/dist/src/local_engine/storage/SourceJobExecutionStore.d.ts +25 -0
  56. package/dist/src/local_engine/storage/SourceJobExecutionStore.js +61 -0
  57. package/dist/src/local_engine/storage/SourceJobExecutionStore.js.map +1 -0
  58. package/dist/src/local_engine/utils.js +20 -4
  59. package/dist/src/local_engine/utils.js.map +1 -1
  60. package/dist/src/logging/LogManager.d.ts +191 -34
  61. package/dist/src/logging/LogManager.js +209 -103
  62. package/dist/src/logging/LogManager.js.map +1 -1
  63. package/dist/src/server/api/destinations.js +30 -6
  64. package/dist/src/server/api/destinations.js.map +1 -1
  65. package/dist/src/server/api/jobs.js +3 -0
  66. package/dist/src/server/api/jobs.js.map +1 -1
  67. package/dist/src/server/api/sources.d.ts +7 -0
  68. package/dist/src/server/api/sources.js +380 -0
  69. package/dist/src/server/api/sources.js.map +1 -0
  70. package/dist/src/server/api.js +64 -3
  71. package/dist/src/server/api.js.map +1 -1
  72. package/dist/src/server.js +203 -19
  73. package/dist/src/server.js.map +1 -1
  74. package/dist/src/ui/components/App.js +165 -21
  75. package/dist/src/ui/components/App.js.map +1 -1
  76. package/dist/src/ui/components/DestinationsView.d.ts +8 -0
  77. package/dist/src/ui/components/DestinationsView.js +30 -9
  78. package/dist/src/ui/components/DestinationsView.js.map +1 -1
  79. package/dist/src/ui/components/FunctionsView.d.ts +7 -0
  80. package/dist/src/ui/components/FunctionsView.js +69 -9
  81. package/dist/src/ui/components/FunctionsView.js.map +1 -1
  82. package/dist/src/ui/components/JobsView.d.ts +7 -0
  83. package/dist/src/ui/components/JobsView.js +55 -15
  84. package/dist/src/ui/components/JobsView.js.map +1 -1
  85. package/dist/src/ui/components/SourceDataViewer.d.ts +8 -0
  86. package/dist/src/ui/components/SourceDataViewer.js +84 -0
  87. package/dist/src/ui/components/SourceDataViewer.js.map +1 -0
  88. package/dist/src/ui/components/SourceJobsSection.d.ts +8 -0
  89. package/dist/src/ui/components/SourceJobsSection.js +99 -0
  90. package/dist/src/ui/components/SourceJobsSection.js.map +1 -0
  91. package/dist/src/ui/components/SourceLifecycleSection.d.ts +7 -0
  92. package/dist/src/ui/components/SourceLifecycleSection.js +58 -0
  93. package/dist/src/ui/components/SourceLifecycleSection.js.map +1 -0
  94. package/dist/src/ui/components/SourceSchemaViewer.d.ts +7 -0
  95. package/dist/src/ui/components/SourceSchemaViewer.js +65 -0
  96. package/dist/src/ui/components/SourceSchemaViewer.js.map +1 -0
  97. package/dist/src/ui/components/SourceWebhookEditor.d.ts +8 -0
  98. package/dist/src/ui/components/SourceWebhookEditor.js +168 -0
  99. package/dist/src/ui/components/SourceWebhookEditor.js.map +1 -0
  100. package/dist/src/ui/components/SourcesView.d.ts +14 -0
  101. package/dist/src/ui/components/SourcesView.js +74 -0
  102. package/dist/src/ui/components/SourcesView.js.map +1 -0
  103. package/dist/src/ui/components/TabbedConsole.d.ts +3 -1
  104. package/dist/src/ui/components/TabbedConsole.js +81 -11
  105. package/dist/src/ui/components/TabbedConsole.js.map +1 -1
  106. package/dist/src/ui/hooks/useEntityNavigation.d.ts +72 -0
  107. package/dist/src/ui/hooks/useEntityNavigation.js +150 -0
  108. package/dist/src/ui/hooks/useEntityNavigation.js.map +1 -0
  109. package/dist/src/ui/hooks/useQueryParams.d.ts +6 -0
  110. package/dist/src/ui/hooks/useQueryParams.js +39 -0
  111. package/dist/src/ui/hooks/useQueryParams.js.map +1 -0
  112. package/dist/src/ui/index.js +3 -2
  113. package/dist/src/ui/index.js.map +1 -1
  114. package/package.json +3 -2
  115. package/dist/public/bundle.932ab47a0dbf0319bc8b.js +0 -3
  116. package/dist/public/bundle.932ab47a0dbf0319bc8b.js.map +0 -1
  117. package/dist/src/server/api/lifecycle.d.ts +0 -6
  118. package/dist/src/server/api/lifecycle.js +0 -72
  119. package/dist/src/server/api/lifecycle.js.map +0 -1
@@ -10,9 +10,96 @@ exports.LocalEngineClient = void 0;
10
10
  const child_process_1 = require("child_process");
11
11
  const path_1 = __importDefault(require("path"));
12
12
  const local_engine_utils_1 = require("./local-engine-utils");
13
+ const LogManager_1 = require("../logging/LogManager");
14
+ function getLogCategoryFromMessageType(context) {
15
+ switch (context.type) {
16
+ case 'function':
17
+ return LogManager_1.LogCategory.Function;
18
+ case 'lifecycle':
19
+ return LogManager_1.LogCategory.Lifecycle;
20
+ case 'destination':
21
+ return LogManager_1.LogCategory.Destination;
22
+ case 'source':
23
+ return LogManager_1.LogCategory.Source;
24
+ case 'jobs':
25
+ return LogManager_1.LogCategory.Jobs;
26
+ default:
27
+ return LogManager_1.LogCategory.AppRunner;
28
+ }
29
+ }
30
+ /**
31
+ * Process buffered output and log complete lines
32
+ */
33
+ function processBufferedOutput(buffer, newData, isError, context) {
34
+ const logManager = LogManager_1.LogManager.getInstance();
35
+ const combined = buffer + newData;
36
+ const lines = combined.split('\n');
37
+ // Keep the last incomplete line in the buffer
38
+ const remainingBuffer = lines.pop() || '';
39
+ // Log only valid JSON lines (filters out pretty-printed output)
40
+ lines.forEach(line => {
41
+ const trimmed = line.trim();
42
+ if (trimmed) {
43
+ try {
44
+ // Try to parse as JSON
45
+ const parsed = JSON.parse(trimmed);
46
+ // Only log if it's a valid JSON object (structured log)
47
+ if (typeof parsed === 'object' && parsed !== null) {
48
+ // Log with execution context
49
+ if (context) {
50
+ // Map execution context type to log category enum
51
+ let category = getLogCategoryFromMessageType(context);
52
+ logManager.log({
53
+ source: LogManager_1.LogSource.App,
54
+ category,
55
+ level: isError ? 'error' : 'info',
56
+ message: trimmed,
57
+ context: { id: context.id }
58
+ });
59
+ }
60
+ else {
61
+ // Fallback for app output without context
62
+ logManager.log({
63
+ source: LogManager_1.LogSource.App,
64
+ category: LogManager_1.LogCategory.AppRunner,
65
+ level: isError ? 'error' : 'info',
66
+ message: trimmed,
67
+ context: { id: '' }
68
+ });
69
+ }
70
+ }
71
+ else {
72
+ console.error(trimmed, context);
73
+ }
74
+ // Silently ignore non-JSON lines (pretty-printed output)
75
+ }
76
+ catch (error) {
77
+ // Not valid JSON - silently ignore
78
+ }
79
+ }
80
+ });
81
+ return remainingBuffer;
82
+ }
13
83
  class LocalEngineClient {
14
84
  constructor() {
15
85
  this.connections = new Map();
86
+ this.logManager = LogManager_1.LogManager.getInstance();
87
+ }
88
+ /**
89
+ * Get the singleton instance of LocalEngineClient
90
+ * This ensures all IPC handlers share the same instance and JobExecutor
91
+ */
92
+ static getInstance() {
93
+ if (!LocalEngineClient.instance) {
94
+ LocalEngineClient.instance = new LocalEngineClient();
95
+ }
96
+ return LocalEngineClient.instance;
97
+ }
98
+ /**
99
+ * Set the JobExecutor instance for handling job trigger requests
100
+ */
101
+ setJobExecutor(jobExecutor) {
102
+ this.jobExecutor = jobExecutor;
16
103
  }
17
104
  /**
18
105
  * Get or create a connection for the specified app
@@ -39,17 +126,26 @@ class LocalEngineClient {
39
126
  */
40
127
  async createConnection(appConfig, appDir) {
41
128
  const wrapperScript = path_1.default.join(__dirname, 'local-engine-unified.js');
42
- console.log(`[IPC Client] Starting unified wrapper for app ${appConfig.manifest.meta?.app_id}: ${wrapperScript}`);
129
+ this.logManager.info(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Starting unified wrapper for app', {
130
+ id: '',
131
+ operation: 'spawn',
132
+ appId: appConfig.manifest.meta?.app_id
133
+ });
43
134
  const childProcess = (0, child_process_1.spawn)('node', [wrapperScript], {
44
135
  cwd: appDir,
45
136
  stdio: ['pipe', 'pipe', 'pipe', 'ipc'],
46
- env: { ...process.env }
137
+ env: {
138
+ ...process.env,
139
+ DISABLE_LOGMANAGER_CONSOLE: 'true' // Prevent double logging from child process
140
+ }
47
141
  });
48
142
  const connection = {
49
143
  process: childProcess,
50
144
  ready: false,
51
145
  pendingRequests: new Map(),
52
- lastActivity: Date.now()
146
+ lastActivity: Date.now(),
147
+ stdoutBuffer: '',
148
+ stderrBuffer: ''
53
149
  };
54
150
  // Set up message handling
55
151
  this.setupMessageHandlers(connection);
@@ -67,27 +163,31 @@ class LocalEngineClient {
67
163
  try {
68
164
  (0, local_engine_utils_1.logIPCMessage)('RECV', message, '[IPC Client]');
69
165
  if (!(0, local_engine_utils_1.validateMessage)(message)) {
70
- console.error('[IPC Client] Received invalid message:', message);
166
+ this.logManager.error(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Received invalid message', {
167
+ id: connection.process.pid.toString(),
168
+ messageType: message?.type
169
+ });
71
170
  return;
72
171
  }
73
172
  this.handleChildMessage(connection, message);
74
173
  }
75
174
  catch (error) {
76
- console.error('[IPC Client] Error handling child message:', error);
175
+ this.logManager.error(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Error handling child message', {
176
+ id: 'unknown',
177
+ error
178
+ });
77
179
  }
78
180
  });
79
- // Handle stdout/stderr for debugging
181
+ // Handle stdout/stderr - processBufferedOutput logs to LogManager
80
182
  connection.process.stdout?.on('data', (data) => {
81
- const output = data.toString().trim();
82
- if (output) {
83
- console.log(`[IPC Child STDOUT] ${output}`);
84
- }
183
+ const output = data.toString();
184
+ connection.stdoutBuffer = processBufferedOutput(connection.stdoutBuffer || '', output, false, connection.currentContext // Pass execution context
185
+ );
85
186
  });
86
187
  connection.process.stderr?.on('data', (data) => {
87
- const error = data.toString().trim();
88
- if (error) {
89
- console.error(`[IPC Child STDERR] ${error}`);
90
- }
188
+ const error = data.toString();
189
+ connection.stderrBuffer = processBufferedOutput(connection.stderrBuffer || '', error, true, connection.currentContext // Pass execution context
190
+ );
91
191
  });
92
192
  }
93
193
  /**
@@ -95,15 +195,27 @@ class LocalEngineClient {
95
195
  */
96
196
  setupErrorHandlers(connection) {
97
197
  connection.process.on('error', (error) => {
98
- console.error('[IPC Client] Child process error:', error);
198
+ this.logManager.error(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Child process error', {
199
+ id: connection.process.pid?.toString() || 'unknown',
200
+ operation: 'error',
201
+ error
202
+ });
99
203
  this.handleConnectionError(connection, error);
100
204
  });
101
205
  connection.process.on('exit', (code, signal) => {
102
- console.log(`[IPC Client] Child process exited with code ${code}, signal ${signal}`);
206
+ this.logManager.info(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Child process exited', {
207
+ id: connection.process.pid?.toString() || 'unknown',
208
+ operation: 'exit',
209
+ exitCode: code ?? undefined,
210
+ signal: signal ?? undefined
211
+ });
103
212
  this.handleConnectionExit(connection, code, signal);
104
213
  });
105
214
  connection.process.on('close', () => {
106
- console.log('[IPC Client] Child process closed');
215
+ this.logManager.info(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Child process closed', {
216
+ id: connection.process.pid?.toString() || 'unknown',
217
+ operation: 'close'
218
+ });
107
219
  connection.ready = false;
108
220
  });
109
221
  }
@@ -128,15 +240,29 @@ class LocalEngineClient {
128
240
  case 'error':
129
241
  this.handleErrorMessage(connection, message);
130
242
  break;
243
+ case 'trigger_job':
244
+ this.handleTriggerJobMessage(connection, message);
245
+ break;
246
+ case 'get_job_detail':
247
+ this.handleGetJobDetailMessage(connection, message);
248
+ break;
249
+ case 'get_job_status':
250
+ this.handleGetJobStatusMessage(connection, message);
251
+ break;
131
252
  default:
132
- console.warn(`[IPC Client] Unknown message type: ${message.type}`);
253
+ this.logManager.warn(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Unknown message type', {
254
+ id: 'unknown',
255
+ messageType: message.type
256
+ });
133
257
  }
134
258
  }
135
259
  /**
136
260
  * Handle ready message from child
137
261
  */
138
262
  handleReadyMessage(connection) {
139
- console.log('[IPC Client] Child process is ready');
263
+ this.logManager.info(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Child process is ready', {
264
+ id: connection.process.pid?.toString() || 'unknown'
265
+ });
140
266
  connection.ready = true;
141
267
  }
142
268
  /**
@@ -144,15 +270,20 @@ class LocalEngineClient {
144
270
  */
145
271
  handleProgressMessage(connection, message) {
146
272
  const { requestId, message: progressMsg, progress } = message.data;
147
- console.log(`[IPC Client] Progress for ${requestId}: ${progressMsg} (${progress || 'N/A'}%)`);
273
+ this.logManager.debug(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, `Progress: ${progressMsg}`, {
274
+ id: requestId || 'unknown',
275
+ messageType: 'progress'
276
+ });
148
277
  }
149
278
  /**
150
279
  * Handle log message from child
151
280
  */
152
281
  handleLogMessage(connection, message) {
153
282
  const { level, message: logMsg, requestId } = message.data;
154
- const prefix = requestId ? `[${requestId.slice(0, 8)}]` : '[IPC Child]';
155
- console.log(`${prefix} [${level.toUpperCase()}] ${logMsg}`);
283
+ this.logManager.debug(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, logMsg, {
284
+ id: requestId || connection.process.pid.toString() || 'unknown',
285
+ messageType: 'log'
286
+ });
156
287
  }
157
288
  /**
158
289
  * Handle success message from child
@@ -164,9 +295,16 @@ class LocalEngineClient {
164
295
  (0, local_engine_utils_1.cleanupPendingRequest)(pendingRequest);
165
296
  connection.pendingRequests.delete(requestId);
166
297
  pendingRequest.resolve(result);
298
+ // Clear execution context
299
+ if (connection.currentContext?.requestId === requestId) {
300
+ connection.currentContext = undefined;
301
+ }
167
302
  }
168
303
  else {
169
- console.warn(`[IPC Client] Received success for unknown request: ${requestId}`);
304
+ this.logManager.warn(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Received success for unknown request', {
305
+ id: requestId || 'unknown',
306
+ messageType: 'success'
307
+ });
170
308
  }
171
309
  }
172
310
  /**
@@ -180,16 +318,196 @@ class LocalEngineClient {
180
318
  connection.pendingRequests.delete(requestId);
181
319
  const error = (0, local_engine_utils_1.deserializeError)({ message: errorMsg, stack });
182
320
  pendingRequest.reject(error);
321
+ // Clear execution context
322
+ if (connection.currentContext?.requestId === requestId) {
323
+ connection.currentContext = undefined;
324
+ }
183
325
  }
184
326
  else {
185
- console.warn(`[IPC Client] Received error for unknown request: ${requestId} - ${errorMsg}`);
327
+ this.logManager.warn(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Received error for unknown request', {
328
+ id: requestId || 'unknown',
329
+ messageType: 'error',
330
+ errorMessage: errorMsg
331
+ });
332
+ }
333
+ }
334
+ /**
335
+ * Handle job trigger request from child
336
+ */
337
+ async handleTriggerJobMessage(connection, message) {
338
+ const { jobName, parameters } = message.data;
339
+ const requestId = message.id;
340
+ if (!this.jobExecutor) {
341
+ this.logManager.error(LogManager_1.LogSource.System, LogManager_1.LogCategory.Jobs, 'JobExecutor not available', {
342
+ id: requestId,
343
+ jobName
344
+ });
345
+ // Send error response
346
+ const errorResponse = {
347
+ ...(0, local_engine_utils_1.createBaseMessage)('error'),
348
+ type: 'error',
349
+ data: {
350
+ requestId,
351
+ error: 'JobExecutor not initialized',
352
+ executionTime: 0
353
+ }
354
+ };
355
+ (0, local_engine_utils_1.sendIPCMessage)(connection.process, errorResponse);
356
+ return;
357
+ }
358
+ this.logManager.info(LogManager_1.LogSource.System, LogManager_1.LogCategory.Jobs, 'Processing job trigger request from child', {
359
+ id: requestId,
360
+ jobName
361
+ });
362
+ // Execute the job - this returns a response object with success/error info
363
+ const response = await this.jobExecutor.executeJob({
364
+ jobId: jobName,
365
+ parameters: parameters || {}
366
+ });
367
+ // Check if execution failed
368
+ if (!response.success) {
369
+ this.logManager.error(LogManager_1.LogSource.System, LogManager_1.LogCategory.Jobs, 'Job trigger request failed', {
370
+ id: requestId,
371
+ jobName,
372
+ error: response.error
373
+ });
374
+ // Send error response back to child
375
+ const errorResponse = {
376
+ ...(0, local_engine_utils_1.createBaseMessage)('error'),
377
+ type: 'error',
378
+ data: {
379
+ requestId,
380
+ error: response.error || 'Failed to trigger job',
381
+ executionTime: 0
382
+ }
383
+ };
384
+ (0, local_engine_utils_1.sendIPCMessage)(connection.process, errorResponse);
385
+ return;
386
+ }
387
+ // Get the execution details
388
+ const execution = this.jobExecutor.getExecution(response.executionId);
389
+ if (!execution) {
390
+ this.logManager.error(LogManager_1.LogSource.System, LogManager_1.LogCategory.Jobs, 'Execution not found after trigger', {
391
+ id: requestId,
392
+ jobName,
393
+ executionId: response.executionId
394
+ });
395
+ const errorResponse = {
396
+ ...(0, local_engine_utils_1.createBaseMessage)('error'),
397
+ type: 'error',
398
+ data: {
399
+ requestId,
400
+ error: `Execution not found after trigger: ${response.executionId}`,
401
+ executionTime: 0
402
+ }
403
+ };
404
+ (0, local_engine_utils_1.sendIPCMessage)(connection.process, errorResponse);
405
+ return;
406
+ }
407
+ this.logManager.info(LogManager_1.LogSource.System, LogManager_1.LogCategory.Jobs, 'Job triggered successfully from child', {
408
+ id: requestId,
409
+ jobName,
410
+ executionId: response.executionId
411
+ });
412
+ // Send success response with execution details
413
+ const successResponse = {
414
+ ...(0, local_engine_utils_1.createBaseMessage)('success'),
415
+ type: 'success',
416
+ data: {
417
+ requestId,
418
+ result: {
419
+ jobId: execution.id,
420
+ jobName: execution.jobId,
421
+ status: execution.status,
422
+ parameters: execution.parameters,
423
+ startedAt: execution.startedAt,
424
+ completedAt: execution.completedAt
425
+ },
426
+ executionTime: 0
427
+ }
428
+ };
429
+ (0, local_engine_utils_1.sendIPCMessage)(connection.process, successResponse);
430
+ }
431
+ /**
432
+ * Handle job detail request from child
433
+ */
434
+ async handleGetJobDetailMessage(connection, message) {
435
+ const { requestId, executionId } = message.data;
436
+ const execution = this.jobExecutor?.getExecution(executionId);
437
+ if (!execution) {
438
+ const errorResponse = {
439
+ ...(0, local_engine_utils_1.createBaseMessage)('error'),
440
+ type: 'error',
441
+ data: {
442
+ requestId,
443
+ error: `Execution ${executionId} not found`,
444
+ executionTime: 0
445
+ }
446
+ };
447
+ (0, local_engine_utils_1.sendIPCMessage)(connection.process, errorResponse);
448
+ return;
186
449
  }
450
+ // Send success response with execution details
451
+ const successResponse = {
452
+ ...(0, local_engine_utils_1.createBaseMessage)('success'),
453
+ type: 'success',
454
+ data: {
455
+ requestId,
456
+ result: {
457
+ jobId: execution.id,
458
+ jobName: execution.jobId,
459
+ status: execution.status,
460
+ parameters: execution.parameters,
461
+ startedAt: execution.startedAt,
462
+ completedAt: execution.completedAt
463
+ },
464
+ executionTime: 0
465
+ }
466
+ };
467
+ (0, local_engine_utils_1.sendIPCMessage)(connection.process, successResponse);
468
+ }
469
+ /**
470
+ * Handle job status request from child
471
+ */
472
+ async handleGetJobStatusMessage(connection, message) {
473
+ const { requestId, executionId } = message.data;
474
+ const execution = this.jobExecutor?.getExecution(executionId);
475
+ if (!execution) {
476
+ const errorResponse = {
477
+ ...(0, local_engine_utils_1.createBaseMessage)('error'),
478
+ type: 'error',
479
+ data: {
480
+ requestId,
481
+ error: `Execution ${executionId} not found`,
482
+ executionTime: 0
483
+ }
484
+ };
485
+ (0, local_engine_utils_1.sendIPCMessage)(connection.process, errorResponse);
486
+ return;
487
+ }
488
+ // Send success response with just the status
489
+ const successResponse = {
490
+ ...(0, local_engine_utils_1.createBaseMessage)('success'),
491
+ type: 'success',
492
+ data: {
493
+ requestId,
494
+ result: {
495
+ status: execution.status
496
+ },
497
+ executionTime: 0
498
+ }
499
+ };
500
+ (0, local_engine_utils_1.sendIPCMessage)(connection.process, successResponse);
187
501
  }
188
502
  /**
189
503
  * Handle connection errors
190
504
  */
191
505
  handleConnectionError(connection, error) {
192
- console.error('[IPC Client] Connection error:', error);
506
+ this.logManager.error(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Connection error', {
507
+ id: connection.process.pid?.toString() || 'unknown',
508
+ operation: 'error',
509
+ error
510
+ });
193
511
  // Reject all pending requests
194
512
  for (const [requestId, pendingRequest] of connection.pendingRequests) {
195
513
  (0, local_engine_utils_1.cleanupPendingRequest)(pendingRequest);
@@ -198,10 +516,58 @@ class LocalEngineClient {
198
516
  connection.pendingRequests.clear();
199
517
  connection.ready = false;
200
518
  }
519
+ /**
520
+ * Flush remaining buffered output before connection closes
521
+ */
522
+ flushRemainingBuffers(connection) {
523
+ const logManager = LogManager_1.LogManager.getInstance();
524
+ // Flush stdout buffer if it has content
525
+ if (connection.stdoutBuffer?.trim()) {
526
+ try {
527
+ logManager.log({
528
+ source: LogManager_1.LogSource.App,
529
+ category: LogManager_1.LogCategory.AppRunner,
530
+ level: 'info',
531
+ message: connection.stdoutBuffer.trim(),
532
+ context: { id: 'unknown' }
533
+ });
534
+ connection.stdoutBuffer = '';
535
+ }
536
+ catch (error) {
537
+ this.logManager.error(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Error flushing stdout buffer', {
538
+ id: 'buffer',
539
+ operation: 'flush',
540
+ error
541
+ });
542
+ }
543
+ }
544
+ // Flush stderr buffer if it has content
545
+ if (connection.stderrBuffer?.trim()) {
546
+ try {
547
+ logManager.log({
548
+ source: LogManager_1.LogSource.App,
549
+ category: LogManager_1.LogCategory.AppRunner,
550
+ level: 'error',
551
+ message: connection.stderrBuffer.trim(),
552
+ context: { id: 'unknown' }
553
+ });
554
+ connection.stderrBuffer = '';
555
+ }
556
+ catch (error) {
557
+ this.logManager.error(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Error flushing stderr buffer', {
558
+ id: 'buffer',
559
+ operation: 'flush',
560
+ error
561
+ });
562
+ }
563
+ }
564
+ }
201
565
  /**
202
566
  * Handle connection exit
203
567
  */
204
568
  handleConnectionExit(connection, code, signal) {
569
+ // Flush any remaining buffered output before handling exit
570
+ this.flushRemainingBuffers(connection);
205
571
  // Reject all pending requests
206
572
  for (const [requestId, pendingRequest] of connection.pendingRequests) {
207
573
  (0, local_engine_utils_1.cleanupPendingRequest)(pendingRequest);
@@ -238,6 +604,50 @@ class LocalEngineClient {
238
604
  checkReady();
239
605
  });
240
606
  }
607
+ /**
608
+ * Get execution type from message type
609
+ */
610
+ getExecutionType(messageType) {
611
+ if (messageType === 'execute_function')
612
+ return 'function';
613
+ if (messageType === 'execute_lifecycle')
614
+ return 'lifecycle';
615
+ if (messageType.startsWith('execute_destination_'))
616
+ return 'destination';
617
+ if (messageType.startsWith('execute_source_'))
618
+ return 'source';
619
+ if (messageType === 'execute_job')
620
+ return 'jobs';
621
+ return 'function'; // fallback
622
+ }
623
+ /**
624
+ * Get execution ID from message
625
+ */
626
+ getExecutionId(message) {
627
+ switch (message.type) {
628
+ case 'execute_function':
629
+ return message.data.functionId;
630
+ case 'execute_lifecycle':
631
+ return message.data.method;
632
+ case 'execute_destination_ready':
633
+ case 'execute_destination_deliver':
634
+ case 'execute_destination_schema':
635
+ return message.data.destinationId;
636
+ case 'execute_source_webhook':
637
+ case 'execute_source_create':
638
+ case 'execute_source_update':
639
+ case 'execute_source_delete':
640
+ case 'execute_source_enable':
641
+ case 'execute_source_pause':
642
+ case 'execute_source_job':
643
+ case 'execute_source_schema':
644
+ return message.data.sourceId;
645
+ case 'execute_job':
646
+ return message.data.jobId;
647
+ default:
648
+ return 'unknown';
649
+ }
650
+ }
241
651
  /**
242
652
  * Send a request and wait for response
243
653
  */
@@ -246,6 +656,13 @@ class LocalEngineClient {
246
656
  const pendingRequest = (0, local_engine_utils_1.createPendingRequest)(message.id, message.type === 'execute_function' ? 'function' : 'lifecycle', resolve, reject, timeoutMs);
247
657
  // Set up timeout
248
658
  pendingRequest.timeout = (0, local_engine_utils_1.createRequestTimeout)(message.id, timeoutMs, reject, () => connection.pendingRequests.delete(message.id));
659
+ // Set execution context for stdout/stderr capture
660
+ connection.currentContext = {
661
+ type: this.getExecutionType(message.type),
662
+ id: this.getExecutionId(message),
663
+ requestId: message.id,
664
+ startTime: Date.now()
665
+ };
249
666
  // Track the request
250
667
  connection.pendingRequests.set(message.id, pendingRequest);
251
668
  // Send the message
@@ -329,6 +746,102 @@ class LocalEngineClient {
329
746
  };
330
747
  return this.sendRequest(connection, message);
331
748
  }
749
+ /**
750
+ * Execute source webhook
751
+ */
752
+ async executeSourceWebhook(request, appConfig) {
753
+ const connection = await this.getConnection(appConfig, appConfig.path);
754
+ const message = {
755
+ ...(0, local_engine_utils_1.createBaseMessage)('execute_source_webhook'),
756
+ type: 'execute_source_webhook',
757
+ data: request
758
+ };
759
+ return this.sendRequest(connection, message);
760
+ }
761
+ /**
762
+ * Execute source create lifecycle
763
+ */
764
+ async executeSourceCreate(sourceId, guid, appConfig) {
765
+ const connection = await this.getConnection(appConfig, appConfig.path);
766
+ const message = {
767
+ ...(0, local_engine_utils_1.createBaseMessage)('execute_source_create'),
768
+ type: 'execute_source_create',
769
+ data: { sourceId, guid, action: 'create' }
770
+ };
771
+ return this.sendRequest(connection, message);
772
+ }
773
+ /**
774
+ * Execute source update lifecycle
775
+ */
776
+ async executeSourceUpdate(sourceId, guid, appConfig) {
777
+ const connection = await this.getConnection(appConfig, appConfig.path);
778
+ const message = {
779
+ ...(0, local_engine_utils_1.createBaseMessage)('execute_source_update'),
780
+ type: 'execute_source_update',
781
+ data: { sourceId, guid, action: 'update' }
782
+ };
783
+ return this.sendRequest(connection, message);
784
+ }
785
+ /**
786
+ * Execute source delete lifecycle
787
+ */
788
+ async executeSourceDelete(sourceId, guid, appConfig) {
789
+ const connection = await this.getConnection(appConfig, appConfig.path);
790
+ const message = {
791
+ ...(0, local_engine_utils_1.createBaseMessage)('execute_source_delete'),
792
+ type: 'execute_source_delete',
793
+ data: { sourceId, guid, action: 'delete' }
794
+ };
795
+ return this.sendRequest(connection, message);
796
+ }
797
+ /**
798
+ * Execute source enable lifecycle
799
+ */
800
+ async executeSourceEnable(sourceId, guid, appConfig) {
801
+ const connection = await this.getConnection(appConfig, appConfig.path);
802
+ const message = {
803
+ ...(0, local_engine_utils_1.createBaseMessage)('execute_source_enable'),
804
+ type: 'execute_source_enable',
805
+ data: { sourceId, guid, action: 'enable' }
806
+ };
807
+ return this.sendRequest(connection, message);
808
+ }
809
+ /**
810
+ * Execute source pause lifecycle
811
+ */
812
+ async executeSourcePause(sourceId, guid, appConfig) {
813
+ const connection = await this.getConnection(appConfig, appConfig.path);
814
+ const message = {
815
+ ...(0, local_engine_utils_1.createBaseMessage)('execute_source_pause'),
816
+ type: 'execute_source_pause',
817
+ data: { sourceId, guid, action: 'pause' }
818
+ };
819
+ return this.sendRequest(connection, message);
820
+ }
821
+ /**
822
+ * Execute source job
823
+ */
824
+ async executeSourceJob(request, appConfig) {
825
+ const connection = await this.getConnection(appConfig, appConfig.path);
826
+ const message = {
827
+ ...(0, local_engine_utils_1.createBaseMessage)('execute_source_job'),
828
+ type: 'execute_source_job',
829
+ data: request
830
+ };
831
+ return this.sendRequest(connection, message);
832
+ }
833
+ /**
834
+ * Execute source schema
835
+ */
836
+ async executeSourceSchema(sourceId, appConfig) {
837
+ const connection = await this.getConnection(appConfig, appConfig.path);
838
+ const message = {
839
+ ...(0, local_engine_utils_1.createBaseMessage)('execute_source_schema'),
840
+ type: 'execute_source_schema',
841
+ data: { sourceId }
842
+ };
843
+ return this.sendRequest(connection, message);
844
+ }
332
845
  /**
333
846
  * Close a specific connection
334
847
  */
@@ -337,6 +850,8 @@ class LocalEngineClient {
337
850
  if (!connection)
338
851
  return;
339
852
  try {
853
+ // Flush any remaining buffered output before shutdown
854
+ this.flushRemainingBuffers(connection);
340
855
  // Send shutdown message
341
856
  const shutdownMessage = {
342
857
  ...(0, local_engine_utils_1.createBaseMessage)('shutdown'),
@@ -351,7 +866,11 @@ class LocalEngineClient {
351
866
  }
352
867
  }
353
868
  catch (error) {
354
- console.warn(`[IPC Client] Error during connection shutdown: ${error}`);
869
+ this.logManager.warn(LogManager_1.LogSource.System, LogManager_1.LogCategory.AppRunner, 'Error during connection shutdown', {
870
+ id: connection.process.pid?.toString() || 'unknown',
871
+ operation: 'shutdown',
872
+ error
873
+ });
355
874
  }
356
875
  finally {
357
876
  this.connections.delete(connectionKey);