awc-zns-mtd 2.9.0 → 2.10.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 (38) hide show
  1. package/.github/workflows/ci.yml +148 -0
  2. package/.husky/pre-commit +2 -0
  3. package/.prettierignore +31 -0
  4. package/.prettierrc +13 -0
  5. package/IMPLEMENTATION_SUMMARY.md +410 -0
  6. package/PHASE_2_SUMMARY.md +289 -0
  7. package/README.md +114 -47
  8. package/SECURITY.md +58 -0
  9. package/eslint.config.js +70 -0
  10. package/jest.config.js +49 -0
  11. package/package.json +40 -14
  12. package/src/modules/custom-agents/cli/awc-agent.js +505 -372
  13. package/test/integration/cli/cli-commands.integration.test.js +101 -0
  14. package/test/setup.js +22 -0
  15. package/test/unit/commands/version.test.js +39 -0
  16. package/test/unit/config/config-manager.test.js +147 -0
  17. package/test/unit/utils/file-utils.test.js +177 -0
  18. package/test/unit/utils/validators.test.js +57 -0
  19. package/tools/cli/commands/init.js +556 -513
  20. package/tools/cli/commands/new-project.js +680 -659
  21. package/tools/cli/commands/validate.js +13 -13
  22. package/tools/cli/commands/version.js +5 -3
  23. package/tools/cli/utils/console-logger.js +39 -15
  24. package/tools/cli/utils/logger.js +176 -0
  25. package/tools/cli/utils/project-analyzer.js +33 -16
  26. package/tools/cli/utils/validators.js +144 -0
  27. package/tools/cli/utils/version.js +6 -2
  28. package/tools/config/config-manager.js +243 -0
  29. package/tools/version/changelog-manager.js +301 -288
  30. package/tools/version/update-checker.js +32 -32
  31. package/tools/version/version-bump.js +89 -90
  32. package/tools/version/version-manager.js +17 -7
  33. package/tsconfig.json +47 -0
  34. package/types/index.d.ts +206 -0
  35. package/tools/cli/commands/init-old.js +0 -147
  36. package/tools/cli/commands/new-project-broken.js +0 -1302
  37. package/tools/cli/commands/new-project-old.js +0 -1302
  38. package/tools/cli/commands/new-project.js.backup +0 -1302
