@git.zone/cli 1.21.5 → 2.1.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.
Files changed (61) hide show
  1. package/dist_ts/00_commitinfo_data.js +2 -2
  2. package/dist_ts/mod_commit/index.js +5 -2
  3. package/dist_ts/mod_commit/mod.helpers.js +24 -9
  4. package/dist_ts/mod_format/classes.baseformatter.js +4 -4
  5. package/dist_ts/mod_format/classes.changecache.js +29 -17
  6. package/dist_ts/mod_format/classes.diffreporter.js +10 -4
  7. package/dist_ts/mod_format/classes.formatstats.js +5 -2
  8. package/dist_ts/mod_format/classes.rollbackmanager.js +41 -17
  9. package/dist_ts/mod_format/format.cleanup.js +5 -3
  10. package/dist_ts/mod_format/format.copy.js +12 -4
  11. package/dist_ts/mod_format/format.gitignore.js +14 -5
  12. package/dist_ts/mod_format/format.license.js +4 -2
  13. package/dist_ts/mod_format/format.packagejson.js +6 -2
  14. package/dist_ts/mod_format/format.readme.js +9 -5
  15. package/dist_ts/mod_format/format.tsconfig.js +7 -4
  16. package/dist_ts/mod_format/formatters/cleanup.formatter.js +2 -2
  17. package/dist_ts/mod_format/formatters/prettier.formatter.js +19 -6
  18. package/dist_ts/mod_format/index.js +9 -3
  19. package/dist_ts/mod_meta/meta.classes.meta.js +82 -17
  20. package/dist_ts/mod_services/classes.globalregistry.d.ts +77 -0
  21. package/dist_ts/mod_services/classes.globalregistry.js +133 -0
  22. package/dist_ts/mod_services/classes.serviceconfiguration.d.ts +7 -0
  23. package/dist_ts/mod_services/classes.serviceconfiguration.js +86 -10
  24. package/dist_ts/mod_services/classes.servicemanager.d.ts +38 -0
  25. package/dist_ts/mod_services/classes.servicemanager.js +353 -10
  26. package/dist_ts/mod_services/helpers.d.ts +1 -1
  27. package/dist_ts/mod_services/helpers.js +8 -4
  28. package/dist_ts/mod_services/index.js +194 -28
  29. package/dist_ts/mod_standard/index.js +22 -9
  30. package/dist_ts/mod_template/index.js +2 -2
  31. package/dist_ts/plugins.d.ts +2 -0
  32. package/dist_ts/plugins.js +4 -1
  33. package/package.json +7 -6
  34. package/readme.hints.md +55 -2
  35. package/ts/00_commitinfo_data.ts +1 -1
  36. package/ts/mod_commit/index.ts +4 -4
  37. package/ts/mod_commit/mod.helpers.ts +23 -11
  38. package/ts/mod_format/classes.baseformatter.ts +3 -3
  39. package/ts/mod_format/classes.changecache.ts +28 -16
  40. package/ts/mod_format/classes.diffreporter.ts +9 -8
  41. package/ts/mod_format/classes.formatstats.ts +4 -4
  42. package/ts/mod_format/classes.rollbackmanager.ts +40 -18
  43. package/ts/mod_format/format.cleanup.ts +4 -4
  44. package/ts/mod_format/format.copy.ts +11 -3
  45. package/ts/mod_format/format.gitignore.ts +13 -6
  46. package/ts/mod_format/format.license.ts +3 -3
  47. package/ts/mod_format/format.packagejson.ts +5 -3
  48. package/ts/mod_format/format.readme.ts +8 -11
  49. package/ts/mod_format/format.tsconfig.ts +6 -5
  50. package/ts/mod_format/formatters/cleanup.formatter.ts +1 -1
  51. package/ts/mod_format/formatters/prettier.formatter.ts +18 -8
  52. package/ts/mod_format/index.ts +10 -5
  53. package/ts/mod_meta/meta.classes.meta.ts +84 -41
  54. package/ts/mod_services/classes.globalregistry.ts +190 -0
  55. package/ts/mod_services/classes.serviceconfiguration.ts +121 -35
  56. package/ts/mod_services/classes.servicemanager.ts +405 -32
  57. package/ts/mod_services/helpers.ts +8 -4
  58. package/ts/mod_services/index.ts +257 -48
  59. package/ts/mod_standard/index.ts +23 -10
  60. package/ts/mod_template/index.ts +1 -1
  61. package/ts/plugins.ts +4 -0
