@_davideast/stitch-mcp 0.5.2 → 0.5.3

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 (126) hide show
  1. package/dist/chunk-22bymmh9.js +137 -0
  2. package/dist/chunk-22bymmh9.js.map +10 -0
  3. package/dist/chunk-387yyye2.js +248 -0
  4. package/dist/chunk-387yyye2.js.map +14 -0
  5. package/dist/chunk-3ff2k44g.js +19 -0
  6. package/dist/chunk-3ff2k44g.js.map +9 -0
  7. package/dist/chunk-46cay1zp.js +273 -0
  8. package/dist/chunk-46cay1zp.js.map +10 -0
  9. package/dist/chunk-48e1jpm8.js +167 -0
  10. package/dist/chunk-48e1jpm8.js.map +10 -0
  11. package/dist/chunk-4arzkk1s.js +69 -0
  12. package/dist/chunk-4arzkk1s.js.map +10 -0
  13. package/dist/chunk-4js7vw6h.js +415 -0
  14. package/dist/chunk-4js7vw6h.js.map +20 -0
  15. package/dist/chunk-4p1wfk3t.js +736 -0
  16. package/dist/chunk-4p1wfk3t.js.map +16 -0
  17. package/dist/chunk-4zg969tc.js +370 -0
  18. package/dist/chunk-4zg969tc.js.map +16 -0
  19. package/dist/chunk-5jjt7tgw.js +247 -0
  20. package/dist/chunk-5jjt7tgw.js.map +14 -0
  21. package/dist/chunk-5t2h8z2n.js +273 -0
  22. package/dist/chunk-5t2h8z2n.js.map +10 -0
  23. package/dist/chunk-5zy3et1m.js +759 -0
  24. package/dist/chunk-5zy3et1m.js.map +19 -0
  25. package/dist/chunk-6wvst7z8.js +125 -0
  26. package/dist/chunk-6wvst7z8.js.map +12 -0
  27. package/dist/chunk-8mm08arm.js +256 -0
  28. package/dist/chunk-8mm08arm.js.map +11 -0
  29. package/dist/chunk-8nv4wwv0.js +19 -0
  30. package/dist/chunk-8nv4wwv0.js.map +9 -0
  31. package/dist/chunk-9cjny9z2.js +19 -0
  32. package/dist/chunk-9cjny9z2.js.map +9 -0
  33. package/dist/chunk-9ggfw78s.js +19 -0
  34. package/dist/chunk-9ggfw78s.js.map +9 -0
  35. package/dist/chunk-9nyyn1hn.js +125 -0
  36. package/dist/chunk-9nyyn1hn.js.map +12 -0
  37. package/dist/chunk-9nzbvp6r.js +19 -0
  38. package/dist/chunk-9nzbvp6r.js.map +9 -0
  39. package/dist/chunk-a0gmbh8e.js +415 -0
  40. package/dist/chunk-a0gmbh8e.js.map +20 -0
  41. package/dist/chunk-acv998mp.js +941 -0
  42. package/dist/chunk-acv998mp.js.map +27 -0
  43. package/dist/chunk-cpjsvven.js +10 -0
  44. package/dist/chunk-cpjsvven.js.map +9 -0
  45. package/dist/chunk-dmrahbs1.js +31467 -0
  46. package/dist/chunk-dmrahbs1.js.map +245 -0
  47. package/dist/chunk-dts6851a.js +137 -0
  48. package/dist/chunk-dts6851a.js.map +10 -0
  49. package/dist/chunk-efd0rm6g.js +69 -0
  50. package/dist/chunk-efd0rm6g.js.map +10 -0
  51. package/dist/chunk-f1kjn6cd.js +16554 -0
  52. package/dist/chunk-f1kjn6cd.js.map +98 -0
  53. package/dist/chunk-f5f6ekgp.js +109 -0
  54. package/dist/chunk-f5f6ekgp.js.map +10 -0
  55. package/dist/chunk-fmewhfh3.js +137 -0
  56. package/dist/chunk-fmewhfh3.js.map +10 -0
  57. package/dist/chunk-fmhrn6cg.js +6382 -0
  58. package/dist/chunk-fmhrn6cg.js.map +109 -0
  59. package/dist/chunk-gh7dzfhb.js +256 -0
  60. package/dist/chunk-gh7dzfhb.js.map +11 -0
  61. package/dist/chunk-gwhtc0fe.js +370 -0
  62. package/dist/chunk-gwhtc0fe.js.map +16 -0
  63. package/dist/chunk-hc7sdwmn.js +449 -0
  64. package/dist/chunk-hc7sdwmn.js.map +17 -0
  65. package/dist/chunk-k4xwb3wp.js +44184 -0
  66. package/dist/chunk-k4xwb3wp.js.map +237 -0
  67. package/dist/chunk-k751yfm6.js +736 -0
  68. package/dist/chunk-k751yfm6.js.map +16 -0
  69. package/dist/chunk-kkc2tvar.js +19 -0
  70. package/dist/chunk-kkc2tvar.js.map +9 -0
  71. package/dist/chunk-kva47mgc.js +10 -0
  72. package/dist/chunk-kva47mgc.js.map +9 -0
  73. package/dist/chunk-nv2j020p.js +45210 -0
  74. package/dist/chunk-nv2j020p.js.map +258 -0
  75. package/dist/chunk-pdj9s41r.js +683 -0
  76. package/dist/chunk-pdj9s41r.js.map +17 -0
  77. package/dist/chunk-ppphsy4t.js +273 -0
  78. package/dist/chunk-ppphsy4t.js.map +10 -0
  79. package/dist/chunk-psmw9zpa.js +941 -0
  80. package/dist/chunk-psmw9zpa.js.map +27 -0
  81. package/dist/chunk-pz31v3ma.js +24 -0
  82. package/dist/chunk-pz31v3ma.js.map +9 -0
  83. package/dist/chunk-qbt0906e.js +1495 -0
  84. package/dist/chunk-qbt0906e.js.map +23 -0
  85. package/dist/chunk-rh3k09h7.js +19 -0
  86. package/dist/chunk-rh3k09h7.js.map +9 -0
  87. package/dist/chunk-saznae7w.js +10 -0
  88. package/dist/chunk-saznae7w.js.map +9 -0
  89. package/dist/chunk-sscqdg1j.js +69 -0
  90. package/dist/chunk-sscqdg1j.js.map +10 -0
  91. package/dist/chunk-stgj6y85.js +835 -0
  92. package/dist/chunk-stgj6y85.js.map +19 -0
  93. package/dist/chunk-t3tqmxyj.js +42 -0
  94. package/dist/chunk-t3tqmxyj.js.map +9 -0
  95. package/dist/chunk-v8ak35zd.js +94 -0
  96. package/dist/chunk-v8ak35zd.js.map +10 -0
  97. package/dist/chunk-w9acw256.js +167 -0
  98. package/dist/chunk-w9acw256.js.map +10 -0
  99. package/dist/chunk-wq60thjn.js +167 -0
  100. package/dist/chunk-wq60thjn.js.map +10 -0
  101. package/dist/chunk-wzkdeb8a.js +736 -0
  102. package/dist/chunk-wzkdeb8a.js.map +16 -0
  103. package/dist/chunk-xxv6j815.js +256 -0
  104. package/dist/chunk-xxv6j815.js.map +11 -0
  105. package/dist/chunk-yjnj35q8.js +1495 -0
  106. package/dist/chunk-yjnj35q8.js.map +23 -0
  107. package/dist/chunk-yvzzrczy.js +45206 -0
  108. package/dist/chunk-yvzzrczy.js.map +258 -0
  109. package/dist/chunk-ywax1akt.js +370 -0
  110. package/dist/chunk-ywax1akt.js.map +16 -0
  111. package/dist/chunk-zakq9pc0.js +4989 -0
  112. package/dist/chunk-zakq9pc0.js.map +65 -0
  113. package/dist/commands/doctor/command.js +1 -1
  114. package/dist/commands/doctor/steps/AdcProjectCheckStep.d.ts +8 -0
  115. package/dist/commands/init/command.js +1 -1
  116. package/dist/commands/logout/command.js +1 -1
  117. package/dist/commands/proxy/command.js +1 -1
  118. package/dist/commands/screens/command.js +2 -2
  119. package/dist/commands/serve/command.js +3 -3
  120. package/dist/commands/site/command.js +1 -1
  121. package/dist/commands/snapshot/command.js +1 -1
  122. package/dist/commands/tool/command.js +1 -1
  123. package/dist/commands/view/command.js +1 -1
  124. package/dist/index.js +4 -4
  125. package/dist/lib/server/AssetGateway.d.ts +12 -0
  126. package/package.json +1 -1
