@icarusmx/creta 1.5.1 → 1.5.4

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
@@ -9,13 +9,15 @@ import { CretaCodeSession } from '../lib/session.js'
9
9
  import { PullRequestTutorial } from '../lib/pr-tutorial.js'
10
10
  import { CommandHelpExecutor } from '../lib/executors/CommandHelpExecutor.js'
11
11
  import { PapersExecutor } from '../lib/papers/PapersExecutor.js'
12
- import { Lesson1SystemDecomposition } from '../lessons/lesson1-system-decomposition.js'
13
- import { Lesson2ObjectRequests } from '../lessons/lesson2-object-requests.js'
14
- import { Lesson3OnlyWay } from '../lessons/lesson3-only-way.js'
15
- import { Lesson4OperationSignatures } from '../lessons/lesson4-operation-signatures.js'
16
- import { Lesson5InterfaceSet } from '../lessons/lesson5-interface-set.js'
17
- import { Lesson6InterfaceDesign } from '../lessons/lesson6-interface-design.js'
18
- import { Lesson7ObjectDefinition } from '../lessons/lesson7-object-definition.js'
12
+ import { ExercisesExecutor } from '../lib/executors/ExercisesExecutor.js'
13
+ import { LessonBuilder } from '../lib/builders/LessonBuilder.js'
14
+ import { LESSON_1_SYSTEM_DECOMPOSITION } from '../lib/data/lessons/lesson1-system-decomposition.js'
15
+ import { LESSON_2_OBJECT_REQUESTS } from '../lib/data/lessons/lesson2-object-requests.js'
16
+ import { LESSON_3_ONLY_WAY } from '../lib/data/lessons/lesson3-only-way.js'
17
+ import { LESSON_4_OPERATION_SIGNATURES } from '../lib/data/lessons/lesson4-operation-signatures.js'
18
+ import { LESSON_5_INTERFACE_SET } from '../lib/data/lessons/lesson5-interface-set.js'
19
+ import { LESSON_6_INTERFACE_DESIGN } from '../lib/data/lessons/lesson6-interface-design.js'
20
+ import { LESSON_7_OBJECT_DEFINITION } from '../lib/data/lessons/lesson7-object-definition.js'
19
21
 
20
22
  const ENUNCIADOS = [
21
23
  {
@@ -637,7 +639,8 @@ async function startMainMenuInteractive() {
637
639
  { id: 1, title: "Aprender sintaxis" },
638
640
  { id: 2, title: "Aprender conceptos de diseño" },
639
641
  { id: 3, title: "Construir proyectos" },
640
- { id: 4, title: "📄 Recrear papers clásicos" }
642
+ { id: 4, title: "Recrear papers clásicos" },
643
+ { id: 5, title: "Practicar con ejercicios" }
641
644
  ]
642
645
 
643
646
  let selectedIndex = 0
@@ -710,6 +713,9 @@ Salgamos de este laberinto 🏛️
710
713
  } else if (selectedOption.id === 4) {
711
714
  const executor = new PapersExecutor()
712
715
  executor.execute().then(resolve)
716
+ } else if (selectedOption.id === 5) {
717
+ const executor = new ExercisesExecutor()
718
+ executor.execute().then(resolve)
713
719
  }
714
720
  return
715
721
  }
