(sources: SourceDisplayInfo[])
| 93 | * Generate the startup table showing sources and their tools |
| 94 | */ |
| 95 | export function generateStartupTable(sources: SourceDisplayInfo[]): string { |
| 96 | if (sources.length === 0) { |
| 97 | return ""; |
| 98 | } |
| 99 | |
| 100 | // Calculate column widths based on content |
| 101 | const idTypeWidth = Math.max( |
| 102 | 20, |
| 103 | ...sources.map((s) => `${s.id} (${s.type})`.length) |
| 104 | ); |
| 105 | const hostDbWidth = Math.max( |
| 106 | 24, |
| 107 | ...sources.map((s) => formatHostDatabase(s.host, s.database).length) |
| 108 | ); |
| 109 | const modeWidth = Math.max( |
| 110 | 10, |
| 111 | ...sources.map((s) => { |
| 112 | const modes: string[] = []; |
| 113 | if (s.isDemo) modes.push("DEMO"); |
| 114 | if (s.readonly) modes.push("READ-ONLY"); |
| 115 | return modes.join(" ").length; |
| 116 | }) |
| 117 | ); |
| 118 | |
| 119 | // Total width: left border (1) + space + idTypeWidth + space + separator (1) + space + hostDbWidth + space + separator (1) + space + modeWidth + space + right border (1) |
| 120 | // = idTypeWidth + hostDbWidth + modeWidth + 10 |
| 121 | const totalWidth = 2 + idTypeWidth + 3 + hostDbWidth + 3 + modeWidth + 2; |
| 122 | |
| 123 | const lines: string[] = []; |
| 124 | |
| 125 | for (let i = 0; i < sources.length; i++) { |
| 126 | const source = sources[i]; |
| 127 | const isFirst = i === 0; |
| 128 | const isLast = i === sources.length - 1; |
| 129 | |
| 130 | // Top border (only for first source) |
| 131 | if (isFirst) { |
| 132 | lines.push(horizontalLine(totalWidth, BOX.topLeft, BOX.topRight)); |
| 133 | } |
| 134 | |
| 135 | // Source header row |
| 136 | const idType = fitString(`${source.id} (${source.type})`, idTypeWidth); |
| 137 | const hostDb = fitString( |
| 138 | formatHostDatabase(source.host, source.database), |
| 139 | hostDbWidth |
| 140 | ); |
| 141 | |
| 142 | // Mode indicators |
| 143 | const modes: string[] = []; |
| 144 | if (source.isDemo) modes.push("DEMO"); |
| 145 | if (source.readonly) modes.push("READ-ONLY"); |
| 146 | const modeStr = fitString(modes.join(" "), modeWidth); |
| 147 | |
| 148 | lines.push( |
| 149 | `${BOX.vertical} ${idType} ${BOX.vertical} ${hostDb} ${BOX.vertical} ${modeStr} ${BOX.vertical}` |
| 150 | ); |
| 151 | |
| 152 | // Separator after header |
no test coverage detected