@icarusmx/creta 1.4.18 → 1.5.1
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 +395 -0
- package/bin/creta.js +1645 -25
- package/docs/diagrams/README.md +131 -0
- package/docs/diagrams/architecture-overview.mmd +71 -0
- package/docs/diagrams/architecture.svg +1 -0
- package/docs/diagrams/ecosystem-integration.mmd +49 -0
- package/docs/diagrams/evolution-phases.mmd +49 -0
- package/docs/diagrams/output.svg +1 -0
- package/docs/diagrams/phase2-command-help-flow.mmd +51 -0
- package/docs/diagrams/user-journey.mmd +78 -0
- package/lib/cli/index.js +6 -0
- package/lib/customizers/TerminalCustomizer.js +186 -15
- package/lib/data/command-help/cd.js +47 -0
- package/lib/data/command-help/git-add.js +43 -0
- package/lib/data/command-help/git-commit.js +39 -0
- package/lib/data/command-help/git-log.js +47 -0
- package/lib/data/command-help/git-push.js +35 -0
- package/lib/data/command-help/git-status.js +31 -0
- package/lib/data/command-help/index.js +30 -0
- package/lib/data/command-help/ls.js +51 -0
- package/lib/data/command-help/mkdir.js +31 -0
- package/lib/data/command-help/touch.js +26 -0
- package/lib/data/command-help/wc.js +43 -0
- package/lib/data/messages.js +16 -4
- package/lib/executors/CommandHelpExecutor.js +93 -0
- package/lib/papers/AccessControl.js +121 -0
- package/lib/papers/PapersExecutor.js +276 -0
- package/package.json +1 -4
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export const gitCommit = {
|
|
2
|
+
command: 'git commit',
|
|
3
|
+
description: 'Guarda los cambios en staging con un mensaje descriptivo',
|
|
4
|
+
usage: 'git commit [opciones]',
|
|
5
|
+
commonOptions: [
|
|
6
|
+
{
|
|
7
|
+
flag: '-m "mensaje"',
|
|
8
|
+
description: 'Commit con mensaje directo (sin abrir editor)'
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
flag: '-am "mensaje"',
|
|
12
|
+
description: 'Add + commit de archivos ya rastreados en un solo paso'
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
flag: '--amend',
|
|
16
|
+
description: 'Modificar el último commit (agregar cambios o cambiar mensaje)'
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
examples: [
|
|
20
|
+
{
|
|
21
|
+
command: 'git commit -m "add login feature"',
|
|
22
|
+
description: 'Commit con mensaje descriptivo'
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
command: 'git commit -am "fix header bug"',
|
|
26
|
+
description: 'Agregar y hacer commit en un paso (solo archivos tracked)'
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
command: 'git commit --amend -m "nuevo mensaje"',
|
|
30
|
+
description: 'Cambiar el mensaje del último commit'
|
|
31
|
+
}
|
|
32
|
+
],
|
|
33
|
+
relatedLesson: 'Git básico',
|
|
34
|
+
tips: [
|
|
35
|
+
'Mensajes claros y descriptivos: "add" "fix" "update" "remove"',
|
|
36
|
+
'Un commit = un cambio lógico (no mezclar features diferentes)',
|
|
37
|
+
'Usa git log para ver tu historial de commits'
|
|
38
|
+
]
|
|
39
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export const gitLog = {
|
|
2
|
+
command: 'git log',
|
|
3
|
+
description: 'Muestra el historial de commits del repositorio',
|
|
4
|
+
usage: 'git log [opciones]',
|
|
5
|
+
commonOptions: [
|
|
6
|
+
{
|
|
7
|
+
flag: '--oneline',
|
|
8
|
+
description: 'Vista compacta (un commit por línea)'
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
flag: '-n 5',
|
|
12
|
+
description: 'Mostrar solo los últimos N commits'
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
flag: '--graph',
|
|
16
|
+
description: 'Muestra un gráfico ASCII de las ramas'
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
flag: '--author="nombre"',
|
|
20
|
+
description: 'Filtrar commits por autor'
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
examples: [
|
|
24
|
+
{
|
|
25
|
+
command: 'git log',
|
|
26
|
+
description: 'Ver historial completo de commits'
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
command: 'git log --oneline',
|
|
30
|
+
description: 'Vista compacta (más legible)'
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
command: 'git log --oneline -10',
|
|
34
|
+
description: 'Solo los últimos 10 commits'
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
command: 'git log --graph --oneline',
|
|
38
|
+
description: 'Ver gráfico de ramas con commits'
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
relatedLesson: 'Git básico',
|
|
42
|
+
tips: [
|
|
43
|
+
'Presiona "q" para salir de git log',
|
|
44
|
+
'git log --oneline es el más útil para ver historial rápido',
|
|
45
|
+
'Combina con grep: git log --oneline | grep "fix"'
|
|
46
|
+
]
|
|
47
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export const gitPush = {
|
|
2
|
+
command: 'git push',
|
|
3
|
+
description: 'Envía tus commits locales al repositorio remoto (GitHub, etc.)',
|
|
4
|
+
usage: 'git push [remoto] [rama]',
|
|
5
|
+
commonOptions: [
|
|
6
|
+
{
|
|
7
|
+
flag: '-u origin main',
|
|
8
|
+
description: 'Primera vez: establece tracking entre rama local y remota'
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
flag: '--force',
|
|
12
|
+
description: '⚠️ PELIGROSO: fuerza el push (sobrescribe historial remoto)'
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
examples: [
|
|
16
|
+
{
|
|
17
|
+
command: 'git push',
|
|
18
|
+
description: 'Enviar commits al remoto (si ya hay tracking configurado)'
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
command: 'git push -u origin main',
|
|
22
|
+
description: 'Primera vez: conectar rama local main con origin/main'
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
command: 'git push origin feature-branch',
|
|
26
|
+
description: 'Push de una rama específica'
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
relatedLesson: 'Git colaboración',
|
|
30
|
+
tips: [
|
|
31
|
+
'Primero commit local, luego push al remoto',
|
|
32
|
+
'Si da error: probablemente necesitas hacer git pull primero',
|
|
33
|
+
'NUNCA uses --force en main/master a menos que sepas exactamente qué haces'
|
|
34
|
+
]
|
|
35
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export const gitStatus = {
|
|
2
|
+
command: 'git status',
|
|
3
|
+
description: 'Muestra el estado actual de tu repositorio (archivos modificados, staging, branch)',
|
|
4
|
+
usage: 'git status',
|
|
5
|
+
commonOptions: [
|
|
6
|
+
{
|
|
7
|
+
flag: '-s',
|
|
8
|
+
description: 'Formato corto (short) - vista compacta'
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
flag: '-b',
|
|
12
|
+
description: 'Muestra la rama actual'
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
examples: [
|
|
16
|
+
{
|
|
17
|
+
command: 'git status',
|
|
18
|
+
description: 'Ver todos los cambios y archivos sin seguimiento'
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
command: 'git status -s',
|
|
22
|
+
description: 'Vista compacta (M = modificado, A = agregado, ?? = sin seguimiento)'
|
|
23
|
+
}
|
|
24
|
+
],
|
|
25
|
+
relatedLesson: 'Git básico',
|
|
26
|
+
tips: [
|
|
27
|
+
'Ejecuta git status SIEMPRE antes de hacer commit',
|
|
28
|
+
'Te dice en qué branch estás y qué cambios tienes',
|
|
29
|
+
'Rojo = cambios sin agregar, Verde = cambios en staging listos para commit'
|
|
30
|
+
]
|
|
31
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Basic commands
|
|
2
|
+
export { ls } from './ls.js'
|
|
3
|
+
export { cd } from './cd.js'
|
|
4
|
+
export { mkdir } from './mkdir.js'
|
|
5
|
+
export { touch } from './touch.js'
|
|
6
|
+
export { wc } from './wc.js'
|
|
7
|
+
|
|
8
|
+
// Git commands
|
|
9
|
+
export { gitStatus } from './git-status.js'
|
|
10
|
+
export { gitAdd } from './git-add.js'
|
|
11
|
+
export { gitCommit } from './git-commit.js'
|
|
12
|
+
export { gitPush } from './git-push.js'
|
|
13
|
+
export { gitLog } from './git-log.js'
|
|
14
|
+
|
|
15
|
+
// Command mapping for lookup
|
|
16
|
+
export const commandMap = {
|
|
17
|
+
// Basic
|
|
18
|
+
'ls': 'ls',
|
|
19
|
+
'cd': 'cd',
|
|
20
|
+
'mkdir': 'mkdir',
|
|
21
|
+
'touch': 'touch',
|
|
22
|
+
'wc': 'wc',
|
|
23
|
+
|
|
24
|
+
// Git
|
|
25
|
+
'git status': 'gitStatus',
|
|
26
|
+
'git add': 'gitAdd',
|
|
27
|
+
'git commit': 'gitCommit',
|
|
28
|
+
'git push': 'gitPush',
|
|
29
|
+
'git log': 'gitLog'
|
|
30
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export const ls = {
|
|
2
|
+
command: 'ls',
|
|
3
|
+
description: 'Lista archivos y carpetas en el directorio actual',
|
|
4
|
+
usage: 'ls [opciones] [directorio]',
|
|
5
|
+
commonOptions: [
|
|
6
|
+
{
|
|
7
|
+
flag: '-l',
|
|
8
|
+
description: 'Formato largo (permisos, tamaño, fecha)'
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
flag: '-a',
|
|
12
|
+
description: 'Muestra archivos ocultos (.files)'
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
flag: '-h',
|
|
16
|
+
description: 'Tamaños legibles (KB, MB, GB) - usar con -l'
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
flag: '-t',
|
|
20
|
+
description: 'Ordena por fecha de modificación (más reciente primero)'
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
flag: '-r',
|
|
24
|
+
description: 'Orden inverso'
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
examples: [
|
|
28
|
+
{
|
|
29
|
+
command: 'ls',
|
|
30
|
+
description: 'Ver archivos en directorio actual'
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
command: 'ls -la',
|
|
34
|
+
description: 'Ver TODO incluyendo ocultos en formato largo'
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
command: 'ls -lh',
|
|
38
|
+
description: 'Ver con tamaños legibles (1.2M en vez de 1234567)'
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
command: 'ls -lt',
|
|
42
|
+
description: 'Ver ordenado por fecha (archivos más recientes arriba)'
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
relatedLesson: 'Primeros comandos',
|
|
46
|
+
tips: [
|
|
47
|
+
'Pro tip: usa `ls -la` casi siempre para ver archivos ocultos como .git',
|
|
48
|
+
'Los archivos que empiezan con . están ocultos por defecto',
|
|
49
|
+
'Combina opciones: `ls -lath` = largo + todo + legible + por fecha'
|
|
50
|
+
]
|
|
51
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export const mkdir = {
|
|
2
|
+
command: 'mkdir',
|
|
3
|
+
description: 'Crea un nuevo directorio (carpeta)',
|
|
4
|
+
usage: 'mkdir [opciones] nombre_directorio',
|
|
5
|
+
commonOptions: [
|
|
6
|
+
{
|
|
7
|
+
flag: '-p',
|
|
8
|
+
description: 'Crea directorios padres si no existen'
|
|
9
|
+
}
|
|
10
|
+
],
|
|
11
|
+
examples: [
|
|
12
|
+
{
|
|
13
|
+
command: 'mkdir proyectos',
|
|
14
|
+
description: 'Crear carpeta llamada "proyectos"'
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
command: 'mkdir -p proyectos/frontend/components',
|
|
18
|
+
description: 'Crear estructura completa de carpetas'
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
command: 'mkdir proyecto-1 proyecto-2',
|
|
22
|
+
description: 'Crear múltiples carpetas a la vez'
|
|
23
|
+
}
|
|
24
|
+
],
|
|
25
|
+
relatedLesson: 'Primeros comandos',
|
|
26
|
+
tips: [
|
|
27
|
+
'Usa -p para crear carpetas anidadas sin errores',
|
|
28
|
+
'Los nombres con espacios necesitan comillas: mkdir "Mi Proyecto"',
|
|
29
|
+
'Convención: usa guiones (-) en vez de espacios en nombres'
|
|
30
|
+
]
|
|
31
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export const touch = {
|
|
2
|
+
command: 'touch',
|
|
3
|
+
description: 'Crea un archivo vacío o actualiza su fecha de modificación',
|
|
4
|
+
usage: 'touch nombre_archivo',
|
|
5
|
+
commonOptions: [],
|
|
6
|
+
examples: [
|
|
7
|
+
{
|
|
8
|
+
command: 'touch index.js',
|
|
9
|
+
description: 'Crear archivo index.js vacío'
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
command: 'touch style.css script.js',
|
|
13
|
+
description: 'Crear múltiples archivos a la vez'
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
command: 'touch src/components/Header.svelte',
|
|
17
|
+
description: 'Crear archivo en una ruta específica'
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
relatedLesson: 'Primeros comandos',
|
|
21
|
+
tips: [
|
|
22
|
+
'Si el archivo ya existe, touch solo actualiza su fecha (no lo modifica)',
|
|
23
|
+
'Útil para crear archivos rápidamente antes de editarlos',
|
|
24
|
+
'Para crear carpetas usa mkdir, no touch'
|
|
25
|
+
]
|
|
26
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export const wc = {
|
|
2
|
+
command: 'wc',
|
|
3
|
+
description: 'Cuenta líneas, palabras y caracteres en archivos (Word Count)',
|
|
4
|
+
usage: 'wc [opciones] archivo',
|
|
5
|
+
commonOptions: [
|
|
6
|
+
{
|
|
7
|
+
flag: '-l',
|
|
8
|
+
description: 'Solo contar líneas'
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
flag: '-w',
|
|
12
|
+
description: 'Solo contar palabras'
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
flag: '-c',
|
|
16
|
+
description: 'Solo contar caracteres (bytes)'
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
examples: [
|
|
20
|
+
{
|
|
21
|
+
command: 'wc archivo.txt',
|
|
22
|
+
description: 'Contar líneas, palabras y caracteres'
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
command: 'wc -l archivo.txt',
|
|
26
|
+
description: 'Solo contar cuántas líneas tiene el archivo'
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
command: 'ls | wc -l',
|
|
30
|
+
description: 'Contar cuántos archivos hay en el directorio'
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
command: 'wc -l *.js',
|
|
34
|
+
description: 'Contar líneas de todos los archivos .js'
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
relatedLesson: 'Piping y redirección',
|
|
38
|
+
tips: [
|
|
39
|
+
'Muy útil con pipes para contar resultados',
|
|
40
|
+
'Ejemplo: git log --oneline | wc -l = contar commits',
|
|
41
|
+
'Puedes usar wc con múltiples archivos para ver totales'
|
|
42
|
+
]
|
|
43
|
+
}
|
package/lib/data/messages.js
CHANGED
|
@@ -11,17 +11,29 @@ Salgamos de este laberinto 🏛️
|
|
|
11
11
|
|
|
12
12
|
export const HELP_TEXT = `
|
|
13
13
|
📚 Comandos disponibles:
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
|
|
15
|
+
🎓 Aprendizaje:
|
|
16
|
+
creta - Menú principal (recomendado para empezar)
|
|
17
|
+
creta sintaxis - Aprende terminal, Git, piping y scripts (¡con práctica interactiva!) 💻
|
|
18
|
+
creta enunciados - Explora los 7 enunciados fundamentales (conceptos OOP) 🧠
|
|
19
|
+
creta proyectos - Ver proyectos disponibles
|
|
20
|
+
|
|
21
|
+
🚀 Portafolios:
|
|
16
22
|
creta portafolio - Crea tu portafolio personal (reto completo)
|
|
17
23
|
creta portafolio-1 - Desbloquea nivel 1 (navbar) 🔓
|
|
18
24
|
creta portafolio-2 - Desbloquea nivel 2 (navbar + hero) 🔓
|
|
19
25
|
creta portafolio-3 - Desbloquea nivel 3 (solución completa) 🔓
|
|
26
|
+
|
|
27
|
+
🛠️ Utilidades:
|
|
20
28
|
creta code - Inicia sesión interactiva de programación 🤖
|
|
29
|
+
creta reset - Reinicia tu estado de usuario (nombre, progreso) 🗑️
|
|
30
|
+
creta icarus-terminal - Personaliza tu terminal con tema de Icarus
|
|
31
|
+
creta revert-terminal - Revertir personalización de terminal
|
|
21
32
|
creta help - Muestra esta ayuda
|
|
22
33
|
|
|
23
|
-
|
|
24
|
-
|
|
34
|
+
💾 Datos locales:
|
|
35
|
+
~/.creta/user.json - Tu perfil (usa 'creta reset' para borrar)
|
|
36
|
+
/tmp/creta-practice-* - Sandboxes temporales (limpieza automática)
|
|
25
37
|
|
|
26
38
|
🎯 La filosofía Creta: partir de enunciados que generan 'ruido' para
|
|
27
39
|
construir comprensión real, no solo sintaxis.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import chalk from 'chalk'
|
|
2
|
+
import * as commandHelp from '../data/command-help/index.js'
|
|
3
|
+
|
|
4
|
+
export class CommandHelpExecutor {
|
|
5
|
+
constructor(commandArgs) {
|
|
6
|
+
this.commandArgs = commandArgs // e.g., ['ls'] or ['git', 'status']
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
async execute() {
|
|
10
|
+
const commandKey = this.commandArgs.join(' ')
|
|
11
|
+
const helpDataKey = commandHelp.commandMap[commandKey]
|
|
12
|
+
|
|
13
|
+
if (!helpDataKey) {
|
|
14
|
+
this.showNotFound(commandKey)
|
|
15
|
+
return
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const helpData = commandHelp[helpDataKey]
|
|
19
|
+
this.renderHelp(helpData)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
renderHelp(data) {
|
|
23
|
+
console.log('')
|
|
24
|
+
console.log(chalk.bold.cyan(`📘 ${data.command}`))
|
|
25
|
+
console.log(chalk.dim('─'.repeat(60)))
|
|
26
|
+
console.log('')
|
|
27
|
+
|
|
28
|
+
// Description
|
|
29
|
+
console.log(chalk.white(data.description))
|
|
30
|
+
console.log('')
|
|
31
|
+
|
|
32
|
+
// Usage
|
|
33
|
+
console.log(chalk.bold('Uso:'))
|
|
34
|
+
console.log(chalk.yellow(` ${data.usage}`))
|
|
35
|
+
console.log('')
|
|
36
|
+
|
|
37
|
+
// Common Options
|
|
38
|
+
if (data.commonOptions && data.commonOptions.length > 0) {
|
|
39
|
+
console.log(chalk.bold('Opciones comunes:'))
|
|
40
|
+
data.commonOptions.forEach(opt => {
|
|
41
|
+
console.log(chalk.cyan(` ${opt.flag}`))
|
|
42
|
+
console.log(chalk.dim(` ${opt.description}`))
|
|
43
|
+
})
|
|
44
|
+
console.log('')
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Examples
|
|
48
|
+
if (data.examples && data.examples.length > 0) {
|
|
49
|
+
console.log(chalk.bold('Ejemplos:'))
|
|
50
|
+
data.examples.forEach(ex => {
|
|
51
|
+
console.log(chalk.green(` $ ${ex.command}`))
|
|
52
|
+
console.log(chalk.dim(` ${ex.description}`))
|
|
53
|
+
console.log('')
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Tips
|
|
58
|
+
if (data.tips && data.tips.length > 0) {
|
|
59
|
+
console.log(chalk.bold.yellow('💡 Tips:'))
|
|
60
|
+
data.tips.forEach(tip => {
|
|
61
|
+
console.log(chalk.yellow(` • ${tip}`))
|
|
62
|
+
})
|
|
63
|
+
console.log('')
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Related Lesson
|
|
67
|
+
if (data.relatedLesson) {
|
|
68
|
+
console.log(chalk.dim(`📚 Lección relacionada: ${data.relatedLesson}`))
|
|
69
|
+
console.log(chalk.dim(` Ejecuta: creta sintaxis`))
|
|
70
|
+
console.log('')
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
showNotFound(commandKey) {
|
|
75
|
+
console.log('')
|
|
76
|
+
console.log(chalk.red(`❌ No tenemos ayuda para: ${chalk.bold(commandKey)}`))
|
|
77
|
+
console.log('')
|
|
78
|
+
console.log(chalk.dim('Comandos disponibles:'))
|
|
79
|
+
console.log('')
|
|
80
|
+
|
|
81
|
+
console.log(chalk.bold(' Básicos:'))
|
|
82
|
+
console.log(chalk.cyan(' ls, cd, mkdir, touch, wc'))
|
|
83
|
+
console.log('')
|
|
84
|
+
|
|
85
|
+
console.log(chalk.bold(' Git:'))
|
|
86
|
+
console.log(chalk.cyan(' git status, git add, git commit, git push, git log'))
|
|
87
|
+
console.log('')
|
|
88
|
+
|
|
89
|
+
console.log(chalk.dim('💡 Ejemplo: creta ls'))
|
|
90
|
+
console.log(chalk.dim('💡 Ejemplo: creta git status'))
|
|
91
|
+
console.log('')
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import os from 'os'
|
|
4
|
+
|
|
5
|
+
export class AccessControl {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.userFilePath = path.join(os.homedir(), '.creta', 'user.json')
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
getUserData() {
|
|
11
|
+
try {
|
|
12
|
+
if (!fs.existsSync(this.userFilePath)) {
|
|
13
|
+
return this.getDefaultUser()
|
|
14
|
+
}
|
|
15
|
+
const data = fs.readFileSync(this.userFilePath, 'utf8')
|
|
16
|
+
return JSON.parse(data)
|
|
17
|
+
} catch (error) {
|
|
18
|
+
return this.getDefaultUser()
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
getDefaultUser() {
|
|
23
|
+
return {
|
|
24
|
+
name: 'guest',
|
|
25
|
+
lessonsCompleted: [],
|
|
26
|
+
projectsCreated: [],
|
|
27
|
+
papersCompleted: []
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Paper unlock requirements
|
|
32
|
+
getPaperRequirements() {
|
|
33
|
+
return {
|
|
34
|
+
'mapreduce': {
|
|
35
|
+
name: 'MapReduce (2004)',
|
|
36
|
+
description: 'Procesamiento de datos en paralelo',
|
|
37
|
+
requirement: 'Completa 3+ lecciones de sintaxis',
|
|
38
|
+
check: (user) => {
|
|
39
|
+
const sintaxisLessons = user.lessonsCompleted.filter(l =>
|
|
40
|
+
l.id && l.id.includes('sintaxis')
|
|
41
|
+
).length
|
|
42
|
+
return sintaxisLessons >= 3
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
'bitcoin': {
|
|
46
|
+
name: 'Bitcoin (2008)',
|
|
47
|
+
description: 'Blockchain y consenso descentralizado',
|
|
48
|
+
requirement: 'Completa MapReduce + 1 proyecto',
|
|
49
|
+
check: (user) => {
|
|
50
|
+
const hasMapReduce = user.papersCompleted?.some(p => p.id === 'mapreduce')
|
|
51
|
+
const hasProject = user.projectsCreated.length >= 1
|
|
52
|
+
return hasMapReduce && hasProject
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
'spark': {
|
|
56
|
+
name: 'Spark (2010)',
|
|
57
|
+
description: 'MapReduce en memoria (RDDs)',
|
|
58
|
+
requirement: 'Completa MapReduce + Bitcoin',
|
|
59
|
+
check: (user) => {
|
|
60
|
+
const hasMapReduce = user.papersCompleted?.some(p => p.id === 'mapreduce')
|
|
61
|
+
const hasBitcoin = user.papersCompleted?.some(p => p.id === 'bitcoin')
|
|
62
|
+
return hasMapReduce && hasBitcoin
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
isUnlocked(paperId) {
|
|
69
|
+
const user = this.getUserData()
|
|
70
|
+
const requirements = this.getPaperRequirements()
|
|
71
|
+
const paper = requirements[paperId]
|
|
72
|
+
|
|
73
|
+
if (!paper) return false
|
|
74
|
+
|
|
75
|
+
return paper.check(user)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
getAvailablePapers() {
|
|
79
|
+
const user = this.getUserData()
|
|
80
|
+
const requirements = this.getPaperRequirements()
|
|
81
|
+
|
|
82
|
+
return Object.keys(requirements).map(paperId => ({
|
|
83
|
+
id: paperId,
|
|
84
|
+
...requirements[paperId],
|
|
85
|
+
unlocked: requirements[paperId].check(user),
|
|
86
|
+
completed: user.papersCompleted?.some(p => p.id === paperId) || false
|
|
87
|
+
}))
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
markPaperCompleted(paperId) {
|
|
91
|
+
const user = this.getUserData()
|
|
92
|
+
|
|
93
|
+
// Initialize papersCompleted if it doesn't exist
|
|
94
|
+
if (!user.papersCompleted) {
|
|
95
|
+
user.papersCompleted = []
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Check if already completed
|
|
99
|
+
const alreadyCompleted = user.papersCompleted.some(p => p.id === paperId)
|
|
100
|
+
if (alreadyCompleted) {
|
|
101
|
+
return
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Add completion record
|
|
105
|
+
user.papersCompleted.push({
|
|
106
|
+
id: paperId,
|
|
107
|
+
completedAt: new Date().toISOString()
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
// Save to file
|
|
111
|
+
try {
|
|
112
|
+
const dir = path.dirname(this.userFilePath)
|
|
113
|
+
if (!fs.existsSync(dir)) {
|
|
114
|
+
fs.mkdirSync(dir, { recursive: true })
|
|
115
|
+
}
|
|
116
|
+
fs.writeFileSync(this.userFilePath, JSON.stringify(user, null, 2))
|
|
117
|
+
} catch (error) {
|
|
118
|
+
console.error('Error saving user progress:', error.message)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|