Skip to content

Commit 3f63bc1

Browse files
committed
refactor: extract settings hub entry wrapper
1 parent 05defab commit 3f63bc1

3 files changed

Lines changed: 99 additions & 1 deletion

File tree

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import type { MenuItem, SelectOptions } from "../ui/select.js";
2+
import type { SettingsHubActionType } from "./unified-settings-controller.js";
3+
4+
export async function promptSettingsHubEntry<
5+
TAction extends { type: SettingsHubActionType },
6+
>(params: {
7+
initialFocus: TAction["type"];
8+
promptSettingsHubMenu: (
9+
initialFocus: TAction["type"],
10+
deps: {
11+
isInteractive: () => boolean;
12+
getUiRuntimeOptions: () => ReturnType<
13+
typeof import("../ui/runtime.js").getUiRuntimeOptions
14+
>;
15+
buildItems: () => MenuItem<TAction>[];
16+
findInitialCursor: (
17+
items: MenuItem<TAction>[],
18+
initialFocus: TAction["type"],
19+
) => number | undefined;
20+
select: <T>(
21+
items: MenuItem<T>[],
22+
options: SelectOptions<T>,
23+
) => Promise<T | null>;
24+
copy: {
25+
title: string;
26+
subtitle: string;
27+
help: string;
28+
};
29+
},
30+
) => Promise<TAction | null>;
31+
isInteractive: () => boolean;
32+
getUiRuntimeOptions: () => ReturnType<
33+
typeof import("../ui/runtime.js").getUiRuntimeOptions
34+
>;
35+
buildItems: () => MenuItem<TAction>[];
36+
findInitialCursor: (
37+
items: MenuItem<TAction>[],
38+
initialFocus: TAction["type"],
39+
) => number | undefined;
40+
select: <T>(
41+
items: MenuItem<T>[],
42+
options: SelectOptions<T>,
43+
) => Promise<T | null>;
44+
copy: {
45+
title: string;
46+
subtitle: string;
47+
help: string;
48+
};
49+
}): Promise<TAction | null> {
50+
return params.promptSettingsHubMenu(params.initialFocus, {
51+
isInteractive: params.isInteractive,
52+
getUiRuntimeOptions: params.getUiRuntimeOptions,
53+
buildItems: params.buildItems,
54+
findInitialCursor: params.findInitialCursor,
55+
select: params.select,
56+
copy: params.copy,
57+
});
58+
}

lib/codex-manager/settings-hub.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ import {
7070
} from "./experimental-settings-schema.js";
7171
import { loadExperimentalSyncTargetState } from "./experimental-sync-target.js";
7272
import { loadExperimentalSyncTargetEntry } from "./experimental-sync-target-entry.js";
73+
import { promptSettingsHubEntry } from "./settings-hub-entry.js";
7374
import {
7475
buildSettingsHubItems,
7576
findSettingsHubInitialCursor,
@@ -758,7 +759,9 @@ async function configureBackendSettings(
758759
async function promptSettingsHub(
759760
initialFocus: SettingsHubAction["type"] = "account-list",
760761
): Promise<SettingsHubAction | null> {
761-
return promptSettingsHubMenu(initialFocus, {
762+
return promptSettingsHubEntry({
763+
initialFocus,
764+
promptSettingsHubMenu,
762765
isInteractive: () => input.isTTY && output.isTTY,
763766
getUiRuntimeOptions,
764767
buildItems: () => buildSettingsHubItems(UI_COPY.settings),

test/settings-hub-entry.test.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { describe, expect, it, vi } from "vitest";
2+
import { promptSettingsHubEntry } from "../lib/codex-manager/settings-hub-entry.js";
3+
4+
describe("settings hub entry", () => {
5+
it("passes focus and dependencies through to the settings hub prompt helper", async () => {
6+
const promptSettingsHubMenu = vi.fn(async () => ({
7+
type: "back" as const,
8+
}));
9+
const buildItems = vi.fn(() => []);
10+
const findInitialCursor = vi.fn(() => 0);
11+
const select = vi.fn();
12+
13+
const result = await promptSettingsHubEntry({
14+
initialFocus: "account-list",
15+
promptSettingsHubMenu,
16+
isInteractive: () => true,
17+
getUiRuntimeOptions: vi.fn(() => ({ theme: {} }) as never),
18+
buildItems,
19+
findInitialCursor,
20+
select,
21+
copy: { title: "Settings", subtitle: "Subtitle", help: "Help" },
22+
});
23+
24+
expect(promptSettingsHubMenu).toHaveBeenCalledWith(
25+
"account-list",
26+
expect.objectContaining({
27+
isInteractive: expect.any(Function),
28+
getUiRuntimeOptions: expect.any(Function),
29+
buildItems,
30+
findInitialCursor,
31+
select,
32+
copy: { title: "Settings", subtitle: "Subtitle", help: "Help" },
33+
}),
34+
);
35+
expect(result).toEqual({ type: "back" });
36+
});
37+
});

0 commit comments

Comments
 (0)