[
  {
    "path": ".gitignore",
    "content": "node_modules/"
  },
  {
    "path": ".vscode/launch.json",
    "content": "{\n    // Use IntelliSense to learn about possible attributes.\n    // Hover to view descriptions of existing attributes.\n    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387\n    \"version\": \"0.2.0\",\n    \"configurations\": [\n        {\n            \"type\": \"node\",\n            \"request\": \"launch\",\n            \"name\": \"Launch Program\",\n            \"skipFiles\": [\n                \"<node_internals>/**\"\n            ],\n            \"program\": \"${workspaceFolder}/Intermediate/17-debugging.js\"\n        }\n    ]\n}"
  },
  {
    "path": "Basic/00-helloworld.js",
    "content": "/*\nClases 1 a 14 (sin código)\nVídeo: https://youtu.be/1glVfFxj8a4\n\nClase 15 - Hola mundo\nVídeo: https://youtu.be/1glVfFxj8a4?t=2390\n*/\n\n// Esto es un comentario simple\n\n/*\nEsto es\nun comentario\nen varias líneas\n*/\n\nconsole.log(\"¡Hola, JavaScript!\")\nconsole.log('¡Hola, JavaScript!')\nconsole.log(`¡Hola, JavaScript!`)\n\n// console.log(\"¡Hola, JavaScript!\")\n\n/*\nconsole.log(\"¡Hola, JavaScript!\")\nconsole.log('¡Hola, JavaScript!')\nconsole.log(`¡Hola, JavaScript!`)\n*/\n\nconsole.log(\"5\")\nconsole.log(5)\nconsole.log(5 + 2)\nconsole.log(5 - 2)\nconsole.log(5 * 2)\nconsole.log(5 / 2)\nconsole.log(5 % 2)\nconsole.log(5 ** 2)"
  },
  {
    "path": "Basic/01-variables.js",
    "content": "/*\nClase 16 - Variables\nVídeo: https://youtu.be/1glVfFxj8a4?t=3049\n*/\n\n// var\n\nvar helloWorld = \"¡Hola, JavaScript!\"\nconsole.log(helloWorld)\n\nhelloWorld = \"¡Hola de nuevo, JavaScript!\"\nconsole.log(helloWorld)\n\n// let\n\nlet helloWorld2 = \"¡Hola, JavaScript 2!\"\nconsole.log(helloWorld2)\n\nhelloWorld2 = \"¡Hola de nuevo, JavaScript 2!\"\nconsole.log(helloWorld2)\n\n// const\n\nconst helloWorld3 = \"¡Hola, JavaScript 3!\"\nconsole.log(helloWorld3)\n\n// Error\n// helloWorld3 = \"¡Hola de nuevo, JavaScript 2!\"\n// console.log(helloWorld3)"
  },
  {
    "path": "Basic/02-datatypes.js",
    "content": "/*\nClase 17 - Tipos de datos\nVídeo: https://youtu.be/1glVfFxj8a4?t=3599\n*/\n\n// Tipos de datos primitivos\n\n// Cadenas de texto (string)\nlet myName = \"Brais Moure\"\nlet alias = 'MoureDev'\nlet email = `braismoure@mouredev.com`\n\n// Números (number)\nlet age = 37 // Entero\nlet height = 1.77 // Decimal\n\n// Booleanos (boolean)\nlet isTeacher = true\nlet isStudent = false\n\n// Undefined\nlet undefinedValue\nconsole.log(undefinedValue)\n\n// Null\nlet nullValue = null\n\n// Symbol\n\nlet mySymbol = Symbol(\"mysymbol\")\n\n// BigInt\n\nlet myBigInt = BigInt(817239871289371986589716389471628379612983761289376129)\nlet myBigInt2 = 817239871289371986589716389471628379612983761289376129n\n\n// Mostramos los tipos de datos\nconsole.log(typeof myName)\nconsole.log(typeof alias)\nconsole.log(typeof email)\n\nconsole.log(typeof age)\nconsole.log(typeof height)\n\nconsole.log(typeof isTeacher)\nconsole.log(typeof isStudent)\n\nconsole.log(typeof undefinedValue)\n\nconsole.log(typeof nullValue)\n\nconsole.log(typeof mySymbol)\n\nconsole.log(typeof myBigInt)\nconsole.log(typeof myBigInt2)"
  },
  {
    "path": "Basic/03-beginner-exercises.js",
    "content": "/*\nClase 18 - Ejercicios: primeros pasos\nVídeo: https://youtu.be/1glVfFxj8a4?t=4733\n*/\n\n// 1. Escribe un comentario en una línea\n\n// 2. Escribe un comentario en varias líneas\n\n// 3. Declara variables con valores asociados a todos los datos de tipo primitivos\n\n// 4. Imprime por consola el valor de todas las variables\n\n// 5. Imprime por consola el tipo de todas las variables\n\n// 6. A continuación, modifica los valores de las variables por otros del mismo tipo\n\n// 7. A continuación, modifica los valores de las variables por otros de distinto tipo\n\n// 8. Declara constantes con valores asociados a todos los tipos de datos primitivos\n\n// 9. A continuación, modifica los valores de las constantes\n\n// 10. Comenta las líneas que produzcan algún tipo de error al ejecutarse"
  },
  {
    "path": "Basic/04-operators.js",
    "content": "/*\nClase 19 - Operadores\nVídeo: https://youtu.be/1glVfFxj8a4?t=4937\n*/\n\n// Operadores Aritméticos\n\nlet a = 5\nlet b = 10\n\nconsole.log(a + b) // Suma\nconsole.log(a - b) // Resta\nconsole.log(a * b) // Multiplicación\nconsole.log(a / b) // División\n\nconsole.log(a % b) // Módulo\nconsole.log(a ** b) // Exponente\n\na++ // Incremento\nconsole.log(a)\n\nb-- // Decremento\nconsole.log(b)\n\n// Operadores de asignacion\n\nlet myVariable = 2\nconsole.log(myVariable)\nmyVariable += 2 // Suma con asignación\nconsole.log(myVariable)\n\nmyVariable -= 2 // Resta con asignación\nmyVariable *= 2 // Multiplicación con asignación\nmyVariable /= 2 // División con asignación\nmyVariable %= 2 // Módulo con asignación\nmyVariable **= 2 // Exponente con asignación\n\n// Operadores de comparación\n\nconsole.log(a > b) // Mayor que\nconsole.log(a < b) // Menor que\nconsole.log(a >= b) // Mayor o igual que\nconsole.log(a <= b) // Menor o igual que\nconsole.log(a == b) // Igualdad por valor\nconsole.log(a == 6)\nconsole.log(a == \"6\")\nconsole.log(a == a)\nconsole.log(a === a) // Igualdad por identidad (por tipo y valor) o igualdad estricta\nconsole.log(a === 6)\nconsole.log(a === \"6\")\nconsole.log(a != 6) // Desigualdad por valor\nconsole.log(a !== \"6\") // Desigualdad por identidad (por tipo y valor) o desigualdad estricta\nconsole.log(0 == false)\nconsole.log(1 == false)\nconsole.log(2 == false)\nconsole.log(0 == \"\")\nconsole.log(0 == \" \")\nconsole.log(0 == '')\nconsole.log(0 == \"Hola\")\nconsole.log(0 === \"\")\nconsole.log(undefined == null)\nconsole.log(undefined === null)\n\n/*\nTruthy values (valores verdaderos)\n\n- Todos los numeros positivos y negativos menos el cero\n- Todas las cadenas de texto menos las vacías\n- El boolean true\n*/\n\n/*\nFalsy values (valores falsos)\n\n- 0\n-  0n\n- null\n- undefined\n- NaN (Not a Number)\n- El boolean false\n- Cadenas de texto vacías \n*/\n\n// Operadores lógicos\n\n// and (&&)\nconsole.log(5 > 10 && 15 > 20)\nconsole.log(5 < 10 && 15 < 20)\nconsole.log(5 < 10 && 15 > 20)\nconsole.log(5 > 10 && 15 > 20 && 30 > 40)\n\n// or (||)\nconsole.log(5 > 10 || 15 > 20)\nconsole.log(5 < 10 || 15 < 20)\nconsole.log(5 < 10 || 15 > 20)\nconsole.log(5 > 10 || 15 > 20 || 30 > 40)\n\nconsole.log(5 > 10 && 15 > 20 || 30 < 40)\n\n// not (!)\nconsole.log(!true)\nconsole.log(!false)\nconsole.log(!(5 > 10 && 15 > 20))\nconsole.log(!(5 > 10 || 15 > 20))\n\n// Operadores ternarios\n\nconst isRaining = false\nisRaining ? console.log(\"Está lloviendo\") : console.log(\"No está lloviendo\")"
  },
  {
    "path": "Basic/05-operators-exercises.js",
    "content": "/*\nClase 20 - Ejercicios: Operadores\nVídeo: https://youtu.be/1glVfFxj8a4?t=6458\n*/\n\n// 1. Crea una variable para cada operación aritmética\n\n// 2. Crea una variable para cada tipo de operación de asignación,\n//    que haga uso de las variables utilizadas para las operaciones aritméticas\n\n// 3. Imprime 5 comparaciones verdaderas con diferentes operadores de comparación\n\n// 4. Imprime 5 comparaciones falsas con diferentes operadores de comparación\n\n// 5. Utiliza el operador lógico and\n\n// 6. Utiliza el operador lógico or\n\n// 7. Combina ambos operadores lógicos\n\n// 8. Añade alguna negación\n\n// 9. Utiliza el operador ternario\n\n// 10. Combina operadores aritméticos, de comparáción y lógicas"
  },
  {
    "path": "Basic/06-strings.js",
    "content": "/*\nClase 21 - Strings\nVídeo: https://youtu.be/1glVfFxj8a4?t=6565\n*/\n\n// Strings (cadenas de texto)\n\n// Concatenación\n\nlet myName = \"Brais\"\nlet greeting = \"Hola, \" + myName + \"!\"\nconsole.log(greeting)\nconsole.log(typeof greeting)\n\n// Longitud\n\nconsole.log(greeting.length)\n\n// Acceso a caracteres\n\nconsole.log(greeting[0])\nconsole.log(greeting[11])\n\n// Métodos comunes\n\nconsole.log(greeting.toUpperCase()) // Mayúsculas\nconsole.log(greeting.toLowerCase()) // Minúsculas\nconsole.log(greeting.indexOf(\"Hola\")) // Índice\nconsole.log(greeting.indexOf(\"Brais\"))\nconsole.log(greeting.indexOf(\"MoureDev\"))\nconsole.log(greeting.includes(\"Hola\")) // Incluye\nconsole.log(greeting.includes(\"Brais\"))\nconsole.log(greeting.includes(\"MoureDev\"))\nconsole.log(greeting.slice(0, 10)) // Sección\nconsole.log(greeting.replace(\"Brais\", \"MoureDev\")) // Reemplazo\n\n// Template literals (plantillas literales)\n\n// Strings en varias líneas\nlet message = `Hola, este\nes mi\ncurso de\nJavaScript`\nconsole.log(message)\n\n// Interpolación de valores\nlet email = \"braismoure@mouredev.com\"\nconsole.log(`Hola, ${myName}! Tu email es ${email}.`)"
  },
  {
    "path": "Basic/07-strings-exercises.js",
    "content": "/*\nClase 22 - Ejercicios: Strings\nVídeo: https://youtu.be/1glVfFxj8a4?t=7226\n*/\n\n// 1. Concatena dos cadenas de texto\n\n// 2. Muestra la longitud de una cadena de texto\n\n// 3. Muestra el primer y último carácter de un string\n\n// 4. Convierte a mayúsculas y minúsculas un string\n\n// 5. Crea una cadena de texto en varias líneas\n\n// 6. Interpola el valor de una variable en un string\n\n// 7. Reemplaza todos los espacios en blanco de un string por guiones\n\n// 8. Comprueba si una cadena de texto contiene una palabra concreta\n\n// 9. Comprueba si dos strings son iguales\n\n// 10. Comprueba si dos strings tienen la misma longitud"
  },
  {
    "path": "Basic/08-conditionals.js",
    "content": "/*\nClase 23 - Condicionales\nVídeo: https://youtu.be/1glVfFxj8a4?t=7277\n*/\n\n// if, else if, else\n\n// if (si)\n\nlet age = 37\n\nif (age == 37) {\n    console.log(\"La edad es 37\")\n}\n\n// else (si no)\n\nif (age == 37) {\n    console.log(\"La edad es 37\")\n} else {\n    console.log(\"La edad no es 37\")\n}\n\n// else if (si no, si)\n\nif (age == 37) {\n    console.log(\"La edad es 37\")\n} else if (age < 18) {\n    console.log(\"Es menor de edad\")\n} else {\n    console.log(\"La edad no es 37 ni es menor de edad\")\n}\n\n// Operador ternario\n\nconst message = age == 37 ? \"La edad es 37\" : \"La edad no es 37\"\nconsole.log(message)\n\n// switch\n\nlet day = 3\nlet dayName\n\nswitch (day) {\n    case 0:\n        dayName = \"Lunes\"\n        break\n    case 1:\n        dayName = \"Martes\"\n        break\n    case 2:\n        dayName = \"Miércoles\"\n        break\n    case 3:\n        dayName = \"Jueves\"\n        break\n    case 4:\n        dayName = \"Viernes\"\n        break\n    case 5:\n        dayName = \"Sábado\"\n        break\n    case 6:\n        dayName = \"Domingo\"\n        break\n    default:\n        dayName = \"Número de día incorrecto\"\n}\n\nconsole.log(dayName)"
  },
  {
    "path": "Basic/09-conditionals-exercises.js",
    "content": "/*\nClase 24 - Ejercicios: Condicionales\nVídeo: https://youtu.be/1glVfFxj8a4?t=8652\n*/\n\n// if/else/else if/ternaria\n\n// 1. Imprime por consola tu nombre si una variable toma su valor\n\n// 2. Imprime por consola un mensaje si el usuario y contraseña concide con unos establecidos\n\n// 3. Verifica si un número es positivo, negativo o cero e imprime un mensaje\n\n// 4. Verifica si una persona puede votar o no (mayor o igual a 18) e indica cuántos años le faltan\n\n// 5. Usa el operador ternario para asignar el valor \"adulto\" o \"menor\" a una variable\n//    dependiendo de la edad \n\n// 6. Muestra en que estación del año nos encontramos dependiendo del valor de una variable \"mes\"\n\n// 7. Muestra el número de días que tiene un mes dependiendo de la variable del ejercicio anterior\n\n// switch\n\n// 8. Usa un switch para imprimir un mensaje de saludo diferente dependiendo del idioma\n\n// 9. Usa un switch para hacer de nuevo el ejercicio 6\n\n// 10. Usa un switch para hacer de nuevo el ejercicio 7"
  },
  {
    "path": "Basic/10-array.js",
    "content": "/*\nClase 25 - Arrays\nVídeo: https://youtu.be/1glVfFxj8a4?t=8741\n*/\n\n// Array\n\n// Declaración\n\nlet myArray = []\nlet myArray2 = new Array()\n\nconsole.log(myArray)\nconsole.log(myArray2)\n\n// Inicialización\n\nmyArray = [3]\nmyArray2 = new Array(3)\n\nconsole.log(myArray)\nconsole.log(myArray2)\n\nmyArray = [1, 2, 3, 4]\nmyArray2 = new Array(1, 2, 3, 4)\n\nconsole.log(myArray)\nconsole.log(myArray2)\n\nmyArray = [\"Brais\", \"Moure\", \"mouredev\", 37, true]\nmyArray2 = new Array(\"Brais\", \"Moure\", \"mouredev\", 37, true)\n\nconsole.log(myArray)\nconsole.log(myArray2)\n\nmyArray2 = new Array(3)\nmyArray2[2] = \"Brais\"\n// myArray2[0] = \"Moure\"\nmyArray2[1] = \"mouredev\"\nmyArray2[4] = \"mouredev\"\n\nconsole.log(myArray2)\n\nmyArray = []\nmyArray[2] = \"Brais\"\n// myArray[0] = \"Moure\"\nmyArray[1] = \"mouredev\"\n\nconsole.log(myArray)\n\n// Métodos comunes\n\nmyArray = []\n\n// push y pop\n\nmyArray.push(\"Brais\")\nmyArray.push(\"Moure\")\nmyArray.push(\"mouredev\")\nmyArray.push(37)\n\nconsole.log(myArray)\n\nconsole.log(myArray.pop()) // Elimina el último y lo devuelve\nmyArray.pop()\n\nconsole.log(myArray)\n\n// shift y unshift\n\nconsole.log(myArray.shift())\nconsole.log(myArray)\n\nmyArray.unshift(\"Brais\", \"mouredev\")\nconsole.log(myArray)\n\n// length\n\nconsole.log(myArray.length)\n\n// clear\n\nmyArray = []\nmyArray.length = 0 // alternativa\nconsole.log(myArray)\n\n// slice\n\nmyArray = [\"Brais\", \"Moure\", \"mouredev\", 37, true]\n\nlet myNewArray = myArray.slice(1, 3)\n\nconsole.log(myArray)\nconsole.log(myNewArray)\n\n// splice\n\nmyArray.splice(1, 3)\nconsole.log(myArray)\n\nmyArray = [\"Brais\", \"Moure\", \"mouredev\", 37, true]\n\nmyArray.splice(1, 2, \"Nueva entrada\")\nconsole.log(myArray)"
  },
  {
    "path": "Basic/11-set.js",
    "content": "/*\nClase 26 - Sets \nVídeo: https://youtu.be/1glVfFxj8a4?t=9952\n*/\n\n// Set\n\n// Declaración\n\nlet mySet = new Set()\n\nconsole.log(mySet)\n\n// Inicialización\n\nmySet = new Set([\"Brais\", \"Moure\", \"mouredev\", 37, true, \"braismoure@mouredev.com\"])\n\nconsole.log(mySet)\n\n// Métodos comunes\n\n// add y delete\n\nmySet.add(\"https://moure.dev\")\n\nconsole.log(mySet)\n\nmySet.delete(\"https://moure.dev\")\n\nconsole.log(mySet)\n\nconsole.log(mySet.delete(\"Brais\"))\nconsole.log(mySet.delete(4))\n\nconsole.log(mySet)\n\n// has\n\nconsole.log(mySet.has(\"Moure\"))\nconsole.log(mySet.has(\"Brais\"))\n\n// size\n\nconsole.log(mySet.size)\n\n// Convertir un set a array\nlet myArray = Array.from(mySet)\nconsole.log(myArray)\n\n// Convertir un array a set\n\nmySet = new Set(myArray)\nconsole.log(mySet)\n\n// No admite duplicados\n\nmySet.add(\"braismoure@mouredev.com\")\nmySet.add(\"braismoure@mouredev.com\")\nmySet.add(\"braismoure@mouredev.com\")\nmySet.add(\"BraisMoure@mouredev.com\")\nconsole.log(mySet)"
  },
  {
    "path": "Basic/12-map.js",
    "content": "/*\nClase 27 - Maps\nVídeo: https://youtu.be/1glVfFxj8a4?t=10755\n*/\n\n// Map\n\n// Declaración\n\nlet myMap = new Map()\n\nconsole.log(myMap)\n\n// Inicialiación\n\nmyMap = new Map([\n    [\"name\", \"Brais\"],\n    [\"email\", \"braismoure@mouredev.com\"],\n    [\"age\", 37]\n])\n\nconsole.log(myMap)\n\n// Métodos y propiedades\n\n// set\n\nmyMap.set(\"alias\", \"mouredev\")\nmyMap.set(\"name\", \"Brais Moure\")\n\nconsole.log(myMap)\n\n// get\n\nconsole.log(myMap.get(\"name\"))\nconsole.log(myMap.get(\"surname\"))\n\n// has\n\nconsole.log(myMap.has(\"surname\"))\nconsole.log(myMap.has(\"age\"))\n\n// delete\n\nmyMap.delete(\"email\")\n\nconsole.log(myMap)\n\n// keys, values y entries\n\nconsole.log(myMap.keys())\nconsole.log(myMap.values())\nconsole.log(myMap.entries())\n\n// size\n\nconsole.log(myMap.size)\n\n// clear\n\nmyMap.clear()\n\nconsole.log(myMap)\n\n\n\n"
  },
  {
    "path": "Basic/13-structures-exercises.js",
    "content": "/*\nClase 28 - Ejercicios: Estructuras\nVídeo: https://youtu.be/1glVfFxj8a4?t=11451\n*/\n\n// 1. Crea un array que almacene cinco animales\n\n// 2. Añade dos más. Uno al principio y otro al final\n\n// 3. Elimina el que se encuentra en tercera posición\n\n// 4. Crea un set que almacene cinco libros\n\n// 5. Añade dos más. Uno de ellos repetido\n\n// 6. Elimina uno concreto a tu elección\n\n// 7. Crea un mapa que asocie el número del mes a su nombre\n\n// 8. Comprueba si el mes número 5 existe en el map e imprime su valor\n\n// 9. Añade al mapa una clave con un array que almacene los meses de verano\n\n// 10. Crea un Array, transfórmalo a un Set y almacénalo en un Map"
  },
  {
    "path": "Basic/14-loops.js",
    "content": "/*\nClase 29 - Bucles\nVídeo: https://youtu.be/1glVfFxj8a4?t=11575\n*/\n\n// Loops o bucles\n\n// for\n\nfor (let i = 0; i < 5; i++) {\n    console.log(`Hola ${i}`)\n}\n\nconst numbers = [1, 2, 3, 4, 5, 6, 7, 8]\n\nfor (let i = 0; i < numbers.length; i++) {\n    console.log(`Elemento: ${numbers[i]}`)\n}\n\n// while\n\nlet i = 0\nwhile (i < 5) {\n    console.log(`Hola ${i}`)\n    i++\n}\n\n// Bucle infinito\n// while(true) {\n// }\n\n// do while\n\ni = 6\ndo {\n    console.log(`Hola ${i}`)\n    i++\n} while (i < 5)\n\n// for of\n\nconst myArray = [1, 2, 3, 4]\n\nconst mySet = new Set([\"Brais\", \"Moure\", \"mouredev\", 37, true, \"braismoure@mouredev.com\"])\n\nconst myMap = new Map([\n    [\"name\", \"Brais\"],\n    [\"email\", \"braismoure@mouredev.com\"],\n    [\"age\", 37]\n])\n\nconst myString = \"¡Hola, JavaScript!\"\n\nfor (let value of myArray) {\n    console.log(value)\n}\n\nfor (let value of mySet) {\n    console.log(value)\n}\n\nfor (let value of myMap) {\n    console.log(value)\n}\n\nfor (let value of myString) {\n    console.log(value)\n}\n\n// break y continue\n\nfor (let i = 0; i < 10; i++) {\n    if (i == 5) {\n        continue\n    } else if (i == 7) {\n        break\n    }\n    console.log(`Hola ${i}`)\n}"
  },
  {
    "path": "Basic/15-loops-exercises.js",
    "content": "/*\nClase 30 - Ejercicios: Bucles\nVídeo: https://youtu.be/1glVfFxj8a4?t=12732\n*/\n\n// NOTA: Explora diferentes sintaxis de bucles para resolver los ejercicios\n\n// 1. Crea un bucle que imprima los números del 1 al 20\n\n// 2. Crea un bucle que sume todos los números del 1 al 100 y muestre el resultado\n\n// 3. Crea un bucle que imprima todos los números pares entre 1 y 50\n\n// 4. Dado un array de nombres, usa un bucle para imprimir cada nombre en la consola\n\n// 5. Escribe un bucle que cuente el número de vocales en una cadena de texto\n\n// 6. Dado un array de números, usa un bucle para multiplicar todos los números y mostrar el producto\n\n// 7. Escribe un bucle que imprima la tabla de multiplicar del 5\n\n// 8. Usa un bucle para invertir una cadena de texto\n\n// 9. Usa un bucle para generar los primeros 10 números de la secuencia de Fibonacci\n\n// 10. Dado un array de números, usa un bucle para crear un nuevo array que contenga solo los números mayores a 10"
  },
  {
    "path": "Basic/16-functions.js",
    "content": "/*\nClase 31 - Funciones\nVídeo: https://youtu.be/1glVfFxj8a4?t=12829\n*/\n\n// Funciones\n\n// Simple\n\nfunction myFunc() {\n    console.log(\"¡Hola, función!\")\n}\n\nfor (let i = 0; i < 5; i++) {\n    myFunc()\n}\n\n// Con parámetros\n\nfunction myFuncWithParams(name) {\n    console.log(`¡Hola, ${name}!`)\n}\n\nmyFuncWithParams(\"Brais\")\nmyFuncWithParams(\"MoureDev\")\n\n// Funciones anónimas\n\nconst myFunc2 = function (name) {\n    console.log(`¡Hola, ${name}!`)\n}\n\nmyFunc2(\"Brais Moure\")\n\n// Arrow functions\n\nconst myFunc3 = (name) => {\n    console.log(`¡Hola, ${name}!`)\n}\n\nconst myFunc4 = (name) => console.log(`¡Hola, ${name}!`)\n\nmyFunc3(\"Brais Moure\")\nmyFunc4(\"Brais Moure\")\n\n// Parámetros\n\nfunction sum(a, b) {\n    console.log(a + b)\n}\n\nsum(5, 10)\nsum(5)\nsum()\n\nfunction defaultSum(a = 0, b = 0) {\n    console.log(a + b)\n}\n\n// Por defecto\n\ndefaultSum()\ndefaultSum(5)\ndefaultSum(5, 10)\ndefaultSum(undefined, 5)\n\n// Retorno de valores\n\nfunction mult(a, b) {\n    return a * b\n}\n\nlet result = mult(5, 10)\nconsole.log(result)\n\n// Funciones anidadas\n\nfunction extern() {\n    console.log(\"Función externa\")\n    function intern() {\n        console.log(\"Función interna\")\n    }\n    intern()\n}\n\nextern()\n// intern() Error: fuera del scope\n\n// Funciones de orden superior\n\nfunction applyFunc(func, param) {\n    func(param)\n}\n\napplyFunc(myFunc4, \"función de orden superior\")\n\n// forEach\n\nconst myArray = [1, 2, 3, 4]\n\nconst mySet = new Set([\"Brais\", \"Moure\", \"mouredev\", 37, true, \"braismoure@mouredev.com\"])\n\nconst myMap = new Map([\n    [\"name\", \"Brais\"],\n    [\"email\", \"braismoure@mouredev.com\"],\n    [\"age\", 37]\n])\n\nmyArray.forEach(function (value) {\n    console.log(value)\n})\n\nmyArray.forEach((value) => console.log(value))\n\nmySet.forEach((value) => console.log(value))\n\nmyMap.forEach((value) => console.log(value))"
  },
  {
    "path": "Basic/17-functions-exercises.js",
    "content": "/*\nClase 32 - Ejercicios: Funciones\nVídeo: https://youtu.be/1glVfFxj8a4?t=14146\n*/\n\n// NOTA: Explora diferentes sintaxis de funciones para resolver los ejercicios\n\n// 1. Crea una función que reciba dos números y devuelva su suma\n\n// 2. Crea una función que reciba un array de números y devuelva el mayor de ellos\n\n// 3. Crea una función que reciba un string y devuelva el número de vocales que contiene\n\n// 4. Crea una función que reciba un array de strings y devuelva un nuevo array con las strings en mayúsculas\n\n// 5. Crea una función que reciba un número y devuelva true si es primo, y false en caso contrario\n\n// 6. Crea una función que reciba dos arrays y devuelva un nuevo array que contenga los elementos comunes entre ambos\n\n// 7. Crea una función que reciba un array de números y devuelva la suma de todos los números pares\n\n// 8. Crea una función que reciba un array de números y devuelva un nuevo array con cada número elevado al cuadrado\n\n// 9. Crea una función que reciba una cadena de texto y devuelva la misma cadena con las palabras en orden inverso\n\n// 10. Crea una función que calcule el factorial de un número dado"
  },
  {
    "path": "Basic/18-objects.js",
    "content": "/*\nClase 33 - Objetos\nVídeo: https://youtu.be/1glVfFxj8a4?t=14229\n*/\n\n// Objetos\n\n// Sintaxis\n\nlet person = {\n    name: \"Brais\",\n    age: 37,\n    alias: \"MoureDev\"\n}\n\n// Acceso a propiedades\n\n// Notación punto\nconsole.log(person.name)\n\n// Notación de corchetes\nconsole.log(person[\"name\"])\n\n// Modificación de propiedades\n\nperson.name = \"Brais Moure\"\nconsole.log(person.name)\n\nconsole.log(typeof person.age)\nperson.age = \"37\"\nconsole.log(person.age)\nconsole.log(typeof person.age)\n\n// Eliminación de propiedades\n\ndelete person.age\n\nconsole.log(person)\n\n// Nueva propiedad\n\nperson.email = \"braismoure@mouredev.com\"\nperson[\"age\"] = 37\n\nconsole.log(person)\n\n// Métodos (funciones)\n\nlet person2 = {\n    name: \"Brais\",\n    age: 37,\n    alias: \"MoureDev\",\n    walk: function () {\n        console.log(\"La persona camina.\")\n    }\n}\nperson2.walk()\n\n// Anidación de objetos\n\nlet person3 = {\n    name: \"Brais\",\n    age: 37,\n    alias: \"MoureDev\",\n    walk: function () {\n        console.log(\"La persona camina.\")\n    },\n    job: {\n        name: \"Programador\",\n        exp: 15,\n        work: function () {\n            console.log(`La persona de ${this.age} años de experiencia trabaja.`)\n        }\n    }\n}\n\nconsole.log(person3)\n\nconsole.log(person3.name)\nconsole.log(person3.job)\nconsole.log(person3.job.name)\nperson3.job.work()\n\n// Igualdad de objetos\n\nlet person4 = {\n    name: \"Brais Moure\",\n    alias: \"MoureDev\",\n    email: \"braismoure@mouredev.com\",\n    age: 37\n}\n\nconsole.log(person)\nconsole.log(person4)\n\nconsole.log(person == person4)\nconsole.log(person === person4)\n\nconsole.log(person.name == person4.name)\n\n// Iteración\n\nfor (let key in person4) {\n    console.log(key + \": \" + person4[key])\n}\n\n// Funciones como objetos\n\nfunction Person(name, age) { // Debería ser una clase\n    this.name = name\n    this.age = age\n}\n\nlet person5 = new Person(\"Brais\", 37)\nconsole.log(person5)\nconsole.log(person5.name)\n\nconsole.log(typeof person5)\nconsole.log(typeof person4)"
  },
  {
    "path": "Basic/19-objects-exercises.js",
    "content": "/*\nClase 34 - Ejercicios: Objetos\nVídeo: https://youtu.be/1glVfFxj8a4?t=15675\n*/\n\n// 1. Crea un objeto con 3 propiedades\n\n// 2. Accede y muestra su valor\n\n// 3. Agrega una nueva propiedad\n\n// 4. Elimina una de las 3 primeras propiedades\n\n// 5. Agrega una función e invócala\n\n// 6. Itera las propiedades del objeto\n\n// 7. Crea un objeto anidado\n\n// 8. Accede y muestra el valor de las propiedades anidadas\n\n// 9. Comprueba si los dos objetos creados son iguales\n\n// 10. Comprueba si dos propiedades diferentes son iguales"
  },
  {
    "path": "Basic/20-destructuring-spreading.js",
    "content": "/*\nClase 35 - Desestructuración y propagación\nVídeo: https://youtu.be/1glVfFxj8a4?t=15747\n*/\n\nlet myArray = [1, 2, 3, 4]\n\nlet person = {\n    name: \"Brais\",\n    age: 37,\n    alias: \"MoureDev\"\n}\n\nlet myValue = myArray[1]\nconsole.log(myValue)\n\nlet myName = person.name\nconsole.log(myName)\n\n// Desestructuración\n\n// Sintaxis arrays\n\nlet [myValue0, myValue1, myValue2, myValue3, myValue4] = myArray\nconsole.log(myValue0)\nconsole.log(myValue1)\nconsole.log(myValue2)\nconsole.log(myValue3)\nconsole.log(myValue4)\n\n// Sintaxis arrays con valores predeterminados\n\nlet [myValue5 = 0, myValue6 = 0, myValue7 = 0, myValue8 = 0, myValue9 = 0] = myArray\nconsole.log(myValue5)\nconsole.log(myValue6)\nconsole.log(myValue7)\nconsole.log(myValue8)\nconsole.log(myValue9)\n\n// Ignorar elementos array\n\nlet [myValue10, , , myValue13] = myArray\nconsole.log(myValue10)\nconsole.log(myValue13)\n\n// Sintaxis objects\n\nlet { name, age, alias } = person\nconsole.log(name)\nconsole.log(age)\nconsole.log(alias)\n\n// Sintaxis objects con valores predeterminados\n\nlet { name2, age2, alias2, email = \"email@email.com\" } = person\nconsole.log(name2) // No existe\nconsole.log(age2)  // No existe\nconsole.log(alias2)  // No existe\nconsole.log(email)\n\n// Sintaxis objects con nuevos nombres de variables\n\nlet { alias: alias3, name: name3, age: age3 } = person\nconsole.log(name3)\nconsole.log(age3)\nconsole.log(alias3)\n\n// Objects anidados\n\nlet person3 = {\n    name: \"Brais\",\n    age: 37,\n    alias: \"MoureDev\",\n    walk: function () {\n        console.log(\"La persona camina.\")\n    },\n    job: {\n        name: \"Programador\",\n        exp: 15,\n        work: function () {\n            console.log(`La persona de ${this.age} años de experiencia trabaja.`)\n        }\n    }\n}\n\nlet { name: name4, job: { name: jobName } } = person3\n\nconsole.log(name4)\nconsole.log(jobName)\n\n// Propagación (...)\n\n// Sintaxis arrays\n\nlet myArray2 = [...myArray, 5, 6]\n\nconsole.log(myArray2)\n\n// Copia de arrays\n\nlet myArray3 = [...myArray]\n\nconsole.log(myArray3)\n\n// Combinación de arrays\n\nlet myArray4 = [...myArray, ...myArray2, ...myArray3]\n\nconsole.log(myArray4)\n\n// Sintaxis objects\n\nlet person4 = { ...person, email: \"braismoure@mouredev.com\" }\n\nconsole.log(person4)\n\n// Copia de objects\n\nlet person5 = { ...person }\n\nconsole.log(person5)"
  },
  {
    "path": "Basic/21-destructuring-spreading-exercises.js",
    "content": "/*\nClase 36 - Ejercicios: Desestructuración y propagación\nVídeo: https://youtu.be/1glVfFxj8a4?t=16802\n*/\n\n// 1. Usa desestructuración para extraer los dos primeros elementos de un array \n\n// 2. Usa desestructuración en un array y asigna un valor predeterminado a una variable\n\n// 3. Usa desestructuración para extraer dos propiedades de un objeto\n\n// 4. Usa desestructuración para extraer dos propiedades de un objeto y asígnalas\n//    a nuevas variables con nombres diferentes\n\n// 5. Usa desestructuración para extraer dos propiedades de un objeto anidado\n\n// 6. Usa propagación para combinar dos arrays en uno nuevo\n\n// 7. Usa propagación para crear una copia de un array\n\n// 8. Usa propagación para combinar dos objetos en uno nuevo\n\n// 9. Usa propagación para crear una copia de un objeto\n\n// 10. Combina desestructuración y propagación"
  },
  {
    "path": "Basic/22-classes.js",
    "content": "/*\nClase 37 - Clases\nVídeo: https://youtu.be/1glVfFxj8a4?t=16864\n*/\n\n// Clases\n\nclass Person {\n\n    constructor(name, age, alias) {\n        this.name = name\n        this.age = age\n        this.alias = alias\n    }\n\n}\n\n// Sintaxis\n\nlet person = new Person(\"Brais\", 37, \"MoureDev\")\nlet person2 = new Person(\"Brais\", 37, \"MoureDev\")\n\nconsole.log(person)\nconsole.log(person2)\n\nconsole.log(typeof person)\n\n// Valores por defecto\n\nclass DefaultPerson {\n\n    constructor(name = \"Sin nombre\", age = 0, alias = \"Sin alias\") {\n        this.name = name\n        this.age = age\n        this.alias = alias\n    }\n\n}\n\nlet person3 = new DefaultPerson(\"Brais\", 37)\n\nconsole.log(person3)\n\n// Acceso a propiedades\n\nconsole.log(person3.alias)\nconsole.log(person3[\"alias\"])\n\nperson3.alias = \"MoureDev\"\n\nconsole.log(person3.alias)\n\n// Funciones en clases\n\nclass PersonWithMethod {\n\n    constructor(name, age, alias) {\n        this.name = name\n        this.age = age\n        this.alias = alias\n    }\n\n    walk() {\n        console.log(\"La persona camina.\")\n    }\n\n}\n\nlet person4 = new PersonWithMethod(\"Brais\", 37, \"MoureDev\")\nperson4.walk()\n\n// Propiedades privadas\n\nclass PrivatePerson {\n\n    #bank\n\n    constructor(name, age, alias, bank) {\n        this.name = name\n        this.age = age\n        this.alias = alias\n        this.#bank = bank\n    }\n\n    pay() {\n        this.#bank\n    }\n\n}\n\nlet person5 = new PrivatePerson(\"Brais\", 37, \"MoureDev\", \"IBAN123456789\")\n\n// No podemos acceder\n// console.log(person5.bank) \n// person5.bank = \"new IBAN123456789\" // bank no es #bank\n\nconsole.log(person5)\n\n// Getters y Setters\n\nclass GetSetPerson {\n\n    #name\n    #age\n    #alias\n    #bank\n\n    constructor(name, age, alias, bank) {\n        this.#name = name\n        this.#age = age\n        this.#alias = alias\n        this.#bank = bank\n    }\n\n    get name() {\n        return this.#name\n    }\n\n    set bank(bank) {\n        this.#bank = bank\n    }\n\n}\n\nperson6 = new GetSetPerson(\"Brais\", 37, \"MoureDev\", \"IBAN123456789\")\n\nconsole.log(person6)\nconsole.log(person6.name)\n\nperson6.bank = \"new IBAN123456789\"\n\n/*\nClase 38 - Herencia de clases\nVídeo: https://youtu.be/1glVfFxj8a4?t=17999\n*/\n\n// Herencia\n\nclass Animal {\n\n    constructor(name) {\n        this.name = name\n    }\n\n    sound() {\n        console.log(\"El animal emite un sonido genérico\")\n    }\n\n}\n\nclass Dog extends Animal {\n\n    sound() {\n        console.log(\"Guau!\")\n    }\n\n    run() {\n        console.log(\"El perro corre\")\n    }\n\n}\n\nclass Fish extends Animal {\n\n    constructor(name, size) {\n        super(name)\n        this.size = size\n    }\n\n    swim() {\n        console.log(\"El pez nada\")\n    }\n\n}\n\nlet myDog = new Dog(\"MoureDog\")\nmyDog.run()\nmyDog.sound()\n\nlet myFish = new Fish(\"MoureFish\", 10)\nmyFish.swim()\nmyFish.sound()\n\n// Métodos estáticos\n\nclass MathOperations {\n\n    static sum(a, b) {\n        return a + b\n    }\n}\n\nconsole.log(MathOperations.sum(5, 10))"
  },
  {
    "path": "Basic/23-classes-exercises.js",
    "content": "/*\nClase 39 - Ejercicios: Clases\nVídeo: https://youtu.be/1glVfFxj8a4?t=18630\n*/\n\n// 1. Crea una clase que reciba dos propiedades\n\n// 2. Añade un método a la clase que utilice las propiedades\n\n// 3. Muestra los valores de las propiedades e invoca a la función\n\n// 4. Añade un método estático a la primera clase\n\n// 5. Haz uso del método estático\n\n// 6. Crea una clase que haga uso de herencia\n\n// 7. Crea una clase que haga uso de getters y setters\n\n// 8. Modifica la clase con getters y setters para que use propiedades privadas\n\n// 9. Utiliza los get y set y muestra sus valores\n\n// 10. Sobrescribe un método de una clase que utilice herencia "
  },
  {
    "path": "Basic/24-error-handling.js",
    "content": "/*\nClase 40 - Manejo de errores\nVídeo: https://youtu.be/1glVfFxj8a4?t=18751\n*/\n\n// Excepción\n\n// Produce una excepción\nlet myObject\n// console.log(myObject.email)\n\n// Captura de errores\n\n// try-catch\n\ntry {\n    // Código que intenta ejecutar\n    console.log(myObject.email)\n    console.log(\"Finaliza la ejecución sin errores\")\n} catch {\n    // Bloque de error\n    console.log(\"Se ha producido un error\")\n}\n\n// Captura del error\n\ntry {\n    console.log(myObject.email)\n} catch (error) {\n    console.log(\"Se ha producido un error:\", error.message)\n}\n\n// finally\n\ntry {\n    console.log(myObject.email)\n} catch (error) {\n    console.log(\"Se ha producido un error:\", error.message)\n} finally {\n    console.log(\"Este código se ejecuta siempre\")\n}\n\n// No está soportado\n// try {\n//     console.log(myObject.email)\n// } finally {\n//     console.log(\"Este código se ejecuta siempre\")\n// }\n\n// Lanzamiento de errores\n\n// throw\n\n// throw new Error(\"Se ha producido un error\")\n\nfunction sumIntegers(a, b) {\n    if (typeof a !== \"number\" || typeof b !== \"number\") {\n        throw new TypeError(\"Esta operación sólo suma números\")\n    }\n    if (!Number.isInteger(a) || !Number.isInteger(b)) {\n        throw new Error(\"Esta operación sólo suma números enteros\")\n    }\n    if (a == 0 || b == 0) {\n        throw new SumZeroIntegerError(\"Se está intentando sumar cero\", a, b)\n    }\n    return a + b\n}\n\ntry {\n    console.log(sumIntegers(5, 10))\n    // console.log(sumIntegers(5.5, 10))\n    console.log(sumIntegers(\"5\", 10))\n    // console.log(sumIntegers(5, \"10\"))\n    // console.log(sumIntegers(\"5\", \"10\"))\n} catch (error) {\n    console.log(\"Se ha producido un error:\", error.message)\n}\n\n// Capturar varios tipos de errores\n\ntry {\n    // console.log(sumIntegers(5.5, 10))\n    console.log(sumIntegers(\"5\", 10))\n} catch (error) {\n    if (error instanceof TypeError) {\n        console.log(\"Se ha producido un error de tipo:\", error.message)\n    } else if (error instanceof Error) {\n        console.log(\"Se ha producido un error:\", error.message)\n    }\n}\n\n// Crear excepciones personalizadas\n\nclass SumZeroIntegerError extends Error {\n    constructor(message, a, b) {\n        super(message)\n        this.a = a\n        this.b = b\n    }\n\n    printNumbers() {\n        console.log(this.a, \" + \", this.b)\n    }\n}\n\ntry {\n    console.log(sumIntegers(0, 10))\n} catch (error) {\n    console.log(\"Se ha producido un error personalizado:\", error.message)\n    error.printNumbers()\n}"
  },
  {
    "path": "Basic/25-error-handling-exercises.js",
    "content": "/*\nClase 41 - Ejercicios: Manejo de errores\nVídeo: https://youtu.be/1glVfFxj8a4?t=20392\n*/\n\n// 1. Captura una excepción utilizando try-catch\n\n// 2. Captura una excepción utilizando try-catch y finally\n\n// 3. Lanza una excepción genérica\n\n// 4. Crea una excepción personalizada\n\n// 5. Lanza una excepción personalizada\n\n// 6. Lanza varias excepciones según una lógica definida\n\n// 7. Captura varias excepciones en un mismo try-catch\n\n// 8. Crea un bucle que intente transformar a float cada valor y capture y muestre los errores\n\n// 9. Crea una función que verifique si un objeto tiene una propiedad específica y lance una excepción personalizada\n\n// 10. Crea una función que realice reintentos en caso de error hasta un máximo de 10"
  },
  {
    "path": "Basic/26-console-methods.js",
    "content": "/*\nClase 42 - Console\nVídeo: https://youtu.be/1glVfFxj8a4?t=20444\n*/\n\n// Console\n\n// log\n\nconsole.log(\"¡Hola, JavaScript!\")\n\n// error\n\nconsole.error(\"Este es un mensaje de error.\")\nconsole.error(\"Error al conectarse a la base de datos: \", new Error(\"Conexión fallida.\"))\n\n// warn\n\nconsole.warn(\"Este es un mensaje de advertencia.\")\n\n// info\n\nconsole.info(\"Este es un mensaje de información adicional.\")\n\n// table\n\nlet data = [\n    [\"Brais\", 37],\n    [\"Sara\", 21]\n]\n\nconsole.table(data)\n\ndata = [\n    { name: \"Brais\", age: 37 },\n    { name: \"Sara\", age: 21 }\n]\n\nconsole.table(data)\n\n// group\n\nconsole.group(\"Usuario:\")\nconsole.log(\"Nombre: Brais\")\nconsole.log(\"Edad: 37\")\nconsole.groupEnd()\n\n// time\n\nconsole.time(\"Tiempo de ejecución 2\")\n\nfor (let i = 0; i < 10000; i++) {\n\n}\n\nconsole.time(\"Tiempo de ejecución 1\")\n\nfor (let i = 0; i < 10000; i++) {\n\n}\n\nconsole.timeEnd(\"Tiempo de ejecución 2\")\n\nfor (let i = 0; i < 10000; i++) {\n\n}\n\nconsole.timeEnd(\"Tiempo de ejecución 1\")\n\n// assert\n\nlet age = 17\nconsole.assert(age >= 18, \"El usuario debe ser mayor de edad.\")\n\n// count\n\nconsole.count(\"Click\")\nconsole.count(\"Click\")\nconsole.count(\"Click\")\nconsole.countReset(\"Click\")\nconsole.count(\"Click\")\n\n// trace\n\nfunction funcA() {\n    funcB()\n}\n\nfunction funcB() {\n    console.trace(\"Seguimiento de la ejecución.\")\n}\n\nfuncA()\n\n// clear\n\n// console.clear()"
  },
  {
    "path": "Basic/27-console-methods-exercises.js",
    "content": "/*\nClase 43 - Ejercicios: Console\nVídeo: https://youtu.be/1glVfFxj8a4?t=21421\n*/\n\n// 1. Crea un función que utilice error correctamente\n\n// 2. Crea una función que utilice warn correctamente\n\n// 3. Crea una función que utilice info correctamente\n\n// 4. Utiliza table\n\n// 5. Utiliza group\n\n// 6. Utiliza time\n\n// 7. Valida con assert si un número es positivo\n\n// 8. Utiliza count\n\n// 9. Utiliza trace\n\n// 10. Utiliza clear"
  },
  {
    "path": "Basic/28-export-modules.js",
    "content": "/*\nClase 44 - Módulos\nVídeo: https://youtu.be/1glVfFxj8a4?t=21480\n*/\n\n// Exportación de módulos\n\n// Funciones\n\nexport function add(a, b) {\n    return a + b\n}\n\nconsole.log(add(5, 10))\n\n// Propiedades\n\nexport const PI = 3.1416\nexport let name = \"MoureDev\"\n\n// Clases\n\nexport class Circle {\n\n    constructor(radius) {\n        this.radius = radius\n    }\n\n    area() {\n        return Math.PI * Math.pow(this.radius, 2)\n    }\n\n    perimeter() {\n        return 2 * Math.PI * this.radius\n    }\n\n}\n\n// Exportación por defecto\n\nexport default function substract(a, b) {\n    return a - b\n}\n\n// export default class MyClass {\n\n//     func() {\n//         console.log(\"Mi clase\")\n//     }\n// }\n"
  },
  {
    "path": "Basic/29-import-modules.js",
    "content": "/*\nClase 44 - Módulos\nVídeo: https://youtu.be/1glVfFxj8a4?t=21480\n*/\n\n// Importación de módulos\n\nimport { add, PI, name, Circle } from \"./28-export-modules.js\"\n\nimport defaultImport from \"./28-export-modules.js\"\n\n// Funciones\n\nconsole.log(add(5, 10))\n\n// Propiedades\n\nconsole.log(PI)\nconsole.log(name)\n\n// Clases\n\nlet circle = new Circle(10)\nconsole.log(circle.radius)\nconsole.log(circle.area().toFixed(2))\nconsole.log(circle.perimeter().toFixed(2))\n\n// Importación por defecto\n\nconsole.log(defaultImport(5, 10))\n\n// let myClass = new defaultImport()\n// myClass.func()\n\n// Proyecto modular\n\n// import { MyImport } from \"./directory/file.js\""
  },
  {
    "path": "Basic/30-import-external-modules.cjs",
    "content": "/*\nClase 44 - Módulos \nVídeo: https://youtu.be/1glVfFxj8a4?t=21480\n*/\n\n// Módulos externos\n\nconst os = require(\"os\")\n\nconsole.log(os.platform())\nconsole.log(os.arch())\nconsole.log(os.totalmem())\nconsole.log(os.freemem())"
  },
  {
    "path": "Basic/31-modules-exercises.js",
    "content": "/*\nClase 45 - Ejercicios: Módulos\nVídeo: https://youtu.be/1glVfFxj8a4?t=22720\n*/\n\n// 1. Exporta una función\n\n// 2. Exporta una constante\n\n// 3. Exporta una clase\n\n// 4. Importa una función\n\n// 5. Importa una constante\n\n// 6. Importa una clase\n\n// 7. Exporta una función, una constante y una clase por defecto (en caso de que lo permita)\n\n// 8. Importa una función, una constante y una clase por defecto (en caso de que lo permita)\n\n// 9. Exporta una función, una constante y una clase desde una carpeta\n\n// 10. Importa una función, una constante y una clase desde un directorio diferente al anterior"
  },
  {
    "path": "Basic/package.json",
    "content": "{\n    \"type\": \"module\"\n}"
  },
  {
    "path": "Intermediate/00-advanced-functions.js",
    "content": "/*\nClases 2 a 11 - Funciones avanzadas\nVídeo: https://youtu.be/iJvLAZ8MJ2E?t=346\n*/\n\n// Ciudadanos de primera clase\n\nconst greet = function (name) {\n    console.log(`Hola, ${name}`)\n}\n\ngreet(\"Brais\")\n\nfunction processGreeting(greetFunction, name) {\n    greetFunction(name)\n}\n\nfunction returnGreeting() {\n    return greet\n}\n\nprocessGreeting(greet, \"MoureDev\")\nconst greet2 = returnGreeting()\ngreet2(\"Brais Moure\")\n\n// Arrow functions avanzadas\n\n// - Retorno implícito\nconst multiply = (a, b) => a * b\nconsole.log(multiply(2, 5))\n\n// - this léxico\nconst handler = {\n    name: \"Brais\",\n    greeting: function () {\n        console.log(`Hola, ${this.name}`)\n    },\n    arrowGreeting: () => {\n        console.log(`Hola, ${this.name}`)\n    }\n}\n\nhandler.greeting()\nhandler.arrowGreeting();\n\n// IIFE (Expresión de Función Invocada Inmediatamente)\n\n(function () {\n    console.log(\"IIFE clásico\")\n})();\n\n(() => {\n    console.log(\"IIFE con arrow function\")\n})();\n\n// Parámetros Rest (...)\n\nfunction sum(...numbers) {\n    let result = 0\n    for (let number of numbers) {\n        result += number\n    }\n    return result\n}\n\nconsole.log(sum(1, 2, 3, 4, 5))\nconsole.log(sum(10, 15))\n\n// Operador Spread (...)\n\nconst numbers = [1, 2, 3]\nfunction sumWithSpread(a, b, c) {\n    return a + b + c\n}\n\nconsole.log(sumWithSpread(1, 2, 3)) // Sin Spread\nconsole.log(sumWithSpread(...numbers)) // Con Spread\n\n// Closures (Clausuras)\n\nfunction createCounter() {\n    let counter = 0\n    return function () {\n        counter++\n        console.log(`Contador: ${counter}`)\n    }\n}\n\nconst counter = createCounter()\ncounter()\ncounter()\ncounter()\ncounter()\n\n// Recursividad\n\nfunction factorial(n) {\n    if (n <= 1) {\n        return 1\n    }\n    return n * factorial(n - 1)\n}\n\nconsole.log(factorial(5))\n\n// Funciones parciales\n\nfunction partialSum(a) {\n    return function (b, c) {\n        return sum(a, b, c)\n    }\n}\n\nconst sumWith = partialSum(4)\nconsole.log(sumWith(2, 3))\nconsole.log(sumWith(1, 2))\n\n// Currying\n\nfunction currySum(a) {\n    return function (b) {\n        return function (c) {\n            return function (d) {\n                return sum(a, b, c, d)\n            }\n        }\n    }\n}\n\nconst sumAB = currySum(1)(2)\nconst sumC = sumAB(3)\nconsole.log(sumC(3))\nconsole.log(sumC(4))\nconsole.log(sumAB(5)(7))\n\n// Callbacks\n\nfunction processData(data, callback) {\n    const result = sum(...data)\n    callback(result)\n}\n\nfunction processResult(result) {\n    console.log(result)\n}\n\nfunction processResult2(result) {\n    console.log(`Mi resultado es: ${result}`)\n}\n\nprocessData([1, 2, 3], processResult)\nprocessData([1, 2, 3], processResult2)\nprocessData([1, 2, 3], (result) => {\n    console.log(`Mi resultado en la arrow function es: ${result}`)\n})"
  },
  {
    "path": "Intermediate/01-advanced-functions-exercises.js",
    "content": "/*\nClase 12 - Funciones avanzadas\nVídeo: https://youtu.be/iJvLAZ8MJ2E?t=4112\n*/\n\n// 1. Crea una función que retorne a otra función\n\n// 2. Implementa una función currificada que multiplique 3 números\n\n// 3. Desarrolla una función recursiva que calcule la potencia de un número elevado a un exponente\n\n// 4. Crea una función createCounter() que reciba un valor inicial y retorne un objeto con métodos para increment(), decrement() y getValue(), utilizando un closure para mantener el estado\n\n// 5. Crea una función sumManyTimes(multiplier, ...numbers) que primero sume todos los números (usando parámetros Rest) y luego multiplique el resultado por multiplier\n\n// 6. Crea un Callback que se invoque con el resultado de la suma de todos los números que se le pasan a una función\n\n// 7. Desarrolla una función parcial\n\n// 8. Implementa un ejemplo que haga uso de Spread\n\n// 9. Implementa un retorno implícito\n\n// 10. Haz uso del this léxico"
  },
  {
    "path": "Intermediate/02-advanced-structures.js",
    "content": "/*\nClases 13 a 22 - Estructuras avanzadas\nVídeo: https://youtu.be/iJvLAZ8MJ2E?t=4355\n*/\n\n// Arrays avanzados\n\n// - Métodos funcionales\n\n// forEach\n\nlet numbers = [1, 2, 3, 4, 5, 6]\n\nnumbers.forEach(element => console.log(element))\n\n// map\n\nlet doubled = numbers.map(element => element * 2)\nconsole.log(doubled)\n\n// filter\n\nlet evens = numbers.filter(element => element % 2 === 0)\nconsole.log(evens)\n\n// reduce\n\nlet sum = numbers.reduce((result, current) => result + current, 0)\nconsole.log(sum)\n\n// - Manipulación\n\n// flat\n\nlet nestedArray = [1, [2, [3, [4]]]]\nconsole.log(nestedArray)\nlet flatArray = nestedArray.flat(1)\nconsole.log(flatArray)\nflatArray = nestedArray.flat(2)\nconsole.log(flatArray)\nflatArray = nestedArray.flat(3)\nconsole.log(flatArray)\n\n// flatMap\n\nlet phrases = [\"Hola mundo\", \"Adiós mundo\"]\nlet words = phrases.flatMap(phrase => phrase.split(\" \"))\nconsole.log(words)\n\n// - Ordenación\n\n// sort\n\nlet unsorted = [\"b\", \"a\", \"d\", \"c\"]\nlet sorted = unsorted.sort()\nconsole.log(sorted)\n\nunsorted = [3, 4, 1, 6, 10]\nsorted = unsorted.sort((a, b) => a - b)\n\nconsole.log(sorted)\n\n// reverse\n\nsorted.reverse()\nconsole.log(sorted)\n\n// - Búsqueda\n\n// includes\n\nconsole.log(sorted.includes(4))\nconsole.log(sorted.includes(5))\n\n// find\n\nlet firstEven = sorted.find(element => element % 2 === 0)\nconsole.log(firstEven)\n\n// findIndex\n\nlet firstEvenIndex = sorted.findIndex(element => element % 2 === 0)\nconsole.log(firstEvenIndex)\n\n// Sets avanzados\n\n// - Operaciones\n\n// Eliminación de duplicados\n\nlet numbersArray = [1, 2, 2, 3, 4, 5, 6, 6]\nnumbersArray = [...new Set(numbersArray)]\nconsole.log(numbersArray)\n\n// Unión\n\nconst setA = new Set([1, 2, 3])\nconst setB = new Set([2, 3, 4, 5])\nconst union = new Set([...setA, ...setB])\nconsole.log(union)\n\n// Intersección\n\nconst intersection = new Set([...setA].filter(element => setB.has(element)))\nconsole.log(intersection)\n\n// Diferencia\n\nconst difference = new Set([...setA].filter(element => !setB.has(element)))\nconsole.log(difference)\n\n// - Conversión\n\n// Set a Array\n\nconsole.log([...setA])\n\n// - Iteración\n\n// forEach\n\nsetA.forEach(element => console.log(element))\n\n// Maps avanzados\n\n// - Iteración\n\nlet myMap = new Map([\n    [\"name\", \"MoureDev\"],\n    [\"age\", 37]\n])\n\nmyMap.forEach((value, key) => console.log(`${key}: ${value}`))\n\n// - Conversión\n\n// Map a Array\n\nconst arrayFromMap = Array.from(myMap)\nconsole.log(arrayFromMap)\n\n// Map a Objeto\n\nconst objectFromMap = Object.fromEntries(myMap)\nconsole.log(objectFromMap)\n\n// Objeto a Map\n\nconst mapFromObject = new Map(Object.entries(objectFromMap))\nconsole.log(mapFromObject)"
  },
  {
    "path": "Intermediate/03-advanced-structures-exercises.js",
    "content": "/*\nClase 23 - Estructuras avanzadas\nVídeo: https://youtu.be/iJvLAZ8MJ2E?t=7514\n*/\n\n// 1. Utiliza map, filter y reduce para crear un ejemplo diferente al de la lección\n\n// 2. Dado un array de números, crea uno nuevo con dichos números elevados al cubo y filtra sólo los números pares\n\n// 3. Utiliza flat y flatMap para crear un ejemplo diferente al de la lección\n\n// 4. Ordena un array de números de mayor a menor\n\n// 5. Dados dos sets, encuentra la unión, intersección y diferencia de ellos\n\n// 6. Itera los resultados del ejercicio anterior\n\n// 7. Crea un mapa que almacene información se usuarios (nombre, edad y email) e itera los datos\n\n// 8. Dado el mapa anterior, crea un array con los nombres\n\n// 9. Dado el mapa anterior, obtén un array con los email de los usuarios mayores de edad y transfórmalo a un set\n\n// 10. Transforma el mapa en un objeto, a continuación, transforma el objeto en un mapa con clave el email de cada usuario y como valor todos los datos del usuario"
  },
  {
    "path": "Intermediate/04-advanced-objects.js",
    "content": "/*\nClases 24 a 28 - Objetos y clases avanzados\nVídeo: https://youtu.be/iJvLAZ8MJ2E?t=7639\n*/\n\n// Objetos avanzados\n\n// - Prototipos y Herencia\n\n// Prototipos\n\nlet person = {\n    name: \"Brais\",\n    age: 37,\n    greet() {\n        console.log(`Hola, soy ${this.name}`)\n    }\n}\n\nconsole.log(person.__proto__)\nconsole.log(Object.getPrototypeOf(person))\n\nperson.sayAge = function () {\n    console.log(`Tengo ${this.age} años`)\n}\n\nconsole.log(person)\nperson.sayAge()\n\n// Herencia\n\nlet programmer = Object.create(person)\nprogrammer.language = \"JavaScript\"\n\nprogrammer.name = \"MoureDev\"\nconsole.log(person.name)\nconsole.log(person.language)\n\nconsole.log(programmer.name)\nconsole.log(programmer.age)\nconsole.log(programmer.language)\nprogrammer.greet()\nprogrammer.sayAge()\n\n// - Métodos estáticos y de instancia\n\nfunction Person(name, age) {\n    this.name = name\n    this.age = age\n}\n\nPerson.prototype.greet = function () {\n    console.log(`Hola, soy ${this.name}`)\n}\n\nlet newPerson = new Person(\"Brais\", 37)\nnewPerson.greet()\n\n// - Métodos avanzados\n\n// assign\n\nlet personCore = { name: \"Brais\" }\nlet personDetails = { age: 37, alias: \"MoureDev\" }\n\nlet fullPerson = Object.assign(personCore, personDetails)\nconsole.log(fullPerson)\n\n// keys, values, entries\n\nconsole.log(Object.keys(fullPerson))\nconsole.log(Object.values(fullPerson))\nconsole.log(Object.entries(fullPerson))"
  },
  {
    "path": "Intermediate/05-advanced-classes.js",
    "content": "/*\nClases 29 a 37 - Objetos y clases avanzados\nVídeo: https://youtu.be/iJvLAZ8MJ2E?t=9096\n*/\n\n// Clases avanzadas\n\nclass Person {\n    constructor(name, age) {\n        this.name = name\n        this.age = age\n    }\n\n    greet() {\n        console.log(`Hola, soy ${this.name}`)\n    }\n}\n\nconst person = new Person(\"Brais\", 37)\nperson.greet()\n\nperson.sayAge = function () {\n    console.log(`Tengo ${this.age} años`)\n}\nperson.sayAge()\n\n// - Abstracción\n\nclass Animal {\n    constructor(name) {\n        if (new.target === Animal) {\n            throw new Error(\"No se puede instanciar una clase abstracta\")\n        }\n        this.name = name\n    }\n\n    makeSound() {\n        throw new Error(\"Este método tiene que ser implementado por la subclase\")\n    }\n}\n\n// Error\n// const animal = new Animal(\"Mou\")\n// console.log(animal)\n\n// - Polimorfismo\n\nclass Cat extends Animal {\n\n    makeSound() {\n        console.log(\"Miau!\")\n    }\n}\n\nclass Dog extends Animal {\n\n    makeSound() {\n        console.log(\"Guau!\")\n    }\n}\n\nconst cat = new Cat(\"MoureCat\")\nconsole.log(cat)\ncat.makeSound()\n\nconst dog = new Dog(\"MoureDog\")\nconsole.log(dog)\ndog.makeSound()\n\n// - Mixins\n\nconst FlyMixin = {\n    fly() {\n        console.log(`${this.name} está volando`)\n    }\n}\n\nclass Bird extends Animal { }\n\nclass Dragon extends Animal { }\n\nObject.assign(Bird.prototype, FlyMixin)\nObject.assign(Dragon.prototype, FlyMixin)\n\nconst bird = new Bird(\"MoureBird\")\n\nconsole.log(bird.name)\nbird.fly()\n\nconst dragon = new Dragon(\"MoureDragon\")\n\nconsole.log(dragon.name)\ndragon.fly()\n\n// - Patrón Singleton\n\nclass Session {\n\n    constructor(name) {\n        if (Session.instance) {\n            return Session.instance\n        }\n        this.name = name\n        Session.instance = this\n    }\n}\n\nconst session1 = new Session(\"Brais Moure\")\nconst session2 = new Session()\nconsole.log(session1.name)\nconsole.log(session2.name)\nconsole.log(session1 === session2)\n\nconst session3 = new Session(\"MoureDev\")\nconsole.log(session3.name)\nconsole.log(session2 === session3)\n\n// - Symbol\n\nconst ID = Symbol(\"id\")\n\nclass User {\n    constructor(name) {\n        this.name = name\n        this[ID] = Math.random()\n    }\n\n    getId() {\n        return this[ID]\n    }\n}\n\nconst user = new User(\"Brais\")\nconsole.log(user.name)\nconsole.log(user.ID)\nconsole.log(user.getId())\n\n// - instanceof\n\nclass Car { }\n\nconst car = new Car()\n\nconsole.log(car instanceof Car)\n\n// - create\n\nconst anotherCar = Object.create(Car.prototype)\n\nconsole.log(anotherCar instanceof Car)\n\n// - Proxy\n\nconst proxy = {\n    get(target, property) {\n        console.log(`Se accede a la propiedad ${property}`)\n        return target[property]\n    },\n    set(target, property, value) {\n        if (property === \"balance\" && value < 0) {\n            throw new Error(\"El saldo no puede ser negativo\")\n        }\n        target[property] = value\n    }\n}\n\nclass BankAccount {\n    constructor(balance) {\n        this.balance = balance\n    }\n}\n\nconst account = new Proxy(new BankAccount(100), proxy)\nconsole.log(account.balance)\n\naccount.balance = 50\nconsole.log(account.balance)\n\n// Error\n// account.balance = -10"
  },
  {
    "path": "Intermediate/06-advanced-objects-classes-exercises.js",
    "content": "/*\nClase 38 - Objetos y clases avanzados\nVídeo: https://youtu.be/iJvLAZ8MJ2E?t=11832\n*/\n\n// 1. Agregega una función al prototipo de un objeto\n\n// 2. Crea un objeto que herede de otro\n\n// 3. Define un método de instancia en un objeto\n\n// 4. Haz uso de get y set en un objeto\n\n// 5. Utiliza la operación assign en un objeto\n\n// 6. Crea una clase abstracta\n\n// 7. Utiliza polimorfismo en dos clases diferentes\n\n// 8. Implementa un Mixin\n\n// 9. Crea un Singleton\n\n// 10. Desarrolla un Proxy"
  },
  {
    "path": "Intermediate/07-async.js",
    "content": "/*\nClases 39 a 44 - Asincronía\nVídeo: https://youtu.be/iJvLAZ8MJ2E?t=11890\n*/\n\n// Programación asíncrona\n\n// Código síncrono\n\nconsole.log(\"Inicio\")\n\nfor (let i = 0; i < 100000000; i++) { }\n\nconsole.log(\"Fin\")\n\n// Event Loop (Bucle de eventos)\n\n// Componentes del Event Loop:\n// 1. Call Stack (Pila de ejecución)\n// 2. Web APIs (APIs del navegador) o Node.js:\n// 3. Task Queue (setTimeout()) y Microtask Queue (Promesas)\n\n// Flujo del Event Loop:\n// 1. Call Stack\n// 2. Operaciones asíncronas -> Web APIs o Node.js\n// 3. Operación termina -> La coloca en Task Queue o Microtask Queue\n// 4. Si Call Stack vacío -> Mueve tareas del Microtask Queue o Task Queue al Call Stack\n// 5. El proceso se repite\n\n// Código asíncrono\n\n// - Callbacks\n\nconsole.log(\"Inicio\")\n\nsetTimeout(() => {\n    console.log(\"Esto se ejecuta después de 2 segundos\")\n}, 2000)\n\nconsole.log(\"Fin\")\n\n// - Problema: Callback Hell\n\nfunction step1(callback) {\n    setTimeout(() => {\n        console.log(\"Paso 1 completado\")\n        callback()\n    }, 1000)\n}\n\nfunction step2(callback) {\n    setTimeout(() => {\n        console.log(\"Paso 2 completado\")\n        callback()\n    }, 1000)\n}\n\nfunction step3(callback) {\n    setTimeout(() => {\n        console.log(\"Paso 3 completado\")\n        callback()\n    }, 1000)\n}\n\nstep1(() => {\n    step2(() => {\n        step3(() => {\n            console.log(\"Todos los pasos completados\")\n        })\n    })\n})\n\n// - Promesas\n\nconst promise = new Promise((resolve, reject) => {\n    // IMPORTANTE: Inicialmente escribí setInterval, pero lo correcto es setTimeout\n    // setInterval se ejecutaría indefinidamente cada 4s, y el proceso nunca finalizaría\n    setTimeout(() => {\n        const ok = false\n        if (ok) {\n            resolve(\"Operación exitosa\")\n        } else {\n            reject(\"Se ha producido un error\")\n        }\n    }, 4000)\n})\n\npromise\n    .then(result => {\n        console.log(result)\n    })\n    .catch(error => {\n        console.log(error)\n    })\n\n// - Encadenamiento de promesas\n\nfunction step1Promise() {\n    return new Promise(resolve => {\n        setTimeout(() => {\n            console.log(\"Paso 1 con promesa completado\")\n            resolve()\n        }, 1000)\n    })\n}\n\nfunction step2Promise() {\n    return new Promise(resolve => {\n        setTimeout(() => {\n            console.log(\"Paso 2 con promesa completado\")\n            resolve()\n        }, 1000)\n    })\n}\n\nfunction step3Promise() {\n    return new Promise(resolve => {\n        setTimeout(() => {\n            console.log(\"Paso 3 con promesa completado\")\n            resolve()\n        }, 1000)\n    })\n}\n\nstep1Promise()\n    .then(step2Promise)\n    .then(step3Promise)\n    .then(() => {\n        console.log(\"Todos los pasos con promesa completados\")\n    })\n\n// - Async/Await\n\nfunction wait(ms) {\n    return new Promise(resolve => setTimeout(resolve, ms))\n}\n\nasync function process() {\n\n    console.log(\"Inicio del proceso\")\n\n    await wait(5000)\n    console.log(\"Proceso después de 5 segundos\")\n\n    await wait(1000)\n    console.log(\"Proceso después de 1 segundo\")\n\n    await wait(2000)\n    console.log(\"Proceso después de 2 segundos\")\n\n    console.log(\"Fin del proceso\")\n}\n\nprocess()"
  },
  {
    "path": "Intermediate/08-async-exercises.js",
    "content": "/*\nClase 45 - Asincronía\nVídeo: https://youtu.be/iJvLAZ8MJ2E?t=14558\n*/\n\n// 1. Crea una función para saludar que reciba un nombre y un callback. \n//    El callback debe ejecutarse después de 2 segundos y mostrar en consola \"Hola, [nombre]\".\n\n// 2. Crea tres funciones task1(callback), task2(callback) y task3(callback). \n//    Cada función debe tardar 1 segundo en ejecutarse y luego llamar al callback.\n\n// 3. Crea una función para verificar un número que retorne una Promesa. \n//    Si el número es par, la promesa se resuelve con el mensaje \"Número par\". \n//    Si el número es impar, la promesa se rechaza con el mensaje \"Número impar\".\n\n// 4. Crea tres funciones que devuelvan promesas:\n//    firstTask(): tarda 1s y muestra \"Primera tarea completada\".\n//    secondTask(): tarda 2s y muestra \"Segunda tarea completada\".\n//    thirdTask(): tarda 1.5s y muestra \"Tercera tarea completada\".\n\n// 5. Transforma el ejercicio anterior de Promesas en una función async/await llamada executeTasks().\n\n// 6. Crea una función getUser(id) que devuelva una promesa y simule una llamada a una API (que se demore 2s).\n//    Si el id es menor a 5, la promesa se resuelve con { id, nombre: \"Usuario \" + id }.\n//    Si el id es 5 o mayor, la promesa se rechaza con el mensaje \"Usuario no encontrado\".\n//    Usa async/await para llamar a getUser(id) y maneja los errores con try/catch.\n\n// 7. Intenta predecir el resultado de este código antes de ejecutarlo en la consola:\n//    console.log(\"Inicio\")\n//    setTimeout(() => console.log(\"setTimeout ejecutado\"), 0)\n//    Promise.resolve().then(() => console.log(\"Promesa resuelta\"))\n//    console.log(\"Fin\")\n\n// 8. Crea tres funciones que devuelvan promesas con tiempos de espera distintos.\n//    A continuación, usa Promise.all() para ejecutarlas todas al mismo tiempo y mostrar \"Todas las promesas resueltas\" cuando terminen.\n\n// 9. Crea una función waitSeconds(segundos) que use setTimeout dentro de una Promesa para esperar la cantidad de segundos indicada.\n//    A continuación, usa async/await para que se espere 3 segundos antes de mostrar \"Tiempo finalizado\" en consola.\n\n// 10. Crea una simulación de un cajero automático usando asincronía.\n//     - La función checkBalance() tarda 1s y devuelve un saldo de 500$.\n//     - La función withdrawMoney(amount) tarda 2s y retira dinero si hay suficiente saldo, o devuelve un error si no hay fondos.\n//     - Usa async/await para hacer que el usuario intente retirar 300$ y luego 300$ más.\n//     \n//     Posible salida esperada:\n//     Saldo disponible: 500$\n//     Retirando 300$...\n//     Operación exitosa, saldo restante: 200$\n//     Retirando 300$...\n//     Error: Fondos insuficientes"
  },
  {
    "path": "Intermediate/09-apis.js",
    "content": "/*\nClases 46 a 59 - APIs\nVídeo: https://youtu.be/iJvLAZ8MJ2E?t=14777\n*/\n\n// Manejo de APIs\n\n// - APIs REST (HTTP + URLs + JSON)\n\n// Métodos HTTP:\n// - GET\n// - POST\n// - PUT\n// - DELETE\n\n// Códigos de respuesta HTTP:\n// - 200 OK\n// - 201\n// - 400\n// - 404\n// - 500\n\n// Consumir una API\n\n// https://jsonplaceholder.typicode.com\n\n// GET\nfetch(\"https://jsonplaceholder.typicode.com/posts\")\n    .then(response => {\n        // Transforma la respuesta a JSON\n        return response.json()\n    })\n    .then(data => {\n        // Procesa los datos\n        console.log(data)\n    })\n    .catch(error => {\n        // Captura errores\n        console.log(\"Error\", error)\n    })\n\n// Uso de Async/Await\n\nasync function getPosts() {\n    try {\n        const response = await fetch(\"https://jsonplaceholder.typicode.com/posts\")\n        const data = await response.json()\n        console.log(data)\n    } catch (error) {\n        console.log(\"Error\", error)\n    }\n}\n\ngetPosts()\n\n// Solicitud POST\n\nasync function createPost() {\n    try {\n\n        const newPost = {\n            userId: 1,\n            title: \"Este es el título de mi post\",\n            body: \"Este es el cuerpo de mi post\"\n        }\n\n        const response = await fetch(\"https://jsonplaceholder.typicode.com/posts\", {\n            method: \"POST\",\n            headers: {\n                \"Content-Type\": \"application/json\"\n            },\n            body: JSON.stringify(newPost)\n        })\n\n        const data = await response.json()\n        console.log(data)\n    } catch (error) {\n        console.log(\"Error\", error)\n    }\n}\n\ncreatePost()\n\n// Herramientas para realizar peticiones HTTP\n// - https://postman.com\n// - https://apidog.com\n// - https://thunderclient.com\n\n// Manejo de errores\n\nfetch(\"https://jsonplaceholder.typicode.com/mouredev\")\n    .then(response => {\n        if (!response.ok) {\n            throw Error(`Status HTTP: ${response.status}`)\n        }\n        return response.json()\n    })\n    .catch(error => {\n        console.log(\"Error\", error)\n    })\n\n// Métodos HTTP adicionales\n// - PATCH\n// - OPTIONS\n\nasync function partialPostUpdate() {\n    try {\n        const response = await fetch(\"https://jsonplaceholder.typicode.com/posts/10\", {\n            method: \"PATCH\",\n            headers: {\n                \"Content-Type\": \"application/json\"\n            },\n            body: JSON.stringify({ title: \"Este es el nuevo título de mi post\" })\n        })\n\n        const data = await response.json()\n        console.log(data)\n    } catch (error) {\n        console.log(\"Error\", error)\n    }\n}\n\npartialPostUpdate()\n\n// Autenticación mediante API Key\n\nasync function getWeather(city) {\n\n    // https://openweathermap.org\n    const apiKey = \"TU_API_KEY\"\n    const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${apiKey}`\n\n    try {\n        const response = await fetch(url)\n        const data = await response.json()\n        console.log(data)\n    } catch (error) {\n        console.log(\"Error\", error)\n    }\n}\n\ngetWeather(\"Madrid\")\n\n// Otros métodos de Autenticación y Autorización\n// - Bearer Tokens\n// - JWT\n\n// Versionado de APIs\n// - https://api.example.com/v1/resources\n// - https://api.example.com/v2/resources\n\n// Otras APIs\n\nasync function getPokemon(pokemon) {\n\n    // https://pokeapi.co\n    const url = `https://pokeapi.co/api/v2/pokemon/${pokemon}`\n\n    try {\n        const response = await fetch(url)\n        const data = await response.json()\n        console.log(`Habilidades de ${data.name}`)\n        data.abilities.forEach(ability => {\n            console.log(ability.ability.name)\n        })\n    } catch (error) {\n        console.log(\"Error\", error)\n    }\n}\n\ngetPokemon(\"pikachu\")"
  },
  {
    "path": "Intermediate/10-apis-exercises.js",
    "content": "/*\nClase 60 - APIs\nVídeo: https://youtu.be/iJvLAZ8MJ2E?t=18710\n*/\n\n// 1. Realiza una petición GET con fetch() a JSONPlaceholder y muestra en la consola la lista de publicaciones\n\n// 2. Modifica el ejercicio anterior para que verifique si la respuesta es correcta usando response.ok. Si no lo es, lanza y muestra un error\n\n// 3. Reescribe el ejercicio 1 usando la sintaxis async/await en lugar de promesas\n\n// 4. Realiza una petición POST a JSONPlaceholder para crear una nueva publicación. Envía un objeto con propiedades como title o body\n\n// 5. Utiliza el método PUT para actualizar completamente un recurso (por ejemplo, modificar una publicación) en JSONPlaceholder\n\n// 6. Realiza una petición PATCH para modificar únicamente uno o dos campos de un recurso existente\n\n// 7. Envía una solicitud DELETE a la API para borrar un recurso (por ejemplo, una publicación) y verifica la respuesta\n\n// 8. Crea una función que realice una solicitud GET (la que quieras) a OpenWeatherMap\n\n// 9. Utiliza la PokéAPI para obtener los datos de un Pokémon concreto, a continuación los detalles de la especie y, finalmente, la cadena evolutiva a partir de la especie\n\n// 10. Utiliza una herramienta como Postman o Thunder Client para probar diferentes endpoint de una API\n"
  },
  {
    "path": "Intermediate/11-dom.js",
    "content": "/*\nClases 61 a 68 - DOM\nVídeo: https://youtu.be/iJvLAZ8MJ2E?t=18822\n*/\n\n// Manejo del DOM (Document Object Model)\n\nconsole.log(document)\n\n// - Selección de elementos\n\n// Métodos básicos (selector HTML)\n\nconst myElementById = document.getElementById(\"id\")\n\nconst myElementsByClass = document.getElementsByClassName(\"class\")\n\nconst myElementsByTag = document.getElementsByTagName(\"tag\")\n\n// Métodos más modernos (selector CSS)\n\ndocument.querySelector(\".paragraph\")\ndocument.querySelectorAll(\".paragraph\")\n\n// - Manipulación de elementos\n\nconst title = document.getElementById(\"title\")\ntitle.textContent = \"Hola JavaScript\"\n\nconst container = document.querySelector(\".container\")\ncontainer.innerHTML = \"<p>Esto es un nuevo párrafo</p>\"\n\n// - Modificación de atributos\n\n// Obtención del atributo\nconst link = document.querySelector(\"a\")\nconst url = link.getAttribute(\"href\")\n\n// Establecimiento del atributo\nlink.setAttribute(\"href\", \"https://example.com\")\n\n// Comprobación de atributo\nconst hasTarget = link.hasAttribute(\"target\")\n\n// Eliminación de atributos\nlink.removeAttribute(\"target\")\n\n// - Interacción con clases CSS\n\nconst box = document.querySelector(\".box\")\nbox.classList.add(\"selected\")\nbox.classList.remove(\"selected\")\nbox.classList.toggle(\"selected\")\n\nconst button = document.querySelector(\"button\")\nbutton.style.backgroundColor = \"blue\"\nbutton.style.color = \"white\"\nbutton.style.padding = \"10px\"\n\n// - Creación y eliminación de elementos\n\n// Creación\n\nconst newParagraph = document.createElement(\"p\")\nnewParagraph.textContent = \"Este es un nuevo párrafo creado desde JS\"\nnewParagraph.style.padding = \"8px\"\n\ncontainer.appendChild(newParagraph)\n\nconst itemsList = document.querySelector(\"ul\")\nconst newItem = document.createElement(\"li\")\nnewItem.textContent = \"Nuevo elemento\"\n\n// Inserción en un lugar concreto\n\nconst secondItem = itemsList.children[1]\nitemsList.insertBefore(newItem, secondItem)\n\nitemsList.append(newItem)\nitemsList.prepend(newItem)\nsecondItem.before(newItem)\nsecondItem.after(newItem)\n\n// Eliminación\n\nnewParagraph.remove()\n\n// Eliminación tradicional\n\nconst parent = newParagraph.parentElement\nparent.removeChild(newParagraph)\n\n// - Elementos del DOM\n\nfunction showMsg() {\n    alert(\"Clic!\")\n}\n\nconst sendButton = document.querySelector(\"#send\")\nsendButton.addEventListener(\"click\", showMsg)\n\nsendButton.addEventListener(\"click\", () => {\n    alert(\"Clic con una arrow function!\")\n})\n\n// Eventos comunes\n\ndocument.addEventListener(\"DOMContentLoader\", () => {\n    console.log(\"El DOM está completamente cargado\")\n})\n\nsendButton.addEventListener(\"mouseenter\", () => {\n    sendButton.style.backgroundColor = \"green\"\n})\n\nsendButton.addEventListener(\"mouseleave\", () => {\n    sendButton.style.backgroundColor = \"blue\"\n})\n\nconst form = document.querySelector(\"form\")\nform.addEventListener(\"submit\", (event) => {\n    // Código\n})"
  },
  {
    "path": "Intermediate/12-dom-example.html",
    "content": "<!-- \nClase 69 - DOM\nVídeo: https://youtu.be/iJvLAZ8MJ2E?t=21754\n-->\n<!DOCTYPE html>\n<html lang=\"es\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>HTML de ejemplo</title>\n</head>\n<body>\n    <h1>Mi título</h1>\n    <button>Mi botón</button>\n    <!-- <script>\n        console.log(\"Mi script\")\n        const myH1 = document.querySelector(\"h1\")\n        console.log(myH1)\n\n        myH1.textContent = \"Mi nuevo título\"\n    </script> -->\n    <script src=\"13-dom-example.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "Intermediate/13-dom-example.js",
    "content": "/*\nClase 69 - DOM\nVídeo: https://youtu.be/iJvLAZ8MJ2E?t=21754\n*/\n\nconsole.log(document)\n\nconst myH1 = document.querySelector(\"h1\")\nconsole.log(myH1)\n\nmyH1.textContent = \"Mi nuevo título\""
  },
  {
    "path": "Intermediate/14-tasklist.html",
    "content": "<!-- \nClase 70 - DOM\nVídeo: https://youtu.be/iJvLAZ8MJ2E?t=22342\n-->\n<!DOCTYPE html>\n<html lang=\"es\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>Lista de tareas</title>\n</head>\n<body>\n    <h1>Mis tareas</h1>\n    <input id=\"text\" type=\"text\" placeholder=\"Escribe una tarea\">\n    <button id=\"button\">Agregar tarea</button>\n    <ul id=\"list\"></ul>\n    <script src=\"15-tasklist.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "Intermediate/15-tasklist.js",
    "content": "/*\nClase 70 - DOM\nVídeo: https://youtu.be/iJvLAZ8MJ2E?t=22342\n*/\n\nconst text = document.getElementById(\"text\")\nconst button = document.getElementById(\"button\")\nconst list = document.getElementById(\"list\")\n\nfunction addTask() {\n\n    if (text.value === \"\") return\n\n    const newElement = document.createElement(\"li\")\n    newElement.textContent = text.value\n\n    newElement.addEventListener(\"click\", () => {\n        newElement.remove()\n    })\n\n    list.appendChild(newElement)\n\n    text.value = \"\"\n}\n\nbutton.addEventListener(\"click\", addTask)\n\ntext.addEventListener(\"keypress\", (event) => {\n    if (event.key === \"Enter\") {\n        addTask()\n    }\n})"
  },
  {
    "path": "Intermediate/16-dom-exercises.js",
    "content": "/*\nClase 71 - DOM\nVídeo: https://youtu.be/iJvLAZ8MJ2E?t=23010\n*/\n\n// 1. Crea un elemento (por ejemplo, un <h1 id=\"title\">) y cambia su contenido a \"¡Hola Mundo!\"\" al cargar la página\n\n// 2. Inserta una imagen con id=\"myImage\" y cambia su atributo src a otra URL\n\n// 3. Crea un <div id=\"box\"> sin clases y agrega la clase resaltado cuando se cargue la página\n\n// 4. Crea un párrafo con id=\"paragraph\" y cambia su color de texto a azul\n\n// 5. Agrega un botón que, al hacer clic, cree un nuevo elemento <li> con el texto \"Nuevo elemento y lo agregue a una lista <ul id=\"list\">\n\n// 6. Crea un párrafo con id=\"deleteParagraph\" y un botón. Al hacer clic en el botón, elimina el párrafo del DOM\n\n// 7. Crea un <div id=\"content\"> con algún texto y reemplaza su contenido por un <h2> con el mensaje \"Nuevo Contenido\"\n\n// 8. Crea un botón con id=\"greetBtn\" y añade un evento que muestre una alerta con el mensaje \"¡Hola!\" al hacer clic\n\n// 9. Crea un <input id=\"textInput\"> y un <div id=\"result\">. Al escribir en el input, el <div> se debe actualizarse mostrando lo que se escribe\n\n// 10. Crea un botón con id=\"backgroundBtn\" y, al hacer clic, cambia el color de fondo del <body> a un color diferente"
  },
  {
    "path": "Intermediate/17-debugging.js",
    "content": "/*\nClases 72 a 73 - Depuración\nVídeo: https://youtu.be/iJvLAZ8MJ2E?t=23085\n*/\n\n// Depuración\n\n// console.log() (básico)\n\nfunction sum(a, b) {\n    console.log(\"a:\", a)\n    console.log(\"typeof a:\", typeof a)\n    console.log(\"b:\", b)\n    console.log(\"typeof b:\", typeof b)\n    return a + b\n}\n\nconsole.log(sum(3, \"5\"))\n\n// Depurador (profesional)\n\nfunction divide(a, b) {\n    if (b === 0) {\n        throw new Error(\"No se puede dividir por cero\")\n    }\n    return a / b\n}\n\n// console.log(divide(5, 0)) Error"
  },
  {
    "path": "Intermediate/18-debugging-exercises.js",
    "content": "/*\nClases 74 - Depuración\nVídeo: https://youtu.be/iJvLAZ8MJ2E?t=24329\n*/\n\n// 1. Crea un código con un error lógico y usa VS Code para encontrarlo\n\n// 2. Experimenta con breakpoints y observa cómo cambia el flujo de ejecución\n"
  },
  {
    "path": "Intermediate/19-regex.js",
    "content": "/*\nClases 75 a 78 - Regex\nVídeo: https://youtu.be/iJvLAZ8MJ2E?t=24363\n*/\n\n// Expresiones regulares\n\n// - Sintaxis\n\nconst regex = /abc/\nconst regex2 = RegExp(\"abc\")\nconst text = \"Hola abc JavaScript\"\n\n// test: verifica coincidencia con true o false\n\nconsole.log(regex.test(text))\nconsole.log(regex2.test(text))\n\nconst text2 = \"Mi edad es 37\"\nconst regex3 = /\\d/g\nconst regex4 = /[4-6]/\nconsole.log(regex3.test(text2))\nconsole.log(regex4.test(text2))\n\n// replace: reemplaza el texto que coincide con el patrón\n\nconst regex5 = /JavaScript/\nconsole.log(\"Hola JavaScript\".replace(regex5, \"JS\"))\nconst text3 = \"Estoy contando 1 2 3 4 5 6 7\"\nconsole.log(text3.replace(regex3, \"[número]\"))\n\n// exec: retorna detalles de la coincidencia\n\nconsole.log(regex3.exec(text3))\n\nwhile ((match = regex3.exec(text3)) !== null) {\n    console.log(match)\n}"
  },
  {
    "path": "Intermediate/20-regex-exercises.js",
    "content": "/*\nClase 79 - Regex\nVídeo: https://youtu.be/iJvLAZ8MJ2E?t=25888\n*/\n\n// 1. Crea una RegEx que valide correos electrónicos\n\n// 2. Crea una RegEx obtenga Hashtags de un Texto\n\n// 3. Crea una RegEx que valide contraseñas seguras (mínimo 8 caracteres, al menos una letra y un número)\n\n// NOTA: Aplícalas utilizando diferentes operaciones"
  },
  {
    "path": "Intermediate/21-testing.js",
    "content": "/*\nClases 80 a 81 - Testing\nVídeo: https://youtu.be/iJvLAZ8MJ2E?t=25938\n*/\n\n// Testing\n\n// - Tipos de testing\n\n// Pruebas unitarias\n\nfunction sum(a, b) {\n    return a + b\n}\n\nmodule.exports = sum\n\nconsole.log(sum(3, 5) === 8)\n\n// Pruebas de integración\n\n// Pruebas end-to-end (E2E)"
  },
  {
    "path": "Intermediate/22-testing.test.js",
    "content": "/*\nClases 80 a 81 - Testing\nVídeo: https://youtu.be/iJvLAZ8MJ2E?t=25938\n*/\n\nconst sum = require('./21-testing')\n\ntest(\"Suma de 3 + 5 tiene que ser 8\", () => {\n    expect(sum(3, 5)).toBe(8)\n})\n\ntest(\"Suma de 3 + 3 tiene que ser 6\", () => {\n    expect(sum(3, 4)).toBe(6)\n})"
  },
  {
    "path": "Intermediate/23-testing-exercises.js",
    "content": "/*\nClase 82 - Testing\nVídeo: https://youtu.be/iJvLAZ8MJ2E?t=26946\n*/\n\n// 1. Crea una función isEven(number) que devuelva true si el número es par y false si es impar\n\n// 2. Escribe una prueba en Jest para verificar que la función funciona correctamente\n\n// 3. Verifica que la prueba se ejecuta satisfactoriamente"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "README.md",
    "content": "# Hello JavaScript\n\n[![JavaScript](https://img.shields.io/badge/JavaScript-ES6+-yellow?style=for-the-badge&logo=javascript&logoColor=white&labelColor=101010)](https://developer.mozilla.org/es/docs/Web/JavaScript) [![NodeJS](https://img.shields.io/badge/NODEJS-v20+-green?style=for-the-badge&logo=nodedotjs&logoColor=white&labelColor=101010)](https://nodejs.org/)\n\n## Curso para aprender el lenguaje de programación JavaScript desde cero y para principiantes\n\n![](./Images/header.jpg)\n\n### Proyecto realizado durante emisiones en directo desde [Twitch](https://twitch.tv/mouredev)\n> ##### Si consideras útil el curso, apóyalo haciendo \"★ Star\" en el repositorio. ¡Gracias!\n\n## Clases en vídeo\n\n### Curso de fundamentos desde cero\n\n<a href=\"https://youtu.be/1glVfFxj8a4\"><img src=\"http://i3.ytimg.com/vi/1glVfFxj8a4/maxresdefault.jpg\" style=\"height: 50%; width:50%;\"/></a>\n\n* [Introducción](https://youtu.be/1glVfFxj8a4)\n* [1 - Contexto](https://youtu.be/1glVfFxj8a4?t=174)\n* [2 - Historia](https://youtu.be/1glVfFxj8a4?t=322)\n* [3 - JavaScript y Java](https://youtu.be/1glVfFxj8a4?t=665)\n* [4 - Utilización](https://youtu.be/1glVfFxj8a4?t=931)\n* [5 - Especificación ECMAScript](https://youtu.be/1glVfFxj8a4?t=1017)\n* [6 - Motor V8](https://youtu.be/1glVfFxj8a4?t=1293)\n* [7 - Referencia](https://youtu.be/1glVfFxj8a4?t=1403)\n* [8 - Ejercicios prácticos](https://youtu.be/1glVfFxj8a4?t=1621)\n* [9 - Versión](https://youtu.be/1glVfFxj8a4?t=1705)\n* [10 - Explorador web](https://youtu.be/1glVfFxj8a4?t=1768)\n* [11 - Playground](https://youtu.be/1glVfFxj8a4?t=1893)\n* [12 - Instalación](https://youtu.be/1glVfFxj8a4?t=1988)\n* [13 - Editor de código](https://youtu.be/1glVfFxj8a4?t=2256)\n* [14 - Buenas prácticas](https://youtu.be/1glVfFxj8a4?t=2311)\n* [15 - Hola mundo](https://youtu.be/1glVfFxj8a4?t=2390) | [Código](./Basic/00-helloworld.js)\n* [16 - Variables](https://youtu.be/1glVfFxj8a4?t=3049) | [Código](./Basic/01-variables.js)\n* [17 - Tipos de datos](https://youtu.be/1glVfFxj8a4?t=3599) | [Código](./Basic/02-datatypes.js)\n* [18 - Ejercicios: primeros pasos](https://youtu.be/1glVfFxj8a4?t=4733) | [Ejercicios](./Basic/03-beginner-exercises.js)\n* [19 - Operadores](https://youtu.be/1glVfFxj8a4?t=4937) | [Código](./Basic/04-operators.js)\n* [20 - Ejercicios: Operadores](https://youtu.be/1glVfFxj8a4?t=6458) | [Ejercicios](./Basic/05-operators-exercises.js)\n* [21 - Strings](https://youtu.be/1glVfFxj8a4?t=6565) | [Código](./Basic/06-strings.js)\n* [22 - Ejercicios: Strings](https://youtu.be/1glVfFxj8a4?t=7226) | [Ejercicios](./Basic/07-strings-exercises.js)\n* [23 - Condicionales](https://youtu.be/1glVfFxj8a4?t=7277) | [Código](./Basic/08-conditionals.js)\n* [24 - Ejercicios: Condicionales](https://youtu.be/1glVfFxj8a4?t=8652) | [Ejercicios](./Basic/09-conditionals-exercises.js)\n* [25 - Arrays](https://youtu.be/1glVfFxj8a4?t=8741) | [Código](./Basic/10-array.js)\n* [26 - Sets](https://youtu.be/1glVfFxj8a4?t=9952) | [Código](./Basic/11-set.js)\n* [27 - Maps](https://youtu.be/1glVfFxj8a4?t=10755) | [Código](./Basic/12-map.js)\n* [28 - Ejercicios: Estructuras](https://youtu.be/1glVfFxj8a4?t=11451) | [Ejercicios](./Basic/13-structures-exercises.js)\n* [29 - Bucles](https://youtu.be/1glVfFxj8a4?t=11575) | [Código](./Basic/14-loops.js)\n* [30 - Ejercicios: Bucles](https://youtu.be/1glVfFxj8a4?t=12732) | [Ejercicios](./Basic/15-loops-exercises.js)\n* [31 - Funciones](https://youtu.be/1glVfFxj8a4?t=12829) | [Código](./Basic/16-functions.js)\n* [32 - Ejercicios: Funciones](https://youtu.be/1glVfFxj8a4?t=14146) | [Ejercicios](./Basic/17-functions-exercises.js)\n* [33 - Objetos](https://youtu.be/1glVfFxj8a4?t=14229) | [Código](./Basic/18-objects.js)\n* [34 - Ejercicios: Objetos](https://youtu.be/1glVfFxj8a4?t=15675) | [Ejercicios](./Basic/19-objects-exercises.js)\n* [35 - Desestructuración y propagación](https://youtu.be/1glVfFxj8a4?t=15747) | [Código](./Basic/20-destructuring-spreading.js)\n* [36 - Ejercicios: Desestructuración y propagación](https://youtu.be/1glVfFxj8a4?t=16802) | [Ejercicios](./Basic/21-destructuring-spreading-exercises.js)\n* [37 - Clases](https://youtu.be/1glVfFxj8a4?t=16864) | [Código](./Basic/22-classes.js)\n* [38 - Herencia de clases](https://youtu.be/1glVfFxj8a4?t=17999) | [Código](./Basic/22-classes.js)\n* [39 - Ejercicios: Clases](https://youtu.be/1glVfFxj8a4?t=18630) | [Ejercicios](./Basic/23-classes-exercises.js)\n* [40 - Manejo de errores](https://youtu.be/1glVfFxj8a4?t=18751) | [Código](./Basic/24-error-handling.js)\n* [41 - Ejercicios: Manejo de errores](https://youtu.be/1glVfFxj8a4?t=20392) | [Ejercicios](./Basic/25-error-handling-exercises.js)\n* [42 - Console](https://youtu.be/1glVfFxj8a4?t=20444) | [Código](./Basic/26-console-methods.js)\n* [43 - Ejercicios: Console](https://youtu.be/1glVfFxj8a4?t=21421) | [Ejercicios](./Basic/27-console-methods-exercises.js)\n* [44 - Módulos](https://youtu.be/1glVfFxj8a4?t=21480) | [Código exportación](./Basic/28-export-modules.js) | [Código importación](./Basic/29-import-modules.js) | [Código externos](./Basic/30-import-external-modules.cjs)\n* [45 - Ejercicios: Módulos](https://youtu.be/1glVfFxj8a4?t=22720) | [Ejercicios](./Basic/31-modules-exercises.js) | [package.json](./Basic/package.json)\n* [Despedida](https://youtu.be/1glVfFxj8a4?t=22776)\n\n### Curso de fundamentos intermedio (continuación del desde cero)\n\n<a href=\"https://youtu.be/iJvLAZ8MJ2E\"><img src=\"http://i3.ytimg.com/vi/iJvLAZ8MJ2E/maxresdefault.jpg\" style=\"height: 50%; width:50%;\"/></a>\n\n* [Introducción](https://youtu.be/iJvLAZ8MJ2E)\n* [1 - Primeros pasos](https://youtu.be/iJvLAZ8MJ2E?t=279)\n\nFunciones avanzadas | [Código](./Intermediate/00-advanced-functions.js)\n\n* [2 - Ciudadanos de primera clase](https://youtu.be/iJvLAZ8MJ2E?t=346)\n* [3 - Arrow functions](https://youtu.be/iJvLAZ8MJ2E?t=782)\n* [4 - IIFE](https://youtu.be/iJvLAZ8MJ2E?t=1278)\n* [5 - Parámetros rest](https://youtu.be/iJvLAZ8MJ2E?t=1873)\n* [6 - Operador Spread](https://youtu.be/iJvLAZ8MJ2E?t=2126)\n* [7 - Closures](https://youtu.be/iJvLAZ8MJ2E?t=2356)\n* [8 - Recursividad](https://youtu.be/iJvLAZ8MJ2E?t=2650)\n* [9 - Funciones parciales](https://youtu.be/iJvLAZ8MJ2E?t=3013)\n* [10 - Currying](https://youtu.be/iJvLAZ8MJ2E?t=3473)\n* [11 - Callbacks](https://youtu.be/iJvLAZ8MJ2E?t=3675)\n* [12 - Ejercicios: Funciones avanzadas](https://youtu.be/iJvLAZ8MJ2E?t=4112) | [Ejercicios](./Intermediate/01-advanced-functions-exercises.js)\n\nEstructuras avanzadas | [Código](./Intermediate/02-advanced-structures.js)\n\n* [13 - Estructuras avanzadas](https://youtu.be/iJvLAZ8MJ2E?t=4355)\n* [14 - Arrays avanzados: métodos funcionales](https://youtu.be/iJvLAZ8MJ2E?t=4411)\n* [15 - Arrays avanzados: manipulación](https://youtu.be/iJvLAZ8MJ2E?t=5244)\n* [16 - Arrays avanzados: ordenación](https://youtu.be/iJvLAZ8MJ2E?t=5621)\n* [17 - Arrays avanzados: búsqueda](https://youtu.be/iJvLAZ8MJ2E?t=5979)\n* [18 - Sets avanzados: operaciones](https://youtu.be/iJvLAZ8MJ2E?t=6288)\n* [19 - Sets avanzados: conversión](https://youtu.be/iJvLAZ8MJ2E?t=6949)\n* [20 - Sets avanzados: iteración](https://youtu.be/iJvLAZ8MJ2E?t=6992)\n* [21 - Maps avanzados: iteración](https://youtu.be/iJvLAZ8MJ2E?t=7061)\n* [22 - Maps avanzados: conversión](https://youtu.be/iJvLAZ8MJ2E?t=7207)\n* [23 - Ejercicios: Estructuras avanzadas](https://youtu.be/iJvLAZ8MJ2E?t=7514) | [Ejercicios](./Intermediate/03-advanced-structures-exercises.js)\n\nObjetos y clases avanzados | [Código Objetos](./Intermediate/04-advanced-objects.js) | [Código Clases](./Intermediate/05-advanced-classes.js)\n\n* [24 - Objetos avanzados](https://youtu.be/iJvLAZ8MJ2E?t=7639)\n* [25 - Prototipos](https://youtu.be/iJvLAZ8MJ2E?t=7695)\n* [26 - Herencia](https://youtu.be/iJvLAZ8MJ2E?t=8068)\n* [27 - Métodos estáticos y de instancia](https://youtu.be/iJvLAZ8MJ2E?t=8577)\n* [28 - Métodos avanzados](https://youtu.be/iJvLAZ8MJ2E?t=8896)\n* [29 - Clases avanzadas](https://youtu.be/iJvLAZ8MJ2E?t=9096)\n* [30 - Abstracción](https://youtu.be/iJvLAZ8MJ2E?t=9408)\n* [31 - Polimorfismo](https://youtu.be/iJvLAZ8MJ2E?t=9694)\n* [32 - Mixins](https://youtu.be/iJvLAZ8MJ2E?t=9956)\n* [33 - Singleton](https://youtu.be/iJvLAZ8MJ2E?t=10454)\n* [34 - Symbol](https://youtu.be/iJvLAZ8MJ2E?t=10901)\n* [35 - instanceof](https://youtu.be/iJvLAZ8MJ2E?t=11264)\n* [36 - create](https://youtu.be/iJvLAZ8MJ2E?t=11331)\n* [37 - Proxy](https://youtu.be/iJvLAZ8MJ2E?t=11375)\n* [38 - Ejercicios: Objetos y clases avanzados](https://youtu.be/iJvLAZ8MJ2E?t=11832) | [Ejercicios](./Intermediate/06-advanced-objects-classes-exercises)\n\nAsincronía | [Código](./Intermediate/07-async.js)\n\n* [39 - Asincronía](https://youtu.be/iJvLAZ8MJ2E?t=11890)\n* [40 - Código síncrono](https://youtu.be/iJvLAZ8MJ2E?t=12245)\n* [41 - Event Loop](https://youtu.be/iJvLAZ8MJ2E?t=12366)\n* [42 - Callbacks](https://youtu.be/iJvLAZ8MJ2E?t=12729)\n* [43 - Promesas](https://youtu.be/iJvLAZ8MJ2E?t=13349)\n* [44 - Async/Await](https://youtu.be/iJvLAZ8MJ2E?t=14171)\n* [45 - Ejercicios: Asincronía](https://youtu.be/iJvLAZ8MJ2E?t=14558) | [Ejercicios](./Intermediate/08-async-exercises.js)\n\nAPIs | [Código](./Intermediate/09-apis.js)\n\n* [46 - APIs](https://youtu.be/iJvLAZ8MJ2E?t=14777)\n* [47 - API REST](https://youtu.be/iJvLAZ8MJ2E?t=14973)\n* [48 - Métodos HTTP](https://youtu.be/iJvLAZ8MJ2E?t=15134)\n* [49 - Códigos de respuesta HTTP](https://youtu.be/iJvLAZ8MJ2E?t=15294)\n* [50 - GET](https://youtu.be/iJvLAZ8MJ2E?t=15477)\n* [51 - Async/Await en APIs](https://youtu.be/iJvLAZ8MJ2E?t=16400)\n* [52 - POST](https://youtu.be/iJvLAZ8MJ2E?t=16626)\n* [53 - Herramientas para realizar peticiones HTTP](https://youtu.be/iJvLAZ8MJ2E?t=17088)\n* [54 - Manejo de errores](https://youtu.be/iJvLAZ8MJ2E?t=17325)\n* [55 - Métodos HTTP adicionales](https://youtu.be/iJvLAZ8MJ2E?t=17619)\n* [56 - Autenticación mediante API Key](https://youtu.be/iJvLAZ8MJ2E?t=17770)\n* [57 - Otros métodos de autenticación y autorización](https://youtu.be/iJvLAZ8MJ2E?t=18244)\n* [58 - Versionado de APIs](https://youtu.be/iJvLAZ8MJ2E?t=18323)\n* [59 - Otras APIs](https://youtu.be/iJvLAZ8MJ2E?t=18441)\n* [60 - Ejercicios: APIs](https://youtu.be/iJvLAZ8MJ2E?t=18710) | [Ejercicios](./Intermediate/10-apis-exercises.js)\n\nDOM | [Código](./Intermediate/11-dom.js)\n\n* [61 - DOM](https://youtu.be/iJvLAZ8MJ2E?t=18822)\n* [62 - Estructura del DOM](https://youtu.be/iJvLAZ8MJ2E?t=19105)\n* [63 - Métodos de selección](https://youtu.be/iJvLAZ8MJ2E?t=19172)\n* [64 - Manipulación de elementos](https://youtu.be/iJvLAZ8MJ2E?t=19792)\n* [65 - Modificación de atributos](https://youtu.be/iJvLAZ8MJ2E?t=19996)\n* [66 - Interacción con clases CSS](https://youtu.be/iJvLAZ8MJ2E?t=20326)\n* [67 - Creación y eliminación de elementos](https://youtu.be/iJvLAZ8MJ2E?t=20787)\n* [68 - Elementos y eventos del DOM](https://youtu.be/iJvLAZ8MJ2E?t=21377)\n* [69 - Ejemplos: acceso al DOM](https://youtu.be/iJvLAZ8MJ2E?t=21754) | Ejemplo simple: [HTML](./Intermediate/12-dom-example.html) - [JS](./Intermediate/13-dom-example.js)\n* [70 - Ejemplos: lista de tareas](https://youtu.be/iJvLAZ8MJ2E?t=22342) Ejemplo lista de tareas: [HTML](./Intermediate/14-tasklist.html) - [JS](./Intermediate/15-tasklist.js)\n* [71 - Ejercicios: DOM](https://youtu.be/iJvLAZ8MJ2E?t=23010) | [Ejercicios](./Intermediate/16-dom-exercises.js)\n\nDepuración | [Código](./Intermediate/17-debugging.js)\n\n* [72 - Depuración](https://youtu.be/iJvLAZ8MJ2E?t=23085)\n* [73 - Depurador](https://youtu.be/iJvLAZ8MJ2E?t=23370)\n* [74 - Ejercicios: Depuración](https://youtu.be/iJvLAZ8MJ2E?t=24329) | [Ejercicios](./Intermediate/18-debugging-exercises.js)\n\nRegex | [Código](./Intermediate/19-regex.js)\n\n* [75 - Regex](https://youtu.be/iJvLAZ8MJ2E?t=24363)\n* [76 - Sintaxis: test](https://youtu.be/iJvLAZ8MJ2E?t=24444)\n* [77 - Sintaxis: replace](https://youtu.be/iJvLAZ8MJ2E?t=24989)\n* [78 - Sintaxis: exec](https://youtu.be/iJvLAZ8MJ2E?t=25365)\n* [79 - Ejercicios: Regex](https://youtu.be/iJvLAZ8MJ2E?t=25888) | [Ejercicios](./Intermediate/20-regex-exercises.js)\n\nTesting | [Código](./Intermediate/21-testing.js) | [Test](./Intermediate/22-testing.test.js)\n\n* [80 - Testing](https://youtu.be/iJvLAZ8MJ2E?t=25938)\n* [81 - Jest](https://youtu.be/iJvLAZ8MJ2E?t=26272)\n* [82 - Ejercicios: Testing](https://youtu.be/iJvLAZ8MJ2E?t=26946) | [Ejercicios](./Intermediate/23-testing-exercises.js)\n* [Despedida](https://youtu.be/iJvLAZ8MJ2E?t=26970)\n\n## Enlaces de interés\n\n* Impacto: [Stack Overflow](https://survey.stackoverflow.co/2023/#most-popular-technologies-language) | [GitHub](https://github.blog/2023-11-08-the-state-of-open-source-and-ai/) | [Índice TIOBE](https://www.tiobe.com/tiobe-index/) | [Google Trends](https://trends.google.es/trends/explore?cat=5&date=today%205-y&q=%2Fm%2F02p97,%2Fm%2F05z1_,%2Fm%2F07sbkfb&hl=es)\n* [Historia](https://es.wikipedia.org/wiki/JavaScript)\n* [Especificación ECMAScript](https://tc39.es/ecma262/)\n* [Documentación Mozilla](https://developer.mozilla.org/es/docs/Web/JavaScript)\n* [Documentación W3Schools](https://www.w3schools.com/js/)\n* [Documentación JS Info](https://es.javascript.info/)\n* [Libro Eloquent JavaScript](https://eloquentjavascript.net/)\n* [Playground](https://runjs.app/play)\n* [Node.js](https://nodejs.org)\n* Exploradores: [Chrome](https://www.google.com/intl/es_es/chrome/) | [Brave](https://brave.com/download/)\n* [Visual Studio Code](https://code.visualstudio.com/)\n* [Guía de estilo](https://google.github.io/styleguide/jsguide.html)\n* Clientes HTTP: [Postman](https://postman.com) | [Apidog](https://apidog.com) | [Thunder Client](https://thunderclient.com)\n* APIs: [JSONPlaceholder](https://jsonplaceholder.typicode.com) | [OpenWeather](https://openweathermap.org) | [PokéAPI](https://pokeapi.co)\n* Expresiones regulares: [Documentación](https://developer.mozilla.org/es/docs/Web/JavaScript/Guide/Regular_expressions/Cheatsheet\n) | [Regex101](https://regex101.com/)\n* [Jest](https://jestjs.io/)\n\n## Únete al campus de programación de la comunidad\n\n![https://mouredev.pro](./Images/pro.jpg)\n\n#### Te presento [mouredev pro](https://mouredev.pro), mi proyecto más importante para ayudarte a estudiar programación y desarrollo de software de manera diferente.\n\n> **¿Buscas un extra?** Aquí encontrarás este y otros cursos editados por lecciones individuales, para avanzar a tu ritmo y guardar el progreso. También dispondrás de ejercicios y correcciones, test para validar tus conocimientos, examen y certificado público de finalización, soporte, foro de estudiantes, reunionnes grupales, cursos exclusivos y mucho más.\n> \n> Entra en **[mouredev.pro](https://mouredev.pro)** y utiliza el cupón **\"JAVASCRIPT\"** con un 15% de descuento en tu primera suscripción.\n\n## Preguntas frecuentes\n\n#### ¿Debo tener conocimientos previos?\nMi idea es que el curso sea desde cero y para principiantes. Pensado para una persona que comienza por primera vez a programar. Es un curso de fundamentos, donde nos centraremos en aprender las bases del lenguaje con JavaScript puro (Vanilla JS). Esto no es un curso para aprender a desarrollar proyectos. Vamos a empezar desde el principio.\n\nSi la acogida de la comunidad es buena, seguiré creando cursos más avanzados.\n\n#### ¿Este curso se va a subir a YouTube?\n\nSí, una vez finalizados, todos los cursos son editados y subidos en bloque a YouTube.\n\n#### ¿Existe algún lugar donde consultar dudas?\nHe creado un canal llamado \"JavaScript\" en el [servidor de Discord](https://discord.gg/mouredev) de la comunidad. Allí puedes consultar dudas y ayudar al resto de miembros. Así nos beneficiamos tod@s.\n\n#### ¿Cómo puedo practicar?\nEn cada lección encontrarás ejercicios para poner en práctica lo aprendido. También puedes realizar los ejercicios de mi web [retosdeprogramacion.com](https://retosdeprogramacion.com).\n\n## ![https://mouredev.com](https://raw.githubusercontent.com/mouredev/mouredev/master/mouredev_emote.png) Hola, mi nombre es Brais Moure.\n### Freelance full-stack iOS & Android engineer\n\n[![YouTube Channel Subscribers](https://img.shields.io/youtube/channel/subscribers/UCxPD7bsocoAMq8Dj18kmGyQ?style=social)](https://youtube.com/mouredevapps?sub_confirmation=1)\n[![Twitch Status](https://img.shields.io/twitch/status/mouredev?style=social)](https://twitch.com/mouredev)\n[![Discord](https://img.shields.io/discord/729672926432985098?style=social&label=Discord&logo=discord)](https://mouredev.com/discord)\n[![Twitter Follow](https://img.shields.io/twitter/follow/mouredev?style=social)](https://twitter.com/mouredev)\n![GitHub Followers](https://img.shields.io/github/followers/mouredev?style=social)\n![GitHub Followers](https://img.shields.io/github/stars/mouredev?style=social)\n\nSoy ingeniero de software desde 2010. Desde 2018 combino mi trabajo desarrollando Apps con la creación de contenido formativo sobre programación y tecnología en diferentes redes sociales como **[@mouredev](https://moure.dev)**.\n\nSi quieres unirte a nuestra comunidad de desarrollo, aprender programación, mejorar tus habilidades y ayudar a la continuidad del proyecto, puedes encontrarnos en:\n\n[![Twitch](https://img.shields.io/badge/Twitch-Programación_en_directo-9146FF?style=for-the-badge&logo=twitch&logoColor=white&labelColor=101010)](https://twitch.tv/mouredev)\n[![Discord](https://img.shields.io/badge/Discord-Servidor_de_la_comunidad-5865F2?style=for-the-badge&logo=discord&logoColor=white&labelColor=101010)](https://mouredev.com/discord) [![Pro](https://img.shields.io/badge/Cursos-mouredev.pro-FF5500?style=for-the-badge&logo=gnometerminal&logoColor=white&labelColor=101010)](https://mouredev.pro)\n[![Link](https://img.shields.io/badge/Links_de_interés-moure.dev-14a1f0?style=for-the-badge&logo=Linktree&logoColor=white&labelColor=101010)](https://moure.dev) [![Web](https://img.shields.io/badge/GitHub-MoureDev-087ec4?style=for-the-badge&logo=github&logoColor=white&labelColor=101010)](https://github.com/mouredev)\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"hello_javascript\",\n  \"version\": \"1.0.0\",\n  \"description\": \"[![JavaScript](https://img.shields.io/badge/JavaScript-ES6+-yellow?style=for-the-badge&logo=javascript&logoColor=white&labelColor=101010)](https://developer.mozilla.org/es/docs/Web/JavaScript) [![NodeJS](https://img.shields.io/badge/NODEJS-v20+-green?style=for-the-badge&logo=nodedotjs&logoColor=white&labelColor=101010)](https://nodejs.org/)\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"jest\"\n  },\n  \"keywords\": [],\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"devDependencies\": {\n    \"jest\": \"^29.7.0\"\n  }\n}"
  }
]