@kainoa/simplybuild 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +62 -0
  2. package/dist/app/runSimplyBuild.d.ts +25 -0
  3. package/dist/app/runSimplyBuild.js +287 -0
  4. package/dist/app/runSimplyBuild.js.map +1 -0
  5. package/dist/cli.d.ts +2 -0
  6. package/dist/cli.js +146 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/discovery/projects.d.ts +2 -0
  9. package/dist/discovery/projects.js +51 -0
  10. package/dist/discovery/projects.js.map +1 -0
  11. package/dist/discovery/schemes.d.ts +3 -0
  12. package/dist/discovery/schemes.js +67 -0
  13. package/dist/discovery/schemes.js.map +1 -0
  14. package/dist/discovery/targets.d.ts +6 -0
  15. package/dist/discovery/targets.js +133 -0
  16. package/dist/discovery/targets.js.map +1 -0
  17. package/dist/matching/targetMatcher.d.ts +15 -0
  18. package/dist/matching/targetMatcher.js +104 -0
  19. package/dist/matching/targetMatcher.js.map +1 -0
  20. package/dist/runner/commandRunner.d.ts +2 -0
  21. package/dist/runner/commandRunner.js +41 -0
  22. package/dist/runner/commandRunner.js.map +1 -0
  23. package/dist/runner/pipelines.d.ts +23 -0
  24. package/dist/runner/pipelines.js +159 -0
  25. package/dist/runner/pipelines.js.map +1 -0
  26. package/dist/runner/xcodebuildmcpRunner.d.ts +14 -0
  27. package/dist/runner/xcodebuildmcpRunner.js +53 -0
  28. package/dist/runner/xcodebuildmcpRunner.js.map +1 -0
  29. package/dist/setup/xcodebuildmcpPrereq.d.ts +9 -0
  30. package/dist/setup/xcodebuildmcpPrereq.js +120 -0
  31. package/dist/setup/xcodebuildmcpPrereq.js.map +1 -0
  32. package/dist/state/store.d.ts +14 -0
  33. package/dist/state/store.js +126 -0
  34. package/dist/state/store.js.map +1 -0
  35. package/dist/types.d.ts +73 -0
  36. package/dist/types.js +20 -0
  37. package/dist/types.js.map +1 -0
  38. package/dist/ui/prompts.d.ts +22 -0
  39. package/dist/ui/prompts.js +93 -0
  40. package/dist/ui/prompts.js.map +1 -0
  41. package/package.json +38 -0
