@git.zone/cli 1.16.9 → 1.17.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/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/gitzone.cli.js +8 -1
- package/dist_ts/mod_format/format.packagejson.js +3 -3
- package/dist_ts/mod_services/classes.dockercontainer.d.ts +68 -0
- package/dist_ts/mod_services/classes.dockercontainer.js +194 -0
- package/dist_ts/mod_services/classes.serviceconfiguration.d.ts +69 -0
- package/dist_ts/mod_services/classes.serviceconfiguration.js +195 -0
- package/dist_ts/mod_services/classes.servicemanager.d.ts +49 -0
- package/dist_ts/mod_services/classes.servicemanager.js +364 -0
- package/dist_ts/mod_services/helpers.d.ts +24 -0
- package/dist_ts/mod_services/helpers.js +108 -0
- package/dist_ts/mod_services/index.d.ts +1 -0
- package/dist_ts/mod_services/index.js +184 -0
- package/dist_ts/mod_services/mod.plugins.d.ts +7 -0
- package/dist_ts/mod_services/mod.plugins.js +8 -0
- package/dist_ts/plugins.d.ts +6 -1
- package/dist_ts/plugins.js +7 -2
- package/package.json +6 -5
- package/readme.md +123 -16
- package/readme.plan.md +119 -188
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/gitzone.cli.ts +8 -0
- package/ts/mod_format/format.packagejson.ts +2 -2
- package/ts/mod_services/classes.dockercontainer.ts +227 -0
- package/ts/mod_services/classes.serviceconfiguration.ts +246 -0
- package/ts/mod_services/classes.servicemanager.ts +424 -0
- package/ts/mod_services/helpers.ts +123 -0
- package/ts/mod_services/index.ts +219 -0
- package/ts/mod_services/mod.plugins.ts +9 -0
- package/ts/plugins.ts +10 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import * as plugins from './mod.plugins.js';
|
|
2
|
+
import * as helpers from './helpers.js';
|
|
3
|
+
import { logger } from '../gitzone.logging.js';
|
|
4
|
+
|
|
5
|
+
export interface IServiceConfig {
|
|
6
|
+
PROJECT_NAME: string;
|
|
7
|
+
MONGODB_HOST: string;
|
|
8
|
+
MONGODB_NAME: string;
|
|
9
|
+
MONGODB_PORT: string;
|
|
10
|
+
MONGODB_USER: string;
|
|
11
|
+
MONGODB_PASS: string;
|
|
12
|
+
S3_HOST: string;
|
|
13
|
+
S3_PORT: string;
|
|
14
|
+
S3_CONSOLE_PORT: string;
|
|
15
|
+
S3_USER: string;
|
|
16
|
+
S3_PASS: string;
|
|
17
|
+
S3_BUCKET: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class ServiceConfiguration {
|
|
21
|
+
private configPath: string;
|
|
22
|
+
private config: IServiceConfig;
|
|
23
|
+
|
|
24
|
+
constructor() {
|
|
25
|
+
this.configPath = plugins.path.join(process.cwd(), '.nogit', 'env.json');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Load or create the configuration
|
|
30
|
+
*/
|
|
31
|
+
public async loadOrCreate(): Promise<IServiceConfig> {
|
|
32
|
+
await this.ensureNogitDirectory();
|
|
33
|
+
|
|
34
|
+
if (await this.configExists()) {
|
|
35
|
+
await this.loadConfig();
|
|
36
|
+
await this.updateMissingFields();
|
|
37
|
+
} else {
|
|
38
|
+
await this.createDefaultConfig();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return this.config;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get the current configuration
|
|
46
|
+
*/
|
|
47
|
+
public getConfig(): IServiceConfig {
|
|
48
|
+
return this.config;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Save the configuration to file
|
|
53
|
+
*/
|
|
54
|
+
public async saveConfig(): Promise<void> {
|
|
55
|
+
await plugins.smartfile.memory.toFs(
|
|
56
|
+
JSON.stringify(this.config, null, 2),
|
|
57
|
+
this.configPath
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Ensure .nogit directory exists
|
|
63
|
+
*/
|
|
64
|
+
private async ensureNogitDirectory(): Promise<void> {
|
|
65
|
+
const nogitPath = plugins.path.join(process.cwd(), '.nogit');
|
|
66
|
+
await plugins.smartfile.fs.ensureDir(nogitPath);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Check if configuration file exists
|
|
71
|
+
*/
|
|
72
|
+
private async configExists(): Promise<boolean> {
|
|
73
|
+
return plugins.smartfile.fs.fileExists(this.configPath);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Load configuration from file
|
|
78
|
+
*/
|
|
79
|
+
private async loadConfig(): Promise<void> {
|
|
80
|
+
const configContent = await plugins.smartfile.fs.toStringSync(this.configPath);
|
|
81
|
+
this.config = JSON.parse(configContent);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Create default configuration
|
|
86
|
+
*/
|
|
87
|
+
private async createDefaultConfig(): Promise<void> {
|
|
88
|
+
const projectName = helpers.getProjectName();
|
|
89
|
+
const mongoPort = await helpers.getRandomAvailablePort();
|
|
90
|
+
const s3Port = await helpers.getRandomAvailablePort();
|
|
91
|
+
let s3ConsolePort = s3Port + 1;
|
|
92
|
+
|
|
93
|
+
// Ensure console port is also available
|
|
94
|
+
while (!(await helpers.isPortAvailable(s3ConsolePort))) {
|
|
95
|
+
s3ConsolePort++;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
this.config = {
|
|
99
|
+
PROJECT_NAME: projectName,
|
|
100
|
+
MONGODB_HOST: 'localhost',
|
|
101
|
+
MONGODB_NAME: projectName,
|
|
102
|
+
MONGODB_PORT: mongoPort.toString(),
|
|
103
|
+
MONGODB_USER: 'defaultadmin',
|
|
104
|
+
MONGODB_PASS: 'defaultpass',
|
|
105
|
+
S3_HOST: 'localhost',
|
|
106
|
+
S3_PORT: s3Port.toString(),
|
|
107
|
+
S3_CONSOLE_PORT: s3ConsolePort.toString(),
|
|
108
|
+
S3_USER: 'defaultadmin',
|
|
109
|
+
S3_PASS: 'defaultpass',
|
|
110
|
+
S3_BUCKET: `${projectName}-documents`
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
await this.saveConfig();
|
|
114
|
+
|
|
115
|
+
logger.log('ok', '✅ Created .nogit/env.json with project defaults');
|
|
116
|
+
logger.log('info', `📍 MongoDB port: ${mongoPort}`);
|
|
117
|
+
logger.log('info', `📍 S3 API port: ${s3Port}`);
|
|
118
|
+
logger.log('info', `📍 S3 Console port: ${s3ConsolePort}`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Update missing fields in existing configuration
|
|
123
|
+
*/
|
|
124
|
+
private async updateMissingFields(): Promise<void> {
|
|
125
|
+
const projectName = helpers.getProjectName();
|
|
126
|
+
let updated = false;
|
|
127
|
+
const fieldsAdded: string[] = [];
|
|
128
|
+
|
|
129
|
+
// Check and add missing fields
|
|
130
|
+
if (!this.config.PROJECT_NAME) {
|
|
131
|
+
this.config.PROJECT_NAME = projectName;
|
|
132
|
+
fieldsAdded.push('PROJECT_NAME');
|
|
133
|
+
updated = true;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (!this.config.MONGODB_HOST) {
|
|
137
|
+
this.config.MONGODB_HOST = 'localhost';
|
|
138
|
+
fieldsAdded.push('MONGODB_HOST');
|
|
139
|
+
updated = true;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (!this.config.MONGODB_NAME) {
|
|
143
|
+
this.config.MONGODB_NAME = projectName;
|
|
144
|
+
fieldsAdded.push('MONGODB_NAME');
|
|
145
|
+
updated = true;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (!this.config.MONGODB_PORT) {
|
|
149
|
+
const port = await helpers.getRandomAvailablePort();
|
|
150
|
+
this.config.MONGODB_PORT = port.toString();
|
|
151
|
+
fieldsAdded.push(`MONGODB_PORT(${port})`);
|
|
152
|
+
updated = true;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (!this.config.MONGODB_USER) {
|
|
156
|
+
this.config.MONGODB_USER = 'defaultadmin';
|
|
157
|
+
fieldsAdded.push('MONGODB_USER');
|
|
158
|
+
updated = true;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (!this.config.MONGODB_PASS) {
|
|
162
|
+
this.config.MONGODB_PASS = 'defaultpass';
|
|
163
|
+
fieldsAdded.push('MONGODB_PASS');
|
|
164
|
+
updated = true;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (!this.config.S3_HOST) {
|
|
168
|
+
this.config.S3_HOST = 'localhost';
|
|
169
|
+
fieldsAdded.push('S3_HOST');
|
|
170
|
+
updated = true;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (!this.config.S3_PORT) {
|
|
174
|
+
const port = await helpers.getRandomAvailablePort();
|
|
175
|
+
this.config.S3_PORT = port.toString();
|
|
176
|
+
fieldsAdded.push(`S3_PORT(${port})`);
|
|
177
|
+
updated = true;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (!this.config.S3_CONSOLE_PORT) {
|
|
181
|
+
const s3Port = parseInt(this.config.S3_PORT);
|
|
182
|
+
let consolePort = s3Port + 1;
|
|
183
|
+
|
|
184
|
+
while (!(await helpers.isPortAvailable(consolePort))) {
|
|
185
|
+
consolePort++;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
this.config.S3_CONSOLE_PORT = consolePort.toString();
|
|
189
|
+
fieldsAdded.push(`S3_CONSOLE_PORT(${consolePort})`);
|
|
190
|
+
updated = true;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (!this.config.S3_USER) {
|
|
194
|
+
this.config.S3_USER = 'defaultadmin';
|
|
195
|
+
fieldsAdded.push('S3_USER');
|
|
196
|
+
updated = true;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (!this.config.S3_PASS) {
|
|
200
|
+
this.config.S3_PASS = 'defaultpass';
|
|
201
|
+
fieldsAdded.push('S3_PASS');
|
|
202
|
+
updated = true;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (!this.config.S3_BUCKET) {
|
|
206
|
+
this.config.S3_BUCKET = `${projectName}-documents`;
|
|
207
|
+
fieldsAdded.push('S3_BUCKET');
|
|
208
|
+
updated = true;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (updated) {
|
|
212
|
+
await this.saveConfig();
|
|
213
|
+
logger.log('ok', `✅ Added missing fields: ${fieldsAdded.join(', ')}`);
|
|
214
|
+
} else {
|
|
215
|
+
logger.log('ok', '✅ Configuration complete');
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Get MongoDB connection string
|
|
221
|
+
*/
|
|
222
|
+
public getMongoConnectionString(useNetworkIp: boolean = false): string {
|
|
223
|
+
const host = useNetworkIp ? '${networkIp}' : this.config.MONGODB_HOST;
|
|
224
|
+
return `mongodb://${this.config.MONGODB_USER}:${this.config.MONGODB_PASS}@${host}:${this.config.MONGODB_PORT}/${this.config.MONGODB_NAME}?authSource=admin`;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Get container names
|
|
229
|
+
*/
|
|
230
|
+
public getContainerNames() {
|
|
231
|
+
return {
|
|
232
|
+
mongo: `${this.config.PROJECT_NAME}-mongodb`,
|
|
233
|
+
minio: `${this.config.PROJECT_NAME}-minio`
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Get data directories
|
|
239
|
+
*/
|
|
240
|
+
public getDataDirectories() {
|
|
241
|
+
return {
|
|
242
|
+
mongo: plugins.path.join(process.cwd(), '.nogit', 'mongodata'),
|
|
243
|
+
minio: plugins.path.join(process.cwd(), '.nogit', 'miniodata')
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
}
|
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
import * as plugins from './mod.plugins.js';
|
|
2
|
+
import * as helpers from './helpers.js';
|
|
3
|
+
import { ServiceConfiguration } from './classes.serviceconfiguration.js';
|
|
4
|
+
import { DockerContainer } from './classes.dockercontainer.js';
|
|
5
|
+
import { logger } from '../gitzone.logging.js';
|
|
6
|
+
|
|
7
|
+
export class ServiceManager {
|
|
8
|
+
private config: ServiceConfiguration;
|
|
9
|
+
private docker: DockerContainer;
|
|
10
|
+
|
|
11
|
+
constructor() {
|
|
12
|
+
this.config = new ServiceConfiguration();
|
|
13
|
+
this.docker = new DockerContainer();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Initialize the service manager
|
|
18
|
+
*/
|
|
19
|
+
public async init(): Promise<void> {
|
|
20
|
+
// Check Docker availability
|
|
21
|
+
if (!(await this.docker.checkDocker())) {
|
|
22
|
+
logger.log('error', 'Error: Docker is not installed. Please install Docker first.');
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Load or create configuration
|
|
27
|
+
await this.config.loadOrCreate();
|
|
28
|
+
logger.log('info', `📋 Project: ${this.config.getConfig().PROJECT_NAME}`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Start MongoDB service
|
|
33
|
+
*/
|
|
34
|
+
public async startMongoDB(): Promise<void> {
|
|
35
|
+
logger.log('note', '📦 MongoDB:');
|
|
36
|
+
|
|
37
|
+
const config = this.config.getConfig();
|
|
38
|
+
const containers = this.config.getContainerNames();
|
|
39
|
+
const directories = this.config.getDataDirectories();
|
|
40
|
+
|
|
41
|
+
// Ensure data directory exists
|
|
42
|
+
await plugins.smartfile.fs.ensureDir(directories.mongo);
|
|
43
|
+
|
|
44
|
+
const status = await this.docker.getStatus(containers.mongo);
|
|
45
|
+
|
|
46
|
+
switch (status) {
|
|
47
|
+
case 'running':
|
|
48
|
+
logger.log('ok', ' Already running ✓');
|
|
49
|
+
break;
|
|
50
|
+
|
|
51
|
+
case 'stopped':
|
|
52
|
+
if (await this.docker.start(containers.mongo)) {
|
|
53
|
+
logger.log('ok', ' Started ✓');
|
|
54
|
+
} else {
|
|
55
|
+
logger.log('error', ' Failed to start');
|
|
56
|
+
}
|
|
57
|
+
break;
|
|
58
|
+
|
|
59
|
+
case 'not_exists':
|
|
60
|
+
logger.log('note', ' Creating container...');
|
|
61
|
+
|
|
62
|
+
const success = await this.docker.run({
|
|
63
|
+
name: containers.mongo,
|
|
64
|
+
image: 'mongo:7.0',
|
|
65
|
+
ports: {
|
|
66
|
+
[`0.0.0.0:${config.MONGODB_PORT}`]: '27017'
|
|
67
|
+
},
|
|
68
|
+
volumes: {
|
|
69
|
+
[directories.mongo]: '/data/db'
|
|
70
|
+
},
|
|
71
|
+
environment: {
|
|
72
|
+
MONGO_INITDB_ROOT_USERNAME: config.MONGODB_USER,
|
|
73
|
+
MONGO_INITDB_ROOT_PASSWORD: config.MONGODB_PASS,
|
|
74
|
+
MONGO_INITDB_DATABASE: config.MONGODB_NAME
|
|
75
|
+
},
|
|
76
|
+
restart: 'unless-stopped',
|
|
77
|
+
command: '--bind_ip_all'
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
if (success) {
|
|
81
|
+
logger.log('ok', ' Created and started ✓');
|
|
82
|
+
} else {
|
|
83
|
+
logger.log('error', ' Failed to create container');
|
|
84
|
+
}
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
logger.log('info', ` Container: ${containers.mongo}`);
|
|
89
|
+
logger.log('info', ` Port: ${config.MONGODB_PORT}`);
|
|
90
|
+
logger.log('info', ` Connection: ${this.config.getMongoConnectionString()}`);
|
|
91
|
+
|
|
92
|
+
// Show Compass connection string
|
|
93
|
+
const networkIp = await helpers.getLocalNetworkIp();
|
|
94
|
+
const compassString = `mongodb://${config.MONGODB_USER}:${config.MONGODB_PASS}@${networkIp}:${config.MONGODB_PORT}/${config.MONGODB_NAME}?authSource=admin`;
|
|
95
|
+
logger.log('ok', ` Compass: ${compassString}`);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Start MinIO service
|
|
100
|
+
*/
|
|
101
|
+
public async startMinIO(): Promise<void> {
|
|
102
|
+
logger.log('note', '📦 S3/MinIO:');
|
|
103
|
+
|
|
104
|
+
const config = this.config.getConfig();
|
|
105
|
+
const containers = this.config.getContainerNames();
|
|
106
|
+
const directories = this.config.getDataDirectories();
|
|
107
|
+
|
|
108
|
+
// Ensure data directory exists
|
|
109
|
+
await plugins.smartfile.fs.ensureDir(directories.minio);
|
|
110
|
+
|
|
111
|
+
const status = await this.docker.getStatus(containers.minio);
|
|
112
|
+
|
|
113
|
+
switch (status) {
|
|
114
|
+
case 'running':
|
|
115
|
+
logger.log('ok', ' Already running ✓');
|
|
116
|
+
break;
|
|
117
|
+
|
|
118
|
+
case 'stopped':
|
|
119
|
+
if (await this.docker.start(containers.minio)) {
|
|
120
|
+
logger.log('ok', ' Started ✓');
|
|
121
|
+
} else {
|
|
122
|
+
logger.log('error', ' Failed to start');
|
|
123
|
+
}
|
|
124
|
+
break;
|
|
125
|
+
|
|
126
|
+
case 'not_exists':
|
|
127
|
+
logger.log('note', ' Creating container...');
|
|
128
|
+
|
|
129
|
+
const success = await this.docker.run({
|
|
130
|
+
name: containers.minio,
|
|
131
|
+
image: 'minio/minio',
|
|
132
|
+
ports: {
|
|
133
|
+
[config.S3_PORT]: '9000',
|
|
134
|
+
[config.S3_CONSOLE_PORT]: '9001'
|
|
135
|
+
},
|
|
136
|
+
volumes: {
|
|
137
|
+
[directories.minio]: '/data'
|
|
138
|
+
},
|
|
139
|
+
environment: {
|
|
140
|
+
MINIO_ROOT_USER: config.S3_USER,
|
|
141
|
+
MINIO_ROOT_PASSWORD: config.S3_PASS
|
|
142
|
+
},
|
|
143
|
+
restart: 'unless-stopped',
|
|
144
|
+
command: 'server /data --console-address ":9001"'
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
if (success) {
|
|
148
|
+
logger.log('ok', ' Created and started ✓');
|
|
149
|
+
|
|
150
|
+
// Wait for MinIO to be ready
|
|
151
|
+
await plugins.smartdelay.delayFor(3000);
|
|
152
|
+
|
|
153
|
+
// Create default bucket
|
|
154
|
+
await this.docker.exec(
|
|
155
|
+
containers.minio,
|
|
156
|
+
`mc alias set local http://localhost:9000 ${config.S3_USER} ${config.S3_PASS}`
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
await this.docker.exec(
|
|
160
|
+
containers.minio,
|
|
161
|
+
`mc mb local/${config.S3_BUCKET}`
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
logger.log('ok', ` Bucket '${config.S3_BUCKET}' created ✓`);
|
|
165
|
+
} else {
|
|
166
|
+
logger.log('error', ' Failed to create container');
|
|
167
|
+
}
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
logger.log('info', ` Container: ${containers.minio}`);
|
|
172
|
+
logger.log('info', ` Port: ${config.S3_PORT}`);
|
|
173
|
+
logger.log('info', ` Bucket: ${config.S3_BUCKET}`);
|
|
174
|
+
logger.log('info', ` API: http://${config.S3_HOST}:${config.S3_PORT}`);
|
|
175
|
+
logger.log('info', ` Console: http://${config.S3_HOST}:${config.S3_CONSOLE_PORT} (login: ${config.S3_USER}/***)`);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Stop MongoDB service
|
|
180
|
+
*/
|
|
181
|
+
public async stopMongoDB(): Promise<void> {
|
|
182
|
+
logger.log('note', '📦 MongoDB:');
|
|
183
|
+
|
|
184
|
+
const containers = this.config.getContainerNames();
|
|
185
|
+
const status = await this.docker.getStatus(containers.mongo);
|
|
186
|
+
|
|
187
|
+
if (status === 'running') {
|
|
188
|
+
if (await this.docker.stop(containers.mongo)) {
|
|
189
|
+
logger.log('ok', ' Stopped ✓');
|
|
190
|
+
} else {
|
|
191
|
+
logger.log('error', ' Failed to stop');
|
|
192
|
+
}
|
|
193
|
+
} else {
|
|
194
|
+
logger.log('note', ' Not running');
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Stop MinIO service
|
|
200
|
+
*/
|
|
201
|
+
public async stopMinIO(): Promise<void> {
|
|
202
|
+
logger.log('note', '📦 S3/MinIO:');
|
|
203
|
+
|
|
204
|
+
const containers = this.config.getContainerNames();
|
|
205
|
+
const status = await this.docker.getStatus(containers.minio);
|
|
206
|
+
|
|
207
|
+
if (status === 'running') {
|
|
208
|
+
if (await this.docker.stop(containers.minio)) {
|
|
209
|
+
logger.log('ok', ' Stopped ✓');
|
|
210
|
+
} else {
|
|
211
|
+
logger.log('error', ' Failed to stop');
|
|
212
|
+
}
|
|
213
|
+
} else {
|
|
214
|
+
logger.log('note', ' Not running');
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Show service status
|
|
220
|
+
*/
|
|
221
|
+
public async showStatus(): Promise<void> {
|
|
222
|
+
helpers.printHeader('Service Status');
|
|
223
|
+
|
|
224
|
+
const config = this.config.getConfig();
|
|
225
|
+
const containers = this.config.getContainerNames();
|
|
226
|
+
|
|
227
|
+
logger.log('info', `Project: ${config.PROJECT_NAME}`);
|
|
228
|
+
console.log();
|
|
229
|
+
|
|
230
|
+
// MongoDB status
|
|
231
|
+
const mongoStatus = await this.docker.getStatus(containers.mongo);
|
|
232
|
+
switch (mongoStatus) {
|
|
233
|
+
case 'running':
|
|
234
|
+
logger.log('ok', '📦 MongoDB: 🟢 Running');
|
|
235
|
+
logger.log('info', ` ├─ Container: ${containers.mongo}`);
|
|
236
|
+
logger.log('info', ` ├─ Connection: ${this.config.getMongoConnectionString()}`);
|
|
237
|
+
|
|
238
|
+
// Show Compass connection string
|
|
239
|
+
const networkIp = await helpers.getLocalNetworkIp();
|
|
240
|
+
const compassString = `mongodb://${config.MONGODB_USER}:${config.MONGODB_PASS}@${networkIp}:${config.MONGODB_PORT}/${config.MONGODB_NAME}?authSource=admin`;
|
|
241
|
+
logger.log('ok', ` └─ Compass: ${compassString}`);
|
|
242
|
+
break;
|
|
243
|
+
case 'stopped':
|
|
244
|
+
logger.log('note', '📦 MongoDB: 🟡 Stopped');
|
|
245
|
+
logger.log('info', ` └─ Container: ${containers.mongo}`);
|
|
246
|
+
break;
|
|
247
|
+
case 'not_exists':
|
|
248
|
+
logger.log('info', '📦 MongoDB: ⚪ Not installed');
|
|
249
|
+
break;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// MinIO status
|
|
253
|
+
const minioStatus = await this.docker.getStatus(containers.minio);
|
|
254
|
+
switch (minioStatus) {
|
|
255
|
+
case 'running':
|
|
256
|
+
logger.log('ok', '📦 S3/MinIO: 🟢 Running');
|
|
257
|
+
logger.log('info', ` ├─ Container: ${containers.minio}`);
|
|
258
|
+
logger.log('info', ` ├─ API: http://${config.S3_HOST}:${config.S3_PORT}`);
|
|
259
|
+
logger.log('info', ` ├─ Console: http://${config.S3_HOST}:${config.S3_CONSOLE_PORT}`);
|
|
260
|
+
logger.log('info', ` └─ Bucket: ${config.S3_BUCKET}`);
|
|
261
|
+
break;
|
|
262
|
+
case 'stopped':
|
|
263
|
+
logger.log('note', '📦 S3/MinIO: 🟡 Stopped');
|
|
264
|
+
logger.log('info', ` └─ Container: ${containers.minio}`);
|
|
265
|
+
break;
|
|
266
|
+
case 'not_exists':
|
|
267
|
+
logger.log('info', '📦 S3/MinIO: ⚪ Not installed');
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Show configuration
|
|
274
|
+
*/
|
|
275
|
+
public async showConfig(): Promise<void> {
|
|
276
|
+
helpers.printHeader('Current Configuration');
|
|
277
|
+
|
|
278
|
+
const config = this.config.getConfig();
|
|
279
|
+
|
|
280
|
+
logger.log('info', `Project: ${config.PROJECT_NAME}`);
|
|
281
|
+
console.log();
|
|
282
|
+
|
|
283
|
+
logger.log('note', 'MongoDB:');
|
|
284
|
+
logger.log('info', ` Host: ${config.MONGODB_HOST}:${config.MONGODB_PORT}`);
|
|
285
|
+
logger.log('info', ` Database: ${config.MONGODB_NAME}`);
|
|
286
|
+
logger.log('info', ` User: ${config.MONGODB_USER}`);
|
|
287
|
+
logger.log('info', ' Password: ***');
|
|
288
|
+
logger.log('info', ` Container: ${this.config.getContainerNames().mongo}`);
|
|
289
|
+
logger.log('info', ` Data: ${this.config.getDataDirectories().mongo}`);
|
|
290
|
+
logger.log('info', ` Connection: ${this.config.getMongoConnectionString()}`);
|
|
291
|
+
|
|
292
|
+
console.log();
|
|
293
|
+
logger.log('note', 'S3/MinIO:');
|
|
294
|
+
logger.log('info', ` Host: ${config.S3_HOST}`);
|
|
295
|
+
logger.log('info', ` API Port: ${config.S3_PORT}`);
|
|
296
|
+
logger.log('info', ` Console Port: ${config.S3_CONSOLE_PORT}`);
|
|
297
|
+
logger.log('info', ` User: ${config.S3_USER}`);
|
|
298
|
+
logger.log('info', ' Password: ***');
|
|
299
|
+
logger.log('info', ` Bucket: ${config.S3_BUCKET}`);
|
|
300
|
+
logger.log('info', ` Container: ${this.config.getContainerNames().minio}`);
|
|
301
|
+
logger.log('info', ` Data: ${this.config.getDataDirectories().minio}`);
|
|
302
|
+
logger.log('info', ` API URL: http://${config.S3_HOST}:${config.S3_PORT}`);
|
|
303
|
+
logger.log('info', ` Console URL: http://${config.S3_HOST}:${config.S3_CONSOLE_PORT}`);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Show MongoDB Compass connection string
|
|
308
|
+
*/
|
|
309
|
+
public async showCompassConnection(): Promise<void> {
|
|
310
|
+
helpers.printHeader('MongoDB Compass Connection');
|
|
311
|
+
|
|
312
|
+
const config = this.config.getConfig();
|
|
313
|
+
const networkIp = await helpers.getLocalNetworkIp();
|
|
314
|
+
|
|
315
|
+
const connectionString = `mongodb://${config.MONGODB_USER}:${config.MONGODB_PASS}@${networkIp}:${config.MONGODB_PORT}/${config.MONGODB_NAME}?authSource=admin`;
|
|
316
|
+
|
|
317
|
+
logger.log('info', 'MongoDB Compass is a GUI tool for MongoDB. To connect:');
|
|
318
|
+
console.log();
|
|
319
|
+
logger.log('info', '1. Download MongoDB Compass from:');
|
|
320
|
+
logger.log('info', ' https://www.mongodb.com/products/compass');
|
|
321
|
+
console.log();
|
|
322
|
+
logger.log('info', '2. Open Compass and paste this connection string:');
|
|
323
|
+
logger.log('ok', ` ${connectionString}`);
|
|
324
|
+
console.log();
|
|
325
|
+
logger.log('note', 'Connection Details:');
|
|
326
|
+
logger.log('info', ` Network IP: ${networkIp}`);
|
|
327
|
+
logger.log('info', ` Port: ${config.MONGODB_PORT}`);
|
|
328
|
+
logger.log('info', ` Database: ${config.MONGODB_NAME}`);
|
|
329
|
+
logger.log('info', ` Username: ${config.MONGODB_USER}`);
|
|
330
|
+
logger.log('info', ` Auth Source: admin`);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Show logs for a service
|
|
335
|
+
*/
|
|
336
|
+
public async showLogs(service: string, lines: number = 20): Promise<void> {
|
|
337
|
+
const containers = this.config.getContainerNames();
|
|
338
|
+
|
|
339
|
+
switch (service) {
|
|
340
|
+
case 'mongo':
|
|
341
|
+
case 'mongodb':
|
|
342
|
+
if (await this.docker.isRunning(containers.mongo)) {
|
|
343
|
+
helpers.printHeader(`MongoDB Logs (last ${lines} lines)`);
|
|
344
|
+
const logs = await this.docker.logs(containers.mongo, lines);
|
|
345
|
+
console.log(logs);
|
|
346
|
+
} else {
|
|
347
|
+
logger.log('note', 'MongoDB container is not running');
|
|
348
|
+
}
|
|
349
|
+
break;
|
|
350
|
+
|
|
351
|
+
case 'minio':
|
|
352
|
+
case 's3':
|
|
353
|
+
if (await this.docker.isRunning(containers.minio)) {
|
|
354
|
+
helpers.printHeader(`S3/MinIO Logs (last ${lines} lines)`);
|
|
355
|
+
const logs = await this.docker.logs(containers.minio, lines);
|
|
356
|
+
console.log(logs);
|
|
357
|
+
} else {
|
|
358
|
+
logger.log('note', 'S3/MinIO container is not running');
|
|
359
|
+
}
|
|
360
|
+
break;
|
|
361
|
+
|
|
362
|
+
case 'all':
|
|
363
|
+
case '':
|
|
364
|
+
await this.showLogs('mongo', lines);
|
|
365
|
+
console.log();
|
|
366
|
+
await this.showLogs('minio', lines);
|
|
367
|
+
break;
|
|
368
|
+
|
|
369
|
+
default:
|
|
370
|
+
logger.log('note', 'Usage: gitzone services logs [mongo|s3|all] [lines]');
|
|
371
|
+
break;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Remove containers
|
|
377
|
+
*/
|
|
378
|
+
public async removeContainers(): Promise<void> {
|
|
379
|
+
const containers = this.config.getContainerNames();
|
|
380
|
+
let removed = false;
|
|
381
|
+
|
|
382
|
+
if (await this.docker.exists(containers.mongo)) {
|
|
383
|
+
if (await this.docker.remove(containers.mongo, true)) {
|
|
384
|
+
logger.log('ok', ' MongoDB container removed ✓');
|
|
385
|
+
removed = true;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
if (await this.docker.exists(containers.minio)) {
|
|
390
|
+
if (await this.docker.remove(containers.minio, true)) {
|
|
391
|
+
logger.log('ok', ' S3/MinIO container removed ✓');
|
|
392
|
+
removed = true;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
if (!removed) {
|
|
397
|
+
logger.log('note', ' No containers to remove');
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Clean data directories
|
|
403
|
+
*/
|
|
404
|
+
public async cleanData(): Promise<void> {
|
|
405
|
+
const directories = this.config.getDataDirectories();
|
|
406
|
+
let cleaned = false;
|
|
407
|
+
|
|
408
|
+
if (await plugins.smartfile.fs.fileExists(directories.mongo)) {
|
|
409
|
+
await plugins.smartfile.fs.remove(directories.mongo);
|
|
410
|
+
logger.log('ok', ' MongoDB data removed ✓');
|
|
411
|
+
cleaned = true;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
if (await plugins.smartfile.fs.fileExists(directories.minio)) {
|
|
415
|
+
await plugins.smartfile.fs.remove(directories.minio);
|
|
416
|
+
logger.log('ok', ' S3/MinIO data removed ✓');
|
|
417
|
+
cleaned = true;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
if (!cleaned) {
|
|
421
|
+
logger.log('note', ' No data to clean');
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|