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.
- package/.github/workflows/ci.yml +148 -0
- package/.husky/pre-commit +2 -0
- package/.prettierignore +31 -0
- package/.prettierrc +13 -0
- package/IMPLEMENTATION_SUMMARY.md +410 -0
- package/PHASE_2_SUMMARY.md +289 -0
- package/README.md +114 -47
- package/SECURITY.md +58 -0
- package/eslint.config.js +70 -0
- package/jest.config.js +49 -0
- package/package.json +40 -14
- package/src/modules/custom-agents/cli/awc-agent.js +505 -372
- package/test/integration/cli/cli-commands.integration.test.js +101 -0
- package/test/setup.js +22 -0
- package/test/unit/commands/version.test.js +39 -0
- package/test/unit/config/config-manager.test.js +147 -0
- package/test/unit/utils/file-utils.test.js +177 -0
- package/test/unit/utils/validators.test.js +57 -0
- package/tools/cli/commands/init.js +556 -513
- package/tools/cli/commands/new-project.js +680 -659
- package/tools/cli/commands/validate.js +13 -13
- package/tools/cli/commands/version.js +5 -3
- package/tools/cli/utils/console-logger.js +39 -15
- package/tools/cli/utils/logger.js +176 -0
- package/tools/cli/utils/project-analyzer.js +33 -16
- package/tools/cli/utils/validators.js +144 -0
- package/tools/cli/utils/version.js +6 -2
- package/tools/config/config-manager.js +243 -0
- package/tools/version/changelog-manager.js +301 -288
- package/tools/version/update-checker.js +32 -32
- package/tools/version/version-bump.js +89 -90
- package/tools/version/version-manager.js +17 -7
- package/tsconfig.json +47 -0
- package/types/index.d.ts +206 -0
- package/tools/cli/commands/init-old.js +0 -147
- package/tools/cli/commands/new-project-broken.js +0 -1302
- package/tools/cli/commands/new-project-old.js +0 -1302
- 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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
const
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
errors
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
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;
|