@git.zone/cli 1.21.4 → 2.0.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/assets/templates/tsconfig_update/tsconfig.json +0 -1
- package/dist_ts/00_commitinfo_data.js +2 -2
- package/dist_ts/mod_commit/index.js +5 -2
- package/dist_ts/mod_commit/mod.helpers.js +24 -9
- package/dist_ts/mod_format/classes.baseformatter.js +4 -4
- package/dist_ts/mod_format/classes.changecache.js +29 -17
- package/dist_ts/mod_format/classes.diffreporter.js +10 -4
- package/dist_ts/mod_format/classes.formatstats.js +5 -2
- package/dist_ts/mod_format/classes.rollbackmanager.js +41 -17
- package/dist_ts/mod_format/format.cleanup.js +5 -3
- package/dist_ts/mod_format/format.copy.js +12 -4
- package/dist_ts/mod_format/format.gitignore.js +14 -5
- package/dist_ts/mod_format/format.license.js +4 -2
- package/dist_ts/mod_format/format.packagejson.js +6 -2
- package/dist_ts/mod_format/format.readme.js +9 -5
- package/dist_ts/mod_format/format.tsconfig.js +7 -4
- package/dist_ts/mod_format/formatters/cleanup.formatter.js +2 -2
- package/dist_ts/mod_format/formatters/prettier.formatter.js +19 -6
- package/dist_ts/mod_format/index.js +9 -3
- package/dist_ts/mod_meta/meta.classes.meta.js +82 -17
- package/dist_ts/mod_services/classes.serviceconfiguration.d.ts +7 -0
- package/dist_ts/mod_services/classes.serviceconfiguration.js +86 -10
- package/dist_ts/mod_services/classes.servicemanager.d.ts +33 -0
- package/dist_ts/mod_services/classes.servicemanager.js +319 -10
- package/dist_ts/mod_services/helpers.d.ts +1 -1
- package/dist_ts/mod_services/helpers.js +8 -4
- package/dist_ts/mod_services/index.js +51 -27
- package/dist_ts/mod_standard/index.js +22 -9
- package/dist_ts/mod_template/index.js +2 -2
- package/dist_ts/plugins.d.ts +2 -0
- package/dist_ts/plugins.js +4 -1
- package/package.json +7 -6
- package/readme.hints.md +55 -2
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/mod_commit/index.ts +4 -4
- package/ts/mod_commit/mod.helpers.ts +23 -11
- package/ts/mod_format/classes.baseformatter.ts +3 -3
- package/ts/mod_format/classes.changecache.ts +28 -16
- package/ts/mod_format/classes.diffreporter.ts +9 -8
- package/ts/mod_format/classes.formatstats.ts +4 -4
- package/ts/mod_format/classes.rollbackmanager.ts +40 -18
- package/ts/mod_format/format.cleanup.ts +4 -4
- package/ts/mod_format/format.copy.ts +11 -3
- package/ts/mod_format/format.gitignore.ts +13 -6
- package/ts/mod_format/format.license.ts +3 -3
- package/ts/mod_format/format.packagejson.ts +5 -3
- package/ts/mod_format/format.readme.ts +8 -11
- package/ts/mod_format/format.tsconfig.ts +6 -5
- package/ts/mod_format/formatters/cleanup.formatter.ts +1 -1
- package/ts/mod_format/formatters/prettier.formatter.ts +18 -8
- package/ts/mod_format/index.ts +10 -5
- package/ts/mod_meta/meta.classes.meta.ts +84 -41
- package/ts/mod_services/classes.serviceconfiguration.ts +121 -35
- package/ts/mod_services/classes.servicemanager.ts +365 -32
- package/ts/mod_services/helpers.ts +8 -4
- package/ts/mod_services/index.ts +73 -45
- package/ts/mod_standard/index.ts +23 -10
- package/ts/mod_template/index.ts +1 -1
- package/ts/plugins.ts +4 -0
|
@@ -7,12 +7,13 @@ import { logger } from '../gitzone.logging.js';
|
|
|
7
7
|
export class ServiceManager {
|
|
8
8
|
private config: ServiceConfiguration;
|
|
9
9
|
private docker: DockerContainer;
|
|
10
|
-
|
|
10
|
+
private enabledServices: string[] | null = null;
|
|
11
|
+
|
|
11
12
|
constructor() {
|
|
12
13
|
this.config = new ServiceConfiguration();
|
|
13
14
|
this.docker = new DockerContainer();
|
|
14
15
|
}
|
|
15
|
-
|
|
16
|
+
|
|
16
17
|
/**
|
|
17
18
|
* Initialize the service manager
|
|
18
19
|
*/
|
|
@@ -22,15 +23,134 @@ export class ServiceManager {
|
|
|
22
23
|
logger.log('error', 'Error: Docker is not installed. Please install Docker first.');
|
|
23
24
|
process.exit(1);
|
|
24
25
|
}
|
|
25
|
-
|
|
26
|
+
|
|
26
27
|
// Load or create configuration
|
|
27
28
|
await this.config.loadOrCreate();
|
|
28
29
|
logger.log('info', `📋 Project: ${this.config.getConfig().PROJECT_NAME}`);
|
|
29
|
-
|
|
30
|
+
|
|
31
|
+
// Load service selection from npmextra.json
|
|
32
|
+
await this.loadServiceConfiguration();
|
|
33
|
+
|
|
30
34
|
// Validate and update ports if needed
|
|
31
35
|
await this.config.validateAndUpdatePorts();
|
|
32
36
|
}
|
|
33
|
-
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Load service configuration from npmextra.json
|
|
40
|
+
*/
|
|
41
|
+
private async loadServiceConfiguration(): Promise<void> {
|
|
42
|
+
const npmextraConfig = new plugins.npmextra.Npmextra(process.cwd());
|
|
43
|
+
const gitzoneConfig = npmextraConfig.dataFor<any>('gitzone', {});
|
|
44
|
+
|
|
45
|
+
// Check if services array exists
|
|
46
|
+
if (!gitzoneConfig.services || !Array.isArray(gitzoneConfig.services) || gitzoneConfig.services.length === 0) {
|
|
47
|
+
// Prompt user to select services
|
|
48
|
+
const smartinteract = new plugins.smartinteract.SmartInteract();
|
|
49
|
+
const response = await smartinteract.askQuestion({
|
|
50
|
+
name: 'services',
|
|
51
|
+
type: 'checkbox',
|
|
52
|
+
message: 'Which services do you want to enable for this project?',
|
|
53
|
+
choices: [
|
|
54
|
+
{ name: 'MongoDB', value: 'mongodb' },
|
|
55
|
+
{ name: 'MinIO (S3)', value: 'minio' },
|
|
56
|
+
{ name: 'Elasticsearch', value: 'elasticsearch' }
|
|
57
|
+
],
|
|
58
|
+
default: ['mongodb', 'minio', 'elasticsearch']
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
this.enabledServices = response.value || ['mongodb', 'minio', 'elasticsearch'];
|
|
62
|
+
|
|
63
|
+
// Save to npmextra.json
|
|
64
|
+
await this.saveServiceConfiguration(this.enabledServices);
|
|
65
|
+
} else {
|
|
66
|
+
this.enabledServices = gitzoneConfig.services;
|
|
67
|
+
logger.log('info', `🔧 Enabled services: ${this.enabledServices.join(', ')}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Save service configuration to npmextra.json
|
|
73
|
+
*/
|
|
74
|
+
private async saveServiceConfiguration(services: string[]): Promise<void> {
|
|
75
|
+
const npmextraPath = plugins.path.join(process.cwd(), 'npmextra.json');
|
|
76
|
+
let npmextraData: any = {};
|
|
77
|
+
|
|
78
|
+
// Read existing npmextra.json if it exists
|
|
79
|
+
if (await plugins.smartfs.file(npmextraPath).exists()) {
|
|
80
|
+
const content = await plugins.smartfs.file(npmextraPath).encoding('utf8').read();
|
|
81
|
+
npmextraData = JSON.parse(content as string);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Update gitzone.services
|
|
85
|
+
if (!npmextraData.gitzone) {
|
|
86
|
+
npmextraData.gitzone = {};
|
|
87
|
+
}
|
|
88
|
+
npmextraData.gitzone.services = services;
|
|
89
|
+
|
|
90
|
+
// Write back to npmextra.json
|
|
91
|
+
await plugins.smartfs
|
|
92
|
+
.file(npmextraPath)
|
|
93
|
+
.encoding('utf8')
|
|
94
|
+
.write(JSON.stringify(npmextraData, null, 2));
|
|
95
|
+
|
|
96
|
+
logger.log('ok', `✅ Saved service configuration to npmextra.json`);
|
|
97
|
+
logger.log('info', `🔧 Enabled services: ${services.join(', ')}`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Check if a service is enabled
|
|
102
|
+
*/
|
|
103
|
+
private isServiceEnabled(service: string): boolean {
|
|
104
|
+
if (!this.enabledServices) {
|
|
105
|
+
return true; // If no configuration, enable all
|
|
106
|
+
}
|
|
107
|
+
return this.enabledServices.includes(service);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Start all enabled services
|
|
112
|
+
*/
|
|
113
|
+
public async startAll(): Promise<void> {
|
|
114
|
+
let first = true;
|
|
115
|
+
if (this.isServiceEnabled('mongodb')) {
|
|
116
|
+
if (!first) console.log();
|
|
117
|
+
await this.startMongoDB();
|
|
118
|
+
first = false;
|
|
119
|
+
}
|
|
120
|
+
if (this.isServiceEnabled('minio')) {
|
|
121
|
+
if (!first) console.log();
|
|
122
|
+
await this.startMinIO();
|
|
123
|
+
first = false;
|
|
124
|
+
}
|
|
125
|
+
if (this.isServiceEnabled('elasticsearch')) {
|
|
126
|
+
if (!first) console.log();
|
|
127
|
+
await this.startElasticsearch();
|
|
128
|
+
first = false;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Stop all enabled services
|
|
134
|
+
*/
|
|
135
|
+
public async stopAll(): Promise<void> {
|
|
136
|
+
let first = true;
|
|
137
|
+
if (this.isServiceEnabled('mongodb')) {
|
|
138
|
+
if (!first) console.log();
|
|
139
|
+
await this.stopMongoDB();
|
|
140
|
+
first = false;
|
|
141
|
+
}
|
|
142
|
+
if (this.isServiceEnabled('minio')) {
|
|
143
|
+
if (!first) console.log();
|
|
144
|
+
await this.stopMinIO();
|
|
145
|
+
first = false;
|
|
146
|
+
}
|
|
147
|
+
if (this.isServiceEnabled('elasticsearch')) {
|
|
148
|
+
if (!first) console.log();
|
|
149
|
+
await this.stopElasticsearch();
|
|
150
|
+
first = false;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
34
154
|
/**
|
|
35
155
|
* Start MongoDB service
|
|
36
156
|
*/
|
|
@@ -42,7 +162,7 @@ export class ServiceManager {
|
|
|
42
162
|
const directories = this.config.getDataDirectories();
|
|
43
163
|
|
|
44
164
|
// Ensure data directory exists
|
|
45
|
-
await plugins.
|
|
165
|
+
await plugins.smartfs.directory(directories.mongo).recursive().create();
|
|
46
166
|
|
|
47
167
|
const status = await this.docker.getStatus(containers.mongo);
|
|
48
168
|
|
|
@@ -141,7 +261,7 @@ export class ServiceManager {
|
|
|
141
261
|
const directories = this.config.getDataDirectories();
|
|
142
262
|
|
|
143
263
|
// Ensure data directory exists
|
|
144
|
-
await plugins.
|
|
264
|
+
await plugins.smartfs.directory(directories.minio).recursive().create();
|
|
145
265
|
|
|
146
266
|
const status = await this.docker.getStatus(containers.minio);
|
|
147
267
|
|
|
@@ -259,7 +379,103 @@ export class ServiceManager {
|
|
|
259
379
|
logger.log('info', ` API: http://${config.S3_HOST}:${config.S3_PORT}`);
|
|
260
380
|
logger.log('info', ` Console: http://${config.S3_HOST}:${config.S3_CONSOLE_PORT} (login: ${config.S3_ACCESSKEY}/***)`);
|
|
261
381
|
}
|
|
262
|
-
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Start Elasticsearch service
|
|
385
|
+
*/
|
|
386
|
+
public async startElasticsearch(): Promise<void> {
|
|
387
|
+
logger.log('note', '📦 Elasticsearch:');
|
|
388
|
+
|
|
389
|
+
const config = this.config.getConfig();
|
|
390
|
+
const containers = this.config.getContainerNames();
|
|
391
|
+
const directories = this.config.getDataDirectories();
|
|
392
|
+
|
|
393
|
+
// Ensure data directory exists
|
|
394
|
+
await plugins.smartfs.directory(directories.elasticsearch).recursive().create();
|
|
395
|
+
|
|
396
|
+
const status = await this.docker.getStatus(containers.elasticsearch);
|
|
397
|
+
|
|
398
|
+
switch (status) {
|
|
399
|
+
case 'running':
|
|
400
|
+
logger.log('ok', ' Already running ✓');
|
|
401
|
+
break;
|
|
402
|
+
|
|
403
|
+
case 'stopped':
|
|
404
|
+
// Check if port mapping matches config
|
|
405
|
+
const esPortMappings = await this.docker.getPortMappings(containers.elasticsearch);
|
|
406
|
+
if (esPortMappings && esPortMappings['9200'] !== config.ELASTICSEARCH_PORT) {
|
|
407
|
+
logger.log('note', ' Port configuration changed, recreating container...');
|
|
408
|
+
await this.docker.remove(containers.elasticsearch, true);
|
|
409
|
+
// Fall through to create new container
|
|
410
|
+
const success = await this.docker.run({
|
|
411
|
+
name: containers.elasticsearch,
|
|
412
|
+
image: 'elasticsearch:8.11.0',
|
|
413
|
+
ports: {
|
|
414
|
+
[`0.0.0.0:${config.ELASTICSEARCH_PORT}`]: '9200'
|
|
415
|
+
},
|
|
416
|
+
volumes: {
|
|
417
|
+
[directories.elasticsearch]: '/usr/share/elasticsearch/data'
|
|
418
|
+
},
|
|
419
|
+
environment: {
|
|
420
|
+
'discovery.type': 'single-node',
|
|
421
|
+
'xpack.security.enabled': 'true',
|
|
422
|
+
'ELASTIC_PASSWORD': config.ELASTICSEARCH_PASS,
|
|
423
|
+
'ES_JAVA_OPTS': '-Xms512m -Xmx512m'
|
|
424
|
+
},
|
|
425
|
+
restart: 'unless-stopped'
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
if (success) {
|
|
429
|
+
logger.log('ok', ' Recreated with new port ✓');
|
|
430
|
+
} else {
|
|
431
|
+
logger.log('error', ' Failed to recreate container');
|
|
432
|
+
}
|
|
433
|
+
} else {
|
|
434
|
+
// Ports match, just start the container
|
|
435
|
+
if (await this.docker.start(containers.elasticsearch)) {
|
|
436
|
+
logger.log('ok', ' Started ✓');
|
|
437
|
+
} else {
|
|
438
|
+
logger.log('error', ' Failed to start');
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
break;
|
|
442
|
+
|
|
443
|
+
case 'not_exists':
|
|
444
|
+
logger.log('note', ' Creating container...');
|
|
445
|
+
|
|
446
|
+
const success = await this.docker.run({
|
|
447
|
+
name: containers.elasticsearch,
|
|
448
|
+
image: 'elasticsearch:8.11.0',
|
|
449
|
+
ports: {
|
|
450
|
+
[`0.0.0.0:${config.ELASTICSEARCH_PORT}`]: '9200'
|
|
451
|
+
},
|
|
452
|
+
volumes: {
|
|
453
|
+
[directories.elasticsearch]: '/usr/share/elasticsearch/data'
|
|
454
|
+
},
|
|
455
|
+
environment: {
|
|
456
|
+
'discovery.type': 'single-node',
|
|
457
|
+
'xpack.security.enabled': 'true',
|
|
458
|
+
'ELASTIC_PASSWORD': config.ELASTICSEARCH_PASS,
|
|
459
|
+
'ES_JAVA_OPTS': '-Xms512m -Xmx512m'
|
|
460
|
+
},
|
|
461
|
+
restart: 'unless-stopped'
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
if (success) {
|
|
465
|
+
logger.log('ok', ' Created and started ✓');
|
|
466
|
+
} else {
|
|
467
|
+
logger.log('error', ' Failed to create container');
|
|
468
|
+
}
|
|
469
|
+
break;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
logger.log('info', ` Container: ${containers.elasticsearch}`);
|
|
473
|
+
logger.log('info', ` Port: ${config.ELASTICSEARCH_PORT}`);
|
|
474
|
+
logger.log('info', ` Connection: ${config.ELASTICSEARCH_URL}`);
|
|
475
|
+
logger.log('info', ` Username: ${config.ELASTICSEARCH_USER}`);
|
|
476
|
+
logger.log('info', ` Password: ${config.ELASTICSEARCH_PASS}`);
|
|
477
|
+
}
|
|
478
|
+
|
|
263
479
|
/**
|
|
264
480
|
* Stop MongoDB service
|
|
265
481
|
*/
|
|
@@ -285,10 +501,10 @@ export class ServiceManager {
|
|
|
285
501
|
*/
|
|
286
502
|
public async stopMinIO(): Promise<void> {
|
|
287
503
|
logger.log('note', '📦 S3/MinIO:');
|
|
288
|
-
|
|
504
|
+
|
|
289
505
|
const containers = this.config.getContainerNames();
|
|
290
506
|
const status = await this.docker.getStatus(containers.minio);
|
|
291
|
-
|
|
507
|
+
|
|
292
508
|
if (status === 'running') {
|
|
293
509
|
if (await this.docker.stop(containers.minio)) {
|
|
294
510
|
logger.log('ok', ' Stopped ✓');
|
|
@@ -299,7 +515,27 @@ export class ServiceManager {
|
|
|
299
515
|
logger.log('note', ' Not running');
|
|
300
516
|
}
|
|
301
517
|
}
|
|
302
|
-
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* Stop Elasticsearch service
|
|
521
|
+
*/
|
|
522
|
+
public async stopElasticsearch(): Promise<void> {
|
|
523
|
+
logger.log('note', '📦 Elasticsearch:');
|
|
524
|
+
|
|
525
|
+
const containers = this.config.getContainerNames();
|
|
526
|
+
const status = await this.docker.getStatus(containers.elasticsearch);
|
|
527
|
+
|
|
528
|
+
if (status === 'running') {
|
|
529
|
+
if (await this.docker.stop(containers.elasticsearch)) {
|
|
530
|
+
logger.log('ok', ' Stopped ✓');
|
|
531
|
+
} else {
|
|
532
|
+
logger.log('error', ' Failed to stop');
|
|
533
|
+
}
|
|
534
|
+
} else {
|
|
535
|
+
logger.log('note', ' Not running');
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
303
539
|
/**
|
|
304
540
|
* Show service status
|
|
305
541
|
*/
|
|
@@ -385,8 +621,36 @@ export class ServiceManager {
|
|
|
385
621
|
}
|
|
386
622
|
break;
|
|
387
623
|
}
|
|
624
|
+
|
|
625
|
+
// Elasticsearch status
|
|
626
|
+
const esStatus = await this.docker.getStatus(containers.elasticsearch);
|
|
627
|
+
switch (esStatus) {
|
|
628
|
+
case 'running':
|
|
629
|
+
logger.log('ok', '📦 Elasticsearch: 🟢 Running');
|
|
630
|
+
logger.log('info', ` ├─ Container: ${containers.elasticsearch}`);
|
|
631
|
+
logger.log('info', ` ├─ Port: ${config.ELASTICSEARCH_PORT}`);
|
|
632
|
+
logger.log('info', ` ├─ Connection: ${config.ELASTICSEARCH_URL}`);
|
|
633
|
+
logger.log('info', ` └─ Credentials: ${config.ELASTICSEARCH_USER}/${config.ELASTICSEARCH_PASS}`);
|
|
634
|
+
break;
|
|
635
|
+
case 'stopped':
|
|
636
|
+
logger.log('note', '📦 Elasticsearch: 🟡 Stopped');
|
|
637
|
+
logger.log('info', ` ├─ Container: ${containers.elasticsearch}`);
|
|
638
|
+
logger.log('info', ` └─ Port: ${config.ELASTICSEARCH_PORT}`);
|
|
639
|
+
break;
|
|
640
|
+
case 'not_exists':
|
|
641
|
+
logger.log('info', '📦 Elasticsearch: ⚪ Not installed');
|
|
642
|
+
// Check port availability
|
|
643
|
+
const esPort = parseInt(config.ELASTICSEARCH_PORT);
|
|
644
|
+
const esAvailable = await helpers.isPortAvailable(esPort);
|
|
645
|
+
if (!esAvailable) {
|
|
646
|
+
logger.log('error', ` └─ ⚠️ Port ${esPort} is in use by another process`);
|
|
647
|
+
} else {
|
|
648
|
+
logger.log('info', ` └─ Port ${esPort} is available`);
|
|
649
|
+
}
|
|
650
|
+
break;
|
|
651
|
+
}
|
|
388
652
|
}
|
|
389
|
-
|
|
653
|
+
|
|
390
654
|
/**
|
|
391
655
|
* Show configuration
|
|
392
656
|
*/
|
|
@@ -420,6 +684,15 @@ export class ServiceManager {
|
|
|
420
684
|
logger.log('info', ` Data: ${this.config.getDataDirectories().minio}`);
|
|
421
685
|
logger.log('info', ` Endpoint: ${config.S3_ENDPOINT}`);
|
|
422
686
|
logger.log('info', ` Console URL: http://${config.S3_HOST}:${config.S3_CONSOLE_PORT}`);
|
|
687
|
+
|
|
688
|
+
console.log();
|
|
689
|
+
logger.log('note', 'Elasticsearch:');
|
|
690
|
+
logger.log('info', ` Host: ${config.ELASTICSEARCH_HOST}:${config.ELASTICSEARCH_PORT}`);
|
|
691
|
+
logger.log('info', ` User: ${config.ELASTICSEARCH_USER}`);
|
|
692
|
+
logger.log('info', ' Password: ***');
|
|
693
|
+
logger.log('info', ` Container: ${this.config.getContainerNames().elasticsearch}`);
|
|
694
|
+
logger.log('info', ` Data: ${this.config.getDataDirectories().elasticsearch}`);
|
|
695
|
+
logger.log('info', ` Connection: ${config.ELASTICSEARCH_URL}`);
|
|
423
696
|
}
|
|
424
697
|
|
|
425
698
|
/**
|
|
@@ -477,16 +750,29 @@ export class ServiceManager {
|
|
|
477
750
|
logger.log('note', 'S3/MinIO container is not running');
|
|
478
751
|
}
|
|
479
752
|
break;
|
|
480
|
-
|
|
753
|
+
|
|
754
|
+
case 'elasticsearch':
|
|
755
|
+
case 'es':
|
|
756
|
+
if (await this.docker.isRunning(containers.elasticsearch)) {
|
|
757
|
+
helpers.printHeader(`Elasticsearch Logs (last ${lines} lines)`);
|
|
758
|
+
const logs = await this.docker.logs(containers.elasticsearch, lines);
|
|
759
|
+
console.log(logs);
|
|
760
|
+
} else {
|
|
761
|
+
logger.log('note', 'Elasticsearch container is not running');
|
|
762
|
+
}
|
|
763
|
+
break;
|
|
764
|
+
|
|
481
765
|
case 'all':
|
|
482
766
|
case '':
|
|
483
767
|
await this.showLogs('mongo', lines);
|
|
484
768
|
console.log();
|
|
485
769
|
await this.showLogs('minio', lines);
|
|
770
|
+
console.log();
|
|
771
|
+
await this.showLogs('elasticsearch', lines);
|
|
486
772
|
break;
|
|
487
|
-
|
|
773
|
+
|
|
488
774
|
default:
|
|
489
|
-
logger.log('note', 'Usage: gitzone services logs [mongo|s3|all] [lines]');
|
|
775
|
+
logger.log('note', 'Usage: gitzone services logs [mongo|s3|elasticsearch|all] [lines]');
|
|
490
776
|
break;
|
|
491
777
|
}
|
|
492
778
|
}
|
|
@@ -497,21 +783,28 @@ export class ServiceManager {
|
|
|
497
783
|
public async removeContainers(): Promise<void> {
|
|
498
784
|
const containers = this.config.getContainerNames();
|
|
499
785
|
let removed = false;
|
|
500
|
-
|
|
786
|
+
|
|
501
787
|
if (await this.docker.exists(containers.mongo)) {
|
|
502
788
|
if (await this.docker.remove(containers.mongo, true)) {
|
|
503
789
|
logger.log('ok', ' MongoDB container removed ✓');
|
|
504
790
|
removed = true;
|
|
505
791
|
}
|
|
506
792
|
}
|
|
507
|
-
|
|
793
|
+
|
|
508
794
|
if (await this.docker.exists(containers.minio)) {
|
|
509
795
|
if (await this.docker.remove(containers.minio, true)) {
|
|
510
796
|
logger.log('ok', ' S3/MinIO container removed ✓');
|
|
511
797
|
removed = true;
|
|
512
798
|
}
|
|
513
799
|
}
|
|
514
|
-
|
|
800
|
+
|
|
801
|
+
if (await this.docker.exists(containers.elasticsearch)) {
|
|
802
|
+
if (await this.docker.remove(containers.elasticsearch, true)) {
|
|
803
|
+
logger.log('ok', ' Elasticsearch container removed ✓');
|
|
804
|
+
removed = true;
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
|
|
515
808
|
if (!removed) {
|
|
516
809
|
logger.log('note', ' No containers to remove');
|
|
517
810
|
}
|
|
@@ -523,24 +816,60 @@ export class ServiceManager {
|
|
|
523
816
|
public async cleanData(): Promise<void> {
|
|
524
817
|
const directories = this.config.getDataDirectories();
|
|
525
818
|
let cleaned = false;
|
|
526
|
-
|
|
527
|
-
if (await plugins.
|
|
528
|
-
await plugins.
|
|
819
|
+
|
|
820
|
+
if (await plugins.smartfs.directory(directories.mongo).exists()) {
|
|
821
|
+
await plugins.smartfs.directory(directories.mongo).recursive().delete();
|
|
529
822
|
logger.log('ok', ' MongoDB data removed ✓');
|
|
530
823
|
cleaned = true;
|
|
531
824
|
}
|
|
532
|
-
|
|
533
|
-
if (await plugins.
|
|
534
|
-
await plugins.
|
|
825
|
+
|
|
826
|
+
if (await plugins.smartfs.directory(directories.minio).exists()) {
|
|
827
|
+
await plugins.smartfs.directory(directories.minio).recursive().delete();
|
|
535
828
|
logger.log('ok', ' S3/MinIO data removed ✓');
|
|
536
829
|
cleaned = true;
|
|
537
830
|
}
|
|
538
|
-
|
|
831
|
+
|
|
832
|
+
if (await plugins.smartfs.directory(directories.elasticsearch).exists()) {
|
|
833
|
+
await plugins.smartfs.directory(directories.elasticsearch).recursive().delete();
|
|
834
|
+
logger.log('ok', ' Elasticsearch data removed ✓');
|
|
835
|
+
cleaned = true;
|
|
836
|
+
}
|
|
837
|
+
|
|
539
838
|
if (!cleaned) {
|
|
540
839
|
logger.log('note', ' No data to clean');
|
|
541
840
|
}
|
|
542
841
|
}
|
|
543
842
|
|
|
843
|
+
/**
|
|
844
|
+
* Configure which services are enabled
|
|
845
|
+
*/
|
|
846
|
+
public async configureServices(): Promise<void> {
|
|
847
|
+
logger.log('note', 'Select which services to enable for this project:');
|
|
848
|
+
console.log();
|
|
849
|
+
|
|
850
|
+
const currentServices = this.enabledServices || ['mongodb', 'minio', 'elasticsearch'];
|
|
851
|
+
|
|
852
|
+
const smartinteract = new plugins.smartinteract.SmartInteract();
|
|
853
|
+
const response = await smartinteract.askQuestion({
|
|
854
|
+
name: 'services',
|
|
855
|
+
type: 'checkbox',
|
|
856
|
+
message: 'Which services do you want to enable?',
|
|
857
|
+
choices: [
|
|
858
|
+
{ name: 'MongoDB', value: 'mongodb' },
|
|
859
|
+
{ name: 'MinIO (S3)', value: 'minio' },
|
|
860
|
+
{ name: 'Elasticsearch', value: 'elasticsearch' }
|
|
861
|
+
],
|
|
862
|
+
default: currentServices
|
|
863
|
+
});
|
|
864
|
+
|
|
865
|
+
this.enabledServices = response.value || ['mongodb', 'minio', 'elasticsearch'];
|
|
866
|
+
|
|
867
|
+
// Save to npmextra.json
|
|
868
|
+
await this.saveServiceConfiguration(this.enabledServices);
|
|
869
|
+
|
|
870
|
+
logger.log('ok', '✅ Service configuration updated');
|
|
871
|
+
}
|
|
872
|
+
|
|
544
873
|
/**
|
|
545
874
|
* Reconfigure services with new ports
|
|
546
875
|
*/
|
|
@@ -551,20 +880,25 @@ export class ServiceManager {
|
|
|
551
880
|
|
|
552
881
|
// Stop existing containers
|
|
553
882
|
logger.log('note', '🛑 Stopping existing containers...');
|
|
554
|
-
|
|
883
|
+
|
|
555
884
|
if (await this.docker.exists(containers.mongo)) {
|
|
556
885
|
await this.docker.stop(containers.mongo);
|
|
557
886
|
logger.log('ok', ' MongoDB stopped ✓');
|
|
558
887
|
}
|
|
559
|
-
|
|
888
|
+
|
|
560
889
|
if (await this.docker.exists(containers.minio)) {
|
|
561
890
|
await this.docker.stop(containers.minio);
|
|
562
891
|
logger.log('ok', ' S3/MinIO stopped ✓');
|
|
563
892
|
}
|
|
564
|
-
|
|
893
|
+
|
|
894
|
+
if (await this.docker.exists(containers.elasticsearch)) {
|
|
895
|
+
await this.docker.stop(containers.elasticsearch);
|
|
896
|
+
logger.log('ok', ' Elasticsearch stopped ✓');
|
|
897
|
+
}
|
|
898
|
+
|
|
565
899
|
// Reconfigure ports
|
|
566
900
|
await this.config.reconfigurePorts();
|
|
567
|
-
|
|
901
|
+
|
|
568
902
|
// Ask if user wants to restart services
|
|
569
903
|
const smartinteract = new plugins.smartinteract.SmartInteract();
|
|
570
904
|
const response = await smartinteract.askQuestion({
|
|
@@ -573,11 +907,10 @@ export class ServiceManager {
|
|
|
573
907
|
message: 'Do you want to start services with new ports?',
|
|
574
908
|
default: true
|
|
575
909
|
});
|
|
576
|
-
|
|
910
|
+
|
|
577
911
|
if (response.value) {
|
|
578
912
|
console.log();
|
|
579
|
-
await this.
|
|
580
|
-
await this.startMinIO();
|
|
913
|
+
await this.startAll();
|
|
581
914
|
}
|
|
582
915
|
}
|
|
583
916
|
}
|
|
@@ -42,11 +42,15 @@ export const getRandomAvailablePort = async (): Promise<number> => {
|
|
|
42
42
|
/**
|
|
43
43
|
* Get the project name from package.json or directory
|
|
44
44
|
*/
|
|
45
|
-
export const getProjectName = (): string => {
|
|
45
|
+
export const getProjectName = async (): Promise<string> => {
|
|
46
46
|
try {
|
|
47
47
|
const packageJsonPath = plugins.path.join(process.cwd(), 'package.json');
|
|
48
|
-
if (plugins.
|
|
49
|
-
const
|
|
48
|
+
if (await plugins.smartfs.file(packageJsonPath).exists()) {
|
|
49
|
+
const content = (await plugins.smartfs
|
|
50
|
+
.file(packageJsonPath)
|
|
51
|
+
.encoding('utf8')
|
|
52
|
+
.read()) as string;
|
|
53
|
+
const packageJson = JSON.parse(content);
|
|
50
54
|
if (packageJson.name) {
|
|
51
55
|
// Sanitize: @fin.cx/skr → fin-cx-skr
|
|
52
56
|
return packageJson.name.replace(/@/g, '').replace(/[\/\.]/g, '-');
|
|
@@ -55,7 +59,7 @@ export const getProjectName = (): string => {
|
|
|
55
59
|
} catch (error) {
|
|
56
60
|
// Ignore errors and fall back to directory name
|
|
57
61
|
}
|
|
58
|
-
|
|
62
|
+
|
|
59
63
|
return plugins.path.basename(process.cwd());
|
|
60
64
|
};
|
|
61
65
|
|