@@ -746,10 +752,11 @@ async function startMainMenuFallback() {
746
752
  console.log("1. Aprender sintaxis")
747
753
  console.log("2. Aprender conceptos de diseño")
748
754
  console.log("3. Construir proyectos")
749
- console.log("4. 📄 Recrear papers clásicos")
755
+ console.log("4. Recrear papers clásicos")
756
+ console.log("5. Practicar con ejercicios")
750
757
  console.log("")
751
758
 
752
- const respuesta = await askQuestion("Elige una opción (1-4) o 'q' para salir: ")
759
+ const respuesta = await askQuestion("Elige una opción (1-5) o 'q' para salir: ")
753
760
 
754
761
  if (respuesta.toLowerCase() === 'q') {
755
762
  console.log("Hecho con <3 por icarus.mx")
@@ -772,8 +779,12 @@ async function startMainMenuFallback() {
772
779
  rl.close()
773
780
  const executor = new PapersExecutor()
774
781
  await executor.execute()
782
+ } else if (opcionSeleccionada === 5) {
783
+ rl.close()
784
+ const executor = new ExercisesExecutor()
785
+ await executor.execute()
775
786
  } else {
776
- console.log("❌ Opción no válida. Elige 1, 2, 3 o 4.")
787
+ console.log("❌ Opción no válida. Elige 1, 2, 3, 4 o 5.")
777
788
  rl.close()
778
789
  }
779
790
 
@@ -892,7 +903,7 @@ async function startEnunciadosSelectorInteractive() {
892
903
  await new Promise(resolve => setTimeout(resolve, 1500)) // Brief pause
893
904
 
894
905
  try {
895
- const lesson1 = new Lesson1SystemDecomposition()
906
+ const lesson1 = new LessonBuilder(LESSON_1_SYSTEM_DECOMPOSITION)
896
907
  await lesson1.start()
897
908
  await returnToMainMenu()
898
909
  } catch (error) {
@@ -908,7 +919,7 @@ async function startEnunciadosSelectorInteractive() {
908
919
  await new Promise(resolve => setTimeout(resolve, 1500)) // Brief pause
909
920
 
910
921
  try {
911
- const lesson1 = new Lesson1SystemDecomposition()
922
+ const lesson1 = new LessonBuilder(LESSON_1_SYSTEM_DECOMPOSITION)
912
923
  await lesson1.start()
913
924
  await returnToMainMenu()
914
925
  } catch (error) {
@@ -924,7 +935,7 @@ async function startEnunciadosSelectorInteractive() {
924
935
  await new Promise(resolve => setTimeout(resolve, 1500)) // Brief pause
925
936
 
926
937
  try {
927
- const lesson2 = new Lesson2ObjectRequests()
938
+ const lesson2 = new LessonBuilder(LESSON_2_OBJECT_REQUESTS)
928
939
  await lesson2.start()
929
940
  await returnToMainMenu()
930
941
  } catch (error) {
@@ -940,7 +951,7 @@ async function startEnunciadosSelectorInteractive() {
940
951
  await new Promise(resolve => setTimeout(resolve, 1500)) // Brief pause
941
952
 
942
953
  try {
943
- const lesson3 = new Lesson3OnlyWay()
954
+ const lesson3 = new LessonBuilder(LESSON_3_ONLY_WAY)
944
955
  await lesson3.start()
945
956
  await returnToMainMenu()
946
957
  } catch (error) {
@@ -956,7 +967,7 @@ async function startEnunciadosSelectorInteractive() {
956
967
  await new Promise(resolve => setTimeout(resolve, 1500)) // Brief pause
957
968
 
958
969
  try {
959
- const lesson4 = new Lesson4OperationSignatures()
970
+ const lesson4 = new LessonBuilder(LESSON_4_OPERATION_SIGNATURES)
960
971
  await lesson4.start()
961
972
  await returnToMainMenu()
962
973
  } catch (error) {
@@ -972,7 +983,7 @@ async function startEnunciadosSelectorInteractive() {
972
983
  await new Promise(resolve => setTimeout(resolve, 1500)) // Brief pause
973
984
 
974
985
  try {
975
- const lesson5 = new Lesson5InterfaceSet()
986
+ const lesson5 = new LessonBuilder(LESSON_5_INTERFACE_SET)
976
987
  await lesson5.start()
977
988
  await returnToMainMenu()
978
989
  } catch (error) {
@@ -988,7 +999,7 @@ async function startEnunciadosSelectorInteractive() {
988
999
  await new Promise(resolve => setTimeout(resolve, 1500)) // Brief pause
989
1000
 
990
1001
  try {
991
- const lesson6 = new Lesson6InterfaceDesign()
1002
+ const lesson6 = new LessonBuilder(LESSON_6_INTERFACE_DESIGN)
992
1003
  await lesson6.start()
993
1004
  await returnToMainMenu()
994
1005
  } catch (error) {
@@ -1004,7 +1015,7 @@ async function startEnunciadosSelectorInteractive() {
1004
1015
  await new Promise(resolve => setTimeout(resolve, 1500)) // Brief pause
1005
1016
 
1006
1017
  try {
1007
- const lesson7 = new Lesson7ObjectDefinition()
1018
+ const lesson7 = new LessonBuilder(LESSON_7_OBJECT_DEFINITION)
1008
1019
  await lesson7.start()
1009
1020
  await returnToMainMenu()
1010
1021
  } catch (error) {
@@ -1098,7 +1109,7 @@ async function startEnunciadosSelectorFallback() {
1098
1109
  await new Promise(resolve => setTimeout(resolve, 1500)) // Brief pause
1099
1110
 
1100
1111
  try {
1101
- const lesson1 = new Lesson1SystemDecomposition()
1112
+ const lesson1 = new LessonBuilder(LESSON_1_SYSTEM_DECOMPOSITION)
1102
1113
  await lesson1.start()
1103
1114
  } catch (error) {
1104
1115
  console.error("\n❌ Error al ejecutar la lección:", error.message)
@@ -1114,7 +1125,7 @@ async function startEnunciadosSelectorFallback() {
1114
1125
  await new Promise(resolve => setTimeout(resolve, 1500)) // Brief pause
1115
1126
 
1116
1127
  try {
1117
- const lesson1 = new Lesson1SystemDecomposition()
1128
+ const lesson1 = new LessonBuilder(LESSON_1_SYSTEM_DECOMPOSITION)
1118
1129
  await lesson1.start()
1119
1130
  } catch (error) {
1120
1131
  console.error("\n❌ Error al ejecutar la lección:", error.message)
@@ -1130,7 +1141,7 @@ async function startEnunciadosSelectorFallback() {
1130
1141
  await new Promise(resolve => setTimeout(resolve, 1500)) // Brief pause
1131
1142
 
1132
1143
  try {
1133
- const lesson2 = new Lesson2ObjectRequests()
1144
+ const lesson2 = new LessonBuilder(LESSON_2_OBJECT_REQUESTS)
1134
1145
  await lesson2.start()
1135
1146
  } catch (error) {
1136
1147
  console.error("\n❌ Error al ejecutar la lección:", error.message)
@@ -1146,7 +1157,7 @@ async function startEnunciadosSelectorFallback() {
1146
1157
  await new Promise(resolve => setTimeout(resolve, 1500)) // Brief pause
1147
1158
 
1148
1159
  try {
1149
- const lesson3 = new Lesson3OnlyWay()
1160
+ const lesson3 = new LessonBuilder(LESSON_3_ONLY_WAY)
1150
1161
  await lesson3.start()
1151
1162
  } catch (error) {
1152
1163
  console.error("\n❌ Error al ejecutar la lección:", error.message)
@@ -1162,7 +1173,7 @@ async function startEnunciadosSelectorFallback() {
1162
1173
  await new Promise(resolve => setTimeout(resolve, 1500)) // Brief pause
1163
1174
 
1164
1175
  try {
1165
- const lesson4 = new Lesson4OperationSignatures()
1176
+ const lesson4 = new LessonBuilder(LESSON_4_OPERATION_SIGNATURES)
1166
1177
  await lesson4.start()
1167
1178
  } catch (error) {
1168
1179
  console.error("\n❌ Error al ejecutar la lección:", error.message)
@@ -1178,7 +1189,7 @@ async function startEnunciadosSelectorFallback() {
1178
1189
  await new Promise(resolve => setTimeout(resolve, 1500)) // Brief pause
1179
1190
 
1180
1191
  try {
1181
- const lesson5 = new Lesson5InterfaceSet()
1192
+ const lesson5 = new LessonBuilder(LESSON_5_INTERFACE_SET)
1182
1193
  await lesson5.start()
1183
1194
  } catch (error) {
1184
1195
  console.error("\n❌ Error al ejecutar la lección:", error.message)
@@ -1194,7 +1205,7 @@ async function startEnunciadosSelectorFallback() {
1194
1205
  await new Promise(resolve => setTimeout(resolve, 1500)) // Brief pause
1195
1206
 
1196
1207
  try {
1197
- const lesson6 = new Lesson6InterfaceDesign()
1208
+ const lesson6 = new LessonBuilder(LESSON_6_INTERFACE_DESIGN)
1198
1209
  await lesson6.start()
1199
1210
  } catch (error) {
1200
1211
  console.error("\n❌ Error al ejecutar la lección:", error.message)
@@ -1210,7 +1221,7 @@ async function startEnunciadosSelectorFallback() {
1210
1221
  await new Promise(resolve => setTimeout(resolve, 1500)) // Brief pause
1211
1222
 
1212
1223
  try {
1213
- const lesson7 = new Lesson7ObjectDefinition()
1224
+ const lesson7 = new LessonBuilder(LESSON_7_OBJECT_DEFINITION)
1214
1225
  await lesson7.start()
1215
1226
  } catch (error) {
1216
1227
  console.error("\n❌ Error al ejecutar la lección:", error.message)
@@ -0,0 +1,271 @@
1
+ import { createInterface } from 'readline'
2
+ import { execSync } from 'child_process'
3
+ import path from 'path'
4
+ import { fileURLToPath } from 'url'
5
+ import fs from 'fs'
6
+
7
+ const __filename = fileURLToPath(import.meta.url)
8
+ const __dirname = path.dirname(__filename)
9
+
10
+ export class ExercisesExecutor {
11
+ constructor() {
12
+ this.exercises = [
13
+ {
14
+ id: 1,
15
+ title: "Array & Object Manipulation Warmups",
16
+ description: "JavaScript fundamentals with LazyVim tips",
17
+ file: "array-object-manipulation.md",
18
+ lines: 1282,
19
+ topics: ["JavaScript", "Arrays", "Objects", "LazyVim"]
20
+ },
21
+ {
22
+ id: 2,
23
+ title: "Git Stash Workflow",
24
+ description: "Wrong branch recovery patterns",
25
+ file: "git-stash-workflow.md",
26
+ lines: 427,
27
+ topics: ["Git", "Stash", "Branching", "Workflow"]
28
+ },
29
+ {
30
+ id: 3,
31
+ title: "Railway Deployment Guide",
32
+ description: "Deploy Node.js apps with Railway CLI",
33
+ file: "railway-deployment.md",
34
+ lines: 500,
35
+ topics: ["Railway", "Deployment", "Node.js", "DevOps"]
36
+ }
37
+ ]
38
+ }
39
+
40
+ async execute() {
41
+ // Check if setRawMode is available
42
+ if (typeof process.stdin.setRawMode === 'function') {
43
+ return await this.executeInteractive()
44
+ } else {
45
+ return await this.executeFallback()
46
+ }
47
+ }
48
+
49
+ async executeInteractive() {
50
+ console.log("\n📝 Ejercicios de Práctica")
51
+ console.log("Elige qué ejercicio quieres practicar:")
52
+ console.log("")
53
+
54
+ let selectedIndex = 0
55
+
56
+ // Enable raw mode
57
+ process.stdin.setRawMode(true)
58
+ process.stdin.resume()
59
+ process.stdin.setEncoding('utf8')
60
+
61
+ const renderOptions = () => {
62
+ // Clear screen
63
+ process.stdout.write('\x1b[2J')
64
+ process.stdout.write('\x1b[H')
65
+
66
+ console.log("📝 Ejercicios de Práctica")
67
+ console.log("Elige qué ejercicio quieres practicar:")
68
+ console.log("")
69
+
70
+ this.exercises.forEach((exercise, index) => {
71
+ const isSelected = index === selectedIndex
72
+ const prefix = isSelected ? '▶ ' : ' '
73
+ const highlight = isSelected ? '\x1b[36m' : '\x1b[37m'
74
+ const reset = '\x1b[0m'
75
+
76
+ console.log(`${highlight}${prefix}${exercise.id}. ${exercise.title}${reset}`)
77
+ if (isSelected) {
78
+ console.log(`${highlight} ${exercise.description} (${exercise.lines} líneas)${reset}`)
79
+ }
80
+ console.log("")
81
+ })
82
+
83
+ console.log("\n💡 Tip: Estos archivos están optimizados para LazyVim")
84
+ console.log(" Usa 'nvim' para abrirlos y aprovechar los fold markers")
85
+ }
86
+
87
+ return new Promise((resolve) => {
88
+ renderOptions()
89
+
90
+ const onKeyPress = async (key) => {
91
+ if (key === 'q' || key === '\x03') { // q or Ctrl+C
92
+ process.stdin.setRawMode(false)
93
+ process.stdin.removeListener('data', onKeyPress)
94
+ console.log("\nHecho con <3 por icarus.mx")
95
+ resolve()
96
+ return
97
+ }
98
+
99
+ if (key === '\r' || key === '\n') { // Enter
100
+ process.stdin.setRawMode(false)
101
+ process.stdin.removeListener('data', onKeyPress)
102
+
103
+ const selectedExercise = this.exercises[selectedIndex]
104
+
105
+ // Clear screen
106
+ process.stdout.write('\x1b[2J')
107
+ process.stdout.write('\x1b[H')
108
+
109
+ await this.openExercise(selectedExercise)
110
+ resolve()
111
+ return
112
+ }
113
+
114
+ // Arrow keys
115
+ if (key === '\u001b[A') { // Up
116
+ selectedIndex = selectedIndex > 0 ? selectedIndex - 1 : this.exercises.length - 1
117
+ renderOptions()
118
+ } else if (key === '\u001b[B') { // Down
119
+ selectedIndex = selectedIndex < this.exercises.length - 1 ? selectedIndex + 1 : 0
120
+ renderOptions()
121
+ }
122
+ }
123
+
124
+ process.stdin.on('data', onKeyPress)
125
+ })
126
+ }
127
+
128
+ async executeFallback() {
129
+ const rl = createInterface({
130
+ input: process.stdin,
131
+ output: process.stdout
132
+ })
133
+
134
+ const askQuestion = (question) => {
135
+ return new Promise((resolve) => {
136
+ rl.question(question, resolve)
137
+ })
138
+ }
139
+
140
+ try {
141
+ console.log("\n📝 Ejercicios de Práctica")
142
+ console.log("Elige qué ejercicio quieres practicar:")
143
+ console.log("")
144
+
145
+ this.exercises.forEach((exercise) => {
146
+ console.log(`${exercise.id}. ${exercise.title}`)
147
+ console.log(` ${exercise.description} (${exercise.lines} líneas)`)
148
+ console.log("")
149
+ })
150
+
151
+ console.log("💡 Tip: Estos archivos están optimizados para LazyVim")
152
+ console.log(" Usa 'nvim' para abrirlos y aprovechar los fold markers")
153
+ console.log("")
154
+
155
+ const respuesta = await askQuestion(`Elige una opción (1-${this.exercises.length}) o 'q' para salir: `)
156
+
157
+ if (respuesta.toLowerCase() === 'q') {
158
+ console.log("Hecho con <3 por icarus.mx")
159
+ rl.close()
160
+ return
161
+ }
162
+
163
+ const opcionSeleccionada = parseInt(respuesta)
164
+
165
+ if (opcionSeleccionada >= 1 && opcionSeleccionada <= this.exercises.length) {
166
+ const selectedExercise = this.exercises[opcionSeleccionada - 1]
167
+ rl.close()
168
+ await this.openExercise(selectedExercise)
169
+ } else {
170
+ console.log(`❌ Opción no válida. Elige un número entre 1 y ${this.exercises.length}.`)
171
+ rl.close()
172
+ }
173
+
174
+ } catch (error) {
175
+ console.error('Error:', error.message)
176
+ rl.close()
177
+ process.exit(1)
178
+ }
179
+ }
180
+
181
+ async openExercise(exercise) {
182
+ const exercisePath = path.join(__dirname, '..', 'exercises', exercise.file)
183
+
184
+ console.log(`\n📖 ${exercise.title}`)
185
+ console.log("=" .repeat(50))
186
+ console.log("")
187
+ console.log(`📍 Ubicación: ${exercisePath}`)
188
+ console.log(`📊 Líneas: ${exercise.lines}`)
189
+ console.log(`🏷️ Temas: ${exercise.topics.join(', ')}`)
190
+ console.log("")
191
+
192
+ // Check if file exists
193
+ if (!fs.existsSync(exercisePath)) {
194
+ console.log(`❌ Error: No se encontró el archivo ${exercise.file}`)
195
+ console.log("")
196
+ console.log("💡 Tip: Asegúrate de estar ejecutando Creta desde el directorio correcto")
197
+ return
198
+ }
199
+
200
+ console.log("📚 Opciones:")
201
+ console.log("")
202
+ console.log("1. Abrir con nvim (recomendado para aprovechar fold markers)")
203
+ console.log("2. Mostrar la ruta (copiar al portapapeles)")
204
+ console.log("3. Ver los primeros 20 líneas")
205
+ console.log("")
206
+
207
+ const rl = createInterface({
208
+ input: process.stdin,
209
+ output: process.stdout
210
+ })
211
+
212
+ const askQuestion = (question) => {
213
+ return new Promise((resolve) => {
214
+ rl.question(question, resolve)
215
+ })
216
+ }
217
+
218
+ const choice = await askQuestion("Elige una opción (1-3) o Enter para abrir con nvim: ")
219
+ rl.close()
220
+
221
+ if (choice === '' || choice === '1') {
222
+ // Open with nvim
223
+ console.log("\n🚀 Abriendo con nvim...")
224
+ console.log("💡 Tip: Usa 'zM' para cerrar todos los folds y ver la estructura")
225
+ console.log("")
226
+
227
+ try {
228
+ // Try to open with nvim
229
+ execSync(`nvim "${exercisePath}"`, { stdio: 'inherit' })
230
+ } catch (error) {
231
+ console.log("\n⚠️ No se pudo abrir nvim. Intentando con el editor por defecto...")
232
+ try {
233
+ execSync(`$EDITOR "${exercisePath}" || vi "${exercisePath}"`, { stdio: 'inherit' })
234
+ } catch (fallbackError) {
235
+ console.log("\n❌ No se pudo abrir ningún editor.")
236
+ console.log(`📍 Abre manualmente: ${exercisePath}`)
237
+ }
238
+ }
239
+ } else if (choice === '2') {
240
+ // Show path
241
+ console.log("\n📋 Ruta copiada al portapapeles (en algunos sistemas):")
242
+ console.log(exercisePath)
243
+ console.log("")
244
+ console.log("💡 Tip: Usa este comando para abrirlo:")
245
+ console.log(` nvim "${exercisePath}"`)
246
+
247
+ // Try to copy to clipboard (macOS)
248
+ try {
249
+ execSync(`echo "${exercisePath}" | pbcopy`, { stdio: 'ignore' })
250
+ console.log("✓ Ruta copiada al portapapeles (macOS)")
251
+ } catch (error) {
252
+ // Silently fail if pbcopy not available
253
+ }
254
+ } else if (choice === '3') {
255
+ // Show preview
256
+ console.log("\n📄 Primeras 20 líneas:")
257
+ console.log("=" .repeat(50))
258
+ try {
259
+ const preview = execSync(`head -20 "${exercisePath}"`, { encoding: 'utf8' })
260
+ console.log(preview)
261
+ } catch (error) {
262
+ console.log("❌ Error al leer el archivo")
263
+ }
264
+ console.log("=" .repeat(50))
265
+ console.log("")
266
+ console.log(`💡 Abre el archivo completo con: nvim "${exercisePath}"`)
267
+ }
268
+
269
+ console.log("")
270
+ }
271
+ }
@@ -66,6 +66,7 @@ export class UserState {
66
66
 
67
67
  static setName(name) {
68
68
  const state = loadState()
69
+ if (!state) return null
69
70
  state.name = name
70
71
  saveState(state)
71
72
  return state
@@ -73,6 +74,18 @@ export class UserState {
73
74
 
74
75
  static updateLastSeen() {
75
76
  const state = loadState()
77
+ if (!state) {
78
+ console.error('Warning: Could not load user state')
79
+ return {
80
+ name: null,
81
+ createdAt: new Date().toISOString(),
82
+ lessonsCompleted: [],
83
+ projectsCreated: [],
84
+ discord: null,
85
+ stats: { totalSessions: 0, lastSeen: null },
86
+ lastSeen: null
87
+ }
88
+ }
76
89
  const now = new Date().toISOString()
77
90
  state.lastSeen = now
78
91
  state.stats = state.stats || { totalSessions: 0, lastSeen: null }
@@ -84,6 +97,7 @@ export class UserState {
84
97
 
85
98
  static addCompletedLesson(lessonId) {
86
99
  const state = loadState()
100
+ if (!state) return null
87
101
  const alreadyCompleted = state.lessonsCompleted.some(
88
102
  lesson => typeof lesson === 'object' ? lesson.id === lessonId : lesson === lessonId
89
103
  )
@@ -100,6 +114,7 @@ export class UserState {
100
114
 
101
115
  static addProject(projectName) {
102
116
  const state = loadState()
117
+ if (!state) return null
103
118
  state.projectsCreated = state.projectsCreated || []
104
119
  state.projectsCreated.push({
105
120
  name: projectName,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@icarusmx/creta",
3
- "version": "1.5.1",
3
+ "version": "1.5.4",
4
4
  "description": "Salgamos de este laberinto.",
5
5
  "type": "module",
6
6
  "bin": {