dominion-cli 0.1.2 → 0.2.1

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 (131) hide show
  1. package/dist/cli.js +43 -29
  2. package/dist/cli.js.map +1 -1
  3. package/dist/commands/account.d.ts +1 -1
  4. package/dist/commands/account.d.ts.map +1 -1
  5. package/dist/commands/account.js +6 -9
  6. package/dist/commands/account.js.map +1 -1
  7. package/dist/commands/billing.d.ts +1 -1
  8. package/dist/commands/billing.d.ts.map +1 -1
  9. package/dist/commands/billing.js +3 -7
  10. package/dist/commands/billing.js.map +1 -1
  11. package/dist/commands/buy.d.ts +7 -7
  12. package/dist/commands/buy.d.ts.map +1 -1
  13. package/dist/commands/buy.js +46 -142
  14. package/dist/commands/buy.js.map +1 -1
  15. package/dist/commands/cart/add.d.ts +1 -1
  16. package/dist/commands/cart/add.d.ts.map +1 -1
  17. package/dist/commands/cart/add.js +9 -8
  18. package/dist/commands/cart/add.js.map +1 -1
  19. package/dist/commands/credits.js +1 -1
  20. package/dist/commands/dns/add.d.ts +3 -3
  21. package/dist/commands/dns/add.d.ts.map +1 -1
  22. package/dist/commands/dns/add.js +3 -3
  23. package/dist/commands/dns/add.js.map +1 -1
  24. package/dist/commands/dns/list.d.ts +3 -3
  25. package/dist/commands/dns/list.d.ts.map +1 -1
  26. package/dist/commands/dns/list.js +3 -3
  27. package/dist/commands/dns/list.js.map +1 -1
  28. package/dist/commands/dns/remove.d.ts +3 -3
  29. package/dist/commands/dns/remove.d.ts.map +1 -1
  30. package/dist/commands/dns/remove.js +3 -3
  31. package/dist/commands/dns/remove.js.map +1 -1
  32. package/dist/commands/domains/detail.d.ts +1 -1
  33. package/dist/commands/domains/detail.js +3 -3
  34. package/dist/commands/domains/detail.js.map +1 -1
  35. package/dist/commands/domains/list.d.ts +1 -1
  36. package/dist/commands/domains/list.js +3 -3
  37. package/dist/commands/domains/list.js.map +1 -1
  38. package/dist/commands/login.d.ts +6 -6
  39. package/dist/commands/login.d.ts.map +1 -1
  40. package/dist/commands/login.js +58 -42
  41. package/dist/commands/login.js.map +1 -1
  42. package/dist/commands/logout.d.ts +1 -1
  43. package/dist/commands/logout.js +1 -1
  44. package/dist/commands/search.d.ts +2 -2
  45. package/dist/commands/search.js +4 -4
  46. package/dist/commands/search.js.map +1 -1
  47. package/dist/commands/settings/set.d.ts +4 -4
  48. package/dist/commands/settings/set.d.ts.map +1 -1
  49. package/dist/commands/settings/set.js +10 -11
  50. package/dist/commands/settings/set.js.map +1 -1
  51. package/dist/commands/settings/view.d.ts +3 -3
  52. package/dist/commands/settings/view.d.ts.map +1 -1
  53. package/dist/commands/settings/view.js +4 -4
  54. package/dist/commands/settings/view.js.map +1 -1
  55. package/dist/commands/vercel/link.d.ts +4 -4
  56. package/dist/commands/vercel/link.d.ts.map +1 -1
  57. package/dist/commands/vercel/link.js +8 -8
  58. package/dist/commands/vercel/link.js.map +1 -1
  59. package/dist/commands/whoami.d.ts +1 -1
  60. package/dist/commands/whoami.js +3 -3
  61. package/dist/commands/whoami.js.map +1 -1
  62. package/dist/components/account-card.d.ts +3 -3
  63. package/dist/components/account-card.d.ts.map +1 -1
  64. package/dist/components/account-card.js +3 -3
  65. package/dist/components/account-card.js.map +1 -1
  66. package/dist/components/auth-gate.d.ts +19 -0
  67. package/dist/components/auth-gate.d.ts.map +1 -0
  68. package/dist/components/auth-gate.js +143 -0
  69. package/dist/components/auth-gate.js.map +1 -0
  70. package/dist/components/command-runner.d.ts +25 -0
  71. package/dist/components/command-runner.d.ts.map +1 -0
  72. package/dist/components/command-runner.js +67 -0
  73. package/dist/components/command-runner.js.map +1 -0
  74. package/dist/components/prompt.d.ts +24 -0
  75. package/dist/components/prompt.d.ts.map +1 -0
  76. package/dist/components/prompt.js +113 -0
  77. package/dist/components/prompt.js.map +1 -0
  78. package/dist/components/search-results.d.ts +1 -1
  79. package/dist/components/search-results.js +1 -1
  80. package/dist/components/spinner.d.ts +12 -0
  81. package/dist/components/spinner.d.ts.map +1 -0
  82. package/dist/components/spinner.js +21 -0
  83. package/dist/components/spinner.js.map +1 -0
  84. package/dist/lib/auth-flow.d.ts +41 -0
  85. package/dist/lib/auth-flow.d.ts.map +1 -0
  86. package/dist/lib/auth-flow.js +98 -0
  87. package/dist/lib/auth-flow.js.map +1 -0
  88. package/dist/lib/auth.d.ts +17 -9
  89. package/dist/lib/auth.d.ts.map +1 -1
  90. package/dist/lib/auth.js +125 -46
  91. package/dist/lib/auth.js.map +1 -1
  92. package/dist/lib/command-registry.d.ts +47 -0
  93. package/dist/lib/command-registry.d.ts.map +1 -0
  94. package/dist/lib/command-registry.js +384 -0
  95. package/dist/lib/command-registry.js.map +1 -0
  96. package/dist/lib/config.d.ts.map +1 -1
  97. package/dist/lib/config.js +0 -8
  98. package/dist/lib/config.js.map +1 -1
  99. package/dist/lib/dns-validation.d.ts +1 -1
  100. package/dist/lib/dns-validation.d.ts.map +1 -1
  101. package/dist/lib/dns-validation.js +2 -2
  102. package/dist/lib/dns-validation.js.map +1 -1
  103. package/dist/lib/dominion-client.d.ts +43 -0
  104. package/dist/lib/dominion-client.d.ts.map +1 -0
  105. package/dist/lib/dominion-client.js +189 -0
  106. package/dist/lib/dominion-client.js.map +1 -0
  107. package/dist/lib/error-personality.js +7 -7
  108. package/dist/lib/error-personality.js.map +1 -1
  109. package/dist/lib/history.d.ts +40 -0
  110. package/dist/lib/history.d.ts.map +1 -0
  111. package/dist/lib/history.js +113 -0
  112. package/dist/lib/history.js.map +1 -0
  113. package/dist/lib/nameserver-presets.js +4 -4
  114. package/dist/lib/nameserver-presets.js.map +1 -1
  115. package/dist/lib/purchase.d.ts +20 -23
  116. package/dist/lib/purchase.d.ts.map +1 -1
  117. package/dist/lib/purchase.js +42 -70
  118. package/dist/lib/purchase.js.map +1 -1
  119. package/dist/lib/schemas.d.ts +351 -352
  120. package/dist/lib/schemas.d.ts.map +1 -1
  121. package/dist/lib/schemas.js +1 -2
  122. package/dist/lib/schemas.js.map +1 -1
  123. package/dist/lib/types.d.ts +8 -11
  124. package/dist/lib/types.d.ts.map +1 -1
  125. package/dist/lib/types.js +1 -4
  126. package/dist/lib/types.js.map +1 -1
  127. package/dist/repl.d.ts +17 -0
  128. package/dist/repl.d.ts.map +1 -0
  129. package/dist/repl.js +189 -0
  130. package/dist/repl.js.map +1 -0
  131. package/package.json +2 -1
