diff --git a/index.js b/index.js index 09b6e29..ba0d01f 100644 --- a/index.js +++ b/index.js @@ -16,7 +16,7 @@ * the DSH credential service (falling back to the process environment). */ -import { existsSync, readdirSync } from 'node:fs' +import { existsSync, readdirSync, statSync } from 'node:fs' import { mkdir, readFile, writeFile } from 'node:fs/promises' import { request as httpRequest } from 'node:http' import { request as httpsRequest } from 'node:https' @@ -508,8 +508,52 @@ export function apply(ctx, config) { } } + /** + * The workspace whose destinations file was written most recently. An empty + * destinations list (a scratch config, or one where every system was removed) + * loses to any workspace that still lists systems, so the settings page never + * opens on an empty page while a usable config exists elsewhere. + */ + async function lastModifiedWorkspace() { + let best + let bestTime = -Infinity + let any + let anyTime = -Infinity + for (const row of listWorkspaces()) { + if (!row.path) continue + for (const fileName of FILE_NAMES) { + const candidate = join(row.path, CONFIG_DIR, fileName) + let mtimeMs + try { + mtimeMs = statSync(candidate).mtimeMs + } catch { + continue + } + if (mtimeMs > anyTime) { + anyTime = mtimeMs + any = row.path + } + if (mtimeMs <= bestTime) continue + try { + const parsed = await parseDestinations(await readFile(candidate, 'utf8')) + if (!normalizeDestinations(parsed.destinations).length) continue + } catch { + continue + } + bestTime = mtimeMs + best = row.path + } + } + return best || any + } + async function stateOf({ sessionId, workspace }) { - const cwd = workspace || resolveCwd(sessionId) || listWorkspaces()[0]?.path || process.cwd() + const cwd = + workspace || + resolveCwd(sessionId) || + (await lastModifiedWorkspace()) || + listWorkspaces()[0]?.path || + process.cwd() const file = existingWorkspaceFile(cwd) let raw = '' let exists = false