diff --git a/packages/api/src/@core/connections/connections.controller.ts b/packages/api/src/@core/connections/connections.controller.ts new file mode 100644 index 000000000..d62418cf7 --- /dev/null +++ b/packages/api/src/@core/connections/connections.controller.ts @@ -0,0 +1,48 @@ +import { Controller, Get, Query, Res } from '@nestjs/common'; +import { Response } from 'express'; // Importing the Express Response type for type checking +import { CrmConnectionsService } from './crm/services/crm-connection.service'; +import { ProviderVertical, getProviderVertical } from '../utils/providers'; + +@Controller('connections') +export class ConnectionsController { + constructor(private readonly crmConnectionsService: CrmConnectionsService) {} + + @Get('oauth/callback') + handleCallback( + @Res() res: Response, + @Query('projectId') projectId: string, + @Query('linkedUserId') linkedUserId: string, + @Query('providerName') providerName: string, + @Query('code') code: string, + @Query('returnUrl') returnUrl: string, + @Query('accountURL') zohoAccountURL?: string, + ) { + //TODO; ADD VERIFICATION OF PARAMS + switch (getProviderVertical(providerName)) { + case ProviderVertical.CRM: + this.crmConnectionsService.handleCRMCallBack( + projectId, + linkedUserId, + providerName, + code, + zohoAccountURL, + ); + case ProviderVertical.ATS: + break; + case ProviderVertical.Accounting: + break; + case ProviderVertical.FileStorage: + break; + case ProviderVertical.HRIS: + break; + case ProviderVertical.MarketingAutomation: + break; + case ProviderVertical.Ticketing: + break; + case ProviderVertical.Unknown: + break; + } + + res.redirect(returnUrl); + } +} diff --git a/packages/api/src/@core/connections/connections.module.ts b/packages/api/src/@core/connections/connections.module.ts index f3072162d..da2fd4f3c 100644 --- a/packages/api/src/@core/connections/connections.module.ts +++ b/packages/api/src/@core/connections/connections.module.ts @@ -1,7 +1,9 @@ import { Module } from '@nestjs/common'; import { CrmConnectionModule } from './crm/crm-connection.module'; +import { ConnectionsController } from './connections.controller'; @Module({ + controllers: [ConnectionsController], imports: [CrmConnectionModule], }) export class ConnectionsModule {} diff --git a/packages/api/src/@core/connections/crm/crm-connection.controller.ts b/packages/api/src/@core/connections/crm/crm-connection.controller.ts deleted file mode 100644 index 1d1255d54..000000000 --- a/packages/api/src/@core/connections/crm/crm-connection.controller.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Controller, Get, Query, Res } from '@nestjs/common'; -import { Response } from 'express'; // Importing the Express Response type for type checking -import { CrmConnectionsService } from './services/crm-connection.service'; - -@Controller('connections/crm') -export class CrmConnectionsController { - constructor(private readonly crmConnectionsService: CrmConnectionsService) {} - - @Get('oauth/callback') - handleCRMCallback( - @Res() res: Response, - @Query('projectId') projectId: string, - @Query('linkedUserId') linkedUserId: string, - @Query('providerName') providerName: string, - @Query('returnUrl') returnUrl: string, - @Query('code') code: string, - @Query('accountURL') zohoAccountURL?: string, - ) { - //TODO; ADD VERIFICATION OF PARAMS - - this.crmConnectionsService.handleCRMCallBack( - projectId, - linkedUserId, - providerName, - code, - zohoAccountURL, - ); - res.redirect(returnUrl); - } -} diff --git a/packages/api/src/@core/connections/crm/crm-connection.module.ts b/packages/api/src/@core/connections/crm/crm-connection.module.ts index f0f29a404..5f141df48 100644 --- a/packages/api/src/@core/connections/crm/crm-connection.module.ts +++ b/packages/api/src/@core/connections/crm/crm-connection.module.ts @@ -1,5 +1,4 @@ import { Module } from '@nestjs/common'; -import { CrmConnectionsController } from './crm-connection.controller'; import { CrmConnectionsService } from './services/crm-connection.service'; import { PrismaService } from 'src/@core/prisma/prisma.service'; import { FreshsalesConnectionService } from './services/freshsales/freshsales.service'; @@ -10,7 +9,6 @@ import { ZohoConnectionService } from './services/zoho/zoho.service'; import { LoggerService } from 'src/@core/logger/logger.service'; @Module({ - controllers: [CrmConnectionsController], providers: [ CrmConnectionsService, PrismaService, diff --git a/packages/api/src/@core/utils/providers.ts b/packages/api/src/@core/utils/providers.ts new file mode 100644 index 000000000..3f9ba3a76 --- /dev/null +++ b/packages/api/src/@core/utils/providers.ts @@ -0,0 +1,48 @@ +export const CRM_PROVIDERS = [ + 'zoho', + 'zendesk', + 'hubspot', + 'pipedrive', + 'freshsales', +]; +export const HRIS_PROVIDERS = []; +export const ATS_PROVIDERS = []; +export const ACCOUNTING_PROVIDERS = []; +export const TICKETING_PROVIDERS = []; +export const MARKETING_AUTOMATION_PROVIDERS = []; +export const FILE_STORAGE_PROVIDERS = []; + +export enum ProviderVertical { + CRM = 'CRM', + HRIS = 'HRIS', + ATS = 'ATS', + Accounting = 'Accounting', + Ticketing = 'Ticketing', + MarketingAutomation = 'Marketing Automation', + FileStorage = 'File Storage', + Unknown = 'Unknown', // Used if the provider does not match any category +} +export function getProviderVertical(providerName: string): ProviderVertical { + if (CRM_PROVIDERS.includes(providerName)) { + return ProviderVertical.CRM; + } + if (HRIS_PROVIDERS.includes(providerName)) { + return ProviderVertical.HRIS; + } + if (ATS_PROVIDERS.includes(providerName)) { + return ProviderVertical.ATS; + } + if (ACCOUNTING_PROVIDERS.includes(providerName)) { + return ProviderVertical.Accounting; + } + if (TICKETING_PROVIDERS.includes(providerName)) { + return ProviderVertical.Ticketing; + } + if (MARKETING_AUTOMATION_PROVIDERS.includes(providerName)) { + return ProviderVertical.MarketingAutomation; + } + if (FILE_STORAGE_PROVIDERS.includes(providerName)) { + return ProviderVertical.FileStorage; + } + return ProviderVertical.Unknown; +} diff --git a/packages/frontend-snippet/.env.example b/packages/frontend-snippet/.env.example new file mode 100644 index 000000000..e8b645c74 --- /dev/null +++ b/packages/frontend-snippet/.env.example @@ -0,0 +1 @@ +CLIENT_ID= #hubspot client id \ No newline at end of file diff --git a/packages/frontend-snippet/.eslintrc.cjs b/packages/frontend-snippet/.eslintrc.cjs new file mode 100644 index 000000000..d6c953795 --- /dev/null +++ b/packages/frontend-snippet/.eslintrc.cjs @@ -0,0 +1,18 @@ +module.exports = { + root: true, + env: { browser: true, es2020: true }, + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:react-hooks/recommended', + ], + ignorePatterns: ['dist', '.eslintrc.cjs'], + parser: '@typescript-eslint/parser', + plugins: ['react-refresh'], + rules: { + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + }, +} diff --git a/packages/frontend-snippet/.gitignore b/packages/frontend-snippet/.gitignore new file mode 100644 index 000000000..3b0b40372 --- /dev/null +++ b/packages/frontend-snippet/.gitignore @@ -0,0 +1,26 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +.env \ No newline at end of file diff --git a/packages/frontend-snippet/README.md b/packages/frontend-snippet/README.md new file mode 100644 index 000000000..1ebe379f5 --- /dev/null +++ b/packages/frontend-snippet/README.md @@ -0,0 +1,27 @@ +# React + TypeScript + Vite + +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh + +## Expanding the ESLint configuration + +If you are developing a production application, we recommend updating the configuration to enable type aware lint rules: + +- Configure the top-level `parserOptions` property like this: + +```js + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + project: ['./tsconfig.json', './tsconfig.node.json'], + tsconfigRootDir: __dirname, + }, +``` + +- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked` +- Optionally add `plugin:@typescript-eslint/stylistic-type-checked` +- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list diff --git a/packages/frontend-snippet/index.html b/packages/frontend-snippet/index.html new file mode 100644 index 000000000..e4b78eae1 --- /dev/null +++ b/packages/frontend-snippet/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite + React + TS + + +
+ + + diff --git a/packages/frontend-snippet/package.json b/packages/frontend-snippet/package.json new file mode 100644 index 000000000..3716a6d8c --- /dev/null +++ b/packages/frontend-snippet/package.json @@ -0,0 +1,28 @@ +{ + "name": "frontend-snippet", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "preview": "vite preview" + }, + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18.2.15", + "@types/react-dom": "^18.2.7", + "@typescript-eslint/eslint-plugin": "^6.0.0", + "@typescript-eslint/parser": "^6.0.0", + "@vitejs/plugin-react": "^4.0.3", + "eslint": "^8.45.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.3", + "typescript": "^5.0.2", + "vite": "^4.4.5" + } +} diff --git a/packages/frontend-snippet/public/vite.svg b/packages/frontend-snippet/public/vite.svg new file mode 100644 index 000000000..e7b8dfb1b --- /dev/null +++ b/packages/frontend-snippet/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/frontend-snippet/src/App.css b/packages/frontend-snippet/src/App.css new file mode 100644 index 000000000..b9d355df2 --- /dev/null +++ b/packages/frontend-snippet/src/App.css @@ -0,0 +1,42 @@ +#root { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; + transition: filter 300ms; +} +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} +.logo.react:hover { + filter: drop-shadow(0 0 2em #61dafbaa); +} + +@keyframes logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +@media (prefers-reduced-motion: no-preference) { + a:nth-of-type(2) .logo { + animation: logo-spin infinite 20s linear; + } +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; +} diff --git a/packages/frontend-snippet/src/App.tsx b/packages/frontend-snippet/src/App.tsx new file mode 100644 index 000000000..b99310cf1 --- /dev/null +++ b/packages/frontend-snippet/src/App.tsx @@ -0,0 +1,28 @@ +import './App.css' +import useOAuth from './hooks/useOAuth'; + +const CLIENT_ID = import.meta.env.VITE_CLIENT_ID; // Replace with your OAuth client ID +const SCOPES = 'crm.lists.read%20crm.objects.contacts.read%20crm.objects.contacts.write%20crm.objects.custom.read%20crm.objects.custom.write%20crm.objects.companies.write%20crm.schemas.contacts.read%20crm.objects.feedback_submissions.read%20crm.lists.write%20crm.objects.companies.read%20crm.objects.deals.read%20crm.objects.deals.write%20crm.schemas.contacts.write'; // Replace with your requested scopes +const REDIRECT_URI = 'http://localhost:3000/oauth/callback'; // Replace with your redirect URI + +function App() { + const { open, isReady } = useOAuth({ + linkToken: 'ADD_GENERATED_LINK_TOKEN', // Replace with your link token + clientId: CLIENT_ID!, + scopes: SCOPES, + redirectUri: REDIRECT_URI, + onSuccess: () => console.log('OAuth successful') + }); + return ( + <> +

