├── .gitignore ├── README.md ├── assets └── banner.png ├── plantilla-node-express ├── package-lock.json ├── package.json └── src │ └── index.js ├── plantilla-react-base ├── .gitignore ├── README.md ├── eslint.config.js ├── index.html ├── package-lock.json ├── package.json ├── public │ └── vite.svg ├── src │ ├── App.css │ ├── App.jsx │ ├── assets │ │ └── react.svg │ ├── index.css │ └── main.jsx └── vite.config.js ├── prueba-axios ├── .gitignore ├── Desafios_Dominar_Axios.pdf ├── README.md ├── Retos_Axios_Endpoints_Reales.pdf ├── eslint.config.js ├── index.html ├── package-lock.json ├── package.json ├── public │ └── vite.svg ├── src │ ├── App.css │ ├── App.jsx │ ├── assets │ │ └── react.svg │ ├── index.css │ └── main.jsx └── vite.config.js ├── prueba-final ├── .gitignore ├── Guia_Consumo_API_Productos.pdf ├── README.md ├── eslint.config.js ├── index.html ├── package-lock.json ├── package.json ├── public │ └── vite.svg ├── src │ ├── App.css │ ├── App.jsx │ ├── assets │ │ └── react.svg │ ├── index.css │ └── main.jsx └── vite.config.js ├── prueba1-formulario-registro ├── .gitignore ├── README.md ├── eslint.config.js ├── index.html ├── package-lock.json ├── package.json ├── public │ └── vite.svg ├── src │ ├── App.css │ ├── App.jsx │ ├── assets │ │ └── react.svg │ ├── index.css │ └── main.jsx └── vite.config.js ├── prueba2-api-productos ├── README.md ├── package-lock.json ├── package.json └── src │ ├── controllers │ └── productosController.js │ ├── index.js │ └── routes │ └── productos.js ├── prueba3-tareas-zustand ├── .gitignore ├── README.md ├── eslint.config.js ├── index.html ├── package-lock.json ├── package.json ├── public │ └── vite.svg ├── src │ ├── App.css │ ├── App.jsx │ ├── assets │ │ └── react.svg │ ├── index.css │ ├── main.jsx │ └── store │ │ └── tareas.jsx └── vite.config.js └── prueba4-postgreSql ├── README.md ├── package-lock.json ├── package.json └── src ├── controllers └── productosController.js ├── db └── db.js ├── index.js └── routes └── productos.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Node.js dependencies 2 | node_modules/ 3 | npm-debug.log* 4 | yarn-debug.log* 5 | yarn-error.log* 6 | 7 | # Logs 8 | logs/ 9 | *.log 10 | *.log.* 11 | 12 | # Environment variables 13 | .env 14 | 15 | # Build outputs 16 | dist/ 17 | build/ 18 | 19 | # System files 20 | .DS_Store 21 | Thumbs.db 22 | 23 | # IDE files 24 | .vscode/ 25 | .idea/ 26 | *.iml 27 | 28 | # Temporary files 29 | *.tmp 30 | *.swp 31 | *.swo 32 | *.bak 33 | 34 | # Coverage reports 35 | coverage/ 36 | 37 | # Miscellaneous 38 | *.out 39 | *.lock -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohanBoDev/mini-pruebas-fullstack/ecbbae8fe61f7dd6d52f1fb23641461beaf3385e/README.md -------------------------------------------------------------------------------- /assets/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohanBoDev/mini-pruebas-fullstack/ecbbae8fe61f7dd6d52f1fb23641461beaf3385e/assets/banner.png -------------------------------------------------------------------------------- /plantilla-node-express/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "plantilla-node-express", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "plantilla-node-express", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "cors": "^2.8.5", 13 | "dotenv": "^16.5.0", 14 | "express": "^5.1.0", 15 | "nodemon": "^3.1.9" 16 | } 17 | }, 18 | "node_modules/accepts": { 19 | "version": "2.0.0", 20 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", 21 | "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", 22 | "dependencies": { 23 | "mime-types": "^3.0.0", 24 | "negotiator": "^1.0.0" 25 | }, 26 | "engines": { 27 | "node": ">= 0.6" 28 | } 29 | }, 30 | "node_modules/anymatch": { 31 | "version": "3.1.3", 32 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", 33 | "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", 34 | "dependencies": { 35 | "normalize-path": "^3.0.0", 36 | "picomatch": "^2.0.4" 37 | }, 38 | "engines": { 39 | "node": ">= 8" 40 | } 41 | }, 42 | "node_modules/balanced-match": { 43 | "version": "1.0.2", 44 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 45 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 46 | }, 47 | "node_modules/binary-extensions": { 48 | "version": "2.3.0", 49 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", 50 | "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", 51 | "engines": { 52 | "node": ">=8" 53 | }, 54 | "funding": { 55 | "url": "https://github.com/sponsors/sindresorhus" 56 | } 57 | }, 58 | "node_modules/body-parser": { 59 | "version": "2.2.0", 60 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", 61 | "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", 62 | "dependencies": { 63 | "bytes": "^3.1.2", 64 | "content-type": "^1.0.5", 65 | "debug": "^4.4.0", 66 | "http-errors": "^2.0.0", 67 | "iconv-lite": "^0.6.3", 68 | "on-finished": "^2.4.1", 69 | "qs": "^6.14.0", 70 | "raw-body": "^3.0.0", 71 | "type-is": "^2.0.0" 72 | }, 73 | "engines": { 74 | "node": ">=18" 75 | } 76 | }, 77 | "node_modules/brace-expansion": { 78 | "version": "1.1.11", 79 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 80 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 81 | "dependencies": { 82 | "balanced-match": "^1.0.0", 83 | "concat-map": "0.0.1" 84 | } 85 | }, 86 | "node_modules/braces": { 87 | "version": "3.0.3", 88 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", 89 | "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", 90 | "dependencies": { 91 | "fill-range": "^7.1.1" 92 | }, 93 | "engines": { 94 | "node": ">=8" 95 | } 96 | }, 97 | "node_modules/bytes": { 98 | "version": "3.1.2", 99 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 100 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 101 | "engines": { 102 | "node": ">= 0.8" 103 | } 104 | }, 105 | "node_modules/call-bind-apply-helpers": { 106 | "version": "1.0.2", 107 | "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", 108 | "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", 109 | "dependencies": { 110 | "es-errors": "^1.3.0", 111 | "function-bind": "^1.1.2" 112 | }, 113 | "engines": { 114 | "node": ">= 0.4" 115 | } 116 | }, 117 | "node_modules/call-bound": { 118 | "version": "1.0.4", 119 | "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", 120 | "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", 121 | "dependencies": { 122 | "call-bind-apply-helpers": "^1.0.2", 123 | "get-intrinsic": "^1.3.0" 124 | }, 125 | "engines": { 126 | "node": ">= 0.4" 127 | }, 128 | "funding": { 129 | "url": "https://github.com/sponsors/ljharb" 130 | } 131 | }, 132 | "node_modules/chokidar": { 133 | "version": "3.6.0", 134 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", 135 | "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", 136 | "dependencies": { 137 | "anymatch": "~3.1.2", 138 | "braces": "~3.0.2", 139 | "glob-parent": "~5.1.2", 140 | "is-binary-path": "~2.1.0", 141 | "is-glob": "~4.0.1", 142 | "normalize-path": "~3.0.0", 143 | "readdirp": "~3.6.0" 144 | }, 145 | "engines": { 146 | "node": ">= 8.10.0" 147 | }, 148 | "funding": { 149 | "url": "https://paulmillr.com/funding/" 150 | }, 151 | "optionalDependencies": { 152 | "fsevents": "~2.3.2" 153 | } 154 | }, 155 | "node_modules/concat-map": { 156 | "version": "0.0.1", 157 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 158 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" 159 | }, 160 | "node_modules/content-disposition": { 161 | "version": "1.0.0", 162 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", 163 | "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", 164 | "dependencies": { 165 | "safe-buffer": "5.2.1" 166 | }, 167 | "engines": { 168 | "node": ">= 0.6" 169 | } 170 | }, 171 | "node_modules/content-type": { 172 | "version": "1.0.5", 173 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 174 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 175 | "engines": { 176 | "node": ">= 0.6" 177 | } 178 | }, 179 | "node_modules/cookie": { 180 | "version": "0.7.2", 181 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", 182 | "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", 183 | "engines": { 184 | "node": ">= 0.6" 185 | } 186 | }, 187 | "node_modules/cookie-signature": { 188 | "version": "1.2.2", 189 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", 190 | "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", 191 | "engines": { 192 | "node": ">=6.6.0" 193 | } 194 | }, 195 | "node_modules/cors": { 196 | "version": "2.8.5", 197 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 198 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 199 | "dependencies": { 200 | "object-assign": "^4", 201 | "vary": "^1" 202 | }, 203 | "engines": { 204 | "node": ">= 0.10" 205 | } 206 | }, 207 | "node_modules/debug": { 208 | "version": "4.4.0", 209 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", 210 | "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", 211 | "dependencies": { 212 | "ms": "^2.1.3" 213 | }, 214 | "engines": { 215 | "node": ">=6.0" 216 | }, 217 | "peerDependenciesMeta": { 218 | "supports-color": { 219 | "optional": true 220 | } 221 | } 222 | }, 223 | "node_modules/depd": { 224 | "version": "2.0.0", 225 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 226 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 227 | "engines": { 228 | "node": ">= 0.8" 229 | } 230 | }, 231 | "node_modules/dotenv": { 232 | "version": "16.5.0", 233 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz", 234 | "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==", 235 | "engines": { 236 | "node": ">=12" 237 | }, 238 | "funding": { 239 | "url": "https://dotenvx.com" 240 | } 241 | }, 242 | "node_modules/dunder-proto": { 243 | "version": "1.0.1", 244 | "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", 245 | "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", 246 | "dependencies": { 247 | "call-bind-apply-helpers": "^1.0.1", 248 | "es-errors": "^1.3.0", 249 | "gopd": "^1.2.0" 250 | }, 251 | "engines": { 252 | "node": ">= 0.4" 253 | } 254 | }, 255 | "node_modules/ee-first": { 256 | "version": "1.1.1", 257 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 258 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 259 | }, 260 | "node_modules/encodeurl": { 261 | "version": "2.0.0", 262 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", 263 | "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", 264 | "engines": { 265 | "node": ">= 0.8" 266 | } 267 | }, 268 | "node_modules/es-define-property": { 269 | "version": "1.0.1", 270 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", 271 | "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", 272 | "engines": { 273 | "node": ">= 0.4" 274 | } 275 | }, 276 | "node_modules/es-errors": { 277 | "version": "1.3.0", 278 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 279 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 280 | "engines": { 281 | "node": ">= 0.4" 282 | } 283 | }, 284 | "node_modules/es-object-atoms": { 285 | "version": "1.1.1", 286 | "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", 287 | "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", 288 | "dependencies": { 289 | "es-errors": "^1.3.0" 290 | }, 291 | "engines": { 292 | "node": ">= 0.4" 293 | } 294 | }, 295 | "node_modules/escape-html": { 296 | "version": "1.0.3", 297 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 298 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 299 | }, 300 | "node_modules/etag": { 301 | "version": "1.8.1", 302 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 303 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 304 | "engines": { 305 | "node": ">= 0.6" 306 | } 307 | }, 308 | "node_modules/express": { 309 | "version": "5.1.0", 310 | "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", 311 | "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", 312 | "dependencies": { 313 | "accepts": "^2.0.0", 314 | "body-parser": "^2.2.0", 315 | "content-disposition": "^1.0.0", 316 | "content-type": "^1.0.5", 317 | "cookie": "^0.7.1", 318 | "cookie-signature": "^1.2.1", 319 | "debug": "^4.4.0", 320 | "encodeurl": "^2.0.0", 321 | "escape-html": "^1.0.3", 322 | "etag": "^1.8.1", 323 | "finalhandler": "^2.1.0", 324 | "fresh": "^2.0.0", 325 | "http-errors": "^2.0.0", 326 | "merge-descriptors": "^2.0.0", 327 | "mime-types": "^3.0.0", 328 | "on-finished": "^2.4.1", 329 | "once": "^1.4.0", 330 | "parseurl": "^1.3.3", 331 | "proxy-addr": "^2.0.7", 332 | "qs": "^6.14.0", 333 | "range-parser": "^1.2.1", 334 | "router": "^2.2.0", 335 | "send": "^1.1.0", 336 | "serve-static": "^2.2.0", 337 | "statuses": "^2.0.1", 338 | "type-is": "^2.0.1", 339 | "vary": "^1.1.2" 340 | }, 341 | "engines": { 342 | "node": ">= 18" 343 | }, 344 | "funding": { 345 | "type": "opencollective", 346 | "url": "https://opencollective.com/express" 347 | } 348 | }, 349 | "node_modules/fill-range": { 350 | "version": "7.1.1", 351 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", 352 | "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", 353 | "dependencies": { 354 | "to-regex-range": "^5.0.1" 355 | }, 356 | "engines": { 357 | "node": ">=8" 358 | } 359 | }, 360 | "node_modules/finalhandler": { 361 | "version": "2.1.0", 362 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", 363 | "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", 364 | "dependencies": { 365 | "debug": "^4.4.0", 366 | "encodeurl": "^2.0.0", 367 | "escape-html": "^1.0.3", 368 | "on-finished": "^2.4.1", 369 | "parseurl": "^1.3.3", 370 | "statuses": "^2.0.1" 371 | }, 372 | "engines": { 373 | "node": ">= 0.8" 374 | } 375 | }, 376 | "node_modules/forwarded": { 377 | "version": "0.2.0", 378 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 379 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 380 | "engines": { 381 | "node": ">= 0.6" 382 | } 383 | }, 384 | "node_modules/fresh": { 385 | "version": "2.0.0", 386 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", 387 | "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", 388 | "engines": { 389 | "node": ">= 0.8" 390 | } 391 | }, 392 | "node_modules/fsevents": { 393 | "version": "2.3.3", 394 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 395 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 396 | "hasInstallScript": true, 397 | "optional": true, 398 | "os": [ 399 | "darwin" 400 | ], 401 | "engines": { 402 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 403 | } 404 | }, 405 | "node_modules/function-bind": { 406 | "version": "1.1.2", 407 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 408 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 409 | "funding": { 410 | "url": "https://github.com/sponsors/ljharb" 411 | } 412 | }, 413 | "node_modules/get-intrinsic": { 414 | "version": "1.3.0", 415 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", 416 | "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", 417 | "dependencies": { 418 | "call-bind-apply-helpers": "^1.0.2", 419 | "es-define-property": "^1.0.1", 420 | "es-errors": "^1.3.0", 421 | "es-object-atoms": "^1.1.1", 422 | "function-bind": "^1.1.2", 423 | "get-proto": "^1.0.1", 424 | "gopd": "^1.2.0", 425 | "has-symbols": "^1.1.0", 426 | "hasown": "^2.0.2", 427 | "math-intrinsics": "^1.1.0" 428 | }, 429 | "engines": { 430 | "node": ">= 0.4" 431 | }, 432 | "funding": { 433 | "url": "https://github.com/sponsors/ljharb" 434 | } 435 | }, 436 | "node_modules/get-proto": { 437 | "version": "1.0.1", 438 | "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", 439 | "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", 440 | "dependencies": { 441 | "dunder-proto": "^1.0.1", 442 | "es-object-atoms": "^1.0.0" 443 | }, 444 | "engines": { 445 | "node": ">= 0.4" 446 | } 447 | }, 448 | "node_modules/glob-parent": { 449 | "version": "5.1.2", 450 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 451 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 452 | "dependencies": { 453 | "is-glob": "^4.0.1" 454 | }, 455 | "engines": { 456 | "node": ">= 6" 457 | } 458 | }, 459 | "node_modules/gopd": { 460 | "version": "1.2.0", 461 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", 462 | "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", 463 | "engines": { 464 | "node": ">= 0.4" 465 | }, 466 | "funding": { 467 | "url": "https://github.com/sponsors/ljharb" 468 | } 469 | }, 470 | "node_modules/has-flag": { 471 | "version": "3.0.0", 472 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 473 | "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", 474 | "engines": { 475 | "node": ">=4" 476 | } 477 | }, 478 | "node_modules/has-symbols": { 479 | "version": "1.1.0", 480 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", 481 | "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", 482 | "engines": { 483 | "node": ">= 0.4" 484 | }, 485 | "funding": { 486 | "url": "https://github.com/sponsors/ljharb" 487 | } 488 | }, 489 | "node_modules/hasown": { 490 | "version": "2.0.2", 491 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 492 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 493 | "dependencies": { 494 | "function-bind": "^1.1.2" 495 | }, 496 | "engines": { 497 | "node": ">= 0.4" 498 | } 499 | }, 500 | "node_modules/http-errors": { 501 | "version": "2.0.0", 502 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 503 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 504 | "dependencies": { 505 | "depd": "2.0.0", 506 | "inherits": "2.0.4", 507 | "setprototypeof": "1.2.0", 508 | "statuses": "2.0.1", 509 | "toidentifier": "1.0.1" 510 | }, 511 | "engines": { 512 | "node": ">= 0.8" 513 | } 514 | }, 515 | "node_modules/iconv-lite": { 516 | "version": "0.6.3", 517 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", 518 | "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", 519 | "dependencies": { 520 | "safer-buffer": ">= 2.1.2 < 3.0.0" 521 | }, 522 | "engines": { 523 | "node": ">=0.10.0" 524 | } 525 | }, 526 | "node_modules/ignore-by-default": { 527 | "version": "1.0.1", 528 | "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", 529 | "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" 530 | }, 531 | "node_modules/inherits": { 532 | "version": "2.0.4", 533 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 534 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 535 | }, 536 | "node_modules/ipaddr.js": { 537 | "version": "1.9.1", 538 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 539 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 540 | "engines": { 541 | "node": ">= 0.10" 542 | } 543 | }, 544 | "node_modules/is-binary-path": { 545 | "version": "2.1.0", 546 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 547 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 548 | "dependencies": { 549 | "binary-extensions": "^2.0.0" 550 | }, 551 | "engines": { 552 | "node": ">=8" 553 | } 554 | }, 555 | "node_modules/is-extglob": { 556 | "version": "2.1.1", 557 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 558 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 559 | "engines": { 560 | "node": ">=0.10.0" 561 | } 562 | }, 563 | "node_modules/is-glob": { 564 | "version": "4.0.3", 565 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 566 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 567 | "dependencies": { 568 | "is-extglob": "^2.1.1" 569 | }, 570 | "engines": { 571 | "node": ">=0.10.0" 572 | } 573 | }, 574 | "node_modules/is-number": { 575 | "version": "7.0.0", 576 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 577 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 578 | "engines": { 579 | "node": ">=0.12.0" 580 | } 581 | }, 582 | "node_modules/is-promise": { 583 | "version": "4.0.0", 584 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", 585 | "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==" 586 | }, 587 | "node_modules/math-intrinsics": { 588 | "version": "1.1.0", 589 | "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", 590 | "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", 591 | "engines": { 592 | "node": ">= 0.4" 593 | } 594 | }, 595 | "node_modules/media-typer": { 596 | "version": "1.1.0", 597 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", 598 | "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", 599 | "engines": { 600 | "node": ">= 0.8" 601 | } 602 | }, 603 | "node_modules/merge-descriptors": { 604 | "version": "2.0.0", 605 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", 606 | "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", 607 | "engines": { 608 | "node": ">=18" 609 | }, 610 | "funding": { 611 | "url": "https://github.com/sponsors/sindresorhus" 612 | } 613 | }, 614 | "node_modules/mime-db": { 615 | "version": "1.54.0", 616 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", 617 | "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", 618 | "engines": { 619 | "node": ">= 0.6" 620 | } 621 | }, 622 | "node_modules/mime-types": { 623 | "version": "3.0.1", 624 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", 625 | "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", 626 | "dependencies": { 627 | "mime-db": "^1.54.0" 628 | }, 629 | "engines": { 630 | "node": ">= 0.6" 631 | } 632 | }, 633 | "node_modules/minimatch": { 634 | "version": "3.1.2", 635 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 636 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 637 | "dependencies": { 638 | "brace-expansion": "^1.1.7" 639 | }, 640 | "engines": { 641 | "node": "*" 642 | } 643 | }, 644 | "node_modules/ms": { 645 | "version": "2.1.3", 646 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 647 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 648 | }, 649 | "node_modules/negotiator": { 650 | "version": "1.0.0", 651 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", 652 | "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", 653 | "engines": { 654 | "node": ">= 0.6" 655 | } 656 | }, 657 | "node_modules/nodemon": { 658 | "version": "3.1.9", 659 | "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.9.tgz", 660 | "integrity": "sha512-hdr1oIb2p6ZSxu3PB2JWWYS7ZQ0qvaZsc3hK8DR8f02kRzc8rjYmxAIvdz+aYC+8F2IjNaB7HMcSDg8nQpJxyg==", 661 | "dependencies": { 662 | "chokidar": "^3.5.2", 663 | "debug": "^4", 664 | "ignore-by-default": "^1.0.1", 665 | "minimatch": "^3.1.2", 666 | "pstree.remy": "^1.1.8", 667 | "semver": "^7.5.3", 668 | "simple-update-notifier": "^2.0.0", 669 | "supports-color": "^5.5.0", 670 | "touch": "^3.1.0", 671 | "undefsafe": "^2.0.5" 672 | }, 673 | "bin": { 674 | "nodemon": "bin/nodemon.js" 675 | }, 676 | "engines": { 677 | "node": ">=10" 678 | }, 679 | "funding": { 680 | "type": "opencollective", 681 | "url": "https://opencollective.com/nodemon" 682 | } 683 | }, 684 | "node_modules/normalize-path": { 685 | "version": "3.0.0", 686 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 687 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 688 | "engines": { 689 | "node": ">=0.10.0" 690 | } 691 | }, 692 | "node_modules/object-assign": { 693 | "version": "4.1.1", 694 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 695 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", 696 | "engines": { 697 | "node": ">=0.10.0" 698 | } 699 | }, 700 | "node_modules/object-inspect": { 701 | "version": "1.13.4", 702 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", 703 | "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", 704 | "engines": { 705 | "node": ">= 0.4" 706 | }, 707 | "funding": { 708 | "url": "https://github.com/sponsors/ljharb" 709 | } 710 | }, 711 | "node_modules/on-finished": { 712 | "version": "2.4.1", 713 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 714 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 715 | "dependencies": { 716 | "ee-first": "1.1.1" 717 | }, 718 | "engines": { 719 | "node": ">= 0.8" 720 | } 721 | }, 722 | "node_modules/once": { 723 | "version": "1.4.0", 724 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 725 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 726 | "dependencies": { 727 | "wrappy": "1" 728 | } 729 | }, 730 | "node_modules/parseurl": { 731 | "version": "1.3.3", 732 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 733 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 734 | "engines": { 735 | "node": ">= 0.8" 736 | } 737 | }, 738 | "node_modules/path-to-regexp": { 739 | "version": "8.2.0", 740 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", 741 | "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", 742 | "engines": { 743 | "node": ">=16" 744 | } 745 | }, 746 | "node_modules/picomatch": { 747 | "version": "2.3.1", 748 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 749 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 750 | "engines": { 751 | "node": ">=8.6" 752 | }, 753 | "funding": { 754 | "url": "https://github.com/sponsors/jonschlinkert" 755 | } 756 | }, 757 | "node_modules/proxy-addr": { 758 | "version": "2.0.7", 759 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 760 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 761 | "dependencies": { 762 | "forwarded": "0.2.0", 763 | "ipaddr.js": "1.9.1" 764 | }, 765 | "engines": { 766 | "node": ">= 0.10" 767 | } 768 | }, 769 | "node_modules/pstree.remy": { 770 | "version": "1.1.8", 771 | "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", 772 | "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" 773 | }, 774 | "node_modules/qs": { 775 | "version": "6.14.0", 776 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", 777 | "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", 778 | "dependencies": { 779 | "side-channel": "^1.1.0" 780 | }, 781 | "engines": { 782 | "node": ">=0.6" 783 | }, 784 | "funding": { 785 | "url": "https://github.com/sponsors/ljharb" 786 | } 787 | }, 788 | "node_modules/range-parser": { 789 | "version": "1.2.1", 790 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 791 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 792 | "engines": { 793 | "node": ">= 0.6" 794 | } 795 | }, 796 | "node_modules/raw-body": { 797 | "version": "3.0.0", 798 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", 799 | "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", 800 | "dependencies": { 801 | "bytes": "3.1.2", 802 | "http-errors": "2.0.0", 803 | "iconv-lite": "0.6.3", 804 | "unpipe": "1.0.0" 805 | }, 806 | "engines": { 807 | "node": ">= 0.8" 808 | } 809 | }, 810 | "node_modules/readdirp": { 811 | "version": "3.6.0", 812 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 813 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 814 | "dependencies": { 815 | "picomatch": "^2.2.1" 816 | }, 817 | "engines": { 818 | "node": ">=8.10.0" 819 | } 820 | }, 821 | "node_modules/router": { 822 | "version": "2.2.0", 823 | "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", 824 | "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", 825 | "dependencies": { 826 | "debug": "^4.4.0", 827 | "depd": "^2.0.0", 828 | "is-promise": "^4.0.0", 829 | "parseurl": "^1.3.3", 830 | "path-to-regexp": "^8.0.0" 831 | }, 832 | "engines": { 833 | "node": ">= 18" 834 | } 835 | }, 836 | "node_modules/safe-buffer": { 837 | "version": "5.2.1", 838 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 839 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 840 | "funding": [ 841 | { 842 | "type": "github", 843 | "url": "https://github.com/sponsors/feross" 844 | }, 845 | { 846 | "type": "patreon", 847 | "url": "https://www.patreon.com/feross" 848 | }, 849 | { 850 | "type": "consulting", 851 | "url": "https://feross.org/support" 852 | } 853 | ] 854 | }, 855 | "node_modules/safer-buffer": { 856 | "version": "2.1.2", 857 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 858 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 859 | }, 860 | "node_modules/semver": { 861 | "version": "7.7.1", 862 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", 863 | "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", 864 | "bin": { 865 | "semver": "bin/semver.js" 866 | }, 867 | "engines": { 868 | "node": ">=10" 869 | } 870 | }, 871 | "node_modules/send": { 872 | "version": "1.2.0", 873 | "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", 874 | "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", 875 | "dependencies": { 876 | "debug": "^4.3.5", 877 | "encodeurl": "^2.0.0", 878 | "escape-html": "^1.0.3", 879 | "etag": "^1.8.1", 880 | "fresh": "^2.0.0", 881 | "http-errors": "^2.0.0", 882 | "mime-types": "^3.0.1", 883 | "ms": "^2.1.3", 884 | "on-finished": "^2.4.1", 885 | "range-parser": "^1.2.1", 886 | "statuses": "^2.0.1" 887 | }, 888 | "engines": { 889 | "node": ">= 18" 890 | } 891 | }, 892 | "node_modules/serve-static": { 893 | "version": "2.2.0", 894 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", 895 | "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", 896 | "dependencies": { 897 | "encodeurl": "^2.0.0", 898 | "escape-html": "^1.0.3", 899 | "parseurl": "^1.3.3", 900 | "send": "^1.2.0" 901 | }, 902 | "engines": { 903 | "node": ">= 18" 904 | } 905 | }, 906 | "node_modules/setprototypeof": { 907 | "version": "1.2.0", 908 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 909 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 910 | }, 911 | "node_modules/side-channel": { 912 | "version": "1.1.0", 913 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", 914 | "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", 915 | "dependencies": { 916 | "es-errors": "^1.3.0", 917 | "object-inspect": "^1.13.3", 918 | "side-channel-list": "^1.0.0", 919 | "side-channel-map": "^1.0.1", 920 | "side-channel-weakmap": "^1.0.2" 921 | }, 922 | "engines": { 923 | "node": ">= 0.4" 924 | }, 925 | "funding": { 926 | "url": "https://github.com/sponsors/ljharb" 927 | } 928 | }, 929 | "node_modules/side-channel-list": { 930 | "version": "1.0.0", 931 | "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", 932 | "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", 933 | "dependencies": { 934 | "es-errors": "^1.3.0", 935 | "object-inspect": "^1.13.3" 936 | }, 937 | "engines": { 938 | "node": ">= 0.4" 939 | }, 940 | "funding": { 941 | "url": "https://github.com/sponsors/ljharb" 942 | } 943 | }, 944 | "node_modules/side-channel-map": { 945 | "version": "1.0.1", 946 | "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", 947 | "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", 948 | "dependencies": { 949 | "call-bound": "^1.0.2", 950 | "es-errors": "^1.3.0", 951 | "get-intrinsic": "^1.2.5", 952 | "object-inspect": "^1.13.3" 953 | }, 954 | "engines": { 955 | "node": ">= 0.4" 956 | }, 957 | "funding": { 958 | "url": "https://github.com/sponsors/ljharb" 959 | } 960 | }, 961 | "node_modules/side-channel-weakmap": { 962 | "version": "1.0.2", 963 | "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", 964 | "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", 965 | "dependencies": { 966 | "call-bound": "^1.0.2", 967 | "es-errors": "^1.3.0", 968 | "get-intrinsic": "^1.2.5", 969 | "object-inspect": "^1.13.3", 970 | "side-channel-map": "^1.0.1" 971 | }, 972 | "engines": { 973 | "node": ">= 0.4" 974 | }, 975 | "funding": { 976 | "url": "https://github.com/sponsors/ljharb" 977 | } 978 | }, 979 | "node_modules/simple-update-notifier": { 980 | "version": "2.0.0", 981 | "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", 982 | "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", 983 | "dependencies": { 984 | "semver": "^7.5.3" 985 | }, 986 | "engines": { 987 | "node": ">=10" 988 | } 989 | }, 990 | "node_modules/statuses": { 991 | "version": "2.0.1", 992 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 993 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 994 | "engines": { 995 | "node": ">= 0.8" 996 | } 997 | }, 998 | "node_modules/supports-color": { 999 | "version": "5.5.0", 1000 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1001 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1002 | "dependencies": { 1003 | "has-flag": "^3.0.0" 1004 | }, 1005 | "engines": { 1006 | "node": ">=4" 1007 | } 1008 | }, 1009 | "node_modules/to-regex-range": { 1010 | "version": "5.0.1", 1011 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1012 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1013 | "dependencies": { 1014 | "is-number": "^7.0.0" 1015 | }, 1016 | "engines": { 1017 | "node": ">=8.0" 1018 | } 1019 | }, 1020 | "node_modules/toidentifier": { 1021 | "version": "1.0.1", 1022 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 1023 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 1024 | "engines": { 1025 | "node": ">=0.6" 1026 | } 1027 | }, 1028 | "node_modules/touch": { 1029 | "version": "3.1.1", 1030 | "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", 1031 | "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", 1032 | "bin": { 1033 | "nodetouch": "bin/nodetouch.js" 1034 | } 1035 | }, 1036 | "node_modules/type-is": { 1037 | "version": "2.0.1", 1038 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", 1039 | "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", 1040 | "dependencies": { 1041 | "content-type": "^1.0.5", 1042 | "media-typer": "^1.1.0", 1043 | "mime-types": "^3.0.0" 1044 | }, 1045 | "engines": { 1046 | "node": ">= 0.6" 1047 | } 1048 | }, 1049 | "node_modules/undefsafe": { 1050 | "version": "2.0.5", 1051 | "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", 1052 | "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" 1053 | }, 1054 | "node_modules/unpipe": { 1055 | "version": "1.0.0", 1056 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1057 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 1058 | "engines": { 1059 | "node": ">= 0.8" 1060 | } 1061 | }, 1062 | "node_modules/vary": { 1063 | "version": "1.1.2", 1064 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1065 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 1066 | "engines": { 1067 | "node": ">= 0.8" 1068 | } 1069 | }, 1070 | "node_modules/wrappy": { 1071 | "version": "1.0.2", 1072 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1073 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" 1074 | } 1075 | } 1076 | } 1077 | -------------------------------------------------------------------------------- /plantilla-node-express/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "plantilla-node-express", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "type": "module", 6 | 7 | "scripts": { 8 | "dev": "nodemon src/index.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "description": "", 14 | "dependencies": { 15 | "cors": "^2.8.5", 16 | "dotenv": "^16.5.0", 17 | "express": "^5.1.0", 18 | "nodemon": "^3.1.9" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /plantilla-node-express/src/index.js: -------------------------------------------------------------------------------- 1 | // src/index.js 2 | import express from "express"; 3 | import cors from "cors"; 4 | import dotenv from "dotenv"; 5 | 6 | dotenv.config(); 7 | 8 | const app = express(); 9 | app.use(cors()); 10 | app.use(express.json()); 11 | 12 | app.get("/", (req, res) => { 13 | res.send("API funcionando 🚀"); 14 | }); 15 | 16 | const PORT = process.env.PORT || 3000; 17 | app.listen(PORT, () => { 18 | console.log(`Servidor corriendo en http://localhost:${PORT}`); 19 | }); 20 | -------------------------------------------------------------------------------- /plantilla-react-base/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /plantilla-react-base/README.md: -------------------------------------------------------------------------------- 1 | # React + Vite 2 | 3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. 4 | 5 | Currently, two official plugins are available: 6 | 7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh 8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh 9 | 10 | ## Expanding the ESLint configuration 11 | 12 | If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project. 13 | -------------------------------------------------------------------------------- /plantilla-react-base/eslint.config.js: -------------------------------------------------------------------------------- 1 | import js from '@eslint/js' 2 | import globals from 'globals' 3 | import reactHooks from 'eslint-plugin-react-hooks' 4 | import reactRefresh from 'eslint-plugin-react-refresh' 5 | 6 | export default [ 7 | { ignores: ['dist'] }, 8 | { 9 | files: ['**/*.{js,jsx}'], 10 | languageOptions: { 11 | ecmaVersion: 2020, 12 | globals: globals.browser, 13 | parserOptions: { 14 | ecmaVersion: 'latest', 15 | ecmaFeatures: { jsx: true }, 16 | sourceType: 'module', 17 | }, 18 | }, 19 | plugins: { 20 | 'react-hooks': reactHooks, 21 | 'react-refresh': reactRefresh, 22 | }, 23 | rules: { 24 | ...js.configs.recommended.rules, 25 | ...reactHooks.configs.recommended.rules, 26 | 'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }], 27 | 'react-refresh/only-export-components': [ 28 | 'warn', 29 | { allowConstantExport: true }, 30 | ], 31 | }, 32 | }, 33 | ] 34 | -------------------------------------------------------------------------------- /plantilla-react-base/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /plantilla-react-base/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "plantilla-react-base", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "lint": "eslint .", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "@chakra-ui/react": "^2.10.7", 14 | "@emotion/react": "^11.14.0", 15 | "@emotion/styled": "^11.14.0", 16 | "@tailwindcss/postcss": "^4.1.4", 17 | "framer-motion": "^12.7.4", 18 | "react": "^19.0.0", 19 | "react-dom": "^19.0.0", 20 | "react-hook-form": "^7.56.1", 21 | "react-icons": "^5.5.0", 22 | "zustand": "^5.0.3" 23 | }, 24 | "devDependencies": { 25 | "@eslint/js": "^9.22.0", 26 | "@tailwindcss/vite": "^4.1.4", 27 | "@types/react": "^19.0.10", 28 | "@types/react-dom": "^19.0.4", 29 | "@vitejs/plugin-react": "^4.3.4", 30 | "autoprefixer": "^10.4.21", 31 | "eslint": "^9.22.0", 32 | "eslint-plugin-react-hooks": "^5.2.0", 33 | "eslint-plugin-react-refresh": "^0.4.19", 34 | "globals": "^16.0.0", 35 | "postcss": "^8.5.3", 36 | "tailwindcss": "^4.1.4", 37 | "vite": "^6.3.1" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /plantilla-react-base/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /plantilla-react-base/src/App.css: -------------------------------------------------------------------------------- 1 | #root { 2 | max-width: 1280px; 3 | margin: 0 auto; 4 | padding: 2rem; 5 | text-align: center; 6 | } 7 | 8 | .logo { 9 | height: 6em; 10 | padding: 1.5em; 11 | will-change: filter; 12 | transition: filter 300ms; 13 | } 14 | .logo:hover { 15 | filter: drop-shadow(0 0 2em #646cffaa); 16 | } 17 | .logo.react:hover { 18 | filter: drop-shadow(0 0 2em #61dafbaa); 19 | } 20 | 21 | @keyframes logo-spin { 22 | from { 23 | transform: rotate(0deg); 24 | } 25 | to { 26 | transform: rotate(360deg); 27 | } 28 | } 29 | 30 | @media (prefers-reduced-motion: no-preference) { 31 | a:nth-of-type(2) .logo { 32 | animation: logo-spin infinite 20s linear; 33 | } 34 | } 35 | 36 | .card { 37 | padding: 2em; 38 | } 39 | 40 | .read-the-docs { 41 | color: #888; 42 | } 43 | -------------------------------------------------------------------------------- /plantilla-react-base/src/App.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react' 2 | import reactLogo from './assets/react.svg' 3 | import viteLogo from '/vite.svg' 4 | import './App.css' 5 | import { Box, Text, Stack } from '@chakra-ui/react'; 6 | 7 | 8 | function App() { 9 | const [count, setCount] = useState(0) 10 | 11 | return ( 12 |
13 | 14 | Título en grande 15 | 16 | 17 | 18 | Caja 1 19 | Caja 2 20 | 21 |
22 | ) 23 | } 24 | 25 | export default App 26 | -------------------------------------------------------------------------------- /plantilla-react-base/src/assets/react.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /plantilla-react-base/src/index.css: -------------------------------------------------------------------------------- 1 | @import "tailwindcss"; 2 | -------------------------------------------------------------------------------- /plantilla-react-base/src/main.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import App from './App.jsx' 4 | import './index.css' 5 | import { ChakraProvider } from '@chakra-ui/react' 6 | 7 | ReactDOM.createRoot(document.getElementById('root')).render( 8 | 9 | 10 | 11 | 12 | , 13 | ) 14 | -------------------------------------------------------------------------------- /plantilla-react-base/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | import tailwindcss from "@tailwindcss/vite"; 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig({ 7 | plugins: [react(), tailwindcss()], 8 | }) 9 | -------------------------------------------------------------------------------- /prueba-axios/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /prueba-axios/Desafios_Dominar_Axios.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohanBoDev/mini-pruebas-fullstack/ecbbae8fe61f7dd6d52f1fb23641461beaf3385e/prueba-axios/Desafios_Dominar_Axios.pdf -------------------------------------------------------------------------------- /prueba-axios/README.md: -------------------------------------------------------------------------------- 1 | # React + Vite 2 | 3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. 4 | 5 | Currently, two official plugins are available: 6 | 7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh 8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh 9 | 10 | ## Expanding the ESLint configuration 11 | 12 | If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project. 13 | -------------------------------------------------------------------------------- /prueba-axios/Retos_Axios_Endpoints_Reales.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohanBoDev/mini-pruebas-fullstack/ecbbae8fe61f7dd6d52f1fb23641461beaf3385e/prueba-axios/Retos_Axios_Endpoints_Reales.pdf -------------------------------------------------------------------------------- /prueba-axios/eslint.config.js: -------------------------------------------------------------------------------- 1 | import js from '@eslint/js' 2 | import globals from 'globals' 3 | import reactHooks from 'eslint-plugin-react-hooks' 4 | import reactRefresh from 'eslint-plugin-react-refresh' 5 | 6 | export default [ 7 | { ignores: ['dist'] }, 8 | { 9 | files: ['**/*.{js,jsx}'], 10 | languageOptions: { 11 | ecmaVersion: 2020, 12 | globals: globals.browser, 13 | parserOptions: { 14 | ecmaVersion: 'latest', 15 | ecmaFeatures: { jsx: true }, 16 | sourceType: 'module', 17 | }, 18 | }, 19 | plugins: { 20 | 'react-hooks': reactHooks, 21 | 'react-refresh': reactRefresh, 22 | }, 23 | rules: { 24 | ...js.configs.recommended.rules, 25 | ...reactHooks.configs.recommended.rules, 26 | 'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }], 27 | 'react-refresh/only-export-components': [ 28 | 'warn', 29 | { allowConstantExport: true }, 30 | ], 31 | }, 32 | }, 33 | ] 34 | -------------------------------------------------------------------------------- /prueba-axios/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /prueba-axios/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "plantilla-react-base", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "lint": "eslint .", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "@chakra-ui/react": "^2.10.7", 14 | "@emotion/react": "^11.14.0", 15 | "@emotion/styled": "^11.14.0", 16 | "@tailwindcss/postcss": "^4.1.4", 17 | "axios": "^1.9.0", 18 | "framer-motion": "^12.7.4", 19 | "react": "^19.0.0", 20 | "react-dom": "^19.0.0", 21 | "react-hook-form": "^7.56.1", 22 | "react-icons": "^5.5.0", 23 | "zustand": "^5.0.3" 24 | }, 25 | "devDependencies": { 26 | "@eslint/js": "^9.22.0", 27 | "@tailwindcss/vite": "^4.1.4", 28 | "@types/react": "^19.0.10", 29 | "@types/react-dom": "^19.0.4", 30 | "@vitejs/plugin-react": "^4.3.4", 31 | "autoprefixer": "^10.4.21", 32 | "eslint": "^9.22.0", 33 | "eslint-plugin-react-hooks": "^5.2.0", 34 | "eslint-plugin-react-refresh": "^0.4.19", 35 | "globals": "^16.0.0", 36 | "postcss": "^8.5.3", 37 | "tailwindcss": "^4.1.4", 38 | "vite": "^6.3.1" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /prueba-axios/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /prueba-axios/src/App.css: -------------------------------------------------------------------------------- 1 | #root { 2 | max-width: 1280px; 3 | margin: 0 auto; 4 | padding: 2rem; 5 | text-align: center; 6 | } 7 | 8 | .logo { 9 | height: 6em; 10 | padding: 1.5em; 11 | will-change: filter; 12 | transition: filter 300ms; 13 | } 14 | .logo:hover { 15 | filter: drop-shadow(0 0 2em #646cffaa); 16 | } 17 | .logo.react:hover { 18 | filter: drop-shadow(0 0 2em #61dafbaa); 19 | } 20 | 21 | @keyframes logo-spin { 22 | from { 23 | transform: rotate(0deg); 24 | } 25 | to { 26 | transform: rotate(360deg); 27 | } 28 | } 29 | 30 | @media (prefers-reduced-motion: no-preference) { 31 | a:nth-of-type(2) .logo { 32 | animation: logo-spin infinite 20s linear; 33 | } 34 | } 35 | 36 | .card { 37 | padding: 2em; 38 | } 39 | 40 | .read-the-docs { 41 | color: #888; 42 | } 43 | -------------------------------------------------------------------------------- /prueba-axios/src/App.jsx: -------------------------------------------------------------------------------- 1 | import { useState, useEffect, use } from 'react' 2 | import reactLogo from './assets/react.svg' 3 | import viteLogo from '/vite.svg' 4 | import './App.css' 5 | import axios from 'axios' 6 | 7 | 8 | function App() { 9 | const [lista, setLista] = useState([]) 10 | const [title, setTitle] = useState("") 11 | const [body, setBody] = useState("") 12 | const [publicacion, setPublicacion] = useState([]) 13 | const [id, setId] = useState(0) 14 | const [comentarios, setComentarios] = useState([]) 15 | 16 | const obtenerUsuarios = async () => { 17 | try { 18 | const usuarios = await axios.get("https://jsonplaceholder.typicode.com/users") 19 | setLista(usuarios.data) 20 | } catch (error) { 21 | console.log(error.message) 22 | } 23 | } 24 | 25 | const obtenerPublicacion = async () => { 26 | try { 27 | const getPublicacion = await axios.get("https://jsonplaceholder.typicode.com/posts") 28 | setPublicacion(getPublicacion.data) 29 | } catch (error) { 30 | console.log(error.message) 31 | } 32 | } 33 | 34 | const actualizarPublicacion = async () => { 35 | try { 36 | const publicacionActualizada = await axios.put("https://jsonplaceholder.typicode.com/posts/1", 37 | { 38 | title: title 39 | } 40 | ) 41 | console.log("Titulo actualziado correctamente") 42 | } catch (error) { 43 | console.log(error.message) 44 | } 45 | 46 | } 47 | 48 | const crearPublicacion = async () => { 49 | try { 50 | const publicacionCreada = await axios.post("https://jsonplaceholder.typicode.com/posts", 51 | { 52 | title: title, 53 | body: body, 54 | id: id 55 | } 56 | ) 57 | 58 | console.log("Se creo correctamente") 59 | } catch (error) { 60 | console.log(error.message) 61 | } 62 | } 63 | 64 | const eliminarPublicacion = async () => { 65 | try { 66 | const eliminada = await axios.delete("https://jsonplaceholder.typicode.com/posts/1") 67 | alert("Publicacion eliminadad correctamente") 68 | setPublicacion(prev => prev.filter((p) => p.id !== 1)); 69 | } catch (error) { 70 | console.log(error.message) 71 | } 72 | } 73 | 74 | const obtenerComentarios = async () => { 75 | try { 76 | const comentarios = await axios.get("https://jsonplaceholder.typicode.com/posts/1/comments") 77 | alert("Comentario obtenido") 78 | setComentarios(comentarios.data) 79 | } catch (error) { 80 | console.log(error.message) 81 | } 82 | } 83 | 84 | useEffect(() => { 85 | obtenerUsuarios(); 86 | obtenerPublicacion(); 87 | obtenerComentarios(); 88 | }, []) 89 | return ( 90 |
91 | {/* Formulario de la publicacion */} 92 |
93 |
{ e.preventDefault(); crearPublicacion(); }} action=""> 94 | 95 | setTitle(e.target.value)} /> 96 | 97 | setBody(e.target.value)} /> 98 | 99 | setId(Number(e.target.value))} /> 100 | 101 |
102 |
103 | {/*Seccion de usuarios*/} 104 |
105 | 115 |
116 | {/* Seccion de publicaciones */} 117 |
118 |

