From 607608315bfa992b66e14380dbedee1b43eab85b Mon Sep 17 00:00:00 2001 From: CrisNAC Date: Wed, 11 Mar 2026 19:07:02 -0300 Subject: [PATCH 1/6] =?UTF-8?q?Se=20hizo=20un=20npm=20audit=20para=20arreg?= =?UTF-8?q?lo=20de=20vulnerabilidades,=20se=20instal=C3=B3=20zod=20y=20tsx?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 680 ++++------------------------------------------ package.json | 5 +- 2 files changed, 55 insertions(+), 630 deletions(-) diff --git a/package-lock.json b/package-lock.json index f224fef..4442980 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,83 +19,17 @@ "jsonwebtoken": "^9.0.3", "morgan": "^1.10.1", "nodemon": "^3.1.14", - "pg": "^8.19.0" + "pg": "^8.19.0", + "zod": "^4.3.6" }, "devDependencies": { "@types/express": "^5.0.6", "@types/node": "^25.3.2", - "prisma": "^7.4.1", + "prisma": "^6.19.2", "tsx": "^4.21.0", "typescript": "^5.9.3" } }, - "node_modules/@chevrotain/cst-dts-gen": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-10.5.0.tgz", - "integrity": "sha512-lhmC/FyqQ2o7pGK4Om+hzuDrm9rhFYIJ/AXoQBeongmn870Xeb0L6oGEiuR8nohFNL5sMaQEJWCxr1oIVIVXrw==", - "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "@chevrotain/gast": "10.5.0", - "@chevrotain/types": "10.5.0", - "lodash": "4.17.21" - } - }, - "node_modules/@chevrotain/gast": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-10.5.0.tgz", - "integrity": "sha512-pXdMJ9XeDAbgOWKuD1Fldz4ieCs6+nLNmyVhe2gZVqoO7v8HXuHYs5OV2EzUtbuai37TlOAQHrTDvxMnvMJz3A==", - "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "@chevrotain/types": "10.5.0", - "lodash": "4.17.21" - } - }, - "node_modules/@chevrotain/types": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-10.5.0.tgz", - "integrity": "sha512-f1MAia0x/pAVPWH/T73BJVyO2XU5tI4/iE7cnxb7tqdNTNhQI3Uq3XkqcoteTmD4t1aM0LbHCJOhgIDn07kl2A==", - "devOptional": true, - "license": "Apache-2.0" - }, - "node_modules/@chevrotain/utils": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-10.5.0.tgz", - "integrity": "sha512-hBzuU5+JjB2cqNZyszkDHZgOSrUUT8V3dhgRl8Q9Gp6dAj/H5+KILGjbhDpc3Iy9qmqlm/akuOI2ut9VUtzJxQ==", - "devOptional": true, - "license": "Apache-2.0" - }, - "node_modules/@electric-sql/pglite": { - "version": "0.3.15", - "resolved": "https://registry.npmjs.org/@electric-sql/pglite/-/pglite-0.3.15.tgz", - "integrity": "sha512-Cj++n1Mekf9ETfdc16TlDi+cDDQF0W7EcbyRHYOAeZdsAe8M/FJg18itDTSwyHfar2WIezawM9o0EKaRGVKygQ==", - "devOptional": true, - "license": "Apache-2.0" - }, - "node_modules/@electric-sql/pglite-socket": { - "version": "0.0.20", - "resolved": "https://registry.npmjs.org/@electric-sql/pglite-socket/-/pglite-socket-0.0.20.tgz", - "integrity": "sha512-J5nLGsicnD9wJHnno9r+DGxfcZWh+YJMCe0q/aCgtG6XOm9Z7fKeite8IZSNXgZeGltSigM9U/vAWZQWdgcSFg==", - "devOptional": true, - "license": "Apache-2.0", - "bin": { - "pglite-server": "dist/scripts/server.js" - }, - "peerDependencies": { - "@electric-sql/pglite": "0.3.15" - } - }, - "node_modules/@electric-sql/pglite-tools": { - "version": "0.2.20", - "resolved": "https://registry.npmjs.org/@electric-sql/pglite-tools/-/pglite-tools-0.2.20.tgz", - "integrity": "sha512-BK50ZnYa3IG7ztXhtgYf0Q7zijV32Iw1cYS8C+ThdQlwx12V5VZ9KRJ42y82Hyb4PkTxZQklVQA9JHyUlex33A==", - "devOptional": true, - "license": "Apache-2.0", - "peerDependencies": { - "@electric-sql/pglite": "0.3.15" - } - }, "node_modules/@esbuild/aix-ppc64": { "version": "0.27.3", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", @@ -538,33 +472,6 @@ "node": ">=18" } }, - "node_modules/@hono/node-server": { - "version": "1.19.9", - "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.9.tgz", - "integrity": "sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=18.14.1" - }, - "peerDependencies": { - "hono": "^4" - } - }, - "node_modules/@mrleebo/prisma-ast": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/@mrleebo/prisma-ast/-/prisma-ast-0.13.1.tgz", - "integrity": "sha512-XyroGQXcHrZdvmrGJvsA9KNeOOgGMg1Vg9OlheUsBOSKznLMDl+YChxbkboRHvtFYJEMRYmlV3uoo/njCw05iw==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "chevrotain": "^10.5.0", - "lilconfig": "^2.1.0" - }, - "engines": { - "node": ">=16" - } - }, "node_modules/@prisma/adapter-pg": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/@prisma/adapter-pg/-/adapter-pg-7.4.1.tgz", @@ -607,9 +514,9 @@ "license": "Apache-2.0" }, "node_modules/@prisma/config": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@prisma/config/-/config-7.4.1.tgz", - "integrity": "sha512-vteSXm8N46bo3FW9MhPGVHAj+KRgrR6TWtlSk6GqToCKjTnOexXdPZyiDyEsfVW38YhqEmVl6w/6iHN8uYVJcw==", + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.19.2.tgz", + "integrity": "sha512-kadBGDl+aUswv/zZMk9Mx0C8UZs1kjao8H9/JpI4Wh4SHZaM7zkTwiKn/iFLfRg+XtOAo/Z/c6pAYhijKl0nzQ==", "devOptional": true, "license": "Apache-2.0", "dependencies": { @@ -625,32 +532,6 @@ "integrity": "sha512-qEtzO8oLouRv18JDQUC3G3Gnv+fGVscHZm/x1DBB/WT+kOvPDQLM2woX6IGgWnSMYYlrxjuALshT7G/blvY0bQ==", "license": "Apache-2.0" }, - "node_modules/@prisma/dev": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@prisma/dev/-/dev-0.20.0.tgz", - "integrity": "sha512-ovlBYwWor0OzG+yH4J3Ot+AneD818BttLA+Ii7wjbcLHUrnC4tbUPVGyNd3c/+71KETPKZfjhkTSpdS15dmXNQ==", - "devOptional": true, - "license": "ISC", - "dependencies": { - "@electric-sql/pglite": "0.3.15", - "@electric-sql/pglite-socket": "0.0.20", - "@electric-sql/pglite-tools": "0.2.20", - "@hono/node-server": "1.19.9", - "@mrleebo/prisma-ast": "0.13.1", - "@prisma/get-platform": "7.2.0", - "@prisma/query-plan-executor": "7.2.0", - "foreground-child": "3.3.1", - "get-port-please": "3.2.0", - "hono": "4.11.4", - "http-status-codes": "2.3.0", - "pathe": "2.0.3", - "proper-lockfile": "4.1.2", - "remeda": "2.33.4", - "std-env": "3.10.0", - "valibot": "1.2.0", - "zeptomatch": "2.1.0" - } - }, "node_modules/@prisma/driver-adapter-utils": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/@prisma/driver-adapter-utils/-/driver-adapter-utils-7.4.1.tgz", @@ -661,94 +542,69 @@ } }, "node_modules/@prisma/engines": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-7.4.1.tgz", - "integrity": "sha512-BZEBdHvNJx5PzIG37EI/Zi5UUI5hGWjkYsQmKa7OIK6evAvebOTwutjS/VRI6cA6grmA52eLZR+oekGRMqkKxQ==", + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.19.2.tgz", + "integrity": "sha512-TTkJ8r+uk/uqczX40wb+ODG0E0icVsMgwCTyTHXehaEfb0uo80M9g1aW1tEJrxmFHeOZFXdI2sTA1j1AgcHi4A==", "devOptional": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "7.4.1", - "@prisma/engines-version": "7.5.0-4.55ae170b1ced7fc6ed07a15f110549408c501bb3", - "@prisma/fetch-engine": "7.4.1", - "@prisma/get-platform": "7.4.1" + "@prisma/debug": "6.19.2", + "@prisma/engines-version": "7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7", + "@prisma/fetch-engine": "6.19.2", + "@prisma/get-platform": "6.19.2" } }, "node_modules/@prisma/engines-version": { - "version": "7.5.0-4.55ae170b1ced7fc6ed07a15f110549408c501bb3", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-7.5.0-4.55ae170b1ced7fc6ed07a15f110549408c501bb3.tgz", - "integrity": "sha512-fUxVd1TjOW8K4XsZ8dAm88sDW5Ry7AxWDfsYEWwScS6Fjo3caKC6hgNumUfsmsy0Il9LjDn5X0PpVXNt3iwayw==", + "version": "7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7.tgz", + "integrity": "sha512-03bgb1VD5gvuumNf+7fVGBzfpJPjmqV423l/WxsWk2cNQ42JD0/SsFBPhN6z8iAvdHs07/7ei77SKu7aZfq8bA==", "devOptional": true, "license": "Apache-2.0" }, - "node_modules/@prisma/engines/node_modules/@prisma/get-platform": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.4.1.tgz", - "integrity": "sha512-kN4tmkQzlgm/KtE+jTNSYjsDxxe/5i6GApPI32BN9T0tlgsgSBtDJbjGBICttkAIjsh73dXf8raPKxO/2n2UUg==", + "node_modules/@prisma/engines/node_modules/@prisma/debug": { + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.19.2.tgz", + "integrity": "sha512-lFnEZsLdFLmEVCVNdskLDCL8Uup41GDfU0LUfquw+ercJC8ODTuL0WNKgOKmYxCJVvFwf0OuZBzW99DuWmoH2A==", "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "@prisma/debug": "7.4.1" - } + "license": "Apache-2.0" }, "node_modules/@prisma/fetch-engine": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-7.4.1.tgz", - "integrity": "sha512-Z9kbuxX2bvEsyeS3LZEiEnxG0lVtZbpYgaAnPj69N+A9f2De8Lta0EoFtld9zhfERVPIQWhSWUc8himky3qYdA==", + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.19.2.tgz", + "integrity": "sha512-h4Ff4Pho+SR1S8XerMCC12X//oY2bG3Iug/fUnudfcXEUnIeRiBdXHFdGlGOgQ3HqKgosTEhkZMvGM9tWtYC+Q==", "devOptional": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "7.4.1", - "@prisma/engines-version": "7.5.0-4.55ae170b1ced7fc6ed07a15f110549408c501bb3", - "@prisma/get-platform": "7.4.1" + "@prisma/debug": "6.19.2", + "@prisma/engines-version": "7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7", + "@prisma/get-platform": "6.19.2" } }, - "node_modules/@prisma/fetch-engine/node_modules/@prisma/get-platform": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.4.1.tgz", - "integrity": "sha512-kN4tmkQzlgm/KtE+jTNSYjsDxxe/5i6GApPI32BN9T0tlgsgSBtDJbjGBICttkAIjsh73dXf8raPKxO/2n2UUg==", + "node_modules/@prisma/fetch-engine/node_modules/@prisma/debug": { + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.19.2.tgz", + "integrity": "sha512-lFnEZsLdFLmEVCVNdskLDCL8Uup41GDfU0LUfquw+ercJC8ODTuL0WNKgOKmYxCJVvFwf0OuZBzW99DuWmoH2A==", "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "@prisma/debug": "7.4.1" - } + "license": "Apache-2.0" }, "node_modules/@prisma/get-platform": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.2.0.tgz", - "integrity": "sha512-k1V0l0Td1732EHpAfi2eySTezyllok9dXb6UQanajkJQzPUGi3vO2z7jdkz67SypFTdmbnyGYxvEvYZdZsMAVA==", + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.19.2.tgz", + "integrity": "sha512-PGLr06JUSTqIvztJtAzIxOwtWKtJm5WwOG6xpsgD37Rc84FpfUBGLKz65YpJBGtkRQGXTYEFie7pYALocC3MtA==", "devOptional": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "7.2.0" + "@prisma/debug": "6.19.2" } }, "node_modules/@prisma/get-platform/node_modules/@prisma/debug": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-7.2.0.tgz", - "integrity": "sha512-YSGTiSlBAVJPzX4ONZmMotL+ozJwQjRmZweQNIq/ER0tQJKJynNkRB3kyvt37eOfsbMCXk3gnLF6J9OJ4QWftw==", + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.19.2.tgz", + "integrity": "sha512-lFnEZsLdFLmEVCVNdskLDCL8Uup41GDfU0LUfquw+ercJC8ODTuL0WNKgOKmYxCJVvFwf0OuZBzW99DuWmoH2A==", "devOptional": true, "license": "Apache-2.0" }, - "node_modules/@prisma/query-plan-executor": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@prisma/query-plan-executor/-/query-plan-executor-7.2.0.tgz", - "integrity": "sha512-EOZmNzcV8uJ0mae3DhTsiHgoNCuu1J9mULQpGCh62zN3PxPTd+qI9tJvk5jOst8WHKQNwJWR3b39t0XvfBB0WQ==", - "devOptional": true, - "license": "Apache-2.0" - }, - "node_modules/@prisma/studio-core": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/@prisma/studio-core/-/studio-core-0.13.1.tgz", - "integrity": "sha512-agdqaPEePRHcQ7CexEfkX1RvSH9uWDb6pXrZnhCRykhDFAV0/0P3d07WtfiY8hZWb7oRU4v+NkT4cGFHkQJIPg==", - "devOptional": true, - "license": "Apache-2.0", - "peerDependencies": { - "@types/react": "^18.0.0 || ^19.0.0", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, "node_modules/@standard-schema/spec": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", @@ -833,17 +689,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/react": { - "version": "19.2.14", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", - "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", - "devOptional": true, - "license": "MIT", - "peer": true, - "dependencies": { - "csstype": "^3.2.2" - } - }, "node_modules/@types/send": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", @@ -891,16 +736,6 @@ "node": ">= 8" } }, - "node_modules/aws-ssl-profiles": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", - "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">= 6.0.0" - } - }, "node_modules/balanced-match": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", @@ -1082,21 +917,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/chevrotain": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-10.5.0.tgz", - "integrity": "sha512-Pkv5rBY3+CsHOYfV5g/Vs5JY9WTHHDEKOlohI2XeygaZhUeqhAlldZ8Hz9cRmxu709bvS08YzxHdTPHhffc13A==", - "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "@chevrotain/cst-dts-gen": "10.5.0", - "@chevrotain/gast": "10.5.0", - "@chevrotain/types": "10.5.0", - "@chevrotain/utils": "10.5.0", - "lodash": "4.17.21", - "regexp-to-ast": "0.5.0" - } - }, "node_modules/chokidar": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", @@ -1216,29 +1036,6 @@ "url": "https://opencollective.com/express" } }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/csstype": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "devOptional": true, - "license": "MIT", - "peer": true - }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -1273,16 +1070,6 @@ "devOptional": true, "license": "MIT" }, - "node_modules/denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", - "devOptional": true, - "license": "Apache-2.0", - "engines": { - "node": ">=0.10" - } - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -1563,23 +1350,6 @@ "url": "https://opencollective.com/express" } }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "devOptional": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -1621,16 +1391,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/generate-function": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", - "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "is-property": "^1.0.2" - } - }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -1655,13 +1415,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-port-please": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/get-port-please/-/get-port-please-3.2.0.tgz", - "integrity": "sha512-I9QVvBw5U/hw3RmWpYKRumUeaDgxTPd401x364rLmWBJcOQ753eov1eTgzDqRG9bqFIfDc7gfzcQEWrUri3o1A==", - "devOptional": true, - "license": "MIT" - }, "node_modules/get-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", @@ -1730,27 +1483,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "devOptional": true, - "license": "ISC" - }, - "node_modules/grammex": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/grammex/-/grammex-3.1.12.tgz", - "integrity": "sha512-6ufJOsSA7LcQehIJNCO7HIBykfM7DXQual0Ny780/DEcJIpBlHRvcqEBWGPYd7hrXL2GJ3oJI1MIhaXjWmLQOQ==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/graphmatch": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/graphmatch/-/graphmatch-1.1.1.tgz", - "integrity": "sha512-5ykVn/EXM1hF0XCaWh05VbYvEiOL2lY1kBxZtaYsyvjp7cmWOU1XsAdfQBwClraEofXDT197lFbXOEVMHpvQOg==", - "devOptional": true, - "license": "MIT" - }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -1784,16 +1516,6 @@ "node": ">= 0.4" } }, - "node_modules/hono": { - "version": "4.11.4", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.4.tgz", - "integrity": "sha512-U7tt8JsyrxSRKspfhtLET79pU8K+tInj5QZXs1jSugO1Vq5dFj3kmZsRldo29mTBfcjDRVRXrEZ6LS63Cog9ZA==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=16.9.0" - } - }, "node_modules/http-errors": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", @@ -1814,13 +1536,6 @@ "url": "https://opencollective.com/express" } }, - "node_modules/http-status-codes": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/http-status-codes/-/http-status-codes-2.3.0.tgz", - "integrity": "sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==", - "devOptional": true, - "license": "MIT" - }, "node_modules/iconv-lite": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", @@ -1906,20 +1621,6 @@ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", "license": "MIT" }, - "node_modules/is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "devOptional": true, - "license": "ISC" - }, "node_modules/jiti": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", @@ -1973,23 +1674,6 @@ "safe-buffer": "^5.0.1" } }, - "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "devOptional": true, - "license": "MIT" - }, "node_modules/lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -2032,29 +1716,6 @@ "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", "license": "MIT" }, - "node_modules/long": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", - "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", - "devOptional": true, - "license": "Apache-2.0" - }, - "node_modules/lru.min": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.4.tgz", - "integrity": "sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA==", - "devOptional": true, - "license": "MIT", - "engines": { - "bun": ">=1.0.0", - "deno": ">=1.30.0", - "node": ">=8.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wellwelwel" - } - }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -2174,40 +1835,6 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, - "node_modules/mysql2": { - "version": "3.15.3", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.15.3.tgz", - "integrity": "sha512-FBrGau0IXmuqg4haEZRBfHNWB5mUARw6hNwPDXXGg0XzVJ50mr/9hb267lvpVMnhZ1FON3qNd4Xfcez1rbFwSg==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "aws-ssl-profiles": "^1.1.1", - "denque": "^2.1.0", - "generate-function": "^2.3.1", - "iconv-lite": "^0.7.0", - "long": "^5.2.1", - "lru.min": "^1.0.0", - "named-placeholders": "^1.1.3", - "seq-queue": "^0.0.5", - "sqlstring": "^2.3.2" - }, - "engines": { - "node": ">= 8.0" - } - }, - "node_modules/named-placeholders": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.6.tgz", - "integrity": "sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "lru.min": "^1.1.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/negotiator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", @@ -2409,16 +2036,6 @@ "node": ">= 0.8" } }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/path-to-regexp": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", @@ -2565,20 +2182,6 @@ "pathe": "^2.0.3" } }, - "node_modules/postgres": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.4.7.tgz", - "integrity": "sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==", - "devOptional": true, - "license": "Unlicense", - "engines": { - "node": ">=12" - }, - "funding": { - "type": "individual", - "url": "https://github.com/sponsors/porsager" - } - }, "node_modules/postgres-array": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.4.tgz", @@ -2619,58 +2222,31 @@ } }, "node_modules/prisma": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-7.4.1.tgz", - "integrity": "sha512-gDKOXwnPiMdB+uYMhMeN8jj4K7Cu3Q2wB/wUsITOoOk446HtVb8T9BZxFJ1Zop6alc89k6PMNdR2FZCpbXp/jw==", + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.19.2.tgz", + "integrity": "sha512-XTKeKxtQElcq3U9/jHyxSPgiRgeYDKxWTPOf6NkXA0dNj5j40MfEsZkMbyNpwDWCUv7YBFUl7I2VK/6ALbmhEg==", "devOptional": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@prisma/config": "7.4.1", - "@prisma/dev": "0.20.0", - "@prisma/engines": "7.4.1", - "@prisma/studio-core": "0.13.1", - "mysql2": "3.15.3", - "postgres": "3.4.7" + "@prisma/config": "6.19.2", + "@prisma/engines": "6.19.2" }, "bin": { "prisma": "build/index.js" }, "engines": { - "node": "^20.19 || ^22.12 || >=24.0" + "node": ">=18.18" }, "peerDependencies": { - "better-sqlite3": ">=9.0.0", - "typescript": ">=5.4.0" + "typescript": ">=5.1.0" }, "peerDependenciesMeta": { - "better-sqlite3": { - "optional": true - }, "typescript": { "optional": true } } }, - "node_modules/proper-lockfile": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", - "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "retry": "^0.12.0", - "signal-exit": "^3.0.2" - } - }, - "node_modules/proper-lockfile/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "devOptional": true, - "license": "ISC" - }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -2757,31 +2333,6 @@ "destr": "^2.0.3" } }, - "node_modules/react": { - "version": "19.2.4", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", - "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", - "devOptional": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "19.2.4", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", - "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", - "devOptional": true, - "license": "MIT", - "peer": true, - "dependencies": { - "scheduler": "^0.27.0" - }, - "peerDependencies": { - "react": "^19.2.4" - } - }, "node_modules/readdirp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", @@ -2796,23 +2347,6 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/regexp-to-ast": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz", - "integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/remeda": { - "version": "2.33.4", - "resolved": "https://registry.npmjs.org/remeda/-/remeda-2.33.4.tgz", - "integrity": "sha512-ygHswjlc/opg2VrtiYvUOPLjxjtdKvjGz1/plDhkG66hjNjFr1xmfrs2ClNFo/E6TyUFiwYNh53bKV26oBoMGQ==", - "devOptional": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/remeda" - } - }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", @@ -2823,16 +2357,6 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, "node_modules/router": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", @@ -2861,14 +2385,6 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "license": "MIT" }, - "node_modules/scheduler": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", - "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", - "devOptional": true, - "license": "MIT", - "peer": true - }, "node_modules/semver": { "version": "7.7.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", @@ -2907,12 +2423,6 @@ "url": "https://opencollective.com/express" } }, - "node_modules/seq-queue": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", - "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==", - "devOptional": true - }, "node_modules/serve-static": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", @@ -2938,29 +2448,6 @@ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "license": "ISC" }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", @@ -3033,19 +2520,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "devOptional": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/simple-update-notifier": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", @@ -3067,16 +2541,6 @@ "node": ">= 10.x" } }, - "node_modules/sqlstring": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", - "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/statuses": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", @@ -3086,13 +2550,6 @@ "node": ">= 0.8" } }, - "node_modules/std-env": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", - "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", - "devOptional": true, - "license": "MIT" - }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -3215,21 +2672,6 @@ "node": ">= 0.8" } }, - "node_modules/valibot": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/valibot/-/valibot-1.2.0.tgz", - "integrity": "sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg==", - "devOptional": true, - "license": "MIT", - "peerDependencies": { - "typescript": ">=5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -3239,22 +2681,6 @@ "node": ">= 0.8" } }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "devOptional": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -3270,15 +2696,13 @@ "node": ">=0.4" } }, - "node_modules/zeptomatch": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/zeptomatch/-/zeptomatch-2.1.0.tgz", - "integrity": "sha512-KiGErG2J0G82LSpniV0CtIzjlJ10E04j02VOudJsPyPwNZgGnRKQy7I1R7GMyg/QswnE4l7ohSGrQbQbjXPPDA==", - "devOptional": true, + "node_modules/zod": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", + "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", "license": "MIT", - "dependencies": { - "grammex": "^3.1.11", - "graphmatch": "^1.1.0" + "funding": { + "url": "https://github.com/sponsors/colinhacks" } } } diff --git a/package.json b/package.json index 9360a77..a63aeef 100644 --- a/package.json +++ b/package.json @@ -31,12 +31,13 @@ "jsonwebtoken": "^9.0.3", "morgan": "^1.10.1", "nodemon": "^3.1.14", - "pg": "^8.19.0" + "pg": "^8.19.0", + "zod": "^4.3.6" }, "devDependencies": { "@types/express": "^5.0.6", "@types/node": "^25.3.2", - "prisma": "^7.4.1", + "prisma": "^6.19.2", "tsx": "^4.21.0", "typescript": "^5.9.3" } From 48b145a2cda3860b348743879517d4d0ff0faf00 Mon Sep 17 00:00:00 2001 From: CrisNAC Date: Wed, 18 Mar 2026 22:25:03 -0300 Subject: [PATCH 2/6] OM-273: Cambios por npm audit fix --force --- package-lock.json | 435 ++++------------------------------------------ package.json | 2 +- 2 files changed, 36 insertions(+), 401 deletions(-) diff --git a/package-lock.json b/package-lock.json index f7e42cc..b6b643d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,80 +25,13 @@ "devDependencies": { "@types/express": "^5.0.6", "@types/node": "^25.3.2", - "prisma": "^7.4.1", + "prisma": "^6.19.2", "supertest": "^7.2.2", "tsx": "^4.21.0", "typescript": "^5.9.3", "vitest": "^4.1.0" } }, - "node_modules/@chevrotain/cst-dts-gen": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-10.5.0.tgz", - "integrity": "sha512-lhmC/FyqQ2o7pGK4Om+hzuDrm9rhFYIJ/AXoQBeongmn870Xeb0L6oGEiuR8nohFNL5sMaQEJWCxr1oIVIVXrw==", - "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "@chevrotain/gast": "10.5.0", - "@chevrotain/types": "10.5.0", - "lodash": "4.17.21" - } - }, - "node_modules/@chevrotain/gast": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-10.5.0.tgz", - "integrity": "sha512-pXdMJ9XeDAbgOWKuD1Fldz4ieCs6+nLNmyVhe2gZVqoO7v8HXuHYs5OV2EzUtbuai37TlOAQHrTDvxMnvMJz3A==", - "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "@chevrotain/types": "10.5.0", - "lodash": "4.17.21" - } - }, - "node_modules/@chevrotain/types": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-10.5.0.tgz", - "integrity": "sha512-f1MAia0x/pAVPWH/T73BJVyO2XU5tI4/iE7cnxb7tqdNTNhQI3Uq3XkqcoteTmD4t1aM0LbHCJOhgIDn07kl2A==", - "devOptional": true, - "license": "Apache-2.0" - }, - "node_modules/@chevrotain/utils": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-10.5.0.tgz", - "integrity": "sha512-hBzuU5+JjB2cqNZyszkDHZgOSrUUT8V3dhgRl8Q9Gp6dAj/H5+KILGjbhDpc3Iy9qmqlm/akuOI2ut9VUtzJxQ==", - "devOptional": true, - "license": "Apache-2.0" - }, - "node_modules/@electric-sql/pglite": { - "version": "0.3.15", - "resolved": "https://registry.npmjs.org/@electric-sql/pglite/-/pglite-0.3.15.tgz", - "integrity": "sha512-Cj++n1Mekf9ETfdc16TlDi+cDDQF0W7EcbyRHYOAeZdsAe8M/FJg18itDTSwyHfar2WIezawM9o0EKaRGVKygQ==", - "devOptional": true, - "license": "Apache-2.0" - }, - "node_modules/@electric-sql/pglite-socket": { - "version": "0.0.20", - "resolved": "https://registry.npmjs.org/@electric-sql/pglite-socket/-/pglite-socket-0.0.20.tgz", - "integrity": "sha512-J5nLGsicnD9wJHnno9r+DGxfcZWh+YJMCe0q/aCgtG6XOm9Z7fKeite8IZSNXgZeGltSigM9U/vAWZQWdgcSFg==", - "devOptional": true, - "license": "Apache-2.0", - "bin": { - "pglite-server": "dist/scripts/server.js" - }, - "peerDependencies": { - "@electric-sql/pglite": "0.3.15" - } - }, - "node_modules/@electric-sql/pglite-tools": { - "version": "0.2.20", - "resolved": "https://registry.npmjs.org/@electric-sql/pglite-tools/-/pglite-tools-0.2.20.tgz", - "integrity": "sha512-BK50ZnYa3IG7ztXhtgYf0Q7zijV32Iw1cYS8C+ThdQlwx12V5VZ9KRJ42y82Hyb4PkTxZQklVQA9JHyUlex33A==", - "devOptional": true, - "license": "Apache-2.0", - "peerDependencies": { - "@electric-sql/pglite": "0.3.15" - } - }, "node_modules/@emnapi/core": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.0.tgz", @@ -575,19 +508,6 @@ "node": ">=18" } }, - "node_modules/@hono/node-server": { - "version": "1.19.9", - "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.9.tgz", - "integrity": "sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=18.14.1" - }, - "peerDependencies": { - "hono": "^4" - } - }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", @@ -595,20 +515,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@mrleebo/prisma-ast": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/@mrleebo/prisma-ast/-/prisma-ast-0.13.1.tgz", - "integrity": "sha512-XyroGQXcHrZdvmrGJvsA9KNeOOgGMg1Vg9OlheUsBOSKznLMDl+YChxbkboRHvtFYJEMRYmlV3uoo/njCw05iw==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "chevrotain": "^10.5.0", - "lilconfig": "^2.1.0" - }, - "engines": { - "node": ">=16" - } - }, "node_modules/@napi-rs/wasm-runtime": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz", @@ -712,9 +618,9 @@ "license": "Apache-2.0" }, "node_modules/@prisma/config": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@prisma/config/-/config-7.5.0.tgz", - "integrity": "sha512-1J/9YEX7A889xM46PYg9e8VAuSL1IUmXJW3tEhMv7XQHDWlfC9YSkIw9sTYRaq5GswGlxZ+GnnyiNsUZ9JJhSQ==", + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.19.2.tgz", + "integrity": "sha512-kadBGDl+aUswv/zZMk9Mx0C8UZs1kjao8H9/JpI4Wh4SHZaM7zkTwiKn/iFLfRg+XtOAo/Z/c6pAYhijKl0nzQ==", "devOptional": true, "license": "Apache-2.0", "dependencies": { @@ -740,57 +646,51 @@ } }, "node_modules/@prisma/engines": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-7.5.0.tgz", - "integrity": "sha512-ondGRhzoaVpRWvFaQ5wH5zS1BIbhzbKqczKjCn6j3L0Zfe/LInjcEg8+xtB49AuZBX30qyx1ZtGoootUohz2pw==", + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.19.2.tgz", + "integrity": "sha512-TTkJ8r+uk/uqczX40wb+ODG0E0icVsMgwCTyTHXehaEfb0uo80M9g1aW1tEJrxmFHeOZFXdI2sTA1j1AgcHi4A==", "devOptional": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "7.5.0", - "@prisma/engines-version": "7.5.0-15.280c870be64f457428992c43c1f6d557fab6e29e", - "@prisma/fetch-engine": "7.5.0", - "@prisma/get-platform": "7.5.0" + "@prisma/debug": "6.19.2", + "@prisma/engines-version": "7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7", + "@prisma/fetch-engine": "6.19.2", + "@prisma/get-platform": "6.19.2" } }, "node_modules/@prisma/engines-version": { - "version": "7.5.0-15.280c870be64f457428992c43c1f6d557fab6e29e", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-7.5.0-15.280c870be64f457428992c43c1f6d557fab6e29e.tgz", - "integrity": "sha512-E+iRV/vbJLl8iGjVr6g/TEWokA+gjkV/doZkaQN1i/ULVdDwGnPJDfLUIFGS3BVwlG/m6L8T4x1x5isl8hGMxA==", + "version": "7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7.tgz", + "integrity": "sha512-03bgb1VD5gvuumNf+7fVGBzfpJPjmqV423l/WxsWk2cNQ42JD0/SsFBPhN6z8iAvdHs07/7ei77SKu7aZfq8bA==", "devOptional": true, "license": "Apache-2.0" }, - "node_modules/@prisma/engines/node_modules/@prisma/get-platform": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.5.0.tgz", - "integrity": "sha512-7I+2y1nu/gkEKSiHHbcZ1HPe/euGdEqJZxEEMT0246q4De1+hla0ZzlTgvaT9dHcVCgLSuCG8v39db5qUUWNgw==", + "node_modules/@prisma/engines/node_modules/@prisma/debug": { + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.19.2.tgz", + "integrity": "sha512-lFnEZsLdFLmEVCVNdskLDCL8Uup41GDfU0LUfquw+ercJC8ODTuL0WNKgOKmYxCJVvFwf0OuZBzW99DuWmoH2A==", "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "@prisma/debug": "7.5.0" - } + "license": "Apache-2.0" }, "node_modules/@prisma/fetch-engine": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-7.5.0.tgz", - "integrity": "sha512-kZCl2FV54qnyrVdnII8MI6qvt7HfU6Cbiz8dZ8PXz4f4lbSw45jEB9/gEMK2SGdiNhBKyk/Wv95uthoLhGMLYA==", + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.19.2.tgz", + "integrity": "sha512-h4Ff4Pho+SR1S8XerMCC12X//oY2bG3Iug/fUnudfcXEUnIeRiBdXHFdGlGOgQ3HqKgosTEhkZMvGM9tWtYC+Q==", "devOptional": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "7.5.0", - "@prisma/engines-version": "7.5.0-15.280c870be64f457428992c43c1f6d557fab6e29e", - "@prisma/get-platform": "7.5.0" + "@prisma/debug": "6.19.2", + "@prisma/engines-version": "7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7", + "@prisma/get-platform": "6.19.2" } }, - "node_modules/@prisma/fetch-engine/node_modules/@prisma/get-platform": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.5.0.tgz", - "integrity": "sha512-7I+2y1nu/gkEKSiHHbcZ1HPe/euGdEqJZxEEMT0246q4De1+hla0ZzlTgvaT9dHcVCgLSuCG8v39db5qUUWNgw==", + "node_modules/@prisma/fetch-engine/node_modules/@prisma/debug": { + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.19.2.tgz", + "integrity": "sha512-lFnEZsLdFLmEVCVNdskLDCL8Uup41GDfU0LUfquw+ercJC8ODTuL0WNKgOKmYxCJVvFwf0OuZBzW99DuWmoH2A==", "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "@prisma/debug": "7.5.0" - } + "license": "Apache-2.0" }, "node_modules/@prisma/get-platform": { "version": "6.19.2", @@ -809,29 +709,6 @@ "devOptional": true, "license": "Apache-2.0" }, - "node_modules/@prisma/query-plan-executor": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@prisma/query-plan-executor/-/query-plan-executor-7.2.0.tgz", - "integrity": "sha512-EOZmNzcV8uJ0mae3DhTsiHgoNCuu1J9mULQpGCh62zN3PxPTd+qI9tJvk5jOst8WHKQNwJWR3b39t0XvfBB0WQ==", - "devOptional": true, - "license": "Apache-2.0" - }, - "node_modules/@prisma/studio-core": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/@prisma/studio-core/-/studio-core-0.21.1.tgz", - "integrity": "sha512-bOGqG/eMQtKC0XVvcVLRmhWWzm/I+0QUWqAEhEBtetpuS3k3V4IWqKGUONkAIT223DNXJMxMtZp36b1FmcdPeg==", - "devOptional": true, - "license": "Apache-2.0", - "engines": { - "node": "^20.19 || ^22.12 || ^24.0", - "pnpm": "8" - }, - "peerDependencies": { - "@types/react": "^18.0.0 || ^19.0.0", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, "node_modules/@rolldown/binding-android-arm64": { "version": "1.0.0-rc.9", "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.9.tgz", @@ -1408,16 +1285,6 @@ "dev": true, "license": "MIT" }, - "node_modules/aws-ssl-profiles": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", - "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">= 6.0.0" - } - }, "node_modules/balanced-match": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", @@ -1645,21 +1512,6 @@ "node": ">=18" } }, - "node_modules/chevrotain": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-10.5.0.tgz", - "integrity": "sha512-Pkv5rBY3+CsHOYfV5g/Vs5JY9WTHHDEKOlohI2XeygaZhUeqhAlldZ8Hz9cRmxu709bvS08YzxHdTPHhffc13A==", - "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "@chevrotain/cst-dts-gen": "10.5.0", - "@chevrotain/gast": "10.5.0", - "@chevrotain/types": "10.5.0", - "@chevrotain/utils": "10.5.0", - "lodash": "4.17.21", - "regexp-to-ast": "0.5.0" - } - }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -1859,16 +1711,6 @@ "node": ">=0.4.0" } }, - "node_modules/denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", - "devOptional": true, - "license": "Apache-2.0", - "engines": { - "node": ">=0.10" - } - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -2229,23 +2071,6 @@ "url": "https://opencollective.com/express" } }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "devOptional": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/form-data": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", @@ -2905,23 +2730,6 @@ "url": "https://opencollective.com/parcel" } }, - "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "devOptional": true, - "license": "MIT" - }, "node_modules/lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -2964,29 +2772,6 @@ "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", "license": "MIT" }, - "node_modules/long": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", - "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", - "devOptional": true, - "license": "Apache-2.0" - }, - "node_modules/lru.min": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.4.tgz", - "integrity": "sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA==", - "devOptional": true, - "license": "MIT", - "engines": { - "bun": ">=1.0.0", - "deno": ">=1.30.0", - "node": ">=8.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wellwelwel" - } - }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", @@ -3139,40 +2924,6 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, - "node_modules/mysql2": { - "version": "3.15.3", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.15.3.tgz", - "integrity": "sha512-FBrGau0IXmuqg4haEZRBfHNWB5mUARw6hNwPDXXGg0XzVJ50mr/9hb267lvpVMnhZ1FON3qNd4Xfcez1rbFwSg==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "aws-ssl-profiles": "^1.1.1", - "denque": "^2.1.0", - "generate-function": "^2.3.1", - "iconv-lite": "^0.7.0", - "long": "^5.2.1", - "lru.min": "^1.0.0", - "named-placeholders": "^1.1.3", - "seq-queue": "^0.0.5", - "sqlstring": "^2.3.2" - }, - "engines": { - "node": ">= 8.0" - } - }, - "node_modules/named-placeholders": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.6.tgz", - "integrity": "sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "lru.min": "^1.1.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -3613,20 +3364,6 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/postgres": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.4.7.tgz", - "integrity": "sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==", - "devOptional": true, - "license": "Unlicense", - "engines": { - "node": ">=12" - }, - "funding": { - "type": "individual", - "url": "https://github.com/sponsors/porsager" - } - }, "node_modules/postgres-array": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.4.tgz", @@ -3673,19 +3410,15 @@ "license": "MIT" }, "node_modules/prisma": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-7.5.0.tgz", - "integrity": "sha512-n30qZpWehaYQzigLjmuPisyEsvOzHt7bZeRyg8gZ5DvJo9FGjD+gNaY59Ns3hlLD5/jZH5GBeftIss0jDbUoLg==", + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.19.2.tgz", + "integrity": "sha512-XTKeKxtQElcq3U9/jHyxSPgiRgeYDKxWTPOf6NkXA0dNj5j40MfEsZkMbyNpwDWCUv7YBFUl7I2VK/6ALbmhEg==", "devOptional": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@prisma/config": "7.5.0", - "@prisma/dev": "0.20.0", - "@prisma/engines": "7.5.0", - "@prisma/studio-core": "0.21.1", - "mysql2": "3.15.3", - "postgres": "3.4.7" + "@prisma/config": "6.19.2", + "@prisma/engines": "6.19.2" }, "bin": { "prisma": "build/index.js" @@ -3788,31 +3521,6 @@ "destr": "^2.0.3" } }, - "node_modules/react": { - "version": "19.2.4", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", - "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", - "devOptional": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "19.2.4", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", - "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", - "devOptional": true, - "license": "MIT", - "peer": true, - "dependencies": { - "scheduler": "^0.27.0" - }, - "peerDependencies": { - "react": "^19.2.4" - } - }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -3825,23 +3533,6 @@ "node": ">=8.10.0" } }, - "node_modules/regexp-to-ast": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz", - "integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/remeda": { - "version": "2.33.4", - "resolved": "https://registry.npmjs.org/remeda/-/remeda-2.33.4.tgz", - "integrity": "sha512-ygHswjlc/opg2VrtiYvUOPLjxjtdKvjGz1/plDhkG66hjNjFr1xmfrs2ClNFo/E6TyUFiwYNh53bKV26oBoMGQ==", - "devOptional": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/remeda" - } - }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", @@ -3852,16 +3543,6 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, "node_modules/rolldown": { "version": "1.0.0-rc.9", "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.9.tgz", @@ -4080,19 +3761,6 @@ "dev": true, "license": "ISC" }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "devOptional": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/simple-update-notifier": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", @@ -4124,16 +3792,6 @@ "node": ">= 10.x" } }, - "node_modules/sqlstring": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", - "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", @@ -4150,13 +3808,6 @@ "node": ">= 0.8" } }, - "node_modules/std-env": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", - "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", - "devOptional": true, - "license": "MIT" - }, "node_modules/superagent": { "version": "10.3.0", "resolved": "https://registry.npmjs.org/superagent/-/superagent-10.3.0.tgz", @@ -4600,22 +4251,6 @@ "dev": true, "license": "MIT" }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "devOptional": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/why-is-node-running": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", diff --git a/package.json b/package.json index 992b36b..8f0696e 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "devDependencies": { "@types/express": "^5.0.6", "@types/node": "^25.3.2", - "prisma": "^7.4.1", + "prisma": "^6.19.2", "supertest": "^7.2.2", "tsx": "^4.21.0", "typescript": "^5.9.3", From 52f54d74e60cae07e662ba1f328befebdb9bf3de Mon Sep 17 00:00:00 2001 From: CrisNAC Date: Wed, 18 Mar 2026 22:25:35 -0300 Subject: [PATCH 3/6] OM-273: Todoos los DTOs que se van a usar --- .../product-reviews/dtos/get-reviews.dto.ts | 19 -- .../commerce/product-reviews/dtos/index.ts | 1 - .../products/dtos/create-product.dto.ts | 53 ------ .../products/dtos/filter-product.dto.ts | 36 ---- src/modules/commerce/products/dtos/index.ts | 2 - .../global/dtos/addresses/address.dto.ts | 128 ++++++++++++++ .../global/dtos/base/base.response.dto.ts | 48 +++++ .../global/dtos/collections/collection.dto.ts | 102 +++++++++++ .../dtos/notifications/notification.dto.ts | 87 +++++++++ src/modules/global/dtos/orders/order.dto.ts | 145 +++++++++++++++ .../product-category.dto.ts | 70 ++++++++ .../product-reviews/product-review.dto.ts | 142 +++++++++++++++ .../dtos/product-tags/product-tag.dto.ts | 70 ++++++++ .../dtos/products/product.request.dto.ts | 165 ++++++++++++++++++ .../dtos/products/product.response.dto.ts | 87 +++++++++ .../dtos/shipping-zones/shipping-zone.dto.ts | 119 +++++++++++++ .../store-categories/store-category.dto.ts | 70 ++++++++ .../global/dtos/stores/store.request.dto.ts | 159 +++++++++++++++++ .../global/dtos/stores/store.response.dto.ts | 57 ++++++ .../global/dtos/users/user.request.dto.ts | 99 +++++++++++ .../global/dtos/users/user.response.dto.ts | 33 ++++ .../global/dtos/wishlists/wishlist.dto.ts | 113 ++++++++++++ 22 files changed, 1694 insertions(+), 111 deletions(-) delete mode 100644 src/modules/commerce/product-reviews/dtos/get-reviews.dto.ts delete mode 100644 src/modules/commerce/product-reviews/dtos/index.ts delete mode 100644 src/modules/commerce/products/dtos/create-product.dto.ts delete mode 100644 src/modules/commerce/products/dtos/filter-product.dto.ts delete mode 100644 src/modules/commerce/products/dtos/index.ts create mode 100644 src/modules/global/dtos/addresses/address.dto.ts create mode 100644 src/modules/global/dtos/base/base.response.dto.ts create mode 100644 src/modules/global/dtos/collections/collection.dto.ts create mode 100644 src/modules/global/dtos/notifications/notification.dto.ts create mode 100644 src/modules/global/dtos/orders/order.dto.ts create mode 100644 src/modules/global/dtos/product-categories/product-category.dto.ts create mode 100644 src/modules/global/dtos/product-reviews/product-review.dto.ts create mode 100644 src/modules/global/dtos/product-tags/product-tag.dto.ts create mode 100644 src/modules/global/dtos/products/product.request.dto.ts create mode 100644 src/modules/global/dtos/products/product.response.dto.ts create mode 100644 src/modules/global/dtos/shipping-zones/shipping-zone.dto.ts create mode 100644 src/modules/global/dtos/store-categories/store-category.dto.ts create mode 100644 src/modules/global/dtos/stores/store.request.dto.ts create mode 100644 src/modules/global/dtos/stores/store.response.dto.ts create mode 100644 src/modules/global/dtos/users/user.request.dto.ts create mode 100644 src/modules/global/dtos/users/user.response.dto.ts create mode 100644 src/modules/global/dtos/wishlists/wishlist.dto.ts diff --git a/src/modules/commerce/product-reviews/dtos/get-reviews.dto.ts b/src/modules/commerce/product-reviews/dtos/get-reviews.dto.ts deleted file mode 100644 index e035483..0000000 --- a/src/modules/commerce/product-reviews/dtos/get-reviews.dto.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { z } from "zod"; - -export const GetReviewsDTO = z.object({ - page: z - .string() - .transform(Number) - .pipe(z.number().int().positive("page debe ser mayor a 0")) - .optional() - .default("1"), - - limit: z - .string() - .transform(Number) - .pipe(z.number().int().min(1).max(100, "limit no puede superar 100")) - .optional() - .default("10") -}); - -export type GetReviewsDTOType = z.infer; \ No newline at end of file diff --git a/src/modules/commerce/product-reviews/dtos/index.ts b/src/modules/commerce/product-reviews/dtos/index.ts deleted file mode 100644 index c366ec6..0000000 --- a/src/modules/commerce/product-reviews/dtos/index.ts +++ /dev/null @@ -1 +0,0 @@ -import { GetReviewsDTO } from "./get-reviews.dto"; \ No newline at end of file diff --git a/src/modules/commerce/products/dtos/create-product.dto.ts b/src/modules/commerce/products/dtos/create-product.dto.ts deleted file mode 100644 index b182d7e..0000000 --- a/src/modules/commerce/products/dtos/create-product.dto.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { z } from "zod"; - -export const CreateProductDTO = z.object({ - name: z - .string({ required_error: "name es requerido" }) - .min(1, "name no puede estar vacío") - .max(100, "name no puede superar 100 caracteres"), - - price: z - .number({ required_error: "price es requerido", invalid_type_error: "price debe ser número" }) - .positive("price debe ser mayor a 0"), - - categoryId: z - .number({ required_error: "categoryId es requerido", invalid_type_error: "categoryId debe ser número" }) - .int("categoryId debe ser entero") - .positive(), - - description: z - .string() - .max(2000, "description no puede superar 2000 caracteres") - .nullable() - .optional(), - - quantity: z - .number() - .int("quantity debe ser entero") - .min(0, "quantity no puede ser negativo") - .nullable() - .optional(), - - tags: z - .union([ - z.array(z.number().int().positive()), - z.string().transform((val) => - val.split(",").map((v) => { - const n = Number(v.trim()); - if (!Number.isInteger(n) || n <= 0) throw new Error("tag inválido"); - return n; - }) - ) - ]) - .optional() - .default([]), - - visible: z - .union([ - z.boolean(), - z.enum(["true", "false", "1", "0"]).transform((v) => v === "true" || v === "1") - ]) - .optional() -}); - -export type CreateProductDTOType = z.infer; \ No newline at end of file diff --git a/src/modules/commerce/products/dtos/filter-product.dto.ts b/src/modules/commerce/products/dtos/filter-product.dto.ts deleted file mode 100644 index 299aff0..0000000 --- a/src/modules/commerce/products/dtos/filter-product.dto.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { z } from "zod"; - -export const FilterProductDTO = z.object({ - name: z.string().optional(), - - category: z - .string() - .transform(Number) - .pipe(z.number().int().positive("category debe ser un ID válido")) - .optional(), - - visible: z - .enum(["true", "false"]) - .transform((v) => v === "true") - .optional(), - - minPrice: z - .string() - .transform(Number) - .pipe(z.number().positive("minPrice debe ser mayor a 0")) - .optional(), - - maxPrice: z - .string() - .transform(Number) - .pipe(z.number().positive("maxPrice debe ser mayor a 0")) - .optional() -}).refine( - (data) => - data.minPrice === undefined || - data.maxPrice === undefined || - data.minPrice <= data.maxPrice, - { message: "minPrice no puede ser mayor que maxPrice", path: ["minPrice"] } -); - -export type FilterProductDTOType = z.infer; \ No newline at end of file diff --git a/src/modules/commerce/products/dtos/index.ts b/src/modules/commerce/products/dtos/index.ts deleted file mode 100644 index 788f649..0000000 --- a/src/modules/commerce/products/dtos/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -import { CreateProductDTO } from "./create-product.dto"; -import { FilterProductDTO } from "./filter-product.dto"; \ No newline at end of file diff --git a/src/modules/global/dtos/addresses/address.dto.ts b/src/modules/global/dtos/addresses/address.dto.ts new file mode 100644 index 0000000..fb5a5a3 --- /dev/null +++ b/src/modules/global/dtos/addresses/address.dto.ts @@ -0,0 +1,128 @@ +import { z } from "zod"; +import { BaseResponseDTO } from "../base/base.response.dto.js"; + +// ─── REQUEST ───────────────────────────────────────────────────── +export const CreateAddressDTO = z.object({ + fk_user: z + .number({ error: "fk_user es requerido" }) + .int() + .positive("fk_user debe ser un ID válido"), + + fk_store: z + .number() + .int() + .positive("fk_store debe ser un ID válido") + .nullable() + .optional(), + + address: z + .string({ error: "address es requerido" }) + .min(1, "address no puede estar vacío"), + + city: z + .string({ error: "city es requerido" }) + .min(1, "city no puede estar vacío") + .max(100, "city no puede superar 100 caracteres"), + + region: z + .string({ error: "region es requerida" }) + .min(1, "region no puede estar vacía") + .max(100, "region no puede superar 100 caracteres"), + + postal_code: z + .string() + .max(20, "postal_code no puede superar 20 caracteres") + .nullable() + .optional() +}); + +export type CreateAddressDTOType = z.infer; + +export const UpdateAddressDTO = z + .object({ + address: z.string().min(1, "address no puede estar vacío").optional(), + + city: z + .string() + .min(1, "city no puede estar vacío") + .max(100, "city no puede superar 100 caracteres") + .optional(), + + region: z + .string() + .min(1, "region no puede estar vacía") + .max(100, "region no puede superar 100 caracteres") + .optional(), + + postal_code: z + .string() + .max(20, "postal_code no puede superar 20 caracteres") + .nullable() + .optional() + }) + .refine((data) => Object.keys(data).length > 0, { + message: "Debe enviar al menos un campo para actualizar" + }); + +export type UpdateAddressDTOType = z.infer; + +export const FilterAddressDTO = z.object({ + fk_user: z + .string() + .transform(Number) + .pipe(z.number().int().positive("fk_user debe ser un ID válido")) + .optional(), + + city: z.string().optional(), + region: z.string().optional(), + + page: z + .string() + .transform(Number) + .pipe(z.number().int().positive("page debe ser mayor a 0")) + .optional() + .default(1), + + limit: z + .string() + .transform(Number) + .pipe(z.number().int().min(1).max(100, "limit no puede superar 100")) + .optional() + .default(10) +}); + +export type FilterAddressDTOType = z.infer; + +// ─── RESPONSE ──────────────────────────────────────────────────── +export class AddressResponseDTO extends BaseResponseDTO { + id_address: number; + fk_user: number; + fk_store: number | null; + address: string; + city: string; + region: string; + postal_code: string | null; + + constructor(data: any) { + super({ + id: data.id_address, + created_at: data.created_at, + updated_at: data.updated_at + }); + this.id_address = data.id_address; + this.fk_user = data.fk_user; + this.fk_store = data.fk_store ?? null; + this.address = data.address; + this.city = data.city; + this.region = data.region; + this.postal_code = data.postal_code ?? null; + } + + static map(data: any): AddressResponseDTO { + return new AddressResponseDTO(data); + } + + static mapList(data: any[]): AddressResponseDTO[] { + return data.map(AddressResponseDTO.map); + } +} diff --git a/src/modules/global/dtos/base/base.response.dto.ts b/src/modules/global/dtos/base/base.response.dto.ts new file mode 100644 index 0000000..d3403d1 --- /dev/null +++ b/src/modules/global/dtos/base/base.response.dto.ts @@ -0,0 +1,48 @@ + +export class BaseResponseDTO { + id: number; + created_at: Date; + updated_at: Date; + + constructor(data: { id: number; created_at: Date; updated_at: Date }) { + this.id = data.id; + this.created_at = data.created_at; + this.updated_at = data.updated_at; + } +} + + +export class PaginatedResponseDTO { + content: T[]; + total_elements: number; + total_pages: number; + size: number; + page: number; + + constructor(data: { + content: T[]; + total_elements: number; + size: number; + page: number; + }) { + this.content = data.content; + this.total_elements = data.total_elements; + this.total_pages = Math.ceil(data.total_elements / data.size); + this.size = data.size; + this.page = data.page; + } + + static from( + items: T[], + totalCount: number, + page: number, + limit: number + ): PaginatedResponseDTO { + return new PaginatedResponseDTO({ + content: items, + total_elements: totalCount, + size: limit, + page + }); + } +} diff --git a/src/modules/global/dtos/collections/collection.dto.ts b/src/modules/global/dtos/collections/collection.dto.ts new file mode 100644 index 0000000..c04fefe --- /dev/null +++ b/src/modules/global/dtos/collections/collection.dto.ts @@ -0,0 +1,102 @@ +import { z } from "zod"; +import { BaseResponseDTO } from "../base/base.response.dto.js"; + +// ─── REQUEST ───────────────────────────────────────────────────── +export const CreateCollectionDTO = z.object({ + fk_store: z + .number({ error: "fk_store es requerido" }) + .int() + .positive("fk_store debe ser un ID válido"), + + title: z + .string({ error: "title es requerido" }) + .min(1, "title no puede estar vacío") + .max(100, "title no puede superar 100 caracteres"), + + description: z + .string() + .max(2000, "description no puede superar 2000 caracteres") + .nullable() + .optional(), + + productIds: z + .array(z.number().int().positive("Cada productId debe ser un ID válido")) + .optional() + .default([]) +}); + +export type CreateCollectionDTOType = z.infer; + +export const UpdateCollectionDTO = z + .object({ + title: z + .string() + .min(1, "title no puede estar vacío") + .max(100, "title no puede superar 100 caracteres") + .optional(), + + description: z + .string() + .max(2000, "description no puede superar 2000 caracteres") + .nullable() + .optional() + }) + .refine((data) => Object.keys(data).length > 0, { + message: "Debe enviar al menos un campo para actualizar" + }); + +export type UpdateCollectionDTOType = z.infer; + +export const FilterCollectionDTO = z.object({ + title: z.string().optional(), + + fk_store: z + .string() + .transform(Number) + .pipe(z.number().int().positive("fk_store debe ser un ID válido")) + .optional(), + + page: z + .string() + .transform(Number) + .pipe(z.number().int().positive("page debe ser mayor a 0")) + .optional() + .default(1), + + limit: z + .string() + .transform(Number) + .pipe(z.number().int().min(1).max(100, "limit no puede superar 100")) + .optional() + .default(10) +}); + +export type FilterCollectionDTOType = z.infer; + +// ─── RESPONSE ──────────────────────────────────────────────────── +export class CollectionResponseDTO extends BaseResponseDTO { + id_collection: number; + fk_store: number; + title: string; + description: string | null; + + constructor(data: any) { + super({ + id: data.id_collection, + created_at: data.created_at, + updated_at: data.updated_at + }); + this.id_collection = data.id_collection; + this.fk_store = data.fk_store; + this.title = data.title; + this.description = data.description ?? null; + } + + static map(data: any): CollectionResponseDTO { + return new CollectionResponseDTO(data); + } + + static mapList(data: any[]): CollectionResponseDTO[] { + return data.map(CollectionResponseDTO.map); + } +} diff --git a/src/modules/global/dtos/notifications/notification.dto.ts b/src/modules/global/dtos/notifications/notification.dto.ts new file mode 100644 index 0000000..65a6670 --- /dev/null +++ b/src/modules/global/dtos/notifications/notification.dto.ts @@ -0,0 +1,87 @@ +import { z } from "zod"; +import { BaseResponseDTO } from "../base/base.response.dto.js"; + +// ─── REQUEST ───────────────────────────────────────────────────── +export const CreateNotificationDTO = z.object({ + fk_user: z + .number({ error: "fk_user es requerido" }) + .int() + .positive("fk_user debe ser un ID válido"), + + title: z + .string({ error: "title es requerido" }) + .min(1, "title no puede estar vacío") + .max(100, "title no puede superar 100 caracteres"), + + message: z + .string() + .max(2000, "message no puede superar 2000 caracteres") + .nullable() + .optional() +}); + +export type CreateNotificationDTOType = z.infer; + +export const UpdateNotificationDTO = z + .object({ + read: z.boolean().optional() + }) + .refine((data) => Object.keys(data).length > 0, { + message: "Debe enviar al menos un campo para actualizar" + }); + +export type UpdateNotificationDTOType = z.infer; + +export const FilterNotificationDTO = z.object({ + read: z + .enum(["true", "false"]) + .transform((v) => v === "true") + .optional(), + + page: z + .string() + .transform(Number) + .pipe(z.number().int().positive("page debe ser mayor a 0")) + .optional() + .default(1), + + limit: z + .string() + .transform(Number) + .pipe(z.number().int().min(1).max(100, "limit no puede superar 100")) + .optional() + .default(10) +}); + +export type FilterNotificationDTOType = z.infer; + +// ─── RESPONSE ──────────────────────────────────────────────────── +export class NotificationResponseDTO extends BaseResponseDTO { + id_notification: number; + fk_user: number; + title: string; + message: string | null; + read: boolean; + + constructor(data: any) { + super({ + id: data.id_notification, + created_at: data.created_at, + updated_at: data.updated_at + }); + this.id_notification = data.id_notification; + this.fk_user = data.fk_user; + this.title = data.title; + this.message = data.message ?? null; + this.read = data.read; + // status excluido intencionalmente + } + + static map(data: any): NotificationResponseDTO { + return new NotificationResponseDTO(data); + } + + static mapList(data: any[]): NotificationResponseDTO[] { + return data.map(NotificationResponseDTO.map); + } +} diff --git a/src/modules/global/dtos/orders/order.dto.ts b/src/modules/global/dtos/orders/order.dto.ts new file mode 100644 index 0000000..7196019 --- /dev/null +++ b/src/modules/global/dtos/orders/order.dto.ts @@ -0,0 +1,145 @@ +import { z } from "zod"; +import { BaseResponseDTO } from "../base/base.response.dto.js"; + +// ─── REQUEST ───────────────────────────────────────────────────── +const OrderItemRequestDTO = z.object({ + fk_product: z + .number({ error: "fk_product es requerido" }) + .int() + .positive("fk_product debe ser un ID válido"), + + quantity: z + .number({ error: "quantity es requerido" }) + .int("quantity debe ser entero") + .min(1, "quantity debe ser al menos 1") +}); + +export const CreateOrderDTO = z.object({ + fk_address: z + .number({ error: "fk_address es requerido" }) + .int() + .positive("fk_address debe ser un ID válido"), + + fk_wishlist: z + .number({ error: "fk_wishlist es requerido" }) + .int() + .positive("fk_wishlist debe ser un ID válido"), + + notes: z + .string() + .max(2000, "notes no puede superar 2000 caracteres") + .nullable() + .optional(), + + items: z + .array(OrderItemRequestDTO) + .min(1, "El pedido debe tener al menos un producto") +}); + +export type CreateOrderDTOType = z.infer; + +export const UpdateOrderDTO = z + .object({ + order_status: z + .enum(["PENDING", "PROCESSING", "SHIPPED", "DELIVERED", "CANCELLED"], { + error: "order_status debe ser PENDING, PROCESSING, SHIPPED, DELIVERED o CANCELLED" + }) + .optional(), + + notes: z + .string() + .max(2000, "notes no puede superar 2000 caracteres") + .nullable() + .optional(), + + fk_address: z + .number() + .int() + .positive("fk_address debe ser un ID válido") + .optional() + }) + .refine((data) => Object.keys(data).length > 0, { + message: "Debe enviar al menos un campo para actualizar" + }); + +export type UpdateOrderDTOType = z.infer; + +export const FilterOrderDTO = z.object({ + fk_user: z + .string() + .transform(Number) + .pipe(z.number().int().positive("fk_user debe ser un ID válido")) + .optional(), + + order_status: z + .enum(["PENDING", "PROCESSING", "SHIPPED", "DELIVERED", "CANCELLED"], { + error: "order_status debe ser PENDING, PROCESSING, SHIPPED, DELIVERED o CANCELLED" + }) + .optional(), + + page: z + .string() + .transform(Number) + .pipe(z.number().int().positive("page debe ser mayor a 0")) + .optional() + .default(1), + + limit: z + .string() + .transform(Number) + .pipe(z.number().int().min(1).max(100, "limit no puede superar 100")) + .optional() + .default(10) +}); + +export type FilterOrderDTOType = z.infer; + +// ─── RESPONSE ──────────────────────────────────────────────────── +export class OrderItemResponseDTO { + id_order_item: number; + fk_product: number; + quantity: number; + subtotal: number; + + constructor(data: any) { + this.id_order_item = data.id_order_item; + this.fk_product = data.fk_product; + this.quantity = data.quantity; + this.subtotal = Number(data.subtotal); + } +} + +export class OrderResponseDTO extends BaseResponseDTO { + id_order: number; + fk_user: number; + fk_address: number; + fk_wishlist: number; + total: number; + order_status: string; + notes: string | null; + order_items: OrderItemResponseDTO[]; + + constructor(data: any) { + super({ + id: data.id_order, + created_at: data.created_at, + updated_at: data.updated_at + }); + this.id_order = data.id_order; + this.fk_user = data.fk_user; + this.fk_address = data.fk_address; + this.fk_wishlist = data.fk_wishlist; + this.total = Number(data.total); + this.order_status = data.order_status; + this.notes = data.notes ?? null; + this.order_items = data.order_items?.map((i: any) => new OrderItemResponseDTO(i)) ?? []; + } + + static map(data: any): OrderResponseDTO { + return new OrderResponseDTO(data); + } + + static mapList(data: any[]): OrderResponseDTO[] { + return data.map(OrderResponseDTO.map); + } +} diff --git a/src/modules/global/dtos/product-categories/product-category.dto.ts b/src/modules/global/dtos/product-categories/product-category.dto.ts new file mode 100644 index 0000000..1b0c49b --- /dev/null +++ b/src/modules/global/dtos/product-categories/product-category.dto.ts @@ -0,0 +1,70 @@ +import { z } from "zod"; +import { BaseResponseDTO } from "../base/base.response.dto.js"; + +// ─── REQUEST ───────────────────────────────────────────────────── +export const CreateProductCategoryDTO = z.object({ + name: z + .string({ error: "name es requerido" }) + .min(1, "name no puede estar vacío") + .max(100, "name no puede superar 100 caracteres") +}); + +export type CreateProductCategoryDTOType = z.infer; + +export const UpdateProductCategoryDTO = z + .object({ + name: z + .string() + .min(1, "name no puede estar vacío") + .max(100, "name no puede superar 100 caracteres") + .optional() + }) + .refine((data) => Object.keys(data).length > 0, { + message: "Debe enviar al menos un campo para actualizar" + }); + +export type UpdateProductCategoryDTOType = z.infer; + +export const FilterProductCategoryDTO = z.object({ + name: z.string().optional(), + + page: z + .string() + .transform(Number) + .pipe(z.number().int().positive("page debe ser mayor a 0")) + .optional() + .default(1), + + limit: z + .string() + .transform(Number) + .pipe(z.number().int().min(1).max(100, "limit no puede superar 100")) + .optional() + .default(10) +}); + +export type FilterProductCategoryDTOType = z.infer; + +// ─── RESPONSE ──────────────────────────────────────────────────── +export class ProductCategoryResponseDTO extends BaseResponseDTO { + id_product_category: number; + name: string; + + constructor(data: any) { + super({ + id: data.id_product_category, + created_at: data.created_at, + updated_at: data.updated_at + }); + this.id_product_category = data.id_product_category; + this.name = data.name; + } + + static map(data: any): ProductCategoryResponseDTO { + return new ProductCategoryResponseDTO(data); + } + + static mapList(data: any[]): ProductCategoryResponseDTO[] { + return data.map(ProductCategoryResponseDTO.map); + } +} diff --git a/src/modules/global/dtos/product-reviews/product-review.dto.ts b/src/modules/global/dtos/product-reviews/product-review.dto.ts new file mode 100644 index 0000000..1a9519b --- /dev/null +++ b/src/modules/global/dtos/product-reviews/product-review.dto.ts @@ -0,0 +1,142 @@ +import { z } from "zod"; +import { BaseResponseDTO } from "../base/base.response.dto.js"; + +// ─── REQUEST ───────────────────────────────────────────────────── +export const CreateProductReviewDTO = z.object({ + rating: z + .number({ error: "rating es requerido" }) + .int("rating debe ser entero") + .min(1, "rating mínimo es 1") + .max(5, "rating máximo es 5"), + + comment: z + .string() + .max(2000, "comment no puede superar 2000 caracteres") + .nullable() + .optional() +}); + +export type CreateProductReviewDTOType = z.infer; + +export const UpdateProductReviewDTO = z + .object({ + rating: z + .number({ error: "rating debe ser número" }) + .int("rating debe ser entero") + .min(1, "rating mínimo es 1") + .max(5, "rating máximo es 5") + .optional(), + + comment: z + .string() + .max(2000, "comment no puede superar 2000 caracteres") + .nullable() + .optional() + }) + .refine((data) => Object.keys(data).length > 0, { + message: "Debe enviar al menos un campo para actualizar" + }); + +export type UpdateProductReviewDTOType = z.infer; + +export const FilterProductReviewDTO = z.object({ + fk_product: z + .string() + .transform(Number) + .pipe(z.number().int().positive("fk_product debe ser un ID válido")) + .optional(), + + approved: z + .enum(["true", "false"]) + .transform((v) => v === "true") + .optional(), + + minRating: z + .string() + .transform(Number) + .pipe(z.number().int().min(1).max(5, "minRating máximo es 5")) + .optional(), + + maxRating: z + .string() + .transform(Number) + .pipe(z.number().int().min(1).max(5, "maxRating máximo es 5")) + .optional(), + + page: z + .string() + .transform(Number) + .pipe(z.number().int().positive("page debe ser mayor a 0")) + .optional() + .default(1), + + limit: z + .string() + .transform(Number) + .pipe(z.number().int().min(1).max(100, "limit no puede superar 100")) + .optional() + .default(10) +}); + +export type FilterProductReviewDTOType = z.infer; + +// ─── RESPONSE ──────────────────────────────────────────────────── +export class ProductReviewResponseDTO extends BaseResponseDTO { + id_product_review: number; + fk_product: number; + fk_user: number; + customer_name: string; + rating: number; + comment: string | null; + is_verified: boolean; + + constructor(data: any) { + super({ + id: data.id_product_review, + created_at: data.created_at, + updated_at: data.updated_at + }); + this.id_product_review = data.id_product_review; + this.fk_product = data.fk_product; + this.fk_user = data.fk_user; + this.customer_name = data.user?.name ?? ""; + this.rating = data.rating; + this.comment = data.comment ?? null; + this.is_verified = data.approved ?? false; + // status excluido intencionalmente + } + + static map(data: any): ProductReviewResponseDTO { + return new ProductReviewResponseDTO(data); + } + + static mapList(data: any[]): ProductReviewResponseDTO[] { + return data.map(ProductReviewResponseDTO.map); + } +} + +// ─── REVIEWS CON STATS (GET /products/:id/reviews) ─────────────── +export class ProductReviewsWithStatsResponseDTO { + stats: { + average_rating: number | null; + total_reviews: number; + verified_reviews: number; + }; + pagination: { + page: number; + limit: number; + total_reviews: number; + total_pages: number; + }; + reviews: ProductReviewResponseDTO[]; + + constructor(data: { + stats: { average_rating: number | null; total_reviews: number; verified_reviews: number }; + pagination: { page: number; limit: number; total_reviews: number; total_pages: number }; + reviews: any[]; + }) { + this.stats = data.stats; + this.pagination = data.pagination; + this.reviews = ProductReviewResponseDTO.mapList(data.reviews); + } +} diff --git a/src/modules/global/dtos/product-tags/product-tag.dto.ts b/src/modules/global/dtos/product-tags/product-tag.dto.ts new file mode 100644 index 0000000..9d3ab11 --- /dev/null +++ b/src/modules/global/dtos/product-tags/product-tag.dto.ts @@ -0,0 +1,70 @@ +import { z } from "zod"; +import { BaseResponseDTO } from "../base/base.response.dto.js"; + +// ─── REQUEST ───────────────────────────────────────────────────── +export const CreateProductTagDTO = z.object({ + name: z + .string({ error: "name es requerido" }) + .min(1, "name no puede estar vacío") + .max(20, "name no puede superar 20 caracteres") +}); + +export type CreateProductTagDTOType = z.infer; + +export const UpdateProductTagDTO = z + .object({ + name: z + .string() + .min(1, "name no puede estar vacío") + .max(20, "name no puede superar 20 caracteres") + .optional() + }) + .refine((data) => Object.keys(data).length > 0, { + message: "Debe enviar al menos un campo para actualizar" + }); + +export type UpdateProductTagDTOType = z.infer; + +export const FilterProductTagDTO = z.object({ + name: z.string().optional(), + + page: z + .string() + .transform(Number) + .pipe(z.number().int().positive("page debe ser mayor a 0")) + .optional() + .default(1), + + limit: z + .string() + .transform(Number) + .pipe(z.number().int().min(1).max(100, "limit no puede superar 100")) + .optional() + .default(10) +}); + +export type FilterProductTagDTOType = z.infer; + +// ─── RESPONSE ──────────────────────────────────────────────────── +export class ProductTagResponseDTO extends BaseResponseDTO { + id_product_tag: number; + name: string; + + constructor(data: any) { + super({ + id: data.id_product_tag, + created_at: data.created_at, + updated_at: data.updated_at + }); + this.id_product_tag = data.id_product_tag; + this.name = data.name; + } + + static map(data: any): ProductTagResponseDTO { + return new ProductTagResponseDTO(data); + } + + static mapList(data: any[]): ProductTagResponseDTO[] { + return data.map(ProductTagResponseDTO.map); + } +} diff --git a/src/modules/global/dtos/products/product.request.dto.ts b/src/modules/global/dtos/products/product.request.dto.ts new file mode 100644 index 0000000..75de162 --- /dev/null +++ b/src/modules/global/dtos/products/product.request.dto.ts @@ -0,0 +1,165 @@ +import { z } from "zod"; + +// ─── CREATE ────────────────────────────────────────────────────── +export const CreateProductDTO = z.object({ + name: z + .string({ error: "name es requerido" }) + .min(1, "name no puede estar vacío") + .max(100, "name no puede superar 100 caracteres"), + + price: z + .number({ error: "price es requerido" }) + .positive("price debe ser mayor a 0"), + + categoryId: z + .number({ error: "categoryId es requerido" }) + .int("categoryId debe ser entero") + .positive("categoryId debe ser un ID válido"), + + description: z + .string() + .max(2000, "description no puede superar 2000 caracteres") + .nullable() + .optional(), + + quantity: z + .number() + .int("quantity debe ser entero") + .min(0, "quantity no puede ser negativo") + .nullable() + .optional(), + + tags: z + .union([ + z.array(z.number().int().positive()), + z.string().transform((val) => + val.split(",").map((v) => { + const n = Number(v.trim()); + if (!Number.isInteger(n) || n <= 0) throw new Error("tag inválido"); + return n; + }) + ) + ]) + .optional() + .default([]), + + visible: z + .union([ + z.boolean(), + z.enum(["true", "false", "1", "0"]).transform((v) => v === "true" || v === "1") + ]) + .optional() +}); + +export type CreateProductDTOType = z.infer; + +// ─── UPDATE ────────────────────────────────────────────────────── +export const UpdateProductDTO = z + .object({ + name: z + .string() + .min(1, "name no puede estar vacío") + .max(100, "name no puede superar 100 caracteres") + .optional(), + + price: z + .number({ error: "price debe ser número" }) + .positive("price debe ser mayor a 0") + .optional(), + + categoryId: z + .number({ error: "categoryId debe ser número" }) + .int() + .positive("categoryId debe ser un ID válido") + .optional(), + + description: z + .string() + .max(2000, "description no puede superar 2000 caracteres") + .nullable() + .optional(), + + quantity: z + .number() + .int("quantity debe ser entero") + .min(0, "quantity no puede ser negativo") + .nullable() + .optional(), + + tags: z + .union([ + z.array(z.number().int().positive()), + z.string().transform((val) => + val.split(",").map((v) => { + const n = Number(v.trim()); + if (!Number.isInteger(n) || n <= 0) throw new Error("tag inválido"); + return n; + }) + ) + ]) + .optional(), + + visible: z + .union([ + z.boolean(), + z.enum(["true", "false", "1", "0"]).transform((v) => v === "true" || v === "1") + ]) + .optional() + }) + .refine((data) => Object.keys(data).length > 0, { + message: "Debe enviar al menos un campo para actualizar" + }); + +export type UpdateProductDTOType = z.infer; + +// ─── FILTER ────────────────────────────────────────────────────── +export const FilterProductDTO = z + .object({ + name: z.string().optional(), + + categoryId: z + .string() + .transform(Number) + .pipe(z.number().int().positive("categoryId debe ser un ID válido")) + .optional(), + + visible: z + .enum(["true", "false"]) + .transform((v) => v === "true") + .optional(), + + minPrice: z + .string() + .transform(Number) + .pipe(z.number().positive("minPrice debe ser mayor a 0")) + .optional(), + + maxPrice: z + .string() + .transform(Number) + .pipe(z.number().positive("maxPrice debe ser mayor a 0")) + .optional(), + + page: z + .string() + .transform(Number) + .pipe(z.number().int().positive("page debe ser mayor a 0")) + .optional() + .default(1), + + limit: z + .string() + .transform(Number) + .pipe(z.number().int().min(1).max(100, "limit no puede superar 100")) + .optional() + .default(10) + }) + .refine( + (data) => + data.minPrice === undefined || + data.maxPrice === undefined || + data.minPrice <= data.maxPrice, + { message: "minPrice no puede ser mayor que maxPrice", path: ["minPrice"] } + ); + +export type FilterProductDTOType = z.infer; diff --git a/src/modules/global/dtos/products/product.response.dto.ts b/src/modules/global/dtos/products/product.response.dto.ts new file mode 100644 index 0000000..c2ed45a --- /dev/null +++ b/src/modules/global/dtos/products/product.response.dto.ts @@ -0,0 +1,87 @@ +import { BaseResponseDTO } from "../base/base.response.dto.js"; + +// ─── NESTED DTOs ───────────────────────────────────────────────── +export class ProductCategoryNestedDTO { + id_product_category: number; + name: string; + + constructor(data: any) { + this.id_product_category = data.id_product_category; + this.name = data.name; + } +} + +export class ProductTagNestedDTO { + id_product_tag: number; + name: string; + + constructor(data: any) { + this.id_product_tag = data.id_product_tag; + this.name = data.name; + } +} + +// ─── PRODUCT RESPONSE DTO ──────────────────────────────────────── +export class ProductResponseDTO extends BaseResponseDTO { + id_product: number; + name: string; + description: string | null; + price: number; + quantity: number | null; + visible: boolean; + fk_store: number; + product_category: ProductCategoryNestedDTO | null; + tags: ProductTagNestedDTO[]; + + constructor(data: any) { + super({ + id: data.id_product, + created_at: data.created_at, + updated_at: data.updated_at + }); + this.id_product = data.id_product; + this.name = data.name; + this.description = data.description ?? null; + this.price = Number(data.price); + this.quantity = data.quantity ?? null; + this.visible = data.visible; + this.fk_store = data.fk_store; + this.product_category = data.product_category + ? new ProductCategoryNestedDTO(data.product_category) + : null; + this.tags = + data.product_tag_relations?.map( + (r: any) => new ProductTagNestedDTO(r.product_tag) + ) ?? []; + // status excluido intencionalmente + } + + static map(data: any): ProductResponseDTO { + return new ProductResponseDTO(data); + } + + static mapList(data: any[]): ProductResponseDTO[] { + return data.map(ProductResponseDTO.map); + } +} + +// ─── PRODUCT WITH REVIEWS STATS ────────────────────────────────── +// Usado en GET /products/:id +export class ProductDetailResponseDTO extends ProductResponseDTO { + average_rating: number | null; + review_count: number; + + constructor(data: any, averageRating: number | null, reviewCount: number) { + super(data); + this.average_rating = averageRating; + this.review_count = reviewCount; + } + + static mapWithStats( + data: any, + averageRating: number | null, + reviewCount: number + ): ProductDetailResponseDTO { + return new ProductDetailResponseDTO(data, averageRating, reviewCount); + } +} diff --git a/src/modules/global/dtos/shipping-zones/shipping-zone.dto.ts b/src/modules/global/dtos/shipping-zones/shipping-zone.dto.ts new file mode 100644 index 0000000..af81430 --- /dev/null +++ b/src/modules/global/dtos/shipping-zones/shipping-zone.dto.ts @@ -0,0 +1,119 @@ +import { z } from "zod"; +import { BaseResponseDTO } from "../base/base.response.dto.js"; + +// ─── REQUEST ───────────────────────────────────────────────────── +export const CreateShippingZoneDTO = z.object({ + fk_store: z + .number({ error: "fk_store es requerido" }) + .int() + .positive("fk_store debe ser un ID válido"), + + region: z + .string({ error: "region es requerida" }) + .min(1, "region no puede estar vacía") + .max(50, "region no puede superar 50 caracteres"), + + postal_code: z + .string() + .max(20, "postal_code no puede superar 20 caracteres") + .nullable() + .optional(), + + base_price: z + .number({ error: "base_price es requerido" }) + .min(0, "base_price no puede ser negativo"), + + distance_price: z + .number({ error: "distance_price es requerido" }) + .min(0, "distance_price no puede ser negativo") +}); + +export type CreateShippingZoneDTOType = z.infer; + +export const UpdateShippingZoneDTO = z + .object({ + region: z + .string() + .min(1, "region no puede estar vacía") + .max(50, "region no puede superar 50 caracteres") + .optional(), + + postal_code: z + .string() + .max(20, "postal_code no puede superar 20 caracteres") + .nullable() + .optional(), + + base_price: z + .number({ error: "base_price debe ser número" }) + .min(0, "base_price no puede ser negativo") + .optional(), + + distance_price: z + .number({ error: "distance_price debe ser número" }) + .min(0, "distance_price no puede ser negativo") + .optional() + }) + .refine((data) => Object.keys(data).length > 0, { + message: "Debe enviar al menos un campo para actualizar" + }); + +export type UpdateShippingZoneDTOType = z.infer; + +export const FilterShippingZoneDTO = z.object({ + fk_store: z + .string() + .transform(Number) + .pipe(z.number().int().positive("fk_store debe ser un ID válido")) + .optional(), + + region: z.string().optional(), + + page: z + .string() + .transform(Number) + .pipe(z.number().int().positive("page debe ser mayor a 0")) + .optional() + .default(1), + + limit: z + .string() + .transform(Number) + .pipe(z.number().int().min(1).max(100, "limit no puede superar 100")) + .optional() + .default(10) +}); + +export type FilterShippingZoneDTOType = z.infer; + +// ─── RESPONSE ──────────────────────────────────────────────────── +export class ShippingZoneResponseDTO extends BaseResponseDTO { + id_shipping_zone: number; + fk_store: number; + region: string; + postal_code: string | null; + base_price: number; + distance_price: number; + + constructor(data: any) { + super({ + id: data.id_shipping_zone, + created_at: data.created_at, + updated_at: data.updated_at + }); + this.id_shipping_zone = data.id_shipping_zone; + this.fk_store = data.fk_store; + this.region = data.region; + this.postal_code = data.postal_code ?? null; + this.base_price = Number(data.base_price); + this.distance_price = Number(data.distance_price); + } + + static map(data: any): ShippingZoneResponseDTO { + return new ShippingZoneResponseDTO(data); + } + + static mapList(data: any[]): ShippingZoneResponseDTO[] { + return data.map(ShippingZoneResponseDTO.map); + } +} diff --git a/src/modules/global/dtos/store-categories/store-category.dto.ts b/src/modules/global/dtos/store-categories/store-category.dto.ts new file mode 100644 index 0000000..041e734 --- /dev/null +++ b/src/modules/global/dtos/store-categories/store-category.dto.ts @@ -0,0 +1,70 @@ +import { z } from "zod"; +import { BaseResponseDTO } from "../base/base.response.dto.js"; + +// ─── REQUEST ───────────────────────────────────────────────────── +export const CreateStoreCategoryDTO = z.object({ + name: z + .string({ error: "name es requerido" }) + .min(1, "name no puede estar vacío") + .max(100, "name no puede superar 100 caracteres") +}); + +export type CreateStoreCategoryDTOType = z.infer; + +export const UpdateStoreCategoryDTO = z + .object({ + name: z + .string() + .min(1, "name no puede estar vacío") + .max(100, "name no puede superar 100 caracteres") + .optional() + }) + .refine((data) => Object.keys(data).length > 0, { + message: "Debe enviar al menos un campo para actualizar" + }); + +export type UpdateStoreCategoryDTOType = z.infer; + +export const FilterStoreCategoryDTO = z.object({ + name: z.string().optional(), + + page: z + .string() + .transform(Number) + .pipe(z.number().int().positive("page debe ser mayor a 0")) + .optional() + .default(1), + + limit: z + .string() + .transform(Number) + .pipe(z.number().int().min(1).max(100, "limit no puede superar 100")) + .optional() + .default(10) +}); + +export type FilterStoreCategoryDTOType = z.infer; + +// ─── RESPONSE ──────────────────────────────────────────────────── +export class StoreCategoryResponseDTO extends BaseResponseDTO { + id_store_category: number; + name: string; + + constructor(data: any) { + super({ + id: data.id_store_category, + created_at: data.created_at, + updated_at: data.updated_at + }); + this.id_store_category = data.id_store_category; + this.name = data.name; + } + + static map(data: any): StoreCategoryResponseDTO { + return new StoreCategoryResponseDTO(data); + } + + static mapList(data: any[]): StoreCategoryResponseDTO[] { + return data.map(StoreCategoryResponseDTO.map); + } +} diff --git a/src/modules/global/dtos/stores/store.request.dto.ts b/src/modules/global/dtos/stores/store.request.dto.ts new file mode 100644 index 0000000..d4a2452 --- /dev/null +++ b/src/modules/global/dtos/stores/store.request.dto.ts @@ -0,0 +1,159 @@ +import { z } from "zod"; + +// ─── CREATE ────────────────────────────────────────────────────── +export const CreateStoreDTO = z.object({ + fk_user: z + .number({ error: "fk_user es requerido" }) + .int() + .positive("fk_user debe ser un ID válido"), + + fk_store_category: z + .number({ error: "fk_store_category es requerido" }) + .int() + .positive("fk_store_category debe ser un ID válido"), + + name: z + .string({ error: "name es requerido" }) + .min(1, "name no puede estar vacío") + .max(100, "name no puede superar 100 caracteres"), + + email: z + .string({ error: "email es requerido" }) + .email("email no tiene formato válido") + .max(100, "email no puede superar 100 caracteres"), + + phone: z + .string({ error: "phone es requerido" }) + .min(1, "phone no puede estar vacío") + .max(20, "phone no puede superar 20 caracteres"), + + description: z + .string() + .max(2000, "description no puede superar 2000 caracteres") + .nullable() + .optional(), + + logo: z + .string() + .url("logo debe ser una URL válida") + .max(500) + .nullable() + .optional(), + + website_url: z + .string() + .url("website_url debe ser una URL válida") + .max(500) + .nullable() + .optional(), + + instagram_url: z + .string() + .url("instagram_url debe ser una URL válida") + .max(500) + .nullable() + .optional(), + + tiktok_url: z + .string() + .url("tiktok_url debe ser una URL válida") + .max(500) + .nullable() + .optional() +}); + +export type CreateStoreDTOType = z.infer; + +// ─── UPDATE ────────────────────────────────────────────────────── +export const UpdateStoreDTO = z + .object({ + fk_store_category: z + .number() + .int() + .positive("fk_store_category debe ser un ID válido") + .optional(), + + name: z + .string() + .min(1, "name no puede estar vacío") + .max(100, "name no puede superar 100 caracteres") + .optional(), + + email: z + .string() + .email("email no tiene formato válido") + .max(100, "email no puede superar 100 caracteres") + .optional(), + + phone: z + .string() + .min(1, "phone no puede estar vacío") + .max(20, "phone no puede superar 20 caracteres") + .optional(), + + description: z + .string() + .max(2000, "description no puede superar 2000 caracteres") + .nullable() + .optional(), + + logo: z + .string() + .url("logo debe ser una URL válida") + .max(500) + .nullable() + .optional(), + + website_url: z + .string() + .url("website_url debe ser una URL válida") + .max(500) + .nullable() + .optional(), + + instagram_url: z + .string() + .url("instagram_url debe ser una URL válida") + .max(500) + .nullable() + .optional(), + + tiktok_url: z + .string() + .url("tiktok_url debe ser una URL válida") + .max(500) + .nullable() + .optional() + }) + .refine((data) => Object.keys(data).length > 0, { + message: "Debe enviar al menos un campo para actualizar" + }); + +export type UpdateStoreDTOType = z.infer; + +// ─── FILTER ────────────────────────────────────────────────────── +export const FilterStoreDTO = z.object({ + name: z.string().optional(), + + fk_store_category: z + .string() + .transform(Number) + .pipe(z.number().int().positive("fk_store_category debe ser un ID válido")) + .optional(), + + page: z + .string() + .transform(Number) + .pipe(z.number().int().positive("page debe ser mayor a 0")) + .optional() + .default(1), + + limit: z + .string() + .transform(Number) + .pipe(z.number().int().min(1).max(100, "limit no puede superar 100")) + .optional() + .default(10) +}); + +export type FilterStoreDTOType = z.infer; diff --git a/src/modules/global/dtos/stores/store.response.dto.ts b/src/modules/global/dtos/stores/store.response.dto.ts new file mode 100644 index 0000000..9fca257 --- /dev/null +++ b/src/modules/global/dtos/stores/store.response.dto.ts @@ -0,0 +1,57 @@ +import { BaseResponseDTO } from "../base/base.response.dto.js"; + +// ─── STORE CATEGORY NESTED ─────────────────────────────────────── +export class StoreCategoryNestedDTO { + id_store_category: number; + name: string; + + constructor(data: any) { + this.id_store_category = data.id_store_category; + this.name = data.name; + } +} + +// ─── STORE RESPONSE DTO ────────────────────────────────────────── +export class StoreResponseDTO extends BaseResponseDTO { + id_store: number; + name: string; + email: string; + phone: string; + description: string | null; + logo: string | null; + website_url: string | null; + instagram_url: string | null; + tiktok_url: string | null; + fk_user: number; + store_category: StoreCategoryNestedDTO | null; + + constructor(data: any) { + super({ + id: data.id_store, + created_at: data.created_at, + updated_at: data.updated_at + }); + this.id_store = data.id_store; + this.name = data.name; + this.email = data.email; + this.phone = data.phone; + this.description = data.description ?? null; + this.logo = data.logo ?? null; + this.website_url = data.website_url ?? null; + this.instagram_url = data.instagram_url ?? null; + this.tiktok_url = data.tiktok_url ?? null; + this.fk_user = data.fk_user; + this.store_category = data.store_category + ? new StoreCategoryNestedDTO(data.store_category) + : null; + // status excluido intencionalmente + } + + static map(data: any): StoreResponseDTO { + return new StoreResponseDTO(data); + } + + static mapList(data: any[]): StoreResponseDTO[] { + return data.map(StoreResponseDTO.map); + } +} diff --git a/src/modules/global/dtos/users/user.request.dto.ts b/src/modules/global/dtos/users/user.request.dto.ts new file mode 100644 index 0000000..81788aa --- /dev/null +++ b/src/modules/global/dtos/users/user.request.dto.ts @@ -0,0 +1,99 @@ +import { z } from "zod"; + +// ─── CREATE ────────────────────────────────────────────────────── +export const CreateUserDTO = z.object({ + name: z + .string({ error: "name es requerido" }) + .min(1, "name no puede estar vacío") + .max(100, "name no puede superar 100 caracteres"), + + email: z + .string({ error: "email es requerido" }) + .email("email no tiene formato válido") + .max(100, "email no puede superar 100 caracteres"), + + password: z + .string({ error: "password es requerido" }) + .min(8, "password debe tener al menos 8 caracteres") + .max(255, "password no puede superar 255 caracteres"), + + phone: z + .string() + .max(20, "phone no puede superar 20 caracteres") + .nullable() + .optional(), + + role: z + .enum(["ADMIN", "CUSTOMER", "SELLER", "DELIVERY"], { + error: "role debe ser ADMIN, CUSTOMER, SELLER o DELIVERY" + }) + .optional() + .default("CUSTOMER") +}); + +export type CreateUserDTOType = z.infer; + +// ─── UPDATE ────────────────────────────────────────────────────── +export const UpdateUserDTO = z + .object({ + name: z + .string() + .min(1, "name no puede estar vacío") + .max(100, "name no puede superar 100 caracteres") + .optional(), + + email: z + .string() + .email("email no tiene formato válido") + .max(100, "email no puede superar 100 caracteres") + .optional(), + + password: z + .string() + .min(8, "password debe tener al menos 8 caracteres") + .max(255, "password no puede superar 255 caracteres") + .optional(), + + phone: z + .string() + .max(20, "phone no puede superar 20 caracteres") + .nullable() + .optional() + }) + .refine((data) => Object.keys(data).length > 0, { + message: "Debe enviar al menos un campo para actualizar" + }); + +export type UpdateUserDTOType = z.infer; + +// ─── FILTER ────────────────────────────────────────────────────── +export const FilterUserDTO = z.object({ + name: z.string().optional(), + + email: z + .string() + .email("email no tiene formato válido") + .optional(), + + role: z + .enum(["ADMIN", "CUSTOMER", "SELLER", "DELIVERY"], { + error: "role debe ser ADMIN, CUSTOMER, SELLER o DELIVERY" + }) + .optional(), + + page: z + .string() + .transform(Number) + .pipe(z.number().int().positive("page debe ser mayor a 0")) + .optional() + .default(1), + + limit: z + .string() + .transform(Number) + .pipe(z.number().int().min(1).max(100, "limit no puede superar 100")) + .optional() + .default(10) +}); + +export type FilterUserDTOType = z.infer; diff --git a/src/modules/global/dtos/users/user.response.dto.ts b/src/modules/global/dtos/users/user.response.dto.ts new file mode 100644 index 0000000..e752d23 --- /dev/null +++ b/src/modules/global/dtos/users/user.response.dto.ts @@ -0,0 +1,33 @@ +import { BaseResponseDTO } from "../base/base.response.dto.js"; + +// ─── USER RESPONSE DTO ─────────────────────────────────────────── +export class UserResponseDTO extends BaseResponseDTO { + id_user: number; + name: string; + email: string; + phone: string | null; + role: string; + + constructor(data: any) { + super({ + id: data.id_user, + created_at: data.created_at, + updated_at: data.updated_at + }); + this.id_user = data.id_user; + this.name = data.name; + this.email = data.email; + this.phone = data.phone ?? null; + this.role = data.role; + // password_hash excluido intencionalmente + // status excluido intencionalmente + } + + static map(data: any): UserResponseDTO { + return new UserResponseDTO(data); + } + + static mapList(data: any[]): UserResponseDTO[] { + return data.map(UserResponseDTO.map); + } +} diff --git a/src/modules/global/dtos/wishlists/wishlist.dto.ts b/src/modules/global/dtos/wishlists/wishlist.dto.ts new file mode 100644 index 0000000..a2d641d --- /dev/null +++ b/src/modules/global/dtos/wishlists/wishlist.dto.ts @@ -0,0 +1,113 @@ +import { z } from "zod"; +import { BaseResponseDTO } from "../base/base.response.dto.js"; + +// ─── REQUEST ───────────────────────────────────────────────────── +export const CreateWishlistDTO = z.object({ + name: z + .string({ error: "name es requerido" }) + .min(1, "name no puede estar vacío") + .max(50, "name no puede superar 50 caracteres") +}); + +export type CreateWishlistDTOType = z.infer; + +export const UpdateWishlistDTO = z + .object({ + name: z + .string() + .min(1, "name no puede estar vacío") + .max(50, "name no puede superar 50 caracteres") + .optional() + }) + .refine((data) => Object.keys(data).length > 0, { + message: "Debe enviar al menos un campo para actualizar" + }); + +export type UpdateWishlistDTOType = z.infer; + +export const FilterWishlistDTO = z.object({ + page: z + .string() + .transform(Number) + .pipe(z.number().int().positive("page debe ser mayor a 0")) + .optional() + .default(1), + + limit: z + .string() + .transform(Number) + .pipe(z.number().int().min(1).max(100, "limit no puede superar 100")) + .optional() + .default(10) +}); + +export type FilterWishlistDTOType = z.infer; + +// ─── WISHLIST ITEM REQUEST ──────────────────────────────────────── +export const CreateWishlistItemDTO = z.object({ + fk_product: z + .number({ error: "fk_product es requerido" }) + .int() + .positive("fk_product debe ser un ID válido"), + + quantity: z + .number({ error: "quantity es requerido" }) + .int("quantity debe ser entero") + .min(1, "quantity debe ser al menos 1") +}); + +export type CreateWishlistItemDTOType = z.infer; + +export const UpdateWishlistItemDTO = z + .object({ + quantity: z + .number({ error: "quantity debe ser número" }) + .int("quantity debe ser entero") + .min(1, "quantity debe ser al menos 1") + .optional() + }) + .refine((data) => Object.keys(data).length > 0, { + message: "Debe enviar al menos un campo para actualizar" + }); + +export type UpdateWishlistItemDTOType = z.infer; + +// ─── RESPONSE ──────────────────────────────────────────────────── +export class WishlistItemResponseDTO { + id_wishlist_item: number; + fk_product: number; + quantity: number; + + constructor(data: any) { + this.id_wishlist_item = data.id_wishlist_item; + this.fk_product = data.fk_product; + this.quantity = data.quantity; + } +} + +export class WishlistResponseDTO extends BaseResponseDTO { + id_wishlist: number; + fk_user: number; + name: string; + items: WishlistItemResponseDTO[]; + + constructor(data: any) { + super({ + id: data.id_wishlist, + created_at: data.created_at, + updated_at: data.updated_at + }); + this.id_wishlist = data.id_wishlist; + this.fk_user = data.fk_user; + this.name = data.name; + this.items = data.wishlist_items?.map((i: any) => new WishlistItemResponseDTO(i)) ?? []; + } + + static map(data: any): WishlistResponseDTO { + return new WishlistResponseDTO(data); + } + + static mapList(data: any[]): WishlistResponseDTO[] { + return data.map(WishlistResponseDTO.map); + } +} From 24e1fbde63420409ddc7fd6d524ed7ff01f23c0c Mon Sep 17 00:00:00 2001 From: CrisNAC Date: Wed, 18 Mar 2026 23:49:40 -0300 Subject: [PATCH 4/6] OM-273: Correcciones de CodeRabbit v1 --- package-lock.json | 678 ++++++++++++++++-- package.json | 2 +- prisma.config.js | 8 +- src/middlewares/validate.middleware.ts | 2 +- .../commerce/collection}/.gitkeep | 0 .../commerces/dtos/create-store.dto.ts | 36 - src/modules/commerce/commerces/dtos/index.ts | 1 - .../commerce/commerces/store.routes.js | 6 +- .../product-review.controller.js | 8 +- .../product-reviews/product-review.routes.js | 6 +- .../global/dtos/addresses/address.dto.ts | 2 +- .../global/dtos/base/base.response.dto.ts | 4 +- .../global/dtos/collections/collection.dto.ts | 2 +- .../dtos/notifications/notification.dto.ts | 2 +- src/modules/global/dtos/orders/order.dto.ts | 2 +- .../product-category.dto.ts | 2 +- .../product-reviews/product-review.dto.ts | 14 +- .../dtos/product-tags/product-tag.dto.ts | 2 +- .../dtos/products/product.request.dto.ts | 2 +- .../dtos/shipping-zones/shipping-zone.dto.ts | 2 +- .../store-categories/store-category.dto.ts | 2 +- .../global/dtos/stores/store.request.dto.ts | 2 +- .../global/dtos/users/user.request.dto.ts | 13 +- .../global/dtos/wishlists/wishlist.dto.ts | 4 +- 24 files changed, 688 insertions(+), 114 deletions(-) rename src/{lib => modules/commerce/collection}/.gitkeep (100%) delete mode 100644 src/modules/commerce/commerces/dtos/create-store.dto.ts delete mode 100644 src/modules/commerce/commerces/dtos/index.ts diff --git a/package-lock.json b/package-lock.json index b6b643d..6e4319c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,13 +25,80 @@ "devDependencies": { "@types/express": "^5.0.6", "@types/node": "^25.3.2", - "prisma": "^6.19.2", + "prisma": "^7.4.1", "supertest": "^7.2.2", "tsx": "^4.21.0", "typescript": "^5.9.3", "vitest": "^4.1.0" } }, + "node_modules/@chevrotain/cst-dts-gen": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-10.5.0.tgz", + "integrity": "sha512-lhmC/FyqQ2o7pGK4Om+hzuDrm9rhFYIJ/AXoQBeongmn870Xeb0L6oGEiuR8nohFNL5sMaQEJWCxr1oIVIVXrw==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/gast": "10.5.0", + "@chevrotain/types": "10.5.0", + "lodash": "4.17.21" + } + }, + "node_modules/@chevrotain/gast": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-10.5.0.tgz", + "integrity": "sha512-pXdMJ9XeDAbgOWKuD1Fldz4ieCs6+nLNmyVhe2gZVqoO7v8HXuHYs5OV2EzUtbuai37TlOAQHrTDvxMnvMJz3A==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/types": "10.5.0", + "lodash": "4.17.21" + } + }, + "node_modules/@chevrotain/types": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-10.5.0.tgz", + "integrity": "sha512-f1MAia0x/pAVPWH/T73BJVyO2XU5tI4/iE7cnxb7tqdNTNhQI3Uq3XkqcoteTmD4t1aM0LbHCJOhgIDn07kl2A==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/utils": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-10.5.0.tgz", + "integrity": "sha512-hBzuU5+JjB2cqNZyszkDHZgOSrUUT8V3dhgRl8Q9Gp6dAj/H5+KILGjbhDpc3Iy9qmqlm/akuOI2ut9VUtzJxQ==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@electric-sql/pglite": { + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@electric-sql/pglite/-/pglite-0.3.15.tgz", + "integrity": "sha512-Cj++n1Mekf9ETfdc16TlDi+cDDQF0W7EcbyRHYOAeZdsAe8M/FJg18itDTSwyHfar2WIezawM9o0EKaRGVKygQ==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@electric-sql/pglite-socket": { + "version": "0.0.20", + "resolved": "https://registry.npmjs.org/@electric-sql/pglite-socket/-/pglite-socket-0.0.20.tgz", + "integrity": "sha512-J5nLGsicnD9wJHnno9r+DGxfcZWh+YJMCe0q/aCgtG6XOm9Z7fKeite8IZSNXgZeGltSigM9U/vAWZQWdgcSFg==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "pglite-server": "dist/scripts/server.js" + }, + "peerDependencies": { + "@electric-sql/pglite": "0.3.15" + } + }, + "node_modules/@electric-sql/pglite-tools": { + "version": "0.2.20", + "resolved": "https://registry.npmjs.org/@electric-sql/pglite-tools/-/pglite-tools-0.2.20.tgz", + "integrity": "sha512-BK50ZnYa3IG7ztXhtgYf0Q7zijV32Iw1cYS8C+ThdQlwx12V5VZ9KRJ42y82Hyb4PkTxZQklVQA9JHyUlex33A==", + "devOptional": true, + "license": "Apache-2.0", + "peerDependencies": { + "@electric-sql/pglite": "0.3.15" + } + }, "node_modules/@emnapi/core": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.0.tgz", @@ -508,6 +575,19 @@ "node": ">=18" } }, + "node_modules/@hono/node-server": { + "version": "1.19.9", + "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.9.tgz", + "integrity": "sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=18.14.1" + }, + "peerDependencies": { + "hono": "^4" + } + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", @@ -515,6 +595,20 @@ "dev": true, "license": "MIT" }, + "node_modules/@mrleebo/prisma-ast": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/@mrleebo/prisma-ast/-/prisma-ast-0.13.1.tgz", + "integrity": "sha512-XyroGQXcHrZdvmrGJvsA9KNeOOgGMg1Vg9OlheUsBOSKznLMDl+YChxbkboRHvtFYJEMRYmlV3uoo/njCw05iw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "chevrotain": "^10.5.0", + "lilconfig": "^2.1.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/@napi-rs/wasm-runtime": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz", @@ -618,9 +712,9 @@ "license": "Apache-2.0" }, "node_modules/@prisma/config": { - "version": "6.19.2", - "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.19.2.tgz", - "integrity": "sha512-kadBGDl+aUswv/zZMk9Mx0C8UZs1kjao8H9/JpI4Wh4SHZaM7zkTwiKn/iFLfRg+XtOAo/Z/c6pAYhijKl0nzQ==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@prisma/config/-/config-7.5.0.tgz", + "integrity": "sha512-1J/9YEX7A889xM46PYg9e8VAuSL1IUmXJW3tEhMv7XQHDWlfC9YSkIw9sTYRaq5GswGlxZ+GnnyiNsUZ9JJhSQ==", "devOptional": true, "license": "Apache-2.0", "dependencies": { @@ -636,6 +730,32 @@ "integrity": "sha512-163+nffny0JoPEkDhfNco0vcuT3ymIJc9+WX7MHSQhfkeKUmKe9/wqvGk5SjppT93DtBjVwr5HPJYlXbzm6qtg==", "license": "Apache-2.0" }, + "node_modules/@prisma/dev": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@prisma/dev/-/dev-0.20.0.tgz", + "integrity": "sha512-ovlBYwWor0OzG+yH4J3Ot+AneD818BttLA+Ii7wjbcLHUrnC4tbUPVGyNd3c/+71KETPKZfjhkTSpdS15dmXNQ==", + "devOptional": true, + "license": "ISC", + "dependencies": { + "@electric-sql/pglite": "0.3.15", + "@electric-sql/pglite-socket": "0.0.20", + "@electric-sql/pglite-tools": "0.2.20", + "@hono/node-server": "1.19.9", + "@mrleebo/prisma-ast": "0.13.1", + "@prisma/get-platform": "7.2.0", + "@prisma/query-plan-executor": "7.2.0", + "foreground-child": "3.3.1", + "get-port-please": "3.2.0", + "hono": "4.11.4", + "http-status-codes": "2.3.0", + "pathe": "2.0.3", + "proper-lockfile": "4.1.2", + "remeda": "2.33.4", + "std-env": "3.10.0", + "valibot": "1.2.0", + "zeptomatch": "2.1.0" + } + }, "node_modules/@prisma/driver-adapter-utils": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@prisma/driver-adapter-utils/-/driver-adapter-utils-7.5.0.tgz", @@ -646,69 +766,98 @@ } }, "node_modules/@prisma/engines": { - "version": "6.19.2", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.19.2.tgz", - "integrity": "sha512-TTkJ8r+uk/uqczX40wb+ODG0E0icVsMgwCTyTHXehaEfb0uo80M9g1aW1tEJrxmFHeOZFXdI2sTA1j1AgcHi4A==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-7.5.0.tgz", + "integrity": "sha512-ondGRhzoaVpRWvFaQ5wH5zS1BIbhzbKqczKjCn6j3L0Zfe/LInjcEg8+xtB49AuZBX30qyx1ZtGoootUohz2pw==", "devOptional": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "6.19.2", - "@prisma/engines-version": "7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7", - "@prisma/fetch-engine": "6.19.2", - "@prisma/get-platform": "6.19.2" + "@prisma/debug": "7.5.0", + "@prisma/engines-version": "7.5.0-15.280c870be64f457428992c43c1f6d557fab6e29e", + "@prisma/fetch-engine": "7.5.0", + "@prisma/get-platform": "7.5.0" } }, "node_modules/@prisma/engines-version": { - "version": "7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7.tgz", - "integrity": "sha512-03bgb1VD5gvuumNf+7fVGBzfpJPjmqV423l/WxsWk2cNQ42JD0/SsFBPhN6z8iAvdHs07/7ei77SKu7aZfq8bA==", + "version": "7.5.0-15.280c870be64f457428992c43c1f6d557fab6e29e", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-7.5.0-15.280c870be64f457428992c43c1f6d557fab6e29e.tgz", + "integrity": "sha512-E+iRV/vbJLl8iGjVr6g/TEWokA+gjkV/doZkaQN1i/ULVdDwGnPJDfLUIFGS3BVwlG/m6L8T4x1x5isl8hGMxA==", "devOptional": true, "license": "Apache-2.0" }, - "node_modules/@prisma/engines/node_modules/@prisma/debug": { - "version": "6.19.2", - "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.19.2.tgz", - "integrity": "sha512-lFnEZsLdFLmEVCVNdskLDCL8Uup41GDfU0LUfquw+ercJC8ODTuL0WNKgOKmYxCJVvFwf0OuZBzW99DuWmoH2A==", + "node_modules/@prisma/engines/node_modules/@prisma/get-platform": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.5.0.tgz", + "integrity": "sha512-7I+2y1nu/gkEKSiHHbcZ1HPe/euGdEqJZxEEMT0246q4De1+hla0ZzlTgvaT9dHcVCgLSuCG8v39db5qUUWNgw==", "devOptional": true, - "license": "Apache-2.0" + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "7.5.0" + } }, "node_modules/@prisma/fetch-engine": { - "version": "6.19.2", - "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.19.2.tgz", - "integrity": "sha512-h4Ff4Pho+SR1S8XerMCC12X//oY2bG3Iug/fUnudfcXEUnIeRiBdXHFdGlGOgQ3HqKgosTEhkZMvGM9tWtYC+Q==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-7.5.0.tgz", + "integrity": "sha512-kZCl2FV54qnyrVdnII8MI6qvt7HfU6Cbiz8dZ8PXz4f4lbSw45jEB9/gEMK2SGdiNhBKyk/Wv95uthoLhGMLYA==", "devOptional": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "6.19.2", - "@prisma/engines-version": "7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7", - "@prisma/get-platform": "6.19.2" + "@prisma/debug": "7.5.0", + "@prisma/engines-version": "7.5.0-15.280c870be64f457428992c43c1f6d557fab6e29e", + "@prisma/get-platform": "7.5.0" } }, - "node_modules/@prisma/fetch-engine/node_modules/@prisma/debug": { - "version": "6.19.2", - "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.19.2.tgz", - "integrity": "sha512-lFnEZsLdFLmEVCVNdskLDCL8Uup41GDfU0LUfquw+ercJC8ODTuL0WNKgOKmYxCJVvFwf0OuZBzW99DuWmoH2A==", + "node_modules/@prisma/fetch-engine/node_modules/@prisma/get-platform": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.5.0.tgz", + "integrity": "sha512-7I+2y1nu/gkEKSiHHbcZ1HPe/euGdEqJZxEEMT0246q4De1+hla0ZzlTgvaT9dHcVCgLSuCG8v39db5qUUWNgw==", "devOptional": true, - "license": "Apache-2.0" + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "7.5.0" + } }, "node_modules/@prisma/get-platform": { - "version": "6.19.2", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.19.2.tgz", - "integrity": "sha512-PGLr06JUSTqIvztJtAzIxOwtWKtJm5WwOG6xpsgD37Rc84FpfUBGLKz65YpJBGtkRQGXTYEFie7pYALocC3MtA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.2.0.tgz", + "integrity": "sha512-k1V0l0Td1732EHpAfi2eySTezyllok9dXb6UQanajkJQzPUGi3vO2z7jdkz67SypFTdmbnyGYxvEvYZdZsMAVA==", "devOptional": true, "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "6.19.2" + "@prisma/debug": "7.2.0" } }, "node_modules/@prisma/get-platform/node_modules/@prisma/debug": { - "version": "6.19.2", - "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.19.2.tgz", - "integrity": "sha512-lFnEZsLdFLmEVCVNdskLDCL8Uup41GDfU0LUfquw+ercJC8ODTuL0WNKgOKmYxCJVvFwf0OuZBzW99DuWmoH2A==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-7.2.0.tgz", + "integrity": "sha512-YSGTiSlBAVJPzX4ONZmMotL+ozJwQjRmZweQNIq/ER0tQJKJynNkRB3kyvt37eOfsbMCXk3gnLF6J9OJ4QWftw==", "devOptional": true, "license": "Apache-2.0" }, + "node_modules/@prisma/query-plan-executor": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@prisma/query-plan-executor/-/query-plan-executor-7.2.0.tgz", + "integrity": "sha512-EOZmNzcV8uJ0mae3DhTsiHgoNCuu1J9mULQpGCh62zN3PxPTd+qI9tJvk5jOst8WHKQNwJWR3b39t0XvfBB0WQ==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/studio-core": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@prisma/studio-core/-/studio-core-0.21.1.tgz", + "integrity": "sha512-bOGqG/eMQtKC0XVvcVLRmhWWzm/I+0QUWqAEhEBtetpuS3k3V4IWqKGUONkAIT223DNXJMxMtZp36b1FmcdPeg==", + "devOptional": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19 || ^22.12 || ^24.0", + "pnpm": "8" + }, + "peerDependencies": { + "@types/react": "^18.0.0 || ^19.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, "node_modules/@rolldown/binding-android-arm64": { "version": "1.0.0-rc.9", "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.9.tgz", @@ -1101,6 +1250,17 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/react": { + "version": "19.2.14", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", + "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", + "devOptional": true, + "license": "MIT", + "peer": true, + "dependencies": { + "csstype": "^3.2.2" + } + }, "node_modules/@types/send": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", @@ -1285,6 +1445,16 @@ "dev": true, "license": "MIT" }, + "node_modules/aws-ssl-profiles": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", + "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/balanced-match": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", @@ -1512,6 +1682,21 @@ "node": ">=18" } }, + "node_modules/chevrotain": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-10.5.0.tgz", + "integrity": "sha512-Pkv5rBY3+CsHOYfV5g/Vs5JY9WTHHDEKOlohI2XeygaZhUeqhAlldZ8Hz9cRmxu709bvS08YzxHdTPHhffc13A==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/cst-dts-gen": "10.5.0", + "@chevrotain/gast": "10.5.0", + "@chevrotain/types": "10.5.0", + "@chevrotain/utils": "10.5.0", + "lodash": "4.17.21", + "regexp-to-ast": "0.5.0" + } + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -1667,6 +1852,29 @@ "url": "https://opencollective.com/express" } }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "devOptional": true, + "license": "MIT", + "peer": true + }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -1711,6 +1919,16 @@ "node": ">=0.4.0" } }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "devOptional": true, + "license": "Apache-2.0", + "engines": { + "node": ">=0.10" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -2071,6 +2289,23 @@ "url": "https://opencollective.com/express" } }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "devOptional": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/form-data": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", @@ -2170,6 +2405,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "is-property": "^1.0.2" + } + }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -2194,6 +2439,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-port-please": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/get-port-please/-/get-port-please-3.2.0.tgz", + "integrity": "sha512-I9QVvBw5U/hw3RmWpYKRumUeaDgxTPd401x364rLmWBJcOQ753eov1eTgzDqRG9bqFIfDc7gfzcQEWrUri3o1A==", + "devOptional": true, + "license": "MIT" + }, "node_modules/get-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", @@ -2262,6 +2514,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "devOptional": true, + "license": "ISC" + }, + "node_modules/grammex": { + "version": "3.1.12", + "resolved": "https://registry.npmjs.org/grammex/-/grammex-3.1.12.tgz", + "integrity": "sha512-6ufJOsSA7LcQehIJNCO7HIBykfM7DXQual0Ny780/DEcJIpBlHRvcqEBWGPYd7hrXL2GJ3oJI1MIhaXjWmLQOQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/graphmatch": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/graphmatch/-/graphmatch-1.1.1.tgz", + "integrity": "sha512-5ykVn/EXM1hF0XCaWh05VbYvEiOL2lY1kBxZtaYsyvjp7cmWOU1XsAdfQBwClraEofXDT197lFbXOEVMHpvQOg==", + "devOptional": true, + "license": "MIT" + }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -2311,6 +2584,16 @@ "node": ">= 0.4" } }, + "node_modules/hono": { + "version": "4.11.4", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.4.tgz", + "integrity": "sha512-U7tt8JsyrxSRKspfhtLET79pU8K+tInj5QZXs1jSugO1Vq5dFj3kmZsRldo29mTBfcjDRVRXrEZ6LS63Cog9ZA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=16.9.0" + } + }, "node_modules/http-errors": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", @@ -2331,6 +2614,13 @@ "url": "https://opencollective.com/express" } }, + "node_modules/http-status-codes": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/http-status-codes/-/http-status-codes-2.3.0.tgz", + "integrity": "sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==", + "devOptional": true, + "license": "MIT" + }, "node_modules/iconv-lite": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", @@ -2416,6 +2706,20 @@ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", "license": "MIT" }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "devOptional": true, + "license": "ISC" + }, "node_modules/jiti": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", @@ -2730,6 +3034,23 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "devOptional": true, + "license": "MIT" + }, "node_modules/lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -2772,6 +3093,29 @@ "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", "license": "MIT" }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/lru.min": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.4.tgz", + "integrity": "sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA==", + "devOptional": true, + "license": "MIT", + "engines": { + "bun": ">=1.0.0", + "deno": ">=1.30.0", + "node": ">=8.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wellwelwel" + } + }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", @@ -2924,6 +3268,40 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, + "node_modules/mysql2": { + "version": "3.15.3", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.15.3.tgz", + "integrity": "sha512-FBrGau0IXmuqg4haEZRBfHNWB5mUARw6hNwPDXXGg0XzVJ50mr/9hb267lvpVMnhZ1FON3qNd4Xfcez1rbFwSg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "aws-ssl-profiles": "^1.1.1", + "denque": "^2.1.0", + "generate-function": "^2.3.1", + "iconv-lite": "^0.7.0", + "long": "^5.2.1", + "lru.min": "^1.0.0", + "named-placeholders": "^1.1.3", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.2" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/named-placeholders": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.6.tgz", + "integrity": "sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "lru.min": "^1.1.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -3125,6 +3503,16 @@ "node": ">= 0.8" } }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/path-to-regexp": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", @@ -3364,6 +3752,20 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/postgres": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.4.7.tgz", + "integrity": "sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==", + "devOptional": true, + "license": "Unlicense", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/porsager" + } + }, "node_modules/postgres-array": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.4.tgz", @@ -3410,31 +3812,58 @@ "license": "MIT" }, "node_modules/prisma": { - "version": "6.19.2", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.19.2.tgz", - "integrity": "sha512-XTKeKxtQElcq3U9/jHyxSPgiRgeYDKxWTPOf6NkXA0dNj5j40MfEsZkMbyNpwDWCUv7YBFUl7I2VK/6ALbmhEg==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-7.5.0.tgz", + "integrity": "sha512-n30qZpWehaYQzigLjmuPisyEsvOzHt7bZeRyg8gZ5DvJo9FGjD+gNaY59Ns3hlLD5/jZH5GBeftIss0jDbUoLg==", "devOptional": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@prisma/config": "6.19.2", - "@prisma/engines": "6.19.2" + "@prisma/config": "7.5.0", + "@prisma/dev": "0.20.0", + "@prisma/engines": "7.5.0", + "@prisma/studio-core": "0.21.1", + "mysql2": "3.15.3", + "postgres": "3.4.7" }, "bin": { "prisma": "build/index.js" }, "engines": { - "node": ">=18.18" + "node": "^20.19 || ^22.12 || >=24.0" }, "peerDependencies": { - "typescript": ">=5.1.0" + "better-sqlite3": ">=9.0.0", + "typescript": ">=5.4.0" }, "peerDependenciesMeta": { + "better-sqlite3": { + "optional": true + }, "typescript": { "optional": true } } }, + "node_modules/proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, + "node_modules/proper-lockfile/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "devOptional": true, + "license": "ISC" + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -3521,6 +3950,31 @@ "destr": "^2.0.3" } }, + "node_modules/react": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", + "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "devOptional": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", + "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", + "devOptional": true, + "license": "MIT", + "peer": true, + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.4" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -3533,6 +3987,23 @@ "node": ">=8.10.0" } }, + "node_modules/regexp-to-ast": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz", + "integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/remeda": { + "version": "2.33.4", + "resolved": "https://registry.npmjs.org/remeda/-/remeda-2.33.4.tgz", + "integrity": "sha512-ygHswjlc/opg2VrtiYvUOPLjxjtdKvjGz1/plDhkG66hjNjFr1xmfrs2ClNFo/E6TyUFiwYNh53bKV26oBoMGQ==", + "devOptional": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/remeda" + } + }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", @@ -3543,6 +4014,16 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/rolldown": { "version": "1.0.0-rc.9", "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.9.tgz", @@ -3619,6 +4100,14 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "license": "MIT" }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "devOptional": true, + "license": "MIT", + "peer": true + }, "node_modules/semver": { "version": "7.7.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", @@ -3657,6 +4146,12 @@ "url": "https://opencollective.com/express" } }, + "node_modules/seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==", + "devOptional": true + }, "node_modules/serve-static": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", @@ -3682,6 +4177,29 @@ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "license": "ISC" }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", @@ -3761,6 +4279,19 @@ "dev": true, "license": "ISC" }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "devOptional": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/simple-update-notifier": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", @@ -3792,6 +4323,16 @@ "node": ">= 10.x" } }, + "node_modules/sqlstring": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", @@ -3808,6 +4349,13 @@ "node": ">= 0.8" } }, + "node_modules/std-env": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "devOptional": true, + "license": "MIT" + }, "node_modules/superagent": { "version": "10.3.0", "resolved": "https://registry.npmjs.org/superagent/-/superagent-10.3.0.tgz", @@ -4048,6 +4596,21 @@ "node": ">= 0.8" } }, + "node_modules/valibot": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/valibot/-/valibot-1.2.0.tgz", + "integrity": "sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg==", + "devOptional": true, + "license": "MIT", + "peerDependencies": { + "typescript": ">=5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -4251,6 +4814,22 @@ "dev": true, "license": "MIT" }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "devOptional": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/why-is-node-running": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", @@ -4283,6 +4862,17 @@ "node": ">=0.4" } }, + "node_modules/zeptomatch": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/zeptomatch/-/zeptomatch-2.1.0.tgz", + "integrity": "sha512-KiGErG2J0G82LSpniV0CtIzjlJ10E04j02VOudJsPyPwNZgGnRKQy7I1R7GMyg/QswnE4l7ohSGrQbQbjXPPDA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "grammex": "^3.1.11", + "graphmatch": "^1.1.0" + } + }, "node_modules/zod": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", diff --git a/package.json b/package.json index 8f0696e..992b36b 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "devDependencies": { "@types/express": "^5.0.6", "@types/node": "^25.3.2", - "prisma": "^6.19.2", + "prisma": "^7.4.1", "supertest": "^7.2.2", "tsx": "^4.21.0", "typescript": "^5.9.3", diff --git a/prisma.config.js b/prisma.config.js index 7466996..230c74f 100644 --- a/prisma.config.js +++ b/prisma.config.js @@ -2,12 +2,18 @@ // npm install --save-dev prisma dotenv import "dotenv/config"; import { defineConfig } from "prisma/config"; + +const directUrl = process.env["DIRECT_URL"]; +if (!directUrl) { + throw new Error("La variable de entorno DIRECT_URL es requerida y no está definida"); +} + export default defineConfig({ schema: "prisma/schema.prisma", migrations: { path: "prisma/migrations", }, datasource: { - url: process.env["DIRECT_URL"] || "", + url: directUrl, }, }); diff --git a/src/middlewares/validate.middleware.ts b/src/middlewares/validate.middleware.ts index 425e195..000a60f 100644 --- a/src/middlewares/validate.middleware.ts +++ b/src/middlewares/validate.middleware.ts @@ -9,7 +9,7 @@ export const validate = const result = schema.safeParse(req[section]); if (!result.success) { - const errors = result.error.errors.map((e) => ({ + const errors = result.error.issues.map((e) => ({ field: e.path.join("."), message: e.message })); diff --git a/src/lib/.gitkeep b/src/modules/commerce/collection/.gitkeep similarity index 100% rename from src/lib/.gitkeep rename to src/modules/commerce/collection/.gitkeep diff --git a/src/modules/commerce/commerces/dtos/create-store.dto.ts b/src/modules/commerce/commerces/dtos/create-store.dto.ts deleted file mode 100644 index abc123e..0000000 --- a/src/modules/commerce/commerces/dtos/create-store.dto.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { z } from "zod"; - -export const CreateStoreDTO = z.object({ - fk_user: z - .number({ required_error: "fk_user es requerido" }) - .int() - .positive(), - - fk_store_category: z - .number({ required_error: "fk_store_category es requerido" }) - .int() - .positive(), - - name: z - .string({ required_error: "name es requerido" }) - .min(1) - .max(100), - - email: z - .string({ required_error: "email es requerido" }) - .email("email no tiene formato válido") - .max(100), - - phone: z - .string({ required_error: "phone es requerido" }) - .min(1) - .max(20), - - description: z.string().max(2000).nullable().optional(), - logo: z.string().url("logo debe ser una URL válida").max(500).nullable().optional(), - website_url: z.string().url().max(500).nullable().optional(), - instagram_url: z.string().url().max(500).nullable().optional(), - tiktok_url: z.string().url().max(500).nullable().optional() -}); - -export type CreateStoreDTOType = z.infer; \ No newline at end of file diff --git a/src/modules/commerce/commerces/dtos/index.ts b/src/modules/commerce/commerces/dtos/index.ts deleted file mode 100644 index 90089e8..0000000 --- a/src/modules/commerce/commerces/dtos/index.ts +++ /dev/null @@ -1 +0,0 @@ -import { CreateStoreDTO } from "./create-store.dto"; \ No newline at end of file diff --git a/src/modules/commerce/commerces/store.routes.js b/src/modules/commerce/commerces/store.routes.js index f8f0914..0531934 100644 --- a/src/modules/commerce/commerces/store.routes.js +++ b/src/modules/commerce/commerces/store.routes.js @@ -1,6 +1,6 @@ // src/modules/commerce/commerces/store.routes.js import { Router } from "express"; -import authenticate from '@/config/jwt.config.js'; +import authenticate from '../../../config/jwt.config.js'; import { createStore, updateStore, @@ -10,10 +10,6 @@ import { filterStoreProducts, deleteStore } from "./store.controller.js"; -import { - CreateStoreDTO, -} from "./dtos/index"; -import { validate } from "../../../middlewares/validate.middleware.js"; const router = Router(); diff --git a/src/modules/commerce/product-reviews/product-review.controller.js b/src/modules/commerce/product-reviews/product-review.controller.js index 3b36e3d..42a344f 100644 --- a/src/modules/commerce/product-reviews/product-review.controller.js +++ b/src/modules/commerce/product-reviews/product-review.controller.js @@ -5,9 +5,11 @@ export const getProductReviews = async (req, res) => { const result = await getProductReviewsService(req.params.id, req.query); return res.status(200).json(result); } catch (error) { - console.error("Error obteniendo reseñas:", error); - return res.status(error.status || 500).json({ - message: error.message || "Error interno del servidor" + const status = Number.isInteger(error?.status) && error.status >= 400 && error.status <= 599 + ? error.status + : 500; + return res.status(status).json({ + message: status < 500 ? error.message : "Error interno del servidor" }); } }; \ No newline at end of file diff --git a/src/modules/commerce/product-reviews/product-review.routes.js b/src/modules/commerce/product-reviews/product-review.routes.js index 4138d83..3f58456 100644 --- a/src/modules/commerce/product-reviews/product-review.routes.js +++ b/src/modules/commerce/product-reviews/product-review.routes.js @@ -2,13 +2,9 @@ import { Router } from "express"; import { getProductReviews, } from "./product-review.controller.js"; -import { - GetReviewsDTO, -} from "./dtos/index"; -import { validate } from "@/middlewares/validate.middleware.js"; const router = Router(); -router.get("/:id", validate(GetReviewsDTO, "query"), getProductReviews); +router.get("/:id", getProductReviews); export default router; \ No newline at end of file diff --git a/src/modules/global/dtos/addresses/address.dto.ts b/src/modules/global/dtos/addresses/address.dto.ts index fb5a5a3..161626c 100644 --- a/src/modules/global/dtos/addresses/address.dto.ts +++ b/src/modules/global/dtos/addresses/address.dto.ts @@ -60,7 +60,7 @@ export const UpdateAddressDTO = z .nullable() .optional() }) - .refine((data) => Object.keys(data).length > 0, { + .refine((data) => Object.values(data).some((v) => v !== undefined), { message: "Debe enviar al menos un campo para actualizar" }); diff --git a/src/modules/global/dtos/base/base.response.dto.ts b/src/modules/global/dtos/base/base.response.dto.ts index d3403d1..e3fe149 100644 --- a/src/modules/global/dtos/base/base.response.dto.ts +++ b/src/modules/global/dtos/base/base.response.dto.ts @@ -27,8 +27,8 @@ export class PaginatedResponseDTO { }) { this.content = data.content; this.total_elements = data.total_elements; - this.total_pages = Math.ceil(data.total_elements / data.size); - this.size = data.size; + this.size = data.size > 0 ? data.size : 0; + this.total_pages = data.size > 0 ? Math.ceil(data.total_elements / data.size) : 0; this.page = data.page; } diff --git a/src/modules/global/dtos/collections/collection.dto.ts b/src/modules/global/dtos/collections/collection.dto.ts index c04fefe..1fb49ff 100644 --- a/src/modules/global/dtos/collections/collection.dto.ts +++ b/src/modules/global/dtos/collections/collection.dto.ts @@ -41,7 +41,7 @@ export const UpdateCollectionDTO = z .nullable() .optional() }) - .refine((data) => Object.keys(data).length > 0, { + .refine((data) => Object.values(data).some((v) => v !== undefined), { message: "Debe enviar al menos un campo para actualizar" }); diff --git a/src/modules/global/dtos/notifications/notification.dto.ts b/src/modules/global/dtos/notifications/notification.dto.ts index 65a6670..de8106e 100644 --- a/src/modules/global/dtos/notifications/notification.dto.ts +++ b/src/modules/global/dtos/notifications/notification.dto.ts @@ -26,7 +26,7 @@ export const UpdateNotificationDTO = z .object({ read: z.boolean().optional() }) - .refine((data) => Object.keys(data).length > 0, { + .refine((data) => Object.values(data).some((v) => v !== undefined), { message: "Debe enviar al menos un campo para actualizar" }); diff --git a/src/modules/global/dtos/orders/order.dto.ts b/src/modules/global/dtos/orders/order.dto.ts index 7196019..b43583b 100644 --- a/src/modules/global/dtos/orders/order.dto.ts +++ b/src/modules/global/dtos/orders/order.dto.ts @@ -58,7 +58,7 @@ export const UpdateOrderDTO = z .positive("fk_address debe ser un ID válido") .optional() }) - .refine((data) => Object.keys(data).length > 0, { + .refine((data) => Object.values(data).some((v) => v !== undefined), { message: "Debe enviar al menos un campo para actualizar" }); diff --git a/src/modules/global/dtos/product-categories/product-category.dto.ts b/src/modules/global/dtos/product-categories/product-category.dto.ts index 1b0c49b..2fef620 100644 --- a/src/modules/global/dtos/product-categories/product-category.dto.ts +++ b/src/modules/global/dtos/product-categories/product-category.dto.ts @@ -19,7 +19,7 @@ export const UpdateProductCategoryDTO = z .max(100, "name no puede superar 100 caracteres") .optional() }) - .refine((data) => Object.keys(data).length > 0, { + .refine((data) => Object.values(data).some((v) => v !== undefined), { message: "Debe enviar al menos un campo para actualizar" }); diff --git a/src/modules/global/dtos/product-reviews/product-review.dto.ts b/src/modules/global/dtos/product-reviews/product-review.dto.ts index 1a9519b..e424f07 100644 --- a/src/modules/global/dtos/product-reviews/product-review.dto.ts +++ b/src/modules/global/dtos/product-reviews/product-review.dto.ts @@ -33,7 +33,7 @@ export const UpdateProductReviewDTO = z .nullable() .optional() }) - .refine((data) => Object.keys(data).length > 0, { + .refine((data) => Object.values(data).some((v) => v !== undefined), { message: "Debe enviar al menos un campo para actualizar" }); @@ -76,6 +76,18 @@ export const FilterProductReviewDTO = z.object({ .pipe(z.number().int().min(1).max(100, "limit no puede superar 100")) .optional() .default(10) +}).superRefine((data, ctx) => { + if ( + data.minRating !== undefined && + data.maxRating !== undefined && + data.minRating > data.maxRating + ) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: "minRating no puede ser mayor que maxRating", + path: ["maxRating"] + }); + } }); export type FilterProductReviewDTOType = z.infer; diff --git a/src/modules/global/dtos/product-tags/product-tag.dto.ts b/src/modules/global/dtos/product-tags/product-tag.dto.ts index 9d3ab11..b9f548d 100644 --- a/src/modules/global/dtos/product-tags/product-tag.dto.ts +++ b/src/modules/global/dtos/product-tags/product-tag.dto.ts @@ -19,7 +19,7 @@ export const UpdateProductTagDTO = z .max(20, "name no puede superar 20 caracteres") .optional() }) - .refine((data) => Object.keys(data).length > 0, { + .refine((data) => Object.values(data).some((v) => v !== undefined), { message: "Debe enviar al menos un campo para actualizar" }); diff --git a/src/modules/global/dtos/products/product.request.dto.ts b/src/modules/global/dtos/products/product.request.dto.ts index 75de162..bed506e 100644 --- a/src/modules/global/dtos/products/product.request.dto.ts +++ b/src/modules/global/dtos/products/product.request.dto.ts @@ -106,7 +106,7 @@ export const UpdateProductDTO = z ]) .optional() }) - .refine((data) => Object.keys(data).length > 0, { + .refine((data) => Object.values(data).some((v) => v !== undefined), { message: "Debe enviar al menos un campo para actualizar" }); diff --git a/src/modules/global/dtos/shipping-zones/shipping-zone.dto.ts b/src/modules/global/dtos/shipping-zones/shipping-zone.dto.ts index af81430..27a6ec2 100644 --- a/src/modules/global/dtos/shipping-zones/shipping-zone.dto.ts +++ b/src/modules/global/dtos/shipping-zones/shipping-zone.dto.ts @@ -54,7 +54,7 @@ export const UpdateShippingZoneDTO = z .min(0, "distance_price no puede ser negativo") .optional() }) - .refine((data) => Object.keys(data).length > 0, { + .refine((data) => Object.values(data).some((v) => v !== undefined), { message: "Debe enviar al menos un campo para actualizar" }); diff --git a/src/modules/global/dtos/store-categories/store-category.dto.ts b/src/modules/global/dtos/store-categories/store-category.dto.ts index 041e734..0e7e7db 100644 --- a/src/modules/global/dtos/store-categories/store-category.dto.ts +++ b/src/modules/global/dtos/store-categories/store-category.dto.ts @@ -19,7 +19,7 @@ export const UpdateStoreCategoryDTO = z .max(100, "name no puede superar 100 caracteres") .optional() }) - .refine((data) => Object.keys(data).length > 0, { + .refine((data) => Object.values(data).some((v) => v !== undefined), { message: "Debe enviar al menos un campo para actualizar" }); diff --git a/src/modules/global/dtos/stores/store.request.dto.ts b/src/modules/global/dtos/stores/store.request.dto.ts index d4a2452..a008cca 100644 --- a/src/modules/global/dtos/stores/store.request.dto.ts +++ b/src/modules/global/dtos/stores/store.request.dto.ts @@ -125,7 +125,7 @@ export const UpdateStoreDTO = z .nullable() .optional() }) - .refine((data) => Object.keys(data).length > 0, { + .refine((data) => Object.values(data).some((v) => v !== undefined), { message: "Debe enviar al menos un campo para actualizar" }); diff --git a/src/modules/global/dtos/users/user.request.dto.ts b/src/modules/global/dtos/users/user.request.dto.ts index 81788aa..f975ca1 100644 --- a/src/modules/global/dtos/users/user.request.dto.ts +++ b/src/modules/global/dtos/users/user.request.dto.ts @@ -4,21 +4,25 @@ import { z } from "zod"; export const CreateUserDTO = z.object({ name: z .string({ error: "name es requerido" }) + .trim() .min(1, "name no puede estar vacío") .max(100, "name no puede superar 100 caracteres"), email: z .string({ error: "email es requerido" }) + .trim() .email("email no tiene formato válido") .max(100, "email no puede superar 100 caracteres"), password: z .string({ error: "password es requerido" }) + .trim() .min(8, "password debe tener al menos 8 caracteres") .max(255, "password no puede superar 255 caracteres"), phone: z .string() + .trim() .max(20, "phone no puede superar 20 caracteres") .nullable() .optional(), @@ -38,29 +42,33 @@ export const UpdateUserDTO = z .object({ name: z .string() + .trim() .min(1, "name no puede estar vacío") .max(100, "name no puede superar 100 caracteres") .optional(), email: z .string() + .trim() .email("email no tiene formato válido") .max(100, "email no puede superar 100 caracteres") .optional(), password: z .string() + .trim() .min(8, "password debe tener al menos 8 caracteres") .max(255, "password no puede superar 255 caracteres") .optional(), phone: z .string() + .trim() .max(20, "phone no puede superar 20 caracteres") .nullable() .optional() }) - .refine((data) => Object.keys(data).length > 0, { + .refine((data) => Object.values(data).some((v) => v !== undefined), { message: "Debe enviar al menos un campo para actualizar" }); @@ -68,10 +76,11 @@ export type UpdateUserDTOType = z.infer; // ─── FILTER ────────────────────────────────────────────────────── export const FilterUserDTO = z.object({ - name: z.string().optional(), + name: z.string().trim().optional(), email: z .string() + .trim() .email("email no tiene formato válido") .optional(), diff --git a/src/modules/global/dtos/wishlists/wishlist.dto.ts b/src/modules/global/dtos/wishlists/wishlist.dto.ts index a2d641d..b5427cb 100644 --- a/src/modules/global/dtos/wishlists/wishlist.dto.ts +++ b/src/modules/global/dtos/wishlists/wishlist.dto.ts @@ -19,7 +19,7 @@ export const UpdateWishlistDTO = z .max(50, "name no puede superar 50 caracteres") .optional() }) - .refine((data) => Object.keys(data).length > 0, { + .refine((data) => Object.values(data).some((v) => v !== undefined), { message: "Debe enviar al menos un campo para actualizar" }); @@ -66,7 +66,7 @@ export const UpdateWishlistItemDTO = z .min(1, "quantity debe ser al menos 1") .optional() }) - .refine((data) => Object.keys(data).length > 0, { + .refine((data) => Object.values(data).some((v) => v !== undefined), { message: "Debe enviar al menos un campo para actualizar" }); From 4356823b530f78a90d98d6186f6b55912bba7e2b Mon Sep 17 00:00:00 2001 From: CrisNAC Date: Thu, 19 Mar 2026 00:11:12 -0300 Subject: [PATCH 5/6] OM-273: Correcciones de CodeRabbit v2 --- .../global/dtos/addresses/address.dto.ts | 12 ++++++++-- .../product-category.dto.ts | 14 +++++++++-- .../global/dtos/users/user.request.dto.ts | 23 +++++++++++++++---- .../global/dtos/wishlists/wishlist.dto.ts | 15 ++++++++++-- 4 files changed, 53 insertions(+), 11 deletions(-) diff --git a/src/modules/global/dtos/addresses/address.dto.ts b/src/modules/global/dtos/addresses/address.dto.ts index 161626c..27679ba 100644 --- a/src/modules/global/dtos/addresses/address.dto.ts +++ b/src/modules/global/dtos/addresses/address.dto.ts @@ -17,10 +17,13 @@ export const CreateAddressDTO = z.object({ address: z .string({ error: "address es requerido" }) - .min(1, "address no puede estar vacío"), + .trim() + .min(1, "address no puede estar vacío") + .max(500, "address no puede superar 500 caracteres"), city: z .string({ error: "city es requerido" }) + .trim() .min(1, "city no puede estar vacío") .max(100, "city no puede superar 100 caracteres"), @@ -40,10 +43,15 @@ export type CreateAddressDTOType = z.infer; export const UpdateAddressDTO = z .object({ - address: z.string().min(1, "address no puede estar vacío").optional(), + address: z + .string() + .trim() + .min(1, "address no puede estar vacío") + .max(500, "address no puede superar 500 caracteres").optional(), city: z .string() + .trim() .min(1, "city no puede estar vacío") .max(100, "city no puede superar 100 caracteres") .optional(), diff --git a/src/modules/global/dtos/product-categories/product-category.dto.ts b/src/modules/global/dtos/product-categories/product-category.dto.ts index 2fef620..4cf6cf5 100644 --- a/src/modules/global/dtos/product-categories/product-category.dto.ts +++ b/src/modules/global/dtos/product-categories/product-category.dto.ts @@ -4,7 +4,12 @@ import { BaseResponseDTO } from "../base/base.response.dto.js"; // ─── REQUEST ───────────────────────────────────────────────────── export const CreateProductCategoryDTO = z.object({ name: z - .string({ error: "name es requerido" }) + .string({ + error: (issue) => + issue.input === undefined + ? "name es requerido" + : "name debe ser un texto" + }) .min(1, "name no puede estar vacío") .max(100, "name no puede superar 100 caracteres") }); @@ -14,7 +19,12 @@ export type CreateProductCategoryDTOType = z.infer + issue.input === undefined + ? "name es requerido" + : "name debe ser un texto" + }) .min(1, "name no puede estar vacío") .max(100, "name no puede superar 100 caracteres") .optional() diff --git a/src/modules/global/dtos/users/user.request.dto.ts b/src/modules/global/dtos/users/user.request.dto.ts index f975ca1..d9cd458 100644 --- a/src/modules/global/dtos/users/user.request.dto.ts +++ b/src/modules/global/dtos/users/user.request.dto.ts @@ -3,20 +3,34 @@ import { z } from "zod"; // ─── CREATE ────────────────────────────────────────────────────── export const CreateUserDTO = z.object({ name: z - .string({ error: "name es requerido" }) + .string({ + error: (issue) => + issue.input === undefined + ? "name es requerido" + : "name debe ser un texto" + }) .trim() .min(1, "name no puede estar vacío") .max(100, "name no puede superar 100 caracteres"), email: z - .string({ error: "email es requerido" }) + .string({ + error: (issue) => + issue.input === undefined + ? "email es requerido" + : "email debe ser un texto" + }) .trim() .email("email no tiene formato válido") .max(100, "email no puede superar 100 caracteres"), password: z - .string({ error: "password es requerido" }) - .trim() + .string({ + error: (issue) => + issue.input === undefined + ? "password es requerido" + : "password debe ser un texto" + }) .min(8, "password debe tener al menos 8 caracteres") .max(255, "password no puede superar 255 caracteres"), @@ -56,7 +70,6 @@ export const UpdateUserDTO = z password: z .string() - .trim() .min(8, "password debe tener al menos 8 caracteres") .max(255, "password no puede superar 255 caracteres") .optional(), diff --git a/src/modules/global/dtos/wishlists/wishlist.dto.ts b/src/modules/global/dtos/wishlists/wishlist.dto.ts index b5427cb..5b72abe 100644 --- a/src/modules/global/dtos/wishlists/wishlist.dto.ts +++ b/src/modules/global/dtos/wishlists/wishlist.dto.ts @@ -4,7 +4,13 @@ import { BaseResponseDTO } from "../base/base.response.dto.js"; // ─── REQUEST ───────────────────────────────────────────────────── export const CreateWishlistDTO = z.object({ name: z - .string({ error: "name es requerido" }) + .string({ + error: (issue) => + issue.input === undefined + ? "name es requerido" + : "name debe ser un texto" + }) + .trim() .min(1, "name no puede estar vacío") .max(50, "name no puede superar 50 caracteres") }); @@ -14,7 +20,12 @@ export type CreateWishlistDTOType = z.infer; export const UpdateWishlistDTO = z .object({ name: z - .string() + .string({ + error: (issue) => + issue.input === undefined + ? "name es requerido" + : "name debe ser un texto" + }) .min(1, "name no puede estar vacío") .max(50, "name no puede superar 50 caracteres") .optional() From c07a82aa8e44c88f93aa45d36b90b672bb20ffc8 Mon Sep 17 00:00:00 2001 From: CrisNAC Date: Thu, 19 Mar 2026 00:21:30 -0300 Subject: [PATCH 6/6] OM-273: Correcciones de CodeRabbit v3 --- src/modules/global/dtos/addresses/address.dto.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/modules/global/dtos/addresses/address.dto.ts b/src/modules/global/dtos/addresses/address.dto.ts index 27679ba..5ced6f1 100644 --- a/src/modules/global/dtos/addresses/address.dto.ts +++ b/src/modules/global/dtos/addresses/address.dto.ts @@ -29,11 +29,13 @@ export const CreateAddressDTO = z.object({ region: z .string({ error: "region es requerida" }) + .trim() .min(1, "region no puede estar vacía") .max(100, "region no puede superar 100 caracteres"), postal_code: z .string() + .trim() .max(20, "postal_code no puede superar 20 caracteres") .nullable() .optional() @@ -58,12 +60,14 @@ export const UpdateAddressDTO = z region: z .string() + .trim() .min(1, "region no puede estar vacía") .max(100, "region no puede superar 100 caracteres") .optional(), postal_code: z .string() + .trim() .max(20, "postal_code no puede superar 20 caracteres") .nullable() .optional() @@ -81,8 +85,8 @@ export const FilterAddressDTO = z.object({ .pipe(z.number().int().positive("fk_user debe ser un ID válido")) .optional(), - city: z.string().optional(), - region: z.string().optional(), + city: z.string().trim().optional(), + region: z.string().trim().optional(), page: z .string()