Integrations Flow

+
+ +
+ + ) +} + +export default App diff --git a/packages/frontend-snippet/src/assets/react.svg b/packages/frontend-snippet/src/assets/react.svg new file mode 100644 index 000000000..6c87de9bb --- /dev/null +++ b/packages/frontend-snippet/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/frontend-snippet/src/hooks/useOAuth.ts b/packages/frontend-snippet/src/hooks/useOAuth.ts new file mode 100644 index 000000000..409c126cf --- /dev/null +++ b/packages/frontend-snippet/src/hooks/useOAuth.ts @@ -0,0 +1,33 @@ +import { useState, useEffect } from 'react'; + +type UseOAuthProps = { + linkToken: string; + clientId: string; // Your OAuth client ID + scopes: string; // The scopes you are requesting + redirectUri: string; // The redirect URI registered with the OAuth provider + onSuccess: () => void; +}; + +const useOAuth = ({ linkToken, clientId, scopes, redirectUri, onSuccess }: UseOAuthProps) => { + const [isReady, setIsReady] = useState(false); + + useEffect(() => { + // Perform any setup logic here + setTimeout(() => setIsReady(true), 1000); // Simulating async operation + }, []); + + const openModal = () => { + //const authUrl = `https://app-eu1.hubspot.com/oauth/authorize?client_id=${encodeURIComponent(clientId)}&scope=${encodeURIComponent(scopes)}&redirect_uri=${encodeURIComponent(redirectUri)}`; + const authUrl = `https://app-eu1.hubspot.com/oauth/authorize?client_id=${clientId}&redirect_uri=http://localhost:3000/oauth/callback&scope=crm.lists.read%20crm.lists.write` + const width = 600, height = 600; + const left = (window.innerWidth - width) / 2; + const top = (window.innerHeight - height) / 2; + window.open(authUrl, 'OAuth', `width=${width},height=${height},top=${top},left=${left}`); + + // Call the onSuccess function here if needed, or after the OAuth flow is completed + }; + + return { open: openModal, isReady }; +}; + +export default useOAuth; diff --git a/packages/frontend-snippet/src/index.css b/packages/frontend-snippet/src/index.css new file mode 100644 index 000000000..2c3fac689 --- /dev/null +++ b/packages/frontend-snippet/src/index.css @@ -0,0 +1,69 @@ +:root { + font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} diff --git a/packages/frontend-snippet/src/main.tsx b/packages/frontend-snippet/src/main.tsx new file mode 100644 index 000000000..3d7150da8 --- /dev/null +++ b/packages/frontend-snippet/src/main.tsx @@ -0,0 +1,10 @@ +import React from 'react' +import ReactDOM from 'react-dom/client' +import App from './App.tsx' +import './index.css' + +ReactDOM.createRoot(document.getElementById('root')!).render( + + + , +) diff --git a/packages/frontend-snippet/src/vite-env.d.ts b/packages/frontend-snippet/src/vite-env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/packages/frontend-snippet/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/packages/frontend-snippet/tsconfig.json b/packages/frontend-snippet/tsconfig.json new file mode 100644 index 000000000..a7fc6fbf2 --- /dev/null +++ b/packages/frontend-snippet/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/packages/frontend-snippet/tsconfig.node.json b/packages/frontend-snippet/tsconfig.node.json new file mode 100644 index 000000000..42872c59f --- /dev/null +++ b/packages/frontend-snippet/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/packages/frontend-snippet/vite.config.ts b/packages/frontend-snippet/vite.config.ts new file mode 100644 index 000000000..5a33944a9 --- /dev/null +++ b/packages/frontend-snippet/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], +}) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 04b619f97..cfcd6216e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -172,6 +172,46 @@ importers: specifier: ^5.1.3 version: 5.1.3 + packages/frontend-snippet: + dependencies: + react: + specifier: ^18.2.0 + version: 18.2.0 + react-dom: + specifier: ^18.2.0 + version: 18.2.0(react@18.2.0) + devDependencies: + '@types/react': + specifier: ^18.2.15 + version: 18.2.33 + '@types/react-dom': + specifier: ^18.2.7 + version: 18.2.7 + '@typescript-eslint/eslint-plugin': + specifier: ^6.0.0 + version: 6.9.1(@typescript-eslint/parser@6.9.1)(eslint@8.52.0)(typescript@5.1.3) + '@typescript-eslint/parser': + specifier: ^6.0.0 + version: 6.9.1(eslint@8.52.0)(typescript@5.1.3) + '@vitejs/plugin-react': + specifier: ^4.0.3 + version: 4.0.3(vite@4.4.5) + eslint: + specifier: ^8.45.0 + version: 8.52.0 + eslint-plugin-react-hooks: + specifier: ^4.6.0 + version: 4.6.0(eslint@8.52.0) + eslint-plugin-react-refresh: + specifier: ^0.4.3 + version: 0.4.3(eslint@8.52.0) + typescript: + specifier: ^5.0.2 + version: 5.1.3 + vite: + specifier: ^4.4.5 + version: 4.4.5 + packages/sdk: dependencies: axios: @@ -1435,6 +1475,26 @@ packages: '@babel/plugin-transform-react-jsx': 7.22.15(@babel/core@7.23.2) dev: false + /@babel/plugin-transform-react-jsx-self@7.23.3(@babel/core@7.23.2): + resolution: {integrity: sha512-qXRvbeKDSfwnlJnanVRp0SfuWE5DQhwQr5xtLBzp56Wabyo+4CMosF6Kfp+eOD/4FYpql64XVJ2W0pVLlJZxOQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.2 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-react-jsx-source@7.23.3(@babel/core@7.23.2): + resolution: {integrity: sha512-91RS0MDnAWDNvGC6Wio5XYkyWI39FMFO+JK9+4AlgaTH+yWwVTsw7/sn6LK0lH7c5F+TFkpv/3LfCJ1Ydwof/g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.2 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + /@babel/plugin-transform-react-jsx@7.22.15(@babel/core@7.23.2): resolution: {integrity: sha512-oKckg2eZFa8771O/5vi7XeTvmM6+O9cxZu+kanTU7tD4sin5nO/G8jGJhq8Hvt2Z0kUoEDRayuZLaUlYl8QuGA==} engines: {node: '>=6.9.0'} @@ -4204,6 +4264,12 @@ packages: /@types/range-parser@1.2.6: resolution: {integrity: sha512-+0autS93xyXizIYiyL02FCY8N+KkKPhILhcUSA276HxzreZ16kl+cmwvV2qAM/PuCCwPXzOXOWhiPcw20uSFcA==} + /@types/react-dom@18.2.7: + resolution: {integrity: sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==} + dependencies: + '@types/react': 18.2.33 + dev: true + /@types/react-router-config@5.0.9: resolution: {integrity: sha512-a7zOj9yVUtM3Ns5stoseQAAsmppNxZpXDv6tZiFV5qlRmV4W96u53on1vApBX1eRSc8mrFOiB54Hc0Pk1J8GFg==} dependencies: @@ -4402,6 +4468,35 @@ packages: - supports-color dev: true + /@typescript-eslint/eslint-plugin@6.9.1(@typescript-eslint/parser@6.9.1)(eslint@8.52.0)(typescript@5.1.3): + resolution: {integrity: sha512-w0tiiRc9I4S5XSXXrMHOWgHgxbrBn1Ro+PmiYhSg2ZVdxrAJtQgzU5o2m1BfP6UOn7Vxcc6152vFjQfmZR4xEg==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@eslint-community/regexpp': 4.10.0 + '@typescript-eslint/parser': 6.9.1(eslint@8.52.0)(typescript@5.1.3) + '@typescript-eslint/scope-manager': 6.9.1 + '@typescript-eslint/type-utils': 6.9.1(eslint@8.52.0)(typescript@5.1.3) + '@typescript-eslint/utils': 6.9.1(eslint@8.52.0)(typescript@5.1.3) + '@typescript-eslint/visitor-keys': 6.9.1 + debug: 4.3.4 + eslint: 8.52.0 + graphemer: 1.4.0 + ignore: 5.2.4 + natural-compare: 1.4.0 + semver: 7.5.4 + ts-api-utils: 1.0.3(typescript@5.1.3) + typescript: 5.1.3 + transitivePeerDependencies: + - supports-color + dev: true + /@typescript-eslint/parser@5.59.11(eslint@8.52.0)(typescript@5.1.3): resolution: {integrity: sha512-s9ZF3M+Nym6CAZEkJJeO2TFHHDsKAM3ecNkLuH4i4s8/RCPnF5JRip2GyviYkeEAcwGMJxkqG9h2dAsnA1nZpA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4464,6 +4559,27 @@ packages: - supports-color dev: true + /@typescript-eslint/parser@6.9.1(eslint@8.52.0)(typescript@5.1.3): + resolution: {integrity: sha512-C7AK2wn43GSaCUZ9do6Ksgi2g3mwFkMO3Cis96kzmgudoVaKyt62yNzJOktP0HDLb/iO2O0n2lBOzJgr6Q/cyg==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 6.9.1 + '@typescript-eslint/types': 6.9.1 + '@typescript-eslint/typescript-estree': 6.9.1(typescript@5.1.3) + '@typescript-eslint/visitor-keys': 6.9.1 + debug: 4.3.4 + eslint: 8.52.0 + typescript: 5.1.3 + transitivePeerDependencies: + - supports-color + dev: true + /@typescript-eslint/scope-manager@5.59.11: resolution: {integrity: sha512-dHFOsxoLFtrIcSj5h0QoBT/89hxQONwmn3FOQ0GOQcLOOXm+MIrS8zEAhs4tWl5MraxCY3ZJpaXQQdFMc2Tu+Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4548,6 +4664,26 @@ packages: - supports-color dev: true + /@typescript-eslint/type-utils@6.9.1(eslint@8.52.0)(typescript@5.1.3): + resolution: {integrity: sha512-eh2oHaUKCK58qIeYp19F5V5TbpM52680sB4zNSz29VBQPTWIlE/hCj5P5B1AChxECe/fmZlspAWFuRniep1Skg==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 6.9.1(typescript@5.1.3) + '@typescript-eslint/utils': 6.9.1(eslint@8.52.0)(typescript@5.1.3) + debug: 4.3.4 + eslint: 8.52.0 + ts-api-utils: 1.0.3(typescript@5.1.3) + typescript: 5.1.3 + transitivePeerDependencies: + - supports-color + dev: true + /@typescript-eslint/types@5.59.11: resolution: {integrity: sha512-epoN6R6tkvBYSc+cllrz+c2sOFWkbisJZWkOE+y3xHtvYaOE6Wk6B8e114McRJwFRjGvYdJwLXQH5c9osME/AA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4626,6 +4762,27 @@ packages: - supports-color dev: true + /@typescript-eslint/typescript-estree@6.9.1(typescript@5.1.3): + resolution: {integrity: sha512-U+mUylTHfcqeO7mLWVQ5W/tMLXqVpRv61wm9ZtfE5egz7gtnmqVIw9ryh0mgIlkKk9rZLY3UHygsBSdB9/ftyw==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 6.9.1 + '@typescript-eslint/visitor-keys': 6.9.1 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.5.4 + ts-api-utils: 1.0.3(typescript@5.1.3) + typescript: 5.1.3 + transitivePeerDependencies: + - supports-color + dev: true + /@typescript-eslint/utils@5.59.11(eslint@8.52.0)(typescript@5.1.3): resolution: {integrity: sha512-didu2rHSOMUdJThLk4aZ1Or8IcO3HzCw/ZvEjTTIfjIrcdd5cvSIwwDy2AOlE7htSNp7QIZ10fLMyRCveesMLg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4684,6 +4841,25 @@ packages: - typescript dev: true + /@typescript-eslint/utils@6.9.1(eslint@8.52.0)(typescript@5.1.3): + resolution: {integrity: sha512-L1T0A5nFdQrMVunpZgzqPL6y2wVreSyHhKGZryS6jrEN7bD9NplVAyMryUhXsQ4TWLnZmxc2ekar/lSGIlprCA==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.52.0) + '@types/json-schema': 7.0.14 + '@types/semver': 7.5.4 + '@typescript-eslint/scope-manager': 6.9.1 + '@typescript-eslint/types': 6.9.1 + '@typescript-eslint/typescript-estree': 6.9.1(typescript@5.1.3) + eslint: 8.52.0 + semver: 7.5.4 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + /@typescript-eslint/visitor-keys@5.59.11: resolution: {integrity: sha512-KGYniTGG3AMTuKF9QBD7EIrvufkB6O6uX3knP73xbKLMpH+QRPcgnCxjWXSHjMRuOxFLovljqQgQpR0c7GvjoA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4711,6 +4887,21 @@ packages: /@ungap/structured-clone@1.2.0: resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + /@vitejs/plugin-react@4.0.3(vite@4.4.5): + resolution: {integrity: sha512-pwXDog5nwwvSIzwrvYYmA2Ljcd/ZNlcsSG2Q9CNDBwnsd55UGAyr2doXtB5j+2uymRCnCfExlznzzSFbBRcoCg==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^4.2.0 + dependencies: + '@babel/core': 7.23.2 + '@babel/plugin-transform-react-jsx-self': 7.23.3(@babel/core@7.23.2) + '@babel/plugin-transform-react-jsx-source': 7.23.3(@babel/core@7.23.2) + react-refresh: 0.14.0 + vite: 4.4.5 + transitivePeerDependencies: + - supports-color + dev: true + /@webassemblyjs/ast@1.11.6: resolution: {integrity: sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==} dependencies: @@ -6940,6 +7131,23 @@ packages: prettier-linter-helpers: 1.0.0 dev: true + /eslint-plugin-react-hooks@4.6.0(eslint@8.52.0): + resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==} + engines: {node: '>=10'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 + dependencies: + eslint: 8.52.0 + dev: true + + /eslint-plugin-react-refresh@0.4.3(eslint@8.52.0): + resolution: {integrity: sha512-Hh0wv8bUNY877+sI0BlCUlsS0TYYQqvzEwJsJJPM2WF4RnTStSnSR3zdJYa2nPOJgg3UghXi54lVyMSmpCalzA==} + peerDependencies: + eslint: '>=7' + dependencies: + eslint: 8.52.0 + dev: true + /eslint-plugin-react@7.33.2(eslint@8.52.0): resolution: {integrity: sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==} engines: {node: '>=4'} @@ -9924,7 +10132,6 @@ packages: resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - dev: false /natural-compare-lite@1.4.0: resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} @@ -10971,7 +11178,6 @@ packages: nanoid: 3.3.6 picocolors: 1.0.0 source-map-js: 1.0.2 - dev: false /preferred-pm@3.1.2: resolution: {integrity: sha512-nk7dKrcW8hfCZ4H6klWcdRknBOXWzNQByJ0oJyX97BOupsYD+FzLS4hflgEu/uPUEHZCuRfMxzCBsuWd7OzT8Q==} @@ -11262,6 +11468,16 @@ packages: react: 17.0.2 scheduler: 0.20.2 + /react-dom@18.2.0(react@18.2.0): + resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} + peerDependencies: + react: ^18.2.0 + dependencies: + loose-envify: 1.4.0 + react: 18.2.0 + scheduler: 0.23.0 + dev: false + /react-error-overlay@6.0.11: resolution: {integrity: sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==} dev: false @@ -11323,6 +11539,11 @@ packages: webpack: 5.89.0 dev: false + /react-refresh@0.14.0: + resolution: {integrity: sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==} + engines: {node: '>=0.10.0'} + dev: true + /react-router-config@5.1.1(react-router@5.3.4)(react@17.0.2): resolution: {integrity: sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg==} peerDependencies: @@ -11387,6 +11608,13 @@ packages: loose-envify: 1.4.0 object-assign: 4.1.1 + /react@18.2.0: + resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} + engines: {node: '>=0.10.0'} + dependencies: + loose-envify: 1.4.0 + dev: false + /read-pkg-up@7.0.1: resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} engines: {node: '>=8'} @@ -11818,6 +12046,12 @@ packages: loose-envify: 1.4.0 object-assign: 4.1.1 + /scheduler@0.23.0: + resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} + dependencies: + loose-envify: 1.4.0 + dev: false + /schema-utils@2.7.0: resolution: {integrity: sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==} engines: {node: '>= 8.9.0'} @@ -12135,7 +12369,6 @@ packages: /source-map-js@1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} - dev: false /source-map-support@0.5.13: resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} @@ -13335,6 +13568,41 @@ packages: vfile-message: 2.0.4 dev: false + /vite@4.4.5: + resolution: {integrity: sha512-4m5kEtAWHYr0O1Fu7rZp64CfO1PsRGZlD3TAB32UmQlpd7qg15VF7ROqGN5CyqN7HFuwr7ICNM2+fDWRqFEKaA==} + engines: {node: ^14.18.0 || >=16.0.0} + hasBin: true + peerDependencies: + '@types/node': '>= 14' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + esbuild: 0.18.20 + postcss: 8.4.31 + rollup: 3.29.4 + optionalDependencies: + fsevents: 2.3.3 + dev: true + /wait-on@6.0.1: resolution: {integrity: sha512-zht+KASY3usTY5u2LgaNqn/Cd8MukxLGjdcZxT2ns5QzDmTFc4XoWBgC+C/na+sMRZTuVygQoMYwdcVjHnYIVw==} engines: {node: '>=10.0.0'}