diff --git a/studyAi/package-lock.json b/studyAi/package-lock.json index 0f775098..75c2d602 100644 --- a/studyAi/package-lock.json +++ b/studyAi/package-lock.json @@ -16,15 +16,25 @@ "@fortawesome/free-solid-svg-icons": "^6.4.2", "@fortawesome/react-fontawesome": "^0.2.0", "@mui/material": "^5.14.12", + "@next-auth/prisma-adapter": "^1.0.7", + "@prisma/client": "^5.4.2", + "axios": "^1.5.1", + "bcryptjs": "^2.4.3", + "dotenv": "^16.3.1", "lodash": "^4.17.21", + "mongodb": "^6.1.0", + "moongoose": "^0.0.5", "mssql": "^10.0.1", "next": "13.5.4", "next-auth": "^4.23.2", "react": "18", - "react-dom": "18" + "react-dom": "18", + "zod": "^3.22.4" }, "devDependencies": { + "@types/bcryptjs": "^2.4.5", "@types/lodash": "^4.14.199", + "@types/mongoose": "^5.11.97", "@types/mssql": "^9.1.1", "@types/node": "20", "@types/react": "18", @@ -890,6 +900,14 @@ "resolved": "https://registry.npmjs.org/@js-joda/core/-/core-5.6.1.tgz", "integrity": "sha512-Xla/d7ZMMR6+zRd6lTio0wRZECfcfFJP7GGe9A9L4tDOlD5CX4YcZ4YZle9w58bBYzssojVapI84RraKWDQZRg==" }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.0.tgz", + "integrity": "sha512-Xfijy7HvfzzqiOAhAepF4SGN5e9leLkMvg/OPOF97XemjfVCYN/oWa75wnkc6mltMSTwY+XlbhWgUOJmkFspSw==", + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, "node_modules/@mui/base": { "version": "5.0.0-beta.19", "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.19.tgz", @@ -1120,6 +1138,15 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, + "node_modules/@next-auth/prisma-adapter": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@next-auth/prisma-adapter/-/prisma-adapter-1.0.7.tgz", + "integrity": "sha512-Cdko4KfcmKjsyHFrWwZ//lfLUbcLqlyFqjd/nYE2m3aZ7tjMNUjpks47iw7NTCnXf+5UWz5Ypyt1dSs1EP5QJw==", + "peerDependencies": { + "@prisma/client": ">=2.26.0 || >=3", + "next-auth": "^4" + } + }, "node_modules/@next/env": { "version": "13.5.4", "resolved": "https://registry.npmjs.org/@next/env/-/env-13.5.4.tgz", @@ -1321,6 +1348,31 @@ "url": "https://opencollective.com/popperjs" } }, + "node_modules/@prisma/client": { + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.4.2.tgz", + "integrity": "sha512-2xsPaz4EaMKj1WS9iW6MlPhmbqtBsXAOeVttSePp8vTFTtvzh2hZbDgswwBdSCgPzmmwF+tLB259QzggvCmJqA==", + "hasInstallScript": true, + "dependencies": { + "@prisma/engines-version": "5.4.1-2.ac9d7041ed77bcc8a8dbd2ab6616b39013829574" + }, + "engines": { + "node": ">=16.13" + }, + "peerDependencies": { + "prisma": "*" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + } + } + }, + "node_modules/@prisma/engines-version": { + "version": "5.4.1-2.ac9d7041ed77bcc8a8dbd2ab6616b39013829574", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.4.1-2.ac9d7041ed77bcc8a8dbd2ab6616b39013829574.tgz", + "integrity": "sha512-wvupDL4AA1vf4TQNANg7kR7y98ITqPsk6aacfBxZKtrJKRIsWjURHkZCGcQliHdqCiW/hGreO6d6ZuSv9MhdAA==" + }, "node_modules/@rushstack/eslint-patch": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.5.1.tgz", @@ -1372,6 +1424,12 @@ "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", "dev": true }, + "node_modules/@types/bcryptjs": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.5.tgz", + "integrity": "sha512-tOF6TivOIvq+TWQm78335CMdyVJhpBG3NUdWQDAp95ax4E2rSKbws/ELHLk5EBoucwx/tHt3/hhLOHwWJgVrSw==", + "dev": true + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -1384,6 +1442,16 @@ "integrity": "sha512-Vrjz5N5Ia4SEzWWgIVwnHNEnb1UE1XMkvY5DGXrAeOGE9imk0hgTHh5GyDjLDJi9OTCn9oo9dXH1uToK1VRfrg==", "dev": true }, + "node_modules/@types/mongoose": { + "version": "5.11.97", + "resolved": "https://registry.npmjs.org/@types/mongoose/-/mongoose-5.11.97.tgz", + "integrity": "sha512-cqwOVYT3qXyLiGw7ueU2kX9noE8DPGRY6z8eUxudhXY8NZ7DMKYAxyZkLSevGfhCX3dO/AoX5/SO9lAzfjon0Q==", + "deprecated": "Mongoose publishes its own types, so you do not need to install this package.", + "dev": true, + "dependencies": { + "mongoose": "*" + } + }, "node_modules/@types/mssql": { "version": "9.1.1", "resolved": "https://registry.npmjs.org/@types/mssql/-/mssql-9.1.1.tgz", @@ -1398,8 +1466,7 @@ "node_modules/@types/node": { "version": "20.8.3", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.3.tgz", - "integrity": "sha512-jxiZQFpb+NlH5kjW49vXxvxTjeeqlbsnTAdBTKpzEdPs9itay7MscYXz3Fo9VYFEsfQ6LJFitHad3faerLAjCw==", - "dev": true + "integrity": "sha512-jxiZQFpb+NlH5kjW49vXxvxTjeeqlbsnTAdBTKpzEdPs9itay7MscYXz3Fo9VYFEsfQ6LJFitHad3faerLAjCw==" }, "node_modules/@types/parse-json": { "version": "4.0.0", @@ -1452,6 +1519,20 @@ "@types/node": "*" } }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.2.tgz", + "integrity": "sha512-uNv6b/uGRLlCVmelat2rA8bcVd3k/42mV2EmjhPh6JLkd35T5bgwR/t6xy7a9MWhd9sixIeBUzhBenvk3NO+DQ==" + }, + "node_modules/@types/whatwg-url": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", + "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", + "dependencies": { + "@types/node": "*", + "@types/webidl-conversions": "*" + } + }, "node_modules/@typescript-eslint/parser": { "version": "6.7.4", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.4.tgz", @@ -1891,6 +1972,16 @@ "node": ">=4" } }, + "node_modules/axios": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.1.tgz", + "integrity": "sha512-Q28iYCWzNHjAm+yEAot5QaAMxhMghWLFVf7rRdwhUI+c2jix2DUXjAHXVi+s1ibs3mjPO/cCgbA++3BjD0vP/A==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/axobject-query": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", @@ -1939,6 +2030,11 @@ } ] }, + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -1958,6 +2054,11 @@ "readable-stream": "^4.2.0" } }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -2012,6 +2113,14 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/bson": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.2.0.tgz", + "integrity": "sha512-ID1cI+7bazPDyL9wYy9GaQ8gEEohWvcUl/Yf0dIdutJxnmInEEyCsb4awy/OiBfall7zBA179Pahi3vCdFze3Q==", + "engines": { + "node": ">=16.20.1" + } + }, "node_modules/buffer": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", @@ -2040,6 +2149,11 @@ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" }, + "node_modules/buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha512-Zy8ZXMyxIT6RMTeY7OP/bDndfj6bwCan7SS98CEndS6deHwWPpseeHlwarNcBim+etXnF9HBc1non5JgDaJU1g==" + }, "node_modules/busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -2167,6 +2281,15 @@ "node": ">=6" } }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2224,6 +2347,11 @@ "node": ">= 0.6" } }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, "node_modules/cosmiconfig": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", @@ -2420,6 +2548,17 @@ "csstype": "^3.0.2" } }, + "node_modules/dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -2594,6 +2733,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es6-promise": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz", + "integrity": "sha512-oj4jOSXvWglTsc3wrw86iom3LDPOx1nbipQk+jaG3dy+sMRM6ReSgVr/VlmBuF6lXUrflN9DCcQHeSbAwGUl4g==" + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -3168,6 +3312,25 @@ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, + "node_modules/follow-redirects": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -3597,6 +3760,12 @@ "node": ">= 0.4" } }, + "node_modules/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", + "devOptional": true + }, "node_modules/is-array-buffer": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", @@ -4024,6 +4193,17 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, + "node_modules/json-stable-stringify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz", + "integrity": "sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g==", + "dependencies": { + "jsonify": "^0.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", @@ -4042,6 +4222,14 @@ "json5": "lib/cli.js" } }, + "node_modules/jsonify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", + "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/jsonwebtoken": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", @@ -4116,6 +4304,15 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/kareem": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", + "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==", + "dev": true, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -4256,6 +4453,11 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -4318,6 +4520,242 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/mongodb": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.1.0.tgz", + "integrity": "sha512-AvzNY0zMkpothZ5mJAaIo2bGDjlJQqqAbn9fvtVgwIIUPEfdrqGxqNjjbuKyrgQxg2EvCmfWdjq+4uj96c0YPw==", + "dependencies": { + "@mongodb-js/saslprep": "^1.1.0", + "bson": "^6.1.0", + "mongodb-connection-string-url": "^2.6.0" + }, + "engines": { + "node": ">=16.20.1" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", + "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", + "dependencies": { + "@types/whatwg-url": "^8.2.1", + "whatwg-url": "^11.0.0" + } + }, + "node_modules/mongodb-core": { + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.20.tgz", + "integrity": "sha512-IN57CX5/Q1bhDq6ShAR6gIv4koFsZP7L8WOK1S0lR0pVDQaScffSMV5jxubLsmZ7J+UdqmykKw4r9hG3XQEGgQ==", + "dependencies": { + "bson": "~1.0.4", + "require_optional": "~1.0.0" + } + }, + "node_modules/mongodb-core/node_modules/bson": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.0.9.tgz", + "integrity": "sha512-IQX9/h7WdMBIW/q/++tGd+emQr0XMdeZ6icnT/74Xk9fnabWn+gZgpE+9V+gujL3hhJOoNrnDVY7tWdzc7NUTg==", + "deprecated": "Fixed a critical issue with BSON serialization documented in CVE-2019-2391, see https://bit.ly/2KcpXdo for more details", + "engines": { + "node": ">=0.6.19" + } + }, + "node_modules/mongoose": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-7.6.3.tgz", + "integrity": "sha512-moYP2qWCOdWRDeBxqB/zYwQmQnTBsF5DoolX5uPyI218BkiA1ujGY27P0NTd4oWIX+LLkZPw0LDzlc/7oh1plg==", + "dev": true, + "dependencies": { + "bson": "^5.5.0", + "kareem": "2.5.1", + "mongodb": "5.9.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "16.0.1" + }, + "engines": { + "node": ">=14.20.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mongoose/node_modules/bson": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/bson/-/bson-5.5.1.tgz", + "integrity": "sha512-ix0EwukN2EpC0SRWIj/7B5+A6uQMQy6KMREI9qQqvgpkV2frH63T0UDVd1SYedL6dNCmDBYB3QtXi4ISk9YT+g==", + "dev": true, + "engines": { + "node": ">=14.20.1" + } + }, + "node_modules/mongoose/node_modules/mongodb": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.9.0.tgz", + "integrity": "sha512-g+GCMHN1CoRUA+wb1Agv0TI4YTSiWr42B5ulkiAfLLHitGK1R+PkSAf3Lr5rPZwi/3F04LiaZEW0Kxro9Fi2TA==", + "dev": true, + "dependencies": { + "bson": "^5.5.0", + "mongodb-connection-string-url": "^2.6.0", + "socks": "^2.7.1" + }, + "engines": { + "node": ">=14.20.1" + }, + "optionalDependencies": { + "@mongodb-js/saslprep": "^1.1.0" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.0.0", + "kerberos": "^1.0.0 || ^2.0.0", + "mongodb-client-encryption": ">=2.3.0 <3", + "snappy": "^7.2.2" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + } + } + }, + "node_modules/mongoose/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/moongoose": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/moongoose/-/moongoose-0.0.5.tgz", + "integrity": "sha512-kVF8ZMDP4uk6MU4I3Iuv4+rMrkFWaOP3iVSlJ/t0W5dCelOXk7cfiXnFvLWM7s+PGn7p+CMCBV5WanMGDt4RIg==", + "dependencies": { + "ajv": "^4.1.1", + "bluebird": "^3.4.0", + "mongodb": "^2.2.6", + "streamz": "^1.5.2" + } + }, + "node_modules/moongoose/node_modules/ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha512-I/bSHSNEcFFqXLf91nchoNB9D1Kie3QKcWdchYUaoIg1+1bdWDkdfdlvdIOJbi9U8xR0y+MWc5D+won9v95WlQ==", + "dependencies": { + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" + } + }, + "node_modules/moongoose/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/moongoose/node_modules/mongodb": { + "version": "2.2.36", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.36.tgz", + "integrity": "sha512-P2SBLQ8Z0PVx71ngoXwo12+FiSfbNfGOClAao03/bant5DgLNkOPAck5IaJcEk4gKlQhDEURzfR3xuBG1/B+IA==", + "dependencies": { + "es6-promise": "3.2.1", + "mongodb-core": "2.1.20", + "readable-stream": "2.2.7" + }, + "engines": { + "node": ">=0.10.3" + } + }, + "node_modules/moongoose/node_modules/readable-stream": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz", + "integrity": "sha512-a6ibcfWFhgihuTw/chl+u3fB5ykBZFmnvpyZHebY0MCQE4vvYcsCLpCeaQ1BkH7HdJYavNSqF0WDLeo4IPHQaQ==", + "dependencies": { + "buffer-shims": "~1.0.0", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~1.0.0", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/moongoose/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/moongoose/node_modules/string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "dev": true, + "dependencies": { + "debug": "4.x" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -4995,6 +5433,11 @@ "node": ">= 0.6.0" } }, + "node_modules/process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha512-yN0WQmuCX63LP/TMvAg31nvT6m4vDqJEiiv2CAZqWOGNWutc9DfDk1NPYYmKUFmaVM2UwDowH4u5AHWYP/jxKw==" + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -5005,6 +5448,11 @@ "react-is": "^16.13.1" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", @@ -5153,6 +5601,31 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/require_optional": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", + "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", + "dependencies": { + "resolve-from": "^2.0.0", + "semver": "^5.1.0" + } + }, + "node_modules/require_optional/node_modules/resolve-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha512-qpFcKaXsq8+oRoLilkwyc7zHGF5i9Q2/25NIgLQQ/+VVv9rU4qvr6nXVAw1DsnXJyQkZsR4Ytfbtg5ehfcUssQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require_optional/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/resolve": { "version": "1.22.6", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", @@ -5362,6 +5835,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/sift": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", + "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==", + "dev": true + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -5371,6 +5850,30 @@ "node": ">=8" } }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "devOptional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "devOptional": true, + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -5387,6 +5890,14 @@ "node": ">=0.10.0" } }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "dependencies": { + "memory-pager": "^1.0.2" + } + }, "node_modules/sprintf-js": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", @@ -5409,6 +5920,14 @@ "node": ">=10.0.0" } }, + "node_modules/streamz": { + "version": "1.8.12", + "resolved": "https://registry.npmjs.org/streamz/-/streamz-1.8.12.tgz", + "integrity": "sha512-O75iqd6oo3tqlfCKoReXLwLAweyr0dkzSPxDLPkmHtbPz8Y/+s2sSOAJHpDYzw2LGZbWBbHgd1Df4zw3i7bqiw==", + "dependencies": { + "bluebird": "~3.7.2" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -5727,6 +6246,17 @@ "node": ">=8.0" } }, + "node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/ts-api-utils": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", @@ -5965,8 +6495,7 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/uuid": { "version": "8.3.2", @@ -5994,6 +6523,26 @@ "node": ">=10.13.0" } }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -6123,6 +6672,14 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zod": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", + "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } }, "dependencies": { @@ -6790,6 +7347,14 @@ "resolved": "https://registry.npmjs.org/@js-joda/core/-/core-5.6.1.tgz", "integrity": "sha512-Xla/d7ZMMR6+zRd6lTio0wRZECfcfFJP7GGe9A9L4tDOlD5CX4YcZ4YZle9w58bBYzssojVapI84RraKWDQZRg==" }, + "@mongodb-js/saslprep": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.0.tgz", + "integrity": "sha512-Xfijy7HvfzzqiOAhAepF4SGN5e9leLkMvg/OPOF97XemjfVCYN/oWa75wnkc6mltMSTwY+XlbhWgUOJmkFspSw==", + "requires": { + "sparse-bitfield": "^3.0.3" + } + }, "@mui/base": { "version": "5.0.0-beta.19", "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.19.tgz", @@ -6895,6 +7460,12 @@ } } }, + "@next-auth/prisma-adapter": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@next-auth/prisma-adapter/-/prisma-adapter-1.0.7.tgz", + "integrity": "sha512-Cdko4KfcmKjsyHFrWwZ//lfLUbcLqlyFqjd/nYE2m3aZ7tjMNUjpks47iw7NTCnXf+5UWz5Ypyt1dSs1EP5QJw==", + "requires": {} + }, "@next/env": { "version": "13.5.4", "resolved": "https://registry.npmjs.org/@next/env/-/env-13.5.4.tgz", @@ -6999,6 +7570,19 @@ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==" }, + "@prisma/client": { + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.4.2.tgz", + "integrity": "sha512-2xsPaz4EaMKj1WS9iW6MlPhmbqtBsXAOeVttSePp8vTFTtvzh2hZbDgswwBdSCgPzmmwF+tLB259QzggvCmJqA==", + "requires": { + "@prisma/engines-version": "5.4.1-2.ac9d7041ed77bcc8a8dbd2ab6616b39013829574" + } + }, + "@prisma/engines-version": { + "version": "5.4.1-2.ac9d7041ed77bcc8a8dbd2ab6616b39013829574", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.4.1-2.ac9d7041ed77bcc8a8dbd2ab6616b39013829574.tgz", + "integrity": "sha512-wvupDL4AA1vf4TQNANg7kR7y98ITqPsk6aacfBxZKtrJKRIsWjURHkZCGcQliHdqCiW/hGreO6d6ZuSv9MhdAA==" + }, "@rushstack/eslint-patch": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.5.1.tgz", @@ -7047,6 +7631,12 @@ "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", "dev": true }, + "@types/bcryptjs": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.5.tgz", + "integrity": "sha512-tOF6TivOIvq+TWQm78335CMdyVJhpBG3NUdWQDAp95ax4E2rSKbws/ELHLk5EBoucwx/tHt3/hhLOHwWJgVrSw==", + "dev": true + }, "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -7059,6 +7649,15 @@ "integrity": "sha512-Vrjz5N5Ia4SEzWWgIVwnHNEnb1UE1XMkvY5DGXrAeOGE9imk0hgTHh5GyDjLDJi9OTCn9oo9dXH1uToK1VRfrg==", "dev": true }, + "@types/mongoose": { + "version": "5.11.97", + "resolved": "https://registry.npmjs.org/@types/mongoose/-/mongoose-5.11.97.tgz", + "integrity": "sha512-cqwOVYT3qXyLiGw7ueU2kX9noE8DPGRY6z8eUxudhXY8NZ7DMKYAxyZkLSevGfhCX3dO/AoX5/SO9lAzfjon0Q==", + "dev": true, + "requires": { + "mongoose": "*" + } + }, "@types/mssql": { "version": "9.1.1", "resolved": "https://registry.npmjs.org/@types/mssql/-/mssql-9.1.1.tgz", @@ -7073,8 +7672,7 @@ "@types/node": { "version": "20.8.3", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.3.tgz", - "integrity": "sha512-jxiZQFpb+NlH5kjW49vXxvxTjeeqlbsnTAdBTKpzEdPs9itay7MscYXz3Fo9VYFEsfQ6LJFitHad3faerLAjCw==", - "dev": true + "integrity": "sha512-jxiZQFpb+NlH5kjW49vXxvxTjeeqlbsnTAdBTKpzEdPs9itay7MscYXz3Fo9VYFEsfQ6LJFitHad3faerLAjCw==" }, "@types/parse-json": { "version": "4.0.0", @@ -7127,6 +7725,20 @@ "@types/node": "*" } }, + "@types/webidl-conversions": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.2.tgz", + "integrity": "sha512-uNv6b/uGRLlCVmelat2rA8bcVd3k/42mV2EmjhPh6JLkd35T5bgwR/t6xy7a9MWhd9sixIeBUzhBenvk3NO+DQ==" + }, + "@types/whatwg-url": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", + "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", + "requires": { + "@types/node": "*", + "@types/webidl-conversions": "*" + } + }, "@typescript-eslint/parser": { "version": "6.7.4", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.4.tgz", @@ -7417,6 +8029,16 @@ "integrity": "sha512-/dlp0fxyM3R8YW7MFzaHWXrf4zzbr0vaYb23VBFCl83R7nWNPg/yaQw2Dc8jzCMmDVLhSdzH8MjrsuIUuvX+6g==", "dev": true }, + "axios": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.1.tgz", + "integrity": "sha512-Q28iYCWzNHjAm+yEAot5QaAMxhMghWLFVf7rRdwhUI+c2jix2DUXjAHXVi+s1ibs3mjPO/cCgbA++3BjD0vP/A==", + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "axobject-query": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", @@ -7447,6 +8069,11 @@ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, + "bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" + }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -7463,6 +8090,11 @@ "readable-stream": "^4.2.0" } }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -7494,6 +8126,11 @@ "update-browserslist-db": "^1.0.13" } }, + "bson": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.2.0.tgz", + "integrity": "sha512-ID1cI+7bazPDyL9wYy9GaQ8gEEohWvcUl/Yf0dIdutJxnmInEEyCsb4awy/OiBfall7zBA179Pahi3vCdFze3Q==" + }, "buffer": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", @@ -7508,6 +8145,11 @@ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" }, + "buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha512-Zy8ZXMyxIT6RMTeY7OP/bDndfj6bwCan7SS98CEndS6deHwWPpseeHlwarNcBim+etXnF9HBc1non5JgDaJU1g==" + }, "busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -7588,6 +8230,11 @@ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==" }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==" + }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -7633,6 +8280,11 @@ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, "cosmiconfig": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", @@ -7781,6 +8433,11 @@ "csstype": "^3.0.2" } }, + "dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==" + }, "ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -7931,6 +8588,11 @@ "is-symbol": "^1.0.2" } }, + "es6-promise": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz", + "integrity": "sha512-oj4jOSXvWglTsc3wrw86iom3LDPOx1nbipQk+jaG3dy+sMRM6ReSgVr/VlmBuF6lXUrflN9DCcQHeSbAwGUl4g==" + }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -8371,6 +9033,11 @@ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, + "follow-redirects": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==" + }, "for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -8664,6 +9331,12 @@ "side-channel": "^1.0.4" } }, + "ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", + "devOptional": true + }, "is-array-buffer": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", @@ -8959,6 +9632,14 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, + "json-stable-stringify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz", + "integrity": "sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g==", + "requires": { + "jsonify": "^0.0.1" + } + }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", @@ -8974,6 +9655,11 @@ "minimist": "^1.2.0" } }, + "jsonify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", + "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==" + }, "jsonwebtoken": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", @@ -9043,6 +9729,12 @@ "safe-buffer": "^5.0.1" } }, + "kareem": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", + "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==", + "dev": true + }, "keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -9165,6 +9857,11 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, + "memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" + }, "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -9209,6 +9906,161 @@ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true }, + "mongodb": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.1.0.tgz", + "integrity": "sha512-AvzNY0zMkpothZ5mJAaIo2bGDjlJQqqAbn9fvtVgwIIUPEfdrqGxqNjjbuKyrgQxg2EvCmfWdjq+4uj96c0YPw==", + "requires": { + "@mongodb-js/saslprep": "^1.1.0", + "bson": "^6.1.0", + "mongodb-connection-string-url": "^2.6.0" + } + }, + "mongodb-connection-string-url": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", + "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", + "requires": { + "@types/whatwg-url": "^8.2.1", + "whatwg-url": "^11.0.0" + } + }, + "mongodb-core": { + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.20.tgz", + "integrity": "sha512-IN57CX5/Q1bhDq6ShAR6gIv4koFsZP7L8WOK1S0lR0pVDQaScffSMV5jxubLsmZ7J+UdqmykKw4r9hG3XQEGgQ==", + "requires": { + "bson": "~1.0.4", + "require_optional": "~1.0.0" + }, + "dependencies": { + "bson": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.0.9.tgz", + "integrity": "sha512-IQX9/h7WdMBIW/q/++tGd+emQr0XMdeZ6icnT/74Xk9fnabWn+gZgpE+9V+gujL3hhJOoNrnDVY7tWdzc7NUTg==" + } + } + }, + "mongoose": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-7.6.3.tgz", + "integrity": "sha512-moYP2qWCOdWRDeBxqB/zYwQmQnTBsF5DoolX5uPyI218BkiA1ujGY27P0NTd4oWIX+LLkZPw0LDzlc/7oh1plg==", + "dev": true, + "requires": { + "bson": "^5.5.0", + "kareem": "2.5.1", + "mongodb": "5.9.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "16.0.1" + }, + "dependencies": { + "bson": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/bson/-/bson-5.5.1.tgz", + "integrity": "sha512-ix0EwukN2EpC0SRWIj/7B5+A6uQMQy6KMREI9qQqvgpkV2frH63T0UDVd1SYedL6dNCmDBYB3QtXi4ISk9YT+g==", + "dev": true + }, + "mongodb": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.9.0.tgz", + "integrity": "sha512-g+GCMHN1CoRUA+wb1Agv0TI4YTSiWr42B5ulkiAfLLHitGK1R+PkSAf3Lr5rPZwi/3F04LiaZEW0Kxro9Fi2TA==", + "dev": true, + "requires": { + "@mongodb-js/saslprep": "^1.1.0", + "bson": "^5.5.0", + "mongodb-connection-string-url": "^2.6.0", + "socks": "^2.7.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "moongoose": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/moongoose/-/moongoose-0.0.5.tgz", + "integrity": "sha512-kVF8ZMDP4uk6MU4I3Iuv4+rMrkFWaOP3iVSlJ/t0W5dCelOXk7cfiXnFvLWM7s+PGn7p+CMCBV5WanMGDt4RIg==", + "requires": { + "ajv": "^4.1.1", + "bluebird": "^3.4.0", + "mongodb": "^2.2.6", + "streamz": "^1.5.2" + }, + "dependencies": { + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha512-I/bSHSNEcFFqXLf91nchoNB9D1Kie3QKcWdchYUaoIg1+1bdWDkdfdlvdIOJbi9U8xR0y+MWc5D+won9v95WlQ==", + "requires": { + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "mongodb": { + "version": "2.2.36", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.36.tgz", + "integrity": "sha512-P2SBLQ8Z0PVx71ngoXwo12+FiSfbNfGOClAao03/bant5DgLNkOPAck5IaJcEk4gKlQhDEURzfR3xuBG1/B+IA==", + "requires": { + "es6-promise": "3.2.1", + "mongodb-core": "2.1.20", + "readable-stream": "2.2.7" + } + }, + "readable-stream": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz", + "integrity": "sha512-a6ibcfWFhgihuTw/chl+u3fB5ykBZFmnvpyZHebY0MCQE4vvYcsCLpCeaQ1BkH7HdJYavNSqF0WDLeo4IPHQaQ==", + "requires": { + "buffer-shims": "~1.0.0", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~1.0.0", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "dev": true + }, + "mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "dev": true, + "requires": { + "debug": "4.x" + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -9653,6 +10505,11 @@ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==" }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha512-yN0WQmuCX63LP/TMvAg31nvT6m4vDqJEiiv2CAZqWOGNWutc9DfDk1NPYYmKUFmaVM2UwDowH4u5AHWYP/jxKw==" + }, "prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -9663,6 +10520,11 @@ "react-is": "^16.13.1" } }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", @@ -9766,6 +10628,27 @@ "set-function-name": "^2.0.0" } }, + "require_optional": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", + "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", + "requires": { + "resolve-from": "^2.0.0", + "semver": "^5.1.0" + }, + "dependencies": { + "resolve-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha512-qpFcKaXsq8+oRoLilkwyc7zHGF5i9Q2/25NIgLQQ/+VVv9rU4qvr6nXVAw1DsnXJyQkZsR4Ytfbtg5ehfcUssQ==" + }, + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" + } + } + }, "resolve": { "version": "1.22.6", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", @@ -9898,12 +10781,34 @@ "object-inspect": "^1.9.0" } }, + "sift": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", + "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==", + "dev": true + }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, + "smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "devOptional": true + }, + "socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "devOptional": true, + "requires": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + } + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -9914,6 +10819,14 @@ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" }, + "sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "requires": { + "memory-pager": "^1.0.2" + } + }, "sprintf-js": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", @@ -9929,6 +10842,14 @@ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" }, + "streamz": { + "version": "1.8.12", + "resolved": "https://registry.npmjs.org/streamz/-/streamz-1.8.12.tgz", + "integrity": "sha512-O75iqd6oo3tqlfCKoReXLwLAweyr0dkzSPxDLPkmHtbPz8Y/+s2sSOAJHpDYzw2LGZbWBbHgd1Df4zw3i7bqiw==", + "requires": { + "bluebird": "~3.7.2" + } + }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -10161,6 +11082,14 @@ "is-number": "^7.0.0" } }, + "tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "requires": { + "punycode": "^2.1.1" + } + }, "ts-api-utils": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", @@ -10317,8 +11246,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "uuid": { "version": "8.3.2", @@ -10340,6 +11268,20 @@ "graceful-fs": "^4.1.2" } }, + "webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" + }, + "whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "requires": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -10433,6 +11375,11 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true + }, + "zod": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", + "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==" } } } diff --git a/studyAi/package.json b/studyAi/package.json index be55bbbe..5ebe85e1 100644 --- a/studyAi/package.json +++ b/studyAi/package.json @@ -7,7 +7,8 @@ "dev": "next dev", "build": "next build", "start": "next start", - "lint": "next lint" + "lint": "next lint", + "prisma": "npx prisma generate " }, "dependencies": { "@emotion/react": "^11.11.1", @@ -18,15 +19,25 @@ "@fortawesome/free-solid-svg-icons": "^6.4.2", "@fortawesome/react-fontawesome": "^0.2.0", "@mui/material": "^5.14.12", + "@next-auth/prisma-adapter": "^1.0.7", + "@prisma/client": "^5.4.2", + "axios": "^1.5.1", + "bcryptjs": "^2.4.3", + "dotenv": "^16.3.1", "lodash": "^4.17.21", + "mongodb": "^6.1.0", + "moongoose": "^0.0.5", "mssql": "^10.0.1", "next": "13.5.4", "next-auth": "^4.23.2", "react": "18", - "react-dom": "18" + "react-dom": "18", + "zod": "^3.22.4" }, "devDependencies": { + "@types/bcryptjs": "^2.4.5", "@types/lodash": "^4.14.199", + "@types/mongoose": "^5.11.97", "@types/mssql": "^9.1.1", "@types/node": "20", "@types/react": "18", diff --git a/studyAi/prisma/schema.prisma b/studyAi/prisma/schema.prisma new file mode 100644 index 00000000..f68b8dc9 --- /dev/null +++ b/studyAi/prisma/schema.prisma @@ -0,0 +1,110 @@ +// 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 = "mongodb" + url = env("DATABASE_URL") +} +type QuestionData{ + title String + description String +} +type AnswerData{ + answer String +} +type LikeCounter { + likes Int + dislikes Int +} +model Question { + id String @id @default(auto()) @map("_id") @db.ObjectId + creatorId String + type String + tags String[] + question QuestionData + answer AnswerData + dateCreated DateTime @default(now()) + likeCounter LikeCounter +} + +model QuestionLikes { + id String @id @default(auto()) @map("_id") @db.ObjectId + dateCreated DateTime @default(now()) + userId String @unique @db.ObjectId + questionId String @unique @db.ObjectId +} +model Quiz { + id String @id @default(auto()) @map("_id") @db.ObjectId + name String + tags String + likes Int + creatorId String @unique @db.ObjectId + questionIds String[] + dateCreated DateTime @default(now()) +} +model QuizLikes { + id String @id @default(auto()) @map("_id") @db.ObjectId + dateCreated DateTime @default(now()) + userId String @unique @db.ObjectId + questionId String @unique @db.ObjectId +} +model Submissions { + id String @id @default(auto()) @map("_id") @db.ObjectId + time DateTime @default(now()) + score Int + dateCreated DateTime @default(now()) + userId String @unique @db.ObjectId + quizId String @unique @db.ObjectId +} + +model UserCredentials{ + id String @id @default(auto()) @map("_id") @db.ObjectId + userId String @unique @db.ObjectId + email String @unique + password String? + provider String +} +model Account { + id String @id @default(auto()) @map("_id") @db.ObjectId + userId String @unique @db.ObjectId + type String + provider String + providerAccountId String + refresh_token String? + access_token String? + expires_at Int? + token_type String? + scope String? + id_token String? + session_state String? + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + + @@unique([provider, providerAccountId]) +} +model Session { + id String @id @default(auto()) @map("_id") @db.ObjectId + sessionToken String @unique + userId String @db.ObjectId + expires DateTime + user User @relation(fields: [userId], references: [id], onDelete: Cascade) +} +model User { + id String @id @default(auto()) @map("_id") @db.ObjectId + name String + email String @unique + usersReached Int @default(0) + dateCreated DateTime @default(now()) + emailVerified DateTime? + image String? + accounts Account[] + sessions Session[] +} +model VerificationToken { + id String @id @default(auto()) @map("_id") @db.ObjectId + identifier String + token String @unique + expires DateTime + @@unique([identifier, token]) +} \ No newline at end of file diff --git a/studyAi/scripts/generateEnv.ts b/studyAi/scripts/generateEnv.ts index b2fc5cf0..020b1059 100644 --- a/studyAi/scripts/generateEnv.ts +++ b/studyAi/scripts/generateEnv.ts @@ -64,7 +64,7 @@ const main = async () => { await delay(500); const value = runCommand(`vlt secrets get --plaintext ${str}`); if (!value) return null; - return str + "=" + value; + return str + "=" + `"${value.replace("\n", "")}"\n`; }); const contentArr = await Promise.all(contentArrPromise); //log all errors from secrets diff --git a/studyAi/src/app/api/auth/[...nextauth]/funcs.ts b/studyAi/src/app/api/auth/[...nextauth]/funcs.ts new file mode 100644 index 00000000..6aaba14c --- /dev/null +++ b/studyAi/src/app/api/auth/[...nextauth]/funcs.ts @@ -0,0 +1,52 @@ +import { + connectToDb, + findUniqueByEmail, + prismaDb, +} from "@/app/util/prisma/helpers"; +import { Profile, Account } from "next-auth"; +export const addCredDoc = async ({ + profile, + account, + isNewUser, +}: { + account: Account | null; + profile?: Profile | undefined; + isNewUser?: boolean | undefined; +}) => { + if (!isNewUser) return; + //procced only if new user + if (!profile) return; + //for Oauth provider mapping to db + try { + const { email, name } = profile; + if (!email || !name) return; + await connectToDb(); + const [user, userDoc] = await Promise.all([ + findUniqueByEmail(email, "userCredentials"), + findUniqueByEmail(email, "user"), + ]); + if (account && account.userId && !user) + return await prismaDb.userCredentials.create({ + data: { + userId: account.userId, + email, + provider: "oauth", + }, + }); + //this only occurs when oauth is typically used, + //since sign with email and pw already + //has the cred file created + if (userDoc && !user) + return await prismaDb.userCredentials.create({ + data: { + userId: userDoc.id, + email, + provider: "oauth", + }, + }); + } catch (err) { + console.error(err); + } finally { + prismaDb.$disconnect(); + } +}; diff --git a/studyAi/src/app/api/auth/[...nextauth]/options.ts b/studyAi/src/app/api/auth/[...nextauth]/options.ts index f1562b62..5eb95e40 100644 --- a/studyAi/src/app/api/auth/[...nextauth]/options.ts +++ b/studyAi/src/app/api/auth/[...nextauth]/options.ts @@ -1,45 +1,103 @@ -import type { NextAuthOptions } from 'next-auth' -import GoogleProvider from 'next-auth/providers/google' -import CredentialsProvider from 'next-auth/providers/credentials' - +import type { NextAuthOptions } from "next-auth"; +import bcrypt from "bcryptjs"; +import GoogleProvider from "next-auth/providers/google"; +import CredentialsProvider from "next-auth/providers/credentials"; +import { + connectToDb, + findUniqueByEmail, + findUniqueById, + prismaDb, +} from "@/app/util/prisma/helpers"; +import { PrismaAdapter } from "@next-auth/prisma-adapter"; +import { addCredDoc } from "./funcs"; export const options: NextAuthOptions = { - providers: [ - GoogleProvider({ - clientId: process.env.GOOGLE_CLIENT_ID as string, - clientSecret: process.env.GOOGLE_CLIENT_SECRET as string, - }), - CredentialsProvider({ - name: 'Credentials', - credentials: { - email: { - label: 'Email:', - type: 'text', - placeholder: 'email' - }, - password: { - label: 'Password:', - type: "password", - placeholder: "password" - } - }, - async authorize(credentials) { - const user = { - id: "1", - email: "admin@studyai.com", - password: "studyai" - } - - if (credentials?.email === user.email && credentials?.password === user.password) { - console.log(user.email, user.password) - return user - } else { - return null - } - }, - }), - ], - pages: { - signIn: '/../../../auth/login/page', - newUser: '/../../../auth/signup/page', - } -} + adapter: PrismaAdapter(prismaDb), + session: { + strategy: "jwt", + }, + jwt: { + secret: process.env.NEXTAUTH_SECRET as string, + }, + providers: [ + GoogleProvider({ + clientId: process.env.GOOGLE_CLIENT_ID as string, + clientSecret: process.env.GOOGLE_CLIENT_SECRET as string, + }), + CredentialsProvider({ + name: "Credentials", + credentials: { + email: { + label: "Email", + type: "text", + placeholder: "email", + }, + password: { + label: "Password", + type: "password", + placeholder: "password", + }, + }, + async authorize(credentials, req) { + try { + // check to see if email and password is there + if (!credentials?.email || !credentials.password) { + throw new Error("Please enter an email and password"); + } + await connectToDb(); + const user = await findUniqueByEmail( + credentials.email, + "userCredentials" + ); + //if no user was found + if (!user || !user?.password) throw new Error("No user found"); + // // check to see if password matches + const passwordMatch = await bcrypt.compare( + credentials.password, + user.password + ); + // if password does not match + if (!passwordMatch) throw new Error("Incorrect password"); + const userId = user.userId; + const userInfo = await findUniqueById(userId, "user"); + return userInfo; + } catch (err) { + console.error(err); + return null; + } finally { + prismaDb.$disconnect(); + } + }, + }), + ], + pages: { + signIn: "/../../../auth/login/page", + error: "/../../../auth/login/page", + }, + callbacks: { + async session({ session }) { + try { + await connectToDb(); + const sessionCreds = await findUniqueByEmail( + session.user.email, + "userCredentials" + ); + if (!sessionCreds) return session; + const sessionUser = await findUniqueById(sessionCreds.userId, "user"); + if (!sessionUser) return session; + session.user = sessionUser; + return session; + } catch (err) { + console.error(err); + return session; + } finally { + prismaDb.$disconnect(); + } + }, + }, + events: { + //create a user document on oauth sign in + signIn: async ({ profile, account, isNewUser }) => { + await addCredDoc({ profile, account, isNewUser }); + }, + }, +}; diff --git a/studyAi/src/app/api/auth/[...nextauth]/route.ts b/studyAi/src/app/api/auth/[...nextauth]/route.ts index 31860015..31d07050 100644 --- a/studyAi/src/app/api/auth/[...nextauth]/route.ts +++ b/studyAi/src/app/api/auth/[...nextauth]/route.ts @@ -1,6 +1,10 @@ -import NextAuth from 'next-auth' -import { options } from './options' +import NextAuth from "next-auth"; +import { options } from "./options"; +const env = process.env.NODE_ENV; +if (env === "development") + process.env.NEXTAUTH_URL = process.env.NEXT_AUTH_URL_DEV; +//for prod +else process.env.NEXTAUTH_URL = process.env.NEXTAUTH_URL; +const handler = NextAuth(options); -const handler = NextAuth(options) - -export {handler as GET, handler as POST} +export { handler as GET, handler as POST }; \ No newline at end of file diff --git a/studyAi/src/app/api/seed/route.ts b/studyAi/src/app/api/seed/route.ts deleted file mode 100644 index fd890b2c..00000000 --- a/studyAi/src/app/api/seed/route.ts +++ /dev/null @@ -1,16 +0,0 @@ -import ExecuteQuery from "@/app/mssql/db"; - -import { NextApiRequest, NextApiResponse } from "next"; -import { NextRequest, NextResponse } from "next/server"; - -export async function GET(req: NextRequest, res: NextResponse) { - console.log(await ExecuteQuery("select * from dbo.users")); - - return NextResponse.json({ message: "This is a GET request." }); -} - -// export async function POST(req: NextRequest, res: NextResponse) { -// console.log(await ExecuteQuery("select * from dbo.users")); - -// return NextResponse.json({ message: "This is a GET request." }); -// } diff --git a/studyAi/src/app/api/user/createUser.ts b/studyAi/src/app/api/user/createUser.ts new file mode 100644 index 00000000..3963bbbb --- /dev/null +++ b/studyAi/src/app/api/user/createUser.ts @@ -0,0 +1,65 @@ +import { hash } from "bcryptjs"; +import { + prismaDb, + findUniqueByEmail, + connectToDb, +} from "@/app/util/prisma/helpers"; +import { NextResponse } from "next/server"; +import * as z from "zod"; +//schema for validating user inputs +const userSchema = z.object({ + email: z.string().min(1, "Email is required").email("Invalid Email"), + password: z.string().nullable(), + name: z.string(), + provider: z.string(), +}); +export async function createUser(req: Request) { + try { + const bodyPromise = req.json(); + const [body, _] = await Promise.all([bodyPromise, connectToDb()]); + const { email, password, name, provider } = userSchema.parse(body); + const user = await findUniqueByEmail(email, "userCredentials"); + if (user) + return NextResponse.json({ + status: 409, + user: null, + message: "User with this email, already exists", + }); + const doesUserDocExist = await findUniqueByEmail(email, "user"); + const newUserPromise = doesUserDocExist + ? doesUserDocExist + : prismaDb.user.create({ + data: { + name, + email, + usersReached: 0, + }, + }); + let hashPasswordPromise = null; + if (password) hashPasswordPromise = hash(password, 10); + const [newUser, hashedPassword] = await Promise.all([ + newUserPromise, + hashPasswordPromise, + ]); + await prismaDb.userCredentials.create({ + data: { + userId: newUser.id, + email, + password: hashedPassword, + provider, + }, + }); + return NextResponse.json({ + newUser, + message: "User created successfully", + status: 201, + }); + } catch (err) { + return NextResponse.json({ + status: 500, + message: "Something went wrong", + }); + } finally { + prismaDb.$disconnect(); + } +} diff --git a/studyAi/src/app/api/user/deleteUser.ts b/studyAi/src/app/api/user/deleteUser.ts new file mode 100644 index 00000000..458c7764 --- /dev/null +++ b/studyAi/src/app/api/user/deleteUser.ts @@ -0,0 +1,32 @@ +import { connectToDb, prismaDb } from "@/app/util/prisma/helpers"; +import { NextResponse } from "next/server"; +export async function deleteUser(req: Request) { + try { + const bodyPromise = req.json(); + const [body, _] = await Promise.all([bodyPromise, connectToDb()]); + const { userId } = body; + //add verify token here + const userCred = prismaDb.userCredentials.delete({ + where: { + userId, + }, + }); + const user = prismaDb.user.delete({ + where: { + id: userId, + }, + }); + await Promise.all([userCred, user]); + return NextResponse.json({ + message: "User deleted successfully", + status: 201, + }); + } catch (err) { + return NextResponse.json({ + status: 500, + message: "Something went wrong", + }); + } finally { + prismaDb.$disconnect(); + } +} diff --git a/studyAi/src/app/api/user/route.ts b/studyAi/src/app/api/user/route.ts new file mode 100644 index 00000000..e5af1b8b --- /dev/null +++ b/studyAi/src/app/api/user/route.ts @@ -0,0 +1,3 @@ +import { createUser } from "./createUser"; +import { deleteUser } from "./deleteUser"; +export { createUser as POST, deleteUser as DELETE }; diff --git a/studyAi/src/app/api/utils/sessionFuncs.tsx b/studyAi/src/app/api/utils/sessionFuncs.tsx new file mode 100644 index 00000000..790e55b2 --- /dev/null +++ b/studyAi/src/app/api/utils/sessionFuncs.tsx @@ -0,0 +1,48 @@ +import type { + GetServerSidePropsContext, + NextApiRequest, + NextApiResponse, +} from "next"; +import { getServerSession } from "next-auth/next"; +import { options } from "../auth/[...nextauth]/options"; +import { redirect } from "next/navigation"; + +// Use it in server contexts +export function getSessionData( + ...args: + | [GetServerSidePropsContext["req"], GetServerSidePropsContext["res"]] + | [NextApiRequest, NextApiResponse] + | [] +) { + return getServerSession(...args, options); +} +export const protectRouteSSR = async ( + url: string, + ...context: + | [GetServerSidePropsContext["req"], GetServerSidePropsContext["res"]] + | [NextApiRequest, NextApiResponse] + | [] +) => { + const session = await getSessionData(...context); + if (!session) return redirect(url); + return { + props: { + session, + }, + }; +}; +export const redirectIfLoggedIn = async ( + url: string, + ...context: + | [GetServerSidePropsContext["req"], GetServerSidePropsContext["res"]] + | [NextApiRequest, NextApiResponse] + | [] +) => { + const session = await getSessionData(...context); + if (session) return redirect(url); + return { + props: { + session, + }, + }; +}; diff --git a/studyAi/src/app/api/utils/verifyToken.ts b/studyAi/src/app/api/utils/verifyToken.ts new file mode 100644 index 00000000..11197f65 --- /dev/null +++ b/studyAi/src/app/api/utils/verifyToken.ts @@ -0,0 +1,3 @@ +const verifyToken = (token: string) => { + +} \ No newline at end of file diff --git a/studyAi/src/app/auth/components/authPageWrapper.tsx b/studyAi/src/app/auth/components/authPageWrapper.tsx index dd31b3b7..02a9002b 100644 --- a/studyAi/src/app/auth/components/authPageWrapper.tsx +++ b/studyAi/src/app/auth/components/authPageWrapper.tsx @@ -18,7 +18,13 @@ export const AuthHeader = ({ type }: { type: "login" | "signup" }) => { ); }; -export const AuthPage = ({ type }: { type: "login" | "signup" }) => { +export const AuthPage = ({ + type, + errMessageArr, +}: { + type: "login" | "signup"; + errMessageArr?: { code: string; message: string }[]; +}) => { const bottomText = type === "login" ? "Don't have an account?" : "Already have an account?"; return ( @@ -26,7 +32,7 @@ export const AuthPage = ({ type }: { type: "login" | "signup" }) => {
- + {bottomText} signIn("google"); -export const AuthFormBtns = () => { +import axios from "axios"; +import { useRouter } from "next/navigation"; +import { useRef } from "react"; +import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime"; +const onGoogleSign = async () => await signIn("google"); +const onEmailSign = async ( + creds: { email: string; password: string }, + router: AppRouterInstance +) => { + const signInData = await signIn("credentials", { ...creds, redirect: false }); + if (signInData?.error) { + console.error(signInData.error); + } + if (signInData?.ok && !signInData?.error) { + router.push("/dashboard"); + } +}; +export const AuthFormBtns = ({ type }: { type: "login" | "signup" }) => { + const router = useRouter(); return (
); }; - -export const AuthForm = () => { +export const AuthForm = ({ + type, + errMessageArr, +}: { + type: "login" | "signup"; + errMessageArr?: { code: string; message: string }[]; +}) => { + const router = useRouter(); + //for debounce user inputs + const submitted = useRef(false); const onSubmit = async (e: React.FormEvent) => { e.preventDefault(); - //grab uncontrolled inputs here - const formData = new FormData(e.currentTarget); - const data = Object.fromEntries(formData.entries()); - const { email, password } = data; - const creds = { - email: email.toString(), - password: password.toString(), - }; - signIn("credentials", { ...creds, redirect: false }).then((callback) => { - if (callback?.error) { - console.error(callback.error); + if (submitted.current) return; + submitted.current = true; + try { + const formData = new FormData(e.currentTarget); + const data = Object.fromEntries(formData.entries()); + const { email, password, name } = data; + const creds = { + name: name?.toString(), + email: email.toString(), + password: password.toString(), + provider: "email", + }; + switch (type) { + case "login": + await onEmailSign( + { + email: creds.email, + password: creds.password, + }, + router + ); + return; + case "signup": + const res = await axios({ + method: "POST", + url: "/api/user", + data: { + ...creds, + }, + }); + //immeaditely sign in user + if (res.data.status === 201) { + await onEmailSign( + { + email: creds.email, + password: creds.password, + }, + router + ); + } else console.error("Registration Failed"); + break; } - - if (callback?.ok && !callback?.error) { - console.log("Logged in successfully!"); - } - }); + } catch (err) { + console.error(err); + } finally { + submitted.current = false; + } }; return (
+ {errMessageArr && + errMessageArr.map((err) => ( + + {err.message} + + ))}
+ {type === "signup" && ( + + )} + { className: "text-Black text-sm tracking-tight underline", }} /> - +
); diff --git a/studyAi/src/app/auth/components/client/authWrapper.tsx b/studyAi/src/app/auth/components/client/authWrapper.tsx index f81c6d6e..1ea09a46 100644 --- a/studyAi/src/app/auth/components/client/authWrapper.tsx +++ b/studyAi/src/app/auth/components/client/authWrapper.tsx @@ -14,7 +14,7 @@ const AuthPageWrapper = ({ children }: { children: React.ReactNode }) => { return (
- {children} - - ) +export default function Provider({ children }: { children: React.ReactNode }) { + return {children}; } diff --git a/studyAi/src/app/auth/error/page.tsx b/studyAi/src/app/auth/error/page.tsx new file mode 100644 index 00000000..18388715 --- /dev/null +++ b/studyAi/src/app/auth/error/page.tsx @@ -0,0 +1,57 @@ +import { redirectIfLoggedIn } from "@/app/api/utils/sessionFuncs"; +import AuthPage from "../components/authPageWrapper"; +import { redirect } from "next/navigation"; +function getErrorMessage(errorCode: string) { + let errorMessage; + switch (errorCode) { + case "CredentialsSignin": + errorMessage = "Invalid email or password."; + break; + case "OAuthCreateAccount": + errorMessage = + "There was an error creating your account with this provider (i.e Google, Github, etc)"; + break; + case "OAuthAccountNotLinked": + errorMessage = + "This account is not linked with this provider (i.e Google, Github, etc). Login to your account another way, and link this provider"; + case "EmailSignin": + errorMessage = "The email you provided is not registered."; + break; + case "AccountNotLinked": + errorMessage = "This account is not linked with any provider."; + break; + case "OAuthSignin": + errorMessage = "There was an error with the OAuth provider."; + break; + default: + errorMessage = "An unknown error occurred."; + } + return errorMessage; +} + +const determineErrorMessageArr = (err: string | string[]) => { + if (typeof err === "string") + return [ + { + code: err, + message: getErrorMessage(err), + }, + ]; + return err.map((e) => ({ + code: e, + message: getErrorMessage(e), + })); +}; +export default async function ErrorPage({ + params, + searchParams, +}: { + params: { slug: string }; + searchParams: { [key: string]: string | string[] | undefined }; +}) { + const session = await redirectIfLoggedIn("/dashboard"); + const error = searchParams.error; + if (!error) redirect("/auth/login"); + const errorMessageArr = determineErrorMessageArr(error); + return ; +} diff --git a/studyAi/src/app/auth/login/page.tsx b/studyAi/src/app/auth/login/page.tsx index 1fefaf82..446dedea 100644 --- a/studyAi/src/app/auth/login/page.tsx +++ b/studyAi/src/app/auth/login/page.tsx @@ -1,24 +1,7 @@ -"use client"; - +import { redirectIfLoggedIn } from "@/app/api/utils/sessionFuncs"; import AuthPage from "../components/authPageWrapper"; -import { useState, useEffect } from "react"; -import { signIn, useSession } from "next-auth/react"; -import { useRouter } from "next/navigation"; - - -export default function LoginPage() { - const session = useSession(); - const router = useRouter(); - // --- Check if the user is logged In --- - // useEffect(() => { - // if (session?.status === "authenticated") { - // router.push("./"); - // } - // }, [session]); - if (session) { - console.log('session', session); - } - console.log('no session'); - return ; +export default async function LoginPage() { + const session = await redirectIfLoggedIn("/dashboard"); + return ; } diff --git a/studyAi/src/app/auth/signup/page.tsx b/studyAi/src/app/auth/signup/page.tsx index 8fcd7a36..40f1430c 100644 --- a/studyAi/src/app/auth/signup/page.tsx +++ b/studyAi/src/app/auth/signup/page.tsx @@ -1,4 +1,6 @@ +import { redirectIfLoggedIn } from "@/app/api/utils/sessionFuncs"; import AuthPage from "../components/authPageWrapper"; -export default function SignUpPage() { +export default async function SignUpPage() { + const session = await redirectIfLoggedIn("/dashboard"); return ; } diff --git a/studyAi/src/app/dashboard/page.tsx b/studyAi/src/app/dashboard/page.tsx index 236809b2..d6a5fc77 100644 --- a/studyAi/src/app/dashboard/page.tsx +++ b/studyAi/src/app/dashboard/page.tsx @@ -1,3 +1,16 @@ -export default function DashboardPage() { - return <>; +import { protectRouteSSR } from "../api/utils/sessionFuncs"; +import NavigationWrapper from "../util/components/navigation/navigationWrapper"; +export default async function DashboardPage() { + const sessionData = await protectRouteSSR("/auth/login"); + return ( + + {" "} + Hello + + ); } diff --git a/studyAi/src/app/dashboard/questions/question/components/questionView/page.tsx b/studyAi/src/app/dashboard/questions/question/components/questionView/page.tsx deleted file mode 100644 index 6b8e3274..00000000 --- a/studyAi/src/app/dashboard/questions/question/components/questionView/page.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function QuestionListPage() { - return <>; -} diff --git a/studyAi/src/app/dashboard/questions/question/page.tsx b/studyAi/src/app/dashboard/questions/question/page.tsx deleted file mode 100644 index c190de02..00000000 --- a/studyAi/src/app/dashboard/questions/question/page.tsx +++ /dev/null @@ -1,4 +0,0 @@ -const QuestionPage = () => { - return <> -} -export default QuestionPage \ No newline at end of file diff --git a/studyAi/src/app/dashboard/questions/question/questionView/page.tsx b/studyAi/src/app/dashboard/questions/question/questionView/page.tsx deleted file mode 100644 index 6b8e3274..00000000 --- a/studyAi/src/app/dashboard/questions/question/questionView/page.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function QuestionListPage() { - return <>; -} diff --git a/studyAi/src/app/library/exam/page.tsx b/studyAi/src/app/library/exam/[id]/page.tsx similarity index 100% rename from studyAi/src/app/library/exam/page.tsx rename to studyAi/src/app/library/exam/[id]/page.tsx diff --git a/studyAi/src/app/library/question/[id]/page.tsx b/studyAi/src/app/library/question/[id]/page.tsx new file mode 100644 index 00000000..655172af --- /dev/null +++ b/studyAi/src/app/library/question/[id]/page.tsx @@ -0,0 +1,22 @@ +import NavigationWrapper from "@/app/util/components/navigation/navigationWrapper"; +import NavigationBtns from "../components/client/navigationBtns"; +import QuestionContainer from "../components/server/questionContainer"; +import AnswerContainer from "../components/server/answerContainer"; +export default function QuestionPage() { + return ( + + +
+ + +
+

Question Page

+
+ ); +} diff --git a/studyAi/src/app/library/question/components/client/navigationBtns.tsx b/studyAi/src/app/library/question/components/client/navigationBtns.tsx new file mode 100644 index 00000000..1a572f86 --- /dev/null +++ b/studyAi/src/app/library/question/components/client/navigationBtns.tsx @@ -0,0 +1,46 @@ +"use client"; + +import StopWatch from "@/app/util/components/time/stopwatch"; +import Timer from "@/app/util/components/time/timer"; +import useWindowWidth from "@/app/util/hooks/useWindowWidth"; +import { faArrowLeft, faArrowRight } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { Button } from "@mui/material"; + +export default function NavigationBtns() { + const windowWidth = useWindowWidth(); + return ( +
+ + {/* */} + + +
+ ); +} diff --git a/studyAi/src/app/library/question/components/server/answerContainer.tsx b/studyAi/src/app/library/question/components/server/answerContainer.tsx new file mode 100644 index 00000000..54c924ef --- /dev/null +++ b/studyAi/src/app/library/question/components/server/answerContainer.tsx @@ -0,0 +1,4 @@ +const AnswerContainer = () => { + return <> +}; +export default AnswerContainer; diff --git a/studyAi/src/app/library/question/components/server/questionContainer.tsx b/studyAi/src/app/library/question/components/server/questionContainer.tsx new file mode 100644 index 00000000..a0cf8ad3 --- /dev/null +++ b/studyAi/src/app/library/question/components/server/questionContainer.tsx @@ -0,0 +1,4 @@ +export const QuestionContainer = () => { + return <> +} +export default QuestionContainer \ No newline at end of file diff --git a/studyAi/src/app/library/question/page.tsx b/studyAi/src/app/library/question/page.tsx deleted file mode 100644 index e0298e7f..00000000 --- a/studyAi/src/app/library/question/page.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function QuestionPage() { - return <>; -} diff --git a/studyAi/src/app/mssql/db.tsx b/studyAi/src/app/mssql/db.tsx deleted file mode 100644 index ed5716e0..00000000 --- a/studyAi/src/app/mssql/db.tsx +++ /dev/null @@ -1,26 +0,0 @@ -// db.js -import sql from "mssql"; - -// connection configs -const config = { - user: "studyai_admin", - password: "V46team39", - server: "studyai-server.database.windows.net", - database: "StudyAI", - // port: 1433, - options: { - // instancename: "SQLEXPRESS", - trustedconnection: true, - trustServerCertificate: true, - }, -}; - -export default async function ExecuteQuery(query: any) { - try { - let pool = await sql.connect(config); - let products = await pool.request().query(query); - return products.recordsets; - } catch (error) { - console.log(error); - } -} diff --git a/studyAi/src/app/page.tsx b/studyAi/src/app/page.tsx index cd0a6863..98de47e3 100644 --- a/studyAi/src/app/page.tsx +++ b/studyAi/src/app/page.tsx @@ -1,6 +1,5 @@ import Link from "next/link"; import NavigationWrapper from "./util/components/navigation/navigationWrapper"; - export default function Home() { return ( Dashboard Exams Library Questions Library - Questions Page + Questions Page Exam Page ); diff --git a/studyAi/src/app/util/components/navigation/client/authentication.tsx b/studyAi/src/app/util/components/navigation/client/authentication.tsx index 1183740b..0e2c23b7 100644 --- a/studyAi/src/app/util/components/navigation/client/authentication.tsx +++ b/studyAi/src/app/util/components/navigation/client/authentication.tsx @@ -1,7 +1,11 @@ "use client"; import NextLink from "next/link"; +import { signOut, useSession } from "next-auth/react"; import { UserProfileNav } from "@/app/util/components/navigation/client/userProfile"; import useWindowWidth from "@/app/util/hooks/useWindowWidth"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faRightFromBracket } from "@fortawesome/free-solid-svg-icons"; +import { Button, ButtonProps } from "@mui/material"; export type RecursiveClassNames = { [key: string]: RecursiveClassNames | string | null; value: string | null; @@ -37,7 +41,7 @@ const AuthenticationButtons = ({ {authenicationLinks.map((link, idx) => ( ); }; - +export const LogoutBtn = ( + props: { + icon?: boolean; + } & ButtonProps +) => { + const className = props.className; + const classStyles = + (className ? className : "") + "flex w-full [&>*]:rounded-none"; + const domProps = { ...props }; + delete domProps.icon; + const newProps: ButtonProps = { + ...domProps, + className: classStyles, + sx: props.sx ? props.sx : {}, + }; + const onLogout = () => + signOut({ + callbackUrl: "/auth/login", + }); + return ( + + ); +}; const AuthenticationNav = ({ classNames, authBtnClassNames, - userProfClassNames, -}: { +}: // userProfClassNames, +{ classNames?: string; authBtnClassNames?: RecursiveClassNames; - userProfClassNames?: RecursiveClassNames; + // userProfClassNames?: RecursiveClassNames; }) => { - const isLoggedIn: boolean = true; + const session = useSession(); + const isLoggedIn = session.status === "authenticated"; const windowWidth = useWindowWidth(); const containerClassNames = - "flex flex-col space-y-4 xs:space-0 xs:items-center xs:justify-end xs:h-full xs:flex-row xs:grow" + + "flex flex-col xs:items-center xs:justify-end xs:h-full xs:flex-row xs:grow" + " " + (classNames ? classNames : ""); return ( @@ -69,7 +112,7 @@ const AuthenticationNav = ({ {isLoggedIn ? ( 480} - userProfClassNames={userProfClassNames} + // userProfClassNames={userProfClassNames} /> ) : ( diff --git a/studyAi/src/app/util/components/navigation/client/desktopNavbar.tsx b/studyAi/src/app/util/components/navigation/client/desktopNavbar.tsx index f865f5e2..67acf152 100644 --- a/studyAi/src/app/util/components/navigation/client/desktopNavbar.tsx +++ b/studyAi/src/app/util/components/navigation/client/desktopNavbar.tsx @@ -1,6 +1,6 @@ "use client"; import React from "react"; -import { MenuItem, Menu, Link, Button } from "@mui/material"; +import { MenuItem, Menu, Link } from "@mui/material"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faCaretDown, @@ -10,9 +10,7 @@ import useElementPosition from "@/app/util/hooks/useElementSize"; import { faWandMagicSparkles } from "@fortawesome/free-solid-svg-icons/faWandMagicSparkles"; import { faFileLines } from "@fortawesome/free-regular-svg-icons"; import useDropdown from "@/app/util/hooks/useDropdown"; -import dynamic from "next/dynamic"; - -const menuItemLinks = [ +export const menuItemLinks = [ { href: "/", text: "Create Question", diff --git a/studyAi/src/app/util/components/navigation/client/mobileNavbar.tsx b/studyAi/src/app/util/components/navigation/client/mobileNavbar.tsx index 953645a8..822ec54a 100644 --- a/studyAi/src/app/util/components/navigation/client/mobileNavbar.tsx +++ b/studyAi/src/app/util/components/navigation/client/mobileNavbar.tsx @@ -5,9 +5,13 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faBars, faClose } from "@fortawesome/free-solid-svg-icons"; import dynamic from "next/dynamic"; import AuthenticationNav, { + LogoutBtn, RecursiveClassNames, } from "../client/authentication"; import { NavButtons } from "../server/desktopNavbar"; +import { menuItemLinks } from "./desktopNavbar"; +import NextLink from "next/link"; +import { useSession } from "next-auth/react"; const Drawer = dynamic(() => import("./drawer"), { ssr: false }); export const NavDrawer = ({ children }: { children: React.ReactNode }) => { const [open, setOpen] = React.useState(false); @@ -28,6 +32,8 @@ export const NavDrawer = ({ children }: { children: React.ReactNode }) => { variant="text" aria-label="open-drawer" onClick={toggleDrawer(true)} + className="aspect-square text-2xl" + sx={{ minWidth: 'unset'}} > @@ -42,7 +48,7 @@ export const NavDrawer = ({ children }: { children: React.ReactNode }) => { + +
+ ); +}; +export default TimeControlsWrapper; diff --git a/studyAi/src/app/util/components/time/timer.tsx b/studyAi/src/app/util/components/time/timer.tsx new file mode 100644 index 00000000..74941610 --- /dev/null +++ b/studyAi/src/app/util/components/time/timer.tsx @@ -0,0 +1,84 @@ +//we store state in react-sweet state +"use client"; +import formatMilliseconds from "../../parsers/formatMilliseconds"; +import useTimeHook from "./hooks/useTimeHook"; +import TimeControlsWrapper from "./timeControls"; + +const Timer = ({ + initialTimeLeft, + updateTimeAction, + totalTimeGiven, +}: { + updateTimeAction?: () => void; + initialTimeLeft: number; + totalTimeGiven?: number; +}) => { + const { + time, + stopTimer, + setTime, + updateTimeActionIntervalRef, + intervalRef, + mounted, + setPause, + paused, + } = useTimeHook({ + initialTime: initialTimeLeft, + callback: (time) => { + if (updateTimeAction) updateTimeAction(); + }, + }); + const startTimer = () => { + setPause(false); + //we change local state every second, as a balance between performance and accuracy + intervalRef.current = setInterval(() => { + if (!mounted.current) return; + setTime((prevTime) => { + const newTime = prevTime - 1000; + if (newTime > 0) return newTime; + if (newTime <= 0 && intervalRef.current) { + setPause(true); + clearInterval(intervalRef.current); + } + return 0; + }); + }, 1000); + updateTimeActionIntervalRef.current = setInterval( + () => { + if (!mounted.current) return; + //keep this slower occuring action in sync with locally changing one + if (!intervalRef.current && updateTimeActionIntervalRef.current) + clearInterval(updateTimeActionIntervalRef.current); + //update below function with time value + if (updateTimeAction) updateTimeAction(); + }, + //we update every 5 second to local state (as updating local storage is a costly computation due to stringification) + initialTimeLeft < 5000 ? initialTimeLeft : 5000 + ); + }; + const resetTimer = () => { + if (intervalRef.current) clearInterval(intervalRef.current); + if (updateTimeActionIntervalRef.current) + clearInterval(updateTimeActionIntervalRef.current); + setTime(totalTimeGiven ? totalTimeGiven : 100000); + }; + return ( +
+ +
+ {formatMilliseconds(time)} +
+
+
+ ); +}; + +export default Timer; diff --git a/studyAi/src/app/util/hooks/useElementSize.tsx b/studyAi/src/app/util/hooks/useElementSize.tsx index b1f3cea0..f7281799 100644 --- a/studyAi/src/app/util/hooks/useElementSize.tsx +++ b/studyAi/src/app/util/hooks/useElementSize.tsx @@ -1,20 +1,20 @@ -"use client" +"use client"; +import { debounce } from "lodash"; import { useState, useEffect } from "react"; const useElementPosition = () => { const [elementRef, setRef] = useState(null); - const [position, setPosition] = useState({ x: 0, y: 0, width:0, height:0 }); + const [position, setPosition] = useState({ x: 0, y: 0, width: 0, height: 0 }); useEffect(() => { if (!elementRef) return; const element = elementRef; - const handlePositionChange = () => { + const handlePositionChange = debounce(() => { if (element) { - const { x, y, width, height } = element.getBoundingClientRect(); - setPosition({ x, y, width, height }); + const { x, y, width, height } = element.getBoundingClientRect(); + setPosition({ x, y, width, height }); } - }; - + }, 500); window.addEventListener("resize", handlePositionChange); document.addEventListener("scroll", handlePositionChange); diff --git a/studyAi/src/app/util/hooks/useWindowWidth.tsx b/studyAi/src/app/util/hooks/useWindowWidth.tsx index 4cbcd5d9..81b595ac 100644 --- a/studyAi/src/app/util/hooks/useWindowWidth.tsx +++ b/studyAi/src/app/util/hooks/useWindowWidth.tsx @@ -4,7 +4,7 @@ import { debounce } from "lodash"; const useWindowWidth = () => { const [windowWidth, setWindowWidth] = useState(0); useEffect(() => { - if(windowWidth === 0 ) setWindowWidth(window.innerWidth); + setWindowWidth(window.innerWidth); const handleResize = debounce(() => { setWindowWidth(window.innerWidth); }, 500); diff --git a/studyAi/src/app/util/icons/timerIcon.tsx b/studyAi/src/app/util/icons/timerIcon.tsx new file mode 100644 index 00000000..1a197ab8 --- /dev/null +++ b/studyAi/src/app/util/icons/timerIcon.tsx @@ -0,0 +1,25 @@ +import { SVGProps } from "react"; + +export const TimerIcon = (props: SVGProps) => { + return ( + + + + + + + + ); +}; +export default TimerIcon; diff --git a/studyAi/src/app/util/parsers/formatMilliseconds.tsx b/studyAi/src/app/util/parsers/formatMilliseconds.tsx new file mode 100644 index 00000000..f9adfc11 --- /dev/null +++ b/studyAi/src/app/util/parsers/formatMilliseconds.tsx @@ -0,0 +1,11 @@ +function formatMilliseconds(milliseconds: number): string { + const totalSeconds = Math.floor(milliseconds / 1000); + const minutes = Math.floor(totalSeconds / 60); + const seconds = totalSeconds % 60; + + const formattedMinutes = String(minutes).padStart(2, "0"); + const formattedSeconds = String(seconds).padStart(2, "0"); + + return `${formattedMinutes}:${formattedSeconds}`; +} +export default formatMilliseconds; \ No newline at end of file diff --git a/studyAi/src/app/util/prisma/helpers.ts b/studyAi/src/app/util/prisma/helpers.ts new file mode 100644 index 00000000..9e3b4895 --- /dev/null +++ b/studyAi/src/app/util/prisma/helpers.ts @@ -0,0 +1,40 @@ +import { PrismaClient } from "@prisma/client"; +import { + PrismaTypeMap, + PrismaTypeMapAsGeneric, + assertPrismaModel, +} from "@/app/util/prisma/typeGuards"; +export const prismaDb = new PrismaClient(); +export const connectToDb = async () => { + try { + await prismaDb.$connect(); + } catch (e) { + throw new Error("Unable to connect to database"); + } +}; +export async function findUniqueByEmail( + email: string, + collection: K +): Promise | null> { + const col = prismaDb[collection] as any; + const user = await col.findUnique({ + where: { + email: email, + }, + }); + const docType = assertPrismaModel(collection, user); + return docType; +} +export async function findUniqueById( + id: string, + collection: K +): Promise | null> { + const col = prismaDb[collection] as any; + const doc = await col.findUnique({ + where: { + id: id, + }, + }); + const docType = assertPrismaModel(collection, doc); + return docType; +} diff --git a/studyAi/src/app/util/prisma/typeGuards.ts b/studyAi/src/app/util/prisma/typeGuards.ts new file mode 100644 index 00000000..996c6b36 --- /dev/null +++ b/studyAi/src/app/util/prisma/typeGuards.ts @@ -0,0 +1,123 @@ +import { + User, + UserCredentials, + Question, + QuestionLikes, + Submissions, + Quiz, + QuizLikes, +} from "@prisma/client/edge"; +export type PrismaTypeMap = { + user: User; + userCredentials: UserCredentials; + question: Question; + questionLikes: QuestionLikes; + submissions: Submissions; + quiz: Quiz; + quizLikes: QuizLikes; +}; +export type PrismaTypeMapAsGeneric< + K extends keyof PrismaTypeMap = keyof PrismaTypeMap +> = { + [P in K]: PrismaTypeMap[P]; +}[K]; +function typeWrapper(func: () => boolean) { + try { + return func(); + } catch (e) { + return false; + } +} +export function isUser(obj: any): obj is User { + return typeWrapper( + () => + typeof obj.id === "string" && + typeof obj.name === "string" && + typeof obj.email === "string" && + typeof obj.usersReached === "number" + ); +} +export function isUserCreds(obj: any): obj is UserCredentials { + return typeWrapper( + () => + typeof obj.id === "string" && + typeof obj.userId === "string" && + typeof obj.email === "string" && + typeof obj.provider === "string" + ); +} +export function isQuestion(obj: any): obj is Question { + return typeWrapper( + () => + typeof obj.id === "string" && + typeof obj.creatorId === "string" && + typeof obj.type === "string" && + typeof obj.question === "object" && + typeof obj.question.title === "string" && + typeof obj.question.description === "string" && + typeof obj.answer === "object" && + typeof obj.answer.answer === "string" && + typeof obj.likeCounter === "object" && + typeof obj.likeCounter.likes === "number" && + typeof obj.likeCounter.dislikes === "number" + ); +} +export function isQuestionLikes(obj: any): obj is QuestionLikes { + return typeWrapper( + () => + typeof obj.id === "string" && + typeof obj.userId === "string" && + typeof obj.questionId === "string" + ); +} +export function isSubmissions(obj: any): obj is Submissions { + return typeWrapper( + () => + typeof obj.id === "string" && + typeof obj.score === "number" && + typeof obj.userId === "string" && + typeof obj.quizId === "string" + ); +} +export function isQuiz(obj: any): obj is Quiz { + return typeWrapper( + () => + typeof obj.id === "string" && + typeof obj.name === "string" && + typeof obj.tags === "string" && + typeof obj.likes === "number" && + typeof obj.creatorId === "string" + ); +} +export function isQuizLikes(obj: any): obj is QuizLikes { + return typeWrapper( + () => + typeof obj.id === "string" && + typeof obj.userId === "string" && + typeof obj.questionId === "string" + ); +} +export const assertPrismaModel = ( + collection: K, + doc: PrismaTypeMapAsGeneric +): PrismaTypeMapAsGeneric | null => { + // return doc; + switch (collection) { + case "user": + return isUser(doc) ? doc : null; + case "userCredentials": + return isUserCreds(doc) ? doc : null; + case "question": + return isQuestion(doc) ? doc : null; + case "questionLikes": + return isQuestionLikes(doc) ? doc : null; + case "submissions": + return isSubmissions(doc) ? doc : null; + case "quiz": + return isQuiz(doc) ? doc : null; + case "quizLikes": + return isQuizLikes(doc) ? doc : null; + default: + return doc; + } +}; diff --git a/studyAi/src/app/util/prisma/types.ts b/studyAi/src/app/util/prisma/types.ts new file mode 100644 index 00000000..55cb0433 --- /dev/null +++ b/studyAi/src/app/util/prisma/types.ts @@ -0,0 +1,12 @@ +import { + PrismaClient, +} from "@prisma/client/edge"; +export type IgnorePrismaBuiltins = string extends S + ? string + : S extends "" + ? S + : S extends `$${infer T}` + ? never + : S; +export type PrismaKeys = Exclude; +export type PrismaModelName = IgnorePrismaBuiltins; diff --git a/studyAi/src/app/util/types/UserData.ts b/studyAi/src/app/util/types/UserData.ts index cbac80b9..a00f7c7c 100644 --- a/studyAi/src/app/util/types/UserData.ts +++ b/studyAi/src/app/util/types/UserData.ts @@ -1,6 +1,3 @@ -export interface UserInfo { - id: string; - email: string; - first_name: string; - last_name: string; -} +import { User } from "@prisma/client"; + +export type UserInfo = User \ No newline at end of file diff --git a/studyAi/src/app/util/types/nextauth.d.ts b/studyAi/src/app/util/types/nextauth.d.ts index 6058c98d..63c957d8 100644 --- a/studyAi/src/app/util/types/nextauth.d.ts +++ b/studyAi/src/app/util/types/nextauth.d.ts @@ -1,12 +1,8 @@ -import NextAuth, { DefaultSession } from "next-auth" -import { User, Session } from "next-auth" - +import NextAuth, { DefaultSession } from "next-auth"; +import { Session } from "next-auth"; +import { User } from "@prisma/client"; declare module "next-auth" { - interface Session { - user: { - id: string - email: string - password: string - } - } + interface Session { + user: User; + } }