@@ -0,0 +1,247 @@
1
+ import {
2
+ ConsoleUI,
3
+ GcloudHandler,
4
+ execCommand,
5
+ getGcloudConfigPath
6
+ } from "./chunk-zakq9pc0.js";
7
+ import {
8
+ runSteps
9
+ } from "./chunk-f2hq6bfv.js";
10
+ import"./chunk-tz7wnw4s.js";
11
+ import {
12
+ icons,
13
+ theme
14
+ } from "./chunk-kbtqrkwh.js";
15
+ import"./chunk-3sfn889r.js";
16
+ import"./chunk-c6ge431q.js";
17
+ import"./chunk-9wyra8hs.js";
18
+
19
+ // src/commands/logout/steps/PrepareStep.ts
20
+ class PrepareStep {
21
+ id = "prepare";
22
+ name = "Preparation";
23
+ async shouldRun(context) {
24
+ return true;
25
+ }
26
+ async run(context) {
27
+ const result = await context.gcloudService.ensureInstalled({
28
+ minVersion: "400.0.0",
29
+ forceLocal: false
30
+ });
31
+ if (!result.success) {
32
+ return {
33
+ success: false,
34
+ error: new Error("Google Cloud CLI not found"),
35
+ errorCode: "GCLOUD_NOT_FOUND",
36
+ shouldExit: true
37
+ };
38
+ }
39
+ context.gcloudPath = result.data.path;
40
+ if (!context.input.force) {
41
+ const shouldLogout = await context.ui.promptConfirm("Are you sure you want to log out? This will revoke all credentials.", false);
42
+ if (!shouldLogout) {
43
+ context.ui.log(`
44
+ Logout cancelled.
45
+ `);
46
+ return { success: true, shouldExit: true, detail: "Cancelled" };
47
+ }
48
+ }
49
+ return { success: true };
50
+ }
51
+ }
52
+
53
+ // src/commands/logout/steps/RevokeUserStep.ts
54
+ class RevokeUserStep {
55
+ id = "revoke-user";
56
+ name = "Revoke user authentication";
57
+ async shouldRun(context) {
58
+ if (!context.gcloudPath) {
59
+ const result = await context.gcloudService.ensureInstalled({ minVersion: "400.0.0", forceLocal: false });
60
+ if (result.success)
61
+ context.gcloudPath = result.data.path;
62
+ else
63
+ return false;
64
+ }
65
+ return true;
66
+ }
67
+ async run(context) {
68
+ const activeAccount = await context.gcloudService.getActiveAccount();
69
+ if (activeAccount) {
70
+ context.ui.log(theme.gray("Revoking user authentication..."));
71
+ const userResult = await execCommand([context.gcloudPath, "auth", "revoke", "--all"], { env: this.getEnvironment() });
72
+ if (userResult.success || userResult.stderr?.includes("No credentialed accounts")) {
73
+ context.ui.log(theme.green(`${icons.success} User authentication revoked`));
74
+ context.userRevoked = true;
75
+ } else {
76
+ context.ui.log(theme.yellow(`${icons.warning} Failed to revoke user authentication`));
77
+ }
78
+ } else {
79
+ context.ui.log(theme.gray("No active user authentication found"));
80
+ context.userRevoked = true;
81
+ }
82
+ return { success: true };
83
+ }
84
+ getEnvironment() {
85
+ const configPath = getGcloudConfigPath();
86
+ const env = { ...process.env };
87
+ env.CLOUDSDK_CONFIG = configPath;
88
+ env.CLOUDSDK_CORE_DISABLE_PROMPTS = "1";
89
+ return env;
90
+ }
91
+ }
92
+
93
+ // src/commands/logout/steps/RevokeAdcStep.ts
94
+ class RevokeAdcStep {
95
+ id = "revoke-adc";
96
+ name = "Revoke Application Default Credentials";
97
+ async shouldRun(context) {
98
+ if (!context.gcloudPath) {
99
+ const result = await context.gcloudService.ensureInstalled({ minVersion: "400.0.0", forceLocal: false });
100
+ if (result.success)
101
+ context.gcloudPath = result.data.path;
102
+ else
103
+ return false;
104
+ }
105
+ return true;
106
+ }
107
+ async run(context) {
108
+ const hasADC = await context.gcloudService.hasADC();
109
+ if (hasADC) {
110
+ context.ui.log(theme.gray("Revoking Application Default Credentials..."));
111
+ const adcResult = await execCommand([context.gcloudPath, "auth", "application-default", "revoke"], { env: this.getEnvironment() });
112
+ if (adcResult.success || adcResult.stderr?.includes("No credentials")) {
113
+ context.ui.log(theme.green(`${icons.success} Application Default Credentials revoked`));
114
+ context.adcRevoked = true;
115
+ } else {
116
+ context.ui.log(theme.yellow(`${icons.warning} Failed to revoke Application Default Credentials`));
117
+ }
118
+ } else {
119
+ context.ui.log(theme.gray("No Application Default Credentials found"));
120
+ context.adcRevoked = true;
121
+ }
122
+ return { success: true };
123
+ }
124
+ getEnvironment() {
125
+ const configPath = getGcloudConfigPath();
126
+ const env = { ...process.env };
127
+ env.CLOUDSDK_CONFIG = configPath;
128
+ env.CLOUDSDK_CORE_DISABLE_PROMPTS = "1";
129
+ return env;
130
+ }
131
+ }
132
+
133
+ // src/commands/logout/steps/ClearConfigStep.ts
134
+ import fs from "node:fs";
135
+
136
+ class ClearConfigStep {
137
+ id = "clear-config";
138
+ name = "Clear configuration directory";
139
+ async shouldRun(context) {
140
+ return context.input.clearConfig;
141
+ }
142
+ async run(context) {
143
+ context.ui.log(theme.gray("Clearing gcloud configuration directory..."));
144
+ const configPath = getGcloudConfigPath();
145
+ try {
146
+ if (fs.existsSync(configPath)) {
147
+ fs.rmSync(configPath, { recursive: true, force: true });
148
+ context.ui.log(theme.green(`${icons.success} Configuration directory cleared`));
149
+ context.configCleared = true;
150
+ } else {
151
+ context.ui.log(theme.gray("Configuration directory does not exist"));
152
+ context.configCleared = true;
153
+ }
154
+ } catch (error) {
155
+ context.ui.log(theme.yellow(`${icons.warning} Failed to clear configuration directory`));
156
+ context.ui.log(theme.gray(` ${error instanceof Error ? error.message : String(error)}`));
157
+ }
158
+ return { success: true };
159
+ }
160
+ }
161
+
162
+ // src/commands/logout/handler.ts
163
+ class LogoutHandler {
164
+ gcloudService;
165
+ steps;
166
+ constructor(gcloudService = new GcloudHandler) {
167
+ this.gcloudService = gcloudService;
168
+ this.steps = [
169
+ new PrepareStep,
170
+ new RevokeUserStep,
171
+ new RevokeAdcStep,
172
+ new ClearConfigStep
173
+ ];
174
+ }
175
+ async execute(input) {
176
+ const context = {
177
+ input,
178
+ ui: new ConsoleUI,
179
+ gcloudService: this.gcloudService,
180
+ userRevoked: false,
181
+ adcRevoked: false,
182
+ configCleared: false
183
+ };
184
+ console.log(`
185
+ ${theme.blue("Logout from Google Cloud")}
186
+ `);
187
+ try {
188
+ const { stoppedAt } = await runSteps(this.steps, context, {
189
+ onAfterStep: (_step, result) => {
190
+ if (!result.success && result.errorCode === "GCLOUD_NOT_FOUND")
191
+ return true;
192
+ if (result.shouldExit)
193
+ return true;
194
+ return false;
195
+ }
196
+ });
197
+ if (stoppedAt) {
198
+ if (stoppedAt.result.errorCode === "GCLOUD_NOT_FOUND") {
199
+ return {
200
+ success: false,
201
+ error: {
202
+ code: "GCLOUD_NOT_FOUND",
203
+ message: stoppedAt.result.error?.message || "Gcloud not found",
204
+ recoverable: true
205
+ }
206
+ };
207
+ }
208
+ return {
209
+ success: true,
210
+ data: {
211
+ userRevoked: context.userRevoked,
212
+ adcRevoked: context.adcRevoked,
213
+ configCleared: context.configCleared
214
+ }
215
+ };
216
+ }
217
+ console.log(`
218
+ ${theme.green("Successfully logged out!")}
219
+ `);
220
+ console.log(theme.gray("To log back in, run:"));
221
+ console.log(theme.cyan(` stitch-mcp init
222
+ `));
223
+ return {
224
+ success: true,
225
+ data: {
226
+ userRevoked: context.userRevoked,
227
+ adcRevoked: context.adcRevoked,
228
+ configCleared: context.configCleared
229
+ }
230
+ };
231
+ } catch (error) {
232
+ return {
233
+ success: false,
234
+ error: {
235
+ code: "UNKNOWN_ERROR",
236
+ message: error instanceof Error ? error.message : String(error),
237
+ recoverable: false
238
+ }
239
+ };
240
+ }
241
+ }
242
+ }
243
+ export {
244
+ LogoutHandler
245
+ };
246
+
247
+ //# debugId=7DEB3E4B3913ED0164756E2164756E21
@@ -0,0 +1,14 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/commands/logout/steps/PrepareStep.ts", "../src/commands/logout/steps/RevokeUserStep.ts", "../src/commands/logout/steps/RevokeAdcStep.ts", "../src/commands/logout/steps/ClearConfigStep.ts", "../src/commands/logout/handler.ts"],
4
+ "sourcesContent": [
5
+ "import { type CommandStep, type StepResult } from '../../../framework/CommandStep.js';\nimport { type LogoutContext } from '../context.js';\n\nexport class PrepareStep implements CommandStep<LogoutContext> {\n id = 'prepare';\n name = 'Preparation';\n\n async shouldRun(context: LogoutContext): Promise<boolean> {\n return true;\n }\n\n async run(context: LogoutContext): Promise<StepResult> {\n // Check for gcloud availability\n const result = await context.gcloudService.ensureInstalled({\n minVersion: '400.0.0',\n forceLocal: false,\n });\n\n if (!result.success) {\n return {\n success: false,\n error: new Error('Google Cloud CLI not found'),\n errorCode: 'GCLOUD_NOT_FOUND',\n shouldExit: true\n };\n }\n context.gcloudPath = result.data.path;\n\n if (!context.input.force) {\n const shouldLogout = await context.ui.promptConfirm(\n 'Are you sure you want to log out? This will revoke all credentials.',\n false\n );\n\n if (!shouldLogout) {\n context.ui.log('\\nLogout cancelled.\\n');\n return { success: true, shouldExit: true, detail: 'Cancelled' };\n }\n }\n\n return { success: true };\n }\n}\n",
6
+ "import { type CommandStep, type StepResult } from '../../../framework/CommandStep.js';\nimport { type LogoutContext } from '../context.js';\nimport { execCommand } from '../../../platform/shell.js';\nimport { theme, icons } from '../../../ui/theme.js';\nimport { getGcloudConfigPath } from '../../../platform/detector.js';\n\nexport class RevokeUserStep implements CommandStep<LogoutContext> {\n id = 'revoke-user';\n name = 'Revoke user authentication';\n\n async shouldRun(context: LogoutContext): Promise<boolean> {\n // If force is true, we might not have set gcloudPath yet in ConfirmStep\n if (!context.gcloudPath) {\n const result = await context.gcloudService.ensureInstalled({ minVersion: '400.0.0', forceLocal: false });\n if (result.success) context.gcloudPath = result.data.path;\n else return false;\n }\n return true;\n }\n\n async run(context: LogoutContext): Promise<StepResult> {\n const activeAccount = await context.gcloudService.getActiveAccount();\n\n if (activeAccount) {\n context.ui.log(theme.gray('Revoking user authentication...'));\n const userResult = await execCommand(\n [context.gcloudPath!, 'auth', 'revoke', '--all'],\n { env: this.getEnvironment() }\n );\n\n if (userResult.success || userResult.stderr?.includes('No credentialed accounts')) {\n context.ui.log(theme.green(`${icons.success} User authentication revoked`));\n context.userRevoked = true;\n } else {\n context.ui.log(theme.yellow(`${icons.warning} Failed to revoke user authentication`));\n }\n } else {\n context.ui.log(theme.gray('No active user authentication found'));\n context.userRevoked = true;\n }\n\n return { success: true };\n }\n\n private getEnvironment(): Record<string, string> {\n const configPath = getGcloudConfigPath();\n const env: Record<string, string> = { ...process.env as Record<string, string> };\n env.CLOUDSDK_CONFIG = configPath;\n env.CLOUDSDK_CORE_DISABLE_PROMPTS = '1';\n return env;\n }\n}\n",
7
+ "import { type CommandStep, type StepResult } from '../../../framework/CommandStep.js';\nimport { type LogoutContext } from '../context.js';\nimport { execCommand } from '../../../platform/shell.js';\nimport { theme, icons } from '../../../ui/theme.js';\nimport { getGcloudConfigPath } from '../../../platform/detector.js';\n\nexport class RevokeAdcStep implements CommandStep<LogoutContext> {\n id = 'revoke-adc';\n name = 'Revoke Application Default Credentials';\n\n async shouldRun(context: LogoutContext): Promise<boolean> {\n if (!context.gcloudPath) {\n const result = await context.gcloudService.ensureInstalled({ minVersion: '400.0.0', forceLocal: false });\n if (result.success) context.gcloudPath = result.data.path;\n else return false;\n }\n return true;\n }\n\n async run(context: LogoutContext): Promise<StepResult> {\n const hasADC = await context.gcloudService.hasADC();\n if (hasADC) {\n context.ui.log(theme.gray('Revoking Application Default Credentials...'));\n const adcResult = await execCommand(\n [context.gcloudPath!, 'auth', 'application-default', 'revoke'],\n { env: this.getEnvironment() }\n );\n\n if (adcResult.success || adcResult.stderr?.includes('No credentials')) {\n context.ui.log(theme.green(`${icons.success} Application Default Credentials revoked`));\n context.adcRevoked = true;\n } else {\n context.ui.log(theme.yellow(`${icons.warning} Failed to revoke Application Default Credentials`));\n }\n } else {\n context.ui.log(theme.gray('No Application Default Credentials found'));\n context.adcRevoked = true;\n }\n return { success: true };\n }\n\n private getEnvironment(): Record<string, string> {\n const configPath = getGcloudConfigPath();\n const env: Record<string, string> = { ...process.env as Record<string, string> };\n env.CLOUDSDK_CONFIG = configPath;\n env.CLOUDSDK_CORE_DISABLE_PROMPTS = '1';\n return env;\n }\n}\n",
8
+ "import { type CommandStep, type StepResult } from '../../../framework/CommandStep.js';\nimport { type LogoutContext } from '../context.js';\nimport { theme, icons } from '../../../ui/theme.js';\nimport { getGcloudConfigPath } from '../../../platform/detector.js';\nimport fs from 'node:fs';\n\nexport class ClearConfigStep implements CommandStep<LogoutContext> {\n id = 'clear-config';\n name = 'Clear configuration directory';\n\n async shouldRun(context: LogoutContext): Promise<boolean> {\n return context.input.clearConfig;\n }\n\n async run(context: LogoutContext): Promise<StepResult> {\n context.ui.log(theme.gray('Clearing gcloud configuration directory...'));\n const configPath = getGcloudConfigPath();\n\n try {\n if (fs.existsSync(configPath)) {\n fs.rmSync(configPath, { recursive: true, force: true });\n context.ui.log(theme.green(`${icons.success} Configuration directory cleared`));\n context.configCleared = true;\n } else {\n context.ui.log(theme.gray('Configuration directory does not exist'));\n context.configCleared = true;\n }\n } catch (error) {\n context.ui.log(theme.yellow(`${icons.warning} Failed to clear configuration directory`));\n context.ui.log(theme.gray(` ${error instanceof Error ? error.message : String(error)}`));\n }\n return { success: true };\n }\n}\n",
9
+ "import { type LogoutCommand, type LogoutInput, type LogoutResult } from './spec.js';\nimport { GcloudHandler } from '../../services/gcloud/handler.js';\nimport { type GcloudService } from '../../services/gcloud/spec.js';\nimport { theme } from '../../ui/theme.js';\nimport { ConsoleUI } from '../../framework/ConsoleUI.js';\nimport { type LogoutContext } from './context.js';\nimport { type CommandStep } from '../../framework/CommandStep.js';\nimport { runSteps } from '../../framework/StepRunner.js';\n\nimport { PrepareStep } from './steps/PrepareStep.js';\nimport { RevokeUserStep } from './steps/RevokeUserStep.js';\nimport { RevokeAdcStep } from './steps/RevokeAdcStep.js';\nimport { ClearConfigStep } from './steps/ClearConfigStep.js';\n\nexport class LogoutHandler implements LogoutCommand {\n private steps: CommandStep<LogoutContext>[];\n\n constructor(private readonly gcloudService: GcloudService = new GcloudHandler()) {\n this.steps = [\n new PrepareStep(),\n new RevokeUserStep(),\n new RevokeAdcStep(),\n new ClearConfigStep(),\n ];\n }\n\n async execute(input: LogoutInput): Promise<LogoutResult> {\n const context: LogoutContext = {\n input,\n ui: new ConsoleUI(),\n gcloudService: this.gcloudService,\n userRevoked: false,\n adcRevoked: false,\n configCleared: false,\n };\n\n console.log(`\\n${theme.blue('Logout from Google Cloud')}\\n`);\n\n try {\n const { stoppedAt } = await runSteps(this.steps, context, {\n onAfterStep: (_step, result) => {\n if (!result.success && result.errorCode === 'GCLOUD_NOT_FOUND') return true;\n if (result.shouldExit) return true;\n return false;\n },\n });\n\n if (stoppedAt) {\n if (stoppedAt.result.errorCode === 'GCLOUD_NOT_FOUND') {\n return {\n success: false,\n error: {\n code: 'GCLOUD_NOT_FOUND',\n message: stoppedAt.result.error?.message || 'Gcloud not found',\n recoverable: true,\n },\n };\n }\n // shouldExit case — successful early exit\n return {\n success: true,\n data: {\n userRevoked: context.userRevoked,\n adcRevoked: context.adcRevoked,\n configCleared: context.configCleared,\n },\n };\n }\n\n console.log(`\\n${theme.green('Successfully logged out!')}\\n`);\n console.log(theme.gray('To log back in, run:'));\n console.log(theme.cyan(' stitch-mcp init\\n'));\n\n return {\n success: true,\n data: {\n userRevoked: context.userRevoked,\n adcRevoked: context.adcRevoked,\n configCleared: context.configCleared,\n },\n };\n\n } catch (error) {\n return {\n success: false,\n error: {\n code: 'UNKNOWN_ERROR',\n message: error instanceof Error ? error.message : String(error),\n recoverable: false,\n },\n };\n }\n }\n}\n"
10
+ ],
11
+ "mappings": "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",
12
+ "debugId": "7DEB3E4B3913ED0164756E2164756E21",
13
+ "names": []
14
+ }
@@ -0,0 +1,273 @@
1
+ import {
2
+ openUrl,
3
+ require_jsx_dev_runtime
4
+ } from "./chunk-krfqppg2.js";
5
+ import {
6
+ StitchViteServer
7
+ } from "./chunk-k4xwb3wp.js";
8
+ import"./chunk-abf1r0jh.js";
9
+ import {
10
+ Box_default,
11
+ Text,
12
+ use_app_default,
13
+ use_input_default
14
+ } from "./chunk-7y4xzvkz.js";
15
+ import {
16
+ require_react
17
+ } from "./chunk-4jwmvjb4.js";
18
+ import {
19
+ downloadText
20
+ } from "./chunk-34w2wfyp.js";
21
+ import {
22
+ clipboardy_default
23
+ } from "./chunk-akd997ec.js";
24
+ import"./chunk-q6sv0243.js";
25
+ import"./chunk-4jygt4d6.js";
26
+ import"./chunk-tz7wnw4s.js";
27
+ import"./chunk-3sfn889r.js";
28
+ import {
29
+ __toESM
30
+ } from "./chunk-9wyra8hs.js";
31
+
32
+ // src/commands/screens/ScreensView.tsx
33
+ var import_react = __toESM(require_react(), 1);
34
+ var jsx_dev_runtime = __toESM(require_jsx_dev_runtime(), 1);
35
+ function ScreensView({ projectId, projectTitle, screens }) {
36
+ const { exit } = use_app_default();
37
+ const [selectedIndex, setSelectedIndex] = import_react.useState(0);
38
+ const [windowStart, setWindowStart] = import_react.useState(0);
39
+ const [status, setStatus] = import_react.useState("");
40
+ const [serverUrl, setServerUrl] = import_react.useState(null);
41
+ const serverRef = import_react.useRef(null);
42
+ const VIEW_HEIGHT = 10;
43
+ import_react.default.useEffect(() => {
44
+ if (selectedIndex < windowStart) {
45
+ setWindowStart(selectedIndex);
46
+ } else if (selectedIndex >= windowStart + VIEW_HEIGHT) {
47
+ setWindowStart(selectedIndex - VIEW_HEIGHT + 1);
48
+ }
49
+ }, [selectedIndex, windowStart, VIEW_HEIGHT]);
50
+ import_react.useEffect(() => {
51
+ return () => {
52
+ if (serverRef.current)
53
+ serverRef.current.stop();
54
+ };
55
+ }, []);
56
+ async function serveScreen(screen) {
57
+ if (!screen.hasCode || !screen.codeUrl) {
58
+ setStatus("No HTML to serve");
59
+ return;
60
+ }
61
+ setStatus("Preparing server...");
62
+ let srv = serverRef.current;
63
+ let url = serverUrl;
64
+ let justStarted = false;
65
+ if (!srv) {
66
+ srv = new StitchViteServer;
67
+ url = await srv.start(0);
68
+ serverRef.current = srv;
69
+ setServerUrl(url);
70
+ justStarted = true;
71
+ }
72
+ if (!url)
73
+ return;
74
+ try {
75
+ const html = await downloadText(screen.codeUrl);
76
+ const route = `/screens/${screen.screenId}`;
77
+ srv.mount(route, html);
78
+ const fullUrl = `${url}${route}`;
79
+ if (justStarted) {
80
+ openUrl(fullUrl);
81
+ } else {
82
+ srv.navigate(fullUrl);
83
+ }
84
+ setStatus(`Serving at ${fullUrl}`);
85
+ } catch (e) {
86
+ setStatus("Error serving screen");
87
+ }
88
+ }
89
+ use_input_default((input, key) => {
90
+ if (input === "q") {
91
+ exit();
92
+ return;
93
+ }
94
+ if (key.upArrow || input === "k") {
95
+ setSelectedIndex((prev) => Math.max(0, prev - 1));
96
+ setStatus("");
97
+ }
98
+ if (key.downArrow || input === "j") {
99
+ setSelectedIndex((prev) => Math.min(screens.length - 1, prev + 1));
100
+ setStatus("");
101
+ }
102
+ if (input === "c") {
103
+ const screen = screens[selectedIndex];
104
+ if (screen?.hasCode && screen.codeUrl) {
105
+ setStatus("Copying...");
106
+ downloadText(screen.codeUrl).then((code) => {
107
+ clipboardy_default.write(code);
108
+ setStatus("HTML copied!");
109
+ }).catch(() => setStatus("Failed to copy"));
110
+ } else {
111
+ setStatus("No HTML available");
112
+ }
113
+ }
114
+ if (input === "i") {
115
+ const screen = screens[selectedIndex];
116
+ if (screen?.hasImage) {
117
+ setStatus("Image copy not implemented");
118
+ } else {
119
+ setStatus("No image available");
120
+ }
121
+ }
122
+ if (input === "s") {
123
+ const screen = screens[selectedIndex];
124
+ if (screen) {
125
+ serveScreen(screen);
126
+ }
127
+ }
128
+ });
129
+ const visibleScreens = screens.slice(windowStart, windowStart + VIEW_HEIGHT);
130
+ return /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
131
+ flexDirection: "column",
132
+ padding: 1,
133
+ children: [
134
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
135
+ bold: true,
136
+ children: [
137
+ projectTitle,
138
+ " (",
139
+ screens.length,
140
+ " screens)"
141
+ ]
142
+ }, undefined, true, undefined, this),
143
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
144
+ dimColor: true,
145
+ children: [
146
+ "projectId: ",
147
+ projectId
148
+ ]
149
+ }, undefined, true, undefined, this),
150
+ serverUrl && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
151
+ dimColor: true,
152
+ children: [
153
+ "Server: ",
154
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
155
+ color: "green",
156
+ children: serverUrl
157
+ }, undefined, false, undefined, this)
158
+ ]
159
+ }, undefined, true, undefined, this),
160
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
161
+ children: " "
162
+ }, undefined, false, undefined, this),
163
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
164
+ flexDirection: "column",
165
+ borderStyle: "single",
166
+ borderColor: "yellow",
167
+ paddingX: 1,
168
+ children: [
169
+ windowStart > 0 && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
170
+ dimColor: true,
171
+ children: [
172
+ "... ",
173
+ windowStart,
174
+ " more above ..."
175
+ ]
176
+ }, undefined, true, undefined, this),
177
+ visibleScreens.map((screen, index) => {
178
+ const absoluteIndex = windowStart + index;
179
+ const isSelected = absoluteIndex === selectedIndex;
180
+ const num = String(absoluteIndex + 1).padStart(2, " ");
181
+ const selector = isSelected ? "▸" : " ";
182
+ return /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
183
+ flexDirection: "column",
184
+ children: [
185
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
186
+ justifyContent: "space-between",
187
+ children: [
188
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
189
+ children: [
190
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
191
+ dimColor: true,
192
+ children: num
193
+ }, undefined, false, undefined, this),
194
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
195
+ color: isSelected ? "cyan" : undefined,
196
+ children: [
197
+ " ",
198
+ selector,
199
+ " "
200
+ ]
201
+ }, undefined, true, undefined, this),
202
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
203
+ color: isSelected ? "cyan" : undefined,
204
+ bold: isSelected,
205
+ children: screen.title.slice(0, 28)
206
+ }, undefined, false, undefined, this)
207
+ ]
208
+ }, undefined, true, undefined, this),
209
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
210
+ children: [
211
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
212
+ dimColor: true,
213
+ children: "html"
214
+ }, undefined, false, undefined, this),
215
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
216
+ color: screen.hasCode ? "green" : "gray",
217
+ children: screen.hasCode ? "[✓]" : "[ ]"
218
+ }, undefined, false, undefined, this),
219
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
220
+ children: " "
221
+ }, undefined, false, undefined, this),
222
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
223
+ dimColor: true,
224
+ children: "img"
225
+ }, undefined, false, undefined, this),
226
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
227
+ color: screen.hasImage ? "green" : "gray",
228
+ children: screen.hasImage ? "[✓]" : "[ ]"
229
+ }, undefined, false, undefined, this)
230
+ ]
231
+ }, undefined, true, undefined, this)
232
+ ]
233
+ }, undefined, true, undefined, this),
234
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
235
+ dimColor: true,
236
+ color: "gray",
237
+ children: [
238
+ " screenId: ",
239
+ screen.screenId
240
+ ]
241
+ }, undefined, true, undefined, this),
242
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
243
+ children: " "
244
+ }, undefined, false, undefined, this)
245
+ ]
246
+ }, screen.screenId, true, undefined, this);
247
+ }),
248
+ windowStart + VIEW_HEIGHT < screens.length && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
249
+ dimColor: true,
250
+ children: [
251
+ "... ",
252
+ screens.length - (windowStart + VIEW_HEIGHT),
253
+ " more below ..."
254
+ ]
255
+ }, undefined, true, undefined, this)
256
+ ]
257
+ }, undefined, true, undefined, this),
258
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
259
+ dimColor: true,
260
+ children: "[c]opy html [i]mage [s]erve [q]uit"
261
+ }, undefined, false, undefined, this),
262
+ status && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
263
+ color: "yellow",
264
+ children: status
265
+ }, undefined, false, undefined, this)
266
+ ]
267
+ }, undefined, true, undefined, this);
268
+ }
269
+ export {
270
+ ScreensView
271
+ };
272
+
273
+ //# debugId=A890852E888CB14764756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/commands/screens/ScreensView.tsx"],
4
+ "sourcesContent": [
5
+ "import React, { useState, useEffect, useRef } from 'react';\nimport { Box, Text, useInput, useApp } from 'ink';\nimport { downloadText } from '../../ui/copy-behaviors/clipboard.js';\nimport clipboard from 'clipboardy';\nimport { StitchViteServer } from '../../lib/server/vite/StitchViteServer.js';\nimport { openUrl } from '../../platform/browser.js';\n\ninterface Screen {\n screenId: string;\n title: string;\n hasCode: boolean;\n codeUrl: string | null;\n hasImage: boolean;\n}\n\ninterface ScreensViewProps {\n projectId: string;\n projectTitle: string;\n screens: Screen[];\n}\n\nexport function ScreensView({ projectId, projectTitle, screens }: ScreensViewProps) {\n const { exit } = useApp();\n const [selectedIndex, setSelectedIndex] = useState(0);\n const [windowStart, setWindowStart] = useState(0);\n const [status, setStatus] = useState('');\n const [serverUrl, setServerUrl] = useState<string | null>(null);\n\n const serverRef = useRef<StitchViteServer | null>(null);\n\n const VIEW_HEIGHT = 10;\n\n // Helper to sync window with selection\n React.useEffect(() => {\n if (selectedIndex < windowStart) {\n setWindowStart(selectedIndex);\n } else if (selectedIndex >= windowStart + VIEW_HEIGHT) {\n setWindowStart(selectedIndex - VIEW_HEIGHT + 1);\n }\n }, [selectedIndex, windowStart, VIEW_HEIGHT]);\n\n useEffect(() => {\n return () => {\n if (serverRef.current) serverRef.current.stop();\n };\n }, []);\n\n async function serveScreen(screen: Screen) {\n if (!screen.hasCode || !screen.codeUrl) {\n setStatus('No HTML to serve');\n return;\n }\n\n setStatus('Preparing server...');\n let srv = serverRef.current;\n let url = serverUrl;\n let justStarted = false;\n\n if (!srv) {\n srv = new StitchViteServer();\n url = await srv.start(0);\n serverRef.current = srv;\n setServerUrl(url);\n justStarted = true;\n }\n\n if (!url) return; // Should not happen\n\n try {\n const html = await downloadText(screen.codeUrl);\n const route = `/screens/${screen.screenId}`;\n srv.mount(route, html);\n\n const fullUrl = `${url}${route}`;\n\n if (justStarted) {\n openUrl(fullUrl);\n } else {\n srv.navigate(fullUrl);\n }\n setStatus(`Serving at ${fullUrl}`);\n } catch (e) {\n setStatus('Error serving screen');\n }\n }\n\n useInput((input, key) => {\n if (input === 'q') {\n exit();\n return;\n }\n\n if (key.upArrow || input === 'k') {\n setSelectedIndex(prev => Math.max(0, prev - 1));\n setStatus('');\n }\n\n if (key.downArrow || input === 'j') {\n setSelectedIndex(prev => Math.min(screens.length - 1, prev + 1));\n setStatus('');\n }\n\n // Copy code\n if (input === 'c') {\n const screen = screens[selectedIndex];\n if (screen?.hasCode && screen.codeUrl) {\n setStatus('Copying...');\n downloadText(screen.codeUrl)\n .then(code => {\n clipboard.write(code);\n setStatus('HTML copied!');\n })\n .catch(() => setStatus('Failed to copy'));\n } else {\n setStatus('No HTML available');\n }\n }\n\n // Copy image (placeholder)\n if (input === 'i') {\n const screen = screens[selectedIndex];\n if (screen?.hasImage) {\n setStatus('Image copy not implemented');\n } else {\n setStatus('No image available');\n }\n }\n\n // Serve\n if (input === 's') {\n const screen = screens[selectedIndex];\n if (screen) {\n serveScreen(screen);\n }\n }\n });\n\n const visibleScreens = screens.slice(windowStart, windowStart + VIEW_HEIGHT);\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n {/* Header */}\n <Text bold>{projectTitle} ({screens.length} screens)</Text>\n <Text dimColor>projectId: {projectId}</Text>\n {serverUrl && <Text dimColor>Server: <Text color=\"green\">{serverUrl}</Text></Text>}\n <Text> </Text>\n\n {/* Screen List */}\n <Box flexDirection=\"column\" borderStyle=\"single\" borderColor=\"yellow\" paddingX={1}>\n {windowStart > 0 && <Text dimColor>... {windowStart} more above ...</Text>}\n\n {visibleScreens.map((screen, index) => {\n // Adjust index for absolute position\n const absoluteIndex = windowStart + index;\n const isSelected = absoluteIndex === selectedIndex;\n const num = String(absoluteIndex + 1).padStart(2, ' ');\n const selector = isSelected ? '▸' : ' ';\n\n return (\n <Box key={screen.screenId} flexDirection=\"column\">\n {/* Row 1: Title + Checkboxes */}\n <Box justifyContent=\"space-between\">\n <Box>\n <Text dimColor>{num}</Text>\n <Text color={isSelected ? 'cyan' : undefined}> {selector} </Text>\n <Text color={isSelected ? 'cyan' : undefined} bold={isSelected}>\n {screen.title.slice(0, 28)}\n </Text>\n </Box>\n <Box>\n <Text dimColor>html</Text>\n <Text color={screen.hasCode ? 'green' : 'gray'}>\n {screen.hasCode ? '[✓]' : '[ ]'}\n </Text>\n <Text> </Text>\n <Text dimColor>img</Text>\n <Text color={screen.hasImage ? 'green' : 'gray'}>\n {screen.hasImage ? '[✓]' : '[ ]'}\n </Text>\n </Box>\n </Box>\n {/* Row 2: screenId */}\n <Text dimColor color=\"gray\"> screenId: {screen.screenId}</Text>\n <Text> </Text>\n </Box>\n );\n })}\n\n {windowStart + VIEW_HEIGHT < screens.length && (\n <Text dimColor>... {screens.length - (windowStart + VIEW_HEIGHT)} more below ...</Text>\n )}\n </Box>\n\n {/* Footer */}\n <Text dimColor>[c]opy html [i]mage [s]erve [q]uit</Text>\n {status && <Text color=\"yellow\">{status}</Text>}\n </Box>\n );\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "A890852E888CB14764756E2164756E21",
9
+ "names": []
10
+ }