Publicaciones

119 | 128 |
129 | 130 | 131 | 132 | {/* Formulario que actualiza el post*/} 133 |
{ e.preventDefault(); actualizarPublicacion() }}> 134 | 135 | setTitle(e.target.value)} /> 136 | 137 |
138 | 139 | {/* Seccion de comentarios */} 140 |
141 |

Comentarios

142 | 151 | 152 |
153 |
154 | 155 | ) 156 | } 157 | 158 | export default App 159 | -------------------------------------------------------------------------------- /prueba-axios/src/assets/react.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /prueba-axios/src/index.css: -------------------------------------------------------------------------------- 1 | @import "tailwindcss"; 2 | -------------------------------------------------------------------------------- /prueba-axios/src/main.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import App from './App.jsx' 4 | import './index.css' 5 | 6 | 7 | ReactDOM.createRoot(document.getElementById('root')).render( 8 | 9 | 10 | , 11 | ) 12 | -------------------------------------------------------------------------------- /prueba-axios/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | import tailwindcss from "@tailwindcss/vite"; 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig({ 7 | plugins: [react(), tailwindcss()], 8 | }) 9 | -------------------------------------------------------------------------------- /prueba-final/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /prueba-final/Guia_Consumo_API_Productos.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohanBoDev/mini-pruebas-fullstack/ecbbae8fe61f7dd6d52f1fb23641461beaf3385e/prueba-final/Guia_Consumo_API_Productos.pdf -------------------------------------------------------------------------------- /prueba-final/README.md: -------------------------------------------------------------------------------- 1 | // 🔍 Obtener todos los productos 2 | http://localhost:3000/api/productos 3 | 4 | // 🔍 Obtener un producto por ID 5 | http://localhost:3000/api/productos/:id 6 | 7 | // 📝 Crear un nuevo producto 8 | http://localhost:3000/api/productos 9 | 10 | // ✏️ Actualizar un producto por ID 11 | http://localhost:3000/api/productos/:id 12 | 13 | // ❌ Eliminar un producto por ID 14 | http://localhost:3000/api/productos/:id 15 | -------------------------------------------------------------------------------- /prueba-final/eslint.config.js: -------------------------------------------------------------------------------- 1 | import js from '@eslint/js' 2 | import globals from 'globals' 3 | import reactHooks from 'eslint-plugin-react-hooks' 4 | import reactRefresh from 'eslint-plugin-react-refresh' 5 | 6 | export default [ 7 | { ignores: ['dist'] }, 8 | { 9 | files: ['**/*.{js,jsx}'], 10 | languageOptions: { 11 | ecmaVersion: 2020, 12 | globals: globals.browser, 13 | parserOptions: { 14 | ecmaVersion: 'latest', 15 | ecmaFeatures: { jsx: true }, 16 | sourceType: 'module', 17 | }, 18 | }, 19 | plugins: { 20 | 'react-hooks': reactHooks, 21 | 'react-refresh': reactRefresh, 22 | }, 23 | rules: { 24 | ...js.configs.recommended.rules, 25 | ...reactHooks.configs.recommended.rules, 26 | 'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }], 27 | 'react-refresh/only-export-components': [ 28 | 'warn', 29 | { allowConstantExport: true }, 30 | ], 31 | }, 32 | }, 33 | ] 34 | -------------------------------------------------------------------------------- /prueba-final/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /prueba-final/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "plantilla-react-base", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "lint": "eslint .", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "@chakra-ui/react": "^2.10.7", 14 | "@emotion/react": "^11.14.0", 15 | "@emotion/styled": "^11.14.0", 16 | "@tailwindcss/postcss": "^4.1.4", 17 | "axios": "^1.9.0", 18 | "framer-motion": "^12.7.4", 19 | "react": "^19.0.0", 20 | "react-dom": "^19.0.0", 21 | "react-hook-form": "^7.56.1", 22 | "react-icons": "^5.5.0", 23 | "zustand": "^5.0.3" 24 | }, 25 | "devDependencies": { 26 | "@eslint/js": "^9.22.0", 27 | "@tailwindcss/vite": "^4.1.4", 28 | "@types/react": "^19.0.10", 29 | "@types/react-dom": "^19.0.4", 30 | "@vitejs/plugin-react": "^4.3.4", 31 | "autoprefixer": "^10.4.21", 32 | "eslint": "^9.22.0", 33 | "eslint-plugin-react-hooks": "^5.2.0", 34 | "eslint-plugin-react-refresh": "^0.4.19", 35 | "globals": "^16.0.0", 36 | "postcss": "^8.5.3", 37 | "tailwindcss": "^4.1.4", 38 | "vite": "^6.3.1" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /prueba-final/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /prueba-final/src/App.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohanBoDev/mini-pruebas-fullstack/ecbbae8fe61f7dd6d52f1fb23641461beaf3385e/prueba-final/src/App.css -------------------------------------------------------------------------------- /prueba-final/src/App.jsx: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from 'react' 2 | import axios from 'axios' 3 | import { 4 | Box, 5 | Heading, 6 | Text, 7 | Input, 8 | Button, 9 | Stack, 10 | SimpleGrid, 11 | Card, 12 | CardBody, 13 | CardHeader, 14 | useToast, 15 | Container 16 | } from '@chakra-ui/react' 17 | 18 | function App() { 19 | const [productos, setProductos] = useState([]) 20 | const [producto, setProducto] = useState(null) 21 | const [nombre, setNombre] = useState("") 22 | const [precio, setPrecio] = useState(0) 23 | const [categoria, setCategoria] = useState("") 24 | const [id, setId] = useState("") 25 | const toast = useToast() 26 | 27 | const crearProducto = async () => { 28 | if (!nombre || !precio || !categoria) { 29 | toast({ 30 | title: "Campos incompletos.", 31 | status: "warning", 32 | isClosable: true, 33 | }) 34 | return; 35 | } 36 | 37 | try { 38 | const res = await axios.post("http://localhost:3000/api/productos", { 39 | nombre, 40 | precio, 41 | categoria 42 | }) 43 | 44 | toast({ 45 | title: "Producto creado.", 46 | description: `Se agregó ${res.data.nombre}`, 47 | status: "success", 48 | isClosable: true, 49 | }) 50 | 51 | setNombre("") 52 | setPrecio(0) 53 | setCategoria("") 54 | obtenerProductos() 55 | } catch (error) { 56 | toast({ 57 | title: "Error al crear producto.", 58 | description: error.message, 59 | status: "error", 60 | isClosable: true, 61 | }) 62 | } 63 | } 64 | 65 | const eliminarProducto = async (id) => { 66 | try { 67 | await axios.delete(`http://localhost:3000/api/productos/${id}`) 68 | obtenerProductos() 69 | toast({ 70 | title: "Producto eliminado.", 71 | status: "info", 72 | isClosable: true, 73 | }) 74 | } catch (error) { 75 | toast({ 76 | title: "Error al eliminar producto.", 77 | description: error.message, 78 | status: "error", 79 | isClosable: true, 80 | }) 81 | } 82 | } 83 | 84 | const obtenerProductos = async () => { 85 | try { 86 | const res = await axios.get("http://localhost:3000/api/productos/") 87 | setProductos(res.data) 88 | } catch (error) { 89 | console.log(error.message) 90 | } 91 | } 92 | 93 | const obtenerProductoPorId = async (id) => { 94 | try { 95 | const res = await axios.get(`http://localhost:3000/api/productos/${id}`) 96 | setProducto(res.data) 97 | } catch (error) { 98 | setProducto(null) 99 | } 100 | } 101 | 102 | useEffect(() => { 103 | obtenerProductos() 104 | }, []) 105 | 106 | return ( 107 | 108 | 109 | 110 | Todos los productos disponibles 111 | 112 | 113 | {productos.length > 0 ? ( 114 | 115 | {productos.map((producto) => ( 116 | 117 | 118 | {producto.nombre} 119 | 120 | 121 | Precio: ${producto.precio} 122 | Categoría: {producto.categoria} 123 | 132 | 133 | 134 | ))} 135 | 136 | ) : ( 137 | No tienes productos todavía 138 | )} 139 | 140 | 141 | 142 | Crear producto 143 | 144 | setNombre(e.target.value)} /> 145 | setPrecio(Number(e.target.value))} /> 146 | setCategoria(e.target.value)} /> 147 | 148 | 149 | 150 | 151 | 152 | Buscar por ID 153 |
{ e.preventDefault(); obtenerProductoPorId(id); }}> 154 | 155 | setId(e.target.value)} /> 156 | 157 | 158 |
159 |
160 | 161 | 162 | {producto ? ( 163 | 164 | Producto encontrado 165 | Nombre: {producto.nombre} 166 | Precio: ${producto.precio} 167 | 168 | ) : ( 169 | 170 | Producto no encontrado 171 | 172 | )} 173 | 174 |
175 |
176 |
177 | ) 178 | } 179 | 180 | export default App 181 | -------------------------------------------------------------------------------- /prueba-final/src/assets/react.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /prueba-final/src/index.css: -------------------------------------------------------------------------------- 1 | @import "tailwindcss"; 2 | -------------------------------------------------------------------------------- /prueba-final/src/main.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import App from './App.jsx' 4 | import './index.css' 5 | import { ChakraProvider } from '@chakra-ui/react' 6 | 7 | 8 | ReactDOM.createRoot(document.getElementById('root')).render( 9 | 10 | 11 | 12 | 13 | 14 | , 15 | ) 16 | -------------------------------------------------------------------------------- /prueba-final/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | import tailwindcss from "@tailwindcss/vite"; 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig({ 7 | plugins: [react(), tailwindcss()], 8 | }) 9 | -------------------------------------------------------------------------------- /prueba1-formulario-registro/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /prueba1-formulario-registro/README.md: -------------------------------------------------------------------------------- 1 | # 🧪 Prueba 1 – Formulario de Registro con Validación (React + Tailwind) 2 | 3 | ## 📋 Descripción 4 | 5 | Esta prueba consiste en desarrollar un formulario de registro utilizando **React** y **Tailwind CSS**, aplicando validaciones para garantizar la calidad de los datos ingresados por el usuario. 6 | 7 | --- 8 | 9 | ## ✅ Requisitos funcionales 10 | 11 | - Crear un formulario con los siguientes campos: 12 | - **Nombre** 13 | - **Correo electrónico** 14 | - **Contraseña** 15 | 16 | - Aplicar validaciones: 17 | - El **correo electrónico** debe tener un formato válido. 18 | - La **contraseña** debe tener **mínimo 6 caracteres**. 19 | - Todos los campos deben ser obligatorios. 20 | 21 | - Mostrar mensajes de error claros si las validaciones fallan. 22 | 23 | --- 24 | 25 | ## 🎨 Requisitos de estilo 26 | 27 | - Utilizar **Tailwind CSS v4** para todo el diseño del formulario. 28 | - El formulario debe ser **responsive** y tener un diseño limpio. 29 | - Puede usarse **Chakra UI** opcionalmente para algunos componentes visuales (botones, inputs, etc.). 30 | 31 | --- 32 | 33 | ## 💡 Tecnologías permitidas 34 | 35 | - React + Vite 36 | - Tailwind CSS v4 37 | - Chakra UI (opcional) 38 | - Zustand (opcional si se quiere persistir el estado del usuario registrado) 39 | 40 | --- 41 | 42 | ## 🚀 Objetivo 43 | 44 | Crear un formulario funcional y visualmente agradable que valide correctamente los datos de entrada y pueda ser base para una futura autenticación o registro de usuarios. 45 | 46 | --- 47 | 48 | 49 | ## 📝 Notas 50 | 51 | - No es necesario conectarse a un backend en esta prueba. 52 | - El foco está en la validación, estructura y presentación del formulario. 53 | -------------------------------------------------------------------------------- /prueba1-formulario-registro/eslint.config.js: -------------------------------------------------------------------------------- 1 | import js from '@eslint/js' 2 | import globals from 'globals' 3 | import reactHooks from 'eslint-plugin-react-hooks' 4 | import reactRefresh from 'eslint-plugin-react-refresh' 5 | 6 | export default [ 7 | { ignores: ['dist'] }, 8 | { 9 | files: ['**/*.{js,jsx}'], 10 | languageOptions: { 11 | ecmaVersion: 2020, 12 | globals: globals.browser, 13 | parserOptions: { 14 | ecmaVersion: 'latest', 15 | ecmaFeatures: { jsx: true }, 16 | sourceType: 'module', 17 | }, 18 | }, 19 | plugins: { 20 | 'react-hooks': reactHooks, 21 | 'react-refresh': reactRefresh, 22 | }, 23 | rules: { 24 | ...js.configs.recommended.rules, 25 | ...reactHooks.configs.recommended.rules, 26 | 'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }], 27 | 'react-refresh/only-export-components': [ 28 | 'warn', 29 | { allowConstantExport: true }, 30 | ], 31 | }, 32 | }, 33 | ] 34 | -------------------------------------------------------------------------------- /prueba1-formulario-registro/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /prueba1-formulario-registro/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "plantilla-react-base", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "lint": "eslint .", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "@chakra-ui/react": "^2.10.7", 14 | "@emotion/react": "^11.14.0", 15 | "@emotion/styled": "^11.14.0", 16 | "@tailwindcss/postcss": "^4.1.4", 17 | "framer-motion": "^12.7.4", 18 | "react": "^19.0.0", 19 | "react-dom": "^19.0.0", 20 | "react-hook-form": "^7.56.1", 21 | "react-icons": "^5.5.0", 22 | "zustand": "^5.0.3" 23 | }, 24 | "devDependencies": { 25 | "@eslint/js": "^9.22.0", 26 | "@tailwindcss/vite": "^4.1.4", 27 | "@types/react": "^19.0.10", 28 | "@types/react-dom": "^19.0.4", 29 | "@vitejs/plugin-react": "^4.3.4", 30 | "autoprefixer": "^10.4.21", 31 | "eslint": "^9.22.0", 32 | "eslint-plugin-react-hooks": "^5.2.0", 33 | "eslint-plugin-react-refresh": "^0.4.19", 34 | "globals": "^16.0.0", 35 | "postcss": "^8.5.3", 36 | "tailwindcss": "^4.1.4", 37 | "vite": "^6.3.1" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /prueba1-formulario-registro/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /prueba1-formulario-registro/src/App.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohanBoDev/mini-pruebas-fullstack/ecbbae8fe61f7dd6d52f1fb23641461beaf3385e/prueba1-formulario-registro/src/App.css -------------------------------------------------------------------------------- /prueba1-formulario-registro/src/App.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | 3 | function App() { 4 | const [usuarios, setUsuarios] = useState([]); 5 | 6 | useEffect(() => { 7 | fetch("https://jsonplaceholder.typicode.com/users") // Llama a la API al montar 8 | .then((res) => res.json()) // Convierte a JSON 9 | .then((data) => setUsuarios(data)); // Guarda los datos en el estado 10 | }, []); // Solo se ejecuta una vez (como al iniciar) 11 | 12 | return ( 13 | 18 | ); 19 | } 20 | export default App -------------------------------------------------------------------------------- /prueba1-formulario-registro/src/assets/react.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /prueba1-formulario-registro/src/index.css: -------------------------------------------------------------------------------- 1 | @import "tailwindcss"; 2 | 3 | -------------------------------------------------------------------------------- /prueba1-formulario-registro/src/main.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import App from './App.jsx' 4 | import './index.css' 5 | 6 | ReactDOM.createRoot(document.getElementById('root')).render( 7 | 8 | 9 | , 10 | ) 11 | -------------------------------------------------------------------------------- /prueba1-formulario-registro/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | import tailwindcss from "@tailwindcss/vite"; 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig({ 7 | plugins: [react(), tailwindcss()], 8 | }) 9 | -------------------------------------------------------------------------------- /prueba2-api-productos/README.md: -------------------------------------------------------------------------------- 1 | # 🧪 Prueba 2 – API REST de Productos (Node.js + Express) 2 | 3 | ## 📋 Descripción 4 | 5 | Esta prueba consiste en desarrollar una **API REST utilizando Node.js y Express** que permita gestionar productos a través de operaciones CRUD (Crear, Leer, Actualizar, Eliminar). No es necesario usar una base de datos; los datos pueden mantenerse en un array en memoria. 6 | 7 | --- 8 | 9 | ## ✅ Requisitos funcionales 10 | 11 | - Crear una API con las siguientes rutas: 12 | - `GET /api/productos` → Obtener todos los productos 13 | - `GET /api/productos/:id` → Obtener un producto por ID 14 | - `POST /api/productos` → Crear un nuevo producto 15 | - `PUT /api/productos/:id` → Actualizar un producto existente 16 | - `DELETE /api/productos/:id` → Eliminar un producto 17 | 18 | - Cada producto debe tener: 19 | - `id`: número o string único 20 | - `nombre`: string 21 | - `precio`: número 22 | - `categoría`: string (opcional) 23 | 24 | --- 25 | 26 | ## 💡 Consideraciones técnicas 27 | 28 | - Los productos deben almacenarse en un array en memoria. 29 | - Validar que el cuerpo de los `POST` y `PUT` incluya `nombre` y `precio`. 30 | - Se puede usar `uuid` para generar IDs si se desea. 31 | - El servidor debe correr en el puerto `3000`. 32 | 33 | --- 34 | 35 | ## 🧱 Tecnologías usadas 36 | 37 | - 🟢 Node.js 38 | - ⚙️ Express.js 39 | - 🔄 Cors 40 | - 📦 dotenv 41 | - (Opcional: `uuid` para generar IDs únicos) 42 | 43 | --- 44 | 45 | ## 🚀 Instalación y ejecución 46 | 47 | ```bash 48 | npm install 49 | npm run dev 50 | -------------------------------------------------------------------------------- /prueba2-api-productos/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "plantilla-node-express", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "plantilla-node-express", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "cors": "^2.8.5", 13 | "dotenv": "^16.5.0", 14 | "express": "^5.1.0", 15 | "nodemon": "^3.1.9" 16 | } 17 | }, 18 | "node_modules/accepts": { 19 | "version": "2.0.0", 20 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", 21 | "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", 22 | "dependencies": { 23 | "mime-types": "^3.0.0", 24 | "negotiator": "^1.0.0" 25 | }, 26 | "engines": { 27 | "node": ">= 0.6" 28 | } 29 | }, 30 | "node_modules/anymatch": { 31 | "version": "3.1.3", 32 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", 33 | "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", 34 | "dependencies": { 35 | "normalize-path": "^3.0.0", 36 | "picomatch": "^2.0.4" 37 | }, 38 | "engines": { 39 | "node": ">= 8" 40 | } 41 | }, 42 | "node_modules/balanced-match": { 43 | "version": "1.0.2", 44 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 45 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 46 | }, 47 | "node_modules/binary-extensions": { 48 | "version": "2.3.0", 49 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", 50 | "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", 51 | "engines": { 52 | "node": ">=8" 53 | }, 54 | "funding": { 55 | "url": "https://github.com/sponsors/sindresorhus" 56 | } 57 | }, 58 | "node_modules/body-parser": { 59 | "version": "2.2.0", 60 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", 61 | "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", 62 | "dependencies": { 63 | "bytes": "^3.1.2", 64 | "content-type": "^1.0.5", 65 | "debug": "^4.4.0", 66 | "http-errors": "^2.0.0", 67 | "iconv-lite": "^0.6.3", 68 | "on-finished": "^2.4.1", 69 | "qs": "^6.14.0", 70 | "raw-body": "^3.0.0", 71 | "type-is": "^2.0.0" 72 | }, 73 | "engines": { 74 | "node": ">=18" 75 | } 76 | }, 77 | "node_modules/brace-expansion": { 78 | "version": "1.1.11", 79 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 80 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 81 | "dependencies": { 82 | "balanced-match": "^1.0.0", 83 | "concat-map": "0.0.1" 84 | } 85 | }, 86 | "node_modules/braces": { 87 | "version": "3.0.3", 88 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", 89 | "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", 90 | "dependencies": { 91 | "fill-range": "^7.1.1" 92 | }, 93 | "engines": { 94 | "node": ">=8" 95 | } 96 | }, 97 | "node_modules/bytes": { 98 | "version": "3.1.2", 99 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 100 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 101 | "engines": { 102 | "node": ">= 0.8" 103 | } 104 | }, 105 | "node_modules/call-bind-apply-helpers": { 106 | "version": "1.0.2", 107 | "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", 108 | "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", 109 | "dependencies": { 110 | "es-errors": "^1.3.0", 111 | "function-bind": "^1.1.2" 112 | }, 113 | "engines": { 114 | "node": ">= 0.4" 115 | } 116 | }, 117 | "node_modules/call-bound": { 118 | "version": "1.0.4", 119 | "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", 120 | "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", 121 | "dependencies": { 122 | "call-bind-apply-helpers": "^1.0.2", 123 | "get-intrinsic": "^1.3.0" 124 | }, 125 | "engines": { 126 | "node": ">= 0.4" 127 | }, 128 | "funding": { 129 | "url": "https://github.com/sponsors/ljharb" 130 | } 131 | }, 132 | "node_modules/chokidar": { 133 | "version": "3.6.0", 134 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", 135 | "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", 136 | "dependencies": { 137 | "anymatch": "~3.1.2", 138 | "braces": "~3.0.2", 139 | "glob-parent": "~5.1.2", 140 | "is-binary-path": "~2.1.0", 141 | "is-glob": "~4.0.1", 142 | "normalize-path": "~3.0.0", 143 | "readdirp": "~3.6.0" 144 | }, 145 | "engines": { 146 | "node": ">= 8.10.0" 147 | }, 148 | "funding": { 149 | "url": "https://paulmillr.com/funding/" 150 | }, 151 | "optionalDependencies": { 152 | "fsevents": "~2.3.2" 153 | } 154 | }, 155 | "node_modules/concat-map": { 156 | "version": "0.0.1", 157 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 158 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" 159 | }, 160 | "node_modules/content-disposition": { 161 | "version": "1.0.0", 162 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", 163 | "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", 164 | "dependencies": { 165 | "safe-buffer": "5.2.1" 166 | }, 167 | "engines": { 168 | "node": ">= 0.6" 169 | } 170 | }, 171 | "node_modules/content-type": { 172 | "version": "1.0.5", 173 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 174 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 175 | "engines": { 176 | "node": ">= 0.6" 177 | } 178 | }, 179 | "node_modules/cookie": { 180 | "version": "0.7.2", 181 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", 182 | "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", 183 | "engines": { 184 | "node": ">= 0.6" 185 | } 186 | }, 187 | "node_modules/cookie-signature": { 188 | "version": "1.2.2", 189 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", 190 | "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", 191 | "engines": { 192 | "node": ">=6.6.0" 193 | } 194 | }, 195 | "node_modules/cors": { 196 | "version": "2.8.5", 197 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 198 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 199 | "dependencies": { 200 | "object-assign": "^4", 201 | "vary": "^1" 202 | }, 203 | "engines": { 204 | "node": ">= 0.10" 205 | } 206 | }, 207 | "node_modules/debug": { 208 | "version": "4.4.0", 209 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", 210 | "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", 211 | "dependencies": { 212 | "ms": "^2.1.3" 213 | }, 214 | "engines": { 215 | "node": ">=6.0" 216 | }, 217 | "peerDependenciesMeta": { 218 | "supports-color": { 219 | "optional": true 220 | } 221 | } 222 | }, 223 | "node_modules/depd": { 224 | "version": "2.0.0", 225 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 226 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 227 | "engines": { 228 | "node": ">= 0.8" 229 | } 230 | }, 231 | "node_modules/dotenv": { 232 | "version": "16.5.0", 233 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz", 234 | "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==", 235 | "engines": { 236 | "node": ">=12" 237 | }, 238 | "funding": { 239 | "url": "https://dotenvx.com" 240 | } 241 | }, 242 | "node_modules/dunder-proto": { 243 | "version": "1.0.1", 244 | "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", 245 | "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", 246 | "dependencies": { 247 | "call-bind-apply-helpers": "^1.0.1", 248 | "es-errors": "^1.3.0", 249 | "gopd": "^1.2.0" 250 | }, 251 | "engines": { 252 | "node": ">= 0.4" 253 | } 254 | }, 255 | "node_modules/ee-first": { 256 | "version": "1.1.1", 257 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 258 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 259 | }, 260 | "node_modules/encodeurl": { 261 | "version": "2.0.0", 262 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", 263 | "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", 264 | "engines": { 265 | "node": ">= 0.8" 266 | } 267 | }, 268 | "node_modules/es-define-property": { 269 | "version": "1.0.1", 270 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", 271 | "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", 272 | "engines": { 273 | "node": ">= 0.4" 274 | } 275 | }, 276 | "node_modules/es-errors": { 277 | "version": "1.3.0", 278 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 279 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 280 | "engines": { 281 | "node": ">= 0.4" 282 | } 283 | }, 284 | "node_modules/es-object-atoms": { 285 | "version": "1.1.1", 286 | "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", 287 | "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", 288 | "dependencies": { 289 | "es-errors": "^1.3.0" 290 | }, 291 | "engines": { 292 | "node": ">= 0.4" 293 | } 294 | }, 295 | "node_modules/escape-html": { 296 | "version": "1.0.3", 297 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 298 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 299 | }, 300 | "node_modules/etag": { 301 | "version": "1.8.1", 302 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 303 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 304 | "engines": { 305 | "node": ">= 0.6" 306 | } 307 | }, 308 | "node_modules/express": { 309 | "version": "5.1.0", 310 | "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", 311 | "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", 312 | "dependencies": { 313 | "accepts": "^2.0.0", 314 | "body-parser": "^2.2.0", 315 | "content-disposition": "^1.0.0", 316 | "content-type": "^1.0.5", 317 | "cookie": "^0.7.1", 318 | "cookie-signature": "^1.2.1", 319 | "debug": "^4.4.0", 320 | "encodeurl": "^2.0.0", 321 | "escape-html": "^1.0.3", 322 | "etag": "^1.8.1", 323 | "finalhandler": "^2.1.0", 324 | "fresh": "^2.0.0", 325 | "http-errors": "^2.0.0", 326 | "merge-descriptors": "^2.0.0", 327 | "mime-types": "^3.0.0", 328 | "on-finished": "^2.4.1", 329 | "once": "^1.4.0", 330 | "parseurl": "^1.3.3", 331 | "proxy-addr": "^2.0.7", 332 | "qs": "^6.14.0", 333 | "range-parser": "^1.2.1", 334 | "router": "^2.2.0", 335 | "send": "^1.1.0", 336 | "serve-static": "^2.2.0", 337 | "statuses": "^2.0.1", 338 | "type-is": "^2.0.1", 339 | "vary": "^1.1.2" 340 | }, 341 | "engines": { 342 | "node": ">= 18" 343 | }, 344 | "funding": { 345 | "type": "opencollective", 346 | "url": "https://opencollective.com/express" 347 | } 348 | }, 349 | "node_modules/fill-range": { 350 | "version": "7.1.1", 351 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", 352 | "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", 353 | "dependencies": { 354 | "to-regex-range": "^5.0.1" 355 | }, 356 | "engines": { 357 | "node": ">=8" 358 | } 359 | }, 360 | "node_modules/finalhandler": { 361 | "version": "2.1.0", 362 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", 363 | "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", 364 | "dependencies": { 365 | "debug": "^4.4.0", 366 | "encodeurl": "^2.0.0", 367 | "escape-html": "^1.0.3", 368 | "on-finished": "^2.4.1", 369 | "parseurl": "^1.3.3", 370 | "statuses": "^2.0.1" 371 | }, 372 | "engines": { 373 | "node": ">= 0.8" 374 | } 375 | }, 376 | "node_modules/forwarded": { 377 | "version": "0.2.0", 378 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 379 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 380 | "engines": { 381 | "node": ">= 0.6" 382 | } 383 | }, 384 | "node_modules/fresh": { 385 | "version": "2.0.0", 386 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", 387 | "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", 388 | "engines": { 389 | "node": ">= 0.8" 390 | } 391 | }, 392 | "node_modules/fsevents": { 393 | "version": "2.3.3", 394 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 395 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 396 | "hasInstallScript": true, 397 | "optional": true, 398 | "os": [ 399 | "darwin" 400 | ], 401 | "engines": { 402 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 403 | } 404 | }, 405 | "node_modules/function-bind": { 406 | "version": "1.1.2", 407 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 408 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 409 | "funding": { 410 | "url": "https://github.com/sponsors/ljharb" 411 | } 412 | }, 413 | "node_modules/get-intrinsic": { 414 | "version": "1.3.0", 415 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", 416 | "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", 417 | "dependencies": { 418 | "call-bind-apply-helpers": "^1.0.2", 419 | "es-define-property": "^1.0.1", 420 | "es-errors": "^1.3.0", 421 | "es-object-atoms": "^1.1.1", 422 | "function-bind": "^1.1.2", 423 | "get-proto": "^1.0.1", 424 | "gopd": "^1.2.0", 425 | "has-symbols": "^1.1.0", 426 | "hasown": "^2.0.2", 427 | "math-intrinsics": "^1.1.0" 428 | }, 429 | "engines": { 430 | "node": ">= 0.4" 431 | }, 432 | "funding": { 433 | "url": "https://github.com/sponsors/ljharb" 434 | } 435 | }, 436 | "node_modules/get-proto": { 437 | "version": "1.0.1", 438 | "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", 439 | "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", 440 | "dependencies": { 441 | "dunder-proto": "^1.0.1", 442 | "es-object-atoms": "^1.0.0" 443 | }, 444 | "engines": { 445 | "node": ">= 0.4" 446 | } 447 | }, 448 | "node_modules/glob-parent": { 449 | "version": "5.1.2", 450 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 451 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 452 | "dependencies": { 453 | "is-glob": "^4.0.1" 454 | }, 455 | "engines": { 456 | "node": ">= 6" 457 | } 458 | }, 459 | "node_modules/gopd": { 460 | "version": "1.2.0", 461 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", 462 | "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", 463 | "engines": { 464 | "node": ">= 0.4" 465 | }, 466 | "funding": { 467 | "url": "https://github.com/sponsors/ljharb" 468 | } 469 | }, 470 | "node_modules/has-flag": { 471 | "version": "3.0.0", 472 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 473 | "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", 474 | "engines": { 475 | "node": ">=4" 476 | } 477 | }, 478 | "node_modules/has-symbols": { 479 | "version": "1.1.0", 480 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", 481 | "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", 482 | "engines": { 483 | "node": ">= 0.4" 484 | }, 485 | "funding": { 486 | "url": "https://github.com/sponsors/ljharb" 487 | } 488 | }, 489 | "node_modules/hasown": { 490 | "version": "2.0.2", 491 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 492 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 493 | "dependencies": { 494 | "function-bind": "^1.1.2" 495 | }, 496 | "engines": { 497 | "node": ">= 0.4" 498 | } 499 | }, 500 | "node_modules/http-errors": { 501 | "version": "2.0.0", 502 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 503 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 504 | "dependencies": { 505 | "depd": "2.0.0", 506 | "inherits": "2.0.4", 507 | "setprototypeof": "1.2.0", 508 | "statuses": "2.0.1", 509 | "toidentifier": "1.0.1" 510 | }, 511 | "engines": { 512 | "node": ">= 0.8" 513 | } 514 | }, 515 | "node_modules/iconv-lite": { 516 | "version": "0.6.3", 517 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", 518 | "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", 519 | "dependencies": { 520 | "safer-buffer": ">= 2.1.2 < 3.0.0" 521 | }, 522 | "engines": { 523 | "node": ">=0.10.0" 524 | } 525 | }, 526 | "node_modules/ignore-by-default": { 527 | "version": "1.0.1", 528 | "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", 529 | "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" 530 | }, 531 | "node_modules/inherits": { 532 | "version": "2.0.4", 533 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 534 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 535 | }, 536 | "node_modules/ipaddr.js": { 537 | "version": "1.9.1", 538 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 539 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 540 | "engines": { 541 | "node": ">= 0.10" 542 | } 543 | }, 544 | "node_modules/is-binary-path": { 545 | "version": "2.1.0", 546 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 547 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 548 | "dependencies": { 549 | "binary-extensions": "^2.0.0" 550 | }, 551 | "engines": { 552 | "node": ">=8" 553 | } 554 | }, 555 | "node_modules/is-extglob": { 556 | "version": "2.1.1", 557 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 558 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 559 | "engines": { 560 | "node": ">=0.10.0" 561 | } 562 | }, 563 | "node_modules/is-glob": { 564 | "version": "4.0.3", 565 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 566 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 567 | "dependencies": { 568 | "is-extglob": "^2.1.1" 569 | }, 570 | "engines": { 571 | "node": ">=0.10.0" 572 | } 573 | }, 574 | "node_modules/is-number": { 575 | "version": "7.0.0", 576 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 577 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 578 | "engines": { 579 | "node": ">=0.12.0" 580 | } 581 | }, 582 | "node_modules/is-promise": { 583 | "version": "4.0.0", 584 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", 585 | "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==" 586 | }, 587 | "node_modules/math-intrinsics": { 588 | "version": "1.1.0", 589 | "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", 590 | "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", 591 | "engines": { 592 | "node": ">= 0.4" 593 | } 594 | }, 595 | "node_modules/media-typer": { 596 | "version": "1.1.0", 597 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", 598 | "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", 599 | "engines": { 600 | "node": ">= 0.8" 601 | } 602 | }, 603 | "node_modules/merge-descriptors": { 604 | "version": "2.0.0", 605 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", 606 | "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", 607 | "engines": { 608 | "node": ">=18" 609 | }, 610 | "funding": { 611 | "url": "https://github.com/sponsors/sindresorhus" 612 | } 613 | }, 614 | "node_modules/mime-db": { 615 | "version": "1.54.0", 616 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", 617 | "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", 618 | "engines": { 619 | "node": ">= 0.6" 620 | } 621 | }, 622 | "node_modules/mime-types": { 623 | "version": "3.0.1", 624 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", 625 | "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", 626 | "dependencies": { 627 | "mime-db": "^1.54.0" 628 | }, 629 | "engines": { 630 | "node": ">= 0.6" 631 | } 632 | }, 633 | "node_modules/minimatch": { 634 | "version": "3.1.2", 635 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 636 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 637 | "dependencies": { 638 | "brace-expansion": "^1.1.7" 639 | }, 640 | "engines": { 641 | "node": "*" 642 | } 643 | }, 644 | "node_modules/ms": { 645 | "version": "2.1.3", 646 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 647 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 648 | }, 649 | "node_modules/negotiator": { 650 | "version": "1.0.0", 651 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", 652 | "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", 653 | "engines": { 654 | "node": ">= 0.6" 655 | } 656 | }, 657 | "node_modules/nodemon": { 658 | "version": "3.1.9", 659 | "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.9.tgz", 660 | "integrity": "sha512-hdr1oIb2p6ZSxu3PB2JWWYS7ZQ0qvaZsc3hK8DR8f02kRzc8rjYmxAIvdz+aYC+8F2IjNaB7HMcSDg8nQpJxyg==", 661 | "dependencies": { 662 | "chokidar": "^3.5.2", 663 | "debug": "^4", 664 | "ignore-by-default": "^1.0.1", 665 | "minimatch": "^3.1.2", 666 | "pstree.remy": "^1.1.8", 667 | "semver": "^7.5.3", 668 | "simple-update-notifier": "^2.0.0", 669 | "supports-color": "^5.5.0", 670 | "touch": "^3.1.0", 671 | "undefsafe": "^2.0.5" 672 | }, 673 | "bin": { 674 | "nodemon": "bin/nodemon.js" 675 | }, 676 | "engines": { 677 | "node": ">=10" 678 | }, 679 | "funding": { 680 | "type": "opencollective", 681 | "url": "https://opencollective.com/nodemon" 682 | } 683 | }, 684 | "node_modules/normalize-path": { 685 | "version": "3.0.0", 686 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 687 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 688 | "engines": { 689 | "node": ">=0.10.0" 690 | } 691 | }, 692 | "node_modules/object-assign": { 693 | "version": "4.1.1", 694 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 695 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", 696 | "engines": { 697 | "node": ">=0.10.0" 698 | } 699 | }, 700 | "node_modules/object-inspect": { 701 | "version": "1.13.4", 702 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", 703 | "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", 704 | "engines": { 705 | "node": ">= 0.4" 706 | }, 707 | "funding": { 708 | "url": "https://github.com/sponsors/ljharb" 709 | } 710 | }, 711 | "node_modules/on-finished": { 712 | "version": "2.4.1", 713 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 714 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 715 | "dependencies": { 716 | "ee-first": "1.1.1" 717 | }, 718 | "engines": { 719 | "node": ">= 0.8" 720 | } 721 | }, 722 | "node_modules/once": { 723 | "version": "1.4.0", 724 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 725 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 726 | "dependencies": { 727 | "wrappy": "1" 728 | } 729 | }, 730 | "node_modules/parseurl": { 731 | "version": "1.3.3", 732 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 733 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 734 | "engines": { 735 | "node": ">= 0.8" 736 | } 737 | }, 738 | "node_modules/path-to-regexp": { 739 | "version": "8.2.0", 740 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", 741 | "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", 742 | "engines": { 743 | "node": ">=16" 744 | } 745 | }, 746 | "node_modules/picomatch": { 747 | "version": "2.3.1", 748 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 749 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 750 | "engines": { 751 | "node": ">=8.6" 752 | }, 753 | "funding": { 754 | "url": "https://github.com/sponsors/jonschlinkert" 755 | } 756 | }, 757 | "node_modules/proxy-addr": { 758 | "version": "2.0.7", 759 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 760 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 761 | "dependencies": { 762 | "forwarded": "0.2.0", 763 | "ipaddr.js": "1.9.1" 764 | }, 765 | "engines": { 766 | "node": ">= 0.10" 767 | } 768 | }, 769 | "node_modules/pstree.remy": { 770 | "version": "1.1.8", 771 | "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", 772 | "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" 773 | }, 774 | "node_modules/qs": { 775 | "version": "6.14.0", 776 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", 777 | "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", 778 | "dependencies": { 779 | "side-channel": "^1.1.0" 780 | }, 781 | "engines": { 782 | "node": ">=0.6" 783 | }, 784 | "funding": { 785 | "url": "https://github.com/sponsors/ljharb" 786 | } 787 | }, 788 | "node_modules/range-parser": { 789 | "version": "1.2.1", 790 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 791 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 792 | "engines": { 793 | "node": ">= 0.6" 794 | } 795 | }, 796 | "node_modules/raw-body": { 797 | "version": "3.0.0", 798 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", 799 | "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", 800 | "dependencies": { 801 | "bytes": "3.1.2", 802 | "http-errors": "2.0.0", 803 | "iconv-lite": "0.6.3", 804 | "unpipe": "1.0.0" 805 | }, 806 | "engines": { 807 | "node": ">= 0.8" 808 | } 809 | }, 810 | "node_modules/readdirp": { 811 | "version": "3.6.0", 812 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 813 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 814 | "dependencies": { 815 | "picomatch": "^2.2.1" 816 | }, 817 | "engines": { 818 | "node": ">=8.10.0" 819 | } 820 | }, 821 | "node_modules/router": { 822 | "version": "2.2.0", 823 | "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", 824 | "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", 825 | "dependencies": { 826 | "debug": "^4.4.0", 827 | "depd": "^2.0.0", 828 | "is-promise": "^4.0.0", 829 | "parseurl": "^1.3.3", 830 | "path-to-regexp": "^8.0.0" 831 | }, 832 | "engines": { 833 | "node": ">= 18" 834 | } 835 | }, 836 | "node_modules/safe-buffer": { 837 | "version": "5.2.1", 838 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 839 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 840 | "funding": [ 841 | { 842 | "type": "github", 843 | "url": "https://github.com/sponsors/feross" 844 | }, 845 | { 846 | "type": "patreon", 847 | "url": "https://www.patreon.com/feross" 848 | }, 849 | { 850 | "type": "consulting", 851 | "url": "https://feross.org/support" 852 | } 853 | ] 854 | }, 855 | "node_modules/safer-buffer": { 856 | "version": "2.1.2", 857 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 858 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 859 | }, 860 | "node_modules/semver": { 861 | "version": "7.7.1", 862 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", 863 | "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", 864 | "bin": { 865 | "semver": "bin/semver.js" 866 | }, 867 | "engines": { 868 | "node": ">=10" 869 | } 870 | }, 871 | "node_modules/send": { 872 | "version": "1.2.0", 873 | "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", 874 | "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", 875 | "dependencies": { 876 | "debug": "^4.3.5", 877 | "encodeurl": "^2.0.0", 878 | "escape-html": "^1.0.3", 879 | "etag": "^1.8.1", 880 | "fresh": "^2.0.0", 881 | "http-errors": "^2.0.0", 882 | "mime-types": "^3.0.1", 883 | "ms": "^2.1.3", 884 | "on-finished": "^2.4.1", 885 | "range-parser": "^1.2.1", 886 | "statuses": "^2.0.1" 887 | }, 888 | "engines": { 889 | "node": ">= 18" 890 | } 891 | }, 892 | "node_modules/serve-static": { 893 | "version": "2.2.0", 894 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", 895 | "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", 896 | "dependencies": { 897 | "encodeurl": "^2.0.0", 898 | "escape-html": "^1.0.3", 899 | "parseurl": "^1.3.3", 900 | "send": "^1.2.0" 901 | }, 902 | "engines": { 903 | "node": ">= 18" 904 | } 905 | }, 906 | "node_modules/setprototypeof": { 907 | "version": "1.2.0", 908 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 909 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 910 | }, 911 | "node_modules/side-channel": { 912 | "version": "1.1.0", 913 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", 914 | "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", 915 | "dependencies": { 916 | "es-errors": "^1.3.0", 917 | "object-inspect": "^1.13.3", 918 | "side-channel-list": "^1.0.0", 919 | "side-channel-map": "^1.0.1", 920 | "side-channel-weakmap": "^1.0.2" 921 | }, 922 | "engines": { 923 | "node": ">= 0.4" 924 | }, 925 | "funding": { 926 | "url": "https://github.com/sponsors/ljharb" 927 | } 928 | }, 929 | "node_modules/side-channel-list": { 930 | "version": "1.0.0", 931 | "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", 932 | "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", 933 | "dependencies": { 934 | "es-errors": "^1.3.0", 935 | "object-inspect": "^1.13.3" 936 | }, 937 | "engines": { 938 | "node": ">= 0.4" 939 | }, 940 | "funding": { 941 | "url": "https://github.com/sponsors/ljharb" 942 | } 943 | }, 944 | "node_modules/side-channel-map": { 945 | "version": "1.0.1", 946 | "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", 947 | "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", 948 | "dependencies": { 949 | "call-bound": "^1.0.2", 950 | "es-errors": "^1.3.0", 951 | "get-intrinsic": "^1.2.5", 952 | "object-inspect": "^1.13.3" 953 | }, 954 | "engines": { 955 | "node": ">= 0.4" 956 | }, 957 | "funding": { 958 | "url": "https://github.com/sponsors/ljharb" 959 | } 960 | }, 961 | "node_modules/side-channel-weakmap": { 962 | "version": "1.0.2", 963 | "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", 964 | "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", 965 | "dependencies": { 966 | "call-bound": "^1.0.2", 967 | "es-errors": "^1.3.0", 968 | "get-intrinsic": "^1.2.5", 969 | "object-inspect": "^1.13.3", 970 | "side-channel-map": "^1.0.1" 971 | }, 972 | "engines": { 973 | "node": ">= 0.4" 974 | }, 975 | "funding": { 976 | "url": "https://github.com/sponsors/ljharb" 977 | } 978 | }, 979 | "node_modules/simple-update-notifier": { 980 | "version": "2.0.0", 981 | "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", 982 | "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", 983 | "dependencies": { 984 | "semver": "^7.5.3" 985 | }, 986 | "engines": { 987 | "node": ">=10" 988 | } 989 | }, 990 | "node_modules/statuses": { 991 | "version": "2.0.1", 992 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 993 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 994 | "engines": { 995 | "node": ">= 0.8" 996 | } 997 | }, 998 | "node_modules/supports-color": { 999 | "version": "5.5.0", 1000 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1001 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1002 | "dependencies": { 1003 | "has-flag": "^3.0.0" 1004 | }, 1005 | "engines": { 1006 | "node": ">=4" 1007 | } 1008 | }, 1009 | "node_modules/to-regex-range": { 1010 | "version": "5.0.1", 1011 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1012 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1013 | "dependencies": { 1014 | "is-number": "^7.0.0" 1015 | }, 1016 | "engines": { 1017 | "node": ">=8.0" 1018 | } 1019 | }, 1020 | "node_modules/toidentifier": { 1021 | "version": "1.0.1", 1022 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 1023 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 1024 | "engines": { 1025 | "node": ">=0.6" 1026 | } 1027 | }, 1028 | "node_modules/touch": { 1029 | "version": "3.1.1", 1030 | "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", 1031 | "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", 1032 | "bin": { 1033 | "nodetouch": "bin/nodetouch.js" 1034 | } 1035 | }, 1036 | "node_modules/type-is": { 1037 | "version": "2.0.1", 1038 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", 1039 | "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", 1040 | "dependencies": { 1041 | "content-type": "^1.0.5", 1042 | "media-typer": "^1.1.0", 1043 | "mime-types": "^3.0.0" 1044 | }, 1045 | "engines": { 1046 | "node": ">= 0.6" 1047 | } 1048 | }, 1049 | "node_modules/undefsafe": { 1050 | "version": "2.0.5", 1051 | "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", 1052 | "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" 1053 | }, 1054 | "node_modules/unpipe": { 1055 | "version": "1.0.0", 1056 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1057 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 1058 | "engines": { 1059 | "node": ">= 0.8" 1060 | } 1061 | }, 1062 | "node_modules/vary": { 1063 | "version": "1.1.2", 1064 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1065 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 1066 | "engines": { 1067 | "node": ">= 0.8" 1068 | } 1069 | }, 1070 | "node_modules/wrappy": { 1071 | "version": "1.0.2", 1072 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1073 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" 1074 | } 1075 | } 1076 | } 1077 | -------------------------------------------------------------------------------- /prueba2-api-productos/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "plantilla-node-express", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "type": "module", 6 | 7 | "scripts": { 8 | "dev": "nodemon src/index.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "description": "", 14 | "dependencies": { 15 | "cors": "^2.8.5", 16 | "dotenv": "^16.5.0", 17 | "express": "^5.1.0", 18 | "nodemon": "^3.1.9" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /prueba2-api-productos/src/controllers/productosController.js: -------------------------------------------------------------------------------- 1 | // src/controllers/productosController.js 2 | 3 | let productos = []; // array temporal 4 | 5 | export const obtenerProductos = (req, res) => { 6 | if(productos.length >= 1){ 7 | res.json(productos); 8 | } 9 | return res.status(404).json({message: "No tienes productos"}) 10 | }; 11 | 12 | export const obtenerProductoPorId = (req, res) => { 13 | const { id } = req.params; 14 | const producto = productos.find((p) => p.id === id); 15 | if (!producto) return res.status(404).json({ mensaje: "No encontrado" }); 16 | res.json(producto); 17 | }; 18 | 19 | export const crearProducto = (req, res) => { 20 | const { nombre, precio, categoria } = req.body; 21 | if (!nombre || !precio) { 22 | return res.status(400).json({ mensaje: "Nombre y precio son requeridos" }); 23 | } 24 | 25 | const nuevoProducto = { 26 | id: Date.now().toString(), // ID único 27 | nombre, 28 | precio, 29 | categoria: categoria || "", 30 | }; 31 | 32 | productos.push(nuevoProducto); 33 | res.status(201).json(nuevoProducto); 34 | }; 35 | 36 | export const actualizarProducto = (req, res) => { 37 | const { id } = req.params; 38 | const index = productos.findIndex((p) => p.id === id); 39 | if (index === -1) return res.status(404).json({ mensaje: "No encontrado" }); 40 | 41 | const { nombre, precio, categoria } = req.body; 42 | productos[index] = { 43 | ...productos[index], 44 | nombre: nombre || productos[index].nombre, 45 | precio: precio || productos[index].precio, 46 | categoria: categoria || productos[index].categoria, 47 | }; 48 | 49 | res.json(productos[index]); 50 | }; 51 | 52 | export const eliminarProducto = (req, res) => { 53 | const { id } = req.params; 54 | 55 | const existe = productos.some((p) => p.id === id); 56 | if (!existe) { 57 | return res.status(404).json({ mensaje: "Producto no encontrado" }); 58 | } 59 | 60 | productos = productos.filter((p) => p.id !== id); 61 | res.json({ mensaje: "Producto eliminado" }); 62 | }; 63 | -------------------------------------------------------------------------------- /prueba2-api-productos/src/index.js: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import cors from "cors"; 3 | import dotenv from "dotenv"; 4 | import productosRoutes from "./routes/productos.js"; 5 | 6 | dotenv.config(); 7 | const app = express(); 8 | app.use(cors()); 9 | app.use(express.json()); 10 | 11 | app.use("/api/productos", productosRoutes); 12 | 13 | const PORT = process.env.PORT || 3100; 14 | app.listen(PORT, () => { 15 | console.log(`Servidor corriendo en http://localhost:${PORT}`); 16 | }); 17 | -------------------------------------------------------------------------------- /prueba2-api-productos/src/routes/productos.js: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import { 3 | obtenerProductos, 4 | obtenerProductoPorId, 5 | crearProducto, 6 | actualizarProducto, 7 | eliminarProducto, 8 | } from "../controllers/productosController.js"; 9 | 10 | const router = express.Router(); 11 | 12 | router.get("/", obtenerProductos); 13 | router.get("/:id", obtenerProductoPorId); 14 | router.post("/", crearProducto); 15 | router.put("/:id", actualizarProducto); 16 | router.delete("/:id", eliminarProducto); 17 | 18 | export default router; 19 | -------------------------------------------------------------------------------- /prueba3-tareas-zustand/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /prueba3-tareas-zustand/README.md: -------------------------------------------------------------------------------- 1 | # 🧪 Prueba 3 – Lista de Tareas con Zustand 2 | 3 | ## 📋 Descripción 4 | 5 | En esta prueba se debe desarrollar una aplicación en React que permita gestionar una **lista de tareas** (To-Do List) utilizando el gestor de estado global **Zustand**. 6 | 7 | --- 8 | 9 | ## ✅ Requisitos funcionales 10 | 11 | - El usuario debe poder: 12 | - Añadir una nueva tarea con un texto. 13 | - Marcar una tarea como completada. 14 | - Eliminar una tarea. 15 | 16 | - Las tareas deben tener al menos: 17 | - `id`: único 18 | - `texto`: contenido de la tarea 19 | - `completada`: booleano 20 | 21 | --- 22 | 23 | ## 💡 Consideraciones técnicas 24 | 25 | - Utilizar Zustand para manejar el estado de las tareas. 26 | - No es necesario usar bases de datos (puede mantenerse todo en memoria). 27 | - Las tareas pueden ser visibles en una lista. 28 | - Puede usarse Tailwind CSS y/o Chakra UI para los estilos. 29 | - Se recomienda uso de componentes reutilizables para cada tarea. 30 | 31 | --- 32 | 33 | ## 🧱 Tecnologías usadas 34 | 35 | - ⚛️ React + Vite 36 | - 🎨 Tailwind CSS v4 37 | - 📦 Zustand 38 | - (Opcional) Chakra UI 39 | 40 | --- 41 | 42 | ## 🚀 Instalación y ejecución 43 | 44 | ```bash 45 | npm install 46 | npm run dev 47 | -------------------------------------------------------------------------------- /prueba3-tareas-zustand/eslint.config.js: -------------------------------------------------------------------------------- 1 | import js from '@eslint/js' 2 | import globals from 'globals' 3 | import reactHooks from 'eslint-plugin-react-hooks' 4 | import reactRefresh from 'eslint-plugin-react-refresh' 5 | 6 | export default [ 7 | { ignores: ['dist'] }, 8 | { 9 | files: ['**/*.{js,jsx}'], 10 | languageOptions: { 11 | ecmaVersion: 2020, 12 | globals: globals.browser, 13 | parserOptions: { 14 | ecmaVersion: 'latest', 15 | ecmaFeatures: { jsx: true }, 16 | sourceType: 'module', 17 | }, 18 | }, 19 | plugins: { 20 | 'react-hooks': reactHooks, 21 | 'react-refresh': reactRefresh, 22 | }, 23 | rules: { 24 | ...js.configs.recommended.rules, 25 | ...reactHooks.configs.recommended.rules, 26 | 'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }], 27 | 'react-refresh/only-export-components': [ 28 | 'warn', 29 | { allowConstantExport: true }, 30 | ], 31 | }, 32 | }, 33 | ] 34 | -------------------------------------------------------------------------------- /prueba3-tareas-zustand/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /prueba3-tareas-zustand/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "plantilla-react-base", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "lint": "eslint .", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "@chakra-ui/react": "^2.10.7", 14 | "@emotion/react": "^11.14.0", 15 | "@emotion/styled": "^11.14.0", 16 | "@tailwindcss/postcss": "^4.1.4", 17 | "framer-motion": "^12.7.4", 18 | "react": "^19.0.0", 19 | "react-dom": "^19.0.0", 20 | "react-hook-form": "^7.56.1", 21 | "react-icons": "^5.5.0", 22 | "zustand": "^5.0.3" 23 | }, 24 | "devDependencies": { 25 | "@eslint/js": "^9.22.0", 26 | "@tailwindcss/vite": "^4.1.4", 27 | "@types/react": "^19.0.10", 28 | "@types/react-dom": "^19.0.4", 29 | "@vitejs/plugin-react": "^4.3.4", 30 | "autoprefixer": "^10.4.21", 31 | "eslint": "^9.22.0", 32 | "eslint-plugin-react-hooks": "^5.2.0", 33 | "eslint-plugin-react-refresh": "^0.4.19", 34 | "globals": "^16.0.0", 35 | "postcss": "^8.5.3", 36 | "tailwindcss": "^4.1.4", 37 | "vite": "^6.3.1" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /prueba3-tareas-zustand/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /prueba3-tareas-zustand/src/App.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohanBoDev/mini-pruebas-fullstack/ecbbae8fe61f7dd6d52f1fb23641461beaf3385e/prueba3-tareas-zustand/src/App.css -------------------------------------------------------------------------------- /prueba3-tareas-zustand/src/App.jsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react' 2 | import reactLogo from './assets/react.svg' 3 | import viteLogo from '/vite.svg' 4 | import './App.css' 5 | import useTareas from './store/tareas' 6 | 7 | function App() { 8 | const [texto, setTexto] = useState("") 9 | const { agregarTarea, tareas, marcarTarea, eliminarTarea } = useTareas(); 10 | 11 | const handleAgregar = () => { 12 | if (texto.trim() !== "") { 13 | agregarTarea(texto); 14 | setTexto("") 15 | } 16 | else { 17 | alert("Llena el campo") 18 | } 19 | 20 | }; 21 | 22 | return ( 23 |
24 |

