@icarusmx/creta 0.8.0 → 0.8.2

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.
@@ -6,7 +6,8 @@
6
6
  "WebFetch(domain:github.com)",
7
7
  "Bash(npm install)",
8
8
  "Bash(npm run dev:*)",
9
- "Bash(rm:*)"
9
+ "Bash(rm:*)",
10
+ "Bash(npm publish:*)"
10
11
  ],
11
12
  "deny": [],
12
13
  "ask": []
package/bin/creta.js CHANGED
@@ -580,6 +580,110 @@ function showHelp() {
580
580
  }
581
581
 
582
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() {
583
687
  const rl = createInterface({
584
688
  input: process.stdin,
585
689
  output: process.stdout
@@ -592,10 +696,10 @@ async function startMainMenu() {
592
696
  }
593
697
 
594
698
  try {
595
- console.log("¿Qué quieres hacer hoy?")
699
+ console.log("Te ofrecemos las siguientes opciones")
596
700
  console.log("")
597
- console.log("1. 🧠 Conceptos - Explora los enunciados fundamentales")
598
- console.log("2. 🚀 Proyectos - Crea tu portafolio personal")
701
+ console.log("1. 🧠 Aprender conceptos - Explora los enunciados fundamentales")
702
+ console.log("2. 🚀 Construir proyectos - Crea tu portafolio personal")
599
703
  console.log("")
600
704
 
601
705
  const respuesta = await askQuestion("Elige una opción (1-2) o 'q' para salir: ")
@@ -674,27 +778,7 @@ async function startEnunciadosSelectorInteractive() {
674
778
  const highlight = isSelected ? '\x1b[36m' : '\x1b[37m' // cyan for selected, white for normal
675
779
  const reset = '\x1b[0m'
676
780
 
677
- console.log(`${highlight}${prefix}${index + 1}. [${enunciado.nivel}] ${enunciado.enfoque}${reset}`)
678
-
679
- if (isSelected) {
680
- // Show full text for selected option with word wrapping
681
- const maxWidth = 66
682
- const words = enunciado.texto.split(' ')
683
- let currentLine = ' "'
684
-
685
- words.forEach(word => {
686
- if (currentLine.length + word.length + 1 <= maxWidth) {
687
- currentLine += (currentLine === ' "' ? '' : ' ') + word
688
- } else {
689
- console.log(`${highlight}${currentLine}${reset}`)
690
- currentLine = ' ' + word
691
- }
692
- })
693
-
694
- if (currentLine.length > 6) {
695
- console.log(`${highlight}${currentLine}"${reset}`)
696
- }
697
- }
781
+ console.log(`${highlight}${prefix}${index + 1}. ${enunciado.texto}${reset}`)
698
782
  console.log("")
699
783
  })
700
784
  }
@@ -770,8 +854,7 @@ async function startEnunciadosSelectorFallback() {
770
854
  console.log("")
771
855
 
772
856
  ENUNCIADOS.forEach((enunciado, index) => {
773
- console.log(`${index + 1}. [${enunciado.nivel}] ${enunciado.enfoque}`)
774
- console.log(` "${enunciado.texto}"`)
857
+ console.log(`${index + 1}. ${enunciado.texto}`)
775
858
  console.log("")
776
859
  })
777
860
 
@@ -815,6 +898,114 @@ async function startEnunciadosSelectorFallback() {
815
898
 
816
899
 
817
900
  async function startProyectosSelector() {
901
+ // Always try interactive mode first, fall back only if it fails
902
+ try {
903
+ return await startProyectosSelectorInteractive()
904
+ } catch (error) {
905
+ // If interactive mode fails, fall back to numbered selection
906
+ console.log('\nModo interactivo no disponible, usando selección numérica...\n')
907
+ return await startProyectosSelectorFallback()
908
+ }
909
+ }
910
+
911
+ async function startProyectosSelectorInteractive() {
912
+ // Check if setRawMode is available before trying to use it
913
+ if (typeof process.stdin.setRawMode !== 'function') {
914
+ throw new Error('setRawMode not available')
915
+ }
916
+
917
+ console.log("\n🚀 Proyectos Disponibles")
918
+ console.log("¿Qué proyecto quieres crear?")
919
+ console.log("Usa ↑/↓ para navegar, Enter para seleccionar, 'q' para salir\n")
920
+
921
+ const projects = [
922
+ { id: 1, title: "🎨 Portafolio Personal", description: "Reto completo", level: 0 },
923
+ { id: 2, title: "🔓 Portafolio Nivel 1", description: "Solo navbar", level: 1 },
924
+ { id: 3, title: "🔓 Portafolio Nivel 2", description: "Navbar + hero", level: 2 },
925
+ { id: 4, title: "🔓 Portafolio Nivel 3", description: "Solución completa", level: 3 }
926
+ ]
927
+
928
+ let selectedIndex = 0
929
+
930
+ // Enable raw mode to capture arrow keys
931
+ try {
932
+ process.stdin.setRawMode(true)
933
+ process.stdin.resume()
934
+ process.stdin.setEncoding('utf8')
935
+ } catch (error) {
936
+ throw new Error('Failed to enable raw mode: ' + error.message)
937
+ }
938
+
939
+ const renderOptions = () => {
940
+ // Clear previous output and move cursor to top
941
+ process.stdout.write('\x1b[2J')
942
+ process.stdout.write('\x1b[H')
943
+
944
+ console.log("🚀 Proyectos Disponibles")
945
+ console.log("¿Qué proyecto quieres crear?")
946
+ console.log("Usa ↑/↓ para navegar, Enter para seleccionar, 'q' para salir\n")
947
+
948
+ projects.forEach((project, index) => {
949
+ const isSelected = index === selectedIndex
950
+ const prefix = isSelected ? '▶ ' : ' '
951
+ const highlight = isSelected ? '\x1b[36m' : '\x1b[37m' // cyan for selected, white for normal
952
+ const reset = '\x1b[0m'
953
+
954
+ console.log(`${highlight}${prefix}${project.title}${reset}`)
955
+ if (isSelected) {
956
+ console.log(`${highlight} ${project.description}${reset}`)
957
+ }
958
+ console.log("")
959
+ })
960
+ }
961
+
962
+ return new Promise((resolve) => {
963
+ renderOptions()
964
+
965
+ const onKeyPress = (key) => {
966
+ if (key === 'q' || key === '\x03') { // q or Ctrl+C
967
+ process.stdin.setRawMode(false)
968
+ process.stdin.removeListener('data', onKeyPress)
969
+ console.log("\n¡Hasta la vista! 👋")
970
+ resolve()
971
+ return
972
+ }
973
+
974
+ if (key === '\r' || key === '\n') { // Enter
975
+ process.stdin.setRawMode(false)
976
+ process.stdin.removeListener('data', onKeyPress)
977
+
978
+ const selectedProject = projects[selectedIndex]
979
+ const level = selectedProject.level
980
+
981
+ // Clear screen
982
+ process.stdout.write('\x1b[2J')
983
+ process.stdout.write('\x1b[H')
984
+
985
+ // Check if we're in an existing Creta project
986
+ if (level > 0 && isInCretaProject()) {
987
+ unstuckProject(level).then(resolve)
988
+ } else {
989
+ createPortfolioProject(level).then(resolve)
990
+ }
991
+ return
992
+ }
993
+
994
+ // Handle arrow keys (escape sequences)
995
+ if (key === '\u001b[A') { // Up arrow
996
+ selectedIndex = selectedIndex > 0 ? selectedIndex - 1 : projects.length - 1
997
+ renderOptions()
998
+ } else if (key === '\u001b[B') { // Down arrow
999
+ selectedIndex = selectedIndex < projects.length - 1 ? selectedIndex + 1 : 0
1000
+ renderOptions()
1001
+ }
1002
+ }
1003
+
1004
+ process.stdin.on('data', onKeyPress)
1005
+ })
1006
+ }
1007
+
1008
+ async function startProyectosSelectorFallback() {
818
1009
  const rl = createInterface({
819
1010
  input: process.stdin,
820
1011
  output: process.stdout
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@icarusmx/creta",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
4
4
  "description": "Salgamos de este laberinto.",
5
5
  "type": "module",
6
6
  "bin": {