@@ -1,288 +1,301 @@
1
- /**
2
- * Changelog Manager
3
- * Gestor de changelog automático para AWC ZNS-MTD
4
- */
5
-
6
- const fs = require('fs-extra');
7
- const path = require('path');
8
-
9
- class ChangelogManager {
10
- constructor(changelogPath = null) {
11
- this.changelogPath = changelogPath || path.join(__dirname, '../../CHANGELOG.md');
12
- this.changeTypes = {
13
- 'added': 'Añadido',
14
- 'changed': 'Cambiado',
15
- 'deprecated': 'Obsoleto',
16
- 'removed': 'Eliminado',
17
- 'fixed': 'Corregido',
18
- 'security': 'Seguridad'
19
- };
20
- }
21
-
22
- /**
23
- * Lee el contenido del changelog
24
- */
25
- async readChangelog() {
26
- if (!(await fs.pathExists(this.changelogPath))) {
27
- return null;
28
- }
29
-
30
- try {
31
- return await fs.readFile(this.changelogPath, 'utf8');
32
- } catch (error) {
33
- throw new Error(`Error al leer changelog: ${error.message}`);
34
- }
35
- }
36
-
37
- /**
38
- * Obtiene las notas de una versión específica
39
- */
40
- async getVersionNotes(version) {
41
- const content = await this.readChangelog();
42
-
43
- if (!content) return null;
44
-
45
- // Buscar sección de la versión
46
- const versionRegex = new RegExp(`## \\[${version}\\]([\\s\\S]*?)(?=## \\[|$)`, 'i');
47
- const match = content.match(versionRegex);
48
-
49
- if (!match) return null;
50
-
51
- return this.parseVersionSection(match[1]);
52
- }
53
-
54
- /**
55
- * Parsea una sección de versión del changelog
56
- * @private
57
- */
58
- parseVersionSection(section) {
59
- const parsed = {
60
- added: [],
61
- changed: [],
62
- deprecated: [],
63
- removed: [],
64
- fixed: [],
65
- security: []
66
- };
67
-
68
- // Buscar cada tipo de cambio
69
- Object.keys(this.changeTypes).forEach(type => {
70
- const typeRegex = new RegExp(`### ${this.changeTypes[type]}([\\s\\S]*?)(?=###|$)`, 'i');
71
- const match = section.match(typeRegex);
72
-
73
- if (match) {
74
- // Extraer items (líneas que empiezan con -)
75
- const items = match[1].match(/^- (.+)$/gm) || [];
76
- parsed[type] = items.map(item => item.replace(/^- /, '').trim());
77
- }
78
- });
79
-
80
- return parsed;
81
- }
82
-
83
- /**
84
- * Obtiene el último cambio registrado
85
- */
86
- async getLatestRelease() {
87
- const content = await this.readChangelog();
88
-
89
- if (!content) return null;
90
-
91
- // Buscar primera versión (ignorando Unreleased)
92
- const versionRegex = /## \[(\d+\.\d+\.\d+)\] - (\d{4}-\d{2}-\d{2})/;
93
- const match = content.match(versionRegex);
94
-
95
- if (!match) return null;
96
-
97
- const [, version, date] = match;
98
- const notes = await this.getVersionNotes(version);
99
-
100
- return {
101
- version,
102
- date,
103
- notes
104
- };
105
- }
106
-
107
- /**
108
- * Agrega una nueva versión al changelog
109
- */
110
- async addVersion(version, date, changes) {
111
- const content = await this.readChangelog();
112
-
113
- if (!content) {
114
- throw new Error('Changelog no encontrado');
115
- }
116
-
117
- // Generar sección de la nueva versión
118
- const versionSection = this.generateVersionSection(version, date, changes);
119
-
120
- // Insertar después de "## [Unreleased]"
121
- const unreleasedRegex = /(## \[Unreleased\][\s\S]*?)(?=## \[|$)/;
122
- const newContent = content.replace(unreleasedRegex, `$1\n${versionSection}\n`);
123
-
124
- await fs.writeFile(this.changelogPath, newContent, 'utf8');
125
- }
126
-
127
- /**
128
- * Genera sección de versión en formato markdown
129
- * @private
130
- */
131
- generateVersionSection(version, date, changes) {
132
- let section = `## [${version}] - ${date}\n\n`;
133
-
134
- // Agregar cada tipo de cambio si tiene items
135
- Object.keys(this.changeTypes).forEach(type => {
136
- if (changes[type] && changes[type].length > 0) {
137
- section += `### ${this.changeTypes[type]}\n\n`;
138
- changes[type].forEach(item => {
139
- section += `- ${item}\n`;
140
- });
141
- section += '\n';
142
- }
143
- });
144
-
145
- return section;
146
- }
147
-
148
- /**
149
- * Obtiene todos los cambios no liberados (Unreleased)
150
- */
151
- async getUnreleasedChanges() {
152
- const content = await this.readChangelog();
153
-
154
- if (!content) return null;
155
-
156
- const unreleasedRegex = /## \[Unreleased\]([\s\S]*?)(?=## \[|$)/;
157
- const match = content.match(unreleasedRegex);
158
-
159
- if (!match) return null;
160
-
161
- return this.parseVersionSection(match[1]);
162
- }
163
-
164
- /**
165
- * Verifica si hay cambios breaking en una versión
166
- */
167
- async hasBreakingChanges(version) {
168
- const notes = await this.getVersionNotes(version);
169
-
170
- if (!notes) return false;
171
-
172
- // Buscar indicadores de breaking changes
173
- const breakingIndicators = [
174
- 'BREAKING CHANGE',
175
- 'breaking change',
176
- 'incompatible',
177
- 'removed',
178
- 'deprecated'
179
- ];
180
-
181
- const allChanges = Object.values(notes).flat().join(' ').toLowerCase();
182
-
183
- return breakingIndicators.some(indicator =>
184
- allChanges.includes(indicator.toLowerCase())
185
- );
186
- }
187
-
188
- /**
189
- * Genera resumen de cambios entre dos versiones
190
- */
191
- async getChangesSummary(fromVersion, toVersion) {
192
- const content = await this.readChangelog();
193
-
194
- if (!content) return null;
195
-
196
- const summary = {
197
- from: fromVersion,
198
- to: toVersion,
199
- changes: {
200
- added: [],
201
- changed: [],
202
- deprecated: [],
203
- removed: [],
204
- fixed: [],
205
- security: []
206
- },
207
- breakingChanges: false
208
- };
209
-
210
- // Parsear todas las versiones entre fromVersion y toVersion
211
- const versionRegex = /## \[(\d+\.\d+\.\d+)\]/g;
212
- const versions = [];
213
- let match;
214
-
215
- while ((match = versionRegex.exec(content)) !== null) {
216
- versions.push(match[1]);
217
- }
218
-
219
- // Filtrar versiones en el rango
220
- const fromIndex = versions.indexOf(fromVersion);
221
- const toIndex = versions.indexOf(toVersion);
222
-
223
- if (fromIndex === -1 || toIndex === -1) {
224
- return null;
225
- }
226
-
227
- const versionsInRange = versions.slice(toIndex, fromIndex);
228
-
229
- // Agregar cambios de cada versión
230
- for (const version of versionsInRange) {
231
- const notes = await this.getVersionNotes(version);
232
-
233
- if (notes) {
234
- Object.keys(notes).forEach(type => {
235
- summary.changes[type].push(...notes[type]);
236
- });
237
-
238
- if (await this.hasBreakingChanges(version)) {
239
- summary.breakingChanges = true;
240
- }
241
- }
242
- }
243
-
244
- return summary;
245
- }
246
-
247
- /**
248
- * Valida formato del changelog
249
- */
250
- async validateChangelog() {
251
- const content = await this.readChangelog();
252
-
253
- if (!content) {
254
- return {
255
- valid: false,
256
- errors: ['Changelog no encontrado']
257
- };
258
- }
259
-
260
- const errors = [];
261
-
262
- // Verificar formato de versiones
263
- const versionRegex = /## \[\d+\.\d+\.\d+\] - \d{4}-\d{2}-\d{2}/g;
264
- if (!versionRegex.test(content)) {
265
- errors.push('Formato de versión inválido');
266
- }
267
-
268
- // Verificar sección Unreleased
269
- if (!content.includes('## [Unreleased]')) {
270
- errors.push('Falta sección [Unreleased]');
271
- }
272
-
273
- // Verificar tipos de cambio
274
- const requiredSections = Object.values(this.changeTypes);
275
- // No es obligatorio tener todas las secciones, solo verificar que las que existan sean válidas
276
-
277
- return {
278
- valid: errors.length === 0,
279
- errors
280
- };
281
- }
282
- }
283
-
284
- // Singleton instance
285
- const changelogManager = new ChangelogManager();
286
-
287
- module.exports = changelogManager;
288
- module.exports.ChangelogManager = ChangelogManager;
1
+ /**
2
+ * Changelog Manager
3
+ * Gestor de changelog automático para AWC ZNS-MTD
4
+ */
5
+
6
+ const fs = require('fs-extra');
7
+ const path = require('path');
8
+
9
+ class ChangelogManager {
10
+ constructor(changelogPath = null) {
11
+ this.changelogPath = changelogPath || path.join(__dirname, '../../CHANGELOG.md');
12
+ this.changeTypes = {
13
+ added: 'Añadido',
14
+ changed: 'Cambiado',
15
+ deprecated: 'Obsoleto',
16
+ removed: 'Eliminado',
17
+ fixed: 'Corregido',
18
+ security: 'Seguridad'
19
+ };
20
+ }
21
+
22
+ /**
23
+ * Lee el contenido del changelog
24
+ */
25
+ async readChangelog() {
26
+ if (!(await fs.pathExists(this.changelogPath))) {
27
+ return null;
28
+ }
29
+
30
+ try {
31
+ return await fs.readFile(this.changelogPath, 'utf8');
32
+ } catch (error) {
33
+ throw new Error(`Error al leer changelog: ${error.message}`);
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Obtiene las notas de una versión específica
39
+ */
40
+ async getVersionNotes(version) {
41
+ const content = await this.readChangelog();
42
+
43
+ if (!content) {
44
+ return null;
45
+ }
46
+
47
+ // Buscar sección de la versión
48
+ const versionRegex = new RegExp(`## \\[${version}\\]([\\s\\S]*?)(?=## \\[|$)`, 'i');
49
+ const match = content.match(versionRegex);
50
+
51
+ if (!match) {
52
+ return null;
53
+ }
54
+
55
+ return this.parseVersionSection(match[1]);
56
+ }
57
+
58
+ /**
59
+ * Parsea una sección de versión del changelog
60
+ * @private
61
+ */
62
+ parseVersionSection(section) {
63
+ const parsed = {
64
+ added: [],
65
+ changed: [],
66
+ deprecated: [],
67
+ removed: [],
68
+ fixed: [],
69
+ security: []
70
+ };
71
+
72
+ // Buscar cada tipo de cambio
73
+ Object.keys(this.changeTypes).forEach((type) => {
74
+ const typeRegex = new RegExp(`### ${this.changeTypes[type]}([\\s\\S]*?)(?=###|$)`, 'i');
75
+ const match = section.match(typeRegex);
76
+
77
+ if (match) {
78
+ // Extraer items (líneas que empiezan con -)
79
+ const items = match[1].match(/^- (.+)$/gm) || [];
80
+ parsed[type] = items.map((item) => item.replace(/^- /, '').trim());
81
+ }
82
+ });
83
+
84
+ return parsed;
85
+ }
86
+
87
+ /**
88
+ * Obtiene el último cambio registrado
89
+ */
90
+ async getLatestRelease() {
91
+ const content = await this.readChangelog();
92
+
93
+ if (!content) {
94
+ return null;
95
+ }
96
+
97
+ // Buscar primera versión (ignorando Unreleased)
98
+ const versionRegex = /## \[(\d+\.\d+\.\d+)\] - (\d{4}-\d{2}-\d{2})/;
99
+ const match = content.match(versionRegex);
100
+
101
+ if (!match) {
102
+ return null;
103
+ }
104
+
105
+ const [, version, date] = match;
106
+ const notes = await this.getVersionNotes(version);
107
+
108
+ return {
109
+ version,
110
+ date,
111
+ notes
112
+ };
113
+ }
114
+
115
+ /**
116
+ * Agrega una nueva versión al changelog
117
+ */
118
+ async addVersion(version, date, changes) {
119
+ const content = await this.readChangelog();
120
+
121
+ if (!content) {
122
+ throw new Error('Changelog no encontrado');
123
+ }
124
+
125
+ // Generar sección de la nueva versión
126
+ const versionSection = this.generateVersionSection(version, date, changes);
127
+
128
+ // Insertar después de "## [Unreleased]"
129
+ const unreleasedRegex = /(## \[Unreleased\][\s\S]*?)(?=## \[|$)/;
130
+ const newContent = content.replace(unreleasedRegex, `$1\n${versionSection}\n`);
131
+
132
+ await fs.writeFile(this.changelogPath, newContent, 'utf8');
133
+ }
134
+
135
+ /**
136
+ * Genera sección de versión en formato markdown
137
+ * @private
138
+ */
139
+ generateVersionSection(version, date, changes) {
140
+ let section = `## [${version}] - ${date}\n\n`;
141
+
142
+ // Agregar cada tipo de cambio si tiene items
143
+ Object.keys(this.changeTypes).forEach((type) => {
144
+ if (changes[type] && changes[type].length > 0) {
145
+ section += `### ${this.changeTypes[type]}\n\n`;
146
+ changes[type].forEach((item) => {
147
+ section += `- ${item}\n`;
148
+ });
149
+ section += '\n';
150
+ }
151
+ });
152
+
153
+ return section;
154
+ }
155
+
156
+ /**
157
+ * Obtiene todos los cambios no liberados (Unreleased)
158
+ */
159
+ async getUnreleasedChanges() {
160
+ const content = await this.readChangelog();
161
+
162
+ if (!content) {
163
+ return null;
164
+ }
165
+
166
+ const unreleasedRegex = /## \[Unreleased\]([\s\S]*?)(?=## \[|$)/;
167
+ const match = content.match(unreleasedRegex);
168
+
169
+ if (!match) {
170
+ return null;
171
+ }
172
+
173
+ return this.parseVersionSection(match[1]);
174
+ }
175
+
176
+ /**
177
+ * Verifica si hay cambios breaking en una versión
178
+ */
179
+ async hasBreakingChanges(version) {
180
+ const notes = await this.getVersionNotes(version);
181
+
182
+ if (!notes) {
183
+ return false;
184
+ }
185
+
186
+ // Buscar indicadores de breaking changes
187
+ const breakingIndicators = [
188
+ 'BREAKING CHANGE',
189
+ 'breaking change',
190
+ 'incompatible',
191
+ 'removed',
192
+ 'deprecated'
193
+ ];
194
+
195
+ const allChanges = Object.values(notes).flat().join(' ').toLowerCase();
196
+
197
+ return breakingIndicators.some((indicator) => allChanges.includes(indicator.toLowerCase()));
198
+ }
199
+
200
+ /**
201
+ * Genera resumen de cambios entre dos versiones
202
+ */
203
+ async getChangesSummary(fromVersion, toVersion) {
204
+ const content = await this.readChangelog();
205
+
206
+ if (!content) {
207
+ return null;
208
+ }
209
+
210
+ const summary = {
211
+ from: fromVersion,
212
+ to: toVersion,
213
+ changes: {
214
+ added: [],
215
+ changed: [],
216
+ deprecated: [],
217
+ removed: [],
218
+ fixed: [],
219
+ security: []
220
+ },
221
+ breakingChanges: false
222
+ };
223
+
224
+ // Parsear todas las versiones entre fromVersion y toVersion
225
+ const versionRegex = /## \[(\d+\.\d+\.\d+)\]/g;
226
+ const versions = [];
227
+ let match;
228
+
229
+ while ((match = versionRegex.exec(content)) !== null) {
230
+ versions.push(match[1]);
231
+ }
232
+
233
+ // Filtrar versiones en el rango
234
+ const fromIndex = versions.indexOf(fromVersion);
235
+ const toIndex = versions.indexOf(toVersion);
236
+
237
+ if (fromIndex === -1 || toIndex === -1) {
238
+ return null;
239
+ }
240
+
241
+ const versionsInRange = versions.slice(toIndex, fromIndex);
242
+
243
+ // Agregar cambios de cada versión
244
+ for (const version of versionsInRange) {
245
+ const notes = await this.getVersionNotes(version);
246
+
247
+ if (notes) {
248
+ Object.keys(notes).forEach((type) => {
249
+ summary.changes[type].push(...notes[type]);
250
+ });
251
+
252
+ if (await this.hasBreakingChanges(version)) {
253
+ summary.breakingChanges = true;
254
+ }
255
+ }
256
+ }
257
+
258
+ return summary;
259
+ }
260
+
261
+ /**
262
+ * Valida formato del changelog
263
+ */
264
+ async validateChangelog() {
265
+ const content = await this.readChangelog();
266
+
267
+ if (!content) {
268
+ return {
269
+ valid: false,
270
+ errors: ['Changelog no encontrado']
271
+ };
272
+ }
273
+
274
+ const errors = [];
275
+
276
+ // Verificar formato de versiones
277
+ const versionRegex = /## \[\d+\.\d+\.\d+\] - \d{4}-\d{2}-\d{2}/g;
278
+ if (!versionRegex.test(content)) {
279
+ errors.push('Formato de versión inválido');
280
+ }
281
+
282
+ // Verificar sección Unreleased
283
+ if (!content.includes('## [Unreleased]')) {
284
+ errors.push('Falta sección [Unreleased]');
285
+ }
286
+
287
+ // Verificar tipos de cambio
288
+ // No es obligatorio tener todas las secciones, solo verificar que las que existan sean válidas
289
+
290
+ return {
291
+ valid: errors.length === 0,
292
+ errors
293
+ };
294
+ }
295
+ }
296
+
297
+ // Singleton instance
298
+ const changelogManager = new ChangelogManager();
299
+
300
+ module.exports = changelogManager;
301
+ module.exports.ChangelogManager = ChangelogManager;