@icarusmx/creta 0.10.2 → 0.11.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
@@ -7,6 +7,7 @@ import path from 'path'
7
7
  import { fileURLToPath } from 'url'
8
8
  import { CretaCodeSession } from '../lib/session.js'
9
9
  import { Lesson1SystemDecomposition } from '../lessons/lesson1-system-decomposition.js'
10
+ import { Lesson2ObjectRequests } from '../lessons/lesson2-object-requests.js'
10
11
  import { Lesson6InterfaceDesign } from '../lessons/lesson6-interface-design.js'
11
12
 
12
13
  const ENUNCIADOS = [
@@ -841,6 +842,20 @@ async function startEnunciadosSelectorInteractive() {
841
842
  console.log("- Ejercicios prácticos que ilustren el concepto")
842
843
  console.log("- Proyectos específicos para internalizar la idea")
843
844
  }
845
+ } else if (enunciadoSeleccionado.id === 2) {
846
+ console.log("\n🚀 ¡Lección disponible! Iniciando sesión de estudio dirigida...")
847
+ await new Promise(resolve => setTimeout(resolve, 1500)) // Brief pause
848
+
849
+ try {
850
+ const lesson2 = new Lesson2ObjectRequests()
851
+ await lesson2.start()
852
+ } catch (error) {
853
+ console.error("\n❌ Error al ejecutar la lección:", error.message)
854
+ console.log("\n🚀 Próximamente:")
855
+ console.log("- Sesiones de estudio dirigidas basadas en este enunciado")
856
+ console.log("- Ejercicios prácticos que ilustren el concepto")
857
+ console.log("- Proyectos específicos para internalizar la idea")
858
+ }
844
859
  } else if (enunciadoSeleccionado.id === 6) {
845
860
  console.log("\n🚀 ¡Lección disponible! Iniciando sesión de estudio dirigida...")
846
861
  await new Promise(resolve => setTimeout(resolve, 1500)) // Brief pause
@@ -956,6 +971,22 @@ async function startEnunciadosSelectorFallback() {
956
971
  console.log("- Proyectos específicos para internalizar la idea")
957
972
  }
958
973
  return
974
+ } else if (enunciadoSeleccionado.id === 2) {
975
+ console.log("\n🚀 ¡Lección disponible! Iniciando sesión de estudio dirigida...")
976
+ rl.close()
977
+ await new Promise(resolve => setTimeout(resolve, 1500)) // Brief pause
978
+
979
+ try {
980
+ const lesson2 = new Lesson2ObjectRequests()
981
+ await lesson2.start()
982
+ } catch (error) {
983
+ console.error("\n❌ Error al ejecutar la lección:", error.message)
984
+ console.log("\n🚀 Próximamente:")
985
+ console.log("- Sesiones de estudio dirigidas basadas en este enunciado")
986
+ console.log("- Ejercicios prácticos que ilustren el concepto")
987
+ console.log("- Proyectos específicos para internalizar la idea")
988
+ }
989
+ return
959
990
  } else if (enunciadoSeleccionado.id === 6) {
960
991
  console.log("\n🚀 ¡Lección disponible! Iniciando sesión de estudio dirigida...")
961
992
  rl.close()
@@ -0,0 +1,312 @@
1
+ #!/usr/bin/env node
2
+
3
+ // LECCIÓN 2: Los objetos interactúan entre sí a través de solicitudes
4
+ // Enfoque práctico: Demostrar cómo los objetos se comunican sin acceder directamente a datos internos
5
+
6
+ import { createInterface } from 'readline'
7
+
8
+ export class Lesson2ObjectRequests {
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 2: Interacción a través de Solicitudes")
18
+ console.log("=" .repeat(50))
19
+ console.log("📚 Enunciado: Los objetos interactúan entre sí a través de solicitudes.")
20
+ console.log("\n💡 ¿Qué significa esto exactamente?")
21
+ console.log("- Los objetos NO acceden directamente a los datos de otros objetos")
22
+ console.log("- En lugar de eso, hacen SOLICITUDES específicas")
23
+ console.log("- Cada solicitud tiene un propósito claro y definido")
24
+
25
+ await this.waitForEnter("\nPresiona Enter para comenzar el ejercicio práctico...")
26
+
27
+ await this.practicalExercise()
28
+ await this.conclusion()
29
+
30
+ this.rl.close()
31
+ }
32
+
33
+ async practicalExercise() {
34
+ console.clear()
35
+ console.log("🛠️ EJERCICIO PRÁCTICO: Sistema de Mensajería")
36
+ console.log("=" .repeat(50))
37
+ console.log("🎯 Vamos a ver cómo los objetos se solicitan información sin acceso directo")
38
+ console.log("\nSistema: Chat entre usuarios")
39
+ console.log("Objetos: User, Message, ChatRoom")
40
+
41
+ await this.waitForEnter("\nPresiona Enter para ver el ANTI-PATRÓN...")
42
+
43
+ await this.step1_ShowAntiPattern()
44
+ await this.step2_ShowCorrectPattern()
45
+ await this.step3_RequestTypes()
46
+ await this.step4_ComplexInteraction()
47
+ }
48
+
49
+ async step1_ShowAntiPattern() {
50
+ console.clear()
51
+ console.log("❌ ANTI-PATRÓN: Acceso Directo (INCORRECTO)")
52
+ console.log("=" .repeat(45))
53
+ console.log("Veamos qué NO debemos hacer:")
54
+
55
+ console.log("\n// ❌ MALO: Acceso directo a datos internos")
56
+ console.log(`class ChatRoom {
57
+ addMessage(user, text) {
58
+ // ❌ Accediendo directamente a user.name
59
+ if (user.name && user.name.length > 0) {
60
+ // ❌ Accediendo directamente a user.isActive
61
+ if (user.isActive === true) {
62
+ const message = new Message(user.name, text)
63
+ this.messages.push(message)
64
+ }
65
+ }
66
+ }
67
+ }`)
68
+
69
+ console.log("\n🚨 Problemas del acceso directo:")
70
+ console.log("• ChatRoom conoce la estructura interna de User")
71
+ console.log("• Si User cambia, ChatRoom se rompe")
72
+ console.log("• No hay control sobre qué se accede")
73
+ console.log("• Violación de encapsulación")
74
+
75
+ await this.waitForEnter("\nPresiona Enter para ver la forma CORRECTA...")
76
+ }
77
+
78
+ async step2_ShowCorrectPattern() {
79
+ console.clear()
80
+ console.log("✅ PATRÓN CORRECTO: Solicitudes (CORRECTO)")
81
+ console.log("=" .repeat(45))
82
+ console.log("Ahora veamos cómo debe ser:")
83
+
84
+ console.log("\n// ✅ BUENO: Comunicación a través de solicitudes")
85
+ console.log(`class User {
86
+ constructor(name) {
87
+ this.#name = name
88
+ this.#isActive = true
89
+ }
90
+
91
+ // 🔑 SOLICITUD: getName()
92
+ getName() {
93
+ return this.#name
94
+ }
95
+
96
+ // 🔑 SOLICITUD: isCurrentlyActive()
97
+ isCurrentlyActive() {
98
+ return this.#isActive
99
+ }
100
+
101
+ // 🔑 SOLICITUD: canSendMessage()
102
+ canSendMessage() {
103
+ return this.#isActive && this.#name.length > 0
104
+ }
105
+ }`)
106
+
107
+ await this.waitForEnter("\nPresiona Enter para ver cómo ChatRoom usa las solicitudes...")
108
+
109
+ console.log("\n// ✅ ChatRoom usa SOLICITUDES, no acceso directo")
110
+ console.log(`class ChatRoom {
111
+ addMessage(user, text) {
112
+ // ✅ SOLICITUD: ¿puede enviar mensajes?
113
+ if (user.canSendMessage()) {
114
+ // ✅ SOLICITUD: dame tu nombre
115
+ const userName = user.getName()
116
+ const message = new Message(userName, text)
117
+ this.messages.push(message)
118
+ }
119
+ }
120
+
121
+ getActiveUsers() {
122
+ return this.users.filter(user =>
123
+ // ✅ SOLICITUD: ¿estás activo?
124
+ user.isCurrentlyActive()
125
+ )
126
+ }
127
+ }`)
128
+
129
+ console.log("\n🌟 Beneficios de las solicitudes:")
130
+ console.log("• ChatRoom no conoce la estructura interna de User")
131
+ console.log("• User controla qué información expone")
132
+ console.log("• Cambios internos en User no afectan ChatRoom")
133
+ console.log("• Cada solicitud tiene un propósito específico")
134
+
135
+ await this.waitForEnter("\nPresiona Enter para ver tipos de solicitudes...")
136
+ }
137
+
138
+ async step3_RequestTypes() {
139
+ console.clear()
140
+ console.log("🔍 TIPOS DE SOLICITUDES")
141
+ console.log("=" .repeat(30))
142
+ console.log("Las solicitudes pueden ser de diferentes tipos:")
143
+
144
+ console.log("\n1️⃣ SOLICITUDES DE CONSULTA (Query)")
145
+ console.log(" • user.getName() → devuelve información")
146
+ console.log(" • user.isCurrentlyActive() → devuelve estado")
147
+ console.log(" • message.getTimestamp() → devuelve dato")
148
+
149
+ console.log("\n2️⃣ SOLICITUDES DE ACCIÓN (Command)")
150
+ console.log(" • user.setActive(false) → cambia estado")
151
+ console.log(" • message.markAsRead() → ejecuta acción")
152
+ console.log(" • chatRoom.addUser(user) → modifica colección")
153
+
154
+ console.log("\n3️⃣ SOLICITUDES DE VALIDACIÓN (Validation)")
155
+ console.log(" • user.canSendMessage() → verifica capacidad")
156
+ console.log(" • message.isValid() → verifica integridad")
157
+ console.log(" • chatRoom.hasPermission(user) → verifica acceso")
158
+
159
+ await this.waitForEnter("\nPresiona Enter para ver una interacción compleja...")
160
+
161
+ console.clear()
162
+ console.log("💬 EJEMPLO: Enviar mensaje con validaciones")
163
+ console.log("=" .repeat(45))
164
+
165
+ console.log("\n// Los objetos colaboran solo a través de solicitudes")
166
+ console.log(`function sendMessage(chatRoom, user, text) {
167
+ // 🔍 SOLICITUD: ¿el usuario puede enviar?
168
+ if (!user.canSendMessage()) {
169
+ console.log("Usuario no puede enviar mensajes")
170
+ return false
171
+ }
172
+
173
+ // 🔍 SOLICITUD: ¿el usuario tiene permisos en este chat?
174
+ if (!chatRoom.hasPermission(user)) {
175
+ console.log("Sin permisos en este chat")
176
+ return false
177
+ }
178
+
179
+ // 🔍 SOLICITUD: ¿el texto es válido?
180
+ const message = new Message(user.getName(), text)
181
+ if (!message.isValid()) {
182
+ console.log("Mensaje inválido")
183
+ return false
184
+ }
185
+
186
+ // ⚡ SOLICITUD: agregar el mensaje
187
+ chatRoom.addMessage(user, text)
188
+
189
+ // 🔍 SOLICITUD: notificar a usuarios activos
190
+ const activeUsers = chatRoom.getActiveUsers()
191
+ activeUsers.forEach(activeUser => {
192
+ // 🔍 SOLICITUD: notificar
193
+ activeUser.notifyNewMessage(message)
194
+ })
195
+
196
+ return true
197
+ }`)
198
+
199
+ console.log("\n🎯 Observa: En ningún momento accedemos directamente a")
200
+ console.log(" user.#name, user.#isActive, chatRoom.#messages, etc.")
201
+ console.log(" Todo pasa por SOLICITUDES específicas.")
202
+
203
+ await this.waitForEnter("\nPresiona Enter para la demostración final...")
204
+ }
205
+
206
+ async step4_ComplexInteraction() {
207
+ console.clear()
208
+ console.log("🎭 DEMOSTRACIÓN: Interacción Completa")
209
+ console.log("=" .repeat(40))
210
+ console.log("Veamos todos los objetos interactuando:")
211
+
212
+ console.log("\n// Crear objetos")
213
+ console.log("const chatRoom = new ChatRoom('Desarrollo')")
214
+ console.log("const ana = new User('Ana')")
215
+ console.log("const carlos = new User('Carlos')")
216
+ console.log("")
217
+ console.log("// Agregar usuarios al chat")
218
+ console.log("chatRoom.addUser(ana) // SOLICITUD")
219
+ console.log("chatRoom.addUser(carlos) // SOLICITUD")
220
+ console.log("")
221
+ console.log("// Ana envía mensaje")
222
+ console.log("sendMessage(chatRoom, ana, 'Hola a todos!')")
223
+ console.log("")
224
+ console.log("// Secuencia de SOLICITUDES que se ejecutan:")
225
+ console.log("// 1. ana.canSendMessage() → true")
226
+ console.log("// 2. chatRoom.hasPermission(ana) → true")
227
+ console.log("// 3. ana.getName() → 'Ana'")
228
+ console.log("// 4. message.isValid() → true")
229
+ console.log("// 5. chatRoom.addMessage(ana, text)")
230
+ console.log("// 6. chatRoom.getActiveUsers() → [ana, carlos]")
231
+ console.log("// 7. carlos.notifyNewMessage(message)")
232
+
233
+ console.log("\n💡 Resultado:")
234
+ console.log("✅ Ana: Mensaje enviado")
235
+ console.log("📬 Carlos: Notificación recibida")
236
+
237
+ await this.waitForEnter("\nPresiona Enter para ver qué pasa si Carlos se desconecta...")
238
+
239
+ console.log("\n// Carlos se desconecta")
240
+ console.log("carlos.setActive(false) // SOLICITUD")
241
+ console.log("")
242
+ console.log("// Ana envía otro mensaje")
243
+ console.log("sendMessage(chatRoom, ana, 'Carlos, ¿estás ahí?')")
244
+ console.log("")
245
+ console.log("// Secuencia de SOLICITUDES:")
246
+ console.log("// 1-5. Igual que antes...")
247
+ console.log("// 6. chatRoom.getActiveUsers() → [ana] // ¡Carlos ya no aparece!")
248
+ console.log("// 7. Solo ana.notifyNewMessage() se ejecuta")
249
+
250
+ console.log("\n💡 Resultado:")
251
+ console.log("✅ Ana: Mensaje enviado")
252
+ console.log("😴 Carlos: No recibe notificación (está inactivo)")
253
+
254
+ console.log("\n🎯 Observación clave:")
255
+ console.log("Los objetos cambian su comportamiento interno, pero las")
256
+ console.log("SOLICITUDES siguen siendo las mismas. La interacción es estable.")
257
+
258
+ await this.waitForEnter("\nPresiona Enter para la conclusión...")
259
+ }
260
+
261
+ async conclusion() {
262
+ console.clear()
263
+ console.log("🎓 CONCLUSIÓN: Interacción a través de Solicitudes")
264
+ console.log("=" .repeat(50))
265
+ console.log("🎯 Hemos demostrado que:")
266
+
267
+ console.log("\n1️⃣ Los objetos NUNCA acceden directamente a datos internos")
268
+ console.log("2️⃣ Toda comunicación ocurre a través de SOLICITUDES específicas")
269
+ console.log("3️⃣ Cada solicitud tiene un propósito claro y definido")
270
+ console.log("4️⃣ Los objetos controlan qué información exponen")
271
+
272
+ console.log("\n🔑 Tipos de solicitudes vistas:")
273
+ console.log("• CONSULTA: getName(), isCurrentlyActive()")
274
+ console.log("• ACCIÓN: setActive(), addMessage()")
275
+ console.log("• VALIDACIÓN: canSendMessage(), hasPermission()")
276
+
277
+ console.log("\n🌟 Beneficios fundamentales:")
278
+ console.log("• Encapsulación preservada")
279
+ console.log("• Flexibilidad para cambios internos")
280
+ console.log("• Interacciones estables y predecibles")
281
+ console.log("• Control total sobre el acceso a datos")
282
+
283
+ console.log("\n📚 Conexión con otras lecciones:")
284
+ console.log("• Lección 1: Los objetos que identificamos ahora interactúan")
285
+ console.log("• Lección 3: Las solicitudes son la ÚNICA forma de ejecutar operaciones")
286
+ console.log("• Lecciones 4-6: Cómo definir formalmente estas solicitudes")
287
+
288
+ console.log("\n💭 Reflexión:")
289
+ console.log("¿Te imaginas un mundo donde pudieras acceder directamente")
290
+ console.log("a la cuenta bancaria de cualquier persona? ¡Sería un caos!")
291
+ console.log("Los objetos funcionan igual: solicitudes controladas, acceso seguro.")
292
+
293
+ console.log("\n🏆 Ahora entiendes por qué los objetos interactúan a través")
294
+ console.log("de solicitudes: es la base de la comunicación segura y ordenada.")
295
+
296
+ await this.waitForEnter("\n✨ ¡Lección 2 completada! Presiona Enter para salir...")
297
+ }
298
+
299
+ async waitForEnter(message) {
300
+ return new Promise((resolve) => {
301
+ this.rl.question(message, () => {
302
+ resolve()
303
+ })
304
+ })
305
+ }
306
+ }
307
+
308
+ // Para usar la lección independientemente
309
+ if (import.meta.url === `file://${process.argv[1]}`) {
310
+ const lesson = new Lesson2ObjectRequests()
311
+ await lesson.start()
312
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@icarusmx/creta",
3
- "version": "0.10.2",
3
+ "version": "0.11.0",
4
4
  "description": "Salgamos de este laberinto.",
5
5
  "type": "module",
6
6
  "bin": {