├── front
└── mymentor-gpt
│ ├── README.md
│ ├── src
│ ├── vite-env.d.ts
│ ├── pages
│ │ ├── Consult.tsx
│ │ ├── Swot.tsx
│ │ └── Login.tsx
│ ├── index.css
│ ├── components
│ │ ├── ProtectedRoute.tsx
│ │ ├── Notification.tsx
│ │ ├── Navbar.tsx
│ │ ├── Modal.tsx
│ │ ├── Sidebar.tsx
│ │ └── InputSuggest.tsx
│ ├── main.tsx
│ └── assets
│ │ └── loading.svg
│ ├── .dockerignore
│ ├── .env.template
│ ├── postcss.config.js
│ ├── tsconfig.json
│ ├── vite.config.ts
│ ├── index.html
│ ├── .gitignore
│ ├── Dockerfile
│ ├── nginx.conf
│ ├── tsconfig.node.json
│ ├── tailwind.config.js
│ ├── deploy.sh
│ ├── tsconfig.app.json
│ ├── .eslintrc.cjs
│ └── package.json
├── back
├── certs
│ ├── myCA.srl
│ ├── server.ext
│ ├── server.csr
│ ├── myCA.pem
│ ├── generate_certs.sh
│ ├── server.crt
│ ├── server.key
│ └── myCA.key
├── .env.template
├── Dockerfile
├── prompt.js
├── package.json
├── deploy.sh
├── server.js
└── package-lock.json
├── .gitignore
├── README.md
└── LICENSE
/front/mymentor-gpt/README.md:
--------------------------------------------------------------------------------
1 | # MyMenthor FrontEnd
2 |
--------------------------------------------------------------------------------
/back/certs/myCA.srl:
--------------------------------------------------------------------------------
1 | 1470D823A2800A25B4DDDF3A195AA5CEB50A0DE1
2 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | build
3 | .dockerignore
4 | Dockerfile
5 | .git
6 | .gitignore
7 | .env
8 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/.env.template:
--------------------------------------------------------------------------------
1 | VITE_API_URL=Backend URL
2 | VITE_API_USERNAME=Name of user login
3 | VITE_API_PASSWORD=password
4 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/postcss.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/back/.env.template:
--------------------------------------------------------------------------------
1 | NAME=Username expected
2 | PASSWORD=password
3 | CLIENTURL=Origin to allow requests from (CORS)
4 | OPENAI_KEY=Key obtained from platform.openai
5 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "files": [],
3 | "references": [
4 | {
5 | "path": "./tsconfig.app.json"
6 | },
7 | {
8 | "path": "./tsconfig.node.json"
9 | }
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react-swc'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | })
8 |
--------------------------------------------------------------------------------
/back/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:18-alpine
2 |
3 | ENV NODE_ENV=production
4 |
5 | WORKDIR /usr/src/app
6 |
7 | COPY package*.json ./
8 |
9 | RUN npm install
10 |
11 | COPY . .
12 |
13 | EXPOSE 8080
14 |
15 | ENTRYPOINT [ "node", "server.js" ]
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | jspm_packages/
3 |
4 | .npm
5 |
6 | .eslintcache
7 |
8 | .node_repl_history
9 |
10 | logs/
11 | *.log
12 |
13 | build/
14 | *.tgz
15 |
16 | .env
17 | .env.test
18 | .env.*.local
19 | .env.*
20 | !.env.template
21 |
22 | *.rc
23 |
24 | dist/
25 |
26 | *.tsbuildinfo
27 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | MyMenthor GPT
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:18-alpine AS build
2 |
3 | WORKDIR /app
4 |
5 | COPY package*.json ./
6 |
7 | RUN npm install
8 |
9 | COPY . .
10 |
11 | RUN npm run build
12 |
13 | FROM nginx:alpine
14 |
15 | COPY --from=build /app/dist /usr/share/nginx/html
16 |
17 | COPY nginx.conf /etc/nginx/conf.d/default.conf
18 |
19 | EXPOSE 8080
20 |
21 | CMD ["nginx", "-g", "daemon off;"]
22 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/nginx.conf:
--------------------------------------------------------------------------------
1 | server {
2 | listen 8080;
3 |
4 | server_name _;
5 |
6 | root /usr/share/nginx/html;
7 | index index.html index.htm;
8 |
9 | location / {
10 | try_files $uri /index.html;
11 | }
12 |
13 | error_page 404 /index.html;
14 |
15 | access_log /var/log/nginx/react-app.access.log;
16 | error_log /var/log/nginx/react-app.error.log;
17 | }
18 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
5 | "skipLibCheck": true,
6 | "module": "ESNext",
7 | "moduleResolution": "bundler",
8 | "allowSyntheticDefaultImports": true,
9 | "strict": true,
10 | "noEmit": true
11 | },
12 | "include": ["vite.config.ts"]
13 | }
14 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/src/pages/Consult.tsx:
--------------------------------------------------------------------------------
1 | import { Outlet } from 'react-router-dom';
2 | import Navbar from '../components/Navbar';
3 | import Sidebar from '../components/Sidebar';
4 |
5 | function ConsultPage() {
6 | return (
7 | <>
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | >
16 | )
17 | }
18 |
19 | export default ConsultPage
20 |
--------------------------------------------------------------------------------
/back/prompt.js:
--------------------------------------------------------------------------------
1 | export default ({sector, about}) => (`
2 | You are a helpful assistant that helps teams from businesses of various sectors to brainstorm ideas for the company.
3 |
4 | The current company operates in the sector of ${sector} and the team needs to brainstorm possible ideas to describe the company\`s ${about}.
5 |
6 | The answer must be in JSON format with the key "suggestions" whose value is an array with two suggestions for the team, such as
7 | {"suggestions": ["suggestion1", "suggestion2"]}
8 | `)
9 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 |
3 | const defaultTheme = require('tailwindcss/defaultTheme')
4 |
5 | export default {
6 | content: [
7 | "./index.html",
8 | "./src/**/*.{js,ts,jsx,tsx}",
9 | ],
10 | theme: {
11 | extend: {
12 | fontFamily: {
13 | "sans": ["Poppins", ...defaultTheme.fontFamily.sans],
14 | "rubik": ["Rubik"]
15 | }
16 | },
17 | },
18 | plugins: [],
19 | fontFamily: {
20 | },
21 | }
22 |
23 |
--------------------------------------------------------------------------------
/back/certs/server.ext:
--------------------------------------------------------------------------------
1 | authorityKeyIdentifier=keyid,issuer
2 | basicConstraints=CA:FALSE
3 | keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
4 | subjectAltName = @alt_names
5 | [alt_names]
6 | DNS.1 = server # Be sure to include the domain name here because Common Name is not so commonly honoured by itself
7 | DNS.2 = bar.server # Optionally, add additional domains (I've added a subdomain here)
8 | IP.1 = 192.168.0.13 # Optionally, add an IP address (if the connection which you have planned requires it)
9 |
--------------------------------------------------------------------------------
/back/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "back",
3 | "type": "module",
4 | "version": "1.0.0",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "description": "",
13 | "dependencies": {
14 | "cookie-parser": "^1.4.6",
15 | "cors": "^2.8.5",
16 | "dotenv": "^16.4.5",
17 | "express": "^4.19.2",
18 | "js-cookie": "^3.0.5",
19 | "openai": "^4.52.0",
20 | "react-router-dom": "^6.23.1"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/back/deploy.sh:
--------------------------------------------------------------------------------
1 | LOCATION=us-east1
2 | PROJECT_ID=$(gcloud config list --format 'value(core.project)')
3 | REPOSITORY=${PROJECT_ID}
4 | IMG=mymenthorback
5 | SERVICE_NAME=mymenthorback
6 |
7 | docker build -t ${LOCATION}-docker.pkg.dev/${PROJECT_ID}/${REPOSITORY}/${IMG}:latest .
8 |
9 | docker push ${LOCATION}-docker.pkg.dev/${PROJECT_ID}/${REPOSITORY}/${IMG}:latest
10 |
11 | gcloud run deploy ${SERVICE_NAME} \
12 | --image=${LOCATION}-docker.pkg.dev/${PROJECT_ID}/${REPOSITORY}/${IMG}:latest \
13 | --region=${LOCATION} \
14 | --platform=managed \
15 | --allow-unauthenticated
16 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/deploy.sh:
--------------------------------------------------------------------------------
1 | LOCATION=us-east1
2 | PROJECT_ID=$(gcloud config list --format 'value(core.project)')
3 | REPOSITORY=${PROJECT_ID}
4 | IMG=mymenthor
5 | SERVICE_NAME=mymenthor
6 |
7 | docker build -t ${LOCATION}-docker.pkg.dev/${PROJECT_ID}/${REPOSITORY}/${IMG}:latest .
8 |
9 | docker push ${LOCATION}-docker.pkg.dev/${PROJECT_ID}/${REPOSITORY}/${IMG}:latest
10 |
11 | gcloud run deploy ${SERVICE_NAME} \
12 | --image=${LOCATION}-docker.pkg.dev/${PROJECT_ID}/${REPOSITORY}/${IMG}:latest \
13 | --region=${LOCATION} \
14 | --platform=managed \
15 | --allow-unauthenticated
16 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/src/index.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700;800;900&display=swap");
2 | @import url('https://fonts.googleapis.com/css2?family=Rubik:ital,wght@0,300..900;1,300..900&display=swap');
3 |
4 | @tailwind base;
5 | @tailwind components;
6 | @tailwind utilities;
7 |
8 | :root {
9 | /* background: linear-gradient(90deg, #e3ffe7 0%, #d9e7ff 100%); */
10 |
11 | /* background-color: #0093E9; */
12 | /* background-image: linear-gradient(160deg, #0093E9 0%, #80D0C7 100%); */
13 | }
14 |
15 | @layer base {
16 | .font-outline-2 {
17 | -webkit-text-stroke: 1px #22d3ee;
18 | }
19 | .font-outline-4 {
20 | -webkit-text-stroke: 4px black;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
5 | "target": "ES2020",
6 | "useDefineForClassFields": true,
7 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
8 | "module": "ESNext",
9 | "skipLibCheck": true,
10 |
11 | /* Bundler mode */
12 | "moduleResolution": "bundler",
13 | "allowImportingTsExtensions": true,
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "moduleDetection": "force",
17 | "noEmit": true,
18 | "jsx": "react-jsx",
19 |
20 | /* Linting */
21 | "strict": true,
22 | "noUnusedLocals": true,
23 | "noUnusedParameters": true,
24 | "noFallthroughCasesInSwitch": true
25 | },
26 | "include": ["src"]
27 | }
28 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/src/components/ProtectedRoute.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Navigate } from 'react-router-dom';
3 |
4 | interface ProtectedRouteProps {
5 | component: React.ComponentType;
6 | }
7 |
8 | const ProtectedRoute: React.FC = ({ component: Component }) => {
9 |
10 | const expectedUsername = import.meta.env.VITE_API_USERNAME;
11 |
12 | const expectedPassword = import.meta.env.VITE_API_PASSWORD;
13 |
14 | const name = localStorage.getItem('username');
15 | const password = localStorage.getItem('password');
16 |
17 | const isAuthenticated = (name === expectedUsername && password === expectedPassword);
18 |
19 | if (!isAuthenticated) {
20 | return ;
21 | }
22 | return ;
23 | };
24 |
25 | export default ProtectedRoute;
26 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom/client'
3 | import LoginPage from './pages/Login.tsx'
4 | import ConsultPage from './pages/Consult.tsx'
5 | import SwotPage from './pages/Swot.tsx'
6 | import ProtectedRoute from './components/ProtectedRoute.tsx'
7 | import './index.css'
8 | import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
9 |
10 | ReactDOM.createRoot(document.getElementById('root')!).render(
11 |
12 |
13 |
14 | } />
15 | } >
16 | } />
17 |
18 |
19 |
20 | ,
21 | )
22 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: { browser: true, es2020: true },
4 | extends: [
5 | 'eslint:recommended',
6 | 'plugin:@typescript-eslint/recommended-type-checked',
7 | 'plugin:react-hooks/recommended',
8 | 'plugin:@typescript-eslint/stylistic-type-checked',
9 | 'plugin:react/recommended',
10 | 'plugin:react/jsx-runtime'
11 | ],
12 | ignorePatterns: ['dist', '.eslintrc.cjs'],
13 | parser: '@typescript-eslint/parser',
14 | plugins: ['react-refresh'],
15 | rules: {
16 | 'react-refresh/only-export-components': [
17 | 'warn',
18 | { allowConstantExport: true },
19 | ],
20 | },
21 | parserOptions: {
22 | ecmaVersion: 'latest',
23 | sourceType: 'module',
24 | project: ['./tsconfig.json', './tsconfig.node.json'],
25 | tsconfigRootDir: __dirname,
26 | },
27 | }
28 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/src/components/Notification.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 |
3 | const Notification: React.FC<{ message: string }> = ({ message }) => {
4 | const [show, setShow] = useState(false);
5 |
6 | useEffect(() => {
7 | setShow(true);
8 |
9 | // Hide the notification after 5 seconds
10 | const timer = setTimeout(() => {
11 | setShow(false);
12 | }, 5000);
13 |
14 | return () => clearTimeout(timer);
15 | }, []);
16 |
17 | return (
18 |
23 | {message}
24 |
25 |
26 | );
27 | };
28 |
29 | export default Notification;
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # experiment-react-gpt
2 |
3 | ## Front
4 |
5 | ### Develop
6 |
7 | In a terminal, simply go to `front/mymentor-gpt/` and run `npm run dev`. It expects to find a `.env` file, make sure to use `.env.template`
8 | as a reference. The username and password should match what the backend sees as correct.
9 |
10 | ### Deploy
11 |
12 | Just run `./deploy.sh`. It expects to already have `gcloud init` executed. Also the artifact registry repository is already expected to be available.
13 | For deploying on cloud run use the file `.env.production`.
14 |
15 | ## Back
16 |
17 | ### Develop
18 |
19 | Go to `back` and then run `node server.js`. It also expects to have the files `.env` properly setup. Use `env.template` as reference. Notice the
20 | username and password must be the same as from the `front` setting.
21 |
22 |
23 | ### Deploy
24 |
25 | Run `./deploy.sh`. For deploying on cloud run use the file `.env.production`.
26 |
--------------------------------------------------------------------------------
/back/certs/server.csr:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE REQUEST-----
2 | MIICijCCAXICAQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx
3 | ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcN
4 | AQEBBQADggEPADCCAQoCggEBAKt9YQSO8NS0Mxp43xZD1HYwxLFDtFWWTWqG6MX+
5 | zyDl3zF/lkqDLu7TjQdNnnW6cB28wrT05kIB23FuMkVLEbf6OR7OXURC8kVg3fOb
6 | XhV9/4oMxQbZgakL2scxgkvxJQDH04fju/VCPd/IK2eKiuY3i2YcB7AS4w6VbERV
7 | zrLfba8ml9mLC2glYWqWV9hmrUH9MHscPnFcocq9zfENoKQw48IP7s+Wzs4/+ZVe
8 | cJclG2200b3JdG1DEUBIxkhWCuBDSeDz/w2xXbQrEEeNTTI/WMqexKDtPO2BC1Po
9 | VpPMnYvVOr9vUNf1HT9YuyvZvdl9mouCbS+hE1clb9yaK1cCAwEAAaAAMA0GCSqG
10 | SIb3DQEBCwUAA4IBAQAx4b7S9plJwIOUHolbt7zlxT8T0bMM7LsF2bbjMr3z926a
11 | ouBG76S+dHwCqsu/mceYSVZxjRF0L9WdxXkdAzplPd8/La+FePb2tiZK6X7cO6Gd
12 | VVlwjCsF/Gz4ztn2Ht6HNvIKszJBj1a6xrTCRnh1p7JttwPzPsfGuloeR6y8qjTw
13 | UUyoiyI7dlzNbf9u8Kh4fwdNGDBQ0Ll4N19A3zGmBPEm9eF+t874P8XJA1Q9zbmF
14 | jyCaBLLZq9TXqHRwjdSZpDZH5hn+S4z+2s1WoeZsE/LIVG+nG7AlBrkYxZEfwV/D
15 | uOpejAfFZBLmoGTCdtH0AnCwPTUFgGTd6rDu6OgX
16 | -----END CERTIFICATE REQUEST-----
17 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/src/assets/loading.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 willfuks
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mymentor-gpt",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc -b && vite build",
9 | "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "js-cookie": "^3.0.5",
14 | "react": "^18.3.1",
15 | "react-dom": "^18.3.1",
16 | "react-icons": "^5.2.1",
17 | "react-router-dom": "^6.23.1"
18 | },
19 | "devDependencies": {
20 | "@types/js-cookie": "^3.0.6",
21 | "@types/node": "^20.14.7",
22 | "@types/react": "^18.3.3",
23 | "@types/react-dom": "^18.3.0",
24 | "@typescript-eslint/eslint-plugin": "^7.13.1",
25 | "@typescript-eslint/parser": "^7.13.1",
26 | "@vitejs/plugin-react-swc": "^3.5.0",
27 | "autoprefixer": "^10.4.19",
28 | "eslint": "^8.57.0",
29 | "eslint-plugin-react": "^7.34.3",
30 | "eslint-plugin-react-hooks": "^4.6.2",
31 | "eslint-plugin-react-refresh": "^0.4.7",
32 | "postcss": "^8.4.38",
33 | "tailwindcss": "^3.4.4",
34 | "typescript": "^5.2.2",
35 | "vite": "^5.3.1"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/src/components/Navbar.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import Modal from './Modal';
3 | import { TbLogout } from "react-icons/tb";
4 | import { useLocation } from 'react-router-dom';
5 |
6 | const Navbar: React.FC = () => {
7 | const [isModalOpen, setIsModalOpen] = useState(false);
8 |
9 | const handleOpenModal = () => {
10 | setIsModalOpen(true);
11 | };
12 |
13 | const location = useLocation();
14 | const pathSegments = location.pathname.split('/');
15 | const lastSegment = pathSegments[pathSegments.length - 1] || '';
16 |
17 | return (
18 |
31 | );
32 | };
33 |
34 | export default Navbar;
35 |
--------------------------------------------------------------------------------
/back/certs/myCA.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDazCCAlOgAwIBAgIUf8RNGe8uiGWB2DB8UnVsLhwSQkcwDQYJKoZIhvcNAQEL
3 | BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
4 | GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yNDA2MjIxNTEzMjlaFw0yNjA5
5 | MjUxNTEzMjlaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
6 | HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB
7 | AQUAA4IBDwAwggEKAoIBAQCaCHobTBFwRvy+qkMZtxdUJcVXWBxNQKEbFLM2Umj5
8 | ac269KAz831NCcsTnMkVij0rM3qpGXJhJdUD5/j8RDpHlkkUc9/i3fx08hrFZ5pG
9 | OTgrFLvtA+DtnfavYIzMhwZWx312B5QtDTGWV/+YrU6gQiELzsIJRwbut0BXyEKQ
10 | UOqCfFFuujnr/cM4svte/YHTFJ3dTYizruVEm9ljN6EZVmM6vh1GoXzSpqmsv1Ii
11 | txZdvvFobO/vrYIxMwskemrPIsRkR7+ZLrknus6i+0Kwo4BJQy7pWqh8XLCZhTR1
12 | UqbFcX/6Cf357XOgSliufUYJQgeXGkwP6d8rivgw4QaTAgMBAAGjUzBRMB0GA1Ud
13 | DgQWBBSTT4jVnZkQh3yTSjfcOYWKy8NvsDAfBgNVHSMEGDAWgBSTT4jVnZkQh3yT
14 | SjfcOYWKy8NvsDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAd
15 | pyUYpAH54o68p9fhrs17x98xHzeaoz9yYTxGxI0GCSx9JTDrNxLF37MJ0IwL994H
16 | 78NQSZZ6DeVh7+8yOlTl/9eM9FDYbTiGbc5K+mLLgPLsz+ydcZo4E8OZDjnKPrMl
17 | mXMZep/UWDMrNRfHHCiCMUdzIfP2ZOgkA7obrMpU4RLdCUuMlSzmhZnFkmKBV3sQ
18 | 1V1Y6fvydv63tQ6BhdrDEWfLQj18Ylj9Bh70LAT3v5xG8IHVxL8OHPQhrE8swoVy
19 | GJagRI2SLyHLaA3vrT+jFbDj9j+OHphxym39GYlTj/l1JxSE5kmr6+wpUu0d+c6Z
20 | I0VuIr5iaWejAyOL9hWZ
21 | -----END CERTIFICATE-----
22 |
--------------------------------------------------------------------------------
/back/certs/generate_certs.sh:
--------------------------------------------------------------------------------
1 | ######################
2 | # Become a Certificate Authority
3 | ######################
4 |
5 | # Generate private key
6 | openssl genrsa -des3 -out myCA.key 2048
7 | # Generate root certificate
8 | openssl req -x509 -new -nodes -key myCA.key -sha256 -days 825 -out myCA.pem
9 |
10 | ######################
11 | # Create CA-signed certs
12 | ######################
13 |
14 | NAME=server
15 | # Generate a private key
16 | openssl genrsa -out $NAME.key 2048
17 | # Create a certificate-signing request
18 | openssl req -new -key $NAME.key -out $NAME.csr
19 | # Create a config file for the extensions
20 | >$NAME.ext cat <<-EOF
21 | authorityKeyIdentifier=keyid,issuer
22 | basicConstraints=CA:FALSE
23 | keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
24 | subjectAltName = @alt_names
25 | [alt_names]
26 | DNS.1 = $NAME # Be sure to include the domain name here because Common Name is not so commonly honoured by itself
27 | DNS.2 = bar.$NAME # Optionally, add additional domains (I've added a subdomain here)
28 | IP.1 = 192.168.0.13 # Optionally, add an IP address (if the connection which you have planned requires it)
29 | EOF
30 | # Create the signed certificate
31 | openssl x509 -req -in $NAME.csr -CA myCA.pem -CAkey myCA.key -CAcreateserial \
32 | -out $NAME.crt -days 825 -sha256 -extfile $NAME.ext
33 |
--------------------------------------------------------------------------------
/back/certs/server.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDeDCCAmCgAwIBAgIUFHDYI6KACiW03d86GVqlzrUKDeEwDQYJKoZIhvcNAQEL
3 | BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
4 | GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yNDA2MjIxNTEzNDlaFw0yNjA5
5 | MjUxNTEzNDlaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
6 | HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB
7 | AQUAA4IBDwAwggEKAoIBAQCrfWEEjvDUtDMaeN8WQ9R2MMSxQ7RVlk1qhujF/s8g
8 | 5d8xf5ZKgy7u040HTZ51unAdvMK09OZCAdtxbjJFSxG3+jkezl1EQvJFYN3zm14V
9 | ff+KDMUG2YGpC9rHMYJL8SUAx9OH47v1Qj3fyCtniormN4tmHAewEuMOlWxEVc6y
10 | 322vJpfZiwtoJWFqllfYZq1B/TB7HD5xXKHKvc3xDaCkMOPCD+7Pls7OP/mVXnCX
11 | JRtttNG9yXRtQxFASMZIVgrgQ0ng8/8NsV20KxBHjU0yP1jKnsSg7TztgQtT6FaT
12 | zJ2L1Tq/b1DX9R0/WLsr2b3ZfZqLgm0voRNXJW/cmitXAgMBAAGjYDBeMB8GA1Ud
13 | IwQYMBaAFJNPiNWdmRCHfJNKN9w5hYrLw2+wMAkGA1UdEwQCMAAwCwYDVR0PBAQD
14 | AgTwMCMGA1UdEQQcMBqCBnNlcnZlcoIKYmFyLnNlcnZlcocEwKgADTANBgkqhkiG
15 | 9w0BAQsFAAOCAQEAACS0uujRE3+FZ4UBEwgD2vAN7zLvXz1uJYUyoD+wrrHF7Qfh
16 | 1LLWzXI0e9rALViHqOFJd/fY0rDv770Cp/AYvOUX451pYZ15WvN2zAajJUu/PYJ0
17 | Y0K9byMH+Ekx/sQcZvXJ9Ss5oatWiGjKunrJSywgJBUnRV8+L8HvDrOxw6sj4xXP
18 | Zal0mzk2UkQOckVWjRwsHm5/SAKISlaRHvnghZgKvNlcFFL1OxN74lNbo9ab0GP2
19 | tPlCVpeN1rawfNcb3LL2M2omNuiRRvBrHk8x9GEWDIIuaUCCZ4KdwhUT4OKFIjC0
20 | OHDt24TRARd6A5JGSTCsvgChfWkdruTWEyxY5g==
21 | -----END CERTIFICATE-----
22 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/src/components/Modal.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { useNavigate } from 'react-router-dom';
3 | import { FiX, FiCheck } from 'react-icons/fi';
4 |
5 | interface ModalProps {
6 | setIsModalOpen: React.Dispatch>;
7 | }
8 |
9 | const Modal: React.FC = ({ setIsModalOpen }) => {
10 | const navigate = useNavigate();
11 |
12 | const handleCancel = () => {
13 | setIsModalOpen(false);
14 | };
15 |
16 | const handleOk = () => {
17 | localStorage.removeItem('username');
18 | localStorage.removeItem('password');
19 | document.cookie = 'username=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
20 | document.cookie = 'password=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
21 | navigate('/');
22 | };
23 |
24 | return (
25 |
26 |
27 |
Confirm logout?
28 |
29 |
36 |
43 |
44 |
45 |
46 | );
47 | };
48 |
49 | export default Modal;
50 |
--------------------------------------------------------------------------------
/back/certs/server.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEogIBAAKCAQEAq31hBI7w1LQzGnjfFkPUdjDEsUO0VZZNaoboxf7PIOXfMX+W
3 | SoMu7tONB02edbpwHbzCtPTmQgHbcW4yRUsRt/o5Hs5dRELyRWDd85teFX3/igzF
4 | BtmBqQvaxzGCS/ElAMfTh+O79UI938grZ4qK5jeLZhwHsBLjDpVsRFXOst9tryaX
5 | 2YsLaCVhapZX2GatQf0wexw+cVyhyr3N8Q2gpDDjwg/uz5bOzj/5lV5wlyUbbbTR
6 | vcl0bUMRQEjGSFYK4ENJ4PP/DbFdtCsQR41NMj9Yyp7EoO087YELU+hWk8ydi9U6
7 | v29Q1/UdP1i7K9m92X2ai4JtL6ETVyVv3JorVwIDAQABAoIBADTxg2dN3go9C93r
8 | XSxZiplmmwMDHQSjX4k411pxPW8xqMN2WWbtsyqmg06y5u3/vidgJFiLlx7fxejy
9 | FXERKQo8pS/elCrD5FoI+tz/pX9LI/5xzM49jmsrLsL6hPh/HWZtSuAULe4dIk8Z
10 | VFUmD5XdphrDIph4bEMPXJqIR0UvdbhtVo3XUbYEkLhf/7KG3lSrhCYftR8KzwdJ
11 | LDjNODRPn0HALAYqp2li4aLWh8n+YFPgbOXpqQVuoJr6JGBjjrrABOoOPqVxvVet
12 | 5Kr0agSB4ts0FkVpsjkv5Q1EqI0WzpKYBGwmPZWA/gVtjOLYfmlSl/IVg3amuK8Z
13 | WjUBmXECgYEA4ybw4kgw8IFEBS76IB/2BMnwh5HaBS3whj4r54IRrHwoodFsXxMY
14 | MgaEUrMKi0iv/13e0Rw9HmDjgIzecEqvqPIpeAkQwXehINSr47nIVFo3wkA7rBCW
15 | amYavsJd+BgPEFYwDvm6KCJn9ZuJCjFI2+6X7iXM1lGAiohiATs+pokCgYEAwUTF
16 | Tca45DASdKcy5YKIaKezeVRNLX/nEI2ELaSGPx3F8Cla5oQk3DhGL1VP+meFKWT9
17 | tYvXiAZhYwExr41FOMRtJ2lw7Zmz1qw2ewB21Hf460lafHZgXfZF15fbmd19aD8J
18 | 4q0XB71gRPnXezm8TY43gczSex5S82U6Riznyt8CgYB6coNnd4LqIsSIBsrOhmwY
19 | KMOAUR81q438z4bbRUJBuKwujrXcim6AiQLLkbgdXRGClxeFobNQrOn2YfmGjrwi
20 | VmgETN67a8Fv8TS3jW5wCjIEhJumJUrwEBpaumvtUQrNw6gkannvKJzhyPYWiHq+
21 | E9/SgI3q+gRQqTQrdcRQAQKBgFsUcrstjJKVCQ2KghThCDHx3kWucdSgcx884e60
22 | m0OBX3fHtXvvCIPzzTefR9qlEH8qhdoZtg/3mcuTk3u84sNW5m3tZffDOJpRfDdJ
23 | R7bndxpC7m67RrzhQ5bPjQEc/W20T49QrQrLt2OqLl93HQOboxL7mLHG36aurODH
24 | ZtEXAoGAH50jVU6j408gjLLYCcyBp25NJzyAyR+TX369XDtb6jQ1A6s4cV8cbuSJ
25 | kkJHPwXDB8GXJpK7ZR4lV1yjwsC1qvHZQw+1fm1SsRNAj7Xjj5evtsr5Dwtbj7KO
26 | D8yqv+sYZzmOR35BoPciefgsKujsQvMQCXLVIX6qwBTHEqeLvxc=
27 | -----END RSA PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/src/pages/Swot.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | import InputSuggest from '../components/InputSuggest';
3 | import { GiOpenTreasureChest } from "react-icons/gi";
4 | import { MdOutlineCenterFocusWeak } from "react-icons/md";
5 | import { GiBiceps } from "react-icons/gi";
6 | import { GrThreats } from "react-icons/gr";
7 |
8 |
9 | function SwotPage() {
10 |
11 | const [sector, setSector] = useState('');
12 |
13 | const handleChange = (event: React.ChangeEvent): void => {
14 | setSector(event.target.value);
15 | };
16 |
17 | const data = [
18 | ['SWOT: Strength', ],
19 | ['SWOT: Weakness', ],
20 | ['SWOT: Opportunities', ],
21 | ['SWOT: Threats', ]
22 | ]
23 |
24 | return (
25 |
26 |
27 |
28 |
32 |
40 |
BrainStorm
41 |
42 | {data.map((e) => (
43 |
49 | ))}
50 |
51 |
52 |
53 |
54 |
55 | );
56 | }
57 |
58 | export default SwotPage
59 |
--------------------------------------------------------------------------------
/back/certs/myCA.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | Proc-Type: 4,ENCRYPTED
3 | DEK-Info: DES-EDE3-CBC,0EB4F38B5F610B6C
4 |
5 | ltx475pWH3rOtYLjltfTph5KdVCMiAOddAj0wCA5VSRwgCN6o6wz8KdWQ8PHn1qz
6 | BlqRgYQOGarKyQpNl+lUXVaEIf4o9zDdMXhYViV7l9XC2JvCXGXYAzn6/Ss79RM9
7 | Oi4jR4yYBQPAXSXH8pQJiOWu4ay31Q4zHy0AGg4PNNfpVWZqmAo35RMJXegakrV3
8 | TK7RTk3ZAa0x8SP89Gbqvu0thqKuF39iKB3HqErwLt+829g8jZ8YX4YZlclfyO5w
9 | d6H70DEViNPWuoA0Z0arwfwyxlQiaxcOHbbT1n2+uQ+B74nKhGNsDsfHR37BCE8n
10 | Vm7SnAzkIyqJyHGK0OHei4zSspcId3exXXCFFe6UKoa/lnpd5tnPb3M7BjfaY8Uf
11 | zv7tQRWaLqSB+S9AosyqoXZC6H6S07IE5HI23wEaVIkiGAsino/+LFyL84EFfJY8
12 | yf1GbSd4ZhkhkxU4wehg77er9X0zOb6SrWr1MDFllbe3EUKDaMtTpAPENbDFez0G
13 | MffVm0qCoFyjgwbb0/wqjlPyaXRSob6d7mh+cP1vuo9/lIvpyWcsjztENx+cozVg
14 | dvwfZXBPKYzMPMHp+2x8YUz55mov3T36bXnKz2OIQ93btyuquM7S14ikawHoaY7g
15 | XA2Ycv4U/xQg3r/UDbuqeCE65tgSQNWDDoauYzAsQ0pv2LiUyLm64Ou/gK8/gx+k
16 | jELdNJFcx3g7UHKXxwxTtKOm43gdwkXdBhFmpIZN03TXtZ8AUSI1SYpidTdm0iPM
17 | dzA7DJSGeaObvAGEjFwUwpVrOMCi964XTJ3dVTjooUZLwT9BOcTj4OozjAODIAxb
18 | dCznSWDY/hgz9wIkSIJWCZtltOrnPzElAKElrge94nFTKQh4eTKv8CDy/a5IbuEs
19 | hulUUUxktzLl6A0VmlzBfOZcTPXzmAqALUWfgM9ZyGq+I8rEwCgQuGNWvVv+Lko2
20 | 7fLzn6XKi72GHvUsb162Z3vxgFOmGxDl4X0U9lLeslfmST+ckjyN3GCtTw+vIPxD
21 | JGbOc9mgI9y6ZB8GiOScZrdWzOwT4jA6sglGO2mr3SutbEyPZZo8ClV0jgYBfBRu
22 | XGdekI4ZowD4XrrfImepC5k0RUmeJUL9pIv6sJquC6TAsI0pBS41PRbudW1aN3w9
23 | 9JhvXSi+/1Az5QBYaLT65aTdMlUA4Pvq8x2yzdCD607a7S+IGg/DvHzkc07FlFl0
24 | WTw1WtHeKm8gakOczwoKV5V5kn0Feb0NFIxfVnbEHCsy1HYnqYn0vxFxAZlAcBWX
25 | bvFJzsMSTNB2G7bGToGCnkh2KU4wDVZMLkaRiWp0I2sg/IAcRIcaZ6K53Rj0bCds
26 | 6wAltmM3uXamnsS4dfAnzb005VJcxtXzzO9rb+Lman+1HizzZdNWUWPQluuh4Q4O
27 | KlMoeOJH3dffVabFSBMPGIW7vicm5aprsYUr4dZkB6IjU2fI9xmJe5H3lMr/RWK5
28 | otOgKIdMUkp86h2wohA2uzfCkLv2k36bqD1CPTl7kXU3pboqZJIs8X/PphGBfW5X
29 | 3186rON3H3FyX6C51OMXx9VEVF0Ln0PSFBP/3HMR5W0C+pVePqF3iKFn4SHeFpd4
30 | -----END RSA PRIVATE KEY-----
31 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/src/components/Sidebar.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | import { FaBars, FaTimes } from 'react-icons/fa';
3 | import { Link } from 'react-router-dom';
4 | import { AiOutlinePartition } from "react-icons/ai";
5 |
6 | const Sidebar = () => {
7 | const [isSidebarOpen, setIsSidebarOpen] = useState(false);
8 | const [activeItem, setActiveItem] = useState('slot');
9 |
10 | const toggleSidebar = () => {
11 | setIsSidebarOpen(!isSidebarOpen);
12 | };
13 |
14 | const handleMenuItemClick = (item: string) => () => {
15 | setIsSidebarOpen(false);
16 | setActiveItem(item);
17 | }
18 |
19 | return (
20 |
21 | {!isSidebarOpen &&
22 |
}
28 |
33 |
34 |
40 |
41 |
Menu
42 |
43 | -
44 |
49 |
50 |
SWOT
51 |
52 |
53 |
54 |
55 |
56 |
57 | {isSidebarOpen && (
58 |
62 | )}
63 |
64 | );
65 | };
66 |
67 | export default Sidebar;
68 |
--------------------------------------------------------------------------------
/back/server.js:
--------------------------------------------------------------------------------
1 | import express from 'express';
2 | import cookieParser from 'cookie-parser';
3 | import cors from 'cors';
4 | import dotenv from 'dotenv';
5 | import fs from 'fs';
6 | import https from 'https';
7 | import path from 'path';
8 | import { fileURLToPath } from 'url';
9 | import OpenAI from 'openai';
10 | import templatePrompt from './prompt.js';
11 |
12 |
13 | const __filename = fileURLToPath(import.meta.url);
14 | const __dirname = path.dirname(__filename);
15 |
16 | const mode = process.env.NODE_ENV || 'development';
17 | const envFile = mode === 'production' ? '.env.production' : '.env';
18 | dotenv.config({ path: path.resolve(__dirname, envFile) });
19 |
20 | const app = express();
21 |
22 | app.use(express.json());
23 | app.use(express.urlencoded({ extended: true }));
24 | app.use(cookieParser());
25 |
26 | const corsOptions = {
27 | origin: process.env.CLIENTURL,
28 | credentials: true
29 | }
30 |
31 | app.use(cors(corsOptions));
32 | app.options('*', cors(corsOptions));
33 |
34 | const validUsername = process.env.NAME;
35 | const validPassword = process.env.PASSWORD;
36 |
37 | const openai = new OpenAI({
38 | apiKey: process.env['OPENAI_KEY'],
39 | timeout: 20 * 1000, // 20 seconds
40 | });
41 |
42 | function readTemplateFromFile(filePath) {
43 | try {
44 | const template = fs.readFileSync(filePath, 'utf8');
45 | return template;
46 | } catch (err) {
47 | console.error('Error reading template file:', err);
48 | return null;
49 | }
50 | }
51 |
52 | const checkCookies = (req, res, next) => {
53 | const expectedCookieName1 = 'username';
54 | const expectedCookieValue1 = validUsername;
55 |
56 | const expectedCookieName2 = 'password';
57 | const expectedCookieValue2 = validPassword;
58 |
59 | if (
60 | req.cookies[expectedCookieName1] === expectedCookieValue1 &&
61 | req.cookies[expectedCookieName2] === expectedCookieValue2
62 | ) {
63 | return next();
64 | }
65 | return res.status(403).json({ message: 'Forbidden: Invalid or missing cookies' });
66 | };
67 |
68 | app.post('/login', (req, res) => {
69 | const { name, password } = req.body;
70 |
71 | if (name === validUsername && password === validPassword) {
72 | res.cookie('username', name, { httpOnly: false, secure: true, maxAge: 36000000, sameSite: 'None' });
73 | res.cookie('password', password, { httpOnly: false, secure: true, maxAge: 36000000, sameSite: 'None' });
74 | return res.status(200).json({ message: 'Login successful' });
75 | }
76 | res.status(401).json({ message: 'Invalid credentials' });
77 | });
78 |
79 | app.post('/suggest', checkCookies, async (req, res) => {
80 | try {
81 | const { sector, about } = req.body;
82 | const prompt = templatePrompt({sector, about});
83 |
84 | const response = await openai.chat.completions.create({
85 | messages: [{ role: 'user', content: prompt}],
86 | model: 'gpt-3.5-turbo-1106',
87 | temperature: 1,
88 | response_format: {"type": "json_object"},
89 | });
90 |
91 | const json_resp = JSON.parse(response.choices[0].message.content);
92 | return res.status(200).json(json_resp );
93 |
94 | // const mock = {
95 | // "suggestions": [
96 | // "Exploring new marketing strategies to reach a wider audience",
97 | // "Developing innovative products to stay ahead of competitors in the market"
98 | // ]
99 | // }
100 | // return res.status(200).json(mock);
101 | } catch (error){
102 | res.status(500).json({ message: error});
103 | }
104 | });
105 |
106 | // const options = {
107 | // key: fs.readFileSync(path.resolve(__dirname, './certs/server.key')),
108 | // cert: fs.readFileSync(path.resolve(__dirname, './certs/server.crt'))
109 | // };
110 |
111 | const PORT = process.env.PORT || 8080;
112 | // const server = https.createServer(options, app)
113 | // server.listen(PORT, () => {
114 | // console.log(`HTTPS Server is running on port ${PORT}`);
115 | // });
116 |
117 | app.listen(PORT, () => {
118 | console.log(`Server running on port ${PORT}`);
119 | });
120 |
121 |
122 | process.on('SIGINT', () => {
123 | console.log('SIGINT received: shutting down gracefully');
124 | server.close(() => {
125 | console.log('Server closed');
126 | process.exit(0);
127 | });
128 | });
129 |
130 | process.on('SIGTERM', () => {
131 | console.log('SIGTERM received: shutting down gracefully');
132 | server.close(() => {
133 | console.log('Server closed');
134 | process.exit(0);
135 | });
136 | });
137 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/src/pages/Login.tsx:
--------------------------------------------------------------------------------
1 | import { useState, FormEventHandler, useEffect } from 'react';
2 | import { FaCompass } from "react-icons/fa6";
3 | import { useNavigate, useLocation } from 'react-router-dom';
4 | import Notification from '../components/Notification';
5 |
6 |
7 | const APIURL = import.meta.env.VITE_API_URL;
8 |
9 | function LoginPage() {
10 |
11 | const location = useLocation();
12 | const [showNotification, setShowNotification] = useState(false);
13 | const [name, setName] = useState('');
14 | const [password, setPassword] = useState('');
15 | const [error, setError] = useState('');
16 | const [loading, setLoading] = useState(false);
17 |
18 | const navigate = useNavigate();
19 |
20 | useEffect(() => {
21 | if (location.state?.from === '/protected') {
22 | setShowNotification(true);
23 |
24 | navigate(location.pathname, { replace: true, state: {} });
25 |
26 | setTimeout(() => {
27 | setShowNotification(false);
28 | }, 5000);
29 | }
30 | }, [location.state, location.pathname, navigate]);
31 |
32 |
33 | const handleSubmit: FormEventHandler = async (e) => {
34 | e.preventDefault();
35 | setError('');
36 |
37 | if (name === '' || password === '') {
38 | setError('Both fields are required.');
39 | return;
40 | }
41 | const data = {name, password};
42 |
43 | try {
44 | const response = await fetch(`${APIURL}/login`, {
45 | method: 'POST',
46 | headers: {
47 | 'Content-Type': 'application/json',
48 | },
49 | body: JSON.stringify(data),
50 | credentials: 'include',
51 | });
52 |
53 | if (!response.ok) {
54 | const errorBody = await response.json();
55 | setError(errorBody.message || 'Something went wrong');
56 | } else {
57 | const result = await response.json();
58 | localStorage.setItem('username', name);
59 | localStorage.setItem('password', password);
60 | console.log('Success:', result);
61 | navigate('/consult/swot');
62 | }
63 | } catch (error) {
64 | console.error('Error:', error);
65 | setError('Failed to login. Please try again.');
66 | } finally {
67 | setLoading(false);
68 | }
69 |
70 | };
71 |
72 |
73 | return (
74 | <>
75 |
76 | {showNotification && (
77 |
78 | )}
79 |
80 |
81 |
82 |
83 | MyMenthor
84 |
85 |
86 |
87 |
88 | Log In to your account
89 |
90 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 | >
131 | )
132 | }
133 |
134 | export default LoginPage
135 |
--------------------------------------------------------------------------------
/front/mymentor-gpt/src/components/InputSuggest.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import Notification from '../components/Notification';
3 | import { HiOutlineLightBulb } from "react-icons/hi";
4 | import { RiDeleteBin5Line } from "react-icons/ri";
5 | import { FaCheck } from "react-icons/fa";
6 | import LoadingIcon from '../assets/loading.svg';
7 |
8 |
9 | const APIURL = import.meta.env.VITE_API_URL;
10 |
11 | interface TooltipProps {
12 | classes?: string,
13 | text: string;
14 | children: React.ReactNode
15 | }
16 |
17 | const Tooltip: React.FC = ({ classes='', children, text }) => {
18 | return (
19 |
20 | {children}
21 |
22 |
23 | {text}
24 |
31 |
32 |
33 |
34 | );
35 | };
36 |
37 | const InputSuggest: React.FC<{ sector: string, about: string, icon: React.ReactNode }> = ({ sector, about, icon }) => {
38 |
39 | const [data, setData] = useState([]);
40 | const [isEmptySector, setIsEmptySector] = useState(false);
41 | const [text, setText] = useState('');
42 | const [showNotification, setShowNotification] = useState(false);
43 | const [error, setError] = useState('');
44 | const [isLoading, setIsLoading] = useState(false);
45 |
46 | const handleSuggest = (about: string) => async () => {
47 | if (!sector) {
48 | setIsEmptySector(true);
49 | return
50 | }
51 | try {
52 | setIsLoading(true);
53 | const response = await fetch(`${APIURL}/suggest`, {
54 | method: 'POST',
55 | headers: {
56 | 'Content-Type': 'application/json',
57 | },
58 | body: JSON.stringify({ sector, about }),
59 | credentials: 'include',
60 | });
61 |
62 | if (!response.ok) {
63 | const errorBody = await response.json();
64 | console.log('errorBody ', errorBody.message);
65 | setIsLoading(false);
66 | setError(errorBody.message || 'Something went wrong');
67 | setShowNotification(true)
68 | } else {
69 | setIsLoading(false);
70 | const data = await response.json();
71 | console.log('Success:', data);
72 | setData(data['suggestions']);
73 | }
74 | } catch (error) {
75 | console.error('And the Error is:', error);
76 | setIsLoading(false);
77 | setError(JSON.stringify(error) || 'Something went wrong');
78 | setShowNotification(true)
79 | }
80 | };
81 |
82 | const handleChange = (event: React.ChangeEvent) => {
83 | setText(event.target.value);
84 | };
85 |
86 | const handleDeleteClick = (i: number) => () => {
87 | setData(data.filter((_, index) => index !== i));
88 | };
89 |
90 | const handleSelectClick = (i:number) => () => {
91 | setText(data[i]);
92 | handleDeleteClick(i)();
93 | };
94 |
95 | return (
96 |
97 | {showNotification && (
98 |
99 | )}
100 | {isEmptySector && (
101 |
102 | )}
103 |
107 |
108 |
{about}
109 | { icon }
110 |
111 |
117 | { data && (
118 |
119 | {data.map((suggestion: string, index: number) => (
120 |
121 |
{suggestion}
122 |
123 |
127 |
135 |
136 |
137 |
138 |
146 |
147 |
148 |
149 | ))}
150 |
151 | )}
152 |
165 |
166 |
167 | )
168 |
169 | };
170 |
171 | export default InputSuggest;
172 |
--------------------------------------------------------------------------------
/back/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "back",
3 | "version": "1.0.0",
4 | "lockfileVersion": 3,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "back",
9 | "version": "1.0.0",
10 | "license": "ISC",
11 | "dependencies": {
12 | "cookie-parser": "^1.4.6",
13 | "cors": "^2.8.5",
14 | "dotenv": "^16.4.5",
15 | "express": "^4.19.2",
16 | "js-cookie": "^3.0.5",
17 | "openai": "^4.52.0",
18 | "react-router-dom": "^6.23.1"
19 | }
20 | },
21 | "node_modules/@remix-run/router": {
22 | "version": "1.16.1",
23 | "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.16.1.tgz",
24 | "integrity": "sha512-es2g3dq6Nb07iFxGk5GuHN20RwBZOsuDQN7izWIisUcv9r+d2C5jQxqmgkdebXgReWfiyUabcki6Fg77mSNrig==",
25 | "license": "MIT",
26 | "engines": {
27 | "node": ">=14.0.0"
28 | }
29 | },
30 | "node_modules/@types/node": {
31 | "version": "18.19.39",
32 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz",
33 | "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==",
34 | "license": "MIT",
35 | "dependencies": {
36 | "undici-types": "~5.26.4"
37 | }
38 | },
39 | "node_modules/@types/node-fetch": {
40 | "version": "2.6.11",
41 | "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz",
42 | "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==",
43 | "license": "MIT",
44 | "dependencies": {
45 | "@types/node": "*",
46 | "form-data": "^4.0.0"
47 | }
48 | },
49 | "node_modules/abort-controller": {
50 | "version": "3.0.0",
51 | "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
52 | "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
53 | "license": "MIT",
54 | "dependencies": {
55 | "event-target-shim": "^5.0.0"
56 | },
57 | "engines": {
58 | "node": ">=6.5"
59 | }
60 | },
61 | "node_modules/accepts": {
62 | "version": "1.3.8",
63 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
64 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
65 | "license": "MIT",
66 | "dependencies": {
67 | "mime-types": "~2.1.34",
68 | "negotiator": "0.6.3"
69 | },
70 | "engines": {
71 | "node": ">= 0.6"
72 | }
73 | },
74 | "node_modules/agentkeepalive": {
75 | "version": "4.5.0",
76 | "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz",
77 | "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==",
78 | "license": "MIT",
79 | "dependencies": {
80 | "humanize-ms": "^1.2.1"
81 | },
82 | "engines": {
83 | "node": ">= 8.0.0"
84 | }
85 | },
86 | "node_modules/array-flatten": {
87 | "version": "1.1.1",
88 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
89 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
90 | "license": "MIT"
91 | },
92 | "node_modules/asynckit": {
93 | "version": "0.4.0",
94 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
95 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
96 | "license": "MIT"
97 | },
98 | "node_modules/body-parser": {
99 | "version": "1.20.2",
100 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
101 | "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
102 | "license": "MIT",
103 | "dependencies": {
104 | "bytes": "3.1.2",
105 | "content-type": "~1.0.5",
106 | "debug": "2.6.9",
107 | "depd": "2.0.0",
108 | "destroy": "1.2.0",
109 | "http-errors": "2.0.0",
110 | "iconv-lite": "0.4.24",
111 | "on-finished": "2.4.1",
112 | "qs": "6.11.0",
113 | "raw-body": "2.5.2",
114 | "type-is": "~1.6.18",
115 | "unpipe": "1.0.0"
116 | },
117 | "engines": {
118 | "node": ">= 0.8",
119 | "npm": "1.2.8000 || >= 1.4.16"
120 | }
121 | },
122 | "node_modules/bytes": {
123 | "version": "3.1.2",
124 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
125 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
126 | "license": "MIT",
127 | "engines": {
128 | "node": ">= 0.8"
129 | }
130 | },
131 | "node_modules/call-bind": {
132 | "version": "1.0.7",
133 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
134 | "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
135 | "license": "MIT",
136 | "dependencies": {
137 | "es-define-property": "^1.0.0",
138 | "es-errors": "^1.3.0",
139 | "function-bind": "^1.1.2",
140 | "get-intrinsic": "^1.2.4",
141 | "set-function-length": "^1.2.1"
142 | },
143 | "engines": {
144 | "node": ">= 0.4"
145 | },
146 | "funding": {
147 | "url": "https://github.com/sponsors/ljharb"
148 | }
149 | },
150 | "node_modules/combined-stream": {
151 | "version": "1.0.8",
152 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
153 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
154 | "license": "MIT",
155 | "dependencies": {
156 | "delayed-stream": "~1.0.0"
157 | },
158 | "engines": {
159 | "node": ">= 0.8"
160 | }
161 | },
162 | "node_modules/content-disposition": {
163 | "version": "0.5.4",
164 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
165 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
166 | "license": "MIT",
167 | "dependencies": {
168 | "safe-buffer": "5.2.1"
169 | },
170 | "engines": {
171 | "node": ">= 0.6"
172 | }
173 | },
174 | "node_modules/content-type": {
175 | "version": "1.0.5",
176 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
177 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
178 | "license": "MIT",
179 | "engines": {
180 | "node": ">= 0.6"
181 | }
182 | },
183 | "node_modules/cookie": {
184 | "version": "0.6.0",
185 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
186 | "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
187 | "license": "MIT",
188 | "engines": {
189 | "node": ">= 0.6"
190 | }
191 | },
192 | "node_modules/cookie-parser": {
193 | "version": "1.4.6",
194 | "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz",
195 | "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==",
196 | "license": "MIT",
197 | "dependencies": {
198 | "cookie": "0.4.1",
199 | "cookie-signature": "1.0.6"
200 | },
201 | "engines": {
202 | "node": ">= 0.8.0"
203 | }
204 | },
205 | "node_modules/cookie-parser/node_modules/cookie": {
206 | "version": "0.4.1",
207 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
208 | "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==",
209 | "license": "MIT",
210 | "engines": {
211 | "node": ">= 0.6"
212 | }
213 | },
214 | "node_modules/cookie-signature": {
215 | "version": "1.0.6",
216 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
217 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
218 | "license": "MIT"
219 | },
220 | "node_modules/cors": {
221 | "version": "2.8.5",
222 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
223 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
224 | "license": "MIT",
225 | "dependencies": {
226 | "object-assign": "^4",
227 | "vary": "^1"
228 | },
229 | "engines": {
230 | "node": ">= 0.10"
231 | }
232 | },
233 | "node_modules/debug": {
234 | "version": "2.6.9",
235 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
236 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
237 | "license": "MIT",
238 | "dependencies": {
239 | "ms": "2.0.0"
240 | }
241 | },
242 | "node_modules/define-data-property": {
243 | "version": "1.1.4",
244 | "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
245 | "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
246 | "license": "MIT",
247 | "dependencies": {
248 | "es-define-property": "^1.0.0",
249 | "es-errors": "^1.3.0",
250 | "gopd": "^1.0.1"
251 | },
252 | "engines": {
253 | "node": ">= 0.4"
254 | },
255 | "funding": {
256 | "url": "https://github.com/sponsors/ljharb"
257 | }
258 | },
259 | "node_modules/delayed-stream": {
260 | "version": "1.0.0",
261 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
262 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
263 | "license": "MIT",
264 | "engines": {
265 | "node": ">=0.4.0"
266 | }
267 | },
268 | "node_modules/depd": {
269 | "version": "2.0.0",
270 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
271 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
272 | "license": "MIT",
273 | "engines": {
274 | "node": ">= 0.8"
275 | }
276 | },
277 | "node_modules/destroy": {
278 | "version": "1.2.0",
279 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
280 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
281 | "license": "MIT",
282 | "engines": {
283 | "node": ">= 0.8",
284 | "npm": "1.2.8000 || >= 1.4.16"
285 | }
286 | },
287 | "node_modules/dotenv": {
288 | "version": "16.4.5",
289 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
290 | "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
291 | "license": "BSD-2-Clause",
292 | "engines": {
293 | "node": ">=12"
294 | },
295 | "funding": {
296 | "url": "https://dotenvx.com"
297 | }
298 | },
299 | "node_modules/ee-first": {
300 | "version": "1.1.1",
301 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
302 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
303 | "license": "MIT"
304 | },
305 | "node_modules/encodeurl": {
306 | "version": "1.0.2",
307 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
308 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
309 | "license": "MIT",
310 | "engines": {
311 | "node": ">= 0.8"
312 | }
313 | },
314 | "node_modules/es-define-property": {
315 | "version": "1.0.0",
316 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
317 | "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
318 | "license": "MIT",
319 | "dependencies": {
320 | "get-intrinsic": "^1.2.4"
321 | },
322 | "engines": {
323 | "node": ">= 0.4"
324 | }
325 | },
326 | "node_modules/es-errors": {
327 | "version": "1.3.0",
328 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
329 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
330 | "license": "MIT",
331 | "engines": {
332 | "node": ">= 0.4"
333 | }
334 | },
335 | "node_modules/escape-html": {
336 | "version": "1.0.3",
337 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
338 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
339 | "license": "MIT"
340 | },
341 | "node_modules/etag": {
342 | "version": "1.8.1",
343 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
344 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
345 | "license": "MIT",
346 | "engines": {
347 | "node": ">= 0.6"
348 | }
349 | },
350 | "node_modules/event-target-shim": {
351 | "version": "5.0.1",
352 | "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
353 | "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
354 | "license": "MIT",
355 | "engines": {
356 | "node": ">=6"
357 | }
358 | },
359 | "node_modules/express": {
360 | "version": "4.19.2",
361 | "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
362 | "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
363 | "license": "MIT",
364 | "dependencies": {
365 | "accepts": "~1.3.8",
366 | "array-flatten": "1.1.1",
367 | "body-parser": "1.20.2",
368 | "content-disposition": "0.5.4",
369 | "content-type": "~1.0.4",
370 | "cookie": "0.6.0",
371 | "cookie-signature": "1.0.6",
372 | "debug": "2.6.9",
373 | "depd": "2.0.0",
374 | "encodeurl": "~1.0.2",
375 | "escape-html": "~1.0.3",
376 | "etag": "~1.8.1",
377 | "finalhandler": "1.2.0",
378 | "fresh": "0.5.2",
379 | "http-errors": "2.0.0",
380 | "merge-descriptors": "1.0.1",
381 | "methods": "~1.1.2",
382 | "on-finished": "2.4.1",
383 | "parseurl": "~1.3.3",
384 | "path-to-regexp": "0.1.7",
385 | "proxy-addr": "~2.0.7",
386 | "qs": "6.11.0",
387 | "range-parser": "~1.2.1",
388 | "safe-buffer": "5.2.1",
389 | "send": "0.18.0",
390 | "serve-static": "1.15.0",
391 | "setprototypeof": "1.2.0",
392 | "statuses": "2.0.1",
393 | "type-is": "~1.6.18",
394 | "utils-merge": "1.0.1",
395 | "vary": "~1.1.2"
396 | },
397 | "engines": {
398 | "node": ">= 0.10.0"
399 | }
400 | },
401 | "node_modules/finalhandler": {
402 | "version": "1.2.0",
403 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
404 | "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
405 | "license": "MIT",
406 | "dependencies": {
407 | "debug": "2.6.9",
408 | "encodeurl": "~1.0.2",
409 | "escape-html": "~1.0.3",
410 | "on-finished": "2.4.1",
411 | "parseurl": "~1.3.3",
412 | "statuses": "2.0.1",
413 | "unpipe": "~1.0.0"
414 | },
415 | "engines": {
416 | "node": ">= 0.8"
417 | }
418 | },
419 | "node_modules/form-data": {
420 | "version": "4.0.0",
421 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
422 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
423 | "license": "MIT",
424 | "dependencies": {
425 | "asynckit": "^0.4.0",
426 | "combined-stream": "^1.0.8",
427 | "mime-types": "^2.1.12"
428 | },
429 | "engines": {
430 | "node": ">= 6"
431 | }
432 | },
433 | "node_modules/form-data-encoder": {
434 | "version": "1.7.2",
435 | "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz",
436 | "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==",
437 | "license": "MIT"
438 | },
439 | "node_modules/formdata-node": {
440 | "version": "4.4.1",
441 | "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz",
442 | "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==",
443 | "license": "MIT",
444 | "dependencies": {
445 | "node-domexception": "1.0.0",
446 | "web-streams-polyfill": "4.0.0-beta.3"
447 | },
448 | "engines": {
449 | "node": ">= 12.20"
450 | }
451 | },
452 | "node_modules/formdata-node/node_modules/web-streams-polyfill": {
453 | "version": "4.0.0-beta.3",
454 | "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz",
455 | "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==",
456 | "license": "MIT",
457 | "engines": {
458 | "node": ">= 14"
459 | }
460 | },
461 | "node_modules/forwarded": {
462 | "version": "0.2.0",
463 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
464 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
465 | "license": "MIT",
466 | "engines": {
467 | "node": ">= 0.6"
468 | }
469 | },
470 | "node_modules/fresh": {
471 | "version": "0.5.2",
472 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
473 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
474 | "license": "MIT",
475 | "engines": {
476 | "node": ">= 0.6"
477 | }
478 | },
479 | "node_modules/function-bind": {
480 | "version": "1.1.2",
481 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
482 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
483 | "license": "MIT",
484 | "funding": {
485 | "url": "https://github.com/sponsors/ljharb"
486 | }
487 | },
488 | "node_modules/get-intrinsic": {
489 | "version": "1.2.4",
490 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
491 | "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
492 | "license": "MIT",
493 | "dependencies": {
494 | "es-errors": "^1.3.0",
495 | "function-bind": "^1.1.2",
496 | "has-proto": "^1.0.1",
497 | "has-symbols": "^1.0.3",
498 | "hasown": "^2.0.0"
499 | },
500 | "engines": {
501 | "node": ">= 0.4"
502 | },
503 | "funding": {
504 | "url": "https://github.com/sponsors/ljharb"
505 | }
506 | },
507 | "node_modules/gopd": {
508 | "version": "1.0.1",
509 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
510 | "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
511 | "license": "MIT",
512 | "dependencies": {
513 | "get-intrinsic": "^1.1.3"
514 | },
515 | "funding": {
516 | "url": "https://github.com/sponsors/ljharb"
517 | }
518 | },
519 | "node_modules/has-property-descriptors": {
520 | "version": "1.0.2",
521 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
522 | "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
523 | "license": "MIT",
524 | "dependencies": {
525 | "es-define-property": "^1.0.0"
526 | },
527 | "funding": {
528 | "url": "https://github.com/sponsors/ljharb"
529 | }
530 | },
531 | "node_modules/has-proto": {
532 | "version": "1.0.3",
533 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
534 | "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
535 | "license": "MIT",
536 | "engines": {
537 | "node": ">= 0.4"
538 | },
539 | "funding": {
540 | "url": "https://github.com/sponsors/ljharb"
541 | }
542 | },
543 | "node_modules/has-symbols": {
544 | "version": "1.0.3",
545 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
546 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
547 | "license": "MIT",
548 | "engines": {
549 | "node": ">= 0.4"
550 | },
551 | "funding": {
552 | "url": "https://github.com/sponsors/ljharb"
553 | }
554 | },
555 | "node_modules/hasown": {
556 | "version": "2.0.2",
557 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
558 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
559 | "license": "MIT",
560 | "dependencies": {
561 | "function-bind": "^1.1.2"
562 | },
563 | "engines": {
564 | "node": ">= 0.4"
565 | }
566 | },
567 | "node_modules/http-errors": {
568 | "version": "2.0.0",
569 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
570 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
571 | "license": "MIT",
572 | "dependencies": {
573 | "depd": "2.0.0",
574 | "inherits": "2.0.4",
575 | "setprototypeof": "1.2.0",
576 | "statuses": "2.0.1",
577 | "toidentifier": "1.0.1"
578 | },
579 | "engines": {
580 | "node": ">= 0.8"
581 | }
582 | },
583 | "node_modules/humanize-ms": {
584 | "version": "1.2.1",
585 | "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
586 | "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
587 | "license": "MIT",
588 | "dependencies": {
589 | "ms": "^2.0.0"
590 | }
591 | },
592 | "node_modules/iconv-lite": {
593 | "version": "0.4.24",
594 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
595 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
596 | "license": "MIT",
597 | "dependencies": {
598 | "safer-buffer": ">= 2.1.2 < 3"
599 | },
600 | "engines": {
601 | "node": ">=0.10.0"
602 | }
603 | },
604 | "node_modules/inherits": {
605 | "version": "2.0.4",
606 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
607 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
608 | "license": "ISC"
609 | },
610 | "node_modules/ipaddr.js": {
611 | "version": "1.9.1",
612 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
613 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
614 | "license": "MIT",
615 | "engines": {
616 | "node": ">= 0.10"
617 | }
618 | },
619 | "node_modules/js-cookie": {
620 | "version": "3.0.5",
621 | "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz",
622 | "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==",
623 | "license": "MIT",
624 | "engines": {
625 | "node": ">=14"
626 | }
627 | },
628 | "node_modules/js-tokens": {
629 | "version": "4.0.0",
630 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
631 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
632 | "license": "MIT",
633 | "peer": true
634 | },
635 | "node_modules/loose-envify": {
636 | "version": "1.4.0",
637 | "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
638 | "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
639 | "license": "MIT",
640 | "peer": true,
641 | "dependencies": {
642 | "js-tokens": "^3.0.0 || ^4.0.0"
643 | },
644 | "bin": {
645 | "loose-envify": "cli.js"
646 | }
647 | },
648 | "node_modules/media-typer": {
649 | "version": "0.3.0",
650 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
651 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
652 | "license": "MIT",
653 | "engines": {
654 | "node": ">= 0.6"
655 | }
656 | },
657 | "node_modules/merge-descriptors": {
658 | "version": "1.0.1",
659 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
660 | "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==",
661 | "license": "MIT"
662 | },
663 | "node_modules/methods": {
664 | "version": "1.1.2",
665 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
666 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
667 | "license": "MIT",
668 | "engines": {
669 | "node": ">= 0.6"
670 | }
671 | },
672 | "node_modules/mime": {
673 | "version": "1.6.0",
674 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
675 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
676 | "license": "MIT",
677 | "bin": {
678 | "mime": "cli.js"
679 | },
680 | "engines": {
681 | "node": ">=4"
682 | }
683 | },
684 | "node_modules/mime-db": {
685 | "version": "1.52.0",
686 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
687 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
688 | "license": "MIT",
689 | "engines": {
690 | "node": ">= 0.6"
691 | }
692 | },
693 | "node_modules/mime-types": {
694 | "version": "2.1.35",
695 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
696 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
697 | "license": "MIT",
698 | "dependencies": {
699 | "mime-db": "1.52.0"
700 | },
701 | "engines": {
702 | "node": ">= 0.6"
703 | }
704 | },
705 | "node_modules/ms": {
706 | "version": "2.0.0",
707 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
708 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
709 | "license": "MIT"
710 | },
711 | "node_modules/negotiator": {
712 | "version": "0.6.3",
713 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
714 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
715 | "license": "MIT",
716 | "engines": {
717 | "node": ">= 0.6"
718 | }
719 | },
720 | "node_modules/node-domexception": {
721 | "version": "1.0.0",
722 | "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
723 | "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
724 | "funding": [
725 | {
726 | "type": "github",
727 | "url": "https://github.com/sponsors/jimmywarting"
728 | },
729 | {
730 | "type": "github",
731 | "url": "https://paypal.me/jimmywarting"
732 | }
733 | ],
734 | "license": "MIT",
735 | "engines": {
736 | "node": ">=10.5.0"
737 | }
738 | },
739 | "node_modules/node-fetch": {
740 | "version": "2.7.0",
741 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
742 | "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
743 | "license": "MIT",
744 | "dependencies": {
745 | "whatwg-url": "^5.0.0"
746 | },
747 | "engines": {
748 | "node": "4.x || >=6.0.0"
749 | },
750 | "peerDependencies": {
751 | "encoding": "^0.1.0"
752 | },
753 | "peerDependenciesMeta": {
754 | "encoding": {
755 | "optional": true
756 | }
757 | }
758 | },
759 | "node_modules/object-assign": {
760 | "version": "4.1.1",
761 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
762 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
763 | "license": "MIT",
764 | "engines": {
765 | "node": ">=0.10.0"
766 | }
767 | },
768 | "node_modules/object-inspect": {
769 | "version": "1.13.2",
770 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz",
771 | "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==",
772 | "license": "MIT",
773 | "engines": {
774 | "node": ">= 0.4"
775 | },
776 | "funding": {
777 | "url": "https://github.com/sponsors/ljharb"
778 | }
779 | },
780 | "node_modules/on-finished": {
781 | "version": "2.4.1",
782 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
783 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
784 | "license": "MIT",
785 | "dependencies": {
786 | "ee-first": "1.1.1"
787 | },
788 | "engines": {
789 | "node": ">= 0.8"
790 | }
791 | },
792 | "node_modules/openai": {
793 | "version": "4.52.0",
794 | "resolved": "https://registry.npmjs.org/openai/-/openai-4.52.0.tgz",
795 | "integrity": "sha512-xmiNcdA9QJ5wffHpZDpIsge6AsPTETJ6h5iqDNuFQ7qGSNtonHn8Qe0VHy4UwLE8rBWiSqh4j+iSvuYZSeKkPg==",
796 | "license": "Apache-2.0",
797 | "dependencies": {
798 | "@types/node": "^18.11.18",
799 | "@types/node-fetch": "^2.6.4",
800 | "abort-controller": "^3.0.0",
801 | "agentkeepalive": "^4.2.1",
802 | "form-data-encoder": "1.7.2",
803 | "formdata-node": "^4.3.2",
804 | "node-fetch": "^2.6.7",
805 | "web-streams-polyfill": "^3.2.1"
806 | },
807 | "bin": {
808 | "openai": "bin/cli"
809 | }
810 | },
811 | "node_modules/parseurl": {
812 | "version": "1.3.3",
813 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
814 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
815 | "license": "MIT",
816 | "engines": {
817 | "node": ">= 0.8"
818 | }
819 | },
820 | "node_modules/path-to-regexp": {
821 | "version": "0.1.7",
822 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
823 | "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==",
824 | "license": "MIT"
825 | },
826 | "node_modules/proxy-addr": {
827 | "version": "2.0.7",
828 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
829 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
830 | "license": "MIT",
831 | "dependencies": {
832 | "forwarded": "0.2.0",
833 | "ipaddr.js": "1.9.1"
834 | },
835 | "engines": {
836 | "node": ">= 0.10"
837 | }
838 | },
839 | "node_modules/qs": {
840 | "version": "6.11.0",
841 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
842 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
843 | "license": "BSD-3-Clause",
844 | "dependencies": {
845 | "side-channel": "^1.0.4"
846 | },
847 | "engines": {
848 | "node": ">=0.6"
849 | },
850 | "funding": {
851 | "url": "https://github.com/sponsors/ljharb"
852 | }
853 | },
854 | "node_modules/range-parser": {
855 | "version": "1.2.1",
856 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
857 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
858 | "license": "MIT",
859 | "engines": {
860 | "node": ">= 0.6"
861 | }
862 | },
863 | "node_modules/raw-body": {
864 | "version": "2.5.2",
865 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
866 | "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
867 | "license": "MIT",
868 | "dependencies": {
869 | "bytes": "3.1.2",
870 | "http-errors": "2.0.0",
871 | "iconv-lite": "0.4.24",
872 | "unpipe": "1.0.0"
873 | },
874 | "engines": {
875 | "node": ">= 0.8"
876 | }
877 | },
878 | "node_modules/react": {
879 | "version": "18.3.1",
880 | "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
881 | "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
882 | "license": "MIT",
883 | "peer": true,
884 | "dependencies": {
885 | "loose-envify": "^1.1.0"
886 | },
887 | "engines": {
888 | "node": ">=0.10.0"
889 | }
890 | },
891 | "node_modules/react-dom": {
892 | "version": "18.3.1",
893 | "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
894 | "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
895 | "license": "MIT",
896 | "peer": true,
897 | "dependencies": {
898 | "loose-envify": "^1.1.0",
899 | "scheduler": "^0.23.2"
900 | },
901 | "peerDependencies": {
902 | "react": "^18.3.1"
903 | }
904 | },
905 | "node_modules/react-router": {
906 | "version": "6.23.1",
907 | "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.23.1.tgz",
908 | "integrity": "sha512-fzcOaRF69uvqbbM7OhvQyBTFDVrrGlsFdS3AL+1KfIBtGETibHzi3FkoTRyiDJnWNc2VxrfvR+657ROHjaNjqQ==",
909 | "license": "MIT",
910 | "dependencies": {
911 | "@remix-run/router": "1.16.1"
912 | },
913 | "engines": {
914 | "node": ">=14.0.0"
915 | },
916 | "peerDependencies": {
917 | "react": ">=16.8"
918 | }
919 | },
920 | "node_modules/react-router-dom": {
921 | "version": "6.23.1",
922 | "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.23.1.tgz",
923 | "integrity": "sha512-utP+K+aSTtEdbWpC+4gxhdlPFwuEfDKq8ZrPFU65bbRJY+l706qjR7yaidBpo3MSeA/fzwbXWbKBI6ftOnP3OQ==",
924 | "license": "MIT",
925 | "dependencies": {
926 | "@remix-run/router": "1.16.1",
927 | "react-router": "6.23.1"
928 | },
929 | "engines": {
930 | "node": ">=14.0.0"
931 | },
932 | "peerDependencies": {
933 | "react": ">=16.8",
934 | "react-dom": ">=16.8"
935 | }
936 | },
937 | "node_modules/safe-buffer": {
938 | "version": "5.2.1",
939 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
940 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
941 | "funding": [
942 | {
943 | "type": "github",
944 | "url": "https://github.com/sponsors/feross"
945 | },
946 | {
947 | "type": "patreon",
948 | "url": "https://www.patreon.com/feross"
949 | },
950 | {
951 | "type": "consulting",
952 | "url": "https://feross.org/support"
953 | }
954 | ],
955 | "license": "MIT"
956 | },
957 | "node_modules/safer-buffer": {
958 | "version": "2.1.2",
959 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
960 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
961 | "license": "MIT"
962 | },
963 | "node_modules/scheduler": {
964 | "version": "0.23.2",
965 | "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
966 | "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
967 | "license": "MIT",
968 | "peer": true,
969 | "dependencies": {
970 | "loose-envify": "^1.1.0"
971 | }
972 | },
973 | "node_modules/send": {
974 | "version": "0.18.0",
975 | "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
976 | "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
977 | "license": "MIT",
978 | "dependencies": {
979 | "debug": "2.6.9",
980 | "depd": "2.0.0",
981 | "destroy": "1.2.0",
982 | "encodeurl": "~1.0.2",
983 | "escape-html": "~1.0.3",
984 | "etag": "~1.8.1",
985 | "fresh": "0.5.2",
986 | "http-errors": "2.0.0",
987 | "mime": "1.6.0",
988 | "ms": "2.1.3",
989 | "on-finished": "2.4.1",
990 | "range-parser": "~1.2.1",
991 | "statuses": "2.0.1"
992 | },
993 | "engines": {
994 | "node": ">= 0.8.0"
995 | }
996 | },
997 | "node_modules/send/node_modules/ms": {
998 | "version": "2.1.3",
999 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
1000 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
1001 | "license": "MIT"
1002 | },
1003 | "node_modules/serve-static": {
1004 | "version": "1.15.0",
1005 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
1006 | "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
1007 | "license": "MIT",
1008 | "dependencies": {
1009 | "encodeurl": "~1.0.2",
1010 | "escape-html": "~1.0.3",
1011 | "parseurl": "~1.3.3",
1012 | "send": "0.18.0"
1013 | },
1014 | "engines": {
1015 | "node": ">= 0.8.0"
1016 | }
1017 | },
1018 | "node_modules/set-function-length": {
1019 | "version": "1.2.2",
1020 | "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
1021 | "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
1022 | "license": "MIT",
1023 | "dependencies": {
1024 | "define-data-property": "^1.1.4",
1025 | "es-errors": "^1.3.0",
1026 | "function-bind": "^1.1.2",
1027 | "get-intrinsic": "^1.2.4",
1028 | "gopd": "^1.0.1",
1029 | "has-property-descriptors": "^1.0.2"
1030 | },
1031 | "engines": {
1032 | "node": ">= 0.4"
1033 | }
1034 | },
1035 | "node_modules/setprototypeof": {
1036 | "version": "1.2.0",
1037 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
1038 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
1039 | "license": "ISC"
1040 | },
1041 | "node_modules/side-channel": {
1042 | "version": "1.0.6",
1043 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
1044 | "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
1045 | "license": "MIT",
1046 | "dependencies": {
1047 | "call-bind": "^1.0.7",
1048 | "es-errors": "^1.3.0",
1049 | "get-intrinsic": "^1.2.4",
1050 | "object-inspect": "^1.13.1"
1051 | },
1052 | "engines": {
1053 | "node": ">= 0.4"
1054 | },
1055 | "funding": {
1056 | "url": "https://github.com/sponsors/ljharb"
1057 | }
1058 | },
1059 | "node_modules/statuses": {
1060 | "version": "2.0.1",
1061 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
1062 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
1063 | "license": "MIT",
1064 | "engines": {
1065 | "node": ">= 0.8"
1066 | }
1067 | },
1068 | "node_modules/toidentifier": {
1069 | "version": "1.0.1",
1070 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
1071 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
1072 | "license": "MIT",
1073 | "engines": {
1074 | "node": ">=0.6"
1075 | }
1076 | },
1077 | "node_modules/tr46": {
1078 | "version": "0.0.3",
1079 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
1080 | "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
1081 | "license": "MIT"
1082 | },
1083 | "node_modules/type-is": {
1084 | "version": "1.6.18",
1085 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
1086 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
1087 | "license": "MIT",
1088 | "dependencies": {
1089 | "media-typer": "0.3.0",
1090 | "mime-types": "~2.1.24"
1091 | },
1092 | "engines": {
1093 | "node": ">= 0.6"
1094 | }
1095 | },
1096 | "node_modules/undici-types": {
1097 | "version": "5.26.5",
1098 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
1099 | "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
1100 | "license": "MIT"
1101 | },
1102 | "node_modules/unpipe": {
1103 | "version": "1.0.0",
1104 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
1105 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
1106 | "license": "MIT",
1107 | "engines": {
1108 | "node": ">= 0.8"
1109 | }
1110 | },
1111 | "node_modules/utils-merge": {
1112 | "version": "1.0.1",
1113 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
1114 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
1115 | "license": "MIT",
1116 | "engines": {
1117 | "node": ">= 0.4.0"
1118 | }
1119 | },
1120 | "node_modules/vary": {
1121 | "version": "1.1.2",
1122 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
1123 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
1124 | "license": "MIT",
1125 | "engines": {
1126 | "node": ">= 0.8"
1127 | }
1128 | },
1129 | "node_modules/web-streams-polyfill": {
1130 | "version": "3.3.3",
1131 | "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
1132 | "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
1133 | "license": "MIT",
1134 | "engines": {
1135 | "node": ">= 8"
1136 | }
1137 | },
1138 | "node_modules/webidl-conversions": {
1139 | "version": "3.0.1",
1140 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
1141 | "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
1142 | "license": "BSD-2-Clause"
1143 | },
1144 | "node_modules/whatwg-url": {
1145 | "version": "5.0.0",
1146 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
1147 | "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
1148 | "license": "MIT",
1149 | "dependencies": {
1150 | "tr46": "~0.0.3",
1151 | "webidl-conversions": "^3.0.0"
1152 | }
1153 | }
1154 | }
1155 | }
1156 |
--------------------------------------------------------------------------------