@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
@@ -101,7 +101,12 @@ export let run = async (
101
101
  // Plan phase
102
102
  logger.log('info', 'Analyzing project for format operations...');
103
103
  let plan = options.fromPlan
104
- ? JSON.parse(await plugins.smartfile.fs.toStringSync(options.fromPlan))
104
+ ? JSON.parse(
105
+ (await plugins.smartfs
106
+ .file(options.fromPlan)
107
+ .encoding('utf8')
108
+ .read()) as string,
109
+ )
105
110
  : await planner.planFormat(activeFormatters);
106
111
 
107
112
  // Display plan
@@ -109,10 +114,10 @@ export let run = async (
109
114
 
110
115
  // Save plan if requested
111
116
  if (options.savePlan) {
112
- await plugins.smartfile.memory.toFs(
113
- JSON.stringify(plan, null, 2),
114
- options.savePlan,
115
- );
117
+ await plugins.smartfs
118
+ .file(options.savePlan)
119
+ .encoding('utf8')
120
+ .write(JSON.stringify(plan, null, 2));
116
121
  logger.log('info', `Plan saved to ${options.savePlan}`);
117
122
  }
118
123
 
@@ -48,15 +48,17 @@ export class Meta {
48
48
  public async readDirectory() {
49
49
  await this.syncToRemote(true);
50
50
  logger.log('info', `reading directory`);
51
- const metaFileExists = plugins.smartfile.fs.fileExistsSync(
52
- this.filePaths.metaJson,
53
- );
51
+ const metaFileExists = await plugins.smartfs
52
+ .file(this.filePaths.metaJson)
53
+ .exists();
54
54
  if (!metaFileExists) {
55
55
  throw new Error(`meta file does not exist at ${this.filePaths.metaJson}`);
56
56
  }
57
- this.metaRepoData = plugins.smartfile.fs.toObjectSync(
58
- this.filePaths.metaJson,
59
- );
57
+ const content = (await plugins.smartfs
58
+ .file(this.filePaths.metaJson)
59
+ .encoding('utf8')
60
+ .read()) as string;
61
+ this.metaRepoData = JSON.parse(content);
60
62
  }
61
63
 
62
64
  /**
@@ -78,15 +80,15 @@ export class Meta {
78
80
  */
79
81
  public async writeToDisk() {
80
82
  // write .meta.json to disk
81
- plugins.smartfile.memory.toFsSync(
82
- JSON.stringify(this.metaRepoData, null, 2),
83
- this.filePaths.metaJson,
84
- );
83
+ await plugins.smartfs
84
+ .file(this.filePaths.metaJson)
85
+ .encoding('utf8')
86
+ .write(JSON.stringify(this.metaRepoData, null, 2));
85
87
  // write .gitignore to disk
86
- plugins.smartfile.memory.toFsSync(
87
- await this.generateGitignore(),
88
- this.filePaths.gitIgnore,
89
- );
88
+ await plugins.smartfs
89
+ .file(this.filePaths.gitIgnore)
90
+ .encoding('utf8')
91
+ .write(await this.generateGitignore());
90
92
  }
91
93
 
92
94
  /**
@@ -112,10 +114,25 @@ export class Meta {
112
114
  */
113
115
  public async updateLocalRepos() {
114
116
  await this.syncToRemote();
115
- const projects = plugins.smartfile.fs.toObjectSync(
116
- this.filePaths.metaJson,
117
- ).projects;
118
- const preExistingFolders = plugins.smartfile.fs.listFoldersSync(this.cwd);
117
+ const metaContent = (await plugins.smartfs
118
+ .file(this.filePaths.metaJson)
119
+ .encoding('utf8')
120
+ .read()) as string;
121
+ const projects = JSON.parse(metaContent).projects;
122
+ const entries = await plugins.smartfs.directory(this.cwd).list();
123
+ const preExistingFolders: string[] = [];
124
+ for (const entry of entries) {
125
+ try {
126
+ const stats = await plugins.smartfs
127
+ .file(plugins.path.join(this.cwd, entry.path))
128
+ .stat();
129
+ if (stats.isDirectory) {
130
+ preExistingFolders.push(entry.name);
131
+ }
132
+ } catch {
133
+ // Skip entries that can't be accessed
134
+ }
135
+ }
119
136
  for (const preExistingFolderArg of preExistingFolders) {
120
137
  if (
121
138
  preExistingFolderArg !== '.git' &&
@@ -143,9 +160,17 @@ export class Meta {
143
160
  await this.sortMetaRepoData();
144
161
  const missingRepos: string[] = [];
145
162
  for (const key of Object.keys(this.metaRepoData.projects)) {
146
- plugins.smartfile.fs.isDirectory(key)
147
- ? logger.log('ok', `${key} -> is already cloned`)
148
- : missingRepos.push(key);
163
+ const fullPath = plugins.path.join(this.cwd, key);
164
+ try {
165
+ const stats = await plugins.smartfs.file(fullPath).stat();
166
+ if (stats.isDirectory) {
167
+ logger.log('ok', `${key} -> is already cloned`);
168
+ } else {
169
+ missingRepos.push(key);
170
+ }
171
+ } catch {
172
+ missingRepos.push(key);
173
+ }
149
174
  }
150
175
 
151
176
  logger.log('info', `found ${missingRepos.length} missing repos`);
@@ -165,7 +190,20 @@ export class Meta {
165
190
  await this.syncToRemote();
166
191
 
167
192
  // go recursive
168
- const folders = await plugins.smartfile.fs.listFolders(this.cwd);
193
+ const listEntries = await plugins.smartfs.directory(this.cwd).list();
194
+ const folders: string[] = [];
195
+ for (const entry of listEntries) {
196
+ try {
197
+ const stats = await plugins.smartfs
198
+ .file(plugins.path.join(this.cwd, entry.path))
199
+ .stat();
200
+ if (stats.isDirectory) {
201
+ folders.push(entry.name);
202
+ }
203
+ } catch {
204
+ // Skip entries that can't be accessed
205
+ }
206
+ }
169
207
  const childMetaRepositories: string[] = [];
170
208
  for (const folder of folders) {
171
209
  logger.log('info', folder);
@@ -180,27 +218,31 @@ export class Meta {
180
218
  */
181
219
  public async initProject() {
182
220
  await this.syncToRemote(true);
183
- const fileExists = await plugins.smartfile.fs.fileExists(
184
- this.filePaths.metaJson,
185
- );
221
+ const fileExists = await plugins.smartfs
222
+ .file(this.filePaths.metaJson)
223
+ .exists();
186
224
  if (!fileExists) {
187
- await plugins.smartfile.memory.toFs(
188
- JSON.stringify({
189
- projects: {},
190
- }),
191
- this.filePaths.metaJson,
192
- );
225
+ await plugins.smartfs
226
+ .file(this.filePaths.metaJson)
227
+ .encoding('utf8')
228
+ .write(
229
+ JSON.stringify({
230
+ projects: {},
231
+ }),
232
+ );
193
233
  logger.log(
194
234
  `success`,
195
235
  `created a new .meta.json in directory ${this.cwd}`,
196
236
  );
197
- await plugins.smartfile.memory.toFs(
198
- JSON.stringify({
199
- name: this.dirName,
200
- version: '1.0.0',
201
- }),
202
- this.filePaths.packageJson,
203
- );
237
+ await plugins.smartfs
238
+ .file(this.filePaths.packageJson)
239
+ .encoding('utf8')
240
+ .write(
241
+ JSON.stringify({
242
+ name: this.dirName,
243
+ version: '1.0.0',
244
+ }),
245
+ );
204
246
  logger.log(
205
247
  `success`,
206
248
  `created a new package.json in directory ${this.cwd}`,
@@ -264,9 +306,10 @@ export class Meta {
264
306
  await this.writeToDisk();
265
307
 
266
308
  logger.log('info', 'removing directory from cwd');
267
- await plugins.smartfile.fs.remove(
268
- plugins.path.join(paths.cwd, projectNameArg),
269
- );
309
+ await plugins.smartfs
310
+ .directory(plugins.path.join(paths.cwd, projectNameArg))
311
+ .recursive()
312
+ .delete();
270
313
  await this.updateLocalRepos();
271
314
  }
272
315
  }
@@ -0,0 +1,190 @@
1
+ import * as plugins from '../plugins.js';
2
+ import { DockerContainer } from './classes.dockercontainer.js';
3
+ import { logger } from '../gitzone.logging.js';
4
+
5
+ export interface IRegisteredProject {
6
+ projectPath: string;
7
+ projectName: string;
8
+ containers: {
9
+ mongo?: string;
10
+ minio?: string;
11
+ elasticsearch?: string;
12
+ };
13
+ ports: {
14
+ mongo?: number;
15
+ s3?: number;
16
+ s3Console?: number;
17
+ elasticsearch?: number;
18
+ };
19
+ enabledServices: string[];
20
+ lastActive: number;
21
+ }
22
+
23
+ export interface IGlobalRegistryData {
24
+ projects: { [projectPath: string]: IRegisteredProject };
25
+ }
26
+
27
+ export class GlobalRegistry {
28
+ private static instance: GlobalRegistry | null = null;
29
+ private kvStore: plugins.npmextra.KeyValueStore<IGlobalRegistryData>;
30
+ private docker: DockerContainer;
31
+
32
+ private constructor() {
33
+ this.kvStore = new plugins.npmextra.KeyValueStore({
34
+ typeArg: 'userHomeDir',
35
+ identityArg: 'gitzone-services',
36
+ });
37
+ this.docker = new DockerContainer();
38
+ }
39
+
40
+ /**
41
+ * Get the singleton instance
42
+ */
43
+ public static getInstance(): GlobalRegistry {
44
+ if (!GlobalRegistry.instance) {
45
+ GlobalRegistry.instance = new GlobalRegistry();
46
+ }
47
+ return GlobalRegistry.instance;
48
+ }
49
+
50
+ /**
51
+ * Register or update a project in the global registry
52
+ */
53
+ public async registerProject(data: Omit<IRegisteredProject, 'lastActive'>): Promise<void> {
54
+ const allData = await this.kvStore.readAll();
55
+ const projects = allData.projects || {};
56
+
57
+ projects[data.projectPath] = {
58
+ ...data,
59
+ lastActive: Date.now(),
60
+ };
61
+
62
+ await this.kvStore.writeKey('projects', projects);
63
+ }
64
+
65
+ /**
66
+ * Remove a project from the registry
67
+ */
68
+ public async unregisterProject(projectPath: string): Promise<void> {
69
+ const allData = await this.kvStore.readAll();
70
+ const projects = allData.projects || {};
71
+
72
+ if (projects[projectPath]) {
73
+ delete projects[projectPath];
74
+ await this.kvStore.writeKey('projects', projects);
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Update the lastActive timestamp for a project
80
+ */
81
+ public async touchProject(projectPath: string): Promise<void> {
82
+ const allData = await this.kvStore.readAll();
83
+ const projects = allData.projects || {};
84
+
85
+ if (projects[projectPath]) {
86
+ projects[projectPath].lastActive = Date.now();
87
+ await this.kvStore.writeKey('projects', projects);
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Get all registered projects
93
+ */
94
+ public async getAllProjects(): Promise<{ [path: string]: IRegisteredProject }> {
95
+ const allData = await this.kvStore.readAll();
96
+ return allData.projects || {};
97
+ }
98
+
99
+ /**
100
+ * Check if a project is registered
101
+ */
102
+ public async isRegistered(projectPath: string): Promise<boolean> {
103
+ const projects = await this.getAllProjects();
104
+ return !!projects[projectPath];
105
+ }
106
+
107
+ /**
108
+ * Get status of all containers across all registered projects
109
+ */
110
+ public async getGlobalStatus(): Promise<
111
+ Array<{
112
+ projectPath: string;
113
+ projectName: string;
114
+ containers: Array<{ name: string; status: string }>;
115
+ lastActive: number;
116
+ }>
117
+ > {
118
+ const projects = await this.getAllProjects();
119
+ const result: Array<{
120
+ projectPath: string;
121
+ projectName: string;
122
+ containers: Array<{ name: string; status: string }>;
123
+ lastActive: number;
124
+ }> = [];
125
+
126
+ for (const [path, project] of Object.entries(projects)) {
127
+ const containerStatuses: Array<{ name: string; status: string }> = [];
128
+
129
+ for (const containerName of Object.values(project.containers)) {
130
+ if (containerName) {
131
+ const status = await this.docker.getStatus(containerName);
132
+ containerStatuses.push({ name: containerName, status });
133
+ }
134
+ }
135
+
136
+ result.push({
137
+ projectPath: path,
138
+ projectName: project.projectName,
139
+ containers: containerStatuses,
140
+ lastActive: project.lastActive,
141
+ });
142
+ }
143
+
144
+ return result;
145
+ }
146
+
147
+ /**
148
+ * Stop all containers across all registered projects
149
+ */
150
+ public async stopAll(): Promise<{ stopped: string[]; failed: string[] }> {
151
+ const projects = await this.getAllProjects();
152
+ const stopped: string[] = [];
153
+ const failed: string[] = [];
154
+
155
+ for (const project of Object.values(projects)) {
156
+ for (const containerName of Object.values(project.containers)) {
157
+ if (containerName) {
158
+ const status = await this.docker.getStatus(containerName);
159
+ if (status === 'running') {
160
+ if (await this.docker.stop(containerName)) {
161
+ stopped.push(containerName);
162
+ } else {
163
+ failed.push(containerName);
164
+ }
165
+ }
166
+ }
167
+ }
168
+ }
169
+
170
+ return { stopped, failed };
171
+ }
172
+
173
+ /**
174
+ * Remove stale registry entries (projects that no longer exist on disk)
175
+ */
176
+ public async cleanup(): Promise<string[]> {
177
+ const projects = await this.getAllProjects();
178
+ const removed: string[] = [];
179
+
180
+ for (const projectPath of Object.keys(projects)) {
181
+ const exists = await plugins.smartfs.directory(projectPath).exists();
182
+ if (!exists) {
183
+ await this.unregisterProject(projectPath);
184
+ removed.push(projectPath);
185
+ }
186
+ }
187
+
188
+ return removed;
189
+ }
190
+ }