UNPKG

everything-dev

Version:

A consolidated product package for building Module Federation apps with oRPC APIs.

1 lines 10.6 kB
{"version":3,"file":"streaming-view.cjs","names":["colors","icons","linkify"],"sources":["../../src/components/streaming-view.ts"],"sourcesContent":["import chalk from \"chalk\";\nimport { linkify } from \"../utils/linkify\";\nimport { colors, icons } from \"../utils/theme\";\nimport type { ProcessState, ProcessStatus } from \"./dev-view\";\n\nconst orange = chalk.hex(\"#ffaa00\");\nconst PLUGIN_PREFIX = \"plugin:\";\n\nexport interface StreamingViewHandle {\n updateProcess: (name: string, status: ProcessStatus, message?: string) => void;\n addLog: (source: string, line: string, isError?: boolean) => void;\n unmount: () => Promise<void> | void;\n}\n\nconst getTimestamp = (): string => {\n const now = new Date();\n return `${now.getHours().toString().padStart(2, \"0\")}:${now.getMinutes().toString().padStart(2, \"0\")}:${now.getSeconds().toString().padStart(2, \"0\")}`;\n};\n\nconst write = (text: string) => process.stdout.write(`${text}\\n`);\n\nconst getServiceColor = (name: string): ((s: string) => string) => {\n if (name.startsWith(PLUGIN_PREFIX)) return orange;\n if (name === \"host\") return colors.cyan;\n if (name === \"ui\" || name === \"ui-ssr\") return colors.magenta;\n if (name === \"api\") return colors.blue;\n return colors.white;\n};\n\nconst getDisplayName = (name: string): string => {\n return name.startsWith(PLUGIN_PREFIX)\n ? name.slice(PLUGIN_PREFIX.length).toUpperCase()\n : name.toUpperCase();\n};\n\nconst isPlugin = (name: string): boolean => name.startsWith(PLUGIN_PREFIX);\n\nconst getSectionedProcesses = (processes: ProcessState[]) => {\n const plugins = processes.filter((p) => isPlugin(p.name));\n const services = processes.filter((p) => !isPlugin(p.name));\n const sections: Array<{ key: string; title: string; processes: ProcessState[] }> = [];\n if (plugins.length > 0) sections.push({ key: \"plugins\", title: \"PLUGINS\", processes: plugins });\n if (services.length > 0)\n sections.push({ key: \"services\", title: \"SERVICES\", processes: services });\n return sections;\n};\n\nconst getColumnWidths = (processes: ProcessState[]) => {\n const name = Math.max(6, ...processes.map((p) => getDisplayName(p.name).length));\n const source = Math.max(10, ...processes.map((p) => (p.source ? ` (${p.source})`.length : 0)));\n return { name, source };\n};\n\nconst getStatusIcon = (status: ProcessStatus): string => {\n switch (status) {\n case \"pending\":\n return icons.pending;\n case \"starting\":\n return icons.scan;\n case \"ready\":\n return icons.ok;\n case \"error\":\n return icons.err;\n }\n};\n\nexport function renderStreamingView(\n initialProcesses: ProcessState[],\n description: string,\n env: Record<string, string>,\n onExit?: () => Promise<void> | void,\n): StreamingViewHandle {\n const processes = new Map<string, ProcessState>();\n for (const p of initialProcesses) {\n processes.set(p.name, { ...p });\n }\n\n let allReadyPrinted = false;\n const hostProcess = initialProcesses.find((p) => p.name === \"host\");\n const hostPort = hostProcess?.port || 3000;\n const proxyTarget = env.API_PROXY;\n const sectionedProcesses = getSectionedProcesses(initialProcesses);\n const columnWidths = getColumnWidths(initialProcesses);\n const lastLogBySource = new Map<string, string>();\n\n const headerLines: string[] = [\n \"\",\n colors.cyan(`${\"\".repeat(52)}`),\n ` ${icons.run} ${colors.cyan(description.toUpperCase())}`,\n colors.cyan(`${\"\".repeat(52)}`),\n \"\",\n ];\n\n if (proxyTarget) {\n headerLines.push(orange(` ${icons.arrow} API PROXY → ${proxyTarget}`), \"\");\n }\n\n for (const section of sectionedProcesses) {\n headerLines.push(colors.cyan(` ${section.title}`));\n for (const proc of section.processes) {\n const color = getServiceColor(proc.name);\n const sourceLabel = proc.source ? ` (${proc.source})` : \"\";\n headerLines.push(\n `${colors.dim(`[${getTimestamp()}]`)} ${color(`[${getDisplayName(proc.name).padEnd(columnWidths.name)}]`)} ${icons.pending} waiting${sourceLabel.padEnd(columnWidths.source)}`,\n );\n }\n headerLines.push(\"\");\n }\n console.log(headerLines.join(\"\\n\"));\n\n const checkAllReady = () => {\n if (allReadyPrinted) return;\n const allReady = Array.from(processes.values()).every((p) => p.status === \"ready\");\n if (allReady) {\n allReadyPrinted = true;\n const readyLines = [\n \"\",\n colors.dim(`${\"\".repeat(52)}`),\n colors.green(`${icons.ok} All ${processes.size} services ready`),\n colors.green(`${icons.arrow} http://localhost:${hostPort}`),\n colors.dim(`${\"\".repeat(52)}`),\n \"\",\n ];\n console.log(readyLines.join(\"\\n\"));\n }\n };\n\n const updateProcess = (name: string, status: ProcessStatus, message?: string) => {\n const proc = processes.get(name);\n if (!proc) return;\n\n proc.status = status;\n if (message) proc.message = message;\n\n const color = getServiceColor(name);\n const icon = getStatusIcon(status);\n const displayName = getDisplayName(name).padEnd(columnWidths.name);\n const sourceLabel = proc?.source ? ` (${proc.source})` : \"\";\n const isRemote = proc?.source === \"remote\";\n const isHost = name === \"host\";\n const showPort = proc.port > 0 && (isHost || !isRemote) && status === \"ready\";\n const statusText =\n status === \"ready\"\n ? isRemote && !isHost\n ? \"loaded\"\n : \"running\"\n : status === \"starting\"\n ? \"starting\"\n : status === \"error\"\n ? \"failed\"\n : \"waiting\";\n const portStr = showPort ? ` :${proc.port}` : \"\";\n\n write(\n `${colors.dim(`[${getTimestamp()}]`)} ${color(`[${displayName}]`)} ${status === \"ready\" ? colors.green(icon) : status === \"error\" ? colors.error(icon) : icon} ${statusText}${sourceLabel.padEnd(columnWidths.source)}${portStr}`,\n );\n\n checkAllReady();\n };\n\n const addLog = (source: string, line: string, isError = false) => {\n const lastLine = lastLogBySource.get(source);\n const nextLine = `${isError ? \"ERR\" : \"OUT\"}:${line}`;\n if (lastLine === nextLine) return;\n lastLogBySource.set(source, nextLine);\n\n const color = getServiceColor(source);\n const logColor = isError ? colors.error : colors.dim;\n write(\n `${colors.dim(`[${getTimestamp()}]`)} ${color(`[${source.toUpperCase()}]`)} ${colors.dim(\"\")} ${logColor(linkify(line))}`,\n );\n };\n\n const unmount = () => onExit?.();\n\n return { updateProcess, addLog, unmount };\n}\n"],"mappings":";;;;;;;AAKA,MAAM,SAAS,cAAM,IAAI,SAAS;AAClC,MAAM,gBAAgB;AAQtB,MAAM,qBAA6B;CACjC,MAAM,sBAAM,IAAI,KAAK;CACrB,OAAO,GAAG,IAAI,SAAS,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,GAAG,GAAG,EAAE,GAAG,IAAI,WAAW,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,GAAG,GAAG,EAAE,GAAG,IAAI,WAAW,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,GAAG,GAAG;AACrJ;AAEA,MAAM,SAAS,SAAiB,QAAQ,OAAO,MAAM,GAAG,KAAK,GAAG;AAEhE,MAAM,mBAAmB,SAA0C;CACjE,IAAI,KAAK,WAAW,aAAa,GAAG,OAAO;CAC3C,IAAI,SAAS,QAAQ,OAAOA,qBAAO;CACnC,IAAI,SAAS,QAAQ,SAAS,UAAU,OAAOA,qBAAO;CACtD,IAAI,SAAS,OAAO,OAAOA,qBAAO;CAClC,OAAOA,qBAAO;AAChB;AAEA,MAAM,kBAAkB,SAAyB;CAC/C,OAAO,KAAK,WAAW,aAAa,IAChC,KAAK,MAAM,CAAoB,CAAC,CAAC,YAAY,IAC7C,KAAK,YAAY;AACvB;AAEA,MAAM,YAAY,SAA0B,KAAK,WAAW,aAAa;AAEzE,MAAM,yBAAyB,cAA8B;CAC3D,MAAM,UAAU,UAAU,QAAQ,MAAM,SAAS,EAAE,IAAI,CAAC;CACxD,MAAM,WAAW,UAAU,QAAQ,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC;CAC1D,MAAM,WAA6E,CAAC;CACpF,IAAI,QAAQ,SAAS,GAAG,SAAS,KAAK;EAAE,KAAK;EAAW,OAAO;EAAW,WAAW;CAAQ,CAAC;CAC9F,IAAI,SAAS,SAAS,GACpB,SAAS,KAAK;EAAE,KAAK;EAAY,OAAO;EAAY,WAAW;CAAS,CAAC;CAC3E,OAAO;AACT;AAEA,MAAM,mBAAmB,cAA8B;CAGrD,OAAO;EAAE,MAFI,KAAK,IAAI,GAAG,GAAG,UAAU,KAAK,MAAM,eAAe,EAAE,IAAI,CAAC,CAAC,MAAM,CAElE;EAAG,QADA,KAAK,IAAI,IAAI,GAAG,UAAU,KAAK,MAAO,EAAE,SAAS,KAAK,EAAE,OAAO,GAAG,SAAS,CAAE,CACxE;CAAE;AACxB;AAEA,MAAM,iBAAiB,WAAkC;CACvD,QAAQ,QAAR;EACE,KAAK,WACH,OAAOC,oBAAM;EACf,KAAK,YACH,OAAOA,oBAAM;EACf,KAAK,SACH,OAAOA,oBAAM;EACf,KAAK,SACH,OAAOA,oBAAM;CACjB;AACF;AAEA,SAAgB,oBACd,kBACA,aACA,KACA,QACqB;CACrB,MAAM,4BAAY,IAAI,IAA0B;CAChD,KAAK,MAAM,KAAK,kBACd,UAAU,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;CAGhC,IAAI,kBAAkB;CAEtB,MAAM,WADc,iBAAiB,MAAM,MAAM,EAAE,SAAS,MACjC,CAAC,EAAE,QAAQ;CACtC,MAAM,cAAc,IAAI;CACxB,MAAM,qBAAqB,sBAAsB,gBAAgB;CACjE,MAAM,eAAe,gBAAgB,gBAAgB;CACrD,MAAM,kCAAkB,IAAI,IAAoB;CAEhD,MAAM,cAAwB;EAC5B;EACAD,qBAAO,KAAK,GAAG,IAAI,OAAO,EAAE,GAAG;EAC/B,KAAKC,oBAAM,IAAI,GAAGD,qBAAO,KAAK,YAAY,YAAY,CAAC;EACvDA,qBAAO,KAAK,GAAG,IAAI,OAAO,EAAE,GAAG;EAC/B;CACF;CAEA,IAAI,aACF,YAAY,KAAK,OAAO,KAAKC,oBAAM,MAAM,eAAe,aAAa,GAAG,EAAE;CAG5E,KAAK,MAAM,WAAW,oBAAoB;EACxC,YAAY,KAAKD,qBAAO,KAAK,KAAK,QAAQ,OAAO,CAAC;EAClD,KAAK,MAAM,QAAQ,QAAQ,WAAW;GACpC,MAAM,QAAQ,gBAAgB,KAAK,IAAI;GACvC,MAAM,cAAc,KAAK,SAAS,KAAK,KAAK,OAAO,KAAK;GACxD,YAAY,KACV,GAAGA,qBAAO,IAAI,IAAI,aAAa,EAAE,EAAE,EAAE,GAAG,MAAM,IAAI,eAAe,KAAK,IAAI,CAAC,CAAC,OAAO,aAAa,IAAI,EAAE,EAAE,EAAE,IAAIC,oBAAM,QAAQ,UAAU,YAAY,OAAO,aAAa,MAAM,GAC9K;EACF;EACA,YAAY,KAAK,EAAE;CACrB;CACA,QAAQ,IAAI,YAAY,KAAK,IAAI,CAAC;CAElC,MAAM,sBAAsB;EAC1B,IAAI,iBAAiB;EAErB,IADiB,MAAM,KAAK,UAAU,OAAO,CAAC,CAAC,CAAC,OAAO,MAAM,EAAE,WAAW,OAC/D,GAAG;GACZ,kBAAkB;GAClB,MAAM,aAAa;IACjB;IACAD,qBAAO,IAAI,GAAG,IAAI,OAAO,EAAE,GAAG;IAC9BA,qBAAO,MAAM,GAAGC,oBAAM,GAAG,OAAO,UAAU,KAAK,gBAAgB;IAC/DD,qBAAO,MAAM,GAAGC,oBAAM,MAAM,oBAAoB,UAAU;IAC1DD,qBAAO,IAAI,GAAG,IAAI,OAAO,EAAE,GAAG;IAC9B;GACF;GACA,QAAQ,IAAI,WAAW,KAAK,IAAI,CAAC;EACnC;CACF;CAEA,MAAM,iBAAiB,MAAc,QAAuB,YAAqB;EAC/E,MAAM,OAAO,UAAU,IAAI,IAAI;EAC/B,IAAI,CAAC,MAAM;EAEX,KAAK,SAAS;EACd,IAAI,SAAS,KAAK,UAAU;EAE5B,MAAM,QAAQ,gBAAgB,IAAI;EAClC,MAAM,OAAO,cAAc,MAAM;EACjC,MAAM,cAAc,eAAe,IAAI,CAAC,CAAC,OAAO,aAAa,IAAI;EACjE,MAAM,cAAc,MAAM,SAAS,KAAK,KAAK,OAAO,KAAK;EACzD,MAAM,WAAW,MAAM,WAAW;EAClC,MAAM,SAAS,SAAS;EACxB,MAAM,WAAW,KAAK,OAAO,MAAM,UAAU,CAAC,aAAa,WAAW;EACtE,MAAM,aACJ,WAAW,UACP,YAAY,CAAC,SACX,WACA,YACF,WAAW,aACT,aACA,WAAW,UACT,WACA;EACV,MAAM,UAAU,WAAW,KAAK,KAAK,SAAS;EAE9C,MACE,GAAGA,qBAAO,IAAI,IAAI,aAAa,EAAE,EAAE,EAAE,GAAG,MAAM,IAAI,YAAY,EAAE,EAAE,IAAI,WAAW,UAAUA,qBAAO,MAAM,IAAI,IAAI,WAAW,UAAUA,qBAAO,MAAM,IAAI,IAAI,KAAK,GAAG,aAAa,YAAY,OAAO,aAAa,MAAM,IAAI,SAC3N;EAEA,cAAc;CAChB;CAEA,MAAM,UAAU,QAAgB,MAAc,UAAU,UAAU;EAChE,MAAM,WAAW,gBAAgB,IAAI,MAAM;EAC3C,MAAM,WAAW,GAAG,UAAU,QAAQ,MAAM,GAAG;EAC/C,IAAI,aAAa,UAAU;EAC3B,gBAAgB,IAAI,QAAQ,QAAQ;EAEpC,MAAM,QAAQ,gBAAgB,MAAM;EACpC,MAAM,WAAW,UAAUA,qBAAO,QAAQA,qBAAO;EACjD,MACE,GAAGA,qBAAO,IAAI,IAAI,aAAa,EAAE,EAAE,EAAE,GAAG,MAAM,IAAI,OAAO,YAAY,EAAE,EAAE,EAAE,IAAIA,qBAAO,IAAI,GAAG,EAAE,GAAG,SAASE,wBAAQ,IAAI,CAAC,GAC1H;CACF;CAEA,MAAM,gBAAgB,SAAS;CAE/B,OAAO;EAAE;EAAe;EAAQ;CAAQ;AAC1C"}