@icarusmx/creta 1.5.15 → 1.5.16

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
@@ -10,7 +10,7 @@ import { PullRequestTutorial } from '../lib/pr-tutorial.js'
10
10
  import { VimSetupTutorial } from '../lib/vim-setup-tutorial.js'
11
11
  import { AWSGuideViewer } from '../lib/aws-guide-viewer.js'
12
12
  import { CommandHelpExecutor } from '../lib/executors/CommandHelpExecutor.js'
13
- import { readExercise, listExercises } from '../lib/readers/exercise-reader.js'
13
+ import { readExercise, listExercises, syncBiblioteca } from '../lib/readers/exercise-reader.js'
14
14
  import { PapersExecutor } from '../lib/papers/PapersExecutor.js'
15
15
  import { ExercisesExecutor } from '../lib/executors/ExercisesExecutor.js'
16
16
  import { executeSintaxis } from '../lib/executors/sintaxis-executor.js'
@@ -193,6 +193,9 @@ if (command.startsWith('portafolio')) {
193
193
  } else if (command === 'exercises' || command === 'ejercicios') {
194
194
  // List all exercises
195
195
  await listExercises()
196
+ } else if (command === 'biblioteca') {
197
+ // Sync exercises to ~/.creta/biblioteca
198
+ await syncBiblioteca()
196
199
  } else if (command === 'help' || command === 'ayuda') {
197
200
  // Show available commands
198
201
  showHelp()
@@ -708,6 +711,7 @@ function showHelp() {
708
711
  console.log(" creta code - Sesión interactiva de programación con IA\n")
709
712
 
710
713
  console.log("🔧 Utilidades:")
714
+ console.log(" creta biblioteca - Sincroniza ejercicios a ~/.creta/biblioteca/")
711
715
  console.log(" creta reset - Reinicia tu progreso (elimina ~/.creta/user.json)")
712
716
  console.log(" creta privacy - Explica qué datos guarda Creta y dónde\n")
713
717
 
@@ -1,6 +1,7 @@
1
- import { readFileSync, readdirSync } from 'fs'
1
+ import { readFileSync, readdirSync, existsSync, mkdirSync, copyFileSync, statSync } from 'fs'
2
2
  import { join, dirname } from 'path'
3
3
  import { fileURLToPath } from 'url'
4
+ import { homedir } from 'os'
4
5
  import chalk from 'chalk'
5
6
 
6
7
  const __filename = fileURLToPath(import.meta.url)
@@ -9,6 +10,78 @@ const __dirname = dirname(__filename)
9
10
  export class ExerciseReader {
10
11
  constructor() {
11
12
  this.exercisesDir = join(__dirname, '../exercises')
13
+ this.bibliotecaDir = join(homedir(), '.creta', 'biblioteca')
14
+ }
15
+
16
+ /**
17
+ * Ensure biblioteca directory exists and sync exercises
18
+ */
19
+ syncBiblioteca(silent = false) {
20
+ try {
21
+ // Create directory if needed
22
+ if (!existsSync(this.bibliotecaDir)) {
23
+ mkdirSync(this.bibliotecaDir, { recursive: true })
24
+ if (!silent) {
25
+ console.log(chalk.cyan('\n📚 Creando biblioteca en ~/.creta/biblioteca...'))
26
+ }
27
+ }
28
+
29
+ // Get all exercise files
30
+ const exercises = this.getAvailableExercises()
31
+ let copied = 0
32
+ let updated = 0
33
+ let skipped = 0
34
+
35
+ exercises.forEach(exercise => {
36
+ const sourcePath = join(this.exercisesDir, exercise.filename)
37
+ const destPath = join(this.bibliotecaDir, exercise.filename)
38
+
39
+ // Check if destination exists and is up to date
40
+ if (existsSync(destPath)) {
41
+ const sourceStats = statSync(sourcePath)
42
+ const destStats = statSync(destPath)
43
+
44
+ if (sourceStats.mtime > destStats.mtime) {
45
+ copyFileSync(sourcePath, destPath)
46
+ updated++
47
+ } else {
48
+ skipped++
49
+ }
50
+ } else {
51
+ copyFileSync(sourcePath, destPath)
52
+ copied++
53
+ }
54
+ })
55
+
56
+ if (!silent) {
57
+ console.log(chalk.green('\n✅ Biblioteca sincronizada'))
58
+ if (copied > 0) console.log(chalk.gray(` ${copied} ejercicio${copied !== 1 ? 's' : ''} copiado${copied !== 1 ? 's' : ''}`))
59
+ if (updated > 0) console.log(chalk.gray(` ${updated} ejercicio${updated !== 1 ? 's' : ''} actualizado${updated !== 1 ? 's' : ''}`))
60
+ if (skipped > 0) console.log(chalk.gray(` ${skipped} ejercicio${skipped !== 1 ? 's' : ''} sin cambios`))
61
+ console.log(chalk.cyan(`\n💡 Abre ejercicios con: nvim ~/.creta/biblioteca/<archivo>.md`))
62
+ console.log(chalk.gray(` Ejemplo: nvim ~/.creta/biblioteca/14-gh-fundamentals.md\n`))
63
+ }
64
+
65
+ return { copied, updated, skipped, total: exercises.length }
66
+ } catch (error) {
67
+ if (!silent) {
68
+ console.error(chalk.red('\n❌ Error sincronizando biblioteca:'), error.message)
69
+ }
70
+ return { copied: 0, updated: 0, skipped: 0, total: 0, error }
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Check if biblioteca needs initialization (show tip on first read)
76
+ */
77
+ checkBiblioteca() {
78
+ if (!existsSync(this.bibliotecaDir)) {
79
+ return {
80
+ exists: false,
81
+ message: chalk.dim(`\n💡 Tip: Ejecuta ${chalk.cyan('creta biblioteca')} para copiar ejercicios a ~/.creta/biblioteca/\n Así podrás abrirlos en nvim con fold markers.`)
82
+ }
83
+ }
84
+ return { exists: true, message: null }
12
85
  }
13
86
 
14
87
  /**
@@ -94,6 +167,13 @@ export class ExerciseReader {
94
167
  const content = readFileSync(filepath, 'utf-8')
95
168
 
96
169
  this.displayExercise(exercise, content)
170
+
171
+ // Show biblioteca tip on first read
172
+ const bibliotecaStatus = this.checkBiblioteca()
173
+ if (!bibliotecaStatus.exists && bibliotecaStatus.message) {
174
+ console.log(bibliotecaStatus.message)
175
+ }
176
+
97
177
  return true
98
178
  } catch (error) {
99
179
  console.error(chalk.red('❌ Error leyendo ejercicio:'), error.message)
@@ -195,3 +275,11 @@ export async function listExercises() {
195
275
  const reader = new ExerciseReader()
196
276
  reader.list()
197
277
  }
278
+
279
+ /**
280
+ * Sync biblioteca CLI entry point
281
+ */
282
+ export async function syncBiblioteca() {
283
+ const reader = new ExerciseReader()
284
+ reader.syncBiblioteca()
285
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@icarusmx/creta",
3
- "version": "1.5.15",
3
+ "version": "1.5.16",
4
4
  "description": "Salgamos de este laberinto.",
5
5
  "type": "module",
6
6
  "bin": {