@icarusmx/creta 0.7.3 → 0.8.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/bin/creta.js +339 -16
- package/package.json +1 -1
package/bin/creta.js
CHANGED
|
@@ -49,12 +49,13 @@ const ENUNCIADOS = [
|
|
|
49
49
|
const args = process.argv.slice(2)
|
|
50
50
|
const command = args[0]
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
console.log("
|
|
52
|
+
// Welcome message
|
|
53
|
+
console.log("🏛️ Bienvenido a Creta")
|
|
54
|
+
console.log("La escuela de software de icarus.mx\n")
|
|
54
55
|
|
|
55
56
|
if (!command) {
|
|
56
|
-
// Default behavior: show
|
|
57
|
-
await
|
|
57
|
+
// Default behavior: show main menu
|
|
58
|
+
await startMainMenu()
|
|
58
59
|
process.exit(0)
|
|
59
60
|
}
|
|
60
61
|
|
|
@@ -578,6 +579,157 @@ function showHelp() {
|
|
|
578
579
|
console.log(" construir comprensión real, no solo sintaxis.")
|
|
579
580
|
}
|
|
580
581
|
|
|
582
|
+
async function startMainMenu() {
|
|
583
|
+
// Always try interactive mode first, fall back only if it fails
|
|
584
|
+
try {
|
|
585
|
+
return await startMainMenuInteractive()
|
|
586
|
+
} catch (error) {
|
|
587
|
+
// If interactive mode fails, fall back to numbered selection
|
|
588
|
+
console.log('\nModo interactivo no disponible, usando selección numérica...\n')
|
|
589
|
+
return await startMainMenuFallback()
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
async function startMainMenuInteractive() {
|
|
594
|
+
// Check if setRawMode is available before trying to use it
|
|
595
|
+
if (typeof process.stdin.setRawMode !== 'function') {
|
|
596
|
+
throw new Error('setRawMode not available')
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
console.log("Te ofrecemos las siguientes opciones")
|
|
600
|
+
console.log("Usa ↑/↓ para navegar, Enter para seleccionar, 'q' para salir\n")
|
|
601
|
+
|
|
602
|
+
const options = [
|
|
603
|
+
{ id: 1, title: "🧠 Aprender conceptos", description: "Explora los enunciados fundamentales" },
|
|
604
|
+
{ id: 2, title: "🚀 Construir proyectos", description: "Crea tu portafolio personal" }
|
|
605
|
+
]
|
|
606
|
+
|
|
607
|
+
let selectedIndex = 0
|
|
608
|
+
|
|
609
|
+
// Enable raw mode to capture arrow keys
|
|
610
|
+
try {
|
|
611
|
+
process.stdin.setRawMode(true)
|
|
612
|
+
process.stdin.resume()
|
|
613
|
+
process.stdin.setEncoding('utf8')
|
|
614
|
+
} catch (error) {
|
|
615
|
+
throw new Error('Failed to enable raw mode: ' + error.message)
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
const renderOptions = () => {
|
|
619
|
+
// Clear previous output and move cursor to top
|
|
620
|
+
process.stdout.write('\x1b[2J')
|
|
621
|
+
process.stdout.write('\x1b[H')
|
|
622
|
+
|
|
623
|
+
console.log("🏛️ Bienvenido a Creta")
|
|
624
|
+
console.log("La escuela de software de icarus.mx\n")
|
|
625
|
+
console.log("Te ofrecemos las siguientes opciones")
|
|
626
|
+
console.log("Usa ↑/↓ para navegar, Enter para seleccionar, 'q' para salir\n")
|
|
627
|
+
|
|
628
|
+
options.forEach((option, index) => {
|
|
629
|
+
const isSelected = index === selectedIndex
|
|
630
|
+
const prefix = isSelected ? '▶ ' : ' '
|
|
631
|
+
const highlight = isSelected ? '\x1b[36m' : '\x1b[37m' // cyan for selected, white for normal
|
|
632
|
+
const reset = '\x1b[0m'
|
|
633
|
+
|
|
634
|
+
console.log(`${highlight}${prefix}${option.title}${reset}`)
|
|
635
|
+
if (isSelected) {
|
|
636
|
+
console.log(`${highlight} ${option.description}${reset}`)
|
|
637
|
+
}
|
|
638
|
+
console.log("")
|
|
639
|
+
})
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
return new Promise((resolve) => {
|
|
643
|
+
renderOptions()
|
|
644
|
+
|
|
645
|
+
const onKeyPress = (key) => {
|
|
646
|
+
if (key === 'q' || key === '\x03') { // q or Ctrl+C
|
|
647
|
+
process.stdin.setRawMode(false)
|
|
648
|
+
process.stdin.removeListener('data', onKeyPress)
|
|
649
|
+
console.log("\n¡Hasta la vista! 👋")
|
|
650
|
+
resolve()
|
|
651
|
+
return
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
if (key === '\r' || key === '\n') { // Enter
|
|
655
|
+
process.stdin.setRawMode(false)
|
|
656
|
+
process.stdin.removeListener('data', onKeyPress)
|
|
657
|
+
|
|
658
|
+
const selectedOption = options[selectedIndex]
|
|
659
|
+
|
|
660
|
+
// Clear screen
|
|
661
|
+
process.stdout.write('\x1b[2J')
|
|
662
|
+
process.stdout.write('\x1b[H')
|
|
663
|
+
|
|
664
|
+
if (selectedOption.id === 1) {
|
|
665
|
+
startEnunciadosSelector().then(resolve)
|
|
666
|
+
} else if (selectedOption.id === 2) {
|
|
667
|
+
startProyectosSelector().then(resolve)
|
|
668
|
+
}
|
|
669
|
+
return
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// Handle arrow keys (escape sequences)
|
|
673
|
+
if (key === '\u001b[A') { // Up arrow
|
|
674
|
+
selectedIndex = selectedIndex > 0 ? selectedIndex - 1 : options.length - 1
|
|
675
|
+
renderOptions()
|
|
676
|
+
} else if (key === '\u001b[B') { // Down arrow
|
|
677
|
+
selectedIndex = selectedIndex < options.length - 1 ? selectedIndex + 1 : 0
|
|
678
|
+
renderOptions()
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
process.stdin.on('data', onKeyPress)
|
|
683
|
+
})
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
async function startMainMenuFallback() {
|
|
687
|
+
const rl = createInterface({
|
|
688
|
+
input: process.stdin,
|
|
689
|
+
output: process.stdout
|
|
690
|
+
})
|
|
691
|
+
|
|
692
|
+
const askQuestion = (question) => {
|
|
693
|
+
return new Promise((resolve) => {
|
|
694
|
+
rl.question(question, resolve)
|
|
695
|
+
})
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
try {
|
|
699
|
+
console.log("Te ofrecemos las siguientes opciones")
|
|
700
|
+
console.log("")
|
|
701
|
+
console.log("1. 🧠 Aprender conceptos - Explora los enunciados fundamentales")
|
|
702
|
+
console.log("2. 🚀 Construir proyectos - Crea tu portafolio personal")
|
|
703
|
+
console.log("")
|
|
704
|
+
|
|
705
|
+
const respuesta = await askQuestion("Elige una opción (1-2) o 'q' para salir: ")
|
|
706
|
+
|
|
707
|
+
if (respuesta.toLowerCase() === 'q') {
|
|
708
|
+
console.log("¡Hasta la vista! 👋")
|
|
709
|
+
rl.close()
|
|
710
|
+
return
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
const opcionSeleccionada = parseInt(respuesta)
|
|
714
|
+
|
|
715
|
+
if (opcionSeleccionada === 1) {
|
|
716
|
+
rl.close()
|
|
717
|
+
await startEnunciadosSelector()
|
|
718
|
+
} else if (opcionSeleccionada === 2) {
|
|
719
|
+
rl.close()
|
|
720
|
+
await startProyectosSelector()
|
|
721
|
+
} else {
|
|
722
|
+
console.log("❌ Opción no válida. Elige 1 o 2.")
|
|
723
|
+
rl.close()
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
} catch (error) {
|
|
727
|
+
console.error('Error:', error.message)
|
|
728
|
+
rl.close()
|
|
729
|
+
process.exit(1)
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
|
|
581
733
|
async function startEnunciadosSelector() {
|
|
582
734
|
// Always try interactive mode first, fall back only if it fails
|
|
583
735
|
try {
|
|
@@ -590,27 +742,34 @@ async function startEnunciadosSelector() {
|
|
|
590
742
|
}
|
|
591
743
|
|
|
592
744
|
async function startEnunciadosSelectorInteractive() {
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
745
|
+
// Check if setRawMode is available before trying to use it
|
|
746
|
+
if (typeof process.stdin.setRawMode !== 'function') {
|
|
747
|
+
throw new Error('setRawMode not available')
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
console.log("\n🧠 Conceptos Fundamentales")
|
|
751
|
+
console.log("¿Cuáles de estos enunciados quieres explorar?")
|
|
596
752
|
console.log("Usa ↑/↓ para navegar, Enter para seleccionar, 'q' para salir\n")
|
|
597
753
|
|
|
598
754
|
let selectedIndex = 0
|
|
599
755
|
let running = true
|
|
600
756
|
|
|
601
757
|
// Enable raw mode to capture arrow keys
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
758
|
+
try {
|
|
759
|
+
process.stdin.setRawMode(true)
|
|
760
|
+
process.stdin.resume()
|
|
761
|
+
process.stdin.setEncoding('utf8')
|
|
762
|
+
} catch (error) {
|
|
763
|
+
throw new Error('Failed to enable raw mode: ' + error.message)
|
|
764
|
+
}
|
|
605
765
|
|
|
606
766
|
const renderOptions = () => {
|
|
607
767
|
// Clear previous output and move cursor to top
|
|
608
768
|
process.stdout.write('\x1b[2J')
|
|
609
769
|
process.stdout.write('\x1b[H')
|
|
610
770
|
|
|
611
|
-
console.log("🧠
|
|
612
|
-
console.log("
|
|
613
|
-
console.log("¿Cuál de estos enunciados te genera más 'ruido' (curiosidad/confusión)?")
|
|
771
|
+
console.log("🧠 Conceptos Fundamentales")
|
|
772
|
+
console.log("¿Cuáles de estos enunciados quieres explorar?")
|
|
614
773
|
console.log("Usa ↑/↓ para navegar, Enter para seleccionar, 'q' para salir\n")
|
|
615
774
|
|
|
616
775
|
ENUNCIADOS.forEach((enunciado, index) => {
|
|
@@ -710,9 +869,8 @@ async function startEnunciadosSelectorFallback() {
|
|
|
710
869
|
}
|
|
711
870
|
|
|
712
871
|
try {
|
|
713
|
-
console.log("\n🧠
|
|
714
|
-
console.log("
|
|
715
|
-
console.log("¿Cuál de estos enunciados te genera más 'ruido' (curiosidad/confusión)?")
|
|
872
|
+
console.log("\n🧠 Conceptos Fundamentales")
|
|
873
|
+
console.log("¿Cuáles de estos enunciados quieres explorar?")
|
|
716
874
|
console.log("")
|
|
717
875
|
|
|
718
876
|
ENUNCIADOS.forEach((enunciado, index) => {
|
|
@@ -758,3 +916,168 @@ async function startEnunciadosSelectorFallback() {
|
|
|
758
916
|
process.exit(1)
|
|
759
917
|
}
|
|
760
918
|
}
|
|
919
|
+
|
|
920
|
+
|
|
921
|
+
async function startProyectosSelector() {
|
|
922
|
+
// Always try interactive mode first, fall back only if it fails
|
|
923
|
+
try {
|
|
924
|
+
return await startProyectosSelectorInteractive()
|
|
925
|
+
} catch (error) {
|
|
926
|
+
// If interactive mode fails, fall back to numbered selection
|
|
927
|
+
console.log('\nModo interactivo no disponible, usando selección numérica...\n')
|
|
928
|
+
return await startProyectosSelectorFallback()
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
async function startProyectosSelectorInteractive() {
|
|
933
|
+
// Check if setRawMode is available before trying to use it
|
|
934
|
+
if (typeof process.stdin.setRawMode !== 'function') {
|
|
935
|
+
throw new Error('setRawMode not available')
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
console.log("\n🚀 Proyectos Disponibles")
|
|
939
|
+
console.log("¿Qué proyecto quieres crear?")
|
|
940
|
+
console.log("Usa ↑/↓ para navegar, Enter para seleccionar, 'q' para salir\n")
|
|
941
|
+
|
|
942
|
+
const projects = [
|
|
943
|
+
{ id: 1, title: "🎨 Portafolio Personal", description: "Reto completo", level: 0 },
|
|
944
|
+
{ id: 2, title: "🔓 Portafolio Nivel 1", description: "Solo navbar", level: 1 },
|
|
945
|
+
{ id: 3, title: "🔓 Portafolio Nivel 2", description: "Navbar + hero", level: 2 },
|
|
946
|
+
{ id: 4, title: "🔓 Portafolio Nivel 3", description: "Solución completa", level: 3 }
|
|
947
|
+
]
|
|
948
|
+
|
|
949
|
+
let selectedIndex = 0
|
|
950
|
+
|
|
951
|
+
// Enable raw mode to capture arrow keys
|
|
952
|
+
try {
|
|
953
|
+
process.stdin.setRawMode(true)
|
|
954
|
+
process.stdin.resume()
|
|
955
|
+
process.stdin.setEncoding('utf8')
|
|
956
|
+
} catch (error) {
|
|
957
|
+
throw new Error('Failed to enable raw mode: ' + error.message)
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
const renderOptions = () => {
|
|
961
|
+
// Clear previous output and move cursor to top
|
|
962
|
+
process.stdout.write('\x1b[2J')
|
|
963
|
+
process.stdout.write('\x1b[H')
|
|
964
|
+
|
|
965
|
+
console.log("🚀 Proyectos Disponibles")
|
|
966
|
+
console.log("¿Qué proyecto quieres crear?")
|
|
967
|
+
console.log("Usa ↑/↓ para navegar, Enter para seleccionar, 'q' para salir\n")
|
|
968
|
+
|
|
969
|
+
projects.forEach((project, index) => {
|
|
970
|
+
const isSelected = index === selectedIndex
|
|
971
|
+
const prefix = isSelected ? '▶ ' : ' '
|
|
972
|
+
const highlight = isSelected ? '\x1b[36m' : '\x1b[37m' // cyan for selected, white for normal
|
|
973
|
+
const reset = '\x1b[0m'
|
|
974
|
+
|
|
975
|
+
console.log(`${highlight}${prefix}${project.title}${reset}`)
|
|
976
|
+
if (isSelected) {
|
|
977
|
+
console.log(`${highlight} ${project.description}${reset}`)
|
|
978
|
+
}
|
|
979
|
+
console.log("")
|
|
980
|
+
})
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
return new Promise((resolve) => {
|
|
984
|
+
renderOptions()
|
|
985
|
+
|
|
986
|
+
const onKeyPress = (key) => {
|
|
987
|
+
if (key === 'q' || key === '\x03') { // q or Ctrl+C
|
|
988
|
+
process.stdin.setRawMode(false)
|
|
989
|
+
process.stdin.removeListener('data', onKeyPress)
|
|
990
|
+
console.log("\n¡Hasta la vista! 👋")
|
|
991
|
+
resolve()
|
|
992
|
+
return
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
if (key === '\r' || key === '\n') { // Enter
|
|
996
|
+
process.stdin.setRawMode(false)
|
|
997
|
+
process.stdin.removeListener('data', onKeyPress)
|
|
998
|
+
|
|
999
|
+
const selectedProject = projects[selectedIndex]
|
|
1000
|
+
const level = selectedProject.level
|
|
1001
|
+
|
|
1002
|
+
// Clear screen
|
|
1003
|
+
process.stdout.write('\x1b[2J')
|
|
1004
|
+
process.stdout.write('\x1b[H')
|
|
1005
|
+
|
|
1006
|
+
// Check if we're in an existing Creta project
|
|
1007
|
+
if (level > 0 && isInCretaProject()) {
|
|
1008
|
+
unstuckProject(level).then(resolve)
|
|
1009
|
+
} else {
|
|
1010
|
+
createPortfolioProject(level).then(resolve)
|
|
1011
|
+
}
|
|
1012
|
+
return
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
// Handle arrow keys (escape sequences)
|
|
1016
|
+
if (key === '\u001b[A') { // Up arrow
|
|
1017
|
+
selectedIndex = selectedIndex > 0 ? selectedIndex - 1 : projects.length - 1
|
|
1018
|
+
renderOptions()
|
|
1019
|
+
} else if (key === '\u001b[B') { // Down arrow
|
|
1020
|
+
selectedIndex = selectedIndex < projects.length - 1 ? selectedIndex + 1 : 0
|
|
1021
|
+
renderOptions()
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
process.stdin.on('data', onKeyPress)
|
|
1026
|
+
})
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
async function startProyectosSelectorFallback() {
|
|
1030
|
+
const rl = createInterface({
|
|
1031
|
+
input: process.stdin,
|
|
1032
|
+
output: process.stdout
|
|
1033
|
+
})
|
|
1034
|
+
|
|
1035
|
+
const askQuestion = (question) => {
|
|
1036
|
+
return new Promise((resolve) => {
|
|
1037
|
+
rl.question(question, resolve)
|
|
1038
|
+
})
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
try {
|
|
1042
|
+
console.log("\n🚀 Proyectos Disponibles")
|
|
1043
|
+
console.log("¿Qué proyecto quieres crear?")
|
|
1044
|
+
console.log("")
|
|
1045
|
+
console.log("1. 🎨 Portafolio Personal - Reto completo")
|
|
1046
|
+
console.log("2. 🔓 Portafolio Nivel 1 - Solo navbar")
|
|
1047
|
+
console.log("3. 🔓 Portafolio Nivel 2 - Navbar + hero")
|
|
1048
|
+
console.log("4. 🔓 Portafolio Nivel 3 - Solución completa")
|
|
1049
|
+
console.log("")
|
|
1050
|
+
|
|
1051
|
+
const respuesta = await askQuestion("Elige una opción (1-4) o 'q' para salir: ")
|
|
1052
|
+
|
|
1053
|
+
if (respuesta.toLowerCase() === 'q') {
|
|
1054
|
+
console.log("¡Hasta la vista! 👋")
|
|
1055
|
+
rl.close()
|
|
1056
|
+
return
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
const opcionSeleccionada = parseInt(respuesta)
|
|
1060
|
+
|
|
1061
|
+
if (opcionSeleccionada >= 1 && opcionSeleccionada <= 4) {
|
|
1062
|
+
rl.close()
|
|
1063
|
+
|
|
1064
|
+
// Map selection to portfolio level
|
|
1065
|
+
const level = opcionSeleccionada === 1 ? 0 : opcionSeleccionada - 1
|
|
1066
|
+
|
|
1067
|
+
// Check if we're in an existing Creta project
|
|
1068
|
+
if (level > 0 && isInCretaProject()) {
|
|
1069
|
+
await unstuckProject(level)
|
|
1070
|
+
} else {
|
|
1071
|
+
await createPortfolioProject(level)
|
|
1072
|
+
}
|
|
1073
|
+
} else {
|
|
1074
|
+
console.log("❌ Opción no válida. Elige un número entre 1 y 4.")
|
|
1075
|
+
rl.close()
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
} catch (error) {
|
|
1079
|
+
console.error('Error:', error.message)
|
|
1080
|
+
rl.close()
|
|
1081
|
+
process.exit(1)
|
|
1082
|
+
}
|
|
1083
|
+
}
|