@@ -0,0 +1,53 @@
1
+ import { runCommand } from "./commandRunner.js";
2
+ function mergeTextContent(content) {
3
+ if (!Array.isArray(content)) {
4
+ return "";
5
+ }
6
+ const textBlocks = content
7
+ .filter((entry) => {
8
+ return Boolean(entry && typeof entry === "object");
9
+ })
10
+ .filter((entry) => entry.type === "text" && typeof entry.text === "string")
11
+ .map((entry) => entry.text ?? "");
12
+ return textBlocks.join("\n\n").trim();
13
+ }
14
+ export function parseXcodebuildMcpOutput(stdout) {
15
+ try {
16
+ const parsed = JSON.parse(stdout);
17
+ const text = mergeTextContent(parsed.content);
18
+ const isError = parsed.isError === true;
19
+ return {
20
+ text,
21
+ isError,
22
+ json: parsed,
23
+ };
24
+ }
25
+ catch {
26
+ return {
27
+ text: stdout.trim(),
28
+ isError: false,
29
+ json: null,
30
+ };
31
+ }
32
+ }
33
+ function withStandardToolOptions(args) {
34
+ const hasOutput = args.includes("--output");
35
+ const hasStyle = args.includes("--style");
36
+ const merged = [...args];
37
+ if (!hasOutput) {
38
+ merged.push("--output", "json");
39
+ }
40
+ if (!hasStyle) {
41
+ merged.push("--style", "minimal");
42
+ }
43
+ return merged;
44
+ }
45
+ export async function runXcodebuildmcpTool(args, options = {}) {
46
+ const result = await runCommand("xcodebuildmcp", withStandardToolOptions(args), options);
47
+ const response = parseXcodebuildMcpOutput(result.stdout);
48
+ return {
49
+ ...result,
50
+ response,
51
+ };
52
+ }
53
+ //# sourceMappingURL=xcodebuildmcpRunner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xcodebuildmcpRunner.js","sourceRoot":"","sources":["../../src/runner/xcodebuildmcpRunner.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAYhD,SAAS,gBAAgB,CAAC,OAAgB;IACxC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,UAAU,GAAG,OAAO;SACvB,MAAM,CAAC,CAAC,KAAK,EAA6C,EAAE;QAC3D,OAAO,OAAO,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC;IACrD,CAAC,CAAC;SACD,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC;SAC1E,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IAEpC,OAAO,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,MAAc;IACrD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAA4B,CAAC;QAC7D,MAAM,IAAI,GAAG,gBAAgB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC9C,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,KAAK,IAAI,CAAC;QACxC,OAAO;YACL,IAAI;YACJ,OAAO;YACP,IAAI,EAAE,MAAM;SACb,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE;YACnB,OAAO,EAAE,KAAK;YACd,IAAI,EAAE,IAAI;SACX,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,uBAAuB,CAAC,IAAc;IAC7C,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IACzB,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAClC,CAAC;IACD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,IAAc,EACd,UAA+C,EAAE;IAEjD,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,eAAe,EAAE,uBAAuB,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;IACzF,MAAM,QAAQ,GAAG,wBAAwB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAEzD,OAAO;QACL,GAAG,MAAM;QACT,QAAQ;KACT,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { CommandResult } from "../types.js";
2
+ import type { PromptApi } from "../ui/prompts.js";
3
+ interface EnsureXcodebuildmcpReadyDependencies {
4
+ runRaw?: (command: string, args: string[], options: {
5
+ verbose?: boolean;
6
+ }) => Promise<CommandResult>;
7
+ }
8
+ export declare function ensureXcodebuildmcpReady(prompts: PromptApi, verbose: boolean, deps?: EnsureXcodebuildmcpReadyDependencies): Promise<void>;
9
+ export {};
@@ -0,0 +1,120 @@
1
+ import { runCommand } from "../runner/commandRunner.js";
2
+ import { UserFacingError } from "../types.js";
3
+ const REQUIRED_TOOL = "xcodebuildmcp";
4
+ const INSTALL_ARGS = ["install", "-g", REQUIRED_TOOL];
5
+ const INSTALL_COMMAND_TEXT = `npm ${INSTALL_ARGS.join(" ")}`;
6
+ function standardHelpDetails(extra = []) {
7
+ return [
8
+ `Required dependency: ${REQUIRED_TOOL}`,
9
+ `Install it with: ${INSTALL_COMMAND_TEXT}`,
10
+ "Global npm installs may require elevated permissions depending on your npm prefix.",
11
+ ...extra,
12
+ ];
13
+ }
14
+ function formatFailureDetail(failure) {
15
+ if (failure.type === "result") {
16
+ const detail = (failure.result.stderr || failure.result.stdout).trim();
17
+ return detail.length > 0 ? detail : undefined;
18
+ }
19
+ if (failure.error instanceof Error && failure.error.message.trim().length > 0) {
20
+ return failure.error.message.trim();
21
+ }
22
+ return undefined;
23
+ }
24
+ function isMissingBinaryError(error, command) {
25
+ if (!error || typeof error !== "object") {
26
+ return false;
27
+ }
28
+ const errno = error;
29
+ if (errno.code !== "ENOENT") {
30
+ return false;
31
+ }
32
+ if (errno.path === command) {
33
+ return true;
34
+ }
35
+ return typeof errno.message === "string" && errno.message.includes(command);
36
+ }
37
+ async function probeXcodebuildmcp(runRaw) {
38
+ try {
39
+ const result = await runRaw(REQUIRED_TOOL, ["--version"], { verbose: false });
40
+ if (result.ok) {
41
+ return { status: "ready" };
42
+ }
43
+ return {
44
+ status: "failed",
45
+ failure: {
46
+ type: "result",
47
+ result,
48
+ },
49
+ };
50
+ }
51
+ catch (error) {
52
+ if (isMissingBinaryError(error, REQUIRED_TOOL)) {
53
+ return { status: "missing" };
54
+ }
55
+ return {
56
+ status: "failed",
57
+ failure: {
58
+ type: "error",
59
+ error,
60
+ },
61
+ };
62
+ }
63
+ }
64
+ export async function ensureXcodebuildmcpReady(prompts, verbose, deps = {}) {
65
+ const runRaw = deps.runRaw ?? ((command, args, options) => runCommand(command, args, options));
66
+ const initialProbe = await probeXcodebuildmcp(runRaw);
67
+ if (initialProbe.status === "ready") {
68
+ return;
69
+ }
70
+ if (initialProbe.status === "failed") {
71
+ throw new UserFacingError("Failed to verify `xcodebuildmcp` availability.", standardHelpDetails(formatFailureDetail(initialProbe.failure)
72
+ ? [`Probe error: ${formatFailureDetail(initialProbe.failure)}`]
73
+ : []));
74
+ }
75
+ if (!prompts.interactive) {
76
+ throw new UserFacingError("`xcodebuildmcp` is required for simplybuild.", standardHelpDetails([
77
+ "Automatic installation requires an interactive terminal.",
78
+ ]));
79
+ }
80
+ prompts.warn("`xcodebuildmcp` is required for simplybuild.");
81
+ const shouldInstall = await prompts.confirm("Install `xcodebuildmcp` now with `npm install -g xcodebuildmcp`?", true);
82
+ if (!shouldInstall) {
83
+ throw new UserFacingError("`xcodebuildmcp` is required for simplybuild.", standardHelpDetails(["Installation was declined."]));
84
+ }
85
+ const installResult = await prompts.stage("Installing xcodebuildmcp globally", async () => {
86
+ try {
87
+ return await runRaw("npm", INSTALL_ARGS, { verbose });
88
+ }
89
+ catch (error) {
90
+ throw new UserFacingError("Failed to install `xcodebuildmcp` automatically.", standardHelpDetails(formatFailureDetail({ type: "error", error })
91
+ ? [`Install error: ${formatFailureDetail({ type: "error", error })}`]
92
+ : []));
93
+ }
94
+ }, {
95
+ success: "Installed xcodebuildmcp",
96
+ error: "Failed to install xcodebuildmcp",
97
+ });
98
+ if (!installResult.ok) {
99
+ const installFailure = {
100
+ type: "result",
101
+ result: installResult,
102
+ };
103
+ throw new UserFacingError("Failed to install `xcodebuildmcp` automatically.", standardHelpDetails(formatFailureDetail(installFailure)
104
+ ? [`Install error: ${formatFailureDetail(installFailure)}`]
105
+ : []));
106
+ }
107
+ const postInstallProbe = await probeXcodebuildmcp(runRaw);
108
+ if (postInstallProbe.status === "ready") {
109
+ return;
110
+ }
111
+ if (postInstallProbe.status === "missing") {
112
+ throw new UserFacingError("`xcodebuildmcp` was installed but is not available in the current PATH.", standardHelpDetails([
113
+ "Open a new terminal session and verify with `which xcodebuildmcp`.",
114
+ ]));
115
+ }
116
+ throw new UserFacingError("Failed to verify `xcodebuildmcp` after installation.", standardHelpDetails(formatFailureDetail(postInstallProbe.failure)
117
+ ? [`Probe error: ${formatFailureDetail(postInstallProbe.failure)}`]
118
+ : []));
119
+ }
120
+ //# sourceMappingURL=xcodebuildmcpPrereq.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xcodebuildmcpPrereq.js","sourceRoot":"","sources":["../../src/setup/xcodebuildmcpPrereq.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { type ContainerKind, type ProjectMemory, type TargetCandidate } from "../types.js";
2
+ export interface StateStore {
3
+ readonly statePath: string;
4
+ getProjectMemory(projectKey: string): Promise<ProjectMemory | undefined>;
5
+ setProjectContext(projectKey: string, payload: {
6
+ containerPath: string;
7
+ containerKind: ContainerKind;
8
+ scheme: string;
9
+ target: Pick<TargetCandidate, "kind" | "id" | "name">;
10
+ }): Promise<void>;
11
+ markPhysicalDeviceApproved(projectKey: string, deviceId: string): Promise<void>;
12
+ isPhysicalDeviceApproved(projectKey: string, deviceId: string): Promise<boolean>;
13
+ }
14
+ export declare function createStateStore(customStatePath?: string): StateStore;
@@ -0,0 +1,126 @@
1
+ import { promises as fs } from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ function nowIso() {
5
+ return new Date().toISOString();
6
+ }
7
+ function defaultStateDir() {
8
+ const xdgState = process.env.XDG_STATE_HOME;
9
+ if (xdgState && xdgState.trim().length > 0) {
10
+ return path.resolve(xdgState, "simplybuild");
11
+ }
12
+ return path.resolve(os.homedir(), ".local", "state", "simplybuild");
13
+ }
14
+ function createEmptyState() {
15
+ return {
16
+ version: 1,
17
+ projects: {},
18
+ };
19
+ }
20
+ function isProjectMemory(value) {
21
+ if (!value || typeof value !== "object") {
22
+ return false;
23
+ }
24
+ const item = value;
25
+ return (typeof item.updatedAt === "string" &&
26
+ Array.isArray(item.approvedPhysicalDeviceIds) &&
27
+ item.approvedPhysicalDeviceIds.every((id) => typeof id === "string"));
28
+ }
29
+ function isStateFile(value) {
30
+ if (!value || typeof value !== "object") {
31
+ return false;
32
+ }
33
+ const state = value;
34
+ if (state.version !== 1 || !state.projects || typeof state.projects !== "object") {
35
+ return false;
36
+ }
37
+ return Object.values(state.projects).every((entry) => isProjectMemory(entry));
38
+ }
39
+ async function ensureDir(dir) {
40
+ await fs.mkdir(dir, { recursive: true });
41
+ }
42
+ export function createStateStore(customStatePath) {
43
+ const statePath = customStatePath ?? path.join(defaultStateDir(), "state.json");
44
+ let cache = null;
45
+ const load = async () => {
46
+ if (cache) {
47
+ return cache;
48
+ }
49
+ await ensureDir(path.dirname(statePath));
50
+ try {
51
+ const raw = await fs.readFile(statePath, "utf8");
52
+ const parsed = JSON.parse(raw);
53
+ if (isStateFile(parsed)) {
54
+ cache = parsed;
55
+ return cache;
56
+ }
57
+ const backup = `${statePath}.corrupt-${Date.now()}`;
58
+ await fs.rename(statePath, backup).catch(() => undefined);
59
+ cache = createEmptyState();
60
+ return cache;
61
+ }
62
+ catch {
63
+ const backup = `${statePath}.corrupt-${Date.now()}`;
64
+ await fs.rename(statePath, backup).catch(() => undefined);
65
+ cache = createEmptyState();
66
+ return cache;
67
+ }
68
+ };
69
+ const save = async (state) => {
70
+ await ensureDir(path.dirname(statePath));
71
+ const tempPath = `${statePath}.tmp`;
72
+ await fs.writeFile(tempPath, JSON.stringify(state, null, 2), "utf8");
73
+ await fs.rename(tempPath, statePath);
74
+ };
75
+ const getOrCreateProject = (state, projectKey) => {
76
+ const existing = state.projects[projectKey];
77
+ if (existing) {
78
+ return existing;
79
+ }
80
+ const created = {
81
+ approvedPhysicalDeviceIds: [],
82
+ updatedAt: nowIso(),
83
+ };
84
+ state.projects[projectKey] = created;
85
+ return created;
86
+ };
87
+ return {
88
+ statePath,
89
+ async getProjectMemory(projectKey) {
90
+ const state = await load();
91
+ return state.projects[projectKey];
92
+ },
93
+ async setProjectContext(projectKey, payload) {
94
+ const state = await load();
95
+ const project = getOrCreateProject(state, projectKey);
96
+ project.lastSelectedContainerPath = payload.containerPath;
97
+ project.containerKind = payload.containerKind;
98
+ project.lastScheme = payload.scheme;
99
+ project.lastTarget = {
100
+ kind: payload.target.kind,
101
+ id: payload.target.id,
102
+ name: payload.target.name,
103
+ };
104
+ project.updatedAt = nowIso();
105
+ await save(state);
106
+ },
107
+ async markPhysicalDeviceApproved(projectKey, deviceId) {
108
+ const state = await load();
109
+ const project = getOrCreateProject(state, projectKey);
110
+ if (!project.approvedPhysicalDeviceIds.includes(deviceId)) {
111
+ project.approvedPhysicalDeviceIds.push(deviceId);
112
+ }
113
+ project.updatedAt = nowIso();
114
+ await save(state);
115
+ },
116
+ async isPhysicalDeviceApproved(projectKey, deviceId) {
117
+ const state = await load();
118
+ const project = state.projects[projectKey];
119
+ if (!project) {
120
+ return false;
121
+ }
122
+ return project.approvedPhysicalDeviceIds.includes(deviceId);
123
+ },
124
+ };
125
+ }
126
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/state/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ export type ContainerKind = "workspace" | "project";
2
+ export type TargetKind = "physical" | "simulator";
3
+ export interface ProjectCandidate {
4
+ kind: ContainerKind;
5
+ path: string;
6
+ name: string;
7
+ }
8
+ export interface SchemeCandidate {
9
+ name: string;
10
+ isLikelyTestScheme: boolean;
11
+ }
12
+ export interface TargetCandidate {
13
+ kind: TargetKind;
14
+ id: string;
15
+ name: string;
16
+ os: string;
17
+ state: string;
18
+ isBooted?: boolean;
19
+ }
20
+ export interface ResolvedContext {
21
+ container: ProjectCandidate;
22
+ scheme: string;
23
+ target: TargetCandidate;
24
+ source: "interactive" | "query" | "explicit";
25
+ }
26
+ export interface CliOptions {
27
+ query?: string;
28
+ device?: string;
29
+ scheme?: string;
30
+ listDevices: boolean;
31
+ listProjects: boolean;
32
+ verbose: boolean;
33
+ help: boolean;
34
+ }
35
+ export interface CommandResult {
36
+ ok: boolean;
37
+ code: number;
38
+ stdout: string;
39
+ stderr: string;
40
+ }
41
+ export interface CommandRunOptions {
42
+ cwd?: string;
43
+ verbose?: boolean;
44
+ env?: NodeJS.ProcessEnv;
45
+ }
46
+ export interface ProjectMemory {
47
+ lastSelectedContainerPath?: string;
48
+ containerKind?: ContainerKind;
49
+ lastScheme?: string;
50
+ lastTarget?: {
51
+ kind: TargetKind;
52
+ id: string;
53
+ name: string;
54
+ };
55
+ approvedPhysicalDeviceIds: string[];
56
+ updatedAt: string;
57
+ }
58
+ export interface StateFile {
59
+ version: 1;
60
+ projects: Record<string, ProjectMemory>;
61
+ }
62
+ export declare class UserFacingError extends Error {
63
+ readonly details?: string[];
64
+ constructor(message: string, details?: string[]);
65
+ }
66
+ export declare class UserCancelledError extends Error {
67
+ constructor(message?: string);
68
+ }
69
+ export declare const MATCHING_THRESHOLDS: {
70
+ readonly closeMatch: 0.72;
71
+ readonly ambiguityDelta: 0.08;
72
+ readonly physicalPreferenceWindow: 0.03;
73
+ };
package/dist/types.js ADDED
@@ -0,0 +1,20 @@
1
+ export class UserFacingError extends Error {
2
+ details;
3
+ constructor(message, details) {
4
+ super(message);
5
+ this.name = "UserFacingError";
6
+ this.details = details;
7
+ }
8
+ }
9
+ export class UserCancelledError extends Error {
10
+ constructor(message = "Operation cancelled") {
11
+ super(message);
12
+ this.name = "UserCancelledError";
13
+ }
14
+ }
15
+ export const MATCHING_THRESHOLDS = {
16
+ closeMatch: 0.72,
17
+ ambiguityDelta: 0.08,
18
+ physicalPreferenceWindow: 0.03,
19
+ };
20
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAuEA,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACxB,OAAO,CAAY;IAEnC,YAAY,OAAe,EAAE,OAAkB;QAC7C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF;AAED,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,OAAO,GAAG,qBAAqB;QACzC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,UAAU,EAAE,IAAI;IAChB,cAAc,EAAE,IAAI;IACpB,wBAAwB,EAAE,IAAI;CACtB,CAAC"}
@@ -0,0 +1,22 @@
1
+ export interface SelectOption<T> {
2
+ value: T;
3
+ label: string;
4
+ hint?: string;
5
+ disabled?: boolean;
6
+ }
7
+ export interface PromptApi {
8
+ readonly interactive: boolean;
9
+ intro(title: string): void;
10
+ outro(message: string): void;
11
+ info(message: string): void;
12
+ warn(message: string): void;
13
+ step(message: string): void;
14
+ select<T>(message: string, options: SelectOption<T>[], initialValue?: T): Promise<T>;
15
+ confirm(message: string, initialValue?: boolean): Promise<boolean>;
16
+ text(message: string, initialValue?: string): Promise<string>;
17
+ stage<T>(message: string, task: () => Promise<T>, labels?: {
18
+ success?: string;
19
+ error?: string;
20
+ }): Promise<T>;
21
+ }
22
+ export declare function createPromptApi(forceInteractive?: boolean): PromptApi;
@@ -0,0 +1,93 @@
1
+ import * as p from "@clack/prompts";
2
+ import { UserCancelledError, UserFacingError } from "../types.js";
3
+ export function createPromptApi(forceInteractive) {
4
+ const interactive = forceInteractive ?? Boolean(process.stdin.isTTY && process.stdout.isTTY && !p.isCI());
5
+ const assertInteractive = () => {
6
+ if (!interactive) {
7
+ throw new UserFacingError("This step requires an interactive terminal, but no TTY is available.");
8
+ }
9
+ };
10
+ const resolveValue = (value) => {
11
+ if (p.isCancel(value)) {
12
+ p.cancel("Operation cancelled.");
13
+ throw new UserCancelledError();
14
+ }
15
+ return value;
16
+ };
17
+ return {
18
+ interactive,
19
+ intro(title) {
20
+ if (interactive) {
21
+ p.intro(title);
22
+ }
23
+ },
24
+ outro(message) {
25
+ if (interactive) {
26
+ p.outro(message);
27
+ }
28
+ },
29
+ info(message) {
30
+ p.log.info(message);
31
+ },
32
+ warn(message) {
33
+ p.log.warn(message);
34
+ },
35
+ step(message) {
36
+ p.log.step(message);
37
+ },
38
+ async select(message, options, initialValue) {
39
+ assertInteractive();
40
+ const selectOptions = options.map((option) => ({
41
+ value: option.value,
42
+ label: option.label,
43
+ hint: option.hint,
44
+ disabled: option.disabled,
45
+ }));
46
+ const value = await p.select({
47
+ message,
48
+ options: selectOptions,
49
+ initialValue,
50
+ });
51
+ return resolveValue(value);
52
+ },
53
+ async confirm(message, initialValue = true) {
54
+ assertInteractive();
55
+ const value = await p.confirm({
56
+ message,
57
+ initialValue,
58
+ });
59
+ return resolveValue(value);
60
+ },
61
+ async text(message, initialValue = "") {
62
+ assertInteractive();
63
+ const value = await p.text({
64
+ message,
65
+ initialValue,
66
+ validate: (input) => {
67
+ if (!input || input.trim().length === 0) {
68
+ return "Value is required";
69
+ }
70
+ return undefined;
71
+ },
72
+ });
73
+ return resolveValue(value).trim();
74
+ },
75
+ async stage(message, task, labels) {
76
+ if (!interactive) {
77
+ return task();
78
+ }
79
+ const s = p.spinner();
80
+ s.start(message);
81
+ try {
82
+ const result = await task();
83
+ s.stop(labels?.success ?? message);
84
+ return result;
85
+ }
86
+ catch (error) {
87
+ s.error(labels?.error ?? message);
88
+ throw error;
89
+ }
90
+ },
91
+ };
92
+ }
93
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/ui/prompts.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@kainoa/simplybuild",
3
+ "version": "0.1.0",
4
+ "description": "Smart iOS build and deploy CLI wrapper for xcodebuildmcp",
5
+ "type": "module",
6
+ "bin": {
7
+ "simplybuild": "./dist/cli.js",
8
+ "sb": "./dist/cli.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "README.md"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsc -p tsconfig.json",
16
+ "typecheck": "tsc -p tsconfig.json --noEmit",
17
+ "test": "vitest run"
18
+ },
19
+ "keywords": [
20
+ "ios",
21
+ "xcode",
22
+ "xcodebuild",
23
+ "cli",
24
+ "xcodebuildmcp"
25
+ ],
26
+ "license": "MIT",
27
+ "engines": {
28
+ "node": ">=20"
29
+ },
30
+ "dependencies": {
31
+ "@clack/prompts": "^1.0.0"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^22.10.2",
35
+ "typescript": "^5.7.2",
36
+ "vitest": "^3.2.4"
37
+ }
38
+ }