ante-erp-cli 1.7.2 → 1.7.4

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/bin/ante-cli.js CHANGED
@@ -212,6 +212,9 @@ program
212
212
  .option('--frontend <url>', 'Frontend domain/URL')
213
213
  .option('--api <url>', 'API domain/URL')
214
214
  .option('--detect', 'Auto-detect public IP address')
215
+ .option('--ssl, --enable-ssl', 'Enable SSL certificate (Let\'s Encrypt)')
216
+ .option('--email <email>', 'Email for SSL certificate notifications')
217
+ .option('--ssl-staging', 'Use Let\'s Encrypt staging environment (for testing)')
215
218
  .option('--no-interactive', 'Non-interactive mode')
216
219
  .action(setDomain);
217
220
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ante-erp-cli",
3
- "version": "1.7.2",
3
+ "version": "1.7.4",
4
4
  "description": "Comprehensive CLI tool for managing ANTE ERP self-hosted installations",
5
5
  "type": "module",
6
6
  "bin": {
@@ -7,6 +7,7 @@ import { getInstallDir } from '../utils/config.js';
7
7
  import { detectPublicIPWithFeedback, buildURL, isValidIPv4 } from '../utils/network.js';
8
8
  import { configureNginx, requiresNginx } from '../utils/nginx.js';
9
9
  import { pullImages, stopServices, startServices, waitForServiceHealthy } from '../utils/docker.js';
10
+ import { obtainSSLCertificate, updateNginxForSSL, setupAutoRenewal, extractDomain } from '../utils/ssl.js';
10
11
 
11
12
  /**
12
13
  * Validate URL format with proper hostname and protocol checking
@@ -42,6 +43,22 @@ function validateUrl(url) {
42
43
  }
43
44
  }
44
45
 
46
+ /**
47
+ * Validate email format
48
+ * @param {string} email - Email to validate
49
+ * @returns {boolean|string} True if valid, error message if invalid
50
+ */
51
+ function validateEmail(email) {
52
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
53
+ if (!email || email.trim() === '') {
54
+ return 'Email is required';
55
+ }
56
+ if (!emailRegex.test(email)) {
57
+ return 'Please enter a valid email address';
58
+ }
59
+ return true;
60
+ }
61
+
45
62
  /**
46
63
  * Sanitize URL by normalizing common formatting issues
47
64
  * @param {string} url - URL to sanitize
@@ -279,7 +296,8 @@ export async function setDomain(options) {
279
296
  console.log(chalk.green('āœ“ Configuration updated'));
280
297
 
281
298
  // Configure NGINX if needed (for domains or HTTPS)
282
- if (requiresNginx(frontendUrl, apiUrl)) {
299
+ const needsNginx = requiresNginx(frontendUrl, apiUrl);
300
+ if (needsNginx) {
283
301
  console.log(chalk.gray('\nšŸ”§ Setting up reverse proxy...\n'));
284
302
 
285
303
  try {
@@ -295,6 +313,109 @@ export async function setDomain(options) {
295
313
  }
296
314
  }
297
315
 
316
+ // Check if HTTPS is configured and offer SSL setup
317
+ const isHttps = frontendUrl.startsWith('https://') || apiUrl.startsWith('https://');
318
+ const frontendDomain = extractDomain(frontendUrl);
319
+ const apiDomain = extractDomain(apiUrl);
320
+ const isDomainName = !frontendDomain.match(/^(\d+\.){3}\d+$/) && frontendDomain !== 'localhost';
321
+
322
+ if (isHttps && isDomainName && needsNginx) {
323
+ // SSL setup workflow
324
+ let enableSsl = options.ssl || false;
325
+ let sslEmail = options.email || '';
326
+
327
+ // If not specified via flags, ask in interactive mode
328
+ if (options.interactive !== false && !options.ssl) {
329
+ console.log(chalk.cyan('\nšŸ”’ SSL/HTTPS Configuration\n'));
330
+ console.log(chalk.gray('You\'re using HTTPS URLs. Would you like to obtain SSL certificates now?\n'));
331
+ console.log(chalk.gray('This will:'));
332
+ console.log(chalk.gray(' • Obtain free SSL certificates from Let\'s Encrypt'));
333
+ console.log(chalk.gray(' • Configure NGINX for HTTPS'));
334
+ console.log(chalk.gray(' • Set up automatic certificate renewal\n'));
335
+
336
+ const sslPrompt = await inquirer.prompt([
337
+ {
338
+ type: 'confirm',
339
+ name: 'enable',
340
+ message: 'Enable SSL certificate now?',
341
+ default: true
342
+ }
343
+ ]);
344
+
345
+ enableSsl = sslPrompt.enable;
346
+
347
+ if (enableSsl) {
348
+ const emailPrompt = await inquirer.prompt([
349
+ {
350
+ type: 'input',
351
+ name: 'email',
352
+ message: 'Email address for certificate notifications:',
353
+ validate: validateEmail
354
+ }
355
+ ]);
356
+ sslEmail = emailPrompt.email;
357
+ }
358
+ }
359
+
360
+ // Execute SSL setup if enabled
361
+ if (enableSsl) {
362
+ if (!sslEmail) {
363
+ console.log(chalk.yellow('\n⚠ SSL setup skipped: Email address required'));
364
+ console.log(chalk.gray(' Run "ante ssl enable --email your@email.com" to enable SSL later\n'));
365
+ } else {
366
+ try {
367
+ console.log(chalk.bold('\nšŸ”’ Setting up SSL/HTTPS...\n'));
368
+
369
+ // Step 1: Obtain certificates
370
+ console.log(chalk.cyan('šŸ“‹ Obtaining SSL certificates...\n'));
371
+
372
+ const domains = [];
373
+ if (frontendDomain !== 'localhost' && !frontendDomain.match(/^\d+\.\d+\.\d+\.\d+$/)) {
374
+ domains.push(frontendDomain);
375
+ }
376
+ if (apiDomain !== frontendDomain && apiDomain !== 'localhost' && !apiDomain.match(/^\d+\.\d+\.\d+\.\d+$/)) {
377
+ domains.push(apiDomain);
378
+ }
379
+
380
+ for (const domain of domains) {
381
+ console.log(chalk.gray(` Obtaining certificate for ${domain}...`));
382
+ await obtainSSLCertificate({
383
+ domain,
384
+ email: sslEmail,
385
+ staging: options.sslStaging || false
386
+ });
387
+ }
388
+
389
+ console.log(chalk.green('\nāœ“ SSL certificates obtained\n'));
390
+
391
+ // Step 2: Update NGINX for HTTPS
392
+ console.log(chalk.cyan('šŸ”§ Configuring NGINX for HTTPS...\n'));
393
+
394
+ await updateNginxForSSL({
395
+ frontendDomain: frontendUrl,
396
+ apiDomain: apiUrl,
397
+ frontendPort: 8080,
398
+ apiPort: 3001
399
+ });
400
+
401
+ // Step 3: Setup auto-renewal
402
+ console.log(chalk.cyan('šŸ”„ Setting up automatic certificate renewal...\n'));
403
+ await setupAutoRenewal();
404
+
405
+ console.log(chalk.green('āœ“ SSL/HTTPS configured successfully\n'));
406
+
407
+ } catch (error) {
408
+ console.log(chalk.red('\nāœ— SSL setup failed:'), error.message);
409
+ console.log(chalk.yellow('\n⚠ You can enable SSL later with:'));
410
+ console.log(chalk.gray(` ante ssl enable --email ${sslEmail}\n`));
411
+ }
412
+ }
413
+ } else if (options.interactive !== false) {
414
+ console.log(chalk.gray('\nSSL setup skipped. You can enable it later with:'));
415
+ console.log(chalk.gray(' ante ssl enable --email your@email.com\n'));
416
+ }
417
+ }
418
+
298
419
  // Restart containers to apply new environment variables
299
420
  console.log(chalk.gray('\nšŸ”„ Restarting services with updated configuration...\n'));
300
421