@vizzly-testing/cli 0.13.4 → 0.15.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 (143) hide show
  1. package/dist/cli.js +68 -68
  2. package/dist/commands/doctor.js +30 -34
  3. package/dist/commands/finalize.js +24 -23
  4. package/dist/commands/init.js +30 -28
  5. package/dist/commands/login.js +49 -55
  6. package/dist/commands/logout.js +14 -19
  7. package/dist/commands/project.js +83 -103
  8. package/dist/commands/run.js +77 -89
  9. package/dist/commands/status.js +48 -49
  10. package/dist/commands/tdd-daemon.js +90 -86
  11. package/dist/commands/tdd.js +59 -88
  12. package/dist/commands/upload.js +57 -57
  13. package/dist/commands/whoami.js +40 -45
  14. package/dist/index.js +2 -5
  15. package/dist/plugin-loader.js +15 -17
  16. package/dist/reporter/reporter-bundle.css +1 -1
  17. package/dist/reporter/reporter-bundle.iife.js +78 -32
  18. package/dist/sdk/index.js +36 -45
  19. package/dist/server/handlers/api-handler.js +14 -15
  20. package/dist/server/handlers/tdd-handler.js +34 -37
  21. package/dist/server/http-server.js +75 -869
  22. package/dist/server/middleware/cors.js +22 -0
  23. package/dist/server/middleware/json-parser.js +35 -0
  24. package/dist/server/middleware/response.js +79 -0
  25. package/dist/server/routers/assets.js +91 -0
  26. package/dist/server/routers/auth.js +144 -0
  27. package/dist/server/routers/baseline.js +163 -0
  28. package/dist/server/routers/cloud-proxy.js +146 -0
  29. package/dist/server/routers/config.js +126 -0
  30. package/dist/server/routers/dashboard.js +130 -0
  31. package/dist/server/routers/health.js +61 -0
  32. package/dist/server/routers/projects.js +168 -0
  33. package/dist/server/routers/screenshot.js +86 -0
  34. package/dist/services/auth-service.js +1 -1
  35. package/dist/services/build-manager.js +13 -40
  36. package/dist/services/config-service.js +2 -4
  37. package/dist/services/html-report-generator.js +6 -5
  38. package/dist/services/index.js +64 -0
  39. package/dist/services/project-service.js +121 -40
  40. package/dist/services/screenshot-server.js +9 -9
  41. package/dist/services/server-manager.js +11 -18
  42. package/dist/services/static-report-generator.js +3 -4
  43. package/dist/services/tdd-service.js +246 -103
  44. package/dist/services/test-runner.js +24 -25
  45. package/dist/services/uploader.js +5 -4
  46. package/dist/types/commands/init.d.ts +1 -2
  47. package/dist/types/index.d.ts +2 -3
  48. package/dist/types/plugin-loader.d.ts +1 -2
  49. package/dist/types/reporter/src/api/client.d.ts +178 -0
  50. package/dist/types/reporter/src/components/app-router.d.ts +1 -3
  51. package/dist/types/reporter/src/components/code-block.d.ts +4 -0
  52. package/dist/types/reporter/src/components/comparison/comparison-modes/onion-skin-mode.d.ts +10 -0
  53. package/dist/types/reporter/src/components/comparison/comparison-modes/overlay-mode.d.ts +11 -0
  54. package/dist/types/reporter/src/components/comparison/comparison-modes/shared/base-comparison-mode.d.ts +14 -0
  55. package/dist/types/reporter/src/components/comparison/comparison-modes/shared/image-renderer.d.ts +30 -0
  56. package/dist/types/reporter/src/components/comparison/comparison-modes/toggle-view.d.ts +8 -0
  57. package/dist/types/reporter/src/components/comparison/comparison-viewer.d.ts +4 -0
  58. package/dist/types/reporter/src/components/comparison/fullscreen-viewer.d.ts +13 -0
  59. package/dist/types/reporter/src/components/comparison/screenshot-display.d.ts +16 -0
  60. package/dist/types/reporter/src/components/comparison/screenshot-list.d.ts +9 -0
  61. package/dist/types/reporter/src/components/comparison/variant-selector.d.ts +1 -1
  62. package/dist/types/reporter/src/components/design-system/alert.d.ts +9 -0
  63. package/dist/types/reporter/src/components/design-system/badge.d.ts +17 -0
  64. package/dist/types/reporter/src/components/design-system/button.d.ts +19 -0
  65. package/dist/types/reporter/src/components/design-system/card.d.ts +31 -0
  66. package/dist/types/reporter/src/components/design-system/empty-state.d.ts +13 -0
  67. package/dist/types/reporter/src/components/design-system/form-controls.d.ts +44 -0
  68. package/dist/types/reporter/src/components/design-system/health-ring.d.ts +7 -0
  69. package/dist/types/reporter/src/components/design-system/index.d.ts +11 -0
  70. package/dist/types/reporter/src/components/design-system/modal.d.ts +10 -0
  71. package/dist/types/reporter/src/components/design-system/skeleton.d.ts +19 -0
  72. package/dist/types/reporter/src/components/design-system/spinner.d.ts +10 -0
  73. package/dist/types/reporter/src/components/design-system/tabs.d.ts +13 -0
  74. package/dist/types/reporter/src/components/layout/header.d.ts +5 -0
  75. package/dist/types/reporter/src/components/layout/index.d.ts +2 -0
  76. package/dist/types/reporter/src/components/layout/layout.d.ts +6 -0
  77. package/dist/types/reporter/src/components/views/builds-view.d.ts +1 -0
  78. package/dist/types/reporter/src/components/views/comparison-detail-view.d.ts +5 -0
  79. package/dist/types/reporter/src/components/views/comparisons-view.d.ts +5 -6
  80. package/dist/types/reporter/src/components/views/stats-view.d.ts +1 -6
  81. package/dist/types/reporter/src/components/waiting-for-screenshots.d.ts +1 -0
  82. package/dist/types/reporter/src/hooks/queries/use-auth-queries.d.ts +15 -0
  83. package/dist/types/reporter/src/hooks/queries/use-cloud-queries.d.ts +6 -0
  84. package/dist/types/reporter/src/hooks/queries/use-config-queries.d.ts +6 -0
  85. package/dist/types/reporter/src/hooks/queries/use-tdd-queries.d.ts +9 -0
  86. package/dist/types/reporter/src/lib/query-client.d.ts +2 -0
  87. package/dist/types/reporter/src/lib/query-keys.d.ts +13 -0
  88. package/dist/types/sdk/index.d.ts +2 -4
  89. package/dist/types/server/handlers/tdd-handler.d.ts +2 -0
  90. package/dist/types/server/http-server.d.ts +1 -1
  91. package/dist/types/server/middleware/cors.d.ts +11 -0
  92. package/dist/types/server/middleware/json-parser.d.ts +10 -0
  93. package/dist/types/server/middleware/response.d.ts +50 -0
  94. package/dist/types/server/routers/assets.d.ts +6 -0
  95. package/dist/types/server/routers/auth.d.ts +9 -0
  96. package/dist/types/server/routers/baseline.d.ts +13 -0
  97. package/dist/types/server/routers/cloud-proxy.d.ts +11 -0
  98. package/dist/types/server/routers/config.d.ts +9 -0
  99. package/dist/types/server/routers/dashboard.d.ts +6 -0
  100. package/dist/types/server/routers/health.d.ts +11 -0
  101. package/dist/types/server/routers/projects.d.ts +9 -0
  102. package/dist/types/server/routers/screenshot.d.ts +11 -0
  103. package/dist/types/services/build-manager.d.ts +4 -3
  104. package/dist/types/services/config-service.d.ts +2 -3
  105. package/dist/types/services/index.d.ts +7 -0
  106. package/dist/types/services/project-service.d.ts +6 -4
  107. package/dist/types/services/screenshot-server.d.ts +5 -5
  108. package/dist/types/services/server-manager.d.ts +5 -3
  109. package/dist/types/services/tdd-service.d.ts +12 -1
  110. package/dist/types/services/test-runner.d.ts +3 -3
  111. package/dist/types/utils/output.d.ts +84 -0
  112. package/dist/utils/config-loader.js +24 -48
  113. package/dist/utils/global-config.js +2 -17
  114. package/dist/utils/output.js +445 -0
  115. package/dist/utils/security.js +3 -4
  116. package/docs/api-reference.md +0 -1
  117. package/docs/plugins.md +22 -22
  118. package/package.json +3 -2
  119. package/dist/container/index.js +0 -215
  120. package/dist/services/base-service.js +0 -154
  121. package/dist/types/container/index.d.ts +0 -59
  122. package/dist/types/reporter/src/components/comparison/viewer-modes/onion-viewer.d.ts +0 -3
  123. package/dist/types/reporter/src/components/comparison/viewer-modes/overlay-viewer.d.ts +0 -3
  124. package/dist/types/reporter/src/components/comparison/viewer-modes/side-by-side-viewer.d.ts +0 -3
  125. package/dist/types/reporter/src/components/comparison/viewer-modes/toggle-viewer.d.ts +0 -3
  126. package/dist/types/reporter/src/components/dashboard/dashboard-header.d.ts +0 -5
  127. package/dist/types/reporter/src/components/dashboard/dashboard-stats.d.ts +0 -4
  128. package/dist/types/reporter/src/components/dashboard/empty-state.d.ts +0 -8
  129. package/dist/types/reporter/src/components/ui/form-field.d.ts +0 -16
  130. package/dist/types/reporter/src/components/ui/status-badge.d.ts +0 -5
  131. package/dist/types/reporter/src/hooks/use-auth.d.ts +0 -10
  132. package/dist/types/reporter/src/hooks/use-baseline-actions.d.ts +0 -5
  133. package/dist/types/reporter/src/hooks/use-config.d.ts +0 -9
  134. package/dist/types/reporter/src/hooks/use-projects.d.ts +0 -10
  135. package/dist/types/reporter/src/hooks/use-report-data.d.ts +0 -7
  136. package/dist/types/reporter/src/hooks/use-vizzly-api.d.ts +0 -9
  137. package/dist/types/services/base-service.d.ts +0 -71
  138. package/dist/types/utils/console-ui.d.ts +0 -61
  139. package/dist/types/utils/logger-factory.d.ts +0 -26
  140. package/dist/types/utils/logger.d.ts +0 -79
  141. package/dist/utils/console-ui.js +0 -241
  142. package/dist/utils/logger-factory.js +0 -76
  143. package/dist/utils/logger.js +0 -231
