@edenapp/sdk 0.6.2 → 0.6.4

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 (100) hide show
  1. package/dist/app-frame/frame-injector.js +6 -6
  2. package/dist/app-frame/frame-injector.js.map +3 -3
  3. package/dist/app-runtime/app-preload.js +2 -2
  4. package/dist/app-runtime/app-preload.js.map +3 -3
  5. package/dist/app-runtime/backend-preload.js +3 -3
  6. package/dist/app-runtime/backend-preload.js.map +3 -3
  7. package/dist/apps/prebuilt/com.eden.calculator/CHANGELOG.md +12 -0
  8. package/dist/apps/prebuilt/com.eden.calculator/package.json +1 -1
  9. package/dist/apps/prebuilt/com.eden.context-menu/dist/assets/{index-PflHQ4jS.css → index-B3l0_BgM.css} +1 -1
  10. package/dist/apps/prebuilt/com.eden.context-menu/dist/assets/index-CQD24gQV.js +1 -0
  11. package/dist/apps/prebuilt/com.eden.context-menu/dist/index.html +2 -2
  12. package/dist/apps/prebuilt/com.eden.context-menu/manifest.json +1 -1
  13. package/dist/apps/prebuilt/com.eden.eveshell/dist/assets/index-bsf9U6_1.js +1 -0
  14. package/dist/apps/prebuilt/com.eden.eveshell/dist/index.html +1 -1
  15. package/dist/apps/prebuilt/com.eden.example.hello/backend/node_modules/@edenapp/types/CHANGELOG.md +8 -0
  16. package/dist/apps/prebuilt/com.eden.example.hello/backend/node_modules/@edenapp/types/ContextMenu.d.ts +7 -1
  17. package/dist/apps/prebuilt/com.eden.example.hello/backend/node_modules/@edenapp/types/commands.generated.d.ts +8 -1
  18. package/dist/apps/prebuilt/com.eden.example.hello/backend/node_modules/@edenapp/types/events.generated.d.ts +1 -1
  19. package/dist/apps/prebuilt/com.eden.example.hello/backend/node_modules/@edenapp/types/index.d.ts +5 -1
  20. package/dist/apps/prebuilt/com.eden.example.hello/backend/node_modules/@edenapp/types/ipc/appbus.d.ts +2 -12
  21. package/dist/apps/prebuilt/com.eden.example.hello/backend/node_modules/@edenapp/types/package.json +1 -1
  22. package/dist/apps/prebuilt/com.eden.example.hello/frontend/node_modules/@edenapp/types/CHANGELOG.md +8 -0
  23. package/dist/apps/prebuilt/com.eden.example.hello/frontend/node_modules/@edenapp/types/ContextMenu.d.ts +7 -1
  24. package/dist/apps/prebuilt/com.eden.example.hello/frontend/node_modules/@edenapp/types/commands.generated.d.ts +8 -1
  25. package/dist/apps/prebuilt/com.eden.example.hello/frontend/node_modules/@edenapp/types/events.generated.d.ts +1 -1
  26. package/dist/apps/prebuilt/com.eden.example.hello/frontend/node_modules/@edenapp/types/index.d.ts +5 -1
  27. package/dist/apps/prebuilt/com.eden.example.hello/frontend/node_modules/@edenapp/types/ipc/appbus.d.ts +2 -12
  28. package/dist/apps/prebuilt/com.eden.example.hello/frontend/node_modules/@edenapp/types/package.json +1 -1
  29. package/dist/apps/prebuilt/com.eden.files/CHANGELOG.md +17 -0
  30. package/dist/apps/prebuilt/com.eden.files/dist/assets/index-bw-C9AMI.js +1 -0
  31. package/dist/apps/prebuilt/com.eden.files/dist/index.html +1 -1
  32. package/dist/apps/prebuilt/com.eden.files/package.json +1 -1
  33. package/dist/apps/prebuilt/com.eden.login/CHANGELOG.md +12 -0
  34. package/dist/apps/prebuilt/com.eden.login/package.json +1 -1
  35. package/dist/apps/prebuilt/com.eden.process-manager/CHANGELOG.md +12 -0
  36. package/dist/apps/prebuilt/com.eden.process-manager/package.json +1 -1
  37. package/dist/filesystem/FilesystemHandler.d.ts +8 -0
  38. package/dist/filesystem/FilesystemHandler.d.ts.map +1 -1
  39. package/dist/filesystem/FilesystemHandler.js +13 -0
  40. package/dist/filesystem/FilesystemHandler.js.map +1 -1
  41. package/dist/filesystem/FilesystemHandler.test.d.ts +2 -0
  42. package/dist/filesystem/FilesystemHandler.test.d.ts.map +1 -0
  43. package/dist/filesystem/FilesystemHandler.test.js +22 -0
  44. package/dist/filesystem/FilesystemHandler.test.js.map +1 -0
  45. package/dist/generated/runtime.d.ts.map +1 -1
  46. package/dist/generated/runtime.js +1 -0
  47. package/dist/generated/runtime.js.map +1 -1
  48. package/dist/i18n/I18nHandler.d.ts +2 -1
  49. package/dist/i18n/I18nHandler.d.ts.map +1 -1
  50. package/dist/i18n/I18nHandler.js.map +1 -1
  51. package/dist/i18n/I18nManager.d.ts +3 -1
  52. package/dist/i18n/I18nManager.d.ts.map +1 -1
  53. package/dist/i18n/I18nManager.js.map +1 -1
  54. package/dist/ipc/CommandDecorators.d.ts +2 -4
  55. package/dist/ipc/CommandDecorators.d.ts.map +1 -1
  56. package/dist/ipc/CommandDecorators.js +1 -1
  57. package/dist/ipc/CommandDecorators.js.map +1 -1
  58. package/dist/ipc/CommandMetadata.d.ts +7 -3
  59. package/dist/ipc/CommandMetadata.d.ts.map +1 -1
  60. package/dist/ipc/CommandMetadata.js.map +1 -1
  61. package/dist/ipc/CommandRegistry.d.ts +8 -5
  62. package/dist/ipc/CommandRegistry.d.ts.map +1 -1
  63. package/dist/ipc/CommandRegistry.js +3 -2
  64. package/dist/ipc/CommandRegistry.js.map +1 -1
  65. package/dist/ipc/CommandRegistry.test.js.map +1 -1
  66. package/dist/ipc/EdenEmitter.d.ts.map +1 -1
  67. package/dist/ipc/EdenEmitter.js.map +1 -1
  68. package/dist/ipc/EdenEmitter.test.js.map +1 -1
  69. package/dist/ipc/EventHandler.js.map +1 -1
  70. package/dist/ipc/EventSubscriberManager.d.ts +2 -2
  71. package/dist/ipc/EventSubscriberManager.d.ts.map +1 -1
  72. package/dist/ipc/EventSubscriberManager.js.map +1 -1
  73. package/dist/ipc/EventSubscriberManager.test.js +70 -45
  74. package/dist/ipc/EventSubscriberManager.test.js.map +1 -1
  75. package/dist/ipc/IPCBridge.d.ts +1 -0
  76. package/dist/ipc/IPCBridge.d.ts.map +1 -1
  77. package/dist/ipc/IPCBridge.js +22 -7
  78. package/dist/ipc/IPCBridge.js.map +1 -1
  79. package/dist/logging/electron.d.ts.map +1 -1
  80. package/dist/logging/electron.js +8 -7
  81. package/dist/logging/electron.js.map +1 -1
  82. package/dist/logging/logger.d.ts.map +1 -1
  83. package/dist/logging/logger.js +9 -7
  84. package/dist/logging/logger.js.map +1 -1
  85. package/dist/process-manager/BackendManager.d.ts +3 -2
  86. package/dist/process-manager/BackendManager.d.ts.map +1 -1
  87. package/dist/process-manager/BackendManager.js +18 -5
  88. package/dist/process-manager/BackendManager.js.map +1 -1
  89. package/dist/process-manager/ProcessManager.d.ts +1 -1
  90. package/dist/process-manager/ProcessManager.d.ts.map +1 -1
  91. package/dist/process-manager/ProcessManager.js.map +1 -1
  92. package/dist/process-manager/ProcessMetricsCollector.test.js +26 -18
  93. package/dist/process-manager/ProcessMetricsCollector.test.js.map +1 -1
  94. package/dist/view-manager/ViewManager.d.ts +2 -2
  95. package/dist/view-manager/ViewManager.d.ts.map +1 -1
  96. package/dist/view-manager/ViewManager.js.map +1 -1
  97. package/package.json +4 -4
  98. package/dist/apps/prebuilt/com.eden.context-menu/dist/assets/index-B-ks_-b3.js +0 -1
  99. package/dist/apps/prebuilt/com.eden.eveshell/dist/assets/index-B-bahmO2.js +0 -1
  100. package/dist/apps/prebuilt/com.eden.files/dist/assets/index-BT-jTYkQ.js +0 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/app-runtime/app-preload.ts", "../../src/logging/levels.ts", "../../src/logging/logger.ts", "../../src/app-runtime/common/ipc-port.ts", "../../src/app-runtime/common/port-channel.ts", "../../src/app-runtime/common/api-factory.ts"],
