@edenapp/sdk 0.6.0 → 0.6.3
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.
- package/dist/app-frame/frame-injector.js +6 -6
- package/dist/app-frame/frame-injector.js.map +3 -3
- package/dist/app-runtime/app-preload.js +2 -2
- package/dist/app-runtime/app-preload.js.map +3 -3
- package/dist/app-runtime/backend-preload.js +3 -3
- package/dist/app-runtime/backend-preload.js.map +3 -3
- package/dist/apps/prebuilt/com.eden.calculator/CHANGELOG.md +14 -0
- package/dist/apps/prebuilt/com.eden.calculator/package.json +1 -1
- package/dist/apps/prebuilt/com.eden.context-menu/dist/assets/{index-PflHQ4jS.css → index-B3l0_BgM.css} +1 -1
- package/dist/apps/prebuilt/com.eden.context-menu/dist/assets/index-CQD24gQV.js +1 -0
- package/dist/apps/prebuilt/com.eden.context-menu/dist/index.html +2 -2
- package/dist/apps/prebuilt/com.eden.context-menu/manifest.json +1 -1
- package/dist/apps/prebuilt/com.eden.eveshell/dist/assets/index-bsf9U6_1.js +1 -0
- package/dist/apps/prebuilt/com.eden.eveshell/dist/index.html +1 -1
- package/dist/apps/prebuilt/com.eden.example.hello/backend/node_modules/@edenapp/types/CHANGELOG.md +14 -0
- package/dist/apps/prebuilt/com.eden.example.hello/backend/node_modules/@edenapp/types/ContextMenu.d.ts +7 -1
- package/dist/apps/prebuilt/com.eden.example.hello/backend/node_modules/@edenapp/types/commands.generated.d.ts +1 -1
- package/dist/apps/prebuilt/com.eden.example.hello/backend/node_modules/@edenapp/types/events.generated.d.ts +1 -1
- package/dist/apps/prebuilt/com.eden.example.hello/backend/node_modules/@edenapp/types/index.d.ts +5 -1
- package/dist/apps/prebuilt/com.eden.example.hello/backend/node_modules/@edenapp/types/ipc/appbus.d.ts +2 -12
- package/dist/apps/prebuilt/com.eden.example.hello/backend/node_modules/@edenapp/types/package.json +1 -1
- package/dist/apps/prebuilt/com.eden.example.hello/frontend/node_modules/@edenapp/types/CHANGELOG.md +14 -0
- package/dist/apps/prebuilt/com.eden.example.hello/frontend/node_modules/@edenapp/types/ContextMenu.d.ts +7 -1
- package/dist/apps/prebuilt/com.eden.example.hello/frontend/node_modules/@edenapp/types/commands.generated.d.ts +1 -1
- package/dist/apps/prebuilt/com.eden.example.hello/frontend/node_modules/@edenapp/types/events.generated.d.ts +1 -1
- package/dist/apps/prebuilt/com.eden.example.hello/frontend/node_modules/@edenapp/types/index.d.ts +5 -1
- package/dist/apps/prebuilt/com.eden.example.hello/frontend/node_modules/@edenapp/types/ipc/appbus.d.ts +2 -12
- package/dist/apps/prebuilt/com.eden.example.hello/frontend/node_modules/@edenapp/types/package.json +1 -1
- package/dist/apps/prebuilt/com.eden.files/CHANGELOG.md +19 -0
- package/dist/apps/prebuilt/com.eden.files/dist/assets/index-bw-C9AMI.js +1 -0
- package/dist/apps/prebuilt/com.eden.files/dist/index.html +1 -1
- package/dist/apps/prebuilt/com.eden.files/package.json +1 -1
- package/dist/apps/prebuilt/com.eden.login/CHANGELOG.md +14 -0
- package/dist/apps/prebuilt/com.eden.login/package.json +1 -1
- package/dist/apps/prebuilt/com.eden.process-manager/CHANGELOG.md +14 -0
- package/dist/apps/prebuilt/com.eden.process-manager/package.json +1 -1
- package/dist/i18n/I18nHandler.d.ts +2 -1
- package/dist/i18n/I18nHandler.d.ts.map +1 -1
- package/dist/i18n/I18nHandler.js.map +1 -1
- package/dist/i18n/I18nManager.d.ts +3 -1
- package/dist/i18n/I18nManager.d.ts.map +1 -1
- package/dist/i18n/I18nManager.js.map +1 -1
- package/dist/ipc/CommandDecorators.d.ts +2 -4
- package/dist/ipc/CommandDecorators.d.ts.map +1 -1
- package/dist/ipc/CommandDecorators.js +1 -1
- package/dist/ipc/CommandDecorators.js.map +1 -1
- package/dist/ipc/CommandMetadata.d.ts +7 -3
- package/dist/ipc/CommandMetadata.d.ts.map +1 -1
- package/dist/ipc/CommandMetadata.js.map +1 -1
- package/dist/ipc/CommandRegistry.d.ts +8 -5
- package/dist/ipc/CommandRegistry.d.ts.map +1 -1
- package/dist/ipc/CommandRegistry.js +3 -2
- package/dist/ipc/CommandRegistry.js.map +1 -1
- package/dist/ipc/CommandRegistry.test.js.map +1 -1
- package/dist/ipc/EdenEmitter.d.ts.map +1 -1
- package/dist/ipc/EdenEmitter.js.map +1 -1
- package/dist/ipc/EdenEmitter.test.js.map +1 -1
- package/dist/ipc/EventHandler.js.map +1 -1
- package/dist/ipc/EventSubscriberManager.d.ts +2 -2
- package/dist/ipc/EventSubscriberManager.d.ts.map +1 -1
- package/dist/ipc/EventSubscriberManager.js.map +1 -1
- package/dist/ipc/EventSubscriberManager.test.js +70 -45
- package/dist/ipc/EventSubscriberManager.test.js.map +1 -1
- package/dist/ipc/IPCBridge.d.ts +1 -0
- package/dist/ipc/IPCBridge.d.ts.map +1 -1
- package/dist/ipc/IPCBridge.js +22 -7
- package/dist/ipc/IPCBridge.js.map +1 -1
- package/dist/logging/electron.d.ts.map +1 -1
- package/dist/logging/electron.js +8 -7
- package/dist/logging/electron.js.map +1 -1
- package/dist/logging/logger.d.ts.map +1 -1
- package/dist/logging/logger.js +9 -7
- package/dist/logging/logger.js.map +1 -1
- package/dist/process-manager/BackendManager.d.ts +3 -2
- package/dist/process-manager/BackendManager.d.ts.map +1 -1
- package/dist/process-manager/BackendManager.js +18 -5
- package/dist/process-manager/BackendManager.js.map +1 -1
- package/dist/process-manager/ProcessManager.d.ts +1 -1
- package/dist/process-manager/ProcessManager.d.ts.map +1 -1
- package/dist/process-manager/ProcessManager.js.map +1 -1
- package/dist/process-manager/ProcessMetricsCollector.d.ts.map +1 -1
- package/dist/process-manager/ProcessMetricsCollector.js +6 -8
- package/dist/process-manager/ProcessMetricsCollector.js.map +1 -1
- package/dist/process-manager/ProcessMetricsCollector.test.js +70 -34
- package/dist/process-manager/ProcessMetricsCollector.test.js.map +1 -1
- package/dist/view-manager/ViewManager.d.ts +2 -2
- package/dist/view-manager/ViewManager.d.ts.map +1 -1
- package/dist/view-manager/ViewManager.js.map +1 -1
- package/package.json +4 -4
- package/dist/apps/prebuilt/com.eden.context-menu/dist/assets/index-B-ks_-b3.js +0 -1
- package/dist/apps/prebuilt/com.eden.eveshell/dist/assets/index-B-bahmO2.js +0 -1
- 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/logging/levels.ts", "../../src/logging/logger.ts", "../../src/app-runtime/common/port-channel.ts", "../../src/app-runtime/common/api-factory.ts", "../../src/app-runtime/backend-preload.ts"],
|
|
4
|
-
"sourcesContent": ["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/**\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", "import {\n type CallsiteInfo,\n log,\n logFromConsole,\n setLogContext,\n} from \"../logging\";\n/**\n * Backend Runtime\n *\n * This module runs inside Electron's utility process (forked by BackendManager).\n * It provides the global `worker` object with `edenAPI` and `appBus` APIs,\n * mirroring the frontend's `window.edenAPI` and `window.appBus`.\n *\n * Environment variables expected:\n * - EDEN_APP_ID: The app's identifier\n * - EDEN_BACKEND_ENTRY: Path to the actual backend entry point\n * - EDEN_INSTALL_PATH: Path to the app's installation directory\n * - EDEN_MANIFEST: JSON-stringified app manifest\n */\n\nimport type { AppBusAPI, AppBusConnection, EdenAPI } from \"@edenapp/types\";\n\nimport type { WorkerGlobal } from \"@edenapp/types/worker\";\nimport {\n createAppBusAPI,\n createEdenAPI,\n type ShellTransport,\n} from \"./common/api-factory\";\nimport {\n createAppBusState,\n createMessageIdGenerator,\n createPortConnection,\n handlePortClosed,\n handleAppBusPort as handlePortSetup,\n wrapElectronPort,\n} from \"./common/port-channel\";\n\n// Electron utility process extends the Node process with parentPort\n// This is available when running inside utilityProcess.fork()\n// We use Electron's types which should be available\n\n// Get app info from environment\nconst appId = process.env.EDEN_APP_ID!;\nconst backendEntry = process.env.EDEN_BACKEND_ENTRY!;\nconst manifest = JSON.parse(process.env.EDEN_MANIFEST || \"{}\");\n\nsetLogContext({ appId });\n\nconst captureConsoleCallsite = (): CallsiteInfo | undefined => {\n const err = new Error();\n Error.captureStackTrace?.(err, captureConsoleCallsite);\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 (\n trimmed.includes(\"backend-preload\") ||\n trimmed.includes(\"/logging/\") ||\n trimmed.includes(\"\\\\logging\\\\\")\n ) {\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\nconsole.log = (...args: unknown[]) =>\n logFromConsole({ level: \"info\", args, callsite: captureConsoleCallsite() });\nconsole.info = (...args: unknown[]) =>\n logFromConsole({ level: \"info\", args, callsite: captureConsoleCallsite() });\nconsole.warn = (...args: unknown[]) =>\n logFromConsole({ level: \"warn\", args, callsite: captureConsoleCallsite() });\nconsole.error = (...args: unknown[]) =>\n logFromConsole({ level: \"error\", args, callsite: captureConsoleCallsite() });\nconsole.debug = (...args: unknown[]) =>\n logFromConsole({ level: \"debug\", args, callsite: captureConsoleCallsite() });\nconsole.trace = (...args: unknown[]) =>\n logFromConsole({ level: \"trace\", args, callsite: captureConsoleCallsite() });\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// Port for direct frontend<->backend communication (received from main)\nlet frontendPort: Electron.MessagePortMain | null = null;\n\n// Port for IPC with main process (process.parentPort)\nconst parentPort = process.parentPort;\nif (!parentPort) {\n log.error(\"Not running in utility process - parentPort not available\");\n process.exit(1);\n}\n\n// Event subscriptions\nconst eventSubscriptions: Map<string, Set<Function>> = new Map();\n\n// Pending shell command requests\nconst pendingCommands: Map<\n string,\n { resolve: (value: any) => void; reject: (reason: any) => void }\n> = new Map();\nlet commandIdCounter = 0;\n\n// AppBus state\nconst appBusState = createAppBusState(\"backend-appbus\");\n\n/**\n * Generate unique command ID\n */\nfunction generateCommandId(): string {\n return `cmd-${appId}-${Date.now()}-${++commandIdCounter}`;\n}\n\n/**\n * Send a shell command to main process and wait for response\n */\nasync function shellCommand(command: string, args: any): Promise<any> {\n return new Promise((resolve, reject) => {\n const commandId = generateCommandId();\n\n // Set timeout\n const timeout = setTimeout(() => {\n pendingCommands.delete(commandId);\n reject(new Error(`Shell command '${command}' timed out`));\n }, 30000);\n\n pendingCommands.set(commandId, {\n resolve: (value) => {\n clearTimeout(timeout);\n resolve(value);\n },\n reject: (reason) => {\n clearTimeout(timeout);\n reject(reason);\n },\n });\n\n parentPort!.postMessage({\n type: \"shell-command\",\n commandId,\n command,\n args: { ...args, _callerAppId: appId },\n });\n });\n}\n\n// ===================================================================\n// Shared API Implementation\n// ===================================================================\n\n// Shell transport implementation using internal shellCommand\nconst shellTransport: ShellTransport = {\n exec: (command: string, args: any) => {\n return shellCommand(command, args);\n },\n};\n\n/**\n * Eden API implementation for utility process\n */\nconst edenAPI: EdenAPI = createEdenAPI(shellTransport, eventSubscriptions, {\n getLaunchArgs: () => launchArgs,\n});\n\n/**\n * AppBus API implementation for utility process\n */\nconst appBus: AppBusAPI = createAppBusAPI(\n { transport: shellTransport, isBackend: true },\n appBusState,\n);\n\n// Frontend communication state\nlet frontendConnection: AppBusConnection | null = null;\n\n// Check if this app has a frontend (from manifest)\nconst hasFrontend = !!manifest.frontend?.entry;\n\n// appAPI will be set after frontend port is received (for apps with frontend)\n// For backend-only apps, worker.appAPI will be undefined\n\n/**\n * Handle messages from main process (via parentPort)\n */\nparentPort.on(\"message\", (event: Electron.MessageEvent) => {\n const message = event.data;\n\n if (message.type === \"shell-command-response\") {\n // Response to a shell command we sent\n const pending = pendingCommands.get(message.commandId);\n if (pending) {\n pendingCommands.delete(message.commandId);\n if (message.error) {\n pending.reject(new Error(message.error));\n } else {\n pending.resolve(message.result);\n }\n }\n } else if (message.type === \"shell-event\") {\n // Event notification from main\n const { eventName, payload } = message;\n const callbacks = eventSubscriptions.get(eventName);\n if (callbacks) {\n callbacks.forEach((callback) => {\n try {\n callback(payload);\n } catch (err) {\n log.error(`Error in event callback for ${eventName}:`, err);\n }\n });\n }\n } else if (message.type === \"appbus-port\") {\n // AppBus connection port\n const [port] = event.ports;\n if (port) {\n handleAppBusPort(port, message);\n }\n } else if (message.type === \"appbus-port-closed\") {\n // AppBus connection closed\n handlePortClosed(appBusState, message.connectionId);\n } else if (message.type === \"shutdown\") {\n // Graceful shutdown request\n log.info(`Shutdown requested`);\n process.exit(0);\n }\n});\n\n/**\n * Set up frontend port using createPortConnection\n */\nfunction setupFrontendPort(port: Electron.MessagePortMain): void {\n const wrappedPort = wrapElectronPort(port);\n\n // Create connection using shared utility\n frontendConnection = createPortConnection(\n wrappedPort,\n \"__frontend__\",\n new Map([[\"__frontend__\", wrappedPort]]),\n new Map(),\n createMessageIdGenerator(\"backend-to-frontend\"),\n );\n}\n\n/**\n * Handle AppBus port connections (using shared utility)\n */\nfunction handleAppBusPort(port: Electron.MessagePortMain, data: any): void {\n // Wrap Electron MessagePortMain to IPCPort interface\n const wrappedPort = wrapElectronPort(port);\n\n handlePortSetup(wrappedPort, data, appBusState);\n}\n\n/**\n * Load and execute the actual backend entry point\n */\nasync function loadBackendEntry(): Promise<void> {\n try {\n log.info(`Loading backend entry: ${backendEntry}`);\n await import(backendEntry);\n log.info(`Backend loaded successfully`);\n\n // Signal to main that we're ready\n parentPort!.postMessage({ type: \"backend-ready\" });\n } catch (error) {\n log.error(`Failed to load backend:`, error);\n parentPort!.postMessage({\n type: \"backend-error\",\n error: error instanceof Error ? error.message : String(error),\n });\n process.exit(1);\n }\n}\n\n/**\n * Wait for frontend port (if app has frontend) then load backend\n */\nasync function initializeBackend(): Promise<void> {\n if (hasFrontend) {\n // Wait for init-port message before loading backend\n await new Promise<void>((resolve) => {\n const handler = (event: Electron.MessageEvent) => {\n if (event.data.type === \"init-port\") {\n const [port] = event.ports;\n if (port) {\n frontendPort = port;\n setupFrontendPort(port);\n log.info(`Frontend port initialized`);\n }\n parentPort.removeListener(\"message\", handler);\n resolve();\n }\n };\n parentPort.on(\"message\", handler);\n });\n }\n\n // Now load backend - worker.appAPI is ready (for apps with frontend)\n await loadBackendEntry();\n}\n\n/**\n * Get AppAPI connection\n * Throws if app has no frontend\n */\nfunction getAppAPI(): AppBusConnection {\n if (!frontendConnection) {\n throw new Error(\n \"AppAPI not available: This app has no frontend connection. \" +\n \"Ensure 'frontend.entry' is defined in manifest.json if you need frontend communication.\",\n );\n }\n return frontendConnection;\n}\n\n/**\n * Set up the global worker object\n */\n// For apps with frontend, appAPI will be set in initializeBackend after port is received\n((globalThis as any).worker as WorkerGlobal) = {\n edenAPI,\n appBus,\n getAppAPI,\n};\n\n// Start initialization\ninitializeBackend();\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["LOG_LEVEL_ORDER", "parseLogLevel", "value", "normalized", "isLogLevelEnabled", "level", "minLevel", "globalContext", "config", "resolveDefaultConfig", "baseConsole", "setLogContext", "next", "globalContext", "createLogger", "context", "args", "emit", "log", "logFromConsole", "record", "emit", "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", "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", "
|
|
4
|
+
"sourcesContent": ["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/**\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", "import {\n type CallsiteInfo,\n log,\n logFromConsole,\n setLogContext,\n} from \"../logging\";\n/**\n * Backend Runtime\n *\n * This module runs inside Electron's utility process (forked by BackendManager).\n * It provides the global `worker` object with `edenAPI` and `appBus` APIs,\n * mirroring the frontend's `window.edenAPI` and `window.appBus`.\n *\n * Environment variables expected:\n * - EDEN_APP_ID: The app's identifier\n * - EDEN_BACKEND_ENTRY: Path to the actual backend entry point\n * - EDEN_INSTALL_PATH: Path to the app's installation directory\n * - EDEN_MANIFEST: JSON-stringified app manifest\n */\n\nimport type {\n AppBusAPI,\n AppBusConnection,\n CommandArgs,\n CommandName,\n CommandResult,\n EdenAPI,\n} from \"@edenapp/types\";\n\nimport type { WorkerGlobal } from \"@edenapp/types/worker\";\nimport {\n createAppBusAPI,\n createEdenAPI,\n type ShellTransport,\n} from \"./common/api-factory\";\nimport {\n type AppBusPortData,\n createAppBusState,\n createMessageIdGenerator,\n createPortConnection,\n handlePortClosed,\n handleAppBusPort as handlePortSetup,\n wrapElectronPort,\n} from \"./common/port-channel\";\n\ntype RuntimeMessage = {\n type: string;\n commandId?: string;\n command?: string;\n args?: unknown;\n result?: unknown;\n error?: string;\n eventName?: string;\n payload?: unknown;\n connectionId?: string;\n role?: \"service\" | \"client\";\n serviceName?: string;\n targetAppId?: string;\n sourceAppId?: string;\n};\n\n// Electron utility process extends the Node process with parentPort\n// This is available when running inside utilityProcess.fork()\n// We use Electron's types which should be available\n\n// Get app info from environment\nconst appId = process.env.EDEN_APP_ID!;\nconst backendEntry = process.env.EDEN_BACKEND_ENTRY!;\nconst manifest = JSON.parse(process.env.EDEN_MANIFEST || \"{}\");\n\nsetLogContext({ appId });\n\nconst captureConsoleCallsite = (): CallsiteInfo | undefined => {\n const err = new Error();\n Error.captureStackTrace?.(err, captureConsoleCallsite);\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 (\n trimmed.includes(\"backend-preload\") ||\n trimmed.includes(\"/logging/\") ||\n trimmed.includes(\"\\\\logging\\\\\")\n ) {\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\nconsole.log = (...args: unknown[]) =>\n logFromConsole({ level: \"info\", args, callsite: captureConsoleCallsite() });\nconsole.info = (...args: unknown[]) =>\n logFromConsole({ level: \"info\", args, callsite: captureConsoleCallsite() });\nconsole.warn = (...args: unknown[]) =>\n logFromConsole({ level: \"warn\", args, callsite: captureConsoleCallsite() });\nconsole.error = (...args: unknown[]) =>\n logFromConsole({ level: \"error\", args, callsite: captureConsoleCallsite() });\nconsole.debug = (...args: unknown[]) =>\n logFromConsole({ level: \"debug\", args, callsite: captureConsoleCallsite() });\nconsole.trace = (...args: unknown[]) =>\n logFromConsole({ level: \"trace\", args, callsite: captureConsoleCallsite() });\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// Port for direct frontend<->backend communication (received from main)\nlet frontendPort: Electron.MessagePortMain | null = null;\n\n// Port for IPC with main process (process.parentPort)\nconst parentPort = process.parentPort;\nif (!parentPort) {\n log.error(\"Not running in utility process - parentPort not available\");\n process.exit(1);\n}\n\n// Event subscriptions\nconst eventSubscriptions: Map<\n string,\n Set<(payload: unknown) => void>\n> = new Map();\n\ntype PendingCommandResult = CommandResult<CommandName>;\n\n// Pending shell command requests\nconst pendingCommands: Map<\n string,\n {\n resolve: (value: PendingCommandResult) => void;\n reject: (reason: unknown) => void;\n }\n> = new Map();\nlet commandIdCounter = 0;\n\n// AppBus state\nconst appBusState = createAppBusState(\"backend-appbus\");\n\n/**\n * Generate unique command ID\n */\nfunction generateCommandId(): string {\n return `cmd-${appId}-${Date.now()}-${++commandIdCounter}`;\n}\n\nfunction asCommandArgs(value: unknown): Record<string, unknown> {\n if (value && typeof value === \"object\" && !Array.isArray(value)) {\n return { ...(value as Record<string, unknown>) };\n }\n\n return {};\n}\n\n/**\n * Send a shell command to main process and wait for response\n */\nfunction shellCommand<T extends CommandName>(\n command: T,\n args: CommandArgs<T>,\n): Promise<CommandResult<T>> {\n return new Promise((resolve, reject) => {\n const commandId = generateCommandId();\n\n // Set timeout\n const timeout = setTimeout(() => {\n pendingCommands.delete(commandId);\n reject(new Error(`Shell command '${command}' timed out`));\n }, 30000);\n\n pendingCommands.set(commandId, {\n resolve: (value) => {\n clearTimeout(timeout);\n resolve(value as CommandResult<T>);\n },\n reject: (reason) => {\n clearTimeout(timeout);\n reject(reason);\n },\n });\n\n parentPort!.postMessage({\n type: \"shell-command\",\n commandId,\n command,\n args: { ...asCommandArgs(args), _callerAppId: appId },\n });\n });\n}\n\n// ===================================================================\n// Shared API Implementation\n// ===================================================================\n\n// Shell transport implementation using internal shellCommand\nconst shellTransport: ShellTransport = {\n exec: shellCommand,\n};\n\n/**\n * Eden API implementation for utility process\n */\nconst edenAPI: EdenAPI = createEdenAPI(shellTransport, eventSubscriptions, {\n getLaunchArgs: () => launchArgs,\n});\n\n/**\n * AppBus API implementation for utility process\n */\nconst appBus: AppBusAPI = createAppBusAPI(\n { transport: shellTransport },\n appBusState,\n);\n\n// Frontend communication state\nlet frontendConnection: AppBusConnection | null = null;\n\n// Check if this app has a frontend (from manifest)\nconst hasFrontend = !!manifest.frontend?.entry;\n\n// appAPI will be set after frontend port is received (for apps with frontend)\n// For backend-only apps, worker.appAPI will be undefined\n\n/**\n * Handle messages from main process (via parentPort)\n */\nparentPort.on(\"message\", (event: Electron.MessageEvent) => {\n const message = event.data as RuntimeMessage;\n\n if (message.type === \"shell-command-response\") {\n if (!message.commandId) {\n return;\n }\n\n // Response to a shell command we sent\n const pending = pendingCommands.get(message.commandId);\n if (pending) {\n pendingCommands.delete(message.commandId);\n if (message.error) {\n pending.reject(new Error(message.error));\n } else {\n pending.resolve(message.result as PendingCommandResult);\n }\n }\n } else if (message.type === \"shell-event\") {\n if (!message.eventName) {\n return;\n }\n\n // Event notification from main\n const { eventName, payload } = message;\n const callbacks = eventSubscriptions.get(eventName);\n if (callbacks) {\n callbacks.forEach((callback) => {\n try {\n callback(payload);\n } catch (err) {\n log.error(`Error in event callback for ${eventName}:`, err);\n }\n });\n }\n } else if (message.type === \"appbus-port\") {\n // AppBus connection port\n const [port] = event.ports;\n if (port && message.connectionId && message.role && message.serviceName) {\n handleAppBusPort(port, {\n connectionId: message.connectionId,\n role: message.role,\n serviceName: message.serviceName,\n targetAppId: message.targetAppId,\n sourceAppId: message.sourceAppId,\n });\n }\n } else if (message.type === \"appbus-port-closed\") {\n if (!message.connectionId) {\n return;\n }\n\n // AppBus connection closed\n handlePortClosed(appBusState, message.connectionId);\n } else if (message.type === \"shutdown\") {\n // Graceful shutdown request\n log.info(`Shutdown requested`);\n process.exit(0);\n }\n});\n\n/**\n * Set up frontend port using createPortConnection\n */\nfunction setupFrontendPort(port: Electron.MessagePortMain): void {\n const wrappedPort = wrapElectronPort(port);\n\n // Create connection using shared utility\n frontendConnection = createPortConnection(\n wrappedPort,\n \"__frontend__\",\n new Map([[\"__frontend__\", wrappedPort]]),\n new Map(),\n createMessageIdGenerator(\"backend-to-frontend\"),\n );\n}\n\n/**\n * Handle AppBus port connections (using shared utility)\n */\nfunction handleAppBusPort(\n port: Electron.MessagePortMain,\n data: AppBusPortData,\n): void {\n // Wrap Electron MessagePortMain to IPCPort interface\n const wrappedPort = wrapElectronPort(port);\n\n handlePortSetup(wrappedPort, data, appBusState);\n}\n\n/**\n * Load and execute the actual backend entry point\n */\nasync function loadBackendEntry(): Promise<void> {\n try {\n log.info(`Loading backend entry: ${backendEntry}`);\n await import(backendEntry);\n log.info(`Backend loaded successfully`);\n\n // Signal to main that we're ready\n parentPort!.postMessage({ type: \"backend-ready\" });\n } catch (error) {\n log.error(`Failed to load backend:`, error);\n parentPort!.postMessage({\n type: \"backend-error\",\n error: error instanceof Error ? error.message : String(error),\n });\n process.exit(1);\n }\n}\n\n/**\n * Wait for frontend port (if app has frontend) then load backend\n */\nasync function initializeBackend(): Promise<void> {\n if (hasFrontend) {\n // Wait for init-port message before loading backend\n await new Promise<void>((resolve) => {\n const handler = (event: Electron.MessageEvent) => {\n if (event.data.type === \"init-port\") {\n const [port] = event.ports;\n if (port) {\n frontendPort = port;\n setupFrontendPort(port);\n log.info(`Frontend port initialized`);\n }\n parentPort.removeListener(\"message\", handler);\n resolve();\n }\n };\n parentPort.on(\"message\", handler);\n });\n }\n\n // Now load backend - worker.appAPI is ready (for apps with frontend)\n await loadBackendEntry();\n}\n\n/**\n * Get AppAPI connection\n * Throws if app has no frontend\n */\nfunction getAppAPI(): AppBusConnection {\n if (!frontendConnection) {\n throw new Error(\n \"AppAPI not available: This app has no frontend connection. \" +\n \"Ensure 'frontend.entry' is defined in manifest.json if you need frontend communication.\",\n );\n }\n return frontendConnection;\n}\n\n/**\n * Set up the global worker object\n */\n// For apps with frontend, appAPI will be set in initializeBackend after port is received\n(\n globalThis as typeof globalThis & {\n worker?: WorkerGlobal;\n }\n).worker = {\n edenAPI,\n appBus,\n getAppAPI,\n};\n\n// Start initialization\ninitializeBackend();\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["LOG_LEVEL_ORDER", "parseLogLevel", "value", "normalized", "isLogLevelEnabled", "level", "minLevel", "runtimeGlobal", "globalContext", "config", "resolveDefaultConfig", "baseConsole", "setLogContext", "next", "globalContext", "createLogger", "context", "args", "emit", "log", "logFromConsole", "record", "emit", "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", "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", "backendEntry", "manifest", "setLogContext", "captureConsoleCallsite", "_a", "err", "stack", "lines", "line", "trimmed", "match", "file", "lineNumber", "columnNumber", "args", "logFromConsole", "launchArgs", "launchArgsArg", "arg", "jsonStr", "log", "frontendPort", "parentPort", "eventSubscriptions", "pendingCommands", "commandIdCounter", "appBusState", "createAppBusState", "generateCommandId", "asCommandArgs", "value", "shellCommand", "command", "resolve", "reject", "commandId", "timeout", "reason", "shellTransport", "edenAPI", "createEdenAPI", "appBus", "createAppBusAPI", "frontendConnection", "hasFrontend", "event", "message", "pending", "eventName", "payload", "callbacks", "callback", "port", "handleAppBusPort", "handlePortClosed", "setupFrontendPort", "wrappedPort", "createPortConnection", "createMessageIdGenerator", "data", "loadBackendEntry", "error", "initializeBackend", "handler", "getAppAPI"]
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
body{font-family:var(--eden-font-family-base);background:transparent;color:var(--eden-color-text-primary);overflow:hidden;height:100vh;width:100vw}.context-menu-root{position:fixed;top:0;right:0;bottom:0;left:0;z-index:var(--eden-z-popover);display:none;pointer-events:none}.context-menu-root.is-open{display:block;pointer-events:auto}.context-menu-overlay{position:fixed;top:0;right:0;bottom:0;left:0;background:transparent;-webkit-backdrop-filter:none;backdrop-filter:none}.context-menu{position:absolute;min-width:200px;max-width:360px;padding:var(--eden-space-md);font-family:var(--eden-font-family-base);font-size:var(--eden-font-size-md);background:var(--eden-color-bg-glass-strong);border:1px solid var(--eden-color-border-medium);border-radius:var(--eden-radius-lg);box-shadow:var(--eden-shadow-xl);backdrop-filter:var(--eden-glass-ultra);-webkit-backdrop-filter:var(--eden-glass-ultra);animation:context-menu-fade-in var(--eden-duration-fast) var(--eden-transition-ease-out);box-sizing:border-box}.context-menu-title{border-bottom:1px solid var(--eden-color-border-light);padding-bottom:6px;padding-left:6px;display:none;color:var(--eden-color-text-muted);font-size:var(--eden-font-size-xs);letter-spacing:var(--eden-font-letter-spacing-wide);text-transform:uppercase}.context-menu-title.is-visible{display:block;margin-bottom:var(--eden-space-sm)}.context-menu-items{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--eden-space-xs);width:100%}.context-menu-item{width:100%;padding:var(--eden-space-sm) var(--eden-space-md);border-radius:var(--eden-radius-sm);cursor:pointer;transition:background var(--eden-transition-fast);color:var(--eden-color-text-primary);display:flex;align-items:center;gap:var(--eden-space-sm);-webkit-user-select:none;user-select:none;box-sizing:border-box}.context-menu-item:hover{background:var(--eden-color-surface-hover)}.context-menu-item-danger{color:var(--eden-color-danger)}.context-menu-item-danger:hover{background:var(--eden-color-danger-bg)}.context-menu-item-disabled{opacity:.5;pointer-events:none}.context-menu-section-title{padding:6px 8px;font-size:var(--eden-font-size-xs);font-weight:var(--eden-font-weight-semibold);color:var(--eden-color-text-muted);text-transform:uppercase;letter-spacing:var(--eden-font-letter-spacing-wide)}.context-menu-divider{height:1px;background:var(--eden-color-border-light);margin:4px 0}.context-menu-icon{width:1em;height:1em;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.context-menu-icon svg{width:1em;height:1em;display:block}.context-menu-label{flex:1;min-width:0}.context-menu-shortcut{font-size:12px;color:var(--eden-color-text-muted)}@keyframes context-menu-fade-in{0%{opacity:0}to{opacity:1}}
|
|
1
|
+
body{font-family:var(--eden-font-family-base);background:transparent;color:var(--eden-color-text-primary);overflow:hidden;height:100vh;width:100vw}.context-menu-root{position:fixed;top:0;right:0;bottom:0;left:0;z-index:var(--eden-z-popover);display:none;pointer-events:none}.context-menu-root.is-open{display:block;pointer-events:auto}.context-menu-overlay{position:fixed;top:0;right:0;bottom:0;left:0;background:transparent;-webkit-backdrop-filter:none;backdrop-filter:none}.context-menu{position:absolute;min-width:200px;max-width:360px;padding:var(--eden-space-md);font-family:var(--eden-font-family-base);font-size:var(--eden-font-size-md);background:var(--eden-color-bg-glass-strong);border:1px solid var(--eden-color-border-medium);border-radius:var(--eden-radius-lg);box-shadow:var(--eden-shadow-xl);backdrop-filter:var(--eden-glass-ultra);-webkit-backdrop-filter:var(--eden-glass-ultra);animation:context-menu-fade-in var(--eden-duration-fast) var(--eden-transition-ease-out);box-sizing:border-box}.context-menu-title{border-bottom:1px solid var(--eden-color-border-light);padding-bottom:6px;padding-left:6px;display:none;color:var(--eden-color-text-muted);font-size:var(--eden-font-size-xs);letter-spacing:var(--eden-font-letter-spacing-wide);text-transform:uppercase}.context-menu-title.is-visible{display:block;margin-bottom:var(--eden-space-sm)}.context-menu-items{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--eden-space-xs);width:100%}.context-menu-item{width:100%;padding:var(--eden-space-sm) var(--eden-space-md);border-radius:var(--eden-radius-sm);cursor:pointer;transition:background var(--eden-transition-fast);color:var(--eden-color-text-primary);display:flex;align-items:center;gap:var(--eden-space-sm);-webkit-user-select:none;user-select:none;box-sizing:border-box}.context-menu-item:hover,.context-menu-item-open{background:var(--eden-color-surface-hover)}.context-menu-item-danger{color:var(--eden-color-danger)}.context-menu-item-danger:hover{background:var(--eden-color-danger-bg)}.context-menu-item-disabled{opacity:.5;pointer-events:none}.context-menu-section-title{padding:6px 8px;font-size:var(--eden-font-size-xs);font-weight:var(--eden-font-weight-semibold);color:var(--eden-color-text-muted);text-transform:uppercase;letter-spacing:var(--eden-font-letter-spacing-wide)}.context-menu-divider{height:1px;background:var(--eden-color-border-light);margin:4px 0}.context-menu-icon{width:1em;height:1em;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.context-menu-icon svg{width:1em;height:1em;display:block}.context-menu-app-icon img{width:1.25em;height:1.25em;display:block;object-fit:contain;border-radius:2px}.context-menu-app-icon{width:1.25em;height:1.25em;margin-left:-2px;margin-right:-2px}.context-menu-label{flex:1;min-width:0}.context-menu-shortcut{font-size:12px;color:var(--eden-color-text-muted)}.context-menu-submenu-indicator{width:1em;height:1em;display:inline-flex;align-items:center;justify-content:center;color:var(--eden-color-text-muted);flex-shrink:0}.context-menu-submenu-indicator svg{width:1em;height:1em;display:block}.context-menu-item[data-submenu-side=left] .context-menu-submenu-indicator svg{transform:scaleX(-1)}@keyframes context-menu-fade-in{0%{opacity:0}to{opacity:1}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(){const n=document.createElement("link").relList;if(n&&n.supports&&n.supports("modulepreload"))return;for(const t of document.querySelectorAll('link[rel="modulepreload"]'))l(t);new MutationObserver(t=>{for(const o of t)if(o.type==="childList")for(const c of o.addedNodes)c.tagName==="LINK"&&c.rel==="modulepreload"&&l(c)}).observe(document,{childList:!0,subtree:!0});function i(t){const o={};return t.integrity&&(o.integrity=t.integrity),t.referrerPolicy&&(o.referrerPolicy=t.referrerPolicy),t.crossOrigin==="use-credentials"?o.credentials="include":t.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function l(t){if(t.ep)return;t.ep=!0;const o=i(t);fetch(t.href,o)}})();function U(){const e=document.getElementById("context-menu-root"),n=document.getElementById("context-menu-overlay"),i=document.getElementById("context-menu"),l=document.getElementById("context-menu-title"),t=document.getElementById("context-menu-items");if(!e||!n||!i||!l||!t)throw new Error("Context menu elements not found");return{root:e,overlay:n,menu:i,titleEl:l,itemsEl:t}}function G(e){const{root:n,menu:i,titleEl:l,itemsEl:t}=e,o={titleEl:l,itemsEl:t},c=new WeakMap([[i,o]]);i.classList.add("context-menu-panel"),i.dataset.menuDepth="0";const p=s=>{const y=c.get(s);if(y)return y;const r=document.createElement("div");r.className="eden-popover-title context-menu-title";const u=document.createElement("ul");u.className="context-menu-items",s.append(r,u);const w={titleEl:r,itemsEl:u};return c.set(s,w),w};return{getPanelElements:p,createSubmenuPanel:s=>{const y=document.createElement("div");return y.className="eden-popover context-menu context-menu-panel context-menu-submenu",y.tabIndex=-1,y.dataset.menuDepth=String(s),y.addEventListener("click",r=>r.stopPropagation()),y.addEventListener("contextmenu",r=>r.preventDefault()),p(y),n.appendChild(y),y},getPanel:s=>s===0?i:n.querySelector(`.context-menu-panel[data-menu-depth="${s}"]`)}}const M=new Map;function K(e){return!e||typeof e=="string"?null:e.type==="app"?e.appId:null}function T(e,n){var i;for(const l of e){if(l.type!=="item")continue;const t=K(l.icon);t&&n.add(t),(i=l.items)!=null&&i.length&&T(l.items,n)}}async function X(e){const n=new Set;T(e,n),await Promise.all([...n].map(i=>J(i)))}async function J(e){if(M.has(e))return M.get(e);try{const n=await window.edenAPI.shellCommand("package/get-icon",{appId:e});return M.set(e,n.icon),n.icon}catch(n){console.warn(`Failed to fetch icon for ${e}:`,n),M.set(e,void 0);return}}function Q(e){return M.get(e)}const m=8,V=4;function O(e,n,i){return i<=n?n:Math.min(Math.max(e,n),i)}function B(e,n,i,l){const t=l(),o=e.getBoundingClientRect(),c=t.width-m-o.width,p=t.height-m-o.height,a=O(n,m,c),x=O(i,m,p);e.style.left=`${a}px`,e.style.top=`${x}px`,e.style.right="",e.style.bottom="",e.style.transform=""}function R(e,n,i){const l=i(),t=e.getBoundingClientRect(),o=n.left??(n.right!==void 0?l.width-n.right-t.width:m),c=n.top??(n.bottom!==void 0?l.height-n.bottom-t.height:m);B(e,o,c,i)}function q(e,n,i){const l=i(),t=n.getBoundingClientRect(),o=e.getBoundingClientRect(),c=t.right+V,p=t.left-o.width-V,a=l.width-m-c,x=p-m,y=a>=o.width||a>=x?"right":"left",r=y==="right"?c:p,u=t.top-V;return B(e,r,u,i),e.dataset.submenuSide=y,y}const Y={plus:'<line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line>',minus:'<line x1="5" y1="12" x2="19" y2="12"></line>',x:'<line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line>',check:'<polyline points="20 6 9 17 4 12"></polyline>',"check-circle":'<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path><polyline points="22 4 12 14.01 9 11.01"></polyline>',"x-circle":'<circle cx="12" cy="12" r="10"></circle><line x1="15" y1="9" x2="9" y2="15"></line><line x1="9" y1="9" x2="15" y2="15"></line>',"refresh-cw":'<polyline points="23 4 23 10 17 10"></polyline><polyline points="1 20 1 14 7 14"></polyline><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"></path>',"refresh-ccw":'<polyline points="1 4 1 10 7 10"></polyline><polyline points="23 20 23 14 17 14"></polyline><path d="M20.49 9A9 9 0 0 0 5.64 5.64L1 10m22 4l-4.64 4.36A9 9 0 0 1 3.51 15"></path>',"rotate-cw":'<polyline points="23 4 23 10 17 10"></polyline><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"></path>',"rotate-ccw":'<polyline points="1 4 1 10 7 10"></polyline><path d="M3.51 15a9 9 0 1 0 2.12-9.36L1 10"></path>',edit:'<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path>',"edit-2":'<path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>',"edit-3":'<path d="M12 20h9"></path><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"></path>',scissors:'<circle cx="6" cy="6" r="3"></circle><circle cx="6" cy="18" r="3"></circle><line x1="20" y1="4" x2="8.12" y2="15.88"></line><line x1="14.47" y1="14.48" x2="20" y2="20"></line><line x1="8.12" y1="8.12" x2="12" y2="12"></line>',copy:'<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>',clipboard:'<path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect>',file:'<path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline>',"file-text":'<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline>',"file-plus":'<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="12" y1="18" x2="12" y2="12"></line><line x1="9" y1="15" x2="15" y2="15"></line>',"file-minus":'<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="9" y1="15" x2="15" y2="15"></line>',folder:'<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path>',"folder-plus":'<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path><line x1="12" y1="11" x2="12" y2="17"></line><line x1="9" y1="14" x2="15" y2="14"></line>',"folder-minus":'<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path><line x1="9" y1="14" x2="15" y2="14"></line>',save:'<path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"></path><polyline points="17 21 17 13 7 13 7 21"></polyline><polyline points="7 3 7 8 15 8"></polyline>',download:'<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line>',upload:'<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="17 8 12 3 7 8"></polyline><line x1="12" y1="3" x2="12" y2="15"></line>',trash:'<polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>',"trash-2":'<polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path><line x1="10" y1="11" x2="10" y2="17"></line><line x1="14" y1="11" x2="14" y2="17"></line>',"arrow-up":'<line x1="12" y1="19" x2="12" y2="5"></line><polyline points="5 12 12 5 19 12"></polyline>',"arrow-down":'<line x1="12" y1="5" x2="12" y2="19"></line><polyline points="19 12 12 19 5 12"></polyline>',"arrow-left":'<line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline>',"arrow-right":'<line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline>',"chevron-up":'<polyline points="18 15 12 9 6 15"></polyline>',"chevron-down":'<polyline points="6 9 12 15 18 9"></polyline>',"chevron-left":'<polyline points="15 18 9 12 15 6"></polyline>',"chevron-right":'<polyline points="9 18 15 12 9 6"></polyline>',"corner-up-left":'<polyline points="9 14 4 9 9 4"></polyline><path d="M20 20v-7a4 4 0 0 0-4-4H4"></path>',"corner-up-right":'<polyline points="15 14 20 9 15 4"></polyline><path d="M4 20v-7a4 4 0 0 1 4-4h12"></path>',move:'<polyline points="5 9 2 12 5 15"></polyline><polyline points="9 5 12 2 15 5"></polyline><polyline points="15 19 12 22 9 19"></polyline><polyline points="19 9 22 12 19 15"></polyline><line x1="2" y1="12" x2="22" y2="12"></line><line x1="12" y1="2" x2="12" y2="22"></line>',maximize:'<path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"></path>',minimize:'<path d="M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3"></path>',"maximize-2":'<polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" y1="3" x2="14" y2="10"></line><line x1="3" y1="21" x2="10" y2="14"></line>',"minimize-2":'<polyline points="4 14 10 14 10 20"></polyline><polyline points="20 10 14 10 14 4"></polyline><line x1="14" y1="10" x2="21" y2="3"></line><line x1="3" y1="21" x2="10" y2="14"></line>',eye:'<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path><circle cx="12" cy="12" r="3"></circle>',"eye-off":'<path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"></path><line x1="1" y1="1" x2="23" y2="23"></line>',"zoom-in":'<circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line><line x1="11" y1="8" x2="11" y2="14"></line><line x1="8" y1="11" x2="14" y2="11"></line>',"zoom-out":'<circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line><line x1="8" y1="11" x2="14" y2="11"></line>',search:'<circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line>',filter:'<polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"></polygon>',list:'<line x1="8" y1="6" x2="21" y2="6"></line><line x1="8" y1="12" x2="21" y2="12"></line><line x1="8" y1="18" x2="21" y2="18"></line><line x1="3" y1="6" x2="3.01" y2="6"></line><line x1="3" y1="12" x2="3.01" y2="12"></line><line x1="3" y1="18" x2="3.01" y2="18"></line>',grid:'<rect x="3" y="3" width="7" height="7"></rect><rect x="14" y="3" width="7" height="7"></rect><rect x="14" y="14" width="7" height="7"></rect><rect x="3" y="14" width="7" height="7"></rect>',layout:'<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><line x1="3" y1="9" x2="21" y2="9"></line><line x1="9" y1="21" x2="9" y2="9"></line>',sidebar:'<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><line x1="9" y1="3" x2="9" y2="21"></line>',columns:'<path d="M12 3h7a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-7m0-18H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h7m0-18v18"></path>',play:'<polygon points="5 3 19 12 5 21 5 3"></polygon>',pause:'<rect x="6" y="4" width="4" height="16"></rect><rect x="14" y="4" width="4" height="16"></rect>',"stop-circle":'<circle cx="12" cy="12" r="10"></circle><rect x="9" y="9" width="6" height="6"></rect>',"skip-back":'<polygon points="19 20 9 12 19 4 19 20"></polygon><line x1="5" y1="19" x2="5" y2="5"></line>',"skip-forward":'<polygon points="5 4 15 12 5 20 5 4"></polygon><line x1="19" y1="5" x2="19" y2="19"></line>',volume:'<polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon>',"volume-1":'<polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon><path d="M15.54 8.46a5 5 0 0 1 0 7.07"></path>',"volume-2":'<polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon><path d="M19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07"></path>',"volume-x":'<polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon><line x1="23" y1="9" x2="17" y2="15"></line><line x1="17" y1="9" x2="23" y2="15"></line>',image:'<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><circle cx="8.5" cy="8.5" r="1.5"></circle><polyline points="21 15 16 10 5 21"></polyline>',camera:'<path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"></path><circle cx="12" cy="13" r="4"></circle>',film:'<rect x="2" y="2" width="20" height="20" rx="2.18" ry="2.18"></rect><line x1="7" y1="2" x2="7" y2="22"></line><line x1="17" y1="2" x2="17" y2="22"></line><line x1="2" y1="12" x2="22" y2="12"></line><line x1="2" y1="7" x2="7" y2="7"></line><line x1="2" y1="17" x2="7" y2="17"></line><line x1="17" y1="17" x2="22" y2="17"></line><line x1="17" y1="7" x2="22" y2="7"></line>',music:'<path d="M9 18V5l12-2v13"></path><circle cx="6" cy="18" r="3"></circle><circle cx="18" cy="16" r="3"></circle>',mail:'<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path><polyline points="22,6 12,13 2,6"></polyline>',"message-square":'<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>',"message-circle":'<path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path>',send:'<line x1="22" y1="2" x2="11" y2="13"></line><polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>',share:'<circle cx="18" cy="5" r="3"></circle><circle cx="6" cy="12" r="3"></circle><circle cx="18" cy="19" r="3"></circle><line x1="8.59" y1="13.51" x2="15.42" y2="17.49"></line><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"></line>',"share-2":'<circle cx="18" cy="5" r="3"></circle><circle cx="6" cy="12" r="3"></circle><circle cx="18" cy="19" r="3"></circle><line x1="8.59" y1="13.51" x2="15.42" y2="17.49"></line><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"></line>',phone:'<path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"></path>',user:'<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path><circle cx="12" cy="7" r="4"></circle>',"user-plus":'<path d="M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path><circle cx="8.5" cy="7" r="4"></circle><line x1="20" y1="8" x2="20" y2="14"></line><line x1="23" y1="11" x2="17" y2="11"></line>',"user-minus":'<path d="M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path><circle cx="8.5" cy="7" r="4"></circle><line x1="23" y1="11" x2="17" y2="11"></line>',"user-x":'<path d="M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path><circle cx="8.5" cy="7" r="4"></circle><line x1="18" y1="8" x2="23" y2="13"></line><line x1="23" y1="8" x2="18" y2="13"></line>',"user-check":'<path d="M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path><circle cx="8.5" cy="7" r="4"></circle><polyline points="17 11 19 13 23 9"></polyline>',users:'<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path><circle cx="9" cy="7" r="4"></circle><path d="M23 21v-2a4 4 0 0 0-3-3.87"></path><path d="M16 3.13a4 4 0 0 1 0 7.75"></path>',settings:'<circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path>',sliders:'<line x1="4" y1="21" x2="4" y2="14"></line><line x1="4" y1="10" x2="4" y2="3"></line><line x1="12" y1="21" x2="12" y2="12"></line><line x1="12" y1="8" x2="12" y2="3"></line><line x1="20" y1="21" x2="20" y2="16"></line><line x1="20" y1="12" x2="20" y2="3"></line><line x1="1" y1="14" x2="7" y2="14"></line><line x1="9" y1="8" x2="15" y2="8"></line><line x1="17" y1="16" x2="23" y2="16"></line>',tool:'<path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"></path>',wrench:'<path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"></path>',terminal:'<polyline points="4 17 10 11 4 5"></polyline><line x1="12" y1="19" x2="20" y2="19"></line>',code:'<polyline points="16 18 22 12 16 6"></polyline><polyline points="8 6 2 12 8 18"></polyline>',info:'<circle cx="12" cy="12" r="10"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line>',"alert-circle":'<circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="12"></line><line x1="12" y1="16" x2="12.01" y2="16"></line>',"alert-triangle":'<path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path><line x1="12" y1="9" x2="12" y2="13"></line><line x1="12" y1="17" x2="12.01" y2="17"></line>',"help-circle":'<circle cx="12" cy="12" r="10"></circle><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path><line x1="12" y1="17" x2="12.01" y2="17"></line>',bell:'<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"></path><path d="M13.73 21a2 2 0 0 1-3.46 0"></path>',"bell-off":'<path d="M13.73 21a2 2 0 0 1-3.46 0"></path><path d="M18.63 13A17.89 17.89 0 0 1 18 8"></path><path d="M6.26 6.26A5.86 5.86 0 0 0 6 8c0 7-3 9-3 9h14"></path><path d="M18 8a6 6 0 0 0-9.33-5"></path><line x1="1" y1="1" x2="23" y2="23"></line>',star:'<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon>',heart:'<path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"></path>',bookmark:'<path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"></path>',flag:'<path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z"></path><line x1="4" y1="22" x2="4" y2="15"></line>',tag:'<path d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z"></path><line x1="7" y1="7" x2="7.01" y2="7"></line>',clock:'<circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline>',calendar:'<rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line>',lock:'<rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 10 0v4"></path>',unlock:'<rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 9.9-1"></path>',key:'<path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"></path>',shield:'<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path>',link:'<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path>',"link-2":'<path d="M15 7h3a5 5 0 0 1 5 5 5 5 0 0 1-5 5h-3m-6 0H6a5 5 0 0 1-5-5 5 5 0 0 1 5-5h3"></path><line x1="8" y1="12" x2="16" y2="12"></line>',"external-link":'<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line>',"log-in":'<path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"></path><polyline points="10 17 15 12 10 7"></polyline><line x1="15" y1="12" x2="3" y2="12"></line>',"log-out":'<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path><polyline points="16 17 21 12 16 7"></polyline><line x1="21" y1="12" x2="9" y2="12"></line>',power:'<path d="M18.36 6.64a9 9 0 1 1-12.73 0"></path><line x1="12" y1="2" x2="12" y2="12"></line>',"more-horizontal":'<circle cx="12" cy="12" r="1"></circle><circle cx="19" cy="12" r="1"></circle><circle cx="5" cy="12" r="1"></circle>',"more-vertical":'<circle cx="12" cy="12" r="1"></circle><circle cx="12" cy="5" r="1"></circle><circle cx="12" cy="19" r="1"></circle>',menu:'<line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line>',home:'<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline>',globe:'<circle cx="12" cy="12" r="10"></circle><line x1="2" y1="12" x2="22" y2="12"></line><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"></path>',package:'<line x1="16.5" y1="9.4" x2="7.5" y2="4.21"></line><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path><polyline points="3.27 6.96 12 12.01 20.73 6.96"></polyline><line x1="12" y1="22.08" x2="12" y2="12"></line>',printer:'<polyline points="6 9 6 2 18 2 18 9"></polyline><path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"></path><rect x="6" y="14" width="12" height="8"></rect>',archive:'<polyline points="21 8 21 21 3 21 3 8"></polyline><rect x="1" y="3" width="22" height="5"></rect><line x1="10" y1="12" x2="14" y2="12"></line>',box:'<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path><polyline points="3.27 6.96 12 12.01 20.73 6.96"></polyline><line x1="12" y1="22.08" x2="12" y2="12"></line>',hash:'<line x1="4" y1="9" x2="20" y2="9"></line><line x1="4" y1="15" x2="20" y2="15"></line><line x1="10" y1="3" x2="8" y2="21"></line><line x1="16" y1="3" x2="14" y2="21"></line>',"at-sign":'<circle cx="12" cy="12" r="4"></circle><path d="M16 8v5a3 3 0 0 0 6 0v-1a10 10 0 1 0-3.92 7.94"></path>',percent:'<line x1="19" y1="5" x2="5" y2="19"></line><circle cx="6.5" cy="6.5" r="2.5"></circle><circle cx="17.5" cy="17.5" r="2.5"></circle>',type:'<polyline points="4 7 4 4 20 4 20 7"></polyline><line x1="9" y1="20" x2="15" y2="20"></line><line x1="12" y1="4" x2="12" y2="20"></line>',bold:'<path d="M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z"></path><path d="M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z"></path>',italic:'<line x1="19" y1="4" x2="10" y2="4"></line><line x1="14" y1="20" x2="5" y2="20"></line><line x1="15" y1="4" x2="9" y2="20"></line>',underline:'<path d="M6 3v7a6 6 0 0 0 6 6 6 6 0 0 0 6-6V3"></path><line x1="4" y1="21" x2="20" y2="21"></line>',"align-left":'<line x1="17" y1="10" x2="3" y2="10"></line><line x1="21" y1="6" x2="3" y2="6"></line><line x1="21" y1="14" x2="3" y2="14"></line><line x1="17" y1="18" x2="3" y2="18"></line>',"align-center":'<line x1="18" y1="10" x2="6" y2="10"></line><line x1="21" y1="6" x2="3" y2="6"></line><line x1="21" y1="14" x2="3" y2="14"></line><line x1="18" y1="18" x2="6" y2="18"></line>',"align-right":'<line x1="21" y1="10" x2="7" y2="10"></line><line x1="21" y1="6" x2="3" y2="6"></line><line x1="21" y1="14" x2="3" y2="14"></line><line x1="21" y1="18" x2="7" y2="18"></line>'};function A(e){return Y[e]??null}function F(e){return e.join(".")}function Z(e,n){var t;let i=e,l=null;for(const o of n){if(l=i[o]??null,!l)return null;l.type!=="item"||!((t=l.items)!=null&&t.length)?i=[]:i=l.items}return l}function D(e,n){return e.querySelector(`.context-menu-item[data-menu-path="${F(n)}"]`)}function e1(e,n){const i=e.querySelectorAll(".context-menu-submenu");for(const l of i)Number.parseInt(l.dataset.menuDepth??"0",10)>=n&&l.remove()}function n1(e,n){return e.slice(0,Math.max(0,n-1))}function t1(e,n,i){const l=e.querySelectorAll(".context-menu-item");for(const t of l){const o=t.dataset.menuPath;if(!o||t.dataset.hasSubmenu!=="true"){t.classList.remove("context-menu-item-open"),delete t.dataset.submenuSide;continue}const c=o.split(".").map(s=>Number.parseInt(s,10)),p=n.length>=c.length&&c.every((s,y)=>n[y]===s);if(t.classList.toggle("context-menu-item-open",p),!p){delete t.dataset.submenuSide;continue}const a=i(c.length),x=a==null?void 0:a.dataset.submenuSide;x?t.dataset.submenuSide=x:delete t.dataset.submenuSide}}function i1(e){if(!e)return null;if(typeof e=="string"){const i=e.trim();if(!i)return null;const l=A(i);return l?{type:"glyph",svg:l}:null}if(e.type==="app")return{type:"app",appId:e.appId};const n=A(e.name);return n?{type:"glyph",svg:n}:null}function l1(e,n){const i=i1(e.icon);if(!i)return null;if(i.type==="app"){const t=n(i.appId);if(!t)return null;const o=document.createElement("span");o.className="context-menu-icon context-menu-app-icon";const c=document.createElement("img");return c.src=t,c.alt="",c.decoding="async",o.appendChild(c),o}const l=document.createElement("span");return l.className="context-menu-icon",l.innerHTML=`<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${i.svg}</svg>`,l}function o1(e,n,i,l,t,o){const{titleEl:c,itemsEl:p}=o.getPanelElements(e);c.textContent=n??"",c.classList.toggle("is-visible",!!n),p.innerHTML="",i.forEach((a,x)=>{var N;const s=[...t,x],y=F(s);if(a.type==="separator"){const h=document.createElement("li");h.className="context-menu-divider",p.appendChild(h);return}if(a.type==="title"){const h=document.createElement("li");h.className="context-menu-section-title",h.textContent=a.label,p.appendChild(h);return}const r=document.createElement("li");r.className="context-menu-item",r.dataset.menuPath=y,a.danger&&r.classList.add("context-menu-item-danger"),a.disabled&&r.classList.add("context-menu-item-disabled");const u=l1(a,o.getAppIcon);u&&r.appendChild(u);const w=document.createElement("span");if(w.className="context-menu-label",w.textContent=a.label,r.appendChild(w),a.shortcut){const h=document.createElement("span");h.className="context-menu-shortcut",h.textContent=a.shortcut,r.appendChild(h)}const P=(N=a.items)!=null&&N.length?a.items:null;if(P){r.dataset.hasSubmenu="true";const h=A("chevron-right"),f=document.createElement("span");f.className="context-menu-submenu-indicator",h?f.innerHTML=`<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${h}</svg>`:f.textContent=">",r.appendChild(f)}if(a.disabled)r.setAttribute("aria-disabled","true");else if(P){const h=()=>{o.onOpenSubmenu({entry:r,itemPath:s,submenuItems:P,panelDepth:l+1})};r.addEventListener("pointerenter",h),r.addEventListener("click",f=>{f.preventDefault(),f.stopPropagation(),h()})}else r.addEventListener("pointerenter",()=>{o.onCloseSubmenusFrom(l+1)}),r.addEventListener("click",()=>{o.onSelectItem(a.id)});p.appendChild(r)})}const{root:L,overlay:c1,menu:v,titleEl:C,itemsEl:$}=U(),{getPanelElements:a1,createSubmenuPanel:W,getPanel:r1}=G({root:L,menu:v,titleEl:C,itemsEl:$});let H=null,d=null,g=[];async function _(){try{const e=await window.edenAPI.shellCommand("view/window-size",{});return H=e,e}catch(e){return console.error("Failed to get window size:",e),{width:window.innerWidth,height:window.innerHeight}}}async function z(e){const n=H??await _(),i=e?{x:0,y:0,width:n.width,height:n.height}:{x:0,y:0,width:0,height:0};try{await window.edenAPI.shellCommand("view/update-bounds",{bounds:i})}catch(l){console.error("Failed to update context menu bounds:",l)}}function j(e){L.classList.toggle("is-open",e)}function S(){return H??{width:window.innerWidth,height:window.innerHeight}}function E(){t1(L,g,r1)}function I(e){e1(L,e),g=n1(g,e),E()}function k(e,n,i,l,t){o1(e,n,i,l,t,{getPanelElements:a1,getAppIcon:Q,onOpenSubmenu:({entry:o,itemPath:c,submenuItems:p,panelDepth:a})=>{I(a),g=c;const x=W(a);k(x,void 0,p,a,c),q(x,o,S),E()},onCloseSubmenusFrom:I,onSelectItem:o=>{b("select",o)}})}function y1(e){var n;if(!d||e.length===0){E();return}I(1);for(let i=0;i<e.length;i+=1){const l=e.slice(0,i+1),t=Z(d.items,l),o=D(L,l);if(!t||t.type!=="item"||!((n=t.items)!=null&&n.length)||!o){g=l.slice(0,i);break}g=l;const c=W(i+1);k(c,void 0,t.items,i+1,l),q(c,o,S)}E()}function b(e,n,i=!0){if(!d)return;const{requestId:l}=d;d=null,g=[],j(!1),C.textContent="",C.classList.remove("is-visible"),$.innerHTML="",I(1),z(!1),i&&window.edenAPI.shellCommand("context-menu/resolve",{requestId:l,itemId:n,reason:e})}async function p1(e){d&&b("replaced",void 0,!1),d={requestId:e.requestId,position:e.position,items:e.items},await X(e.items),await z(!0),j(!0),k(v,e.title,e.items,0,[]),R(v,e.position,S),E(),v.focus()}async function s1(){await window.edenAPI.shellCommand("context-menu/register-display",{}),await _(),await z(!1),c1.addEventListener("click",()=>b("dismiss")),v.addEventListener("click",e=>e.stopPropagation()),v.addEventListener("contextmenu",e=>e.preventDefault()),window.addEventListener("keydown",e=>{e.key==="Escape"&&b("dismiss")}),await window.edenAPI.subscribe("context-menu/opened",({menu:e})=>{p1(e)}),await window.edenAPI.subscribe("context-menu/closed",e=>{!d||d.requestId!==e.requestId||e.reason==="select"||e.reason==="dismiss"||b(e.reason,e.itemId,!1)}),await window.edenAPI.subscribe("view/global-bounds-changed",({windowSize:e})=>{if(H=e,d){z(!0);const n=[...g];R(v,d.position,S),y1(n)}}),console.log("Eden Context Menu ready!")}s1();
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<meta charset="UTF-8" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>Eden Context Menu</title>
|
|
8
|
-
<script type="module" crossorigin src="./assets/index-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
8
|
+
<script type="module" crossorigin src="./assets/index-CQD24gQV.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="./assets/index-B3l0_BgM.css">
|
|
10
10
|
</head>
|
|
11
11
|
|
|
12
12
|
<body>
|