@icarusmx/creta 0.8.2 → 0.9.0

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 CHANGED
@@ -6,6 +6,7 @@ import fs from 'fs'
6
6
  import path from 'path'
7
7
  import { fileURLToPath } from 'url'
8
8
  import { CretaCodeSession } from '../lib/session.js'
9
+ import { Lesson6InterfaceDesign } from '../lessons/lesson6-interface-design.js'
9
10
 
10
11
  const ENUNCIADOS = [
11
12
  {
@@ -786,7 +787,7 @@ async function startEnunciadosSelectorInteractive() {
786
787
  return new Promise((resolve) => {
787
788
  renderOptions()
788
789
 
789
- const onKeyPress = (key) => {
790
+ const onKeyPress = async (key) => {
790
791
  if (key === 'q' || key === '\x03') { // q or Ctrl+C
791
792
  process.stdin.setRawMode(false)
792
793
  process.stdin.removeListener('data', onKeyPress)
@@ -810,13 +811,30 @@ async function startEnunciadosSelectorInteractive() {
810
811
  console.log(`\n💡 Enfoque: ${enunciadoSeleccionado.enfoque}`)
811
812
  console.log(`📚 Nivel: ${enunciadoSeleccionado.nivel}`)
812
813
 
813
- console.log("\n🚀 Próximamente:")
814
- console.log("- Sesiones de estudio dirigidas basadas en este enunciado")
815
- console.log("- Ejercicios prácticos que ilustren el concepto")
816
- console.log("- Proyectos específicos para internalizar la idea")
814
+ // Check if we have a lesson implementation for this enunciado
815
+ if (enunciadoSeleccionado.id === 6) {
816
+ console.log("\n🚀 ¡Lección disponible! Iniciando sesión de estudio dirigida...")
817
+ await new Promise(resolve => setTimeout(resolve, 1500)) // Brief pause
818
+
819
+ try {
820
+ const lesson6 = new Lesson6InterfaceDesign()
821
+ await lesson6.start()
822
+ } catch (error) {
823
+ console.error("\n❌ Error al ejecutar la lección:", error.message)
824
+ console.log("\n🚀 Próximamente:")
825
+ console.log("- Sesiones de estudio dirigidas basadas en este enunciado")
826
+ console.log("- Ejercicios prácticos que ilustren el concepto")
827
+ console.log("- Proyectos específicos para internalizar la idea")
828
+ }
829
+ } else {
830
+ console.log("\n🚀 Próximamente:")
831
+ console.log("- Sesiones de estudio dirigidas basadas en este enunciado")
832
+ console.log("- Ejercicios prácticos que ilustren el concepto")
833
+ console.log("- Proyectos específicos para internalizar la idea")
817
834
 
818
- console.log("\n💭 Por ahora, reflexiona: ¿qué parte específica de este enunciado")
819
- console.log(" te genera más curiosidad o confusión?")
835
+ console.log("\n💭 Por ahora, reflexiona: ¿qué parte específica de este enunciado")
836
+ console.log(" te genera más curiosidad o confusión?")
837
+ }
820
838
 
821
839
  resolve()
822
840
  return
@@ -876,13 +894,32 @@ async function startEnunciadosSelectorFallback() {
876
894
  console.log(`\n💡 Enfoque: ${enunciadoSeleccionado.enfoque}`)
877
895
  console.log(`📚 Nivel: ${enunciadoSeleccionado.nivel}`)
878
896
 
879
- console.log("\n🚀 Próximamente:")
880
- console.log("- Sesiones de estudio dirigidas basadas en este enunciado")
881
- console.log("- Ejercicios prácticos que ilustren el concepto")
882
- console.log("- Proyectos específicos para internalizar la idea")
897
+ // Check if we have a lesson implementation for this enunciado
898
+ if (enunciadoSeleccionado.id === 6) {
899
+ console.log("\n🚀 ¡Lección disponible! Iniciando sesión de estudio dirigida...")
900
+ rl.close()
901
+ await new Promise(resolve => setTimeout(resolve, 1500)) // Brief pause
902
+
903
+ try {
904
+ const lesson6 = new Lesson6InterfaceDesign()
905
+ await lesson6.start()
906
+ } catch (error) {
907
+ console.error("\n❌ Error al ejecutar la lección:", error.message)
908
+ console.log("\n🚀 Próximamente:")
909
+ console.log("- Sesiones de estudio dirigidas basadas en este enunciado")
910
+ console.log("- Ejercicios prácticos que ilustren el concepto")
911
+ console.log("- Proyectos específicos para internalizar la idea")
912
+ }
913
+ return
914
+ } else {
915
+ console.log("\n🚀 Próximamente:")
916
+ console.log("- Sesiones de estudio dirigidas basadas en este enunciado")
917
+ console.log("- Ejercicios prácticos que ilustren el concepto")
918
+ console.log("- Proyectos específicos para internalizar la idea")
883
919
 
884
- console.log("\n💭 Por ahora, reflexiona: ¿qué parte específica de este enunciado")
885
- console.log(" te genera más curiosidad o confusión?")
920
+ console.log("\n💭 Por ahora, reflexiona: ¿qué parte específica de este enunciado")
921
+ console.log(" te genera más curiosidad o confusión?")
922
+ }
886
923
 
887
924
  } else {
888
925
  console.log("❌ Opción no válida. Elige un número entre 1 y 6.")
@@ -0,0 +1,306 @@
1
+ #!/usr/bin/env node
2
+
3
+ // LECCIÓN 6: El énfasis al diseñar los objetos debe estar en la definición de sus solicitudes e interfaces
4
+ // Enfoque práctico: Sistema de gestión de tareas con diseño interface-first
5
+
6
+ import { createInterface } from 'readline'
7
+
8
+ export class Lesson6InterfaceDesign {
9
+ constructor() {
10
+ this.rl = createInterface({
11
+ input: process.stdin,
12
+ output: process.stdout
13
+ })
14
+ }
15
+
16
+ async start() {
17
+ console.log("🎯 LECCIÓN 6: Diseño basado en Interfaces")
18
+ console.log("=" .repeat(50))
19
+ console.log("📚 Concepto: El énfasis al diseñar los objetos debe estar en la definición de sus solicitudes e interfaces.")
20
+ console.log("\n💡 ¿Por qué es importante?")
21
+ console.log("- Las interfaces definen QUÉ hace un objeto, no CÓMO lo hace")
22
+ console.log("- Facilita la colaboración entre objetos")
23
+ console.log("- Permite cambiar implementaciones sin afectar otros objetos")
24
+ console.log("- Hace el código más mantenible y extensible")
25
+
26
+ await this.waitForEnter("\nPresiona Enter para comenzar el ejercicio práctico...")
27
+
28
+ await this.practicalExercise()
29
+ await this.conclusion()
30
+
31
+ this.rl.close()
32
+ }
33
+
34
+ async practicalExercise() {
35
+ console.clear()
36
+ console.log("🛠️ EJERCICIO PRÁCTICO: Sistema de Gestión de Tareas")
37
+ console.log("=" .repeat(50))
38
+ console.log("🎯 Objetivo: Diseñar interfaces ANTES de implementar")
39
+ console.log("\nVamos a crear un sistema donde:")
40
+ console.log("- TaskManager gestiona una colección de tareas")
41
+ console.log("- Task representa una tarea individual")
42
+ console.log("- TaskStorage guarda y recupera tareas")
43
+
44
+ await this.waitForEnter("\nPresiona Enter para ver cómo diseñar las interfaces...")
45
+
46
+ await this.step1_DefineRequests()
47
+ await this.step2_DefineInterfaces()
48
+ await this.step3_ImplementObjects()
49
+ await this.step4_TestInteraction()
50
+ }
51
+
52
+ async step1_DefineRequests() {
53
+ console.clear()
54
+ console.log("📋 PASO 1: Definir las Solicitudes")
55
+ console.log("=" .repeat(40))
56
+ console.log("Antes de escribir código, pensemos: ¿Qué solicitudes debe manejar cada objeto?")
57
+ console.log("\n🎯 TaskManager debe poder:")
58
+ console.log(" - Crear una nueva tarea")
59
+ console.log(" - Listar todas las tareas")
60
+ console.log(" - Marcar tarea como completada")
61
+ console.log(" - Eliminar una tarea")
62
+
63
+ console.log("\n📝 Task debe poder:")
64
+ console.log(" - Proporcionar su información")
65
+ console.log(" - Cambiar su estado (pendiente/completada)")
66
+ console.log(" - Validar si está completada")
67
+
68
+ console.log("\n💾 TaskStorage debe poder:")
69
+ console.log(" - Guardar una tarea")
70
+ console.log(" - Recuperar todas las tareas")
71
+ console.log(" - Eliminar una tarea específica")
72
+
73
+ await this.waitForEnter("\n✅ ¡Excelente! Ya definimos QUÉ debe hacer cada objeto. Presiona Enter para definir las interfaces...")
74
+ }
75
+
76
+ async step2_DefineInterfaces() {
77
+ console.clear()
78
+ console.log("🔌 PASO 2: Definir las Interfaces (Firmas de Operación)")
79
+ console.log("=" .repeat(50))
80
+ console.log("Ahora especifiquemos CÓMO se solicitan estas operaciones:")
81
+
82
+ console.log("\n// TaskManager Interface")
83
+ console.log("class TaskManager {")
84
+ console.log(" createTask(title, description) → Task")
85
+ console.log(" getAllTasks() → Array<Task>")
86
+ console.log(" completeTask(taskId) → boolean")
87
+ console.log(" deleteTask(taskId) → boolean")
88
+ console.log("}")
89
+
90
+ console.log("\n// Task Interface")
91
+ console.log("class Task {")
92
+ console.log(" constructor(id, title, description) → Task")
93
+ console.log(" getInfo() → {id, title, description, completed}")
94
+ console.log(" markCompleted() → void")
95
+ console.log(" isCompleted() → boolean")
96
+ console.log("}")
97
+
98
+ console.log("\n// TaskStorage Interface")
99
+ console.log("class TaskStorage {")
100
+ console.log(" save(task) → void")
101
+ console.log(" findAll() → Array<Task>")
102
+ console.log(" remove(taskId) → boolean")
103
+ console.log("}")
104
+
105
+ console.log("\n💡 Observa que cada operación especifica:")
106
+ console.log(" a) Nombre de la operación (createTask, save, etc.)")
107
+ console.log(" b) Insumos necesarios (title, description, taskId, etc.)")
108
+ console.log(" c) Valor que regresa (Task, boolean, Array, etc.)")
109
+
110
+ await this.waitForEnter("\n✅ Interfaces definidas. Presiona Enter para implementar...")
111
+ }
112
+
113
+ async step3_ImplementObjects() {
114
+ console.clear()
115
+ console.log("⚙️ PASO 3: Implementar los Objetos")
116
+ console.log("=" .repeat(40))
117
+ console.log("Ahora que tenemos las interfaces claras, implementemos:")
118
+
119
+ console.log("\n// Implementación de Task")
120
+ console.log(`class Task {
121
+ constructor(id, title, description) {
122
+ this.id = id
123
+ this.title = title
124
+ this.description = description
125
+ this.completed = false
126
+ }
127
+
128
+ getInfo() {
129
+ return {
130
+ id: this.id,
131
+ title: this.title,
132
+ description: this.description,
133
+ completed: this.completed
134
+ }
135
+ }
136
+
137
+ markCompleted() {
138
+ this.completed = true
139
+ }
140
+
141
+ isCompleted() {
142
+ return this.completed
143
+ }
144
+ }`)
145
+
146
+ await this.waitForEnter("\nPresiona Enter para ver TaskStorage...")
147
+
148
+ console.log("\n// Implementación de TaskStorage")
149
+ console.log(`class TaskStorage {
150
+ constructor() {
151
+ this.tasks = []
152
+ }
153
+
154
+ save(task) {
155
+ this.tasks.push(task)
156
+ }
157
+
158
+ findAll() {
159
+ return [...this.tasks]
160
+ }
161
+
162
+ remove(taskId) {
163
+ const index = this.tasks.findIndex(t => t.id === taskId)
164
+ if (index !== -1) {
165
+ this.tasks.splice(index, 1)
166
+ return true
167
+ }
168
+ return false
169
+ }
170
+ }`)
171
+
172
+ await this.waitForEnter("\nPresiona Enter para ver TaskManager...")
173
+
174
+ console.log("\n// Implementación de TaskManager")
175
+ console.log(`class TaskManager {
176
+ constructor(storage) {
177
+ this.storage = storage
178
+ this.nextId = 1
179
+ }
180
+
181
+ createTask(title, description) {
182
+ const task = new Task(this.nextId++, title, description)
183
+ this.storage.save(task)
184
+ return task
185
+ }
186
+
187
+ getAllTasks() {
188
+ return this.storage.findAll()
189
+ }
190
+
191
+ completeTask(taskId) {
192
+ const tasks = this.storage.findAll()
193
+ const task = tasks.find(t => t.id === taskId)
194
+ if (task) {
195
+ task.markCompleted()
196
+ return true
197
+ }
198
+ return false
199
+ }
200
+
201
+ deleteTask(taskId) {
202
+ return this.storage.remove(taskId)
203
+ }
204
+ }`)
205
+
206
+ await this.waitForEnter("\n✅ Implementación completa. Presiona Enter para probar la interacción...")
207
+ }
208
+
209
+ async step4_TestInteraction() {
210
+ console.clear()
211
+ console.log("🧪 PASO 4: Probar la Interacción entre Objetos")
212
+ console.log("=" .repeat(45))
213
+ console.log("Veamos cómo los objetos colaboran usando sus interfaces:")
214
+
215
+ console.log("\n// Crear el sistema")
216
+ console.log("const storage = new TaskStorage()")
217
+ console.log("const manager = new TaskManager(storage)")
218
+ console.log("")
219
+ console.log("// Los objetos interactúan a través de solicitudes")
220
+ console.log("const task1 = manager.createTask('Estudiar OOP', 'Completar lección 6')")
221
+ console.log("const task2 = manager.createTask('Practicar código', 'Implementar sistema de tareas')")
222
+ console.log("")
223
+ console.log("// Cada solicitud respeta la interfaz definida")
224
+ console.log("manager.completeTask(task1.id)")
225
+ console.log("const allTasks = manager.getAllTasks()")
226
+ console.log("")
227
+ console.log("allTasks.forEach(task => {")
228
+ console.log(" const info = task.getInfo() // Solicitud a Task")
229
+ console.log(" console.log(`${info.title}: ${info.completed ? '✅' : '❌'}`)")
230
+ console.log("})")
231
+
232
+ console.log("\n🎯 Resultado esperado:")
233
+ console.log("Estudiar OOP: ✅")
234
+ console.log("Practicar código: ❌")
235
+
236
+ await this.waitForEnter("\nPresiona Enter para ver los beneficios de este enfoque...")
237
+
238
+ console.clear()
239
+ console.log("🌟 BENEFICIOS DEL DISEÑO INTERFACE-FIRST")
240
+ console.log("=" .repeat(45))
241
+ console.log("1. 🎯 Claridad: Cada objeto tiene responsabilidades bien definidas")
242
+ console.log("2. 🔗 Colaboración: Los objetos saben exactamente cómo solicitar operaciones")
243
+ console.log("3. 🔄 Flexibilidad: Podemos cambiar TaskStorage por DatabaseStorage sin afectar TaskManager")
244
+ console.log("4. 🧪 Testeable: Podemos crear mocks fácilmente para testing")
245
+ console.log("5. 📚 Mantenible: Las interfaces documentan el contrato de cada objeto")
246
+
247
+ console.log("\n💡 Ejemplo de extensibilidad:")
248
+ console.log("// Podemos cambiar el storage sin modificar TaskManager")
249
+ console.log("class DatabaseStorage {")
250
+ console.log(" save(task) { /* guardar en BD */ }")
251
+ console.log(" findAll() { /* consultar BD */ }")
252
+ console.log(" remove(taskId) { /* eliminar de BD */ }")
253
+ console.log("}")
254
+ console.log("")
255
+ console.log("// TaskManager sigue funcionando igual!")
256
+ console.log("const dbStorage = new DatabaseStorage()")
257
+ console.log("const manager = new TaskManager(dbStorage)")
258
+
259
+ await this.waitForEnter("\nPresiona Enter para continuar con la conclusión...")
260
+ }
261
+
262
+ async conclusion() {
263
+ console.clear()
264
+ console.log("🎓 CONCLUSIÓN: Diseño basado en Interfaces")
265
+ console.log("=" .repeat(45))
266
+ console.log("🎯 Hemos demostrado que:")
267
+ console.log("\n1. El ÉNFASIS debe estar en definir QUÉ solicitudes maneja cada objeto")
268
+ console.log("2. Las INTERFACES especifican cómo hacer estas solicitudes")
269
+ console.log("3. La IMPLEMENTACIÓN viene después, siguiendo el contrato")
270
+ console.log("4. Los objetos COLABORAN a través de estas interfaces bien definidas")
271
+
272
+ console.log("\n📚 Conexión con lecciones anteriores:")
273
+ console.log("• Lección 2: Los objetos interactúan a través de solicitudes ✓")
274
+ console.log("• Lección 3: Las solicitudes son la única forma de ejecutar operaciones ✓")
275
+ console.log("• Lección 4: Cada operación tiene nombre, insumos y valor de retorno ✓")
276
+ console.log("• Lección 5: La interfaz es el conjunto de todas las firmas ✓")
277
+ console.log("• Lección 6: El énfasis está en definir solicitudes e interfaces ✓")
278
+
279
+ console.log("\n🚀 Próximo paso:")
280
+ console.log("Practica este enfoque en tus propios proyectos:")
281
+ console.log("1. Define primero QUÉ debe hacer cada objeto")
282
+ console.log("2. Especifica las interfaces (firmas de operación)")
283
+ console.log("3. Implementa respetando esos contratos")
284
+ console.log("4. Haz que los objetos colaboren a través de solicitudes")
285
+
286
+ console.log("\n💭 Reflexión final:")
287
+ console.log("¿Cómo cambiaría tu forma de programar si siempre empezaras")
288
+ console.log("definiendo las interfaces antes de la implementación?")
289
+
290
+ await this.waitForEnter("\n✨ ¡Lección 6 completada! Presiona Enter para salir...")
291
+ }
292
+
293
+ async waitForEnter(message) {
294
+ return new Promise((resolve) => {
295
+ this.rl.question(message, () => {
296
+ resolve()
297
+ })
298
+ })
299
+ }
300
+ }
301
+
302
+ // Para usar la lección independientemente
303
+ if (import.meta.url === `file://${process.argv[1]}`) {
304
+ const lesson = new Lesson6InterfaceDesign()
305
+ await lesson.start()
306
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@icarusmx/creta",
3
- "version": "0.8.2",
3
+ "version": "0.9.0",
4
4
  "description": "Salgamos de este laberinto.",
5
5
  "type": "module",
6
6
  "bin": {