@_davideast/stitch-mcp 0.3.2 → 0.5.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 (214) hide show
  1. package/README.md +54 -239
  2. package/dist/chunk-25wakzyb.js +137 -0
  3. package/dist/chunk-25wakzyb.js.map +10 -0
  4. package/dist/chunk-2cetsfw4.js +16531 -0
  5. package/dist/chunk-2cetsfw4.js.map +95 -0
  6. package/dist/chunk-2fcdwvrm.js +54 -0
  7. package/dist/chunk-2fcdwvrm.js.map +10 -0
  8. package/dist/chunk-2k7n0w2x.js +3980 -0
  9. package/dist/chunk-2k7n0w2x.js.map +16 -0
  10. package/dist/chunk-2kyqsrg2.js +403 -0
  11. package/dist/chunk-2kyqsrg2.js.map +10 -0
  12. package/dist/chunk-384jmtpy.js +11057 -0
  13. package/dist/chunk-384jmtpy.js.map +238 -0
  14. package/dist/chunk-3at4pjgn.js +22 -0
  15. package/dist/chunk-3at4pjgn.js.map +9 -0
  16. package/dist/chunk-3sfn889r.js +492 -0
  17. package/dist/chunk-3sfn889r.js.map +13 -0
  18. package/dist/chunk-45wx7tn7.js +94 -0
  19. package/dist/chunk-45wx7tn7.js.map +10 -0
  20. package/dist/chunk-48d17n29.js +10 -0
  21. package/dist/chunk-48d17n29.js.map +9 -0
  22. package/dist/chunk-4jwmvjb4.js +839 -0
  23. package/dist/chunk-4jwmvjb4.js.map +11 -0
  24. package/dist/chunk-4jygt4d6.js +14 -0
  25. package/dist/chunk-4jygt4d6.js.map +10 -0
  26. package/dist/chunk-4vxy1qce.js +68 -0
  27. package/dist/chunk-4vxy1qce.js.map +10 -0
  28. package/dist/chunk-7tx0wn04.js +11 -0
  29. package/dist/chunk-7tx0wn04.js.map +9 -0
  30. package/dist/chunk-7xh1y383.js +45188 -0
  31. package/dist/chunk-7xh1y383.js.map +258 -0
  32. package/dist/chunk-8yrtq2qs.js +18 -0
  33. package/dist/chunk-8yrtq2qs.js.map +9 -0
  34. package/dist/chunk-985f11w6.js +21 -0
  35. package/dist/chunk-985f11w6.js.map +9 -0
  36. package/dist/chunk-9tvppjaf.js +250 -0
  37. package/dist/chunk-9tvppjaf.js.map +14 -0
  38. package/dist/chunk-9wyra8hs.js +32 -0
  39. package/dist/chunk-9wyra8hs.js.map +9 -0
  40. package/dist/chunk-cwkb2wbe.js +733 -0
  41. package/dist/chunk-cwkb2wbe.js.map +16 -0
  42. package/dist/chunk-djhzzcgj.js +362 -0
  43. package/dist/chunk-djhzzcgj.js.map +13 -0
  44. package/dist/chunk-edp6faw2.js +7 -0
  45. package/dist/chunk-edp6faw2.js.map +9 -0
  46. package/dist/chunk-ezmw2j8c.js +14 -0
  47. package/dist/chunk-ezmw2j8c.js.map +9 -0
  48. package/dist/chunk-f2hq6bfv.js +22 -0
  49. package/dist/chunk-f2hq6bfv.js.map +10 -0
  50. package/dist/chunk-fwb4fnkp.js +31 -0
  51. package/dist/chunk-fwb4fnkp.js.map +10 -0
  52. package/dist/chunk-h18jrqed.js +9517 -0
  53. package/dist/chunk-h18jrqed.js.map +99 -0
  54. package/dist/chunk-hb3c6f6a.js +42 -0
  55. package/dist/chunk-hb3c6f6a.js.map +9 -0
  56. package/dist/chunk-jy2d17pr.js +252 -0
  57. package/dist/chunk-jy2d17pr.js.map +11 -0
  58. package/dist/chunk-kbtqrkwh.js +24 -0
  59. package/dist/chunk-kbtqrkwh.js.map +10 -0
  60. package/dist/chunk-knbnsf6s.js +92 -0
  61. package/dist/chunk-knbnsf6s.js.map +10 -0
  62. package/dist/chunk-mv9ssgmx.js +446 -0
  63. package/dist/chunk-mv9ssgmx.js.map +17 -0
  64. package/dist/chunk-nq68kghz.js +1647 -0
  65. package/dist/chunk-nq68kghz.js.map +10 -0
  66. package/dist/chunk-nthabjd9.js +3138 -0
  67. package/dist/chunk-nthabjd9.js.map +34 -0
  68. package/dist/chunk-nxpzt33t.js +278 -0
  69. package/dist/chunk-nxpzt33t.js.map +10 -0
  70. package/dist/chunk-pfyjtfex.js +172 -0
  71. package/dist/chunk-pfyjtfex.js.map +10 -0
  72. package/dist/chunk-q1nd6g0y.js +392 -0
  73. package/dist/chunk-q1nd6g0y.js.map +20 -0
  74. package/dist/chunk-q4js8r0z.js +4708 -0
  75. package/dist/chunk-q4js8r0z.js.map +29 -0
  76. package/dist/chunk-qv44tmn6.js +289 -0
  77. package/dist/chunk-qv44tmn6.js.map +13 -0
  78. package/dist/chunk-r2sg2nxa.js +20 -0
  79. package/dist/chunk-r2sg2nxa.js.map +9 -0
  80. package/dist/chunk-rp8wjzht.js +16959 -0
  81. package/dist/chunk-rp8wjzht.js.map +26 -0
  82. package/dist/chunk-rpxnm86e.js +372 -0
  83. package/dist/chunk-rpxnm86e.js.map +17 -0
  84. package/dist/chunk-sdp429xd.js +914 -0
  85. package/dist/chunk-sdp429xd.js.map +24 -0
  86. package/dist/chunk-t85nbjjb.js +113 -0
  87. package/dist/chunk-t85nbjjb.js.map +10 -0
  88. package/dist/chunk-tz7wnw4s.js +211 -0
  89. package/dist/chunk-tz7wnw4s.js.map +11 -0
  90. package/dist/chunk-v7117ywx.js +1477 -0
  91. package/dist/chunk-v7117ywx.js.map +23 -0
  92. package/dist/chunk-w8q7nsm7.js +2098 -0
  93. package/dist/chunk-w8q7nsm7.js.map +44 -0
  94. package/dist/chunk-wa64nz8b.js +47 -0
  95. package/dist/chunk-wa64nz8b.js.map +10 -0
  96. package/dist/chunk-wz8d5vzb.js +234 -0
  97. package/dist/chunk-wz8d5vzb.js.map +11 -0
  98. package/dist/chunk-ycfxp056.js +677 -0
  99. package/dist/chunk-ycfxp056.js.map +17 -0
  100. package/dist/chunk-z9d2xc83.js +3256 -0
  101. package/dist/chunk-z9d2xc83.js.map +84 -0
  102. package/dist/cli.js +111 -125552
  103. package/dist/cli.js.map +19 -0
  104. package/dist/commands/autoload.d.ts +2 -0
  105. package/dist/commands/doctor/command.d.ts +2 -1
  106. package/dist/commands/doctor/command.js +82 -0
  107. package/dist/commands/doctor/command.js.map +11 -0
  108. package/dist/commands/doctor/spec.d.ts +16 -8
  109. package/dist/commands/init/command.d.ts +2 -1
  110. package/dist/commands/init/command.js +98 -0
  111. package/dist/commands/init/command.js.map +11 -0
  112. package/dist/commands/init/spec.d.ts +29 -9
  113. package/dist/commands/logout/command.d.ts +2 -1
  114. package/dist/commands/logout/command.js +79 -0
  115. package/dist/commands/logout/command.js.map +11 -0
  116. package/dist/commands/logout/spec.d.ts +11 -0
  117. package/dist/commands/proxy/command.d.ts +2 -1
  118. package/dist/commands/proxy/command.js +56 -0
  119. package/dist/commands/proxy/command.js.map +11 -0
  120. package/dist/commands/proxy/spec.d.ts +15 -0
  121. package/dist/commands/screens/command.d.ts +2 -1
  122. package/dist/commands/screens/command.js +61 -0
  123. package/dist/commands/screens/command.js.map +11 -0
  124. package/dist/commands/screens/spec.d.ts +9 -0
  125. package/dist/commands/serve/command.d.ts +2 -1
  126. package/dist/commands/serve/command.js +65 -0
  127. package/dist/commands/serve/command.js.map +11 -0
  128. package/dist/commands/serve/spec.d.ts +9 -0
  129. package/dist/commands/site/command.d.ts +2 -1
  130. package/dist/commands/site/command.js +53 -0
  131. package/dist/commands/site/command.js.map +11 -0
  132. package/dist/commands/site/spec.d.ts +15 -0
  133. package/dist/commands/snapshot/command.d.ts +2 -1
  134. package/dist/commands/snapshot/command.js +59 -0
  135. package/dist/commands/snapshot/command.js.map +11 -0
  136. package/dist/commands/tool/command.d.ts +2 -1
  137. package/dist/commands/tool/command.js +79 -0
  138. package/dist/commands/tool/command.js.map +11 -0
  139. package/dist/commands/tool/handler.d.ts +17 -0
  140. package/dist/commands/tool/spec.d.ts +17 -0
  141. package/dist/commands/tool/steps/ValidateToolStep.d.ts +8 -0
  142. package/dist/commands/tool/virtual-tools/index.d.ts +1 -0
  143. package/dist/commands/tool/virtual-tools/list-tools.d.ts +2 -0
  144. package/dist/commands/view/command.d.ts +2 -1
  145. package/dist/commands/view/command.js +52 -0
  146. package/dist/commands/view/command.js.map +11 -0
  147. package/dist/commands/view/spec.d.ts +24 -0
  148. package/dist/framework/CommandDefinition.d.ts +2 -2
  149. package/dist/index.js +26 -21668
  150. package/dist/index.js.map +9 -0
  151. package/dist/lib/services/site/schemas.d.ts +8 -8
  152. package/dist/services/config/handler.d.ts +12 -0
  153. package/dist/services/config/spec.d.ts +82 -0
  154. package/dist/services/gcloud/auth.d.ts +28 -0
  155. package/dist/services/gcloud/core.d.ts +21 -0
  156. package/dist/services/gcloud/handler.d.ts +6 -18
  157. package/dist/services/gcloud/install.d.ts +23 -0
  158. package/dist/services/gcloud/projects.d.ts +15 -0
  159. package/dist/services/gcloud/spec.d.ts +32 -24
  160. package/dist/services/mcp-client/client.d.ts +0 -5
  161. package/dist/services/mcp-client/spec.d.ts +6 -6
  162. package/dist/services/mcp-config/spec.d.ts +12 -12
  163. package/dist/services/project/spec.d.ts +4 -4
  164. package/dist/services/proxy/spec.d.ts +3 -3
  165. package/dist/services/stitch/api.d.ts +10 -0
  166. package/dist/services/stitch/connection.d.ts +5 -0
  167. package/dist/services/stitch/handler.d.ts +5 -3
  168. package/dist/services/stitch/iam.d.ts +11 -0
  169. package/dist/services/stitch/spec.d.ts +6 -6
  170. package/dist/services/view/spec.d.ts +7 -7
  171. package/dist/src/cli.d.ts +1 -0
  172. package/dist/src/commands/doctor/handler.d.ts +9 -0
  173. package/dist/src/commands/doctor/handler.test.d.ts +1 -0
  174. package/dist/src/commands/doctor/spec.d.ts +130 -0
  175. package/dist/src/commands/doctor/spec.test.d.ts +1 -0
  176. package/dist/src/commands/init/handler.d.ts +17 -0
  177. package/dist/src/commands/init/handler.test.d.ts +1 -0
  178. package/dist/src/commands/init/spec.d.ts +88 -0
  179. package/dist/src/commands/init/spec.test.d.ts +1 -0
  180. package/dist/src/commands/proxy/handler.d.ts +7 -0
  181. package/dist/src/commands/proxy/handler.test.d.ts +1 -0
  182. package/dist/src/index.d.ts +13 -0
  183. package/dist/src/platform/detector.d.ts +29 -0
  184. package/dist/src/platform/paths.d.ts +20 -0
  185. package/dist/src/platform/shell.d.ts +26 -0
  186. package/dist/src/services/gcloud/handler.d.ts +48 -0
  187. package/dist/src/services/gcloud/handler.test.d.ts +1 -0
  188. package/dist/src/services/gcloud/spec.d.ts +405 -0
  189. package/dist/src/services/mcp-config/handler.d.ts +12 -0
  190. package/dist/src/services/mcp-config/handler.test.d.ts +1 -0
  191. package/dist/src/services/mcp-config/spec.d.ts +88 -0
  192. package/dist/src/services/mcp-config/spec.test.d.ts +1 -0
  193. package/dist/src/services/project/handler.d.ts +11 -0
  194. package/dist/src/services/project/handler.test.d.ts +1 -0
  195. package/dist/src/services/project/spec.d.ts +86 -0
  196. package/dist/src/services/project/spec.test.d.ts +1 -0
  197. package/dist/src/services/proxy/handler.d.ts +15 -0
  198. package/dist/src/services/proxy/handler.test.d.ts +1 -0
  199. package/dist/src/services/proxy/spec.d.ts +83 -0
  200. package/dist/src/services/proxy/spec.test.d.ts +1 -0
  201. package/dist/src/services/stitch/handler.d.ts +15 -0
  202. package/dist/src/services/stitch/handler.test.d.ts +1 -0
  203. package/dist/src/services/stitch/spec.d.ts +262 -0
  204. package/dist/src/services/stitch/spec.test.d.ts +1 -0
  205. package/dist/src/ui/spinner.d.ts +11 -0
  206. package/dist/src/ui/theme.d.ts +18 -0
  207. package/dist/src/ui/wizard.d.ts +24 -0
  208. package/dist/tests/mocks/shell.d.ts +2 -0
  209. package/dist/ui/JsonTree.d.ts +1 -1
  210. package/package.json +2 -2
  211. package/dist/commands/registry.d.ts +0 -2
  212. package/dist/ui/copy-behaviors/index.d.ts +0 -8
  213. package/dist/ui/serve-behaviors/index.d.ts +0 -7
  214. /package/dist/ui/navigation-behaviors/{index.d.ts → handler.d.ts} +0 -0