4
- "sourcesContent": ["import type { AppBusConnection } from \"@edenapp/types/ipc/appbus\";\nimport { contextBridge, ipcRenderer } from \"electron\";\nimport { log, setLogContext } from \"../logging\";\nimport {\n createAppBusAPI,\n createEdenAPI,\n type ShellTransport,\n} from \"./common/api-factory\";\nimport {\n createAppBusState,\n createMessageIdGenerator,\n createPortConnection,\n handleAppBusPort,\n handlePortClosed,\n type PendingRequest,\n wrapDOMPort,\n} from \"./common/port-channel\";\n\n// Per-app state\nlet appId: string | null = null;\n\n// MessagePort for direct frontend<->backend communication\nlet backendPort: MessagePort | null = null;\nlet backendConnection: AppBusConnection | null = null;\n\n// Pending requests waiting for responses (for backend communication)\nconst pendingBackendRequests: Map<string, PendingRequest> = new Map();\n\n// Message ID generator for backend communication\nconst generateBackendMessageId = createMessageIdGenerator(\"backend\");\n\n// Event subscription system\nconst eventSubscriptions: Map<string, Set<Function>> = new Map();\n\n// Extract appId from process arguments\n// Arguments are passed as --app-id=com.example.app\nconst appIdArg = process.argv.find((arg) => arg.startsWith(\"--app-id=\"));\nif (appIdArg) {\n appId = appIdArg.split(\"=\")[1];\n setLogContext({ appId });\n log.info(`Initialized for app: ${appId}`);\n} else {\n log.warn(\"No app ID found in arguments\");\n}\n\n// Extract launch args\nlet launchArgs: string[] = [];\nconst launchArgsArg = process.argv.find((arg) =>\n arg.startsWith(\"--launch-args=\"),\n);\nif (launchArgsArg) {\n try {\n const jsonStr = launchArgsArg.split(\"=\").slice(1).join(\"=\");\n launchArgs = JSON.parse(jsonStr);\n } catch (e) {\n log.error(\"Failed to parse launch args:\", e);\n }\n}\n\n// Handle receiving the backend MessagePort\nipcRenderer.on(\"backend-port\", (event: any) => {\n const [port] = event.ports as MessagePort[];\n if (!port) {\n log.error(\"Received backend-port event without port\");\n return;\n }\n\n backendPort = port;\n log.info(`Backend port received for app ${appId}`);\n\n // Wrap DOM MessagePort to IPCPort interface\n const wrappedPort = wrapDOMPort(port);\n\n // Create connection object - handles all message routing internally\n backendConnection = createPortConnection(\n wrappedPort,\n \"__backend__\",\n new Map([[\"__backend__\", wrappedPort]]), // Dummy map since we won't close this\n pendingBackendRequests,\n generateBackendMessageId,\n );\n});\n\n// Set up unified message listener for shell-message channel\nipcRenderer.on(\"shell-message\", (_event: any, message: any) => {\n const { type, payload } = message;\n const callbacks = eventSubscriptions.get(type);\n\n if (callbacks) {\n callbacks.forEach((callback) => {\n try {\n callback(payload);\n } catch (err) {\n log.error(`Error in event listener for ${type}:`, err);\n }\n });\n }\n});\n\n// Expose safe API to the app\ncontextBridge.exposeInMainWorld(\"getAppAPI\", () => {\n if (!backendConnection) {\n throw new Error(\n \"AppAPI not available: Backend not connected. \" +\n \"This could mean the app has no backend, or the connection is not yet established.\",\n );\n }\n return backendConnection;\n});\n\n// ===================================================================\n// Shared API Implementation\n// ===================================================================\n\n// Shell transport implementation using ipcRenderer\nconst shellTransport: ShellTransport = {\n exec: (command: string, args: any) => {\n return ipcRenderer.invoke(\"shell-command\", command, args);\n },\n};\n\n// Expose edenAPI for shell commands and event subscriptions\nconst edenAPI = createEdenAPI(shellTransport, eventSubscriptions, {\n getLaunchArgs: () => launchArgs,\n});\n\ncontextBridge.exposeInMainWorld(\"edenAPI\", edenAPI);\n\n// ===================================================================\n// AppBus - App-to-App Communication System\n// ===================================================================\n\nconst appBusState = createAppBusState(\"appbus\");\n\n// Handle incoming MessagePorts for peer-to-peer channels\nipcRenderer.on(\"appbus-port\", (event: any, data: any) => {\n const [port] = event.ports as MessagePort[];\n if (!port) {\n log.error(\"Received appbus-port event without port\");\n return;\n }\n\n // Wrap DOM MessagePort to IPCPort interface\n const wrappedPort = wrapDOMPort(port);\n\n handleAppBusPort(wrappedPort, data, appBusState);\n});\n\n// Handle port closed notification\nipcRenderer.on(\n \"appbus-port-closed\",\n (_event: any, data: { connectionId: string }) => {\n handlePortClosed(appBusState, data.connectionId);\n },\n);\n\n// Expose appBus API for app-to-app communication\ncontextBridge.exposeInMainWorld(\n \"appBus\",\n createAppBusAPI({ transport: shellTransport }, appBusState),\n);\n\n// ===================================================================\n// Universal Zoom Prevention\n// ===================================================================\n// Disable default browser zoom behavior for all apps\n// This runs when the DOM is ready for all apps, regardless of app-frame usage\n\nconst setupZoomPrevention = () => {\n // Block Ctrl/Cmd + Plus/Minus/Equals for keyboard zoom\n document.addEventListener(\n \"keydown\",\n (e: KeyboardEvent) => {\n if (\n (e.ctrlKey || e.metaKey) &&\n (e.key === \"+\" || e.key === \"-\" || e.key === \"=\" || e.key === \"0\")\n ) {\n e.preventDefault();\n }\n },\n { capture: true },\n );\n\n // Block Ctrl/Cmd + Mouse wheel for zoom\n document.addEventListener(\n \"wheel\",\n (e: WheelEvent) => {\n if (e.ctrlKey || e.metaKey) {\n e.preventDefault();\n }\n },\n { passive: false, capture: true },\n );\n\n log.info(\"Zoom prevention enabled\");\n};\n\n// Setup when DOM is ready\nif (document.readyState === \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", setupZoomPrevention);\n} else {\n setupZoomPrevention();\n}\n\nlog.info(\"Universal app preload loaded\");\n", "export type LogLevel = \"trace\" | \"debug\" | \"info\" | \"warn\" | \"error\" | \"fatal\";\n\nexport const LOG_LEVEL_ORDER: Record<LogLevel, number> = {\n trace: 10,\n debug: 20,\n info: 30,\n warn: 40,\n error: 50,\n fatal: 60,\n};\n\nexport function parseLogLevel(value?: string | null): LogLevel | null {\n if (!value) return null;\n const normalized = value.trim().toLowerCase();\n if (normalized in LOG_LEVEL_ORDER) {\n return normalized as LogLevel;\n }\n return null;\n}\n\nexport function isLogLevelEnabled(\n level: LogLevel,\n minLevel: LogLevel,\n): boolean {\n return LOG_LEVEL_ORDER[level] >= LOG_LEVEL_ORDER[minLevel];\n}\n", "import type { LogLevel } from \"./levels\";\nimport { isLogLevelEnabled, parseLogLevel } from \"./levels\";\n\nexport type LogFormat = \"pretty\" | \"raw\";\nexport type LogPathMode = \"short\" | \"full\" | \"file\";\n\nexport interface LogContext {\n appId?: string;\n viewId?: number;\n webContentsId?: number;\n processType?: string;\n source?: string;\n}\n\nexport interface CallsiteInfo {\n file: string;\n line: number;\n column?: number;\n}\n\nexport interface LoggerConfig {\n minLevel: LogLevel;\n format: LogFormat;\n includeTimestamp: boolean;\n includeCallsite: boolean;\n pathMode: LogPathMode;\n}\n\nexport interface Logger {\n trace: (...args: unknown[]) => void;\n debug: (...args: unknown[]) => void;\n info: (...args: unknown[]) => void;\n warn: (...args: unknown[]) => void;\n error: (...args: unknown[]) => void;\n fatal: (...args: unknown[]) => void;\n}\n\ninterface LogRecord {\n level: LogLevel;\n args: unknown[];\n context?: LogContext;\n callsite?: CallsiteInfo;\n timestamp?: number;\n skipCallsite?: boolean;\n}\n\nlet globalContext: LogContext = {};\n\nlet config: LoggerConfig = resolveDefaultConfig();\nconst baseConsole = {\n debug: console.debug.bind(console),\n warn: console.warn.bind(console),\n error: console.error.bind(console),\n info: console.log.bind(console),\n};\n\nexport function configureLogger(next: Partial<LoggerConfig>): void {\n config = { ...config, ...next };\n}\n\nexport function getLoggerConfig(): LoggerConfig {\n return config;\n}\n\nexport function setLogContext(next: Partial<LogContext>): void {\n globalContext = { ...globalContext, ...next };\n}\n\nexport function createLogger(context?: LogContext): Logger {\n return {\n trace: (...args) => emit({ level: \"trace\", args, context }),\n debug: (...args) => emit({ level: \"debug\", args, context }),\n info: (...args) => emit({ level: \"info\", args, context }),\n warn: (...args) => emit({ level: \"warn\", args, context }),\n error: (...args) => emit({ level: \"error\", args, context }),\n fatal: (...args) => emit({ level: \"fatal\", args, context }),\n };\n}\n\nexport const log: Logger = createLogger();\n\nexport function logExternal(record: {\n level: LogLevel;\n message: string;\n context?: LogContext;\n callsite?: CallsiteInfo;\n}): void {\n emit({\n level: record.level,\n args: [record.message],\n context: record.context,\n callsite: record.callsite,\n skipCallsite: true,\n });\n}\n\nexport function logFromConsole(record: {\n level: LogLevel;\n args: unknown[];\n context?: LogContext;\n callsite?: CallsiteInfo;\n}): void {\n emit({\n level: record.level,\n args: record.args,\n context: record.context,\n callsite: record.callsite,\n skipCallsite: true,\n });\n}\n\nfunction emit(record: LogRecord): void {\n const { level } = record;\n if (!isLogLevelEnabled(level, config.minLevel)) return;\n\n const timestamp = record.timestamp ?? Date.now();\n const context = mergeContext(record.context);\n const callsite =\n record.callsite ??\n (config.includeCallsite && !record.skipCallsite\n ? captureCallsite()\n : undefined);\n\n const prefix =\n config.format === \"pretty\"\n ? formatPrefix({ level, timestamp, context, callsite })\n : \"\";\n\n const target = consoleForLevel(level);\n if (prefix) {\n target(prefix, ...record.args);\n } else {\n target(...record.args);\n }\n}\n\nfunction mergeContext(context?: LogContext): LogContext {\n const base = getBaseContext();\n return { ...base, ...context };\n}\n\nfunction getBaseContext(): LogContext {\n const envAppId = getEnvValue(\"EDEN_APP_ID\");\n const globalAppId = (globalThis as any).__EDEN_APP_ID__ as string | undefined;\n return {\n processType: detectProcessType(),\n appId: globalContext.appId ?? envAppId ?? globalAppId,\n viewId: globalContext.viewId,\n webContentsId: globalContext.webContentsId,\n source: globalContext.source,\n };\n}\n\nfunction detectProcessType(): string {\n const processObj = (globalThis as any).process as\n | { type?: string; env?: Record<string, string>; cwd?: () => string }\n | undefined;\n if (processObj) {\n const type = processObj.type;\n if (type === \"browser\") return \"main\";\n if (type === \"utility\") return \"backend\";\n if (type) return type;\n }\n if (typeof (globalThis as any).window !== \"undefined\") return \"renderer\";\n return \"node\";\n}\n\nfunction resolveDefaultConfig(): LoggerConfig {\n const envLevel = parseLogLevel(getEnvValue(\"EDEN_LOG_LEVEL\"));\n const envFormat = getEnvValue(\"EDEN_LOG_FORMAT\") as LogFormat | undefined;\n const envPathMode = getEnvValue(\"EDEN_LOG_PATH\") as LogPathMode | undefined;\n const isTest = getEnvValue(\"NODE_ENV\") === \"test\";\n const isRenderer = detectProcessType() === \"renderer\";\n\n return {\n minLevel: envLevel ?? \"debug\",\n format: envFormat ?? (isTest || isRenderer ? \"raw\" : \"pretty\"),\n includeTimestamp: getEnvBool(\"EDEN_LOG_TIMESTAMP\", !isTest),\n includeCallsite: getEnvBool(\"EDEN_LOG_CALLSITE\", !isTest && !isRenderer),\n pathMode: envPathMode ?? \"short\",\n };\n}\n\nfunction consoleForLevel(level: LogLevel): (...args: unknown[]) => void {\n const useLiveConsole = getEnvValue(\"NODE_ENV\") === \"test\";\n switch (level) {\n case \"trace\":\n case \"debug\":\n return useLiveConsole ? console.debug.bind(console) : baseConsole.debug;\n case \"warn\":\n return useLiveConsole ? console.warn.bind(console) : baseConsole.warn;\n case \"error\":\n case \"fatal\":\n return useLiveConsole ? console.error.bind(console) : baseConsole.error;\n case \"info\":\n default:\n return useLiveConsole ? console.log.bind(console) : baseConsole.info;\n }\n}\n\nfunction formatPrefix(record: {\n level: LogLevel;\n timestamp: number;\n context?: LogContext;\n callsite?: CallsiteInfo;\n}): string {\n const parts: string[] = [];\n\n if (config.includeTimestamp) {\n parts.push(new Date(record.timestamp).toISOString());\n }\n\n parts.push(record.level.toUpperCase());\n\n if (record.context?.processType) {\n parts.push(record.context.processType);\n }\n if (record.context?.appId) {\n parts.push(`app=${record.context.appId}`);\n }\n if (record.context?.viewId !== undefined) {\n parts.push(`view=${record.context.viewId}`);\n }\n if (record.context?.webContentsId !== undefined) {\n parts.push(`wc=${record.context.webContentsId}`);\n }\n if (record.context?.source) {\n parts.push(record.context.source);\n }\n if (record.callsite) {\n const file = shortenPath(record.callsite.file, config.pathMode);\n parts.push(`${file}:${record.callsite.line}`);\n }\n\n return `[${parts.join(\"] [\")}]`;\n}\n\nfunction captureCallsite(): CallsiteInfo | undefined {\n const err = new Error();\n (Error as any).captureStackTrace?.(err, captureCallsite);\n const stack = err.stack;\n if (!stack) return undefined;\n\n const lines = stack.split(\"\\n\").slice(1);\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n if (trimmed.includes(\"/logging/\") || trimmed.includes(\"\\\\logging\\\\\")) {\n continue;\n }\n\n const match =\n trimmed.match(/\\(([^)]+):(\\d+):(\\d+)\\)$/) ??\n trimmed.match(/at\\s+([^\\s]+):(\\d+):(\\d+)$/);\n\n if (!match) continue;\n\n const file = match[1];\n const lineNumber = Number(match[2]);\n const columnNumber = Number(match[3]);\n\n if (!file || Number.isNaN(lineNumber)) continue;\n\n return {\n file,\n line: lineNumber,\n column: Number.isNaN(columnNumber) ? undefined : columnNumber,\n };\n }\n\n return undefined;\n}\n\nfunction shortenPath(path: string, mode: LogPathMode): string {\n if (mode === \"full\") return path;\n if (mode === \"file\") {\n const cleaned = path.replace(/^[^:]*[\\\\/]/, \"\");\n return cleaned || path;\n }\n\n let normalized = path;\n if (normalized.startsWith(\"file://\")) {\n normalized = normalized.slice(\"file://\".length);\n }\n\n try {\n const processObj = (globalThis as any).process as\n | { cwd?: () => string }\n | undefined;\n if (processObj?.cwd) {\n const cwd = processObj.cwd();\n if (normalized.startsWith(cwd)) {\n return normalized.slice(cwd.length + 1);\n }\n }\n } catch {\n // Ignore errors resolving cwd\n }\n\n const normalizedPath = normalized.replace(/\\\\/g, \"/\");\n const distIndex = normalizedPath.lastIndexOf(\"/dist/\");\n if (distIndex >= 0) {\n return normalizedPath.slice(distIndex + 1);\n }\n\n const sdkIndex = normalizedPath.lastIndexOf(\"/sdk/\");\n if (sdkIndex >= 0) {\n return normalizedPath.slice(sdkIndex + 1);\n }\n\n const segments = normalizedPath.split(\"/\").filter(Boolean);\n if (segments.length >= 2) {\n return segments.slice(-2).join(\"/\");\n }\n\n return normalizedPath;\n}\n\nfunction getEnvValue(key: string): string | undefined {\n const processObj = (globalThis as any).process as\n | { env?: Record<string, string> }\n | undefined;\n if (processObj?.env?.[key]) {\n return processObj.env[key];\n }\n const globalValue = (globalThis as any)[key];\n if (typeof globalValue === \"string\") {\n return globalValue;\n }\n return undefined;\n}\n\nfunction getEnvBool(key: string, fallback: boolean): boolean {\n const value = getEnvValue(key);\n if (value === undefined) return fallback;\n const normalized = value.trim().toLowerCase();\n if ([\"1\", \"true\", \"yes\", \"on\"].includes(normalized)) return true;\n if ([\"0\", \"false\", \"no\", \"off\"].includes(normalized)) return false;\n return fallback;\n}\n", "import { log } from \"../../logging\";\n/**\n * IPC Port - Unified interface for MessagePort communication\n *\n * Provides a common interface for both:\n * - DOM MessagePort (frontend/preload)\n * - Electron MessagePortMain (backend utility process)\n */\n\n/**\n * Unified interface for both DOM MessagePort and Electron MessagePortMain\n */\nexport interface IPCPort {\n postMessage(message: any): void;\n on(event: \"message\", listener: (event: { data: any }) => void): void;\n on(event: \"close\", listener: () => void): void;\n off(event: \"message\", listener: (event: { data: any }) => void): void;\n off(event: \"close\", listener: () => void): void;\n start(): void;\n close(): void;\n}\n\n/**\n * Wrap a DOM MessagePort to conform to IPCPort interface\n */\nexport function wrapDOMPort(port: MessagePort): IPCPort {\n const messageListeners = new Map<\n (event: { data: any }) => void,\n (event: MessageEvent) => void\n >();\n const closeListeners = new Set<() => void>();\n\n return {\n postMessage: (message: any) => port.postMessage(message),\n\n on: ((event: string, listener: any) => {\n if (event === \"message\") {\n // Create a wrapper that extracts data from MessageEvent\n const wrapper = (e: MessageEvent) => listener({ data: e.data });\n messageListeners.set(listener, wrapper);\n port.addEventListener(\"message\", wrapper);\n } else if (event === \"close\") {\n closeListeners.add(listener);\n }\n }) as IPCPort[\"on\"],\n\n off: ((event: string, listener: any) => {\n if (event === \"message\") {\n const wrapper = messageListeners.get(listener);\n if (wrapper) {\n port.removeEventListener(\"message\", wrapper);\n messageListeners.delete(listener);\n }\n } else if (event === \"close\") {\n closeListeners.delete(listener);\n }\n }) as IPCPort[\"off\"],\n\n start: () => port.start(),\n close: () => {\n port.close();\n // Manually trigger close listeners as DOM MessagePort doesn't emit 'close'\n closeListeners.forEach((listener) => {\n try {\n listener();\n } catch (e) {\n log.error(\"Error in close listener:\", e);\n }\n });\n closeListeners.clear();\n },\n };\n}\n\n/**\n * Wrap an Electron MessagePortMain to conform to IPCPort interface\n * (MessagePortMain already uses the EventEmitter pattern)\n */\nexport function wrapElectronPort(port: Electron.MessagePortMain): IPCPort {\n return port as unknown as IPCPort;\n}\n", "import { log } from \"../../logging\";\n\n/**\n * Port Channel - Shared utilities for MessagePort communication\n *\n * This module provides reusable utilities for setting up MessagePort-based\n * communication channels between frontend, backend, and AppBus connections.\n *\n * Used by:\n * - app-preload.ts (frontend)\n * - backend-preload.ts (backend)\n */\n\nexport type { IPCPort } from \"./ipc-port\";\n// Re-export IPCPort types and wrappers\nexport { wrapDOMPort, wrapElectronPort } from \"./ipc-port\";\n\nimport type {\n AppBusConnection,\n ServiceConnectCallback,\n} from \"@edenapp/types/ipc/appbus\";\nimport type { IPCPort } from \"./ipc-port\";\n\n/**\n * Pending request tracking\n */\nexport interface PendingRequest {\n resolve: (value: any) => void;\n reject: (reason: any) => void;\n}\n\n/**\n * Pending port arrival tracking\n */\nexport interface PendingPortArrival {\n resolve: (port: IPCPort) => void;\n reject: (reason: Error) => void;\n}\n\n/**\n * Options for setting up a client port\n */\nexport interface ClientPortOptions {\n port: IPCPort;\n connectionId: string;\n portStore: Map<string, IPCPort>;\n pendingRequests: Map<string, PendingRequest>;\n pendingPortArrivals?: Map<string, PendingPortArrival>;\n logPrefix?: string;\n}\n\n/**\n * Message ID generator factory\n */\nexport function createMessageIdGenerator(prefix: string = \"msg\"): () => string {\n let counter = 0;\n return () => `${prefix}-${Date.now()}-${++counter}`;\n}\n\n/**\n * AppBus state for an app\n */\nexport interface AppBusState {\n registeredServices: Map<string, ServiceConnectCallback>;\n connectedPorts: Map<string, IPCPort>;\n pendingRequests: Map<string, PendingRequest>;\n pendingPortArrivals: Map<string, PendingPortArrival>;\n messageIdGenerator: () => string;\n}\n\n/**\n * Create AppBus state for an app\n */\nexport function createAppBusState(prefix: string = \"appbus\"): AppBusState {\n return {\n registeredServices: new Map(),\n connectedPorts: new Map(),\n pendingRequests: new Map(),\n pendingPortArrivals: new Map(),\n messageIdGenerator: createMessageIdGenerator(prefix),\n };\n}\n\n/**\n * Wait for a port to arrive for a given connection ID\n *\n * @param connectionId The connection ID to wait for\n * @param state AppBus state containing connectedPorts and pendingPortArrivals\n * @param timeoutMs Timeout in milliseconds (default: 5000)\n * @returns Promise that resolves with the port or rejects on timeout\n */\nexport function waitForPort(\n connectionId: string,\n state: AppBusState,\n timeoutMs: number = 5000,\n): Promise<IPCPort> {\n // Check if port is already available\n const existing = state.connectedPorts.get(connectionId);\n if (existing) {\n return Promise.resolve(existing);\n }\n\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n state.pendingPortArrivals.delete(connectionId);\n reject(\n new Error(\n `Port for connection ${connectionId} not received within ${timeoutMs}ms`,\n ),\n );\n }, timeoutMs);\n\n state.pendingPortArrivals.set(connectionId, {\n resolve: (port: IPCPort) => {\n clearTimeout(timeout);\n resolve(port);\n },\n reject: (reason: Error) => {\n clearTimeout(timeout);\n reject(reason);\n },\n });\n });\n}\n\n/**\n * Set up a MessagePort as a client (sends requests, receives responses)\n *\n * @param options Configuration for the client port\n */\nexport function setupClientPort(options: ClientPortOptions): void {\n const {\n port,\n connectionId,\n portStore,\n pendingRequests,\n pendingPortArrivals,\n } = options;\n\n // Store the port for later use\n portStore.set(connectionId, port);\n\n // Resolve any pending port arrivals waiting for this connection\n if (pendingPortArrivals) {\n const pending = pendingPortArrivals.get(connectionId);\n if (pending) {\n pendingPortArrivals.delete(connectionId);\n pending.resolve(port);\n }\n }\n\n // Set up response handler\n port.on(\"message\", (event) => {\n const { type, messageId, payload, error } = event.data;\n\n if (type === \"response\" && messageId) {\n const pending = pendingRequests.get(messageId);\n if (pending) {\n pendingRequests.delete(messageId);\n if (error) {\n pending.reject(new Error(error));\n } else {\n pending.resolve(payload);\n }\n }\n }\n });\n\n port.start();\n}\n\n/**\n * Create a connection object for a port (Electron IPC style)\n *\n * @param port The IPCPort to wrap\n * @param connectionId The connection ID\n * @param portStore The Map storing ports\n * @param pendingRequests The Map tracking pending requests for outgoing requests\n * @param generateMessageId Function to generate unique message IDs\n * @returns Connection object with send/on/off, request/handle/removeHandler, and close methods\n */\nexport function createPortConnection(\n port: IPCPort,\n connectionId: string,\n portStore: Map<string, IPCPort>,\n pendingRequests: Map<string, PendingRequest>,\n generateMessageId: () => string,\n): AppBusConnection {\n // Method-specific listeners for fire-and-forget messages (send \u2192 on)\n const messageListeners: Map<string, Set<(args: any) => void>> = new Map();\n\n // Method-specific handlers for request/response (request \u2192 handle)\n const requestHandlers: Map<string, (args: any) => any | Promise<any>> =\n new Map();\n\n // Store the port for later use (cleanup, connectivity checks)\n portStore.set(connectionId, port);\n\n // Set up incoming message handler\n port.on(\"message\", (event) => {\n const { type, method, payload, messageId } = event.data;\n\n if (type === \"message\") {\n // Fire-and-forget message - dispatch to on() listeners\n const listeners = messageListeners.get(method);\n if (listeners) {\n listeners.forEach((callback) => {\n try {\n callback(payload);\n } catch (err) {\n log.error(`Error in on('${method}') listener:`, err);\n }\n });\n }\n } else if (type === \"request\") {\n // Request expecting response - dispatch to handle() handler\n const handler = requestHandlers.get(method);\n if (handler) {\n try {\n const result = handler(payload);\n Promise.resolve(result)\n .then((response) => {\n port.postMessage({\n type: \"response\",\n messageId,\n payload: response,\n });\n })\n .catch((err) => {\n port.postMessage({\n type: \"response\",\n messageId,\n error: err instanceof Error ? err.message : String(err),\n });\n });\n } catch (err) {\n port.postMessage({\n type: \"response\",\n messageId,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n } else {\n port.postMessage({\n type: \"response\",\n messageId,\n error: `No handler registered for method '${method}'`,\n });\n }\n } else if (type === \"response\" && messageId) {\n // Response to our outgoing request\n const pending = pendingRequests.get(messageId);\n if (pending) {\n pendingRequests.delete(messageId);\n if (event.data.error) {\n pending.reject(new Error(event.data.error));\n } else {\n pending.resolve(payload);\n }\n }\n }\n });\n\n port.start();\n\n return {\n // Fire-and-forget messaging\n send: (method: string, args?: any) => {\n port.postMessage({ type: \"message\", method, payload: args });\n },\n\n on: (method: string, callback: (args: any) => void) => {\n if (typeof callback !== \"function\") {\n throw new Error(\"Callback must be a function\");\n }\n if (!messageListeners.has(method)) {\n messageListeners.set(method, new Set());\n }\n messageListeners.get(method)!.add(callback);\n },\n\n once: (method: string, callback: (args: any) => void) => {\n if (typeof callback !== \"function\") {\n throw new Error(\"Callback must be a function\");\n }\n const wrapper = (args: any) => {\n // Remove before calling to prevent issues if callback throws\n const listeners = messageListeners.get(method);\n if (listeners) {\n listeners.delete(wrapper);\n if (listeners.size === 0) {\n messageListeners.delete(method);\n }\n }\n callback(args);\n };\n if (!messageListeners.has(method)) {\n messageListeners.set(method, new Set());\n }\n messageListeners.get(method)!.add(wrapper);\n },\n\n off: (method: string, callback: (args: any) => void) => {\n const listeners = messageListeners.get(method);\n if (listeners) {\n listeners.delete(callback);\n if (listeners.size === 0) {\n messageListeners.delete(method);\n }\n }\n },\n\n // Request/response\n request: (\n method: string,\n args?: any,\n timeout: number = 30000,\n ): Promise<any> => {\n return new Promise((resolve, reject) => {\n const messageId = generateMessageId();\n\n // Timeout after specified duration\n const timeoutId = setTimeout(() => {\n if (pendingRequests.has(messageId)) {\n pendingRequests.delete(messageId);\n reject(new Error(`Request '${method}' timed out`));\n }\n }, timeout);\n\n pendingRequests.set(messageId, {\n resolve: (value) => {\n clearTimeout(timeoutId);\n resolve(value);\n },\n reject: (reason) => {\n clearTimeout(timeoutId);\n reject(reason);\n },\n });\n\n port.postMessage({\n type: \"request\",\n method,\n payload: args,\n messageId,\n });\n });\n },\n\n handle: (method: string, handler: (args: any) => any | Promise<any>) => {\n if (typeof handler !== \"function\") {\n throw new Error(\"Handler must be a function\");\n }\n if (requestHandlers.has(method)) {\n throw new Error(`Handler already registered for method '${method}'`);\n }\n requestHandlers.set(method, handler);\n },\n\n removeHandler: (method: string) => {\n requestHandlers.delete(method);\n },\n\n // Connection management\n isConnected: () => {\n return portStore.has(connectionId);\n },\n\n onClose: (callback: () => void) => {\n port.on(\"close\", callback);\n },\n\n close: () => {\n portStore.delete(connectionId);\n messageListeners.clear();\n requestHandlers.clear();\n port.close();\n },\n };\n}\n\n/**\n * Handle an incoming AppBus port (can be service or client role)\n *\n * @param port The MessagePort received\n * @param data Connection metadata\n * @param state AppBus state (services, ports, pending requests)\n * @param logPrefix Prefix for log messages\n */\nexport function handleAppBusPort(\n port: IPCPort,\n data: {\n connectionId: string;\n role: \"service\" | \"client\";\n serviceName: string;\n targetAppId?: string;\n sourceAppId?: string;\n },\n state: AppBusState,\n): void {\n const { connectionId, role, serviceName, targetAppId, sourceAppId } = data;\n\n if (role === \"service\") {\n // A client is connecting to our service\n log.info(\n `Received connection from ${sourceAppId} for service ${serviceName}`,\n );\n\n const onConnect = state.registeredServices.get(serviceName);\n if (!onConnect) {\n log.error(\n `No onConnect callback registered for service \"${serviceName}\"`,\n );\n return;\n }\n\n // Create a bidirectional AppBusConnection for the service to use\n const connection = createPortConnection(\n port,\n connectionId,\n state.connectedPorts,\n state.pendingRequests,\n state.messageIdGenerator,\n );\n\n // Call the onConnect callback with the connection and client info\n try {\n onConnect(connection, { appId: sourceAppId || \"unknown\" });\n } catch (err) {\n log.error(\n `Error in onConnect callback for service \"${serviceName}\":`,\n err,\n );\n }\n } else if (role === \"client\") {\n // We're connecting to another app's service\n log.info(`Connected to ${targetAppId}/${serviceName}`);\n\n setupClientPort({\n port,\n connectionId,\n portStore: state.connectedPorts,\n pendingRequests: state.pendingRequests,\n pendingPortArrivals: state.pendingPortArrivals,\n });\n }\n}\n/**\n * Handle a port being closed from the other side\n * Triggered by a notification from the main process\n *\n * @param state AppBus state\n * @param connectionId The ID of the closed connection\n */\nexport function handlePortClosed(\n state: AppBusState,\n connectionId: string,\n): void {\n const port = state.connectedPorts.get(connectionId);\n if (port) {\n port.close();\n state.connectedPorts.delete(connectionId);\n }\n}\n", "import type {\n AppBusAPI,\n AppBusConnection,\n EdenAPI,\n ServiceConnectCallback,\n ServiceInfo,\n} from \"@edenapp/types\";\nimport type { AppBusState, IPCPort } from \"./port-channel\";\nimport { createPortConnection, waitForPort } from \"./port-channel\";\n\n/**\n * Interface for sending shell commands to the main process\n */\nexport interface ShellTransport {\n exec(command: string, args: any): Promise<any>;\n}\n\n/**\n * Configuration for AppBus API\n */\nexport interface AppBusConfig {\n transport: ShellTransport;\n isBackend?: boolean;\n}\n\n/**\n * Create the EdenAPI object\n */\nexport function createEdenAPI(\n transport: ShellTransport,\n eventSubscriptions: Map<string, Set<Function>>,\n options?: { getLaunchArgs?: () => string[] },\n): EdenAPI {\n return {\n shellCommand: (command: string, args: any) => {\n return transport.exec(command, args);\n },\n\n subscribe: async (eventName: string, callback: Function) => {\n if (typeof callback !== \"function\") {\n throw new Error(\"Callback must be a function\");\n }\n\n // Register with backend/main\n await transport.exec(\"event/subscribe\", { eventName });\n\n // Register callback locally\n if (!eventSubscriptions.has(eventName)) {\n eventSubscriptions.set(eventName, new Set());\n }\n eventSubscriptions.get(eventName)!.add(callback);\n },\n\n unsubscribe: async (eventName: string, callback: Function) => {\n const callbacks = eventSubscriptions.get(eventName);\n if (callbacks) {\n callbacks.delete(callback);\n\n // If no more callbacks, unregister from backend/main\n if (callbacks.size === 0) {\n eventSubscriptions.delete(eventName);\n await transport.exec(\"event/unsubscribe\", { eventName });\n }\n }\n },\n\n isEventSupported: (eventName: string) => {\n return transport.exec(\"event/exists\", { eventName });\n },\n\n getLaunchArgs: (): string[] => {\n if (options?.getLaunchArgs) {\n return options.getLaunchArgs();\n }\n return [];\n },\n };\n}\n\n/**\n * Create the AppBusAPI object\n */\nexport function createAppBusAPI(\n config: AppBusConfig,\n state: AppBusState,\n): AppBusAPI {\n const { transport, isBackend } = config;\n const {\n registeredServices,\n connectedPorts,\n pendingRequests,\n messageIdGenerator,\n } = state;\n\n return {\n exposeService: async (\n serviceName: string,\n onConnect: ServiceConnectCallback,\n options?: {\n description?: string;\n allowedClients?: string[];\n },\n ): Promise<{ success: boolean; error?: string }> => {\n if (typeof onConnect !== \"function\") {\n throw new Error(\"onConnect callback must be a function\");\n }\n\n // Store the onConnect callback locally\n // When a client connects, handleAppBusPort will call this with the connection\n registeredServices.set(serviceName, onConnect);\n\n // Register with main process\n const result = await transport.exec(\"appbus/register\", {\n serviceName,\n description: options?.description,\n allowedClients: options?.allowedClients,\n isBackend,\n });\n\n if (!result.success) {\n registeredServices.delete(serviceName);\n }\n\n return result;\n },\n\n unexposeService: async (\n serviceName: string,\n ): Promise<{ success: boolean }> => {\n registeredServices.delete(serviceName);\n return transport.exec(\"appbus/unregister\", {\n serviceName,\n });\n },\n\n connect: async (\n targetAppId: string,\n serviceName: string,\n ): Promise<AppBusConnection | { error: string }> => {\n // Request connection through shell command\n const result = await transport.exec(\"appbus/connect\", {\n targetAppId,\n serviceName,\n isBackend,\n });\n\n if (!result.success) {\n return { error: result.error || \"Connection failed\" };\n }\n\n const { connectionId } = result;\n\n // Wait for the port to be received via handleAppBusPort\n let port: IPCPort;\n try {\n port = await waitForPort(connectionId, state, 5000);\n } catch (err) {\n return {\n error:\n err instanceof Error ? err.message : \"MessagePort not received\",\n };\n }\n\n // Use shared utility to create connection object\n return createPortConnection(\n port,\n connectionId,\n connectedPorts,\n pendingRequests,\n messageIdGenerator,\n );\n },\n\n listServices: async (): Promise<{ services: ServiceInfo[] }> => {\n return transport.exec(\"appbus/list\", {});\n },\n\n listServicesByApp: async (\n appId: string,\n ): Promise<{ services: ServiceInfo[] }> => {\n return transport.exec(\"appbus/list-by-app\", { appId });\n },\n };\n}\n"],
5
- "mappings": "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",
6
- "names": ["import_electron", "LOG_LEVEL_ORDER", "parseLogLevel", "value", "normalized", "isLogLevelEnabled", "level", "minLevel", "globalContext", "config", "resolveDefaultConfig", "baseConsole", "setLogContext", "next", "globalContext", "createLogger", "context", "args", "emit", "log", "emit", "record", "level", "isLogLevelEnabled", "config", "timestamp", "context", "mergeContext", "callsite", "captureCallsite", "prefix", "formatPrefix", "target", "consoleForLevel", "getBaseContext", "envAppId", "getEnvValue", "globalAppId", "detectProcessType", "globalContext", "processObj", "type", "resolveDefaultConfig", "envLevel", "parseLogLevel", "envFormat", "envPathMode", "isTest", "isRenderer", "getEnvBool", "useLiveConsole", "baseConsole", "_a", "_b", "_c", "_d", "_e", "parts", "file", "shortenPath", "err", "stack", "lines", "line", "trimmed", "match", "lineNumber", "columnNumber", "path", "mode", "normalized", "cwd", "normalizedPath", "distIndex", "sdkIndex", "segments", "key", "globalValue", "fallback", "value", "wrapDOMPort", "port", "messageListeners", "closeListeners", "message", "event", "listener", "wrapper", "e", "log", "createMessageIdGenerator", "prefix", "counter", "createAppBusState", "waitForPort", "connectionId", "state", "timeoutMs", "existing", "resolve", "reject", "timeout", "port", "reason", "setupClientPort", "options", "portStore", "pendingRequests", "pendingPortArrivals", "pending", "event", "type", "messageId", "payload", "error", "createPortConnection", "generateMessageId", "messageListeners", "requestHandlers", "method", "listeners", "callback", "err", "log", "handler", "result", "response", "args", "wrapper", "timeoutId", "value", "handleAppBusPort", "data", "role", "serviceName", "targetAppId", "sourceAppId", "onConnect", "connection", "handlePortClosed", "createEdenAPI", "transport", "eventSubscriptions", "options", "command", "args", "eventName", "callback", "callbacks", "createAppBusAPI", "config", "state", "isBackend", "registeredServices", "connectedPorts", "pendingRequests", "messageIdGenerator", "serviceName", "onConnect", "result", "targetAppId", "connectionId", "port", "waitForPort", "err", "createPortConnection", "appId", "appId", "backendPort", "backendConnection", "pendingBackendRequests", "generateBackendMessageId", "createMessageIdGenerator", "eventSubscriptions", "appIdArg", "arg", "setLogContext", "log", "launchArgs", "launchArgsArg", "jsonStr", "event", "port", "wrappedPort", "wrapDOMPort", "createPortConnection", "_event", "message", "type", "payload", "callbacks", "callback", "err", "shellTransport", "command", "args", "edenAPI", "createEdenAPI", "appBusState", "createAppBusState", "data", "handleAppBusPort", "handlePortClosed", "createAppBusAPI", "setupZoomPrevention"]
4
+ "sourcesContent": ["import type { AppBusConnection } from \"@edenapp/types/ipc/appbus\";\nimport { contextBridge, ipcRenderer } from \"electron\";\nimport { log, setLogContext } from \"../logging\";\nimport {\n createAppBusAPI,\n createEdenAPI,\n type ShellTransport,\n} from \"./common/api-factory\";\nimport {\n type AppBusPortData,\n createAppBusState,\n createMessageIdGenerator,\n createPortConnection,\n handleAppBusPort,\n handlePortClosed,\n type PendingRequest,\n wrapDOMPort,\n} from \"./common/port-channel\";\n\n// Per-app state\nlet appId: string | null = null;\n\n// MessagePort for direct frontend<->backend communication\nlet backendPort: MessagePort | null = null;\nlet backendConnection: AppBusConnection | null = null;\n\n// Pending requests waiting for responses (for backend communication)\nconst pendingBackendRequests: Map<string, PendingRequest> = new Map();\n\n// Message ID generator for backend communication\nconst generateBackendMessageId = createMessageIdGenerator(\"backend\");\n\n// Event subscription system\nconst eventSubscriptions: Map<\n string,\n Set<(payload: unknown) => void>\n> = new Map();\n\n// Extract appId from process arguments\n// Arguments are passed as --app-id=com.example.app\nconst appIdArg = process.argv.find((arg) => arg.startsWith(\"--app-id=\"));\nif (appIdArg) {\n appId = appIdArg.split(\"=\")[1];\n setLogContext({ appId });\n log.info(`Initialized for app: ${appId}`);\n} else {\n log.warn(\"No app ID found in arguments\");\n}\n\n// Extract launch args\nlet launchArgs: string[] = [];\nconst launchArgsArg = process.argv.find((arg) =>\n arg.startsWith(\"--launch-args=\"),\n);\nif (launchArgsArg) {\n try {\n const jsonStr = launchArgsArg.split(\"=\").slice(1).join(\"=\");\n launchArgs = JSON.parse(jsonStr);\n } catch (e) {\n log.error(\"Failed to parse launch args:\", e);\n }\n}\n\n// Handle receiving the backend MessagePort\nipcRenderer.on(\"backend-port\", (event) => {\n const [port] = event.ports as MessagePort[];\n if (!port) {\n log.error(\"Received backend-port event without port\");\n return;\n }\n\n backendPort = port;\n log.info(`Backend port received for app ${appId}`);\n\n // Wrap DOM MessagePort to IPCPort interface\n const wrappedPort = wrapDOMPort(port);\n\n // Create connection object - handles all message routing internally\n backendConnection = createPortConnection(\n wrappedPort,\n \"__backend__\",\n new Map([[\"__backend__\", wrappedPort]]), // Dummy map since we won't close this\n pendingBackendRequests,\n generateBackendMessageId,\n );\n});\n\n// Set up unified message listener for shell-message channel\nipcRenderer.on(\n \"shell-message\",\n (_event, message: { type: string; payload: unknown }) => {\n const { type, payload } = message;\n const callbacks = eventSubscriptions.get(type);\n\n if (callbacks) {\n callbacks.forEach((callback) => {\n try {\n callback(payload);\n } catch (err) {\n log.error(`Error in event listener for ${type}:`, err);\n }\n });\n }\n },\n);\n\n// Expose safe API to the app\ncontextBridge.exposeInMainWorld(\"getAppAPI\", () => {\n if (!backendConnection) {\n throw new Error(\n \"AppAPI not available: Backend not connected. \" +\n \"This could mean the app has no backend, or the connection is not yet established.\",\n );\n }\n return backendConnection;\n});\n\n// ===================================================================\n// Shared API Implementation\n// ===================================================================\n\n// Shell transport implementation using ipcRenderer\nconst shellTransport: ShellTransport = {\n exec: (command, args) => {\n return ipcRenderer.invoke(\"shell-command\", command, args);\n },\n};\n\n// Expose edenAPI for shell commands and event subscriptions\nconst edenAPI = createEdenAPI(shellTransport, eventSubscriptions, {\n getLaunchArgs: () => launchArgs,\n});\n\ncontextBridge.exposeInMainWorld(\"edenAPI\", edenAPI);\n\n// ===================================================================\n// AppBus - App-to-App Communication System\n// ===================================================================\n\nconst appBusState = createAppBusState(\"appbus\");\n\n// Handle incoming MessagePorts for peer-to-peer channels\nipcRenderer.on(\"appbus-port\", (event, data: AppBusPortData) => {\n const [port] = event.ports as MessagePort[];\n if (!port) {\n log.error(\"Received appbus-port event without port\");\n return;\n }\n\n // Wrap DOM MessagePort to IPCPort interface\n const wrappedPort = wrapDOMPort(port);\n\n handleAppBusPort(wrappedPort, data, appBusState);\n});\n\n// Handle port closed notification\nipcRenderer.on(\n \"appbus-port-closed\",\n (_event, data: { connectionId: string }) => {\n handlePortClosed(appBusState, data.connectionId);\n },\n);\n\n// Expose appBus API for app-to-app communication\ncontextBridge.exposeInMainWorld(\n \"appBus\",\n createAppBusAPI({ transport: shellTransport }, appBusState),\n);\n\n// ===================================================================\n// Universal Zoom Prevention\n// ===================================================================\n// Disable default browser zoom behavior for all apps\n// This runs when the DOM is ready for all apps, regardless of app-frame usage\n\nconst setupZoomPrevention = () => {\n // Block Ctrl/Cmd + Plus/Minus/Equals for keyboard zoom\n document.addEventListener(\n \"keydown\",\n (e: KeyboardEvent) => {\n if (\n (e.ctrlKey || e.metaKey) &&\n (e.key === \"+\" || e.key === \"-\" || e.key === \"=\" || e.key === \"0\")\n ) {\n e.preventDefault();\n }\n },\n { capture: true },\n );\n\n // Block Ctrl/Cmd + Mouse wheel for zoom\n document.addEventListener(\n \"wheel\",\n (e: WheelEvent) => {\n if (e.ctrlKey || e.metaKey) {\n e.preventDefault();\n }\n },\n { passive: false, capture: true },\n );\n\n log.info(\"Zoom prevention enabled\");\n};\n\n// Setup when DOM is ready\nif (document.readyState === \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", setupZoomPrevention);\n} else {\n setupZoomPrevention();\n}\n\nlog.info(\"Universal app preload loaded\");\n", "export type LogLevel = \"trace\" | \"debug\" | \"info\" | \"warn\" | \"error\" | \"fatal\";\n\nexport const LOG_LEVEL_ORDER: Record<LogLevel, number> = {\n trace: 10,\n debug: 20,\n info: 30,\n warn: 40,\n error: 50,\n fatal: 60,\n};\n\nexport function parseLogLevel(value?: string | null): LogLevel | null {\n if (!value) return null;\n const normalized = value.trim().toLowerCase();\n if (normalized in LOG_LEVEL_ORDER) {\n return normalized as LogLevel;\n }\n return null;\n}\n\nexport function isLogLevelEnabled(\n level: LogLevel,\n minLevel: LogLevel,\n): boolean {\n return LOG_LEVEL_ORDER[level] >= LOG_LEVEL_ORDER[minLevel];\n}\n", "import type { LogLevel } from \"./levels\";\nimport { isLogLevelEnabled, parseLogLevel } from \"./levels\";\n\nexport type LogFormat = \"pretty\" | \"raw\";\nexport type LogPathMode = \"short\" | \"full\" | \"file\";\n\nexport interface LogContext {\n appId?: string;\n viewId?: number;\n webContentsId?: number;\n processType?: string;\n source?: string;\n}\n\nexport interface CallsiteInfo {\n file: string;\n line: number;\n column?: number;\n}\n\nexport interface LoggerConfig {\n minLevel: LogLevel;\n format: LogFormat;\n includeTimestamp: boolean;\n includeCallsite: boolean;\n pathMode: LogPathMode;\n}\n\nexport interface Logger {\n trace: (...args: unknown[]) => void;\n debug: (...args: unknown[]) => void;\n info: (...args: unknown[]) => void;\n warn: (...args: unknown[]) => void;\n error: (...args: unknown[]) => void;\n fatal: (...args: unknown[]) => void;\n}\n\ninterface LogRecord {\n level: LogLevel;\n args: unknown[];\n context?: LogContext;\n callsite?: CallsiteInfo;\n timestamp?: number;\n skipCallsite?: boolean;\n}\n\ntype StackTraceFrameSkipper = (...args: unknown[]) => unknown;\n\ntype V8ErrorConstructor = ErrorConstructor & {\n captureStackTrace?: (\n targetObject: object,\n constructorOpt?: StackTraceFrameSkipper,\n ) => void;\n};\n\ntype RuntimeProcessLike = {\n type?: string;\n env?: Record<string, string>;\n cwd?: () => string;\n};\n\ntype RuntimeGlobal = typeof globalThis & {\n __EDEN_APP_ID__?: string;\n process?: RuntimeProcessLike;\n window?: unknown;\n [key: string]: unknown;\n};\n\nconst runtimeGlobal = globalThis as RuntimeGlobal;\n\nlet globalContext: LogContext = {};\n\nlet config: LoggerConfig = resolveDefaultConfig();\nconst baseConsole = {\n debug: console.debug.bind(console),\n warn: console.warn.bind(console),\n error: console.error.bind(console),\n info: console.log.bind(console),\n};\n\nexport function configureLogger(next: Partial<LoggerConfig>): void {\n config = { ...config, ...next };\n}\n\nexport function getLoggerConfig(): LoggerConfig {\n return config;\n}\n\nexport function setLogContext(next: Partial<LogContext>): void {\n globalContext = { ...globalContext, ...next };\n}\n\nexport function createLogger(context?: LogContext): Logger {\n return {\n trace: (...args) => emit({ level: \"trace\", args, context }),\n debug: (...args) => emit({ level: \"debug\", args, context }),\n info: (...args) => emit({ level: \"info\", args, context }),\n warn: (...args) => emit({ level: \"warn\", args, context }),\n error: (...args) => emit({ level: \"error\", args, context }),\n fatal: (...args) => emit({ level: \"fatal\", args, context }),\n };\n}\n\nexport const log: Logger = createLogger();\n\nexport function logExternal(record: {\n level: LogLevel;\n message: string;\n context?: LogContext;\n callsite?: CallsiteInfo;\n}): void {\n emit({\n level: record.level,\n args: [record.message],\n context: record.context,\n callsite: record.callsite,\n skipCallsite: true,\n });\n}\n\nexport function logFromConsole(record: {\n level: LogLevel;\n args: unknown[];\n context?: LogContext;\n callsite?: CallsiteInfo;\n}): void {\n emit({\n level: record.level,\n args: record.args,\n context: record.context,\n callsite: record.callsite,\n skipCallsite: true,\n });\n}\n\nfunction emit(record: LogRecord): void {\n const { level } = record;\n if (!isLogLevelEnabled(level, config.minLevel)) return;\n\n const timestamp = record.timestamp ?? Date.now();\n const context = mergeContext(record.context);\n const callsite =\n record.callsite ??\n (config.includeCallsite && !record.skipCallsite\n ? captureCallsite()\n : undefined);\n\n const prefix =\n config.format === \"pretty\"\n ? formatPrefix({ level, timestamp, context, callsite })\n : \"\";\n\n const target = consoleForLevel(level);\n if (prefix) {\n target(prefix, ...record.args);\n } else {\n target(...record.args);\n }\n}\n\nfunction mergeContext(context?: LogContext): LogContext {\n const base = getBaseContext();\n return { ...base, ...context };\n}\n\nfunction getBaseContext(): LogContext {\n const envAppId = getEnvValue(\"EDEN_APP_ID\");\n const globalAppId = runtimeGlobal.__EDEN_APP_ID__;\n return {\n processType: detectProcessType(),\n appId: globalContext.appId ?? envAppId ?? globalAppId,\n viewId: globalContext.viewId,\n webContentsId: globalContext.webContentsId,\n source: globalContext.source,\n };\n}\n\nfunction detectProcessType(): string {\n const processObj = runtimeGlobal.process;\n if (processObj) {\n const type = processObj.type;\n if (type === \"browser\") return \"main\";\n if (type === \"utility\") return \"backend\";\n if (type) return type;\n }\n if (typeof runtimeGlobal.window !== \"undefined\") return \"renderer\";\n return \"node\";\n}\n\nfunction resolveDefaultConfig(): LoggerConfig {\n const envLevel = parseLogLevel(getEnvValue(\"EDEN_LOG_LEVEL\"));\n const envFormat = getEnvValue(\"EDEN_LOG_FORMAT\") as LogFormat | undefined;\n const envPathMode = getEnvValue(\"EDEN_LOG_PATH\") as LogPathMode | undefined;\n const isTest = getEnvValue(\"NODE_ENV\") === \"test\";\n const isRenderer = detectProcessType() === \"renderer\";\n\n return {\n minLevel: envLevel ?? \"debug\",\n format: envFormat ?? (isTest || isRenderer ? \"raw\" : \"pretty\"),\n includeTimestamp: getEnvBool(\"EDEN_LOG_TIMESTAMP\", !isTest),\n includeCallsite: getEnvBool(\"EDEN_LOG_CALLSITE\", !isTest && !isRenderer),\n pathMode: envPathMode ?? \"short\",\n };\n}\n\nfunction consoleForLevel(level: LogLevel): (...args: unknown[]) => void {\n const useLiveConsole = getEnvValue(\"NODE_ENV\") === \"test\";\n switch (level) {\n case \"trace\":\n case \"debug\":\n return useLiveConsole ? console.debug.bind(console) : baseConsole.debug;\n case \"warn\":\n return useLiveConsole ? console.warn.bind(console) : baseConsole.warn;\n case \"error\":\n case \"fatal\":\n return useLiveConsole ? console.error.bind(console) : baseConsole.error;\n case \"info\":\n default:\n return useLiveConsole ? console.log.bind(console) : baseConsole.info;\n }\n}\n\nfunction formatPrefix(record: {\n level: LogLevel;\n timestamp: number;\n context?: LogContext;\n callsite?: CallsiteInfo;\n}): string {\n const parts: string[] = [];\n\n if (config.includeTimestamp) {\n parts.push(new Date(record.timestamp).toISOString());\n }\n\n parts.push(record.level.toUpperCase());\n\n if (record.context?.processType) {\n parts.push(record.context.processType);\n }\n if (record.context?.appId) {\n parts.push(`app=${record.context.appId}`);\n }\n if (record.context?.viewId !== undefined) {\n parts.push(`view=${record.context.viewId}`);\n }\n if (record.context?.webContentsId !== undefined) {\n parts.push(`wc=${record.context.webContentsId}`);\n }\n if (record.context?.source) {\n parts.push(record.context.source);\n }\n if (record.callsite) {\n const file = shortenPath(record.callsite.file, config.pathMode);\n parts.push(`${file}:${record.callsite.line}`);\n }\n\n return `[${parts.join(\"] [\")}]`;\n}\n\nfunction captureCallsite(): CallsiteInfo | undefined {\n const err = new Error();\n const v8Error = Error as V8ErrorConstructor;\n v8Error.captureStackTrace?.(err, captureCallsite);\n const stack = err.stack;\n if (!stack) return undefined;\n\n const lines = stack.split(\"\\n\").slice(1);\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n if (trimmed.includes(\"/logging/\") || trimmed.includes(\"\\\\logging\\\\\")) {\n continue;\n }\n\n const match =\n trimmed.match(/\\(([^)]+):(\\d+):(\\d+)\\)$/) ??\n trimmed.match(/at\\s+([^\\s]+):(\\d+):(\\d+)$/);\n\n if (!match) continue;\n\n const file = match[1];\n const lineNumber = Number(match[2]);\n const columnNumber = Number(match[3]);\n\n if (!file || Number.isNaN(lineNumber)) continue;\n\n return {\n file,\n line: lineNumber,\n column: Number.isNaN(columnNumber) ? undefined : columnNumber,\n };\n }\n\n return undefined;\n}\n\nfunction shortenPath(path: string, mode: LogPathMode): string {\n if (mode === \"full\") return path;\n if (mode === \"file\") {\n const cleaned = path.replace(/^[^:]*[\\\\/]/, \"\");\n return cleaned || path;\n }\n\n let normalized = path;\n if (normalized.startsWith(\"file://\")) {\n normalized = normalized.slice(\"file://\".length);\n }\n\n try {\n const processObj = runtimeGlobal.process;\n if (processObj?.cwd) {\n const cwd = processObj.cwd();\n if (normalized.startsWith(cwd)) {\n return normalized.slice(cwd.length + 1);\n }\n }\n } catch {\n // Ignore errors resolving cwd\n }\n\n const normalizedPath = normalized.replace(/\\\\/g, \"/\");\n const distIndex = normalizedPath.lastIndexOf(\"/dist/\");\n if (distIndex >= 0) {\n return normalizedPath.slice(distIndex + 1);\n }\n\n const sdkIndex = normalizedPath.lastIndexOf(\"/sdk/\");\n if (sdkIndex >= 0) {\n return normalizedPath.slice(sdkIndex + 1);\n }\n\n const segments = normalizedPath.split(\"/\").filter(Boolean);\n if (segments.length >= 2) {\n return segments.slice(-2).join(\"/\");\n }\n\n return normalizedPath;\n}\n\nfunction getEnvValue(key: string): string | undefined {\n const processObj = runtimeGlobal.process;\n if (processObj?.env?.[key]) {\n return processObj.env[key];\n }\n const globalValue = runtimeGlobal[key];\n if (typeof globalValue === \"string\") {\n return globalValue;\n }\n return undefined;\n}\n\nfunction getEnvBool(key: string, fallback: boolean): boolean {\n const value = getEnvValue(key);\n if (value === undefined) return fallback;\n const normalized = value.trim().toLowerCase();\n if ([\"1\", \"true\", \"yes\", \"on\"].includes(normalized)) return true;\n if ([\"0\", \"false\", \"no\", \"off\"].includes(normalized)) return false;\n return fallback;\n}\n", "import { log } from \"../../logging\";\n/**\n * IPC Port - Unified interface for MessagePort communication\n *\n * Provides a common interface for both:\n * - DOM MessagePort (frontend/preload)\n * - Electron MessagePortMain (backend utility process)\n */\n\nexport type PortMessage =\n | { type: \"message\"; method: string; payload?: unknown }\n | { type: \"request\"; method: string; payload?: unknown; messageId: string }\n | { type: \"response\"; messageId: string; payload?: unknown; error?: string };\n\nexport interface IPCPortMessageEvent {\n data: PortMessage;\n}\n\n/**\n * Unified interface for both DOM MessagePort and Electron MessagePortMain\n */\nexport interface IPCPort {\n postMessage(message: PortMessage): void;\n on(event: \"message\", listener: (event: IPCPortMessageEvent) => void): void;\n on(event: \"close\", listener: () => void): void;\n off(event: \"message\", listener: (event: IPCPortMessageEvent) => void): void;\n off(event: \"close\", listener: () => void): void;\n start(): void;\n close(): void;\n}\n\n/**\n * Wrap a DOM MessagePort to conform to IPCPort interface\n */\nexport function wrapDOMPort(port: MessagePort): IPCPort {\n const messageListeners = new Map<\n (event: IPCPortMessageEvent) => void,\n (event: MessageEvent<PortMessage>) => void\n >();\n const closeListeners = new Set<() => void>();\n\n function on(\n event: \"message\",\n listener: (event: IPCPortMessageEvent) => void,\n ): void;\n function on(event: \"close\", listener: () => void): void;\n function on(\n event: \"message\" | \"close\",\n listener: ((event: IPCPortMessageEvent) => void) | (() => void),\n ): void {\n if (event === \"message\") {\n const messageListener = listener as (event: IPCPortMessageEvent) => void;\n const wrapper = (messageEvent: MessageEvent<PortMessage>) =>\n messageListener({ data: messageEvent.data });\n messageListeners.set(messageListener, wrapper);\n port.addEventListener(\"message\", wrapper);\n return;\n }\n\n closeListeners.add(listener as () => void);\n }\n\n function off(\n event: \"message\",\n listener: (event: IPCPortMessageEvent) => void,\n ): void;\n function off(event: \"close\", listener: () => void): void;\n function off(\n event: \"message\" | \"close\",\n listener: ((event: IPCPortMessageEvent) => void) | (() => void),\n ): void {\n if (event === \"message\") {\n const messageListener = listener as (event: IPCPortMessageEvent) => void;\n const wrapper = messageListeners.get(messageListener);\n if (wrapper) {\n port.removeEventListener(\"message\", wrapper);\n messageListeners.delete(messageListener);\n }\n return;\n }\n\n closeListeners.delete(listener as () => void);\n }\n\n return {\n postMessage: (message: PortMessage) => port.postMessage(message),\n on,\n off,\n start: () => port.start(),\n close: () => {\n port.close();\n // Manually trigger close listeners as DOM MessagePort doesn't emit 'close'\n closeListeners.forEach((listener) => {\n try {\n listener();\n } catch (e) {\n log.error(\"Error in close listener:\", e);\n }\n });\n closeListeners.clear();\n },\n };\n}\n\n/**\n * Wrap an Electron MessagePortMain to conform to IPCPort interface\n * (MessagePortMain already uses the EventEmitter pattern)\n */\nexport function wrapElectronPort(port: Electron.MessagePortMain): IPCPort {\n return port as unknown as IPCPort;\n}\n", "import { log } from \"../../logging\";\n\n/**\n * Port Channel - Shared utilities for MessagePort communication\n *\n * This module provides reusable utilities for setting up MessagePort-based\n * communication channels between frontend, backend, and AppBus connections.\n *\n * Used by:\n * - app-preload.ts (frontend)\n * - backend-preload.ts (backend)\n */\n\nexport type { IPCPort } from \"./ipc-port\";\n// Re-export IPCPort types and wrappers\nexport { wrapDOMPort, wrapElectronPort } from \"./ipc-port\";\n\nimport type {\n AppBusConnection,\n ServiceConnectCallback,\n} from \"@edenapp/types/ipc/appbus\";\nimport type { IPCPort } from \"./ipc-port\";\n\n/**\n * Pending request tracking\n */\nexport interface PendingRequest {\n resolve: (value: unknown) => void;\n reject: (reason: unknown) => void;\n}\n\n/**\n * Pending port arrival tracking\n */\nexport interface PendingPortArrival {\n resolve: (port: IPCPort) => void;\n reject: (reason: Error) => void;\n}\n\n/**\n * Options for setting up a client port\n */\nexport interface ClientPortOptions {\n port: IPCPort;\n connectionId: string;\n portStore: Map<string, IPCPort>;\n pendingRequests: Map<string, PendingRequest>;\n pendingPortArrivals?: Map<string, PendingPortArrival>;\n logPrefix?: string;\n}\n\n/**\n * Message ID generator factory\n */\nexport function createMessageIdGenerator(prefix: string = \"msg\"): () => string {\n let counter = 0;\n return () => `${prefix}-${Date.now()}-${++counter}`;\n}\n\n/**\n * AppBus state for an app\n */\nexport interface AppBusState {\n registeredServices: Map<string, ServiceConnectCallback>;\n connectedPorts: Map<string, IPCPort>;\n pendingRequests: Map<string, PendingRequest>;\n pendingPortArrivals: Map<string, PendingPortArrival>;\n messageIdGenerator: () => string;\n}\n\nexport interface AppBusPortData {\n connectionId: string;\n role: \"service\" | \"client\";\n serviceName: string;\n targetAppId?: string;\n sourceAppId?: string;\n}\n\n/**\n * Create AppBus state for an app\n */\nexport function createAppBusState(prefix: string = \"appbus\"): AppBusState {\n return {\n registeredServices: new Map(),\n connectedPorts: new Map(),\n pendingRequests: new Map(),\n pendingPortArrivals: new Map(),\n messageIdGenerator: createMessageIdGenerator(prefix),\n };\n}\n\n/**\n * Wait for a port to arrive for a given connection ID\n *\n * @param connectionId The connection ID to wait for\n * @param state AppBus state containing connectedPorts and pendingPortArrivals\n * @param timeoutMs Timeout in milliseconds (default: 5000)\n * @returns Promise that resolves with the port or rejects on timeout\n */\nexport function waitForPort(\n connectionId: string,\n state: AppBusState,\n timeoutMs: number = 5000,\n): Promise<IPCPort> {\n // Check if port is already available\n const existing = state.connectedPorts.get(connectionId);\n if (existing) {\n return Promise.resolve(existing);\n }\n\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n state.pendingPortArrivals.delete(connectionId);\n reject(\n new Error(\n `Port for connection ${connectionId} not received within ${timeoutMs}ms`,\n ),\n );\n }, timeoutMs);\n\n state.pendingPortArrivals.set(connectionId, {\n resolve: (port: IPCPort) => {\n clearTimeout(timeout);\n resolve(port);\n },\n reject: (reason: Error) => {\n clearTimeout(timeout);\n reject(reason);\n },\n });\n });\n}\n\n/**\n * Set up a MessagePort as a client (sends requests, receives responses)\n *\n * @param options Configuration for the client port\n */\nexport function setupClientPort(options: ClientPortOptions): void {\n const {\n port,\n connectionId,\n portStore,\n pendingRequests,\n pendingPortArrivals,\n } = options;\n\n // Store the port for later use\n portStore.set(connectionId, port);\n\n // Resolve any pending port arrivals waiting for this connection\n if (pendingPortArrivals) {\n const pending = pendingPortArrivals.get(connectionId);\n if (pending) {\n pendingPortArrivals.delete(connectionId);\n pending.resolve(port);\n }\n }\n\n // Set up response handler\n port.on(\"message\", (event) => {\n const { type } = event.data;\n\n if (type === \"response\") {\n const { messageId, payload, error } = event.data;\n const pending = pendingRequests.get(messageId);\n if (pending) {\n pendingRequests.delete(messageId);\n if (error) {\n pending.reject(new Error(error));\n } else {\n pending.resolve(payload);\n }\n }\n }\n });\n\n port.start();\n}\n\n/**\n * Create a connection object for a port (Electron IPC style)\n *\n * @param port The IPCPort to wrap\n * @param connectionId The connection ID\n * @param portStore The Map storing ports\n * @param pendingRequests The Map tracking pending requests for outgoing requests\n * @param generateMessageId Function to generate unique message IDs\n * @returns Connection object with send/on/off, request/handle/removeHandler, and close methods\n */\nexport function createPortConnection(\n port: IPCPort,\n connectionId: string,\n portStore: Map<string, IPCPort>,\n pendingRequests: Map<string, PendingRequest>,\n generateMessageId: () => string,\n): AppBusConnection {\n // Method-specific listeners for fire-and-forget messages (send \u2192 on)\n const messageListeners: Map<string, Set<(args: unknown) => void>> = new Map();\n\n // Method-specific handlers for request/response (request \u2192 handle)\n const requestHandlers: Map<\n string,\n (args: unknown) => unknown | Promise<unknown>\n > = new Map();\n\n // Store the port for later use (cleanup, connectivity checks)\n portStore.set(connectionId, port);\n\n // Set up incoming message handler\n port.on(\"message\", (event) => {\n const { type } = event.data;\n\n if (type === \"message\") {\n const { method, payload } = event.data;\n // Fire-and-forget message - dispatch to on() listeners\n const listeners = messageListeners.get(method);\n if (listeners) {\n listeners.forEach((callback) => {\n try {\n callback(payload);\n } catch (err) {\n log.error(`Error in on('${method}') listener:`, err);\n }\n });\n }\n } else if (type === \"request\") {\n const { method, payload, messageId } = event.data;\n // Request expecting response - dispatch to handle() handler\n const handler = requestHandlers.get(method);\n if (handler) {\n try {\n const result = handler(payload);\n Promise.resolve(result)\n .then((response) => {\n port.postMessage({\n type: \"response\",\n messageId,\n payload: response,\n });\n })\n .catch((err) => {\n port.postMessage({\n type: \"response\",\n messageId,\n error: err instanceof Error ? err.message : String(err),\n });\n });\n } catch (err) {\n port.postMessage({\n type: \"response\",\n messageId,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n } else {\n port.postMessage({\n type: \"response\",\n messageId,\n error: `No handler registered for method '${method}'`,\n });\n }\n } else if (type === \"response\") {\n const { messageId, payload } = event.data;\n // Response to our outgoing request\n const pending = pendingRequests.get(messageId);\n if (pending) {\n pendingRequests.delete(messageId);\n if (event.data.error) {\n pending.reject(new Error(event.data.error));\n } else {\n pending.resolve(payload);\n }\n }\n }\n });\n\n port.start();\n\n return {\n // Fire-and-forget messaging\n send: (method: string, args?: unknown) => {\n port.postMessage({ type: \"message\", method, payload: args });\n },\n\n on: (method: string, callback: (args: unknown) => void) => {\n if (typeof callback !== \"function\") {\n throw new Error(\"Callback must be a function\");\n }\n if (!messageListeners.has(method)) {\n messageListeners.set(method, new Set());\n }\n messageListeners.get(method)!.add(callback);\n },\n\n once: (method: string, callback: (args: unknown) => void) => {\n if (typeof callback !== \"function\") {\n throw new Error(\"Callback must be a function\");\n }\n const wrapper = (args: unknown) => {\n // Remove before calling to prevent issues if callback throws\n const listeners = messageListeners.get(method);\n if (listeners) {\n listeners.delete(wrapper);\n if (listeners.size === 0) {\n messageListeners.delete(method);\n }\n }\n callback(args);\n };\n if (!messageListeners.has(method)) {\n messageListeners.set(method, new Set());\n }\n messageListeners.get(method)!.add(wrapper);\n },\n\n off: (method: string, callback: (args: unknown) => void) => {\n const listeners = messageListeners.get(method);\n if (listeners) {\n listeners.delete(callback);\n if (listeners.size === 0) {\n messageListeners.delete(method);\n }\n }\n },\n\n // Request/response\n request: (\n method: string,\n args?: unknown,\n timeout: number = 30000,\n ): Promise<unknown> => {\n return new Promise((resolve, reject) => {\n const messageId = generateMessageId();\n\n // Timeout after specified duration\n const timeoutId = setTimeout(() => {\n if (pendingRequests.has(messageId)) {\n pendingRequests.delete(messageId);\n reject(new Error(`Request '${method}' timed out`));\n }\n }, timeout);\n\n pendingRequests.set(messageId, {\n resolve: (value) => {\n clearTimeout(timeoutId);\n resolve(value);\n },\n reject: (reason) => {\n clearTimeout(timeoutId);\n reject(reason);\n },\n });\n\n port.postMessage({\n type: \"request\",\n method,\n payload: args,\n messageId,\n });\n });\n },\n\n handle: (\n method: string,\n handler: (args: unknown) => unknown | Promise<unknown>,\n ) => {\n if (typeof handler !== \"function\") {\n throw new Error(\"Handler must be a function\");\n }\n if (requestHandlers.has(method)) {\n throw new Error(`Handler already registered for method '${method}'`);\n }\n requestHandlers.set(method, handler);\n },\n\n removeHandler: (method: string) => {\n requestHandlers.delete(method);\n },\n\n // Connection management\n isConnected: () => {\n return portStore.has(connectionId);\n },\n\n onClose: (callback: () => void) => {\n port.on(\"close\", callback);\n },\n\n close: () => {\n portStore.delete(connectionId);\n messageListeners.clear();\n requestHandlers.clear();\n port.close();\n },\n };\n}\n\n/**\n * Handle an incoming AppBus port (can be service or client role)\n *\n * @param port The MessagePort received\n * @param data Connection metadata\n * @param state AppBus state (services, ports, pending requests)\n * @param logPrefix Prefix for log messages\n */\nexport function handleAppBusPort(\n port: IPCPort,\n data: AppBusPortData,\n state: AppBusState,\n): void {\n const { connectionId, role, serviceName, targetAppId, sourceAppId } = data;\n\n if (role === \"service\") {\n // A client is connecting to our service\n log.info(\n `Received connection from ${sourceAppId} for service ${serviceName}`,\n );\n\n const onConnect = state.registeredServices.get(serviceName);\n if (!onConnect) {\n log.error(\n `No onConnect callback registered for service \"${serviceName}\"`,\n );\n return;\n }\n\n // Create a bidirectional AppBusConnection for the service to use\n const connection = createPortConnection(\n port,\n connectionId,\n state.connectedPorts,\n state.pendingRequests,\n state.messageIdGenerator,\n );\n\n // Call the onConnect callback with the connection and client info\n try {\n onConnect(connection, { appId: sourceAppId || \"unknown\" });\n } catch (err) {\n log.error(\n `Error in onConnect callback for service \"${serviceName}\":`,\n err,\n );\n }\n } else if (role === \"client\") {\n // We're connecting to another app's service\n log.info(`Connected to ${targetAppId}/${serviceName}`);\n\n setupClientPort({\n port,\n connectionId,\n portStore: state.connectedPorts,\n pendingRequests: state.pendingRequests,\n pendingPortArrivals: state.pendingPortArrivals,\n });\n }\n}\n/**\n * Handle a port being closed from the other side\n * Triggered by a notification from the main process\n *\n * @param state AppBus state\n * @param connectionId The ID of the closed connection\n */\nexport function handlePortClosed(\n state: AppBusState,\n connectionId: string,\n): void {\n const port = state.connectedPorts.get(connectionId);\n if (port) {\n port.close();\n state.connectedPorts.delete(connectionId);\n }\n}\n", "import type {\n AppBusAPI,\n AppBusConnection,\n CommandArgs,\n CommandName,\n CommandResult,\n EdenAPI,\n EventData,\n EventName,\n ServiceConnectCallback,\n ServiceInfo,\n} from \"@edenapp/types\";\nimport type { AppBusState, IPCPort } from \"./port-channel\";\nimport { createPortConnection, waitForPort } from \"./port-channel\";\n\n/**\n * Interface for sending shell commands to the main process\n */\nexport interface ShellTransport {\n exec<T extends CommandName>(\n command: T,\n args: CommandArgs<T>,\n ): Promise<CommandResult<T>>;\n}\n\nexport type EventSubscriptionCallback = (payload: unknown) => void;\n\n/**\n * Configuration for AppBus API\n */\nexport interface AppBusConfig {\n transport: ShellTransport;\n}\n\n/**\n * Create the EdenAPI object\n */\nexport function createEdenAPI(\n transport: ShellTransport,\n eventSubscriptions: Map<string, Set<EventSubscriptionCallback>>,\n options?: { getLaunchArgs?: () => string[] },\n): EdenAPI {\n return {\n shellCommand: transport.exec,\n\n subscribe: async <T extends EventName>(\n eventName: T,\n callback: (data: EventData<T>) => void,\n ) => {\n if (typeof callback !== \"function\") {\n throw new Error(\"Callback must be a function\");\n }\n\n // Register with backend/main\n await transport.exec(\"event/subscribe\", { eventName });\n\n // Register callback locally\n if (!eventSubscriptions.has(eventName)) {\n eventSubscriptions.set(eventName, new Set());\n }\n eventSubscriptions\n .get(eventName)!\n .add(callback as EventSubscriptionCallback);\n },\n\n unsubscribe: async <T extends EventName>(\n eventName: T,\n callback: (data: EventData<T>) => void,\n ) => {\n const callbacks = eventSubscriptions.get(eventName);\n if (callbacks) {\n callbacks.delete(callback as EventSubscriptionCallback);\n\n // If no more callbacks, unregister from backend/main\n if (callbacks.size === 0) {\n eventSubscriptions.delete(eventName);\n await transport.exec(\"event/unsubscribe\", { eventName });\n }\n }\n },\n\n isEventSupported: (eventName: string) => {\n return transport.exec(\"event/exists\", { eventName });\n },\n\n getLaunchArgs: (): string[] => {\n if (options?.getLaunchArgs) {\n return options.getLaunchArgs();\n }\n return [];\n },\n };\n}\n\n/**\n * Create the AppBusAPI object\n */\nexport function createAppBusAPI(\n config: AppBusConfig,\n state: AppBusState,\n): AppBusAPI {\n const { transport } = config;\n const {\n registeredServices,\n connectedPorts,\n pendingRequests,\n messageIdGenerator,\n } = state;\n\n return {\n exposeService: async (\n serviceName: string,\n onConnect: ServiceConnectCallback,\n options?: {\n description?: string;\n allowedClients?: string[];\n },\n ): Promise<{ success: boolean; error?: string }> => {\n if (typeof onConnect !== \"function\") {\n throw new Error(\"onConnect callback must be a function\");\n }\n\n // Store the onConnect callback locally\n // When a client connects, handleAppBusPort will call this with the connection\n registeredServices.set(serviceName, onConnect);\n\n // Register with main process\n const result = await transport.exec(\"appbus/register\", {\n serviceName,\n description: options?.description,\n allowedClients: options?.allowedClients,\n });\n\n if (!result.success) {\n registeredServices.delete(serviceName);\n }\n\n return result;\n },\n\n unexposeService: async (\n serviceName: string,\n ): Promise<{ success: boolean }> => {\n registeredServices.delete(serviceName);\n return transport.exec(\"appbus/unregister\", {\n serviceName,\n });\n },\n\n connect: async (\n targetAppId: string,\n serviceName: string,\n ): Promise<AppBusConnection | { error: string }> => {\n // Request connection through shell command\n const result = await transport.exec(\"appbus/connect\", {\n targetAppId,\n serviceName,\n });\n\n if (!result.success) {\n return { error: result.error || \"Connection failed\" };\n }\n\n const { connectionId } = result;\n if (!connectionId) {\n return { error: \"Connection ID was not provided\" };\n }\n\n // Wait for the port to be received via handleAppBusPort\n let port: IPCPort;\n try {\n port = await waitForPort(connectionId, state, 5000);\n } catch (err) {\n return {\n error:\n err instanceof Error ? err.message : \"MessagePort not received\",\n };\n }\n\n // Use shared utility to create connection object\n return createPortConnection(\n port,\n connectionId,\n connectedPorts,\n pendingRequests,\n messageIdGenerator,\n );\n },\n\n listServices: async (): Promise<{ services: ServiceInfo[] }> => {\n return transport.exec(\"appbus/list\", {});\n },\n\n listServicesByApp: async (\n appId: string,\n ): Promise<{ services: ServiceInfo[] }> => {\n return transport.exec(\"appbus/list-by-app\", { appId });\n },\n };\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["import_electron", "LOG_LEVEL_ORDER", "parseLogLevel", "value", "normalized", "isLogLevelEnabled", "level", "minLevel", "runtimeGlobal", "globalContext", "config", "resolveDefaultConfig", "baseConsole", "setLogContext", "next", "globalContext", "createLogger", "context", "args", "emit", "log", "emit", "record", "level", "isLogLevelEnabled", "config", "timestamp", "context", "mergeContext", "callsite", "captureCallsite", "prefix", "formatPrefix", "target", "consoleForLevel", "getBaseContext", "envAppId", "getEnvValue", "globalAppId", "runtimeGlobal", "detectProcessType", "globalContext", "processObj", "type", "resolveDefaultConfig", "envLevel", "parseLogLevel", "envFormat", "envPathMode", "isTest", "isRenderer", "getEnvBool", "useLiveConsole", "baseConsole", "_a", "_b", "_c", "_d", "_e", "parts", "file", "shortenPath", "err", "v8Error", "stack", "lines", "line", "trimmed", "match", "lineNumber", "columnNumber", "path", "mode", "normalized", "cwd", "normalizedPath", "distIndex", "sdkIndex", "segments", "key", "globalValue", "fallback", "value", "wrapDOMPort", "port", "messageListeners", "closeListeners", "on", "event", "listener", "messageListener", "wrapper", "messageEvent", "off", "message", "e", "log", "createMessageIdGenerator", "prefix", "counter", "createAppBusState", "waitForPort", "connectionId", "state", "timeoutMs", "existing", "resolve", "reject", "timeout", "port", "reason", "setupClientPort", "options", "portStore", "pendingRequests", "pendingPortArrivals", "pending", "event", "type", "messageId", "payload", "error", "createPortConnection", "generateMessageId", "messageListeners", "requestHandlers", "method", "listeners", "callback", "err", "log", "handler", "result", "response", "args", "wrapper", "timeoutId", "value", "handleAppBusPort", "data", "role", "serviceName", "targetAppId", "sourceAppId", "onConnect", "connection", "handlePortClosed", "createEdenAPI", "transport", "eventSubscriptions", "options", "eventName", "callback", "callbacks", "createAppBusAPI", "config", "state", "registeredServices", "connectedPorts", "pendingRequests", "messageIdGenerator", "serviceName", "onConnect", "result", "targetAppId", "connectionId", "port", "waitForPort", "err", "createPortConnection", "appId", "appId", "backendPort", "backendConnection", "pendingBackendRequests", "generateBackendMessageId", "createMessageIdGenerator", "eventSubscriptions", "appIdArg", "arg", "setLogContext", "log", "launchArgs", "launchArgsArg", "jsonStr", "event", "port", "wrappedPort", "wrapDOMPort", "createPortConnection", "_event", "message", "type", "payload", "callbacks", "callback", "err", "shellTransport", "command", "args", "edenAPI", "createEdenAPI", "appBusState", "createAppBusState", "data", "handleAppBusPort", "handlePortClosed", "createAppBusAPI", "setupZoomPrevention"]
7
7
  }
