git-tag-generate 0.0.2 → 1.0.4
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/README.md +220 -2
- package/dist/main.js +14 -0
- package/dist/main.js.map +7 -0
- package/package.json +64 -14
- package/.eslintrc.js +0 -13
- package/.nvmrc +0 -1
- package/main.js +0 -41
- package/src/gitCreate.js +0 -69
- package/src/tagList.js +0 -132
- package/src/tagNew.js +0 -77
package/README.md
CHANGED
|
@@ -1,3 +1,221 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Git Tag Generate
|
|
2
2
|
|
|
3
|
-
Herramienta para
|
|
3
|
+
Herramienta CLI moderna para generar tags Git siguiendo Semantic Versioning (SemVer) con soporte para prefijos, prerelease y gestión avanzada de tags.
|
|
4
|
+
|
|
5
|
+
## Características
|
|
6
|
+
|
|
7
|
+
- ✨ **CLI Híbrido**: comandos explícitos y atajos ergonómicos
|
|
8
|
+
- 🎯 **SemVer Completo**: patch, minor, major, prepatch, preminor, premajor, prerelease
|
|
9
|
+
- 🏷️ **Prefijos Flexibles**: organiza tags por proyecto/módulo con prefijos normalizados
|
|
10
|
+
- 🚀 **Prerelease**: soporte para beta, alpha, rc y identificadores personalizados
|
|
11
|
+
- 🗑️ **Borrado Múltiple**: elimina varios tags a la vez con multi-select
|
|
12
|
+
- 🔍 **Listado**: agrupa tags por prefijo, muestra historial ordenado
|
|
13
|
+
- ✅ **Validaciones**: verifica repo Git, remote origin, rama actual, duplicados
|
|
14
|
+
|
|
15
|
+
## Requisitos
|
|
16
|
+
|
|
17
|
+
- **Node.js** ≥ 20.0.0
|
|
18
|
+
|
|
19
|
+
## Instalación
|
|
20
|
+
|
|
21
|
+
### Global (recomendado)
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install -g git-tag-generate
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
o
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pnpm install -g git-tag-generate
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Uso
|
|
34
|
+
|
|
35
|
+
### Comportamiento Inteligente
|
|
36
|
+
|
|
37
|
+
Al ejecutar `gtg` sin argumentos, la herramienta detecta automáticamente el estado del repositorio:
|
|
38
|
+
|
|
39
|
+
- **Sin tags existentes**: ejecuta `gtg new` para crear el primer tag (0.0.1)
|
|
40
|
+
- **Con tags existentes**: ejecuta `gtg next` para incrementar desde el último tag
|
|
41
|
+
|
|
42
|
+
### Comandos
|
|
43
|
+
|
|
44
|
+
| Comando | Descripción |
|
|
45
|
+
| - | - |
|
|
46
|
+
| `gtg` | Flujo inteligente: `new` si no hay tags, `next` si ya existen |
|
|
47
|
+
| `gtg new` | Crear primer tag con versión inicial `0.0.1` |
|
|
48
|
+
| `gtg next` | Generar siguiente tag con incremento SemVer |
|
|
49
|
+
| `gtg list` | Listar todos los tags agrupados por prefijo |
|
|
50
|
+
| `gtg delete` | Eliminar tags con selección múltiple |
|
|
51
|
+
|
|
52
|
+
### Atajos
|
|
53
|
+
|
|
54
|
+
Los siguientes atajos ejecutan `gtg next --level <nivel>`:
|
|
55
|
+
|
|
56
|
+
| Atajo | Equivalente | Descripción |
|
|
57
|
+
| - | - | - |
|
|
58
|
+
| `gtg patch` | `gtg next -l patch` | Incrementa versión patch (0.0.X) |
|
|
59
|
+
| `gtg minor` | `gtg next -l minor` | Incrementa versión minor (0.X.0) |
|
|
60
|
+
| `gtg major` | `gtg next -l major` | Incrementa versión major (X.0.0) |
|
|
61
|
+
| `gtg prepatch` | `gtg next -l prepatch` | Prepatch con prerelease (0.0.X-beta.0) |
|
|
62
|
+
| `gtg preminor` | `gtg next -l preminor` | Preminor con prerelease (0.X.0-beta.0) |
|
|
63
|
+
| `gtg premajor` | `gtg next -l premajor` | Premajor con prerelease (X.0.0-beta.0) |
|
|
64
|
+
| `gtg prerelease` | `gtg next -l prerelease` | Incrementa número de prerelease |
|
|
65
|
+
|
|
66
|
+
### Flags
|
|
67
|
+
|
|
68
|
+
| Flag | Alias | Descripción |
|
|
69
|
+
| - | - | - |
|
|
70
|
+
| `--level <nivel>` | `-l` | Especifica nivel de incremento SemVer |
|
|
71
|
+
| `--beta` | - | Usa identificador `beta` para prerelease |
|
|
72
|
+
| `--alpha` | - | Usa identificador `alpha` para prerelease |
|
|
73
|
+
| `--id <id>` | - | Identificador personalizado para prerelease |
|
|
74
|
+
| `--noPush` | - | Crea el tag localmente sin subirlo al remote |
|
|
75
|
+
| `--dry-run` | - | Simula la operación sin crear el tag |
|
|
76
|
+
| `--prefixes` | - | Lista solo los prefijos disponibles (con `list`) |
|
|
77
|
+
| `--help` | `-h` | Muestra ayuda |
|
|
78
|
+
|
|
79
|
+
## Ejemplos
|
|
80
|
+
|
|
81
|
+
### Crear primer tag
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# Interactivo: pregunta por prefijo y crea tag 0.0.1
|
|
85
|
+
gtg new
|
|
86
|
+
|
|
87
|
+
# Ejemplo de flujo:
|
|
88
|
+
# ¿Deseas usar un prefijo para el tag? (y/N): y
|
|
89
|
+
# Ingresa el prefijo: my-app
|
|
90
|
+
# Prefijo normalizado: my-app
|
|
91
|
+
# Versión inicial: 0.0.1
|
|
92
|
+
# ¿Crear tag 'my-app-0.0.1'? (Y/n): y
|
|
93
|
+
# ✓ Tag 'my-app-0.0.1' creado exitosamente y subido al remote
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Incrementar versiones
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
# Incremento básico con atajos
|
|
100
|
+
gtg patch # 0.0.1 → 0.0.2
|
|
101
|
+
gtg minor # 0.0.2 → 0.1.0
|
|
102
|
+
gtg major # 0.1.0 → 1.0.0
|
|
103
|
+
|
|
104
|
+
# Con flags explícitos
|
|
105
|
+
gtg next --level patch
|
|
106
|
+
gtg next -l minor
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Prerelease
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# Crear prerelease beta
|
|
113
|
+
gtg prepatch --beta # 1.0.0 → 1.0.1-beta.0
|
|
114
|
+
gtg preminor --beta # 1.0.1 → 1.1.0-beta.0
|
|
115
|
+
gtg premajor --beta # 1.0.0 → 2.0.0-beta.0
|
|
116
|
+
|
|
117
|
+
# Incrementar prerelease existente
|
|
118
|
+
gtg prerelease --beta # 1.0.1-beta.0 → 1.0.1-beta.1
|
|
119
|
+
|
|
120
|
+
# Con identificadores personalizados
|
|
121
|
+
gtg prepatch --alpha # 1.0.0 → 1.0.1-alpha.0
|
|
122
|
+
gtg prepatch --id rc # 1.0.0 → 1.0.1-rc.0
|
|
123
|
+
gtg next -l prepatch --id canary
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Listar tags
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
# Listar todos los tags agrupados por prefijo
|
|
130
|
+
gtg list
|
|
131
|
+
|
|
132
|
+
# Ejemplo de salida:
|
|
133
|
+
# Tags encontrados: 8
|
|
134
|
+
#
|
|
135
|
+
# my-app:
|
|
136
|
+
# → my-app-1.0.0 (2026-01-25T10:30:00)
|
|
137
|
+
# my-app-0.1.0 (2026-01-24T15:20:00)
|
|
138
|
+
# my-app-0.0.1 (2026-01-23T09:00:00)
|
|
139
|
+
#
|
|
140
|
+
# (sin prefijo):
|
|
141
|
+
# → 2.0.0 (2026-01-22T12:00:00)
|
|
142
|
+
|
|
143
|
+
# Listar solo prefijos
|
|
144
|
+
gtg list --prefixes
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Eliminar tags
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
# Multi-select interactivo
|
|
151
|
+
gtg delete
|
|
152
|
+
|
|
153
|
+
# Ejemplo de flujo:
|
|
154
|
+
# Selecciona los tags a eliminar:
|
|
155
|
+
# ◉ my-app-0.0.1 (2026-01-23)
|
|
156
|
+
# ◯ my-app-0.1.0 (2026-01-24)
|
|
157
|
+
# ◉ my-app-1.0.0-beta.0 (2026-01-25)
|
|
158
|
+
#
|
|
159
|
+
# Tags a eliminar (2):
|
|
160
|
+
# - my-app-0.0.1
|
|
161
|
+
# - my-app-1.0.0-beta.0
|
|
162
|
+
#
|
|
163
|
+
# ¿Estás seguro de eliminar 2 tag(s)? (y/N): y
|
|
164
|
+
# ✓ my-app-0.0.1: eliminado local y remotamente
|
|
165
|
+
# ✓ my-app-1.0.0-beta.0: eliminado local y remotamente
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Opciones avanzadas
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
# Crear tag sin subirlo al remote
|
|
172
|
+
gtg patch --noPush
|
|
173
|
+
|
|
174
|
+
# Simular creación (dry run)
|
|
175
|
+
gtg major --dry-run
|
|
176
|
+
|
|
177
|
+
# Combinar flags
|
|
178
|
+
gtg prepatch --beta --noPush --dry-run
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Prefijos
|
|
182
|
+
|
|
183
|
+
Los prefijos permiten organizar tags por proyecto, módulo o entorno:
|
|
184
|
+
|
|
185
|
+
- **Con prefijo**: `my-app-1.0.0`, `backend-2.5.0`, `frontend-0.3.1`
|
|
186
|
+
- **Sin prefijo**: `1.0.0`, `2.0.0`
|
|
187
|
+
|
|
188
|
+
### Normalización automática
|
|
189
|
+
|
|
190
|
+
Los prefijos se normalizan siguiendo estas reglas:
|
|
191
|
+
|
|
192
|
+
- Convertidos a minúsculas
|
|
193
|
+
- Espacios y guiones bajos → guiones (`-`)
|
|
194
|
+
- Caracteres especiales eliminados
|
|
195
|
+
- Solo alfanuméricos y guiones permitidos
|
|
196
|
+
- No pueden empezar/terminar con guión
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
# Entrada → Salida normalizada
|
|
200
|
+
"My App" → "my-app"
|
|
201
|
+
"backend_v2" → "backend-v2"
|
|
202
|
+
"Front-End!" → "front-end"
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## Validaciones
|
|
206
|
+
|
|
207
|
+
La CLI realiza las siguientes validaciones automáticas:
|
|
208
|
+
|
|
209
|
+
- ✓ **Repositorio Git válido**: verifica que estés en un repo Git
|
|
210
|
+
- ✓ **Remote origin**: confirma existencia del remote antes de push
|
|
211
|
+
- ✓ **Rama actual**: advierte si no estás en `main`/`master` y pide confirmación
|
|
212
|
+
- ✓ **Tags duplicados**: previene creación de tags existentes
|
|
213
|
+
- ✓ **Formato SemVer**: valida que las versiones cumplan el estándar
|
|
214
|
+
|
|
215
|
+
## Licencia
|
|
216
|
+
|
|
217
|
+
[GPL-3.0 license](LICENSE.md)
|
|
218
|
+
|
|
219
|
+
## Autor
|
|
220
|
+
|
|
221
|
+
[GitHub](https://github.com/ddniel16) | [X](https://x.com/ddniel16) | [Website](https://ddniel16.dev)
|
package/dist/main.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var ce=Object.defineProperty;var L=(e,r)=>()=>(e&&(r=e(e=0)),r);var ge=(e,r)=>{for(var t in r)ce(e,t,{get:r[t],enumerable:!0})};import{simpleGit as me}from"simple-git";function d(e=process.cwd()){return X??=me(e),X}async function F(){try{return await d().status(),!0}catch{return!1}}async function Y(e="origin"){try{return(await d().getRemotes(!1)).some(o=>o.name===e)}catch{return!1}}async function ue(){return(await d().status()).current??"unknown"}async function K(){let e=await ue(),t=["main","master"].includes(e);return{currentBranch:e,isMain:t,shouldWarn:!t}}var X,C=L(()=>{"use strict";X=null});function J(e){let r=e.trim(),t=r.match(/^(.+)-(\d+\.\d+\.\d+(?:-[\w.]+)?)$/);if(!t)return{fullName:r,version:r};let[,o,n]=t;return!o||o.trim()===""?{fullName:r,version:n}:{fullName:r,prefix:o,version:n}}function Q(e,r){return!r||r.trim()===""?e:`${r}-${e}`}function v(e){let r=new Set;for(let t of e)r.add(t.prefix??null);return Array.from(r)}function ee(e,r){return e.filter(t=>r===null?!t.prefix:t.prefix===r)}var E=L(()=>{"use strict"});var k={};ge(k,{createTag:()=>I,deleteRemoteTag:()=>te,deleteTag:()=>O,getLastTag:()=>B,listTags:()=>g,pushTag:()=>re,tagExists:()=>b});async function g(e={}){let r=d(),t=e.sortBy??"-creatordate",o=await r.tag(["--sort="+t,"--format=%(refname:short)|%(creatordate:iso8601)|%(objectname:short)"]);if(!o||o.trim()==="")return[];let n=o.trim().split(`
|
|
3
|
+
`),s=[];for(let a of n){let[i,m,l]=a.split("|");if(!i)continue;let p=J(i);s.push({...p,date:m,hash:l})}return e.prefix!==void 0?s.filter(a=>e.prefix===""||e.prefix===void 0?!a.prefix:a.prefix===e.prefix):s}async function b(e){return(await g()).some(t=>t.fullName===e)}async function I(e){let{tagName:r,message:t,push:o=!0,dryRun:n=!1}=e;try{if(await b(r))return{success:!1,message:`El tag '${r}' ya existe`,error:new Error("Tag duplicado")};if(n)return{success:!0,message:`[DRY RUN] Se crear\xEDa el tag '${r}'${o?" y se subir\xEDa al remote":""}`};let s=d(),a=t??`Tag ${r}`;return await s.addAnnotatedTag(r,a),o&&await re(r,n),{success:!0,message:`Tag '${r}' creado exitosamente${o?" y subido al remote":""}`}}catch(s){return{success:!1,message:`Error al crear tag '${r}'`,error:s instanceof Error?s:new Error(String(s))}}}async function re(e,r=!1){try{return r?{success:!0,message:`[DRY RUN] Se subir\xEDa el tag '${e}' al remote`}:(await d().pushTags("origin"),{success:!0,message:`Tag '${e}' subido al remote`})}catch(t){return{success:!1,message:`Error al subir tag '${e}'`,error:t instanceof Error?t:new Error(String(t))}}}async function O(e){let{tagName:r,deleteRemote:t=!0,dryRun:o=!1}=e;try{return await b(r)?o?{success:!0,message:`[DRY RUN] Se eliminar\xEDa el tag '${r}'${t?" local y remotamente":" localmente"}`}:(await d().tag(["-d",r]),t&&await te(r,o),{success:!0,message:`Tag '${r}' eliminado${t?" local y remotamente":" localmente"}`}):{success:!1,message:`El tag '${r}' no existe`,error:new Error("Tag no encontrado")}}catch(n){return{success:!1,message:`Error al eliminar tag '${r}'`,error:n instanceof Error?n:new Error(String(n))}}}async function te(e,r=!1){try{return r?{success:!0,message:`[DRY RUN] Se eliminar\xEDa el tag '${e}' del remote`}:(await d().push("origin",`:refs/tags/${e}`),{success:!0,message:`Tag '${e}' eliminado del remote`})}catch(t){return{success:!1,message:`Error al eliminar tag '${e}' del remote`,error:t instanceof Error?t:new Error(String(t))}}}async function B(e){let r=await g({sortBy:"-creatordate",prefix:e});return r.length>0?r[0]:null}var T=L(()=>{"use strict";C();E()});C();import x from"chalk";import R from"chalk";function h(e,r=1){console.error(R.red("\u2717"),e),process.exit(r)}function y(e){console.log(R.green("\u2713"),e)}function u(e){console.log(R.yellow("\u26A0"),e)}function c(e){console.log(R.blue("\u2139"),e)}import{input as he,confirm as U}from"@inquirer/prompts";import S from"chalk";function w(e){return e.toLowerCase().trim().replace(/[\s_]+/g,"-").replace(/[^\w-]/g,"").replace(/-+/g,"-").replace(/^-|-$/g,"")}function N(e){return!e||e.trim().length===0?!1:/^[a-z0-9]+(-[a-z0-9]+)*$/.test(e)}import V from"semver";var G="0.0.1";function H(e){return/^\d+\.\d+\.\d+(?:-[0-9A-Za-z-.]+)?$/.test(e)?V.valid(e)!==null:!1}function pe(e,r,t){return(r==="prepatch"||r==="preminor"||r==="premajor"||r==="prerelease")&&!t&&(t="beta"),t?V.inc(e,r,t):V.inc(e,r)}function Z(e,r,t){if(!e)return G;let o=pe(e,r,t);if(!o)throw new Error(`No se pudo incrementar la versi\xF3n ${e} con nivel ${r}`);return o}T();C();E();async function oe(){let e=await g({sortBy:"-creatordate"}),r=v(e),t=[];for(let o of r){let n=ee(e,o);n.length>0&&t.push({prefix:o,tags:n,latest:n[0]})}return t}async function W(e){return B(e)}async function de(e){return!await b(e)}async function D(e,r,t={}){if(!H(e))return{success:!1,message:`La versi\xF3n '${e}' no es v\xE1lida seg\xFAn SemVer`};let o=Q(e,r);if(!await de(o))return{success:!1,message:`El tag '${o}' ya existe`};let n=await I({tagName:o,message:t.message,push:t.push??!0,dryRun:t.dryRun??!1});return{success:n.success,message:n.message,tagName:n.success?o:void 0}}async function ne(e,r,t,o={}){let s=(await W(r))?.version??null,a=Z(s,e,t);return D(a,r,o)}async function A(){return K()}async function ae(e){c("Creando nuevo tag");let r=await A();r.shouldWarn&&(u(`Est\xE1s en la rama '${S.yellow(r.currentBranch)}' (no es main/master)`),await U({message:"\xBFDeseas continuar de todas formas?",default:!1})||(console.log(S.gray("Operaci\xF3n cancelada")),process.exit(0)));let t;if(await U({message:"\xBFDeseas usar un prefijo para el tag?",default:!1})){let m=await he({message:"Ingresa el prefijo (se normalizar\xE1 autom\xE1ticamente):",validate:l=>{if(!l||l.trim().length===0)return"El prefijo no puede estar vac\xEDo";let p=w(l);return N(p)?!0:`El prefijo '${p}' no es v\xE1lido. Solo letras min\xFAsculas, n\xFAmeros y guiones`}});t=w(m),c(`Prefijo normalizado: ${S.cyan(t)}`)}let n=G;c(`Versi\xF3n inicial: ${S.cyan(n)}`);let s=t?`${t}-${n}`:n;await U({message:`\xBFCrear tag '${S.green(s)}'?`,default:!0})||(console.log(S.gray("Operaci\xF3n cancelada")),process.exit(0));let i=await D(n,t,{push:!e.noPush,dryRun:e.dryRun});i.success||h(i.message),y(i.message)}import{select as M,confirm as xe,input as ye}from"@inquirer/prompts";import $ from"chalk";E();T();async function se(e){c("Generando siguiente tag");let r=await g();r.length===0&&(u('No hay tags existentes. Usa el comando "new" para crear el primero.'),process.exit(0));let t=v(r),o;if(t.length>1||t.length===1&&t[0]!==null){let l=t.map(j=>({name:j??$.gray("(sin prefijo)"),value:j}));l.push({name:$.green("+ Crear nuevo prefijo"),value:"__new__"});let p=await M({message:"Selecciona el prefijo:",choices:l});if(p==="__new__"){let j=await ye({message:"Ingresa el nuevo prefijo:",validate:_=>{if(!_||_.trim().length===0)return"El prefijo no puede estar vac\xEDo";let q=w(_);return N(q)?!0:`El prefijo '${q}' no es v\xE1lido`}});o=w(j),c(`Prefijo normalizado: ${$.cyan(o)}`)}else o=p??void 0}else t.length===1&&t[0]!==null&&(o=t[0]);let n=await W(o);n?c(`\xDAltimo tag: ${$.cyan(n.fullName)} (${n.version})`):c("No hay tags previos con este prefijo. Se usar\xE1 versi\xF3n inicial.");let s,a;e.level?s=e.level:s=await M({message:"Selecciona el nivel de incremento:",choices:[{name:"Patch (0.0.X)",value:"patch"},{name:"Minor (0.X.0)",value:"minor"},{name:"Major (X.0.0)",value:"major"},{name:"Prepatch (0.0.X-beta.0)",value:"prepatch"},{name:"Preminor (0.X.0-beta.0)",value:"preminor"},{name:"Premajor (X.0.0-beta.0)",value:"premajor"},{name:"Prerelease (incrementar prerelease)",value:"prerelease"}]}),e.beta?a="beta":e.alpha?a="alpha":e.id&&(a=e.id),(s==="prepatch"||s==="preminor"||s==="premajor"||s==="prerelease")&&!a&&(a=await M({message:"Selecciona el identificador de prerelease:",choices:[{name:"beta",value:"beta"},{name:"alpha",value:"alpha"},{name:"rc",value:"rc"}]}));let i=await A();i.shouldWarn&&(u(`Est\xE1s en la rama '${$.yellow(i.currentBranch)}' (no es main/master)`),await xe({message:"\xBFDeseas continuar de todas formas?",default:!1})||(console.log($.gray("Operaci\xF3n cancelada")),process.exit(0)));let m=await ne(s,o,a,{push:!e.noPush,dryRun:e.dryRun});m.success||h(m.message),y(m.message)}import f from"chalk";E();T();async function ie(e){let r=await g();if(r.length===0){u("No hay tags en el repositorio");return}if(e.prefixes){let o=v(r);console.log(f.bold(`
|
|
4
|
+
Prefijos disponibles:`));for(let n of o)console.log(n===null?f.gray(" (sin prefijo)"):f.cyan(` ${n}`));return}let t=await oe();console.log(f.bold(`
|
|
5
|
+
Tags encontrados: ${r.length}
|
|
6
|
+
`));for(let o of t){let n=o.prefix===null?f.gray("(sin prefijo)"):f.cyan(o.prefix);console.log(f.bold(`${n}:`));for(let s=0;s<o.tags.length;s++){let a=o.tags[s],i=s===0,m=i?f.green("\u2192"):" ",l=i?f.green(a.fullName):a.fullName,p=a.date?f.gray(`(${a.date})`):"";console.log(` ${m} ${l} ${p}`)}console.log("")}}T();import{checkbox as we,confirm as ve}from"@inquirer/prompts";import P from"chalk";async function le(e){c("Selecciona los tags a eliminar");let r=await g();if(r.length===0){u("No hay tags en el repositorio");return}let t=await we({message:"Selecciona los tags a eliminar (usa espacio para seleccionar):",choices:r.map(a=>({name:`${a.fullName} ${a.date?P.gray(`(${a.date})`):""}`,value:a.fullName})),pageSize:15});if(t.length===0){console.log(P.gray("Ning\xFAn tag seleccionado. Operaci\xF3n cancelada."));return}console.log(P.yellow(`
|
|
7
|
+
Tags a eliminar (${t.length}):`));for(let a of t)console.log(P.red(` - ${a}`));if(!await ve({message:`\xBFEst\xE1s seguro de eliminar ${t.length} tag(s)?`,default:!1})){console.log(P.gray("Operaci\xF3n cancelada"));return}let n=0,s=0;for(let a of t){let i=await O({tagName:a,deleteRemote:!e.noPush,dryRun:e.dryRun});i.success?(y(`${a}: ${i.message}`),n++):(console.error(P.red(`\u2717 ${a}: ${i.message}`)),s++)}console.log(""),n>0&&y(`${n} tag(s) eliminado(s) correctamente`),s>0&&u(`${s} tag(s) con errores`)}function Te(){let e={},r=process.argv.slice(2),t=0;for(;t<r.length;){let o=r[t];if(!o){t++;continue}if(o==="--noPush"){e.noPush=!0,t++;continue}if(o==="--dry-run"){e.dryRun=!0,t++;continue}if(o==="--prefixes"){e.prefixes=!0,t++;continue}if(o==="--beta"){e.beta=!0,t++;continue}if(o==="--alpha"){e.alpha=!0,t++;continue}if(o==="-l"||o==="--level"){let n=r[t+1];if(n&&!n.startsWith("-")){e.level=n,t+=2;continue}}if(o==="--id"){let n=r[t+1];if(n&&!n.startsWith("-")){e.id=n,t+=2;continue}}!e.command&&!o.startsWith("-")&&(e.command=o),t++}return e}function Se(e){let{command:r}=e,t={patch:"patch",minor:"minor",major:"major",prepatch:"prepatch",preminor:"preminor",premajor:"premajor",prerelease:"prerelease"};return r&&r in t?{...e,command:"next",level:t[r]}:e}function $e(){console.log(x.bold(`
|
|
8
|
+
Git Tag Generate (gtg) - Generador de tags Git con SemVer
|
|
9
|
+
`)),console.log(x.bold("Uso:")),console.log(" gtg Flujo inteligente: new si no hay tags, next si existen"),console.log(" gtg new Crear primer tag"),console.log(" gtg next Generar siguiente tag"),console.log(" gtg list Listar tags"),console.log(` gtg delete Eliminar tags (multi-select)
|
|
10
|
+
`),console.log(x.bold("Atajos:")),console.log(" gtg patch Equivale a: gtg next --level patch"),console.log(" gtg minor Equivale a: gtg next --level minor"),console.log(" gtg major Equivale a: gtg next --level major"),console.log(" gtg prepatch Equivale a: gtg next --level prepatch"),console.log(" gtg preminor Equivale a: gtg next --level preminor"),console.log(" gtg premajor Equivale a: gtg next --level premajor"),console.log(` gtg prerelease Equivale a: gtg next --level prerelease
|
|
11
|
+
`),console.log(x.bold("Flags:")),console.log(" -l, --level <nivel> Especificar nivel: patch|minor|major|prepatch|..."),console.log(" --beta Usar identificador beta para prerelease"),console.log(" --alpha Usar identificador alpha para prerelease"),console.log(" --id <id> Identificador custom para prerelease"),console.log(" --noPush No subir tag al remote"),console.log(" --dry-run Simular sin crear tag"),console.log(" --prefixes Solo listar prefijos (con comando list)"),console.log(" -v, --version Mostrar versi\xF3n del programa"),console.log(` -h, --help Mostrar esta ayuda
|
|
12
|
+
`),console.log(x.bold("Ejemplos:")),console.log(" gtg new # Crear primer tag (0.0.1)"),console.log(" gtg patch # Incrementar patch (0.0.1 \u2192 0.0.2)"),console.log(" gtg minor # Incrementar minor (0.0.2 \u2192 0.1.0)"),console.log(" gtg major # Incrementar major (0.1.0 \u2192 1.0.0)"),console.log(" gtg next --beta # Crear prerelease beta"),console.log(' gtg prepatch --id rc # Crear prepatch con id "rc"'),console.log(" gtg list --prefixes # Listar solo prefijos"),console.log(" gtg delete # Eliminar tags (multi-select)"),console.log(" gtg patch --noPush # Crear sin subir al remote"),console.log(` gtg major --dry-run # Simular creaci\xF3n
|
|
13
|
+
`)}async function Pe(){let e=Te(),r=Se(e);(process.argv.includes("-v")||process.argv.includes("--version"))&&(console.log("git-tag-generate v1.0.4"),process.exit(0)),(r.command==="help"||process.argv.includes("-h")||process.argv.includes("--help"))&&($e(),process.exit(0)),await F()||h("No est\xE1s en un repositorio Git v\xE1lido"),r.command!=="list"&&!await Y("origin")&&h('No se encontr\xF3 el remote "origin". Aseg\xFArate de tener un remote configurado.');let t=r.command;if(!t){let{listTags:o}=await Promise.resolve().then(()=>(T(),k));t=(await o()).length>0?"next":"new"}try{switch(t){case"new":await ae(r);break;case"next":await se(r);break;case"list":await ie(r);break;case"delete":await le(r);break;default:console.error(x.red(`Comando desconocido: ${t}`)),console.log(x.gray('Usa "gtg --help" para ver comandos disponibles')),process.exit(1)}}catch(o){h(`Error inesperado: ${o instanceof Error?o.message:String(o)}`)}}Pe().catch(e=>{console.error(x.red("Error fatal:"),e),process.exit(1)});
|
|
14
|
+
//# sourceMappingURL=main.js.map
|
package/dist/main.js.map
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/git/repo.ts", "../src/domain/tag.ts", "../src/git/tags.ts", "../src/cli/index.ts", "../src/utils/validators.ts", "../src/cli/commands/new.ts", "../src/utils/slug.ts", "../src/domain/semver.ts", "../src/services/tagService.ts", "../src/cli/commands/next.ts", "../src/cli/commands/list.ts", "../src/cli/commands/delete.ts"],
|
|
4
|
+
"sourcesContent": ["import { simpleGit, type SimpleGit } from 'simple-git';\nimport type { BranchWarning } from '../types/index.js';\n\nlet gitInstance: SimpleGit | null = null;\n\n/**\n * Obtiene la instancia de SimpleGit (singleton)\n * @param baseDir - Directorio base del repositorio\n * @returns Instancia de SimpleGit\n */\nexport function getGit(baseDir = process.cwd()): SimpleGit {\n gitInstance ??= simpleGit(baseDir);\n return gitInstance;\n}\n\n/**\n * Verifica si el directorio actual es un repositorio Git\n * @returns true si es un repositorio Git v\u00E1lido\n */\nexport async function isGitRepo(): Promise<boolean> {\n try {\n const git = getGit();\n await git.status();\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Verifica si existe un remote espec\u00EDfico\n * @param remoteName - Nombre del remote (default: 'origin')\n * @returns true si el remote existe\n */\nexport async function hasRemote(remoteName = 'origin'): Promise<boolean> {\n try {\n const git = getGit();\n const remotes = await git.getRemotes(false);\n return remotes.some((remote) => remote.name === remoteName);\n } catch {\n return false;\n }\n}\n\n/**\n * Obtiene la rama actual\n * @returns Nombre de la rama actual\n */\nexport async function getCurrentBranch(): Promise<string> {\n const git = getGit();\n const status = await git.status();\n return status.current ?? 'unknown';\n}\n\n/**\n * Verifica el estado de la rama y retorna advertencias si no es main/master\n * @returns Informaci\u00F3n sobre la rama actual\n */\nexport async function checkBranchStatus(): Promise<BranchWarning> {\n const currentBranch = await getCurrentBranch();\n const mainBranches = ['main', 'master'];\n const isMain = mainBranches.includes(currentBranch);\n\n return {\n currentBranch,\n isMain,\n shouldWarn: !isMain,\n };\n}\n\n/**\n * Obtiene la URL del remote origin\n * @returns URL del remote o null si no existe\n */\nexport async function getRemoteUrl(remoteName = 'origin'): Promise<string | null> {\n try {\n const git = getGit();\n const remotes = await git.getRemotes(true);\n const remote = remotes.find((r) => r.name === remoteName);\n return remote?.refs.fetch ?? null;\n } catch {\n return null;\n }\n}\n", "import type { Tag } from '../types/index.js';\n\n/**\n * Parsea un tag completo separando prefijo y versi\u00F3n\n * Formato esperado: \"prefix-1.0.0\" o \"1.0.0\" (sin prefijo)\n * @param fullTag - Nombre completo del tag\n * @returns Objeto Tag con prefijo (opcional) y versi\u00F3n\n */\nexport function parseTag(fullTag: string): Tag {\n const trimmedTag = fullTag.trim();\n\n // Buscar patr\u00F3n: prefijo-version o solo version\n // Si hay guion, lo que est\u00E1 antes es prefijo, despu\u00E9s es versi\u00F3n\n const match = trimmedTag.match(/^(.+)-(\\d+\\.\\d+\\.\\d+(?:-[\\w.]+)?)$/);\n\n if (!match) {\n // No hay guion con formato v\u00E1lido, es solo versi\u00F3n (sin prefijo)\n return {\n fullName: trimmedTag,\n version: trimmedTag,\n };\n }\n\n const [, prefixPart, version] = match;\n\n if (!prefixPart || prefixPart.trim() === '') {\n // Sin prefijo\n return {\n fullName: trimmedTag,\n version,\n };\n }\n\n return {\n fullName: trimmedTag,\n prefix: prefixPart,\n version,\n };\n}\n\n/**\n * Formatea un tag completo a partir de prefijo y versi\u00F3n\n * @param version - Versi\u00F3n semver\n * @param prefix - Prefijo opcional\n * @returns Tag completo formateado\n */\nexport function formatTag(version: string, prefix?: string): string {\n if (!prefix || prefix.trim() === '') {\n return version;\n }\n return `${prefix}-${version}`;\n}\n\n/**\n * Extrae todos los prefijos \u00FAnicos de una lista de tags\n * @param tags - Lista de tags\n * @returns Array de prefijos \u00FAnicos (puede incluir null para tags sin prefijo)\n */\nexport function extractPrefixes(tags: Tag[]): (string | null)[] {\n const prefixSet = new Set<string | null>();\n\n for (const tag of tags) {\n prefixSet.add(tag.prefix ?? null);\n }\n\n return Array.from(prefixSet);\n}\n\n/**\n * Filtra tags por prefijo espec\u00EDfico\n * @param tags - Lista de tags\n * @param prefix - Prefijo a filtrar (null para tags sin prefijo)\n * @returns Tags que coinciden con el prefijo\n */\nexport function filterByPrefix(tags: Tag[], prefix: string | null): Tag[] {\n return tags.filter((tag) => {\n if (prefix === null) {\n return !tag.prefix;\n }\n return tag.prefix === prefix;\n });\n}\n", "import { getGit } from './repo.js';\nimport { parseTag } from '../domain/tag.js';\nimport type {\n Tag,\n CreateTagOptions,\n DeleteTagOptions,\n ListTagsOptions,\n GitOperationResult,\n} from '../types/index.js';\n\n/**\n * Lista todos los tags del repositorio\n * @param options - Opciones de filtrado y ordenamiento\n * @returns Lista de tags parseados\n */\nexport async function listTags(options: ListTagsOptions = {}): Promise<Tag[]> {\n const git = getGit();\n\n const sortBy = options.sortBy ?? '-creatordate';\n const tagList = await git.tag([\n '--sort=' + sortBy,\n '--format=%(refname:short)|%(creatordate:iso8601)|%(objectname:short)',\n ]);\n\n if (!tagList || tagList.trim() === '') {\n return [];\n }\n\n const tagLines = tagList.trim().split('\\n');\n const tags: Tag[] = [];\n\n for (const line of tagLines) {\n const [fullName, date, hash] = line.split('|');\n if (!fullName) continue;\n\n const parsed = parseTag(fullName);\n tags.push({\n ...parsed,\n date,\n hash,\n });\n }\n\n // Filtrar por prefijo si se especifica\n if (options.prefix !== undefined) {\n return tags.filter((tag) => {\n if (options.prefix === '' || options.prefix === undefined) {\n return !tag.prefix;\n }\n return tag.prefix === options.prefix;\n });\n }\n\n return tags;\n}\n\n/**\n * Verifica si un tag existe\n * @param tagName - Nombre del tag\n * @returns true si existe\n */\nexport async function tagExists(tagName: string): Promise<boolean> {\n const tags = await listTags();\n return tags.some((tag) => tag.fullName === tagName);\n}\n\n/**\n * Crea un nuevo tag\n * @param options - Opciones de creaci\u00F3n\n * @returns Resultado de la operaci\u00F3n\n */\nexport async function createTag(options: CreateTagOptions): Promise<GitOperationResult> {\n const { tagName, message, push = true, dryRun = false } = options;\n\n try {\n // Verificar si el tag ya existe\n if (await tagExists(tagName)) {\n return {\n success: false,\n message: `El tag '${tagName}' ya existe`,\n error: new Error('Tag duplicado'),\n };\n }\n\n if (dryRun) {\n return {\n success: true,\n message: `[DRY RUN] Se crear\u00EDa el tag '${tagName}'${push ? ' y se subir\u00EDa al remote' : ''}`,\n };\n }\n\n const git = getGit();\n\n // Crear tag anotado con mensaje\n const tagMessage = message ?? `Tag ${tagName}`;\n await git.addAnnotatedTag(tagName, tagMessage);\n\n // Push si est\u00E1 habilitado\n if (push) {\n await pushTag(tagName, dryRun);\n }\n\n return {\n success: true,\n message: `Tag '${tagName}' creado exitosamente${push ? ' y subido al remote' : ''}`,\n };\n } catch (error) {\n return {\n success: false,\n message: `Error al crear tag '${tagName}'`,\n error: error instanceof Error ? error : new Error(String(error)),\n };\n }\n}\n\n/**\n * Sube un tag al remote\n * @param tagName - Nombre del tag\n * @param dryRun - Si es true, solo simula la operaci\u00F3n\n * @returns Resultado de la operaci\u00F3n\n */\nexport async function pushTag(tagName: string, dryRun = false): Promise<GitOperationResult> {\n try {\n if (dryRun) {\n return {\n success: true,\n message: `[DRY RUN] Se subir\u00EDa el tag '${tagName}' al remote`,\n };\n }\n\n const git = getGit();\n await git.pushTags('origin');\n\n return {\n success: true,\n message: `Tag '${tagName}' subido al remote`,\n };\n } catch (error) {\n return {\n success: false,\n message: `Error al subir tag '${tagName}'`,\n error: error instanceof Error ? error : new Error(String(error)),\n };\n }\n}\n\n/**\n * Elimina un tag localmente\n * @param options - Opciones de eliminaci\u00F3n\n * @returns Resultado de la operaci\u00F3n\n */\nexport async function deleteTag(options: DeleteTagOptions): Promise<GitOperationResult> {\n const { tagName, deleteRemote = true, dryRun = false } = options;\n\n try {\n // Verificar que el tag existe\n if (!(await tagExists(tagName))) {\n return {\n success: false,\n message: `El tag '${tagName}' no existe`,\n error: new Error('Tag no encontrado'),\n };\n }\n\n if (dryRun) {\n return {\n success: true,\n message: `[DRY RUN] Se eliminar\u00EDa el tag '${tagName}'${deleteRemote ? ' local y remotamente' : ' localmente'}`,\n };\n }\n\n const git = getGit();\n\n // Eliminar tag local\n await git.tag(['-d', tagName]);\n\n // Eliminar del remote si est\u00E1 habilitado\n if (deleteRemote) {\n await deleteRemoteTag(tagName, dryRun);\n }\n\n return {\n success: true,\n message: `Tag '${tagName}' eliminado${deleteRemote ? ' local y remotamente' : ' localmente'}`,\n };\n } catch (error) {\n return {\n success: false,\n message: `Error al eliminar tag '${tagName}'`,\n error: error instanceof Error ? error : new Error(String(error)),\n };\n }\n}\n\n/**\n * Elimina un tag del remote\n * @param tagName - Nombre del tag\n * @param dryRun - Si es true, solo simula la operaci\u00F3n\n * @returns Resultado de la operaci\u00F3n\n */\nexport async function deleteRemoteTag(\n tagName: string,\n dryRun = false\n): Promise<GitOperationResult> {\n try {\n if (dryRun) {\n return {\n success: true,\n message: `[DRY RUN] Se eliminar\u00EDa el tag '${tagName}' del remote`,\n };\n }\n\n const git = getGit();\n await git.push('origin', `:refs/tags/${tagName}`);\n\n return {\n success: true,\n message: `Tag '${tagName}' eliminado del remote`,\n };\n } catch (error) {\n return {\n success: false,\n message: `Error al eliminar tag '${tagName}' del remote`,\n error: error instanceof Error ? error : new Error(String(error)),\n };\n }\n}\n\n/**\n * Obtiene el \u00FAltimo tag (globalmente o por prefijo)\n * @param prefix - Prefijo opcional para filtrar\n * @returns \u00DAltimo tag o null si no hay tags\n */\nexport async function getLastTag(prefix?: string): Promise<Tag | null> {\n const tags = await listTags({ sortBy: '-creatordate', prefix });\n return tags.length > 0 ? tags[0] : null;\n}\n", "#!/usr/bin/env node\n\nimport chalk from 'chalk';\nimport { isGitRepo, hasRemote } from '../git/repo.js';\nimport { exitWithError } from '../utils/validators.js';\nimport { newCommand } from './commands/new.js';\nimport { nextCommand } from './commands/next.js';\nimport { listCommand } from './commands/list.js';\nimport { deleteCommand } from './commands/delete.js';\nimport type { CliArgs, SemVerLevel } from '../types/index.js';\n\ndeclare const __VERSION__: string;\ndeclare const __PKG_NAME__: string;\n\n/**\n * Parsea los argumentos de l\u00EDnea de comandos\n */\nfunction parseArgs(): CliArgs {\n const args: CliArgs = {};\n const rawArgs = process.argv.slice(2);\n\n let i = 0;\n while (i < rawArgs.length) {\n const arg = rawArgs[i];\n\n if (!arg) {\n i++;\n continue;\n }\n\n // Flags booleanos\n if (arg === '--noPush') {\n args.noPush = true;\n i++;\n continue;\n }\n\n if (arg === '--dry-run') {\n args.dryRun = true;\n i++;\n continue;\n }\n\n if (arg === '--prefixes') {\n args.prefixes = true;\n i++;\n continue;\n }\n\n if (arg === '--beta') {\n args.beta = true;\n i++;\n continue;\n }\n\n if (arg === '--alpha') {\n args.alpha = true;\n i++;\n continue;\n }\n\n // Flags con valor\n if (arg === '-l' || arg === '--level') {\n const level = rawArgs[i + 1];\n if (level && !level.startsWith('-')) {\n args.level = level as SemVerLevel;\n i += 2;\n continue;\n }\n }\n\n if (arg === '--id') {\n const id = rawArgs[i + 1];\n if (id && !id.startsWith('-')) {\n args.id = id;\n i += 2;\n continue;\n }\n }\n\n // Comandos y atajos\n if (!args.command && !arg.startsWith('-')) {\n args.command = arg;\n }\n\n i++;\n }\n\n return args;\n}\n\n/**\n * Mapea atajos de comandos a comandos reales\n */\nfunction mapShortcuts(args: CliArgs): CliArgs {\n const { command } = args;\n\n // Atajos de niveles SemVer\n const levelShortcuts: Record<string, SemVerLevel> = {\n patch: 'patch',\n minor: 'minor',\n major: 'major',\n prepatch: 'prepatch',\n preminor: 'preminor',\n premajor: 'premajor',\n prerelease: 'prerelease',\n };\n\n if (command && command in levelShortcuts) {\n return {\n ...args,\n command: 'next',\n level: levelShortcuts[command],\n };\n }\n\n return args;\n}\n\n/**\n * Muestra ayuda\n */\nfunction showHelp(): void {\n console.log(chalk.bold('\\nGit Tag Generate (gtg) - Generador de tags Git con SemVer\\n'));\n\n console.log(chalk.bold('Uso:'));\n console.log(' gtg Flujo inteligente: new si no hay tags, next si existen');\n console.log(' gtg new Crear primer tag');\n console.log(' gtg next Generar siguiente tag');\n console.log(' gtg list Listar tags');\n console.log(' gtg delete Eliminar tags (multi-select)\\n');\n\n console.log(chalk.bold('Atajos:'));\n console.log(' gtg patch Equivale a: gtg next --level patch');\n console.log(' gtg minor Equivale a: gtg next --level minor');\n console.log(' gtg major Equivale a: gtg next --level major');\n console.log(' gtg prepatch Equivale a: gtg next --level prepatch');\n console.log(' gtg preminor Equivale a: gtg next --level preminor');\n console.log(' gtg premajor Equivale a: gtg next --level premajor');\n console.log(' gtg prerelease Equivale a: gtg next --level prerelease\\n');\n\n console.log(chalk.bold('Flags:'));\n console.log(' -l, --level <nivel> Especificar nivel: patch|minor|major|prepatch|...');\n console.log(' --beta Usar identificador beta para prerelease');\n console.log(' --alpha Usar identificador alpha para prerelease');\n console.log(' --id <id> Identificador custom para prerelease');\n console.log(' --noPush No subir tag al remote');\n console.log(' --dry-run Simular sin crear tag');\n console.log(' --prefixes Solo listar prefijos (con comando list)');\n console.log(' -v, --version Mostrar versi\u00F3n del programa');\n console.log(' -h, --help Mostrar esta ayuda\\n');\n\n console.log(chalk.bold('Ejemplos:'));\n console.log(' gtg new # Crear primer tag (0.0.1)');\n console.log(' gtg patch # Incrementar patch (0.0.1 \u2192 0.0.2)');\n console.log(' gtg minor # Incrementar minor (0.0.2 \u2192 0.1.0)');\n console.log(' gtg major # Incrementar major (0.1.0 \u2192 1.0.0)');\n console.log(' gtg next --beta # Crear prerelease beta');\n console.log(' gtg prepatch --id rc # Crear prepatch con id \"rc\"');\n console.log(' gtg list --prefixes # Listar solo prefijos');\n console.log(' gtg delete # Eliminar tags (multi-select)');\n console.log(' gtg patch --noPush # Crear sin subir al remote');\n console.log(' gtg major --dry-run # Simular creaci\u00F3n\\n');\n}\n\n/**\n * Funci\u00F3n principal\n */\nasync function main(): Promise<void> {\n const rawArgs = parseArgs();\n const args = mapShortcuts(rawArgs);\n\n // Mostrar versi\u00F3n\n if (process.argv.includes('-v') || process.argv.includes('--version')) {\n console.log(`${__PKG_NAME__} v${__VERSION__}`);\n process.exit(0);\n }\n\n // Mostrar ayuda\n if (args.command === 'help' || process.argv.includes('-h') || process.argv.includes('--help')) {\n showHelp();\n process.exit(0);\n }\n\n // Validar que estamos en un repo Git (excepto para help)\n if (!(await isGitRepo())) {\n exitWithError('No est\u00E1s en un repositorio Git v\u00E1lido');\n }\n\n // Validar que existe remote origin (excepto para list)\n if (args.command !== 'list' && !(await hasRemote('origin'))) {\n exitWithError('No se encontr\u00F3 el remote \"origin\". Aseg\u00FArate de tener un remote configurado.');\n }\n\n // Si no hay comando especificado, usar inteligencia\n let command = args.command;\n if (!command) {\n // Detectar si hay tags existentes para decidir entre 'new' y 'next'\n const { listTags } = await import('../git/tags.js');\n const existingTags = await listTags();\n command = existingTags.length > 0 ? 'next' : 'new';\n }\n\n try {\n switch (command) {\n case 'new':\n await newCommand(args);\n break;\n case 'next':\n await nextCommand(args);\n break;\n case 'list':\n await listCommand(args);\n break;\n case 'delete':\n await deleteCommand(args);\n break;\n default:\n console.error(chalk.red(`Comando desconocido: ${command}`));\n console.log(chalk.gray('Usa \"gtg --help\" para ver comandos disponibles'));\n process.exit(1);\n }\n } catch (error) {\n exitWithError(`Error inesperado: ${error instanceof Error ? error.message : String(error)}`);\n }\n}\n\n// Ejecutar\nmain().catch((error) => {\n console.error(chalk.red('Error fatal:'), error);\n process.exit(1);\n});\n", "import chalk from 'chalk';\n\n/**\n * Formatea un error para mostrar al usuario\n * @param error - Error a formatear\n * @returns Mensaje formateado\n */\nexport function formatError(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n return String(error);\n}\n\n/**\n * Muestra un mensaje de error y termina el proceso\n * @param message - Mensaje de error\n * @param exitCode - C\u00F3digo de salida (default: 1)\n */\nexport function exitWithError(message: string, exitCode = 1): never {\n console.error(chalk.red('\u2717'), message);\n process.exit(exitCode);\n}\n\n/**\n * Muestra un mensaje de \u00E9xito\n * @param message - Mensaje de \u00E9xito\n */\nexport function showSuccess(message: string): void {\n console.log(chalk.green('\u2713'), message);\n}\n\n/**\n * Muestra un mensaje de advertencia\n * @param message - Mensaje de advertencia\n */\nexport function showWarning(message: string): void {\n console.log(chalk.yellow('\u26A0'), message);\n}\n\n/**\n * Muestra un mensaje informativo\n * @param message - Mensaje informativo\n */\nexport function showInfo(message: string): void {\n console.log(chalk.blue('\u2139'), message);\n}\n", "import { input, confirm } from '@inquirer/prompts';\nimport chalk from 'chalk';\nimport { normalizePrefix, isValidPrefix } from '../../utils/slug.js';\nimport { DEFAULT_INITIAL_VERSION } from '../../domain/semver.js';\nimport * as tagService from '../../services/tagService.js';\nimport { showSuccess, showWarning, showInfo, exitWithError } from '../../utils/validators.js';\nimport type { CliArgs } from '../../types/index.js';\n\n/**\n * Comando para crear el primer tag (con o sin prefijo)\n * @param args - Argumentos de CLI\n */\nexport async function newCommand(args: CliArgs): Promise<void> {\n showInfo('Creando nuevo tag');\n\n // Verificar estado de la rama\n const branchStatus = await tagService.checkBranchStatus();\n if (branchStatus.shouldWarn) {\n showWarning(\n `Est\u00E1s en la rama '${chalk.yellow(branchStatus.currentBranch)}' (no es main/master)`\n );\n const continueAnyway = await confirm({\n message: '\u00BFDeseas continuar de todas formas?',\n default: false,\n });\n if (!continueAnyway) {\n console.log(chalk.gray('Operaci\u00F3n cancelada'));\n process.exit(0);\n }\n }\n\n // Prompt para prefijo (opcional)\n let prefix: string | undefined;\n const usePrefixResponse = await confirm({\n message: '\u00BFDeseas usar un prefijo para el tag?',\n default: false,\n });\n\n if (usePrefixResponse) {\n const prefixInput = await input({\n message: 'Ingresa el prefijo (se normalizar\u00E1 autom\u00E1ticamente):',\n validate: (value) => {\n if (!value || value.trim().length === 0) {\n return 'El prefijo no puede estar vac\u00EDo';\n }\n const normalized = normalizePrefix(value);\n if (!isValidPrefix(normalized)) {\n return `El prefijo '${normalized}' no es v\u00E1lido. Solo letras min\u00FAsculas, n\u00FAmeros y guiones`;\n }\n return true;\n },\n });\n\n prefix = normalizePrefix(prefixInput);\n showInfo(`Prefijo normalizado: ${chalk.cyan(prefix)}`);\n }\n\n // Mostrar versi\u00F3n inicial\n const version = DEFAULT_INITIAL_VERSION;\n showInfo(`Versi\u00F3n inicial: ${chalk.cyan(version)}`);\n\n // Confirmar creaci\u00F3n\n const tagName = prefix ? `${prefix}-${version}` : version;\n const confirmCreate = await confirm({\n message: `\u00BFCrear tag '${chalk.green(tagName)}'?`,\n default: true,\n });\n\n if (!confirmCreate) {\n console.log(chalk.gray('Operaci\u00F3n cancelada'));\n process.exit(0);\n }\n\n // Crear tag\n const result = await tagService.createNewTag(version, prefix, {\n push: !args.noPush,\n dryRun: args.dryRun,\n });\n\n if (!result.success) {\n exitWithError(result.message);\n }\n\n showSuccess(result.message);\n}\n", "/**\n * Normaliza un string para usarlo como prefijo de tag\n * Convierte a min\u00FAsculas, reemplaza espacios y caracteres especiales por guiones\n * @param text - Texto a normalizar\n * @returns String normalizado apto para prefijo\n */\nexport function normalizePrefix(text: string): string {\n return text\n .toLowerCase()\n .trim()\n .replace(/[\\s_]+/g, '-') // Espacios y guiones bajos a guiones\n .replace(/[^\\w-]/g, '') // Eliminar caracteres no alfanum\u00E9ricos excepto guiones\n .replace(/-+/g, '-') // M\u00FAltiples guiones a uno solo\n .replace(/^-|-$/g, ''); // Eliminar guiones al inicio y final\n}\n\n/**\n * Valida si un prefijo tiene formato v\u00E1lido\n * @param prefix - Prefijo a validar\n * @returns true si es v\u00E1lido\n */\nexport function isValidPrefix(prefix: string): boolean {\n if (!prefix || prefix.trim().length === 0) {\n return false;\n }\n // Solo letras min\u00FAsculas, n\u00FAmeros y guiones, no puede empezar/terminar con guion\n return /^[a-z0-9]+(-[a-z0-9]+)*$/.test(prefix);\n}\n", "import semver from 'semver';\nimport type { SemVerLevel } from '../types/index.js';\n\n/**\n * Versi\u00F3n inicial por defecto para nuevos tags\n */\nexport const DEFAULT_INITIAL_VERSION = '0.0.1';\n\n/**\n * Valida si una versi\u00F3n cumple con el formato SemVer\n * @param version - Versi\u00F3n a validar\n * @returns true si es v\u00E1lida\n */\nexport function isValidSemVer(version: string): boolean {\n // Enfoque estricto: no permitir prefijo 'v' ni formatos abreviados\n // Patr\u00F3n b\u00E1sico SemVer: MAJOR.MINOR.PATCH con prerelease opcional\n const strictPattern = /^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z-.]+)?$/;\n if (!strictPattern.test(version)) {\n return false;\n }\n return semver.valid(version) !== null;\n}\n\n/**\n * Verifica si una versi\u00F3n es prerelease (beta, alpha, rc, etc.)\n * @param version - Versi\u00F3n a verificar\n * @returns true si es prerelease\n */\nexport function isPrerelease(version: string): boolean {\n const parsed = semver.parse(version);\n return parsed !== null && parsed.prerelease.length > 0;\n}\n\n/**\n * Incrementa una versi\u00F3n seg\u00FAn el nivel especificado\n * @param currentVersion - Versi\u00F3n actual\n * @param level - Nivel de incremento\n * @param prereleaseId - Identificador para prerelease (beta, alpha, rc)\n * @returns Nueva versi\u00F3n incrementada\n */\nexport function incrementVersion(\n currentVersion: string,\n level: SemVerLevel,\n prereleaseId?: string\n): string | null {\n // Para niveles de prerelease, necesitamos un identificador\n if (\n (level === 'prepatch' ||\n level === 'preminor' ||\n level === 'premajor' ||\n level === 'prerelease') &&\n !prereleaseId\n ) {\n prereleaseId = 'beta'; // Default a beta si no se especifica\n }\n\n // semver.inc requiere que prereleaseId sea string si se pasa\n if (prereleaseId) {\n return semver.inc(currentVersion, level, prereleaseId);\n }\n\n return semver.inc(currentVersion, level);\n}\n\n/**\n * Obtiene la siguiente versi\u00F3n bas\u00E1ndose en el \u00FAltimo tag\n * Si no hay tag previo, retorna la versi\u00F3n inicial (0.0.1)\n * @param lastVersion - \u00DAltima versi\u00F3n (null si no existe)\n * @param level - Nivel de incremento\n * @param prereleaseId - Identificador para prerelease\n * @returns Nueva versi\u00F3n\n */\nexport function getNextVersion(\n lastVersion: string | null,\n level: SemVerLevel,\n prereleaseId?: string\n): string {\n // Si no hay versi\u00F3n previa, retornar versi\u00F3n inicial\n if (!lastVersion) {\n return DEFAULT_INITIAL_VERSION;\n }\n\n const nextVersion = incrementVersion(lastVersion, level, prereleaseId);\n\n if (!nextVersion) {\n throw new Error(`No se pudo incrementar la versi\u00F3n ${lastVersion} con nivel ${level}`);\n }\n\n return nextVersion;\n}\n\n/**\n * Compara dos versiones semver\n * @param v1 - Primera versi\u00F3n\n * @param v2 - Segunda versi\u00F3n\n * @returns -1 si v1 < v2, 0 si v1 === v2, 1 si v1 > v2\n */\nexport function compareVersions(v1: string, v2: string): number {\n return semver.compare(v1, v2);\n}\n\n/**\n * Extrae el identificador de prerelease de una versi\u00F3n\n * @param version - Versi\u00F3n a analizar\n * @returns Identificador de prerelease o null\n */\nexport function getPrereleaseId(version: string): string | null {\n const parsed = semver.parse(version);\n if (!parsed || parsed.prerelease.length === 0) {\n return null;\n }\n\n // El primer elemento del prerelease suele ser el identificador (beta, alpha, rc)\n return String(parsed.prerelease[0]);\n}\n", "import * as gitTags from '../git/tags.js';\nimport * as gitRepo from '../git/repo.js';\nimport { extractPrefixes, filterByPrefix, formatTag } from '../domain/tag.js';\nimport { getNextVersion, isValidSemVer } from '../domain/semver.js';\nimport type { Tag, TagGroup, SemVerLevel, CreateTagOptions } from '../types/index.js';\n\n/**\n * Obtiene todos los tags agrupados por prefijo\n * @returns Array de grupos de tags\n */\nexport async function groupByPrefix(): Promise<TagGroup[]> {\n const allTags = await gitTags.listTags({ sortBy: '-creatordate' });\n const prefixes = extractPrefixes(allTags);\n\n const groups: TagGroup[] = [];\n\n for (const prefix of prefixes) {\n const tagsInGroup = filterByPrefix(allTags, prefix);\n if (tagsInGroup.length > 0) {\n groups.push({\n prefix,\n tags: tagsInGroup,\n latest: tagsInGroup[0], // Ya est\u00E1n ordenados por fecha\n });\n }\n }\n\n return groups;\n}\n\n/**\n * Obtiene el \u00FAltimo tag, opcionalmente filtrado por prefijo\n * @param prefix - Prefijo opcional\n * @returns \u00DAltimo tag o null\n */\nexport async function getLastTag(prefix?: string): Promise<Tag | null> {\n return gitTags.getLastTag(prefix);\n}\n\n/**\n * Valida que un tag sea \u00FAnico\n * @param tagName - Nombre del tag a validar\n * @returns true si es \u00FAnico\n */\nexport async function validateNewTag(tagName: string): Promise<boolean> {\n return !(await gitTags.tagExists(tagName));\n}\n\n/**\n * Crea un nuevo tag con validaciones\n * @param version - Versi\u00F3n del tag\n * @param prefix - Prefijo opcional\n * @param options - Opciones adicionales\n * @returns Resultado de la operaci\u00F3n\n */\nexport async function createNewTag(\n version: string,\n prefix: string | undefined,\n options: Partial<CreateTagOptions> = {}\n): Promise<{ success: boolean; message: string; tagName?: string }> {\n // Validar formato SemVer\n if (!isValidSemVer(version)) {\n return {\n success: false,\n message: `La versi\u00F3n '${version}' no es v\u00E1lida seg\u00FAn SemVer`,\n };\n }\n\n const tagName = formatTag(version, prefix);\n\n // Validar unicidad\n if (!(await validateNewTag(tagName))) {\n return {\n success: false,\n message: `El tag '${tagName}' ya existe`,\n };\n }\n\n // Crear tag\n const result = await gitTags.createTag({\n tagName,\n message: options.message,\n push: options.push ?? true,\n dryRun: options.dryRun ?? false,\n });\n\n return {\n success: result.success,\n message: result.message,\n tagName: result.success ? tagName : undefined,\n };\n}\n\n/**\n * Genera el siguiente tag basado en el \u00FAltimo existente\n * @param level - Nivel de incremento SemVer\n * @param prefix - Prefijo opcional\n * @param prereleaseId - Identificador de prerelease\n * @param options - Opciones adicionales\n * @returns Resultado con el nuevo tag\n */\nexport async function generateNextTag(\n level: SemVerLevel,\n prefix: string | undefined,\n prereleaseId: string | undefined,\n options: Partial<CreateTagOptions> = {}\n): Promise<{ success: boolean; message: string; tagName?: string }> {\n // Obtener \u00FAltimo tag con el mismo prefijo\n const lastTag = await getLastTag(prefix);\n const lastVersion = lastTag?.version ?? null;\n\n // Calcular siguiente versi\u00F3n\n const nextVersion = getNextVersion(lastVersion, level, prereleaseId);\n\n // Crear el tag\n return createNewTag(nextVersion, prefix, options);\n}\n\n/**\n * Verifica el estado de la rama actual\n * @returns Informaci\u00F3n sobre la rama\n */\nexport async function checkBranchStatus() {\n return gitRepo.checkBranchStatus();\n}\n", "import { select, confirm, input } from '@inquirer/prompts';\nimport chalk from 'chalk';\nimport * as tagService from '../../services/tagService.js';\nimport { extractPrefixes } from '../../domain/tag.js';\nimport { listTags } from '../../git/tags.js';\nimport { normalizePrefix, isValidPrefix } from '../../utils/slug.js';\nimport { showSuccess, showWarning, showInfo, exitWithError } from '../../utils/validators.js';\nimport type { CliArgs, SemVerLevel } from '../../types/index.js';\n\n/**\n * Comando para generar el siguiente tag basado en SemVer\n * @param args - Argumentos de CLI\n */\nexport async function nextCommand(args: CliArgs): Promise<void> {\n showInfo('Generando siguiente tag');\n\n // Obtener todos los tags\n const allTags = await listTags();\n\n if (allTags.length === 0) {\n showWarning('No hay tags existentes. Usa el comando \"new\" para crear el primero.');\n process.exit(0);\n }\n\n // Extraer prefijos disponibles\n const prefixes = extractPrefixes(allTags);\n let selectedPrefix: string | undefined;\n\n // Si hay m\u00FAltiples prefijos o prefijos + sin prefijo, preguntar\n if (prefixes.length > 1 || (prefixes.length === 1 && prefixes[0] !== null)) {\n const prefixChoices = prefixes.map((p) => ({\n name: p ?? chalk.gray('(sin prefijo)'),\n value: p,\n }));\n\n // A\u00F1adir opci\u00F3n para crear nuevo prefijo\n prefixChoices.push({\n name: chalk.green('+ Crear nuevo prefijo'),\n value: '__new__',\n });\n\n const prefixChoice = await select({\n message: 'Selecciona el prefijo:',\n choices: prefixChoices,\n });\n\n if (prefixChoice === '__new__') {\n const newPrefixInput = await input({\n message: 'Ingresa el nuevo prefijo:',\n validate: (value) => {\n if (!value || value.trim().length === 0) {\n return 'El prefijo no puede estar vac\u00EDo';\n }\n const normalized = normalizePrefix(value);\n if (!isValidPrefix(normalized)) {\n return `El prefijo '${normalized}' no es v\u00E1lido`;\n }\n return true;\n },\n });\n selectedPrefix = normalizePrefix(newPrefixInput);\n showInfo(`Prefijo normalizado: ${chalk.cyan(selectedPrefix)}`);\n } else {\n selectedPrefix = prefixChoice ?? undefined;\n }\n // eslint-disable-next-line no-dupe-else-if\n } else if (prefixes.length === 1 && prefixes[0] !== null) {\n selectedPrefix = prefixes[0];\n }\n\n // Obtener \u00FAltimo tag con ese prefijo\n const lastTag = await tagService.getLastTag(selectedPrefix);\n\n if (lastTag) {\n showInfo(`\u00DAltimo tag: ${chalk.cyan(lastTag.fullName)} (${lastTag.version})`);\n } else {\n showInfo(`No hay tags previos con este prefijo. Se usar\u00E1 versi\u00F3n inicial.`);\n }\n\n // Determinar nivel de incremento\n let level: SemVerLevel;\n let prereleaseId: string | undefined;\n\n if (args.level) {\n level = args.level;\n } else {\n // Prompt para nivel\n level = await select<SemVerLevel>({\n message: 'Selecciona el nivel de incremento:',\n choices: [\n { name: 'Patch (0.0.X)', value: 'patch' },\n { name: 'Minor (0.X.0)', value: 'minor' },\n { name: 'Major (X.0.0)', value: 'major' },\n { name: 'Prepatch (0.0.X-beta.0)', value: 'prepatch' },\n { name: 'Preminor (0.X.0-beta.0)', value: 'preminor' },\n { name: 'Premajor (X.0.0-beta.0)', value: 'premajor' },\n { name: 'Prerelease (incrementar prerelease)', value: 'prerelease' },\n ],\n });\n }\n\n // Detectar prerelease id desde flags\n if (args.beta) {\n prereleaseId = 'beta';\n } else if (args.alpha) {\n prereleaseId = 'alpha';\n } else if (args.id) {\n prereleaseId = args.id;\n }\n\n // Si es nivel prerelease y no hay id, preguntar\n if (\n (level === 'prepatch' ||\n level === 'preminor' ||\n level === 'premajor' ||\n level === 'prerelease') &&\n !prereleaseId\n ) {\n prereleaseId = await select({\n message: 'Selecciona el identificador de prerelease:',\n choices: [\n { name: 'beta', value: 'beta' },\n { name: 'alpha', value: 'alpha' },\n { name: 'rc', value: 'rc' },\n ],\n });\n }\n\n // Verificar estado de la rama\n const branchStatus = await tagService.checkBranchStatus();\n if (branchStatus.shouldWarn) {\n showWarning(\n `Est\u00E1s en la rama '${chalk.yellow(branchStatus.currentBranch)}' (no es main/master)`\n );\n const continueAnyway = await confirm({\n message: '\u00BFDeseas continuar de todas formas?',\n default: false,\n });\n if (!continueAnyway) {\n console.log(chalk.gray('Operaci\u00F3n cancelada'));\n process.exit(0);\n }\n }\n\n // Generar siguiente tag\n const result = await tagService.generateNextTag(level, selectedPrefix, prereleaseId, {\n push: !args.noPush,\n dryRun: args.dryRun,\n });\n\n if (!result.success) {\n exitWithError(result.message);\n }\n\n showSuccess(result.message);\n}\n", "import chalk from 'chalk';\nimport * as tagService from '../../services/tagService.js';\nimport { extractPrefixes } from '../../domain/tag.js';\nimport { listTags } from '../../git/tags.js';\nimport { showWarning } from '../../utils/validators.js';\nimport type { CliArgs } from '../../types/index.js';\n\n/**\n * Comando para listar tags\n * @param args - Argumentos de CLI\n */\nexport async function listCommand(args: CliArgs): Promise<void> {\n const allTags = await listTags();\n\n if (allTags.length === 0) {\n showWarning('No hay tags en el repositorio');\n return;\n }\n\n // Si solo se piden prefijos\n if (args.prefixes) {\n const prefixes = extractPrefixes(allTags);\n console.log(chalk.bold('\\nPrefijos disponibles:'));\n for (const prefix of prefixes) {\n if (prefix === null) {\n console.log(chalk.gray(' (sin prefijo)'));\n } else {\n console.log(chalk.cyan(` ${prefix}`));\n }\n }\n return;\n }\n\n // Listar agrupados por prefijo\n const groups = await tagService.groupByPrefix();\n\n console.log(chalk.bold(`\\nTags encontrados: ${allTags.length}\\n`));\n\n for (const group of groups) {\n const prefixLabel =\n group.prefix === null ? chalk.gray('(sin prefijo)') : chalk.cyan(group.prefix);\n console.log(chalk.bold(`${prefixLabel}:`));\n\n for (let i = 0; i < group.tags.length; i++) {\n const tag = group.tags[i];\n const isLatest = i === 0;\n const marker = isLatest ? chalk.green('\u2192') : ' ';\n const tagDisplay = isLatest ? chalk.green(tag.fullName) : tag.fullName;\n const dateDisplay = tag.date ? chalk.gray(`(${tag.date})`) : '';\n\n console.log(` ${marker} ${tagDisplay} ${dateDisplay}`);\n }\n console.log('');\n }\n}\n", "import { checkbox, confirm } from '@inquirer/prompts';\nimport chalk from 'chalk';\nimport { listTags, deleteTag } from '../../git/tags.js';\nimport { showSuccess, showWarning, showInfo } from '../../utils/validators.js';\nimport type { CliArgs } from '../../types/index.js';\n\n/**\n * Comando para eliminar tags (multi-select)\n * @param args - Argumentos de CLI\n */\nexport async function deleteCommand(args: CliArgs): Promise<void> {\n showInfo('Selecciona los tags a eliminar');\n\n const allTags = await listTags();\n\n if (allTags.length === 0) {\n showWarning('No hay tags en el repositorio');\n return;\n }\n\n // Multi-select de tags\n const selectedTags = await checkbox({\n message: 'Selecciona los tags a eliminar (usa espacio para seleccionar):',\n choices: allTags.map((tag) => ({\n name: `${tag.fullName} ${tag.date ? chalk.gray(`(${tag.date})`) : ''}`,\n value: tag.fullName,\n })),\n pageSize: 15,\n });\n\n if (selectedTags.length === 0) {\n console.log(chalk.gray('Ning\u00FAn tag seleccionado. Operaci\u00F3n cancelada.'));\n return;\n }\n\n // Mostrar resumen\n console.log(chalk.yellow(`\\nTags a eliminar (${selectedTags.length}):`));\n for (const tagName of selectedTags) {\n console.log(chalk.red(` - ${tagName}`));\n }\n\n // Confirmar eliminaci\u00F3n\n const confirmDelete = await confirm({\n message: `\u00BFEst\u00E1s seguro de eliminar ${selectedTags.length} tag(s)?`,\n default: false,\n });\n\n if (!confirmDelete) {\n console.log(chalk.gray('Operaci\u00F3n cancelada'));\n return;\n }\n\n // Eliminar cada tag\n let successCount = 0;\n let errorCount = 0;\n\n for (const tagName of selectedTags) {\n const result = await deleteTag({\n tagName,\n deleteRemote: !args.noPush,\n dryRun: args.dryRun,\n });\n\n if (result.success) {\n showSuccess(`${tagName}: ${result.message}`);\n successCount++;\n } else {\n console.error(chalk.red(`\u2717 ${tagName}: ${result.message}`));\n errorCount++;\n }\n }\n\n // Resumen final\n console.log('');\n if (successCount > 0) {\n showSuccess(`${successCount} tag(s) eliminado(s) correctamente`);\n }\n if (errorCount > 0) {\n showWarning(`${errorCount} tag(s) con errores`);\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["simpleGit", "getGit", "baseDir", "gitInstance", "isGitRepo", "hasRemote", "remoteName", "remote", "getCurrentBranch", "checkBranchStatus", "currentBranch", "isMain", "init_repo", "__esmMin", "parseTag", "fullTag", "trimmedTag", "match", "prefixPart", "version", "formatTag", "prefix", "extractPrefixes", "tags", "prefixSet", "tag", "filterByPrefix", "init_tag", "__esmMin", "tags_exports", "__export", "createTag", "deleteRemoteTag", "deleteTag", "getLastTag", "listTags", "pushTag", "tagExists", "options", "git", "getGit", "sortBy", "tagList", "tagLines", "tags", "line", "fullName", "date", "hash", "parsed", "parseTag", "tag", "tagName", "message", "push", "dryRun", "tagMessage", "error", "deleteRemote", "prefix", "init_tags", "__esmMin", "init_repo", "init_tag", "init_repo", "chalk", "chalk", "exitWithError", "message", "exitCode", "chalk", "showSuccess", "showWarning", "showInfo", "input", "confirm", "chalk", "normalizePrefix", "text", "isValidPrefix", "prefix", "semver", "DEFAULT_INITIAL_VERSION", "isValidSemVer", "version", "incrementVersion", "currentVersion", "level", "prereleaseId", "semver", "getNextVersion", "lastVersion", "DEFAULT_INITIAL_VERSION", "nextVersion", "init_tags", "init_repo", "init_tag", "groupByPrefix", "allTags", "listTags", "prefixes", "extractPrefixes", "groups", "prefix", "tagsInGroup", "filterByPrefix", "getLastTag", "validateNewTag", "tagName", "tagExists", "createNewTag", "version", "options", "isValidSemVer", "formatTag", "result", "createTag", "generateNextTag", "level", "prereleaseId", "lastVersion", "nextVersion", "getNextVersion", "checkBranchStatus", "newCommand", "args", "showInfo", "branchStatus", "checkBranchStatus", "showWarning", "chalk", "confirm", "prefix", "prefixInput", "input", "value", "normalized", "normalizePrefix", "isValidPrefix", "version", "DEFAULT_INITIAL_VERSION", "tagName", "result", "createNewTag", "exitWithError", "showSuccess", "select", "confirm", "input", "chalk", "init_tag", "init_tags", "nextCommand", "args", "showInfo", "allTags", "listTags", "showWarning", "prefixes", "extractPrefixes", "selectedPrefix", "prefixChoices", "p", "chalk", "prefixChoice", "select", "newPrefixInput", "input", "value", "normalized", "normalizePrefix", "isValidPrefix", "lastTag", "getLastTag", "level", "prereleaseId", "branchStatus", "checkBranchStatus", "confirm", "result", "generateNextTag", "exitWithError", "showSuccess", "chalk", "init_tag", "init_tags", "listCommand", "args", "allTags", "listTags", "showWarning", "prefixes", "extractPrefixes", "chalk", "prefix", "groups", "groupByPrefix", "group", "prefixLabel", "i", "tag", "isLatest", "marker", "tagDisplay", "dateDisplay", "init_tags", "checkbox", "confirm", "chalk", "deleteCommand", "args", "showInfo", "allTags", "listTags", "showWarning", "selectedTags", "checkbox", "tag", "chalk", "tagName", "confirm", "successCount", "errorCount", "result", "deleteTag", "showSuccess", "parseArgs", "args", "rawArgs", "i", "arg", "level", "id", "mapShortcuts", "command", "levelShortcuts", "showHelp", "chalk", "main", "isGitRepo", "exitWithError", "hasRemote", "listTags", "newCommand", "nextCommand", "listCommand", "deleteCommand", "error"]
|
|
7
|
+
}
|
package/package.json
CHANGED
|
@@ -1,27 +1,77 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "git-tag-generate",
|
|
3
3
|
"homepage": "https://github.com/ddniel16/git-tag-generate",
|
|
4
|
-
"version": "
|
|
5
|
-
"license": "GPL-3.0
|
|
4
|
+
"version": "1.0.4",
|
|
5
|
+
"license": "GPL-3.0",
|
|
6
6
|
"author": {
|
|
7
|
-
"name": "
|
|
7
|
+
"name": "ddniel16",
|
|
8
8
|
"url": "https://github.com/ddniel16"
|
|
9
9
|
},
|
|
10
|
+
"type": "module",
|
|
10
11
|
"bin": {
|
|
11
|
-
"gtg": "main.js"
|
|
12
|
+
"gtg": "./dist/main.js"
|
|
13
|
+
},
|
|
14
|
+
"main": "./dist/main.js",
|
|
15
|
+
"files": [
|
|
16
|
+
"dist/",
|
|
17
|
+
"README.md",
|
|
18
|
+
"LICENSE.md"
|
|
19
|
+
],
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=20.0.0"
|
|
12
22
|
},
|
|
13
23
|
"preferGlobal": true,
|
|
14
|
-
"
|
|
15
|
-
|
|
24
|
+
"keywords": [
|
|
25
|
+
"git",
|
|
26
|
+
"tag",
|
|
27
|
+
"git-tag-generate",
|
|
28
|
+
"version",
|
|
29
|
+
"release",
|
|
30
|
+
"git-tag",
|
|
31
|
+
"semver",
|
|
32
|
+
"cli",
|
|
33
|
+
"typescript"
|
|
34
|
+
],
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "git+https://github.com/ddniel16/git-tag-generate.git"
|
|
38
|
+
},
|
|
16
39
|
"dependencies": {
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"slugify": "^1.6.6"
|
|
40
|
+
"@inquirer/prompts": "^5.5.0",
|
|
41
|
+
"chalk": "^5.3.0",
|
|
42
|
+
"semver": "^7.6.0",
|
|
43
|
+
"simple-git": "^3.25.0"
|
|
22
44
|
},
|
|
23
45
|
"devDependencies": {
|
|
24
|
-
"
|
|
25
|
-
"
|
|
46
|
+
"@types/node": "^20.11.0",
|
|
47
|
+
"@types/semver": "^7.5.6",
|
|
48
|
+
"@typescript-eslint/eslint-plugin": "^8.18.0",
|
|
49
|
+
"@typescript-eslint/parser": "^8.18.0",
|
|
50
|
+
"@vitest/coverage-v8": "^1.2.0",
|
|
51
|
+
"esbuild": "^0.20.0",
|
|
52
|
+
"eslint": "^9.39.0",
|
|
53
|
+
"eslint-config-prettier": "^10.1.8",
|
|
54
|
+
"prettier": "^3.2.0",
|
|
55
|
+
"typescript": "^5.3.3",
|
|
56
|
+
"vitest": "^1.2.0"
|
|
57
|
+
},
|
|
58
|
+
"scripts": {
|
|
59
|
+
"clean": "node -e \"try { require('fs').rmSync('dist', { recursive: true, force: true }) } catch(e){}\"",
|
|
60
|
+
"build": "node --run clean && node --run validate && node esbuild.config.mjs",
|
|
61
|
+
"validate": "node --run lint && node --run type-check && node --run format",
|
|
62
|
+
"postbuild": "chmod +x dist/main.js",
|
|
63
|
+
"test": "vitest run",
|
|
64
|
+
"test:watch": "vitest",
|
|
65
|
+
"test:coverage": "vitest run --coverage",
|
|
66
|
+
"test:ci": "vitest run --coverage --reporter=verbose",
|
|
67
|
+
"lint": "eslint src",
|
|
68
|
+
"lint:fix": "eslint src --fix",
|
|
69
|
+
"format": "prettier --check \"src/**/*.ts\"",
|
|
70
|
+
"format:fix": "prettier --write \"src/**/*.ts\"",
|
|
71
|
+
"type-check": "tsc --noEmit",
|
|
72
|
+
"link": "pnpm link --global",
|
|
73
|
+
"unlink": "pnpm unlink --global",
|
|
74
|
+
"preversion": "node --run test && node --run build",
|
|
75
|
+
"postversion": "git push && git push --tags"
|
|
26
76
|
}
|
|
27
|
-
}
|
|
77
|
+
}
|
package/.eslintrc.js
DELETED
package/.nvmrc
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
v18
|
package/main.js
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const commandLineArgs = require('command-line-args');
|
|
4
|
-
const inquirer = require('inquirer');
|
|
5
|
-
const chalk = require('chalk');
|
|
6
|
-
const log = console.log;
|
|
7
|
-
|
|
8
|
-
const MSG_CREATE_NEW_PREFIX = 'Crear nuevo prefix';
|
|
9
|
-
|
|
10
|
-
const optionDefinitions = [
|
|
11
|
-
{name: 'no-push', type: Boolean},
|
|
12
|
-
];
|
|
13
|
-
const args = commandLineArgs(optionDefinitions);
|
|
14
|
-
|
|
15
|
-
const tagList = require('./src/tagList');
|
|
16
|
-
const tagNew = require('./src/tagNew');
|
|
17
|
-
|
|
18
|
-
if (tagList.getLastTag() === false) {
|
|
19
|
-
log(chalk.yellow('No hay tags previos'));
|
|
20
|
-
tagNew.createFirstTag(args);
|
|
21
|
-
} else {
|
|
22
|
-
log('El último tag es:', chalk.green(tagList.getLastTag()));
|
|
23
|
-
|
|
24
|
-
const choicesList = tagList.getListPrefix();
|
|
25
|
-
choicesList.push(new inquirer.Separator());
|
|
26
|
-
choicesList.push(MSG_CREATE_NEW_PREFIX);
|
|
27
|
-
|
|
28
|
-
inquirer.prompt([{
|
|
29
|
-
type: 'list',
|
|
30
|
-
name: 'prefix',
|
|
31
|
-
message: '¿Seguir con el prefix o con uno nuevo?',
|
|
32
|
-
choices: choicesList,
|
|
33
|
-
}]).then((answers) => {
|
|
34
|
-
if (answers.prefix === MSG_CREATE_NEW_PREFIX) {
|
|
35
|
-
tagNew.createFirstTag(args);
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
tagNew.createNextTag(args, answers.prefix);
|
|
40
|
-
});
|
|
41
|
-
}
|
package/src/gitCreate.js
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
const childProcess = require('child_process');
|
|
2
|
-
const chalk = require('chalk');
|
|
3
|
-
const log = console.log;
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Clase para crear y pushear
|
|
7
|
-
*/
|
|
8
|
-
class GitCreateClass {
|
|
9
|
-
/** Constructor */
|
|
10
|
-
constructor() {
|
|
11
|
-
this.spawnOptions = {encoding: 'utf-8'};
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Crear un tag
|
|
16
|
-
* @param {string} tag
|
|
17
|
-
*/
|
|
18
|
-
createTag(tag) {
|
|
19
|
-
const spawn = childProcess.spawnSync(
|
|
20
|
-
'git',
|
|
21
|
-
['tag', tag],
|
|
22
|
-
this.spawnOptions,
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
if (spawn.status !== 0) {
|
|
26
|
-
const errorText = spawn.stderr.toString().trim();
|
|
27
|
-
log(chalk.red('No se pudo crear el tag'));
|
|
28
|
-
log(errorText);
|
|
29
|
-
process.exit(0);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
log('Se creo el tag:', chalk.green(tag));
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Pushear un tag
|
|
37
|
-
* @param {string} tag
|
|
38
|
-
*/
|
|
39
|
-
pushTag(tag) {
|
|
40
|
-
const spawn = childProcess.spawnSync(
|
|
41
|
-
'git',
|
|
42
|
-
['push', 'origin', tag],
|
|
43
|
-
this.spawnOptions,
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
if (spawn.status !== 0) {
|
|
47
|
-
const errorText = spawn.stderr.toString().trim();
|
|
48
|
-
log(chalk.red('No se pudo pushear el tag'));
|
|
49
|
-
log(errorText);
|
|
50
|
-
process.exit(0);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
log('Se pusheo el tag:', chalk.green(tag));
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Crear y pushear un tag
|
|
58
|
-
* @param {string} tag
|
|
59
|
-
* @param {object} args
|
|
60
|
-
*/
|
|
61
|
-
createTagAndPush(tag, args) {
|
|
62
|
-
this.createTag(tag);
|
|
63
|
-
if (args['no-push'] === false || args['no-push'] === undefined) {
|
|
64
|
-
this.pushTag(tag);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
module.exports = new GitCreateClass();
|
package/src/tagList.js
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
const childProcess = require('child_process');
|
|
2
|
-
const chalk = require('chalk');
|
|
3
|
-
const log = console.log;
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Clase para obtener información de los tags
|
|
7
|
-
*/
|
|
8
|
-
class TagListClass {
|
|
9
|
-
/** Constructor */
|
|
10
|
-
constructor() {
|
|
11
|
-
this.tagsRaw = [];
|
|
12
|
-
this.fetchAllTags();
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Actualiza la lista de tags del repositorio
|
|
17
|
-
* @return {string} stdout
|
|
18
|
-
*/
|
|
19
|
-
fetchAllTags() {
|
|
20
|
-
const spawn = childProcess.spawnSync(
|
|
21
|
-
'git',
|
|
22
|
-
['fetch', '--all', '--tags'],
|
|
23
|
-
{encoding: 'utf-8'},
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
if (spawn.status !== 0) {
|
|
27
|
-
const errorText = spawn.stderr.toString().trim();
|
|
28
|
-
log(chalk.red('No es un repositorio git'));
|
|
29
|
-
log(errorText);
|
|
30
|
-
process.exit(0);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return spawn.stdout.toString().trim();
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Devuelve el listado de prefijos que hay en el repositorio
|
|
38
|
-
* @return {array} tags
|
|
39
|
-
*/
|
|
40
|
-
getListPrefix() {
|
|
41
|
-
const tagsRaw = this.getListRaw();
|
|
42
|
-
let tagsPrefix = tagsRaw.map(function(tagRaw) {
|
|
43
|
-
const version = tagRaw.split('-').pop();
|
|
44
|
-
if (tagRaw.replaceAll(version, '') === '') {
|
|
45
|
-
return '';
|
|
46
|
-
}
|
|
47
|
-
return tagRaw.replaceAll('-' + version, '');
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
tagsPrefix = [...new Set(tagsPrefix)];
|
|
51
|
-
return tagsPrefix;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Devuelve el último tag del repositorio
|
|
56
|
-
* @return {array} tags
|
|
57
|
-
*/
|
|
58
|
-
getLastTag() {
|
|
59
|
-
if (this.getListRaw() === false) {
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
const first = [...this.getListRaw()].shift();
|
|
63
|
-
return first;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Devuelve el último tag del repositorio que empieza por el prefijo indicado
|
|
68
|
-
* @param {string} searchPrefix
|
|
69
|
-
* @return {string} tag
|
|
70
|
-
*/
|
|
71
|
-
getLastTagByPrefix(searchPrefix) {
|
|
72
|
-
return (function() {
|
|
73
|
-
const args = [
|
|
74
|
-
'tag',
|
|
75
|
-
'-l', searchPrefix + '-*',
|
|
76
|
-
'--format', '%(refname:strip=2)',
|
|
77
|
-
'--sort', '-creatordate',
|
|
78
|
-
];
|
|
79
|
-
|
|
80
|
-
const spawn = childProcess.spawnSync('git', args, {encoding: 'utf-8'});
|
|
81
|
-
if (spawn.status !== 0) {
|
|
82
|
-
const errorText = spawn.stderr.toString().trim();
|
|
83
|
-
log(chalk.red('No es un repositorio git'));
|
|
84
|
-
log(errorText);
|
|
85
|
-
process.exit(0);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return spawn.stdout.toString().trim().split('\n').shift();
|
|
89
|
-
})();
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Devuelve el listado de tags del repositorio
|
|
94
|
-
* @return {array} tags
|
|
95
|
-
*/
|
|
96
|
-
getListRaw() {
|
|
97
|
-
if (this.tagsRaw.length > 0) {
|
|
98
|
-
return this.tagsRaw;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const tagListRaw = (function() {
|
|
102
|
-
const spawn = childProcess.spawnSync(
|
|
103
|
-
'git',
|
|
104
|
-
['tag', '--format', '%(refname:strip=2)', '--sort', '-creatordate'],
|
|
105
|
-
{encoding: 'utf-8'},
|
|
106
|
-
);
|
|
107
|
-
|
|
108
|
-
if (spawn.status !== 0) {
|
|
109
|
-
const errorText = spawn.stderr.toString().trim();
|
|
110
|
-
log(chalk.red('No es un repositorio git'));
|
|
111
|
-
log(errorText);
|
|
112
|
-
process.exit(0);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return spawn.stdout.toString().trim();
|
|
116
|
-
})();
|
|
117
|
-
|
|
118
|
-
if (tagListRaw.trim() === '') {
|
|
119
|
-
return false;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const list = tagListRaw.trim().split('\n');
|
|
123
|
-
|
|
124
|
-
for (let i = 0; i < list.length; i++) {
|
|
125
|
-
this.tagsRaw.push(list[i].replaceAll('"', ''));
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
return this.tagsRaw;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
module.exports = new TagListClass();
|
package/src/tagNew.js
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
const slugify = require('slugify');
|
|
2
|
-
const inquirer = require('inquirer');
|
|
3
|
-
const chalk = require('chalk');
|
|
4
|
-
const semver = require('semver');
|
|
5
|
-
const log = console.log;
|
|
6
|
-
|
|
7
|
-
const GitCreate = require('./gitCreate');
|
|
8
|
-
const TagList = require('./tagList');
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Clase para crear tags
|
|
12
|
-
*/
|
|
13
|
-
class TagNewClass {
|
|
14
|
-
/**
|
|
15
|
-
* Crea el primer tag
|
|
16
|
-
* @param {object} args
|
|
17
|
-
*/
|
|
18
|
-
createFirstTag(args) {
|
|
19
|
-
inquirer.prompt([{
|
|
20
|
-
name: 'prefix',
|
|
21
|
-
message: '¿Algún prefix?',
|
|
22
|
-
}]).then((answers) => {
|
|
23
|
-
let version = '0.0.1';
|
|
24
|
-
const prefix = slugify(answers.prefix).trim();
|
|
25
|
-
|
|
26
|
-
if (prefix === '') {
|
|
27
|
-
log(chalk.yellow('No se va a usar prefix'));
|
|
28
|
-
} else {
|
|
29
|
-
log(chalk.yellow('Se va a usar el prefix:'), chalk.green(prefix));
|
|
30
|
-
version = prefix + '-' + version;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
inquirer.prompt([{
|
|
34
|
-
type: 'confirm',
|
|
35
|
-
name: 'confirm',
|
|
36
|
-
message: 'Se va a crear el tag "' + version + '" ¿Continuar?',
|
|
37
|
-
}]).then((answers) => {
|
|
38
|
-
if (answers.confirm === false) {
|
|
39
|
-
log(chalk.red('No se creo el tag'));
|
|
40
|
-
process.exit(0);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
GitCreate.createTagAndPush(version, args);
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Crea el siguiente tag de un prefix
|
|
50
|
-
* @param {object} args
|
|
51
|
-
* @param {string} prefix
|
|
52
|
-
*/
|
|
53
|
-
createNextTag(args, prefix) {
|
|
54
|
-
const version = TagList.getLastTagByPrefix(prefix).split('-').pop();
|
|
55
|
-
|
|
56
|
-
const vPatch = prefix + '-' + semver.inc(version, 'patch');
|
|
57
|
-
const vMinor = prefix + '-' + semver.inc(version, 'minor');
|
|
58
|
-
const vMajor = prefix + '-' + semver.inc(version, 'major');
|
|
59
|
-
|
|
60
|
-
const newReleases = [
|
|
61
|
-
{name: 'Patch ' + vPatch, value: vPatch},
|
|
62
|
-
{name: 'Minor ' + vMinor, value: vMinor},
|
|
63
|
-
{name: 'Major ' + vMajor, value: vMajor},
|
|
64
|
-
];
|
|
65
|
-
|
|
66
|
-
inquirer.prompt([{
|
|
67
|
-
type: 'list',
|
|
68
|
-
name: 'release',
|
|
69
|
-
message: '--------',
|
|
70
|
-
choices: newReleases,
|
|
71
|
-
}]).then((answers) => {
|
|
72
|
-
GitCreate.createTagAndPush(answers.release, args);
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
module.exports = new TagNewClass();
|