@simplens/onboard 1.0.1 ā 1.0.2
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.
- package/README.md +331 -214
- package/dist/__tests__/env-config.test.d.ts +2 -0
- package/dist/__tests__/env-config.test.d.ts.map +1 -0
- package/dist/__tests__/env-config.test.js +23 -0
- package/dist/__tests__/env-config.test.js.map +1 -0
- package/dist/__tests__/infra-prompts.test.d.ts +2 -0
- package/dist/__tests__/infra-prompts.test.d.ts.map +1 -0
- package/dist/__tests__/infra-prompts.test.js +43 -0
- package/dist/__tests__/infra-prompts.test.js.map +1 -0
- package/dist/__tests__/infra.test.d.ts +2 -0
- package/dist/__tests__/infra.test.d.ts.map +1 -0
- package/dist/__tests__/infra.test.js +14 -0
- package/dist/__tests__/infra.test.js.map +1 -0
- package/dist/__tests__/nginx.test.d.ts +2 -0
- package/dist/__tests__/nginx.test.d.ts.map +1 -0
- package/dist/__tests__/nginx.test.js +16 -0
- package/dist/__tests__/nginx.test.js.map +1 -0
- package/dist/env-config.d.ts +27 -12
- package/dist/env-config.d.ts.map +1 -1
- package/dist/env-config.js +253 -128
- package/dist/env-config.js.map +1 -1
- package/dist/index.js +340 -69
- package/dist/index.js.map +1 -1
- package/dist/infra.d.ts +19 -8
- package/dist/infra.d.ts.map +1 -1
- package/dist/infra.js +267 -128
- package/dist/infra.js.map +1 -1
- package/dist/plugins.d.ts +5 -10
- package/dist/plugins.d.ts.map +1 -1
- package/dist/plugins.js +75 -44
- package/dist/plugins.js.map +1 -1
- package/dist/services.d.ts +1 -23
- package/dist/services.d.ts.map +1 -1
- package/dist/services.js +47 -62
- package/dist/services.js.map +1 -1
- package/dist/templates.d.ts +2 -1
- package/dist/templates.d.ts.map +1 -1
- package/dist/templates.js +203 -191
- package/dist/templates.js.map +1 -1
- package/dist/types/domain.d.ts +2 -0
- package/dist/types/domain.d.ts.map +1 -1
- package/dist/ui.d.ts +45 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +93 -0
- package/dist/ui.js.map +1 -0
- package/dist/utils/logger.d.ts +1 -0
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +32 -7
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils.d.ts +8 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +66 -2
- package/dist/utils.js.map +1 -1
- package/dist/validators.d.ts +1 -52
- package/dist/validators.d.ts.map +1 -1
- package/dist/validators.js +10 -57
- package/dist/validators.js.map +1 -1
- package/package.json +3 -5
- package/src/__tests__/env-config.test.ts +28 -0
- package/src/__tests__/errors.test.ts +187 -187
- package/src/__tests__/infra-prompts.test.ts +54 -0
- package/src/__tests__/infra.test.ts +15 -0
- package/src/__tests__/utils.test.ts +142 -142
- package/src/__tests__/validators.test.ts +195 -195
- package/src/config/constants.ts +86 -86
- package/src/config/index.ts +1 -1
- package/src/env-config.ts +455 -311
- package/src/index.ts +534 -202
- package/src/infra.ts +404 -245
- package/src/plugins.ts +221 -190
- package/src/services.ts +175 -190
- package/src/templates.ts +209 -196
- package/src/types/domain.ts +129 -127
- package/src/types/errors.ts +173 -173
- package/src/types/index.ts +2 -2
- package/src/ui.ts +91 -0
- package/src/utils/index.ts +1 -1
- package/src/utils/logger.ts +144 -118
- package/src/utils.ts +183 -105
- package/src/validators.ts +145 -192
- package/tsconfig.json +18 -18
- package/vitest.config.ts +22 -22
package/src/types/errors.ts
CHANGED
|
@@ -1,173 +1,173 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Custom error types for better error handling and troubleshooting
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Base error class for all onboarding errors
|
|
7
|
-
*/
|
|
8
|
-
export class OnboardingError extends Error {
|
|
9
|
-
constructor(
|
|
10
|
-
public readonly code: string,
|
|
11
|
-
message: string,
|
|
12
|
-
public readonly troubleshooting?: string
|
|
13
|
-
) {
|
|
14
|
-
super(message);
|
|
15
|
-
this.name = 'OnboardingError';
|
|
16
|
-
Error.captureStackTrace(this, this.constructor);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Docker-related errors
|
|
22
|
-
*/
|
|
23
|
-
export class DockerError extends OnboardingError {
|
|
24
|
-
constructor(message: string, troubleshooting?: string) {
|
|
25
|
-
super('DOCKER_ERROR', message, troubleshooting);
|
|
26
|
-
this.name = 'DockerError';
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export class DockerNotInstalledError extends DockerError {
|
|
31
|
-
constructor() {
|
|
32
|
-
super(
|
|
33
|
-
'Docker is not installed on this system',
|
|
34
|
-
'Please install Docker from: https://docs.docker.com/get-docker/'
|
|
35
|
-
);
|
|
36
|
-
this.name = 'DockerNotInstalledError';
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export class DockerNotRunningError extends DockerError {
|
|
41
|
-
constructor() {
|
|
42
|
-
super(
|
|
43
|
-
'Docker daemon is not running',
|
|
44
|
-
'Please start Docker Desktop or Docker daemon, then try again'
|
|
45
|
-
);
|
|
46
|
-
this.name = 'DockerNotRunningError';
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export class DockerPermissionError extends DockerError {
|
|
51
|
-
constructor() {
|
|
52
|
-
super(
|
|
53
|
-
'Permission denied when accessing Docker',
|
|
54
|
-
'Try running with sudo or add your user to the docker group:\n' +
|
|
55
|
-
' sudo usermod -aG docker $USER\n' +
|
|
56
|
-
' Then log out and log back in'
|
|
57
|
-
);
|
|
58
|
-
this.name = 'DockerPermissionError';
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export class DockerComposeError extends DockerError {
|
|
63
|
-
constructor(operation: string, details?: string) {
|
|
64
|
-
super(
|
|
65
|
-
`Failed to ${operation} with docker-compose`,
|
|
66
|
-
details || 'Check docker-compose logs for more details:\n docker-compose logs'
|
|
67
|
-
);
|
|
68
|
-
this.name = 'DockerComposeError';
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* File system errors
|
|
74
|
-
*/
|
|
75
|
-
export class FileSystemError extends OnboardingError {
|
|
76
|
-
constructor(message: string, public readonly path: string, troubleshooting?: string) {
|
|
77
|
-
super('FILESYSTEM_ERROR', message, troubleshooting);
|
|
78
|
-
this.name = 'FileSystemError';
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export class DirectoryNotWritableError extends FileSystemError {
|
|
83
|
-
constructor(path: string) {
|
|
84
|
-
super(
|
|
85
|
-
`Directory is not writable: ${path}`,
|
|
86
|
-
path,
|
|
87
|
-
'Check directory permissions or choose a different directory'
|
|
88
|
-
);
|
|
89
|
-
this.name = 'DirectoryNotWritableError';
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export class FileNotFoundError extends FileSystemError {
|
|
94
|
-
constructor(path: string) {
|
|
95
|
-
super(
|
|
96
|
-
`File not found: ${path}`,
|
|
97
|
-
path,
|
|
98
|
-
'Ensure the file exists or check the path'
|
|
99
|
-
);
|
|
100
|
-
this.name = 'FileNotFoundError';
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Configuration errors
|
|
106
|
-
*/
|
|
107
|
-
export class ConfigurationError extends OnboardingError {
|
|
108
|
-
constructor(message: string, troubleshooting?: string) {
|
|
109
|
-
super('CONFIG_ERROR', message, troubleshooting);
|
|
110
|
-
this.name = 'ConfigurationError';
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export class InvalidEnvironmentValueError extends ConfigurationError {
|
|
115
|
-
constructor(key: string, value: string, expectedFormat: string) {
|
|
116
|
-
super(
|
|
117
|
-
`Invalid value for ${key}: ${value}`,
|
|
118
|
-
`Expected format: ${expectedFormat}`
|
|
119
|
-
);
|
|
120
|
-
this.name = 'InvalidEnvironmentValueError';
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
export class PluginConfigurationError extends ConfigurationError {
|
|
125
|
-
constructor(pluginName: string, details: string) {
|
|
126
|
-
super(
|
|
127
|
-
`Failed to configure plugin ${pluginName}`,
|
|
128
|
-
details
|
|
129
|
-
);
|
|
130
|
-
this.name = 'PluginConfigurationError';
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Service health errors
|
|
136
|
-
*/
|
|
137
|
-
export class ServiceHealthError extends OnboardingError {
|
|
138
|
-
constructor(serviceName: string, timeout: number) {
|
|
139
|
-
super(
|
|
140
|
-
'SERVICE_HEALTH_ERROR',
|
|
141
|
-
`Service '${serviceName}' did not become healthy within ${timeout}ms`,
|
|
142
|
-
`Check service logs:\n docker-compose logs ${serviceName}\n\n` +
|
|
143
|
-
'Or check container status:\n docker ps -a'
|
|
144
|
-
);
|
|
145
|
-
this.name = 'ServiceHealthError';
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Type guard to check if an error is an OnboardingError
|
|
151
|
-
*/
|
|
152
|
-
export function isOnboardingError(error: unknown): error is OnboardingError {
|
|
153
|
-
return error instanceof OnboardingError;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Format error for user display
|
|
158
|
-
*/
|
|
159
|
-
export function formatErrorForUser(error: unknown): string {
|
|
160
|
-
if (isOnboardingError(error)) {
|
|
161
|
-
let message = `ā ${error.message}`;
|
|
162
|
-
if (error.troubleshooting) {
|
|
163
|
-
message += `\n\nš” Troubleshooting:\n${error.troubleshooting}`;
|
|
164
|
-
}
|
|
165
|
-
return message;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
if (error instanceof Error) {
|
|
169
|
-
return `ā Unexpected error: ${error.message}`;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
return `ā An unknown error occurred`;
|
|
173
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Custom error types for better error handling and troubleshooting
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Base error class for all onboarding errors
|
|
7
|
+
*/
|
|
8
|
+
export class OnboardingError extends Error {
|
|
9
|
+
constructor(
|
|
10
|
+
public readonly code: string,
|
|
11
|
+
message: string,
|
|
12
|
+
public readonly troubleshooting?: string
|
|
13
|
+
) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.name = 'OnboardingError';
|
|
16
|
+
Error.captureStackTrace(this, this.constructor);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Docker-related errors
|
|
22
|
+
*/
|
|
23
|
+
export class DockerError extends OnboardingError {
|
|
24
|
+
constructor(message: string, troubleshooting?: string) {
|
|
25
|
+
super('DOCKER_ERROR', message, troubleshooting);
|
|
26
|
+
this.name = 'DockerError';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export class DockerNotInstalledError extends DockerError {
|
|
31
|
+
constructor() {
|
|
32
|
+
super(
|
|
33
|
+
'Docker is not installed on this system',
|
|
34
|
+
'Please install Docker from: https://docs.docker.com/get-docker/'
|
|
35
|
+
);
|
|
36
|
+
this.name = 'DockerNotInstalledError';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export class DockerNotRunningError extends DockerError {
|
|
41
|
+
constructor() {
|
|
42
|
+
super(
|
|
43
|
+
'Docker daemon is not running',
|
|
44
|
+
'Please start Docker Desktop or Docker daemon, then try again'
|
|
45
|
+
);
|
|
46
|
+
this.name = 'DockerNotRunningError';
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export class DockerPermissionError extends DockerError {
|
|
51
|
+
constructor() {
|
|
52
|
+
super(
|
|
53
|
+
'Permission denied when accessing Docker',
|
|
54
|
+
'Try running with sudo or add your user to the docker group:\n' +
|
|
55
|
+
' sudo usermod -aG docker $USER\n' +
|
|
56
|
+
' Then log out and log back in'
|
|
57
|
+
);
|
|
58
|
+
this.name = 'DockerPermissionError';
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export class DockerComposeError extends DockerError {
|
|
63
|
+
constructor(operation: string, details?: string) {
|
|
64
|
+
super(
|
|
65
|
+
`Failed to ${operation} with docker-compose`,
|
|
66
|
+
details || 'Check docker-compose logs for more details:\n docker-compose logs'
|
|
67
|
+
);
|
|
68
|
+
this.name = 'DockerComposeError';
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* File system errors
|
|
74
|
+
*/
|
|
75
|
+
export class FileSystemError extends OnboardingError {
|
|
76
|
+
constructor(message: string, public readonly path: string, troubleshooting?: string) {
|
|
77
|
+
super('FILESYSTEM_ERROR', message, troubleshooting);
|
|
78
|
+
this.name = 'FileSystemError';
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export class DirectoryNotWritableError extends FileSystemError {
|
|
83
|
+
constructor(path: string) {
|
|
84
|
+
super(
|
|
85
|
+
`Directory is not writable: ${path}`,
|
|
86
|
+
path,
|
|
87
|
+
'Check directory permissions or choose a different directory'
|
|
88
|
+
);
|
|
89
|
+
this.name = 'DirectoryNotWritableError';
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export class FileNotFoundError extends FileSystemError {
|
|
94
|
+
constructor(path: string) {
|
|
95
|
+
super(
|
|
96
|
+
`File not found: ${path}`,
|
|
97
|
+
path,
|
|
98
|
+
'Ensure the file exists or check the path'
|
|
99
|
+
);
|
|
100
|
+
this.name = 'FileNotFoundError';
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Configuration errors
|
|
106
|
+
*/
|
|
107
|
+
export class ConfigurationError extends OnboardingError {
|
|
108
|
+
constructor(message: string, troubleshooting?: string) {
|
|
109
|
+
super('CONFIG_ERROR', message, troubleshooting);
|
|
110
|
+
this.name = 'ConfigurationError';
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export class InvalidEnvironmentValueError extends ConfigurationError {
|
|
115
|
+
constructor(key: string, value: string, expectedFormat: string) {
|
|
116
|
+
super(
|
|
117
|
+
`Invalid value for ${key}: ${value}`,
|
|
118
|
+
`Expected format: ${expectedFormat}`
|
|
119
|
+
);
|
|
120
|
+
this.name = 'InvalidEnvironmentValueError';
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export class PluginConfigurationError extends ConfigurationError {
|
|
125
|
+
constructor(pluginName: string, details: string) {
|
|
126
|
+
super(
|
|
127
|
+
`Failed to configure plugin ${pluginName}`,
|
|
128
|
+
details
|
|
129
|
+
);
|
|
130
|
+
this.name = 'PluginConfigurationError';
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Service health errors
|
|
136
|
+
*/
|
|
137
|
+
export class ServiceHealthError extends OnboardingError {
|
|
138
|
+
constructor(serviceName: string, timeout: number) {
|
|
139
|
+
super(
|
|
140
|
+
'SERVICE_HEALTH_ERROR',
|
|
141
|
+
`Service '${serviceName}' did not become healthy within ${timeout}ms`,
|
|
142
|
+
`Check service logs:\n docker-compose logs ${serviceName}\n\n` +
|
|
143
|
+
'Or check container status:\n docker ps -a'
|
|
144
|
+
);
|
|
145
|
+
this.name = 'ServiceHealthError';
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Type guard to check if an error is an OnboardingError
|
|
151
|
+
*/
|
|
152
|
+
export function isOnboardingError(error: unknown): error is OnboardingError {
|
|
153
|
+
return error instanceof OnboardingError;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Format error for user display
|
|
158
|
+
*/
|
|
159
|
+
export function formatErrorForUser(error: unknown): string {
|
|
160
|
+
if (isOnboardingError(error)) {
|
|
161
|
+
let message = `ā ${error.message}`;
|
|
162
|
+
if (error.troubleshooting) {
|
|
163
|
+
message += `\n\nš” Troubleshooting:\n${error.troubleshooting}`;
|
|
164
|
+
}
|
|
165
|
+
return message;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (error instanceof Error) {
|
|
169
|
+
return `ā Unexpected error: ${error.message}`;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return `ā An unknown error occurred`;
|
|
173
|
+
}
|
package/src/types/index.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from './errors.js';
|
|
2
|
-
export * from './domain.js';
|
|
1
|
+
export * from './errors.js';
|
|
2
|
+
export * from './domain.js';
|
package/src/ui.ts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized UI helpers ā themed intro/outro and cancellation handling.
|
|
3
|
+
*
|
|
4
|
+
* NOTE: Individual @clack/prompts functions (text, confirm, select, etc.)
|
|
5
|
+
* should be imported directly from '@clack/prompts' in each consumer file.
|
|
6
|
+
* Re-exporting from here causes TypeScript resolution issues with .d.mts types.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { intro as clackIntro, outro as clackOutro, cancel as clackCancel, isCancel, log as clackLog, note as clackNote, spinner as clackSpinner } from '@clack/prompts';
|
|
10
|
+
import chalk from 'chalk';
|
|
11
|
+
import { getLoggerConfig } from './utils/logger.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Themed intro ā blue bar
|
|
15
|
+
*/
|
|
16
|
+
export function intro(title?: string): void {
|
|
17
|
+
if (getLoggerConfig().silent) return;
|
|
18
|
+
clackIntro(chalk.bgBlueBright.black(` ${title ?? ''} `));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Themed outro ā blue text
|
|
23
|
+
*/
|
|
24
|
+
export function outro(message?: string): void {
|
|
25
|
+
if (getLoggerConfig().silent) return;
|
|
26
|
+
clackOutro(chalk.blueBright(message ?? 'Done'));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Wrapped log functions that respect silent mode
|
|
31
|
+
*/
|
|
32
|
+
export const log = {
|
|
33
|
+
step: (message: string) => {
|
|
34
|
+
if (getLoggerConfig().silent) return;
|
|
35
|
+
clackLog.step(message);
|
|
36
|
+
},
|
|
37
|
+
info: (message: string) => {
|
|
38
|
+
if (getLoggerConfig().silent) return;
|
|
39
|
+
clackLog.info(message);
|
|
40
|
+
},
|
|
41
|
+
warning: (message: string) => {
|
|
42
|
+
if (getLoggerConfig().silent) return;
|
|
43
|
+
clackLog.warning(message);
|
|
44
|
+
},
|
|
45
|
+
error: (message: string) => {
|
|
46
|
+
if (getLoggerConfig().silent) return;
|
|
47
|
+
clackLog.error(message);
|
|
48
|
+
},
|
|
49
|
+
success: (message: string) => {
|
|
50
|
+
if (getLoggerConfig().silent) return;
|
|
51
|
+
clackLog.success(message);
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Wrapped note function that respects silent mode
|
|
57
|
+
*/
|
|
58
|
+
export function note(message: string, title?: string): void {
|
|
59
|
+
if (getLoggerConfig().silent) return;
|
|
60
|
+
clackNote(message, title);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Wrapped spinner that respects silent mode
|
|
65
|
+
* Returns a no-op spinner in silent mode
|
|
66
|
+
*/
|
|
67
|
+
export function spinner() {
|
|
68
|
+
if (getLoggerConfig().silent) {
|
|
69
|
+
// Return a no-op spinner with all required methods
|
|
70
|
+
return {
|
|
71
|
+
start: () => {},
|
|
72
|
+
stop: () => {},
|
|
73
|
+
message: () => {},
|
|
74
|
+
error: () => {},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return clackSpinner();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Handle user cancellation (Ctrl-C) for any prompt value.
|
|
82
|
+
* Exits the process with code 0 after printing a message.
|
|
83
|
+
*/
|
|
84
|
+
export function handleCancel(value: unknown, message = 'Setup cancelled.'): void {
|
|
85
|
+
if (isCancel(value)) {
|
|
86
|
+
if (!getLoggerConfig().silent) {
|
|
87
|
+
clackCancel(chalk.blueBright(message));
|
|
88
|
+
}
|
|
89
|
+
process.exit(0);
|
|
90
|
+
}
|
|
91
|
+
}
|
package/src/utils/index.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from './logger.js';
|
|
1
|
+
export * from './logger.js';
|