TodoAPP

25 |
26 | setTexto(e.target.value)} 30 | placeholder='Crea una tarea...' 31 | className='bg-white/40 rounded-xl pl-3 py-2 text-white' 32 | /> 33 | 34 |
35 | { 36 | (tareas.length === 0 ?

No tienes tareas

37 | : 38 |
    39 | {tareas.map((tarea) => ( 40 |
  • 45 | 46 |

    {tarea.texto}{" "}

    50 |
    51 | 52 | 53 |
    54 | 55 |
  • 56 | ))} 57 |
58 | ) 59 | } 60 | 61 |
62 | 63 |
64 | 65 |
66 | 67 | ); 68 | } 69 | 70 | export default App 71 | -------------------------------------------------------------------------------- /prueba3-tareas-zustand/src/assets/react.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /prueba3-tareas-zustand/src/index.css: -------------------------------------------------------------------------------- 1 | @import "tailwindcss"; 2 | -------------------------------------------------------------------------------- /prueba3-tareas-zustand/src/main.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import App from './App.jsx' 4 | import './index.css' 5 | 6 | ReactDOM.createRoot(document.getElementById('root')).render( 7 | 8 | 9 | , 10 | ) 11 | -------------------------------------------------------------------------------- /prueba3-tareas-zustand/src/store/tareas.jsx: -------------------------------------------------------------------------------- 1 | // src/store/tareas.js 2 | import { create } from 'zustand'; 3 | 4 | const useTareas = create((set) => ({ 5 | tareas: [], 6 | agregarTarea: (texto) => 7 | set((state) => ({ 8 | tareas: [ 9 | ...state.tareas, 10 | { 11 | id: Date.now(), 12 | texto, 13 | completada: false 14 | } 15 | ] 16 | })), 17 | marcarTarea: (id) => 18 | set((state) => ({ 19 | tareas: state.tareas.map((tarea) => 20 | tarea.id === id 21 | ? { ...tarea, completada: !tarea.completada } 22 | : tarea 23 | ), 24 | })), 25 | eliminarTarea: (id) => 26 | set((state) => ({ 27 | tareas: state.tareas.filter((tarea) => tarea.id !== id) 28 | })) 29 | })); 30 | 31 | export default useTareas; 32 | -------------------------------------------------------------------------------- /prueba3-tareas-zustand/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | import tailwindcss from "@tailwindcss/vite"; 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig({ 7 | plugins: [react(), tailwindcss()], 8 | }) 9 | -------------------------------------------------------------------------------- /prueba4-postgreSql/README.md: -------------------------------------------------------------------------------- 1 | # 🧪 Prueba 4: API de Productos con PostgreSQL (Node.js + Express) 2 | 3 | ## 📝 Descripción 4 | 5 | Esta prueba consiste en adaptar una API REST de productos utilizando Node.js, Express y PostgreSQL como base de datos, reemplazando el almacenamiento en memoria por persistencia real. Se utiliza la librería `pg` para conectarse a PostgreSQL. 6 | 7 | --- 8 | 9 | ## 📦 Instalación 10 | 11 | 1. Copia la plantilla base: 12 | 13 | ```bash 14 | cp -r prueba2-api-productos prueba4-postgresql 15 | cd prueba4-postgresql 16 | ``` 17 | 18 | 2. Instala las dependencias: 19 | 20 | ```bash 21 | npm install 22 | ``` 23 | 24 | 3. Crea una base de datos PostgreSQL: 25 | 26 | Puedes llamarla por ejemplo `productosdb`. 27 | 28 | 4. Ejecuta esta consulta para crear la tabla de productos: 29 | 30 | ```sql 31 | CREATE TABLE productos ( 32 | id SERIAL PRIMARY KEY, 33 | nombre VARCHAR(100) NOT NULL, 34 | precio NUMERIC(10, 2) NOT NULL, 35 | categoria VARCHAR(50) NOT NULL 36 | ); 37 | ``` 38 | 39 | --- 40 | 41 | ## ⚙️ Variables de entorno 42 | 43 | Crea un archivo `.env` con el siguiente contenido: 44 | 45 | ```env 46 | DATABASE_URL=postgresql://usuario:contraseña@localhost:5432/productosdb 47 | PORT=3000 48 | ``` 49 | 50 | Reemplaza `usuario` y `contraseña` por los de tu base de datos. 51 | 52 | --- 53 | 54 | ## 🚀 Ejecutar el servidor 55 | 56 | ```bash 57 | npm run dev 58 | ``` 59 | 60 | --- 61 | 62 | ## 📁 Endpoints disponibles 63 | 64 | - `GET /api/productos` → Lista todos los productos. 65 | - `POST /api/productos` → Crea un nuevo producto. 66 | - `PUT /api/productos/:id` → Actualiza un producto por ID. 67 | - `DELETE /api/productos/:id` → Elimina un producto por ID. 68 | 69 | --- 70 | 71 | ## 🛠️ Tecnologías usadas 72 | 73 | - Node.js 74 | - Express 75 | - PostgreSQL 76 | - pg 77 | - dotenv 78 | - nodemon (opcional) -------------------------------------------------------------------------------- /prueba4-postgreSql/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "plantilla-node-express", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "plantilla-node-express", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "cors": "^2.8.5", 13 | "dotenv": "^16.5.0", 14 | "express": "^5.1.0", 15 | "nodemon": "^3.1.9", 16 | "pg": "^8.15.5" 17 | } 18 | }, 19 | "node_modules/accepts": { 20 | "version": "2.0.0", 21 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", 22 | "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", 23 | "dependencies": { 24 | "mime-types": "^3.0.0", 25 | "negotiator": "^1.0.0" 26 | }, 27 | "engines": { 28 | "node": ">= 0.6" 29 | } 30 | }, 31 | "node_modules/anymatch": { 32 | "version": "3.1.3", 33 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", 34 | "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", 35 | "dependencies": { 36 | "normalize-path": "^3.0.0", 37 | "picomatch": "^2.0.4" 38 | }, 39 | "engines": { 40 | "node": ">= 8" 41 | } 42 | }, 43 | "node_modules/balanced-match": { 44 | "version": "1.0.2", 45 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 46 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 47 | }, 48 | "node_modules/binary-extensions": { 49 | "version": "2.3.0", 50 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", 51 | "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", 52 | "engines": { 53 | "node": ">=8" 54 | }, 55 | "funding": { 56 | "url": "https://github.com/sponsors/sindresorhus" 57 | } 58 | }, 59 | "node_modules/body-parser": { 60 | "version": "2.2.0", 61 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", 62 | "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", 63 | "dependencies": { 64 | "bytes": "^3.1.2", 65 | "content-type": "^1.0.5", 66 | "debug": "^4.4.0", 67 | "http-errors": "^2.0.0", 68 | "iconv-lite": "^0.6.3", 69 | "on-finished": "^2.4.1", 70 | "qs": "^6.14.0", 71 | "raw-body": "^3.0.0", 72 | "type-is": "^2.0.0" 73 | }, 74 | "engines": { 75 | "node": ">=18" 76 | } 77 | }, 78 | "node_modules/brace-expansion": { 79 | "version": "1.1.11", 80 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 81 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 82 | "dependencies": { 83 | "balanced-match": "^1.0.0", 84 | "concat-map": "0.0.1" 85 | } 86 | }, 87 | "node_modules/braces": { 88 | "version": "3.0.3", 89 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", 90 | "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", 91 | "dependencies": { 92 | "fill-range": "^7.1.1" 93 | }, 94 | "engines": { 95 | "node": ">=8" 96 | } 97 | }, 98 | "node_modules/bytes": { 99 | "version": "3.1.2", 100 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 101 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 102 | "engines": { 103 | "node": ">= 0.8" 104 | } 105 | }, 106 | "node_modules/call-bind-apply-helpers": { 107 | "version": "1.0.2", 108 | "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", 109 | "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", 110 | "dependencies": { 111 | "es-errors": "^1.3.0", 112 | "function-bind": "^1.1.2" 113 | }, 114 | "engines": { 115 | "node": ">= 0.4" 116 | } 117 | }, 118 | "node_modules/call-bound": { 119 | "version": "1.0.4", 120 | "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", 121 | "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", 122 | "dependencies": { 123 | "call-bind-apply-helpers": "^1.0.2", 124 | "get-intrinsic": "^1.3.0" 125 | }, 126 | "engines": { 127 | "node": ">= 0.4" 128 | }, 129 | "funding": { 130 | "url": "https://github.com/sponsors/ljharb" 131 | } 132 | }, 133 | "node_modules/chokidar": { 134 | "version": "3.6.0", 135 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", 136 | "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", 137 | "dependencies": { 138 | "anymatch": "~3.1.2", 139 | "braces": "~3.0.2", 140 | "glob-parent": "~5.1.2", 141 | "is-binary-path": "~2.1.0", 142 | "is-glob": "~4.0.1", 143 | "normalize-path": "~3.0.0", 144 | "readdirp": "~3.6.0" 145 | }, 146 | "engines": { 147 | "node": ">= 8.10.0" 148 | }, 149 | "funding": { 150 | "url": "https://paulmillr.com/funding/" 151 | }, 152 | "optionalDependencies": { 153 | "fsevents": "~2.3.2" 154 | } 155 | }, 156 | "node_modules/concat-map": { 157 | "version": "0.0.1", 158 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 159 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" 160 | }, 161 | "node_modules/content-disposition": { 162 | "version": "1.0.0", 163 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", 164 | "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", 165 | "dependencies": { 166 | "safe-buffer": "5.2.1" 167 | }, 168 | "engines": { 169 | "node": ">= 0.6" 170 | } 171 | }, 172 | "node_modules/content-type": { 173 | "version": "1.0.5", 174 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 175 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 176 | "engines": { 177 | "node": ">= 0.6" 178 | } 179 | }, 180 | "node_modules/cookie": { 181 | "version": "0.7.2", 182 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", 183 | "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", 184 | "engines": { 185 | "node": ">= 0.6" 186 | } 187 | }, 188 | "node_modules/cookie-signature": { 189 | "version": "1.2.2", 190 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", 191 | "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", 192 | "engines": { 193 | "node": ">=6.6.0" 194 | } 195 | }, 196 | "node_modules/cors": { 197 | "version": "2.8.5", 198 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 199 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 200 | "dependencies": { 201 | "object-assign": "^4", 202 | "vary": "^1" 203 | }, 204 | "engines": { 205 | "node": ">= 0.10" 206 | } 207 | }, 208 | "node_modules/debug": { 209 | "version": "4.4.0", 210 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", 211 | "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", 212 | "dependencies": { 213 | "ms": "^2.1.3" 214 | }, 215 | "engines": { 216 | "node": ">=6.0" 217 | }, 218 | "peerDependenciesMeta": { 219 | "supports-color": { 220 | "optional": true 221 | } 222 | } 223 | }, 224 | "node_modules/depd": { 225 | "version": "2.0.0", 226 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 227 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 228 | "engines": { 229 | "node": ">= 0.8" 230 | } 231 | }, 232 | "node_modules/dotenv": { 233 | "version": "16.5.0", 234 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz", 235 | "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==", 236 | "engines": { 237 | "node": ">=12" 238 | }, 239 | "funding": { 240 | "url": "https://dotenvx.com" 241 | } 242 | }, 243 | "node_modules/dunder-proto": { 244 | "version": "1.0.1", 245 | "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", 246 | "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", 247 | "dependencies": { 248 | "call-bind-apply-helpers": "^1.0.1", 249 | "es-errors": "^1.3.0", 250 | "gopd": "^1.2.0" 251 | }, 252 | "engines": { 253 | "node": ">= 0.4" 254 | } 255 | }, 256 | "node_modules/ee-first": { 257 | "version": "1.1.1", 258 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 259 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 260 | }, 261 | "node_modules/encodeurl": { 262 | "version": "2.0.0", 263 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", 264 | "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", 265 | "engines": { 266 | "node": ">= 0.8" 267 | } 268 | }, 269 | "node_modules/es-define-property": { 270 | "version": "1.0.1", 271 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", 272 | "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", 273 | "engines": { 274 | "node": ">= 0.4" 275 | } 276 | }, 277 | "node_modules/es-errors": { 278 | "version": "1.3.0", 279 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 280 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 281 | "engines": { 282 | "node": ">= 0.4" 283 | } 284 | }, 285 | "node_modules/es-object-atoms": { 286 | "version": "1.1.1", 287 | "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", 288 | "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", 289 | "dependencies": { 290 | "es-errors": "^1.3.0" 291 | }, 292 | "engines": { 293 | "node": ">= 0.4" 294 | } 295 | }, 296 | "node_modules/escape-html": { 297 | "version": "1.0.3", 298 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 299 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 300 | }, 301 | "node_modules/etag": { 302 | "version": "1.8.1", 303 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 304 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 305 | "engines": { 306 | "node": ">= 0.6" 307 | } 308 | }, 309 | "node_modules/express": { 310 | "version": "5.1.0", 311 | "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", 312 | "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", 313 | "dependencies": { 314 | "accepts": "^2.0.0", 315 | "body-parser": "^2.2.0", 316 | "content-disposition": "^1.0.0", 317 | "content-type": "^1.0.5", 318 | "cookie": "^0.7.1", 319 | "cookie-signature": "^1.2.1", 320 | "debug": "^4.4.0", 321 | "encodeurl": "^2.0.0", 322 | "escape-html": "^1.0.3", 323 | "etag": "^1.8.1", 324 | "finalhandler": "^2.1.0", 325 | "fresh": "^2.0.0", 326 | "http-errors": "^2.0.0", 327 | "merge-descriptors": "^2.0.0", 328 | "mime-types": "^3.0.0", 329 | "on-finished": "^2.4.1", 330 | "once": "^1.4.0", 331 | "parseurl": "^1.3.3", 332 | "proxy-addr": "^2.0.7", 333 | "qs": "^6.14.0", 334 | "range-parser": "^1.2.1", 335 | "router": "^2.2.0", 336 | "send": "^1.1.0", 337 | "serve-static": "^2.2.0", 338 | "statuses": "^2.0.1", 339 | "type-is": "^2.0.1", 340 | "vary": "^1.1.2" 341 | }, 342 | "engines": { 343 | "node": ">= 18" 344 | }, 345 | "funding": { 346 | "type": "opencollective", 347 | "url": "https://opencollective.com/express" 348 | } 349 | }, 350 | "node_modules/fill-range": { 351 | "version": "7.1.1", 352 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", 353 | "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", 354 | "dependencies": { 355 | "to-regex-range": "^5.0.1" 356 | }, 357 | "engines": { 358 | "node": ">=8" 359 | } 360 | }, 361 | "node_modules/finalhandler": { 362 | "version": "2.1.0", 363 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", 364 | "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", 365 | "dependencies": { 366 | "debug": "^4.4.0", 367 | "encodeurl": "^2.0.0", 368 | "escape-html": "^1.0.3", 369 | "on-finished": "^2.4.1", 370 | "parseurl": "^1.3.3", 371 | "statuses": "^2.0.1" 372 | }, 373 | "engines": { 374 | "node": ">= 0.8" 375 | } 376 | }, 377 | "node_modules/forwarded": { 378 | "version": "0.2.0", 379 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 380 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 381 | "engines": { 382 | "node": ">= 0.6" 383 | } 384 | }, 385 | "node_modules/fresh": { 386 | "version": "2.0.0", 387 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", 388 | "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", 389 | "engines": { 390 | "node": ">= 0.8" 391 | } 392 | }, 393 | "node_modules/fsevents": { 394 | "version": "2.3.3", 395 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 396 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 397 | "hasInstallScript": true, 398 | "optional": true, 399 | "os": [ 400 | "darwin" 401 | ], 402 | "engines": { 403 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 404 | } 405 | }, 406 | "node_modules/function-bind": { 407 | "version": "1.1.2", 408 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 409 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 410 | "funding": { 411 | "url": "https://github.com/sponsors/ljharb" 412 | } 413 | }, 414 | "node_modules/get-intrinsic": { 415 | "version": "1.3.0", 416 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", 417 | "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", 418 | "dependencies": { 419 | "call-bind-apply-helpers": "^1.0.2", 420 | "es-define-property": "^1.0.1", 421 | "es-errors": "^1.3.0", 422 | "es-object-atoms": "^1.1.1", 423 | "function-bind": "^1.1.2", 424 | "get-proto": "^1.0.1", 425 | "gopd": "^1.2.0", 426 | "has-symbols": "^1.1.0", 427 | "hasown": "^2.0.2", 428 | "math-intrinsics": "^1.1.0" 429 | }, 430 | "engines": { 431 | "node": ">= 0.4" 432 | }, 433 | "funding": { 434 | "url": "https://github.com/sponsors/ljharb" 435 | } 436 | }, 437 | "node_modules/get-proto": { 438 | "version": "1.0.1", 439 | "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", 440 | "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", 441 | "dependencies": { 442 | "dunder-proto": "^1.0.1", 443 | "es-object-atoms": "^1.0.0" 444 | }, 445 | "engines": { 446 | "node": ">= 0.4" 447 | } 448 | }, 449 | "node_modules/glob-parent": { 450 | "version": "5.1.2", 451 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 452 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 453 | "dependencies": { 454 | "is-glob": "^4.0.1" 455 | }, 456 | "engines": { 457 | "node": ">= 6" 458 | } 459 | }, 460 | "node_modules/gopd": { 461 | "version": "1.2.0", 462 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", 463 | "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", 464 | "engines": { 465 | "node": ">= 0.4" 466 | }, 467 | "funding": { 468 | "url": "https://github.com/sponsors/ljharb" 469 | } 470 | }, 471 | "node_modules/has-flag": { 472 | "version": "3.0.0", 473 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 474 | "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", 475 | "engines": { 476 | "node": ">=4" 477 | } 478 | }, 479 | "node_modules/has-symbols": { 480 | "version": "1.1.0", 481 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", 482 | "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", 483 | "engines": { 484 | "node": ">= 0.4" 485 | }, 486 | "funding": { 487 | "url": "https://github.com/sponsors/ljharb" 488 | } 489 | }, 490 | "node_modules/hasown": { 491 | "version": "2.0.2", 492 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 493 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 494 | "dependencies": { 495 | "function-bind": "^1.1.2" 496 | }, 497 | "engines": { 498 | "node": ">= 0.4" 499 | } 500 | }, 501 | "node_modules/http-errors": { 502 | "version": "2.0.0", 503 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 504 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 505 | "dependencies": { 506 | "depd": "2.0.0", 507 | "inherits": "2.0.4", 508 | "setprototypeof": "1.2.0", 509 | "statuses": "2.0.1", 510 | "toidentifier": "1.0.1" 511 | }, 512 | "engines": { 513 | "node": ">= 0.8" 514 | } 515 | }, 516 | "node_modules/iconv-lite": { 517 | "version": "0.6.3", 518 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", 519 | "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", 520 | "dependencies": { 521 | "safer-buffer": ">= 2.1.2 < 3.0.0" 522 | }, 523 | "engines": { 524 | "node": ">=0.10.0" 525 | } 526 | }, 527 | "node_modules/ignore-by-default": { 528 | "version": "1.0.1", 529 | "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", 530 | "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" 531 | }, 532 | "node_modules/inherits": { 533 | "version": "2.0.4", 534 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 535 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 536 | }, 537 | "node_modules/ipaddr.js": { 538 | "version": "1.9.1", 539 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 540 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 541 | "engines": { 542 | "node": ">= 0.10" 543 | } 544 | }, 545 | "node_modules/is-binary-path": { 546 | "version": "2.1.0", 547 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 548 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 549 | "dependencies": { 550 | "binary-extensions": "^2.0.0" 551 | }, 552 | "engines": { 553 | "node": ">=8" 554 | } 555 | }, 556 | "node_modules/is-extglob": { 557 | "version": "2.1.1", 558 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 559 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 560 | "engines": { 561 | "node": ">=0.10.0" 562 | } 563 | }, 564 | "node_modules/is-glob": { 565 | "version": "4.0.3", 566 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 567 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 568 | "dependencies": { 569 | "is-extglob": "^2.1.1" 570 | }, 571 | "engines": { 572 | "node": ">=0.10.0" 573 | } 574 | }, 575 | "node_modules/is-number": { 576 | "version": "7.0.0", 577 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 578 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 579 | "engines": { 580 | "node": ">=0.12.0" 581 | } 582 | }, 583 | "node_modules/is-promise": { 584 | "version": "4.0.0", 585 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", 586 | "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==" 587 | }, 588 | "node_modules/math-intrinsics": { 589 | "version": "1.1.0", 590 | "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", 591 | "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", 592 | "engines": { 593 | "node": ">= 0.4" 594 | } 595 | }, 596 | "node_modules/media-typer": { 597 | "version": "1.1.0", 598 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", 599 | "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", 600 | "engines": { 601 | "node": ">= 0.8" 602 | } 603 | }, 604 | "node_modules/merge-descriptors": { 605 | "version": "2.0.0", 606 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", 607 | "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", 608 | "engines": { 609 | "node": ">=18" 610 | }, 611 | "funding": { 612 | "url": "https://github.com/sponsors/sindresorhus" 613 | } 614 | }, 615 | "node_modules/mime-db": { 616 | "version": "1.54.0", 617 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", 618 | "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", 619 | "engines": { 620 | "node": ">= 0.6" 621 | } 622 | }, 623 | "node_modules/mime-types": { 624 | "version": "3.0.1", 625 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", 626 | "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", 627 | "dependencies": { 628 | "mime-db": "^1.54.0" 629 | }, 630 | "engines": { 631 | "node": ">= 0.6" 632 | } 633 | }, 634 | "node_modules/minimatch": { 635 | "version": "3.1.2", 636 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 637 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 638 | "dependencies": { 639 | "brace-expansion": "^1.1.7" 640 | }, 641 | "engines": { 642 | "node": "*" 643 | } 644 | }, 645 | "node_modules/ms": { 646 | "version": "2.1.3", 647 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 648 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 649 | }, 650 | "node_modules/negotiator": { 651 | "version": "1.0.0", 652 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", 653 | "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", 654 | "engines": { 655 | "node": ">= 0.6" 656 | } 657 | }, 658 | "node_modules/nodemon": { 659 | "version": "3.1.9", 660 | "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.9.tgz", 661 | "integrity": "sha512-hdr1oIb2p6ZSxu3PB2JWWYS7ZQ0qvaZsc3hK8DR8f02kRzc8rjYmxAIvdz+aYC+8F2IjNaB7HMcSDg8nQpJxyg==", 662 | "dependencies": { 663 | "chokidar": "^3.5.2", 664 | "debug": "^4", 665 | "ignore-by-default": "^1.0.1", 666 | "minimatch": "^3.1.2", 667 | "pstree.remy": "^1.1.8", 668 | "semver": "^7.5.3", 669 | "simple-update-notifier": "^2.0.0", 670 | "supports-color": "^5.5.0", 671 | "touch": "^3.1.0", 672 | "undefsafe": "^2.0.5" 673 | }, 674 | "bin": { 675 | "nodemon": "bin/nodemon.js" 676 | }, 677 | "engines": { 678 | "node": ">=10" 679 | }, 680 | "funding": { 681 | "type": "opencollective", 682 | "url": "https://opencollective.com/nodemon" 683 | } 684 | }, 685 | "node_modules/normalize-path": { 686 | "version": "3.0.0", 687 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 688 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 689 | "engines": { 690 | "node": ">=0.10.0" 691 | } 692 | }, 693 | "node_modules/object-assign": { 694 | "version": "4.1.1", 695 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 696 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", 697 | "engines": { 698 | "node": ">=0.10.0" 699 | } 700 | }, 701 | "node_modules/object-inspect": { 702 | "version": "1.13.4", 703 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", 704 | "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", 705 | "engines": { 706 | "node": ">= 0.4" 707 | }, 708 | "funding": { 709 | "url": "https://github.com/sponsors/ljharb" 710 | } 711 | }, 712 | "node_modules/on-finished": { 713 | "version": "2.4.1", 714 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 715 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 716 | "dependencies": { 717 | "ee-first": "1.1.1" 718 | }, 719 | "engines": { 720 | "node": ">= 0.8" 721 | } 722 | }, 723 | "node_modules/once": { 724 | "version": "1.4.0", 725 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 726 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 727 | "dependencies": { 728 | "wrappy": "1" 729 | } 730 | }, 731 | "node_modules/parseurl": { 732 | "version": "1.3.3", 733 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 734 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 735 | "engines": { 736 | "node": ">= 0.8" 737 | } 738 | }, 739 | "node_modules/path-to-regexp": { 740 | "version": "8.2.0", 741 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", 742 | "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", 743 | "engines": { 744 | "node": ">=16" 745 | } 746 | }, 747 | "node_modules/pg": { 748 | "version": "8.15.5", 749 | "resolved": "https://registry.npmjs.org/pg/-/pg-8.15.5.tgz", 750 | "integrity": "sha512-EpAhHFQc+aH9VfeffWIVC+XXk6lmAhS9W1FxtxcPXs94yxhrI1I6w/zkWfIOII/OkBv3Be04X3xMOj0kQ78l6w==", 751 | "dependencies": { 752 | "pg-connection-string": "^2.8.5", 753 | "pg-pool": "^3.9.5", 754 | "pg-protocol": "^1.9.5", 755 | "pg-types": "^2.1.0", 756 | "pgpass": "1.x" 757 | }, 758 | "engines": { 759 | "node": ">= 8.0.0" 760 | }, 761 | "optionalDependencies": { 762 | "pg-cloudflare": "^1.2.5" 763 | }, 764 | "peerDependencies": { 765 | "pg-native": ">=3.0.1" 766 | }, 767 | "peerDependenciesMeta": { 768 | "pg-native": { 769 | "optional": true 770 | } 771 | } 772 | }, 773 | "node_modules/pg-cloudflare": { 774 | "version": "1.2.5", 775 | "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.2.5.tgz", 776 | "integrity": "sha512-OOX22Vt0vOSRrdoUPKJ8Wi2OpE/o/h9T8X1s4qSkCedbNah9ei2W2765be8iMVxQUsvgT7zIAT2eIa9fs5+vtg==", 777 | "optional": true 778 | }, 779 | "node_modules/pg-connection-string": { 780 | "version": "2.8.5", 781 | "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.8.5.tgz", 782 | "integrity": "sha512-Ni8FuZ8yAF+sWZzojvtLE2b03cqjO5jNULcHFfM9ZZ0/JXrgom5pBREbtnAw7oxsxJqHw9Nz/XWORUEL3/IFow==" 783 | }, 784 | "node_modules/pg-int8": { 785 | "version": "1.0.1", 786 | "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", 787 | "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", 788 | "engines": { 789 | "node": ">=4.0.0" 790 | } 791 | }, 792 | "node_modules/pg-pool": { 793 | "version": "3.9.5", 794 | "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.9.5.tgz", 795 | "integrity": "sha512-DxyAlOgvUzRFpFAZjbCc8fUfG7BcETDHgepFPf724B0i08k9PAiZV1tkGGgQIL0jbMEuR9jW1YN7eX+WgXxCsQ==", 796 | "peerDependencies": { 797 | "pg": ">=8.0" 798 | } 799 | }, 800 | "node_modules/pg-protocol": { 801 | "version": "1.9.5", 802 | "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.9.5.tgz", 803 | "integrity": "sha512-DYTWtWpfd5FOro3UnAfwvhD8jh59r2ig8bPtc9H8Ds7MscE/9NYruUQWFAOuraRl29jwcT2kyMFQ3MxeaVjUhg==" 804 | }, 805 | "node_modules/pg-types": { 806 | "version": "2.2.0", 807 | "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", 808 | "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", 809 | "dependencies": { 810 | "pg-int8": "1.0.1", 811 | "postgres-array": "~2.0.0", 812 | "postgres-bytea": "~1.0.0", 813 | "postgres-date": "~1.0.4", 814 | "postgres-interval": "^1.1.0" 815 | }, 816 | "engines": { 817 | "node": ">=4" 818 | } 819 | }, 820 | "node_modules/pgpass": { 821 | "version": "1.0.5", 822 | "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", 823 | "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", 824 | "dependencies": { 825 | "split2": "^4.1.0" 826 | } 827 | }, 828 | "node_modules/picomatch": { 829 | "version": "2.3.1", 830 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 831 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 832 | "engines": { 833 | "node": ">=8.6" 834 | }, 835 | "funding": { 836 | "url": "https://github.com/sponsors/jonschlinkert" 837 | } 838 | }, 839 | "node_modules/postgres-array": { 840 | "version": "2.0.0", 841 | "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", 842 | "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", 843 | "engines": { 844 | "node": ">=4" 845 | } 846 | }, 847 | "node_modules/postgres-bytea": { 848 | "version": "1.0.0", 849 | "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", 850 | "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", 851 | "engines": { 852 | "node": ">=0.10.0" 853 | } 854 | }, 855 | "node_modules/postgres-date": { 856 | "version": "1.0.7", 857 | "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", 858 | "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", 859 | "engines": { 860 | "node": ">=0.10.0" 861 | } 862 | }, 863 | "node_modules/postgres-interval": { 864 | "version": "1.2.0", 865 | "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", 866 | "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", 867 | "dependencies": { 868 | "xtend": "^4.0.0" 869 | }, 870 | "engines": { 871 | "node": ">=0.10.0" 872 | } 873 | }, 874 | "node_modules/proxy-addr": { 875 | "version": "2.0.7", 876 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 877 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 878 | "dependencies": { 879 | "forwarded": "0.2.0", 880 | "ipaddr.js": "1.9.1" 881 | }, 882 | "engines": { 883 | "node": ">= 0.10" 884 | } 885 | }, 886 | "node_modules/pstree.remy": { 887 | "version": "1.1.8", 888 | "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", 889 | "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" 890 | }, 891 | "node_modules/qs": { 892 | "version": "6.14.0", 893 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", 894 | "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", 895 | "dependencies": { 896 | "side-channel": "^1.1.0" 897 | }, 898 | "engines": { 899 | "node": ">=0.6" 900 | }, 901 | "funding": { 902 | "url": "https://github.com/sponsors/ljharb" 903 | } 904 | }, 905 | "node_modules/range-parser": { 906 | "version": "1.2.1", 907 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 908 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 909 | "engines": { 910 | "node": ">= 0.6" 911 | } 912 | }, 913 | "node_modules/raw-body": { 914 | "version": "3.0.0", 915 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", 916 | "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", 917 | "dependencies": { 918 | "bytes": "3.1.2", 919 | "http-errors": "2.0.0", 920 | "iconv-lite": "0.6.3", 921 | "unpipe": "1.0.0" 922 | }, 923 | "engines": { 924 | "node": ">= 0.8" 925 | } 926 | }, 927 | "node_modules/readdirp": { 928 | "version": "3.6.0", 929 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 930 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 931 | "dependencies": { 932 | "picomatch": "^2.2.1" 933 | }, 934 | "engines": { 935 | "node": ">=8.10.0" 936 | } 937 | }, 938 | "node_modules/router": { 939 | "version": "2.2.0", 940 | "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", 941 | "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", 942 | "dependencies": { 943 | "debug": "^4.4.0", 944 | "depd": "^2.0.0", 945 | "is-promise": "^4.0.0", 946 | "parseurl": "^1.3.3", 947 | "path-to-regexp": "^8.0.0" 948 | }, 949 | "engines": { 950 | "node": ">= 18" 951 | } 952 | }, 953 | "node_modules/safe-buffer": { 954 | "version": "5.2.1", 955 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 956 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 957 | "funding": [ 958 | { 959 | "type": "github", 960 | "url": "https://github.com/sponsors/feross" 961 | }, 962 | { 963 | "type": "patreon", 964 | "url": "https://www.patreon.com/feross" 965 | }, 966 | { 967 | "type": "consulting", 968 | "url": "https://feross.org/support" 969 | } 970 | ] 971 | }, 972 | "node_modules/safer-buffer": { 973 | "version": "2.1.2", 974 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 975 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 976 | }, 977 | "node_modules/semver": { 978 | "version": "7.7.1", 979 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", 980 | "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", 981 | "bin": { 982 | "semver": "bin/semver.js" 983 | }, 984 | "engines": { 985 | "node": ">=10" 986 | } 987 | }, 988 | "node_modules/send": { 989 | "version": "1.2.0", 990 | "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", 991 | "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", 992 | "dependencies": { 993 | "debug": "^4.3.5", 994 | "encodeurl": "^2.0.0", 995 | "escape-html": "^1.0.3", 996 | "etag": "^1.8.1", 997 | "fresh": "^2.0.0", 998 | "http-errors": "^2.0.0", 999 | "mime-types": "^3.0.1", 1000 | "ms": "^2.1.3", 1001 | "on-finished": "^2.4.1", 1002 | "range-parser": "^1.2.1", 1003 | "statuses": "^2.0.1" 1004 | }, 1005 | "engines": { 1006 | "node": ">= 18" 1007 | } 1008 | }, 1009 | "node_modules/serve-static": { 1010 | "version": "2.2.0", 1011 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", 1012 | "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", 1013 | "dependencies": { 1014 | "encodeurl": "^2.0.0", 1015 | "escape-html": "^1.0.3", 1016 | "parseurl": "^1.3.3", 1017 | "send": "^1.2.0" 1018 | }, 1019 | "engines": { 1020 | "node": ">= 18" 1021 | } 1022 | }, 1023 | "node_modules/setprototypeof": { 1024 | "version": "1.2.0", 1025 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 1026 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 1027 | }, 1028 | "node_modules/side-channel": { 1029 | "version": "1.1.0", 1030 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", 1031 | "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", 1032 | "dependencies": { 1033 | "es-errors": "^1.3.0", 1034 | "object-inspect": "^1.13.3", 1035 | "side-channel-list": "^1.0.0", 1036 | "side-channel-map": "^1.0.1", 1037 | "side-channel-weakmap": "^1.0.2" 1038 | }, 1039 | "engines": { 1040 | "node": ">= 0.4" 1041 | }, 1042 | "funding": { 1043 | "url": "https://github.com/sponsors/ljharb" 1044 | } 1045 | }, 1046 | "node_modules/side-channel-list": { 1047 | "version": "1.0.0", 1048 | "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", 1049 | "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", 1050 | "dependencies": { 1051 | "es-errors": "^1.3.0", 1052 | "object-inspect": "^1.13.3" 1053 | }, 1054 | "engines": { 1055 | "node": ">= 0.4" 1056 | }, 1057 | "funding": { 1058 | "url": "https://github.com/sponsors/ljharb" 1059 | } 1060 | }, 1061 | "node_modules/side-channel-map": { 1062 | "version": "1.0.1", 1063 | "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", 1064 | "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", 1065 | "dependencies": { 1066 | "call-bound": "^1.0.2", 1067 | "es-errors": "^1.3.0", 1068 | "get-intrinsic": "^1.2.5", 1069 | "object-inspect": "^1.13.3" 1070 | }, 1071 | "engines": { 1072 | "node": ">= 0.4" 1073 | }, 1074 | "funding": { 1075 | "url": "https://github.com/sponsors/ljharb" 1076 | } 1077 | }, 1078 | "node_modules/side-channel-weakmap": { 1079 | "version": "1.0.2", 1080 | "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", 1081 | "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", 1082 | "dependencies": { 1083 | "call-bound": "^1.0.2", 1084 | "es-errors": "^1.3.0", 1085 | "get-intrinsic": "^1.2.5", 1086 | "object-inspect": "^1.13.3", 1087 | "side-channel-map": "^1.0.1" 1088 | }, 1089 | "engines": { 1090 | "node": ">= 0.4" 1091 | }, 1092 | "funding": { 1093 | "url": "https://github.com/sponsors/ljharb" 1094 | } 1095 | }, 1096 | "node_modules/simple-update-notifier": { 1097 | "version": "2.0.0", 1098 | "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", 1099 | "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", 1100 | "dependencies": { 1101 | "semver": "^7.5.3" 1102 | }, 1103 | "engines": { 1104 | "node": ">=10" 1105 | } 1106 | }, 1107 | "node_modules/split2": { 1108 | "version": "4.2.0", 1109 | "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", 1110 | "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", 1111 | "engines": { 1112 | "node": ">= 10.x" 1113 | } 1114 | }, 1115 | "node_modules/statuses": { 1116 | "version": "2.0.1", 1117 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 1118 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 1119 | "engines": { 1120 | "node": ">= 0.8" 1121 | } 1122 | }, 1123 | "node_modules/supports-color": { 1124 | "version": "5.5.0", 1125 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1126 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1127 | "dependencies": { 1128 | "has-flag": "^3.0.0" 1129 | }, 1130 | "engines": { 1131 | "node": ">=4" 1132 | } 1133 | }, 1134 | "node_modules/to-regex-range": { 1135 | "version": "5.0.1", 1136 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1137 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1138 | "dependencies": { 1139 | "is-number": "^7.0.0" 1140 | }, 1141 | "engines": { 1142 | "node": ">=8.0" 1143 | } 1144 | }, 1145 | "node_modules/toidentifier": { 1146 | "version": "1.0.1", 1147 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 1148 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 1149 | "engines": { 1150 | "node": ">=0.6" 1151 | } 1152 | }, 1153 | "node_modules/touch": { 1154 | "version": "3.1.1", 1155 | "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", 1156 | "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", 1157 | "bin": { 1158 | "nodetouch": "bin/nodetouch.js" 1159 | } 1160 | }, 1161 | "node_modules/type-is": { 1162 | "version": "2.0.1", 1163 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", 1164 | "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", 1165 | "dependencies": { 1166 | "content-type": "^1.0.5", 1167 | "media-typer": "^1.1.0", 1168 | "mime-types": "^3.0.0" 1169 | }, 1170 | "engines": { 1171 | "node": ">= 0.6" 1172 | } 1173 | }, 1174 | "node_modules/undefsafe": { 1175 | "version": "2.0.5", 1176 | "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", 1177 | "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" 1178 | }, 1179 | "node_modules/unpipe": { 1180 | "version": "1.0.0", 1181 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1182 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 1183 | "engines": { 1184 | "node": ">= 0.8" 1185 | } 1186 | }, 1187 | "node_modules/vary": { 1188 | "version": "1.1.2", 1189 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1190 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 1191 | "engines": { 1192 | "node": ">= 0.8" 1193 | } 1194 | }, 1195 | "node_modules/wrappy": { 1196 | "version": "1.0.2", 1197 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1198 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" 1199 | }, 1200 | "node_modules/xtend": { 1201 | "version": "4.0.2", 1202 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", 1203 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", 1204 | "engines": { 1205 | "node": ">=0.4" 1206 | } 1207 | } 1208 | } 1209 | } 1210 | -------------------------------------------------------------------------------- /prueba4-postgreSql/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "plantilla-node-express", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "nodemon src/index.js", 8 | "db" : "node src/db/db.js" 9 | 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "description": "", 15 | "dependencies": { 16 | "cors": "^2.8.5", 17 | "dotenv": "^16.5.0", 18 | "express": "^5.1.0", 19 | "nodemon": "^3.1.9", 20 | "pg": "^8.15.5" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /prueba4-postgreSql/src/controllers/productosController.js: -------------------------------------------------------------------------------- 1 | // src/controllers/productosController.js 2 | import pool from "../db/db.js"; 3 | 4 | export const obtenerProductos = async (req, res) => { 5 | try { 6 | const result = await pool.query("SELECT * FROM productos"); 7 | if (result.rows.length > 0) { 8 | res.json(result.rows); 9 | } else { 10 | res.status(404).json({ message: "No tienes productos" }); 11 | } 12 | } catch (error) { 13 | res.status(500).json({ error: "Error al obtener productos" }); 14 | } 15 | }; 16 | 17 | export const obtenerProductoPorId = async (req, res) => { 18 | const { id } = req.params; 19 | try { 20 | const result = await pool.query("SELECT * FROM productos WHERE id = $1", [id]); 21 | if (result.rows.length === 0) { 22 | return res.status(404).json({ mensaje: "No encontrado" }); 23 | } 24 | res.json(result.rows[0]); 25 | } catch (error) { 26 | res.status(500).json({ error: "Error al buscar producto" }); 27 | } 28 | }; 29 | 30 | export const crearProducto = async (req, res) => { 31 | const { nombre, precio, categoria } = req.body; 32 | if (!nombre || !precio) { 33 | return res.status(400).json({ mensaje: "Nombre y precio son requeridos" }); 34 | } 35 | 36 | try { 37 | const result = await pool.query( 38 | "INSERT INTO productos (nombre, precio, categoria) VALUES ($1, $2, $3) RETURNING *", 39 | [nombre, precio, categoria || ""] 40 | ); 41 | res.status(201).json(result.rows[0]); 42 | } catch (error) { 43 | res.status(500).json({ error: "Error al crear producto" }); 44 | } 45 | }; 46 | 47 | export const actualizarProducto = async (req, res) => { 48 | const { id } = req.params; 49 | const { nombre, precio, categoria } = req.body; 50 | 51 | try { 52 | const result = await pool.query( 53 | "UPDATE productos SET nombre=$1, precio=$2, categoria=$3 WHERE id=$4 RETURNING *", 54 | [nombre, precio, categoria, id] 55 | ); 56 | 57 | if (result.rows.length === 0) { 58 | return res.status(404).json({ mensaje: "Producto no encontrado" }); 59 | } 60 | 61 | res.json(result.rows[0]); 62 | } catch (error) { 63 | res.status(500).json({ error: "Error al actualizar producto" }); 64 | } 65 | }; 66 | 67 | export const eliminarProducto = async (req, res) => { 68 | const { id } = req.params; 69 | try { 70 | const result = await pool.query("DELETE FROM productos WHERE id=$1 RETURNING *", [id]); 71 | 72 | if (result.rows.length === 0) { 73 | return res.status(404).json({ mensaje: "Producto no encontrado" }); 74 | } 75 | 76 | res.json({ mensaje: "Producto eliminado" }); 77 | } catch (error) { 78 | res.status(500).json({ error: "Error al eliminar producto" }); 79 | } 80 | }; 81 | -------------------------------------------------------------------------------- /prueba4-postgreSql/src/db/db.js: -------------------------------------------------------------------------------- 1 | // db/index.js 2 | import pkg from 'pg'; 3 | import dotenv from 'dotenv'; 4 | 5 | dotenv.config(); 6 | 7 | const { Pool } = pkg; 8 | 9 | const pool = new Pool({ 10 | connectionString: process.env.DATABASE_URL, 11 | }); 12 | 13 | pool.on('connect', () => { 14 | console.log('🟢 Conectado a PostgreSQL'); 15 | }); 16 | 17 | 18 | 19 | 20 | export default pool; 21 | -------------------------------------------------------------------------------- /prueba4-postgreSql/src/index.js: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import cors from "cors"; 3 | import dotenv from "dotenv"; 4 | import productosRoutes from "./routes/productos.js"; 5 | import pool from "./db/db.js"; 6 | 7 | dotenv.config(); 8 | 9 | const app = express(); 10 | app.use(cors()); 11 | app.use(express.json()); 12 | 13 | app.use("/api/productos", productosRoutes); 14 | 15 | app.get("/", (req, res) => { 16 | res.send("API activa"); 17 | }); 18 | 19 | 20 | const PORT = process.env.PORT || 3000; 21 | app.listen(PORT, () => { 22 | console.log(`Servidor corriendo en http://localhost:${PORT}`); 23 | }); 24 | -------------------------------------------------------------------------------- /prueba4-postgreSql/src/routes/productos.js: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import { 3 | obtenerProductos, 4 | obtenerProductoPorId, 5 | crearProducto, 6 | actualizarProducto, 7 | eliminarProducto, 8 | } from "../controllers/productosController.js"; 9 | 10 | const router = express.Router(); 11 | 12 | router.get("/", obtenerProductos); 13 | router.get("/:id", obtenerProductoPorId); 14 | router.post("/", crearProducto); 15 | router.put("/:id", actualizarProducto); 16 | router.delete("/:id", eliminarProducto); 17 | 18 | export default router; 19 | --------------------------------------------------------------------------------