ante-erp-cli 1.11.59 → 1.11.61

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ante-erp-cli",
3
- "version": "1.11.59",
3
+ "version": "1.11.61",
4
4
  "description": "Comprehensive CLI tool for managing ANTE ERP self-hosted installations",
5
5
  "type": "module",
6
6
  "bin": {
@@ -46,9 +46,9 @@ function getEnvValue(envPath, key) {
46
46
  }
47
47
 
48
48
  /**
49
- * Check if gate-app, guardian-app, or facial-web is installed by checking docker-compose.yml
49
+ * Check if optional apps are installed by checking docker-compose.yml
50
50
  * @param {string} composeFile - Path to docker-compose.yml
51
- * @returns {{hasGateApp: boolean, hasGuardianApp: boolean, hasFacialWeb: boolean}}
51
+ * @returns {{hasGateApp: boolean, hasGuardianApp: boolean, hasFacialWeb: boolean, hasPosApp: boolean, hasMlmApp: boolean, hasBackendMlm: boolean}}
52
52
  */
53
53
  function detectInstalledApps(composeFile) {
54
54
  try {
@@ -56,10 +56,13 @@ function detectInstalledApps(composeFile) {
56
56
  return {
57
57
  hasGateApp: composeContent.includes('gate-app:') || composeContent.includes('container_name: ante-gate-app'),
58
58
  hasGuardianApp: composeContent.includes('guardian-app:') || composeContent.includes('container_name: ante-guardian-app'),
59
- hasFacialWeb: composeContent.includes('facial-web:') || composeContent.includes('container_name: ante-facial-web')
59
+ hasFacialWeb: composeContent.includes('facial-web:') || composeContent.includes('container_name: ante-facial-web'),
60
+ hasPosApp: composeContent.includes('pos-app:') || composeContent.includes('container_name: ante-pos'),
61
+ hasMlmApp: composeContent.includes('mlm-app:') || composeContent.includes('container_name: ante-mlm'),
62
+ hasBackendMlm: composeContent.includes('backend-mlm:') || composeContent.includes('container_name: ante-backend-mlm')
60
63
  };
61
64
  } catch {
62
- return { hasGateApp: false, hasGuardianApp: false, hasFacialWeb: false };
65
+ return { hasGateApp: false, hasGuardianApp: false, hasFacialWeb: false, hasPosApp: false, hasMlmApp: false, hasBackendMlm: false };
63
66
  }
64
67
  }
65
68
 
@@ -87,7 +90,7 @@ export async function sslEnable(options) {
87
90
  console.log(chalk.gray(`Installation: ${installDir}\n`));
88
91
 
89
92
  // Detect which apps are installed
90
- const { hasGateApp, hasGuardianApp, hasFacialWeb } = detectInstalledApps(composeFile);
93
+ const { hasGateApp, hasGuardianApp, hasFacialWeb, hasPosApp, hasMlmApp, hasBackendMlm } = detectInstalledApps(composeFile);
91
94
 
92
95
  // Read current configuration
93
96
  const frontendUrl = getEnvValue(envPath, 'FRONTEND_URL');
@@ -95,6 +98,9 @@ export async function sslEnable(options) {
95
98
  const gateAppUrl = hasGateApp ? getEnvValue(envPath, 'GATE_APP_URL') : '';
96
99
  const guardianAppUrl = hasGuardianApp ? getEnvValue(envPath, 'GUARDIAN_APP_URL') : '';
97
100
  const facialWebUrl = hasFacialWeb ? getEnvValue(envPath, 'FACIAL_WEB_URL') : '';
101
+ const posAppUrl = hasPosApp ? getEnvValue(envPath, 'POS_APP_URL') : '';
102
+ const mlmAppUrl = hasMlmApp ? getEnvValue(envPath, 'MLM_APP_URL') : '';
103
+ const backendMlmUrl = hasBackendMlm ? getEnvValue(envPath, 'MLM_API_URL') : '';
98
104
 
99
105
  if (!frontendUrl || !apiUrl) {
100
106
  console.log(chalk.red('✗ Domain configuration not found'));
@@ -111,7 +117,10 @@ export async function sslEnable(options) {
111
117
  const allHttps = frontendUrl.startsWith('https://') && apiUrl.startsWith('https://') &&
112
118
  (!gateAppUrl || gateAppUrl.startsWith('https://')) &&
113
119
  (!guardianAppUrl || guardianAppUrl.startsWith('https://')) &&
114
- (!facialWebUrl || facialWebUrl.startsWith('https://'));
120
+ (!facialWebUrl || facialWebUrl.startsWith('https://')) &&
121
+ (!posAppUrl || posAppUrl.startsWith('https://')) &&
122
+ (!mlmAppUrl || mlmAppUrl.startsWith('https://')) &&
123
+ (!backendMlmUrl || backendMlmUrl.startsWith('https://'));
115
124
 
116
125
  if (allHttps) {
117
126
  console.log(chalk.yellow('⚠ Domains are already configured with HTTPS:\n'));
@@ -119,6 +128,9 @@ export async function sslEnable(options) {
119
128
  if (gateAppUrl) console.log(chalk.gray(` Gate App: ${gateAppUrl}`));
120
129
  if (guardianAppUrl) console.log(chalk.gray(` Guardian: ${guardianAppUrl}`));
121
130
  if (facialWebUrl) console.log(chalk.gray(` Facial Web: ${facialWebUrl}`));
131
+ if (posAppUrl) console.log(chalk.gray(` POS App: ${posAppUrl}`));
132
+ if (mlmAppUrl) console.log(chalk.gray(` MLM App: ${mlmAppUrl}`));
133
+ if (backendMlmUrl) console.log(chalk.gray(` Backend MLM: ${backendMlmUrl}`));
122
134
  console.log(chalk.gray(` API: ${apiUrl}\n`));
123
135
 
124
136
  // Check certificate status
@@ -153,24 +165,53 @@ export async function sslEnable(options) {
153
165
  }
154
166
  }
155
167
 
168
+ if (posAppUrl) {
169
+ const posAppDomain = extractDomain(posAppUrl);
170
+ const posAppStatus = await checkSSLStatus(posAppDomain);
171
+ if (posAppStatus.installed) {
172
+ console.log(chalk.green(`✓ POS App SSL: Valid (expires in ${posAppStatus.daysUntilExpiry} days)`));
173
+ }
174
+ }
175
+
176
+ if (mlmAppUrl) {
177
+ const mlmAppDomain = extractDomain(mlmAppUrl);
178
+ const mlmAppStatus = await checkSSLStatus(mlmAppDomain);
179
+ if (mlmAppStatus.installed) {
180
+ console.log(chalk.green(`✓ MLM App SSL: Valid (expires in ${mlmAppStatus.daysUntilExpiry} days)`));
181
+ }
182
+ }
183
+
184
+ if (backendMlmUrl) {
185
+ const backendMlmDomain = extractDomain(backendMlmUrl);
186
+ const backendMlmStatus = await checkSSLStatus(backendMlmDomain);
187
+ if (backendMlmStatus.installed) {
188
+ console.log(chalk.green(`✓ Backend MLM SSL: Valid (expires in ${backendMlmStatus.daysUntilExpiry} days)`));
189
+ }
190
+ }
191
+
156
192
  if (apiStatus.installed) {
157
193
  console.log(chalk.green(`✓ API SSL: Valid (expires in ${apiStatus.daysUntilExpiry} days)`));
158
194
  }
159
195
 
160
196
  console.log();
161
197
 
162
- const { proceed } = await inquirer.prompt([
163
- {
164
- type: 'confirm',
165
- name: 'proceed',
166
- message: 'Do you want to renew or reconfigure SSL certificates?',
167
- default: false
198
+ // In non-interactive mode, automatically proceed with renewal/reconfiguration
199
+ if (options.interactive !== false) {
200
+ const { proceed } = await inquirer.prompt([
201
+ {
202
+ type: 'confirm',
203
+ name: 'proceed',
204
+ message: 'Do you want to renew or reconfigure SSL certificates?',
205
+ default: false
206
+ }
207
+ ]);
208
+
209
+ if (!proceed) {
210
+ console.log(chalk.gray('\nSSL configuration cancelled.\n'));
211
+ return;
168
212
  }
169
- ]);
170
-
171
- if (!proceed) {
172
- console.log(chalk.gray('\nSSL configuration cancelled.\n'));
173
- return;
213
+ } else {
214
+ console.log(chalk.gray('Non-interactive mode: Proceeding with SSL reconfiguration...\n'));
174
215
  }
175
216
  }
176
217
 
@@ -180,6 +221,9 @@ export async function sslEnable(options) {
180
221
  if (gateAppUrl) console.log(chalk.gray(` Gate App: ${gateAppUrl}`));
181
222
  if (guardianAppUrl) console.log(chalk.gray(` Guardian: ${guardianAppUrl}`));
182
223
  if (facialWebUrl) console.log(chalk.gray(` Facial Web: ${facialWebUrl}`));
224
+ if (posAppUrl) console.log(chalk.gray(` POS App: ${posAppUrl}`));
225
+ if (mlmAppUrl) console.log(chalk.gray(` MLM App: ${mlmAppUrl}`));
226
+ if (backendMlmUrl) console.log(chalk.gray(` Backend MLM: ${backendMlmUrl}`));
183
227
  console.log(chalk.gray(` API: ${apiUrl}\n`));
184
228
 
185
229
  // Detect domains to configure
@@ -230,6 +274,42 @@ export async function sslEnable(options) {
230
274
  }
231
275
  }
232
276
 
277
+ if (posAppUrl) {
278
+ const posAppDomain = extractDomain(posAppUrl);
279
+ if (posAppDomain !== 'localhost' && !posAppDomain.match(/^\d+\.\d+\.\d+\.\d+$/) && !domains.find(d => d.domain === posAppDomain)) {
280
+ domains.push({
281
+ name: 'POS App',
282
+ domain: posAppDomain,
283
+ port: posAppUrl.match(/:(\d+)/) ? posAppUrl.match(/:(\d+)/)[1] : 8084,
284
+ url: posAppUrl
285
+ });
286
+ }
287
+ }
288
+
289
+ if (mlmAppUrl) {
290
+ const mlmAppDomain = extractDomain(mlmAppUrl);
291
+ if (mlmAppDomain !== 'localhost' && !mlmAppDomain.match(/^\d+\.\d+\.\d+\.\d+$/) && !domains.find(d => d.domain === mlmAppDomain)) {
292
+ domains.push({
293
+ name: 'MLM App',
294
+ domain: mlmAppDomain,
295
+ port: mlmAppUrl.match(/:(\d+)/) ? mlmAppUrl.match(/:(\d+)/)[1] : 9005,
296
+ url: mlmAppUrl
297
+ });
298
+ }
299
+ }
300
+
301
+ if (backendMlmUrl) {
302
+ const backendMlmDomain = extractDomain(backendMlmUrl);
303
+ if (backendMlmDomain !== 'localhost' && !backendMlmDomain.match(/^\d+\.\d+\.\d+\.\d+$/) && !domains.find(d => d.domain === backendMlmDomain)) {
304
+ domains.push({
305
+ name: 'Backend MLM',
306
+ domain: backendMlmDomain,
307
+ port: backendMlmUrl.match(/:(\d+)/) ? backendMlmUrl.match(/:(\d+)/)[1] : 4001,
308
+ url: backendMlmUrl
309
+ });
310
+ }
311
+ }
312
+
233
313
  if (apiDomain !== 'localhost' && !apiDomain.match(/^\d+\.\d+\.\d+\.\d+$/) && apiDomain !== frontendDomain) {
234
314
  domains.push({
235
315
  name: 'API',
@@ -347,6 +427,21 @@ export async function sslEnable(options) {
347
427
  sslConfig.facialWebPort = facialWebUrl.match(/:(\d+)/) ? parseInt(facialWebUrl.match(/:(\d+)/)[1]) : 8083;
348
428
  }
349
429
 
430
+ if (posAppUrl) {
431
+ sslConfig.posAppDomain = posAppUrl;
432
+ sslConfig.posAppPort = posAppUrl.match(/:(\d+)/) ? parseInt(posAppUrl.match(/:(\d+)/)[1]) : 8084;
433
+ }
434
+
435
+ if (mlmAppUrl) {
436
+ sslConfig.mlmAppDomain = mlmAppUrl;
437
+ sslConfig.mlmAppPort = mlmAppUrl.match(/:(\d+)/) ? parseInt(mlmAppUrl.match(/:(\d+)/)[1]) : 9005;
438
+ }
439
+
440
+ if (backendMlmUrl) {
441
+ sslConfig.backendMlmDomain = backendMlmUrl;
442
+ sslConfig.backendMlmPort = backendMlmUrl.match(/:(\d+)/) ? parseInt(backendMlmUrl.match(/:(\d+)/)[1]) : 4001;
443
+ }
444
+
350
445
  await updateNginxForSSL(sslConfig);
351
446
  } catch (error) {
352
447
  console.log(chalk.red('\n✗ Failed to configure NGINX:'), error.message);
@@ -416,13 +511,16 @@ export async function sslStatus() {
416
511
  const composeFile = join(installDir, 'docker-compose.yml');
417
512
 
418
513
  // Detect which apps are installed
419
- const { hasGateApp, hasGuardianApp, hasFacialWeb } = detectInstalledApps(composeFile);
514
+ const { hasGateApp, hasGuardianApp, hasFacialWeb, hasPosApp, hasMlmApp, hasBackendMlm } = detectInstalledApps(composeFile);
420
515
 
421
516
  const frontendUrl = getEnvValue(envPath, 'FRONTEND_URL');
422
517
  const apiUrl = getEnvValue(envPath, 'API_URL');
423
518
  const gateAppUrl = hasGateApp ? getEnvValue(envPath, 'GATE_APP_URL') : '';
424
519
  const guardianAppUrl = hasGuardianApp ? getEnvValue(envPath, 'GUARDIAN_APP_URL') : '';
425
520
  const facialWebUrl = hasFacialWeb ? getEnvValue(envPath, 'FACIAL_WEB_URL') : '';
521
+ const posAppUrl = hasPosApp ? getEnvValue(envPath, 'POS_APP_URL') : '';
522
+ const mlmAppUrl = hasMlmApp ? getEnvValue(envPath, 'MLM_APP_URL') : '';
523
+ const backendMlmUrl = hasBackendMlm ? getEnvValue(envPath, 'MLM_API_URL') : '';
426
524
 
427
525
  if (!frontendUrl || !apiUrl) {
428
526
  console.log(chalk.red('✗ Domain configuration not found\n'));
@@ -451,6 +549,21 @@ export async function sslStatus() {
451
549
  domains.push({ name: 'Facial Web', domain: facialWebDomain, url: facialWebUrl });
452
550
  }
453
551
 
552
+ if (posAppUrl) {
553
+ const posAppDomain = extractDomain(posAppUrl);
554
+ domains.push({ name: 'POS App', domain: posAppDomain, url: posAppUrl });
555
+ }
556
+
557
+ if (mlmAppUrl) {
558
+ const mlmAppDomain = extractDomain(mlmAppUrl);
559
+ domains.push({ name: 'MLM App', domain: mlmAppDomain, url: mlmAppUrl });
560
+ }
561
+
562
+ if (backendMlmUrl) {
563
+ const backendMlmDomain = extractDomain(backendMlmUrl);
564
+ domains.push({ name: 'Backend MLM', domain: backendMlmDomain, url: backendMlmUrl });
565
+ }
566
+
454
567
  domains.push({ name: 'API', domain: apiDomain, url: apiUrl });
455
568
 
456
569
  for (const { name, domain, url } of domains) {
package/src/utils/ssl.js CHANGED
@@ -128,14 +128,16 @@ export async function obtainSSLCertificate(config) {
128
128
  * @param {string} [config.guardianAppDomain] - Guardian App domain URL (optional)
129
129
  * @param {string} [config.facialAppDomain] - Facial Web domain URL (optional)
130
130
  * @param {string} [config.posAppDomain] - POS App domain URL (optional)
131
- * @param {string} [config.clientAppDomain] - Client App domain URL (optional)
131
+ * @param {string} [config.mlmAppDomain] - MLM App domain URL (optional)
132
+ * @param {string} [config.backendMlmDomain] - Backend MLM API domain URL (optional)
132
133
  * @param {number} [config.frontendPort=8080] - Frontend port
133
134
  * @param {number} [config.apiPort=3001] - API port
134
135
  * @param {number} [config.gateAppPort=8081] - Gate App port
135
136
  * @param {number} [config.guardianAppPort=8082] - Guardian App port
136
137
  * @param {number} [config.facialWebPort=8083] - Facial Web port
137
138
  * @param {number} [config.posAppPort=8084] - POS App port
138
- * @param {number} [config.clientAppPort=9005] - Client App port
139
+ * @param {number} [config.mlmAppPort=9005] - MLM App port
140
+ * @param {number} [config.backendMlmPort=4001] - Backend MLM API port
139
141
  * @returns {Promise<void>}
140
142
  */
141
143
  export async function updateNginxForSSL(config) {
@@ -146,16 +148,16 @@ export async function updateNginxForSSL(config) {
146
148
  guardianAppDomain,
147
149
  facialAppDomain,
148
150
  posAppDomain,
149
- clientAppDomain,
150
- backendClientDomain,
151
+ mlmAppDomain,
152
+ backendMlmDomain,
151
153
  frontendPort = 8080,
152
154
  apiPort = 3001,
153
155
  gateAppPort = 8081,
154
156
  guardianAppPort = 8082,
155
157
  facialWebPort = 8083,
156
158
  posAppPort = 8084,
157
- clientAppPort = 9005,
158
- backendClientPort = 4001
159
+ mlmAppPort = 9005,
160
+ backendMlmPort = 4001
159
161
  } = config;
160
162
  const spinner = ora('Updating NGINX configuration for HTTPS...').start();
161
163
 
@@ -182,16 +184,16 @@ export async function updateNginxForSSL(config) {
182
184
  guardianAppDomain,
183
185
  facialAppDomain,
184
186
  posAppDomain,
185
- clientAppDomain,
186
- backendClientDomain,
187
+ mlmAppDomain,
188
+ backendMlmDomain,
187
189
  frontendPort,
188
190
  apiPort,
189
191
  gateAppPort,
190
192
  guardianAppPort,
191
193
  facialWebPort,
192
194
  posAppPort,
193
- clientAppPort,
194
- backendClientPort,
195
+ mlmAppPort,
196
+ backendMlmPort,
195
197
  ssl: true
196
198
  });
197
199