database-devtools 0.1.0
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/LICENSE +5 -0
- package/dist/adapter/index.cjs +314 -0
- package/dist/adapter/index.cjs.map +1 -0
- package/dist/adapter/index.d.cts +34 -0
- package/dist/adapter/index.d.ts +34 -0
- package/dist/adapter/index.js +6 -0
- package/dist/adapter/index.js.map +1 -0
- package/dist/adapter-BjJm71wW.d.cts +30 -0
- package/dist/adapter-DJSjDewg.d.ts +30 -0
- package/dist/adapters/sqlite/index.cjs +251 -0
- package/dist/adapters/sqlite/index.cjs.map +1 -0
- package/dist/adapters/sqlite/index.d.cts +21 -0
- package/dist/adapters/sqlite/index.d.ts +21 -0
- package/dist/adapters/sqlite/index.js +6 -0
- package/dist/adapters/sqlite/index.js.map +1 -0
- package/dist/chunk-2JGL2JVD.js +52 -0
- package/dist/chunk-2JGL2JVD.js.map +1 -0
- package/dist/chunk-AZECU6D7.js +27 -0
- package/dist/chunk-AZECU6D7.js.map +1 -0
- package/dist/chunk-BLOSGEQV.js +71 -0
- package/dist/chunk-BLOSGEQV.js.map +1 -0
- package/dist/chunk-CPVVIH5G.js +258 -0
- package/dist/chunk-CPVVIH5G.js.map +1 -0
- package/dist/chunk-DGUM43GV.js +10 -0
- package/dist/chunk-DGUM43GV.js.map +1 -0
- package/dist/chunk-HIDZTOJ3.js +9 -0
- package/dist/chunk-HIDZTOJ3.js.map +1 -0
- package/dist/chunk-I65IM47D.js +243 -0
- package/dist/chunk-I65IM47D.js.map +1 -0
- package/dist/chunk-MXVIGMVT.js +3 -0
- package/dist/chunk-MXVIGMVT.js.map +1 -0
- package/dist/chunk-O6AO7KHA.js +3 -0
- package/dist/chunk-O6AO7KHA.js.map +1 -0
- package/dist/chunk-TNDOAHT5.js +1784 -0
- package/dist/chunk-TNDOAHT5.js.map +1 -0
- package/dist/chunk-ZS5MZR75.js +655 -0
- package/dist/chunk-ZS5MZR75.js.map +1 -0
- package/dist/cli.cjs +2053 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/client/index.cjs +947 -0
- package/dist/client/index.cjs.map +1 -0
- package/dist/client/index.d.cts +75 -0
- package/dist/client/index.d.ts +75 -0
- package/dist/client/index.js +98 -0
- package/dist/client/index.js.map +1 -0
- package/dist/createDevToolsServer-B7NQ_5H4.d.cts +292 -0
- package/dist/createDevToolsServer-DlNMoCJR.d.ts +292 -0
- package/dist/handleDeviceSnapshot-CR-4QMdk.d.ts +116 -0
- package/dist/handleDeviceSnapshot-cYGuitSc.d.cts +116 -0
- package/dist/index.cjs +5877 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +61 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.js +2748 -0
- package/dist/index.js.map +1 -0
- package/dist/inspector/index.cjs +57 -0
- package/dist/inspector/index.cjs.map +1 -0
- package/dist/inspector/index.d.cts +26 -0
- package/dist/inspector/index.d.ts +26 -0
- package/dist/inspector/index.js +5 -0
- package/dist/inspector/index.js.map +1 -0
- package/dist/inspectors/sqlite/index.cjs +306 -0
- package/dist/inspectors/sqlite/index.cjs.map +1 -0
- package/dist/inspectors/sqlite/index.d.cts +53 -0
- package/dist/inspectors/sqlite/index.d.ts +53 -0
- package/dist/inspectors/sqlite/index.js +260 -0
- package/dist/inspectors/sqlite/index.js.map +1 -0
- package/dist/register-BuicFu9L.d.cts +32 -0
- package/dist/register-aITLN9Q9.d.ts +32 -0
- package/dist/server/index.cjs +1948 -0
- package/dist/server/index.cjs.map +1 -0
- package/dist/server/index.d.cts +15 -0
- package/dist/server/index.d.ts +15 -0
- package/dist/server/index.js +7 -0
- package/dist/server/index.js.map +1 -0
- package/dist/snapshot-Dhyecgo2.d.cts +33 -0
- package/dist/snapshot-Dhyecgo2.d.ts +33 -0
- package/dist/types/protocol.cjs +309 -0
- package/dist/types/protocol.cjs.map +1 -0
- package/dist/types/protocol.d.cts +291 -0
- package/dist/types/protocol.d.ts +291 -0
- package/dist/types/protocol.js +4 -0
- package/dist/types/protocol.js.map +1 -0
- package/dist/types-BRLJdBRY.d.cts +16 -0
- package/dist/types-CF6qEU-_.d.ts +16 -0
- package/dist/types-CIA11diJ.d.cts +62 -0
- package/dist/types-CKVRCX-e.d.ts +62 -0
- package/dist/web/assets/index-CLEaIsUd.css +1 -0
- package/dist/web/assets/index-DQrPRTOy.js +100 -0
- package/dist/web/assets/sql-wasm-UFUCzYNW.wasm +0 -0
- package/dist/web/index.html +26 -0
- package/dist/write-C3toEIMs.d.cts +21 -0
- package/dist/write-C3toEIMs.d.ts +21 -0
- package/package.json +137 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server/connectionManager.ts","../src/server/cors.ts","../src/server/deviceRegistry.ts","../src/utils/logger.ts","../src/server/heartbeat.ts","../src/server/messageRouter.ts","../src/server/pendingRefreshStore.ts","../src/server/refreshCoordinator.ts","../src/server/snapshotStore.ts","../src/server/attachWebUi.ts","../src/server/attachWebSocket.ts","../src/server/projectData.ts","../src/server/deviceExportStorage.ts","../src/server/migrateLegacyActiveDb.ts","../src/server/snapshotFileStore.ts","../src/server/writeCoordinator.ts","../src/server/writeSessionManager.ts","../src/server/createDevToolsServer.ts"],"names":["path","express","readFile","writeFile","mkdir","stat","rm","absolutePath"],"mappings":"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","file":"chunk-TNDOAHT5.js","sourcesContent":["import type { WebSocket } from 'ws';\nimport type { DevToolsRole, DeviceMetadata } from '../types/protocol';\nimport { generateConnectionId } from '../utils/ids';\n\nexport type ConnectedClient = {\n socket: WebSocket;\n connectionId: string;\n role: DevToolsRole;\n deviceId?: string;\n metadata?: DeviceMetadata;\n connectedAt: number;\n lastPongAt: number;\n};\n\nexport type RegisterClientInput = {\n socket: WebSocket;\n role: DevToolsRole;\n deviceId?: string;\n metadata?: DeviceMetadata;\n};\n\nexport class ConnectionManager {\n private readonly clients = new Map<WebSocket, ConnectedClient>();\n\n add(input: RegisterClientInput): ConnectedClient {\n const now = Date.now();\n const client: ConnectedClient = {\n socket: input.socket,\n connectionId: generateConnectionId(),\n role: input.role,\n deviceId: input.deviceId,\n metadata: input.metadata,\n connectedAt: now,\n lastPongAt: now,\n };\n\n this.clients.set(input.socket, client);\n return client;\n }\n\n remove(socket: WebSocket): ConnectedClient | undefined {\n const client = this.clients.get(socket);\n\n if (client) {\n this.clients.delete(socket);\n }\n\n return client;\n }\n\n getBySocket(socket: WebSocket): ConnectedClient | undefined {\n return this.clients.get(socket);\n }\n\n getByConnectionId(connectionId: string): ConnectedClient | undefined {\n for (const client of this.clients.values()) {\n if (client.connectionId === connectionId) {\n return client;\n }\n }\n\n return undefined;\n }\n\n getByDeviceId(deviceId: string): ConnectedClient | undefined {\n for (const client of this.clients.values()) {\n if (client.deviceId === deviceId) {\n return client;\n }\n }\n\n return undefined;\n }\n\n getByRole(role: DevToolsRole): ConnectedClient[] {\n return [...this.clients.values()].filter((client) => client.role === role);\n }\n\n updateLastPong(socket: WebSocket): void {\n const client = this.clients.get(socket);\n\n if (client) {\n client.lastPongAt = Date.now();\n }\n }\n\n getAll(): ConnectedClient[] {\n return [...this.clients.values()];\n }\n}\n","import type { NextFunction, Request, Response } from 'express';\r\nimport {\r\n SNAPSHOT_KIND_HEADER,\r\n SNAPSHOT_MIME_HEADER,\r\n SNAPSHOT_NAME_HEADER,\r\n} from '../types/snapshot';\r\n\r\nconst ALLOWED_METHODS = 'GET, POST, OPTIONS';\r\n\r\nconst ALLOWED_HEADERS = [\r\n 'Content-Type',\r\n SNAPSHOT_KIND_HEADER,\r\n SNAPSHOT_MIME_HEADER,\r\n SNAPSHOT_NAME_HEADER,\r\n].join(', ');\r\n\r\nexport type CorsOptions = {\r\n /** Fixed origin, or `*` when request has no Origin header. */\r\n allowedOrigin?: string;\r\n};\r\n\r\nexport function resolveCorsOrigin(\r\n requestOrigin: string | undefined,\r\n configuredOrigin?: string,\r\n): string {\r\n if (configuredOrigin) {\r\n return configuredOrigin;\r\n }\r\n\r\n if (!requestOrigin) {\r\n return '*';\r\n }\r\n\r\n try {\r\n const url = new URL(requestOrigin);\r\n const isLocalDev =\r\n url.hostname === 'localhost' ||\r\n url.hostname === '127.0.0.1' ||\r\n url.hostname === '10.0.2.2';\r\n\r\n if (isLocalDev) {\r\n return requestOrigin;\r\n }\r\n } catch {\r\n return '*';\r\n }\r\n\r\n return '*';\r\n}\r\n\r\nexport function createCorsMiddleware(options: CorsOptions = {}) {\r\n const configuredOrigin = options.allowedOrigin ?? process.env.DATABASE_DEVTOOLS_CORS_ORIGIN;\r\n\r\n return (request: Request, response: Response, next: NextFunction): void => {\r\n const origin = resolveCorsOrigin(request.header('origin'), configuredOrigin);\r\n\r\n response.setHeader('Access-Control-Allow-Origin', origin);\r\n response.setHeader('Access-Control-Allow-Methods', ALLOWED_METHODS);\r\n response.setHeader('Access-Control-Allow-Headers', ALLOWED_HEADERS);\r\n response.setHeader('Vary', 'Origin');\r\n\r\n if (request.method === 'OPTIONS') {\r\n response.status(204).end();\r\n return;\r\n }\r\n\r\n next();\r\n };\r\n}\r\n","import type { ConnectionManager } from './connectionManager';\nimport type { DeviceStatusPayload } from '../types/protocol';\nimport { DevToolsRole } from '../types/protocol';\n\nexport class DeviceRegistry {\n constructor(private readonly connectionManager: ConnectionManager) {}\n\n snapshot(): DeviceStatusPayload {\n const browsers = this.connectionManager\n .getByRole(DevToolsRole.BROWSER)\n .map((client) => ({\n connectionId: client.connectionId,\n connectedAt: client.connectedAt,\n }));\n\n const mobiles = this.connectionManager\n .getByRole(DevToolsRole.MOBILE)\n .map((client) => ({\n deviceId: client.deviceId ?? client.connectionId,\n connectionId: client.connectionId,\n connectedAt: client.connectedAt,\n metadata: client.metadata,\n }));\n\n return {\n browserCount: browsers.length,\n mobileCount: mobiles.length,\n browsers,\n mobiles,\n };\n }\n}\n","const RESET = '\\x1b[0m';\r\nconst GREEN = '\\x1b[32m';\r\nconst YELLOW = '\\x1b[33m';\r\nconst CYAN = '\\x1b[36m';\r\nconst RED = '\\x1b[31m';\r\nconst DIM = '\\x1b[2m';\r\n\r\nconst PREFIX = `${DIM}[database-devtools]${RESET}`;\r\n\r\nfunction log(color: string, symbol: string, message: string): void {\r\n console.log(`${PREFIX} ${color}${symbol}${RESET} ${message}`);\r\n}\r\n\r\nexport const logger = {\r\n browserConnected(connectionId?: string): void {\r\n const suffix = connectionId ? ` ${DIM}(${connectionId})${RESET}` : '';\r\n log(GREEN, '✓', `Browser Connected${suffix}`);\r\n },\r\n\r\n browserDisconnected(connectionId?: string): void {\r\n const suffix = connectionId ? ` ${DIM}(${connectionId})${RESET}` : '';\r\n log(YELLOW, '✓', `Browser Disconnected${suffix}`);\r\n },\r\n\r\n mobileConnected(deviceId?: string): void {\r\n const suffix = deviceId ? ` ${DIM}(deviceId: ${deviceId})${RESET}` : '';\r\n log(GREEN, '✓', `Mobile Connected${suffix}`);\r\n },\r\n\r\n mobileDisconnected(deviceId?: string): void {\r\n const suffix = deviceId ? ` ${DIM}(deviceId: ${deviceId})${RESET}` : '';\r\n log(YELLOW, '✓', `Mobile Disconnected${suffix}`);\r\n },\r\n\r\n broadcastSent(target?: string): void {\r\n const suffix = target ? ` ${DIM}→ ${target}${RESET}` : '';\r\n log(CYAN, '✓', `Broadcast Sent${suffix}`);\r\n },\r\n\r\n serverStarted(url: string, wsUrl: string, webUiEnabled = false): void {\r\n log(GREEN, '✓', `Server started at ${url}`);\r\n log(GREEN, '✓', `WebSocket endpoint ${wsUrl}`);\r\n\r\n if (webUiEnabled) {\r\n log(GREEN, '✓', `Browser UI available at ${url}`);\r\n }\r\n },\r\n\r\n heartbeatTimeout(connectionId: string): void {\r\n log(RED, '✓', `Heartbeat timeout — removing ${connectionId}`);\r\n },\r\n\r\n refreshStarted(deviceId: string): void {\r\n log(CYAN, '↻', `Refresh started ${DIM}(${deviceId})${RESET}`);\r\n },\r\n\r\n refreshUploaded(deviceId: string, bytes: number): void {\r\n log(GREEN, '↻', `Snapshot uploaded ${DIM}(${deviceId}, ${bytes} bytes)${RESET}`);\r\n },\r\n\r\n refreshFailed(deviceId: string, code: string, message: string): void {\r\n log(RED, '↻', `Refresh failed ${DIM}(${deviceId}: ${code})${RESET} ${message}`);\r\n },\r\n\r\n /** @deprecated Use refreshStarted */\r\n syncStarted(syncId: string, deviceId: string): void {\r\n this.refreshStarted(deviceId);\r\n },\r\n\r\n /** @deprecated Use refreshUploaded */\r\n syncUploaded(syncId: string, bytes: number): void {\r\n this.refreshUploaded(syncId, bytes);\r\n },\r\n\r\n /** @deprecated Use refreshFailed */\r\n syncFailed(syncId: string, code: string, message: string): void {\r\n this.refreshFailed(syncId, code, message);\r\n },\r\n\r\n error(message: string): void {\r\n log(RED, '✗', message);\r\n },\r\n};\r\n","import {\n createMessage,\n HEARTBEAT_INTERVAL_MS,\n HEARTBEAT_TIMEOUT_MS,\n MessageType,\n type PingMessage,\n} from '../types/protocol';\nimport { generatePingId } from '../utils/ids';\nimport { logger } from '../utils/logger';\nimport type { ConnectionManager } from './connectionManager';\nimport type { MessageRouter } from './messageRouter';\n\nexport class Heartbeat {\n private interval: ReturnType<typeof setInterval> | null = null;\n\n constructor(\n private readonly connectionManager: ConnectionManager,\n private readonly router: MessageRouter,\n ) {}\n\n start(): void {\n if (this.interval !== null) {\n return;\n }\n\n this.interval = setInterval(() => {\n this.pingAll();\n this.removeStaleConnections();\n }, HEARTBEAT_INTERVAL_MS);\n }\n\n stop(): void {\n if (this.interval !== null) {\n clearInterval(this.interval);\n this.interval = null;\n }\n }\n\n private pingAll(): void {\n const pingId = generatePingId();\n const message = createMessage<PingMessage>({\n type: MessageType.PING,\n pingId,\n });\n\n for (const client of this.connectionManager.getAll()) {\n this.router.sendToSocket(client.socket, message);\n }\n }\n\n private removeStaleConnections(): void {\n const now = Date.now();\n\n for (const client of this.connectionManager.getAll()) {\n if (now - client.lastPongAt > HEARTBEAT_INTERVAL_MS + HEARTBEAT_TIMEOUT_MS) {\n logger.heartbeatTimeout(client.connectionId);\n client.socket.terminate();\n this.connectionManager.remove(client.socket);\n }\n }\n }\n}\n","import type { WebSocket } from 'ws';\nimport {\n createMessage,\n DevToolsRole,\n MessageType,\n type BroadcastMessage,\n type DeviceStatusMessage,\n type ServerMessage,\n} from '../types/protocol';\nimport { logger } from '../utils/logger';\nimport type { ConnectionManager } from './connectionManager';\nimport type { DeviceRegistry } from './deviceRegistry';\n\nexport type OutboundMessage = ServerMessage;\n\nexport class MessageRouter {\n constructor(\n private readonly connectionManager: ConnectionManager,\n private readonly deviceRegistry: DeviceRegistry,\n ) {}\n\n sendToSocket(socket: WebSocket, message: OutboundMessage): void {\n if (socket.readyState === socket.OPEN) {\n socket.send(JSON.stringify(message));\n }\n }\n\n sendToBrowser(connectionId: string, message: OutboundMessage): void {\n const client = this.connectionManager.getByConnectionId(connectionId);\n\n if (client?.role === DevToolsRole.BROWSER) {\n this.sendToSocket(client.socket, message);\n }\n }\n\n sendToMobile(deviceId: string, message: OutboundMessage): void {\n const client = this.connectionManager.getByDeviceId(deviceId);\n\n if (client?.role === DevToolsRole.MOBILE) {\n this.sendToSocket(client.socket, message);\n }\n }\n\n broadcastToBrowsers(message: OutboundMessage): void {\n for (const client of this.connectionManager.getByRole(DevToolsRole.BROWSER)) {\n this.sendToSocket(client.socket, message);\n }\n\n logger.broadcastSent('browsers');\n }\n\n broadcastToMobiles(message: OutboundMessage): void {\n for (const client of this.connectionManager.getByRole(DevToolsRole.MOBILE)) {\n this.sendToSocket(client.socket, message);\n }\n\n logger.broadcastSent('mobiles');\n }\n\n broadcastToAll(message: OutboundMessage): void {\n for (const client of this.connectionManager.getAll()) {\n this.sendToSocket(client.socket, message);\n }\n\n logger.broadcastSent('all');\n }\n\n broadcast(message: unknown, target: 'browsers' | 'mobiles' | 'all' = 'all'): void {\n const broadcastMessage = createMessage<BroadcastMessage>({\n type: MessageType.BROADCAST,\n payload: message,\n });\n\n if (target === 'browsers') {\n this.broadcastToBrowsers(broadcastMessage);\n return;\n }\n\n if (target === 'mobiles') {\n this.broadcastToMobiles(broadcastMessage);\n return;\n }\n\n this.broadcastToAll(broadcastMessage);\n }\n\n broadcastDeviceStatus(): void {\n const message = createMessage<DeviceStatusMessage>({\n type: MessageType.DEVICE_STATUS,\n payload: this.deviceRegistry.snapshot(),\n });\n\n this.broadcastToAll(message);\n }\n}\n","import type { RefreshInitiator, RefreshType } from '../types/protocol';\r\nimport { REFRESH_TIMEOUT_MS } from '../types/protocol';\r\n\r\nexport type PendingRefresh = {\r\n deviceId: string;\r\n refreshType: RefreshType;\r\n startedAt: number;\r\n initiator: RefreshInitiator;\r\n browserConnectionId?: string;\r\n notifyAllBrowsers?: boolean;\r\n};\r\n\r\nexport class PendingRefreshStore {\r\n private readonly pendingByDevice = new Map<string, PendingRefresh>();\r\n\r\n create(input: PendingRefresh): void {\r\n this.pendingByDevice.set(input.deviceId, input);\r\n }\r\n\r\n get(deviceId: string): PendingRefresh | undefined {\r\n return this.pendingByDevice.get(deviceId);\r\n }\r\n\r\n has(deviceId: string): boolean {\r\n return this.pendingByDevice.has(deviceId);\r\n }\r\n\r\n remove(deviceId: string): void {\r\n this.pendingByDevice.delete(deviceId);\r\n }\r\n\r\n getExpired(now = Date.now()): PendingRefresh[] {\r\n return [...this.pendingByDevice.values()].filter(\r\n (pending) => now - pending.startedAt >= REFRESH_TIMEOUT_MS,\r\n );\r\n }\r\n}\r\n","import type { WebSocket } from 'ws';\r\nimport {\r\n createMessage,\r\n DevToolsRole,\r\n MessageType,\r\n type ExportSnapshotErrorMessage,\r\n type ExportSnapshotRequestMessage,\r\n type RefreshErrorCode,\r\n type RefreshErrorMessage,\r\n type RefreshRequestMessage,\r\n type RefreshState,\r\n type RefreshStatusMessage,\r\n type SnapshotReadyMessage,\r\n type SnapshotUploadRequestedMessage,\r\n} from '../types/protocol';\r\nimport { logger } from '../utils/logger';\r\nimport type { ConnectionManager } from './connectionManager';\r\nimport type { MessageRouter } from './messageRouter';\r\nimport type { PendingRefreshStore } from './pendingRefreshStore';\r\nimport type { SnapshotFileStore } from './snapshotFileStore';\r\nimport type { SnapshotStore } from './snapshotStore';\r\n\r\nexport class RefreshCoordinator {\r\n constructor(\r\n private readonly connectionManager: ConnectionManager,\r\n private readonly router: MessageRouter,\r\n private readonly pending: PendingRefreshStore,\r\n private readonly snapshots: SnapshotStore,\r\n private readonly snapshotFiles?: SnapshotFileStore,\r\n ) {}\r\n\r\n handleRefreshRequest(browserSocket: WebSocket, message: RefreshRequestMessage): void {\r\n const browser = this.connectionManager.getBySocket(browserSocket);\r\n\r\n if (!browser || browser.role !== DevToolsRole.BROWSER) {\r\n return;\r\n }\r\n\r\n if (message.refreshType !== 'snapshot') {\r\n this.sendRefreshError(browser.connectionId, {\r\n deviceId: message.deviceId,\r\n code: 'INVALID_REQUEST',\r\n message: `Unsupported refresh type: ${message.refreshType}`,\r\n });\r\n return;\r\n }\r\n\r\n const mobile = this.connectionManager.getByDeviceId(message.deviceId);\r\n\r\n if (!mobile) {\r\n this.sendRefreshError(browser.connectionId, {\r\n deviceId: message.deviceId,\r\n code: 'DEVICE_OFFLINE',\r\n message: `Device ${message.deviceId} is not connected`,\r\n });\r\n return;\r\n }\r\n\r\n if (this.pending.has(message.deviceId)) {\r\n this.sendRefreshError(browser.connectionId, {\r\n deviceId: message.deviceId,\r\n code: 'REFRESH_IN_PROGRESS',\r\n message: 'A refresh is already in progress for this device',\r\n });\r\n return;\r\n }\r\n\r\n this.pending.create({\r\n deviceId: message.deviceId,\r\n initiator: 'browser',\r\n browserConnectionId: browser.connectionId,\r\n refreshType: message.refreshType,\r\n startedAt: Date.now(),\r\n });\r\n\r\n logger.refreshStarted(message.deviceId);\r\n\r\n this.sendRefreshStatus(browser.connectionId, message.deviceId, 'requested');\r\n this.sendRefreshStatus(browser.connectionId, message.deviceId, 'exporting');\r\n\r\n this.requestMobileUpload(message.deviceId, message.refreshType);\r\n }\r\n\r\n handleMobileExportRequest(mobileSocket: WebSocket, message: ExportSnapshotRequestMessage): void {\r\n const mobile = this.connectionManager.getBySocket(mobileSocket);\r\n\r\n if (!mobile || mobile.role !== DevToolsRole.MOBILE || !mobile.deviceId) {\r\n return;\r\n }\r\n\r\n if (message.refreshType !== 'snapshot') {\r\n this.sendExportSnapshotError(mobileSocket, {\r\n code: 'INVALID_REQUEST',\r\n message: `Unsupported refresh type: ${message.refreshType}`,\r\n });\r\n return;\r\n }\r\n\r\n if (this.pending.has(mobile.deviceId)) {\r\n this.sendExportSnapshotError(mobileSocket, {\r\n code: 'REFRESH_IN_PROGRESS',\r\n message: 'An export is already in progress for this device',\r\n });\r\n return;\r\n }\r\n\r\n this.pending.create({\r\n deviceId: mobile.deviceId,\r\n initiator: 'mobile',\r\n notifyAllBrowsers: true,\r\n refreshType: message.refreshType,\r\n startedAt: Date.now(),\r\n });\r\n\r\n logger.refreshStarted(mobile.deviceId);\r\n\r\n this.requestMobileUpload(mobile.deviceId, message.refreshType);\r\n }\r\n\r\n async handleSnapshotUpload(\r\n deviceId: string,\r\n body: Buffer,\r\n metadata?: { kind?: string; mimeType?: string; databaseName?: string },\r\n ): Promise<{ ok: true; stored: SnapshotReadyMessage } | { ok: false; code: RefreshErrorCode }> {\r\n const pending = this.pending.get(deviceId);\r\n\r\n if (!pending) {\r\n return { ok: false, code: 'SNAPSHOT_NOT_FOUND' };\r\n }\r\n\r\n if (pending.browserConnectionId) {\r\n this.sendRefreshStatus(pending.browserConnectionId, deviceId, 'uploading');\r\n }\r\n\r\n const stored = this.snapshots.set(deviceId, body, {\r\n kind: metadata?.kind ?? 'sqlite',\r\n mimeType: metadata?.mimeType ?? 'application/x-sqlite3',\r\n databaseName: metadata?.databaseName,\r\n });\r\n\r\n const mobile = this.connectionManager.getByDeviceId(deviceId);\r\n\r\n await this.snapshotFiles?.persistDeviceSnapshot({\r\n deviceId,\r\n bytes: body,\r\n kind: stored.kind,\r\n mimeType: stored.mimeType,\r\n databaseName: stored.databaseName,\r\n bundleId: mobile?.metadata?.bundleId,\r\n });\r\n\r\n logger.refreshUploaded(deviceId, body.byteLength);\r\n\r\n const readyMessage = createMessage<SnapshotReadyMessage>({\r\n type: MessageType.SNAPSHOT_READY,\r\n deviceId,\r\n size: body.byteLength,\r\n exportedAt: stored.exportedAt,\r\n kind: stored.kind,\r\n mimeType: stored.mimeType,\r\n ...(stored.databaseName ? { databaseName: stored.databaseName } : {}),\r\n });\r\n\r\n if (pending.notifyAllBrowsers) {\r\n this.router.broadcastToBrowsers(readyMessage);\r\n } else if (pending.browserConnectionId) {\r\n this.sendRefreshStatus(pending.browserConnectionId, deviceId, 'ready');\r\n this.router.sendToBrowser(pending.browserConnectionId, readyMessage);\r\n }\r\n\r\n this.pending.remove(deviceId);\r\n\r\n return { ok: true, stored: readyMessage };\r\n }\r\n\r\n getSnapshot(deviceId: string): Buffer | undefined {\r\n return this.snapshots.getBytes(deviceId);\r\n }\r\n\r\n async getSnapshotAsync(deviceId: string): Promise<Buffer | undefined> {\r\n if (this.snapshotFiles) {\r\n const fromDisk = await this.snapshotFiles.readDeviceSnapshot(deviceId);\r\n\r\n if (fromDisk) {\r\n return fromDisk;\r\n }\r\n }\r\n\r\n return this.snapshots.getBytes(deviceId);\r\n }\r\n\r\n checkTimeouts(): void {\r\n for (const pending of this.pending.getExpired()) {\r\n if (pending.initiator === 'mobile') {\r\n this.failMobileExport(\r\n pending.deviceId,\r\n 'TIMEOUT',\r\n 'Export timed out waiting for device upload',\r\n );\r\n continue;\r\n }\r\n\r\n if (pending.browserConnectionId) {\r\n this.failRefresh(\r\n pending.deviceId,\r\n pending.browserConnectionId,\r\n 'TIMEOUT',\r\n 'Refresh timed out waiting for device upload',\r\n );\r\n } else {\r\n this.pending.remove(pending.deviceId);\r\n }\r\n }\r\n }\r\n\r\n private requestMobileUpload(deviceId: string, refreshType: 'snapshot'): void {\r\n this.router.sendToMobile(\r\n deviceId,\r\n createMessage<SnapshotUploadRequestedMessage>({\r\n type: MessageType.SNAPSHOT_UPLOAD_REQUESTED,\r\n deviceId,\r\n refreshType,\r\n }),\r\n );\r\n }\r\n\r\n private failRefresh(\r\n deviceId: string,\r\n browserConnectionId: string,\r\n code: RefreshErrorCode,\r\n message: string,\r\n ): void {\r\n logger.refreshFailed(deviceId, code, message);\r\n\r\n this.sendRefreshError(browserConnectionId, {\r\n deviceId,\r\n code,\r\n message,\r\n });\r\n\r\n this.pending.remove(deviceId);\r\n }\r\n\r\n private failMobileExport(\r\n deviceId: string,\r\n code: RefreshErrorCode,\r\n message: string,\r\n ): void {\r\n logger.refreshFailed(deviceId, code, message);\r\n\r\n const mobile = this.connectionManager.getByDeviceId(deviceId);\r\n\r\n if (mobile) {\r\n this.sendExportSnapshotError(mobile.socket, { code, message });\r\n }\r\n\r\n const refreshError = createMessage<RefreshErrorMessage>({\r\n type: MessageType.REFRESH_ERROR,\r\n deviceId,\r\n code,\r\n message,\r\n });\r\n\r\n this.router.broadcastToBrowsers(refreshError);\r\n this.pending.remove(deviceId);\r\n }\r\n\r\n private sendRefreshStatus(\r\n browserConnectionId: string,\r\n deviceId: string,\r\n state: RefreshState,\r\n ): void {\r\n const statusMessage = createMessage<RefreshStatusMessage>({\r\n type: MessageType.REFRESH_STATUS,\r\n deviceId,\r\n state,\r\n });\r\n\r\n this.router.sendToBrowser(browserConnectionId, statusMessage);\r\n }\r\n\r\n private sendRefreshError(\r\n browserConnectionId: string,\r\n input: {\r\n deviceId: string;\r\n code: RefreshErrorCode;\r\n message: string;\r\n },\r\n ): void {\r\n const message = createMessage<RefreshErrorMessage>({\r\n type: MessageType.REFRESH_ERROR,\r\n deviceId: input.deviceId,\r\n code: input.code,\r\n message: input.message,\r\n });\r\n\r\n this.router.sendToBrowser(browserConnectionId, message);\r\n logger.refreshFailed(input.deviceId, input.code, input.message);\r\n }\r\n\r\n private sendExportSnapshotError(\r\n mobileSocket: WebSocket,\r\n input: {\r\n code: RefreshErrorCode;\r\n message: string;\r\n },\r\n ): void {\r\n const message = createMessage<ExportSnapshotErrorMessage>({\r\n type: MessageType.EXPORT_SNAPSHOT_ERROR,\r\n code: input.code,\r\n message: input.message,\r\n });\r\n\r\n this.router.sendToSocket(mobileSocket, message);\r\n }\r\n}\r\n","export type StoredSnapshot = {\r\n deviceId: string;\r\n bytes: Buffer;\r\n kind: string;\r\n mimeType: string;\r\n databaseName?: string;\r\n exportedAt: number;\r\n};\r\n\r\nexport class SnapshotStore {\r\n private readonly snapshots = new Map<string, StoredSnapshot>();\r\n\r\n set(\r\n deviceId: string,\r\n bytes: Buffer,\r\n metadata: { kind: string; mimeType: string; databaseName?: string },\r\n ): StoredSnapshot {\r\n const stored: StoredSnapshot = {\r\n deviceId,\r\n bytes,\r\n kind: metadata.kind,\r\n mimeType: metadata.mimeType,\r\n databaseName: metadata.databaseName,\r\n exportedAt: Date.now(),\r\n };\r\n\r\n this.snapshots.set(deviceId, stored);\r\n return stored;\r\n }\r\n\r\n get(deviceId: string): StoredSnapshot | undefined {\r\n return this.snapshots.get(deviceId);\r\n }\r\n\r\n getBytes(deviceId: string): Buffer | undefined {\r\n return this.snapshots.get(deviceId)?.bytes;\r\n }\r\n}\r\n","import { existsSync } from 'node:fs';\r\nimport path from 'node:path';\r\nimport type { Express, Request, Response } from 'express';\r\nimport express from 'express';\r\n\r\nfunction shouldServeSpa(request: Request): boolean {\r\n if (request.method !== 'GET' && request.method !== 'HEAD') {\r\n return false;\r\n }\r\n\r\n if (request.path.startsWith('/api')) {\r\n return false;\r\n }\r\n\r\n if (request.path === '/health') {\r\n return false;\r\n }\r\n\r\n return true;\r\n}\r\n\r\nexport function attachWebUi(app: Express, webDistPath: string): void {\r\n const indexPath = path.join(webDistPath, 'index.html');\r\n\r\n if (!existsSync(indexPath)) {\r\n return;\r\n }\r\n\r\n app.use(\r\n express.static(webDistPath, {\r\n index: false,\r\n setHeaders(response, filePath) {\r\n if (filePath.endsWith('.wasm')) {\r\n response.setHeader('Content-Type', 'application/wasm');\r\n }\r\n },\r\n }),\r\n );\r\n\r\n app.get('*', (request: Request, response: Response, next) => {\r\n if (!shouldServeSpa(request)) {\r\n next();\r\n return;\r\n }\r\n\r\n response.sendFile(indexPath);\r\n });\r\n}\r\n","import type { Server } from 'node:http';\r\nimport { WebSocketServer, type WebSocket } from 'ws';\r\nimport {\r\n DEVTOOLS_WS_PATH,\r\n DevToolsRole,\r\n isBeginTransactionRequestMessage,\r\n isCommitTransactionRequestMessage,\r\n isExportSnapshotRequestMessage,\r\n isPongMessage,\r\n isRefreshRequestMessage,\r\n isRegisterMessage,\r\n isRollbackTransactionRequestMessage,\r\n isTransactionAckMessage,\r\n isWriteAckMessage,\r\n isWriteRequestMessage,\r\n} from '../types/protocol';\r\nimport { logger } from '../utils/logger';\r\nimport type { ConnectionManager } from './connectionManager';\r\nimport type { Heartbeat } from './heartbeat';\r\nimport type { MessageRouter } from './messageRouter';\r\nimport type { RefreshCoordinator } from './refreshCoordinator';\r\nimport type { SnapshotFileStore } from './snapshotFileStore';\r\nimport type { WriteCoordinator } from './writeCoordinator';\r\n\r\nexport type AttachWebSocketOptions = {\r\n snapshotFileStore?: SnapshotFileStore;\r\n};\r\n\r\nexport type AttachWebSocketResult = {\r\n wss: WebSocketServer;\r\n};\r\n\r\nexport function attachWebSocket(\r\n httpServer: Server,\r\n connectionManager: ConnectionManager,\r\n router: MessageRouter,\r\n heartbeat: Heartbeat,\r\n refreshCoordinator: RefreshCoordinator,\r\n writeCoordinator: WriteCoordinator,\r\n options?: AttachWebSocketOptions,\r\n): AttachWebSocketResult {\r\n const wss = new WebSocketServer({ server: httpServer, path: DEVTOOLS_WS_PATH });\r\n\r\n const handleDisconnect = (socket: WebSocket): void => {\r\n const client = connectionManager.remove(socket);\r\n\r\n if (!client) {\r\n return;\r\n }\r\n\r\n if (client.role === DevToolsRole.MOBILE) {\r\n if (client.deviceId) {\r\n writeCoordinator.rollbackSessionsForDevice(client.deviceId);\r\n }\r\n\r\n logger.mobileDisconnected(client.deviceId);\r\n } else {\r\n writeCoordinator.rollbackSessionsOnBrowserDisconnect(client.connectionId);\r\n logger.browserDisconnected(client.connectionId);\r\n }\r\n\r\n router.broadcastDeviceStatus();\r\n };\r\n\r\n wss.on('connection', (socket: WebSocket) => {\r\n socket.on('message', (raw) => {\r\n let parsed: unknown;\r\n\r\n try {\r\n parsed = JSON.parse(String(raw));\r\n } catch {\r\n return;\r\n }\r\n\r\n if (isRegisterMessage(parsed)) {\r\n const existing = connectionManager.getBySocket(socket);\r\n\r\n if (existing) {\r\n return;\r\n }\r\n\r\n const client = connectionManager.add({\r\n socket,\r\n role: parsed.role,\r\n deviceId: parsed.deviceId,\r\n metadata: parsed.metadata,\r\n });\r\n\r\n if (client.role === DevToolsRole.MOBILE) {\r\n logger.mobileConnected(client.deviceId);\r\n\r\n if (client.deviceId && options?.snapshotFileStore) {\r\n void options.snapshotFileStore\r\n .reconcileOnMobileConnect({\r\n deviceId: client.deviceId,\r\n bundleId: client.metadata?.bundleId,\r\n })\r\n .finally(() => {\r\n router.broadcastDeviceStatus();\r\n });\r\n return;\r\n }\r\n } else {\r\n logger.browserConnected(client.connectionId);\r\n }\r\n\r\n router.broadcastDeviceStatus();\r\n return;\r\n }\r\n\r\n if (isPongMessage(parsed)) {\r\n connectionManager.updateLastPong(socket);\r\n return;\r\n }\r\n\r\n if (isRefreshRequestMessage(parsed)) {\r\n refreshCoordinator.handleRefreshRequest(socket, parsed);\r\n return;\r\n }\r\n\r\n if (isExportSnapshotRequestMessage(parsed)) {\r\n refreshCoordinator.handleMobileExportRequest(socket, parsed);\r\n return;\r\n }\r\n\r\n if (isBeginTransactionRequestMessage(parsed)) {\r\n writeCoordinator.handleBeginTransactionRequest(socket, parsed);\r\n return;\r\n }\r\n\r\n if (isCommitTransactionRequestMessage(parsed)) {\r\n writeCoordinator.handleCommitTransactionRequest(socket, parsed);\r\n return;\r\n }\r\n\r\n if (isRollbackTransactionRequestMessage(parsed)) {\r\n writeCoordinator.handleRollbackTransactionRequest(socket, parsed);\r\n return;\r\n }\r\n\r\n if (isWriteRequestMessage(parsed)) {\r\n writeCoordinator.handleWriteRequest(socket, parsed);\r\n return;\r\n }\r\n\r\n if (isTransactionAckMessage(parsed)) {\r\n writeCoordinator.handleTransactionAck(parsed);\r\n return;\r\n }\r\n\r\n if (isWriteAckMessage(parsed)) {\r\n writeCoordinator.handleWriteAck(parsed);\r\n }\r\n });\r\n\r\n socket.on('close', () => {\r\n handleDisconnect(socket);\r\n });\r\n\r\n socket.on('error', () => {\r\n handleDisconnect(socket);\r\n });\r\n });\r\n\r\n heartbeat.start();\r\n\r\n return { wss };\r\n}\r\n","import { mkdir, readFile, writeFile } from 'node:fs/promises';\r\nimport path from 'node:path';\r\n\r\nexport const DEFAULT_DATA_DIR = '.devtools';\r\n\r\n/** @deprecated Legacy single-database path. Removed — use per-device exports instead. */\r\nexport const DEFAULT_DATABASE_RELATIVE_PATH = 'databases/active.db';\r\n\r\nexport type ProjectDevToolsConfig = {\r\n /** @deprecated No longer used. */\r\n defaultDatabase?: string;\r\n deviceSync?: {\r\n /** @deprecated Ignored — active.db is no longer written. */\r\n promoteLatestToActive?: boolean;\r\n };\r\n};\r\n\r\nexport type DatabaseManifestEntry = {\r\n id: string;\r\n label: string;\r\n relativePath: string;\r\n source: 'active' | 'device';\r\n deviceId?: string;\r\n bundleId?: string;\r\n storageKey?: string;\r\n kind: string;\r\n mimeType: string;\r\n databaseName?: string;\r\n size: number;\r\n updatedAt: number;\r\n};\r\n\r\nexport type DatabaseManifest = {\r\n version: 1;\r\n /** @deprecated No longer written. */\r\n activeDatabase?: string;\r\n entries: DatabaseManifestEntry[];\r\n};\r\n\r\nexport type PersistDeviceSnapshotInput = {\r\n deviceId: string;\r\n bytes: Buffer;\r\n kind: string;\r\n mimeType: string;\r\n databaseName?: string;\r\n bundleId?: string;\r\n};\r\n\r\nexport type PersistDeviceSnapshotResult = {\r\n deviceRelativePath: string;\r\n exportedAt: number;\r\n size: number;\r\n};\r\n\r\nconst DEFAULT_CONFIG: ProjectDevToolsConfig = {\r\n deviceSync: {\r\n promoteLatestToActive: false,\r\n },\r\n};\r\n\r\nexport function resolveDataDir(explicitDir?: string): string {\r\n const fromEnv = process.env.DATABASE_DEVTOOLS_DATA_DIR?.trim();\r\n\r\n if (explicitDir?.trim()) {\r\n return path.resolve(explicitDir.trim());\r\n }\r\n\r\n if (fromEnv) {\r\n return path.resolve(fromEnv);\r\n }\r\n\r\n return path.resolve(process.cwd(), DEFAULT_DATA_DIR);\r\n}\r\n\r\nexport function isPersistenceEnabled(): boolean {\r\n const flag = process.env.DATABASE_DEVTOOLS_SNAPSHOT_PERSIST?.trim().toLowerCase();\r\n\r\n if (flag === '0' || flag === 'false' || flag === 'off') {\r\n return false;\r\n }\r\n\r\n return true;\r\n}\r\n\r\nexport function sanitizePathSegment(value: string): string {\r\n return value.replace(/[^a-zA-Z0-9._-]+/g, '_');\r\n}\r\n\r\nexport function resolveProjectPaths(dataDir: string) {\r\n const databasesDir = path.join(dataDir, 'databases');\r\n const devicesDir = path.join(databasesDir, 'devices');\r\n const configPath = path.join(dataDir, 'devtools.json');\r\n const manifestPath = path.join(dataDir, 'manifest.json');\r\n\r\n return {\r\n dataDir,\r\n databasesDir,\r\n devicesDir,\r\n configPath,\r\n manifestPath,\r\n };\r\n}\r\n\r\nexport async function ensureProjectDirectories(dataDir: string): Promise<void> {\r\n const paths = resolveProjectPaths(dataDir);\r\n\r\n await mkdir(paths.devicesDir, { recursive: true });\r\n}\r\n\r\nexport async function loadProjectConfig(dataDir: string): Promise<ProjectDevToolsConfig> {\r\n const { configPath } = resolveProjectPaths(dataDir);\r\n\r\n try {\r\n const raw = await readFile(configPath, 'utf8');\r\n const parsed = JSON.parse(raw) as ProjectDevToolsConfig;\r\n\r\n return {\r\n ...DEFAULT_CONFIG,\r\n ...parsed,\r\n deviceSync: {\r\n promoteLatestToActive: false,\r\n },\r\n };\r\n } catch {\r\n return { ...DEFAULT_CONFIG };\r\n }\r\n}\r\n\r\nexport async function writeDefaultProjectConfig(dataDir: string): Promise<void> {\r\n const { configPath } = resolveProjectPaths(dataDir);\r\n\r\n try {\r\n await readFile(configPath, 'utf8');\r\n } catch {\r\n await mkdir(dataDir, { recursive: true });\r\n await writeFile(configPath, `${JSON.stringify(DEFAULT_CONFIG, null, 2)}\\n`, 'utf8');\r\n }\r\n}\r\n\r\nexport function resolveActiveDatabasePath(dataDir: string, config: ProjectDevToolsConfig): string {\r\n const relative = config.defaultDatabase ?? DEFAULT_DATABASE_RELATIVE_PATH;\r\n return path.join(dataDir, relative);\r\n}\r\n\r\nexport function deviceDatabaseFileName(deviceId: string): string {\r\n return `Database-${sanitizePathSegment(deviceId)}.db`;\r\n}\r\n\r\nexport const DEVICE_EXPORT_FILE_NAME = 'database.db';\r\n\r\nexport function resolveDeviceStorageKey(input: { bundleId?: string; deviceId: string }): string {\r\n const bundleId = input.bundleId?.trim();\r\n\r\n if (bundleId) {\r\n return sanitizePathSegment(bundleId);\r\n }\r\n\r\n return sanitizePathSegment(input.deviceId);\r\n}\r\n\r\nexport function deviceStorageManifestId(storageKey: string): string {\r\n return `device:${storageKey}`;\r\n}\r\n\r\nexport function deviceStorageRelativePath(storageKey: string): string {\r\n return path\r\n .join('databases', 'devices', storageKey, DEVICE_EXPORT_FILE_NAME)\r\n .replace(/\\\\/g, '/');\r\n}\r\n\r\nexport function deviceDatabaseRelativePath(deviceId: string): string {\r\n const segment = sanitizePathSegment(deviceId);\r\n return path\r\n .join('databases', 'devices', segment, deviceDatabaseFileName(deviceId))\r\n .replace(/\\\\/g, '/');\r\n}\r\n\r\n/** @deprecated Legacy path — migrated reads still check this location. */\r\nexport function deviceLatestRelativePath(deviceId: string): string {\r\n return path.join('databases', 'devices', sanitizePathSegment(deviceId), 'latest.db').replace(/\\\\/g, '/');\r\n}\r\n\r\nexport async function readManifest(dataDir: string): Promise<DatabaseManifest> {\r\n const { manifestPath } = resolveProjectPaths(dataDir);\r\n\r\n try {\r\n const raw = await readFile(manifestPath, 'utf8');\r\n const parsed = JSON.parse(raw) as DatabaseManifest;\r\n\r\n if (parsed.version !== 1 || !Array.isArray(parsed.entries)) {\r\n return { version: 1, entries: [] };\r\n }\r\n\r\n return parsed;\r\n } catch {\r\n return { version: 1, entries: [] };\r\n }\r\n}\r\n\r\nexport async function writeManifest(dataDir: string, manifest: DatabaseManifest): Promise<void> {\r\n const { manifestPath } = resolveProjectPaths(dataDir);\r\n\r\n await mkdir(dataDir, { recursive: true });\r\n await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\\n`, 'utf8');\r\n}\r\n\r\nexport function upsertManifestEntry(\r\n manifest: DatabaseManifest,\r\n entry: DatabaseManifestEntry,\r\n): DatabaseManifest {\r\n const entries = manifest.entries.filter((item) => item.id !== entry.id);\r\n entries.push(entry);\r\n\r\n entries.sort((left, right) => right.updatedAt - left.updatedAt);\r\n\r\n return {\r\n version: manifest.version,\r\n entries,\r\n };\r\n}\r\n","import type { DatabaseManifestEntry } from './projectData';\r\nimport { deviceStorageManifestId, sanitizePathSegment } from './projectData';\r\n\r\nexport type ListedDeviceExportLike = {\r\n id: string;\r\n deviceId?: string;\r\n bundleId?: string;\r\n storageKey?: string;\r\n databaseName?: string;\r\n updatedAt: number;\r\n};\r\n\r\nexport function deriveStorageKeyFromEntry(entry: DatabaseManifestEntry): string {\r\n if (entry.storageKey) {\r\n return entry.storageKey;\r\n }\r\n\r\n if (entry.bundleId) {\r\n return sanitizePathSegment(entry.bundleId);\r\n }\r\n\r\n const match = entry.relativePath.match(/databases\\/devices\\/([^/]+)\\//);\r\n\r\n if (match?.[1]) {\r\n return match[1];\r\n }\r\n\r\n if (entry.deviceId) {\r\n return sanitizePathSegment(entry.deviceId);\r\n }\r\n\r\n return entry.id;\r\n}\r\n\r\nexport function findManifestEntryByDeviceId(\r\n entries: DatabaseManifestEntry[],\r\n deviceId: string,\r\n): DatabaseManifestEntry | undefined {\r\n return entries.find((entry) => entry.source === 'device' && entry.deviceId === deviceId);\r\n}\r\n\r\nexport type PruneDeviceExportsInput = {\r\n keepStorageKey: string;\r\n keepDeviceId: string;\r\n bundleId?: string;\r\n databaseName?: string;\r\n};\r\n\r\nexport function selectDeviceExportEntriesToPrune(\r\n entries: DatabaseManifestEntry[],\r\n keep: PruneDeviceExportsInput,\r\n): DatabaseManifestEntry[] {\r\n const keepManifestId = deviceStorageManifestId(keep.keepStorageKey);\r\n\r\n return entries.filter((entry) => {\r\n if (entry.source !== 'device') {\r\n return false;\r\n }\r\n\r\n if (entry.id === keepManifestId) {\r\n return false;\r\n }\r\n\r\n const entryStorageKey = deriveStorageKeyFromEntry(entry);\r\n\r\n if (entryStorageKey === keep.keepStorageKey) {\r\n return true;\r\n }\r\n\r\n if (keep.bundleId && entry.bundleId === keep.bundleId) {\r\n return true;\r\n }\r\n\r\n if (\r\n keep.bundleId &&\r\n keep.databaseName &&\r\n !entry.bundleId &&\r\n entry.databaseName === keep.databaseName\r\n ) {\r\n return true;\r\n }\r\n\r\n if (\r\n !keep.bundleId &&\r\n keep.databaseName &&\r\n entry.databaseName === keep.databaseName &&\r\n entry.deviceId !== keep.keepDeviceId\r\n ) {\r\n return true;\r\n }\r\n\r\n return false;\r\n });\r\n}\r\n\r\nexport function dedupeListedDeviceExports<T extends ListedDeviceExportLike>(entries: T[]): T[] {\r\n const byStorageKey = new Map<string, T>();\r\n\r\n for (const entry of entries) {\r\n const storageKey = entry.storageKey\r\n ? entry.storageKey\r\n : entry.bundleId\r\n ? sanitizePathSegment(entry.bundleId)\r\n : entry.deviceId\r\n ? sanitizePathSegment(entry.deviceId)\r\n : entry.id;\r\n\r\n const existing = byStorageKey.get(storageKey);\r\n\r\n if (!existing || entry.updatedAt > existing.updatedAt) {\r\n byStorageKey.set(storageKey, entry);\r\n }\r\n }\r\n\r\n return [...byStorageKey.values()].sort((left, right) => right.updatedAt - left.updatedAt);\r\n}\r\n\r\nexport type ReconcileLegacyExportsInput = {\r\n entries: DatabaseManifestEntry[];\r\n preferredDeviceId?: string;\r\n};\r\n\r\nexport function reconcileLegacyManifestEntries(\r\n input: ReconcileLegacyExportsInput,\r\n): DatabaseManifestEntry[] {\r\n const deviceEntries = input.entries.filter((entry) => entry.source === 'device');\r\n const otherEntries = input.entries.filter((entry) => entry.source !== 'device');\r\n const groups = new Map<string, DatabaseManifestEntry[]>();\r\n\r\n for (const entry of deviceEntries) {\r\n const groupKey = entry.bundleId\r\n ? `bundle:${entry.bundleId}`\r\n : entry.databaseName\r\n ? `db:${entry.databaseName}`\r\n : `device:${deriveStorageKeyFromEntry(entry)}`;\r\n\r\n const group = groups.get(groupKey) ?? [];\r\n group.push(entry);\r\n groups.set(groupKey, group);\r\n }\r\n\r\n const keptDeviceEntries: DatabaseManifestEntry[] = [];\r\n\r\n for (const group of groups.values()) {\r\n if (group.length === 1) {\r\n keptDeviceEntries.push(group[0]!);\r\n continue;\r\n }\r\n\r\n const preferred = input.preferredDeviceId\r\n ? group.find((entry) => entry.deviceId === input.preferredDeviceId)\r\n : undefined;\r\n\r\n const newest = [...group].sort((left, right) => right.updatedAt - left.updatedAt)[0]!;\r\n keptDeviceEntries.push(preferred ?? newest);\r\n }\r\n\r\n return [...otherEntries, ...keptDeviceEntries].sort((left, right) => right.updatedAt - left.updatedAt);\r\n}\r\n\r\nexport function removedManifestEntries(\r\n before: DatabaseManifestEntry[],\r\n after: DatabaseManifestEntry[],\r\n): DatabaseManifestEntry[] {\r\n const afterIds = new Set(after.map((entry) => entry.id));\r\n return before.filter((entry) => !afterIds.has(entry.id));\r\n}\r\n","import { readFile, rm, stat, writeFile } from 'node:fs/promises';\r\nimport path from 'node:path';\r\nimport {\r\n DEFAULT_DATABASE_RELATIVE_PATH,\r\n readManifest,\r\n resolveProjectPaths,\r\n writeManifest,\r\n type DatabaseManifest,\r\n type ProjectDevToolsConfig,\r\n} from './projectData';\r\n\r\nconst NORMALIZED_CONFIG: ProjectDevToolsConfig = {\r\n deviceSync: {\r\n promoteLatestToActive: false,\r\n },\r\n};\r\n\r\nexport function stripLegacyActiveManifest(manifest: DatabaseManifest): DatabaseManifest {\r\n const entries = manifest.entries.filter(\r\n (entry) =>\r\n entry.source !== 'active' &&\r\n entry.id !== 'active' &&\r\n !entry.id.startsWith('import:'),\r\n );\r\n\r\n return {\r\n version: 1,\r\n entries,\r\n };\r\n}\r\n\r\nexport function normalizeProjectConfig(config: ProjectDevToolsConfig): ProjectDevToolsConfig {\r\n return {\r\n ...NORMALIZED_CONFIG,\r\n deviceSync: {\r\n ...NORMALIZED_CONFIG.deviceSync,\r\n promoteLatestToActive: false,\r\n },\r\n };\r\n}\r\n\r\nexport async function migrateLegacyActiveDatabase(dataDir: string): Promise<boolean> {\r\n const { configPath } = resolveProjectPaths(dataDir);\r\n const manifest = await readManifest(dataDir);\r\n const stripped = stripLegacyActiveManifest(manifest);\r\n const activeDbPath = path.join(dataDir, DEFAULT_DATABASE_RELATIVE_PATH);\r\n\r\n let changed =\r\n stripped.entries.length !== manifest.entries.length || Boolean(manifest.activeDatabase);\r\n\r\n if (changed) {\r\n await writeManifest(dataDir, stripped);\r\n }\r\n\r\n try {\r\n await stat(activeDbPath);\r\n const hasDeviceExports = stripped.entries.some((entry) => entry.source === 'device');\r\n\r\n if (hasDeviceExports || manifest.entries.some((entry) => entry.source === 'active')) {\r\n await rm(activeDbPath, { force: true });\r\n changed = true;\r\n }\r\n } catch {\r\n // active.db not present\r\n }\r\n\r\n try {\r\n const raw = await readFile(configPath, 'utf8');\r\n const parsed = JSON.parse(raw) as ProjectDevToolsConfig;\r\n\r\n if (parsed.defaultDatabase || parsed.deviceSync?.promoteLatestToActive) {\r\n await writeFile(\r\n configPath,\r\n `${JSON.stringify(normalizeProjectConfig(parsed), null, 2)}\\n`,\r\n 'utf8',\r\n );\r\n changed = true;\r\n }\r\n } catch {\r\n // config will be created on next export\r\n }\r\n\r\n const importsDir = path.join(dataDir, 'databases', 'imports');\r\n\r\n try {\r\n await stat(importsDir);\r\n await rm(importsDir, { recursive: true, force: true });\r\n changed = true;\r\n } catch {\r\n // imports directory not present\r\n }\r\n\r\n return changed;\r\n}\r\n","import { mkdir, readFile, rm, stat, writeFile } from 'node:fs/promises';\r\nimport path from 'node:path';\r\nimport { SQLITE_SNAPSHOT_MIME_TYPE } from '../types/snapshot';\r\nimport {\r\n dedupeListedDeviceExports,\r\n findManifestEntryByDeviceId,\r\n reconcileLegacyManifestEntries,\r\n removedManifestEntries,\r\n selectDeviceExportEntriesToPrune,\r\n} from './deviceExportStorage';\r\nimport { migrateLegacyActiveDatabase } from './migrateLegacyActiveDb';\r\nimport {\r\n deviceDatabaseRelativePath,\r\n deviceLatestRelativePath,\r\n deviceStorageManifestId,\r\n deviceStorageRelativePath,\r\n ensureProjectDirectories,\r\n isPersistenceEnabled,\r\n readManifest,\r\n resolveDataDir,\r\n resolveDeviceStorageKey,\r\n resolveProjectPaths,\r\n sanitizePathSegment,\r\n upsertManifestEntry,\r\n writeDefaultProjectConfig,\r\n writeManifest,\r\n type DatabaseManifestEntry,\r\n type PersistDeviceSnapshotInput,\r\n type PersistDeviceSnapshotResult,\r\n} from './projectData';\r\n\r\nexport type ProjectDatabaseMeta = {\r\n exists: boolean;\r\n relativePath?: string;\r\n absolutePath?: string;\r\n kind?: string;\r\n mimeType?: string;\r\n databaseName?: string;\r\n size?: number;\r\n updatedAt?: number;\r\n source?: DatabaseManifestEntry['source'];\r\n deviceId?: string;\r\n};\r\n\r\nexport type ListedProjectDatabase = {\r\n id: string;\r\n label: string;\r\n relativePath: string;\r\n source: DatabaseManifestEntry['source'];\r\n deviceId?: string;\r\n bundleId?: string;\r\n storageKey?: string;\r\n databaseName?: string;\r\n size: number;\r\n updatedAt: number;\r\n};\r\n\r\nexport class SnapshotFileStore {\r\n private readonly dataDir: string;\r\n private readonly enabled: boolean;\r\n\r\n constructor(options?: { dataDir?: string; enabled?: boolean }) {\r\n this.dataDir = resolveDataDir(options?.dataDir);\r\n this.enabled = options?.enabled ?? isPersistenceEnabled();\r\n }\r\n\r\n getDataDir(): string {\r\n return this.dataDir;\r\n }\r\n\r\n isEnabled(): boolean {\r\n return this.enabled;\r\n }\r\n\r\n async persistDeviceSnapshot(\r\n input: PersistDeviceSnapshotInput,\r\n ): Promise<PersistDeviceSnapshotResult | null> {\r\n if (!this.enabled) {\r\n return null;\r\n }\r\n\r\n await writeDefaultProjectConfig(this.dataDir);\r\n await ensureProjectDirectories(this.dataDir);\r\n\r\n const storageKey = resolveDeviceStorageKey({\r\n bundleId: input.bundleId,\r\n deviceId: input.deviceId,\r\n });\r\n const deviceRelativePath = deviceStorageRelativePath(storageKey);\r\n const deviceAbsolutePath = path.join(this.dataDir, deviceRelativePath);\r\n const exportedAt = Date.now();\r\n\r\n await this.pruneDeviceExports({\r\n keepStorageKey: storageKey,\r\n keepDeviceId: input.deviceId,\r\n bundleId: input.bundleId,\r\n databaseName: input.databaseName,\r\n });\r\n\r\n await mkdir(path.dirname(deviceAbsolutePath), { recursive: true });\r\n await writeFile(deviceAbsolutePath, input.bytes);\r\n\r\n const manifest = await readManifest(this.dataDir);\r\n\r\n const deviceEntry: DatabaseManifestEntry = {\r\n id: deviceStorageManifestId(storageKey),\r\n label: input.databaseName ?? `Device ${input.deviceId}`,\r\n relativePath: deviceRelativePath.replace(/\\\\/g, '/'),\r\n source: 'device',\r\n deviceId: input.deviceId,\r\n bundleId: input.bundleId,\r\n storageKey,\r\n kind: input.kind,\r\n mimeType: input.mimeType,\r\n databaseName: input.databaseName,\r\n size: input.bytes.byteLength,\r\n updatedAt: exportedAt,\r\n };\r\n\r\n const nextManifest = upsertManifestEntry(manifest, deviceEntry);\r\n\r\n await writeManifest(this.dataDir, nextManifest);\r\n\r\n return {\r\n deviceRelativePath: deviceRelativePath.replace(/\\\\/g, '/'),\r\n exportedAt,\r\n size: input.bytes.byteLength,\r\n };\r\n }\r\n\r\n async reconcileOnMobileConnect(input: {\r\n deviceId: string;\r\n bundleId?: string;\r\n }): Promise<void> {\r\n if (!this.enabled) {\r\n return;\r\n }\r\n\r\n await this.reconcileLegacyExports(input.deviceId);\r\n\r\n const storageKey = resolveDeviceStorageKey({\r\n bundleId: input.bundleId,\r\n deviceId: input.deviceId,\r\n });\r\n const manifest = await readManifest(this.dataDir);\r\n const canonicalEntry = manifest.entries.find(\r\n (entry) => entry.source === 'device' && entry.storageKey === storageKey,\r\n );\r\n\r\n if (canonicalEntry && canonicalEntry.deviceId !== input.deviceId) {\r\n const updated = upsertManifestEntry(manifest, {\r\n ...canonicalEntry,\r\n deviceId: input.deviceId,\r\n bundleId: input.bundleId ?? canonicalEntry.bundleId,\r\n updatedAt: Date.now(),\r\n });\r\n\r\n await writeManifest(this.dataDir, updated);\r\n }\r\n\r\n await this.pruneDeviceExports({\r\n keepStorageKey: storageKey,\r\n keepDeviceId: input.deviceId,\r\n bundleId: input.bundleId,\r\n databaseName: canonicalEntry?.databaseName,\r\n });\r\n }\r\n\r\n async readDeviceSnapshot(deviceId: string): Promise<Buffer | undefined> {\r\n return this.readDeviceDatabase(deviceId);\r\n }\r\n\r\n async readDeviceDatabase(deviceId: string): Promise<Buffer | undefined> {\r\n if (!this.enabled) {\r\n return undefined;\r\n }\r\n\r\n const resolved = await this.resolveDeviceDatabaseFile(deviceId);\r\n\r\n if (!resolved) {\r\n return undefined;\r\n }\r\n\r\n try {\r\n return await readFile(resolved.absolutePath);\r\n } catch {\r\n return undefined;\r\n }\r\n }\r\n\r\n async getDeviceDatabaseMeta(deviceId: string): Promise<ProjectDatabaseMeta> {\r\n if (!this.enabled) {\r\n return { exists: false, deviceId };\r\n }\r\n\r\n const resolved = await this.resolveDeviceDatabaseFile(deviceId);\r\n\r\n if (!resolved) {\r\n return { exists: false, deviceId };\r\n }\r\n\r\n try {\r\n const fileStat = await stat(resolved.absolutePath);\r\n const manifest = await readManifest(this.dataDir);\r\n const entry = manifest.entries.find(\r\n (item) => item.deviceId === deviceId && item.source === 'device',\r\n );\r\n\r\n return {\r\n exists: true,\r\n relativePath: resolved.relativePath,\r\n absolutePath: resolved.absolutePath,\r\n kind: entry?.kind ?? 'sqlite',\r\n mimeType: entry?.mimeType ?? SQLITE_SNAPSHOT_MIME_TYPE,\r\n databaseName: entry?.databaseName ?? path.basename(resolved.absolutePath),\r\n size: fileStat.size,\r\n updatedAt: entry?.updatedAt ?? fileStat.mtimeMs,\r\n source: 'device',\r\n deviceId,\r\n };\r\n } catch {\r\n return { exists: false, deviceId, relativePath: resolved.relativePath };\r\n }\r\n }\r\n\r\n async listDeviceExports(): Promise<ListedProjectDatabase[]> {\r\n await this.reconcileLegacyExports();\r\n const databases = await this.listDatabases();\r\n const deviceExports = databases.filter((entry) => entry.source === 'device' && entry.deviceId);\r\n return dedupeListedDeviceExports(deviceExports);\r\n }\r\n\r\n private async reconcileLegacyExports(preferredDeviceId?: string): Promise<void> {\r\n if (!this.enabled) {\r\n return;\r\n }\r\n\r\n await migrateLegacyActiveDatabase(this.dataDir);\r\n\r\n const manifest = await readManifest(this.dataDir);\r\n const nextEntries = reconcileLegacyManifestEntries({\r\n entries: manifest.entries,\r\n preferredDeviceId,\r\n });\r\n\r\n if (nextEntries.length === manifest.entries.length) {\r\n const sameOrder = nextEntries.every((entry, index) => entry.id === manifest.entries[index]?.id);\r\n\r\n if (sameOrder) {\r\n return;\r\n }\r\n }\r\n\r\n const removed = removedManifestEntries(manifest.entries, nextEntries);\r\n\r\n for (const entry of removed) {\r\n await this.deleteEntryFiles(entry);\r\n }\r\n\r\n await writeManifest(this.dataDir, {\r\n ...manifest,\r\n entries: nextEntries,\r\n });\r\n }\r\n\r\n private async pruneDeviceExports(input: {\r\n keepStorageKey: string;\r\n keepDeviceId: string;\r\n bundleId?: string;\r\n databaseName?: string;\r\n }): Promise<void> {\r\n const manifest = await readManifest(this.dataDir);\r\n const removed = selectDeviceExportEntriesToPrune(manifest.entries, input);\r\n\r\n if (removed.length === 0) {\r\n return;\r\n }\r\n\r\n for (const entry of removed) {\r\n await this.deleteEntryFiles(entry);\r\n }\r\n\r\n const removedIds = new Set(removed.map((entry) => entry.id));\r\n\r\n await writeManifest(this.dataDir, {\r\n ...manifest,\r\n entries: manifest.entries.filter((entry) => !removedIds.has(entry.id)),\r\n });\r\n }\r\n\r\n private async deleteEntryFiles(entry: DatabaseManifestEntry): Promise<void> {\r\n const absolutePath = path.join(this.dataDir, entry.relativePath);\r\n\r\n try {\r\n await rm(absolutePath, { force: true });\r\n } catch {\r\n // ignore missing files\r\n }\r\n\r\n try {\r\n await rm(path.dirname(absolutePath), { recursive: true, force: true });\r\n } catch {\r\n // ignore cleanup failures\r\n }\r\n }\r\n\r\n private manifestEntryToListed(entry: DatabaseManifestEntry, fileStat: { size: number }): ListedProjectDatabase {\r\n return {\r\n id: entry.id,\r\n label: entry.label,\r\n relativePath: entry.relativePath,\r\n source: entry.source,\r\n deviceId: entry.deviceId,\r\n bundleId: entry.bundleId,\r\n storageKey: entry.storageKey,\r\n databaseName: entry.databaseName,\r\n size: fileStat.size,\r\n updatedAt: entry.updatedAt,\r\n };\r\n }\r\n\r\n private async resolveDeviceDatabaseFile(\r\n deviceId: string,\r\n ): Promise<{ relativePath: string; absolutePath: string } | undefined> {\r\n const manifest = await readManifest(this.dataDir);\r\n const manifestEntry = findManifestEntryByDeviceId(manifest.entries, deviceId);\r\n\r\n if (manifestEntry) {\r\n const absolutePath = path.join(this.dataDir, manifestEntry.relativePath);\r\n\r\n try {\r\n await stat(absolutePath);\r\n return { relativePath: manifestEntry.relativePath, absolutePath };\r\n } catch {\r\n // fall through to legacy paths\r\n }\r\n }\r\n\r\n const candidates = [\r\n deviceDatabaseRelativePath(deviceId),\r\n deviceLatestRelativePath(deviceId),\r\n ];\r\n\r\n for (const relativePath of candidates) {\r\n const absolutePath = path.join(this.dataDir, relativePath);\r\n\r\n try {\r\n await stat(absolutePath);\r\n return { relativePath, absolutePath };\r\n } catch {\r\n // try next candidate\r\n }\r\n }\r\n\r\n if (!manifestEntry) {\r\n return undefined;\r\n }\r\n\r\n const absolutePath = path.join(this.dataDir, manifestEntry.relativePath);\r\n\r\n try {\r\n await stat(absolutePath);\r\n return { relativePath: manifestEntry.relativePath, absolutePath };\r\n } catch {\r\n return undefined;\r\n }\r\n }\r\n\r\n /** @deprecated Proxies to the newest device export for backward-compatible API callers. */\r\n async readActiveDatabase(): Promise<Buffer | undefined> {\r\n if (!this.enabled) {\r\n return undefined;\r\n }\r\n\r\n const meta = await this.getActiveDatabaseMeta();\r\n\r\n if (!meta.exists || !meta.deviceId) {\r\n return undefined;\r\n }\r\n\r\n return this.readDeviceDatabase(meta.deviceId);\r\n }\r\n\r\n /** @deprecated Proxies to the newest device export for backward-compatible API callers. */\r\n async getActiveDatabaseMeta(): Promise<ProjectDatabaseMeta> {\r\n if (!this.enabled) {\r\n return { exists: false };\r\n }\r\n\r\n await migrateLegacyActiveDatabase(this.dataDir);\r\n\r\n const exports = await this.listDeviceExports();\r\n const latest = exports[0];\r\n\r\n if (!latest?.deviceId) {\r\n return { exists: false };\r\n }\r\n\r\n return this.getDeviceDatabaseMeta(latest.deviceId);\r\n }\r\n\r\n async listDatabases(): Promise<ListedProjectDatabase[]> {\r\n if (!this.enabled) {\r\n return [];\r\n }\r\n\r\n await ensureProjectDirectories(this.dataDir);\r\n await this.reconcileLegacyExports();\r\n\r\n const manifest = await readManifest(this.dataDir);\r\n const listed = new Map<string, ListedProjectDatabase>();\r\n\r\n for (const entry of manifest.entries) {\r\n if (entry.source === 'active' || entry.id.startsWith('import:')) {\r\n continue;\r\n }\r\n\r\n const absolutePath = path.join(this.dataDir, entry.relativePath);\r\n\r\n try {\r\n const fileStat = await stat(absolutePath);\r\n\r\n listed.set(entry.id, this.manifestEntryToListed(entry, fileStat));\r\n } catch {\r\n // Ignore missing files from manifest.\r\n }\r\n }\r\n\r\n return [...listed.values()].sort((left, right) => right.updatedAt - left.updatedAt);\r\n }\r\n\r\n async readDatabaseByRelativePath(relativePath: string): Promise<Buffer | undefined> {\r\n if (!this.enabled) {\r\n return undefined;\r\n }\r\n\r\n const normalized = relativePath.replace(/\\\\/g, '/');\r\n const absolutePath = path.resolve(this.dataDir, normalized);\r\n const dataDirResolved = path.resolve(this.dataDir);\r\n\r\n if (!absolutePath.startsWith(dataDirResolved)) {\r\n return undefined;\r\n }\r\n\r\n if (!normalized.toLowerCase().endsWith('.db')) {\r\n return undefined;\r\n }\r\n\r\n try {\r\n return await readFile(absolutePath);\r\n } catch {\r\n return undefined;\r\n }\r\n }\r\n\r\n getDeviceDirectoryName(deviceId: string): string {\r\n return sanitizePathSegment(deviceId);\r\n }\r\n}\r\n","import type { WebSocket } from 'ws';\r\nimport {\r\n createMessage,\r\n DevToolsRole,\r\n MessageType,\r\n type BeginTransactionMessage,\r\n type BeginTransactionRequestMessage,\r\n type CommitTransactionMessage,\r\n type CommitTransactionRequestMessage,\r\n type ExecuteWriteMessage,\r\n type RollbackTransactionMessage,\r\n type RollbackTransactionRequestMessage,\r\n type TransactionAckMessage,\r\n type TransactionStatusMessage,\r\n type WriteAckMessage,\r\n type WriteErrorCode,\r\n type WriteErrorMessage,\r\n type WriteRequestMessage,\r\n type WriteResultMessage,\r\n} from '../types/protocol';\r\nimport { logger } from '../utils/logger';\r\nimport type { ConnectionManager } from './connectionManager';\r\nimport type { MessageRouter } from './messageRouter';\r\nimport type { WriteSessionManager, WriteSession } from './writeSessionManager';\r\n\r\nexport class WriteCoordinator {\r\n constructor(\r\n private readonly connectionManager: ConnectionManager,\r\n private readonly router: MessageRouter,\r\n private readonly sessions: WriteSessionManager,\r\n ) {}\r\n\r\n handleBeginTransactionRequest(\r\n browserSocket: WebSocket,\r\n message: BeginTransactionRequestMessage,\r\n ): void {\r\n const browser = this.connectionManager.getBySocket(browserSocket);\r\n\r\n if (!browser || browser.role !== DevToolsRole.BROWSER) {\r\n return;\r\n }\r\n\r\n const mobile = this.connectionManager.getByDeviceId(message.deviceId);\r\n\r\n if (!mobile) {\r\n this.sendWriteError(browser.connectionId, {\r\n transactionId: message.transactionId,\r\n code: 'DEVICE_OFFLINE',\r\n message: `Device ${message.deviceId} is not connected`,\r\n });\r\n return;\r\n }\r\n\r\n if (this.sessions.getActiveForDevice(message.deviceId)) {\r\n this.sendWriteError(browser.connectionId, {\r\n transactionId: message.transactionId,\r\n code: 'TRANSACTION_BUSY',\r\n message: 'A transaction is already open for this device',\r\n });\r\n return;\r\n }\r\n\r\n this.sessions.create({\r\n transactionId: message.transactionId,\r\n deviceId: message.deviceId,\r\n browserConnectionId: browser.connectionId,\r\n });\r\n\r\n logger.syncStarted(message.transactionId, message.deviceId);\r\n\r\n this.router.sendToMobile(\r\n message.deviceId,\r\n createMessage<BeginTransactionMessage>({\r\n type: MessageType.BEGIN_TRANSACTION,\r\n transactionId: message.transactionId,\r\n }),\r\n );\r\n }\r\n\r\n handleCommitTransactionRequest(\r\n browserSocket: WebSocket,\r\n message: CommitTransactionRequestMessage,\r\n ): void {\r\n const browser = this.connectionManager.getBySocket(browserSocket);\r\n const session = this.sessions.get(message.transactionId);\r\n\r\n if (!browser || browser.role !== DevToolsRole.BROWSER || !session) {\r\n return;\r\n }\r\n\r\n if (session.browserConnectionId !== browser.connectionId) {\r\n return;\r\n }\r\n\r\n if (session.state !== 'open') {\r\n this.sendWriteError(browser.connectionId, {\r\n transactionId: message.transactionId,\r\n code: 'NO_TRANSACTION',\r\n message: 'Transaction is not open',\r\n });\r\n return;\r\n }\r\n\r\n this.sessions.setState(message.transactionId, 'committing');\r\n\r\n this.router.sendToMobile(\r\n session.deviceId,\r\n createMessage<CommitTransactionMessage>({\r\n type: MessageType.COMMIT_TRANSACTION,\r\n transactionId: message.transactionId,\r\n }),\r\n );\r\n }\r\n\r\n handleRollbackTransactionRequest(\r\n browserSocket: WebSocket,\r\n message: RollbackTransactionRequestMessage,\r\n ): void {\r\n const browser = this.connectionManager.getBySocket(browserSocket);\r\n const session = this.sessions.get(message.transactionId);\r\n\r\n if (!browser || browser.role !== DevToolsRole.BROWSER || !session) {\r\n return;\r\n }\r\n\r\n if (session.browserConnectionId !== browser.connectionId) {\r\n return;\r\n }\r\n\r\n if (session.state !== 'open' && session.state !== 'committing') {\r\n this.sendWriteError(browser.connectionId, {\r\n transactionId: message.transactionId,\r\n code: 'NO_TRANSACTION',\r\n message: 'Transaction is not open',\r\n });\r\n return;\r\n }\r\n\r\n this.sessions.setState(message.transactionId, 'rolling_back');\r\n\r\n this.router.sendToMobile(\r\n session.deviceId,\r\n createMessage<RollbackTransactionMessage>({\r\n type: MessageType.ROLLBACK_TRANSACTION,\r\n transactionId: message.transactionId,\r\n }),\r\n );\r\n }\r\n\r\n handleWriteRequest(browserSocket: WebSocket, message: WriteRequestMessage): void {\r\n const browser = this.connectionManager.getBySocket(browserSocket);\r\n const session = this.sessions.get(message.transactionId);\r\n\r\n if (!browser || browser.role !== DevToolsRole.BROWSER || !session) {\r\n return;\r\n }\r\n\r\n if (session.browserConnectionId !== browser.connectionId) {\r\n return;\r\n }\r\n\r\n if (session.state !== 'open') {\r\n this.sendWriteError(browser.connectionId, {\r\n transactionId: message.transactionId,\r\n writeId: message.writeId,\r\n code: 'NO_TRANSACTION',\r\n message: 'Transaction is not open',\r\n });\r\n return;\r\n }\r\n\r\n const mobile = this.connectionManager.getByDeviceId(session.deviceId);\r\n\r\n if (!mobile) {\r\n this.sendWriteError(browser.connectionId, {\r\n transactionId: message.transactionId,\r\n writeId: message.writeId,\r\n code: 'DEVICE_OFFLINE',\r\n message: `Device ${session.deviceId} is not connected`,\r\n });\r\n return;\r\n }\r\n\r\n this.sessions.incrementPendingWrites(message.transactionId);\r\n\r\n this.router.sendToMobile(\r\n session.deviceId,\r\n createMessage<ExecuteWriteMessage>({\r\n type: MessageType.EXECUTE_WRITE,\r\n writeId: message.writeId,\r\n transactionId: message.transactionId,\r\n operation: message.operation,\r\n }),\r\n );\r\n }\r\n\r\n handleTransactionAck(message: TransactionAckMessage): void {\r\n const session = this.sessions.get(message.transactionId);\r\n\r\n if (!session) {\r\n return;\r\n }\r\n\r\n if (!message.ok) {\r\n this.sessions.setState(message.transactionId, 'failed');\r\n this.sendWriteError(session.browserConnectionId, {\r\n transactionId: message.transactionId,\r\n code: message.action === 'begin' ? 'ADAPTER_ERROR' : 'WRITE_FAILED',\r\n message: message.message ?? `Transaction ${message.action} failed`,\r\n });\r\n this.sessions.remove(message.transactionId);\r\n return;\r\n }\r\n\r\n if (message.action === 'begin') {\r\n this.sendTransactionStatus(session.browserConnectionId, {\r\n transactionId: message.transactionId,\r\n deviceId: session.deviceId,\r\n state: 'open',\r\n });\r\n return;\r\n }\r\n\r\n if (message.action === 'commit') {\r\n this.sendTransactionStatus(session.browserConnectionId, {\r\n transactionId: message.transactionId,\r\n deviceId: session.deviceId,\r\n state: 'idle',\r\n });\r\n this.sessions.remove(message.transactionId);\r\n return;\r\n }\r\n\r\n this.sendTransactionStatus(session.browserConnectionId, {\r\n transactionId: message.transactionId,\r\n deviceId: session.deviceId,\r\n state: 'idle',\r\n message: message.message,\r\n });\r\n this.sessions.remove(message.transactionId);\r\n }\r\n\r\n handleWriteAck(message: WriteAckMessage): void {\r\n const session = this.sessions.get(message.transactionId);\r\n\r\n if (!session) {\r\n return;\r\n }\r\n\r\n this.sessions.decrementPendingWrites(message.transactionId);\r\n\r\n if (!message.ok) {\r\n this.sendWriteError(session.browserConnectionId, {\r\n transactionId: message.transactionId,\r\n writeId: message.writeId,\r\n code: 'WRITE_FAILED',\r\n message: message.message ?? 'Write operation failed',\r\n });\r\n return;\r\n }\r\n\r\n this.router.sendToBrowser(\r\n session.browserConnectionId,\r\n createMessage<WriteResultMessage>({\r\n type: MessageType.WRITE_RESULT,\r\n writeId: message.writeId,\r\n transactionId: message.transactionId,\r\n rowsAffected: message.rowsAffected ?? 0,\r\n }),\r\n );\r\n }\r\n\r\n checkTimeouts(): void {\r\n for (const session of this.sessions.getExpired()) {\r\n this.rollbackSession(session, 'TIMEOUT', 'Write transaction timed out');\r\n }\r\n }\r\n\r\n rollbackSessionsOnBrowserDisconnect(browserConnectionId: string): void {\r\n for (const session of this.sessions.getByBrowserConnectionId(browserConnectionId)) {\r\n this.rollbackSession(session, 'NO_TRANSACTION', 'Browser disconnected');\r\n }\r\n }\r\n\r\n rollbackSessionsForDevice(deviceId: string): void {\r\n for (const session of this.sessions.getByDeviceId(deviceId)) {\r\n this.rollbackSession(session, 'NO_TRANSACTION', 'Device disconnected');\r\n }\r\n }\r\n\r\n private rollbackSession(\r\n session: WriteSession,\r\n code: WriteErrorCode,\r\n message: string,\r\n ): void {\r\n logger.syncFailed(session.transactionId, code, message);\r\n\r\n this.sendWriteError(session.browserConnectionId, {\r\n transactionId: session.transactionId,\r\n code,\r\n message,\r\n });\r\n\r\n this.router.sendToMobile(\r\n session.deviceId,\r\n createMessage<RollbackTransactionMessage>({\r\n type: MessageType.ROLLBACK_TRANSACTION,\r\n transactionId: session.transactionId,\r\n }),\r\n );\r\n\r\n this.sessions.remove(session.transactionId);\r\n }\r\n\r\n private sendTransactionStatus(\r\n browserConnectionId: string,\r\n payload: Omit<TransactionStatusMessage, 'type' | 'timestamp'>,\r\n ): void {\r\n this.router.sendToBrowser(\r\n browserConnectionId,\r\n createMessage<TransactionStatusMessage>({\r\n type: MessageType.TRANSACTION_STATUS,\r\n ...payload,\r\n }),\r\n );\r\n }\r\n\r\n private sendWriteError(\r\n browserConnectionId: string,\r\n payload: {\r\n transactionId: string;\r\n writeId?: string;\r\n code: WriteErrorCode;\r\n message: string;\r\n },\r\n ): void {\r\n this.router.sendToBrowser(\r\n browserConnectionId,\r\n createMessage<WriteErrorMessage>({\r\n type: MessageType.WRITE_ERROR,\r\n ...payload,\r\n }),\r\n );\r\n }\r\n}\r\n","import type { TransactionStatusState } from '../types/protocol';\r\nimport { WRITE_TRANSACTION_TIMEOUT_MS } from '../types/protocol';\r\n\r\nexport type WriteSession = {\r\n transactionId: string;\r\n deviceId: string;\r\n browserConnectionId: string;\r\n state: TransactionStatusState;\r\n pendingWrites: number;\r\n createdAt: number;\r\n};\r\n\r\nexport class WriteSessionManager {\r\n private readonly sessions = new Map<string, WriteSession>();\r\n private readonly activeByDevice = new Map<string, string>();\r\n\r\n create(input: {\r\n transactionId: string;\r\n deviceId: string;\r\n browserConnectionId: string;\r\n }): WriteSession {\r\n const session: WriteSession = {\r\n transactionId: input.transactionId,\r\n deviceId: input.deviceId,\r\n browserConnectionId: input.browserConnectionId,\r\n state: 'opening',\r\n pendingWrites: 0,\r\n createdAt: Date.now(),\r\n };\r\n\r\n this.sessions.set(input.transactionId, session);\r\n this.activeByDevice.set(input.deviceId, input.transactionId);\r\n return session;\r\n }\r\n\r\n get(transactionId: string): WriteSession | undefined {\r\n return this.sessions.get(transactionId);\r\n }\r\n\r\n getActiveForDevice(deviceId: string): WriteSession | undefined {\r\n const transactionId = this.activeByDevice.get(deviceId);\r\n\r\n if (!transactionId) {\r\n return undefined;\r\n }\r\n\r\n return this.sessions.get(transactionId);\r\n }\r\n\r\n setState(transactionId: string, state: TransactionStatusState): WriteSession | undefined {\r\n const session = this.sessions.get(transactionId);\r\n\r\n if (!session) {\r\n return undefined;\r\n }\r\n\r\n session.state = state;\r\n return session;\r\n }\r\n\r\n incrementPendingWrites(transactionId: string): WriteSession | undefined {\r\n const session = this.sessions.get(transactionId);\r\n\r\n if (!session) {\r\n return undefined;\r\n }\r\n\r\n session.pendingWrites += 1;\r\n return session;\r\n }\r\n\r\n decrementPendingWrites(transactionId: string): WriteSession | undefined {\r\n const session = this.sessions.get(transactionId);\r\n\r\n if (!session) {\r\n return undefined;\r\n }\r\n\r\n session.pendingWrites = Math.max(0, session.pendingWrites - 1);\r\n return session;\r\n }\r\n\r\n remove(transactionId: string): void {\r\n const session = this.sessions.get(transactionId);\r\n\r\n if (!session) {\r\n return;\r\n }\r\n\r\n if (this.activeByDevice.get(session.deviceId) === transactionId) {\r\n this.activeByDevice.delete(session.deviceId);\r\n }\r\n\r\n this.sessions.delete(transactionId);\r\n }\r\n\r\n getExpired(now = Date.now()): WriteSession[] {\r\n return [...this.sessions.values()].filter((session) => {\r\n if (session.state === 'idle' || session.state === 'failed') {\r\n return false;\r\n }\r\n\r\n return now - session.createdAt >= WRITE_TRANSACTION_TIMEOUT_MS;\r\n });\r\n }\r\n\r\n getByBrowserConnectionId(browserConnectionId: string): WriteSession[] {\r\n return [...this.sessions.values()].filter(\r\n (session) => session.browserConnectionId === browserConnectionId,\r\n );\r\n }\r\n\r\n getByDeviceId(deviceId: string): WriteSession[] {\r\n return [...this.sessions.values()].filter((session) => session.deviceId === deviceId);\r\n }\r\n}\r\n","import express from 'express';\r\nimport { createServer, type Server } from 'node:http';\r\nimport {\r\n DEFAULT_DEVTOOLS_HOST,\r\n DEFAULT_DEVTOOLS_PORT,\r\n DEVICE_SNAPSHOT_API_PATH,\r\n MAX_SNAPSHOT_BYTES,\r\n PROJECT_DATABASE_API_PATH,\r\n PROJECT_DATABASE_META_API_PATH,\r\n PROJECT_DATABASES_API_PATH,\r\n PROJECT_DEVICE_EXPORTS_API_PATH,\r\n buildDevToolsHttpUrl,\r\n buildDevToolsWsUrl,\r\n} from '../types/protocol';\r\nimport { SNAPSHOT_KIND_HEADER, SNAPSHOT_MIME_HEADER, SNAPSHOT_NAME_HEADER, SQLITE_SNAPSHOT_MIME_TYPE } from '../types/snapshot';\r\nimport { logger } from '../utils/logger';\r\nimport { attachWebUi } from './attachWebUi';\r\nimport { attachWebSocket } from './attachWebSocket';\r\nimport { ConnectionManager } from './connectionManager';\r\nimport { createCorsMiddleware } from './cors';\r\nimport { DeviceRegistry } from './deviceRegistry';\r\nimport { Heartbeat } from './heartbeat';\r\nimport { MessageRouter } from './messageRouter';\r\nimport { PendingRefreshStore } from './pendingRefreshStore';\r\nimport { RefreshCoordinator } from './refreshCoordinator';\r\nimport { SnapshotFileStore } from './snapshotFileStore';\r\nimport { SnapshotStore } from './snapshotStore';\r\nimport { WriteCoordinator } from './writeCoordinator';\r\nimport { WriteSessionManager } from './writeSessionManager';\r\n\r\nexport type DevToolsServerOptions = {\r\n host?: string;\r\n port?: number;\r\n dataDir?: string;\r\n snapshotPersistence?: boolean;\r\n webDistPath?: string;\r\n};\r\n\r\nexport type DevToolsServerUrls = {\r\n httpUrl: string;\r\n wsUrl: string;\r\n webUiEnabled: boolean;\r\n};\r\n\r\nexport type DevToolsServer = {\r\n app: express.Express;\r\n httpServer: Server;\r\n connectionManager: ConnectionManager;\r\n deviceRegistry: DeviceRegistry;\r\n router: MessageRouter;\r\n heartbeat: Heartbeat;\r\n snapshotStore: SnapshotStore;\r\n snapshotFileStore: SnapshotFileStore;\r\n pendingRefreshStore: PendingRefreshStore;\r\n writeSessions: WriteSessionManager;\r\n refreshCoordinator: RefreshCoordinator;\r\n writeCoordinator: WriteCoordinator;\r\n urls: DevToolsServerUrls;\r\n close: () => Promise<void>;\r\n};\r\n\r\nexport async function createDevToolsServer(\r\n options: DevToolsServerOptions = {},\r\n): Promise<DevToolsServer> {\r\n const host = options.host ?? DEFAULT_DEVTOOLS_HOST;\r\n const port = options.port ?? DEFAULT_DEVTOOLS_PORT;\r\n\r\n const app = express();\r\n const connectionManager = new ConnectionManager();\r\n const deviceRegistry = new DeviceRegistry(connectionManager);\r\n const router = new MessageRouter(connectionManager, deviceRegistry);\r\n const heartbeat = new Heartbeat(connectionManager, router);\r\n const snapshotStore = new SnapshotStore();\r\n const snapshotFileStore = new SnapshotFileStore({\r\n dataDir: options.dataDir,\r\n enabled: options.snapshotPersistence,\r\n });\r\n const pendingRefreshStore = new PendingRefreshStore();\r\n const writeSessions = new WriteSessionManager();\r\n\r\n const refreshCoordinator = new RefreshCoordinator(\r\n connectionManager,\r\n router,\r\n pendingRefreshStore,\r\n snapshotStore,\r\n snapshotFileStore,\r\n );\r\n const writeCoordinator = new WriteCoordinator(connectionManager, router, writeSessions);\r\n\r\n app.use(createCorsMiddleware());\r\n\r\n app.get('/health', (_request, response) => {\r\n response.json({ ok: true, ...deviceRegistry.snapshot() });\r\n });\r\n\r\n app.post(\r\n `${DEVICE_SNAPSHOT_API_PATH}/:deviceId/snapshot`,\r\n express.raw({ type: 'application/octet-stream', limit: MAX_SNAPSHOT_BYTES }),\r\n async (request, response) => {\r\n const deviceId = decodeURIComponent(request.params.deviceId);\r\n const body = request.body;\r\n\r\n if (!Buffer.isBuffer(body) || body.length === 0) {\r\n response.status(400).json({ ok: false, error: 'Empty snapshot body' });\r\n return;\r\n }\r\n\r\n const kindHeader = request.header(SNAPSHOT_KIND_HEADER);\r\n const mimeHeader = request.header(SNAPSHOT_MIME_HEADER);\r\n const nameHeader = request.header(SNAPSHOT_NAME_HEADER);\r\n\r\n const result = await refreshCoordinator.handleSnapshotUpload(deviceId, body, {\r\n kind: typeof kindHeader === 'string' ? kindHeader : undefined,\r\n mimeType: typeof mimeHeader === 'string' ? mimeHeader : undefined,\r\n databaseName: typeof nameHeader === 'string' ? nameHeader : undefined,\r\n });\r\n\r\n if (!result.ok) {\r\n response.status(result.code === 'SNAPSHOT_NOT_FOUND' ? 404 : 400).json({\r\n ok: false,\r\n error: result.code,\r\n });\r\n return;\r\n }\r\n\r\n response.status(201).json({ ok: true, deviceId, size: body.byteLength });\r\n },\r\n );\r\n\r\n app.get(`${DEVICE_SNAPSHOT_API_PATH}/:deviceId/snapshot`, async (request, response) => {\r\n const deviceId = decodeURIComponent(request.params.deviceId);\r\n const snapshot = await refreshCoordinator.getSnapshotAsync(deviceId);\r\n\r\n if (!snapshot) {\r\n response.status(404).json({ ok: false, error: 'SNAPSHOT_NOT_FOUND' });\r\n return;\r\n }\r\n\r\n response\r\n .status(200)\r\n .set('Content-Type', 'application/octet-stream')\r\n .send(snapshot);\r\n });\r\n\r\n app.get(PROJECT_DATABASE_META_API_PATH, async (_request, response) => {\r\n const meta = await snapshotFileStore.getActiveDatabaseMeta();\r\n response.json(meta);\r\n });\r\n\r\n app.get(PROJECT_DATABASES_API_PATH, async (_request, response) => {\r\n const databases = await snapshotFileStore.listDatabases();\r\n response.json({ databases });\r\n });\r\n\r\n app.get(PROJECT_DEVICE_EXPORTS_API_PATH, async (_request, response) => {\r\n const devices = await snapshotFileStore.listDeviceExports();\r\n response.json({ devices });\r\n });\r\n\r\n app.get(`${PROJECT_DEVICE_EXPORTS_API_PATH}/:deviceId/database/meta`, async (request, response) => {\r\n const deviceId = decodeURIComponent(request.params.deviceId);\r\n const meta = await snapshotFileStore.getDeviceDatabaseMeta(deviceId);\r\n response.json(meta);\r\n });\r\n\r\n app.get(`${PROJECT_DEVICE_EXPORTS_API_PATH}/:deviceId/database`, async (request, response) => {\r\n const deviceId = decodeURIComponent(request.params.deviceId);\r\n const meta = await snapshotFileStore.getDeviceDatabaseMeta(deviceId);\r\n\r\n if (!meta.exists) {\r\n response.status(404).json({ ok: false, error: 'DEVICE_DATABASE_NOT_FOUND', deviceId });\r\n return;\r\n }\r\n\r\n const bytes = await snapshotFileStore.readDeviceDatabase(deviceId);\r\n\r\n if (!bytes) {\r\n response.status(404).json({ ok: false, error: 'DEVICE_DATABASE_NOT_FOUND', deviceId });\r\n return;\r\n }\r\n\r\n response\r\n .status(200)\r\n .set('Content-Type', meta.mimeType ?? SQLITE_SNAPSHOT_MIME_TYPE)\r\n .send(bytes);\r\n });\r\n\r\n app.get(PROJECT_DATABASE_API_PATH, async (_request, response) => {\r\n const meta = await snapshotFileStore.getActiveDatabaseMeta();\r\n\r\n if (!meta.exists) {\r\n response.status(404).json({ ok: false, error: 'PROJECT_DATABASE_NOT_FOUND' });\r\n return;\r\n }\r\n\r\n const bytes = await snapshotFileStore.readActiveDatabase();\r\n\r\n if (!bytes) {\r\n response.status(404).json({ ok: false, error: 'PROJECT_DATABASE_NOT_FOUND' });\r\n return;\r\n }\r\n\r\n response\r\n .status(200)\r\n .set('Content-Type', meta.mimeType ?? SQLITE_SNAPSHOT_MIME_TYPE)\r\n .send(bytes);\r\n });\r\n\r\n if (options.webDistPath) {\r\n attachWebUi(app, options.webDistPath);\r\n }\r\n\r\n const httpServer = createServer(app);\r\n attachWebSocket(\r\n httpServer,\r\n connectionManager,\r\n router,\r\n heartbeat,\r\n refreshCoordinator,\r\n writeCoordinator,\r\n { snapshotFileStore },\r\n );\r\n\r\n const refreshTimeoutInterval = setInterval(() => {\r\n refreshCoordinator.checkTimeouts();\r\n writeCoordinator.checkTimeouts();\r\n }, 5_000);\r\n\r\n if (snapshotFileStore.isEnabled()) {\r\n await snapshotFileStore.listDeviceExports();\r\n }\r\n\r\n await new Promise<void>((resolve, reject) => {\r\n httpServer.once('error', reject);\r\n httpServer.listen(port, host, () => resolve());\r\n });\r\n\r\n const displayHost = host === '0.0.0.0' ? 'localhost' : host;\r\n const httpUrl = buildDevToolsHttpUrl(displayHost, port);\r\n const wsUrl = buildDevToolsWsUrl(displayHost, port);\r\n const webUiEnabled = Boolean(options.webDistPath);\r\n\r\n logger.serverStarted(httpUrl, wsUrl, webUiEnabled);\r\n\r\n return {\r\n app,\r\n httpServer,\r\n connectionManager,\r\n deviceRegistry,\r\n router,\r\n heartbeat,\r\n snapshotStore,\r\n snapshotFileStore,\r\n pendingRefreshStore,\r\n writeSessions,\r\n refreshCoordinator,\r\n writeCoordinator,\r\n urls: {\r\n httpUrl,\r\n wsUrl,\r\n webUiEnabled,\r\n },\r\n close: () =>\r\n new Promise((resolve, reject) => {\r\n clearInterval(refreshTimeoutInterval);\r\n heartbeat.stop();\r\n httpServer.close((error) => {\r\n if (error) {\r\n reject(error);\r\n return;\r\n }\r\n\r\n resolve();\r\n });\r\n }),\r\n };\r\n}\r\n"]}
|