@@ -0,0 +1,143 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * Auth Gate — Claude Code-style browser-based authentication.
4
+ *
5
+ * State machine:
6
+ * email-prompt → sending → waiting → success → done
7
+ * ↘ error (retry / password / exit)
8
+ *
9
+ * Opens browser for magic link verification. Falls back to
10
+ * password mode in headless environments or on user request.
11
+ */
12
+ import { Box, Text, useApp, useInput } from "ink";
13
+ import { useState, useEffect } from "react";
14
+ import { Spinner } from "./spinner.js";
15
+ import { createCliSession, pollCliSession } from "../lib/auth-flow.js";
16
+ import { saveCredentials, openInBrowser } from "../lib/auth.js";
17
+ import { inkColors } from "../lib/theme.js";
18
+ export function AuthGate({ onComplete, configManager, message }) {
19
+ const { exit } = useApp();
20
+ const [step, setStep] = useState("email-prompt");
21
+ const [email, setEmail] = useState("");
22
+ const [sessionId, setSessionId] = useState("");
23
+ const [errorMessage, setErrorMessage] = useState("");
24
+ const [dots, setDots] = useState("");
25
+ // Animated dots for waiting state
26
+ useEffect(() => {
27
+ if (step !== "waiting")
28
+ return;
29
+ const interval = setInterval(() => {
30
+ setDots((prev) => (prev.length >= 3 ? "" : prev + "."));
31
+ }, 500);
32
+ return () => clearInterval(interval);
33
+ }, [step]);
34
+ // ─── Send magic link ────────────────────────────────────────────────
35
+ useEffect(() => {
36
+ if (step !== "sending")
37
+ return;
38
+ let cancelled = false;
39
+ const send = async () => {
40
+ const result = await createCliSession(email, configManager);
41
+ if (cancelled)
42
+ return;
43
+ if (!result.success || !result.sessionId) {
44
+ setErrorMessage(result.error ?? "Failed to send login link.");
45
+ setStep("error");
46
+ return;
47
+ }
48
+ setSessionId(result.sessionId);
49
+ // Try to open browser
50
+ try {
51
+ await openInBrowser("https://dominion.sh/login");
52
+ }
53
+ catch {
54
+ // Browser didn't open — user will use email link
55
+ }
56
+ setStep("waiting");
57
+ };
58
+ send();
59
+ return () => { cancelled = true; };
60
+ }, [step, email, configManager]);
61
+ // ─── Poll for verification ──────────────────────────────────────────
62
+ useEffect(() => {
63
+ if (step !== "waiting" || !sessionId)
64
+ return;
65
+ let cancelled = false;
66
+ const poll = async () => {
67
+ while (!cancelled) {
68
+ await new Promise((r) => setTimeout(r, 2000));
69
+ if (cancelled)
70
+ break;
71
+ const result = await pollCliSession(sessionId, configManager);
72
+ if (cancelled)
73
+ break;
74
+ if (result.status === "authenticated" && result.token && result.user) {
75
+ saveCredentials(result.user.email, result.token, configManager);
76
+ setStep("success");
77
+ // Brief pause to show success, then continue
78
+ setTimeout(() => {
79
+ if (!cancelled)
80
+ onComplete(result.user.email);
81
+ }, 1500);
82
+ return;
83
+ }
84
+ if (result.status === "expired") {
85
+ setErrorMessage("Login link expired. Please try again.");
86
+ setStep("error");
87
+ return;
88
+ }
89
+ if (result.status === "error") {
90
+ setErrorMessage(result.error ?? "Connection lost.");
91
+ setStep("error");
92
+ return;
93
+ }
94
+ }
95
+ };
96
+ poll();
97
+ return () => { cancelled = true; };
98
+ }, [step, sessionId, configManager, onComplete]);
99
+ // ─── Input handling ─────────────────────────────────────────────────
100
+ useInput((input, key) => {
101
+ if (step === "success" || step === "sending" || step === "waiting") {
102
+ // Ctrl+C during waiting
103
+ if (key.escape) {
104
+ exit();
105
+ }
106
+ return;
107
+ }
108
+ if (step === "error") {
109
+ if (input === "r" || input === "R") {
110
+ setErrorMessage("");
111
+ setStep("email-prompt");
112
+ }
113
+ else if (key.escape) {
114
+ exit();
115
+ }
116
+ return;
117
+ }
118
+ // Email prompt
119
+ if (step === "email-prompt") {
120
+ if (key.return && email.trim()) {
121
+ setStep("sending");
122
+ return;
123
+ }
124
+ if (key.backspace || key.delete) {
125
+ setEmail((prev) => prev.slice(0, -1));
126
+ return;
127
+ }
128
+ if (key.ctrl || key.meta || key.escape) {
129
+ if (key.escape)
130
+ exit();
131
+ return;
132
+ }
133
+ if (key.upArrow || key.downArrow || key.leftArrow || key.rightArrow || key.tab)
134
+ return;
135
+ if (input) {
136
+ setEmail((prev) => prev + input);
137
+ }
138
+ }
139
+ });
140
+ // ─── Render ─────────────────────────────────────────────────────────
141
+ return (_jsxs(Box, { flexDirection: "column", gap: 1, children: [message && (_jsx(Text, { color: inkColors.muted, children: message })), step === "email-prompt" && (_jsxs(Box, { flexDirection: "column", gap: 1, children: [_jsx(Text, { bold: true, color: inkColors.primary, children: "Enter your email to get started" }), _jsxs(Box, { children: [_jsx(Text, { color: "green", children: "> " }), _jsx(Text, { bold: true, children: "Email: " }), _jsx(Text, { color: "white", children: email }), _jsx(Text, { color: inkColors.primary, children: "│" })] }), _jsxs(Text, { color: inkColors.muted, children: [" ", "We'll send a login link to your inbox."] })] })), step === "sending" && (_jsx(Box, { children: _jsx(Spinner, { label: `Sending login link to ${email}...` }) })), step === "waiting" && (_jsxs(Box, { flexDirection: "column", gap: 1, children: [_jsx(Box, { children: _jsx(Spinner, { label: `Waiting for verification${dots}` }) }), _jsxs(Text, { color: inkColors.muted, children: [" ", "Check your email and click the login link."] }), _jsxs(Text, { color: inkColors.muted, children: [" ", "Press ", _jsx(Text, { bold: true, color: inkColors.white, children: "Esc" }), " to cancel."] })] })), step === "success" && (_jsxs(Box, { flexDirection: "column", gap: 1, children: [_jsxs(Text, { color: inkColors.success, bold: true, children: ["✓ ", "Authenticated!"] }), _jsxs(Text, { color: inkColors.muted, children: [" ", "Welcome to Dominion. Credentials saved."] })] })), step === "error" && (_jsxs(Box, { flexDirection: "column", gap: 1, children: [_jsxs(Text, { color: inkColors.error, bold: true, children: ["✗ ", errorMessage] }), _jsxs(Text, { color: inkColors.muted, children: [" ", "Press ", _jsx(Text, { bold: true, color: inkColors.white, children: "R" }), " to retry, ", _jsx(Text, { bold: true, color: inkColors.white, children: "Esc" }), " to exit."] })] }))] }));
142
+ }
143
+ //# sourceMappingURL=auth-gate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-gate.js","sourceRoot":"","sources":["../../src/components/auth-gate.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * CommandRunner — wraps command components for REPL mode.
3
+ *
4
+ * Intercepts useApp().exit() calls from child components so they
5
+ * signal "command done" instead of killing the entire Ink app.
6
+ * Also provides error boundary and timeout protection.
7
+ */
8
+ import { type ReactElement } from "react";
9
+ interface CommandRunnerProps {
10
+ /** The command element to render. */
11
+ element: ReactElement;
12
+ /** Called when the command finishes (either via exit() or error). */
13
+ onComplete: () => void;
14
+ /** Timeout in ms before force-completing. Default: 60000 (60s). */
15
+ timeout?: number;
16
+ }
17
+ /**
18
+ * Renders a command component with exit() interception.
19
+ *
20
+ * Shadows Ink's AppContext to replace the real exit() with a
21
+ * callback that signals the REPL to return to the prompt.
22
+ */
23
+ export declare function CommandRunner({ element, onComplete, timeout }: CommandRunnerProps): import("react/jsx-runtime").JSX.Element;
24
+ export {};
25
+ //# sourceMappingURL=command-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-runner.d.ts","sourceRoot":"","sources":["../../src/components/command-runner.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,KAAK,YAAY,EAA6B,MAAM,OAAO,CAAC;AAKrE,UAAU,kBAAkB;IAC1B,qCAAqC;IACrC,OAAO,EAAE,YAAY,CAAC;IACtB,qEAAqE;IACrE,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAmCD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,OAAe,EAAE,EAAE,kBAAkB,2CAmCzF"}
@@ -0,0 +1,67 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * CommandRunner — wraps command components for REPL mode.
4
+ *
5
+ * Intercepts useApp().exit() calls from child components so they
6
+ * signal "command done" instead of killing the entire Ink app.
7
+ * Also provides error boundary and timeout protection.
8
+ */
9
+ import { Component } from "react";
10
+ import { useApp, Box, Text } from "ink";
11
+ import AppContext from "ink/build/components/AppContext.js";
12
+ import { inkColors } from "../lib/theme.js";
13
+ /**
14
+ * Error boundary that catches render errors from command components.
15
+ */
16
+ class CommandErrorBoundary extends Component {
17
+ constructor(props) {
18
+ super(props);
19
+ this.state = { error: null };
20
+ }
21
+ static getDerivedStateFromError(error) {
22
+ return { error };
23
+ }
24
+ componentDidCatch(error) {
25
+ this.props.onError(error);
26
+ }
27
+ render() {
28
+ if (this.state.error) {
29
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "red", bold: true, children: "Command error:" }), _jsx(Text, { color: inkColors.muted, children: this.state.error.message })] }));
30
+ }
31
+ return this.props.children;
32
+ }
33
+ }
34
+ /**
35
+ * Renders a command component with exit() interception.
36
+ *
37
+ * Shadows Ink's AppContext to replace the real exit() with a
38
+ * callback that signals the REPL to return to the prompt.
39
+ */
40
+ export function CommandRunner({ element, onComplete, timeout = 60000 }) {
41
+ const realApp = useApp();
42
+ // Create a fake app context that intercepts exit()
43
+ const fakeApp = {
44
+ ...realApp,
45
+ exit: (_error) => {
46
+ onComplete();
47
+ },
48
+ };
49
+ // Set up timeout protection
50
+ const timeoutRef = { current: null };
51
+ if (timeout > 0) {
52
+ // Clear previous timeout on re-render
53
+ if (timeoutRef.current)
54
+ clearTimeout(timeoutRef.current);
55
+ timeoutRef.current = setTimeout(() => {
56
+ onComplete();
57
+ }, timeout);
58
+ }
59
+ const handleError = (_error) => {
60
+ if (timeoutRef.current)
61
+ clearTimeout(timeoutRef.current);
62
+ // Error boundary renders the error message, then we complete after a delay
63
+ setTimeout(() => onComplete(), 2000);
64
+ };
65
+ return (_jsx(AppContext.Provider, { value: fakeApp, children: _jsx(CommandErrorBoundary, { onError: handleError, children: element }) }));
66
+ }
67
+ //# sourceMappingURL=command-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-runner.js","sourceRoot":"","sources":["../../src/components/command-runner.tsx"],"names":[],"mappings":";AAAA;;;;;;GAMG;AAEH,OAAO,EAAqB,SAAS,EAAkB,MAAM,OAAO,CAAC;AACrE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AACxC,OAAO,UAAU,MAAM,oCAAoC,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAW5C;;GAEG;AACH,MAAM,oBAAqB,SAAQ,SAGlC;IACC,YAAY,KAA+D;QACzE,KAAK,CAAC,KAAK,CAAC,CAAC;QACb,IAAI,CAAC,KAAK,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAC/B,CAAC;IAED,MAAM,CAAC,wBAAwB,CAAC,KAAY;QAC1C,OAAO,EAAE,KAAK,EAAE,CAAC;IACnB,CAAC;IAED,iBAAiB,CAAC,KAAY;QAC5B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED,MAAM;QACJ,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACrB,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,aACzB,KAAC,IAAI,IAAC,KAAK,EAAC,KAAK,EAAC,IAAI,qCAAsB,EAC5C,KAAC,IAAI,IAAC,KAAK,EAAE,SAAS,CAAC,KAAK,YAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,GAAQ,IAC3D,CACP,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;IAC7B,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,GAAG,KAAK,EAAsB;IACxF,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC;IAEzB,mDAAmD;IACnD,MAAM,OAAO,GAAG;QACd,GAAG,OAAO;QACV,IAAI,EAAE,CAAC,MAAc,EAAE,EAAE;YACvB,UAAU,EAAE,CAAC;QACf,CAAC;KACF,CAAC;IAEF,4BAA4B;IAC5B,MAAM,UAAU,GAAG,EAAE,OAAO,EAAE,IAA4C,EAAE,CAAC;IAE7E,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAChB,sCAAsC;QACtC,IAAI,UAAU,CAAC,OAAO;YAAE,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QACzD,UAAU,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YACnC,UAAU,EAAE,CAAC;QACf,CAAC,EAAE,OAAO,CAAC,CAAC;IACd,CAAC;IAED,MAAM,WAAW,GAAG,CAAC,MAAa,EAAE,EAAE;QACpC,IAAI,UAAU,CAAC,OAAO;YAAE,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QACzD,2EAA2E;QAC3E,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,EAAE,EAAE,IAAI,CAAC,CAAC;IACvC,CAAC,CAAC;IAEF,OAAO,CACL,KAAC,UAAU,CAAC,QAAQ,IAAC,KAAK,EAAE,OAAO,YACjC,KAAC,oBAAoB,IAAC,OAAO,EAAE,WAAW,YACvC,OAAO,GACa,GACH,CACvB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Prompt — interactive input prompt for REPL mode.
3
+ *
4
+ * Renders "dominion> " and captures user input character by character
5
+ * using Ink's useInput hook. Supports history navigation and tab completion.
6
+ */
7
+ export interface PromptProps {
8
+ /** Called when user presses Enter with input text. */
9
+ onSubmit: (input: string) => void;
10
+ /** Disable input (during command execution). */
11
+ disabled?: boolean;
12
+ /** Prompt prefix (e.g., "corey@dominion"). */
13
+ prefix?: string;
14
+ /** Navigate history up. Returns previous entry or null. */
15
+ onHistoryUp?: () => string | null;
16
+ /** Navigate history down. Returns next entry or null. */
17
+ onHistoryDown?: () => string | null;
18
+ /** Tab completion handler. Returns completed text or null. */
19
+ onTab?: (partial: string) => string | null;
20
+ /** Completion candidates to display (shown below prompt). */
21
+ completionCandidates?: string[];
22
+ }
23
+ export declare function Prompt({ onSubmit, disabled, prefix, onHistoryUp, onHistoryDown, onTab, completionCandidates, }: PromptProps): import("react/jsx-runtime").JSX.Element | null;
24
+ //# sourceMappingURL=prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/components/prompt.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,MAAM,WAAW,WAAW;IAC1B,sDAAsD;IACtD,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,gDAAgD;IAChD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IAClC,yDAAyD;IACzD,aAAa,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IACpC,8DAA8D;IAC9D,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC3C,6DAA6D;IAC7D,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAED,wBAAgB,MAAM,CAAC,EACrB,QAAQ,EACR,QAAgB,EAChB,MAAmB,EACnB,WAAW,EACX,aAAa,EACb,KAAK,EACL,oBAAoB,GACrB,EAAE,WAAW,kDAuIb"}
@@ -0,0 +1,113 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * Prompt — interactive input prompt for REPL mode.
4
+ *
5
+ * Renders "dominion> " and captures user input character by character
6
+ * using Ink's useInput hook. Supports history navigation and tab completion.
7
+ */
8
+ import { Box, Text, useInput } from "ink";
9
+ import { useState, useCallback } from "react";
10
+ import { inkColors } from "../lib/theme.js";
11
+ export function Prompt({ onSubmit, disabled = false, prefix = "dominion", onHistoryUp, onHistoryDown, onTab, completionCandidates, }) {
12
+ const [input, setInput] = useState("");
13
+ const [savedInput, setSavedInput] = useState(null);
14
+ const [cursorOffset, setCursorOffset] = useState(0);
15
+ const cursorPos = input.length - cursorOffset;
16
+ const handleSubmit = useCallback(() => {
17
+ const trimmed = input.trim();
18
+ setInput("");
19
+ setCursorOffset(0);
20
+ setSavedInput(null);
21
+ if (trimmed) {
22
+ onSubmit(trimmed);
23
+ }
24
+ }, [input, onSubmit]);
25
+ useInput((ch, key) => {
26
+ if (disabled)
27
+ return;
28
+ // Enter — submit
29
+ if (key.return) {
30
+ handleSubmit();
31
+ return;
32
+ }
33
+ // Escape — clear line
34
+ if (key.escape) {
35
+ setInput("");
36
+ setCursorOffset(0);
37
+ setSavedInput(null);
38
+ return;
39
+ }
40
+ // Backspace
41
+ if (key.backspace || key.delete) {
42
+ if (cursorPos > 0) {
43
+ setInput((prev) => prev.slice(0, cursorPos - 1) + prev.slice(cursorPos));
44
+ if (cursorOffset > 0) {
45
+ // Keep cursor offset the same — cursor stays in place
46
+ }
47
+ else {
48
+ // Cursor at end, just remove last char
49
+ }
50
+ }
51
+ return;
52
+ }
53
+ // Up arrow — history
54
+ if (key.upArrow && onHistoryUp) {
55
+ if (savedInput === null) {
56
+ setSavedInput(input);
57
+ }
58
+ const prev = onHistoryUp();
59
+ if (prev !== null) {
60
+ setInput(prev);
61
+ setCursorOffset(0);
62
+ }
63
+ return;
64
+ }
65
+ // Down arrow — history
66
+ if (key.downArrow && onHistoryDown) {
67
+ const next = onHistoryDown();
68
+ if (next !== null) {
69
+ setInput(next);
70
+ setCursorOffset(0);
71
+ }
72
+ else if (savedInput !== null) {
73
+ setInput(savedInput);
74
+ setSavedInput(null);
75
+ setCursorOffset(0);
76
+ }
77
+ return;
78
+ }
79
+ // Left arrow
80
+ if (key.leftArrow) {
81
+ setCursorOffset((prev) => Math.min(prev + 1, input.length));
82
+ return;
83
+ }
84
+ // Right arrow
85
+ if (key.rightArrow) {
86
+ setCursorOffset((prev) => Math.max(prev - 1, 0));
87
+ return;
88
+ }
89
+ // Tab — completion
90
+ if (key.tab && onTab) {
91
+ const completed = onTab(input);
92
+ if (completed !== null) {
93
+ setInput(completed);
94
+ setCursorOffset(0);
95
+ }
96
+ return;
97
+ }
98
+ // Regular character input
99
+ if (ch && !key.ctrl && !key.meta) {
100
+ setInput((prev) => prev.slice(0, cursorPos) + ch + prev.slice(cursorPos));
101
+ return;
102
+ }
103
+ }, { isActive: !disabled });
104
+ if (disabled) {
105
+ return null;
106
+ }
107
+ // Render input with cursor
108
+ const before = input.slice(0, cursorPos);
109
+ const cursorChar = input[cursorPos] ?? " ";
110
+ const after = input.slice(cursorPos + 1);
111
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { color: inkColors.primary, bold: true, children: prefix }), _jsx(Text, { color: inkColors.muted, children: "> " }), _jsx(Text, { children: before }), _jsx(Text, { inverse: true, children: cursorChar }), _jsx(Text, { children: after })] }), completionCandidates && completionCandidates.length > 0 && (_jsx(Box, { paddingLeft: prefix.length + 2, children: _jsx(Text, { color: inkColors.muted, children: completionCandidates.join(" ") }) }))] }));
112
+ }
113
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/components/prompt.tsx"],"names":[],"mappings":"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"}
@@ -13,7 +13,7 @@ export interface SearchResultsProps {
13
13
  }
