@ollie-shop/cli 0.3.0 → 0.3.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 (139) hide show
  1. package/.turbo/turbo-build.log +14 -2
  2. package/CHANGELOG.md +48 -0
  3. package/__tests__/mocks/core.ts +1 -1
  4. package/dist/index.d.ts +0 -2
  5. package/dist/index.js +40631 -75
  6. package/package.json +7 -6
  7. package/src/actions/component.actions.ts +148 -204
  8. package/src/actions/function.actions.ts +78 -171
  9. package/src/actions/project.actions.ts +16 -11
  10. package/src/commands/__tests__/component.test.ts +4 -7
  11. package/src/commands/__tests__/function.test.ts +1 -1
  12. package/src/commands/__tests__/store-version.test.ts +1 -4
  13. package/src/commands/component.ts +0 -10
  14. package/src/commands/function.ts +5 -56
  15. package/src/schemas/command.schema.ts +296 -6
  16. package/src/utils/__tests__/rich-progress.test.ts +22 -11
  17. package/src/utils/cli-progress-reporter.ts +2 -2
  18. package/src/utils/command-parser.ts +0 -5
  19. package/src/utils/console.ts +33 -4
  20. package/src/utils/constants.ts +32 -0
  21. package/src/utils/deploy-helpers.ts +357 -0
  22. package/src/utils/errors.ts +133 -2
  23. package/src/utils/interactive-builder.ts +61 -7
  24. package/src/utils/rich-progress.ts +25 -14
  25. package/src/utils/validation-helpers.ts +145 -12
  26. package/tsup.config.ts +15 -0
  27. package/dist/__tests__/helpers/cli-test-helper.d.ts +0 -89
  28. package/dist/__tests__/helpers/cli-test-helper.d.ts.map +0 -1
  29. package/dist/__tests__/helpers/cli-test-helper.js +0 -220
  30. package/dist/__tests__/mocks/index.d.ts +0 -69
  31. package/dist/__tests__/mocks/index.d.ts.map +0 -1
  32. package/dist/__tests__/mocks/index.js +0 -77
  33. package/dist/actions/component.actions.d.ts +0 -14
  34. package/dist/actions/component.actions.d.ts.map +0 -1
  35. package/dist/actions/component.actions.js +0 -273
  36. package/dist/actions/function.actions.d.ts +0 -15
  37. package/dist/actions/function.actions.d.ts.map +0 -1
  38. package/dist/actions/function.actions.js +0 -254
  39. package/dist/actions/project.actions.d.ts +0 -17
  40. package/dist/actions/project.actions.d.ts.map +0 -1
  41. package/dist/actions/project.actions.js +0 -97
  42. package/dist/actions/version.actions.d.ts +0 -19
  43. package/dist/actions/version.actions.d.ts.map +0 -1
  44. package/dist/actions/version.actions.js +0 -216
  45. package/dist/commands/component.d.ts +0 -3
  46. package/dist/commands/component.d.ts.map +0 -1
  47. package/dist/commands/component.js +0 -192
  48. package/dist/commands/docs.d.ts +0 -3
  49. package/dist/commands/docs.d.ts.map +0 -1
  50. package/dist/commands/docs.js +0 -16
  51. package/dist/commands/function.d.ts +0 -3
  52. package/dist/commands/function.d.ts.map +0 -1
  53. package/dist/commands/function.js +0 -243
  54. package/dist/commands/help.d.ts +0 -3
  55. package/dist/commands/help.d.ts.map +0 -1
  56. package/dist/commands/help.js +0 -20
  57. package/dist/commands/index.d.ts +0 -3
  58. package/dist/commands/index.d.ts.map +0 -1
  59. package/dist/commands/index.js +0 -26
  60. package/dist/commands/login.d.ts +0 -3
  61. package/dist/commands/login.d.ts.map +0 -1
  62. package/dist/commands/login.js +0 -175
  63. package/dist/commands/project.d.ts +0 -3
  64. package/dist/commands/project.d.ts.map +0 -1
  65. package/dist/commands/project.js +0 -78
  66. package/dist/commands/store-version.d.ts +0 -3
  67. package/dist/commands/store-version.d.ts.map +0 -1
  68. package/dist/commands/store-version.js +0 -241
  69. package/dist/commands/version.d.ts +0 -3
  70. package/dist/commands/version.d.ts.map +0 -1
  71. package/dist/commands/version.js +0 -46
  72. package/dist/commands/whoami.d.ts +0 -3
  73. package/dist/commands/whoami.d.ts.map +0 -1
  74. package/dist/commands/whoami.js +0 -41
  75. package/dist/index.d.ts.map +0 -1
  76. package/dist/prompts/component.prompts.d.ts +0 -14
  77. package/dist/prompts/component.prompts.d.ts.map +0 -1
  78. package/dist/prompts/component.prompts.js +0 -75
  79. package/dist/prompts/function.prompts.d.ts +0 -21
  80. package/dist/prompts/function.prompts.d.ts.map +0 -1
  81. package/dist/prompts/function.prompts.js +0 -127
  82. package/dist/schemas/command.schema.d.ts +0 -516
  83. package/dist/schemas/command.schema.d.ts.map +0 -1
  84. package/dist/schemas/command.schema.js +0 -267
  85. package/dist/types/index.d.ts +0 -147
  86. package/dist/types/index.d.ts.map +0 -1
  87. package/dist/types/index.js +0 -18
  88. package/dist/utils/auth.d.ts +0 -4
  89. package/dist/utils/auth.d.ts.map +0 -1
  90. package/dist/utils/auth.js +0 -26
  91. package/dist/utils/cli-progress-reporter.d.ts +0 -12
  92. package/dist/utils/cli-progress-reporter.d.ts.map +0 -1
  93. package/dist/utils/cli-progress-reporter.js +0 -77
  94. package/dist/utils/command-builder.d.ts +0 -22
  95. package/dist/utils/command-builder.d.ts.map +0 -1
  96. package/dist/utils/command-builder.js +0 -268
  97. package/dist/utils/command-helpers.d.ts +0 -19
  98. package/dist/utils/command-helpers.d.ts.map +0 -1
  99. package/dist/utils/command-helpers.js +0 -79
  100. package/dist/utils/command-parser.d.ts +0 -146
  101. package/dist/utils/command-parser.d.ts.map +0 -1
  102. package/dist/utils/command-parser.js +0 -179
  103. package/dist/utils/command-suggestions.d.ts +0 -35
  104. package/dist/utils/command-suggestions.d.ts.map +0 -1
  105. package/dist/utils/command-suggestions.js +0 -152
  106. package/dist/utils/console.d.ts +0 -44
  107. package/dist/utils/console.d.ts.map +0 -1
  108. package/dist/utils/console.js +0 -233
  109. package/dist/utils/constants.d.ts +0 -8
  110. package/dist/utils/constants.d.ts.map +0 -1
  111. package/dist/utils/constants.js +0 -10
  112. package/dist/utils/context-detector.d.ts +0 -12
  113. package/dist/utils/context-detector.d.ts.map +0 -1
  114. package/dist/utils/context-detector.js +0 -155
  115. package/dist/utils/enhanced-error-handler.d.ts +0 -47
  116. package/dist/utils/enhanced-error-handler.d.ts.map +0 -1
  117. package/dist/utils/enhanced-error-handler.js +0 -221
  118. package/dist/utils/error-handler.d.ts +0 -3
  119. package/dist/utils/error-handler.d.ts.map +0 -1
  120. package/dist/utils/error-handler.js +0 -55
  121. package/dist/utils/errors.d.ts +0 -44
  122. package/dist/utils/errors.d.ts.map +0 -1
  123. package/dist/utils/errors.js +0 -76
  124. package/dist/utils/interactive-builder.d.ts +0 -22
  125. package/dist/utils/interactive-builder.d.ts.map +0 -1
  126. package/dist/utils/interactive-builder.js +0 -246
  127. package/dist/utils/rich-progress.d.ts +0 -59
  128. package/dist/utils/rich-progress.d.ts.map +0 -1
  129. package/dist/utils/rich-progress.js +0 -234
  130. package/dist/utils/store.d.ts +0 -11
  131. package/dist/utils/store.d.ts.map +0 -1
  132. package/dist/utils/store.js +0 -19
  133. package/dist/utils/validation-error-formatter.d.ts +0 -25
  134. package/dist/utils/validation-error-formatter.d.ts.map +0 -1
  135. package/dist/utils/validation-error-formatter.js +0 -258
  136. package/dist/utils/validation-helpers.d.ts +0 -60
  137. package/dist/utils/validation-helpers.d.ts.map +0 -1
  138. package/dist/utils/validation-helpers.js +0 -152
  139. package/src/commands/__tests__/version.test.ts +0 -71