@@ -1,15 +1,25 @@
1
1
  import * as plugins from './mod.plugins.js';
2
2
  import * as helpers from './helpers.js';
3
3
  import { ServiceManager } from './classes.servicemanager.js';
4
+ import { GlobalRegistry } from './classes.globalregistry.js';
4
5
  import { logger } from '../gitzone.logging.js';
5
6
 
6
7
  export const run = async (argvArg: any) => {
8
+ const isGlobal = argvArg.g || argvArg.global;
9
+ const command = argvArg._[1] || 'help';
10
+
11
+ // Handle global commands first
12
+ if (isGlobal) {
13
+ await handleGlobalCommand(command);
14
+ return;
15
+ }
16
+
17
+ // Local project commands
7
18
  const serviceManager = new ServiceManager();
8
19
  await serviceManager.init();
9
-
10
- const command = argvArg._[1] || 'help';
20
+
11
21
  const service = argvArg._[2] || 'all';
12
-
22
+
13
23
  switch (command) {
14
24
  case 'start':
15
25
  await handleStart(serviceManager, service);
@@ -28,9 +38,13 @@ export const run = async (argvArg: any) => {
28
38
  break;
29
39
 
30
40
  case 'config':
31
- await serviceManager.showConfig();
41
+ if (service === 'services' || argvArg._[2] === 'services') {
42
+ await handleConfigureServices(serviceManager);
43
+ } else {
44
+ await serviceManager.showConfig();
45
+ }
32
46
  break;
33
-
47
+
34
48
  case 'compass':
35
49
  await serviceManager.showCompassConnection();
36
50
  break;
@@ -61,63 +75,69 @@ export const run = async (argvArg: any) => {
61
75
 
62
76
  async function handleStart(serviceManager: ServiceManager, service: string) {
63
77
  helpers.printHeader('Starting Services');
64
-
78
+
65
79
  switch (service) {
66
80
  case 'mongo':
67
81
  case 'mongodb':
68
82
  await serviceManager.startMongoDB();
69
83
  break;
70
-
84
+
71
85
  case 'minio':
72
86
  case 's3':
73
87
  await serviceManager.startMinIO();
74
88
  break;
75
-
89
+
90
+ case 'elasticsearch':
91
+ case 'es':
92
+ await serviceManager.startElasticsearch();
93
+ break;
94
+
76
95
  case 'all':
77
96
  case '':
78
- await serviceManager.startMongoDB();
79
- console.log();
80
- await serviceManager.startMinIO();
97
+ await serviceManager.startAll();
81
98
  break;
82
-
99
+
83
100
  default:
84
101
  logger.log('error', `Unknown service: ${service}`);
85
- logger.log('note', 'Use: mongo, s3, or all');
102
+ logger.log('note', 'Use: mongo, s3, elasticsearch, or all');
86
103
  break;
87
104
  }
88
105
  }
89
106
 
90
107
  async function handleStop(serviceManager: ServiceManager, service: string) {
91
108
  helpers.printHeader('Stopping Services');
92
-
109
+
93
110
  switch (service) {
94
111
  case 'mongo':
95
112
  case 'mongodb':
96
113
  await serviceManager.stopMongoDB();
97
114
  break;
98
-
115
+
99
116
  case 'minio':
100
117
  case 's3':
101
118
  await serviceManager.stopMinIO();
102
119
  break;
103
-
120
+
121
+ case 'elasticsearch':
122
+ case 'es':
123
+ await serviceManager.stopElasticsearch();
124
+ break;
125
+
104
126
  case 'all':
105
127
  case '':
106
- await serviceManager.stopMongoDB();
107
- console.log();
108
- await serviceManager.stopMinIO();
128
+ await serviceManager.stopAll();
109
129
  break;
110
-
130
+
111
131
  default:
112
132
  logger.log('error', `Unknown service: ${service}`);
113
- logger.log('note', 'Use: mongo, s3, or all');
133
+ logger.log('note', 'Use: mongo, s3, elasticsearch, or all');
114
134
  break;
115
135
  }
116
136
  }
117
137
 
118
138
  async function handleRestart(serviceManager: ServiceManager, service: string) {
119
139
  helpers.printHeader('Restarting Services');
120
-
140
+
121
141
  switch (service) {
122
142
  case 'mongo':
123
143
  case 'mongodb':
@@ -125,24 +145,28 @@ async function handleRestart(serviceManager: ServiceManager, service: string) {
125
145
  await plugins.smartdelay.delayFor(2000);
126
146
  await serviceManager.startMongoDB();
127
147
  break;
128
-
148
+
129
149
  case 'minio':
130
150
  case 's3':
131
151
  await serviceManager.stopMinIO();
132
152
  await plugins.smartdelay.delayFor(2000);
133
153
  await serviceManager.startMinIO();
134
154
  break;
135
-
155
+
156
+ case 'elasticsearch':
157
+ case 'es':
158
+ await serviceManager.stopElasticsearch();
159
+ await plugins.smartdelay.delayFor(2000);
160
+ await serviceManager.startElasticsearch();
161
+ break;
162
+
136
163
  case 'all':
137
164
  case '':
138
- await serviceManager.stopMongoDB();
139
- await serviceManager.stopMinIO();
165
+ await serviceManager.stopAll();
140
166
  await plugins.smartdelay.delayFor(2000);
141
- await serviceManager.startMongoDB();
142
- console.log();
143
- await serviceManager.startMinIO();
167
+ await serviceManager.startAll();
144
168
  break;
145
-
169
+
146
170
  default:
147
171
  logger.log('error', `Unknown service: ${service}`);
148
172
  break;
@@ -166,7 +190,7 @@ async function handleClean(serviceManager: ServiceManager) {
166
190
  helpers.printHeader('Clean All');
167
191
  logger.log('error', '⚠️ WARNING: This will remove all containers and data!');
168
192
  logger.log('error', 'This action cannot be undone!');
169
-
193
+
170
194
  const smartinteraction = new plugins.smartinteract.SmartInteract();
171
195
  const confirmAnswer = await smartinteraction.askQuestion({
172
196
  name: 'confirm',
@@ -174,7 +198,7 @@ async function handleClean(serviceManager: ServiceManager) {
174
198
  message: 'Type "yes" to confirm:',
175
199
  default: 'no'
176
200
  });
177
-
201
+
178
202
  if (confirmAnswer.value === 'yes') {
179
203
  await serviceManager.removeContainers();
180
204
  console.log();
@@ -185,40 +209,225 @@ async function handleClean(serviceManager: ServiceManager) {
185
209
  }
186
210
  }
187
211
 
212
+ async function handleConfigureServices(serviceManager: ServiceManager) {
213
+ helpers.printHeader('Configure Services');
214
+ await serviceManager.configureServices();
215
+ }
216
+
188
217
  function showHelp() {
189
218
  helpers.printHeader('GitZone Services Manager');
190
-
219
+
191
220
  logger.log('ok', 'Usage: gitzone services [command] [options]');
192
221
  console.log();
193
-
222
+
194
223
  logger.log('note', 'Commands:');
195
- logger.log('info', ' start [service] Start services (mongo|s3|all)');
196
- logger.log('info', ' stop [service] Stop services (mongo|s3|all)');
197
- logger.log('info', ' restart [service] Restart services (mongo|s3|all)');
224
+ logger.log('info', ' start [service] Start services (mongo|s3|elasticsearch|all)');
225
+ logger.log('info', ' stop [service] Stop services (mongo|s3|elasticsearch|all)');
226
+ logger.log('info', ' restart [service] Restart services (mongo|s3|elasticsearch|all)');
198
227
  logger.log('info', ' status Show service status');
199
228
  logger.log('info', ' config Show current configuration');
229
+ logger.log('info', ' config services Configure which services are enabled');
200
230
  logger.log('info', ' compass Show MongoDB Compass connection string');
201
- logger.log('info', ' logs [service] Show logs (mongo|s3|all) [lines]');
231
+ logger.log('info', ' logs [service] Show logs (mongo|s3|elasticsearch|all) [lines]');
202
232
  logger.log('info', ' reconfigure Reassign ports and restart services');
203
233
  logger.log('info', ' remove Remove all containers');
204
234
  logger.log('info', ' clean Remove all containers and data ⚠️');
205
235
  logger.log('info', ' help Show this help message');
206
236
  console.log();
207
-
237
+
238
+ logger.log('note', 'Available Services:');
239
+ logger.log('info', ' • MongoDB (mongo) - Document database');
240
+ logger.log('info', ' • MinIO (s3) - S3-compatible object storage');
241
+ logger.log('info', ' • Elasticsearch (elasticsearch) - Search and analytics engine');
242
+ console.log();
243
+
208
244
  logger.log('note', 'Features:');
209
245
  logger.log('info', ' • Auto-creates .nogit/env.json with smart defaults');
210
- logger.log('info', ' • Random ports (20000-30000) to avoid conflicts');
246
+ logger.log('info', ' • Random ports (20000-30000) for MongoDB/MinIO to avoid conflicts');
247
+ logger.log('info', ' • Elasticsearch uses standard port 9200');
211
248
  logger.log('info', ' • Project-specific containers for multi-project support');
212
249
  logger.log('info', ' • Preserves custom configuration values');
213
250
  logger.log('info', ' • MongoDB Compass connection support');
214
251
  console.log();
215
-
252
+
216
253
  logger.log('note', 'Examples:');
217
- logger.log('info', ' gitzone services start # Start all services');
218
- logger.log('info', ' gitzone services start mongo # Start only MongoDB');
219
- logger.log('info', ' gitzone services stop # Stop all services');
220
- logger.log('info', ' gitzone services status # Check service status');
221
- logger.log('info', ' gitzone services config # Show configuration');
222
- logger.log('info', ' gitzone services compass # Get MongoDB Compass connection');
223
- logger.log('info', ' gitzone services logs mongo 50 # Show last 50 lines of MongoDB logs');
254
+ logger.log('info', ' gitzone services start # Start all services');
255
+ logger.log('info', ' gitzone services start mongo # Start only MongoDB');
256
+ logger.log('info', ' gitzone services start elasticsearch # Start only Elasticsearch');
257
+ logger.log('info', ' gitzone services stop # Stop all services');
258
+ logger.log('info', ' gitzone services status # Check service status');
259
+ logger.log('info', ' gitzone services config # Show configuration');
260
+ logger.log('info', ' gitzone services compass # Get MongoDB Compass connection');
261
+ logger.log('info', ' gitzone services logs elasticsearch # Show Elasticsearch logs');
262
+ console.log();
263
+
264
+ logger.log('note', 'Global Commands (-g/--global):');
265
+ logger.log('info', ' list -g List all registered projects');
266
+ logger.log('info', ' status -g Show status across all projects');
267
+ logger.log('info', ' stop -g Stop all containers across all projects');
268
+ logger.log('info', ' cleanup -g Remove stale registry entries');
269
+ console.log();
270
+
271
+ logger.log('note', 'Global Examples:');
272
+ logger.log('info', ' gitzone services list -g # List all registered projects');
273
+ logger.log('info', ' gitzone services status -g # Show global container status');
274
+ logger.log('info', ' gitzone services stop -g # Stop all (prompts for confirmation)');
275
+ }
276
+
277
+ // ==================== Global Command Handlers ====================
278
+
279
+ async function handleGlobalCommand(command: string) {
280
+ const globalRegistry = GlobalRegistry.getInstance();
281
+
282
+ switch (command) {
283
+ case 'list':
284
+ await handleGlobalList(globalRegistry);
285
+ break;
286
+
287
+ case 'status':
288
+ await handleGlobalStatus(globalRegistry);
289
+ break;
290
+
291
+ case 'stop':
292
+ await handleGlobalStop(globalRegistry);
293
+ break;
294
+
295
+ case 'cleanup':
296
+ await handleGlobalCleanup(globalRegistry);
297
+ break;
298
+
299
+ case 'help':
300
+ default:
301
+ showHelp();
302
+ break;
303
+ }
304
+ }
305
+
306
+ async function handleGlobalList(globalRegistry: GlobalRegistry) {
307
+ helpers.printHeader('Registered Projects (Global)');
308
+
309
+ const projects = await globalRegistry.getAllProjects();
310
+ const projectPaths = Object.keys(projects);
311
+
312
+ if (projectPaths.length === 0) {
313
+ logger.log('note', 'No projects registered');
314
+ return;
315
+ }
316
+
317
+ for (const path of projectPaths) {
318
+ const project = projects[path];
319
+ const lastActive = new Date(project.lastActive).toLocaleString();
320
+
321
+ console.log();
322
+ logger.log('ok', `📁 ${project.projectName}`);
323
+ logger.log('info', ` Path: ${project.projectPath}`);
324
+ logger.log('info', ` Services: ${project.enabledServices.join(', ')}`);
325
+ logger.log('info', ` Last Active: ${lastActive}`);
326
+ }
327
+ }
328
+
329
+ async function handleGlobalStatus(globalRegistry: GlobalRegistry) {
330
+ helpers.printHeader('Global Service Status');
331
+
332
+ const statuses = await globalRegistry.getGlobalStatus();
333
+
334
+ if (statuses.length === 0) {
335
+ logger.log('note', 'No projects registered');
336
+ return;
337
+ }
338
+
339
+ let runningCount = 0;
340
+ let totalContainers = 0;
341
+
342
+ for (const project of statuses) {
343
+ console.log();
344
+ logger.log('ok', `📁 ${project.projectName}`);
345
+ logger.log('info', ` Path: ${project.projectPath}`);
346
+
347
+ if (project.containers.length === 0) {
348
+ logger.log('note', ' No containers configured');
349
+ continue;
350
+ }
351
+
352
+ for (const container of project.containers) {
353
+ totalContainers++;
354
+ const statusIcon = container.status === 'running' ? '🟢' : container.status === 'exited' ? '🟡' : '⚪';
355
+ if (container.status === 'running') runningCount++;
356
+ logger.log('info', ` ${statusIcon} ${container.name}: ${container.status}`);
357
+ }
358
+ }
359
+
360
+ console.log();
361
+ logger.log('note', `Summary: ${runningCount}/${totalContainers} containers running across ${statuses.length} project(s)`);
362
+ }
363
+
364
+ async function handleGlobalStop(globalRegistry: GlobalRegistry) {
365
+ helpers.printHeader('Stop All Containers (Global)');
366
+
367
+ const statuses = await globalRegistry.getGlobalStatus();
368
+
369
+ // Count running containers
370
+ let runningCount = 0;
371
+ for (const project of statuses) {
372
+ for (const container of project.containers) {
373
+ if (container.status === 'running') runningCount++;
374
+ }
375
+ }
376
+
377
+ if (runningCount === 0) {
378
+ logger.log('note', 'No running containers found');
379
+ return;
380
+ }
381
+
382
+ logger.log('note', `Found ${runningCount} running container(s) across ${statuses.length} project(s)`);
383
+ console.log();
384
+
385
+ // Show what will be stopped
386
+ for (const project of statuses) {
387
+ const runningContainers = project.containers.filter(c => c.status === 'running');
388
+ if (runningContainers.length > 0) {
389
+ logger.log('info', `${project.projectName}:`);
390
+ for (const container of runningContainers) {
391
+ logger.log('info', ` • ${container.name}`);
392
+ }
393
+ }
394
+ }
395
+
396
+ console.log();
397
+ const shouldContinue = await plugins.smartinteract.SmartInteract.getCliConfirmation(
398
+ 'Stop all containers?',
399
+ false
400
+ );
401
+
402
+ if (!shouldContinue) {
403
+ logger.log('note', 'Cancelled');
404
+ return;
405
+ }
406
+
407
+ logger.log('note', 'Stopping all containers...');
408
+ const result = await globalRegistry.stopAll();
409
+
410
+ if (result.stopped.length > 0) {
411
+ logger.log('ok', `Stopped: ${result.stopped.join(', ')}`);
412
+ }
413
+ if (result.failed.length > 0) {
414
+ logger.log('error', `Failed to stop: ${result.failed.join(', ')}`);
415
+ }
416
+ }
417
+
418
+ async function handleGlobalCleanup(globalRegistry: GlobalRegistry) {
419
+ helpers.printHeader('Cleanup Registry (Global)');
420
+
421
+ logger.log('note', 'Checking for stale registry entries...');
422
+ const removed = await globalRegistry.cleanup();
423
+
424
+ if (removed.length === 0) {
425
+ logger.log('ok', 'No stale entries found');
426
+ return;
427
+ }
428
+
429
+ logger.log('ok', `Removed ${removed.length} stale entr${removed.length === 1 ? 'y' : 'ies'}:`);
430
+ for (const path of removed) {
431
+ logger.log('info', ` • ${path}`);
432
+ }
224
433
  }
@@ -6,23 +6,36 @@ import * as paths from '../paths.js';
6
6
 
7
7
  import { logger } from '../gitzone.logging.js';
8
8
 
9
- export let run = () => {
9
+ export let run = async () => {
10
10
  const done = plugins.smartpromise.defer();
11
11
  logger.log('warn', 'no action specified');
12
+
13
+ const dirEntries = await plugins.smartfs.directory(paths.templatesDir).list();
14
+ const templates: string[] = [];
15
+ for (const entry of dirEntries) {
16
+ try {
17
+ const stats = await plugins.smartfs
18
+ .file(plugins.path.join(paths.templatesDir, entry.path))
19
+ .stat();
20
+ if (stats.isDirectory) {
21
+ templates.push(entry.name);
22
+ }
23
+ } catch {
24
+ // Skip entries that can't be accessed
25
+ }
26
+ }
27
+
28
+ let projects = `\n`;
29
+ for (const template of templates) {
30
+ projects += ` - ${template}\n`;
31
+ }
32
+
12
33
  logger.log(
13
34
  'info',
14
35
  `
15
36
  You can do one of the following things:
16
37
  * create a new project with 'gitzone template [template]'
17
- the following templates exist: ${(() => {
18
- let projects = `\n`;
19
- for (const template of plugins.smartfile.fs.listFoldersSync(
20
- paths.templatesDir,
21
- )) {
22
- projects += ` - ${template}\n`;
23
- }
24
- return projects;
25
- })()}
38
+ the following templates exist: ${projects}
26
39
  * format a project with 'gitzone format'
27
40
  `,
28
41
  );
@@ -11,7 +11,7 @@ export const getTemplatePath = (templateNameArg: string) => {
11
11
  * receives a template name and returns wether there is a corresponding template
12
12
  */
13
13
  export const isTemplate = async (templateNameArg: string) => {
14
- return plugins.smartfile.fs.isDirectory(getTemplatePath(templateNameArg));
14
+ return plugins.smartfs.directory(getTemplatePath(templateNameArg)).exists();
15
15
  };
16
16
 
17
17
  export const getTemplate = async (templateNameArg: string) => {
package/ts/plugins.ts CHANGED
@@ -10,9 +10,13 @@ import * as smartupdate from '@push.rocks/smartupdate';
10
10
  import * as smartshell from '@push.rocks/smartshell';
11
11
  import * as smartnetwork from '@push.rocks/smartnetwork';
12
12
  import * as smartfile from '@push.rocks/smartfile';
13
+ import { SmartFs, SmartFsProviderNode } from '@push.rocks/smartfs';
13
14
  import * as smartinteract from '@push.rocks/smartinteract';
14
15
  import * as smartdelay from '@push.rocks/smartdelay';
15
16
 
17
+ // Create smartfs instance for filesystem operations
18
+ export const smartfs = new SmartFs(new SmartFsProviderNode());
19
+
16
20
  export {
17
21
  smartlog,
18
22
  smartlogDestinationLocal,