diff --git a/.husky/pre-commit b/.husky/pre-commit index e52b67f0..344e8095 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -2,5 +2,5 @@ . "$(dirname "$0")/_/husky.sh" npx lint-staged -yarn ts:check -yarn lint +# pnpm run ts:check +# pnpm run lint diff --git a/.npmrc b/.npmrc new file mode 100644 index 00000000..323fbeb4 --- /dev/null +++ b/.npmrc @@ -0,0 +1,6 @@ +public-hoist-pattern[]=@types/* +public-hoist-pattern[]=playwright-core +public-hoist-pattern[]=zod +side-effects-cache=false +strict-peer-dependencies=false +prefer-workspace-packages=true diff --git a/lerna.json b/lerna.json index 0f5ade3a..84eb5c5c 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "version": "3.22.1", "packages": ["packages/*"], - "npmClient": "yarn", + "npmClient": "pnpm", "useWorkspaces": true } diff --git a/next.config.js b/next.config.js index 97f3af44..2631a5c2 100644 --- a/next.config.js +++ b/next.config.js @@ -1,4 +1,7 @@ module.exports = { + compiler: { + styledComponents: true, + }, typescript: { // !! WARN !! // Dangerously allow production builds to successfully complete even if diff --git a/package.json b/package.json index 125473db..5b70f38c 100644 --- a/package.json +++ b/package.json @@ -24,15 +24,16 @@ "node": ">=12.20.0" }, "devDependencies": { - "husky": "^7.0.1", - "lerna": "^3.22.1", - "lint-staged": "^11.1.0", - "prettier": "^2.1.2" + "husky": "^9.1.6", + "lerna": "^8.1.8", + "lint-staged": "^15.2.10", + "prettier": "^3.3.3" }, "lint-staged": { "**/*.{ts,tsx,js,jsx,md,json,html}": [ "prettier --write" ] }, - "license": "MIT" + "license": "MIT", + "packageManager": "pnpm@8.14.0+sha512.5d4bf97b349faf1a51318aa1ba887e99d9c36e203dbcb55938a91fddd2454246cb00723d6642f54d463a0f52a2701dadf8de002a37fc613c9cdc94ed5675ddce" } diff --git a/packages/create-orca-app/package.json b/packages/create-orca-app/package.json index 442781fb..9da20317 100644 --- a/packages/create-orca-app/package.json +++ b/packages/create-orca-app/package.json @@ -30,10 +30,10 @@ }, "license": "MIT", "dependencies": { - "chalk": "^2.4.2", - "commander": "^2.20.0", - "cross-spawn": "^6.0.5", - "rimraf": "^3.0.0", - "validate-npm-package-name": "^3.0.0" + "chalk": "^5.3.0", + "commander": "^12.1.0", + "cross-spawn": "^7.0.3", + "rimraf": "^6.0.1", + "validate-npm-package-name": "^5.0.1" } } diff --git a/packages/orca-api/.eslintignore b/packages/orca-api/.eslintignore deleted file mode 100644 index b7dab5e9..00000000 --- a/packages/orca-api/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules -build \ No newline at end of file diff --git a/packages/orca-api/createSuperAdmin.js b/packages/orca-api/createSuperAdmin.js index ebfa5e4c..d4905168 100644 --- a/packages/orca-api/createSuperAdmin.js +++ b/packages/orca-api/createSuperAdmin.js @@ -26,6 +26,7 @@ if (!email.match(emailRegex)) { async function connectToDb() { try { const client = await mongoose.connect(process.env.MONGO_URL, { + dbName: 'orca', useCreateIndex: true, useNewUrlParser: true, useFindAndModify: false, diff --git a/packages/orca-api/eslint.config.mjs b/packages/orca-api/eslint.config.mjs new file mode 100644 index 00000000..cea670d0 --- /dev/null +++ b/packages/orca-api/eslint.config.mjs @@ -0,0 +1,36 @@ +import typescriptEslint from "@typescript-eslint/eslint-plugin"; +import tsParser from "@typescript-eslint/parser"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import js from "@eslint/js"; +import { FlatCompat } from "@eslint/eslintrc"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all +}); + +export default [{ + ignores: ["**/node_modules", "**/build"], +}, ...compat.extends( + "eslint:recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended", +), { + plugins: { + "@typescript-eslint": typescriptEslint, + }, + + languageOptions: { + parser: tsParser, + }, + + rules: { + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/explicit-module-boundary-types": "off", + }, +}]; \ No newline at end of file diff --git a/packages/orca-api/package.json b/packages/orca-api/package.json index d9e3607d..0396fc74 100644 --- a/packages/orca-api/package.json +++ b/packages/orca-api/package.json @@ -6,7 +6,7 @@ "dev": "ts-node-dev --respawn --transpile-only --watch \"src/**\" --poll src/index.ts", "build": "tsc", "start": "NODE_ENV=production node build/index.js", - "lint": "eslint . --ext .ts", + "lint": "eslint ./src", "ts:check": "tsc -p tsconfig.json --noEmit" }, "repository": { @@ -15,19 +15,19 @@ "directory": "packages/orca-api" }, "dependencies": { - "bcrypt": "^5.0.1", - "cloudinary": "^1.23.0", + "bcrypt": "^5.1.1", + "cloudinary": "^2.4.0", "compression": "^1.7.4", - "connect-mongo": "^3.2.0", - "cookie-parser": "^1.4.5", + "connect-mongo": "^5.1.0", + "cookie-parser": "^1.4.6", "cors": "^2.8.5", - "dotenv": "^8.2.0", + "dotenv": "^16.4.5", "esm": "^3.2.25", - "express": "^4.16.4", - "express-session": "^1.17.1", - "jsonwebtoken": "^8.5.1", + "express": "^4.21.0", + "express-session": "^1.18.0", + "jsonwebtoken": "^9.0.2", "mailgun-js": "^0.22.0", - "mongoose": "^5.10.8", + "mongoose": "^5.13.22", "multer": "^1.4.2", "nodemailer": "^6.6.3", "nodemailer-mailgun-transport": "^2.1.3", @@ -35,27 +35,30 @@ "passport-facebook": "^3.0.0", "passport-github2": "^0.1.12", "passport-google-oauth20": "^2.0.0", - "passport-jwt": "^4.0.0", + "passport-jwt": "^4.0.1", "passport-local": "^1.0.0", - "socket.io": "^3.1.1", + "socket.io": "^4.7.5", "streamifier": "^0.1.1", - "subscriptions-transport-ws": "^0.9.18", - "uuid": "^8.3.1" + "subscriptions-transport-ws": "^0.11.0", + "uuid": "^10.0.0" }, "devDependencies": { + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "^9.10.0", + "@eslint/migrate-config": "^1.3.0", "@types/dotenv": "^8.2.0", - "@types/express-session": "^1.17.3", - "@types/mongoose": "^5.10.1", - "@types/multer": "^1.4.5", - "@types/node": "^14.14.10", - "@types/nodemailer": "^6.4.0", - "@types/passport": "^1.0.4", - "@types/uuid": "^8.3.0", - "@typescript-eslint/eslint-plugin": "^4.28.4", - "@typescript-eslint/parser": "^4.28.4", - "eslint": "^7.31.0", - "faker": "^5.4.0", - "ts-node-dev": "^1.1.6", - "typescript": "^4.1.2" + "@types/express-session": "^1.18.0", + "@types/mongoose": "^5.11.97", + "@types/multer": "^1.4.12", + "@types/node": "^22.5.4", + "@types/nodemailer": "^6.4.15", + "@types/passport": "^1.0.16", + "@types/uuid": "^10.0.0", + "@typescript-eslint/eslint-plugin": "^8.5.0", + "@typescript-eslint/parser": "^8.5.0", + "eslint": "^9.10.0", + "faker": "^6.6.6", + "ts-node-dev": "^2.0.0", + "typescript": "^5.6.2" } } diff --git a/packages/orca-api/pnpm-lock.yaml b/packages/orca-api/pnpm-lock.yaml new file mode 100644 index 00000000..0c596f5c --- /dev/null +++ b/packages/orca-api/pnpm-lock.yaml @@ -0,0 +1,4117 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + bcrypt: + specifier: ^5.0.1 + version: 5.1.1 + cloudinary: + specifier: ^1.23.0 + version: 1.41.3 + compression: + specifier: ^1.7.4 + version: 1.7.4 + connect-mongo: + specifier: ^3.2.0 + version: 3.2.0(express-session@1.18.0) + cookie-parser: + specifier: ^1.4.5 + version: 1.4.6 + cors: + specifier: ^2.8.5 + version: 2.8.5 + dotenv: + specifier: ^8.2.0 + version: 8.6.0 + esm: + specifier: ^3.2.25 + version: 3.2.25 + express: + specifier: ^4.16.4 + version: 4.21.0 + express-session: + specifier: ^1.17.1 + version: 1.18.0 + jsonwebtoken: + specifier: ^8.5.1 + version: 8.5.1 + mailgun-js: + specifier: ^0.22.0 + version: 0.22.0 + mongoose: + specifier: ^8.6.2 + version: 8.6.2 + multer: + specifier: ^1.4.2 + version: 1.4.4 + nodemailer: + specifier: ^6.6.3 + version: 6.9.15 + nodemailer-mailgun-transport: + specifier: ^2.1.3 + version: 2.1.5(lodash@4.17.21) + passport: + specifier: ^0.4.1 + version: 0.4.1 + passport-facebook: + specifier: ^3.0.0 + version: 3.0.0 + passport-github2: + specifier: ^0.1.12 + version: 0.1.12 + passport-google-oauth20: + specifier: ^2.0.0 + version: 2.0.0 + passport-jwt: + specifier: ^4.0.0 + version: 4.0.1 + passport-local: + specifier: ^1.0.0 + version: 1.0.0 + socket.io: + specifier: ^3.1.1 + version: 3.1.2 + streamifier: + specifier: ^0.1.1 + version: 0.1.1 + subscriptions-transport-ws: + specifier: ^0.9.18 + version: 0.9.19(graphql@16.9.0) + uuid: + specifier: ^8.3.1 + version: 8.3.2 + devDependencies: + '@types/dotenv': + specifier: ^8.2.0 + version: 8.2.0 + '@types/express-session': + specifier: ^1.17.3 + version: 1.18.0 + '@types/mongoose': + specifier: ^5.10.1 + version: 5.11.97 + '@types/multer': + specifier: ^1.4.5 + version: 1.4.12 + '@types/node': + specifier: ^14.14.10 + version: 14.18.63 + '@types/nodemailer': + specifier: ^6.4.0 + version: 6.4.15 + '@types/passport': + specifier: ^1.0.4 + version: 1.0.16 + '@types/uuid': + specifier: ^8.3.0 + version: 8.3.4 + '@typescript-eslint/eslint-plugin': + specifier: ^4.28.4 + version: 4.33.0(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@4.9.5))(eslint@7.32.0)(typescript@4.9.5) + '@typescript-eslint/parser': + specifier: ^4.28.4 + version: 4.33.0(eslint@7.32.0)(typescript@4.9.5) + eslint: + specifier: ^7.31.0 + version: 7.32.0 + faker: + specifier: ^5.4.0 + version: 5.5.3 + ts-node-dev: + specifier: ^1.1.6 + version: 1.1.8(typescript@4.9.5) + typescript: + specifier: ^4.1.2 + version: 4.9.5 + +packages: + + '@babel/code-frame@7.12.11': + resolution: {integrity: sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==} + + '@babel/helper-validator-identifier@7.24.7': + resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} + engines: {node: '>=6.9.0'} + + '@babel/highlight@7.24.7': + resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} + engines: {node: '>=6.9.0'} + + '@eslint/eslintrc@0.4.3': + resolution: {integrity: sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==} + engines: {node: ^10.12.0 || >=12.0.0} + + '@humanwhocodes/config-array@0.5.0': + resolution: {integrity: sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==} + engines: {node: '>=10.10.0'} + deprecated: Use @eslint/config-array instead + + '@humanwhocodes/object-schema@1.2.1': + resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} + deprecated: Use @eslint/object-schema instead + + '@mapbox/node-pre-gyp@1.0.11': + resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} + hasBin: true + + '@mongodb-js/saslprep@1.1.9': + resolution: {integrity: sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@types/body-parser@1.19.5': + resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} + + '@types/component-emitter@1.2.14': + resolution: {integrity: sha512-lmPil1g82wwWg/qHSxMWkSKyJGQOK+ejXeMAAWyxNtVUD0/Ycj2maL63RAqpxVfdtvTfZkRnqzB0A9ft59y69g==} + + '@types/connect@3.4.38': + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + + '@types/cookie@0.4.1': + resolution: {integrity: sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==} + + '@types/cors@2.8.17': + resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==} + + '@types/dotenv@8.2.0': + resolution: {integrity: sha512-ylSC9GhfRH7m1EUXBXofhgx4lUWmFeQDINW5oLuS+gxWdfUeW4zJdeVTYVkexEW+e2VUvlZR2kGnGGipAWR7kw==} + deprecated: This is a stub types definition. dotenv provides its own type definitions, so you do not need this installed. + + '@types/express-serve-static-core@4.19.5': + resolution: {integrity: sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==} + + '@types/express-session@1.18.0': + resolution: {integrity: sha512-27JdDRgor6PoYlURY+Y5kCakqp5ulC0kmf7y+QwaY+hv9jEFuQOThgkjyA53RP3jmKuBsH5GR6qEfFmvb8mwOA==} + + '@types/express@4.17.21': + resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} + + '@types/http-errors@2.0.4': + resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/mime@1.3.5': + resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + + '@types/mongoose@5.11.97': + resolution: {integrity: sha512-cqwOVYT3qXyLiGw7ueU2kX9noE8DPGRY6z8eUxudhXY8NZ7DMKYAxyZkLSevGfhCX3dO/AoX5/SO9lAzfjon0Q==} + deprecated: Mongoose publishes its own types, so you do not need to install this package. + + '@types/multer@1.4.12': + resolution: {integrity: sha512-pQ2hoqvXiJt2FP9WQVLPRO+AmiIm/ZYkavPlIQnx282u4ZrVdztx0pkh3jjpQt0Kz+YI0YhSG264y08UJKoUQg==} + + '@types/node@14.18.63': + resolution: {integrity: sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==} + + '@types/nodemailer@6.4.15': + resolution: {integrity: sha512-0EBJxawVNjPkng1zm2vopRctuWVCxk34JcIlRuXSf54habUWdz1FB7wHDqOqvDa8Mtpt0Q3LTXQkAs2LNyK5jQ==} + + '@types/passport@1.0.16': + resolution: {integrity: sha512-FD0qD5hbPWQzaM0wHUnJ/T0BBCJBxCeemtnCwc/ThhTg3x9jfrAcRUmj5Dopza+MfFS9acTe3wk7rcVnRIp/0A==} + + '@types/qs@6.9.15': + resolution: {integrity: sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==} + + '@types/range-parser@1.2.7': + resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + + '@types/send@0.17.4': + resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} + + '@types/serve-static@1.15.7': + resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} + + '@types/strip-bom@3.0.0': + resolution: {integrity: sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==} + + '@types/strip-json-comments@0.0.30': + resolution: {integrity: sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==} + + '@types/uuid@8.3.4': + resolution: {integrity: sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==} + + '@types/webidl-conversions@7.0.3': + resolution: {integrity: sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==} + + '@types/whatwg-url@11.0.5': + resolution: {integrity: sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==} + + '@typescript-eslint/eslint-plugin@4.33.0': + resolution: {integrity: sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==} + engines: {node: ^10.12.0 || >=12.0.0} + peerDependencies: + '@typescript-eslint/parser': ^4.0.0 + eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/experimental-utils@4.33.0': + resolution: {integrity: sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==} + engines: {node: ^10.12.0 || >=12.0.0} + peerDependencies: + eslint: '*' + + '@typescript-eslint/parser@4.33.0': + resolution: {integrity: sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==} + engines: {node: ^10.12.0 || >=12.0.0} + peerDependencies: + eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/scope-manager@4.33.0': + resolution: {integrity: sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==} + engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} + + '@typescript-eslint/types@4.33.0': + resolution: {integrity: sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==} + engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} + + '@typescript-eslint/typescript-estree@4.33.0': + resolution: {integrity: sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==} + engines: {node: ^10.12.0 || >=12.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/visitor-keys@4.33.0': + resolution: {integrity: sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==} + engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1} + + abbrev@1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + + accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@7.4.1: + resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} + engines: {node: '>=0.4.0'} + hasBin: true + + agent-base@4.2.1: + resolution: {integrity: sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==} + engines: {node: '>= 4.0.0'} + + agent-base@4.3.0: + resolution: {integrity: sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==} + engines: {node: '>= 4.0.0'} + + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + append-field@1.0.0: + resolution: {integrity: sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==} + + aproba@2.0.0: + resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} + + are-we-there-yet@2.0.0: + resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} + engines: {node: '>=10'} + deprecated: This package is no longer supported. + + arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + ast-types@0.14.2: + resolution: {integrity: sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA==} + engines: {node: '>=4'} + + astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + + async@2.6.4: + resolution: {integrity: sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + axios@1.7.7: + resolution: {integrity: sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==} + + backo2@1.0.2: + resolution: {integrity: sha512-zj6Z6M7Eq+PBZ7PQxl5NT665MvJdAkzp0f60nAJ+sLaSCBPMwVak5ZegFbgVCzFcCJTKFoMizvM5Ld7+JrRJHA==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + base-64@1.0.0: + resolution: {integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==} + + base64-arraybuffer@0.1.4: + resolution: {integrity: sha512-a1eIFi4R9ySrbiMuyTGx5e92uRH5tQY6kArNcFaKBUleIoLjdjBg7Zxm3Mqm3Kmkf27HLR/1fnxX9q8GQ7Iavg==} + engines: {node: '>= 0.6.0'} + + base64id@2.0.0: + resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} + engines: {node: ^4.5.0 || >= 5.9} + + base64url@3.0.1: + resolution: {integrity: sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==} + engines: {node: '>=6.0.0'} + + bcrypt@5.1.1: + resolution: {integrity: sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==} + engines: {node: '>= 10.0.0'} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + bl@2.2.1: + resolution: {integrity: sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==} + + bluebird@3.7.2: + resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} + + body-parser@1.20.3: + resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + bson@1.1.6: + resolution: {integrity: sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==} + engines: {node: '>=0.6.19'} + + bson@6.8.0: + resolution: {integrity: sha512-iOJg8pr7wq2tg/zSlCCHMi3hMm5JTOxLTagf3zxhcenHsFp+c6uOs6K7W5UE7A4QIJGtqh/ZovFNMP4mOPJynQ==} + engines: {node: '>=16.20.1'} + + buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + busboy@0.2.14: + resolution: {integrity: sha512-InWFDomvlkEj+xWLBfU3AvnbVYqeTWmQopiW0tWWEy5yehYm2YkGEc59sUmw/4ty5Zj/b0WHGs1LgecuBSBGrg==} + engines: {node: '>=0.8.0'} + + bytes@3.0.0: + resolution: {integrity: sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==} + engines: {node: '>= 0.8'} + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + chownr@2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + + cloudinary-core@2.13.1: + resolution: {integrity: sha512-z53GPNWnvU0Zi+ns8CIVbZBfj7ps/++zDvwIyiFuq5p1MoK+KUCg0k5mBceDDHTnx1gHmHUd9aohS+gDxPNt6w==} + peerDependencies: + lodash: '>=4.0' + + cloudinary@1.41.3: + resolution: {integrity: sha512-4o84y+E7dbif3lMns+p3UW6w6hLHEifbX/7zBJvaih1E9QNMZITENQ14GPYJC4JmhygYXsuuBb9bRA3xWEoOfg==} + engines: {node: '>=0.6'} + + co@4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + color-support@1.1.3: + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} + hasBin: true + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + component-emitter@1.3.1: + resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} + + compressible@2.0.18: + resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} + engines: {node: '>= 0.6'} + + compression@1.7.4: + resolution: {integrity: sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==} + engines: {node: '>= 0.8.0'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + concat-stream@1.6.2: + resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} + engines: {'0': node >= 0.8} + + connect-mongo@3.2.0: + resolution: {integrity: sha512-0Mx88079Z20CG909wCFlR3UxhMYGg6Ibn1hkIje1hwsqOLWtL9HJV+XD0DAjUvQScK6WqY/FA8tSVQM9rR64Rw==} + peerDependencies: + express-session: ^1.17.1 + + console-control-strings@1.1.0: + resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} + + consolidate@0.15.1: + resolution: {integrity: sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==} + engines: {node: '>= 0.10.0'} + deprecated: Please upgrade to consolidate v1.0.0+ as it has been modernized with several long-awaited fixes implemented. Maintenance is supported by Forward Email at https://forwardemail.net ; follow/watch https://github.com/ladjs/consolidate for updates and release changelog + peerDependencies: + arc-templates: ^0.5.3 + atpl: '>=0.7.6' + babel-core: ^6.26.3 + bracket-template: ^1.1.5 + coffee-script: ^1.12.7 + dot: ^1.1.3 + dust: ^0.3.0 + dustjs-helpers: ^1.7.4 + dustjs-linkedin: ^2.7.5 + eco: ^1.1.0-rc-3 + ect: ^0.5.9 + ejs: ^3.1.5 + haml-coffee: ^1.14.1 + hamlet: ^0.3.3 + hamljs: ^0.6.2 + handlebars: ^4.7.6 + hogan.js: ^3.0.2 + htmling: ^0.0.8 + jade: ^1.11.0 + jazz: ^0.0.18 + jqtpl: ~1.1.0 + just: ^0.1.8 + liquid-node: ^3.0.1 + liquor: ^0.0.5 + lodash: ^4.17.20 + marko: ^3.14.4 + mote: ^0.2.0 + mustache: ^3.0.0 + nunjucks: ^3.2.2 + plates: ~0.4.11 + pug: ^3.0.0 + qejs: ^3.0.5 + ractive: ^1.3.12 + razor-tmpl: ^1.3.1 + react: ^16.13.1 + react-dom: ^16.13.1 + slm: ^2.0.0 + squirrelly: ^5.1.0 + swig: ^1.4.2 + swig-templates: ^2.0.3 + teacup: ^2.0.0 + templayed: '>=0.2.3' + then-jade: '*' + then-pug: '*' + tinyliquid: ^0.2.34 + toffee: ^0.3.6 + twig: ^1.15.2 + twing: ^5.0.2 + underscore: ^1.11.0 + vash: ^0.13.0 + velocityjs: ^2.0.1 + walrus: ^0.10.1 + whiskers: ^0.4.0 + peerDependenciesMeta: + arc-templates: + optional: true + atpl: + optional: true + babel-core: + optional: true + bracket-template: + optional: true + coffee-script: + optional: true + dot: + optional: true + dust: + optional: true + dustjs-helpers: + optional: true + dustjs-linkedin: + optional: true + eco: + optional: true + ect: + optional: true + ejs: + optional: true + haml-coffee: + optional: true + hamlet: + optional: true + hamljs: + optional: true + handlebars: + optional: true + hogan.js: + optional: true + htmling: + optional: true + jade: + optional: true + jazz: + optional: true + jqtpl: + optional: true + just: + optional: true + liquid-node: + optional: true + liquor: + optional: true + lodash: + optional: true + marko: + optional: true + mote: + optional: true + mustache: + optional: true + nunjucks: + optional: true + plates: + optional: true + pug: + optional: true + qejs: + optional: true + ractive: + optional: true + razor-tmpl: + optional: true + react: + optional: true + react-dom: + optional: true + slm: + optional: true + squirrelly: + optional: true + swig: + optional: true + swig-templates: + optional: true + teacup: + optional: true + templayed: + optional: true + then-jade: + optional: true + then-pug: + optional: true + tinyliquid: + optional: true + toffee: + optional: true + twig: + optional: true + twing: + optional: true + underscore: + optional: true + vash: + optional: true + velocityjs: + optional: true + walrus: + optional: true + whiskers: + optional: true + + content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + cookie-parser@1.4.6: + resolution: {integrity: sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==} + engines: {node: '>= 0.8.0'} + + cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + + cookie-signature@1.0.7: + resolution: {integrity: sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==} + + cookie@0.4.1: + resolution: {integrity: sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==} + engines: {node: '>= 0.6'} + + cookie@0.4.2: + resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==} + engines: {node: '>= 0.6'} + + cookie@0.6.0: + resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} + engines: {node: '>= 0.6'} + + core-js@3.38.1: + resolution: {integrity: sha512-OP35aUorbU3Zvlx7pjsFdu1rGNnD4pgw/CWoYzRY3t2EzoVT7shKHY1dlAy3f41cGIO7ZDPQimhGFTlEYkG/Hw==} + + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + cors@2.8.5: + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} + + create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + + cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + + data-uri-to-buffer@1.2.0: + resolution: {integrity: sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ==} + + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@3.1.0: + resolution: {integrity: sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + degenerator@1.0.4: + resolution: {integrity: sha512-EMAC+riLSC64jKfOs1jp8J7M4ZXstUUwTdwFBEv6HOzL/Ae+eAzMKEK0nJnpof2fnw9IOjmE6u6qXFejVyk8AA==} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + delegates@1.0.0: + resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} + + denque@1.5.1: + resolution: {integrity: sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==} + engines: {node: '>=0.10'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + detect-libc@2.0.3: + resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} + engines: {node: '>=8'} + + dicer@0.2.5: + resolution: {integrity: sha512-FDvbtnq7dzlPz0wyYlOExifDEZcu8h+rErEXgfxqmLfRfC/kJidEFh4+effJRO3P0xmfqyPbSMG0LveNRfTKVg==} + engines: {node: '>=0.8.0'} + + diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + + dotenv@8.6.0: + resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==} + engines: {node: '>=10'} + + dynamic-dedupe@0.3.0: + resolution: {integrity: sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==} + + ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + + engine.io-parser@4.0.3: + resolution: {integrity: sha512-xEAAY0msNnESNPc00e19y5heTPX4y/TJ36gr8t1voOaNmTojP9b3oK3BbJLFufW2XFPQaaijpFewm2g2Um3uqA==} + engines: {node: '>=8.0.0'} + + engine.io@4.1.2: + resolution: {integrity: sha512-t5z6zjXuVLhXDMiFJPYsPOWEER8B0tIsD3ETgw19S1yg9zryvUfY3Vhtk3Gf4sihw/bQGIqQ//gjvVlu+Ca0bQ==} + engines: {node: '>=10.0.0'} + + enquirer@2.4.1: + resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} + engines: {node: '>=8.6'} + + es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es6-promise@4.2.8: + resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==} + + es6-promisify@5.0.0: + resolution: {integrity: sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + escodegen@1.14.3: + resolution: {integrity: sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==} + engines: {node: '>=4.0'} + hasBin: true + + eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + + eslint-utils@2.1.0: + resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==} + engines: {node: '>=6'} + + eslint-utils@3.0.0: + resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} + engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} + peerDependencies: + eslint: '>=5' + + eslint-visitor-keys@1.3.0: + resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==} + engines: {node: '>=4'} + + eslint-visitor-keys@2.1.0: + resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} + engines: {node: '>=10'} + + eslint@7.32.0: + resolution: {integrity: sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==} + engines: {node: ^10.12.0 || >=12.0.0} + hasBin: true + + esm@3.2.25: + resolution: {integrity: sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==} + engines: {node: '>=6'} + + espree@7.3.1: + resolution: {integrity: sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==} + engines: {node: ^10.12.0 || >=12.0.0} + + esprima@3.1.3: + resolution: {integrity: sha512-AWwVMNxwhN8+NIPQzAQZCm7RkLC4RbM3B1OobMuyp3i+w73X57KCKaVIxaRZb+DYCojq7rspo+fmuQfAboyhFg==} + engines: {node: '>=4'} + hasBin: true + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + eventemitter3@3.1.2: + resolution: {integrity: sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==} + + express-session@1.18.0: + resolution: {integrity: sha512-m93QLWr0ju+rOwApSsyso838LQwgfs44QtOP/WBiwtAgPIo/SAh1a5c6nn2BR6mFNZehTpqKDESzP+fRHVbxwQ==} + engines: {node: '>= 0.8.0'} + + express@4.21.0: + resolution: {integrity: sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==} + engines: {node: '>= 0.10.0'} + + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + faker@5.5.3: + resolution: {integrity: sha512-wLTv2a28wjUyWkbnX7u/ABZBkUkIF2fCd73V6P2oFqEGEktDfzWx4UxrSqtPRw0xPRAcjeAOIiJWqZm3pP4u3g==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fast-uri@3.0.1: + resolution: {integrity: sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==} + + fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + + file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + + file-uri-to-path@1.0.0: + resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + finalhandler@1.3.1: + resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} + engines: {node: '>= 0.8'} + + flat-cache@3.2.0: + resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} + engines: {node: ^10.12.0 || >=12.0.0} + + flatted@3.3.1: + resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + form-data@2.5.1: + resolution: {integrity: sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==} + engines: {node: '>= 0.12'} + + form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + + fs-minipass@2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + ftp@0.3.10: + resolution: {integrity: sha512-faFVML1aBx2UoDStmLwv2Wptt4vw5x03xxX172nhA5Y5HBshW5JweqQ2W4xL4dezQTG8inJsuYcpPHHU3X5OTQ==} + engines: {node: '>=0.8.0'} + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + functional-red-black-tree@1.0.1: + resolution: {integrity: sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==} + + gauge@3.0.2: + resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} + engines: {node: '>=10'} + deprecated: This package is no longer supported. + + get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + + get-uri@2.0.4: + resolution: {integrity: sha512-v7LT/s8kVjs+Tx0ykk1I+H/rbpzkHvuIq87LmeXptcf5sNWm9uQiwjNAt94SJPA1zOlCntmnOlJvVWKmzsxG8Q==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + + globals@13.24.0: + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} + engines: {node: '>=8'} + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + + graphql@16.9.0: + resolution: {integrity: sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==} + engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} + + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + engines: {node: '>= 0.4'} + + has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + + has-unicode@2.0.1: + resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + + http-proxy-agent@2.1.0: + resolution: {integrity: sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==} + engines: {node: '>= 4.5.0'} + + https-proxy-agent@3.0.1: + resolution: {integrity: sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==} + engines: {node: '>= 4.5.0'} + + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + ignore@4.0.6: + resolution: {integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==} + engines: {node: '>= 4'} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + inflection@1.12.0: + resolution: {integrity: sha512-lRy4DxuIFWXlJU7ed8UiTJOSTqStqYdEb4CEbtXfNbkdj3nH1L+reUWiE10VWcJS2yR7tge8Z74pJjtBjNwj0w==} + engines: {'0': node >= 0.4.0} + + inflection@1.3.8: + resolution: {integrity: sha512-xRvG6XhAkbneGO5BXP0uKyGkzmZ2bBbrFkx4ZVNx2TmsECbiq/pJapbbx/NECh+E85IfZwW5+IeVNJfkQgavag==} + engines: {'0': node >= 0.4.0} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ip@1.1.5: + resolution: {integrity: sha512-rBtCAQAJm8A110nbwn6YdveUnuZH3WrC36IwkRXxDnq53JvXA2NVQvB7IHyKomxK1MJ4VDNw3UtFDdXQ+AvLYA==} + + ip@1.1.9: + resolution: {integrity: sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==} + + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-core-module@2.15.1: + resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} + engines: {node: '>= 0.4'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-stream@1.1.0: + resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==} + engines: {node: '>=0.10.0'} + + isarray@0.0.1: + resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==} + + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + iterall@1.3.0: + resolution: {integrity: sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + jsonwebtoken@8.5.1: + resolution: {integrity: sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==} + engines: {node: '>=4', npm: '>=1.4.28'} + + jsonwebtoken@9.0.2: + resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} + engines: {node: '>=12', npm: '>=6'} + + jwa@1.4.1: + resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==} + + jws@3.2.2: + resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==} + + kareem@2.6.3: + resolution: {integrity: sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==} + engines: {node: '>=12.0.0'} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + levn@0.3.0: + resolution: {integrity: sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==} + engines: {node: '>= 0.8.0'} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lodash.includes@4.3.0: + resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} + + lodash.isboolean@3.0.3: + resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} + + lodash.isinteger@4.0.4: + resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==} + + lodash.isnumber@3.0.3: + resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==} + + lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + + lodash.isstring@4.0.1: + resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash.once@4.1.1: + resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} + + lodash.truncate@4.4.2: + resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + mailgun-js@0.22.0: + resolution: {integrity: sha512-a2alg5nuTZA9Psa1pSEIEsbxr1Zrmqx4VkgGCQ30xVh0kIH7Bu57AYILo+0v8QLSdXtCyLaS+KVmdCrQo0uWFA==} + engines: {node: '>=6.0.0'} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. + + mailgun.js@8.2.2: + resolution: {integrity: sha512-po/KtofzrTuKhHLenbmliDsVVOFANwcfDFUGnggwnyZJmZz7JgBlV6nzK9o2Fk+OK2SiBmJTK25RbkAj57Hd+Q==} + + make-dir@3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + + make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + + media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + + memory-pager@1.5.0: + resolution: {integrity: sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==} + + merge-descriptors@1.0.3: + resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-db@1.53.0: + resolution: {integrity: sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass@3.3.6: + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} + + minipass@5.0.0: + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} + + minizlib@2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} + + mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + + mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + + mongodb-connection-string-url@3.0.1: + resolution: {integrity: sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==} + + mongodb@3.7.4: + resolution: {integrity: sha512-K5q8aBqEXMwWdVNh94UQTwZ6BejVbFhh1uB6c5FKtPE9eUMZPUO3sRZdgIEcHSrAWmxzpG/FeODDKL388sqRmw==} + engines: {node: '>=4'} + peerDependencies: + aws4: '*' + bson-ext: '*' + kerberos: '*' + mongodb-client-encryption: '*' + mongodb-extjson: '*' + snappy: '*' + peerDependenciesMeta: + aws4: + optional: true + bson-ext: + optional: true + kerberos: + optional: true + mongodb-client-encryption: + optional: true + mongodb-extjson: + optional: true + snappy: + optional: true + + mongodb@6.8.0: + resolution: {integrity: sha512-HGQ9NWDle5WvwMnrvUxsFYPd3JEbqD3RgABHBQRuoCEND0qzhsd0iH5ypHsf1eJ+sXmvmyKpP+FLOKY8Il7jMw==} + 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 + + mongoose@8.6.2: + resolution: {integrity: sha512-ErbDVvuUzUfyQpXvJ6sXznmZDICD8r6wIsa0VKjJtB6/LZncqwUn5Um040G1BaNo6L3Jz+xItLSwT0wZmSmUaQ==} + engines: {node: '>=16.20.1'} + + mpath@0.9.0: + resolution: {integrity: sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==} + engines: {node: '>=4.0.0'} + + mquery@5.0.0: + resolution: {integrity: sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==} + engines: {node: '>=14.0.0'} + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + multer@1.4.4: + resolution: {integrity: sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==} + engines: {node: '>= 0.10.0'} + deprecated: Multer 1.x is affected by CVE-2022-24434. This is fixed in v1.4.4-lts.1 which drops support for versions of Node.js before 6. Please upgrade to at least Node.js 6 and version 1.4.4-lts.1 of Multer. If you need support for older versions of Node.js, we are open to accepting patches that would fix the CVE on the main 1.x release line, whilst maintaining compatibility with Node.js 0.10. + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + + netmask@1.0.6: + resolution: {integrity: sha512-3DWDqAtIiPSkBXZyYEjwebfK56nrlQfRGt642fu8RPaL+ePu750+HCMHxjJCG3iEHq/0aeMvX6KIzlv7nuhfrA==} + engines: {node: '>= 0.4.0'} + + node-addon-api@5.1.0: + resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==} + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + nodemailer-mailgun-transport@2.1.5: + resolution: {integrity: sha512-hF7POkaxFgMvYEd5aHLaQJI2511ld+aQlQi7JH6bGjhjlZ33cIbTB9PimlIrLu5XC3z76Kde6e65OIwL9lOdTA==} + + nodemailer@6.9.15: + resolution: {integrity: sha512-AHf04ySLC6CIfuRtRiEYtGEXgRfa6INgWGluDhnxTZhHSKvrBu7lc1VVchQ0d8nPc4cFaZoPq8vkyNoZr0TpGQ==} + engines: {node: '>=6.0.0'} + + nopt@5.0.0: + resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} + engines: {node: '>=6'} + hasBin: true + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + npmlog@5.0.1: + resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} + deprecated: This package is no longer supported. + + oauth@0.10.0: + resolution: {integrity: sha512-1orQ9MT1vHFGQxhuy7E/0gECD3fd2fCC+PIX+/jgmU/gI3EpRocXtmtvxCO5x3WZ443FLTLFWNDjl5MPJf9u+Q==} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.2: + resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==} + engines: {node: '>= 0.4'} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + on-headers@1.0.2: + resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==} + engines: {node: '>= 0.8'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + optional-require@1.1.8: + resolution: {integrity: sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==} + engines: {node: '>=4'} + + optionator@0.8.3: + resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==} + engines: {node: '>= 0.8.0'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + pac-proxy-agent@3.0.1: + resolution: {integrity: sha512-44DUg21G/liUZ48dJpUSjZnFfZro/0K5JTyFYLBcmh9+T6Ooi4/i4efwUiEy0+4oQusCBqWdhv16XohIj1GqnQ==} + + pac-resolver@3.0.0: + resolution: {integrity: sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + passport-facebook@3.0.0: + resolution: {integrity: sha512-K/qNzuFsFISYAyC1Nma4qgY/12V3RSLFdFVsPKXiKZt434wOvthFW1p7zKa1iQihQMRhaWorVE1o3Vi1o+ZgeQ==} + engines: {node: '>= 0.4.0'} + + passport-github2@0.1.12: + resolution: {integrity: sha512-3nPUCc7ttF/3HSP/k9sAXjz3SkGv5Nki84I05kSQPo01Jqq1NzJACgMblCK0fGcv9pKCG/KXU3AJRDGLqHLoIw==} + engines: {node: '>= 0.8.0'} + + passport-google-oauth20@2.0.0: + resolution: {integrity: sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ==} + engines: {node: '>= 0.4.0'} + + passport-jwt@4.0.1: + resolution: {integrity: sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==} + + passport-local@1.0.0: + resolution: {integrity: sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==} + engines: {node: '>= 0.4.0'} + + passport-oauth2@1.8.0: + resolution: {integrity: sha512-cjsQbOrXIDE4P8nNb3FQRCCmJJ/utnFKEz2NX209f7KOHPoX18gF7gBzBbLLsj2/je4KrgiwLLGjf0lm9rtTBA==} + engines: {node: '>= 0.4.0'} + + passport-strategy@1.0.0: + resolution: {integrity: sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==} + engines: {node: '>= 0.4.0'} + + passport@0.4.1: + resolution: {integrity: sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==} + engines: {node: '>= 0.4.0'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-proxy@1.0.0: + resolution: {integrity: sha512-p9IuY9FRY1nU59RDW+tnLL6qMxmBnY03WGYxzy1FcqE5OMO5ggz7ahmOBH0JBS+9f95Yc7V5TZ+kHpTeFWaLQA==} + + path-to-regexp@0.1.10: + resolution: {integrity: sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + pause@0.0.1: + resolution: {integrity: sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==} + + picocolors@1.1.0: + resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + prelude-ls@1.1.2: + resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} + engines: {node: '>= 0.8.0'} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + + progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + + promisify-call@2.0.4: + resolution: {integrity: sha512-ZX68J1+1Pe0I8NC0P6Ji3fDDcJceVfpoygfDLgdb1fp5vW9IRlwSpDaxe1T5HgwchyHV2DsL/pWzWikUiWEbLQ==} + engines: {node: '>=4.0'} + + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + + proxy-agent@3.1.1: + resolution: {integrity: sha512-WudaR0eTsDx33O3EJE16PjBRZWcX8GqCEeERw1W3hZJgH/F2a46g7jty6UGty6NeJ4CKQy8ds2CJPMiyeqaTvw==} + engines: {node: '>=6'} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + q@1.5.1: + resolution: {integrity: sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==} + engines: {node: '>=0.6.0', teleport: '>=0.2.0'} + deprecated: |- + You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other. + + (For a CapTP with native promises, see @endo/eventual-send and @endo/captp) + + qs@6.13.0: + resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} + engines: {node: '>=0.6'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + random-bytes@1.0.0: + resolution: {integrity: sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==} + engines: {node: '>= 0.8'} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + raw-body@2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} + + readable-stream@1.1.14: + resolution: {integrity: sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==} + + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + regexpp@3.2.0: + resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} + engines: {node: '>=8'} + + require-at@1.0.6: + resolution: {integrity: sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==} + engines: {node: '>=4'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rimraf@2.7.1: + resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + saslprep@1.0.3: + resolution: {integrity: sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==} + engines: {node: '>=6'} + + semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} + engines: {node: '>=10'} + hasBin: true + + send@0.19.0: + resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} + engines: {node: '>= 0.8.0'} + + serve-static@1.16.2: + resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} + engines: {node: '>= 0.8.0'} + + set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + side-channel@1.0.6: + resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} + engines: {node: '>= 0.4'} + + sift@17.1.3: + resolution: {integrity: sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + slice-ansi@4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + + smart-buffer@4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + + socket.io-adapter@2.1.0: + resolution: {integrity: sha512-+vDov/aTsLjViYTwS9fPy5pEtTkrbEKsw2M+oVSoFGw6OD1IpvlV1VPhUzNbofCQ8oyMbdYJqDtGdmHQK6TdPg==} + + socket.io-parser@4.0.5: + resolution: {integrity: sha512-sNjbT9dX63nqUFIOv95tTVm6elyIU4RvB1m8dOeZt+IgWwcWklFDOdmGcfo3zSiRsnR/3pJkjY5lfoGqEe4Eig==} + engines: {node: '>=10.0.0'} + + socket.io@3.1.2: + resolution: {integrity: sha512-JubKZnTQ4Z8G4IZWtaAZSiRP3I/inpy8c/Bsx2jrwGrTbKeVU5xd6qkKMHpChYeM3dWZSO0QACiGK+obhBNwYw==} + engines: {node: '>=10.0.0'} + + socks-proxy-agent@4.0.2: + resolution: {integrity: sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==} + engines: {node: '>= 6'} + + socks@2.3.3: + resolution: {integrity: sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + sparse-bitfield@3.0.3: + resolution: {integrity: sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + + streamifier@0.1.1: + resolution: {integrity: sha512-zDgl+muIlWzXNsXeyUfOk9dChMjlpkq0DRsxujtYPgyJ676yQ8jEm6zzaaWHFDg5BNcLuif0eD2MTyJdZqXpdg==} + engines: {node: '>=0.10'} + + streamsearch@0.1.2: + resolution: {integrity: sha512-jos8u++JKm0ARcSUTAZXOVC0mSox7Bhn6sBgty73P1f3JGf7yG2clTbBNHUdde/kdvP2FESam+vM6l8jBrNxHA==} + engines: {node: '>=0.8.0'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string_decoder@0.10.31: + resolution: {integrity: sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==} + + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + subscriptions-transport-ws@0.9.19: + resolution: {integrity: sha512-dxdemxFFB0ppCLg10FTtRqH/31FNRL1y1BQv8209MK5I4CwALb7iihQg+7p65lFcIl8MHatINWBLOqpgU4Kyyw==} + deprecated: The `subscriptions-transport-ws` package is no longer maintained. We recommend you use `graphql-ws` instead. For help migrating Apollo software to `graphql-ws`, see https://www.apollographql.com/docs/apollo-server/data/subscriptions/#switching-from-subscriptions-transport-ws For general help using `graphql-ws`, see https://github.com/enisdenjo/graphql-ws/blob/master/README.md + peerDependencies: + graphql: '>=0.10.0' + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + symbol-observable@1.2.0: + resolution: {integrity: sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==} + engines: {node: '>=0.10.0'} + + table@6.8.2: + resolution: {integrity: sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==} + engines: {node: '>=10.0.0'} + + tar@6.2.1: + resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} + engines: {node: '>=10'} + + text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + + thunkify@2.1.2: + resolution: {integrity: sha512-w9foI80XcGImrhMQ19pxunaEC5Rp2uzxZZg4XBAFRfiLOplk3F0l7wo+bO16vC2/nlQfR/mXZxcduo0MF2GWLg==} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + tr46@4.1.1: + resolution: {integrity: sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==} + engines: {node: '>=14'} + + tree-kill@1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + + ts-node-dev@1.1.8: + resolution: {integrity: sha512-Q/m3vEwzYwLZKmV6/0VlFxcZzVV/xcgOt+Tx/VjaaRHyiBcFlV0541yrT09QjzzCxlDZ34OzKjrFAynlmtflEg==} + engines: {node: '>=0.8.0'} + hasBin: true + peerDependencies: + node-notifier: '*' + typescript: '*' + peerDependenciesMeta: + node-notifier: + optional: true + + ts-node@9.1.1: + resolution: {integrity: sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==} + engines: {node: '>=10.0.0'} + hasBin: true + peerDependencies: + typescript: '>=2.7' + + tsconfig@7.0.0: + resolution: {integrity: sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==} + + tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + + tslib@2.7.0: + resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} + + tsscmp@1.0.6: + resolution: {integrity: sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==} + engines: {node: '>=0.6.x'} + + tsutils@3.21.0: + resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} + engines: {node: '>= 6'} + peerDependencies: + typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + + type-check@0.3.2: + resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==} + engines: {node: '>= 0.8.0'} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + + type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + + typedarray@0.0.6: + resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} + + typescript@4.9.5: + resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} + engines: {node: '>=4.2.0'} + hasBin: true + + uid-safe@2.1.5: + resolution: {integrity: sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==} + engines: {node: '>= 0.8'} + + uid2@0.0.4: + resolution: {integrity: sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==} + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + url-join@4.0.1: + resolution: {integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + + v8-compile-cache@2.4.0: + resolution: {integrity: sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==} + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + + whatwg-url@13.0.0: + resolution: {integrity: sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==} + engines: {node: '>=16'} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + wide-align@1.1.5: + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + + with-callback@1.0.2: + resolution: {integrity: sha512-zaUhn7OWgikdqWlPYpZ4rTX/6IAV0czMVyd+C6QLVrif2tATF28CYUnHBmHs2a5EaZo7bB1+plBUPHto+HW8uA==} + engines: {node: '>=4'} + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + ws@7.4.6: + resolution: {integrity: sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@7.5.10: + resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + xregexp@2.0.0: + resolution: {integrity: sha512-xl/50/Cf32VsGq/1R8jJE5ajH1yMCQkpmoS10QbFZWl2Oor4H0Me64Pu2yxvsRWK3m6soJbmGfzSR7BYmDcWAA==} + + xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + +snapshots: + + '@babel/code-frame@7.12.11': + dependencies: + '@babel/highlight': 7.24.7 + + '@babel/helper-validator-identifier@7.24.7': {} + + '@babel/highlight@7.24.7': + dependencies: + '@babel/helper-validator-identifier': 7.24.7 + chalk: 2.4.2 + js-tokens: 4.0.0 + picocolors: 1.1.0 + + '@eslint/eslintrc@0.4.3': + dependencies: + ajv: 6.12.6 + debug: 4.3.7 + espree: 7.3.1 + globals: 13.24.0 + ignore: 4.0.6 + import-fresh: 3.3.0 + js-yaml: 3.14.1 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@humanwhocodes/config-array@0.5.0': + dependencies: + '@humanwhocodes/object-schema': 1.2.1 + debug: 4.3.7 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@humanwhocodes/object-schema@1.2.1': {} + + '@mapbox/node-pre-gyp@1.0.11': + dependencies: + detect-libc: 2.0.3 + https-proxy-agent: 5.0.1 + make-dir: 3.1.0 + node-fetch: 2.7.0 + nopt: 5.0.0 + npmlog: 5.0.1 + rimraf: 3.0.2 + semver: 7.6.3 + tar: 6.2.1 + transitivePeerDependencies: + - encoding + - supports-color + + '@mongodb-js/saslprep@1.1.9': + dependencies: + sparse-bitfield: 3.0.3 + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + + '@types/body-parser@1.19.5': + dependencies: + '@types/connect': 3.4.38 + '@types/node': 14.18.63 + + '@types/component-emitter@1.2.14': {} + + '@types/connect@3.4.38': + dependencies: + '@types/node': 14.18.63 + + '@types/cookie@0.4.1': {} + + '@types/cors@2.8.17': + dependencies: + '@types/node': 14.18.63 + + '@types/dotenv@8.2.0': + dependencies: + dotenv: 8.6.0 + + '@types/express-serve-static-core@4.19.5': + dependencies: + '@types/node': 14.18.63 + '@types/qs': 6.9.15 + '@types/range-parser': 1.2.7 + '@types/send': 0.17.4 + + '@types/express-session@1.18.0': + dependencies: + '@types/express': 4.17.21 + + '@types/express@4.17.21': + dependencies: + '@types/body-parser': 1.19.5 + '@types/express-serve-static-core': 4.19.5 + '@types/qs': 6.9.15 + '@types/serve-static': 1.15.7 + + '@types/http-errors@2.0.4': {} + + '@types/json-schema@7.0.15': {} + + '@types/mime@1.3.5': {} + + '@types/mongoose@5.11.97': + dependencies: + mongoose: 8.6.2 + transitivePeerDependencies: + - '@aws-sdk/credential-providers' + - '@mongodb-js/zstd' + - gcp-metadata + - kerberos + - mongodb-client-encryption + - snappy + - socks + - supports-color + + '@types/multer@1.4.12': + dependencies: + '@types/express': 4.17.21 + + '@types/node@14.18.63': {} + + '@types/nodemailer@6.4.15': + dependencies: + '@types/node': 14.18.63 + + '@types/passport@1.0.16': + dependencies: + '@types/express': 4.17.21 + + '@types/qs@6.9.15': {} + + '@types/range-parser@1.2.7': {} + + '@types/send@0.17.4': + dependencies: + '@types/mime': 1.3.5 + '@types/node': 14.18.63 + + '@types/serve-static@1.15.7': + dependencies: + '@types/http-errors': 2.0.4 + '@types/node': 14.18.63 + '@types/send': 0.17.4 + + '@types/strip-bom@3.0.0': {} + + '@types/strip-json-comments@0.0.30': {} + + '@types/uuid@8.3.4': {} + + '@types/webidl-conversions@7.0.3': {} + + '@types/whatwg-url@11.0.5': + dependencies: + '@types/webidl-conversions': 7.0.3 + + '@typescript-eslint/eslint-plugin@4.33.0(@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@4.9.5))(eslint@7.32.0)(typescript@4.9.5)': + dependencies: + '@typescript-eslint/experimental-utils': 4.33.0(eslint@7.32.0)(typescript@4.9.5) + '@typescript-eslint/parser': 4.33.0(eslint@7.32.0)(typescript@4.9.5) + '@typescript-eslint/scope-manager': 4.33.0 + debug: 4.3.7 + eslint: 7.32.0 + functional-red-black-tree: 1.0.1 + ignore: 5.3.2 + regexpp: 3.2.0 + semver: 7.6.3 + tsutils: 3.21.0(typescript@4.9.5) + optionalDependencies: + typescript: 4.9.5 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/experimental-utils@4.33.0(eslint@7.32.0)(typescript@4.9.5)': + dependencies: + '@types/json-schema': 7.0.15 + '@typescript-eslint/scope-manager': 4.33.0 + '@typescript-eslint/types': 4.33.0 + '@typescript-eslint/typescript-estree': 4.33.0(typescript@4.9.5) + eslint: 7.32.0 + eslint-scope: 5.1.1 + eslint-utils: 3.0.0(eslint@7.32.0) + transitivePeerDependencies: + - supports-color + - typescript + + '@typescript-eslint/parser@4.33.0(eslint@7.32.0)(typescript@4.9.5)': + dependencies: + '@typescript-eslint/scope-manager': 4.33.0 + '@typescript-eslint/types': 4.33.0 + '@typescript-eslint/typescript-estree': 4.33.0(typescript@4.9.5) + debug: 4.3.7 + eslint: 7.32.0 + optionalDependencies: + typescript: 4.9.5 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@4.33.0': + dependencies: + '@typescript-eslint/types': 4.33.0 + '@typescript-eslint/visitor-keys': 4.33.0 + + '@typescript-eslint/types@4.33.0': {} + + '@typescript-eslint/typescript-estree@4.33.0(typescript@4.9.5)': + dependencies: + '@typescript-eslint/types': 4.33.0 + '@typescript-eslint/visitor-keys': 4.33.0 + debug: 4.3.7 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.6.3 + tsutils: 3.21.0(typescript@4.9.5) + optionalDependencies: + typescript: 4.9.5 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@4.33.0': + dependencies: + '@typescript-eslint/types': 4.33.0 + eslint-visitor-keys: 2.1.0 + + abbrev@1.1.1: {} + + accepts@1.3.8: + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + + acorn-jsx@5.3.2(acorn@7.4.1): + dependencies: + acorn: 7.4.1 + + acorn@7.4.1: {} + + agent-base@4.2.1: + dependencies: + es6-promisify: 5.0.0 + + agent-base@4.3.0: + dependencies: + es6-promisify: 5.0.0 + + agent-base@6.0.2: + dependencies: + debug: 4.3.7 + transitivePeerDependencies: + - supports-color + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.0.1 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-colors@4.1.3: {} + + ansi-regex@5.0.1: {} + + ansi-styles@3.2.1: + dependencies: + color-convert: 1.9.3 + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + append-field@1.0.0: {} + + aproba@2.0.0: {} + + are-we-there-yet@2.0.0: + dependencies: + delegates: 1.0.0 + readable-stream: 3.6.2 + + arg@4.1.3: {} + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + array-flatten@1.1.1: {} + + array-union@2.1.0: {} + + ast-types@0.14.2: + dependencies: + tslib: 2.7.0 + + astral-regex@2.0.0: {} + + async@2.6.4: + dependencies: + lodash: 4.17.21 + + asynckit@0.4.0: {} + + axios@1.7.7: + dependencies: + follow-redirects: 1.15.9 + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + backo2@1.0.2: {} + + balanced-match@1.0.2: {} + + base-64@1.0.0: {} + + base64-arraybuffer@0.1.4: {} + + base64id@2.0.0: {} + + base64url@3.0.1: {} + + bcrypt@5.1.1: + dependencies: + '@mapbox/node-pre-gyp': 1.0.11 + node-addon-api: 5.1.0 + transitivePeerDependencies: + - encoding + - supports-color + + binary-extensions@2.3.0: {} + + bl@2.2.1: + dependencies: + readable-stream: 2.3.8 + safe-buffer: 5.2.1 + + bluebird@3.7.2: {} + + body-parser@1.20.3: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.13.0 + raw-body: 2.5.2 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + brace-expansion@1.1.11: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + bson@1.1.6: {} + + bson@6.8.0: {} + + buffer-equal-constant-time@1.0.1: {} + + buffer-from@1.1.2: {} + + busboy@0.2.14: + dependencies: + dicer: 0.2.5 + readable-stream: 1.1.14 + + bytes@3.0.0: {} + + bytes@3.1.2: {} + + call-bind@1.0.7: + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + set-function-length: 1.2.2 + + callsites@3.1.0: {} + + chalk@2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + chownr@2.0.0: {} + + cloudinary-core@2.13.1(lodash@4.17.21): + dependencies: + lodash: 4.17.21 + + cloudinary@1.41.3: + dependencies: + cloudinary-core: 2.13.1(lodash@4.17.21) + core-js: 3.38.1 + lodash: 4.17.21 + q: 1.5.1 + + co@4.6.0: {} + + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.3: {} + + color-name@1.1.4: {} + + color-support@1.1.3: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + component-emitter@1.3.1: {} + + compressible@2.0.18: + dependencies: + mime-db: 1.53.0 + + compression@1.7.4: + dependencies: + accepts: 1.3.8 + bytes: 3.0.0 + compressible: 2.0.18 + debug: 2.6.9 + on-headers: 1.0.2 + safe-buffer: 5.1.2 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + concat-map@0.0.1: {} + + concat-stream@1.6.2: + dependencies: + buffer-from: 1.1.2 + inherits: 2.0.4 + readable-stream: 2.3.8 + typedarray: 0.0.6 + + connect-mongo@3.2.0(express-session@1.18.0): + dependencies: + express-session: 1.18.0 + mongodb: 3.7.4 + transitivePeerDependencies: + - aws4 + - bson-ext + - kerberos + - mongodb-client-encryption + - mongodb-extjson + - snappy + + console-control-strings@1.1.0: {} + + consolidate@0.15.1(lodash@4.17.21): + dependencies: + bluebird: 3.7.2 + optionalDependencies: + lodash: 4.17.21 + + content-disposition@0.5.4: + dependencies: + safe-buffer: 5.2.1 + + content-type@1.0.5: {} + + cookie-parser@1.4.6: + dependencies: + cookie: 0.4.1 + cookie-signature: 1.0.6 + + cookie-signature@1.0.6: {} + + cookie-signature@1.0.7: {} + + cookie@0.4.1: {} + + cookie@0.4.2: {} + + cookie@0.6.0: {} + + core-js@3.38.1: {} + + core-util-is@1.0.3: {} + + cors@2.8.5: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + + create-require@1.1.1: {} + + cross-spawn@7.0.3: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + data-uri-to-buffer@1.2.0: {} + + debug@2.6.9: + dependencies: + ms: 2.0.0 + + debug@3.1.0: + dependencies: + ms: 2.0.0 + + debug@3.2.7: + dependencies: + ms: 2.1.3 + + debug@4.3.7: + dependencies: + ms: 2.1.3 + + deep-is@0.1.4: {} + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + gopd: 1.0.1 + + degenerator@1.0.4: + dependencies: + ast-types: 0.14.2 + escodegen: 1.14.3 + esprima: 3.1.3 + + delayed-stream@1.0.0: {} + + delegates@1.0.0: {} + + denque@1.5.1: {} + + depd@2.0.0: {} + + destroy@1.2.0: {} + + detect-libc@2.0.3: {} + + dicer@0.2.5: + dependencies: + readable-stream: 1.1.14 + streamsearch: 0.1.2 + + diff@4.0.2: {} + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + doctrine@3.0.0: + dependencies: + esutils: 2.0.3 + + dotenv@8.6.0: {} + + dynamic-dedupe@0.3.0: + dependencies: + xtend: 4.0.2 + + ecdsa-sig-formatter@1.0.11: + dependencies: + safe-buffer: 5.2.1 + + ee-first@1.1.1: {} + + emoji-regex@8.0.0: {} + + encodeurl@1.0.2: {} + + encodeurl@2.0.0: {} + + engine.io-parser@4.0.3: + dependencies: + base64-arraybuffer: 0.1.4 + + engine.io@4.1.2: + dependencies: + accepts: 1.3.8 + base64id: 2.0.0 + cookie: 0.4.2 + cors: 2.8.5 + debug: 4.3.7 + engine.io-parser: 4.0.3 + ws: 7.4.6 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + enquirer@2.4.1: + dependencies: + ansi-colors: 4.1.3 + strip-ansi: 6.0.1 + + es-define-property@1.0.0: + dependencies: + get-intrinsic: 1.2.4 + + es-errors@1.3.0: {} + + es6-promise@4.2.8: {} + + es6-promisify@5.0.0: + dependencies: + es6-promise: 4.2.8 + + escape-html@1.0.3: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@4.0.0: {} + + escodegen@1.14.3: + dependencies: + esprima: 4.0.1 + estraverse: 4.3.0 + esutils: 2.0.3 + optionator: 0.8.3 + optionalDependencies: + source-map: 0.6.1 + + eslint-scope@5.1.1: + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + + eslint-utils@2.1.0: + dependencies: + eslint-visitor-keys: 1.3.0 + + eslint-utils@3.0.0(eslint@7.32.0): + dependencies: + eslint: 7.32.0 + eslint-visitor-keys: 2.1.0 + + eslint-visitor-keys@1.3.0: {} + + eslint-visitor-keys@2.1.0: {} + + eslint@7.32.0: + dependencies: + '@babel/code-frame': 7.12.11 + '@eslint/eslintrc': 0.4.3 + '@humanwhocodes/config-array': 0.5.0 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.7 + doctrine: 3.0.0 + enquirer: 2.4.1 + escape-string-regexp: 4.0.0 + eslint-scope: 5.1.1 + eslint-utils: 2.1.0 + eslint-visitor-keys: 2.1.0 + espree: 7.3.1 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + functional-red-black-tree: 1.0.1 + glob-parent: 5.1.2 + globals: 13.24.0 + ignore: 4.0.6 + import-fresh: 3.3.0 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + js-yaml: 3.14.1 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + progress: 2.0.3 + regexpp: 3.2.0 + semver: 7.6.3 + strip-ansi: 6.0.1 + strip-json-comments: 3.1.1 + table: 6.8.2 + text-table: 0.2.0 + v8-compile-cache: 2.4.0 + transitivePeerDependencies: + - supports-color + + esm@3.2.25: {} + + espree@7.3.1: + dependencies: + acorn: 7.4.1 + acorn-jsx: 5.3.2(acorn@7.4.1) + eslint-visitor-keys: 1.3.0 + + esprima@3.1.3: {} + + esprima@4.0.1: {} + + esquery@1.6.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@4.3.0: {} + + estraverse@5.3.0: {} + + esutils@2.0.3: {} + + etag@1.8.1: {} + + eventemitter3@3.1.2: {} + + express-session@1.18.0: + dependencies: + cookie: 0.6.0 + cookie-signature: 1.0.7 + debug: 2.6.9 + depd: 2.0.0 + on-headers: 1.0.2 + parseurl: 1.3.3 + safe-buffer: 5.2.1 + uid-safe: 2.1.5 + transitivePeerDependencies: + - supports-color + + express@4.21.0: + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.3 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.6.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.3.1 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.3 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.10 + proxy-addr: 2.0.7 + qs: 6.13.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.19.0 + serve-static: 1.16.2 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + extend@3.0.2: {} + + faker@5.5.3: {} + + fast-deep-equal@3.1.3: {} + + fast-glob@3.3.2: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fast-uri@3.0.1: {} + + fastq@1.17.1: + dependencies: + reusify: 1.0.4 + + file-entry-cache@6.0.1: + dependencies: + flat-cache: 3.2.0 + + file-uri-to-path@1.0.0: {} + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + finalhandler@1.3.1: + dependencies: + debug: 2.6.9 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + flat-cache@3.2.0: + dependencies: + flatted: 3.3.1 + keyv: 4.5.4 + rimraf: 3.0.2 + + flatted@3.3.1: {} + + follow-redirects@1.15.9: {} + + form-data@2.5.1: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + + form-data@4.0.0: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + + forwarded@0.2.0: {} + + fresh@0.5.2: {} + + fs-minipass@2.1.0: + dependencies: + minipass: 3.3.6 + + fs.realpath@1.0.0: {} + + fsevents@2.3.3: + optional: true + + ftp@0.3.10: + dependencies: + readable-stream: 1.1.14 + xregexp: 2.0.0 + + function-bind@1.1.2: {} + + functional-red-black-tree@1.0.1: {} + + gauge@3.0.2: + dependencies: + aproba: 2.0.0 + color-support: 1.1.3 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + object-assign: 4.1.1 + signal-exit: 3.0.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wide-align: 1.1.5 + + get-intrinsic@1.2.4: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.2 + + get-uri@2.0.4: + dependencies: + data-uri-to-buffer: 1.2.0 + debug: 2.6.9 + extend: 3.0.2 + file-uri-to-path: 1.0.0 + ftp: 0.3.10 + readable-stream: 2.3.8 + transitivePeerDependencies: + - supports-color + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + globals@13.24.0: + dependencies: + type-fest: 0.20.2 + + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + + gopd@1.0.1: + dependencies: + get-intrinsic: 1.2.4 + + graphql@16.9.0: {} + + has-flag@3.0.0: {} + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.0 + + has-proto@1.0.3: {} + + has-symbols@1.0.3: {} + + has-unicode@2.0.1: {} + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + http-errors@2.0.0: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + + http-proxy-agent@2.1.0: + dependencies: + agent-base: 4.3.0 + debug: 3.1.0 + transitivePeerDependencies: + - supports-color + + https-proxy-agent@3.0.1: + dependencies: + agent-base: 4.3.0 + debug: 3.2.7 + transitivePeerDependencies: + - supports-color + + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.3.7 + transitivePeerDependencies: + - supports-color + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + + ignore@4.0.6: {} + + ignore@5.3.2: {} + + import-fresh@3.3.0: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + imurmurhash@0.1.4: {} + + inflection@1.12.0: {} + + inflection@1.3.8: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + + ip@1.1.5: {} + + ip@1.1.9: {} + + ipaddr.js@1.9.1: {} + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-core-module@2.15.1: + dependencies: + hasown: 2.0.2 + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-number@7.0.0: {} + + is-stream@1.1.0: {} + + isarray@0.0.1: {} + + isarray@1.0.0: {} + + isexe@2.0.0: {} + + iterall@1.3.0: {} + + js-tokens@4.0.0: {} + + js-yaml@3.14.1: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + + json-buffer@3.0.1: {} + + json-schema-traverse@0.4.1: {} + + json-schema-traverse@1.0.0: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + jsonwebtoken@8.5.1: + dependencies: + jws: 3.2.2 + lodash.includes: 4.3.0 + lodash.isboolean: 3.0.3 + lodash.isinteger: 4.0.4 + lodash.isnumber: 3.0.3 + lodash.isplainobject: 4.0.6 + lodash.isstring: 4.0.1 + lodash.once: 4.1.1 + ms: 2.1.3 + semver: 5.7.2 + + jsonwebtoken@9.0.2: + dependencies: + jws: 3.2.2 + lodash.includes: 4.3.0 + lodash.isboolean: 3.0.3 + lodash.isinteger: 4.0.4 + lodash.isnumber: 3.0.3 + lodash.isplainobject: 4.0.6 + lodash.isstring: 4.0.1 + lodash.once: 4.1.1 + ms: 2.1.3 + semver: 7.6.3 + + jwa@1.4.1: + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + + jws@3.2.2: + dependencies: + jwa: 1.4.1 + safe-buffer: 5.2.1 + + kareem@2.6.3: {} + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + levn@0.3.0: + dependencies: + prelude-ls: 1.1.2 + type-check: 0.3.2 + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lodash.includes@4.3.0: {} + + lodash.isboolean@3.0.3: {} + + lodash.isinteger@4.0.4: {} + + lodash.isnumber@3.0.3: {} + + lodash.isplainobject@4.0.6: {} + + lodash.isstring@4.0.1: {} + + lodash.merge@4.6.2: {} + + lodash.once@4.1.1: {} + + lodash.truncate@4.4.2: {} + + lodash@4.17.21: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + mailgun-js@0.22.0: + dependencies: + async: 2.6.4 + debug: 4.3.7 + form-data: 2.5.1 + inflection: 1.12.0 + is-stream: 1.1.0 + path-proxy: 1.0.0 + promisify-call: 2.0.4 + proxy-agent: 3.1.1 + tsscmp: 1.0.6 + transitivePeerDependencies: + - supports-color + + mailgun.js@8.2.2: + dependencies: + axios: 1.7.7 + base-64: 1.0.0 + url-join: 4.0.1 + transitivePeerDependencies: + - debug + + make-dir@3.1.0: + dependencies: + semver: 6.3.1 + + make-error@1.3.6: {} + + media-typer@0.3.0: {} + + memory-pager@1.5.0: {} + + merge-descriptors@1.0.3: {} + + merge2@1.4.1: {} + + methods@1.1.2: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.52.0: {} + + mime-db@1.53.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime@1.6.0: {} + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.11 + + minimist@1.2.8: {} + + minipass@3.3.6: + dependencies: + yallist: 4.0.0 + + minipass@5.0.0: {} + + minizlib@2.1.2: + dependencies: + minipass: 3.3.6 + yallist: 4.0.0 + + mkdirp@0.5.6: + dependencies: + minimist: 1.2.8 + + mkdirp@1.0.4: {} + + mongodb-connection-string-url@3.0.1: + dependencies: + '@types/whatwg-url': 11.0.5 + whatwg-url: 13.0.0 + + mongodb@3.7.4: + dependencies: + bl: 2.2.1 + bson: 1.1.6 + denque: 1.5.1 + optional-require: 1.1.8 + safe-buffer: 5.2.1 + optionalDependencies: + saslprep: 1.0.3 + + mongodb@6.8.0: + dependencies: + '@mongodb-js/saslprep': 1.1.9 + bson: 6.8.0 + mongodb-connection-string-url: 3.0.1 + + mongoose@8.6.2: + dependencies: + bson: 6.8.0 + kareem: 2.6.3 + mongodb: 6.8.0 + mpath: 0.9.0 + mquery: 5.0.0 + ms: 2.1.3 + sift: 17.1.3 + transitivePeerDependencies: + - '@aws-sdk/credential-providers' + - '@mongodb-js/zstd' + - gcp-metadata + - kerberos + - mongodb-client-encryption + - snappy + - socks + - supports-color + + mpath@0.9.0: {} + + mquery@5.0.0: + dependencies: + debug: 4.3.7 + transitivePeerDependencies: + - supports-color + + ms@2.0.0: {} + + ms@2.1.3: {} + + multer@1.4.4: + dependencies: + append-field: 1.0.0 + busboy: 0.2.14 + concat-stream: 1.6.2 + mkdirp: 0.5.6 + object-assign: 4.1.1 + on-finished: 2.4.1 + type-is: 1.6.18 + xtend: 4.0.2 + + natural-compare@1.4.0: {} + + negotiator@0.6.3: {} + + netmask@1.0.6: {} + + node-addon-api@5.1.0: {} + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + nodemailer-mailgun-transport@2.1.5(lodash@4.17.21): + dependencies: + consolidate: 0.15.1(lodash@4.17.21) + form-data: 4.0.0 + mailgun.js: 8.2.2 + transitivePeerDependencies: + - arc-templates + - atpl + - babel-core + - bracket-template + - coffee-script + - debug + - dot + - dust + - dustjs-helpers + - dustjs-linkedin + - eco + - ect + - ejs + - haml-coffee + - hamlet + - hamljs + - handlebars + - hogan.js + - htmling + - jade + - jazz + - jqtpl + - just + - liquid-node + - liquor + - lodash + - marko + - mote + - mustache + - nunjucks + - plates + - pug + - qejs + - ractive + - razor-tmpl + - react + - react-dom + - slm + - squirrelly + - swig + - swig-templates + - teacup + - templayed + - then-jade + - then-pug + - tinyliquid + - toffee + - twig + - twing + - underscore + - vash + - velocityjs + - walrus + - whiskers + + nodemailer@6.9.15: {} + + nopt@5.0.0: + dependencies: + abbrev: 1.1.1 + + normalize-path@3.0.0: {} + + npmlog@5.0.1: + dependencies: + are-we-there-yet: 2.0.0 + console-control-strings: 1.1.0 + gauge: 3.0.2 + set-blocking: 2.0.0 + + oauth@0.10.0: {} + + object-assign@4.1.1: {} + + object-inspect@1.13.2: {} + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + on-headers@1.0.2: {} + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + optional-require@1.1.8: + dependencies: + require-at: 1.0.6 + + optionator@0.8.3: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.3.0 + prelude-ls: 1.1.2 + type-check: 0.3.2 + word-wrap: 1.2.5 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + pac-proxy-agent@3.0.1: + dependencies: + agent-base: 4.3.0 + debug: 4.3.7 + get-uri: 2.0.4 + http-proxy-agent: 2.1.0 + https-proxy-agent: 3.0.1 + pac-resolver: 3.0.0 + raw-body: 2.5.2 + socks-proxy-agent: 4.0.2 + transitivePeerDependencies: + - supports-color + + pac-resolver@3.0.0: + dependencies: + co: 4.6.0 + degenerator: 1.0.4 + ip: 1.1.9 + netmask: 1.0.6 + thunkify: 2.1.2 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parseurl@1.3.3: {} + + passport-facebook@3.0.0: + dependencies: + passport-oauth2: 1.8.0 + + passport-github2@0.1.12: + dependencies: + passport-oauth2: 1.8.0 + + passport-google-oauth20@2.0.0: + dependencies: + passport-oauth2: 1.8.0 + + passport-jwt@4.0.1: + dependencies: + jsonwebtoken: 9.0.2 + passport-strategy: 1.0.0 + + passport-local@1.0.0: + dependencies: + passport-strategy: 1.0.0 + + passport-oauth2@1.8.0: + dependencies: + base64url: 3.0.1 + oauth: 0.10.0 + passport-strategy: 1.0.0 + uid2: 0.0.4 + utils-merge: 1.0.1 + + passport-strategy@1.0.0: {} + + passport@0.4.1: + dependencies: + passport-strategy: 1.0.0 + pause: 0.0.1 + + path-is-absolute@1.0.1: {} + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + path-proxy@1.0.0: + dependencies: + inflection: 1.3.8 + + path-to-regexp@0.1.10: {} + + path-type@4.0.0: {} + + pause@0.0.1: {} + + picocolors@1.1.0: {} + + picomatch@2.3.1: {} + + prelude-ls@1.1.2: {} + + prelude-ls@1.2.1: {} + + process-nextick-args@2.0.1: {} + + progress@2.0.3: {} + + promisify-call@2.0.4: + dependencies: + with-callback: 1.0.2 + + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + + proxy-agent@3.1.1: + dependencies: + agent-base: 4.3.0 + debug: 4.3.7 + http-proxy-agent: 2.1.0 + https-proxy-agent: 3.0.1 + lru-cache: 5.1.1 + pac-proxy-agent: 3.0.1 + proxy-from-env: 1.1.0 + socks-proxy-agent: 4.0.2 + transitivePeerDependencies: + - supports-color + + proxy-from-env@1.1.0: {} + + punycode@2.3.1: {} + + q@1.5.1: {} + + qs@6.13.0: + dependencies: + side-channel: 1.0.6 + + queue-microtask@1.2.3: {} + + random-bytes@1.0.0: {} + + range-parser@1.2.1: {} + + raw-body@2.5.2: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + + readable-stream@1.1.14: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 0.0.1 + string_decoder: 0.10.31 + + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + regexpp@3.2.0: {} + + require-at@1.0.6: {} + + require-from-string@2.0.2: {} + + resolve-from@4.0.0: {} + + resolve@1.22.8: + dependencies: + is-core-module: 2.15.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + reusify@1.0.4: {} + + rimraf@2.7.1: + dependencies: + glob: 7.2.3 + + rimraf@3.0.2: + dependencies: + glob: 7.2.3 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + safe-buffer@5.1.2: {} + + safe-buffer@5.2.1: {} + + safer-buffer@2.1.2: {} + + saslprep@1.0.3: + dependencies: + sparse-bitfield: 3.0.3 + optional: true + + semver@5.7.2: {} + + semver@6.3.1: {} + + semver@7.6.3: {} + + send@0.19.0: + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + + serve-static@1.16.2: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.19.0 + transitivePeerDependencies: + - supports-color + + set-blocking@2.0.0: {} + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + gopd: 1.0.1 + has-property-descriptors: 1.0.2 + + setprototypeof@1.2.0: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + side-channel@1.0.6: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + object-inspect: 1.13.2 + + sift@17.1.3: {} + + signal-exit@3.0.7: {} + + slash@3.0.0: {} + + slice-ansi@4.0.0: + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + + smart-buffer@4.2.0: {} + + socket.io-adapter@2.1.0: {} + + socket.io-parser@4.0.5: + dependencies: + '@types/component-emitter': 1.2.14 + component-emitter: 1.3.1 + debug: 4.3.7 + transitivePeerDependencies: + - supports-color + + socket.io@3.1.2: + dependencies: + '@types/cookie': 0.4.1 + '@types/cors': 2.8.17 + '@types/node': 14.18.63 + accepts: 1.3.8 + base64id: 2.0.0 + debug: 4.3.7 + engine.io: 4.1.2 + socket.io-adapter: 2.1.0 + socket.io-parser: 4.0.5 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + socks-proxy-agent@4.0.2: + dependencies: + agent-base: 4.2.1 + socks: 2.3.3 + + socks@2.3.3: + dependencies: + ip: 1.1.5 + smart-buffer: 4.2.0 + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.6.1: {} + + sparse-bitfield@3.0.3: + dependencies: + memory-pager: 1.5.0 + + sprintf-js@1.0.3: {} + + statuses@2.0.1: {} + + streamifier@0.1.1: {} + + streamsearch@0.1.2: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string_decoder@0.10.31: {} + + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-bom@3.0.0: {} + + strip-json-comments@2.0.1: {} + + strip-json-comments@3.1.1: {} + + subscriptions-transport-ws@0.9.19(graphql@16.9.0): + dependencies: + backo2: 1.0.2 + eventemitter3: 3.1.2 + graphql: 16.9.0 + iterall: 1.3.0 + symbol-observable: 1.2.0 + ws: 7.5.10 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + supports-color@5.5.0: + dependencies: + has-flag: 3.0.0 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + symbol-observable@1.2.0: {} + + table@6.8.2: + dependencies: + ajv: 8.17.1 + lodash.truncate: 4.4.2 + slice-ansi: 4.0.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + tar@6.2.1: + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 5.0.0 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 + + text-table@0.2.0: {} + + thunkify@2.1.2: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + toidentifier@1.0.1: {} + + tr46@0.0.3: {} + + tr46@4.1.1: + dependencies: + punycode: 2.3.1 + + tree-kill@1.2.2: {} + + ts-node-dev@1.1.8(typescript@4.9.5): + dependencies: + chokidar: 3.6.0 + dynamic-dedupe: 0.3.0 + minimist: 1.2.8 + mkdirp: 1.0.4 + resolve: 1.22.8 + rimraf: 2.7.1 + source-map-support: 0.5.21 + tree-kill: 1.2.2 + ts-node: 9.1.1(typescript@4.9.5) + tsconfig: 7.0.0 + typescript: 4.9.5 + + ts-node@9.1.1(typescript@4.9.5): + dependencies: + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + source-map-support: 0.5.21 + typescript: 4.9.5 + yn: 3.1.1 + + tsconfig@7.0.0: + dependencies: + '@types/strip-bom': 3.0.0 + '@types/strip-json-comments': 0.0.30 + strip-bom: 3.0.0 + strip-json-comments: 2.0.1 + + tslib@1.14.1: {} + + tslib@2.7.0: {} + + tsscmp@1.0.6: {} + + tsutils@3.21.0(typescript@4.9.5): + dependencies: + tslib: 1.14.1 + typescript: 4.9.5 + + type-check@0.3.2: + dependencies: + prelude-ls: 1.1.2 + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-fest@0.20.2: {} + + type-is@1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + + typedarray@0.0.6: {} + + typescript@4.9.5: {} + + uid-safe@2.1.5: + dependencies: + random-bytes: 1.0.0 + + uid2@0.0.4: {} + + unpipe@1.0.0: {} + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + url-join@4.0.1: {} + + util-deprecate@1.0.2: {} + + utils-merge@1.0.1: {} + + uuid@8.3.2: {} + + v8-compile-cache@2.4.0: {} + + vary@1.1.2: {} + + webidl-conversions@3.0.1: {} + + webidl-conversions@7.0.0: {} + + whatwg-url@13.0.0: + dependencies: + tr46: 4.1.1 + webidl-conversions: 7.0.0 + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + wide-align@1.1.5: + dependencies: + string-width: 4.2.3 + + with-callback@1.0.2: {} + + word-wrap@1.2.5: {} + + wrappy@1.0.2: {} + + ws@7.4.6: {} + + ws@7.5.10: {} + + xregexp@2.0.0: {} + + xtend@4.0.2: {} + + yallist@3.1.1: {} + + yallist@4.0.0: {} + + yn@3.1.1: {} diff --git a/packages/orca-api/src/constants/Notification.ts b/packages/orca-api/src/constants/Notification.ts index 78e3673c..96290218 100644 --- a/packages/orca-api/src/constants/Notification.ts +++ b/packages/orca-api/src/constants/Notification.ts @@ -1,6 +1,6 @@ -export const NotificationType = { - LIKE: 'LIKE', - FOLLOW: 'FOLLOW', - COMMENT: 'COMMENT', - MESSAGE: 'MESSAGE', -}; +export enum NotificationType { + LIKE = 'LIKE', + FOLLOW = 'FOLLOW', + COMMENT = 'COMMENT', + MESSAGE = 'MESSAGE', +} diff --git a/packages/orca-api/src/controllers/auth.ts b/packages/orca-api/src/controllers/auth.ts index 6983383c..0afdbde1 100644 --- a/packages/orca-api/src/controllers/auth.ts +++ b/packages/orca-api/src/controllers/auth.ts @@ -17,7 +17,7 @@ import { URLSearchParams } from 'url'; import { SocialProvider } from '../authentication'; const AuthController = { - authUser: async (req: Request, res: Response): Promise => { + authUser: async (req: Request, res: Response) => { passport.authenticate('jwt', { session: false }, async (err, user) => { if (!user) { return res.send(null); @@ -27,11 +27,12 @@ const AuthController = { const authUser = await getAuthUser(user._id); return res.send(authUser); } catch (error) { + console.error(error); return res.send(ErrorCodes.Internal).send(ErrorMessages.Generic); } })(req, res); }, - signUp: async (req: Request, res: Response, next: NextFunction): Promise => { + signUp: async (req: Request, res: Response, next: NextFunction) => { const { fullName, username, email, password } = req.body; if (!fullName || !email || !password) { @@ -76,6 +77,7 @@ const AuthController = { }); return res.send('success'); } catch (error) { + console.error(error); return res.status(ErrorCodes.Internal).send(ErrorMessages.Generic); } } @@ -95,10 +97,11 @@ const AuthController = { }); })(req, res, next); } catch (error) { + console.error(error); res.send(ErrorCodes.Un_Authorized).send(ErrorMessages.Generic); } }, - emailVerify: async (req: Request, res: Response, next: NextFunction): Promise => { + emailVerify: async (req: Request, res: Response, next: NextFunction) => { passport.authenticate('signup', { session: false }, async (err) => { if (err) { return res.status(ErrorCodes.Bad_Request).send(ErrorMessages.Generic); @@ -113,6 +116,7 @@ const AuthController = { try { decoded = await jwt.verify(token, process.env.SECRET); } catch (error) { + console.error(error); return res.status(ErrorCodes.Bad_Request).send('The link has expired.'); } @@ -136,11 +140,12 @@ const AuthController = { handler(req, res, next); }); } catch (error) { + console.error(error); res.send(ErrorCodes.Un_Authorized).send(ErrorMessages.Generic); } })(req, res, next); }, - login: async (req: Request, res: Response, next: NextFunction): Promise => { + login: async (req: Request, res: Response, next: NextFunction) => { passport.authenticate('login', async (err, user) => { try { const isEmailVerificationRequired = await checkEmailVerification(); @@ -169,14 +174,14 @@ const AuthController = { } })(req, res, next); }, - logout: async (req: Request, res: Response): Promise => { + logout: async (req: Request, res: Response) => { if (req.cookies['token']) { return res.clearCookie('token').send('You have been successfully logged out.'); } else { return res.send('You have been successfully logged out.'); } }, - forgotPassword: async (req: Request, res: Response): Promise => { + forgotPassword: async (req: Request, res: Response) => { const { email } = req.body; const user = await getUserByEmail(email); @@ -203,16 +208,18 @@ const AuthController = { }); return res.send(`Password reset instruction has been sent to the ${email} email address.`); } catch (error) { + console.error(error); return res.status(ErrorCodes.Internal).send(ErrorMessages.Generic); } }, - resetPassword: async (req: Request, res: Response): Promise => { + resetPassword: async (req: Request, res: Response) => { const { password, token, email } = req.body; let decoded = null; try { decoded = await jwt.verify(token, process.env.SECRET); } catch (error) { + console.error(error); return res.status(ErrorCodes.Bad_Request).send('The link has expired.'); } @@ -230,7 +237,7 @@ const AuthController = { return res.cookie('token', token).send({ user, token }); }); }, - githubCallback: async (req: Request, res: Response, next: NextFunction): Promise => { + githubCallback: async (req: Request, res: Response, next: NextFunction) => { passport.authenticate( 'github', { failureRedirect: `${process.env.FRONTEND_URL}?auth=social&responseType=error`, session: false }, @@ -253,7 +260,7 @@ const AuthController = { } )(req, res, next); }, - googleCallback: async (req: Request, res: Response, next: NextFunction): Promise => { + googleCallback: async (req: Request, res: Response, next: NextFunction) => { passport.authenticate( 'google', { failureRedirect: `${process.env.FRONTEND_URL}?auth=social&responseType=error`, session: false }, @@ -276,7 +283,7 @@ const AuthController = { } )(req, res, next); }, - facebookCallback: async (req: Request, res: Response, next: NextFunction): Promise => { + facebookCallback: async (req: Request, res: Response, next: NextFunction) => { passport.authenticate( 'facebook', { failureRedirect: `${process.env.FRONTEND_URL}?auth=social&responseType=error`, session: false }, diff --git a/packages/orca-api/src/controllers/channel.ts b/packages/orca-api/src/controllers/channel.ts index ea7b7c3b..cf490221 100644 --- a/packages/orca-api/src/controllers/channel.ts +++ b/packages/orca-api/src/controllers/channel.ts @@ -11,20 +11,21 @@ import { } from '../db'; import { getChannelPosts } from '../db'; import { ErrorCodes, ErrorMessages } from '../constants'; +import { IChannel } from '../models/channel'; const channelNameReg = /[-!$%^&*()_+|~=`\\#{}[\]:";'<>?,./]/; const ChannelController = { - channels: async (req: Request, res: Response): Promise => { + channels: async (req: Request, res: Response) => { const channels = await getChannels(); return res.send(channels); }, - channelByName: async (req: Request, res: Response): Promise => { + channelByName: async (req: Request, res: Response) => { const { name } = req.params; const channel = await getChannelByName(name); return res.send(channel); }, - create: async (req: Request, res: Response): Promise => { + create: async (req: Request, res: Response) => { const { name, authRequired, description, order } = req.body; const trimmedName = name.trim(); @@ -42,7 +43,7 @@ const ChannelController = { const newChannel = await createChannel(trimmedName, authRequired, order, description); return res.send(newChannel); }, - update: async (req: Request, res: Response): Promise => { + update: async (req: Request, res: Response) => { const { _id, name, authRequired, description } = req.body; const trimmedName = name.trim(); @@ -59,12 +60,12 @@ const ChannelController = { const updatedChannel = await updateChannel(_id, trimmedName, authRequired, description); return res.send(updatedChannel); }, - reorder: async (req: Request, res: Response): Promise => { + reorder: async (req: Request, res: Response) => { const { sortedChannels } = req.body; await reorderChannels(sortedChannels); return res.send('success'); }, - delete: async (req: Request, res: Response): Promise => { + delete: async (req: Request, res: Response) => { const { id } = req.body; const channel = await deleteChannel(id); // Delete all channel posts, and their images from CDN. diff --git a/packages/orca-api/src/controllers/comment.ts b/packages/orca-api/src/controllers/comment.ts index 3568ed59..73766a3a 100644 --- a/packages/orca-api/src/controllers/comment.ts +++ b/packages/orca-api/src/controllers/comment.ts @@ -1,9 +1,10 @@ import { Request, Response } from 'express'; -import { commentById, createComment, deleteComment } from '../db'; import { AuthUser, ErrorCodes, ErrorMessages } from '../constants'; +import { commentById, createComment, deleteComment } from '../db'; +import { IComment } from '../models/comment'; const CommentController = { - create: async (req: Request, res: Response): Promise => { + create: async (req: Request, res: Response) => { const authUser = req.user as AuthUser; const { comment, postId } = req.body; @@ -11,15 +12,15 @@ const CommentController = { return res.status(ErrorCodes.Internal).send('Please insert a comment.'); } - const newComment: any = await createComment(comment, authUser._id, postId); + const newComment: IComment = await createComment(comment, authUser._id, postId); return res.send(newComment); }, - delete: async (req: Request, res: Response): Promise => { + delete: async (req: Request, res: Response) => { const { id } = req.body; const authUser = req.user as AuthUser; // Check if the comment author is removing the comment. - const comment: any = await commentById(id); + const comment: IComment = await commentById(id); if (comment.author.toString() === authUser._id.toString()) { const deletedComment = await deleteComment(id); return res.send(deletedComment); diff --git a/packages/orca-api/src/controllers/follow.ts b/packages/orca-api/src/controllers/follow.ts index 3f0db160..6cde3226 100644 --- a/packages/orca-api/src/controllers/follow.ts +++ b/packages/orca-api/src/controllers/follow.ts @@ -1,20 +1,21 @@ import { Request, Response } from 'express'; import { AuthUser, ErrorCodes, ErrorMessages } from '../constants'; import { createFollow, deleteFollow, followById } from '../db'; +import { IFollow } from '../models/follow'; const FollowController = { - create: async (req: Request, res: Response): Promise => { + create: async (req: Request, res: Response) => { const { userId } = req.body; const authUser = req.user as AuthUser; const follow = await createFollow(userId, authUser._id); return res.send(follow); }, - delete: async (req: Request, res: Response): Promise => { + delete: async (req: Request, res: Response) => { const { id } = req.body; const authUser = req.user as AuthUser; // Check if the follow author is removing the follow. - const follow: any = await followById(id); + const follow: IFollow = await followById(id); if (follow.follower.toString() === authUser._id.toString()) { const deletedFollow = await deleteFollow(id); return res.send(deletedFollow); diff --git a/packages/orca-api/src/controllers/like.ts b/packages/orca-api/src/controllers/like.ts index 7e12e9f7..dd4eeac8 100644 --- a/packages/orca-api/src/controllers/like.ts +++ b/packages/orca-api/src/controllers/like.ts @@ -1,15 +1,16 @@ import { Request, Response } from 'express'; import { AuthUser, ErrorCodes, ErrorMessages } from '../constants'; import { createLike, deleteLike, likeById } from '../db'; +import { ILike } from '../models/like'; const LikeController = { - create: async (req: Request, res: Response): Promise => { + create: async (req: Request, res: Response) => { const { postId } = req.body; const authUser = req.user as AuthUser; const like = await createLike(authUser._id, postId); return res.send(like); }, - delete: async (req: Request, res: Response): Promise => { + delete: async (req: Request, res: Response) => { const { id } = req.body; const authUser = req.user as AuthUser; diff --git a/packages/orca-api/src/controllers/message.ts b/packages/orca-api/src/controllers/message.ts index 8307ba60..92751490 100644 --- a/packages/orca-api/src/controllers/message.ts +++ b/packages/orca-api/src/controllers/message.ts @@ -1,20 +1,21 @@ import { Request, Response } from 'express'; -import { getMessages, createMessage, getConversations, updateMessageSeen } from '../db/message'; import { AuthUser, ErrorCodes } from '../constants'; +import { createMessage, getConversations, getMessages, IConversation, updateMessageSeen } from '../db/message'; +import { IMessage } from '../models/message'; const MessageController = { - conversations: async (req: Request, res: Response): Promise => { + conversations: async (req: Request, res: Response) => { const authUser = req.user as AuthUser; const users = await getConversations(authUser._id); return res.send(users); }, - messages: async (req: Request, res: Response): Promise => { + messages: async (req: Request, res: Response) => { const authUser = req.user as AuthUser; const userId = req.query.userId as string; const message = await getMessages(authUser._id, userId); return res.send(message); }, - create: async (req: Request, res: Response): Promise => { + create: async (req: Request, res: Response) => { const { message, receiver } = req.body; const authUser = req.user as AuthUser; @@ -25,7 +26,7 @@ const MessageController = { const newMessage = await createMessage(message, authUser._id, receiver); return res.send(newMessage); }, - updateMessageSeen: async (req: Request, res: Response): Promise => { + updateMessageSeen: async (req: Request, res: Response) => { const { sender } = req.body; const authUser = req.user as AuthUser; const messages = updateMessageSeen(sender, authUser._id); diff --git a/packages/orca-api/src/controllers/notification.ts b/packages/orca-api/src/controllers/notification.ts index 462af747..5262ea64 100644 --- a/packages/orca-api/src/controllers/notification.ts +++ b/packages/orca-api/src/controllers/notification.ts @@ -1,30 +1,34 @@ import { Request, Response } from 'express'; import { AuthUser, ErrorCodes } from '../constants'; import { - getUserNotifications, createNotification, deleteNotification, - updateNotificationSeen, - notificationById, + getUserNotifications, notificationByAuthorAndUserId, + notificationById, updateMessagesNotificationSeen, + updateNotificationSeen, } from '../db'; +import { INotification } from '../models/notification'; import { sendNotificationEmail } from '../utils/notificationEmails'; const NotificationController = { - notificationsByUserId: async (req: Request, res: Response): Promise => { + notificationsByUserId: async (req: Request, res: Response): Promise> => { const authUser = req.user as AuthUser; const { offset, limit } = req.query; const notifications = await getUserNotifications(authUser._id, +offset, +limit); return res.send(notifications); }, - notificationByAuthorAndUserId: async (req: Request, res: Response): Promise => { + notificationByAuthorAndUserId: async ( + req: Request, + res: Response + ): Promise> => { const authUser = req.user as AuthUser; const { userId } = req.params; const notification = await notificationByAuthorAndUserId(authUser._id, userId); return res.send(notification); }, - create: async (req: Request, res: Response): Promise => { + create: async (req: Request, res: Response): Promise> => { const { userId, postId, notificationType, notificationTypeId } = req.body; const authUser = req.user as AuthUser; @@ -37,7 +41,7 @@ const NotificationController = { appUrl: req.headers.origin, }); - const notification: any = await createNotification( + const notification: INotification = await createNotification( userId, authUser._id, postId, @@ -47,12 +51,12 @@ const NotificationController = { return res.send(notification); }, - delete: async (req: Request, res: Response): Promise => { + delete: async (req: Request, res: Response): Promise> => { const { id } = req.body; const authUser = req.user as AuthUser; // Check if the notification author is removing the notification. - const notification: any = await notificationById(id); + const notification: INotification = await notificationById(id); if (notification.author.toString() === authUser._id.toString()) { const deletedNotification = await deleteNotification(id); return res.send(deletedNotification); @@ -60,12 +64,12 @@ const NotificationController = { return res.status(ErrorCodes.Bad_Request).send('Unauthorized'); }, - updateNotificationSeen: async (req: Request, res: Response): Promise => { + updateNotificationSeen: async (req: Request, res: Response): Promise> => { const authUser = req.user as AuthUser; const notifications = await updateNotificationSeen(authUser._id); return res.send(notifications); }, - updateMessagesNotificationSeen: async (req: Request, res: Response): Promise => { + updateMessagesNotificationSeen: async (req: Request, res: Response): Promise> => { const authUser = req.user as AuthUser; const { userId } = req.body; const notifications = await updateMessagesNotificationSeen(authUser._id, userId); diff --git a/packages/orca-api/src/controllers/post.ts b/packages/orca-api/src/controllers/post.ts index c0c32f42..9a6ccd07 100644 --- a/packages/orca-api/src/controllers/post.ts +++ b/packages/orca-api/src/controllers/post.ts @@ -1,43 +1,44 @@ import { Request, Response } from 'express'; import { AuthUser, ErrorCodes, ErrorMessages, UserRole } from '../constants'; -import { uploadToCloudinary, deleteFromCloudinary } from '../utils/cloudinary'; import { - getPostsByChannelId, - getPostsByAuthorId, - getPostById, createPost, deletePost, getFollowedPosts, + getPostById, + getPostsByAuthorId, + getPostsByChannelId, + pinPost, postById, updatePost, - pinPost, } from '../db'; +import { deleteFromCloudinary, uploadToCloudinary } from '../utils/cloudinary'; +import { IPost } from '../models/post'; const PostController = { - postsByFollowing: async (req: Request, res: Response): Promise => { + postsByFollowing: async (req: Request, res: Response): Promise> => { const authUser = req.user as AuthUser; const { offset, limit } = req.query; const posts = await getFollowedPosts(authUser?._id, +offset, +limit); return res.send(posts); }, - postsByChannelId: async (req: Request, res: Response): Promise => { + postsByChannelId: async (req: Request, res: Response): Promise> => { const { channelId } = req.params; const { offset, limit } = req.query; const posts = await getPostsByChannelId(channelId, +offset, +limit); return res.send(posts); }, - postsByAuthorId: async (req: Request, res: Response): Promise => { + postsByAuthorId: async (req: Request, res: Response): Promise> => { const { authorId } = req.params; const { offset, limit } = req.query; const posts = await getPostsByAuthorId(authorId, +offset, +limit); return res.send(posts); }, - postById: async (req: Request, res: Response): Promise => { + postById: async (req: Request, res: Response): Promise> => { const { id } = req.params; const post = await getPostById(id); return res.send(post); }, - create: async (req: Request, res: Response): Promise => { + create: async (req: Request, res: Response): Promise> => { const authUser = req.user as AuthUser; const { title, channelId } = req.body; const image = req.file; @@ -59,10 +60,10 @@ const PostController = { imageUrl = uploadImage.secure_url; imagePublicId = uploadImage.public_id; } - const newPost: any = await createPost(title, imageUrl, imagePublicId, channelId, authUser._id); + const newPost: IPost = await createPost(title, imageUrl, imagePublicId, channelId, authUser._id); return res.send(newPost); }, - update: async (req: Request, res: Response): Promise => { + update: async (req: Request, res: Response): Promise> => { const authUser = req.user as AuthUser; const { postId, title, imageToDeletePublicId, channelId } = req.body; const image = req.file; @@ -70,7 +71,7 @@ const PostController = { // Super Admins can update another user's post. if (authUser.role !== UserRole.SuperAdmin) { // Check if the post author is updating the post. - const post: any = await postById(postId); + const post: IPost = await postById(postId); if (post.author.toString() !== authUser._id.toString()) { return res.status(ErrorCodes.Bad_Request).send('Unauthorized'); } @@ -96,17 +97,24 @@ const PostController = { imagePublicId = uploadImage.public_id; } - const updatedPost = await updatePost(postId, title, imageUrl, imagePublicId, imageToDeletePublicId, channelId); + const updatedPost: IPost = await updatePost({ + postId, + title, + imageUrl, + imagePublicId, + imageToDeletePublicId, + channelId, + }); return res.send(updatedPost); }, - delete: async (req: Request, res: Response): Promise => { + delete: async (req: Request, res: Response): Promise> => { const { id, imagePublicId } = req.body; const authUser = req.user as AuthUser; // Super Admins can delete another user's post. if (authUser.role !== UserRole.SuperAdmin) { // Check if the post author is removing the post. - const post: any = await postById(id); + const post: IPost = await postById(id); if (post.author.toString() !== authUser._id.toString()) { return res.status(ErrorCodes.Bad_Request).send(ErrorMessages.Generic); } @@ -119,12 +127,12 @@ const PostController = { } } - const deletedPost = await deletePost(id); + const deletedPost: IPost = await deletePost(id); return res.send(deletedPost); }, - pin: async (req: Request, res: Response): Promise => { + pin: async (req: Request, res: Response): Promise> => { const { id, pinned } = req.body; - const updatedPost = await pinPost(id, pinned); + const updatedPost: IPost = await pinPost(id, pinned); return res.send(updatedPost); }, }; diff --git a/packages/orca-api/src/controllers/search.ts b/packages/orca-api/src/controllers/search.ts index 23a9f2d7..5f525765 100644 --- a/packages/orca-api/src/controllers/search.ts +++ b/packages/orca-api/src/controllers/search.ts @@ -1,15 +1,17 @@ import { Request, Response } from 'express'; import { AuthUser } from '../constants'; import { searchAll, searchUsers } from '../db'; +import { IPost } from '../models/post'; +import { IUser } from '../models/user'; const searchController = { - search: async (req: Request, res: Response): Promise => { + search: async (req: Request, res: Response<(IUser | IPost)[]>): Promise> => { const { searchQuery } = req.params; const authUser = req.user as AuthUser; const result = await searchAll(searchQuery, authUser?._id); return res.send(result); }, - searchUsers: async (req: Request, res: Response): Promise => { + searchUsers: async (req: Request, res: Response): Promise> => { const { searchQuery } = req.params; const authUser = req.user as AuthUser; const users = await searchUsers(searchQuery, authUser?._id); diff --git a/packages/orca-api/src/controllers/settings.ts b/packages/orca-api/src/controllers/settings.ts index ee758eb2..3b4f8a52 100644 --- a/packages/orca-api/src/controllers/settings.ts +++ b/packages/orca-api/src/controllers/settings.ts @@ -2,37 +2,39 @@ import bcrypt from 'bcrypt'; import { Request, Response } from 'express'; import { AuthUser, ErrorCodes, ErrorMessages, UserRole } from '../constants'; import { + countUsers, + createCommunity, + deleteUser, getSettings, - updateCommunity, - updateProfile, - getUserByUsername, getUserByEmail, - deleteUser, - settingsCreateUser, + getUserByUsername, getUsers, - updatePassword, + settingsCreateUser, + updateCommunity, updateLogo, - createCommunity, - countUsers, + updatePassword, + updateProfile, } from '../db'; +import { ISettings } from '../models/settings'; +import { IUser } from '../models/user'; import { checkEmailVerification } from '../utils'; import { uploadToCloudinary } from '../utils/cloudinary'; const SettingsController = { - settings: async (req: Request, res: Response): Promise => { + settings: async (req: Request, res: Response) => { const settings = await getSettings(); return res.send(settings); }, - users: async (req: Request, res: Response): Promise => { + users: async (req: Request, res: Response) => { const { offset, limit, searchQuery } = req.query; const users = await getUsers(+offset, +limit, null, false, false, searchQuery as string); return res.send(users); }, - usersTotal: async (req: Request, res: Response): Promise => { + usersTotal: async (req: Request, res: Response<{ total: number; verified: number }>) => { const { total, verified } = await countUsers(); return res.send({ total, verified }); }, - updateCommunity: async (req: Request, res: Response): Promise => { + updateCommunity: async (req: Request, res: Response) => { const { communityName, primaryColor, @@ -65,7 +67,7 @@ const SettingsController = { ); return res.send(community); }, - updateProfile: async (req: Request, res: Response): Promise => { + updateProfile: async (req: Request, res: Response) => { const { fullName, username } = req.body; const authUser = req.user as AuthUser; @@ -78,14 +80,14 @@ const SettingsController = { const updatedUser = await updateProfile(authUser._id, fullName, username); return res.send(updatedUser); }, - updatePassword: async (req: Request, res: Response): Promise => { + updatePassword: async (req: Request, res: Response) => { const authUser = req.user as AuthUser; const { password } = req.body; const passwordHash = await bcrypt.hash(password, 10); await updatePassword(authUser._id, passwordHash); return res.send('Password updated successfully.'); }, - uploadLogo: async (req: Request, res: Response): Promise => { + uploadLogo: async (req: Request, res: Response) => { const { imagePublicId } = req.body; const image = req.file; @@ -104,7 +106,7 @@ const SettingsController = { return res.status(ErrorCodes.Internal).send(ErrorMessages.Generic); }, - createUser: async (req: Request, res: Response): Promise => { + createUser: async (req: Request, res: Response) => { const { fullName, email, password, role } = req.body; if (!fullName || !email || !password || !role) { diff --git a/packages/orca-api/src/controllers/user.ts b/packages/orca-api/src/controllers/user.ts index 15cfba8c..dc443810 100644 --- a/packages/orca-api/src/controllers/user.ts +++ b/packages/orca-api/src/controllers/user.ts @@ -1,31 +1,32 @@ import { Request, Response } from 'express'; -import { getNewMembers, getUserById, getUsers, onlineUsers, updateUser, updateUserBanned } from '../db'; import { AuthUser, ErrorCodes, ErrorMessages, UserRole } from '../constants'; +import { getNewMembers, getUserById, getUsers, onlineUsers, updateUser, updateUserBanned } from '../db'; +import { IUser } from '../models/user'; import { uploadToCloudinary } from '../utils/cloudinary'; const UserController = { - user: async (req: Request, res: Response): Promise => { + user: async (req: Request, res: Response) => { const { id } = req.params; const user = await getUserById(id, true); return res.send(user); }, - getUsers: async (req: Request, res: Response): Promise => { + getUsers: async (req: Request, res: Response) => { const authUser = req.user as AuthUser; const { offset, limit, emailVerified } = req.query; const users = await getUsers(+offset, +limit, authUser?._id, emailVerified === 'true', true); return res.send(users); }, - onlineUsers: async (req: Request, res: Response): Promise => { + onlineUsers: async (req: Request, res: Response) => { const authUser = req.user as AuthUser; const users = await onlineUsers(authUser?._id); return res.send(users); }, - newMembers: async (req: Request, res: Response): Promise => { + newMembers: async (req: Request, res: Response) => { const authUser = req.user as AuthUser; const users = await getNewMembers(authUser?._id); return res.send(users); }, - uploadPhoto: async (req: Request, res: Response): Promise => { + uploadPhoto: async (req: Request, res: Response) => { const { imagePublicId, coverImagePublicId, isCover } = req.body; const authUser = req.user as AuthUser; const image = req.file; @@ -57,7 +58,7 @@ const UserController = { return res.status(ErrorCodes.Internal).send(ErrorMessages.Generic); }, - banUser: async (req: Request, res: Response): Promise => { + banUser: async (req: Request, res: Response) => { const { id, banned } = req.body; const user = await getUserById(id); diff --git a/packages/orca-api/src/db/channel.ts b/packages/orca-api/src/db/channel.ts index 35ebc5b0..67d36d81 100644 --- a/packages/orca-api/src/db/channel.ts +++ b/packages/orca-api/src/db/channel.ts @@ -1,11 +1,11 @@ -import Channel from '../models/channel'; +import Channel, { IChannel } from '../models/channel'; -export const getChannels = async (): Promise => { +export const getChannels = async (): Promise => { const channels = await Channel.find({}).sort({ order: 1 }); return channels; }; -export const getChannelByName = async (name: string): Promise => { +export const getChannelByName = async (name: string): Promise => { const channel = await Channel.findOne({ name }); return channel; }; @@ -15,7 +15,7 @@ export const createChannel = async ( authRequired: boolean, order: number, description?: string -): Promise => { +): Promise => { const newChannel = await Channel.create({ name, authRequired, @@ -30,7 +30,7 @@ export const updateChannel = async ( name: string, authRequired: boolean, description?: string -): Promise => { +): Promise => { const updatedChannel = await Channel.findOneAndUpdate( { _id: id }, { name, authRequired, description }, @@ -39,7 +39,7 @@ export const updateChannel = async ( return updatedChannel; }; -export const reorderChannels = async (sortedChannels: any) => { +export const reorderChannels = async (sortedChannels: any): Promise => { sortedChannels.forEach(async (channel, index) => { await Channel.findOneAndUpdate({ _id: channel._id }, { order: index }, { new: true }); }); @@ -47,7 +47,7 @@ export const reorderChannels = async (sortedChannels: any) => { return 'success'; }; -export const deleteChannel = async (id: string): Promise => { +export const deleteChannel = async (id: string): Promise => { const deletedChannel = await Channel.findByIdAndRemove(id); return deletedChannel; }; diff --git a/packages/orca-api/src/db/comment.ts b/packages/orca-api/src/db/comment.ts index 9b921e00..9ad167f6 100644 --- a/packages/orca-api/src/db/comment.ts +++ b/packages/orca-api/src/db/comment.ts @@ -1,14 +1,13 @@ -// @ts-nocheck -import Comment from '../models/comment'; +import Comment, { IComment } from '../models/comment'; import Post from '../models/post'; import User from '../models/user'; -export const commentById = async (id: string): Promise => { +export const commentById = async (id: string): Promise => { const comment = await Comment.findById(id); return comment; }; -export const createComment = async (comment: string, authorId: string, postId: string): Promise => { +export const createComment = async (comment: string, authorId: string, postId: string): Promise => { const newComment = await new Comment({ comment, author: authorId, @@ -24,7 +23,7 @@ export const createComment = async (comment: string, authorId: string, postId: s return newComment; }; -export const deleteComment = async (id: string): Promise => { +export const deleteComment = async (id: string): Promise => { const comment = await Comment.findByIdAndRemove(id); // Delete the comment from the user and post collection. diff --git a/packages/orca-api/src/db/connection.ts b/packages/orca-api/src/db/connection.ts index 84f2280d..7e30e794 100644 --- a/packages/orca-api/src/db/connection.ts +++ b/packages/orca-api/src/db/connection.ts @@ -1,8 +1,9 @@ import mongoose from 'mongoose'; -export const initDb = async (): Promise => { +export const initDb = async (): Promise => { try { const db = await mongoose.connect(process.env.MONGO_URL, { + dbName: 'orca', useCreateIndex: true, useNewUrlParser: true, useFindAndModify: false, diff --git a/packages/orca-api/src/db/follow.ts b/packages/orca-api/src/db/follow.ts index b26bdb69..27be28c2 100644 --- a/packages/orca-api/src/db/follow.ts +++ b/packages/orca-api/src/db/follow.ts @@ -1,13 +1,12 @@ -// @ts-nocheck -import Follow from '../models/follow'; +import Follow, { IFollow } from '../models/follow'; import User from '../models/user'; -export const followById = async (id: string): Promise => { +export const followById = async (id: string): Promise => { const follow = await Follow.findById(id); return follow; }; -export const createFollow = async (userId: string, followerId: string): Promise => { +export const createFollow = async (userId: string, followerId: string): Promise => { const follow = await new Follow({ user: userId, follower: followerId, @@ -20,7 +19,7 @@ export const createFollow = async (userId: string, followerId: string): Promise< return follow; }; -export const deleteFollow = async (id: string): Promise => { +export const deleteFollow = async (id: string): Promise => { const follow = await Follow.findByIdAndRemove(id); // Delete the follow from the user's collection. diff --git a/packages/orca-api/src/db/like.ts b/packages/orca-api/src/db/like.ts index 7e2ba83a..3e9a6359 100644 --- a/packages/orca-api/src/db/like.ts +++ b/packages/orca-api/src/db/like.ts @@ -1,14 +1,13 @@ -// @ts-nocheck -import Like from '../models/like'; +import Like, { ILike } from '../models/like'; import Post from '../models/post'; import User from '../models/user'; -export const likeById = async (id: string): Promise => { +export const likeById = async (id: string): Promise => { const like = await Like.findById(id); return like; }; -export const createLike = async (userId: string, postId: string): Promise => { +export const createLike = async (userId: string, postId: string): Promise => { const like = await new Like({ user: userId, post: postId }).save(); // Push the like to the post and user collection. @@ -18,7 +17,7 @@ export const createLike = async (userId: string, postId: string): Promise = return like; }; -export const deleteLike = async (id: string): Promise => { +export const deleteLike = async (id: string): Promise => { const like = await Like.findByIdAndRemove(id); // Delete the like from the user and post collection. diff --git a/packages/orca-api/src/db/message.ts b/packages/orca-api/src/db/message.ts index f30ef820..458cfc54 100644 --- a/packages/orca-api/src/db/message.ts +++ b/packages/orca-api/src/db/message.ts @@ -1,8 +1,24 @@ import mongoose from 'mongoose'; import { Message, User } from '../models'; +import { IMessage } from '../models/message'; -export const getConversations = async (authUserId: string): Promise => { - const lastConversations = await Message.aggregate([ +export interface IConversation { + _id: mongoose.Types.ObjectId[]; + message: string; + createdAt: Date; + sender: { + _id: mongoose.Types.ObjectId; + username: string; + }; + receiver: { + _id: mongoose.Types.ObjectId; + username: string; + }; + seen: boolean; +} + +export const getConversations = async (authUserId: string) => { + const lastConversations = await Message.aggregate([ { $match: { $or: [ @@ -97,11 +113,11 @@ export const getConversations = async (authUserId: string): Promise => { return lastConversations; }; -export const getMessages = async (authUserId: string, userId: string): Promise => { +export const getMessages = async (authUserId: string, userId: string): Promise => { const message = await Message.find() .and([ - { $or: [{ sender: authUserId }, { receiver: authUserId }] }, - { $or: [{ sender: userId }, { receiver: userId }] }, + { $or: [{ sender: mongoose.Types.ObjectId(authUserId) }, { receiver: mongoose.Types.ObjectId(authUserId) }] }, + { $or: [{ sender: mongoose.Types.ObjectId(userId) }, { receiver: mongoose.Types.ObjectId(userId) }] }, ]) .populate('sender', '-password') .populate('receiver', '-password') @@ -109,7 +125,7 @@ export const getMessages = async (authUserId: string, userId: string): Promise => { +export const createMessage = async (message: string, sender: string, receiver: string): Promise => { let newMessage = await new Message({ message, sender, @@ -120,7 +136,7 @@ export const createMessage = async (message: string, sender: string, receiver: s // Check if user already had a conversation. If not push their ids to users collection. const senderUser = await User.findById(sender); - if (!senderUser.messages.includes(receiver)) { + if (!senderUser.messages.includes(mongoose.Types.ObjectId(receiver))) { await User.findOneAndUpdate({ _id: sender }, { $push: { messages: receiver } }); await User.findOneAndUpdate({ _id: receiver }, { $push: { messages: sender } }); } @@ -128,7 +144,7 @@ export const createMessage = async (message: string, sender: string, receiver: s return newMessage; }; -export const updateMessageSeen = async (sender: string, receiver: string): Promise => { +export const updateMessageSeen = async (sender: string, receiver: string) => { const messages = await Message.updateMany({ sender, receiver, seen: false }, { seen: true }, { multi: true }); return messages; }; diff --git a/packages/orca-api/src/db/notification.ts b/packages/orca-api/src/db/notification.ts index aa8c2124..627d09ba 100644 --- a/packages/orca-api/src/db/notification.ts +++ b/packages/orca-api/src/db/notification.ts @@ -1,9 +1,8 @@ -// @ts-nocheck -import Notification from '../models/notification'; -import { NotificationType } from '../constants'; +import { type NotificationType } from '../constants'; +import Notification, { INotification } from '../models/notification'; import User from '../models/user'; -export const notificationById = async (id: string): Promise => { +export const notificationById = async (id: string): Promise => { const notification = await Notification.findById(id); return notification; }; @@ -13,7 +12,7 @@ export const notificationByAuthorUserAndType = async ( authorId: string, notificationType: string, postId?: string -): Promise => { +): Promise => { const query = { author: authorId, user: userId, @@ -27,7 +26,7 @@ export const notificationByAuthorUserAndType = async ( return notification; }; -export const notificationByAuthorAndUserId = async (authorId: string, userId: string): Promise => { +export const notificationByAuthorAndUserId = async (authorId: string, userId: string): Promise => { const notification = await Notification.findOne({ author: authorId, user: userId, @@ -37,8 +36,8 @@ export const notificationByAuthorAndUserId = async (authorId: string, userId: st return notification; }; -export const getUserNotifications = async (userId: any, offset: number, limit: number): Promise => { - const notifications: any = await Notification.find({ user: userId }) +export const getUserNotifications = async (userId: any, offset: number, limit: number): Promise => { + const notifications: INotification[] = await Notification.find({ user: userId }) .populate('author', '-password') .populate('user', '-password') .populate('follow') @@ -56,7 +55,7 @@ export const createNotification = async ( postId: string, notificationType: NotificationType, notificationTypeId: string -): Promise => { +): Promise => { let newNotification = await new Notification({ author: authorId, user: userId, @@ -77,7 +76,7 @@ export const createNotification = async ( return newNotification; }; -export const deleteNotification = async (id: string): Promise => { +export const deleteNotification = async (id: string): Promise => { let notification = await Notification.findByIdAndRemove(id); // Delete the notification from the user's collection. @@ -93,12 +92,12 @@ export const deleteNotification = async (id: string): Promise => { return notification; }; -export const updateNotificationSeen = async (userId: string): Promise => { +export const updateNotificationSeen = async (userId: string) => { const notifications = await Notification.updateMany({ user: userId, seen: false }, { seen: true }, { multi: true }); return notifications; }; -export const updateMessagesNotificationSeen = async (authUserId: string, userId: string): Promise => { +export const updateMessagesNotificationSeen = async (authUserId: string, userId: string) => { const notifications = await Notification.updateMany( { author: userId, user: authUserId, seen: false, message: { $exists: true, $ne: null } }, { seen: true }, diff --git a/packages/orca-api/src/db/post.ts b/packages/orca-api/src/db/post.ts index 75f2e5d6..c203a85b 100644 --- a/packages/orca-api/src/db/post.ts +++ b/packages/orca-api/src/db/post.ts @@ -1,23 +1,23 @@ -// @ts-nocheck -import Post from '../models/post'; import Channel from '../models/channel'; -import User from '../models/user'; -import Like from '../models/like'; import Comment from '../models/comment'; -import Notification from '../models/notification'; import Follow from '../models/follow'; +import Like from '../models/like'; +import Notification from '../models/notification'; +import Post, { IPost } from '../models/post'; +import User from '../models/user'; +import mongoose, { FilterQuery, UpdateQuery } from 'mongoose'; -export const postById = async (id: string): Promise => { +export const postById = async (id: string): Promise => { const post = await Post.findById(id); return post; }; -export const getFollowedPosts = async (userId: string, offset: number, limit: number): Promise => { +export const getFollowedPosts = async (userId: string, offset: number, limit: number): Promise => { const userFollowing = []; const follow = await Follow.find({ follower: userId }, { _id: 0 }).select('user'); follow.map((f) => userFollowing.push(f.user)); const posts = await Post.find({ - $or: [{ author: { $in: userFollowing } }, { author: userId }], + $or: [{ author: { $in: userFollowing } }, { author: mongoose.Types.ObjectId(userId) }], }) .populate({ path: 'author', @@ -50,12 +50,12 @@ export const getFollowedPosts = async (userId: string, offset: number, limit: nu return posts.filter((p: any) => p?.author?.banned !== true); }; -export const getChannelPosts = async (channelId: any): Promise => { - const posts: any = await Post.find({ channel: channelId }); +export const getChannelPosts = async (channelId: any): Promise => { + const posts: IPost[] = await Post.find({ channel: channelId }); return posts; }; -export const getPostsByChannelId = async (channelId: any, offset: number, limit: number): Promise => { +export const getPostsByChannelId = async (channelId: any, offset: number, limit: number): Promise => { const posts = await Post.find({ channel: channelId }) .populate({ path: 'author', @@ -84,7 +84,7 @@ export const getPostsByChannelId = async (channelId: any, offset: number, limit: return posts.filter((p: any) => p?.author?.banned !== true); }; -export const getPostsByAuthorId = async (authorId: any, offset: number, limit: number): Promise => { +export const getPostsByAuthorId = async (authorId: any, offset: number, limit: number): Promise => { const posts = await Post.find({ author: authorId }) .populate({ path: 'author', @@ -113,7 +113,7 @@ export const getPostsByAuthorId = async (authorId: any, offset: number, limit: n return posts; }; -export const getPostById = async (id: string): Promise => { +export const getPostById = async (id: string): Promise => { const post = await Post.findById(id) .populate({ path: 'author', @@ -141,7 +141,7 @@ export const createPost = async ( imagePublicId: string, channelId: string, authorId: string -): Promise => { +): Promise => { const newPost = await new Post({ title, image: imageUrl, @@ -158,15 +158,22 @@ export const createPost = async ( return newPost; }; -export const updatePost = async ( - postId: string, - title: string, - imageUrl?: string, - imagePublicId?: string, - imageToDeletePublicId?: string, - channelId: string -): Promise => { - const fields = { +export const updatePost = async ({ + postId, + title, + imageUrl, + imagePublicId, + imageToDeletePublicId, + channelId, +}: { + postId: string; + title: string; + imageUrl?: string; + imagePublicId?: string; + imageToDeletePublicId?: string; + channelId: string; +}): Promise => { + const fields: FilterQuery = { title, channel: channelId, }; @@ -181,7 +188,7 @@ export const updatePost = async ( fields.imagePublicId = ''; } - const updatedPost = await Post.findOneAndUpdate({ _id: postId }, { ...fields }, { new: true }) + const updatedPost = await Post.findOneAndUpdate({ _id: postId }, { ...(fields as UpdateQuery) }, { new: true }) .populate({ path: 'author', select: '-password', @@ -209,7 +216,7 @@ export const updatePost = async ( return updatedPost; }; -export const deletePost = async (id: string): Promise => { +export const deletePost = async (id: string): Promise => { const post = await Post.findByIdAndRemove(id); // Pull the post from the channel collection. @@ -246,7 +253,7 @@ export const deletePost = async (id: string): Promise => { return post; }; -export const pinPost = async (id: string, pinned: boolean): Promise => { +export const pinPost = async (id: string, pinned: boolean): Promise => { const updatedPost = await Post.findOneAndUpdate({ _id: id }, { pinned }, { new: true }) .populate({ path: 'author', diff --git a/packages/orca-api/src/db/search.ts b/packages/orca-api/src/db/search.ts index 8f006eba..21b72386 100644 --- a/packages/orca-api/src/db/search.ts +++ b/packages/orca-api/src/db/search.ts @@ -1,7 +1,7 @@ import { Post, User } from '../models'; import { checkEmailVerification } from '../utils'; -export const searchUsers = async (searchQuery: string, authUserId?: string): Promise => { +export const searchUsers = async (searchQuery: string, authUserId?: string) => { if (!searchQuery) { return []; } @@ -28,7 +28,7 @@ export const searchUsers = async (searchQuery: string, authUserId?: string): Pro return users; }; -export const searchAll = async (searchQuery: string, authUserId?: string): Promise => { +export const searchAll = async (searchQuery: string, authUserId?: string) => { if (!searchQuery) { return []; } diff --git a/packages/orca-api/src/db/settings.ts b/packages/orca-api/src/db/settings.ts index 4c6fe974..5efbc996 100644 --- a/packages/orca-api/src/db/settings.ts +++ b/packages/orca-api/src/db/settings.ts @@ -1,8 +1,7 @@ -// @ts-nocheck -import Settings from '../models/settings'; -import User from '../models/user'; +import Settings, { ISettings } from '../models/settings'; +import User, { IUser } from '../models/user'; -export const getSettings = async (): Promise => { +export const getSettings = async (): Promise => { const settings = await Settings.findOne({}); return settings; }; @@ -14,7 +13,7 @@ export const createCommunity = async ( facebookLoginEnabled: boolean, googleLoginEnabled: boolean, githubLoginEnabled: boolean -): Promise => { +): Promise => { const newSettings = await Settings.create({ communityName, primaryColor, @@ -28,12 +27,12 @@ export const createCommunity = async ( export const updateCommunity = async ( communityName: string, - primaryColor: boolean, + primaryColor: string, isEmailVerificationRequired: boolean, facebookLoginEnabled: boolean, googleLoginEnabled: boolean, githubLoginEnabled: boolean -): Promise => { +) => { const settings = await getSettings(); const updatedSettings = await Settings.findOneAndUpdate( { _id: settings._id }, @@ -50,17 +49,17 @@ export const updateCommunity = async ( return updatedSettings; }; -export const updateProfile = async (id: string, fullName: string, username: string): Promise => { +export const updateProfile = async (id: string, fullName: string, username: string): Promise => { const user = await User.findOneAndUpdate({ _id: id }, { fullName, username }, { new: true }); return user; }; -export const updatePassword = async (id: string, password: string): Promise => { +export const updatePassword = async (id: string, password: string): Promise => { const user = await User.findOneAndUpdate({ _id: id }, { password }, { new: true }); return user; }; -export const updateLogo = async (logo: string, logoPublicId: string): Promise => { +export const updateLogo = async (logo: string, logoPublicId: string): Promise => { const settings = await getSettings(); if (!settings) { const newSettings = await Settings.create({ communityLogo: logo, communityLogoPublicId: logoPublicId }); @@ -80,7 +79,7 @@ export const settingsCreateUser = async ( email: string, password: string, role: string -): Promise => { +): Promise => { const user = await User.create({ fullName, email, diff --git a/packages/orca-api/src/db/user.ts b/packages/orca-api/src/db/user.ts index 2c4f87df..eda26440 100644 --- a/packages/orca-api/src/db/user.ts +++ b/packages/orca-api/src/db/user.ts @@ -1,7 +1,8 @@ -// @ts-nocheck +import { FilterQuery } from 'mongoose'; import { User } from '../models'; +import { IUser } from '../models/user'; -export const getAuthUser = async (id: string): Promise => { +export const getAuthUser = async (id: string): Promise => { const user = await User.findOneAndUpdate({ _id: id }, { isOnline: true }) .select('-password') .populate({ path: 'posts', options: { sort: { createdAt: 'desc' } } }) @@ -21,8 +22,8 @@ export const getAuthUser = async (id: string): Promise => { return user; }; -export const getUserById = async (id: string, hideBannedUser?: boolean): Promise => { - const query = { _id: id }; +export const getUserById = async (id: string, hideBannedUser?: boolean): Promise => { + const query: FilterQuery = { _id: id }; if (hideBannedUser) { query.banned = { $ne: true }; } @@ -40,22 +41,22 @@ export const getUserById = async (id: string, hideBannedUser?: boolean): Promise return user; }; -export const getUserByEmail = async (email: string): Promise => { +export const getUserByEmail = async (email: string): Promise => { const user = await User.findOne({ email }); return user; }; -export const getUserByUsername = async (username: string): Promise => { +export const getUserByUsername = async (username: string): Promise => { const user = await User.findOne({ username }).select('-password'); return user; }; -export const updateUserIsOnline = async (userId: string, isOnline: boolean): Promise => { +export const updateUserIsOnline = async (userId: string, isOnline: boolean): Promise => { const user = await User.findOneAndUpdate({ _id: userId }, { isOnline }); return user; }; -export const updateUserResetPasswordToken = async (userId: string, token: string): Promise => { +export const updateUserResetPasswordToken = async (userId: string, token: string): Promise => { const user = await User.findOneAndUpdate({ _id: userId }, { resetPasswordToken: token }); return user; }; @@ -85,7 +86,7 @@ export const getUsers = async ( hideBannedUsers?: boolean, searchQuery?: string ): Promise => { - const query = { _id: { $ne: authUserId } }; + const query: FilterQuery = { _id: { $ne: authUserId } }; if (emailVerified) { query.emailVerified = emailVerified; } @@ -104,18 +105,18 @@ export const getUsers = async ( return users; }; -export const countUsers = async (): Promise => { +export const countUsers = async () => { const total = await User.countDocuments({}); const verified = await User.countDocuments({ emailVerified: true }); return { total, verified }; }; -export const onlineUsers = async (userId?: string): Promise => { +export const onlineUsers = async (userId?: string) => { const users = User.find({ isOnline: true, _id: { $ne: userId }, banned: { $ne: true } }).select('-password'); return users; }; -export const getNewMembers = async (userId?: string): Promise => { +export const getNewMembers = async (userId?: string) => { const users = User.find({ _id: { $ne: userId }, banned: { $ne: true } }) .select('-password') .limit(3) @@ -123,19 +124,19 @@ export const getNewMembers = async (userId?: string): Promise => { return users; }; -export const updateUser = async (id: string, fieldsToUpdate: any): Promise => { +export const updateUser = async (id: string, fieldsToUpdate: any): Promise => { const user = await User.findOneAndUpdate({ _id: id }, { ...fieldsToUpdate }, { new: true }) .populate('posts') .populate('likes'); return user; }; -export const deleteUser = async (id: string): Promise => { +export const deleteUser = async (id: string): Promise => { const user = await User.findByIdAndRemove(id); return user; }; -export const updateUserBanned = async (id: string, banned: boolean): Promise => { +export const updateUserBanned = async (id: string, banned: boolean): Promise => { const user = await User.findOneAndUpdate({ _id: id }, { banned: banned }, { new: true }); return user; diff --git a/packages/orca-api/src/models/channel.ts b/packages/orca-api/src/models/channel.ts index e2fb3c28..4a864c74 100644 --- a/packages/orca-api/src/models/channel.ts +++ b/packages/orca-api/src/models/channel.ts @@ -1,8 +1,16 @@ -import mongoose from 'mongoose'; +import mongoose, { Schema, Document, model, Model } from 'mongoose'; -const Schema = mongoose.Schema; +// 定义接口 +export interface IChannel extends Document { + name: string; + description?: string; + authRequired: boolean; + order: number; + posts: mongoose.Types.ObjectId[]; +} -const ChannelSchema = new Schema( +// 定义 Schema +const ChannelSchema = new Schema>( { name: { type: String, @@ -30,4 +38,5 @@ const ChannelSchema = new Schema( } ); -export default mongoose.model('Channel', ChannelSchema); +// 导出模型 +export default model>('Channel', ChannelSchema); diff --git a/packages/orca-api/src/models/comment.ts b/packages/orca-api/src/models/comment.ts index 32b4a8fe..30d47d66 100644 --- a/packages/orca-api/src/models/comment.ts +++ b/packages/orca-api/src/models/comment.ts @@ -1,8 +1,12 @@ -import mongoose from 'mongoose'; +import mongoose, { Document, Schema, Model } from 'mongoose'; -const Schema = mongoose.Schema; +export interface IComment extends Document { + comment: string; + post: mongoose.Types.ObjectId; + author: mongoose.Types.ObjectId; +} -const CommentSchema = new Schema( +const CommentSchema = new Schema>( { comment: { type: String, @@ -22,4 +26,4 @@ const CommentSchema = new Schema( } ); -export default mongoose.model('Comment', CommentSchema); +export default mongoose.model>('Comment', CommentSchema); diff --git a/packages/orca-api/src/models/follow.ts b/packages/orca-api/src/models/follow.ts index 91862ea9..bf130b87 100644 --- a/packages/orca-api/src/models/follow.ts +++ b/packages/orca-api/src/models/follow.ts @@ -1,8 +1,11 @@ -import mongoose from 'mongoose'; +import mongoose, { Document, Schema, Model } from 'mongoose'; -const Schema = mongoose.Schema; +export interface IFollow extends Document { + user: mongoose.Types.ObjectId; + follower: mongoose.Types.ObjectId; +} -const FollowSchema = new Schema( +const FollowSchema = new Schema>( { user: { type: Schema.Types.ObjectId, @@ -18,4 +21,4 @@ const FollowSchema = new Schema( } ); -export default mongoose.model('Follow', FollowSchema); +export default mongoose.model>('Follow', FollowSchema); diff --git a/packages/orca-api/src/models/like.ts b/packages/orca-api/src/models/like.ts index 5efc85d7..009ecae1 100644 --- a/packages/orca-api/src/models/like.ts +++ b/packages/orca-api/src/models/like.ts @@ -1,8 +1,11 @@ -import mongoose from 'mongoose'; +import mongoose, { Document, Schema, Model } from 'mongoose'; -const Schema = mongoose.Schema; +export interface ILike extends Document { + post: mongoose.Types.ObjectId; + user: mongoose.Types.ObjectId; +} -const LikeSchema = new Schema( +const LikeSchema = new Schema>( { post: { type: Schema.Types.ObjectId, @@ -18,4 +21,4 @@ const LikeSchema = new Schema( } ); -export default mongoose.model('Like', LikeSchema); +export default mongoose.model>('Like', LikeSchema); diff --git a/packages/orca-api/src/models/message.ts b/packages/orca-api/src/models/message.ts index 319a8410..ed4baf76 100644 --- a/packages/orca-api/src/models/message.ts +++ b/packages/orca-api/src/models/message.ts @@ -1,8 +1,13 @@ -import mongoose from 'mongoose'; +import mongoose, { Document, Schema, Model } from 'mongoose'; -const Schema = mongoose.Schema; +export interface IMessage extends Document { + sender: mongoose.Types.ObjectId; + receiver: mongoose.Types.ObjectId; + message: string; + seen: boolean; +} -const MessageSchema = new Schema( +const MessageSchema = new Schema>( { sender: { type: Schema.Types.ObjectId, @@ -21,4 +26,4 @@ const MessageSchema = new Schema( { timestamps: true } ); -export default mongoose.model('Message', MessageSchema); +export default mongoose.model>('Message', MessageSchema); diff --git a/packages/orca-api/src/models/notification.ts b/packages/orca-api/src/models/notification.ts index 59918620..90867c67 100644 --- a/packages/orca-api/src/models/notification.ts +++ b/packages/orca-api/src/models/notification.ts @@ -1,8 +1,17 @@ -import mongoose from 'mongoose'; +import mongoose, { Document, Schema, Model } from 'mongoose'; -const Schema = mongoose.Schema; +export interface INotification extends Document { + author: mongoose.Types.ObjectId; + user: mongoose.Types.ObjectId; + post: mongoose.Types.ObjectId; + like: mongoose.Types.ObjectId; + follow: mongoose.Types.ObjectId; + comment: mongoose.Types.ObjectId; + message: mongoose.Types.ObjectId; + seen: boolean; +} -const NotificationSchema = new Schema( +const NotificationSchema = new Schema>( { author: { type: Schema.Types.ObjectId, @@ -39,4 +48,4 @@ const NotificationSchema = new Schema( } ); -export default mongoose.model('Notification', NotificationSchema); +export default mongoose.model>('Notification', NotificationSchema); diff --git a/packages/orca-api/src/models/post.ts b/packages/orca-api/src/models/post.ts index bf05b0d4..eaa1c384 100644 --- a/packages/orca-api/src/models/post.ts +++ b/packages/orca-api/src/models/post.ts @@ -1,8 +1,17 @@ -import mongoose from 'mongoose'; +import mongoose, { Document, Schema, Model } from 'mongoose'; -const Schema = mongoose.Schema; +export interface IPost extends Document { + title: string; + image: string; + imagePublicId: string; + pinned: boolean; + channel: mongoose.Types.ObjectId; + author: mongoose.Types.ObjectId; + likes: mongoose.Types.ObjectId[]; + comments: mongoose.Types.ObjectId[]; +} -const PostSchema = new Schema( +const PostSchema = new Schema>( { title: String, image: String, @@ -34,4 +43,4 @@ const PostSchema = new Schema( } ); -export default mongoose.model('Post', PostSchema); +export default mongoose.model>('Post', PostSchema); diff --git a/packages/orca-api/src/models/settings.ts b/packages/orca-api/src/models/settings.ts index ef21b303..accfe9eb 100644 --- a/packages/orca-api/src/models/settings.ts +++ b/packages/orca-api/src/models/settings.ts @@ -1,9 +1,18 @@ -import mongoose from 'mongoose'; +import mongoose, { Document, Schema, Model } from 'mongoose'; import { DefaultCommunity } from '../constants'; -const Schema = mongoose.Schema; +export interface ISettings extends Document { + communityName: string; + communityLogo: string; + communityLogoPublicId: string; + facebookLoginEnabled: boolean; + googleLoginEnabled: boolean; + githubLoginEnabled: boolean; + primaryColor: string; + isEmailVerificationRequired: boolean; +} -const SettingsSchema = new Schema( +const SettingsSchema = new Schema>( { communityName: { type: String, @@ -46,4 +55,4 @@ const SettingsSchema = new Schema( } ); -export default mongoose.model('Settings', SettingsSchema); +export default mongoose.model>('Settings', SettingsSchema); diff --git a/packages/orca-api/src/models/user.ts b/packages/orca-api/src/models/user.ts index f024d0af..0928b683 100644 --- a/packages/orca-api/src/models/user.ts +++ b/packages/orca-api/src/models/user.ts @@ -1,10 +1,37 @@ -import mongoose, { Document } from 'mongoose'; +import mongoose, { Document, Schema, Model } from 'mongoose'; import bcrypt from 'bcrypt'; import { UserRole } from '../constants/types'; -const Schema = mongoose.Schema; +export interface IUser extends Document { + role: string; + fullName: string; + email: string; + emailVerified: boolean; + banned: boolean; + password: string; + username: string; + resetPasswordToken: string; + facebookId: string; + googleId: string; + githubId: string; + image: string; + imagePublicId: string; + about: string; + website: string; + coverImage: string; + coverImagePublicId: string; + isOnline: boolean; + posts: mongoose.Types.ObjectId[]; + likes: mongoose.Types.ObjectId[]; + comments: mongoose.Types.ObjectId[]; + followers: mongoose.Types.ObjectId[]; + following: mongoose.Types.ObjectId[]; + notifications: mongoose.Types.ObjectId[]; + messages: mongoose.Types.ObjectId[]; + isValidPassword: (password: string) => Promise; +} -const UserSchema = new Schema( +const UserSchema = new Schema>( { role: { type: String, @@ -112,39 +139,9 @@ const UserSchema = new Schema( } ); -export interface IUser extends Document { - role: string; - fullName: string; - email: string; - emailVerified: boolean; - banned: boolean; - password: string; - username: string; - resetPasswordToken: string; - facebookId: string; - googleId: string; - githubId: string; - image: string; - imagePublicId: string; - about: string; - website: string; - coverImage: string; - coverImagePublicId: string; - isOnline: boolean; - posts: string[]; - likes: string[]; - comments: string[]; - followers: string[]; - following: string[]; - notifications: string[]; - messages: string[]; - isValidPassword: (password: string) => Promise; -} - UserSchema.pre('save', async function (next) { if (this.password) { const hash = await bcrypt.hash(this.password, 10); - this.password = hash; } next(); @@ -153,8 +150,7 @@ UserSchema.pre('save', async function (next) { UserSchema.methods.isValidPassword = async function (password) { const user = this as IUser; const compare = await bcrypt.compare(password, user.password); - return compare; }; -export default mongoose.model('User', UserSchema); +export default mongoose.model>('User', UserSchema); diff --git a/packages/orca-frontend/.babelrc b/packages/orca-frontend/.babelrc deleted file mode 100644 index 854cb73a..00000000 --- a/packages/orca-frontend/.babelrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "presets": ["next/babel"], - "plugins": [["styled-components", { "ssr": true }]] -} diff --git a/packages/orca-frontend/pages/channel/[name].tsx b/packages/orca-frontend/app/channel/[name]/ChannelClient.tsx similarity index 57% rename from packages/orca-frontend/pages/channel/[name].tsx rename to packages/orca-frontend/app/channel/[name]/ChannelClient.tsx index b61bb063..4a7a9241 100644 --- a/packages/orca-frontend/pages/channel/[name].tsx +++ b/packages/orca-frontend/app/channel/[name]/ChannelClient.tsx @@ -1,42 +1,37 @@ +'use client'; + +import axios from 'axios'; import { FC, Fragment } from 'react'; import { useDispatch, useSelector } from 'react-redux'; -import axios from 'axios'; -import { PostCard, PostCreateButton } from '../../components/Post'; -import Layout from '../../components/Layout'; -import { LoadingDots, Skeleton, Spacing, Container, Button, Text } from '../../components/ui'; -import { RootState } from '../../store'; -import { Channel as ChannelType, DataLimit, Post } from '../../constants'; -import { useInfiniteScroll } from '../../utils'; -import Seo from '../../components/Seo'; -import { GetServerSideProps } from 'next'; -import { ChannelInfo } from '../../components/Channel'; -import { CommunityIcon } from '../../components/ui/icons'; -import { openAuthPopup, PopupType } from '../../store/auth'; - -const fetchChannelByName = async (channelName: string) => { - const { data } = await axios.get(`/channels/${channelName}`); - return data; -}; - -const fetchPostsByChannelId = async ({ queryKey, pageParam = 0 }) => { - const [, channelId] = queryKey; - const { data } = await axios.get( - `/posts/channel/${channelId}?offset=${pageParam}&limit=${DataLimit.PostsByChannelName}` - ); - return data; -}; +import { ChannelInfo } from '../../../components/Channel'; +import Layout from '../../../components/Layout'; +import { PostCard, PostCreateButton } from '../../../components/Post'; +import Seo from '../../../components/Seo'; +import { Button, Container, LoadingDots, Skeleton, Spacing, Text } from '../../../components/ui'; +import { CommunityIcon } from '../../../components/ui/icons'; +import { Channel as ChannelType, DataLimit, Post } from '../../../constants'; +import { RootState } from '../../../store'; +import { AuthActionTypes, PopupType, openAuthPopup } from '../../../store/auth'; +import { useInfiniteScroll } from '../../../utils'; +import { Dispatch } from 'redux'; interface ChannelProps { channel: ChannelType; } -const Channel: FC = ({ channel }) => { - const dispatch = useDispatch(); +const ChannelClient: FC = ({ channel }) => { + const dispatch = useDispatch>(); const authUser = useSelector((state: RootState) => state.auth.user); const { data, isFetching, isFetchingNextPage, refetch } = useInfiniteScroll({ key: ['postsByChannelName', channel._id], - apiCall: fetchPostsByChannelId, + apiCall: async ({ queryKey, pageParam = 0 }) => { + const [, channelId] = queryKey; + const { data } = await axios.get( + `/posts/channel/${channelId}?offset=${pageParam}&limit=${DataLimit.PostsByChannelName}` + ); + return data; + }, dataLimit: DataLimit.PostsByChannelName, }); @@ -97,9 +92,4 @@ const Channel: FC = ({ channel }) => { ); }; -export const getServerSideProps: GetServerSideProps = async ({ params }) => { - const channel = await fetchChannelByName(params.name as string); - return { props: { channel: channel } }; -}; - -export default Channel; +export default ChannelClient; diff --git a/packages/orca-frontend/app/channel/[name]/page.tsx b/packages/orca-frontend/app/channel/[name]/page.tsx new file mode 100644 index 00000000..7a965f03 --- /dev/null +++ b/packages/orca-frontend/app/channel/[name]/page.tsx @@ -0,0 +1,19 @@ +import ChannelClient from './ChannelClient'; + +const fetchChannelByName = async (channelName: string) => { + const data = await (await fetch(`http://localhost:4000/channels/${channelName}`, { method: 'GET' })).json(); + console.log(data); + return data; +}; + +// export async function generateStaticParams() { +// const channels = await axios.get('/channels'); +// return channels.data.map((channel: ChannelType) => ({ +// name: channel.name, +// })); +// } + +export default async function Page({ params }) { + const channel = await fetchChannelByName(params.name); + return ; +} diff --git a/packages/orca-frontend/app/globals.css b/packages/orca-frontend/app/globals.css new file mode 100644 index 00000000..e69de29b diff --git a/packages/orca-frontend/pages/_app.tsx b/packages/orca-frontend/app/layout.tsx similarity index 60% rename from packages/orca-frontend/pages/_app.tsx rename to packages/orca-frontend/app/layout.tsx index f49ea28a..b55cc081 100644 --- a/packages/orca-frontend/pages/_app.tsx +++ b/packages/orca-frontend/app/layout.tsx @@ -1,23 +1,37 @@ -import { FC, useEffect, useRef, useState } from 'react'; -import { ThemeProvider } from 'styled-components'; -import type { AppProps } from 'next/app'; +'use client'; + +import React from 'react'; +import './globals.css'; + import axios from 'axios'; import Router from 'next/router'; import NProgress from 'nprogress'; -import { Provider as ReduxProvider } from 'react-redux'; +import { useEffect, useRef, useState } from 'react'; import { QueryClient, QueryClientProvider } from 'react-query'; import { ReactQueryDevtools } from 'react-query/devtools'; -import { Hydrate } from 'react-query/hydration'; +import { Provider as ReduxProvider } from 'react-redux'; +import { ThemeProvider } from 'styled-components'; import App from '../components/App'; -import { store } from '../store'; import AuthPopup from '../components/Auth'; +import StyledComponentsRegistry from '../lib/registry'; +import { store } from '../store'; import currentTheme, { Theme } from '../theme'; import { Config } from '../utils'; axios.defaults.baseURL = Config.API_URL; axios.defaults.withCredentials = true; -const NextApp: FC = ({ Component, pageProps }) => { +/* TODO: should split the code here later, `use client` should not be here */ +/* export const metadata: Metadata = { + title: 'Create Next App', + description: 'Generated by create next app', + viewport: { + initialScale: 1, + width: 'device-width', + }, +} + */ +export default function RootLayout({ children }: { children: React.ReactNode }) { const [theme, setTheme] = useState(null); const queryClientRef = useRef(null); if (!queryClientRef.current) { @@ -48,23 +62,21 @@ const NextApp: FC = ({ Component, pageProps }) => { }, []); return ( - <> - - + + + - - - - - - + + + {children} + + + - - - - + + + + ); -}; - -export default NextApp; +} diff --git a/packages/orca-frontend/pages/members/index.tsx b/packages/orca-frontend/app/members/page.tsx similarity index 94% rename from packages/orca-frontend/pages/members/index.tsx rename to packages/orca-frontend/app/members/page.tsx index c5f42b18..f3522137 100644 --- a/packages/orca-frontend/pages/members/index.tsx +++ b/packages/orca-frontend/app/members/page.tsx @@ -1,14 +1,16 @@ -import React, { FC, Fragment } from 'react'; +'use client'; + import axios from 'axios'; +import { FC, Fragment } from 'react'; +import { useSelector } from 'react-redux'; import Layout from '../../components/Layout'; -import { Wrapper } from '../../components/Members/style'; import MembersCard from '../../components/Members/MembersCard'; -import { useInfiniteScroll } from '../../utils'; -import { DataLimit } from '../../constants'; -import { LoadingDots, Container, Empty, Skeleton } from '../../components/ui'; +import { Wrapper } from '../../components/Members/style'; import Seo from '../../components/Seo'; -import { useSelector } from 'react-redux'; +import { Container, Empty, LoadingDots, Skeleton } from '../../components/ui'; +import { DataLimit } from '../../constants'; import { RootState } from '../../store'; +import { useInfiniteScroll } from '../../utils'; const fetchUsers = async ({ queryKey, pageParam = 0 }) => { const [, isEmailVerificationRequired] = queryKey; diff --git a/packages/orca-frontend/app/messages/[id]/page.tsx b/packages/orca-frontend/app/messages/[id]/page.tsx new file mode 100644 index 00000000..f2bcf2fc --- /dev/null +++ b/packages/orca-frontend/app/messages/[id]/page.tsx @@ -0,0 +1,28 @@ +'use client'; + +import { useParams } from 'next/navigation'; +import Layout from '../../../components/Layout'; +import { Messages } from '../../../components/Messages'; +import Seo from '../../../components/Seo'; + +const Page = () => { + const params = useParams(); + + return ( + + + + + ); +}; + +// export const getServerSideProps: GetServerSideProps = async ({ req }) => { +// const isAuth = await isAuthorized(req); +// if (!isAuth) { +// return redirectToHome(); +// } + +// return { props: {} }; +// }; + +export default Page; diff --git a/packages/orca-frontend/pages/messages/index.tsx b/packages/orca-frontend/app/messages/page.tsx similarity index 83% rename from packages/orca-frontend/pages/messages/index.tsx rename to packages/orca-frontend/app/messages/page.tsx index 7e1251f4..efa2660d 100644 --- a/packages/orca-frontend/pages/messages/index.tsx +++ b/packages/orca-frontend/app/messages/page.tsx @@ -1,16 +1,19 @@ +'use client'; + import { FC } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import Layout from '../../components/Layout'; import { Messages } from '../../components/Messages'; import Seo from '../../components/Seo'; -import { Button, Spacing, Text, Container } from '../../components/ui'; +import { Button, Container, Spacing, Text } from '../../components/ui'; import { CommunityIcon } from '../../components/ui/icons'; import { RootState } from '../../store'; -import { openAuthPopup, PopupType } from '../../store/auth'; +import { AuthActionTypes, openAuthPopup, PopupType } from '../../store/auth'; +import { Dispatch } from 'redux'; const MessagesPage: FC = () => { const authUser = useSelector((state: RootState) => state.auth.user); - const dispatch = useDispatch(); + const dispatch = useDispatch>(); const openAuthModal = () => { dispatch(openAuthPopup(PopupType.Sign_Up)); diff --git a/packages/orca-frontend/app/middleware.ts b/packages/orca-frontend/app/middleware.ts new file mode 100644 index 00000000..7d3a83ae --- /dev/null +++ b/packages/orca-frontend/app/middleware.ts @@ -0,0 +1,12 @@ +import type { NextRequest } from 'next/server'; +import { NextResponse } from 'next/server'; + +// This function can be marked `async` if using `await` inside +export function middleware(request: NextRequest) { + return NextResponse.redirect(new URL('/', request.url)); +} + +// See "Matching Paths" below to learn more +export const config = { + matcher: '/settings/:path', +}; diff --git a/packages/orca-frontend/pages/404.tsx b/packages/orca-frontend/app/not-found.tsx similarity index 95% rename from packages/orca-frontend/pages/404.tsx rename to packages/orca-frontend/app/not-found.tsx index c517b071..a4cd17ed 100644 --- a/packages/orca-frontend/pages/404.tsx +++ b/packages/orca-frontend/app/not-found.tsx @@ -1,3 +1,5 @@ +'use client'; + import { FC } from 'react'; import Seo from '../components/Seo'; import { NotFound } from '../components/ui'; diff --git a/packages/orca-frontend/pages/notifications.tsx b/packages/orca-frontend/app/notifications.tsx similarity index 87% rename from packages/orca-frontend/pages/notifications.tsx rename to packages/orca-frontend/app/notifications.tsx index 72de7be0..09cbe2a5 100644 --- a/packages/orca-frontend/pages/notifications.tsx +++ b/packages/orca-frontend/app/notifications.tsx @@ -1,14 +1,15 @@ -import { FC, useEffect } from 'react'; -import Layout from '../components/Layout'; import axios from 'axios'; +import { FC, useEffect } from 'react'; +import { useMutation, useQuery } from 'react-query'; import { useDispatch, useSelector } from 'react-redux'; +import Layout from '../components/Layout'; import Notification from '../components/Notification'; -import { Empty, Container, Skeleton, Spacing, Button, Text } from '../components/ui'; -import { useMutation, useQuery } from 'react-query'; -import { RootState } from '../store'; -import { openAuthPopup, PopupType } from '../store/auth'; import Seo from '../components/Seo'; +import { Button, Container, Empty, Skeleton, Spacing, Text } from '../components/ui'; import { CommunityIcon } from '../components/ui/icons'; +import { RootState } from '../store'; +import { AuthActionTypes, openAuthPopup, PopupType } from '../store/auth'; +import { Dispatch } from 'redux'; export const updateNotificationSeen = async (): Promise => { const { data } = await axios.put('/notifications/seen'); @@ -26,7 +27,7 @@ const NotificationsPage: FC = () => { enabled: authUser !== null, }); const { mutateAsync } = useMutation(updateNotificationSeen); - const dispatch = useDispatch(); + const dispatch = useDispatch>(); const openAuthModal = () => { dispatch(openAuthPopup(PopupType.Sign_Up)); @@ -79,9 +80,7 @@ const NotificationsPage: FC = () => { {isEmpty && authUser !== null && You don't have notifications yet.} - {notifications?.map((notification) => ( - - ))} + {notifications?.map((notification) => )} ); diff --git a/packages/orca-frontend/app/notifications/page.tsx b/packages/orca-frontend/app/notifications/page.tsx new file mode 100644 index 00000000..e9fd9423 --- /dev/null +++ b/packages/orca-frontend/app/notifications/page.tsx @@ -0,0 +1,96 @@ +'use client'; + +import axios from 'axios'; +import { FC, useEffect } from 'react'; +import { useMutation, useQuery } from 'react-query'; +import { useDispatch, useSelector } from 'react-redux'; +import Layout from '../../components/Layout/Layout'; +import Notification from '../../components/Notification'; +import Seo from '../../components/Seo'; +import { Button } from '../../components/ui/Button'; +import Container from '../../components/ui/Container/Container'; +import Empty from '../../components/ui/Empty'; +import Skeleton from '../../components/ui/Skeleton'; +import Spacing from '../../components/ui/Spacing'; +import CommunityIcon from '../../components/ui/icons/CommunityIcon'; +import { RootState } from '../../store'; +import { AuthActionTypes, PopupType, openAuthPopup } from '../../store/auth'; +import { Dispatch } from 'redux'; + +export const updateNotificationSeen = async (): Promise => { + const { data } = await axios.put('/notifications/seen'); + return data; +}; + +const fetchUserNotifications = async (): Promise => { + const { data } = await axios.get('/notifications'); + return data; +}; + +const NotificationsPage: FC = () => { + const authUser = useSelector((state: RootState) => state.auth.user); + const { data: notifications, isFetching } = useQuery('fetchUserNotifications', fetchUserNotifications, { + enabled: authUser !== null, + }); + const { mutateAsync } = useMutation(updateNotificationSeen); + const dispatch = useDispatch>(); + + const openAuthModal = () => { + dispatch(openAuthPopup(PopupType.Sign_Up)); + }; + + useEffect(() => { + if (authUser?._id) { + mutateAsync(); + } + }, [mutateAsync, authUser]); + + const isEmpty = (!isFetching && !notifications) || notifications?.length === 0; + + if (isFetching) { + return ( + + + + + + ); + } + + if (!authUser) { + return ( + + + + + + {!authUser && ( + + )} + + + {/* To get notifications when someone interacts with your post, follows, or messages you. */} +
To get notifications when someone interacts with your post, follows, or messages you.
+
+
+
+
+ ); + } + + return ( + + + + + {isEmpty && authUser !== null && You don't have notifications yet.} + + {notifications?.map((notification) => )} + + + ); +}; + +export default NotificationsPage; diff --git a/packages/orca-frontend/pages/index.tsx b/packages/orca-frontend/app/page.tsx similarity index 90% rename from packages/orca-frontend/pages/index.tsx rename to packages/orca-frontend/app/page.tsx index 1206de65..546683c3 100644 --- a/packages/orca-frontend/pages/index.tsx +++ b/packages/orca-frontend/app/page.tsx @@ -1,15 +1,18 @@ -import { FC, Fragment } from 'react'; +'use client'; + import axios from 'axios'; +import { FC, Fragment } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import Layout from '../components/Layout'; -import { useInfiniteScroll } from '../utils'; -import { DataLimit, Post } from '../constants'; -import { RootState } from '../store'; import { PostCard, PostCreateButton } from '../components/Post'; -import { Container, Button, Spacing, LoadingDots, Skeleton, Text } from '../components/ui'; -import { openAuthPopup, PopupType } from '../store/auth'; -import { CommunityIcon } from '../components/ui/icons'; import Seo from '../components/Seo'; +import { Button, Container, LoadingDots, Skeleton, Spacing, Text } from '../components/ui'; +import { CommunityIcon } from '../components/ui/icons'; +import { DataLimit, Post } from '../constants'; +import { RootState } from '../store'; +import { AuthActionTypes, openAuthPopup, PopupType } from '../store/auth'; +import { useInfiniteScroll } from '../utils'; +import { Dispatch } from 'redux'; const fetchPostsByFollowing = async ({ pageParam = 0 }) => { const { data } = await axios.get(`/posts/follow?offset=${pageParam}&limit=${DataLimit.PostsByFollowing}`); @@ -17,7 +20,7 @@ const fetchPostsByFollowing = async ({ pageParam = 0 }) => { }; const Home: FC = () => { - const dispatch = useDispatch(); + const dispatch = useDispatch>(); const authUser = useSelector((state: RootState) => state.auth.user); const { data, isFetching, isFetchingNextPage } = useInfiniteScroll({ key: 'postsByFollowing', diff --git a/packages/orca-frontend/pages/post/[id].tsx b/packages/orca-frontend/app/post/[id]/PostPage.tsx similarity index 69% rename from packages/orca-frontend/pages/post/[id].tsx rename to packages/orca-frontend/app/post/[id]/PostPage.tsx index 7158f042..8e9152b7 100644 --- a/packages/orca-frontend/pages/post/[id].tsx +++ b/packages/orca-frontend/app/post/[id]/PostPage.tsx @@ -1,24 +1,22 @@ -import { FC } from 'react'; -import axios from 'axios'; -import Layout from '../../components/Layout'; -import { PostCard } from '../../components/Post'; -import { Container } from '../../components/ui'; -import Seo from '../../components/Seo'; +'use client'; + import { GetServerSideProps } from 'next'; +import { FC } from 'react'; import { useQuery } from 'react-query'; - -const fetchPost = async ({ queryKey }) => { - const [, postId] = queryKey; - const { data } = await axios.get(`/posts/${postId}`); - return data; -}; +import Layout from '../../../components/Layout'; +import { PostCard } from '../../../components/Post'; +import Seo from '../../../components/Seo'; +import { Container } from '../../../components/ui'; +import { fetchPost } from './fetch-post'; interface ProfilePageProps { post: any; } const PostPage: FC = ({ post }) => { - const { data, refetch } = useQuery(['post', post._id], fetchPost, { initialData: post }); + const { data, refetch } = useQuery(['post', post._id], fetchPost, { + initialData: post, + }); return ( diff --git a/packages/orca-frontend/app/post/[id]/fetch-post.tsx b/packages/orca-frontend/app/post/[id]/fetch-post.tsx new file mode 100644 index 00000000..80e03e5a --- /dev/null +++ b/packages/orca-frontend/app/post/[id]/fetch-post.tsx @@ -0,0 +1,6 @@ +export const fetchPost = async ({ queryKey }) => { + const [, postId] = queryKey; + const data = await (await fetch(`http://localhost:4000/posts/${postId}`)).json(); + console.log(data); + return data; +}; diff --git a/packages/orca-frontend/app/post/[id]/page.tsx b/packages/orca-frontend/app/post/[id]/page.tsx new file mode 100644 index 00000000..1e829e2d --- /dev/null +++ b/packages/orca-frontend/app/post/[id]/page.tsx @@ -0,0 +1,9 @@ +import { fetchPost } from './fetch-post'; +import PostPage from './PostPage'; + +const Page = async ({ params }) => { + const post = await fetchPost({ queryKey: ['post', params.id] }); + return ; +}; + +export default Page; diff --git a/packages/orca-frontend/pages/profile/[id].tsx b/packages/orca-frontend/app/profile/[id]/ProfilePage.tsx similarity index 70% rename from packages/orca-frontend/pages/profile/[id].tsx rename to packages/orca-frontend/app/profile/[id]/ProfilePage.tsx index cd7d4458..e3099244 100644 --- a/packages/orca-frontend/pages/profile/[id].tsx +++ b/packages/orca-frontend/app/profile/[id]/ProfilePage.tsx @@ -1,27 +1,16 @@ +'use client'; + import { FC, Fragment } from 'react'; -import axios from 'axios'; import { useSelector } from 'react-redux'; -import { RootState } from '../../store'; -import Layout from '../../components/Layout'; -import Profile from '../../components/Profile'; -import { PostCard, PostCreateButton } from '../../components/Post'; -import { DataLimit, Post } from '../../constants'; -import { useInfiniteScroll } from '../../utils'; -import { Container, Empty, LoadingDots, Skeleton, Spacing, Text } from '../../components/ui'; -import Seo from '../../components/Seo'; -import { GetServerSideProps } from 'next'; - -const fetchUser = async ({ queryKey }) => { - const [, id] = queryKey; - const { data } = await axios.get(`/users/${id}`); - return data; -}; - -const fetchPostsByAuthorId = async ({ queryKey, pageParam = 0 }) => { - const [, authorId] = queryKey; - const { data } = await axios.get(`/posts/author/${authorId}?offset=${pageParam}&limit=${DataLimit.PostsByAuthorId}`); - return data; -}; +import Layout from '../../../components/Layout'; +import { PostCard, PostCreateButton } from '../../../components/Post'; +import Profile from '../../../components/Profile'; +import Seo from '../../../components/Seo'; +import { Container, Empty, LoadingDots, Skeleton, Spacing, Text } from '../../../components/ui'; +import { DataLimit, Post } from '../../../constants'; +import { RootState } from '../../../store'; +import { useInfiniteScroll } from '../../../utils'; +import { fetchPostsByAuthorId } from './fetch-user'; interface ProfilePageProps { user: any; @@ -98,13 +87,4 @@ const ProfilePage: FC = ({ user }) => { ); }; -export const getServerSideProps: GetServerSideProps = async ({ params }) => { - const user = await fetchUser({ queryKey: ['user', params.id] }); - return { - props: { - user, - }, - }; -}; - export default ProfilePage; diff --git a/packages/orca-frontend/app/profile/[id]/fetch-user.tsx b/packages/orca-frontend/app/profile/[id]/fetch-user.tsx new file mode 100644 index 00000000..ac816539 --- /dev/null +++ b/packages/orca-frontend/app/profile/[id]/fetch-user.tsx @@ -0,0 +1,16 @@ +import axios from 'axios'; +import { DataLimit } from '../../../constants'; + +export const fetchUser = async ({ queryKey }) => { + const [, id] = queryKey; + const data = await (await fetch(`http://localhost:4000/users/${id}`, { method: 'GET' })).json(); + return data; +}; + +export const fetchPostsByAuthorId = async ({ queryKey, pageParam = 0 }) => { + const [, authorId] = queryKey; + const { data } = await axios.get( + `http://localhost:4000/posts/author/${authorId}?offset=${pageParam}&limit=${DataLimit.PostsByAuthorId}` + ); + return data; +}; diff --git a/packages/orca-frontend/app/profile/[id]/page.tsx b/packages/orca-frontend/app/profile/[id]/page.tsx new file mode 100644 index 00000000..e38f6d36 --- /dev/null +++ b/packages/orca-frontend/app/profile/[id]/page.tsx @@ -0,0 +1,9 @@ +import { fetchUser } from './fetch-user'; +import ProfilePage from './ProfilePage'; + +const Page = async ({ params }) => { + const user = await fetchUser({ queryKey: ['user', params.id] }); + return ; +}; + +export default Page; diff --git a/packages/orca-frontend/pages/reset-password/index.tsx b/packages/orca-frontend/app/reset-password/page.tsx similarity index 95% rename from packages/orca-frontend/pages/reset-password/index.tsx rename to packages/orca-frontend/app/reset-password/page.tsx index 90254102..cd1e4417 100644 --- a/packages/orca-frontend/pages/reset-password/index.tsx +++ b/packages/orca-frontend/app/reset-password/page.tsx @@ -1,3 +1,5 @@ +'use client'; + import { FC } from 'react'; import ResetPassword from '../../components/Auth/ResetPassword'; import Seo from '../../components/Seo'; diff --git a/packages/orca-frontend/app/settings/[name]/page.tsx b/packages/orca-frontend/app/settings/[name]/page.tsx new file mode 100644 index 00000000..f3007b62 --- /dev/null +++ b/packages/orca-frontend/app/settings/[name]/page.tsx @@ -0,0 +1,70 @@ +'use client'; + +import { useParams } from 'next/navigation'; +import Seo from '../../../components/Seo'; +import { SettingsLayout } from '../../../components/Settings'; +import SettingsAccount from '../../../components/Settings/SettingsAccount'; +import SettingsAuthentication from '../../../components/Settings/SettingsAuthentication'; +import SettingsCommunity from '../../../components/Settings/SettingsCommunity'; +import SettingsUsers from '../../../components/Settings/SettingsUsers'; +import { UserRole } from '../../../constants'; + +const pages = { + community: { + title: 'Community Settings', + component: , + authType: UserRole.Admin, + }, + account: { + title: 'Account Settings', + component: , + authType: UserRole.Regular, + }, + authentication: { + title: 'Authentication Settings', + component: , + authType: UserRole.Regular, + }, + users: { + title: 'Community Users', + component: , + authType: UserRole.SuperAdmin, + }, +}; + +const Settings = () => { + const p = useParams(); + const name = p.name; + + if (!name) { + return null; + } + + const currentPageName = typeof name === 'string' ? name : name[0]; + + const currentPage = pages[currentPageName].component; + const currentTile = pages[currentPageName].title; + + return ( + + + {currentPage} + + ); +}; + +/* such logic should be put in middleware.ts */ +// export const getServerSideProps: GetServerSideProps = async ({ +// req, +// params, +// }) => { +// const name = params.name as string +// const isAuth = await isAuthorized(req, pages[name].authType) +// if (!isAuth) { +// return redirectToHome() +// } + +// return { props: {} } +// } + +export default Settings; diff --git a/packages/orca-frontend/components/App/App.tsx b/packages/orca-frontend/components/App/App.tsx index 3828d69d..15d0add9 100644 --- a/packages/orca-frontend/components/App/App.tsx +++ b/packages/orca-frontend/components/App/App.tsx @@ -1,12 +1,15 @@ import { FC, ReactNode, useEffect } from 'react'; -import { useSelector, useDispatch } from 'react-redux'; -import { addUserNotification, removeUserNotification } from '../../store/auth'; -import { RootState } from '../../store'; -import { Events } from '../../constants'; -import { Alert, GlobalStyle, Loading } from '../ui'; +import theme, { Theme } from '../../theme'; +import GlobalStyle from '../ui/GlobalStyle/GlobalStyle'; +import Alert from '../ui/Alert/Alert'; +import { RootState } from '../../store'; +import { useDispatch, useSelector } from 'react-redux'; import { useAuth, useFetchSettings, useSocket } from '../../utils'; -import { Theme } from '../../theme'; +import { addUserNotification, AuthActionTypes, removeUserNotification } from '../../store/auth'; +import { Events } from '../../constants'; +import { Loading } from '../ui'; +import { Dispatch } from 'redux'; interface AppProps { children: ReactNode; @@ -16,7 +19,7 @@ interface AppProps { const App: FC = ({ children, setTheme }) => { const notification = useSelector((state: RootState) => state.notification); const authUser = useSelector((state: RootState) => state.auth.user); - const dispatch = useDispatch(); + const dispatch = useDispatch>(); const { authError, isAuthFetching } = useAuth(); const { isSettingsFetching } = useFetchSettings(setTheme); const socket = useSocket(); @@ -69,7 +72,7 @@ const App: FC = ({ children, setTheme }) => { <> {children} - + {notification.message && ( diff --git a/packages/orca-frontend/components/Auth/AuthPopup.tsx b/packages/orca-frontend/components/Auth/AuthPopup.tsx index 9a501d4a..1d0d284e 100644 --- a/packages/orca-frontend/components/Auth/AuthPopup.tsx +++ b/packages/orca-frontend/components/Auth/AuthPopup.tsx @@ -1,15 +1,16 @@ -import React, { FC } from 'react'; -import { useSelector, useDispatch } from 'react-redux'; -import { closeAuthPopup, PopupType } from '../../store/auth'; -import { Modal } from '../ui'; +import { FC } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; import { RootState } from '../../store'; -import SignUp from './SignUp'; -import Login from './Login'; +import { AuthActionTypes, closeAuthPopup, PopupType } from '../../store/auth'; +import { Modal } from '../ui'; import ForgotPassword from './ForgotPassword'; +import Login from './Login'; +import SignUp from './SignUp'; +import { Dispatch } from 'redux'; const AuthPopup: FC = () => { const { isPopupOpen, popupType } = useSelector((state: RootState) => state.auth); - const dispatch = useDispatch(); + const dispatch = useDispatch>(); const closeModal = () => { dispatch(closeAuthPopup()); diff --git a/packages/orca-frontend/components/Auth/ForgotPassword.tsx b/packages/orca-frontend/components/Auth/ForgotPassword.tsx index c50cb71d..e1be1468 100644 --- a/packages/orca-frontend/components/Auth/ForgotPassword.tsx +++ b/packages/orca-frontend/components/Auth/ForgotPassword.tsx @@ -1,10 +1,11 @@ -import React, { FC, useState, FormEvent, useEffect } from 'react'; -import { useSelector, useDispatch } from 'react-redux'; -import { PopupType, openAuthPopup } from '../../store/auth'; -import { Container, InputText, Button, Spacing, Text, LinkButton } from '../ui'; -import { RootState } from '../../store'; import axios from 'axios'; +import { FC, FormEvent, useEffect, useState } from 'react'; import { useMutation } from 'react-query'; +import { useDispatch, useSelector } from 'react-redux'; +import { RootState } from '../../store'; +import { AuthActionTypes, PopupType, openAuthPopup } from '../../store/auth'; +import { Button, Container, InputText, LinkButton, Spacing, Text } from '../ui'; +import { Dispatch } from 'redux'; const forgotPassword = async (email: string) => { const response = await axios.post('/forgot-password', { email }); @@ -13,7 +14,7 @@ const forgotPassword = async (email: string) => { const ForgotPassword: FC = () => { const { isPopupOpen, popupType } = useSelector((state: RootState) => state.auth); - const dispatch = useDispatch(); + const dispatch = useDispatch>(); const [errorMessage, setErrorMessage] = useState(''); const [successMessage, setSuccessMessage] = useState(''); const { mutateAsync: forgotPasswordMutation } = useMutation(forgotPassword); diff --git a/packages/orca-frontend/components/Auth/Login.tsx b/packages/orca-frontend/components/Auth/Login.tsx index dba7d477..db6a94a2 100644 --- a/packages/orca-frontend/components/Auth/Login.tsx +++ b/packages/orca-frontend/components/Auth/Login.tsx @@ -1,13 +1,14 @@ -import React, { FC, useState, FormEvent, useEffect } from 'react'; -import { useSelector, useDispatch } from 'react-redux'; -import { closeAuthPopup, setAuthUser, PopupType, openAuthPopup, setToken } from '../../store/auth'; -import { Container, InputText, Button, Spacing, Text, LinkButton } from '../ui'; -import { RootState } from '../../store'; import axios from 'axios'; +import { FC, FormEvent, useEffect, useState } from 'react'; import { useMutation } from 'react-query'; +import { useDispatch, useSelector } from 'react-redux'; +import { RootState } from '../../store'; +import { AuthActionTypes, PopupType, closeAuthPopup, openAuthPopup, setAuthUser, setToken } from '../../store/auth'; import { Config, Cookies, setCookie } from '../../utils'; -import { SocialButton, Or, Bottom } from './style'; -import { GithubIcon, GoogleIcon, FacebookIcon } from '../ui/icons'; +import { Button, Container, InputText, LinkButton, Spacing, Text } from '../ui'; +import { FacebookIcon, GithubIcon, GoogleIcon } from '../ui/icons'; +import { Bottom, Or, SocialButton } from './style'; +import { Dispatch } from 'redux'; interface User { email: string; @@ -29,7 +30,7 @@ const Login: FC = () => { const { facebookLoginEnabled, githubLoginEnabled, googleLoginEnabled } = useSelector( (state: RootState) => state.settings ); - const dispatch = useDispatch(); + const dispatch = useDispatch>(); const [errorMessage, setErrorMessage] = useState(''); const { mutateAsync: logInMutation } = useMutation(logIn); const [values, setValues] = useState(INITIAL_STATE); diff --git a/packages/orca-frontend/components/Auth/ResetPassword.tsx b/packages/orca-frontend/components/Auth/ResetPassword.tsx index 88e699bd..ef42e01c 100644 --- a/packages/orca-frontend/components/Auth/ResetPassword.tsx +++ b/packages/orca-frontend/components/Auth/ResetPassword.tsx @@ -1,12 +1,13 @@ -import React, { FC, useState, FormEvent, useEffect } from 'react'; import axios from 'axios'; -import { useRouter } from 'next/router'; +import { useRouter, useSearchParams } from 'next/navigation'; +import { FC, FormEvent, useEffect, useState } from 'react'; +import { useMutation } from 'react-query'; import { useDispatch, useSelector } from 'react-redux'; -import { Container, InputText, Button, Spacing, Text, H1 } from '../ui'; import { RootState } from '../../store'; -import { useMutation } from 'react-query'; -import { setAuthUser, setToken } from '../../store/auth'; +import { AuthActionTypes, setAuthUser, setToken } from '../../store/auth'; import { Cookies, setCookie } from '../../utils'; +import { Button, Container, H1, InputText, Spacing, Text } from '../ui'; +import { Dispatch } from 'redux'; interface resetPasswordProps { password: string; @@ -26,7 +27,8 @@ const INITIAL_STATE = { const ResetPassword: FC = () => { const router = useRouter(); - const dispatch = useDispatch(); + const searchParams = useSearchParams(); + const dispatch = useDispatch>(); const { isPopupOpen, popupType } = useSelector((state: RootState) => state.auth); const [errorMessage, setErrorMessage] = useState(''); const [successMessage, setSuccessMessage] = useState(''); @@ -41,18 +43,22 @@ const ResetPassword: FC = () => { const onSubmit = async (e: FormEvent) => { e.preventDefault(); setErrorMessage(''); - const { query } = router; + // const { query } = router; - if (!query.email || !query.token) { + if (!searchParams.get('email') || !searchParams.get('token')) { setErrorMessage('The link is broken'); return; } + // if (!query.email || !query.token) { + // setErrorMessage('The link is broken') + // return + // } try { const response = await resetPasswordMutation({ password: values.password, - email: query.email as string, - token: query.token as string, + email: searchParams.get('email') as string, + token: searchParams.get('token') as string, }); const { diff --git a/packages/orca-frontend/components/Auth/SignUp.tsx b/packages/orca-frontend/components/Auth/SignUp.tsx index 0f4f12de..66d43d5e 100644 --- a/packages/orca-frontend/components/Auth/SignUp.tsx +++ b/packages/orca-frontend/components/Auth/SignUp.tsx @@ -1,13 +1,14 @@ -import React, { FC, useState, FormEvent, useEffect } from 'react'; -import { useSelector, useDispatch } from 'react-redux'; -import { PopupType, openAuthPopup, setAuthUser, setToken, closeAuthPopup } from '../../store/auth'; -import { Container, InputText, Button, Spacing, Text, LinkButton } from '../ui'; -import { SuccessContainer, SocialButton, Or, Bottom } from './style'; -import { RootState } from '../../store'; import axios from 'axios'; +import { FC, FormEvent, useEffect, useState } from 'react'; import { useMutation } from 'react-query'; -import { GoogleIcon, FacebookIcon, GithubIcon, SuccessIcon } from '../ui/icons'; +import { useDispatch, useSelector } from 'react-redux'; +import { RootState } from '../../store'; +import { AuthActionTypes, PopupType, closeAuthPopup, openAuthPopup, setAuthUser, setToken } from '../../store/auth'; import { Config, Cookies, setCookie } from '../../utils'; +import { Button, Container, InputText, LinkButton, Spacing, Text } from '../ui'; +import { FacebookIcon, GithubIcon, GoogleIcon, SuccessIcon } from '../ui/icons'; +import { Bottom, Or, SocialButton, SuccessContainer } from './style'; +import { Dispatch } from 'redux'; interface User { fullName: string; @@ -31,7 +32,7 @@ const SignUp: FC = () => { const { isEmailVerificationRequired, facebookLoginEnabled, githubLoginEnabled, googleLoginEnabled } = useSelector( (state: RootState) => state.settings ); - const dispatch = useDispatch(); + const dispatch = useDispatch>(); const [errorMessage, setErrorMessage] = useState(''); const { mutateAsync: signUpMutation } = useMutation(signUp); const [values, setValues] = useState(INITIAL_STATE); diff --git a/packages/orca-frontend/components/Channel/ChannelCreate.tsx b/packages/orca-frontend/components/Channel/ChannelCreate.tsx index 2f5a8077..a6e0608d 100644 --- a/packages/orca-frontend/components/Channel/ChannelCreate.tsx +++ b/packages/orca-frontend/components/Channel/ChannelCreate.tsx @@ -1,11 +1,12 @@ -import { FC, FormEvent } from 'react'; -import { useRouter } from 'next/router'; -import { useDispatch } from 'react-redux'; import axios from 'axios'; +import { useRouter } from 'next/navigation'; +import { FC, FormEvent } from 'react'; import { useMutation, useQueryClient } from 'react-query'; -import { openAlert, AlertTypes } from '../../store/alert'; -import ChannelForm, { ChannelFormMode } from './ChannelForm'; +import { useDispatch } from 'react-redux'; +import { Dispatch } from 'redux'; import { Channel } from '../../constants'; +import { AlertActionTypes, AlertTypes, openAlert } from '../../store/alert'; +import ChannelForm, { ChannelFormMode } from './ChannelForm'; interface ChannelCreateProps { closeModal: () => void; @@ -23,7 +24,7 @@ const createChannel = async (channel: Channel) => { const ChannelCreate: FC = ({ closeModal, channels }) => { const router = useRouter(); - const dispatch = useDispatch(); + const dispatch = useDispatch>(); const queryClient = useQueryClient(); const { mutateAsync, isLoading, error } = useMutation(createChannel); diff --git a/packages/orca-frontend/components/Channel/ChannelEdit.tsx b/packages/orca-frontend/components/Channel/ChannelEdit.tsx index c823de10..10f68067 100644 --- a/packages/orca-frontend/components/Channel/ChannelEdit.tsx +++ b/packages/orca-frontend/components/Channel/ChannelEdit.tsx @@ -1,11 +1,12 @@ -import { FC, FormEvent } from 'react'; import axios from 'axios'; -import { useRouter } from 'next/router'; -import { useDispatch } from 'react-redux'; +import { useRouter } from 'next/navigation'; +import { FC, FormEvent } from 'react'; import { useMutation, useQueryClient } from 'react-query'; -import { openAlert, AlertTypes } from '../../store/alert'; -import ChannelForm, { IChannelForm, ChannelFormMode } from './ChannelForm'; +import { useDispatch } from 'react-redux'; +import { Dispatch } from 'redux'; import { Channel } from '../../constants'; +import { AlertActionTypes, AlertTypes, openAlert } from '../../store/alert'; +import ChannelForm, { ChannelFormMode, IChannelForm } from './ChannelForm'; interface ChannelEditProps { channel: Channel; @@ -23,7 +24,7 @@ const updateChannel = async (channel: any) => { const ChannelEdit: FC = ({ channel, closeModal }) => { const router = useRouter(); - const dispatch = useDispatch(); + const dispatch = useDispatch>(); const queryClient = useQueryClient(); const { mutateAsync, isLoading, error } = useMutation(updateChannel); diff --git a/packages/orca-frontend/components/Channel/ChannelForm.tsx b/packages/orca-frontend/components/Channel/ChannelForm.tsx index 0a08428a..0e6283f9 100644 --- a/packages/orca-frontend/components/Channel/ChannelForm.tsx +++ b/packages/orca-frontend/components/Channel/ChannelForm.tsx @@ -1,7 +1,9 @@ +'use client'; + import { FC, FormEvent, useEffect, useState } from 'react'; -import { InputText, Spacing, P, Toggle, Button, Text, TextAreaAutoSize } from '../ui'; -import { LabelAndToggle, ButtonContainer } from './style'; import { Channel } from '../../constants'; +import { Button, InputText, P, Spacing, Text, TextAreaAutoSize, Toggle } from '../ui'; +import { ButtonContainer, LabelAndToggle } from './style'; export enum ChannelFormMode { Create, diff --git a/packages/orca-frontend/components/Follow/Follow.tsx b/packages/orca-frontend/components/Follow/Follow.tsx index 91bd8f4c..594e0f85 100644 --- a/packages/orca-frontend/components/Follow/Follow.tsx +++ b/packages/orca-frontend/components/Follow/Follow.tsx @@ -1,14 +1,15 @@ -import React, { FC } from 'react'; import axios from 'axios'; -import { useDispatch, useSelector } from 'react-redux'; import debounce from 'lodash/debounce'; +import { FC } from 'react'; import { useMutation } from 'react-query'; -import { RootState } from '../../store'; -import { addUserFollowing, removeUserFollowing } from '../../store/auth'; +import { useDispatch, useSelector } from 'react-redux'; import { AuthUser } from '../../constants'; -import { useNotifications } from '../../utils'; import { NotificationType } from '../../constants/Notification'; +import { RootState } from '../../store'; +import { addUserFollowing, AuthActionTypes, removeUserFollowing } from '../../store/auth'; +import { useNotifications } from '../../utils'; import { Root } from './style'; +import { Dispatch } from 'redux'; const createFollow = async ({ userId }) => { const follow = await axios.post('/follow/create', { userId }); @@ -28,7 +29,7 @@ interface FollowProps { const Follow: FC = ({ user, queryKey }) => { const authUser = useSelector((state: RootState) => state.auth.user); const isFollowing: any = authUser.following.find((f: any) => f.user === user._id); - const dispatch = useDispatch(); + const dispatch = useDispatch>(); const { createNotification, deleteNotification } = useNotifications(); const { mutateAsync: createFollowMutation } = useMutation(createFollow); @@ -38,8 +39,11 @@ const Follow: FC = ({ user, queryKey }) => { const follow = isFollowing ? await deleteFollowMutation(isFollowing._id) : await createFollowMutation({ userId: user._id }); - - isFollowing ? dispatch(removeUserFollowing(follow._id)) : dispatch(addUserFollowing(follow)); + if (isFollowing) { + dispatch(removeUserFollowing(follow._id)); + } else { + dispatch(addUserFollowing(follow)); + } if (isFollowing) { const notification: any = user.notifications.find((n: any) => n?.follow?._id === isFollowing?._id); diff --git a/packages/orca-frontend/components/Header/Header.tsx b/packages/orca-frontend/components/Header/Header.tsx index edd9f93f..65134e33 100644 --- a/packages/orca-frontend/components/Header/Header.tsx +++ b/packages/orca-frontend/components/Header/Header.tsx @@ -1,28 +1,29 @@ -import { useState, forwardRef, ForwardRefRenderFunction, useRef, RefObject, useEffect } from 'react'; -import Router from 'next/router'; -import { useSelector, useDispatch } from 'react-redux'; +import { forwardRef, ForwardRefRenderFunction, RefObject, useEffect, useRef, useState } from 'react'; +// import Router from 'next/router'; +import { useRouter } from 'next/navigation'; import { useMutation } from 'react-query'; -import { useRouter } from 'next/router'; -import { updateNotificationSeen } from '../../pages/notifications'; +import { useDispatch, useSelector } from 'react-redux'; import { - Root, - Wrapper, - Hamburger, Container, - SearchContainer, + Hamburger, + Logo, NotificationsAndAvatar, NotificationsCount, - Logo, + Root, + SearchContainer, + Wrapper, } from './style'; -import { MenuIcon, NotificationIcon } from '../ui/icons'; -import { Link, Button, Avatar, Spacing } from '../ui'; -import { openAuthPopup, cleanUserNotifications, PopupType } from '../../store/auth'; -import HeaderUser from './HeaderUser'; -import HeaderNotifications from './HeaderNotifications'; -import Search from '../Search'; +import { updateNotificationSeen } from '../../app/notifications'; import { RootState } from '../../store'; +import { AuthActionTypes, cleanUserNotifications, openAuthPopup, PopupType } from '../../store/auth'; import { useBreakpoints } from '../../utils'; +import Search from '../Search'; +import { Avatar, Button, Link, Spacing } from '../ui'; +import { MenuIcon, NotificationIcon } from '../ui/icons'; +import HeaderNotifications from './HeaderNotifications'; +import HeaderUser from './HeaderUser'; +import { Dispatch } from 'redux'; interface HeaderProps { toggleSidebar?: () => void; @@ -31,7 +32,7 @@ interface HeaderProps { const Header: ForwardRefRenderFunction = ({ toggleSidebar }, ref) => { const breakpoint = useBreakpoints(); - const dispatch = useDispatch(); + const dispatch = useDispatch>(); const authUser = useSelector((state: RootState) => state.auth.user); const logo = useSelector((state: RootState) => state.settings.communityLogo); const { mutateAsync: updateSeen } = useMutation(updateNotificationSeen); @@ -42,15 +43,14 @@ const Header: ForwardRefRenderFunction = ({ togg const [isNotificationsDropdownOpen, setIsNotificationsDropdownOpen] = useState(false); useEffect(() => { - Router.events.on('routeChangeComplete', () => { - if (isUserDropdownOpen) { - setIsUserDropdownOpen(false); - } - - if (isNotificationsDropdownOpen) { - setIsNotificationsDropdownOpen(false); - } - }); + // Router.events.on('routeChangeComplete', () => { + // if (isUserDropdownOpen) { + // setIsUserDropdownOpen(false); + // } + // if (isNotificationsDropdownOpen) { + // setIsNotificationsDropdownOpen(false); + // } + // }); }, [isUserDropdownOpen, isNotificationsDropdownOpen]); const closeDropDown = () => { diff --git a/packages/orca-frontend/components/Layout/Layout.tsx b/packages/orca-frontend/components/Layout/Layout.tsx index 15b36d90..2c8baae7 100644 --- a/packages/orca-frontend/components/Layout/Layout.tsx +++ b/packages/orca-frontend/components/Layout/Layout.tsx @@ -1,5 +1,7 @@ +'use client'; + import { FC, useEffect, useRef, useState } from 'react'; -import Router from 'next/router'; +// import Router from 'next/router'; import { Root, StyledContainer } from './style'; import Header from '../Header'; import SideBar from '../Sidebar'; @@ -17,7 +19,13 @@ interface LayoutProps { marginTop?: Spacing; } -const Layout: FC = ({ children, hideLeftSidebar, hideRightSidebar, containerMaxWidth, marginTop }) => { +const Layout: FC = ({ + children, + hideLeftSidebar = false, + hideRightSidebar = false, + containerMaxWidth = 'sm', + marginTop = 'md', +}) => { const isAnnouncementDisabled = getCookie(Cookies.Announcement_Disabled); const [isAnnouncementOpen, setIsAnnouncementOpen] = useState(isAnnouncementDisabled !== 'true'); const sideBarRef = useRef(null); @@ -30,11 +38,11 @@ const Layout: FC = ({ children, hideLeftSidebar, hideRightSidebar, const toggleSidebar = () => setIsSidebarOpen(!isSideBarOpen); useEffect(() => { - Router.events.on('routeChangeComplete', () => { - if (isSideBarOpen) { - setIsSidebarOpen(false); - } - }); + // Router.events.on('routeChangeComplete', () => { + // if (isSideBarOpen) { + // setIsSidebarOpen(false); + // } + // }); }, [isSideBarOpen]); return ( @@ -59,11 +67,4 @@ const Layout: FC = ({ children, hideLeftSidebar, hideRightSidebar, ); }; -Layout.defaultProps = { - hideLeftSidebar: false, - hideRightSidebar: false, - containerMaxWidth: 'sm', - marginTop: 'md', -}; - export default Layout; diff --git a/packages/orca-frontend/components/Layout/style.ts b/packages/orca-frontend/components/Layout/style.ts index 8d79aad2..e6619f23 100644 --- a/packages/orca-frontend/components/Layout/style.ts +++ b/packages/orca-frontend/components/Layout/style.ts @@ -1,3 +1,4 @@ +import shouldForwardProp from '@styled-system/should-forward-prop'; import styled from 'styled-components'; import { Container } from '../ui'; @@ -27,7 +28,9 @@ interface StyledContainerProps { hideRightSidebar?: boolean; } -export const StyledContainer = styled(Container)` +export const StyledContainer = styled(Container).withConfig({ + shouldForwardProp: (prop) => shouldForwardProp(prop) && prop !== 'hideRightSidebar', +})` @media (min-width: ${(p) => parseInt(p.theme.screen.md, 10) + 20 + 'px'}) { max-width: ${(p) => p.theme.screen.xs}; } diff --git a/packages/orca-frontend/components/Like/Like.tsx b/packages/orca-frontend/components/Like/Like.tsx index 336c88a5..c6007215 100644 --- a/packages/orca-frontend/components/Like/Like.tsx +++ b/packages/orca-frontend/components/Like/Like.tsx @@ -1,16 +1,17 @@ -import React, { FC } from 'react'; -import styled from 'styled-components'; import axios from 'axios'; -import { useSelector, useDispatch } from 'react-redux'; -import { useMutation, useQueryClient } from 'react-query'; import debounce from 'lodash/debounce'; -import { openAuthPopup, PopupType } from '../../store/auth'; -import { LikeIcon } from '../ui/icons'; -import Spacing from '../ui/Spacing'; +import { FC } from 'react'; +import { useMutation, useQueryClient } from 'react-query'; +import { useDispatch, useSelector } from 'react-redux'; +import styled from 'styled-components'; +import { NotificationType } from '../../constants/Notification'; import { RootState } from '../../store'; +import { AuthActionTypes, openAuthPopup, PopupType } from '../../store/auth'; import { useNotifications } from '../../utils'; -import { NotificationType } from '../../constants/Notification'; import { Button } from '../ui/Button'; +import { LikeIcon } from '../ui/icons'; +import Spacing from '../ui/Spacing'; +import { Dispatch } from 'redux'; const createLike = async ({ postId }) => { const like = await axios.post('/likes/create', { postId }); @@ -35,7 +36,7 @@ const StyledButton = styled(Button)` `; const Like: FC = ({ withText, fullWidth, hasLiked, post, queryKey }) => { - const dispatch = useDispatch(); + const dispatch = useDispatch>(); const authUser = useSelector((state: RootState) => state.auth.user); const color = hasLiked ? 'primary' : 'textSecondary'; const queryClient = useQueryClient(); @@ -101,7 +102,11 @@ const Like: FC = ({ withText, fullWidth, hasLiked, post, queryKey }) const likeMutation = async () => { try { const like = hasLiked ? await deleteLikeMutation(hasLiked?._id) : await createLikeMutation({ postId: post._id }); - hasLiked ? updateAfterUnLike(like._id) : updateAfterLike(like); + if (hasLiked) { + updateAfterUnLike(like._id); + } else { + updateAfterLike(like); + } if (hasLiked) { const notification = post.author.notifications.find((n) => n?.like?._id === hasLiked?._id); diff --git a/packages/orca-frontend/components/Messages/Messages/index.tsx b/packages/orca-frontend/components/Messages/Messages/index.tsx index 6ed8b86c..f8f528a7 100644 --- a/packages/orca-frontend/components/Messages/Messages/index.tsx +++ b/packages/orca-frontend/components/Messages/Messages/index.tsx @@ -1,6 +1,6 @@ import axios from 'axios'; import React, { FC, useEffect } from 'react'; -import { useRouter } from 'next/router'; +import { useRouter } from 'next/navigation'; import { useSelector } from 'react-redux'; import { v4 as uuid } from 'uuid'; import { useMutation, useQuery, useQueryClient } from 'react-query'; @@ -97,7 +97,7 @@ const Messages: FC = ({ userId }) => { }, [user, conversations, userId, authUser, queryClient]); const onSearchItemClick = (user: any) => { - router.push(`/messages/${user._id}`, undefined, { shallow: true }); + router.push(`/messages/${user._id}`); }; return ( diff --git a/packages/orca-frontend/components/Messages/MessagesChat/index.tsx b/packages/orca-frontend/components/Messages/MessagesChat/index.tsx index 018abed6..eb25a825 100644 --- a/packages/orca-frontend/components/Messages/MessagesChat/index.tsx +++ b/packages/orca-frontend/components/Messages/MessagesChat/index.tsx @@ -1,32 +1,33 @@ -import React, { FC, KeyboardEvent, useEffect, useState, useRef, FormEvent } from 'react'; import axios from 'axios'; +import { usePathname } from 'next/navigation'; +import { FC, FormEvent, KeyboardEvent, useEffect, useRef, useState } from 'react'; import { useMutation, useQuery, useQueryClient } from 'react-query'; +import { useDispatch, useSelector } from 'react-redux'; +import { Dispatch } from 'redux'; +import { Events } from '../../../constants'; +import { NotificationType } from '../../../constants/Notification'; +import { RootState } from '../../../store'; +import { AuthActionTypes, removeUserNotification } from '../../../store/auth'; +import { date, useNotifications, useSocket } from '../../../utils'; +import Linkify from '../../Linkify'; +import Search from '../../Search'; +import { Avatar, Button, Link, Spacing } from '../../ui'; +import { PlusIcon } from '../../ui/icons'; +import { addToMessagesList } from '../cache'; import { - Root, - Header, Container, - FullName, - MessageWrapper, - MessagesConversation, Conversation, Form, + FullName, + Header, Message, MessageDate, - Textarea, + MessageWrapper, + MessagesConversation, + Root, ScrollWrapper, + Textarea, } from './style'; -import { Avatar, Link, Spacing, Button } from '../../ui'; -import Search from '../../Search'; -import { PlusIcon } from '../../ui/icons'; -import { RootState } from '../../../store'; -import { useDispatch, useSelector } from 'react-redux'; -import { useSocket, date, useNotifications } from '../../../utils'; -import { Events } from '../../../constants'; -import { addToMessagesList } from '../cache'; -import { NotificationType } from '../../../constants/Notification'; -import { removeUserNotification } from '../../../store/auth'; -import Linkify from '../../Linkify'; -import { useRouter } from 'next/router'; interface MessagesChatProps { onSearchItemClick: (user: any) => void; @@ -51,8 +52,8 @@ const updateMessagesSeen = async (userId) => { }; const MessagesChat: FC = ({ onSearchItemClick, userId, user }) => { - const router = useRouter(); const [message, setMessage] = useState(''); + const pathname = usePathname(); const scrollToBottomRef = useRef(null); const authUser = useSelector((state: RootState) => state.auth.user); const queryClient = useQueryClient(); @@ -62,7 +63,7 @@ const MessagesChat: FC = ({ onSearchItemClick, userId, user } const { mutateAsync: sendMessage } = useMutation(createMessage); const { mutateAsync: updateMessagesSeenMutation } = useMutation(updateMessagesSeen); const socket = useSocket(); - const dispatch = useDispatch(); + const dispatch = useDispatch>(); const { createNotification } = useNotifications(); useEffect(() => { @@ -202,16 +203,18 @@ const MessagesChat: FC = ({ onSearchItemClick, userId, user } - {router.pathname !== '/messages' && ( -
-