@@ -1,4 +1,4 @@
1
- "use strict";var E={trace:10,debug:20,info:30,warn:40,error:50,fatal:60};function B(e){if(!e)return null;let n=e.trim().toLowerCase();return n in E?n:null}function N(e,n){return E[e]>=E[n]}var b={},L=X(),I={debug:console.debug.bind(console),warn:console.warn.bind(console),error:console.error.bind(console),info:console.log.bind(console)};function A(e){b={...b,...e}}function $(e){return{trace:(...n)=>P({level:"trace",args:n,context:e}),debug:(...n)=>P({level:"debug",args:n,context:e}),info:(...n)=>P({level:"info",args:n,context:e}),warn:(...n)=>P({level:"warn",args:n,context:e}),error:(...n)=>P({level:"error",args:n,context:e}),fatal:(...n)=>P({level:"fatal",args:n,context:e})}}var d=$();function v(e){P({level:e.level,args:e.args,context:e.context,callsite:e.callsite,skipCallsite:!0})}function P(e){let{level:n}=e;if(!N(n,L.minLevel))return;let t=e.timestamp??Date.now(),r=Y(e.context),a=e.callsite??(L.includeCallsite&&!e.skipCallsite?F():void 0),o=L.format==="pretty"?ee({level:n,timestamp:t,context:r,callsite:a}):"",c=Z(n);o?c(o,...e.args):c(...e.args)}function Y(e){return{...Q(),...e}}function Q(){let e=y("EDEN_APP_ID"),n=globalThis.__EDEN_APP_ID__;return{processType:D(),appId:b.appId??e??n,viewId:b.viewId,webContentsId:b.webContentsId,source:b.source}}function D(){let e=globalThis.process;if(e){let n=e.type;if(n==="browser")return"main";if(n==="utility")return"backend";if(n)return n}return typeof globalThis.window<"u"?"renderer":"node"}function X(){let e=B(y("EDEN_LOG_LEVEL")),n=y("EDEN_LOG_FORMAT"),t=y("EDEN_LOG_PATH"),r=y("NODE_ENV")==="test",a=D()==="renderer";return{minLevel:e??"debug",format:n??(r||a?"raw":"pretty"),includeTimestamp:_("EDEN_LOG_TIMESTAMP",!r),includeCallsite:_("EDEN_LOG_CALLSITE",!r&&!a),pathMode:t??"short"}}function Z(e){let n=y("NODE_ENV")==="test";switch(e){case"trace":case"debug":return n?console.debug.bind(console):I.debug;case"warn":return n?console.warn.bind(console):I.warn;case"error":case"fatal":return n?console.error.bind(console):I.error;case"info":default:return n?console.log.bind(console):I.info}}function ee(e){var t,r,a,o,c;let n=[];if(L.includeTimestamp&&n.push(new Date(e.timestamp).toISOString()),n.push(e.level.toUpperCase()),(t=e.context)!=null&&t.processType&&n.push(e.context.processType),(r=e.context)!=null&&r.appId&&n.push(`app=${e.context.appId}`),((a=e.context)==null?void 0:a.viewId)!==void 0&&n.push(`view=${e.context.viewId}`),((o=e.context)==null?void 0:o.webContentsId)!==void 0&&n.push(`wc=${e.context.webContentsId}`),(c=e.context)!=null&&c.source&&n.push(e.context.source),e.callsite){let s=ne(e.callsite.file,L.pathMode);n.push(`${s}:${e.callsite.line}`)}return`[${n.join("] [")}]`}function F(){var r;let e=new Error;(r=Error.captureStackTrace)==null||r.call(Error,e,F);let n=e.stack;if(!n)return;let t=n.split(`
2
- `).slice(1);for(let a of t){let o=a.trim();if(!o||o.includes("/logging/")||o.includes("\\logging\\"))continue;let c=o.match(/\(([^)]+):(\d+):(\d+)\)$/)??o.match(/at\s+([^\s]+):(\d+):(\d+)$/);if(!c)continue;let s=c[1],i=Number(c[2]),l=Number(c[3]);if(!(!s||Number.isNaN(i)))return{file:s,line:i,column:Number.isNaN(l)?void 0:l}}}function ne(e,n){if(n==="full")return e;if(n==="file")return e.replace(/^[^:]*[\\/]/,"")||e;let t=e;t.startsWith("file://")&&(t=t.slice(7));try{let s=globalThis.process;if(s!=null&&s.cwd){let i=s.cwd();if(t.startsWith(i))return t.slice(i.length+1)}}catch{}let r=t.replace(/\\/g,"/"),a=r.lastIndexOf("/dist/");if(a>=0)return r.slice(a+1);let o=r.lastIndexOf("/sdk/");if(o>=0)return r.slice(o+1);let c=r.split("/").filter(Boolean);return c.length>=2?c.slice(-2).join("/"):r}function y(e){var r;let n=globalThis.process;if((r=n==null?void 0:n.env)!=null&&r[e])return n.env[e];let t=globalThis[e];if(typeof t=="string")return t}function _(e,n){let t=y(e);if(t===void 0)return n;let r=t.trim().toLowerCase();return["1","true","yes","on"].includes(r)?!0:["0","false","no","off"].includes(r)?!1:n}function M(e="msg"){let n=0;return()=>`${e}-${Date.now()}-${++n}`}function R(e="appbus"){return{registeredServices:new Map,connectedPorts:new Map,pendingRequests:new Map,pendingPortArrivals:new Map,messageIdGenerator:M(e)}}function O(e,n,t=5e3){let r=n.connectedPorts.get(e);return r?Promise.resolve(r):new Promise((a,o)=>{let c=setTimeout(()=>{n.pendingPortArrivals.delete(e),o(new Error(`Port for connection ${e} not received within ${t}ms`))},t);n.pendingPortArrivals.set(e,{resolve:s=>{clearTimeout(c),a(s)},reject:s=>{clearTimeout(c),o(s)}})})}function re(e){let{port:n,connectionId:t,portStore:r,pendingRequests:a,pendingPortArrivals:o}=e;if(r.set(t,n),o){let c=o.get(t);c&&(o.delete(t),c.resolve(n))}n.on("message",c=>{let{type:s,messageId:i,payload:l,error:p}=c.data;if(s==="response"&&i){let g=a.get(i);g&&(a.delete(i),p?g.reject(new Error(p)):g.resolve(l))}}),n.start()}function x(e,n,t,r,a){let o=new Map,c=new Map;return t.set(n,e),e.on("message",s=>{let{type:i,method:l,payload:p,messageId:g}=s.data;if(i==="message"){let u=o.get(l);u&&u.forEach(f=>{try{f(p)}catch(m){d.error(`Error in on('${l}') listener:`,m)}})}else if(i==="request"){let u=c.get(l);if(u)try{let f=u(p);Promise.resolve(f).then(m=>{e.postMessage({type:"response",messageId:g,payload:m})}).catch(m=>{e.postMessage({type:"response",messageId:g,error:m instanceof Error?m.message:String(m)})})}catch(f){e.postMessage({type:"response",messageId:g,error:f instanceof Error?f.message:String(f)})}else e.postMessage({type:"response",messageId:g,error:`No handler registered for method '${l}'`})}else if(i==="response"&&g){let u=r.get(g);u&&(r.delete(g),s.data.error?u.reject(new Error(s.data.error)):u.resolve(p))}}),e.start(),{send:(s,i)=>{e.postMessage({type:"message",method:s,payload:i})},on:(s,i)=>{if(typeof i!="function")throw new Error("Callback must be a function");o.has(s)||o.set(s,new Set),o.get(s).add(i)},once:(s,i)=>{if(typeof i!="function")throw new Error("Callback must be a function");let l=p=>{let g=o.get(s);g&&(g.delete(l),g.size===0&&o.delete(s)),i(p)};o.has(s)||o.set(s,new Set),o.get(s).add(l)},off:(s,i)=>{let l=o.get(s);l&&(l.delete(i),l.size===0&&o.delete(s))},request:(s,i,l=3e4)=>new Promise((p,g)=>{let u=a(),f=setTimeout(()=>{r.has(u)&&(r.delete(u),g(new Error(`Request '${s}' timed out`)))},l);r.set(u,{resolve:m=>{clearTimeout(f),p(m)},reject:m=>{clearTimeout(f),g(m)}}),e.postMessage({type:"request",method:s,payload:i,messageId:u})}),handle:(s,i)=>{if(typeof i!="function")throw new Error("Handler must be a function");if(c.has(s))throw new Error(`Handler already registered for method '${s}'`);c.set(s,i)},removeHandler:s=>{c.delete(s)},isConnected:()=>t.has(n),onClose:s=>{e.on("close",s)},close:()=>{t.delete(n),o.clear(),c.clear(),e.close()}}}function q(e,n,t){let{connectionId:r,role:a,serviceName:o,targetAppId:c,sourceAppId:s}=n;if(a==="service"){d.info(`Received connection from ${s} for service ${o}`);let i=t.registeredServices.get(o);if(!i){d.error(`No onConnect callback registered for service "${o}"`);return}let l=x(e,r,t.connectedPorts,t.pendingRequests,t.messageIdGenerator);try{i(l,{appId:s||"unknown"})}catch(p){d.error(`Error in onConnect callback for service "${o}":`,p)}}else a==="client"&&(d.info(`Connected to ${c}/${o}`),re({port:e,connectionId:r,portStore:t.connectedPorts,pendingRequests:t.pendingRequests,pendingPortArrivals:t.pendingPortArrivals}))}function G(e,n){let t=e.connectedPorts.get(n);t&&(t.close(),e.connectedPorts.delete(n))}function j(e,n,t){return{shellCommand:(r,a)=>e.exec(r,a),subscribe:async(r,a)=>{if(typeof a!="function")throw new Error("Callback must be a function");await e.exec("event/subscribe",{eventName:r}),n.has(r)||n.set(r,new Set),n.get(r).add(a)},unsubscribe:async(r,a)=>{let o=n.get(r);o&&(o.delete(a),o.size===0&&(n.delete(r),await e.exec("event/unsubscribe",{eventName:r})))},isEventSupported:r=>e.exec("event/exists",{eventName:r}),getLaunchArgs:()=>t!=null&&t.getLaunchArgs?t.getLaunchArgs():[]}}function z(e,n){let{transport:t,isBackend:r}=e,{registeredServices:a,connectedPorts:o,pendingRequests:c,messageIdGenerator:s}=n;return{exposeService:async(i,l,p)=>{if(typeof l!="function")throw new Error("onConnect callback must be a function");a.set(i,l);let g=await t.exec("appbus/register",{serviceName:i,description:p==null?void 0:p.description,allowedClients:p==null?void 0:p.allowedClients,isBackend:r});return g.success||a.delete(i),g},unexposeService:async i=>(a.delete(i),t.exec("appbus/unregister",{serviceName:i})),connect:async(i,l)=>{let p=await t.exec("appbus/connect",{targetAppId:i,serviceName:l,isBackend:r});if(!p.success)return{error:p.error||"Connection failed"};let{connectionId:g}=p,u;try{u=await O(g,n,5e3)}catch(f){return{error:f instanceof Error?f.message:"MessagePort not received"}}return x(u,g,o,c,s)},listServices:async()=>t.exec("appbus/list",{}),listServicesByApp:async i=>t.exec("appbus/list-by-app",{appId:i})}}var S=process.env.EDEN_APP_ID,V=process.env.EDEN_BACKEND_ENTRY,oe=JSON.parse(process.env.EDEN_MANIFEST||"{}");A({appId:S});var C=()=>{var r;let e=new Error;(r=Error.captureStackTrace)==null||r.call(Error,e,C);let n=e.stack;if(!n)return;let t=n.split(`
3
- `).slice(1);for(let a of t){let o=a.trim();if(!o||o.includes("backend-preload")||o.includes("/logging/")||o.includes("\\logging\\"))continue;let c=o.match(/\(([^)]+):(\d+):(\d+)\)$/)??o.match(/at\s+([^\s]+):(\d+):(\d+)$/);if(!c)continue;let s=c[1],i=Number(c[2]),l=Number(c[3]);if(!(!s||Number.isNaN(i)))return{file:s,line:i,column:Number.isNaN(l)?void 0:l}}};console.log=(...e)=>v({level:"info",args:e,callsite:C()});console.info=(...e)=>v({level:"info",args:e,callsite:C()});console.warn=(...e)=>v({level:"warn",args:e,callsite:C()});console.error=(...e)=>v({level:"error",args:e,callsite:C()});console.debug=(...e)=>v({level:"debug",args:e,callsite:C()});console.trace=(...e)=>v({level:"trace",args:e,callsite:C()});var J=[],H=process.argv.find(e=>e.startsWith("--launch-args="));if(H)try{let e=H.split("=").slice(1).join("=");J=JSON.parse(e)}catch(e){d.error("Failed to parse launch args:",e)}var se=null,w=process.parentPort;w||(d.error("Not running in utility process - parentPort not available"),process.exit(1));var K=new Map,h=new Map,ie=0,T=R("backend-appbus");function ae(){return`cmd-${S}-${Date.now()}-${++ie}`}async function ce(e,n){return new Promise((t,r)=>{let a=ae(),o=setTimeout(()=>{h.delete(a),r(new Error(`Shell command '${e}' timed out`))},3e4);h.set(a,{resolve:c=>{clearTimeout(o),t(c)},reject:c=>{clearTimeout(o),r(c)}}),w.postMessage({type:"shell-command",commandId:a,command:e,args:{...n,_callerAppId:S}})})}var U={exec:(e,n)=>ce(e,n)},le=j(U,K,{getLaunchArgs:()=>J}),ge=z({transport:U,isBackend:!0},T),k=null,W,pe=!!((W=oe.frontend)!=null&&W.entry);w.on("message",e=>{let n=e.data;if(n.type==="shell-command-response"){let t=h.get(n.commandId);t&&(h.delete(n.commandId),n.error?t.reject(new Error(n.error)):t.resolve(n.result))}else if(n.type==="shell-event"){let{eventName:t,payload:r}=n,a=K.get(t);a&&a.forEach(o=>{try{o(r)}catch(c){d.error(`Error in event callback for ${t}:`,c)}})}else if(n.type==="appbus-port"){let[t]=e.ports;t&&de(t,n)}else n.type==="appbus-port-closed"?G(T,n.connectionId):n.type==="shutdown"&&(d.info("Shutdown requested"),process.exit(0))});function ue(e){let n=e;k=x(n,"__frontend__",new Map([["__frontend__",n]]),new Map,M("backend-to-frontend"))}function de(e,n){let t=e;q(t,n,T)}async function fe(){try{d.info(`Loading backend entry: ${V}`),await import(V),d.info("Backend loaded successfully"),w.postMessage({type:"backend-ready"})}catch(e){d.error("Failed to load backend:",e),w.postMessage({type:"backend-error",error:e instanceof Error?e.message:String(e)}),process.exit(1)}}async function me(){pe&&await new Promise(e=>{let n=t=>{if(t.data.type==="init-port"){let[r]=t.ports;r&&(se=r,ue(r),d.info("Frontend port initialized")),w.removeListener("message",n),e()}};w.on("message",n)}),await fe()}function ve(){if(!k)throw new Error("AppAPI not available: This app has no frontend connection. Ensure 'frontend.entry' is defined in manifest.json if you need frontend communication.");return k}globalThis.worker={edenAPI:le,appBus:ge,getAppAPI:ve};me();
1
+ "use strict";var k={trace:10,debug:20,info:30,warn:40,error:50,fatal:60};function _(e){if(!e)return null;let n=e.trim().toLowerCase();return n in k?n:null}function B(e,n){return k[e]>=k[n]}var E=globalThis,I={},y=Z(),x={debug:console.debug.bind(console),warn:console.warn.bind(console),error:console.error.bind(console),info:console.log.bind(console)};function h(e){I={...I,...e}}function D(e){return{trace:(...n)=>P({level:"trace",args:n,context:e}),debug:(...n)=>P({level:"debug",args:n,context:e}),info:(...n)=>P({level:"info",args:n,context:e}),warn:(...n)=>P({level:"warn",args:n,context:e}),error:(...n)=>P({level:"error",args:n,context:e}),fatal:(...n)=>P({level:"fatal",args:n,context:e})}}var u=D();function v(e){P({level:e.level,args:e.args,context:e.context,callsite:e.callsite,skipCallsite:!0})}function P(e){let{level:n}=e;if(!B(n,y.minLevel))return;let t=e.timestamp??Date.now(),r=Q(e.context),a=e.callsite??(y.includeCallsite&&!e.skipCallsite?O():void 0),s=y.format==="pretty"?ne({level:n,timestamp:t,context:r,callsite:a}):"",i=ee(n);s?i(s,...e.args):i(...e.args)}function Q(e){return{...X(),...e}}function X(){let e=w("EDEN_APP_ID"),n=E.__EDEN_APP_ID__;return{processType:$(),appId:I.appId??e??n,viewId:I.viewId,webContentsId:I.webContentsId,source:I.source}}function $(){let e=E.process;if(e){let n=e.type;if(n==="browser")return"main";if(n==="utility")return"backend";if(n)return n}return typeof E.window<"u"?"renderer":"node"}function Z(){let e=_(w("EDEN_LOG_LEVEL")),n=w("EDEN_LOG_FORMAT"),t=w("EDEN_LOG_PATH"),r=w("NODE_ENV")==="test",a=$()==="renderer";return{minLevel:e??"debug",format:n??(r||a?"raw":"pretty"),includeTimestamp:R("EDEN_LOG_TIMESTAMP",!r),includeCallsite:R("EDEN_LOG_CALLSITE",!r&&!a),pathMode:t??"short"}}function ee(e){let n=w("NODE_ENV")==="test";switch(e){case"trace":case"debug":return n?console.debug.bind(console):x.debug;case"warn":return n?console.warn.bind(console):x.warn;case"error":case"fatal":return n?console.error.bind(console):x.error;case"info":default:return n?console.log.bind(console):x.info}}function ne(e){var t,r,a,s,i;let n=[];if(y.includeTimestamp&&n.push(new Date(e.timestamp).toISOString()),n.push(e.level.toUpperCase()),(t=e.context)!=null&&t.processType&&n.push(e.context.processType),(r=e.context)!=null&&r.appId&&n.push(`app=${e.context.appId}`),((a=e.context)==null?void 0:a.viewId)!==void 0&&n.push(`view=${e.context.viewId}`),((s=e.context)==null?void 0:s.webContentsId)!==void 0&&n.push(`wc=${e.context.webContentsId}`),(i=e.context)!=null&&i.source&&n.push(e.context.source),e.callsite){let o=te(e.callsite.file,y.pathMode);n.push(`${o}:${e.callsite.line}`)}return`[${n.join("] [")}]`}function O(){var a;let e=new Error,n=Error;(a=n.captureStackTrace)==null||a.call(n,e,O);let t=e.stack;if(!t)return;let r=t.split(`
2
+ `).slice(1);for(let s of r){let i=s.trim();if(!i||i.includes("/logging/")||i.includes("\\logging\\"))continue;let o=i.match(/\(([^)]+):(\d+):(\d+)\)$/)??i.match(/at\s+([^\s]+):(\d+):(\d+)$/);if(!o)continue;let c=o[1],l=Number(o[2]),d=Number(o[3]);if(!(!c||Number.isNaN(l)))return{file:c,line:l,column:Number.isNaN(d)?void 0:d}}}function te(e,n){if(n==="full")return e;if(n==="file")return e.replace(/^[^:]*[\\/]/,"")||e;let t=e;t.startsWith("file://")&&(t=t.slice(7));try{let o=E.process;if(o!=null&&o.cwd){let c=o.cwd();if(t.startsWith(c))return t.slice(c.length+1)}}catch{}let r=t.replace(/\\/g,"/"),a=r.lastIndexOf("/dist/");if(a>=0)return r.slice(a+1);let s=r.lastIndexOf("/sdk/");if(s>=0)return r.slice(s+1);let i=r.split("/").filter(Boolean);return i.length>=2?i.slice(-2).join("/"):r}function w(e){var r;let n=E.process;if((r=n==null?void 0:n.env)!=null&&r[e])return n.env[e];let t=E[e];if(typeof t=="string")return t}function R(e,n){let t=w(e);if(t===void 0)return n;let r=t.trim().toLowerCase();return["1","true","yes","on"].includes(r)?!0:["0","false","no","off"].includes(r)?!1:n}function M(e="msg"){let n=0;return()=>`${e}-${Date.now()}-${++n}`}function F(e="appbus"){return{registeredServices:new Map,connectedPorts:new Map,pendingRequests:new Map,pendingPortArrivals:new Map,messageIdGenerator:M(e)}}function G(e,n,t=5e3){let r=n.connectedPorts.get(e);return r?Promise.resolve(r):new Promise((a,s)=>{let i=setTimeout(()=>{n.pendingPortArrivals.delete(e),s(new Error(`Port for connection ${e} not received within ${t}ms`))},t);n.pendingPortArrivals.set(e,{resolve:o=>{clearTimeout(i),a(o)},reject:o=>{clearTimeout(i),s(o)}})})}function re(e){let{port:n,connectionId:t,portStore:r,pendingRequests:a,pendingPortArrivals:s}=e;if(r.set(t,n),s){let i=s.get(t);i&&(s.delete(t),i.resolve(n))}n.on("message",i=>{let{type:o}=i.data;if(o==="response"){let{messageId:c,payload:l,error:d}=i.data,p=a.get(c);p&&(a.delete(c),d?p.reject(new Error(d)):p.resolve(l))}}),n.start()}function L(e,n,t,r,a){let s=new Map,i=new Map;return t.set(n,e),e.on("message",o=>{let{type:c}=o.data;if(c==="message"){let{method:l,payload:d}=o.data,p=s.get(l);p&&p.forEach(g=>{try{g(d)}catch(f){u.error(`Error in on('${l}') listener:`,f)}})}else if(c==="request"){let{method:l,payload:d,messageId:p}=o.data,g=i.get(l);if(g)try{let f=g(d);Promise.resolve(f).then(m=>{e.postMessage({type:"response",messageId:p,payload:m})}).catch(m=>{e.postMessage({type:"response",messageId:p,error:m instanceof Error?m.message:String(m)})})}catch(f){e.postMessage({type:"response",messageId:p,error:f instanceof Error?f.message:String(f)})}else e.postMessage({type:"response",messageId:p,error:`No handler registered for method '${l}'`})}else if(c==="response"){let{messageId:l,payload:d}=o.data,p=r.get(l);p&&(r.delete(l),o.data.error?p.reject(new Error(o.data.error)):p.resolve(d))}}),e.start(),{send:(o,c)=>{e.postMessage({type:"message",method:o,payload:c})},on:(o,c)=>{if(typeof c!="function")throw new Error("Callback must be a function");s.has(o)||s.set(o,new Set),s.get(o).add(c)},once:(o,c)=>{if(typeof c!="function")throw new Error("Callback must be a function");let l=d=>{let p=s.get(o);p&&(p.delete(l),p.size===0&&s.delete(o)),c(d)};s.has(o)||s.set(o,new Set),s.get(o).add(l)},off:(o,c)=>{let l=s.get(o);l&&(l.delete(c),l.size===0&&s.delete(o))},request:(o,c,l=3e4)=>new Promise((d,p)=>{let g=a(),f=setTimeout(()=>{r.has(g)&&(r.delete(g),p(new Error(`Request '${o}' timed out`)))},l);r.set(g,{resolve:m=>{clearTimeout(f),d(m)},reject:m=>{clearTimeout(f),p(m)}}),e.postMessage({type:"request",method:o,payload:c,messageId:g})}),handle:(o,c)=>{if(typeof c!="function")throw new Error("Handler must be a function");if(i.has(o))throw new Error(`Handler already registered for method '${o}'`);i.set(o,c)},removeHandler:o=>{i.delete(o)},isConnected:()=>t.has(n),onClose:o=>{e.on("close",o)},close:()=>{t.delete(n),s.clear(),i.clear(),e.close()}}}function q(e,n,t){let{connectionId:r,role:a,serviceName:s,targetAppId:i,sourceAppId:o}=n;if(a==="service"){u.info(`Received connection from ${o} for service ${s}`);let c=t.registeredServices.get(s);if(!c){u.error(`No onConnect callback registered for service "${s}"`);return}let l=L(e,r,t.connectedPorts,t.pendingRequests,t.messageIdGenerator);try{c(l,{appId:o||"unknown"})}catch(d){u.error(`Error in onConnect callback for service "${s}":`,d)}}else a==="client"&&(u.info(`Connected to ${i}/${s}`),re({port:e,connectionId:r,portStore:t.connectedPorts,pendingRequests:t.pendingRequests,pendingPortArrivals:t.pendingPortArrivals}))}function j(e,n){let t=e.connectedPorts.get(n);t&&(t.close(),e.connectedPorts.delete(n))}function z(e,n,t){return{shellCommand:e.exec,subscribe:async(r,a)=>{if(typeof a!="function")throw new Error("Callback must be a function");await e.exec("event/subscribe",{eventName:r}),n.has(r)||n.set(r,new Set),n.get(r).add(a)},unsubscribe:async(r,a)=>{let s=n.get(r);s&&(s.delete(a),s.size===0&&(n.delete(r),await e.exec("event/unsubscribe",{eventName:r})))},isEventSupported:r=>e.exec("event/exists",{eventName:r}),getLaunchArgs:()=>t!=null&&t.getLaunchArgs?t.getLaunchArgs():[]}}function V(e,n){let{transport:t}=e,{registeredServices:r,connectedPorts:a,pendingRequests:s,messageIdGenerator:i}=n;return{exposeService:async(o,c,l)=>{if(typeof c!="function")throw new Error("onConnect callback must be a function");r.set(o,c);let d=await t.exec("appbus/register",{serviceName:o,description:l==null?void 0:l.description,allowedClients:l==null?void 0:l.allowedClients});return d.success||r.delete(o),d},unexposeService:async o=>(r.delete(o),t.exec("appbus/unregister",{serviceName:o})),connect:async(o,c)=>{let l=await t.exec("appbus/connect",{targetAppId:o,serviceName:c});if(!l.success)return{error:l.error||"Connection failed"};let{connectionId:d}=l;if(!d)return{error:"Connection ID was not provided"};let p;try{p=await G(d,n,5e3)}catch(g){return{error:g instanceof Error?g.message:"MessagePort not received"}}return L(p,d,a,s,i)},listServices:async()=>t.exec("appbus/list",{}),listServicesByApp:async o=>t.exec("appbus/list-by-app",{appId:o})}}var T=process.env.EDEN_APP_ID,H=process.env.EDEN_BACKEND_ENTRY,se=JSON.parse(process.env.EDEN_MANIFEST||"{}");h({appId:T});var b=()=>{var r;let e=new Error;(r=Error.captureStackTrace)==null||r.call(Error,e,b);let n=e.stack;if(!n)return;let t=n.split(`
3
+ `).slice(1);for(let a of t){let s=a.trim();if(!s||s.includes("backend-preload")||s.includes("/logging/")||s.includes("\\logging\\"))continue;let i=s.match(/\(([^)]+):(\d+):(\d+)\)$/)??s.match(/at\s+([^\s]+):(\d+):(\d+)$/);if(!i)continue;let o=i[1],c=Number(i[2]),l=Number(i[3]);if(!(!o||Number.isNaN(c)))return{file:o,line:c,column:Number.isNaN(l)?void 0:l}}};console.log=(...e)=>v({level:"info",args:e,callsite:b()});console.info=(...e)=>v({level:"info",args:e,callsite:b()});console.warn=(...e)=>v({level:"warn",args:e,callsite:b()});console.error=(...e)=>v({level:"error",args:e,callsite:b()});console.debug=(...e)=>v({level:"debug",args:e,callsite:b()});console.trace=(...e)=>v({level:"trace",args:e,callsite:b()});var K=[],W=process.argv.find(e=>e.startsWith("--launch-args="));if(W)try{let e=W.split("=").slice(1).join("=");K=JSON.parse(e)}catch(e){u.error("Failed to parse launch args:",e)}var ie=null,C=process.parentPort;C||(u.error("Not running in utility process - parentPort not available"),process.exit(1));var U=new Map,A=new Map,ae=0,N=F("backend-appbus");function ce(){return`cmd-${T}-${Date.now()}-${++ae}`}function le(e){return e&&typeof e=="object"&&!Array.isArray(e)?{...e}:{}}function pe(e,n){return new Promise((t,r)=>{let a=ce(),s=setTimeout(()=>{A.delete(a),r(new Error(`Shell command '${e}' timed out`))},3e4);A.set(a,{resolve:i=>{clearTimeout(s),t(i)},reject:i=>{clearTimeout(s),r(i)}}),C.postMessage({type:"shell-command",commandId:a,command:e,args:{...le(n),_callerAppId:T}})})}var Y={exec:pe},de=z(Y,U,{getLaunchArgs:()=>K}),ue=V({transport:Y},N),S=null,J,ge=!!((J=se.frontend)!=null&&J.entry);C.on("message",e=>{let n=e.data;if(n.type==="shell-command-response"){if(!n.commandId)return;let t=A.get(n.commandId);t&&(A.delete(n.commandId),n.error?t.reject(new Error(n.error)):t.resolve(n.result))}else if(n.type==="shell-event"){if(!n.eventName)return;let{eventName:t,payload:r}=n,a=U.get(t);a&&a.forEach(s=>{try{s(r)}catch(i){u.error(`Error in event callback for ${t}:`,i)}})}else if(n.type==="appbus-port"){let[t]=e.ports;t&&n.connectionId&&n.role&&n.serviceName&&me(t,{connectionId:n.connectionId,role:n.role,serviceName:n.serviceName,targetAppId:n.targetAppId,sourceAppId:n.sourceAppId})}else if(n.type==="appbus-port-closed"){if(!n.connectionId)return;j(N,n.connectionId)}else n.type==="shutdown"&&(u.info("Shutdown requested"),process.exit(0))});function fe(e){let n=e;S=L(n,"__frontend__",new Map([["__frontend__",n]]),new Map,M("backend-to-frontend"))}function me(e,n){let t=e;q(t,n,N)}async function ve(){try{u.info(`Loading backend entry: ${H}`),await import(H),u.info("Backend loaded successfully"),C.postMessage({type:"backend-ready"})}catch(e){u.error("Failed to load backend:",e),C.postMessage({type:"backend-error",error:e instanceof Error?e.message:String(e)}),process.exit(1)}}async function Pe(){ge&&await new Promise(e=>{let n=t=>{if(t.data.type==="init-port"){let[r]=t.ports;r&&(ie=r,fe(r),u.info("Frontend port initialized")),C.removeListener("message",n),e()}};C.on("message",n)}),await ve()}function we(){if(!S)throw new Error("AppAPI not available: This app has no frontend connection. Ensure 'frontend.entry' is defined in manifest.json if you need frontend communication.");return S}globalThis.worker={edenAPI:de,appBus:ue,getAppAPI:we};Pe();
4
4
  //# sourceMappingURL=backend-preload.js.map