Documentación automática con IA
La documentación es una parte esencial del desarrollo de librerías TypeScript, pero a menudo es vista como una tarea tediosa que consume tiempo valioso que podría destinarse al desarrollo de características. Las herramientas de IA pueden transformar este proceso, ayudándote a generar documentación de alta calidad con menos esfuerzo, manteniendo actualizada la documentación y creando ejemplos relevantes para los usuarios de tu librería. Este documento explorará cómo integrar la IA en tu proceso de documentación para mejorar la calidad y eficiencia.
Generación de documentación técnica
Uno de los usos más poderosos de la IA en el desarrollo de librerías es la generación automática de documentación técnica a partir del código fuente.
Documentación de API con JSDoc y IA
La combinación de JSDoc con IA te permite generar documentación detallada y precisa para tu API.
Generación de comentarios JSDoc
Para obtener el máximo beneficio, sigue estos pasos:
- Identifica las partes de tu código que necesitan documentación (funciones, clases, interfaces, etc.)
- Utiliza un LLM para generar comentarios JSDoc completos
- Revisa y refina los comentarios generados
- Integra los comentarios en tu código
Ejemplo de prompt para generar documentación JSDoc:
Genera documentación JSDoc completa para la siguiente clase TypeScript:
```typescript
export class DateFormatter {
private format: string;
private locale: string;
constructor(format = 'DD/MM/YYYY', locale = 'es-ES') {
this.format = format;
this.locale = locale;
}
formatDate(date: Date): string {
// Implementación básica
const day = date.getDate().toString().padStart(2, '0');
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const year = date.getFullYear();
return this.format
.replace('DD', day)
.replace('MM', month)
.replace('YYYY', year);
}
parseDate(dateString: string): Date | null {
try {
const parts = dateString.split('/');
if (parts.length !== 3) return null;
const day = parseInt(parts[0], 10);
const month = parseInt(parts[1], 10) - 1;
const year = parseInt(parts[2], 10);
const date = new Date(year, month, day);
return date;
} catch (error) {
return null;
}
}
setFormat(format: string): void {
this.format = format;
}
getFormat(): string {
return this.format;
}
setLocale(locale: string): void {
this.locale = locale;
}
getLocale(): string {
return this.locale;
}
}
```
Incluye:
1. Descripción de la clase
2. Parámetros del constructor con valores predeterminados
3. Descripción detallada de cada método
4. Tipos de parámetros y valores de retorno
5. Ejemplos de uso para cada método
6. Cualquier advertencia o caso especial que deba considerarse
Ejemplo de documentación JSDoc generada
La IA podría generar documentación como esta:
/**
* Clase para formatear y analizar fechas con formato personalizable.
* Proporciona métodos para convertir objetos Date a strings y viceversa.
*/
export class DateFormatter {
/** Formato de fecha (por defecto: 'DD/MM/YYYY') */
private format: string;
/** Configuración regional (por defecto: 'es-ES') */
private locale: string;
/**
* Crea una nueva instancia de DateFormatter.
*
* @param {string} format - Patrón de formato para fechas.
* Utiliza 'DD' para día, 'MM' para mes y 'YYYY' para año.
* Por defecto: 'DD/MM/YYYY'
* @param {string} locale - Código de localización.
* Por defecto: 'es-ES'
*
* @example
* // Crear formateador con configuración predeterminada
* const formatter = new DateFormatter();
*
* @example
* // Crear formateador con formato personalizado
* const formatter = new DateFormatter('YYYY-MM-DD', 'en-US');
*/
constructor(format = "DD/MM/YYYY", locale = "es-ES") {
this.format = format;
this.locale = locale;
}
/**
* Convierte un objeto Date a string según el formato configurado.
*
* @param {Date} date - La fecha a formatear
* @returns {string} Fecha formateada como string
*
* @example
* const formatter = new DateFormatter('DD/MM/YYYY');
* const dateStr = formatter.formatDate(new Date(2025, 0, 15));
* // Resultado: '15/01/2025'
*/
formatDate(date: Date): string {
// Implementación básica
const day = date.getDate().toString().padStart(2, "0");
const month = (date.getMonth() + 1).toString().padStart(2, "0");
const year = date.getFullYear();
return this.format.replace("DD", day).replace("MM", month).replace("YYYY", year);
}
/**
* Analiza un string de fecha y lo convierte a objeto Date.
* Actualmente solo soporta formato 'DD/MM/YYYY'.
*
* @param {string} dateString - String de fecha a analizar
* @returns {Date|null} Objeto Date si el análisis es exitoso, null si falla
*
* @example
* const formatter = new DateFormatter();
* const date = formatter.parseDate('15/01/2025');
* // Resultado: Date(2025-01-15)
*
* @example
* const invalidDate = formatter.parseDate('2025-01-15');
* // Resultado: null (formato incorrecto)
*/
parseDate(dateString: string): Date | null {
try {
const parts = dateString.split("/");
if (parts.length !== 3) return null;
const day = parseInt(parts[0], 10);
const month = parseInt(parts[1], 10) - 1;
const year = parseInt(parts[2], 10);
const date = new Date(year, month, day);
return date;
} catch (error) {
return null;
}
}
/**
* Establece un nuevo formato para la fecha.
*
* @param {string} format - Nuevo formato a utilizar
*
* @example
* const formatter = new DateFormatter();
* formatter.setFormat('YYYY-MM-DD');
*/
setFormat(format: string): void {
this.format = format;
}
/**
* Obtiene el formato actual.
*
* @returns {string} El formato actual
*
* @example
* const formatter = new DateFormatter('YYYY/MM/DD');
* const format = formatter.getFormat();
* // Resultado: 'YYYY/MM/DD'
*/
getFormat(): string {
return this.format;
}
/**
* Establece una nueva configuración regional.
*
* @param {string} locale - Nueva configuración regional
*
* @example
* const formatter = new DateFormatter();
* formatter.setLocale('en-US');
*/
setLocale(locale: string): void {
this.locale = locale;
}
/**
* Obtiene la configuración regional actual.
*
* @returns {string} La configuración regional actual
*
* @example
* const formatter = new DateFormatter();
* const locale = formatter.getLocale();
* // Resultado: 'es-ES'
*/
getLocale(): string {
return this.locale;
}
}
Generación de documentación TypeDoc
TypeDoc es una herramienta de generación de documentación para proyectos TypeScript. Puedes usar la IA para mejorar la documentación generada por TypeDoc.
Configuración de TypeDoc
Para configurar TypeDoc en tu proyecto:
- Instala TypeDoc:
npm install --save-dev typedoc
- Crea un archivo de configuración
typedoc.json
:
{
"entryPoints": ["src/index.ts"],
"out": "docs/api",
"excludePrivate": true,
"excludeProtected": true,
"excludeExternals": true,
"theme": "default",
"readme": "none"
}
- Añade un script en tu
package.json
:
{
"scripts": {
"docs:api": "typedoc"
}
}
Integración con VitePress
Para integrar la documentación de API generada con TypeDoc en tu documentación VitePress:
- Configura TypeDoc para generar la salida en un directorio dentro de tu documentación VitePress:
{
"out": "docs/public/api"
}
- Añade un enlace a la documentación de API en tu configuración de VitePress:
// docs/.vitepress/config.ts
export default defineConfig({
// ...
themeConfig: {
// ...
sidebar: [
// ...
{
text: "API Reference",
link: "/api/",
items: [{ text: "API Documentation", link: "/api/" }],
},
],
},
});
- Crea un archivo
docs/api/index.md
que enlace a la documentación generada:
# API Reference
La documentación completa de la API está disponible [aquí](/api/index.html).
Actualización de changelog
Mantener un changelog actualizado es importante para que los usuarios puedan seguir la evolución de tu librería. La IA puede ayudarte a generar entradas de changelog precisas y detalladas.
Generación automática con semantic-release
semantic-release puede generar automáticamente un changelog basado en tus mensajes de commit. Para mejorarlo con IA:
- Configura semantic-release para generar un changelog:
// release.config.js
export default {
branches: ["main"],
plugins: [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"@semantic-release/npm",
[
"@semantic-release/git",
{
message: "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}",
},
],
"@semantic-release/github",
],
};
- Utiliza la IA para generar mensajes de commit que sigan la convención de Conventional Commits:
Ejemplo de prompt para generar mensajes de commit:
He realizado los siguientes cambios en mi librería:
1. Añadido un nuevo método `formatToISO` a la clase DateFormatter
2. Corregido un bug en el método parseDate que no manejaba correctamente años bisiestos
3. Mejorado el rendimiento de la validación de emails
Genera mensajes de commit siguiendo el formato de Conventional Commits para cada uno de estos cambios.
Respuesta esperada:
1. feat(date): añadir método formatToISO a DateFormatter
Añade un nuevo método que permite formatear fechas en formato ISO 8601 (YYYY-MM-DDTHH:mm:ss.sssZ)
2. fix(date): corregir manejo de años bisiestos en parseDate
Soluciona un problema que causaba que el método parseDate no validara correctamente las fechas en años bisiestos
3. perf(validation): mejorar rendimiento en validación de emails
Optimiza el algoritmo de validación de emails para reducir el tiempo de procesamiento en un 30%
Enriquecimiento de changelog manual
Para changelogs manuales, la IA puede ayudarte a enriquecer las entradas con más detalles:
Ejemplo de prompt para enriquecimiento de changelog:
Enriquece las siguientes entradas del changelog con más detalles sobre los cambios, posibles impactos y ejemplos de uso cuando sea relevante:
## [1.2.0] - 2025-03-15
### Añadido
- Método formatToISO en DateFormatter
### Corregido
- Bug con años bisiestos en parseDate
### Mejorado
- Rendimiento de validación de emails
Respuesta esperada:
## [1.2.0] - 2025-03-15
### Añadido
- **Método formatToISO en DateFormatter**: Ahora puedes convertir objetos Date a strings en formato ISO 8601 estándar, facilitando la interoperabilidad con APIs y bases de datos.
```typescript
const formatter = new DateFormatter();
const isoDate = formatter.formatToISO(new Date());
// Resultado: '2025-03-15T14:30:45.123Z'
```
### Corregido
- **Bug con años bisiestos en parseDate**: Solucionado un problema crítico que causaba que fechas como '29/02/2024' fueran rechazadas incorrectamente o generaran objetos Date inválidos. Ahora todas las fechas de años bisiestos son manejadas correctamente.
### Mejorado
- **Rendimiento de validación de emails**: Optimizado el algoritmo de validación de emails, reduciendo el tiempo de procesamiento en un 30%. Esta mejora es especialmente notable al validar lotes grandes de direcciones de email o en aplicaciones con restricciones de rendimiento.
Generación de ejemplos
Los ejemplos de código son una parte crucial de la documentación de una librería, ya que muestran cómo utilizar las diferentes funcionalidades en contextos reales. La IA puede ayudarte a generar ejemplos precisos y variados.
Ejemplos de uso básico
Para generar ejemplos básicos de uso de tu librería:
Ejemplo de prompt:
Genera ejemplos básicos de uso para la siguiente clase TypeScript:
```typescript
export class StringValidator {
private validations: Array<(value: string) => string | null> = [];
public required(message = 'Field is required'): this {
this.validations.push(value => {
if (!value && value !== '') return message;
return null;
});
return this;
}
public minLength(length: number, message?: string): this {
this.validations.push(value => {
if (value.length < length) {
return message || `Must be at least ${length} characters`;
}
return null;
});
return this;
}
public email(message = 'Must be a valid email'): this {
this.validations.push(value => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(value)) return message;
return null;
});
return this;
}
public validate(value: string): { valid: boolean; errors: string[] } {
const errors: string[] = [];
for (const validation of this.validations) {
const error = validation(value);
if (error) errors.push(error);
}
return {
valid: errors.length === 0,
errors
};
}
}
```
Los ejemplos deben mostrar:
1. Creación de un validador simple
2. Encadenamiento de validaciones
3. Validación de diferentes tipos de datos
4. Manejo de los resultados de validación
Respuesta esperada:
// 1. Ejemplo básico de validación de campos requeridos
import { StringValidator } from "mi-libreria";
const nombreValidator = new StringValidator().required();
const resultado = nombreValidator.validate("John");
console.log(resultado.valid); // true
console.log(resultado.errors); // []
// Validando un string vacío
const resultadoVacio = nombreValidator.validate("");
console.log(resultadoVacio.valid); // false
console.log(resultadoVacio.errors); // ['Field is required']
// 2. Encadenamiento de validaciones
const passwordValidator = new StringValidator()
.required("La contraseña es obligatoria")
.minLength(8, "La contraseña debe tener al menos 8 caracteres");
// Contraseña válida
const passResultadoValido = passwordValidator.validate("seguridad123");
console.log(passResultadoValido.valid); // true
// Contraseña demasiado corta
const passResultadoCorto = passwordValidator.validate("123");
console.log(passResultadoCorto.valid); // false
console.log(passResultadoCorto.errors); // ['La contraseña debe tener al menos 8 caracteres']
// 3. Validación de email
const emailValidator = new StringValidator()
.required("El email es obligatorio")
.email("Por favor, introduce un email válido");
// Email válido
console.log(emailValidator.validate("usuario@ejemplo.com").valid); // true
// Email inválido
const emailInvalido = emailValidator.validate("no-es-un-email");
console.log(emailInvalido.valid); // false
console.log(emailInvalido.errors); // ['Por favor, introduce un email válido']
// 4. Manejo de múltiples errores
const formValidator = new StringValidator()
.required("El campo es obligatorio")
.minLength(5, "Mínimo 5 caracteres")
.email("Debe ser un email válido");
// Todos los errores a la vez
const todosErrores = formValidator.validate("abc");
console.log(todosErrores.valid); // false
console.log(todosErrores.errors);
// [
// 'Mínimo 5 caracteres',
// 'Debe ser un email válido'
// ]
// 5. Mensajes de error personalizados
const customValidator = new StringValidator()
.required("Por favor, completa este campo")
.minLength(10, "Tu respuesta es demasiado corta, necesitamos más detalles");
const customResult = customValidator.validate("Corto");
console.log(customResult.errors[0]); // 'Tu respuesta es demasiado corta, necesitamos más detalles'
Ejemplos avanzados y casos de uso
Para casos de uso más avanzados, la IA puede generar ejemplos que muestren cómo integrar tu librería en escenarios reales:
Ejemplo de prompt:
Genera ejemplos avanzados que muestren cómo integrar el StringValidator en un formulario de registro de usuario con validación de varios campos y mensajes de error personalizados. Incluye también un ejemplo de cómo extender la funcionalidad con un validador personalizado.
Respuesta esperada:
import { StringValidator } from "mi-libreria";
// Ejemplo de formulario de registro con validación completa
class RegistroUsuarioForm {
private validators: Record<string, StringValidator> = {};
private formData: Record<string, string> = {};
private formErrors: Record<string, string[]> = {};
constructor() {
// Configurar validadores para cada campo
this.validators = {
username: new StringValidator()
.required("El nombre de usuario es obligatorio")
.minLength(3, "El nombre de usuario debe tener al menos 3 caracteres"),
email: new StringValidator()
.required("El email es obligatorio")
.email("Por favor, introduce un email válido"),
password: new StringValidator()
.required("La contraseña es obligatoria")
.minLength(8, "La contraseña debe tener al menos 8 caracteres")
// Validador personalizado para requerir al menos un número
.custom((value) => {
if (!/\d/.test(value)) {
return "La contraseña debe contener al menos un número";
}
return null;
}),
confirmPassword: new StringValidator()
.required("Por favor, confirma tu contraseña")
// Validador personalizado para comparar con otro campo
.custom((value) => {
if (value !== this.formData.password) {
return "Las contraseñas no coinciden";
}
return null;
}),
};
// Inicializar datos del formulario
this.resetForm();
}
// Añadir método personalizado al prototipo de StringValidator
private extendStringValidator() {
StringValidator.prototype.custom = function (
validationFn: (value: string) => string | null,
): StringValidator {
this.validations.push(validationFn);
return this;
};
}
updateField(fieldName: string, value: string): void {
this.formData[fieldName] = value;
this.validateField(fieldName);
}
validateField(fieldName: string): boolean {
if (!this.validators[fieldName]) {
return true;
}
const result = this.validators[fieldName].validate(this.formData[fieldName]);
this.formErrors[fieldName] = result.errors;
return result.valid;
}
validateForm(): boolean {
let isValid = true;
// Validar todos los campos
Object.keys(this.validators).forEach((fieldName) => {
const fieldValid = this.validateField(fieldName);
isValid = isValid && fieldValid;
});
return isValid;
}
getErrors(): Record<string, string[]> {
return this.formErrors;
}
getFormData(): Record<string, string> {
return { ...this.formData };
}
resetForm(): void {
this.formData = {
username: "",
email: "",
password: "",
confirmPassword: "",
};
this.formErrors = {
username: [],
email: [],
password: [],
confirmPassword: [],
};
}
async submitForm(): Promise<boolean> {
if (!this.validateForm()) {
console.error("El formulario contiene errores:", this.formErrors);
return false;
}
try {
// Aquí iría la lógica para enviar los datos al servidor
console.log("Enviando datos:", this.formData);
await fakeApiCall(this.formData);
console.log("Usuario registrado correctamente");
this.resetForm();
return true;
} catch (error) {
console.error("Error al registrar usuario:", error);
return false;
}
}
}
// Función simulada para representar una llamada API
function fakeApiCall(data: Record<string, string>): Promise<void> {
return new Promise((resolve) => {
setTimeout(() => {
console.log("API: Datos recibidos", data);
resolve();
}, 1000);
});
}
// Ejemplo de uso
const registerForm = new RegistroUsuarioForm();
// Simulación de entradas del usuario
registerForm.updateField("username", "johndoe");
registerForm.updateField("email", "john@example.com");
registerForm.updateField("password", "password"); // Faltaría un número
registerForm.updateField("confirmPassword", "password123"); // No coincide
console.log("¿Formulario válido?", registerForm.validateForm());
console.log("Errores:", registerForm.getErrors());
// Corregimos los errores
registerForm.updateField("password", "password123");
registerForm.updateField("confirmPassword", "password123");
console.log("¿Formulario válido ahora?", registerForm.validateForm());
console.log("Errores:", registerForm.getErrors());
// Enviar formulario
registerForm.submitForm().then((success) => {
if (success) {
console.log("¡Registro completado con éxito!");
}
});
Ejemplos para README
El README es la primera parte de la documentación que verán los usuarios de tu librería. La IA puede ayudarte a generar ejemplos concisos pero informativos para incluir en tu README:
Ejemplo de prompt:
Genera un ejemplo breve pero completo para la sección "Uso rápido" del README de una librería de validación de formularios basada en la clase StringValidator. El ejemplo debe ser conciso pero mostrar las principales características.
Respuesta esperada:
## Uso rápido
```typescript
import { StringValidator } from "my-validator-lib";
// Crear validadores para diferentes campos
const emailValidator = new StringValidator()
.required("El email es obligatorio")
.email("Formato de email inválido");
const passwordValidator = new StringValidator()
.required()
.minLength(8, "La contraseña debe tener al menos 8 caracteres");
// Validar entradas de usuario
const emailResult = emailValidator.validate(userEmail);
if (!emailResult.valid) {
// Mostrar errores al usuario
displayErrors(emailResult.errors);
}
// Encadenamiento de validaciones
const formValidator = new StringValidator()
.required("Todos los campos son obligatorios")
.minLength(3, "Demasiado corto")
.email("Debe ser un email válido");
const result = formValidator.validate("user@example.com");
console.log(result.valid); // true
```
Para más ejemplos y documentación detallada, consulta nuestra [guía completa](docs/validation-guide.md).
VitePress y IA
VitePress es una herramienta excelente para crear documentación para tu librería TypeScript. La IA puede ayudarte a mejorar y mantener esta documentación.
Generación de contenido para VitePress
Puedes utilizar la IA para generar contenido estructurado para tus páginas de documentación en VitePress:
Ejemplo de prompt:
Genera una página de inicio para la documentación VitePress de una librería de validación de formularios. La página debe incluir:
1. Un eslogan/descripción breve
2. Características principales (validación tipada, mensajes personalizables, API fluida)
3. Un ejemplo de código simple
4. Un CTA para comenzar
Respuesta esperada:
---
layout: home
hero:
name: "FormValidator"
text: "Validación de formularios simple y tipada"
tagline: Maneja fácilmente la validación de datos de usuario con TypeScript
actions:
- theme: brand
text: Comenzar
link: /guide/getting-started
- theme: alt
text: Ver en GitHub
link: https://github.com/usuario/form-validator
features:
- icon: 🛡️
title: Validación Tipada
details: Aprovecha TypeScript para validación con tipos estáticos, detectando errores en tiempo de compilación.
- icon: 🔄
title: API Fluida
details: Encadena validadores para crear reglas complejas de manera intuitiva y legible.
- icon: 💬
title: Mensajes Personalizables
details: Define mensajes de error específicos para cada validación y cada idioma.
- icon: 🚀
title: Ligero y Rápido
details: Sin dependencias externas y optimizado para rendimiento, incluso con grandes conjuntos de datos.
---
## Validación simple y potente
```typescript
import { createValidator } from "form-validator";
// Define tus validadores
const validator = createValidator({
name: (v) => v.required().minLength(2),
email: (v) => v.required().email(),
age: (v) => v.number().min(18).max(120),
});
// Valida los datos
const result = validator.validate({
name: "John",
email: "john@example.com",
age: 25,
});
if (result.valid) {
saveUser(result.data); // Datos validados y tipados
} else {
showErrors(result.errors);
}
```
Actualización de documentación existente
La IA también puede ayudarte a actualizar la documentación existente cuando añades nuevas características o realizas cambios en tu librería:
Ejemplo de prompt:
He añadido un nuevo validador `pattern` a mi clase StringValidator que permite validar strings usando expresiones regulares. El método tiene esta firma:
```typescript
public pattern(regex: RegExp, message = 'Invalid format'): this
```
Actualiza la siguiente sección de mi documentación VitePress para incluir este nuevo método:
```markdown
## Validadores disponibles
### required
Verifica que el string no esté vacío.
```typescript
const validator = new StringValidator().required('Campo obligatorio');
```
### minLength
Verifica que el string tenga una longitud mínima.
```typescript
const validator = new StringValidator().minLength(8, 'Muy corto');
```
### email
Verifica que el string sea un email válido.
```typescript
const validator = new StringValidator().email('Email inválido');
```
```
Respuesta esperada:
## Validadores disponibles
### required
Verifica que el string no esté vacío.
```typescript
const validator = new StringValidator().required("Campo obligatorio");
```
### minLength
Verifica que el string tenga una longitud mínima.
```typescript
const validator = new StringValidator().minLength(8, "Muy corto");
```
### email
Verifica que el string sea un email válido.
```typescript
const validator = new StringValidator().email("Email inválido");
```
### pattern
Verifica que el string coincida con un patrón de expresión regular.
```typescript
// Validar un código postal español
const validator = new StringValidator().pattern(/^[0-9]{5}$/, "Código postal inválido");
// Validar un nombre de usuario (letras, números y guiones bajos)
const usernameValidator = new StringValidator().pattern(
/^[a-zA-Z0-9_]+$/,
"Solo letras, números y guiones bajos",
);
```
Automatización del flujo de trabajo de documentación
Para hacer el proceso de documentación más eficiente, puedes automatizar varias partes del proceso utilizando scripts y herramientas de IA.
Scripts para generación de documentación
Puedes crear scripts que utilicen la API de OpenAI u otros proveedores para generar documentación automáticamente:
// scripts/generate-docs.ts
import fs from "fs";
import path from "path";
import { OpenAI } from "openai";
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
async function generateJSDocForFile(filePath: string): Promise<string> {
const sourceCode = fs.readFileSync(filePath, "utf8");
const fileName = path.basename(filePath);
const response = await openai.chat.completions.create({
model: "gpt-4",
messages: [
{
role: "system",
content: "Genera documentación JSDoc completa para el siguiente código TypeScript.",
},
{
role: "user",
content: `Archivo: ${fileName}\n\nCódigo:\n\`\`\`typescript\n${sourceCode}\n\`\`\``,
},
],
temperature: 0.2,
});
return response.choices[0].message.content || "";
}
async function updateFileWithJSDoc(filePath: string, jsdoc: string): Promise<void> {
let sourceCode = fs.readFileSync(filePath, "utf8");
// Análisis simple para insertar la documentación
// (Un enfoque más robusto usaría un parser de TS)
const docBlocks = jsdoc.match(/\/\*\*[\s\S]*?\*\//g) || [];
// Para cada bloque de documentación
for (const docBlock of docBlocks) {
// Extrae el nombre de la función/clase del bloque
const nameMatch = docBlock.match(/@(class|function|method|interface)\s+(\w+)/);
if (nameMatch) {
const [, type, name] = nameMatch;
// Busca la declaración en el código original
const regex = new RegExp(`(export\\s+)?(class|function|interface|const)\\s+${name}`);
const match = sourceCode.match(regex);
if (match) {
const position = match.index;
if (position !== undefined) {
// Inserta el bloque de documentación antes de la declaración
sourceCode =
sourceCode.substring(0, position) + docBlock + "\n" + sourceCode.substring(position);
}
}
}
}
fs.writeFileSync(filePath, sourceCode);
}
async function main() {
const targetFile = process.argv[2];
if (!targetFile) {
console.error("Por favor, especifica un archivo para generar documentación.");
process.exit(1);
}
try {
console.log(`Generando documentación JSDoc para ${targetFile}...`);
const jsdoc = await generateJSDocForFile(targetFile);
await updateFileWithJSDoc(targetFile, jsdoc);
console.log(`✅ Documentación generada y aplicada a ${targetFile}`);
} catch (error) {
console.error("Error al generar documentación:", error);
process.exit(1);
}
}
main();
Integración en CI/CD
Puedes incorporar la generación y validación de documentación en tu pipeline de CI/CD:
# .github/workflows/docs.yml
name: Documentation
on:
push:
branches: [main]
paths:
- "src/**"
- "docs/**"
jobs:
generate-docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: "18"
- name: Install dependencies
run: npm ci
- name: Generate API documentation
run: npm run docs:api
- name: Check for documentation coverage
run: |
COVERAGE=$(node scripts/doc-coverage.js)
if (( $(echo "$COVERAGE < 80" | bc -l) )); then
echo "Documentation coverage $COVERAGE% is below threshold of 80%"
exit 1
fi
- name: Build docs
run: npm run docs:build
- name: Deploy docs
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs/.vitepress/dist
Automatización de actualización de ejemplos
Puedes crear un proceso que actualice automáticamente los ejemplos de código cuando cambias tu API:
- Extrae información sobre la API actual usando análisis estático de TypeScript
- Compara con versiones anteriores para identificar cambios
- Usa IA para generar ejemplos actualizados para las partes modificadas
- Actualiza los archivos de documentación existentes
Buenas prácticas para documentación con IA
Para aprovechar al máximo la IA en tus procesos de documentación, sigue estas mejores prácticas:
Cuando y cómo usar la IA para documentación
- Para documentación inicial: Usa la IA para generar un primer borrador de la documentación cuando empiezas un nuevo componente.
- Para actualizar documentación: Utilízala cuando añadas nuevas características o realices cambios importantes.
- Para generar ejemplos: Genera ejemplos diversos que cubran diferentes casos de uso.
- Para mejorar la legibilidad: Refina la documentación existente para hacerla más clara y accesible.
Revisión humana de la documentación generada
Aunque la IA puede generar documentación de alta calidad, siempre es importante que un desarrollador la revise:
- Verifica la precisión técnica: Asegúrate de que la documentación describe correctamente la funcionalidad.
- Comprueba ejemplos: Verifica que los ejemplos son correctos y siguen buenas prácticas.
- Evalúa la claridad: Asegúrate de que la documentación es fácil de entender para los usuarios.
- Actualiza cuando sea necesario: Refina la documentación según el feedback de los usuarios.
Importante: La documentación generada por IA debe considerarse como un punto de partida, no como el producto final. Siempre revisa y refina la documentación para asegurarte de que realmente explica lo que los usuarios necesitan saber.
Equilibrio entre cantidad y calidad
Es mejor tener menos documentación de alta calidad que mucha documentación mediocre:
- Enfócate en documentar bien las APIs públicas primero
- Prioriza los flujos de trabajo comunes y casos de uso principales
- Asegúrate de que cada ejemplo sea práctico y realista
- Actualiza la documentación existente en lugar de añadir siempre nueva
Limitaciones y consideraciones
Al utilizar IA para generar documentación, es importante tener en cuenta algunas limitaciones:
Conocimiento limitado del dominio específico
La IA no conoce los detalles específicos de tu dominio o los requisitos particulares de tus usuarios:
- Proporciona contexto detallado sobre el propósito de tu librería
- Explica términos específicos de tu dominio
- Especifica la audiencia objetivo de la documentación
Documentación que parece correcta pero no lo es
A veces, la IA puede generar documentación que parece correcta pero contiene inexactitudes:
- Verifica siempre los ejemplos de código proporcionados
- Confirma que los tipos y parámetros coincidan con tu implementación actual
- Asegúrate de que la documentación refleje el comportamiento real del código
Recomendación: Mantén tu documentación cercana al código. Considera herramientas como JSDoc y TypeDoc que extraen la documentación directamente de los comentarios en el código, reduciendo la probabilidad de discrepancias.
Conclusión
La integración de herramientas de IA en tus procesos de documentación puede mejorar significativamente la calidad y eficiencia, permitiéndote:
- Generar documentación completa y detallada con menos esfuerzo
- Mantener la documentación actualizada cuando tu código evoluciona
- Crear ejemplos variados y útiles para diferentes casos de uso
- Mejorar la claridad y accesibilidad de tu documentación
Al combinar las capacidades de la IA con la experiencia humana, puedes crear documentación que sea a la vez completa y accesible, ayudando a los usuarios a aprovechar al máximo tu librería TypeScript.
Siguientes pasos
Una vez que hayas configurado procesos de documentación automatizados con IA, el siguiente paso lógico es establecer una guía clara para los contribuidores de tu proyecto. Consulta Guía de contribución para aprender cómo crear directrices efectivas para colaboradores externos.