diff --git a/.env.example b/.env.example index ad00a941..8ee4adc1 100644 --- a/.env.example +++ b/.env.example @@ -48,4 +48,4 @@ PLATFORM_OAUTH_FAILURE_REDIRECT_PATH=/oauth/failure DOMAIN=localhost FEEDBACK_FORWARD_EMAIL= -NEXT_PUBLIC_BACKEND_URL=http://localhost:4200 +BACKEND_URL=http://localhost:4200 diff --git a/.github/workflows/validate-api-client.yaml b/.github/workflows/validate-api-client.yaml new file mode 100644 index 00000000..2a323c80 --- /dev/null +++ b/.github/workflows/validate-api-client.yaml @@ -0,0 +1,62 @@ +on: + push: + branches: + - '!develop' + - '!main' + paths: + ['packages/api-client/**', '.github/workflows/validate-api-client.yaml'] + pull_request: + paths: + ['packages/api-client/**', '.github/workflows/validate-api-client.yaml'] + +jobs: + validate: + runs-on: ubuntu-latest + name: Validate API Client + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + version: 9.2.0 + run_install: false + + - name: Get pnpm store directory + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + + - uses: actions/cache@v4 + name: Setup pnpm cache + with: + path: ${{ env.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + - name: Install packages + run: | + pnpm i + + - name: Lint + run: | + pnpm run lint:api-client + + - name: Test + run: | + pnpm run test:api-client + + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v3 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + with: + flags: api-client diff --git a/.github/workflows/validate-api.yaml b/.github/workflows/validate-api.yaml index 6bd0a681..8a6b4f04 100644 --- a/.github/workflows/validate-api.yaml +++ b/.github/workflows/validate-api.yaml @@ -55,9 +55,6 @@ jobs: - name: E2E tests env: - GITHUB_CLIENT_ID: dummy - GITHUB_CLIENT_SECRET: dummy - GITHUB_CALLBACK_URL: dummy REDIS_URL: redis://localhost:6379 JWT_SECRET: secret run: pnpm run e2e:api diff --git a/.github/workflows/validate-web.yaml b/.github/workflows/validate-web.yaml index 8bd70b61..b11663f7 100644 --- a/.github/workflows/validate-web.yaml +++ b/.github/workflows/validate-web.yaml @@ -3,9 +3,19 @@ on: branches: - '!develop' - '!main' - paths: ['apps/web/**', '.github/workflows/web.yaml'] + paths: + [ + 'apps/web/**', + '.github/workflows/validate-web.yaml', + '.github/workflows/deploy-web.yaml' + ] pull_request: - paths: ['apps/web/**', '.github/workflows/web.yaml'] + paths: + [ + 'apps/web/**', + '.github/workflows/deploy-web.yaml', + '.github/workflows/validate-web.yaml' + ] jobs: validate: diff --git a/.husky/pre-commit b/.husky/pre-commit index d522362e..f1fdd725 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1,4 @@ #!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" -pnpm lint && pnpm format && pnpm test:api \ No newline at end of file +pnpm lint && pnpm format && pnpm test:api && pnpm test:api-client \ No newline at end of file diff --git a/apps/api/package.json b/apps/api/package.json index 445aa1b7..b4f083c0 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -58,19 +58,11 @@ "@types/cookie-parser": "^1.4.7", "@types/eccrypto": "^1.1.6", "@types/express": "^4.17.17", - "@types/jest": "^29.5.2", "@types/multer": "^1.4.11", - "@types/node": "^20.3.1", "@types/supertest": "^6.0.0", "@types/uuid": "^9.0.8", - "@typescript-eslint/eslint-plugin": "^6.0.0", - "@typescript-eslint/parser": "^6.0.0", "ajv": "^7", "dotenv-cli": "^7.4.2", - "eslint": "^8.42.0", - "eslint-config-prettier": "^9.0.0", - "eslint-plugin-node": "^11.1.0", - "eslint-plugin-prettier": "^5.0.0", "jest": "^29.5.0", "jest-mock-extended": "^3.0.5", "prettier": "^3.0.0", @@ -79,7 +71,6 @@ "supertest": "^6.3.3", "ts-jest": "^29.1.0", "ts-loader": "^9.4.3", - "tsconfig-paths": "^4.2.0", "typescript": "^5.1.3" }, "jest": { diff --git a/apps/api/src/feedback/feedback.e2e.spec.ts b/apps/api/src/feedback/feedback.e2e.spec.ts index cd3d0250..143001af 100644 --- a/apps/api/src/feedback/feedback.e2e.spec.ts +++ b/apps/api/src/feedback/feedback.e2e.spec.ts @@ -42,7 +42,7 @@ describe('Feedback Controller (E2E)', () => { beforeEach(async () => { user = await prisma.user.create({ data: { - email: 'john@keyshade.xyz', + email: 'johndoe@keyshade.xyz', name: 'John', isActive: true, isAdmin: false, diff --git a/apps/api/src/user/service/user.service.ts b/apps/api/src/user/service/user.service.ts index ac25b6bb..84ba3d6d 100644 --- a/apps/api/src/user/service/user.service.ts +++ b/apps/api/src/user/service/user.service.ts @@ -28,6 +28,7 @@ export class UserService { async onApplicationBootstrap() { await this.checkIfAdminExistsOrCreate() + await this.createDummyUser() } async getSelf(user: User) { @@ -294,6 +295,24 @@ export class UserService { return userWithWorkspace } + private async createDummyUser() { + // @ts-expect-error - This is a test environment + if (process.env.NODE_ENV === 'test' || process.env.NODE_ENV === 'e2e') { + this.log.log('Creating dummy user') + + const user = await this.prisma.user.create({ + data: { + email: 'johndoe@example.com', + name: 'John Doe', + isActive: true, + isOnboardingFinished: true + } + }) + + this.log.log('Created dummy user: ', user) + } + } + private async checkIfAdminExistsOrCreate() { const parsedEnv = EnvSchema.safeParse(process.env) let nodeEnv diff --git a/apps/cli/package.json b/apps/cli/package.json index 7b450a14..550a5ee2 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -5,8 +5,8 @@ "main": "index.js", "type": "commonjs", "scripts": { - "build": "npx tsc", - "watch": "npx tsc -w", + "build": "tsc", + "watch": "tsc -w", "start": "node dist/index.js" }, "keywords": [], @@ -16,13 +16,12 @@ "@clack/core": "^0.3.4", "@clack/prompts": "^0.7.0", "@types/figlet": "^1.5.8", - "@types/node": "^20.14.8", "commander": "^12.1.0", "figlet": "^1.7.0", "fs": "0.0.1-security", "nodemon": "^3.1.4", "socket.io-client": "^4.7.5", - "tsconfig-paths": "^4.2.0", "typescript": "^5.5.2" - } + }, + "devDependencies": {} } diff --git a/apps/platform/package.json b/apps/platform/package.json index 1e27c5c9..cf917e4c 100644 --- a/apps/platform/package.json +++ b/apps/platform/package.json @@ -1,65 +1,64 @@ { - "name": "platform", - "version": "1.0.0", - "private": true, - "scripts": { - "dev": "env-cmd -f ../../.env --silent next dev -p 3025", - "build": "next build", - "start": "next start", - "lint": "next lint --fix" - }, - "dependencies": { - "@radix-ui/react-accordion": "^1.2.0", - "@radix-ui/react-avatar": "^1.0.4", - "@radix-ui/react-checkbox": "^1.0.4", - "@radix-ui/react-context-menu": "^2.1.5", - "@radix-ui/react-dialog": "^1.0.5", - "@radix-ui/react-direction": "^1.0.1", - "@radix-ui/react-dropdown-menu": "^2.0.6", - "@radix-ui/react-icons": "^1.3.0", - "@radix-ui/react-label": "^2.0.2", - "@radix-ui/react-menubar": "^1.0.4", - "@radix-ui/react-popover": "^1.0.7", - "@radix-ui/react-scroll-area": "^1.0.5", - "@radix-ui/react-separator": "^1.0.3", - "@radix-ui/react-slot": "^1.0.2", - "@radix-ui/react-switch": "^1.0.3", - "@radix-ui/react-tooltip": "^1.1.2", - "@tanstack/react-table": "^8.16.0", - "avvvatars-react": "^0.4.2", - "class-variance-authority": "^0.7.0", - "clsx": "^2.1.0", - "cmdk": "^1.0.0", - "dayjs": "^1.11.11", - "env-cmd": "^10.1.0", - "framer-motion": "^11.1.7", - "geist": "^1.2.2", - "input-otp": "^1.2.4", - "jotai": "^2.8.0", - "js-cookie": "^3.0.5", - "lucide-react": "^0.340.0", - "next": "^13.5.6", - "next-themes": "^0.3.0", - "react": "^18.3.1", - "react-dom": "^18.3.1", - "sonner": "^1.4.41", - "tailwind-merge": "^2.2.2", - "tailwindcss-animate": "^1.0.7", - "zod": "^3.23.8" - }, - "devDependencies": { - "@next/eslint-plugin-next": "^13.5.6", - "@svgr/webpack": "^8.1.0", - "@tailwindcss/forms": "^0.5.7", - "@types/js-cookie": "^3.0.6", - "@types/node": "^17.0.45", - "@types/react": "^18.3.1", - "@types/react-dom": "^18.3.0", - "autoprefixer": "^10.4.16", - "eslint-config-custom": "workspace:*", - "postcss": "^8.4.31", - "tailwindcss": "^3.3.3", - "tsconfig": "workspace:*", - "typescript": "^4.5.3" - } -} \ No newline at end of file + "name": "platform", + "version": "1.0.0", + "private": true, + "scripts": { + "dev": "env-cmd -f ../../.env --silent next dev -p 3025", + "build": "next build", + "start": "next start", + "lint": "next lint --fix" + }, + "dependencies": { + "@radix-ui/react-accordion": "^1.2.0", + "@radix-ui/react-avatar": "^1.0.4", + "@radix-ui/react-checkbox": "^1.0.4", + "@radix-ui/react-context-menu": "^2.1.5", + "@radix-ui/react-dialog": "^1.0.5", + "@radix-ui/react-direction": "^1.0.1", + "@radix-ui/react-dropdown-menu": "^2.0.6", + "@radix-ui/react-icons": "^1.3.0", + "@radix-ui/react-label": "^2.0.2", + "@radix-ui/react-menubar": "^1.0.4", + "@radix-ui/react-popover": "^1.0.7", + "@radix-ui/react-scroll-area": "^1.0.5", + "@radix-ui/react-separator": "^1.0.3", + "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-switch": "^1.0.3", + "@radix-ui/react-tooltip": "^1.1.2", + "@tanstack/react-table": "^8.16.0", + "avvvatars-react": "^0.4.2", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.0", + "cmdk": "^1.0.0", + "dayjs": "^1.11.11", + "env-cmd": "^10.1.0", + "framer-motion": "^11.1.7", + "geist": "^1.2.2", + "input-otp": "^1.2.4", + "jotai": "^2.8.0", + "js-cookie": "^3.0.5", + "lucide-react": "^0.340.0", + "next": "^13.5.6", + "next-themes": "^0.3.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "sonner": "^1.4.41", + "tailwind-merge": "^2.2.2", + "tailwindcss-animate": "^1.0.7", + "zod": "^3.23.8" + }, + "devDependencies": { + "@next/eslint-plugin-next": "^13.5.6", + "@svgr/webpack": "^8.1.0", + "@tailwindcss/forms": "^0.5.7", + "@types/js-cookie": "^3.0.6", + "@types/react": "^18.3.1", + "@types/react-dom": "^18.3.0", + "autoprefixer": "^10.4.16", + "eslint-config-custom": "workspace:*", + "postcss": "^8.4.31", + "tailwindcss": "^3.3.3", + "tsconfig": "workspace:*", + "typescript": "^4.5.3" + } +} diff --git a/apps/platform/src/lib/api-functions/projects.ts b/apps/platform/src/lib/api-functions/projects.ts index 4ff53b9a..7df9c026 100644 --- a/apps/platform/src/lib/api-functions/projects.ts +++ b/apps/platform/src/lib/api-functions/projects.ts @@ -18,7 +18,7 @@ async function getProjectsbyWorkspaceID( const zProjectWithoutKeysArray = z.array(zProjectWithoutKeys) const { success, data } = zProjectWithoutKeysArray.safeParse(projectData) - + if (!success) { throw new Error('Invalid data') } diff --git a/apps/platform/src/lib/api-functions/secrets.ts b/apps/platform/src/lib/api-functions/secrets.ts index 4ac94218..5e7e2880 100644 --- a/apps/platform/src/lib/api-functions/secrets.ts +++ b/apps/platform/src/lib/api-functions/secrets.ts @@ -1,6 +1,6 @@ import { z } from 'zod' -import { apiClient } from '../api-client' import { zSecret, type Secret } from '@/types' +import { apiClient } from '../api-client' async function getAllSecretbyProjectId( projectId: string diff --git a/apps/web/package.json b/apps/web/package.json index 7d07c493..ccd603aa 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -30,8 +30,6 @@ "@next/eslint-plugin-next": "^13.4.19", "@svgr/webpack": "^8.1.0", "@tailwindcss/forms": "^0.5.7", - "@types/jest": "^29.5.2", - "@types/node": "^17.0.12", "@types/react": "^18.0.22", "@types/react-dom": "^18.0.7", "autoprefixer": "^10.4.16", diff --git a/package.json b/package.json index e5b68fb1..ca61345e 100644 --- a/package.json +++ b/package.json @@ -102,6 +102,7 @@ "lint:api": "turbo run lint --filter=api", "lint:web": "turbo run lint --filter=web", "lint:platform": "turbo run lint --filter=platform", + "lint:api-client": "pnpm run --filter=api-client lint", "build": "turbo run build", "build:api": "pnpm db:generate-types && turbo run build --filter=api", "build:web": "turbo run build --filter=web", @@ -118,13 +119,14 @@ "e2e:api": "pnpm run --filter=api e2e", "test:web": "turbo run test --filter=web", "test:platform": "turbo run test --filter=platform", + "test:api-client": "pnpm run --filter=api-client test", "db:generate-types": "pnpm run --filter=api db:generate-types", "db:generate-migrations": "pnpm run --filter=api db:generate-migrations", "db:deploy-migrations": "pnpm run --filter=api db:deploy-migrations", "db:validate": "pnpm run --filter=api db:validate", "db:format": "pnpm run --filter=api db:format", "db:reset": "pnpm run --filter=api db:reset", - "format": "prettier apps/**/*.{ts,tsx} --write", + "format": "prettier apps/**/*.{ts,tsx} packages/**/*.{ts,tsx} --write", "prepare": "husky", "sourcemaps:api": "turbo run sourcemaps --filter=api", "docker:run:web": "docker run --env-file .env --name ks-web --rm -p 3000:3000 ks-web", @@ -135,12 +137,22 @@ "devDependencies": { "@sentry/cli": "^2.28.6", "@sentry/webpack-plugin": "^2.14.2", + "@typescript-eslint/eslint-plugin": "^6.0.0", + "@typescript-eslint/parser": "^6.0.0", "cross-env": "^7.0.3", + "eslint": "^8.42.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-prettier": "^5.0.0", "husky": "^9.0.11", "prettier": "^3.0.0", "prettier-plugin-tailwindcss": "^0.5.11", "tsconfig": "workspace:*", - "turbo": "^1.12.4" + "turbo": "^1.12.4", + "@types/jest": "^29.5.2", + "jest": "^29.5.0", + "ts-jest": "^29.1.0", + "tsconfig-paths": "^4.2.0" }, "dependencies": { "@semantic-release/changelog": "^6.0.3", @@ -150,16 +162,17 @@ "@semantic-release/release-notes-generator": "^14.0.0", "@sentry/node": "^7.102.0", "@sentry/profiling-node": "^7.102.0", + "@types/node": "^20.14.10", + "chalk": "^4.1.2", "clsx": "^2.1.0", - "framer-motion": "^11.2.9", - "conventional-changelog-writer": "8.0.0", "conventional-changelog-conventionalcommits": "8.0.0", + "conventional-changelog-writer": "8.0.0", + "framer-motion": "^11.2.9", "million": "^3.0.5", + "moment": "^2.30.1", "sharp": "^0.33.3", "tailwind-merge": "^2.3.0", "ts-node": "^10.9.2", - "zod": "^3.23.6", - "chalk": "^4.1.2", - "moment": "^2.30.1" + "zod": "^3.23.6" } } diff --git a/packages/api-client/.eslintrc.js b/packages/api-client/.eslintrc.js new file mode 100644 index 00000000..ae5ee212 --- /dev/null +++ b/packages/api-client/.eslintrc.js @@ -0,0 +1,26 @@ +module.exports = { + parser: '@typescript-eslint/parser', + parserOptions: { + project: 'tsconfig.json', + tsconfigRootDir: __dirname, + sourceType: 'module' + }, + plugins: ['@typescript-eslint/eslint-plugin'], + extends: [ + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended' + ], + root: true, + env: { + node: true, + jest: true + }, + ignorePatterns: ['.eslintrc.js'], + rules: { + '@typescript-eslint/interface-name-prefix': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-unused-vars': ['warn'] + } +} diff --git a/packages/api-client/jest.config.ts b/packages/api-client/jest.config.ts new file mode 100644 index 00000000..586ee443 --- /dev/null +++ b/packages/api-client/jest.config.ts @@ -0,0 +1,20 @@ +import type { Config } from 'jest' + +const config: Config = { + displayName: 'api', + testMatch: ['**/*.spec.ts'], + transform: { + '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }] + }, + moduleFileExtensions: ['ts', 'js', 'html'], + coverageDirectory: '../../coverage/packages/api-client', + globalSetup: './tests/config/setup.ts', + globalTeardown: './tests/config/teardown.ts', + preset: 'ts-jest', + testEnvironment: 'node', + moduleNameMapper: { + '^@package/(.*)$': '/src/$1' + } +} + +export default config diff --git a/packages/api-client/package.json b/packages/api-client/package.json new file mode 100644 index 00000000..0d1f1919 --- /dev/null +++ b/packages/api-client/package.json @@ -0,0 +1,16 @@ +{ + "name": "api-client", + "version": "1.0.0", + "description": "This package holds all the API request logic", + "private": true, + "scripts": { + "build": "tsc", + "watch": "tsc -w", + "start": "node dist/index.js", + "dev": "npx tsc && node dist/index.js", + "test": "BACKEND_URL=http://localhost:4200 jest", + "lint": "eslint \"{src,tests}/**/*.ts\" --fix", + "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"" + }, + "dependencies": {} +} diff --git a/packages/api-client/src/client.ts b/packages/api-client/src/client.ts new file mode 100644 index 00000000..aa724dd1 --- /dev/null +++ b/packages/api-client/src/client.ts @@ -0,0 +1,116 @@ +interface ErrorWithResponse extends Error { + status: number + response: Record +} + +class APIClient { + private baseUrl: string + + private static instance: APIClient | null = null + + constructor(baseUrl: string) { + this.baseUrl = baseUrl + } + + static getInstance(): APIClient { + if (!this.instance) { + this.instance = new APIClient(process.env.BACKEND_URL as string) + } + return this.instance + } + + async request(url: string, options: RequestInit): Promise { + const response = await fetch(`${this.baseUrl}${url}`, options) + if (!response.ok) { + const error = new Error(response.statusText) as ErrorWithResponse + error.status = response.status + error.response = (await response.json()) as Record + throw error + } + + try { + return (await response.json()) as T + } catch (e) { + return response as T + } + } + + /** + * Sends a GET request to the specified URL and returns a Promise that resolves to the response data. + * @param url - The URL to send the GET request to. + * @returns A Promise that resolves to the response data. + */ + get(url: string, headers?: Record): Promise { + return this.request(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + ...headers + }, + credentials: 'include' + }) + } + + /** + * Sends a POST request to the specified URL with the provided data. + * + * @param url - The URL to send the request to. + * @param data - The data to send in the request body. + * @returns A Promise that resolves to the response data. + */ + post( + url: string, + data: any, + headers?: Record + ): Promise { + return this.request(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + ...headers + }, + body: JSON.stringify(data), + credentials: 'include' + }) + } + + /** + * Sends a PUT request to the specified URL with the provided data. + * + * @param url - The URL to send the request to. + * @param data - The data to be sent in the request body. + * @returns A Promise that resolves to the response data. + */ + put(url: string, data: any, headers?: Record): Promise { + return this.request(url, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + ...headers + }, + body: JSON.stringify(data), + credentials: 'include' + }) + } + + /** + * Sends a DELETE request to the specified URL and returns a Promise that resolves to the response data. + * + * @param url - The URL to send the DELETE request to. + * @returns A Promise that resolves to the response data. + */ + delete(url: string, headers?: Record): Promise { + return this.request(url, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + ...headers + }, + credentials: 'include' + }) + } +} + +const client = APIClient.getInstance() + +export default client diff --git a/packages/api-client/src/controllers/environment/environment.ts b/packages/api-client/src/controllers/environment/environment.ts new file mode 100644 index 00000000..70ec208d --- /dev/null +++ b/packages/api-client/src/controllers/environment/environment.ts @@ -0,0 +1,74 @@ +import client from '@package/client' +import { + CreateEnvironmentRequest, + CreateEnvironmentResponse, + DeleteEnvironmentRequest, + DeleteEnvironmentResponse, + GetAllEnvironmentsOfProjectRequest, + GetAllEnvironmentsOfProjectResponse, + GetEnvironmentByIdRequest, + GetEnvironmentByIdResponse, + UpdateEnvironmentRequest, + UpdateEnvironmentResponse +} from '@package/types/environment.types' + +export default class EnvironmentController { + private static apiClient = client + + static async createEnvironment( + request: CreateEnvironmentRequest, + headers?: Record + ): Promise { + return this.apiClient.post( + `/api/environment/${request.projectId}`, + request, + headers + ) + } + + static async updateEnvironment( + request: UpdateEnvironmentRequest, + headers?: Record + ): Promise { + return this.apiClient.put( + `/api/environment/${request.id}`, + request, + headers + ) + } + + static async getEnvironmentById( + request: GetEnvironmentByIdRequest, + + headers?: Record + ): Promise { + return this.apiClient.get( + `/api/environment/${request.id}`, + headers + ) + } + + static async getAllEnvironmentsOfProject( + request: GetAllEnvironmentsOfProjectRequest, + headers?: Record + ): Promise { + let url = `/api/environment/all/${request.projectId}?` + request.page && (url += `page=${request.page}&`) + request.limit && (url += `limit=${request.limit}&`) + request.sort && (url += `sort=${request.sort}&`) + request.order && (url += `order=${request.order}&`) + request.search && (url += `search=${request.search}&`) + + return this.apiClient.get(url, headers) + } + + static async deleteEnvironment( + request: DeleteEnvironmentRequest, + headers?: Record + ): Promise { + return this.apiClient.delete( + `/api/environment/${request.id}`, + headers + ) + } +} diff --git a/packages/api-client/src/index.ts b/packages/api-client/src/index.ts new file mode 100644 index 00000000..e69de29b diff --git a/packages/api-client/src/types/environment.types.d.ts b/packages/api-client/src/types/environment.types.d.ts new file mode 100644 index 00000000..14b44839 --- /dev/null +++ b/packages/api-client/src/types/environment.types.d.ts @@ -0,0 +1,76 @@ +export interface CreateEnvironmentRequest { + name: string + description?: string + projectId: string +} + +export interface CreateEnvironmentResponse { + id: string + name: string + description: string | null + createdAt: string + updatedAt: string + lastUpdatedById: string + projectId: string +} + +export interface UpdateEnvironmentRequest { + id: string + name?: string + description?: string +} + +export interface UpdateEnvironmentResponse { + id: string + name: string + description: string | null + createdAt: string + updatedAt: string + lastUpdatedById: string + projectId: string +} + +export interface GetEnvironmentByIdRequest { + id: string +} + +export interface GetEnvironmentByIdResponse { + id: string + name: string + description: string | null + createdAt: string + updatedAt: string + lastUpdatedById: string + projectId: string +} + +export interface GetAllEnvironmentsOfProjectRequest { + projectId: string + page?: number + limit?: number + sort?: string + order?: string + search?: string +} + +export interface GetAllEnvironmentsOfProjectResponse { + items: { + id: string + name: string + description: string | null + createdAt: string + updatedAt: string + lastUpdatedBy: { + id: string + name: string + email: string + profilePictureUrl: string | null + } + }[] +} + +export interface DeleteEnvironmentRequest { + id: string +} + +export interface DeleteEnvironmentResponse {} diff --git a/packages/api-client/tests/config/setup.ts b/packages/api-client/tests/config/setup.ts new file mode 100644 index 00000000..1a4e0f20 --- /dev/null +++ b/packages/api-client/tests/config/setup.ts @@ -0,0 +1,58 @@ +import { exec } from 'child_process' + +export default async function teardown() { + await executeCommand('docker compose down') + await executeCommand('docker compose -f ../../docker-compose-test.yml up -d') + await executeCommand('cd ../.. && pnpm build:api') + await executeCommand('cd ../.. && pnpm db:deploy-migrations', { + DATABASE_URL: 'postgresql://prisma:prisma@localhost:5432/tests', + PATH: process.env.PATH! + }) + await startAPI() +} + +function executeCommand( + command: string, + env?: Record +): Promise { + return new Promise((resolve, reject) => { + exec(command, { env }, (error, stdout, stderr) => { + console.log('Executing: ', command) + if (error) { + stderr && console.error('Error:', stderr) + reject(error) + } else { + stdout && console.log('Output:', stdout) + resolve() + } + }) + }) +} + +function startAPI(): Promise { + return new Promise((resolve) => { + const apiProcess = exec('cd ../../ && pnpm run start:api', { + env: { + PATH: process.env.PATH, + DATABASE_URL: 'postgresql://prisma:prisma@localhost:5432/tests', + REDIS_URL: 'redis://localhost:6379', + JWT_SECRET: 'secret', + NODE_ENV: 'e2e' + } + }) + + apiProcess.stdout?.on('data', (data) => { + console.log(data) + }) + + apiProcess.stderr?.on('data', (data) => { + console.error('API Error:', data) + }) + + console.log('Launching API...') + setTimeout(() => { + console.log('API launched') + resolve() + }, 10000) + }) +} diff --git a/packages/api-client/tests/config/teardown.ts b/packages/api-client/tests/config/teardown.ts new file mode 100644 index 00000000..c579b9c3 --- /dev/null +++ b/packages/api-client/tests/config/teardown.ts @@ -0,0 +1,21 @@ +import { exec } from 'child_process' + +export default async function teardown() { + await executeCommand('docker compose -f ../../docker-compose-test.yml down') + process.exit(0) +} + +function executeCommand(command: string): Promise { + return new Promise((resolve, reject) => { + exec(command, (error, stdout, stderr) => { + console.log('Executing: ', command) + if (error) { + console.error('Error:', stderr) + reject(error) + } else { + console.log('Output:', stdout) + resolve() + } + }) + }) +} diff --git a/packages/api-client/tests/environment.spec.ts b/packages/api-client/tests/environment.spec.ts new file mode 100644 index 00000000..be06923f --- /dev/null +++ b/packages/api-client/tests/environment.spec.ts @@ -0,0 +1,220 @@ +import client from '@package/client' +import EnvironmentController from '@package/controllers/environment/environment' + +describe('Get Environments Tests', () => { + const email = 'johndoe@example.com' + let projectId: string | null + let workspaceId: string | null + let environment: any + + beforeAll(async () => { + try { + //Create the user's workspace + const workspaceResponse = (await client.post( + '/api/workspace', + { + name: 'My Workspace' + }, + { + 'x-e2e-user-email': email + } + )) as any + + workspaceId = workspaceResponse.id + + // Create a project + const projectResponse = (await client.post( + `/api/project/${workspaceId}`, + { + name: 'Project', + storePrivateKey: true + }, + { + 'x-e2e-user-email': email + } + )) as any + + projectId = projectResponse.id + } catch (error) { + console.error(error) + process.exit(1) + } + }) + + afterAll(async () => { + try { + // Delete the workspace + await client.delete(`/api/workspace/${workspaceId}`, { + 'x-e2e-user-email': email + }) + } catch (error) { + console.error(error) + process.exit(1) + } + }) + + beforeEach(async () => { + // Create an environment + const createEnvironmentResponse = await client.post( + `/api/environment/${projectId}`, + { + name: 'Dev' + }, + { + 'x-e2e-user-email': email + } + ) + + environment = createEnvironmentResponse + }) + + afterEach(async () => { + // Delete the environment + await client.delete(`/api/environment/${environment.id}`, { + 'x-e2e-user-email': email + }) + }) + + it('should return a list of environments', async () => { + try { + const environments = + await EnvironmentController.getAllEnvironmentsOfProject( + { + projectId + }, + { + 'x-e2e-user-email': email + } + ) + + expect(environments).toHaveLength(2) + expect(environments[0].name).toBe('Default') + } catch (error) { + console.error(error) + process.exit(1) + } + }) + + it('should be able to fetch environment by ID', async () => { + try { + const environmentResponse = + await EnvironmentController.getEnvironmentById( + { + id: environment.id + }, + { + 'x-e2e-user-email': email + } + ) + + expect(environmentResponse.id).toBe(environment.id) + expect(environmentResponse.name).toBe('Dev') + } catch (error) { + console.error(error) + process.exit(1) + } + }) + + it('should be able to create an environment', async () => { + try { + const createEnvironmentResponse = + await EnvironmentController.createEnvironment( + { + projectId, + name: 'Prod' + }, + { + 'x-e2e-user-email': email + } + ) + + expect(createEnvironmentResponse.name).toBe('Prod') + + const fetchEnvironmentResponse = (await client.get( + `/api/environment/${createEnvironmentResponse.id}`, + { + 'x-e2e-user-email': email + } + )) as any + + expect(fetchEnvironmentResponse.name).toBe('Prod') + + // Delete the environment + await client.delete(`/api/environment/${createEnvironmentResponse.id}`, { + 'x-e2e-user-email': email + }) + } catch (error) { + console.error(error) + process.exit(1) + } + }) + + it('should be able to update an environment', async () => { + try { + const updateEnvironmentResponse = + await EnvironmentController.updateEnvironment( + { + id: environment.id, + name: 'Prod' + }, + { + 'x-e2e-user-email': email + } + ) + + expect(updateEnvironmentResponse.name).toBe('Prod') + + const fetchEnvironmentResponse = (await client.get( + `/api/environment/${environment.id}`, + { + 'x-e2e-user-email': email + } + )) as any + + expect(fetchEnvironmentResponse.name).toBe('Prod') + } catch (error) { + console.error(error) + process.exit(1) + } + }) + + it('should be able to delete an environment', async () => { + // Create an environment + const createEnvironmentResponse = (await client.post( + `/api/environment/${projectId}`, + { + name: 'Prod' + }, + { + 'x-e2e-user-email': email + } + )) as any + + try { + await EnvironmentController.deleteEnvironment( + { + id: createEnvironmentResponse.id + }, + { + 'x-e2e-user-email': email + } + ) + + // Check if the environment is deleted + const environments = + await EnvironmentController.getAllEnvironmentsOfProject( + { + projectId + }, + { + 'x-e2e-user-email': email + } + ) + + expect(environments).toHaveLength(2) + } catch (error) { + console.error(error) + process.exit(1) + } + }) +}) diff --git a/packages/api-client/tsconfig.json b/packages/api-client/tsconfig.json new file mode 100644 index 00000000..17ad1248 --- /dev/null +++ b/packages/api-client/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "module": "commonjs", + "declaration": true, + "removeComments": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "target": "ES2021", + "inlineSourceMap": true, + "outDir": "./dist", + "baseUrl": "./", + "incremental": true, + "skipLibCheck": true, + "strictNullChecks": false, + "noImplicitAny": false, + "strictBindCallApply": false, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "paths": { + "@package/*": ["src/*"] + } + }, + "include": ["src/**/*.ts", "tests/**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/packages/api-client/tsconfig.spec.json b/packages/api-client/tsconfig.spec.json new file mode 100644 index 00000000..44c2a6c7 --- /dev/null +++ b/packages/api-client/tsconfig.spec.json @@ -0,0 +1,14 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3afc095d..9da6f9bf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,6 +29,9 @@ importers: '@sentry/profiling-node': specifier: ^7.102.0 version: 7.118.0 + '@types/node': + specifier: ^20.14.10 + version: 20.14.10 chalk: specifier: ^4.1.2 version: 4.1.2 @@ -58,7 +61,7 @@ importers: version: 2.3.0 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@20.14.9)(typescript@5.5.3) + version: 10.9.2(@types/node@20.14.10)(typescript@5.5.3) zod: specifier: ^3.23.6 version: 3.23.8 @@ -69,21 +72,51 @@ importers: '@sentry/webpack-plugin': specifier: ^2.14.2 version: 2.20.1(webpack@5.92.1) + '@types/jest': + specifier: ^29.5.2 + version: 29.5.12 + '@typescript-eslint/eslint-plugin': + specifier: ^6.0.0 + version: 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3) + '@typescript-eslint/parser': + specifier: ^6.0.0 + version: 6.21.0(eslint@8.57.0)(typescript@5.5.3) cross-env: specifier: ^7.0.3 version: 7.0.3 + eslint: + specifier: ^8.42.0 + version: 8.57.0 + eslint-config-prettier: + specifier: ^9.0.0 + version: 9.1.0(eslint@8.57.0) + eslint-plugin-node: + specifier: ^11.1.0 + version: 11.1.0(eslint@8.57.0) + eslint-plugin-prettier: + specifier: ^5.0.0 + version: 5.1.3(@types/eslint@8.56.10)(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.3.2) husky: specifier: ^9.0.11 version: 9.0.11 + jest: + specifier: ^29.5.0 + version: 29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) prettier: specifier: ^3.0.0 version: 3.3.2 prettier-plugin-tailwindcss: specifier: ^0.5.11 version: 0.5.14(prettier@3.3.2) + ts-jest: + specifier: ^29.1.0 + version: 29.1.5(@babel/core@7.24.7)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(jest@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(typescript@5.5.3) tsconfig: specifier: workspace:* version: link:packages/tsconfig + tsconfig-paths: + specifier: ^4.2.0 + version: 4.2.0 turbo: specifier: ^1.12.4 version: 1.13.4 @@ -190,51 +223,27 @@ importers: '@types/express': specifier: ^4.17.17 version: 4.17.21 - '@types/jest': - specifier: ^29.5.2 - version: 29.5.12 '@types/multer': specifier: ^1.4.11 version: 1.4.11 - '@types/node': - specifier: ^20.3.1 - version: 20.14.9 '@types/supertest': specifier: ^6.0.0 version: 6.0.2 '@types/uuid': specifier: ^9.0.8 version: 9.0.8 - '@typescript-eslint/eslint-plugin': - specifier: ^6.0.0 - version: 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3) - '@typescript-eslint/parser': - specifier: ^6.0.0 - version: 6.21.0(eslint@8.57.0)(typescript@5.5.3) ajv: specifier: ^7 version: 7.2.4 dotenv-cli: specifier: ^7.4.2 version: 7.4.2 - eslint: - specifier: ^8.42.0 - version: 8.57.0 - eslint-config-prettier: - specifier: ^9.0.0 - version: 9.1.0(eslint@8.57.0) - eslint-plugin-node: - specifier: ^11.1.0 - version: 11.1.0(eslint@8.57.0) - eslint-plugin-prettier: - specifier: ^5.0.0 - version: 5.1.3(@types/eslint@8.56.10)(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.3.2) jest: specifier: ^29.5.0 - version: 29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)) + version: 29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) jest-mock-extended: specifier: ^3.0.5 - version: 3.0.7(jest@29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)))(typescript@5.5.3) + version: 3.0.7(jest@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(typescript@5.5.3) prettier: specifier: ^3.0.0 version: 3.3.2 @@ -252,13 +261,10 @@ importers: version: 6.3.4 ts-jest: specifier: ^29.1.0 - version: 29.1.5(@babel/core@7.24.7)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(jest@29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)))(typescript@5.5.3) + version: 29.1.5(@babel/core@7.24.7)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(jest@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(typescript@5.5.3) ts-loader: specifier: ^9.4.3 version: 9.5.1(typescript@5.5.3)(webpack@5.92.1) - tsconfig-paths: - specifier: ^4.2.0 - version: 4.2.0 typescript: specifier: ^5.1.3 version: 5.5.3 @@ -274,9 +280,6 @@ importers: '@types/figlet': specifier: ^1.5.8 version: 1.5.8 - '@types/node': - specifier: ^20.14.8 - version: 20.14.9 commander: specifier: ^12.1.0 version: 12.1.0 @@ -292,9 +295,6 @@ importers: socket.io-client: specifier: ^4.7.5 version: 4.7.5 - tsconfig-paths: - specifier: ^4.2.0 - version: 4.2.0 typescript: specifier: ^5.5.2 version: 5.5.3 @@ -408,7 +408,7 @@ importers: version: 2.3.0 tailwindcss-animate: specifier: ^1.0.7 - version: 1.0.7(tailwindcss@3.4.4(ts-node@10.9.2(@types/node@17.0.45)(typescript@4.9.5))) + version: 1.0.7(tailwindcss@3.4.4(ts-node@10.9.2(@types/node@20.14.10)(typescript@4.9.5))) zod: specifier: ^3.23.8 version: 3.23.8 @@ -421,13 +421,10 @@ importers: version: 8.1.0(typescript@4.9.5) '@tailwindcss/forms': specifier: ^0.5.7 - version: 0.5.7(tailwindcss@3.4.4(ts-node@10.9.2(@types/node@17.0.45)(typescript@4.9.5))) + version: 0.5.7(tailwindcss@3.4.4(ts-node@10.9.2(@types/node@20.14.10)(typescript@4.9.5))) '@types/js-cookie': specifier: ^3.0.6 version: 3.0.6 - '@types/node': - specifier: ^17.0.45 - version: 17.0.45 '@types/react': specifier: ^18.3.1 version: 18.3.3 @@ -445,7 +442,7 @@ importers: version: 8.4.39 tailwindcss: specifier: ^3.3.3 - version: 3.4.4(ts-node@10.9.2(@types/node@17.0.45)(typescript@4.9.5)) + version: 3.4.4(ts-node@10.9.2(@types/node@20.14.10)(typescript@4.9.5)) tsconfig: specifier: workspace:* version: link:../../packages/tsconfig @@ -512,13 +509,7 @@ importers: version: 8.1.0(typescript@4.9.5) '@tailwindcss/forms': specifier: ^0.5.7 - version: 0.5.7(tailwindcss@3.4.4(ts-node@10.9.2(@types/node@17.0.45)(typescript@4.9.5))) - '@types/jest': - specifier: ^29.5.2 - version: 29.5.12 - '@types/node': - specifier: ^17.0.12 - version: 17.0.45 + version: 0.5.7(tailwindcss@3.4.4(ts-node@10.9.2(@types/node@20.14.10)(typescript@4.9.5))) '@types/react': specifier: ^18.0.22 version: 18.3.3 @@ -536,7 +527,7 @@ importers: version: 8.4.39 tailwindcss: specifier: ^3.3.3 - version: 3.4.4(ts-node@10.9.2(@types/node@17.0.45)(typescript@4.9.5)) + version: 3.4.4(ts-node@10.9.2(@types/node@20.14.10)(typescript@4.9.5)) tsconfig: specifier: workspace:* version: link:../../packages/tsconfig @@ -544,11 +535,13 @@ importers: specifier: ^4.5.3 version: 4.9.5 + packages/api-client: {} + packages/eslint-config-custom: devDependencies: '@vercel/style-guide': specifier: ^5.0.0 - version: 5.2.0(@next/eslint-plugin-next@13.5.6)(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)))(prettier@3.3.2)(typescript@4.9.5) + version: 5.2.0(@next/eslint-plugin-next@13.5.6)(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(prettier@3.3.2)(typescript@4.9.5) eslint-config-turbo: specifier: ^1.10.12 version: 1.13.4(eslint@8.57.0) @@ -3093,11 +3086,8 @@ packages: '@types/multer@1.4.11': resolution: {integrity: sha512-svK240gr6LVWvv3YGyhLlA+6LRRWA4mnGIU7RcNmgjBYFl6665wcXrRfxGp5tEPVHUNm5FMcmq7too9bxCwX/w==} - '@types/node@17.0.45': - resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} - - '@types/node@20.14.9': - resolution: {integrity: sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg==} + '@types/node@20.14.10': + resolution: {integrity: sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -9291,27 +9281,27 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.14.10 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 slash: 3.0.0 - '@jest/core@29.7.0(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3))': + '@jest/core@29.7.0(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3))': dependencies: '@jest/console': 29.7.0 '@jest/reporters': 29.7.0 '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.14.10 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)) + jest-config: 29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -9336,7 +9326,7 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.14.10 jest-mock: 29.7.0 '@jest/expect-utils@29.7.0': @@ -9354,7 +9344,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.14.9 + '@types/node': 20.14.10 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -9376,7 +9366,7 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 20.14.9 + '@types/node': 20.14.10 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -9446,7 +9436,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.14.9 + '@types/node': 20.14.10 '@types/yargs': 17.0.32 chalk: 4.1.2 @@ -10907,10 +10897,10 @@ snapshots: dependencies: tslib: 2.6.3 - '@tailwindcss/forms@0.5.7(tailwindcss@3.4.4(ts-node@10.9.2(@types/node@17.0.45)(typescript@4.9.5)))': + '@tailwindcss/forms@0.5.7(tailwindcss@3.4.4(ts-node@10.9.2(@types/node@20.14.10)(typescript@4.9.5)))': dependencies: mini-svg-data-uri: 1.4.4 - tailwindcss: 3.4.4(ts-node@10.9.2(@types/node@17.0.45)(typescript@4.9.5)) + tailwindcss: 3.4.4(ts-node@10.9.2(@types/node@20.14.10)(typescript@4.9.5)) '@tanstack/react-table@8.19.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: @@ -11125,11 +11115,11 @@ snapshots: '@types/body-parser@1.19.5': dependencies: '@types/connect': 3.4.38 - '@types/node': 20.14.9 + '@types/node': 20.14.10 '@types/connect@3.4.38': dependencies: - '@types/node': 20.14.9 + '@types/node': 20.14.10 '@types/cookie-parser@1.4.7': dependencies: @@ -11141,7 +11131,7 @@ snapshots: '@types/cors@2.8.17': dependencies: - '@types/node': 20.14.9 + '@types/node': 20.14.10 '@types/debug@4.1.12': dependencies: @@ -11150,7 +11140,7 @@ snapshots: '@types/eccrypto@1.1.6': dependencies: '@types/expect': 1.20.4 - '@types/node': 20.14.9 + '@types/node': 20.14.10 '@types/eslint-scope@3.7.7': dependencies: @@ -11172,7 +11162,7 @@ snapshots: '@types/express-serve-static-core@4.19.5': dependencies: - '@types/node': 20.14.9 + '@types/node': 20.14.10 '@types/qs': 6.9.15 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 @@ -11188,7 +11178,7 @@ snapshots: '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 20.14.9 + '@types/node': 20.14.10 '@types/hast@3.0.4': dependencies: @@ -11219,7 +11209,7 @@ snapshots: '@types/jsonwebtoken@9.0.5': dependencies: - '@types/node': 20.14.9 + '@types/node': 20.14.10 '@types/luxon@3.4.2': {} @@ -11239,9 +11229,7 @@ snapshots: dependencies: '@types/express': 4.17.21 - '@types/node@17.0.45': {} - - '@types/node@20.14.9': + '@types/node@20.14.10': dependencies: undici-types: 5.26.5 @@ -11269,12 +11257,12 @@ snapshots: '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 - '@types/node': 20.14.9 + '@types/node': 20.14.10 '@types/serve-static@1.15.7': dependencies: '@types/http-errors': 2.0.4 - '@types/node': 20.14.9 + '@types/node': 20.14.10 '@types/send': 0.17.4 '@types/stack-utils@2.0.3': {} @@ -11283,7 +11271,7 @@ snapshots: dependencies: '@types/cookiejar': 2.1.5 '@types/methods': 1.1.4 - '@types/node': 20.14.9 + '@types/node': 20.14.10 '@types/supertest@6.0.2': dependencies: @@ -11300,7 +11288,7 @@ snapshots: '@types/ws@8.5.10': dependencies: - '@types/node': 20.14.9 + '@types/node': 20.14.10 '@types/yargs-parser@21.0.3': {} @@ -11511,7 +11499,7 @@ snapshots: '@ungap/structured-clone@1.2.0': {} - '@vercel/style-guide@5.2.0(@next/eslint-plugin-next@13.5.6)(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)))(prettier@3.3.2)(typescript@4.9.5)': + '@vercel/style-guide@5.2.0(@next/eslint-plugin-next@13.5.6)(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(prettier@3.3.2)(typescript@4.9.5)': dependencies: '@babel/core': 7.24.7 '@babel/eslint-parser': 7.24.7(@babel/core@7.24.7)(eslint@8.57.0) @@ -11523,9 +11511,9 @@ snapshots: eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@4.9.5))(eslint-plugin-import@2.29.1)(eslint@8.57.0) eslint-plugin-eslint-comments: 3.2.0(eslint@8.57.0) eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@4.9.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) - eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@4.9.5))(eslint@8.57.0)(typescript@4.9.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)))(typescript@4.9.5) + eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@4.9.5))(eslint@8.57.0)(typescript@4.9.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(typescript@4.9.5) eslint-plugin-jsx-a11y: 6.9.0(eslint@8.57.0) - eslint-plugin-playwright: 0.16.0(eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@4.9.5))(eslint@8.57.0)(typescript@4.9.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)))(typescript@4.9.5))(eslint@8.57.0) + eslint-plugin-playwright: 0.16.0(eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@4.9.5))(eslint@8.57.0)(typescript@4.9.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(typescript@4.9.5))(eslint@8.57.0) eslint-plugin-react: 7.34.3(eslint@8.57.0) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) eslint-plugin-testing-library: 6.2.2(eslint@8.57.0)(typescript@4.9.5) @@ -12444,13 +12432,13 @@ snapshots: sha.js: 2.4.11 optional: true - create-jest@29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)): + create-jest@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)) + jest-config: 29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -12750,7 +12738,7 @@ snapshots: dependencies: '@types/cookie': 0.4.1 '@types/cors': 2.8.17 - '@types/node': 20.14.9 + '@types/node': 20.14.10 accepts: 1.3.8 base64id: 2.0.0 cookie: 0.4.2 @@ -12996,13 +12984,13 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@4.9.5))(eslint@8.57.0)(typescript@4.9.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)))(typescript@4.9.5): + eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@4.9.5))(eslint@8.57.0)(typescript@4.9.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(typescript@4.9.5): dependencies: '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@4.9.5) eslint: 8.57.0 optionalDependencies: '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@4.9.5))(eslint@8.57.0)(typescript@4.9.5) - jest: 29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)) + jest: 29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) transitivePeerDependencies: - supports-color - typescript @@ -13037,11 +13025,11 @@ snapshots: resolve: 1.22.8 semver: 6.3.1 - eslint-plugin-playwright@0.16.0(eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@4.9.5))(eslint@8.57.0)(typescript@4.9.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)))(typescript@4.9.5))(eslint@8.57.0): + eslint-plugin-playwright@0.16.0(eslint-plugin-jest@27.9.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@4.9.5))(eslint@8.57.0)(typescript@4.9.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(typescript@4.9.5))(eslint@8.57.0): dependencies: eslint: 8.57.0 optionalDependencies: - eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@4.9.5))(eslint@8.57.0)(typescript@4.9.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)))(typescript@4.9.5) + eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@4.9.5))(eslint@8.57.0)(typescript@4.9.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(typescript@4.9.5) eslint-plugin-prettier@5.1.3(@types/eslint@8.56.10)(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.3.2): dependencies: @@ -14219,7 +14207,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.14.10 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.3 @@ -14239,16 +14227,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)): + jest-cli@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)) + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)) + create-jest: 29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)) + jest-config: 29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -14258,7 +14246,7 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)): + jest-config@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)): dependencies: '@babel/core': 7.24.7 '@jest/test-sequencer': 29.7.0 @@ -14283,8 +14271,8 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 20.14.9 - ts-node: 10.9.2(@types/node@20.14.9)(typescript@5.5.3) + '@types/node': 20.14.10 + ts-node: 10.9.2(@types/node@20.14.10)(typescript@5.5.3) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -14313,7 +14301,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.14.10 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -14323,7 +14311,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 20.14.9 + '@types/node': 20.14.10 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -14359,16 +14347,16 @@ snapshots: slash: 3.0.0 stack-utils: 2.0.6 - jest-mock-extended@3.0.7(jest@29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)))(typescript@5.5.3): + jest-mock-extended@3.0.7(jest@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(typescript@5.5.3): dependencies: - jest: 29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)) + jest: 29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) ts-essentials: 10.0.1(typescript@5.5.3) typescript: 5.5.3 jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.14.10 jest-util: 29.7.0 jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): @@ -14403,7 +14391,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.14.10 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -14431,7 +14419,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.14.10 chalk: 4.1.2 cjs-module-lexer: 1.3.1 collect-v8-coverage: 1.0.2 @@ -14477,7 +14465,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.14.10 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -14496,7 +14484,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.9 + '@types/node': 20.14.10 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -14505,23 +14493,23 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 20.14.9 + '@types/node': 20.14.10 merge-stream: 2.0.0 supports-color: 8.1.1 jest-worker@29.7.0: dependencies: - '@types/node': 20.14.9 + '@types/node': 20.14.10 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)): + jest@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)) + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) '@jest/types': 29.6.3 import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)) + jest-cli: 29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -15649,13 +15637,13 @@ snapshots: camelcase-css: 2.0.1 postcss: 8.4.39 - postcss-load-config@4.0.2(postcss@8.4.39)(ts-node@10.9.2(@types/node@17.0.45)(typescript@4.9.5)): + postcss-load-config@4.0.2(postcss@8.4.39)(ts-node@10.9.2(@types/node@20.14.10)(typescript@4.9.5)): dependencies: lilconfig: 3.1.2 yaml: 2.4.5 optionalDependencies: postcss: 8.4.39 - ts-node: 10.9.2(@types/node@17.0.45)(typescript@4.9.5) + ts-node: 10.9.2(@types/node@20.14.10)(typescript@4.9.5) postcss-nested@6.0.1(postcss@8.4.39): dependencies: @@ -16619,11 +16607,11 @@ snapshots: dependencies: '@babel/runtime': 7.24.7 - tailwindcss-animate@1.0.7(tailwindcss@3.4.4(ts-node@10.9.2(@types/node@17.0.45)(typescript@4.9.5))): + tailwindcss-animate@1.0.7(tailwindcss@3.4.4(ts-node@10.9.2(@types/node@20.14.10)(typescript@4.9.5))): dependencies: - tailwindcss: 3.4.4(ts-node@10.9.2(@types/node@17.0.45)(typescript@4.9.5)) + tailwindcss: 3.4.4(ts-node@10.9.2(@types/node@20.14.10)(typescript@4.9.5)) - tailwindcss@3.4.4(ts-node@10.9.2(@types/node@17.0.45)(typescript@4.9.5)): + tailwindcss@3.4.4(ts-node@10.9.2(@types/node@20.14.10)(typescript@4.9.5)): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -16642,7 +16630,7 @@ snapshots: postcss: 8.4.39 postcss-import: 15.1.0(postcss@8.4.39) postcss-js: 4.0.1(postcss@8.4.39) - postcss-load-config: 4.0.2(postcss@8.4.39)(ts-node@10.9.2(@types/node@17.0.45)(typescript@4.9.5)) + postcss-load-config: 4.0.2(postcss@8.4.39)(ts-node@10.9.2(@types/node@20.14.10)(typescript@4.9.5)) postcss-nested: 6.0.1(postcss@8.4.39) postcss-selector-parser: 6.1.0 resolve: 1.22.8 @@ -16756,11 +16744,11 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-jest@29.1.5(@babel/core@7.24.7)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(jest@29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)))(typescript@5.5.3): + ts-jest@29.1.5(@babel/core@7.24.7)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(jest@29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)))(typescript@5.5.3): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@20.14.9)(ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3)) + jest: 29.7.0(@types/node@20.14.10)(ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3)) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 @@ -16784,14 +16772,14 @@ snapshots: typescript: 5.5.3 webpack: 5.92.1 - ts-node@10.9.2(@types/node@17.0.45)(typescript@4.9.5): + ts-node@10.9.2(@types/node@20.14.10)(typescript@4.9.5): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 17.0.45 + '@types/node': 20.14.10 acorn: 8.12.0 acorn-walk: 8.3.3 arg: 4.1.3 @@ -16803,14 +16791,14 @@ snapshots: yn: 3.1.1 optional: true - ts-node@10.9.2(@types/node@20.14.9)(typescript@5.5.3): + ts-node@10.9.2(@types/node@20.14.10)(typescript@5.5.3): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 20.14.9 + '@types/node': 20.14.10 acorn: 8.12.0 acorn-walk: 8.3.3 arg: 4.1.3