@@ -0,0 +1,357 @@
1
+ import {
2
+ type BuildResponse,
3
+ type BuildResult,
4
+ formatBuildError,
5
+ setBuilderUrl,
6
+ waitForBuildCompletion,
7
+ } from "@ollie-shop/core";
8
+ import { validateBuilderApiUrl } from "../schemas/command.schema";
9
+ import type { CliConsole } from "./console";
10
+ import { DEPLOYMENT_SETTINGS, ERROR_MESSAGES } from "./constants";
11
+ import { RichProgressReporter } from "./rich-progress.js";
12
+
13
+ /**
14
+ * Resource types that can be deployed through the CLI
15
+ * @typedef {"component" | "function"} ResourceType
16
+ */
17
+ export type ResourceType = "component" | "function";
18
+
19
+ /**
20
+ * Error types that can occur during deployment operations
21
+ * @typedef {"BuildTimeoutError" | "BuildFailedError" | "BuildValidationError" | "UnknownError"} DeploymentErrorType
22
+ */
23
+ export type DeploymentErrorType =
24
+ | "BuildTimeoutError"
25
+ | "BuildFailedError"
26
+ | "BuildValidationError"
27
+ | "UnknownError";
28
+
29
+ /**
30
+ * Deployment progress information returned after successful deployment
31
+ * @interface DeploymentProgress
32
+ * @property {BuildResponse} completedBuild - The completed build response from the builder service
33
+ * @property {number} duration - Total deployment duration in seconds
34
+ */
35
+ export interface DeploymentProgress {
36
+ completedBuild: BuildResponse;
37
+ duration: number;
38
+ }
39
+
40
+ /**
41
+ * Configure the builder URL from environment variable with validation
42
+ * Uses BUILDER_API_URL environment variable if set, validates it's a proper URL
43
+ *
44
+ * @throws {Error} If BUILDER_API_URL is set but invalid
45
+ * @example
46
+ * ```typescript
47
+ * // Set environment variable first
48
+ * process.env.BUILDER_API_URL = "https://builder.ollie.shop";
49
+ *
50
+ * // Configure the builder
51
+ * configureBuilderUrl();
52
+ * ```
53
+ */
54
+ export function configureBuilderUrl(): void {
55
+ const builderUrl = process.env.BUILDER_API_URL;
56
+ if (builderUrl) {
57
+ if (!validateBuilderApiUrl(builderUrl)) {
58
+ throw new Error(
59
+ "Invalid BUILDER_API_URL environment variable. Must be a valid HTTP or HTTPS URL.",
60
+ );
61
+ }
62
+ setBuilderUrl(builderUrl);
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Handle deployment errors with proper type safety and user-friendly messages
68
+ * Provides specific error messages and recovery suggestions based on error type
69
+ *
70
+ * @param {unknown} error - The error that occurred during deployment
71
+ * @param {string} _buildId - The build ID (currently unused but kept for future use)
72
+ * @param {ResourceType} resourceType - Type of resource being deployed (component/function)
73
+ * @param {CliConsole} cliConsole - Console instance for output
74
+ * @example
75
+ * ```typescript
76
+ * try {
77
+ * await deployComponent(options);
78
+ * } catch (error) {
79
+ * handleDeploymentError(error, buildId, "component", console);
80
+ * }
81
+ * ```
82
+ */
83
+ export function handleDeploymentError(
84
+ error: unknown,
85
+ _buildId: string,
86
+ resourceType: ResourceType,
87
+ cliConsole: CliConsole,
88
+ ): void {
89
+ const errorType = getErrorType(error);
90
+ const errorMessage = getErrorMessage(error);
91
+
92
+ switch (errorType) {
93
+ case "BuildTimeoutError":
94
+ cliConsole.error(ERROR_MESSAGES.DEPLOYMENT_TIMEOUT);
95
+ cliConsole.suggestions([
96
+ `Retry deployment: ollieshop ${resourceType} deploy --id <${resourceType}-id>`,
97
+ "Check your network connection and try again",
98
+ "Contact support if timeouts persist - this may indicate infrastructure issues",
99
+ ]);
100
+ break;
101
+ case "BuildFailedError":
102
+ cliConsole.error(ERROR_MESSAGES.BUILD_FAILED);
103
+ cliConsole.info("Review the build logs above for specific error details");
104
+ if (errorMessage) {
105
+ cliConsole.info(`Error details: ${errorMessage}`);
106
+ }
107
+ cliConsole.suggestions([
108
+ `Validate your ${resourceType} code: ollieshop ${resourceType} validate`,
109
+ "Check your code for syntax errors and missing dependencies",
110
+ "Ensure all imports and exports are correctly defined",
111
+ ]);
112
+ break;
113
+ case "BuildValidationError":
114
+ cliConsole.error(ERROR_MESSAGES.BUILD_VALIDATION_FAILED);
115
+ handleBuildValidationError(error, resourceType, cliConsole);
116
+ break;
117
+ default:
118
+ cliConsole.error(`${ERROR_MESSAGES.UNKNOWN_ERROR}: ${errorMessage}`);
119
+ break;
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Get the error type from an unknown error with proper type safety
125
+ */
126
+ function getErrorType(error: unknown): DeploymentErrorType {
127
+ if (error && typeof error === "object" && "name" in error) {
128
+ const errorName = (error as { name: string }).name;
129
+ if (isValidErrorType(errorName)) {
130
+ return errorName;
131
+ }
132
+ }
133
+ return "UnknownError";
134
+ }
135
+
136
+ /**
137
+ * Get the error message from an unknown error with proper type safety
138
+ */
139
+ function getErrorMessage(error: unknown): string {
140
+ if (error && typeof error === "object" && "message" in error) {
141
+ return String((error as { message: unknown }).message);
142
+ }
143
+ return "An unknown error occurred";
144
+ }
145
+
146
+ /**
147
+ * Type guard to check if a string is a valid error type
148
+ */
149
+ function isValidErrorType(errorName: string): errorName is DeploymentErrorType {
150
+ return [
151
+ "BuildTimeoutError",
152
+ "BuildFailedError",
153
+ "BuildValidationError",
154
+ ].includes(errorName);
155
+ }
156
+
157
+ /**
158
+ * Show deployment success message with build details
159
+ * Displays build ID, duration, and infrastructure deployment confirmation
160
+ *
161
+ * @param {BuildResponse} completedBuild - The completed build response
162
+ * @param {number} duration - Deployment duration in seconds
163
+ * @param {string} _resourceId - Resource ID (currently unused but kept for future use)
164
+ * @param {ResourceType} _resourceType - Resource type (currently unused but kept for future use)
165
+ * @param {CliConsole} cliConsole - Console instance for output
166
+ * @example
167
+ * ```typescript
168
+ * const { completedBuild, duration } = await waitForDeploymentWithProgress(
169
+ * buildId,
170
+ * "component",
171
+ * console
172
+ * );
173
+ * showDeploymentSuccess(completedBuild, duration, componentId, "component", console);
174
+ * ```
175
+ */
176
+ export function showDeploymentSuccess(
177
+ completedBuild: BuildResponse,
178
+ duration: number,
179
+ _resourceId: string,
180
+ _resourceType: ResourceType,
181
+ cliConsole: CliConsole,
182
+ ): void {
183
+ cliConsole.success("\nāœ… Deployment completed successfully!");
184
+ cliConsole.info(`Build ID: ${completedBuild.id}`);
185
+ cliConsole.info(`Duration: ${duration.toFixed(1)}s`);
186
+
187
+ // Note: Deployment URLs are dynamically generated by the infrastructure
188
+ // For components: CloudFront URL (managed by SST router)
189
+ // For functions: Lambda ARN (managed by AWS)
190
+ cliConsole.info("✨ Resources deployed to cloud infrastructure");
191
+ }
192
+
193
+ // Removed showAsyncModeNextSteps as deployments now always wait for completion
194
+
195
+ /**
196
+ * Wait for deployment completion with real-time progress reporting
197
+ * Shows animated progress bar with ETA while polling the builder service
198
+ *
199
+ * @async
200
+ * @param {string} buildId - The build ID to monitor
201
+ * @param {ResourceType} resourceType - Type of resource being deployed
202
+ * @param {CliConsole} cliConsole - Console instance for progress display
203
+ * @returns {Promise<DeploymentProgress>} Deployment details including completed build and duration
204
+ * @throws {Error} If deployment times out or fails
205
+ * @example
206
+ * ```typescript
207
+ * const result = await buildAndDeployComponent(componentId, path);
208
+ * const { completedBuild, duration } = await waitForDeploymentWithProgress(
209
+ * result.buildId,
210
+ * "component",
211
+ * console
212
+ * );
213
+ * console.log(`Deployment completed in ${duration}s`);
214
+ * ```
215
+ */
216
+ export async function waitForDeploymentWithProgress(
217
+ buildId: string,
218
+ resourceType: ResourceType,
219
+ cliConsole: CliConsole,
220
+ ): Promise<DeploymentProgress> {
221
+ const progressReporter = new RichProgressReporter(cliConsole);
222
+ progressReporter.start();
223
+
224
+ const startTime = Date.now();
225
+ const estimatedDuration = DEPLOYMENT_SETTINGS.ESTIMATED_BUILD_DURATION_MS;
226
+
227
+ // Update progress based on elapsed time
228
+ const progressTimer = setInterval(() => {
229
+ const elapsed = Date.now() - startTime;
230
+ const progress = Math.min(
231
+ elapsed / estimatedDuration,
232
+ DEPLOYMENT_SETTINGS.MAX_PROGRESS_BEFORE_COMPLETION,
233
+ );
234
+ const remainingSeconds = Math.max(
235
+ 0,
236
+ Math.ceil((estimatedDuration - elapsed) / 1000),
237
+ );
238
+
239
+ progressReporter.updateProgress({
240
+ phase: "building",
241
+ message: `Building ${resourceType}... ETA: ${remainingSeconds}s`,
242
+ progress,
243
+ });
244
+ }, DEPLOYMENT_SETTINGS.PROGRESS_UPDATE_INTERVAL_MS);
245
+
246
+ try {
247
+ const completedBuild = await waitForBuildCompletion(buildId, {
248
+ pollIntervalMs: DEPLOYMENT_SETTINGS.DEFAULT_POLL_INTERVAL_MS,
249
+ maxWaitMs: DEPLOYMENT_SETTINGS.DEFAULT_MAX_WAIT_MS,
250
+ });
251
+
252
+ clearInterval(progressTimer);
253
+ const duration = (Date.now() - startTime) / 1000;
254
+ progressReporter.stop(true);
255
+
256
+ return { completedBuild, duration };
257
+ } catch (error) {
258
+ clearInterval(progressTimer);
259
+ progressReporter.stop(false);
260
+ throw error;
261
+ }
262
+ }
263
+
264
+ /**
265
+ * Handle build validation errors with specific suggestions
266
+ * Provides targeted help for common validation issues
267
+ *
268
+ * @param {unknown} error - The validation error
269
+ * @param {ResourceType} resourceType - Type of resource that failed validation
270
+ * @param {CliConsole} cliConsole - Console instance for output
271
+ * @example
272
+ * ```typescript
273
+ * if (error.code === "BUILD_VALIDATION_ERROR") {
274
+ * handleBuildValidationError(error, "component", console);
275
+ * }
276
+ * ```
277
+ */
278
+ export function handleBuildValidationError(
279
+ error: unknown,
280
+ resourceType: ResourceType,
281
+ cliConsole: CliConsole,
282
+ ): void {
283
+ const errorCode = getErrorCode(error);
284
+
285
+ if (errorCode === "BUILD_VALIDATION_ERROR") {
286
+ cliConsole.suggestions([
287
+ `Ensure the ${resourceType} ID is a valid UUID format (e.g., 123e4567-e89b-12d3-a456-426614174000)`,
288
+ `Verify the ${resourceType} directory exists and contains the required files`,
289
+ `Check that your ${resourceType} has a valid package.json with correct entry point`,
290
+ `Run: ollieshop ${resourceType} validate --path <path> to identify specific issues`,
291
+ ]);
292
+ }
293
+ }
294
+
295
+ /**
296
+ * Get error code from unknown error with proper type safety
297
+ */
298
+ function getErrorCode(error: unknown): string | undefined {
299
+ if (error && typeof error === "object" && "code" in error) {
300
+ const code = (error as { code: unknown }).code;
301
+ return typeof code === "string" ? code : undefined;
302
+ }
303
+ return undefined;
304
+ }
305
+
306
+ /**
307
+ * Handle deployment result with proper error handling and type safety
308
+ * Updates spinner state and throws error if deployment failed
309
+ *
310
+ * @param {BuildResult} result - The build result from the deployment attempt
311
+ * @param {ResourceType} resourceType - Type of resource being deployed
312
+ * @param {CliConsole} cliConsole - Console instance for output
313
+ * @param {ReturnType<CliConsole["spinner"]>} spinner - Active spinner to update
314
+ * @throws {Error} If the deployment failed
315
+ * @example
316
+ * ```typescript
317
+ * const result = await buildAndDeployComponent(componentId, path);
318
+ * handleDeploymentResult(result, "component", console, spinner);
319
+ * // If we get here, deployment was initiated successfully
320
+ * ```
321
+ */
322
+ export function handleDeploymentResult(
323
+ result: BuildResult,
324
+ resourceType: ResourceType,
325
+ cliConsole: CliConsole,
326
+ spinner: ReturnType<CliConsole["spinner"]>,
327
+ ): void {
328
+ if (!result.success) {
329
+ const capitalizedType = capitalizeResourceType(resourceType);
330
+ spinner.fail(`${capitalizedType} deployment failed`);
331
+
332
+ const errorMessage = result.error
333
+ ? formatBuildError(result.error)
334
+ : "Unknown error occurred";
335
+
336
+ cliConsole.error(errorMessage);
337
+ handleBuildValidationError(result.error, resourceType, cliConsole);
338
+
339
+ const error = new Error(
340
+ getErrorMessage(result.error) || "Deployment failed",
341
+ );
342
+ error.name = "DeploymentError";
343
+ throw error;
344
+ }
345
+
346
+ const capitalizedType = capitalizeResourceType(resourceType);
347
+ spinner.succeed(`${capitalizedType} deployment initiated!`);
348
+ cliConsole.success(`Build ID: ${result.buildId}`);
349
+ cliConsole.info(`Status: ${result.status}`);
350
+ }
351
+
352
+ /**
353
+ * Capitalize resource type for display purposes
354
+ */
355
+ function capitalizeResourceType(resourceType: ResourceType): string {
356
+ return resourceType.charAt(0).toUpperCase() + resourceType.slice(1);
357
+ }
@@ -1,15 +1,45 @@
1
1
  import type { ZodError } from "zod";
2
2
  import type { ErrorContext } from "../types";
3
3
 
4
+ /**
5
+ * Recovery action that can be suggested to users when an error occurs
6
+ * @interface RecoveryAction
7
+ * @property {string} description - Human-readable description of the recovery action
8
+ * @property {string} [command] - Optional CLI command that can help resolve the issue
9
+ */
4
10
  export interface RecoveryAction {
5
11
  description: string;
6
12
  command?: string;
7
13
  }
8
14
 
15
+ /**
16
+ * Base error class for all Ollie Shop CLI errors
17
+ * Provides context and recovery suggestions to help users resolve issues
18
+ *
19
+ * @class OllieShopCLIError
20
+ * @extends {Error}
21
+ * @example
22
+ * ```typescript
23
+ * throw new OllieShopCLIError(
24
+ * "Component build failed",
25
+ * { componentId: "123", path: "./src" },
26
+ * [
27
+ * { description: "Check your TypeScript configuration" },
28
+ * { description: "Run validation", command: "ollieshop component validate" }
29
+ * ]
30
+ * );
31
+ * ```
32
+ */
9
33
  export class OllieShopCLIError extends Error {
10
34
  public readonly context: ErrorContext;
11
35
  public readonly recoveryActions: RecoveryAction[];
12
36
 
37
+ /**
38
+ * Creates a new OllieShopCLIError instance
39
+ * @param {string} message - The error message
40
+ * @param {ErrorContext} [context={}] - Additional context about the error
41
+ * @param {RecoveryAction[]} [recoveryActions=[]] - Suggested actions to resolve the error
42
+ */
13
43
  constructor(
14
44
  message: string,
15
45
  context: ErrorContext = {},
@@ -21,14 +51,41 @@ export class OllieShopCLIError extends Error {
21
51
  this.recoveryActions = recoveryActions;
22
52
  }
23
53
 
54
+ /**
55
+ * Get the error context details
56
+ * @returns {ErrorContext} The error context object
57
+ */
24
58
  get details(): ErrorContext {
25
59
  return this.context;
26
60
  }
27
61
 
62
+ /**
63
+ * Get suggested recovery actions
64
+ * @returns {RecoveryAction[]} Array of recovery actions
65
+ */
28
66
  get suggestions(): RecoveryAction[] {
29
67
  return this.recoveryActions;
30
68
  }
31
69
 
70
+ /**
71
+ * Create an OllieShopCLIError from a Zod validation error
72
+ * Extracts the most relevant error message and provides validation-specific suggestions
73
+ *
74
+ * @static
75
+ * @param {ZodError} error - The Zod validation error
76
+ * @param {ErrorContext} [context={}] - Additional context to include
77
+ * @returns {OllieShopCLIError} A new OllieShopCLIError instance
78
+ * @example
79
+ * ```typescript
80
+ * try {
81
+ * ComponentNameSchema.parse("Invalid Name!");
82
+ * } catch (error) {
83
+ * if (error instanceof ZodError) {
84
+ * throw OllieShopCLIError.fromZodError(error, { field: "name" });
85
+ * }
86
+ * }
87
+ * ```
88
+ */
32
89
  static fromZodError(
33
90
  error: ZodError,
34
91
  context: ErrorContext = {},
@@ -48,6 +105,23 @@ export class OllieShopCLIError extends Error {
48
105
  ]);
49
106
  }
50
107
 
108
+ /**
109
+ * Create an OllieShopCLIError from an unknown error type
110
+ * Safely handles any error type and converts it to OllieShopCLIError
111
+ *
112
+ * @static
113
+ * @param {unknown} error - Any error or value
114
+ * @param {ErrorContext} [context={}] - Additional context to include
115
+ * @returns {OllieShopCLIError} A new OllieShopCLIError instance
116
+ * @example
117
+ * ```typescript
118
+ * try {
119
+ * // some operation
120
+ * } catch (error) {
121
+ * throw OllieShopCLIError.fromUnknown(error, { operation: "deploy" });
122
+ * }
123
+ * ```
124
+ */
51
125
  static fromUnknown(
52
126
  error: unknown,
53
127
  context: ErrorContext = {},
@@ -68,6 +142,20 @@ export class OllieShopCLIError extends Error {
68
142
  );
69
143
  }
70
144
 
145
+ /**
146
+ * Create a file not found error with helpful suggestions
147
+ *
148
+ * @static
149
+ * @param {string} path - The file path that was not found
150
+ * @param {ErrorContext} [context={}] - Additional context to include
151
+ * @returns {OllieShopCLIError} A new OllieShopCLIError instance with file-specific suggestions
152
+ * @example
153
+ * ```typescript
154
+ * if (!fs.existsSync(configPath)) {
155
+ * throw OllieShopCLIError.fileNotFound(configPath, { operation: "load-config" });
156
+ * }
157
+ * ```
158
+ */
71
159
  static fileNotFound(
72
160
  path: string,
73
161
  context: ErrorContext = {},
@@ -86,11 +174,29 @@ export class OllieShopCLIError extends Error {
86
174
  export const CLIError = OllieShopCLIError;
87
175
 
88
176
  /**
89
- * Command execution error
177
+ * Error thrown when a CLI command execution fails
178
+ * Includes an error code for programmatic error handling
179
+ *
180
+ * @class CommandError
181
+ * @extends {OllieShopCLIError}
182
+ * @example
183
+ * ```typescript
184
+ * throw new CommandError(
185
+ * "Failed to connect to builder service",
186
+ * "BUILDER_CONNECTION_ERROR",
187
+ * { url: builderUrl, timeout: 5000 }
188
+ * );
189
+ * ```
90
190
  */
91
191
  export class CommandError extends OllieShopCLIError {
92
192
  public readonly code: string;
93
193
 
194
+ /**
195
+ * Creates a new CommandError instance
196
+ * @param {string} message - The error message
197
+ * @param {string} code - A unique error code for this type of error
198
+ * @param {ErrorContext} [context={}] - Additional context about the error
199
+ */
94
200
  constructor(message: string, code: string, context: ErrorContext = {}) {
95
201
  super(message, context);
96
202
  this.name = "CommandError";
@@ -99,11 +205,32 @@ export class CommandError extends OllieShopCLIError {
99
205
  }
100
206
 
101
207
  /**
102
- * Validation error with detailed field information
208
+ * Error thrown when validation fails with detailed field-level information
209
+ * Useful for form validation and input checking scenarios
210
+ *
211
+ * @class ValidationError
212
+ * @extends {OllieShopCLIError}
213
+ * @example
214
+ * ```typescript
215
+ * throw new ValidationError(
216
+ * "Component configuration is invalid",
217
+ * [
218
+ * { field: "name", message: "Must be lowercase with hyphens" },
219
+ * { field: "slot", message: "Invalid slot type" }
220
+ * ],
221
+ * { componentPath: "./src/components/header" }
222
+ * );
223
+ * ```
103
224
  */
104
225
  export class ValidationError extends OllieShopCLIError {
105
226
  public readonly fields: Array<{ field: string; message: string }>;
106
227
 
228
+ /**
229
+ * Creates a new ValidationError instance
230
+ * @param {string} message - The overall error message
231
+ * @param {Array<{field: string; message: string}>} [fields=[]] - Field-specific validation errors
232
+ * @param {ErrorContext} [context={}] - Additional context about the error
233
+ */
107
234
  constructor(
108
235
  message: string,
109
236
  fields: Array<{ field: string; message: string }> = [],
@@ -114,6 +241,10 @@ export class ValidationError extends OllieShopCLIError {
114
241
  this.fields = fields;
115
242
  }
116
243
 
244
+ /**
245
+ * Get error details including field-level errors
246
+ * @returns {ErrorContext & {fields: Array<{field: string; message: string}>}} Combined context and field errors
247
+ */
117
248
  get details(): ErrorContext & {
118
249
  fields: Array<{ field: string; message: string }>;
119
250
  } {
@@ -5,11 +5,40 @@ import type { ComponentDeployOptions } from "../schemas/command.schema";
5
5
  import type { InteractiveChoice, MockComponent } from "../types";
6
6
  import type { CliConsole } from "./console.js";
7
7
 
8
+ /**
9
+ * Interactive command builder for creating CLI commands through prompts
10
+ * Provides a wizard-like interface for complex commands
11
+ *
12
+ * @class InteractiveCommandBuilder
13
+ * @example
14
+ * ```typescript
15
+ * const builder = new InteractiveCommandBuilder(console);
16
+ * await builder.buildDeployComponentCommand();
17
+ * // User is guided through deployment options
18
+ * ```
19
+ */
8
20
  export class InteractiveCommandBuilder {
21
+ /**
22
+ * Creates a new InteractiveCommandBuilder instance
23
+ * @param {CliConsole} console - Console instance for I/O operations
24
+ */
9
25
  constructor(private console: CliConsole) {}
10
26
 
11
27
  /**
12
28
  * Build component deploy command interactively
29
+ * Guides user through selecting a component and deployment options
30
+ *
31
+ * @async
32
+ * @throws {Error} If user cancels the wizard
33
+ * @example
34
+ * ```typescript
35
+ * await builder.buildDeployComponentCommand();
36
+ * // Shows:
37
+ * // - List of available components
38
+ * // - Deployment options checkboxes
39
+ * // - Command preview
40
+ * // - Execution confirmation
41
+ * ```
13
42
  */
14
43
  async buildDeployComponentCommand(): Promise<void> {
15
44
  this.console.log(chalk.blue.bold("\nšŸš€ Component Deployment Wizard\n"));
@@ -37,7 +66,6 @@ export class InteractiveCommandBuilder {
37
66
  name: "options",
38
67
  message: "Deployment options:",
39
68
  choices: [
40
- { name: "Wait for completion", value: "wait", checked: true },
41
69
  { name: "Run tests before deploy", value: "test", checked: true },
42
70
  {
43
71
  name: "Enable verbose logging",
@@ -51,10 +79,6 @@ export class InteractiveCommandBuilder {
51
79
  // Build the command
52
80
  let command = `ollieshop component deploy --id ${answers.component}`;
53
81
 
54
- if (answers.options.includes("wait")) {
55
- command += " --wait";
56
- }
57
-
58
82
  if (answers.options.includes("verbose")) {
59
83
  command += " --verbose";
60
84
  }
@@ -82,7 +106,6 @@ export class InteractiveCommandBuilder {
82
106
  const deployOptions: ComponentDeployOptions = {
83
107
  componentId: answers.component,
84
108
  path: process.cwd(),
85
- wait: answers.options.includes("wait"),
86
109
  };
87
110
  await deployComponent(deployOptions, this.console);
88
111
  } else {
@@ -99,6 +122,19 @@ export class InteractiveCommandBuilder {
99
122
 
100
123
  /**
101
124
  * Build component create command interactively
125
+ * Guides user through component creation options with live validation
126
+ *
127
+ * @async
128
+ * @throws {Error} If user cancels the wizard
129
+ * @example
130
+ * ```typescript
131
+ * await builder.buildCreateComponentCommand();
132
+ * // Prompts for:
133
+ * // - Component name (with live validation)
134
+ * // - Component slot selection
135
+ * // - Language preference (TypeScript/JavaScript)
136
+ * // - Test file inclusion
137
+ * ```
102
138
  */
103
139
  async buildCreateComponentCommand(): Promise<void> {
104
140
  this.console.log(chalk.blue.bold("\nšŸŽØ Component Creation Wizard\n"));
@@ -209,6 +245,11 @@ export class InteractiveCommandBuilder {
209
245
 
210
246
  /**
211
247
  * Get available components (mock for now)
248
+ * TODO: Replace with actual API call to list components
249
+ *
250
+ * @private
251
+ * @async
252
+ * @returns {Promise<MockComponent[]>} Array of mock component data
212
253
  */
213
254
  private async getAvailableComponents(): Promise<MockComponent[]> {
214
255
  // TODO: Replace with actual API call
@@ -248,7 +289,20 @@ export class InteractiveCommandBuilder {
248
289
  }
249
290
 
250
291
  /**
251
- * Create an interactive command builder
292
+ * Run an interactive command builder for the specified command
293
+ * Creates a wizard-like interface based on the command type
294
+ *
295
+ * @async
296
+ * @param {string} command - The command type to run interactively
297
+ * @param {CliConsole} console - Console instance for I/O
298
+ * @example
299
+ * ```typescript
300
+ * // Run deployment wizard
301
+ * await runInteractiveCommand("deploy", console);
302
+ *
303
+ * // Run component creation wizard
304
+ * await runInteractiveCommand("create", console);
305
+ * ```
252
306
  */
253
307
  export async function runInteractiveCommand(
254
308
  command: string,