@startanaicompany/cli 1.1.0 → 1.3.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.
- package/CLAUDE.md +112 -7
- package/README.md +62 -8
- package/bin/saac.js +59 -2
- package/create-application-update.md +759 -0
- package/package.json +2 -2
- package/src/commands/create.js +278 -4
- package/src/commands/status.js +164 -4
- package/src/commands/update.js +284 -0
- package/src/lib/api.js +10 -0
- package/src/lib/config.js +8 -7
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@startanaicompany/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Official CLI for StartAnAiCompany.com - Deploy AI recruitment sites with ease",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"saac": "
|
|
7
|
+
"saac": "bin/saac.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"test": "echo \"Error: no test specified\" && exit 1",
|
package/src/commands/create.js
CHANGED
|
@@ -1,4 +1,278 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Create command - Create a new application
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const api = require('../lib/api');
|
|
6
|
+
const { isAuthenticated, saveProjectConfig } = require('../lib/config');
|
|
7
|
+
const logger = require('../lib/logger');
|
|
8
|
+
|
|
9
|
+
async function create(name, options) {
|
|
10
|
+
try {
|
|
11
|
+
// Check authentication
|
|
12
|
+
if (!isAuthenticated()) {
|
|
13
|
+
logger.error('Not logged in');
|
|
14
|
+
logger.newline();
|
|
15
|
+
logger.info('Run:');
|
|
16
|
+
logger.log(' saac login -e <email> -k <api-key>');
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Validate required fields
|
|
21
|
+
if (!name) {
|
|
22
|
+
logger.error('Application name is required');
|
|
23
|
+
logger.newline();
|
|
24
|
+
logger.info('Usage:');
|
|
25
|
+
logger.log(' saac create <name> [options]');
|
|
26
|
+
logger.newline();
|
|
27
|
+
logger.info('Required options:');
|
|
28
|
+
logger.log(' -s, --subdomain <subdomain> Subdomain for your app');
|
|
29
|
+
logger.log(' -r, --repository <url> Git repository URL (SSH format)');
|
|
30
|
+
logger.log(' -t, --git-token <token> Git API token');
|
|
31
|
+
logger.newline();
|
|
32
|
+
logger.info('Optional options:');
|
|
33
|
+
logger.log(' -b, --branch <branch> Git branch (default: master)');
|
|
34
|
+
logger.log(' -d, --domain-suffix <suffix> Domain suffix (default: startanaicompany.com)');
|
|
35
|
+
logger.log(' -p, --port <port> Port to expose (default: 3000)');
|
|
36
|
+
logger.log(' --build-pack <pack> Build pack: dockercompose, nixpacks, dockerfile, static');
|
|
37
|
+
logger.log(' --install-cmd <command> Install command (e.g., "pnpm install")');
|
|
38
|
+
logger.log(' --build-cmd <command> Build command (e.g., "npm run build")');
|
|
39
|
+
logger.log(' --start-cmd <command> Start command (e.g., "node server.js")');
|
|
40
|
+
logger.log(' --pre-deploy-cmd <command> Pre-deployment command (e.g., "npm run migrate")');
|
|
41
|
+
logger.log(' --post-deploy-cmd <command> Post-deployment command (e.g., "npm run seed")');
|
|
42
|
+
logger.log(' --health-check Enable health checks');
|
|
43
|
+
logger.log(' --health-path <path> Health check path (default: /health)');
|
|
44
|
+
logger.log(' --health-interval <seconds> Health check interval in seconds');
|
|
45
|
+
logger.log(' --health-timeout <seconds> Health check timeout in seconds');
|
|
46
|
+
logger.log(' --health-retries <count> Health check retries (1-10)');
|
|
47
|
+
logger.log(' --cpu-limit <limit> CPU limit (e.g., "1", "2.5")');
|
|
48
|
+
logger.log(' --memory-limit <limit> Memory limit (e.g., "512M", "2G")');
|
|
49
|
+
logger.log(' --env <KEY=VALUE> Environment variable (can be used multiple times)');
|
|
50
|
+
logger.newline();
|
|
51
|
+
logger.info('Example:');
|
|
52
|
+
logger.log(' saac create my-app -s myapp -r git@git.startanaicompany.com:user/repo.git -t abc123');
|
|
53
|
+
logger.log(' saac create api -s api -r git@git... -t abc123 --build-pack nixpacks --port 8080');
|
|
54
|
+
logger.log(' saac create web -s web -r git@git... -t abc123 --health-check --pre-deploy-cmd "npm run migrate"');
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (!options.subdomain || !options.repository || !options.gitToken) {
|
|
59
|
+
logger.error('Missing required options: subdomain, repository, and git-token are required');
|
|
60
|
+
logger.newline();
|
|
61
|
+
logger.info('Example:');
|
|
62
|
+
logger.log(` saac create ${name} -s myapp -r git@git.startanaicompany.com:user/repo.git -t your_token`);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
logger.section(`Creating Application: ${name}`);
|
|
67
|
+
logger.newline();
|
|
68
|
+
|
|
69
|
+
// Build application payload
|
|
70
|
+
const appData = {
|
|
71
|
+
name: name,
|
|
72
|
+
subdomain: options.subdomain,
|
|
73
|
+
domain_suffix: options.domainSuffix || 'startanaicompany.com',
|
|
74
|
+
git_repository: options.repository,
|
|
75
|
+
git_branch: options.branch || 'master',
|
|
76
|
+
git_api_token: options.gitToken,
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// Optional: Port configuration
|
|
80
|
+
if (options.port) {
|
|
81
|
+
appData.ports_exposes = options.port;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Optional: Build pack
|
|
85
|
+
if (options.buildPack) {
|
|
86
|
+
const validBuildPacks = ['dockercompose', 'nixpacks', 'dockerfile', 'static'];
|
|
87
|
+
if (!validBuildPacks.includes(options.buildPack)) {
|
|
88
|
+
logger.error(`Invalid build pack: ${options.buildPack}`);
|
|
89
|
+
logger.info(`Must be one of: ${validBuildPacks.join(', ')}`);
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
appData.build_pack = options.buildPack;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Optional: Custom commands
|
|
96
|
+
if (options.installCmd) {
|
|
97
|
+
appData.install_command = options.installCmd;
|
|
98
|
+
}
|
|
99
|
+
if (options.buildCmd) {
|
|
100
|
+
appData.build_command = options.buildCmd;
|
|
101
|
+
}
|
|
102
|
+
if (options.startCmd) {
|
|
103
|
+
appData.start_command = options.startCmd;
|
|
104
|
+
}
|
|
105
|
+
if (options.preDeployCmd) {
|
|
106
|
+
appData.pre_deployment_command = options.preDeployCmd;
|
|
107
|
+
}
|
|
108
|
+
if (options.postDeployCmd) {
|
|
109
|
+
appData.post_deployment_command = options.postDeployCmd;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Optional: Resource limits
|
|
113
|
+
if (options.cpuLimit) {
|
|
114
|
+
appData.cpu_limit = options.cpuLimit;
|
|
115
|
+
}
|
|
116
|
+
if (options.memoryLimit) {
|
|
117
|
+
appData.memory_limit = options.memoryLimit;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Optional: Health check configuration
|
|
121
|
+
if (options.healthCheck) {
|
|
122
|
+
appData.health_check_enabled = true;
|
|
123
|
+
if (options.healthPath) {
|
|
124
|
+
appData.health_check_path = options.healthPath;
|
|
125
|
+
}
|
|
126
|
+
if (options.healthInterval) {
|
|
127
|
+
appData.health_check_interval = parseInt(options.healthInterval, 10);
|
|
128
|
+
}
|
|
129
|
+
if (options.healthTimeout) {
|
|
130
|
+
appData.health_check_timeout = parseInt(options.healthTimeout, 10);
|
|
131
|
+
}
|
|
132
|
+
if (options.healthRetries) {
|
|
133
|
+
const retries = parseInt(options.healthRetries, 10);
|
|
134
|
+
if (retries < 1 || retries > 10) {
|
|
135
|
+
logger.error('Health check retries must be between 1 and 10');
|
|
136
|
+
process.exit(1);
|
|
137
|
+
}
|
|
138
|
+
appData.health_check_retries = retries;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Optional: Environment variables
|
|
143
|
+
if (options.env) {
|
|
144
|
+
const envVars = {};
|
|
145
|
+
const envArray = Array.isArray(options.env) ? options.env : [options.env];
|
|
146
|
+
|
|
147
|
+
for (const envStr of envArray) {
|
|
148
|
+
const [key, ...valueParts] = envStr.split('=');
|
|
149
|
+
const value = valueParts.join('='); // Handle values with '=' in them
|
|
150
|
+
|
|
151
|
+
if (!key || value === undefined) {
|
|
152
|
+
logger.error(`Invalid environment variable format: ${envStr}`);
|
|
153
|
+
logger.info('Use format: KEY=VALUE');
|
|
154
|
+
process.exit(1);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
envVars[key] = value;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (Object.keys(envVars).length > 50) {
|
|
161
|
+
logger.error('Maximum 50 environment variables allowed');
|
|
162
|
+
process.exit(1);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
appData.environment_variables = envVars;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Show configuration summary
|
|
169
|
+
logger.info('Configuration:');
|
|
170
|
+
logger.field('Name', appData.name);
|
|
171
|
+
logger.field('Subdomain', `${appData.subdomain}.${appData.domain_suffix}`);
|
|
172
|
+
logger.field('Repository', appData.git_repository);
|
|
173
|
+
logger.field('Branch', appData.git_branch);
|
|
174
|
+
if (appData.ports_exposes) {
|
|
175
|
+
logger.field('Port', appData.ports_exposes);
|
|
176
|
+
}
|
|
177
|
+
if (appData.build_pack) {
|
|
178
|
+
logger.field('Build Pack', appData.build_pack);
|
|
179
|
+
}
|
|
180
|
+
if (appData.cpu_limit || appData.memory_limit) {
|
|
181
|
+
const limits = [];
|
|
182
|
+
if (appData.cpu_limit) limits.push(`CPU: ${appData.cpu_limit}`);
|
|
183
|
+
if (appData.memory_limit) limits.push(`Memory: ${appData.memory_limit}`);
|
|
184
|
+
logger.field('Resource Limits', limits.join(', '));
|
|
185
|
+
logger.warn('Note: Free tier limited to 1 vCPU, 1024M RAM');
|
|
186
|
+
}
|
|
187
|
+
if (appData.health_check_enabled) {
|
|
188
|
+
logger.field('Health Check', `Enabled on ${appData.health_check_path || '/health'}`);
|
|
189
|
+
}
|
|
190
|
+
if (appData.pre_deployment_command) {
|
|
191
|
+
logger.field('Pre-Deploy Hook', appData.pre_deployment_command);
|
|
192
|
+
}
|
|
193
|
+
if (appData.environment_variables) {
|
|
194
|
+
logger.field('Environment Vars', `${Object.keys(appData.environment_variables).length} variable(s)`);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
logger.newline();
|
|
198
|
+
|
|
199
|
+
const spin = logger.spinner('Creating application...').start();
|
|
200
|
+
|
|
201
|
+
try {
|
|
202
|
+
const result = await api.createApplication(appData);
|
|
203
|
+
|
|
204
|
+
spin.succeed('Application created successfully!');
|
|
205
|
+
|
|
206
|
+
// Save project configuration
|
|
207
|
+
saveProjectConfig({
|
|
208
|
+
applicationUuid: result.coolify_app_uuid,
|
|
209
|
+
applicationName: result.app_name,
|
|
210
|
+
subdomain: result.subdomain,
|
|
211
|
+
domainSuffix: appData.domain_suffix,
|
|
212
|
+
gitRepository: appData.git_repository,
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
logger.newline();
|
|
216
|
+
logger.success('Application created!');
|
|
217
|
+
logger.newline();
|
|
218
|
+
logger.field('Name', result.app_name);
|
|
219
|
+
logger.field('Domain', result.domain);
|
|
220
|
+
logger.field('UUID', result.coolify_app_uuid);
|
|
221
|
+
logger.field('Status', result.deployment_status);
|
|
222
|
+
logger.newline();
|
|
223
|
+
|
|
224
|
+
// Show next steps
|
|
225
|
+
if (result.next_steps && result.next_steps.length > 0) {
|
|
226
|
+
logger.info('Next Steps:');
|
|
227
|
+
result.next_steps.forEach((step, index) => {
|
|
228
|
+
logger.log(` ${index + 1}. ${step}`);
|
|
229
|
+
});
|
|
230
|
+
logger.newline();
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
logger.info('Useful commands:');
|
|
234
|
+
logger.log(` saac deploy Deploy your application`);
|
|
235
|
+
logger.log(` saac logs --follow View deployment logs`);
|
|
236
|
+
logger.log(` saac status Check application status`);
|
|
237
|
+
logger.log(` saac env set KEY=VALUE Set environment variables`);
|
|
238
|
+
|
|
239
|
+
} catch (error) {
|
|
240
|
+
spin.fail('Application creation failed');
|
|
241
|
+
|
|
242
|
+
if (error.response?.status === 403) {
|
|
243
|
+
const data = error.response.data;
|
|
244
|
+
logger.newline();
|
|
245
|
+
logger.error('Quota exceeded');
|
|
246
|
+
if (data.current_tier) {
|
|
247
|
+
logger.field('Current Tier', data.current_tier);
|
|
248
|
+
}
|
|
249
|
+
logger.newline();
|
|
250
|
+
logger.warn(data.error || data.message);
|
|
251
|
+
if (data.upgrade_info) {
|
|
252
|
+
logger.info(data.upgrade_info);
|
|
253
|
+
}
|
|
254
|
+
} else if (error.response?.status === 400) {
|
|
255
|
+
const data = error.response.data;
|
|
256
|
+
logger.newline();
|
|
257
|
+
logger.error('Validation failed');
|
|
258
|
+
if (data.details) {
|
|
259
|
+
logger.newline();
|
|
260
|
+
Object.entries(data.details).forEach(([field, message]) => {
|
|
261
|
+
logger.log(` ${logger.chalk.yellow(field)}: ${message}`);
|
|
262
|
+
});
|
|
263
|
+
} else {
|
|
264
|
+
logger.log(` ${data.message || data.error}`);
|
|
265
|
+
}
|
|
266
|
+
} else {
|
|
267
|
+
throw error;
|
|
268
|
+
}
|
|
269
|
+
process.exit(1);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
} catch (error) {
|
|
273
|
+
logger.error(error.response?.data?.message || error.message);
|
|
274
|
+
process.exit(1);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
module.exports = create;
|
package/src/commands/status.js
CHANGED
|
@@ -1,4 +1,164 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Status command - Show current login and account status
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const api = require('../lib/api');
|
|
6
|
+
const { getUser, isAuthenticated, isTokenExpiringSoon } = require('../lib/config');
|
|
7
|
+
const logger = require('../lib/logger');
|
|
8
|
+
const { table } = require('table');
|
|
9
|
+
|
|
10
|
+
async function status() {
|
|
11
|
+
try {
|
|
12
|
+
logger.section('SAAC Status');
|
|
13
|
+
logger.newline();
|
|
14
|
+
|
|
15
|
+
// Check if logged in locally (silently)
|
|
16
|
+
if (!isAuthenticated()) {
|
|
17
|
+
logger.error('Not logged in');
|
|
18
|
+
logger.newline();
|
|
19
|
+
logger.info('Run:');
|
|
20
|
+
logger.log(' saac login -e <email> -k <api-key>');
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const user = getUser();
|
|
25
|
+
|
|
26
|
+
// Verify session with server first
|
|
27
|
+
const spin = logger.spinner('Verifying session...').start();
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
const client = api.createClient();
|
|
31
|
+
const [userInfo, appsResponse] = await Promise.all([
|
|
32
|
+
client.get('/users/me'),
|
|
33
|
+
client.get('/applications')
|
|
34
|
+
]);
|
|
35
|
+
|
|
36
|
+
spin.succeed('Session verified');
|
|
37
|
+
|
|
38
|
+
const userData = userInfo.data;
|
|
39
|
+
const applicationsData = appsResponse.data;
|
|
40
|
+
const applications = Array.isArray(applicationsData) ? applicationsData :
|
|
41
|
+
(applicationsData.applications || []);
|
|
42
|
+
|
|
43
|
+
logger.newline();
|
|
44
|
+
|
|
45
|
+
// NOW show login status (after successful verification)
|
|
46
|
+
logger.field('Status', logger.chalk.green('✓ Logged in'));
|
|
47
|
+
logger.field('Email', user.email);
|
|
48
|
+
logger.field('Verified', user.verified ? logger.chalk.green('Yes') : logger.chalk.red('No'));
|
|
49
|
+
|
|
50
|
+
// Show session info
|
|
51
|
+
if (user.sessionToken) {
|
|
52
|
+
const expiresAt = new Date(user.expiresAt);
|
|
53
|
+
const now = new Date();
|
|
54
|
+
const daysUntilExpiry = Math.floor((expiresAt - now) / (1000 * 60 * 60 * 24));
|
|
55
|
+
|
|
56
|
+
logger.field('Session expires', expiresAt.toLocaleDateString());
|
|
57
|
+
|
|
58
|
+
if (isTokenExpiringSoon()) {
|
|
59
|
+
logger.field('Warning', logger.chalk.yellow(`⚠ Session expires in ${daysUntilExpiry} days`));
|
|
60
|
+
} else {
|
|
61
|
+
logger.field('Days until expiry', daysUntilExpiry);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
logger.newline();
|
|
66
|
+
|
|
67
|
+
// Show account info
|
|
68
|
+
logger.field('User ID', userData.id);
|
|
69
|
+
logger.field('Git Username', userData.git_username || 'Not set');
|
|
70
|
+
logger.field('Applications', `${userData.application_count} / ${userData.max_applications}`);
|
|
71
|
+
|
|
72
|
+
logger.newline();
|
|
73
|
+
|
|
74
|
+
// Show applications (max 5)
|
|
75
|
+
if (applications.length === 0) {
|
|
76
|
+
logger.info('No applications yet');
|
|
77
|
+
logger.newline();
|
|
78
|
+
logger.info('Create one with: ' + logger.chalk.cyan('saac create <name>'));
|
|
79
|
+
} else {
|
|
80
|
+
const displayApps = applications.slice(0, 5);
|
|
81
|
+
const hasMore = applications.length > 5;
|
|
82
|
+
|
|
83
|
+
const data = [
|
|
84
|
+
['Name', 'Domain', 'Status', 'Created'],
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
displayApps.forEach((app) => {
|
|
88
|
+
const created = new Date(app.created_at).toLocaleDateString();
|
|
89
|
+
const status = app.status || 'unknown';
|
|
90
|
+
|
|
91
|
+
// Status with icons (handle both Coolify format and documented format)
|
|
92
|
+
let statusDisplay;
|
|
93
|
+
if (status.startsWith('running')) {
|
|
94
|
+
statusDisplay = logger.chalk.green('Running ✓');
|
|
95
|
+
} else if (status.startsWith('stopped')) {
|
|
96
|
+
statusDisplay = logger.chalk.yellow('Stopped');
|
|
97
|
+
} else {
|
|
98
|
+
switch (status) {
|
|
99
|
+
case 'active':
|
|
100
|
+
statusDisplay = logger.chalk.green('Active ✓');
|
|
101
|
+
break;
|
|
102
|
+
case 'creating':
|
|
103
|
+
statusDisplay = logger.chalk.yellow('Creating...');
|
|
104
|
+
break;
|
|
105
|
+
case 'error':
|
|
106
|
+
statusDisplay = logger.chalk.red('Error ✗');
|
|
107
|
+
break;
|
|
108
|
+
case 'suspended':
|
|
109
|
+
statusDisplay = logger.chalk.yellow('Suspended ⚠');
|
|
110
|
+
break;
|
|
111
|
+
default:
|
|
112
|
+
statusDisplay = logger.chalk.gray(status);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
data.push([
|
|
117
|
+
app.name,
|
|
118
|
+
app.domain || `${app.subdomain}.startanaicompany.com`,
|
|
119
|
+
statusDisplay,
|
|
120
|
+
created
|
|
121
|
+
]);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
console.log(table(data, {
|
|
125
|
+
header: {
|
|
126
|
+
alignment: 'center',
|
|
127
|
+
content: `Applications (showing ${displayApps.length} of ${applications.length})`,
|
|
128
|
+
},
|
|
129
|
+
}));
|
|
130
|
+
|
|
131
|
+
if (hasMore) {
|
|
132
|
+
logger.warn(`Showing first 5 applications only. You have ${applications.length - 5} more.`);
|
|
133
|
+
logger.info('Run ' + logger.chalk.cyan('saac list') + ' to see all applications');
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
} catch (error) {
|
|
138
|
+
spin.fail('Session verification failed');
|
|
139
|
+
|
|
140
|
+
logger.newline();
|
|
141
|
+
|
|
142
|
+
if (error.response?.status === 401) {
|
|
143
|
+
logger.error('Your session has expired or is invalid');
|
|
144
|
+
logger.newline();
|
|
145
|
+
logger.field('Email', user.email);
|
|
146
|
+
logger.field('Local session expires', new Date(user.expiresAt).toLocaleDateString());
|
|
147
|
+
logger.newline();
|
|
148
|
+
logger.warn('The session token is no longer valid on the server');
|
|
149
|
+
logger.info('Please login again:');
|
|
150
|
+
logger.log(' saac login -e ' + user.email + ' -k <api-key>');
|
|
151
|
+
} else {
|
|
152
|
+
logger.error('Failed to connect to server');
|
|
153
|
+
logger.error(error.message);
|
|
154
|
+
}
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
} catch (error) {
|
|
159
|
+
logger.error(error.response?.data?.message || error.message);
|
|
160
|
+
process.exit(1);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
module.exports = status;
|