@optimizely/ocp-local-env 1.0.0-beta.10

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 (244) hide show
  1. package/README.md +51 -0
  2. package/dist/package.json +112 -0
  3. package/dist/public/bundle.82dc5d29fffb9f205051.js +3 -0
  4. package/dist/public/bundle.82dc5d29fffb9f205051.js.LICENSE.txt +92 -0
  5. package/dist/public/bundle.82dc5d29fffb9f205051.js.map +1 -0
  6. package/dist/public/index.html +1 -0
  7. package/dist/src/cli.d.ts +2 -0
  8. package/dist/src/cli.js +115 -0
  9. package/dist/src/cli.js.map +1 -0
  10. package/dist/src/executor/DestinationExecutor.d.ts +19 -0
  11. package/dist/src/executor/DestinationExecutor.js +72 -0
  12. package/dist/src/executor/DestinationExecutor.js.map +1 -0
  13. package/dist/src/executor/FunctionExecutor.d.ts +67 -0
  14. package/dist/src/executor/FunctionExecutor.js +189 -0
  15. package/dist/src/executor/FunctionExecutor.js.map +1 -0
  16. package/dist/src/executor/JobExecutor.d.ts +79 -0
  17. package/dist/src/executor/JobExecutor.js +215 -0
  18. package/dist/src/executor/JobExecutor.js.map +1 -0
  19. package/dist/src/executor/LifecycleExecutor.d.ts +64 -0
  20. package/dist/src/executor/LifecycleExecutor.js +167 -0
  21. package/dist/src/executor/LifecycleExecutor.js.map +1 -0
  22. package/dist/src/executor/SourceExecutor.d.ts +32 -0
  23. package/dist/src/executor/SourceExecutor.js +163 -0
  24. package/dist/src/executor/SourceExecutor.js.map +1 -0
  25. package/dist/src/executor/watcher.d.ts +62 -0
  26. package/dist/src/executor/watcher.js +213 -0
  27. package/dist/src/executor/watcher.js.map +1 -0
  28. package/dist/src/functions/hello.d.ts +4 -0
  29. package/dist/src/functions/hello.js +8 -0
  30. package/dist/src/functions/hello.js.map +1 -0
  31. package/dist/src/index.d.ts +1 -0
  32. package/dist/src/index.js +9 -0
  33. package/dist/src/index.js.map +1 -0
  34. package/dist/src/jobs/dailyJob.d.ts +4 -0
  35. package/dist/src/jobs/dailyJob.js +8 -0
  36. package/dist/src/jobs/dailyJob.js.map +1 -0
  37. package/dist/src/local_engine/LocalFunctionApi.d.ts +17 -0
  38. package/dist/src/local_engine/LocalFunctionApi.js +54 -0
  39. package/dist/src/local_engine/LocalFunctionApi.js.map +1 -0
  40. package/dist/src/local_engine/LocalJobApi.d.ts +67 -0
  41. package/dist/src/local_engine/LocalJobApi.js +205 -0
  42. package/dist/src/local_engine/LocalJobApi.js.map +1 -0
  43. package/dist/src/local_engine/LocalNotifier.d.ts +9 -0
  44. package/dist/src/local_engine/LocalNotifier.js +26 -0
  45. package/dist/src/local_engine/LocalNotifier.js.map +1 -0
  46. package/dist/src/local_engine/local-engine-child-base.d.ts +110 -0
  47. package/dist/src/local_engine/local-engine-child-base.js +607 -0
  48. package/dist/src/local_engine/local-engine-child-base.js.map +1 -0
  49. package/dist/src/local_engine/local-engine-client.d.ts +161 -0
  50. package/dist/src/local_engine/local-engine-client.js +888 -0
  51. package/dist/src/local_engine/local-engine-client.js.map +1 -0
  52. package/dist/src/local_engine/local-engine-types.d.ts +245 -0
  53. package/dist/src/local_engine/local-engine-types.js +6 -0
  54. package/dist/src/local_engine/local-engine-types.js.map +1 -0
  55. package/dist/src/local_engine/local-engine-unified.d.ts +71 -0
  56. package/dist/src/local_engine/local-engine-unified.js +723 -0
  57. package/dist/src/local_engine/local-engine-unified.js.map +1 -0
  58. package/dist/src/local_engine/local-engine-utils.d.ts +68 -0
  59. package/dist/src/local_engine/local-engine-utils.js +219 -0
  60. package/dist/src/local_engine/local-engine-utils.js.map +1 -0
  61. package/dist/src/local_engine/localSDKConfig.d.ts +40 -0
  62. package/dist/src/local_engine/localSDKConfig.js +247 -0
  63. package/dist/src/local_engine/localSDKConfig.js.map +1 -0
  64. package/dist/src/local_engine/storage/BaseKVStoreWrapper.d.ts +37 -0
  65. package/dist/src/local_engine/storage/BaseKVStoreWrapper.js +110 -0
  66. package/dist/src/local_engine/storage/BaseKVStoreWrapper.js.map +1 -0
  67. package/dist/src/local_engine/storage/LocalConfigStore.d.ts +74 -0
  68. package/dist/src/local_engine/storage/LocalConfigStore.js +178 -0
  69. package/dist/src/local_engine/storage/LocalConfigStore.js.map +1 -0
  70. package/dist/src/local_engine/storage/LocalJobStore.d.ts +111 -0
  71. package/dist/src/local_engine/storage/LocalJobStore.js +249 -0
  72. package/dist/src/local_engine/storage/LocalJobStore.js.map +1 -0
  73. package/dist/src/local_engine/storage/LocalKVStore.d.ts +106 -0
  74. package/dist/src/local_engine/storage/LocalKVStore.js +1061 -0
  75. package/dist/src/local_engine/storage/LocalKVStore.js.map +1 -0
  76. package/dist/src/local_engine/storage/LocalNotificationStore.d.ts +28 -0
  77. package/dist/src/local_engine/storage/LocalNotificationStore.js +149 -0
  78. package/dist/src/local_engine/storage/LocalNotificationStore.js.map +1 -0
  79. package/dist/src/local_engine/storage/LocalSecretsStore.d.ts +115 -0
  80. package/dist/src/local_engine/storage/LocalSecretsStore.js +350 -0
  81. package/dist/src/local_engine/storage/LocalSecretsStore.js.map +1 -0
  82. package/dist/src/local_engine/storage/LocalSecretsStoreWrapper.d.ts +19 -0
  83. package/dist/src/local_engine/storage/LocalSecretsStoreWrapper.js +52 -0
  84. package/dist/src/local_engine/storage/LocalSecretsStoreWrapper.js.map +1 -0
  85. package/dist/src/local_engine/storage/LocalSettingsStore.d.ts +168 -0
  86. package/dist/src/local_engine/storage/LocalSettingsStore.js +509 -0
  87. package/dist/src/local_engine/storage/LocalSettingsStore.js.map +1 -0
  88. package/dist/src/local_engine/storage/LocalSettingsStoreWrapper.d.ts +15 -0
  89. package/dist/src/local_engine/storage/LocalSettingsStoreWrapper.js +28 -0
  90. package/dist/src/local_engine/storage/LocalSettingsStoreWrapper.js.map +1 -0
  91. package/dist/src/local_engine/storage/NumberSet.d.ts +21 -0
  92. package/dist/src/local_engine/storage/NumberSet.js +32 -0
  93. package/dist/src/local_engine/storage/NumberSet.js.map +1 -0
  94. package/dist/src/local_engine/storage/SourceDataStore.d.ts +23 -0
  95. package/dist/src/local_engine/storage/SourceDataStore.js +83 -0
  96. package/dist/src/local_engine/storage/SourceDataStore.js.map +1 -0
  97. package/dist/src/local_engine/storage/SourceJobExecutionStore.d.ts +25 -0
  98. package/dist/src/local_engine/storage/SourceJobExecutionStore.js +61 -0
  99. package/dist/src/local_engine/storage/SourceJobExecutionStore.js.map +1 -0
  100. package/dist/src/local_engine/storage/StringSet.d.ts +21 -0
  101. package/dist/src/local_engine/storage/StringSet.js +32 -0
  102. package/dist/src/local_engine/storage/StringSet.js.map +1 -0
  103. package/dist/src/local_engine/types.d.ts +53 -0
  104. package/dist/src/local_engine/types.js +6 -0
  105. package/dist/src/local_engine/types.js.map +1 -0
  106. package/dist/src/local_engine/utils.d.ts +33 -0
  107. package/dist/src/local_engine/utils.js +143 -0
  108. package/dist/src/local_engine/utils.js.map +1 -0
  109. package/dist/src/logging/LogManager.d.ts +246 -0
  110. package/dist/src/logging/LogManager.js +343 -0
  111. package/dist/src/logging/LogManager.js.map +1 -0
  112. package/dist/src/server/api/destinations.d.ts +7 -0
  113. package/dist/src/server/api/destinations.js +170 -0
  114. package/dist/src/server/api/destinations.js.map +1 -0
  115. package/dist/src/server/api/functions.d.ts +7 -0
  116. package/dist/src/server/api/functions.js +80 -0
  117. package/dist/src/server/api/functions.js.map +1 -0
  118. package/dist/src/server/api/jobs.d.ts +10 -0
  119. package/dist/src/server/api/jobs.js +244 -0
  120. package/dist/src/server/api/jobs.js.map +1 -0
  121. package/dist/src/server/api/settings.d.ts +6 -0
  122. package/dist/src/server/api/settings.js +116 -0
  123. package/dist/src/server/api/settings.js.map +1 -0
  124. package/dist/src/server/api/sources.d.ts +7 -0
  125. package/dist/src/server/api/sources.js +382 -0
  126. package/dist/src/server/api/sources.js.map +1 -0
  127. package/dist/src/server/api/stores.d.ts +2 -0
  128. package/dist/src/server/api/stores.js +341 -0
  129. package/dist/src/server/api/stores.js.map +1 -0
  130. package/dist/src/server/api/v1.d.ts +10 -0
  131. package/dist/src/server/api/v1.js +718 -0
  132. package/dist/src/server/api/v1.js.map +1 -0
  133. package/dist/src/server/api.d.ts +8 -0
  134. package/dist/src/server/api.js +217 -0
  135. package/dist/src/server/api.js.map +1 -0
  136. package/dist/src/server/app-discovery.d.ts +5 -0
  137. package/dist/src/server/app-discovery.js +113 -0
  138. package/dist/src/server/app-discovery.js.map +1 -0
  139. package/dist/src/server/config.d.ts +26 -0
  140. package/dist/src/server/config.js +112 -0
  141. package/dist/src/server/config.js.map +1 -0
  142. package/dist/src/server/mockDataGenerator.d.ts +1 -0
  143. package/dist/src/server/mockDataGenerator.js +154 -0
  144. package/dist/src/server/mockDataGenerator.js.map +1 -0
  145. package/dist/src/server/websocket.d.ts +0 -0
  146. package/dist/src/server/websocket.js +2 -0
  147. package/dist/src/server/websocket.js.map +1 -0
  148. package/dist/src/server.d.ts +2 -0
  149. package/dist/src/server.js +735 -0
  150. package/dist/src/server.js.map +1 -0
  151. package/dist/src/types/app.d.ts +154 -0
  152. package/dist/src/types/app.js +24 -0
  153. package/dist/src/types/app.js.map +1 -0
  154. package/dist/src/types/kvstore.d.ts +320 -0
  155. package/dist/src/types/kvstore.js +5 -0
  156. package/dist/src/types/kvstore.js.map +1 -0
  157. package/dist/src/ui/components/App.d.ts +6 -0
  158. package/dist/src/ui/components/App.js +432 -0
  159. package/dist/src/ui/components/App.js.map +1 -0
  160. package/dist/src/ui/components/DestinationBatchEditor.d.ts +7 -0
  161. package/dist/src/ui/components/DestinationBatchEditor.js +160 -0
  162. package/dist/src/ui/components/DestinationBatchEditor.js.map +1 -0
  163. package/dist/src/ui/components/DestinationSchemaViewer.d.ts +7 -0
  164. package/dist/src/ui/components/DestinationSchemaViewer.js +61 -0
  165. package/dist/src/ui/components/DestinationSchemaViewer.js.map +1 -0
  166. package/dist/src/ui/components/DestinationsView.d.ts +14 -0
  167. package/dist/src/ui/components/DestinationsView.js +68 -0
  168. package/dist/src/ui/components/DestinationsView.js.map +1 -0
  169. package/dist/src/ui/components/FunctionsView.d.ts +13 -0
  170. package/dist/src/ui/components/FunctionsView.js +288 -0
  171. package/dist/src/ui/components/FunctionsView.js.map +1 -0
  172. package/dist/src/ui/components/JobsView.d.ts +13 -0
  173. package/dist/src/ui/components/JobsView.js +320 -0
  174. package/dist/src/ui/components/JobsView.js.map +1 -0
  175. package/dist/src/ui/components/KVStoreViewer.d.ts +11 -0
  176. package/dist/src/ui/components/KVStoreViewer.js +168 -0
  177. package/dist/src/ui/components/KVStoreViewer.js.map +1 -0
  178. package/dist/src/ui/components/MetadataModal.d.ts +14 -0
  179. package/dist/src/ui/components/MetadataModal.js +28 -0
  180. package/dist/src/ui/components/MetadataModal.js.map +1 -0
  181. package/dist/src/ui/components/MetadataModal.test.d.ts +1 -0
  182. package/dist/src/ui/components/MetadataModal.test.js +143 -0
  183. package/dist/src/ui/components/MetadataModal.test.js.map +1 -0
  184. package/dist/src/ui/components/NotificationViewer.d.ts +16 -0
  185. package/dist/src/ui/components/NotificationViewer.js +69 -0
  186. package/dist/src/ui/components/NotificationViewer.js.map +1 -0
  187. package/dist/src/ui/components/SecretsStoreViewer.d.ts +11 -0
  188. package/dist/src/ui/components/SecretsStoreViewer.js +179 -0
  189. package/dist/src/ui/components/SecretsStoreViewer.js.map +1 -0
  190. package/dist/src/ui/components/SettingsStoreViewer.d.ts +24 -0
  191. package/dist/src/ui/components/SettingsStoreViewer.js +132 -0
  192. package/dist/src/ui/components/SettingsStoreViewer.js.map +1 -0
  193. package/dist/src/ui/components/SourceDataViewer.d.ts +8 -0
  194. package/dist/src/ui/components/SourceDataViewer.js +84 -0
  195. package/dist/src/ui/components/SourceDataViewer.js.map +1 -0
  196. package/dist/src/ui/components/SourceJobsSection.d.ts +8 -0
  197. package/dist/src/ui/components/SourceJobsSection.js +99 -0
  198. package/dist/src/ui/components/SourceJobsSection.js.map +1 -0
  199. package/dist/src/ui/components/SourceLifecycleSection.d.ts +7 -0
  200. package/dist/src/ui/components/SourceLifecycleSection.js +58 -0
  201. package/dist/src/ui/components/SourceLifecycleSection.js.map +1 -0
  202. package/dist/src/ui/components/SourceSchemaViewer.d.ts +7 -0
  203. package/dist/src/ui/components/SourceSchemaViewer.js +65 -0
  204. package/dist/src/ui/components/SourceSchemaViewer.js.map +1 -0
  205. package/dist/src/ui/components/SourceWebhookEditor.d.ts +8 -0
  206. package/dist/src/ui/components/SourceWebhookEditor.js +181 -0
  207. package/dist/src/ui/components/SourceWebhookEditor.js.map +1 -0
  208. package/dist/src/ui/components/SourcesView.d.ts +14 -0
  209. package/dist/src/ui/components/SourcesView.js +74 -0
  210. package/dist/src/ui/components/SourcesView.js.map +1 -0
  211. package/dist/src/ui/components/StoreViewer.d.ts +16 -0
  212. package/dist/src/ui/components/StoreViewer.js +86 -0
  213. package/dist/src/ui/components/StoreViewer.js.map +1 -0
  214. package/dist/src/ui/components/TabbedConsole.d.ts +17 -0
  215. package/dist/src/ui/components/TabbedConsole.js +163 -0
  216. package/dist/src/ui/components/TabbedConsole.js.map +1 -0
  217. package/dist/src/ui/components/common/DataTree.d.ts +15 -0
  218. package/dist/src/ui/components/common/DataTree.js +95 -0
  219. package/dist/src/ui/components/common/DataTree.js.map +1 -0
  220. package/dist/src/ui/components/common/EyeIcon.d.ts +11 -0
  221. package/dist/src/ui/components/common/EyeIcon.js +11 -0
  222. package/dist/src/ui/components/common/EyeIcon.js.map +1 -0
  223. package/dist/src/ui/hooks/useEntityNavigation.d.ts +72 -0
  224. package/dist/src/ui/hooks/useEntityNavigation.js +150 -0
  225. package/dist/src/ui/hooks/useEntityNavigation.js.map +1 -0
  226. package/dist/src/ui/hooks/useQueryParams.d.ts +6 -0
  227. package/dist/src/ui/hooks/useQueryParams.js +39 -0
  228. package/dist/src/ui/hooks/useQueryParams.js.map +1 -0
  229. package/dist/src/ui/index.d.ts +1 -0
  230. package/dist/src/ui/index.js +23 -0
  231. package/dist/src/ui/index.js.map +1 -0
  232. package/dist/src/ui/store/formStateSlice.d.ts +54 -0
  233. package/dist/src/ui/store/formStateSlice.js +94 -0
  234. package/dist/src/ui/store/formStateSlice.js.map +1 -0
  235. package/dist/src/ui/store/hooks.d.ts +6 -0
  236. package/dist/src/ui/store/hooks.js +8 -0
  237. package/dist/src/ui/store/hooks.js.map +1 -0
  238. package/dist/src/ui/store/index.d.ts +11 -0
  239. package/dist/src/ui/store/index.js +107 -0
  240. package/dist/src/ui/store/index.js.map +1 -0
  241. package/dist/src/utils/functionEndpoints.d.ts +24 -0
  242. package/dist/src/utils/functionEndpoints.js +45 -0
  243. package/dist/src/utils/functionEndpoints.js.map +1 -0
  244. package/package.json +112 -0