14
14
  /**
15
15
  * Format price from cents to dollars.
16
- * Name.com API returns prices in cents (e.g. 1299 = $12.99).
16
+ * Prices are in cents (e.g. 1299 = $12.99).
17
17
  */
18
18
  export declare function formatPrice(cents: number): string;
19
19
  /**
@@ -9,7 +9,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
9
  import { Box, Text } from "ink";
10
10
  /**
11
11
  * Format price from cents to dollars.
12
- * Name.com API returns prices in cents (e.g. 1299 = $12.99).
12
+ * Prices are in cents (e.g. 1299 = $12.99).
13
13
  */
14
14
  export function formatPrice(cents) {
15
15
  return `$${(cents / 100).toFixed(2)}`;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Animated braille spinner component for Ink.
3
+ *
4
+ * Used during polling states (auth waiting, loading, etc.)
5
+ */
6
+ interface SpinnerProps {
7
+ label?: string;
8
+ color?: string;
9
+ }
10
+ export declare function Spinner({ label, color }: SpinnerProps): import("react/jsx-runtime").JSX.Element;
11
+ export {};
12
+ //# sourceMappingURL=spinner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../src/components/spinner.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,UAAU,YAAY;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,YAAY,2CAgBrD"}
@@ -0,0 +1,21 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * Animated braille spinner component for Ink.
4
+ *
5
+ * Used during polling states (auth waiting, loading, etc.)
6
+ */
7
+ import { Text } from "ink";
8
+ import { useState, useEffect } from "react";
9
+ import { inkColors } from "../lib/theme.js";
10
+ const FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
11
+ export function Spinner({ label, color }) {
12
+ const [frame, setFrame] = useState(0);
13
+ useEffect(() => {
14
+ const interval = setInterval(() => {
15
+ setFrame((prev) => (prev + 1) % FRAMES.length);
16
+ }, 80);
17
+ return () => clearInterval(interval);
18
+ }, []);
19
+ return (_jsxs(Text, { children: [_jsxs(Text, { color: color ?? inkColors.primary, children: [FRAMES[frame], " "] }), label && _jsx(Text, { color: inkColors.muted, children: label })] }));
20
+ }
21
+ //# sourceMappingURL=spinner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../src/components/spinner.tsx"],"names":[],"mappings":";AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAC3B,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAOlE,MAAM,UAAU,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,EAAgB;IACpD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAEtC,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE;YAChC,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QACjD,CAAC,EAAE,EAAE,CAAC,CAAC;QACP,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,CACL,MAAC,IAAI,eACH,MAAC,IAAI,IAAC,KAAK,EAAE,KAAK,IAAI,SAAS,CAAC,OAAO,aAAG,MAAM,CAAC,KAAK,CAAC,SAAS,EAC/D,KAAK,IAAI,KAAC,IAAI,IAAC,KAAK,EAAE,SAAS,CAAC,KAAK,YAAG,KAAK,GAAQ,IACjD,CACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * CLI-side auth flow orchestration for browser-based login.
3
+ *
4
+ * Pattern (same as Claude Code, gh auth login, Vercel CLI):
5
+ * 1. CLI creates pending session on server
6
+ * 2. Server sends magic link email
7
+ * 3. CLI polls until user verifies in browser
8
+ * 4. CLI gets JWT token and saves credentials
9
+ */
10
+ import { ConfigManager } from "./config.js";
11
+ export interface CliSessionResult {
12
+ success: boolean;
13
+ sessionId?: string;
14
+ expiresAt?: string;
15
+ error?: string;
16
+ }
17
+ /**
18
+ * Create a CLI auth session on the server.
19
+ * This triggers a magic link email to the user.
20
+ */
21
+ export declare function createCliSession(email: string, configManager?: ConfigManager): Promise<CliSessionResult>;
22
+ export interface PollResult {
23
+ status: "pending" | "authenticated" | "expired" | "error";
24
+ token?: string;
25
+ user?: {
26
+ id: string;
27
+ email: string;
28
+ };
29
+ error?: string;
30
+ }
31
+ /**
32
+ * Poll a CLI session for completion.
33
+ * Returns the current status.
34
+ */
35
+ export declare function pollCliSession(sessionId: string, configManager?: ConfigManager): Promise<PollResult>;
36
+ /**
37
+ * Detect if running in a headless environment where browser auth won't work.
38
+ * Falls back to password-based auth in these cases.
39
+ */
40
+ export declare function isHeadless(): boolean;
41
+ //# sourceMappingURL=auth-flow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-flow.d.ts","sourceRoot":"","sources":["../../src/lib/auth-flow.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAY5C,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,MAAM,EACb,aAAa,CAAC,EAAE,aAAa,GAC5B,OAAO,CAAC,gBAAgB,CAAC,CA6B3B;AAID,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,SAAS,GAAG,eAAe,GAAG,SAAS,GAAG,OAAO,CAAC;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,aAAa,CAAC,EAAE,aAAa,GAC5B,OAAO,CAAC,UAAU,CAAC,CA2BrB;AAID;;;GAGG;AACH,wBAAgB,UAAU,IAAI,OAAO,CAcpC"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * CLI-side auth flow orchestration for browser-based login.
3
+ *
4
+ * Pattern (same as Claude Code, gh auth login, Vercel CLI):
5
+ * 1. CLI creates pending session on server
6
+ * 2. Server sends magic link email
7
+ * 3. CLI polls until user verifies in browser
8
+ * 4. CLI gets JWT token and saves credentials
9
+ */
10
+ import { ConfigManager } from "./config.js";
11
+ const DEFAULT_API_URL = "https://dominion.sh/api";
12
+ function getApiUrl(configManager) {
13
+ const manager = configManager ?? new ConfigManager();
14
+ const config = manager.load();
15
+ return config.apiBaseUrl ?? process.env.DOMINION_API_URL ?? DEFAULT_API_URL;
16
+ }
17
+ /**
18
+ * Create a CLI auth session on the server.
19
+ * This triggers a magic link email to the user.
20
+ */
21
+ export async function createCliSession(email, configManager) {
22
+ const apiUrl = getApiUrl(configManager);
23
+ try {
24
+ const response = await fetch(`${apiUrl}/auth/cli-session`, {
25
+ method: "POST",
26
+ headers: { "Content-Type": "application/json" },
27
+ body: JSON.stringify({ email }),
28
+ });
29
+ const data = (await response.json());
30
+ if (!response.ok) {
31
+ return {
32
+ success: false,
33
+ error: data.error ?? "Failed to create session",
34
+ };
35
+ }
36
+ return {
37
+ success: true,
38
+ sessionId: data.sessionId,
39
+ expiresAt: data.expiresAt,
40
+ };
41
+ }
42
+ catch (err) {
43
+ return {
44
+ success: false,
45
+ error: `Connection failed: ${err.message}`,
46
+ };
47
+ }
48
+ }
49
+ /**
50
+ * Poll a CLI session for completion.
51
+ * Returns the current status.
52
+ */
53
+ export async function pollCliSession(sessionId, configManager) {
54
+ const apiUrl = getApiUrl(configManager);
55
+ try {
56
+ const response = await fetch(`${apiUrl}/auth/cli-session/${sessionId}`);
57
+ const data = (await response.json());
58
+ const status = data.status;
59
+ if (status === "authenticated") {
60
+ return {
61
+ status: "authenticated",
62
+ token: data.token,
63
+ user: data.user,
64
+ };
65
+ }
66
+ if (status === "expired") {
67
+ return { status: "expired" };
68
+ }
69
+ return { status: "pending" };
70
+ }
71
+ catch (err) {
72
+ return {
73
+ status: "error",
74
+ error: `Connection failed: ${err.message}`,
75
+ };
76
+ }
77
+ }
78
+ // ─── Environment Detection ───────────────────────────────────────────────────
79
+ /**
80
+ * Detect if running in a headless environment where browser auth won't work.
81
+ * Falls back to password-based auth in these cases.
82
+ */
83
+ export function isHeadless() {
84
+ // SSH session
85
+ if (process.env.SSH_TTY || process.env.SSH_CLIENT || process.env.SSH_CONNECTION) {
86
+ return true;
87
+ }
88
+ // CI environments
89
+ if (process.env.CI || process.env.CODESPACES || process.env.GITHUB_ACTIONS) {
90
+ return true;
91
+ }
92
+ // Linux without display server
93
+ if (process.platform === "linux" && !process.env.DISPLAY && !process.env.WAYLAND_DISPLAY) {
94
+ return true;
95
+ }
96
+ return false;
97
+ }
98
+ //# sourceMappingURL=auth-flow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-flow.js","sourceRoot":"","sources":["../../src/lib/auth-flow.ts"],"names":[],"mappings":"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"}