@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,735 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.startServer = startServer;
7
+ const express_1 = __importDefault(require("express"));
8
+ const http_1 = __importDefault(require("http"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const fs_1 = __importDefault(require("fs"));
11
+ const http_proxy_middleware_1 = require("http-proxy-middleware");
12
+ const open_1 = __importDefault(require("open"));
13
+ const os_1 = __importDefault(require("os"));
14
+ // Import our components
15
+ const watcher_1 = require("./executor/watcher");
16
+ const app_discovery_1 = require("./server/app-discovery");
17
+ const api_1 = require("./server/api");
18
+ const config_1 = require("./server/config");
19
+ const LocalConfigStore_1 = require("./local_engine/storage/LocalConfigStore");
20
+ const LocalSettingsStore_1 = require("./local_engine/storage/LocalSettingsStore");
21
+ const LifecycleExecutor_1 = require("./executor/LifecycleExecutor");
22
+ const FunctionExecutor_1 = require("./executor/FunctionExecutor");
23
+ const SourceExecutor_1 = require("./executor/SourceExecutor");
24
+ const LogManager_1 = require("./logging/LogManager");
25
+ /**
26
+ * Wait for the dev server to be fully ready
27
+ */
28
+ async function waitForServerReady(baseUrl) {
29
+ console.log('Waiting for dev server to fully initialize...');
30
+ const maxAttempts = 30; // 30 attempts with 200ms delay = 6 seconds max
31
+ const delayMs = 200;
32
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
33
+ try {
34
+ // Check both health and app endpoints
35
+ const healthUrl = `${baseUrl}/devserver/api/health`;
36
+ const appUrl = `${baseUrl}/devserver/api/app`;
37
+ const [healthResponse, appResponse] = await Promise.all([
38
+ fetch(healthUrl),
39
+ fetch(appUrl)
40
+ ]);
41
+ if (healthResponse.ok && appResponse.ok) {
42
+ const healthData = await healthResponse.json();
43
+ const appData = await appResponse.json();
44
+ // Verify health status and app has valid data
45
+ if (healthData.status === 'ok' && appData.name && appData.name !== 'unknown') {
46
+ console.log(`Dev server is ready! (attempt ${attempt}/${maxAttempts})`);
47
+ return;
48
+ }
49
+ }
50
+ }
51
+ catch (error) {
52
+ // Server not ready yet, continue waiting
53
+ }
54
+ // Wait before next attempt
55
+ await new Promise(resolve => setTimeout(resolve, delayMs));
56
+ }
57
+ console.warn('Dev server may not be fully ready, but proceeding with browser open...');
58
+ }
59
+ async function startServer() {
60
+ // Create Express app
61
+ const app = (0, express_1.default)();
62
+ const server = http_1.default.createServer(app);
63
+ // Parse JSON requests
64
+ app.use(express_1.default.json());
65
+ // Serve static files for dev server
66
+ app.use("/devserver/static", express_1.default.static(path_1.default.join(__dirname, "../public")));
67
+ // Serve static files
68
+ app.use(express_1.default.static(path_1.default.join(__dirname, "../public")));
69
+ // Use the configured app root directory
70
+ const appRootDir = path_1.default.resolve(config_1.config.app.rootDir);
71
+ console.log(`Looking for OCP app in: ${appRootDir}`);
72
+ const ocpApp = await (0, app_discovery_1.discoverApp)(appRootDir);
73
+ if (!ocpApp) {
74
+ console.error(`No OCP app found in ${appRootDir}. Make sure app.yml exists.`);
75
+ process.exit(1);
76
+ }
77
+ console.log(`Found OCP app: ${ocpApp.manifest.meta.display_name} v${ocpApp.manifest.meta.version}`);
78
+ // Set up file watcher
79
+ const watcher = new watcher_1.AppWatcher(appRootDir);
80
+ // Set up config store
81
+ const configStore = new LocalConfigStore_1.LocalConfigStore(appRootDir);
82
+ // Set up settings store
83
+ const settingsStore = LocalSettingsStore_1.LocalSettingsStore.getInstance(appRootDir);
84
+ // Set up lifecycle executor
85
+ const lifecycleExecutor = new LifecycleExecutor_1.LifecycleExecutor(appRootDir, ocpApp, settingsStore, configStore, config_1.config.account, watcher);
86
+ // Set up function executor
87
+ const functionExecutor = new FunctionExecutor_1.FunctionExecutor(appRootDir, ocpApp, settingsStore, configStore, config_1.config.account, watcher);
88
+ // Config endpoint for runtime configuration
89
+ app.get('/devserver/api/config', (req, res) => {
90
+ res.json({
91
+ showZaiusAdminSections: process.env.SHOW_ZAIUS_ADMIN_SECTIONS === 'true'
92
+ });
93
+ });
94
+ // Set up API routes with /devserver prefix
95
+ app.use("/devserver/api", (0, api_1.createApiRoutes)(ocpApp, watcher, configStore));
96
+ // Set up v1 API routes at root level
97
+ const { createV1Routes } = require("./server/api/v1");
98
+ app.use("/v1", createV1Routes(ocpApp, watcher, configStore, lifecycleExecutor, settingsStore));
99
+ // Serve assets from the app directory
100
+ app.get("/assets/overview.md", (req, res) => {
101
+ const overviewPath = path_1.default.join(appRootDir, "assets", "directory", "overview.md");
102
+ // Check if the file exists
103
+ if (fs_1.default.existsSync(overviewPath)) {
104
+ // Set content type for markdown
105
+ res.setHeader("Content-Type", "text/markdown; charset=utf-8");
106
+ // Send the file
107
+ res.sendFile(overviewPath);
108
+ }
109
+ else {
110
+ // Return 404 if file doesn't exist
111
+ res.status(404).json({
112
+ error: {
113
+ message: "Overview file not found",
114
+ code: "FILE_NOT_FOUND",
115
+ },
116
+ });
117
+ }
118
+ });
119
+ app.get("/assets/settings.yml", (req, res) => {
120
+ const settingsPath = path_1.default.join(appRootDir, "forms", "settings.yml");
121
+ // Check if the file exists
122
+ if (fs_1.default.existsSync(settingsPath)) {
123
+ try {
124
+ // Read the file content
125
+ const fileContent = fs_1.default.readFileSync(settingsPath);
126
+ // Set content type for plain text
127
+ res.setHeader("Content-Type", "application/x-yaml");
128
+ // Return just the base64 content
129
+ res.send(fileContent);
130
+ }
131
+ catch (error) {
132
+ res.status(500).json({
133
+ error: {
134
+ message: "Error reading settings file",
135
+ code: "FILE_READ_ERROR",
136
+ },
137
+ });
138
+ }
139
+ }
140
+ else {
141
+ // Return 404 if file doesn't exist
142
+ res.status(404).json({
143
+ error: {
144
+ message: "Settings file not found",
145
+ code: "FILE_NOT_FOUND",
146
+ },
147
+ });
148
+ }
149
+ });
150
+ app.get("/assets/icon.svg", (req, res) => {
151
+ const iconPath = path_1.default.join(appRootDir, "assets", "icon.svg");
152
+ // Check if the file exists
153
+ if (fs_1.default.existsSync(iconPath)) {
154
+ // Set content type for SVG
155
+ res.setHeader("Content-Type", "image/svg+xml");
156
+ // Send the file
157
+ res.sendFile(iconPath);
158
+ }
159
+ else {
160
+ // Return 404 if file doesn't exist
161
+ res.status(404).json({
162
+ error: {
163
+ message: "Icon file not found",
164
+ code: "FILE_NOT_FOUND",
165
+ },
166
+ });
167
+ }
168
+ });
169
+ app.get("/assets/logo.svg", (req, res) => {
170
+ const logoPath = path_1.default.join(appRootDir, "assets", "logo.svg");
171
+ // Check if the file exists
172
+ if (fs_1.default.existsSync(logoPath)) {
173
+ // Set content type for SVG
174
+ res.setHeader("Content-Type", "image/svg+xml");
175
+ // Send the file
176
+ res.sendFile(logoPath);
177
+ }
178
+ else {
179
+ // Return 404 if file doesn't exist
180
+ res.status(404).json({
181
+ error: {
182
+ message: "Logo file not found",
183
+ code: "FILE_NOT_FOUND",
184
+ },
185
+ });
186
+ }
187
+ });
188
+ // Source webhook handler
189
+ async function handleSourceWebhook(req, res, ocpApp, configStore) {
190
+ const { app_id, source_id, guid } = req.params;
191
+ const logger = LogManager_1.LogManager.getInstance();
192
+ try {
193
+ // Validate app_id
194
+ if (app_id !== ocpApp.manifest.meta.app_id) {
195
+ return res.status(404).json({
196
+ error: {
197
+ message: 'Unable to find webhook with given request parameters',
198
+ code: 'APP_NOT_FOUND'
199
+ }
200
+ });
201
+ }
202
+ // Validate source exists
203
+ const sources = ocpApp.manifest.sources || {};
204
+ if (!sources[source_id]) {
205
+ return res.status(404).json({
206
+ error: {
207
+ message: 'Unable to find webhook with given request parameters',
208
+ code: 'SOURCE_NOT_FOUND'
209
+ }
210
+ });
211
+ }
212
+ // Validate GUID
213
+ const storedGuid = configStore.getSourceGuid(source_id);
214
+ if (!storedGuid) {
215
+ // Generate and store GUID on first webhook
216
+ configStore.setSourceGuid(source_id, guid);
217
+ }
218
+ else if (storedGuid !== guid) {
219
+ return res.status(403).json({
220
+ error: {
221
+ message: 'Invalid webhook GUID',
222
+ code: 'INVALID_GUID'
223
+ }
224
+ });
225
+ }
226
+ // Build webhook request
227
+ const sourceExecutor = new SourceExecutor_1.SourceExecutor(ocpApp, configStore);
228
+ const webhookRequest = {
229
+ sourceId: source_id,
230
+ guid: guid,
231
+ method: req.method,
232
+ fullpath: req.url,
233
+ path: req.params[0] || '', // Wildcard path
234
+ params: req.query,
235
+ headers: Object.entries(req.headers),
236
+ body: req.body
237
+ };
238
+ const result = await sourceExecutor.executeSourceWebhook(webhookRequest);
239
+ // Send response
240
+ res.status(result.status);
241
+ // Handle headers - SDK returns headers as an object, not an array
242
+ if (result.headers) {
243
+ if (Array.isArray(result.headers)) {
244
+ // If it's already an array of tuples
245
+ result.headers.forEach(([key, value]) => {
246
+ res.setHeader(key, value);
247
+ });
248
+ }
249
+ else {
250
+ // If it's an object, convert to entries
251
+ Object.entries(result.headers).forEach(([key, value]) => {
252
+ if (value !== undefined) {
253
+ res.setHeader(key, String(value));
254
+ }
255
+ });
256
+ }
257
+ }
258
+ res.send(result.body);
259
+ }
260
+ catch (error) {
261
+ logger.error(LogManager_1.LogSource.System, LogManager_1.LogCategory.Source, 'Source webhook execution failed', {
262
+ id: source_id,
263
+ operation: 'webhook',
264
+ error,
265
+ errorMessage: error.message,
266
+ errorStack: error.stack
267
+ });
268
+ console.error('Source webhook error details:', {
269
+ sourceId: source_id,
270
+ error: error,
271
+ message: error.message,
272
+ stack: error.stack
273
+ });
274
+ res.status(500).json({
275
+ error: {
276
+ message: 'Unexpected error during webhook execution',
277
+ code: 'EXECUTION_ERROR',
278
+ details: error.message || 'Internal server error',
279
+ stack: error.stack
280
+ }
281
+ });
282
+ }
283
+ }
284
+ // Set up production-like function execution routes
285
+ // Format: /functions/<app_id>/<function_id>/<guid> and /functions/<app_id>/<function_id>/<guid>/*
286
+ const handleFunctionExecution = async (req, res) => {
287
+ const { app_id, function_id, guid } = req.params;
288
+ const payload = req.body;
289
+ const logManager = LogManager_1.LogManager.getInstance();
290
+ logManager.info(LogManager_1.LogSource.System, LogManager_1.LogCategory.Function, `Executing function: ${app_id}/${function_id} (${req.method})`, {
291
+ id: function_id,
292
+ method: req.method
293
+ });
294
+ try {
295
+ // Extract path information for InternalRequest
296
+ const remainingPath = req.params[0] || ''; // Everything after GUID
297
+ const fullpath = req.path.replace(/^\/functions/, ''); // Remove /functions prefix
298
+ const path = remainingPath ? `/${remainingPath}` : '/'; // Path for function code
299
+ logManager.debug(LogManager_1.LogSource.System, LogManager_1.LogCategory.Function, `Path handling: originalPath=${req.path}, fullpath=${fullpath}, path=${path}`, {
300
+ id: function_id,
301
+ path
302
+ });
303
+ // Validate app_id matches current app
304
+ if (app_id !== ocpApp.manifest.meta.app_id) {
305
+ return res.status(404).json({
306
+ error: {
307
+ message: 'Unable to find webhook with given request parameters',
308
+ code: 'APP_NOT_FOUND'
309
+ }
310
+ });
311
+ }
312
+ // Validate function exists
313
+ const functions = ocpApp.manifest.functions || {};
314
+ if (!functions[function_id]) {
315
+ return res.status(404).json({
316
+ error: {
317
+ message: 'Unable to find webhook with given request parameters',
318
+ code: 'FUNCTION_NOT_FOUND'
319
+ }
320
+ });
321
+ }
322
+ // Validate app is installed
323
+ if (!configStore.isInstalled()) {
324
+ return res.status(403).json({
325
+ error: {
326
+ message: 'App must be installed to execute functions',
327
+ code: 'APP_NOT_INSTALLED'
328
+ }
329
+ });
330
+ }
331
+ // Validate GUID matches stored GUID for this function
332
+ const expectedGuid = configStore.getFunctionGuid(function_id);
333
+ if (guid !== expectedGuid) {
334
+ return res.status(403).json({
335
+ error: {
336
+ message: 'Invalid function GUID',
337
+ code: 'INVALID_GUID'
338
+ }
339
+ });
340
+ }
341
+ // Prepare function execution request
342
+ const functionRequest = {
343
+ functionId: function_id,
344
+ method: req.method,
345
+ fullpath,
346
+ path,
347
+ params: req.query,
348
+ headers: Object.entries(req.headers),
349
+ body: payload
350
+ };
351
+ // Execute function using FunctionExecutor
352
+ const executionResult = await functionExecutor.executeFunction(functionRequest);
353
+ if (executionResult.success) {
354
+ logManager.info(LogManager_1.LogSource.System, LogManager_1.LogCategory.Function, `Function executed successfully: ${function_id} (${executionResult.executionTime}ms)`, {
355
+ id: function_id,
356
+ executionTime: executionResult.executionTime,
357
+ status: executionResult.status || 200
358
+ });
359
+ // Set response headers if provided
360
+ if (executionResult.headers) {
361
+ for (const [key, value] of executionResult.headers) {
362
+ res.set(key, value);
363
+ }
364
+ }
365
+ // Return successful function execution result
366
+ const status = executionResult.status || 200;
367
+ if (executionResult.body !== null && executionResult.body !== undefined) {
368
+ // Function returned a specific response body
369
+ if (Buffer.isBuffer(executionResult.body) || Array.isArray(executionResult.body)) {
370
+ // Binary response
371
+ res.status(status).send(Buffer.from(executionResult.body));
372
+ }
373
+ else {
374
+ // JSON response
375
+ res.status(status).json(executionResult.body);
376
+ }
377
+ }
378
+ else {
379
+ // No specific body, return execution info
380
+ res.status(status).json({
381
+ result: "Function executed successfully",
382
+ logs: executionResult.logs,
383
+ executionTime: executionResult.executionTime
384
+ });
385
+ }
386
+ }
387
+ else {
388
+ logManager.error(LogManager_1.LogSource.System, LogManager_1.LogCategory.Function, `Function execution failed: ${function_id} - ${executionResult.error?.message}`, {
389
+ id: function_id,
390
+ error: executionResult.error,
391
+ errorMessage: executionResult.error?.message
392
+ });
393
+ // Return standardized error response for function execution failures
394
+ res.status(500).send("Unexpected error during webhook execution");
395
+ }
396
+ }
397
+ catch (error) {
398
+ logManager.error(LogManager_1.LogSource.System, LogManager_1.LogCategory.Function, `Error executing function ${function_id}`, {
399
+ id: function_id,
400
+ error,
401
+ errorMessage: error instanceof Error ? error.message : String(error)
402
+ });
403
+ res.status(500).send("Unexpected error during webhook execution");
404
+ }
405
+ };
406
+ // Global function execution handler (no GUID)
407
+ const handleGlobalFunctionExecution = async (req, res) => {
408
+ const { app_id, function_id } = req.params;
409
+ const payload = req.body;
410
+ const logManager = LogManager_1.LogManager.getInstance();
411
+ logManager.info(LogManager_1.LogSource.System, LogManager_1.LogCategory.Function, `Executing global function: ${app_id}/${function_id} (${req.method})`, {
412
+ id: function_id,
413
+ method: req.method
414
+ });
415
+ try {
416
+ // Extract path information for InternalRequest
417
+ const remainingPath = req.params[0] || ''; // Everything after function_id
418
+ const fullpath = req.path.replace(/^\/functions/, ''); // Remove /functions prefix
419
+ const path = remainingPath ? `/${remainingPath}` : '/'; // Path for function code
420
+ logManager.debug(LogManager_1.LogSource.System, LogManager_1.LogCategory.Function, `Path handling: originalPath=${req.path}, fullpath=${fullpath}, path=${path}`, {
421
+ id: function_id,
422
+ path
423
+ });
424
+ // Validate app_id matches current app
425
+ if (app_id !== ocpApp.manifest.meta.app_id) {
426
+ return res.status(404).json({
427
+ error: {
428
+ message: 'Unable to find webhook with given request parameters',
429
+ code: 'APP_NOT_FOUND'
430
+ }
431
+ });
432
+ }
433
+ // Validate function exists and is global
434
+ const functions = ocpApp.manifest.functions || {};
435
+ if (!functions[function_id]) {
436
+ return res.status(404).json({
437
+ error: {
438
+ message: 'Unable to find webhook with given request parameters',
439
+ code: 'FUNCTION_NOT_FOUND'
440
+ }
441
+ });
442
+ }
443
+ if (!functions[function_id].global) {
444
+ return res.status(403).json({
445
+ error: {
446
+ message: `Function '${function_id}' is not a global function`,
447
+ code: 'NOT_GLOBAL_FUNCTION'
448
+ }
449
+ });
450
+ }
451
+ // Validate app is installed
452
+ if (!configStore.isInstalled()) {
453
+ return res.status(403).json({
454
+ error: {
455
+ message: 'App must be installed to execute functions',
456
+ code: 'APP_NOT_INSTALLED'
457
+ }
458
+ });
459
+ }
460
+ // Prepare function execution request
461
+ const functionRequest = {
462
+ functionId: function_id,
463
+ method: req.method,
464
+ fullpath,
465
+ path,
466
+ params: req.query,
467
+ headers: Object.entries(req.headers),
468
+ body: payload
469
+ };
470
+ // Execute function using FunctionExecutor
471
+ const executionResult = await functionExecutor.executeFunction(functionRequest);
472
+ if (executionResult.success) {
473
+ logManager.info(LogManager_1.LogSource.System, LogManager_1.LogCategory.Function, `Global function executed successfully: ${function_id} (${executionResult.executionTime}ms)`, {
474
+ id: function_id,
475
+ executionTime: executionResult.executionTime,
476
+ status: executionResult.status || 200
477
+ });
478
+ // Set response headers if provided
479
+ if (executionResult.headers) {
480
+ for (const [key, value] of executionResult.headers) {
481
+ res.set(key, value);
482
+ }
483
+ }
484
+ // Return successful function execution result
485
+ const status = executionResult.status || 200;
486
+ if (executionResult.body !== null && executionResult.body !== undefined) {
487
+ // Function returned a specific response body
488
+ if (Buffer.isBuffer(executionResult.body) || Array.isArray(executionResult.body)) {
489
+ // Binary response
490
+ res.status(status).send(Buffer.from(executionResult.body));
491
+ }
492
+ else {
493
+ // JSON response
494
+ res.status(status).json(executionResult.body);
495
+ }
496
+ }
497
+ else {
498
+ // No specific body, return execution info
499
+ res.status(status).json({
500
+ result: "Function executed successfully",
501
+ logs: executionResult.logs,
502
+ executionTime: executionResult.executionTime
503
+ });
504
+ }
505
+ }
506
+ else {
507
+ logManager.error(LogManager_1.LogSource.System, LogManager_1.LogCategory.Function, `Global function execution failed: ${function_id} - ${executionResult.error?.message}`, {
508
+ id: function_id,
509
+ error: executionResult.error,
510
+ errorMessage: executionResult.error?.message
511
+ });
512
+ // Return standardized error response for function execution failures
513
+ res.status(500).send("Unexpected error during webhook execution");
514
+ }
515
+ }
516
+ catch (error) {
517
+ logManager.error(LogManager_1.LogSource.System, LogManager_1.LogCategory.Function, `Error executing global function ${function_id}`, {
518
+ id: function_id,
519
+ error,
520
+ errorMessage: error instanceof Error ? error.message : String(error)
521
+ });
522
+ res.status(500).send("Unexpected error during webhook execution");
523
+ }
524
+ };
525
+ // Register function routes for all HTTP methods
526
+ app.get("/functions/:app_id/:function_id/:guid", handleFunctionExecution);
527
+ app.post("/functions/:app_id/:function_id/:guid", handleFunctionExecution);
528
+ app.put("/functions/:app_id/:function_id/:guid", handleFunctionExecution);
529
+ app.delete("/functions/:app_id/:function_id/:guid", handleFunctionExecution);
530
+ app.patch("/functions/:app_id/:function_id/:guid", handleFunctionExecution);
531
+ app.get("/functions/:app_id/:function_id/:guid/*", handleFunctionExecution);
532
+ app.post("/functions/:app_id/:function_id/:guid/*", handleFunctionExecution);
533
+ app.put("/functions/:app_id/:function_id/:guid/*", handleFunctionExecution);
534
+ app.delete("/functions/:app_id/:function_id/:guid/*", handleFunctionExecution);
535
+ app.patch("/functions/:app_id/:function_id/:guid/*", handleFunctionExecution);
536
+ // Register source webhook routes for all HTTP methods
537
+ app.get("/sources/:app_id/:source_id/:guid", (req, res) => handleSourceWebhook(req, res, ocpApp, configStore));
538
+ app.post("/sources/:app_id/:source_id/:guid", (req, res) => handleSourceWebhook(req, res, ocpApp, configStore));
539
+ app.put("/sources/:app_id/:source_id/:guid", (req, res) => handleSourceWebhook(req, res, ocpApp, configStore));
540
+ app.delete("/sources/:app_id/:source_id/:guid", (req, res) => handleSourceWebhook(req, res, ocpApp, configStore));
541
+ app.patch("/sources/:app_id/:source_id/:guid", (req, res) => handleSourceWebhook(req, res, ocpApp, configStore));
542
+ app.get("/sources/:app_id/:source_id/:guid/*", (req, res) => handleSourceWebhook(req, res, ocpApp, configStore));
543
+ app.post("/sources/:app_id/:source_id/:guid/*", (req, res) => handleSourceWebhook(req, res, ocpApp, configStore));
544
+ app.put("/sources/:app_id/:source_id/:guid/*", (req, res) => handleSourceWebhook(req, res, ocpApp, configStore));
545
+ app.delete("/sources/:app_id/:source_id/:guid/*", (req, res) => handleSourceWebhook(req, res, ocpApp, configStore));
546
+ app.patch("/sources/:app_id/:source_id/:guid/*", (req, res) => handleSourceWebhook(req, res, ocpApp, configStore));
547
+ // Register global function routes (no GUID) for all HTTP methods
548
+ app.get("/functions/:app_id/:function_id", handleGlobalFunctionExecution);
549
+ app.post("/functions/:app_id/:function_id", handleGlobalFunctionExecution);
550
+ app.put("/functions/:app_id/:function_id", handleGlobalFunctionExecution);
551
+ app.delete("/functions/:app_id/:function_id", handleGlobalFunctionExecution);
552
+ app.patch("/functions/:app_id/:function_id", handleGlobalFunctionExecution);
553
+ app.get("/functions/:app_id/:function_id/*", handleGlobalFunctionExecution);
554
+ app.post("/functions/:app_id/:function_id/*", handleGlobalFunctionExecution);
555
+ app.put("/functions/:app_id/:function_id/*", handleGlobalFunctionExecution);
556
+ app.delete("/functions/:app_id/:function_id/*", handleGlobalFunctionExecution);
557
+ app.patch("/functions/:app_id/:function_id/*", handleGlobalFunctionExecution);
558
+ // Middleware to modify JavaScript responses containing IFRAME_PARENT_ORIGIN
559
+ app.use(async (req, res, next) => {
560
+ // Skip proxy for /devserver routes, /v1 API routes, /assets routes, /functions routes, /sources routes, and client-side routes
561
+ if (req.path.startsWith("/devserver") ||
562
+ req.path.startsWith("/v1") ||
563
+ req.path.startsWith("/assets") ||
564
+ req.path.startsWith("/functions") ||
565
+ req.path.startsWith("/sources") ||
566
+ req.path === "/" ||
567
+ req.path.startsWith("/settings") ||
568
+ req.path.startsWith("/jobs") ||
569
+ req.path.startsWith("/destinations")) {
570
+ return next();
571
+ }
572
+ // For JavaScript files, we need to potentially modify the content
573
+ const isJSRequest = req.path.endsWith(".js") ||
574
+ req.headers.accept?.includes("javascript") ||
575
+ req.get("content-type")?.includes("javascript");
576
+ if (isJSRequest) {
577
+ try {
578
+ // Fetch from the target directly
579
+ const targetUrl = `https://directory.zaius.com${req.path}${req.url.includes("?") ? req.url.substring(req.url.indexOf("?")) : ""}`;
580
+ const response = await fetch(targetUrl, {
581
+ method: req.method,
582
+ headers: {
583
+ ...req.headers,
584
+ host: "directory.zaius.com",
585
+ },
586
+ });
587
+ if (response.ok) {
588
+ const content = await response.text();
589
+ const host = req.get("host") || `${config_1.config.server.host}:${config_1.config.server.port}`;
590
+ const protocol = req.secure ? "https" : "http";
591
+ // Replace the IFRAME_PARENT_ORIGIN logic with our local origin
592
+ let modifiedContent = content.replace(/targetOrigin:[a-zA-Z0-9]*,/g, `targetOrigin:'http://${config_1.config.server.host}:${config_1.config.server.port}',`);
593
+ modifiedContent = modifiedContent.replace(/e\.host=\["api"\]\.concat\(t\)\.join\("\."\)/g, `e.host='${config_1.config.server.host}:${config_1.config.server.port}'`);
594
+ console.log(content.match(/e\.host=.{0,40}/g));
595
+ console.log(modifiedContent.match(/e\.host=.{0,40}/g));
596
+ // Set response headers
597
+ response.headers.forEach((value, key) => {
598
+ if (key !== "content-length" && key !== "content-encoding") {
599
+ res.set(key, value);
600
+ }
601
+ });
602
+ res.send(modifiedContent);
603
+ return;
604
+ }
605
+ }
606
+ catch (error) {
607
+ console.error("Error fetching JS file:", error);
608
+ }
609
+ }
610
+ // For all other requests, use the normal proxy
611
+ (0, http_proxy_middleware_1.createProxyMiddleware)({
612
+ target: "https://directory.zaius.com",
613
+ changeOrigin: true,
614
+ secure: true,
615
+ })(req, res, next);
616
+ });
617
+ // Serve the React app for client-side routing (must be last to not interfere with API routes)
618
+ // This catches all routes that aren't handled by previous middleware/routes
619
+ app.get("*", (req, res) => {
620
+ // Only serve index.html for non-API routes
621
+ // API routes are already handled above: /devserver/api/*, /v1/*, /functions/*, /sources/*, /app/*, /assets/*
622
+ res.sendFile(path_1.default.resolve(__dirname, "../public/index.html"));
623
+ });
624
+ // Start the file watcher first
625
+ watcher.start();
626
+ // Trigger initial build asynchronously (non-blocking)
627
+ const logger = LogManager_1.LogManager.getInstance();
628
+ logger.logBuildEvent('started');
629
+ watcher.triggerBuild().catch(error => {
630
+ logger.logBuildEvent('error', {
631
+ error: error instanceof Error ? error : new Error(String(error)),
632
+ errorMessage: 'Initial build failed, check your app code'
633
+ });
634
+ // Don't exit - let user fix code and watcher will rebuild automatically
635
+ });
636
+ // Set up server error handling before attempting to listen
637
+ server.on('error', (error) => {
638
+ if (error.code === 'EADDRINUSE') {
639
+ console.error('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
640
+ console.error(`Port ${config_1.config.server.port} is already in use.`);
641
+ console.error('');
642
+ console.error('To fix this issue, you can:');
643
+ console.error(` 1. Stop the process using port ${config_1.config.server.port}`);
644
+ console.error(` 2. Use a different port: ocp-local-env --port <port>`);
645
+ console.error(` 3. Set OCP_LOCAL_PORT environment variable`);
646
+ console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
647
+ }
648
+ else {
649
+ // For other server errors, display error message
650
+ console.error('\nFailed to start server:', error.message);
651
+ }
652
+ // Clean up resources before exit
653
+ watcher.stop();
654
+ process.exit(1);
655
+ });
656
+ // Start the server
657
+ const port = config_1.config.server.port;
658
+ server.listen(port, async () => {
659
+ const url = `http://localhost:${port}`;
660
+ console.log(`OCP Local Testing Tool running at ${url}`);
661
+ // Auto-open browser unless disabled, and only once per session
662
+ const shouldOpenBrowser = process.env.OCP_LOCAL_OPEN_BROWSER !== "false";
663
+ if (shouldOpenBrowser) {
664
+ // Use a temporary flag file to ensure browser opens only once per session
665
+ const flagFile = path_1.default.join(os_1.default.tmpdir(), `ocp-local-env-browser-opened-${port}`);
666
+ if (!fs_1.default.existsSync(flagFile)) {
667
+ try {
668
+ // Wait for the dev server to be ready before opening browser
669
+ console.log('Waiting for dev server to be ready...');
670
+ await waitForServerReady(url);
671
+ // Create flag file to prevent multiple opens
672
+ fs_1.default.writeFileSync(flagFile, 'opened');
673
+ console.log('Opening browser...');
674
+ await (0, open_1.default)(url);
675
+ // Clean up flag file on process exit
676
+ process.on('exit', () => {
677
+ try {
678
+ if (fs_1.default.existsSync(flagFile)) {
679
+ fs_1.default.unlinkSync(flagFile);
680
+ }
681
+ }
682
+ catch (e) {
683
+ // Ignore cleanup errors
684
+ }
685
+ });
686
+ }
687
+ catch (error) {
688
+ console.warn('Failed to open browser automatically:', error instanceof Error ? error.message : String(error));
689
+ console.log(`Please open your browser manually and go to: ${url}`);
690
+ }
691
+ }
692
+ }
693
+ else {
694
+ console.log(`Open your browser and go to: ${url}`);
695
+ }
696
+ });
697
+ // Handle shutdown
698
+ const shutdown = async () => {
699
+ console.log("Shutting down...");
700
+ // Stop watcher
701
+ watcher.stop();
702
+ // Cleanup IPC connections
703
+ try {
704
+ await lifecycleExecutor.cleanup();
705
+ await functionExecutor.cleanup();
706
+ console.log("IPC connections cleaned up");
707
+ }
708
+ catch (e) {
709
+ console.warn("Error during IPC cleanup:", e);
710
+ }
711
+ // Close server
712
+ server.close();
713
+ // Clean up browser flag file
714
+ try {
715
+ const flagFile = path_1.default.join(os_1.default.tmpdir(), `ocp-local-env-browser-opened-${port}`);
716
+ if (fs_1.default.existsSync(flagFile)) {
717
+ fs_1.default.unlinkSync(flagFile);
718
+ }
719
+ }
720
+ catch (e) {
721
+ // Ignore cleanup errors
722
+ }
723
+ process.exit(0);
724
+ };
725
+ process.on("SIGINT", shutdown);
726
+ process.on("SIGTERM", shutdown);
727
+ }
728
+ // Start the server when this file is executed directly
729
+ if (require.main === module) {
730
+ startServer().catch((error) => {
731
+ console.error('Failed to start server:', error);
732
+ process.exit(1);
733
+ });
734
+ }
735
+ //# sourceMappingURL=server.js.map