@@ -0,0 +1,723 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * Local Engine Unified
5
+ *
6
+ * This script runs in the app's Node.js process context and executes both OCP functions
7
+ * and lifecycle methods using IPC communication with the parent process.
8
+ * This is a single, persistent process that handles all app execution requests.
9
+ */
10
+ var __importDefault = (this && this.__importDefault) || function (mod) {
11
+ return (mod && mod.__esModule) ? mod : { "default": mod };
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.LocalEngineUnified = void 0;
15
+ const path_1 = __importDefault(require("path"));
16
+ const fs_1 = __importDefault(require("fs"));
17
+ const local_engine_child_base_1 = require("./local-engine-child-base");
18
+ const utils_1 = require("./utils");
19
+ const SourceDataStore_1 = require("./storage/SourceDataStore");
20
+ const SourceJobExecutionStore_1 = require("./storage/SourceJobExecutionStore");
21
+ class LocalEngineUnified extends local_engine_child_base_1.LocalEngineChildBase {
22
+ constructor() {
23
+ super(...arguments);
24
+ this.runtime = null;
25
+ this.isInitialized = false;
26
+ }
27
+ /**
28
+ * Initialize the wrapper with app configuration
29
+ * This happens once when the process starts
30
+ */
31
+ async initialize(appConfig, appDir) {
32
+ if (this.isInitialized) {
33
+ this.sendLog('info', 'Wrapper already initialized, skipping initialization');
34
+ return;
35
+ }
36
+ this.sendLog('info', `Initializing unified wrapper for app: ${appConfig.manifest.meta?.app_id || 'unknown'}`);
37
+ try {
38
+ // Load the SDK from app's node_modules
39
+ this.sdkComponents = (0, utils_1.loadAppSDK)(appDir);
40
+ this.sendLog('info', 'SDK loaded successfully');
41
+ // Initialize Runtime
42
+ this.sendLog('info', 'Initializing Runtime...');
43
+ // Try initializing with dist directory first (where built files are)
44
+ try {
45
+ const distDir = path_1.default.join(appDir, 'dist');
46
+ this.runtime = await this.sdkComponents.Runtime.initialize(distDir);
47
+ this.sendLog('info', 'Runtime initialized successfully with dist directory');
48
+ }
49
+ catch (error) {
50
+ // Fallback: try with base directory
51
+ this.sendLog('warn', `Runtime initialization with dist dir failed: ${error}, trying base directory`);
52
+ this.runtime = await this.sdkComponents.Runtime.initialize(appDir);
53
+ this.sendLog('info', 'Runtime initialized successfully with base directory');
54
+ }
55
+ // Import local engine components using dynamic require
56
+ const localEngineDir = __dirname;
57
+ const storageDir = path_1.default.join(__dirname, 'storage');
58
+ const localSDKConfig = require(path_1.default.join(localEngineDir, 'localSDKConfig'));
59
+ this.configureLocalSDKs = localSDKConfig.configureLocalSDKs;
60
+ this.cleanUpLocalSDKs = localSDKConfig.cleanUpLocalSDKs;
61
+ this.LocalSettingsStore = require(path_1.default.join(storageDir, 'LocalSettingsStore')).LocalSettingsStore;
62
+ this.LocalConfigStore = require(path_1.default.join(storageDir, 'LocalConfigStore')).LocalConfigStore;
63
+ this.sendLog('info', 'Local engine components loaded');
64
+ // Configure SDKs for the app
65
+ const settingsStore = this.LocalSettingsStore.getInstance(appDir);
66
+ const configStore = new this.LocalConfigStore(appDir);
67
+ this.sendLog('info', 'Configuring SDKs for local testing...');
68
+ this.configureLocalSDKs(appConfig, settingsStore, appDir, 1, configStore, appConfig.account, appConfig.baseUrl);
69
+ // Initialize source stores
70
+ this.sourceDataStore = new SourceDataStore_1.SourceDataStore(appDir);
71
+ this.sourceJobExecutionStore = new SourceJobExecutionStore_1.SourceJobExecutionStore(appDir);
72
+ this.isInitialized = true;
73
+ this.sendLog('info', 'Unified wrapper initialized successfully - ready to handle function and lifecycle requests');
74
+ }
75
+ catch (error) {
76
+ this.sendLog('error', `Initialization failed: ${error}`);
77
+ throw error;
78
+ }
79
+ }
80
+ /**
81
+ * Execute a function with the given request
82
+ */
83
+ async executeFunction(request) {
84
+ if (!this.appConfig || !this.appDir) {
85
+ throw new Error('Wrapper not properly initialized');
86
+ }
87
+ if (!this.isInitialized) {
88
+ throw new Error('SDK not initialized');
89
+ }
90
+ this.sendLog('info', `Executing function: ${request.functionId}`, this.currentRequestId);
91
+ this.sendProgress(this.currentRequestId, 'Finding function file', 20);
92
+ // Find the built function file
93
+ const functionPath = (0, utils_1.findFunctionFile)(this.appDir, request.functionId, this.appConfig.manifest);
94
+ this.sendLog('info', `Using function file: ${functionPath}`, this.currentRequestId);
95
+ this.sendProgress(this.currentRequestId, 'Loading function module', 40);
96
+ // Load the function module
97
+ const FunctionModule = require(functionPath);
98
+ const FunctionClass = (0, utils_1.findFunctionClass)(FunctionModule);
99
+ this.sendLog('info', 'Function class found, creating request object...', this.currentRequestId);
100
+ this.sendProgress(this.currentRequestId, 'Creating request object', 60);
101
+ // Convert headers array to the format expected by InternalRequest
102
+ const headers = request.headers || [];
103
+ // Convert body to Uint8Array if present
104
+ let bodyArray = null;
105
+ if (request.body !== null && request.body !== undefined) {
106
+ const bodyString = typeof request.body === 'string' ?
107
+ request.body : JSON.stringify(request.body);
108
+ bodyArray = new Uint8Array(Buffer.from(bodyString, 'utf8'));
109
+ }
110
+ const internalRequest = new this.sdkComponents.App.InternalRequest(request.method, request.fullpath, request.path, request.params || {}, headers, bodyArray);
111
+ this.sendLog('debug', `Created InternalRequest - method: ${request.method}, path: ${request.path}`, this.currentRequestId);
112
+ // Create function instance and call perform
113
+ const functionInstance = new FunctionClass(internalRequest);
114
+ if (typeof functionInstance.perform !== 'function') {
115
+ throw new Error('Function class does not implement perform method');
116
+ }
117
+ this.sendLog('info', 'Executing function perform method...', this.currentRequestId);
118
+ this.sendProgress(this.currentRequestId, 'Executing function', 80);
119
+ // Call the function's perform method
120
+ const response = await functionInstance.perform();
121
+ this.sendLog('info', `Function execution completed - status: ${response.status}`, this.currentRequestId);
122
+ this.sendProgress(this.currentRequestId, 'Function execution completed', 100);
123
+ // Convert response to serializable format
124
+ const result = {
125
+ success: true,
126
+ status: response.status || 200,
127
+ headers: response.headers ? response.headers.toArray() : [],
128
+ body: response.bodyAsU8Array ? Array.from(response.bodyAsU8Array) : null
129
+ };
130
+ return result;
131
+ }
132
+ /**
133
+ * Execute a lifecycle method with the given request
134
+ */
135
+ async executeLifecycle(request) {
136
+ if (!this.appConfig || !this.appDir) {
137
+ throw new Error('Wrapper not properly initialized');
138
+ }
139
+ if (!this.isInitialized) {
140
+ throw new Error('SDK not initialized');
141
+ }
142
+ this.sendLog('info', `Executing lifecycle method: ${request.method}`, this.currentRequestId);
143
+ this.sendProgress(this.currentRequestId, 'Checking lifecycle file', 20);
144
+ // Check if built file exists
145
+ if (!fs_1.default.existsSync(request.scriptPath)) {
146
+ throw new Error(`Lifecycle file not built or not found at ${request.scriptPath}`);
147
+ }
148
+ this.sendLog('info', `Using lifecycle file: ${request.scriptPath}`, this.currentRequestId);
149
+ this.sendProgress(this.currentRequestId, 'Loading lifecycle module', 40);
150
+ // Load the lifecycle module
151
+ const LifecycleModule = require(request.scriptPath);
152
+ const LifecycleClass = (0, utils_1.findLifecycleClass)(LifecycleModule);
153
+ // Create instance and call the method
154
+ const lifecycle = new LifecycleClass();
155
+ if (typeof lifecycle[request.method] !== 'function') {
156
+ throw new Error(`Method ${request.method} not found on Lifecycle class`);
157
+ }
158
+ this.sendLog('info', `Executing ${request.method} with params: ${JSON.stringify(request.params)}`, this.currentRequestId);
159
+ this.sendProgress(this.currentRequestId, 'Executing lifecycle method', 60);
160
+ // Call the lifecycle method with appropriate parameters
161
+ let result;
162
+ if (request.method === 'onUpgrade') {
163
+ result = await lifecycle[request.method](request.params?.fromVersion || '0.0.0');
164
+ }
165
+ else if (request.method === 'onSettingsForm') {
166
+ const params = request.params || {};
167
+ result = await lifecycle[request.method](params.page, params.action, params.formData);
168
+ }
169
+ else {
170
+ result = await lifecycle[request.method]();
171
+ }
172
+ this.sendLog('info', `Lifecycle method result: ${JSON.stringify(result)}`, this.currentRequestId);
173
+ this.sendProgress(this.currentRequestId, 'Processing result', 80);
174
+ // Handle different lifecycle method return types
175
+ let processedResult;
176
+ if (request.method === 'onSettingsForm') {
177
+ // The result should be a LifecycleSettingsResult with getResponse method
178
+ let settingsResponse = {};
179
+ if (result && typeof result.getResponse === 'function') {
180
+ this.sendLog('debug', 'Getting response from LifecycleSettingsResult', this.currentRequestId);
181
+ const params = request.params || {};
182
+ settingsResponse = result.getResponse(params.page);
183
+ this.sendLog('debug', `Settings response: ${JSON.stringify(settingsResponse)}`, this.currentRequestId);
184
+ }
185
+ else if (result) {
186
+ this.sendLog('debug', 'Using result as fallback', this.currentRequestId);
187
+ // Fallback - use result as is
188
+ settingsResponse = result;
189
+ }
190
+ // Mock the storage.settings.getAllSections() call since we don't have the full SDK context
191
+ // In real implementation, this would fetch from the app's settings store
192
+ const mockFormData = {}; // This will be populated by the REST endpoint
193
+ processedResult = {
194
+ result: settingsResponse,
195
+ data: mockFormData
196
+ };
197
+ }
198
+ else if (request.method === 'onInstall' || request.method === 'onUninstall' || request.method === 'onUpgrade') {
199
+ // These methods return LifecycleResult with success property
200
+ if (result && typeof result === 'object' && 'success' in result) {
201
+ processedResult = result;
202
+ }
203
+ else {
204
+ // If the result doesn't have success property, assume success if no error was thrown
205
+ this.sendLog('warn', `Lifecycle method ${request.method} did not return a proper LifecycleResult object. Assuming success.`, this.currentRequestId);
206
+ processedResult = {
207
+ success: true,
208
+ message: result?.message || 'Operation completed without explicit success status'
209
+ };
210
+ }
211
+ }
212
+ else if (request.method === 'canUninstall') {
213
+ // canUninstall returns CanUninstallResult with uninstallable property
214
+ if (result && typeof result === 'object' && 'uninstallable' in result) {
215
+ processedResult = result;
216
+ }
217
+ else {
218
+ // If the result doesn't have uninstallable property, this is an error
219
+ throw new Error(`Lifecycle method canUninstall did not return a proper CanUninstallResult object with uninstallable property. Result: ${JSON.stringify(result)}`);
220
+ }
221
+ }
222
+ else {
223
+ // Default fallback for other methods
224
+ processedResult = result;
225
+ }
226
+ this.sendProgress(this.currentRequestId, 'Lifecycle execution completed', 100);
227
+ return {
228
+ success: request.method === 'onSettingsForm' ? true : (processedResult?.success !== false),
229
+ result: processedResult
230
+ };
231
+ }
232
+ /**
233
+ * Execute a job with the given request
234
+ */
235
+ async executeJob(request) {
236
+ if (!this.appConfig || !this.appDir) {
237
+ throw new Error('Local engine not properly initialized');
238
+ }
239
+ if (!this.isInitialized) {
240
+ throw new Error('SDK not initialized');
241
+ }
242
+ this.sendLog('info', `Executing job: ${request.jobId}`, this.currentRequestId);
243
+ this.sendProgress(this.currentRequestId, 'Finding job file', 20);
244
+ // Find job definition in manifest
245
+ const manifest = this.appConfig.manifest;
246
+ let jobDef = null;
247
+ let isSourceJob = false;
248
+ // Check regular jobs
249
+ if (manifest.jobs && manifest.jobs[request.jobId]) {
250
+ jobDef = manifest.jobs[request.jobId];
251
+ isSourceJob = false;
252
+ }
253
+ // Check source jobs (nested under sources)
254
+ else if (manifest.sources) {
255
+ for (const [sourceId, source] of Object.entries(manifest.sources)) {
256
+ const sourceAny = source;
257
+ if (sourceAny.jobs) {
258
+ const compositeJobId = `${sourceId}_${Object.keys(sourceAny.jobs)[0]}`;
259
+ if (compositeJobId === request.jobId || Object.keys(sourceAny.jobs).includes(request.jobId)) {
260
+ const actualJobId = request.jobId.includes('_') ? request.jobId.split('_')[1] : request.jobId;
261
+ jobDef = sourceAny.jobs[actualJobId];
262
+ isSourceJob = true;
263
+ break;
264
+ }
265
+ }
266
+ }
267
+ }
268
+ if (!jobDef) {
269
+ throw new Error(`Job not found in manifest: ${request.jobId}`);
270
+ }
271
+ // Find the built job file
272
+ const jobPath = path_1.default.join(this.appDir, 'dist', 'jobs', `${jobDef.entry_point}.js`);
273
+ if (!fs_1.default.existsSync(jobPath)) {
274
+ throw new Error(`Job file not built or not found: dist/jobs/${jobDef.entry_point}.js`);
275
+ }
276
+ this.sendLog('info', `Using job file: ${jobPath}`, this.currentRequestId);
277
+ this.sendProgress(this.currentRequestId, 'Loading job module', 40);
278
+ // Import job module
279
+ const JobModule = require(jobPath);
280
+ // Find job class (look for default export or named export matching entry point)
281
+ let JobClass = JobModule.default || JobModule[jobDef.entry_point] || JobModule;
282
+ if (typeof JobClass !== 'function') {
283
+ // Look for any class in the module
284
+ const exports = Object.keys(JobModule);
285
+ for (const key of exports) {
286
+ if (typeof JobModule[key] === 'function' && JobModule[key].prototype) {
287
+ JobClass = JobModule[key];
288
+ break;
289
+ }
290
+ }
291
+ }
292
+ if (typeof JobClass !== 'function') {
293
+ throw new Error(`No job class found in ${jobPath}`);
294
+ }
295
+ this.sendLog('info', 'Job class found, creating invocation...', this.currentRequestId);
296
+ this.sendProgress(this.currentRequestId, 'Creating job invocation', 60);
297
+ // Create job invocation
298
+ const invocation = {
299
+ jobId: `${request.jobId}_${Date.now()}`, // Unique run ID
300
+ scheduledAt: new Date(),
301
+ parameters: request.parameters || {}
302
+ };
303
+ // Add dataSyncId for source jobs
304
+ if (isSourceJob && request.dataSyncId) {
305
+ invocation.dataSyncId = request.dataSyncId;
306
+ }
307
+ this.sendLog('info', 'Creating job instance...', this.currentRequestId);
308
+ // Create job instance
309
+ let jobInstance;
310
+ if (isSourceJob && request.dataSyncId) {
311
+ // Source job requires source parameter
312
+ const mockSource = { id: request.sourceKey || 'local-source' };
313
+ jobInstance = new JobClass(invocation, mockSource);
314
+ }
315
+ else {
316
+ jobInstance = new JobClass(invocation);
317
+ }
318
+ // Validate job instance has required methods
319
+ if (typeof jobInstance.prepare !== 'function') {
320
+ throw new Error('Job class does not implement prepare method');
321
+ }
322
+ if (typeof jobInstance.perform !== 'function') {
323
+ throw new Error('Job class does not implement perform method');
324
+ }
325
+ this.sendLog('info', 'Executing job prepare method...', this.currentRequestId);
326
+ this.sendProgress(this.currentRequestId, 'Preparing job', 70);
327
+ // Import LocalJobStore to track state
328
+ const { LocalJobStore } = require('./storage/LocalJobStore');
329
+ const jobStore = LocalJobStore.getInstance(request.appDir);
330
+ const { createHash } = require('crypto');
331
+ let status;
332
+ let statusHash;
333
+ try {
334
+ // Execute prepare phase
335
+ this.sendLog('info', 'Executing job prepare method...', this.currentRequestId);
336
+ status = await jobInstance.prepare(request.parameters || {});
337
+ statusHash = createHash('sha256').update(JSON.stringify(status)).digest('hex');
338
+ // Save initial state from prepare
339
+ jobStore.saveState(request.executionId, status, status.complete || false, statusHash, 'prepare');
340
+ this.sendLog('info', 'Job prepared successfully', this.currentRequestId);
341
+ }
342
+ catch (error) {
343
+ this.sendLog('error', `Job prepare failed: ${error.message}`, this.currentRequestId);
344
+ // Mark job as failed in store
345
+ const { LocalJobStore, JobExecutionStatus } = require('./storage/LocalJobStore');
346
+ const failedJobStore = LocalJobStore.getInstance(request.appDir);
347
+ failedJobStore.updateExecutionStatus(request.executionId, JobExecutionStatus.FAILED, {
348
+ message: error.message,
349
+ stack: error.stack
350
+ });
351
+ throw new Error(`Job prepare method failed: ${error.message}`);
352
+ }
353
+ this.sendLog('info', 'Job prepared, starting perform loop...', this.currentRequestId);
354
+ this.sendProgress(this.currentRequestId, 'Executing job', 80);
355
+ // Execute perform loop
356
+ let loopCount = 0;
357
+ const maxLoops = 1000; // Safety limit
358
+ while (!status.complete && loopCount < maxLoops) {
359
+ this.sendLog('debug', `Job perform loop ${loopCount + 1}`, this.currentRequestId);
360
+ try {
361
+ status = await jobInstance.perform(status);
362
+ loopCount++;
363
+ // Check if state changed and save if so
364
+ const newStatusHash = createHash('sha256').update(JSON.stringify(status)).digest('hex');
365
+ if (statusHash !== newStatusHash) {
366
+ jobStore.saveState(request.executionId, status, status.complete || false, newStatusHash, 'perform');
367
+ statusHash = newStatusHash;
368
+ }
369
+ // Update progress
370
+ this.sendProgress(this.currentRequestId, `Job perform loop ${loopCount}`, 80 + (loopCount / maxLoops) * 15);
371
+ }
372
+ catch (error) {
373
+ this.sendLog('error', `Job perform failed at loop ${loopCount + 1}: ${error.message}`, this.currentRequestId);
374
+ // Mark job as failed in store
375
+ const { LocalJobStore, JobExecutionStatus } = require('./storage/LocalJobStore');
376
+ const failedJobStore = LocalJobStore.getInstance(request.appDir);
377
+ failedJobStore.updateExecutionStatus(request.executionId, JobExecutionStatus.FAILED, {
378
+ message: error.message,
379
+ stack: error.stack
380
+ });
381
+ throw new Error(`Job perform method failed at loop ${loopCount + 1}: ${error.message}`);
382
+ }
383
+ }
384
+ if (loopCount >= maxLoops && !status.complete) {
385
+ // Mark job as failed due to excessive loops
386
+ const { LocalJobStore, JobExecutionStatus } = require('./storage/LocalJobStore');
387
+ const failedJobStore = LocalJobStore.getInstance(request.appDir);
388
+ failedJobStore.updateExecutionStatus(request.executionId, JobExecutionStatus.FAILED, {
389
+ message: `Job exceeded maximum loop count (${maxLoops})`,
390
+ stack: new Error().stack
391
+ });
392
+ throw new Error(`Job exceeded maximum loop count (${maxLoops})`);
393
+ }
394
+ this.sendLog('info', `Job completed after ${loopCount} perform loops`, this.currentRequestId);
395
+ this.sendProgress(this.currentRequestId, 'Job execution completed', 100);
396
+ return {
397
+ success: true,
398
+ result: status,
399
+ loopCount
400
+ };
401
+ }
402
+ /**
403
+ * Execute destination ready() method
404
+ */
405
+ async executeDestinationReady(data) {
406
+ const { destinationId } = data; // entryPoint no longer needed
407
+ if (!this.runtime) {
408
+ throw new Error('Runtime not initialized');
409
+ }
410
+ this.sendLog('info', `Executing ready() for destination: ${destinationId}`, this.currentRequestId);
411
+ // Use Runtime to get destination class
412
+ const DestinationClass = await this.runtime.getDestinationClass(destinationId);
413
+ const destination = new DestinationClass();
414
+ const result = await destination.ready();
415
+ this.sendLog('info', `Destination ready() result: ${JSON.stringify(result)}`, this.currentRequestId);
416
+ return result;
417
+ }
418
+ /**
419
+ * Execute destination deliver() method
420
+ */
421
+ async executeDestinationDeliver(data) {
422
+ const { destinationId, batch } = data; // entryPoint no longer needed
423
+ if (!this.runtime) {
424
+ throw new Error('Runtime not initialized');
425
+ }
426
+ this.sendLog('debug', `Batch: ${JSON.stringify(batch)}`, this.currentRequestId);
427
+ // Use Runtime to get destination class
428
+ const DestinationClass = await this.runtime.getDestinationClass(destinationId);
429
+ const destination = new DestinationClass();
430
+ const result = await destination.deliver(batch);
431
+ this.sendLog('info', `Destination deliver() result: ${JSON.stringify(result)}`, this.currentRequestId);
432
+ return result;
433
+ }
434
+ /**
435
+ * Execute destination schema function
436
+ */
437
+ async executeDestinationSchema(data) {
438
+ const { destinationId } = data;
439
+ if (!this.runtime) {
440
+ throw new Error('Runtime not initialized');
441
+ }
442
+ this.sendLog('info', `Loading schema for destination: ${destinationId}`, this.currentRequestId);
443
+ // Get destination definition from manifest via Runtime
444
+ const destination = this.runtime.manifest.destinations?.[destinationId];
445
+ if (!destination) {
446
+ // Use Runtime's error message format for consistency with production
447
+ throw new Error(`No destination '${destinationId}' defined in manifest`);
448
+ }
449
+ let schema;
450
+ // Check if schema is static (YAML) or dynamic (function)
451
+ if (typeof destination.schema === 'string') {
452
+ // Load static YAML schema using Runtime
453
+ this.sendLog('info', `Loading static YAML schema: ${destination.schema}`, this.currentRequestId);
454
+ const allSchemas = this.runtime.getDestinationSchema();
455
+ // Runtime returns schemas keyed by file path, e.g., "destinations/schema/myschema.yml"
456
+ const schemaKey = `destinations/schema/${destination.schema}.yml`;
457
+ const schemaKeyYaml = `destinations/schema/${destination.schema}.yaml`;
458
+ schema = allSchemas[schemaKey] || allSchemas[schemaKeyYaml];
459
+ if (!schema) {
460
+ throw new Error(`Schema file not found: ${destination.schema}.yml or .yaml`);
461
+ }
462
+ this.sendLog('info', `Static schema loaded: ${destination.schema}`, this.currentRequestId);
463
+ }
464
+ else if (destination.schema?.entry_point) {
465
+ // Load dynamic schema function using Runtime
466
+ this.sendLog('info', `Loading dynamic schema function for: ${destinationId}`, this.currentRequestId);
467
+ const SchemaFunctionClass = await this.runtime.getDestinationSchemaFunctionClass(destinationId);
468
+ const schemaFunction = new SchemaFunctionClass({ destinationKey: destinationId });
469
+ schema = await schemaFunction.getDestinationsSchema();
470
+ this.sendLog('info', `Dynamic schema loaded for ${destinationId}: ${schema.name}`, this.currentRequestId);
471
+ }
472
+ else {
473
+ throw new Error(`Destination '${destinationId}' has invalid schema configuration`);
474
+ }
475
+ return schema;
476
+ }
477
+ /**
478
+ * Handle source webhook
479
+ */
480
+ async handleSourceWebhook(message) {
481
+ const { sourceId, guid, method, fullpath, path, params, headers, body } = message.data;
482
+ if (!this.appConfig) {
483
+ throw new Error('App configuration not initialized');
484
+ }
485
+ // Create configuration
486
+ const sources = this.appConfig.manifest.sources || {};
487
+ const sourceManifest = sources[sourceId];
488
+ if (!sourceManifest) {
489
+ throw new Error(`Source ${sourceId} not found in manifest`);
490
+ }
491
+ const config = {
492
+ dataSyncId: 'mock-data-sync-id',
493
+ sourceKey: sourceId,
494
+ schema: sourceManifest.schema,
495
+ webhookUrl: `http://localhost:${process.env.PORT || 8080}/sources/${this.appConfig.manifest.meta?.app_id}/${sourceId}/${guid}`
496
+ };
497
+ // Load SourceFunction class using runtime - pass sourceId, runtime looks up entry_point
498
+ const SourceFunctionClass = await this.runtime.getSourceFunctionClass(sourceId);
499
+ // Create Request instance using dynamically loaded class
500
+ // Convert body to Buffer format (SDK expects raw body as Uint8Array, not parsed object)
501
+ const bodyBuffer = body ? Buffer.from(JSON.stringify(body)) : Buffer.from('');
502
+ const request = new this.sdkComponents.Request(method, path, params, headers, bodyBuffer);
503
+ // Create mocked Source instance
504
+ const mockedSource = {
505
+ emit: async (data) => {
506
+ this.sourceDataStore.push(sourceId, data, 'webhook');
507
+ return { success: true };
508
+ }
509
+ };
510
+ // Instantiate and execute
511
+ const sourceFunction = new SourceFunctionClass(config, request, mockedSource);
512
+ const response = await sourceFunction.perform();
513
+ // Return response (convert to serializable format like function execution)
514
+ return {
515
+ status: response.status,
516
+ headers: response.headers ? response.headers.toArray() : [],
517
+ body: response.bodyAsU8Array ? Array.from(response.bodyAsU8Array) : null
518
+ };
519
+ }
520
+ /**
521
+ * Handle source lifecycle
522
+ */
523
+ async handleSourceLifecycle(message, action) {
524
+ const { sourceId, guid } = message.data;
525
+ if (!this.appConfig) {
526
+ throw new Error('App configuration not initialized');
527
+ }
528
+ // Create configuration
529
+ const sources = this.appConfig.manifest.sources || {};
530
+ const sourceManifest = sources[sourceId];
531
+ if (!sourceManifest) {
532
+ throw new Error(`Source ${sourceId} not found in manifest`);
533
+ }
534
+ const config = {
535
+ dataSyncId: 'mock-data-sync-id',
536
+ sourceKey: sourceId,
537
+ schema: sourceManifest.schema,
538
+ webhookUrl: `http://localhost:${process.env.PORT || 8080}/sources/${this.appConfig.manifest.meta?.app_id}/${sourceId}/${guid}`
539
+ };
540
+ // Load SourceLifecycle class using runtime - pass sourceId, runtime looks up entry_point
541
+ // Returns null if no lifecycle handler defined
542
+ const SourceLifecycleClass = await this.runtime.getSourceLifecycleClass(sourceId);
543
+ if (!SourceLifecycleClass) {
544
+ return {
545
+ success: true,
546
+ message: 'No lifecycle handler defined for this source'
547
+ };
548
+ }
549
+ // Instantiate lifecycle handler
550
+ const lifecycle = new SourceLifecycleClass(config);
551
+ // Call appropriate method
552
+ let result;
553
+ switch (action) {
554
+ case 'create':
555
+ result = await lifecycle.onSourceCreate();
556
+ break;
557
+ case 'update':
558
+ result = await lifecycle.onSourceUpdate();
559
+ break;
560
+ case 'delete':
561
+ result = await lifecycle.onSourceDelete();
562
+ break;
563
+ case 'enable':
564
+ result = await lifecycle.onSourceEnable();
565
+ break;
566
+ case 'pause':
567
+ result = await lifecycle.onSourcePause();
568
+ break;
569
+ default:
570
+ throw new Error(`Unknown lifecycle action: ${action}`);
571
+ }
572
+ return result;
573
+ }
574
+ /**
575
+ * Handle source job
576
+ */
577
+ async handleSourceJob(message) {
578
+ const { sourceId, jobId, parameters } = message.data;
579
+ const startTime = Date.now();
580
+ const logs = [];
581
+ try {
582
+ if (!this.appConfig) {
583
+ throw new Error('App configuration not initialized');
584
+ }
585
+ // Load SourceJob class using runtime - pass sourceId and jobId, runtime looks up entry_point
586
+ const SourceJobClass = await this.runtime.getSourceJobClass(sourceId, jobId);
587
+ // Create mocked Source instance
588
+ const mockedSource = {
589
+ emit: async (data) => {
590
+ this.sourceDataStore.push(sourceId, data, 'job');
591
+ logs.push(`Pushed data: ${JSON.stringify(data)}`);
592
+ return { success: true };
593
+ }
594
+ };
595
+ // Create invocation
596
+ const invocation = {
597
+ jobId,
598
+ scheduledAt: new Date(),
599
+ parameters: parameters || {},
600
+ dataSyncId: 'mock-data-sync-id'
601
+ };
602
+ // Instantiate job
603
+ const job = new SourceJobClass(invocation, mockedSource);
604
+ // Execute prepare
605
+ logs.push('Preparing job...');
606
+ let status = await job.prepare(parameters || {});
607
+ logs.push('Job prepared');
608
+ // Execute perform loop
609
+ let iterations = 0;
610
+ const maxIterations = 100;
611
+ while (!status.complete && iterations < maxIterations) {
612
+ logs.push(`Performing iteration ${iterations + 1}...`);
613
+ status = await job.perform(status);
614
+ iterations++;
615
+ }
616
+ if (!status.complete) {
617
+ logs.push(`Warning: Job did not complete after ${maxIterations} iterations`);
618
+ }
619
+ else {
620
+ logs.push('Job completed successfully');
621
+ }
622
+ const executionTime = Date.now() - startTime;
623
+ // Store execution
624
+ this.sourceJobExecutionStore.addExecution(sourceId, {
625
+ jobId,
626
+ timestamp: Date.now(),
627
+ success: true,
628
+ logs,
629
+ executionTime,
630
+ result: status
631
+ });
632
+ return {
633
+ success: true,
634
+ logs,
635
+ executionTime,
636
+ result: status
637
+ };
638
+ }
639
+ catch (error) {
640
+ const executionTime = Date.now() - startTime;
641
+ logs.push(`Error: ${error.message}`);
642
+ // Store failed execution
643
+ this.sourceJobExecutionStore.addExecution(sourceId, {
644
+ jobId,
645
+ timestamp: Date.now(),
646
+ success: false,
647
+ logs,
648
+ executionTime,
649
+ error: error.message
650
+ });
651
+ throw error; // Let the base class handler catch and send the error
652
+ }
653
+ }
654
+ /**
655
+ * Handle source schema
656
+ */
657
+ async handleSourceSchema(message) {
658
+ const { sourceId } = message.data;
659
+ if (!this.appConfig) {
660
+ throw new Error('App configuration not initialized');
661
+ }
662
+ if (!this.runtime) {
663
+ throw new Error('Runtime not initialized');
664
+ }
665
+ const sources = this.appConfig.manifest.sources || {};
666
+ const sourceManifest = sources[sourceId];
667
+ if (!sourceManifest) {
668
+ throw new Error(`Source ${sourceId} not found in manifest`);
669
+ }
670
+ const schema = sourceManifest.schema;
671
+ // Static schema - load from YAML file using Runtime
672
+ if (typeof schema === 'string') {
673
+ this.sendLog('info', `Loading static YAML schema: ${schema}`, this.currentRequestId);
674
+ const allSchemas = this.runtime.getSourceSchema();
675
+ // Runtime returns schemas keyed by file path, e.g., "sources/schema/myschema.yml"
676
+ const schemaKey = `sources/schema/${schema}.yml`;
677
+ const schemaKeyYaml = `sources/schema/${schema}.yaml`;
678
+ const loadedSchema = allSchemas[schemaKey] || allSchemas[schemaKeyYaml];
679
+ if (!loadedSchema) {
680
+ throw new Error(`Schema file not found: ${schema}.yml or .yaml`);
681
+ }
682
+ this.sendLog('info', `Static schema loaded: ${schema}`, this.currentRequestId);
683
+ return loadedSchema;
684
+ }
685
+ // Dynamic schema - call the schema function
686
+ if (typeof schema === 'object' && schema.entry_point) {
687
+ this.sendLog('info', `Loading dynamic schema function for: ${sourceId}`, this.currentRequestId);
688
+ const SchemaFunctionClass = await this.runtime.getSourceSchemaFunctionClass(sourceId);
689
+ const config = {
690
+ sourceKey: sourceId
691
+ };
692
+ const schemaFunction = new SchemaFunctionClass(config);
693
+ const result = await schemaFunction.getSourcesSchema();
694
+ this.sendLog('info', `Dynamic schema loaded for ${sourceId}`, this.currentRequestId);
695
+ return result;
696
+ }
697
+ throw new Error('Invalid schema configuration');
698
+ }
699
+ /**
700
+ * Clean up SDK configuration
701
+ * This only happens when the process is shutting down
702
+ */
703
+ async cleanup() {
704
+ this.sendLog('info', 'Cleaning up unified wrapper');
705
+ if (this.cleanUpLocalSDKs && this.appDir && this.isInitialized) {
706
+ try {
707
+ this.cleanUpLocalSDKs(this.appDir);
708
+ this.sendLog('info', 'SDK cleanup completed');
709
+ this.isInitialized = false;
710
+ }
711
+ catch (error) {
712
+ this.sendLog('warn', `SDK cleanup error: ${error}`);
713
+ }
714
+ }
715
+ }
716
+ }
717
+ exports.LocalEngineUnified = LocalEngineUnified;
718
+ // Only execute if this script is run directly (not imported)
719
+ if (require.main === module) {
720
+ const localEngine = new LocalEngineUnified();
721
+ localEngine.start();
722
+ }
723
+ //# sourceMappingURL=local-engine-unified.js.map