├── server
├── .prettierrc
├── .env
├── tsconfig.build.json
├── src
│ ├── app.service.ts
│ ├── pcs
│ │ ├── dto
│ │ │ ├── update-pc.dto.ts
│ │ │ └── create-pc.dto.ts
│ │ ├── pcs.module.ts
│ │ ├── pcs.service.spec.ts
│ │ ├── entities
│ │ │ └── pc.entity.ts
│ │ ├── pcs.controller.spec.ts
│ │ ├── pcs.controller.ts
│ │ └── pcs.service.ts
│ ├── app.controller.ts
│ ├── main.ts
│ ├── app.module.ts
│ └── app.controller.spec.ts
├── nest-cli.json
├── test
│ ├── jest-e2e.json
│ └── app.e2e-spec.ts
├── .gitignore
├── tsconfig.json
├── db
│ ├── data-source.ts
│ └── migrations
│ │ ├── 1707673430266-VarCharAddedToRam.ts
│ │ ├── 1707673280382-EmailAdded.ts
│ │ ├── 1707673305388-EmailRemoved.ts
│ │ └── 1707673549097-VarCharAdded.ts
├── .eslintrc.js
├── README.md
└── package.json
├── app
├── public
│ ├── favicon.ico
│ ├── vercel.svg
│ └── next.svg
├── postcss.config.js
├── next.config.mjs
├── src
│ ├── pages
│ │ ├── _document.tsx
│ │ ├── _app.tsx
│ │ ├── api
│ │ │ └── hello.ts
│ │ ├── components
│ │ │ ├── Pagination.tsx
│ │ │ └── ComputerCard.tsx
│ │ ├── pc
│ │ │ └── [id].tsx
│ │ └── index.tsx
│ └── styles
│ │ └── globals.css
├── utils
│ ├── config.ts
│ └── fetchService.ts
├── .gitignore
├── tsconfig.json
├── tailwind.config.ts
├── package.json
├── models
│ └── computers
│ │ └── computers.interface.ts
├── README.md
├── context
│ └── AdminContext.tsx
└── package-lock.json
└── README.md
/server/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "trailingComma": "all"
4 | }
--------------------------------------------------------------------------------
/app/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Big-Silver/thesis-assessment/main/app/public/favicon.ico
--------------------------------------------------------------------------------
/server/.env:
--------------------------------------------------------------------------------
1 | DB_HOST=localhost
2 | DB_PORT=5432
3 | DB_USERNAME=
4 | DB_PASSWORD=
5 | DB_NAME=computersdb
6 | PORT=3040
7 |
--------------------------------------------------------------------------------
/app/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/server/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
4 | }
5 |
--------------------------------------------------------------------------------
/app/next.config.mjs:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {
3 | reactStrictMode: true,
4 | };
5 |
6 | export default nextConfig;
7 |
--------------------------------------------------------------------------------
/server/src/app.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 |
3 | @Injectable()
4 | export class AppService {
5 | getHello(): string {
6 | return 'Hello World!';
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/server/src/pcs/dto/update-pc.dto.ts:
--------------------------------------------------------------------------------
1 | import { PartialType } from '@nestjs/mapped-types';
2 | import { CreatePcDto } from './create-pc.dto';
3 |
4 | export class UpdatePcDto extends PartialType(CreatePcDto) {}
5 |
--------------------------------------------------------------------------------
/server/nest-cli.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/nest-cli",
3 | "collection": "@nestjs/schematics",
4 | "sourceRoot": "src",
5 | "compilerOptions": {
6 | "deleteOutDir": true
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/server/test/jest-e2e.json:
--------------------------------------------------------------------------------
1 | {
2 | "moduleFileExtensions": ["js", "json", "ts"],
3 | "rootDir": ".",
4 | "testEnvironment": "node",
5 | "testRegex": ".e2e-spec.ts$",
6 | "transform": {
7 | "^.+\\.(t|j)s$": "ts-jest"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/app/src/pages/_document.tsx:
--------------------------------------------------------------------------------
1 | import { Html, Head, Main, NextScript } from "next/document";
2 |
3 | export default function Document() {
4 | return (
5 |
6 |
8 |
9 |
10 |
11 |
12 | );
13 | }
14 |
--------------------------------------------------------------------------------
/server/src/app.controller.ts:
--------------------------------------------------------------------------------
1 | import { Controller, Get } from '@nestjs/common';
2 | import { AppService } from './app.service';
3 |
4 | @Controller()
5 | export class AppController {
6 | constructor(private readonly appService: AppService) {}
7 |
8 | @Get()
9 | getHello(): string {
10 | return this.appService.getHello();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/pages/_app.tsx:
--------------------------------------------------------------------------------
1 | import "@/styles/globals.css";
2 | import type { AppProps } from "next/app";
3 | import { AdminContextProvider } from "../../context/AdminContext";
4 |
5 | export default function App({ Component, pageProps }: AppProps) {
6 | return (
7 |
8 |
9 |
10 | );
11 | }
12 |
--------------------------------------------------------------------------------
/app/utils/config.ts:
--------------------------------------------------------------------------------
1 | export const BASE_API_URL = "http://localhost:3040";
2 | export const getAllPcs = `${BASE_API_URL}/pcs/get_all_pcs`;
3 | export const getById = `${BASE_API_URL}/pcs/get_pc_by_id`;
4 | export const updateById = `${BASE_API_URL}/pcs/update_pc_by_id`;
5 | export const deleteById = `${BASE_API_URL}/pcs/delete_pc_by_id`;
6 | export const addPc = `${BASE_API_URL}/pcs/upload_file`;
7 |
--------------------------------------------------------------------------------
/app/src/pages/api/hello.ts:
--------------------------------------------------------------------------------
1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction
2 | import type { NextApiRequest, NextApiResponse } from "next";
3 |
4 | type Data = {
5 | name: string;
6 | };
7 |
8 | export default function handler(
9 | req: NextApiRequest,
10 | res: NextApiResponse,
11 | ) {
12 | res.status(200).json({ name: "John Doe" });
13 | }
14 |
--------------------------------------------------------------------------------
/server/src/pcs/pcs.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { PcsService } from './pcs.service';
3 | import { PcsController } from './pcs.controller';
4 | import { TypeOrmModule } from '@nestjs/typeorm';
5 | import { Pc } from './entities/pc.entity';
6 |
7 | @Module({
8 | imports: [TypeOrmModule.forFeature([Pc])],
9 | controllers: [PcsController],
10 | providers: [PcsService],
11 | })
12 | export class PcsModule {}
13 |
--------------------------------------------------------------------------------
/server/src/main.ts:
--------------------------------------------------------------------------------
1 | import { NestFactory } from '@nestjs/core';
2 | import { AppModule } from './app.module';
3 | import * as dotenv from 'dotenv';
4 | import * as path from 'path';
5 |
6 | dotenv.config({ path: path.resolve(__dirname, '../.env') });
7 |
8 | async function bootstrap() {
9 | const app = await NestFactory.create(AppModule);
10 |
11 | app.enableCors();
12 |
13 | const port = process.env.PORT;
14 | await app.listen(port);
15 | }
16 |
17 | bootstrap();
18 |
--------------------------------------------------------------------------------
/server/src/app.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { AppController } from './app.controller';
3 | import { AppService } from './app.service';
4 | import { TypeOrmModule } from '@nestjs/typeorm';
5 | import { dataSourceOptions } from 'db/data-source';
6 | import { PcsModule } from './pcs/pcs.module';
7 |
8 | @Module({
9 | imports: [TypeOrmModule.forRoot(dataSourceOptions), PcsModule],
10 | controllers: [AppController],
11 | providers: [AppService],
12 | })
13 | export class AppModule {}
14 |
--------------------------------------------------------------------------------
/server/src/pcs/pcs.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { PcsService } from './pcs.service';
3 |
4 | describe('PcsService', () => {
5 | let service: PcsService;
6 |
7 | beforeEach(async () => {
8 | const module: TestingModule = await Test.createTestingModule({
9 | providers: [PcsService],
10 | }).compile();
11 |
12 | service = module.get(PcsService);
13 | });
14 |
15 | it('should be defined', () => {
16 | expect(service).toBeDefined();
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/server/.gitignore:
--------------------------------------------------------------------------------
1 | # compiled output
2 | /dist
3 | /node_modules
4 |
5 | # Logs
6 | logs
7 | *.log
8 | npm-debug.log*
9 | pnpm-debug.log*
10 | yarn-debug.log*
11 | yarn-error.log*
12 | lerna-debug.log*
13 |
14 | # OS
15 | .DS_Store
16 |
17 | # Tests
18 | /coverage
19 | /.nyc_output
20 |
21 | # IDEs and editors
22 | /.idea
23 | .project
24 | .classpath
25 | .c9/
26 | *.launch
27 | .settings/
28 | *.sublime-workspace
29 |
30 | # IDE - VSCode
31 | .vscode/*
32 | !.vscode/settings.json
33 | !.vscode/tasks.json
34 | !.vscode/launch.json
35 | !.vscode/extensions.json
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 | .yarn/install-state.gz
8 |
9 | # testing
10 | /coverage
11 |
12 | # next.js
13 | /.next/
14 | /out/
15 |
16 | # production
17 | /build
18 |
19 | # misc
20 | .DS_Store
21 | *.pem
22 |
23 | # debug
24 | npm-debug.log*
25 | yarn-debug.log*
26 | yarn-error.log*
27 |
28 | # local env files
29 | .env*.local
30 |
31 | # vercel
32 | .vercel
33 |
34 | # typescript
35 | *.tsbuildinfo
36 | next-env.d.ts
37 |
--------------------------------------------------------------------------------
/app/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "lib": ["dom", "dom.iterable", "esnext"],
4 | "allowJs": true,
5 | "skipLibCheck": true,
6 | "strict": true,
7 | "noEmit": true,
8 | "esModuleInterop": true,
9 | "module": "esnext",
10 | "moduleResolution": "bundler",
11 | "resolveJsonModule": true,
12 | "isolatedModules": true,
13 | "jsx": "preserve",
14 | "incremental": true,
15 | "paths": {
16 | "@/*": ["./src/*"]
17 | }
18 | },
19 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
20 | "exclude": ["node_modules"]
21 | }
22 |
--------------------------------------------------------------------------------
/app/tailwind.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from "tailwindcss";
2 |
3 | const config: Config = {
4 | content: [
5 | "./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
6 | "./src/components/**/*.{js,ts,jsx,tsx,mdx}",
7 | "./src/app/**/*.{js,ts,jsx,tsx,mdx}",
8 | ],
9 | theme: {
10 | extend: {
11 | backgroundImage: {
12 | "gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
13 | "gradient-conic":
14 | "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
15 | },
16 | },
17 | },
18 | plugins: [],
19 | };
20 | export default config;
21 |
--------------------------------------------------------------------------------
/app/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/server/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "declaration": true,
5 | "removeComments": true,
6 | "emitDecoratorMetadata": true,
7 | "experimentalDecorators": true,
8 | "allowSyntheticDefaultImports": true,
9 | "target": "ES2021",
10 | "sourceMap": true,
11 | "outDir": "./dist",
12 | "baseUrl": "./",
13 | "incremental": true,
14 | "skipLibCheck": true,
15 | "strictNullChecks": false,
16 | "noImplicitAny": false,
17 | "strictBindCallApply": false,
18 | "forceConsistentCasingInFileNames": false,
19 | "noFallthroughCasesInSwitch": false
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/server/src/pcs/entities/pc.entity.ts:
--------------------------------------------------------------------------------
1 | import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
2 |
3 | @Entity()
4 | export class Pc {
5 | @PrimaryGeneratedColumn()
6 | computer_id: number;
7 |
8 | @Column({ type: 'varchar' })
9 | ram: string;
10 |
11 | @Column()
12 | storage_type: string;
13 |
14 | @Column()
15 | storage_capacity: string;
16 |
17 | @Column({ type: 'varchar' })
18 | usb_ports: string;
19 |
20 | @Column()
21 | gpu: string;
22 |
23 | @Column({ type: 'varchar' })
24 | weight: string;
25 |
26 | @Column({ type: 'varchar' })
27 | psu_wattage: string;
28 |
29 | @Column()
30 | processor: string;
31 | }
32 |
--------------------------------------------------------------------------------
/server/src/pcs/pcs.controller.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { PcsController } from './pcs.controller';
3 | import { PcsService } from './pcs.service';
4 |
5 | describe('PcsController', () => {
6 | let controller: PcsController;
7 |
8 | beforeEach(async () => {
9 | const module: TestingModule = await Test.createTestingModule({
10 | controllers: [PcsController],
11 | providers: [PcsService],
12 | }).compile();
13 |
14 | controller = module.get(PcsController);
15 | });
16 |
17 | it('should be defined', () => {
18 | expect(controller).toBeDefined();
19 | });
20 | });
21 |
--------------------------------------------------------------------------------
/app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "devtestapp",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint"
10 | },
11 | "dependencies": {
12 | "axios": "^1.6.7",
13 | "next": "14.1.0",
14 | "react": "^18",
15 | "react-dom": "^18",
16 | "react-icons": "^5.0.1"
17 | },
18 | "devDependencies": {
19 | "@types/node": "^20",
20 | "@types/react": "^18",
21 | "@types/react-dom": "^18",
22 | "autoprefixer": "^10.0.1",
23 | "postcss": "^8",
24 | "tailwindcss": "^3.3.0",
25 | "typescript": "^5"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/models/computers/computers.interface.ts:
--------------------------------------------------------------------------------
1 | export interface ComputerRoot {
2 | pcs: ComputerPc[];
3 | totalItems: number;
4 | totalPages: number;
5 | }
6 |
7 | export interface ComputerPc {
8 | computer_id: number;
9 | ram: string;
10 | storage_type: string;
11 | storage_capacity: string;
12 | usb_ports: string;
13 | gpu: string;
14 | weight: string;
15 | psu_wattage: string;
16 | processor: string;
17 | }
18 |
19 | export interface EditComputerPc {
20 | ram: string;
21 | storage_type: string;
22 | storage_capacity: string;
23 | usb_ports: string;
24 | gpu: string;
25 | weight: string;
26 | psu_wattage: string;
27 | processor: string;
28 | }
29 |
--------------------------------------------------------------------------------
/server/src/pcs/dto/create-pc.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsString, IsNotEmpty } from 'class-validator';
2 |
3 | export class CreatePcDto {
4 | @IsString()
5 | @IsNotEmpty()
6 | ram: string;
7 |
8 | @IsString()
9 | @IsNotEmpty()
10 | storage_type: string;
11 |
12 | @IsString()
13 | @IsNotEmpty()
14 | storage_capacity: string;
15 |
16 | @IsString()
17 | @IsNotEmpty()
18 | usb_ports: string;
19 |
20 | @IsString()
21 | @IsNotEmpty()
22 | gpu: string;
23 |
24 | @IsString()
25 | @IsNotEmpty()
26 | weight: string;
27 |
28 | @IsString()
29 | @IsNotEmpty()
30 | psu_wattage: string;
31 |
32 | @IsString()
33 | @IsNotEmpty()
34 | processor: string;
35 | }
36 |
--------------------------------------------------------------------------------
/server/db/data-source.ts:
--------------------------------------------------------------------------------
1 | import { DataSource, DataSourceOptions } from 'typeorm';
2 |
3 | import * as dotenv from 'dotenv';
4 | import * as path from 'path';
5 |
6 | dotenv.config({ path: path.resolve(__dirname, '../.env') });
7 |
8 | export const dataSourceOptions: DataSourceOptions = {
9 | type: 'postgres',
10 | host: process.env.DB_HOST,
11 | port: parseInt(process.env.DB_PORT),
12 | username: process.env.DB_USERNAME,
13 | password: process.env.DB_PASSWORD,
14 | database: process.env.DB_NAME,
15 | entities: ['dist/**/*.entity.js'],
16 | migrations: ['dist/db/migrations/*.js'],
17 | };
18 |
19 | const dataSource = new DataSource(dataSourceOptions);
20 |
21 | export default dataSource;
22 |
--------------------------------------------------------------------------------
/server/src/app.controller.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { AppController } from './app.controller';
3 | import { AppService } from './app.service';
4 |
5 | describe('AppController', () => {
6 | let appController: AppController;
7 |
8 | beforeEach(async () => {
9 | const app: TestingModule = await Test.createTestingModule({
10 | controllers: [AppController],
11 | providers: [AppService],
12 | }).compile();
13 |
14 | appController = app.get(AppController);
15 | });
16 |
17 | describe('root', () => {
18 | it('should return "Hello World!"', () => {
19 | expect(appController.getHello()).toBe('Hello World!');
20 | });
21 | });
22 | });
23 |
--------------------------------------------------------------------------------
/server/db/migrations/1707673430266-VarCharAddedToRam.ts:
--------------------------------------------------------------------------------
1 | import { MigrationInterface, QueryRunner } from "typeorm";
2 |
3 | export class VarCharAddedToRam1707673430266 implements MigrationInterface {
4 | name = 'VarCharAddedToRam1707673430266'
5 |
6 | public async up(queryRunner: QueryRunner): Promise {
7 | await queryRunner.query(`ALTER TABLE "pc" DROP COLUMN "ram"`);
8 | await queryRunner.query(`ALTER TABLE "pc" ADD "ram" character varying NOT NULL`);
9 | }
10 |
11 | public async down(queryRunner: QueryRunner): Promise {
12 | await queryRunner.query(`ALTER TABLE "pc" DROP COLUMN "ram"`);
13 | await queryRunner.query(`ALTER TABLE "pc" ADD "ram" integer NOT NULL`);
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/server/test/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { INestApplication } from '@nestjs/common';
3 | import * as request from 'supertest';
4 | import { AppModule } from './../src/app.module';
5 |
6 | describe('AppController (e2e)', () => {
7 | let app: INestApplication;
8 |
9 | beforeEach(async () => {
10 | const moduleFixture: TestingModule = await Test.createTestingModule({
11 | imports: [AppModule],
12 | }).compile();
13 |
14 | app = moduleFixture.createNestApplication();
15 | await app.init();
16 | });
17 |
18 | it('/ (GET)', () => {
19 | return request(app.getHttpServer())
20 | .get('/')
21 | .expect(200)
22 | .expect('Hello World!');
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/app/src/styles/globals.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap");
2 |
3 | @tailwind base;
4 | @tailwind components;
5 | @tailwind utilities;
6 |
7 | :root {
8 | --foreground-rgb: 0, 0, 0;
9 | --background-start-rgb: 214, 219, 220;
10 | --background-end-rgb: 255, 255, 255;
11 | }
12 |
13 | @media (prefers-color-scheme: dark) {
14 | :root {
15 | --foreground-rgb: 255, 255, 255;
16 | --background-start-rgb: 0, 0, 0;
17 | --background-end-rgb: 0, 0, 0;
18 | }
19 | }
20 |
21 | body {
22 | background-color: rgb(5, 5, 5);
23 | font-family: "Poppins", sans-serif;
24 | color: #fff;
25 | }
26 |
--------------------------------------------------------------------------------
/server/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | parser: '@typescript-eslint/parser',
3 | parserOptions: {
4 | project: 'tsconfig.json',
5 | tsconfigRootDir: __dirname,
6 | sourceType: 'module',
7 | },
8 | plugins: ['@typescript-eslint/eslint-plugin'],
9 | extends: [
10 | 'plugin:@typescript-eslint/recommended',
11 | 'plugin:prettier/recommended',
12 | ],
13 | root: true,
14 | env: {
15 | node: true,
16 | jest: true,
17 | },
18 | ignorePatterns: ['.eslintrc.js'],
19 | rules: {
20 | '@typescript-eslint/interface-name-prefix': 'off',
21 | '@typescript-eslint/explicit-function-return-type': 'off',
22 | '@typescript-eslint/explicit-module-boundary-types': 'off',
23 | '@typescript-eslint/no-explicit-any': 'off',
24 | },
25 | };
26 |
--------------------------------------------------------------------------------
/server/db/migrations/1707673280382-EmailAdded.ts:
--------------------------------------------------------------------------------
1 | import { MigrationInterface, QueryRunner } from "typeorm";
2 |
3 | export class EmailAdded1707673280382 implements MigrationInterface {
4 | name = 'EmailAdded1707673280382'
5 |
6 | public async up(queryRunner: QueryRunner): Promise {
7 | await queryRunner.query(`ALTER TABLE "pc" ADD "email" character varying NOT NULL`);
8 | await queryRunner.query(`ALTER TABLE "pc" ADD CONSTRAINT "UQ_b202b74947f06df05c3734da9f1" UNIQUE ("email")`);
9 | }
10 |
11 | public async down(queryRunner: QueryRunner): Promise {
12 | await queryRunner.query(`ALTER TABLE "pc" DROP CONSTRAINT "UQ_b202b74947f06df05c3734da9f1"`);
13 | await queryRunner.query(`ALTER TABLE "pc" DROP COLUMN "email"`);
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/server/db/migrations/1707673305388-EmailRemoved.ts:
--------------------------------------------------------------------------------
1 | import { MigrationInterface, QueryRunner } from "typeorm";
2 |
3 | export class EmailRemoved1707673305388 implements MigrationInterface {
4 | name = 'EmailRemoved1707673305388'
5 |
6 | public async up(queryRunner: QueryRunner): Promise {
7 | await queryRunner.query(`ALTER TABLE "pc" DROP CONSTRAINT "UQ_b202b74947f06df05c3734da9f1"`);
8 | await queryRunner.query(`ALTER TABLE "pc" DROP COLUMN "email"`);
9 | }
10 |
11 | public async down(queryRunner: QueryRunner): Promise {
12 | await queryRunner.query(`ALTER TABLE "pc" ADD "email" character varying NOT NULL`);
13 | await queryRunner.query(`ALTER TABLE "pc" ADD CONSTRAINT "UQ_b202b74947f06df05c3734da9f1" UNIQUE ("email")`);
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/app/README.md:
--------------------------------------------------------------------------------
1 | # README.md
2 |
3 | ## Next.js App
4 |
5 | This repository contains a Next.js application.
6 |
7 | ### Getting Started
8 |
9 | To run this project locally, follow these steps:
10 |
11 | 1. **Clone the repo**:
12 |
13 | - Clone the repository to a location of your choice on your computer.
14 |
15 | 2. **Navigate into the project directory**:
16 |
17 | ```bash
18 | cd
19 | ```
20 |
21 | 3. **Install Dependencies**:
22 |
23 | ```bash
24 | npm install
25 | ```
26 |
27 | 4. **Start the Development Server**:
28 | ```bash
29 | npm run dev
30 | ```
31 |
32 | This command will start the development server. You can access the application at `http://localhost:3000` by default.
33 |
34 | ### More Information
35 |
36 | For more information on how to work with Next.js, refer to the [Next.js documentation](https://nextjs.org/docs/getting-started).
37 |
--------------------------------------------------------------------------------
/app/context/AdminContext.tsx:
--------------------------------------------------------------------------------
1 | import React, {
2 | createContext,
3 | useState,
4 | useEffect,
5 | ReactNode,
6 | Dispatch,
7 | SetStateAction,
8 | } from "react";
9 |
10 | type AdminContextProps = {
11 | updateState: boolean;
12 | setUpdateState: Dispatch>;
13 | };
14 |
15 | type AdminContextProviderProps = {
16 | children: ReactNode;
17 | };
18 |
19 | const AdminContext = createContext(undefined);
20 |
21 | export const AdminContextProvider: React.FC = ({
22 | children,
23 | }) => {
24 | const [updateState, setUpdateState] = useState(false);
25 |
26 | useEffect(() => {
27 | // Add any initialization logic if needed
28 | }, []);
29 |
30 | return (
31 |
37 | {children}
38 |
39 | );
40 | };
41 |
42 | export default AdminContext;
43 |
--------------------------------------------------------------------------------
/app/public/next.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/server/db/migrations/1707673549097-VarCharAdded.ts:
--------------------------------------------------------------------------------
1 | import { MigrationInterface, QueryRunner } from "typeorm";
2 |
3 | export class VarCharAdded1707673549097 implements MigrationInterface {
4 | name = 'VarCharAdded1707673549097'
5 |
6 | public async up(queryRunner: QueryRunner): Promise {
7 | await queryRunner.query(`ALTER TABLE "pc" DROP COLUMN "usb_ports"`);
8 | await queryRunner.query(`ALTER TABLE "pc" ADD "usb_ports" character varying NOT NULL`);
9 | await queryRunner.query(`ALTER TABLE "pc" DROP COLUMN "weight"`);
10 | await queryRunner.query(`ALTER TABLE "pc" ADD "weight" character varying NOT NULL`);
11 | await queryRunner.query(`ALTER TABLE "pc" DROP COLUMN "psu_wattage"`);
12 | await queryRunner.query(`ALTER TABLE "pc" ADD "psu_wattage" character varying NOT NULL`);
13 | }
14 |
15 | public async down(queryRunner: QueryRunner): Promise {
16 | await queryRunner.query(`ALTER TABLE "pc" DROP COLUMN "psu_wattage"`);
17 | await queryRunner.query(`ALTER TABLE "pc" ADD "psu_wattage" integer NOT NULL`);
18 | await queryRunner.query(`ALTER TABLE "pc" DROP COLUMN "weight"`);
19 | await queryRunner.query(`ALTER TABLE "pc" ADD "weight" integer NOT NULL`);
20 | await queryRunner.query(`ALTER TABLE "pc" DROP COLUMN "usb_ports"`);
21 | await queryRunner.query(`ALTER TABLE "pc" ADD "usb_ports" integer NOT NULL`);
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/pages/components/Pagination.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { RiArrowLeftLine, RiArrowRightLine } from "react-icons/ri";
3 |
4 | interface PaginationProps {
5 | pageNo: number;
6 | totalPages: number;
7 | onPageChange: (newPage: number) => void;
8 | }
9 |
10 | const Pagination: React.FC = ({
11 | pageNo,
12 | totalPages,
13 | onPageChange,
14 | }) => {
15 | const isFirstPage = pageNo === 1;
16 | const isLastPage = pageNo === totalPages;
17 |
18 | return (
19 |
20 | -
21 |
32 |
33 | -
34 |
35 | Page {pageNo} of {totalPages}
36 |
37 |
38 | -
39 |
50 |
51 |
52 | );
53 | };
54 |
55 | export default Pagination;
56 |
--------------------------------------------------------------------------------
/app/utils/fetchService.ts:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 |
3 | export async function fetchData(url: string): Promise {
4 | try {
5 | const response = await axios.get(url);
6 | return response.data;
7 | } catch (error) {
8 | throw error;
9 | }
10 | }
11 |
12 | export async function putData(url: string, body: any): Promise {
13 | try {
14 | const headers = {
15 | "Content-Type": "application/json",
16 | };
17 |
18 | const response = await axios.put(url, body, { headers });
19 |
20 | if (response.status !== 200) {
21 | throw new Error("Failed to update data.");
22 | }
23 |
24 | return response.data;
25 | } catch (error) {
26 | console.error("Error updating data:", error);
27 | throw error;
28 | }
29 | }
30 |
31 | export async function deleteData(url: string): Promise {
32 | try {
33 | const headers = {
34 | "Content-Type": "application/json",
35 | };
36 |
37 | const response = await axios.delete(url, { headers });
38 |
39 | if (response.status !== 200) {
40 | throw new Error("Failed to delete data.");
41 | }
42 |
43 | return response.data;
44 | } catch (error) {
45 | console.error("Error deleting data:", error);
46 | throw error;
47 | }
48 | }
49 |
50 | export async function postData(url: string, body: any): Promise {
51 | try {
52 | const headers = {
53 | "Content-Type": "text/csv",
54 | };
55 |
56 | const response = await axios.post(url, body, { headers });
57 |
58 | if (response.status !== 201) {
59 | throw new Error("Failed to create data.");
60 | }
61 |
62 | return response.data;
63 | } catch (error) {
64 | console.error("Error creating data:", error);
65 | throw error;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/server/README.md:
--------------------------------------------------------------------------------
1 | # README.md
2 |
3 | ## Nest.js App with PostgreSQL Database
4 |
5 | This repository contains a Nest.js application with a PostgreSQL database.
6 |
7 | ### Getting Started
8 |
9 | To run this project locally, follow these steps:
10 |
11 | 1. **Clone the repo**:
12 |
13 | - Clone the repository to a location of your choice on your computer.
14 |
15 | 2. **Navigate into the project directory**:
16 |
17 | ```bash
18 | cd server
19 | ```
20 |
21 | 3. **Install Dependencies**:
22 |
23 | ```bash
24 | npm install
25 | ```
26 |
27 | 4. **Set up Database Configuration**:
28 |
29 | - Rename or copy the `.env.example` file to `.env`.
30 | - Open the `.env` file and configure the following variables for your PostgreSQL database:
31 | ```bash
32 | DB_HOST=your_database_host
33 | DB_PORT=your_database_port
34 | DB_USERNAME=your_database_username
35 | DB_PASSWORD=your_database_password
36 | DB_NAME=your_database_name
37 | PORT=your_port
38 | ```
39 |
40 | 5. **Run Database Migrations**:
41 |
42 | - To generate a new migration, run:
43 |
44 | ```bash
45 | npm run migration:generate --
46 | ```
47 |
48 | Replace `` with an appropriate name for your migration, for example:
49 |
50 | ```bash
51 | npm run migration:generate -- db/migrations/AddNewPaswordColumn
52 | ```
53 |
54 | - To apply pending migrations, run:
55 |
56 | ```bash
57 | npm run migration:run
58 | ```
59 |
60 | 6. **Start the Application**:
61 |
62 | ```bash
63 | npm run start:dev
64 | ```
65 |
66 | This command will start the Nest.js application in development mode. The server will be running at PORT by default.
67 |
68 | ### More Information
69 |
70 | For more information on how to work with Nest.js, refer to the [Nest.js documentation](https://docs.nestjs.com/).
71 |
--------------------------------------------------------------------------------
/app/src/pages/components/ComputerCard.tsx:
--------------------------------------------------------------------------------
1 | import { useRouter } from "next/router";
2 | import React from "react";
3 | import { RiEdit2Line } from "react-icons/ri";
4 | import { TbTrash } from "react-icons/tb";
5 |
6 | type ComputerSpecs = {
7 | id: number;
8 | processor: string;
9 | gpu: string;
10 | storage: string;
11 | weight: string;
12 | ram: string;
13 | handleDelete?: (id: number) => void;
14 | };
15 |
16 | const ComputerCard = ({
17 | id,
18 | processor,
19 | gpu,
20 | storage,
21 | weight,
22 | ram,
23 | handleDelete,
24 | }: ComputerSpecs) => {
25 | const router = useRouter();
26 |
27 | return (
28 |
29 |
30 |
Specfication
31 |
32 | Processor: {processor}
33 |
34 |
35 | GPU: {gpu}
36 |
37 |
38 | Storage: {storage}
39 |
40 |
41 | Weight: {weight}
42 |
43 |
44 | RAM: {ram}
45 |
46 |
47 |
48 |
router.push(`/pc/${id}`)}>
49 |
50 |
{" "}
51 | {handleDelete && (
52 |
handleDelete(id)}>
53 |
54 |
55 | )}
56 |
57 |
58 | );
59 | };
60 |
61 | export default ComputerCard;
62 |
--------------------------------------------------------------------------------
/server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "devtest",
3 | "version": "0.0.1",
4 | "description": "",
5 | "author": "",
6 | "private": true,
7 | "license": "UNLICENSED",
8 | "scripts": {
9 | "build": "nest build",
10 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
11 | "start": "nest start",
12 | "start:dev": "nest start --watch",
13 | "start:debug": "nest start --debug --watch",
14 | "start:prod": "node dist/main",
15 | "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
16 | "test": "jest",
17 | "test:watch": "jest --watch",
18 | "test:cov": "jest --coverage",
19 | "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
20 | "test:e2e": "jest --config ./test/jest-e2e.json",
21 | "typeorm": "npm run build && npx typeorm -d dist/db/data-source.js",
22 | "migration:generate": "npm run typeorm -- migration:generate",
23 | "migration:run": "npm run typeorm -- migration:run",
24 | "migration:revert": "npm run typeorm -- migration:revert"
25 | },
26 | "dependencies": {
27 | "@nestjs/common": "^10.0.0",
28 | "@nestjs/core": "^10.0.0",
29 | "@nestjs/mapped-types": "*",
30 | "@nestjs/platform-express": "^10.0.0",
31 | "@nestjs/typeorm": "^10.0.2",
32 | "class-validator": "^0.14.1",
33 | "csv-parser": "^3.0.0",
34 | "dotenv": "^16.4.4",
35 | "multer": "^1.4.5-lts.1",
36 | "pg": "^8.11.3",
37 | "reflect-metadata": "^0.1.13",
38 | "rxjs": "^7.8.1",
39 | "typeorm": "^0.3.20"
40 | },
41 | "devDependencies": {
42 | "@nestjs/cli": "^10.0.0",
43 | "@nestjs/schematics": "^10.0.0",
44 | "@nestjs/testing": "^10.0.0",
45 | "@types/express": "^4.17.17",
46 | "@types/jest": "^29.5.2",
47 | "@types/node": "^20.3.1",
48 | "@types/supertest": "^6.0.0",
49 | "@typescript-eslint/eslint-plugin": "^6.0.0",
50 | "@typescript-eslint/parser": "^6.0.0",
51 | "eslint": "^8.42.0",
52 | "eslint-config-prettier": "^9.0.0",
53 | "eslint-plugin-prettier": "^5.0.0",
54 | "jest": "^29.5.0",
55 | "prettier": "^3.0.0",
56 | "source-map-support": "^0.5.21",
57 | "supertest": "^6.3.3",
58 | "ts-jest": "^29.1.0",
59 | "ts-loader": "^9.4.3",
60 | "ts-node": "^10.9.1",
61 | "tsconfig-paths": "^4.2.0",
62 | "typescript": "^5.1.3"
63 | },
64 | "jest": {
65 | "moduleFileExtensions": [
66 | "js",
67 | "json",
68 | "ts"
69 | ],
70 | "rootDir": "src",
71 | "testRegex": ".*\\.spec\\.ts$",
72 | "transform": {
73 | "^.+\\.(t|j)s$": "ts-jest"
74 | },
75 | "collectCoverageFrom": [
76 | "**/*.(t|j)s"
77 | ],
78 | "coverageDirectory": "../coverage",
79 | "testEnvironment": "node"
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Thesis Assessment
2 |
3 | This repository contains a Next.js application and a Nest.js application with a PostgreSQL database.
4 |
5 | ## Frontend
6 |
7 | ### Getting Started
8 |
9 | To run this project locally, follow these steps:
10 |
11 | 1. **Clone the repo**:
12 |
13 | - Clone the repository to a location of your choice on your computer.
14 |
15 | 2. **Navigate into the project directory**:
16 |
17 | ```bash
18 | cd app
19 | ```
20 |
21 | 3. **Install Dependencies**:
22 |
23 | ```bash
24 | npm install
25 | ```
26 |
27 | 4. **Start the Development Server**:
28 | ```bash
29 | npm run dev
30 | ```
31 |
32 | This command will start the development server. You can access the application at `http://localhost:3000` by default.
33 |
34 | ### More Information
35 |
36 | For more information on how to work with Next.js, refer to the [Next.js documentation](https://nextjs.org/docs/getting-started).
37 |
38 |
39 | ## Server
40 |
41 | This repository contains a Nest.js application with a PostgreSQL database.
42 |
43 | ### Getting Started
44 |
45 | To run this project locally, follow these steps:
46 |
47 | 1. **Clone the repo**:
48 |
49 | - Clone the repository to a location of your choice on your computer.
50 |
51 | 2. **Navigate into the project directory**:
52 |
53 | ```bash
54 | cd server
55 | ```
56 |
57 | 3. **Install Dependencies**:
58 |
59 | ```bash
60 | npm install
61 | ```
62 |
63 | 4. **Set up Database Configuration**:
64 |
65 | - Rename or copy the `.env.example` file to `.env`.
66 | - Open the `.env` file and configure the following variables for your PostgreSQL database:
67 | ```bash
68 | DB_HOST=your_database_host
69 | DB_PORT=your_database_port
70 | DB_USERNAME=your_database_username
71 | DB_PASSWORD=your_database_password
72 | DB_NAME=your_database_name
73 | PORT=your_port
74 | ```
75 |
76 | 5. **Run Database Migrations**:
77 |
78 | - To generate a new migration, run:
79 |
80 | ```bash
81 | npm run migration:generate --
82 | ```
83 |
84 | Replace `` with an appropriate name for your migration, for example:
85 |
86 | ```bash
87 | npm run migration:generate -- db/migrations/AddNewPaswordColumn
88 | ```
89 |
90 | - To apply pending migrations, run:
91 |
92 | ```bash
93 | npm run migration:run
94 | ```
95 |
96 | 6. **Start the Application**:
97 |
98 | ```bash
99 | npm run start:dev
100 | ```
101 |
102 | This command will start the Nest.js application in development mode. The server will be running at PORT by default.
103 |
104 | ### More Information
105 |
106 | For more information on how to work with Nest.js, refer to the [Nest.js documentation](https://docs.nestjs.com/).
107 |
--------------------------------------------------------------------------------
/server/src/pcs/pcs.controller.ts:
--------------------------------------------------------------------------------
1 | import {
2 | BadRequestException,
3 | Body,
4 | Controller,
5 | Delete,
6 | Get,
7 | HttpException,
8 | HttpStatus,
9 | NotFoundException,
10 | Param,
11 | Post,
12 | Put,
13 | Query,
14 | UploadedFile,
15 | UseInterceptors,
16 | } from '@nestjs/common';
17 | import { FileInterceptor } from '@nestjs/platform-express';
18 | import { Multer } from 'multer';
19 | import * as csvParser from 'csv-parser';
20 | import { Readable } from 'stream';
21 | import { PcsService } from './pcs.service';
22 | import { Pc } from './entities/pc.entity';
23 | import { UpdatePcDto } from './dto/update-pc.dto';
24 |
25 | @Controller('pcs')
26 | export class PcsController {
27 | constructor(private readonly pcsService: PcsService) {}
28 |
29 | @Post('/upload_file')
30 | @UseInterceptors(FileInterceptor('file'))
31 | async uploadFile(
32 | @UploadedFile() file: Multer.File,
33 | ): Promise<{ message: string; statusCode: number }> {
34 | try {
35 | const pcs = await this.parseCsvData(file.buffer);
36 | await this.pcsService.uploadComputersFromCsv(pcs);
37 | return {
38 | message: 'Upload successful',
39 | statusCode: HttpStatus.CREATED,
40 | };
41 | } catch (error) {
42 | console.error('Error uploading file:', error);
43 | throw new Error('Error uploading file');
44 | }
45 | }
46 |
47 | async parseCsvData(fileBuffer: Buffer): Promise {
48 | return new Promise((resolve, reject) => {
49 | const computers: any[] = [];
50 |
51 | // Create a readable stream from the buffer
52 | const bufferStream = new Readable();
53 | bufferStream.push(fileBuffer);
54 | bufferStream.push(null); // Mark the end of the stream
55 |
56 | // Create a CSV parser
57 | const parser = csvParser();
58 |
59 | // Parse the CSV data from the stream
60 | const csvStream = bufferStream.pipe(parser);
61 |
62 | csvStream
63 | .on('data', (data) => {
64 | computers.push(data);
65 | })
66 | .on('end', () => {
67 | resolve(computers);
68 | })
69 | .on('error', (error) => {
70 | reject(error);
71 | });
72 | });
73 | }
74 |
75 | @Get('get_pc_by_id/:id')
76 | async getPcById(@Param('id') id: number): Promise {
77 | try {
78 | const pc = await this.pcsService.getPcById(id);
79 | if (!pc) {
80 | throw new NotFoundException(`Pc with ID ${id} not found`);
81 | }
82 | return pc;
83 | } catch (error) {
84 | throw new HttpException(
85 | 'Failed to fetch Pc',
86 | HttpStatus.INTERNAL_SERVER_ERROR,
87 | );
88 | }
89 | }
90 |
91 | @Get('/get_all_pcs')
92 | async findAll(
93 | @Query('keyword') keyword?: string,
94 | @Query('pageNo') page: number = 1,
95 | @Query('pageSize') limit: number = 10,
96 | ): Promise<{ pcs: Pc[]; totalItems: number; totalPages: number }> {
97 | if (page < 1) {
98 | throw new BadRequestException(
99 | 'Page number must be greater than or equal to 1.',
100 | );
101 | }
102 |
103 | try {
104 | const result = await this.pcsService.findAll(keyword, page, limit);
105 |
106 | if (result.pcs.length === 0) {
107 | throw new NotFoundException('No record found.');
108 | }
109 |
110 | return result;
111 | } catch (error) {
112 | throw new HttpException(
113 | `Error while fetching computers: ${error.message}`,
114 | HttpStatus.NOT_FOUND,
115 | );
116 | }
117 | }
118 |
119 | @Put('update_pc_by_id/:id')
120 | async updatePc(
121 | @Param('id') id: number,
122 | @Body() updatePcDto: UpdatePcDto,
123 | ): Promise {
124 | try {
125 | // Call editPc method from the service to update the Pc entity
126 | const updatedPc = await this.pcsService.editPc(id, updatePcDto);
127 |
128 | // Return the updated Pc entity to the client
129 | return updatedPc;
130 | } catch (error) {
131 | // If an error occurs during the update operation, throw an internal server error
132 | throw new HttpException(
133 | 'Failed to update Pc',
134 | HttpStatus.INTERNAL_SERVER_ERROR,
135 | );
136 | }
137 | }
138 |
139 | @Delete('delete_pc_by_id/:id')
140 | async deletePc(
141 | @Param('id') id: number,
142 | ): Promise<{ message: string; statusCode: number }> {
143 | try {
144 | const pc = await this.pcsService.getPcById(id);
145 | if (!pc) {
146 | throw new NotFoundException(`Pc with ID ${id} not found`);
147 | }
148 | await this.pcsService.deletePc(id);
149 | return { message: 'Pc deleted successfully', statusCode: HttpStatus.OK };
150 | } catch (error) {
151 | throw new HttpException(
152 | 'Failed to delete Pc',
153 | HttpStatus.INTERNAL_SERVER_ERROR,
154 | );
155 | }
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/server/src/pcs/pcs.service.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Injectable,
3 | HttpException,
4 | HttpStatus,
5 | NotFoundException,
6 | } from '@nestjs/common';
7 | import { InjectRepository } from '@nestjs/typeorm';
8 | import { FindOneOptions, ILike, Repository } from 'typeorm';
9 | import { Pc } from './entities/pc.entity';
10 |
11 | @Injectable()
12 | export class PcsService {
13 | constructor(
14 | @InjectRepository(Pc)
15 | private pcRepository: Repository,
16 | ) {}
17 |
18 | async uploadComputersFromCsv(
19 | csvData: any[],
20 | ): Promise<{ message: string; statusCode: number }> {
21 | const computers: Partial[] = [];
22 |
23 | // Iterate over each row of the CSV data
24 | for (const data of csvData) {
25 | // Create a partial Computer object with the extracted properties from the CSV data
26 | const computer: Partial = {
27 | ram: data['8 GB'],
28 | storage_type: data['1 TB SSD'],
29 | storage_capacity: data['1 TB SSD'],
30 | usb_ports: data['2 x USB 3.0, 4 x USB 2.0'],
31 | gpu: data['NVIDIA GeForce GTX 770'],
32 | weight: data['8.1 kg'],
33 | psu_wattage: data['500 W PSU'],
34 | processor: data['Intel® Celeron™ N3050 Processor'],
35 | };
36 |
37 | // Push the partial Computer object to the array
38 | computers.push(computer);
39 | }
40 |
41 | // Call bulkCreate to save the computers to the database
42 | await this.bulkCreate(computers);
43 |
44 | return {
45 | message: 'Pc uploaded successfully.',
46 | statusCode: HttpStatus.OK,
47 | };
48 | }
49 |
50 | async bulkCreate(computers: Partial[]): Promise {
51 | await this.pcRepository.save(computers);
52 | }
53 |
54 | async findAll(
55 | keyword: string | undefined,
56 | page: number,
57 | pageSize: number,
58 | ): Promise<{ pcs: Pc[]; totalItems: number; totalPages: number }> {
59 | try {
60 | let whereCondition: any = {};
61 |
62 | if (keyword) {
63 | whereCondition = [
64 | { processor: ILike(`%${keyword}%`) },
65 | { gpu: ILike(`%${keyword}%`) },
66 | ];
67 | }
68 |
69 | const [pcs, totalItems] = await this.pcRepository.findAndCount({
70 | where: whereCondition,
71 | skip: (page - 1) * pageSize,
72 | take: pageSize,
73 | });
74 |
75 | if (pcs.length === 0) {
76 | throw new HttpException(
77 | 'No records found for the given search term',
78 | HttpStatus.NOT_FOUND,
79 | );
80 | }
81 |
82 | const totalPages = Math.ceil(totalItems / pageSize);
83 |
84 | return {
85 | pcs,
86 | totalItems,
87 | totalPages,
88 | };
89 | } catch (error) {
90 | throw new HttpException(
91 | `Error while retrieving computers: ${error.message}`,
92 | HttpStatus.INTERNAL_SERVER_ERROR,
93 | );
94 | }
95 | }
96 |
97 | async editPc(computerId: number, updatedPcData: Partial): Promise {
98 | try {
99 | // Fetch the Pc entity by ID
100 | const pc = await this.getPcById(computerId);
101 |
102 | // Merge the updated data into the existing Pc entity
103 | Object.assign(pc, updatedPcData);
104 |
105 | // Save the updated Pc entity
106 | return await this.pcRepository.save(pc);
107 | } catch (error) {
108 | throw new HttpException(
109 | 'Failed to update Pc',
110 | HttpStatus.INTERNAL_SERVER_ERROR,
111 | );
112 | }
113 | }
114 |
115 | async getPcById(computerId: number): Promise {
116 | try {
117 | // Define the options to retrieve only required fields
118 | const options: FindOneOptions = {
119 | where: { computer_id: computerId },
120 | select: [
121 | 'computer_id',
122 | 'ram',
123 | 'storage_type',
124 | 'storage_capacity',
125 | 'usb_ports',
126 | 'gpu',
127 | 'weight',
128 | 'psu_wattage',
129 | 'processor',
130 | ],
131 | };
132 |
133 | // Fetch the Pc entity using findOne method with options
134 | const pc = await this.pcRepository.findOne(options);
135 |
136 | // If Pc entity not found, throw NotFoundException
137 | if (!pc) {
138 | throw new NotFoundException(`Pc with ID ${computerId} not found`);
139 | }
140 |
141 | return pc;
142 | } catch (error) {
143 | // If any error occurs, throw HttpException with appropriate status
144 | throw new HttpException('Failed to fetch Pc by ID', HttpStatus.NOT_FOUND);
145 | }
146 | }
147 |
148 | async deletePc(id: number): Promise {
149 | try {
150 | await this.pcRepository.delete(id);
151 | } catch (error) {
152 | throw new HttpException(
153 | 'Failed to delete Pc',
154 | HttpStatus.INTERNAL_SERVER_ERROR,
155 | );
156 | }
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/app/src/pages/pc/[id].tsx:
--------------------------------------------------------------------------------
1 | import { useRouter } from "next/router";
2 | import React, { useEffect, useState } from "react";
3 | import { fetchData, putData } from "../../../utils/fetchService";
4 | import { getById, updateById } from "../../../utils/config";
5 | import { EditComputerPc } from "../../../models/computers/computers.interface";
6 |
7 | export default function Computer() {
8 | const router = useRouter();
9 | const { id } = router.query;
10 | const [isLoading, setIsLoading] = useState(true);
11 |
12 | const [formData, setFormData] = useState({
13 | ram: "",
14 | storage_type: "",
15 | storage_capacity: "",
16 | usb_ports: "",
17 | gpu: "",
18 | weight: "",
19 | psu_wattage: "",
20 | processor: "",
21 | });
22 |
23 | useEffect(() => {
24 | const fetchDataFromApis = async () => {
25 | try {
26 | if (id !== undefined) {
27 | const idToFetch = Array.isArray(id) ? id[0] : id;
28 | const idNumber = parseInt(idToFetch, 10);
29 |
30 | if (!isNaN(idNumber)) {
31 | const data = await fetchData(`${getById}/${id}`);
32 | setIsLoading(false);
33 |
34 | if (data) {
35 | setFormData(data);
36 | }
37 | }
38 | }
39 | } catch (error) {
40 | setIsLoading(false);
41 | }
42 | };
43 | fetchDataFromApis();
44 | }, [id]);
45 |
46 | const handleInputChange = (e: React.ChangeEvent) => {
47 | const { name, value } = e.target;
48 | setFormData({
49 | ...formData,
50 | [name]: value,
51 | });
52 | };
53 |
54 | const handleUpdate = async (e: React.FormEvent) => {
55 | e.preventDefault();
56 | try {
57 | const response = await putData(`${updateById}/${id}`, formData);
58 |
59 | if (response) {
60 | await router.push("/");
61 | }
62 | } catch (error) {
63 | console.error("Update failed:", error);
64 | }
65 | };
66 |
67 | if (isLoading) {
68 | return Loading...
;
69 | }
70 |
71 | return (
72 |
73 |
74 |
75 | Edit Specification
76 |
77 |
202 |
203 |
204 | );
205 | }
206 |
--------------------------------------------------------------------------------
/app/src/pages/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect, useContext } from "react";
2 | import ComputerCard from "./components/ComputerCard";
3 | import AdminContext from "../../context/AdminContext";
4 | import { deleteData, fetchData, postData } from "../../utils/fetchService";
5 | import { addPc, deleteById, getAllPcs } from "../../utils/config";
6 | import { ComputerRoot } from "../../models/computers/computers.interface";
7 | import Pagination from "./components/Pagination";
8 | import { AxiosError } from "axios";
9 |
10 | export default function Home() {
11 | const [pageNo, setPageNo] = useState(1);
12 | const pageSize = 10;
13 | const adminContext = useContext(AdminContext);
14 | if (!adminContext) {
15 | return null;
16 | }
17 | const { updateState, setUpdateState } = adminContext;
18 |
19 | const [isLoading, setIsLoading] = useState(true);
20 | const [searchQuery, setSearchQuery] = useState("");
21 | const [allSpecifications, setAllSpecifications] =
22 | useState(null);
23 | const [totalPages, setTotalPages] = useState(1);
24 | const [file, setFile] = useState(null);
25 | const [successMessage, setSuccessMessage] = useState(null);
26 | const [errorMessage, setErrorMessage] = useState(null);
27 |
28 | useEffect(() => {
29 | const fetchDataFromApis = async () => {
30 | try {
31 | const queryParams = [`pageNo=${pageNo}`, `pageSize=${pageSize}`];
32 |
33 | if (searchQuery) {
34 | // Encode special characters, except for spaces
35 | const encodedKeyword = encodeURIComponent(searchQuery);
36 | queryParams.push(`keyword=${encodedKeyword}`);
37 | }
38 |
39 | const queryString = queryParams.join("&");
40 |
41 | const data = await fetchData(
42 | `${getAllPcs}?${queryString}`
43 | );
44 | setAllSpecifications(data);
45 | setTotalPages(Math.ceil(data?.totalItems / pageSize));
46 |
47 | setUpdateState(false);
48 | setIsLoading(false);
49 | } catch (error) {
50 | if ((error as AxiosError).response?.status === 404) {
51 | setAllSpecifications(null);
52 | } else {
53 | console.error("Error fetching data:", error);
54 | }
55 | setIsLoading(false);
56 | }
57 | };
58 |
59 | fetchDataFromApis();
60 | }, [updateState, pageNo, searchQuery]);
61 |
62 | const handleDelete = async (id: number) => {
63 | try {
64 | const response = await deleteData(`${deleteById}/${id}`);
65 |
66 | if (response) {
67 | setUpdateState(true);
68 | setSuccessMessage("Data deleted successfully");
69 | setTimeout(() => {
70 | setSuccessMessage(null);
71 | }, 5000);
72 | }
73 | } catch (error) {
74 | console.error("Error deleting data:", error);
75 | setErrorMessage("Error deleting data");
76 | setTimeout(() => {
77 | setErrorMessage(null);
78 | }, 5000);
79 | }
80 | };
81 |
82 | const handleFileChange = (event: React.ChangeEvent) => {
83 | const files = event.target.files;
84 | if (files && files.length > 0) {
85 | setFile(files[0]);
86 | }
87 | };
88 |
89 | const handleUpload = async () => {
90 | if (file) {
91 | const formData = new FormData();
92 | formData.append("file", file);
93 |
94 | try {
95 | const response = await postData(addPc, formData);
96 | if (response) {
97 | setSuccessMessage("File uploaded successfully");
98 | setUpdateState(true);
99 | setTimeout(() => {
100 | setSuccessMessage(null);
101 | }, 5000);
102 | }
103 | } catch (error) {
104 | setErrorMessage("Error uploading file");
105 | console.error("Error uploading file:", error);
106 | setTimeout(() => {
107 | setErrorMessage(null);
108 | }, 5000);
109 | } finally {
110 | setFile(null);
111 | }
112 | } else {
113 | setErrorMessage("File is undefined");
114 | setTimeout(() => {
115 | setErrorMessage(null);
116 | }, 5000);
117 | }
118 | };
119 |
120 | const handleSearch = (query: string) => {
121 | setPageNo(1);
122 | setSearchQuery(query);
123 | };
124 |
125 | const handlePageChange = (newPage: number) => {
126 | setPageNo(newPage);
127 | };
128 |
129 | return (
130 |
131 |
132 |
133 | Check.com
134 |
135 | <>
136 | {isLoading ? (
137 |
Loading...
138 | ) : (
139 |
140 |
handleSearch(e.target.value)}
145 | placeholder="Search by Processor or GPU..."
146 | />
147 |
148 |
154 |
160 |
161 | {successMessage && (
162 |
163 | {successMessage}
164 |
165 | )}
166 | {errorMessage && (
167 |
168 | {errorMessage}
169 |
170 | )}
171 |
172 |
173 | {!allSpecifications?.pcs.length ? (
174 |
175 | No record found
176 |
177 | ) : (
178 |
179 | {allSpecifications?.pcs.map((computer) => (
180 |
184 |
193 |
194 | ))}
195 |
196 | )}
197 |
198 | {allSpecifications?.pcs.length && (
199 |
206 | )}
207 |
208 | )}
209 | >
210 |
211 |
212 | );
213 | }
214 |
--------------------------------------------------------------------------------
/app/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "devtestapp",
3 | "version": "0.1.0",
4 | "lockfileVersion": 3,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "devtestapp",
9 | "version": "0.1.0",
10 | "dependencies": {
11 | "axios": "^1.6.7",
12 | "next": "14.1.0",
13 | "react": "^18",
14 | "react-dom": "^18",
15 | "react-icons": "^5.0.1"
16 | },
17 | "devDependencies": {
18 | "@types/node": "^20",
19 | "@types/react": "^18",
20 | "@types/react-dom": "^18",
21 | "autoprefixer": "^10.0.1",
22 | "postcss": "^8",
23 | "tailwindcss": "^3.3.0",
24 | "typescript": "^5"
25 | }
26 | },
27 | "node_modules/@alloc/quick-lru": {
28 | "version": "5.2.0",
29 | "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
30 | "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
31 | "dev": true,
32 | "engines": {
33 | "node": ">=10"
34 | },
35 | "funding": {
36 | "url": "https://github.com/sponsors/sindresorhus"
37 | }
38 | },
39 | "node_modules/@isaacs/cliui": {
40 | "version": "8.0.2",
41 | "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
42 | "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
43 | "dev": true,
44 | "dependencies": {
45 | "string-width": "^5.1.2",
46 | "string-width-cjs": "npm:string-width@^4.2.0",
47 | "strip-ansi": "^7.0.1",
48 | "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
49 | "wrap-ansi": "^8.1.0",
50 | "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
51 | },
52 | "engines": {
53 | "node": ">=12"
54 | }
55 | },
56 | "node_modules/@jridgewell/gen-mapping": {
57 | "version": "0.3.3",
58 | "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
59 | "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
60 | "dev": true,
61 | "dependencies": {
62 | "@jridgewell/set-array": "^1.0.1",
63 | "@jridgewell/sourcemap-codec": "^1.4.10",
64 | "@jridgewell/trace-mapping": "^0.3.9"
65 | },
66 | "engines": {
67 | "node": ">=6.0.0"
68 | }
69 | },
70 | "node_modules/@jridgewell/resolve-uri": {
71 | "version": "3.1.1",
72 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
73 | "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
74 | "dev": true,
75 | "engines": {
76 | "node": ">=6.0.0"
77 | }
78 | },
79 | "node_modules/@jridgewell/set-array": {
80 | "version": "1.1.2",
81 | "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
82 | "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
83 | "dev": true,
84 | "engines": {
85 | "node": ">=6.0.0"
86 | }
87 | },
88 | "node_modules/@jridgewell/sourcemap-codec": {
89 | "version": "1.4.15",
90 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
91 | "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
92 | "dev": true
93 | },
94 | "node_modules/@jridgewell/trace-mapping": {
95 | "version": "0.3.22",
96 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz",
97 | "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==",
98 | "dev": true,
99 | "dependencies": {
100 | "@jridgewell/resolve-uri": "^3.1.0",
101 | "@jridgewell/sourcemap-codec": "^1.4.14"
102 | }
103 | },
104 | "node_modules/@next/env": {
105 | "version": "14.1.0",
106 | "resolved": "https://registry.npmjs.org/@next/env/-/env-14.1.0.tgz",
107 | "integrity": "sha512-Py8zIo+02ht82brwwhTg36iogzFqGLPXlRGKQw5s+qP/kMNc4MAyDeEwBKDijk6zTIbegEgu8Qy7C1LboslQAw=="
108 | },
109 | "node_modules/@next/swc-darwin-arm64": {
110 | "version": "14.1.0",
111 | "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.1.0.tgz",
112 | "integrity": "sha512-nUDn7TOGcIeyQni6lZHfzNoo9S0euXnu0jhsbMOmMJUBfgsnESdjN97kM7cBqQxZa8L/bM9om/S5/1dzCrW6wQ==",
113 | "cpu": [
114 | "arm64"
115 | ],
116 | "optional": true,
117 | "os": [
118 | "darwin"
119 | ],
120 | "engines": {
121 | "node": ">= 10"
122 | }
123 | },
124 | "node_modules/@nodelib/fs.scandir": {
125 | "version": "2.1.5",
126 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
127 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
128 | "dev": true,
129 | "dependencies": {
130 | "@nodelib/fs.stat": "2.0.5",
131 | "run-parallel": "^1.1.9"
132 | },
133 | "engines": {
134 | "node": ">= 8"
135 | }
136 | },
137 | "node_modules/@nodelib/fs.stat": {
138 | "version": "2.0.5",
139 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
140 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
141 | "dev": true,
142 | "engines": {
143 | "node": ">= 8"
144 | }
145 | },
146 | "node_modules/@nodelib/fs.walk": {
147 | "version": "1.2.8",
148 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
149 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
150 | "dev": true,
151 | "dependencies": {
152 | "@nodelib/fs.scandir": "2.1.5",
153 | "fastq": "^1.6.0"
154 | },
155 | "engines": {
156 | "node": ">= 8"
157 | }
158 | },
159 | "node_modules/@pkgjs/parseargs": {
160 | "version": "0.11.0",
161 | "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
162 | "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
163 | "dev": true,
164 | "optional": true,
165 | "engines": {
166 | "node": ">=14"
167 | }
168 | },
169 | "node_modules/@swc/helpers": {
170 | "version": "0.5.2",
171 | "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.2.tgz",
172 | "integrity": "sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==",
173 | "dependencies": {
174 | "tslib": "^2.4.0"
175 | }
176 | },
177 | "node_modules/@types/node": {
178 | "version": "20.11.17",
179 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.17.tgz",
180 | "integrity": "sha512-QmgQZGWu1Yw9TDyAP9ZzpFJKynYNeOvwMJmaxABfieQoVoiVOS6MN1WSpqpRcbeA5+RW82kraAVxCCJg+780Qw==",
181 | "dev": true,
182 | "dependencies": {
183 | "undici-types": "~5.26.4"
184 | }
185 | },
186 | "node_modules/@types/prop-types": {
187 | "version": "15.7.11",
188 | "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz",
189 | "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==",
190 | "dev": true
191 | },
192 | "node_modules/@types/react": {
193 | "version": "18.2.55",
194 | "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.55.tgz",
195 | "integrity": "sha512-Y2Tz5P4yz23brwm2d7jNon39qoAtMMmalOQv6+fEFt1mT+FcM3D841wDpoUvFXhaYenuROCy3FZYqdTjM7qVyA==",
196 | "dev": true,
197 | "dependencies": {
198 | "@types/prop-types": "*",
199 | "@types/scheduler": "*",
200 | "csstype": "^3.0.2"
201 | }
202 | },
203 | "node_modules/@types/react-dom": {
204 | "version": "18.2.19",
205 | "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.19.tgz",
206 | "integrity": "sha512-aZvQL6uUbIJpjZk4U8JZGbau9KDeAwMfmhyWorxgBkqDIEf6ROjRozcmPIicqsUwPUjbkDfHKgGee1Lq65APcA==",
207 | "dev": true,
208 | "dependencies": {
209 | "@types/react": "*"
210 | }
211 | },
212 | "node_modules/@types/scheduler": {
213 | "version": "0.16.8",
214 | "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz",
215 | "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==",
216 | "dev": true
217 | },
218 | "node_modules/ansi-regex": {
219 | "version": "6.0.1",
220 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
221 | "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
222 | "dev": true,
223 | "engines": {
224 | "node": ">=12"
225 | },
226 | "funding": {
227 | "url": "https://github.com/chalk/ansi-regex?sponsor=1"
228 | }
229 | },
230 | "node_modules/ansi-styles": {
231 | "version": "6.2.1",
232 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
233 | "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
234 | "dev": true,
235 | "engines": {
236 | "node": ">=12"
237 | },
238 | "funding": {
239 | "url": "https://github.com/chalk/ansi-styles?sponsor=1"
240 | }
241 | },
242 | "node_modules/any-promise": {
243 | "version": "1.3.0",
244 | "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
245 | "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
246 | "dev": true
247 | },
248 | "node_modules/anymatch": {
249 | "version": "3.1.3",
250 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
251 | "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
252 | "dev": true,
253 | "dependencies": {
254 | "normalize-path": "^3.0.0",
255 | "picomatch": "^2.0.4"
256 | },
257 | "engines": {
258 | "node": ">= 8"
259 | }
260 | },
261 | "node_modules/arg": {
262 | "version": "5.0.2",
263 | "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
264 | "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
265 | "dev": true
266 | },
267 | "node_modules/asynckit": {
268 | "version": "0.4.0",
269 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
270 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
271 | },
272 | "node_modules/autoprefixer": {
273 | "version": "10.4.17",
274 | "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.17.tgz",
275 | "integrity": "sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg==",
276 | "dev": true,
277 | "funding": [
278 | {
279 | "type": "opencollective",
280 | "url": "https://opencollective.com/postcss/"
281 | },
282 | {
283 | "type": "tidelift",
284 | "url": "https://tidelift.com/funding/github/npm/autoprefixer"
285 | },
286 | {
287 | "type": "github",
288 | "url": "https://github.com/sponsors/ai"
289 | }
290 | ],
291 | "dependencies": {
292 | "browserslist": "^4.22.2",
293 | "caniuse-lite": "^1.0.30001578",
294 | "fraction.js": "^4.3.7",
295 | "normalize-range": "^0.1.2",
296 | "picocolors": "^1.0.0",
297 | "postcss-value-parser": "^4.2.0"
298 | },
299 | "bin": {
300 | "autoprefixer": "bin/autoprefixer"
301 | },
302 | "engines": {
303 | "node": "^10 || ^12 || >=14"
304 | },
305 | "peerDependencies": {
306 | "postcss": "^8.1.0"
307 | }
308 | },
309 | "node_modules/axios": {
310 | "version": "1.6.7",
311 | "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz",
312 | "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==",
313 | "dependencies": {
314 | "follow-redirects": "^1.15.4",
315 | "form-data": "^4.0.0",
316 | "proxy-from-env": "^1.1.0"
317 | }
318 | },
319 | "node_modules/balanced-match": {
320 | "version": "1.0.2",
321 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
322 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
323 | "dev": true
324 | },
325 | "node_modules/binary-extensions": {
326 | "version": "2.2.0",
327 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
328 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
329 | "dev": true,
330 | "engines": {
331 | "node": ">=8"
332 | }
333 | },
334 | "node_modules/brace-expansion": {
335 | "version": "2.0.1",
336 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
337 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
338 | "dev": true,
339 | "dependencies": {
340 | "balanced-match": "^1.0.0"
341 | }
342 | },
343 | "node_modules/braces": {
344 | "version": "3.0.2",
345 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
346 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
347 | "dev": true,
348 | "dependencies": {
349 | "fill-range": "^7.0.1"
350 | },
351 | "engines": {
352 | "node": ">=8"
353 | }
354 | },
355 | "node_modules/browserslist": {
356 | "version": "4.22.3",
357 | "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz",
358 | "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==",
359 | "dev": true,
360 | "funding": [
361 | {
362 | "type": "opencollective",
363 | "url": "https://opencollective.com/browserslist"
364 | },
365 | {
366 | "type": "tidelift",
367 | "url": "https://tidelift.com/funding/github/npm/browserslist"
368 | },
369 | {
370 | "type": "github",
371 | "url": "https://github.com/sponsors/ai"
372 | }
373 | ],
374 | "dependencies": {
375 | "caniuse-lite": "^1.0.30001580",
376 | "electron-to-chromium": "^1.4.648",
377 | "node-releases": "^2.0.14",
378 | "update-browserslist-db": "^1.0.13"
379 | },
380 | "bin": {
381 | "browserslist": "cli.js"
382 | },
383 | "engines": {
384 | "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
385 | }
386 | },
387 | "node_modules/busboy": {
388 | "version": "1.6.0",
389 | "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
390 | "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
391 | "dependencies": {
392 | "streamsearch": "^1.1.0"
393 | },
394 | "engines": {
395 | "node": ">=10.16.0"
396 | }
397 | },
398 | "node_modules/camelcase-css": {
399 | "version": "2.0.1",
400 | "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
401 | "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
402 | "dev": true,
403 | "engines": {
404 | "node": ">= 6"
405 | }
406 | },
407 | "node_modules/caniuse-lite": {
408 | "version": "1.0.30001587",
409 | "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001587.tgz",
410 | "integrity": "sha512-HMFNotUmLXn71BQxg8cijvqxnIAofforZOwGsxyXJ0qugTdspUF4sPSJ2vhgprHCB996tIDzEq1ubumPDV8ULA==",
411 | "funding": [
412 | {
413 | "type": "opencollective",
414 | "url": "https://opencollective.com/browserslist"
415 | },
416 | {
417 | "type": "tidelift",
418 | "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
419 | },
420 | {
421 | "type": "github",
422 | "url": "https://github.com/sponsors/ai"
423 | }
424 | ]
425 | },
426 | "node_modules/chokidar": {
427 | "version": "3.6.0",
428 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
429 | "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
430 | "dev": true,
431 | "dependencies": {
432 | "anymatch": "~3.1.2",
433 | "braces": "~3.0.2",
434 | "glob-parent": "~5.1.2",
435 | "is-binary-path": "~2.1.0",
436 | "is-glob": "~4.0.1",
437 | "normalize-path": "~3.0.0",
438 | "readdirp": "~3.6.0"
439 | },
440 | "engines": {
441 | "node": ">= 8.10.0"
442 | },
443 | "funding": {
444 | "url": "https://paulmillr.com/funding/"
445 | },
446 | "optionalDependencies": {
447 | "fsevents": "~2.3.2"
448 | }
449 | },
450 | "node_modules/chokidar/node_modules/glob-parent": {
451 | "version": "5.1.2",
452 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
453 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
454 | "dev": true,
455 | "dependencies": {
456 | "is-glob": "^4.0.1"
457 | },
458 | "engines": {
459 | "node": ">= 6"
460 | }
461 | },
462 | "node_modules/client-only": {
463 | "version": "0.0.1",
464 | "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
465 | "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
466 | },
467 | "node_modules/color-convert": {
468 | "version": "2.0.1",
469 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
470 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
471 | "dev": true,
472 | "dependencies": {
473 | "color-name": "~1.1.4"
474 | },
475 | "engines": {
476 | "node": ">=7.0.0"
477 | }
478 | },
479 | "node_modules/color-name": {
480 | "version": "1.1.4",
481 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
482 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
483 | "dev": true
484 | },
485 | "node_modules/combined-stream": {
486 | "version": "1.0.8",
487 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
488 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
489 | "dependencies": {
490 | "delayed-stream": "~1.0.0"
491 | },
492 | "engines": {
493 | "node": ">= 0.8"
494 | }
495 | },
496 | "node_modules/commander": {
497 | "version": "4.1.1",
498 | "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
499 | "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
500 | "dev": true,
501 | "engines": {
502 | "node": ">= 6"
503 | }
504 | },
505 | "node_modules/cross-spawn": {
506 | "version": "7.0.3",
507 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
508 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
509 | "dev": true,
510 | "dependencies": {
511 | "path-key": "^3.1.0",
512 | "shebang-command": "^2.0.0",
513 | "which": "^2.0.1"
514 | },
515 | "engines": {
516 | "node": ">= 8"
517 | }
518 | },
519 | "node_modules/cssesc": {
520 | "version": "3.0.0",
521 | "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
522 | "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
523 | "dev": true,
524 | "bin": {
525 | "cssesc": "bin/cssesc"
526 | },
527 | "engines": {
528 | "node": ">=4"
529 | }
530 | },
531 | "node_modules/csstype": {
532 | "version": "3.1.3",
533 | "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
534 | "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
535 | "dev": true
536 | },
537 | "node_modules/delayed-stream": {
538 | "version": "1.0.0",
539 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
540 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
541 | "engines": {
542 | "node": ">=0.4.0"
543 | }
544 | },
545 | "node_modules/didyoumean": {
546 | "version": "1.2.2",
547 | "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
548 | "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
549 | "dev": true
550 | },
551 | "node_modules/dlv": {
552 | "version": "1.1.3",
553 | "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
554 | "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
555 | "dev": true
556 | },
557 | "node_modules/eastasianwidth": {
558 | "version": "0.2.0",
559 | "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
560 | "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
561 | "dev": true
562 | },
563 | "node_modules/electron-to-chromium": {
564 | "version": "1.4.665",
565 | "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.665.tgz",
566 | "integrity": "sha512-UpyCWObBoD+nSZgOC2ToaIdZB0r9GhqT2WahPKiSki6ckkSuKhQNso8V2PrFcHBMleI/eqbKgVQgVC4Wni4ilw==",
567 | "dev": true
568 | },
569 | "node_modules/emoji-regex": {
570 | "version": "9.2.2",
571 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
572 | "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
573 | "dev": true
574 | },
575 | "node_modules/escalade": {
576 | "version": "3.1.2",
577 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
578 | "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
579 | "dev": true,
580 | "engines": {
581 | "node": ">=6"
582 | }
583 | },
584 | "node_modules/fast-glob": {
585 | "version": "3.3.2",
586 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
587 | "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
588 | "dev": true,
589 | "dependencies": {
590 | "@nodelib/fs.stat": "^2.0.2",
591 | "@nodelib/fs.walk": "^1.2.3",
592 | "glob-parent": "^5.1.2",
593 | "merge2": "^1.3.0",
594 | "micromatch": "^4.0.4"
595 | },
596 | "engines": {
597 | "node": ">=8.6.0"
598 | }
599 | },
600 | "node_modules/fast-glob/node_modules/glob-parent": {
601 | "version": "5.1.2",
602 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
603 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
604 | "dev": true,
605 | "dependencies": {
606 | "is-glob": "^4.0.1"
607 | },
608 | "engines": {
609 | "node": ">= 6"
610 | }
611 | },
612 | "node_modules/fastq": {
613 | "version": "1.17.1",
614 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
615 | "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
616 | "dev": true,
617 | "dependencies": {
618 | "reusify": "^1.0.4"
619 | }
620 | },
621 | "node_modules/fill-range": {
622 | "version": "7.0.1",
623 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
624 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
625 | "dev": true,
626 | "dependencies": {
627 | "to-regex-range": "^5.0.1"
628 | },
629 | "engines": {
630 | "node": ">=8"
631 | }
632 | },
633 | "node_modules/follow-redirects": {
634 | "version": "1.15.5",
635 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz",
636 | "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==",
637 | "funding": [
638 | {
639 | "type": "individual",
640 | "url": "https://github.com/sponsors/RubenVerborgh"
641 | }
642 | ],
643 | "engines": {
644 | "node": ">=4.0"
645 | },
646 | "peerDependenciesMeta": {
647 | "debug": {
648 | "optional": true
649 | }
650 | }
651 | },
652 | "node_modules/foreground-child": {
653 | "version": "3.1.1",
654 | "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
655 | "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
656 | "dev": true,
657 | "dependencies": {
658 | "cross-spawn": "^7.0.0",
659 | "signal-exit": "^4.0.1"
660 | },
661 | "engines": {
662 | "node": ">=14"
663 | },
664 | "funding": {
665 | "url": "https://github.com/sponsors/isaacs"
666 | }
667 | },
668 | "node_modules/form-data": {
669 | "version": "4.0.0",
670 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
671 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
672 | "dependencies": {
673 | "asynckit": "^0.4.0",
674 | "combined-stream": "^1.0.8",
675 | "mime-types": "^2.1.12"
676 | },
677 | "engines": {
678 | "node": ">= 6"
679 | }
680 | },
681 | "node_modules/fraction.js": {
682 | "version": "4.3.7",
683 | "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
684 | "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==",
685 | "dev": true,
686 | "engines": {
687 | "node": "*"
688 | },
689 | "funding": {
690 | "type": "patreon",
691 | "url": "https://github.com/sponsors/rawify"
692 | }
693 | },
694 | "node_modules/fsevents": {
695 | "version": "2.3.3",
696 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
697 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
698 | "dev": true,
699 | "hasInstallScript": true,
700 | "optional": true,
701 | "os": [
702 | "darwin"
703 | ],
704 | "engines": {
705 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
706 | }
707 | },
708 | "node_modules/function-bind": {
709 | "version": "1.1.2",
710 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
711 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
712 | "dev": true,
713 | "funding": {
714 | "url": "https://github.com/sponsors/ljharb"
715 | }
716 | },
717 | "node_modules/glob": {
718 | "version": "10.3.10",
719 | "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
720 | "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
721 | "dev": true,
722 | "dependencies": {
723 | "foreground-child": "^3.1.0",
724 | "jackspeak": "^2.3.5",
725 | "minimatch": "^9.0.1",
726 | "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
727 | "path-scurry": "^1.10.1"
728 | },
729 | "bin": {
730 | "glob": "dist/esm/bin.mjs"
731 | },
732 | "engines": {
733 | "node": ">=16 || 14 >=14.17"
734 | },
735 | "funding": {
736 | "url": "https://github.com/sponsors/isaacs"
737 | }
738 | },
739 | "node_modules/glob-parent": {
740 | "version": "6.0.2",
741 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
742 | "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
743 | "dev": true,
744 | "dependencies": {
745 | "is-glob": "^4.0.3"
746 | },
747 | "engines": {
748 | "node": ">=10.13.0"
749 | }
750 | },
751 | "node_modules/graceful-fs": {
752 | "version": "4.2.11",
753 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
754 | "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
755 | },
756 | "node_modules/hasown": {
757 | "version": "2.0.1",
758 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz",
759 | "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==",
760 | "dev": true,
761 | "dependencies": {
762 | "function-bind": "^1.1.2"
763 | },
764 | "engines": {
765 | "node": ">= 0.4"
766 | }
767 | },
768 | "node_modules/is-binary-path": {
769 | "version": "2.1.0",
770 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
771 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
772 | "dev": true,
773 | "dependencies": {
774 | "binary-extensions": "^2.0.0"
775 | },
776 | "engines": {
777 | "node": ">=8"
778 | }
779 | },
780 | "node_modules/is-core-module": {
781 | "version": "2.13.1",
782 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
783 | "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
784 | "dev": true,
785 | "dependencies": {
786 | "hasown": "^2.0.0"
787 | },
788 | "funding": {
789 | "url": "https://github.com/sponsors/ljharb"
790 | }
791 | },
792 | "node_modules/is-extglob": {
793 | "version": "2.1.1",
794 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
795 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
796 | "dev": true,
797 | "engines": {
798 | "node": ">=0.10.0"
799 | }
800 | },
801 | "node_modules/is-fullwidth-code-point": {
802 | "version": "3.0.0",
803 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
804 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
805 | "dev": true,
806 | "engines": {
807 | "node": ">=8"
808 | }
809 | },
810 | "node_modules/is-glob": {
811 | "version": "4.0.3",
812 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
813 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
814 | "dev": true,
815 | "dependencies": {
816 | "is-extglob": "^2.1.1"
817 | },
818 | "engines": {
819 | "node": ">=0.10.0"
820 | }
821 | },
822 | "node_modules/is-number": {
823 | "version": "7.0.0",
824 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
825 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
826 | "dev": true,
827 | "engines": {
828 | "node": ">=0.12.0"
829 | }
830 | },
831 | "node_modules/isexe": {
832 | "version": "2.0.0",
833 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
834 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
835 | "dev": true
836 | },
837 | "node_modules/jackspeak": {
838 | "version": "2.3.6",
839 | "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
840 | "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
841 | "dev": true,
842 | "dependencies": {
843 | "@isaacs/cliui": "^8.0.2"
844 | },
845 | "engines": {
846 | "node": ">=14"
847 | },
848 | "funding": {
849 | "url": "https://github.com/sponsors/isaacs"
850 | },
851 | "optionalDependencies": {
852 | "@pkgjs/parseargs": "^0.11.0"
853 | }
854 | },
855 | "node_modules/jiti": {
856 | "version": "1.21.0",
857 | "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz",
858 | "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==",
859 | "dev": true,
860 | "bin": {
861 | "jiti": "bin/jiti.js"
862 | }
863 | },
864 | "node_modules/js-tokens": {
865 | "version": "4.0.0",
866 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
867 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
868 | },
869 | "node_modules/lilconfig": {
870 | "version": "2.1.0",
871 | "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
872 | "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
873 | "dev": true,
874 | "engines": {
875 | "node": ">=10"
876 | }
877 | },
878 | "node_modules/lines-and-columns": {
879 | "version": "1.2.4",
880 | "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
881 | "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
882 | "dev": true
883 | },
884 | "node_modules/loose-envify": {
885 | "version": "1.4.0",
886 | "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
887 | "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
888 | "dependencies": {
889 | "js-tokens": "^3.0.0 || ^4.0.0"
890 | },
891 | "bin": {
892 | "loose-envify": "cli.js"
893 | }
894 | },
895 | "node_modules/lru-cache": {
896 | "version": "10.2.0",
897 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz",
898 | "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==",
899 | "dev": true,
900 | "engines": {
901 | "node": "14 || >=16.14"
902 | }
903 | },
904 | "node_modules/merge2": {
905 | "version": "1.4.1",
906 | "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
907 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
908 | "dev": true,
909 | "engines": {
910 | "node": ">= 8"
911 | }
912 | },
913 | "node_modules/micromatch": {
914 | "version": "4.0.5",
915 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
916 | "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
917 | "dev": true,
918 | "dependencies": {
919 | "braces": "^3.0.2",
920 | "picomatch": "^2.3.1"
921 | },
922 | "engines": {
923 | "node": ">=8.6"
924 | }
925 | },
926 | "node_modules/mime-db": {
927 | "version": "1.52.0",
928 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
929 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
930 | "engines": {
931 | "node": ">= 0.6"
932 | }
933 | },
934 | "node_modules/mime-types": {
935 | "version": "2.1.35",
936 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
937 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
938 | "dependencies": {
939 | "mime-db": "1.52.0"
940 | },
941 | "engines": {
942 | "node": ">= 0.6"
943 | }
944 | },
945 | "node_modules/minimatch": {
946 | "version": "9.0.3",
947 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
948 | "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
949 | "dev": true,
950 | "dependencies": {
951 | "brace-expansion": "^2.0.1"
952 | },
953 | "engines": {
954 | "node": ">=16 || 14 >=14.17"
955 | },
956 | "funding": {
957 | "url": "https://github.com/sponsors/isaacs"
958 | }
959 | },
960 | "node_modules/minipass": {
961 | "version": "7.0.4",
962 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
963 | "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
964 | "dev": true,
965 | "engines": {
966 | "node": ">=16 || 14 >=14.17"
967 | }
968 | },
969 | "node_modules/mz": {
970 | "version": "2.7.0",
971 | "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
972 | "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
973 | "dev": true,
974 | "dependencies": {
975 | "any-promise": "^1.0.0",
976 | "object-assign": "^4.0.1",
977 | "thenify-all": "^1.0.0"
978 | }
979 | },
980 | "node_modules/nanoid": {
981 | "version": "3.3.7",
982 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
983 | "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
984 | "funding": [
985 | {
986 | "type": "github",
987 | "url": "https://github.com/sponsors/ai"
988 | }
989 | ],
990 | "bin": {
991 | "nanoid": "bin/nanoid.cjs"
992 | },
993 | "engines": {
994 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
995 | }
996 | },
997 | "node_modules/next": {
998 | "version": "14.1.0",
999 | "resolved": "https://registry.npmjs.org/next/-/next-14.1.0.tgz",
1000 | "integrity": "sha512-wlzrsbfeSU48YQBjZhDzOwhWhGsy+uQycR8bHAOt1LY1bn3zZEcDyHQOEoN3aWzQ8LHCAJ1nqrWCc9XF2+O45Q==",
1001 | "dependencies": {
1002 | "@next/env": "14.1.0",
1003 | "@swc/helpers": "0.5.2",
1004 | "busboy": "1.6.0",
1005 | "caniuse-lite": "^1.0.30001579",
1006 | "graceful-fs": "^4.2.11",
1007 | "postcss": "8.4.31",
1008 | "styled-jsx": "5.1.1"
1009 | },
1010 | "bin": {
1011 | "next": "dist/bin/next"
1012 | },
1013 | "engines": {
1014 | "node": ">=18.17.0"
1015 | },
1016 | "optionalDependencies": {
1017 | "@next/swc-darwin-arm64": "14.1.0",
1018 | "@next/swc-darwin-x64": "14.1.0",
1019 | "@next/swc-linux-arm64-gnu": "14.1.0",
1020 | "@next/swc-linux-arm64-musl": "14.1.0",
1021 | "@next/swc-linux-x64-gnu": "14.1.0",
1022 | "@next/swc-linux-x64-musl": "14.1.0",
1023 | "@next/swc-win32-arm64-msvc": "14.1.0",
1024 | "@next/swc-win32-ia32-msvc": "14.1.0",
1025 | "@next/swc-win32-x64-msvc": "14.1.0"
1026 | },
1027 | "peerDependencies": {
1028 | "@opentelemetry/api": "^1.1.0",
1029 | "react": "^18.2.0",
1030 | "react-dom": "^18.2.0",
1031 | "sass": "^1.3.0"
1032 | },
1033 | "peerDependenciesMeta": {
1034 | "@opentelemetry/api": {
1035 | "optional": true
1036 | },
1037 | "sass": {
1038 | "optional": true
1039 | }
1040 | }
1041 | },
1042 | "node_modules/next/node_modules/postcss": {
1043 | "version": "8.4.31",
1044 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
1045 | "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
1046 | "funding": [
1047 | {
1048 | "type": "opencollective",
1049 | "url": "https://opencollective.com/postcss/"
1050 | },
1051 | {
1052 | "type": "tidelift",
1053 | "url": "https://tidelift.com/funding/github/npm/postcss"
1054 | },
1055 | {
1056 | "type": "github",
1057 | "url": "https://github.com/sponsors/ai"
1058 | }
1059 | ],
1060 | "dependencies": {
1061 | "nanoid": "^3.3.6",
1062 | "picocolors": "^1.0.0",
1063 | "source-map-js": "^1.0.2"
1064 | },
1065 | "engines": {
1066 | "node": "^10 || ^12 || >=14"
1067 | }
1068 | },
1069 | "node_modules/node-releases": {
1070 | "version": "2.0.14",
1071 | "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
1072 | "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==",
1073 | "dev": true
1074 | },
1075 | "node_modules/normalize-path": {
1076 | "version": "3.0.0",
1077 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
1078 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
1079 | "dev": true,
1080 | "engines": {
1081 | "node": ">=0.10.0"
1082 | }
1083 | },
1084 | "node_modules/normalize-range": {
1085 | "version": "0.1.2",
1086 | "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
1087 | "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
1088 | "dev": true,
1089 | "engines": {
1090 | "node": ">=0.10.0"
1091 | }
1092 | },
1093 | "node_modules/object-assign": {
1094 | "version": "4.1.1",
1095 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
1096 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
1097 | "dev": true,
1098 | "engines": {
1099 | "node": ">=0.10.0"
1100 | }
1101 | },
1102 | "node_modules/object-hash": {
1103 | "version": "3.0.0",
1104 | "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
1105 | "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
1106 | "dev": true,
1107 | "engines": {
1108 | "node": ">= 6"
1109 | }
1110 | },
1111 | "node_modules/path-key": {
1112 | "version": "3.1.1",
1113 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
1114 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
1115 | "dev": true,
1116 | "engines": {
1117 | "node": ">=8"
1118 | }
1119 | },
1120 | "node_modules/path-parse": {
1121 | "version": "1.0.7",
1122 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
1123 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
1124 | "dev": true
1125 | },
1126 | "node_modules/path-scurry": {
1127 | "version": "1.10.1",
1128 | "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz",
1129 | "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==",
1130 | "dev": true,
1131 | "dependencies": {
1132 | "lru-cache": "^9.1.1 || ^10.0.0",
1133 | "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
1134 | },
1135 | "engines": {
1136 | "node": ">=16 || 14 >=14.17"
1137 | },
1138 | "funding": {
1139 | "url": "https://github.com/sponsors/isaacs"
1140 | }
1141 | },
1142 | "node_modules/picocolors": {
1143 | "version": "1.0.0",
1144 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
1145 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
1146 | },
1147 | "node_modules/picomatch": {
1148 | "version": "2.3.1",
1149 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
1150 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
1151 | "dev": true,
1152 | "engines": {
1153 | "node": ">=8.6"
1154 | },
1155 | "funding": {
1156 | "url": "https://github.com/sponsors/jonschlinkert"
1157 | }
1158 | },
1159 | "node_modules/pify": {
1160 | "version": "2.3.0",
1161 | "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
1162 | "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
1163 | "dev": true,
1164 | "engines": {
1165 | "node": ">=0.10.0"
1166 | }
1167 | },
1168 | "node_modules/pirates": {
1169 | "version": "4.0.6",
1170 | "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
1171 | "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
1172 | "dev": true,
1173 | "engines": {
1174 | "node": ">= 6"
1175 | }
1176 | },
1177 | "node_modules/postcss": {
1178 | "version": "8.4.35",
1179 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz",
1180 | "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==",
1181 | "dev": true,
1182 | "funding": [
1183 | {
1184 | "type": "opencollective",
1185 | "url": "https://opencollective.com/postcss/"
1186 | },
1187 | {
1188 | "type": "tidelift",
1189 | "url": "https://tidelift.com/funding/github/npm/postcss"
1190 | },
1191 | {
1192 | "type": "github",
1193 | "url": "https://github.com/sponsors/ai"
1194 | }
1195 | ],
1196 | "dependencies": {
1197 | "nanoid": "^3.3.7",
1198 | "picocolors": "^1.0.0",
1199 | "source-map-js": "^1.0.2"
1200 | },
1201 | "engines": {
1202 | "node": "^10 || ^12 || >=14"
1203 | }
1204 | },
1205 | "node_modules/postcss-import": {
1206 | "version": "15.1.0",
1207 | "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
1208 | "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
1209 | "dev": true,
1210 | "dependencies": {
1211 | "postcss-value-parser": "^4.0.0",
1212 | "read-cache": "^1.0.0",
1213 | "resolve": "^1.1.7"
1214 | },
1215 | "engines": {
1216 | "node": ">=14.0.0"
1217 | },
1218 | "peerDependencies": {
1219 | "postcss": "^8.0.0"
1220 | }
1221 | },
1222 | "node_modules/postcss-js": {
1223 | "version": "4.0.1",
1224 | "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
1225 | "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
1226 | "dev": true,
1227 | "dependencies": {
1228 | "camelcase-css": "^2.0.1"
1229 | },
1230 | "engines": {
1231 | "node": "^12 || ^14 || >= 16"
1232 | },
1233 | "funding": {
1234 | "type": "opencollective",
1235 | "url": "https://opencollective.com/postcss/"
1236 | },
1237 | "peerDependencies": {
1238 | "postcss": "^8.4.21"
1239 | }
1240 | },
1241 | "node_modules/postcss-load-config": {
1242 | "version": "4.0.2",
1243 | "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
1244 | "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
1245 | "dev": true,
1246 | "funding": [
1247 | {
1248 | "type": "opencollective",
1249 | "url": "https://opencollective.com/postcss/"
1250 | },
1251 | {
1252 | "type": "github",
1253 | "url": "https://github.com/sponsors/ai"
1254 | }
1255 | ],
1256 | "dependencies": {
1257 | "lilconfig": "^3.0.0",
1258 | "yaml": "^2.3.4"
1259 | },
1260 | "engines": {
1261 | "node": ">= 14"
1262 | },
1263 | "peerDependencies": {
1264 | "postcss": ">=8.0.9",
1265 | "ts-node": ">=9.0.0"
1266 | },
1267 | "peerDependenciesMeta": {
1268 | "postcss": {
1269 | "optional": true
1270 | },
1271 | "ts-node": {
1272 | "optional": true
1273 | }
1274 | }
1275 | },
1276 | "node_modules/postcss-load-config/node_modules/lilconfig": {
1277 | "version": "3.0.0",
1278 | "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz",
1279 | "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==",
1280 | "dev": true,
1281 | "engines": {
1282 | "node": ">=14"
1283 | }
1284 | },
1285 | "node_modules/postcss-nested": {
1286 | "version": "6.0.1",
1287 | "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz",
1288 | "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==",
1289 | "dev": true,
1290 | "dependencies": {
1291 | "postcss-selector-parser": "^6.0.11"
1292 | },
1293 | "engines": {
1294 | "node": ">=12.0"
1295 | },
1296 | "funding": {
1297 | "type": "opencollective",
1298 | "url": "https://opencollective.com/postcss/"
1299 | },
1300 | "peerDependencies": {
1301 | "postcss": "^8.2.14"
1302 | }
1303 | },
1304 | "node_modules/postcss-selector-parser": {
1305 | "version": "6.0.15",
1306 | "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz",
1307 | "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==",
1308 | "dev": true,
1309 | "dependencies": {
1310 | "cssesc": "^3.0.0",
1311 | "util-deprecate": "^1.0.2"
1312 | },
1313 | "engines": {
1314 | "node": ">=4"
1315 | }
1316 | },
1317 | "node_modules/postcss-value-parser": {
1318 | "version": "4.2.0",
1319 | "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
1320 | "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
1321 | "dev": true
1322 | },
1323 | "node_modules/proxy-from-env": {
1324 | "version": "1.1.0",
1325 | "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
1326 | "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
1327 | },
1328 | "node_modules/queue-microtask": {
1329 | "version": "1.2.3",
1330 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
1331 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
1332 | "dev": true,
1333 | "funding": [
1334 | {
1335 | "type": "github",
1336 | "url": "https://github.com/sponsors/feross"
1337 | },
1338 | {
1339 | "type": "patreon",
1340 | "url": "https://www.patreon.com/feross"
1341 | },
1342 | {
1343 | "type": "consulting",
1344 | "url": "https://feross.org/support"
1345 | }
1346 | ]
1347 | },
1348 | "node_modules/react": {
1349 | "version": "18.2.0",
1350 | "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
1351 | "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
1352 | "dependencies": {
1353 | "loose-envify": "^1.1.0"
1354 | },
1355 | "engines": {
1356 | "node": ">=0.10.0"
1357 | }
1358 | },
1359 | "node_modules/react-dom": {
1360 | "version": "18.2.0",
1361 | "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
1362 | "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
1363 | "dependencies": {
1364 | "loose-envify": "^1.1.0",
1365 | "scheduler": "^0.23.0"
1366 | },
1367 | "peerDependencies": {
1368 | "react": "^18.2.0"
1369 | }
1370 | },
1371 | "node_modules/react-icons": {
1372 | "version": "5.0.1",
1373 | "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.0.1.tgz",
1374 | "integrity": "sha512-WqLZJ4bLzlhmsvme6iFdgO8gfZP17rfjYEJ2m9RsZjZ+cc4k1hTzknEz63YS1MeT50kVzoa1Nz36f4BEx+Wigw==",
1375 | "peerDependencies": {
1376 | "react": "*"
1377 | }
1378 | },
1379 | "node_modules/read-cache": {
1380 | "version": "1.0.0",
1381 | "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
1382 | "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
1383 | "dev": true,
1384 | "dependencies": {
1385 | "pify": "^2.3.0"
1386 | }
1387 | },
1388 | "node_modules/readdirp": {
1389 | "version": "3.6.0",
1390 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
1391 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
1392 | "dev": true,
1393 | "dependencies": {
1394 | "picomatch": "^2.2.1"
1395 | },
1396 | "engines": {
1397 | "node": ">=8.10.0"
1398 | }
1399 | },
1400 | "node_modules/resolve": {
1401 | "version": "1.22.8",
1402 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
1403 | "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
1404 | "dev": true,
1405 | "dependencies": {
1406 | "is-core-module": "^2.13.0",
1407 | "path-parse": "^1.0.7",
1408 | "supports-preserve-symlinks-flag": "^1.0.0"
1409 | },
1410 | "bin": {
1411 | "resolve": "bin/resolve"
1412 | },
1413 | "funding": {
1414 | "url": "https://github.com/sponsors/ljharb"
1415 | }
1416 | },
1417 | "node_modules/reusify": {
1418 | "version": "1.0.4",
1419 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
1420 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
1421 | "dev": true,
1422 | "engines": {
1423 | "iojs": ">=1.0.0",
1424 | "node": ">=0.10.0"
1425 | }
1426 | },
1427 | "node_modules/run-parallel": {
1428 | "version": "1.2.0",
1429 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
1430 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
1431 | "dev": true,
1432 | "funding": [
1433 | {
1434 | "type": "github",
1435 | "url": "https://github.com/sponsors/feross"
1436 | },
1437 | {
1438 | "type": "patreon",
1439 | "url": "https://www.patreon.com/feross"
1440 | },
1441 | {
1442 | "type": "consulting",
1443 | "url": "https://feross.org/support"
1444 | }
1445 | ],
1446 | "dependencies": {
1447 | "queue-microtask": "^1.2.2"
1448 | }
1449 | },
1450 | "node_modules/scheduler": {
1451 | "version": "0.23.0",
1452 | "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
1453 | "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
1454 | "dependencies": {
1455 | "loose-envify": "^1.1.0"
1456 | }
1457 | },
1458 | "node_modules/shebang-command": {
1459 | "version": "2.0.0",
1460 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
1461 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
1462 | "dev": true,
1463 | "dependencies": {
1464 | "shebang-regex": "^3.0.0"
1465 | },
1466 | "engines": {
1467 | "node": ">=8"
1468 | }
1469 | },
1470 | "node_modules/shebang-regex": {
1471 | "version": "3.0.0",
1472 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
1473 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
1474 | "dev": true,
1475 | "engines": {
1476 | "node": ">=8"
1477 | }
1478 | },
1479 | "node_modules/signal-exit": {
1480 | "version": "4.1.0",
1481 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
1482 | "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
1483 | "dev": true,
1484 | "engines": {
1485 | "node": ">=14"
1486 | },
1487 | "funding": {
1488 | "url": "https://github.com/sponsors/isaacs"
1489 | }
1490 | },
1491 | "node_modules/source-map-js": {
1492 | "version": "1.0.2",
1493 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
1494 | "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
1495 | "engines": {
1496 | "node": ">=0.10.0"
1497 | }
1498 | },
1499 | "node_modules/streamsearch": {
1500 | "version": "1.1.0",
1501 | "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
1502 | "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
1503 | "engines": {
1504 | "node": ">=10.0.0"
1505 | }
1506 | },
1507 | "node_modules/string-width": {
1508 | "version": "5.1.2",
1509 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
1510 | "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
1511 | "dev": true,
1512 | "dependencies": {
1513 | "eastasianwidth": "^0.2.0",
1514 | "emoji-regex": "^9.2.2",
1515 | "strip-ansi": "^7.0.1"
1516 | },
1517 | "engines": {
1518 | "node": ">=12"
1519 | },
1520 | "funding": {
1521 | "url": "https://github.com/sponsors/sindresorhus"
1522 | }
1523 | },
1524 | "node_modules/string-width-cjs": {
1525 | "name": "string-width",
1526 | "version": "4.2.3",
1527 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
1528 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
1529 | "dev": true,
1530 | "dependencies": {
1531 | "emoji-regex": "^8.0.0",
1532 | "is-fullwidth-code-point": "^3.0.0",
1533 | "strip-ansi": "^6.0.1"
1534 | },
1535 | "engines": {
1536 | "node": ">=8"
1537 | }
1538 | },
1539 | "node_modules/string-width-cjs/node_modules/ansi-regex": {
1540 | "version": "5.0.1",
1541 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
1542 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
1543 | "dev": true,
1544 | "engines": {
1545 | "node": ">=8"
1546 | }
1547 | },
1548 | "node_modules/string-width-cjs/node_modules/emoji-regex": {
1549 | "version": "8.0.0",
1550 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
1551 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
1552 | "dev": true
1553 | },
1554 | "node_modules/string-width-cjs/node_modules/strip-ansi": {
1555 | "version": "6.0.1",
1556 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
1557 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
1558 | "dev": true,
1559 | "dependencies": {
1560 | "ansi-regex": "^5.0.1"
1561 | },
1562 | "engines": {
1563 | "node": ">=8"
1564 | }
1565 | },
1566 | "node_modules/strip-ansi": {
1567 | "version": "7.1.0",
1568 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
1569 | "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
1570 | "dev": true,
1571 | "dependencies": {
1572 | "ansi-regex": "^6.0.1"
1573 | },
1574 | "engines": {
1575 | "node": ">=12"
1576 | },
1577 | "funding": {
1578 | "url": "https://github.com/chalk/strip-ansi?sponsor=1"
1579 | }
1580 | },
1581 | "node_modules/strip-ansi-cjs": {
1582 | "name": "strip-ansi",
1583 | "version": "6.0.1",
1584 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
1585 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
1586 | "dev": true,
1587 | "dependencies": {
1588 | "ansi-regex": "^5.0.1"
1589 | },
1590 | "engines": {
1591 | "node": ">=8"
1592 | }
1593 | },
1594 | "node_modules/strip-ansi-cjs/node_modules/ansi-regex": {
1595 | "version": "5.0.1",
1596 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
1597 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
1598 | "dev": true,
1599 | "engines": {
1600 | "node": ">=8"
1601 | }
1602 | },
1603 | "node_modules/styled-jsx": {
1604 | "version": "5.1.1",
1605 | "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz",
1606 | "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==",
1607 | "dependencies": {
1608 | "client-only": "0.0.1"
1609 | },
1610 | "engines": {
1611 | "node": ">= 12.0.0"
1612 | },
1613 | "peerDependencies": {
1614 | "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0"
1615 | },
1616 | "peerDependenciesMeta": {
1617 | "@babel/core": {
1618 | "optional": true
1619 | },
1620 | "babel-plugin-macros": {
1621 | "optional": true
1622 | }
1623 | }
1624 | },
1625 | "node_modules/sucrase": {
1626 | "version": "3.35.0",
1627 | "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
1628 | "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
1629 | "dev": true,
1630 | "dependencies": {
1631 | "@jridgewell/gen-mapping": "^0.3.2",
1632 | "commander": "^4.0.0",
1633 | "glob": "^10.3.10",
1634 | "lines-and-columns": "^1.1.6",
1635 | "mz": "^2.7.0",
1636 | "pirates": "^4.0.1",
1637 | "ts-interface-checker": "^0.1.9"
1638 | },
1639 | "bin": {
1640 | "sucrase": "bin/sucrase",
1641 | "sucrase-node": "bin/sucrase-node"
1642 | },
1643 | "engines": {
1644 | "node": ">=16 || 14 >=14.17"
1645 | }
1646 | },
1647 | "node_modules/supports-preserve-symlinks-flag": {
1648 | "version": "1.0.0",
1649 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
1650 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
1651 | "dev": true,
1652 | "engines": {
1653 | "node": ">= 0.4"
1654 | },
1655 | "funding": {
1656 | "url": "https://github.com/sponsors/ljharb"
1657 | }
1658 | },
1659 | "node_modules/tailwindcss": {
1660 | "version": "3.4.1",
1661 | "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.1.tgz",
1662 | "integrity": "sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==",
1663 | "dev": true,
1664 | "dependencies": {
1665 | "@alloc/quick-lru": "^5.2.0",
1666 | "arg": "^5.0.2",
1667 | "chokidar": "^3.5.3",
1668 | "didyoumean": "^1.2.2",
1669 | "dlv": "^1.1.3",
1670 | "fast-glob": "^3.3.0",
1671 | "glob-parent": "^6.0.2",
1672 | "is-glob": "^4.0.3",
1673 | "jiti": "^1.19.1",
1674 | "lilconfig": "^2.1.0",
1675 | "micromatch": "^4.0.5",
1676 | "normalize-path": "^3.0.0",
1677 | "object-hash": "^3.0.0",
1678 | "picocolors": "^1.0.0",
1679 | "postcss": "^8.4.23",
1680 | "postcss-import": "^15.1.0",
1681 | "postcss-js": "^4.0.1",
1682 | "postcss-load-config": "^4.0.1",
1683 | "postcss-nested": "^6.0.1",
1684 | "postcss-selector-parser": "^6.0.11",
1685 | "resolve": "^1.22.2",
1686 | "sucrase": "^3.32.0"
1687 | },
1688 | "bin": {
1689 | "tailwind": "lib/cli.js",
1690 | "tailwindcss": "lib/cli.js"
1691 | },
1692 | "engines": {
1693 | "node": ">=14.0.0"
1694 | }
1695 | },
1696 | "node_modules/thenify": {
1697 | "version": "3.3.1",
1698 | "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
1699 | "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
1700 | "dev": true,
1701 | "dependencies": {
1702 | "any-promise": "^1.0.0"
1703 | }
1704 | },
1705 | "node_modules/thenify-all": {
1706 | "version": "1.6.0",
1707 | "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
1708 | "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
1709 | "dev": true,
1710 | "dependencies": {
1711 | "thenify": ">= 3.1.0 < 4"
1712 | },
1713 | "engines": {
1714 | "node": ">=0.8"
1715 | }
1716 | },
1717 | "node_modules/to-regex-range": {
1718 | "version": "5.0.1",
1719 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
1720 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
1721 | "dev": true,
1722 | "dependencies": {
1723 | "is-number": "^7.0.0"
1724 | },
1725 | "engines": {
1726 | "node": ">=8.0"
1727 | }
1728 | },
1729 | "node_modules/ts-interface-checker": {
1730 | "version": "0.1.13",
1731 | "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
1732 | "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
1733 | "dev": true
1734 | },
1735 | "node_modules/tslib": {
1736 | "version": "2.6.2",
1737 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
1738 | "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
1739 | },
1740 | "node_modules/typescript": {
1741 | "version": "5.3.3",
1742 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz",
1743 | "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
1744 | "dev": true,
1745 | "bin": {
1746 | "tsc": "bin/tsc",
1747 | "tsserver": "bin/tsserver"
1748 | },
1749 | "engines": {
1750 | "node": ">=14.17"
1751 | }
1752 | },
1753 | "node_modules/undici-types": {
1754 | "version": "5.26.5",
1755 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
1756 | "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
1757 | "dev": true
1758 | },
1759 | "node_modules/update-browserslist-db": {
1760 | "version": "1.0.13",
1761 | "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz",
1762 | "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==",
1763 | "dev": true,
1764 | "funding": [
1765 | {
1766 | "type": "opencollective",
1767 | "url": "https://opencollective.com/browserslist"
1768 | },
1769 | {
1770 | "type": "tidelift",
1771 | "url": "https://tidelift.com/funding/github/npm/browserslist"
1772 | },
1773 | {
1774 | "type": "github",
1775 | "url": "https://github.com/sponsors/ai"
1776 | }
1777 | ],
1778 | "dependencies": {
1779 | "escalade": "^3.1.1",
1780 | "picocolors": "^1.0.0"
1781 | },
1782 | "bin": {
1783 | "update-browserslist-db": "cli.js"
1784 | },
1785 | "peerDependencies": {
1786 | "browserslist": ">= 4.21.0"
1787 | }
1788 | },
1789 | "node_modules/util-deprecate": {
1790 | "version": "1.0.2",
1791 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
1792 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
1793 | "dev": true
1794 | },
1795 | "node_modules/which": {
1796 | "version": "2.0.2",
1797 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
1798 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
1799 | "dev": true,
1800 | "dependencies": {
1801 | "isexe": "^2.0.0"
1802 | },
1803 | "bin": {
1804 | "node-which": "bin/node-which"
1805 | },
1806 | "engines": {
1807 | "node": ">= 8"
1808 | }
1809 | },
1810 | "node_modules/wrap-ansi": {
1811 | "version": "8.1.0",
1812 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
1813 | "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
1814 | "dev": true,
1815 | "dependencies": {
1816 | "ansi-styles": "^6.1.0",
1817 | "string-width": "^5.0.1",
1818 | "strip-ansi": "^7.0.1"
1819 | },
1820 | "engines": {
1821 | "node": ">=12"
1822 | },
1823 | "funding": {
1824 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
1825 | }
1826 | },
1827 | "node_modules/wrap-ansi-cjs": {
1828 | "name": "wrap-ansi",
1829 | "version": "7.0.0",
1830 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
1831 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
1832 | "dev": true,
1833 | "dependencies": {
1834 | "ansi-styles": "^4.0.0",
1835 | "string-width": "^4.1.0",
1836 | "strip-ansi": "^6.0.0"
1837 | },
1838 | "engines": {
1839 | "node": ">=10"
1840 | },
1841 | "funding": {
1842 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
1843 | }
1844 | },
1845 | "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": {
1846 | "version": "5.0.1",
1847 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
1848 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
1849 | "dev": true,
1850 | "engines": {
1851 | "node": ">=8"
1852 | }
1853 | },
1854 | "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
1855 | "version": "4.3.0",
1856 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
1857 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
1858 | "dev": true,
1859 | "dependencies": {
1860 | "color-convert": "^2.0.1"
1861 | },
1862 | "engines": {
1863 | "node": ">=8"
1864 | },
1865 | "funding": {
1866 | "url": "https://github.com/chalk/ansi-styles?sponsor=1"
1867 | }
1868 | },
1869 | "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
1870 | "version": "8.0.0",
1871 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
1872 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
1873 | "dev": true
1874 | },
1875 | "node_modules/wrap-ansi-cjs/node_modules/string-width": {
1876 | "version": "4.2.3",
1877 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
1878 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
1879 | "dev": true,
1880 | "dependencies": {
1881 | "emoji-regex": "^8.0.0",
1882 | "is-fullwidth-code-point": "^3.0.0",
1883 | "strip-ansi": "^6.0.1"
1884 | },
1885 | "engines": {
1886 | "node": ">=8"
1887 | }
1888 | },
1889 | "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": {
1890 | "version": "6.0.1",
1891 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
1892 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
1893 | "dev": true,
1894 | "dependencies": {
1895 | "ansi-regex": "^5.0.1"
1896 | },
1897 | "engines": {
1898 | "node": ">=8"
1899 | }
1900 | },
1901 | "node_modules/yaml": {
1902 | "version": "2.3.4",
1903 | "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz",
1904 | "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==",
1905 | "dev": true,
1906 | "engines": {
1907 | "node": ">= 14"
1908 | }
1909 | },
1910 | "node_modules/@next/swc-darwin-x64": {
1911 | "version": "14.1.0",
1912 | "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.1.0.tgz",
1913 | "integrity": "sha512-1jgudN5haWxiAl3O1ljUS2GfupPmcftu2RYJqZiMJmmbBT5M1XDffjUtRUzP4W3cBHsrvkfOFdQ71hAreNQP6g==",
1914 | "cpu": [
1915 | "x64"
1916 | ],
1917 | "optional": true,
1918 | "os": [
1919 | "darwin"
1920 | ],
1921 | "engines": {
1922 | "node": ">= 10"
1923 | }
1924 | },
1925 | "node_modules/@next/swc-linux-arm64-gnu": {
1926 | "version": "14.1.0",
1927 | "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.1.0.tgz",
1928 | "integrity": "sha512-RHo7Tcj+jllXUbK7xk2NyIDod3YcCPDZxj1WLIYxd709BQ7WuRYl3OWUNG+WUfqeQBds6kvZYlc42NJJTNi4tQ==",
1929 | "cpu": [
1930 | "arm64"
1931 | ],
1932 | "optional": true,
1933 | "os": [
1934 | "linux"
1935 | ],
1936 | "engines": {
1937 | "node": ">= 10"
1938 | }
1939 | },
1940 | "node_modules/@next/swc-linux-arm64-musl": {
1941 | "version": "14.1.0",
1942 | "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.1.0.tgz",
1943 | "integrity": "sha512-v6kP8sHYxjO8RwHmWMJSq7VZP2nYCkRVQ0qolh2l6xroe9QjbgV8siTbduED4u0hlk0+tjS6/Tuy4n5XCp+l6g==",
1944 | "cpu": [
1945 | "arm64"
1946 | ],
1947 | "optional": true,
1948 | "os": [
1949 | "linux"
1950 | ],
1951 | "engines": {
1952 | "node": ">= 10"
1953 | }
1954 | },
1955 | "node_modules/@next/swc-linux-x64-gnu": {
1956 | "version": "14.1.0",
1957 | "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.1.0.tgz",
1958 | "integrity": "sha512-zJ2pnoFYB1F4vmEVlb/eSe+VH679zT1VdXlZKX+pE66grOgjmKJHKacf82g/sWE4MQ4Rk2FMBCRnX+l6/TVYzQ==",
1959 | "cpu": [
1960 | "x64"
1961 | ],
1962 | "optional": true,
1963 | "os": [
1964 | "linux"
1965 | ],
1966 | "engines": {
1967 | "node": ">= 10"
1968 | }
1969 | },
1970 | "node_modules/@next/swc-linux-x64-musl": {
1971 | "version": "14.1.0",
1972 | "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.1.0.tgz",
1973 | "integrity": "sha512-rbaIYFt2X9YZBSbH/CwGAjbBG2/MrACCVu2X0+kSykHzHnYH5FjHxwXLkcoJ10cX0aWCEynpu+rP76x0914atg==",
1974 | "cpu": [
1975 | "x64"
1976 | ],
1977 | "optional": true,
1978 | "os": [
1979 | "linux"
1980 | ],
1981 | "engines": {
1982 | "node": ">= 10"
1983 | }
1984 | },
1985 | "node_modules/@next/swc-win32-arm64-msvc": {
1986 | "version": "14.1.0",
1987 | "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.1.0.tgz",
1988 | "integrity": "sha512-o1N5TsYc8f/HpGt39OUQpQ9AKIGApd3QLueu7hXk//2xq5Z9OxmV6sQfNp8C7qYmiOlHYODOGqNNa0e9jvchGQ==",
1989 | "cpu": [
1990 | "arm64"
1991 | ],
1992 | "optional": true,
1993 | "os": [
1994 | "win32"
1995 | ],
1996 | "engines": {
1997 | "node": ">= 10"
1998 | }
1999 | },
2000 | "node_modules/@next/swc-win32-ia32-msvc": {
2001 | "version": "14.1.0",
2002 | "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.1.0.tgz",
2003 | "integrity": "sha512-XXIuB1DBRCFwNO6EEzCTMHT5pauwaSj4SWs7CYnME57eaReAKBXCnkUE80p/pAZcewm7hs+vGvNqDPacEXHVkw==",
2004 | "cpu": [
2005 | "ia32"
2006 | ],
2007 | "optional": true,
2008 | "os": [
2009 | "win32"
2010 | ],
2011 | "engines": {
2012 | "node": ">= 10"
2013 | }
2014 | },
2015 | "node_modules/@next/swc-win32-x64-msvc": {
2016 | "version": "14.1.0",
2017 | "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.1.0.tgz",
2018 | "integrity": "sha512-9WEbVRRAqJ3YFVqEZIxUqkiO8l1nool1LmNxygr5HWF8AcSYsEpneUDhmjUVJEzO2A04+oPtZdombzzPPkTtgg==",
2019 | "cpu": [
2020 | "x64"
2021 | ],
2022 | "optional": true,
2023 | "os": [
2024 | "win32"
2025 | ],
2026 | "engines": {
2027 | "node": ">= 10"
2028 | }
2029 | }
2030 | }
2031 | }
2032 |
--------------------------------------------------------------------------------