@git.zone/cli 1.16.9 → 1.17.1
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 +2 -2
- 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 +363 -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 +29 -24
- 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 +423 -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,123 @@
|
|
|
1
|
+
import * as plugins from './mod.plugins.js';
|
|
2
|
+
import * as net from 'net';
|
|
3
|
+
import { logger } from '../gitzone.logging.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Check if a port is available
|
|
7
|
+
*/
|
|
8
|
+
export const isPortAvailable = async (port: number): Promise<boolean> => {
|
|
9
|
+
return new Promise((resolve) => {
|
|
10
|
+
const server = net.createServer();
|
|
11
|
+
|
|
12
|
+
server.once('error', () => {
|
|
13
|
+
resolve(false);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
server.once('listening', () => {
|
|
17
|
+
server.close();
|
|
18
|
+
resolve(true);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
server.listen(port, '0.0.0.0');
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Get a random available port between 20000 and 30000
|
|
27
|
+
*/
|
|
28
|
+
export const getRandomAvailablePort = async (): Promise<number> => {
|
|
29
|
+
const maxAttempts = 100;
|
|
30
|
+
|
|
31
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
32
|
+
const port = Math.floor(Math.random() * 10001) + 20000;
|
|
33
|
+
if (await isPortAvailable(port)) {
|
|
34
|
+
return port;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Fallback: let the system assign a port
|
|
39
|
+
return 0;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Get the project name from package.json or directory
|
|
44
|
+
*/
|
|
45
|
+
export const getProjectName = (): string => {
|
|
46
|
+
try {
|
|
47
|
+
const packageJsonPath = plugins.path.join(process.cwd(), 'package.json');
|
|
48
|
+
if (plugins.smartfile.fs.fileExistsSync(packageJsonPath)) {
|
|
49
|
+
const packageJson = plugins.smartfile.fs.toObjectSync(packageJsonPath);
|
|
50
|
+
if (packageJson.name) {
|
|
51
|
+
// Sanitize: @fin.cx/skr → fin-cx-skr
|
|
52
|
+
return packageJson.name.replace(/@/g, '').replace(/[\/\.]/g, '-');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
} catch (error) {
|
|
56
|
+
// Ignore errors and fall back to directory name
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return plugins.path.basename(process.cwd());
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Print a header with decorative lines
|
|
64
|
+
*/
|
|
65
|
+
export const printHeader = (title: string) => {
|
|
66
|
+
console.log();
|
|
67
|
+
logger.log('info', '═══════════════════════════════════════════════════════════════');
|
|
68
|
+
logger.log('info', ` ${title}`);
|
|
69
|
+
logger.log('info', '═══════════════════════════════════════════════════════════════');
|
|
70
|
+
console.log();
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Format bytes to human readable string
|
|
75
|
+
*/
|
|
76
|
+
export const formatBytes = (bytes: number): string => {
|
|
77
|
+
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
78
|
+
let size = bytes;
|
|
79
|
+
let unitIndex = 0;
|
|
80
|
+
|
|
81
|
+
while (size >= 1024 && unitIndex < units.length - 1) {
|
|
82
|
+
size /= 1024;
|
|
83
|
+
unitIndex++;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return `${size.toFixed(2)} ${units[unitIndex]}`;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Get the local network IP address
|
|
91
|
+
*/
|
|
92
|
+
export const getLocalNetworkIp = async (): Promise<string> => {
|
|
93
|
+
const smartnetworkInstance = new plugins.smartnetwork.SmartNetwork();
|
|
94
|
+
const gateways = await smartnetworkInstance.getGateways();
|
|
95
|
+
|
|
96
|
+
// Find the best local IP from network interfaces
|
|
97
|
+
for (const interfaceName of Object.keys(gateways)) {
|
|
98
|
+
const interfaces = gateways[interfaceName];
|
|
99
|
+
for (const iface of interfaces) {
|
|
100
|
+
// Skip loopback and internal interfaces
|
|
101
|
+
if (!iface.internal && iface.family === 'IPv4') {
|
|
102
|
+
const address = iface.address;
|
|
103
|
+
// Prefer LAN IPs
|
|
104
|
+
if (address.startsWith('192.168.') || address.startsWith('10.') || address.startsWith('172.')) {
|
|
105
|
+
return address;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Fallback: try to get any non-internal IPv4
|
|
112
|
+
for (const interfaceName of Object.keys(gateways)) {
|
|
113
|
+
const interfaces = gateways[interfaceName];
|
|
114
|
+
for (const iface of interfaces) {
|
|
115
|
+
if (!iface.internal && iface.family === 'IPv4') {
|
|
116
|
+
return iface.address;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Last resort: localhost
|
|
122
|
+
return 'localhost';
|
|
123
|
+
};
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import * as plugins from './mod.plugins.js';
|
|
2
|
+
import * as helpers from './helpers.js';
|
|
3
|
+
import { ServiceManager } from './classes.servicemanager.js';
|
|
4
|
+
import { logger } from '../gitzone.logging.js';
|
|
5
|
+
|
|
6
|
+
export const run = async (argvArg: any) => {
|
|
7
|
+
const serviceManager = new ServiceManager();
|
|
8
|
+
await serviceManager.init();
|
|
9
|
+
|
|
10
|
+
const command = argvArg._[1] || 'help';
|
|
11
|
+
const service = argvArg._[2] || 'all';
|
|
12
|
+
|
|
13
|
+
switch (command) {
|
|
14
|
+
case 'start':
|
|
15
|
+
await handleStart(serviceManager, service);
|
|
16
|
+
break;
|
|
17
|
+
|
|
18
|
+
case 'stop':
|
|
19
|
+
await handleStop(serviceManager, service);
|
|
20
|
+
break;
|
|
21
|
+
|
|
22
|
+
case 'restart':
|
|
23
|
+
await handleRestart(serviceManager, service);
|
|
24
|
+
break;
|
|
25
|
+
|
|
26
|
+
case 'status':
|
|
27
|
+
await serviceManager.showStatus();
|
|
28
|
+
break;
|
|
29
|
+
|
|
30
|
+
case 'config':
|
|
31
|
+
await serviceManager.showConfig();
|
|
32
|
+
break;
|
|
33
|
+
|
|
34
|
+
case 'compass':
|
|
35
|
+
await serviceManager.showCompassConnection();
|
|
36
|
+
break;
|
|
37
|
+
|
|
38
|
+
case 'logs':
|
|
39
|
+
const lines = parseInt(argvArg._[3]) || 20;
|
|
40
|
+
await serviceManager.showLogs(service, lines);
|
|
41
|
+
break;
|
|
42
|
+
|
|
43
|
+
case 'remove':
|
|
44
|
+
await handleRemove(serviceManager);
|
|
45
|
+
break;
|
|
46
|
+
|
|
47
|
+
case 'clean':
|
|
48
|
+
await handleClean(serviceManager);
|
|
49
|
+
break;
|
|
50
|
+
|
|
51
|
+
case 'help':
|
|
52
|
+
default:
|
|
53
|
+
showHelp();
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
async function handleStart(serviceManager: ServiceManager, service: string) {
|
|
59
|
+
helpers.printHeader('Starting Services');
|
|
60
|
+
|
|
61
|
+
switch (service) {
|
|
62
|
+
case 'mongo':
|
|
63
|
+
case 'mongodb':
|
|
64
|
+
await serviceManager.startMongoDB();
|
|
65
|
+
break;
|
|
66
|
+
|
|
67
|
+
case 'minio':
|
|
68
|
+
case 's3':
|
|
69
|
+
await serviceManager.startMinIO();
|
|
70
|
+
break;
|
|
71
|
+
|
|
72
|
+
case 'all':
|
|
73
|
+
case '':
|
|
74
|
+
await serviceManager.startMongoDB();
|
|
75
|
+
console.log();
|
|
76
|
+
await serviceManager.startMinIO();
|
|
77
|
+
break;
|
|
78
|
+
|
|
79
|
+
default:
|
|
80
|
+
logger.log('error', `Unknown service: ${service}`);
|
|
81
|
+
logger.log('note', 'Use: mongo, s3, or all');
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function handleStop(serviceManager: ServiceManager, service: string) {
|
|
87
|
+
helpers.printHeader('Stopping Services');
|
|
88
|
+
|
|
89
|
+
switch (service) {
|
|
90
|
+
case 'mongo':
|
|
91
|
+
case 'mongodb':
|
|
92
|
+
await serviceManager.stopMongoDB();
|
|
93
|
+
break;
|
|
94
|
+
|
|
95
|
+
case 'minio':
|
|
96
|
+
case 's3':
|
|
97
|
+
await serviceManager.stopMinIO();
|
|
98
|
+
break;
|
|
99
|
+
|
|
100
|
+
case 'all':
|
|
101
|
+
case '':
|
|
102
|
+
await serviceManager.stopMongoDB();
|
|
103
|
+
console.log();
|
|
104
|
+
await serviceManager.stopMinIO();
|
|
105
|
+
break;
|
|
106
|
+
|
|
107
|
+
default:
|
|
108
|
+
logger.log('error', `Unknown service: ${service}`);
|
|
109
|
+
logger.log('note', 'Use: mongo, s3, or all');
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async function handleRestart(serviceManager: ServiceManager, service: string) {
|
|
115
|
+
helpers.printHeader('Restarting Services');
|
|
116
|
+
|
|
117
|
+
switch (service) {
|
|
118
|
+
case 'mongo':
|
|
119
|
+
case 'mongodb':
|
|
120
|
+
await serviceManager.stopMongoDB();
|
|
121
|
+
await plugins.smartdelay.delayFor(2000);
|
|
122
|
+
await serviceManager.startMongoDB();
|
|
123
|
+
break;
|
|
124
|
+
|
|
125
|
+
case 'minio':
|
|
126
|
+
case 's3':
|
|
127
|
+
await serviceManager.stopMinIO();
|
|
128
|
+
await plugins.smartdelay.delayFor(2000);
|
|
129
|
+
await serviceManager.startMinIO();
|
|
130
|
+
break;
|
|
131
|
+
|
|
132
|
+
case 'all':
|
|
133
|
+
case '':
|
|
134
|
+
await serviceManager.stopMongoDB();
|
|
135
|
+
await serviceManager.stopMinIO();
|
|
136
|
+
await plugins.smartdelay.delayFor(2000);
|
|
137
|
+
await serviceManager.startMongoDB();
|
|
138
|
+
console.log();
|
|
139
|
+
await serviceManager.startMinIO();
|
|
140
|
+
break;
|
|
141
|
+
|
|
142
|
+
default:
|
|
143
|
+
logger.log('error', `Unknown service: ${service}`);
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
async function handleRemove(serviceManager: ServiceManager) {
|
|
149
|
+
helpers.printHeader('Removing Containers');
|
|
150
|
+
logger.log('note', '⚠️ This will remove containers but preserve data');
|
|
151
|
+
|
|
152
|
+
const shouldContinue = await plugins.smartinteract.SmartInteract.getCliConfirmation('Continue?', false);
|
|
153
|
+
|
|
154
|
+
if (shouldContinue) {
|
|
155
|
+
await serviceManager.removeContainers();
|
|
156
|
+
} else {
|
|
157
|
+
logger.log('note', 'Cancelled');
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async function handleClean(serviceManager: ServiceManager) {
|
|
162
|
+
helpers.printHeader('Clean All');
|
|
163
|
+
logger.log('error', '⚠️ WARNING: This will remove all containers and data!');
|
|
164
|
+
logger.log('error', 'This action cannot be undone!');
|
|
165
|
+
|
|
166
|
+
const smartinteraction = new plugins.smartinteract.SmartInteract();
|
|
167
|
+
const confirmAnswer = await smartinteraction.askQuestion({
|
|
168
|
+
name: 'confirm',
|
|
169
|
+
type: 'input',
|
|
170
|
+
message: 'Type "yes" to confirm:',
|
|
171
|
+
default: 'no'
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
if (confirmAnswer.value === 'yes') {
|
|
175
|
+
await serviceManager.removeContainers();
|
|
176
|
+
console.log();
|
|
177
|
+
await serviceManager.cleanData();
|
|
178
|
+
logger.log('ok', 'All cleaned ✓');
|
|
179
|
+
} else {
|
|
180
|
+
logger.log('note', 'Cancelled');
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function showHelp() {
|
|
185
|
+
helpers.printHeader('GitZone Services Manager');
|
|
186
|
+
|
|
187
|
+
logger.log('ok', 'Usage: gitzone services [command] [options]');
|
|
188
|
+
console.log();
|
|
189
|
+
|
|
190
|
+
logger.log('note', 'Commands:');
|
|
191
|
+
logger.log('info', ' start [service] Start services (mongo|s3|all)');
|
|
192
|
+
logger.log('info', ' stop [service] Stop services (mongo|s3|all)');
|
|
193
|
+
logger.log('info', ' restart [service] Restart services (mongo|s3|all)');
|
|
194
|
+
logger.log('info', ' status Show service status');
|
|
195
|
+
logger.log('info', ' config Show current configuration');
|
|
196
|
+
logger.log('info', ' compass Show MongoDB Compass connection string');
|
|
197
|
+
logger.log('info', ' logs [service] Show logs (mongo|s3|all) [lines]');
|
|
198
|
+
logger.log('info', ' remove Remove all containers');
|
|
199
|
+
logger.log('info', ' clean Remove all containers and data ⚠️');
|
|
200
|
+
logger.log('info', ' help Show this help message');
|
|
201
|
+
console.log();
|
|
202
|
+
|
|
203
|
+
logger.log('note', 'Features:');
|
|
204
|
+
logger.log('info', ' • Auto-creates .nogit/env.json with smart defaults');
|
|
205
|
+
logger.log('info', ' • Random ports (20000-30000) to avoid conflicts');
|
|
206
|
+
logger.log('info', ' • Project-specific containers for multi-project support');
|
|
207
|
+
logger.log('info', ' • Preserves custom configuration values');
|
|
208
|
+
logger.log('info', ' • MongoDB Compass connection support');
|
|
209
|
+
console.log();
|
|
210
|
+
|
|
211
|
+
logger.log('note', 'Examples:');
|
|
212
|
+
logger.log('info', ' gitzone services start # Start all services');
|
|
213
|
+
logger.log('info', ' gitzone services start mongo # Start only MongoDB');
|
|
214
|
+
logger.log('info', ' gitzone services stop # Stop all services');
|
|
215
|
+
logger.log('info', ' gitzone services status # Check service status');
|
|
216
|
+
logger.log('info', ' gitzone services config # Show configuration');
|
|
217
|
+
logger.log('info', ' gitzone services compass # Get MongoDB Compass connection');
|
|
218
|
+
logger.log('info', ' gitzone services logs mongo 50 # Show last 50 lines of MongoDB logs');
|
|
219
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from '../plugins.js';
|
|
2
|
+
|
|
3
|
+
import * as smartshell from '@push.rocks/smartshell';
|
|
4
|
+
import * as smartfile from '@push.rocks/smartfile';
|
|
5
|
+
import * as smartinteract from '@push.rocks/smartinteract';
|
|
6
|
+
import * as smartnetwork from '@push.rocks/smartnetwork';
|
|
7
|
+
import * as smartdelay from '@push.rocks/smartdelay';
|
|
8
|
+
|
|
9
|
+
export { smartshell, smartfile, smartinteract, smartnetwork, smartdelay };
|
package/ts/plugins.ts
CHANGED
|
@@ -7,6 +7,11 @@ import * as smartcli from '@push.rocks/smartcli';
|
|
|
7
7
|
import * as smartpath from '@push.rocks/smartpath';
|
|
8
8
|
import * as smartpromise from '@push.rocks/smartpromise';
|
|
9
9
|
import * as smartupdate from '@push.rocks/smartupdate';
|
|
10
|
+
import * as smartshell from '@push.rocks/smartshell';
|
|
11
|
+
import * as smartnetwork from '@push.rocks/smartnetwork';
|
|
12
|
+
import * as smartfile from '@push.rocks/smartfile';
|
|
13
|
+
import * as smartinteract from '@push.rocks/smartinteract';
|
|
14
|
+
import * as smartdelay from '@push.rocks/smartdelay';
|
|
10
15
|
|
|
11
16
|
export {
|
|
12
17
|
smartlog,
|
|
@@ -18,4 +23,9 @@ export {
|
|
|
18
23
|
smartpath,
|
|
19
24
|
smartpromise,
|
|
20
25
|
smartupdate,
|
|
26
|
+
smartshell,
|
|
27
|
+
smartnetwork,
|
|
28
|
+
smartfile,
|
|
29
|
+
smartinteract,
|
|
30
|
+
smartdelay,
|
|
21
31
|
};
|