@@ -3,7 +3,7 @@
3
3
  * Select, list, and manage project tokens
4
4
  */
5
5
 
6
- import { ConsoleUI } from '../utils/console-ui.js';
6
+ import * as output from '../utils/output.js';
7
7
  import { AuthService } from '../services/auth-service.js';
8
8
  import { getApiUrl } from '../utils/environment-config.js';
9
9
  import { getAuthTokens, saveProjectMapping, getProjectMapping, getProjectMappings, deleteProjectMapping } from '../utils/global-config.js';
@@ -16,7 +16,7 @@ import readline from 'readline';
16
16
  * @param {Object} globalOptions - Global CLI options
17
17
  */
18
18
  export async function projectSelectCommand(options = {}, globalOptions = {}) {
19
- let ui = new ConsoleUI({
19
+ output.configure({
20
20
  json: globalOptions.json,
21
21
  verbose: globalOptions.verbose,
22
22
  color: !globalOptions.noColor
@@ -25,9 +25,9 @@ export async function projectSelectCommand(options = {}, globalOptions = {}) {
25
25
  // Check authentication
26
26
  let auth = await getAuthTokens();
27
27
  if (!auth || !auth.accessToken) {
28
- ui.error('Not authenticated', null, 0);
29
- console.log(''); // Empty line for spacing
30
- ui.info('Run "vizzly login" to authenticate first');
28
+ output.error('Not authenticated');
29
+ output.blank();
30
+ output.info('Run "vizzly login" to authenticate first');
31
31
  process.exit(1);
32
32
  }
33
33
  let authService = new AuthService({
@@ -35,61 +35,59 @@ export async function projectSelectCommand(options = {}, globalOptions = {}) {
35
35
  });
36
36
 
37
37
  // Get user info to show organizations
38
- ui.startSpinner('Fetching organizations...');
38
+ output.startSpinner('Fetching organizations...');
39
39
  let userInfo = await authService.whoami();
40
- ui.stopSpinner();
40
+ output.stopSpinner();
41
41
  if (!userInfo.organizations || userInfo.organizations.length === 0) {
42
- ui.error('No organizations found', null, 0);
43
- console.log(''); // Empty line for spacing
44
- ui.info('Create an organization at https://vizzly.dev');
42
+ output.error('No organizations found');
43
+ output.blank();
44
+ output.info('Create an organization at https://vizzly.dev');
45
45
  process.exit(1);
46
46
  }
47
47
 
48
48
  // Select organization
49
- console.log(''); // Empty line for spacing
50
- ui.info('Select an organization:');
51
- console.log(''); // Empty line for spacing
52
-
49
+ output.blank();
50
+ output.info('Select an organization:');
51
+ output.blank();
53
52
  userInfo.organizations.forEach((org, index) => {
54
- console.log(` ${index + 1}. ${org.name} (@${org.slug})`);
53
+ output.print(` ${index + 1}. ${org.name} (@${org.slug})`);
55
54
  });
56
- console.log(''); // Empty line for spacing
55
+ output.blank();
57
56
  let orgChoice = await promptNumber('Enter number', 1, userInfo.organizations.length);
58
57
  let selectedOrg = userInfo.organizations[orgChoice - 1];
59
58
 
60
59
  // List projects for organization
61
- ui.startSpinner(`Fetching projects for ${selectedOrg.name}...`);
60
+ output.startSpinner(`Fetching projects for ${selectedOrg.name}...`);
62
61
  let response = await makeAuthenticatedRequest(`${options.apiUrl || getApiUrl()}/api/project`, {
63
62
  headers: {
64
63
  Authorization: `Bearer ${auth.accessToken}`,
65
64
  'X-Organization': selectedOrg.slug
66
65
  }
67
66
  });
68
- ui.stopSpinner();
67
+ output.stopSpinner();
69
68
 
70
69
  // Handle both array response and object with projects property
71
70
  let projects = Array.isArray(response) ? response : response.projects || [];
72
71
  if (projects.length === 0) {
73
- ui.error('No projects found', null, 0);
74
- console.log(''); // Empty line for spacing
75
- ui.info(`Create a project in ${selectedOrg.name} at https://vizzly.dev`);
72
+ output.error('No projects found');
73
+ output.blank();
74
+ output.info(`Create a project in ${selectedOrg.name} at https://vizzly.dev`);
76
75
  process.exit(1);
77
76
  }
78
77
 
79
78
  // Select project
80
- console.log(''); // Empty line for spacing
81
- ui.info('Select a project:');
82
- console.log(''); // Empty line for spacing
83
-
79
+ output.blank();
80
+ output.info('Select a project:');
81
+ output.blank();
84
82
  projects.forEach((project, index) => {
85
- console.log(` ${index + 1}. ${project.name} (${project.slug})`);
83
+ output.print(` ${index + 1}. ${project.name} (${project.slug})`);
86
84
  });
87
- console.log(''); // Empty line for spacing
85
+ output.blank();
88
86
  let projectChoice = await promptNumber('Enter number', 1, projects.length);
89
87
  let selectedProject = projects[projectChoice - 1];
90
88
 
91
89
  // Create API token for project
92
- ui.startSpinner(`Creating API token for ${selectedProject.name}...`);
90
+ output.startSpinner(`Creating API token for ${selectedProject.name}...`);
93
91
  let tokenResponse = await makeAuthenticatedRequest(`${options.apiUrl || getApiUrl()}/api/project/${selectedProject.slug}/tokens`, {
94
92
  method: 'POST',
95
93
  headers: {
@@ -102,7 +100,7 @@ export async function projectSelectCommand(options = {}, globalOptions = {}) {
102
100
  description: `Generated by vizzly CLI for ${process.cwd()}`
103
101
  })
104
102
  });
105
- ui.stopSpinner();
103
+ output.stopSpinner();
106
104
 
107
105
  // Save project mapping
108
106
  let currentDir = resolve(process.cwd());
@@ -112,19 +110,15 @@ export async function projectSelectCommand(options = {}, globalOptions = {}) {
112
110
  projectName: selectedProject.name,
113
111
  organizationSlug: selectedOrg.slug
114
112
  });
115
- ui.success('Project configured!');
116
- console.log(''); // Empty line for spacing
117
- ui.info(`Project: ${selectedProject.name}`);
118
- ui.info(`Organization: ${selectedOrg.name}`);
119
- ui.info(`Directory: ${currentDir}`);
120
- ui.cleanup();
113
+ output.success('Project configured!');
114
+ output.blank();
115
+ output.info(`Project: ${selectedProject.name}`);
116
+ output.info(`Organization: ${selectedOrg.name}`);
117
+ output.info(`Directory: ${currentDir}`);
118
+ output.cleanup();
121
119
  } catch (error) {
122
- ui.stopSpinner();
123
- ui.error('Failed to configure project', error, 0);
124
- if (globalOptions.verbose && error.stack) {
125
- console.error(''); // Empty line for spacing
126
- console.error(error.stack);
127
- }
120
+ output.stopSpinner();
121
+ output.error('Failed to configure project', error);
128
122
  process.exit(1);
129
123
  }
130
124
  }
@@ -135,7 +129,7 @@ export async function projectSelectCommand(options = {}, globalOptions = {}) {
135
129
  * @param {Object} globalOptions - Global CLI options
136
130
  */
137
131
  export async function projectListCommand(_options = {}, globalOptions = {}) {
138
- let ui = new ConsoleUI({
132
+ output.configure({
139
133
  json: globalOptions.json,
140
134
  verbose: globalOptions.verbose,
141
135
  color: !globalOptions.noColor
@@ -144,20 +138,19 @@ export async function projectListCommand(_options = {}, globalOptions = {}) {
144
138
  let mappings = await getProjectMappings();
145
139
  let paths = Object.keys(mappings);
146
140
  if (paths.length === 0) {
147
- ui.info('No projects configured');
148
- console.log(''); // Empty line for spacing
149
- ui.info('Run "vizzly project:select" to configure a project');
150
- ui.cleanup();
141
+ output.info('No projects configured');
142
+ output.blank();
143
+ output.info('Run "vizzly project:select" to configure a project');
144
+ output.cleanup();
151
145
  return;
152
146
  }
153
147
  if (globalOptions.json) {
154
- ui.data(mappings);
155
- ui.cleanup();
148
+ output.data(mappings);
149
+ output.cleanup();
156
150
  return;
157
151
  }
158
- ui.info('Configured projects:');
159
- console.log(''); // Empty line for spacing
160
-
152
+ output.info('Configured projects:');
153
+ output.blank();
161
154
  let currentDir = resolve(process.cwd());
162
155
  for (let path of paths) {
163
156
  let mapping = mappings[path];
@@ -166,22 +159,18 @@ export async function projectListCommand(_options = {}, globalOptions = {}) {
166
159
 
167
160
  // Extract token string (handle both string and object formats)
168
161
  let tokenStr = typeof mapping.token === 'string' ? mapping.token : mapping.token?.token || '[invalid token]';
169
- console.log(`${marker} ${path}`);
170
- console.log(` Project: ${mapping.projectName} (${mapping.projectSlug})`);
171
- console.log(` Organization: ${mapping.organizationSlug}`);
162
+ output.print(`${marker} ${path}`);
163
+ output.print(` Project: ${mapping.projectName} (${mapping.projectSlug})`);
164
+ output.print(` Organization: ${mapping.organizationSlug}`);
172
165
  if (globalOptions.verbose) {
173
- console.log(` Token: ${tokenStr.substring(0, 20)}...`);
174
- console.log(` Created: ${new Date(mapping.createdAt).toLocaleString()}`);
166
+ output.print(` Token: ${tokenStr.substring(0, 20)}...`);
167
+ output.print(` Created: ${new Date(mapping.createdAt).toLocaleString()}`);
175
168
  }
176
- console.log(''); // Empty line for spacing
169
+ output.blank();
177
170
  }
178
- ui.cleanup();
171
+ output.cleanup();
179
172
  } catch (error) {
180
- ui.error('Failed to list projects', error, 0);
181
- if (globalOptions.verbose && error.stack) {
182
- console.error(''); // Empty line for spacing
183
- console.error(error.stack);
184
- }
173
+ output.error('Failed to list projects', error);
185
174
  process.exit(1);
186
175
  }
187
176
  }
@@ -192,7 +181,7 @@ export async function projectListCommand(_options = {}, globalOptions = {}) {
192
181
  * @param {Object} globalOptions - Global CLI options
193
182
  */
194
183
  export async function projectTokenCommand(_options = {}, globalOptions = {}) {
195
- let ui = new ConsoleUI({
184
+ output.configure({
196
185
  json: globalOptions.json,
197
186
  verbose: globalOptions.verbose,
198
187
  color: !globalOptions.noColor
@@ -201,36 +190,32 @@ export async function projectTokenCommand(_options = {}, globalOptions = {}) {
201
190
  let currentDir = resolve(process.cwd());
202
191
  let mapping = await getProjectMapping(currentDir);
203
192
  if (!mapping) {
204
- ui.error('No project configured for this directory', null, 0);
205
- console.log(''); // Empty line for spacing
206
- ui.info('Run "vizzly project:select" to configure a project');
193
+ output.error('No project configured for this directory');
194
+ output.blank();
195
+ output.info('Run "vizzly project:select" to configure a project');
207
196
  process.exit(1);
208
197
  }
209
198
 
210
199
  // Extract token string (handle both string and object formats)
211
200
  let tokenStr = typeof mapping.token === 'string' ? mapping.token : mapping.token?.token || '[invalid token]';
212
201
  if (globalOptions.json) {
213
- ui.data({
202
+ output.data({
214
203
  token: tokenStr,
215
204
  projectSlug: mapping.projectSlug,
216
205
  organizationSlug: mapping.organizationSlug
217
206
  });
218
- ui.cleanup();
207
+ output.cleanup();
219
208
  return;
220
209
  }
221
- ui.info('Project token:');
222
- console.log(''); // Empty line for spacing
223
- console.log(` ${tokenStr}`);
224
- console.log(''); // Empty line for spacing
225
- ui.info(`Project: ${mapping.projectName} (${mapping.projectSlug})`);
226
- ui.info(`Organization: ${mapping.organizationSlug}`);
227
- ui.cleanup();
210
+ output.info('Project token:');
211
+ output.blank();
212
+ output.print(` ${tokenStr}`);
213
+ output.blank();
214
+ output.info(`Project: ${mapping.projectName} (${mapping.projectSlug})`);
215
+ output.info(`Organization: ${mapping.organizationSlug}`);
216
+ output.cleanup();
228
217
  } catch (error) {
229
- ui.error('Failed to get project token', error, 0);
230
- if (globalOptions.verbose && error.stack) {
231
- console.error(''); // Empty line for spacing
232
- console.error(error.stack);
233
- }
218
+ output.error('Failed to get project token', error);
234
219
  process.exit(1);
235
220
  }
236
221
  }
@@ -266,7 +251,7 @@ function promptNumber(message, min, max) {
266
251
  rl.question(`${message} (${min}-${max}): `, answer => {
267
252
  let num = parseInt(answer, 10);
268
253
  if (isNaN(num) || num < min || num > max) {
269
- console.log(`Please enter a number between ${min} and ${max}`);
254
+ output.print(`Please enter a number between ${min} and ${max}`);
270
255
  ask();
271
256
  } else {
272
257
  rl.close();
@@ -284,7 +269,7 @@ function promptNumber(message, min, max) {
284
269
  * @param {Object} globalOptions - Global CLI options
285
270
  */
286
271
  export async function projectRemoveCommand(_options = {}, globalOptions = {}) {
287
- let ui = new ConsoleUI({
272
+ output.configure({
288
273
  json: globalOptions.json,
289
274
  verbose: globalOptions.verbose,
290
275
  color: !globalOptions.noColor
@@ -293,36 +278,31 @@ export async function projectRemoveCommand(_options = {}, globalOptions = {}) {
293
278
  let currentDir = resolve(process.cwd());
294
279
  let mapping = await getProjectMapping(currentDir);
295
280
  if (!mapping) {
296
- ui.info('No project configured for this directory');
297
- ui.cleanup();
281
+ output.info('No project configured for this directory');
282
+ output.cleanup();
298
283
  return;
299
284
  }
300
285
 
301
286
  // Confirm removal
302
- console.log(''); // Empty line for spacing
303
- ui.info('Current project configuration:');
304
- console.log(` Project: ${mapping.projectName} (${mapping.projectSlug})`);
305
- console.log(` Organization: ${mapping.organizationSlug}`);
306
- console.log(` Directory: ${currentDir}`);
307
- console.log(''); // Empty line for spacing
308
-
287
+ output.blank();
288
+ output.info('Current project configuration:');
289
+ output.print(` Project: ${mapping.projectName} (${mapping.projectSlug})`);
290
+ output.print(` Organization: ${mapping.organizationSlug}`);
291
+ output.print(` Directory: ${currentDir}`);
292
+ output.blank();
309
293
  let confirmed = await promptConfirm('Remove this project configuration?');
310
294
  if (!confirmed) {
311
- ui.info('Cancelled');
312
- ui.cleanup();
295
+ output.info('Cancelled');
296
+ output.cleanup();
313
297
  return;
314
298
  }
315
299
  await deleteProjectMapping(currentDir);
316
- ui.success('Project configuration removed');
317
- console.log(''); // Empty line for spacing
318
- ui.info('Run "vizzly project:select" to configure a different project');
319
- ui.cleanup();
300
+ output.success('Project configuration removed');
301
+ output.blank();
302
+ output.info('Run "vizzly project:select" to configure a different project');
303
+ output.cleanup();
320
304
  } catch (error) {
321
- ui.error('Failed to remove project configuration', error, 0);
322
- if (globalOptions.verbose && error.stack) {
323
- console.error(''); // Empty line for spacing
324
- console.error(error.stack);
325
- }
305
+ output.error('Failed to remove project configuration', error);
326
306
  process.exit(1);
327
307
  }
328
308
  }