diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..641cfea --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +DATABASE_URL="file:./dev.db" \ No newline at end of file diff --git a/.gitignore b/.gitignore index 8bacf16..c3cf474 100644 --- a/.gitignore +++ b/.gitignore @@ -35,4 +35,12 @@ lerna-debug.log* !.vscode/extensions.json # Sqlite -*.sqlite \ No newline at end of file +*.sqlite +*.db +*.db-journal + +# Prisma migrations +prisma/migrations + +# .env file +.env \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 546f9a1..c37832b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,13 +12,12 @@ "@nestjs/common": "^9.0.0", "@nestjs/core": "^9.0.0", "@nestjs/platform-express": "^9.0.0", - "@nestjs/typeorm": "^9.0.1", + "@prisma/client": "^4.15.0", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", "reflect-metadata": "^0.1.13", "rxjs": "^7.2.0", - "sqlite3": "^5.1.6", - "typeorm": "^0.3.16" + "sqlite3": "^5.1.6" }, "devDependencies": { "@nestjs/cli": "^9.0.0", @@ -26,7 +25,7 @@ "@nestjs/testing": "^9.0.0", "@types/express": "^4.17.13", "@types/jest": "29.5.0", - "@types/node": "18.15.11", + "@types/node": "^18.15.11", "@types/supertest": "^2.0.11", "@typescript-eslint/eslint-plugin": "^5.0.0", "@typescript-eslint/parser": "^5.0.0", @@ -35,13 +34,14 @@ "eslint-plugin-prettier": "^4.0.0", "jest": "29.5.0", "prettier": "^2.3.2", + "prisma": "^4.15.0", "source-map-support": "^0.5.20", "supertest": "^6.1.3", "ts-jest": "29.0.5", "ts-loader": "^9.2.3", - "ts-node": "^10.0.0", + "ts-node": "^10.9.1", "tsconfig-paths": "4.2.0", - "typescript": "^4.7.4" + "typescript": "^4.9.5" } }, "node_modules/@ampproject/remapping": { @@ -671,17 +671,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/runtime": { - "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.3.tgz", - "integrity": "sha512-XsDuspWKLUsxwCp6r7EhsExHtYfbe5oAGQ19kqngTdCPUoPQzOPdUbD/pB9PJiwb2ptYKQDjSJT3R6dC+EPqfQ==", - "dependencies": { - "regenerator-runtime": "^0.13.11" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/template": { "version": "7.21.9", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.21.9.tgz", @@ -760,7 +749,7 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "devOptional": true, + "dev": true, "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, @@ -772,7 +761,7 @@ "version": "0.3.9", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "devOptional": true, + "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -1299,7 +1288,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "devOptional": true, + "dev": true, "engines": { "node": ">=6.0.0" } @@ -1327,7 +1316,7 @@ "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "devOptional": true + "dev": true }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.18", @@ -1600,21 +1589,6 @@ } } }, - "node_modules/@nestjs/typeorm": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@nestjs/typeorm/-/typeorm-9.0.1.tgz", - "integrity": "sha512-A2BgLIPsMtmMI0bPKEf4bmzgFPsnvHqNBx3KkvaJ7hJrBQy0OqYOb+Rr06ifblKWDWS2tUPNrAFQbZjtk3PI+g==", - "dependencies": { - "uuid": "8.3.2" - }, - "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0", - "@nestjs/core": "^8.0.0 || ^9.0.0", - "reflect-metadata": "^0.1.13", - "rxjs": "^7.2.0", - "typeorm": "^0.3.0" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1718,6 +1692,38 @@ "npm": ">=5.0.0" } }, + "node_modules/@prisma/client": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.15.0.tgz", + "integrity": "sha512-xnROvyABcGiwqRNdrObHVZkD9EjkJYHOmVdlKy1yGgI+XOzvMzJ4tRg3dz1pUlsyhKxXGCnjIQjWW+2ur+YXuw==", + "hasInstallScript": true, + "dependencies": { + "@prisma/engines-version": "4.15.0-28.8fbc245156db7124f997f4cecdd8d1219e360944" + }, + "engines": { + "node": ">=14.17" + }, + "peerDependencies": { + "prisma": "*" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + } + } + }, + "node_modules/@prisma/engines": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.15.0.tgz", + "integrity": "sha512-FTaOCGs0LL0OW68juZlGxFtYviZa4xdQj/rQEdat2txw0s3Vu/saAPKjNVXfIgUsGXmQ72HPgNr6935/P8FNAA==", + "devOptional": true, + "hasInstallScript": true + }, + "node_modules/@prisma/engines-version": { + "version": "4.15.0-28.8fbc245156db7124f997f4cecdd8d1219e360944", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-4.15.0-28.8fbc245156db7124f997f4cecdd8d1219e360944.tgz", + "integrity": "sha512-sVOig4tjGxxlYaFcXgE71f/rtFhzyYrfyfNFUsxCIEJyVKU9rdOWIlIwQ2NQ7PntvGnn+x0XuFo4OC1jvPJKzg==" + }, "node_modules/@sinclair/typebox": { "version": "0.25.24", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", @@ -1742,11 +1748,6 @@ "@sinonjs/commons": "^3.0.0" } }, - "node_modules/@sqltools/formatter": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", - "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==" - }, "node_modules/@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -1760,25 +1761,25 @@ "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "devOptional": true + "dev": true }, "node_modules/@tsconfig/node12": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "devOptional": true + "dev": true }, "node_modules/@tsconfig/node14": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "devOptional": true + "dev": true }, "node_modules/@tsconfig/node16": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "devOptional": true + "dev": true }, "node_modules/@types/babel__core": { "version": "7.20.1", @@ -1955,7 +1956,7 @@ "version": "18.15.11", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz", "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==", - "devOptional": true + "dev": true }, "node_modules/@types/parse-json": { "version": "4.0.0", @@ -2419,7 +2420,7 @@ "version": "8.8.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "devOptional": true, + "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -2449,7 +2450,7 @@ "version": "8.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "devOptional": true, + "dev": true, "engines": { "node": ">=0.4.0" } @@ -2583,11 +2584,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" - }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -2601,14 +2597,6 @@ "node": ">= 8" } }, - "node_modules/app-root-path": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz", - "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==", - "engines": { - "node": ">= 6.0.0" - } - }, "node_modules/append-field": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", @@ -2648,7 +2636,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "devOptional": true + "dev": true }, "node_modules/argparse": { "version": "2.0.1", @@ -2782,6 +2770,7 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, "funding": [ { "type": "github", @@ -3256,61 +3245,6 @@ "node": ">=8" } }, - "node_modules/cli-highlight": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", - "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", - "dependencies": { - "chalk": "^4.0.0", - "highlight.js": "^10.7.1", - "mz": "^2.4.0", - "parse5": "^5.1.1", - "parse5-htmlparser2-tree-adapter": "^6.0.0", - "yargs": "^16.0.0" - }, - "bin": { - "highlight": "bin/highlight" - }, - "engines": { - "node": ">=8.0.0", - "npm": ">=5.0.0" - } - }, - "node_modules/cli-highlight/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/cli-highlight/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cli-highlight/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "engines": { - "node": ">=10" - } - }, "node_modules/cli-spinners": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.0.tgz", @@ -3351,6 +3285,7 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -3546,7 +3481,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "devOptional": true + "dev": true }, "node_modules/cross-spawn": { "version": "7.0.3", @@ -3562,21 +3497,6 @@ "node": ">= 8" } }, - "node_modules/date-fns": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", - "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", - "dependencies": { - "@babel/runtime": "^7.21.0" - }, - "engines": { - "node": ">=0.11" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" - } - }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -3688,7 +3608,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "devOptional": true, + "dev": true, "engines": { "node": ">=0.3.1" } @@ -3726,14 +3646,6 @@ "node": ">=6.0.0" } }, - "node_modules/dotenv": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", - "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", - "engines": { - "node": ">=12" - } - }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -3847,6 +3759,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, "engines": { "node": ">=6" } @@ -4673,6 +4586,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -4857,14 +4771,6 @@ "node": ">=8" } }, - "node_modules/highlight.js": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", - "engines": { - "node": "*" - } - }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -4951,6 +4857,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, "funding": [ { "type": "github", @@ -6139,7 +6046,7 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "devOptional": true + "dev": true }, "node_modules/make-fetch-happen": { "version": "9.1.0", @@ -6557,16 +6464,6 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -6989,24 +6886,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse5": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", - "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dependencies": { - "parse5": "^6.0.1" - } - }, - "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" - }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -7257,6 +7136,23 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/prisma": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-4.15.0.tgz", + "integrity": "sha512-iKZZpobPl48gTcSZVawLMQ3lEy6BnXwtoMj7hluoGFYu2kQ6F9LBuBrUyF95zRVnNo8/3KzLXJXJ5TEnLSJFiA==", + "devOptional": true, + "hasInstallScript": true, + "dependencies": { + "@prisma/engines": "4.15.0" + }, + "bin": { + "prisma": "build/index.js", + "prisma2": "build/index.js" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -7460,15 +7356,11 @@ "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" }, - "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -7847,18 +7739,6 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -8405,25 +8285,6 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -8557,7 +8418,7 @@ "version": "10.9.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "devOptional": true, + "dev": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -8709,198 +8570,11 @@ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" }, - "node_modules/typeorm": { - "version": "0.3.16", - "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.16.tgz", - "integrity": "sha512-wJ4Qy1oqRKNDdZiBTTaVMqwo/XxC52Q7uNPTjltPgLhvIW173bL6Iad0lhptMOsFlpixFPaUu3PNziaRBwX2Zw==", - "dependencies": { - "@sqltools/formatter": "^1.2.5", - "app-root-path": "^3.1.0", - "buffer": "^6.0.3", - "chalk": "^4.1.2", - "cli-highlight": "^2.1.11", - "date-fns": "^2.29.3", - "debug": "^4.3.4", - "dotenv": "^16.0.3", - "glob": "^8.1.0", - "mkdirp": "^2.1.3", - "reflect-metadata": "^0.1.13", - "sha.js": "^2.4.11", - "tslib": "^2.5.0", - "uuid": "^9.0.0", - "yargs": "^17.6.2" - }, - "bin": { - "typeorm": "cli.js", - "typeorm-ts-node-commonjs": "cli-ts-node-commonjs.js", - "typeorm-ts-node-esm": "cli-ts-node-esm.js" - }, - "engines": { - "node": ">= 12.9.0" - }, - "funding": { - "url": "https://opencollective.com/typeorm" - }, - "peerDependencies": { - "@google-cloud/spanner": "^5.18.0", - "@sap/hana-client": "^2.12.25", - "better-sqlite3": "^7.1.2 || ^8.0.0", - "hdb-pool": "^0.1.6", - "ioredis": "^5.0.4", - "mongodb": "^5.2.0", - "mssql": "^9.1.1", - "mysql2": "^2.2.5 || ^3.0.1", - "oracledb": "^5.1.0", - "pg": "^8.5.1", - "pg-native": "^3.0.0", - "pg-query-stream": "^4.0.0", - "redis": "^3.1.1 || ^4.0.0", - "sql.js": "^1.4.0", - "sqlite3": "^5.0.3", - "ts-node": "^10.7.0", - "typeorm-aurora-data-api-driver": "^2.0.0" - }, - "peerDependenciesMeta": { - "@google-cloud/spanner": { - "optional": true - }, - "@sap/hana-client": { - "optional": true - }, - "better-sqlite3": { - "optional": true - }, - "hdb-pool": { - "optional": true - }, - "ioredis": { - "optional": true - }, - "mongodb": { - "optional": true - }, - "mssql": { - "optional": true - }, - "mysql2": { - "optional": true - }, - "oracledb": { - "optional": true - }, - "pg": { - "optional": true - }, - "pg-native": { - "optional": true - }, - "pg-query-stream": { - "optional": true - }, - "redis": { - "optional": true - }, - "sql.js": { - "optional": true - }, - "sqlite3": { - "optional": true - }, - "ts-node": { - "optional": true - }, - "typeorm-aurora-data-api-driver": { - "optional": true - } - } - }, - "node_modules/typeorm/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/typeorm/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/typeorm/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/typeorm/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/typeorm/node_modules/mkdirp": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.6.tgz", - "integrity": "sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/typeorm/node_modules/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/typescript": { "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "devOptional": true, + "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -9007,19 +8681,11 @@ "node": ">= 0.4.0" } }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "devOptional": true + "dev": true }, "node_modules/v8-to-istanbul": { "version": "9.1.0", @@ -9266,6 +8932,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -9308,6 +8975,7 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, "engines": { "node": ">=10" } @@ -9331,6 +8999,7 @@ "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -9348,6 +9017,7 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, "engines": { "node": ">=12" } @@ -9356,7 +9026,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "devOptional": true, + "dev": true, "engines": { "node": ">=6" } diff --git a/package.json b/package.json index e4d826c..2d0a765 100644 --- a/package.json +++ b/package.json @@ -17,19 +17,19 @@ "test:watch": "jest --watch", "test:cov": "jest --coverage", "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", - "test:e2e": "jest --config ./test/jest-e2e.json" + "test:e2e": "jest --config ./test/jest-e2e.json", + "migrate": "prisma migrate dev" }, "dependencies": { "@nestjs/common": "^9.0.0", "@nestjs/core": "^9.0.0", "@nestjs/platform-express": "^9.0.0", - "@nestjs/typeorm": "^9.0.1", + "@prisma/client": "^4.15.0", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", "reflect-metadata": "^0.1.13", "rxjs": "^7.2.0", - "sqlite3": "^5.1.6", - "typeorm": "^0.3.16" + "sqlite3": "^5.1.6" }, "devDependencies": { "@nestjs/cli": "^9.0.0", @@ -37,7 +37,7 @@ "@nestjs/testing": "^9.0.0", "@types/express": "^4.17.13", "@types/jest": "29.5.0", - "@types/node": "18.15.11", + "@types/node": "^18.15.11", "@types/supertest": "^2.0.11", "@typescript-eslint/eslint-plugin": "^5.0.0", "@typescript-eslint/parser": "^5.0.0", @@ -46,13 +46,14 @@ "eslint-plugin-prettier": "^4.0.0", "jest": "29.5.0", "prettier": "^2.3.2", + "prisma": "^4.15.0", "source-map-support": "^0.5.20", "supertest": "^6.1.3", "ts-jest": "29.0.5", "ts-loader": "^9.2.3", - "ts-node": "^10.0.0", + "ts-node": "^10.9.1", "tsconfig-paths": "4.2.0", - "typescript": "^4.7.4" + "typescript": "^4.9.5" }, "jest": { "moduleFileExtensions": [ diff --git a/prisma/prisma.module.ts b/prisma/prisma.module.ts new file mode 100644 index 0000000..1755781 --- /dev/null +++ b/prisma/prisma.module.ts @@ -0,0 +1,8 @@ +import { Module } from '@nestjs/common'; +import { PrismaService } from './prisma.service'; + +@Module({ + providers: [PrismaService], + exports: [PrismaService], +}) +export class PrismaModule {} \ No newline at end of file diff --git a/prisma/prisma.service.ts b/prisma/prisma.service.ts new file mode 100644 index 0000000..f4701c8 --- /dev/null +++ b/prisma/prisma.service.ts @@ -0,0 +1,15 @@ +import { INestApplication, Injectable, OnModuleInit } from '@nestjs/common'; +import { PrismaClient } from '@prisma/client'; + +@Injectable() +export class PrismaService extends PrismaClient implements OnModuleInit { + async onModuleInit() { + await this.$connect(); + } + + async enableShutdownHooks(app: INestApplication) { + this.$on('beforeExit', async () => { + await app.close(); + }); + } +} \ No newline at end of file diff --git a/prisma/schema.prisma b/prisma/schema.prisma new file mode 100644 index 0000000..fe6c810 --- /dev/null +++ b/prisma/schema.prisma @@ -0,0 +1,29 @@ +// This is your Prisma schema file, +// learn more about it in the docs: https://pris.ly/d/prisma-schema + +generator client { + provider = "prisma-client-js" +} + +datasource db { + provider = "sqlite" + url = env("DATABASE_URL") +} + +model BugCard { + id Int @id @default(autoincrement()) + title String + description String +} + +model IssueCard { + id Int @id @default(autoincrement()) + title String + description String +} + +model TaskCard { + id Int @id @default(autoincrement()) + title String + category String +} \ No newline at end of file diff --git a/src/app.module.ts b/src/app.module.ts index f28048f..269b407 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -3,19 +3,10 @@ import { APP_PIPE } from '@nestjs/core'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { CardsModule } from './cards/cards.module'; -import { UtilsModule } from './utils/utils.module'; -import { TypeOrmModule } from '@nestjs/typeorm'; @Module({ imports: [ CardsModule, - UtilsModule, - TypeOrmModule.forRoot({ - type: 'sqlite', - database: 'db.sqlite', - entities: [__dirname + '/**/*.entity{.ts,.js}'], - synchronize: true, - }), ], controllers: [AppController], providers: [ diff --git a/src/cards/cards.controller.ts b/src/cards/cards.controller.ts index e0a4281..1467d71 100644 --- a/src/cards/cards.controller.ts +++ b/src/cards/cards.controller.ts @@ -1,30 +1,32 @@ -import { Controller, Post, Get, Delete, Body, Param } from '@nestjs/common'; +import { Controller, Post, Get, Delete, Body, Param, Patch } from '@nestjs/common'; import { CreateCardDto } from './dtos/create-card.dto'; import { CardsService } from './cards.service'; import { CardType } from './cards.enum'; +import { ValidateCardType } from './validators/card-type.validator'; +import { ValidateId } from './validators/card-id.validator'; -@Controller('cards') +@Controller('trello-manager') export class CardsController { constructor(private cardsService: CardsService) { } - @Post("/trello-manager") + @Post("") async createCard(@Body() body: CreateCardDto) { return await this.cardsService.createCard(body); } - @Get("/trello-manager/:type") - async getCards(@Param() type: CardType) { + @Get("/:type") + async getCards(@ValidateCardType() type: CardType) { return await this.cardsService.getCards(type); } - @Get("/trello-manager/:type/:id") - async getCard(@Param('type') type: CardType, @Param('id') id: number) { + @Get("/:type/:id") + async getCard(@ValidateCardType() type: CardType, @ValidateId() id: number) { return await this.cardsService.getCard(type, id); } - @Delete("/trello-manager/:type/:id") - async deleteCard(@Param('type') type: CardType, @Param('id') id: number) { + @Delete("/:type/:id") + async deleteCard(@ValidateCardType() type: CardType, @ValidateId() id: number) { return await this.cardsService.deleteCard(type, id); } diff --git a/src/cards/cards.module.ts b/src/cards/cards.module.ts index 222c5aa..495efd9 100644 --- a/src/cards/cards.module.ts +++ b/src/cards/cards.module.ts @@ -1,14 +1,11 @@ import { Module } from '@nestjs/common'; import { CardsController } from './cards.controller'; import { CardsService } from './cards.service'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { BugCard } from './entities/bug.card.entity'; -import { IssueCard } from './entities/issue.card.entity'; -import { TaskCard } from './entities/task.card.entity'; +import { PrismaModule } from 'prisma/prisma.module'; @Module({ controllers: [CardsController], providers: [CardsService], - imports: [TypeOrmModule.forFeature([BugCard, IssueCard, TaskCard])], + imports: [PrismaModule], }) export class CardsModule {} diff --git a/src/cards/cards.service.ts b/src/cards/cards.service.ts index 4e56e91..89703d5 100644 --- a/src/cards/cards.service.ts +++ b/src/cards/cards.service.ts @@ -1,11 +1,13 @@ import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common'; import { CreateCardDto } from './dtos/create-card.dto'; import { CardType } from './cards.enum'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; -import { BugCard } from './entities/bug.card.entity'; -import { IssueCard } from './entities/issue.card.entity'; -import { TaskCard } from './entities/task.card.entity'; +import { PrismaService } from 'prisma/prisma.service'; +import { + BugCard as BugCardModel, + IssueCard as IssueCardModel, + TaskCard as TaskCardModel, + Prisma } from '@prisma/client'; + /** @@ -15,21 +17,16 @@ import { TaskCard } from './entities/task.card.entity'; export class CardsService { constructor( - @InjectRepository(BugCard) - private bugCardRepository: Repository, - @InjectRepository(IssueCard) - private issueCardRepository: Repository, - @InjectRepository(TaskCard) - private taskCardRepository: Repository, + private readonly prismaService: PrismaService, ) {} /** * This method creates a card based on the type of card. * * @param {CreateCardDto} card - The card to be created. - * @returns {Promise} The created card. + * @returns {Promise} The created card. */ - async createCard(card: CreateCardDto) { + async createCard(card: CreateCardDto): Promise { switch (card.type) { case CardType.ISSUE: return await this.createIssueCard(card); @@ -40,6 +37,47 @@ export class CardsService { }; } + /** + * This method returns all cards of a given type. + * + * @param {CardType} type - The type of card. + * @returns {Promise} The cards of the given type. + */ + async getCards(type: CardType): Promise { + return this.prismaService[this.formatType(type)].findMany(); + } + + /** + * This method returns a card of a given type and id. + * + * @param {CardType} type - The type of card. + * @param {number} id - The id of the card. + * @returns {Promise} The card of the given type and id. + */ + async getCard(type: CardType, id: number): Promise { + const card = await this.prismaService[this.formatType(type)].findUnique({ where: { id:Number(id) } }); + if (!card){ + throw new NotFoundException(`Card with id ${id} not found`); + }; + return card; + } + + /** + * This method deletes a card of a given type and id. + * + * @param {CardType} type - The type of card. + * @param {number} id - The id of the card. + */ + async deleteCard(type: CardType, id: number) { + await this.prismaService[this.formatType(type)].delete( + { + where: { id: Number(id) } + } + ).catch(() => { + throw new NotFoundException(`Card with id ${id} not found`); + }); + } + /** * This method validates the data of an issue card. * @@ -56,12 +94,17 @@ export class CardsService { * This method creates an issue card. * * @param card - The card to be created. - * @returns {Promise} The created card. + * @returns {Promise} The created card. */ - async createIssueCard(card: CreateCardDto) { - this.validateIssueCard - const issueCard = this.issueCardRepository.create(card); - return await this.issueCardRepository.save(issueCard); + async createIssueCard(card: CreateCardDto): Promise { + this.validateIssueCard(card); + const issueCard = this.prismaService.issueCard.create({ + data: { + title: card.title, + description: card.description, + }, + }); + return issueCard; } /** @@ -80,12 +123,17 @@ export class CardsService { * This method creates a task card. * * @param card - The card to be created. - * @returns {Promise} The created card. + * @returns {Promise} The created card. */ - async createTaskCard(card: CreateCardDto) { - this.validateTaskCard - const taskCard = this.taskCardRepository.create(card); - return await this.taskCardRepository.save(taskCard); + async createTaskCard(card: CreateCardDto): Promise { + this.validateTaskCard(card) + const taskCard = this.prismaService.taskCard.create({ + data: { + title: card.title, + category: card.category, + }, + }); + return taskCard; } /** @@ -104,68 +152,28 @@ export class CardsService { * This method creates a bug card. * * @param card - The card to be created. - * @returns {Promise} The created card. + * @returns {Promise} The created card. * @todo Generate a random title function. */ - async createBugCard(card: CreateCardDto) { + async createBugCard(card: CreateCardDto): Promise { this.validateBugCard(card); card.title = 'Bug'+'-'+'RandomWord'+'-'+ Math.floor(Math.random() * 1000); - const bugCard = this.bugCardRepository.create(card); - return await this.bugCardRepository.save(bugCard); + const bugCard = this.prismaService.bugCard.create({ + data: { + title: card.title, + description: card.description, + }, + }); + return bugCard; } /** - * This method returns all cards of a given type. + * This method returns the Prisma model name based on the type. * * @param {CardType} type - The type of card. - * @returns {Promise} The cards of the given type. + * @returns {string} The Prisma model name. */ - async getCards(type: CardType) { - return this.getCardRepository(type).find(); - } - - /** - * This method returns a card of a given type and id. - * - * @param {CardType} type - The type of card. - * @param {number} id - The id of the card. - * @returns {Promise} The card of the given type and id. - */ - async getCard(type: CardType, id: number) { - return this.getCardRepository(type).findOneBy({id}); - } - - /** - * This method deletes a card of a given type and id. - * - * @param {CardType} type - The type of card. - * @param {number} id - The id of the card. - * @returns {Promise} The deleted card. - * @throws {NotFoundException} - If the card is not found. - */ - async deleteCard(type: CardType, id: number) { - const repo = this.getCardRepository(type); - let card = await repo.findOneBy({id}) - if (!card) { - throw new NotFoundException('Card not found'); - } - return repo.delete(card.id); - } - - /** - * This method returns the repository of a given type of card. - * - * @param {CardType} type - The type of card. - * @returns {Repository | Repository | Repository} The repository of the given type of card. - */ - private getCardRepository(type: CardType) { - switch (type) { - case CardType.ISSUE: - return this.issueCardRepository; - case CardType.TASK: - return this.taskCardRepository; - case CardType.BUG: - return this.bugCardRepository; - }; + private formatType(type: CardType) { + return type.toLowerCase() + 'Card'; } } diff --git a/src/cards/dtos/create-card.dto.ts b/src/cards/dtos/create-card.dto.ts index 567a265..17ccde6 100644 --- a/src/cards/dtos/create-card.dto.ts +++ b/src/cards/dtos/create-card.dto.ts @@ -1,4 +1,4 @@ -import { IsString, IsOptional } from "class-validator"; +import { IsString, IsOptional, IsEnum } from "class-validator"; import { CardType } from "../cards.enum"; import { CardCategory } from "../cards.enum"; @@ -17,5 +17,6 @@ export class CreateCardDto { @IsString() @IsOptional() + @IsEnum(CardCategory) category?: CardCategory; } \ No newline at end of file diff --git a/src/cards/entities/bug.card.entity.ts b/src/cards/entities/bug.card.entity.ts deleted file mode 100644 index 6352949..0000000 --- a/src/cards/entities/bug.card.entity.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; - -@Entity() -export class BugCard { - @PrimaryGeneratedColumn() - id: number; - - @Column() - title: string; - - @Column() - description: string; -} \ No newline at end of file diff --git a/src/cards/entities/issue.card.entity.ts b/src/cards/entities/issue.card.entity.ts deleted file mode 100644 index 178c234..0000000 --- a/src/cards/entities/issue.card.entity.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Entity, Column, PrimaryGeneratedColumn } from "typeorm"; - -@Entity() -export class IssueCard { - @PrimaryGeneratedColumn() - id: number; - - @Column() - title: string; - - @Column() - description: string; -} \ No newline at end of file diff --git a/src/cards/entities/task.card.entity.ts b/src/cards/entities/task.card.entity.ts deleted file mode 100644 index 04eaaaa..0000000 --- a/src/cards/entities/task.card.entity.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Entity, Column, PrimaryGeneratedColumn } from "typeorm"; -import { CardCategory } from "../cards.enum"; - -@Entity() -export class TaskCard { - @PrimaryGeneratedColumn() - id: number; - - @Column() - title: string; - - @Column() - category: CardCategory; -} \ No newline at end of file diff --git a/src/cards/requests.http b/src/cards/requests.http new file mode 100644 index 0000000..37a1ebe --- /dev/null +++ b/src/cards/requests.http @@ -0,0 +1,58 @@ +### Create a new IssueCard +POST http://localhost:3000/trello-manager +content-type: application/json + +{ + "type": "issue", + "title": "Test Issue Title", + "description": "Test Issue Description" +} + +### Create a new BugCard +POST http://localhost:3000/trello-manager +content-type: application/json + +{ + "type": "bug", + "description": "Test Bug Description" +} + +### Create a new TaskCard +POST http://localhost:3000/trello-manager +content-type: application/json + +{ + "type": "task", + "title": "Test Task Title", + "category": "test" +} + + +### List all IssueCards +GET http://localhost:3000/trello-manager/issue + +### List all BugCards +GET http://localhost:3000/trello-manager/bug + +### List all TaskCards +GET http://localhost:3000/trello-manager/task + + +### Get a single IssueCard +GET http://localhost:3000/trello-manager/issue/4 + + +### Get a single BugCard +GET http://localhost:3000/trello-manager/bug/1 + +### Get a single TaskCard +GET http://localhost:3000/trello-manager/task/1 + +### Delete a single IssueCard +DELETE http://localhost:3000/trello-manager/issue/4 + +### Delete a single BugCard +DELETE http://localhost:3000/trello-manager/bug/1 + +### Delete a single TaskCard +DELETE http://localhost:3000/trello-manager/task/1 diff --git a/src/cards/validators/card-id.validator.ts b/src/cards/validators/card-id.validator.ts new file mode 100644 index 0000000..ef18f85 --- /dev/null +++ b/src/cards/validators/card-id.validator.ts @@ -0,0 +1,13 @@ +import { createParamDecorator, BadRequestException, ExecutionContext } from '@nestjs/common'; + +export const ValidateId = createParamDecorator((data, ctx: ExecutionContext) => { + const request = ctx.switchToHttp().getRequest(); + const id = request.params.id + + // Validates if id is a number + if (isNaN(id)) { + throw new BadRequestException('Invalid id'); + } + + return id; +}); \ No newline at end of file diff --git a/src/cards/validators/card-type.validator.ts b/src/cards/validators/card-type.validator.ts new file mode 100644 index 0000000..551f3bb --- /dev/null +++ b/src/cards/validators/card-type.validator.ts @@ -0,0 +1,13 @@ +import { createParamDecorator, BadRequestException, ExecutionContext } from '@nestjs/common'; +import { CardType } from '../cards.enum'; + +export const ValidateCardType = createParamDecorator((data, ctx: ExecutionContext) => { + const request = ctx.switchToHttp().getRequest(); + const type: CardType = request.params.type + + if (!Object.values(CardType).includes(type)) { + throw new BadRequestException('Invalid card type'); + } + + return type; +}); \ No newline at end of file diff --git a/src/utils/utils.module.ts b/src/utils/utils.module.ts deleted file mode 100644 index 6ab7dfe..0000000 --- a/src/utils/utils.module.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { Module } from '@nestjs/common'; - -@Module({}) -export class UtilsModule {}