@icarusmx/creta 1.5.3 → 1.5.6
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 +14 -4
- package/lib/builders/MenuBuilder.js +23 -4
- package/lib/executors/ExercisesExecutor.js +271 -0
- package/lib/exercises/array-object-manipulation.md +1281 -0
- package/lib/exercises/git-stash-workflow.md +426 -0
- package/lib/exercises/railway-deployment.md +1185 -0
- package/lib/papers/bitcoin/bitcoin.md +92 -0
- package/lib/papers/mapreduce/mapreduce.md +476 -0
- package/lib/papers/spark/spark.md +49 -0
- package/package.json +5 -1
- package/ascii-logo.txt +0 -8
- package/codex-refactor.txt +0 -13
- package/docs/diagrams/README.md +0 -131
- package/docs/diagrams/architecture-overview.mmd +0 -71
- package/docs/diagrams/architecture.svg +0 -1
- package/docs/diagrams/ecosystem-integration.mmd +0 -49
- package/docs/diagrams/evolution-phases.mmd +0 -49
- package/docs/diagrams/output.svg +0 -1
- package/docs/diagrams/phase2-command-help-flow.mmd +0 -51
- package/docs/diagrams/user-journey.mmd +0 -78
- package/ejemplo.sh +0 -3
- package/refactor.txt +0 -581
- package/templates/sveltekit-portfolio/package.json +0 -20
- package/templates/sveltekit-portfolio/src/app.css +0 -51
- package/templates/sveltekit-portfolio/src/app.html +0 -12
- package/templates/sveltekit-portfolio/src/routes/+layout.svelte +0 -108
- package/templates/sveltekit-portfolio/src/routes/+page.svelte +0 -79
- package/templates/sveltekit-portfolio/static/favicon.png +0 -0
- package/templates/sveltekit-portfolio/svelte.config.js +0 -10
- package/templates/sveltekit-portfolio/vite.config.js +0 -10
- package/test/enunciados.test.js +0 -72
- package/test/sintaxis-menu.test.js +0 -45
- package/wea-fome-qlia.sh +0 -92
package/refactor.txt
DELETED
|
@@ -1,581 +0,0 @@
|
|
|
1
|
-
# CRETA CLI - REFACTORING STRATEGY v2.0
|
|
2
|
-
# Data-Driven Architecture (Discord-Inspired)
|
|
3
|
-
# bin/creta.js = 1616 líneas → Target: <100 líneas entry point
|
|
4
|
-
|
|
5
|
-
## 🚨 PROBLEMA ACTUAL
|
|
6
|
-
|
|
7
|
-
bin/creta.js ha crecido a 1616 líneas con **text y logic acoplados**:
|
|
8
|
-
- Hardcoded messages mezclados con execution logic
|
|
9
|
-
- Lessons con 280+ líneas de text + code
|
|
10
|
-
- Difícil traducir a otros idiomas
|
|
11
|
-
- Imposible reutilizar lesson logic
|
|
12
|
-
- No hay separación clara data vs behavior
|
|
13
|
-
|
|
14
|
-
## 💡 INSIGHT CLAVE (Discord API Pattern)
|
|
15
|
-
|
|
16
|
-
```js
|
|
17
|
-
// Discord approach: Data + Builder
|
|
18
|
-
const embed = new EmbedBuilder()
|
|
19
|
-
.setTitle('Title here')
|
|
20
|
-
.setDescription('Description here')
|
|
21
|
-
.addFields({ name: 'Field', value: 'Value' })
|
|
22
|
-
|
|
23
|
-
// Creta equivalent:
|
|
24
|
-
const lesson = new LessonBuilder(TERMINAL_BASICO_DATA)
|
|
25
|
-
.withIntro()
|
|
26
|
-
.withSteps()
|
|
27
|
-
.start()
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
**Principio:** Separar QUÉ (data) de CÓMO (execution)
|
|
31
|
-
|
|
32
|
-
## 🎯 OBJETIVO
|
|
33
|
-
|
|
34
|
-
**Data-Driven Architecture:**
|
|
35
|
-
- **Data:** Constants (text, config, lesson content) - easy to modify
|
|
36
|
-
- **Builders:** Execution engines (lesson-builder, menu-builder) - reusable
|
|
37
|
-
- **Orchestrators:** Coordinan builders con data - simple routing
|
|
38
|
-
|
|
39
|
-
## 📁 NUEVA ESTRUCTURA
|
|
40
|
-
|
|
41
|
-
```
|
|
42
|
-
cli/
|
|
43
|
-
├── bin/
|
|
44
|
-
│ └── creta.js # <100 líneas - Pure orchestration
|
|
45
|
-
│
|
|
46
|
-
├── lib/
|
|
47
|
-
│ ├── data/ # 📝 ALL CONTENT HERE
|
|
48
|
-
│ │ ├── enunciados.js # ENUNCIADOS array
|
|
49
|
-
│ │ ├── messages.js # UI messages, help text
|
|
50
|
-
│ │ ├── lessons/ # Lesson content (data only)
|
|
51
|
-
│ │ │ ├── lesson1-data.js # Sistema - text only
|
|
52
|
-
│ │ │ ├── lesson2-data.js # Solicitudes - text only
|
|
53
|
-
│ │ │ ├── lesson7-data.js # Definición - text only
|
|
54
|
-
│ │ │ └── sintaxis/
|
|
55
|
-
│ │ │ ├── terminal-basico.js
|
|
56
|
-
│ │ │ ├── git-basico.js
|
|
57
|
-
│ │ │ ├── git-colaboracion.js
|
|
58
|
-
│ │ │ └── git-avanzado.js
|
|
59
|
-
│ │ └── menus.js # Menu configurations
|
|
60
|
-
│ │
|
|
61
|
-
│ ├── builders/ # 🏗️ EXECUTION ENGINES
|
|
62
|
-
│ │ ├── LessonBuilder.js # Executes lesson data
|
|
63
|
-
│ │ ├── MenuBuilder.js # Renders menus from config
|
|
64
|
-
│ │ ├── ProjectBuilder.js # Creates projects from templates
|
|
65
|
-
│ │ └── InteractiveBuilder.js # Handles interactive flows
|
|
66
|
-
│ │
|
|
67
|
-
│ ├── executors/ # 🎮 ORCHESTRATORS
|
|
68
|
-
│ │ ├── enunciados-executor.js # Lesson selector + executor
|
|
69
|
-
│ │ ├── sintaxis-executor.js # Sintaxis lesson flow
|
|
70
|
-
│ │ ├── proyectos-executor.js # Project creation flow
|
|
71
|
-
│ │ └── portfolio-executor.js # Portfolio level flow
|
|
72
|
-
│ │
|
|
73
|
-
│ ├── templates/ # 📋 TEMPLATE OPERATIONS
|
|
74
|
-
│ │ ├── TemplateProcessor.js # Copy & process templates
|
|
75
|
-
│ │ ├── LevelModifier.js # Apply level modifications
|
|
76
|
-
│ │ └── PlaceholderReplacer.js # Replace {{VARIABLES}}
|
|
77
|
-
│ │
|
|
78
|
-
│ ├── utils/ # 🔧 UTILITIES
|
|
79
|
-
│ │ ├── input.js # readline helpers
|
|
80
|
-
│ │ ├── output.js # console formatting
|
|
81
|
-
│ │ ├── file-utils.js # fs operations
|
|
82
|
-
│ │ └── validators.js # input validation
|
|
83
|
-
│ │
|
|
84
|
-
│ ├── session.js # Existing - no changes
|
|
85
|
-
│ └── pr-tutorial.js # Existing - no changes
|
|
86
|
-
│
|
|
87
|
-
├── lessons/ # ❌ TO BE REMOVED
|
|
88
|
-
│ └── lesson*.js # Migrate to data/ + LessonBuilder
|
|
89
|
-
│
|
|
90
|
-
└── templates/ # ✅ KEEP AS IS
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
## 🏗️ CORE ARCHITECTURE PATTERNS
|
|
94
|
-
|
|
95
|
-
### Pattern 1: Data Objects (Discord-style)
|
|
96
|
-
|
|
97
|
-
```js
|
|
98
|
-
// lib/data/lessons/sintaxis/terminal-basico.js
|
|
99
|
-
export const TERMINAL_BASICO = {
|
|
100
|
-
id: 'terminal-basico',
|
|
101
|
-
title: 'Terminal Básico',
|
|
102
|
-
|
|
103
|
-
intro: {
|
|
104
|
-
definition: 'Sintaxis: estudia el modo en que se combinan las palabras...',
|
|
105
|
-
explanation: 'En esta sección aprenderemos algo más que palabras, aprenderemos comandos.',
|
|
106
|
-
detail: 'Al final del día un comando es una palabra, la diferencia es que está dotada de un significado que tu computadora entiende.'
|
|
107
|
-
},
|
|
108
|
-
|
|
109
|
-
steps: [
|
|
110
|
-
{
|
|
111
|
-
type: 'command',
|
|
112
|
-
command: 'ls',
|
|
113
|
-
description: 'Este es tu primer comando: ls',
|
|
114
|
-
instruction: 'Presiona ctrl + c para terminar esta sesión y después ejecuta el comando ls en tu terminal',
|
|
115
|
-
exitOnComplete: true
|
|
116
|
-
},
|
|
117
|
-
{
|
|
118
|
-
type: 'command',
|
|
119
|
-
command: 'pwd',
|
|
120
|
-
description: '¿Dónde estás? Usa pwd para descubrirlo',
|
|
121
|
-
expectedOutput: (output) => output.includes('/'),
|
|
122
|
-
onSuccess: '¡Correcto! Ahora sabes tu ubicación actual.'
|
|
123
|
-
},
|
|
124
|
-
{
|
|
125
|
-
type: 'interactive-challenge',
|
|
126
|
-
prompt: '¿Qué comando usarías para crear un directorio?',
|
|
127
|
-
answer: 'mkdir',
|
|
128
|
-
hint: 'Piensa en "make directory"',
|
|
129
|
-
onSuccess: '¡Exacto! mkdir crea directorios.'
|
|
130
|
-
}
|
|
131
|
-
]
|
|
132
|
-
}
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
### Pattern 2: Builders (Execution Logic)
|
|
136
|
-
|
|
137
|
-
```js
|
|
138
|
-
// lib/builders/LessonBuilder.js
|
|
139
|
-
export class LessonBuilder {
|
|
140
|
-
constructor(lessonData) {
|
|
141
|
-
this.data = lessonData
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
async start() {
|
|
145
|
-
await this.showIntro()
|
|
146
|
-
await this.executeSteps()
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
async showIntro() {
|
|
150
|
-
console.log(this.data.intro.definition)
|
|
151
|
-
await this.waitForEnter()
|
|
152
|
-
|
|
153
|
-
if (this.data.intro.explanation) {
|
|
154
|
-
console.log(`\n${this.data.intro.explanation}`)
|
|
155
|
-
if (this.data.intro.detail) {
|
|
156
|
-
console.log(`\n${this.data.intro.detail}`)
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
async executeSteps() {
|
|
162
|
-
for (const step of this.data.steps) {
|
|
163
|
-
await this.executeStep(step)
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
async executeStep(step) {
|
|
168
|
-
switch(step.type) {
|
|
169
|
-
case 'command':
|
|
170
|
-
await this.showCommand(step)
|
|
171
|
-
break
|
|
172
|
-
case 'interactive-challenge':
|
|
173
|
-
await this.runChallenge(step)
|
|
174
|
-
break
|
|
175
|
-
case 'explanation':
|
|
176
|
-
await this.showExplanation(step)
|
|
177
|
-
break
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
async showCommand(step) {
|
|
182
|
-
console.log(`\n${step.description}`)
|
|
183
|
-
console.log(`\n${step.instruction}`)
|
|
184
|
-
if (step.exitOnComplete) {
|
|
185
|
-
// Don't wait, let them exit
|
|
186
|
-
return
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
async runChallenge(step) {
|
|
191
|
-
const rl = createPromptInterface()
|
|
192
|
-
const answer = await askQuestion(rl, `\n${step.prompt}: `)
|
|
193
|
-
|
|
194
|
-
if (answer.toLowerCase() === step.answer.toLowerCase()) {
|
|
195
|
-
console.log(`\n✅ ${step.onSuccess}`)
|
|
196
|
-
} else {
|
|
197
|
-
console.log(`\n💡 Hint: ${step.hint}`)
|
|
198
|
-
}
|
|
199
|
-
rl.close()
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
async waitForEnter() {
|
|
203
|
-
const rl = createPromptInterface()
|
|
204
|
-
await new Promise(resolve => {
|
|
205
|
-
rl.question('\nPresiona Enter para comenzar...', () => {
|
|
206
|
-
rl.close()
|
|
207
|
-
resolve()
|
|
208
|
-
})
|
|
209
|
-
})
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
### Pattern 3: Executors (Orchestration)
|
|
215
|
-
|
|
216
|
-
```js
|
|
217
|
-
// lib/executors/sintaxis-executor.js
|
|
218
|
-
import { TERMINAL_BASICO } from '../data/lessons/sintaxis/terminal-basico.js'
|
|
219
|
-
import { GIT_BASICO } from '../data/lessons/sintaxis/git-basico.js'
|
|
220
|
-
import { LessonBuilder } from '../builders/LessonBuilder.js'
|
|
221
|
-
import { MenuBuilder } from '../builders/MenuBuilder.js'
|
|
222
|
-
|
|
223
|
-
export async function executeSintaxis() {
|
|
224
|
-
// Step 1: Show lesson menu
|
|
225
|
-
const menuConfig = {
|
|
226
|
-
title: 'Aprender Sintaxis',
|
|
227
|
-
options: [
|
|
228
|
-
{ id: 1, title: 'Terminal básico', data: TERMINAL_BASICO },
|
|
229
|
-
{ id: 2, title: 'Git básico', data: GIT_BASICO },
|
|
230
|
-
// ...
|
|
231
|
-
]
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
const menu = new MenuBuilder(menuConfig)
|
|
235
|
-
const selected = await menu.show()
|
|
236
|
-
|
|
237
|
-
// Step 2: Execute selected lesson
|
|
238
|
-
if (selected) {
|
|
239
|
-
const lesson = new LessonBuilder(selected.data)
|
|
240
|
-
await lesson.start()
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
### Pattern 4: Minimal Entry Point
|
|
246
|
-
|
|
247
|
-
```js
|
|
248
|
-
// bin/creta.js (<100 lines)
|
|
249
|
-
import { executeEnunciados } from '../lib/executors/enunciados-executor.js'
|
|
250
|
-
import { executeSintaxis } from '../lib/executors/sintaxis-executor.js'
|
|
251
|
-
import { executeProyectos } from '../lib/executors/proyectos-executor.js'
|
|
252
|
-
import { showHelp } from '../lib/commands/help.js'
|
|
253
|
-
import { WELCOME_BANNER } from '../lib/data/messages.js'
|
|
254
|
-
|
|
255
|
-
console.log(WELCOME_BANNER)
|
|
256
|
-
|
|
257
|
-
const args = process.argv.slice(2)
|
|
258
|
-
const command = args[0]
|
|
259
|
-
|
|
260
|
-
if (!command) {
|
|
261
|
-
const mainMenu = new MenuBuilder(MAIN_MENU_CONFIG)
|
|
262
|
-
const choice = await mainMenu.show()
|
|
263
|
-
|
|
264
|
-
switch(choice.id) {
|
|
265
|
-
case 1: await executeSintaxis(); break
|
|
266
|
-
case 2: await executeEnunciados(); break
|
|
267
|
-
case 3: await executeProyectos(); break
|
|
268
|
-
}
|
|
269
|
-
process.exit(0)
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// Route commands
|
|
273
|
-
const commands = {
|
|
274
|
-
'enunciados': executeEnunciados,
|
|
275
|
-
'portafolio': executePortfolio,
|
|
276
|
-
'help': showHelp
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
const handler = commands[command]
|
|
280
|
-
if (handler) {
|
|
281
|
-
await handler(args)
|
|
282
|
-
} else {
|
|
283
|
-
console.log(`Comando no reconocido: ${command}`)
|
|
284
|
-
process.exit(1)
|
|
285
|
-
}
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
## 🔨 REFACTORING PHASES (Data-Driven)
|
|
289
|
-
|
|
290
|
-
### PHASE 1: Create Data Layer (Zero Risk)
|
|
291
|
-
**Goal:** Extract ALL content to data files
|
|
292
|
-
|
|
293
|
-
1. **Create lib/data/enunciados.js**
|
|
294
|
-
- Move ENUNCIADOS array
|
|
295
|
-
|
|
296
|
-
2. **Create lib/data/messages.js**
|
|
297
|
-
- WELCOME_BANNER
|
|
298
|
-
- HELP_TEXT
|
|
299
|
-
- All user-facing strings
|
|
300
|
-
|
|
301
|
-
3. **Create lib/data/menus.js**
|
|
302
|
-
- MAIN_MENU_CONFIG
|
|
303
|
-
- ENUNCIADOS_MENU_CONFIG
|
|
304
|
-
- PROYECTOS_MENU_CONFIG
|
|
305
|
-
|
|
306
|
-
4. **Create lib/data/lessons/lesson1-data.js → lesson7-data.js**
|
|
307
|
-
- Extract all text from lesson files
|
|
308
|
-
- Convert to data objects
|
|
309
|
-
```js
|
|
310
|
-
export const LESSON_1_SISTEMA = {
|
|
311
|
-
enunciado: { id: 1, texto: '...', nivel: '...' },
|
|
312
|
-
intro: { ... },
|
|
313
|
-
challenges: [ ... ],
|
|
314
|
-
examples: [ ... ]
|
|
315
|
-
}
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
**Result:** All content centralized, easy to translate
|
|
319
|
-
|
|
320
|
-
### PHASE 2: Create Builders (Low Risk)
|
|
321
|
-
**Goal:** Reusable execution engines
|
|
322
|
-
|
|
323
|
-
1. **Create lib/builders/LessonBuilder.js**
|
|
324
|
-
- Takes lesson data object
|
|
325
|
-
- Executes intro, steps, challenges
|
|
326
|
-
- ~150 lines
|
|
327
|
-
|
|
328
|
-
2. **Create lib/builders/MenuBuilder.js**
|
|
329
|
-
- Takes menu config
|
|
330
|
-
- Renders interactive/fallback
|
|
331
|
-
- Handles selection
|
|
332
|
-
- ~120 lines
|
|
333
|
-
|
|
334
|
-
3. **Create lib/builders/ProjectBuilder.js**
|
|
335
|
-
- Takes template config
|
|
336
|
-
- Creates/updates projects
|
|
337
|
-
- ~100 lines
|
|
338
|
-
|
|
339
|
-
4. **Create lib/builders/InteractiveBuilder.js**
|
|
340
|
-
- Reusable interactive patterns
|
|
341
|
-
- Arrow keys, prompts, etc.
|
|
342
|
-
- ~80 lines
|
|
343
|
-
|
|
344
|
-
**Result:** Reusable builders for all flows
|
|
345
|
-
|
|
346
|
-
### PHASE 3: Create Template System (Medium Risk)
|
|
347
|
-
**Goal:** Clean template operations
|
|
348
|
-
|
|
349
|
-
1. **Create lib/templates/TemplateProcessor.js**
|
|
350
|
-
- Copy templates
|
|
351
|
-
- Binary file handling
|
|
352
|
-
- ~80 lines
|
|
353
|
-
|
|
354
|
-
2. **Create lib/templates/LevelModifier.js**
|
|
355
|
-
- applyLevelModifications logic
|
|
356
|
-
- Layout/page modifications
|
|
357
|
-
- ~150 lines
|
|
358
|
-
|
|
359
|
-
3. **Create lib/templates/PlaceholderReplacer.js**
|
|
360
|
-
- Replace {{VARIABLES}}
|
|
361
|
-
- Template string processing
|
|
362
|
-
- ~40 lines
|
|
363
|
-
|
|
364
|
-
**Result:** Template operations modular
|
|
365
|
-
|
|
366
|
-
### PHASE 4: Create Executors (Medium Risk)
|
|
367
|
-
**Goal:** Orchestrate builders + data
|
|
368
|
-
|
|
369
|
-
1. **Create lib/executors/enunciados-executor.js**
|
|
370
|
-
- Load lesson data
|
|
371
|
-
- Use MenuBuilder for selection
|
|
372
|
-
- Use LessonBuilder for execution
|
|
373
|
-
- ~80 lines
|
|
374
|
-
|
|
375
|
-
2. **Create lib/executors/sintaxis-executor.js**
|
|
376
|
-
- Load sintaxis lessons
|
|
377
|
-
- Menu + execution flow
|
|
378
|
-
- ~60 lines
|
|
379
|
-
|
|
380
|
-
3. **Create lib/executors/proyectos-executor.js**
|
|
381
|
-
- PR tutorial + portfolio
|
|
382
|
-
- Use ProjectBuilder
|
|
383
|
-
- ~80 lines
|
|
384
|
-
|
|
385
|
-
4. **Create lib/executors/portfolio-executor.js**
|
|
386
|
-
- Level selection + creation
|
|
387
|
-
- ~60 lines
|
|
388
|
-
|
|
389
|
-
**Result:** Clean orchestration layer
|
|
390
|
-
|
|
391
|
-
### PHASE 5: Refactor Entry Point (Low Risk)
|
|
392
|
-
**Goal:** Minimal bin/creta.js
|
|
393
|
-
|
|
394
|
-
1. **Simplify bin/creta.js**
|
|
395
|
-
- Import executors
|
|
396
|
-
- Route commands
|
|
397
|
-
- Handle errors
|
|
398
|
-
- **Target: <100 lines**
|
|
399
|
-
|
|
400
|
-
**Result:** Clean entry point
|
|
401
|
-
|
|
402
|
-
### PHASE 6: Migrate Existing Lessons (High Impact)
|
|
403
|
-
**Goal:** Replace lessons/* with data + LessonBuilder
|
|
404
|
-
|
|
405
|
-
1. **For each lesson1-7:**
|
|
406
|
-
- Extract to data/lessons/lesson{N}-data.js
|
|
407
|
-
- Test with LessonBuilder
|
|
408
|
-
- Remove old lesson file
|
|
409
|
-
|
|
410
|
-
2. **Update imports in executors**
|
|
411
|
-
|
|
412
|
-
**Result:** All lessons use LessonBuilder
|
|
413
|
-
|
|
414
|
-
### PHASE 7: Create Utils (Low Risk)
|
|
415
|
-
**Goal:** Shared utilities
|
|
416
|
-
|
|
417
|
-
1. **Create lib/utils/input.js**
|
|
418
|
-
- readline helpers
|
|
419
|
-
- ~40 lines
|
|
420
|
-
|
|
421
|
-
2. **Create lib/utils/output.js**
|
|
422
|
-
- formatting, colors
|
|
423
|
-
- ~40 lines
|
|
424
|
-
|
|
425
|
-
3. **Create lib/utils/file-utils.js**
|
|
426
|
-
- fs operations
|
|
427
|
-
- ~50 lines
|
|
428
|
-
|
|
429
|
-
**Result:** Clean utility layer
|
|
430
|
-
|
|
431
|
-
## 📊 EXPECTED RESULTS
|
|
432
|
-
|
|
433
|
-
**Before:**
|
|
434
|
-
- bin/creta.js: 1616 lines (mixed concerns)
|
|
435
|
-
- lessons/: 7 files × ~200 lines = 1400 lines (text + logic)
|
|
436
|
-
|
|
437
|
-
**After:**
|
|
438
|
-
- bin/creta.js: <100 lines (pure routing)
|
|
439
|
-
- lib/data/: ~1200 lines (content only, easy to translate)
|
|
440
|
-
- lib/builders/: ~450 lines (4 reusable engines)
|
|
441
|
-
- lib/executors/: ~280 lines (4 orchestrators)
|
|
442
|
-
- lib/templates/: ~270 lines (3 template modules)
|
|
443
|
-
- lib/utils/: ~130 lines (3 utilities)
|
|
444
|
-
|
|
445
|
-
**Total:** ~2430 lines in 25+ focused modules
|
|
446
|
-
**Key win:** Content separated from logic, reusable builders
|
|
447
|
-
|
|
448
|
-
## 🎯 BENEFITS
|
|
449
|
-
|
|
450
|
-
### For Content:
|
|
451
|
-
✅ Easy to translate (just swap data files)
|
|
452
|
-
✅ Non-developers can edit lessons
|
|
453
|
-
✅ Version control friendly (small diffs)
|
|
454
|
-
✅ A/B test different lesson flows
|
|
455
|
-
|
|
456
|
-
### For Code:
|
|
457
|
-
✅ Reusable builders for all lessons
|
|
458
|
-
✅ Test builders once, works for all content
|
|
459
|
-
✅ Add new lesson = just add data file
|
|
460
|
-
✅ DRY - no repeated execution logic
|
|
461
|
-
|
|
462
|
-
### For Maintenance:
|
|
463
|
-
✅ Clear separation of concerns
|
|
464
|
-
✅ Easy to find and fix bugs
|
|
465
|
-
✅ Simple to add features
|
|
466
|
-
✅ Refactor-friendly architecture
|
|
467
|
-
|
|
468
|
-
## 🚀 EXECUTION STRATEGY
|
|
469
|
-
|
|
470
|
-
### Approach: "Discord Pattern Migration"
|
|
471
|
-
1. Create data structure for one lesson
|
|
472
|
-
2. Create builder that executes it
|
|
473
|
-
3. Verify it works identically
|
|
474
|
-
4. Migrate next lesson
|
|
475
|
-
5. Remove old code
|
|
476
|
-
6. Repeat
|
|
477
|
-
|
|
478
|
-
### Testing Each Phase:
|
|
479
|
-
```bash
|
|
480
|
-
# Test lesson with new builder
|
|
481
|
-
node -e "
|
|
482
|
-
import { LESSON_1_SISTEMA } from './lib/data/lessons/lesson1-data.js'
|
|
483
|
-
import { LessonBuilder } from './lib/builders/LessonBuilder.js'
|
|
484
|
-
const lesson = new LessonBuilder(LESSON_1_SISTEMA)
|
|
485
|
-
await lesson.start()
|
|
486
|
-
"
|
|
487
|
-
|
|
488
|
-
# Test full flow
|
|
489
|
-
node bin/creta.js enunciados
|
|
490
|
-
node bin/creta.js portafolio
|
|
491
|
-
```
|
|
492
|
-
|
|
493
|
-
### Git Strategy:
|
|
494
|
-
- Commit after each phase
|
|
495
|
-
- Keep old code until new is tested
|
|
496
|
-
- Easy rollback
|
|
497
|
-
- Tag stable versions
|
|
498
|
-
|
|
499
|
-
### Priority Order:
|
|
500
|
-
1. Phase 1 (data layer) - Foundation
|
|
501
|
-
2. Phase 2 (builders) - Core engines
|
|
502
|
-
3. Phase 7 (utils) - Supporting tools
|
|
503
|
-
4. Phase 4 (executors) - Orchestration
|
|
504
|
-
5. Phase 3 (templates) - Template system
|
|
505
|
-
6. Phase 5 (entry point) - Simplification
|
|
506
|
-
7. Phase 6 (migrate lessons) - Final migration
|
|
507
|
-
|
|
508
|
-
## 📝 ARCHITECTURAL PRINCIPLES
|
|
509
|
-
|
|
510
|
-
### Data-Driven Design:
|
|
511
|
-
1. **Data is King:** All content in data/
|
|
512
|
-
2. **Builders Execute:** Logic in builders/
|
|
513
|
-
3. **Executors Orchestrate:** Flow in executors/
|
|
514
|
-
4. **Entry Routes:** bin/creta.js just routes
|
|
515
|
-
|
|
516
|
-
### Simple Solutions:
|
|
517
|
-
- No over-engineering
|
|
518
|
-
- JavaScript objects (not complex schemas)
|
|
519
|
-
- Readable, not clever
|
|
520
|
-
- Maintainable over perfect
|
|
521
|
-
|
|
522
|
-
### Discord-Inspired Patterns:
|
|
523
|
-
```js
|
|
524
|
-
// Instead of:
|
|
525
|
-
class Lesson7 {
|
|
526
|
-
async start() {
|
|
527
|
-
console.log("hardcoded text...")
|
|
528
|
-
// logic
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
// Do this:
|
|
533
|
-
const LESSON_7 = {
|
|
534
|
-
intro: { text: "..." },
|
|
535
|
-
steps: [...]
|
|
536
|
-
}
|
|
537
|
-
const lesson = new LessonBuilder(LESSON_7)
|
|
538
|
-
await lesson.start()
|
|
539
|
-
```
|
|
540
|
-
|
|
541
|
-
## ✅ SUCCESS CRITERIA
|
|
542
|
-
|
|
543
|
-
Refactoring complete when:
|
|
544
|
-
1. ✅ bin/creta.js < 100 lines
|
|
545
|
-
2. ✅ All content in lib/data/
|
|
546
|
-
3. ✅ All lessons use LessonBuilder
|
|
547
|
-
4. ✅ MenuBuilder handles all menus
|
|
548
|
-
5. ✅ No text hardcoded in logic
|
|
549
|
-
6. ✅ All existing commands work
|
|
550
|
-
7. ✅ Easy to add new lessons (just add data)
|
|
551
|
-
8. ✅ Easy to translate (just swap data files)
|
|
552
|
-
|
|
553
|
-
## 🎯 LONG-TERM WINS
|
|
554
|
-
|
|
555
|
-
### Easy Internationalization:
|
|
556
|
-
```js
|
|
557
|
-
// lib/data/lessons/en/lesson1-data.js
|
|
558
|
-
// lib/data/lessons/es/lesson1-data.js
|
|
559
|
-
// Just swap import based on locale
|
|
560
|
-
```
|
|
561
|
-
|
|
562
|
-
### CMS-Ready:
|
|
563
|
-
- Data files could come from database
|
|
564
|
-
- Non-technical content updates
|
|
565
|
-
- A/B testing different lesson flows
|
|
566
|
-
|
|
567
|
-
### Extensible:
|
|
568
|
-
- New lesson types? Add to builder
|
|
569
|
-
- New step types? Extend executeStep()
|
|
570
|
-
- New templates? Add to ProjectBuilder
|
|
571
|
-
|
|
572
|
-
---
|
|
573
|
-
|
|
574
|
-
**Philosophy:** "Text tells the story, builders bring it to life"
|
|
575
|
-
|
|
576
|
-
**Start Date:** TBD
|
|
577
|
-
**Target Completion:** 2-3 days (phased)
|
|
578
|
-
**Estimated Effort:** 12-16 hours
|
|
579
|
-
**Risk Level:** Low-Medium (data migration is safe, builders are reusable)
|
|
580
|
-
|
|
581
|
-
Last updated: 2025-10-03
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "{{PROJECT_NAME}}",
|
|
3
|
-
"version": "0.0.1",
|
|
4
|
-
"private": true,
|
|
5
|
-
"scripts": {
|
|
6
|
-
"build": "vite build",
|
|
7
|
-
"dev": "vite dev",
|
|
8
|
-
"preview": "vite preview"
|
|
9
|
-
},
|
|
10
|
-
"devDependencies": {
|
|
11
|
-
"@sveltejs/adapter-auto": "^3.0.0",
|
|
12
|
-
"@sveltejs/kit": "^2.0.0",
|
|
13
|
-
"@sveltejs/vite-plugin-svelte": "^4.0.0",
|
|
14
|
-
"svelte": "^5.0.0",
|
|
15
|
-
"tailwindcss": "^4.0.0",
|
|
16
|
-
"@tailwindcss/vite": "^4.0.0",
|
|
17
|
-
"vite": "^5.0.3"
|
|
18
|
-
},
|
|
19
|
-
"type": "module"
|
|
20
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
@import "tailwindcss";
|
|
2
|
-
|
|
3
|
-
/* Animaciones personalizadas */
|
|
4
|
-
@keyframes fade-in {
|
|
5
|
-
from {
|
|
6
|
-
opacity: 0;
|
|
7
|
-
transform: translateY(20px);
|
|
8
|
-
}
|
|
9
|
-
to {
|
|
10
|
-
opacity: 1;
|
|
11
|
-
transform: translateY(0);
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
.animate-fade-in {
|
|
16
|
-
animation: fade-in 1s ease-out;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/* Mejoras de scroll suave */
|
|
20
|
-
html {
|
|
21
|
-
scroll-behavior: smooth;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/* Estilos personalizados para el código */
|
|
25
|
-
code {
|
|
26
|
-
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/* Hover effects para las tarjetas de proyectos */
|
|
30
|
-
.project-card {
|
|
31
|
-
transition: transform 0.2s ease-in-out;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
.project-card:hover {
|
|
35
|
-
transform: translateY(-5px);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/* Efectos de focus mejorados */
|
|
39
|
-
input:focus,
|
|
40
|
-
textarea:focus {
|
|
41
|
-
outline: none;
|
|
42
|
-
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/* Gradientes personalizados */
|
|
46
|
-
.gradient-text {
|
|
47
|
-
background: linear-gradient(45deg, #3b82f6, #8b5cf6);
|
|
48
|
-
-webkit-background-clip: text;
|
|
49
|
-
-webkit-text-fill-color: transparent;
|
|
50
|
-
background-clip: text;
|
|
51
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="es">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8" />
|
|
5
|
-
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
|
-
%sveltekit.head%
|
|
8
|
-
</head>
|
|
9
|
-
<body data-sveltekit-preload-data="hover" class="antialiased">
|
|
10
|
-
<div style="display: contents">%sveltekit.body%</div>
|
|
11
|
-
</body>
|
|
12
|
-
</html>
|