@@ -0,0 +1,733 @@
1
+ import {
2
+ require_jsx_dev_runtime
3
+ } from "./chunk-wz8d5vzb.js";
4
+ import {
5
+ Box_default,
6
+ Text,
7
+ use_app_default,
8
+ use_input_default,
9
+ use_stdout_default
10
+ } from "./chunk-2cetsfw4.js";
11
+ import {
12
+ require_react
13
+ } from "./chunk-4jwmvjb4.js";
14
+ import {
15
+ StitchViteServer
16
+ } from "./chunk-7xh1y383.js";
17
+ import {
18
+ ProjectSyncer,
19
+ SiteService,
20
+ pLimit
21
+ } from "./chunk-qv44tmn6.js";
22
+ import {
23
+ require_lib
24
+ } from "./chunk-w8q7nsm7.js";
25
+ import {
26
+ require_cli_spinners
27
+ } from "./chunk-nq68kghz.js";
28
+ import {
29
+ source_default
30
+ } from "./chunk-3sfn889r.js";
31
+ import {
32
+ __toESM
33
+ } from "./chunk-9wyra8hs.js";
34
+
35
+ // src/commands/site/ui/SiteBuilder.tsx
36
+ var import_react4 = __toESM(require_react(), 1);
37
+
38
+ // node_modules/ink-spinner/build/index.js
39
+ var import_react = __toESM(require_react(), 1);
40
+ var import_cli_spinners = __toESM(require_cli_spinners(), 1);
41
+ function Spinner({ type = "dots" }) {
42
+ const [frame, setFrame] = import_react.useState(0);
43
+ const spinner = import_cli_spinners.default[type];
44
+ import_react.useEffect(() => {
45
+ const timer = setInterval(() => {
46
+ setFrame((previousFrame) => {
47
+ const isLastFrame = previousFrame === spinner.frames.length - 1;
48
+ return isLastFrame ? 0 : previousFrame + 1;
49
+ });
50
+ }, spinner.interval);
51
+ return () => {
52
+ clearInterval(timer);
53
+ };
54
+ }, [spinner]);
55
+ return import_react.default.createElement(Text, null, spinner.frames[frame]);
56
+ }
57
+ var build_default = Spinner;
58
+
59
+ // node_modules/ink-text-input/build/index.js
60
+ var import_react2 = __toESM(require_react(), 1);
61
+ function TextInput({ value: originalValue, placeholder = "", focus = true, mask, highlightPastedText = false, showCursor = true, onChange, onSubmit }) {
62
+ const [state, setState] = import_react2.useState({
63
+ cursorOffset: (originalValue || "").length,
64
+ cursorWidth: 0
65
+ });
66
+ const { cursorOffset, cursorWidth } = state;
67
+ import_react2.useEffect(() => {
68
+ setState((previousState) => {
69
+ if (!focus || !showCursor) {
70
+ return previousState;
71
+ }
72
+ const newValue = originalValue || "";
73
+ if (previousState.cursorOffset > newValue.length - 1) {
74
+ return {
75
+ cursorOffset: newValue.length,
76
+ cursorWidth: 0
77
+ };
78
+ }
79
+ return previousState;
80
+ });
81
+ }, [originalValue, focus, showCursor]);
82
+ const cursorActualWidth = highlightPastedText ? cursorWidth : 0;
83
+ const value = mask ? mask.repeat(originalValue.length) : originalValue;
84
+ let renderedValue = value;
85
+ let renderedPlaceholder = placeholder ? source_default.grey(placeholder) : undefined;
86
+ if (showCursor && focus) {
87
+ renderedPlaceholder = placeholder.length > 0 ? source_default.inverse(placeholder[0]) + source_default.grey(placeholder.slice(1)) : source_default.inverse(" ");
88
+ renderedValue = value.length > 0 ? "" : source_default.inverse(" ");
89
+ let i = 0;
90
+ for (const char of value) {
91
+ renderedValue += i >= cursorOffset - cursorActualWidth && i <= cursorOffset ? source_default.inverse(char) : char;
92
+ i++;
93
+ }
94
+ if (value.length > 0 && cursorOffset === value.length) {
95
+ renderedValue += source_default.inverse(" ");
96
+ }
97
+ }
98
+ use_input_default((input, key) => {
99
+ if (key.upArrow || key.downArrow || key.ctrl && input === "c" || key.tab || key.shift && key.tab) {
100
+ return;
101
+ }
102
+ if (key.return) {
103
+ if (onSubmit) {
104
+ onSubmit(originalValue);
105
+ }
106
+ return;
107
+ }
108
+ let nextCursorOffset = cursorOffset;
109
+ let nextValue = originalValue;
110
+ let nextCursorWidth = 0;
111
+ if (key.leftArrow) {
112
+ if (showCursor) {
113
+ nextCursorOffset--;
114
+ }
115
+ } else if (key.rightArrow) {
116
+ if (showCursor) {
117
+ nextCursorOffset++;
118
+ }
119
+ } else if (key.backspace || key.delete) {
120
+ if (cursorOffset > 0) {
121
+ nextValue = originalValue.slice(0, cursorOffset - 1) + originalValue.slice(cursorOffset, originalValue.length);
122
+ nextCursorOffset--;
123
+ }
124
+ } else {
125
+ nextValue = originalValue.slice(0, cursorOffset) + input + originalValue.slice(cursorOffset, originalValue.length);
126
+ nextCursorOffset += input.length;
127
+ if (input.length > 1) {
128
+ nextCursorWidth = input.length;
129
+ }
130
+ }
131
+ if (cursorOffset < 0) {
132
+ nextCursorOffset = 0;
133
+ }
134
+ if (cursorOffset > originalValue.length) {
135
+ nextCursorOffset = originalValue.length;
136
+ }
137
+ setState({
138
+ cursorOffset: nextCursorOffset,
139
+ cursorWidth: nextCursorWidth
140
+ });
141
+ if (nextValue !== originalValue) {
142
+ onChange(nextValue);
143
+ }
144
+ }, { isActive: focus });
145
+ return import_react2.default.createElement(Text, null, placeholder ? value.length > 0 ? renderedValue : renderedPlaceholder : renderedValue);
146
+ }
147
+ var build_default2 = TextInput;
148
+
149
+ // src/commands/site/utils/SiteManifest.ts
150
+ var import_fs_extra = __toESM(require_lib(), 1);
151
+ import path from "path";
152
+ import os from "os";
153
+
154
+ class SiteManifest {
155
+ filePath;
156
+ legacyPath;
157
+ constructor(projectId) {
158
+ const dir = path.join(os.homedir(), ".stitch-mcp", "site", projectId);
159
+ this.filePath = path.join(dir, "site-manifest.json");
160
+ this.legacyPath = path.join(dir, "discarded.json");
161
+ }
162
+ async load() {
163
+ try {
164
+ const data = await import_fs_extra.default.readJson(this.filePath);
165
+ return new Map(Object.entries(data.screens || {}));
166
+ } catch {}
167
+ try {
168
+ const legacy = await import_fs_extra.default.readJson(this.legacyPath);
169
+ const map = new Map;
170
+ for (const id of legacy.discardedScreenIds || []) {
171
+ map.set(id, { status: "discarded" });
172
+ }
173
+ return map;
174
+ } catch {
175
+ return new Map;
176
+ }
177
+ }
178
+ async save(screens) {
179
+ const record = {};
180
+ for (const screen of screens) {
181
+ const entry = {};
182
+ if (screen.status !== "ignored") {
183
+ entry.status = screen.status;
184
+ }
185
+ if (screen.route !== "") {
186
+ entry.route = screen.route;
187
+ }
188
+ if (entry.status || entry.route) {
189
+ record[screen.id] = entry;
190
+ }
191
+ }
192
+ await import_fs_extra.default.ensureDir(path.dirname(this.filePath));
193
+ const data = { screens: record };
194
+ await import_fs_extra.default.writeJson(this.filePath, data, { spaces: 2 });
195
+ }
196
+ }
197
+
198
+ // src/commands/site/ui/components/StatusIcon.tsx
199
+ var jsx_dev_runtime = __toESM(require_jsx_dev_runtime(), 1);
200
+ var StatusIcon = ({ status }) => {
201
+ if (status === "included") {
202
+ return /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
203
+ color: "green",
204
+ children: "✔ "
205
+ }, undefined, false, undefined, this);
206
+ }
207
+ if (status === "discarded") {
208
+ return /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
209
+ color: "red",
210
+ children: "✖ "
211
+ }, undefined, false, undefined, this);
212
+ }
213
+ return /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
214
+ color: "gray",
215
+ children: "- "
216
+ }, undefined, false, undefined, this);
217
+ };
218
+
219
+ // src/commands/site/ui/ScreenList.tsx
220
+ var jsx_dev_runtime2 = __toESM(require_jsx_dev_runtime(), 1);
221
+ var ScreenList = ({ items, activeIndex }) => {
222
+ const { stdout } = use_stdout_default();
223
+ const height = stdout ? stdout.rows : 20;
224
+ const LIST_HEIGHT = Math.max(5, height - 10);
225
+ let start = 0;
226
+ if (activeIndex >= LIST_HEIGHT) {
227
+ start = activeIndex - LIST_HEIGHT + 1;
228
+ }
229
+ start = Math.max(0, activeIndex - Math.floor(LIST_HEIGHT / 2));
230
+ const end = Math.min(items.length, start + LIST_HEIGHT);
231
+ if (end - start < LIST_HEIGHT && items.length > LIST_HEIGHT) {
232
+ start = Math.max(0, items.length - LIST_HEIGHT);
233
+ }
234
+ const visibleItems = items.slice(start, end);
235
+ return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
236
+ flexDirection: "column",
237
+ flexGrow: 1,
238
+ borderStyle: "single",
239
+ borderColor: "blue",
240
+ children: [
241
+ start > 0 && /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
242
+ paddingLeft: 1,
243
+ children: /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
244
+ color: "gray",
245
+ children: [
246
+ "... ",
247
+ start,
248
+ " more above ..."
249
+ ]
250
+ }, undefined, true, undefined, this)
251
+ }, undefined, false, undefined, this),
252
+ visibleItems.map((item, i) => {
253
+ const index = start + i;
254
+ const isActive = index === activeIndex;
255
+ const { screen } = item;
256
+ return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
257
+ children: [
258
+ /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
259
+ color: isActive ? "cyan" : undefined,
260
+ children: isActive ? "> " : " "
261
+ }, undefined, false, undefined, this),
262
+ /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(StatusIcon, {
263
+ status: screen.status
264
+ }, undefined, false, undefined, this),
265
+ /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
266
+ color: isActive ? "cyan" : undefined,
267
+ wrap: "truncate",
268
+ children: screen.title
269
+ }, undefined, false, undefined, this),
270
+ screen.route && /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
271
+ color: "gray",
272
+ children: [
273
+ " -> ",
274
+ screen.route
275
+ ]
276
+ }, undefined, true, undefined, this)
277
+ ]
278
+ }, screen.id, true, undefined, this);
279
+ }),
280
+ end < items.length && /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
281
+ paddingLeft: 1,
282
+ children: /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
283
+ color: "gray",
284
+ children: [
285
+ "... ",
286
+ items.length - end,
287
+ " more below ..."
288
+ ]
289
+ }, undefined, true, undefined, this)
290
+ }, undefined, false, undefined, this)
291
+ ]
292
+ }, undefined, true, undefined, this);
293
+ };
294
+
295
+ // src/commands/site/hooks/useProjectHydration.ts
296
+ var import_react3 = __toESM(require_react(), 1);
297
+ function useProjectHydration(screens, server, syncer, activeScreenId) {
298
+ const [hydrationStatus, setHydrationStatus] = import_react3.useState("idle");
299
+ const [progress, setProgress] = import_react3.useState(0);
300
+ const contentCache = import_react3.useRef(new Map);
301
+ const [htmlContent, setHtmlContent] = import_react3.useState(new Map);
302
+ import_react3.useEffect(() => {
303
+ if (!server || screens.length === 0)
304
+ return;
305
+ let mounted = true;
306
+ const hydrate = async () => {
307
+ const toDownload = screens.filter((s) => {
308
+ if (contentCache.current.has(s.id))
309
+ return false;
310
+ return s.status === "included" || s.id === activeScreenId;
311
+ });
312
+ if (toDownload.length === 0) {
313
+ if (hydrationStatus === "idle" || hydrationStatus === "downloading") {
314
+ setHydrationStatus("ready");
315
+ setHtmlContent(new Map(contentCache.current));
316
+ }
317
+ if (activeScreenId && contentCache.current.has(activeScreenId)) {
318
+ server.mount(`/_preview/${activeScreenId}`, contentCache.current.get(activeScreenId));
319
+ }
320
+ return;
321
+ }
322
+ setHydrationStatus("downloading");
323
+ const limit = pLimit(3);
324
+ let completed = 0;
325
+ const total = toDownload.length;
326
+ try {
327
+ await Promise.all(toDownload.map((screen) => limit(async () => {
328
+ if (!mounted)
329
+ return;
330
+ if (!screen.downloadUrl)
331
+ return;
332
+ try {
333
+ const html = await syncer.fetchContent(screen.downloadUrl);
334
+ if (mounted) {
335
+ contentCache.current.set(screen.id, html);
336
+ server.mount(`/_preview/${screen.id}`, html);
337
+ }
338
+ } catch (e) {
339
+ console.error(`Failed to hydrate ${screen.id}`, e);
340
+ }
341
+ if (mounted) {
342
+ completed++;
343
+ setProgress(completed / total);
344
+ }
345
+ })));
346
+ if (mounted) {
347
+ setHtmlContent(new Map(contentCache.current));
348
+ setHydrationStatus("ready");
349
+ }
350
+ } catch (e) {
351
+ if (mounted)
352
+ setHydrationStatus("error");
353
+ }
354
+ };
355
+ hydrate();
356
+ return () => {
357
+ mounted = false;
358
+ };
359
+ }, [screens, server, syncer, activeScreenId]);
360
+ return { hydrationStatus, progress, htmlContent };
361
+ }
362
+
363
+ // src/commands/site/ui/SiteBuilder.tsx
364
+ var jsx_dev_runtime3 = __toESM(require_jsx_dev_runtime(), 1);
365
+ import { spawn } from "child_process";
366
+ var SiteBuilder = ({ projectId, client, onExit }) => {
367
+ const { exit } = use_app_default();
368
+ const [loading, setLoading] = import_react4.useState(true);
369
+ const [error, setError] = import_react4.useState(null);
370
+ const [screens, setScreens] = import_react4.useState([]);
371
+ const [showSelectedOnly, setShowSelectedOnly] = import_react4.useState(false);
372
+ const [activeIndex, setActiveIndex] = import_react4.useState(0);
373
+ const [viewMode, setViewMode] = import_react4.useState("default");
374
+ const siteManifest = import_react4.useMemo(() => new SiteManifest(projectId), [projectId]);
375
+ const [isEditingRoute, setIsEditingRoute] = import_react4.useState(false);
376
+ const [routeValue, setRouteValue] = import_react4.useState("");
377
+ const [followMode, setFollowMode] = import_react4.useState(true);
378
+ const [showAllKeys, setShowAllKeys] = import_react4.useState(false);
379
+ const [serverUrl, setServerUrl] = import_react4.useState(null);
380
+ const [server, setServer] = import_react4.useState(null);
381
+ const syncer = import_react4.useMemo(() => new ProjectSyncer(client), [client]);
382
+ import_react4.useEffect(() => {
383
+ let mounted = true;
384
+ const srv = new StitchViteServer;
385
+ setServer(srv);
386
+ const init = async () => {
387
+ try {
388
+ const url = await srv.start(0);
389
+ if (mounted)
390
+ setServerUrl(url);
391
+ const remoteScreens = await syncer.fetchManifest(projectId);
392
+ const uiScreens = SiteService.toUIScreens(remoteScreens);
393
+ const saved = await siteManifest.load();
394
+ for (const screen of uiScreens) {
395
+ const state = saved.get(screen.id);
396
+ if (state?.status)
397
+ screen.status = state.status;
398
+ if (state?.route)
399
+ screen.route = state.route;
400
+ }
401
+ if (mounted) {
402
+ setScreens(uiScreens);
403
+ setLoading(false);
404
+ }
405
+ } catch (e) {
406
+ if (mounted)
407
+ setError(e.message);
408
+ }
409
+ };
410
+ init();
411
+ return () => {
412
+ mounted = false;
413
+ srv.stop();
414
+ };
415
+ }, [projectId, syncer]);
416
+ const displayList = import_react4.useMemo(() => {
417
+ let list = screens.map((s, i) => ({ screen: s, sourceIndex: i }));
418
+ if (viewMode === "discarded") {
419
+ return list.filter((item) => item.screen.status === "discarded");
420
+ }
421
+ list = list.filter((item) => item.screen.status !== "discarded");
422
+ if (showSelectedOnly) {
423
+ list = list.filter((item) => item.screen.status === "included");
424
+ }
425
+ return list;
426
+ }, [screens, viewMode, showSelectedOnly]);
427
+ import_react4.useEffect(() => {
428
+ setActiveIndex((prev) => {
429
+ if (displayList.length === 0)
430
+ return 0;
431
+ return Math.min(prev, Math.max(0, displayList.length - 1));
432
+ });
433
+ }, [displayList.length]);
434
+ const activeItem = displayList[activeIndex];
435
+ const activeScreenId = activeItem?.screen.id;
436
+ const { hydrationStatus, progress, htmlContent } = useProjectHydration(screens, server, syncer, activeScreenId);
437
+ import_react4.useEffect(() => {
438
+ if (server && followMode && hydrationStatus === "ready" && activeScreenId) {
439
+ server.navigate(`/_preview/${activeScreenId}`);
440
+ }
441
+ }, [activeScreenId, followMode, server, hydrationStatus]);
442
+ use_input_default((input, key) => {
443
+ if (loading || error)
444
+ return;
445
+ if (isEditingRoute) {
446
+ if (key.escape) {
447
+ setIsEditingRoute(false);
448
+ setRouteValue("");
449
+ }
450
+ return;
451
+ }
452
+ if (key.upArrow) {
453
+ setActiveIndex((prev) => Math.max(0, prev - 1));
454
+ }
455
+ if (key.downArrow) {
456
+ setActiveIndex((prev) => Math.min(displayList.length - 1, prev + 1));
457
+ }
458
+ if (input === " ") {
459
+ if (activeItem) {
460
+ const originalIndex = activeItem.sourceIndex;
461
+ setScreens((prev) => {
462
+ const next = [...prev];
463
+ const s = next[originalIndex];
464
+ if (s) {
465
+ s.status = s.status === "included" ? "ignored" : "included";
466
+ }
467
+ siteManifest.save(next);
468
+ return next;
469
+ });
470
+ }
471
+ }
472
+ if (key.return) {
473
+ if (activeItem) {
474
+ setRouteValue(activeItem.screen.route);
475
+ setIsEditingRoute(true);
476
+ }
477
+ }
478
+ if (input === "t") {
479
+ setShowSelectedOnly((prev) => !prev);
480
+ }
481
+ if (input === "f") {
482
+ setFollowMode((prev) => !prev);
483
+ }
484
+ if (input === "x") {
485
+ const item = displayList[activeIndex];
486
+ if (!item)
487
+ return;
488
+ if (viewMode === "discarded") {
489
+ const idx = item.sourceIndex;
490
+ setScreens((prev) => {
491
+ const next = [...prev];
492
+ if (next[idx])
493
+ next[idx].status = "ignored";
494
+ siteManifest.save(next);
495
+ return next;
496
+ });
497
+ } else {
498
+ const idx = item.sourceIndex;
499
+ setScreens((prev) => {
500
+ const next = [...prev];
501
+ if (next[idx])
502
+ next[idx].status = "discarded";
503
+ siteManifest.save(next);
504
+ return next;
505
+ });
506
+ }
507
+ }
508
+ if (input === "d") {
509
+ setViewMode((prev) => prev === "default" ? "discarded" : "default");
510
+ setActiveIndex(0);
511
+ }
512
+ if (input === "o") {
513
+ if (serverUrl && activeScreenId) {
514
+ const start = process.platform == "darwin" ? "open" : process.platform == "win32" ? "start" : "xdg-open";
515
+ const target = `${serverUrl}/_preview/${activeScreenId}`;
516
+ if (process.platform === "win32") {
517
+ spawn("cmd", ["/c", "start", target], { detached: true, stdio: "ignore" }).unref();
518
+ } else {
519
+ spawn(start, [target], { detached: true, stdio: "ignore" }).unref();
520
+ }
521
+ }
522
+ }
523
+ if (input === "g") {
524
+ const included = screens.filter((s) => s.status === "included");
525
+ const invalid = included.find((s) => !s.route || s.route.trim() === "");
526
+ if (invalid) {
527
+ return;
528
+ }
529
+ const finalConfig = {
530
+ projectId,
531
+ routes: included.map((s) => ({
532
+ screenId: s.id,
533
+ route: s.route,
534
+ status: s.status
535
+ }))
536
+ };
537
+ onExit(finalConfig, htmlContent);
538
+ exit();
539
+ }
540
+ if (input === "e") {
541
+ const included = screens.filter((s) => s.status === "included");
542
+ const exportData = {
543
+ projectId,
544
+ routes: included.map((s) => ({
545
+ screenId: s.id,
546
+ route: s.route
547
+ }))
548
+ };
549
+ process.stdout.write(JSON.stringify(exportData, null, 2) + `
550
+ `);
551
+ }
552
+ if (input === "?") {
553
+ setShowAllKeys((prev) => !prev);
554
+ }
555
+ if (input === "q") {
556
+ onExit(null);
557
+ exit();
558
+ }
559
+ });
560
+ const handleRouteSubmit = (val) => {
561
+ if (activeItem) {
562
+ const originalIndex = activeItem.sourceIndex;
563
+ setScreens((prev) => {
564
+ const next = [...prev];
565
+ if (next[originalIndex]) {
566
+ next[originalIndex].route = val;
567
+ }
568
+ siteManifest.save(next);
569
+ return next;
570
+ });
571
+ setIsEditingRoute(false);
572
+ setActiveIndex((prev) => Math.min(displayList.length - 1, prev + 1));
573
+ }
574
+ };
575
+ if (error) {
576
+ return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
577
+ color: "red",
578
+ children: [
579
+ "Error: ",
580
+ error
581
+ ]
582
+ }, undefined, true, undefined, this);
583
+ }
584
+ if (loading) {
585
+ return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
586
+ children: /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
587
+ color: "green",
588
+ children: [
589
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(build_default, {
590
+ type: "dots"
591
+ }, undefined, false, undefined, this),
592
+ " Loading project..."
593
+ ]
594
+ }, undefined, true, undefined, this)
595
+ }, undefined, false, undefined, this);
596
+ }
597
+ return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
598
+ flexDirection: "column",
599
+ height: "100%",
600
+ children: [
601
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
602
+ borderStyle: "single",
603
+ borderColor: "cyan",
604
+ paddingX: 1,
605
+ children: [
606
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
607
+ children: "Stitch Site Builder"
608
+ }, undefined, false, undefined, this),
609
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
610
+ marginLeft: 2,
611
+ children: /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
612
+ color: "gray",
613
+ children: serverUrl
614
+ }, undefined, false, undefined, this)
615
+ }, undefined, false, undefined, this),
616
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
617
+ marginLeft: 2,
618
+ children: viewMode === "discarded" ? /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
619
+ color: "red",
620
+ children: [
621
+ "Viewing Discarded (",
622
+ displayList.length,
623
+ ")"
624
+ ]
625
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
626
+ children: [
627
+ "Filter: ",
628
+ showSelectedOnly ? "Selected" : "All",
629
+ " (",
630
+ displayList.length,
631
+ ")"
632
+ ]
633
+ }, undefined, true, undefined, this)
634
+ }, undefined, false, undefined, this),
635
+ viewMode === "default" && screens.filter((s) => s.status === "discarded").length > 0 && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
636
+ marginLeft: 2,
637
+ children: /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
638
+ dimColor: true,
639
+ children: [
640
+ screens.filter((s) => s.status === "discarded").length,
641
+ " discarded (press d to view)"
642
+ ]
643
+ }, undefined, true, undefined, this)
644
+ }, undefined, false, undefined, this),
645
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
646
+ marginLeft: 2,
647
+ children: [
648
+ hydrationStatus === "downloading" && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
649
+ color: "yellow",
650
+ children: [
651
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(build_default, {
652
+ type: "dots"
653
+ }, undefined, false, undefined, this),
654
+ " Downloading... ",
655
+ Math.round(progress * 100),
656
+ "%"
657
+ ]
658
+ }, undefined, true, undefined, this),
659
+ hydrationStatus === "ready" && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
660
+ color: "green",
661
+ children: "Ready"
662
+ }, undefined, false, undefined, this)
663
+ ]
664
+ }, undefined, true, undefined, this)
665
+ ]
666
+ }, undefined, true, undefined, this),
667
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(ScreenList, {
668
+ items: displayList,
669
+ activeIndex
670
+ }, undefined, false, undefined, this),
671
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
672
+ borderStyle: "single",
673
+ borderColor: isEditingRoute ? "green" : "gray",
674
+ paddingX: 1,
675
+ flexDirection: "column",
676
+ children: activeItem ? /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(jsx_dev_runtime3.Fragment, {
677
+ children: [
678
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
679
+ bold: true,
680
+ children: [
681
+ "Route for: ",
682
+ activeItem.screen.title
683
+ ]
684
+ }, undefined, true, undefined, this),
685
+ isEditingRoute ? /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
686
+ children: [
687
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
688
+ color: "green",
689
+ children: "> "
690
+ }, undefined, false, undefined, this),
691
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(build_default2, {
692
+ value: routeValue,
693
+ onChange: setRouteValue,
694
+ onSubmit: handleRouteSubmit
695
+ }, undefined, false, undefined, this)
696
+ ]
697
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
698
+ children: [
699
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
700
+ color: "gray",
701
+ children: activeItem.screen.route || "No route defined"
702
+ }, undefined, false, undefined, this),
703
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
704
+ marginLeft: 2,
705
+ children: /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
706
+ dimColor: true,
707
+ children: "Press Enter to edit"
708
+ }, undefined, false, undefined, this)
709
+ }, undefined, false, undefined, this)
710
+ ]
711
+ }, undefined, true, undefined, this)
712
+ ]
713
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
714
+ color: "gray",
715
+ children: "No screen selected"
716
+ }, undefined, false, undefined, this)
717
+ }, undefined, false, undefined, this),
718
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
719
+ borderStyle: "single",
720
+ borderColor: "gray",
721
+ paddingX: 1,
722
+ children: /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
723
+ dimColor: true,
724
+ children: viewMode === "discarded" ? "[x] Undiscard [d] Back to All [q] Quit" : showAllKeys ? `[Space] Toggle [Enter] Edit Route [x] Discard [d] View Discarded [t] Filter [f] Follow: ${followMode ? "ON" : "OFF"} [o] Open [g] Generate [e] Export [q] Quit [?] Less` : "[Space] Toggle [Enter] Edit Route [g] Generate [x] Discard [o] Open [q] Quit [?] More"
725
+ }, undefined, false, undefined, this)
726
+ }, undefined, false, undefined, this)
727
+ ]
728
+ }, undefined, true, undefined, this);
729
+ };
730
+
731
+ export { SiteManifest, SiteBuilder };
732
+
733
+ //# debugId=064C634C04DC16A364756E2164756E21