Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
66 lines
2.0 KiB
TypeScript
66 lines
2.0 KiB
TypeScript
/** Host-like input for select-host group matching (avoids coupling to full Host). */
|
|
export type SelectHostGroupMatchable = {
|
|
id: string;
|
|
group?: string;
|
|
protocol?: string;
|
|
};
|
|
|
|
export type GroupSelectionState = 'none' | 'partial' | 'all';
|
|
|
|
/** Whether a host belongs to groupPath (exact match or nested under it). */
|
|
export function hostMatchesGroupPath(
|
|
host: Pick<SelectHostGroupMatchable, 'group'>,
|
|
groupPath: string,
|
|
): boolean {
|
|
const path = groupPath.trim();
|
|
if (!path) return false;
|
|
const group = host.group?.trim() ?? '';
|
|
return group === path || group.startsWith(`${path}/`);
|
|
}
|
|
|
|
/** Collect selectable (non-serial) host ids under a group path, including nested groups. */
|
|
export function collectSelectableHostIdsInGroup(
|
|
hosts: SelectHostGroupMatchable[],
|
|
groupPath: string,
|
|
): string[] {
|
|
return hosts
|
|
.filter((host) => host.protocol !== 'serial' && hostMatchesGroupPath(host, groupPath))
|
|
.map((host) => host.id);
|
|
}
|
|
|
|
export function getGroupSelectionState(
|
|
selectedHostIds: Iterable<string>,
|
|
groupHostIds: string[],
|
|
): GroupSelectionState {
|
|
if (groupHostIds.length === 0) return 'none';
|
|
const selected = selectedHostIds instanceof Set
|
|
? selectedHostIds
|
|
: new Set(selectedHostIds);
|
|
let matched = 0;
|
|
for (const id of groupHostIds) {
|
|
if (selected.has(id)) matched += 1;
|
|
}
|
|
if (matched === 0) return 'none';
|
|
if (matched === groupHostIds.length) return 'all';
|
|
return 'partial';
|
|
}
|
|
|
|
/**
|
|
* Toggle a set of host ids in the current selection.
|
|
* If every id is already selected, remove them; otherwise add any missing ones.
|
|
*/
|
|
export function toggleIdsInSelection(
|
|
selectedHostIds: string[],
|
|
idsToToggle: string[],
|
|
): string[] {
|
|
if (idsToToggle.length === 0) return [...selectedHostIds];
|
|
const selected = new Set(selectedHostIds);
|
|
const allSelected = idsToToggle.every((id) => selected.has(id));
|
|
if (allSelected) {
|
|
for (const id of idsToToggle) selected.delete(id);
|
|
} else {
|
|
for (const id of idsToToggle) selected.add(id);
|
|
}
|
|
return Array.from(selected);
|
|
}
|